changeset 0:879c2819a48d

Initial commit.
author Brian Smith <brian@dbsoft.org>
date Fri, 18 Feb 2011 08:45:38 -0600
parents
children 821abb186ec1
files Makefile.in acinclude.m4 aclocal.m4 compat.h config.h.in configure configure.in dw.h extract/extract.c extract/makefile extract/makefile.b32 extract/makefile.g95 extract/makefile.gcc extract/makefile.vac extract/makefile.vc gtk/FILE.xpm gtk/FOLDER.xpm gtk/dw.c gtk/install.xpm gtk/install_banner.xpm gtk/messagebox_error.xpm gtk/messagebox_information.xpm gtk/messagebox_question.xpm gtk/messagebox_warning.xpm gtk/resources.c incace/acestruc.h incace/acestruc.h~ incace/attribs.h incace/declare.h incace/declare.h~ incace/globals.h incace/os.h incace/portable.h incace/uac_comm.h incace/uac_crc.h incace/uac_crt.h incace/uac_dcpr.h incace/uac_sys.h incace/unace.h inczip/consts.h inczip/crypt.h inczip/ebcdic.h inczip/globals.h inczip/inflate.h inczip/nt.h inczip/os2acl.h inczip/os2cfg.h inczip/os2data.h inczip/rsxntwin.h inczip/tables.h inczip/ttyio.h inczip/unzip.h inczip/unzpriv.h inczip/version.h inczip/w32cfg.h inczip/zip.h install.c install.def install.h install.sh instsup.c instsup.h license.txt os2/bitmaps/file.ico os2/bitmaps/folder.ico os2/bitmaps/install.bmp os2/bitmaps/install.ico os2/dirent.c os2/dw.c packace/Makefile.in packace/globals.c packace/makefile.b32 packace/makefile.g95 packace/makefile.gcc packace/makefile.vac packace/makefile.vc packace/uac_comm.c packace/uac_crc.c packace/uac_crt.c packace/uac_dcpr.c packace/uac_sys.c packace/unace.c packinst/packinst.c packzip/Makefile.in packzip/api.c packzip/apihelp.c packzip/crc32.c packzip/crc_i386.S packzip/crc_i386.c packzip/crc_lcc.asm packzip/crctab.c packzip/crypt.c packzip/envargs.c packzip/explode.c packzip/extract.c packzip/fileio.c packzip/funzip.c packzip/globals.c packzip/inflate.c packzip/list.c packzip/makefile.b32 packzip/makefile.g95 packzip/makefile.gcc packzip/makefile.os2 packzip/makefile.vc packzip/match.c packzip/nt.c packzip/os2.c packzip/os2acl.c packzip/process.c packzip/rexxapi.c packzip/rexxapi.def packzip/rexxhelp.c packzip/stub.def packzip/ttyio.c packzip/unix.c packzip/unreduce.c packzip/unshrink.c packzip/unzip.c packzip/unzip.def packzip/unzipstb.c packzip/win32.c packzip/zipinfo.c platform/dirent.h rexx.c scripts/finished.cmd scripts/license.txt scripts/page1.cmd scripts/page2.cmd scripts/page3.cmd scripts/page4.cmd scripts/readme.cmd scripts/readme.txt scripts/reboot.cmd sfxace/Makefile.in sfxace/globals.c sfxace/install.PRJ sfxace/makefile.b32 sfxace/makefile.emx sfxace/makefile.g95 sfxace/makefile.gcc sfxace/makefile.vac sfxace/makefile.vc sfxace/sfx.rc sfxace/uac_comm.c sfxace/uac_crc.c sfxace/uac_crt.c sfxace/uac_dcpr.c sfxace/uac_sys.c sfxace/unace.c sfxos2.rc sfxwin.rc sfxzip/Makefile.in sfxzip/api.c sfxzip/apihelp.c sfxzip/crc32.c sfxzip/crc_i386.S sfxzip/crc_i386.asm sfxzip/crc_i386.c sfxzip/crc_lcc.asm sfxzip/crctab.c sfxzip/crypt.c sfxzip/envargs.c sfxzip/explode.c sfxzip/extract.c sfxzip/fileio.c sfxzip/funzip.c sfxzip/globals.c sfxzip/inflate.c sfxzip/list.c sfxzip/makefile.b32 sfxzip/makefile.g95 sfxzip/makefile.gcc sfxzip/makefile.os2 sfxzip/makefile.vc sfxzip/match.c sfxzip/nt.c sfxzip/os2.c sfxzip/os2acl.c sfxzip/process.c sfxzip/rexxapi.c sfxzip/rexxhelp.c sfxzip/sfx.def sfxzip/sfx.rc sfxzip/ttyio.c sfxzip/unix.c sfxzip/unreduce.c sfxzip/unshrink.c sfxzip/unzip.c sfxzip/unzipstb.c sfxzip/win32.c sfxzip/zipinfo.c uninst/Makefile.in uninst/dbuninst.def uninst/makefile.vac uninst/makefile.vc uninst/uninst.c win/bitmaps/file.ico win/bitmaps/folder.ico win/bitmaps/install.bmp win/bitmaps/install.ico win/dirent.c win/dw.c win32sup.cpp
diffstat 204 files changed, 106851 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile.in	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,32 @@
+# Installer Makefile
+
+all: sfxace packace uninst
+
+$(OBJECTS):
+	$(CC) $(CFLAGS) -c $<	
+
+packace: packace/Makefile Makefile
+	@cd packace
+	$(MAKE) -f Makefile all
+	@cd ..
+
+packzip: packzip/Makefile Makefile
+	@cd packzip
+	$(MAKE) -f Makefile all
+	@cd ..
+
+sfxace: sfxace/Makefile Makefile
+	@cd sfxace
+	$(MAKE) -f Makefile all
+	@cd ..
+
+sfxzip: sfxzip/Makefile Makefile
+	@cd sfxzip
+	$(MAKE) -f Makefile all
+	@cd ..
+
+uninst: uninst/Makefile Makefile
+	@cd uninst
+	$(MAKE) -f Makefile all
+	@cd ..
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/acinclude.m4	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,1127 @@
+dnl aclocal.m4 generated automatically by aclocal 1.4a
+
+dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+dnl PARTICULAR PURPOSE.
+
+# Configure paths for GLIB
+# Owen Taylor     97-11-3
+
+dnl AM_PATH_GLIB([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]])
+dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if "gmodule" or 
+dnl gthread is specified in MODULES, pass to glib-config
+dnl
+AC_DEFUN(AM_PATH_GLIB,
+[dnl 
+dnl Get the cflags and libraries from the glib-config script
+dnl
+AC_ARG_WITH(glib-prefix,[  --with-glib-prefix=PFX  Prefix where GLIB is installed (optional)],
+            glib_config_prefix="$withval", glib_config_prefix="")
+AC_ARG_WITH(glib-exec-prefix,[  --with-glib-exec-prefix=PFX Exec prefix where GLIB is installed (optional)],
+            glib_config_exec_prefix="$withval", glib_config_exec_prefix="")
+AC_ARG_ENABLE(glibtest, [  --disable-glibtest      Do not try to compile and run a test GLIB program],
+		    , enable_glibtest=yes)
+
+  if test x$glib_config_exec_prefix != x ; then
+     glib_config_args="$glib_config_args --exec-prefix=$glib_config_exec_prefix"
+     if test x${GLIB_CONFIG+set} != xset ; then
+        GLIB_CONFIG=$glib_config_exec_prefix/bin/glib-config
+     fi
+  fi
+  if test x$glib_config_prefix != x ; then
+     glib_config_args="$glib_config_args --prefix=$glib_config_prefix"
+     if test x${GLIB_CONFIG+set} != xset ; then
+        GLIB_CONFIG=$glib_config_prefix/bin/glib-config
+     fi
+  fi
+
+  for module in . $4
+  do
+      case "$module" in
+         gmodule) 
+             glib_config_args="$glib_config_args gmodule"
+         ;;
+         gthread) 
+             glib_config_args="$glib_config_args gthread"
+         ;;
+      esac
+  done
+
+  AC_PATH_PROG(GLIB_CONFIG, glib-config, no)
+  min_glib_version=ifelse([$1], ,1.2.0,$1)
+  AC_MSG_CHECKING(for GLIB - version >= $min_glib_version)
+  no_glib=""
+  if test "$GLIB_CONFIG" = "no" ; then
+    no_glib=yes
+  else
+    GLIB_CFLAGS=`$GLIB_CONFIG $glib_config_args --cflags`
+    GLIB_LIBS=`$GLIB_CONFIG $glib_config_args --libs`
+    glib_config_major_version=`$GLIB_CONFIG $glib_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    glib_config_minor_version=`$GLIB_CONFIG $glib_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    glib_config_micro_version=`$GLIB_CONFIG $glib_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+    if test "x$enable_glibtest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $GLIB_CFLAGS"
+      LIBS="$GLIB_LIBS $LIBS"
+dnl
+dnl Now check if the installed GLIB is sufficiently new. (Also sanity
+dnl checks the results of glib-config to some extent
+dnl
+      rm -f conf.glibtest
+      AC_TRY_RUN([
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int 
+main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.glibtest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_glib_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_glib_version");
+     exit(1);
+   }
+
+  if ((glib_major_version != $glib_config_major_version) ||
+      (glib_minor_version != $glib_config_minor_version) ||
+      (glib_micro_version != $glib_config_micro_version))
+    {
+      printf("\n*** 'glib-config --version' returned %d.%d.%d, but GLIB (%d.%d.%d)\n", 
+             $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version,
+             glib_major_version, glib_minor_version, glib_micro_version);
+      printf ("*** was found! If glib-config was correct, then it is best\n");
+      printf ("*** to remove the old version of GLIB. You may also be able to fix the error\n");
+      printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+      printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+      printf("*** required on your system.\n");
+      printf("*** If glib-config was wrong, set the environment variable GLIB_CONFIG\n");
+      printf("*** to point to the correct copy of glib-config, and remove the file config.cache\n");
+      printf("*** before re-running configure\n");
+    } 
+  else if ((glib_major_version != GLIB_MAJOR_VERSION) ||
+	   (glib_minor_version != GLIB_MINOR_VERSION) ||
+           (glib_micro_version != GLIB_MICRO_VERSION))
+    {
+      printf("*** GLIB header files (version %d.%d.%d) do not match\n",
+	     GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
+      printf("*** library (version %d.%d.%d)\n",
+	     glib_major_version, glib_minor_version, glib_micro_version);
+    }
+  else
+    {
+      if ((glib_major_version > major) ||
+        ((glib_major_version == major) && (glib_minor_version > minor)) ||
+        ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro)))
+      {
+        return 0;
+       }
+     else
+      {
+        printf("\n*** An old version of GLIB (%d.%d.%d) was found.\n",
+               glib_major_version, glib_minor_version, glib_micro_version);
+        printf("*** You need a version of GLIB newer than %d.%d.%d. The latest version of\n",
+	       major, minor, micro);
+        printf("*** GLIB is always available from ftp://ftp.gtk.org.\n");
+        printf("***\n");
+        printf("*** If you have already installed a sufficiently new version, this error\n");
+        printf("*** probably means that the wrong copy of the glib-config shell script is\n");
+        printf("*** being found. The easiest way to fix this is to remove the old version\n");
+        printf("*** of GLIB, but you can also set the GLIB_CONFIG environment to point to the\n");
+        printf("*** correct copy of glib-config. (In this case, you will have to\n");
+        printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+        printf("*** so that the correct libraries are found at run-time))\n");
+      }
+    }
+  return 1;
+}
+],, no_glib=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_glib" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$GLIB_CONFIG" = "no" ; then
+       echo "*** The glib-config script installed by GLIB could not be found"
+       echo "*** If GLIB was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the GLIB_CONFIG environment variable to the"
+       echo "*** full path to glib-config."
+     else
+       if test -f conf.glibtest ; then
+        :
+       else
+          echo "*** Could not run GLIB test program, checking why..."
+          CFLAGS="$CFLAGS $GLIB_CFLAGS"
+          LIBS="$LIBS $GLIB_LIBS"
+          AC_TRY_LINK([
+#include <glib.h>
+#include <stdio.h>
+],      [ return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding GLIB or finding the wrong"
+          echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means GLIB was incorrectly installed"
+          echo "*** or that you have moved GLIB since it was installed. In the latter case, you"
+          echo "*** may want to edit the glib-config script: $GLIB_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     GLIB_CFLAGS=""
+     GLIB_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(GLIB_CFLAGS)
+  AC_SUBST(GLIB_LIBS)
+  rm -f conf.glibtest
+])
+
+# Configure paths for GTK+
+# Owen Taylor     97-11-3
+
+dnl AM_PATH_GTK([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]])
+dnl Test for GTK, and define GTK_CFLAGS and GTK_LIBS
+dnl
+AC_DEFUN(AM_PATH_GTK,
+[dnl 
+dnl Get the cflags and libraries from the gtk-config script
+dnl
+AC_ARG_WITH(gtk-prefix,[  --with-gtk-prefix=PFX   Prefix where GTK is installed (optional)],
+            gtk_config_prefix="$withval", gtk_config_prefix="")
+AC_ARG_WITH(gtk-exec-prefix,[  --with-gtk-exec-prefix=PFX Exec prefix where GTK is installed (optional)],
+            gtk_config_exec_prefix="$withval", gtk_config_exec_prefix="")
+AC_ARG_ENABLE(gtktest, [  --disable-gtktest       Do not try to compile and run a test GTK program],
+		    , enable_gtktest=yes)
+
+  for module in . $4
+  do
+      case "$module" in
+         gthread) 
+             gtk_config_args="$gtk_config_args gthread"
+         ;;
+      esac
+  done
+
+  if test x$gtk_config_exec_prefix != x ; then
+     gtk_config_args="$gtk_config_args --exec-prefix=$gtk_config_exec_prefix"
+     if test x${GTK_CONFIG+set} != xset ; then
+        GTK_CONFIG=$gtk_config_exec_prefix/bin/gtk-config
+     fi
+  fi
+  if test x$gtk_config_prefix != x ; then
+     gtk_config_args="$gtk_config_args --prefix=$gtk_config_prefix"
+     if test x${GTK_CONFIG+set} != xset ; then
+        GTK_CONFIG=$gtk_config_prefix/bin/gtk-config
+     fi
+  fi
+
+  AC_PATH_PROG(GTK_CONFIG, gtk-config, no)
+  min_gtk_version=ifelse([$1], ,1.2.0,$1)
+  AC_MSG_CHECKING(for GTK - version >= $min_gtk_version)
+  no_gtk=""
+  if test "$GTK_CONFIG" = "no" ; then
+    no_gtk=yes
+  else
+    GTK_CFLAGS=`$GTK_CONFIG $gtk_config_args --cflags`
+    GTK_LIBS=`$GTK_CONFIG $gtk_config_args --libs`
+    gtk_config_major_version=`$GTK_CONFIG $gtk_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    gtk_config_minor_version=`$GTK_CONFIG $gtk_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    gtk_config_micro_version=`$GTK_CONFIG $gtk_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+    if test "x$enable_gtktest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $GTK_CFLAGS"
+      LIBS="$GTK_LIBS $LIBS"
+dnl
+dnl Now check if the installed GTK is sufficiently new. (Also sanity
+dnl checks the results of gtk-config to some extent
+dnl
+      rm -f conf.gtktest
+      AC_TRY_RUN([
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int 
+main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.gtktest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_gtk_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_gtk_version");
+     exit(1);
+   }
+
+  if ((gtk_major_version != $gtk_config_major_version) ||
+      (gtk_minor_version != $gtk_config_minor_version) ||
+      (gtk_micro_version != $gtk_config_micro_version))
+    {
+      printf("\n*** 'gtk-config --version' returned %d.%d.%d, but GTK+ (%d.%d.%d)\n", 
+             $gtk_config_major_version, $gtk_config_minor_version, $gtk_config_micro_version,
+             gtk_major_version, gtk_minor_version, gtk_micro_version);
+      printf ("*** was found! If gtk-config was correct, then it is best\n");
+      printf ("*** to remove the old version of GTK+. You may also be able to fix the error\n");
+      printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+      printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+      printf("*** required on your system.\n");
+      printf("*** If gtk-config was wrong, set the environment variable GTK_CONFIG\n");
+      printf("*** to point to the correct copy of gtk-config, and remove the file config.cache\n");
+      printf("*** before re-running configure\n");
+    } 
+#if defined (GTK_MAJOR_VERSION) && defined (GTK_MINOR_VERSION) && defined (GTK_MICRO_VERSION)
+  else if ((gtk_major_version != GTK_MAJOR_VERSION) ||
+	   (gtk_minor_version != GTK_MINOR_VERSION) ||
+           (gtk_micro_version != GTK_MICRO_VERSION))
+    {
+      printf("*** GTK+ header files (version %d.%d.%d) do not match\n",
+	     GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
+      printf("*** library (version %d.%d.%d)\n",
+	     gtk_major_version, gtk_minor_version, gtk_micro_version);
+    }
+#endif /* defined (GTK_MAJOR_VERSION) ... */
+  else
+    {
+      if ((gtk_major_version > major) ||
+        ((gtk_major_version == major) && (gtk_minor_version > minor)) ||
+        ((gtk_major_version == major) && (gtk_minor_version == minor) && (gtk_micro_version >= micro)))
+      {
+        return 0;
+       }
+     else
+      {
+        printf("\n*** An old version of GTK+ (%d.%d.%d) was found.\n",
+               gtk_major_version, gtk_minor_version, gtk_micro_version);
+        printf("*** You need a version of GTK+ newer than %d.%d.%d. The latest version of\n",
+	       major, minor, micro);
+        printf("*** GTK+ is always available from ftp://ftp.gtk.org.\n");
+        printf("***\n");
+        printf("*** If you have already installed a sufficiently new version, this error\n");
+        printf("*** probably means that the wrong copy of the gtk-config shell script is\n");
+        printf("*** being found. The easiest way to fix this is to remove the old version\n");
+        printf("*** of GTK+, but you can also set the GTK_CONFIG environment to point to the\n");
+        printf("*** correct copy of gtk-config. (In this case, you will have to\n");
+        printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+        printf("*** so that the correct libraries are found at run-time))\n");
+      }
+    }
+  return 1;
+}
+],, no_gtk=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_gtk" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$GTK_CONFIG" = "no" ; then
+       echo "*** The gtk-config script installed by GTK could not be found"
+       echo "*** If GTK was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the GTK_CONFIG environment variable to the"
+       echo "*** full path to gtk-config."
+     else
+       if test -f conf.gtktest ; then
+        :
+       else
+          echo "*** Could not run GTK test program, checking why..."
+          CFLAGS="$CFLAGS $GTK_CFLAGS"
+          LIBS="$LIBS $GTK_LIBS"
+          AC_TRY_LINK([
+#include <gtk/gtk.h>
+#include <stdio.h>
+],      [ return ((gtk_major_version) || (gtk_minor_version) || (gtk_micro_version)); ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding GTK or finding the wrong"
+          echo "*** version of GTK. If it is not finding GTK, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means GTK was incorrectly installed"
+          echo "*** or that you have moved GTK since it was installed. In the latter case, you"
+          echo "*** may want to edit the gtk-config script: $GTK_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     GTK_CFLAGS=""
+     GTK_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(GTK_CFLAGS)
+  AC_SUBST(GTK_LIBS)
+  rm -f conf.gtktest
+])
+
+# Configure paths for IMLIB
+# David Walluck   99-9-18   
+# Frank Belew     98-8-31
+# stolen from Manish Singh
+# Shamelessly stolen from Owen Taylor
+
+dnl AM_PATH_IMLIB([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for IMLIB, and define IMLIB_CFLAGS and IMLIB_LIBS
+dnl
+AC_DEFUN(AM_PATH_IMLIB,
+[dnl 
+dnl Get the cflags and libraries from the imlib-config script
+dnl
+AC_ARG_WITH(imlib-prefix,[  --with-imlib-prefix=PFX Prefix where IMLIB is installed (optional)],
+            imlib_prefix="$withval", imlib_prefix="")
+AC_ARG_WITH(imlib-exec-prefix,[  --with-imlib-exec-prefix=PFX Exec prefix where IMLIB is installed (optional)],
+            imlib_exec_prefix="$withval", imlib_exec_prefix="")
+AC_ARG_ENABLE(imlibtest, [  --disable-imlibtest Do not try to compile and run a test IMLIB program],
+		    , enable_imlibtest=yes)
+
+  if test x$imlib_exec_prefix != x ; then
+     imlib_args="$imlib_args --exec-prefix=$imlib_exec_prefix"
+     if test x${IMLIB_CONFIG+set} != xset ; then
+        IMLIB_CONFIG=$imlib_exec_prefix/bin/imlib-config
+     fi
+  fi
+  if test x$imlib_prefix != x ; then
+     imlib_args="$imlib_args --prefix=$imlib_prefix"
+     if test x${IMLIB_CONFIG+set} != xset ; then
+        IMLIB_CONFIG=$imlib_prefix/bin/imlib-config
+     fi
+  fi
+
+  AC_PATH_PROG(IMLIB_CONFIG, imlib-config, no)
+  min_imlib_version=ifelse([$1], ,1.9.4,$1)
+  AC_MSG_CHECKING(for IMLIB - version >= $min_imlib_version)
+  no_imlib=""
+  if test "$IMLIB_CONFIG" = "no" ; then
+    no_imlib=yes
+  else
+    IMLIB_CFLAGS=`$IMLIB_CONFIG $imlibconf_args --cflags`
+    IMLIB_LIBS=`$IMLIB_CONFIG $imlibconf_args --libs`
+
+    imlib_major_version=`$IMLIB_CONFIG $imlib_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    imlib_minor_version=`$IMLIB_CONFIG $imlib_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    imlib_micro_version=`$IMLIB_CONFIG $imlib_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+    if test "x$enable_imlibtest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $IMLIB_CFLAGS"
+      LIBS="$LIBS $IMLIB_LIBS"
+dnl
+dnl Now check if the installed IMLIB is sufficiently new. (Also sanity
+dnl checks the results of imlib-config to some extent
+dnl
+      rm -f conf.imlibtest
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+#include <Imlib.h>
+
+int main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.imlibtest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_imlib_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_imlib_version");
+     exit(1);
+   }
+
+    if (($imlib_major_version > major) ||
+        (($imlib_major_version == major) && ($imlib_minor_version > minor)) ||
+	(($imlib_major_version == major) && ($imlib_minor_version == minor) &&
+	($imlib_micro_version >= micro)))
+    {
+      return 0;
+    }
+  else
+    {
+      printf("\n*** 'imlib-config --version' returned %d.%d.%d, but the minimum version\n", $imlib_major_version, $imlib_minor_version, $imlib_micro_version);
+      printf("*** of IMLIB required is %d.%d.%d. If imlib-config is correct, then it is\n", major, minor, micro);
+      printf("*** best to upgrade to the required version.\n");
+      printf("*** If imlib-config was wrong, set the environment variable IMLIB_CONFIG\n");
+      printf("*** to point to the correct copy of imlib-config, and remove the file\n");
+      printf("*** config.cache before re-running configure\n");
+      return 1;
+    }
+}
+
+],, no_imlib=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_imlib" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$IMLIB_CONFIG" = "no" ; then
+       echo "*** The imlib-config script installed by IMLIB could not be found"
+       echo "*** If IMLIB was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the IMLIB_CONFIG environment variable to the"
+       echo "*** full path to imlib-config."
+     else
+       if test -f conf.imlibtest ; then
+        :
+       else
+          echo "*** Could not run IMLIB test program, checking why..."
+          CFLAGS="$CFLAGS $IMLIB_CFLAGS"
+          LIBS="$LIBS $IMLIB_LIBS"
+          AC_TRY_LINK([
+#include <stdio.h>
+#include <Imlib.h>
+],      [ return 0; ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding IMLIB or finding the wrong"
+          echo "*** version of IMLIB. If it is not finding IMLIB, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means IMLIB was incorrectly installed"
+          echo "*** or that you have moved IMLIB since it was installed. In the latter case, you"
+          echo "*** may want to edit the imlib-config script: $IMLIB_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     IMLIB_CFLAGS=""
+     IMLIB_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(IMLIB_CFLAGS)
+  AC_SUBST(IMLIB_LIBS)
+  rm -f conf.imlibtest
+])
+
+# Check for gdk-imlib
+AC_DEFUN(AM_PATH_GDK_IMLIB,
+[dnl 
+dnl Get the cflags and libraries from the imlib-config script
+dnl
+AC_ARG_WITH(imlib-prefix,[  --with-imlib-prefix=PFX Prefix where IMLIB is installed (optional)],
+            imlib_prefix="$withval", imlib_prefix="")
+AC_ARG_WITH(imlib-exec-prefix,[  --with-imlib-exec-prefix=PFX Exec prefix where IMLIB is installed (optional)],
+            imlib_exec_prefix="$withval", imlib_exec_prefix="")
+AC_ARG_ENABLE(imlibtest, [  --disable-imlibtest     Do not try to compile and run a test IMLIB program],
+		    , enable_imlibtest=yes)
+
+  if test x$imlib_exec_prefix != x ; then
+     imlib_args="$imlib_args --exec-prefix=$imlib_exec_prefix"
+     if test x${IMLIB_CONFIG+set} != xset ; then
+        IMLIB_CONFIG=$imlib_exec_prefix/bin/imlib-config
+     fi
+  fi
+  if test x$imlib_prefix != x ; then
+     imlib_args="$imlib_args --prefix=$imlib_prefix"
+     if test x${IMLIB_CONFIG+set} != xset ; then
+        IMLIB_CONFIG=$imlib_prefix/bin/imlib-config
+     fi
+  fi
+
+  AC_PATH_PROG(IMLIB_CONFIG, imlib-config, no)
+  min_imlib_version=ifelse([$1], ,1.9.4,$1)
+  AC_MSG_CHECKING(for IMLIB - version >= $min_imlib_version)
+  no_imlib=""
+  if test "$IMLIB_CONFIG" = "no" ; then
+    no_imlib=yes
+  else
+    GDK_IMLIB_CFLAGS=`$IMLIB_CONFIG $imlibconf_args --cflags-gdk`
+    GDK_IMLIB_LIBS=`$IMLIB_CONFIG $imlibconf_args --libs-gdk`
+
+    imlib_major_version=`$IMLIB_CONFIG $imlib_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    imlib_minor_version=`$IMLIB_CONFIG $imlib_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    imlib_micro_version=`$IMLIB_CONFIG $imlib_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`                  
+    if test "x$enable_imlibtest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $GDK_IMLIB_CFLAGS"
+      LIBS="$LIBS $GDK_IMLIB_LIBS"
+dnl
+dnl Now check if the installed IMLIB is sufficiently new. (Also sanity
+dnl checks the results of imlib-config to some extent
+dnl
+      rm -f conf.imlibtest
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+#include <gdk_imlib.h>
+
+int main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.gdkimlibtest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_imlib_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_imlib_version");
+     exit(1);
+   }
+
+    if (($imlib_major_version > major) ||
+        (($imlib_major_version == major) && ($imlib_minor_version > minor)) ||
+	(($imlib_major_version == major) && ($imlib_minor_version == minor) &&
+	($imlib_micro_version >= micro)))
+    {
+      return 0;
+    }
+  else
+    {
+      printf("\n*** 'imlib-config --version' returned %d.%d.%d, but the minimum version\n", $imlib_major_version, $imlib_minor_version, $imlib_micro_version);
+      printf("*** of IMLIB required is %d.%d.%d. If imlib-config is correct, then it is\n", major, minor, micro);
+      printf("*** best to upgrade to the required version.\n");
+      printf("*** If imlib-config was wrong, set the environment variable IMLIB_CONFIG\n");
+      printf("*** to point to the correct copy of imlib-config, and remove the file\n");
+      printf("*** config.cache before re-running configure\n");
+      return 1;
+    }
+}
+
+],, no_imlib=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_imlib" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$IMLIB_CONFIG" = "no" ; then
+       echo "*** The imlib-config script installed by IMLIB could not be found"
+       echo "*** If IMLIB was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the IMLIB_CONFIG environment variable to the"
+       echo "*** full path to imlib-config."
+     else
+       if test -f conf.gdkimlibtest ; then
+        :
+       else
+          echo "*** Could not run IMLIB test program, checking why..."
+          CFLAGS="$CFLAGS $GDK_IMLIB_CFLAGS"
+          LIBS="$LIBS $GDK_IMLIB_LIBS"
+          AC_TRY_LINK([
+#include <stdio.h>
+#include <gdk_imlib.h>
+],      [ return 0; ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding IMLIB or finding the wrong"
+          echo "*** version of IMLIB. If it is not finding IMLIB, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means IMLIB was incorrectly installed"
+          echo "*** or that you have moved IMLIB since it was installed. In the latter case, you"
+          echo "*** may want to edit the imlib-config script: $IMLIB_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     GDK_IMLIB_CFLAGS=""
+     GDK_IMLIB_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(GDK_IMLIB_CFLAGS)
+  AC_SUBST(GDK_IMLIB_LIBS)
+  rm -f conf.gdkimlibtest
+])
+
+# Configure paths for ESD
+# David Walluck   99-9-20
+# Manish Singh    98-9-30
+# stolen back from Frank Belew
+# stolen from Manish Singh
+# Shamelessly stolen from Owen Taylor
+
+dnl AM_PATH_ESD([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for ESD, and define ESD_CFLAGS and ESD_LIBS
+dnl
+AC_DEFUN(AM_PATH_ESD,
+[dnl 
+dnl Get the cflags and libraries from the esd-config script
+dnl
+AC_ARG_WITH(esd-prefix,[  --with-esd-prefix=PFX   Prefix where ESD is installed (optional)],
+            esd_prefix="$withval", esd_prefix="")
+AC_ARG_WITH(esd-exec-prefix,[  --with-esd-exec-prefix=PFX Exec prefix where ESD is installed (optional)],
+            esd_exec_prefix="$withval", esd_exec_prefix="")
+AC_ARG_ENABLE(esdtest, [  --disable-esdtest       Do not try to compile and run a test ESD program],
+		    , enable_esdtest=yes)
+
+  if test x$esd_exec_prefix != x ; then
+     esd_args="$esd_args --exec-prefix=$esd_exec_prefix"
+     if test x${ESD_CONFIG+set} != xset ; then
+        ESD_CONFIG=$esd_exec_prefix/bin/esd-config
+     fi
+  fi
+  if test x$esd_prefix != x ; then
+     esd_args="$esd_args --prefix=$esd_prefix"
+     if test x${ESD_CONFIG+set} != xset ; then
+        ESD_CONFIG=$esd_prefix/bin/esd-config
+     fi
+  fi
+
+  AC_PATH_PROG(ESD_CONFIG, esd-config, no)
+  min_esd_version=ifelse([$1], ,0.2.5,$1)
+  AC_MSG_CHECKING(for ESD - version >= $min_esd_version)
+  no_esd=""
+  if test "$ESD_CONFIG" = "no" ; then
+    no_esd=yes
+  else
+    ESD_CFLAGS=`$ESD_CONFIG $esdconf_args --cflags`
+    ESD_LIBS=`$ESD_CONFIG $esdconf_args --libs`
+
+    esd_major_version=`$ESD_CONFIG $esd_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    esd_minor_version=`$ESD_CONFIG $esd_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    esd_micro_version=`$ESD_CONFIG $esd_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+    if test "x$enable_esdtest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $ESD_CFLAGS"
+      LIBS="$LIBS $ESD_LIBS"
+dnl
+dnl Now check if the installed ESD is sufficiently new. (Also sanity
+dnl checks the results of esd-config to some extent
+dnl
+      rm -f conf.esdtest
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+#include <esd.h>
+
+int main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.esdtest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_esd_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_esd_version");
+     exit(1);
+   }
+
+   if (($esd_major_version > major) ||
+      (($esd_major_version == major) && ($esd_minor_version > minor)) ||
+      (($esd_major_version == major) && ($esd_minor_version == minor) && ($esd_micro_version >= micro)))
+    {
+      return 0;
+    }
+  else
+    {
+      printf("\n*** 'esd-config --version' returned %d.%d.%d, but the minimum version\n", $esd_major_version, $esd_minor_version, $esd_micro_version);
+      printf("*** of ESD required is %d.%d.%d. If esd-config is correct, then it is\n", major, minor, micro);
+      printf("*** best to upgrade to the required version.\n");
+      printf("*** If esd-config was wrong, set the environment variable ESD_CONFIG\n");
+      printf("*** to point to the correct copy of esd-config, and remove the file\n");
+      printf("*** config.cache before re-running configure\n");
+      return 1;
+    }
+}
+
+],, no_esd=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_esd" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$ESD_CONFIG" = "no" ; then
+       echo "*** The esd-config script installed by ESD could not be found"
+       echo "*** If ESD was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the ESD_CONFIG environment variable to the"
+       echo "*** full path to esd-config."
+     else
+       if test -f conf.esdtest ; then
+        :
+       else
+          echo "*** Could not run ESD test program, checking why..."
+          CFLAGS="$CFLAGS $ESD_CFLAGS"
+          LIBS="$LIBS $ESD_LIBS"
+          AC_TRY_LINK([
+#include <stdio.h>
+#include <esd.h>
+],      [ return 0; ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding ESD or finding the wrong"
+          echo "*** version of ESD. If it is not finding ESD, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means ESD was incorrectly installed"
+          echo "*** or that you have moved ESD since it was installed. In the latter case, you"
+          echo "*** may want to edit the esd-config script: $ESD_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     ESD_CFLAGS=""
+     ESD_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(ESD_CFLAGS)
+  AC_SUBST(ESD_LIBS)
+  rm -f conf.esdtest
+])
+
+# Configure paths for AUDIOFILE
+# Bertrand Guiheneuf 98-10-21
+# stolen from esd.m4 in esound :
+# Manish Singh    98-9-30
+# stolen back from Frank Belew
+# stolen from Manish Singh
+# Shamelessly stolen from Owen Taylor
+
+dnl AM_PATH_AUDIOFILE([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for AUDIOFILE, and define AUDIOFILE_CFLAGS and AUDIOFILE_LIBS
+dnl
+AC_DEFUN(AM_PATH_AUDIOFILE,
+[dnl 
+dnl Get the cflags and libraries from the audiofile-config script
+dnl
+AC_ARG_WITH(audiofile-prefix,[  --with-audiofile-prefix=PFX Prefix where AUDIOFILE is installed (optional)],
+            audiofile_prefix="$withval", audiofile_prefix="")
+AC_ARG_WITH(audiofile-exec-prefix,[  --with-audiofile-exec-prefix=PFX Exec prefix where AUDIOFILE is installed
+                          (optional)],
+            audiofile_exec_prefix="$withval", audiofile_exec_prefix="")
+AC_ARG_ENABLE(audiofiletest, [  --disable-audiofiletest Do not try to compile and run a test AUDIOFILE program],
+		    , enable_audiofiletest=yes)
+
+  if test x$audiofile_exec_prefix != x ; then
+     audiofile_args="$audiofile_args --exec-prefix=$audiofile_exec_prefix"
+     if test x${AUDIOFILE_CONFIG+set} != xset ; then
+        AUDIOFILE_CONFIG=$audiofile_exec_prefix/bin/audiofile-config
+     fi
+  fi
+  if test x$audiofile_prefix != x ; then
+     audiofile_args="$audiofile_args --prefix=$audiofile_prefix"
+     if test x${AUDIOFILE_CONFIG+set} != xset ; then
+        AUDIOFILE_CONFIG=$audiofile_prefix/bin/audiofile-config
+     fi
+  fi
+
+  AC_PATH_PROG(AUDIOFILE_CONFIG, audiofile-config, no)
+  min_audiofile_version=ifelse([$1], ,0.1.5,$1)
+  AC_MSG_CHECKING(for AUDIOFILE - version >= $min_audiofile_version)
+  no_audiofile=""
+  if test "$AUDIOFILE_CONFIG" = "no" ; then
+    no_audiofile=yes
+  else
+    AUDIOFILE_LIBS=`$AUDIOFILE_CONFIG $audiofileconf_args --libs`
+    AUDIOFILE_CFLAGS=`$AUDIOFILE_CONFIG $audiofileconf_args --cflags`
+    audiofile_major_version=`$AUDIOFILE_CONFIG $audiofile_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    audiofile_minor_version=`$AUDIOFILE_CONFIG $audiofile_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    audiofile_micro_version=`$AUDIOFILE_CONFIG $audiofile_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+    if test "x$enable_audiofiletest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $AUDIOFILE_CFLAGS"
+      LIBS="$LIBS $AUDIOFILE_LIBS"
+dnl
+dnl Now check if the installed AUDIOFILE is sufficiently new. (Also sanity
+dnl checks the results of audiofile-config to some extent
+dnl
+      rm -f conf.audiofiletest
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+#include <audiofile.h>
+
+int main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.audiofiletest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_audiofile_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_audiofile_version");
+     exit(1);
+   }
+
+   if (($audiofile_major_version > major) ||
+      (($audiofile_major_version == major) && ($audiofile_minor_version > minor)) ||
+      (($audiofile_major_version == major) && ($audiofile_minor_version == minor) && ($audiofile_micro_version >= micro)))
+    {
+      return 0;
+    }
+  else
+    {
+      printf("\n*** 'audiofile-config --version' returned %d.%d.%d, but the minimum version\n", $audiofile_major_version, $audiofile_minor_version, $audiofile_micro_version);
+      printf("*** of AUDIOFILE required is %d.%d.%d. If audiofile-config is correct, then it is\n", major, minor, micro);
+      printf("*** best to upgrade to the required version.\n");
+      printf("*** If audiofile-config was wrong, set the environment variable AUDIOFILE_CONFIG\n");
+      printf("*** to point to the correct copy of audiofile-config, and remove the file\n");
+      printf("*** config.cache before re-running configure\n");
+      return 1;
+    }
+}
+
+],, no_audiofile=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_audiofile" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$AUDIOFILE_CONFIG" = "no" ; then
+       echo "*** The audiofile-config script installed by AUDIOFILE could not be found"
+       echo "*** If AUDIOFILE was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the AUDIOFILE_CONFIG environment variable to the"
+       echo "*** full path to audiofile-config."
+     else
+       if test -f conf.audiofiletest ; then
+        :
+       else
+          echo "*** Could not run AUDIOFILE test program, checking why..."
+          CFLAGS="$CFLAGS $AUDIOFILE_CFLAGS"
+          LIBS="$LIBS $AUDIOFILE_LIBS"
+          AC_TRY_LINK([
+#include <stdio.h>
+#include <audiofile.h>
+],      [ return 0; ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding AUDIOFILE or finding the wrong"
+          echo "*** version of AUDIOFILE. If it is not finding AUDIOFILE, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means AUDIOFILE was incorrectly installed"
+          echo "*** or that you have moved AUDIOFILE since it was installed. In the latter case, you"
+          echo "*** may want to edit the audiofile-config script: $AUDIOFILE_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     AUDIOFILE_CFLAGS=""
+     AUDIOFILE_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(AUDIOFILE_CFLAGS)
+  AC_SUBST(AUDIOFILE_LIBS)
+  rm -f conf.audiofiletest
+])
+# Configure paths for GNOME
+# David Walluck   99-9-24
+
+dnl AM_PATH_GNOME([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for GNOME, and define GNOME_CFLAGS and GNOME_LIBS
+dnl
+AC_DEFUN(AM_PATH_GNOME,
+[dnl
+dnl Get the cflags and libraries from the gnome-config script
+dnl
+AC_ARG_WITH(gnome-prefix,[  --with-gnome-prefix=PFX Prefix where GNOME is installed (optional)],
+            gnome_prefix="$withval", gnome_prefix="")
+AC_ARG_WITH(gnome-exec-prefix,[  --with-gnome-exec-prefix=PFX Exec prefix where GNOME is installed (optional)],
+            gnome_exec_prefix="$withval", gnome_exec_prefix="")
+AC_ARG_ENABLE(gnometest, [  --disable-gnometest     Do not try to compile and run a test GNOME program],
+		    , enable_gnometest=yes)
+
+  if test x$gnome_exec_prefix != x ; then
+     gnome_args="$gnome_args --exec-prefix=$gnome_exec_prefix"
+     if test x${GNOME_CONFIG+set} != xset ; then
+        GNOME_CONFIG=$gnome_exec_prefix/bin/gnome-config
+     fi
+  fi
+  if test x$gnome_prefix != x ; then
+     gnome_args="$gnome_args --prefix=$gnome_prefix"
+     if test x${GNOME_CONFIG+set} != xset ; then
+        GNOME_CONFIG=$gnome_prefix/bin/gnome-config
+     fi
+  fi
+
+  AC_PATH_PROG(GNOME_CONFIG, gnome-config, no)
+  min_gnome_version=ifelse([$1], ,0.2.7,$1)
+  AC_MSG_CHECKING(for GNOME - version >= $min_gnome_version)
+  no_gnome=""
+  if test "$GNOME_CONFIG" = "no" ; then
+    no_gnome=yes
+  else
+    GNOME_CFLAGS=`$GNOME_CONFIG $gnomeconf_args gnome --cflags`
+    GNOME_LIBS=`$GNOME_CONFIG $gnomeconf_args gnome --libs`
+
+    gnome_major_version=`$GNOME_CONFIG $gnome_args --version | \
+           sed 's/gnome-libs //' | sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    gnome_minor_version=`$GNOME_CONFIG $gnome_args --version | \
+           sed 's/gnome-libs //' | sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    gnome_micro_version=`$GNOME_CONFIG $gnome_config_args --version | \
+           sed 's/gnome-libs //' | sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+    if test "x$enable_gnometest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $GNOME_CFLAGS"
+      LIBS="$LIBS $GNOME_LIBS"
+dnl
+dnl Now check if the installed GNOME is sufficiently new. (Also sanity
+dnl checks the results of gnome-config to some extent
+dnl
+      rm -f conf.gnometest
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gnome.h>
+
+int main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.gnometest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_gnome_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_gnome_version");
+     exit(1);
+   }
+
+   if (($gnome_major_version > major) ||
+      (($gnome_major_version == major) && ($gnome_minor_version > minor)) ||
+      (($gnome_major_version == major) && ($gnome_minor_version == minor) && ($gnome_micro_version >= micro)))
+    {
+      return 0;
+    }
+  else
+    {
+      printf("\n*** 'gnome-config --version' returned %d.%d.%d, but the minimum version\n", $gnome_major_version, $gnome_minor_version, $gnome_micro_version);
+      printf("*** of GNOME required is %d.%d.%d. If gnome-config is correct, then it is\n", major, minor, micro);
+      printf("*** best to upgrade to the required version.\n");
+      printf("*** If gnome-config was wrong, set the environment variable GNOME_CONFIG\n");
+      printf("*** to point to the correct copy of gnome-config, and remove the file\n");
+      printf("*** config.cache before re-running configure\n");
+      return 1;
+    }
+}
+
+],, no_gnome=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_gnome" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])
+  else
+     AC_MSG_RESULT(no)
+     if test "$GNOME_CONFIG" = "no" ; then
+       echo "*** The gnome-config script installed by GNOME could not be found"
+       echo "*** If GNOME was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the GNOME_CONFIG environment variable to the"
+       echo "*** full path to gnome-config."
+     else
+       if test -f conf.gnometest ; then
+        :
+       else
+          echo "*** Could not run GNOME test program, checking why..."
+          CFLAGS="$CFLAGS $GNOME_CFLAGS"
+          LIBS="$LIBS $GNOME_LIBS"
+          AC_TRY_LINK([
+#include <stdio.h>
+#include <gnome.h>
+],      [ return 0; ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding GNOME or finding the wrong"
+          echo "*** version of GNOME. If it is not finding GNOME, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means GNOME was incorrectly installed"
+          echo "*** or that you have moved GNOME since it was installed. In the latter case, you"
+          echo "*** may want to edit the gnome-config script: $GNOME_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     GNOME_CFLAGS=""
+     GNOME_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(GNOME_CFLAGS)
+  AC_SUBST(GNOME_LIBS)
+  rm -f conf.gnometest
+])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aclocal.m4	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,1140 @@
+dnl aclocal.m4 generated automatically by aclocal 1.4a
+
+dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+dnl PARTICULAR PURPOSE.
+
+dnl aclocal.m4 generated automatically by aclocal 1.4a
+
+dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+dnl PARTICULAR PURPOSE.
+
+# Configure paths for GLIB
+# Owen Taylor     97-11-3
+
+dnl AM_PATH_GLIB([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]])
+dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if "gmodule" or 
+dnl gthread is specified in MODULES, pass to glib-config
+dnl
+AC_DEFUN(AM_PATH_GLIB,
+[dnl 
+dnl Get the cflags and libraries from the glib-config script
+dnl
+AC_ARG_WITH(glib-prefix,[  --with-glib-prefix=PFX  Prefix where GLIB is installed (optional)],
+            glib_config_prefix="$withval", glib_config_prefix="")
+AC_ARG_WITH(glib-exec-prefix,[  --with-glib-exec-prefix=PFX Exec prefix where GLIB is installed (optional)],
+            glib_config_exec_prefix="$withval", glib_config_exec_prefix="")
+AC_ARG_ENABLE(glibtest, [  --disable-glibtest      Do not try to compile and run a test GLIB program],
+		    , enable_glibtest=yes)
+
+  if test x$glib_config_exec_prefix != x ; then
+     glib_config_args="$glib_config_args --exec-prefix=$glib_config_exec_prefix"
+     if test x${GLIB_CONFIG+set} != xset ; then
+        GLIB_CONFIG=$glib_config_exec_prefix/bin/glib-config
+     fi
+  fi
+  if test x$glib_config_prefix != x ; then
+     glib_config_args="$glib_config_args --prefix=$glib_config_prefix"
+     if test x${GLIB_CONFIG+set} != xset ; then
+        GLIB_CONFIG=$glib_config_prefix/bin/glib-config
+     fi
+  fi
+
+  for module in . $4
+  do
+      case "$module" in
+         gmodule) 
+             glib_config_args="$glib_config_args gmodule"
+         ;;
+         gthread) 
+             glib_config_args="$glib_config_args gthread"
+         ;;
+      esac
+  done
+
+  AC_PATH_PROG(GLIB_CONFIG, glib-config, no)
+  min_glib_version=ifelse([$1], ,1.2.0,$1)
+  AC_MSG_CHECKING(for GLIB - version >= $min_glib_version)
+  no_glib=""
+  if test "$GLIB_CONFIG" = "no" ; then
+    no_glib=yes
+  else
+    GLIB_CFLAGS=`$GLIB_CONFIG $glib_config_args --cflags`
+    GLIB_LIBS=`$GLIB_CONFIG $glib_config_args --libs`
+    glib_config_major_version=`$GLIB_CONFIG $glib_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    glib_config_minor_version=`$GLIB_CONFIG $glib_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    glib_config_micro_version=`$GLIB_CONFIG $glib_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+    if test "x$enable_glibtest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $GLIB_CFLAGS"
+      LIBS="$GLIB_LIBS $LIBS"
+dnl
+dnl Now check if the installed GLIB is sufficiently new. (Also sanity
+dnl checks the results of glib-config to some extent
+dnl
+      rm -f conf.glibtest
+      AC_TRY_RUN([
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int 
+main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.glibtest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_glib_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_glib_version");
+     exit(1);
+   }
+
+  if ((glib_major_version != $glib_config_major_version) ||
+      (glib_minor_version != $glib_config_minor_version) ||
+      (glib_micro_version != $glib_config_micro_version))
+    {
+      printf("\n*** 'glib-config --version' returned %d.%d.%d, but GLIB (%d.%d.%d)\n", 
+             $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version,
+             glib_major_version, glib_minor_version, glib_micro_version);
+      printf ("*** was found! If glib-config was correct, then it is best\n");
+      printf ("*** to remove the old version of GLIB. You may also be able to fix the error\n");
+      printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+      printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+      printf("*** required on your system.\n");
+      printf("*** If glib-config was wrong, set the environment variable GLIB_CONFIG\n");
+      printf("*** to point to the correct copy of glib-config, and remove the file config.cache\n");
+      printf("*** before re-running configure\n");
+    } 
+  else if ((glib_major_version != GLIB_MAJOR_VERSION) ||
+	   (glib_minor_version != GLIB_MINOR_VERSION) ||
+           (glib_micro_version != GLIB_MICRO_VERSION))
+    {
+      printf("*** GLIB header files (version %d.%d.%d) do not match\n",
+	     GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
+      printf("*** library (version %d.%d.%d)\n",
+	     glib_major_version, glib_minor_version, glib_micro_version);
+    }
+  else
+    {
+      if ((glib_major_version > major) ||
+        ((glib_major_version == major) && (glib_minor_version > minor)) ||
+        ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro)))
+      {
+        return 0;
+       }
+     else
+      {
+        printf("\n*** An old version of GLIB (%d.%d.%d) was found.\n",
+               glib_major_version, glib_minor_version, glib_micro_version);
+        printf("*** You need a version of GLIB newer than %d.%d.%d. The latest version of\n",
+	       major, minor, micro);
+        printf("*** GLIB is always available from ftp://ftp.gtk.org.\n");
+        printf("***\n");
+        printf("*** If you have already installed a sufficiently new version, this error\n");
+        printf("*** probably means that the wrong copy of the glib-config shell script is\n");
+        printf("*** being found. The easiest way to fix this is to remove the old version\n");
+        printf("*** of GLIB, but you can also set the GLIB_CONFIG environment to point to the\n");
+        printf("*** correct copy of glib-config. (In this case, you will have to\n");
+        printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+        printf("*** so that the correct libraries are found at run-time))\n");
+      }
+    }
+  return 1;
+}
+],, no_glib=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_glib" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$GLIB_CONFIG" = "no" ; then
+       echo "*** The glib-config script installed by GLIB could not be found"
+       echo "*** If GLIB was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the GLIB_CONFIG environment variable to the"
+       echo "*** full path to glib-config."
+     else
+       if test -f conf.glibtest ; then
+        :
+       else
+          echo "*** Could not run GLIB test program, checking why..."
+          CFLAGS="$CFLAGS $GLIB_CFLAGS"
+          LIBS="$LIBS $GLIB_LIBS"
+          AC_TRY_LINK([
+#include <glib.h>
+#include <stdio.h>
+],      [ return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding GLIB or finding the wrong"
+          echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means GLIB was incorrectly installed"
+          echo "*** or that you have moved GLIB since it was installed. In the latter case, you"
+          echo "*** may want to edit the glib-config script: $GLIB_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     GLIB_CFLAGS=""
+     GLIB_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(GLIB_CFLAGS)
+  AC_SUBST(GLIB_LIBS)
+  rm -f conf.glibtest
+])
+
+# Configure paths for GTK+
+# Owen Taylor     97-11-3
+
+dnl AM_PATH_GTK([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]])
+dnl Test for GTK, and define GTK_CFLAGS and GTK_LIBS
+dnl
+AC_DEFUN(AM_PATH_GTK,
+[dnl 
+dnl Get the cflags and libraries from the gtk-config script
+dnl
+AC_ARG_WITH(gtk-prefix,[  --with-gtk-prefix=PFX   Prefix where GTK is installed (optional)],
+            gtk_config_prefix="$withval", gtk_config_prefix="")
+AC_ARG_WITH(gtk-exec-prefix,[  --with-gtk-exec-prefix=PFX Exec prefix where GTK is installed (optional)],
+            gtk_config_exec_prefix="$withval", gtk_config_exec_prefix="")
+AC_ARG_ENABLE(gtktest, [  --disable-gtktest       Do not try to compile and run a test GTK program],
+		    , enable_gtktest=yes)
+
+  for module in . $4
+  do
+      case "$module" in
+         gthread) 
+             gtk_config_args="$gtk_config_args gthread"
+         ;;
+      esac
+  done
+
+  if test x$gtk_config_exec_prefix != x ; then
+     gtk_config_args="$gtk_config_args --exec-prefix=$gtk_config_exec_prefix"
+     if test x${GTK_CONFIG+set} != xset ; then
+        GTK_CONFIG=$gtk_config_exec_prefix/bin/gtk-config
+     fi
+  fi
+  if test x$gtk_config_prefix != x ; then
+     gtk_config_args="$gtk_config_args --prefix=$gtk_config_prefix"
+     if test x${GTK_CONFIG+set} != xset ; then
+        GTK_CONFIG=$gtk_config_prefix/bin/gtk-config
+     fi
+  fi
+
+  AC_PATH_PROG(GTK_CONFIG, gtk-config, no)
+  min_gtk_version=ifelse([$1], ,1.2.0,$1)
+  AC_MSG_CHECKING(for GTK - version >= $min_gtk_version)
+  no_gtk=""
+  if test "$GTK_CONFIG" = "no" ; then
+    no_gtk=yes
+  else
+    GTK_CFLAGS=`$GTK_CONFIG $gtk_config_args --cflags`
+    GTK_LIBS=`$GTK_CONFIG $gtk_config_args --libs`
+    gtk_config_major_version=`$GTK_CONFIG $gtk_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    gtk_config_minor_version=`$GTK_CONFIG $gtk_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    gtk_config_micro_version=`$GTK_CONFIG $gtk_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+    if test "x$enable_gtktest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $GTK_CFLAGS"
+      LIBS="$GTK_LIBS $LIBS"
+dnl
+dnl Now check if the installed GTK is sufficiently new. (Also sanity
+dnl checks the results of gtk-config to some extent
+dnl
+      rm -f conf.gtktest
+      AC_TRY_RUN([
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int 
+main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.gtktest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_gtk_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_gtk_version");
+     exit(1);
+   }
+
+  if ((gtk_major_version != $gtk_config_major_version) ||
+      (gtk_minor_version != $gtk_config_minor_version) ||
+      (gtk_micro_version != $gtk_config_micro_version))
+    {
+      printf("\n*** 'gtk-config --version' returned %d.%d.%d, but GTK+ (%d.%d.%d)\n", 
+             $gtk_config_major_version, $gtk_config_minor_version, $gtk_config_micro_version,
+             gtk_major_version, gtk_minor_version, gtk_micro_version);
+      printf ("*** was found! If gtk-config was correct, then it is best\n");
+      printf ("*** to remove the old version of GTK+. You may also be able to fix the error\n");
+      printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+      printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+      printf("*** required on your system.\n");
+      printf("*** If gtk-config was wrong, set the environment variable GTK_CONFIG\n");
+      printf("*** to point to the correct copy of gtk-config, and remove the file config.cache\n");
+      printf("*** before re-running configure\n");
+    } 
+#if defined (GTK_MAJOR_VERSION) && defined (GTK_MINOR_VERSION) && defined (GTK_MICRO_VERSION)
+  else if ((gtk_major_version != GTK_MAJOR_VERSION) ||
+	   (gtk_minor_version != GTK_MINOR_VERSION) ||
+           (gtk_micro_version != GTK_MICRO_VERSION))
+    {
+      printf("*** GTK+ header files (version %d.%d.%d) do not match\n",
+	     GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
+      printf("*** library (version %d.%d.%d)\n",
+	     gtk_major_version, gtk_minor_version, gtk_micro_version);
+    }
+#endif /* defined (GTK_MAJOR_VERSION) ... */
+  else
+    {
+      if ((gtk_major_version > major) ||
+        ((gtk_major_version == major) && (gtk_minor_version > minor)) ||
+        ((gtk_major_version == major) && (gtk_minor_version == minor) && (gtk_micro_version >= micro)))
+      {
+        return 0;
+       }
+     else
+      {
+        printf("\n*** An old version of GTK+ (%d.%d.%d) was found.\n",
+               gtk_major_version, gtk_minor_version, gtk_micro_version);
+        printf("*** You need a version of GTK+ newer than %d.%d.%d. The latest version of\n",
+	       major, minor, micro);
+        printf("*** GTK+ is always available from ftp://ftp.gtk.org.\n");
+        printf("***\n");
+        printf("*** If you have already installed a sufficiently new version, this error\n");
+        printf("*** probably means that the wrong copy of the gtk-config shell script is\n");
+        printf("*** being found. The easiest way to fix this is to remove the old version\n");
+        printf("*** of GTK+, but you can also set the GTK_CONFIG environment to point to the\n");
+        printf("*** correct copy of gtk-config. (In this case, you will have to\n");
+        printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+        printf("*** so that the correct libraries are found at run-time))\n");
+      }
+    }
+  return 1;
+}
+],, no_gtk=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_gtk" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$GTK_CONFIG" = "no" ; then
+       echo "*** The gtk-config script installed by GTK could not be found"
+       echo "*** If GTK was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the GTK_CONFIG environment variable to the"
+       echo "*** full path to gtk-config."
+     else
+       if test -f conf.gtktest ; then
+        :
+       else
+          echo "*** Could not run GTK test program, checking why..."
+          CFLAGS="$CFLAGS $GTK_CFLAGS"
+          LIBS="$LIBS $GTK_LIBS"
+          AC_TRY_LINK([
+#include <gtk/gtk.h>
+#include <stdio.h>
+],      [ return ((gtk_major_version) || (gtk_minor_version) || (gtk_micro_version)); ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding GTK or finding the wrong"
+          echo "*** version of GTK. If it is not finding GTK, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means GTK was incorrectly installed"
+          echo "*** or that you have moved GTK since it was installed. In the latter case, you"
+          echo "*** may want to edit the gtk-config script: $GTK_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     GTK_CFLAGS=""
+     GTK_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(GTK_CFLAGS)
+  AC_SUBST(GTK_LIBS)
+  rm -f conf.gtktest
+])
+
+# Configure paths for IMLIB
+# David Walluck   99-9-18   
+# Frank Belew     98-8-31
+# stolen from Manish Singh
+# Shamelessly stolen from Owen Taylor
+
+dnl AM_PATH_IMLIB([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for IMLIB, and define IMLIB_CFLAGS and IMLIB_LIBS
+dnl
+AC_DEFUN(AM_PATH_IMLIB,
+[dnl 
+dnl Get the cflags and libraries from the imlib-config script
+dnl
+AC_ARG_WITH(imlib-prefix,[  --with-imlib-prefix=PFX Prefix where IMLIB is installed (optional)],
+            imlib_prefix="$withval", imlib_prefix="")
+AC_ARG_WITH(imlib-exec-prefix,[  --with-imlib-exec-prefix=PFX Exec prefix where IMLIB is installed (optional)],
+            imlib_exec_prefix="$withval", imlib_exec_prefix="")
+AC_ARG_ENABLE(imlibtest, [  --disable-imlibtest Do not try to compile and run a test IMLIB program],
+		    , enable_imlibtest=yes)
+
+  if test x$imlib_exec_prefix != x ; then
+     imlib_args="$imlib_args --exec-prefix=$imlib_exec_prefix"
+     if test x${IMLIB_CONFIG+set} != xset ; then
+        IMLIB_CONFIG=$imlib_exec_prefix/bin/imlib-config
+     fi
+  fi
+  if test x$imlib_prefix != x ; then
+     imlib_args="$imlib_args --prefix=$imlib_prefix"
+     if test x${IMLIB_CONFIG+set} != xset ; then
+        IMLIB_CONFIG=$imlib_prefix/bin/imlib-config
+     fi
+  fi
+
+  AC_PATH_PROG(IMLIB_CONFIG, imlib-config, no)
+  min_imlib_version=ifelse([$1], ,1.9.4,$1)
+  AC_MSG_CHECKING(for IMLIB - version >= $min_imlib_version)
+  no_imlib=""
+  if test "$IMLIB_CONFIG" = "no" ; then
+    no_imlib=yes
+  else
+    IMLIB_CFLAGS=`$IMLIB_CONFIG $imlibconf_args --cflags`
+    IMLIB_LIBS=`$IMLIB_CONFIG $imlibconf_args --libs`
+
+    imlib_major_version=`$IMLIB_CONFIG $imlib_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    imlib_minor_version=`$IMLIB_CONFIG $imlib_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    imlib_micro_version=`$IMLIB_CONFIG $imlib_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+    if test "x$enable_imlibtest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $IMLIB_CFLAGS"
+      LIBS="$LIBS $IMLIB_LIBS"
+dnl
+dnl Now check if the installed IMLIB is sufficiently new. (Also sanity
+dnl checks the results of imlib-config to some extent
+dnl
+      rm -f conf.imlibtest
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+#include <Imlib.h>
+
+int main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.imlibtest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_imlib_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_imlib_version");
+     exit(1);
+   }
+
+    if (($imlib_major_version > major) ||
+        (($imlib_major_version == major) && ($imlib_minor_version > minor)) ||
+	(($imlib_major_version == major) && ($imlib_minor_version == minor) &&
+	($imlib_micro_version >= micro)))
+    {
+      return 0;
+    }
+  else
+    {
+      printf("\n*** 'imlib-config --version' returned %d.%d.%d, but the minimum version\n", $imlib_major_version, $imlib_minor_version, $imlib_micro_version);
+      printf("*** of IMLIB required is %d.%d.%d. If imlib-config is correct, then it is\n", major, minor, micro);
+      printf("*** best to upgrade to the required version.\n");
+      printf("*** If imlib-config was wrong, set the environment variable IMLIB_CONFIG\n");
+      printf("*** to point to the correct copy of imlib-config, and remove the file\n");
+      printf("*** config.cache before re-running configure\n");
+      return 1;
+    }
+}
+
+],, no_imlib=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_imlib" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$IMLIB_CONFIG" = "no" ; then
+       echo "*** The imlib-config script installed by IMLIB could not be found"
+       echo "*** If IMLIB was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the IMLIB_CONFIG environment variable to the"
+       echo "*** full path to imlib-config."
+     else
+       if test -f conf.imlibtest ; then
+        :
+       else
+          echo "*** Could not run IMLIB test program, checking why..."
+          CFLAGS="$CFLAGS $IMLIB_CFLAGS"
+          LIBS="$LIBS $IMLIB_LIBS"
+          AC_TRY_LINK([
+#include <stdio.h>
+#include <Imlib.h>
+],      [ return 0; ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding IMLIB or finding the wrong"
+          echo "*** version of IMLIB. If it is not finding IMLIB, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means IMLIB was incorrectly installed"
+          echo "*** or that you have moved IMLIB since it was installed. In the latter case, you"
+          echo "*** may want to edit the imlib-config script: $IMLIB_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     IMLIB_CFLAGS=""
+     IMLIB_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(IMLIB_CFLAGS)
+  AC_SUBST(IMLIB_LIBS)
+  rm -f conf.imlibtest
+])
+
+# Check for gdk-imlib
+AC_DEFUN(AM_PATH_GDK_IMLIB,
+[dnl 
+dnl Get the cflags and libraries from the imlib-config script
+dnl
+AC_ARG_WITH(imlib-prefix,[  --with-imlib-prefix=PFX Prefix where IMLIB is installed (optional)],
+            imlib_prefix="$withval", imlib_prefix="")
+AC_ARG_WITH(imlib-exec-prefix,[  --with-imlib-exec-prefix=PFX Exec prefix where IMLIB is installed (optional)],
+            imlib_exec_prefix="$withval", imlib_exec_prefix="")
+AC_ARG_ENABLE(imlibtest, [  --disable-imlibtest     Do not try to compile and run a test IMLIB program],
+		    , enable_imlibtest=yes)
+
+  if test x$imlib_exec_prefix != x ; then
+     imlib_args="$imlib_args --exec-prefix=$imlib_exec_prefix"
+     if test x${IMLIB_CONFIG+set} != xset ; then
+        IMLIB_CONFIG=$imlib_exec_prefix/bin/imlib-config
+     fi
+  fi
+  if test x$imlib_prefix != x ; then
+     imlib_args="$imlib_args --prefix=$imlib_prefix"
+     if test x${IMLIB_CONFIG+set} != xset ; then
+        IMLIB_CONFIG=$imlib_prefix/bin/imlib-config
+     fi
+  fi
+
+  AC_PATH_PROG(IMLIB_CONFIG, imlib-config, no)
+  min_imlib_version=ifelse([$1], ,1.9.4,$1)
+  AC_MSG_CHECKING(for IMLIB - version >= $min_imlib_version)
+  no_imlib=""
+  if test "$IMLIB_CONFIG" = "no" ; then
+    no_imlib=yes
+  else
+    GDK_IMLIB_CFLAGS=`$IMLIB_CONFIG $imlibconf_args --cflags-gdk`
+    GDK_IMLIB_LIBS=`$IMLIB_CONFIG $imlibconf_args --libs-gdk`
+
+    imlib_major_version=`$IMLIB_CONFIG $imlib_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    imlib_minor_version=`$IMLIB_CONFIG $imlib_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    imlib_micro_version=`$IMLIB_CONFIG $imlib_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`                  
+    if test "x$enable_imlibtest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $GDK_IMLIB_CFLAGS"
+      LIBS="$LIBS $GDK_IMLIB_LIBS"
+dnl
+dnl Now check if the installed IMLIB is sufficiently new. (Also sanity
+dnl checks the results of imlib-config to some extent
+dnl
+      rm -f conf.imlibtest
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+#include <gdk_imlib.h>
+
+int main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.gdkimlibtest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_imlib_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_imlib_version");
+     exit(1);
+   }
+
+    if (($imlib_major_version > major) ||
+        (($imlib_major_version == major) && ($imlib_minor_version > minor)) ||
+	(($imlib_major_version == major) && ($imlib_minor_version == minor) &&
+	($imlib_micro_version >= micro)))
+    {
+      return 0;
+    }
+  else
+    {
+      printf("\n*** 'imlib-config --version' returned %d.%d.%d, but the minimum version\n", $imlib_major_version, $imlib_minor_version, $imlib_micro_version);
+      printf("*** of IMLIB required is %d.%d.%d. If imlib-config is correct, then it is\n", major, minor, micro);
+      printf("*** best to upgrade to the required version.\n");
+      printf("*** If imlib-config was wrong, set the environment variable IMLIB_CONFIG\n");
+      printf("*** to point to the correct copy of imlib-config, and remove the file\n");
+      printf("*** config.cache before re-running configure\n");
+      return 1;
+    }
+}
+
+],, no_imlib=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_imlib" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$IMLIB_CONFIG" = "no" ; then
+       echo "*** The imlib-config script installed by IMLIB could not be found"
+       echo "*** If IMLIB was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the IMLIB_CONFIG environment variable to the"
+       echo "*** full path to imlib-config."
+     else
+       if test -f conf.gdkimlibtest ; then
+        :
+       else
+          echo "*** Could not run IMLIB test program, checking why..."
+          CFLAGS="$CFLAGS $GDK_IMLIB_CFLAGS"
+          LIBS="$LIBS $GDK_IMLIB_LIBS"
+          AC_TRY_LINK([
+#include <stdio.h>
+#include <gdk_imlib.h>
+],      [ return 0; ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding IMLIB or finding the wrong"
+          echo "*** version of IMLIB. If it is not finding IMLIB, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means IMLIB was incorrectly installed"
+          echo "*** or that you have moved IMLIB since it was installed. In the latter case, you"
+          echo "*** may want to edit the imlib-config script: $IMLIB_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     GDK_IMLIB_CFLAGS=""
+     GDK_IMLIB_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(GDK_IMLIB_CFLAGS)
+  AC_SUBST(GDK_IMLIB_LIBS)
+  rm -f conf.gdkimlibtest
+])
+
+# Configure paths for ESD
+# David Walluck   99-9-20
+# Manish Singh    98-9-30
+# stolen back from Frank Belew
+# stolen from Manish Singh
+# Shamelessly stolen from Owen Taylor
+
+dnl AM_PATH_ESD([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for ESD, and define ESD_CFLAGS and ESD_LIBS
+dnl
+AC_DEFUN(AM_PATH_ESD,
+[dnl 
+dnl Get the cflags and libraries from the esd-config script
+dnl
+AC_ARG_WITH(esd-prefix,[  --with-esd-prefix=PFX   Prefix where ESD is installed (optional)],
+            esd_prefix="$withval", esd_prefix="")
+AC_ARG_WITH(esd-exec-prefix,[  --with-esd-exec-prefix=PFX Exec prefix where ESD is installed (optional)],
+            esd_exec_prefix="$withval", esd_exec_prefix="")
+AC_ARG_ENABLE(esdtest, [  --disable-esdtest       Do not try to compile and run a test ESD program],
+		    , enable_esdtest=yes)
+
+  if test x$esd_exec_prefix != x ; then
+     esd_args="$esd_args --exec-prefix=$esd_exec_prefix"
+     if test x${ESD_CONFIG+set} != xset ; then
+        ESD_CONFIG=$esd_exec_prefix/bin/esd-config
+     fi
+  fi
+  if test x$esd_prefix != x ; then
+     esd_args="$esd_args --prefix=$esd_prefix"
+     if test x${ESD_CONFIG+set} != xset ; then
+        ESD_CONFIG=$esd_prefix/bin/esd-config
+     fi
+  fi
+
+  AC_PATH_PROG(ESD_CONFIG, esd-config, no)
+  min_esd_version=ifelse([$1], ,0.2.5,$1)
+  AC_MSG_CHECKING(for ESD - version >= $min_esd_version)
+  no_esd=""
+  if test "$ESD_CONFIG" = "no" ; then
+    no_esd=yes
+  else
+    ESD_CFLAGS=`$ESD_CONFIG $esdconf_args --cflags`
+    ESD_LIBS=`$ESD_CONFIG $esdconf_args --libs`
+
+    esd_major_version=`$ESD_CONFIG $esd_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    esd_minor_version=`$ESD_CONFIG $esd_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    esd_micro_version=`$ESD_CONFIG $esd_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+    if test "x$enable_esdtest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $ESD_CFLAGS"
+      LIBS="$LIBS $ESD_LIBS"
+dnl
+dnl Now check if the installed ESD is sufficiently new. (Also sanity
+dnl checks the results of esd-config to some extent
+dnl
+      rm -f conf.esdtest
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+#include <esd.h>
+
+int main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.esdtest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_esd_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_esd_version");
+     exit(1);
+   }
+
+   if (($esd_major_version > major) ||
+      (($esd_major_version == major) && ($esd_minor_version > minor)) ||
+      (($esd_major_version == major) && ($esd_minor_version == minor) && ($esd_micro_version >= micro)))
+    {
+      return 0;
+    }
+  else
+    {
+      printf("\n*** 'esd-config --version' returned %d.%d.%d, but the minimum version\n", $esd_major_version, $esd_minor_version, $esd_micro_version);
+      printf("*** of ESD required is %d.%d.%d. If esd-config is correct, then it is\n", major, minor, micro);
+      printf("*** best to upgrade to the required version.\n");
+      printf("*** If esd-config was wrong, set the environment variable ESD_CONFIG\n");
+      printf("*** to point to the correct copy of esd-config, and remove the file\n");
+      printf("*** config.cache before re-running configure\n");
+      return 1;
+    }
+}
+
+],, no_esd=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_esd" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$ESD_CONFIG" = "no" ; then
+       echo "*** The esd-config script installed by ESD could not be found"
+       echo "*** If ESD was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the ESD_CONFIG environment variable to the"
+       echo "*** full path to esd-config."
+     else
+       if test -f conf.esdtest ; then
+        :
+       else
+          echo "*** Could not run ESD test program, checking why..."
+          CFLAGS="$CFLAGS $ESD_CFLAGS"
+          LIBS="$LIBS $ESD_LIBS"
+          AC_TRY_LINK([
+#include <stdio.h>
+#include <esd.h>
+],      [ return 0; ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding ESD or finding the wrong"
+          echo "*** version of ESD. If it is not finding ESD, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means ESD was incorrectly installed"
+          echo "*** or that you have moved ESD since it was installed. In the latter case, you"
+          echo "*** may want to edit the esd-config script: $ESD_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     ESD_CFLAGS=""
+     ESD_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(ESD_CFLAGS)
+  AC_SUBST(ESD_LIBS)
+  rm -f conf.esdtest
+])
+
+# Configure paths for AUDIOFILE
+# Bertrand Guiheneuf 98-10-21
+# stolen from esd.m4 in esound :
+# Manish Singh    98-9-30
+# stolen back from Frank Belew
+# stolen from Manish Singh
+# Shamelessly stolen from Owen Taylor
+
+dnl AM_PATH_AUDIOFILE([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for AUDIOFILE, and define AUDIOFILE_CFLAGS and AUDIOFILE_LIBS
+dnl
+AC_DEFUN(AM_PATH_AUDIOFILE,
+[dnl 
+dnl Get the cflags and libraries from the audiofile-config script
+dnl
+AC_ARG_WITH(audiofile-prefix,[  --with-audiofile-prefix=PFX Prefix where AUDIOFILE is installed (optional)],
+            audiofile_prefix="$withval", audiofile_prefix="")
+AC_ARG_WITH(audiofile-exec-prefix,[  --with-audiofile-exec-prefix=PFX Exec prefix where AUDIOFILE is installed
+                          (optional)],
+            audiofile_exec_prefix="$withval", audiofile_exec_prefix="")
+AC_ARG_ENABLE(audiofiletest, [  --disable-audiofiletest Do not try to compile and run a test AUDIOFILE program],
+		    , enable_audiofiletest=yes)
+
+  if test x$audiofile_exec_prefix != x ; then
+     audiofile_args="$audiofile_args --exec-prefix=$audiofile_exec_prefix"
+     if test x${AUDIOFILE_CONFIG+set} != xset ; then
+        AUDIOFILE_CONFIG=$audiofile_exec_prefix/bin/audiofile-config
+     fi
+  fi
+  if test x$audiofile_prefix != x ; then
+     audiofile_args="$audiofile_args --prefix=$audiofile_prefix"
+     if test x${AUDIOFILE_CONFIG+set} != xset ; then
+        AUDIOFILE_CONFIG=$audiofile_prefix/bin/audiofile-config
+     fi
+  fi
+
+  AC_PATH_PROG(AUDIOFILE_CONFIG, audiofile-config, no)
+  min_audiofile_version=ifelse([$1], ,0.1.5,$1)
+  AC_MSG_CHECKING(for AUDIOFILE - version >= $min_audiofile_version)
+  no_audiofile=""
+  if test "$AUDIOFILE_CONFIG" = "no" ; then
+    no_audiofile=yes
+  else
+    AUDIOFILE_LIBS=`$AUDIOFILE_CONFIG $audiofileconf_args --libs`
+    AUDIOFILE_CFLAGS=`$AUDIOFILE_CONFIG $audiofileconf_args --cflags`
+    audiofile_major_version=`$AUDIOFILE_CONFIG $audiofile_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    audiofile_minor_version=`$AUDIOFILE_CONFIG $audiofile_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    audiofile_micro_version=`$AUDIOFILE_CONFIG $audiofile_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+    if test "x$enable_audiofiletest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $AUDIOFILE_CFLAGS"
+      LIBS="$LIBS $AUDIOFILE_LIBS"
+dnl
+dnl Now check if the installed AUDIOFILE is sufficiently new. (Also sanity
+dnl checks the results of audiofile-config to some extent
+dnl
+      rm -f conf.audiofiletest
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+#include <audiofile.h>
+
+int main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.audiofiletest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_audiofile_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_audiofile_version");
+     exit(1);
+   }
+
+   if (($audiofile_major_version > major) ||
+      (($audiofile_major_version == major) && ($audiofile_minor_version > minor)) ||
+      (($audiofile_major_version == major) && ($audiofile_minor_version == minor) && ($audiofile_micro_version >= micro)))
+    {
+      return 0;
+    }
+  else
+    {
+      printf("\n*** 'audiofile-config --version' returned %d.%d.%d, but the minimum version\n", $audiofile_major_version, $audiofile_minor_version, $audiofile_micro_version);
+      printf("*** of AUDIOFILE required is %d.%d.%d. If audiofile-config is correct, then it is\n", major, minor, micro);
+      printf("*** best to upgrade to the required version.\n");
+      printf("*** If audiofile-config was wrong, set the environment variable AUDIOFILE_CONFIG\n");
+      printf("*** to point to the correct copy of audiofile-config, and remove the file\n");
+      printf("*** config.cache before re-running configure\n");
+      return 1;
+    }
+}
+
+],, no_audiofile=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_audiofile" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$AUDIOFILE_CONFIG" = "no" ; then
+       echo "*** The audiofile-config script installed by AUDIOFILE could not be found"
+       echo "*** If AUDIOFILE was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the AUDIOFILE_CONFIG environment variable to the"
+       echo "*** full path to audiofile-config."
+     else
+       if test -f conf.audiofiletest ; then
+        :
+       else
+          echo "*** Could not run AUDIOFILE test program, checking why..."
+          CFLAGS="$CFLAGS $AUDIOFILE_CFLAGS"
+          LIBS="$LIBS $AUDIOFILE_LIBS"
+          AC_TRY_LINK([
+#include <stdio.h>
+#include <audiofile.h>
+],      [ return 0; ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding AUDIOFILE or finding the wrong"
+          echo "*** version of AUDIOFILE. If it is not finding AUDIOFILE, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means AUDIOFILE was incorrectly installed"
+          echo "*** or that you have moved AUDIOFILE since it was installed. In the latter case, you"
+          echo "*** may want to edit the audiofile-config script: $AUDIOFILE_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     AUDIOFILE_CFLAGS=""
+     AUDIOFILE_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(AUDIOFILE_CFLAGS)
+  AC_SUBST(AUDIOFILE_LIBS)
+  rm -f conf.audiofiletest
+])
+# Configure paths for GNOME
+# David Walluck   99-9-24
+
+dnl AM_PATH_GNOME([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for GNOME, and define GNOME_CFLAGS and GNOME_LIBS
+dnl
+AC_DEFUN(AM_PATH_GNOME,
+[dnl
+dnl Get the cflags and libraries from the gnome-config script
+dnl
+AC_ARG_WITH(gnome-prefix,[  --with-gnome-prefix=PFX Prefix where GNOME is installed (optional)],
+            gnome_prefix="$withval", gnome_prefix="")
+AC_ARG_WITH(gnome-exec-prefix,[  --with-gnome-exec-prefix=PFX Exec prefix where GNOME is installed (optional)],
+            gnome_exec_prefix="$withval", gnome_exec_prefix="")
+AC_ARG_ENABLE(gnometest, [  --disable-gnometest     Do not try to compile and run a test GNOME program],
+		    , enable_gnometest=yes)
+
+  if test x$gnome_exec_prefix != x ; then
+     gnome_args="$gnome_args --exec-prefix=$gnome_exec_prefix"
+     if test x${GNOME_CONFIG+set} != xset ; then
+        GNOME_CONFIG=$gnome_exec_prefix/bin/gnome-config
+     fi
+  fi
+  if test x$gnome_prefix != x ; then
+     gnome_args="$gnome_args --prefix=$gnome_prefix"
+     if test x${GNOME_CONFIG+set} != xset ; then
+        GNOME_CONFIG=$gnome_prefix/bin/gnome-config
+     fi
+  fi
+
+  AC_PATH_PROG(GNOME_CONFIG, gnome-config, no)
+  min_gnome_version=ifelse([$1], ,0.2.7,$1)
+  AC_MSG_CHECKING(for GNOME - version >= $min_gnome_version)
+  no_gnome=""
+  if test "$GNOME_CONFIG" = "no" ; then
+    no_gnome=yes
+  else
+    GNOME_CFLAGS=`$GNOME_CONFIG $gnomeconf_args gnome --cflags`
+    GNOME_LIBS=`$GNOME_CONFIG $gnomeconf_args gnome --libs`
+
+    gnome_major_version=`$GNOME_CONFIG $gnome_args --version | \
+           sed 's/gnome-libs //' | sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    gnome_minor_version=`$GNOME_CONFIG $gnome_args --version | \
+           sed 's/gnome-libs //' | sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    gnome_micro_version=`$GNOME_CONFIG $gnome_config_args --version | \
+           sed 's/gnome-libs //' | sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+    if test "x$enable_gnometest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $GNOME_CFLAGS"
+      LIBS="$LIBS $GNOME_LIBS"
+dnl
+dnl Now check if the installed GNOME is sufficiently new. (Also sanity
+dnl checks the results of gnome-config to some extent
+dnl
+      rm -f conf.gnometest
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gnome.h>
+
+int main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.gnometest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_gnome_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_gnome_version");
+     exit(1);
+   }
+
+   if (($gnome_major_version > major) ||
+      (($gnome_major_version == major) && ($gnome_minor_version > minor)) ||
+      (($gnome_major_version == major) && ($gnome_minor_version == minor) && ($gnome_micro_version >= micro)))
+    {
+      return 0;
+    }
+  else
+    {
+      printf("\n*** 'gnome-config --version' returned %d.%d.%d, but the minimum version\n", $gnome_major_version, $gnome_minor_version, $gnome_micro_version);
+      printf("*** of GNOME required is %d.%d.%d. If gnome-config is correct, then it is\n", major, minor, micro);
+      printf("*** best to upgrade to the required version.\n");
+      printf("*** If gnome-config was wrong, set the environment variable GNOME_CONFIG\n");
+      printf("*** to point to the correct copy of gnome-config, and remove the file\n");
+      printf("*** config.cache before re-running configure\n");
+      return 1;
+    }
+}
+
+],, no_gnome=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_gnome" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])
+  else
+     AC_MSG_RESULT(no)
+     if test "$GNOME_CONFIG" = "no" ; then
+       echo "*** The gnome-config script installed by GNOME could not be found"
+       echo "*** If GNOME was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the GNOME_CONFIG environment variable to the"
+       echo "*** full path to gnome-config."
+     else
+       if test -f conf.gnometest ; then
+        :
+       else
+          echo "*** Could not run GNOME test program, checking why..."
+          CFLAGS="$CFLAGS $GNOME_CFLAGS"
+          LIBS="$LIBS $GNOME_LIBS"
+          AC_TRY_LINK([
+#include <stdio.h>
+#include <gnome.h>
+],      [ return 0; ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding GNOME or finding the wrong"
+          echo "*** version of GNOME. If it is not finding GNOME, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means GNOME was incorrectly installed"
+          echo "*** or that you have moved GNOME since it was installed. In the latter case, you"
+          echo "*** may want to edit the gnome-config script: $GNOME_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     GNOME_CFLAGS=""
+     GNOME_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(GNOME_CFLAGS)
+  AC_SUBST(GNOME_LIBS)
+  rm -f conf.gnometest
+])
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/compat.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,228 @@
+/* $Id: compat.h,v 1.2 2003/02/14 16:16:40 bsmith Exp $ */
+
+#ifndef _COMPAT_H
+#define _COMPAT_H
+
+/* This header includes and defines everything needed for a given OS/compiler */
+#ifdef __UNIX__
+#include "config.h"
+
+#include <sys/stat.h>
+#include <unistd.h>
+void msleep(long period);
+#endif /* Unix */
+
+#ifndef __TARGET__
+#define __TARGET__ "dw"
+#endif
+
+#include <sys/types.h>
+#if HAVE_DIRENT_H
+#include <dirent.h>
+#define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+#if HAVE_SYS_NDIR_H
+#include <sys/ndir.h>
+#endif /* HAVE_SYS_NDIR_H */
+#if HAVE_SYS_DIR_H
+#include <sys/dir.h>
+#endif /* HAVE_SYS_DIR_H */
+#if HAVE_NDIR_H
+#include <ndir.h>
+#endif /* HAVE_NDIR_H */
+#endif /* HAVE_DIRENT_H */
+
+#ifdef DIRSEP
+#undef DIRSEP
+#endif
+
+#if defined(__EMX__) || defined(__OS2__) || defined(__WIN32__) || defined(WINNT)
+#include <io.h>
+#include <process.h>
+
+#define DIRSEP "\\"
+#define INIDIR "."
+#define TYPDIR "."
+#else
+#define DIRSEP "/"
+#define INIDIR "~/." __TARGET__
+#define TYPDIR "/usr/local/" __TARGET__
+#endif
+
+/* OS/2 */
+#if defined(__EMX__) || defined(__OS2__)
+#define INCL_WIN
+#define INCL_GPI
+#define INCL_VIO
+#define INCL_NLS
+#define INCL_DOS
+#define INCL_DEV
+#define INCL_DOSERRORS
+
+#if defined(__IBMC__) && !defined(API)
+#define API _System
+#endif
+
+#define msleep(a) DosSleep(a)
+
+#ifdef __EMX__
+#include <dirent.h>
+#include <sys/stat.h>
+#define HAVE_PIPE
+#ifdef FD_SETSIZE
+#undef FD_SETSIZE
+#endif
+#define FD_SETSIZE 1024
+#endif /* __EMX__ */
+
+#if defined(__EMX__) || defined(__WATCOMC__)
+#define strcasecmp stricmp
+#define strncasecmp strnicmp
+#endif
+
+#ifndef OS2
+#define OS2
+#endif /* OS2 */
+
+#include <os2.h>
+
+#ifndef BKS_TABBEDDIALOG
+#define BKS_TABBEDDIALOG          0x0800
+#endif 
+
+#define PIPENAME "\\socket\\" __TARGET__ "%d"
+#define TPIPENAME "\\socket\\" __TARGET__ "%d"
+#else
+#define PIPENAME "/tmp/" __TARGET__ "%d"
+#define TPIPENAME "/tmp/" __TARGET__ "%d"
+#endif /* __EMX__ || __IBMC__ */
+
+#if defined(__OS2__) && (defined(__IBMC__) || defined(__WATCOMC__))
+#define BSD_SELECT
+
+#include <types.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/select.h>
+#include <sys/ioctl.h>
+#include <direct.h>
+#include <stdarg.h>
+/* For VAC we are using the Mozilla dirent.c */
+#ifndef __WATCOMC__
+#include "platform/dirent.h"
+#endif
+#endif
+
+/* Windows */
+#if defined(__WIN32__) || defined(WINNT)
+#include <windows.h>
+#include <winsock.h>
+#include <time.h>
+#include <process.h>
+#include <sys/stat.h>
+#ifdef MSVC
+#include "platform/dirent.h"
+#else
+#include <dir.h>
+#include <dirent.h>
+#endif
+#include <stdarg.h>
+
+#if defined(MSVC) && !defined(API)
+#define API _cdecl
+#endif
+
+#if defined(__CYGWIN32__) || defined(__MINGW32__)
+#include <sys/un.h>
+#endif /* __CYGWIN32__ || __MINGW32__ */
+
+#ifndef __CYGWIN32__
+#define NO_DOMAIN_SOCKETS
+#endif /* __CYGWIN32__ */
+
+#if defined(_P_NOWAIT) && !defined(P_NOWAIT)
+#define P_NOWAIT _P_NOWAIT
+#endif
+
+#define strcasecmp stricmp
+#define strncasecmp strnicmp
+#define msleep Sleep
+
+#endif /* WIN32 */
+
+/* Everything else ;) */
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#include <stdlib.h>
+#include <stddef.h>
+#include <signal.h>
+#include <fcntl.h>
+
+#if !defined(__WIN32__) && !defined(WINNT)
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/nameser.h>
+#if defined(__OS2__) && defined(RES_DEFAULT)
+#undef RES_DEFAULT
+#endif
+#include <resolv.h>
+#include <stdarg.h>
+#include <string.h>
+#endif /* !WIN32 */
+#include <ctype.h>
+
+#ifndef _MAX_PATH
+#define _MAX_PATH 255
+#endif
+
+/* IBM C doesn't allow "t" in the mode parameter
+ * because it violates the ANSI standard.
+ */
+#ifdef __IBMC__
+#define FOPEN_READ_TEXT "r"
+#define FOPEN_WRITE_TEXT "w"
+#define FOPEN_APPEND_TEXT "a"
+#else
+#define FOPEN_READ_TEXT "rt"
+#define FOPEN_WRITE_TEXT "wt"
+#define FOPEN_APPEND_TEXT "at"
+#endif
+#define FOPEN_READ_BINARY "rb"
+#define FOPEN_WRITE_BINARY "wb"
+#define FOPEN_APPEND_BINARY "ab"
+
+#ifndef API
+#define API
+#endif
+
+/* Compatibility layer for IBM C/Winsock */
+int	API sockread (int a, void *b, int c, int d);
+int	API sockwrite (int a, void *b, int c, int d);
+int	API sockclose(int a);
+int API socksprintf(int fd, char *format, ...);
+int API sockpipe(int *pipes);
+void API sockinit(void);
+void API sockshutdown(void);
+int API makedir(char *path);
+void API nonblock(int fd);
+void API block(int fd);
+void API setfileinfo(char *filename, char *url, char *logfile);
+long double API drivesize(int drive);
+long double API drivefree(int drive);
+int API isdrive(int drive);
+void API getfsname(int drive, char *buf, int len);
+FILE * API fsopen(char *path, char *modes);
+int API fsclose(FILE *fp);
+char * API fsgets(char *str, int size, FILE *stream);
+int API fsseek(FILE *stream, long offset, int whence);
+int API locale_init(char *filename, int my_locale);
+char * API locale_string(char *default_text, int message);
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config.h.in	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,37 @@
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define if you have the ANSI C header files.  */
+#undef STDC_HEADERS
+
+/* Define if you have the connect function.  */
+#undef HAVE_CONNECT
+
+/* Define if you have the pipe function.  */
+#undef HAVE_PIPE
+
+/* Define if you have the <dirent.h> header file.  */
+#undef HAVE_DIRENT_H
+
+/* Define if you have the <ndir.h> header file.  */
+#undef HAVE_NDIR_H
+
+/* Define if you have the <sys/dir.h> header file.  */
+#undef HAVE_SYS_DIR_H
+
+/* Define if you have the <sys/ndir.h> header file.  */
+#undef HAVE_SYS_NDIR_H
+
+/* Define if you have the <unistd.h> header file.  */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the <sys/stat.h> header file.  */
+#undef HAVE_SYS_STAT_H
+
+/* Determine whether we have the pipe function */
+#undef HAVE_PIPE
+
+/* Define if IMLIB is available. */
+#undef USE_IMLIB
+
+/* Define if PIXBUF is available. */
+#undef USE_PIXBUF
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/configure	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,5840 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.53.
+#
+# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
+# Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+
+# NLS nuisances.
+# Support unset when possible.
+if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+(set +x; test -n "`(LANG=C; export LANG) 2>&1`") &&
+    { $as_unset LANG || test "${LANG+set}" != set; } ||
+      { LANG=C; export LANG; }
+(set +x; test -n "`(LC_ALL=C; export LC_ALL) 2>&1`") &&
+    { $as_unset LC_ALL || test "${LC_ALL+set}" != set; } ||
+      { LC_ALL=C; export LC_ALL; }
+(set +x; test -n "`(LC_TIME=C; export LC_TIME) 2>&1`") &&
+    { $as_unset LC_TIME || test "${LC_TIME+set}" != set; } ||
+      { LC_TIME=C; export LC_TIME; }
+(set +x; test -n "`(LC_CTYPE=C; export LC_CTYPE) 2>&1`") &&
+    { $as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set; } ||
+      { LC_CTYPE=C; export LC_CTYPE; }
+(set +x; test -n "`(LANGUAGE=C; export LANGUAGE) 2>&1`") &&
+    { $as_unset LANGUAGE || test "${LANGUAGE+set}" != set; } ||
+      { LANGUAGE=C; export LANGUAGE; }
+(set +x; test -n "`(LC_COLLATE=C; export LC_COLLATE) 2>&1`") &&
+    { $as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set; } ||
+      { LC_COLLATE=C; export LC_COLLATE; }
+(set +x; test -n "`(LC_NUMERIC=C; export LC_NUMERIC) 2>&1`") &&
+    { $as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set; } ||
+      { LC_NUMERIC=C; export LC_NUMERIC; }
+(set +x; test -n "`(LC_MESSAGES=C; export LC_MESSAGES) 2>&1`") &&
+    { $as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set; } ||
+      { LC_MESSAGES=C; export LC_MESSAGES; }
+
+
+# Name of the executable.
+as_me=`(basename "$0") 2>/dev/null ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)$' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\/\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conftest.sh
+  echo  "exit 0"   >>conftest.sh
+  chmod +x conftest.sh
+  if (PATH=".;."; conftest.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conftest.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+	 case $as_dir in
+	 /*)
+	   if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+	     CONFIG_SHELL=$as_dir/$as_base
+	     export CONFIG_SHELL
+	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+	   fi;;
+	 esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='	' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; }
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete.  It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="install.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_option in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    eval "enable_$ac_feature=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_$ac_feature='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_$ac_package='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/-/_/g'`
+    eval "with_$ac_package=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+    eval "$ac_envvar='$ac_optarg'"
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+              localstatedir libdir includedir oldincludedir infodir mandir
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+         X"$0" : 'X\(//\)[^/]' \| \
+         X"$0" : 'X\(//\)$' \| \
+         X"$0" : 'X\(/\)' \| \
+         .     : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+   { (exit 1); exit 1; }; }
+  else
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+  fi
+fi
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+  cat <<_ACEOF
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --infodir=DIR          info documentation [PREFIX/info]
+  --mandir=DIR           man documentation [PREFIX/man]
+_ACEOF
+
+  cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --disable-glibtest      Do not try to compile and run a test GLIB program
+  --disable-gtktest       Do not try to compile and run a test GTK program
+  --disable-imlibtest     Do not try to compile and run a test IMLIB program
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-glib-prefix=PFX  Prefix where GLIB is installed (optional)
+  --with-glib-exec-prefix=PFX Exec prefix where GLIB is installed (optional)
+  --with-gtk-prefix=PFX   Prefix where GTK is installed (optional)
+  --with-gtk-exec-prefix=PFX Exec prefix where GTK is installed (optional)
+  --with-imlib-prefix=PFX Prefix where IMLIB is installed (optional)
+  --with-imlib-exec-prefix=PFX Exec prefix where IMLIB is installed (optional)
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
+              headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  ac_popdir=`pwd`
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d $ac_dir || continue
+    ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+# absolute.
+ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+ac_abs_top_builddir=`cd "$ac_dir" && cd $ac_top_builddir && pwd`
+ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
+
+    cd $ac_dir
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_srcdir/configure.gnu; then
+      echo
+      $SHELL $ac_srcdir/configure.gnu  --help=recursive
+    elif test -f $ac_srcdir/configure; then
+      echo
+      $SHELL $ac_srcdir/configure  --help=recursive
+    elif test -f $ac_srcdir/configure.ac ||
+           test -f $ac_srcdir/configure.in; then
+      echo
+      $ac_configure --help
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi
+    cd $ac_popdir
+  done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+  cat <<\_ACEOF
+
+Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
+Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.53.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell meta-characters.
+ac_configure_args=
+ac_sep=
+for ac_arg
+do
+  case $ac_arg in
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n ) continue ;;
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    continue ;;
+  *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+    ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+  esac
+  case " $ac_configure_args " in
+    *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+    *) ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+       ac_sep=" " ;;
+  esac
+  # Get rid of the leading space.
+done
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+{
+  (set) 2>&1 |
+    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      sed -n \
+        "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+    	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+      ;;
+    *)
+      sed -n \
+        "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+}
+    echo
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      sed "/^$/d" confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core core.* *.core &&
+  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+     ' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . $cache_file;;
+      *)                      . ./$cache_file;;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+               sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+  eval ac_new_val="\$ac_env_${ac_var}_value"
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+        { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+        { echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+        { echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+        ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+INCLUDES="-I."
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    set dummy "$as_dir/$ac_word" ${1+"$@"}
+    shift
+    ac_cv_prog_CC="$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CC" && break
+done
+
+  CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH" >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH" >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output" >&5
+echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+  (eval $ac_link_default) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Find the output, starting from the most likely.  This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+for ac_file in `ls a_out.exe a.exe conftest.exe 2>/dev/null;
+                ls a.out conftest 2>/dev/null;
+                ls a.* conftest.* 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb | *.xSYM ) ;;
+    a.out ) # We found the default executable, but exeext='' is most
+            # certainly right.
+            break;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+          # FIXME: I believe we export ac_cv_exeext for Libtool --akim.
+          export ac_cv_exeext
+          break;;
+    * ) break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables" >&5
+echo "$as_me: error: C compiler cannot create executables" >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in `(ls conftest.exe; ls conftest; ls conftest.*) 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+          export ac_cv_exeext
+          break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link" >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile" >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_compiler_gnu=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+# Some people use a C++ compiler to compile C.  Since we use `exit',
+# in C++ we need to declare it.  In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+  choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  for ac_declaration in \
+   ''\
+   '#include <stdlib.h>' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+$ac_declaration
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+continue
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_declaration
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Extract the first word of "gmake", so it can be a program name with args.
+set dummy gmake; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_MAKE+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$MAKE"; then
+  ac_cv_prog_MAKE="$MAKE" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_MAKE="gmake"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+MAKE=$ac_cv_prog_MAKE
+if test -n "$MAKE"; then
+  echo "$as_me:$LINENO: result: $MAKE" >&5
+echo "${ECHO_T}$MAKE" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test x"$MAKE" = x; then
+  # Extract the first word of "make", so it can be a program name with args.
+set dummy make; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_MAKE+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$MAKE"; then
+  ac_cv_prog_MAKE="$MAKE" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_MAKE="make"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+MAKE=$ac_cv_prog_MAKE
+if test -n "$MAKE"; then
+  echo "$as_me:$LINENO: result: $MAKE" >&5
+echo "${ECHO_T}$MAKE" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f $ac_dir/shtool; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+        if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+          if test $ac_prog = install &&
+            grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+            # AIX install.  It has an incompatible calling convention.
+            :
+          elif test $ac_prog = install &&
+            grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+            # program-specific install script used by HP pwplus--don't use.
+            :
+          else
+            ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+            break 3
+          fi
+        fi
+      done
+    done
+    ;;
+esac
+done
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL=$ac_install_sh
+  fi
+fi
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <assert.h>
+                     Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <assert.h>
+                     Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check" >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) (('a' <= (c) && (c) <= 'i') \
+                     || ('j' <= (c) && (c) <= 'r') \
+                     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+        || toupper (i) != TOUPPER (i))
+      exit(2);
+  exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+
+
+
+
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
+  as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5
+echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <$ac_hdr>
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+if ((DIR *) 0)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1
+_ACEOF
+
+ac_header_dirent=$ac_hdr; break
+fi
+
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+  echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6
+if test "${ac_cv_search_opendir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_opendir=no
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="none required"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_opendir" = no; then
+  for ac_lib in dir; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="-l$ac_lib"
+break
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6
+if test "$ac_cv_search_opendir" != no; then
+  test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS"
+
+fi
+
+else
+  echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6
+if test "${ac_cv_search_opendir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_opendir=no
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="none required"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_opendir" = no; then
+  for ac_lib in x; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="-l$ac_lib"
+break
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6
+if test "$ac_cv_search_opendir" != no; then
+  test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS"
+
+fi
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                  inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_header in unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_header_compiler=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc in
+  yes:no )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;};;
+  no:yes )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;};;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in sys/stat.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_header_compiler=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc in
+  yes:no )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;};;
+  no:yes )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;};;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_func in pipe
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+char (*f) ();
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+f = $ac_func;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$as_ac_var=no"
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_PIPE 1
+_ACEOF
+
+fi
+done
+
+
+
+for ac_func in connect
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char $ac_func ();
+char (*f) ();
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+f = $ac_func;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$as_ac_var=no"
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+if test x"$ac_cv_func_connect" = x"no"; then
+  if test -z "$libsocket"; then
+    echo "$as_me:$LINENO: checking for socket in -lsocket" >&5
+echo $ECHO_N "checking for socket in -lsocket... $ECHO_C" >&6
+if test "${ac_cv_lib_socket_socket+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char socket ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+socket ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_socket_socket=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_socket_socket=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_socket_socket" >&5
+echo "${ECHO_T}$ac_cv_lib_socket_socket" >&6
+if test $ac_cv_lib_socket_socket = yes; then
+  LIBS="$LIBS -lsocket"
+fi
+
+  fi
+
+    if test -z "$libinet"; then
+    echo "$as_me:$LINENO: checking for socket in -linet" >&5
+echo $ECHO_N "checking for socket in -linet... $ECHO_C" >&6
+if test "${ac_cv_lib_inet_socket+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-linet  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char socket ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+socket ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_inet_socket=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_inet_socket=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_inet_socket" >&5
+echo "${ECHO_T}$ac_cv_lib_inet_socket" >&6
+if test $ac_cv_lib_inet_socket = yes; then
+  libnsl=1; LIBS="$LIBS -linet -lnsl_s"
+fi
+
+  fi
+
+  if test -z "$libnsl"; then
+    echo "$as_me:$LINENO: checking for gethostname in -lnsl" >&5
+echo $ECHO_N "checking for gethostname in -lnsl... $ECHO_C" >&6
+if test "${ac_cv_lib_nsl_gethostname+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnsl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char gethostname ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+gethostname ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_nsl_gethostname=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_nsl_gethostname=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostname" >&5
+echo "${ECHO_T}$ac_cv_lib_nsl_gethostname" >&6
+if test $ac_cv_lib_nsl_gethostname = yes; then
+  LIBS="$LIBS -lnsl"
+fi
+
+  fi
+fi
+
+echo "$as_me:$LINENO: checking for getpwnam in -lsun" >&5
+echo $ECHO_N "checking for getpwnam in -lsun... $ECHO_C" >&6
+if test "${ac_cv_lib_sun_getpwnam+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsun  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char getpwnam ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+getpwnam ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_sun_getpwnam=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_sun_getpwnam=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_sun_getpwnam" >&5
+echo "${ECHO_T}$ac_cv_lib_sun_getpwnam" >&6
+if test $ac_cv_lib_sun_getpwnam = yes; then
+  LIBS="$LIBS -lsun"
+fi
+
+echo "$as_me:$LINENO: checking for inet_addr in -ldgc" >&5
+echo $ECHO_N "checking for inet_addr in -ldgc... $ECHO_C" >&6
+if test "${ac_cv_lib_dgc_inet_addr+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldgc  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char inet_addr ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+inet_addr ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_dgc_inet_addr=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_dgc_inet_addr=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dgc_inet_addr" >&5
+echo "${ECHO_T}$ac_cv_lib_dgc_inet_addr" >&6
+if test $ac_cv_lib_dgc_inet_addr = yes; then
+  LIBS="$LIBS -ldgc"
+fi
+
+echo "$as_me:$LINENO: checking for gethostbyname in -lresolv" >&5
+echo $ECHO_N "checking for gethostbyname in -lresolv... $ECHO_C" >&6
+if test "${ac_cv_lib_resolv_gethostbyname+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lresolv  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char gethostbyname ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+gethostbyname ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_resolv_gethostbyname=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_resolv_gethostbyname=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_resolv_gethostbyname" >&5
+echo "${ECHO_T}$ac_cv_lib_resolv_gethostbyname" >&6
+if test $ac_cv_lib_resolv_gethostbyname = yes; then
+  LIBS="$LIBS -lresolv"
+fi
+
+
+OPSYSTEM=`uname -s`
+
+if test $OPSYSTEM = "Darwin"; then
+	DW_SRC=mac
+        DW_DEFINE=__MAC__
+	SHAREDFLAG=-dynamiclib
+	SOSUFFIX=dylib
+	LIBS="$LIBS -framework Carbon"
+else
+	# Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_PKG_CFG+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$PKG_CFG"; then
+  ac_cv_prog_PKG_CFG="$PKG_CFG" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_PKG_CFG="pkg-config"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+PKG_CFG=$ac_cv_prog_PKG_CFG
+if test -n "$PKG_CFG"; then
+  echo "$as_me:$LINENO: result: $PKG_CFG" >&5
+echo "${ECHO_T}$PKG_CFG" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+	if test x"$PKG_CFG" != x; then
+	  GTK_LIBS=`$PKG_CFG --silence-errors --libs gtk+-2.0 gthread-2.0`
+	fi
+
+	if test x"$GTK_LIBS" = x; then
+
+# Check whether --with-glib-prefix or --without-glib-prefix was given.
+if test "${with_glib_prefix+set}" = set; then
+  withval="$with_glib_prefix"
+  glib_config_prefix="$withval"
+else
+  glib_config_prefix=""
+fi;
+
+# Check whether --with-glib-exec-prefix or --without-glib-exec-prefix was given.
+if test "${with_glib_exec_prefix+set}" = set; then
+  withval="$with_glib_exec_prefix"
+  glib_config_exec_prefix="$withval"
+else
+  glib_config_exec_prefix=""
+fi;
+# Check whether --enable-glibtest or --disable-glibtest was given.
+if test "${enable_glibtest+set}" = set; then
+  enableval="$enable_glibtest"
+
+else
+  enable_glibtest=yes
+fi;
+
+  if test x$glib_config_exec_prefix != x ; then
+     glib_config_args="$glib_config_args --exec-prefix=$glib_config_exec_prefix"
+     if test x${GLIB_CONFIG+set} != xset ; then
+        GLIB_CONFIG=$glib_config_exec_prefix/bin/glib-config
+     fi
+  fi
+  if test x$glib_config_prefix != x ; then
+     glib_config_args="$glib_config_args --prefix=$glib_config_prefix"
+     if test x${GLIB_CONFIG+set} != xset ; then
+        GLIB_CONFIG=$glib_config_prefix/bin/glib-config
+     fi
+  fi
+
+  for module in .
+  do
+      case "$module" in
+         gmodule)
+             glib_config_args="$glib_config_args gmodule"
+         ;;
+         gthread)
+             glib_config_args="$glib_config_args gthread"
+         ;;
+      esac
+  done
+
+  # Extract the first word of "glib-config", so it can be a program name with args.
+set dummy glib-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_GLIB_CONFIG+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $GLIB_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_GLIB_CONFIG="$GLIB_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_GLIB_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_path_GLIB_CONFIG" && ac_cv_path_GLIB_CONFIG="no"
+  ;;
+esac
+fi
+GLIB_CONFIG=$ac_cv_path_GLIB_CONFIG
+
+if test -n "$GLIB_CONFIG"; then
+  echo "$as_me:$LINENO: result: $GLIB_CONFIG" >&5
+echo "${ECHO_T}$GLIB_CONFIG" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  min_glib_version=1.2.0
+  echo "$as_me:$LINENO: checking for GLIB - version >= $min_glib_version" >&5
+echo $ECHO_N "checking for GLIB - version >= $min_glib_version... $ECHO_C" >&6
+  no_glib=""
+  if test "$GLIB_CONFIG" = "no" ; then
+    no_glib=yes
+  else
+    GLIB_CFLAGS=`$GLIB_CONFIG $glib_config_args --cflags`
+    GLIB_LIBS=`$GLIB_CONFIG $glib_config_args --libs`
+    glib_config_major_version=`$GLIB_CONFIG $glib_config_args --version | \
+           sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'`
+    glib_config_minor_version=`$GLIB_CONFIG $glib_config_args --version | \
+           sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'`
+    glib_config_micro_version=`$GLIB_CONFIG $glib_config_args --version | \
+           sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'`
+    if test "x$enable_glibtest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $GLIB_CFLAGS"
+      LIBS="$GLIB_LIBS $LIBS"
+      rm -f conf.glibtest
+      if test "$cross_compiling" = yes; then
+  echo $ac_n "cross compiling; assumed OK... $ac_c"
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.glibtest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_glib_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_glib_version");
+     exit(1);
+   }
+
+  if ((glib_major_version != $glib_config_major_version) ||
+      (glib_minor_version != $glib_config_minor_version) ||
+      (glib_micro_version != $glib_config_micro_version))
+    {
+      printf("\n*** 'glib-config --version' returned %d.%d.%d, but GLIB (%d.%d.%d)\n",
+             $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version,
+             glib_major_version, glib_minor_version, glib_micro_version);
+      printf ("*** was found! If glib-config was correct, then it is best\n");
+      printf ("*** to remove the old version of GLIB. You may also be able to fix the error\n");
+      printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+      printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+      printf("*** required on your system.\n");
+      printf("*** If glib-config was wrong, set the environment variable GLIB_CONFIG\n");
+      printf("*** to point to the correct copy of glib-config, and remove the file config.cache\n");
+      printf("*** before re-running configure\n");
+    }
+  else if ((glib_major_version != GLIB_MAJOR_VERSION) ||
+	   (glib_minor_version != GLIB_MINOR_VERSION) ||
+           (glib_micro_version != GLIB_MICRO_VERSION))
+    {
+      printf("*** GLIB header files (version %d.%d.%d) do not match\n",
+	     GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
+      printf("*** library (version %d.%d.%d)\n",
+	     glib_major_version, glib_minor_version, glib_micro_version);
+    }
+  else
+    {
+      if ((glib_major_version > major) ||
+        ((glib_major_version == major) && (glib_minor_version > minor)) ||
+        ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro)))
+      {
+        return 0;
+       }
+     else
+      {
+        printf("\n*** An old version of GLIB (%d.%d.%d) was found.\n",
+               glib_major_version, glib_minor_version, glib_micro_version);
+        printf("*** You need a version of GLIB newer than %d.%d.%d. The latest version of\n",
+	       major, minor, micro);
+        printf("*** GLIB is always available from ftp://ftp.gtk.org.\n");
+        printf("***\n");
+        printf("*** If you have already installed a sufficiently new version, this error\n");
+        printf("*** probably means that the wrong copy of the glib-config shell script is\n");
+        printf("*** being found. The easiest way to fix this is to remove the old version\n");
+        printf("*** of GLIB, but you can also set the GLIB_CONFIG environment to point to the\n");
+        printf("*** correct copy of glib-config. (In this case, you will have to\n");
+        printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+        printf("*** so that the correct libraries are found at run-time))\n");
+      }
+    }
+  return 1;
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+( exit $ac_status )
+no_glib=yes
+fi
+rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_glib" = x ; then
+     echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+     :
+  else
+     echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+     if test "$GLIB_CONFIG" = "no" ; then
+       echo "*** The glib-config script installed by GLIB could not be found"
+       echo "*** If GLIB was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the GLIB_CONFIG environment variable to the"
+       echo "*** full path to glib-config."
+     else
+       if test -f conf.glibtest ; then
+        :
+       else
+          echo "*** Could not run GLIB test program, checking why..."
+          CFLAGS="$CFLAGS $GLIB_CFLAGS"
+          LIBS="$LIBS $GLIB_LIBS"
+          cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#include <glib.h>
+#include <stdio.h>
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+ return ((glib_major_version) || (glib_minor_version) || (glib_micro_version));
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+   echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding GLIB or finding the wrong"
+          echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means GLIB was incorrectly installed"
+          echo "*** or that you have moved GLIB since it was installed. In the latter case, you"
+          echo "*** may want to edit the glib-config script: $GLIB_CONFIG"
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     GLIB_CFLAGS=""
+     GLIB_LIBS=""
+     { { echo "$as_me:$LINENO: error: { { echo \"$as_me:$LINENO: error: Cannot find GLIB: Is glib-config in path?\" >&5
+echo \"$as_me: error: Cannot find GLIB: Is glib-config in path?\" >&2;}
+   { (exit 1); exit 1; }; }" >&5
+echo "$as_me: error: { { echo \"$as_me:$LINENO: error: Cannot find GLIB: Is glib-config in path?\" >&5
+echo \"$as_me: error: Cannot find GLIB: Is glib-config in path?\" >&2;}
+   { (exit 1); exit 1; }; }" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+
+
+  rm -f conf.glibtest
+
+
+# Check whether --with-gtk-prefix or --without-gtk-prefix was given.
+if test "${with_gtk_prefix+set}" = set; then
+  withval="$with_gtk_prefix"
+  gtk_config_prefix="$withval"
+else
+  gtk_config_prefix=""
+fi;
+
+# Check whether --with-gtk-exec-prefix or --without-gtk-exec-prefix was given.
+if test "${with_gtk_exec_prefix+set}" = set; then
+  withval="$with_gtk_exec_prefix"
+  gtk_config_exec_prefix="$withval"
+else
+  gtk_config_exec_prefix=""
+fi;
+# Check whether --enable-gtktest or --disable-gtktest was given.
+if test "${enable_gtktest+set}" = set; then
+  enableval="$enable_gtktest"
+
+else
+  enable_gtktest=yes
+fi;
+
+  for module in . gthread
+  do
+      case "$module" in
+         gthread)
+             gtk_config_args="$gtk_config_args gthread"
+         ;;
+      esac
+  done
+
+  if test x$gtk_config_exec_prefix != x ; then
+     gtk_config_args="$gtk_config_args --exec-prefix=$gtk_config_exec_prefix"
+     if test x${GTK_CONFIG+set} != xset ; then
+        GTK_CONFIG=$gtk_config_exec_prefix/bin/gtk-config
+     fi
+  fi
+  if test x$gtk_config_prefix != x ; then
+     gtk_config_args="$gtk_config_args --prefix=$gtk_config_prefix"
+     if test x${GTK_CONFIG+set} != xset ; then
+        GTK_CONFIG=$gtk_config_prefix/bin/gtk-config
+     fi
+  fi
+
+  # Extract the first word of "gtk-config", so it can be a program name with args.
+set dummy gtk-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_GTK_CONFIG+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $GTK_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_GTK_CONFIG="$GTK_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_GTK_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_path_GTK_CONFIG" && ac_cv_path_GTK_CONFIG="no"
+  ;;
+esac
+fi
+GTK_CONFIG=$ac_cv_path_GTK_CONFIG
+
+if test -n "$GTK_CONFIG"; then
+  echo "$as_me:$LINENO: result: $GTK_CONFIG" >&5
+echo "${ECHO_T}$GTK_CONFIG" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  min_gtk_version=1.2.0
+  echo "$as_me:$LINENO: checking for GTK - version >= $min_gtk_version" >&5
+echo $ECHO_N "checking for GTK - version >= $min_gtk_version... $ECHO_C" >&6
+  no_gtk=""
+  if test "$GTK_CONFIG" = "no" ; then
+    no_gtk=yes
+  else
+    GTK_CFLAGS=`$GTK_CONFIG $gtk_config_args --cflags`
+    GTK_LIBS=`$GTK_CONFIG $gtk_config_args --libs`
+    gtk_config_major_version=`$GTK_CONFIG $gtk_config_args --version | \
+           sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'`
+    gtk_config_minor_version=`$GTK_CONFIG $gtk_config_args --version | \
+           sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'`
+    gtk_config_micro_version=`$GTK_CONFIG $gtk_config_args --version | \
+           sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'`
+    if test "x$enable_gtktest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $GTK_CFLAGS"
+      LIBS="$GTK_LIBS $LIBS"
+      rm -f conf.gtktest
+      if test "$cross_compiling" = yes; then
+  echo $ac_n "cross compiling; assumed OK... $ac_c"
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.gtktest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_gtk_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_gtk_version");
+     exit(1);
+   }
+
+  if ((gtk_major_version != $gtk_config_major_version) ||
+      (gtk_minor_version != $gtk_config_minor_version) ||
+      (gtk_micro_version != $gtk_config_micro_version))
+    {
+      printf("\n*** 'gtk-config --version' returned %d.%d.%d, but GTK+ (%d.%d.%d)\n",
+             $gtk_config_major_version, $gtk_config_minor_version, $gtk_config_micro_version,
+             gtk_major_version, gtk_minor_version, gtk_micro_version);
+      printf ("*** was found! If gtk-config was correct, then it is best\n");
+      printf ("*** to remove the old version of GTK+. You may also be able to fix the error\n");
+      printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+      printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+      printf("*** required on your system.\n");
+      printf("*** If gtk-config was wrong, set the environment variable GTK_CONFIG\n");
+      printf("*** to point to the correct copy of gtk-config, and remove the file config.cache\n");
+      printf("*** before re-running configure\n");
+    }
+#if defined (GTK_MAJOR_VERSION) && defined (GTK_MINOR_VERSION) && defined (GTK_MICRO_VERSION)
+  else if ((gtk_major_version != GTK_MAJOR_VERSION) ||
+	   (gtk_minor_version != GTK_MINOR_VERSION) ||
+           (gtk_micro_version != GTK_MICRO_VERSION))
+    {
+      printf("*** GTK+ header files (version %d.%d.%d) do not match\n",
+	     GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
+      printf("*** library (version %d.%d.%d)\n",
+	     gtk_major_version, gtk_minor_version, gtk_micro_version);
+    }
+#endif /* defined (GTK_MAJOR_VERSION) ... */
+  else
+    {
+      if ((gtk_major_version > major) ||
+        ((gtk_major_version == major) && (gtk_minor_version > minor)) ||
+        ((gtk_major_version == major) && (gtk_minor_version == minor) && (gtk_micro_version >= micro)))
+      {
+        return 0;
+       }
+     else
+      {
+        printf("\n*** An old version of GTK+ (%d.%d.%d) was found.\n",
+               gtk_major_version, gtk_minor_version, gtk_micro_version);
+        printf("*** You need a version of GTK+ newer than %d.%d.%d. The latest version of\n",
+	       major, minor, micro);
+        printf("*** GTK+ is always available from ftp://ftp.gtk.org.\n");
+        printf("***\n");
+        printf("*** If you have already installed a sufficiently new version, this error\n");
+        printf("*** probably means that the wrong copy of the gtk-config shell script is\n");
+        printf("*** being found. The easiest way to fix this is to remove the old version\n");
+        printf("*** of GTK+, but you can also set the GTK_CONFIG environment to point to the\n");
+        printf("*** correct copy of gtk-config. (In this case, you will have to\n");
+        printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+        printf("*** so that the correct libraries are found at run-time))\n");
+      }
+    }
+  return 1;
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+( exit $ac_status )
+no_gtk=yes
+fi
+rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_gtk" = x ; then
+     echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+     :
+  else
+     echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+     if test "$GTK_CONFIG" = "no" ; then
+       echo "*** The gtk-config script installed by GTK could not be found"
+       echo "*** If GTK was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the GTK_CONFIG environment variable to the"
+       echo "*** full path to gtk-config."
+     else
+       if test -f conf.gtktest ; then
+        :
+       else
+          echo "*** Could not run GTK test program, checking why..."
+          CFLAGS="$CFLAGS $GTK_CFLAGS"
+          LIBS="$LIBS $GTK_LIBS"
+          cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+ return ((gtk_major_version) || (gtk_minor_version) || (gtk_micro_version));
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+   echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding GTK or finding the wrong"
+          echo "*** version of GTK. If it is not finding GTK, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means GTK was incorrectly installed"
+          echo "*** or that you have moved GTK since it was installed. In the latter case, you"
+          echo "*** may want to edit the gtk-config script: $GTK_CONFIG"
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     GTK_CFLAGS=""
+     GTK_LIBS=""
+     { { echo "$as_me:$LINENO: error: { { echo \"$as_me:$LINENO: error: Cannot find GTK: Is gtk-config in path?\" >&5
+echo \"$as_me: error: Cannot find GTK: Is gtk-config in path?\" >&2;}
+   { (exit 1); exit 1; }; }" >&5
+echo "$as_me: error: { { echo \"$as_me:$LINENO: error: Cannot find GTK: Is gtk-config in path?\" >&5
+echo \"$as_me: error: Cannot find GTK: Is gtk-config in path?\" >&2;}
+   { (exit 1); exit 1; }; }" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+
+
+  rm -f conf.gtktest
+
+
+# Check whether --with-imlib-prefix or --without-imlib-prefix was given.
+if test "${with_imlib_prefix+set}" = set; then
+  withval="$with_imlib_prefix"
+  imlib_prefix="$withval"
+else
+  imlib_prefix=""
+fi;
+
+# Check whether --with-imlib-exec-prefix or --without-imlib-exec-prefix was given.
+if test "${with_imlib_exec_prefix+set}" = set; then
+  withval="$with_imlib_exec_prefix"
+  imlib_exec_prefix="$withval"
+else
+  imlib_exec_prefix=""
+fi;
+# Check whether --enable-imlibtest or --disable-imlibtest was given.
+if test "${enable_imlibtest+set}" = set; then
+  enableval="$enable_imlibtest"
+
+else
+  enable_imlibtest=yes
+fi;
+
+  if test x$imlib_exec_prefix != x ; then
+     imlib_args="$imlib_args --exec-prefix=$imlib_exec_prefix"
+     if test x${IMLIB_CONFIG+set} != xset ; then
+        IMLIB_CONFIG=$imlib_exec_prefix/bin/imlib-config
+     fi
+  fi
+  if test x$imlib_prefix != x ; then
+     imlib_args="$imlib_args --prefix=$imlib_prefix"
+     if test x${IMLIB_CONFIG+set} != xset ; then
+        IMLIB_CONFIG=$imlib_prefix/bin/imlib-config
+     fi
+  fi
+
+  # Extract the first word of "imlib-config", so it can be a program name with args.
+set dummy imlib-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_IMLIB_CONFIG+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $IMLIB_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_IMLIB_CONFIG="$IMLIB_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_IMLIB_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_path_IMLIB_CONFIG" && ac_cv_path_IMLIB_CONFIG="no"
+  ;;
+esac
+fi
+IMLIB_CONFIG=$ac_cv_path_IMLIB_CONFIG
+
+if test -n "$IMLIB_CONFIG"; then
+  echo "$as_me:$LINENO: result: $IMLIB_CONFIG" >&5
+echo "${ECHO_T}$IMLIB_CONFIG" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  min_imlib_version=1.9.4
+  echo "$as_me:$LINENO: checking for IMLIB - version >= $min_imlib_version" >&5
+echo $ECHO_N "checking for IMLIB - version >= $min_imlib_version... $ECHO_C" >&6
+  no_imlib=""
+  if test "$IMLIB_CONFIG" = "no" ; then
+    no_imlib=yes
+  else
+    GDK_IMLIB_CFLAGS=`$IMLIB_CONFIG $imlibconf_args --cflags-gdk`
+    GDK_IMLIB_LIBS=`$IMLIB_CONFIG $imlibconf_args --libs-gdk`
+
+    imlib_major_version=`$IMLIB_CONFIG $imlib_args --version | \
+           sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'`
+    imlib_minor_version=`$IMLIB_CONFIG $imlib_args --version | \
+           sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'`
+    imlib_micro_version=`$IMLIB_CONFIG $imlib_args --version | \
+           sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'`
+    if test "x$enable_imlibtest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $GDK_IMLIB_CFLAGS"
+      LIBS="$LIBS $GDK_IMLIB_LIBS"
+      rm -f conf.imlibtest
+      if test "$cross_compiling" = yes; then
+  echo $ac_n "cross compiling; assumed OK... $ac_c"
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <gdk_imlib.h>
+
+int main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.gdkimlibtest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_imlib_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_imlib_version");
+     exit(1);
+   }
+
+    if (($imlib_major_version > major) ||
+        (($imlib_major_version == major) && ($imlib_minor_version > minor)) ||
+	(($imlib_major_version == major) && ($imlib_minor_version == minor) &&
+	($imlib_micro_version >= micro)))
+    {
+      return 0;
+    }
+  else
+    {
+      printf("\n*** 'imlib-config --version' returned %d.%d.%d, but the minimum version\n", $imlib_major_version, $imlib_minor_version, $imlib_micro_version);
+      printf("*** of IMLIB required is %d.%d.%d. If imlib-config is correct, then it is\n", major, minor, micro);
+      printf("*** best to upgrade to the required version.\n");
+      printf("*** If imlib-config was wrong, set the environment variable IMLIB_CONFIG\n");
+      printf("*** to point to the correct copy of imlib-config, and remove the file\n");
+      printf("*** config.cache before re-running configure\n");
+      return 1;
+    }
+}
+
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+( exit $ac_status )
+no_imlib=yes
+fi
+rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_imlib" = x ; then
+     echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+     cat >>confdefs.h <<\_ACEOF
+#define USE_IMLIB 1
+_ACEOF
+
+  else
+     echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+     if test "$IMLIB_CONFIG" = "no" ; then
+       echo "*** The imlib-config script installed by IMLIB could not be found"
+       echo "*** If IMLIB was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the IMLIB_CONFIG environment variable to the"
+       echo "*** full path to imlib-config."
+     else
+       if test -f conf.gdkimlibtest ; then
+        :
+       else
+          echo "*** Could not run IMLIB test program, checking why..."
+          CFLAGS="$CFLAGS $GDK_IMLIB_CFLAGS"
+          LIBS="$LIBS $GDK_IMLIB_LIBS"
+          cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#include <stdio.h>
+#include <gdk_imlib.h>
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+ return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+   echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding IMLIB or finding the wrong"
+          echo "*** version of IMLIB. If it is not finding IMLIB, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means IMLIB was incorrectly installed"
+          echo "*** or that you have moved IMLIB since it was installed. In the latter case, you"
+          echo "*** may want to edit the imlib-config script: $IMLIB_CONFIG"
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     GDK_IMLIB_CFLAGS=""
+     GDK_IMLIB_LIBS=""
+     { { echo "$as_me:$LINENO: error: IMLIB not found or too old. Dynamic Windows cannot build without it." >&5
+echo "$as_me: error: IMLIB not found or too old. Dynamic Windows cannot build without it." >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+
+
+  rm -f conf.gdkimlibtest
+
+	else
+	  GTK_CFLAGS=`$PKG_CFG --cflags gtk+-2.0 gthread-2.0`
+	  GTK_LIBS=`$PKG_CFG --libs gtk+-2.0 gthread-2.0`
+	fi
+fi
+
+if test "${ac_cv_header_pthread_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for pthread.h" >&5
+echo $ECHO_N "checking for pthread.h... $ECHO_C" >&6
+if test "${ac_cv_header_pthread_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_pthread_h" >&5
+echo "${ECHO_T}$ac_cv_header_pthread_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking pthread.h usability" >&5
+echo $ECHO_N "checking pthread.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+#include <pthread.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_header_compiler=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking pthread.h presence" >&5
+echo $ECHO_N "checking pthread.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <pthread.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc in
+  yes:no )
+    { echo "$as_me:$LINENO: WARNING: pthread.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: pthread.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: pthread.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: pthread.h: proceeding with the preprocessor's result" >&2;};;
+  no:yes )
+    { echo "$as_me:$LINENO: WARNING: pthread.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: pthread.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: pthread.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: pthread.h: check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: pthread.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: pthread.h: proceeding with the preprocessor's result" >&2;};;
+esac
+echo "$as_me:$LINENO: checking for pthread.h" >&5
+echo $ECHO_N "checking for pthread.h... $ECHO_C" >&6
+if test "${ac_cv_header_pthread_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_pthread_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_pthread_h" >&5
+echo "${ECHO_T}$ac_cv_header_pthread_h" >&6
+
+fi
+if test $ac_cv_header_pthread_h = yes; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: pthread header not found. Dynamic Windows cannot build without it." >&5
+echo "$as_me: error: pthread header not found. Dynamic Windows cannot build without it." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+echo "$as_me:$LINENO: checking for pthread_attr_init in -lpthread" >&5
+echo $ECHO_N "checking for pthread_attr_init in -lpthread... $ECHO_C" >&6
+if test "${ac_cv_lib_pthread_pthread_attr_init+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char pthread_attr_init ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+pthread_attr_init ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_pthread_pthread_attr_init=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_pthread_pthread_attr_init=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_attr_init" >&5
+echo "${ECHO_T}$ac_cv_lib_pthread_pthread_attr_init" >&6
+if test $ac_cv_lib_pthread_pthread_attr_init = yes; then
+  PTHREAD_LIBS="-lpthread"
+else
+  echo "$as_me:$LINENO: checking for pthread_attr_init in -lpthreads" >&5
+echo $ECHO_N "checking for pthread_attr_init in -lpthreads... $ECHO_C" >&6
+if test "${ac_cv_lib_pthreads_pthread_attr_init+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthreads  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char pthread_attr_init ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+pthread_attr_init ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_pthreads_pthread_attr_init=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_pthreads_pthread_attr_init=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_pthreads_pthread_attr_init" >&5
+echo "${ECHO_T}$ac_cv_lib_pthreads_pthread_attr_init" >&6
+if test $ac_cv_lib_pthreads_pthread_attr_init = yes; then
+  PTHREAD_LIBS="-lpthreads"
+else
+  echo "$as_me:$LINENO: checking for pthread_attr_init in -lc_r" >&5
+echo $ECHO_N "checking for pthread_attr_init in -lc_r... $ECHO_C" >&6
+if test "${ac_cv_lib_c_r_pthread_attr_init+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc_r  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char pthread_attr_init ();
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+pthread_attr_init ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_c_r_pthread_attr_init=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_c_r_pthread_attr_init=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_c_r_pthread_attr_init" >&5
+echo "${ECHO_T}$ac_cv_lib_c_r_pthread_attr_init" >&6
+if test $ac_cv_lib_c_r_pthread_attr_init = yes; then
+  PTHREAD_LIBS="-lc_r"
+else
+  { { echo "$as_me:$LINENO: error: pthread library not found. HandyFTP cannot build without it.
+      " >&5
+echo "$as_me: error: pthread library not found. HandyFTP cannot build without it.
+      " >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+
+
+fi
+
+
+fi
+
+
+CFLAGS="$CFLAGS $GTK_CFLAGS $GDK_IMLIB_FLAGS"
+LIBS="$LIBS $GTK_LIBS $PTHREAD_LIBS $GDK_IMLIB_LIBS"
+
+RM="rm -f"
+LN="ln -s"
+CP="cp"
+MV="mv"
+MKDIR="mkdir"
+
+
+
+
+
+
+
+
+
+ac_config_files="$ac_config_files Makefile sfxace/Makefile sfxzip/Makefile packace/Makefile packzip/Makefile uninst/Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overriden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+  (set) 2>&1 |
+    case `(ac_space=' '; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+        "s/'/'\\\\''/g;
+    	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;;
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n \
+        "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+} |
+  sed '
+     t clear
+     : clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     : end' >>confcache
+if cmp -s $cache_file confcache; then :; else
+  if test -w $cache_file; then
+    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+    cat confcache >$cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[ 	]*VPATH[ 	]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[ 	]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[ 	]*$//;
+}'
+fi
+
+DEFS=-DHAVE_CONFIG_H
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+
+# NLS nuisances.
+# Support unset when possible.
+if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+(set +x; test -n "`(LANG=C; export LANG) 2>&1`") &&
+    { $as_unset LANG || test "${LANG+set}" != set; } ||
+      { LANG=C; export LANG; }
+(set +x; test -n "`(LC_ALL=C; export LC_ALL) 2>&1`") &&
+    { $as_unset LC_ALL || test "${LC_ALL+set}" != set; } ||
+      { LC_ALL=C; export LC_ALL; }
+(set +x; test -n "`(LC_TIME=C; export LC_TIME) 2>&1`") &&
+    { $as_unset LC_TIME || test "${LC_TIME+set}" != set; } ||
+      { LC_TIME=C; export LC_TIME; }
+(set +x; test -n "`(LC_CTYPE=C; export LC_CTYPE) 2>&1`") &&
+    { $as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set; } ||
+      { LC_CTYPE=C; export LC_CTYPE; }
+(set +x; test -n "`(LANGUAGE=C; export LANGUAGE) 2>&1`") &&
+    { $as_unset LANGUAGE || test "${LANGUAGE+set}" != set; } ||
+      { LANGUAGE=C; export LANGUAGE; }
+(set +x; test -n "`(LC_COLLATE=C; export LC_COLLATE) 2>&1`") &&
+    { $as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set; } ||
+      { LC_COLLATE=C; export LC_COLLATE; }
+(set +x; test -n "`(LC_NUMERIC=C; export LC_NUMERIC) 2>&1`") &&
+    { $as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set; } ||
+      { LC_NUMERIC=C; export LC_NUMERIC; }
+(set +x; test -n "`(LC_MESSAGES=C; export LC_MESSAGES) 2>&1`") &&
+    { $as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set; } ||
+      { LC_MESSAGES=C; export LC_MESSAGES; }
+
+
+# Name of the executable.
+as_me=`(basename "$0") 2>/dev/null ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)$' \| \
+	 .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+  	  /^X\/\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\/\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conftest.sh
+  echo  "exit 0"   >>conftest.sh
+  chmod +x conftest.sh
+  if (PATH=".;."; conftest.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conftest.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+	 case $as_dir in
+	 /*)
+	   if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+	     CONFIG_SHELL=$as_dir/$as_base
+	     export CONFIG_SHELL
+	     exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+	   fi;;
+	 esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='	' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; }
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.  Logging --version etc. is OK.
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.53.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number, then exit
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+  --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.53,
+  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+INSTALL="$INSTALL"
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "x$1" : 'x\([^=]*\)='`
+    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+    shift
+    set dummy "$ac_option" "$ac_optarg" ${1+"$@"}
+    shift
+    ;;
+  -*);;
+  *) # This is not an option, so the user has probably given explicit
+     # arguments.
+     ac_need_defaults=false;;
+  esac
+
+  case $1 in
+  # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    echo "running $SHELL $0 " $ac_configure_args " --no-create --no-recursion"
+    exec $SHELL $0 $ac_configure_args --no-create --no-recursion ;;
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+  --version | --vers* | -V )
+    echo "$ac_cs_version"; exit 0 ;;
+  --he | --h)
+    # Conflict between --help and --header
+    { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit 0 ;;
+  --debug | --d* | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    shift
+    CONFIG_FILES="$CONFIG_FILES $1"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $1"
+    ac_need_defaults=false;;
+
+  # This is an error.
+  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1" ;;
+
+  esac
+  shift
+done
+
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+  case "$ac_config_target" in
+  # Handling of arguments.
+  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+  "sfxace/Makefile" ) CONFIG_FILES="$CONFIG_FILES sfxace/Makefile" ;;
+  "sfxzip/Makefile" ) CONFIG_FILES="$CONFIG_FILES sfxzip/Makefile" ;;
+  "packace/Makefile" ) CONFIG_FILES="$CONFIG_FILES packace/Makefile" ;;
+  "packzip/Makefile" ) CONFIG_FILES="$CONFIG_FILES packzip/Makefile" ;;
+  "uninst/Makefile" ) CONFIG_FILES="$CONFIG_FILES uninst/Makefile" ;;
+  "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+: ${TMPDIR=/tmp}
+{
+  tmp=`(umask 077 && mktemp -d -q "$TMPDIR/csXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=$TMPDIR/cs$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in $TMPDIR" >&2
+   { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+  # Protect against being on the right side of a sed subst in config.status.
+  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@MAKE@,$MAKE,;t t
+s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s,@INSTALL_DATA@,$INSTALL_DATA,;t t
+s,@CPP@,$CPP,;t t
+s,@PKG_CFG@,$PKG_CFG,;t t
+s,@GLIB_CONFIG@,$GLIB_CONFIG,;t t
+s,@GLIB_CFLAGS@,$GLIB_CFLAGS,;t t
+s,@GLIB_LIBS@,$GLIB_LIBS,;t t
+s,@GTK_CONFIG@,$GTK_CONFIG,;t t
+s,@GTK_CFLAGS@,$GTK_CFLAGS,;t t
+s,@GTK_LIBS@,$GTK_LIBS,;t t
+s,@IMLIB_CONFIG@,$IMLIB_CONFIG,;t t
+s,@GDK_IMLIB_CFLAGS@,$GDK_IMLIB_CFLAGS,;t t
+s,@GDK_IMLIB_LIBS@,$GDK_IMLIB_LIBS,;t t
+s,@INCLUDES@,$INCLUDES,;t t
+s,@RM@,$RM,;t t
+s,@LN@,$LN,;t t
+s,@CP@,$CP,;t t
+s,@MV@,$MV,;t t
+s,@MKDIR@,$MKDIR,;t t
+CEOF
+
+_ACEOF
+
+  cat >>$CONFIG_STATUS <<\_ACEOF
+  # Split the substitutions into bite-sized pieces for seds with
+  # small command number limits, like on Digital OSF/1 and HP-UX.
+  ac_max_sed_lines=48
+  ac_sed_frag=1 # Number of current file.
+  ac_beg=1 # First line for current file.
+  ac_end=$ac_max_sed_lines # Line after last line for current file.
+  ac_more_lines=:
+  ac_sed_cmds=
+  while $ac_more_lines; do
+    if test $ac_beg -gt 1; then
+      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    else
+      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    fi
+    if test ! -s $tmp/subs.frag; then
+      ac_more_lines=false
+    else
+      # The purpose of the label and of the branching condition is to
+      # speed up the sed processing (if there are no `@' at all, there
+      # is no need to browse any of the substitutions).
+      # These are the two extra sed commands mentioned above.
+      (echo ':t
+  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+      if test -z "$ac_sed_cmds"; then
+  	ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+      else
+  	ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+      fi
+      ac_sed_frag=`expr $ac_sed_frag + 1`
+      ac_beg=$ac_end
+      ac_end=`expr $ac_end + $ac_max_sed_lines`
+    fi
+  done
+  if test -z "$ac_sed_cmds"; then
+    ac_sed_cmds=cat
+  fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+        cat >$tmp/stdin
+        ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+        ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+        ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+         X"$ac_file" : 'X\(//\)[^/]' \| \
+         X"$ac_file" : 'X\(//\)$' \| \
+         X"$ac_file" : 'X\(/\)' \| \
+         .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+  { case "$ac_dir" in
+  [\\/]* | ?:[\\/]* ) as_incr_dir=;;
+  *)                      as_incr_dir=.;;
+esac
+as_dummy="$ac_dir"
+for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do
+  case $as_mkdir_dir in
+    # Skip DOS drivespec
+    ?:) as_incr_dir=$as_mkdir_dir ;;
+    *)
+      as_incr_dir=$as_incr_dir/$as_mkdir_dir
+      test -d "$as_incr_dir" ||
+        mkdir "$as_incr_dir" ||
+	{ { echo "$as_me:$LINENO: error: cannot create \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }
+    ;;
+  esac
+done; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+# absolute.
+ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+ac_abs_top_builddir=`cd "$ac_dir" && cd $ac_top_builddir && pwd`
+ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
+
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+  esac
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    configure_input=
+  else
+    configure_input="$ac_file.  "
+  fi
+  configure_input=$configure_input"Generated from `echo $ac_file_in |
+                                     sed 's,.*/,,'` by configure."
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+         # Absolute (can't be DOS-style, as IFS=:)
+         test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+         echo $f;;
+      *) # Relative
+         if test -f "$f"; then
+           # Build tree
+           echo $f
+         elif test -f "$srcdir/$f"; then
+           # Source tree
+           echo $srcdir/$f
+         else
+           # /dev/null tree
+           { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+         fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+s,@INSTALL@,$ac_INSTALL,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+  rm -f $tmp/stdin
+  if test x"$ac_file" != x-; then
+    mv $tmp/out $ac_file
+  else
+    cat $tmp/out
+    rm -f $tmp/out
+  fi
+
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([ 	]*\)#\([ 	]*define[ 	][ 	]*\)'
+ac_dB='[ 	].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([ 	]*\)#\([ 	]*\)undef\([ 	][ 	]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+        cat >$tmp/stdin
+        ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+        ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+        ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+         # Absolute (can't be DOS-style, as IFS=:)
+         test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+         echo $f;;
+      *) # Relative
+         if test -f "$f"; then
+           # Build tree
+           echo $f
+         elif test -f "$srcdir/$f"; then
+           # Source tree
+           echo $srcdir/$f
+         else
+           # /dev/null tree
+           { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+         fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+  # Remove the trailing spaces.
+  sed 's/[ 	]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h.  The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status.  Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[ 	]*#[ 	]*define[ 	][ 	]*\([^ 	(][^ 	(]*\)\(([^)]*)\)[ 	]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[ 	]*#[ 	]*define[ 	][ 	]*\([^ 	][^ 	]*\)[ 	]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless.  Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >>conftest.undefs <<\_ACEOF
+s,^[ 	]*#[ 	]*undef[ 	][ 	]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo '  if egrep "^[ 	]*#[ 	]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo '  # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo '  :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+  # Write a limited-size here document to $tmp/defines.sed.
+  echo '  cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#define' lines.
+  echo '/^[ 	]*#[ 	]*define/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/defines.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+  rm -f conftest.defines
+  mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo '  fi # egrep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+  # Write a limited-size here document to $tmp/undefs.sed.
+  echo '  cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#undef'
+  echo '/^[ 	]*#[ 	]*undef/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+  rm -f conftest.undefs
+  mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    echo "/* Generated by configure.  */" >$tmp/config.h
+  else
+    echo "/* $ac_file.  Generated by configure.  */" >$tmp/config.h
+  fi
+  cat $tmp/in >>$tmp/config.h
+  rm -f $tmp/in
+  if test x"$ac_file" != x-; then
+    if cmp -s $ac_file $tmp/config.h 2>/dev/null; then
+      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+         X"$ac_file" : 'X\(//\)[^/]' \| \
+         X"$ac_file" : 'X\(//\)$' \| \
+         X"$ac_file" : 'X\(/\)' \| \
+         .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+  	  /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+  	  /^X\(\/\/\)$/{ s//\1/; q; }
+  	  /^X\(\/\).*/{ s//\1/; q; }
+  	  s/.*/./; q'`
+      { case "$ac_dir" in
+  [\\/]* | ?:[\\/]* ) as_incr_dir=;;
+  *)                      as_incr_dir=.;;
+esac
+as_dummy="$ac_dir"
+for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do
+  case $as_mkdir_dir in
+    # Skip DOS drivespec
+    ?:) as_incr_dir=$as_mkdir_dir ;;
+    *)
+      as_incr_dir=$as_incr_dir/$as_mkdir_dir
+      test -d "$as_incr_dir" ||
+        mkdir "$as_incr_dir" ||
+	{ { echo "$as_me:$LINENO: error: cannot create \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }
+    ;;
+  esac
+done; }
+
+      rm -f $ac_file
+      mv $tmp/config.h $ac_file
+    fi
+  else
+    cat $tmp/config.h
+    rm -f $tmp/config.h
+  fi
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/configure.in	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,102 @@
+AC_INIT(install.c)
+AC_CONFIG_HEADER(config.h)
+
+INCLUDES="-I."
+
+AC_PROG_CC
+
+AC_CHECK_PROG(MAKE, gmake, gmake)
+if test x"$MAKE" = x; then
+  AC_CHECK_PROG(MAKE, make, make)
+fi
+
+AC_PROG_INSTALL
+
+AC_SUBST(MAKE)
+
+AC_HEADER_STDC
+AC_HEADER_DIRENT
+AC_CHECK_HEADERS(unistd.h)
+AC_CHECK_HEADERS(sys/stat.h)
+
+AC_CHECK_FUNCS(pipe, AC_DEFINE(HAVE_PIPE,1,Determine whether we have the pipe function))                      
+
+AC_CHECK_FUNCS(connect)
+if test x"$ac_cv_func_connect" = x"no"; then
+  if test -z "$libsocket"; then
+    AC_CHECK_LIB(socket, socket, LIBS="$LIBS -lsocket",)
+  fi
+
+  dnl this is for isc.  need the nsl_s library as well.
+  if test -z "$libinet"; then
+    AC_CHECK_LIB(inet, socket, libnsl=1; LIBS="$LIBS -linet -lnsl_s",)
+  fi
+
+  if test -z "$libnsl"; then
+    AC_CHECK_LIB(nsl, gethostname, LIBS="$LIBS -lnsl",)
+  fi
+fi
+
+AC_CHECK_LIB(sun, getpwnam, LIBS="$LIBS -lsun",)
+AC_CHECK_LIB(dgc, inet_addr, LIBS="$LIBS -ldgc",)
+AC_CHECK_LIB(resolv, gethostbyname, LIBS="$LIBS -lresolv",)
+
+OPSYSTEM=`uname -s`
+
+if test $OPSYSTEM = "Darwin"; then
+	DW_SRC=mac
+        DW_DEFINE=__MAC__
+	SHAREDFLAG=-dynamiclib
+	SOSUFFIX=dylib
+	LIBS="$LIBS -framework Carbon"
+else
+	AC_CHECK_PROG(PKG_CFG, pkg-config, pkg-config)
+	if test x"$PKG_CFG" != x; then
+	  GTK_LIBS=`$PKG_CFG --silence-errors --libs gtk+-2.0 gthread-2.0`
+	fi
+
+	if test x"$GTK_LIBS" = x; then
+	  AM_PATH_GLIB(1.2.0,,AC_MSG_ERROR(AC_MSG_ERROR(Cannot find GLIB: Is glib-config in path?)))
+	  AM_PATH_GTK(1.2.0,,AC_MSG_ERROR(AC_MSG_ERROR(Cannot find GTK: Is gtk-config in path?)), gthread)
+	  AM_PATH_GDK_IMLIB(1.9.4, AC_DEFINE(USE_IMLIB), AC_MSG_ERROR(IMLIB not found or too old. Dynamic Windows cannot build without it.))
+	else
+	  GTK_CFLAGS=`$PKG_CFG --cflags gtk+-2.0 gthread-2.0`
+	  GTK_LIBS=`$PKG_CFG --libs gtk+-2.0 gthread-2.0`
+	fi
+fi
+
+AC_CHECK_HEADER(pthread.h,,AC_MSG_ERROR([pthread header not found. Dynamic Windows cannot build without it.]))
+AC_CHECK_LIB(pthread, pthread_attr_init, PTHREAD_LIBS="-lpthread",
+AC_CHECK_LIB(pthreads, pthread_attr_init, PTHREAD_LIBS="-lpthreads",
+  AC_CHECK_LIB(c_r, pthread_attr_init, PTHREAD_LIBS="-lc_r",
+      AC_MSG_ERROR(pthread library not found. HandyFTP cannot build without it.
+      )
+    )
+  )
+)
+
+CFLAGS="$CFLAGS $GTK_CFLAGS $GDK_IMLIB_FLAGS"
+LIBS="$LIBS $GTK_LIBS $PTHREAD_LIBS $GDK_IMLIB_LIBS"
+
+RM="rm -f"
+LN="ln -s"
+CP="cp"
+MV="mv"
+MKDIR="mkdir"
+
+
+AC_SUBST(INCLUDES)
+AC_SUBST(RM)
+AC_SUBST(LN)
+AC_SUBST(CP)
+AC_SUBST(MV)
+AC_SUBST(MKDIR)
+
+AC_CONFIG_FILES([
+Makefile
+sfxace/Makefile
+sfxzip/Makefile
+packace/Makefile
+packzip/Makefile
+uninst/Makefile ])
+AC_OUTPUT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dw.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,1085 @@
+/* $Id: dw.h,v 1.33 2003/12/02 18:40:52 bsmith Exp $ */
+
+#ifndef _H_DW
+#define _H_DW
+
+/* Dynamic Windows version numbers */
+#define DW_MAJOR_VERSION 1
+#define DW_MINOR_VERSION 0
+#define DW_SUB_VERSION 0
+
+/* These corespond to the entries in the color
+ * arrays in the Win32 dw.c, they are also the
+ * same as DOS ANSI colors.
+ */
+#define DW_CLR_BLACK             0
+#define DW_CLR_DARKRED           1
+#define DW_CLR_DARKGREEN         2
+#define DW_CLR_BROWN             3
+#define DW_CLR_DARKBLUE          4
+#define DW_CLR_DARKPINK          5
+#define DW_CLR_DARKCYAN          6
+#define DW_CLR_PALEGRAY          7
+#define DW_CLR_DARKGRAY          8
+#define DW_CLR_RED               9
+#define DW_CLR_GREEN             10
+#define DW_CLR_YELLOW            11
+#define DW_CLR_BLUE              12
+#define DW_CLR_PINK              13
+#define DW_CLR_CYAN              14
+#define DW_CLR_WHITE             15
+#define DW_CLR_DEFAULT           16
+
+/* Signal handler defines */
+#define DW_SIGNAL_CONFIGURE      "configure_event"
+#define DW_SIGNAL_KEY_PRESS      "key_press_event"
+#define DW_SIGNAL_BUTTON_PRESS   "button_press_event"
+#define DW_SIGNAL_BUTTON_RELEASE "button_release_event"
+#define DW_SIGNAL_MOTION_NOTIFY  "motion_notify_event"
+#define DW_SIGNAL_DELETE         "delete_event"
+#define DW_SIGNAL_EXPOSE         "expose_event"
+#define DW_SIGNAL_CLICKED        "clicked"
+#define DW_SIGNAL_ITEM_ENTER     "container-select"
+#define DW_SIGNAL_ITEM_CONTEXT   "container-context"
+#define DW_SIGNAL_ITEM_SELECT    "tree-select"
+#define DW_SIGNAL_LIST_SELECT    "item-select"
+#define DW_SIGNAL_SET_FOCUS      "set-focus"
+#define DW_SIGNAL_VALUE_CHANGED  "value_changed"
+#define DW_SIGNAL_SWITCH_PAGE    "switch-page"
+#define DW_SIGNAL_COLUMN_CLICK   "click-column"
+#define DW_SIGNAL_TREE_EXPAND    "tree-expand"
+
+#if defined(__OS2__) || defined(__WIN32__) || defined(__MAC__) || defined(WINNT) || defined(__EMX__)
+/* OS/2, Windows or MacOS */
+
+#if defined(__IBMC__) && !defined(API)
+#define API _System
+#endif
+
+/* Used internally */
+#define TYPEBOX  0
+#define TYPEITEM 1
+
+#define SIZESTATIC 0
+#define SIZEEXPAND 1
+
+#define SPLITBAR_WIDTH 4
+#define BUBBLE_HELP_MAX 256
+
+typedef struct _user_data
+{
+	struct _user_data *next;
+	void              *data;
+	char              *varname;
+} UserData;
+
+/* OS/2 Specific section */
+#if defined(__OS2__) || defined(__EMX__)
+#define INCL_DOS
+#define INCL_WIN
+#define INCL_GPI
+
+#include <os2.h>
+
+#define DW_DT_LEFT               DT_LEFT
+#define DW_DT_QUERYEXTENT        DT_QUERYEXTENT
+#define DW_DT_UNDERSCORE         DT_UNDERSCORE
+#define DW_DT_STRIKEOUT          DT_STRIKEOUT
+#define DW_DT_TEXTATTRS          DT_TEXTATTRS
+#define DW_DT_EXTERNALLEADING    DT_EXTERNALLEADING
+#define DW_DT_CENTER             DT_CENTER
+#define DW_DT_RIGHT              DT_RIGHT
+#define DW_DT_TOP                DT_TOP
+#define DW_DT_VCENTER            DT_VCENTER
+#define DW_DT_BOTTOM             DT_BOTTOM
+#define DW_DT_HALFTONE           DT_HALFTONE
+#define DW_DT_MNEMONIC           DT_MNEMONIC
+#define DW_DT_WORDBREAK          DT_WORDBREAK
+#define DW_DT_ERASERECT          DT_ERASERECT
+
+#ifndef FCF_CLOSEBUTTON
+#define FCF_CLOSEBUTTON            0x04000000L
+#endif
+
+#define DW_FCF_TITLEBAR          FCF_TITLEBAR
+#define DW_FCF_SYSMENU           (FCF_SYSMENU | FCF_CLOSEBUTTON)
+#define DW_FCF_MENU              FCF_MENU
+#define DW_FCF_SIZEBORDER        FCF_SIZEBORDER
+#define DW_FCF_MINBUTTON         FCF_MINBUTTON
+#define DW_FCF_MAXBUTTON         FCF_MAXBUTTON
+#define DW_FCF_MINMAX            FCF_MINMAX
+#define DW_FCF_VERTSCROLL        FCF_VERTSCROLL
+#define DW_FCF_HORZSCROLL        FCF_HORZSCROLL
+#define DW_FCF_DLGBORDER         FCF_DLGBORDER
+#define DW_FCF_BORDER            FCF_BORDER
+#define DW_FCF_SHELLPOSITION     FCF_SHELLPOSITION
+#define DW_FCF_TASKLIST          FCF_TASKLIST
+#define DW_FCF_NOBYTEALIGN       FCF_NOBYTEALIGN
+#define DW_FCF_NOMOVEWITHOWNER   FCF_NOMOVEWITHOWNER
+#define DW_FCF_SYSMODAL          FCF_SYSMODAL
+#define DW_FCF_HIDEBUTTON        FCF_HIDEBUTTON
+#define DW_FCF_HIDEMAX           FCF_HIDEMAX
+#define DW_FCF_AUTOICON          FCF_AUTOICON
+#define DW_FCF_MAXIMIZE          WS_MAXIMIZED
+#define DW_FCF_MINIMIZE          WS_MINIMIZED
+
+#define DW_CFA_BITMAPORICON      CFA_BITMAPORICON
+#define DW_CFA_STRING            CFA_STRING
+#define DW_CFA_ULONG             CFA_ULONG
+#define DW_CFA_TIME              CFA_TIME
+#define DW_CFA_DATE              CFA_DATE
+#define DW_CFA_CENTER            CFA_CENTER
+#define DW_CFA_LEFT              CFA_LEFT
+#define DW_CFA_RIGHT             CFA_RIGHT
+#define DW_CFA_HORZSEPARATOR     CFA_HORZSEPARATOR
+#define DW_CFA_SEPARATOR         CFA_SEPARATOR
+#define DW_CFA_STRINGANDICON     0
+
+#define DW_CRA_SELECTED          CRA_SELECTED
+#define DW_CRA_CURSORED          CRA_CURSORED
+
+#define DW_LS_MULTIPLESEL        LS_MULTIPLESEL
+
+#define DW_LIT_NONE              -1
+
+#define DW_MLE_CASESENSITIVE     MLFSEARCH_CASESENSITIVE
+
+#define DW_POINTER_ARROW         SPTR_ARROW
+#define DW_POINTER_CLOCK         SPTR_WAIT
+
+#define DW_OS2_NEW_WINDOW        1
+
+/* flag values for dw_messagebox() */
+#define DW_MB_OK                 MB_OK
+#define DW_MB_OKCANCEL           MB_OKCANCEL
+#define DW_MB_YESNO              MB_YESNO
+#define DW_MB_YESNOCANCEL        MB_YESNOCANCEL
+
+#define DW_MB_WARNING            MB_WARNING
+#define DW_MB_ERROR              MB_ERROR
+#define DW_MB_INFORMATION        MB_INFORMATION
+#define DW_MB_QUESTION           MB_QUERY
+
+/* Virtual Key Codes */
+#define VK_LBUTTON           VK_BUTTON1
+#define VK_RBUTTON           VK_BUTTON2
+#define VK_MBUTTON           VK_BUTTON3
+#define VK_RETURN            VK_NEWLINE
+#define VK_SNAPSHOT          VK_PRINTSCRN
+#define VK_CANCEL            VK_BREAK
+#define VK_CAPITAL           VK_CAPSLOCK
+#define VK_ESCAPE            VK_ESC
+#define VK_PRIOR             VK_PAGEUP
+#define VK_NEXT              VK_PAGEDOWN
+#define VK_SELECT            133
+#define VK_EXECUTE           134
+#define VK_PRINT             135
+#define VK_HELP              136
+#define VK_LWIN              137
+#define VK_RWIN              138
+#define VK_MULTIPLY          ('*' + 128)
+#define VK_ADD               ('+' + 128)
+#define VK_SEPARATOR         141
+#define VK_SUBTRACT          ('-' + 128)
+#define VK_DECIMAL           ('.' + 128)
+#define VK_DIVIDE            ('/' + 128)
+#define VK_SCROLL            VK_SCRLLOCK
+#define VK_LSHIFT            VK_SHIFT
+#define VK_RSHIFT            147
+#define VK_LCONTROL          VK_CTRL
+#define VK_RCONTROL          149
+#define VK_NUMPAD0           ('0' + 128)
+#define VK_NUMPAD1           ('1' + 128)
+#define VK_NUMPAD2           ('2' + 128)
+#define VK_NUMPAD3           ('3' + 128)
+#define VK_NUMPAD4           ('4' + 128)
+#define VK_NUMPAD5           ('5' + 128)
+#define VK_NUMPAD6           ('6' + 128)
+#define VK_NUMPAD7           ('7' + 128)
+#define VK_NUMPAD8           ('8' + 128)
+#define VK_NUMPAD9           ('9' + 128)
+#define VK_BACK              VK_BACKSPACE
+#define VK_LMENU             VK_MENU
+#define VK_RMENU             VK_MENU
+
+typedef struct _window_data {
+	PFNWP oldproc;
+	UserData *root;
+	HWND clickdefault;
+	ULONG flags;
+	void *data;
+} WindowData;
+
+typedef struct _hpixmap {
+	unsigned long width, height;
+	HDC hdc;
+	HPS hps;
+	HBITMAP hbm;
+	HWND handle;
+} *HPIXMAP;
+
+typedef void *HTREEITEM;
+typedef HWND HMENUI;
+typedef HMODULE HMOD;
+typedef unsigned short UWORD;
+
+extern HAB dwhab;
+extern HMQ dwhmq;
+#endif
+
+#if defined(__MAC__)
+/* MacOS specific section */
+#include <Carbon/Carbon.h>
+
+typedef ControlRef HWND;
+typedef ThreadID DWTID;
+typedef unsigned long ULONG;
+typedef long LONG;
+typedef unsigned short USHORT;
+typedef short SHORT;
+typedef unsigned short UWORD;
+typedef short WORD ;
+typedef unsigned char UCHAR;
+typedef char CHAR;
+typedef unsigned UINT;
+typedef int INT;
+typedef void *HMTX;
+typedef void *HEV;
+typedef void *HMOD;
+typedef void *HPIXMAP;
+typedef void *HTREEITEM;
+typedef void *HMENUI;
+
+typedef struct _window_data {
+	UserData *root;
+	HWND clickdefault;
+	ULONG flags;
+	void *data;
+} WindowData;
+
+#define DW_DT_LEFT               0
+#define DW_DT_QUERYEXTENT        0
+#define DW_DT_UNDERSCORE         0
+#define DW_DT_STRIKEOUT          0
+#define DW_DT_TEXTATTRS          0
+#define DW_DT_EXTERNALLEADING    0
+#define DW_DT_CENTER             0
+#define DW_DT_RIGHT              0
+#define DW_DT_TOP                0
+#define DW_DT_VCENTER            0
+#define DW_DT_BOTTOM             0
+#define DW_DT_HALFTONE           0
+#define DW_DT_MNEMONIC           0
+#define DW_DT_WORDBREAK          0
+#define DW_DT_ERASERECT          0
+
+#define DW_FCF_TITLEBAR          0
+#define DW_FCF_SYSMENU           0
+#define DW_FCF_MENU              0
+#define DW_FCF_SIZEBORDER        0
+#define DW_FCF_MINBUTTON         0
+#define DW_FCF_MAXBUTTON         0
+#define DW_FCF_MINMAX            0
+#define DW_FCF_VERTSCROLL        0
+#define DW_FCF_HORZSCROLL        0
+#define DW_FCF_DLGBORDER         0
+#define DW_FCF_BORDER            0
+#define DW_FCF_SHELLPOSITION     0
+#define DW_FCF_TASKLIST          0
+#define DW_FCF_NOBYTEALIGN       0
+#define DW_FCF_NOMOVEWITHOWNER   0
+#define DW_FCF_SYSMODAL          0
+#define DW_FCF_HIDEBUTTON        0
+#define DW_FCF_HIDEMAX           0
+#define DW_FCF_AUTOICON          0
+#define DW_FCF_MAXIMIZE          0
+#define DW_FCF_MINIMIZE          0
+
+#define DW_CFA_BITMAPORICON      1
+#define DW_CFA_STRING            (1 << 1)
+#define DW_CFA_ULONG             (1 << 2)
+#define DW_CFA_TIME              (1 << 3)
+#define DW_CFA_DATE              (1 << 4)
+#define DW_CFA_CENTER            (1 << 5)
+#define DW_CFA_LEFT              (1 << 6)
+#define DW_CFA_RIGHT             (1 << 7)
+#define DW_CFA_STRINGANDICON     (1 << 8)
+#define DW_CFA_HORZSEPARATOR     0
+#define DW_CFA_SEPARATOR         0
+
+#define DW_CRA_SELECTED          1
+#define DW_CRA_CURSORED          (1 << 1)
+
+#define DW_LS_MULTIPLESEL        1
+
+#define DW_LIT_NONE              -1
+
+#define DW_MLE_CASESENSITIVE     MLFSEARCH_CASESENSITIVE
+
+#define DW_POINTER_ARROW         0
+#define DW_POINTER_CLOCK         watchCursor
+
+#define HWND_DESKTOP		 ((HWND)0)
+
+/* flag values for dw_messagebox() */
+#define DW_MB_OK                 (1 << 1)
+#define DW_MB_OKCANCEL           (1 << 2)
+#define DW_MB_YESNO              (1 << 3)
+#define DW_MB_YESNOCANCEL        (1 << 4)
+
+#define DW_MB_WARNING            (1 << 10)
+#define DW_MB_ERROR              (1 << 11)
+#define DW_MB_INFORMATION        (1 << 12)
+#define DW_MB_QUESTION           (1 << 13)
+
+
+#endif
+
+/* Windows specific section */
+#if defined(__WIN32__) || defined(WINNT)
+#include <windows.h>
+#include <commctrl.h>
+
+#if defined(MSVC) && !defined(API)
+#define API _cdecl
+#endif
+
+#define DW_DT_LEFT               SS_LEFT
+#define DW_DT_QUERYEXTENT        0
+#define DW_DT_UNDERSCORE         0
+#define DW_DT_STRIKEOUT          0
+#define DW_DT_TEXTATTRS          0
+#define DW_DT_EXTERNALLEADING    0
+#define DW_DT_CENTER             SS_CENTER
+#define DW_DT_RIGHT              SS_RIGHT
+#define DW_DT_TOP                0
+#define DW_DT_VCENTER            SS_NOPREFIX
+#define DW_DT_BOTTOM             0
+#define DW_DT_HALFTONE           0
+#define DW_DT_MNEMONIC           0
+#define DW_DT_WORDBREAK          0
+#define DW_DT_ERASERECT          0
+
+#define DW_FCF_TITLEBAR          WS_CAPTION
+#define DW_FCF_SYSMENU           WS_SYSMENU
+#define DW_FCF_MENU              0
+#define DW_FCF_SIZEBORDER        WS_THICKFRAME
+#define DW_FCF_MINBUTTON         WS_MINIMIZEBOX
+#define DW_FCF_MAXBUTTON         WS_MAXIMIZEBOX
+#define DW_FCF_MINMAX            (WS_MINIMIZEBOX|WS_MAXIMIZEBOX)
+#define DW_FCF_VERTSCROLL        WS_VSCROLL
+#define DW_FCF_HORZSCROLL        WS_HSCROLL
+#define DW_FCF_DLGBORDER         WS_DLGFRAME
+#define DW_FCF_BORDER            WS_BORDER
+#define DW_FCF_SHELLPOSITION     0
+#define DW_FCF_TASKLIST          WS_VSCROLL
+#define DW_FCF_NOBYTEALIGN       0
+#define DW_FCF_NOMOVEWITHOWNER   0
+#define DW_FCF_SYSMODAL          0
+#define DW_FCF_HIDEBUTTON        WS_MINIMIZEBOX
+#define DW_FCF_HIDEMAX           0
+#define DW_FCF_AUTOICON          0
+#define DW_FCF_MAXIMIZE          WS_MAXIMIZE
+#define DW_FCF_MINIMIZE          WS_MINIMIZE
+
+#define DW_CFA_BITMAPORICON      1
+#define DW_CFA_STRING            (1 << 1)
+#define DW_CFA_ULONG             (1 << 2)
+#define DW_CFA_TIME              (1 << 3)
+#define DW_CFA_DATE              (1 << 4)
+#define DW_CFA_CENTER            (1 << 5)
+#define DW_CFA_LEFT              (1 << 6)
+#define DW_CFA_RIGHT             (1 << 7)
+#define DW_CFA_STRINGANDICON     (1 << 8)
+#define DW_CFA_HORZSEPARATOR     0
+#define DW_CFA_SEPARATOR         0
+
+#define DW_CRA_SELECTED          LVNI_SELECTED
+#define DW_CRA_CURSORED          LVNI_FOCUSED
+
+#define DW_LS_MULTIPLESEL        LBS_MULTIPLESEL
+
+#define DW_LIT_NONE              -1
+
+#define DW_MLE_CASESENSITIVE     1
+
+#define DW_POINTER_ARROW         32512
+#define DW_POINTER_CLOCK         32514
+
+/* flag values for dw_messagebox() */
+#define DW_MB_OK                 MB_OK
+#define DW_MB_OKCANCEL           MB_OKCANCEL
+#define DW_MB_YESNO              MB_YESNO
+#define DW_MB_YESNOCANCEL        MB_YESNOCANCEL
+
+#define DW_MB_WARNING            MB_ICONWARNING
+#define DW_MB_ERROR              MB_ICONERROR
+#define DW_MB_INFORMATION        MB_ICONINFORMATION
+#define DW_MB_QUESTION           MB_ICONQUESTION
+
+/* Key Modifiers */
+#define KC_CTRL                  (1)
+#define KC_SHIFT                 (1 << 1)
+#define KC_ALT                   (1 << 2)
+
+#define STATICCLASSNAME "STATIC"
+#define COMBOBOXCLASSNAME "COMBOBOX"
+#define LISTBOXCLASSNAME "LISTBOX"
+#define BUTTONCLASSNAME "BUTTON"
+#define POPUPMENUCLASSNAME "POPUPMENU"
+#define EDITCLASSNAME "EDIT"
+#define FRAMECLASSNAME "FRAME"
+#define SCROLLBARCLASSNAME "SCROLLBAR"
+
+#define ClassName "dynamicwindows"
+#define SplitbarClassName "dwsplitbar"
+#define ObjectClassName "dwobjectclass"
+#define DefaultFont NULL
+
+typedef struct _color {
+	int fore;
+	int back;
+	HWND combo, buddy;
+	int user;
+	int vcenter;
+	HWND clickdefault;
+	HBRUSH hbrush;
+	HFONT hfont;
+	char fontname[128];
+	WNDPROC pOldProc;
+	UserData *root;
+} ColorInfo;
+
+typedef struct _notebookpage {
+	ColorInfo cinfo;
+	TC_ITEM item;
+	HWND hwnd;
+	int realid;
+} NotebookPage;
+
+typedef HANDLE HMTX;
+typedef HANDLE HEV;
+typedef HANDLE HMOD;
+
+typedef struct _container {
+	ColorInfo cinfo;
+	ULONG *flags;
+	WNDPROC pOldProc;
+	ULONG columns;
+} ContainerInfo;
+
+typedef struct _hpixmap {
+	unsigned long width, height;
+	HBITMAP hbm;
+	HDC hdc;
+	HWND handle;
+	void *bits;
+} *HPIXMAP;
+
+typedef HWND HMENUI;
+#endif
+
+typedef struct _item {
+	/* Item type - Box or Item */
+	int type;
+	/* Handle to Frame or Window */
+	HWND hwnd;
+	/* Width and Height of static size */
+	int width, height, origwidth, origheight;
+	/* Size Type - Static or Expand */
+	int hsize, vsize;
+	/* Padding */
+	int pad;
+	/* Ratio of current item */
+	float xratio, yratio;
+} Item;
+
+typedef struct _box {
+#if defined(__WIN32__) || defined(WINNT)
+	ColorInfo cinfo;
+#elif defined(__OS2__) || defined(__EMX__)
+	PFNWP oldproc;
+	UserData *root;
+	HWND hwndtitle;
+	int titlebar;
+#endif
+	/* Number of items in the box */
+	int count;
+	/* Box type - horizontal or vertical */
+	int type;
+	/* Padding */
+	int pad, parentpad, grouppadx, grouppady;
+	/* Groupbox */
+	HWND grouphwnd;
+	/* Default item */
+	HWND defaultitem;
+	/* Used as temporary storage in the calculation stage */
+	int upx, upy, minheight, minwidth;
+	/* Ratio in this box */
+	float xratio, yratio, parentxratio, parentyratio;
+	/* Used for calculating individual item ratios */
+	int width, height;
+	/* Any combinations of flags describing the box */
+	unsigned long flags;
+	/* Array of item structures */
+	struct _item *items;
+} Box;
+
+typedef struct _bubblebutton {
+#if defined(__WIN32__) || defined(WINNT)
+	ColorInfo cinfo;
+	int checkbox;
+	WNDPROC pOldProc;
+#endif
+#if defined(__OS2__) || defined(__EMX__)
+	PFNWP pOldProc;
+	UserData *root;
+#endif
+	unsigned long id;
+	char bubbletext[BUBBLE_HELP_MAX];
+} BubbleButton;
+
+#else
+/* GTK Specific section */
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdkprivate.h>
+#include <gdk/gdkkeysyms.h>
+#include <pthread.h>
+#include <dlfcn.h>
+
+#define DW_DT_LEFT               1
+#define DW_DT_UNDERSCORE         (1 << 1)
+#define DW_DT_STRIKEOUT          (1 << 2)
+#define DW_DT_CENTER             (1 << 3)
+#define DW_DT_RIGHT              (1 << 4)
+#define DW_DT_TOP                (1 << 5)
+#define DW_DT_VCENTER            (1 << 6)
+#define DW_DT_BOTTOM             (1 << 7)
+#define DW_DT_HALFTONE           (1 << 8)
+#define DW_DT_MNEMONIC           (1 << 9)
+#define DW_DT_WORDBREAK          (1 << 10)
+#define DW_DT_ERASERECT          (1 << 11)
+
+/* these don't exist under gtk, so make them dummy entries */
+#define DW_DT_QUERYEXTENT        0
+#define DW_DT_TEXTATTRS          0
+#define DW_DT_EXTERNALLEADING    0
+
+#define DW_FCF_TITLEBAR          1
+#define DW_FCF_SYSMENU           (1 << 1)
+#define DW_FCF_MENU              (1 << 2)
+#define DW_FCF_SIZEBORDER        (1 << 3)
+#define DW_FCF_MINBUTTON         (1 << 4)
+#define DW_FCF_MAXBUTTON         (1 << 5)
+#define DW_FCF_MINMAX            (1 << 6)
+#define DW_FCF_VERTSCROLL        (1 << 7)
+#define DW_FCF_HORZSCROLL        (1 << 8)
+#define DW_FCF_DLGBORDER         (1 << 9)
+#define DW_FCF_BORDER            (1 << 10)
+#define DW_FCF_SHELLPOSITION     (1 << 11)
+#define DW_FCF_TASKLIST          (1 << 12)
+#define DW_FCF_NOBYTEALIGN       (1 << 13)
+#define DW_FCF_NOMOVEWITHOWNER   (1 << 14)
+#define DW_FCF_SYSMODAL          (1 << 15)
+#define DW_FCF_HIDEBUTTON        (1 << 16)
+#define DW_FCF_HIDEMAX           (1 << 17)
+#define DW_FCF_AUTOICON          (1 << 18)
+#define DW_FCF_MAXIMIZE          (1 << 19)
+#define DW_FCF_MINIMIZE          (1 << 20)
+
+#define DW_CFA_BITMAPORICON      1
+#define DW_CFA_STRING            (1 << 1)
+#define DW_CFA_ULONG             (1 << 2)
+#define DW_CFA_TIME              (1 << 3)
+#define DW_CFA_DATE              (1 << 4)
+#define DW_CFA_CENTER            (1 << 5)
+#define DW_CFA_LEFT              (1 << 6)
+#define DW_CFA_RIGHT             (1 << 7)
+#define DW_CFA_HORZSEPARATOR     (1 << 8)
+#define DW_CFA_SEPARATOR         (1 << 9)
+#define DW_CFA_STRINGANDICON     (1 << 10)
+
+#define DW_CRA_SELECTED          1
+#define DW_CRA_CURSORED          (1 << 1)
+
+#define DW_LS_MULTIPLESEL        1
+
+#define DW_LIT_NONE              -1
+
+#define DW_MLE_CASESENSITIVE     1
+
+#define DW_POINTER_ARROW         GDK_TOP_LEFT_ARROW
+#define DW_POINTER_CLOCK         GDK_WATCH
+
+#define HWND_DESKTOP             ((HWND)0)
+
+/* flag values for dw_messagebox() */
+#define DW_MB_OK                 (1 << 1)
+#define DW_MB_OKCANCEL           (1 << 2)
+#define DW_MB_YESNO              (1 << 3)
+#define DW_MB_YESNOCANCEL        (1 << 4)
+
+#define DW_MB_WARNING            (1 << 10)
+#define DW_MB_ERROR              (1 << 11)
+#define DW_MB_INFORMATION        (1 << 12)
+#define DW_MB_QUESTION           (1 << 13)
+
+/* Virtual Key Codes */
+#define VK_LBUTTON           GDK_Pointer_Button1
+#define VK_RBUTTON           GDK_Pointer_Button3
+#define VK_CANCEL            GDK_Cancel
+#define VK_MBUTTON           GDK_Pointer_Button2
+#define VK_BACK              GDK_BackSpace
+#define VK_TAB               GDK_Tab
+#define VK_CLEAR             GDK_Clear
+#define VK_RETURN            GDK_Return
+#define VK_MENU              GDK_Menu
+#define VK_PAUSE             GDK_Pause
+#define VK_CAPITAL           GDK_Caps_Lock
+#define VK_ESCAPE            GDK_Escape
+#define VK_SPACE             GDK_space
+#define VK_PRIOR             GDK_Page_Up
+#define VK_NEXT              GDK_Page_Down
+#define VK_END               GDK_End
+#define VK_HOME              GDK_Home
+#define VK_LEFT              GDK_Left
+#define VK_UP                GDK_Up
+#define VK_RIGHT             GDK_Right
+#define VK_DOWN              GDK_Down
+#define VK_SELECT            GDK_Select
+#define VK_PRINT             GDK_Sys_Req
+#define VK_EXECUTE           GDK_Execute
+#define VK_SNAPSHOT          GDK_Print
+#define VK_INSERT            GDK_Insert
+#define VK_DELETE            GDK_Delete
+#define VK_HELP              GDK_Help
+#define VK_LWIN              GDK_Super_L
+#define VK_RWIN              GDK_Super_R
+#define VK_NUMPAD0           GDK_KP_0
+#define VK_NUMPAD1           GDK_KP_1
+#define VK_NUMPAD2           GDK_KP_2
+#define VK_NUMPAD3           GDK_KP_3
+#define VK_NUMPAD4           GDK_KP_4
+#define VK_NUMPAD5           GDK_KP_5
+#define VK_NUMPAD6           GDK_KP_6
+#define VK_NUMPAD7           GDK_KP_7
+#define VK_NUMPAD8           GDK_KP_8
+#define VK_NUMPAD9           GDK_KP_9
+#define VK_MULTIPLY          GDK_KP_Multiply
+#define VK_ADD               GDK_KP_Add
+#define VK_SEPARATOR         GDK_KP_Separator
+#define VK_SUBTRACT          GDK_KP_Subtract
+#define VK_DECIMAL           GDK_KP_Decimal
+#define VK_DIVIDE            GDK_KP_Divide
+#define VK_F1                GDK_F1
+#define VK_F2                GDK_F2
+#define VK_F3                GDK_F3
+#define VK_F4                GDK_F4
+#define VK_F5                GDK_F5
+#define VK_F6                GDK_F6
+#define VK_F7                GDK_F7
+#define VK_F8                GDK_F8
+#define VK_F9                GDK_F9
+#define VK_F10               GDK_F10
+#define VK_F11               GDK_F11
+#define VK_F12               GDK_F12
+#define VK_F13               GDK_F13
+#define VK_F14               GDK_F14
+#define VK_F15               GDK_F15
+#define VK_F16               GDK_F16
+#define VK_F17               GDK_F17
+#define VK_F18               GDK_F18
+#define VK_F19               GDK_F19
+#define VK_F20               GDK_F20
+#define VK_F21               GDK_F21
+#define VK_F22               GDK_F22
+#define VK_F23               GDK_F23
+#define VK_F24               GDK_F24
+#define VK_NUMLOCK           GDK_Num_Lock
+#define VK_SCROLL            GDK_Scroll_Lock
+#define VK_LSHIFT            GDK_Shift_L
+#define VK_RSHIFT            GDK_Shift_R
+#define VK_LCONTROL          GDK_Control_L
+#define VK_RCONTROL          GDK_Control_R
+#define VK_LMENU             GDK_Menu
+#define VK_RMENU             GDK_Menu
+
+/* Key Modifiers */
+#define KC_CTRL              GDK_CONTROL_MASK
+#define KC_SHIFT             GDK_SHIFT_MASK
+#define KC_ALT               GDK_MOD1_MASK
+
+typedef GtkWidget *HWND;
+#ifndef _ENVRNMNT_H
+typedef unsigned long ULONG;
+#endif
+typedef long LONG;
+typedef unsigned short USHORT;
+typedef short SHORT;
+typedef unsigned short UWORD;
+typedef short WORD ;
+typedef unsigned char UCHAR;
+typedef char CHAR;
+typedef unsigned UINT;
+typedef int INT;
+typedef pthread_mutex_t *HMTX;
+typedef struct _dw_unix_event {
+	pthread_mutex_t mutex;
+	pthread_cond_t event;
+	pthread_t thread;
+	int alive;
+	int posted;
+} *HEV;
+typedef pthread_t DWTID;
+typedef void * HMOD;
+
+typedef struct _hpixmap {
+	unsigned long width, height;
+	GdkPixmap *pixmap;
+	HWND handle;
+} *HPIXMAP;
+
+typedef GtkWidget *HMENUI;
+typedef void *HTREEITEM;
+
+typedef struct _resource_struct {
+	long resource_max, *resource_id;
+	char **resource_data;
+} DWResources;
+
+#if !defined(DW_RESOURCES) || defined(BUILD_DLL)
+static DWResources _resources = { 0, 0, 0 };
+#else
+extern DWResources _resources;
+#endif
+
+#endif
+
+#if !defined(__OS2__) && !defined(__EMX__)
+typedef struct _CDATE
+{
+	UCHAR  day;
+	UCHAR  month;
+	USHORT year;
+} CDATE;
+typedef CDATE *PCDATE;
+
+typedef struct _CTIME
+{
+	UCHAR hours;
+	UCHAR minutes;
+	UCHAR seconds;
+	UCHAR ucReserved;
+} CTIME;
+typedef CTIME *PCTIME;
+#endif
+
+#if defined(__OS2__) || defined(__WIN32__) || defined(WINNT) || defined(__EMX__)
+typedef unsigned long DWTID;
+#endif
+
+typedef struct _dwenv {
+	/* Operating System Name and DW Build Date/Time */
+	char osName[30], buildDate[30], buildTime[30];
+	/* Versions and builds */
+	short MajorVersion, MinorVersion, MajorBuild, MinorBuild;
+	/* Dynamic Window version */
+	short DWMajorVersion, DWMinorVersion, DWSubVersion;
+} DWEnv;
+
+
+typedef struct _dwexpose {
+	int x, y;
+	int width, height;
+} DWExpose;
+
+typedef struct _dwdialog {
+	HEV eve;
+	int done;
+	int method;
+	void *data, *result;
+} DWDialog;
+
+#define DW_SIGNAL_FUNC(a) ((void *)a)
+
+#define DW_DESKTOP               HWND_DESKTOP
+#define DW_MINIMIZED 1
+
+#define DW_BUTTON1_MASK 1
+#define DW_BUTTON2_MASK (1 << 1)
+#define DW_BUTTON3_MASK (1 << 2)
+
+#define DW_EXEC_CON 0
+#define DW_EXEC_GUI 1
+
+#define DW_FILE_OPEN      0
+#define DW_FILE_SAVE      1
+#define DW_DIRECTORY_OPEN 2
+
+#define DW_HORZ 0
+#define DW_VERT 1
+
+/* Obsolete, should disappear sometime */
+#define BOXHORZ DW_HORZ
+#define BOXVERT DW_VERT
+
+#define DW_SCROLL_UP 0
+#define DW_SCROLL_DOWN 1
+#define DW_SCROLL_TOP 2
+#define DW_SCROLL_BOTTOM 3
+
+/* return values for dw_messagebox() */
+#define DW_MB_RETURN_OK           0
+#define DW_MB_RETURN_YES          1
+#define DW_MB_RETURN_NO           0
+#define DW_MB_RETURN_CANCEL       2
+
+#define DW_PIXMAP_WIDTH(x) (x ? x->width : 0)
+#define DW_PIXMAP_HEIGHT(x) (x ? x->height : 0)
+
+#define DW_RGB_COLOR (0xF0000000)
+#define DW_RGB_TRANSPARENT (0x0F000000)
+#define DW_RGB_MASK (0x00FFFFFF)
+#define DW_RED_MASK (0x000000FF)
+#define DW_GREEN_MASK (0x0000FF00)
+#define DW_BLUE_MASK (0x00FF0000)
+#define DW_RED_VALUE(a) (a & DW_RED_MASK)
+#define DW_GREEN_VALUE(a) ((a & DW_GREEN_MASK) >> 8)
+#define DW_BLUE_VALUE(a) ((a & DW_BLUE_MASK) >> 16)
+#define DW_RGB(a, b, c) (0xF0000000 | a | b << 8 | c << 16)
+
+#define DW_MENU_SEPARATOR ""
+#define DW_NOMENU 0
+
+#if defined(__OS2__) || defined(__EMX__)
+#define DW_OS2_RGB(a) ((DW_RED_VALUE(a) << 16) | (DW_GREEN_VALUE(a) << 8) | DW_BLUE_VALUE(a))
+#endif
+
+#ifndef API
+#define API
+#endif
+
+#define DWSIGNAL API
+
+/* Let other APIs know what types we've defined,
+ * Regina REXX in particular, on Unix.
+ */
+#define ULONG_TYPEDEFED 1
+#define LONG_TYPEDEFED 1
+#define USHORT_TYPEDEFED 1
+#define SHORT_TYPEDEFED 1
+#define UWORD_TYPEDEFED 1
+#define WORD_TYPEDEFED 1
+#define UCHAR_TYPEDEFED 1
+#define CHAR_TYPEDEFED 1
+#define UINT_TYPEDEFED 1
+#define INT_TYPEDEFED 1
+
+/* Public function prototypes */
+void API dw_box_pack_start(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad);
+void API dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad);
+#if !defined(__OS2__) && !defined(__WIN32__) && !defined(__EMX__) && !defined(__MAC__)
+int API dw_int_init(DWResources *res, int newthread, int *argc, char **argv[]);
+#define dw_init(a, b, c) dw_int_init(&_resources, a, &b, &c)
+#else
+int API dw_init(int newthread, int argc, char *argv[]);
+#endif
+void API dw_main(void);
+void API dw_main_sleep(int seconds);
+void API dw_main_iteration(void);
+void API dw_free(void *ptr);
+int API dw_window_show(HWND handle);
+int API dw_window_hide(HWND handle);
+int API dw_window_minimize(HWND handle);
+int API dw_window_raise(HWND handle);
+int API dw_window_lower(HWND handle);
+int API dw_window_destroy(HWND handle);
+void API dw_window_redraw(HWND handle);
+int API dw_window_set_font(HWND handle, char *fontname);
+int API dw_window_set_color(HWND handle, unsigned long fore, unsigned long back);
+HWND API dw_window_new(HWND hwndOwner, char *title, unsigned long flStyle);
+HWND API dw_box_new(int type, int pad);
+HWND API dw_groupbox_new(int type, int pad, char *title);
+HWND API dw_mdi_new(unsigned long id);
+HWND API dw_bitmap_new(unsigned long id);
+HWND API dw_bitmapbutton_new(char *text, unsigned long id);
+HWND API dw_bitmapbutton_new_from_file(char *text, unsigned long id, char *filename);
+HWND API dw_container_new(unsigned long id, int multi);
+HWND API dw_tree_new(unsigned long id);
+HWND API dw_text_new(char *text, unsigned long id);
+HWND API dw_status_text_new(char *text, unsigned long id);
+HWND API dw_mle_new(unsigned long id);
+HWND API dw_entryfield_new(char *text, unsigned long id);
+HWND API dw_entryfield_password_new(char *text, ULONG id);
+HWND API dw_combobox_new(char *text, unsigned long id);
+HWND API dw_button_new(char *text, unsigned long id);
+HWND API dw_spinbutton_new(char *text, unsigned long id);
+HWND API dw_radiobutton_new(char *text, ULONG id);
+HWND API dw_percent_new(unsigned long id);
+HWND API dw_slider_new(int vertical, int increments, ULONG id);
+HWND API dw_scrollbar_new(int vertical, int increments, ULONG id);
+HWND API dw_checkbox_new(char *text, unsigned long id);
+HWND API dw_listbox_new(unsigned long id, int multi);
+void API dw_listbox_append(HWND handle, char *text);
+void API dw_listbox_clear(HWND handle);
+int API dw_listbox_count(HWND handle);
+void API dw_listbox_set_top(HWND handle, int top);
+void API dw_listbox_select(HWND handle, int index, int state);
+void API dw_listbox_delete(HWND handle, int index);
+void API dw_listbox_query_text(HWND handle, unsigned int index, char *buffer, unsigned int length);
+void API dw_listbox_set_text(HWND handle, unsigned int index, char *buffer);
+unsigned int API dw_listbox_selected(HWND handle);
+int API dw_listbox_selected_multi(HWND handle, int where);
+unsigned int API dw_percent_query_range(HWND handle);
+void API dw_percent_set_pos(HWND handle, unsigned int position);
+unsigned int API dw_slider_query_pos(HWND handle);
+void API dw_slider_set_pos(HWND handle, unsigned int position);
+unsigned int API dw_scrollbar_query_pos(HWND handle);
+void API dw_scrollbar_set_pos(HWND handle, unsigned int position);
+void API dw_scrollbar_set_range(HWND handle, unsigned int range, unsigned int visible);
+void API dw_window_set_pos(HWND handle, unsigned long x, unsigned long y);
+void API dw_window_set_usize(HWND handle, unsigned long width, unsigned long height);
+void API dw_window_set_pos_size(HWND handle, unsigned long x, unsigned long y, unsigned long width, unsigned long height);
+void API dw_window_get_pos_size(HWND handle, unsigned long *x, unsigned long *y, unsigned long *width, unsigned long *height);
+void API dw_window_set_style(HWND handle, unsigned long style, unsigned long mask);
+void API dw_window_set_icon(HWND handle, unsigned long id);
+void API dw_window_set_bitmap(HWND handle, unsigned long id, char *filename);
+char * API dw_window_get_text(HWND handle);
+void API dw_window_set_text(HWND handle, char *text);
+int API dw_window_set_border(HWND handle, int border);
+void API dw_window_disable(HWND handle);
+void API dw_window_enable(HWND handle);
+void API dw_window_capture(HWND handle);
+void API dw_window_release(void);
+void API dw_window_reparent(HWND handle, HWND newparent);
+void API dw_window_pointer(HWND handle, int pointertype);
+void API dw_window_default(HWND window, HWND defaultitem);
+void API dw_window_click_default(HWND window, HWND next);
+unsigned int API dw_mle_import(HWND handle, char *buffer, int startpoint);
+void API dw_mle_export(HWND handle, char *buffer, int startpoint, int length);
+void API dw_mle_query(HWND handle, unsigned long *bytes, unsigned long *lines);
+void API dw_mle_delete(HWND handle, int startpoint, int length);
+void API dw_mle_clear(HWND handle);
+void API dw_mle_freeze(HWND handle);
+void API dw_mle_thaw(HWND handle);
+void API dw_mle_set(HWND handle, int point);
+void API dw_mle_set_visible(HWND handle, int line);
+void API dw_mle_set_editable(HWND handle, int state);
+void API dw_mle_set_word_wrap(HWND handle, int state);
+int API dw_mle_search(HWND handle, char *text, int point, unsigned long flags);
+void API dw_spinbutton_set_pos(HWND handle, long position);
+void API dw_spinbutton_set_limits(HWND handle, long upper, long lower);
+void API dw_entryfield_set_limit(HWND handle, ULONG limit);
+long API dw_spinbutton_query(HWND handle);
+int API dw_checkbox_query(HWND handle);
+void API dw_checkbox_set(HWND handle, int value);
+HTREEITEM API dw_tree_insert(HWND handle, char *title, unsigned long icon, HTREEITEM parent, void *itemdata);
+HTREEITEM API dw_tree_insert_after(HWND handle, HTREEITEM item, char *title, unsigned long icon, HTREEITEM parent, void *itemdata);
+void API dw_tree_clear(HWND handle);
+void API dw_tree_delete(HWND handle, HTREEITEM item);
+void API dw_tree_set(HWND handle, HTREEITEM item, char *title, unsigned long icon);
+void API dw_tree_expand(HWND handle, HTREEITEM item);
+void API dw_tree_collapse(HWND handle, HTREEITEM item);
+void API dw_tree_item_select(HWND handle, HTREEITEM item);
+void API dw_tree_set_data(HWND handle, HTREEITEM item, void *itemdata);
+void * API dw_tree_get_data(HWND handle, HTREEITEM item);
+char * API dw_tree_get_title(HWND handle, HTREEITEM item);
+HTREEITEM API dw_tree_get_parent(HWND handle, HTREEITEM item);
+int API dw_container_setup(HWND handle, unsigned long *flags, char **titles, int count, int separator);
+unsigned long API dw_icon_load(unsigned long module, unsigned long id);
+unsigned long API dw_icon_load_from_file(char *filename);
+void API dw_icon_free(unsigned long handle);
+void * API dw_container_alloc(HWND handle, int rowcount);
+void API dw_container_set_item(HWND handle, void *pointer, int column, int row, void *data);
+void API dw_container_change_item(HWND handle, int column, int row, void *data);
+void API dw_container_set_column_width(HWND handle, int column, int width);
+void API dw_container_set_row_title(void *pointer, int row, char *title);
+void API dw_container_insert(HWND handle, void *pointer, int rowcount);
+void API dw_container_clear(HWND handle, int redraw);
+void API dw_container_delete(HWND handle, int rowcount);
+char * API dw_container_query_start(HWND handle, unsigned long flags);
+char * API dw_container_query_next(HWND handle, unsigned long flags);
+void API dw_container_scroll(HWND handle, int direction, long rows);
+void API dw_container_cursor(HWND handle, char *text);
+void API dw_container_delete_row(HWND handle, char *text);
+void API dw_container_optimize(HWND handle);
+int API dw_filesystem_setup(HWND handle, unsigned long *flags, char **titles, int count);
+void API dw_filesystem_set_item(HWND handle, void *pointer, int column, int row, void *data);
+void API dw_filesystem_set_file(HWND handle, void *pointer, int row, char *filename, unsigned long icon);
+void dw_taskbar_insert(HWND handle, unsigned long icon, char *bubbletext);
+void dw_taskbar_delete(HWND handle, unsigned long icon);
+int API dw_screen_width(void);
+int API dw_screen_height(void);
+unsigned long API dw_color_depth(void);
+HWND API dw_notebook_new(unsigned long id, int top);
+unsigned long API dw_notebook_page_new(HWND handle, unsigned long flags, int front);
+void API dw_notebook_page_destroy(HWND handle, unsigned int pageid);
+void API dw_notebook_page_set_text(HWND handle, unsigned long pageid, char *text);
+void API dw_notebook_page_set_status_text(HWND handle, unsigned long pageid, char *text);
+void API dw_notebook_page_set(HWND handle, unsigned int pageid);
+unsigned long API dw_notebook_page_query(HWND handle);
+void API dw_notebook_pack(HWND handle, unsigned long pageid, HWND page);
+HWND API dw_splitbar_new(int type, HWND topleft, HWND bottomright, unsigned long id);
+void API dw_splitbar_set(HWND handle, float percent);
+float API dw_splitbar_get(HWND handle);
+HMENUI API dw_menu_new(unsigned long id);
+HMENUI API dw_menubar_new(HWND location);
+HWND API dw_menu_append_item(HMENUI menu, char *title, unsigned long id, unsigned long flags, int end, int check, HMENUI submenu);
+void API dw_menu_item_set_check(HMENUI menu, unsigned long id, int check);
+void API dw_menu_popup(HMENUI *menu, HWND parent, int x, int y);
+void API dw_menu_destroy(HMENUI *menu);
+void API dw_pointer_query_pos(long *x, long *y);
+void API dw_pointer_set_pos(long x, long y);
+void API dw_window_function(HWND handle, void *function, void *data);
+HWND API dw_window_from_id(HWND handle, int id);
+HMTX API dw_mutex_new(void);
+void API dw_mutex_close(HMTX mutex);
+void API dw_mutex_lock(HMTX mutex);
+void API dw_mutex_unlock(HMTX mutex);
+HEV API dw_event_new(void);
+int API dw_event_reset(HEV eve);
+int API dw_event_post(HEV eve);
+int API dw_event_wait(HEV eve, unsigned long timeout);
+int API dw_event_close (HEV *eve);
+DWTID API dw_thread_new(void *func, void *data, int stack);
+void API dw_thread_end(void);
+DWTID API dw_thread_id(void);
+void API dw_exit(int exitcode);
+HWND API dw_render_new(unsigned long id);
+void API dw_color_foreground_set(unsigned long value);
+void API dw_color_background_set(unsigned long value);
+void API dw_draw_point(HWND handle, HPIXMAP pixmap, int x, int y);
+void API dw_draw_line(HWND handle, HPIXMAP pixmap, int x1, int y1, int x2, int y2);
+void API dw_draw_rect(HWND handle, HPIXMAP pixmap, int fill, int x, int y, int width, int height);
+void API dw_draw_text(HWND handle, HPIXMAP pixmap, int x, int y, char *text);
+void API dw_font_text_extents(HWND handle, HPIXMAP pixmap, char *text, int *width, int *height);
+void API dw_flush(void);
+void API dw_pixmap_bitblt(HWND dest, HPIXMAP destp, int xdest, int ydest, int width, int height, HWND src, HPIXMAP srcp, int xsrc, int ysrc);
+HPIXMAP API dw_pixmap_new(HWND handle, unsigned long width, unsigned long height, int depth);
+HPIXMAP API dw_pixmap_new_from_file(HWND handle, char *filename);
+HPIXMAP API dw_pixmap_grab(HWND handle, ULONG id);
+void API dw_pixmap_destroy(HPIXMAP pixmap);
+void API dw_beep(int freq, int dur);
+int API dw_messagebox(char *title, int flags, char *format, ...);
+void API dw_environment_query(DWEnv *env);
+int API dw_exec(char *program, int type, char **params);
+int API dw_browse(char *url);
+char * API dw_file_browse(char *title, char *defpath, char *ext, int flags);
+char * API dw_user_dir(void);
+DWDialog * API dw_dialog_new(void *data);
+int API dw_dialog_dismiss(DWDialog *dialog, void *result);
+void * API dw_dialog_wait(DWDialog *dialog);
+void API dw_window_set_data(HWND window, char *dataname, void *data);
+void * API dw_window_get_data(HWND window, char *dataname);
+int API dw_module_load(char *name, HMOD *handle);
+int API dw_module_symbol(HMOD handle, char *name, void**func);
+int API dw_module_close(HMOD handle);
+int API dw_timer_connect(int interval, void *sigfunc, void *data);
+void API dw_timer_disconnect(int id);
+void API dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data);
+void API dw_signal_disconnect_by_window(HWND window);
+void API dw_signal_disconnect_by_data(HWND window, void *data);
+void API dw_signal_disconnect_by_name(HWND window, char *signame);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extract/extract.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,162 @@
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <fcntl.h>
+#include <process.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "dw.h"
+
+FILE *self;
+int aceoffset, current_file = 0, packagesize = 0, files = 0;
+
+int checktext(char *text, char *buffer, int buflen)
+{
+	int z, len = strlen(text);
+
+	for(z=0;z<(buflen-len);z++)
+	{
+		if(memcmp(text, &buffer[z], len) == 0)
+			return z;
+	}
+	return -1;
+
+}
+
+/*
+ * Returns the offset withing the executable to the specified text.
+ */
+long findtext(char *text)
+{
+	char buffer[512];
+	int offset;
+	unsigned long curpos = 0;
+
+	fseek(self, 0, SEEK_SET);
+	fread(buffer, 1, 512, self);
+	if((offset = checktext(text, buffer, 512)) > -1)
+		return offset;
+	while(!feof(self))
+	{
+		memcpy(buffer, &buffer[256], 256);
+		fread(&buffer[256], 1, 256, self);
+		curpos += 256;
+		if((offset = checktext(text, buffer, 512)) > -1)
+			return offset+curpos;
+
+	}
+	return -1;
+}
+
+/* We encode archive search text so we don't get confused
+ * by the string table - I was using LXLite to take care
+ * of this problem on OS/2 but in portable code this may
+ * not be an option. */
+char *decode(char *input)
+{
+	char	*result;
+	int	i = 0;
+
+	result = (char *)malloc(strlen(input) / 2 + 1);
+
+	while (input[0] && input[1])
+	{
+		result[i] = ((input[0] - 0x41) << 4) | (input[1] - 0x41);
+		input += 2;
+		i++;
+	}
+	result[i] = '\0';
+
+	return result;
+}
+
+/*
+ * Find the offset withing the executable of the ace data for use.
+ */
+int aceseek_entry(int num)
+{
+	long headerstart;
+	char headerbuf[20], packageconfig[100];
+	int z, start = 0, entry = 0, packageoffset=0;
+	/* Decode DBSOFT-ACE - small memleak but
+	 * install should not be running for very long. :) */
+	sprintf(headerbuf, "%s%d", decode("EEECFDEPEGFECNEBEDEF"), num);
+	if((headerstart = findtext(headerbuf)) < 0)
+		return FALSE;
+
+	fseek(self, headerstart+strlen(headerbuf), SEEK_SET);
+	fread(packageconfig, 1, 100, self);
+
+	for(z=0;z<100;z++)
+	{
+		if(packageconfig[z] == '-' || packageconfig[z] == '~')
+		{
+			char cur = packageconfig[z];
+			packageconfig[z] = 0;
+			switch(entry)
+			{
+			case 0:
+				current_file = 0;
+				files = atoi(&packageconfig[start]);
+				break;
+			case 1:
+				packagesize = atoi(&packageconfig[start]);
+				break;
+			}
+			start = z+1;
+			if(cur == '~')
+			{
+				packageoffset = z + 1;
+				z = 100;
+			}
+			entry++;
+		}
+	}
+	aceoffset=headerstart+strlen(headerbuf)+packageoffset;
+	fseek(self, aceoffset, SEEK_SET);
+	return TRUE;
+}
+
+int main(int argc, char *argv[])
+{
+	printf("Extract (c) 2001 DBSoft\n");
+
+	if(argc != 2)
+	{
+		printf("Usage: extract <sfxname>.exe\n");
+		exit(1);
+	}
+	if((self = fopen(argv[1], "rb")) != NULL)
+	{
+		int z;
+
+		printf("Processing...\n");
+
+		for(z=0;z<10;z++)
+		{
+			if(aceseek_entry(z))
+			{
+				FILE *tmpf;
+				char tmpname[100], *buf = malloc(packagesize);
+
+				sprintf(tmpname, "entry%d.ace", z);
+
+				if((tmpf = fopen(tmpname, "wb")) != NULL)
+				{
+					printf("Extracting \"entry%d.ace\".\n", z);
+					fread(buf, packagesize, 1, self);
+					fwrite(buf, packagesize, 1, tmpf);
+					fclose(tmpf);
+				}
+				free(buf);
+			}
+		}
+	}
+	else
+		printf("Could not open \"%s\"!", argv[1]);
+
+	return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extract/makefile	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,46 @@
+# Installer Makefile
+
+CC = gcc
+RM = rm -f
+RC = rc
+MAKE = make
+
+DEFS =
+LIBS =
+
+CFLAGS = -O -g -I../incace -Wall
+LDFLAGS = 
+
+
+OBJECTS = globals.o packinst.o uac_comm.o uac_crc.o \
+          uac_crt.o uac_dcpr.o uac_sys.o unace.o
+
+SOURCES = globals.c ../packinst/packinst.c uac_comm.c \
+	  uac_crc.c uac_crt.c uac_dcpr.c uac_sys.c unace.c
+
+all: packinst
+
+$(OBJECTS):
+	$(CC) $(CFLAGS) -c $<	
+
+Include: ../incace/Makefile Makefile
+#	cd include
+#	$(MAKE) -f Makefile all
+
+packinst:  $(OBJECTS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $(DEFS) -o packinst $(OBJECTS)
+
+clean: 
+	$(RM) $(OBJECTS) packinst *~
+
+globals.o: globals.c ../incace/globals.h ../incace/acestruc.h ../incace/unace.h
+packinst.o: ../packinst/packinst.c
+uac_comm.o: uac_comm.c ../incace/globals.h ../incace/uac_dcpr.h ../incace/uac_comm.h
+uac_crc.o: uac_crc.c ../incace/uac_crc.h
+uac_crt.o: uac_crt.c ../incace/os.h ../incace/attribs.h ../incace/globals.h ../incace/uac_crt.h ../incace/uac_sys.h
+uac_dcpr.o: uac_dcpr.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h \
+	      ../incace/uac_dcpr.h ../incace/uac_sys.h
+uac_sys.o: uac_sys.c ../incace/os.h ../incace/globals.h ../incace/uac_sys.h
+unace.o: unace.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h ../incace/uac_crt.h \
+           ../incace/uac_dcpr.h ../incace/uac_sys.h
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extract/makefile.b32	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,41 @@
+# Common settings for Borland 32-bit compilation (makefile.b32 files)
+
+LINK=ilink32
+
+OPT = -O2
+LDFLAGS = -lxncd -l-P
+CPPFLAGS = /I"..\incace" /DWIN32
+LINKFLAGS=/aa -L$(BCCDIR)\lib\psdk
+
+DUMMY=dummy
+
+SRCSUFF = cpp
+OBJSUFF = obj
+
+TARGET = packinst
+OBJECTS = globals.obj uac_comm.obj uac_crc.obj uac_crt.obj uac_dcpr.obj uac_sys.obj unace.obj packinst.obj
+
+all: $(TARGET).exe
+
+packinst.exe:      $(OBJECTS)
+	bcc32 $(LDFLAGS) -epackinst.exe @&&|
+$(OBJECTS)
+|
+
+.$(SRCSUFF).obj:
+	bcc32 $(CPPFLAGS) -c {$< }
+
+packinst.obj: ..\packinst\packinst.c
+	bcc32 $(CPPFLAGS) -P- -c ..\packinst\packinst.c
+        
+.c.obj:
+	bcc32 $(CPPFLAGS) -P- -c {$< }
+        
+clean:
+        -erase *.obj
+        -erase *.exe
+        -erase *.res
+        -erase *.map
+        -erase *.rws
+        -erase *.tds
+        -erase *.il?
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extract/makefile.g95	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,46 @@
+# Installer Makefile
+
+CC = gcc
+RM = rm -f
+RC = rc
+MAKE = make
+
+DEFS =
+LIBS =
+
+CFLAGS = -mno-cygwin -O -g -I../incace -Wall -DWIN32
+LDFLAGS = -mno-cygwin
+
+
+OBJECTS = globals.o packinst.o uac_comm.o uac_crc.o \
+          uac_crt.o uac_dcpr.o uac_sys.o unace.o
+
+SOURCES = globals.c ../packinst/packinst.c uac_comm.c \
+	  uac_crc.c uac_crt.c uac_dcpr.c uac_sys.c unace.c
+
+all: packinst
+
+$(OBJECTS):
+	$(CC) $(CFLAGS) -c $<	
+
+Include: ../incace/Makefile Makefile
+#	cd include
+#	$(MAKE) -f Makefile all
+
+packinst:  $(OBJECTS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $(DEFS) -o packinst $(OBJECTS)
+
+clean: 
+	$(RM) $(OBJECTS) packinst *~
+
+globals.o: globals.c ../incace/globals.h ../incace/acestruc.h ../incace/unace.h
+packinst.o: ../packinst/packinst.c
+uac_comm.o: uac_comm.c ../incace/globals.h ../incace/uac_dcpr.h ../incace/uac_comm.h
+uac_crc.o: uac_crc.c ../incace/uac_crc.h
+uac_crt.o: uac_crt.c ../incace/os.h ../incace/attribs.h ../incace/globals.h ../incace/uac_crt.h ../incace/uac_sys.h
+uac_dcpr.o: uac_dcpr.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h \
+	      ../incace/uac_dcpr.h ../incace/uac_sys.h
+uac_sys.o: uac_sys.c ../incace/os.h ../incace/globals.h ../incace/uac_sys.h
+unace.o: unace.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h ../incace/uac_crt.h \
+           ../incace/uac_dcpr.h ../incace/uac_sys.h
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extract/makefile.gcc	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,46 @@
+# Installer Makefile
+
+CC = gcc
+RM = rm -f
+RC = rc
+MAKE = make
+
+DEFS =
+LIBS =
+
+CFLAGS = -O -g -I../incace -Wall
+LDFLAGS = 
+
+
+OBJECTS = globals.o packinst.o uac_comm.o uac_crc.o \
+          uac_crt.o uac_dcpr.o uac_sys.o unace.o
+
+SOURCES = globals.c ../packinst/packinst.c uac_comm.c \
+	  uac_crc.c uac_crt.c uac_dcpr.c uac_sys.c unace.c
+
+all: packinst
+
+$(OBJECTS):
+	$(CC) $(CFLAGS) -c $<	
+
+Include: ../incace/Makefile Makefile
+#	cd include
+#	$(MAKE) -f Makefile all
+
+packinst:  $(OBJECTS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $(DEFS) -o packinst $(OBJECTS)
+
+clean: 
+	$(RM) $(OBJECTS) packinst *~
+
+globals.o: globals.c ../incace/globals.h ../incace/acestruc.h ../incace/unace.h
+packinst.o: ../packinst/packinst.c
+uac_comm.o: uac_comm.c ../incace/globals.h ../incace/uac_dcpr.h ../incace/uac_comm.h
+uac_crc.o: uac_crc.c ../incace/uac_crc.h
+uac_crt.o: uac_crt.c ../incace/os.h ../incace/attribs.h ../incace/globals.h ../incace/uac_crt.h ../incace/uac_sys.h
+uac_dcpr.o: uac_dcpr.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h \
+	      ../incace/uac_dcpr.h ../incace/uac_sys.h
+uac_sys.o: uac_sys.c ../incace/os.h ../incace/globals.h ../incace/uac_sys.h
+unace.o: unace.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h ../incace/uac_crt.h \
+           ../incace/uac_dcpr.h ../incace/uac_sys.h
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extract/makefile.vac	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,25 @@
+# Installer Makefile
+
+CFLAGS = /Ss /I.. /C
+
+OBJECTS = extract.obj
+
+SOURCES = extract.c
+
+all: extract.exe
+
+$(OBJECTS):
+	icc $(CFLAGS) %s
+
+extract.exe:  $(OBJECTS)
+	icc @<<
+	 /B" /de /optfunc"
+	 /Feextract.exe
+	 $(OBJECTS)
+<<
+	lxlite extract.exe
+
+clean: 
+	rm $(OBJECTS) extract.exe
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extract/makefile.vc	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,38 @@
+#
+CC = cl
+CFLAGS = -c -G5 -GD -Zp1 -DWIN32 -D__WIN32__ -DMSVC -I. -I.. -I..\incace
+CFLAGS_DEBUG = -Zi
+CFLAGS_COMPILE = -MTd
+LIBS = kernel32.lib advapi32.lib user32.lib
+RES = 
+LINKFLAGS = -machine:i386 -debug:full -debugtype:cv
+DLLLINKFLAGS = -dll
+LINK = link
+
+OBJS = 	extract.obj
+                
+all: extract.exe
+
+clean:
+	-erase *.dll
+        -erase *.exe
+        -erase *.opt
+        -erase *.lib
+        -erase *.obj
+        -erase *.map
+        -erase *.pdb
+        -erase *.ilk
+        -erase *.exp
+        -erase *.res
+        -erase *~
+        
+extract.exe: $(OBJS)
+	$(LINK) @<<
+-out:$(@) -subsystem:console
+$(LINKFLAGS)
+$(OBJS)
+$(LIBS)
+<<
+
+.c.obj:
+	$(CC) $(CFLAGS) $(CFLAGS_DEBUG) $(CFLAGS_COMPILE) $*.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gtk/FILE.xpm	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,35 @@
+/* XPM */
+static char * FILE_xpm[] = {
+"16 16 16 1",
+" 	c None",
+".	c #000000",
+"+	c #D5FFFF",
+"@	c #F7F7F7",
+"#	c #8092AA",
+"$	c #646464",
+"%	c #AADBFF",
+"&	c #F0F0F0",
+"*	c #E8E8E8",
+"=	c #D5DBFF",
+"-	c #5592AA",
+";	c #E0E0E0",
+">	c #2B92FF",
+",	c #2B6DAA",
+"'	c #556DAA",
+")	c #55DBFF",
+"                ",
+"  #########-    ",
+"  #@@@@@@@#)$   ",
+"  #@@@@@@@>>,$  ",
+"  #@@@@@@&==%-$ ",
+"  #@@@@@@@+++=$ ",
+"  #@@@@@@&+++=$ ",
+"  #&&@*++%+++=$ ",
+"  #&&&*++++++%$ ",
+"  #**++%%%+++%$ ",
+"  #**++++%%++%$ ",
+"  -;;++%%%%%%%$ ",
+"  -;+++++%%%%%$ ",
+"  '###########$ ",
+"   $$$$$$$$$$$$ ",
+"                "};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gtk/FOLDER.xpm	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,29 @@
+/* XPM */
+static char * FOLDER_xpm[] = {
+"16 16 10 1",
+" 	c None",
+".	c #000000",
+"+	c #AA9200",
+"@	c #FFFFAA",
+"#	c #FFDB55",
+"$	c #AA6D00",
+"%	c #F7F7F7",
+"&	c #D59255",
+"*	c #FFDBAA",
+"=	c #D5B655",
+"                ",
+"  &&&&          ",
+" &%%%%&         ",
+"&%@@@@%+++++$   ",
+"&@@@@@@%%%%%$   ",
+"&@*++++++++++++ ",
+"&#+%%%%%%%%%*%+$",
+"&#+@@@@@@@@@#@+$",
+"&#+@@@@@@@@@.@+$",
+"&#+@@**@**@@=@+$",
+"&#+@########=@+$",
+"&#+@########=@+$",
+" ++++++++++++++$",
+"  $$$$$$$$$$$$$ ",
+"                ",
+"                "};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gtk/dw.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,8512 @@
+/*
+ * Dynamic Windows:
+ *          A GTK like implementation of the PM GUI
+ *          GTK forwarder module for portabilty.
+ *
+ * (C) 2000-2003 Brian Smith <dbsoft@technologist.com>
+ * (C) 2003 Mark Hessling <m.hessling@qut.edu.au>
+ *
+ */
+#include "dw.h"
+#include <string.h>
+#include <stdlib.h>
+#include <sys/utsname.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include "config.h"
+#include <gdk/gdkkeysyms.h>
+#ifdef USE_IMLIB
+#include <gdk_imlib.h>
+#endif
+#if GTK_MAJOR_VERSION > 1
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#endif
+
+#include "gtk/messagebox_error.xpm"
+#include "gtk/messagebox_warning.xpm"
+#include "gtk/messagebox_information.xpm"
+#include "gtk/messagebox_question.xpm"
+
+/* These are used for resource management */
+#if defined(DW_RESOURCES) && !defined(BUILD_DLL)
+extern DWResources _resources;
+#endif
+
+GdkColor _colors[] =
+{
+	{ 0, 0x0000, 0x0000, 0x0000 },	/* 0  black */
+	{ 0, 0xbbbb, 0x0000, 0x0000 },	/* 1  red */
+	{ 0, 0x0000, 0xbbbb, 0x0000 },	/* 2  green */
+	{ 0, 0xaaaa, 0xaaaa, 0x0000 },	/* 3  yellow */
+	{ 0, 0x0000, 0x0000, 0xcccc },	/* 4  blue */
+	{ 0, 0xbbbb, 0x0000, 0xbbbb },	/* 5  magenta */
+	{ 0, 0x0000, 0xbbbb, 0xbbbb },	/* 6  cyan */
+	{ 0, 0xbbbb, 0xbbbb, 0xbbbb },	/* 7  white */
+	{ 0, 0x7777, 0x7777, 0x7777 },	/* 8  grey */
+	{ 0, 0xffff, 0x0000, 0x0000 },	/* 9  bright red */
+	{ 0, 0x0000, 0xffff, 0x0000 },	/* 10 bright green */
+	{ 0, 0xeeee, 0xeeee, 0x0000 },	/* 11 bright yellow */
+	{ 0, 0x0000, 0x0000, 0xffff },	/* 12 bright blue */
+	{ 0, 0xffff, 0x0000, 0xffff },	/* 13 bright magenta */
+	{ 0, 0x0000, 0xeeee, 0xeeee },	/* 14 bright cyan */
+	{ 0, 0xffff, 0xffff, 0xffff },	/* 15 bright white */
+};
+
+#define DW_THREAD_LIMIT 50
+
+#ifndef max
+# define max(a,b)        (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifndef min
+# define min(a,b)        (((a) < (b)) ? (a) : (b))
+#endif
+
+DWTID _dw_thread_list[DW_THREAD_LIMIT];
+GdkColor _foreground[DW_THREAD_LIMIT];
+GdkColor _background[DW_THREAD_LIMIT];
+int _transparent[DW_THREAD_LIMIT];
+
+GtkWidget *last_window = NULL, *popup = NULL;
+
+static int _dw_file_active = 0, _dw_ignore_click = 0, _dw_ignore_expand = 0;
+static pthread_t _dw_thread = (pthread_t)-1;
+static int _dw_mutex_locked[DW_THREAD_LIMIT];
+/* Use default border size for the default enlightenment theme */
+static int _dw_border_width = 12, _dw_border_height = 28;
+
+#define  DW_MUTEX_LOCK { int index = _find_thread_index(dw_thread_id()); if(pthread_self() != _dw_thread && _dw_mutex_locked[index] == FALSE) { gdk_threads_enter(); _dw_mutex_locked[index] = TRUE; _locked_by_me = TRUE;  } }
+#define  DW_MUTEX_UNLOCK { if(pthread_self() != _dw_thread && _locked_by_me == TRUE) { gdk_threads_leave(); _dw_mutex_locked[_find_thread_index(dw_thread_id())] = FALSE; _locked_by_me = FALSE; } }
+
+#define DEFAULT_SIZE_WIDTH 12
+#define DEFAULT_SIZE_HEIGHT 6
+#define DEFAULT_TITLEBAR_HEIGHT 22
+
+static GdkColormap *_dw_cmap = NULL;
+
+/* Signal forwarder prototypes */
+static gint _button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data);
+static gint _button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer data);
+static gint _motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data);
+static gint _delete_event(GtkWidget *widget, GdkEvent *event, gpointer data);
+static gint _key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data);
+static gint _generic_event(GtkWidget *widget, gpointer data);
+static gint _configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer data);
+static gint _activate_event(GtkWidget *widget, gpointer data);
+static gint _container_select_event(GtkWidget *widget, GdkEventButton *event, gpointer data);
+static gint _container_context_event(GtkWidget *widget, GdkEventButton *event, gpointer data);
+static gint _item_select_event(GtkWidget *widget, GtkWidget *child, gpointer data);
+static gint _expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data);
+static gint _set_focus_event(GtkWindow *window, GtkWidget *widget, gpointer data);
+static gint _tree_context_event(GtkWidget *widget, GdkEventButton *event, gpointer data);
+static gint _value_changed_event(GtkAdjustment *adjustment, gpointer user_data);
+#if GTK_MAJOR_VERSION > 1
+static gint _tree_select_event(GtkTreeSelection *sel, gpointer data);
+static gint _tree_expand_event(GtkTreeView *treeview, GtkTreeIter *arg1, GtkTreePath *arg2, gpointer data);
+#else
+static gint _tree_select_event(GtkTree *tree, GtkWidget *child, gpointer data);
+static gint _tree_expand_event(GtkTreeItem *treeitem, gpointer data);
+#endif
+static gint _switch_page_event(GtkNotebook *notebook, GtkNotebookPage *page, guint page_num, gpointer data);
+static gint _column_click_event(GtkWidget *widget, gint column_num, gpointer data);
+
+typedef struct
+{
+	GdkPixmap *pixmap;
+	GdkBitmap *mask;
+	int used;
+	unsigned long width, height;
+#if GTK_MAJOR_VERSION > 1
+	GdkPixbuf *pixbuf;
+#endif
+} DWPrivatePixmap;
+
+static DWPrivatePixmap *_PixmapArray = NULL;
+static int _PixmapCount = 0;
+
+typedef struct
+{
+	void *func;
+	char name[30];
+
+} SignalList;
+
+typedef struct
+{
+	HWND window;
+	void *func;
+	gpointer data;
+	gint cid;
+	void *intfunc;
+
+} SignalHandler;
+
+#define SIGNALMAX 19
+
+/* A list of signal forwarders, to account for paramater differences. */
+static SignalList SignalTranslate[SIGNALMAX] = {
+	{ _configure_event,         DW_SIGNAL_CONFIGURE },
+	{ _key_press_event,         DW_SIGNAL_KEY_PRESS },
+	{ _button_press_event,      DW_SIGNAL_BUTTON_PRESS },
+	{ _button_release_event,    DW_SIGNAL_BUTTON_RELEASE },
+	{ _motion_notify_event,     DW_SIGNAL_MOTION_NOTIFY },
+	{ _delete_event,            DW_SIGNAL_DELETE },
+	{ _expose_event,            DW_SIGNAL_EXPOSE },
+	{ _activate_event,          "activate" },
+	{ _generic_event,           DW_SIGNAL_CLICKED },
+	{ _container_select_event,  DW_SIGNAL_ITEM_ENTER },
+	{ _container_context_event, DW_SIGNAL_ITEM_CONTEXT },
+	{ _tree_context_event,      "tree-context" },
+	{ _item_select_event,       DW_SIGNAL_LIST_SELECT },
+	{ _tree_select_event,       DW_SIGNAL_ITEM_SELECT },
+	{ _set_focus_event,         DW_SIGNAL_SET_FOCUS },
+	{ _value_changed_event,     DW_SIGNAL_VALUE_CHANGED },
+	{ _switch_page_event,       DW_SIGNAL_SWITCH_PAGE },
+	{ _column_click_event,      DW_SIGNAL_COLUMN_CLICK },
+	{ _tree_expand_event,       DW_SIGNAL_TREE_EXPAND }
+};
+
+/* Alignment flags */
+#define DW_CENTER 0.5f
+#define DW_LEFT 0.0f
+#define DW_RIGHT 1.0f
+
+static void _dw_msleep(long period)
+{
+#ifdef __sun__
+	/* usleep() isn't threadsafe on Solaris */
+	struct timespec req;
+
+	req.tv_sec = 0;
+	req.tv_nsec = period * 10000000;
+
+	nanosleep(&req, NULL);
+#else
+	usleep(period * 1000);
+#endif
+}
+
+/* Finds the translation function for a given signal name */
+static void *_findsigfunc(char *signame)
+{
+	int z;
+
+	for(z=0;z<SIGNALMAX;z++)
+	{
+		if(strcasecmp(signame, SignalTranslate[z].name) == 0)
+			return SignalTranslate[z].func;
+	}
+	return NULL;
+}
+
+static SignalHandler _get_signal_handler(GtkWidget *widget, gpointer data)
+{
+	int counter = (int)data;
+	SignalHandler sh;
+	char text[100];
+
+	sprintf(text, "_dw_sigwindow%d", counter);
+	sh.window = (HWND)gtk_object_get_data(GTK_OBJECT(widget), text);
+	sprintf(text, "_dw_sigfunc%d", counter);
+	sh.func = (void *)gtk_object_get_data(GTK_OBJECT(widget), text);
+	sprintf(text, "_dw_intfunc%d", counter);
+	sh.intfunc = (void *)gtk_object_get_data(GTK_OBJECT(widget), text);
+	sprintf(text, "_dw_sigdata%d", counter);
+	sh.data = gtk_object_get_data(GTK_OBJECT(widget), text);
+	sprintf(text, "_dw_sigcid%d", counter);
+	sh.cid = (gint)gtk_object_get_data(GTK_OBJECT(widget), text);
+
+	return sh;
+}
+
+static void _remove_signal_handler(GtkWidget *widget, int counter)
+{
+	char text[100];
+	gint cid;
+
+	sprintf(text, "_dw_sigcid%d", counter);
+	cid = (gint)gtk_object_get_data(GTK_OBJECT(widget), text);
+	gtk_signal_disconnect(GTK_OBJECT(widget), cid);
+	gtk_object_set_data(GTK_OBJECT(widget), text, NULL);
+	sprintf(text, "_dw_sigwindow%d", counter);
+	gtk_object_set_data(GTK_OBJECT(widget), text, NULL);
+	sprintf(text, "_dw_sigfunc%d", counter);
+	gtk_object_set_data(GTK_OBJECT(widget), text, NULL);
+	sprintf(text, "_dw_intfunc%d", counter);
+	gtk_object_set_data(GTK_OBJECT(widget), text, NULL);
+	sprintf(text, "_dw_sigdata%d", counter);
+	gtk_object_set_data(GTK_OBJECT(widget), text, NULL);
+}
+
+static int _set_signal_handler(GtkWidget *widget, HWND window, void *func, gpointer data, void *intfunc)
+{
+	int counter = (int)gtk_object_get_data(GTK_OBJECT(widget), "_dw_sigcounter");
+	char text[100];
+
+	sprintf(text, "_dw_sigwindow%d", counter);
+	gtk_object_set_data(GTK_OBJECT(widget), text, (gpointer)window);
+	sprintf(text, "_dw_sigfunc%d", counter);
+	gtk_object_set_data(GTK_OBJECT(widget), text, (gpointer)func);
+	sprintf(text, "_dw_intfunc%d", counter);
+	gtk_object_set_data(GTK_OBJECT(widget), text, (gpointer)intfunc);
+	sprintf(text, "_dw_sigdata%d", counter);
+	gtk_object_set_data(GTK_OBJECT(widget), text, (gpointer)data);
+
+	counter++;
+	gtk_object_set_data(GTK_OBJECT(widget), "_dw_sigcounter", (gpointer)counter);
+
+	return counter - 1;
+}
+
+static void _set_signal_handler_id(GtkWidget *widget, int counter, gint cid)
+{
+	char text[100];
+
+	sprintf(text, "_dw_sigcid%d", counter);
+	gtk_object_set_data(GTK_OBJECT(widget), text, (gpointer)cid);
+}
+
+static gint _set_focus_event(GtkWindow *window, GtkWidget *widget, gpointer data)
+{
+	SignalHandler work = _get_signal_handler((GtkWidget *)window, data);
+	int retval = FALSE;
+
+	if(work.window)
+	{
+		int (*setfocusfunc)(HWND, void *) = work.func;
+
+		retval = setfocusfunc(work.window, work.data);
+	}
+	return retval;
+}
+
+static gint _button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+	SignalHandler work = _get_signal_handler(widget, data);
+	int retval = FALSE;
+
+	if(work.window)
+	{
+		int (*buttonfunc)(HWND, int, int, int, void *) = work.func;
+		int mybutton = event->button;
+
+		if(event->button == 3)
+			mybutton = 2;
+		else if(event->button == 2)
+			mybutton = 3;
+
+		retval = buttonfunc(work.window, event->x, event->y, mybutton, work.data);
+	}
+	return retval;
+}
+
+static gint _button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+	SignalHandler work = _get_signal_handler(widget, data);
+	int retval = FALSE;
+
+	if(work.window)
+	{
+		int (*buttonfunc)(HWND, int, int, int, void *) = work.func;
+		int mybutton = event->button;
+
+		if(event->button == 3)
+			mybutton = 2;
+		else if(event->button == 2)
+			mybutton = 3;
+
+		retval = buttonfunc(work.window, event->x, event->y, mybutton, work.data);
+	}
+	return retval;
+}
+
+static gint _motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data)
+{
+	SignalHandler work = _get_signal_handler(widget, data);
+	int retval = FALSE;
+
+	if(work.window)
+	{
+		int (*motionfunc)(HWND, int, int, int, void *) = work.func;
+		int keys = 0, x, y;
+		GdkModifierType state;
+
+		if (event->is_hint)
+			gdk_window_get_pointer (event->window, &x, &y, &state);
+		else
+		{
+			x = event->x;
+			y = event->y;
+			state = event->state;
+		}
+
+		if (state & GDK_BUTTON1_MASK)
+			keys = DW_BUTTON1_MASK;
+		if (state & GDK_BUTTON3_MASK)
+			keys |= DW_BUTTON2_MASK;
+		if (state & GDK_BUTTON2_MASK)
+			keys |= DW_BUTTON3_MASK;
+
+		retval = motionfunc(work.window, x, y, keys, work.data);
+	}
+	return retval;
+}
+
+static gint _delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+	SignalHandler work = _get_signal_handler(widget, data);
+	int retval = FALSE;
+
+	if(work.window)
+	{
+		int (*closefunc)(HWND, void *) = work.func;
+
+		retval = closefunc(work.window, work.data);
+	}
+	return retval;
+}
+
+static gint _key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+	SignalHandler work = _get_signal_handler(widget, data);
+	int retval = FALSE;
+
+	if(work.window)
+	{
+		int (*keypressfunc)(HWND, char, int, int, void *) = work.func;
+
+		retval = keypressfunc(work.window, *event->string, event->keyval,
+							  event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK), work.data);
+	}
+	return retval;
+}
+
+static gint _generic_event(GtkWidget *widget, gpointer data)
+{
+	SignalHandler work = _get_signal_handler(widget, data);
+	int retval = FALSE;
+
+	if(work.window)
+	{
+		int (*genericfunc)(HWND, void *) = work.func;
+
+		retval = genericfunc(work.window, work.data);
+	}
+	return retval;
+}
+
+static gint _activate_event(GtkWidget *widget, gpointer data)
+{
+	SignalHandler work = _get_signal_handler(widget, data);
+	int retval = FALSE;
+
+	if(work.window && !_dw_ignore_click)
+	{
+		int (*activatefunc)(HWND, void *) = work.func;
+
+		retval = activatefunc(popup ? popup : work.window, work.data);
+	}
+	return retval;
+}
+
+static gint _configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
+{
+	SignalHandler work = _get_signal_handler(widget, data);
+	int retval = FALSE;
+
+	if(work.window)
+	{
+		int (*sizefunc)(HWND, int, int, void *) = work.func;
+
+		retval = sizefunc(work.window, event->width, event->height, work.data);
+	}
+	return retval;
+}
+
+static gint _expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
+{
+	SignalHandler work = _get_signal_handler(widget, data);
+	int retval = FALSE;
+
+	if(work.window)
+	{
+		DWExpose exp;
+		int (*exposefunc)(HWND, DWExpose *, void *) = work.func;
+
+		exp.x = event->area.x;
+		exp.y = event->area.y;
+		exp.width = event->area.width;
+		exp.height = event->area.height;
+		retval = exposefunc(work.window, &exp, work.data);
+	}
+	return retval;
+}
+
+static gint _item_select_event(GtkWidget *widget, GtkWidget *child, gpointer data)
+{
+	SignalHandler work = _get_signal_handler(widget, data);
+	static int _dw_recursing = 0;
+	int retval = FALSE;
+
+	if(_dw_recursing)
+		return FALSE;
+
+	if(work.window)
+	{
+		int (*selectfunc)(HWND, int, void *) = work.func;
+		GList *list;
+		int item = 0;
+
+		_dw_recursing = 1;
+
+		if(GTK_IS_COMBO(work.window))
+			list = GTK_LIST(GTK_COMBO(work.window)->list)->children;
+		else if(GTK_IS_LIST(widget))
+			list = GTK_LIST(widget)->children;
+		else
+			return FALSE;
+
+		while(list)
+		{
+			if(list->data == (gpointer)child)
+			{
+				if(!gtk_object_get_data(GTK_OBJECT(work.window), "_dw_appending"))
+				{
+					gtk_object_set_data(GTK_OBJECT(work.window), "_dw_item", (gpointer)item);
+					if(selectfunc)
+						retval = selectfunc(work.window, item, work.data);
+				}
+				break;
+			}
+			item++;
+			list = list->next;
+		}
+		_dw_recursing = 0;
+	}
+	return retval;
+}
+
+static gint _container_context_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+	SignalHandler work = _get_signal_handler(widget, data);
+	int retval = FALSE;
+
+	if(work.window)
+	{
+		if(event->button == 3)
+		{
+			int (*contextfunc)(HWND, char *, int, int, void *, void *) = work.func;
+			char *text;
+			int row, col;
+
+			gtk_clist_get_selection_info(GTK_CLIST(widget), event->x, event->y, &row, &col);
+
+			text = (char *)gtk_clist_get_row_data(GTK_CLIST(widget), row);
+			retval = contextfunc(work.window, text, event->x, event->y, work.data, NULL);
+		}
+	}
+	return retval;
+}
+
+static gint _tree_context_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+	SignalHandler work = _get_signal_handler(widget, data);
+	int retval = FALSE;
+
+	if(work.window)
+	{
+		if(event->button == 3)
+		{
+#if GTK_MAJOR_VERSION > 1
+			int (*contextfunc)(HWND, char *, int, int, void *, void *) = work.func;
+			char *text = NULL;
+			void *itemdata = NULL;
+
+			if(widget && GTK_IS_TREE_VIEW(widget))
+			{
+				GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
+				GtkTreeIter iter;
+        
+				if(sel && gtk_tree_selection_get_selected(sel, NULL, &iter))
+				{
+					GtkTreeModel *store = (GtkTreeModel *)gtk_object_get_data(GTK_OBJECT(widget), "_dw_tree_store");
+					gtk_tree_model_get(store, &iter, 0, &text, 2, &itemdata, -1);
+				}
+			}
+
+			retval = contextfunc(work.window, text, event->x, event->y, work.data, itemdata);
+#else
+			int (*contextfunc)(HWND, char *, int, int, void *, void *) = work.func;
+			char *text = (char *)gtk_object_get_data(GTK_OBJECT(widget), "_dw_text");
+			void *itemdata = (void *)gtk_object_get_data(GTK_OBJECT(widget), "_dw_itemdata");
+
+			if(widget != work.window)
+			{
+				GtkWidget *tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(work.window));
+
+				if(tree && GTK_IS_TREE(tree))
+				{
+					GtkWidget *lastselect = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_lastselect");
+
+					if(lastselect && GTK_IS_TREE_ITEM(lastselect))
+					{
+						text = (char *)gtk_object_get_data(GTK_OBJECT(lastselect), "_dw_text");
+						itemdata = (void *)gtk_object_get_data(GTK_OBJECT(lastselect), "_dw_itemdata");
+					}
+				}
+			}
+
+			retval = contextfunc(work.window, text, event->x, event->y, work.data, itemdata);
+#endif
+		}
+	}
+	return retval;
+}
+
+#if GTK_MAJOR_VERSION > 1
+static gint _tree_select_event(GtkTreeSelection *sel, gpointer data)
+{
+	GtkWidget *item, *widget = (GtkWidget *)gtk_tree_selection_get_tree_view(sel);
+	int retval = FALSE;
+
+	if(widget)
+	{
+		SignalHandler work = _get_signal_handler(widget, data);
+
+		if(work.window)
+		{
+			int (*treeselectfunc)(HWND, HTREEITEM, char *, void *, void *) = work.func;
+			GtkTreeIter iter;
+			char *text = NULL;
+			void *itemdata = NULL;
+
+			if(gtk_tree_selection_get_selected(sel, NULL, &iter))
+			{
+				GtkTreeModel *store = (GtkTreeModel *)gtk_object_get_data(GTK_OBJECT(widget), "_dw_tree_store");
+				gtk_tree_model_get(store, &iter, 0, &text, 2, &itemdata, 3, &item, -1);
+				retval = treeselectfunc(work.window, (HTREEITEM)item, text, work.data, itemdata);
+			}
+		}
+	}
+	return retval;
+}
+
+static gint _tree_expand_event(GtkTreeView *widget, GtkTreeIter *iter, GtkTreePath *path, gpointer data)
+{
+	SignalHandler work = _get_signal_handler((GtkWidget *)widget, data);
+	int retval = FALSE;
+
+	if(!_dw_ignore_expand && work.window)
+	{
+		int (*treeexpandfunc)(HWND, HTREEITEM, void *) = work.func;
+		retval = treeexpandfunc(work.window, (HTREEITEM)iter, work.data);
+	}
+	return retval;
+}
+#else
+static gint _tree_select_event(GtkTree *tree, GtkWidget *child, gpointer data)
+{
+	SignalHandler work = _get_signal_handler((GtkWidget *)tree, data);
+	GtkWidget *treeroot = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(child), "_dw_tree");
+	int retval = FALSE;
+
+	if(treeroot && GTK_IS_TREE(treeroot))
+	{
+		GtkWidget *lastselect = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(treeroot), "_dw_lastselect");
+		if(lastselect && GTK_IS_TREE_ITEM(lastselect))
+			gtk_tree_item_deselect(GTK_TREE_ITEM(lastselect));
+		gtk_object_set_data(GTK_OBJECT(treeroot), "_dw_lastselect", (gpointer)child);
+	}
+
+	if(work.window)
+	{
+		int (*treeselectfunc)(HWND, HTREEITEM, char *, void *, void *) = work.func;
+		char *text = (char *)gtk_object_get_data(GTK_OBJECT(child), "_dw_text");
+		void *itemdata = (void *)gtk_object_get_data(GTK_OBJECT(child), "_dw_itemdata");
+		retval = treeselectfunc(work.window, (HTREEITEM)child, text, work.data, itemdata);
+	}
+	return retval;
+}
+
+static gint _tree_expand_event(GtkTreeItem *treeitem, gpointer data)
+{
+	SignalHandler work = _get_signal_handler((GtkWidget *)treeitem, data);
+	int retval = FALSE;
+
+	if(!_dw_ignore_expand && work.window)
+	{
+		int (*treeexpandfunc)(HWND, HTREEITEM, void *) = work.func;
+		retval = treeexpandfunc(work.window, (HTREEITEM)treeitem, work.data);
+	}
+	return retval;
+}
+#endif
+
+static gint _container_select_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+	SignalHandler work = _get_signal_handler(widget, data);
+	int retval = FALSE;
+
+	if(work.window)
+	{
+		if(event->button == 1 && event->type == GDK_2BUTTON_PRESS)
+		{
+			int (*contextfunc)(HWND, char *, void *) = work.func;
+			char *text;
+			int row, col;
+
+			gtk_clist_get_selection_info(GTK_CLIST(widget), event->x, event->y, &row, &col);
+
+			text = (char *)gtk_clist_get_row_data(GTK_CLIST(widget), row);
+			retval = contextfunc(work.window, text, work.data);
+			gtk_object_set_data(GTK_OBJECT(widget), "_dw_double_click", (gpointer)1);
+		}
+	}
+	return retval;
+}
+
+static gint _container_enter_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+	SignalHandler work = _get_signal_handler(widget, data);
+	int retval = FALSE;
+
+	if(work.window && event->keyval == VK_RETURN)
+	{
+		int (*contextfunc)(HWND, char *, void *) = work.func;
+		char *text;
+
+		text = (char *)gtk_clist_get_row_data(GTK_CLIST(widget), GTK_CLIST(widget)->focus_row);
+		retval = contextfunc(work.window, text, work.data);
+	}
+	return retval;
+}
+
+/* Return the logical page id from the physical page id */
+int _get_logical_page(HWND handle, unsigned long pageid)
+{
+	int z;
+	GtkWidget **pagearray = gtk_object_get_data(GTK_OBJECT(handle), "_dw_pagearray");
+	GtkWidget *thispage = gtk_notebook_get_nth_page(GTK_NOTEBOOK(handle), pageid);
+  
+	if(pagearray && thispage)
+	{
+		for(z=0;z<256;z++)
+		{
+			if(thispage == pagearray[z])
+				return z;
+		}
+	}
+	return 256;
+}
+
+
+static gint _switch_page_event(GtkNotebook *notebook, GtkNotebookPage *page, guint page_num, gpointer data)
+{
+	SignalHandler work = _get_signal_handler((GtkWidget *)notebook, data);
+	int retval = FALSE;
+
+	if(work.window)
+	{
+		int (*switchpagefunc)(HWND, unsigned long, void *) = work.func;
+		retval = switchpagefunc(work.window, _get_logical_page(GTK_WIDGET(notebook), page_num), work.data);
+	}
+	return retval;
+}
+
+static gint _column_click_event(GtkWidget *widget, gint column_num, gpointer data)
+{
+	SignalHandler work = _get_signal_handler(widget, data);
+	int retval = FALSE;
+
+	if(work.window)
+	{
+		int (*clickcolumnfunc)(HWND, int, void *) = work.func;
+		retval = clickcolumnfunc(work.window, column_num, work.data);
+	}
+	return retval;
+}
+
+static gint _container_select_row(GtkWidget *widget, gint row, gint column, GdkEventButton *event, gpointer data)
+{
+	SignalHandler work = _get_signal_handler(widget, data);
+	char *rowdata = gtk_clist_get_row_data(GTK_CLIST(widget), row);
+	int (*contextfunc)(HWND, HWND, char *, void *, void *) = work.func;
+
+	if(!work.window)
+		return TRUE;
+
+	if(gtk_object_get_data(GTK_OBJECT(widget), "_dw_double_click"))
+	{
+		gtk_object_set_data(GTK_OBJECT(widget), "_dw_double_click", (gpointer)0);
+		return TRUE;
+	}
+	return contextfunc(work.window, 0, rowdata, work.data, 0);;
+}
+
+static int _round_value(gfloat val)
+{
+	int newval = (int)val;
+
+	if(val >= 0.5 + (gfloat)newval)
+		newval++;
+
+	return newval;
+}
+
+static gint _value_changed_event(GtkAdjustment *adjustment, gpointer data)
+{
+	int max = _round_value(adjustment->upper);
+	int val = _round_value(adjustment->value);
+	GtkWidget *slider = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(adjustment), "_dw_slider");
+	GtkWidget *scrollbar = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(adjustment), "_dw_scrollbar");
+
+	if(slider)
+	{
+		SignalHandler work = _get_signal_handler((GtkWidget *)adjustment, data);
+
+		if(work.window)
+		{
+			int (*valuechangedfunc)(HWND, int, void *) = work.func;
+
+			if(GTK_IS_VSCALE(slider))
+				valuechangedfunc(work.window, (max - val) - 1,  work.data);
+			else
+				valuechangedfunc(work.window, val,  work.data);
+		}
+	}
+	else if(scrollbar)
+	{
+		SignalHandler work = _get_signal_handler((GtkWidget *)adjustment, data);
+
+		if(work.window)
+		{
+			int (*valuechangedfunc)(HWND, int, void *) = work.func;
+
+			valuechangedfunc(work.window, val,  work.data);
+		}
+	}
+	return FALSE;
+}
+
+static gint _default_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+	GtkWidget *next = (GtkWidget *)data;
+
+	if(next)
+	{
+		if(event->keyval == GDK_Return)
+		{
+			if(GTK_IS_BUTTON(next))
+				gtk_signal_emit_by_name(GTK_OBJECT(next), "clicked");
+			else
+				gtk_widget_grab_focus(next);
+		}
+	}
+	return FALSE;
+}
+
+static GdkPixmap *_find_private_pixmap(GdkBitmap **bitmap, long id, unsigned long *userwidth, unsigned long *userheight)
+{
+	if(id < _PixmapCount && _PixmapArray[id].used)
+	{
+		*bitmap = _PixmapArray[id].mask;
+		if(userwidth)
+			*userwidth = _PixmapArray[id].width;
+		if(userheight)
+			*userheight = _PixmapArray[id].height;
+		return _PixmapArray[id].pixmap;
+	}
+	return NULL;
+}
+
+static GdkPixmap *_find_pixmap(GdkBitmap **bitmap, long id, HWND handle, unsigned long *userwidth, unsigned long *userheight)
+{
+	char *data = NULL;
+	int z;
+
+	if(id & (1 << 31))
+		return _find_private_pixmap(bitmap, (id & 0xFFFFFF), userwidth, userheight);
+
+	for(z=0;z<_resources.resource_max;z++)
+	{
+		if(_resources.resource_id[z] == id)
+		{
+			data = _resources.resource_data[z];
+			break;
+		}
+	}
+
+	if(data)
+	{
+		GdkPixmap *icon_pixmap = NULL;
+#if GTK_MAJOR_VERSION > 1
+		GdkPixbuf *icon_pixbuf = gdk_pixbuf_new_from_xpm_data((const char **)data);
+
+		if(userwidth)
+			*userwidth = gdk_pixbuf_get_width(icon_pixbuf);
+		if(userheight)
+			*userheight = gdk_pixbuf_get_height(icon_pixbuf);
+      
+		gdk_pixbuf_render_pixmap_and_mask(icon_pixbuf, &icon_pixmap, bitmap, 1);
+		g_object_unref(icon_pixbuf);
+#elif defined(USE_IMLIB)
+		gdk_imlib_data_to_pixmap((char **)data, &icon_pixmap, bitmap);
+#else
+		icon_pixmap = gdk_pixmap_create_from_xpm_d(handle->window, bitmap, &_colors[DW_CLR_PALEGRAY], (char **)data);
+#endif
+		return icon_pixmap;
+	}
+	return NULL;
+}
+
+#if GTK_MAJOR_VERSION > 1
+static GdkPixbuf *_find_private_pixbuf(long id)
+{
+	if(id < _PixmapCount && _PixmapArray[id].used)
+		return _PixmapArray[id].pixbuf;
+	return NULL;
+}
+
+static GdkPixbuf *_find_pixbuf(long id)
+{
+	char *data = NULL;
+	int z;
+
+	if(id & (1 << 31))
+		return _find_private_pixbuf((id & 0xFFFFFF));
+
+	for(z=0;z<_resources.resource_max;z++)
+	{
+		if(_resources.resource_id[z] == id)
+		{
+			data = _resources.resource_data[z];
+			break;
+		}
+	}
+
+	if(data)
+		return gdk_pixbuf_new_from_xpm_data((const char **)data);
+	return NULL;
+}
+#endif
+
+static void _size_allocate(GtkWindow *window)
+{
+  XSizeHints sizehints;
+
+  sizehints.base_width = 1;
+  sizehints.base_height = 1;
+  sizehints.width_inc = 1;
+  sizehints.height_inc = 1;
+  sizehints.min_width = 8;
+  sizehints.min_height = 8;
+  
+  sizehints.flags = (PBaseSize|PMinSize|PResizeInc);
+  
+  XSetWMNormalHints (GDK_DISPLAY(),
+		     GDK_WINDOW_XWINDOW (GTK_WIDGET (window)->window),
+		     &sizehints);
+  gdk_flush ();
+}
+
+/* Find the index of a given thread */
+static int _find_thread_index(DWTID tid)
+{
+	int z;
+
+	for(z=0;z<DW_THREAD_LIMIT;z++)
+	{
+		if(_dw_thread_list[z] == tid)
+			return z;
+	}
+	return 0;
+}
+
+/* Add a thread id to the thread list */
+static void _dw_thread_add(DWTID tid)
+{
+	int z;
+
+	for(z=0;z<DW_THREAD_LIMIT;z++)
+	{
+		if(_dw_thread_list[z] == tid)
+			return;
+
+		if(_dw_thread_list[z] == (DWTID)-1)
+		{
+			_dw_thread_list[z] = tid;
+			_foreground[z].pixel = _foreground[z].red =_foreground[z].green = _foreground[z].blue = 0;
+			_background[z].pixel = 1;
+			_background[z].red = _background[z].green = _background[z].blue = 0;
+			_transparent[z] = 1;
+			return;
+		}
+	}
+}
+
+/* Remove a thread id to the thread list */
+static void _dw_thread_remove(DWTID tid)
+{
+	int z;
+
+	for(z=0;z<DW_THREAD_LIMIT;z++)
+	{
+		if(_dw_thread_list[z] == (DWTID)tid)
+			_dw_thread_list[z] = (DWTID)-1;
+	}
+}
+
+/*
+ * Initializes the Dynamic Windows engine.
+ * Parameters:
+ *           newthread: True if this is the only thread.
+ *                      False if there is already a message loop running.
+ */
+int dw_int_init(DWResources *res, int newthread, int *argc, char **argv[])
+{
+	int z;
+	char *tmp;
+
+	if(res)
+	{
+		_resources.resource_max = res->resource_max;
+		_resources.resource_id = res->resource_id;
+		_resources.resource_data = res->resource_data;
+	}
+	gtk_set_locale();
+	g_thread_init(NULL);
+#if GTK_MAJOR_VERSION > 1
+	gdk_threads_init();
+#endif
+
+	gtk_init(argc, argv);
+#ifdef USE_IMLIB
+	gdk_imlib_init();
+#endif
+	/* Add colors to the system colormap */
+	_dw_cmap = gdk_colormap_get_system();
+	for(z=0;z<16;z++)
+		gdk_color_alloc(_dw_cmap, &_colors[z]);
+
+	tmp = getenv("DW_BORDER_WIDTH");
+	if(tmp)
+		_dw_border_width = atoi(tmp);
+	tmp = getenv("DW_BORDER_HEIGHT");
+	if(tmp)
+		_dw_border_height = atoi(tmp);
+
+	for(z=0;z<DW_THREAD_LIMIT;z++)
+		_dw_thread_list[z] = (DWTID)-1;
+
+	gtk_rc_parse_string("style \"gtk-tooltips-style\" { bg[NORMAL] = \"#eeee00\" } widget \"gtk-tooltips\" style \"gtk-tooltips-style\"");
+
+	return TRUE;
+}
+
+/*
+ * Runs a message loop for Dynamic Windows.
+ */
+void dw_main(void)
+{
+	gdk_threads_enter();
+	_dw_thread = pthread_self();
+	_dw_thread_add(_dw_thread);
+	gtk_main();
+	_dw_thread = (pthread_t)-1;
+	gdk_threads_leave();
+}
+
+/*
+ * Runs a message loop for Dynamic Windows, for a period of milliseconds.
+ * Parameters:
+ *           milliseconds: Number of milliseconds to run the loop for.
+ */
+void dw_main_sleep(int milliseconds)
+{
+	struct timeval tv, start;
+	pthread_t curr = pthread_self();
+
+	gettimeofday(&start, NULL);
+
+	if(_dw_thread == (pthread_t)-1 || _dw_thread == curr)
+	{
+		pthread_t orig = _dw_thread;
+
+		gettimeofday(&tv, NULL);
+
+		while(((tv.tv_sec - start.tv_sec)*1000) + ((tv.tv_usec - start.tv_usec)/1000) <= milliseconds)
+		{
+			if(orig == (pthread_t)-1)
+			{
+				gdk_threads_enter();
+				_dw_thread = curr;
+			}
+			if(gtk_events_pending())
+				gtk_main_iteration();
+			else
+				_dw_msleep(1);
+			if(orig == (pthread_t)-1)
+			{
+				_dw_thread = orig;
+				gdk_threads_leave();
+			}
+			gettimeofday(&tv, NULL);
+		}
+	}
+	else
+		_dw_msleep(milliseconds);
+}
+
+/*
+ * Processes a single message iteration and returns.
+ */
+void dw_main_iteration(void)
+{
+	gdk_threads_enter();
+	_dw_thread = pthread_self();
+	_dw_thread_add(_dw_thread);
+	gtk_main_iteration();
+	_dw_thread = (pthread_t)-1;
+	gdk_threads_leave();
+}
+
+/*
+ * Free's memory allocated by dynamic windows.
+ * Parameters:
+ *           ptr: Pointer to dynamic windows allocated
+ *                memory to be free()'d.
+ */
+void dw_free(void *ptr)
+{
+	free(ptr);
+}
+
+/*
+ * Allocates and initializes a dialog struct.
+ * Parameters:
+ *           data: User defined data to be passed to functions.
+ */
+DWDialog *dw_dialog_new(void *data)
+{
+	DWDialog *tmp = malloc(sizeof(DWDialog));
+
+	tmp->eve = dw_event_new();
+	dw_event_reset(tmp->eve);
+	tmp->data = data;
+	tmp->done = FALSE;
+	tmp->method = FALSE;
+	tmp->result = NULL;
+
+    return tmp;
+}
+
+/*
+ * Accepts a dialog struct and returns the given data to the
+ * initial called of dw_dialog_wait().
+ * Parameters:
+ *           dialog: Pointer to a dialog struct aquired by dw_dialog_new).
+ *           result: Data to be returned by dw_dialog_wait().
+ */
+int dw_dialog_dismiss(DWDialog *dialog, void *result)
+{
+	dialog->result = result;
+	if(dialog->method)
+		gtk_main_quit();
+	else
+		dw_event_post(dialog->eve);
+	dialog->done = TRUE;
+	return 0;
+}
+
+/*
+ * Accepts a dialog struct waits for dw_dialog_dismiss() to be
+ * called by a signal handler with the given dialog struct.
+ * Parameters:
+ *           dialog: Pointer to a dialog struct aquired by dw_dialog_new).
+ */
+void *dw_dialog_wait(DWDialog *dialog)
+{
+	void *tmp;
+	int newprocess = 0;
+
+	/* _dw_thread will be -1 if dw_main hasn't been run yet. */
+	if(_dw_thread == (pthread_t)-1)
+	{
+		_dw_thread = pthread_self();
+		newprocess = 1;
+		gdk_threads_enter();
+	}
+
+	if(pthread_self() == _dw_thread)
+	{
+		dialog->method = TRUE;
+		gtk_main();
+	}
+	else
+	{
+		dialog->method = FALSE;
+		dw_event_wait(dialog->eve, -1);
+	}
+
+	if(newprocess)
+	{
+		_dw_thread = (pthread_t)-1;
+		gdk_threads_leave();
+	}
+
+	dw_event_close(&dialog->eve);
+	tmp = dialog->result;
+	free(dialog);
+	return tmp;
+}
+
+static int _dw_ok_func(HWND window, void *data)
+{
+	DWDialog *dwwait = (DWDialog *)data;
+
+	if(!dwwait)
+		return FALSE;
+
+	dw_window_destroy((HWND)dwwait->data);
+	dw_dialog_dismiss((DWDialog *)data, (void *)DW_MB_RETURN_OK);
+	return FALSE;
+}
+
+int _dw_yes_func(HWND window, void *data)
+{
+	DWDialog *dwwait = (DWDialog *)data;
+
+	if(!dwwait)
+		return FALSE;
+
+	dw_window_destroy((HWND)dwwait->data);
+	dw_dialog_dismiss((DWDialog *)data, (void *)DW_MB_RETURN_YES);
+	return FALSE;
+}
+
+int _dw_no_func(HWND window, void *data)
+{
+	DWDialog *dwwait = (DWDialog *)data;
+
+	if(!dwwait)
+		return FALSE;
+
+	dw_window_destroy((HWND)dwwait->data);
+	dw_dialog_dismiss((DWDialog *)data, (void *)DW_MB_RETURN_NO);
+	return FALSE;
+}
+
+int _dw_cancel_func(HWND window, void *data)
+{
+	DWDialog *dwwait = (DWDialog *)data;
+
+	if(!dwwait)
+		return FALSE;
+
+	dw_window_destroy((HWND)dwwait->data);
+	dw_dialog_dismiss((DWDialog *)data, (void *)DW_MB_RETURN_CANCEL);
+	return FALSE;
+}
+
+/*
+ * Displays a Message Box with given text and title..
+ * Parameters:
+ *           title: The title of the message box.
+ *           flags: Defines buttons and icons to display
+ *           format: printf style format string.
+ *           ...: Additional variables for use in the format.
+ */
+int dw_messagebox(char *title, int flags, char *format, ...)
+{
+	HWND entrywindow, texttargetbox, imagetextbox, mainbox, okbutton, nobutton, yesbutton, cancelbutton, buttonbox, stext;
+	ULONG flStyle = DW_FCF_TITLEBAR | DW_FCF_SHELLPOSITION | DW_FCF_DLGBORDER;
+	DWDialog *dwwait;
+	va_list args;
+	char outbuf[1000];
+	char **xpm_data = NULL;
+	int x, y, extra_width=0,text_width,text_height;
+	int width,height;
+
+	va_start(args, format);
+	vsprintf(outbuf, format, args);
+	va_end(args);
+
+	entrywindow = dw_window_new(HWND_DESKTOP, title, flStyle);
+	mainbox = dw_box_new(DW_VERT, 10);
+	dw_box_pack_start(entrywindow, mainbox, 0, 0, TRUE, TRUE, 0);
+
+	/* determine if an icon is to be used - if so we need another HORZ box */
+	if((flags & DW_MB_ERROR) | (flags & DW_MB_WARNING) | (flags & DW_MB_INFORMATION) | (flags & DW_MB_QUESTION))
+	{
+		imagetextbox = dw_box_new(DW_HORZ, 0);
+		dw_box_pack_start(mainbox, imagetextbox, 0, 0, TRUE, TRUE, 2);
+		texttargetbox = imagetextbox;
+	}
+	else
+	{
+		imagetextbox = NULL;
+		texttargetbox = mainbox;
+	}
+
+	if(flags & DW_MB_ERROR)
+		xpm_data = (char **)_dw_messagebox_error;
+	else if(flags & DW_MB_WARNING)
+		xpm_data = (char **)_dw_messagebox_warning;
+	else if(flags & DW_MB_INFORMATION)
+		xpm_data = (char **)_dw_messagebox_information;
+	else if(flags & DW_MB_QUESTION)
+		xpm_data = (char **)_dw_messagebox_question;
+
+	if(xpm_data)
+		extra_width = 32;
+
+	if(texttargetbox == imagetextbox)
+	{
+		GdkPixmap *icon_pixmap = NULL;
+		GdkBitmap *bitmap = NULL;
+		HWND handle = dw_bitmap_new( 100 );
+#if GTK_MAJOR_VERSION > 1
+		GdkPixbuf *icon_pixbuf = gdk_pixbuf_new_from_xpm_data((const char **)xpm_data);
+
+		gdk_pixbuf_render_pixmap_and_mask(icon_pixbuf, &icon_pixmap, &bitmap, 1);
+		g_object_unref(icon_pixbuf);
+#elif defined(USE_IMLIB)
+		gdk_imlib_data_to_pixmap((char **)xpm_data, &icon_pixmap, &bitmap);
+#else
+		icon_pixmap = gdk_pixmap_create_from_xpm_d(handle->window, &bitmap, &_colors[DW_CLR_PALEGRAY], (char **)xpm_data);
+#endif
+
+#if GTK_MAJOR_VERSION > 1
+		gtk_image_set_from_pixmap(GTK_IMAGE(handle), icon_pixmap, bitmap);
+#else
+		gtk_pixmap_set(GTK_PIXMAP(handle), icon_pixmap, bitmap);
+#endif
+
+		dw_box_pack_start( texttargetbox, handle, 32, 32, FALSE, FALSE, 2);
+	}
+
+	/* Create text */
+	text_width = 240;
+	text_height = 0;
+	stext = dw_text_new(outbuf, 0);
+	dw_window_set_style(stext, DW_DT_WORDBREAK, DW_DT_WORDBREAK);
+	dw_font_text_extents(stext, NULL, outbuf, &width, &height);
+	height = height+3;
+	if(width < text_width)
+		text_height = height*2;
+	else if(width < text_width*2)
+		text_height = height*3;
+	else if(width < text_width*3)
+		text_height = height*4;
+	else /* width > (3*text_width) */
+	{
+		text_width = (width / 3) + 60;
+		text_height = height*4;
+	}
+	dw_box_pack_start(texttargetbox, stext, text_width, text_height, TRUE, TRUE, 2);
+
+	/* Buttons */
+	buttonbox = dw_box_new(DW_HORZ, 10);
+
+	dw_box_pack_start(mainbox, buttonbox, 0, 40, TRUE, FALSE, 0);
+
+	dwwait = dw_dialog_new((void *)entrywindow);
+
+	/* which buttons ? */
+	if(flags & DW_MB_OK)
+	{
+		okbutton = dw_button_new("Ok", 1001L);
+		dw_box_pack_start(buttonbox, okbutton, 50, 30, TRUE, FALSE, 2);
+		dw_signal_connect(okbutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_ok_func), (void *)dwwait);
+	}
+	else if(flags & DW_MB_OKCANCEL)
+	{
+		okbutton = dw_button_new("Ok", 1001L);
+		dw_box_pack_start(buttonbox, okbutton, 50, 30, TRUE, FALSE, 2);
+		dw_signal_connect(okbutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_ok_func), (void *)dwwait);
+		cancelbutton = dw_button_new("Cancel", 1002L);
+		dw_box_pack_start(buttonbox, cancelbutton, 50, 30, TRUE, FALSE, 2);
+		dw_signal_connect(cancelbutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_cancel_func), (void *)dwwait);
+	}
+	else if(flags & DW_MB_YESNO)
+	{
+		yesbutton = dw_button_new("Yes", 1001L);
+		dw_box_pack_start(buttonbox, yesbutton, 50, 30, TRUE, FALSE, 2);
+		dw_signal_connect(yesbutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_yes_func), (void *)dwwait);
+		nobutton = dw_button_new("No", 1002L);
+		dw_box_pack_start(buttonbox, nobutton, 50, 30, TRUE, FALSE, 2);
+		dw_signal_connect(nobutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_no_func), (void *)dwwait);
+	}
+	else if(flags & DW_MB_YESNOCANCEL)
+	{
+		yesbutton = dw_button_new("Yes", 1001L);
+		dw_box_pack_start(buttonbox, yesbutton, 50, 30, TRUE, FALSE, 2);
+		dw_signal_connect(yesbutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_yes_func), (void *)dwwait);
+		nobutton = dw_button_new("No", 1002L);
+		dw_box_pack_start(buttonbox, nobutton, 50, 30, TRUE, FALSE, 2);
+		dw_signal_connect(nobutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_no_func), (void *)dwwait);
+		cancelbutton = dw_button_new("Cancel", 1003L);
+		dw_box_pack_start(buttonbox, cancelbutton, 50, 30, TRUE, FALSE, 2);
+		dw_signal_connect(cancelbutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_cancel_func), (void *)dwwait);
+	}
+
+	height = max(50,text_height)+100;
+	x = (dw_screen_width() - (text_width+60+extra_width))/2;
+	y = (dw_screen_height() - height)/2;
+
+	dw_window_set_pos_size(entrywindow, x, y, (text_width+60+extra_width), height);
+
+	dw_window_show(entrywindow);
+
+	return (int)dw_dialog_wait(dwwait);
+}
+
+/*
+ * Minimizes or Iconifies a top-level window.
+ * Parameters:
+ *           handle: The window handle to minimize.
+ */
+int dw_window_minimize(HWND handle)
+{
+	int _locked_by_me = FALSE;
+
+	if(!handle)
+		return 0;
+
+	DW_MUTEX_LOCK;
+	XIconifyWindow(GDK_WINDOW_XDISPLAY(GTK_WIDGET(handle)->window),
+				   GDK_WINDOW_XWINDOW(GTK_WIDGET(handle)->window),
+				   DefaultScreen (GDK_DISPLAY ()));
+	DW_MUTEX_UNLOCK;
+	return 0;
+}
+
+/*
+ * Makes the window topmost.
+ * Parameters:
+ *           handle: The window handle to make topmost.
+ */
+int dw_window_raise(HWND handle)
+{
+	int _locked_by_me = FALSE;
+
+	if(!handle)
+		return 0;
+
+	DW_MUTEX_LOCK;
+	gdk_window_raise(GTK_WIDGET(handle)->window);
+	DW_MUTEX_UNLOCK;
+	return 0;
+}
+
+/*
+ * Makes the window bottommost.
+ * Parameters:
+ *           handle: The window handle to make bottommost.
+ */
+int dw_window_lower(HWND handle)
+{
+	int _locked_by_me = FALSE;
+
+	if(!handle)
+		return 0;
+
+	DW_MUTEX_LOCK;
+	gdk_window_lower(GTK_WIDGET(handle)->window);
+	DW_MUTEX_UNLOCK;
+	return 0;
+}
+
+/*
+ * Makes the window visible.
+ * Parameters:
+ *           handle: The window handle to make visible.
+ */
+int dw_window_show(HWND handle)
+{
+	int _locked_by_me = FALSE;
+	GtkWidget *defaultitem;
+
+	if(!handle)
+		return 0;
+
+	DW_MUTEX_LOCK;
+	gtk_widget_show(handle);
+	if(GTK_WIDGET(handle)->window)
+	{
+		int width = (int)gtk_object_get_data(GTK_OBJECT(handle), "_dw_width");
+		int height = (int)gtk_object_get_data(GTK_OBJECT(handle), "_dw_height");
+
+		if(width && height)
+		{
+			gtk_widget_set_usize(handle, width, height);
+			gtk_object_set_data(GTK_OBJECT(handle), "_dw_width", 0);
+			gtk_object_set_data(GTK_OBJECT(handle), "_dw_height", 0);
+		}
+
+		gdk_window_raise(GTK_WIDGET(handle)->window);
+		gdk_flush();
+		gdk_window_show(GTK_WIDGET(handle)->window);
+		gdk_flush();
+	}
+	defaultitem = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_defaultitem");
+	if(defaultitem)
+		gtk_widget_grab_focus(defaultitem);
+	DW_MUTEX_UNLOCK;
+	return 0;
+}
+
+/*
+ * Makes the window invisible.
+ * Parameters:
+ *           handle: The window handle to make visible.
+ */
+int dw_window_hide(HWND handle)
+{
+	int _locked_by_me = FALSE;
+
+	if(!handle)
+		return 0;
+
+	DW_MUTEX_LOCK;
+	gtk_widget_hide(handle);
+	DW_MUTEX_UNLOCK;
+	return 0;
+}
+
+/*
+ * Destroys a window and all of it's children.
+ * Parameters:
+ *           handle: The window handle to destroy.
+ */
+int dw_window_destroy(HWND handle)
+{
+	int _locked_by_me = FALSE;
+
+	if(!handle)
+		return 0;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_WIDGET(handle))
+	{
+		GtkWidget *eventbox = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_eventbox");
+
+		if(eventbox && GTK_IS_WIDGET(eventbox))
+			gtk_widget_destroy(eventbox);
+        else
+			gtk_widget_destroy(handle);
+	}
+	DW_MUTEX_UNLOCK;
+	return 0;
+}
+
+/* Causes entire window to be invalidated and redrawn.
+ * Parameters:
+ *           handle: Toplevel window handle to be redrawn.
+ */
+void dw_window_redraw(HWND handle)
+{
+}
+
+/*
+ * Changes a window's parent to newparent.
+ * Parameters:
+ *           handle: The window handle to destroy.
+ *           newparent: The window's new parent window.
+ */
+void dw_window_reparent(HWND handle, HWND newparent)
+{
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	gdk_window_reparent(GTK_WIDGET(handle)->window, newparent ? GTK_WIDGET(newparent)->window : GDK_ROOT_PARENT(), 0, 0);
+	DW_MUTEX_UNLOCK;
+}
+
+static int _set_font(HWND handle, char *fontname)
+{
+	int retval = FALSE;
+#if GTK_MAJOR_VERSION < 2
+	GtkStyle *style;
+	GdkFont *font = NULL;
+
+	font = gdk_font_load(fontname);
+
+	if(font)
+	{
+		style = gtk_widget_get_style(handle);
+		style->font = font;
+		gtk_widget_set_style(handle, style);
+		retval = TRUE;
+	}
+#else
+	PangoFontDescription *font = pango_font_description_from_string(fontname);
+  
+	if(font)
+	{
+		gtk_widget_modify_font(handle, font);
+		pango_font_description_free(font);
+	}
+#endif
+	return retval;
+}
+
+/*
+ * Sets the font used by a specified window (widget) handle.
+ * Parameters:
+ *          handle: The window (widget) handle.
+ *          fontname: Name and size of the font in the form "size.fontname"
+ */
+int dw_window_set_font(HWND handle, char *fontname)
+{
+#if GTK_MAJOR_VERSION > 1
+	PangoFontDescription *pfont;
+#else
+	GdkFont *gdkfont;
+#endif
+	GtkWidget *handle2 = handle;
+	char *font;
+	int _locked_by_me = FALSE;
+	gpointer data;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+		if(tmp)
+			handle2 = tmp;
+	}
+	font = strdup(fontname);
+
+#if GTK_MAJOR_VERSION < 2
+	/* Free old font if it exists */
+	gdkfont = (GdkFont *)gtk_object_get_data(GTK_OBJECT(handle2), "_dw_gdkfont");
+	if(gdkfont)
+		gdk_font_unref(gdkfont);
+	gdkfont = gdk_font_load(fontname);
+	if(!gdkfont)
+		gdkfont = gdk_font_load("fixed");
+	gtk_object_set_data(GTK_OBJECT(handle2), "_dw_gdkfont", (gpointer)gdkfont);
+#endif
+
+	/* Free old font name if one is allocated */
+	data = gtk_object_get_data(GTK_OBJECT(handle2), "_dw_fontname");
+	if(data)
+		free(data);
+
+	gtk_object_set_data(GTK_OBJECT(handle2), "_dw_fontname", (gpointer)font);
+#if GTK_MAJOR_VERSION > 1
+	pfont = pango_font_description_from_string(fontname);
+
+	if(pfont)
+	{
+		gtk_widget_modify_font(handle2, pfont);
+		pango_font_description_free(pfont);
+	}
+#endif
+	DW_MUTEX_UNLOCK;
+	return TRUE;
+}
+
+void _free_gdk_colors(HWND handle)
+{
+	GdkColor *old = (GdkColor *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_foregdk");
+
+	if(old)
+		free(old);
+
+	old = (GdkColor *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_backgdk");
+
+	if(old)
+		free(old);
+}
+
+/* Free old color pointers and allocate new ones */
+static void _save_gdk_colors(HWND handle, GdkColor fore, GdkColor back)
+{
+	GdkColor *foregdk = malloc(sizeof(GdkColor));
+	GdkColor *backgdk = malloc(sizeof(GdkColor));
+
+	_free_gdk_colors(handle);
+
+	*foregdk = fore;
+	*backgdk = back;
+
+	gtk_object_set_data(GTK_OBJECT(handle), "_dw_foregdk", (gpointer)foregdk);
+	gtk_object_set_data(GTK_OBJECT(handle), "_dw_backgdk", (gpointer)backgdk);
+}
+
+static int _set_color(HWND handle, unsigned long fore, unsigned long back)
+{
+	/* Remember that each color component in X11 use 16 bit no matter
+	 * what the destination display supports. (and thus GDK)
+	 */
+	GdkColor forecolor, backcolor;
+#if GTK_MAJOR_VERSION < 2
+	GtkStyle *style = gtk_style_copy(gtk_widget_get_style(handle));
+#endif
+
+	if(fore & DW_RGB_COLOR)
+	{
+		forecolor.pixel = 0;
+		forecolor.red = DW_RED_VALUE(fore) << 8;
+		forecolor.green = DW_GREEN_VALUE(fore) << 8;
+		forecolor.blue = DW_BLUE_VALUE(fore) << 8;
+
+		gdk_color_alloc(_dw_cmap, &forecolor);
+
+#if GTK_MAJOR_VERSION > 1
+		gtk_widget_modify_text(handle, 0, &forecolor);
+		gtk_widget_modify_text(handle, 1, &forecolor);
+		gtk_widget_modify_fg(handle, 0, &forecolor);
+		gtk_widget_modify_fg(handle, 1, &forecolor);
+#else
+		if(style)
+			style->text[0] = style->text[1] = style->fg[0] = style->fg[1] = forecolor;
+#endif
+	}
+	else if(fore != DW_CLR_DEFAULT)
+	{
+		forecolor = _colors[fore];
+
+#if GTK_MAJOR_VERSION > 1
+		gtk_widget_modify_text(handle, 0, &_colors[fore]);
+		gtk_widget_modify_text(handle, 1, &_colors[fore]);
+		gtk_widget_modify_fg(handle, 0, &_colors[fore]);
+		gtk_widget_modify_fg(handle, 1, &_colors[fore]);
+#else
+		if(style)
+			style->text[0] = style->text[1] = style->fg[0] = style->fg[1] = _colors[fore];
+#endif
+	}
+	if(back & DW_RGB_COLOR)
+	{
+		backcolor.pixel = 0;
+		backcolor.red = DW_RED_VALUE(back) << 8;
+		backcolor.green = DW_GREEN_VALUE(back) << 8;
+		backcolor.blue = DW_BLUE_VALUE(back) << 8;
+
+		gdk_color_alloc(_dw_cmap, &backcolor);
+
+#if GTK_MAJOR_VERSION > 1
+		gtk_widget_modify_base(handle, 0, &backcolor);
+		gtk_widget_modify_base(handle, 1, &backcolor);
+		gtk_widget_modify_bg(handle, 0, &backcolor);
+		gtk_widget_modify_bg(handle, 1, &backcolor);
+#else
+		if(style)
+			style->base[0] = style->base[1] = style->bg[0] = style->bg[1] = backcolor;
+#endif
+	}
+	else if(back != DW_CLR_DEFAULT)
+	{
+		backcolor = _colors[back];
+
+#if GTK_MAJOR_VERSION > 1
+		gtk_widget_modify_base(handle, 0, &_colors[back]);
+		gtk_widget_modify_base(handle, 1, &_colors[back]);
+		gtk_widget_modify_bg(handle, 0, &_colors[back]);
+		gtk_widget_modify_bg(handle, 1, &_colors[back]);
+#else
+		if(style)
+			style->base[0] = style->base[1] = style->bg[0] = style->bg[1] = _colors[back];
+#endif
+	}
+
+	_save_gdk_colors(handle, forecolor, backcolor);
+
+	if(GTK_IS_CLIST(handle))
+	{
+		int z, rowcount = (int)gtk_object_get_data(GTK_OBJECT(handle), "_dw_rowcount");
+
+		for(z=0;z<rowcount;z++)
+		{
+			gtk_clist_set_foreground(GTK_CLIST(handle), z, &forecolor);
+			gtk_clist_set_background(GTK_CLIST(handle), z, &backcolor);
+		}
+	}
+
+#if GTK_MAJOR_VERSION < 2
+	if(style)
+	{
+		gtk_widget_set_style(handle, style);
+		gtk_style_unref(style);
+	}
+#endif
+	return TRUE;
+}
+/*
+ * Sets the colors used by a specified window (widget) handle.
+ * Parameters:
+ *          handle: The window (widget) handle.
+ *          fore: Foreground color in RGB format.
+ *          back: Background color in RGB format.
+ */
+int dw_window_set_color(HWND handle, unsigned long fore, unsigned long back)
+{
+	GtkWidget *handle2 = handle;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+
+	if(GTK_IS_SCROLLED_WINDOW(handle) || GTK_IS_BOX(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+		if(tmp)
+			handle2 = tmp;
+	}
+	else if(GTK_IS_TABLE(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_eventbox");
+		if(tmp)
+			handle2 = tmp;
+	}
+
+	_set_color(handle2, fore, back);
+
+	DW_MUTEX_UNLOCK;
+	return TRUE;
+}
+
+/*
+ * Sets the font used by a specified window (widget) handle.
+ * Parameters:
+ *          handle: The window (widget) handle.
+ *          border: Size of the window border in pixels.
+ */
+int dw_window_set_border(HWND handle, int border)
+{
+	/* TODO */
+	return 0;
+}
+
+/*
+ * Captures the mouse input to this window.
+ * Parameters:
+ *       handle: Handle to receive mouse input.
+ */
+void dw_window_capture(HWND handle)
+{
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	gdk_pointer_grab(handle->window, TRUE, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK, NULL, NULL, GDK_CURRENT_TIME);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Changes the appearance of the mouse pointer.
+ * Parameters:
+ *       handle: Handle to widget for which to change.
+ *       cursortype: ID of the pointer you want.
+ */
+void dw_window_pointer(HWND handle, int pointertype)
+{
+	int _locked_by_me = FALSE;
+	GdkCursor *cursor;
+
+	DW_MUTEX_LOCK;
+	if(pointertype & (1 << 31))
+	{
+		GdkBitmap *bitmap = NULL;
+		GdkPixmap  *pixmap = _find_private_pixmap(&bitmap, (pointertype & 0xFFFFFF), NULL, NULL);
+		cursor = gdk_cursor_new_from_pixmap(pixmap, (GdkPixmap *)bitmap, &_colors[DW_CLR_WHITE], &_colors[DW_CLR_BLACK], 8, 8);
+	}
+	else
+		cursor = gdk_cursor_new(pointertype);
+	if(handle && handle->window)
+		gdk_window_set_cursor(handle->window, cursor);
+	gdk_cursor_destroy(cursor);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Releases previous mouse capture.
+ */
+void dw_window_release(void)
+{
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	gdk_pointer_ungrab(GDK_CURRENT_TIME);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Create a new Window Frame.
+ * Parameters:
+ *       owner: The Owner's window handle or HWND_DESKTOP.
+ *       title: The Window title.
+ *       flStyle: Style flags, see the PM reference.
+ */
+HWND dw_window_new(HWND hwndOwner, char *title, unsigned long flStyle)
+{
+	GtkWidget *tmp;
+	int _locked_by_me = FALSE;
+	int flags = 0;
+
+	DW_MUTEX_LOCK;
+	last_window = tmp = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+	gtk_window_set_title(GTK_WINDOW(tmp), title);
+	if(!(flStyle & DW_FCF_SIZEBORDER))
+		gtk_window_set_policy(GTK_WINDOW(tmp), FALSE, FALSE, TRUE);
+
+	gtk_widget_realize(tmp);
+
+	if(flStyle & DW_FCF_TITLEBAR)
+		flags |= GDK_DECOR_TITLE;
+
+	if(flStyle & DW_FCF_MINMAX)
+		flags |= GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE;
+
+	if(flStyle & DW_FCF_SIZEBORDER)
+		flags |= GDK_DECOR_RESIZEH | GDK_DECOR_BORDER;
+
+	if(flStyle & DW_FCF_BORDER || flStyle & DW_FCF_DLGBORDER)
+		flags |= GDK_DECOR_BORDER;
+
+	if(flStyle & DW_FCF_MAXIMIZE)
+	{
+		flags &= ~DW_FCF_MAXIMIZE;
+#if GTK_MAJOR_VERSION > 1
+		gtk_window_maximize(GTK_WINDOW(tmp));
+#endif
+	}
+	if(flStyle & DW_FCF_MINIMIZE)
+	{
+		flags &= ~DW_FCF_MINIMIZE;
+#if GTK_MAJOR_VERSION > 1
+		gtk_window_iconify(GTK_WINDOW(tmp));
+#endif
+	}
+
+	gdk_window_set_decorations(tmp->window, flags);
+
+	if(hwndOwner)
+		gdk_window_reparent(GTK_WIDGET(tmp)->window, GTK_WIDGET(hwndOwner)->window, 0, 0);
+
+	if(flStyle & DW_FCF_SIZEBORDER)
+		gtk_object_set_data(GTK_OBJECT(tmp), "_dw_size", (gpointer)1);
+
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Create a new Box to be packed.
+ * Parameters:
+ *       type: Either DW_VERT (vertical) or DW_HORZ (horizontal).
+ *       pad: Number of pixels to pad around the box.
+ */
+HWND dw_box_new(int type, int pad)
+{
+	GtkWidget *tmp, *eventbox;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	tmp = gtk_table_new(1, 1, FALSE);
+	eventbox = gtk_event_box_new();
+
+	gtk_widget_show(eventbox);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_eventbox", (gpointer)eventbox);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_boxtype", (gpointer)type);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_boxpad", (gpointer)pad);
+	gtk_widget_show(tmp);
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Create a new Group Box to be packed.
+ * Parameters:
+ *       type: Either DW_VERT (vertical) or DW_HORZ (horizontal).
+ *       pad: Number of pixels to pad around the box.
+ *       title: Text to be displayined in the group outline.
+ */
+HWND dw_groupbox_new(int type, int pad, char *title)
+{
+	GtkWidget *tmp, *frame;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	frame = gtk_frame_new(NULL);
+	gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
+	gtk_frame_set_label(GTK_FRAME(frame), title && *title ? title : NULL);
+	tmp = gtk_table_new(1, 1, FALSE);
+	gtk_container_border_width(GTK_CONTAINER(tmp), pad);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_boxtype", (gpointer)type);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_boxpad", (gpointer)pad);
+	gtk_object_set_data(GTK_OBJECT(frame), "_dw_boxhandle", (gpointer)tmp);
+	gtk_container_add(GTK_CONTAINER(frame), tmp);
+	gtk_widget_show(tmp);
+	gtk_widget_show(frame);
+	DW_MUTEX_UNLOCK;
+	return frame;
+}
+
+/*
+ * Create a new MDI Frame to be packed.
+ * Parameters:
+ *       id: An ID to be used with dw_window_from_id or 0L.
+ */
+HWND dw_mdi_new(unsigned long id)
+{
+	GtkWidget *tmp;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	tmp = gtk_vbox_new(FALSE, 0);
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Create a bitmap object to be packed.
+ * Parameters:
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND dw_bitmap_new(unsigned long id)
+{
+#if GTK_MAJOR_VERSION < 2
+	GdkPixmap *pixmap = NULL;
+	GdkBitmap *bitmap = NULL;
+	static char * test_xpm[] = {
+		"1 1 2 1",
+		"	c None",
+		".	c #FFFFFF",
+		"."};
+#endif
+	GtkWidget *tmp;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+#if GTK_MAJOR_VERSION > 1
+	tmp = gtk_image_new();
+#elif defined(USE_IMLIB)
+	gdk_imlib_data_to_pixmap(test_xpm, &pixmap, &bitmap);
+#else
+	gtk_widget_realize(last_window);
+
+	if(last_window)
+		pixmap = gdk_pixmap_create_from_xpm_d(last_window->window, &bitmap, &_colors[DW_CLR_PALEGRAY], test_xpm);
+#endif
+#if GTK_MAJOR_VERSION < 2
+	tmp = gtk_pixmap_new(pixmap, bitmap);
+#endif
+	gtk_widget_show(tmp);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Create a notebook object to be packed.
+ * Parameters:
+ *       id: An ID to be used for getting the resource from the
+ *           resource file.
+ */
+HWND dw_notebook_new(unsigned long id, int top)
+{
+	GtkWidget *tmp, **pagearray = calloc(sizeof(GtkWidget *), 256);
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	tmp = gtk_notebook_new();
+	if(top)
+		gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tmp), GTK_POS_TOP);
+	else
+		gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tmp), GTK_POS_BOTTOM);
+	gtk_notebook_set_scrollable(GTK_NOTEBOOK(tmp), TRUE);
+#if 0
+	gtk_notebook_popup_enable(GTK_NOTEBOOK(tmp));
+#endif
+	gtk_widget_show(tmp);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_pagearray", (gpointer)pagearray);
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Create a menu object to be popped up.
+ * Parameters:
+ *       id: An ID to be used for getting the resource from the
+ *           resource file.
+ */
+HMENUI dw_menu_new(unsigned long id)
+{
+	int _locked_by_me = FALSE;
+	GtkAccelGroup *accel_group;
+	HMENUI tmp;
+
+	DW_MUTEX_LOCK;
+	tmp = gtk_menu_new();
+	gtk_widget_show(tmp);
+	accel_group = gtk_accel_group_new();
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_accel", (gpointer)accel_group);
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Create a menubar on a window.
+ * Parameters:
+ *       location: Handle of a window frame to be attached to.
+ */
+HMENUI dw_menubar_new(HWND location)
+{
+	GtkWidget *box;
+	int _locked_by_me = FALSE;
+	GtkAccelGroup *accel_group;
+	HMENUI tmp;
+
+	DW_MUTEX_LOCK;
+	tmp = gtk_menu_bar_new();
+	box = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(location));
+	gtk_widget_show(tmp);
+	accel_group = gtk_accel_group_new();
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_accel", (gpointer)accel_group);
+
+	if(box)
+		gtk_box_pack_end(GTK_BOX(box), tmp, FALSE, FALSE, 0);
+
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Destroys a menu created with dw_menubar_new or dw_menu_new.
+ * Parameters:
+ *       menu: Handle of a menu.
+ */
+void dw_menu_destroy(HMENUI *menu)
+{
+	if(menu && *menu)
+	{
+		int _locked_by_me = FALSE;
+
+		DW_MUTEX_LOCK;
+		gtk_widget_destroy(*menu);
+		*menu = NULL;
+		DW_MUTEX_UNLOCK;
+	}
+}
+
+char _removetilde(char *dest, char *src)
+{
+	int z, cur=0;
+	char accel = '\0';
+
+	for(z=0;z<strlen(src);z++)
+	{
+		if(src[z] != '~')
+		{
+			dest[cur] = src[z];
+			cur++;
+		}
+		else
+		{
+			dest[cur] = '_';
+			accel = src[z+1];
+			cur++;
+		}
+	}
+	dest[cur] = 0;
+	return accel;
+}
+
+/*
+ * Adds a menuitem or submenu to an existing menu.
+ * Parameters:
+ *       menu: The handle the the existing menu.
+ *       title: The title text on the menu item to be added.
+ *       id: An ID to be used for message passing.
+ *       flags: Extended attributes to set on the menu.
+ *       end: If TRUE memu is positioned at the end of the menu.
+ *       check: If TRUE menu is "check"able.
+ *       submenu: Handle to an existing menu to be a submenu or NULL.
+ */
+HWND dw_menu_append_item(HMENUI menu, char *title, unsigned long id, unsigned long flags, int end, int check, HMENUI submenu)
+{
+	GtkWidget *tmphandle;
+	char accel, *tempbuf = malloc(strlen(title)+1);
+	int _locked_by_me = FALSE, submenucount;
+	guint tmp_key;
+	GtkAccelGroup *accel_group;
+
+	if(!menu)
+	{
+		free(tempbuf);
+		return NULL;
+	}
+
+	DW_MUTEX_LOCK;
+	accel = _removetilde(tempbuf, title);
+
+	accel_group = (GtkAccelGroup *)gtk_object_get_data(GTK_OBJECT(menu), "_dw_accel");
+	submenucount = (int)gtk_object_get_data(GTK_OBJECT(menu), "_dw_submenucount");
+
+	if(strlen(tempbuf) == 0)
+		tmphandle=gtk_menu_item_new();
+	else
+	{
+		if(check)
+		{
+			char numbuf[10];
+			if(accel && accel_group)
+			{
+				tmphandle=gtk_check_menu_item_new_with_label("");
+				tmp_key = gtk_label_parse_uline(GTK_LABEL(GTK_BIN(tmphandle)->child), tempbuf);
+#if 0 /* This isn't working right */
+				gtk_widget_add_accelerator(tmphandle, "activate", accel_group, tmp_key, GDK_MOD1_MASK, 0);
+#endif
+			}
+			else
+				tmphandle=gtk_check_menu_item_new_with_label(tempbuf);
+			gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(tmphandle), TRUE);
+			sprintf(numbuf, "%lu", id);
+			gtk_object_set_data(GTK_OBJECT(menu), numbuf, (gpointer)tmphandle);
+		}
+		else
+		{
+			if(accel && accel_group)
+			{
+				tmphandle=gtk_menu_item_new_with_label("");
+				tmp_key = gtk_label_parse_uline(GTK_LABEL(GTK_BIN(tmphandle)->child), tempbuf);
+#if 0 /* This isn't working right */
+				gtk_widget_add_accelerator(tmphandle, "activate", accel_group, tmp_key, GDK_MOD1_MASK, 0);
+#endif
+			}
+			else
+				tmphandle=gtk_menu_item_new_with_label(tempbuf);
+		}
+	}
+
+	gtk_widget_show(tmphandle);
+
+	if(submenu)
+	{
+		char tempbuf[100];
+
+		sprintf(tempbuf, "_dw_submenu%d", submenucount);
+		submenucount++;
+		gtk_menu_item_set_submenu(GTK_MENU_ITEM(tmphandle), submenu);
+		gtk_object_set_data(GTK_OBJECT(menu), tempbuf, (gpointer)submenu);
+		gtk_object_set_data(GTK_OBJECT(menu), "_dw_submenucount", (gpointer)submenucount);
+	}
+
+	if(GTK_IS_MENU_BAR(menu))
+		gtk_menu_bar_append(GTK_MENU_BAR(menu), tmphandle);
+	else
+		gtk_menu_append(GTK_MENU(menu), tmphandle);
+
+	gtk_object_set_data(GTK_OBJECT(tmphandle), "_dw_id", (gpointer)id);
+	free(tempbuf);
+	DW_MUTEX_UNLOCK;
+	return tmphandle;
+}
+
+GtkWidget *_find_submenu_id(GtkWidget *start, char *name)
+{
+	GtkWidget *tmp;
+	int z, submenucount = (int)gtk_object_get_data(GTK_OBJECT(start), "_dw_submenucount");
+
+	if((tmp = gtk_object_get_data(GTK_OBJECT(start), name)))
+		return tmp;
+
+	for(z=0;z<submenucount;z++)
+	{
+		char tempbuf[100];
+		GtkWidget *submenu, *menuitem;
+
+		sprintf(tempbuf, "_dw_submenu%d", z);
+
+		if((submenu = gtk_object_get_data(GTK_OBJECT(start), tempbuf)))
+		{
+			if((menuitem = _find_submenu_id(submenu, name)))
+				return menuitem;
+		}
+	}
+	return NULL;
+}
+
+/*
+ * Sets the state of a menu item check.
+ * Parameters:
+ *       menu: The handle the the existing menu.
+ *       id: Menuitem id.
+ *       check: TRUE for checked FALSE for not checked.
+ */
+void dw_menu_item_set_check(HMENUI menu, unsigned long id, int check)
+{
+	char numbuf[10];
+	GtkWidget *tmphandle;
+	int _locked_by_me = FALSE;
+
+	if(!menu)
+		return;
+
+	DW_MUTEX_LOCK;
+	sprintf(numbuf, "%lu", id);
+	tmphandle = _find_submenu_id(menu, numbuf);
+
+	if(tmphandle)
+	{
+		_dw_ignore_click = 1;
+		if(GTK_CHECK_MENU_ITEM(tmphandle)->active != check)
+			gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(tmphandle), check);
+		_dw_ignore_click = 0;
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Pops up a context menu at given x and y coordinates.
+ * Parameters:
+ *       menu: The handle the the existing menu.
+ *       parent: Handle to the window initiating the popup.
+ *       x: X coordinate.
+ *       y: Y coordinate.
+ */
+void dw_menu_popup(HMENUI *menu, HWND parent, int x, int y)
+{
+	int _locked_by_me = FALSE;
+
+	if(!menu || !*menu)
+		return;
+
+	popup = parent;
+
+	DW_MUTEX_LOCK;
+	gtk_menu_popup(GTK_MENU(*menu), NULL, NULL, NULL, NULL, 1, GDK_CURRENT_TIME);
+	*menu = NULL;
+	DW_MUTEX_UNLOCK;
+}
+
+
+/*
+ * Returns the current X and Y coordinates of the mouse pointer.
+ * Parameters:
+ *       x: Pointer to variable to store X coordinate.
+ *       y: Pointer to variable to store Y coordinate.
+ */
+void dw_pointer_query_pos(long *x, long *y)
+{
+	GdkModifierType state;
+	int gx, gy;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	gdk_window_get_pointer (GDK_ROOT_PARENT(), &gx, &gy, &state);
+	*x = gx;
+	*y = gy;
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Sets the X and Y coordinates of the mouse pointer.
+ * Parameters:
+ *       x: X coordinate.
+ *       y: Y coordinate.
+ */
+void dw_pointer_set_pos(long x, long y)
+{
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	XWarpPointer(GDK_DISPLAY(), None, GDK_ROOT_WINDOW(), 0,0,0,0, x, y);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Create a container object to be packed.
+ * Parameters:
+ *       id: An ID to be used for getting the resource from the
+ *           resource file.
+ */
+HWND dw_container_new(unsigned long id, int multi)
+{
+	GtkWidget *tmp;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	tmp = gtk_scrolled_window_new (NULL, NULL);
+	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (tmp),
+					GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_multi", (gpointer)multi);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+	gtk_widget_show(tmp);
+
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Create a tree object to be packed.
+ * Parameters:
+ *       id: An ID to be used for getting the resource from the
+ *           resource file.
+ */
+HWND dw_tree_new(ULONG id)
+{
+	GtkWidget *tmp, *tree;
+#if GTK_MAJOR_VERSION > 1
+	GtkTreeStore *store;
+	GtkTreeViewColumn *col;
+	GtkCellRenderer *rend;
+	GtkTreeSelection *sel;
+#endif
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	tmp = gtk_scrolled_window_new(NULL, NULL);
+	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (tmp),
+					GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+	gtk_widget_show(tmp);
+#if GTK_MAJOR_VERSION > 1
+	store = gtk_tree_store_new(4, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_POINTER, G_TYPE_POINTER);
+	tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
+	gtk_object_set_data(GTK_OBJECT(tree), "_dw_tree_store", (gpointer)store);
+	col = gtk_tree_view_column_new();
+
+	rend = gtk_cell_renderer_pixbuf_new();
+	gtk_tree_view_column_pack_start(col, rend, FALSE);
+	gtk_tree_view_column_add_attribute(col, rend, "pixbuf", 1);
+	rend = gtk_cell_renderer_text_new();
+	gtk_tree_view_column_pack_start(col, rend, TRUE);
+	gtk_tree_view_column_add_attribute(col, rend, "text", 0);
+
+	gtk_tree_view_append_column(GTK_TREE_VIEW (tree), col);
+	gtk_tree_view_set_expander_column(GTK_TREE_VIEW(tree), col);
+	gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree), FALSE);
+  
+	sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
+	gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
+#else
+	tree = gtk_tree_new();
+#endif
+	if(!tree)
+	{
+		gtk_widget_destroy(tmp);
+		DW_MUTEX_UNLOCK;
+		return FALSE;
+	}
+	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(tmp), tree);
+#if GTK_MAJOR_VERSION < 2
+	/* Set the selection mode */
+	gtk_tree_set_selection_mode (GTK_TREE(tree), GTK_SELECTION_SINGLE);
+	gtk_tree_set_view_mode(GTK_TREE(tree), GTK_TREE_VIEW_ITEM);
+#endif
+
+	gtk_object_set_user_data(GTK_OBJECT(tmp), (gpointer)tree);
+	gtk_widget_show(tree);
+
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+
+/*
+ * Create a new static text window (widget) to be packed.
+ * Parameters:
+ *       text: The text to be display by the static text widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND dw_text_new(char *text, unsigned long id)
+{
+	GtkWidget *tmp;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	tmp = gtk_label_new(text);
+
+	/* Left and centered */
+	gtk_misc_set_alignment(GTK_MISC(tmp), 0.0f, 0.5f);
+	gtk_widget_show(tmp);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+	gtk_misc_set_alignment(GTK_MISC(tmp), DW_LEFT, DW_LEFT);
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Create a new status text window (widget) to be packed.
+ * Parameters:
+ *       text: The text to be display by the static text widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND dw_status_text_new(char *text, ULONG id)
+{
+	GtkWidget *tmp, *frame;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	frame = gtk_frame_new(NULL);
+	gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
+	tmp = gtk_label_new(text);
+	gtk_container_add(GTK_CONTAINER(frame), tmp);
+	gtk_widget_show(tmp);
+	gtk_widget_show(frame);
+
+	/* Left and centered */
+	gtk_misc_set_alignment(GTK_MISC(tmp), 0.0f, 0.5f);
+	gtk_object_set_data(GTK_OBJECT(frame), "_dw_id", (gpointer)id);
+	gtk_object_set_data(GTK_OBJECT(frame), "_dw_label", (gpointer)tmp);
+	DW_MUTEX_UNLOCK;
+	return frame;
+}
+
+/*
+ * Create a new Multiline Editbox window (widget) to be packed.
+ * Parameters:
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND dw_mle_new(unsigned long id)
+{
+	GtkWidget *tmp, *tmpbox, *scroller;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+#if GTK_MAJOR_VERSION > 1
+	tmpbox = gtk_scrolled_window_new (NULL, NULL);
+	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(tmpbox),
+					GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+	gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(tmpbox), GTK_SHADOW_ETCHED_IN);
+	tmp = gtk_text_view_new();
+	gtk_container_add (GTK_CONTAINER(tmpbox), tmp);
+	gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(tmp), GTK_WRAP_NONE);
+
+	scroller = NULL;  
+#else
+	tmpbox = gtk_hbox_new(FALSE, 0);
+	tmp = gtk_text_new(NULL, NULL);
+	gtk_text_set_word_wrap(GTK_TEXT(tmp), FALSE);
+	gtk_text_set_line_wrap(GTK_TEXT(tmp), FALSE);
+	scroller = gtk_vscrollbar_new(GTK_TEXT(tmp)->vadj);
+	GTK_WIDGET_UNSET_FLAGS(scroller, GTK_CAN_FOCUS);
+	gtk_box_pack_start(GTK_BOX(tmpbox), tmp, TRUE, TRUE, 0);
+	gtk_box_pack_start(GTK_BOX(tmpbox), scroller, FALSE, TRUE, 0);
+	gtk_widget_show(scroller);
+#endif
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+	gtk_object_set_user_data(GTK_OBJECT(tmpbox), (gpointer)tmp);
+	gtk_widget_show(tmp);
+	gtk_widget_show(tmpbox);
+	DW_MUTEX_UNLOCK;
+	return tmpbox;
+}
+
+/*
+ * Create a new Entryfield window (widget) to be packed.
+ * Parameters:
+ *       text: The default text to be in the entryfield widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND dw_entryfield_new(char *text, unsigned long id)
+{
+	GtkWidget *tmp;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	tmp = gtk_entry_new();
+
+	gtk_entry_set_text(GTK_ENTRY(tmp), text);
+
+	gtk_widget_show(tmp);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Create a new Entryfield (password) window (widget) to be packed.
+ * Parameters:
+ *       text: The default text to be in the entryfield widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND dw_entryfield_password_new(char *text, ULONG id)
+{
+	GtkWidget *tmp;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	tmp = gtk_entry_new();
+
+	gtk_entry_set_visibility(GTK_ENTRY(tmp), FALSE);
+	gtk_entry_set_text(GTK_ENTRY(tmp), text);
+
+	gtk_widget_show(tmp);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Create a new Combobox window (widget) to be packed.
+ * Parameters:
+ *       text: The default text to be in the combpbox widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND dw_combobox_new(char *text, unsigned long id)
+{
+	GtkWidget *tmp;
+	int sigid, _locked_by_me = FALSE;
+	gint cid;
+
+	DW_MUTEX_LOCK;
+	tmp = gtk_combo_new();
+	gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(tmp)->entry), text);
+	gtk_combo_set_use_arrows(GTK_COMBO(tmp), TRUE);
+	gtk_object_set_user_data(GTK_OBJECT(tmp), NULL);
+	gtk_widget_show(tmp);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+
+	sigid = _set_signal_handler(GTK_COMBO(tmp)->list, tmp, NULL, NULL, NULL);
+	cid = gtk_signal_connect(GTK_OBJECT(GTK_COMBO(tmp)->list), "select_child", GTK_SIGNAL_FUNC(_item_select_event), (gpointer)sigid);
+	_set_signal_handler_id(GTK_COMBO(tmp)->list, sigid, cid);
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Create a new button window (widget) to be packed.
+ * Parameters:
+ *       text: The text to be display by the static text widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND dw_button_new(char *text, unsigned long id)
+{
+	GtkWidget *tmp;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	tmp = gtk_button_new_with_label(text);
+	gtk_widget_show(tmp);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Create a new bitmap button window (widget) to be packed.
+ * Parameters:
+ *       text: Bubble help text to be displayed.
+ *       id: An ID of a bitmap in the resource file.
+ */
+HWND dw_bitmapbutton_new(char *text, unsigned long id)
+{
+	GtkWidget *tmp;
+	GtkWidget *bitmap;
+    GtkTooltips *tooltips;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	tmp = gtk_button_new();
+	bitmap = dw_bitmap_new(id);
+
+	if(bitmap)
+	{
+		dw_window_set_bitmap(bitmap, id, NULL);
+		gtk_container_add (GTK_CONTAINER(tmp), bitmap);
+	}
+	gtk_widget_show(tmp);
+	if(text)
+	{
+		tooltips = gtk_tooltips_new();
+		gtk_tooltips_set_tip(tooltips, tmp, text, NULL);
+		gtk_object_set_data(GTK_OBJECT(tmp), "tooltip", (gpointer)tooltips);
+	}
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Create a new bitmap button window (widget) to be packed from a file.
+ * Parameters:
+ *       text: Bubble help text to be displayed.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ *       filename: Name of the file, omit extention to have
+ *                 DW pick the appropriate file extension.
+ *                 (BMP on OS/2 or Windows, XPM on Unix)
+ */
+HWND dw_bitmapbutton_new_from_file(char *text, unsigned long id, char *filename)
+{
+	GtkWidget *tmp;
+	GtkWidget *bitmap;
+    GtkTooltips *tooltips;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	tmp = gtk_button_new();
+	bitmap = dw_bitmap_new(id);
+
+	if(bitmap)
+	{
+		dw_window_set_bitmap(bitmap, 0, filename);
+		gtk_container_add (GTK_CONTAINER(tmp), bitmap);
+	}
+	gtk_widget_show(tmp);
+	if(text)
+	{
+		tooltips = gtk_tooltips_new();
+		gtk_tooltips_set_tip(tooltips, tmp, text, NULL);
+		gtk_object_set_data(GTK_OBJECT(tmp), "tooltip", (gpointer)tooltips);
+	}
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Create a new spinbutton window (widget) to be packed.
+ * Parameters:
+ *       text: The text to be display by the static text widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND dw_spinbutton_new(char *text, unsigned long id)
+{
+	GtkAdjustment *adj;
+	GtkWidget *tmp;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	adj = (GtkAdjustment *)gtk_adjustment_new (1.0, 0.0, 100.0, 1.0, 5.0, 0.0);
+	tmp = gtk_spin_button_new (adj, 0, 0);
+	gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(tmp), TRUE);
+	gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(tmp), TRUE);
+	gtk_widget_show(tmp);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Create a new radiobutton window (widget) to be packed.
+ * Parameters:
+ *       text: The text to be display by the static text widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND dw_radiobutton_new(char *text, ULONG id)
+{
+	/* This will have to be fixed in the future. */
+	GtkWidget *tmp;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	tmp = gtk_radio_button_new_with_label(NULL, text);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+	gtk_widget_show(tmp);
+
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Create a new slider window (widget) to be packed.
+ * Parameters:
+ *       vertical: TRUE or FALSE if slider is vertical.
+ *       increments: Number of increments available.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND dw_slider_new(int vertical, int increments, ULONG id)
+{
+	GtkWidget *tmp;
+	GtkAdjustment *adjustment;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	adjustment = (GtkAdjustment *)gtk_adjustment_new(0, 0, (gfloat)increments, 1, 1, 1);
+	if(vertical)
+		tmp = gtk_vscale_new(adjustment);
+	else
+		tmp = gtk_hscale_new(adjustment);
+	gtk_widget_show(tmp);
+	gtk_scale_set_draw_value(GTK_SCALE(tmp), 0);
+	gtk_scale_set_digits(GTK_SCALE(tmp), 0);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_adjustment", (gpointer)adjustment);
+	gtk_object_set_data(GTK_OBJECT(adjustment), "_dw_slider", (gpointer)tmp);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Create a new scrollbar window (widget) to be packed.
+ * Parameters:
+ *       vertical: TRUE or FALSE if scrollbar is vertical.
+ *       increments: Number of increments available.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND dw_scrollbar_new(int vertical, int increments, ULONG id)
+{
+	GtkWidget *tmp;
+	GtkAdjustment *adjustment;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	adjustment = (GtkAdjustment *)gtk_adjustment_new(0, 0, (gfloat)increments, 1, 1, 1);
+	if(vertical)
+		tmp = gtk_vscrollbar_new(adjustment);
+	else
+		tmp = gtk_hscrollbar_new(adjustment);
+	GTK_WIDGET_UNSET_FLAGS(tmp, GTK_CAN_FOCUS);
+	gtk_widget_show(tmp);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_adjustment", (gpointer)adjustment);
+	gtk_object_set_data(GTK_OBJECT(adjustment), "_dw_scrollbar", (gpointer)tmp);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Create a new percent bar window (widget) to be packed.
+ * Parameters:
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND dw_percent_new(unsigned long id)
+{
+	GtkWidget *tmp;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	tmp = gtk_progress_bar_new();
+	gtk_widget_show(tmp);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Create a new checkbox window (widget) to be packed.
+ * Parameters:
+ *       text: The text to be display by the static text widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND dw_checkbox_new(char *text, unsigned long id)
+{
+	GtkWidget *tmp;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	tmp = gtk_check_button_new_with_label(text);
+	gtk_widget_show(tmp);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Create a new listbox window (widget) to be packed.
+ * Parameters:
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ *       multi: Multiple select TRUE or FALSE.
+ */
+HWND dw_listbox_new(unsigned long id, int multi)
+{
+	GtkWidget *tmp, *list;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	tmp = gtk_scrolled_window_new(NULL, NULL);
+	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (tmp),
+				       GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+
+	list = gtk_list_new();
+	gtk_list_set_selection_mode(GTK_LIST(list), multi ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE);
+
+	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(tmp),
+					      list);
+	gtk_object_set_user_data(GTK_OBJECT(tmp), list);
+	gtk_widget_show(list);
+	gtk_widget_show(tmp);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Sets the icon used for a given window.
+ * Parameters:
+ *       handle: Handle to the window.
+ *       id: An ID to be used to specify the icon.
+ */
+void dw_window_set_icon(HWND handle, unsigned long id)
+{
+	GdkBitmap *bitmap = NULL;
+	GdkPixmap *icon_pixmap;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	icon_pixmap = _find_pixmap(&bitmap, id, handle, NULL, NULL);
+
+	if(handle->window && icon_pixmap)
+		gdk_window_set_icon(handle->window, NULL, icon_pixmap, bitmap);
+
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Sets the bitmap used for a given static window.
+ * Parameters:
+ *       handle: Handle to the window.
+ *       id: An ID to be used to specify the icon,
+ *           (pass 0 if you use the filename param)
+ *       filename: a path to a file (Bitmap on OS/2 or
+ *                 Windows and a pixmap on Unix, pass
+ *                 NULL if you use the id param)
+ */
+void dw_window_set_bitmap(HWND handle, unsigned long id, char *filename)
+{
+	GdkBitmap *bitmap = NULL;
+	GdkPixmap *tmp;
+	int _locked_by_me = FALSE;
+
+	if(!id && !filename)
+		return;
+
+	DW_MUTEX_LOCK;
+	if(id)
+		tmp = _find_pixmap(&bitmap, id, handle, NULL, NULL);
+	else
+	{
+		char *file = alloca(strlen(filename) + 5);
+#if GTK_MAJOR_VERSION > 1
+		GdkPixbuf *pixbuf;
+#elif defined(USE_IMLIB)
+		GdkImlibImage *image;
+#endif
+
+		if (!file)
+		{
+			DW_MUTEX_UNLOCK;
+			return;
+		}
+
+		strcpy(file, filename);
+
+		/* check if we can read from this file (it exists and read permission) */
+		if(access(file, 04) != 0)
+		{
+			/* Try with .xpm extention */
+			strcat(file, ".xpm");
+			if(access(file, 04) != 0)
+			{
+				DW_MUTEX_UNLOCK;
+				return;
+			}
+		}
+#if GTK_MAJOR_VERSION > 1
+		pixbuf = gdk_pixbuf_new_from_file(file, NULL);
+
+		gdk_pixbuf_render_pixmap_and_mask(pixbuf, &tmp, &bitmap, 1);
+		g_object_unref(pixbuf);
+#elif defined(USE_IMLIB)
+		image = gdk_imlib_load_image(file);
+
+		gdk_imlib_render(image, image->rgb_width, image->rgb_height);
+		tmp = gdk_imlib_copy_image(image);
+		bitmap = gdk_imlib_copy_mask(image);
+		gdk_imlib_destroy_image(image);
+#else
+		tmp = gdk_pixmap_create_from_xpm(handle->window, &bitmap, &_colors[DW_CLR_PALEGRAY], file);
+#endif
+	}
+
+	if(tmp)
+#if GTK_MAJOR_VERSION > 1
+		gtk_image_set_from_pixmap(GTK_IMAGE(handle), tmp, bitmap);
+#else
+		gtk_pixmap_set(GTK_PIXMAP(handle), tmp, bitmap);
+#endif
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Sets the text used for a given window.
+ * Parameters:
+ *       handle: Handle to the window.
+ *       text: The text associsated with a given window.                       f
+ */
+void dw_window_set_text(HWND handle, char *text)
+{
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_ENTRY(handle))
+		gtk_entry_set_text(GTK_ENTRY(handle), text);
+	else if(GTK_IS_COMBO(handle))
+		gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(handle)->entry), text);
+	else if(GTK_IS_LABEL(handle))
+		gtk_label_set_text(GTK_LABEL(handle), text);
+	else if(GTK_IS_BUTTON(handle))
+	{
+#if GTK_MAJOR_VERSION < 2
+		GtkWidget *label = GTK_BUTTON(handle)->child;
+
+		if(GTK_IS_LABEL(label))
+			gtk_label_set_text(GTK_LABEL(label), text);
+#else
+		gtk_button_set_label(GTK_BUTTON(handle), text);
+#endif
+	}
+	else if(GTK_WIDGET_TOPLEVEL(handle))
+		gtk_window_set_title(GTK_WINDOW(handle), text);
+	else if(GTK_IS_FRAME(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_label");
+		if(tmp && GTK_IS_LABEL(tmp))
+			gtk_label_set_text(GTK_LABEL(tmp), text);
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Gets the text used for a given window.
+ * Parameters:
+ *       handle: Handle to the window.
+ * Returns:
+ *       text: The text associsated with a given window.
+ */
+char *dw_window_get_text(HWND handle)
+{
+#if GTK_MAJOR_VERSION > 1
+	const char *possible = "";
+#else
+	char *possible = "";
+#endif
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_ENTRY(handle))
+		possible = gtk_entry_get_text(GTK_ENTRY(handle));
+	else if(GTK_IS_COMBO(handle))
+		possible = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(handle)->entry));
+
+	DW_MUTEX_UNLOCK;
+	return strdup(possible);
+}
+
+/*
+ * Disables given window (widget).
+ * Parameters:
+ *       handle: Handle to the window.
+ */
+void dw_window_disable(HWND handle)
+{
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	gtk_widget_set_sensitive(handle, FALSE);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Enables given window (widget).
+ * Parameters:
+ *       handle: Handle to the window.
+ */
+void dw_window_enable(HWND handle)
+{
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	gtk_widget_set_sensitive(handle, TRUE);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Gets the child window handle with specified ID.
+ * Parameters:
+ *       handle: Handle to the parent window.
+ *       id: Integer ID of the child.
+ */
+HWND API dw_window_from_id(HWND handle, int id)
+{
+	GList *orig = NULL, *list = NULL;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	if(handle && GTK_IS_CONTAINER(handle))
+	{
+#if GTK_MAJOR_VERSION > 1
+		orig = list = gtk_container_get_children(GTK_CONTAINER(handle));
+#else
+		orig = list = gtk_container_children(GTK_CONTAINER(handle));
+#endif
+	}
+	while(list)
+	{
+		if(GTK_IS_WIDGET(list->data))
+		{
+			if(id == (int)gtk_object_get_data(GTK_OBJECT(list->data), "_dw_id"))
+			{
+				HWND ret = (HWND)list->data;
+				g_list_free(orig);
+				DW_MUTEX_UNLOCK;
+				return ret;
+			}
+		}
+		list = list->next;
+	}
+	if(orig)
+		g_list_free(orig);
+	DW_MUTEX_UNLOCK;
+    return 0L;
+}
+
+void _strip_cr(char *dest, char *src)
+{
+	int z, x = 0;
+
+	for(z=0;z<strlen(src);z++)
+	{
+		if(src[z] != '\r')
+		{
+			dest[x] = src[z];
+			x++;
+		}
+	}
+	dest[x] = 0;
+}
+
+/*
+ * Adds text to an MLE box and returns the current point.
+ * Parameters:
+ *          handle: Handle to the MLE to be queried.
+ *          buffer: Text buffer to be imported.
+ *          startpoint: Point to start entering text.
+ */
+unsigned int dw_mle_import(HWND handle, char *buffer, int startpoint)
+{
+	unsigned int tmppoint = startpoint;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+#if GTK_MAJOR_VERSION > 1
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+#else
+	if(GTK_IS_BOX(handle))
+#endif
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+#if GTK_MAJOR_VERSION > 1
+		if(tmp && GTK_IS_TEXT_VIEW(tmp))
+		{
+			char *impbuf = malloc(strlen(buffer)+1);
+			GtkTextBuffer *tbuffer;
+			GtkTextIter iter;
+      
+			_strip_cr(impbuf, buffer);
+
+			tbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tmp));
+			gtk_text_buffer_get_iter_at_offset(tbuffer, &iter, startpoint);
+			gtk_text_buffer_place_cursor(tbuffer, &iter);
+			gtk_text_buffer_insert_at_cursor(tbuffer, impbuf, -1);
+			tmppoint = (startpoint > -1 ? startpoint : 0) + strlen(impbuf);
+			free(impbuf);
+		}
+#else
+		GdkFont *font = (GdkFont *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_gdkfont");
+    
+		if(tmp && GTK_IS_TEXT(tmp))
+		{
+			GdkColor *fore = (GdkColor *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_foregdk");
+			GdkColor *back = (GdkColor *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_backgdk");
+			char *impbuf = malloc(strlen(buffer)+1);
+
+			_strip_cr(impbuf, buffer);
+
+			gtk_text_set_point(GTK_TEXT(tmp), startpoint < 0 ? 0 : startpoint);
+			gtk_text_insert(GTK_TEXT(tmp), font, fore, back, impbuf, -1);
+			tmppoint = gtk_text_get_point(GTK_TEXT(tmp));
+			free(impbuf);
+		}
+#endif
+	}
+	DW_MUTEX_UNLOCK;
+	return tmppoint;
+}
+
+/*
+ * Grabs text from an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to be queried.
+ *          buffer: Text buffer to be exported.
+ *          startpoint: Point to start grabbing text.
+ *          length: Amount of text to be grabbed.
+ */
+void dw_mle_export(HWND handle, char *buffer, int startpoint, int length)
+{
+	int _locked_by_me = FALSE;
+	gchar *text;
+
+	DW_MUTEX_LOCK;
+	/* force the return value to nul in case the following tests fail */
+	if(buffer)
+		strcpy(buffer,"");
+#if GTK_MAJOR_VERSION > 1
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+#else
+	if(GTK_IS_BOX(handle))
+#endif
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+#if GTK_MAJOR_VERSION > 1
+		if(tmp && GTK_IS_TEXT_VIEW(tmp))
+		{
+			GtkTextBuffer *tbuffer;
+			GtkTextIter start, end;
+
+			tbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tmp));
+			gtk_text_buffer_get_iter_at_offset(tbuffer, &start, startpoint);
+			gtk_text_buffer_get_iter_at_offset(tbuffer, &end, startpoint + length);
+			text = gtk_text_iter_get_text(&start, &end);
+			if(text) /* Should this get freed? */
+			{
+				if(buffer)
+					strcpy(buffer, text);
+			}
+		}
+#else
+		if(tmp && GTK_IS_TEXT(tmp))
+		{
+			text = gtk_editable_get_chars(GTK_EDITABLE(&(GTK_TEXT(tmp)->editable)), startpoint, startpoint + length - 1);
+			if(text)
+			{
+				if(buffer)
+					strcpy(buffer, text);
+				g_free(text);
+			}
+		}
+#endif
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Obtains information about an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to be queried.
+ *          bytes: A pointer to a variable to return the total bytes.
+ *          lines: A pointer to a variable to return the number of lines.
+ */
+void dw_mle_query(HWND handle, unsigned long *bytes, unsigned long *lines)
+{
+	int _locked_by_me = FALSE;
+
+	if(bytes)
+		*bytes = 0;
+	if(lines)
+		*lines = 0;
+
+	DW_MUTEX_LOCK;
+#if GTK_MAJOR_VERSION > 1
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+		if(tmp && GTK_IS_TEXT_VIEW(tmp))
+		{
+			GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(tmp));
+      
+			if(bytes)
+				*bytes = gtk_text_buffer_get_char_count(buffer) + 1;
+			if(lines)
+				*lines = gtk_text_buffer_get_line_count(buffer) + 1;
+		}
+	}
+#else
+	if(GTK_IS_BOX(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+		if(tmp && GTK_IS_TEXT(tmp))
+		{
+			if(bytes)
+				*bytes = gtk_text_get_length(GTK_TEXT(tmp)) + 1;
+			if(lines)
+			{
+				gchar *text;
+
+				*lines = 0;
+				text = gtk_editable_get_chars(GTK_EDITABLE(&(GTK_TEXT(tmp)->editable)), 0, gtk_text_get_length(GTK_TEXT(tmp)));
+
+				if(text)
+				{
+					int z, len = strlen(text);
+
+					for(z=0;z<len;z++)
+					{
+						if(text[z] == '\n')
+							(*lines)++;
+					}
+					g_free(text);
+				}
+			}
+		}
+	}
+#endif
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Deletes text from an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to be deleted from.
+ *          startpoint: Point to start deleting text.
+ *          length: Amount of text to be deleted.
+ */
+void dw_mle_delete(HWND handle, int startpoint, int length)
+{
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+#if GTK_MAJOR_VERSION > 1
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+#else
+	if(GTK_IS_BOX(handle))
+#endif
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+#if GTK_MAJOR_VERSION > 1
+		if(tmp && GTK_IS_TEXT_VIEW(tmp))
+		{
+			GtkTextBuffer *tbuffer;
+			GtkTextIter start, end;
+
+			tbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tmp));
+			gtk_text_buffer_get_iter_at_offset(tbuffer, &start, startpoint);
+			gtk_text_buffer_get_iter_at_offset(tbuffer, &end, startpoint + length);
+			gtk_text_buffer_delete(tbuffer, &start, &end);
+		}
+#else
+		if(tmp && GTK_IS_TEXT(tmp))
+		{
+			gtk_text_set_point(GTK_TEXT(tmp), startpoint);
+			gtk_text_forward_delete(GTK_TEXT(tmp), length);
+		}
+#endif
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Clears all text from an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to be cleared.
+ */
+void dw_mle_clear(HWND handle)
+{
+	int length, _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+#if GTK_MAJOR_VERSION > 1
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+		if(tmp && GTK_IS_TEXT_VIEW(tmp))
+		{
+			GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(tmp));
+      
+			length = -1;
+			gtk_text_buffer_set_text(buffer, "", length);
+		}
+	}
+#else
+	if(GTK_IS_BOX(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+		if(tmp && GTK_IS_TEXT(tmp))
+		{
+			length = gtk_text_get_length(GTK_TEXT(tmp));
+			gtk_text_set_point(GTK_TEXT(tmp), 0);
+			gtk_text_forward_delete(GTK_TEXT(tmp), length);
+		}
+	}
+#endif
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Sets the visible line of an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE.
+ *          line: Line to be visible.
+ */
+void dw_mle_set_visible(HWND handle, int line)
+{
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+#if GTK_MAJOR_VERSION > 1
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+		if(tmp && GTK_IS_TEXT_VIEW(tmp))
+		{
+			GtkTextBuffer *tbuffer;
+			GtkTextIter iter;
+			GtkTextMark *mark = (GtkTextMark *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_mark");
+
+			tbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tmp));
+			gtk_text_buffer_get_iter_at_offset(tbuffer, &iter, 0);
+			gtk_text_iter_set_line(&iter, line);
+			if(!mark)
+			{
+				mark = gtk_text_buffer_create_mark(tbuffer, NULL, &iter, FALSE);
+				gtk_object_set_data(GTK_OBJECT(handle), "_dw_mark", (gpointer)mark);
+			}
+			else
+				gtk_text_buffer_move_mark(tbuffer, mark, &iter);
+			gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(tmp), mark,
+										 0, FALSE, 0, 0);
+		}
+	}
+#else
+	if(GTK_IS_BOX(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+		if(tmp && GTK_IS_TEXT(tmp))
+		{
+			unsigned long lines;
+			float pos, ratio;
+
+			dw_mle_query(handle, NULL, &lines);
+
+			if(lines)
+			{
+				ratio = (float)line/(float)lines;
+
+				pos = (ratio * (float)(GTK_TEXT(tmp)->vadj->upper - GTK_TEXT(tmp)->vadj->lower)) + GTK_TEXT(tmp)->vadj->lower;
+
+				gtk_adjustment_set_value(GTK_TEXT(tmp)->vadj, pos);
+			}
+		}
+	}
+#endif
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Sets the editablity of an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE.
+ *          state: TRUE if it can be edited, FALSE for readonly.
+ */
+void dw_mle_set_editable(HWND handle, int state)
+{
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+#if GTK_MAJOR_VERSION > 1
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+		if(tmp && GTK_IS_TEXT_VIEW(tmp))
+			gtk_text_view_set_editable(GTK_TEXT_VIEW(tmp), state);
+	}
+#else
+	if(GTK_IS_BOX(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+		if(tmp && GTK_IS_TEXT(tmp))
+			gtk_text_set_editable(GTK_TEXT(tmp), state);
+	}
+#endif
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Sets the word wrap state of an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE.
+ *          state: TRUE if it wraps, FALSE if it doesn't.
+ */
+void dw_mle_set_word_wrap(HWND handle, int state)
+{
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+#if GTK_MAJOR_VERSION > 1
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+		if(tmp && GTK_IS_TEXT_VIEW(tmp))
+			gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(tmp), GTK_WRAP_WORD);
+	}
+#else
+	if(GTK_IS_BOX(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+		if(tmp && GTK_IS_TEXT(tmp))
+		{
+			gtk_text_set_word_wrap(GTK_TEXT(tmp), state);
+			gtk_text_set_line_wrap(GTK_TEXT(tmp), state);
+		}
+	}
+#endif
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Sets the current cursor position of an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to be positioned.
+ *          point: Point to position cursor.
+ */
+void dw_mle_set(HWND handle, int point)
+{
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+#if GTK_MAJOR_VERSION > 1
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+#else
+	if(GTK_IS_BOX(handle))
+#endif
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+#if GTK_MAJOR_VERSION > 1
+		if(tmp && GTK_IS_TEXT_VIEW(tmp))
+		{
+			GtkTextBuffer *tbuffer;
+			GtkTextIter iter;
+			GtkTextMark *mark = (GtkTextMark *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_mark");
+
+			tbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tmp));
+			gtk_text_buffer_get_iter_at_offset(tbuffer, &iter, point);
+			if(!mark)
+			{
+				mark = gtk_text_buffer_create_mark(tbuffer, NULL, &iter, FALSE);
+				gtk_object_set_data(GTK_OBJECT(handle), "_dw_mark", (gpointer)mark);
+			}
+			else
+				gtk_text_buffer_move_mark(tbuffer, mark, &iter);
+			gtk_text_buffer_place_cursor(tbuffer, &iter);
+			gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(tmp), mark,
+										 0, FALSE, 0, 0);
+		}
+#else
+		if(tmp && GTK_IS_TEXT(tmp))
+		{
+			unsigned long chars;
+			float pos, ratio;
+
+			dw_mle_query(handle, &chars, NULL);
+
+			if(chars)
+			{
+				ratio = (float)point/(float)chars;
+
+				pos = (ratio * (float)(GTK_TEXT(tmp)->vadj->upper - GTK_TEXT(tmp)->vadj->lower)) + GTK_TEXT(tmp)->vadj->lower;
+
+				gtk_adjustment_set_value(GTK_TEXT(tmp)->vadj, pos);
+			}
+			gtk_text_set_point(GTK_TEXT(tmp), point);
+		}
+#endif
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Finds text in an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to be cleared.
+ *          text: Text to search for.
+ *          point: Start point of search.
+ *          flags: Search specific flags.
+ */
+int dw_mle_search(HWND handle, char *text, int point, unsigned long flags)
+{
+	int _locked_by_me = FALSE, retval = 0;
+
+	DW_MUTEX_LOCK;
+#if GTK_MAJOR_VERSION > 1
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+#else
+	if(GTK_IS_BOX(handle))
+#endif
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+#if GTK_MAJOR_VERSION > 1
+		if(tmp && GTK_IS_TEXT_VIEW(tmp))
+		{
+			GtkTextBuffer *tbuffer;
+			GtkTextIter iter, found;
+
+			tbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tmp));
+			gtk_text_buffer_get_iter_at_offset(tbuffer, &iter, point);
+			gtk_text_iter_forward_search(&iter, text, GTK_TEXT_SEARCH_TEXT_ONLY, &found, NULL, NULL);
+			retval = gtk_text_iter_get_offset(&found);  
+		}
+#else
+		if(tmp && GTK_IS_TEXT(tmp))
+		{
+			int len = gtk_text_get_length(GTK_TEXT(tmp));
+			gchar *tmpbuf;
+
+			tmpbuf = gtk_editable_get_chars(GTK_EDITABLE(&(GTK_TEXT(tmp)->editable)), 0, len);
+			if(tmpbuf)
+			{
+				int z, textlen;
+
+				textlen = strlen(text);
+
+				if(flags & DW_MLE_CASESENSITIVE)
+				{
+					for(z=point;z<(len-textlen) && !retval;z++)
+					{
+						if(strncmp(&tmpbuf[z], text, textlen) == 0)
+							retval = z + textlen;
+					}
+				}
+				else
+				{
+					for(z=point;z<(len-textlen) && !retval;z++)
+					{
+						if(strncasecmp(&tmpbuf[z], text, textlen) == 0)
+							retval = z + textlen;
+					}
+				}
+
+				if(retval)
+				{
+					gtk_text_set_point(GTK_TEXT(tmp), retval - textlen);
+					gtk_editable_select_region(&(GTK_TEXT(tmp)->editable), retval - textlen, retval);
+				}
+
+				g_free(tmpbuf);
+			}
+		}
+#endif
+	}
+	DW_MUTEX_UNLOCK;
+	return retval;
+}
+
+/*
+ * Stops redrawing of an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to freeze.
+ */
+void dw_mle_freeze(HWND handle)
+{
+#if GTK_MAJOR_VERSION < 2
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_BOX(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+		if(tmp && GTK_IS_TEXT(tmp))
+		{
+			gtk_text_freeze(GTK_TEXT(tmp));
+		}
+	}
+	DW_MUTEX_UNLOCK;
+#endif
+}
+
+/*
+ * Resumes redrawing of an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to thaw.
+ */
+void dw_mle_thaw(HWND handle)
+{
+#if GTK_MAJOR_VERSION < 2
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_BOX(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+		if(tmp && GTK_IS_TEXT(tmp))
+		{
+			gtk_text_thaw(GTK_TEXT(tmp));
+		}
+	}
+	DW_MUTEX_UNLOCK;
+#endif
+}
+
+/*
+ * Returns the range of the percent bar.
+ * Parameters:
+ *          handle: Handle to the percent bar to be queried.
+ */
+unsigned int dw_percent_query_range(HWND handle)
+{
+	return 100;
+}
+
+/*
+ * Sets the percent bar position.
+ * Parameters:
+ *          handle: Handle to the percent bar to be set.
+ *          position: Position of the percent bar withing the range.
+ */
+void dw_percent_set_pos(HWND handle, unsigned int position)
+{
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	gtk_progress_bar_update(GTK_PROGRESS_BAR(handle), (gfloat)position/100);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Returns the position of the slider.
+ * Parameters:
+ *          handle: Handle to the slider to be queried.
+ */
+unsigned int dw_slider_query_pos(HWND handle)
+{
+	int val = 0, _locked_by_me = FALSE;
+	GtkAdjustment *adjustment;
+
+	if(!handle)
+		return 0;
+
+	DW_MUTEX_LOCK;
+	adjustment = (GtkAdjustment *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_adjustment");
+	if(adjustment)
+	{
+		int max = _round_value(adjustment->upper) - 1;
+		int thisval = _round_value(adjustment->value);
+
+		if(GTK_IS_VSCALE(handle))
+			val = max - thisval;
+        else
+			val = thisval;
+	}
+	DW_MUTEX_UNLOCK;
+	return val;
+}
+
+/*
+ * Sets the slider position.
+ * Parameters:
+ *          handle: Handle to the slider to be set.
+ *          position: Position of the slider withing the range.
+ */
+void dw_slider_set_pos(HWND handle, unsigned int position)
+{
+	int _locked_by_me = FALSE;
+	GtkAdjustment *adjustment;
+
+	if(!handle)
+		return;
+
+	DW_MUTEX_LOCK;
+	adjustment = (GtkAdjustment *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_adjustment");
+	if(adjustment)
+	{
+		int max = _round_value(adjustment->upper) - 1;
+
+		if(GTK_IS_VSCALE(handle))
+			gtk_adjustment_set_value(adjustment, (gfloat)(max - position));
+        else
+			gtk_adjustment_set_value(adjustment, (gfloat)position);
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Returns the position of the scrollbar.
+ * Parameters:
+ *          handle: Handle to the scrollbar to be queried.
+ */
+unsigned int dw_scrollbar_query_pos(HWND handle)
+{
+	int val = 0, _locked_by_me = FALSE;
+	GtkAdjustment *adjustment;
+
+	if(!handle)
+		return 0;
+
+	DW_MUTEX_LOCK;
+	adjustment = (GtkAdjustment *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_adjustment");
+	if(adjustment)
+		val = _round_value(adjustment->value);
+	DW_MUTEX_UNLOCK;
+	return val;
+}
+
+/*
+ * Sets the scrollbar position.
+ * Parameters:
+ *          handle: Handle to the scrollbar to be set.
+ *          position: Position of the scrollbar withing the range.
+ */
+void dw_scrollbar_set_pos(HWND handle, unsigned int position)
+{
+	int _locked_by_me = FALSE;
+	GtkAdjustment *adjustment;
+
+	if(!handle)
+		return;
+
+	DW_MUTEX_LOCK;
+	adjustment = (GtkAdjustment *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_adjustment");
+	if(adjustment)
+		gtk_adjustment_set_value(adjustment, (gfloat)position);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Sets the scrollbar range.
+ * Parameters:
+ *          handle: Handle to the scrollbar to be set.
+ *          range: Maximum range value.
+ *          visible: Visible area relative to the range.
+ */
+void API dw_scrollbar_set_range(HWND handle, unsigned int range, unsigned int visible)
+{
+	int _locked_by_me = FALSE;
+	GtkAdjustment *adjustment;
+
+	if(!handle)
+		return;
+
+	DW_MUTEX_LOCK;
+	adjustment = (GtkAdjustment *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_adjustment");
+	if(adjustment)
+	{
+		adjustment->upper = (gdouble)range;
+		adjustment->page_increment = adjustment->page_size = (gdouble)visible;
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Sets the spinbutton value.
+ * Parameters:
+ *          handle: Handle to the spinbutton to be set.
+ *          position: Current value of the spinbutton.
+ */
+void dw_spinbutton_set_pos(HWND handle, long position)
+{
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	gtk_spin_button_set_value(GTK_SPIN_BUTTON(handle), (gfloat)position);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Sets the spinbutton limits.
+ * Parameters:
+ *          handle: Handle to the spinbutton to be set.
+ *          position: Current value of the spinbutton.
+ *          position: Current value of the spinbutton.
+ */
+void dw_spinbutton_set_limits(HWND handle, long upper, long lower)
+{
+	long curval;
+	GtkAdjustment *adj;
+	int _locked_by_me = FALSE;
+
+	curval = dw_spinbutton_query(handle);
+	DW_MUTEX_LOCK;
+	adj = (GtkAdjustment *)gtk_adjustment_new((gfloat)curval, (gfloat)lower, (gfloat)upper, 1.0, 5.0, 0.0);
+	gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(handle), adj);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Sets the entryfield character limit.
+ * Parameters:
+ *          handle: Handle to the spinbutton to be set.
+ *          limit: Number of characters the entryfield will take.
+ */
+void dw_entryfield_set_limit(HWND handle, ULONG limit)
+{
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	gtk_entry_set_max_length(GTK_ENTRY(handle), limit);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Returns the current value of the spinbutton.
+ * Parameters:
+ *          handle: Handle to the spinbutton to be queried.
+ */
+long dw_spinbutton_query(HWND handle)
+{
+	long retval;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	retval = (long)gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(handle));
+	DW_MUTEX_UNLOCK;
+
+	return retval;
+}
+
+/*
+ * Returns the state of the checkbox.
+ * Parameters:
+ *          handle: Handle to the checkbox to be queried.
+ */
+int dw_checkbox_query(HWND handle)
+{
+	int retval;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	retval = GTK_TOGGLE_BUTTON(handle)->active;
+	DW_MUTEX_UNLOCK;
+
+	return retval;
+}
+
+/*
+ * Sets the state of the checkbox.
+ * Parameters:
+ *          handle: Handle to the checkbox to be queried.
+ *          value: TRUE for checked, FALSE for unchecked.
+ */
+void dw_checkbox_set(HWND handle, int value)
+{
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(handle), value);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Inserts an item into a tree window (widget) after another item.
+ * Parameters:
+ *          handle: Handle to the tree to be inserted.
+ *          item: Handle to the item to be positioned after.
+ *          title: The text title of the entry.
+ *          icon: Handle to coresponding icon.
+ *          parent: Parent handle or 0 if root.
+ *          itemdata: Item specific data.
+ */
+HTREEITEM dw_tree_insert_after(HWND handle, HTREEITEM item, char *title, unsigned long icon, HTREEITEM parent, void *itemdata)
+{
+#if GTK_MAJOR_VERSION > 1
+	GtkWidget *tree;
+	GtkTreeIter *iter;
+	GtkTreeStore *store;
+	GdkPixbuf *pixbuf;
+	HTREEITEM retval = 0;
+	int _locked_by_me = FALSE;
+
+	if(!handle)
+		return NULL;
+
+	DW_MUTEX_LOCK;
+	if((tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle)))
+		&& GTK_IS_TREE_VIEW(tree) &&
+		(store = (GtkTreeStore *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_store")))
+	{
+		iter = (GtkTreeIter *)malloc(sizeof(GtkTreeIter));
+        
+		pixbuf = _find_pixbuf(icon);
+
+		gtk_tree_store_insert_after(store, iter, (GtkTreeIter *)parent, (GtkTreeIter *)item);
+		gtk_tree_store_set (store, iter, 0, title, 1, pixbuf, 2, itemdata, 3, iter, -1);
+		if(pixbuf && !(icon & (1 << 31)))
+			g_object_unref(pixbuf);
+		retval = (HTREEITEM)iter;
+	}
+	DW_MUTEX_UNLOCK;
+  
+	return retval;
+#else
+	GtkWidget *newitem, *tree, *subtree, *label, *hbox, *pixmap;
+	GdkPixmap *gdkpix;
+	GdkBitmap *gdkbmp = NULL;
+	int position = -1;
+	int _locked_by_me = FALSE;
+
+	if(!handle)
+		return NULL;
+
+	DW_MUTEX_LOCK;
+	tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+	if(!tree || !GTK_IS_TREE(tree))
+	{
+		DW_MUTEX_UNLOCK;
+		return NULL;
+	}
+
+	if(item && GTK_IS_TREE_ITEM(item))
+		position = gtk_tree_child_position(GTK_TREE(tree), item);
+
+	position++;
+
+	newitem = gtk_tree_item_new();
+	label = gtk_label_new(title);
+	gtk_object_set_data(GTK_OBJECT(newitem), "_dw_text", (gpointer)strdup(title));
+	gtk_object_set_data(GTK_OBJECT(newitem), "_dw_itemdata", (gpointer)itemdata);
+	gtk_object_set_data(GTK_OBJECT(newitem), "_dw_tree", (gpointer)tree);
+	gtk_object_set_data(GTK_OBJECT(newitem), "_dw_parent", (gpointer)parent);
+	hbox = gtk_hbox_new(FALSE, 2);
+	gtk_object_set_data(GTK_OBJECT(newitem), "_dw_hbox", (gpointer)hbox);
+	gdkpix = _find_pixmap(&gdkbmp, icon, hbox, NULL, NULL);
+	gtk_container_add(GTK_CONTAINER(newitem), hbox);
+	if(gdkpix)
+	{
+		pixmap = gtk_pixmap_new(gdkpix, gdkbmp);
+		gtk_box_pack_start(GTK_BOX(hbox), pixmap, FALSE, TRUE, 0);
+		gtk_widget_show(pixmap);
+	}
+	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);
+	gtk_widget_show(label);
+	gtk_widget_show(hbox);
+
+	{
+		void *thisfunc = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_expand_func");
+		void *mydata = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_expand_data");
+		SignalHandler work = _get_signal_handler(tree, mydata);
+
+		if(thisfunc && work.window)
+		{
+			int sigid = _set_signal_handler(newitem, work.window, work.func, work.data, thisfunc);
+			gint cid =gtk_signal_connect(GTK_OBJECT(newitem), "expand", GTK_SIGNAL_FUNC(thisfunc),(gpointer)sigid);
+			_set_signal_handler_id(newitem, sigid, cid);
+		}
+	}
+
+	_dw_ignore_expand = 1;
+	if(parent)
+	{
+		subtree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(parent));
+		if(!subtree || !GTK_IS_TREE(subtree))
+		{
+			void *thisfunc = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_select_child_func");
+			void *mydata = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_select_child_data");
+			SignalHandler work = _get_signal_handler(tree, mydata);
+
+			subtree = gtk_tree_new();
+
+			if(thisfunc && work.window)
+			{
+				int sigid = _set_signal_handler(subtree, work.window, work.func, work.data, thisfunc);
+				gint cid =gtk_signal_connect(GTK_OBJECT(subtree), "select-child", GTK_SIGNAL_FUNC(thisfunc),(gpointer)sigid);
+				_set_signal_handler_id(subtree, sigid, cid);
+			}
+
+			thisfunc = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_container_context_func");
+			mydata = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_container_context_data");
+			work = _get_signal_handler(tree, mydata);
+
+			if(thisfunc && work.window)
+			{
+				int sigid = _set_signal_handler(subtree, work.window, work.func, work.data, thisfunc);
+				gint cid =gtk_signal_connect(GTK_OBJECT(subtree), "button_press_event", GTK_SIGNAL_FUNC(thisfunc),(gpointer)sigid);
+				_set_signal_handler_id(subtree, sigid, cid);
+			}
+
+			gtk_object_set_user_data(GTK_OBJECT(parent), subtree);
+			gtk_tree_set_selection_mode(GTK_TREE(subtree), GTK_SELECTION_SINGLE);
+			gtk_tree_set_view_mode(GTK_TREE(subtree), GTK_TREE_VIEW_ITEM);
+			gtk_tree_item_set_subtree(GTK_TREE_ITEM(parent), subtree);
+			gtk_object_set_data(GTK_OBJECT(subtree), "_dw_parentitem", (gpointer)parent);
+			gtk_tree_item_collapse(GTK_TREE_ITEM(parent));
+			gtk_widget_show(subtree);
+			gtk_tree_item_expand(GTK_TREE_ITEM(parent));
+			gtk_tree_item_collapse(GTK_TREE_ITEM(parent));
+		}
+		gtk_object_set_data(GTK_OBJECT(newitem), "_dw_parenttree", (gpointer)subtree);
+		gtk_tree_insert(GTK_TREE(subtree), newitem, position);
+	}
+	else
+	{
+		gtk_object_set_data(GTK_OBJECT(newitem), "_dw_parenttree", (gpointer)tree);
+		gtk_tree_insert(GTK_TREE(tree), newitem, position);
+	}
+	gtk_tree_item_expand(GTK_TREE_ITEM(newitem));
+	gtk_tree_item_collapse(GTK_TREE_ITEM(newitem));
+	gtk_widget_show(newitem);
+	_dw_ignore_expand = 0;
+	DW_MUTEX_UNLOCK;
+	return (HTREEITEM)newitem;
+#endif
+}
+
+/*
+ * Inserts an item into a tree window (widget).
+ * Parameters:
+ *          handle: Handle to the tree to be inserted.
+ *          title: The text title of the entry.
+ *          icon: Handle to coresponding icon.
+ *          parent: Parent handle or 0 if root.
+ *          itemdata: Item specific data.
+ */
+HTREEITEM dw_tree_insert(HWND handle, char *title, unsigned long icon, HTREEITEM parent, void *itemdata)
+{
+#if GTK_MAJOR_VERSION > 1
+	GtkWidget *tree;
+	GtkTreeIter *iter;
+	GtkTreeStore *store;
+	GdkPixbuf *pixbuf;
+	HTREEITEM retval = 0;
+	int _locked_by_me = FALSE;
+
+	if(!handle)
+		return NULL;
+
+	DW_MUTEX_LOCK;
+	if((tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle)))
+		&& GTK_IS_TREE_VIEW(tree) &&
+		(store = (GtkTreeStore *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_store")))
+	{
+		iter = (GtkTreeIter *)malloc(sizeof(GtkTreeIter));
+    
+		pixbuf = _find_pixbuf(icon);
+
+		gtk_tree_store_append (store, iter, (GtkTreeIter *)parent);
+		gtk_tree_store_set (store, iter, 0, title, 1, pixbuf, 2, itemdata, 3, iter, -1);
+		if(pixbuf && !(icon & (1 << 31)))
+			g_object_unref(pixbuf);
+		retval = (HTREEITEM)iter;
+	}
+	DW_MUTEX_UNLOCK;
+
+	return retval;
+#else
+	GtkWidget *item, *tree, *subtree, *label, *hbox, *pixmap;
+	GdkPixmap *gdkpix;
+	GdkBitmap *gdkbmp = NULL;
+	int _locked_by_me = FALSE;
+
+	if(!handle)
+		return NULL;
+
+	DW_MUTEX_LOCK;
+	tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+	if(!tree || !GTK_IS_TREE(tree))
+	{
+		DW_MUTEX_UNLOCK;
+		return NULL;
+	}
+	item = gtk_tree_item_new();
+	label = gtk_label_new(title);
+	gtk_object_set_data(GTK_OBJECT(item), "_dw_text", (gpointer)strdup(title));
+	gtk_object_set_data(GTK_OBJECT(item), "_dw_itemdata", (gpointer)itemdata);
+	gtk_object_set_data(GTK_OBJECT(item), "_dw_tree", (gpointer)tree);
+	gtk_object_set_data(GTK_OBJECT(item), "_dw_parent", (gpointer)parent);
+	hbox = gtk_hbox_new(FALSE, 2);
+	gtk_object_set_data(GTK_OBJECT(item), "_dw_hbox", (gpointer)hbox);
+	gdkpix = _find_pixmap(&gdkbmp, icon, hbox, NULL, NULL);
+	gtk_container_add(GTK_CONTAINER(item), hbox);
+	if(gdkpix)
+	{
+		pixmap = gtk_pixmap_new(gdkpix, gdkbmp);
+		gtk_box_pack_start(GTK_BOX(hbox), pixmap, FALSE, TRUE, 0);
+		gtk_widget_show(pixmap);
+	}
+	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);
+	gtk_widget_show(label);
+	gtk_widget_show(hbox);
+
+	{
+		void *thisfunc = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_expand_func");
+		void *mydata = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_expand_data");
+		SignalHandler work = _get_signal_handler(tree, mydata);
+
+		if(thisfunc && work.window)
+		{
+			int sigid = _set_signal_handler(item, work.window, work.func, work.data, thisfunc);
+			gint cid =gtk_signal_connect(GTK_OBJECT(item), "expand", GTK_SIGNAL_FUNC(thisfunc),(gpointer)sigid);
+			_set_signal_handler_id(item, sigid, cid);
+		}
+	}
+
+	_dw_ignore_expand = 1;
+	if(parent)
+	{
+		subtree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(parent));
+		if(!subtree || !GTK_IS_TREE(subtree))
+		{
+			void *thisfunc = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_select_child_func");
+			void *mydata = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_select_child_data");
+			SignalHandler work = _get_signal_handler(tree, mydata);
+
+			subtree = gtk_tree_new();
+
+			if(thisfunc && work.window)
+			{
+				int sigid = _set_signal_handler(subtree, work.window, work.func, work.data, thisfunc);
+				gint cid =gtk_signal_connect(GTK_OBJECT(subtree), "select-child", GTK_SIGNAL_FUNC(thisfunc),(gpointer)sigid);
+				_set_signal_handler_id(subtree, sigid, cid);
+			}
+
+			thisfunc = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_container_context_func");
+			mydata = (void *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_container_context_data");
+			work = _get_signal_handler(tree, mydata);
+
+			if(thisfunc && work.window)
+			{
+				int sigid = _set_signal_handler(subtree, work.window, work.func, work.data, thisfunc);
+				gint cid =gtk_signal_connect(GTK_OBJECT(subtree), "button_press_event", GTK_SIGNAL_FUNC(thisfunc),(gpointer)sigid);
+				_set_signal_handler_id(subtree, sigid, cid);
+			}
+
+			gtk_object_set_user_data(GTK_OBJECT(parent), subtree);
+			gtk_tree_set_selection_mode(GTK_TREE(subtree), GTK_SELECTION_SINGLE);
+			gtk_tree_set_view_mode(GTK_TREE(subtree), GTK_TREE_VIEW_ITEM);
+			gtk_tree_item_set_subtree(GTK_TREE_ITEM(parent), subtree);
+			gtk_object_set_data(GTK_OBJECT(subtree), "_dw_parentitem", (gpointer)parent);
+			gtk_tree_item_collapse(GTK_TREE_ITEM(parent));
+			gtk_widget_show(subtree);
+			gtk_tree_item_expand(GTK_TREE_ITEM(parent));
+			gtk_tree_item_collapse(GTK_TREE_ITEM(parent));
+		}
+		gtk_object_set_data(GTK_OBJECT(item), "_dw_parenttree", (gpointer)subtree);
+		gtk_tree_append(GTK_TREE(subtree), item);
+	}
+	else
+	{
+		gtk_object_set_data(GTK_OBJECT(item), "_dw_parenttree", (gpointer)tree);
+		gtk_tree_append(GTK_TREE(tree), item);
+	}
+	gtk_tree_item_expand(GTK_TREE_ITEM(item));
+	gtk_tree_item_collapse(GTK_TREE_ITEM(item));
+	gtk_widget_show(item);
+	_dw_ignore_expand = 0;
+	DW_MUTEX_UNLOCK;
+	return (HTREEITEM)item;
+#endif
+}
+
+/*
+ * Sets the text and icon of an item in a tree window (widget).
+ * Parameters:
+ *          handle: Handle to the tree containing the item.
+ *          item: Handle of the item to be modified.
+ *          title: The text title of the entry.
+ *          icon: Handle to coresponding icon.
+ */
+void dw_tree_set(HWND handle, HTREEITEM item, char *title, unsigned long icon)
+{
+#if GTK_MAJOR_VERSION > 1
+	GtkWidget *tree;
+	GtkTreeStore *store;
+	GdkPixbuf *pixbuf;
+	int _locked_by_me = FALSE;
+
+	if(!handle)
+		return;
+
+	DW_MUTEX_LOCK;
+	if((tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle)))
+		&& GTK_IS_TREE_VIEW(tree) &&
+		(store = (GtkTreeStore *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_store")))
+	{
+		pixbuf = _find_pixbuf(icon);
+
+		gtk_tree_store_set(store, (GtkTreeIter *)item, 0, title, 1, pixbuf, -1);
+		if(pixbuf && !(icon & (1 << 31)))
+			g_object_unref(pixbuf);
+	}
+	DW_MUTEX_UNLOCK;
+#else
+	GtkWidget *label, *hbox, *pixmap;
+	GdkPixmap *gdkpix;
+	GdkBitmap *gdkbmp = NULL;
+	char *oldtext;
+	int _locked_by_me = FALSE;
+
+	if(!handle || !item)
+		return;
+
+	DW_MUTEX_LOCK;
+	oldtext = (char *)gtk_object_get_data(GTK_OBJECT(item), "_dw_text");
+	if(oldtext)
+		free(oldtext);
+	label = gtk_label_new(title);
+	gtk_object_set_data(GTK_OBJECT(item), "_dw_text", (gpointer)strdup(title));
+	hbox = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(item), "_dw_hbox");
+	gtk_widget_destroy(hbox);
+	hbox = gtk_hbox_new(FALSE, 2);
+	gtk_object_set_data(GTK_OBJECT(item), "_dw_hbox", (gpointer)hbox);
+	gdkpix = _find_pixmap(&gdkbmp, icon, hbox, NULL, NULL);
+	gtk_container_add(GTK_CONTAINER(item), hbox);
+	if(gdkpix)
+	{
+		pixmap = gtk_pixmap_new(gdkpix, gdkbmp);
+		gtk_box_pack_start(GTK_BOX(hbox), pixmap, FALSE, TRUE, 0);
+		gtk_widget_show(pixmap);
+	}
+	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);
+	gtk_widget_show(label);
+	gtk_widget_show(hbox);
+	DW_MUTEX_UNLOCK;
+#endif
+}
+
+/*
+ * Sets the item data of a tree item.
+ * Parameters:
+ *          handle: Handle to the tree containing the item.
+ *          item: Handle of the item to be modified.
+ *          itemdata: User defined data to be associated with item.
+ */
+void dw_tree_set_data(HWND handle, HTREEITEM item, void *itemdata)
+{
+#if GTK_MAJOR_VERSION > 1
+	GtkWidget *tree;
+	GtkTreeStore *store;
+	int _locked_by_me = FALSE;
+
+	if(!handle || !item)
+		return;
+
+	DW_MUTEX_LOCK;
+	if((tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle)))
+		&& GTK_IS_TREE_VIEW(tree) &&
+		(store = (GtkTreeStore *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_store")))
+			gtk_tree_store_set(store, (GtkTreeIter *)item, 2, itemdata, -1);
+	DW_MUTEX_UNLOCK;
+#else
+	int _locked_by_me = FALSE;
+
+	if(!handle || !item)
+		return;
+
+	DW_MUTEX_LOCK;
+	gtk_object_set_data(GTK_OBJECT(item), "_dw_itemdata", (gpointer)itemdata);
+	DW_MUTEX_UNLOCK;
+#endif
+}
+
+/*
+ * Gets the text an item in a tree window (widget).
+ * Parameters:
+ *          handle: Handle to the tree containing the item.
+ *          item: Handle of the item to be modified.
+ */
+char * API dw_tree_get_title(HWND handle, HTREEITEM item)
+{
+	int _locked_by_me = FALSE;
+	char *text = NULL;
+
+	if(!handle || !item)
+		return text;
+
+	DW_MUTEX_LOCK;
+#if GTK_MAJOR_VERSION > 1
+	GtkWidget *tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+	GtkTreeModel *store;
+
+	if(tree && GTK_IS_TREE_VIEW(tree) &&
+	   (store = (GtkTreeModel *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_store")))
+		gtk_tree_model_get(store, (GtkTreeIter *)item, 0, &text, -1);
+#else
+	text = (char *)gtk_object_get_data(GTK_OBJECT(item), "_dw_text");
+#endif
+	DW_MUTEX_UNLOCK;
+	return text;
+}
+
+/*
+ * Gets the text an item in a tree window (widget).
+ * Parameters:
+ *          handle: Handle to the tree containing the item.
+ *          item: Handle of the item to be modified.
+ */
+HTREEITEM API dw_tree_get_parent(HWND handle, HTREEITEM item)
+{
+	int _locked_by_me = FALSE;
+	HTREEITEM parent = (HTREEITEM)0;
+
+	if(!handle || !item)
+		return parent;
+
+	DW_MUTEX_LOCK;
+#if GTK_MAJOR_VERSION > 1
+	GtkWidget *tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+	GtkTreeModel *store;
+
+	if(tree && GTK_IS_TREE_VIEW(tree) &&
+	   (store = (GtkTreeModel *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_store")))
+	{
+		GtkTreeIter *p = malloc(sizeof(GtkTreeIter));
+
+		if(gtk_tree_model_iter_parent(store, p, (GtkTreeIter *)item))
+			parent = p;
+		else
+			free(p);
+	}
+#else
+	parent = (HTREEITEM)gtk_object_get_data(GTK_OBJECT(item), "_dw_parent");
+#endif
+	DW_MUTEX_UNLOCK;
+	return parent;
+}
+
+/*
+ * Gets the item data of a tree item.
+ * Parameters:
+ *          handle: Handle to the tree containing the item.
+ *          item: Handle of the item to be modified.
+ */
+void *dw_tree_get_data(HWND handle, HTREEITEM item)
+{
+	void *ret = NULL;
+#if GTK_MAJOR_VERSION > 1
+	GtkWidget *tree;
+	GtkTreeModel *store;
+	int _locked_by_me = FALSE;
+
+	if(!handle || !item)
+		return NULL;
+
+	DW_MUTEX_LOCK;
+	if((tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle)))
+		&& GTK_IS_TREE_VIEW(tree) &&
+		(store = (GtkTreeModel *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_store")))
+			gtk_tree_model_get(store, (GtkTreeIter *)item, 2, &ret, -1);
+	DW_MUTEX_UNLOCK;
+#else
+	int _locked_by_me = FALSE;
+
+	if(!handle || !item)
+		return NULL;
+
+	DW_MUTEX_LOCK;
+	ret = (void *)gtk_object_get_data(GTK_OBJECT(item), "_dw_itemdata");
+	DW_MUTEX_UNLOCK;
+#endif
+	return ret;
+}
+
+/*
+ * Sets this item as the active selection.
+ * Parameters:
+ *       handle: Handle to the tree window (widget) to be selected.
+ *       item: Handle to the item to be selected.
+ */
+void dw_tree_item_select(HWND handle, HTREEITEM item)
+{
+#if GTK_MAJOR_VERSION > 1
+	GtkWidget *tree;
+	GtkTreeStore *store;
+	int _locked_by_me = FALSE;
+
+	if(!handle || !item)
+		return;
+
+	DW_MUTEX_LOCK;
+	if((tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle)))
+		&& GTK_IS_TREE_VIEW(tree) &&
+		(store = (GtkTreeStore *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_store")))
+	{    
+		GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), (GtkTreeIter *)item);
+		GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
+    
+		gtk_tree_view_set_cursor(GTK_TREE_VIEW(tree), path, NULL, FALSE);
+		gtk_tree_selection_select_iter(sel, (GtkTreeIter *)item);
+		gtk_tree_path_free(path);
+	}
+	DW_MUTEX_UNLOCK;
+#else
+	GtkWidget *lastselect, *tree;
+	int _locked_by_me = FALSE;
+
+	if(!handle || !item)
+		return;
+
+	DW_MUTEX_LOCK;
+	tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+	lastselect = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_lastselect");
+	if(lastselect && GTK_IS_TREE_ITEM(lastselect))
+		gtk_tree_item_deselect(GTK_TREE_ITEM(lastselect));
+	gtk_tree_item_select(GTK_TREE_ITEM(item));
+	gtk_object_set_data(GTK_OBJECT(tree), "_dw_lastselect", (gpointer)item);
+	DW_MUTEX_UNLOCK;
+#endif
+}
+
+#if GTK_MAJOR_VERSION > 1
+static void _dw_recursive_free(GtkTreeModel *store, GtkTreeIter parent)
+{
+	void *data;
+	GtkTreeIter iter;
+  
+	gtk_tree_model_get(store, &parent, 3, &data, -1);
+	if(data)
+		free(data);
+	gtk_tree_store_set(GTK_TREE_STORE(store), &parent, 3, NULL, -1);
+
+	if(gtk_tree_model_iter_children(store, &iter, &parent))
+	{
+		do {
+			_dw_recursive_free(GTK_TREE_MODEL(store), iter);
+		} while(gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
+	}
+}
+#endif
+
+/*
+ * Removes all nodes from a tree.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be cleared.
+ */
+void dw_tree_clear(HWND handle)
+{
+#if GTK_MAJOR_VERSION > 1
+	GtkWidget *tree;               
+	GtkTreeStore *store;
+	int _locked_by_me = FALSE;
+
+	if(!handle)
+		return;
+
+	DW_MUTEX_LOCK;
+	if((tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle)))
+		&& GTK_IS_TREE_VIEW(tree) &&
+		(store = (GtkTreeStore *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_store")))
+		{
+			GtkTreeIter iter;
+
+			if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter))
+			{
+				do {
+					_dw_recursive_free(GTK_TREE_MODEL(store), iter);
+				} while(gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
+			}
+			gtk_tree_store_clear(store);
+		}
+	DW_MUTEX_UNLOCK;
+#else
+	GtkWidget *tree;
+	int _locked_by_me = FALSE;
+
+	if(!handle)
+		return;
+
+	DW_MUTEX_LOCK;
+	tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+	if(!tree || !GTK_IS_TREE(tree))
+	{
+		DW_MUTEX_UNLOCK;
+		return;
+	}
+	gtk_object_set_data(GTK_OBJECT(tree), "_dw_lastselect", NULL);
+	gtk_tree_clear_items(GTK_TREE(tree), 0, 1000000);
+	DW_MUTEX_UNLOCK;
+#endif
+}
+
+/*
+ * Expands a node on a tree.
+ * Parameters:
+ *       handle: Handle to the tree window (widget).
+ *       item: Handle to node to be expanded.
+ */
+void dw_tree_expand(HWND handle, HTREEITEM item)
+{
+#if GTK_MAJOR_VERSION > 1
+	GtkWidget *tree;
+	GtkTreeStore *store;
+	int _locked_by_me = FALSE;
+
+	if(!handle)
+		return;
+
+	DW_MUTEX_LOCK;
+	if((tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle)))
+		&& GTK_IS_TREE_VIEW(tree) &&
+		(store = (GtkTreeStore *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_store")))
+	{
+		GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), (GtkTreeIter *)item);
+		gtk_tree_view_expand_row(GTK_TREE_VIEW(tree), path, FALSE);
+		gtk_tree_path_free(path);
+	}
+	DW_MUTEX_UNLOCK;
+#else
+	int _locked_by_me = FALSE;
+
+	if(!handle || !item)
+		return;
+
+	DW_MUTEX_LOCK;
+	_dw_ignore_expand = 1;
+	if(GTK_IS_TREE_ITEM(item))
+		gtk_tree_item_expand(GTK_TREE_ITEM(item));
+	_dw_ignore_expand = 0;
+	DW_MUTEX_UNLOCK;
+#endif
+}
+
+/*
+ * Collapses a node on a tree.
+ * Parameters:
+ *       handle: Handle to the tree window (widget).
+ *       item: Handle to node to be collapsed.
+ */
+void dw_tree_collapse(HWND handle, HTREEITEM item)
+{
+#if GTK_MAJOR_VERSION > 1
+	GtkWidget *tree;
+	GtkTreeStore *store;
+	int _locked_by_me = FALSE;
+
+	if(!handle)
+		return;
+
+	DW_MUTEX_LOCK;
+	if((tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle)))
+		&& GTK_IS_TREE_VIEW(tree) &&
+		(store = (GtkTreeStore *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_store")))
+	{
+		GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), (GtkTreeIter *)item);
+		gtk_tree_view_collapse_row(GTK_TREE_VIEW(tree), path);
+		gtk_tree_path_free(path);
+	}
+	DW_MUTEX_UNLOCK;
+#else
+	int _locked_by_me = FALSE;
+
+	if(!handle || !item)
+		return;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_TREE_ITEM(item))
+		gtk_tree_item_collapse(GTK_TREE_ITEM(item));
+	DW_MUTEX_UNLOCK;
+#endif
+}
+
+/*
+ * Removes a node from a tree.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be cleared.
+ *       item: Handle to node to be deleted.
+ */
+void dw_tree_delete(HWND handle, HTREEITEM item)
+{
+#if GTK_MAJOR_VERSION > 1
+	GtkWidget *tree;
+	GtkTreeStore *store;
+	int _locked_by_me = FALSE;
+
+	if(!handle)
+		return;
+
+	DW_MUTEX_LOCK;
+	if((tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle)))
+		&& GTK_IS_TREE_VIEW(tree) &&
+		(store = (GtkTreeStore *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_tree_store")))
+	{
+		gtk_tree_store_remove(store, (GtkTreeIter *)item);
+		free(item);
+	}
+	DW_MUTEX_UNLOCK;
+#else
+	GtkWidget *tree, *lastselect, *parenttree;
+	int _locked_by_me = FALSE;
+
+	if(!handle || !item || !GTK_IS_WIDGET(handle) || !GTK_IS_WIDGET(item))
+		return;
+
+	DW_MUTEX_LOCK;
+	tree = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+	if(!tree || !GTK_IS_TREE(tree))
+	{
+		DW_MUTEX_UNLOCK;
+		return;
+	}
+
+	lastselect = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(tree), "_dw_lastselect");
+
+	parenttree = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(item), "_dw_parenttree");
+
+	if(lastselect == item)
+	{
+		gtk_tree_item_deselect(GTK_TREE_ITEM(lastselect));
+		gtk_object_set_data(GTK_OBJECT(tree), "_dw_lastselect", NULL);
+	}
+
+	if(parenttree && GTK_IS_WIDGET(parenttree))
+		gtk_container_remove(GTK_CONTAINER(parenttree), item);
+	DW_MUTEX_UNLOCK;
+#endif
+}
+
+static int _dw_container_setup(HWND handle, unsigned long *flags, char **titles, int count, int separator, int extra)
+{
+	GtkWidget *clist;
+	char numbuf[10];
+	int z, multi;
+	int _locked_by_me = FALSE;
+	GtkJustification justification;
+
+	DW_MUTEX_LOCK;
+    clist = gtk_clist_new_with_titles(count, (gchar **)titles);
+	if(!clist)
+	{
+		DW_MUTEX_UNLOCK;
+		return FALSE;
+	}
+	multi = (int)gtk_object_get_data(GTK_OBJECT(handle), "_dw_multi");
+	gtk_object_set_data(GTK_OBJECT(handle), "_dw_multi", (gpointer)multi);
+
+	gtk_clist_set_column_auto_resize(GTK_CLIST(clist), 0, TRUE);
+	if(multi)
+		gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_EXTENDED);
+	else
+		gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_SINGLE);
+	gtk_container_add(GTK_CONTAINER(handle), clist);
+	gtk_object_set_user_data(GTK_OBJECT(handle), (gpointer)clist);
+	gtk_widget_show(clist);
+	gtk_object_set_data(GTK_OBJECT(clist), "_dw_colcount", (gpointer)count);
+
+    if(extra)
+		gtk_clist_set_column_width(GTK_CLIST(clist), 1, 120);
+
+	for(z=0;z<count;z++)
+	{
+		if(!extra || z > 1)
+			gtk_clist_set_column_width(GTK_CLIST(clist), z, 50);
+		sprintf(numbuf, "%d", z);
+		gtk_object_set_data(GTK_OBJECT(clist), numbuf, (gpointer)flags[z]);
+		if(flags[z]&DW_CFA_RIGHT)
+			justification = GTK_JUSTIFY_RIGHT;
+		else if(flags[z]&DW_CFA_CENTER)
+			justification = GTK_JUSTIFY_CENTER;
+		else
+			justification = GTK_JUSTIFY_LEFT;
+		gtk_clist_set_column_justification(GTK_CLIST(clist),z,justification);
+	}
+
+	DW_MUTEX_UNLOCK;
+	return TRUE;
+}
+
+/*
+ * Sets up the container columns.
+ * Parameters:
+ *          handle: Handle to the container to be configured.
+ *          flags: An array of unsigned longs with column flags.
+ *          titles: An array of strings with column text titles.
+ *          count: The number of columns (this should match the arrays).
+ *          separator: The column number that contains the main separator.
+ *                     (this item may only be used in OS/2)
+ */
+int dw_container_setup(HWND handle, unsigned long *flags, char **titles, int count, int separator)
+{
+	return _dw_container_setup(handle, flags, titles, count, separator, 0);
+}
+
+/*
+ * Sets up the filesystem columns, note: filesystem always has an icon/filename field.
+ * Parameters:
+ *          handle: Handle to the container to be configured.
+ *          flags: An array of unsigned longs with column flags.
+ *          titles: An array of strings with column text titles.
+ *          count: The number of columns (this should match the arrays).
+ */
+int dw_filesystem_setup(HWND handle, unsigned long *flags, char **titles, int count)
+{
+	char **newtitles = malloc(sizeof(char *) * (count + 1));
+	unsigned long *newflags = malloc(sizeof(unsigned long) * (count + 1));
+
+	newtitles[0] = "Filename";
+
+	newflags[0] = DW_CFA_STRINGANDICON | DW_CFA_LEFT | DW_CFA_HORZSEPARATOR;
+
+	memcpy(&newtitles[1], titles, sizeof(char *) * count);
+	memcpy(&newflags[1], flags, sizeof(unsigned long) * count);
+
+	_dw_container_setup(handle, newflags, newtitles, count + 1, 1, 1);
+
+	free(newtitles);
+	free(newflags);
+	return TRUE;
+}
+
+/*
+ * Obtains an icon from a module (or header in GTK).
+ * Parameters:
+ *          module: Handle to module (DLL) in OS/2 and Windows.
+ *          id: A unsigned long id int the resources on OS/2 and
+ *              Windows, on GTK this is converted to a pointer
+ *              to an embedded XPM.
+ */
+unsigned long dw_icon_load(unsigned long module, unsigned long id)
+{
+	return id;
+}
+
+/*
+ * Obtains an icon from a file.
+ * Parameters:
+ *       filename: Name of the file, omit extention to have
+ *                 DW pick the appropriate file extension.
+ *                 (ICO on OS/2 or Windows, XPM on Unix)
+ */
+unsigned long API dw_icon_load_from_file(char *filename)
+{
+	int found = -1, _locked_by_me = FALSE;
+#if GTK_MAJOR_VERSION > 1
+	GdkPixbuf *pixbuf;
+#elif defined(USE_IMLIB)
+	GdkImlibImage *image;
+#endif
+	char *file = alloca(strlen(filename) + 5);
+	unsigned long z, ret = 0;
+
+	if (!file)
+		return 0;
+
+	strcpy(file, filename);
+
+	/* check if we can read from this file (it exists and read permission) */
+	if(access(file, 04) != 0)
+	{
+		/* Try with .xpm extention */
+		strcat(file, ".xpm");
+		if(access(file, 04) != 0)
+			return 0;
+	}
+
+	DW_MUTEX_LOCK;
+	/* Find a free entry in the array */
+	for(z=0;z<_PixmapCount;z++)
+	{
+		if(!_PixmapArray[z].used)
+		{
+			ret = found = z;
+			break;
+		}
+	}
+
+	/* If there are no free entries, expand the
+	 * array.
+	 */
+	if(found == -1)
+	{
+		DWPrivatePixmap *old = _PixmapArray;
+
+		ret = found = _PixmapCount;
+		_PixmapCount++;
+
+		_PixmapArray = malloc(sizeof(DWPrivatePixmap) * _PixmapCount);
+
+		if(found)
+			memcpy(_PixmapArray, old, sizeof(DWPrivatePixmap) * found);
+		if(old)
+			free(old);
+		_PixmapArray[found].used = 1;
+		_PixmapArray[found].pixmap = _PixmapArray[found].mask = NULL;
+	}
+
+#if GTK_MAJOR_VERSION > 1
+	pixbuf = gdk_pixbuf_new_from_file(file, NULL);
+
+	if(pixbuf)
+	{
+		_PixmapArray[found].pixbuf = pixbuf;
+		_PixmapArray[found].width = gdk_pixbuf_get_width(pixbuf);
+		_PixmapArray[found].height = gdk_pixbuf_get_height(pixbuf);
+
+		gdk_pixbuf_render_pixmap_and_mask(pixbuf, &_PixmapArray[found].pixmap, &_PixmapArray[found].mask, 1);
+	}
+#elif defined(USE_IMLIB)
+	image = gdk_imlib_load_image(file);
+
+	if(image)
+	{
+		_PixmapArray[found].width = image->rgb_width;
+		_PixmapArray[found].height = image->rgb_height;
+
+		gdk_imlib_render(image, image->rgb_width, image->rgb_height);
+		_PixmapArray[found].pixmap = gdk_imlib_copy_image(image);
+		_PixmapArray[found].mask = gdk_imlib_copy_mask(image);
+		gdk_imlib_destroy_image(image);
+	}
+#else
+	if (last_window)
+		_PixmapArray[found].pixmap = gdk_pixmap_create_from_xpm(last_window->window, &_PixmapArray[found].mask, &_colors[DW_CLR_PALEGRAY], file);
+#endif
+	DW_MUTEX_UNLOCK;
+	if(!_PixmapArray[found].pixmap || !_PixmapArray[found].mask)
+	{
+		_PixmapArray[found].used = 0;
+		_PixmapArray[found].pixmap = _PixmapArray[found].mask = NULL;
+		return 0;
+	}
+	return ret | (1 << 31);
+}
+
+/*
+ * Frees a loaded resource in OS/2 and Windows.
+ * Parameters:
+ *          handle: Handle to icon returned by dw_icon_load().
+ */
+void dw_icon_free(unsigned long handle)
+{
+	/* If it is a private icon, find the item
+	 * free the associated structures and set
+	 * the entry to unused.
+	 */
+	if(handle & (1 << 31))
+	{
+		unsigned long id = handle & 0xFFFFFF;
+
+		if(id < _PixmapCount && _PixmapArray[id].used)
+		{
+#if GTK_MAJOR_VERSION > 1
+			if(_PixmapArray[id].pixbuf)
+			{
+				g_object_unref(_PixmapArray[id].pixbuf);
+				_PixmapArray[id].pixbuf = NULL;
+			}
+#endif
+			if(_PixmapArray[id].mask)
+			{
+				gdk_bitmap_unref(_PixmapArray[id].mask);
+				_PixmapArray[id].mask = NULL;
+			}
+			if(_PixmapArray[id].pixmap)
+			{
+				gdk_pixmap_unref(_PixmapArray[id].pixmap);
+				_PixmapArray[id].pixmap = NULL;
+			}
+			_PixmapArray[id].used = 0;
+		}
+	}
+}
+
+/* Clears a CList selection and associated selection list */
+void _dw_unselect(GtkWidget *clist)
+{
+	gtk_clist_unselect_all(GTK_CLIST(clist));
+}
+
+/*
+ * Allocates memory used to populate a container.
+ * Parameters:
+ *          handle: Handle to the container window (widget).
+ *          rowcount: The number of items to be populated.
+ */
+void *dw_container_alloc(HWND handle, int rowcount)
+{
+	int z, count = 0;
+	GtkWidget *clist;
+	GdkColor *fore, *back;
+	char **blah;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	clist = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+	if(!clist)
+	{
+		DW_MUTEX_UNLOCK;
+		return NULL;
+	}
+
+	count = (int)gtk_object_get_data(GTK_OBJECT(clist), "_dw_colcount");
+
+	if(!count)
+	{
+		DW_MUTEX_UNLOCK;
+		return NULL;
+	}
+
+	blah = malloc(sizeof(char *) * count);
+	memset(blah, 0, sizeof(char *) * count);
+
+	fore = (GdkColor *)gtk_object_get_data(GTK_OBJECT(clist), "_dw_foregdk");
+	back = (GdkColor *)gtk_object_get_data(GTK_OBJECT(clist), "_dw_backgdk");
+	gtk_clist_freeze(GTK_CLIST(clist));
+	for(z=0;z<rowcount;z++)
+	{
+		gtk_clist_append(GTK_CLIST(clist), blah);
+		if(fore)
+			gtk_clist_set_foreground(GTK_CLIST(clist), z, fore);
+		if(back)
+			gtk_clist_set_background(GTK_CLIST(clist), z, back);
+	}
+	gtk_object_set_data(GTK_OBJECT(clist), "_dw_rowcount", (gpointer)rowcount);
+	free(blah);
+	DW_MUTEX_UNLOCK;
+	return (void *)handle;
+}
+
+/*
+ * Internal representation of dw_container_set_item() extracted so we can pass
+ * two data pointers; icon and text for dw_filesystem_set_item().
+ */
+void _dw_container_set_item(HWND handle, void *pointer, int column, int row, void *data, char *text)
+{
+	char numbuf[10], textbuffer[100];
+	int flag = 0;
+	GtkWidget *clist;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	clist = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+	if(!clist)
+	{
+		DW_MUTEX_UNLOCK;
+		return;
+	}
+
+	sprintf(numbuf, "%d", column);
+	flag = (int)gtk_object_get_data(GTK_OBJECT(clist), numbuf);
+
+	if(flag & DW_CFA_BITMAPORICON)
+	{
+		long hicon = *((long *)data);
+		GdkBitmap *bitmap = NULL;
+		GdkPixmap *pixmap = _find_pixmap(&bitmap, hicon, clist, NULL, NULL);
+
+		if(pixmap)
+			gtk_clist_set_pixmap(GTK_CLIST(clist), row, column, pixmap, bitmap);
+	}
+	else if(flag & DW_CFA_STRINGANDICON)
+	{
+		long hicon = *((long *)data);
+		GdkBitmap *bitmap = NULL;
+		GdkPixmap *pixmap = _find_pixmap(&bitmap, hicon, clist, NULL, NULL);
+
+		if(pixmap)
+			gtk_clist_set_pixtext(GTK_CLIST(clist), row, column, text, 2, pixmap, bitmap);
+	}
+	else if(flag & DW_CFA_STRING)
+	{
+		char *tmp = *((char **)data);
+		gtk_clist_set_text(GTK_CLIST(clist), row, column, tmp);
+	}
+	else if(flag & DW_CFA_ULONG)
+	{
+		ULONG tmp = *((ULONG *)data);
+
+		sprintf(textbuffer, "%lu", tmp);
+
+		gtk_clist_set_text(GTK_CLIST(clist), row, column, textbuffer);
+	}
+	else if(flag & DW_CFA_DATE)
+	{
+		struct tm curtm;
+		CDATE cdate = *((CDATE *)data);
+
+		curtm.tm_mday = cdate.day;
+		curtm.tm_mon = cdate.month - 1;
+		curtm.tm_year = cdate.year - 1900;
+
+		strftime(textbuffer, 100, "%x", &curtm);
+
+		gtk_clist_set_text(GTK_CLIST(clist), row, column, textbuffer);
+	}
+	else if(flag & DW_CFA_TIME)
+	{
+		struct tm curtm;
+		CTIME ctime = *((CTIME *)data);
+
+		curtm.tm_hour = ctime.hours;
+		curtm.tm_min = ctime.minutes;
+		curtm.tm_sec = ctime.seconds;
+
+		strftime(textbuffer, 100, "%X", &curtm);
+
+		gtk_clist_set_text(GTK_CLIST(clist), row, column, textbuffer);
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Sets an item in specified row and column to the given data.
+ * Parameters:
+ *          handle: Handle to the container window (widget).
+ *          pointer: Pointer to the allocated memory in dw_container_alloc().
+ *          column: Zero based column of data being set.
+ *          row: Zero based row of data being set.
+ *          data: Pointer to the data to be added.
+ */
+void dw_container_set_item(HWND handle, void *pointer, int column, int row, void *data)
+{
+	_dw_container_set_item(handle, NULL, column, row, data, NULL);
+}
+
+/*
+ * Changes an existing item in specified row and column to the given data.
+ * Parameters:
+ *          handle: Handle to the container window (widget).
+ *          column: Zero based column of data being set.
+ *          row: Zero based row of data being set.
+ *          data: Pointer to the data to be added.
+ */
+void dw_container_change_item(HWND handle, int column, int row, void *data)
+{
+	_dw_container_set_item(handle, NULL, column, row, data, NULL);
+}
+
+/*
+ * Sets an item in specified row and column to the given data.
+ * Parameters:
+ *          handle: Handle to the container window (widget).
+ *          pointer: Pointer to the allocated memory in dw_container_alloc().
+ *          column: Zero based column of data being set.
+ *          row: Zero based row of data being set.
+ *          data: Pointer to the data to be added.
+ */
+void dw_filesystem_set_file(HWND handle, void *pointer, int row, char *filename, unsigned long icon)
+{
+	_dw_container_set_item(handle, pointer, 0, row, (void *)&icon, filename);
+}
+
+/*
+ * Sets an item in specified row and column to the given data.
+ * Parameters:
+ *          handle: Handle to the container window (widget).
+ *          pointer: Pointer to the allocated memory in dw_container_alloc().
+ *          column: Zero based column of data being set.
+ *          row: Zero based row of data being set.
+ *          data: Pointer to the data to be added.
+ */
+void dw_filesystem_set_item(HWND handle, void *pointer, int column, int row, void *data)
+{
+	_dw_container_set_item(handle, pointer, column + 1, row, data, NULL);
+}
+
+/*
+ * Sets the width of a column in the container.
+ * Parameters:
+ *          handle: Handle to window (widget) of container.
+ *          column: Zero based column of width being set.
+ *          width: Width of column in pixels.
+ */
+void dw_container_set_column_width(HWND handle, int column, int width)
+{
+	GtkWidget *clist;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	clist = gtk_object_get_user_data(GTK_OBJECT(handle));
+
+	if(clist && GTK_IS_CLIST(clist))
+		gtk_clist_set_column_width(GTK_CLIST(clist), column, width);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Sets the title of a row in the container.
+ * Parameters:
+ *          pointer: Pointer to the allocated memory in dw_container_alloc().
+ *          row: Zero based row of data being set.
+ *          title: String title of the item.
+ */
+void dw_container_set_row_title(void *pointer, int row, char *title)
+{
+	GtkWidget *clist;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	clist = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(pointer));
+
+	if(clist)
+		gtk_clist_set_row_data(GTK_CLIST(clist), row, (gpointer)title);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Sets the title of a row in the container.
+ * Parameters:
+ *          handle: Handle to the container window (widget).
+ *          pointer: Pointer to the allocated memory in dw_container_alloc().
+ *          rowcount: The number of rows to be inserted.
+ */
+void dw_container_insert(HWND handle, void *pointer, int rowcount)
+{
+	GtkWidget *clist;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	clist = gtk_object_get_user_data(GTK_OBJECT(handle));
+
+	if(clist && GTK_IS_CLIST(clist))
+		gtk_clist_thaw(GTK_CLIST(clist));
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Removes the first x rows from a container.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be deleted from.
+ *       rowcount: The number of rows to be deleted.
+ */
+void dw_container_delete(HWND handle, int rowcount)
+{
+	GtkWidget *clist;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	clist = (GtkWidget*)gtk_object_get_user_data(GTK_OBJECT(handle));
+	if(clist && GTK_IS_CLIST(clist))
+	{
+		int rows, z;
+
+		rows = (int)gtk_object_get_data(GTK_OBJECT(clist), "_dw_rowcount");
+
+		_dw_unselect(clist);
+
+		for(z=0;z<rowcount;z++)
+			gtk_clist_remove(GTK_CLIST(clist), 0);
+
+		if(rows - rowcount < 0)
+			rows = 0;
+		else
+			rows -= rowcount;
+
+		gtk_object_set_data(GTK_OBJECT(clist), "_dw_rowcount", (gpointer)rows);
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Removes all rows from a container.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be cleared.
+ *       redraw: TRUE to cause the container to redraw immediately.
+ */
+void dw_container_clear(HWND handle, int redraw)
+{
+	GtkWidget *clist;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	clist = (GtkWidget*)gtk_object_get_user_data(GTK_OBJECT(handle));
+	if(clist && GTK_IS_CLIST(clist))
+	{
+		_dw_unselect(clist);
+		gtk_clist_clear(GTK_CLIST(clist));
+		gtk_object_set_data(GTK_OBJECT(clist), "_dw_rowcount", (gpointer)0);
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Scrolls container up or down.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be scrolled.
+ *       direction: DW_SCROLL_UP, DW_SCROLL_DOWN, DW_SCROLL_TOP or
+ *                  DW_SCROLL_BOTTOM. (rows is ignored for last two)
+ *       rows: The number of rows to be scrolled.
+ */
+void dw_container_scroll(HWND handle, int direction, long rows)
+{
+	GtkAdjustment *adj;
+	GtkWidget *clist;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	clist = (GtkWidget*)gtk_object_get_user_data(GTK_OBJECT(handle));
+	if(clist && GTK_IS_CLIST(clist))
+	{
+		adj = gtk_clist_get_vadjustment(GTK_CLIST(clist));
+		if(adj)
+		{
+			switch(direction)
+			{
+			case DW_SCROLL_TOP:
+				adj->value = adj->lower;
+				break;
+			case DW_SCROLL_BOTTOM:
+				adj->value = adj->upper;
+				break;
+			}
+			gtk_clist_set_vadjustment(GTK_CLIST(clist), adj);
+		}
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Starts a new query of a container.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be queried.
+ *       flags: If this parameter is DW_CRA_SELECTED it will only
+ *              return items that are currently selected.  Otherwise
+ *              it will return all records in the container.
+ */
+char *dw_container_query_start(HWND handle, unsigned long flags)
+{
+	GtkWidget *clist;
+	GList *list;
+	char *retval = NULL;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	clist = (GtkWidget*)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+	if(!clist)
+	{
+		DW_MUTEX_UNLOCK;
+		return NULL;
+	}
+
+	/* These should be separate but right now this will work */
+	if(flags & DW_CRA_SELECTED)
+	{
+		list = GTK_CLIST(clist)->selection;
+
+		if(list)
+		{
+			gtk_object_set_data(GTK_OBJECT(clist), "_dw_querypos", (gpointer)1);
+			retval = (char *)gtk_clist_get_row_data(GTK_CLIST(clist), GPOINTER_TO_UINT(list->data));
+		}
+	}
+	else if(flags & DW_CRA_CURSORED)
+	{
+		retval = (char *)gtk_clist_get_row_data(GTK_CLIST(clist), GTK_CLIST(clist)->focus_row);
+	}
+	else
+	{
+		retval = (char *)gtk_clist_get_row_data(GTK_CLIST(clist), 0);
+		gtk_object_set_data(GTK_OBJECT(clist), "_dw_querypos", (gpointer)1);
+	}
+	DW_MUTEX_UNLOCK;
+	return retval;
+}
+
+/*
+ * Continues an existing query of a container.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be queried.
+ *       flags: If this parameter is DW_CRA_SELECTED it will only
+ *              return items that are currently selected.  Otherwise
+ *              it will return all records in the container.
+ */
+char *dw_container_query_next(HWND handle, unsigned long flags)
+{
+	GtkWidget *clist;
+	GList *list;
+	char *retval = NULL;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	clist = (GtkWidget*)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+	if(!clist)
+	{
+		DW_MUTEX_UNLOCK;
+		return NULL;
+	}
+
+	/* These should be separate but right now this will work */
+	if(flags & DW_CRA_SELECTED)
+	{
+		list = GTK_CLIST(clist)->selection;
+
+		if(list)
+		{
+			int counter = 0, pos = (int)gtk_object_get_data(GTK_OBJECT(clist), "_dw_querypos");
+			gtk_object_set_data(GTK_OBJECT(clist), "_dw_querypos", (gpointer)pos+1);
+
+			while(list && counter < pos)
+			{
+				list = list->next;
+				counter++;
+			}
+
+			if(list)
+				retval = (char *)gtk_clist_get_row_data(GTK_CLIST(clist), GPOINTER_TO_UINT(list->data));
+		}
+	}
+	else if(flags & DW_CRA_CURSORED)
+	{
+		/* There will only be one item cursored,
+		 * retrieve it with dw_container_query_start()
+		 */
+		retval = NULL;
+	}
+	else
+	{
+		int pos = (int)gtk_object_get_data(GTK_OBJECT(clist), "_dw_querypos");
+
+		retval = (char *)gtk_clist_get_row_data(GTK_CLIST(clist), pos);
+		gtk_object_set_data(GTK_OBJECT(clist), "_dw_querypos", (gpointer)pos+1);
+	}
+	DW_MUTEX_UNLOCK;
+	return retval;
+}
+
+/*
+ * Cursors the item with the text speficied, and scrolls to that item.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be queried.
+ *       text:  Text usually returned by dw_container_query().
+ */
+void dw_container_cursor(HWND handle, char *text)
+{
+	int _locked_by_me = FALSE;
+	GtkWidget *clist;
+	int rowcount, z;
+	char *rowdata;
+
+	DW_MUTEX_LOCK;
+	clist = (GtkWidget*)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+	if(!clist)
+	{
+		DW_MUTEX_UNLOCK;
+		return;
+	}
+	rowcount = (int)gtk_object_get_data(GTK_OBJECT(clist), "_dw_rowcount");
+
+	for(z=0;z<rowcount;z++)
+	{
+		rowdata = gtk_clist_get_row_data(GTK_CLIST(clist), z);
+		if(rowdata == text)
+		{
+			gfloat pos;
+			GtkAdjustment *adj = gtk_clist_get_vadjustment(GTK_CLIST(clist));
+
+			_dw_unselect(clist);
+
+			gtk_clist_select_row(GTK_CLIST(clist), z, 0);
+
+			pos = ((adj->upper - adj->lower) * ((gfloat)z/(gfloat)rowcount)) + adj->lower;
+			gtk_adjustment_set_value(adj, pos);
+			DW_MUTEX_UNLOCK;
+			return;
+		}
+	}
+
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Deletes the item with the text speficied.
+ * Parameters:
+ *       handle: Handle to the window (widget).
+ *       text:  Text usually returned by dw_container_query().
+ */
+void dw_container_delete_row(HWND handle, char *text)
+{
+	int _locked_by_me = FALSE;
+	GtkWidget *clist;
+	int rowcount, z;
+	char *rowdata;
+
+	DW_MUTEX_LOCK;
+	clist = (GtkWidget*)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+	if(!clist)
+	{
+		DW_MUTEX_UNLOCK;
+		return;
+	}
+	rowcount = (int)gtk_object_get_data(GTK_OBJECT(clist), "_dw_rowcount");
+
+	for(z=0;z<rowcount;z++)
+	{
+		rowdata = gtk_clist_get_row_data(GTK_CLIST(clist), z);
+		if(rowdata == text)
+		{
+			_dw_unselect(clist);
+
+			gtk_clist_remove(GTK_CLIST(clist), z);
+
+			rowcount--;
+
+			gtk_object_set_data(GTK_OBJECT(clist), "_dw_rowcount", (gpointer)rowcount);
+			DW_MUTEX_UNLOCK;
+			return;
+		}
+	}
+
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Optimizes the column widths so that all data is visible.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be optimized.
+ */
+void dw_container_optimize(HWND handle)
+{
+	int _locked_by_me = FALSE;
+	GtkWidget *clist;
+	int colcount, z;
+
+	DW_MUTEX_LOCK;
+	clist = (GtkWidget*)gtk_object_get_user_data(GTK_OBJECT(handle));
+
+	if(!clist)
+	{
+		DW_MUTEX_UNLOCK;
+		return;
+	}
+	colcount = (int)gtk_object_get_data(GTK_OBJECT(clist), "_dw_colcount");
+	for(z=0;z<colcount;z++)
+	{
+		int width = gtk_clist_optimal_column_width(GTK_CLIST(clist), z);
+		gtk_clist_set_column_width(GTK_CLIST(clist), z, width);
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Inserts an icon into the taskbar.
+ * Parameters:
+ *       handle: Window handle that will handle taskbar icon messages.
+ *       icon: Icon handle to display in the taskbar.
+ *       bubbletext: Text to show when the mouse is above the icon.
+ */
+void dw_taskbar_insert(HWND handle, unsigned long icon, char *bubbletext)
+{
+	/* TODO */
+}
+
+/*
+ * Deletes an icon from the taskbar.
+ * Parameters:
+ *       handle: Window handle that was used with dw_taskbar_insert().
+ *       icon: Icon handle that was used with dw_taskbar_insert().
+ */
+void dw_taskbar_delete(HWND handle, unsigned long icon)
+{
+	/* TODO */
+}
+
+/*
+ * Creates a rendering context widget (window) to be packed.
+ * Parameters:
+ *       id: An id to be used with dw_window_from_id.
+ * Returns:
+ *       A handle to the widget or NULL on failure.
+ */
+HWND dw_render_new(unsigned long id)
+{
+	int _locked_by_me = FALSE;
+	GtkWidget *tmp;
+
+	DW_MUTEX_LOCK;
+	tmp = gtk_drawing_area_new();
+	gtk_widget_set_events(tmp, GDK_EXPOSURE_MASK
+						  | GDK_LEAVE_NOTIFY_MASK
+						  | GDK_BUTTON_PRESS_MASK
+						  | GDK_KEY_PRESS_MASK
+						  | GDK_POINTER_MOTION_MASK
+						  | GDK_POINTER_MOTION_HINT_MASK);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+	GTK_WIDGET_SET_FLAGS(tmp, GTK_CAN_FOCUS);
+	gtk_widget_show(tmp);
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/* Returns a GdkColor from a DW color */
+static GdkColor _internal_color(unsigned long value)
+{
+	if(DW_RGB_COLOR & value)
+	{
+		GdkColor color = { 0, DW_RED_VALUE(value) << 8, DW_GREEN_VALUE(value) << 8, DW_BLUE_VALUE(value) << 8 };
+		return color;
+	}
+	if (value < 16)
+		return _colors[value];
+	return _colors[0];
+}
+
+/* Sets the current foreground drawing color.
+ * Parameters:
+ *       red: red value.
+ *       green: green value.
+ *       blue: blue value.
+ */
+void dw_color_foreground_set(unsigned long value)
+{
+	int _locked_by_me = FALSE, index = _find_thread_index(dw_thread_id());
+	GdkColor color = _internal_color(value);
+
+	DW_MUTEX_LOCK;
+	gdk_color_alloc(_dw_cmap, &color);
+	_foreground[index] = color;
+	DW_MUTEX_UNLOCK;
+}
+
+/* Sets the current background drawing color.
+ * Parameters:
+ *       red: red value.
+ *       green: green value.
+ *       blue: blue value.
+ */
+void dw_color_background_set(unsigned long value)
+{
+	int _locked_by_me = FALSE, index = _find_thread_index(dw_thread_id());
+	GdkColor color = _internal_color(value);
+
+	DW_MUTEX_LOCK;
+	gdk_color_alloc(_dw_cmap, &color);
+	if(value == DW_CLR_DEFAULT)
+		_transparent[index] = 1;
+	else
+		_transparent[index] = 0;
+
+	_background[index] = color;
+	DW_MUTEX_UNLOCK;
+}
+
+GdkGC *_set_colors(GdkWindow *window)
+{
+	GdkGC *gc = NULL;
+	int index = _find_thread_index(dw_thread_id());
+
+	if(!window)
+		return NULL;
+	gc = gdk_gc_new(window);
+	if(gc)
+	{
+		gdk_gc_set_foreground(gc, &_foreground[index]);
+		gdk_gc_set_background(gc, &_background[index]);
+	}
+	return gc;
+}
+
+/* Draw a point on a window (preferably a render window).
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       x: X coordinate.
+ *       y: Y coordinate.
+ */
+void dw_draw_point(HWND handle, HPIXMAP pixmap, int x, int y)
+{
+	int _locked_by_me = FALSE;
+	GdkGC *gc = NULL;
+
+	DW_MUTEX_LOCK;
+	if(handle)
+		gc = _set_colors(handle->window);
+	else if(pixmap)
+		gc = _set_colors(pixmap->pixmap);
+	if(gc)
+	{
+		gdk_draw_point(handle ? handle->window : pixmap->pixmap, gc, x, y);
+		gdk_gc_unref(gc);
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/* Draw a line on a window (preferably a render window).
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       x1: First X coordinate.
+ *       y1: First Y coordinate.
+ *       x2: Second X coordinate.
+ *       y2: Second Y coordinate.
+ */
+void dw_draw_line(HWND handle, HPIXMAP pixmap, int x1, int y1, int x2, int y2)
+{
+	int _locked_by_me = FALSE;
+	GdkGC *gc = NULL;
+
+	DW_MUTEX_LOCK;
+	if(handle)
+		gc = _set_colors(handle->window);
+	else if(pixmap)
+		gc = _set_colors(pixmap->pixmap);
+	if(gc)
+	{
+		gdk_draw_line(handle ? handle->window : pixmap->pixmap, gc, x1, y1, x2, y2);
+		gdk_gc_unref(gc);
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/* Draw a rectangle on a window (preferably a render window).
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       x: X coordinate.
+ *       y: Y coordinate.
+ *       width: Width of rectangle.
+ *       height: Height of rectangle.
+ */
+void dw_draw_rect(HWND handle, HPIXMAP pixmap, int fill, int x, int y, int width, int height)
+{
+	int _locked_by_me = FALSE;
+	GdkGC *gc = NULL;
+
+	DW_MUTEX_LOCK;
+	if(handle)
+		gc = _set_colors(handle->window);
+	else if(pixmap)
+		gc = _set_colors(pixmap->pixmap);
+	if(gc)
+	{
+		gdk_draw_rectangle(handle ? handle->window : pixmap->pixmap, gc, fill, x, y, width, height);
+		gdk_gc_unref(gc);
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/* Draw text on a window (preferably a render window).
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       x: X coordinate.
+ *       y: Y coordinate.
+*       text: Text to be displayed.
+  */
+void dw_draw_text(HWND handle, HPIXMAP pixmap, int x, int y, char *text)
+{
+	int _locked_by_me = FALSE;
+	GdkGC *gc = NULL;
+#if GTK_MAJOR_VERSION > 1
+	PangoFontDescription *font;
+#else
+	GdkFont *font;
+#endif
+	char *fontname = "fixed";
+
+	if(!text)
+		return;
+
+	DW_MUTEX_LOCK;
+	if(handle)
+	{
+		fontname = (char *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_fontname");
+		gc = _set_colors(handle->window);
+	}
+	else if(pixmap)
+	{
+		fontname = (char *)gtk_object_get_data(GTK_OBJECT(pixmap->handle), "_dw_fontname");
+		gc = _set_colors(pixmap->pixmap);
+	}
+	if(gc)
+	{
+#if GTK_MAJOR_VERSION > 1
+		font = pango_font_description_from_string(fontname);
+		if(font)
+		{
+			PangoContext *context = gdk_pango_context_get();
+
+			if(context)
+			{
+				PangoLayout *layout = pango_layout_new(context);
+
+				if(layout)
+				{
+					int index = _find_thread_index(dw_thread_id());
+
+					gdk_pango_context_set_colormap(context, _dw_cmap);
+					pango_layout_set_font_description(layout, font);
+					pango_layout_set_text(layout, text, strlen(text));
+
+					if(_transparent[index])
+						gdk_draw_layout(handle ? handle->window : pixmap->pixmap, gc, x, y, layout);
+					else
+						gdk_draw_layout_with_colors(handle ? handle->window : pixmap->pixmap, gc, x, y, layout, &_foreground[index], &_background[index]);
+
+					g_object_unref(layout);
+				}
+				g_object_unref(context);
+			}
+			pango_font_description_free(font);
+		}
+#else
+		font = gdk_font_load(fontname);
+		if(!font)
+			font = gdk_font_load("fixed");
+		if(font)
+		{
+			gint ascent, descent, width, junk_ascent, junk_descent, junk_width;
+			int index = _find_thread_index(dw_thread_id());
+
+			/* gdk_text_extents() calculates ascent and descent based on the string, so
+			 * a string without a character with a descent or without an ascent will have
+			 * incorrect ascent/descent values
+			 */
+			gdk_text_extents(font, text, strlen(text), NULL, NULL, &width, &junk_ascent, &junk_descent);
+			/* force ascent/descent to be maximum values */
+			gdk_text_extents(font, "(g", 2, NULL, NULL, &junk_width, &ascent, &descent);
+			if(!_transparent[index])
+			{
+				GdkGC *gc2 = NULL;
+
+				gc2 = gdk_gc_new(handle ? handle->window : pixmap->pixmap);
+				if(gc2)
+				{
+					gdk_gc_set_foreground(gc2, &_background[index]);
+					gdk_gc_set_background(gc2, &_background[index]);
+				}
+				gdk_draw_rectangle(handle ? handle->window : pixmap->pixmap, gc2, TRUE, x, y, width, ascent + descent + 1);
+				gdk_gc_unref(gc2);
+			}
+			gdk_draw_text(handle ? handle->window : pixmap->pixmap, font, gc, x, y + ascent + 1, text, strlen(text));
+			gdk_font_unref(font);
+		}
+#endif
+		gdk_gc_unref(gc);
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/* Query the width and height of a text string.
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       text: Text to be queried.
+ *       width: Pointer to a variable to be filled in with the width.
+ *       height Pointer to a variable to be filled in with the height.
+ */
+void dw_font_text_extents(HWND handle, HPIXMAP pixmap, char *text, int *width, int *height)
+{
+	int _locked_by_me = FALSE;
+#if GTK_MAJOR_VERSION > 1
+	PangoFontDescription *font;
+#else
+	GdkFont *font;
+#endif
+	char *fontname = NULL;
+
+	if(!text)
+		return;
+
+	DW_MUTEX_LOCK;
+	if(handle)
+		fontname = (char *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_fontname");
+	else if(pixmap)
+		fontname = (char *)gtk_object_get_data(GTK_OBJECT(pixmap->handle), "_dw_fontname");
+
+#if GTK_MAJOR_VERSION > 1
+	font = pango_font_description_from_string(fontname ? fontname : "monospace 10");
+	if(font)
+	{
+		PangoContext *context = gdk_pango_context_get();
+
+		if(context)
+		{
+			PangoLayout *layout = pango_layout_new(context);
+
+			if(layout)
+			{
+				PangoRectangle rect;
+
+				pango_layout_set_font_description(layout, font);
+				pango_layout_set_text(layout, text, -1);
+				pango_layout_get_pixel_extents(layout, NULL, &rect);
+
+				if(width)
+					*width = rect.width;
+				if(height)
+					*height = rect.height;
+
+				g_object_unref(layout);
+			}
+			g_object_unref(context);
+		}
+		pango_font_description_free(font);
+	}
+#else
+
+	font = gdk_font_load(fontname ? fontname : "fixed");
+	if(!font)
+		font = gdk_font_load("fixed");
+	if(font)
+	{
+		if(width)
+			*width = gdk_string_width(font, text);
+		if(height)
+			*height = gdk_string_height(font, text);
+		gdk_font_unref(font);
+	}
+#endif
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Creates a pixmap with given parameters.
+ * Parameters:
+ *       handle: Window handle the pixmap is associated with.
+ *       width: Width of the pixmap in pixels.
+ *       height: Height of the pixmap in pixels.
+ *       depth: Color depth of the pixmap.
+ * Returns:
+ *       A handle to a pixmap or NULL on failure.
+ */
+HPIXMAP dw_pixmap_new(HWND handle, unsigned long width, unsigned long height, int depth)
+{
+	int _locked_by_me = FALSE;
+	HPIXMAP pixmap;
+
+	if (!(pixmap = calloc(1,sizeof(struct _hpixmap))))
+		return NULL;
+
+	if (!depth)
+		depth = -1;
+
+	pixmap->width = width; pixmap->height = height;
+
+
+	DW_MUTEX_LOCK;
+	pixmap->handle = handle;
+	pixmap->pixmap = gdk_pixmap_new(handle->window, width, height, depth);
+	DW_MUTEX_UNLOCK;
+	return pixmap;
+}
+
+/*
+ * Creates a pixmap from a file.
+ * Parameters:
+ *       handle: Window handle the pixmap is associated with.
+ *       filename: Name of the file, omit extention to have
+ *                 DW pick the appropriate file extension.
+ *                 (BMP on OS/2 or Windows, XPM on Unix)
+ * Returns:
+ *       A handle to a pixmap or NULL on failure.
+ */
+HPIXMAP dw_pixmap_new_from_file(HWND handle, char *filename)
+{
+	int _locked_by_me = FALSE;
+	HPIXMAP pixmap;
+#ifndef USE_IMLIB
+	GdkBitmap *bitmap = NULL;
+#endif
+#if GTK_MAJOR_VERSION > 1
+	GdkPixbuf *pixbuf;
+#elif defined(USE_IMLIB)
+	GdkImlibImage *image;
+#endif
+	char *file = alloca(strlen(filename) + 5);
+
+	if (!file || !(pixmap = calloc(1,sizeof(struct _hpixmap))))
+		return NULL;
+
+	strcpy(file, filename);
+
+	/* check if we can read from this file (it exists and read permission) */
+	if(access(file, 04) != 0)
+	{
+		/* Try with .xpm extention */
+		strcat(file, ".xpm");
+		if(access(file, 04) != 0)
+		{
+			free(pixmap);
+			return NULL;
+		}
+	}
+
+	DW_MUTEX_LOCK;
+#if GTK_MAJOR_VERSION > 1
+	pixbuf = gdk_pixbuf_new_from_file(file, NULL);
+
+	pixmap->width = gdk_pixbuf_get_width(pixbuf);
+	pixmap->height = gdk_pixbuf_get_height(pixbuf);
+
+	gdk_pixbuf_render_pixmap_and_mask(pixbuf, &pixmap->pixmap, &bitmap, 1);
+	g_object_unref(pixbuf);
+#elif defined(USE_IMLIB)
+	image = gdk_imlib_load_image(file);
+
+	pixmap->width = image->rgb_width;
+	pixmap->height = image->rgb_height;
+
+	gdk_imlib_render(image, pixmap->width, pixmap->height);
+	pixmap->pixmap = gdk_imlib_copy_image(image);
+	gdk_imlib_destroy_image(image);
+#else
+	pixmap->pixmap = gdk_pixmap_create_from_xpm(handle->window, &bitmap, &_colors[DW_CLR_PALEGRAY], file);
+#endif
+	pixmap->handle = handle;
+	DW_MUTEX_UNLOCK;
+	return pixmap;
+}
+
+/*
+ * Creates a pixmap from internal resource graphic specified by id.
+ * Parameters:
+ *       handle: Window handle the pixmap is associated with.
+ *       id: Resource ID associated with requested pixmap.
+ * Returns:
+ *       A handle to a pixmap or NULL on failure.
+ */
+HPIXMAP dw_pixmap_grab(HWND handle, ULONG id)
+{
+	GdkBitmap *bitmap = NULL;
+	HPIXMAP pixmap;
+	int _locked_by_me = FALSE;
+
+	if (!(pixmap = calloc(1,sizeof(struct _hpixmap))))
+		return NULL;
+
+
+	DW_MUTEX_LOCK;
+	pixmap->pixmap = _find_pixmap(&bitmap, id, handle, &pixmap->width, &pixmap->height);
+	if(pixmap->pixmap)
+	{
+#if GTK_MAJOR_VERSION < 2
+		GdkPixmapPrivate *pvt = (GdkPixmapPrivate *)pixmap->pixmap;
+		pixmap->width = pvt->width; pixmap->height = pvt->height;
+#endif
+	}
+	DW_MUTEX_UNLOCK;
+	return pixmap;
+}
+
+/* Call this after drawing to the screen to make sure
+ * anything you have drawn is visible.
+ */
+void dw_flush(void)
+{
+#if GTK_MAJOR_VERSION < 2
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	gdk_flush();
+	DW_MUTEX_UNLOCK;
+#endif
+}
+
+/*
+ * Destroys an allocated pixmap.
+ * Parameters:
+ *       pixmap: Handle to a pixmap returned by
+ *               dw_pixmap_new..
+ */
+void dw_pixmap_destroy(HPIXMAP pixmap)
+{
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	gdk_pixmap_unref(pixmap->pixmap);
+	free(pixmap);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Copies from one item to another.
+ * Parameters:
+ *       dest: Destination window handle.
+ *       destp: Destination pixmap. (choose only one).
+ *       xdest: X coordinate of destination.
+ *       ydest: Y coordinate of destination.
+ *       width: Width of area to copy.
+ *       height: Height of area to copy.
+ *       src: Source window handle.
+ *       srcp: Source pixmap. (choose only one).
+ *       xsrc: X coordinate of source.
+ *       ysrc: Y coordinate of source.
+ */
+void dw_pixmap_bitblt(HWND dest, HPIXMAP destp, int xdest, int ydest, int width, int height, HWND src, HPIXMAP srcp, int xsrc, int ysrc)
+{
+	/* Ok, these #ifdefs are going to get a bit confusing because
+	 * when using gdk-pixbuf, pixmaps are really pixbufs, so we
+	 * have to use the pixbuf functions on them, and thus convoluting
+	 * the code here a bit. -Brian
+	 */
+	int _locked_by_me = FALSE;
+	GdkGC *gc = NULL;
+
+	if((!dest && (!destp || !destp->pixmap)) || (!src && (!srcp || !srcp->pixmap)))
+		return;
+
+	DW_MUTEX_LOCK;
+	if(dest)
+		gc = _set_colors(dest->window);
+	else if(src)
+		gc = _set_colors(src->window);
+	else if(destp)
+		gc = gdk_gc_new(destp->pixmap);
+	else if(srcp)
+		gc = gdk_gc_new(srcp->pixmap);
+
+	if(gc)
+	{
+			gdk_draw_pixmap(dest ? dest->window : destp->pixmap, gc, src ? src->window : srcp->pixmap, xsrc, ysrc, xdest, ydest, width, height);
+			gdk_gc_unref(gc);
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Emits a beep.
+ * Parameters:
+ *       freq: Frequency.
+ *       dur: Duration.
+ */
+void dw_beep(int freq, int dur)
+{
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	gdk_beep();
+	DW_MUTEX_UNLOCK;
+}
+
+void _my_strlwr(char *buf)
+{
+	int z, len = strlen(buf);
+
+	for(z=0;z<len;z++)
+	{
+		if(buf[z] >= 'A' && buf[z] <= 'Z')
+			buf[z] -= 'A' - 'a';
+	}
+}
+
+/* Open a shared library and return a handle.
+ * Parameters:
+ *         name: Base name of the shared library.
+ *         handle: Pointer to a module handle,
+ *                 will be filled in with the handle.
+ */
+int dw_module_load(char *name, HMOD *handle)
+{
+	int len;
+	char *newname;
+	char errorbuf[1024];
+
+
+	if(!handle)
+		return -1;
+
+	if((len = strlen(name)) == 0)
+		return	-1;
+
+	/* Lenth + "lib" + ".so" + NULL */
+	newname = malloc(len + 7);
+
+	if(!newname)
+		return -1;
+
+	sprintf(newname, "lib%s.so", name);
+	_my_strlwr(newname);
+
+	*handle = dlopen(newname, RTLD_NOW);
+	if(*handle == NULL)
+	{
+		strncpy(errorbuf, dlerror(), 1024);
+		printf("%s\n", errorbuf);
+		sprintf(newname, "lib%s.so", name);
+		*handle = dlopen(newname, RTLD_NOW);
+	}
+
+	free(newname);
+
+	return (NULL == *handle) ? -1 : 0;
+}
+
+/* Queries the address of a symbol within open handle.
+ * Parameters:
+ *         handle: Module handle returned by dw_module_load()
+ *         name: Name of the symbol you want the address of.
+ *         func: A pointer to a function pointer, to obtain
+ *               the address.
+ */
+int dw_module_symbol(HMOD handle, char *name, void**func)
+{
+	if(!func || !name)
+		return	-1;
+
+	if(strlen(name) == 0)
+		return	-1;
+
+	*func = (void*)dlsym(handle, name);
+	return	(NULL == *func);
+}
+
+/* Frees the shared library previously opened.
+ * Parameters:
+ *         handle: Module handle returned by dw_module_load()
+ */
+int dw_module_close(HMOD handle)
+{
+	if(handle)
+		return dlclose(handle);
+	return 0;
+}
+
+/*
+ * Returns the handle to an unnamed mutex semaphore.
+ */
+HMTX dw_mutex_new(void)
+{
+	HMTX mutex = malloc(sizeof(pthread_mutex_t));
+
+	pthread_mutex_init(mutex, NULL);
+	return mutex;
+}
+
+/*
+ * Closes a semaphore created by dw_mutex_new().
+ * Parameters:
+ *       mutex: The handle to the mutex returned by dw_mutex_new().
+ */
+void dw_mutex_close(HMTX mutex)
+{
+	if(mutex)
+	{
+		pthread_mutex_destroy(mutex);
+		free(mutex);
+	}
+}
+
+/*
+ * Tries to gain access to the semaphore, if it can't it blocks.
+ * Parameters:
+ *       mutex: The handle to the mutex returned by dw_mutex_new().
+ */
+void dw_mutex_lock(HMTX mutex)
+{
+	/* If we are being called from an event handler we must release
+	 * the GTK mutex so we don't deadlock.
+	 */
+	if(pthread_self() == _dw_thread)
+		gdk_threads_leave();
+
+	pthread_mutex_lock(mutex);
+
+	/* And of course relock it when we have acquired the mutext */
+	if(pthread_self() == _dw_thread)
+		gdk_threads_enter();
+}
+
+/*
+ * Reliquishes the access to the semaphore.
+ * Parameters:
+ *       mutex: The handle to the mutex returned by dw_mutex_new().
+ */
+void dw_mutex_unlock(HMTX mutex)
+{
+	pthread_mutex_unlock(mutex);
+}
+
+/*
+ * Returns the handle to an unnamed event semaphore.
+ */
+HEV dw_event_new(void)
+{
+	HEV eve = (HEV)malloc(sizeof(struct _dw_unix_event));
+
+	if(!eve)
+		return NULL;
+
+	/* We need to be careful here, mutexes on Linux are
+	 * FAST by default but are error checking on other
+	 * systems such as FreeBSD and OS/2, perhaps others.
+	 */
+	pthread_mutex_init (&(eve->mutex), NULL);
+	pthread_mutex_lock (&(eve->mutex));
+	pthread_cond_init (&(eve->event), NULL);
+
+	pthread_mutex_unlock (&(eve->mutex));
+	eve->alive = 1;
+	eve->posted = 0;
+
+	return eve;
+}
+
+/*
+ * Resets a semaphore created by dw_event_new().
+ * Parameters:
+ *       eve: The handle to the event returned by dw_event_new().
+ */
+int dw_event_reset (HEV eve)
+{
+	if(!eve)
+		return FALSE;
+
+	pthread_mutex_lock (&(eve->mutex));
+	pthread_cond_broadcast (&(eve->event));
+	pthread_cond_init (&(eve->event), NULL);
+	eve->posted = 0;
+	pthread_mutex_unlock (&(eve->mutex));
+	return 0;
+}
+
+/*
+ * Posts a semaphore created by dw_event_new(). Causing all threads
+ * waiting on this event in dw_event_wait to continue.
+ * Parameters:
+ *       eve: The handle to the event returned by dw_event_new().
+ */
+int dw_event_post (HEV eve)
+{
+	if(!eve)
+		return FALSE;
+
+	pthread_mutex_lock (&(eve->mutex));
+	pthread_cond_broadcast (&(eve->event));
+	eve->posted = 1;
+	pthread_mutex_unlock (&(eve->mutex));
+	return 0;
+}
+
+/*
+ * Waits on a semaphore created by dw_event_new(), until the
+ * event gets posted or until the timeout expires.
+ * Parameters:
+ *       eve: The handle to the event returned by dw_event_new().
+ */
+int dw_event_wait(HEV eve, unsigned long timeout)
+{
+	int rc;
+	struct timeval now;
+	struct timespec timeo;
+
+	if(!eve)
+		return FALSE;
+
+	if(eve->posted)
+		return 0;
+
+	pthread_mutex_lock (&(eve->mutex));
+	gettimeofday(&now, 0);
+	timeo.tv_sec = now.tv_sec + (timeout / 1000);
+	timeo.tv_nsec = now.tv_usec * 1000;
+	rc = pthread_cond_timedwait (&(eve->event), &(eve->mutex), &timeo);
+	pthread_mutex_unlock (&(eve->mutex));
+	if(!rc)
+		return 1;
+	if(rc == ETIMEDOUT)
+		return -1;
+	return 0;
+}
+
+/*
+ * Closes a semaphore created by dw_event_new().
+ * Parameters:
+ *       eve: The handle to the event returned by dw_event_new().
+ */
+int dw_event_close(HEV *eve)
+{
+	if(!eve || !(*eve))
+		return FALSE;
+
+	pthread_mutex_lock (&((*eve)->mutex));
+	pthread_cond_destroy (&((*eve)->event));
+	pthread_mutex_unlock (&((*eve)->mutex));
+	pthread_mutex_destroy (&((*eve)->mutex));
+	free(*eve);
+	*eve = NULL;
+
+	return TRUE;
+}
+
+/*
+ * Setup thread independent color sets.
+ */
+void _dwthreadstart(void *data)
+{
+	void (*threadfunc)(void *) = NULL;
+	void **tmp = (void **)data;
+
+	threadfunc = (void (*)(void *))tmp[0];
+
+	_dw_thread_add(dw_thread_id());
+	threadfunc(tmp[1]);
+	_dw_thread_remove(dw_thread_id());
+	free(tmp);
+}
+/*
+ * Creates a new thread with a starting point of func.
+ * Parameters:
+ *       func: Function which will be run in the new thread.
+ *       data: Parameter(s) passed to the function.
+ *       stack: Stack size of new thread (OS/2 and Windows only).
+ */
+DWTID dw_thread_new(void *func, void *data, int stack)
+{
+	DWTID gtkthread;
+	void **tmp = malloc(sizeof(void *) * 2);
+
+	tmp[0] = func;
+	tmp[1] = data;
+
+	pthread_create(&gtkthread, NULL, (void *)_dwthreadstart, (void *)tmp);
+	return gtkthread;
+}
+
+/*
+ * Ends execution of current thread immediately.
+ */
+void dw_thread_end(void)
+{
+	pthread_exit(NULL);
+}
+
+/*
+ * Returns the current thread's ID.
+ */
+DWTID dw_thread_id(void)
+{
+	return (DWTID)pthread_self();
+}
+
+/*
+ * Cleanly terminates a DW session, should be signal handler safe.
+ * Parameters:
+ *       exitcode: Exit code reported to the operating system.
+ */
+void dw_exit(int exitcode)
+{
+	exit(exitcode);
+}
+
+#define DW_EXPAND (GTK_EXPAND | GTK_SHRINK | GTK_FILL)
+
+/*
+ * Pack windows (widgets) into a box from the end (or bottom).
+ * Parameters:
+ *       box: Window handle of the box to be packed into.
+ *       item: Window handle of the item to be back.
+ *       width: Width in pixels of the item or -1 to be self determined.
+ *       height: Height in pixels of the item or -1 to be self determined.
+ *       hsize: TRUE if the window (widget) should expand horizontally to fill space given.
+ *       vsize: TRUE if the window (widget) should expand vertically to fill space given.
+ *       pad: Number of pixels of padding around the item.
+ */
+void dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad)
+{
+	int warn = FALSE, _locked_by_me = FALSE;
+	GtkWidget *tmp, *tmpitem;
+
+	if(!box)
+		return;
+
+		/*
+		 * If you try and pack an item into itself VERY bad things can happen; like at least an
+		 * infinite loop on GTK! Lets be safe!
+		 */
+	if(box == item)
+	{
+		dw_messagebox("dw_box_pack_end()", DW_MB_OK|DW_MB_ERROR, "Danger! Danger! Will Robinson; box and item are the same!",box,item);
+		return;
+	}
+
+	DW_MUTEX_LOCK;
+
+	if((tmp  = gtk_object_get_data(GTK_OBJECT(box), "_dw_boxhandle")))
+		box = tmp;
+
+	if(!item)
+	{
+		item = gtk_label_new("");
+		gtk_widget_show(item);
+	}
+
+	tmpitem = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(item), "_dw_boxhandle");
+
+	if(GTK_IS_TABLE(box))
+	{
+		int boxcount = (int)gtk_object_get_data(GTK_OBJECT(box), "_dw_boxcount");
+		int boxtype = (int)gtk_object_get_data(GTK_OBJECT(box), "_dw_boxtype");
+
+		/* If the item being packed is a box, then we use it's padding
+		 * instead of the padding specified on the pack line, this is
+		 * due to a bug in the OS/2 and Win32 renderer and a limitation
+		 * of the GtkTable class.
+		 */
+		if(GTK_IS_TABLE(item) || (tmpitem && GTK_IS_TABLE(tmpitem)))
+		{
+			GtkWidget *eventbox = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(item), "_dw_eventbox");
+
+			if(eventbox)
+			{
+				gtk_container_add(GTK_CONTAINER(eventbox), item);
+				pad = (int)gtk_object_get_data(GTK_OBJECT(item), "_dw_boxpad");
+				item = eventbox;
+			}
+		}
+		else
+		{
+			/* Only show warning if item is not a box */
+			warn = TRUE;
+		}
+
+		if(boxtype == DW_VERT)
+			gtk_table_resize(GTK_TABLE(box), boxcount + 1, 1);
+		else
+			gtk_table_resize(GTK_TABLE(box), 1, boxcount + 1);
+
+		gtk_table_attach(GTK_TABLE(box), item, 0, 1, 0, 1, hsize ? DW_EXPAND : 0, vsize ? DW_EXPAND : 0, pad, pad);
+		gtk_object_set_data(GTK_OBJECT(box), "_dw_boxcount", (gpointer)boxcount + 1);
+		gtk_widget_set_usize(item, width, height);
+		if(GTK_IS_RADIO_BUTTON(item))
+		{
+			GSList *group;
+			GtkWidget *groupstart = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(box), "_dw_group");
+
+			if(groupstart)
+			{
+				group = gtk_radio_button_group(GTK_RADIO_BUTTON(groupstart));
+				gtk_radio_button_set_group(GTK_RADIO_BUTTON(item), group);
+			}
+			else
+				gtk_object_set_data(GTK_OBJECT(box), "_dw_group", (gpointer)item);
+		}
+	}
+	else
+	{
+		GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
+
+		if(GTK_IS_TABLE(item) || (tmpitem && GTK_IS_TABLE(tmpitem)))
+		{
+			GtkWidget *eventbox = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(item), "_dw_eventbox");
+
+			if(eventbox)
+			{
+				gtk_container_add(GTK_CONTAINER(eventbox), item);
+				pad = (int)gtk_object_get_data(GTK_OBJECT(item), "_dw_boxpad");
+				item = eventbox;
+			}
+		}
+		else
+		{
+			/* Only show warning if item is not a box */
+			warn = TRUE;
+		}
+
+		gtk_container_border_width(GTK_CONTAINER(box), pad);
+		gtk_container_add(GTK_CONTAINER(box), vbox);
+		gtk_box_pack_end(GTK_BOX(vbox), item, TRUE, TRUE, 0);
+		gtk_widget_show(vbox);
+
+		gtk_widget_set_usize(item, width, height);
+		gtk_object_set_user_data(GTK_OBJECT(box), vbox);
+	}
+	DW_MUTEX_UNLOCK;
+
+	if(warn)
+	{
+		if ( width == 0 && hsize == FALSE )
+			dw_messagebox("dw_box_pack_end()", DW_MB_OK|DW_MB_ERROR, "Width and expand Horizonal both unset for box: %x item: %x",box,item);
+		if ( height == 0 && vsize == FALSE )
+			dw_messagebox("dw_box_pack_end()", DW_MB_OK|DW_MB_ERROR, "Height and expand Vertical both unset for box: %x item: %x",box,item);
+	}
+}
+
+/*
+ * Sets the size of a given window (widget).
+ * Parameters:
+ *          handle: Window (widget) handle.
+ *          width: New width in pixels.
+ *          height: New height in pixels.
+ */
+void dw_window_set_usize(HWND handle, unsigned long width, unsigned long height)
+{
+	int _locked_by_me = FALSE;
+
+	if(!handle)
+		return;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_WINDOW(handle))
+	{
+		_size_allocate(GTK_WINDOW(handle));
+		if(handle->window)
+			gdk_window_resize(handle->window, width - _dw_border_width, height - _dw_border_height);
+		gtk_window_set_default_size(GTK_WINDOW(handle), width - _dw_border_width, height - _dw_border_height);
+		if(!gtk_object_get_data(GTK_OBJECT(handle), "_dw_size"))
+		{
+			gtk_object_set_data(GTK_OBJECT(handle), "_dw_width", (gpointer)width - _dw_border_width);
+			gtk_object_set_data(GTK_OBJECT(handle), "_dw_height", (gpointer)height - _dw_border_height);
+		}
+	}
+	else
+		gtk_widget_set_usize(handle, width, height);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Returns the width of the screen.
+ */
+int dw_screen_width(void)
+{
+	int retval;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	retval = gdk_screen_width();
+	DW_MUTEX_UNLOCK;
+	return retval;
+}
+
+/*
+ * Returns the height of the screen.
+ */
+int dw_screen_height(void)
+{
+	int retval;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_UNLOCK;
+	retval = gdk_screen_height();
+	DW_MUTEX_UNLOCK;
+	return retval;
+}
+
+/* This should return the current color depth */
+unsigned long dw_color_depth(void)
+{
+	int retval;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_UNLOCK;
+	retval = gdk_visual_get_best_depth();
+	DW_MUTEX_UNLOCK;
+	return retval;
+}
+
+/*
+ * Sets the position of a given window (widget).
+ * Parameters:
+ *          handle: Window (widget) handle.
+ *          x: X location from the bottom left.
+ *          y: Y location from the bottom left.
+ */
+void dw_window_set_pos(HWND handle, unsigned long x, unsigned long y)
+{
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	if(handle && handle->window)
+		gdk_window_move(handle->window, x, y);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Sets the position and size of a given window (widget).
+ * Parameters:
+ *          handle: Window (widget) handle.
+ *          x: X location from the bottom left.
+ *          y: Y location from the bottom left.
+ *          width: Width of the widget.
+ *          height: Height of the widget.
+ */
+void dw_window_set_pos_size(HWND handle, unsigned long x, unsigned long y, unsigned long width, unsigned long height)
+{
+	int _locked_by_me = FALSE;
+
+	if(!handle)
+		return;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_WINDOW(handle))
+	{
+		dw_window_set_usize(handle, width, height);
+		gtk_widget_set_uposition(handle, x, y);
+	}
+	else if(handle->window)
+	{
+		gdk_window_resize(handle->window, width, height);
+		gdk_window_move(handle->window, x, y);
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Gets the position and size of a given window (widget).
+ * Parameters:
+ *          handle: Window (widget) handle.
+ *          x: X location from the bottom left.
+ *          y: Y location from the bottom left.
+ *          width: Width of the widget.
+ *          height: Height of the widget.
+ */
+void dw_window_get_pos_size(HWND handle, ULONG *x, ULONG *y, ULONG *width, ULONG *height)
+{
+	int _locked_by_me = FALSE;
+	gint gx, gy, gwidth, gheight, gdepth;
+
+	if(handle && handle->window)
+	{
+		DW_MUTEX_LOCK;
+
+		gdk_window_get_geometry(handle->window, &gx, &gy, &gwidth, &gheight, &gdepth);
+		gdk_window_get_root_origin(handle->window, &gx, &gy);
+		if(x)
+			*x = gx;
+		if(y)
+			*y = gy;
+		if(GTK_IS_WINDOW(handle))
+		{
+			if(width)
+				*width = gwidth + _dw_border_width;
+			if(height)
+				*height = gheight + _dw_border_height;
+		}
+		else
+		{
+			if(width)
+				*width = gwidth;
+			if(height)
+				*height = gheight;
+		}
+		DW_MUTEX_UNLOCK;
+	}
+}
+
+/*
+ * Sets the style of a given window (widget).
+ * Parameters:
+ *          handle: Window (widget) handle.
+ *          width: New width in pixels.
+ *          height: New height in pixels.
+ */
+void dw_window_set_style(HWND handle, unsigned long style, unsigned long mask)
+{
+	GtkWidget *handle2 = handle;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+		if(tmp)
+			handle2 = tmp;
+	}
+	else if(GTK_IS_FRAME(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_label");
+		if(tmp && GTK_IS_LABEL(tmp))
+			handle2 = tmp;
+	}
+	if(GTK_IS_LABEL(handle2))
+	{
+		if(style & DW_DT_CENTER || style & DW_DT_VCENTER)
+		{
+			gfloat x, y;
+
+			x = y = DW_LEFT;
+
+			if(style & DW_DT_CENTER)
+				x = DW_CENTER;
+
+			if(style & DW_DT_VCENTER)
+				y = DW_CENTER;
+
+			gtk_misc_set_alignment(GTK_MISC(handle2), x, y);
+		}
+		if(style & DW_DT_WORDBREAK)
+			gtk_label_set_line_wrap(GTK_LABEL(handle), TRUE);
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Adds a new page to specified notebook.
+ * Parameters:
+ *          handle: Window (widget) handle.
+ *          flags: Any additional page creation flags.
+ *          front: If TRUE page is added at the beginning.
+ */
+unsigned long dw_notebook_page_new(HWND handle, unsigned long flags, int front)
+{
+	int z;
+	int _locked_by_me = FALSE;
+	GtkWidget **pagearray;
+
+	DW_MUTEX_LOCK;
+	pagearray = (GtkWidget **)gtk_object_get_data(GTK_OBJECT(handle), "_dw_pagearray");
+
+	if(pagearray)
+	{    
+		for(z=0;z<256;z++)
+		{
+			if(!pagearray[z])
+			{
+				char text[100];
+				int num = z;
+
+				if(front)
+					num |= 1 << 16;
+
+				sprintf(text, "_dw_page%d", z);
+				/* Save the real id and the creation flags */
+				gtk_object_set_data(GTK_OBJECT(handle), text, (gpointer)num);
+				DW_MUTEX_UNLOCK;
+				return z;
+			}
+		}
+	}
+	DW_MUTEX_UNLOCK;
+  
+	/* Hopefully this won't happen. */
+	return 256;
+}
+
+/* Return the physical page id from the logical page id */
+int _get_physical_page(HWND handle, unsigned long pageid)
+{
+	int z;
+	GtkWidget *thispage, **pagearray = gtk_object_get_data(GTK_OBJECT(handle), "_dw_pagearray");
+
+	if(pagearray)
+	{
+		for(z=0;z<256;z++)
+		{
+			if((thispage = gtk_notebook_get_nth_page(GTK_NOTEBOOK(handle), z)))
+			{
+				if(thispage == pagearray[pageid])
+					return z;
+			}
+		}
+	}
+	return 256;                                        
+}
+
+/*
+ * Remove a page from a notebook.
+ * Parameters:
+ *          handle: Handle to the notebook widget.
+ *          pageid: ID of the page to be destroyed.
+ */
+void dw_notebook_page_destroy(HWND handle, unsigned int pageid)
+{
+	int realpage, _locked_by_me = FALSE;
+	GtkWidget **pagearray;
+
+	DW_MUTEX_LOCK;
+	realpage = _get_physical_page(handle, pageid);
+	if(realpage > -1 && realpage < 256)
+	{  
+		gtk_notebook_remove_page(GTK_NOTEBOOK(handle), realpage);
+		if((pagearray = gtk_object_get_data(GTK_OBJECT(handle), "_dw_pagearray")))
+			pagearray[pageid] = NULL;
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Queries the currently visible page ID.
+ * Parameters:
+ *          handle: Handle to the notebook widget.
+ */
+unsigned long dw_notebook_page_query(HWND handle)
+{
+	int retval, phys;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	phys = gtk_notebook_get_current_page(GTK_NOTEBOOK(handle));
+	retval = _get_logical_page(handle, phys);
+	DW_MUTEX_UNLOCK;
+	return retval;
+}
+
+/*
+ * Sets the currently visibale page ID.
+ * Parameters:
+ *          handle: Handle to the notebook widget.
+ *          pageid: ID of the page to be made visible.
+ */
+void dw_notebook_page_set(HWND handle, unsigned int pageid)
+{
+	int realpage, _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	realpage = _get_physical_page(handle, pageid);
+	if(realpage > -1 && realpage < 256)
+		gtk_notebook_set_page(GTK_NOTEBOOK(handle), pageid);
+	DW_MUTEX_UNLOCK;
+}
+
+
+/*
+ * Sets the text on the specified notebook tab.
+ * Parameters:
+ *          handle: Notebook handle.
+ *          pageid: Page ID of the tab to set.
+ *          text: Pointer to the text to set.
+ */
+void dw_notebook_page_set_text(HWND handle, unsigned long pageid, char *text)
+{
+	GtkWidget *child;
+	int realpage, _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	realpage = _get_physical_page(handle, pageid);
+	if(realpage < 0 || realpage > 255)
+	{
+		char ptext[100];
+		int num;
+    
+		sprintf(ptext, "_dw_page%d", (int)pageid);
+		num = (int)gtk_object_get_data(GTK_OBJECT(handle), ptext);
+		realpage = 0xFF & num;
+	}
+  
+	if(realpage > -1 && realpage < 256)
+	{  
+		child = gtk_notebook_get_nth_page(GTK_NOTEBOOK(handle), realpage);
+		if(child)
+			gtk_notebook_set_tab_label_text(GTK_NOTEBOOK(handle), child, text);
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Sets the text on the specified notebook tab status area.
+ * Parameters:
+ *          handle: Notebook handle.
+ *          pageid: Page ID of the tab to set.
+ *          text: Pointer to the text to set.
+ */
+void dw_notebook_page_set_status_text(HWND handle, unsigned long pageid, char *text)
+{
+	/* TODO (if possible) */
+}
+
+/*
+ * Packs the specified box into the notebook page.
+ * Parameters:
+ *          handle: Handle to the notebook to be packed.
+ *          pageid: Page ID in the notebook which is being packed.
+ *          page: Box handle to be packed.
+ */
+void dw_notebook_pack(HWND handle, unsigned long pageid, HWND page)
+{
+	GtkWidget *label, *child, *oldlabel, **pagearray;
+	gchar *text = NULL;
+	int num, z, realpage = -1, pad, _locked_by_me = FALSE;
+	char ptext[100];
+
+	DW_MUTEX_LOCK;
+	sprintf(ptext, "_dw_page%d", (int)pageid);
+	num = (int)gtk_object_get_data(GTK_OBJECT(handle), ptext);
+	gtk_object_set_data(GTK_OBJECT(handle), ptext, NULL);
+	pagearray = (GtkWidget **)gtk_object_get_data(GTK_OBJECT(handle), "_dw_pagearray");
+
+	if(!pagearray)
+	{
+		DW_MUTEX_UNLOCK;
+		return;
+	}
+
+	/* The page already exists... so get it's current page */
+	if(pagearray[pageid])
+	{
+		for(z=0;z<256;z++)
+		{
+			child = gtk_notebook_get_nth_page(GTK_NOTEBOOK(handle), z);
+			if(child == pagearray[pageid])
+			{
+				oldlabel = gtk_notebook_get_tab_label(GTK_NOTEBOOK(handle), child);
+				if(oldlabel)
+					gtk_label_get(GTK_LABEL(oldlabel), &text);
+				gtk_notebook_remove_page(GTK_NOTEBOOK(handle), z);
+				realpage = z;
+				break;
+			}
+		}
+	}
+  
+	pagearray[pageid] = page;
+
+	label = gtk_label_new(text ? text : "");
+
+	if(GTK_IS_TABLE(page))
+	{
+		pad = (int)gtk_object_get_data(GTK_OBJECT(page), "_dw_boxpad");
+		gtk_container_border_width(GTK_CONTAINER(page), pad);
+	}
+
+	if(realpage != -1)
+		gtk_notebook_insert_page(GTK_NOTEBOOK(handle), page, label, realpage);
+	else if(num & ~(0xFF))
+		gtk_notebook_insert_page(GTK_NOTEBOOK(handle), page, label, 0);
+	else
+		gtk_notebook_insert_page(GTK_NOTEBOOK(handle), page, label, 256);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Appends the specified text to the listbox's (or combobox) entry list.
+ * Parameters:
+ *          handle: Handle to the listbox to be appended to.
+ *          text: Text to append into listbox.
+ */
+void dw_listbox_append(HWND handle, char *text)
+{
+	GtkWidget *handle2 = handle;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+		if(tmp)
+			handle2 = tmp;
+	}
+	gtk_object_set_data(GTK_OBJECT(handle), "_dw_appending", (gpointer)1);
+	if(GTK_IS_LIST(handle2))
+	{
+		GtkWidget *list_item;
+		GList *tmp;
+		char *font = (char *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_font");
+		GdkColor *fore = (GdkColor *)gtk_object_get_data(GTK_OBJECT(handle2), "_dw_foregdk");
+		GdkColor *back = (GdkColor *)gtk_object_get_data(GTK_OBJECT(handle2), "_dw_backgdk");
+
+		list_item=gtk_list_item_new_with_label(text);
+
+		if(font)
+			_set_font(GTK_LIST_ITEM(list_item)->item.bin.child, font);
+		if(fore && back)
+			_set_color(GTK_LIST_ITEM(list_item)->item.bin.child,
+					   DW_RGB(fore->red, fore->green, fore->blue),
+					   DW_RGB(back->red, back->green, back->blue));
+
+		tmp  = g_list_append(NULL, list_item);
+		gtk_widget_show(list_item);
+		gtk_list_append_items(GTK_LIST(handle2),tmp);
+	}
+	else if(GTK_IS_COMBO(handle2))
+	{
+		GList *tmp = (GList *)gtk_object_get_user_data(GTK_OBJECT(handle2));
+		char *addtext = strdup(text);
+
+		if(addtext)
+		{
+			tmp = g_list_append(tmp, addtext);
+			gtk_object_set_user_data(GTK_OBJECT(handle2), tmp);
+			gtk_combo_set_popdown_strings(GTK_COMBO(handle2), tmp);
+		}
+	}
+	gtk_object_set_data(GTK_OBJECT(handle), "_dw_appending", NULL);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Clears the listbox's (or combobox) list of all entries.
+ * Parameters:
+ *          handle: Handle to the listbox to be cleared.
+ */
+void dw_listbox_clear(HWND handle)
+{
+	GtkWidget *handle2 = handle;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+		if(tmp)
+			handle2 = tmp;
+	}
+	if(GTK_IS_COMBO(handle2))
+	{
+		GList *list, *tmp = (GList *)gtk_object_get_user_data(GTK_OBJECT(handle2));
+
+		if(tmp)
+		{
+			list = tmp;
+			while(list)
+			{
+				if(list->data)
+					free(list->data);
+				list=list->next;
+			}
+			g_list_free(tmp);
+		}
+		gtk_object_set_user_data(GTK_OBJECT(handle2), NULL);
+	}
+	else if(GTK_IS_LIST(handle2))
+	{
+		int count = dw_listbox_count(handle);
+
+		gtk_list_clear_items(GTK_LIST(handle2), 0, count - 1);
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Returns the listbox's item count.
+ * Parameters:
+ *          handle: Handle to the listbox to be counted
+ */
+int dw_listbox_count(HWND handle)
+{
+	GtkWidget *handle2 = handle;
+    int retval = 0;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+		if(tmp)
+			handle2 = tmp;
+	}
+	else if(GTK_IS_COMBO(handle))
+	{
+		handle2 = GTK_COMBO(handle)->list;
+	}
+	if(GTK_IS_LIST(handle2))
+	{
+		GList *list = GTK_LIST(handle2)->children;
+		while(list)
+		{
+			list = list->next;
+			retval++;
+		}
+	}
+	DW_MUTEX_UNLOCK;
+	return retval;
+}
+
+/*
+ * Sets the topmost item in the viewport.
+ * Parameters:
+ *          handle: Handle to the listbox to be cleared.
+ *          top: Index to the top item.
+ */
+void dw_listbox_set_top(HWND handle, int top)
+{
+	GtkWidget *handle2 = handle;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+		if(tmp)
+			handle2 = tmp;
+	}
+	if(GTK_IS_LIST(handle2))
+	{
+		int count = dw_listbox_count(handle);
+		GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(handle));
+		float pos, ratio;
+
+		if(count)
+		{
+			ratio = (float)top/(float)count;
+
+			pos = (ratio * (float)(adj->upper - adj->lower)) + adj->lower;
+
+			gtk_adjustment_set_value(adj, pos);
+		}
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Copies the given index item's text into buffer.
+ * Parameters:
+ *          handle: Handle to the listbox to be queried.
+ *          index: Index into the list to be queried.
+ *          buffer: Buffer where text will be copied.
+ *          length: Length of the buffer (including NULL).
+ */
+void dw_listbox_query_text(HWND handle, unsigned int index, char *buffer, unsigned int length)
+{
+	GtkWidget *handle2 = handle;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+		if(tmp)
+			handle2 = tmp;
+	}
+	else if(GTK_IS_COMBO(handle))
+	{
+		handle2 = GTK_COMBO(handle)->list;
+	}
+	if(GTK_IS_LIST(handle2))
+	{
+		int counter = 0;
+		GList *list = GTK_LIST(handle2)->children;
+
+		while(list)
+		{
+			if(counter == index)
+			{
+				gchar *text = "";
+
+				if(GTK_IS_LIST_ITEM(list->data))
+				{
+					GtkListItem *li = GTK_LIST_ITEM(list->data);
+
+					if(GTK_IS_ITEM(&(li->item)))
+					{
+						GtkItem *i = &(li->item);
+
+						if(GTK_IS_BIN(&(i->bin)))
+						{
+							GtkBin *b = &(i->bin);
+
+							if(GTK_IS_LABEL(b->child))
+								gtk_label_get(GTK_LABEL(b->child), &text);
+						}
+					}
+				}
+				else if(GTK_IS_COMBO(handle) && list->data)
+					text = (gchar *)list->data;
+
+				strncpy(buffer, (char *)text, length);
+				break;
+			}
+			list = list->next;
+			counter++;
+		}
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Sets the text of a given listbox entry.
+ * Parameters:
+ *          handle: Handle to the listbox to be queried.
+ *          index: Index into the list to be queried.
+ *          buffer: Buffer where text will be copied.
+ */
+void dw_listbox_set_text(HWND handle, unsigned int index, char *buffer)
+{
+	GtkWidget *handle2 = handle;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+		if(tmp)
+			handle2 = tmp;
+	}
+	else if(GTK_IS_COMBO(handle))
+	{
+		handle2 = GTK_COMBO(handle)->list;
+	}
+	if(GTK_IS_LIST(handle2))
+	{
+		int counter = 0;
+		GList *list = GTK_LIST(handle2)->children;
+
+		while(list)
+		{
+			if(counter == index)
+			{
+
+				if(GTK_IS_LIST_ITEM(list->data))
+				{
+					GtkListItem *li = GTK_LIST_ITEM(list->data);
+
+					if(GTK_IS_ITEM(&(li->item)))
+					{
+						GtkItem *i = &(li->item);
+
+						if(GTK_IS_BIN(&(i->bin)))
+						{
+							GtkBin *b = &(i->bin);
+
+							if(GTK_IS_LABEL(b->child))
+								gtk_label_set_text(GTK_LABEL(b->child), buffer);
+						}
+					}
+				}
+				else if(GTK_IS_COMBO(handle))
+				{
+					if(list->data)
+						g_free(list->data);
+					list->data = g_strdup(buffer);
+				}
+				break;
+			}
+			list = list->next;
+			counter++;
+		}
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+#if GTK_MAJOR_VERSION < 2
+/* Check if a GList item is in another GList */
+static int _dw_in_list(GList *item, GList *list)
+{
+	while(list)
+	{
+		if(list->data == item->data)
+			return TRUE;
+
+		list = list->next;
+	}
+	return FALSE;
+}
+#endif
+
+/*
+ * Returns the index to the current selected item or -1 when done.
+ * Parameters:
+ *          handle: Handle to the listbox to be queried.
+ *          where: Either the previous return or -1 to restart.
+ */
+int dw_listbox_selected_multi(HWND handle, int where)
+{
+	GtkWidget *handle2 = handle;
+	int retval = DW_LIT_NONE;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+		if(tmp)
+			handle2 = tmp;
+	}
+	if(GTK_IS_LIST(handle2))
+	{
+#if GTK_MAJOR_VERSION > 1
+		int counter = 0;
+		GList *list = GTK_LIST(handle2)->children;
+
+		while(list)
+		{
+			GtkItem *item = (GtkItem *)list->data;
+
+			if(item &&
+			   item->bin.container.widget.state == GTK_STATE_SELECTED
+			   && counter > where)
+			{
+				retval = counter;
+				break;
+			}
+
+
+			list = list->next;
+			counter++;
+		}
+#else
+		int counter = 0;
+		GList *list = GTK_LIST(handle2)->children;
+
+		while(list)
+		{
+			if(counter > where && _dw_in_list(list, GTK_LIST(handle2)->selection))
+			{
+				retval = counter;
+				break;
+			}
+
+			list = list->next;
+			counter++;
+		}
+#endif
+	}
+	DW_MUTEX_UNLOCK;
+	return retval;
+}
+
+/*
+ * Returns the index to the item in the list currently selected.
+ * Parameters:
+ *          handle: Handle to the listbox to be queried.
+ */
+unsigned int dw_listbox_selected(HWND handle)
+{
+	GtkWidget *handle2 = handle;
+	int retval = DW_LIT_NONE;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+		if(tmp)
+			handle2 = tmp;
+	}
+	else if(GTK_IS_COMBO(handle))
+	{
+		retval = (unsigned int)gtk_object_get_data(GTK_OBJECT(handle), "_dw_item");
+		DW_MUTEX_UNLOCK;
+		return retval;
+	}
+	if(GTK_IS_LIST(handle2))
+	{
+		int counter = 0;
+		GList *list = GTK_LIST(handle2)->children;
+#if GTK_MAJOR_VERSION > 1
+
+		while(list)
+		{
+			GtkItem *item = (GtkItem *)list->data;
+
+			if(item && item->bin.container.widget.state == GTK_STATE_SELECTED)
+			{
+				retval = counter;
+				break;
+			}
+
+			list = list->next;
+			counter++;
+		}
+#else
+		GList *selection = GTK_LIST(handle2)->selection;
+
+		if(selection)
+		{
+			while(list)
+			{
+				if(list->data == selection->data)
+				{
+					retval = counter;
+					break;
+				}
+
+				list = list->next;
+				counter++;
+			}
+		}
+#endif
+	}
+	DW_MUTEX_UNLOCK;
+	return retval;
+}
+
+/*
+ * Sets the selection state of a given index.
+ * Parameters:
+ *          handle: Handle to the listbox to be set.
+ *          index: Item index.
+ *          state: TRUE if selected FALSE if unselected.
+ */
+void dw_listbox_select(HWND handle, int index, int state)
+{
+	GtkWidget *handle2 = handle;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+		if(tmp)
+			handle2 = tmp;
+	}
+	else if(GTK_IS_COMBO(handle))
+	{
+		handle2 = GTK_COMBO(handle)->list;
+	}
+	if(GTK_IS_LIST(handle2))
+	{
+		if(state)
+			gtk_list_select_item(GTK_LIST(handle2), index);
+		else
+			gtk_list_unselect_item(GTK_LIST(handle2), index);
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Deletes the item with given index from the list.
+ * Parameters:
+ *          handle: Handle to the listbox to be set.
+ *          index: Item index.
+ */
+void dw_listbox_delete(HWND handle, int index)
+{
+	GtkWidget *handle2 = handle;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_SCROLLED_WINDOW(handle))
+	{
+		GtkWidget *tmp = (GtkWidget *)gtk_object_get_user_data(GTK_OBJECT(handle));
+		if(tmp)
+			handle2 = tmp;
+	}
+	else if(GTK_IS_COMBO(handle))
+	{
+		handle2 = GTK_COMBO(handle)->list;
+	}
+	if(GTK_IS_LIST(handle2))
+{
+		gtk_list_clear_items(GTK_LIST(handle2), index, index+1);
+}
+	DW_MUTEX_UNLOCK;
+}
+
+/* Reposition the bar according to the percentage */
+static gint _splitbar_size_allocate(GtkWidget *widget, GtkAllocation *event, gpointer data)
+{
+	float *percent = (float *)gtk_object_get_data(GTK_OBJECT(widget), "_dw_percent");
+	int lastwidth = (int)gtk_object_get_data(GTK_OBJECT(widget), "_dw_lastwidth");
+	int lastheight = (int)gtk_object_get_data(GTK_OBJECT(widget), "_dw_lastheight");
+
+	/* Prevent infinite recursion ;) */  
+	if(!percent || (lastwidth == event->width && lastheight == event->height))
+		return FALSE;
+
+	lastwidth = event->width; lastheight = event->height;
+  
+	gtk_object_set_data(GTK_OBJECT(widget), "_dw_lastwidth", (gpointer)lastwidth);
+	gtk_object_set_data(GTK_OBJECT(widget), "_dw_lastheight", (gpointer)lastheight);
+
+	if(GTK_IS_HPANED(widget))
+		gtk_paned_set_position(GTK_PANED(widget), (int)(event->width * (*percent / 100.0)));
+	if(GTK_IS_VPANED(widget))
+		gtk_paned_set_position(GTK_PANED(widget), (int)(event->height * (*percent / 100.0)));
+	gtk_object_set_data(GTK_OBJECT(widget), "_dw_waiting", NULL);
+	return FALSE;
+}
+
+#if GTK_MAJOR_VERSION > 1
+/* Figure out the new percentage */
+static void _splitbar_accept_position(GObject *object, GParamSpec *pspec, gpointer data)
+{
+	GtkWidget *widget = (GtkWidget *)data;
+	float *percent = (float *)gtk_object_get_data(GTK_OBJECT(widget), "_dw_percent");
+	int size = 0, position = gtk_paned_get_position(GTK_PANED(widget));
+
+	if(!percent || gtk_object_get_data(GTK_OBJECT(widget), "_dw_waiting"))
+		return;
+
+	if(GTK_IS_VPANED(widget))
+		size = widget->allocation.height;
+	else if(GTK_IS_HPANED(widget))
+		size = widget->allocation.width;
+
+	if(size > 0)
+		*percent = ((float)(position * 100) / (float)size);
+}
+#endif
+
+/*
+ * Creates a splitbar window (widget) with given parameters.
+ * Parameters:
+ *       type: Value can be DW_VERT or DW_HORZ.
+ *       topleft: Handle to the window to be top or left.
+ *       bottomright:  Handle to the window to be bottom or right.
+ * Returns:
+ *       A handle to a splitbar window or NULL on failure.
+ */
+HWND dw_splitbar_new(int type, HWND topleft, HWND bottomright, unsigned long id)
+{
+	GtkWidget *tmp = NULL;
+	int _locked_by_me = FALSE;
+	float *percent = malloc(sizeof(float));
+  
+	DW_MUTEX_LOCK;
+	if(type == DW_HORZ)
+		tmp = gtk_hpaned_new();
+	else
+		tmp = gtk_vpaned_new();
+	gtk_paned_add1(GTK_PANED(tmp), topleft);
+	gtk_paned_add2(GTK_PANED(tmp), bottomright);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_id", (gpointer)id);
+	*percent = 50.0;
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_percent", (gpointer)percent);
+	gtk_object_set_data(GTK_OBJECT(tmp), "_dw_waiting", (gpointer)1);
+	gtk_signal_connect(GTK_OBJECT(tmp), "size-allocate", GTK_SIGNAL_FUNC(_splitbar_size_allocate), NULL);
+#if GTK_MAJOR_VERSION > 1
+	g_signal_connect(G_OBJECT(tmp), "notify::position", (GCallback)_splitbar_accept_position, (gpointer)tmp);
+#else
+	gtk_paned_set_handle_size(GTK_PANED(tmp), 3);
+#endif
+	gtk_widget_show(tmp);
+	DW_MUTEX_UNLOCK;
+	return tmp;
+}
+
+/*
+ * Sets the position of a splitbar (pecentage).
+ * Parameters:
+ *       handle: The handle to the splitbar returned by dw_splitbar_new().
+ */
+void dw_splitbar_set(HWND handle, float percent)
+{
+	float *mypercent = (float *)dw_window_get_data(handle, "_dw_percent");
+	int size = 0, position;
+
+	if(GTK_IS_VPANED(handle))
+		size = handle->allocation.height;
+	else if(GTK_IS_HPANED(handle))
+		size = handle->allocation.width;
+
+	if(mypercent)
+		*mypercent = percent;
+
+	if(size > 10)
+	{        
+		position = (int)((float)size * (percent / 100.0));
+
+		gtk_paned_set_position(GTK_PANED(handle), position);
+	}
+}
+
+/*
+ * Gets the position of a splitbar (pecentage).
+ * Parameters:
+ *       handle: The handle to the splitbar returned by dw_splitbar_new().
+ */
+float dw_splitbar_get(HWND handle)
+{
+	float *percent = (float *)dw_window_get_data(handle, "_dw_percent");
+
+	if(percent)
+		return *percent;
+	return 0.0;
+}
+
+/*
+ * Pack windows (widgets) into a box from the start (or top).
+ * Parameters:
+ *       box: Window handle of the box to be packed into.
+ *       item: Window handle of the item to be back.
+ *       width: Width in pixels of the item or -1 to be self determined.
+ *       height: Height in pixels of the item or -1 to be self determined.
+ *       hsize: TRUE if the window (widget) should expand horizontally to fill space given.
+ *       vsize: TRUE if the window (widget) should expand vertically to fill space given.
+ *       pad: Number of pixels of padding around the item.
+ */
+void dw_box_pack_start(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad)
+{
+	int warn = FALSE, _locked_by_me = FALSE;
+	GtkWidget *tmp, *tmpitem;
+
+	if(!box)
+		return;
+
+		/*
+		 * If you try and pack an item into itself VERY bad things can happen; like at least an
+		 * infinite loop on GTK! Lets be safe!
+		 */
+	if(box == item)
+	{
+		dw_messagebox("dw_box_pack_start()", DW_MB_OK|DW_MB_ERROR, "Danger! Danger! Will Robinson; box and item are the same!",box,item);
+		return;
+	}
+
+	DW_MUTEX_LOCK;
+
+	if((tmp  = gtk_object_get_data(GTK_OBJECT(box), "_dw_boxhandle")))
+		box = tmp;
+
+	if(!item)
+	{
+		item = gtk_label_new("");
+		gtk_widget_show(item);
+	}
+
+	tmpitem = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(item), "_dw_boxhandle");
+
+	if(GTK_IS_TABLE(box))
+	{
+		int boxcount = (int)gtk_object_get_data(GTK_OBJECT(box), "_dw_boxcount");
+		int boxtype = (int)gtk_object_get_data(GTK_OBJECT(box), "_dw_boxtype");
+		int x, y;
+
+		/* If the item being packed is a box, then we use it's padding
+		 * instead of the padding specified on the pack line, this is
+		 * due to a bug in the OS/2 and Win32 renderer and a limitation
+		 * of the GtkTable class.
+		 */
+		if(GTK_IS_TABLE(item) || (tmpitem && GTK_IS_TABLE(tmpitem)))
+		{
+			GtkWidget *eventbox = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(item), "_dw_eventbox");
+
+			if(eventbox)
+			{
+				gtk_container_add(GTK_CONTAINER(eventbox), item);
+				pad = (int)gtk_object_get_data(GTK_OBJECT(item), "_dw_boxpad");
+				item = eventbox;
+			}
+		}
+		else
+		{
+			/* Only show warning if item is not a box */
+			warn = TRUE;
+		}
+
+		if(boxtype == DW_VERT)
+		{
+			x = 0;
+			y = boxcount;
+			gtk_table_resize(GTK_TABLE(box), boxcount + 1, 1);
+		}
+		else
+		{
+			x = boxcount;
+			y = 0;
+			gtk_table_resize(GTK_TABLE(box), 1, boxcount + 1);
+		}
+
+		gtk_table_attach(GTK_TABLE(box), item, x, x + 1, y, y + 1, hsize ? DW_EXPAND : 0, vsize ? DW_EXPAND : 0, pad, pad);
+		gtk_object_set_data(GTK_OBJECT(box), "_dw_boxcount", (gpointer)boxcount + 1);
+		gtk_widget_set_usize(item, width, height);
+		if(GTK_IS_RADIO_BUTTON(item))
+		{
+			GSList *group;
+			GtkWidget *groupstart = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(box), "_dw_group");
+
+			if(groupstart)
+			{
+				group = gtk_radio_button_group(GTK_RADIO_BUTTON(groupstart));
+				gtk_radio_button_set_group(GTK_RADIO_BUTTON(item), group);
+			}
+			else
+				gtk_object_set_data(GTK_OBJECT(box), "_dw_group", (gpointer)item);
+		}
+	}
+	else
+	{
+		GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
+
+		if(GTK_IS_TABLE(item) || (tmpitem && GTK_IS_TABLE(tmpitem)))
+		{
+			GtkWidget *eventbox = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(item), "_dw_eventbox");
+
+			if(eventbox)
+			{
+				gtk_container_add(GTK_CONTAINER(eventbox), item);
+				pad = (int)gtk_object_get_data(GTK_OBJECT(item), "_dw_boxpad");
+				item = eventbox;
+			}
+		}
+		else
+		{
+			/* Only show warning if item is not a box */
+			warn = TRUE;
+		}
+
+		gtk_container_border_width(GTK_CONTAINER(box), pad);
+		gtk_container_add(GTK_CONTAINER(box), vbox);
+		gtk_box_pack_end(GTK_BOX(vbox), item, TRUE, TRUE, 0);
+		gtk_widget_show(vbox);
+
+		gtk_widget_set_usize(item, width, height);
+		gtk_object_set_user_data(GTK_OBJECT(box), vbox);
+	}
+	DW_MUTEX_UNLOCK;
+
+	if(warn)
+	{
+		if ( width == 0 && hsize == FALSE )
+			dw_messagebox("dw_box_pack_start()", DW_MB_OK|DW_MB_ERROR, "Width and expand Horizonal both unset for box: %x item: %x",box,item);
+		if ( height == 0 && vsize == FALSE )
+			dw_messagebox("dw_box_pack_start()", DW_MB_OK|DW_MB_ERROR, "Height and expand Vertical both unset for box: %x item: %x",box,item);
+	}
+}
+
+/*
+ * Sets the default focus item for a window/dialog.
+ * Parameters:
+ *         window: Toplevel window or dialog.
+ *         defaultitem: Handle to the dialog item to be default.
+ */
+void dw_window_default(HWND window, HWND defaultitem)
+{
+	int _locked_by_me = FALSE;
+
+	if(!window)
+		return;
+
+	DW_MUTEX_LOCK;
+	gtk_object_set_data(GTK_OBJECT(window),  "_dw_defaultitem", (gpointer)defaultitem);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Sets window to click the default dialog item when an ENTER is pressed.
+ * Parameters:
+ *         window: Window (widget) to look for the ENTER press.
+ *         next: Window (widget) to move to next (or click)
+ */
+void dw_window_click_default(HWND window, HWND next)
+{
+	int _locked_by_me = FALSE;
+
+	if(!window)
+		return;
+
+	DW_MUTEX_LOCK;
+	gtk_signal_connect(GTK_OBJECT(window), "key_press_event", GTK_SIGNAL_FUNC(_default_key_press_event), next);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Returns some information about the current operating environment.
+ * Parameters:
+ *       env: Pointer to a DWEnv struct.
+ */
+void dw_environment_query(DWEnv *env)
+{
+	struct utsname name;
+	char tempbuf[100];
+	int len, z;
+
+	uname(&name);
+	strcpy(env->osName, name.sysname);
+	strcpy(tempbuf, name.release);
+
+	env->MajorBuild = env->MinorBuild = 0;
+
+	len = strlen(tempbuf);
+
+	strcpy(env->buildDate, __DATE__);
+	strcpy(env->buildTime, __TIME__);
+	env->DWMajorVersion = DW_MAJOR_VERSION;
+	env->DWMinorVersion = DW_MINOR_VERSION;
+	env->DWSubVersion = DW_SUB_VERSION;
+
+	for(z=1;z<len;z++)
+	{
+		if(tempbuf[z] == '.')
+		{
+			tempbuf[z] = '\0';
+			env->MajorVersion = atoi(&tempbuf[z-1]);
+			env->MinorVersion = atoi(&tempbuf[z+1]);
+			return;
+		}
+	}
+	env->MajorVersion = atoi(tempbuf);
+	env->MinorVersion = 0;
+}
+
+/* Internal function to handle the file OK press */
+static gint _gtk_file_ok(GtkWidget *widget, DWDialog *dwwait)
+{
+#if GTK_MAJOR_VERSION > 1
+	const char *tmp;
+#else
+	char *tmp;
+#endif
+	char *tmpdup=NULL;
+
+	if(!dwwait)
+		return FALSE;
+
+	if((tmp = gtk_file_selection_get_filename(GTK_FILE_SELECTION(dwwait->data))))
+		tmpdup = strdup(tmp);
+	gtk_widget_destroy(GTK_WIDGET(dwwait->data));
+	_dw_file_active = 0;
+	dw_dialog_dismiss(dwwait, (void *)tmpdup);
+	return FALSE;
+}
+
+/* Internal function to handle the file Cancel press */
+static gint _gtk_file_cancel(GtkWidget *widget, DWDialog *dwwait)
+{
+	if(!dwwait)
+		return FALSE;
+
+	gtk_widget_destroy(GTK_WIDGET(dwwait->data));
+	_dw_file_active = 0;
+	dw_dialog_dismiss(dwwait, NULL);
+	return FALSE;
+}
+
+/* The next few functions are support functions for the UNIX folder browser */
+static void _populate_directory(HWND tree, HTREEITEM parent, char *path)
+{
+	struct dirent *dent;
+	HTREEITEM item;
+	DIR *hdir;
+
+	if((hdir = opendir(path)))
+	{
+		while((dent = readdir(hdir)))
+		{
+			if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, ".."))
+			{
+				int len = strlen(path);
+				char *folder = malloc(len + strlen(dent->d_name) + 2);
+				struct stat bleah;
+				HTREEITEM tempitem;
+
+				strcpy(folder, path);
+				strcpy(&folder[len], dent->d_name);
+
+				stat(folder, &bleah);
+
+				if(S_IFDIR & bleah.st_mode)
+				{
+					item = dw_tree_insert(tree, dent->d_name, 0, parent, (void *)parent);
+					tempitem = dw_tree_insert(tree, "", 0, item, 0);
+					dw_tree_set_data(tree, item, (void *)tempitem);
+				}
+
+				free(folder);
+			}
+		}
+		closedir(hdir);
+	}
+}
+
+static int DWSIGNAL _dw_folder_ok_func(HWND window, void *data)
+{
+	DWDialog *dwwait = (DWDialog *)data;
+	void *treedata;
+
+	if(!dwwait)
+		return FALSE;
+
+	treedata = dw_window_get_data((HWND)dwwait->data, "_dw_tree_selected");
+	dw_window_destroy((HWND)dwwait->data);
+	dw_dialog_dismiss(dwwait, treedata);
+	return FALSE;
+}
+
+static int DWSIGNAL _dw_folder_cancel_func(HWND window, void *data)
+{
+	DWDialog *dwwait = (DWDialog *)data;
+
+	if(!dwwait)
+		return FALSE;
+
+	dw_window_destroy((HWND)dwwait->data);
+	dw_dialog_dismiss(dwwait, NULL);
+	return FALSE;
+}
+
+static char *_tree_folder(HWND tree, HTREEITEM item)
+{
+	char *folder=strdup("");
+	HTREEITEM parent = item;
+
+	while(parent)
+	{
+		char *temp, *text = dw_tree_get_title(tree, parent);
+
+		if(text)
+		{
+			temp = malloc(strlen(text) + strlen(folder) + 3);
+			strcpy(temp, text);
+			if(strcmp(text, "/"))
+				strcat(temp, "/");
+			strcat(temp, folder);
+			free(folder);
+			folder = temp;
+		}
+		parent = dw_tree_get_parent(tree, parent);
+	}
+	return folder;
+}
+
+static int DWSIGNAL _item_select(HWND window, HTREEITEM item, char *text, void *data, void *itemdata)
+{
+	DWDialog *dwwait = (DWDialog *)data;
+	char *treedata = (char *)dw_window_get_data((HWND)dwwait->data, "_dw_tree_selected");
+
+	text = text; itemdata = itemdata;
+	if(treedata)
+		free(treedata);
+
+	treedata = _tree_folder(window, item);
+	dw_window_set_data((HWND)dwwait->data, "_dw_tree_selected", (void *)treedata);
+
+	return FALSE;
+}
+
+static int DWSIGNAL _tree_expand(HWND window, HTREEITEM item, void *data)
+{
+	DWDialog *dwwait = (DWDialog *)data;
+	HWND tree = (HWND)dw_window_get_data((HWND)dwwait->data, "_dw_tree");
+	HTREEITEM tempitem = (HTREEITEM)dw_tree_get_data(tree, item);
+
+	if(tempitem)
+	{
+		char *folder = _tree_folder(tree, item);
+
+		dw_tree_set_data(tree, item, 0);
+
+		if(*folder)
+			_populate_directory(tree, item, folder);
+
+#if GTK_MAJOR_VERSION > 1
+		/* FIXME: GTK 1.x tree control goes crazy when
+		 * I delete the temporary item.  The subtree
+		 * it sits on ceases to be valid and attempts
+		 * to delete or recreate it fail horribly.
+		 */
+		dw_tree_delete(tree, tempitem);
+#endif
+		free(folder);
+	}
+
+	return FALSE;
+}
+
+/*
+ * Opens a file dialog and queries user selection.
+ * Parameters:
+ *       title: Title bar text for dialog.
+ *       defpath: The default path of the open dialog.
+ *       ext: Default file extention.
+ *       flags: DW_FILE_OPEN or DW_FILE_SAVE or DW_DIRECTORY_OPEN
+ * Returns:
+ *       NULL on error. A malloced buffer containing
+ *       the file path on success.
+ *       
+ */
+char *dw_file_browse(char *title, char *defpath, char *ext, int flags)
+{
+	GtkWidget *filew;
+	int _locked_by_me = FALSE;
+	DWDialog *dwwait;
+
+	if(flags == DW_DIRECTORY_OPEN)
+	{
+		HWND window, hbox, vbox, tree, button;
+		HTREEITEM item, tempitem;
+
+		window = dw_window_new( HWND_DESKTOP, title, DW_FCF_SHELLPOSITION | DW_FCF_TITLEBAR | DW_FCF_SIZEBORDER | DW_FCF_MINMAX);
+
+		vbox = dw_box_new(DW_VERT, 5);
+
+		dw_box_pack_start(window, vbox, 0, 0, TRUE, TRUE, 0);
+
+		tree = dw_tree_new(60);
+
+		dw_box_pack_start(vbox, tree, 1, 1, TRUE, TRUE, 0);
+		dw_window_set_data(window, "_dw_tree", (void *)tree);
+
+		hbox = dw_box_new(DW_HORZ, 0);
+
+		dw_box_pack_start(vbox, hbox, 0, 0, TRUE, FALSE, 0);
+
+		dwwait = dw_dialog_new((void *)window);
+
+		dw_signal_connect(tree, DW_SIGNAL_ITEM_SELECT, DW_SIGNAL_FUNC(_item_select), (void *)dwwait);
+		dw_signal_connect(tree, DW_SIGNAL_TREE_EXPAND, DW_SIGNAL_FUNC(_tree_expand), (void *)dwwait);
+
+		button = dw_button_new("Ok", 1001L);
+		dw_box_pack_start(hbox, button, 50, 30, TRUE, FALSE, 3);
+		dw_signal_connect(button, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_folder_ok_func), (void *)dwwait);
+
+		button = dw_button_new("Cancel", 1002L);
+		dw_box_pack_start(hbox, button, 50, 30, TRUE, FALSE, 3);
+		dw_signal_connect(button, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_folder_cancel_func), (void *)dwwait);
+
+		item = dw_tree_insert(tree, "/", 0, NULL, 0);
+		tempitem = dw_tree_insert(tree, "", 0, item, 0);
+		dw_tree_set_data(tree, item, (void *)tempitem);
+
+		dw_window_set_usize(window, 225, 300);
+		dw_window_show(window);
+	}
+	else
+	{
+		DW_MUTEX_LOCK;
+
+		/* The DW mutex should be sufficient for
+		 * insuring no thread changes this unknowingly.
+		 */
+		if(_dw_file_active)
+		{
+			DW_MUTEX_UNLOCK;
+			return NULL;
+		}
+
+		_dw_file_active = 1;
+
+		filew = gtk_file_selection_new(title);
+
+		dwwait = dw_dialog_new((void *)filew);
+
+		gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filew)->ok_button), "clicked", (GtkSignalFunc) _gtk_file_ok, dwwait);
+		gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filew)->cancel_button), "clicked", (GtkSignalFunc) _gtk_file_cancel, dwwait);
+
+		if(defpath)
+			gtk_file_selection_set_filename(GTK_FILE_SELECTION(filew), defpath);
+
+		gtk_widget_show(filew);
+
+		DW_MUTEX_UNLOCK;
+	}
+	return (char *)dw_dialog_wait(dwwait);
+}
+
+
+/*
+ * Execute and external program in a seperate session.
+ * Parameters:
+ *       program: Program name with optional path.
+ *       type: Either DW_EXEC_CON or DW_EXEC_GUI.
+ *       params: An array of pointers to string arguements.
+ * Returns:
+ *       -1 on error.
+ */
+int dw_exec(char *program, int type, char **params)
+{
+	int ret = -1;
+
+	if((ret = fork()) == 0)
+	{
+		int i;
+
+		for (i = 3; i < 256; i++)
+			close(i);
+		setsid();
+		if(type == DW_EXEC_GUI)
+		{
+			execvp(program, params);
+		}
+		else if(type == DW_EXEC_CON)
+		{
+			char **tmpargs;
+
+			if(!params)
+			{
+				tmpargs = malloc(sizeof(char *));
+				tmpargs[0] = NULL;
+			}
+			else
+			{
+				int z = 0;
+
+				while(params[z])
+				{
+					z++;
+				}
+				tmpargs = malloc(sizeof(char *)*(z+3));
+				z=0;
+				tmpargs[0] = "xterm";
+				tmpargs[1] = "-e";
+				while(params[z])
+				{
+					tmpargs[z+2] = params[z];
+					z++;
+				}
+				tmpargs[z+2] = NULL;
+			}
+			execvp("xterm", tmpargs);
+			free(tmpargs);
+		}
+		/* If we got here exec failed */
+		_exit(-1);
+	}
+	return ret;
+}
+
+/*
+ * Loads a web browser pointed at the given URL.
+ * Parameters:
+ *       url: Uniform resource locator.
+ */
+int dw_browse(char *url)
+{
+	/* Is there a way to find the webbrowser in Unix? */
+	char *execargs[3], *browser = "netscape", *tmp;
+
+	tmp = getenv( "DW_BROWSER" );
+	if(tmp) browser = tmp;
+	execargs[0] = browser;
+	execargs[1] = url;
+	execargs[2] = NULL;
+
+	return dw_exec(browser, DW_EXEC_GUI, execargs);
+}
+
+/*
+ * Returns a pointer to a static buffer which containes the
+ * current user directory.  Or the root directory (C:\ on
+ * OS/2 and Windows).
+ */
+char *dw_user_dir(void)
+{
+	static char _user_dir[1024] = "";
+
+	if(!_user_dir[0])
+	{
+		char *home = getenv("HOME");
+
+		if(home)
+			strcpy(_user_dir, home);
+		else
+			strcpy(_user_dir, "/");
+	}
+	return _user_dir;
+}
+
+/*
+ * Call a function from the window (widget)'s context.
+ * Parameters:
+ *       handle: Window handle of the widget.
+ *       function: Function pointer to be called.
+ *       data: Pointer to the data to be passed to the function.
+ */
+void dw_window_function(HWND handle, void *function, void *data)
+{
+	void (* windowfunc)(void *);
+
+	windowfunc = function;
+
+	if(windowfunc)
+		windowfunc(data);
+}
+
+/*
+ * Add a named user data item to a window handle.
+ * Parameters:
+ *       window: Window handle of signal to be called back.
+ *       dataname: A string pointer identifying which signal to be hooked.
+ *       data: User data to be passed to the handler function.
+ */
+void dw_window_set_data(HWND window, char *dataname, void *data)
+{
+	int _locked_by_me = FALSE;
+
+	if(!window)
+		return;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_OBJECT(window))
+	{
+		if(GTK_IS_SCROLLED_WINDOW(window))
+		{
+			HWND thiswindow = (HWND)gtk_object_get_user_data(GTK_OBJECT(window));
+
+			if(thiswindow && GTK_IS_OBJECT(thiswindow))
+				gtk_object_set_data(GTK_OBJECT(thiswindow), dataname, (gpointer)data);
+		}
+		if(GTK_IS_COMBO(window))
+			gtk_object_set_data(GTK_OBJECT(GTK_COMBO(window)->entry), dataname, (gpointer)data);
+		gtk_object_set_data(GTK_OBJECT(window), dataname, (gpointer)data);
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Gets a named user data item to a window handle.
+ * Parameters:
+ *       window: Window handle of signal to be called back.
+ *       dataname: A string pointer identifying which signal to be hooked.
+ *       data: User data to be passed to the handler function.
+ */
+void *dw_window_get_data(HWND window, char *dataname)
+{
+	int _locked_by_me = FALSE;
+	void *ret = NULL;
+
+	if(!window)
+		return NULL;
+
+	DW_MUTEX_LOCK;
+    if(GTK_IS_OBJECT(window))
+		ret = (void *)gtk_object_get_data(GTK_OBJECT(window), dataname);
+	DW_MUTEX_UNLOCK;
+	return ret;
+}
+
+/*
+ * Add a callback to a timer event.
+ * Parameters:
+ *       interval: Milliseconds to delay between calls.
+ *       sigfunc: The pointer to the function to be used as the callback.
+ *       data: User data to be passed to the handler function.
+ * Returns:
+ *       Timer ID for use with dw_timer_disconnect(), 0 on error.
+ */
+int API dw_timer_connect(int interval, void *sigfunc, void *data)
+{
+	int tag, _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	tag = gtk_timeout_add(interval, (GtkFunction)sigfunc, data);
+	DW_MUTEX_UNLOCK;
+	return tag;
+}
+
+/*
+ * Removes timer callback.
+ * Parameters:
+ *       id: Timer ID returned by dw_timer_connect().
+ */
+void API dw_timer_disconnect(int id)
+{
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	gtk_timeout_remove(id);
+	DW_MUTEX_UNLOCK;
+}
+
+/* Get the actual signal window handle not the user window handle
+ * Should mimic the code in dw_signal_connect() below.
+ */
+static HWND _find_signal_window(HWND window, char *signame)
+{
+	HWND thiswindow = window;
+
+	if(GTK_IS_SCROLLED_WINDOW(thiswindow))
+		thiswindow = (HWND)gtk_object_get_user_data(GTK_OBJECT(window));
+	else if(GTK_IS_COMBO(thiswindow) && signame && strcmp(signame, DW_SIGNAL_LIST_SELECT) == 0)
+		thiswindow = GTK_COMBO(thiswindow)->list;
+	else if(GTK_IS_COMBO(thiswindow) && signame && strcmp(signame, DW_SIGNAL_SET_FOCUS) == 0)
+		thiswindow = GTK_COMBO(thiswindow)->entry;
+	else if(GTK_IS_VSCALE(thiswindow) || GTK_IS_HSCALE(thiswindow) ||
+			GTK_IS_VSCROLLBAR(thiswindow) || GTK_IS_HSCROLLBAR(thiswindow))
+		thiswindow = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(thiswindow), "_dw_adjustment");
+#if GTK_MAJOR_VERSION > 1
+	else if(GTK_IS_TREE_VIEW(thiswindow) && strcmp(signame, DW_SIGNAL_ITEM_SELECT) == 0)
+		thiswindow = (GtkWidget *)gtk_tree_view_get_selection(GTK_TREE_VIEW(thiswindow));
+#endif
+	return thiswindow;
+}
+
+/*
+ * Add a callback to a window event.
+ * Parameters:
+ *       window: Window handle of signal to be called back.
+ *       signame: A string pointer identifying which signal to be hooked.
+ *       sigfunc: The pointer to the function to be used as the callback.
+ *       data: User data to be passed to the handler function.
+ */
+void dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data)
+{
+	void *thisfunc  = _findsigfunc(signame);
+	char *thisname = signame;
+	HWND thiswindow = window;
+	int sigid, _locked_by_me = FALSE;
+	gint cid;
+
+	DW_MUTEX_LOCK;
+	if(GTK_IS_SCROLLED_WINDOW(thiswindow))
+	{
+		thiswindow = (HWND)gtk_object_get_user_data(GTK_OBJECT(window));
+	}
+
+	if(GTK_IS_MENU_ITEM(thiswindow) && strcmp(signame, DW_SIGNAL_CLICKED) == 0)
+	{
+		thisname = "activate";
+		thisfunc = _findsigfunc(thisname);
+	}
+	else if(GTK_IS_CLIST(thiswindow) && strcmp(signame, DW_SIGNAL_ITEM_CONTEXT) == 0)
+	{
+		thisname = "button_press_event";
+		thisfunc = _findsigfunc(DW_SIGNAL_ITEM_CONTEXT);
+	}
+#if GTK_MAJOR_VERSION > 1
+	else if(GTK_IS_TREE_VIEW(thiswindow)  && strcmp(signame, DW_SIGNAL_ITEM_CONTEXT) == 0)
+	{
+		thisfunc = _findsigfunc("tree-context");
+		sigid = _set_signal_handler(thiswindow, window, sigfunc, data, thisfunc);
+		cid = gtk_signal_connect(GTK_OBJECT(thiswindow), "button_press_event", GTK_SIGNAL_FUNC(thisfunc), (gpointer)sigid);
+		_set_signal_handler_id(thiswindow, sigid, cid);
+		sigid = _set_signal_handler(window, window, sigfunc, data, thisfunc);
+		cid = gtk_signal_connect(GTK_OBJECT(window), "button_press_event", GTK_SIGNAL_FUNC(thisfunc), (gpointer)sigid);
+		_set_signal_handler_id(window, sigid, cid);
+		DW_MUTEX_UNLOCK;
+		return;
+	}
+	else if(GTK_IS_TREE_VIEW(thiswindow) && strcmp(signame, DW_SIGNAL_ITEM_SELECT) == 0)
+	{
+		GtkWidget *treeview = thiswindow;
+
+		thiswindow = (GtkWidget *)gtk_tree_view_get_selection(GTK_TREE_VIEW(thiswindow));
+		thisname = "changed";
+
+		sigid = _set_signal_handler(treeview, window, sigfunc, data, thisfunc);
+		cid = g_signal_connect(G_OBJECT(thiswindow), thisname, (GCallback)thisfunc, (gpointer)sigid);
+		_set_signal_handler_id(treeview, sigid, cid);
+		DW_MUTEX_UNLOCK;
+		return;
+	}
+	else if(GTK_IS_TREE_VIEW(thiswindow) && strcmp(signame, DW_SIGNAL_TREE_EXPAND) == 0)
+	{
+		thisname = "row-expanded";
+	}
+#else
+	else if(GTK_IS_TREE(thiswindow)  && strcmp(signame, DW_SIGNAL_ITEM_CONTEXT) == 0)
+	{
+		thisfunc = _findsigfunc("tree-context");
+		sigid = _set_signal_handler(thiswindow, window, sigfunc, data, thisfunc);
+
+		gtk_object_set_data(GTK_OBJECT(thiswindow), "_dw_container_context_func", (gpointer)thisfunc);
+		gtk_object_set_data(GTK_OBJECT(thiswindow), "_dw_container_context_data", (gpointer)sigid);
+		cid = gtk_signal_connect(GTK_OBJECT(thiswindow), "button_press_event", GTK_SIGNAL_FUNC(thisfunc), (gpointer)sigid);
+		_set_signal_handler_id(thiswindow, sigid, cid);
+		sigid = _set_signal_handler(window, window, sigfunc, data, thisfunc);
+		cid = gtk_signal_connect(GTK_OBJECT(window), "button_press_event", GTK_SIGNAL_FUNC(thisfunc), (gpointer)sigid);
+		_set_signal_handler_id(window, sigid, cid);
+		DW_MUTEX_UNLOCK;
+		return;
+	}
+	else if(GTK_IS_TREE(thiswindow) && strcmp(signame, DW_SIGNAL_ITEM_SELECT) == 0)
+	{
+		if(thisfunc)
+		{
+			sigid = _set_signal_handler(thiswindow, window, sigfunc, data, thisfunc);
+			gtk_object_set_data(GTK_OBJECT(thiswindow), "_dw_select_child_func", (gpointer)thisfunc);
+			gtk_object_set_data(GTK_OBJECT(thiswindow), "_dw_select_child_data", (gpointer)sigid);
+		}
+		thisname = "select-child";
+	}
+	else if(GTK_IS_TREE(thiswindow) && strcmp(signame, DW_SIGNAL_TREE_EXPAND) == 0)
+	{
+		if(thisfunc)
+		{
+			sigid = _set_signal_handler(thiswindow, window, sigfunc, data, thisfunc);
+			gtk_object_set_data(GTK_OBJECT(thiswindow), "_dw_tree_expand_func", (gpointer)thisfunc);
+			gtk_object_set_data(GTK_OBJECT(thiswindow), "_dw_tree_expand_data", (gpointer)sigid);
+		}
+		DW_MUTEX_UNLOCK;
+		return;
+	}
+#endif
+	else if(GTK_IS_CLIST(thiswindow) && strcmp(signame, DW_SIGNAL_ITEM_ENTER) == 0)
+	{
+		sigid = _set_signal_handler(thiswindow, window, sigfunc, data, _container_enter_event);
+		cid = gtk_signal_connect(GTK_OBJECT(thiswindow), "key_press_event", GTK_SIGNAL_FUNC(_container_enter_event), (gpointer)sigid);
+		_set_signal_handler_id(thiswindow, sigid, cid);
+
+		thisname = "button_press_event";
+		thisfunc = _findsigfunc(DW_SIGNAL_ITEM_ENTER);
+	}
+	else if(GTK_IS_CLIST(thiswindow) && strcmp(signame, DW_SIGNAL_ITEM_SELECT) == 0)
+	{
+		thisname = "select_row";
+		thisfunc = (void *)_container_select_row;
+	}
+	else if(GTK_IS_COMBO(thiswindow) && strcmp(signame, DW_SIGNAL_LIST_SELECT) == 0)
+	{
+		thisname = "select_child";
+		thiswindow = GTK_COMBO(thiswindow)->list;
+	}
+	else if(GTK_IS_LIST(thiswindow) && strcmp(signame, DW_SIGNAL_LIST_SELECT) == 0)
+	{
+		thisname = "select_child";
+	}
+	else if(strcmp(signame, DW_SIGNAL_SET_FOCUS) == 0)
+	{
+		thisname = "focus-in-event";
+		if(GTK_IS_COMBO(thiswindow))
+			thiswindow = GTK_COMBO(thiswindow)->entry;
+	}
+#if 0
+	else if(strcmp(signame, DW_SIGNAL_LOSE_FOCUS) == 0)
+	{
+		thisname = "focus-out-event";
+		if(GTK_IS_COMBO(thiswindow))
+			thiswindow = GTK_COMBO(thiswindow)->entry;
+	}
+#endif
+	else if(GTK_IS_VSCALE(thiswindow) || GTK_IS_HSCALE(thiswindow) ||
+			GTK_IS_VSCROLLBAR(thiswindow) || GTK_IS_HSCROLLBAR(thiswindow))
+	{
+		thiswindow = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(thiswindow), "_dw_adjustment");
+	}
+	else if(GTK_IS_NOTEBOOK(thiswindow) && strcmp(signame, DW_SIGNAL_SWITCH_PAGE) == 0)
+	{
+		thisname = "switch-page";
+	}
+	else if(GTK_IS_CLIST(thiswindow) && strcmp(signame, DW_SIGNAL_COLUMN_CLICK) == 0)
+	{
+		thisname = "click-column";
+	}
+
+	if(!thisfunc || !thiswindow)
+	{
+		DW_MUTEX_UNLOCK;
+		return;
+	}
+
+	sigid = _set_signal_handler(thiswindow, window, sigfunc, data, thisfunc);
+	cid = gtk_signal_connect(GTK_OBJECT(thiswindow), thisname, GTK_SIGNAL_FUNC(thisfunc),(gpointer)sigid);
+	_set_signal_handler_id(thiswindow, sigid, cid);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Removes callbacks for a given window with given name.
+ * Parameters:
+ *       window: Window handle of callback to be removed.
+ */
+void dw_signal_disconnect_by_name(HWND window, char *signame)
+{
+	HWND thiswindow;
+	int z, count;
+	void *thisfunc;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	thiswindow = _find_signal_window(window, signame);
+	count = (int)gtk_object_get_data(GTK_OBJECT(thiswindow), "_dw_sigcounter");
+	thisfunc  = _findsigfunc(signame);
+
+	for(z=0;z<count;z++)
+	{
+		SignalHandler sh = _get_signal_handler(thiswindow, (gpointer)z);
+
+		if(sh.intfunc == thisfunc)
+			_remove_signal_handler(thiswindow, z);
+	}
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Removes all callbacks for a given window.
+ * Parameters:
+ *       window: Window handle of callback to be removed.
+ */
+void dw_signal_disconnect_by_window(HWND window)
+{
+	HWND thiswindow;
+	int z, count;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	thiswindow = _find_signal_window(window, NULL);
+	count = (int)gtk_object_get_data(GTK_OBJECT(thiswindow), "_dw_sigcounter");
+
+	for(z=0;z<count;z++)
+		_remove_signal_handler(thiswindow, z);
+	gtk_object_set_data(GTK_OBJECT(thiswindow), "_dw_sigcounter", NULL);
+	DW_MUTEX_UNLOCK;
+}
+
+/*
+ * Removes all callbacks for a given window with specified data.
+ * Parameters:
+ *       window: Window handle of callback to be removed.
+ *       data: Pointer to the data to be compared against.
+ */
+void dw_signal_disconnect_by_data(HWND window, void *data)
+{
+	HWND thiswindow;
+	int z, count;
+	int _locked_by_me = FALSE;
+
+	DW_MUTEX_LOCK;
+	thiswindow = _find_signal_window(window, NULL);
+	count = (int)gtk_object_get_data(GTK_OBJECT(thiswindow), "_dw_sigcounter");
+
+	for(z=0;z<count;z++)
+	{
+		SignalHandler sh = _get_signal_handler(thiswindow, (gpointer)z);
+
+		if(sh.data == data)
+			_remove_signal_handler(thiswindow, z);
+	}
+	DW_MUTEX_UNLOCK;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gtk/install.xpm	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,1314 @@
+/* XPM */
+static char * install_xpm[] = {
+"64 64 1247 2",
+"  	c None",
+". 	c #404040",
+"+ 	c #808080",
+"@ 	c #606260",
+"# 	c #404440",
+"$ 	c #383230",
+"% 	c #302020",
+"& 	c #402820",
+"* 	c #503020",
+"= 	c #504224",
+"- 	c #505428",
+"; 	c #282A14",
+"> 	c #202020",
+", 	c #35322B",
+"' 	c #2A2416",
+") 	c #212317",
+"! 	c #182218",
+"~ 	c #383934",
+"{ 	c #585050",
+"] 	c #5E4E48",
+"^ 	c #644C40",
+"/ 	c #604B38",
+"( 	c #5C4A30",
+"_ 	c #644E30",
+": 	c #6C5230",
+"< 	c #5A4A2E",
+"[ 	c #48422C",
+"} 	c #242116",
+"| 	c #141514",
+"1 	c #282A28",
+"2 	c #3A3B3A",
+"3 	c #4C4C4C",
+"4 	c #262626",
+"5 	c #6A6456",
+"6 	c #55492B",
+"7 	c #42462E",
+"8 	c #304430",
+"9 	c #303228",
+"0 	c #5C3A30",
+"a 	c #885440",
+"b 	c #886440",
+"c 	c #887440",
+"d 	c #645238",
+"e 	c #403030",
+"f 	c #201818",
+"g 	c #505450",
+"h 	c #747674",
+"i 	c #989898",
+"j 	c #1A1B1C",
+"k 	c #343638",
+"l 	c #222320",
+"m 	c #1C140C",
+"n 	c #281810",
+"o 	c #291E13",
+"p 	c #5B4B3B",
+"q 	c #8C7260",
+"r 	c #7D644B",
+"s 	c #6E5636",
+"t 	c #655537",
+"u 	c #5C5438",
+"v 	c #604B34",
+"w 	c #644230",
+"x 	c #764F38",
+"y 	c #885C40",
+"z 	c #886C40",
+"A 	c #70573C",
+"B 	c #584238",
+"C 	c #2C211C",
+"D 	c #3C3736",
+"E 	c #2C2220",
+"F 	c #665640",
+"G 	c #A08A60",
+"H 	c #AC9B7C",
+"I 	c #B8AC98",
+"J 	c #706758",
+"K 	c #282218",
+"L 	c #3A3732",
+"M 	c #686C70",
+"N 	c #444640",
+"O 	c #202010",
+"P 	c #382818",
+"Q 	c #523C26",
+"R 	c #765636",
+"S 	c #986440",
+"T 	c #906440",
+"U 	c #7C5C40",
+"V 	c #705440",
+"W 	c #382A20",
+"X 	c #786E6C",
+"Y 	c #584440",
+"Z 	c #A48258",
+"` 	c #F0C070",
+" .	c #E4C084",
+"..	c #D8C098",
+"+.	c #948264",
+"@.	c #504430",
+"#.	c #746E64",
+"$.	c #242620",
+"%.	c #202218",
+"&.	c #282214",
+"*.	c #302210",
+"=.	c #544134",
+"-.	c #786058",
+";.	c #6A5140",
+">.	c #5C4228",
+",.	c #644628",
+"'.	c #6C4A28",
+").	c #6D502F",
+"!.	c #7F5D37",
+"~.	c #906438",
+"{.	c #90603C",
+"].	c #905C40",
+"^.	c #8C5C40",
+"/.	c #8C603C",
+"(.	c #8C6438",
+"_.	c #886438",
+":.	c #88603C",
+"<.	c #8A6940",
+"[.	c #8C7640",
+"}.	c #463B20",
+"|.	c #363236",
+"1.	c #6C646C",
+"2.	c #807368",
+"3.	c #BAA170",
+"4.	c #E0C07C",
+"5.	c #E2C080",
+"6.	c #BC9B70",
+"7.	c #94765C",
+"8.	c #846D60",
+"9.	c #746464",
+"0.	c #4A4342",
+"a.	c #202220",
+"b.	c #303130",
+"c.	c #484C40",
+"d.	c #404430",
+"e.	c #504428",
+"f.	c #604420",
+"g.	c #744C30",
+"h.	c #886430",
+"i.	c #905C38",
+"j.	c #985440",
+"k.	c #905440",
+"l.	c #885C38",
+"m.	c #987640",
+"n.	c #A89840",
+"o.	c #544C20",
+"p.	c #201820",
+"q.	c #403040",
+"r.	c #887864",
+"s.	c #D0C088",
+"t.	c #E4B47C",
+"u.	c #D8A888",
+"v.	c #946C5C",
+"w.	c #503030",
+"x.	c #483A38",
+"y.	c #202118",
+"z.	c #404230",
+"A.	c #564B34",
+"B.	c #6C5438",
+"C.	c #745434",
+"D.	c #7C5430",
+"E.	c #825C38",
+"F.	c #8C6440",
+"G.	c #8C643C",
+"H.	c #88643C",
+"I.	c #865C3C",
+"J.	c #7C5C38",
+"K.	c #8A693C",
+"L.	c #B2914C",
+"M.	c #CCAC58",
+"N.	c #8E7A34",
+"O.	c #504810",
+"P.	c #282408",
+"Q.	c #362E28",
+"R.	c #6C5C50",
+"S.	c #A08E70",
+"T.	c #D4C090",
+"U.	c #DAC086",
+"V.	c #DABA82",
+"W.	c #D4B488",
+"X.	c #B0906C",
+"Y.	c #8C6C50",
+"Z.	c #846954",
+"`.	c #7C6658",
+" +	c #6E645C",
+".+	c #45433B",
+"++	c #181808",
+"@+	c #303010",
+"#+	c #644A28",
+"$+	c #906C40",
+"%+	c #7C6438",
+"&+	c #706430",
+"*+	c #8C7E38",
+"=+	c #C8A848",
+"-+	c #A09020",
+";+	c #4C4430",
+">+	c #988860",
+",+	c #B8A47C",
+"'+	c #CCB47C",
+")+	c #C8A870",
+"!+	c #C09870",
+"~+	c #B88870",
+"{+	c #4A4636",
+"]+	c #262720",
+"^+	c #4C4E40",
+"/+	c #64513C",
+"(+	c #7C5438",
+"_+	c #86683C",
+":+	c #7C6C38",
+"<+	c #786A3E",
+"[+	c #746844",
+"}+	c #7E6242",
+"|+	c #82603C",
+"1+	c #766434",
+"2+	c #765C38",
+"3+	c #7C5440",
+"4+	c #84693C",
+"5+	c #A4932C",
+"6+	c #BCA820",
+"7+	c #D68C34",
+"8+	c #F07048",
+"9+	c #D86832",
+"0+	c #C0601C",
+"a+	c #9C6520",
+"b+	c #786A24",
+"c+	c #96874C",
+"d+	c #B4A474",
+"e+	c #C6B286",
+"f+	c #D8BA94",
+"g+	c #D8B490",
+"h+	c #D4BA8C",
+"i+	c #CEBA82",
+"j+	c #CAAE76",
+"k+	c #C49C70",
+"l+	c #C09070",
+"m+	c #A27F64",
+"n+	c #846E58",
+"o+	c #856F4F",
+"p+	c #867046",
+"q+	c #73644B",
+"r+	c #605850",
+"s+	c #403D38",
+"t+	c #645850",
+"u+	c #604430",
+"v+	c #745438",
+"w+	c #68683C",
+"x+	c #606C48",
+"y+	c #746044",
+"z+	c #705C38",
+"A+	c #D0B800",
+"B+	c #E06C10",
+"C+	c #F02020",
+"D+	c #E8281C",
+"E+	c #E03018",
+"F+	c #E88230",
+"G+	c #F0D448",
+"H+	c #E0CA68",
+"I+	c #C8A070",
+"J+	c #C89870",
+"K+	c #C09868",
+"L+	c #B89860",
+"M+	c #7C6440",
+"N+	c #403020",
+"O+	c #403A30",
+"P+	c #3E342C",
+"Q+	c #483220",
+"R+	c #624B2C",
+"S+	c #7C6038",
+"T+	c #785E3E",
+"U+	c #7C5838",
+"V+	c #7C5834",
+"W+	c #7C5C30",
+"X+	c #765C30",
+"Y+	c #705C30",
+"Z+	c #705834",
+"`+	c #705438",
+" @	c #7E613C",
+".@	c #8C6E40",
+"+@	c #AC9242",
+"@@	c #CCB644",
+"#@	c #D08D26",
+"$@	c #D46408",
+"%@	c #DC4210",
+"&@	c #E42018",
+"*@	c #E02416",
+"=@	c #DC2814",
+"-@	c #E05124",
+";@	c #E47A34",
+">@	c #E29D58",
+",@	c #D2B486",
+"'@	c #D0A87C",
+")@	c #D2AE82",
+"!@	c #D2AA7C",
+"~@	c #D0A070",
+"{@	c #CCA070",
+"]@	c #C49C6C",
+"^@	c #BC9468",
+"/@	c #B89068",
+"(@	c #9A7654",
+"_@	c #745C44",
+":@	c #6C5C48",
+"<@	c #463F34",
+"[@	c #363736",
+"}@	c #181008",
+"|@	c #302010",
+"1@	c #504220",
+"2@	c #705430",
+"3@	c #885430",
+"4@	c #8C6E38",
+"5@	c #A88840",
+"6@	c #CCAE44",
+"7@	c #E4722C",
+"8@	c #D81010",
+"9@	c #D81810",
+"0@	c #D82010",
+"a@	c #D82018",
+"b@	c #D82020",
+"c@	c #E47048",
+"d@	c #D8A07C",
+"e@	c #D89870",
+"f@	c #D09870",
+"g@	c #B88868",
+"h@	c #B88860",
+"i@	c #A87E58",
+"j@	c #987450",
+"k@	c #6C6E6C",
+"l@	c #2E2A26",
+"m@	c #5C544C",
+"n@	c #66583E",
+"o@	c #765834",
+"p@	c #705830",
+"q@	c #765030",
+"r@	c #7C4C30",
+"s@	c #764C30",
+"t@	c #704C30",
+"u@	c #7C5F2C",
+"v@	c #887228",
+"w@	c #A28924",
+"x@	c #BCA020",
+"y@	c #CC8926",
+"z@	c #DC722C",
+"A@	c #D6451E",
+"B@	c #D01810",
+"C@	c #CC1C10",
+"D@	c #C82010",
+"E@	c #CC2010",
+"F@	c #D02010",
+"G@	c #D02014",
+"H@	c #D02018",
+"I@	c #DA482C",
+"J@	c #E47040",
+"K@	c #E09B4A",
+"L@	c #DCC654",
+"M@	c #D2B762",
+"N@	c #D0A476",
+"O@	c #D49C76",
+"P@	c #CC9876",
+"Q@	c #C8987C",
+"R@	c #C0986E",
+"S@	c #B89064",
+"T@	c #B88864",
+"U@	c #AC8358",
+"V@	c #A07E50",
+"W@	c #8A724C",
+"X@	c #746648",
+"Y@	c #86725E",
+"Z@	c #987E74",
+"`@	c #544B40",
+" #	c #10180C",
+".#	c #444444",
+"+#	c #888888",
+"@#	c #7C6E5C",
+"##	c #704430",
+"$#	c #886A28",
+"%#	c #B8A410",
+"&#	c #CC6408",
+"*#	c #C81010",
+"=#	c #C81810",
+"-#	c #C02010",
+";#	c #B82010",
+">#	c #E07618",
+",#	c #E8CC20",
+"'#	c #D8BA48",
+")#	c #C89888",
+"!#	c #C09874",
+"~#	c #B89060",
+"{#	c #B08858",
+"]#	c #A88850",
+"^#	c #A07650",
+"/#	c #986450",
+"(#	c #5C4A34",
+"_#	c #203018",
+":#	c #222222",
+"<#	c #5A4C3A",
+"[#	c #6C5430",
+"}#	c #685430",
+"|#	c #705030",
+"1#	c #6C5030",
+"2#	c #684C30",
+"3#	c #785B2C",
+"4#	c #A68C24",
+"5#	c #C4AE20",
+"6#	c #C48916",
+"7#	c #C4640C",
+"8#	c #C23E0E",
+"9#	c #C01810",
+"0#	c #C01C10",
+"a#	c #BC1C12",
+"b#	c #B81814",
+"c#	c #BC1C16",
+"d#	c #C02018",
+"e#	c #C02014",
+"f#	c #C42010",
+"g#	c #D04B18",
+"h#	c #D87620",
+"i#	c #D49546",
+"j#	c #D0B46C",
+"k#	c #D0AA6E",
+"l#	c #C0A070",
+"m#	c #C09C72",
+"n#	c #BC986E",
+"o#	c #B89868",
+"p#	c #B89464",
+"q#	c #B4905E",
+"r#	c #B0905C",
+"s#	c #B08C5A",
+"t#	c #A87E54",
+"u#	c #A87E50",
+"v#	c #826040",
+"w#	c #5C4230",
+"x#	c #5C5344",
+"y#	c #5C6458",
+"z#	c #382A18",
+"A#	c #605430",
+"B#	c #807228",
+"C#	c #D06E1C",
+"D#	c #B81018",
+"E#	c #B8181C",
+"F#	c #B82020",
+"G#	c #B82018",
+"H#	c #C82020",
+"I#	c #D07044",
+"J#	c #D8C068",
+"K#	c #C0A870",
+"L#	c #B8A870",
+"M#	c #B8A068",
+"N#	c #B89870",
+"O#	c #A89858",
+"P#	c #A89054",
+"Q#	c #A87460",
+"R#	c #A87458",
+"S#	c #A87450",
+"T#	c #644A30",
+"U#	c #5C5C54",
+"V#	c #342A18",
+"W#	c #685030",
+"X#	c #68502C",
+"Y#	c #685428",
+"Z#	c #746328",
+"`#	c #A28B1E",
+" $	c #C4A414",
+".$	c #C49116",
+"+$	c #C47E18",
+"@$	c #BA4B16",
+"#$	c #B01814",
+"$$	c #B41814",
+"%$	c #B01C16",
+"&$	c #B02018",
+"*$	c #B41C16",
+"=$	c #B81C16",
+"-$	c #BC4926",
+";$	c #C17234",
+">$	c #C8914A",
+",$	c #D0B060",
+"'$	c #C8A868",
+")$	c #BC986C",
+"!$	c #B89468",
+"~$	c #B49060",
+"{$	c #AC8756",
+"]$	c #A87954",
+"^$	c #8E6848",
+"/$	c #745C38",
+"($	c #5C513C",
+"_$	c #484946",
+":$	c #302A18",
+"<$	c #684C28",
+"[$	c #605420",
+"}$	c #605428",
+"|$	c #807220",
+"1$	c #E8B808",
+"2$	c #C4740C",
+"3$	c #A03010",
+"4$	c #A42810",
+"5$	c #A82010",
+"6$	c #A92208",
+"7$	c #AA2400",
+"8$	c #C16E28",
+"9$	c #D8B850",
+"0$	c #D0A860",
+"a$	c #B09058",
+"b$	c #B07E58",
+"c$	c #404420",
+"d$	c #545848",
+"e$	c #808284",
+"f$	c #5C564E",
+"g$	c #282114",
+"h$	c #181810",
+"i$	c #38361E",
+"j$	c #58542C",
+"k$	c #604C2E",
+"l$	c #684430",
+"m$	c #603F2C",
+"n$	c #583A28",
+"o$	c #503A20",
+"p$	c #483A18",
+"q$	c #4C3E1C",
+"r$	c #685A20",
+"s$	c #988724",
+"t$	c #B09C28",
+"u$	c #B8801A",
+"v$	c #C0640C",
+"w$	c #AE460C",
+"x$	c #9C280C",
+"y$	c #9E240C",
+"z$	c #A0200C",
+"A$	c #A81810",
+"B$	c #B01014",
+"C$	c #A02108",
+"D$	c #A12204",
+"E$	c #B14816",
+"F$	c #C2873C",
+"G$	c #C4A050",
+"H$	c #BE945C",
+"I$	c #B48C60",
+"J$	c #AC8C54",
+"K$	c #AC8354",
+"L$	c #AC7954",
+"M$	c #936947",
+"N$	c #7E5E3E",
+"O$	c #4F4027",
+"P$	c #202210",
+"Q$	c #2A2C24",
+"R$	c #847664",
+"S$	c #504228",
+"T$	c #303020",
+"U$	c #404224",
+"V$	c #584C2C",
+"W$	c #503A28",
+"X$	c #382810",
+"Y$	c #403010",
+"Z$	c #706018",
+"`$	c #C0A830",
+" %	c #AC5C20",
+".%	c #981010",
+"+%	c #98180C",
+"@%	c #982008",
+"#%	c #A0180C",
+"$%	c #A81010",
+"%%	c #B56618",
+"&%	c #BC9848",
+"*%	c #4E4C3E",
+"=%	c #504C30",
+"-%	c #5E4F34",
+";%	c #6C5238",
+">%	c #56462E",
+",%	c #403A24",
+"'%	c #3C321E",
+")%	c #3C2D1C",
+"!%	c #402C20",
+"~%	c #442C20",
+"{%	c #483020",
+"]%	c #806A18",
+"^%	c #AE8018",
+"/%	c #A45C20",
+"(%	c #9A3A18",
+"_%	c #901810",
+":%	c #94180E",
+"<%	c #98180E",
+"[%	c #981810",
+"}%	c #9C180E",
+"|%	c #9C180C",
+"1%	c #9C1D08",
+"2%	c #AB440E",
+"3%	c #B0792C",
+"4%	c #AC8C40",
+"5%	c #AE8A4C",
+"6%	c #A47E54",
+"7%	c #8F6E47",
+"8%	c #74624A",
+"9%	c #6C5C40",
+"0%	c #6C4A38",
+"a%	c #201810",
+"b%	c #101000",
+"c%	c #282010",
+"d%	c #483028",
+"e%	c #907418",
+"f%	c #AC6408",
+"g%	c #881010",
+"h%	c #881810",
+"i%	c #882010",
+"j%	c #90200C",
+"k%	c #A55A10",
+"l%	c #B07E60",
+"m%	c #A07E58",
+"n%	c #988850",
+"o%	c #76683E",
+"p%	c #323732",
+"q%	c #646E64",
+"r%	c #6C6052",
+"s%	c #745240",
+"t%	c #704E38",
+"u%	c #6C4A30",
+"v%	c #644228",
+"w%	c #5C3A20",
+"x%	c #4A2D1C",
+"y%	c #382018",
+"z%	c #604828",
+"A%	c #786028",
+"B%	c #9C8B14",
+"C%	c #C0B600",
+"D%	c #B28910",
+"E%	c #A86414",
+"F%	c #AC6C08",
+"G%	c #B06808",
+"H%	c #B46408",
+"I%	c #A23A0C",
+"J%	c #901010",
+"K%	c #8C1410",
+"L%	c #901410",
+"M%	c #A2430C",
+"N%	c #B46E08",
+"O%	c #B47206",
+"P%	c #B47604",
+"Q%	c #B87702",
+"R%	c #BD7800",
+"S%	c #AE8410",
+"T%	c #A68E30",
+"U%	c #AA804C",
+"V%	c #A47954",
+"W%	c #7D5D3F",
+"X%	c #5A3C2E",
+"Y%	c #4D3E37",
+"Z%	c #6C6464",
+"`%	c #745238",
+" &	c #A87440",
+".&	c #A86C40",
+"+&	c #A86440",
+"@&	c #6C3A28",
+"#&	c #301010",
+"$&	c #706020",
+"%&	c #A8A210",
+"&&	c #B0B400",
+"*&	c #B8AE18",
+"=&	c #C8B018",
+"-&	c #AC7608",
+";&	c #D0CC00",
+">&	c #B8AE10",
+",&	c #A48238",
+"'&	c #845240",
+")&	c #603030",
+"!&	c #301818",
+"~&	c #363232",
+"{&	c #4A3528",
+"]&	c #8E5F40",
+"^&	c #A86C48",
+"/&	c #8E573C",
+"(&	c #744230",
+"_&	c #6C462C",
+":&	c #665120",
+"<&	c #685818",
+"[&	c #6C6110",
+"}&	c #706A08",
+"|&	c #786718",
+"1&	c #806428",
+"2&	c #867216",
+"3&	c #8C8004",
+"4&	c #A69B02",
+"5&	c #9E6304",
+"6&	c #7C1008",
+"7&	c #7C100E",
+"8&	c #7C1014",
+"9&	c #7C140E",
+"0&	c #7C1814",
+"a&	c #801414",
+"b&	c #841014",
+"c&	c #8A1012",
+"d&	c #861412",
+"e&	c #945416",
+"f&	c #AC9018",
+"g&	c #B0941C",
+"h&	c #B49820",
+"i&	c #A88928",
+"j&	c #9C7A30",
+"k&	c #987A30",
+"l&	c #947A30",
+"m&	c #846B34",
+"n&	c #795D3B",
+"o&	c #573B2B",
+"p&	c #180C0C",
+"q&	c #B07450",
+"r&	c #B87450",
+"s&	c #A06C40",
+"t&	c #5C4220",
+"u&	c #402020",
+"v&	c #443414",
+"w&	c #484808",
+"x&	c #7C7E04",
+"y&	c #906200",
+"z&	c #701000",
+"A&	c #70100C",
+"B&	c #701018",
+"C&	c #7C3224",
+"D&	c #645430",
+"E&	c #4A4626",
+"F&	c #685B4C",
+"G&	c #645234",
+"H&	c #8A6842",
+"I&	c #B07E50",
+"J&	c #A47548",
+"K&	c #986C40",
+"L&	c #64462C",
+"M&	c #302018",
+"N&	c #3A3312",
+"O&	c #44460C",
+"P&	c #76740E",
+"Q&	c #88590C",
+"R&	c #681008",
+"S&	c #681410",
+"T&	c #681818",
+"U&	c #681416",
+"V&	c #681014",
+"W&	c #68100E",
+"X&	c #6C1010",
+"Y&	c #6C1016",
+"Z&	c #6E1414",
+"`&	c #741814",
+" *	c #721416",
+".*	c #782E2A",
+"+*	c #804C3C",
+"@*	c #82583A",
+"#*	c #846438",
+"$*	c #86603C",
+"%*	c #6A5038",
+"&*	c #433C27",
+"**	c #3A341E",
+"=*	c #3F3C31",
+"-*	c #645C34",
+";*	c #282018",
+">*	c #303210",
+",*	c #404410",
+"'*	c #706A18",
+")*	c #805018",
+"!*	c #601010",
+"~*	c #601814",
+"{*	c #602018",
+"]*	c #742A30",
+"^*	c #784448",
+"/*	c #74543C",
+"(*	c #704C40",
+"_*	c #3C3228",
+":*	c #54544C",
+"<*	c #3A3E38",
+"[*	c #283024",
+"}*	c #46422A",
+"|*	c #866440",
+"1*	c #8A5F44",
+"2*	c #5A3E30",
+"3*	c #483228",
+"4*	c #30251C",
+"5*	c #28290C",
+"6*	c #383A08",
+"7*	c #665E10",
+"8*	c #948218",
+"9*	c #764914",
+"0*	c #581010",
+"a*	c #541214",
+"b*	c #501418",
+"c*	c #5C1012",
+"d*	c #601014",
+"e*	c #581412",
+"f*	c #581814",
+"g*	c #5C1414",
+"h*	c #662A28",
+"i*	c #6C443C",
+"j*	c #664C32",
+"k*	c #584F24",
+"l*	c #504A20",
+"m*	c #6A5B2C",
+"n*	c #846C38",
+"o*	c #926D40",
+"p*	c #A06E48",
+"q*	c #946A48",
+"r*	c #886648",
+"s*	c #765D3C",
+"t*	c #695E45",
+"u*	c #6E685A",
+"v*	c #57544D",
+"w*	c #181818",
+"x*	c #303030",
+"y*	c #282820",
+"z*	c #845C40",
+"A*	c #101010",
+"B*	c #202008",
+"C*	c #303000",
+"D*	c #5C5208",
+"E*	c #887410",
+"F*	c #6C4210",
+"G*	c #501010",
+"H*	c #480C14",
+"I*	c #400818",
+"J*	c #582A20",
+"K*	c #584428",
+"L*	c #504420",
+"M*	c #403A18",
+"N*	c #645228",
+"O*	c #987440",
+"P*	c #A87E48",
+"Q*	c #B88850",
+"R*	c #B08850",
+"S*	c #7E683E",
+"T*	c #1C1818",
+"U*	c #383030",
+"V*	c #3C2C24",
+"W*	c #402818",
+"X*	c #563924",
+"Y*	c #8A643C",
+"Z*	c #966D40",
+"`*	c #845C38",
+" =	c #684730",
+".=	c #4C3228",
+"+=	c #3E2D14",
+"@=	c #302800",
+"#=	c #564C06",
+"$=	c #7C700C",
+"%=	c #60400A",
+"&=	c #441008",
+"*=	c #460E0E",
+"==	c #4C0E12",
+"-=	c #4A100C",
+";=	c #4A1008",
+">=	c #501008",
+",=	c #50100C",
+"'=	c #501410",
+")=	c #501810",
+"!=	c #4C2914",
+"~=	c #4C3A1C",
+"{=	c #664B28",
+"]=	c #966D3C",
+"^=	c #B07E48",
+"/=	c #B4834C",
+"(=	c #B8884C",
+"_=	c #B88848",
+":=	c #9B6E47",
+"<=	c #865E3E",
+"[=	c #78624A",
+"}=	c #503028",
+"|=	c #603020",
+"1=	c #482818",
+"2=	c #6C5428",
+"3=	c #A87E40",
+"4=	c #302000",
+"5=	c #504604",
+"6=	c #706C08",
+"7=	c #543E04",
+"8=	c #381000",
+"9=	c #441000",
+"0=	c #501000",
+"a=	c #502010",
+"b=	c #402808",
+"c=	c #8C5C38",
+"d=	c #C88850",
+"e=	c #C08850",
+"f=	c #B88840",
+"g=	c #B87E48",
+"h=	c #1C1814",
+"i=	c #383028",
+"j=	c #483528",
+"k=	c #503624",
+"l=	c #62472C",
+"m=	c #926840",
+"n=	c #A87448",
+"o=	c #A07148",
+"p=	c #986E48",
+"q=	c #604B2A",
+"r=	c #28280C",
+"s=	c #464408",
+"t=	c #646004",
+"u=	c #503608",
+"v=	c #3C0C0C",
+"w=	c #3E0E0E",
+"x=	c #401010",
+"y=	c #420C0C",
+"z=	c #480C0C",
+"A=	c #48120E",
+"B=	c #481810",
+"C=	c #441814",
+"D=	c #401818",
+"E=	c #48251C",
+"F=	c #503220",
+"G=	c #664728",
+"H=	c #806034",
+"I=	c #A27644",
+"J=	c #BC8850",
+"K=	c #B8834C",
+"L=	c #B47E4C",
+"M=	c #B07E4C",
+"N=	c #976E43",
+"O=	c #715D49",
+"P=	c #645C54",
+"Q=	c #54504C",
+"R=	c #403A28",
+"S=	c #584430",
+"T=	c #583A30",
+"U=	c #7C5240",
+"V=	c #3C420C",
+"W=	c #585400",
+"X=	c #4C2E0C",
+"Y=	c #380C14",
+"Z=	c #401414",
+"`=	c #402010",
+" -	c #403228",
+".-	c #8C6648",
+"+-	c #C88860",
+"@-	c #C09058",
+"#-	c #B89850",
+"$-	c #B89050",
+"%-	c #B87E50",
+"&-	c #A88848",
+"*-	c #181814",
+"=-	c #303028",
+"--	c #58442C",
+";-	c #604330",
+">-	c #604230",
+",-	c #7C533C",
+"'-	c #986448",
+")-	c #8A6540",
+"!-	c #7C6638",
+"~-	c #524B2A",
+"{-	c #28301C",
+"]-	c #46421E",
+"^-	c #645420",
+"/-	c #4E341E",
+"(-	c #38141C",
+"_-	c #301616",
+":-	c #341A1A",
+"<-	c #401C24",
+"[-	c #623230",
+"}-	c #84483C",
+"|-	c #845238",
+"1-	c #845C34",
+"2-	c #7C5C36",
+"3-	c #806140",
+"4-	c #AA7750",
+"5-	c #C88858",
+"6-	c #C08C54",
+"7-	c #B88C50",
+"8-	c #B48850",
+"9-	c #B48350",
+"0-	c #B47950",
+"a-	c #AC7E4C",
+"b-	c #A48844",
+"c-	c #A08840",
+"d-	c #A47E48",
+"e-	c #8A6344",
+"f-	c #7A644E",
+"g-	c #887664",
+"h-	c #50433E",
+"i-	c #181018",
+"j-	c #6C4C30",
+"k-	c #403A20",
+"l-	c #504230",
+"m-	c #503A30",
+"n-	c #302820",
+"o-	c #845C48",
+"p-	c #C8905C",
+"q-	c #C89858",
+"r-	c #C09854",
+"s-	c #988840",
+"t-	c #A07E48",
+"u-	c #A07450",
+"v-	c #906C48",
+"w-	c #5C4238",
+"x-	c #302030",
+"y-	c #483A2C",
+"z-	c #5C4428",
+"A-	c #604428",
+"B-	c #684C2C",
+"C-	c #765434",
+"D-	c #745034",
+"E-	c #624730",
+"F-	c #604C30",
+"G-	c #443A26",
+"H-	c #28281C",
+"I-	c #28241A",
+"J-	c #4A3A24",
+"K-	c #785C3A",
+"L-	c #846444",
+"M-	c #A67A50",
+"N-	c #C49056",
+"O-	c #C09050",
+"P-	c #C08858",
+"Q-	c #C08854",
+"R-	c #BC8350",
+"S-	c #B47E50",
+"T-	c #AC7948",
+"U-	c #A87948",
+"V-	c #8F6E43",
+"W-	c #79613D",
+"X-	c #74643C",
+"Y-	c #76664A",
+"Z-	c #786858",
+"`-	c #483C38",
+" ;	c #383A1C",
+".;	c #C09054",
+"+;	c #C07E50",
+"@;	c #524E2A",
+"#;	c #5C604C",
+"$;	c #201418",
+"%;	c #402830",
+"&;	c #503630",
+"*;	c #905840",
+"=;	c #985C40",
+"-;	c #865C38",
+";;	c #745C30",
+">;	c #6C572E",
+",;	c #64522C",
+"';	c #644A32",
+");	c #644238",
+"!;	c #966748",
+"~;	c #C88C58",
+"{;	c #C89258",
+"];	c #C89058",
+"^;	c #C88854",
+"/;	c #BC7950",
+"(;	c #B07948",
+"_;	c #A47940",
+":;	c #A07440",
+"<;	c #8E633C",
+"[;	c #7C5238",
+"};	c #7D583B",
+"|;	c #54422A",
+"1;	c #292715",
+"2;	c #2E3026",
+"3;	c #201018",
+"4;	c #402030",
+"5;	c #503230",
+"6;	c #A06C48",
+"7;	c #B87A58",
+"8;	c #D89060",
+"9;	c #D0945C",
+"0;	c #C89054",
+"a;	c #B07448",
+"b;	c #745230",
+"c;	c #1A1D14",
+"d;	c #343A28",
+"e;	c #463F28",
+"f;	c #825C3C",
+"g;	c #946C44",
+"h;	c #986C48",
+"i;	c #A07048",
+"j;	c #A87D54",
+"k;	c #A88660",
+"l;	c #B08458",
+"m;	c #B88250",
+"n;	c #C08D54",
+"o;	c #C8945A",
+"p;	c #C08C50",
+"q;	c #A47144",
+"r;	c #764F34",
+"s;	c #543A28",
+"t;	c #3E2C1C",
+"u;	c #281E10",
+"v;	c #292113",
+"w;	c #15120B",
+"x;	c #142A10",
+"y;	c #285420",
+"z;	c #3C4C20",
+"A;	c #A06C50",
+"B;	c #B08E60",
+"C;	c #A88E58",
+"D;	c #B0864C",
+"E;	c #986E40",
+"F;	c #4C2A28",
+"G;	c #0A1508",
+"H;	c #323218",
+"I;	c #583F24",
+"J;	c #82583C",
+"K;	c #B48A5C",
+"L;	c #8E714C",
+"M;	c #8E693E",
+"N;	c #C08C56",
+"O;	c #AC7E50",
+"P;	c #86653C",
+"Q;	c #644C28",
+"R;	c #4C3220",
+"S;	c #2E1D14",
+"T;	c #583A20",
+"U;	c #B88658",
+"V;	c #745440",
+"W;	c #201010",
+"X;	c #180808",
+"Y;	c #200010",
+"Z;	c #140C08",
+"`;	c #38291C",
+" >	c #483A28",
+".>	c #5C472C",
+"+>	c #7C5844",
+"@>	c #4E3624",
+"#>	c #926E40",
+"$>	c #C48350",
+"%>	c #B08848",
+"&>	c #967238",
+"*>	c #7C5C28",
+"=>	c #744F2C",
+"->	c #6C4230",
+";>	c #462920",
+">>	c #181408",
+",>	c #1C0C0C",
+"'>	c #200810",
+")>	c #745C28",
+"!>	c #281010",
+"~>	c #403224",
+"{>	c #725434",
+"]>	c #7C6444",
+"^>	c #342418",
+"/>	c #684B30",
+"(>	c #A07648",
+"_>	c #B07F4C",
+":>	c #A67648",
+"<>	c #785C38",
+"[>	c #4E3E24",
+"}>	c #2C2014",
+"|>	c #241810",
+"1>	c #201410",
+"2>	c #1C1410",
+"3>	c #302218",
+"4>	c #744C38",
+"5>	c #746C40",
+"6>	c #282020",
+"7>	c #102010",
+"8>	c #242218",
+"9>	c #484430",
+"0>	c #624C34",
+"a>	c #3C2818",
+"b>	c #4A3520",
+"c>	c #544228",
+"d>	c #6C4F30",
+"e>	c #664B2C",
+"f>	c #483A20",
+"g>	c #382D1C",
+"h>	c #2C2018",
+"i>	c #281C10",
+"j>	c #20140C",
+"k>	c #201C14",
+"l>	c #141410",
+"m>	c #302810",
+"n>	c #301810",
+"o>	c #201808",
+"p>	c #343724",
+"q>	c #664C34",
+"r>	c #7C4C38",
+"s>	c #8A583C",
+"t>	c #886048",
+"u>	c #482820",
+"v>	c #442C1C",
+"w>	c #403018",
+"x>	c #382C14",
+"y>	c #40241C",
+"z>	c #382414",
+"A>	c #38201C",
+"B>	c #382020",
+"C>	c #4A3A36",
+"D>	c #322E26",
+"E>	c #14100C",
+"F>	c #845438",
+"G>	c #8C6448",
+"H>	c #402828",
+"I>	c #645C5C",
+"J>	c #343324",
+"K>	c #705838",
+"L>	c #846D48",
+"M>	c #483520",
+"N>	c #44301C",
+"O>	c #40311C",
+"P>	c #403220",
+"Q>	c #402D20",
+"R>	c #402C1C",
+"S>	c #3C2C1C",
+"T>	c #382820",
+"U>	c #382D24",
+"V>	c #383228",
+"W>	c #2C2520",
+"X>	c #322E2E",
+"Y>	c #5C5C38",
+"Z>	c #7C7648",
+"`>	c #383020",
+" ,	c #303A28",
+".,	c #3A3F28",
+"+,	c #765C40",
+"@,	c #905C48",
+"#,	c #9C684C",
+"$,	c #807648",
+"%,	c #484420",
+"&,	c #4C3A24",
+"*,	c #4C3028",
+"=,	c #443A24",
+"-,	c #403F20",
+";,	c #3C3120",
+">,	c #4E423A",
+",,	c #3E3A32",
+"',	c #181D14",
+"),	c #5C4C38",
+"!,	c #847648",
+"~,	c #383220",
+"{,	c #5C5454",
+"],	c #3A3728",
+"^,	c #8C6D4C",
+"/,	c #503A24",
+"(,	c #4E4742",
+"_,	c #504C4C",
+":,	c #6C5C38",
+"<,	c #946450",
+"[,	c #645C64",
+"},	c #58472C",
+"|,	c #AC8658",
+"1,	c #8C714E",
+"2,	c #58422C",
+"3,	c #58432A",
+"4,	c #4C3B24",
+"5,	c #443624",
+"6,	c #342924",
+"7,	c #322E32",
+"8,	c #443220",
+"9,	c #A08658",
+"0,	c #847E4C",
+"a,	c #221910",
+"b,	c #60543C",
+"c,	c #7C7658",
+"d,	c #5E6142",
+"e,	c #404C2C",
+"f,	c #5A5944",
+"g,	c #74665C",
+"h,	c #463B36",
+"i,	c #181010",
+"j,	c #181914",
+"k,	c #384438",
+"l,	c #5C665C",
+"                                            . + @ # $ % & * = - ;                                                               ",
+"                                            . + @ # $ % & * = - ;                                                               ",
+"                                > . , ' ) ! ~ { ] ^ / ( _ : < [ }               | 1 2 3 4                                       ",
+"                                . + 5 6 7 8 9 % 0 a b c c c d e f               1 g h i 3                                       ",
+"                j k l   m n o ' p q r s t u v w x y b z z z A B C       4 3 D E F G H I J K L 3 4                               ",
+"                k M N O P * Q 6 R S T b b b T S T b b b b b U V W       3 i X Y Z `  ...+.@.#.i 3                               ",
+"    | 1 $.%.&.*.=.-.;.>.,.'.).s !.~.{.].^.y /.~.(._.:.y y y <.[.}.      |.1.2.+.3.4.5. .6.7.8.9.0.a.b.. >                       ",
+"    1 g c.d.e.f.g.a ].S ~.h._.b _.h.i.j.k.a l.h.h.h.l.a a a m.n.o.      p.q.r.s.s.s.4.` t.u.v.w.x.# @ + .                       ",
+"    y.z.A.B.C.D.E.b F.T G._.H.b H._./.].I.J.E.l.l.l.E.J.K.m.L.M.N.O.P.  Q.R.S.T.T.T.U.4.V.W.X.Y.Z.`. +@ .+' , . >               ",
+"    ++@+#+S S S $+c z b b b b b b b b b %+&+J.a a a J.&+*+n.M.` =+-+O.  ;+>+,+......T.s.s.s.'+)+!+~+`.# {+6 5 + .               ",
+"    ]+^+/+(+I.T _+:+<+[+}+y y y y y |+%+1+&+2+3+3+3+4+*+5+6+7+8+9+0+a+b+c+d+e+..f+g+h+s.i+'+j+)+k+l+m+n+o+p+q+r+s+a.            ",
+"    k M t+u+v+b %+&+w+x+y+a a a a a J.&+&+&+z+V V V [.n.6+A+B+C+D+E+F+G+H+s.T...g+u.W.s.'+)+)+)+I+J+J+J+K+L+M+N+O+# a.          ",
+"    j k P+Q+R+%+S+J.T+y+T+J.U+(+(+(+V+W+X+Y+Z+`+ @.@+@@@#@$@%@&@*@=@-@;@>@4.U.T.,@'@)@W.!@~@{@I+]@K+K+K+^@/@(@U _@:@<@a.[@3 4   ",
+"        }@|@1@&+J.a a a J.&+Y+2@2@2@D.3@D.2@2@2@4@5@6@G+7@8@9@0@0@0@a@b@c@` 4.s.'+)+'@u.d@e@f@J+K+L+L+L+/@~+g@h@i@j@:@# k@i 3   ",
+"        l@m@n@Y+o@(+(+(+o@Y+p@2@2@2@q@r@s@t@u@v@w@x@y@z@A@B@C@D@E@F@G@H@I@J@K@L@M@)+N@d@O@f@P@Q@R@L+L+L+S@g@T@h@U@V@W@X@Y@Z@`@ #",
+"        .#+#@#2@2@2@2@2@2@2@2@2@2@2@t@######$#-+%#A+&#*#=#D@-#;#-#D@D@D@F@0@>#,#'#)+~@e@f@J+Q@)#!#L+L+L+~#h@h@h@{#]#]#]#^#/#(#_#",
+"        :#.#<#2@[#}#}#}#[#2@|#t@|#2@1#2#3#$#4#5#6#7#8#9#0#-#a#b#c#d#e#-#f#D@g#h#i#j#k#~@I+l#m#!#n#o#p#~#q#r#s#{#U@i@t#u#v#w#x#y#",
+"            z#2@}#A#A#A#}#2@t@##t@2@}#A#B#-+5#,#C#D#b#;#;#;#b#D#E#F#G#;#;#;#d#H#I#J#j#)+K#L#M#L+o#N#/@h@r#O#P#]#i@Q#R#S#T#O U#i ",
+"k k j       V#}#W#2#2#2#X#Y#X#2#X#Y#Z#B#`# $.$+$@$#$$$b#b#b#$$#$%$&$*$b#b#b#=$G#-$;$>$,$'$l#)$/@!$o#~${#s#r#{$u#]$R#^$/$($N _$3 ",
+"M M k       :$A#2#######<$[$}$A#}$[$|$-+ $1$2$3$4$5$#$D#D#D##$5$5$5$#$D#D#D##$5$6$7$8$9$0$J+l+~+/@L+a$]#{#h@b$S#S#S#/$c$d$M k   ",
+"e$e$f$z#g$h$i$j$k$l$m$n$o$p$q$1@r$|$s$t$u$v$w$x$y$z$A$B$B$B$A$z$z$z$A$B$B$B$A$z$C$D$E$8$F$G$H$g@I$a$J$]#K$b$L$S#M$N$O$P$Q$k j   ",
+"i i R$2@S$T$U$- V$u+W$N+P |@X$Y$Z$-+t$`$ %.%+%@%@%@%#%$%$%$%#%@%@%@%#%$%$%$%#%@%@%@%D$7$%%`$&%h@{#]#]#]#u#S#S#S#N$6 '           ",
+"3 3 *%=%-%;%>%,%'%z#)%N+!%& ~%{%]%%#^%/%(%_%:%+%+%+%<%[%[%[%<%+%+%+%<%[%}%#%|%+%+%+%1%D$2%%%3%4%5%{#U@i@6%V@7%N$8%5 ,           ",
+"    ! 8 9%S#0%% a%b%c%N+d%w.w.w.e%A+f%g%h%i%_%.%.%.%_%i%i%i%_%.%.%.%_%i%j%@%+%.%.%.%+%@%D$7$k%-+4%h@l%Q#m%n%o%6 5 + .           ",
+"    p%q%r%s%t%u%v%w%x%y%& d%z%A%B%C%D%/%E%F%G%H%I%J%K%h%h%h%K%J%L%_%_%_%:%+%:%_%M%N%O%P%Q%R%S%-+T%4%U%R#V%V@W%X%Y%. >           ",
+"    3 i Z%e `% &.&+&@&#&y%N+$&-+%&&&*&`$=&A+A+A+f%g%g%g%g%g%g%g%h%i%_%.%.%.%_%i%-&;&;&;&;&;&>&-+-+-+,&S#S#S#'&)&!&              ",
+"    4 3 ~&f {&`%]&^&/&(&_&#+:&<&[&}&|&1&2&3&4&C%5&6&7&8&8&8&7&6&9&0&a&b&c&J%d&0&e&f&g&h&h&h&i&j&k&l&m&/$n&N$o&!&p&              ",
+"            f e s%S#q&r&s&h.t&|@|@|@y%u&v&w&x&&&y&z&A&B&B&B&A&z&A&B&B&B&8&g%8&B&C&3@i.S S S S S T b D&c$E&6 '                   ",
+"            ~&Z%F&G&H&I&J&K&L&M&M&M&M&M&N&O&P&%&Q&R&S&T&U&V&W&R&X&B&Y&V&Z&`& *B&.*+*@*#*#*#*#*#*$*y %*;+&***=*.#:#              ",
+"            3 i y#_#-*]#u#S#0%% % % ;*O >*,*'*-+)*!*~*{*~*!*!*!*V&B&V&!*~*{*T&B&]*^*/*&+&+&+&+&+J.a (*Y _*O :*+#.#              ",
+"            4 3 <*[*}*D&|*S#1*0%2*3*4*h$5*6*7*8*9*0*a*b*a*0*0*0*c*d*c*0*e*f*g*d*h*i*j*}$k*l*m*n*o*p*q*r*s*D&t*u*v*. >           ",
+"                w*x*y*O T#S#S#S#z*u+W A*B*C*D*E*F*G*H*I*H*G*G*G*G*G*G*G*G*G*G*G*J*u+K*L*M*@+N*O*P*Q*Q*Q*R*]#S*6 5 + .           ",
+"                T*U*V*W*X*u%Y*P*Z*`* =.=+=@=#=$=%=&=*=H*==G*-=&=;=>=,=G*G*G*'=)=!=p$~=o${=W+]=^=/=Q*(=_=/=I&:=<=[=5 v*.#:#      ",
+"                f e }=|=1=|@2=5@3= &S a w%4=5=6=7=8=&=G*G*G*&=8=9=0=>=G*G*G*)=a=b=C*Y$* c=d=d=d=e=Q*_=f=g=r&r&r&<=6 u*+#.#      ",
+"                h=i=j=n$k=Q+l=J.m=n=o=p=q=r=s=t=u=v=w=x=x=x=w=v=y=z=A=B=C=D=E=F=G=W+H=#*I=e=e=e=J=Q*K=g=L=I&M=^=N=N$O=P=Q=.#:#  ",
+"                h$T$R=@.S=u+T=w.U=S#u#]#-*_#V=W=X=I*Y=#&#&#&Y=I*I*I*Z=`=y%%  -@..-+-@-#-$-Q*Q*Q*Q*Q*%-r&I&]#&-5@P*S#`%N+P=+#.#  ",
+"                *-=-R=e.--u+;->-,-'-)-!-~-{-]-^-/-(-_-n n n :-<-[-}-|-1-2-/$3-.-4-5-6-$-7-Q*8-R*9-%-0-q&a-&-b-c-d-S#e-;%f-g-h-i-",
+"                w*x*R=L*K*u+2#2@(+a j-L*k-T$l-V m-% ;*O O O n-e o-+-p-q-r-#-@-+-5-d=e=Q*Q*Q*R*]#I&r&q&S#P*5@c-s-t-S#u-j@v-b w-x-",
+"                T*U*y-K*z-A-B-2@C-(+D-j- =w E-F-G-H-I-;*J-[#K-L-M-p-p-p-N-O-6-P-Q-e=e=e=R-%-S-I&M=^=T-n=U-P*d-t-V-N$W-X-Y-Z-`-i-",
+"                f e m-u+A-f.<$2@2@2@(+a k.j.g.L* ;_#H-% v+Q*.;q-q-q-p-+-5-d=e=Q*Q*Q*e=d=+;r&r&r&^=5@3= &n=S#S#S#N$6 @;- #;M k   ",
+"                $;%;&;u+A-f.<$2@p@Y+U+a *;=;-;;;>;,;';);!;~;{;q-q-q-];5-^;d=e=Q*Q*Q*R-+;/;r&r&r&(;3=_;:;<;[;};N$|;' 1;; 2;k j   ",
+"                3;4;5;u+A-f.<$2@Y+&+J.a ].S K&O*:; &6;/#7;8;9;q-q-q-0;d=d=d=e=Q*Q*Q*%-r&r&r&r&r&a; &:;O*b;* Q 6 '               ",
+"                c;d;e;K*z-A-B-2@o@J.f;y F.$+g;h;i;n=j;k;l;m;n;q-o;p-N-O-p;e=J=Q*Q*Q*9-I&I&I&M=^=q;S r;s;t;u;v;' w;              ",
+"                x;y;z;L*K*u+2#2@(+a y b z c v-/#A;S#B;L#C;O*D;q-p-+-@-#-$-Q*Q*Q*Q*Q*R*]#]#]#&-5@E;a F;                          ",
+"                G;x;H;o$I;A-B-2@C-(+J;y F.$+g;h;i;n=K;l#L;>.M;.;N;P-6-O-p;e=J=Q*(=_=/=I&O;u#P;Q;I;R;S;                          ",
+"                    n * T;f.<$2@2@2@(+a ].S K&O*:; &U;J+V;W;j-Q*Q*Q*e=d=d=d=e=Q*_=f=g=r&q&S#w W;}@      X;Y;                    ",
+"                    Z;n `; >.>2@p@Y+U+a ].S K&O*:; &U;J++>!&@>[##>Q*e=d=$>+;K=%>&>*>=>->->->;>W;m ++>>}@,>'>                    ",
+"                        w*x*l-2@Y+&+J.a ].S K&O*:; &U;J+o-u&M&O [#Q*e=d=+;r&^=5@)>Y$|@W;!>#&!>W;a%O a%W;W;W;                    ",
+"                          w*~>2#{>J.f;y F.$+g;h;i;n=K;l#]>P ^>M&/>(>_>e=:>F.<>D&[>P }>a%|>n |>a%a%a%1>W;2>h$                    ",
+"                            3>u+4>a y b z c v-/#A;S#B;L#5>@+P u&w b (>Q*.@A#R=> 6>% ;*O O O O O a%W;W;W;h$7>                    ",
+"                            8>9>0>(+J;y F.$+g;h;i;n=K;l#]>P a>W*b>c>d>`*e>f>g>;*h>M&}>c%c%c%i>n n n j>}@k>y*l>                  ",
+"                            ! 8 =%2@(+a ].S K&O*:; &U;J+o-u&W*Y$m>O P * W*|@|@|@|@|@|@|@|@|@n>#&n>|@o>  ;*e f                   ",
+"                              ! p>=%q>r>s>S K&O*:; &U;J+t>u>v>w>x>m>a>u>y>y%z>X$X$X$z>y%y%y%A>B>C>m@D>  E>f                     ",
+"                                ! 8 @.##F>S K&O*:; &U;J+G>* {%N+w>Y$W*u&u&u&W*Y$Y$Y$W*u&u&u&H>e I>+#.#                          ",
+"                                  ! J>@.K>$+g;h;i;n=K;l#L>f>M>{%N>w>O>P>Q>& R>w>w>w>S>T>U>V>W>f X>.#:#                          ",
+"                                    ! 8 Y>c v-/#A;S#B;L#Z>c$f>* {%N+k-c$k-N+N+N+N+N+`>T$ ,8 !                                   ",
+"                                      ! .,Y>+,@,#,S#B;L#$,%,&,}=*,d%=,c$-,k-;,T>>,P=,,h$',!                                     ",
+"                                        ! 8 ),a '-S#B;L#!,L*W$w.w.w. >c$c$c$~,% {,+#.#                                          ",
+"                                          ! ],),v#n=K;l#^,n$s;W$W$W$/,o$ >O+(,{,_,.#:#                                          ",
+"                                            ! 8 :, &U;J+<,)&n$L*L*L*T;|=w.q.[,+#.#                                              ",
+"                                              ! },K&|,l#1,2,3,K*4,P>5, >6,p.7,.#:#                                              ",
+"                                                8,b 9,L#0,- V$u+3*% 9 8 !                                                       ",
+"                                                a,8,b,c,d,e,f,g,h,i,j,!                                                         ",
+"                                                    a.# k,8 l,+#.#                                                              "};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gtk/install_banner.xpm	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,1094 @@
+/* XPM */
+static char * install_banner_xpm[] = {
+"100 275 816 2",
+"  	c None",
+". 	c #8B101D",
+"+ 	c #8B101E",
+"@ 	c #8A101E",
+"# 	c #8A101D",
+"$ 	c #8A101F",
+"% 	c #8A111F",
+"& 	c #8B101F",
+"* 	c #8A1020",
+"= 	c #89101F",
+"- 	c #891020",
+"; 	c #891021",
+"> 	c #891022",
+", 	c #881022",
+"' 	c #881122",
+") 	c #881023",
+"! 	c #871023",
+"~ 	c #871024",
+"{ 	c #871124",
+"] 	c #861024",
+"^ 	c #861025",
+"/ 	c #871025",
+"( 	c #861026",
+"_ 	c #861126",
+": 	c #861027",
+"< 	c #861028",
+"[ 	c #861029",
+"} 	c #851029",
+"| 	c #851129",
+"1 	c #85102A",
+"2 	c #85112A",
+"3 	c #8A1021",
+"4 	c #881123",
+"5 	c #881124",
+"6 	c #861125",
+"7 	c #861128",
+"8 	c #861129",
+"9 	c #85102B",
+"0 	c #84102B",
+"a 	c #891121",
+"b 	c #891122",
+"c 	c #881021",
+"d 	c #871022",
+"e 	c #871125",
+"f 	c #861127",
+"g 	c #84112A",
+"h 	c #84102A",
+"i 	c #84112B",
+"j 	c #84102C",
+"k 	c #8A1120",
+"l 	c #891120",
+"m 	c #881024",
+"n 	c #871026",
+"o 	c #841129",
+"p 	c #84112C",
+"q 	c #84102D",
+"r 	c #881121",
+"s 	c #871123",
+"t 	c #83102C",
+"u 	c #83102D",
+"v 	c #871126",
+"w 	c #85112B",
+"x 	c #83112C",
+"y 	c #83112D",
+"z 	c #851028",
+"A 	c #83102E",
+"B 	c #82102E",
+"C 	c #82112E",
+"D 	c #83102F",
+"E 	c #82102F",
+"F 	c #83112E",
+"G 	c #82112F",
+"H 	c #821030",
+"I 	c #811030",
+"J 	c #83112F",
+"K 	c #811130",
+"L 	c #811031",
+"M 	c #83102B",
+"N 	c #821130",
+"O 	c #811131",
+"P 	c #871122",
+"Q 	c #84112D",
+"R 	c #821131",
+"S 	c #81102F",
+"T 	c #821031",
+"U 	c #801131",
+"V 	c #801031",
+"W 	c #85112C",
+"X 	c #811032",
+"Y 	c #801132",
+"Z 	c #801032",
+"` 	c #801133",
+" .	c #811132",
+"..	c #801033",
+"+.	c #801134",
+"@.	c #7F1134",
+"#.	c #7F1133",
+"$.	c #7F1033",
+"%.	c #801035",
+"&.	c #83112B",
+"*.	c #7F1132",
+"=.	c #7F1034",
+"-.	c #7F1135",
+";.	c #7F1035",
+">.	c #801034",
+",.	c #831030",
+"'.	c #7F1036",
+").	c #7F1136",
+"!.	c #841029",
+"~.	c #82102D",
+"{.	c #7F1137",
+"].	c #7E1137",
+"^.	c #7F1037",
+"/.	c #7E1037",
+"(.	c #7F1138",
+"_.	c #7F1038",
+":.	c #7E1038",
+"<.	c #7E1138",
+"[.	c #7D1138",
+"}.	c #7D1038",
+"|.	c #7D1039",
+"1.	c #7D1139",
+"2.	c #7E1139",
+"3.	c #7D113A",
+"4.	c #7F1032",
+"5.	c #81112F",
+"6.	c #7E1039",
+"7.	c #7D103A",
+"8.	c #7C113B",
+"9.	c #7C103A",
+"0.	c #7C113A",
+"a.	c #7D113B",
+"b.	c #7C113C",
+"c.	c #7D103B",
+"d.	c #85102C",
+"e.	c #7C103C",
+"f.	c #7B113B",
+"g.	c #7B113D",
+"h.	c #7C103D",
+"i.	c #7B103D",
+"j.	c #7B113E",
+"k.	c #7C103B",
+"l.	c #7B113C",
+"m.	c #7A113E",
+"n.	c #7A113F",
+"o.	c #7C113D",
+"p.	c #7B103E",
+"q.	c #811033",
+"r.	c #801135",
+"s.	c #7B113F",
+"t.	c #FEFEFE",
+"u.	c #7D113C",
+"v.	c #7C113E",
+"w.	c #7A103F",
+"x.	c #C2C2C2",
+"y.	c #7A1140",
+"z.	c #79113F",
+"A.	c #791040",
+"B.	c #791140",
+"C.	c #7B103F",
+"D.	c #791141",
+"E.	c #791142",
+"F.	c #781142",
+"G.	c #020202",
+"H.	c #7A1040",
+"I.	c #781141",
+"J.	c #781143",
+"K.	c #79103F",
+"L.	c #781144",
+"M.	c #791041",
+"N.	c #781145",
+"O.	c #781043",
+"P.	c #781146",
+"Q.	c #771145",
+"R.	c #771146",
+"S.	c #828282",
+"T.	c #761146",
+"U.	c #771147",
+"V.	c #771245",
+"W.	c #771246",
+"X.	c #761147",
+"Y.	c #761148",
+"Z.	c #761247",
+"`.	c #761149",
+" +	c #761249",
+".+	c #751149",
+"++	c #7E1036",
+"@+	c #75114A",
+"#+	c #75124A",
+"$+	c #7E1136",
+"%+	c #771148",
+"&+	c #761248",
+"*+	c #76114A",
+"=+	c #74114A",
+"-+	c #0202FE",
+";+	c #76124A",
+">+	c #75114B",
+",+	c #74114C",
+"'+	c #020282",
+")+	c #74114B",
+"!+	c #751249",
+"~+	c #74124B",
+"{+	c #74114D",
+"]+	c #73114D",
+"^+	c #75114C",
+"/+	c #74124D",
+"(+	c #74124C",
+"_+	c #73124D",
+":+	c #73114E",
+"<+	c #73124E",
+"[+	c #73124C",
+"}+	c #74114E",
+"|+	c #72114E",
+"1+	c #72124F",
+"2+	c #73114F",
+"3+	c #72124E",
+"4+	c #72114F",
+"5+	c #721250",
+"6+	c #74124E",
+"7+	c #721150",
+"8+	c #711251",
+"9+	c #711151",
+"0+	c #711150",
+"a+	c #711152",
+"b+	c #71124F",
+"c+	c #721151",
+"d+	c #711252",
+"e+	c #7A103E",
+"f+	c #711253",
+"g+	c #711153",
+"h+	c #781042",
+"i+	c #711250",
+"j+	c #701154",
+"k+	c #711154",
+"l+	c #701155",
+"m+	c #711254",
+"n+	c #701254",
+"o+	c #701255",
+"p+	c #791143",
+"q+	c #711155",
+"r+	c #6F1155",
+"s+	c #6F1255",
+"t+	c #701156",
+"u+	c #701256",
+"v+	c #6F1156",
+"w+	c #6F1256",
+"x+	c #6F1157",
+"y+	c #791042",
+"z+	c #6F1257",
+"A+	c #6E1257",
+"B+	c #6E1157",
+"C+	c #6E1158",
+"D+	c #6E1258",
+"E+	c #771144",
+"F+	c #781245",
+"G+	c #6F1158",
+"H+	c #6E1159",
+"I+	c #6E1259",
+"J+	c #6D1259",
+"K+	c #6E125A",
+"L+	c #6D115A",
+"M+	c #6D125B",
+"N+	c #6D1258",
+"O+	c #6D1158",
+"P+	c #6E115A",
+"Q+	c #6D125A",
+"R+	c #6C125B",
+"S+	c #771247",
+"T+	c #751148",
+"U+	c #6D1159",
+"V+	c #6D115B",
+"W+	c #6C115C",
+"X+	c #6D125C",
+"Y+	c #6C125C",
+"Z+	c #74124A",
+"`+	c #6C115B",
+" @	c #6D115C",
+".@	c #6B125C",
+"+@	c #6B115C",
+"@@	c #6B125D",
+"#@	c #75124B",
+"$@	c #6B125E",
+"%@	c #73114C",
+"&@	c #6B115D",
+"*@	c #6B115E",
+"=@	c #6A115F",
+"-@	c #751248",
+";@	c #6A115E",
+">@	c #6B125F",
+",@	c #6A125F",
+"'@	c #6A1260",
+")@	c #6A125E",
+"!@	c #6B115F",
+"~@	c #691160",
+"{@	c #6A1261",
+"]@	c #6C125D",
+"^@	c #6A1160",
+"/@	c #691161",
+"(@	c #691261",
+"_@	c #691262",
+":@	c #691263",
+"<@	c #02FE02",
+"[@	c #691260",
+"}@	c #028202",
+"|@	c #6A1161",
+"1@	c #691162",
+"2@	c #691163",
+"3@	c #691264",
+"4@	c #681263",
+"5@	c #73124F",
+"6@	c #681264",
+"7@	c #671264",
+"8@	c #681265",
+"9@	c #671266",
+"0@	c #681165",
+"a@	c #671265",
+"b@	c #691164",
+"c@	c #681164",
+"d@	c #671166",
+"e@	c #681266",
+"f@	c #671267",
+"g@	c #661268",
+"h@	c #661167",
+"i@	c #671268",
+"j@	c #671167",
+"k@	c #661267",
+"l@	c #651269",
+"m@	c #661269",
+"n@	c #661169",
+"o@	c #66126A",
+"p@	c #65126A",
+"q@	c #701253",
+"r@	c #65126B",
+"s@	c #711255",
+"t@	c #64126B",
+"u@	c #64126C",
+"v@	c #6E1156",
+"w@	c #6F1258",
+"x@	c #63126C",
+"y@	c #64136D",
+"z@	c #63126D",
+"A@	c #63126E",
+"B@	c #64126D",
+"C@	c #64126E",
+"D@	c #63136E",
+"E@	c #63136D",
+"F@	c #63126F",
+"G@	c #63136F",
+"H@	c #62126F",
+"I@	c #621270",
+"J@	c #62136F",
+"K@	c #62126E",
+"L@	c #621271",
+"M@	c #621272",
+"N@	c #631270",
+"O@	c #611272",
+"P@	c #621371",
+"Q@	c #621372",
+"R@	c #611372",
+"S@	c #611273",
+"T@	c #621370",
+"U@	c #621273",
+"V@	c #601373",
+"W@	c #611274",
+"X@	c #601274",
+"Y@	c #601273",
+"Z@	c #601374",
+"`@	c #601275",
+" #	c #6A115D",
+".#	c #601276",
+"+#	c #5F1376",
+"@#	c #611373",
+"##	c #601375",
+"$#	c #5F1276",
+"%#	c #601376",
+"&#	c #5F1277",
+"*#	c #6A1162",
+"=#	c #681163",
+"-#	c #691165",
+";#	c #671165",
+">#	c #611374",
+",#	c #5F1377",
+"'#	c #5E1277",
+")#	c #5E1278",
+"!#	c #671164",
+"~#	c #681166",
+"{#	c #661168",
+"]#	c #5F1278",
+"^#	c #5E1279",
+"/#	c #651169",
+"(#	c #66126B",
+"_#	c #611375",
+":#	c #5E1378",
+"<#	c #5F1379",
+"[#	c #671269",
+"}#	c #651268",
+"|#	c #601377",
+"1#	c #5D1279",
+"2#	c #5E1379",
+"3#	c #5F1375",
+"4#	c #5E1377",
+"5#	c #5F1378",
+"6#	c #5E137A",
+"7#	c #5E127A",
+"8#	c #5D127A",
+"9#	c #64136C",
+"0#	c #5F1279",
+"a#	c #5D1379",
+"b#	c #5D137B",
+"c#	c #5F1275",
+"d#	c #5D137A",
+"e#	c #5D127B",
+"f#	c #5C137B",
+"g#	c #5C127B",
+"h#	c #5D137C",
+"i#	c #5C127A",
+"j#	c #5C127C",
+"k#	c #5C127D",
+"l#	c #601277",
+"m#	c #5C137C",
+"n#	c #5B127D",
+"o#	c #621373",
+"p#	c #5C137D",
+"q#	c #5B137E",
+"r#	c #671168",
+"s#	c #5D127C",
+"t#	c #5B137D",
+"u#	c #5B127E",
+"v#	c #62136E",
+"w#	c #5C137E",
+"x#	c #5B137F",
+"y#	c #5B1380",
+"z#	c #611275",
+"A#	c #5C127E",
+"B#	c #5B127F",
+"C#	c #5B1280",
+"D#	c #5A1280",
+"E#	c #5B1281",
+"F#	c #5A1281",
+"G#	c #FE0202",
+"H#	c #5B127C",
+"I#	c #5A1380",
+"J#	c #5A1381",
+"K#	c #5A1382",
+"L#	c #5A1282",
+"M#	c #591382",
+"N#	c #591282",
+"O#	c #591383",
+"P#	c #591283",
+"Q#	c #591284",
+"R#	c #591384",
+"S#	c #631370",
+"T#	c #581384",
+"U#	c #581284",
+"V#	c #581385",
+"W#	c #581285",
+"X#	c #581286",
+"Y#	c #571386",
+"Z#	c #5B137C",
+"`#	c #591385",
+" $	c #571385",
+".$	c #581386",
+"+$	c #571387",
+"@$	c #571287",
+"#$	c #561287",
+"$$	c #581387",
+"%$	c #561387",
+"&$	c #571388",
+"*$	c #571286",
+"=$	c #561388",
+"-$	c #561288",
+";$	c #561289",
+">$	c #561389",
+",$	c #551289",
+"'$	c #56128A",
+")$	c #55138A",
+"!$	c #56138A",
+"~$	c #5A1283",
+"{$	c #55128A",
+"]$	c #55138B",
+"^$	c #591281",
+"/$	c #551389",
+"($	c #54138B",
+"_$	c #55128B",
+":$	c #55138C",
+"<$	c #54138C",
+"[$	c #54138D",
+"}$	c #581287",
+"|$	c #54138E",
+"1$	c #571288",
+"2$	c #5B1381",
+"3$	c #54128E",
+"4$	c #53138F",
+"5$	c #54138F",
+"6$	c #5C137A",
+"7$	c #54128C",
+"8$	c #54128D",
+"9$	c #531390",
+"0$	c #521390",
+"a$	c #591381",
+"b$	c #521391",
+"c$	c #5A1383",
+"d$	c #531391",
+"e$	c #521392",
+"f$	c #511392",
+"g$	c #55128C",
+"h$	c #511393",
+"i$	c #52138F",
+"j$	c #521393",
+"k$	c #511394",
+"l$	c #53138E",
+"m$	c #501394",
+"n$	c #501395",
+"o$	c #511395",
+"p$	c #591285",
+"q$	c #501495",
+"r$	c #501396",
+"s$	c #4F1396",
+"t$	c #551388",
+"u$	c #54128B",
+"v$	c #4F1496",
+"w$	c #581383",
+"x$	c #54128F",
+"y$	c #511493",
+"z$	c #4F1397",
+"A$	c #521290",
+"B$	c #511494",
+"C$	c #4E1397",
+"D$	c #4E1498",
+"E$	c #4F1398",
+"F$	c #53128F",
+"G$	c #4E1398",
+"H$	c #4F1497",
+"I$	c #4E1399",
+"J$	c #4D1399",
+"K$	c #4D139A",
+"L$	c #511492",
+"M$	c #501496",
+"N$	c #4F1498",
+"O$	c #4D149B",
+"P$	c #571285",
+"Q$	c #501393",
+"R$	c #501494",
+"S$	c #4E139A",
+"T$	c #4D139B",
+"U$	c #531290",
+"V$	c #521291",
+"W$	c #4E139B",
+"X$	c #4C139B",
+"Y$	c #551288",
+"Z$	c #511495",
+"`$	c #4D149C",
+" %	c #4C139C",
+".%	c #4C139D",
+"+%	c #4F1399",
+"@%	c #4E1499",
+"#%	c #4E149A",
+"$%	c #4C149C",
+"%%	c #4C149D",
+"&%	c #4D139C",
+"*%	c #541390",
+"=%	c #4C139E",
+"-%	c #4C139F",
+";%	c #4C149E",
+">%	c #4B139E",
+",%	c #4B149F",
+"'%	c #4B139F",
+")%	c #4D149A",
+"!%	c #4B149E",
+"~%	c #4B14A0",
+"{%	c #4B13A0",
+"]%	c #4B13A1",
+"^%	c #54138A",
+"/%	c #4C13A0",
+"(%	c #4A14A1",
+"_%	c #4A14A0",
+":%	c #4A14A2",
+"<%	c #4D1499",
+"[%	c #4C149F",
+"}%	c #4B14A1",
+"|%	c #4A13A1",
+"1%	c #4A14A3",
+"2%	c #4C149B",
+"3%	c #4A13A2",
+"4%	c #4914A3",
+"5%	c #4A13A3",
+"6%	c #4913A3",
+"7%	c #4913A4",
+"8%	c #4E1497",
+"9%	c #4914A4",
+"0%	c #4813A4",
+"a%	c #4C139A",
+"b%	c #4D149D",
+"c%	c #4814A4",
+"d%	c #4B13A2",
+"e%	c #4914A2",
+"f%	c #4813A5",
+"g%	c #4D1398",
+"h%	c #4814A5",
+"i%	c #521492",
+"j%	c #4F1395",
+"k%	c #4D139D",
+"l%	c #4A13A4",
+"m%	c #4714A5",
+"n%	c #4814A6",
+"o%	c #4714A7",
+"p%	c #4713A6",
+"q%	c #4713A7",
+"r%	c #4714A6",
+"s%	c #4C14A0",
+"t%	c #4A14A4",
+"u%	c #4713A5",
+"v%	c #4614A8",
+"w%	c #4714A8",
+"x%	c #4713A8",
+"y%	c #4613A8",
+"z%	c #511396",
+"A%	c #4813A6",
+"B%	c #4713A9",
+"C%	c #4614A9",
+"D%	c #4613A9",
+"E%	c #4613AA",
+"F%	c #4A13A0",
+"G%	c #4514A9",
+"H%	c #4514AA",
+"I%	c #4614AA",
+"J%	c #4614A7",
+"K%	c #4513AA",
+"L%	c #4614AB",
+"M%	c #4513AB",
+"N%	c #4514AB",
+"O%	c #4913A2",
+"P%	c #4814A7",
+"Q%	c #4613A7",
+"R%	c #4513AC",
+"S%	c #4514AC",
+"T%	c #4914A5",
+"U%	c #501397",
+"V%	c #4513AD",
+"W%	c #4513A9",
+"X%	c #4514AD",
+"Y%	c #4414AD",
+"Z%	c #4413AE",
+"`%	c #4314AE",
+" &	c #4413AD",
+".&	c #4414AE",
+"+&	c #4314AF",
+"@&	c #4414AF",
+"#&	c #4714A9",
+"$&	c #4413AF",
+"%&	c #4313AF",
+"&&	c #4D1498",
+"*&	c #4314B0",
+"=&	c #4414B0",
+"-&	c #4314B1",
+";&	c #4214B1",
+">&	c #4313B0",
+",&	c #4214B2",
+"'&	c #4214B0",
+")&	c #4213B1",
+"!&	c #4313B1",
+"~&	c #4213B2",
+"{&	c #4214B3",
+"]&	c #4114B3",
+"^&	c #4513AE",
+"/&	c #4014B3",
+"(&	c #4414AC",
+"_&	c #4313AE",
+":&	c #4113B2",
+"<&	c #4114B4",
+"[&	c #4113B4",
+"}&	c #4014B4",
+"|&	c #4413AC",
+"1&	c #4314B2",
+"2&	c #4213B3",
+"3&	c #4113B3",
+"4&	c #4014B5",
+"5&	c #4114B2",
+"6&	c #4013B5",
+"7&	c #3F14B5",
+"8&	c #3F14B6",
+"9&	c #4014B6",
+"0&	c #4114B5",
+"a&	c #3F14B7",
+"b&	c #3F14B8",
+"c&	c #4013B7",
+"d&	c #3E14B7",
+"e&	c #3E13B8",
+"f&	c #3E14B8",
+"g&	c #4313B2",
+"h&	c #3E14B9",
+"i&	c #4013B4",
+"j&	c #4014B7",
+"k&	c #3F14B9",
+"l&	c #3E15B9",
+"m&	c #3E14BA",
+"n&	c #4213B0",
+"o&	c #3E13B7",
+"p&	c #3D14BA",
+"q&	c #3E15BA",
+"r&	c #3D14BB",
+"s&	c #3E14BB",
+"t&	c #3D14BC",
+"u&	c #3D15BA",
+"v&	c #3E14BC",
+"w&	c #3D14BD",
+"x&	c #4613AB",
+"y&	c #4514AE",
+"z&	c #4413B0",
+"A&	c #3D14BE",
+"B&	c #3F13B7",
+"C&	c #3E15BB",
+"D&	c #3D15BD",
+"E&	c #3C15BE",
+"F&	c #3C14BD",
+"G&	c #3C14BE",
+"H&	c #3C14BF",
+"I&	c #3B14BF",
+"J&	c #3D15BB",
+"K&	c #3B14C0",
+"L&	c #3C15BD",
+"M&	c #3C14C0",
+"N&	c #3B15C0",
+"O&	c #3E15BC",
+"P&	c #3C15BC",
+"Q&	c #3B14C1",
+"R&	c #3A14C1",
+"S&	c #3B15C1",
+"T&	c #3A15C1",
+"U&	c #3D15BC",
+"V&	c #3C14BC",
+"W&	c #3C15BF",
+"X&	c #3B14BE",
+"Y&	c #3A14C2",
+"Z&	c #3A15C2",
+"`&	c #4014B8",
+" *	c #3D15BE",
+".*	c #3914C3",
+"+*	c #3B15BF",
+"@*	c #3914C2",
+"#*	c #3A14C3",
+"$*	c #3915C2",
+"%*	c #3915C3",
+"&*	c #3914C4",
+"**	c #3814C4",
+"=*	c #3B14C2",
+"-*	c #3914C1",
+";*	c #3815C4",
+">*	c #3814C5",
+",*	c #3915C4",
+"'*	c #3914C5",
+")*	c #3814C6",
+"!*	c #3815C6",
+"~*	c #3815C5",
+"{*	c #3915C5",
+"]*	c #3714C7",
+"^*	c #3714C6",
+"/*	c #3814C7",
+"(*	c #3A15C3",
+"_*	c #3714C5",
+":*	c #3815C7",
+"<*	c #3715C8",
+"[*	c #3714C8",
+"}*	c #3715C6",
+"|*	c #3715C7",
+"1*	c #3714C9",
+"2*	c #3615C9",
+"3*	c #3A14C0",
+"4*	c #3715C9",
+"5*	c #3615CA",
+"6*	c #3714CA",
+"7*	c #3614CA",
+"8*	c #3814C8",
+"9*	c #3614C9",
+"0*	c #3614CB",
+"a*	c #3615CB",
+"b*	c #3515CB",
+"c*	c #3515CC",
+"d*	c #3615CC",
+"e*	c #3715CA",
+"f*	c #3514CB",
+"g*	c #3514CC",
+"h*	c #3514CD",
+"i*	c #3614CC",
+"j*	c #3515CD",
+"k*	c #3414CD",
+"l*	c #3714CB",
+"m*	c #3414CC",
+"n*	c #3414CE",
+"o*	c #3515CE",
+"p*	c #3415CE",
+"q*	c #3C15C0",
+"r*	c #3415CF",
+"s*	c #3915C6",
+"t*	c #3514CA",
+"u*	c #3414D0",
+"v*	c #3514CE",
+"w*	c #3415CD",
+"x*	c #3315CF",
+"y*	c #3414CF",
+"z*	c #3314D0",
+"A*	c #3315D0",
+"B*	c #3415D0",
+"C*	c #3A14C4",
+"D*	c #3314CF",
+"E*	c #3315D1",
+"F*	c #3715CB",
+"G*	c #3214D0",
+"H*	c #3215D1",
+"I*	c #3215D0",
+"J*	c #3214D1",
+"K*	c #3314D1",
+"L*	c #3715C5",
+"M*	c #3215D2",
+"N*	c #3515CF",
+"O*	c #3214D2",
+". + @ # + + @ @ $ % $ & $ $ $ * $ = - - * * - ; - ; - ; ; ; ; > > ; > , , > ' , , , , , , , , ) ) ! ! ~ ! ~ ~ { ~ ~ ~ ] ^ / / / ( ^ _ ( ( ( _ : : : : : : : < < < < < [ } [ [ } } [ | } } | 1 2 2 1 2 1 ",
+"+ + @ @ + & @ $ $ $ $ $ $ * * = - * - ; 3 - - ; ; ; ; ; ; , > , , > , , ' , , , , , , , ) ) ) ) 4 ~ ~ 5 { ~ / ~ ~ 6 ^ ^ ^ ^ 6 ( ( ( ( ( : : : : : < < : : 7 < [ 8 [ [ [ 8 8 } } } } 2 } } } 1 1 9 9 0 0 ",
+"@ $ + @ @ @ $ $ $ $ - - - $ * * * 3 - ; ; a ; ; ; b ; ; c > > > > > , , , ) , d ) ) ) 4 ) ! ! ~ ~ { ~ ~ ~ / ^ e e ^ ( ( ( ( _ ( f : ( : : < < : < < 7 < 7 7 [ 8 | } 8 } } | } } 1 1 g 1 1 h g i 0 0 0 j ",
+"$ $ + @ $ $ % $ - * = $ k * - l - ; - ; ; ; ; ; > , , , > > > , , > ' , ) ) ) ! ! ! { m ! ! ~ ~ ~ ~ { / ^ / e ^ n ^ ( ( _ ( _ _ : ( : : < < < f < } < [ } [ 8 | [ } } [ } } o o h 1 h 0 h 0 i 0 0 i p q ",
+"@ $ $ * * $ k - * * * * - ; ; ; ; ; c ; > , , r > > , , > , , , ) , , ! ! ) ! s ) ! ~ ! ~ ~ e ~ / ~ ^ / n ^ ( ( ( : _ _ ( : : f : < : : < [ < [ 8 [ 8 8 [ [ } [ } | } } g 1 h h 1 9 0 0 0 0 p t j t u q ",
+"$ $ - $ $ * - * - * - ; ; 3 ; ; ; > > > ' > , ' > > , , , ' , ! ) ) 4 ) ) ) ~ ~ m ~ e / ~ ] ~ / 6 v ( ^ n ( : _ : ( : : : < : 7 < 7 < [ [ 8 < | } } [ | } } } | | h | 1 2 i w 9 0 i j j x 0 p y x u y u ",
+"$ = * - - * - - - ; 3 ; ; ; , > , > > > , > , , , , ) d , ) ) ) 4 ! m ) ~ m ~ { ~ ~ / e / / / ^ ^ ( n ( ( ( ( : ( : < f f < < < < < z } [ } [ [ } [ } | 1 } h 1 2 g 2 g 9 i 0 i i 0 x p j q u q u u u A ",
+"* - * ; ; - 3 - ; ; ; > c > > , > ' ' , , , , , , d ! , ) ) s ~ ~ ! ~ m ~ ~ { ^ / / / / ^ ( 6 ( ( ( ( ( : : : < f f < : < < [ < [ } | [ } | } } } 2 } 1 h 1 1 1 g h 0 i 0 i 0 p j t p j q y u A u u B C ",
+"; * ; ; * ; ; ; > , ; ' , , , b b > , , , , ) ) , ! ) ) ) ) ! ~ { ~ ~ ] { / 6 / ^ ( ( ( / _ : ( f : : f f : : < : < < < [ 7 7 [ [ } | } } } } 1 1 2 2 0 2 9 0 i i i 0 0 j t p t u u t u u u y y A A D E ",
+"; - ; ; ; ; a > c , , , > , , , ' , , , , ) , ) ! ~ s ) ! ! ~ ~ ~ / / e / ^ 6 ^ _ _ _ ( ( ( _ : : : : : 7 < < < [ 7 [ [ [ } | } } | } 1 } } } 1 2 1 0 h g i 0 i j p j q p j u y y A F y C B B F B E G E ",
+"; a ; > ; > ; , , > , , , , , , , , ) d ) 4 ! ) ) ~ m 5 ~ { ] / ^ / n ^ ^ n ( ( ( ( ( ( f f : : : : < < 7 < < 8 < [ 8 [ | [ | | } 1 1 h 2 2 0 9 i 2 i j 0 j t j j q y t u u u u F B F A A F A G G G H I ",
+"> a ; a , , b , , ' , , , , ! ) , ) ! ! ~ ~ s ~ ~ ~ ~ / { ^ / ^ / ( / / _ _ ( ( _ f f : : : < : < < [ 7 < z | [ } } [ } } } 2 | 1 h 2 h 1 w h 0 i 0 0 t j t t t q y u y A A C F D B J G B D G E I G K L ",
+"> ' > > ' > , ' , ' ) ' ) 4 ) ) ) ) ~ ! { ~ ~ ~ / / / / ^ / ^ 6 _ / ( _ ( ( ( f : f : < < < < < < 8 < [ [ } } [ | | } 2 2 | o 1 1 h 0 w 0 i p j 0 M t j p y x q u u u y B B A B C E G J G I E N I H O L ",
+", , > , , , , ' , ) , P ) ) ! m ! ~ { ~ { { ] ~ / / / n 6 ^ ( ( ( ( ( _ ( : f : : f < < < < < 8 7 8 [ 8 | [ } | 2 } 1 1 } h 1 h 0 9 i j i p t t x x u Q q y u u y C B E C A E D G E G H H H R I R O L O ",
+", , ' , , , , ) ) s ! ) ! m ~ { ~ ~ ~ { e ^ ^ / / / ^ ( ( _ ( : : : : : : f < : 7 7 < [ < [ [ 8 [ } 8 | } 1 } } 2 g 2 0 0 w w 0 i p j x p p j y u u q A A B A A F F E C J E G H E S T K O O R T L U V O ",
+"' , , 4 ) , ) 4 ) ) ~ m m m ~ ~ / / / / / / ^ ^ _ 6 n ( ( ( ( ( f : < 7 7 7 7 7 [ < [ [ [ } [ [ } | } | } 1 1 2 0 9 9 9 0 W 0 j j j j t x q u u y A B F B A C B G D N E E G K O K I I L L L L O O V V X ",
+", ) ! ! ) ) s 4 ~ m ~ { ~ ^ / ~ / / ^ n 6 n _ _ ( : _ f : : f : : f 7 < < < < 8 [ [ } [ [ | 8 } } } g 1 2 1 1 i h w i i i j p x u p u t u y F A A C C C E B G E G E H K K O N H O O O L L O L L L Y Z Z ",
+") ! ) s ! ~ { ~ ~ { ~ e / e / 6 / ( ^ ( _ _ ( _ f : f f : < : : < < < 8 [ [ [ 8 } } } [ } | 2 | o | 2 2 w i i 0 p 0 p j j y Q u y u u u A A F F A J G C G E H H N N I I H K L L L L L U U L Z V Z Y ` ` ",
+"! ) m ~ ~ 5 ~ ~ ~ ^ ~ / ^ ^ v 6 n n ( ( : : : : f : 7 < : < < < < < [ [ } [ [ } | 8 } | 1 1 1 1 h 1 h 9 w 0 j t j i j j u y Q u u F A u B F J B C D G H N E H I O K O O T O L O V  .U V Z Y Z Y Z Y ..` ",
+"! ! ~ { { ~ / / ^ / / _ ( ^ ( ( ( : : : : : : 7 : < < < < 7 < 8 | [ [ | | 8 [ } } 2 1 } 1 h g 9 0 i 0 0 j j j j y t p x u u F A A B A C G B J E G N E K N K K T O O O L O V O  .Z  .Z Y Y Y ..` ..` +.@.",
+"~ / / / ~ / ^ / ^ _ / ( ( ( ( ( : f : f < 7 < < 7 < < < } [ [ [ | } } } | | | 1 2 1 g 1 h h 0 w 0 p 0 M t j x u q u u F A A F C D E B G E E H H K H H I O L L R O O L  .O U V Z Z Z ` ` #.` $.@.#.@.@.%.",
+"~ ~ ] ^ / / / _ ( _ ( ( : _ _ : : < < < < < < < } 8 [ < 8 [ } [ } } } 1 2 1 h g h 1 0 0 0 i 0 t &.0 j x q q y u y A F A B C J B G G G E E N H H N K T L T O V V O O L  .X Y Y Z *.#.` ` #.#.@.=.@.-.-.;.",
+"^ ^ 6 / ( ^ n ( _ ( : _ _ : : 7 < < < < 7 < 8 [ [ | | } } | } } | 2 } g 1 h h h i h 0 i t x x j p t Q x Q u F A A F F G A E G G G G N K I H R L T O L V O L V  .X Z Z Z ` ` ..#...$.>.@.;.=.;.=.-.;.;.;.",
+"^ e _ n ( ( ( ( : ( f : : < 7 < < 7 [ 8 } [ } | | } [ | | } 1 1 g 2 1 h h h 0 0 i i j p j j t u u y u F u F A B A B J D ,.E E K I K I T R L O L O L L L U L Y Z Z ` ........$.$.@.>.@.@.-.-.;.-.-.'.-.).",
+"( / v ( f ( _ : f : 7 7 < < < < < 7 [ 8 } [ } } } } } | } 1 !.1 0 1 w 0 9 p j p j j p t u u y y A A ~.F F B B E G G E E E N H I I R O L O L O U Y L O O Y  .Y ....#.$.` +.+.>.@.@.@.@.-.-.'.;.).).'.{.{.",
+"_ : _ : : : < : < < 7 < < < [ | } [ | [ [ } } | | 1 2 2 h 0 i i g i 0 0 p j j t q y y u y y y A A A A E E D E E E E N G H I O L O L L U O O  .U V Y Y Y ..#.*.` ..@.` $.@.@.=.@.;.;.-.;.'.'.).).].{.^./.",
+"f ( : : : < 7 < 7 8 [ } [ [ | 8 [ } | | } 1 1 | 2 g 1 0 h h 0 0 i p M j x x t y Q u u A u F A C E J D G J G E N N H N I T T O L O U V O Z Y Y Y Y Z Y #.` +.` =.@.=.@.;.-.-.'.).;.;.'.'.^.].{.^.(._.].(.",
+"f : : < : < < 8 z [ [ 8 } } [ | | [ 1 } 1 1 2 g g w g 0 i i 0 i j t t p q u u F u y A F A C C J E G N G H N K L O L L L T O L L O L O U  .X  .Z ` ..` @.+.@.@.@.@.-.-.-.;.-.).).).{.).{.^.].{.^.:.<.:.:.",
+"< : < < [ 7 [ 8 [ } } } } | | } } } 2 1 i h 1 g 9 0 p j j j x t x x x q A A A F y F A J F D E G E H E N L H L O L O O L O O  .O O Y ` X ` ` ....#.$.=.>.@.@.-.;.;.-.;.).).).).^.^.{.].<.<.:.<.(.<.:.[.<.",
+"< 7 < < [ } } } [ | 8 | 8 } !.2 | 1 9 9 i 2 0 j 0 0 j p x j t j t y y A F A A A B B G E E E N N K L R O O O L L L O O L Y  .Z Y Z Y #.` ..#.#.=.@.@.=.;.-.-.-.).-.'.'.).'.{.).(._.{./.<.:.<.[.}.}.|.}.1.",
+"z [ | } 8 | | } [ | 1 1 } 1 1 9 1 g 0 0 j i i 0 j j y x p x u u F A A A A B B G G E E G H N I K T O K O O L O U U O U X Z Y ` *.......+.=.>.=.@.;.=.;.;.'.;.).).'.^.).{.{.<.{.<.<._.:.<.<.<.:.2.2.1.3.1.",
+"[ | } } } } } 1 2 1 2 2 g h 0 9 0 i w p p p j j u y u y Q A A B A B F B B E N G H E I I I I K L R O O L L V L Y X  . . .4.Y ..` #.$.=.+.@.=.-.-.;.).-.).'.'.).).).{.^.].(.].<.(.:.:.:.<.[.2.2.1.1.1.3.3.",
+"8 } 8 } } 2 | | 2 h 2 0 9 0 0 0 0 j j p j x u p x u F y A B B A D A E E E G 5.N H T N K T L O O L L L V X  .V Y X *.` #.#...@.` @.=.@.-.;.;.;.-.).).).).{./././.{.]./.:.<.<.<.:.:.[.<.|.6.3.1.3.3.3.7.8.",
+"[ 1 1 1 h !.h 2 h 1 h i j 0 i j j q x y x y u u A A C C A C B G E H E H G N H H T O O L R O L L X Z  . .Y Y ....Y $.@.` ` ..=.;.=.-.-.;.).-.-.'.'.{.{././._.:.:.<.:.<.:.<.}.<.|.|.1.1.|.3.3.9.0.a.a.8.b.",
+"o 1 h 2 h 0 9 g 0 i i j p p j p x u u y u u A A B B B C B G G H G N K I N O O L O L L O L L V U X Y Y Y ` Y ` ` #.+.>.=.-.=.-.-.-.).;.;.'.).).'.{.^./._.<.<.<.<.<.<.:.}.|.[.2.2.3.|.3.3.0.c.8.8.8.b.b.b.",
+"h 2 g 9 g i i d.0 j j x x p y y u u A y u B F J D B E E N G E H N N H O T L L L L L U X V X V Y ` Y ` ` ` ` +.@.=.@.@.@.;.-.;.;.-.'.).).'.'.{.{.{./.<.(.<.:.:.<.2.<.<.}.1.1.3.3.0.c.7.8.7.8.e.8.f.b.e.g.",
+"i i i 0 0 0 j j t j u t u q y u y ~.A F A A B J E E H E H H I K K I L L L O O U X  .U Z Y Z ` ` ` #.#.` @.@.>.-.;.=.-.-.'.-.).).{.^.{.^.{.(.(./.(.<.<.<.<.<.<.2.1.|.|.1.3.0.3.9.9.8.8.e.b.b.e.b.b.h.i.j.",
+"i 0 i 0 p M t j x y t y u F y C C B A E G G H H E H K I T I O L O O L V L X  .Z Y Y Z ..Y ` ` @.>.+.@.;.@.=.-.-.-.;.'.'.).).^.).{.].(.:.:.<.(.:.<.:.<.[.<.1.|.1.1.1.7.7.0.a.a.a.8.k.8.e.g.l.g.g.g.g.g.j.",
+"0 j t q j u t u y y u A F C A C C D D H H E G K H I K O I O L L L L V V U Y Y Z Y Y Z ` ..+.=.@.@.-.@.-.;.;.'.;.).).'.).^.^.].(._./.:.:.<.<.:.<.<.<.2.6.6.3.3.3.3.3.c.8.c.8.b.b.b.l.b.g.g.g.j.g.j.j.m.n.",
+"p x t q u y u A A F A D C B D B E H K N I O N L O T L O O L L V U O Z Y X Y Y Y *.+.#.#.=.@.@.-.-.;.;.).;.).).'.).'.^.{.].(.<.<.<.(.:.<.<.[.[.1.1.1.|.3.3.3.0.9.8.8.a.b.8.e.e.e.l.b.o.g.j.g.p.m.j.m.j.n.",
+"p j u y F F A A F G J D D G E N N I H K N L O O L L O O L Z V L Z Z q.Y #...` >.$.>.+.=.r.-.-.-.;.'.'.'.).).'.).{.].].<.(.<.<.<.<.<.:.[.1.1.1.1.3.|.3.3.a.8.a.a.8.e.8.b.b.i.o.g.g.o.j.p.j.s.m.s.n.n.n.n.",
+"Q u u u F C A F E G J E H N K E I I O H L L O U O L U V  . .Z Y Y ` #.....#.@.+.=.=.-.;.;.;.-.).).).{.{.{.^./.].<._.(.:.t.t.t.t.<.[.1.1.|.1.3.9.8.3.9.7.k.u.8.8.l.l.b.g.g.g.p.v.p.j.s.p.n.n.s.s.n.n.n.w.",
+"u A B A J F G J G N E H H N N N L O O O L L L V Y V Z Z Z ` Z ` $.` =.#.+.=.;.@.@.-.;.).'.).'.).'.^.).^.(.<./.t.t.t.t.t.x.x.x.x.t.t.7.|.3.7.k.0.7.a.e.b.k.b.b.b.o.g.g.p.j.j.p.j.j.j.s.w.n.n.n.n.y.z.A.B.",
+"B A C E A G E N N E H T R R O L L O L L V Y  .Z Y Y Z ....` ` =.+.=.@.=.=.@.;.-.;.;.-.'.).).{.{.^.].(.t.t.t.t.x.x.x.x.x.x.x.x.x.x.x.t.t.k.a.8.8.8.b.e.b.b.g.o.o.i.g.i.j.j.j.p.n.s.C.n.n.n.n.y.y.y.D.B.D.",
+"D E J G G N N H O R O L O O O O O U L L Y Z Y ..Z *.$.$.#.>.+.@.=.@.;.@.-.;.).).).).{.'.{.{.t.t.t.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.b.8.b.b.b.o.b.o.j.g.m.m.m.n.n.n.w.w.n.n.n.n.z.y.B.B.B.D.E.E.",
+"G N N 5.K N T K L L L O O O L  . .Z Y Y  .Y Z ..` ` >.$.=.=.t.t.;.;.).).).).).{.).t.t.t.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.o.g.g.j.j.g.j.m.s.s.n.s.s.n.n.n.n.n.y.B.B.D.D.D.D.D.E.F.",
+"G H K R K L L L O O O L L X Y V Y Z Z ..#.` ` ` >.$.+.@.t.t.x.x.t.t.G.).t.t.t.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.g.j.j.j.n.C.n.n.n.n.n.w.n.H.y.B.D.D.D.I.D.F.E.F.J.F.",
+"R K T K O L O O O L V  .O X Y Y Y ` ..` =.$.=.=.@.@.t.t.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.n.n.s.n.n.n.n.B.y.B.B.B.B.D.D.D.F.F.F.F.J.F.J.J.",
+"N O L O U L L L  .V X Y Z Y Y $.#.` ` >.@.@.;.@.t.t.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.w.n.z.K.B.B.y.B.B.E.I.F.E.F.J.J.J.J.J.J.J.L.",
+"O O U O U  .O V Z Z Z ` Z ..` ..>.#.=.=.-.;.;.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.B.D.M.M.D.E.D.E.F.F.F.J.J.L.L.L.L.N.L.L.",
+"O O U U Z Y Z ..` Y ` #.@.=.#.@.@.;.;.-.;.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.E.E.F.F.E.F.O.J.J.L.J.L.L.N.L.N.P.N.",
+" .V Z Y Z ......#.#...+.@.@.=.=.;.-.'.;.).t.x.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.G.J.J.O.J.L.J.L.L.L.N.N.N.N.N.Q.R.",
+" ...` Z ` ..=.=.@.@.@.@.;.;.-.;.;.-.-.).{.t.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.S.G.J.L.J.L.N.L.L.N.N.P.Q.P.P.R.R.R.",
+"Z ` ..` =.@.` =.=.;.@.;.-.).'.'.).).{.{.).t.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.S.S.S.G.J.L.N.N.N.N.P.Q.P.R.R.P.R.T.U.U.",
+"@.=.=.+.+.@.@.;.;.;.-.;.'.'.'.{.).].<.(.].t.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.G.N.L.V.N.N.Q.R.R.W.R.R.T.R.U.T.X.",
+"@.=.@.-.=.;.;.-.-.).'.).^.{.{.{.^.{.<.{._.t.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.G.N.N.W.N.R.P.P.R.R.U.R.X.X.X.Y.X.",
+"+.;.;.;.;.-.-.-.).{.^.].^._.{.(.:.<.<.:.<.t.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.G.N.P.R.R.W.R.R.R.U.X.U.Y.Z.Y.`. +",
+"-.;.'.).'.'.).'.)./.{.].].(.<.<.<.:.<.2.<.t.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.G.R.P.R.R.R.U.X.X.Z.Y.Y.Y.`..+`.`.",
+").'.'.).).++{.{.{.:.(.:.<.<.:.<.<.[.|.|.1.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.G.R.U.U.X.U.Z.X.Y.Y.Y.Y.Y.`..+@+#+",
+"'.'.$+^.{.{./.(.:.<.(.:.:.[.2.2.2.[.|.1.1.t.x.x.x.S.S.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.X.%+Y.Y.Y.&+&+.+`.`.*+*+*+=+=+@+",
+"{.{.].]./.<.<.<.<.:.<.:.|.1.1.|.1.3.1.3.7.t.x.x.x.S.-+S.S.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.X.Y.Y.Y.Y..+.+.+.+;+@+#+>+@+,+>+",
+"/._.].:.<.<.<.[.<.<.[.2.6.2.|.7.7.c.7.a.k.t.x.x.x.S.'+'+-+S.S.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.Y.`..+.+.+@+#+@+=+@+)+>+)+)+,+,+",
+"(.:.<.<.<.<.[.[.|.2.3.1.1.1.3.0.8.k.a.a.e.t.x.x.x.S.-+-+'+'+-+S.S.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.G.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G..+.+!+#+#+>+@+>+)+~+,+,+,+,+{+]+",
+"<.<.<.2.:.1.1.1.7.3.9.3.a.0.8.8.8.8.b.b.b.t.x.x.x.S.-+'+-+-+'+'+-+S.S.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.S.G.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G..+@+@+@+@+>+)+)+)+^+,+/+,+]+/+]+",
+"<.:.<.1.|.7.|.|.7.7.a.0.8.8.8.b.e.b.b.o.g.t.x.x.x.S.-+-+'+'+-+-+-+'+-+S.S.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.S.S.S.G.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.@+@+>+>+^+)+,+,+(+{+_+{+]+]+:+<+",
+"1.|.6.3.3.3.3.9.a.8.a.k.k.b.b.g.l.l.g.g.o.t.x.x.x.S.'+'+-+-+-+'+-+-+'+'+'+S.S.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.~+)+,+,+,+{+{+/+]+/+:+]+:+:+:+:+",
+"3.3.3.0.3.9.0.a.a.k.8.e.e.b.o.b.o.o.j.p.j.t.x.x.x.S.-+-+'+'+-+-+'+'+-+-+-+'+-+S.S.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.,+(+[+{+{+_+{+]+}+:+:+|+|+1+<+2+",
+"3.7.7.8.a.8.8.b.b.l.b.l.g.o.g.g.j.p.p.j.n.t.x.x.x.S.'+'+-+-+'+'+-+-+-+'+'+-+-+'+'+S.S.x.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.[+{+{+_+}+:+<+|+3+|+|+:+|+2+4+5+",
+"8.a.8.e.b.b.b.e.g.o.o.g.g.j.j.j.s.j.w.C.n.t.x.x.x.S.'+-+'+'+-+-+'+'+-+-+-+'+'+-+-+'+-+S.S.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.}+<+6+:+:+<+|+:+|+4+2+4+4+7+5+7+",
+"8.8.8.b.g.b.l.b.o.j.v.g.m.j.n.C.s.n.n.n.n.t.x.x.x.S.'+'+-+-+'+'+-+-+'+'+'+-+-+'+-+-+-+'+'+S.S.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.}+:+|+3+3+|+|+2+4+4+7+7+7+7+8+9+",
+"e.b.b.b.l.o.g.j.g.p.s.m.j.C.n.n.n.n.n.z.y.t.x.x.x.S.-+-+'+'+'+-+'+S.S.-+-+'+-+-+-+'+'+-+-+'+-+S.S.x.x.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.:+:+:+4+<+1+4+4+0+7+5+0+8+8+a+9+",
+"o.b.o.g.g.j.m.j.j.m.j.n.n.n.n.n.n.w.B.y.B.t.x.x.x.S.'+'+'+-+'+'+-+S.S.S.S.-+-+'+'+-+-+'+'+-+-+'+'+S.S.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.4+|+|+4+4+b+5+7+9+c+9+a+a+d+a+a+",
+"g.i.j.j.m.e+s.m.n.n.n.w.z.n.z.y.B.B.B.B.D.t.x.x.x.S.'+-+'+'+-+-+'+S.S.S.S.S.S.-+-+'+-+-+-+'+'+-+-+'+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.4+1+b+7+5+7+7+9+9+9+9+a+d+d+f+g+",
+"p.e+s.s.j.n.n.s.n.n.n.y.B.K.y.B.B.D.D.M.F.t.x.x.x.S.'+'+-+-+'+'+-+S.x.S.S.S.S.S.S.-+-+'+'+-+-+'+-+-+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.4+7+0+7+9+9+8+9+a+a+d+g+g+f+f+f+f+",
+"s.n.s.n.n.n.z.z.n.y.y.B.B.B.M.D.D.h+E.F.E.t.x.x.x.S.'+-+'+'+'+-+'+S.x.x.x.S.S.S.S.S.'+-+-+'+-+-+-+'+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.G.i+7+9+9+9+8+a+d+a+g+f+g+g+j+k+k+l+",
+"s.s.n.n.n.y.n.B.B.A.B.D.D.D.I.E.F.F.F.F.J.t.x.x.x.S.'+'+'+-+'+'+-+S.x.x.G.x.x.S.S.S.S.'+'+-+-+'+'+-+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.S.G.8+9+a+9+a+d+f+g+f+m+m+n+m+k+k+o+l+",
+"n.n.z.n.y.H.B.M.D.D.E.D.D.F.E.p+F.J.J.J.L.t.x.x.x.S.'+-+'+'+-+-+'+S.x.x.x.G.G.x.x.S.S.-+-+'+'+-+-+'+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.S.S.G.9+a+a+g+f+f+g+f+n+j+k+m+o+o+l+l+l+",
+"n.y.H.y.B.B.B.I.D.I.F.E.F.J.J.J.J.L.L.L.N.t.x.x.x.S.'+'+'+-+'+'+'+S.x.'+'+x.x.x.G.x.S.'+'+-+-+'+'+-+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.S.S.S.G.a+g+g+g+g+g+j+q+n+o+l+l+o+r+s+t+u+",
+"B.M.D.D.D.I.I.F.I.F.F.J.J.J.J.L.L.L.N.L.N.t.x.x.x.S.'+'+'+'+'+-+'+S.x.'+'+'+'+x.x.x.S.-+-+'+'+-+-+'+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.S.S.S.G.S.S.S.S.G.g+k+k+n+k+l+l+l+r+o+r+s+v+o+w+v+x+",
+"D.D.D.I.y+F.F.J.h+J.J.J.L.L.L.L.N.N.N.Q.Q.t.x.x.x.S.'+'+'+-+'+'+'+S.x.x.x.'+'+'+'+x.S.'+'+-+'+'+'+-+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.G.k+m+n+o+l+o+l+r+r+s+o+s+v+w+w+z+A+",
+"D.E.E.F.F.J.J.J.J.L.L.L.N.L.N.N.Q.V.N.P.R.t.x.x.x.S.'+-+'+'+'+'+'+S.S.x.x.x.x.'+'+x.S.-+'+'+'+-+-+'+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.G.n+l+l+l+o+r+o+o+t+v+v+v+B+x+C+x+D+",
+"E.J.J.J.J.J.J.L.L.L.L.N.E+F+R.R.P.R.R.R.R.t.x.x.x.S.'+'+'+-+'+'+'+-+'+S.S.x.x.x.x.x.S.'+'+-+-+'+'+-+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.G.l+o+s+u+o+r+w+v+w+v+z+z+G+z+C+H+I+",
+"F.J.J.J.L.L.L.N.N.N.P.P.N.R.R.R.R.R.R.U.X.t.x.x.x.S.'+'+'+'+'+-+'+'+'+'+'+S.S.x.x.x.S.-+-+'+'+-+-+'+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.G.r+r+s+w+v+w+A+z+z+C+B+D+D+H+I+J+H+",
+"J.J.L.L.L.L.N.N.N.Q.R.P.P.R.R.R.R.W.R.Z.U.t.x.x.x.t.t.'+'+-+'+'+'+-+'+'+'+-+'+S.S.x.S.'+'+-+'+'+'+-+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.G.w+w+w+x+B+z+C+B+G+C+C+H+I+H+K+L+M+",
+"L.L.N.N.N.N.N.P.R.R.R.R.R.R.T.U.U.U.X.X.Y.t.x.x.x.x.x.t.t.'+'+'+'+'+'+-+'+'+'+'+'+S.S.-+'+'+'+-+-+'+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.G.v+z+z+x+G+D+D+N+O+J+H+P+L+Q+Q+M+R+",
+"L.N.N.N.R.R.P.R.R.R.U.X.R.X.X.S+Y.Y.T+Y.T+t.x.x.x.x.x.x.x.t.t.'+'+'+'+'+'+-+'+'+'+-+'+'+'+-+-+'+'+-+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.S.G.x+B+D+D+C+I+U+J+U+L+Q+L+M+V+V+R+W+",
+"N.N.R.R.R.R.R.T.U.X.R.X.X.Y.Y.Y.T+.+`.!+.+t.x.x.x.x.x.x.x.x.x.t.t.'+'+'+'+'+'+-+'+'+'+'+'+'+'+-+'+'+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.S.S.G.D+C+I+I+J+H+J+Q+L+L+M+V+X+M+Y+Y+Y+",
+"R.P.R.R.R.R.X.X.X.X.X.Y.Y.&+`..+.+.+!+.+Z+t.S.x.x.x.x.x.x.x.x.x.x.t.t.'+'+-+'+'+'+-+'+'+'+-+'+'+'+-+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.G.S.S.S.S.S.S.S.S.S.S.S.G.G.U+I+I+I+P+Q+M+M+M+V+R+`+ @ @W+.@+@Y+",
+"R.R.R.X.U.W.Y.Y.Y.Y.`.Y.`.!+.+.+@+#+@+@+@+G.G.S.x.x.x.x.x.x.x.x.x.x.x.t.t.'+'+'+'+'+'+-+'+'+'+'+'+'+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.G.S.S.S.S.S.S.S.S.S.S.G.G.I+H+K+P+P+Q+L+Q+`+M+Y+X+Y+Y+Y+W+Y+@@@@@@",
+"R.X.U.Y.Y.Y.Y.Y.Y.`..+.+*+@+@+@+>+#@)+)+>+~+,+G.S.S.x.x.x.x.x.x.x.x.x.x.x.t.t.'+'+-+'+'+'+-+'+'+'+-+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.G.S.S.S.S.S.S.S.S.S.G.G.H+I+L+L+L+L+M+M+M+X+`+Y+W+Y+Y++@.@Y+@@@@@@$@",
+"%+U.%+&+Y.`.Y.`..+.+@+@+@+@+>+~+>+,+,+,+]+]+%@_+G.G.S.S.x.x.x.x.x.x.x.x.x.x.x.t.t.'+'+'+'+'+'+-+'+'+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.G.S.S.S.S.S.S.S.S.G.G.H+I+Q+P+L+L+V+R+V+W+W+Y+Y+Y+Y+.@&@.@@@@@*@*@$@=@",
+"Y.-@`.Y. +.+@+@+@+@+#+=+>+)+,+(+,+,+%@]+{+_+:+:+<+|+G.G.S.S.x.x.x.x.x.x.x.x.x.x.x.t.t.'+'+-+'+'+'+-+t.x.x.x.S.S.S.S.S.S.S.S.S.G.G.S.S.S.S.S.S.S.G.G.Q+L+U+Q+Q+V+M+R+R+Y+Y+W++@Y+W+&@@@@@@@$@$@$@;@>@,@'@",
+"`.`. +.+@+.+#+@+=+>+)+)+,+,+,+(+,+{+]+]+:+:+3+:+t.t.x.x.G.G.S.S.x.x.x.x.x.x.x.x.x.x.x.t.t.'+'+'+'+'+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.G.G.K+Q+Q+Q+V+M+M+R+Y+Y+Y+Y+Y+W+Y+@@@@&@*@$@)@*@$@)@=@,@=@'@",
+"@+@+@+.+#+#+=+#@)+(+)+,+,+/+,+{+]+:+<+:+:+:+t.t.x.x.x.x.x.x.G.G.S.S.x.x.x.x.x.x.x.x.x.x.x.t.t.'+'+-+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.G.G.t.U+Q+V+L+`+R+R+W+W+Y+Y+W+Y++@@@&@@@@@$@$@)@!@,@'@'@~@'@{@'@",
+"@+@+=+>+#@)+,+)+,+]+(+,+{+:+]+]+:+3+3+:+t.t.x.x.x.x.x.x.x.x.x.x.G.G.S.S.x.x.x.x.x.x.x.x.x.x.x.t.t.'+t.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.G.G.S.G.G.t.t.R+ @ @Y+W+Y+W+.@.@@@]@&@@@$@)@$@,@,@'@^@=@'@/@(@(@(@_@",
+")+>+>+)+,+,+,+(+%@%@]+_+_+:+<+|+:+<+t.t.x.x.x.x.x.x.x.x.x.x.x.x.t.S.G.G.S.S.x.x.x.x.x.x.x.x.x.x.x.'+t.x.x.x.S.S.S.S.S.S.S.S.S.G.G.G.S.S.S.S.S.G.x.t.t.Y+Y+W++@&@&@&@&@)@)@)@,@,@=@'@'@'@(@~@(@/@_@/@_@:@",
+")+,+^+,+,+{+{+:+}+_+:+|+|+:+<+|+t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.t.S.S.S.S.G.G.S.S.x.x.x.x.x.x.<@<@x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.G.x.x.t.t.@@@@@@$@$@;@$@*@,@,@=@[@^@~@(@/@_@(@_@_@:@:@:@",
+",+,+%@{+]+:+<+}+<+:+<+|+3+3+t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.S.S.S.S.S.S.S.G.G.S.S.x.x.x.x.}@}@x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.G.x.x.x.t.t.*@)@=@=@,@=@=@~@^@|@(@(@_@(@1@_@_@:@:@:@:@",
+"(+{+:+]+:+3+:+3+:+|+:+4+4+4+t.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.t.x.x.x.x.x.S.S.S.S.G.G.S.S.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.G.x.x.x.x.x.t.t.'@=@'@(@{@{@{@/@_@_@2@:@:@:@:@:@2@3@4@",
+"}+]+<+<+:+<+<+|+5@4+4+b+5+7+t.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.t.x.x.x.x.x.x.x.x.S.S.S.G.G.S.S.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.G.x.x.x.x.x.x.x.t.t.(@(@(@_@_@_@_@:@:@2@:@2@4@:@6@3@6@",
+":+<+:+:+:+3+4+4+4+4+4+0+0+0+t.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.t.x.x.x.x.x.x.x.x.x.x.S.S.S.G.G.S.S.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.G.S.S.S.S.S.S.S.S.S.G.x.x.x.x.x.x.x.x.x.t.t._@:@:@:@:@:@:@:@:@4@6@6@7@8@9@",
+":+|+4+|+4+4+0+0+0+c+5+0+9+9+t.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.t.x.x.x.x.x.x.x.x.x.x.x.x.S.S.S.G.G.S.S.x.x.x.x.S.S.S.S.S.S.S.S.G.G.S.S.S.S.S.S.S.S.S.G.x.x.x.x.x.x.x.x.x.x.x.t.G.:@:@:@6@3@6@6@0@a@8@0@8@8@",
+"|+4+1+4+5+0+7+7+c+9+9+a+9+d+t.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.t.x.x.x.x.x.x.x.x.x.x.x.x.x.S.S.S.G.G.S.S.x.x.S.S.S.S.S.S.G.G.S.S.S.S.S.S.S.S.S.S.G.x.x.x.x.x.x.x.x.x.x.S.S.S.G.:@b@c@6@8@8@0@a@9@a@9@d@9@",
+"i+0+7+0+0+c+9+9+a+8+a+d+d+g+t.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.G.t.x.x.x.x.x.x.x.x.x.x.x.x.x.S.S.S.S.G.G.S.S.S.S.S.S.G.G.S.S.S.S.S.S.S.S.S.S.S.S.G.x.x.x.x.x.x.x.x.S.S.S.S.S.G.6@0@6@a@8@e@9@e@f@9@9@g@f@",
+"7+9+5+9+8+a+a+9+a+a+a+g+g+g+t.x.x.x.<@<@x.x.x.x.x.x.x.x.t.x.x.x.G.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.S.S.S.S.G.G.S.S.G.G.S.S.S.S.S.S.S.S.S.S.S.S.S.G.x.x.x.x.x.x.x.S.S.S.S.S.S.S.G.8@0@e@a@9@9@f@f@f@h@i@g@g@",
+"9+8+9+a+d+d+g+f+g+g+g+m+n+k+t.x.x.x.<@<@x.x.x.x.x.x.x.x.t.x.x.x.x.G.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.G.G.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.G.e@9@9@j@k@k@f@i@g@i@g@g@l@",
+"d+9+d+a+g+g+g+f+k+j+m+j+l+l+t.x.x.x.}@}@x.x.x.x.x.x.x.x.x.t.t.x.x.x.G.G.t.t.x.x.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.G.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.G.9@9@f@g@i@i@g@m@n@m@l@o@p@",
+"d+f+g+g+g+q@j+j+n+l+j+l+o+l+t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.G.G.t.t.t.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.G.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.G.f@k@f@g@g@m@l@p@l@m@p@p@r@",
+"g+f+g+j+m+s@n+l+o+l+l+o+l+s+t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.G.G.G.t.t.t.t.t.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.G.G.G.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.G.i@g@g@g@m@o@m@o@o@p@r@t@r@",
+"n+n+n+l+o+o+l+l+o+s+l+v+w+v+t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.G.G.G.G.G.t.t.t.t.t.t.S.S.S.S.S.S.G.G.G.G.G.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.G.G.S.S.G.g@m@p@l@p@p@r@r@r@r@t@t@r@",
+"o+o+l+l+o+s+l+l+w+v+v+w+x+z+t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.G.G.G.G.G.G.G.G.G.G.G.G.x.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.G.G.G.G.S.S.G.m@o@r@r@r@t@t@t@r@r@u@t@u@",
+"o+o+r+l+l+u+v+w+w+v@x+B+A+w@t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.G.G.S.G.S.S.G.p@p@r@r@r@r@r@r@u@x@u@u@x@",
+"o+r+r+s+t+x+v+z+z+B+x+C+D+I+t.S.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.G.S.G.S.S.G.t@t@t@t@t@u@t@u@u@x@y@z@A@",
+"v+w+x+v+v+z+B+A+C+D+H+H+O+I+G.G.S.S.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.G.G.G.S.S.G.t@r@t@u@u@B@x@u@z@C@A@A@D@",
+"v+w+B+x+A+D+C+D+C+H+H+J+I+L+Q+V+G.G.S.S.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.S.G.G.S.S.G.u@u@u@z@B@E@z@A@D@A@F@A@F@",
+"A+D+A+C+C+I+C+H+U+Q+J+Q+L+Q+M+X+ @Y+G.G.S.S.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.S.S.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.G.G.G.S.S.G.x@z@z@z@A@A@D@F@G@H@I@H@J@",
+"w@C+H+I+U+L+K+Q+L+V+`+V+R+M+ @Y+W+Y+W+Y+G.G.S.S.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.S.S.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.G.S.S.S.S.G.z@z@A@K@A@H@H@I@I@I@I@I@I@",
+"U+I+J+J+Q+Q+L+L+V+V+R+Y+X+W+W+.@Y+Y+.@&@@@@@G.G.S.S.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.S.S.x.x.x.x.x.x.x.x.t.t.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.G.A@A@H@F@F@J@I@I@I@I@L@L@M@",
+"Q+Q+I+L+V+Q+V+V+Y+W+W+W+Y+Y+W+&@@@@@@@)@$@)@)@$@G.G.S.S.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.S.S.x.x.x.x.x.x.x.x.t.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.G.A@A@H@N@I@H@J@I@I@I@L@L@M@M@O@",
+"L+V+M+M+V+`+ @W+Y+Y+W+.@W+@@@@&@@@$@)@)@=@=@'@,@^@'@G.G.S.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.S.S.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.G.G@H@H@H@H@I@I@L@I@P@L@M@Q@M@M@O@M@",
+"Q+R+V+M+Y+W+Y+Y+W++@@@&@&@;@)@*@$@,@=@,@'@'@,@[@[@|@(@(@G.S.S.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.S.S.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.G.K@H@H@I@H@I@I@L@L@Q@L@M@M@M@R@Q@S@O@S@",
+"`+`+X+Y+Y+Y+Y+@@Y+@@*@$@$@)@;@>@,@,@'@'@^@(@{@/@(@1@_@_@:@G.G.S.S.x.x.x.x.x.x.x.x.x.x.x.x.x.x.t.t.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.G.F@H@H@T@I@L@I@L@Q@P@M@M@M@Q@O@U@O@R@S@S@V@",
+"Y+Y+W+&@@@]@$@@@*@*@$@>@,@,@,@'@'@'@'@|@(@(@(@(@_@_@:@:@:@:@:@G.G.S.S.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.G.H@H@I@T@I@P@L@L@M@M@M@M@O@R@S@M@S@S@S@W@X@X@X@",
+"+@@@Y+@@@@&@$@)@>@=@!@,@^@'@^@{@/@(@/@_@_@1@1@:@:@:@2@:@:@:@6@6@6@G.G.S.S.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.G.H@I@I@I@I@L@L@M@M@M@M@M@M@O@O@S@S@Y@X@W@X@Z@`@`@`@",
+"@@$@@@ #*@)@!@>@>@,@[@^@[@[@/@(@(@(@1@_@_@:@:@:@2@:@:@:@3@3@8@c@8@a@8@G.G.S.S.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.G.H@H@I@I@L@L@L@M@M@M@M@O@O@O@O@S@S@S@Z@Z@`@W@`@`@`@.#+#",
+"$@)@$@*@!@,@'@'@'@~@{@{@~@(@_@_@_@:@:@:@2@:@2@:@3@:@c@6@8@8@8@a@a@9@9@f@f@G.G.S.S.x.x.x.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.G.G.I@I@I@L@L@P@L@L@M@O@O@Q@M@O@@#S@@#S@X@`@X@X@##`@$#%#$#&#+#",
+"=@>@!@=@,@^@[@[@/@(@*#(@(@_@2@:@:@:@:@:@=#=#=#6@-#c@6@a@;#9@a@e@9@f@9@f@g@i@g@G.G.S.S.x.x.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.S.S.G.G.I@I@L@L@L@L@L@M@M@O@M@U@M@R@V@W@X@W@>###W@`@`@`@$#,#&#&#,#'#)#",
+"=@^@'@[@[@'@[@(@_@_@_@1@2@2@:@:@:@=#2@4@6@3@6@!#a@;#a@e@~#9@9@f@f@i@k@g@g@{#m@l@l@G.G.S.S.x.x.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.S.S.G.G.I@I@L@L@L@M@M@O@Q@O@O@O@S@S@Y@Y@X@X@>###`@##`@.#+#&#&#&#&#&#]#^#^#",
+"'@[@^@/@(@_@_@_@_@_@_@:@:@:@:@:@:@4@3@6@8@8@9@e@e@e@9@9@j@k@i@g@g@i@m@/#m@p@o@p@(#p@r@G.G.S.S.x.x.x.x.x.x.x.S.S.S.S.S.S.S.S.S.G.G.L@L@P@L@L@L@M@M@R@O@S@S@@#W@@#Y@W@X@_#`@.#`@$#+#$#&#&#,#:#]#)#<#^#^#^#",
+"|@(@/@(@1@1@_@2@:@2@:@:@:@:@6@3@6@8@8@8@8@8@e@9@f@f@j@f@g@g@g@[#}#m@m@m@o@p@p@r@r@r@t@r@t@G.G.S.S.x.x.x.x.x.S.S.S.S.S.S.S.G.G.T@T@L@Q@M@Q@Q@M@O@Q@O@S@S@S@Y@W@W@`@`@`@##$#$#$#|#$#,#&#:#)#)#<#^#1#2#2#2#",
+"/@_@_@1@2@:@2@:@:@:@:@4@6@8@6@a@8@e@9@e@f@f@f@f@f@k@g@g@m@m@m@l@m@o@p@r@r@r@t@t@t@t@t@u@u@u@x@G.G.S.S.x.x.x.S.S.S.S.S.G.G.I@L@M@M@L@M@O@Q@S@O@R@S@W@Y@X@`@X@X@`@3#+#.#$#&#+#4#]#5#)#)#]#2#^#1#1#2#6#7#8#",
+"1@1@_@:@2@2@:@:@2@3@3@6@7@8@;#e@a@9@9@f@j@k@g@g@g@i@g@m@m@p@o@p@p@r@p@t@r@t@t@t@u@u@9#u@B@z@z@E@A@G.G.S.S.x.S.S.S.S.G.L@P@P@Q@M@M@O@S@M@O@S@X@Y@X@X@X@Z@`@`@`@.#&#$#+#&#,#,#]#5#0#)#^#2#^#^#^#1#1#a#8#b#",
+":@:@:@:@:@=#6@6@6@6@7@;#e@8@9@9@f@f@k@k@k@g@m@g@m@m@l@l@p@p@o@r@r@r@r@r@u@u@u@u@u@B@z@A@A@A@A@A@H@F@F@G.G.S.S.S.G.G.L@M@M@M@Q@O@S@S@S@S@S@Y@W@##X@3#c#`@%#$#$#+#&#&#5#]#)#]#^#)#1#1#^#1#a#1#d#8#e#f#g#h#",
+":@:@3@6@6@6@6@0@8@8@9@9@9@f@f@j@k@k@i@g@m@m@m@m@m@o@p@o@p@r@r@r@t@r@t@u@u@u@z@B@B@E@A@A@D@K@H@H@I@T@I@L@L@G.G.G.M@M@M@O@O@O@S@S@S@W@X@X@W@>#`@##`@.#%#.#$#,#,#)#)#5#:#)#:#2#2#2#a#8#d#1#8#i#8#g#j#e#j#k#",
+"=#c@8@6@a@a@;#a@9@9@f@f@f@j@g@i@i@m@m@m@l@m@o@p@p@r@t@r@r@r@t@u@t@u@x@E@B@z@z@A@A@K@A@F@J@H@H@I@I@I@L@L@M@Q@M@O@O@M@O@O@O@S@Y@W@Y@`@W@##`@.#c#%#,#$#l#&#&#)#,#:#^#^#2#^#^#a#^#1#a#d#b#e#f#j#m#j#m#j#k#n#",
+"6@a@8@e@8@9@9@f@f@f@f@k@g@g@g@m@m@m@l@m@p@r@r@r@r@r@t@t@u@t@9#u@z@z@z@A@A@D@D@K@G@H@H@J@I@I@I@L@P@M@Q@M@M@M@O@O@S@o#@#Y@S@W@W@W@Z@`@`@.#c#$#$#$#,#,#)#&#)#)#^#2#^#a#1#^#8#1#8#d#b#8#e#b#f#j#j#p#k#n#q#q#",
+"8@a@e@9@d@f@j@f@r#k@{#g@g@}#l@l@o@m@p@p@r@r@t@r@t@r@r@u@u@u@B@B@B@A@z@A@K@H@F@H@H@H@I@I@I@L@L@L@M@Q@Q@O@O@R@O@S@S@W@Y@X@X@Z@3#`@$#+#.#&#l#+#&#,#]#]#]#2#^#^#^#^#6#1#8#d#i#b#i#g#s#j#m#m#k#t#k#u#t#u#q#q#",
+"9@e@f@f@f@f@f@g@n@m@m@l@p@o@p@r@r@p@r@r@r@t@t@t@u@u@u@B@B@B@z@A@v#K@F@F@F@T@T@I@L@L@L@P@L@Q@M@M@O@M@O@U@S@S@S@W@X@`@`@`@`@##`@$#$#l#$#,#'#&#'#0#:#2#2#2#^#1#d#8#8#b#e#b#f#e#f#m#m#m#j#u#k#w#u#q#x#x#x#y#",
+"f@f@f@r#g@g@g@m@m@l@l@l@p@r@r@r@r@t@r@t@t@u@u@u@u@B@z@z@A@A@A@K@J@H@H@I@T@L@L@L@L@L@M@M@O@O@M@M@S@S@S@Y@S@@#z#`@##`@`@%#$#$#l#,#&#&#&#)#2#:#)#^#^#1#^#1#a#d#8#e#e#e#j#j#j#m#j#t#p#q#A#u#q#q#B#y#B#C#y#C#",
+"i@k@i@m@g@m@o@m@p@p@r@r@p@r@r@t@t@t@u@u@B@x@B@z@A@A@A@t.t.F@H@H@I@T@I@I@L@L@Q@M@Q@M@M@Q@O@S@@#S@S@S@X@Z@X@`@##3#3#$#$#+#$#+#&#]#)#:#^#2#)#a#a#2#^#8#a#8#8#8#e#g#g#f#j#k#t#t#t#q#u#u#x#q#x#B#y#C#y#y#D#D#",
+"g@m@m@m@l@o@p@p@r@r@r@t@t@r@t@u@u@B@u@B@B@z@z@A@A@t.t.t.t.t.t.T@L@P@L@M@L@M@M@M@O@O@S@U@S@@#W@W@X@`@`@####`@%#$#+#&#&#&#]#5#5#)#)#^#2#1#1#^#8#1#t.t.8#g#g#g#f#m#m#n#k#k#t#n#q#u#B#B#y#B#y#y#C#y#y#y#E#F#",
+"m@p@o@p@p@r@r@r@t@r@t@t@t@u@u@u@B@z@B@C@A@A@A@t.t.x.x.G#G#t.t.t.t.P@M@M@O@O@M@S@O@S@@#>#W@W@_#`@X@c###.#$#+#l#&#'#&#'#)#)#2#2#a#a#^#a#1#d#8#t.t.t.t.t.t.m#j#m#H#p#t#t#u#q#q#u#x#B#y#B#C#y#D#I#F#I#J#K#L#",
+"o@p@p@r@t@r@t@r@t@t@t@u@u@x@u@z@D@z@A@A@K@t.t.x.x.x.x.x.x.G#G#t.t.t.t.M@M@@#S@@#V@X@X@_#`@`@c#`@%#+#$#%#&#&#5#&#:#2#:#:#^#2#2#a#1#^#8#8#t.t.x.x.G#G#t.t.t.t.p#u#q#q#B#x#B#B#x#y#y#C#I#C#D#I#F#J#J#K#K#M#",
+"p@r@r@r@t@r@t@t@t@x@u@u@B@z@A@K@A@H@H@t.t.x.x.x.x.x.x.x.x.x.x.G#G#t.t.t.t.S@X@S@X@X@`@##+#.#$#$#$#&#&#)#]#:#]#]#)#^#1#1#2#a#8#1#d#d#t.t.x.x.x.x.x.x.G#G#t.t.t.t.B#B#B#x#y#y#C#C#I#D#I#F#F#L#J#M#N#N#O#P#",
+"r@r@r@t@r@x@u@B@u@u@z@A@z@A@A@K@H@t.t.x.x.x.x.x.x.x.x.x.t.t.x.x.x.G#G#t.t.t.`@Z@`@$#3#.#$#$#,#,#&#&#)#]#0#:#2#^#1#^#a#1#8#d#d#e#b#t.x.x.x.x.x.x.x.x.x.x.G#G#t.t.t.t.y#y#C#y#I#C#F#J#J#K#M#M#P#O#O#Q#Q#R#",
+"t@9#t@u@u@z@z@z@z@A@A@K@H@J@S#t.t.x.x.S.S.S.x.x.x.x.x.t.S.S.t.x.x.x.x.G#G#t.t.t.+#.#$#,#$#&#,#5#:#)#)#^#^#^#1#^#1#d#1#8#b#e#g#t.t.x.x.x.x.x.x.x.x.t.t.x.x.x.G#G#t.t.t.t.y#D#J#F#J#L#L#O#O#O#O#T#U#R#T#V#",
+"u@z@u@z@z@A@z@A@A@J@H@H@I@T@t.x.x.S.S.S.S.S.S.S.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.S.G.&#&#&#:#)#:#)#0#2#^#1#1#d#1#7#8#i#8#f#g#t.t.x.x.S.S.x.x.x.x.x.t.S.S.t.x.x.x.x.G#G#t.t.t.t.K#M#M#M#M#O#R#T#Q#W#V#V#V#X#",
+"y@z@B@z@A@K@H@H@J@H@I@H@I@L@G.S.S.x.x.S.S.S.S.S.S.t.t.x.x.x.x.x.x.x.x.x.x.x.S.S.G.'#)#]#)#)#2#2#1#1#1#a#1#d#8#d#b#e#s#m#t.x.x.S.S.S.S.S.S.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.S.G.O#P#R#T#T#R#W#V#W#Y#Y#X#Y#",
+"A@A@A@K@J@J@I@G@H@I@L@L@L@L@P@G.G.S.S.x.x.G.S.t.t.t.t.t.t.x.x.x.x.x.x.x.x.S.G.G.:#0#^#^#^#2#^#1#a#a#d#b#d#g#g#g#m#j#Z#Z#G.S.S.x.x.S.S.S.S.S.S.x.x.x.x.x.x.x.x.x.x.x.x.x.S.S.G.R#T#T#`#V#W#V#X# $.$X#+$+$",
+"A@K@H@H@J@T@I@I@L@L@L@M@L@Q@M@O@M@G.G.S.S.t.t.G.x.x.G#t.t.t.t.x.x.x.x.S.S.G.)#]#^#^#^#a#1#a#a#8#d#g#f#f#m#f#j#m#Z#t#p#k#u#G.G.S.S.x.S.S.S.G.G.S.S.x.x.x.x.x.x.x.x.x.S.S.G.G.Q#T#V#W#W#X#.$Y#Y#X#+$+$@$#$",
+"H@H@I@I@I@T@P@P@L@Q@O@M@Q@M@O@O@Q@S@S@t.t.x.x.x.x.x.x.G#G#t.t.t.t.S.S.G.G.2#1#1#^#^#d#7#8#d#8#8#f#b#e#h#j#j#k#n#q#u#q#x#q#x#B#G.G.S.x.x.G.G.S.S.x.S.x.x.x.x.x.x.S.S.G.G.U#W#T#V#.$.$$$+$+$+$+$+$+$%$%$&$",
+"I@L@I@I@L@L@M@M@M@M@O@O@O@@#@#S@S@t.t.x.x.x.x.x.x.x.x.x.x.G#G#t.t.t.t.^#^#^#a#2#1#d#d#e#d#e#f#m#e#m#m#k#k#t#n#u#u#q#x#B#C#B#B#C#y#G.S.S.x.x.G.G.S.S.x.x.x.x.S.S.G.G.T#W#V#.$Y#*$@$@$+$+$+$+$+$#$=$%$-$;$",
+"L@L@L@L@M@O@M@M@Q@R@S@S@S@S@Z@t.t.x.x.x.x.x.x.x.x.x.t.t.x.x.x.G#G#t.t.t.t.1#1#d#8#b#b#g#b#s#m#t#p#j#t#n#u#q#q#u#B#x#x#x#y#y#C#D#I#D#G.G.S.S.G.G.x.x.x.x.S.S.G.G.V#V#X# $X#$$+$+$@$+$+$%$=$%$=$-$;$=$>$>$",
+"M@M@O@Q@O@M@O@S@@#S@S@X@W@t.t.x.x.S.S.S.x.x.x.x.x.t.S.S.t.x.x.x.x.G#G#t.t.t.d#d#e#j#m#j#H#k#k#k#q#u#u#u#q#B#B#B#C#C#C#y#y#D#D#I#J#J#K#K#G.G.S.S.x.x.G.S.S.G.V#.$V#.$Y#Y#+$@$%$%$%$+$+$=$=$=$-$,$'$)$)$!$",
+"M@O@O@M@M@S@V@X@X@W@X@`@t.x.x.S.S.S.S.S.S.S.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.x.G.h#e#H#Z#j#p#n#n#u#x#x#B#B#x#C#y#y#y#C#D#I#I#F#K#F#M#K#M#M#~$P#G.G.S.S.G.G.V#V#.$.$*$$$+$+$+$#$%$%$%$=$=$>$,$>$>$!$!$)${$]$",
+"Q@M@@#S@@#Y@S@##Z@`@`@c#G.S.S.x.x.S.S.S.S.S.S.S.x.x.x.x.x.x.x.x.x.x.x.x.x.S.G.j#n#t#k#q#n#q#u#x#x#C#C#B#y#y#y#t.t.J#F#F#^$K#M#N#P#O#R#O#Q#Q#U#R#G.G..$V#.$+$+$X#+$+$@$#$-$=$%$=$>$>$;$/$)$)$)$)$($_$:$<$",
+"@#@#Z@X@X@z#`@`@`@.#c#$#&#G.G.S.S.x.x.S.S.S.G.G.S.S.x.x.x.x.x.x.x.x.x.S.S.G.n#t#t#t#n#B#B#B#x#x#C#y#y#I#D#t.t.t.t.t.t.L#P#P#N#O#P#R#U#T#W#W#V#Y#X#.$*$@$+$@$+$+$+$%$@$=$=$-$;$>$/$)$)$)$)$]$]$_$<$<$<$[$",
+"S@Y@X@`@`@`@$#$#+#$#,#,#&#,#)#G.G.S.S.x.x.G.S.S.x.x.S.x.x.x.x.x.x.S.S.G.G.t#q#A#u#x#B#x#x#y#y#C#C#C#I#t.t.x.x.G#G#t.t.t.t.O#R#Q#U#W#T#V#.$.$X#.$+$+$}$+$+$%$+$-$=$-$=$=$>$/$)$)$!${$_$_$($($<$<$<$[$<$|$",
+"Z@X@`@.#.#.#$#$#&#&#,#&#)#5#:#0#2#G.G.S.S.x.x.G.S.S.G.x.x.x.x.S.S.G.G.q#q#B#q#x#x#B#y#C#C#I#C#I#I#t.t.x.x.x.x.x.x.G#G#t.t.t.R#T#W#.$V#Y#+$+$@$@$+$@$+$1$%$%$&$-$/$>$/$/$)$)$)$]$]$($($<$<$[$<$[$[$[$|$|$",
+"`@`@.#$#.#$#&#]#'#]#]#)#:#2#^#1#1#1#d#G.G.S.S.G.G.x.x.x.x.S.S.G.G.q#u#B#x#B#B#y#C#D#I#y#I#2$F#t.t.x.x.x.x.x.x.x.x.x.x.G#G#t.t.t.V#.$Y#Y#*$@$+$+$#$=$%$1$=$=$;$,$)$)$)$)$)$]$($<$]$($<$<$[$[$[$[$|$|$3$3$",
+"$#,#,#'#&#'#]#:#)#0#^#2#^#a#a#1#1#1#e#b#e#G.G.S.S.x.x.G.S.S.G.q#B#q#B#x#x#B#C#C#C#y#I#F#I#t.t.x.x.x.x.x.x.x.x.x.t.t.x.x.x.G#t.t.t.t.+$+$+$%$@$+$-$=$=$,$/$>$/$)$'${$]$($:$_$<$<$[$[$[$[$|$|$|$3$4$5$5$5$",
+"&#]#&#,#:#)#)#:#2#^#a#1#8#^#8#8#i#6$f#g#s#m#m#G.G.S.S.G.G.q#x#q#x#C#C#C#C#y#y#D#I#F#F#t.t.x.x.S.S.S.x.x.x.x.x.t.S.S.t.x.x.x.G#G#t.t.t.t.%$=$=$=$/$>$/$)$!$)$)$)$($]$($<$7$7$<$[$8$|$|$|$5$5$5$5$5$4$4$9$",
+"]#)#2#:#^#2#^#^#2#2#1#7#8#8#8#g#g#s#f#j#m#Z#p#n#t#G.G.q#x#x#B#C#C#C#y#C#D#y#C#F#J#K#t.x.x.S.S.S.S.S.S.S.x.x.x.x.t.t.x.x.x.x.x.x.x.x.x.S.G.=$=$>$/$)$!${$)$]$($]$($<$7$<$[$[$|$|$|$|$5$5$5$5$4$4$9$9$0$9$",
+":#^#^#2#a#^#1#7#d#8#e#e#8#g#g#s#m#Z#k#p#k#n#A#q#B#x#x#x#x#C#C#D#C#I#I#D#I#J#a$a$K#~$G.S.S.x.x.S.S.S.S.S.S.S.x.x.x.x.x.x.x.x.x.x.x.x.S.S.G.>$;$)${$]$]$($]$<$($<$[$[$[$[$[$|$|$|$5$4$4$5$4$4$9$0$9$b$b$b$",
+"^#^#^#a#1#d#8#d#g#b#b#g#g#j#j#Z#k#k#t#q#q#u#u#B#B#B#B#y#y#I#y#J#2$J#F#^$a$M#L#c$P#O#P#G.G.S.S.x.x.S.S.S.G.G.S.S.x.x.x.x.x.x.x.x.S.S.G.G.!${$)$]$_$<$($:$:$[$[$[$8$8$|$3$|$5$5$5$5$4$4$4$9$9$b$9$d$b$e$e$",
+"^#1#1#8#i#f#i#e#j#j#j#j#m#n#k#u#n#w#u#B#q#x#y#C#C#C#y#D#I#C#E#F#L#K#K#N#K#c$O#O#R#R#U#T#T#G.G.S.S.x.x.G.S.S.x.x.S.x.x.x.x.x.S.S.G.G.!${$]$)$]$:$7$<$<$[$[$|$[$3$|$|$5$5$4$5$4$5$4$9$4$9$d$b$b$b$e$e$f$e$",
+"^#8#b#e#g#f#f#j#j#j#m#t#u#w#u#q#u#u#x#B#x#C#C#y#C#D#I#I#2$F#J#K#M#M#L#P#P#P#Q#R#`#V#V#V#W#Y#Y#G.G.S.S.x.x.G.S.S.G.x.x.x.x.S.G.G.)$)$]$_$($]$g$<$<$[$[$|$|$|$5$5$5$5$4$5$4$4$9$9$9$b$d$b$e$e$b$e$f$f$h$h$",
+"8#f#e#g#j#j#Z#n#H#t#A#q#q#u#B#B#x#x#C#y#I#y#y#J#D#J#J#K#F#M#M#c$O#P#O#R#R#R#T#V#W#Y#.$.$X#+$+$+$@$G.G.S.S.G.G.x.x.x.x.S.S.G.)$]$($<$<$7$7$<$[$[$[$[$|$|$5$4$4$5$5$4$4$9$i$0$9$d$b$b$e$e$f$e$j$h$k$k$k$k$",
+"f#b#m#j#k#p#p#A#n#u#B#x#B#B#C#y#y#y#y#D#I#I#I#K#M#K#L#K#M#O#O#Q#O#R#U#T#V#V#V#X#.$.$X#+$+$@$+$%$=$+$-$G.G.S.S.x.x.G.S.S.G.]$]$<$:$:$[$<$[$[$[$|$|$l$5$5$5$5$5$4$4$4$9$b$d$b$b$b$b$e$e$h$j$h$k$m$m$k$n$o$",
+"j#Z#p#p#t#u#u#q#q#x#x#x#C#y#y#C#y#D#F#F#J#J#J#K#K#K#O#O#O#P#R#V#`#T#p$V#Y#*$.$.$$$+$@$+$+$1$+$%$=$>$-$/$>$G.G.S.S.G.G.($_$($<$[$<$[$8$[$3$|$|$5$5$5$4$4$4$9$9$0$9$d$b$b$b$e$e$f$h$j$h$h$k$k$k$k$m$n$q$r$",
+"k#u#n#u#u#x#q#B#y#C#B#y#D#I#D#F#D#J#J#J#N#K#K#N#P#O#R#T#R#U#`#V#V#.$X#.$Y#+$@$+$%$+$%$&$=$+$=$>$>$/$,$)${$)$)$G.G.($<$<$<$<$[$[$|$|$|$|$5$|$4$5$4$4$4$4$9$0$0$b$9$b$b$e$e$f$h$h$h$k$h$k$n$o$n$n$r$s$r$r$",
+"u#q#q#B#q#x#B#y#y#C#C#D#y#D#F#F#L#N#L#~$L#M#P#P#U#R#T#T#W#V#V#V#.$Y#@$@$+$+$%$@$+$%$&$=$t$>$/$)$;${$]$]$u$($]$]$<$<$8$8$[$[$8$|$|$|$|$4$5$4$4$4$9$9$0$9$b$d$d$b$f$e$e$f$h$h$k$k$m$o$n$n$n$n$r$r$r$r$v$s$",
+"u#x#B#B#x#C#y#I#y#D#J#F#F#^$J#M#M#O#O#O#O#O#w$U#T#U#V#W#V#*$Y#X#Y#+$@$+$@$%$@$=$&$=$=$>$/$)$,$)$]$_$]$]$<$<$<$<$[$[$[$|$|$|$5$x$x$4$5$4$4$4$0$0$d$9$b$e$e$f$j$e$f$j$h$y$h$k$o$m$n$q$n$r$s$r$s$s$v$z$z$z$",
+"y#B#y#C#C#D#I#I#D#J#K#J#L#N#K#P#O#P#T#w$U#p$W#W#.$Y#.$+$}$+$@$+$@$@$#$-$=$=$=$>$>$)$)$)$!$)${$_$u$<$($<$[$[$[$[$|$|$|$x$4$l$4$4$5$4$4$9$0$A$d$0$b$b$f$e$f$e$h$B$h$k$m$k$o$o$n$r$n$s$s$r$r$v$s$s$s$C$D$E$",
+"C#y#y#I#F#D#F#F#J#K#M#~$~$M#P#Q#R#Q#T#V#V#V#*$.$X#*$+$$$@$+$+$@$%$=$&$=$=$>$/$>$/$)$]$($]$_$($<$:$<$[$[$[$|$|$3$5$4$4$5$F$4$4$4$9$9$0$d$b$b$b$e$f$e$h$h$h$h$y$h$m$B$n$n$n$r$r$s$s$s$v$v$z$C$z$z$G$G$E$D$",
+"I#J#F#J#J#K#J#M#O#O#O#O#P#T#U#T#T#V#W#V#X#.$+$@$@$+$@$%$#$&$=$#$=$=$/$>$>$)$)$]${$)$]$:$<$<$[$[$[$[$[$|$[$|$|$4$5$5$4$4$4$9$9$9$b$b$b$b$b$e$e$e$e$h$k$h$k$k$n$m$n$n$r$r$r$s$s$r$s$s$z$H$C$C$G$I$G$I$J$K$",
+"J#J#a$F#M#M#N#P#P#R#P#R#`#V#V#X#.$X#X#.$@$$$@$+$+$@$@$+$-$=$=$>$,$/$)$/$)$]$]$]$<$<$($<$<$[$[$[$[$3$|$5$5$5$4$4$5$9$9$4$0$d$b$b$b$b$e$f$L$h$j$k$h$k$k$k$k$n$n$r$r$s$s$s$M$r$s$z$z$z$z$N$G$G$G$I$I$I$K$O$",
+"K#K#N#K#O#O#P#O#Q#Q#Q#V#V#P$.$.$Y#Y#$$$$+$@$%$#$=$%$=$>$>$=$/$)$)$)$)$)$($]$<$<$<$7$[$[$|$[$|$|$|$5$5$5$5$4$4$4$4$9$9$0$d$b$e$b$e$j$f$y$h$h$Q$k$o$R$n$n$n$n$r$r$s$s$s$s$z$z$E$z$E$D$I$I$I$I$S$K$K$T$K$T$",
+"K#~$P#O#P#T#Q#T#V#W#P$V#P$X#*$+$Y#@$@$+$#$%$=$-$=$>$=$>$>$/$)$]$]$_$_$($($:$<$[$[$[$|$[$|$|$|$5$x$4$4$5$4$4$9$9$U$V$b$b$b$f$h$f$j$h$h$y$h$m$k$o$o$n$r$n$s$r$s$s$s$v$C$z$z$G$C$G$G$G$S$S$K$S$W$K$O$T$X$T$",
+"P#O#T#T#R#T#`#W#W#.$*$+$+$@$+$+$%$#$%$&$=$-$=$Y$/$;$>$)$)$($]$]$($<$<$7$[$[$[$[$[$|$|$5$5$5$4$5$4$4$9$9$9$0$9$0$b$b$e$e$e$h$h$h$k$h$k$n$o$Z$o$n$n$r$s$r$s$v$z$z$H$C$C$E$G$I$I$I$J$I$K$K$K$K$O$O$T$`$ %.%",
+"R#R#R#W#W#.$.$.$+$*$+$@$+$@$#$%$&$%$=$>$,$/$,$)$'$)$]$)$]$:$:$<$<$[$[$[$[$[$|$|$5$F$5$5$4$5$4$9$4$9$0$d$d$b$e$b$e$f$e$f$h$k$h$k$k$n$o$n$n$n$r$s$s$v$z$s$s$z$z$z$E$D$+%G$I$@%J$#%S$K$T$T$T$X$ % % %$%%%.%",
+"W#V#.$.$.$.$+$+$$$+$+$+$%$%$=$=$=$>$>$!$;$)$)$)$)$u$($<$:$<$8$[$[$[$[$3$|$|$|$|$x$F$4$4$4$4$9$9$b$b$b$b$e$e$h$j$h$h$h$k$m$k$m$n$n$r$r$M$M$r$M$s$r$z$z$z$z$E$G$G$D$G$I$J$S$#%K$K$T$T$ %`$&%.% %%%.%.%%%.%",
+"V#Y#.$Y#+$@$+$+$@$#$-$=$-$=$Y$/$/${$!$)$)$)$($]$]$:$<$<$[$[$[$[$|$|$|$5$5$4$4$4$4$*%4$4$9$9$d$b$b$e$f$e$f$h$h$h$k$k$k$k$n$n$o$M$r$s$r$s$s$z$H$H$C$E$E$E$E$G$J$J$I$S$K$K$T$K$O$`$X$ %&% %.%.%.%%%.%.%=%%%",
+"+$@$+$+$+$+$+$=$=$=$=$>$>$/$/$!$;$)$)$]$]$($<$<$<$<$[$[$[$|$|$|$5$4$4$4$5$5$4$9$9$0$0$0$d$b$e$e$f$f$h$h$h$h$h$k$o$B$o$q$r$r$s$s$s$s$z$s$z$z$C$G$C$G$N$I$@%S$I$K$S$K$T$T$ % %`$ %.% %.%.%%%.%.%.%=%=%-%-%",
+"+$@$+$+$1$-$=$=$,$=$>$!$>$)${${$)$]$($]$<$7$<$<$[$[$3$|$|$|$4$5$4$4$4$4$4$9$9$0$9$b$d$b$e$e$j$h$h$h$h$h$k$n$n$n$n$n$r$s$v$r$r$s$z$z$z$G$C$C$G$@%I$J$I$K$S$K$K$T$X$&%T$$% % %.%$%%%.%.%%%.%.%.%;%>%,%'%-%",
+"+$-$=$%$=$=$/$/$/$>$)$)$)$_$]$]$($7$<$<$[$[$[$|$3$5$|$5$4$x$5$4$4$9$9$0$0$d$d$b$b$e$e$f$L$j$h$h$k$m$k$m$m$n$r$n$r$s$s$s$M$s$z$z$z$G$G$D$D$@%I$I$S$K$)%K$K$O$T$&% %$%%%.%%%.%.%.%.%=%.%=%;%-%!%,%,%~%,%~%",
+"-$=$;$=$t$>$)$)$)$)$($)$($<$:$<$[$[$[$[$[$|$|$5$5$4$5$5$5$5$9$9$9$0$9$d$b$b$e$e$f$e$h$h$h$h$h$o$o$k$n$o$r$r$s$r$s$s$s$s$z$C$z$D$G$G$I$@%I$I$S$K$K$K$T$T$`$X$ %`$ % %.%%%%%.%.%.%.%.%=%'%>%'%'%'%{%]%{%]%",
+">$/$/$/$,$/$)$]$^%]$]$:$<$:$<$[$[$[$[$3$|$|$|$5$5$5$4$4$9$i$9$9$d$d$b$b$e$e$e$f$h$h$k$k$m$m$m$n$n$r$s$r$r$s$r$s$s$z$z$z$G$E$D$G$@%I$I$K$K$K$K$T$T$O$&%$% % % %.%%%.%.%.%=%=%=%=%>%-%'%/%{%{%~%]%(%_%(%:%",
+">$;$,$)${$)$($]$($<$<$8$[$[$8$[$|$|$|$5$5$5$4$4$4$9$9$9$d$b$b$b$e$e$f$e$f$h$h$k$h$k$o$m$m$n$n$n$r$r$r$r$s$z$z$z$z$E$G$D$I$I$<%S$K$)%K$T$T$T$&%&%$%$%`$.% %.%.%%%.%=%;%;%!%;%'%,%[%-%{%~%{%{%}%|%]%|%(%1%",
+"{$)$_$]$]$7$u$<$[$[$[$[$|$|$|$5$4$4$4$5$4$4$4$4$9$0$b$b$b$e$e$e$e$e$j$h$h$m$m$B$k$n$n$n$n$M$s$s$s$r$z$s$z$C$C$C$D$+%I$I$I$K$)%S$T$K$O$2%&%&%$%&% %.%.%.%.%.%;%%%=%;%=%=%'%,%,%{%~%}%_%]%(%3%|%3%:%4%5%5%",
+"]$($($_$<$<$[$8$[$[$|$|$|$|$5$5$4$5$4$9$9$9$0$b$b$b$b$b$e$j$f$j$j$h$h$k$o$m$R$q$r$n$r$r$s$r$r$s$s$z$H$G$C$G$G$I$I$I$J$I$K$T$)%T$T$2%`$T$$%.%.%%%.%%%.%.%%%=%=%>%,%,%[%'%{%_%(%{%{%(%|%:%3%3%6%4%4%1%5%7%",
+"_$<$<$<$<$[$[$[$|$3$5$4$x$5$4$4$4$4$9$d$d$0$0$b$b$b$f$f$e$h$h$h$k$m$m$n$n$n$r$s$M$r$s$r$v$s$z$z$G$8%G$G$I$I$I$J$I$K$K$T$O$T$T$$%T$.%%%%%.%.%%%.%.%.%=%=%>%>%-%[%~%,%~%~%~%(%(%(%|%3%3%3%:%6%1%9%6%9%0%7%",
+"[$[$[$8$[$3$|$5$3$5$5$4$5$4$U$9$0$9$b$b$b$e$e$e$e$f$h$h$y$k$m$m$k$n$o$r$M$s$r$r$s$v$s$H$z$E$N$G$D$I$I$@%J$<%S$S$)%K$a%X$ %&%$%b%$%.%.%.%%%%%.%.%=%>%=%-%'%-%[%~%{%{%{%|%]%|%3%:%5%:%3%4%6%6%7%9%9%0%9%c%",
+"[$|$[$|$5$5$5$5$4$4$4$9$9$4$b$d$d$b$e$b$e$j$h$j$h$k$k$k$k$o$n$n$n$n$r$s$s$s$s$v$C$H$z$E$D$E$G$D$I$J$S$K$J$K$T$T$T$`$&% % %.%.%.%.%.%.%.%=%%%;%=%>%,%'%,%,%~%~%]%|%]%]%d%3%:%:%e%6%1%6%4%9%0%0%0%9%7%0%f%",
+"|$|$5$5$5$4$4$4$9$9$0$9$0$b$b$e$e$b$f$h$f$h$h$h$k$k$Z$o$n$r$q$s$r$r$r$s$s$z$z$z$G$G$G$D$G$g%I$K$@%K$K$K$K$$%T$O$ %$%.% %%%.%%%%%%%=%.%.%>%>%,%,%-%{%{%{%]%]%(%|%|%3%3%6%3%e%6%9%6%c%7%0%0%c%c%0%f%f%h%h%",
+"|$5$4$4$4$4$4$9$9$9$b$b$b$e$f$i%f$f$j$h$k$h$k$m$k$n$n$q$j%s$s$r$r$z$s$z$z$C$G$G$D$@%G$I$I$K$)%K$S$T$O$O$X$&% % %k%%%.%.%.%.%;%;%=%=%;%!%-%,%'%{%{%{%|%|%|%(%:%:%3%5%6%4%l%6%7%c%9%9%7%7%f%f%f%h%m%n%n%o%",
+"x$4$4$4$9$0$b$0$b$b$b$b$f$j$j$e$j$k$k$k$R$o$o$n$n$n$s$r$r$s$s$v$s$z$E$E$C$G$I$I$I$I$J$K$K$)%T$T$2%O$O$ % %$%.%.%.%%%.%.%.%;%=%;%;%,%{%/%{%{%~%|%]%]%(%3%3%1%e%:%4%5%7%9%9%7%c%0%c%9%f%h%h%f%p%q%p%r%q%q%",
+"4$9$9$0$b$b$b$b$e$e$e$f$j$j$k$h$h$R$k$n$n$o$n$r$r$s$r$s$H$z$z$z$E$C$D$I$I$@%S$I$I$K$T$K$T$`$X$$%$%$% %.%.%%%.%.%%%.%%%=%=%;%,%s%,%{%{%~%~%(%]%}%|%3%1%3%3%4%l%t%7%9%9%0%7%9%h%f%f%m%u%n%r%p%r%r%q%q%q%v%",
+"9$0$b$b$b$b$e$e$e$f$h$h$h$k$k$k$n$n$r$n$r$r$r$r$s$s$z$z$z$z$G$C$D$I$I$I$J$K$K$K$)%T$T$X$ %&%&%.%%%.%%%%%%%.%%%=%;%=%-%-%-%'%~%{%~%{%]%|%|%(%:%3%e%4%1%4%9%6%9%9%0%9%9%c%7%f%f%h%p%r%r%o%p%q%w%x%x%w%v%y%",
+"d$b$e$e$f$f$L$h$h$k$k$k$m$o$n$z%n$q$r$r$r$s$s$s$z$z$E$E$G$G$@%I$J$I$S$S$S$K$T$O$X$$% %$% %.%%%%%.%%%%%.%.%!%>%;%-%'%'%'%{%{%(%|%~%3%]%3%:%:%3%1%4%6%6%9%c%9%7%0%f%c%h%f%h%m%h%A%o%r%o%q%x%v%y%B%C%C%D%E%",
+"e$e$e$e$f$h$h$k$k$k$o$o$o$r$j%r$s$M$s$s$s$z$z$z$G$G$G$G$I$J$S$K$S$K$O$T$T$&%2%&% %$% %.%.%.%.%.%=%.%=%=%!%>%,%{%,%,%F%{%F%|%(%|%|%3%6%3%3%5%6%7%9%c%7%7%9%0%h%f%h%f%A%n%A%o%p%p%o%o%y%w%x%D%D%C%G%H%D%I%",
+"f$j$h$k$k$k$Z$m$m$n$r$r$r$r$r$s$s$s$z$z$z$z$z$G$I$I$g%I$J$K$#%K$)%T$&%X$&%X$ %$%.%.%.%.%%%%%.%=%=%>%>%'%'%,%~%~%]%}%{%]%3%|%3%3%5%6%5%9%6%7%7%7%0%9%c%c%f%h%h%f%A%r%r%r%p%q%J%v%y%y%C%C%C%C%I%K%I%L%M%N%",
+"h$h$m$k$o$n$o$r$r$n$M$r$M$s$M$s$v$z$z$G$E$E$G$I$I$I$<%#%K$O$T$O$X$&%&% %$%$%%%.%%%.%.%=%=%=%>%-%[%-%,%{%{%_%{%(%}%|%3%:%3%O%:%4%5%4%9%9%7%9%0%0%0%c%h%h%f%n%n%P%r%o%o%q%Q%v%C%w%y%D%C%H%C%I%I%N%M%N%N%M%",
+"k$o$n$n$n$r$s$s$s$r$r$r$z$z$z$z$D$N$G$@%I$I$I$K$K$)%K$O$T$X$$%&%.% %.%.%%%%%.%%%.%.%;%-%>%,%-%,%{%,%_%{%|%(%]%|%:%:%3%3%O%5%6%4%4%7%0%7%c%0%9%c%f%A%f%p%r%q%q%q%o%w%v%y%y%v%D%C%C%G%I%H%N%H%N%N%R%S%S%S%",
+"n$o$n$n$s$s$s$v$s$v$z$z$H$E$G$G$E$I$I$I$<%S$K$)%T$2%O$T$&%&% %$%.%.%.%.%.%.%;%;%=%-%[%[%{%'%~%~%}%{%|%}%|%|%3%3%4%5%4%l%4%4%c%9%0%9%c%T%c%f%n%f%h%A%o%r%q%o%Q%y%w%w%C%C%C%I%C%E%E%I%M%N%S%N%S%R%S%R%S%S%",
+"r$r$v$s$s$U%s$H$z$C$G$G$D$G$I$G$@%I$@%K$S$T$T$X$&%X$ %.%$%.%.%.%%%%%.%;%%%;%[%-%,%'%'%{%{%{%F%}%|%(%:%:%3%e%:%4%4%6%9%7%c%9%c%0%0%0%m%h%f%h%r%r%r%q%q%w%o%x%v%C%y%D%D%I%H%H%E%H%N%N%N%S%N%S%R%S%S%V%S%S%",
+"v$r$s$s$v$H$z$8%N$8%I$G$@%I$I$S$K$)%)%O$X$X$T$ %.% % %.%.%.%.%.%.%=%;%=%[%[%,%'%~%{%~%{%|%F%|%|%3%3%5%O%4%4%6%6%9%7%7%0%0%0%T%f%h%n%n%p%p%r%q%q%q%x%x%y%w%x%C%W%I%H%I%K%N%N%M%N%R%R%R%R%R%S%R%S%X%X%X%Y%",
+"M$z$z$C$z$z$G$G$I$I$@%I$I$K$K$T$X$T$T$`$2% % %.%%%.%.%.%%%=%.%;%=%-%[%,%'%,%'%_%F%]%|%(%(%3%:%O%O%3%6%6%6%9%7%c%0%9%c%f%h%m%f%h%f%P%n%q%q%w%w%J%y%v%y%D%D%C%C%I%H%K%H%N%N%R%N%R%S%S%S%S%S%S%Y%Y%X%Z%Z%`%",
+"H$C$z$E$G$E$I$I$I$)%J$K$O$T$T$X$X$`$ %&% %.%.%.%.%.%.%=%;%!%-%,%,%'%[%{%{%{%(%|%}%}%:%3%3%4%O%1%7%4%9%7%7%9%7%0%c%h%h%m%n%u%p%r%p%p%o%o%w%v%D%v%y%D%C%D%I%K%E%N%M%N%N%R%N%R%S%S%S%X%R%R% &V%Y%.&.&`%+&@&",
+"8%G$G$I$@%I$J$@%K$K$K$)%T$T$O$&% %$%%%.%.%%%%%.%.%=%>%=%>%'%'%'%-%{%{%}%|%(%:%|%|%3%6%1%1%6%9%7%7%c%9%0%0%0%9%f%h%h%r%p%r%r%o%q%o%x%w%w%C%#&C%I%E%K%H%K%N%L%N%N%N%S%S%S%S%S%R%X%Y%X%Y% &.&Z%.&@&$&%&%&+&",
+"G$&&I$J$S$K$S$T$O$T$X$T$$% % %%%.%.%.%%%%%.%.%.%>%=%-%'%,%'%{%{%~%|%(%]%3%(%O%3%1%1%1%6%9%7%7%7%7%7%0%0%0%A%A%r%r%r%p%o%o%w%q%y%w%w%w%B%G%I%I%H%E%H%M%M%R%M%N%R%S%R%S%R%V%V%S%.&.&.&Y%@&.&@&.&%&+&*&*&*&",
+"I$J$K$S$)%T$T$&%T$&% %$%.%.%.%.%.%.%.%=%=%=%'%[%-%{%'%F%~%~%(%(%|%:%:%:%3%e%6%5%6%9%9%0%7%9%c%0%h%c%m%A%u%f%A%r%o%r%q%x%w%#&y%C%B%E%I%D%I%K%N%N%L%N%S%N%R%S%S%S%X%R%X%X%Y%.&.&.&.&.&$&+&%&=&*&*&*&-&-&;&",
+"K$S$)%X$2%`$$%$%&%&%%%%%.%%%%%.%.%=%=%=%!%=%'%{%~%~%{%{%(%|%|%:%:%:%6%6%4%6%4%7%9%7%7%0%c%c%h%h%h%h%n%r%A%r%q%o%q%v%v%v%C%D%D%D%D%I%H%I%N%K%N%R%S%S%R%S%S%S%S%S%X%X%X%X%.&.&@&Z%.&%&+&>&>&*&*&-&;&-&;&,&",
+"T$X$$%X$$% % %.%.%.%.%.%.%.%=%;%>%,%'%{%,%{%,%~%{%~%(%|%3%3%:%e%6%6%4%9%9%9%9%0%c%0%h%h%f%h%r%A%p%r%q%r%Q%J%Q%Q%y%y%v%C%D%D%E%K%H%H%M%M%N%N%S%S%S%R%S%S%S% &V%Y%Z%.&.&Z%.&@&+&>&*&>&*&*&'&-&)&,&,&,&,&,&",
+" % %$%.% %%%.%.%%%.%.%=%=%>%>%>%'%~%{%,%F%]%|%|%|%]%3%e%3%1%6%6%6%t%7%9%c%9%f%h%c%f%h%f%h%r%o%q%o%o%q%v%v%w%D%C%D%D%C%I%E%I%N%H%N%N%M%R%S%R%R%S%X%S%X%X%X% &.&.&.&@&@&@&%&*&+&*&*&'&!&;&;&~&,&,&,&,&{&]&",
+" %.%.%%%%%.%.%.%;%>%[%-%-%'%-%'%{%_%F%~%}%(%(%|%:%5%3%4%1%9%t%9%7%7%9%9%7%c%h%h%m%f%p%r%P%r%q%x%w%x%v%v%v%C%C%C%I%K%H%H%N%N%N%S%S%S%R%S%S%S%R%V%X%Y% &Y%.&`%.&Z%@&=&>&*&%&*&*&>&-&)&-&;&,&,&{&~&{&]&]&]&",
+".%.%.%.%.%;%=%=%!%-%>%'%,%~%~%{%F%]%|%|%3%3%:%4%4%6%6%6%c%9%7%7%7%f%c%c%f%h%h%n%p%A%p%q%o%w%y%y%w%C%D%C%C%C%E%E%H%H%N%M%R%N%S%R%S%R%S%R%S%S%X%X%Y%^&.&.&+&%&+&=&@&@&*&>&-&-&;&;&;&~&{&,&,&{&]&]&]&]&/&/&",
+".%.%;%=%=%=%'%!%'%'%{%{%{%~%|%|%|%3%(%:%4%4%4%4%4%4%7%7%c%c%c%0%c%h%h%f%A%n%r%q%q%o%Q%x%w%x%x%y%D%G%I%I%H%K%H%M%M%N%R%S%R%S%S%S%S%R%(&X%Y%X%.&.&@&@&_&@&>&+&+&*&*&)&!&-&)&,&,&~&,&~&:&]&]&]&]&]&<&[&<&}&",
+".%;%;%;%-%[%'%~%_%}%{%~%]%(%3%3%3%:%4%4%1%1%7%7%0%7%9%0%0%0%h%f%n%h%p%q%A%o%o%o%v%o%v%C%D%C%C%C%I%E%H%H%K%N%N%N%S%S%R%R%R%R%|&R%Y%Y%Y%.&.&Z%@&+&@&*&+&*&*&*&>&-&-&;&~&1&,&,&{&{&{&2&]&3&]&/&<&<&}&}&4&4&",
+"[%'%,%{%{%{%~%{%{%|%|%:%|%3%O%:%:%5%9%7%7%7%9%7%7%h%c%h%f%f%A%r%p%o%q%o%v%J%y%w%v%D%D%D%G%G%K%K%H%M%M%M%S%N%S%S%S%S%X%X%S%X%X%Y%Y%X%.&.&.&+&$&+&+&>&-&'&-&-&,&;&,&,&~&5&2&]&]&]&{&]&]&]&<&}&}&4&4&6&7&7&",
+"-%'%{%{%~%|%]%(%(%(%3%3%O%e%5%6%6%9%9%9%7%7%c%h%h%f%p%h%p%n%o%q%o%o%o%o%y%v%y%B%D%D%W%C%K%K%M%M%N%S%M%S%S%R%S%R%R%S%Y% &V%Y%Z%Z%.&Z%Z%%&$&>&*&*&'&*&!&-&-&,&1&,&,&,&2&]&]&]&]&]&/&<&}&<&4&4&6&4&8&8&9&8&",
+"_%~%F%_%}%d%3%3%3%3%O%6%4%4%6%7%9%7%9%7%9%0%h%h%f%A%p%r%o%o%q%w%o%w%y%y%v%C%C%C%I%K%I%N%M%N%M%R%S%S%S%S%S%X%Y% &Y%Y%.&.&.&.&@&Z%@&*&=&*&*&>&*&'&!&,&1&,&,&,&~&{&]&{&]&]&]&]&]&<&}&0&}&0&4&9&4&9&9&8&8&a&",
+"{%}%]%:%:%3%5%:%4%6%9%4%0%9%7%0%7%9%h%u%A%u%p%p%r%p%o%q%Q%o%y%y%v%D%C%C%E%I%K%H%K%N%N%N%N%N%R%S%S%S%S%R%(&X%Y%Y%.&Z%.&`%+&+&+&*&*&*&*&-&;&-&-&,&,&~&,&~&]&{&]&{&]&]&]&<&<&<&}&}&}&4&6&4&9&8&8&9&a&a&a&b&",
+"(%:%3%:%5%6%4%l%4%7%7%7%9%9%0%h%c%h%f%r%u%r%r%p%o%q%w%x%y%x%C%D%C%C%E%H%K%N%H%M%N%S%S%R%S%S%S%S%(&R% &X%Y%.&.&Z%_&+&%&@&+&@&*&>&*&-&-&;&-&;&,&,&{&,&{&]&]&]&]&]&<&<&}&}&<&4&6&7&9&9&9&9&8&c&a&a&d&e&b&f&",
+"3%3%:%4%6%6%9%0%7%9%7%c%c%f%h%h%h%p%p%p%q%r%q%x%y%w%y%x%C%D%G%I%E%K%H%M%M%M%M%S%S%S%S%S%R%Y%Y%S%Y%X%Y%Y%.&.&`%$&+&%&*&>&-&'&!&*&!&g&)&~&,&{&,&]&{&]&]&3&<&]&]&<&<&}&4&4&4&9&8&9&9&9&a&a&a&a&d&b&f&h&h&h&",
+"1%1%4%7%7%7%7%9%0%0%h%f%h%u%f%A%n%n%q%J%J%o%J%y%v%C%D%I%H%H%H%H%K%M%N%N%S%S%S%S%S%R%S%Y%S%Y%Y%Y%Y%Z%$&@&`%$&$&*&*&>&*&-&;&-&,&)&,&,&{&{&{&{&]&]&]&]&]&/&}&<&}&i&4&4&4&4&8&8&j&9&j&a&a&b&f&f&f&k&l&h&h&m&",
+"7%7%7%9%c%c%c%c%h%h%h%A%A%r%o%o%q%q%q%w%v%w%#&C%D%E%C%I%H%H%H%M%M%S%N%R%S%S%S%S%V%S%X%Y%Y%.&.&.&`%+&@&*&*&*&>&*&*&;&-&g&;&,&~&,&5&{&{&]&]&]&]&/&]&<&<&0&4&4&4&9&4&9&8&9&a&j&a&b&a&b&b&b&h&h&h&h&m&m&m&m&",
+"9%9%7%c%f%c%f%f%u%f%p%r%o%q%Q%o%v%w%v%#&C%C%W%D%I%N%H%N%M%M%S%R%S%R%S%S%R%S%R%S%Y%X%X% &Z%.&$&$&%&+&*&*&-&n&;&;&;&,&,&,&2&{&{&]&]&]&]&]&]&[&<&<&}&}&4&4&4&4&9&8&8&a&8&a&a&b&b&b&b&b&k&h&h&m&m&m&m&m&m&m&",
+"9%0%7%f%h%p%r%A%n%r%q%o%o%q%w%D%y%v%D%C%D%I%K%H%H%M%N%N%S%S%R%R%S%S%S%X%S%Y%Y%.&Y%.&Z%+&$&@&+&+&*&*&;&*&-&-&;&1&,&,&,&{&]&]&{&3&]&]&]&/&<&}&}&4&4&9&4&9&9&9&8&9&a&b&o&b&b&b&h&k&f&h&h&m&m&m&m&m&m&m&m&p&",
+"h%n%A%n%r%r%n%o%q%q%o%y%v%x%#&C%I%D%C%E%H%H%M%M%R%M%S%R%R%S%S%X%(&(&X%^&Y%.&.&.&.&$&$&+&*&*&>&*&;&*&;&;&~&;&,&,&:&5&]&]&]&]&]&]&<&<&}&}&}&4&4&8&9&9&8&a&c&a&a&b&f&b&f&f&h&h&h&h&h&m&m&m&m&q&m&m&r&r&s&r&",
+"h%p%p%r%o%q%q%Q%y%v%v%v%C%C%I%H%I%H%L%M%N%N%N%S%R%R%S%R%S%R%(&Y%Y%Z%.&.&_&.&%&+&$&*&*&*&-&)&!&-&-&1&;&~&,&{&3&]&]&]&]&]&]&<&<&}&4&0&4&4&4&7&9&8&8&a&a&b&a&a&b&f&h&h&k&k&h&m&m&m&m&m&m&m&m&s&m&s&r&r&r&t&",
+"r%p%o%o%v%w%y%v%C%D%H%D%C%E%H%N%M%N%N%N%R%R%R%S%S%S%Y%Y%S%Y%X%.&.&.&Z%.&+&@&=&*&*&*&-&;&;&;&;&~&1&2&,&{&{&2&2&]&]&]&<&<&i&4&0&4&4&4&7&4&9&9&8&8&a&a&a&b&b&f&b&h&h&h&h&h&m&m&m&m&m&m&u&s&s&s&s&t&t&v&t&w&",
+"q%q%y%x%x%w%D%C%D%H%K%x&L%K%K%N%M%N%S%S%S%S%S%S%S%R% &Y%y&Y%@&@&@&@&+&z&=&>&*&*&*&-&;&;&,&,&~&]&{&5&]&{&3&3&<&]&<&<&}&}&}&4&4&9&8&9&8&a&9&a&b&a&d&b&b&b&h&k&h&m&h&q&m&m&m&m&s&s&m&r&r&s&t&t&t&t&t&w&w&A&",
+"Q%y%D%y%C%C%D%K%E%E%N%N%M%R%S%S%S%S%S%S%S%(&(&X%Y% &.&Z%Z%.&@&$&@&*&*&*&*&-&*&,&,&)&,&~&2&{&]&{&]&]&]&]&]&]&<&}&<&4&4&4&4&9&8&9&9&B&a&a&a&b&b&f&h&h&h&h&m&m&m&m&m&m&q&m&m&s&C&r&v&s&r&t&t&t&w&w&D&E&A&A&",
+"C%C%C%D%I%I%E%K%N%M%M%M%S%R%S%R%S%S%S%R%S%Y%y&.&Z%.&.&@&`%*&+&z&*&n&*&;&;&-&1&,&1&,&,&]&]&{&]&]&]&]&<&i&<&i&<&6&0&7&9&9&8&9&8&a&a&b&a&f&f&f&k&b&h&h&m&h&m&m&m&m&m&m&p&m&s&v&t&s&v&t&t&t&w&w&w&F&A&E&G&G&",
+"C%G%G%H%N%M%M%N%M%R%R%R%S%S%S%S%S%X% &.&Y%.&.&Z%+&@&+&=&=&*&*&*&;&*&;&,&-&~&,&~&]&]&{&{&]&{&]&[&}&}&<&}&4&4&4&9&9&9&9&a&a&a&a&a&a&f&f&f&f&f&m&h&h&m&m&m&m&m&q&m&s&r&r&t&r&r&t&t&t&F&t&A&G&F&G&G&H&I&H&I&",
+"I%N%N%H%N%S%S%N%S%R%S%S%R%Y%S% &y&.&Y%.&.&@&@&+&+&$&*&*&*&;&)&-&;&g&,&,&{&,&{&]&]&]&]&<&/&}&}&<&0&4&6&4&6&7&9&8&a&j&8&a&b&b&b&f&h&h&k&h&h&m&m&m&m&m&m&m&m&s&s&s&J&r&s&t&v&t&w&F&F&F&F&A&G&E&I&H&H&I&H&K&",
+"N%M%M%S%S%S%S%S%S%V%|&X%(&Y%.&.&Z%.&Z%%&@&+&*&+&*&*&-&-&-&;&-&~&,&{&,&5&]&{&{&3&3&]&/&<&}&}&}&4&6&9&4&8&9&8&8&j&a&a&a&b&h&b&f&h&h&h&h&h&m&m&m&m&m&q&p&s&C&r&v&s&t&t&w&t&w&w&L&w&A&G&H&G&I&H&H&H&M&K&N&K&",
+"N%R%R%R%R%S%S%X%Y%X% &Y%^&Z%.&`%%&@&+&@&>&*&>&'&!&!&1&;&,&~&5&:&]&]&{&]&]&]&]&}&]&}&<&i&4&4&9&7&7&9&a&8&j&a&a&a&b&h&f&k&b&h&h&h&m&m&m&m&m&m&m&m&r&s&J&v&O&r&t&t&P&w&w&G&D&G&G&G&H&I&H&I&H&I&K&K&N&Q&K&Q&",
+"S%S%R%S%S%S%S%Y%^&.&.&@&.&_&.&+&@&@&*&*&*&>&*&-&;&,&,&,&,&]&{&]&{&]&]&]&/&<&i&<&4&4&4&9&4&8&9&j&a&8&j&a&f&b&b&f&h&k&h&h&h&m&m&m&m&m&m&m&m&p&s&r&s&t&r&t&t&w&w&w&w&F&A&G&E&G&G&H&I&K&I&N&N&M&Q&K&R&Q&S&T&",
+"R%(&X%S%V%Y%X%X%.&.&Z%Z%+&+&*&>&>&n&*&;&~&;&,&,&~&,&{&{&2&]&{&]&[&}&<&<&<&}&}&4&7&9&4&9&9&8&a&a&a&a&b&f&f&f&f&h&h&h&m&m&q&m&m&m&m&m&C&s&s&s&t&v&v&U&V&w&F&F&F&F&G&G&G&E&H&I&W&H&K&N&Q&K&R&Q&Q&Q&R&T&T&T&",
+"Y%X%Y%Y%Y%Z%Z%`%@&@&+&=&*&-&'&-&-&-&;&~&,&,&,&{&{&{&2&]&]&]&<&]&<&}&4&4&<&4&4&9&9&9&j&j&8&a&a&b&b&b&h&k&h&h&m&m&m&m&m&m&m&m&m&m&p&s&s&r&t&v&t&t&U&w&w&F&w&G&G&G&X&X&H&M&W&H&K&M&Q&K&R&Q&R&R&R&R&R&R&Y&Z&",
+"Y%Z%Z%@&.&$&@&%&*&*&*&*&'&*&;&-&;&~&,&,&2&{&{&]&]&3&]&]&3&/&}&<&0&4&0&4&9&4&8&a&9&a&`&b&a&f&f&k&h&h&h&h&h&m&m&m&m&q&m&q&s&s&s&s&O&t&r&t&t&w&V&F&w& *w&G&W&H&G&H&H&H&N&M&M&N&Q&K&Q&Q&R&R&R&R&Y&Y&Y&Y&.*.*",
+".&@&@&`%+&+&z&*&*&-&*&;&;&-&,&,&,&~&]&]&{&]&3&{&<&/&<&}&}&<&4&4&4&4&4&9&9&8&8&a&a&a&a&b&f&f&k&h&m&m&m&m&m&m&m&m&m&m&m&C&J&r&r&t&t&w&t&w&F&F&G&E&F&G&H&H&+*H&M&I&K&I&K&K&S&Q&S&Q&R&S&S&Y&Z&T&Z&@*Y&@*.*.*",
+"@&$&*&*&>&*&!&;&;&-&;&1&,&,&,&]&,&{&]&]&]&]&]&]&[&<&}&}&4&9&4&8&9&9&9&a&a&b&b&b&b&b&k&h&h&h&h&m&q&m&m&m&m&m&s&m&s&s&s&s&v&t&t&D&w&w&w&A& * *G&H&G&W&I&M&H&W&K&K&N&Q&Q&Q&R&T&S&R&T&Y&Y&T&Y&#*Y&$*.*.*.*%*",
+"z&*&*&*&'&-&-&-&,&,&,&,&5&{&{&]&]&3&]&<&}&}&i&<&0&4&4&7&9&9&8&8&9&a&a&b&b&b&b&h&h&h&h&h&m&m&m&m&m&m&m&s&s&r&r&r&r&t&t&t&w&U&t&L&F&F&G&G&G&G&I&+*M&H&K&K&K&Q&K&R&R&R&R&Q&R&R&R&Z&T&#*.*#*%*.*.*.*&*****&*",
+"*&;&!&)&-&;&,&,&,&{&{&]&]&]&]&]&]&<&[&<&i&}&4&4&6&4&8&8&j&j&a&a&a&b&b&b&b&b&f&h&h&m&m&m&m&m&m&m&m&m&s&s&s&t&t&t&t&t&t&w&w&w&w&A&G&G&G&H&H&H&H&M&H&K&K&Q&Q&S&R&Q&R&R&=*R&-*Y&Y&Y&Z&Y&.*.*.*%*.*&*;*;*;*>*",
+"-&-&1&,&1&,&,&{&{&{&{&]&3&]&/&<&}&<&<&4&4&9&7&8&8&a&9&a&a&a&B&b&b&b&h&h&h&h&h&h&m&m&q&m&m&m&m&q&m&v&r&v&U&t&t&t&w&t&A&w&G&G&G&H&H&X&H&I&I&K&K&K&S&S&R&Q&Q&Q&R&=*T&T&Z&Z&Y&#*@*%*.*.*.*,*&*&*&*'*>*>*)*!*",
+";&~&,&2&{&{&{&3&]&]&]&]&/&]&}&4&4&0&4&4&8&9&8&9&j&a&b&f&a&f&h&h&h&h&h&h&m&m&m&m&m&m&q&s&q&s&r&v&t&v&t&w&w&w&w&F&w&L&F&G&G&H&H&W&H&H&N&K&N&K&R&Q&R&Q&S&R&R&T&R&Y&T&.*Y&#*.*.*&*%*&***,*'*&*;*~*'*~*!*)*)*",
+"{&~&2&3&]&{&3&]&]&i&<&}&<&}&4&4&4&9&9&8&a&a&8&a&a&a&f&b&f&k&h&m&h&h&m&m&m&m&m&m&m&p&s&r&r&v&v&v&t&t&F&w&F&G&F&G&A&G&G&G&H&M&H&I&N&Q&Q&K&S&T&Q&Q&R&R&R&Z&Y&Y&$*@*.*#*.*.*&*%*&*,***>*{*>*>*)*)*>*)*]*]*)*",
+"]&]&{&]&3&]&i&/&<&<&}&}&4&4&9&7&9&9&9&a&a&a&a&f&b&f&k&h&h&h&h&m&m&m&m&m&m&s&m&s&r&s&s&t&t&t&t&t&V&F&w&A&G&G&G&G&W&I&H&I&K&M&K&K&Q&Q&S&S&R&S&R&Q&T&Y&Y&Y&Y&Y&#*.*.*&*%*&*&*;*'*{*>*~*{*~*!*^*/*)*!*)*]*/*",
+"]&]&]&<&<&<&<&}&}&4&4&9&9&9&9&a&B&a&b&a&b&b&b&k&b&h&m&q&m&m&m&q&m&m&m&s&s&s&r&s&r&v&O&w&t&t&w&F&D&w&G&A&H&H&+*H&M&K&N&K&K&K&Q&R&Q&R&R&Q&R&T&R&Y&Y&Z&%*#*.*(*.*&*&*&*&*&*;*>*>*>*)*_*)*)*)*)*:*]*<*]*[*<*",
+"]&]&<&<&}&4&4&6&4&9&9&8&j&8&a&a&a&b&d&b&k&h&h&h&m&m&m&m&m&m&m&m&m&m&s&s&s&C&t&v&w&t&t&L&w&L&A&E&G&E&E&H&I&W&I&M&K&K&K&K&Q&R&Q&R&S&R&R&R&Y&R&Z&Y&%*.*.*#*&***,*{*,***>*>*>*)*)*^*}*)*]*:*|*<*[*|*<*[*[*[*",
+"<&4&4&4&4&4&4&8&8&a&j&a&a&a&b&b&b&k&f&h&h&h&h&m&m&m&m&m&q&m&m&r&s&s&s&t&t&w&V&w&w&w&F&F&G&G&G&G&X&H&M&I&W&H&Q&K&Q&Q&R&Q&R&T&T&R&R&Y&T&$*#*#*.*.*#*,*&*&*>*,*{*'*>*>*>*~*!*)*)*]*/*]*]*/*]*[*<*[*[*[*<*[*",
+"4&6&4&8&8&8&9&8&a&a&a&a&b&f&b&b&h&h&h&m&m&m&m&q&m&m&m&m&q&s&r&r&v&v&v&t&w&F&D&A&G&E&E&E&G&G&H&K&H&I&K&Q&K&R&K&Q&T&Q&Q&Q&Q&Y&Y&Z&@*Z&$*#*$*#*.*&*,*&*'*'*****~*>*!*!*)*]*)*^*]*|*|*]*]*[*[*<*[*[*<*<*<*<*",
+"4&8&8&a&8&a&a&a&d&b&b&b&h&k&h&h&h&m&m&m&m&m&m&m&s&s&r&s&s&t&v&v&t&w&w&w&A&F&L&G&G&G&H&W&H&M&K&K&K&K&K&Q&S&Q&T&R&R&T&R&Y&T&Y&@*%*#*.*#*.*.***&*&*>***>*~*>*)*!*)*/*}*)*|*]*|*]*[*[*<*<*<*[*[*[*[*1*2*[*1*",
+"8&a&a&8&a&a&b&f&b&f&f&k&h&m&m&m&m&m&m&m&m&m&C&s&s&C&r&t&t&t&U&t&F&w&G&w&E&G&G&H&I&H&I&K&K&K&K&Q&3*Q&S&R&R&Q&Q&T&R&R&Z&Z&.*@*#*%*.*%*,*&*{*~*>*~*>*>*>*>*^*)*)*/*]*]*[*[*|*[*<*[*<*<*<*[*[*[*1*4*4*4*5*5*",
+"a&a&a&b&b&b&f&f&h&h&h&m&m&m&m&m&q&m&m&m&s&r&r&s&v&U&t&t&w&w&w&A&F&G&E&G&G&I&H&I&I&I&M&K&K&K&Q&Q&T&Q&Q&R&Z&Z&R&Y&@*Y&.*$*%*&*&*,*&*&*,*&***~*~*!*)*!*)*:*)*}*/*]*]*|*<*[*[*[*[*[*4*[*1*4*[*2*2*1*6*5*7*5*",
+"a&f&b&b&b&h&h&h&m&m&m&q&m&m&m&m&s&s&C&C&r&O&t&t&U&w&t&F&G& *G&E&H&H&G&X&I&M&M&N&K&K&Q&Q&Q&S&R&R&R&R&R&R&Y&Z&Z&.*Y&.*.*.*,*&*;*>*'*>*>*>*~*!*>*)*!*}*)*/*|*8*]*<*<*[*<*<*<*[*[*1*<*1*2*1*7*4*9*7*5*5*7*0*",
+"b&k&h&h&h&h&m&m&m&m&m&m&s&s&r&m&s&r&t&s&t&t&t&F&w&w&G&A&G&H&E&H&I&I&+*I&K&M&K&K&K&Q&S&T&R&R&R&R&Y&Y&T&Y&Y&.*.*#*,*.*&*&*&*'***>*~*>*!*>*)*)*)*|*}*]*|*[*[*<*[*<*[*<*<*<*1*<*1*<*1*7*6*5*7*a*5*a*a*0*b*a*",
+"k&h&m&m&m&m&m&m&m&m&m&m&s&J&r&t&v&t&U&D&w&F&F&w& *A&E&H&H&I&H&I&M&K&K&K&Q&Q&Q&R&Q&Q&S&Q&R&R&Y&R&Z&@*Y&@*#*%*,*&*,*&***~*>*'*!*)*!*!*)*!*]*:*/*]*[*[*<*[*<*[*[*<*<*<*[*[*1*9*5*2*6*7*5*7*7*7*a*0*c*d*c*d*",
+"h&m&m&m&m&m&m&m&m&s&r&s&r&J&t&t&t&D&w&w&w&w&G&A&G&H&H&H&H&K&K&K&K&K&N&Q&R&Q&R&R&T&R&Y&Y&Z&Y&@*Y&.*%*%*.*.*&***&***;*~*>*)*)*)*^*]*^*:*]*|*:*<*[*[*<*<*[*<*[*1*4*[*1*4*e*5*4*e*7*5*a*f*f*a*0*a*a*c*g*g*h*",
+"m&m&m&m&m&s&s&s&C&r&v&t&t&t&D&w&w&G&F& *G&E&G&H&W&I&K&N&K&K&K&K&S&R&Q&T&R&T&R&R&@*R&Y&Y&.*.*%*&*%*.*;*,*,*'*'*~*>*>*>*)*)*)*)*]*]*|*|*[*<*[*[*<*<*<*[*<*[*<*4*9*9*9*5*5*6*5*a*a*5*a*a*i*c*f*i*c*g*j*j*h*",
+"m&s&s&p&s&s&r&t&O&t&t&t&D&w&D&A&G&A&H&G&H&H&H&K&M&K&N&K&Q&3*Q&Q&S&T&Q&S&Y&T&Y&Y&Y&.*(*(*.*.*.*.*****&*>*'*~*!*>*)*>*)*!*|*:*]*]*[*<*[*<*[*[*[*[*[*<*<*1*4*4*4*6*6*e*7*0*5*0*a*a*d*c*d*c*g*g*h*c*j*h*k*h*",
+"s&r&r&s&r&O&t&w&w&w&F&w&F&A& *G&H&I&H&H&M&I&K&N&N&Q&Q&Q&Q&R&R&T&R&R&R&Y&Y&.*@*@*.*.*,*.*;*;*&*;*>*{*>*!*~*>*)*/*^*!*^*/*]*]*|*|*[*<*<*[*<*[*[*[*1*4*9*2*7*4*7*a*0*l*5*a*f*d*d*g*c*i*g*c*m*j*j*h*n*o*p*o*",
+"s&r&r&t&t&t&w&F&w&A&F&E&A&G&H&H&H&H&N&K&q*N&Q&Q&S&R&Q&R&Q&T&Z&R&R&@*@*#*@*$*%*%*.*&*%*,*;***&*>*>*!*)*!*)*^*!*:*/*|*]*[*[*<*<*[*[*[*[*[*<*4*[*2*1*7*2*7*5*e*l*5*0*b*i*c*d*g*c*g*c*g*k*h*j*j*p*p*n*p*r*r*",
+"r&t&t&w&w&w&F&w&G& *G&H&G&I&K&H&K&K&M&Q&K&Q&R&Q&T&T&R&Y&R&Y&Y&Y&.*#*.*.*.*.*&*****&*,*>*>*s*~*~*>*)*)*)*:*|*<*/*]*<*<*<*<*[*[*[*<*[*<*1*1*5*7*4*7*7*7*5*5*t*f*i*i*c*i*d*g*i*h*j*h*h*j*h*n*o*p*p*n*r*r*u*",
+"F&F&V&w&A&G&A&G&G&I&+*H&I&+*M&K&S&K&S&Q&S&Q&R&T&Q&R&R&Y&Z&Y&Y&@*.*.*%*%*&***&*;***>*~*~*>*!*)*)*^*)*^*|*|*]*|*|*[*[*[*<*[*[*[*1*4*[*e*2*1*7*5*e*5*5*5*0*b*d*g*i*c*g*c*g*j*h*v*w*w*n*n*p*p*r*p*r*r*x*y*z*",
+"w&F&A&F&G&G&I&I&I&H&H&I&M&K&N&K&R&Q&Q&Q&R&T&Q&Y&Z&Y&Y&$*%*.*.*.*.*&*&***&***~*>*>*!*)*)*)*)*|*/*]*|*[*[*[*<*[*[*[*[*[*[*[*[*1*4*e*1*1*9*7*7*0*7*a*0*0*c*c*g*d*c*j*j*k*h*w*p*p*n*v*p*r*y*r*u*A*r*B*A*z*A*",
+"F&G&G&E&H&H&H&I&I&K&K&S&Q&T&Q&S&R&R&R&R&Y&R&Y&Y&Y&%*@*%*.*C*,*.*****~***'*>*>*>*)*)*^*/*/*/*]*/*]*[*[*[*<*[*<*<*[*<*<*1*4*4*2*1*e*7*a*e*5*a*b*b*c*d*c*g*g*j*j*j*h*o*p*h*p*n*n*y*r*p*r*r*D*u*A*u*B*z*B*A*",
+"H&H&H&I&M&I&K&K&K&S&Q&Q&R&R&Q&R&R&Y&R&Z&Y&Y&@*.*#*.*.*,*,*****&*;*>*!*>*~*!*)*)*/*/*/*|*[*]*<*<*[*[*<*<*[*<*[*1*1*2*4*1*6*e*5*0*5*7*7*0*d*i*c*c*c*i*h*g*h*w*p*h*w*o*v*n*n*r*r*y*r*r*D*A*A*A*A*A*A*A*A*E*",
+"H&K&K&N&K&Q&N&S&N&Q&Q&Q&R&R&R&R&Y&Y&@*@*%*$*#*.*&*&*,*&***;***>*)*>*>*)*)*!*]*|*|*|*]*<*|*[*<*[*[*[*[*[*[*[*1*9*4*4*5*5*7*7*F*t*b*0*f*i*c*g*c*j*h*k*j*h*w*j*h*n*p*p*n*r*y*r*r*x*B*A*A*A*A*z*A*A*G*A*H*I*",
+"I&K&M&Q&K&Q&Q&Q&Q&T&R&Q&Y&Z&T&$*@*.*#*.*.*.*&*&*;***;*;*>*~*)*^*}*!*}*^*}*|*]*<*]*[*[*[*<*[*[*<*1*4*[*1*9*1*7*7*e*6*a*0*7*0*a*0*0*c*f*g*c*j*h*h*h*j*w*k*v*p*p*v*y*y*y*y*r*x*A*B*A*A*A*A*A*A*E*I*J*E*K*J*",
+"K&Q&K&T&Q&Q&R&R&T&Z&Y&Y&$*$*Y&#*%*&*,*****&*'*{*'*>*~*>*>*L*!*)*!*^*]*]*]*<*[*<*<*[*<*[*<*<*[*<*1*4*4*7*4*7*6*5*5*7*0*d*i*i*c*0*g*g*h*c*j*j*j*o*p*p*p*p*p*r*r*r*r*u*A*A*u*A*B*z*A*z*A*K*I*I*H*H*H*K*M*M*",
+"Q&Q&R&T&R&R&T&Y&R&Z&Y&#*Y&%*.*.*&*&*&*,*'***~*{*)*~*)*!*|*)*|*:*]*]*<*]*[*[*<*<*[*[*[*[*[*1*4*6*4*6*7*5*5*0*0*f*a*a*d*i*g*g*c*c*g*j*j*w*k*n*v*p*N*p*o*y*D*B*r*D*u*B*A*B*z*z*z*A*A*A*H*E*H*E*J*M*M*O*M*O*"};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gtk/messagebox_error.xpm	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,110 @@
+/* XPM */
+static char *_dw_messagebox_error[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 72 1",
+"  c opaque",
+". c #8b0000",
+"X c #930000",
+"o c #9b0000",
+"O c #9c0a0a",
+"+ c #a20000",
+"@ c #a10b0b",
+"# c #ab0000",
+"$ c #aa0a0a",
+"% c #ae1717",
+"& c #b30000",
+"* c #b70b0b",
+"= c #bb0000",
+"- c #b41414",
+"; c #c40000",
+": c #ca0000",
+"> c #cd0909",
+", c #ca1212",
+"< c #d10000",
+"1 c #d30b0b",
+"2 c #dc0000",
+"3 c #dd0909",
+"4 c #c72929",
+"5 c #cd2929",
+"6 c #d62929",
+"7 c #e40000",
+"8 c #ec0303",
+"9 c #ee1515",
+"0 c #eb1f1f",
+"q c #f20000",
+"w c #fd0202",
+"e c #f90808",
+"r c #f51616",
+"t c #f31818",
+"y c #fe1111",
+"u c #fe1c1c",
+"i c #ec2b2b",
+"p c #ed3f3f",
+"a c #f52222",
+"s c #f72c2c",
+"d c #fd2222",
+"f c #ff2828",
+"g c #f23636",
+"h c #f33c3c",
+"j c #fe3333",
+"k c #ff3f3f",
+"l c #ec4444",
+"z c #ff4545",
+"x c #ff4a4a",
+"c c #f75656",
+"v c #f75c5c",
+"b c #fe5555",
+"n c #ff6767",
+"m c #fc6b6b",
+"M c #f57272",
+"N c #fd7272",
+"B c #fc7979",
+"V c #ff8a8a",
+"C c #fe9090",
+"Z c #fd9c9c",
+"A c #fea2a2",
+"S c #feabab",
+"D c #ffb1b1",
+"F c #febcbc",
+"G c #ffc4c4",
+"H c #fecccc",
+"J c #ffd4d4",
+"K c #ffdbdb",
+"L c #ffe1e1",
+"P c #ffebeb",
+"I c white",
+"U c None",
+/* pixels */
+"UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU",
+"UUUUUUUUUUU;;;;;=====UUUUUUUUUUU",
+"UUUUUUUU:::;;::::;;==&&&UUUUUUUU",
+"UUUUUUU::;:20vBBBBMi<;&&&UUUUUUU",
+"UUUUUU:::2cDPPPPPPPPHM1&&#UUUUUU",
+"UUUUU::<iAKKKKKKKKKKKKHl=##UUUUU",
+"UUUU::2hFHHHHHHHHHHHHHHHM;#+UUUU",
+"UUU:::hFFFHFFFFFFFFFFHFFFM=++UUU",
+"UU:::9ZSSHILSSSSSASSLIHSSSl#++UU",
+"UU:;2NZZFIIIKZZCZZZKIIIFZZV1o+UU",
+"UU::aVVZIIIIIJVVVVJIIIIIZVVc#oUU",
+"U:;2bBBBHIIIIIHBBHIIIIIHNbsr:ooU",
+"U;;8nnnnnGIIIIIGGIIIIISsq8qq7ooU",
+"U;;rbbbbbbFIIIIIIIIIIZ8qqqqq8+XU",
+"U;:dxzzzzzzFIIIIIIIIZ8qqqq8qq#XU",
+"U;:tjjjjjjjjDIIIIIIZqqq8qqqqq#XU",
+"U;:rddddddddSIIIIIIZ8qqqq8qqq#XU",
+"U=:eeyyeyyeSIIIIIIIIZ8qq8wqqq#XU",
+"U=;wewwwwwZIIIIIIIIIIZwqw8wqwX.U",
+"U==8wwwwwZIIIIIZZIIIIIZwwwwq7X.U",
+"U=&2wwwwZIIIIIZwwZIIIIIZwwww;..U",
+"UU&=eeejIIIIIAeeeeZIIIIIjeeeo.UU",
+"UU&&3yyynIIIAyyyyyySIIImyyy>..UU",
+"UU&&&tduuNISuuuuuuuuSINuuu9X..UU",
+"UUU&#*dfffbffffffffffbfffaO..UUU",
+"UUUU##,sjjjjjjjjjjjjjjjjj-..UUUU",
+"UUUUU##*gzkkkkkkzkkkkkzg@..UUUUU",
+"UUUUUU#+#6xxxxxxxxxxxz5X..UUUUUU",
+"UUUUUUU++o$5lbbbbbbl4O...UUUUUUU",
+"UUUUUUUU+ooooO-%%%O.....UUUUUUUU",
+"UUUUUUUUUUUooXXXXX...UUUUUUUUUUU",
+"UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU"
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gtk/messagebox_information.xpm	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,43 @@
+/* XPM */
+static char *_dw_messagebox_information[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 5 1",
+"  c opaque",
+". c blue",
+"X c gray60",
+"o c white",
+"O c None",
+/* pixels */
+"OOOOOOOOOOOXXXXXXXXOOOOOOOOOOOOO",
+"OOOOOOOOXXXooooooooXXXOOOOOOOOOO",
+"OOOOOOXXooooooooooooooXXOOOOOOOO",
+"OOOOOXooooooooooooooooooXOOOOOOO",
+"OOOOXoooooooo....oooooooo OOOOOO",
+"OOOXoooooooo......oooooooo OOOOO",
+"OOXooooooooo......ooooooooo OOOO",
+"OXooooooooooo....ooooooooooo OOO",
+"OXoooooooooooooooooooooooooo XOO",
+"Xoooooooooooooooooooooooooooo  O",
+"Xoooooooooo.......ooooooooooo  O",
+"Xoooooooooooo.....ooooooooooo   ",
+"Xoooooooooooo.....ooooooooooo   ",
+"Xoooooooooooo.....ooooooooooo   ",
+"Xoooooooooooo.....ooooooooooo   ",
+"Xoooooooooooo.....ooooooooooo   ",
+"OXooooooooooo.....oooooooooo    ",
+"OXooooooooooo.....oooooooooo    ",
+"OOXoooooooooo.....ooooooooo    O",
+"OOO ooooooo.........oooooo     O",
+"OOOO oooooooooooooooooooo     OO",
+"OOOOO oooooooooooooooooo     OOO",
+"OOOOOO  oooooooooooooo      OOOO",
+"OOOOOOOX   oooooooo        OOOOO",
+"OOOOOOOO      oooo        OOOOOO",
+"OOOOOOOOOO     ooo      OOOOOOOO",
+"OOOOOOOOOOOOO  ooo   OOOOOOOOOOO",
+"OOOOOOOOOOOOOOO oo   OOOOOOOOOOO",
+"OOOOOOOOOOOOOOOO o   OOOOOOOOOOO",
+"OOOOOOOOOOOOOOOOO    OOOOOOOOOOO",
+"OOOOOOOOOOOOOOOOOO   OOOOOOOOOOO",
+"OOOOOOOOOOOOOOOOOOO  OOOOOOOOOOO"
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gtk/messagebox_question.xpm	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,134 @@
+/* XPM */
+static char *_dw_messagebox_question[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 96 2",
+"   c opaque",
+".  c #00008b",
+"X  c #000093",
+"o  c #00009b",
+"O  c #0a0a9b",
+"+  c #0000a3",
+"@  c #0000ab",
+"#  c #0a0aab",
+"$  c #0000b3",
+"%  c #0000bc",
+"&  c #0000c3",
+"*  c #0f0fc6",
+"=  c #0000c9",
+"-  c #0b0bcc",
+";  c #0101d5",
+":  c #0e0ed4",
+">  c #0000da",
+",  c #1111d5",
+"<  c #1919d3",
+"1  c #1d1ddc",
+"2  c #2424c4",
+"3  c #3e3ecf",
+"4  c #2020d3",
+"5  c #2323da",
+"6  c #3030d5",
+"7  c #3030db",
+"8  c #3c3cde",
+"9  c #0000e2",
+"0  c #0d0de3",
+"q  c #0202ea",
+"w  c #1a1ae0",
+"e  c #1919ec",
+"r  c #0000f3",
+"t  c #0a0af5",
+"y  c #0000fc",
+"u  c #0a0afe",
+"i  c #1010f4",
+"p  c #1414ff",
+"a  c #1818ff",
+"s  c #2020e5",
+"d  c #2f2feb",
+"f  c #3e3eeb",
+"g  c #2020f4",
+"h  c #2e2ef7",
+"j  c #2020ff",
+"k  c #2b2bfe",
+"l  c #3030f4",
+"z  c #3e3ef5",
+"x  c #3535fe",
+"c  c #3838f8",
+"v  c #4b4bda",
+"b  c #5252d4",
+"n  c #5252da",
+"m  c #4848eb",
+"M  c #4545f6",
+"N  c #4444ff",
+"B  c #4d4dfe",
+"V  c #5858f7",
+"C  c #5252fd",
+"Z  c #5858ff",
+"A  c #6f6feb",
+"S  c #6c6cf5",
+"D  c #6363fd",
+"F  c #6a6afe",
+"G  c #7474fd",
+"H  c #7b7bfe",
+"J  c #8181d9",
+"K  c #8383e4",
+"L  c #8b8be8",
+"P  c #9191eb",
+"I  c #9c9ced",
+"U  c #8282f5",
+"Y  c #8080fc",
+"T  c #8c8cfe",
+"R  c #9d9df3",
+"E  c #9292fd",
+"W  c #9d9dfe",
+"Q  c #a0a0ed",
+"!  c #aeaeee",
+"~  c #bdbdea",
+"^  c #a3a3fc",
+"/  c #acacfe",
+"(  c #b4b4f1",
+")  c #b5b5fb",
+"_  c #bfbffc",
+"`  c #cfcfed",
+"'  c #c1c1f6",
+"]  c #c1c1fe",
+"[  c #ccccfe",
+"{  c #d1d1fe",
+"}  c #dbdbfe",
+"|  c #e1e1ff",
+" . c #eeeefc",
+".. c #f1f1ff",
+"X. c white",
+"o. c None",
+/* pixels */
+"o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.",
+"o.o.o.o.o.o.o.o.o.o.o.o.= = & & % % % % o.o.o.o.o.o.o.o.o.o.o.o.",
+"o.o.o.o.o.o.o.o.o.= = = & = % & & % % % $ % $ o.o.o.o.o.o.o.o.o.",
+"o.o.o.o.o.o.o.o.= = = = ; 9 d z z f > ; & $ $ $ o.o.o.o.o.o.o.o.",
+"o.o.o.o.o.o.= = = = 9 V ^ ............] G 1 $ $ @ $ o.o.o.o.o.o.",
+"o.o.o.o.o.= = = > M ] | | { I L ! ! ( } | | F : @ @ @ o.o.o.o.o.",
+"o.o.o.o.= = = 0 Y { { ) L ! X.X.X.X.X.~ ' { { / 5 @ + @ o.o.o.o.",
+"o.o.o.o.= = 9 W ] ] R L X.X.X.X.X.X.X.X.X.} ] _ ) 5 + + o.o.o.o.",
+"o.o.o.= = > F ) / ^ L X.X.X.X.X.X.X.X.X.X.X.] ) ) T - + + o.o.o.",
+"o.o.= = = h W W W A X.X.X.X.} ^ W /  .X.X.X...W W W D + + o o.o.",
+"o.o.= = 9 H T T T P X.X.X. .T T T T U  .X.X.X.E T T T , + o o.o.",
+"o.o.= = h H H H H R X.X.X./ H H H H S ~ X.X.X.W H Z c t + o o.o.",
+"o.= & ; B F F F F E X.X...G F F F F b X.X.X.X.l t q r r & o o o.",
+"o.& = 9 B Z Z Z Z Z T / F Z Z Z Z v ` X.X.X._ r r r r r ; o X o.",
+"o.& % q N N N N N N N N N N N N v  .X.X.X...e r r r q r 9 o X o.",
+"o.& % t x x x x x x x x x x x 3  .X.X.X...l r r q r r r r X X o.",
+"o.% % t j j j j j j j j j j 4  .X.X.X. .l r r r r r r r r X X o.",
+"o.& % q p p u p p u p p p u J X.X.X.} l r r r r r r r r 9 X X o.",
+"o.% % 9 y y y y y y y y y r ~ X.X.X.l y r r r y r r r r ; X . o.",
+"o.% % ; y y y y y y y y y y ~ X.X.{ y y y y y y y y y y % . . o.",
+"o.o.% % y y y y y y y y y y Q X.X.Y y y y y y y y y y y o X o.o.",
+"o.o.$ $ 9 u u u u u u u u u a G F u u u u u u u u u u ; . . o.o.",
+"o.o.$ $ % p p a p p p p p p < K A l a a p p p p p p p o . . o.o.",
+"o.o.o.$ $ , j a j j j a a e ` X.X...h a a j j j j a * . . o.o.o.",
+"o.o.o.o.@ @ w k k k k x k w X.X.X.X.Z k k k k k k < . . o.o.o.o.",
+"o.o.o.o.@ @ @ 5 x x x x x l ..X.X.X.C x x x x x 4 . . . o.o.o.o.",
+"o.o.o.o.o.@ + + < N N N N N F ] { H N N N N N 2 . . . o.o.o.o.o.",
+"o.o.o.o.o.o.@ + + # 7 B C B B B B B B B B 6 O . . . o.o.o.o.o.o.",
+"o.o.o.o.o.o.o.o.+ + o # 2 8 m Z Z m 8 2 O . . . o.o.o.o.o.o.o.o.",
+"o.o.o.o.o.o.o.o.o.o o o o o X X X X . . . . . o.o.o.o.o.o.o.o.o.",
+"o.o.o.o.o.o.o.o.o.o.o.o.o X X X X X . . o.o.o.o.o.o.o.o.o.o.o.o.",
+"o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o."
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gtk/messagebox_warning.xpm	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,172 @@
+/* XPM */
+static char *_dw_messagebox_warning[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 134 2",
+"   c opaque",
+".  c #1a1a1a",
+"X  c #212121",
+"o  c #2b2b2b",
+"O  c #323225",
+"+  c #373737",
+"@  c #3c3c31",
+"#  c #4c1c00",
+"$  c #572000",
+"%  c #6d2800",
+"&  c #742b00",
+"*  c #46463c",
+"=  c #6e6e16",
+"-  c gray43",
+";  c #797979",
+":  c #823000",
+">  c #8a3300",
+",  c #943700",
+"<  c #9e3b00",
+"1  c #a63e00",
+"2  c #a83e00",
+"3  c #b34200",
+"4  c #bb4500",
+"5  c #c54900",
+"6  c #cb4c00",
+"7  c #d14d00",
+"8  c #d35303",
+"9  c #d35408",
+"0  c #d55800",
+"q  c #d85f00",
+"w  c #d96400",
+"e  c #da6b00",
+"r  c #dd7100",
+"t  c #dd7a00",
+"y  c #e37b00",
+"u  c #a9a91c",
+"i  c #9a9a44",
+"p  c #88886c",
+"a  c #8b8b79",
+"s  c #b5b54d",
+"d  c #a7a776",
+"f  c #e08500",
+"g  c #e48b00",
+"h  c #e98f01",
+"j  c #e99002",
+"k  c orange2",
+"l  c #e9a100",
+"z  c #eeac00",
+"x  c #f2aa01",
+"c  c #fcbf00",
+"v  c #f9bf0d",
+"b  c #f2c400",
+"n  c #ffc700",
+"m  c #f9cb06",
+"M  c #f9cc0a",
+"N  c #f4d303",
+"B  c #f4d50c",
+"V  c #f9dd00",
+"C  c #fcda0c",
+"Z  c #f5d610",
+"A  c #fcdb13",
+"S  c #ffd32e",
+"D  c #ffd925",
+"F  c #fced03",
+"G  c #ffea0e",
+"H  c #ffeb18",
+"J  c #fff70d",
+"K  c #fffe03",
+"L  c #fffe0c",
+"P  c #fff111",
+"I  c #fff21e",
+"U  c #fffe14",
+"Y  c #fffe1c",
+"T  c #e3e326",
+"R  c #e4e43a",
+"E  c #ffe236",
+"W  c #ffe43f",
+"Q  c #fffe22",
+"!  c #fffe2a",
+"~  c #fff73a",
+"^  c #ffff32",
+"/  c #ffff3a",
+"(  c #ffde56",
+")  c #ffde58",
+"_  c #ffea43",
+"`  c #ffec51",
+"'  c #fff243",
+"]  c #fffe43",
+"[  c #ffff49",
+"{  c #fff356",
+"}  c #fffd54",
+"|  c #ffff5b",
+" . c #e9e978",
+".. c #ffea7b",
+"X. c #ffff63",
+"o. c #fffe6c",
+"O. c #f4f47c",
+"+. c #ffff75",
+"@. c #ffff7a",
+"#. c #838383",
+"$. c #8b8b8b",
+"%. c #949494",
+"&. c #9b9b93",
+"*. c #989898",
+"=. c #b8b898",
+"-. c #b7b7a1",
+";. c #dcdc9e",
+":. c #c6c6b8",
+">. c #c9c9b6",
+",. c #d1d1a6",
+"<. c #dcdcbc",
+"1. c #fff28c",
+"2. c #fffe81",
+"3. c #fffe8b",
+"4. c #fff292",
+"5. c #fffd93",
+"6. c #fffd9b",
+"7. c #eeeea8",
+"8. c #fff3ab",
+"9. c #ffffa2",
+"0. c #ffffad",
+"q. c #ffffb4",
+"w. c #fffebb",
+"e. c #d9d9c6",
+"r. c #e5e5c8",
+"t. c #ebebc7",
+"y. c #ededd4",
+"u. c #fefcc3",
+"i. c #fffdcb",
+"p. c #ffffd2",
+"a. c #ffffdf",
+"s. c #ffffe0",
+"d. c white",
+"f. c None",
+/* pixels */
+"f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.",
+"f.f.f.f.f.f.f.f.f.f.f.f.f.f.6 5     f.f.f.f.f.f.f.f.f.f.f.f.f.f.",
+"f.f.f.f.f.f.f.f.f.f.f.f.f.7 7 7 5     f.f.f.f.f.f.f.f.f.f.f.f.f.",
+"f.f.f.f.f.f.f.f.f.f.f.f.6 6 y y 6 &     f.f.f.f.f.f.f.f.f.f.f.f.",
+"f.f.f.f.f.f.f.f.f.f.f.f.6 0 c c 0 5     f.f.f.f.f.f.f.f.f.f.f.f.",
+"f.f.f.f.f.f.f.f.f.f.f.7 7 k n n k 7 1     f.f.f.f.f.f.f.f.f.f.f.",
+"f.f.f.f.f.f.f.f.f.f.f.6 w S i.i.S w 6     f.f.f.f.f.f.f.f.f.f.f.",
+"f.f.f.f.f.f.f.f.f.f.7 7 x 8.s.s.8.x 7 3     f.f.f.f.f.f.f.f.f.f.",
+"f.f.f.f.f.f.f.f.f.6 7 y ) a.a.s.a.) y 6 &     f.f.f.f.f.f.f.f.f.",
+"f.f.f.f.f.f.f.f.f.7 0 v u.:.%.%.:.u.v 8 4     f.f.f.f.f.f.f.f.f.",
+"f.f.f.f.f.f.f.f.6 6 h ..y.*.*.*.%.e...h 6 ,     f.f.f.f.f.f.f.f.",
+"f.f.f.f.f.f.f.f.7 q D i.r.%.%.%.%.>.i.D w 6     f.f.f.f.f.f.f.f.",
+"f.f.f.f.f.f.f.7 7 x 1.p.t.%.%.%.$.<.p.1.x 8 1     f.f.f.f.f.f.f.",
+"f.f.f.f.f.f.7 7 e _ u.i.i.*.%.$.$.u.u.u.E r 6 #   f.f.f.f.f.f.f.",
+"f.f.f.f.f.f.6 6 M 6.u.u.u.-.$.$.&.u.w.w.4.m 7 4     f.f.f.f.f.f.",
+"f.f.f.f.f.6 7 h ` w.w.w.w.,.#.#.=.q.q.q.0._ h 6 %     f.f.f.f.f.",
+"f.f.f.f.f.8 0 A 5.q.0.q.q.7.; ; ;.9.9.9.6.2.C 0 5     f.f.f.f.f.",
+"f.f.f.f.6 6 z { 9.9.6.6.6.6.a - 6.6.6.5.3.3.' z 6 <     f.f.f.f.",
+"f.f.f.f.7 e H 3.5.5.5.5.5.5.d p 3.3.3.@.@.@.o.G e 6     f.f.f.f.",
+"f.f.f.7 7 b { @.3.@.3.@.3.@.O. .@.+.+.+.o.X.X.~ b 7 4     f.f.f.",
+"f.f.7 7 f I o.o.o.o.o.o.o.o.o.o.X.X.X.| } } [ [ P g 6 #   f.f.f.",
+"f.f.7 0 V ] } } | | | | | s * + i [ [ [ ] ] / / ! V 0 5     f.f.",
+"f.6 7 l U ] ] ] [ ] [ [ [ @ o o o R / ^ ^ ! ! ! ! J l 6 ,     f.",
+"f.7 w F ! ! ^ ^ ^ ^ ^ ^ ^ O X . . T ! Q Q Y Y Y U U F w 5     f.",
+"7 7 b J Y Y Y Y Y Q Q Q Y u . . = U U U U L L L L K K b 6 2     ",
+"6 y K L U U U U U Y U U U U U U U U L L L L K L K K K K y 6     ",
+"7 f N B B B B Z Z Z Z B B B B B B N B N N B N N N N N N f 6     ",
+"6 7 7 8 9 9 9 9 9 9 9 9 9 9 9 9 8 8 9 7 8 8 8 6 7 7 6 7 7 3     ",
+"  & > > & > > & : : : : : : : : & > & > : : : : : : : : $       ",
+"                                                                ",
+"f.                                                            f.",
+"f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f."
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gtk/resources.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,31 @@
+/* XPMs */
+#include "install.xpm"
+#include "install_banner.xpm"
+#include "FILE.xpm"
+#include "FOLDER.xpm"
+
+#define RESOURCE_MAX 4
+
+/* Associated IDs */
+#include "install.h"
+
+long _resource_id[RESOURCE_MAX] = {
+	2000,
+	2001,
+	FOLDERICON,
+	FILEICON
+};
+
+char *_resource_data[RESOURCE_MAX] = {
+	(char *)install_xpm,
+	(char *)install_banner_xpm,
+	(char *)FOLDER_xpm,
+	(char *)FILE_xpm
+};
+
+typedef struct _resource_struct {
+	long resource_max, resource_id;
+	char **resource_data;
+} DWResources;
+
+DWResources _resources = { RESOURCE_MAX, (long)_resource_id, (char **)_resource_data };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/incace/acestruc.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,151 @@
+#ifndef __acestruc_h
+#define __acestruc_h
+
+#include "declare.h"
+#include "portable.h"
+
+#define acesign_len           7
+#define bytes_before_acesign  7
+#define acever               10
+
+struct tech
+{
+   UCHAR TYPE;
+   UCHAR QUAL;
+   USHORT PARM;
+};
+
+typedef struct tacehead
+{
+   USHORT HEAD_CRC;
+   USHORT HEAD_SIZE;
+   UCHAR  HEAD_TYPE;
+   USHORT HEAD_FLAGS;
+   ULONG  ADDSIZE;
+   UCHAR  other[2048];
+
+}  thead;
+
+typedef struct tacemhead
+{
+   USHORT HEAD_CRC;
+   USHORT HEAD_SIZE;
+   UCHAR  HEAD_TYPE;
+   USHORT HEAD_FLAGS;
+
+   UCHAR  ACESIGN[acesign_len];
+   UCHAR  VER_MOD;
+   UCHAR  VER_CR;
+   UCHAR  HOST_CR;
+   UCHAR  VOL_NUM;
+   ULONG  TIME_CR;
+   USHORT RES1;
+   USHORT RES2;
+   ULONG  RES;
+   UCHAR  AV_SIZE;
+   UCHAR  AV[256];
+   USHORT COMM_SIZE;
+   UCHAR  COMM[2048];
+
+}  tmhead;
+
+#ifndef PATH_MAX
+  #define PATH_MAX   512
+#endif
+
+typedef struct tacefhead
+{
+   USHORT HEAD_CRC;
+   USHORT HEAD_SIZE;
+   UCHAR  HEAD_TYPE;
+   USHORT HEAD_FLAGS;
+
+   ULONG  PSIZE;
+   ULONG  SIZE;
+   ULONG  FTIME;
+   ULONG  ATTR;
+   ULONG  CRC32;
+   struct tech TECH;
+   USHORT RESERVED;
+   USHORT FNAME_SIZE;
+   UCHAR  FNAME[PATH_MAX];
+   USHORT COMM_SIZE;
+   UCHAR  COMM[2048];
+
+}  tfhead;
+
+#define mhead    (*t_mhead)
+#define fhead    (*t_fhead)
+#define rhead    (*t_rhead)
+#define tmpmhead (*t_tmpmhead)
+#define tmpfhead (*t_tmpfhead)
+#define tmprhead (*t_tmprhead)
+
+#define mhead_size h_mhead_size(mhead)
+#define fhead_size h_fhead_size(fhead)
+#define rhead_size ((INT)&rhead.REC_CRC-(INT)&head.HEAD_TYPE+sizeof(rhead.REC_CRC))
+
+#define h_mhead_size(phead) ((INT)mhead.AV-(INT)&head.HEAD_TYPE+        \
+                    (phead).AV_SIZE+                                    \
+                    ((phead).HEAD_FLAGS&ACE_COMM?                       \
+                      sizeof((phead).COMM_SIZE)+H_MCOMM_SIZE(phead):0))
+
+
+#define h_fhead_size(phead) ((INT)fhead.FNAME-(INT)&head.HEAD_TYPE+     \
+                    (phead).FNAME_SIZE+                                 \
+                    ((phead).HEAD_FLAGS&ACE_COMM?                       \
+                      sizeof((phead).COMM_SIZE)+H_FCOMM_SIZE(phead):0))
+
+
+//main-comment-definitions
+#define H_MCOMM_SIZE(head) (BUF2WORD((UCHAR*)&(head).AV+(head).AV_SIZE))
+#define MCOMM_SIZE         H_MCOMM_SIZE(mhead)
+#define H_MCOMM(head)      ((UCHAR*)&(head).AV+(head).AV_SIZE+sizeof((head).COMM_SIZE))
+#define MCOMM              H_MCOMM(mhead)
+
+
+//file-comment-definitions
+#define H_FCOMM_SIZE(head) (BUF2WORD((UCHAR*)&(head).FNAME+(head).FNAME_SIZE))
+#define FCOMM_SIZE         H_FCOMM_SIZE(fhead)
+#define H_FCOMM(head)      ((UCHAR*)&(head).FNAME+(head).FNAME_SIZE+sizeof((head).COMM_SIZE))
+#define FCOMM              H_FCOMM(fhead)
+
+//
+#define calc_head_crc getcrc16(CRC_MASK, (CHAR*)&head.HEAD_TYPE, head.HEAD_SIZE)
+#define GET_ADDSIZE   ((head.HEAD_FLAGS & ACE_ADDSIZE) ? head.ADDSIZE : 0)
+
+//archive-header-flags
+#define ACE_LIM256   1024
+#define ACE_MULT_VOL 2048
+#define ACE_AV       4096
+#define ACE_RECOV    8192
+#define ACE_LOCK    16384
+#define ACE_SOLID   32768
+
+//file-header-flags
+#define ACE_ADDSIZE  1
+#define ACE_PASSW    16384
+#define ACE_SP_BEF   4096
+#define ACE_SP_AFTER 8192
+#define ACE_COMM     2
+
+//block types
+#define MAIN_BLK 0
+#define FILE_BLK 1
+#define REC_BLK  2
+
+//known compression types
+#define TYPE_STORE 0
+#define TYPE_LZW1  1
+
+//structure for archive handling
+struct tadat
+{
+   INT   sol,
+         vol,
+         vol_num;
+   ULONG time_cr;
+};
+
+
+#endif /* __acestruc_h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/incace/acestruc.h~	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,151 @@
+#ifndef __acestruc_h
+#define __acestruc_h
+
+#include "dw.h"
+#include "portable.h"
+
+#define acesign_len           7
+#define bytes_before_acesign  7
+#define acever               10
+
+struct tech
+{
+   UCHAR TYPE;
+   UCHAR QUAL;
+   USHORT PARM;
+};
+
+typedef struct tacehead
+{
+   USHORT HEAD_CRC;
+   USHORT HEAD_SIZE;
+   UCHAR  HEAD_TYPE;
+   USHORT HEAD_FLAGS;
+   ULONG  ADDSIZE;
+   UCHAR  other[2048];
+
+}  thead;
+
+typedef struct tacemhead
+{
+   USHORT HEAD_CRC;
+   USHORT HEAD_SIZE;
+   UCHAR  HEAD_TYPE;
+   USHORT HEAD_FLAGS;
+
+   UCHAR  ACESIGN[acesign_len];
+   UCHAR  VER_MOD;
+   UCHAR  VER_CR;
+   UCHAR  HOST_CR;
+   UCHAR  VOL_NUM;
+   ULONG  TIME_CR;
+   USHORT RES1;
+   USHORT RES2;
+   ULONG  RES;
+   UCHAR  AV_SIZE;
+   UCHAR  AV[256];
+   USHORT COMM_SIZE;
+   UCHAR  COMM[2048];
+
+}  tmhead;
+
+#ifndef PATH_MAX
+  #define PATH_MAX   512
+#endif
+
+typedef struct tacefhead
+{
+   USHORT HEAD_CRC;
+   USHORT HEAD_SIZE;
+   UCHAR  HEAD_TYPE;
+   USHORT HEAD_FLAGS;
+
+   ULONG  PSIZE;
+   ULONG  SIZE;
+   ULONG  FTIME;
+   ULONG  ATTR;
+   ULONG  CRC32;
+   struct tech TECH;
+   USHORT RESERVED;
+   USHORT FNAME_SIZE;
+   UCHAR  FNAME[PATH_MAX];
+   USHORT COMM_SIZE;
+   UCHAR  COMM[2048];
+
+}  tfhead;
+
+#define mhead    (*t_mhead)
+#define fhead    (*t_fhead)
+#define rhead    (*t_rhead)
+#define tmpmhead (*t_tmpmhead)
+#define tmpfhead (*t_tmpfhead)
+#define tmprhead (*t_tmprhead)
+
+#define mhead_size h_mhead_size(mhead)
+#define fhead_size h_fhead_size(fhead)
+#define rhead_size ((INT)&rhead.REC_CRC-(INT)&head.HEAD_TYPE+sizeof(rhead.REC_CRC))
+
+#define h_mhead_size(phead) ((INT)mhead.AV-(INT)&head.HEAD_TYPE+        \
+                    (phead).AV_SIZE+                                    \
+                    ((phead).HEAD_FLAGS&ACE_COMM?                       \
+                      sizeof((phead).COMM_SIZE)+H_MCOMM_SIZE(phead):0))
+
+
+#define h_fhead_size(phead) ((INT)fhead.FNAME-(INT)&head.HEAD_TYPE+     \
+                    (phead).FNAME_SIZE+                                 \
+                    ((phead).HEAD_FLAGS&ACE_COMM?                       \
+                      sizeof((phead).COMM_SIZE)+H_FCOMM_SIZE(phead):0))
+
+
+//main-comment-definitions
+#define H_MCOMM_SIZE(head) (BUF2WORD((UCHAR*)&(head).AV+(head).AV_SIZE))
+#define MCOMM_SIZE         H_MCOMM_SIZE(mhead)
+#define H_MCOMM(head)      ((UCHAR*)&(head).AV+(head).AV_SIZE+sizeof((head).COMM_SIZE))
+#define MCOMM              H_MCOMM(mhead)
+
+
+//file-comment-definitions
+#define H_FCOMM_SIZE(head) (BUF2WORD((UCHAR*)&(head).FNAME+(head).FNAME_SIZE))
+#define FCOMM_SIZE         H_FCOMM_SIZE(fhead)
+#define H_FCOMM(head)      ((UCHAR*)&(head).FNAME+(head).FNAME_SIZE+sizeof((head).COMM_SIZE))
+#define FCOMM              H_FCOMM(fhead)
+
+//
+#define calc_head_crc getcrc16(CRC_MASK, (CHAR*)&head.HEAD_TYPE, head.HEAD_SIZE)
+#define GET_ADDSIZE   ((head.HEAD_FLAGS & ACE_ADDSIZE) ? head.ADDSIZE : 0)
+
+//archive-header-flags
+#define ACE_LIM256   1024
+#define ACE_MULT_VOL 2048
+#define ACE_AV       4096
+#define ACE_RECOV    8192
+#define ACE_LOCK    16384
+#define ACE_SOLID   32768
+
+//file-header-flags
+#define ACE_ADDSIZE  1
+#define ACE_PASSW    16384
+#define ACE_SP_BEF   4096
+#define ACE_SP_AFTER 8192
+#define ACE_COMM     2
+
+//block types
+#define MAIN_BLK 0
+#define FILE_BLK 1
+#define REC_BLK  2
+
+//known compression types
+#define TYPE_STORE 0
+#define TYPE_LZW1  1
+
+//structure for archive handling
+struct tadat
+{
+   INT   sol,
+         vol,
+         vol_num;
+   ULONG time_cr;
+};
+
+
+#endif /* __acestruc_h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/incace/attribs.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,33 @@
+#ifndef __attribs_h
+#define __attribs_h
+
+
+#ifndef _A_SUBDIR
+  #define _A_SUBDIR 0x10        // MS-DOS directory constant
+#endif
+
+#ifndef S_IEXEC
+  #ifdef S_IEXECUTE
+    #define S_IEXEC S_IEXECUTE
+  #else
+    #define S_IEXEC 0
+  #endif
+#endif
+
+#ifndef S_IDELETE
+  #define S_IDELETE 0
+#endif
+
+#ifndef S_IRGRP 
+  #define S_IRGRP 0
+  #define S_IWGRP 0
+#endif
+
+#ifndef S_IROTH 
+  #define S_IROTH 0
+  #define S_IWOTH 0
+#endif
+
+
+#endif /* __attribs_h */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/incace/declare.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,13 @@
+/******************************************************/
+/*                                                    */
+/* declare.h: declaration-symbols (UCHAR, ULONG, ...) */
+/*                                                    */
+/******************************************************/
+
+#ifndef __declare_h
+#define __declare_h
+
+#include "dw.h"
+
+#endif /* __declare_h */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/incace/declare.h~	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,27 @@
+/******************************************************/
+/*                                                    */
+/* declare.h: declaration-symbols (UCHAR, ULONG, ...) */
+/*                                                    */
+/******************************************************/
+
+#ifndef __declare_h
+#define __declare_h
+
+#if defined(__CYGWIN__)
+#include <Windows32/Base.h>
+#endif 
+
+#ifdef AMIGA
+
+#include <exec/types.h>
+
+#endif  /* !AMIGA */
+
+typedef unsigned short UWORD ;
+typedef short          WORD  ;
+typedef unsigned       UINT  ;
+typedef int            INT   ;
+
+
+#endif /* __declare_h */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/incace/globals.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,90 @@
+/* ------------------------------------------------------------------------ */
+/*                                                                          */
+/*      Global variable definitions                                         */
+/*                                                                          */
+/* ------------------------------------------------------------------------ */
+
+#ifndef __globals_h
+#define __globals_h
+
+#include "acestruc.h"
+#include "unace.h"
+
+//-------- Ace sign
+extern const char *acesign;
+
+//-------- Version string for program
+extern const char *version;
+
+//-------- header buffer and pointers
+extern thead head;
+
+extern tmhead *t_mhead;
+extern tfhead *t_fhead;
+
+//-------- buffers
+extern ULONG *buf_rd ;
+extern CHAR  *buf    ;
+extern CHAR  *buf_wr ;
+extern UCHAR *readbuf;
+
+//-------- decompressor variables
+extern
+SHORT rpos          ,
+      dcpr_do       ,
+      dcpr_do_max   ,
+      blocksize     ,
+      dcpr_dic      ,
+      dcpr_oldnum   ,
+      bits_rd       ,
+      dcpr_frst_file;
+extern
+USHORT dcpr_code_mn[1 << maxwd_mn],
+       dcpr_code_lg[1 << maxwd_lg];
+extern
+UCHAR dcpr_wd_mn[maxcode + 2],
+      dcpr_wd_lg[maxcode + 2],
+      wd_svwd[svwd_cnt];
+extern
+ULONG dcpr_dpos      ,
+      cpr_dpos2      ,
+      dcpr_dicsiz    ,
+      dcpr_dican     ,
+      dcpr_size      ,
+      dcpr_olddist[4],
+      code_rd        ;
+extern
+CHAR *dcpr_text      ;
+
+//-------- quicksort
+extern USHORT sort_org[maxcode + 2];
+extern UCHAR sort_freq[(maxcode + 2) * 2];
+
+//-------- file handling
+extern CHAR aname[PATH_MAX];
+extern
+INT  archan,
+     wrhan;
+#if !defined(__EMX__) && !defined(__OS2__)
+extern FILE *farchan;
+#endif
+     
+extern LONG skipsize;
+
+//-------- structures for archive handling
+extern struct tadat adat;
+
+//-------- flags
+extern
+INT  f_err      ,
+     f_ovrall   ,
+     f_allvol_pr,
+     f_curpas   ,
+     f_criterr  ;
+
+int pipeit(char *format, ...);
+void error(char *format, ...);
+int confirm(char *format, ...);
+
+#endif /* __globals_h */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/incace/os.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,34 @@
+#ifndef __os_h
+#define __os_h
+
+
+#if defined(AMIGA)
+#ifndef DIRSEP
+#define DIRSEP '/'
+#endif
+#define HI_LO_BYTE_ORDER
+#endif
+
+#if defined(DOS) || defined(WINNT) || defined(WIN16)
+#ifndef DIRSEP
+#define DIRSEP '\\'
+#endif
+#define LO_HI_BYTE_ORDER
+#endif
+
+#if defined(OS2) || defined(__EMX__)
+#ifndef DIRSEP
+#define DIRSEP '\\'
+#endif
+#define LO_HI_BYTE_ORDER
+#endif
+
+#if defined(UNIX)
+#ifndef DIRSEP
+#define DIRSEP '/'
+#endif
+#define HI_LO_BYTE_ORDER
+#endif
+
+
+#endif /* __os_h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/incace/portable.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,101 @@
+/****************************************************************/
+/*                                                              */
+/*   A collection of routines used in making ACE portable for   */
+/*   different computers                                        */
+/*                                                              */
+/****************************************************************/
+
+#ifndef __portable_h
+#define __portable_h
+
+#include "os.h"
+
+#ifdef  HI_LO_BYTE_ORDER
+
+/* All kinds of inplace swap routines, to reverse from LOHI to HILO byte order */
+
+#ifdef AMIGA
+
+#if __SASC && __VERSION__>=6 && __REVISION__>=58
+
+#define WORDswap(n)  (*(n) = __builtin_rol(*(n), 8, 1))
+#define LONGswap(n)  ( WORDswap(&((WORD *)(n))[0]),\
+                       WORDswap(&((WORD *)(n))[1]),\
+                       *(n) = __builtin_rol(*(n), 16, 2) )
+#else /* __SASC */
+
+#define EORSWAP
+
+#endif /* !__SASC */
+
+#endif /* AMIGA  */
+
+
+#ifdef EORSWAP
+
+/*  With some compilers and processors these work faster then the
+ *  regular swap below, for example on a Amiga 68040 using SAS C 6.58.
+ *  But using builtin rotates works even faster, see above.
+ */
+
+#define WORDswap(n) (((BYTE*)(n))[0] ^= ((BYTE*)(n))[1],\
+                     ((BYTE*)(n))[1] ^= ((BYTE*)(n))[0],\
+                     ((BYTE*)(n))[0] ^= ((BYTE*)(n))[1])
+#define LONGswap(n) (((BYTE*)(n))[0] ^= ((BYTE*)(n))[3],\
+                     ((BYTE*)(n))[3] ^= ((BYTE*)(n))[0],\
+                     ((BYTE*)(n))[0] ^= ((BYTE*)(n))[3],\
+                     ((BYTE*)(n))[1] ^= ((BYTE*)(n))[2],\
+                     ((BYTE*)(n))[2] ^= ((BYTE*)(n))[1],\
+                     ((BYTE*)(n))[1] ^= ((BYTE*)(n))[2])
+#endif  /* EORSWAP */
+
+#ifndef WORDswap
+
+/* If not yet defined use the standard swaps */
+
+#define WORDswap(n)  (*(n) = (*(n) << 8) | (*(n) >> 8))
+#define LONGswap(n)  ( WORDswap(&((WORD *)(n))[0]),\
+                       WORDswap(&((WORD *)(n))[1]),\
+                       *(n) = (*(n) >> 16) | (*(n) << 16) )
+#endif /* WORDSWAP */
+
+#endif /* HI_LO_BYTE_ORDER */
+
+
+/* GENERIC: Convert to LONG or WORD from BYTE-Pointer-to-LOHI-byte-order data,
+ *          without worrying if the bytes are word alined in memory.
+ *  p is a pointer to char.
+ */
+
+#ifdef HI_LO_BYTE_ORDER
+
+#define BUFP2WORD(p) ((UWORD)*(p)++ | ((*(p)++)<<8))
+#define BUFP2LONG(p) ((ULONG)*(p)++ | ((*(p)++)<<8) | ((*(p)++)<<16) | ((*(p)++)<<24))
+
+#define BUF2WORD(p) ((UWORD)*(p) | (*((p)+1)<<8))
+#define BUF2LONG(p) ((ULONG)*(p) | (*((p)+1)<<8) | (*((p)+2)<<16) | (*((p)+3)<<24))
+
+#else /* HI_LO_BYTE_ORDER */
+
+#define BUFP2WORD(p) *(UWORD*)((p+=2)-2)
+#define BUFP2LONG(p) *(ULONG*)((p+=4)-4)
+
+#define BUF2WORD(p) (*(UWORD*)p)
+#define BUF2LONG(p) (*(ULONG*)p)
+
+#endif /* !HI_LO_BYTE_ORDER */
+
+/* Timestamp macros */
+
+#define get_tx(m,d,h,n) (((ULONG)m<<21)+((ULONG)d<<16)+((ULONG)h<<11)+(n<<5))
+#define get_tstamp(y,m,d,h,n,s) ((((ULONG)(y-1980))<<25)+get_tx(m,d,h,n)+(s/2))
+
+#define ts_year(ts)  ((UINT)((ts >> 25) & 0x7f) + 1980)
+#define ts_month(ts) ((UINT)(ts >> 21) & 0x0f)      // 1..12 means Jan..Dec
+#define ts_day(ts)   ((UINT)(ts >> 16) & 0x1f)      // 1..31 means 1st..31st
+#define ts_hour(ts)  ((UINT)(ts >> 11) & 0x1f)
+#define ts_min(ts)   ((UINT)(ts >> 5) & 0x3f)
+#define ts_sec(ts)   ((UINT)((ts & 0x1f) * 2))
+
+
+#endif /* __portable_h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/incace/uac_comm.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,14 @@
+#ifndef __uac_comm_h
+#define __uac_comm_h
+
+
+#include "declare.h"
+
+extern INT  comm_cpr_size;
+extern CHAR *comm;
+
+void comment_out(CHAR *top);
+
+
+#endif /* __uac_comm_h */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/incace/uac_crc.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,20 @@
+#ifndef __uac_crc_h
+#define __uac_crc_h
+
+
+#include "declare.h"
+
+#define CRC_MASK 0xFFFFFFFFL
+#define CRCPOLY  0xEDB88320L
+
+
+extern ULONG crctable[256];
+extern ULONG rd_crc;
+
+
+ULONG getcrc(ULONG crc, UCHAR * addr, INT len);
+void  make_crctable(void);
+
+
+#endif /* __uac_crc_h */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/incace/uac_crt.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,12 @@
+#ifndef __uac_crt_h
+#define __uac_crt_h
+
+
+#include "acestruc.h"
+
+CHAR *ace_fname(CHAR * s, thead * head, INT nopath);
+INT  create_dest_file(CHAR * file, INT a);
+
+
+#endif /* __uac_crt_h */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/incace/uac_dcpr.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,14 @@
+#ifndef __uac_dcpr_h
+#define __uac_dcpr_h
+
+#include "declare.h"
+
+INT  calc_dectabs(void);
+void dcpr_comm(INT comm_size);
+INT  read_wd(UINT maxwd, USHORT * code, UCHAR * wd, INT max_el);
+void dcpr_init(void);
+INT  dcpr_adds_blk(CHAR * buf, UINT len);
+void dcpr_init_file(void);
+
+#endif /* __uac_dcpr_h */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/incace/uac_sys.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,18 @@
+#ifndef __uac_sys_h
+#define __uac_sys_h
+
+
+#include "declare.h"
+
+#define upcase(ch) ((in(ch,'a','z'))?(ch-32):(ch))
+
+void memset16(USHORT * dest, SHORT val, INT len);
+INT  cancel(void);
+INT  wrask(CHAR * s);
+#if !defined(__MINGW32__)
+void beep(void);
+#endif
+void set_handler(void);
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/incace/unace.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,66 @@
+#ifndef __unace_h
+#define __unace_h
+
+
+#include "declare.h"
+
+
+//--------- functions
+
+INT read_adds_blk(CHAR * buffer, INT len);
+
+
+//--------- buffers: increase sizes when possible to speed up the program
+
+#define size_rdb  1024
+#define size_wrb  2048
+#define size_buf  1024
+
+#define size_headrdb (sizeof(head)-20) // (some bytes less esp. for Amiga)
+
+
+//--------- (de-)compressor constants
+
+#define maxdic      22
+#define maxwd_mn    11
+#define maxwd_lg    11
+#define maxwd_svwd   7
+#define maxlength  259
+#define maxdis2    255
+#define maxdis3   8191
+#define maxcode   (255+4+maxdic)
+#define svwd_cnt    15
+#define max_cd_mn (256+4+(maxdic+1)-1)
+#define max_cd_lg (256-1)
+
+//--------- flags
+
+#define ERR_MEM      1
+#define ERR_FILES    2
+#define ERR_FOUND    3
+#define ERR_FULL     4
+#define ERR_OPEN     5
+#define ERR_READ     6
+#define ERR_WRITE    7
+#define ERR_CLINE    8
+#define ERR_CRC      9
+#define ERR_OTHER   10
+#define ERR_USER   255
+
+//--------- system things
+
+#define flush fflush(stdout);
+
+#define in(v1,v2,v3) ((((long)v1)>=(v2)) && (((long)v1)<=(v3)))
+
+#define delay_len 500
+
+//-------- file creation
+
+#define fileexists(name) (!access(name, 0))
+
+
+//-------- eof
+
+#endif /* __unace_h */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inczip/consts.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,46 @@
+/*---------------------------------------------------------------------------
+
+  consts.h
+
+  This file contains global, initialized variables that never change.  It is
+  included by unzip.c and windll/windll.c.
+
+  ---------------------------------------------------------------------------*/
+
+
+/* And'ing with mask_bits[n] masks the lower n bits */
+ZCONST ush near mask_bits[] = {
+    0x0000,
+    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+ZCONST char Far VersionDate[] = VERSION_DATE;   /* now defined in version.h */
+
+#ifndef SFX
+   ZCONST char Far EndSigMsg[] = 
+   "\nnote:  didn't find end-of-central-dir signature at end of central dir.\n";
+#endif
+
+ZCONST char Far CentSigMsg[] =
+  "error:  expected central file header signature not found (file #%u).\n";
+ZCONST char Far SeekMsg[] =
+  "error [%s]:  attempt to seek before beginning of zipfile\n%s";
+ZCONST char Far FilenameNotMatched[] = "caution: filename not matched:  %s\n";
+ZCONST char Far ExclFilenameNotMatched[] =
+  "caution: excluded filename not matched:  %s\n";
+
+#ifdef VMS
+  ZCONST char Far ReportMsg[] = "\
+  (please check that you have transferred or created the zipfile in the\n\
+  appropriate BINARY mode--this includes ftp, Kermit, AND unzip'd zipfiles)\n";
+#else
+  ZCONST char Far ReportMsg[] = "\
+  (please check that you have transferred or created the zipfile in the\n\
+  appropriate BINARY mode and that you have compiled UnZip properly)\n";
+#endif
+
+#ifndef SFX
+  ZCONST char Far Zipnfo[] = "zipinfo";
+  ZCONST char Far CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n";
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inczip/crypt.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,24 @@
+/*
+   crypt.h (dummy version) by Info-ZIP.      Last revised: 15 Aug 98
+
+   This is a non-functional version of Info-ZIP's crypt.h encryption/
+   decryption header file for Zip, ZipCloak, UnZip and fUnZip.  This
+   file is not copyrighted and may be distributed without restriction.
+   See the "WHERE" file for sites from which to obtain the full crypt
+   sources (zcrypt28.zip or later).
+ */
+
+#ifndef __crypt_h   /* don't include more than once */
+#define __crypt_h
+
+#ifdef CRYPT
+#  undef CRYPT
+#endif
+#define CRYPT  0    /* dummy version */
+
+#define zencode
+#define zdecode
+
+#define zfwrite  fwrite
+
+#endif /* !__crypt_h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inczip/ebcdic.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,272 @@
+/*---------------------------------------------------------------------------
+
+  ebcdic.h
+
+  The CECP 1047 (Extended de-facto EBCDIC) <-> ISO 8859-1 conversion tables,
+  from ftp://aix1.segi.ulg.ac.be/pub/docs/iso8859/iso8859.networking
+
+  NOTES:
+  <Paul_von_Behren@stortek.com> (OS/390 port 12/97)
+   These table no longer represent the standard mappings (for example in the
+   OS/390 iconv utility).  In order to follow current standards I remapped
+     ebcdic x0a to ascii x15    and
+     ebcdic x85 to ascii x25    (and vice-versa)
+   Without these changes, newlines in auto-convert text files appeared
+   as literal \045.
+   I'm not sure what effect this remap would have on the MVS and CMS ports, so
+   I ifdef'd these changes.  Hopefully these ifdef's can be removed when the
+   MVS/CMS folks test the new mappings.
+
+  Christian Spieler <spieler@ikp.tu-darmstadt.de>, 27-Apr-1998
+   The problem mentioned by Paul von Behren was already observed previously
+   on VM/CMS, during the preparation of the CMS&MVS port of UnZip 5.20 in
+   1996. At that point, the ebcdic tables were not changed since they seemed
+   to be an adopted standard (to my knowledge, these tables are still used
+   as presented in mainfraime KERMIT). Instead, the "end-of-line" conversion
+   feature of Zip's and UnZip's "text-translation" mode was used to force
+   correct mappings between ASCII and EBCDIC newline markers.
+   Before interchanging the ASCII mappings of the EBCDIC control characters
+   "NL" 0x25 and "LF" 0x15 according to the OS/390 setting, we have to
+   make sure that EBCDIC 0x15 is never used as line termination.
+
+  ---------------------------------------------------------------------------*/
+
+#ifndef __ebcdic_h      /* prevent multiple inclusions */
+#define __ebcdic_h
+
+
+#ifndef ZCONST
+#  define ZCONST const
+#endif
+
+#ifdef EBCDIC
+#ifndef MTS             /* MTS uses a slightly "special" EBCDIC code page */
+
+ZCONST uch ebcdic[] = {
+    0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,  /* 00 - 07 */
+#ifdef OS390
+    0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  /* 08 - 0F */
+#else
+    0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  /* 08 - 0F */
+#endif
+    0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,  /* 10 - 17 */
+    0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,  /* 18 - 1F */
+    0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,  /* 20 - 27 */
+    0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,  /* 28 - 2F */
+    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,  /* 30 - 37 */
+    0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,  /* 38 - 3F */
+    0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,  /* 40 - 47 */
+    0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,  /* 48 - 4F */
+    0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,  /* 50 - 57 */
+    0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,  /* 58 - 5F */
+    0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,  /* 60 - 67 */
+    0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,  /* 68 - 6F */
+    0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,  /* 70 - 77 */
+    0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,  /* 78 - 7F */
+#ifdef OS390
+    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x06, 0x17,  /* 80 - 87 */
+#else
+    0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17,  /* 80 - 87 */
+#endif
+    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B,  /* 88 - 8F */
+    0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08,  /* 90 - 97 */
+    0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF,  /* 98 - 9F */
+    0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5,  /* A0 - A7 */
+    0xBB, 0xB4, 0x9A, 0x8A, 0xB0, 0xCA, 0xAF, 0xBC,  /* A8 - AF */
+    0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3,  /* B0 - B7 */
+    0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB,  /* B8 - BF */
+    0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68,  /* C0 - C7 */
+    0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77,  /* C8 - CF */
+    0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF,  /* D0 - D7 */
+    0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xBA, 0xAE, 0x59,  /* D8 - DF */
+    0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48,  /* E0 - E7 */
+    0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57,  /* E8 - EF */
+    0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1,  /* F0 - F7 */
+    0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF   /* F8 - FF */
+};
+
+#if (defined(ZIP) || CRYPT)
+ZCONST uch ascii[] = {
+    0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F,  /* 00 - 07 */
+    0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  /* 08 - 0F */
+#ifdef OS390
+    0x10, 0x11, 0x12, 0x13, 0x9D, 0x0A, 0x08, 0x87,  /* 10 - 17 */
+#else
+    0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87,  /* 10 - 17 */
+#endif
+    0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,  /* 18 - 1F */
+#ifdef OS390
+    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x17, 0x1B,  /* 20 - 27 */
+#else
+    0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B,  /* 20 - 27 */
+#endif
+    0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,  /* 28 - 2F */
+    0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,  /* 30 - 37 */
+    0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,  /* 38 - 3F */
+    0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5,  /* 40 - 47 */
+    0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,  /* 48 - 4F */
+    0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF,  /* 50 - 57 */
+    0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,  /* 58 - 5F */
+    0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5,  /* 60 - 67 */
+    0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,  /* 68 - 6F */
+    0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF,  /* 70 - 77 */
+    0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,  /* 78 - 7F */
+    0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,  /* 80 - 87 */
+    0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1,  /* 88 - 8F */
+    0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,  /* 90 - 97 */
+    0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4,  /* 98 - 9F */
+    0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,  /* A0 - A7 */
+    0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0x5B, 0xDE, 0xAE,  /* A8 - AF */
+    0xAC, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC,  /* B0 - B7 */
+    0xBD, 0xBE, 0xDD, 0xA8, 0xAF, 0x5D, 0xB4, 0xD7,  /* B8 - BF */
+    0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,  /* C0 - C7 */
+    0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5,  /* C8 - CF */
+    0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,  /* D0 - D7 */
+    0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF,  /* D8 - DF */
+    0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,  /* E0 - E7 */
+    0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5,  /* E8 - EF */
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,  /* F0 - F7 */
+    0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F   /* F8 - FF */
+};
+#endif /* ZIP || CRYPT */
+
+#else /* MTS */
+
+/*
+ * This is the MTS ASCII->EBCDIC translation table. It provides a 1-1
+ * translation from ISO 8859/1 8-bit ASCII to IBM Code Page 37 EBCDIC.
+ */
+
+ZCONST uch ebcdic[] = {
+    0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,  /* 00 - 07 */
+    0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  /* 08 - 0F */
+    0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,  /* 10 - 17 */
+    0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,  /* 18 - 1F */
+    0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,  /* 20 - 27 */
+    0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,  /* 28 - 2F */
+    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,  /* 30 - 37 */
+    0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,  /* 38 - 3F */
+    0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,  /* 40 - 47 */
+    0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,  /* 48 - 4F */
+    0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,  /* 50 - 57 */
+    0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D,  /* 58 - 5F */
+    0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,  /* 60 - 67 */
+    0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,  /* 68 - 6F */
+    0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,  /* 70 - 77 */
+    0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,  /* 78 - 7F */
+    0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17,  /* 80 - 87 */
+    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B,  /* 88 - 8F */
+    0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08,  /* 90 - 97 */
+    0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF,  /* 98 - 9F */
+    0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5,  /* A0 - A7 */
+    0xBD, 0xB4, 0x9A, 0x8A, 0x5F, 0xCA, 0xAF, 0xBC,  /* A8 - AF */
+    0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3,  /* B0 - B7 */
+    0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB,  /* B8 - BF */
+    0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68,  /* C0 - C7 */
+    0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77,  /* C8 - CF */
+    0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF,  /* D0 - D7 */
+    0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xAD, 0xAE, 0x59,  /* D8 - DF */
+    0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48,  /* E0 - E7 */
+    0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57,  /* E8 - EF */
+    0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1,  /* F0 - F7 */
+    0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF   /* F8 - FF */
+};
+
+#if (defined(ZIP) || CRYPT)
+ZCONST uch ascii[] = {
+    0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F,  /* 00 - 07 */
+    0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  /* 08 - 0F */
+    0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87,  /* 10 - 17 */
+    0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,  /* 18 - 1F */
+    0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B,  /* 20 - 27 */
+    0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,  /* 28 - 2F */
+    0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,  /* 30 - 37 */
+    0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,  /* 38 - 3F */
+    0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5,  /* 40 - 47 */
+    0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,  /* 48 - 4F */
+    0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF,  /* 50 - 57 */
+    0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAC,  /* 58 - 5F */
+    0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5,  /* 60 - 67 */
+    0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,  /* 68 - 6F */
+    0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF,  /* 70 - 77 */
+    0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,  /* 78 - 7F */
+    0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,  /* 80 - 87 */
+    0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1,  /* 88 - 8F */
+    0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,  /* 90 - 97 */
+    0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4,  /* 98 - 9F */
+    0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,  /* A0 - A7 */
+    0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0xDD, 0xDE, 0xAE,  /* A8 - AF */
+    0x5E, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC,  /* B0 - B7 */
+    0xBD, 0xBE, 0x5B, 0x5D, 0xAF, 0xA8, 0xB4, 0xD7,  /* B8 - BF */
+    0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,  /* C0 - C7 */
+    0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5,  /* C8 - CF */
+    0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,  /* D0 - D7 */
+    0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF,  /* D8 - DF */
+    0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,  /* E0 - E7 */
+    0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5,  /* E8 - EF */
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,  /* F0 - F7 */
+    0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F   /* F8 - FF */
+};
+#endif /* ZIP || CRYPT */
+
+#endif /* ?MTS */
+#endif /* EBCDIC */
+
+/*---------------------------------------------------------------------------
+
+  The following conversion tables translate between IBM PC CP 850
+  (OEM codepage) and the "Western Europe & America" Windows codepage 1252.
+  The Windows codepage 1252 contains the ISO 8859-1 "Latin 1" codepage,
+  with some additional printable characters in the range (0x80 - 0x9F),
+  that is reserved to control codes in the ISO 8859-1 character table.
+
+  The ISO <--> OEM conversion tables were constructed with the help
+  of the WIN32 (Win16?) API's OemToAnsi() and AnsiToOem() conversion
+  functions and have been checked against the CP850 and LATIN1 tables
+  provided in the MS-Kermit 3.14 distribution.
+
+  ---------------------------------------------------------------------------*/
+
+#ifdef IZ_ISO2OEM_ARRAY
+ZCONST uch Far iso2oem[] = {
+    0x3F, 0x3F, 0x27, 0x9F, 0x22, 0x2E, 0xC5, 0xCE,  /* 80 - 87 */
+    0x5E, 0x25, 0x53, 0x3C, 0x4F, 0x3F, 0x3F, 0x3F,  /* 88 - 8F */
+    0x3F, 0x27, 0x27, 0x22, 0x22, 0x07, 0x2D, 0x2D,  /* 90 - 97 */
+    0x7E, 0x54, 0x73, 0x3E, 0x6F, 0x3F, 0x3F, 0x59,  /* 98 - 9F */
+    0xFF, 0xAD, 0xBD, 0x9C, 0xCF, 0xBE, 0xDD, 0xF5,  /* A0 - A7 */
+    0xF9, 0xB8, 0xA6, 0xAE, 0xAA, 0xF0, 0xA9, 0xEE,  /* A8 - AF */
+    0xF8, 0xF1, 0xFD, 0xFC, 0xEF, 0xE6, 0xF4, 0xFA,  /* B0 - B7 */
+    0xF7, 0xFB, 0xA7, 0xAF, 0xAC, 0xAB, 0xF3, 0xA8,  /* B8 - BF */
+    0xB7, 0xB5, 0xB6, 0xC7, 0x8E, 0x8F, 0x92, 0x80,  /* C0 - C7 */
+    0xD4, 0x90, 0xD2, 0xD3, 0xDE, 0xD6, 0xD7, 0xD8,  /* C8 - CF */
+    0xD1, 0xA5, 0xE3, 0xE0, 0xE2, 0xE5, 0x99, 0x9E,  /* D0 - D7 */
+    0x9D, 0xEB, 0xE9, 0xEA, 0x9A, 0xED, 0xE8, 0xE1,  /* D8 - DF */
+    0x85, 0xA0, 0x83, 0xC6, 0x84, 0x86, 0x91, 0x87,  /* E0 - E7 */
+    0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B,  /* E8 - EF */
+    0xD0, 0xA4, 0x95, 0xA2, 0x93, 0xE4, 0x94, 0xF6,  /* F0 - F7 */
+    0x9B, 0x97, 0xA3, 0x96, 0x81, 0xEC, 0xE7, 0x98   /* F8 - FF */
+};
+#endif /* IZ_ISO2OEM_ARRAY */
+
+#ifdef IZ_OEM2ISO_ARRAY
+ZCONST uch Far oem2iso[] = {
+    0xC7, 0xFC, 0xE9, 0xE2, 0xE4, 0xE0, 0xE5, 0xE7,  /* 80 - 87 */
+    0xEA, 0xEB, 0xE8, 0xEF, 0xEE, 0xEC, 0xC4, 0xC5,  /* 88 - 8F */
+    0xC9, 0xE6, 0xC6, 0xF4, 0xF6, 0xF2, 0xFB, 0xF9,  /* 90 - 97 */
+    0xFF, 0xD6, 0xDC, 0xF8, 0xA3, 0xD8, 0xD7, 0x83,  /* 98 - 9F */
+    0xE1, 0xED, 0xF3, 0xFA, 0xF1, 0xD1, 0xAA, 0xBA,  /* A0 - A7 */
+    0xBF, 0xAE, 0xAC, 0xBD, 0xBC, 0xA1, 0xAB, 0xBB,  /* A8 - AF */
+    0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xC1, 0xC2, 0xC0,  /* B0 - B7 */
+    0xA9, 0xA6, 0xA6, 0x2B, 0x2B, 0xA2, 0xA5, 0x2B,  /* B8 - BF */
+    0x2B, 0x2D, 0x2D, 0x2B, 0x2D, 0x2B, 0xE3, 0xC3,  /* C0 - C7 */
+    0x2B, 0x2B, 0x2D, 0x2D, 0xA6, 0x2D, 0x2B, 0xA4,  /* C8 - CF */
+    0xF0, 0xD0, 0xCA, 0xCB, 0xC8, 0x69, 0xCD, 0xCE,  /* D0 - D7 */
+    0xCF, 0x2B, 0x2B, 0xA6, 0x5F, 0xA6, 0xCC, 0xAF,  /* D8 - DF */
+    0xD3, 0xDF, 0xD4, 0xD2, 0xF5, 0xD5, 0xB5, 0xFE,  /* E0 - E7 */
+    0xDE, 0xDA, 0xDB, 0xD9, 0xFD, 0xDD, 0xAF, 0xB4,  /* E8 - EF */
+    0xAD, 0xB1, 0x3D, 0xBE, 0xB6, 0xA7, 0xF7, 0xB8,  /* F0 - F7 */
+    0xB0, 0xA8, 0xB7, 0xB9, 0xB3, 0xB2, 0xA6, 0xA0   /* F8 - FF */
+};
+#endif /* IZ_OEM2ISO_ARRAY */
+
+#endif /* __ebcdic_h  */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inczip/globals.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,395 @@
+/*---------------------------------------------------------------------------
+
+  globals.h
+
+  There is usually no need to include this file since unzip.h includes it.
+
+  This header file is used by all of the UnZip source files.  It contains
+  a struct definition that is used to "house" all of the global variables.
+  This is done to allow for multithreaded environments (OS/2, NT, Win95,
+  Unix) to call UnZip through an API without a semaphore.  REENTRANT should
+  be defined for all platforms that require this.
+
+  GLOBAL CONSTRUCTOR AND DESTRUCTOR (API WRITERS READ THIS!!!)
+  ------------------------------------------------------------
+
+  No, it's not C++, but it's as close as we can get with K&R.
+
+  The main() of each process that uses these globals must include the
+  CONSTRUCTGLOBALS; statement.  This will malloc enough memory for the
+  structure and initialize any variables that require it.  This must
+  also be done by any API function that jumps into the middle of the
+  code.
+
+  The DESTROYGLOBALS; statement should be inserted before EVERY "EXIT(n)".
+  Naturally, it also needs to be put before any API returns as well.
+  In fact, it's much more important in API functions since the process
+  will NOT end, and therefore the memory WON'T automatically be freed
+  by the operating system.
+
+  USING VARIABLES FROM THE STRUCTURE
+  ----------------------------------
+
+  All global variables must now be prefixed with `G.' which is either a
+  global struct (in which case it should be the only global variable) or
+  a macro for the value of a local pointer variable that is passed from
+  function to function.  Yes, this is a pain.  But it's the only way to
+  allow full reentrancy.
+
+  ADDING VARIABLES TO THE STRUCTURE
+  ---------------------------------
+
+  If you make the inclusion of any variables conditional, be sure to only
+  check macros that are GUARANTEED to be included in every module.
+  For instance, newzip and pwdarg are needed only if CRYPT is TRUE,
+  but this is defined after unzip.h has been read.  If you are not careful,
+  some modules will expect your variable to be part of this struct while
+  others won't.  This will cause BIG problems. (Inexplicable crashes at
+  strange times, car fires, etc.)  When in doubt, always include it!
+
+  Note also that UnZipSFX needs a few variables that UnZip doesn't.  However,
+  it also includes some object files from UnZip.  If we were to conditionally
+  include the extra variables that UnZipSFX needs, the object files from
+  UnZip would not mesh with the UnZipSFX object files.  Result: we just
+  include the UnZipSFX variables every time.  (It's only an extra 4 bytes
+  so who cares!)
+
+  ADDING FUNCTIONS
+  ----------------
+
+  To support this new global struct, all functions must now conditionally
+  pass the globals pointer (pG) to each other.  This is supported by 5 macros:
+  __GPRO, __GPRO__, __G, __G__ and __GDEF.  A function that needs no other
+  parameters would look like this:
+
+    int extract_or_test_files(__G)
+      __GDEF
+    {
+       ... stuff ...
+    }
+
+  A function with other parameters would look like:
+
+    int memextract(__G__ tgt, tgtsize, src, srcsize)
+        __GDEF
+        uch *tgt, *src;
+        ulg tgtsize, srcsize;
+    {
+      ... stuff ...
+    }
+
+  In the Function Prototypes section of unzpriv.h, you should use __GPRO and
+  __GPRO__ instead:
+
+    int  uz_opts                   OF((__GPRO__ int *pargc, char ***pargv));
+    int  process_zipfiles          OF((__GPRO));
+
+  Note that there is NO comma after __G__ or __GPRO__ and no semi-colon after
+  __GDEF.  I wish there was another way but I don't think there is.
+
+
+  TESTING THE CODE
+  -----------------
+
+  Whether your platform requires reentrancy or not, you should always try
+  building with REENTRANT defined if any functions have been added.  It is
+  pretty easy to forget a __G__ or a __GDEF and this mistake will only show
+  up if REENTRANT is defined.  All platforms should run with REENTRANT
+  defined.  Platforms that can't take advantage of it will just be paying
+  a performance penalty needlessly.
+
+  SIGNAL MADNESS
+  --------------
+
+  This whole pointer passing scheme falls apart when it comes to SIGNALs.
+  I handle this situation 2 ways right now.  If you define USETHREADID,
+  UnZip will include a 64-entry table.  Each entry can hold a global
+  pointer and thread ID for one thread.  This should allow up to 64
+  threads to access UnZip simultaneously.  Calling DESTROYGLOBALS()
+  will free the global struct and zero the table entry.  If somebody
+  forgets to call DESTROYGLOBALS(), this table will eventually fill up
+  and UnZip will exit with an error message.  A good way to test your
+  code to make sure you didn't forget a DESTROYGLOBALS() is to change
+  THREADID_ENTRIES to 3 or 4 in globals.c, making the table real small.
+  Then make a small test program that calls your API a dozen times.
+
+  Those platforms that don't have threads still need to be able to compile
+  with REENTRANT defined to test and see if new code is correctly written
+  to work either way.  For these platforms, I simply keep a global pointer
+  called GG that points to the Globals structure.  Good enough for testing.
+
+  I believe that NT has thread level storage.  This could probably be used
+  to store a global pointer for the sake of the signal handler more cleanly
+  than my table approach.
+
+  ---------------------------------------------------------------------------*/
+
+#ifndef __globals_h
+#define __globals_h
+
+#ifdef USE_ZLIB
+#  include "zlib.h"
+#endif
+
+
+/*************/
+/*  Globals  */
+/*************/
+
+typedef struct Globals {
+#ifdef DLL
+    zvoid *callerglobs; /* pointer to structure of pass-through global vars */
+#endif
+
+    /* command options of general use */
+    UzpOpts UzO;        /* command options of general use */
+
+#ifndef FUNZIP
+    /* command options specific to the high level command line interface */
+#ifdef MORE
+    int M_flag;         /* -M: built-in "more" function */
+#endif
+
+    /* internal flags and general globals */
+#ifdef MORE
+    int height;           /* check for SIGWINCH, etc., eventually... */
+#endif                    /* (take line-wrapping into account?) */
+#if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME))
+    int tz_is_valid;      /* indicates that timezone info can be used */
+#endif
+#ifdef WINDLL
+    int prompt_always;    /* prompt to overwrite if TRUE */
+#endif
+    int noargs;           /* did true command line have *any* arguments? */
+    unsigned filespecs;   /* number of real file specifications to be matched */
+    unsigned xfilespecs;  /* number of excluded filespecs to be matched */
+    int process_all_files;
+    int create_dirs;      /* used by main(), mapname(), checkdir() */
+    int extract_flag;
+    int newzip;           /* reset in extract.c; used in crypt.c */
+    LONGINT   real_ecrec_offset;
+    LONGINT   expect_ecrec_offset;
+    long csize;           /* used by decompr. (NEXTBYTE): must be signed */
+    long ucsize;          /* used by unReduce(), explode() */
+    long used_csize;      /* used by extract_or_test_member(), explode() */
+
+#ifdef DLL
+     int fValidate;       /* true if only validating an archive */
+     int filenotfound;
+     int redirect_data;   /* redirect data to memory buffer */
+     int redirect_text;   /* redirect text output to buffer */
+# ifndef NO_SLIDE_REDIR
+     int redirect_slide;  /* redirect decompression area to mem buffer */
+     unsigned _wsize;
+# endif
+     unsigned redirect_size;       /* size of redirected output buffer */
+     uch *redirect_buffer;         /* pointer to head of allocated buffer */
+     uch *redirect_pointer;        /* pointer past end of written data */
+# ifndef NO_SLIDE_REDIR
+     uch *redirect_sldptr;         /* head of decompression slide buffer */
+# endif
+# ifdef OS2DLL
+     cbList(processExternally);    /* call-back list */
+# endif
+#endif /* DLL */
+
+    char **pfnames;
+    char **pxnames;
+    char sig[4];
+    char answerbuf[10];
+    min_info info[DIR_BLKSIZ];
+    min_info *pInfo;
+#endif /* !FUNZIP */
+    union work area;                /* see unzpriv.h for definition of work */
+
+#ifndef FUNZIP
+#  if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))
+    ZCONST ulg near *crc_32_tab;
+#  else
+    ZCONST ulg Far *crc_32_tab;
+#  endif
+#endif
+    ulg       crc32val;             /* CRC shift reg. (was static in funzip) */
+
+#ifdef FUNZIP
+    FILE     *in;                   /* file descriptor of compressed stream */
+#endif
+    uch       *inbuf;               /* input buffer (any size is OK) */
+    uch       *inptr;               /* pointer into input buffer */
+    int       incnt;
+
+#ifndef FUNZIP
+    ulg       bitbuf;
+    int       bits_left;            /* unreduce and unshrink only */
+    int       zipeof;
+    char      *argv0;               /* used for NT and EXE_EXTENSION */
+    char      *wildzipfn;
+    char      *zipfn;    /* GRR:  WINDLL:  must nuke any malloc'd zipfn... */
+#ifdef USE_STRM_INPUT
+    FILE      *zipfd;               /* zipfile file descriptor */
+#else
+    int       zipfd;                /* zipfile file handle */
+#endif
+    LONGINT   ziplen;
+    LONGINT   cur_zipfile_bufstart; /* extract_or_test, readbuf, ReadByte */
+    LONGINT   extra_bytes;          /* used in unzip.c, misc.c */
+    uch       *extra_field;         /* Unix, VMS, Mac, OS/2, Acorn, ... */
+    uch       *hold;
+
+    local_file_hdr  lrec;          /* used in unzip.c, extract.c */
+    cdir_file_hdr   crec;          /* used in unzip.c, extract.c, misc.c */
+    ecdir_rec       ecrec;         /* used in unzip.c, extract.c */
+    struct stat     statbuf;       /* used by main, mapname, check_for_newer */
+
+    int      mem_mode;
+    uch      *outbufptr;           /* extract.c static */
+    ulg      outsize;              /* extract.c static */
+    int      reported_backslash;   /* extract.c static */
+    int      disk_full;
+    int      newfile;
+
+    int      didCRlast;            /* fileio static */
+    ulg      numlines;             /* fileio static: number of lines printed */
+    int      sol;                  /* fileio static: at start of line */
+    int      no_ecrec;             /* process static */
+#ifdef SYMLINKS
+    int      symlnk;
+#endif
+#ifdef NOVELL_BUG_FAILSAFE
+    int      dne;                  /* true if stat() says file doesn't exist */
+#endif
+
+    FILE     *outfile;
+    uch      *outbuf;
+    uch      *realbuf;
+
+#ifndef VMS                        /* if SMALL_MEM, outbuf2 is initialized in */
+    uch      *outbuf2;             /*  process_zipfiles() (never changes); */
+#endif                             /*  else malloc'd ONLY if unshrink and -a */
+#endif /* !FUNZIP */
+    uch      *outptr;
+    ulg      outcnt;               /* number of chars stored in outbuf */
+#ifndef FUNZIP
+    char     filename[FILNAMSIZ];  /* also used by NT for temporary SFX path */
+
+#ifdef CMS_MVS
+    char     *tempfn;              /* temp file used; erase on close */
+#endif
+
+    char *key;         /* crypt static: decryption password or NULL */
+    int nopwd;         /* crypt static */
+#endif /* !FUNZIP */
+    ulg keys[3];       /* crypt static: keys defining pseudo-random sequence */
+
+#if (!defined(DOS_FLX_H68_OS2_W32) && !defined(AMIGA) && !defined(RISCOS))
+#if (!defined(MACOS) && !defined(ATARI) && !defined(VMS))
+    int echofd;        /* ttyio static: file descriptor whose echo is off */
+#endif /* !(MACOS || ATARI || VMS) */
+#endif /* !(DOS_FLX_H68_OS2_W32 || AMIGA || RISCOS) */
+
+    unsigned hufts;    /* track memory usage */
+
+#ifdef USE_ZLIB
+    int inflInit;             /* inflate static: zlib inflate() initialized */
+    z_stream dstrm;           /* inflate global: decompression stream */
+#else
+    struct huft *fixed_tl;    /* inflate static */
+    struct huft *fixed_td;    /* inflate static */
+    int fixed_bl, fixed_bd;   /* inflate static */
+    unsigned wp;              /* inflate static: current position in slide */
+    ulg bb;                   /* inflate static: bit buffer */
+    unsigned bk;              /* inflate static: bits in bit buffer */
+#endif /* ?USE_ZLIB */
+
+#ifndef FUNZIP
+#ifdef SMALL_MEM
+    char rgchBigBuffer[512];
+    char rgchSmallBuffer[96];
+    char rgchSmallBuffer2[160];  /* boosted to 160 for local3[] in unzip.c */
+#endif
+
+    MsgFn *message;
+    InputFn *input;
+    PauseFn *mpause;
+    PasswdFn *decr_passwd;
+    StatCBFn *statreportcb;
+#ifdef WINDLL
+    LPUSERFUNCTIONS lpUserFunctions;
+#endif
+
+    int incnt_leftover;       /* so improved NEXTBYTE does not waste input */
+    uch *inptr_leftover;
+
+#ifdef VMS_TEXT_CONV
+    int VMS_line_state;       /* so native VMS variable-length text files are */
+    int VMS_line_length;      /*  readable on other platforms */
+    int VMS_line_pad;
+#endif
+#endif /* !FUNZIP */
+
+#ifdef SYSTEM_SPECIFIC_GLOBALS
+    SYSTEM_SPECIFIC_GLOBALS
+#endif
+
+} Uz_Globs;  /* end of struct Globals */
+
+
+/***************************************************************************/
+
+
+#ifdef FUNZIP
+#  if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))
+     extern ZCONST ulg near  crc_32_tab[256];
+#  else
+     extern ZCONST ulg Far *crc_32_tab;
+#  endif
+#  define CRC_32_TAB  crc_32_tab
+#else
+#  define CRC_32_TAB  G.crc_32_tab
+#endif
+
+
+Uz_Globs *globalsCtor   OF((void));
+
+/* pseudo constant sigs; they are initialized at runtime so unzip executable
+ * won't look like a zipfile
+ */
+extern char local_hdr_sig[4];
+extern char central_hdr_sig[4];
+extern char end_central_sig[4];
+/* extern char extd_local_sig[4];  NOT USED YET */
+
+#ifdef REENTRANT
+#  define G                   (*(Uz_Globs *)pG)
+#  define __G                 pG
+#  define __G__               pG,
+#  define __GPRO              Uz_Globs *pG
+#  define __GPRO__            Uz_Globs *pG,
+#  define __GDEF              Uz_Globs *pG;
+#  ifdef  USETHREADID
+     extern int               lastScan;
+     void deregisterGlobalPointer OF((__GPRO));
+     Uz_Globs *getGlobalPointer   OF((void));
+#    define GETGLOBALS()      Uz_Globs *pG = getGlobalPointer();
+#    define DESTROYGLOBALS()  {free_G_buffers(pG); deregisterGlobalPointer(pG);}
+#  else
+     extern Uz_Globs          *GG;
+#    define GETGLOBALS()      Uz_Globs *pG = GG;
+#    define DESTROYGLOBALS()  {free_G_buffers(pG); free(pG);}
+#  endif /* ?USETHREADID */
+#  define CONSTRUCTGLOBALS()  Uz_Globs *pG = globalsCtor()
+#else /* !REENTRANT */
+   extern Uz_Globs            G;
+#  define __G
+#  define __G__
+#  define __GPRO              void
+#  define __GPRO__
+#  define __GDEF
+#  define GETGLOBALS()
+#  define CONSTRUCTGLOBALS()  globalsCtor()
+#  define DESTROYGLOBALS()
+#endif /* ?REENTRANT */
+
+#define uO              G.UzO
+
+#endif /* __globals_h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inczip/inflate.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,24 @@
+/* inflate.h for UnZip -- put in the public domain by Mark Adler
+   version c14f, 23 November 1995 */
+
+
+/* You can do whatever you like with this source file, though I would
+   prefer that if you modify it and redistribute it that you include
+   comments to that effect with your name and the date.  Thank you.
+
+   History:
+   vers    date          who           what
+   ----  ---------  --------------  ------------------------------------
+    c14  12 Mar 93  M. Adler        made inflate.c standalone with the
+                                    introduction of inflate.h.
+    c14d 28 Aug 93  G. Roelofs      replaced flush/FlushOutput with new version
+    c14e 29 Sep 93  G. Roelofs      moved everything into unzip.h; added crypt.h
+    c14f 23 Nov 95  G. Roelofs      added UNZIP_INTERNAL to accommodate newly
+                                    split unzip.h
+ */
+
+#define UNZIP_INTERNAL
+#include "unzip.h"     /* provides slide[], typedefs and macros */
+#ifdef FUNZIP
+#  include "crypt.h"   /* provides NEXTBYTE macro for crypt version of funzip */
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inczip/nt.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,28 @@
+/* nt.h:  central header for EF_NTSD "SD" extra field */
+
+#ifndef _NT_H
+#define _NT_H
+
+#define NTSD_BUFFERSIZE (1024)  /* threshold to cause malloc() */
+#define OVERRIDE_BACKUP     1   /* we have SeBackupPrivilege on remote */
+#define OVERRIDE_RESTORE    2   /* we have SeRestorePrivilege on remote */
+#define OVERRIDE_SACL       4   /* we have SeSystemSecurityPrivilege on remote */
+
+typedef struct {
+    BOOL bValid;                /* are our contents valid? */
+    BOOL bProcessDefer;         /* process deferred entry yet? */
+    BOOL bUsePrivileges;        /* use privilege overrides? */
+    DWORD dwFileSystemFlags;    /* describes target file system */
+    BOOL bRemote;               /* is volume remote? */
+    DWORD dwRemotePrivileges;   /* relevant only on remote volumes */
+    DWORD dwFileAttributes;
+    char RootPath[MAX_PATH+1];  /* path to network / filesystem */
+} VOLUMECAPS, *PVOLUMECAPS, *LPVOLUMECAPS;
+
+BOOL SecuritySet(char *resource, PVOLUMECAPS VolumeCaps, uch *securitydata);
+BOOL GetVolumeCaps(char *rootpath, char *name, PVOLUMECAPS VolumeCaps);
+BOOL ValidateSecurity(uch *securitydata);
+BOOL ProcessDefer(PDWORD dwDirectoryCount, PDWORD dwBytesProcessed,
+                  PDWORD dwDirectoryFail, PDWORD dwBytesFail);
+
+#endif /* _NT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inczip/os2acl.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,35 @@
+/* os2acl.h
+ *
+ * Author:  Kai Uwe Rommel <rommel@ars.de>
+ * Created: Fri Mar 29 1996
+ */
+ 
+/* $Id: os2acl.h,v 1.1 2001/04/03 20:58:07 bsmith Exp $ */
+
+/*
+ * $Log: os2acl.h,v $
+ * Revision 1.1  2001/04/03 20:58:07  bsmith
+ * Added dual decompressor backends.
+ *
+ * Revision 1.2  2000/07/15 19:50:44  cvsuser
+ * merged 2.2 branch
+ *
+ * Revision 1.1.2.1  2000/04/11 12:38:05  BS
+ * Added wxInstall a self extracting installation program using wxWindows.
+ *
+ * Revision 1.1  1996/03/30 09:35:00  rommel
+ * Initial revision
+ * 
+ */
+
+#ifndef _OS2ACL_H
+#define _OS2ACL_H
+
+#define ACL_BUFFERSIZE 4096
+
+int acl_get(char *server, const char *resource, char *buffer);
+int acl_set(char *server, const char *resource, char *buffer);
+
+#endif /* _OS2ACL_H */
+
+/* end of os2acl.h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inczip/os2cfg.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,136 @@
+/*---------------------------------------------------------------------------
+    OS/2 specific configuration section:
+  ---------------------------------------------------------------------------*/
+
+#ifndef __os2cfg_h
+#define __os2cfg_h
+
+#ifdef MSDOS
+#  include <dos.h>           /* for REGS macro (TC) or _dos_setftime (MSC) */
+#  ifdef __TURBOC__          /* includes Power C */
+#    include <sys/timeb.h>   /* for structure ftime */
+#    ifndef __BORLANDC__     /* there appears to be a bug (?) in Borland's */
+#      include <mem.h>       /*  MEM.H related to __STDC__ and far poin-   */
+#    endif                   /*  ters. (dpk)  [mem.h included for memcpy]  */
+#  endif
+#endif /* MSDOS */
+
+#ifdef __IBMC__
+#  define S_IFMT 0xF000
+#  define timezone _timezone            /* (underscore names work with    */
+#  define tzset _tzset                  /*  all versions of C Set)        */
+#  define PIPE_ERROR (errno == EERRSET || errno == EOS2ERR)
+#endif /* __IBMC__ */
+
+#ifdef __WATCOMC__
+#  ifdef __386__
+#    ifndef WATCOMC_386
+#      define WATCOMC_386
+#    endif
+#    define __32BIT__
+#    undef far
+#    define far
+#    undef near
+#    define near
+
+/* Get asm routines to link properly without using "__cdecl": */
+#    ifndef USE_ZLIB
+#      pragma aux crc32         "_*" parm caller [] value [eax] modify [eax]
+#      pragma aux get_crc_table "_*" parm caller [] value [eax] \
+                                      modify [eax ecx edx]
+#    endif /* !USE_ZLIB */
+#  else /* !__386__ */
+#    ifndef USE_ZLIB
+#      pragma aux crc32         "_*" parm caller [] value [ax dx] \
+                                      modify [ax cx dx bx]
+#      pragma aux get_crc_table "_*" parm caller [] value [ax] \
+                                      modify [ax cx dx bx]
+#    endif /* !USE_ZLIB */
+#  endif /* ?__386__ */
+
+#  ifndef EPIPE
+#    define EPIPE -1
+#  endif
+#  define PIPE_ERROR (errno == EPIPE)
+#endif /* __WATCOMC__ */
+
+#ifdef __EMX__
+#  ifndef __32BIT__
+#    define __32BIT__
+#  endif
+#  define far
+#endif
+
+#ifndef __32BIT__
+#  define __16BIT__
+#endif
+
+#ifdef MSDOS
+#  undef MSDOS
+#endif
+
+#if defined(M_I86CM) || defined(M_I86LM)
+#  define MED_MEM
+#endif
+#if (defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__))
+#  define MED_MEM
+#endif
+#ifdef __16BIT__
+#  ifndef MED_MEM
+#    define SMALL_MEM
+#  endif
+#endif
+
+#ifdef __16BIT__
+# if defined(MSC) || defined(__WATCOMC__)
+#   include <malloc.h>
+#   define nearmalloc _nmalloc
+#   define nearfree _nfree
+# endif
+# if defined(__TURBOC__) && defined(DYNALLOC_CRCTAB)
+#   if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)
+#     undef DYNALLOC_CRCTAB
+#   endif
+# endif
+# ifndef nearmalloc
+#   define nearmalloc malloc
+#   define nearfree free
+# endif
+#endif
+
+/* TIMESTAMP is now supported on OS/2, so enable it by default */
+#if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))
+#  define TIMESTAMP
+#endif
+
+/* check that TZ environment variable is defined before using UTC times */
+#if (!defined(NO_IZ_CHECK_TZ) && !defined(IZ_CHECK_TZ))
+#  define IZ_CHECK_TZ
+#endif
+
+#ifndef OS2_EAS
+#  define OS2_EAS    /* for -l and -v listings (list.c) */
+#endif
+
+#ifdef isupper
+#  undef isupper
+#endif
+#ifdef tolower
+#  undef tolower
+#endif
+#define isupper(x)   IsUpperNLS((unsigned char)(x))
+#define tolower(x)   ToLowerNLS((unsigned char)(x))
+#define USETHREADID
+
+/* handlers for OEM <--> ANSI string conversions */
+#ifndef _OS2_ISO_ANSI
+   /* use home-brewed conversion functions; internal charset is OEM */
+#  ifdef CRTL_CP_IS_ISO
+#    undef CRTL_CP_IS_ISO
+#  endif
+#  ifndef CRTL_CP_IS_OEM
+#    define CRTL_CP_IS_OEM
+#  endif
+#endif
+
+#endif /* !__os2cfg_h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inczip/os2data.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,139 @@
+/*---------------------------------------------------------------------------
+
+  os2data.h
+
+  OS/2-specific structures and data to be included in the global data struc-
+  ture.
+
+  ---------------------------------------------------------------------------*/
+
+
+#define MAXNAMLEN  256
+#define MAXPATHLEN 256
+#define MAXLEN     256    /* temporary buffer length */
+#define IBUF_LEN   4096   /* input buffer length */
+
+#define INCL_NOPM
+#define INCL_DOSNLS
+#define INCL_DOSPROCESS
+#define INCL_DOSDEVICES
+#define INCL_DOSDEVIOCTL
+#define INCL_DOSERRORS
+#define INCL_DOSMISC
+
+#if (defined(OS2DLL) && !defined(DLL))
+#  undef OS2DLL
+#endif
+
+#ifdef OS2DLL
+#  define INCL_REXXSAA
+#  include <rexxsaa.h>
+#endif
+
+#include <os2.h>
+
+
+struct direct
+{
+  ino_t    d_ino;                   /* a bit of a farce */
+  int      d_reclen;                /* more farce */
+  int      d_namlen;                /* length of d_name */
+  char     d_name[MAXNAMLEN + 1];   /* null terminated */
+  /* nonstandard fields */
+  long     d_size;                  /* size in bytes */
+  unsigned d_mode;                  /* MS-DOS or OS/2 file attributes */
+  unsigned d_time;
+  unsigned d_date;
+};
+
+/* The fields d_size and d_mode are extensions by me (Kai Uwe Rommel).  The
+ * find_first and find_next calls deliver these data without any extra cost.
+ * If these data are needed, the fields save a lot of extra calls to stat()
+ * (each stat() again performs a find_first call !).
+ */
+
+struct _dircontents
+{
+  char *_d_entry;
+  long _d_size;
+  unsigned _d_mode, _d_time, _d_date;
+  struct _dircontents *_d_next;
+};
+
+typedef struct _dirdesc
+{
+  int  dd_id;                   /* uniquely identify each open directory */
+  long dd_loc;                  /* where we are in directory entry is this */
+  struct _dircontents *dd_contents;   /* pointer to contents of dir */
+  struct _dircontents *dd_cp;         /* pointer to current position */
+}
+DIR;
+
+
+struct os2Global {
+
+#ifndef SFX
+   HDIR hdir;
+#ifdef __32BIT__
+   ULONG count;
+   FILEFINDBUF3 find;
+#else
+   USHORT count;
+   FILEFINDBUF find;
+#endif
+#endif /* !SFX */
+  
+   int created_dir;        /* used by mapname(), checkdir() */
+   int renamed_fullpath;   /* ditto */
+   int fnlen;              /* ditto */
+#ifdef __32BIT__
+   ULONG nLabelDrive;      /* ditto */
+#else
+   USHORT nLabelDrive;
+#endif
+   int longnameEA;         /* checkdir(), close_outfile() */
+   char *lastpathcomp;     /* ditto */
+  
+   struct direct dp;
+   int lower;
+   USHORT nLastDrive, nResult;
+  
+   DIR *dir;
+   char *dirname, *wildname, matchname[FILNAMSIZ];
+   int firstcall, have_dirname, dirnamelen;
+  
+   int rootlen;          /* length of rootpath */
+   char *rootpath;       /* user's "extract-to" directory */
+   char *buildpathHPFS;  /* full path (so far) to extracted file, */
+   char *buildpathFAT;   /*  both HPFS/EA (main) and FAT versions */
+   char *endHPFS;        /* corresponding pointers to end of */
+   char *endFAT;         /*  buildpath ('\0') */
+
+#ifdef OS2DLL
+   char buffer[IBUF_LEN];
+   char output_var[MAXLEN];
+   char getvar_buf[MAXLEN];
+   int getvar_len;
+  
+   int output_idx;
+   int stem_len;
+   int putchar_idx;
+   int rexx_error;
+   char *rexx_mes;
+
+   SHVBLOCK request;
+#endif
+};
+
+
+#define SYSTEM_SPECIFIC_GLOBALS struct os2Global os2;
+#define SYSTEM_SPECIFIC_CTOR    os2GlobalsCtor
+
+#ifdef OS2DLL
+#  ifdef API_DOC
+#    define SYSTEM_API_BRIEF    REXXBrief
+#    define SYSTEM_API_DETAILS  REXXDetails
+     extern char *REXXBrief;
+     extern APIDocStruct REXXDetails[];
+#  endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inczip/rsxntwin.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,155 @@
+/* rsxntwin.h
+ *
+ * fills some gaps in the rsxnt 1.3 win32 header files (<windows.h>) that are
+ * required for compiling Info-ZIP sources for Win NT / Win 95
+ */
+
+#ifdef __RSXNT__
+#if !defined (_RSXNTWIN_H)
+#define _RSXNTWIN_H
+
+#ifdef TFUNCT   /* TFUNCT is undefined when MSSDK headers are used */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PASCAL __stdcall
+
+#define ANYSIZE_ARRAY 1
+
+#ifndef TIME_ZONE_ID_UNKNOWN
+#  define TIME_ZONE_ID_UNKNOWN  0
+#endif
+
+#define FILE_ATTRIBUTE_HIDDEN   0x00000002
+#define FILE_ATTRIBUTE_SYSTEM   0x00000004
+
+#define FILE_SHARE_DELETE       0x00000004
+
+#define FILE_PERSISTENT_ACLS    0x00000008
+
+#define HFILE_ERROR        ((HFILE)-1)
+
+#define FS_PERSISTENT_ACLS      FILE_PERSISTENT_ACLS
+
+
+BOOL WINAPI DosDateTimeToFileTime(WORD, WORD, LPFILETIME);
+
+
+#ifndef SetVolumeLabel
+#define SetVolumeLabel TFUNCT(SetVolumeLabel)
+#endif
+BOOL WINAPI SetVolumeLabel(LPCTSTR, LPCTSTR);
+
+
+#ifndef GetDriveType
+#define GetDriveType TFUNCT(GetDriveType)
+#endif
+DWORD GetDriveType(LPCTSTR);
+
+#define DRIVE_UNKNOWN     0
+#define DRIVE_REMOVABLE   2
+#define DRIVE_FIXED       3
+#define DRIVE_REMOTE      4
+#define DRIVE_CDROM       5
+#define DRIVE_RAMDISK     6
+
+#ifndef SearchPath
+#define SearchPath TFUNCT(SearchPath)
+#endif
+BOOL WINAPI SearchPath(LPCTSTR, LPCTSTR, LPCTSTR, UINT, LPTSTR, LPTSTR *);
+
+#define ERROR_SUCCESS                   0
+#define ERROR_INSUFFICIENT_BUFFER       122
+
+LONG WINAPI InterlockedExchange(LPLONG, LONG);
+
+#define ACCESS_SYSTEM_SECURITY          0x01000000L
+
+typedef PVOID PSECURITY_DESCRIPTOR;
+typedef PVOID PSID;
+typedef struct _ACL {
+    BYTE  AclRevision;
+    BYTE  Sbz1;
+    WORD   AclSize;
+    WORD   AceCount;
+    WORD   Sbz2;
+} ACL;
+typedef ACL *PACL;
+
+typedef struct _LUID {
+    DWORD LowPart;
+    LONG HighPart;
+} LUID, *PLUID;
+
+typedef struct _LUID_AND_ATTRIBUTES {
+    LUID Luid;
+    DWORD Attributes;
+    } LUID_AND_ATTRIBUTES, * PLUID_AND_ATTRIBUTES;
+
+typedef struct _TOKEN_PRIVILEGES {
+    DWORD PrivilegeCount;
+    LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY];
+} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;
+
+#define TOKEN_QUERY             0x0008
+#define TOKEN_ADJUST_PRIVILEGES 0x0020
+
+BOOL WINAPI OpenProcessToken(HANDLE, DWORD, PHANDLE);
+BOOL WINAPI AdjustTokenPrivileges(HANDLE, BOOL, PTOKEN_PRIVILEGES, DWORD,
+                PTOKEN_PRIVILEGES, PDWORD);
+
+#ifndef LookupPrivilegeValue
+#define LookupPrivilegeValue TFUNCT(LookupPrivilegeValue)
+#endif
+BOOL WINAPI LookupPrivilegeValue(LPCTSTR, LPCTSTR, PLUID);
+
+typedef DWORD SECURITY_INFORMATION, *PSECURITY_INFORMATION;
+#define OWNER_SECURITY_INFORMATION      0x00000001L
+#define GROUP_SECURITY_INFORMATION      0x00000002L
+#define DACL_SECURITY_INFORMATION       0x00000004L
+#define SACL_SECURITY_INFORMATION       0x00000008L
+
+typedef WORD SECURITY_DESCRIPTOR_CONTROL, *PSECURITY_DESCRIPTOR_CONTROL;
+#define SE_DACL_PRESENT         0x0004
+#define SE_SACL_PRESENT         0x0010
+
+#define SE_PRIVILEGE_ENABLED    0x00000002L
+
+#define SE_SECURITY_NAME                  TEXT("SeSecurityPrivilege")
+#define SE_BACKUP_NAME                    TEXT("SeBackupPrivilege")
+#define SE_RESTORE_NAME                   TEXT("SeRestorePrivilege")
+
+BOOL WINAPI GetKernelObjectSecurity(HANDLE, SECURITY_INFORMATION,
+                PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
+BOOL WINAPI SetKernelObjectSecurity(HANDLE, SECURITY_INFORMATION,
+                PSECURITY_DESCRIPTOR);
+BOOL WINAPI IsValidSid(PSID);
+BOOL WINAPI IsValidAcl(PACL);
+BOOL WINAPI InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR);
+BOOL WINAPI IsValidSecurityDescriptor(PSECURITY_DESCRIPTOR);
+DWORD WINAPI GetSecurityDescriptorLength(PSECURITY_DESCRIPTOR);
+BOOL WINAPI GetSecurityDescriptorControl(PSECURITY_DESCRIPTOR,
+                PSECURITY_DESCRIPTOR_CONTROL, LPDWORD);
+BOOL WINAPI SetSecurityDescriptorControl(PSECURITY_DESCRIPTOR,
+                SECURITY_DESCRIPTOR_CONTROL, SECURITY_DESCRIPTOR_CONTROL);
+BOOL WINAPI GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR,
+                                      LPBOOL, PACL *, LPBOOL);
+BOOL WINAPI SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR, BOOL, PACL, BOOL);
+BOOL WINAPI GetSecurityDescriptorSacl(PSECURITY_DESCRIPTOR,
+                                      LPBOOL, PACL *, LPBOOL);
+BOOL WINAPI SetSecurityDescriptorSacl(PSECURITY_DESCRIPTOR, BOOL, PACL, BOOL);
+BOOL WINAPI GetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR, PSID *, LPBOOL);
+BOOL WINAPI SetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR, PSID, BOOL);
+BOOL WINAPI GetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR, PSID *, LPBOOL);
+BOOL WINAPI SetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR, PSID, BOOL);
+VOID WINAPI InitializeCriticalSection();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TFUNCT */
+#endif /* !defined (_RSXNTWIN_H) */
+#endif /* __RSXNT__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inczip/tables.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,81 @@
+/*---------------------------------------------------------------------------
+
+  tables.h
+
+  This file contains only the 32-bit CRC table used in fUnZip;
+  it is in a separate file because it is rather big and ugly and
+  gets in the way during editing.
+  This file can be included in no more than ONE source file per
+  executable, of course.
+
+  ---------------------------------------------------------------------------*/
+
+#ifndef __tables_h   /* prevent multiple inclusions */
+#define __tables_h
+
+#ifdef FUNZIP
+#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))
+
+/* Table of CRC-32's of all single-byte values (made by makecrc.c) */
+ZCONST ulg near crc_32_tab[256] = {
+    0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+    0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+    0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+    0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+    0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+    0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+    0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+    0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+    0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+    0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+    0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+    0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+    0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+    0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+    0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+    0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+    0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+    0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+    0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+    0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+    0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+    0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+    0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+    0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+    0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+    0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+    0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+    0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+    0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+    0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+    0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+    0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+    0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+    0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+    0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+    0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+    0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+    0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+    0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+    0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+    0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+    0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+    0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+    0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+    0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+    0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+    0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+    0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+    0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+    0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+    0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+    0x2d02ef8dL
+};
+
+#else /* USE_ZLIB && !USE_OWN_CRCTAB */
+
+ZCONST uLongf *crc_32_tab = NULL;
+
+#endif /* ?(!USE_ZLIB || USE_OWN_CRCTAB) */
+#endif /* FUNZIP */
+#endif /* __tables_h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inczip/ttyio.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,186 @@
+/*
+   ttyio.h
+ */
+
+#ifndef __ttyio_h   /* don't include more than once */
+#define __ttyio_h
+
+#ifndef __crypt_h
+#  include "crypt.h"  /* ensure that encryption header file has been seen */
+#endif
+
+#if (CRYPT || (defined(UNZIP) && !defined(FUNZIP)))
+/*
+ * Non-echo keyboard/console input support is needed and enabled.
+ */
+
+#ifndef __G         /* UnZip only, for now (DLL stuff) */
+#  define __G
+#  define __G__
+#  define __GDEF
+#  define __GPRO    void
+#  define __GPRO__
+#endif
+
+#ifndef ZCONST      /* UnZip only (until have configure script like Zip) */
+#  define ZCONST const
+#endif
+
+#if (defined(MSDOS) || defined(OS2) || defined(WIN32))
+#  ifndef DOS_OS2_W32
+#    define DOS_OS2_W32
+#  endif
+#endif
+
+#if (defined(DOS_OS2_W32) || defined(__human68k__))
+#  ifndef DOS_H68_OS2_W32
+#    define DOS_H68_OS2_W32
+#  endif
+#endif
+
+#if (defined(DOS_OS2_W32) || defined(FLEXOS))
+#  ifndef DOS_FLX_OS2_W32
+#    define DOS_FLX_OS2_W32
+#  endif
+#endif
+
+#if (defined(DOS_H68_OS2_W32) || defined(FLEXOS))
+#  ifndef DOS_FLX_H68_OS2_W32
+#    define DOS_FLX_H68_OS2_W32
+#  endif
+#endif
+
+#if (defined(VM_CMS) || defined(MVS))
+#  ifndef CMS_MVS
+#    define CMS_MVS
+#  endif
+#endif
+
+
+/* Function prototypes */
+
+/* The following systems supply a `non-echo' character input function "getch()"
+ * (or an alias) and do not need the echoff() / echon() function pair.
+ */
+#ifdef AMIGA
+#  define echoff(f)
+#  define echon()
+#  define getch() Agetch()
+#  define HAVE_WORKING_GETCH
+#endif /* AMIGA */
+
+#ifdef ATARI
+#  define echoff(f)
+#  define echon()
+#  include <osbind.h>
+#  define getch() (Cnecin() & 0x000000ff)
+#  define HAVE_WORKING_GETCH
+#endif
+
+#ifdef MACOS
+#  define echoff(f)
+#  define echon()
+#  define getch() macgetch()
+#  define HAVE_WORKING_GETCH
+#endif
+
+#ifdef QDOS
+#  define echoff(f)
+#  define echon()
+#  define HAVE_WORKING_GETCH
+#endif
+
+#ifdef RISCOS
+#  define echoff(f)
+#  define echon()
+#  define getch() SWI_OS_ReadC()
+#  define HAVE_WORKING_GETCH
+#endif
+
+#ifdef DOS_H68_OS2_W32
+#  define echoff(f)
+#  define echon()
+#  ifdef WIN32
+#    ifndef getch
+#      define getch() getch_win32()
+#    endif
+#  else /* !WIN32 */
+#    ifdef __EMX__
+#      ifndef getch
+#        define getch() _read_kbd(0, 1, 0)
+#      endif
+#    else /* !__EMX__ */
+#      ifdef __GO32__
+#        include <pc.h>
+#        define getch() getkey()
+#      else /* !__GO32__ */
+#        include <conio.h>
+#      endif /* ?__GO32__ */
+#    endif /* ?__EMX__ */
+#  endif /* ?WIN32 */
+#  define HAVE_WORKING_GETCH
+#endif /* DOS_H68_OS2_W32 */
+
+#ifdef FLEXOS
+#  define echoff(f)
+#  define echon()
+#  define getch() getchar() /* not correct, but may not be on a console */
+#  define HAVE_WORKING_GETCH
+#endif
+
+/* For VM/CMS and MVS, we do not (yet) have any support to switch terminal
+ * input echo on and off. The following "fake" definitions allow inclusion
+ * of crypt support and UnZip's "pause prompting" features, but without
+ * any echo suppression.
+ */
+#ifdef CMS_MVS
+#  define echoff(f)
+#  define echon()
+#endif
+
+/* VMS has a single echo() function in ttyio.c to toggle terminal
+ * input echo on and off.
+ */
+#ifdef VMS
+#  define echoff(f)  echo(0)
+#  define echon()    echo(1)
+   int echo OF((int));
+#endif
+
+/* For all other systems, ttyio.c supplies the two functions Echoff() and
+ * Echon() for suppressing and (re)enabling console input echo.
+ */
+#ifndef echoff
+#  define echoff(f)  Echoff(__G__ f)
+#  define echon()    Echon(__G)
+   void Echoff OF((__GPRO__ int f));
+   void Echon OF((__GPRO));
+#endif
+
+/* this stuff is used by MORE and also now by the ctrl-S code; fileio.c only */
+#if (defined(UNZIP) && !defined(FUNZIP))
+#  ifdef HAVE_WORKING_GETCH
+#    define FGETCH(f)  getch()
+#  endif
+#  ifndef FGETCH
+     /* default for all systems where no getch()-like function is available */
+     int zgetch OF((__GPRO__ int f));
+#    define FGETCH(f)  zgetch(__G__ f)
+#  endif
+#endif /* UNZIP && !FUNZIP */
+
+#if (CRYPT && !defined(WINDLL))
+   char *getp OF((__GPRO__ ZCONST char *m, char *p, int n));
+#endif
+
+#else /* !(CRYPT || (UNZIP && !FUNZIP)) */
+
+/*
+ * No need for non-echo keyboard/console input; provide dummy definitions.
+ */
+#define echoff(f)
+#define echon()
+
+#endif /* ?(CRYPT || (UNZIP && !FUNZIP)) */
+
+#endif /* !__ttyio_h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inczip/unzip.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,548 @@
+/*---------------------------------------------------------------------------
+
+  unzip.h (new)
+
+  This header file contains the public macros and typedefs required by
+  both the UnZip sources and by any application using the UnZip API.  If
+  UNZIP_INTERNAL is defined, it includes unzpriv.h (containing includes,
+  prototypes and extern variables used by the actual UnZip sources).
+
+  ---------------------------------------------------------------------------*/
+
+
+#ifndef __unzip_h   /* prevent multiple inclusions */
+#define __unzip_h
+
+/*---------------------------------------------------------------------------
+    Predefined, machine-specific macros.
+  ---------------------------------------------------------------------------*/
+
+#ifdef __GO32__                 /* MS-DOS extender:  NOT Unix */
+#  ifdef unix
+#    undef unix
+#  endif
+#  ifdef __unix
+#    undef __unix
+#  endif
+#  ifdef __unix__
+#    undef __unix__
+#  endif
+#endif
+
+#if ((defined(__convex__) || defined(__convexc__)) && !defined(CONVEX))
+#  define CONVEX
+#endif
+
+#if (defined(unix) || defined(__unix) || defined(__unix__))
+#  ifndef UNIX
+#    define UNIX
+#  endif
+#endif /* unix || __unix || __unix__ */
+#if (defined(M_XENIX) || defined(COHERENT) || defined(__hpux))
+#  ifndef UNIX
+#    define UNIX
+#  endif
+#endif /* M_XENIX || COHERENT || __hpux */
+#if (defined(CONVEX) || defined(MINIX) || defined(_AIX) || defined(__QNX__))
+#  ifndef UNIX
+#    define UNIX
+#  endif
+#endif /* CONVEX || MINIX || _AIX || __QNX__ */
+
+#if (defined(VM_CMS) || defined(MVS))
+#  define CMS_MVS
+#endif
+
+#if (defined(__OS2__) && !defined(OS2))
+#  define OS2
+#endif
+
+#if (defined(__TANDEM) && !defined(TANDEM))
+#  define TANDEM
+#endif
+
+#if (defined(__VMS) && !defined(VMS))
+#  define VMS
+#endif
+
+#if ((defined(__WIN32__) || defined(_WIN32)) && !defined(WIN32))
+#  define WIN32
+#endif
+#if ((defined(__WINNT__) || defined(__WINNT)) && !defined(WIN32))
+#  define WIN32
+#endif
+
+#ifdef __COMPILER_KCC__
+#  include <c-env.h>
+#  ifdef SYS_T20
+#    define TOPS20
+#  endif
+#endif /* __COMPILER_KCC__ */
+
+/* Borland C does not define __TURBOC__ if compiling for a 32-bit platform */
+#ifdef __BORLANDC__
+#  ifndef __TURBOC__
+#    define __TURBOC__
+#  endif
+#  if (!defined(__MSDOS__) && !defined(OS2) && !defined(WIN32))
+#    define __MSDOS__
+#  endif
+#endif
+
+/* define MSDOS for Turbo C (unless OS/2) and Power C as well as Microsoft C */
+#ifdef __POWERC
+#  define __TURBOC__
+#  define MSDOS
+#endif /* __POWERC */
+
+#if (defined(__MSDOS__) && !defined(MSDOS))   /* just to make sure */
+#  define MSDOS
+#endif
+
+/* RSXNTDJ (at least up to v1.3) compiles for WIN32 (RSXNT) using a derivate
+   of the EMX environment, but defines MSDOS and __GO32__. ARG !!! */
+#if (defined(MSDOS) && defined(WIN32))
+#  undef MSDOS                  /* WIN32 is >>>not<<< MSDOS */
+#endif
+#if (defined(__GO32__) && defined(__EMX__) && defined(__RSXNT__))
+#  undef __GO32__
+#endif
+
+#if (defined(linux) && !defined(LINUX))
+#  define LINUX
+#endif
+
+#ifdef __riscos
+#  define RISCOS
+#endif
+
+#if (defined(THINK_C) || defined(MPW))
+#  define MACOS
+#endif
+#if (defined(__MWERKS__) && defined(macintosh))
+#  define MACOS
+#endif
+
+/* use prototypes and ANSI libraries if __STDC__, or Microsoft or Borland C, or
+ * Silicon Graphics, or Convex?, or IBM C Set/2, or GNU gcc/emx, or Watcom C,
+ * or Macintosh, or Windows NT, or Sequent, or Atari or IBM RS/6000.
+ */
+#if (defined(__STDC__) || defined(MSDOS) || defined(WIN32) || defined(__EMX__))
+#  ifndef PROTO
+#    define PROTO
+#  endif
+#  ifndef MODERN
+#    define MODERN
+#  endif
+#endif
+#if (defined(__IBMC__) || defined(__BORLANDC__) || defined(__WATCOMC__))
+#  ifndef PROTO
+#    define PROTO
+#  endif
+#  ifndef MODERN
+#    define MODERN
+#  endif
+#endif
+#if (defined(MACOS) || defined(ATARI_ST) || defined(RISCOS))
+#  ifndef PROTO
+#    define PROTO
+#  endif
+#  ifndef MODERN
+#    define MODERN
+#  endif
+#endif
+/* Sequent running Dynix/ptx:  non-modern compiler */
+#if (defined(_AIX) || defined(sgi) || (defined(_SEQUENT_) && !defined(PTX)))
+#  ifndef PROTO
+#    define PROTO
+#  endif
+#  ifndef MODERN
+#    define MODERN
+#  endif
+#endif
+#if (defined(CMS_MVS) || defined(__BEOS__))  /* || defined(CONVEX) */
+#  ifndef PROTO
+#    define PROTO
+#  endif
+#  ifndef MODERN
+#    define MODERN
+#  endif
+#endif
+
+/* turn off prototypes if requested */
+#if (defined(NOPROTO) && defined(PROTO))
+#  undef PROTO
+#endif
+
+/* used to remove arguments in function prototypes for non-ANSI C */
+#ifdef PROTO
+#  define OF(a) a
+#else
+#  define OF(a) ()
+#endif
+
+/* enable the "const" keyword only if MODERN and if not otherwise instructed */
+#ifdef MODERN
+#  if (!defined(ZCONST) && (defined(USE_CONST) || !defined(NO_CONST)))
+#    define ZCONST const
+#  endif
+#endif
+
+#ifndef ZCONST
+#  define ZCONST
+#endif
+
+
+/*---------------------------------------------------------------------------
+    Grab system-specific public include headers.
+  ---------------------------------------------------------------------------*/
+
+#ifdef POCKET_UNZIP             /* WinCE port */
+#  include "wince/punzip.h"     /* must appear before windows.h */
+#endif
+
+#ifdef WINDLL
+#  include <windows.h>
+#  include "windll/structs.h"
+#endif
+
+/*---------------------------------------------------------------------------
+    Grab system-dependent definition of EXPENTRY for prototypes below.
+  ---------------------------------------------------------------------------*/
+
+#if 0
+#if (defined(OS2) && !defined(FUNZIP))
+#  ifdef UNZIP_INTERNAL
+#    define INCL_NOPM
+#    define INCL_DOSNLS
+#    define INCL_DOSPROCESS
+#    define INCL_DOSDEVICES
+#    define INCL_DOSDEVIOCTL
+#    define INCL_DOSERRORS
+#    define INCL_DOSMISC
+#    ifdef OS2DLL
+#      define INCL_REXXSAA
+#      include <rexxsaa.h>
+#    endif
+#  endif /* UNZIP_INTERNAL */
+#  include <os2.h>
+#  define UZ_EXP EXPENTRY
+#endif /* OS2 && !FUNZIP */
+#endif /* 0 */
+
+#if (defined(OS2) && !defined(FUNZIP))
+#  if (defined(__IBMC__) || defined(__WATCOMC__))
+#    define UZ_EXP  _System    /* compiler keyword */
+#  else
+#    define UZ_EXP
+#  endif
+#endif /* OS2 && !FUNZIP */
+
+#if (defined(WINDLL) || defined(USE_UNZIP_LIB))
+#  ifndef EXPENTRY
+#    define UZ_EXP WINAPI
+#  else
+#    define UZ_EXP EXPENTRY
+#  endif
+#endif
+
+#ifndef UZ_EXP
+#  define UZ_EXP
+#endif
+
+
+/*---------------------------------------------------------------------------
+    Public typedefs.
+  ---------------------------------------------------------------------------*/
+
+#ifndef _IZ_TYPES_DEFINED
+#ifdef MODERN
+   typedef void zvoid;
+#else /* !MODERN */
+#  ifndef AOS_VS         /* mostly modern? */
+#    ifndef VAXC         /* not fully modern, but has knows 'void' */
+#      define void int
+#    endif /* !VAXC */
+#  endif /* !AOS_VS */
+   typedef char zvoid;
+#endif /* ?MODERN */
+typedef unsigned char   uch;    /* code assumes unsigned bytes; these type-  */
+typedef unsigned short  ush;    /*  defs replace byte/UWORD/ULONG (which are */
+typedef unsigned long   ulg;    /*  predefined on some systems) & match zip  */
+#define _IZ_TYPES_DEFINED
+#endif /* !_IZ_TYPES_DEFINED */
+
+/* InputFn is not yet used and is likely to change: */
+#ifdef PROTO
+   typedef int   (UZ_EXP MsgFn)     (zvoid *pG, uch *buf, ulg size, int flag);
+   typedef int   (UZ_EXP InputFn)   (zvoid *pG, uch *buf, int *size, int flag);
+   typedef void  (UZ_EXP PauseFn)   (zvoid *pG, ZCONST char *prompt, int flag);
+   typedef int   (UZ_EXP PasswdFn)  (zvoid *pG, int *rcnt, char *pwbuf,
+                                     int size, ZCONST char *zfn,
+                                     ZCONST char *efn);
+   typedef int   (UZ_EXP StatCBFn)  (zvoid *pG, int fnflag, ZCONST char *zfn,
+                                     ZCONST char *efn, ZCONST zvoid *details);
+   typedef void  (UZ_EXP UsrIniFn)  (void);
+#else /* !PROTO */
+   typedef int   (UZ_EXP MsgFn)     ();
+   typedef int   (UZ_EXP InputFn)   ();
+   typedef void  (UZ_EXP PauseFn)   ();
+   typedef int   (UZ_EXP PasswdFn)  ();
+   typedef int   (UZ_EXP StatCBFn)  ();
+   typedef void  (UZ_EXP UsrIniFn)  ();
+#endif /* ?PROTO */
+
+typedef struct _UzpBuffer {    /* rxstr */
+    ulg   strlength;           /* length of string */
+    char  *strptr;             /* pointer to string */
+} UzpBuffer;
+
+typedef struct _UzpInit {
+    ulg structlen;             /* length of the struct being passed */
+
+    /* GRR: can we assume that each of these is a 32-bit pointer?  if not,
+     * does it matter? add "far" keyword to make sure? */
+    MsgFn *msgfn;
+    InputFn *inputfn;
+    PauseFn *pausefn;
+    UsrIniFn *userfn;          /* user init function to be called after */
+                               /*  globals constructed and initialized */
+
+    /* pointer to program's environment area or something? */
+    /* hooks for performance testing? */
+    /* hooks for extra unzip -v output? (detect CPU or other hardware?) */
+    /* anything else?  let me (Greg) know... */
+} UzpInit;
+
+typedef struct _UzpCB {
+    ulg structlen;             /* length of the struct being passed */
+    /* GRR: can we assume that each of these is a 32-bit pointer?  if not,
+     * does it matter? add "far" keyword to make sure? */
+    MsgFn *msgfn;
+    InputFn *inputfn;
+    PauseFn *pausefn;
+    PasswdFn *passwdfn;
+    StatCBFn *statrepfn;
+} UzpCB;
+
+/* the collection of general UnZip option flags and option arguments */
+typedef struct _UzpOpts {
+#ifndef FUNZIP
+    char *exdir;        /* pointer to extraction root directory (-d option) */
+    char *pwdarg;       /* pointer to command-line password (-P option) */
+    int zipinfo_mode;   /* behave like ZipInfo or like normal UnZip? */
+    int aflag;          /* -a: do ASCII-EBCDIC and/or end-of-line translation */
+#ifdef VMS
+    int bflag;          /* -b: force fixed record format for binary files */
+#endif
+#ifdef UNIXBACKUP
+    int B_flag;         /* -B: back up existing files by renaming to *~ first */
+#endif
+    int cflag;          /* -c: output to stdout */
+    int C_flag;         /* -C: match filenames case-insensitively */
+#ifdef MACOS
+    int E_flag;         /* -E: [MacOS] show Mac extra field during restoring */
+#endif
+    int fflag;          /* -f: "freshen" (extract only newer files) */
+#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))
+    int acorn_nfs_ext;  /* -F: RISC OS types & NFS filetype extensions */
+#endif
+    int hflag;          /* -h: header line (zipinfo) */
+#ifdef MACOS
+    int i_flag;         /* -i: [MacOS] ignore filenames stored in Mac e.f. */
+#endif
+#ifdef RISCOS
+    int scanimage;      /* -I: scan image files */
+#endif
+    int jflag;          /* -j: junk pathnames (unzip) */
+#if (defined(__BEOS__) || defined(MACOS))
+    int J_flag;         /* -J: ignore BeOS/MacOS extra field info (unzip) */
+#endif
+    int lflag;          /* -12slmv: listing format (zipinfo) */
+    int L_flag;         /* -L: convert filenames from some OSes to lowercase */
+    int overwrite_none; /* -n: never overwrite files (no prompting) */
+#ifdef AMIGA
+    int N_flag;         /* -N: restore comments as AmigaDOS filenotes */
+#endif
+    int overwrite_all;  /* -o: OK to overwrite files without prompting */
+#endif /* !FUNZIP */
+    int qflag;          /* -q: produce a lot less output */
+#ifndef FUNZIP
+#if (defined(MSDOS) || defined(FLEXOS) || defined(OS2) || defined(WIN32))
+    int sflag;          /* -s: convert spaces in filenames to underscores */
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WIN32))
+    int volflag;        /* -$: extract volume labels */
+#endif
+    int tflag;          /* -t: test (unzip) or totals line (zipinfo) */
+    int T_flag;         /* -T: timestamps (unzip) or dec. time fmt (zipinfo) */
+    int uflag;          /* -u: "update" (extract only newer/brand-new files) */
+    int vflag;          /* -v: (verbosely) list directory */
+    int V_flag;         /* -V: don't strip VMS version numbers */
+#if (defined(TANDEM) || defined(UNIX) || defined(VMS) || defined(__BEOS__))
+    int X_flag;         /* -X: restore owner/protection or UID/GID or ACLs */
+#endif
+#if (defined(OS2) || defined(WIN32))
+    int X_flag;         /* -X: restore owner/protection or UID/GID or ACLs */
+#endif
+    int zflag;          /* -z: display the zipfile comment (only, for unzip) */
+#endif /* !FUNZIP */
+} UzpOpts;
+
+/* intended to be a private struct: */
+typedef struct _ver {
+    uch major;              /* e.g., integer 5 */
+    uch minor;              /* e.g., 2 */
+    uch patchlevel;         /* e.g., 0 */
+    uch not_used;
+} _version_type;
+
+typedef struct _UzpVer {
+    ulg structlen;          /* length of the struct being passed */
+    ulg flag;               /* bit 0: is_beta   bit 1: uses_zlib */
+    char *betalevel;        /* e.g., "g BETA" or "" */
+    char *date;             /* e.g., "4 Sep 95" (beta) or "4 September 1995" */
+    char *zlib_version;     /* e.g., "0.95" or NULL */
+    _version_type unzip;
+    _version_type zipinfo;
+    _version_type os2dll;
+    _version_type windll;
+} UzpVer;
+
+/* for Visual BASIC access to Windows DLLs: */
+typedef struct _UzpVer2 {
+    ulg structlen;          /* length of the struct being passed */
+    ulg flag;               /* bit 0: is_beta   bit 1: uses_zlib */
+    char betalevel[10];     /* e.g., "g BETA" or "" */
+    char date[20];          /* e.g., "4 Sep 95" (beta) or "4 September 1995" */
+    char zlib_version[10];  /* e.g., "0.95" or NULL */
+    _version_type unzip;
+    _version_type zipinfo;
+    _version_type os2dll;
+    _version_type windll;
+} UzpVer2;
+
+typedef struct central_directory_file_header { /* CENTRAL */
+    uch version_made_by[2];
+    uch version_needed_to_extract[2];
+    ush general_purpose_bit_flag;
+    ush compression_method;
+    ulg last_mod_dos_datetime;
+    ulg crc32;
+    ulg csize;
+    ulg ucsize;
+    ush filename_length;
+    ush extra_field_length;
+    ush file_comment_length;
+    ush disk_number_start;
+    ush internal_file_attributes;
+    ulg external_file_attributes;
+    ulg relative_offset_local_header;
+} cdir_file_hdr;
+
+
+#define UZPINIT_LEN   sizeof(UzpInit)
+#define UZPVER_LEN    sizeof(UzpVer)
+#define cbList(func)  int (* UZ_EXP func)(char *filename, cdir_file_hdr *crec)
+
+
+/*---------------------------------------------------------------------------
+    Return (and exit) values of the public UnZip API functions.
+  ---------------------------------------------------------------------------*/
+
+/* external return codes */
+#define PK_OK              0   /* no error */
+#define PK_COOL            0   /* no error */
+#define PK_GNARLY          0   /* no error */
+#define PK_WARN            1   /* warning error */
+#define PK_ERR             2   /* error in zipfile */
+#define PK_BADERR          3   /* severe error in zipfile */
+#define PK_MEM             4   /* insufficient memory (during initialization) */
+#define PK_MEM2            5   /* insufficient memory (password failure) */
+#define PK_MEM3            6   /* insufficient memory (file decompression) */
+#define PK_MEM4            7   /* insufficient memory (memory decompression) */
+#define PK_MEM5            8   /* insufficient memory (not yet used) */
+#define PK_NOZIP           9   /* zipfile not found */
+#define PK_PARAM          10   /* bad or illegal parameters specified */
+#define PK_FIND           11   /* no files found */
+#define PK_DISK           50   /* disk full */
+#define PK_EOF            51   /* unexpected EOF */
+
+#define IZ_CTRLC          80   /* user hit ^C to terminate */
+#define IZ_UNSUP          81   /* no files found: all unsup. compr/encrypt. */
+#define IZ_BADPWD         82   /* no files found: all had bad password */
+
+/* internal and DLL-only return codes */
+#define IZ_DIR            76   /* potential zipfile is a directory */
+#define IZ_CREATED_DIR    77   /* directory created: set time and permissions */
+#define IZ_VOL_LABEL      78   /* volume label, but can't set on hard disk */
+#define IZ_EF_TRUNC       79   /* local extra field truncated (PKZIP'd) */
+
+/* return codes of password fetches (negative = user abort; positive = error) */
+#define IZ_PW_ENTERED      0   /* got some password string; use/try it */
+#define IZ_PW_CANCEL      -1   /* no password available (for this entry) */
+#define IZ_PW_CANCELALL   -2   /* no password, skip any further pwd. request */
+#define IZ_PW_ERROR        5   /* = PK_MEM2 : failure (no mem, no tty, ...) */
+
+/* flag values for status callback function */
+#define UZ_ST_START_EXTRACT     1
+#define UZ_ST_IN_PROGRESS       2
+#define UZ_ST_FINISH_MEMBER     3
+
+/* return values of status callback function */
+#define UZ_ST_CONTINUE          0
+#define UZ_ST_BREAK             1
+
+
+/*---------------------------------------------------------------------------
+    Prototypes for public UnZip API (DLL) functions.
+  ---------------------------------------------------------------------------*/
+
+#define  UzpMatch match
+
+int      UZ_EXP UzpMain            OF((int argc, char **argv));
+int      UZ_EXP UzpAltMain         OF((int argc, char **argv, UzpInit *init));
+UzpVer * UZ_EXP UzpVersion         OF((void));
+void     UZ_EXP UzpFreeMemBuffer   OF((UzpBuffer *retstr));
+#ifndef WINDLL
+int      UZ_EXP UzpUnzipToMemory   OF((char *zip, char *file, UzpOpts *optflgs,
+                                       UzpCB *UsrFunc, UzpBuffer *retstr));
+#endif
+#ifndef WINDLL
+   int   UZ_EXP UzpGrep            OF((char *archive, char *file,
+                                       char *pattern, int cmd, int SkipBin,
+                                       UzpCB *UsrFunc));
+#endif
+#ifdef OS2
+int      UZ_EXP UzpFileTree        OF((char *name, cbList(callBack),
+                                       char *cpInclude[], char *cpExclude[]));
+#endif
+
+void     UZ_EXP UzpVersion2        OF((UzpVer2 *version));
+int      UZ_EXP UzpValidate        OF((char *archive, int AllCodes));
+
+
+/* default I/O functions (can be swapped out via UzpAltMain() entry point): */
+
+int      UZ_EXP UzpMessagePrnt   OF((zvoid *pG, uch *buf, ulg size, int flag));
+int      UZ_EXP UzpMessageNull   OF((zvoid *pG, uch *buf, ulg size, int flag));
+int      UZ_EXP UzpInput         OF((zvoid *pG, uch *buf, int *size, int flag));
+void     UZ_EXP UzpMorePause     OF((zvoid *pG, ZCONST char *prompt, int flag));
+int      UZ_EXP UzpPassword      OF((zvoid *pG, int *rcnt, char *pwbuf,
+                                     int size, ZCONST char *zfn,
+                                     ZCONST char *efn));
+
+
+/*---------------------------------------------------------------------------
+    Remaining private stuff for UnZip compilation.
+  ---------------------------------------------------------------------------*/
+
+#ifdef UNZIP_INTERNAL
+#  include "unzpriv.h"
+#endif
+
+int pipeit(char *format, ...);
+int pipeit2(char *format, int flag, ...);
+int confirm(char *format, ...);
+
+#endif /* !__unzip_h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inczip/unzpriv.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,2384 @@
+/*---------------------------------------------------------------------------
+
+  unzpriv.h
+
+  This header file contains private (internal) macros, typedefs, prototypes
+  and global-variable declarations used by all of the UnZip source files.
+  In a prior life it was part of the main unzip.h header, but now it is only
+  included by that header if UNZIP_INTERNAL is defined.
+
+  ---------------------------------------------------------------------------*/
+
+
+
+#ifndef __unzpriv_h   /* prevent multiple inclusions */
+#define __unzpriv_h
+
+/* First thing: Signal all following code that we compile UnZip utilities! */
+#ifndef UNZIP
+#  define UNZIP
+#endif
+
+/* GRR 960204:  MORE defined here in preparation for removal altogether */
+#ifndef MORE
+#  define MORE
+#endif
+
+/* fUnZip should never need to be reentrant */
+#ifdef FUNZIP
+#  ifdef REENTRANT
+#    undef REENTRANT
+#  endif
+#  ifdef DLL
+#    undef DLL
+#  endif
+#endif
+
+#if (defined(DLL) && !defined(REENTRANT))
+#  define REENTRANT
+#endif
+
+#if (!defined(DYNAMIC_CRC_TABLE) && !defined(FUNZIP))
+#  define DYNAMIC_CRC_TABLE
+#endif
+
+#if (defined(DYNAMIC_CRC_TABLE) && !defined(REENTRANT))
+#  ifndef DYNALLOC_CRCTAB
+#    define DYNALLOC_CRCTAB
+#  endif
+#endif
+
+/*---------------------------------------------------------------------------
+    OS-dependent configuration for UnZip internals
+  ---------------------------------------------------------------------------*/
+
+/* bad or (occasionally?) missing stddef.h: */
+#if (defined(M_XENIX) || defined(DNIX))
+#  define NO_STDDEF_H
+#endif
+
+#if (defined(M_XENIX) && !defined(M_UNIX))   /* SCO Xenix only, not SCO Unix */
+#  define SCO_XENIX
+#  define NO_LIMITS_H        /* no limits.h, but MODERN defined */
+#  define NO_UID_GID         /* no uid_t/gid_t */
+#  define size_t int
+#endif
+
+#ifdef realix   /* Modcomp Real/IX, real-time SysV.3 variant */
+#  define SYSV
+#  define NO_UID_GID         /* no uid_t/gid_t */
+#endif
+
+#if (defined(_AIX) && !defined(_ALL_SOURCE))
+#  define _ALL_SOURCE
+#endif
+
+#if defined(apollo)          /* defines __STDC__ */
+#    define NO_STDLIB_H
+#endif
+
+#ifdef DNIX
+#  define SYSV
+#  define SHORT_NAMES         /* 14-char limitation on path components */
+/* #  define FILENAME_MAX  14 */
+#  define FILENAME_MAX  NAME_MAX    /* GRR:  experiment */
+#endif
+
+#if (defined(SYSTEM_FIVE) || defined(__SYSTEM_FIVE))
+#  ifndef SYSV
+#    define SYSV
+#  endif
+#endif /* SYSTEM_FIVE || __SYSTEM_FIVE */
+#if (defined(M_SYSV) || defined(M_SYS5))
+#  ifndef SYSV
+#    define SYSV
+#  endif
+#endif /* M_SYSV || M_SYS5 */
+/* __SVR4 and __svr4__ catch Solaris on at least some combos of compiler+OS */
+#if (defined(__SVR4) || defined(__svr4__) || defined(sgi) || defined(__hpux))
+#  ifndef SYSV
+#    define SYSV
+#  endif
+#endif /* __SVR4 || __svr4__ || sgi || __hpux */
+#if (defined(LINUX) || defined(__QNX__))
+#  ifndef SYSV
+#    define SYSV
+#  endif
+#endif /* LINUX || __QNX__ */
+
+#if (defined(ultrix) || defined(__ultrix) || defined(bsd4_2))
+#  if (!defined(BSD) && !defined(SYSV))
+#    define BSD
+#  endif
+#endif /* ultrix || __ultrix || bsd4_2 */
+#if (defined(sun) || defined(pyr) || defined(CONVEX))
+#  if (!defined(BSD) && !defined(SYSV))
+#    define BSD
+#  endif
+#endif /* sun || pyr || CONVEX */
+
+#ifdef pyr  /* Pyramid:  has BSD and AT&T "universes" */
+#  ifdef BSD
+#    define pyr_bsd
+#    define USE_STRINGS_H  /* instead of more common string.h */
+#    define ZMEM           /* ZMEM now uses bcopy/bzero: not in AT&T universe */
+#  endif                   /* (AT&T memcpy claimed to be very slow, though) */
+#  define DECLARE_ERRNO
+#endif /* pyr */
+
+/* stat() bug for Borland, VAX C (also GNU?), and Atari ST MiNT on TOS
+ * filesystems:  returns 0 for wildcards!  (returns 0xffffffff on Minix
+ * filesystem or `U:' drive under Atari MiNT.)  Watcom C was previously
+ * included on this list; it would be good to know what version the problem
+ * was fixed at, if it did exist.  Watcom 10.6 has a separate stat() problem:
+ * it fails on "." when the current directory is a root.  This is covered by
+ * giving it a separate definition of SSTAT in OS-specific header files. */
+#if (defined(__TURBOC__) || defined(VMS) || defined(__MINT__))
+#  define WILD_STAT_BUG
+#endif
+
+#ifdef WILD_STAT_BUG
+#  define SSTAT(path,pbuf) (iswild(path) || stat(path,pbuf))
+#else
+#  define SSTAT stat
+#endif
+
+#ifdef REGULUS  /* returns the inode number on success(!)...argh argh argh */
+#  define stat(p,s) zstat((p),(s))
+#endif
+
+#define STRNICMP zstrnicmp
+
+/*---------------------------------------------------------------------------
+    OS-dependent includes
+  ---------------------------------------------------------------------------*/
+
+#ifdef EFT
+#  define LONGINT off_t  /* Amdahl UTS nonsense ("extended file types") */
+#else
+#  define LONGINT long
+#endif
+
+#ifdef MODERN
+#  ifndef NO_STDDEF_H
+#    include <stddef.h>
+#  endif
+#  ifndef NO_STDLIB_H
+#    include <stdlib.h>  /* standard library prototypes, malloc(), etc. */
+#  endif
+   typedef size_t extent;
+#else /* !MODERN */
+#  ifndef AOS_VS         /* mostly modern? */
+     LONGINT lseek();
+#    ifdef VAXC          /* not fully modern, but does have stdlib.h and void */
+#      include <stdlib.h>
+#    else
+       char *malloc();
+#    endif /* ?VAXC */
+#  endif /* !AOS_VS */
+   typedef unsigned int extent;
+#endif /* ?MODERN */
+
+
+#ifndef MINIX            /* Minix needs it after all the other includes (?) */
+#  include <stdio.h>
+#endif
+#include <ctype.h>       /* skip for VMS, to use tolower() function? */
+#include <errno.h>       /* used in mapname() */
+#ifdef USE_STRINGS_H
+#  include <strings.h>   /* strcpy, strcmp, memcpy, index/rindex, etc. */
+#else
+#  include <string.h>    /* strcpy, strcmp, memcpy, strchr/strrchr, etc. */
+#endif
+#if (defined(MODERN) && !defined(NO_LIMITS_H))
+#  include <limits.h>    /* GRR:  EXPERIMENTAL!  (can be deleted) */
+#endif
+
+/* this include must be down here for SysV.4, for some reason... */
+#include <signal.h>      /* used in unzip.c, fileio.c */
+
+
+/*---------------------------------------------------------------------------
+    API (DLL) section:
+  ---------------------------------------------------------------------------*/
+
+#ifdef DLL
+#  define MAIN   UZ_EXP UzpMain   /* was UzpUnzip */
+#  ifdef OS2DLL
+#    undef Info
+#    define REDIRECTC(c)             varputchar(__G__ c)
+#    define REDIRECTPRINT(buf,size)  varmessage(__G__ buf, size)
+#    define FINISH_REDIRECT()        finish_REXX_redirect(__G)
+#  else
+#    define REDIRECTC(c)
+#    define REDIRECTPRINT(buf,size)  0
+#    define FINISH_REDIRECT()        close_redirect(__G)
+#  endif
+#endif
+
+/*---------------------------------------------------------------------------
+    Acorn RISCOS section:
+  ---------------------------------------------------------------------------*/
+
+#ifdef RISCOS
+#  include "acorn/riscos.h"
+#endif
+
+/*---------------------------------------------------------------------------
+    Amiga section:
+  ---------------------------------------------------------------------------*/
+
+#ifdef AMIGA
+#  include "amiga/amiga.h"
+#endif
+
+/*---------------------------------------------------------------------------
+    AOS/VS section (somewhat similar to Unix, apparently):
+  ---------------------------------------------------------------------------*/
+
+#ifdef AOS_VS
+#  ifdef FILEIO_C
+#    include "aosvs/aosvs.h"
+#  endif
+#endif
+
+/*---------------------------------------------------------------------------
+    Atari ST section:
+  ---------------------------------------------------------------------------*/
+
+#ifdef ATARI
+#  include <time.h>
+#  include <stat.h>
+#  include <fcntl.h>
+#  include <limits.h>
+#  define SYMLINKS
+#  define EXE_EXTENSION  ".tos"
+#  ifndef DATE_FORMAT
+#    define DATE_FORMAT  DF_DMY
+#  endif
+#  define DIR_END        '/'
+#  define INT_SPRINTF
+#  define timezone      _timezone
+#  define lenEOL        2
+#  define PutNativeEOL  {*q++ = native(CR); *q++ = native(LF);}
+#  undef SHORT_NAMES
+#  if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))
+#    define TIMESTAMP
+#  endif
+#endif
+
+/*---------------------------------------------------------------------------
+    BeOS section:
+  ---------------------------------------------------------------------------*/
+
+#ifdef __BEOS__
+#  include <sys/types.h>          /* [cjh]:  This is pretty much a generic  */
+#  include <sys/stat.h>           /* POSIX 1003.1 system; see beos/ for     */
+#  include <fcntl.h>              /* extra code to deal with our extra file */
+#  include <sys/param.h>          /* attributes. */
+#  include <unistd.h>
+#  include <utime.h>
+#  define DIRENT
+#  include <time.h>
+#  ifndef DATE_FORMAT
+#    define DATE_FORMAT DF_MDY  /* GRR:  customize with locale.h somehow? */
+#  endif
+#  define lenEOL        1
+#  define PutNativeEOL  *q++ = native(LF);
+#  define SCREENLINES   screenlines()
+#  define USE_EF_UT_TIME
+#  define SET_DIR_ATTRIB
+#  if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))
+#    define TIMESTAMP
+#  endif
+#  define RESTORE_UIDGID
+#  define NO_GMTIME               /* maybe DR10 will have timezones... */
+#  define INT_SPRINTF
+#  define SYMLINKS
+#  define MAIN main_stub          /* now that we're using a wrapper... */
+#endif
+
+/*---------------------------------------------------------------------------
+    Human68k/X68000 section:
+  ---------------------------------------------------------------------------*/
+
+#ifdef __human68k__    /* DO NOT DEFINE DOS_OS2 HERE!  If Human68k is so much */
+#  include <time.h>    /*  like MS-DOS and/or OS/2, create DOS_H68_OS2 macro. */
+#  include <fcntl.h>
+#  include <io.h>
+#  include <conio.h>
+#  include <jctype.h>
+#  include <sys/stat.h>
+#  ifndef DATE_FORMAT
+#    define DATE_FORMAT DF_YMD   /* Japanese standard */
+#  endif
+      /* GRR:  these EOL macros are guesses */
+#  define lenEOL        2
+#  define PutNativeEOL  {*q++ = native(CR); *q++ = native(LF);}
+#  define EXE_EXTENSION ".exe"   /* just a guess... */
+#endif
+
+/*---------------------------------------------------------------------------
+    Mac section:
+  ---------------------------------------------------------------------------*/
+
+#ifdef MACOS
+#  include "maccfg.h"
+#endif /* MACOS */
+
+/*---------------------------------------------------------------------------
+    MS-DOS, OS/2, FLEXOS section:
+  ---------------------------------------------------------------------------*/
+
+#ifdef WINDLL
+#  define MSWIN
+#  ifdef MORE
+#    undef MORE
+#  endif
+#  ifdef OS2_EAS
+#    undef OS2_EAS
+#  endif
+#endif
+
+#if (defined(_MSC_VER) || (defined(M_I86) && !defined(__WATCOMC__)))
+#  ifndef MSC
+#    define MSC               /* This should work for older MSC, too!  */
+#  endif
+#endif
+
+#if (defined(MSDOS) || defined(OS2) || defined(FLEXOS))
+#  include <sys/types.h>      /* off_t, time_t, dev_t, ... */
+#  include <sys/stat.h>
+#  include <io.h>             /* lseek(), open(), setftime(), dup(), creat() */
+#  include <time.h>           /* localtime() */
+#  include <fcntl.h>          /* O_BINARY for open() w/o CR/LF translation */
+
+#  ifdef OS2                  /* defined for all OS/2 compilers */
+#    include "os2/os2cfg.h"
+#  else
+#    ifdef FLEXOS
+#      include "flexos/flxcfg.h"
+#    else
+#      include "msdos/doscfg.h"
+#    endif
+#  endif
+
+#  if (defined(_MSC_VER) && (_MSC_VER == 700) && !defined(GRR))
+    /*
+     * ARGH.  MSC 7.0 libraries think times are based on 1899 Dec 31 00:00, not
+     *  1970 Jan 1 00:00.  So we have to diddle time_t's appropriately:  add or
+     *  subtract 70 years' worth of seconds; i.e., number of days times 86400;
+     *  i.e., (70*365 regular days + 17 leap days + 1 1899 day) * 86400 ==
+     *  (25550 + 17 + 1) * 86400 == 2209075200 seconds.  We know time_t is an
+     *  unsigned long (ulg) on the only system with this bug.
+     */
+#    define TIMET_TO_NATIVE(x)  (x) += (ulg)2209075200L;
+#    define NATIVE_TO_TIMET(x)  (x) -= (ulg)2209075200L;
+#  endif
+#  if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0450))
+#    define timezone      _timezone
+#  endif
+#  if (defined(__GO32__) || defined(FLEXOS))
+#    define DIR_END       '/'
+#  else
+#    define DIR_END       '\\'  /* OS uses '\\' as directory separator */
+#    define DIR_END2      '/'   /* also check for '/' (RTL may convert) */
+#  endif
+#  ifndef WIN32
+#    ifdef DATE_FORMAT
+#      undef DATE_FORMAT
+#    endif
+#    define DATE_FORMAT   dateformat()
+#  endif
+#  define lenEOL          2
+#  define PutNativeEOL    {*q++ = native(CR); *q++ = native(LF);}
+#  define USE_EF_UT_TIME
+#endif /* MSDOS || OS2 || FLEXOS */
+
+/*---------------------------------------------------------------------------
+    MTS section (piggybacks UNIX, I think):
+  ---------------------------------------------------------------------------*/
+
+#ifdef MTS
+#  include <sys/types.h>      /* off_t, time_t, dev_t, ... */
+#  include <sys/stat.h>
+#  include <sys/file.h>       /* MTS uses this instead of fcntl.h */
+#  include <timeb.h>
+#  include <time.h>
+#  include <unix.h>           /* some important non-ANSI routines */
+#  define mkdir(s,n) (-1)     /* no "make directory" capability */
+#  define EBCDIC              /* set EBCDIC conversion on */
+#  define NO_STRNICMP         /* unzip's is as good the one in MTS */
+#  define USE_FWRITE
+#  define close_outfile()  fclose(G.outfile)   /* can't set time on files */
+#  define umask(n)            /* don't have umask() on MTS */
+#  define FOPWT         "w"   /* open file for writing in TEXT mode */
+#  ifndef DATE_FORMAT
+#    define DATE_FORMAT DF_MDY
+#  endif
+#  define lenEOL        1
+#  define PutNativeEOL  *q++ = native(LF);
+#endif /* MTS */
+
+ /*---------------------------------------------------------------------------
+    QDOS section
+  ---------------------------------------------------------------------------*/
+
+#ifdef QDOS
+#  define DIRENT
+#  include <fcntl.h>
+#  include <unistd.h>
+#  include <sys/stat.h>
+#  include <time.h>
+#  include "qdos/izqdos.h"
+#  ifndef DATE_FORMAT
+#    define DATE_FORMAT DF_MDY
+#  endif
+#  define lenEOL        1
+#  define PutNativeEOL  *q++ = native(LF);
+#  define DIR_END       '_'
+#  define RETURN        QReturn
+#  undef PATH_MAX
+#  define PATH_MAX      36
+#  if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))
+#    define TIMESTAMP
+#  endif
+#endif
+
+/*---------------------------------------------------------------------------
+    Tandem NSK section:
+  ---------------------------------------------------------------------------*/
+
+#ifdef TANDEM
+#  include "tandem.h"
+#  include <fcntl.h>
+   /* use a single LF delimiter so that writes to 101 text files work */
+#  define PutNativeEOL  *q++ = native(LF);
+#  define lenEOL        1
+#  ifndef DATE_FORMAT
+#    define DATE_FORMAT  DF_DMY
+#  endif
+#  define USE_EF_UT_TIME
+#  define RESTORE_UIDGID
+#endif
+
+/*---------------------------------------------------------------------------
+    TOPS-20 section:
+  ---------------------------------------------------------------------------*/
+
+#ifdef TOPS20
+#  include <sys/types.h>        /* off_t, time_t, dev_t, ... */
+#  include <sys/stat.h>
+#  include <sys/param.h>
+#  include <sys/time.h>
+#  include <sys/timeb.h>
+#  include <sys/file.h>
+#  include <timex.h>
+#  include <monsym.h>           /* get amazing monsym() macro */
+   extern int open(), close(), read();
+   extern int stat(), unlink(), jsys(), fcntl();
+   extern long lseek(), dup(), creat();
+#  define strchr    index       /* GRR: necessary? */
+#  define strrchr   rindex
+#  define REALLY_SHORT_SYMS
+#  define NO_MKDIR
+#  define DIR_BEG       '<'
+#  define DIR_END       '>'
+#  define DIR_EXT       ".directory"
+#  ifndef DATE_FORMAT
+#    define DATE_FORMAT DF_MDY
+#  endif
+#  define EXE_EXTENSION ".exe"  /* just a guess... */
+#endif /* TOPS20 */
+
+/*---------------------------------------------------------------------------
+    Unix section:
+  ---------------------------------------------------------------------------*/
+
+#ifdef UNIX
+#  include <sys/types.h>       /* off_t, time_t, dev_t, ... */
+#  include <sys/stat.h>
+
+#  ifndef COHERENT
+#    include <fcntl.h>         /* O_BINARY for open() w/o CR/LF translation */
+#  else /* COHERENT */
+#    ifdef _I386
+#      include <fcntl.h>       /* Coherent 4.0.x, Mark Williams C */
+#    else
+#      include <sys/fcntl.h>   /* Coherent 3.10, Mark Williams C */
+#    endif
+#    define SHORT_SYMS
+#    ifndef __COHERENT__       /* Coherent 4.2 has tzset() */
+#      define tzset  settz
+#    endif
+#  endif /* ?COHERENT */
+
+#  ifndef NO_PARAM_H
+#    ifdef NGROUPS_MAX
+#      undef NGROUPS_MAX       /* SCO bug:  defined again in <sys/param.h> */
+#    endif
+#    ifdef BSD
+#      define TEMP_BSD         /* may be defined again in <sys/param.h> */
+#      undef BSD
+#    endif
+#    include <sys/param.h>     /* conflict with <sys/types.h>, some systems? */
+#    ifdef TEMP_BSD
+#      undef TEMP_BSD
+#      ifndef BSD
+#        define BSD
+#      endif
+#    endif
+#  endif /* !NO_PARAM_H */
+
+#  ifdef __osf__
+#    define DIRENT
+#    ifdef BSD
+#      undef BSD
+#    endif
+#  endif /* __osf__ */
+
+#  ifdef BSD
+#    include <sys/time.h>
+#    include <sys/timeb.h>
+#    ifdef _AIX
+#      include <time.h>
+#    endif
+#  else
+#    include <time.h>
+     struct tm *gmtime(), *localtime();
+#  endif
+
+#  if (defined(BSD4_4) || (defined(SYSV) && defined(MODERN)))
+#    include <unistd.h>        /* this includes utime.h on SGIs */
+#    if (defined(BSD4_4) || defined(linux))
+#      include <utime.h>
+#      define GOT_UTIMBUF
+#    endif
+#  endif
+
+#  if (defined(V7) || defined(pyr_bsd))
+#    define strchr   index
+#    define strrchr  rindex
+#  endif
+#  ifdef V7
+#    define O_RDONLY 0
+#    define O_WRONLY 1
+#    define O_RDWR   2
+#  endif
+
+#  ifdef MINIX
+#    include <stdio.h>
+#  endif
+#  ifndef DATE_FORMAT
+#    define DATE_FORMAT DF_MDY    /* GRR:  customize with locale.h somehow? */
+#  endif
+#  define lenEOL        1
+#  ifdef EBCDIC
+#    define PutNativeEOL  *q++ = '\n';
+#  else
+#    define PutNativeEOL  *q++ = native(LF);
+#  endif
+#  define SCREENLINES   screenlines()
+#  define USE_EF_UT_TIME
+#  define SET_DIR_ATTRIB
+#  if (!defined(TIMESTAMP) && !defined(NOTIMESTAMP))   /* GRR 970513 */
+#    define TIMESTAMP
+#  endif
+#  define RESTORE_UIDGID
+#endif /* UNIX */
+
+/*---------------------------------------------------------------------------
+    VM/CMS and MVS section:
+  ---------------------------------------------------------------------------*/
+
+#ifdef CMS_MVS
+#  include "vmmvs.h"
+#  define CLOSE_INFILE()  close_infile(__G)
+#endif
+
+/*---------------------------------------------------------------------------
+    VMS section:
+  ---------------------------------------------------------------------------*/
+
+#ifdef VMS
+#  include <types.h>                    /* GRR:  experimenting... */
+#  include <stat.h>
+#  include <time.h>                     /* the usual non-BSD time functions */
+#  include <file.h>                     /* same things as fcntl.h has */
+#  include <unixio.h>
+#  include <rms.h>
+#  define _MAX_PATH (NAM$C_MAXRSS+1)    /* to define FILNAMSIZ below */
+#  ifdef RETURN_CODES  /* VMS interprets standard PK return codes incorrectly */
+#    define RETURN(ret) return_VMS(__G__ (ret))   /* verbose version */
+#    define EXIT(ret)   return_VMS(__G__ (ret))
+#  else
+#    define RETURN      return_VMS                /* quiet version */
+#    define EXIT        return_VMS
+#  endif
+#  ifdef VMSCLI
+#    define USAGE(ret)  VMSCLI_usage(__G__ (ret))
+#  endif
+#  define DIR_BEG       '['
+#  define DIR_END       ']'
+#  define DIR_EXT       ".dir"
+#  ifndef DATE_FORMAT
+#    define DATE_FORMAT DF_MDY
+#  endif
+#  define lenEOL        1
+#  define PutNativeEOL  *q++ = native(LF);
+#  define SCREENLINES   screenlines()
+#  if (defined(__VMS_VERSION) && !defined(VMS_VERSION))
+#    define VMS_VERSION __VMS_VERSION
+#  endif
+#  if (defined(__VMS_VER) && !defined(__CRTL_VER))
+#    define __CRTL_VER __VMS_VER
+#  endif
+#  if ((!defined(__CRTL_VER)) || (__CRTL_VER < 70000000))
+#    define NO_GMTIME           /* gmtime() of earlier VMS C RTLs is broken */
+#  else
+#    if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME))
+#      define USE_EF_UT_TIME
+#    endif
+#  endif
+#  if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))
+#    define TIMESTAMP
+#  endif
+#  define RESTORE_UIDGID
+#endif /* VMS */
+
+/*---------------------------------------------------------------------------
+    Win32 (Windows 95/NT) section:
+  ---------------------------------------------------------------------------*/
+
+#if (defined(WIN32) && !defined(POCKET_UNZIP))
+#  include "w32cfg.h"
+#endif
+
+
+
+
+
+/*************/
+/*  Defines  */
+/*************/
+
+#define UNZIP_VERSION     20   /* compatible with PKUNZIP 2.0 */
+#define VMS_UNZIP_VERSION 42   /* if OS-needed-to-extract is VMS:  can do */
+
+#if (defined(MSDOS) || defined(OS2))
+#  define DOS_OS2
+#endif
+
+#if (defined(OS2) || defined(WIN32))
+#  define OS2_W32
+#endif
+
+#if (defined(DOS_OS2) || defined(WIN32))
+#  define DOS_OS2_W32
+#  define DOS_W32_OS2          /* historical:  don't use */
+#endif
+
+#if (defined(DOS_OS2_W32) || defined(__human68k__))
+#  define DOS_H68_OS2_W32
+#endif
+
+#if (defined(DOS_OS2) || defined(FLEXOS))
+#  define DOS_FLX_OS2
+#endif
+
+#if (defined(DOS_OS2_W32) || defined(FLEXOS))
+#  define DOS_FLX_OS2_W32
+#endif
+
+#if (defined(DOS_H68_OS2_W32) || defined(FLEXOS))
+#  define DOS_FLX_H68_OS2_W32
+#endif
+
+#if (defined(TOPS20) || defined(VMS))
+#  define T20_VMS
+#endif
+
+#if (defined(MSDOS) || defined(T20_VMS))
+#  define DOS_T20_VMS
+#endif
+
+/* clean up with a few defaults */
+#ifndef DIR_END
+#  define DIR_END       '/'     /* last char before program name or filename */
+#endif
+#ifndef DATE_FORMAT
+#  define DATE_FORMAT   DF_MDY  /* defaults to US convention */
+#endif
+#ifndef CLOSE_INFILE
+#  define CLOSE_INFILE()  close(G.zipfd)
+#endif
+#ifndef RETURN
+#  define RETURN        return  /* only used in main() */
+#endif
+#ifndef EXIT
+#  define EXIT          exit
+#endif
+#ifndef USAGE
+#  define USAGE(ret)    usage(__G__ (ret))    /* used in unzip.c, zipinfo.c */
+#endif
+#ifndef TIMET_TO_NATIVE         /* everybody but MSC 7.0 and Macintosh */
+#  define TIMET_TO_NATIVE(x)
+#  define NATIVE_TO_TIMET(x)
+#endif
+
+#if (defined(DOS_FLX_OS2_W32) || defined(UNIX) || defined(RISCOS))
+#  ifndef HAVE_UNLINK
+#    define HAVE_UNLINK
+#  endif
+#endif
+#if (defined(AOS_VS) || defined(ATARI) || defined(__BEOS__)) /* GRR: others? */
+#  ifndef HAVE_UNLINK
+#    define HAVE_UNLINK
+#  endif
+#endif
+
+/* OS-specific exceptions to the "ANSI <--> INT_SPRINTF" rule */
+
+#if (!defined(PCHAR_SPRINTF) && !defined(INT_SPRINTF))
+#  if (defined(SYSV) || defined(CONVEX) || defined(NeXT) || defined(BSD4_4))
+#    define INT_SPRINTF      /* sprintf() returns int:  SysVish/Posix */
+#  endif
+#  if (defined(DOS_FLX_OS2_W32) || defined(VMS) || defined(AMIGA))
+#    define INT_SPRINTF      /* sprintf() returns int:  ANSI */
+#  endif
+#  if (defined(ultrix) || defined(__ultrix)) /* Ultrix 4.3 and newer */
+#    if (defined(POSIX) || defined(__POSIX))
+#      define INT_SPRINTF    /* sprintf() returns int:  ANSI/Posix */
+#    endif
+#    ifdef __GNUC__
+#      define PCHAR_SPRINTF  /* undetermined actual return value */
+#    endif
+#  endif
+#  if (defined(__osf__) || defined(_AIX) || defined(CMS_MVS))
+#    define INT_SPRINTF      /* sprintf() returns int:  ANSI/Posix */
+#  endif
+#  if defined(sun)
+#    define PCHAR_SPRINTF    /* sprintf() returns char *:  SunOS cc *and* gcc */
+#  endif
+#endif
+
+/* defaults that we hope will take care of most machines in the future */
+
+#if (!defined(PCHAR_SPRINTF) && !defined(INT_SPRINTF))
+#  ifdef __STDC__
+#    define INT_SPRINTF      /* sprintf() returns int:  ANSI */
+#  endif
+#  ifndef INT_SPRINTF
+#    define PCHAR_SPRINTF    /* sprintf() returns char *:  BSDish */
+#  endif
+#endif
+
+#define MSG_STDERR(f)  (f & 1)        /* bit 0:  0 = stdout, 1 = stderr */
+#define MSG_INFO(f)    ((f & 6) == 0) /* bits 1 and 2:  0 = info */
+#define MSG_WARN(f)    ((f & 6) == 2) /* bits 1 and 2:  1 = warning */
+#define MSG_ERROR(f)   ((f & 6) == 4) /* bits 1 and 2:  2 = error */
+#define MSG_FATAL(f)   ((f & 6) == 6) /* bits 1 and 2:  (3 = fatal error) */
+#define MSG_ZFN(f)     (f & 0x0008)   /* bit 3:  1 = print zipfile name */
+#define MSG_FN(f)      (f & 0x0010)   /* bit 4:  1 = print filename */
+#define MSG_LNEWLN(f)  (f & 0x0020)   /* bit 5:  1 = leading newline if !SOL */
+#define MSG_TNEWLN(f)  (f & 0x0040)   /* bit 6:  1 = trailing newline if !SOL */
+#define MSG_MNEWLN(f)  (f & 0x0080)   /* bit 7:  1 = trailing NL for prompts */
+/* the following are subject to change */
+#define MSG_NO_WGUI(f) (f & 0x0100)   /* bit 8:  1 = skip if Windows GUI */
+#define MSG_NO_AGUI(f) (f & 0x0200)   /* bit 9:  1 = skip if Acorn GUI */
+#define MSG_NO_DLL2(f) (f & 0x0400)   /* bit 10:  1 = skip if OS/2 DLL */
+#define MSG_NO_NDLL(f) (f & 0x0800)   /* bit 11:  1 = skip if WIN32 DLL */
+#define MSG_NO_WDLL(f) (f & 0x1000)   /* bit 12:  1 = skip if Windows DLL */
+
+#if (defined(MORE) && !defined(SCREENLINES))
+#  ifdef DOS_FLX_OS2_W32
+#    define SCREENLINES 25  /* can be (should be) a function instead */
+#  else
+#    define SCREENLINES 24  /* VT-100s are assumed to be minimal hardware */
+#  endif
+#endif
+
+#define DIR_BLKSIZ  64      /* number of directory entries per block
+                             *  (should fit in 4096 bytes, usually) */
+#ifndef WSIZE
+#  define WSIZE     0x8000  /* window size--must be a power of two, and */
+#endif                      /*  at least 32K for zip's deflate method */
+
+#ifndef INBUFSIZ
+#  if (defined(MED_MEM) || defined(SMALL_MEM))
+#    define INBUFSIZ  2048  /* works for MS-DOS small model */
+#  else
+#    define INBUFSIZ  8192  /* larger buffers for real OSes */
+#  endif
+#endif
+
+#ifndef __16BIT__
+#  define nearmalloc  malloc
+#  define nearfree    free
+#  if (!defined(__IBMC__) || !defined(OS2))
+#    ifndef near
+#      define near
+#    endif
+#    ifndef far
+#      define far
+#    endif
+#  endif
+#endif
+
+#if (defined(DYNALLOC_CRCTAB) && !defined(DYNAMIC_CRC_TABLE))
+#  undef DYNALLOC_CRCTAB
+#endif
+
+#if (defined(DYNALLOC_CRCTAB) && defined(REENTRANT))
+#  undef DYNALLOC_CRCTAB   /* not safe with reentrant code */
+#endif
+
+#if (defined(USE_ZLIB) && !defined(USE_OWN_CRCTAB))
+#  ifdef DYNALLOC_CRCTAB
+#    undef DYNALLOC_CRCTAB
+#  endif
+#endif
+
+#if (defined(USE_ZLIB) && defined(ASM_CRC))
+#  undef ASM_CRC
+#endif
+
+/* Logic for case of small memory, length of EOL > 1:  if OUTBUFSIZ == 2048,
+ * OUTBUFSIZ>>1 == 1024 and OUTBUFSIZ>>7 == 16; therefore rawbuf is 1008 bytes
+ * and transbuf 1040 bytes.  Have room for 32 extra EOL chars; 1008/32 == 31.5
+ * chars/line, smaller than estimated 35-70 characters per line for C source
+ * and normal text.  Hence difference is sufficient for most "average" files.
+ * (Argument scales for larger OUTBUFSIZ.)
+ */
+#ifdef SMALL_MEM          /* i.e., 16-bit OSes:  MS-DOS, OS/2 1.x, etc. */
+#  define LoadFarString(x)       fLoadFarString(__G__ (x))
+#  define LoadFarStringSmall(x)  fLoadFarStringSmall(__G__ (x))
+#  define LoadFarStringSmall2(x) fLoadFarStringSmall2(__G__ (x))
+#  if (defined(_MSC_VER) && (_MSC_VER >= 600))
+#    define zfstrcpy(dest, src)  _fstrcpy((dest), (src))
+#  endif
+#  ifndef Far
+#    define Far far  /* __far only works for MSC 6.00, not 6.0a or Borland */
+#  endif
+#  define OUTBUFSIZ INBUFSIZ
+#  if (lenEOL == 1)
+#    define RAWBUFSIZ (OUTBUFSIZ>>1)
+#  else
+#    define RAWBUFSIZ ((OUTBUFSIZ>>1) - (OUTBUFSIZ>>7))
+#  endif
+#  define TRANSBUFSIZ (OUTBUFSIZ-RAWBUFSIZ)
+   typedef short  shrint;            /* short/int or "shrink int" (unshrink) */
+#else
+#  define zfstrcpy(dest, src)       strcpy((dest), (src))
+#  ifdef QDOS
+#    define LoadFarString(x)        Qstrfix(x)   /* fix up _ for '.' */
+#    define LoadFarStringSmall(x)   Qstrfix(x)
+#    define LoadFarStringSmall2(x)  Qstrfix(x)
+#  else
+#    define LoadFarString(x)        x
+#    define LoadFarStringSmall(x)   x
+#    define LoadFarStringSmall2(x)  x
+#  endif
+#  ifdef MED_MEM
+#    define OUTBUFSIZ 0xFF80         /* can't malloc arrays of 0xFFE8 or more */
+#    define TRANSBUFSIZ 0xFF80
+     typedef short  shrint;
+#  else
+#    define OUTBUFSIZ (lenEOL*WSIZE) /* more efficient text conversion */
+#    define TRANSBUFSIZ (lenEOL*OUTBUFSIZ)
+#    ifdef AMIGA
+       typedef short shrint;
+#    else
+       typedef int  shrint;          /* for efficiency/speed, we hope... */
+#    endif
+#  endif /* ?MED_MEM */
+#  define RAWBUFSIZ OUTBUFSIZ
+#endif /* ?SMALL_MEM */
+
+#ifndef Far
+#  define Far
+#endif
+
+#ifndef MAIN
+#  define MAIN  main
+#endif
+
+#ifdef SFX      /* disable some unused features for SFX executables */
+#  ifndef NO_ZIPINFO
+#    define NO_ZIPINFO
+#  endif
+#  ifdef TIMESTAMP
+#    undef TIMESTAMP
+#  endif
+#endif
+
+/* user may have defined both by accident...  NOTIMESTAMP takes precedence */
+#if (defined(TIMESTAMP) && defined(NOTIMESTAMP))
+#  undef TIMESTAMP
+#endif
+
+#if (!defined(COPYRIGHT_CLEAN) && !defined(USE_SMITH_CODE))
+#  define COPYRIGHT_CLEAN
+#endif
+
+#if (!defined(LZW_CLEAN) && !defined(USE_UNSHRINK))
+#  define LZW_CLEAN
+#endif
+
+#ifndef O_BINARY
+#  define O_BINARY  0
+#endif
+
+#ifndef PIPE_ERROR
+#  define PIPE_ERROR (errno == EPIPE)
+#endif
+
+/* File operations--use "b" for binary if allowed or fixed length 512 on VMS */
+#ifdef VMS
+#  define FOPR  "r","ctx=stm"
+#  define FOPM  "r+","ctx=stm","rfm=fix","mrs=512"
+#  define FOPW  "w","ctx=stm","rfm=fix","mrs=512"
+#endif /* VMS */
+
+#ifdef CMS_MVS
+/* Binary files must be RECFM=F,LRECL=1 for ftell() to get correct pos */
+/* ...unless byteseek is used.  Let's try that for a while.            */
+#  define FOPR "rb,byteseek"
+#  define FOPM "r+b,byteseek"
+#  define FOPW "wb,recfm=v,lrecl=32760"
+#  ifdef MVS
+#    define FOPWT "w,lrecl=133"
+#  else
+#    define FOPWT "w"
+#  endif
+#endif /* CMS_MVS */
+
+#ifdef TOPS20          /* TOPS-20 MODERN?  You kidding? */
+#  define FOPW "w8"
+#endif /* TOPS20 */
+
+/* Defaults when nothing special has been defined previously. */
+#ifdef MODERN
+#  ifndef FOPR
+#    define FOPR "rb"
+#  endif
+#  ifndef FOPM
+#    define FOPM "r+b"
+#  endif
+#  ifndef FOPW
+#    define FOPW "wb"
+#  endif
+#  ifndef FOPWT
+#    define FOPWT "wt"
+#  endif
+#else /* !MODERN */
+#  ifndef FOPR
+#    define FOPR "r"
+#  endif
+#  ifndef FOPM
+#    define FOPM "r+"
+#  endif
+#  ifndef FOPW
+#    define FOPW "w"
+#  endif
+#  ifndef FOPWT
+#    define FOPWT "w"
+#  endif
+#endif /* ?MODERN */
+
+/*
+ * If <limits.h> exists on most systems, should include that, since it may
+ * define some or all of the following:  NAME_MAX, PATH_MAX, _POSIX_NAME_MAX,
+ * _POSIX_PATH_MAX.
+ */
+#ifdef DOS_FLX_OS2
+#  include <limits.h>
+#endif
+
+#ifndef PATH_MAX
+#  ifdef MAXPATHLEN
+#    define PATH_MAX      MAXPATHLEN    /* in <sys/param.h> on some systems */
+#  else
+#    ifdef _MAX_PATH
+#      define PATH_MAX    _MAX_PATH
+#    else
+#      if FILENAME_MAX > 255
+#        define PATH_MAX  FILENAME_MAX  /* used like PATH_MAX on some systems */
+#      else
+#        define PATH_MAX  1024
+#      endif
+#    endif /* ?_MAX_PATH */
+#  endif /* ?MAXPATHLEN */
+#endif /* !PATH_MAX */
+
+#define FILNAMSIZ  PATH_MAX
+
+#ifdef SHORT_SYMS                   /* Mark Williams C, ...? */
+#  define extract_or_test_files     xtr_or_tst_files
+#  define extract_or_test_member    xtr_or_tst_member
+#endif
+
+#ifdef REALLY_SHORT_SYMS            /* TOPS-20 linker:  first 6 chars */
+#  define process_cdir_file_hdr     XXpcdfh
+#  define process_local_file_hdr    XXplfh
+#  define extract_or_test_files     XXxotf  /* necessary? */
+#  define extract_or_test_member    XXxotm  /* necessary? */
+#  define check_for_newer           XXcfn
+#  define overwrite_all             XXoa
+#  define process_all_files         XXpaf
+#  define extra_field               XXef
+#  define explode_lit8              XXel8
+#  define explode_lit4              XXel4
+#  define explode_nolit8            XXnl8
+#  define explode_nolit4            XXnl4
+#  define cpdist8                   XXcpdist8
+#  define inflate_codes             XXic
+#  define inflate_stored            XXis
+#  define inflate_fixed             XXif
+#  define inflate_dynamic           XXid
+#  define inflate_block             XXib
+#  define maxcodemax                XXmax
+#endif
+
+#ifndef S_TIME_T_MAX            /* max value of signed (>= 32-bit) time_t */
+#  define S_TIME_T_MAX  ((time_t)(ulg)0x7fffffffL)
+#endif
+#ifndef U_TIME_T_MAX            /* max value of unsigned (>= 32-bit) time_t */
+#  define U_TIME_T_MAX  ((time_t)(ulg)0xffffffffL)
+#endif
+#ifdef DOSTIME_MINIMUM          /* min DOSTIME value (1980-01-01) */
+#  undef DOSTIME_MINIMUM
+#endif
+#define DOSTIME_MINIMUM ((ulg)0x00210000L)
+#ifdef DOSTIME_2038_01_18       /* approximate DOSTIME equivalent of */
+#  undef DOSTIME_2038_01_18     /*  the signed-32-bit time_t limit */
+#endif
+#define DOSTIME_2038_01_18 ((ulg)0x74320000L)
+
+#ifdef QDOS
+#  define ZSUFX         "_zip"
+#  define ALT_ZSUFX     ".zip"
+#else
+#  ifdef RISCOS
+#    define ZSUFX       "/zip"
+#  else
+#    define ZSUFX       ".zip"
+#  endif
+#  define ALT_ZSUFX     ".ZIP"   /* Unix-only so far (only case-sensitive fs) */
+#endif
+
+#define CENTRAL_HDR_SIG   "\001\002"   /* the infamous "PK" signature bytes, */
+#define LOCAL_HDR_SIG     "\003\004"   /*  sans "PK" (so unzip executable not */
+#define END_CENTRAL_SIG   "\005\006"   /*  mistaken for zipfile itself) */
+#define EXTD_LOCAL_SIG    "\007\010"   /* [ASCII "\113" == EBCDIC "\080" ??] */
+
+/* choice of activities for do_string() */
+#define SKIP              0             /* skip header block */
+#define DISPLAY           1             /* display archive comment (ASCII) */
+#define DISPL_8           5             /* display file comment (ext. ASCII) */
+#define DS_FN             2             /* read filename (ext. ASCII) */
+#define EXTRA_FIELD       3             /* copy extra field into buffer */
+#define DS_EF             3
+#ifdef AMIGA
+#  define FILENOTE        4
+#endif
+
+#define DOES_NOT_EXIST    -1   /* return values for check_for_newer() */
+#define EXISTS_AND_OLDER  0
+#define EXISTS_AND_NEWER  1
+
+#define ROOT              0    /* checkdir() extract-to path:  called once */
+#define INIT              1    /* allocate buildpath:  called once per member */
+#define APPEND_DIR        2    /* append a dir comp.:  many times per member */
+#define APPEND_NAME       3    /* append actual filename:  once per member */
+#define GETPATH           4    /* retrieve the complete path and free it */
+#define END               5    /* free root path prior to exiting program */
+
+/* version_made_by codes (central dir):  make sure these */
+/*  are not defined on their respective systems!! */
+#define FS_FAT_           0    /* filesystem used by MS-DOS, OS/2, Win32 */
+#define AMIGA_            1
+#define VMS_              2
+#define UNIX_             3
+#define VM_CMS_           4
+#define ATARI_            5    /* what if it's a minix filesystem? [cjh] */
+#define FS_HPFS_          6    /* filesystem used by OS/2 (and NT 3.x) */
+#define MAC_              7    /* HFS filesystem used by MacOS */
+#define Z_SYSTEM_         8
+#define CPM_              9
+#define TOPS20_           10
+#define FS_NTFS_          11   /* filesystem used by Windows NT */
+#define QDOS_             12
+#define ACORN_            13   /* Archimedes Acorn RISC OS */
+#define FS_VFAT_          14   /* filesystem used by Windows 95, NT */
+#define MVS_              15
+#define BEOS_             16   /* hybrid POSIX/database filesystem */
+#define TANDEM_           17   /* Tandem/NSK */
+#define NUM_HOSTS         18   /* index of last system + 1 */
+
+#define STORED            0    /* compression methods */
+#define SHRUNK            1
+#define REDUCED1          2
+#define REDUCED2          3
+#define REDUCED3          4
+#define REDUCED4          5
+#define IMPLODED          6
+#define TOKENIZED         7
+#define DEFLATED          8
+#define ENHDEFLATED       9
+#define DCLIMPLODED      10
+#define NUM_METHODS      11    /* index of last method + 1 */
+/* don't forget to update list_files(), extract.c and zipinfo.c appropriately
+ * if NUM_METHODS changes */
+
+/* (the PK-class error codes are public and have been moved into unzip.h) */
+
+#define DF_MDY            0    /* date format 10/26/91 (USA only) */
+#define DF_DMY            1    /* date format 26/10/91 (most of the world) */
+#define DF_YMD            2    /* date format 91/10/26 (a few countries) */
+
+/*---------------------------------------------------------------------------
+    Extra-field block ID values and offset info.
+  ---------------------------------------------------------------------------*/
+/* extra-field ID values, all little-endian: */
+#define EF_AV        0x0007    /* PKWARE's authenticity verification */
+#define EF_OS2       0x0009    /* OS/2 extended attributes */
+#define EF_PKW32     0x000a    /* PKWARE's Win95/98/WinNT filetimes */
+#define EF_PKVMS     0x000c    /* PKWARE's VMS */
+#define EF_PKUNIX    0x000d    /* PKWARE's Unix */
+#define EF_IZVMS     0x4d49    /* Info-ZIP's VMS ("IM") */
+#define EF_IZUNIX    0x5855    /* Info-ZIP's old Unix[1] ("UX") */
+#define EF_IZUNIX2   0x7855    /* Info-ZIP's new Unix[2] ("Ux") */
+#define EF_TIME      0x5455    /* universal timestamp ("UT") */
+#define EF_MAC3      0x334d    /* Info-ZIP's new Macintosh (= "M3") */
+#define EF_JLMAC     0x07c8    /* Johnny Lee's old Macintosh (= 1992) */
+#define EF_ZIPIT     0x2605    /* Thomas Brown's Macintosh (ZipIt) */
+#define EF_ZIPIT2    0x2705    /* T. Brown's Mac (ZipIt) v 1.3.8 and newer ? */
+#define EF_VMCMS     0x4704    /* Info-ZIP's VM/CMS ("\004G") */
+#define EF_MVS       0x470f    /* Info-ZIP's MVS ("\017G") */
+#define EF_ACL       0x4c41    /* (OS/2) access control list ("AL") */
+#define EF_NTSD      0x4453    /* NT security descriptor ("SD") */
+#define EF_BEOS      0x6542    /* BeOS ("Be") */
+#define EF_QDOS      0xfb4a    /* SMS/QDOS ("J\373") */
+#define EF_AOSVS     0x5356    /* AOS/VS ("VS") */
+#define EF_SPARK     0x4341    /* David Pilling's Acorn/SparkFS ("AC") */
+#define EF_MD5       0x4b46    /* Fred Kantor's MD5 ("FK") */
+#define EF_ASIUNIX   0x756e    /* ASi's Unix ("nu") */
+
+#define EB_HEADSIZE       4    /* length of extra field block header */
+#define EB_ID             0    /* offset of block ID in header */
+#define EB_LEN            2    /* offset of data length field in header */
+#define EB_UCSIZE_P       0    /* offset of ucsize field in compr. data */
+#define EB_CMPRHEADLEN    6    /* lenght of compression header */
+
+#define EB_UX_MINLEN      8    /* minimal "UX" field contains atime, mtime */
+#define EB_UX_FULLSIZE    12   /* full "UX" field (atime, mtime, uid, gid) */
+#define EB_UX_ATIME       0    /* offset of atime in "UX" extra field data */
+#define EB_UX_MTIME       4    /* offset of mtime in "UX" extra field data */
+#define EB_UX_UID         8    /* byte offset of UID in "UX" field data */
+#define EB_UX_GID         10   /* byte offset of GID in "UX" field data */
+
+#define EB_UX2_MINLEN     4    /* minimal "Ux" field contains UID/GID */
+#define EB_UX2_UID        0    /* byte offset of UID in "Ux" field data */
+#define EB_UX2_GID        2    /* byte offset of GID in "Ux" field data */
+#define EB_UX2_VALID      (1 << 8)      /* UID/GID present */
+
+#define EB_UT_MINLEN      1    /* minimal UT field contains Flags byte */
+#define EB_UT_FLAGS       0    /* byte offset of Flags field */
+#define EB_UT_TIME1       1    /* byte offset of 1st time value */
+#define EB_UT_FL_MTIME    (1 << 0)      /* mtime present */
+#define EB_UT_FL_ATIME    (1 << 1)      /* atime present */
+#define EB_UT_FL_CTIME    (1 << 2)      /* ctime present */
+
+#define EB_FLGS_OFFS      4    /* offset of flags area in generic compressed
+                                  extra field blocks (OS2, NT, and others) */
+#define EB_OS2_HLEN       4    /* size of OS2/ACL compressed data header */
+#define EB_BEOS_HLEN      5    /* length of BeOS e.f attribute header */
+#define EB_BE_FL_UNCMPR   0x01 /* "BeOS attributes uncompressed" bit flag */
+#define EB_MAC3_HLEN      14   /* length of Mac3 attribute block header */
+#define EB_M3_FL_DATFRK   0x01 /* "this entry is data fork" flag */
+#define EB_M3_FL_UNCMPR   0x04 /* "Mac3 attributes uncompressed" bit flag */
+#define EB_M3_FL_TIME64   0x08 /* "Mac3 time fields are 64 bit wide" flag */
+#define EB_M3_FL_NOUTC    0x10 /* "Mac3 timezone offset fields missing" flag */
+
+#define EB_NTSD_C_LEN     4    /* length of central NT security data */
+#define EB_NTSD_L_LEN     5    /* length of minimal local NT security data */
+#define EB_NTSD_VERSION   4    /* offset of NTSD version byte */
+#define EB_NTSD_MAX_VER   (0)  /* maximum version # we know how to handle */
+
+#define EB_ASI_CRC32      0    /* offset of ASI Unix field's crc32 checksum */
+#define EB_ASI_MODE       4    /* offset of ASI Unix permission mode field */
+
+/*---------------------------------------------------------------------------
+    True sizes of the various headers, as defined by PKWARE--so it is not
+    likely that these will ever change.  But if they do, make sure both these
+    defines AND the typedefs below get updated accordingly.
+  ---------------------------------------------------------------------------*/
+#define LREC_SIZE   26   /* lengths of local file headers, central */
+#define CREC_SIZE   42   /*  directory headers, and the end-of-    */
+#define ECREC_SIZE  18   /*  central-dir record, respectively      */
+
+#define MAX_BITS    13                 /* used in unshrink() */
+#define HSIZE       (1 << MAX_BITS)    /* size of global work area */
+
+#define LF     10        /* '\n' on ASCII machines; must be 10 due to EBCDIC */
+#define CR     13        /* '\r' on ASCII machines; must be 13 due to EBCDIC */
+#define CTRLZ  26        /* DOS & OS/2 EOF marker (used in fileio.c, vms.c) */
+
+#ifdef EBCDIC
+#  define foreign(c)    ascii[(uch)(c)]
+#  define native(c)     ebcdic[(uch)(c)]
+#  define NATIVE        "EBCDIC"
+#  define NOANSIFILT
+#endif
+
+#if (defined(CRAY) && defined(ZMEM))
+#  undef ZMEM
+#endif
+
+#ifdef ZMEM
+#  undef ZMEM
+#  define memcmp(b1,b2,len)      bcmp(b2,b1,len)
+#  define memcpy(dest,src,len)   bcopy(src,dest,len)
+#  define memzero                bzero
+#else
+#  define memzero(dest,len)      memset(dest,0,len)
+#endif
+
+#ifdef VMS
+#  define ENV_UNZIP       "UNZIP_OPTS"     /* names of environment variables */
+#  define ENV_ZIPINFO     "ZIPINFO_OPTS"
+#endif /* VMS */
+#ifdef RISCOS
+#  define ENV_UNZIP       "Unzip$Options"
+#  define ENV_ZIPINFO     "Zipinfo$Options"
+#  define ENV_UNZIPEXTS   "Unzip$Exts"
+#endif /* RISCOS */
+#ifndef ENV_UNZIP
+#  define ENV_UNZIP       "UNZIP"          /* the standard names */
+#  define ENV_ZIPINFO     "ZIPINFO"
+#endif
+#define ENV_UNZIP2        "UNZIPOPT"     /* alternate names, for zip compat. */
+#define ENV_ZIPINFO2      "ZIPINFOOPT"
+
+#if (!defined(QQ) && !defined(NOQQ))
+#  define QQ
+#endif
+
+#ifdef QQ                         /* Newtware version:  no file */
+#  define QCOND     (!uO.qflag)   /*  comments with -vq or -vqq */
+#else                             /* Bill Davidsen version:  no way to */
+#  define QCOND     (longhdr)     /*  kill file comments when listing */
+#endif
+
+#ifdef OLD_QQ
+#  define QCOND2    (uO.qflag < 2)
+#else
+#  define QCOND2    (!uO.qflag)
+#endif
+
+#ifndef TRUE
+#  define TRUE      1   /* sort of obvious */
+#endif
+#ifndef FALSE
+#  define FALSE     0
+#endif
+
+#ifndef SEEK_SET
+#  define SEEK_SET  0
+#  define SEEK_CUR  1
+#  define SEEK_END  2
+#endif
+
+#if (defined(UNIX) && defined(S_IFLNK) && !defined(MTS))
+#  define SYMLINKS
+#  ifndef S_ISLNK
+#    define S_ISLNK(m)  (((m) & S_IFMT) == S_IFLNK)
+#  endif
+#endif /* UNIX && S_IFLNK && !MTS */
+
+#ifndef S_ISDIR
+#  ifdef CMS_MVS
+#    define S_ISDIR(m)  (FALSE)
+#  else
+#    define S_ISDIR(m)  (((m) & S_IFMT) == S_IFDIR)
+# endif
+#endif
+
+#ifndef IS_VOLID
+#  define IS_VOLID(m)  ((m) & 0x08)
+#endif
+
+
+
+
+
+/**************/
+/*  Typedefs  */
+/**************/
+
+#ifdef NO_UID_GID
+#  ifdef UID_USHORT
+     typedef unsigned short  uid_t;    /* TI SysV.3 */
+     typedef unsigned short  gid_t;
+#  else
+     typedef unsigned int    uid_t;    /* SCO Xenix */
+     typedef unsigned int    gid_t;
+#  endif
+#endif
+
+#if (defined(WIN32) || defined(sgi) || defined(GOT_UTIMBUF) || defined(ATARI))
+   typedef struct utimbuf ztimbuf;
+#else
+   typedef struct ztimbuf {
+       time_t actime;        /* new access time */
+       time_t modtime;       /* new modification time */
+   } ztimbuf;
+#endif
+
+typedef struct iztimes {
+   time_t atime;             /* new access time */
+   time_t mtime;             /* new modification time */
+   time_t ctime;             /* used for creation time; NOT same as st_ctime */
+} iztimes;
+
+#ifdef SET_DIR_ATTRIB
+   typedef struct dirtime {  /* temporary struct for holding directory info */
+       struct dirtime *next; /*  until can be sorted and set at end */
+       char *fn;             /* filename of directory */
+       union {
+           iztimes t3;       /* mtime, atime, ctime */
+           ztimbuf t2;       /* modtime, actime */
+       } u;
+       unsigned perms;       /* same as min_info.file_attr */
+       int have_uidgid;      /* flag */
+       ush uidgid[2];
+   } dirtime;
+#endif /* SET_DIR_ATTRIB */
+
+typedef struct min_info {
+    long offset;
+    ulg crc;                 /* crc (needed if extended header) */
+    ulg compr_size;          /* compressed size (needed if extended header) */
+    ulg uncompr_size;        /* uncompressed size (needed if extended header) */
+    int hostnum;
+    unsigned file_attr;      /* local flavor, as used by creat(), chmod()... */
+    unsigned encrypted : 1;  /* file encrypted: decrypt before uncompressing */
+    unsigned ExtLocHdr : 1;  /* use time instead of CRC for decrypt check */
+    unsigned textfile : 1;   /* file is text (according to zip) */
+    unsigned textmode : 1;   /* file is to be extracted as text */
+    unsigned lcflag : 1;     /* convert filename to lowercase */
+    unsigned vollabel : 1;   /* "file" is an MS-DOS volume (disk) label */
+} min_info;
+
+typedef struct VMStimbuf {
+    char *revdate;    /* (both roughly correspond to Unix modtime/st_mtime) */
+    char *credate;
+} VMStimbuf;
+
+/*---------------------------------------------------------------------------
+    Zipfile work area declarations.
+  ---------------------------------------------------------------------------*/
+
+#ifdef MALLOC_WORK
+   union work {
+     struct {                 /* unshrink(): */
+       shrint *Parent;          /* (8193 * sizeof(shrint)) */
+       uch *value;
+       uch *Stack;
+     } shrink;
+     uch *Slide;              /* explode(), inflate(), unreduce() */
+   };
+#else /* !MALLOC_WORK */
+   union work {
+     struct {                 /* unshrink(): */
+       shrint Parent[HSIZE];    /* (8192 * sizeof(shrint)) == 16KB minimum */
+       uch value[HSIZE];        /* 8KB */
+       uch Stack[HSIZE];        /* 8KB */
+     } shrink;                  /* total = 32KB minimum; 80KB on Cray/Alpha */
+     uch Slide[WSIZE];        /* explode(), inflate(), unreduce() */
+   };
+#endif /* ?MALLOC_WORK */
+
+#define slide  G.area.Slide
+
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+#  define redirSlide G.redirect_sldptr
+#else
+#  define redirSlide G.area.Slide
+#endif
+
+/*---------------------------------------------------------------------------
+    Zipfile layout declarations.  If these headers ever change, make sure the
+    xxREC_SIZE defines (above) change with them!
+  ---------------------------------------------------------------------------*/
+
+   typedef uch   local_byte_hdr[ LREC_SIZE ];
+#      define L_VERSION_NEEDED_TO_EXTRACT_0     0
+#      define L_VERSION_NEEDED_TO_EXTRACT_1     1
+#      define L_GENERAL_PURPOSE_BIT_FLAG        2
+#      define L_COMPRESSION_METHOD              4
+#      define L_LAST_MOD_DOS_DATETIME           6
+#      define L_CRC32                           10
+#      define L_COMPRESSED_SIZE                 14
+#      define L_UNCOMPRESSED_SIZE               18
+#      define L_FILENAME_LENGTH                 22
+#      define L_EXTRA_FIELD_LENGTH              24
+
+   typedef uch   cdir_byte_hdr[ CREC_SIZE ];
+#      define C_VERSION_MADE_BY_0               0
+#      define C_VERSION_MADE_BY_1               1
+#      define C_VERSION_NEEDED_TO_EXTRACT_0     2
+#      define C_VERSION_NEEDED_TO_EXTRACT_1     3
+#      define C_GENERAL_PURPOSE_BIT_FLAG        4
+#      define C_COMPRESSION_METHOD              6
+#      define C_LAST_MOD_DOS_DATETIME           8
+#      define C_CRC32                           12
+#      define C_COMPRESSED_SIZE                 16
+#      define C_UNCOMPRESSED_SIZE               20
+#      define C_FILENAME_LENGTH                 24
+#      define C_EXTRA_FIELD_LENGTH              26
+#      define C_FILE_COMMENT_LENGTH             28
+#      define C_DISK_NUMBER_START               30
+#      define C_INTERNAL_FILE_ATTRIBUTES        32
+#      define C_EXTERNAL_FILE_ATTRIBUTES        34
+#      define C_RELATIVE_OFFSET_LOCAL_HEADER    38
+
+   typedef uch   ec_byte_rec[ ECREC_SIZE+4 ];
+/*     define SIGNATURE                         0   space-holder only */
+#      define NUMBER_THIS_DISK                  4
+#      define NUM_DISK_WITH_START_CENTRAL_DIR   6
+#      define NUM_ENTRIES_CENTRL_DIR_THS_DISK   8
+#      define TOTAL_ENTRIES_CENTRAL_DIR         10
+#      define SIZE_CENTRAL_DIRECTORY            12
+#      define OFFSET_START_CENTRAL_DIRECTORY    16
+#      define ZIPFILE_COMMENT_LENGTH            20
+
+
+   typedef struct local_file_header {                 /* LOCAL */
+       uch version_needed_to_extract[2];
+       ush general_purpose_bit_flag;
+       ush compression_method;
+       ulg last_mod_dos_datetime;
+       ulg crc32;
+       ulg csize;
+       ulg ucsize;
+       ush filename_length;
+       ush extra_field_length;
+   } local_file_hdr;
+
+#if 0
+   typedef struct central_directory_file_header {     /* CENTRAL */
+       uch version_made_by[2];
+       uch version_needed_to_extract[2];
+       ush general_purpose_bit_flag;
+       ush compression_method;
+       ulg last_mod_dos_datetime;
+       ulg crc32;
+       ulg csize;
+       ulg ucsize;
+       ush filename_length;
+       ush extra_field_length;
+       ush file_comment_length;
+       ush disk_number_start;
+       ush internal_file_attributes;
+       ulg external_file_attributes;
+       ulg relative_offset_local_header;
+   } cdir_file_hdr;
+#endif /* 0 */
+
+   typedef struct end_central_dir_record {            /* END CENTRAL */
+       ush number_this_disk;
+       ush num_disk_start_cdir;
+       ush num_entries_centrl_dir_ths_disk;
+       ush total_entries_central_dir;
+       ulg size_central_directory;
+       ulg offset_start_central_directory;
+       ush zipfile_comment_length;
+   } ecdir_rec;
+
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+   that have 16-bit pointers (e.g. PC's in the small or medium model).
+   Valid extra bits are 0..13.  e == 15 is EOB (end of block), e == 16
+   means that v is a literal, 16 < e < 32 means that v is a pointer to
+   the next table, which codes e - 16 bits, and lastly e == 99 indicates
+   an unused code.  If a code with e == 99 is looked up, this implies an
+   error in the data. */
+
+struct huft {
+    uch e;                /* number of extra bits or operation */
+    uch b;                /* number of bits in this code or subcode */
+    union {
+        ush n;            /* literal, length base, or distance base */
+        struct huft *t;   /* pointer to next level of table */
+    } v;
+};
+
+
+typedef struct _APIDocStruct {
+    char *compare;
+    char *function;
+    char *syntax;
+    char *purpose;
+} APIDocStruct;
+
+
+
+
+/*************/
+/*  Globals  */
+/*************/
+
+#if (defined(OS2) && !defined(FUNZIP))
+#  include "os2/os2data.h"
+#endif
+
+#include "globals.h"
+
+
+
+/*************************/
+/*  Function Prototypes  */
+/*************************/
+
+/*---------------------------------------------------------------------------
+    Functions in unzip.c (initialization routines):
+  ---------------------------------------------------------------------------*/
+
+#ifndef WINDLL
+   int    MAIN                   OF((int argc, char **argv));
+   int    unzip                  OF((__GPRO__ int argc, char **argv));
+   int    uz_opts                OF((__GPRO__ int *pargc, char ***pargv));
+   int    usage                  OF((__GPRO__ int error));
+#endif /* !WINDLL */
+
+/*---------------------------------------------------------------------------
+    Functions in process.c (main driver routines):
+  ---------------------------------------------------------------------------*/
+
+int      process_zipfiles        OF((__GPRO));
+void     free_G_buffers          OF((__GPRO));
+/* static int    do_seekable     OF((__GPRO__ int lastchance)); */
+/* static int    find_ecrec      OF((__GPRO__ long searchlen)); */
+int      uz_end_central          OF((__GPRO));
+int      process_cdir_file_hdr   OF((__GPRO));
+int      get_cdir_ent            OF((__GPRO));
+int      process_local_file_hdr  OF((__GPRO));
+unsigned ef_scan_for_izux        OF((uch *ef_buf, unsigned ef_len, int ef_is_c,
+                                     ulg dos_mdatetime,
+                                     iztimes *z_utim, ush *z_uidgid));
+
+#ifndef SFX
+
+/*---------------------------------------------------------------------------
+    Functions in zipinfo.c (`zipinfo-style' listing routines):
+  ---------------------------------------------------------------------------*/
+
+#ifndef NO_ZIPINFO
+#ifndef WINDLL
+   int   zi_opts                 OF((__GPRO__ int *pargc, char ***pargv));
+#endif
+int      zi_end_central          OF((__GPRO));
+int      zipinfo                 OF((__GPRO));
+/* static int      zi_long       OF((__GPRO__ ulg *pEndprev)); */
+/* static int      zi_short      OF((__GPRO)); */
+/* static char    *zi_time       OF((__GPRO__ ZCONST ulg *datetimez,
+                                     ZCONST time_t *modtimez, char *d_t_str));*/
+#endif /* !NO_ZIPINFO */
+
+/*---------------------------------------------------------------------------
+    Functions in list.c (generic zipfile-listing routines):
+  ---------------------------------------------------------------------------*/
+
+int      list_files              OF((__GPRO));
+#ifdef TIMESTAMP
+   int   get_time_stamp          OF((__GPRO__  time_t *last_modtime,
+                                     unsigned *nmember));
+#endif
+int      ratio                   OF((ulg uc, ulg c));
+void     fnprint                 OF((__GPRO));
+
+#endif /* !SFX */
+
+/*---------------------------------------------------------------------------
+    Functions in fileio.c:
+  ---------------------------------------------------------------------------*/
+
+int      open_input_file      OF((__GPRO));
+int      open_outfile         OF((__GPRO));                    /* also vms.c */
+void     undefer_input        OF((__GPRO));
+void     defer_leftover_input OF((__GPRO));
+unsigned readbuf              OF((__GPRO__ char *buf, register unsigned len));
+int      readbyte             OF((__GPRO));
+int      fillinbuf            OF((__GPRO));
+#ifdef FUNZIP
+   int   flush                OF((__GPRO__ ulg size));  /* actually funzip.c */
+#else
+   int   flush                OF((__GPRO__ uch *buf, ulg size, int unshrink));
+#endif
+/* static int  disk_error     OF((__GPRO)); */
+void     handler              OF((int signal));
+time_t   dos_to_unix_time     OF((ulg dos_datetime));
+int      check_for_newer      OF((__GPRO__ char *filename)); /* os2,vmcms,vms */
+int      do_string            OF((__GPRO__ unsigned int len, int option));
+ush      makeword             OF((ZCONST uch *b));
+ulg      makelong             OF((ZCONST uch *sig));
+#if (!defined(STR_TO_ISO) || defined(NEED_STR2ISO))
+   char *str2iso              OF((char *dst, ZCONST char *src));
+#endif
+#if (!defined(STR_TO_OEM) || defined(NEED_STR2OEM))
+   char *str2oem              OF((char *dst, ZCONST char *src));
+#endif
+int      zstrnicmp            OF((register ZCONST char *s1,
+                                  register ZCONST char *s2,
+                                  register unsigned n));
+#ifdef REGULUS
+   int zstat                  OF((char *p, struct stat *s));
+#endif
+#ifdef ZMEM   /* MUST be ifdef'd because of conflicts with the standard def. */
+   zvoid *memset OF((register zvoid *, register int, register unsigned int));
+   int    memcmp OF((register ZCONST zvoid*, register ZCONST zvoid *,
+                     register unsigned int));
+   zvoid *memcpy OF((register zvoid *, register ZCONST zvoid *,
+                     register unsigned int));
+#endif
+#ifdef SMALL_MEM
+   char *fLoadFarString       OF((__GPRO__ const char Far *sz));
+   char *fLoadFarStringSmall  OF((__GPRO__ const char Far *sz));
+   char *fLoadFarStringSmall2 OF((__GPRO__ const char Far *sz));
+   #ifndef zfstrcpy
+     char Far * Far zfstrcpy  OF((char Far *s1, const char Far *s2));
+   #endif
+#endif
+
+
+/*---------------------------------------------------------------------------
+    Functions in extract.c:
+  ---------------------------------------------------------------------------*/
+
+int    extract_or_test_files     OF((__GPRO));
+/* static int   store_info          OF((void)); */
+/* static int   extract_or_test_member   OF((__GPRO)); */
+/* static int   TestExtraField   OF((__GPRO__ uch *ef, unsigned ef_len)); */
+/* static int   test_OS2         OF((__GPRO__ uch *eb, unsigned eb_size)); */
+/* static int   test_NT          OF((__GPRO__ uch *eb, unsigned eb_size)); */
+int    memextract                OF((__GPRO__ uch *tgt, ulg tgtsize,
+                                     uch *src, ulg srcsize));
+int    memflush                  OF((__GPRO__ uch *rawbuf, ulg size));
+char  *fnfilter                  OF((ZCONST char *raw, uch *space));
+
+/*---------------------------------------------------------------------------
+    Decompression functions:
+  ---------------------------------------------------------------------------*/
+
+#if (!defined(SFX) && !defined(FUNZIP))
+int    explode                   OF((__GPRO));                  /* explode.c */
+#endif
+int    huft_free                 OF((struct huft *t));          /* inflate.c */
+int    huft_build                OF((__GPRO__ ZCONST unsigned *b, unsigned n,
+                                     unsigned s, ZCONST ush *d, ZCONST ush *e,
+                                     struct huft **t, int *m));
+#ifdef USE_ZLIB
+   int    UZinflate              OF((__GPRO));                  /* inflate.c */
+#  define inflate_free(x)        inflateEnd(&((Uz_Globs *)(&G))->dstrm)
+#else
+   int    inflate                OF((__GPRO));                  /* inflate.c */
+   int    inflate_free           OF((__GPRO));                  /* inflate.c */
+#endif /* ?USE_ZLIB */
+#if (!defined(SFX) && !defined(FUNZIP))
+void   unreduce                  OF((__GPRO));                 /* unreduce.c */
+/* static void  LoadFollowers    OF((__GPRO__ f_array *follower, uch *Slen));
+                                                                * unreduce.c */
+int    unshrink                  OF((__GPRO));                 /* unshrink.c */
+/* static void  partial_clear    OF((__GPRO));                  * unshrink.c */
+#endif /* !SFX && !FUNZIP */
+
+/*---------------------------------------------------------------------------
+    Internal API functions (only included in DLL versions):
+  ---------------------------------------------------------------------------*/
+
+#ifdef DLL
+   void     setFileNotFound       OF((__GPRO));                     /* api.c */
+   int      unzipToMemory         OF((__GPRO__ char *zip, char *file,
+                                      UzpBuffer *retstr));          /* api.c */
+   int      redirect_outfile      OF((__GPRO));                     /* api.c */
+   int      writeToMemory         OF((__GPRO__ uch *rawbuf, ulg size));
+   int      close_redirect        OF((__GPRO));                     /* api.c */
+   /* this obsolescent entry point kept for compatibility: */
+   int      UzpUnzip              OF((int argc, char **argv));/* use UzpMain */
+#ifdef OS2DLL
+   int      varmessage            OF((__GPRO__ uch *buf, ulg size));
+   int      varputchar            OF((__GPRO__ int c));         /* rexxapi.c */
+   int      finish_REXX_redirect  OF((__GPRO));                 /* rexxapi.c */
+#endif
+#ifdef API_DOC
+   void     APIhelp               OF((__GPRO__ int argc, char **argv));
+#endif                                                          /* apihelp.c */
+#endif /* DLL */
+
+/*---------------------------------------------------------------------------
+    Acorn RISC OS-only functions:
+  ---------------------------------------------------------------------------*/
+
+#ifdef RISCOS
+   int   isRISCOSexfield     OF((void *extra_field));             /* acorn.c */
+   void  setRISCOSexfield    OF((char *path, void *extra_field)); /* acorn.c */
+   void  printRISCOSexfield  OF((int isdir, void *extra_field));  /* acorn.c */
+#endif
+
+/*---------------------------------------------------------------------------
+    Human68K-only functions:
+  ---------------------------------------------------------------------------*/
+
+#ifdef __human68k__
+   void  InitTwentyOne       OF((void));
+#endif
+
+/*---------------------------------------------------------------------------
+    Macintosh-only functions:
+  ---------------------------------------------------------------------------*/
+
+#ifdef MACOS
+   void    screenOpen        OF((char *));                    /* macscreen.c */
+   void    screenControl     OF((char *, int));               /* macscreen.c */
+   void    screenDump        OF((char *, long));              /* macscreen.c */
+   void    screenUpdate      OF((WindowPtr));                 /* macscreen.c */
+   void    screenClose       OF((void));                      /* macscreen.c */
+   int     macgetch          OF((void));                      /* macscreen.c */
+
+   int     macmkdir     OF((char *));                               /* mac.c */
+   short   macopen      OF((char *, short));                        /* mac.c */
+   short   maccreat     OF((char *));                               /* mac.c */
+   short   macread      OF((short, char *, unsigned));              /* mac.c */
+   long    macwrite     OF((short, char *, unsigned));              /* mac.c */
+   short   macclose     OF((short));                                /* mac.c */
+   long    maclseek     OF((short, long, short));                   /* mac.c */
+   char   *macfgets     OF((char *, int, FILE *));                  /* mac.c */
+   int     macfprintf   OF((FILE *, char *, ...));                  /* mac.c */
+   int     macprintf    OF((char *, ...));                          /* mac.c */
+#endif
+
+/*---------------------------------------------------------------------------
+    MSDOS-only functions:
+  ---------------------------------------------------------------------------*/
+
+#if (defined(MSDOS) && (defined(__GO32__) || defined(__EMX__)))
+   unsigned _dos_getcountryinfo(void *);                          /* msdos.c */
+#if (!defined(__DJGPP__) || (__DJGPP__ < 2))
+   unsigned _dos_setftime(int, unsigned short, unsigned short);   /* msdos.c */
+   unsigned _dos_setfileattr(char *, unsigned);                   /* msdos.c */
+   unsigned _dos_creat(char *, unsigned, int *);                  /* msdos.c */
+   void _dos_getdrive(unsigned *);                                /* msdos.c */
+   unsigned _dos_close(int);                                      /* msdos.c */
+#endif /* !__DJGPP__ || (__DJGPP__ < 2) */
+#endif
+
+/*---------------------------------------------------------------------------
+    OS/2-only functions:
+  ---------------------------------------------------------------------------*/
+
+#ifdef OS2   /* GetFileTime conflicts with something in Win32 header files */
+#if (defined(REENTRANT) && defined(USETHREADID))
+   ulg   GetThreadId          OF((void));
+#endif
+   int   GetCountryInfo       OF((void));                           /* os2.c */
+   long  GetFileTime          OF((ZCONST char *name));              /* os2.c */
+/* static void  SetPathAttrTimes OF((__GPRO__ int flags, int dir));    os2.c */
+/* static int   SetEAs        OF((__GPRO__ const char *path,
+                                  void *eablock));                     os2.c */
+/* static int   SetACL        OF((__GPRO__ const char *path,
+                                  void *eablock));                     os2.c */
+/* static int   IsFileNameValid OF((const char *name));                os2.c */
+/* static void  map2fat       OF((char *pathcomp, char **pEndFAT));    os2.c */
+/* static int   SetLongNameEA OF((char *name, char *longname));        os2.c */
+/* static void  InitNLS       OF((void));                              os2.c */
+   int   IsUpperNLS           OF((int nChr));                       /* os2.c */
+   int   ToLowerNLS           OF((int nChr));                       /* os2.c */
+   void  DebugMalloc          OF((void));                           /* os2.c */
+#endif
+
+/*---------------------------------------------------------------------------
+    QDOS-only functions:
+  ---------------------------------------------------------------------------*/
+
+#ifdef QDOS
+   int    QMatch              (uch, uch);
+   void   QFilename           (__GPRO__ char *);
+   char  *Qstrfix             (char *);
+   int    QReturn             (int zip_error);
+#endif
+
+/*---------------------------------------------------------------------------
+    TOPS20-only functions:
+  ---------------------------------------------------------------------------*/
+
+#ifdef TOPS20
+   int    upper               OF((char *s));                     /* tops20.c */
+   int    enquote             OF((char *s));                     /* tops20.c */
+   int    dequote             OF((char *s));                     /* tops20.c */
+   int    fnlegal             OF(()); /* error if prototyped? */ /* tops20.c */
+#endif
+
+/*---------------------------------------------------------------------------
+    VM/CMS- and MVS-only functions:
+  ---------------------------------------------------------------------------*/
+
+#ifdef CMS_MVS
+   extent getVMMVSexfield     OF((char *type, uch *ef_block, unsigned datalen));
+   FILE  *vmmvs_open_infile   OF((__GPRO));                       /* vmmvs.c */
+   void   close_infile        OF((__GPRO));                       /* vmmvs.c */
+#endif
+
+/*---------------------------------------------------------------------------
+    VMS-only functions:
+  ---------------------------------------------------------------------------*/
+
+#ifdef VMS
+   int    check_format        OF((__GPRO));                         /* vms.c */
+/* int    open_outfile        OF((__GPRO));           * (see fileio.c) vms.c */
+/* int    flush               OF((__GPRO__ uch *rawbuf, unsigned size,
+                                  int final_flag));   * (see fileio.c) vms.c */
+#ifdef RETURN_CODES
+   void   return_VMS          OF((__GPRO__ int zip_error));         /* vms.c */
+#else
+   void   return_VMS          OF((int zip_error));                  /* vms.c */
+#endif
+#ifdef VMSCLI
+   ulg    vms_unzip_cmdline   OF((int *, char ***));            /* cmdline.c */
+   int    VMSCLI_usage        OF((__GPRO__ int error));         /* cmdline.c */
+#endif
+#endif
+
+/*---------------------------------------------------------------------------
+    WIN32-only functions:
+  ---------------------------------------------------------------------------*/
+
+#ifdef WIN32
+   int   IsWinNT        OF((void));                               /* win32.c */
+#ifdef NTSD_EAS
+   void  process_defer_NT     OF((__GPRO));                       /* win32.c */
+   int   test_NTSD      OF((__GPRO__ uch *eb, unsigned eb_size,
+                            uch *eb_ucptr, ulg eb_ucsize));       /* win32.c */
+#  define TEST_NTSD     test_NTSD
+#endif
+#ifdef W32_STAT_BANDAID
+   int   zstat_win32    OF((__W32STAT_GLOBALS__
+                            const char *path, struct stat *buf)); /* win32.c */
+#endif
+#endif
+
+/*---------------------------------------------------------------------------
+    Miscellaneous/shared functions:
+  ---------------------------------------------------------------------------*/
+
+Uz_Globs *globalsCtor    OF((void));                            /* globals.c */
+
+void     envargs         OF((__GPRO__ int *Pargc, char ***Pargv,
+                             ZCONST char *envstr, ZCONST char *envstr2));
+                                                                /* envargs.c */
+void     mksargs         OF((int *argcp, char ***argvp));       /* envargs.c */
+
+int      match           OF((ZCONST char *s, ZCONST char *p,
+                             int ic));                            /* match.c */
+int      iswild          OF((ZCONST char *p));                    /* match.c */
+
+#ifdef DYNALLOC_CRCTAB
+   void     free_crc_table  OF((void));                          /* crctab.c */
+#endif
+#ifndef USE_ZLIB
+   ZCONST ulg near *get_crc_table  OF((void));         /* funzip.c, crctab.c */
+   ulg      crc32           OF((ulg crc, ZCONST uch *buf, extent len));
+#endif /* !USE_ZLIB */                        /* assembler source or crc32.c */
+
+int      dateformat      OF((void));              /* currently, only msdos.c */
+#ifndef WINDLL
+   void  version         OF((__GPRO));                              /* local */
+#endif
+int      mapattr         OF((__GPRO));                              /* local */
+int      mapname         OF((__GPRO__ int renamed));                /* local */
+int      checkdir        OF((__GPRO__ char *pathcomp, int flag));   /* local */
+char    *do_wild         OF((__GPRO__ char *wildzipfn));            /* local */
+char    *GetLoadPath     OF((__GPRO));                              /* local */
+#if (defined(MORE) && (defined(UNIX) || defined(VMS) || defined(__BEOS__)))
+   int screenlines       OF((void));                                /* local */
+#endif
+#ifndef MTS /* macro in MTS */
+   void  close_outfile   OF((__GPRO));                              /* local */
+#endif
+#ifdef SET_DIR_ATTRIB
+   int   set_direc_attribs  OF((__GPRO__ dirtime *d));              /* local */
+#endif
+#ifdef TIMESTAMP
+# ifdef WIN32
+   int   stamp_file      OF((__GPRO__
+                             ZCONST char *fname, time_t modtime));  /* local */
+# else
+   int   stamp_file      OF((ZCONST char *fname, time_t modtime));  /* local */
+# endif
+#endif
+#ifdef SYSTEM_SPECIFIC_CTOR
+   void  SYSTEM_SPECIFIC_CTOR   OF((__GPRO));                       /* local */
+#endif
+
+
+
+
+
+/************/
+/*  Macros  */
+/************/
+
+#ifndef MAX
+#  define MAX(a,b)   ((a) > (b) ? (a) : (b))
+#endif
+#ifndef MIN
+#  define MIN(a,b)   ((a) < (b) ? (a) : (b))
+#endif
+
+#ifdef DEBUG
+#  define Trace(x)   fprintf x
+#else
+#  define Trace(x)
+#endif
+
+#ifdef DEBUG_TIME
+#  define TTrace(x)  fprintf x
+#else
+#  define TTrace(x)
+#endif
+
+#ifdef NO_DEBUG_IN_MACROS
+#  define MTrace(x)
+#else
+#  define MTrace(x)  Trace(x)
+#endif
+
+#if (defined(UNIX) || defined(T20_VMS)) /* generally old systems */
+#  define ToLower(x)   ((char)(isupper((int)x)? tolower((int)x) : x))
+#else
+#  define ToLower      tolower          /* assumed "smart"; used in match() */
+#endif
+
+#ifdef USE_STRM_INPUT
+   /* ``Replace'' the unbuffered UNIX style I/O function with similar
+    * standard C functions from <stdio.h>.
+    */
+#  define read(fd,buf,n) fread((buf),1,(n),(FILE *)(fd))
+#  define lseek(fd,o,w) fseek((FILE *)(fd),(o),(w))
+#  define close(fd) fclose((FILE *)(fd))
+#endif /* USE_STRM_INPUT */
+
+/* The return value of the Info() "macro function" is never checked in
+ * UnZip. Otherwise, to get the same behaviour as for (*G.message)(), the
+ * Info() definition for "FUNZIP" would have to be corrected:
+ * #define Info(buf,flag,sprf_arg) \
+ *      (fprintf((flag)&1? stderr : stdout, \
+ *               (char *)(sprintf sprf_arg, (buf))) == EOF)
+ */
+#ifndef Info   /* may already have been defined for redirection */
+#  ifdef FUNZIP
+#    define Info(buf,flag,sprf_arg) \
+     fprintf((flag)&1? stderr : stdout, (char *)(sprintf sprf_arg, (buf)))
+#  else
+#    ifdef INT_SPRINTF  /* optimized version for "int sprintf()" flavour */
+#      define Info(buf,flag,sprf_arg) \
+       (*G.message)((zvoid *)&G, (uch *)(buf), (ulg)sprintf sprf_arg, (flag))
+#    else          /* generic version, does not use sprintf() return value */
+#      define Info(buf,flag,sprf_arg) \
+       (*G.message)((zvoid *)&G, (uch *)(buf), \
+                     (ulg)(sprintf sprf_arg, strlen((char *)(buf))), (flag))
+#    endif
+#  endif
+#endif /* !Info */
+
+#undef Info
+#define Info(buf,flag,sprf_arg)  (0)
+
+/*  The following macros wrappers around the fnfilter function are used many
+ *  times to prepare archive entry names or name components for displaying
+ *  listings and (warning/error) messages. They use sections in the upper half
+ *  of 'slide' as buffer, since their output is normally fed through the
+ *  Info() macro with 'slide' (the start of this area) as message buffer.
+ */
+#define FnFilter1(fname)  fnfilter((fname), slide + (WSIZE>>1))
+#define FnFilter2(fname)  fnfilter((fname), slide + ((WSIZE>>1) + (WSIZE>>2)))
+
+#ifndef FUNZIP   /* used only in inflate.c */
+#  define MESSAGE(str,len,flag)  (*G.message)((zvoid *)&G,(str),(len),(flag))
+#endif
+
+#if 0            /* Optimization: use the (const) result of crc32(0L,NULL,0) */
+#  define CRCVAL_INITIAL  crc32(0L, NULL, 0)
+#else
+#  define CRCVAL_INITIAL  0L
+#endif
+
+#ifndef TEST_NTSD               /* "NTSD valid?" checking function */
+#  define TEST_NTSD     NULL    /*   ... is not available */
+#endif
+
+/*
+ *  Seek to the block boundary of the block which includes abs_offset,
+ *  then read block into input buffer and set pointers appropriately.
+ *  If block is already in the buffer, just set the pointers.  This macro
+ *  is used by uz_end_central (process.c), zi_end_central (zipinfo.c) and
+ *  do_string (fileio.c).  A slightly modified version is embedded within
+ *  extract_or_test_files (extract.c).  readbyte() and readbuf() (fileio.c)
+ *  are compatible.  NOTE THAT abs_offset is intended to be the "proper off-
+ *  set" (i.e., if there were no extra bytes prepended); cur_zipfile_bufstart
+ *  contains the corrected offset.
+ *
+ *  Since ZLSEEK is never used during decompression, it is safe to use the
+ *  slide[] buffer for the error message.
+ *
+ *  The awkward "%cbs_offset" construct is provided for the obnoxious Solaris
+ *  compiler, which wants to do macro substitution inside strings.
+ */
+
+#ifndef ZLSEEK
+#  ifdef USE_STRM_INPUT
+#    define _ZLS_RELOAD(abs_offset) {\
+         MTrace((stderr, "ZLSEEK: %cbs_offset = %ld, G.extra_bytes = %ld\n",\
+           'a', (abs_offset), G.extra_bytes));\
+         fseek(G.zipfd,(LONGINT)bufstart,SEEK_SET);\
+         G.cur_zipfile_bufstart = ftell(G.zipfd);\
+         MTrace((stderr,\
+           "       request = %ld, (abs+extra) = %ld, inbuf_offset = %ld\n",\
+           request, ((abs_offset)+G.extra_bytes), inbuf_offset));\
+         MTrace((stderr, "       bufstart = %ld, cur_zipfile_bufstart = %ld\n",\
+           bufstart, G.cur_zipfile_bufstart));\
+         if ((G.incnt = fread((char *)G.inbuf,1,INBUFSIZ,G.zipfd)) <= 0)\
+             return(PK_EOF);\
+         G.inptr = G.inbuf + (int)inbuf_offset;\
+         G.incnt -= (int)inbuf_offset;\
+     }
+#  else /* !USE_STRM_INPUT */
+#    define _ZLS_RELOAD(abs_offset) {\
+         MTrace((stderr, "ZLSEEK: %cbs_offset = %ld, G.extra_bytes = %ld\n",\
+           'a', (abs_offset), G.extra_bytes));\
+         G.cur_zipfile_bufstart = lseek(G.zipfd,(LONGINT)bufstart,SEEK_SET);\
+         MTrace((stderr,\
+           "       request = %ld, (abs+extra) = %ld, inbuf_offset = %ld\n",\
+           request, ((abs_offset)+G.extra_bytes), inbuf_offset));\
+         MTrace((stderr, "       bufstart = %ld, cur_zipfile_bufstart = %ld\n",\
+           bufstart, G.cur_zipfile_bufstart));\
+         if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ)) <= 0)\
+             return(PK_EOF);\
+         G.inptr = G.inbuf + (int)inbuf_offset;\
+         G.incnt -= (int)inbuf_offset;\
+     }
+#  endif /* ?USE_STRM_INPUT */
+
+#  define ZLSEEK(abs_offset) {\
+       LONGINT request = (abs_offset) + G.extra_bytes;\
+       LONGINT inbuf_offset = request % INBUFSIZ;\
+       LONGINT bufstart = request - inbuf_offset;\
+\
+       if (request < 0) {\
+           Info(slide, 1, ((char *)slide, LoadFarStringSmall(SeekMsg),\
+             G.zipfn, LoadFarString(ReportMsg)));\
+           return(PK_BADERR);\
+       } else if (bufstart != G.cur_zipfile_bufstart)\
+           _ZLS_RELOAD(abs_offset)\
+       else {\
+           G.incnt += (G.inptr-G.inbuf) - (int)inbuf_offset;\
+           G.inptr = G.inbuf + (int)inbuf_offset;\
+       }\
+   }
+#endif /* !ZLSEEK */
+
+#define SKIP_(length) if(length&&((error=do_string(__G__ length,SKIP))!=0))\
+  {error_in_archive=error; if(error>1) return error;}
+
+/*
+ *  Skip a variable-length field, and report any errors.  Used in zipinfo.c
+ *  and unzip.c in several functions.
+ *
+ *  macro SKIP_(length)
+ *      ush length;
+ *  {
+ *      if (length && ((error = do_string(length, SKIP)) != 0)) {
+ *          error_in_archive = error;   /-* might be warning *-/
+ *          if (error > 1)              /-* fatal *-/
+ *              return (error);
+ *      }
+ *  }
+ *
+ */
+
+
+#ifdef FUNZIP
+#  define FLUSH(w)  flush(__G__ (ulg)(w))
+#  define NEXTBYTE  getc(G.in)   /* redefined in crypt.h if full version */
+#else
+#  define FLUSH(w)  if (G.mem_mode) memflush(__G__ redirSlide,(ulg)(w)); \
+     else flush(__G__ redirSlide,(ulg)(w),0)
+#  define NEXTBYTE  (--G.incnt >= 0 ? (int)(*G.inptr++) : readbyte(__G))
+#endif
+
+
+#define READBITS(nbits,zdest) {if(nbits>G.bits_left) {int temp; G.zipeof=1;\
+  while (G.bits_left<=8*(int)(sizeof(G.bitbuf)-1) && (temp=NEXTBYTE)!=EOF) {\
+  G.bitbuf|=(ulg)temp<<G.bits_left; G.bits_left+=8; G.zipeof=0;}}\
+  zdest=(shrint)((ush)G.bitbuf&mask_bits[nbits]);G.bitbuf>>=nbits;\
+  G.bits_left-=nbits;}
+
+/*
+ * macro READBITS(nbits,zdest)    * only used by unreduce and unshrink *
+ *  {
+ *      if (nbits > G.bits_left) {  * fill G.bitbuf, 8*sizeof(ulg) bits *
+ *          int temp;
+ *
+ *          G.zipeof = 1;
+ *          while (G.bits_left <= 8*(int)(sizeof(G.bitbuf)-1) &&
+ *                 (temp = NEXTBYTE) != EOF) {
+ *              G.bitbuf |= (ulg)temp << G.bits_left;
+ *              G.bits_left += 8;
+ *              G.zipeof = 0;
+ *          }
+ *      }
+ *      zdest = (shrint)((ush)G.bitbuf & mask_bits[nbits]);
+ *      G.bitbuf >>= nbits;
+ *      G.bits_left -= nbits;
+ *  }
+ *
+ */
+
+
+/* GRR:  should change name to STRLOWER and use StringLower if possible */
+
+/*
+ *  Copy the zero-terminated string in str1 into str2, converting any
+ *  uppercase letters to lowercase as we go.  str2 gets zero-terminated
+ *  as well, of course.  str1 and str2 may be the same character array.
+ */
+#ifdef __human68k__
+#  define TOLOWER(str1, str2) \
+   { \
+       char *p=(str1), *q=(str2); \
+       uch c; \
+       while ((c = *p++) != '\0') { \
+           if (iskanji(c)) { \
+               if (*p == '\0') \
+                   break; \
+               *q++ = c; \
+               *q++ = *p++; \
+           } else \
+               *q++ = isupper(c) ? tolower(c) : c; \
+       } \
+       *q = '\0'; \
+   }
+#else
+#  define TOLOWER(str1, str2) \
+   { \
+       char  *p, *q; \
+       p = (str1) - 1; \
+       q = (str2); \
+       while (*++p) \
+           *q++ = (char)(isupper((int)(*p))? tolower((int)(*p)) : *p); \
+       *q = '\0'; \
+   }
+#endif
+/*
+ *  NOTES:  This macro makes no assumptions about the characteristics of
+ *    the tolower() function or macro (beyond its existence), nor does it
+ *    make assumptions about the structure of the character set (i.e., it
+ *    should work on EBCDIC machines, too).  The fact that either or both
+ *    of isupper() and tolower() may be macros has been taken into account;
+ *    watch out for "side effects" (in the C sense) when modifying this
+ *    macro.
+ */
+
+#ifndef foreign
+#  define foreign(c)  (c)
+#endif
+
+#ifndef native
+#  define native(c)   (c)
+#  define A_TO_N(str1)
+#else
+#  ifndef NATIVE
+#    define NATIVE     "native chars"
+#  endif
+#  define A_TO_N(str1) {register uch *p;\
+     for (p=(uch *)(str1); *p; p++) *p=native(*p);}
+#endif
+/*
+ *  Translate the zero-terminated string in str1 from ASCII to the native
+ *  character set. The translation is performed in-place and uses the
+ *  "native" macro to translate each character.
+ *
+ *  NOTE:  Using the "native" macro means that is it the only part of unzip
+ *    which knows which translation table (if any) is actually in use to
+ *    produce the native character set.  This makes adding new character set
+ *    translation tables easy, insofar as all that is needed is an appropriate
+ *    "native" macro definition and the translation table itself.  Currently,
+ *    the only non-ASCII native character set implemented is EBCDIC, but this
+ *    may not always be so.
+ */
+
+
+/* default setup for internal codepage: assume ISO 8859-1 compatibility!! */
+#if (!defined(NATIVE) && !defined(CRTL_CP_IS_ISO) && !defined(CRTL_CP_IS_OEM))
+#  define CRTL_CP_IS_ISO
+#endif
+
+
+/*  Translate "extended ASCII" chars (OEM coding for DOS and OS/2; else
+ *  ISO-8859-1 [ISO Latin 1, Win Ansi,...]) into the internal "native"
+ *  code page.  As with A_TO_N(), conversion is done in place.
+ */
+#ifndef _ISO_INTERN
+#  ifdef CRTL_CP_IS_OEM
+#    ifndef IZ_ISO2OEM_ARRAY
+#      define IZ_ISO2OEM_ARRAY
+#    endif
+#    define _ISO_INTERN(str1) {register uch *p;\
+       for (p=(uch *)(str1); *p; p++)\
+         *p = native((*p & 0x80) ? iso2oem[*p & 0x7f] : *p);}
+#  else
+#    define _ISO_INTERN(str1)   A_TO_N(str1)
+#  endif
+#endif
+
+#ifndef _OEM_INTERN
+#  ifdef CRTL_CP_IS_OEM
+#    define _OEM_INTERN(str1)   A_TO_N(str1)
+#  else
+#    ifndef IZ_OEM2ISO_ARRAY
+#      define IZ_OEM2ISO_ARRAY
+#    endif
+#    define _OEM_INTERN(str1) {register uch *p;\
+       for (p=(uch *)(str1); *p; p++)\
+         *p = native((*p & 0x80) ? oem2iso[*p & 0x7f] : *p);}
+#  endif
+#endif
+
+#ifndef STR_TO_ISO
+#  ifdef CRTL_CP_IS_ISO
+#    define STR_TO_ISO          strcpy
+#  else
+#    define STR_TO_ISO          str2iso
+#    define NEED_STR2ISO
+#  endif
+#endif
+
+#ifndef STR_TO_OEM
+#  ifdef CRTL_CP_IS_OEM
+#    define STR_TO_OEM          strcpy
+#  else
+#    define STR_TO_OEM          str2oem
+#    define NEED_STR2OEM
+#  endif
+#endif
+
+#if (!defined(INTERN_TO_ISO) && !defined(ASCII2ISO))
+#  ifdef CRTL_CP_IS_OEM
+     /* know: "ASCII" is "OEM" */
+#    define ASCII2ISO(c) (((c) & 0x80) ? oem2iso[(c) & 0x7f] : (c))
+#    if (defined(NEED_STR2ISO) && !defined(CRYP_USES_OEM2ISO))
+#      define CRYP_USES_OEM2ISO
+#    endif
+#  else
+     /* assume: "ASCII" is "ISO-ANSI" */
+#    define ASCII2ISO(c) (c)
+#  endif
+#endif
+
+#if (!defined(INTERN_TO_OEM) && !defined(ASCII2OEM))
+#  ifdef CRTL_CP_IS_OEM
+     /* know: "ASCII" is "OEM" */
+#    define ASCII2OEM(c) (c)
+#  else
+     /* assume: "ASCII" is "ISO-ANSI" */
+#    define ASCII2OEM(c) (((c) & 0x80) ? iso2oem[(c) & 0x7f] : (c))
+#    if (defined(NEED_STR2OEM) && !defined(CRYP_USES_ISO2OEM))
+#      define CRYP_USES_ISO2OEM
+#    endif
+#  endif
+#endif
+
+/* codepage conversion setup for testp() in crypt.c */
+#ifdef CRTL_CP_IS_ISO
+#  ifndef STR_TO_CP2
+#    define STR_TO_CP2  STR_TO_OEM
+#  endif
+#else
+#  ifdef CRTL_CP_IS_OEM
+#    ifndef STR_TO_CP2
+#      define STR_TO_CP2  STR_TO_ISO
+#    endif
+#  else /* native internal CP is neither ISO nor OEM */
+#    ifndef STR_TO_CP1
+#      define STR_TO_CP1  STR_TO_ISO
+#    endif
+#    ifndef STR_TO_CP2
+#      define STR_TO_CP2  STR_TO_OEM
+#    endif
+#  endif
+#endif
+
+
+/* Convert filename (and file comment string) into "internal" charset.
+ * This macro assumes that Zip entry filenames are coded in OEM (IBM DOS)
+ * codepage when made on
+ *  -> DOS (this includes 16-bit Windows 3.1)  (FS_FAT_)
+ *  -> OS/2                                    (FS_HPFS_)
+ *  -> Win95/WinNT with Nico Mak's WinZip      (FS_NTFS_ && hostver == "5.0")
+ *
+ * All other ports are assumed to code zip entry filenames in ISO 8859-1.
+ */
+#ifndef Ext_ASCII_TO_Native
+#  define Ext_ASCII_TO_Native(string, hostnum, hostver) \
+    if ((hostnum) == FS_FAT_ || (hostnum) == FS_HPFS_ || \
+        ((hostnum) == FS_NTFS_ && (hostver) == 50)) { \
+        _OEM_INTERN((string)); \
+    } else { \
+        _ISO_INTERN((string)); \
+    }
+#endif
+
+
+
+/**********************/
+/*  Global constants  */
+/**********************/
+
+   extern ZCONST ush near  mask_bits[];
+   extern ZCONST char *fnames[2];
+
+#ifdef EBCDIC
+   extern ZCONST uch ebcdic[];
+#endif
+#ifdef IZ_ISO2OEM_ARRAY
+   extern ZCONST uch Far iso2oem[];
+#endif
+#ifdef IZ_OEM2ISO_ARRAY
+   extern ZCONST uch Far oem2iso[];
+#endif
+
+   extern ZCONST char Far  VersionDate[];
+   extern ZCONST char Far  CentSigMsg[];
+   extern ZCONST char Far  EndSigMsg[];
+   extern ZCONST char Far  SeekMsg[];
+   extern ZCONST char Far  FilenameNotMatched[];
+   extern ZCONST char Far  ExclFilenameNotMatched[];
+   extern ZCONST char Far  ReportMsg[];
+
+#ifndef SFX
+   extern ZCONST char Far  CompiledWith[];
+#endif /* !SFX */
+
+
+
+/***********************************/
+/*  Global (shared?) RTL variables */
+/***********************************/
+
+#ifdef DECLARE_ERRNO
+   extern int             errno;
+#endif
+
+
+#endif /* !__unzpriv_h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inczip/version.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,44 @@
+/*
+   version.h (for UnZip) by Info-ZIP.
+
+   This header file is not copyrighted and may be distributed without
+   restriction.  (That's a little geek humor, heh heh.)
+ */
+
+#ifndef __version_h     /* don't include more than once */
+#define __version_h
+
+#ifdef BETA
+#  undef BETA           /* define BETA for internal beta releases */
+#endif
+
+#ifdef BETA
+#  define BETALEVEL         "d BETA"
+#  define VERSION_DATE      "27 November 98"    /* internal beta version */
+#else
+#  define BETALEVEL         ""
+#  define VERSION_DATE      "28 November 1998"  /* official release version */
+#  define RELEASE
+#endif
+
+#define UZ_MAJORVER    5   /* UnZip */
+#define UZ_MINORVER    4
+
+#define ZI_MAJORVER    2   /* ZipInfo */
+#define ZI_MINORVER    3
+
+#define PATCHLEVEL     0
+
+
+/* these are obsolete but remain for backward compatibility: */
+#define D2_MAJORVER    UZ_MAJORVER   /* DLL for OS/2 */
+#define D2_MINORVER    UZ_MINORVER
+#define D2_PATCHLEVEL  PATCHLEVEL
+
+#define DW_MAJORVER    UZ_MAJORVER   /* DLL for MS Windows */
+#define DW_MINORVER    UZ_MINORVER
+#define DW_PATCHLEVEL  PATCHLEVEL
+
+#define WIN_VERSION_DATE  VERSION_DATE
+
+#endif /* !__version_h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inczip/w32cfg.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,222 @@
+/*---------------------------------------------------------------------------
+    Win32 specific configuration section:
+  ---------------------------------------------------------------------------*/
+
+#ifndef __w32cfg_h
+#define __w32cfg_h
+
+#if (defined(__CYGWIN__) && !defined(__CYGWIN32__))
+#  define __CYGWIN32__        /* new versions of CygWin may not define this */
+#endif
+
+#include <sys/types.h>        /* off_t, time_t, dev_t, ... */
+#include <sys/stat.h>
+#include <io.h>               /* read(), open(), etc. */
+#include <time.h>
+#if (defined(__RSXNT__) || defined(__EMX__)) && !defined(tzset)
+#  define tzset _tzset
+#endif
+#ifdef __MINGW32__
+   extern void _tzset(void);  /* this is missing in <time.h> */
+#  ifndef tzset
+#    define tzset _tzset
+#  endif
+#endif
+#include <memory.h>
+#if (!defined(__RSXNT__) && !defined(__CYGWIN32__))
+#  include <direct.h>         /* mkdir() */
+#endif
+#include <fcntl.h>
+#ifdef __CYGWIN32__
+#  include <unistd.h>
+   extern int setmode(int, int);        /* this is missing in <fcntl.h> */
+#endif
+#if (defined(MSC) || defined(__WATCOMC__) || defined(__MINGW32__))
+#  include <sys/utime.h>
+#else
+#  include <utime.h>
+#endif
+
+#if defined(FILEIO_C)
+#  ifndef __CYGWIN32__
+#    include <conio.h>
+#  endif
+#  include <windows.h>
+#  ifdef __RSXNT__
+#    include "win32/rsxntwin.h"
+#  endif
+#endif
+#if (defined(ENVARGS_C) || defined(EXTRACT_C) || defined(UNZIP_C) || \
+     defined(ZCRYPT_INTERNAL))
+#  include <windows.h>
+#  ifdef __RSXNT__
+#    include "win32/rsxntwin.h"
+#  endif
+#endif
+#if (defined(__CYGWIN32__) || defined(__MINGW32__))
+   /* the following definitions are missing in their <windows.h> */
+#  ifndef AnsiToOem
+#    define AnsiToOem CharToOemA
+#  endif
+#  ifndef OemToAnsi
+#    define OemToAnsi OemToCharA
+#  endif
+#endif
+
+#define DIR_END       '\\'      /* OS uses '\\' as directory separator */
+#define DIR_END2      '/'       /* also check for '/' (RTL may convert) */
+#ifndef DATE_FORMAT
+#  define DATE_FORMAT DF_MDY
+#endif
+#define lenEOL        2
+#define PutNativeEOL  {*q++ = native(CR); *q++ = native(LF);}
+
+#if (defined(__RSXNT__) && !defined(HAVE_MKTIME))
+#  define HAVE_MKTIME           /* use mktime() in time conversion routines */
+#endif
+#if (defined(__CYGWIN32__) && defined(HAVE_MKTIME))
+#  undef HAVE_MKTIME            /* Cygnus' mktime() implementation is buggy */
+#endif
+#if (!defined(NT_TZBUG_WORKAROUND) && !defined(NO_NT_TZBUG_WORKAROUND))
+#  define NT_TZBUG_WORKAROUND
+#endif
+#if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME))
+#  define USE_EF_UT_TIME
+#endif
+#if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))
+#  define TIMESTAMP
+#endif
+#if (!defined(NO_NTSD_EAS) && !defined(NTSD_EAS))
+#  define NTSD_EAS      /* enable NTSD support unless explicitly suppressed */
+#endif
+
+/* handlers for OEM <--> ANSI string conversions */
+#ifdef __RSXNT__
+   /* RSXNT uses OEM coded strings in functions supplied by C RTL */
+#  ifdef CRTL_CP_IS_ISO
+#    undef CRTL_CP_IS_ISO
+#  endif
+#  ifndef CRTL_CP_IS_OEM
+#    define CRTL_CP_IS_OEM
+#  endif
+#else
+   /* "real" native WIN32 compilers use ANSI coded strings in C RTL calls */
+#  ifndef CRTL_CP_IS_ISO
+#    define CRTL_CP_IS_ISO
+#  endif
+#  ifdef CRTL_CP_IS_OEM
+#    undef CRTL_CP_IS_OEM
+#  endif
+#endif
+
+#ifdef CRTL_CP_IS_ISO
+   /* C RTL's file system support assumes ANSI coded strings */
+#  define ISO_TO_INTERN(src, dst)  {if ((src) != (dst)) strcpy((dst), (src));}
+#  define OEM_TO_INTERN(src, dst)  OemToAnsi(src, dst)
+#  define INTERN_TO_ISO(src, dst)  {if ((src) != (dst)) strcpy((dst), (src));}
+#  define INTERN_TO_OEM(src, dst)  AnsiToOem(src, dst)
+#endif /* CRTL_CP_IS_ISO */
+#ifdef CRTL_CP_IS_OEM
+   /* C RTL's file system support assumes OEM coded strings */
+#  define ISO_TO_INTERN(src, dst)  AnsiToOem(src, dst)
+#  define OEM_TO_INTERN(src, dst)  {if ((src) != (dst)) strcpy((dst), (src));}
+#  define INTERN_TO_ISO(src, dst)  OemToAnsi(src, dst)
+#  define INTERN_TO_OEM(src, dst)  {if ((src) != (dst)) strcpy((dst), (src));}
+#endif /* CRTL_CP_IS_OEM */
+#define _OEM_INTERN(str1) OEM_TO_INTERN(str1, str1)
+#define _ISO_INTERN(str1) ISO_TO_INTERN(str1, str1)
+#ifndef WINDLL
+   /* Despite best intentions, for the command-line version UzpPassword()
+    * could return either character set, depending on whether running under
+    * Win95 (DOS-session) or WinNT (native WinNT command interpreter)! */
+#  define STR_TO_CP2(dst, src)  (AnsiToOem(src, dst), dst)
+#  define STR_TO_CP3(dst, src)  (OemToAnsi(src, dst), dst)
+#else
+   /* The WINDLL front end is known to supply ISO/ANSI-coded passwords! */
+#  define STR_TO_CP2(dst, src)  (AnsiToOem(src, dst), dst)
+#endif
+/* dummy defines to disable these functions, they are not needed */
+#define STR_TO_OEM
+#define STR_TO_ISO
+
+/* Static variables that we have to add to Uz_Globs: */
+#define SYSTEM_SPECIFIC_GLOBALS \
+    int created_dir, renamed_fullpath, fnlen;\
+    unsigned nLabelDrive;\
+    char lastRootPath[4];\
+    int lastVolOldFAT, lastVolLocTim;\
+    char *rootpath, *buildpathHPFS, *buildpathFAT, *endHPFS, *endFAT;\
+    char *dirname, *wildname, matchname[FILNAMSIZ];\
+    int rootlen, have_dirname, dirnamelen, notfirstcall;\
+    zvoid *wild_dir;
+
+/* created_dir, renamed_fullpath, fnlen, and nLabelDrive are used by   */
+/*    both mapname() and checkdir().                                   */
+/* lastRootPath and lastVolOldFAT are used by IsVolumeOldFAT().        */
+/* rootlen, rootpath, buildpathHPFS, buildpathFAT, endHPFS, and endFAT */
+/*    are used by checkdir().                                          */
+/* wild_dir, dirname, wildname, matchname[], dirnamelen, have_dirname, */
+/*    and notfirstcall are used by do_wild().                          */
+
+#if (defined(_MSC_VER) && !defined(MSC))
+#  define MSC
+#endif
+
+/* This replacement for C-RTL-supplied getch() (or similar) functionality
+ * avoids leaving unabsorbed LFs in the keyboard buffer under Windows95,
+ * and supports the <ALT>+[0]<digit><digit><digit> feature.
+ */
+int getch_win32  OF((void));
+
+/* This patch of stat() is useful for at least two compilers.  It is   */
+/* difficult to take a stat() of a root directory under Windows95, so  */
+/* zstat_win32() detects that case and fills in suitable values.       */
+#ifndef __RSXNT__
+#  ifndef W32_STATROOT_FIX
+#    define W32_STATROOT_FIX
+#  endif
+#endif /* !__RSXNT__ */
+
+#if (defined(NT_TZBUG_WORKAROUND) || defined(W32_STATROOT_FIX))
+#  define W32_STAT_BANDAID
+#  if (defined(NT_TZBUG_WORKAROUND) && defined(REENTRANT))
+#    define __W32STAT_GLOBALS__     Uz_Globs *pG,
+#    define __W32STAT_G__           pG,
+#  else
+#    define __W32STAT_GLOBALS__
+#    define __W32STAT_G__
+#  endif
+#  undef SSTAT
+#  ifdef WILD_STAT_BUG
+#    define SSTAT(path, pbuf) (iswild(path) || zstat_win32(__W32STAT_G__ path, pbuf))
+#  else
+#    define SSTAT(path, pbuf) zstat_win32(__W32STAT_G__ path, pbuf)
+#  endif
+#endif
+
+#ifdef __WATCOMC__
+#  ifdef __386__
+#    ifndef WATCOMC_386
+#      define WATCOMC_386
+#    endif
+#    define __32BIT__
+#    undef far
+#    define far
+#    undef near
+#    define near
+
+/* Get asm routines to link properly without using "__cdecl": */
+#    ifndef USE_ZLIB
+#      pragma aux crc32         "_*" parm caller [] value [eax] modify [eax]
+#      pragma aux get_crc_table "_*" parm caller [] value [eax] \
+                                      modify [eax ecx edx]
+#    endif /* !USE_ZLIB */
+#  endif /* __386__ */
+
+#  ifndef EPIPE
+#    define EPIPE -1
+#  endif
+#  define PIPE_ERROR (errno == EPIPE)
+#endif /* __WATCOMC__ */
+
+#endif /* !__w32cfg_h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inczip/zip.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,15 @@
+/* This is a dummy zip.h to allow the source files shared with Zip (crypt.c,
+   crc32.c, crctab.c, ttyio.c) to compile for UnZip.  */
+
+#ifndef __zip_h   /* don't include more than once */
+#define __zip_h
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+
+#define local static
+
+#define ZE_MEM         PK_MEM
+#define ziperr(c, h)   return
+
+#endif /* !__zip_h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,2014 @@
+/* $Id: install.c,v 1.48 2003/11/24 18:56:44 bsmith Exp $ */
+
+/*
+ *  install.c (c) 1998-2003 Brian Smith
+ *  parts by Daniele Vistalli
+ */
+
+#ifdef __OS2__
+#define INCL_RXFUNC
+#define INCL_RXMACRO
+#define INCL_RXARI
+#define INCL_RXSYSEXIT
+#define INCL_RXSUBCOM
+#define INCL_RXSHV
+#endif
+
+#ifdef __UNIX__
+#include "config.h"
+#else
+#include "platform/dirent.h"
+#endif
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <fcntl.h>
+#ifndef __UNIX__
+#include <process.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "dw.h"
+#include "compat.h"
+#ifndef __EMX__
+#include <rexxsaa.h>
+#endif
+#include "install.h"
+#include "instsup.h"
+
+/* My Global variables ;) unusually many due to multiple dialogs */
+HWND mainhwnd = 0, hwndHidden;
+char tempPath[_MAX_PATH], *reason = "Error unpacking files, Installer may be corrupt!";
+int current_file=0, success=0, installstate = NONE;
+unsigned long int acepos=0, aceoffset=0;
+/* I know I am being excessive but... better safe than sorry ;) */
+char *configsys[8196];
+int configfilecount=-1, packagechosen, no_update = 0, get_image = 0, image_size = 0;
+int files = 0, packagesize=0, packagesselected[20], dialogx, dialogy;
+char *image_data;
+ULONG foldericon;
+
+/* So these are accessible to REXX */
+int drivelist[26];
+HWND hwnddir, hwndentry, hwndcombo, hwndper, hwndstatus;
+FILE *self;
+char finishedscript[100] = "";
+
+/* These get loaded in loadheader */
+char *INSTALLER_APPLICATION;
+char *INSTALLER_VERSION;
+char *INSTALLER_TITLE;
+char *INSTALLER_PATH;
+char *INSTALLER_FOLDER;
+char *INSTALLER_PROGRAM;
+char *INSTALLER_SHADOW;
+char *INSTALLER_OBJECT;
+char *INSTALLER_SETS;
+char *INSTALLER_SYSVAR;
+char *INSTALLER_SYSLINE;
+char *INSTALLER_PACKAGES[20];
+char *INSTALLER_CONFIRM_WPS;
+char *INSTALLER_CONFIRM_CONFIGSYS;
+char *INSTALLER_CONFIRM_OVERWRITE;
+int INSTALLER_PACKAGE_COUNT;
+
+/* Config.Sys -- Note the drive letter gets replaced with the boot drive letter
+                 It is just a place holder. (For the next 3 entries)             */
+char csfile[] = "C:\\CONFIG.SYS";
+/* Backup Config.Sys filename */
+char bufile[] = "C:\\CONFIG.NST";
+/* Installation Log Database -- Used for uninstallation and aborting */
+#ifdef __WIN32__
+char instlog[MAX_PATH+1] = "C:\\DBINST.LOG";
+#elif defined(__OS2__)
+char instlog[] = "C:\\OS2\\INSTALL\\DBINST.LOG";
+#else
+char instlog[] = "/var/log/dbinst";
+#endif
+char installdir[_MAX_PATH];
+
+char bootdrive[2] = "C";
+#ifdef __UNIX__
+char browsedir[_MAX_PATH+1] = "/";
+#else
+char browsedir[_MAX_PATH+1] = "C:\\";
+#endif
+char installdir2[_MAX_PATH+1] = "";
+char empty_string[] = "";
+char currentcf[_MAX_PATH+1] = "";
+char *instsuffix = NULL;
+
+#ifdef ENABLE_LOGGING
+FILE *logfile;
+#endif
+
+/* Set the instsuffix variable from a string buffer */
+void getsuffix(char *path)
+{
+	int z;
+
+	for(z=strlen(path)-1;z>-1;z--)
+	{
+		if(path[z] == '/' || path[z] == '\\')
+		{
+			if(strlen(&path[z+1]))
+			{
+				char *old = instsuffix;
+
+				instsuffix = strdup(&path[z+1]);
+
+				if(old)
+					free(old);
+			}
+			if(!instsuffix)
+				instsuffix = strdup("path");
+			return;
+		}
+	}
+	if(!instsuffix)
+		instsuffix = strdup("path");
+}
+
+/* In str1, str2 gets replaced by str3 */
+char *replacestr(char *str1, char *str2, char *str3)
+{
+	char bigbuffer[4096];
+	int z, x=0, len1 = strlen(str1), len2 = strlen(str2), len3 = strlen(str3);
+
+	for(z=0;z<len1;z++)
+	{
+		if(len2 > 0 && strncmp(&str1[z], str2, len2)==0)
+		{
+			int i;
+			for(i=0;i<len3;i++)
+			{
+				bigbuffer[x] = str3[i];
+				x++;
+			}
+			z=z+(len2-1);
+		} else {
+			bigbuffer[x] = str1[z];
+			x++;
+		}
+	}
+	bigbuffer[x] = 0;
+	return (char *)strdup(bigbuffer);
+}
+
+/* This function parses a string and replaces all the text in the
+ * Replacement array with the current dynamic text */
+char *replaceem(char *orig)
+{
+	char *tmp1 = NULL, *tmp2 = (char *)strdup(orig);
+	int z;
+
+	/* The variables in this array must be static buffers */
+	Replacements InstRep[] = {
+		{ "%INSTALLPATH%",   installdir },
+		{ "%BOOTDRIVE%",     bootdrive },
+		{ "%ANYSTRING%",     empty_string },
+		{ "%USERPATH%",      installdir2 },
+		{ "%VERSION%",       "" } /* think about this -- should be INSTALLER_VERSION */
+	};
+
+
+	for(z=0;z<5;z++)
+	{
+		tmp1 = replacestr(tmp2, InstRep[z].replacestring, InstRep[z].replacevar);
+		free(tmp2);
+		tmp2 = tmp1;
+        tmp1 = NULL;
+	}
+    return tmp2;
+}
+
+/*
+ * Find the offset withing the executable of the ace data for use.
+ */
+int aceseek_entry(int num)
+{
+	long headerstart;
+	char headerbuf[20], packageconfig[100];
+	int z, start = 0, entry = 0, packageoffset=0;
+	/* Decode DBSOFT-ACE - small memleak but
+	 * install should not be running for very long. :) */
+	sprintf(headerbuf, "%s%d", decode("EEECFDEPEGFECNEBEDEF"), num);
+	if((headerstart = findtext(headerbuf)) < 0)
+	{
+		mesg("Could not find ACE header in executable.");
+		exit(2);
+	}
+
+	fseek(self, headerstart+strlen(headerbuf), SEEK_SET);
+	fread(packageconfig, 1, 100, self);
+
+	for(z=0;z<100;z++)
+	{
+		if(packageconfig[z] == '-' || packageconfig[z] == '~')
+		{
+			char cur = packageconfig[z];
+			packageconfig[z] = 0;
+			switch(entry)
+			{
+			case 0:
+				current_file = 0;
+				files = atoi(&packageconfig[start]);
+				break;
+			case 1:
+				packagesize = atoi(&packageconfig[start]);
+				break;
+			}
+			start = z+1;
+			if(cur == '~')
+			{
+				packageoffset = z + 1;
+				z = 100;
+			}
+			entry++;
+		}
+	}
+	aceoffset=headerstart+strlen(headerbuf)+packageoffset;
+	fseek(self, aceoffset, SEEK_SET);
+	return TRUE;
+}
+
+/*
+ * Reads the embedded .cfg data from the executable and place it in the global
+ * INSTALL_* variables for use.
+ */
+int loadheader(void)
+{
+	char *buffer;
+	long headerstart;
+	int z, start=0, entry=0;
+
+	buffer = malloc(8096*4);
+
+    /* Decode DBSOFT-HEADER */
+	if((headerstart = findtext(decode("EEECFDEPEGFECNEIEFEBEEEFFC"))) < 0)
+	{
+		mesg("Could not find Selfinstaller header in executable.");
+		exit(2);
+	}
+	fseek(self, headerstart+13, SEEK_SET);
+
+	fread(buffer, 1, 8096*4, self);
+	for(z=0;z<8096*4;z++)
+	{
+		if(buffer[z] == '-' || buffer[z] == '~')
+		{
+			char cur = buffer[z];
+			buffer[z] = 0;
+			switch(entry)
+			{
+			case 0:
+				INSTALLER_APPLICATION = (char *)strdup(&buffer[start]);
+				break;
+			case 1:
+				INSTALLER_VERSION = (char *)strdup(&buffer[start]);
+				break;
+			case 2:
+				INSTALLER_TITLE = (char *)strdup(&buffer[start]);
+				break;
+			case 3:
+				INSTALLER_PATH = (char *)strdup(&buffer[start]);
+				break;
+			case 4:
+				INSTALLER_FOLDER = (char *)strdup(&buffer[start]);
+				break;
+			case 5:
+				INSTALLER_PROGRAM = (char *)strdup(&buffer[start]);
+				break;
+			case 6:
+				INSTALLER_SHADOW = (char *)strdup(&buffer[start]);
+				break;
+			case 7:
+				INSTALLER_OBJECT = (char *)strdup(&buffer[start]);
+				break;
+			case 8:
+				INSTALLER_SETS = (char *)strdup(&buffer[start]);
+				break;
+			case 9:
+				INSTALLER_SYSVAR = (char *)strdup(&buffer[start]);
+				break;
+			case 10:
+				INSTALLER_SYSLINE = (char *)strdup(&buffer[start]);
+				break;
+			case 11:
+				INSTALLER_CONFIRM_WPS = (char *)strdup(&buffer[start]);
+				break;
+			case 12:
+				INSTALLER_CONFIRM_CONFIGSYS = (char *)strdup(&buffer[start]);
+				break;
+			case 13:
+				INSTALLER_CONFIRM_OVERWRITE = (char *)strdup(&buffer[start]);
+				break;
+			case 14:
+				INSTALLER_PACKAGE_COUNT = atoi(&buffer[start]);
+				break;
+			default:
+				INSTALLER_PACKAGES[entry-15] = malloc((z-start)+1);
+				strcpy(INSTALLER_PACKAGES[entry-15], &buffer[start]);
+				break;
+			}
+			start = z+1;
+			if(cur == '~')
+			{
+                free(buffer);
+				return TRUE;
+			}
+
+			entry++;
+		}
+	}
+	free(buffer);
+	return FALSE;
+}
+
+/*
+ * Functions to work on an ace file embedded within the archive in an
+ * abstract manner.
+ */
+int aceread(void *buf, size_t count)
+{
+	unsigned long curpos = ftell(self);
+	size_t readit;
+
+	if(count >  (packagesize-(curpos-aceoffset)))
+		readit = (packagesize-(curpos-aceoffset));
+	else
+		readit = count;
+
+	return fread(buf, 1, readit, self);
+}
+
+off_t acelseek(off_t offset, int whence)
+{
+	switch(whence)
+	{
+	case SEEK_SET:
+		fseek(self, aceoffset+offset, SEEK_SET);
+		break;
+	case SEEK_CUR:
+		fseek(self, offset, SEEK_CUR);
+		break;
+	}
+	return acepos;
+}
+
+int aceopen(const char *path, int flags)
+{
+	fseek(self, aceoffset, SEEK_SET);
+	return 0;
+}
+
+int aceclose(int fd)
+{
+	fseek(self, aceoffset, SEEK_SET);
+	return  0;
+}
+
+int acesize(void)
+{
+	return packagesize;
+}
+
+int acetell(int fd)
+{
+	return ftell(self)-aceoffset;
+}
+
+/*
+ * Read the generated log file and remove any files installed.
+ */
+void delete_files(void)
+{
+	char tmpbuf[8196], *fileptr;
+	FILE *tmplf;
+	int linenum=0, found=-1, z;
+
+	if((tmplf=fopen(instlog, "rb"))==NULL)
+		return;
+
+	while(!feof(tmplf))
+	{
+		fgets(tmpbuf, 8196, tmplf);
+		linenum++;
+		if(tmpbuf[0]=='[' && (char *)strstr(tmpbuf, INSTALLER_APPLICATION) != NULL && !feof(tmplf))
+		{
+			fgets(tmpbuf, 8196, tmplf);
+			linenum++;
+			if((char *)strstr(tmpbuf, "<Version>") != NULL && (char *)strstr(tmpbuf, INSTALLER_VERSION) != NULL)
+				found=linenum;
+		}
+	}
+	if(found != -1)
+	{
+		rewind(tmplf);
+		for (z=0;z<found;z++)
+			fgets(tmpbuf, 8196, tmplf);
+		while(!feof(tmplf))
+		{
+			fgets(tmpbuf, 8196, tmplf);
+			if((char *)strstr(tmpbuf, "<FileInst>") != NULL)
+			{
+				fileptr = (char *)strchr(tmpbuf, ',')+1;
+				/* Remove trailing CRLFs */
+				if(fileptr[strlen(fileptr)-1] == '\r' || fileptr[strlen(fileptr)-1] == '\n')
+					fileptr[strlen(fileptr)-1]=0;
+				if(fileptr[strlen(fileptr)-1] == '\r' || fileptr[strlen(fileptr)-1] == '\n')
+					fileptr[strlen(fileptr)-1]=0;
+				remove(fileptr);
+				current_file--;
+                update_percent();
+			}
+			if((char *)strstr(tmpbuf, "<End>") != NULL)
+			{
+				fclose(tmplf);
+				return;
+			}
+		}
+	}
+	fclose(tmplf);
+	return;
+}
+
+/*
+ * Reads a config file into memory for editing with updatesys, updateset, etc.
+ */
+int readconfigfile(char *filename)
+{
+	char tmpbuf[8196];
+	FILE *tmpcs;
+
+    /* Reset this value when restarting */
+	configfilecount = -1;
+
+	if((tmpcs=fopen(filename, "rb"))==NULL)
+	{
+        strcpy(currentcf, empty_string);
+		return 1;
+	}
+	else
+        strcpy(currentcf, filename);
+
+	while(!feof(tmpcs))
+	{
+		configfilecount++;
+		fgets(tmpbuf, 8196, tmpcs);
+		configsys[configfilecount] = malloc(strlen(tmpbuf)+1);
+		strcpy(configsys[configfilecount], tmpbuf);
+        stripcrlf(configsys[configfilecount]);
+	}
+
+	fclose(tmpcs);
+	return 0;
+}
+
+/*
+ * Write the updated config file to disk and backup the original.
+ */
+int writeconfigfile(char *filename, char *backup)
+{
+	FILE *tmpcs;
+	int i;
+
+	if(backup)
+	{
+		remove(backup);
+		rename(filename, backup);
+	}
+	else
+        remove(filename);
+
+	if((tmpcs=fopen(filename, "wb"))==NULL)
+		return 1;
+
+	for(i=0;i<configfilecount;i++)
+	{
+		if(configsys[i])
+		{
+			fwrite(configsys[i], 1, strlen(configsys[i]), tmpcs);
+            /* Add the CRLF that got stripped in the reading stage. */
+            fwrite("\r\n", 1, 2, tmpcs);
+			free(configsys[i]);
+		}
+	}
+
+	fclose(tmpcs);
+	return 0;
+}
+/*
+ * Adds or replaces a SET variable based on the flags (CONFIG.SYS)
+ */
+void updateset(char *setname, char *newvalue, int flag)
+{
+	char *cmpbuf1, *cmpbuf2, *tmpptr, *tmpptr2, *nv;
+	int i, z, t;
+
+    nv=replaceem(newvalue);
+
+	cmpbuf1=malloc(strlen(setname)+2);
+	strcpy(cmpbuf1, setname);
+	strcat(cmpbuf1, "=");
+	for(i=0;i<configfilecount;i++)
+	{
+		if(strlen(cmpbuf1) <= strlen(configsys[i]))
+		{
+			tmpptr=(char *)strdup(configsys[i]);
+			strupr(tmpptr);
+			if((tmpptr2=(char*)strstr(tmpptr, "SET "))!=NULL)
+			{
+				tmpptr2 += 4;
+				cmpbuf2=malloc(strlen(tmpptr2)+1);
+				/* Remove any spaces from the string */
+				z=0;
+				for (t=0;t<strlen(tmpptr2) && z < strlen(cmpbuf1);t++)
+				{
+					if(tmpptr2[t] != ' ')
+					{
+						cmpbuf2[z]=tmpptr2[t];
+						z++;
+					}
+				}
+				cmpbuf2[z]=0;
+				if(strcasecmp(cmpbuf1, cmpbuf2) == 0)
+				{
+					/* Ok we found the entry, and if UPDATE_ALWAYS change it to the
+					 new entry, otherwise exit */
+					if(flag == UPDATE_ALWAYS)
+					{
+#ifdef ENABLE_LOGGING
+						fprintf(logfile, "<CFRemLine>,%s,%s\r\n", currentcf, configsys[i]);
+#endif
+						free(configsys[i]);
+						configsys[i] = malloc(strlen(setname)+strlen(nv)+6);
+                        strcpy(configsys[i], "SET ");
+						strcat(configsys[i], setname);
+                        strcat(configsys[i], "=");
+						strcat(configsys[i], nv);
+#ifdef ENABLE_LOGGING
+						fprintf(logfile, "<CFAddLine>,%s,%s\r\n", currentcf, configsys[i]);
+#endif
+						free(cmpbuf1);free(cmpbuf2);free(tmpptr);
+					}
+					return;
+				}
+				free(cmpbuf2);
+			}
+			free(tmpptr);
+		}
+	}
+	/* Couldn't find the line so we'll add it */
+	configsys[configfilecount]=malloc(strlen(cmpbuf1)+strlen(nv)+6);
+	strcpy(configsys[configfilecount], "SET ");
+	strcat(configsys[configfilecount], setname);
+	strcat(configsys[configfilecount], "=");
+	strcat(configsys[configfilecount], nv);
+#ifdef ENABLE_LOGGING
+	fprintf(logfile, "<CFAddLine>,%s,%s\r\n", currentcf, configsys[configfilecount]);
+#endif
+	configfilecount++;
+	free(cmpbuf1);
+    free(nv);
+}     
+
+/*
+ * Adds an entry to a system variable (CONFIG.SYS)
+ */
+void updatesys(char *sysname, char *newvalue)
+{
+	char *cmpbuf1, *cmpbuf2, *tmpptr, *tmpptr2, *capbuf1, *capbuf2, *nv, *brian;
+	int i, z, t;
+
+	nv=replaceem(newvalue);
+
+	cmpbuf1=malloc(strlen(sysname)+2);
+	strcpy(cmpbuf1, sysname);
+	strcat(cmpbuf1, "=");
+	for(i=0;i<configfilecount;i++)
+	{
+		if(strlen(cmpbuf1) <= strlen(configsys[i]))
+		{
+			cmpbuf2=malloc(strlen(configsys[i])+1);
+			/* Remove any spaces from the string */
+			z=0;
+			for (t=0;t<strlen(configsys[i]) && z < strlen(cmpbuf1);t++)
+			{
+				if(configsys[i][t] != ' ')
+				{
+					cmpbuf2[z]=configsys[i][t];
+					z++;
+				}
+			}
+			cmpbuf2[z]=0;
+			if(strcasecmp(cmpbuf1, cmpbuf2) == 0)
+			{
+				/* Do a case insensitive comparison but preserve the case */
+				tmpptr = &configsys[i][t];
+				capbuf1=malloc(strlen(tmpptr)+1);
+				capbuf2=malloc(strlen(nv)+1);
+				strcpy(capbuf1, tmpptr);
+				strcpy(capbuf2, nv);
+				strupr(capbuf1);
+				strupr(capbuf2);
+				/* Ok, we found the line, and it doesn't have an entry so we'll add it */
+				if((tmpptr2=(char *)strstr(capbuf1, capbuf2)) == NULL)
+				{
+#ifdef ENABLE_LOGGING
+					fprintf(logfile, "<CFRemLine>,%s,%s\r\n", currentcf, configsys[i]);
+#endif
+					brian = configsys[i];
+					configsys[i] = malloc(strlen(configsys[i])+strlen(nv)+4);
+					strcpy(configsys[i], brian);
+					free(brian);
+					/* Remove any trailing CRLFs */
+					if(configsys[i][strlen(configsys[i])-1]!=';')
+						strcat(configsys[i], ";");
+					strcat(configsys[i], nv);
+					strcat(configsys[i], ";");
+#ifdef ENABLE_LOGGING
+					fprintf(logfile, "<CFAddLine>,%s,%s\r\n", currentcf, configsys[i]);
+#endif
+				}
+				free(cmpbuf1);free(cmpbuf2);free(capbuf1);free(capbuf2);
+				return;
+			}
+			free(cmpbuf2);
+		}
+	}
+	/* Couldn't find the line so we'll add it */
+	configsys[configfilecount]=malloc(strlen(cmpbuf1)+strlen(nv)+3);
+	strcpy(configsys[configfilecount], cmpbuf1);
+	strcat(configsys[configfilecount], nv);
+	strcat(configsys[configfilecount], ";");
+#ifdef ENABLE_LOGGING
+	fprintf(logfile, "<CFAddLine>,%s,%s", currentcf, configsys[configfilecount]);
+#endif
+	configfilecount++;
+	free(cmpbuf1);
+	free(nv);
+}
+
+/*
+ * Removes a line from a config file.
+ */
+void removeline(char *text)
+{
+	int z;
+	for(z=0;z<configfilecount;z++)
+	{
+		if(strcasecmp(configsys[z], text) == 0)
+		{
+			int t;
+
+#ifdef ENABLE_LOGGING
+			fprintf(logfile, "<CFRemLine>,%s,%s\r\n", currentcf, configsys[z]);
+#endif
+			free(configsys[z]);
+			for(t=z;t<(configfilecount-1);t++)
+				configsys[t] = configsys[t+1];
+			configfilecount--;
+		}
+	}
+}
+
+
+void DWSIGNAL confirm_yes(HWND window, void *data)
+{
+	DWDialog *dialog = (DWDialog *)data;
+	HWND entrywindow = (HWND)dialog->data;
+
+	dw_dialog_dismiss(dialog, (void *)0);
+	dw_window_destroy(entrywindow);
+}
+
+void DWSIGNAL confirm_no(HWND window, void *data)
+{
+	DWDialog *dialog = (DWDialog *)data;
+	HWND entrywindow = (HWND)dialog->data;
+
+	dw_dialog_dismiss(dialog, (void *)2);
+	dw_window_destroy(entrywindow);
+}
+
+void DWSIGNAL confirm_all(HWND window, void *data)
+{
+	DWDialog *dialog = (DWDialog *)data;
+	HWND entrywindow = (HWND)dialog->data;
+
+	dw_dialog_dismiss(dialog, (void *)1);
+	dw_window_destroy(entrywindow);
+}
+
+void DWSIGNAL confirm_cancel(HWND window, void *data)
+{
+	DWDialog *dialog = (DWDialog *)data;
+	HWND entrywindow = (HWND)dialog->data;
+
+	dw_dialog_dismiss(dialog, (void *)3);
+	dw_window_destroy(entrywindow);
+}
+
+/* Create the confirmation dialog */
+void DWSIGNAL confirm_dialog(char *entrytext, DWDialog *dialog)
+{
+	HWND entrywindow, mainbox, nobutton, yesbutton, allbutton, cancelbutton, buttonbox, stext;
+	ULONG flStyle = DW_FCF_TITLEBAR | DW_FCF_SHELLPOSITION | DW_FCF_DLGBORDER;
+
+	entrywindow = dw_window_new(HWND_DESKTOP, INSTALLER_TITLE, flStyle);
+
+	mainbox = dw_box_new(BOXVERT, 10);
+
+	dw_box_pack_start(entrywindow, mainbox, 150, 70, TRUE, TRUE, 0);
+
+	/* Archive Name */
+	stext = dw_text_new(entrytext, 0);
+
+	dw_window_set_style(stext, DW_DT_WORDBREAK, DW_DT_WORDBREAK);
+
+	dw_box_pack_start(mainbox, stext, 130, 40, TRUE, TRUE, 2);
+
+	/* Buttons */
+	buttonbox = dw_box_new(BOXHORZ, 10);
+
+	dw_box_pack_start(mainbox, buttonbox, 0, 0, TRUE, TRUE, 0);
+
+	yesbutton = dw_button_new("Yes", 1001L);
+
+	dw_box_pack_start(buttonbox, yesbutton, 70, 30, TRUE, TRUE, 2);
+
+	nobutton = dw_button_new("No", 1002L);
+
+	dw_box_pack_start(buttonbox, nobutton, 70, 30, TRUE, TRUE, 2);
+
+	allbutton = dw_button_new("All", 1003L);
+
+	dw_box_pack_start(buttonbox, allbutton, 70, 30, TRUE, TRUE, 2);
+
+	cancelbutton = dw_button_new("Cancel", 1002L);
+
+	dw_box_pack_start(buttonbox, cancelbutton, 70, 30, TRUE, TRUE, 2);
+
+	dialog->data = (void *)entrywindow;
+
+	dw_signal_connect(yesbutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(confirm_yes), (void *)dialog);
+	dw_signal_connect(nobutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(confirm_no), (void *)dialog);
+	dw_signal_connect(allbutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(confirm_all), (void *)dialog);
+	dw_signal_connect(cancelbutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(confirm_cancel), (void *)dialog);
+
+	dw_window_set_pos_size(entrywindow, dialogx, dialogy, 340, 150);
+
+	dw_window_show(entrywindow);
+}
+/*
+ * Display a confirmation dialog with the options: YES NO ALL CANCEL
+ * Returns: 0 for YES, 1 for ALL, 2 for NO and 3 for CANCEL
+ */
+int confirm(char *format, ...)
+{
+	va_list args;
+	DWDialog *dialog;
+	char confirmstring[1024];
+
+	/* if no confirmation, return 1, meaning overwrite all */
+	if (strcasecmp(INSTALLER_CONFIRM_OVERWRITE, "no") == 0)
+		return 1;
+
+	va_start(args, format);
+	vsprintf(confirmstring, format, args);
+	va_end(args);
+
+	dialog = dw_dialog_new(NULL);
+	confirm_dialog(confirmstring, dialog);
+
+	return (int)dw_dialog_wait(dialog);
+}
+
+/*
+ * A function to grab a file from an embedded archive and extract it to the TEMP directory.
+ */
+void grabfile(char *filename)
+{
+	no_update = 1;
+	settempdir();
+	remove(filename);
+	aceseek_entry(0);
+	resetglobals();
+	installer_unpack(filename, 2);
+	no_update = 0;
+}
+
+/*
+ * A function to grab a file from an embedded archive and extract it to the TEMP directory.
+ */
+char *grabimage(char *filename, char *imagebuf, int size)
+{
+	get_image = no_update = 1;
+	image_data = imagebuf;
+	image_size = size;
+	settempdir();
+	aceseek_entry(0);
+	resetglobals();
+	installer_unpack(filename, 2);
+	get_image = no_update = 0;
+	return image_data;
+}
+
+/*
+ * This thread runs along side the main thread allowing the user to cancel the process.
+ */
+void install_thread(void *param)
+{
+	char tmpinstallpath[1024];
+	int  k, j, installcount=0, installed=0;
+
+	installstate = INSTALLING;
+
+#ifdef ENABLE_LOGGING
+	if((logfile=fopen(instlog, "ab"))==NULL)
+	{
+		error("Log file \"%s\" open failed! Installation aborted!", instlog);
+		exit(1);
+	}
+
+	fprintf(logfile, "[%s]\r\n<Version>,%s\r\n<Start>\r\n", INSTALLER_APPLICATION, INSTALLER_VERSION);
+#endif
+
+	/* Create nested subdirectories if necessary. */
+	strcpy(tmpinstallpath, installdir);
+	for(k=3;k<strlen(installdir);k++)
+	{
+		if(tmpinstallpath[k] == '\\')
+		{
+			tmpinstallpath[k] = 0;
+			if(makedir(tmpinstallpath)==0)
+#ifdef ENABLE_LOGGING
+				fprintf(logfile, "<NewDir>,%s\r\n", tmpinstallpath);
+#else
+				;
+#endif
+			tmpinstallpath[k] = '\\';
+		}
+	}
+
+#ifdef ENABLE_LOGGING
+	fprintf(logfile, "<NewDir>,%s\r\n", installdir);
+#endif
+	makedir(installdir);
+
+	if(strlen(installdir) > 0 && installdir[0] > 'a'-1 && installdir[0] < 'z'+1)
+		installdir[0]=installdir[0] - ('a'-'A');
+
+	setdrivedir(installdir);
+
+	/* Unpack files to destination directory */
+	for(j=1;j<INSTALLER_PACKAGE_COUNT;j++)
+	{
+		if(packagesselected[j] == TRUE)
+			installcount++;
+	}
+	if(installcount == 0)
+	{
+		mesg("No packages selected for installation!");
+	}
+	else
+	{
+		for(j=1;j<INSTALLER_PACKAGE_COUNT;j++)
+		{
+			if(packagesselected[j] == TRUE)
+			{
+				char statustext[512];
+				aceseek_entry(j);
+				resetglobals();
+
+				sprintf(statustext,"Copying Files for %s (%d/%d).", INSTALLER_PACKAGES[j], installed+1, installcount);
+				dw_window_set_text(hwndstatus, statustext);
+
+				/* filename parameter when null is all files */
+				installer_unpack(NULL, 2);
+				update_percent();
+				installed++;
+			}
+		}
+        create_uninstall_object();
+	}
+
+	if(success==1)
+	{
+		dw_messagebox(INSTALLER_TITLE, DW_MB_OK | DW_MB_ERROR, reason);
+	}
+
+	if(success==2)
+	{
+		dw_messagebox(INSTALLER_TITLE, DW_MB_OK | DW_MB_INFORMATION, "User aborted installation!");
+	}
+
+	if(installstate != ABORTED)
+		installstate = COMPLETED;
+
+    dw_window_function(mainhwnd, (void *)finish_install, NULL);
+}
+
+/*
+ * Use the information from the .cfg file which is embedded in the EXE to update the
+ * CONFIG.SYS settings.
+ */
+void configsys_update(void)
+{
+	char *arg1, *arg2, *arg3, *arg4;
+	char temp[5000];
+	int z, argn=0;
+
+	if(readconfigfile(csfile))
+		return;
+
+    /* Update Miscellaneous lines */
+	if(strlen(INSTALLER_SYSLINE)>0)
+	{
+		strcpy(temp, INSTALLER_SYSLINE);
+        argn=0;
+		arg1=&temp[0];
+		arg2=arg3=arg4=NULL;
+
+		for(z=0;z<strlen(INSTALLER_SYSLINE);z++)
+		{
+			if(temp[z]==',')
+			{
+				argn++;
+				temp[z]=0;
+				switch(argn)
+				{
+				case 1:
+					arg2=&temp[z+1];
+					break;
+				case 2:
+					if(atoi(arg1) > 0 && atoi(arg1) < 20 && (packagesselected[atoi(arg1)] == TRUE || atoi(arg1) == -1))
+					{
+						char *tmpptr;
+
+						temp[z] = 0;
+						tmpptr = replaceem(arg2);
+						removeline(tmpptr);
+						configsys[configfilecount] = tmpptr;
+#ifdef ENABLE_LOGGING
+						fprintf(logfile, "<CFAddLine>,%s,%s\r\n", currentcf, tmpptr);
+#endif
+						configfilecount++;
+					}
+					break;
+				}
+			}
+		}
+		if(arg2 && *arg2 && atoi(arg1) > 0 && atoi(arg1) < 20 && (packagesselected[atoi(arg1)] == TRUE || atoi(arg1) == -1))
+		{
+			char *tmpptr;
+
+			tmpptr = replaceem(arg2);
+			removeline(tmpptr);
+			configsys[configfilecount] = tmpptr;
+#ifdef ENABLE_LOGGING
+			fprintf(logfile, "<CFAddLine>,%s,%s\r\n", currentcf, tmpptr);
+#endif
+			configfilecount++;
+		}
+
+	}
+	/* Update SET variables */
+	if(strlen(INSTALLER_SETS)>0)
+	{
+		strcpy(temp, INSTALLER_SETS);
+        argn=0;
+		arg1=&temp[0];
+		arg2=arg3=arg4=NULL;
+		for(z=0;z<strlen(INSTALLER_SETS);z++)
+		{
+			if(temp[z]==',')
+			{
+				argn++;
+				temp[z]=0;
+				switch(argn)
+				{
+				case 1:
+					arg2=&temp[z+1];
+					break;
+				case 2:
+					arg3=&temp[z+1];
+					break;
+				case 3:
+					arg4=&temp[z+1];
+					break;
+				case 4:
+					argn=0;
+					if(atoi(arg1) > 0 && atoi(arg1) < 20 && (packagesselected[atoi(arg1)] == TRUE || atoi(arg1) == -1))
+						updateset(arg2, arg3, (int)(arg4[0]-'0'));
+					arg1=&temp[z+1];
+					arg2=arg3=arg4=NULL;
+					break;
+				}
+			}
+		}
+		if(arg4 && atoi(arg1) > 0 && atoi(arg1) < 20 && (packagesselected[atoi(arg1)] == TRUE || atoi(arg1) == -1))
+			updateset(arg2, arg3, (int)arg4-'0');
+	}
+	/* Update system variables */
+	if(strlen(INSTALLER_SYSVAR)>0)
+	{
+		strcpy(temp, INSTALLER_SYSVAR);
+        argn=0;
+		arg1=&temp[0];
+		arg2=arg3=NULL;
+		for(z=0;z<strlen(INSTALLER_SYSVAR);z++)
+		{
+			if(temp[z]==',')
+			{
+				argn++;
+				temp[z]=0;
+				switch(argn)
+				{
+				case 1:
+					arg2=&temp[z+1];
+					break;
+				case 2:
+					arg3=&temp[z+1];
+					break;
+				case 3:
+					argn=0;
+					if(atoi(arg1) > 0 && atoi(arg1) < 20 && (packagesselected[atoi(arg1)] == TRUE || atoi(arg1) == -1))
+						updatesys(arg2, arg3);
+					arg1=&temp[z+1];
+					arg2=arg3=NULL;
+					break;
+				}
+			}
+		}
+   	if(arg3 && atoi(arg1) > 0 && atoi(arg1) < 20 && (packagesselected[atoi(arg1)] == TRUE || atoi(arg1) == -1))
+ 			updatesys(arg2, arg3);
+	}
+
+	writeconfigfile(csfile, bufile);
+}
+
+void create_wps_objects(void)
+{
+	char *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7, *result;
+	char temp[5000];
+	char zerotext[2] = "";
+	int z, argn, len;
+
+	/* Create Folder Objects */
+	if(strlen(INSTALLER_FOLDER)>0)
+	{
+        char *tmpptr = replaceem(INSTALLER_FOLDER);
+		strcpy(temp, tmpptr);
+		free(tmpptr);
+
+		argn=0;
+		arg1=&temp[0];
+		arg2=arg3=arg4=arg5=arg6=&zerotext[0];
+        len = strlen(temp);
+		for(z=0;z<len;z++)
+		{
+			if(temp[z]==',')
+			{
+				argn++;
+				temp[z]=0;
+				switch(argn)
+				{
+				case 1:
+					arg2=&temp[z+1];
+					break;
+				case 2:
+					arg3=&temp[z+1];
+					break;
+				case 3:
+					arg4=&temp[z+1];
+					break;
+				case 4:
+					arg5=&temp[z+1];
+					break;
+				case 5:
+					arg6=&temp[z+1];
+					break;
+				case 6:
+
+					argn=0;
+					if(atoi(arg1) > 0 && atoi(arg1) < 20 && (packagesselected[atoi(arg1)] == TRUE || atoi(arg1) == -1))
+					{
+						result = MakeFolder(arg2, arg3, arg4, arg5, arg6);
+#ifdef ENABLE_LOGGING
+						fprintf(logfile, "<WPSFolderAdd>,%s,%s,%s,%s,%s,%s\r\n", arg2,arg3,arg4,arg5,arg6,result?result:"");
+#endif
+					}
+					arg1=&temp[z+1];
+					arg2=arg3=arg4=arg5=arg6=&zerotext[0];
+					break;
+				}
+			}
+		}
+		if(arg6 && atoi(arg1) > 0 && atoi(arg1) < 20 && (packagesselected[atoi(arg1)] == TRUE || atoi(arg1) == -1))
+		{
+			result = MakeFolder(arg2, arg3, arg4, arg5, arg6);
+#ifdef ENABLE_LOGGING
+			fprintf(logfile, "<WPSFolderAdd>,%s,%s,%s,%s,%s,%s\r\n", arg2, arg3,arg4,arg5,arg6,result?result:"");
+#endif
+		}
+	}
+
+	/* Create Program Objects */
+	if(strlen(INSTALLER_PROGRAM)>0)
+	{
+        char *tmpptr = replaceem(INSTALLER_PROGRAM);
+		strcpy(temp, tmpptr);
+		free(tmpptr);
+
+		argn=0;
+		arg1=&temp[0];
+		arg2=arg3=arg4=arg5=arg6=arg7=&zerotext[0];
+        len = strlen(temp);
+		for(z=0;z<len;z++)
+		{
+			if(temp[z]==',')
+			{
+				argn++;
+				temp[z]=0;
+				switch(argn)
+				{
+				case 1:
+					arg2=&temp[z+1];
+					break;
+				case 2:
+					arg3=&temp[z+1];
+					break;
+				case 3:
+					arg4=&temp[z+1];
+					break;
+				case 4:
+					arg5=&temp[z+1];
+					break;
+				case 5:
+					arg6=&temp[z+1];
+					break;
+				case 6:
+					arg7=&temp[z+1];
+					break;
+				case 7:
+					argn=0;
+					if(atoi(arg1) > 0 && atoi(arg1) < 20 && (packagesselected[atoi(arg1)] == TRUE || atoi(arg1) == -1))
+					{
+						result = MakeProgram(arg2, arg3, arg4, arg5, arg6, arg7);
+#ifdef ENABLE_LOGGING
+						fprintf(logfile, "<WPSProgramAdd>,%s,%s,%s,%s,%s,%s,%s\r\n", arg2,arg3,arg4,arg5,arg6,arg7,result?result:"");
+#endif
+					}
+					arg1=&temp[z+1];
+					arg2=arg3=arg4=arg5=arg6=arg7=&zerotext[0];
+					break;
+				}
+			}
+		}
+		if(arg7 && atoi(arg1) > 0 && atoi(arg1) < 20 && (packagesselected[atoi(arg1)] == TRUE || atoi(arg1) == -1))
+		{
+			result = MakeProgram(arg2, arg3, arg4, arg5, arg6, arg7);
+#ifdef ENABLE_LOGGING
+			fprintf(logfile, "<WPSProgramAdd>,%s,%s,%s,%s,%s,%s,%s\r\n", arg2,arg3,arg4,arg5,arg6,arg7,result?result:"");
+#endif
+		}
+	}
+
+	/* Create Shadow Objects */
+	if(strlen(INSTALLER_SHADOW)>0)
+	{
+        char *tmpptr = replaceem(INSTALLER_SHADOW);
+		strcpy(temp, tmpptr);
+		free(tmpptr);
+
+		argn=0;
+		arg1=&temp[0];
+		arg2=arg3=arg4=arg5=&zerotext[0];
+        len = strlen(temp);
+		for(z=0;z<len;z++)
+		{
+			if(temp[z]==',')
+			{
+				argn++;
+				temp[z]=0;
+				switch(argn)
+				{
+				case 1:
+					arg2=&temp[z+1];
+					break;
+				case 2:
+					arg3=&temp[z+1];
+					break;
+				case 3:
+					arg4=&temp[z+1];
+					break;
+				case 4:
+					arg5=&temp[z+1];
+					break;
+				case 5:
+					argn=0;
+					if(atoi(arg1) > 0 && atoi(arg1) < 20 && (packagesselected[atoi(arg1)] == TRUE || atoi(arg1) == -1))
+					{
+						result = MakeShadow(arg2, arg3, arg4, arg5);
+#ifdef ENABLE_LOGGING
+						fprintf(logfile, "<WPSShadowAdd>,%s,%s,%s,%s,%s\r\n", arg2,arg3,arg4,arg5,result?result:"");
+#endif
+					}
+					arg1=&temp[z+1];
+					arg2=arg3=arg4=&zerotext[0];
+					break;
+				}
+			}
+		}
+		if(arg5 && atoi(arg1) > 0 && atoi(arg1) < 20 && (packagesselected[atoi(arg1)] == TRUE || atoi(arg1) == -1))
+		{
+			result = MakeShadow(arg2, arg3, arg4, arg5);
+#ifdef ENABLE_LOGGING
+			fprintf(logfile, "<WPSShadowAdd>,%s,%s,%s,%s,%s\r\n", arg2,arg3,arg4,arg5,result?result:"");
+#endif
+		}
+	}
+
+	/* Create Generic Objects */
+	if(strlen(INSTALLER_OBJECT)>0)
+	{
+        char *tmpptr = replaceem(INSTALLER_OBJECT);
+		strcpy(temp, tmpptr);
+		free(tmpptr);
+
+		argn=0;
+		arg1=&temp[0];
+		arg2=arg3=arg4=arg5=arg6=&zerotext[0];
+        len = strlen(temp);
+		for(z=0;z<len;z++)
+		{
+			if(temp[z]==',')
+			{
+				argn++;
+				temp[z]=0;
+				switch(argn)
+				{
+				case 1:
+					arg2=&temp[z+1];
+					break;
+				case 2:
+					arg3=&temp[z+1];
+					break;
+				case 3:
+					arg4=&temp[z+1];
+					break;
+				case 4:
+					arg5=&temp[z+1];
+					break;
+				case 5:
+					arg6=&temp[z+1];
+					break;
+				case 6:
+					argn=0;
+					if(atoi(arg1) > 0 && atoi(arg1) < 20 && (packagesselected[atoi(arg1)] == TRUE || atoi(arg1) == -1))
+					{
+						result = MakeObject(arg2, arg3, arg4, arg5, arg6);
+#ifdef ENABLE_LOGGING
+						fprintf(logfile, "<WPSObjectAdd>,%s,%s,%s,%s,%s,%s\r\n", arg2,arg3,arg4,arg5,arg6,result?result:"");
+#endif
+					}
+					arg1=&temp[z+1];
+					arg2=arg3=arg4=arg5=arg6=&zerotext[0];
+					break;
+				}
+			}
+		}
+		if(arg6 && atoi(arg1) > 0 && atoi(arg1) < 20 && (packagesselected[atoi(arg1)] == TRUE || atoi(arg1) == -1))
+		{
+			result = MakeObject(arg2, arg3, arg4, arg5, arg6);
+#ifdef ENABLE_LOGGING
+			fprintf(logfile, "<WPSObjectAdd>,%s,%s,%s,%s,%s,%s\r\n", arg2, arg3,arg4,arg5,arg6,result?result:"");
+#endif
+		}
+	}
+}
+
+/*
+ * Reads a line from a file and returns it in raw.
+ */
+void getline(FILE *f, char *raw)
+{
+	memset(raw, 0, 256);
+	fgets(raw, 255, f);
+    stripcrlf(raw);
+}
+
+/*
+ * Removes a character from a buffer by advancing the buffer to the left.
+ */
+void removechar(char *buffer, int thisone, int len)
+{
+	int x;
+
+	for(x=thisone;x<len;x++)
+        buffer[x] = buffer[x+1];
+}
+
+/*
+ * Breaks up a line in raw into it's components.
+ */
+void parseline(char *raw, char comment, char delimiter, char quotes, char *entry, char *entrydata, char *entrydata2)
+{
+    char in[256];
+	int z, len, in_quotes = 0, entrynum=0, last = 0;
+
+	strcpy(entry, empty_string);
+	strcpy(entrydata, empty_string);
+	strcpy(entrydata2, empty_string);
+	strcpy(in, raw);
+
+	if(in[strlen(in)-1] == '\n')
+		in[strlen(in)-1] = 0;
+
+	if(in[0] != comment)
+	{
+        len=strlen(in);
+		for(z=0;z<len;z++)
+		{
+			if(!in_quotes && in[z] == delimiter)
+			{
+				in[z] = 0;
+                /* Strip any other delimiters */
+				z++;
+				while(in[z] == delimiter && z < len)
+					z++;
+                if(!entrynum)
+					strcpy(entry, in);
+				else
+				{
+					strcpy(entrydata, &in[last]);
+					strcpy(entrydata2, &in[z]);
+				}
+                last = z;
+				if(entrynum)
+					return;
+                entrynum++;
+			}
+			if(in[z] == quotes)
+			{
+				removechar(in, z, len);
+				z--;
+                len--;
+				if(in_quotes)
+					in_quotes = 0;
+				else
+					in_quotes = 1;
+			}
+		}
+		if(!entrynum)
+			strcpy(entry, in);
+		else
+			strcpy(entrydata, &in[last]);
+	}
+}
+
+/*
+ * Reads a line from the file and splits it up into it's components.
+ */
+void getparseline(FILE *f, char comment, char delimiter, char quotes, char *raw, char *entry, char *entrydata, char *entrydata2)
+{
+	getline(f, raw);
+    parseline(raw, comment, delimiter, quotes, entry, entrydata, entrydata2);
+}
+
+typedef struct _directory {
+	char *entry;
+	struct _directory *next;
+} Directory;
+
+Directory *DirRoot = NULL;
+
+/* Free the browser directory listing */
+void freedir(Directory *dir)
+{
+	Directory *tmp, *next;
+
+	tmp = dir;
+	dir = NULL;
+
+	while(tmp != NULL)
+	{
+		next = tmp->next;
+		if(tmp->entry)
+			free(tmp->entry);
+		free(tmp);
+		tmp=next;
+	}
+}
+
+void DWSIGNAL containerselect(HWND hwnd, char *text, void *data)
+{
+	if(text)
+	{
+		char tmpbuf[400];
+
+		if(strcmp(text, "..") != 0)
+		{
+            char c = browsedir[strlen(browsedir)-1];
+			if(c != '\\' && c != '/')
+				strcat(browsedir, DIRSEP);
+			strcat(browsedir, text);
+		}
+		else
+		{
+			int i;
+
+			for(i=strlen(browsedir);i>0;i--)
+			{
+				if(browsedir[i] == '\\' || browsedir[i] == '/')
+				{
+					browsedir[i] = 0;
+					if(browsedir[1] == ':' && strlen(installdir2) == 2)
+						strcat(browsedir, DIRSEP);
+					i=-1;
+				}
+			}
+		}
+		populatedir(hwnddir);
+		strcpy(tmpbuf, browsedir);
+		if(tmpbuf[strlen(tmpbuf)-1] != '\\')
+			strcat(tmpbuf, DIRSEP);
+		strcat(tmpbuf, instsuffix);
+		dw_window_set_text(hwndentry, tmpbuf);
+	}
+}
+
+/* This won't work on Unix so we will need some
+ * #ifdefs at some point.
+ */
+void dirappend(char *tmpbuf)
+{
+#ifdef __UNIX__
+	if(tmpbuf[strlen(tmpbuf)-1] != '/')
+		strcat(tmpbuf, "/");
+#else
+	if(tmpbuf[strlen(tmpbuf)-1] != '\\')
+		strcat(tmpbuf, "\\");
+#endif
+	strcat(tmpbuf, instsuffix);
+}
+
+void DWSIGNAL listboxselect(HWND hwnd, int item, void *data)
+{
+	char tmpbuf[_MAX_PATH+1];
+
+	strcpy(browsedir, "C:\\");
+	browsedir[0] = ('A'+drivelist[item])-1;
+	populatedir(hwnddir);
+	strcpy(tmpbuf, browsedir);
+	dirappend(tmpbuf);
+	dw_window_set_text(hwndentry, tmpbuf);
+}
+
+/* Determine last install location */
+void find_last_install(void)
+{
+	char tmpbuf[8196], *fileptr;
+	FILE *tmplf;
+	int linenum=0, found=-1, theend = 0, count = 0, z;
+
+	if((tmplf=fopen(instlog, "rb"))==NULL)
+		return;
+
+	while(!feof(tmplf))
+	{
+		fgets(tmpbuf, 8196, tmplf);
+		linenum++;
+		if(tmpbuf[0]=='[' && (char *)strstr(tmpbuf, INSTALLER_APPLICATION) != NULL && !feof(tmplf))
+		{
+			/* We don't care about the version so ignore it. */
+			fgets(tmpbuf, 8196, tmplf);
+			linenum++;
+			found=linenum;
+			theend = 0;
+		}
+		if(found != -1 && !theend && ((char *)strstr(tmpbuf, "<End>") != NULL || tmpbuf[0] == '['))
+			theend=linenum;
+	}
+	if(found != -1)
+	{
+		if(!theend)
+			theend = linenum;
+
+		rewind(tmplf);
+		for (z=0;z<found;z++)
+			fgets(tmpbuf, 8196, tmplf);
+
+		fileptr = tmpbuf;
+
+		while(!feof(tmplf) && count < (theend - found))
+		{
+			tmpbuf[0] = 0;
+			fgets(tmpbuf, 8196, tmplf);
+
+			/* Remove trailing CRLFs */
+			if(fileptr[strlen(fileptr)-1] == '\r' || fileptr[strlen(fileptr)-1] == '\n')
+				fileptr[strlen(fileptr)-1]=0;
+			if(fileptr[strlen(fileptr)-1] == '\r' || fileptr[strlen(fileptr)-1] == '\n')
+				fileptr[strlen(fileptr)-1]=0;
+
+			if((char *)strstr(fileptr, "<NewDir>") != NULL)
+			{
+				char *newinst = (char *)strchr(fileptr, ',')+1;
+
+				strcpy(installdir2, newinst);
+				fclose(tmplf);
+				return;
+			}
+
+			count++;
+		}
+	}
+	fclose(tmplf);
+}
+
+/*
+ * Configures the container window passed to it for use with populatedir()
+ */
+void setdir(HWND hwnd)
+{
+	if(!dw_filesystem_setup(hwnd, NULL, NULL, 0))
+		dw_messagebox("HandyFTP", DW_MB_OK | DW_MB_ERROR, "Error Creating Container!");
+
+	dw_signal_connect(hwnd, DW_SIGNAL_ITEM_ENTER, DW_SIGNAL_FUNC(containerselect), NULL);
+}
+
+/* Inserts the list of items into the directory listing */
+void drawdir(HWND hwnd)
+{
+	Directory *tmp;
+	int count = 0, z;
+	void *containerinfo;
+
+	tmp = DirRoot;
+
+	while(tmp != NULL)
+	{
+		count++;
+		tmp=tmp->next;
+	}
+	tmp = DirRoot;
+
+	containerinfo = dw_container_alloc(hwnd, count);
+
+	for(z=0;z<count;z++)
+	{
+		dw_filesystem_set_file(hwnd, containerinfo, z, tmp->entry, foldericon);
+		dw_container_set_row_title(containerinfo, z, tmp->entry);
+
+		tmp=tmp->next;
+	}
+
+	dw_container_insert(hwnd, containerinfo, count);
+
+	dw_container_optimize(hwnd);
+}
+
+/* Sort the directory list */
+void sortdir(void)
+{
+	Directory *tmp, **stem;
+	int working = TRUE;
+
+	while(working)
+	{
+		Directory *prev = NULL;
+		stem = &DirRoot;
+
+		tmp = DirRoot;
+
+		while(tmp)
+		{
+
+			if(prev)
+			{
+				if(strcasecmp(prev->entry, tmp->entry) > 0)
+				{
+					prev->next = tmp->next;
+					*stem = tmp;
+					tmp->next = prev;
+					tmp=NULL;
+				}
+				stem = &prev->next;
+			}
+			if(tmp)
+			{
+				if(!tmp->next)
+					return;
+				prev = tmp;
+				tmp = tmp->next;
+			}
+		}
+	}
+}
+
+/* Makes a copy of a path, but only to it's parent's directory */
+void copyparent(char *dest, char *src)
+{
+	int z, pos = -1, i = strlen(src);
+
+	if(i)
+	{
+		/* If the last character is / or \ and the path isn't
+		 * a root path ( "/" or "\" or "d:\" then remove the
+		 * ending / or \.
+		 */
+		if((src[1] != '/' && src[1] != '\\' && i > 1) ||
+		   ((src[1] == '/' || src[1] == '\\') && i > 3))
+		{
+			if(src[i-1] == '/' || src[i-1] == '\\')
+				src[i-1] = 0;
+		}
+
+		for(z=i-1;z>-1;z--)
+		{
+			if(src[z] == '/' || src[z] == '\\')
+			{
+				pos = z;
+				z = -1;
+			}
+		}
+		if(pos != -1)
+		{
+			/* If we are at the root make sure we include the last / or \ */
+			if(pos == 0)
+				pos = 1;
+			if(pos == 2 && src[1] == ':')
+				pos = 3;
+
+			strncpy(dest, src, pos);
+			dest[pos] = 0;
+		}
+	}
+}
+
+/*
+ * Reads the directory list from the directory specified in the global variable
+ * browserdir and populates the container window passed to it.
+ */
+void populatedir(HWND hwnd)
+{
+	Directory *tmp = DirRoot;
+	char tmpbuf[1024];
+	DIR *dir;
+	struct dirent *ent;
+	struct stat bleah;
+	static firsttime = 1;
+
+	DirRoot = NULL;
+
+	dw_container_clear(hwnd, TRUE);
+
+	if(firsttime)
+	{
+		find_last_install();
+		firsttime = 0;
+		getsuffix(installdir2);
+		copyparent(browsedir, installdir2);
+	}
+
+	freedir(tmp);
+	tmp = NULL;
+
+	if(strlen(browsedir) == 2 && browsedir[1] == ':')
+		strcat(browsedir, DIRSEP);
+
+	if(!(dir = opendir(browsedir)))
+		return;
+
+	while((ent = readdir(dir)) != 0)
+	{
+		if(strcmp(ent->d_name, ".") != 0)
+		{
+			strcpy(tmpbuf, browsedir);
+			if(tmpbuf[strlen(tmpbuf)-1] != '\\' && tmpbuf[strlen(tmpbuf)-1] != '/')
+				strcat(tmpbuf, DIRSEP);
+			strcat(tmpbuf, ent->d_name);
+
+			stat(tmpbuf, &bleah);
+
+			if(S_ISDIR(bleah.st_mode))
+			{
+				if(DirRoot == NULL)
+				{
+					DirRoot = (Directory *)malloc(sizeof(Directory));
+					tmp = DirRoot;
+				}
+				else
+				{
+					tmp->next = (Directory *)malloc(sizeof(Directory));
+					tmp = tmp->next;
+				}
+
+
+				tmp->entry = strdup(ent->d_name);
+
+				tmp->next=NULL;
+			}
+		}
+	}
+
+	closedir(dir);
+	sortdir();
+	drawdir(hwnd);
+}
+
+/* A generic callback function to handle freeing of memory when
+ * the user presses cancel in a dialog.
+ */
+void DWSIGNAL generic_cancel(HWND window, void *data)
+{
+	UserEntry *param = (UserEntry *)data;
+
+	if(param)
+	{
+		dw_window_destroy(param->window);
+		if(param->busy)
+			*param->busy = 0;
+		if(param->data)
+			free(param->data);
+		free(param);
+	}
+}
+
+void DWSIGNAL package_ok(HWND window, void *data)
+{
+	DWDialog *dialog = (DWDialog *)data;
+	UserEntry *param = (UserEntry *)dialog->data;
+	HWND *handles = (HWND *)param->data;
+	int i, j, count = 0;
+
+	for(j=1;j<INSTALLER_PACKAGE_COUNT;j++)
+		packagesselected[j] = FALSE;
+
+	i = dw_listbox_selected_multi(handles[0], -1);
+
+	while(i != -1)
+	{
+		packagesselected[i+1] = TRUE;
+		i = dw_listbox_selected_multi(handles[0], i);
+	}
+
+	for(j=1;j<INSTALLER_PACKAGE_COUNT;j++)
+	{
+		if(packagesselected[j] == TRUE)
+			count++;
+	}
+
+	if(count == 0)
+		packagechosen=FALSE;
+	else
+		packagechosen=TRUE;
+	dw_dialog_dismiss(dialog, (void *)0);
+	dw_window_destroy(param->window);
+	free(param);
+}
+
+void DWSIGNAL package_cancel(HWND window, void *data)
+{
+	DWDialog *dialog = (DWDialog *)data;
+	UserEntry *param = (UserEntry *)dialog->data;
+
+	dw_dialog_dismiss(dialog, (void *)1);
+	dw_window_destroy(param->window);
+	free(param);
+}
+
+void DWSIGNAL package_all(HWND window, void *data)
+{
+	DWDialog *dialog = (DWDialog *)data;
+	UserEntry *param = (UserEntry *)dialog->data;
+	HWND *handles = (HWND *)param->data;
+	int j;
+
+	for(j=0;j<INSTALLER_PACKAGE_COUNT;j++)
+		dw_listbox_select(handles[0], j, TRUE);
+}
+
+void DWSIGNAL package_none(HWND window, void *data)
+{
+	DWDialog *dialog = (DWDialog *)data;
+	UserEntry *param = (UserEntry *)dialog->data;
+	HWND *handles = (HWND *)param->data;
+	int j;
+
+	for(j=0;j<INSTALLER_PACKAGE_COUNT;j++)
+		dw_listbox_select(handles[0], j, FALSE);
+}
+
+void DWSIGNAL package_dialog_create(void *data)
+{
+	HWND entrywindow, mainbox, okbutton, cancelbutton, allbutton, nonebutton,
+		listbox, xbox, *handles = malloc(6 * sizeof(HWND));
+	UserEntry *param = malloc(sizeof(UserEntry));
+	ULONG flStyle = DW_FCF_TITLEBAR | DW_FCF_SHELLPOSITION | DW_FCF_SIZEBORDER;
+	DWDialog **dialog = (DWDialog **)data;
+	int j;
+
+	entrywindow = dw_window_new(HWND_DESKTOP, "Package Selection", flStyle);
+
+	xbox = dw_box_new(BOXHORZ, 0);
+
+	dw_box_pack_start(entrywindow, xbox, 0, 0, TRUE, TRUE, 0);
+
+	/* Buttons */
+	mainbox = dw_box_new(BOXVERT,0);
+
+	dw_box_pack_start(xbox, mainbox, 100, 75, FALSE, TRUE, 4);
+
+	okbutton = dw_button_new("Ok", 1001L);
+
+	dw_box_pack_start(mainbox, okbutton, 100, 30, FALSE, FALSE, 4);
+
+	cancelbutton = dw_button_new("Cancel", 1002L);
+
+	dw_box_pack_start(mainbox, cancelbutton, 100, 30, FALSE, FALSE, 4);
+
+	allbutton = dw_button_new("Select All", 1003L);
+
+	dw_box_pack_start(mainbox, allbutton, 100, 30, FALSE, FALSE, 4);
+
+	nonebutton = dw_button_new("Select None", 1003L);
+
+	dw_box_pack_start(mainbox, nonebutton, 100, 30, FALSE, FALSE, 4);
+
+	/* Pack in some blank space */
+	dw_box_pack_start(mainbox, 0, 10, 10, TRUE, TRUE, 0);
+
+	handles[0] = listbox = dw_listbox_new(0L, TRUE);
+
+	dw_box_pack_start(xbox, listbox, 10, 10, TRUE,TRUE, 4);
+
+	param->window = entrywindow;
+	param->filename = NULL;
+	param->data = (void *)handles;
+	param->busy = 0;
+
+	*dialog = dw_dialog_new(param);
+
+	dw_signal_connect(okbutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(package_ok), (void *)*dialog);
+	dw_signal_connect(cancelbutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(package_cancel), (void *)*dialog);
+	dw_signal_connect(allbutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(package_all), (void *)*dialog);
+	dw_signal_connect(nonebutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(package_none), (void *)*dialog);
+
+	for(j=1;j<INSTALLER_PACKAGE_COUNT;j++)
+		dw_listbox_append(listbox, INSTALLER_PACKAGES[j]);
+
+	dw_window_set_usize(entrywindow, 450, 350);
+
+	dw_window_show(entrywindow);
+
+}
+
+/* Package selection dialog */
+int package_dialog(void)
+{
+	DWDialog *dialog;
+
+	dw_window_function(hwndHidden, (void *)package_dialog_create, (void *)&dialog);
+
+	return (int)dw_dialog_wait(dialog);
+}
+
+
+/*
+ * Create the readme file dialog.
+ */
+void DWSIGNAL readme(char *filename)
+{
+	HWND infowindow, mainbox, mle, okbutton, buttonbox;
+	UserEntry *param = malloc(sizeof(UserEntry));
+	ULONG flStyle = DW_FCF_SYSMENU | DW_FCF_TITLEBAR | DW_FCF_SIZEBORDER | DW_FCF_MINMAX |
+		DW_FCF_SHELLPOSITION | DW_FCF_TASKLIST | DW_FCF_DLGBORDER;
+	char *buffer;
+	ULONG point = -1;
+
+	infowindow = dw_window_new(HWND_DESKTOP, filename, flStyle);
+
+	mainbox = dw_box_new(BOXVERT, 5);
+
+	dw_box_pack_start(infowindow, mainbox, 150, 70, TRUE, TRUE, 0);
+
+	mle = dw_mle_new(100L);
+
+	dw_box_pack_start(mainbox, mle, 130, 350, TRUE, TRUE, 4);
+
+	dw_mle_set_word_wrap(mle, TRUE);
+
+	/* Buttons */
+	buttonbox = dw_box_new(BOXHORZ, 0);
+
+	dw_box_pack_start(mainbox, buttonbox, 0, 0, TRUE, FALSE, 0);
+
+	okbutton = dw_button_new("Ok", 1001L);
+
+	dw_box_pack_start(buttonbox, 0, 50, 30, TRUE, FALSE, 0);
+	dw_box_pack_start(buttonbox, okbutton, 50, 40, FALSE, FALSE, 2);
+	dw_box_pack_start(buttonbox, 0, 50, 30, TRUE, FALSE, 0);
+
+	param->window = infowindow;
+
+	buffer = grabimage(filename, NULL, 0);
+	if(buffer)
+	{
+		point = dw_mle_import(mle, buffer, point);
+		free(buffer);
+	}
+
+	param->data = NULL;
+	param->busy = NULL;
+
+	dw_signal_connect(okbutton, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(generic_cancel), (void *)param);
+
+	dw_window_set_usize(infowindow, 600, 400);
+
+	dw_mle_set(mle, 0);
+
+	dw_window_show(infowindow);
+}
+
+void update_percent(void)
+{
+	static int pixels = 0;
+	ULONG sliderpos = 0;
+
+	if(!no_update && files && (pixels = dw_percent_query_range(hwndper)))
+	{
+		sliderpos = (int)(((float)current_file/(float)files)*pixels);
+		dw_percent_set_pos(hwndper, sliderpos);
+	}
+}
+
+void DWSIGNAL finish_install(void *blah)
+{
+	if(installstate == COMPLETED)
+	{
+		if(strlen(INSTALLER_PROGRAM) > 0 || strlen(INSTALLER_FOLDER) > 0 || strlen(INSTALLER_SHADOW) >0)
+			if((strcasecmp(INSTALLER_CONFIRM_WPS, "no") == 0) || dw_messagebox(INSTALLER_TITLE, DW_MB_YESNO | DW_MB_QUESTION, "Do you wish to make icons on your desktop?"))
+				create_wps_objects();
+		if(strlen(INSTALLER_SETS) > 0 || strlen(INSTALLER_SYSVAR) > 0 || strlen(INSTALLER_SYSLINE) > 0)
+			if((strcasecmp(INSTALLER_CONFIRM_CONFIGSYS, "no") == 0) || dw_messagebox(INSTALLER_TITLE, DW_MB_YESNO | DW_MB_QUESTION, "Do you wish to add the required entries to your system?"))
+				configsys_update();
+		rexx_run(finishedscript);
+	}
+	else
+	{
+#ifdef ENABLE_LOGGING
+		if(dw_messagebox(INSTALLER_TITLE, DW_MB_YESNO | DW_MB_QUESTION, "Do you wish to delete the files that were already copied?"))
+		{
+			fprintf(logfile, "<Removed>\r\n<End>\r\n");
+			fclose(logfile);
+			delete_files();
+			current_file=0;
+			update_percent();
+		}
+#endif
+		exit(1);
+	}
+}
+
+/*
+ * Main function
+ */
+int main(int argc, char *argv[])
+{
+	dw_init(TRUE, argc, argv);
+
+	dialogx = dw_screen_width()/3;
+	dialogy = dw_screen_height()/3;
+
+	if((self = fopen(argv[0], "rb")) == NULL)
+	{
+		mesg("Could not open SFX archive for reading!");
+		exit(1);
+	}
+	if(loadheader() == FALSE)
+	{
+		mesg("Could not load all required variables!");
+		exit(3);
+	}
+	strcpy(installdir, INSTALLER_PATH);
+	getsuffix(INSTALLER_PATH);
+
+	foldericon = dw_icon_load(0,FOLDERICON);
+
+	getbootdrive();
+
+	hwndHidden = dw_window_new(HWND_DESKTOP, "InstallHidden", 0);
+
+	rexx_run("page1.cmd");
+
+	dw_main();
+
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install.def	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,3 @@
+NAME INSTALL WINDOWAPI
+DESCRIPTION "Self extracting Installer (C)'99-01 Brian Smith"
+STACKSIZE 51200
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,130 @@
+/* $Id: install.h,v 1.11 2003/11/22 06:17:05 bsmith Exp $ */
+
+#define I_DialogBeta 329
+#define I_Dialog1 330
+#define I_Dialog2 331
+#define I_Dialog3 332
+#define I_Dialog4 333
+#define I_Dialog5 334
+#define I_Dialog6 335
+#define I_Dialog7 336
+#define I_Dialog8 337
+#define I_Dialog9 338
+#define I_Dialog10 339
+#define I_Dialog11 340
+#define I_Dialog12 341
+
+#define I_Cancel 258
+#define I_Icon 261
+#define I_Logo 262
+#define I_Ja 265
+#define I_Nein 266
+#define I_Halt 267
+#define I_Alle 268
+#define I_Karte 269
+#define I_Confirm 270
+#define I_BMPWin 271
+#define I_Dest 300
+#define I_Text 301
+#define I_OK 304
+#define I_Cancel2 305
+#define I_Logo16 306
+
+#define NONE 0
+#define INSTALLING 1
+#define ABORTED 2
+#define COMPLETED 3
+
+#define UPDATE_ALWAYS 1
+#define UPDATE_NONEXIST 2
+
+#define DLG_PACKAGESTOINSTALL 305
+#define PACKAGES 306
+#define PB_SELECTALL 308
+#define PB_DESELECTALL 309
+#define DLG_SELECTINSTALLATIONDRIVE 311
+#define PB_OK 313
+#define PB_CANCEL 314
+#define DRIVELIST 312
+#define I_LOGO1 316
+#define I_LOGO2 317
+#define I_LOGO3 318
+#define I_LOGO4 319
+#define I_LOGO5 320
+#define I_LOGO6 321
+#define I_LOGO7 322
+#define I_LOGO8 323
+#define I_LOGOBETA 324
+
+/* These are static */
+#define I_Status 348
+#define I_Welcome 349
+
+/* Keep these in order... so we can loop */
+#define I_INFOBOX 355
+#define I_Info1 356
+#define I_Info2 357
+#define I_Info3 358
+#define I_README 359
+#define I_Licence 360
+#define I_Agree 361
+#define I_Updates1 362
+#define I_Updates2 363
+#define I_Updates4 364
+#define I_Updates3 365
+#define I_Dirs 366
+#define I_InstallDir 367
+#define I_Drives 368
+#define I_Percent 369
+#define I_Back 370
+#define I_Next 371
+#define I_Progress 372
+#define I_Grid 373
+#define I_MAX 374
+
+#define FILEICON 3800
+#define FOLDERICON 3810
+
+#define THREAD_STACK_SIZE 32768
+
+#ifndef RESOURCE_MAX
+/* Function prototypes */
+int installer_unpack(char * filename, int operation);
+void resetglobals(void);
+int detect(int argc, char *argv[]);
+void grabfile(char *filename);
+char *grabimage(char *filename, char *imagebuf, int size);
+void DWSIGNAL readme(char *filename);
+void install_thread(void *param);
+void setdir(HWND hwnd);
+void populatedir(HWND hwnd);
+void DWSIGNAL finish_install(void *blah);
+void update_percent(void);
+void DWSIGNAL listboxselect(HWND hwnd, int item, void *data);
+int package_dialog(void);
+void dirappend(char *tmpbuf);
+void getsuffix(char *path);
+
+typedef struct _replacements {
+	char *replacestring, *replacevar;
+} Replacements;
+
+typedef struct _RexxCommands {
+	int id;
+    char file[50];
+} RexxCommands;
+
+typedef struct _userentry {
+	HWND window, entryfield;
+	int page;
+	char *filename;
+	void *data;
+	HWND *busy;
+} UserEntry;
+
+#define COMMANDMAX 20
+
+/* from ftpapi.h */
+#define T_BINARY     3
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install.sh	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,42 @@
+#! /bin/sh
+#
+# Copyright (c) 1999 Marcel Moolenaar
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer 
+#    in this position and unchanged.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+#    derived from this software withough specific prior written permission
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# $FreeBSD: src/tools/install.sh,v 1.3 1999/12/15 18:08:56 marcel Exp $
+
+# parse install's options and ignore them completely.
+# XXX - not all options are recognised.
+while [ ! -z $1 ]; do
+    case $1 in
+    -C | -c | -D | -M | -p | -s) shift;;
+    -f | -g | -m | -o) shift; shift;;
+    *) break;
+    esac
+done
+
+# the remaining arguments are assumed to be files/dirs only.
+exec install -c -p $*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/instsup.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,781 @@
+/* $Id: instsup.c,v 1.30 2003/11/22 00:50:27 bsmith Exp $ */
+
+/*
+ *  instsup.c (c) 1999-2003 Brian Smith
+ */
+
+#include "dw.h"
+#include "compat.h"
+#ifdef __OS2__
+#include <direct.h>
+#include <process.h>
+#endif
+#ifdef __WIN32__
+#include <process.h>
+#include <shlobj.h>
+#include <objbase.h>
+#endif
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include "install.h"
+
+extern HWND mainhwnd;
+HWND hwndMLE = 0;
+extern char *INSTALLER_TITLE, *INSTALLER_APPLICATION, *INSTALLER_VERSION;
+extern char tempPath[], installdir[], csfile[], bufile[], bootdrive[], instlog[], browsedir[];
+extern int installstate, success;
+char *find_var(char *varname);
+int new_var(char *varname, char *data);
+
+FILE *self;
+
+char *replaceem(char *orig);
+
+/* This should return the current color depth */
+ULONG color_depth(void)
+{
+    return dw_color_depth();
+}
+
+/* This should return true for WinNT/2K/XP and false on Win9x */
+int IsWinNT(void);
+
+/*
+ * Call the reboot vector.
+ */
+void sys_reboot(void)
+{
+#ifdef __OS2__
+#define SYSFUNC               0xD5
+#define REBOOT                0xAB
+#define REBOOTDEV             "\\DEV\\DOS$"
+
+    APIRET rc;
+	HFILE  hREBOOT;
+	ULONG  ulAction;
+
+	rc = DosOpen(REBOOTDEV,
+				 &hREBOOT,
+				 &ulAction,
+				 0L,
+				 FILE_NORMAL,
+				 FILE_OPEN,
+				 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE,
+				 0L);
+	if (rc == 0)
+	{
+		DosDevIOCtl(hREBOOT,
+					SYSFUNC,
+					REBOOT,
+					NULL,
+					0L,
+					NULL,
+					NULL,
+					0L,
+					NULL);
+		DosClose(hREBOOT);
+	}
+#elif defined(__WIN32__)
+	if(IsWinNT())
+	{
+		HANDLE hToken;              /* handle to process token */
+		TOKEN_PRIVILEGES tkp;       /* pointer to token structure */
+
+		/* Get the current process token handle so we can get shutdown
+		 * privilege.
+		 */
+
+		if (!OpenProcessToken(GetCurrentProcess(),
+							  TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+			return;
+
+		/* Get the LUID for shutdown privilege. */
+
+		LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
+						 &tkp.Privileges[0].Luid);
+
+		tkp.PrivilegeCount = 1;  // one privilege to set
+		tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+ 
+		/* Get shutdown privilege for this process. */
+ 
+		AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
+							  (PTOKEN_PRIVILEGES) NULL, 0);
+	}
+
+	ExitWindowsEx(EWX_REBOOT, 0);
+#endif
+}
+
+#ifdef __UNIX__
+/*
+ * Converts a string to	upper case.
+ */
+char *strupr(char *blah)
+{
+	int z =	0;
+
+	while(blah[z])
+	{
+		blah[z]	= toupper(blah[z]);
+		z++;
+	}
+	return blah;
+}
+#endif
+
+int makedir(char *path)
+{
+#if defined(__IBMC__) || (defined(__WIN32__) && !defined(__CYGWIN32__))
+	return mkdir(path);
+#else
+	return mkdir(path,S_IRWXU);
+#endif
+}
+
+/*
+ * Display an informational dialog box to the user with the given text.
+ */
+int mesg(char *format, ...) {
+	va_list args;
+	char outbuf[4096];
+
+	va_start(args, format);
+	vsprintf(outbuf, format, args);
+	va_end(args);
+
+	dw_messagebox(INSTALLER_TITLE, DW_MB_OK | DW_MB_INFORMATION, outbuf);
+
+	return strlen(outbuf);
+}
+
+int checktext(char *text, char *buffer, int buflen)
+{
+	int z, len = strlen(text);
+
+	for(z=0;z<(buflen-len);z++)
+	{
+		if(memcmp(text, &buffer[z], len) == 0)
+			return z;
+	}
+	return -1;
+
+}
+
+/*
+ * Returns the offset withing the executable to the specified text.
+ */
+long findtext(char *text)
+{
+	char buffer[512];
+	int offset;
+	unsigned long curpos = 0;
+
+	fseek(self, 0, SEEK_SET);
+	fread(buffer, 1, 512, self);
+	if((offset = checktext(text, buffer, 512)) > -1)
+		return offset;
+	while(!feof(self))
+	{
+		memcpy(buffer, &buffer[256], 256);
+		fread(&buffer[256], 1, 256, self);
+		curpos += 256;
+		if((offset = checktext(text, buffer, 512)) > -1)
+			return offset+curpos;
+
+	}
+	return -1;
+}
+
+/* We encode archive search text so we don't get confused
+ * by the string table - I was using LXLite to take care
+ * of this problem on OS/2 but in portable code this may
+ * not be an option. */
+char *decode(char *input)
+{
+	char	*result;
+	int	i = 0;
+
+	result = (char *)malloc(strlen(input) / 2 + 1);
+
+	while (input[0] && input[1])
+	{
+		result[i] = ((input[0] - 0x41) << 4) | (input[1] - 0x41);
+		input += 2;
+		i++;
+	}
+	result[i] = '\0';
+
+	return result;
+}
+
+/*
+ * Removes any carriage returns or line feeds from the buffer.
+ */
+void stripcrlf(char *buffer)
+{
+	int z, len = strlen(buffer);
+
+	for(z=0;z<len;z++)
+	{
+		if(buffer[z] == '\r' || buffer[z] == '\n')
+		{
+			buffer[z] = 0;
+			return;
+		}
+	}
+}
+
+long double drivefree(int drive)
+{
+#if defined(__EMX__) || defined(__OS2__)
+	ULONG   aulFSInfoBuf[40] = {0};
+	APIRET  rc               = 0;
+
+	DosError(FERR_DISABLEHARDERR);
+	rc = DosQueryFSInfo(drive,
+						FSIL_ALLOC,
+						(PVOID)aulFSInfoBuf,
+						sizeof(aulFSInfoBuf));
+
+	DosError(FERR_ENABLEHARDERR);
+	if (rc != 0)
+		return 0;
+
+	return (long double)((double)aulFSInfoBuf[3] * (double)aulFSInfoBuf[1] * (double)aulFSInfoBuf[4]);
+#elif defined(__WIN32__) || defined(WINNT)
+	char buffer[10] = "C:\\";
+	DWORD spc, bps, fc, tc;
+
+	buffer[0] = drive + 'A' - 1;
+
+	/* Skip CD-ROM drives entirely */
+	if(GetDriveType(buffer) == DRIVE_CDROM)
+		return 0;
+
+	if(GetDiskFreeSpace(buffer, &spc, &bps, &fc, &tc) == 0)
+		return 0;
+
+	return (long double)((double)spc*(double)bps*(double)fc);
+#else
+	return 0;
+#endif
+}
+
+
+
+/*
+ * Display a fatal error message and set the abort flag in case we are in a secondary thread.
+ */
+void error(char *format, ...) {
+	va_list args;
+	char errstring[1024];
+
+	va_start(args, format);
+	vsprintf(errstring, format, args);
+	va_end(args);
+
+	if(installstate != ABORTED)
+	{
+		success=1;
+		installstate=ABORTED;
+	}
+	dw_messagebox(INSTALLER_TITLE, DW_MB_OK | DW_MB_ERROR, errstring);
+}
+
+void setdrivedir(char *drivedir)
+{
+#ifdef __OS2__
+	DosSetDefaultDisk((int)(toupper(drivedir[0])-'A'+1));
+	DosSetCurrentDir(drivedir);
+#elif defined(__WIN32__)
+	SetCurrentDirectory(drivedir);
+#else
+	chdir(drivedir);
+#endif
+}
+
+/*
+ * Make the TEMP directory the current directory, or the root directory of the boot drive.
+ */
+void settempdir(void)
+{
+#ifdef __UNIX__
+	strcpy(tempPath, "/tmp");
+#else
+	char *envdir = getenv("TMP");
+	int	len, freeme = 0;
+
+	if (!envdir)
+		envdir = getenv("TEMP");
+	if (!envdir)
+	{
+		envdir = replaceem("%BOOTDRIVE%:\\");
+		freeme = 1;
+	}
+	strcpy(tempPath,envdir);
+
+	if(freeme)
+		free(envdir);
+
+	len = strlen(tempPath);
+	if (len > 3 && tempPath[len-1] == '\\')
+		tempPath[len-1] = 0;
+	strupr(tempPath);
+#endif
+	setdrivedir(tempPath);
+}
+
+void getbootdrive(void)
+{
+#ifdef __OS2__
+	ULONG   ulSysInfo;
+
+	DosQuerySysInfo(QSV_BOOT_DRIVE,
+			QSV_BOOT_DRIVE,
+			(PVOID)&ulSysInfo,
+			sizeof(ULONG));
+
+	bootdrive[0]=installdir[0]=instlog[0]=csfile[0]=bufile[0]=browsedir[0]=(char)('A'+(ulSysInfo-1));
+#elif defined(__WIN32__)
+	char winpath[MAX_PATH+1] = "";
+
+	GetWindowsDirectory(winpath, MAX_PATH);
+
+	if(winpath[0] && winpath[1] == ':')
+	{
+		bootdrive[0]=installdir[0]=csfile[0]=bufile[0]=browsedir[0]=winpath[0];
+		strcpy(instlog, winpath);
+		if(instlog[strlen(instlog)-1] != '\\')
+			strcat(instlog, "\\");
+		strcat(instlog, "DBINST.LOG");
+	}
+#endif
+}
+
+/*
+ * Start an application using CMD.EXE.
+ */
+int cmdrun(char *progname)
+{
+#ifdef __OS2__
+	STARTDATA SData       = {0};
+	PSZ       PgmTitle    = "",
+		      PgmName     = "CMD.EXE";
+	APIRET    rc          = 0;
+	PID       pid         = 0;
+	ULONG     ulSessID    = 0;
+	CHAR      achObjBuf[256] = {0};
+	HQUEUE hqQueue;
+	REQUESTDATA rdRequest;
+	ULONG ulSzData;
+	BYTE bPriority;
+	PVOID pvData;
+
+	SData.Length  = sizeof(STARTDATA);
+	SData.Related = SSF_RELATED_CHILD;
+	SData.FgBg    = SSF_FGBG_BACK;
+	SData.TraceOpt = SSF_TRACEOPT_NONE;
+	SData.PgmTitle = PgmTitle;
+	SData.PgmName = PgmName;
+	SData.PgmInputs = progname;
+
+	SData.TermQ = "\\QUEUES\\CHILD.QUE";
+	SData.Environment = 0;
+	SData.InheritOpt = SSF_INHERTOPT_SHELL;
+	SData.SessionType = SSF_TYPE_WINDOWABLEVIO;
+    SData.IconFile = 0;
+	SData.PgmHandle = 0;
+
+	SData.PgmControl = SSF_CONTROL_INVISIBLE;
+	SData.Reserved = 0;
+	SData.ObjectBuffer = achObjBuf;
+	SData.ObjectBuffLen = (ULONG) sizeof(achObjBuf);
+
+	if(!(rc = DosCreateQueue(&hqQueue, QUE_FIFO | QUE_CONVERT_ADDRESS,"\\QUEUES\\CHILD.QUE")))
+	{
+		if(!(rc = DosStartSession(&SData, &ulSessID, &pid)))
+			if(!(rc=DosReadQueue(hqQueue, &rdRequest, &ulSzData, &pvData, 0, 0, &bPriority, 0)))
+				DosFreeMem(pvData);
+		DosCloseQueue(hqQueue);
+	}
+
+	if (rc != 0) {
+		mesg("Error %d while attempting to run %s!", rc, progname);
+		return 1;
+	}
+#endif
+	return 0;
+}
+
+void create_uninstall_object(void)
+{
+#ifdef __OS2__
+	char binpath[8096], *objectid = strdup(INSTALLER_APPLICATION);
+	int z;
+
+	WinCreateObject("WPFolder","Remove Programs","OBJECTID=<DBSOFT_UNINSTALL>","<WP_CONFIG>",CO_UPDATEIFEXISTS);
+
+	for(z=0;z<strlen(objectid);z++)
+	{
+		if(objectid[z] == ' ')
+			objectid[z] = '_';
+	}
+
+	sprintf(binpath, "EXENAME=%s\\dbuninst.exe;OBJECTID=<DBUNINST_%s>;PARAMETERS=\"%s\" %s", installdir, objectid, INSTALLER_APPLICATION, INSTALLER_VERSION);
+	WinCreateObject("WPProgram", INSTALLER_APPLICATION, binpath, "<DBSOFT_UNINSTALL>", CO_UPDATEIFEXISTS);
+	free(objectid);
+#elif defined(__WIN32__)
+	char keyname[1024];
+	HKEY hkey;
+
+	sprintf(keyname, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s", INSTALLER_APPLICATION);
+	if(RegCreateKey(HKEY_LOCAL_MACHINE, keyname, &hkey))
+		return;
+	if(RegSetValueEx(hkey, "DisplayName", 0, REG_EXPAND_SZ, (LPBYTE)INSTALLER_APPLICATION,
+						strlen(INSTALLER_APPLICATION) + 1))
+	{
+		RegCloseKey(hkey);
+		return;
+	}
+	sprintf(keyname, "%s\\dbuninst.exe \"%s\" %s", installdir, INSTALLER_APPLICATION,
+			INSTALLER_VERSION);
+	if(RegSetValueEx(hkey, "UninstallString", 0, REG_EXPAND_SZ, (LPBYTE)keyname,
+						strlen(keyname) + 1))
+	{
+		RegCloseKey(hkey);
+		return;
+	}
+	RegCloseKey(hkey);
+#endif
+}
+
+/*
+ * Makes a folder on the desktop.
+ */
+char *MakeFolder(char Title[], char Icon[], char dest[], char id[], char setup[])
+{
+#ifdef __OS2__
+	char szArg[200];
+
+	memset(szArg,0,sizeof(szArg));
+
+	if ((Icon != NULL) && (strlen(Icon) != 0))
+	{
+		strcat(szArg,"ICONFILE=");
+		strcat(szArg,Icon);
+	}
+
+	if ((id != NULL) && (strlen(id) != 0))
+	{
+		strcat(szArg,";OBJECTID=");
+		strcat(szArg,id);
+	}
+
+	if ((setup != NULL) && (strlen(setup) != 0))
+	{
+		strcat(szArg,";");
+		strcat(szArg,setup);
+	}
+
+	WinCreateObject("WPFolder",Title,szArg,dest,CO_UPDATEIFEXISTS);
+#elif defined(__WIN32__)
+	static char startpath[MAX_PATH];
+	LPITEMIDLIST  pidl;
+
+	if(!SHGetSpecialFolderLocation(NULL, CSIDL_PROGRAMS, &pidl))
+	{
+		char *realdest = find_var(dest);
+		int savelength;
+
+		SHGetPathFromIDList(pidl, startpath);
+		savelength = strlen(startpath);
+
+		if(startpath[strlen(startpath)-1] != '\\')
+		{
+			strcat(startpath, "\\");
+			savelength++;
+		}
+		if(realdest)
+		{
+			strcat(startpath, realdest);
+			if(startpath[strlen(startpath)-1] != '\\')
+				strcat(startpath, "\\");
+		}
+		strcat(startpath, Title);
+
+		new_var(id, &startpath[savelength]);
+		CreateDirectory(startpath, NULL);
+		return startpath;
+	}
+#else
+	static char startpath[_MAX_PATH];
+	char *home;
+
+	if((home = getenv("HOME")) != NULL)
+	{
+		char *realdest = find_var(dest);
+		int savelength;
+
+		strcpy(startpath, home);
+		if(startpath[strlen(startpath)-1] != '/')
+			strcat(startpath, "/");
+		strcat(startpath, "gnome-desktop/");
+		savelength = strlen(startpath);
+
+		if(realdest)
+		{
+			strcat(startpath, realdest);
+			if(startpath[strlen(startpath)-1] != '/')
+				strcat(startpath, "/");
+		}
+		strcat(startpath, Title);
+
+		new_var(id, &startpath[savelength]);
+		mkdir(startpath, 755);
+		return startpath;
+	}
+#endif
+	return NULL;
+}
+
+#ifdef __WIN32__
+HRESULT CreateLink(LPCSTR lpszPathObj, LPSTR lpszPathLink, LPSTR lpszDesc);
+#endif
+
+/*
+ * Makes a Program object on the desktop.
+ */
+char *MakeProgram(char Title[], char Program[], char Icon[], char dest[], char id[], char setup[])
+{
+#ifdef __OS2__
+	char szArg[200];
+
+	memset(szArg,0,sizeof(szArg));
+
+	strcat(szArg,"EXENAME=");
+	strcat(szArg,Program);
+
+	if ((Icon != NULL) && (strlen(Icon) != 0))
+	{
+		strcat(szArg,";ICONFILE=");
+		strcat(szArg,Icon);
+	}
+
+	if ((id != NULL) && (strlen(id) != 0))
+	{
+		strcat(szArg,";OBJECTID=");
+		strcat(szArg,id);
+	}
+
+	if ((setup != NULL) && (strlen(setup) != 0))
+	{
+		strcat(szArg,";");
+		strcat(szArg,setup);
+	}
+
+	WinCreateObject("WPProgram",Title,szArg,dest,CO_UPDATEIFEXISTS);
+#elif defined(__WIN32__)
+	static char startpath[MAX_PATH];
+	LPITEMIDLIST  pidl;
+
+	if(!SHGetSpecialFolderLocation(NULL, CSIDL_PROGRAMS, &pidl))
+	{
+		char *realdest = find_var(dest);
+
+		SHGetPathFromIDList(pidl, startpath);
+
+		if(realdest)
+		{
+			if(startpath[strlen(startpath)-1] != '\\')
+				strcat(startpath, "\\");
+			strcat(startpath, realdest);
+		}
+		if(startpath[strlen(startpath)-1] != '\\')
+			strcat(startpath, "\\");
+		strcat(startpath, Title);
+		strcat(startpath, ".lnk");
+
+		CoInitialize(NULL);
+		CreateLink(Program, startpath, Title);
+		CoUninitialize();
+		return startpath;
+	}
+#else
+	static char startpath[_MAX_PATH];
+	char *home;
+
+	if((home = getenv("HOME")) != NULL)
+	{
+		char *realdest = find_var(dest);
+		FILE *fp;
+
+		strcpy(startpath, home);
+		if(startpath[strlen(startpath)-1] != '/')
+			strcat(startpath, "/");
+		strcat(startpath, "gnome-desktop/");
+
+		if(realdest)
+		{
+			strcat(startpath, realdest);
+			if(startpath[strlen(startpath)-1] != '/')
+				strcat(startpath, "/");
+		}
+		strcat(startpath, Title);
+		strcat(startpath, ".desktop");
+
+		if((fp = fopen(startpath, "wt")) != NULL)
+		{
+			fprintf(fp, "[Desktop Entry]\nName=%s\nComment=%s\nExec=%s\n",
+					Title, Title, Program);
+			if(Icon && Icon[0])
+				fprintf(fp, "Icon=/usr/share/pixmaps/%s", Icon);
+			fprintf(fp, "Terminal=false\nType=Application\n");
+			fclose(fp);
+		}
+		return startpath;
+	}
+#endif
+	return NULL;
+}
+/*
+ * Makes a user defined object on the desktop.
+ */
+char *MakeObject(char Title[], char oclass[], char dest[], char id[], char setup[])
+{
+#ifdef __OS2__
+	char szArg[200];
+
+	memset(szArg,0,sizeof(szArg));
+
+	if ((oclass == NULL) || (strlen(oclass) == 0))
+		return NULL;
+
+	if ((id != NULL) && (strlen(id) != 0))
+	{
+		strcat(szArg,"OBJECTID=");
+		strcat(szArg,id);
+	}
+
+	if ((setup != NULL) && (strlen(setup) != 0))
+	{
+		if ((id != NULL) && (strlen(id) != 0))
+			strcat(szArg,";");
+		strcat(szArg,setup);
+	}
+
+	WinCreateObject(oclass,Title,szArg,dest,CO_UPDATEIFEXISTS);
+#elif defined(WIN32)
+    /* Not sure if there is an equivilent on Windows */
+#else
+	/* Unix? */
+#endif
+	return NULL;
+}
+
+/*
+ * Makes a shadow on the desktop.
+ */
+char *MakeShadow(char Title[], char reference[], char dest[], char id[])
+{
+#ifdef __OS2__
+	char szArg[400];
+
+	memset(szArg,0,sizeof(szArg));
+
+	strcpy(szArg,"SHADOWID=");
+	strcat(szArg,reference);
+	if ((id != NULL) && (strlen(id) != 0))
+	{
+		strcat(szArg,";OBJECTID=");
+		strcat(szArg,id);
+	}
+    strcat(szArg,";");
+	WinCreateObject("WPShadow",Title,szArg,dest,CO_UPDATEIFEXISTS);
+#elif defined(WIN32)
+	/* This isn't really the same thing but we'll create
+	 * a shortcut for shadows as well.
+	 */
+	static char startpath[MAX_PATH];
+	LPITEMIDLIST  pidl;
+
+	if(!SHGetSpecialFolderLocation(NULL, CSIDL_PROGRAMS, &pidl))
+	{
+		char *realdest = find_var(dest);
+
+		SHGetPathFromIDList(pidl, startpath);
+
+		if(realdest)
+		{
+			if(startpath[strlen(startpath)-1] != '\\')
+				strcat(startpath, "\\");
+			strcat(startpath, realdest);
+		}
+		if(startpath[strlen(startpath)-1] != '\\')
+			strcat(startpath, "\\");
+		strcat(startpath, Title);
+		strcat(startpath, ".lnk");
+
+		CoInitialize(NULL);
+		CreateLink(reference, startpath, Title);
+		CoUninitialize();
+		return startpath;
+	}
+#else
+	static char startpath[_MAX_PATH];
+	char *home;
+
+	if((home = getenv("HOME")) != NULL)
+	{
+		char *realdest = find_var(dest);
+		FILE *fp;
+
+		strcpy(startpath, home);
+		if(startpath[strlen(startpath)-1] != '/')
+			strcat(startpath, "/");
+		strcat(startpath, "gnome-desktop/");
+
+		if(realdest)
+		{
+			strcat(startpath, realdest);
+			if(startpath[strlen(startpath)-1] != '/')
+				strcat(startpath, "/");
+		}
+		strcat(startpath, Title);
+		strcat(startpath, ".desktop");
+
+		if((fp = fopen(startpath, "wt")) != NULL)
+		{
+			fprintf(fp, "[Desktop Entry]\nName=%s\nComment=%s\nExec=%s\n",
+					Title, Title, reference);
+			fprintf(fp, "Terminal=false\nType=Application\n");
+			fclose(fp);
+		}
+		return startpath;
+	}
+#endif
+	return NULL;
+}
+
+void PM_backslash(
+	char *s)
+{
+	unsigned int pos = strlen(s);
+	if (s[pos-1] != '\\') {
+		s[pos] = '\\';
+		s[pos+1] = '\0';
+		}
+}
+
+void DoGUI(void)
+{
+    update_percent();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/instsup.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,48 @@
+/* $Id: instsup.h,v 1.9 2003/11/21 21:44:21 bsmith Exp $ */
+
+ULONG color_depth(void);
+void sys_reboot(void);
+int makedir(char *path);
+int mesg(char *format, ...);
+int checktext(char *text, char *buffer, int buflen);
+long findtext(char *text);
+char *decode(char *input);
+void stripcrlf(char *buffer);
+long double drivefree(int drive);
+void error(char *format, ...);
+void setdrivedir(char *drivedir);
+void settempdir(void);
+void getbootdrive(void);
+int cmdrun(char *progname);
+char *MakeFolder(char Title[], char Icon[], char dest[], char id[], char setup[]);
+char *MakeProgram(char Title[], char Program[], char Icon[], char dest[], char id[], char setup[]);
+char *MakeObject(char Title[], char oclass[], char dest[], char id[], char setup[]);
+char *MakeShadow(char Title[], char reference[], char dest[], char id[]);
+void PM_backslash(char *s);
+void DoGUI(void);
+void create_uninstall_object(void);
+#ifdef __UNIX__
+char *strupr(char *blah);
+#endif
+
+/* There are actually in rexx.c but they are the only two entry points. */
+void rexx_init(void);
+void rexx_deinit(void);
+int rexx_run(char *filename);
+
+#ifdef __INSTSUP_PRIVATE__
+typedef struct _rexx_var
+{
+	struct _rexx_var	*next;
+	RXSTRING			rxstring;
+	char			*varname;
+} RexxVar;
+#endif
+
+#ifndef DIRSEP
+#if defined(__EMX__) || defined(__IBMC__) || defined(__WIN32__) || defined(WINNT)
+#define DIRSEP "\\"
+#else
+#define DIRSEP "/"
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/license.txt	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,22 @@
+Copyright Information About Installer.
+
+1998-2003 Brian Smith <dbsoft@technologist.com>
+2000 Achim Hasenmueller <achimha@innotek.de>
+2000 Peter Nielsen <peter@pmview.com>
+2003 Mark Hessling <m.hessling@qut.edu.au>
+1998 Sergey I. Yevtushenko
+
+Includes Infozip and Unace under their own licensing terms.
+
+This license allows you to use this source code in any way you wish, given the
+following restrictions:
+
+Source code must keep the copyrights.
+Entities using the source code must acknowledge Dynamic Windows contributors.
+(either passively when queried or actively by acknowledgements in the program)
+The following are not allowed to use Dynamic Windows in a commercial product:
+
+F/X Communications
+Any entity associated with Bjarne Jensen
+
+
Binary file os2/bitmaps/file.ico has changed
Binary file os2/bitmaps/folder.ico has changed
Binary file os2/bitmaps/install.bmp has changed
Binary file os2/bitmaps/install.ico has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/os2/dirent.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,301 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "platform/dirent.h"
+#include <errno.h>
+
+/*#ifndef __EMX__ 
+#include <libx.h>
+#endif */
+
+#define INCL_DOSFILEMGR
+#define INCL_DOSERRORS
+#include <os2.h>
+
+# define FFBUF	FILEFINDBUF3
+# define Word	ULONG
+  /*
+   * LS20 recommends a request count of 100, but according to the
+   * APAR text it does not lead to missing files, just to funny
+   * numbers of returned entries.
+   *
+   * LS30 HPFS386 requires a count greater than 2, or some files
+   * are missing (those starting with a character less that '.').
+   *
+   * Novell looses entries which overflow the buffer. In previous
+   * versions of dirent2, this could have lead to missing files
+   * when the average length of 100 directory entries was 40 bytes
+   * or more (quite unlikely for files on a Novell server).
+   *
+   * Conclusion: Make sure that the entries all fit into the buffer
+   * and that the buffer is large enough for more than 2 entries
+   * (each entry is at most 300 bytes long). And ignore the LS20
+   * effect.
+   */
+# define Count	25
+# define BufSz	(25 * (sizeof(FILEFINDBUF3)+1))
+
+#if defined(__IBMC__) || defined(__IBMCPP__)
+  #define error(rc) _doserrno = rc, errno = EOS2ERR
+#else
+  #define error(rc) errno = 255
+#endif
+
+struct _dirdescr {
+	HDIR		handle;		/* DosFindFirst handle */
+	char		fstype;		/* filesystem type */
+	Word		count;		/* valid entries in <ffbuf> */
+	long		number;		/* absolute number of next entry */
+	int		index;		/* relative number of next entry */
+	FFBUF *		next;		/* pointer to next entry */
+	char		name[MAXPATHLEN+3]; /* directory name */
+	unsigned	attrmask;	/* attribute mask for seekdir */
+	struct dirent	entry;		/* buffer for directory entry */
+	BYTE		ffbuf[BufSz];
+};
+
+/*
+ * Return first char of filesystem type, or 0 if unknown.
+ */
+static char
+getFSType(const char *path)
+{
+	static char cache[1+26];
+	char drive[3], info[512];
+	Word unit, infolen;
+	char r;
+
+	if (isalpha(path[0]) && path[1] == ':') {
+		unit = toupper(path[0]) - '@';
+		path += 2;
+	} else {
+		ULONG driveMap;
+		if (DosQueryCurrentDisk(&unit, &driveMap))
+			return 0;
+	}
+
+	if ((path[0] == '\\' || path[0] == '/')
+	 && (path[1] == '\\' || path[1] == '/'))
+		return 0;
+
+	if (cache [unit])
+		return cache [unit];
+
+	drive[0] = '@' + unit;
+	drive[1] = ':';
+	drive[2] = '\0';
+	infolen = sizeof info;
+	if (DosQueryFSAttach(drive, 0, FSAIL_QUERYNAME, (PVOID)info, &infolen))
+		return 0;
+	if (infolen >= sizeof(FSQBUFFER2)) {
+		FSQBUFFER2 *p = (FSQBUFFER2 *)info;
+		r = p->szFSDName[p->cbName];
+	} else
+		r = 0;
+	return cache [unit] = r;
+}
+
+char *
+_abs_path(const char *name, char *buffer, int len)
+{
+	char buf[4];
+	if (isalpha(name[0]) && name[1] == ':' && name[2] == '\0') {
+		buf[0] = name[0];
+		buf[1] = name[1];
+		buf[2] = '.';
+		buf[3] = '\0';
+		name = buf;
+	}
+	if (DosQueryPathInfo((PSZ)name, FIL_QUERYFULLNAME, buffer, len))
+		return NULL;
+	return buffer;
+}
+
+DIR *
+_openxdir(const char *path, unsigned att_mask)
+{
+	DIR *dir;
+	char name[MAXPATHLEN+3];
+	Word rc;
+
+	if(!path)
+		return NULL;
+
+	dir = malloc(sizeof(DIR));
+	if (dir == NULL) {
+		errno = ENOMEM;
+		return NULL;
+	}
+
+	strncpy(name, path, MAXPATHLEN);
+	name[MAXPATHLEN] = '\0';
+	switch (name[strlen(name)-1]) {
+	default:
+		strcat(name, "\\");
+	case '\\':
+	case '/':
+	case ':':
+		;
+	}
+	strcat(name, ".");
+	if (!abs_path(name, dir->name, MAXPATHLEN+1))
+		strcpy(dir->name, name);
+	if (dir->name[strlen(dir->name)-1] == '\\')
+		strcat(dir->name, "*");
+	else
+		strcat(dir->name, "\\*");
+
+	dir->fstype = getFSType(dir->name);
+	dir->attrmask = att_mask | A_DIR;
+
+	dir->handle = HDIR_CREATE;
+	dir->count = 100;
+	rc = DosFindFirst(dir->name, &dir->handle, dir->attrmask,
+		dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD);
+	switch (rc) {
+	default:
+		free(dir);
+		error(rc);
+		return NULL;
+	case NO_ERROR:
+	case ERROR_NO_MORE_FILES:
+		;
+	}
+
+	dir->number = 0;
+	dir->index = 0;
+	dir->next = (FFBUF *)dir->ffbuf;
+
+	return (DIR *)dir;
+}
+
+DIR *
+_opendir(const char *pathname)
+{
+	return openxdir(pathname, 0);
+}
+
+struct dirent *
+_readdir(DIR *dir)
+{
+	static int dummy_ino = 2;
+
+	if (dir->index == dir->count) {
+		Word rc;
+		dir->count = 100;
+		rc = DosFindNext(dir->handle, dir->ffbuf,
+			sizeof dir->ffbuf, &dir->count);
+		if (rc) {
+			error(rc);
+			return NULL;
+		}
+
+		dir->index = 0;
+		dir->next = (FFBUF *)dir->ffbuf;
+	}
+
+	if (dir->index == dir->count)
+		return NULL;
+
+	memcpy(dir->entry.d_name, dir->next->achName, dir->next->cchName);
+	dir->entry.d_name[dir->next->cchName] = '\0';
+	dir->entry.d_ino = dummy_ino++;
+	dir->entry.d_reclen = dir->next->cchName;
+	dir->entry.d_namlen = dir->next->cchName;
+	dir->entry.d_size = dir->next->cbFile;
+	dir->entry.d_attribute = dir->next->attrFile;
+	dir->entry.d_time = *(USHORT *)&dir->next->ftimeLastWrite;
+	dir->entry.d_date = *(USHORT *)&dir->next->fdateLastWrite;
+
+	switch (dir->fstype) {
+	case 'F': /* FAT */
+	case 'C': /* CDFS */
+		if (dir->next->attrFile & FILE_DIRECTORY)
+			strupr(dir->entry.d_name);
+		else
+			strlwr(dir->entry.d_name);
+	}
+
+	dir->next = (FFBUF *)((BYTE *)dir->next + dir->next->oNextEntryOffset);
+	++dir->number;
+	++dir->index;
+
+	return &dir->entry;
+}
+
+long
+_telldir(DIR *dir)
+{
+	return dir->number;
+}
+
+void
+_seekdir(DIR *dir, long off)
+{
+	if (dir->number > off) {
+		char name[MAXPATHLEN+2];
+		Word rc;
+
+		DosFindClose(dir->handle);
+
+		strcpy(name, dir->name);
+		strcat(name, "*");
+
+		dir->handle = HDIR_CREATE;
+		dir->count = 32767;
+		rc = DosFindFirst(name, &dir->handle, dir->attrmask,
+			dir->ffbuf, sizeof dir->ffbuf, &dir->count, FIL_STANDARD);
+		switch (rc) {
+		default:
+			error(rc);
+			return;
+		case NO_ERROR:
+		case ERROR_NO_MORE_FILES:
+			;
+		}
+
+		dir->number = 0;
+		dir->index = 0;
+		dir->next = (FFBUF *)dir->ffbuf;
+	}
+
+	while (dir->number < off && readdir(dir))
+		;
+}
+
+void
+_closedir(DIR *dir)
+{
+	DosFindClose(dir->handle);
+	free(dir);
+}
+
+/*****************************************************************************/
+
+#ifdef TEST
+
+main(int argc, char **argv)
+{
+	int i;
+	DIR *dir;
+	struct dirent *ep;
+
+	for (i = 1; i < argc; ++i) {
+		dir = opendir(argv[i]);
+		if (!dir)
+			continue;
+		while (ep = readdir(dir))
+			if (strchr("\\/:", argv[i] [strlen(argv[i]) - 1]))
+				printf("%s%s\n", argv[i], ep->d_name);
+			else
+				printf("%s/%s\n", argv[i], ep->d_name);
+		closedir(dir);
+	}
+
+	return 0;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/os2/dw.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,8853 @@
+/*
+ * Dynamic Windows:
+ *          A GTK like implementation of the PM GUI
+ *
+ * (C) 2000-2003 Brian Smith <dbsoft@technologist.com>
+ * (C) 2000 Achim Hasenmueller <achimha@innotek.de>
+ * (C) 2000 Peter Nielsen <peter@pmview.com>
+ * (C) 1998 Sergey I. Yevtushenko (some code borrowed from cell toolkit)
+ *
+ */
+#define INCL_DOS
+#define INCL_DOSERRORS
+#define INCL_WIN
+#define INCL_GPI
+
+#include <os2.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <process.h>
+#include <time.h>
+#include <io.h>
+#ifndef __EMX__
+#include <direct.h>
+#endif
+#include <sys/time.h>
+#include "dw.h"
+
+#define QWP_USER 0
+
+MRESULT EXPENTRY _run_event(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2);
+void _do_resize(Box *thisbox, int x, int y);
+void _handle_splitbar_resize(HWND hwnd, float percent, int type, int x, int y);
+int _load_bitmap_file(char *file, HWND handle, HBITMAP *hbm, HDC *hdc, HPS *hps, unsigned long *width, unsigned long *height);
+void _dw_box_pack_start(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad, char *functionname);
+void _dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad, char *functionname);
+void _free_menu_data(HWND menu);
+
+char ClassName[] = "dynamicwindows";
+char SplitbarClassName[] = "dwsplitbar";
+char *DefaultFont = "9.WarpSans";
+
+HAB dwhab = 0;
+HMQ dwhmq = 0;
+DWTID _dwtid = 0;
+LONG _foreground = 0xAAAAAA, _background = DW_CLR_DEFAULT;
+
+HWND hwndApp = NULLHANDLE, hwndBubble = NULLHANDLE, hwndBubbleLast = NULLHANDLE, hwndEmph = NULLHANDLE;
+PRECORDCORE pCore = NULL, pCoreEmph = NULL;
+ULONG aulBuffer[4];
+HWND lasthcnr = 0, lastitem = 0, popup = 0, desktop;
+
+unsigned long _colors[] = {
+	CLR_BLACK,
+	CLR_DARKRED,
+	CLR_DARKGREEN,
+	CLR_BROWN,
+	CLR_DARKBLUE,
+	CLR_DARKPINK,
+	CLR_DARKCYAN,
+	CLR_PALEGRAY,
+	CLR_DARKGRAY,
+	CLR_RED,
+	CLR_GREEN,
+	CLR_YELLOW,
+	CLR_BLUE,
+	CLR_PINK,
+	CLR_CYAN,
+	CLR_WHITE
+};
+
+#define IS_WARP4() (aulBuffer[0] == 20 && aulBuffer[1] >= 40)
+
+#ifndef min
+#define min(a, b) (((a < b) ? a : b))
+#endif
+
+typedef struct _sighandler
+{
+	struct _sighandler	*next;
+	ULONG message;
+	HWND window;
+	int id;
+	void *signalfunction;
+	void *data;
+
+} SignalHandler;
+
+SignalHandler *Root = NULL;
+
+typedef struct
+{
+	ULONG message;
+	char name[30];
+
+} SignalList;
+
+/* List of signals and their equivilent OS/2 message */
+#define SIGNALMAX 16
+
+SignalList SignalTranslate[SIGNALMAX] = {
+	{ WM_SIZE,         DW_SIGNAL_CONFIGURE },
+	{ WM_CHAR,         DW_SIGNAL_KEY_PRESS },
+	{ WM_BUTTON1DOWN,  DW_SIGNAL_BUTTON_PRESS },
+	{ WM_BUTTON1UP,    DW_SIGNAL_BUTTON_RELEASE },
+	{ WM_MOUSEMOVE,    DW_SIGNAL_MOTION_NOTIFY },
+	{ WM_CLOSE,        DW_SIGNAL_DELETE },
+	{ WM_PAINT,        DW_SIGNAL_EXPOSE },
+	{ WM_COMMAND,      DW_SIGNAL_CLICKED },
+	{ CN_ENTER,        DW_SIGNAL_ITEM_ENTER },
+	{ CN_CONTEXTMENU,  DW_SIGNAL_ITEM_CONTEXT },
+	{ LN_SELECT,       DW_SIGNAL_LIST_SELECT },
+	{ CN_EMPHASIS,     DW_SIGNAL_ITEM_SELECT },
+	{ WM_SETFOCUS,     DW_SIGNAL_SET_FOCUS },
+	{ SLN_SLIDERTRACK, DW_SIGNAL_VALUE_CHANGED },
+	{ BKN_PAGESELECTED,DW_SIGNAL_SWITCH_PAGE },
+	{ CN_EXPANDTREE,   DW_SIGNAL_TREE_EXPAND }
+};
+
+/* This function adds a signal handler callback into the linked list.
+ */
+void _new_signal(ULONG message, HWND window, int id, void *signalfunction, void *data)
+{
+	SignalHandler *new = malloc(sizeof(SignalHandler));
+
+	new->message = message;
+	new->window = window;
+	new->id = id;
+	new->signalfunction = signalfunction;
+	new->data = data;
+	new->next = NULL;
+
+	if (!Root)
+		Root = new;
+	else
+	{
+		SignalHandler *prev = NULL, *tmp = Root;
+		while(tmp)
+		{
+			if(tmp->message == message &&
+			   tmp->window == window &&
+			   tmp->id == id &&
+			   tmp->signalfunction == signalfunction)
+			{
+				tmp->data = data;
+				free(new);
+				return;
+			}
+			prev = tmp;
+			tmp = tmp->next;
+		}
+		if(prev)
+			prev->next = new;
+		else
+			Root = new;
+	}
+}
+
+/* Finds the message number for a given signal name */
+ULONG _findsigmessage(char *signame)
+{
+	int z;
+
+	for(z=0;z<SIGNALMAX;z++)
+	{
+		if(stricmp(signame, SignalTranslate[z].name) == 0)
+			return SignalTranslate[z].message;
+	}
+	return 0L;
+}
+
+typedef struct _CNRITEM
+{
+	MINIRECORDCORE rc;
+	HPOINTER       hptrIcon;
+	PVOID          user;
+	HTREEITEM      parent;
+
+} CNRITEM, *PCNRITEM;
+
+
+int _null_key(HWND window, int key, void *data)
+{
+	window = window; /* keep compiler happy */
+	key = key; /* keep compiler happy */
+	data = data; /* keep compiler happy */
+	return TRUE;
+}
+
+/* Find the desktop window handle */
+HWND _toplevel_window(HWND handle)
+{
+	HWND box, lastbox = WinQueryWindow(handle, QW_PARENT);
+
+	/* Find the toplevel window */
+	while((box = WinQueryWindow(lastbox, QW_PARENT)) != desktop && box > 0)
+	{
+		lastbox = box;
+	}
+	if(box > 0)
+		return lastbox;
+	return handle;
+}
+
+
+/* A "safe" WinSendMsg() that tries multiple times in case the
+ * queue is blocked for one reason or another.
+ */
+MRESULT _dw_send_msg(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2, int failure)
+{
+	MRESULT res;
+	int z = 0;
+
+	while((int)(res = WinSendMsg(hwnd, msg, mp1, mp2)) == failure)
+	{
+		z++;
+		if(z > 5000000)
+			return (MRESULT)failure;
+		dw_main_sleep(1);
+	}
+	return res;
+}
+
+/* Return the entryfield child of a window */
+HWND _find_entryfield(HWND handle)
+{
+	HENUM henum;
+	HWND child, entry = 0;
+
+	henum = WinBeginEnumWindows(handle);
+	while((child = WinGetNextWindow(henum)) != NULLHANDLE)
+	{
+		char tmpbuf[100];
+
+		WinQueryClassName(child, 99, tmpbuf);
+
+		if(strncmp(tmpbuf, "#6", 3)==0)  /* Entryfield */
+		{
+			entry = child;
+			break;
+		}
+	}
+	WinEndEnumWindows(henum);
+	return entry;
+}
+
+/* This function changes the owner of buttons in to the
+ * dynamicwindows handle to fix a problem in notebooks.
+ */
+void _fix_button_owner(HWND handle, HWND dw)
+{
+	HENUM henum;
+	HWND child;
+
+	henum = WinBeginEnumWindows(handle);
+	while((child = WinGetNextWindow(henum)) != NULLHANDLE)
+	{
+		char tmpbuf[100];
+
+		WinQueryClassName(child, 99, tmpbuf);
+
+		if(strncmp(tmpbuf, "#3", 3)==0 && dw)  /* Button */
+			WinSetOwner(child, dw);
+		else if(strncmp(tmpbuf, "dynamicwindows", 14) == 0)
+			dw = child;
+
+		_fix_button_owner(child, dw);
+	}
+	WinEndEnumWindows(henum);
+	return;
+}
+
+/* Free bitmap data associated with a window */
+void _free_bitmap(HWND handle)
+{
+	HBITMAP hbm = (HBITMAP)dw_window_get_data(handle, "_dw_bitmap");
+	HPS hps = (HPS)dw_window_get_data(handle, "_dw_hps");
+	HDC hdc = (HDC)dw_window_get_data(handle, "_dw_hdc");
+	HPIXMAP pixmap = (HPIXMAP)dw_window_get_data(handle, "_dw_hpixmap");
+	HPIXMAP disable = (HPIXMAP)dw_window_get_data(handle, "_dw_hpixmap_disabled");
+
+	if(pixmap)
+		dw_pixmap_destroy(pixmap);
+
+	if(disable)
+		dw_pixmap_destroy(disable);
+
+	if(hps)
+	{
+		GpiSetBitmap(hps, NULLHANDLE);
+		GpiAssociate(hps, NULLHANDLE);
+		GpiDestroyPS(hps);
+	}
+
+	if(hdc)
+		DevCloseDC(hdc);
+
+	if(hbm)
+		GpiDeleteBitmap(hbm);
+}
+
+/* This function removes and handlers on windows and frees
+ * the user memory allocated to it.
+ */
+void _free_window_memory(HWND handle)
+{
+	HENUM henum;
+	HWND child;
+	void *ptr = (void *)WinQueryWindowPtr(handle, QWP_USER);
+
+	dw_signal_disconnect_by_window(handle);
+
+	if((child = WinWindowFromID(handle, FID_MENU)) != NULLHANDLE)
+		_free_menu_data(child);
+
+	if((child = WinWindowFromID(handle, FID_CLIENT)) != NULLHANDLE)
+	{
+		Box *box = (Box *)WinQueryWindowPtr(child, QWP_USER);
+
+		if(box)
+		{
+			if(box->count && box->items)
+				free(box->items);
+
+			WinSetWindowPtr(child, QWP_USER, 0);
+			free(box);
+		}
+	}
+
+	if(ptr)
+	{
+		WindowData *wd = (WindowData *)ptr;
+		char tmpbuf[100];
+
+		/* If this window has an associate bitmap destroy it. */
+		_free_bitmap(handle);
+
+		WinQueryClassName(handle, 99, tmpbuf);
+
+		if(strncmp(tmpbuf, "#1", 3)==0)
+		{
+			Box *box = (Box *)ptr;
+
+			if(box->count && box->items)
+				free(box->items);
+		}
+		else if(strncmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0)
+		{
+			void *data = dw_window_get_data(handle, "_dw_percent");
+
+			if(data)
+				free(data);
+		}
+		else if(strncmp(tmpbuf, "#37", 4)==0)
+		{
+			dw_container_clear(handle, FALSE);
+			if(wd && dw_window_get_data(handle, "_dw_container"))
+			{
+				void *oldflags = wd->data;
+
+				wd->data = NULL;
+				free(oldflags);
+			}
+		}
+
+		if(wd->oldproc)
+			WinSubclassWindow(handle, wd->oldproc);
+
+		dw_window_set_data(handle, NULL, NULL);
+		WinSetWindowPtr(handle, QWP_USER, 0);
+		free(ptr);
+	}
+
+	henum = WinBeginEnumWindows(handle);
+	while((child = WinGetNextWindow(henum)) != NULLHANDLE)
+		_free_window_memory(child);
+
+	WinEndEnumWindows(henum);
+	return;
+}
+
+void _free_menu_data(HWND menu)
+{
+	int i, count = (int)WinSendMsg(menu, MM_QUERYITEMCOUNT, 0, 0);
+
+	dw_signal_disconnect_by_name(menu, DW_SIGNAL_CLICKED);
+	_free_window_memory(menu);
+
+	for(i=0;i<count;i++)
+	{
+		SHORT menuid = (SHORT)WinSendMsg(menu, MM_ITEMIDFROMPOSITION, MPFROMSHORT(i), 0);
+		MENUITEM mi;
+
+		if(WinSendMsg(menu, MM_QUERYITEM, MPFROMSHORT(menuid), MPFROMP(&mi))
+		   && mi.hwndSubMenu)
+			_free_menu_data(mi.hwndSubMenu);
+	}
+}
+
+/* This function returns 1 if the window (widget) handle
+ * passed to it is a valid window that can gain input focus.
+ */
+int _validate_focus(HWND handle)
+{
+	char tmpbuf[100];
+
+	if(!handle)
+		return 0;
+
+	if(!WinIsWindowEnabled(handle) || dw_window_get_data(handle, "_dw_disabled"))
+		return 0;
+
+	WinQueryClassName(handle, 99, tmpbuf);
+
+	/* These are the window classes which can
+	 * obtain input focus.
+	 */
+	if(strncmp(tmpbuf, "#2", 3)==0 ||  /* Combobox */
+	   strncmp(tmpbuf, "#3", 3)==0 ||  /* Button */
+	   strncmp(tmpbuf, "#6", 3)==0 ||  /* Entryfield */
+	   strncmp(tmpbuf, "#7", 3)==0 ||  /* List box */
+	   strncmp(tmpbuf, "#10", 4)==0 || /* MLE */
+	   strncmp(tmpbuf, "#32", 4)==0 || /* Spinbutton */
+	   strncmp(tmpbuf, "#37", 4)==0 || /* Container */
+	   strncmp(tmpbuf, "#38", 4)== 0)  /* Slider */
+		return 1;
+	return 0;
+}
+
+int _focus_check_box(Box *box, HWND handle, int start, HWND defaultitem)
+{
+	int z, n;
+	static HWND lasthwnd, firsthwnd;
+    static int finish_searching;
+
+	/* Start is 2 when we have cycled completely and
+	 * need to set the focus to the last widget we found
+	 * that was valid.
+	 */
+	if(start == 2)
+	{
+		if(lasthwnd)
+			WinSetFocus(HWND_DESKTOP, lasthwnd);
+		return 0;
+	}
+
+	/* Start is 1 when we are entering the function
+	 * for the first time, it is zero when entering
+	 * the function recursively.
+	 */
+	if(start == 1)
+	{
+		lasthwnd = handle;
+		finish_searching = 0;
+		firsthwnd = 0;
+	}
+
+	for(n=0;n<box->count;n++)
+	{
+		/* Vertical boxes are inverted on OS/2 */
+		if(box->type == DW_VERT)
+			z = n;
+		else
+			z = box->count - n - 1;
+
+		if(box->items[z].type == TYPEBOX)
+		{
+			Box *thisbox = WinQueryWindowPtr(box->items[z].hwnd, QWP_USER);
+
+			if(thisbox && _focus_check_box(thisbox, handle, start == 3 ? 3 : 0, defaultitem))
+				return 1;
+		}
+		else
+		{
+			if(box->items[z].hwnd == handle)
+			{
+				if(lasthwnd == handle && firsthwnd)
+					WinSetFocus(HWND_DESKTOP, firsthwnd);
+				else if(lasthwnd == handle && !firsthwnd)
+					finish_searching = 1;
+				else
+					WinSetFocus(HWND_DESKTOP, lasthwnd);
+
+				/* If we aren't looking for the last handle,
+				 * return immediately.
+				 */
+				if(!finish_searching)
+					return 1;
+			}
+			if(_validate_focus(box->items[z].hwnd))
+			{
+				/* Start is 3 when we are looking for the
+				 * first valid item in the layout.
+				 */
+				if(start == 3)
+				{
+					if(!defaultitem || (defaultitem && defaultitem == box->items[z].hwnd))
+					{
+						WinSetFocus(HWND_DESKTOP, box->items[z].hwnd);
+						return 1;
+					}
+				}
+
+				if(!firsthwnd)
+					firsthwnd = box->items[z].hwnd;
+
+				lasthwnd = box->items[z].hwnd;
+			}
+			else
+			{
+				char tmpbuf[100] = "";
+
+				WinQueryClassName(box->items[z].hwnd, 99, tmpbuf);
+				if(strncmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0)
+				{
+					/* Then try the bottom or right box */
+					HWND mybox = (HWND)dw_window_get_data(box->items[z].hwnd, "_dw_bottomright");
+
+					if(mybox)
+					{
+						Box *splitbox = (Box *)WinQueryWindowPtr(mybox, QWP_USER);
+
+						if(splitbox && _focus_check_box(splitbox, handle, start == 3 ? 3 : 0, defaultitem))
+							return 1;
+					}
+
+					/* Try the top or left box */
+					mybox = (HWND)dw_window_get_data(box->items[z].hwnd, "_dw_topleft");
+
+					if(mybox)
+					{
+						Box *splitbox = (Box *)WinQueryWindowPtr(mybox, QWP_USER);
+
+						if(splitbox && _focus_check_box(splitbox, handle, start == 3 ? 3 : 0, defaultitem))
+							return 1;
+					}
+				}
+				else if(strncmp(tmpbuf, "#40", 4)==0) /* Notebook */
+				{
+					Box *notebox;
+					HWND page = (HWND)WinSendMsg(box->items[z].hwnd, BKM_QUERYPAGEWINDOWHWND,
+												 (MPARAM)dw_notebook_page_query(box->items[z].hwnd), 0);
+
+					if(page)
+					{
+						notebox = (Box *)WinQueryWindowPtr(page, QWP_USER);
+
+						if(notebox && _focus_check_box(notebox, handle, start == 3 ? 3 : 0, defaultitem))
+							return 1;
+					}
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+int _focus_check_box_back(Box *box, HWND handle, int start, HWND defaultitem)
+{
+	int z, n;
+	static HWND lasthwnd, firsthwnd;
+    static int finish_searching;
+
+	/* Start is 2 when we have cycled completely and
+	 * need to set the focus to the last widget we found
+	 * that was valid.
+	 */
+	if(start == 2)
+	{
+		if(lasthwnd)
+			WinSetFocus(HWND_DESKTOP, lasthwnd);
+		return 0;
+	}
+
+	/* Start is 1 when we are entering the function
+	 * for the first time, it is zero when entering
+	 * the function recursively.
+	 */
+	if(start == 1)
+	{
+		lasthwnd = handle;
+		finish_searching = 0;
+		firsthwnd = 0;
+	}
+
+	for(n=0;n<box->count;n++)
+	{
+		/* Vertical boxes are inverted on OS/2 */
+		if(box->type == DW_VERT)
+			z = box->count - n - 1;
+		else
+			z = n;
+
+		if(box->items[z].type == TYPEBOX)
+		{
+			Box *thisbox = WinQueryWindowPtr(box->items[z].hwnd, QWP_USER);
+
+			if(thisbox && _focus_check_box_back(thisbox, handle, start == 3 ? 3 : 0, defaultitem))
+				return 1;
+		}
+		else
+		{
+			if(box->items[z].hwnd == handle)
+			{
+				if(lasthwnd == handle && firsthwnd)
+					WinSetFocus(HWND_DESKTOP, firsthwnd);
+				else if(lasthwnd == handle && !firsthwnd)
+					finish_searching = 1;
+				else
+					WinSetFocus(HWND_DESKTOP, lasthwnd);
+
+				/* If we aren't looking for the last handle,
+				 * return immediately.
+				 */
+				if(!finish_searching)
+					return 1;
+			}
+			if(_validate_focus(box->items[z].hwnd))
+			{
+				/* Start is 3 when we are looking for the
+				 * first valid item in the layout.
+				 */
+				if(start == 3)
+				{
+					if(!defaultitem || (defaultitem && defaultitem == box->items[z].hwnd))
+					{
+						WinSetFocus(HWND_DESKTOP, box->items[z].hwnd);
+						return 1;
+					}
+				}
+
+				if(!firsthwnd)
+					firsthwnd = box->items[z].hwnd;
+
+				lasthwnd = box->items[z].hwnd;
+			}
+			else
+			{
+				char tmpbuf[100] = "";
+
+				WinQueryClassName(box->items[z].hwnd, 99, tmpbuf);
+				if(strncmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0)
+				{
+					/* Try the top or left box */
+					HWND mybox = (HWND)dw_window_get_data(box->items[z].hwnd, "_dw_topleft");
+
+					if(mybox)
+					{
+						Box *splitbox = (Box *)WinQueryWindowPtr(mybox, QWP_USER);
+
+						if(splitbox && _focus_check_box_back(splitbox, handle, start == 3 ? 3 : 0, defaultitem))
+							return 1;
+					}
+
+					/* Then try the bottom or right box */
+					mybox = (HWND)dw_window_get_data(box->items[z].hwnd, "_dw_bottomright");
+
+					if(mybox)
+					{
+						Box *splitbox = (Box *)WinQueryWindowPtr(mybox, QWP_USER);
+
+						if(splitbox && _focus_check_box_back(splitbox, handle, start == 3 ? 3 : 0, defaultitem))
+							return 1;
+					}
+				}
+				else if(strncmp(tmpbuf, "#40", 4)==0) /* Notebook */
+				{
+					Box *notebox;
+					HWND page = (HWND)WinSendMsg(box->items[z].hwnd, BKM_QUERYPAGEWINDOWHWND,
+												 (MPARAM)dw_notebook_page_query(box->items[z].hwnd), 0);
+
+					if(page)
+					{
+						notebox = (Box *)WinQueryWindowPtr(page, QWP_USER);
+
+						if(notebox && _focus_check_box_back(notebox, handle, start == 3 ? 3 : 0, defaultitem))
+							return 1;
+					}
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+/* This function finds the first widget in the
+ * layout and moves the current focus to it.
+ */
+int _initial_focus(HWND handle)
+{
+	Box *thisbox = NULL;
+	HWND box;
+
+	box = WinWindowFromID(handle, FID_CLIENT);
+	if(box)
+		thisbox = WinQueryWindowPtr(box, QWP_USER);
+	else
+		return 1;
+
+	if(thisbox)
+		_focus_check_box(thisbox, handle, 3, thisbox->defaultitem);
+	return 0;
+}
+
+/* This function finds the current widget in the
+ * layout and moves the current focus to the next item.
+ */
+void _shift_focus(HWND handle)
+{
+	Box *thisbox;
+	HWND box, lastbox = _toplevel_window(handle);
+
+	box = WinWindowFromID(lastbox, FID_CLIENT);
+	if(box)
+		thisbox = WinQueryWindowPtr(box, QWP_USER);
+	else
+		thisbox = WinQueryWindowPtr(lastbox, QWP_USER);
+
+	if(thisbox)
+	{
+		if(_focus_check_box(thisbox, handle, 1, 0)  == 0)
+			_focus_check_box(thisbox, handle, 2, 0);
+	}
+}
+
+/* This function finds the current widget in the
+ * layout and moves the current focus to the next item.
+ */
+void _shift_focus_back(HWND handle)
+{
+	Box *thisbox;
+	HWND box, lastbox = _toplevel_window(handle);
+
+	box = WinWindowFromID(lastbox, FID_CLIENT);
+	if(box)
+		thisbox = WinQueryWindowPtr(box, QWP_USER);
+	else
+		thisbox = WinQueryWindowPtr(lastbox, QWP_USER);
+
+	if(thisbox)
+	{
+		if(_focus_check_box_back(thisbox, handle, 1, 0)  == 0)
+			_focus_check_box_back(thisbox, handle, 2, 0);
+	}
+}
+
+/* This function will recursively search a box and add up the total height of it */
+void _count_size(HWND box, int type, int *xsize, int *xorigsize)
+{
+	int size = 0, origsize = 0, z;
+	Box *tmp = WinQueryWindowPtr(box, QWP_USER);
+
+	if(!tmp)
+	{
+		*xsize = *xorigsize = 0;
+		return;
+	}
+
+	if(type == tmp->type)
+	{
+		/* If the box is going in the direction we want, then we
+		 * return the entire sum of the items.
+		 */
+		for(z=0;z<tmp->count;z++)
+		{
+			if(tmp->items[z].type == TYPEBOX)
+			{
+				int s, os;
+
+				_count_size(tmp->items[z].hwnd, type, &s, &os);
+				size += s;
+				origsize += os;
+			}
+			else
+			{
+				size += (type == DW_HORZ ? tmp->items[z].width : tmp->items[z].height);
+				origsize += (type == DW_HORZ ? tmp->items[z].origwidth : tmp->items[z].origheight);
+			}
+		}
+	}
+	else
+	{
+		/* If the box is not going in the direction we want, then we only
+		 * want to return the maximum value.
+		 */
+		int tmpsize = 0, tmporigsize = 0;
+
+		for(z=0;z<tmp->count;z++)
+		{
+			if(tmp->items[z].type == TYPEBOX)
+				_count_size(tmp->items[z].hwnd, type, &tmpsize, &tmporigsize);
+			else
+			{
+				tmpsize = (type == DW_HORZ ? tmp->items[z].width : tmp->items[z].height);
+				tmporigsize = (type == DW_HORZ ? tmp->items[z].origwidth : tmp->items[z].origheight);
+			}
+
+			if(tmpsize > size)
+				size = tmpsize;
+		}
+	}
+
+	*xsize = size;
+	*xorigsize = origsize;
+}
+
+
+/* Function: TrackRectangle
+ * Abstract: Tracks given rectangle.
+ *
+ * If rclBounds is NULL, then track rectangle on entire desktop.
+ * rclTrack is in window coorditates and will be mapped to
+ * desktop.
+ */
+
+BOOL _TrackRectangle(HWND hwndBase, RECTL* rclTrack, RECTL* rclBounds)
+{
+	TRACKINFO track;
+	APIRET rc;
+
+	track.cxBorder = 1;
+	track.cyBorder = 1;
+	track.cxGrid   = 1;
+	track.cyGrid   = 1;
+	track.cxKeyboard = 8;
+	track.cyKeyboard = 8;
+
+	if(!rclTrack)
+		return FALSE;
+
+	if(rclBounds)
+	{
+		track.rclBoundary = *rclBounds;
+	}
+	else
+	{
+		track.rclBoundary.yTop    =
+			track.rclBoundary.xRight  = 3000;
+		track.rclBoundary.yBottom =
+			track.rclBoundary.xLeft   = -3000;
+	}
+
+	track.rclTrack = *rclTrack;
+
+	WinMapWindowPoints(hwndBase,
+					   HWND_DESKTOP,
+					   (PPOINTL)&track.rclTrack,
+					   2);
+
+	track.ptlMinTrackSize.x = track.rclTrack.xRight
+		- track.rclTrack.xLeft;
+	track.ptlMinTrackSize.y = track.rclTrack.yTop
+		- track.rclTrack.yBottom;
+	track.ptlMaxTrackSize.x = track.rclTrack.xRight
+		- track.rclTrack.xLeft;
+	track.ptlMaxTrackSize.y = track.rclTrack.yTop
+		- track.rclTrack.yBottom;
+
+	track.fs = TF_MOVE | TF_ALLINBOUNDARY;
+
+	rc = WinTrackRect(HWND_DESKTOP, 0, &track);
+
+	if(rc)
+		*rclTrack = track.rclTrack;
+
+	return rc;
+}
+
+void _check_resize_notebook(HWND hwnd)
+{
+	char tmpbuf[100];
+
+	WinQueryClassName(hwnd, 99, tmpbuf);
+
+	/* If we have a notebook we resize the page again. */
+	if(strncmp(tmpbuf, "#40", 4)==0)
+	{
+		unsigned long x, y, width, height;
+		ULONG page = (ULONG)WinSendMsg(hwnd, BKM_QUERYPAGEID, 0, MPFROM2SHORT(BKA_FIRST, BKA_MAJOR));
+
+		while(page)
+		{
+			HWND pagehwnd = (HWND)WinSendMsg(hwnd, BKM_QUERYPAGEWINDOWHWND, MPFROMLONG(page), 0);
+			RECTL rc;
+
+			Box *pagebox = (Box *)WinQueryWindowPtr(pagehwnd, QWP_USER);
+			if(pagebox)
+			{
+				dw_window_get_pos_size(hwnd, &x, &y, &width, &height);
+
+				rc.xLeft = x;
+				rc.yBottom = y;
+				rc.xRight = x + width;
+				rc.yTop = y + height;
+
+				WinSendMsg(hwnd, BKM_CALCPAGERECT, (MPARAM)&rc, (MPARAM)TRUE);
+
+				_do_resize(pagebox, rc.xRight - rc.xLeft, rc.yTop - rc.yBottom);
+			}
+			page = (ULONG)WinSendMsg(hwnd, BKM_QUERYPAGEID, (MPARAM)page, MPFROM2SHORT(BKA_NEXT, BKA_MAJOR));
+		}
+
+	}
+}
+
+/* Return the OS/2 color from the DW color */
+unsigned long _internal_color(unsigned long color)
+{
+	if(color < 16)
+		return _colors[color];
+	return color;
+}
+
+/* This function calculates how much space the widgets and boxes require
+ * and does expansion as necessary.
+ */
+int _resize_box(Box *thisbox, int *depth, int x, int y, int *usedx, int *usedy,
+				int pass, int *usedpadx, int *usedpady)
+{
+	int z, currentx = 0, currenty = 0;
+	int uymax = 0, uxmax = 0;
+	int upymax = 0, upxmax = 0;
+	/* Used for the SIZEEXPAND */
+	int nux = *usedx, nuy = *usedy;
+	int nupx = *usedpadx, nupy = *usedpady;
+
+	(*usedx) += (thisbox->pad * 2);
+	(*usedy) += (thisbox->pad * 2);
+
+	if(thisbox->grouphwnd)
+	{
+		char *text = dw_window_get_text(thisbox->grouphwnd);
+
+		thisbox->grouppady = 0;
+
+		if(text)
+		{
+			dw_font_text_extents(thisbox->grouphwnd, 0, text, NULL, &thisbox->grouppady);
+			dw_free(text);
+		}
+
+		if(thisbox->grouppady)
+			thisbox->grouppady += 3;
+		else
+			thisbox->grouppady = 6;
+
+		thisbox->grouppadx = 6;
+
+		(*usedx) += thisbox->grouppadx;
+		(*usedpadx) += thisbox->grouppadx;
+		(*usedy) += thisbox->grouppady;
+		(*usedpady) += thisbox->grouppady;
+	}
+
+	for(z=0;z<thisbox->count;z++)
+	{
+		if(thisbox->items[z].type == TYPEBOX)
+		{
+			int initialx, initialy;
+			Box *tmp = WinQueryWindowPtr(thisbox->items[z].hwnd, QWP_USER);
+
+			initialx = x - (*usedx);
+			initialy = y - (*usedy);
+
+			if(tmp)
+			{
+				int newx, newy;
+				int nux = *usedx, nuy = *usedy;
+				int upx = *usedpadx + (tmp->pad*2), upy = *usedpady + (tmp->pad*2);
+
+				/* On the second pass we know how big the box needs to be and how
+				 * much space we have, so we can calculate a ratio for the new box.
+				 */
+				if(pass == 2)
+				{
+					int deep = *depth + 1;
+
+					_resize_box(tmp, &deep, x, y, &nux, &nuy, 1, &upx, &upy);
+
+					tmp->upx = upx - *usedpadx;
+					tmp->upy = upy - *usedpady;
+
+					newx = x - nux;
+					newy = y - nuy;
+
+					tmp->width = thisbox->items[z].width = initialx - newx;
+					tmp->height = thisbox->items[z].height = initialy - newy;
+
+					tmp->parentxratio = thisbox->xratio;
+					tmp->parentyratio = thisbox->yratio;
+
+					tmp->parentpad = tmp->pad;
+
+					/* Just in case */
+					tmp->xratio = thisbox->xratio;
+					tmp->yratio = thisbox->yratio;
+
+					if(thisbox->type == DW_VERT)
+					{
+						int tmppad = (thisbox->items[z].pad*2)+(tmp->pad*2)+tmp->grouppady;
+
+						if((thisbox->items[z].width - tmppad)!=0)
+							tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmppad))/((float)(thisbox->items[z].width-tmppad));
+					}
+					else
+					{
+						if((thisbox->items[z].width-tmp->upx)!=0)
+							tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmp->upx))/((float)(thisbox->items[z].width-tmp->upx));
+					}
+					if(thisbox->type == DW_HORZ)
+					{
+						int tmppad = (thisbox->items[z].pad*2)+(tmp->pad*2)+tmp->grouppadx;
+
+						if((thisbox->items[z].height-tmppad)!=0)
+							tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmppad))/((float)(thisbox->items[z].height-tmppad));
+					}
+					else
+					{
+						if((thisbox->items[z].height-tmp->upy)!=0)
+							tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmp->upy))/((float)(thisbox->items[z].height-tmp->upy));
+					}
+
+					nux = *usedx; nuy = *usedy;
+					upx = *usedpadx + (tmp->pad*2); upy = *usedpady + (tmp->pad*2);
+				}
+
+				(*depth)++;
+
+				_resize_box(tmp, depth, x, y, &nux, &nuy, pass, &upx, &upy);
+
+				(*depth)--;
+
+				newx = x - nux;
+				newy = y - nuy;
+
+				tmp->minwidth = thisbox->items[z].width = initialx - newx;
+				tmp->minheight = thisbox->items[z].height = initialy - newy;
+			}
+		}
+
+		if(pass > 1 && *depth > 0)
+		{
+			if(thisbox->type == DW_VERT)
+			{
+				int tmppad = (thisbox->items[z].pad*2)+(thisbox->parentpad*2)+thisbox->grouppadx;
+
+				if((thisbox->minwidth-tmppad) == 0)
+					thisbox->items[z].xratio = 1.0;
+				else
+					thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-tmppad))/((float)(thisbox->minwidth-tmppad));
+			}
+			else
+			{
+				if(thisbox->minwidth-thisbox->upx == 0)
+					thisbox->items[z].xratio = 1.0;
+				else
+					thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-thisbox->upx))/((float)(thisbox->minwidth-thisbox->upx));
+			}
+
+			if(thisbox->type == DW_HORZ)
+			{
+				int tmppad = (thisbox->items[z].pad*2)+(thisbox->parentpad*2)+thisbox->grouppady;
+
+				if((thisbox->minheight-tmppad) == 0)
+					thisbox->items[z].yratio = 1.0;
+				else
+					thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-tmppad))/((float)(thisbox->minheight-tmppad));
+			}
+			else
+			{
+				if(thisbox->minheight-thisbox->upy == 0)
+					thisbox->items[z].yratio = 1.0;
+				else
+					thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-thisbox->upy))/((float)(thisbox->minheight-thisbox->upy));
+			}
+
+			if(thisbox->items[z].type == TYPEBOX)
+			{
+				Box *tmp = WinQueryWindowPtr(thisbox->items[z].hwnd, QWP_USER);
+
+				if(tmp)
+				{
+					tmp->parentxratio = thisbox->items[z].xratio;
+					tmp->parentyratio = thisbox->items[z].yratio;
+				}
+			}
+		}
+		else
+		{
+			thisbox->items[z].xratio = thisbox->xratio;
+			thisbox->items[z].yratio = thisbox->yratio;
+		}
+
+		if(thisbox->type == DW_VERT)
+		{
+			int itemwidth = thisbox->items[z].width + (thisbox->items[z].pad*2);
+
+			if(itemwidth > uxmax)
+				uxmax = itemwidth;
+			if(thisbox->items[z].hsize != SIZEEXPAND)
+			{
+				if(itemwidth > upxmax)
+					upxmax = itemwidth;
+			}
+			else
+			{
+				if(thisbox->items[z].pad*2 > upxmax)
+					upxmax = thisbox->items[z].pad*2;
+			}
+		}
+		else
+		{
+			if(thisbox->items[z].width == -1)
+			{
+				/* figure out how much space this item requires */
+				/* thisbox->items[z].width = */
+			}
+			else
+			{
+				(*usedx) += thisbox->items[z].width + (thisbox->items[z].pad*2);
+				if(thisbox->items[z].hsize != SIZEEXPAND)
+					(*usedpadx) += (thisbox->items[z].pad*2) + thisbox->items[z].width;
+				else
+					(*usedpadx) += thisbox->items[z].pad*2;
+			}
+		}
+		if(thisbox->type == DW_HORZ)
+		{
+			int itemheight = thisbox->items[z].height + (thisbox->items[z].pad*2);
+
+			if(itemheight > uymax)
+				uymax = itemheight;
+			if(thisbox->items[z].vsize != SIZEEXPAND)
+			{
+				if(itemheight > upymax)
+					upymax = itemheight;
+			}
+			else
+			{
+				if(thisbox->items[z].pad*2 > upymax)
+					upymax = thisbox->items[z].pad*2;
+			}
+		}
+		else
+		{
+			if(thisbox->items[z].height == -1)
+			{
+				/* figure out how much space this item requires */
+				/* thisbox->items[z].height = */
+			}
+			else
+			{
+				(*usedy) += thisbox->items[z].height + (thisbox->items[z].pad*2);
+				if(thisbox->items[z].vsize != SIZEEXPAND)
+					(*usedpady) += (thisbox->items[z].pad*2) + thisbox->items[z].height;
+				else
+					(*usedpady) += thisbox->items[z].pad*2;
+			}
+		}
+	}
+
+	(*usedx) += uxmax;
+	(*usedy) += uymax;
+	(*usedpadx) += upxmax;
+	(*usedpady) += upymax;
+
+	currentx += thisbox->pad;
+	currenty += thisbox->pad;
+
+	if(thisbox->grouphwnd)
+	{
+		currentx += 3;
+		currenty += 3;
+	}
+
+	/* The second pass is for expansion and actual placement. */
+	if(pass > 1)
+	{
+		/* Any SIZEEXPAND items should be set to uxmax/uymax */
+		for(z=0;z<thisbox->count;z++)
+		{
+			if(thisbox->items[z].hsize == SIZEEXPAND && thisbox->type == DW_VERT)
+				thisbox->items[z].width = uxmax-(thisbox->items[z].pad*2);
+			if(thisbox->items[z].vsize == SIZEEXPAND && thisbox->type == DW_HORZ)
+				thisbox->items[z].height = uymax-(thisbox->items[z].pad*2);
+			/* Run this code segment again to finalize the sized after setting uxmax/uymax values. */
+			if(thisbox->items[z].type == TYPEBOX)
+			{
+				Box *tmp = WinQueryWindowPtr(thisbox->items[z].hwnd, QWP_USER);
+
+				if(tmp)
+				{
+					if(*depth > 0)
+					{
+						float calcval;
+
+						if(thisbox->type == DW_VERT)
+						{
+							calcval = (float)(tmp->minwidth-((thisbox->items[z].pad*2)+(thisbox->pad*2)));
+							if(calcval == 0.0)
+								tmp->xratio = thisbox->xratio;
+							else
+								tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-((thisbox->items[z].pad*2)+(thisbox->pad*2))))/calcval;
+							tmp->width = thisbox->items[z].width;
+						}
+						if(thisbox->type == DW_HORZ)
+						{
+							calcval = (float)(tmp->minheight-((thisbox->items[z].pad*2)+(thisbox->pad*2)));
+							if(calcval == 0.0)
+								tmp->yratio = thisbox->yratio;
+							else
+								tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-((thisbox->items[z].pad*2)+(thisbox->pad*2))))/calcval;
+							tmp->height = thisbox->items[z].height;
+						}
+					}
+
+					(*depth)++;
+
+					_resize_box(tmp, depth, x, y, &nux, &nuy, 3, &nupx, &nupy);
+
+					(*depth)--;
+
+				}
+			}
+		}
+
+		for(z=0;z<(thisbox->count);z++)
+		{
+			int height = thisbox->items[z].height;
+			int width = thisbox->items[z].width;
+			int pad = thisbox->items[z].pad;
+			HWND handle = thisbox->items[z].hwnd;
+			int vectorx, vectory;
+
+			/* When upxmax != pad*2 then ratios are incorrect. */
+			vectorx = (int)((width*thisbox->items[z].xratio)-width);
+			vectory = (int)((height*thisbox->items[z].yratio)-height);
+
+			if(width > 0 && height > 0)
+			{
+				char tmpbuf[100];
+				/* This is a hack to fix rounding of the sizing */
+				if(*depth == 0)
+				{
+					vectorx++;
+					vectory++;
+				}
+
+				/* If this item isn't going to expand... reset the vectors to 0 */
+				if(thisbox->items[z].vsize != SIZEEXPAND)
+					vectory = 0;
+				if(thisbox->items[z].hsize != SIZEEXPAND)
+					vectorx = 0;
+
+				WinQueryClassName(handle, 99, tmpbuf);
+
+				if(strncmp(tmpbuf, "#2", 3)==0)
+				{
+					HWND frame = (HWND)dw_window_get_data(handle, "_dw_combo_box");
+					/* Make the combobox big enough to drop down. :) */
+					WinSetWindowPos(handle, HWND_TOP, 0, -100,
+									width + vectorx, (height + vectory) + 100, SWP_MOVE | SWP_SIZE | SWP_ZORDER);
+					WinSetWindowPos(frame, HWND_TOP, currentx + pad, currenty + pad,
+									width + vectorx, height + vectory, SWP_MOVE | SWP_SIZE | SWP_ZORDER);
+				}
+				else if(strncmp(tmpbuf, "#6", 3)==0)
+				{
+					/* Entryfields on OS/2 have a thick border that isn't on Windows and GTK */
+					WinSetWindowPos(handle, HWND_TOP, (currentx + pad) + 3, (currenty + pad) + 3,
+									(width + vectorx) - 6, (height + vectory) - 6, SWP_MOVE | SWP_SIZE | SWP_ZORDER);
+				}
+				else if(strncmp(tmpbuf, "#40", 5)==0)
+				{
+					WinSetWindowPos(handle, HWND_TOP, currentx + pad, currenty + pad,
+									width + vectorx, height + vectory, SWP_MOVE | SWP_SIZE | SWP_ZORDER);
+					_check_resize_notebook(handle);
+				}
+				else if(strncmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0)
+				{
+					/* Then try the bottom or right box */
+					float *percent = (float *)dw_window_get_data(handle, "_dw_percent");
+					int type = (int)dw_window_get_data(handle, "_dw_type");
+					int cx = width + vectorx;
+					int cy = height + vectory;
+
+					WinSetWindowPos(handle, HWND_TOP, currentx + pad, currenty + pad,
+									cx, cy, SWP_MOVE | SWP_SIZE | SWP_ZORDER);
+
+					if(cx > 0 && cy > 0 && percent)
+						_handle_splitbar_resize(handle, *percent, type, cx, cy);
+				}
+				else
+				{
+					WinSetWindowPos(handle, HWND_TOP, currentx + pad, currenty + pad,
+									width + vectorx, height + vectory, SWP_MOVE | SWP_SIZE | SWP_ZORDER);
+					if(thisbox->items[z].type == TYPEBOX)
+					{
+						Box *boxinfo = WinQueryWindowPtr(handle, QWP_USER);
+
+						if(boxinfo && boxinfo->grouphwnd)
+							WinSetWindowPos(boxinfo->grouphwnd, HWND_TOP, 0, 0,
+											width + vectorx, height + vectory, SWP_MOVE | SWP_SIZE);
+
+					}
+
+				}
+
+				if(thisbox->type == DW_HORZ)
+					currentx += width + vectorx + (pad * 2);
+				if(thisbox->type == DW_VERT)
+					currenty += height + vectory + (pad * 2);
+			}
+		}
+	}
+	return 0;
+}
+
+void _do_resize(Box *thisbox, int x, int y)
+{
+	if(x != 0 && y != 0)
+	{
+		if(thisbox)
+		{
+			int usedx = 0, usedy = 0, usedpadx = 0, usedpady = 0, depth = 0;
+
+			_resize_box(thisbox, &depth, x, y, &usedx, &usedy, 1, &usedpadx, &usedpady);
+
+			if(usedx-usedpadx == 0 || usedy-usedpady == 0)
+				return;
+
+			thisbox->xratio = ((float)(x-usedpadx))/((float)(usedx-usedpadx));
+			thisbox->yratio = ((float)(y-usedpady))/((float)(usedy-usedpady));
+
+			usedx = usedy = usedpadx = usedpady = depth = 0;
+
+			_resize_box(thisbox, &depth, x, y, &usedx, &usedy, 2, &usedpadx, &usedpady);
+		}
+	}
+}
+
+/* This procedure handles WM_QUERYTRACKINFO requests from the frame */
+MRESULT EXPENTRY _sizeproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+	PFNWP *blah = WinQueryWindowPtr(hWnd, QWP_USER);
+	Box *thisbox = NULL;
+	HWND box;
+
+	box = WinWindowFromID(hWnd, FID_CLIENT);
+	if(box)
+		thisbox = WinQueryWindowPtr(box, QWP_USER);
+
+	if(thisbox && !thisbox->titlebar)
+	{
+		switch(msg)
+		{
+		case WM_QUERYTRACKINFO:
+			{
+				if(blah && *blah)
+				{
+					PTRACKINFO ptInfo;
+					int res;
+					PFNWP myfunc = *blah;
+					res = (int)myfunc(hWnd, msg, mp1, mp2);
+
+					ptInfo = (PTRACKINFO)(mp2);
+
+					ptInfo->ptlMinTrackSize.y = 8;
+					ptInfo->ptlMinTrackSize.x = 8;
+
+					return (MRESULT)res;
+				}
+			}
+		}
+	}
+
+	if(blah && *blah)
+	{
+		PFNWP myfunc = *blah;
+		return myfunc(hWnd, msg, mp1, mp2);
+	}
+
+	return WinDefWindowProc(hWnd, msg, mp1, mp2);
+}
+
+void _Top(HPS hpsPaint, RECTL rclPaint)
+{
+	POINTL ptl1, ptl2;
+
+	ptl1.x = rclPaint.xLeft;
+	ptl2.y = ptl1.y = rclPaint.yTop - 1;
+	ptl2.x = rclPaint.xRight - 1;
+	GpiMove(hpsPaint, &ptl1);
+	GpiLine(hpsPaint, &ptl2);
+}
+
+/* Left hits the bottom */
+void _Left(HPS hpsPaint, RECTL rclPaint)
+{
+	POINTL ptl1, ptl2;
+
+	ptl2.x = ptl1.x = rclPaint.xLeft;
+	ptl1.y = rclPaint.yTop - 1;
+	ptl2.y = rclPaint.yBottom;
+	GpiMove(hpsPaint, &ptl1);
+	GpiLine(hpsPaint, &ptl2);
+}
+
+void _Bottom(HPS hpsPaint, RECTL rclPaint)
+{
+	POINTL ptl1, ptl2;
+
+	ptl1.x = rclPaint.xRight - 1;
+	ptl1.y = ptl2.y = rclPaint.yBottom;
+	ptl2.x = rclPaint.xLeft;
+	GpiMove(hpsPaint, &ptl1);
+	GpiLine(hpsPaint, &ptl2);
+}
+
+/* Right hits the top */
+void _Right(HPS hpsPaint, RECTL rclPaint)
+{
+	POINTL ptl1, ptl2;
+
+	ptl2.x = ptl1.x = rclPaint.xRight - 1;
+	ptl1.y = rclPaint.yBottom + 1;
+	ptl2.y = rclPaint.yTop - 1;
+	GpiMove(hpsPaint, &ptl1);
+	GpiLine(hpsPaint, &ptl2);
+}
+
+/* This procedure handles drawing of a status border */
+MRESULT EXPENTRY _statusproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+	PFNWP *blah = WinQueryWindowPtr(hWnd, QWP_USER);
+
+	if(blah && *blah)
+	{
+		PFNWP myfunc = *blah;
+
+		switch(msg)
+		{
+		case WM_PAINT:
+			{
+				HPS hpsPaint;
+				RECTL rclPaint;
+				char buf[1024];
+
+				hpsPaint = WinBeginPaint(hWnd, 0, 0);
+				WinQueryWindowRect(hWnd, &rclPaint);
+				WinFillRect(hpsPaint, &rclPaint, CLR_PALEGRAY);
+
+				GpiSetColor(hpsPaint, CLR_DARKGRAY);
+				_Top(hpsPaint, rclPaint);
+				_Left(hpsPaint, rclPaint);
+
+				GpiSetColor(hpsPaint, CLR_WHITE);
+				_Right(hpsPaint, rclPaint);
+				_Bottom(hpsPaint, rclPaint);
+
+				WinQueryWindowText(hWnd, 1024, buf);
+				rclPaint.xLeft += 3;
+				rclPaint.xRight--;
+				rclPaint.yTop--;
+				rclPaint.yBottom++;
+
+				GpiSetColor(hpsPaint, CLR_BLACK);
+				WinDrawText(hpsPaint, -1, buf, &rclPaint, DT_TEXTATTRS, DT_TEXTATTRS, DT_VCENTER | DT_LEFT | DT_TEXTATTRS);
+				WinEndPaint(hpsPaint);
+
+				return (MRESULT)TRUE;
+			}
+		}
+		return myfunc(hWnd, msg, mp1, mp2);
+	}
+
+	return WinDefWindowProc(hWnd, msg, mp1, mp2);
+}
+
+void _click_default(HWND handle)
+{
+	char tmpbuf[100];
+
+	WinQueryClassName(handle, 99, tmpbuf);
+
+	/* These are the window classes which can
+	 * obtain input focus.
+	 */
+	if(strncmp(tmpbuf, "#3", 3)==0)
+	{
+		/* Generate click on default item */
+		SignalHandler *tmp = Root;
+
+		/* Find any callbacks for this function */
+		while(tmp)
+		{
+			if(tmp->message == WM_COMMAND)
+			{
+				int (*clickfunc)(HWND, void *) = (int (*)(HWND, void *))tmp->signalfunction;
+
+				/* Make sure it's the right window, and the right ID */
+				if(tmp->window == handle)
+				{
+					clickfunc(tmp->window, tmp->data);
+					tmp = NULL;
+				}
+			}
+			if(tmp)
+				tmp= tmp->next;
+		}
+	}
+	else
+		WinSetFocus(HWND_DESKTOP, handle);
+}
+
+#define ENTRY_CUT   1001
+#define ENTRY_COPY  1002
+#define ENTRY_PASTE 1003
+#define ENTRY_UNDO  1004
+#define ENTRY_SALL  1005
+
+/* Originally just intended for entryfields, it now serves as a generic
+ * procedure for handling TAB presses to change input focus on controls.
+ */
+MRESULT EXPENTRY _entryproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+	WindowData *blah = (WindowData *)WinQueryWindowPtr(hWnd, QWP_USER);
+	PFNWP oldproc = 0;
+	char tmpbuf[100];
+
+	if(blah)
+		oldproc = blah->oldproc;
+
+	WinQueryClassName(hWnd, 99, tmpbuf);
+
+	/* These are the window classes which should get a menu */
+	if(strncmp(tmpbuf, "#2", 3)==0 ||  /* Combobox */
+	   strncmp(tmpbuf, "#6", 3)==0 ||  /* Entryfield */
+	   strncmp(tmpbuf, "#10", 4)==0 || /* MLE */
+	   strncmp(tmpbuf, "#32", 4)==0)   /* Spinbutton */
+	{
+		switch(msg)
+		{
+		case WM_CONTEXTMENU:
+			{
+				HMENUI hwndMenu = dw_menu_new(0L);
+				long x, y;
+
+				if(strncmp(tmpbuf, "#10", 4)==0 && !WinSendMsg(hWnd, MLM_QUERYREADONLY, 0, 0))
+				{
+					dw_menu_append_item(hwndMenu, "Undo", ENTRY_UNDO, 0L, TRUE, FALSE, 0L);
+					dw_menu_append_item(hwndMenu, "", 0L, 0L, TRUE, FALSE, 0L);
+				}
+				dw_menu_append_item(hwndMenu, "Copy", ENTRY_COPY, 0L, TRUE, FALSE, 0L);
+				if((strncmp(tmpbuf, "#10", 4)!=0  && !dw_window_get_data(hWnd, "_dw_disabled")) || (strncmp(tmpbuf, "#10", 4)==0 && !WinSendMsg(hWnd, MLM_QUERYREADONLY, 0, 0)))
+				{
+					dw_menu_append_item(hwndMenu, "Cut", ENTRY_CUT, 0L, TRUE, FALSE, 0L);
+					dw_menu_append_item(hwndMenu, "Paste", ENTRY_PASTE, 0L, TRUE, FALSE, 0L);
+				}
+				dw_menu_append_item(hwndMenu, "", 0L, 0L, TRUE, FALSE, 0L);
+				dw_menu_append_item(hwndMenu, "Select All", ENTRY_SALL, 0L, TRUE, FALSE, 0L);
+
+				WinSetFocus(HWND_DESKTOP, hWnd);
+				dw_pointer_query_pos(&x, &y);
+				dw_menu_popup(&hwndMenu, hWnd, x, y);
+			}
+			break;
+		case WM_COMMAND:
+			{
+				ULONG command = COMMANDMSG(&msg)->cmd;
+
+				/* MLE */
+				if(strncmp(tmpbuf, "#10", 4)==0)
+				{
+					switch(command)
+					{
+					case ENTRY_CUT:
+						return WinSendMsg(hWnd, MLM_CUT, 0, 0);
+					case ENTRY_COPY:
+						return WinSendMsg(hWnd, MLM_COPY, 0, 0);
+					case ENTRY_PASTE:
+						return WinSendMsg(hWnd, MLM_PASTE, 0, 0);
+					case ENTRY_UNDO:
+						return WinSendMsg(hWnd, MLM_UNDO, 0, 0);
+					case ENTRY_SALL:
+						{
+							ULONG len = (ULONG)WinSendMsg(hWnd, MLM_QUERYTEXTLENGTH, 0, 0);
+							return WinSendMsg(hWnd, MLM_SETSEL, 0, (MPARAM)len);
+						}
+					}
+				}
+				else /* Other */
+				{
+					HWND handle = hWnd;
+
+					/* Get the entryfield handle from multi window controls */
+					if(strncmp(tmpbuf, "#2", 3)==0)
+						handle = WinWindowFromID(hWnd, 667);
+
+					if(handle)
+					{
+						switch(command)
+						{
+						case ENTRY_CUT:
+							return WinSendMsg(handle, EM_CUT, 0, 0);
+						case ENTRY_COPY:
+							return WinSendMsg(handle, EM_COPY, 0, 0);
+						case ENTRY_PASTE:
+							return WinSendMsg(handle, EM_PASTE, 0, 0);
+						case ENTRY_SALL:
+							{
+								LONG len = WinQueryWindowTextLength(hWnd);
+								return WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT(0, (SHORT)len), 0);
+							}
+						}
+					}
+				}
+			}
+			break;
+		}
+	}
+
+	switch(msg)
+	{
+	case WM_BUTTON1DOWN:
+	case WM_BUTTON2DOWN:
+	case WM_BUTTON3DOWN:
+		{
+			if(strncmp(tmpbuf, "#32", 4)==0)
+				_run_event(hWnd, WM_SETFOCUS, (MPARAM)FALSE, (MPARAM)TRUE);
+		}
+		break;
+	case WM_CONTROL:
+		{
+			if(strncmp(tmpbuf, "#38", 4)==0)
+				_run_event(hWnd, msg, mp1, mp2);
+		}
+		break;
+	case WM_SETFOCUS:
+		_run_event(hWnd, msg, mp1, mp2);
+		break;
+	case WM_CHAR:
+		if(_run_event(hWnd, msg, mp1, mp2) == (MRESULT)TRUE)
+			return (MRESULT)TRUE;
+		if(SHORT1FROMMP(mp2) == '\t')
+		{
+			if(CHARMSG(&msg)->fs & KC_SHIFT)
+				_shift_focus_back(hWnd);
+			else
+				_shift_focus(hWnd);
+			return FALSE;
+		}
+		else if(SHORT1FROMMP(mp2) == '\r' && blah && blah->clickdefault)
+			_click_default(blah->clickdefault);
+		/* When you hit escape we get this value and the
+		 * window hangs for reasons unknown. (in an MLE)
+		 */
+		else if(SHORT1FROMMP(mp2) == 283)
+			return (MRESULT)TRUE;
+
+		break;
+	case WM_SIZE:
+		{
+			/* If it's a slider... make sure it shows the correct value */
+			if(strncmp(tmpbuf, "#38", 4)==0)
+				WinPostMsg(hWnd, WM_USER+7, 0, 0);
+		}
+		break;
+	case WM_USER+7:
+		{
+			int pos = (int)dw_window_get_data(hWnd, "_dw_slider_value");
+			WinSendMsg(hWnd, SLM_SETSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), (MPARAM)pos);
+		}
+		break;
+	}
+
+	if(oldproc)
+		return oldproc(hWnd, msg, mp1, mp2);
+
+	return WinDefWindowProc(hWnd, msg, mp1, mp2);
+}
+
+/*  Deal with combobox specifics and enhancements */
+MRESULT EXPENTRY _comboentryproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+	WindowData *blah = (WindowData *)WinQueryWindowPtr(hWnd, QWP_USER);
+
+	switch(msg)
+	{
+	case WM_CONTEXTMENU:
+	case WM_COMMAND:
+		return _entryproc(hWnd, msg, mp1, mp2);
+	case WM_SETFOCUS:
+		_run_event(hWnd, msg, mp1, mp2);
+		break;
+	case WM_CHAR:
+		if(_run_event(hWnd, msg, mp1, mp2) == (MRESULT)TRUE)
+			return (MRESULT)TRUE;
+		/* A Similar problem to the MLE, if ESC just return */
+		if(SHORT1FROMMP(mp2) == 283)
+			return (MRESULT)TRUE;
+		break;
+	}
+
+	if(blah && blah->oldproc)
+		return blah->oldproc(hWnd, msg, mp1, mp2);
+
+	return WinDefWindowProc(hWnd, msg, mp1, mp2);
+}
+
+/* Enhance the standard OS/2 MLE control */
+MRESULT EXPENTRY _mleproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+	switch(msg)
+	{
+	case WM_VSCROLL:
+		if(SHORT2FROMMP(mp2) == SB_SLIDERTRACK)
+		{
+			USHORT pos = SHORT1FROMMP(mp2);
+
+			WinSendMsg(hWnd, msg, mp1, MPFROM2SHORT(pos, SB_SLIDERPOSITION));
+		}
+		break;
+	}
+	return _entryproc(hWnd, msg, mp1, mp2);
+}
+
+/* Handle special messages for the spinbutton's entryfield */
+MRESULT EXPENTRY _spinentryproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+	WindowData *blah = (WindowData *)WinQueryWindowPtr(hWnd, QWP_USER);
+	PFNWP oldproc = 0;
+
+	if(blah)
+		oldproc = blah->oldproc;
+
+	switch(msg)
+	{
+	case WM_CONTEXTMENU:
+	case WM_COMMAND:
+		return _entryproc(hWnd, msg, mp1, mp2);
+	}
+
+	if(oldproc)
+		return oldproc(hWnd, msg, mp1, mp2);
+
+	return WinDefWindowProc(hWnd, msg, mp1, mp2);
+}
+
+int _dw_int_pos(HWND hwnd)
+{
+	int pos = (int)dw_window_get_data(hwnd, "_dw_percent_value");
+	int range = dw_percent_query_range(hwnd);
+	float fpos = (float)pos;
+	float frange = (float)range;
+	float fnew = (fpos/1000.0)*frange;
+	return (int)fnew;
+}
+
+void _dw_int_set(HWND hwnd, int pos)
+{
+	int inew, range = dw_percent_query_range(hwnd);
+	if(range)
+	{
+		float fpos = (float)pos;
+		float frange = (float)range;
+		float fnew = (fpos/frange)*1000.0;
+		inew = (int)fnew;
+		dw_window_set_data(hwnd, "_dw_percent_value", (void *)inew);
+	}
+}
+
+/* Handle size changes in the percent class */
+MRESULT EXPENTRY _percentproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+	WindowData *blah = (WindowData *)WinQueryWindowPtr(hWnd, QWP_USER);
+	PFNWP oldproc = 0;
+
+	if(blah)
+		oldproc = blah->oldproc;
+
+	switch(msg)
+	{
+	case WM_SIZE:
+		WinPostMsg(hWnd, WM_USER+7, 0, 0);
+		break;
+	case WM_USER+7:
+		WinSendMsg(hWnd, SLM_SETSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION,SMA_RANGEVALUE), (MPARAM)_dw_int_pos(hWnd));
+		break;
+	}
+
+	if(oldproc)
+		return oldproc(hWnd, msg, mp1, mp2);
+
+	return WinDefWindowProc(hWnd, msg, mp1, mp2);
+}
+
+/* Handle correct painting of a combobox with the WS_CLIPCHILDREN
+ * flag enabled, and also handle TABs to switch input focus.
+ */
+MRESULT EXPENTRY _comboproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+	WindowData *blah = WinQueryWindowPtr(hWnd, QWP_USER);
+	PFNWP oldproc = 0;
+
+	if(blah)
+		oldproc = blah->oldproc;
+
+	switch(msg)
+	{
+	case WM_CHAR:
+		if(SHORT1FROMMP(mp2) == '\t')
+		{
+			if(CHARMSG(&msg)->fs & KC_SHIFT)
+				_shift_focus_back(hWnd);
+			else
+				_shift_focus(hWnd);
+			return FALSE;
+		}
+		else if(SHORT1FROMMP(mp2) == '\r' && blah && blah->clickdefault)
+			_click_default(blah->clickdefault);
+		break;
+	case WM_BUTTON1DBLCLK:
+	case WM_BUTTON2DBLCLK:
+	case WM_BUTTON3DBLCLK:
+		if(dw_window_get_data(hWnd, "_dw_disabled"))
+			return (MRESULT)TRUE;
+		break;
+	case WM_BUTTON1DOWN:
+	case WM_BUTTON2DOWN:
+	case WM_BUTTON3DOWN:
+		if(_run_event(hWnd, msg, mp1, mp2) == (MRESULT)TRUE)
+			return (MRESULT)TRUE;
+		_run_event(hWnd, WM_SETFOCUS, (MPARAM)FALSE, (MPARAM)TRUE);
+		break;
+	case WM_SETFOCUS:
+		_run_event(hWnd, msg, mp1, mp2);
+		break;
+	case WM_PAINT:
+		{
+			HWND entry, frame = (HWND)dw_window_get_data(hWnd, "_dw_combo_box"), parent = WinQueryWindow(frame, QW_PARENT);
+			HPS hpsPaint;
+			POINTL ptl;
+			unsigned long width, height, thumbheight = 0;
+			ULONG color;
+
+			if((entry = (HWND)dw_window_get_data(hWnd, "_dw_comboentry")) != NULLHANDLE)
+				dw_window_get_pos_size(entry, 0, 0, 0, &thumbheight);
+
+			if(!thumbheight)
+				thumbheight = WinQuerySysValue(HWND_DESKTOP, SV_CYVSCROLLARROW);
+
+			/* Add 6 because it has a thick border like the entryfield */
+			thumbheight += 6;
+
+			color = (ULONG)dw_window_get_data(parent, "_dw_fore");
+			dw_window_get_pos_size(hWnd, 0, 0, &width, &height);
+
+			if(height > thumbheight)
+			{
+				hpsPaint = WinGetPS(hWnd);
+				if(color)
+					GpiSetColor(hpsPaint, _internal_color(color-1));
+				else
+					GpiSetColor(hpsPaint, CLR_PALEGRAY);
+
+				ptl.x = ptl.y = 0;
+				GpiMove(hpsPaint, &ptl);
+
+				ptl.x = width;
+				ptl.y = height - thumbheight;
+				GpiBox(hpsPaint, DRO_FILL, &ptl, 0, 0);
+
+				WinReleasePS(hpsPaint);
+			}
+		}
+		break;
+	}
+	if(oldproc)
+		return oldproc(hWnd, msg, mp1, mp2);
+
+	return WinDefWindowProc(hWnd, msg, mp1, mp2);
+}
+
+void _GetPPFont(HWND hwnd, char *buff)
+{
+    ULONG AttrFound;
+    BYTE  AttrValue[128];
+    ULONG cbRetLen;
+
+    cbRetLen = WinQueryPresParam(hwnd,
+                                 PP_FONTNAMESIZE,
+                                 0,
+                                 &AttrFound,
+                                 sizeof(AttrValue),
+                                 &AttrValue,
+                                 QPF_NOINHERIT);
+
+    if(PP_FONTNAMESIZE == AttrFound && cbRetLen)
+    {
+        memcpy(buff, AttrValue, cbRetLen);
+    }
+}
+
+/* Returns height of specified window. */
+int _get_height(HWND handle)
+{
+	unsigned long height;
+	dw_window_get_pos_size(handle, NULL, NULL, NULL, &height);
+	return (int)height;
+}
+
+/* Find the height of the frame a desktop style window is sitting on */
+int _get_frame_height(HWND handle)
+{
+	while(handle)
+	{
+		HWND client;
+		if((client = WinWindowFromID(handle, FID_CLIENT)) != NULLHANDLE)
+		{
+            return _get_height(WinQueryWindow(handle, QW_PARENT));
+		}
+        handle = WinQueryWindow(handle, QW_PARENT);
+	}
+	return dw_screen_height();
+}
+
+int _HandleScroller(HWND handle, int pos, int which)
+{
+	MPARAM res;
+	int min, max, page;
+
+	if(which == SB_SLIDERTRACK)
+		return pos;
+
+	pos = dw_scrollbar_query_pos(handle);
+	res = WinSendMsg(handle, SBM_QUERYRANGE, 0, 0);
+
+	min = SHORT1FROMMP(res);
+	max = SHORT2FROMMP(res);
+	page = (int)dw_window_get_data(handle, "_dw_scrollbar_visible");
+
+	switch(which)
+	{
+	case SB_LINEUP:
+		pos = pos - 1;
+		if(pos < min)
+			pos = min;
+		dw_scrollbar_set_pos(handle, pos);
+		return pos;
+	case SB_LINEDOWN:
+		pos = pos + 1;
+		if(pos > max)
+			pos = max;
+		dw_scrollbar_set_pos(handle, pos);
+		return pos;
+	case SB_PAGEUP:
+		pos = pos - page;
+		if(pos < min)
+			pos = min;
+		dw_scrollbar_set_pos(handle, pos);
+		return pos;
+	case SB_PAGEDOWN:
+		pos = pos + page;
+		if(pos > max)
+			pos = max;
+		dw_scrollbar_set_pos(handle, pos);
+		return pos;
+	}
+	return -1;
+}
+
+void _clear_emphasis(void)
+{
+	if(hwndEmph && WinIsWindow(dwhab, hwndEmph) && pCoreEmph)
+		WinSendMsg(hwndEmph, CM_SETRECORDEMPHASIS, pCoreEmph, MPFROM2SHORT(FALSE, CRA_SOURCE));
+	hwndEmph = NULLHANDLE;
+	pCoreEmph = NULL;
+}
+
+/* Find the desktop window handle */
+HWND _menu_owner(HWND handle)
+{
+	HWND menuowner = NULLHANDLE, lastowner = (HWND)dw_window_get_data(handle, "_dw_owner");
+	int menubar = (int)dw_window_get_data(handle, "_dw_menubar");
+
+	/* Find the toplevel window */
+	while(!menubar && (menuowner = (HWND)dw_window_get_data(lastowner, "_dw_owner")) != NULLHANDLE)
+	{
+		menubar = (int)dw_window_get_data(lastowner, "_dw_menubar");
+		lastowner = menuowner;
+	}
+	if(menuowner && menubar)
+	{
+		HWND client = WinWindowFromID(menuowner, FID_CLIENT);
+
+		return client ? client : menuowner;
+	}
+	return NULLHANDLE;
+}
+
+MRESULT EXPENTRY _run_event(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+	int result = -1;
+	SignalHandler *tmp = Root;
+	ULONG origmsg = msg;
+
+	if(msg == WM_BUTTON2DOWN || msg == WM_BUTTON3DOWN)
+		msg = WM_BUTTON1DOWN;
+	if(msg == WM_BUTTON2UP || msg == WM_BUTTON3UP)
+		msg = WM_BUTTON1UP;
+	if(msg == WM_VSCROLL || msg == WM_HSCROLL)
+		msg = WM_CONTROL;
+
+	/* Find any callbacks for this function */
+	while(tmp)
+	{
+		if(tmp->message == msg || msg == WM_CONTROL || tmp->message == WM_USER+1)
+		{
+			switch(msg)
+			{
+			case WM_SETFOCUS:
+				{
+					if((mp2 && tmp->message == WM_SETFOCUS) || (!mp2 && tmp->message == WM_USER+1))
+					{
+						int (* API setfocusfunc)(HWND, void *) = (int (* API)(HWND, void *))tmp->signalfunction;
+
+						if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd)
+						{
+							result = setfocusfunc(tmp->window, tmp->data);
+							tmp = NULL;
+						}
+					}
+				}
+				break;
+			case WM_TIMER:
+				{
+					int (* API timerfunc)(void *) = (int (* API)(void *))tmp->signalfunction;
+					if(tmp->id == (int)mp1)
+					{
+						if(!timerfunc(tmp->data))
+							dw_timer_disconnect(tmp->id);
+						tmp = NULL;
+					}
+					result = 0;
+				}
+				break;
+			case WM_SIZE:
+				{
+					int (* API sizefunc)(HWND, int, int, void *) = (int (* API)(HWND, int, int, void *))tmp->signalfunction;
+
+					if((hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd) && SHORT1FROMMP(mp2) && SHORT2FROMMP(mp2))
+					{
+						result = sizefunc(tmp->window, SHORT1FROMMP(mp2), SHORT2FROMMP(mp2), tmp->data);
+						tmp = NULL;
+					}
+				}
+				break;
+			case WM_BUTTON1DOWN:
+				{
+					POINTS pts = (*((POINTS*)&mp1));
+					int (* API buttonfunc)(HWND, int, int, int, void *) = (int (* API)(HWND, int, int, int, void *))tmp->signalfunction;
+
+					if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd || WinQueryCapture(HWND_DESKTOP) == tmp->window)
+					{
+						int button = 0;
+
+						switch(origmsg)
+						{
+						case WM_BUTTON1DOWN:
+							button = 1;
+							break;
+						case WM_BUTTON2DOWN:
+							button = 2;
+							break;
+						case WM_BUTTON3DOWN:
+							button = 3;
+							break;
+						}
+
+						result = buttonfunc(tmp->window, pts.x, _get_frame_height(tmp->window) - pts.y, button, tmp->data);
+						tmp = NULL;
+					}
+				}
+				break;
+			case WM_BUTTON1UP:
+				{
+					POINTS pts = (*((POINTS*)&mp1));
+					int (* API buttonfunc)(HWND, int, int, int, void *) = (int (* API)(HWND, int, int, int, void *))tmp->signalfunction;
+
+					if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd || WinQueryCapture(HWND_DESKTOP) == tmp->window)
+					{
+						int button = 0;
+
+						switch(origmsg)
+						{
+						case WM_BUTTON1UP:
+							button = 1;
+							break;
+						case WM_BUTTON2UP:
+							button = 2;
+							break;
+						case WM_BUTTON3UP:
+							button = 3;
+							break;
+						}
+
+						result = buttonfunc(tmp->window, pts.x, WinQueryWindow(tmp->window, QW_PARENT) == HWND_DESKTOP ? dw_screen_height() - pts.y : _get_height(tmp->window) - pts.y, button, tmp->data);
+						tmp = NULL;
+					}
+				}
+				break;
+			case WM_MOUSEMOVE:
+				{
+					int (* API motionfunc)(HWND, int, int, int, void *) = (int (* API)(HWND, int, int, int, void *))tmp->signalfunction;
+
+					if(hWnd == tmp->window || WinWindowFromID(tmp->window, FID_CLIENT) == hWnd || WinQueryCapture(HWND_DESKTOP) == tmp->window)
+					{
+						int keys = 0;
+						SHORT x = SHORT1FROMMP(mp1), y = SHORT2FROMMP(mp1);
+
+						if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) & 0x8000)
+							keys = DW_BUTTON1_MASK;
+						if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON2) & 0x8000)
+							keys |= DW_BUTTON2_MASK;
+						if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) & 0x8000)
+							keys |= DW_BUTTON3_MASK;
+
+						result = motionfunc(tmp->window, x, _get_frame_height(tmp->window) - y, keys, tmp->data);
+						tmp = NULL;
+					}
+				}
+				break;
+			case WM_CHAR:
+				{
+					int (* API keypressfunc)(HWND, char, int, int, void *) = (int (* API)(HWND, char, int, int, void *))tmp->signalfunction;
+
+					if((hWnd == tmp->window || _toplevel_window(hWnd) == tmp->window) && !(SHORT1FROMMP(mp1) & KC_KEYUP))
+					{
+						int vk;
+						char ch = 0;
+
+						if(SHORT1FROMMP(mp1) & KC_CHAR)
+							ch = (char)SHORT1FROMMP(mp2);
+						if(SHORT1FROMMP(mp1) & KC_VIRTUALKEY)
+							vk = SHORT2FROMMP(mp2);
+						else
+							vk = SHORT1FROMMP(mp2) + 128;
+
+						/* This is a hack to fix shift presses showing
+						 * up as tabs!
+						 */
+						if(ch == '\t' && !(SHORT1FROMMP(mp1) & KC_CHAR))
+						{
+							ch = 0;
+							vk = VK_SHIFT;
+						}
+
+						result = keypressfunc(tmp->window, ch, vk,
+											  SHORT1FROMMP(mp1) & (KC_ALT | KC_SHIFT | KC_CTRL), tmp->data);
+						tmp = NULL;
+					}
+				}
+				break;
+			case WM_CLOSE:
+				{
+					int (* API closefunc)(HWND, void *) = (int (* API)(HWND, void *))tmp->signalfunction;
+
+					if(hWnd == tmp->window || hWnd == WinWindowFromID(tmp->window, FID_CLIENT))
+					{
+						result = closefunc(tmp->window, tmp->data);
+						if(result)
+							result = FALSE;
+						tmp = NULL;
+					}
+				}
+				break;
+			case WM_PAINT:
+				{
+					HPS hps;
+					DWExpose exp;
+					int (* API exposefunc)(HWND, DWExpose *, void *) = (int (* API)(HWND, DWExpose *, void *))tmp->signalfunction;
+					RECTL  rc;
+
+					if(hWnd == tmp->window)
+					{
+						int height = _get_height(hWnd);
+
+						hps = WinBeginPaint(hWnd, 0L, &rc);
+						exp.x = rc.xLeft;
+						exp.y = height - rc.yTop - 1;
+						exp.width = rc.xRight - rc. xLeft;
+						exp.height = rc.yTop - rc.yBottom;
+						result = exposefunc(hWnd, &exp, tmp->data);
+						WinEndPaint(hps);
+					}
+				}
+				break;
+			case WM_COMMAND:
+				{
+					int (* API clickfunc)(HWND, void *) = (int (* API)(HWND, void *))tmp->signalfunction;
+					ULONG command = COMMANDMSG(&msg)->cmd;
+
+					if(tmp->id && command == tmp->id)
+					{
+						HWND menuowner = _menu_owner(tmp->window);
+
+						if(menuowner == hWnd || menuowner == NULLHANDLE)
+						{
+							result = clickfunc(tmp->window, tmp->data);
+							tmp = NULL;
+						}
+					}
+					else if(tmp->window < 65536 && command == tmp->window)
+					{
+						result = clickfunc(popup ?  popup : tmp->window, tmp->data);
+						tmp = NULL;
+					}
+				}
+				break;
+			case WM_CONTROL:
+				if(origmsg == WM_VSCROLL || origmsg == WM_HSCROLL || tmp->message == SHORT2FROMMP(mp1) ||
+				   (tmp->message == SLN_SLIDERTRACK && SHORT2FROMMP(mp1) == SLN_CHANGE))
+				{
+					int svar = SLN_SLIDERTRACK;
+					if(origmsg == WM_CONTROL)
+						svar = SHORT2FROMMP(mp1);
+
+					switch(svar)
+					{
+					case CN_ENTER:
+						{
+							int (* API containerselectfunc)(HWND, char *, void *) = (int (* API)(HWND, char *, void *))tmp->signalfunction;
+							int id = SHORT1FROMMP(mp1);
+							HWND conthwnd = dw_window_from_id(hWnd, id);
+							char *text = NULL;
+
+							if(mp2)
+							{
+								PRECORDCORE pre;
+
+								pre = ((PNOTIFYRECORDENTER)mp2)->pRecord;
+								if(pre)
+									text = pre->pszIcon;
+							}
+
+							if(tmp->window == conthwnd)
+							{
+								result = containerselectfunc(tmp->window, text, tmp->data);
+								tmp = NULL;
+							}
+						}
+						break;
+					case CN_EXPANDTREE:
+						{
+							int (* API treeexpandfunc)(HWND, HTREEITEM, void *) = (int (* API)(HWND, HTREEITEM, void *))tmp->signalfunction;
+							int id = SHORT1FROMMP(mp1);
+							HWND conthwnd = dw_window_from_id(hWnd, id);
+
+							if(tmp->window == conthwnd)
+							{
+								result = treeexpandfunc(tmp->window, (HTREEITEM)mp2, tmp->data);
+								tmp = NULL;
+							}
+						}
+						break;
+					case CN_CONTEXTMENU:
+						{
+							int (* API containercontextfunc)(HWND, char *, int, int, void *, void *) = (int (* API)(HWND, char *, int, int, void *, void *))tmp->signalfunction;
+							int id = SHORT1FROMMP(mp1);
+							HWND conthwnd = dw_window_from_id(hWnd, id);
+							char *text = NULL;
+							void *user = NULL;
+							LONG x,y;
+
+							if(mp2)
+							{
+								PCNRITEM pci;
+
+								pci = (PCNRITEM)mp2;
+
+								text = pci->rc.pszIcon;
+								user = pci->user;
+							}
+
+							dw_pointer_query_pos(&x, &y);
+
+							if(tmp->window == conthwnd)
+							{
+								int container = (int)dw_window_get_data(tmp->window, "_dw_container");
+
+								if(mp2)
+								{
+									if(!container)
+									{
+										NOTIFYRECORDEMPHASIS pre;
+
+										dw_tree_item_select(tmp->window, (HTREEITEM)mp2);
+										pre.pRecord = mp2;
+										pre.fEmphasisMask = CRA_CURSORED;
+										pre.hwndCnr = tmp->window;
+										_run_event(hWnd, WM_CONTROL, MPFROM2SHORT(0, CN_EMPHASIS), (MPARAM)&pre);
+										pre.pRecord->flRecordAttr |= CRA_CURSORED;
+									}
+									else
+									{
+										if(pCoreEmph)
+											_clear_emphasis();
+										hwndEmph = tmp->window;
+										pCoreEmph = mp2;
+										WinSendMsg(tmp->window, CM_SETRECORDEMPHASIS, mp2, MPFROM2SHORT(TRUE, CRA_SOURCE));
+									}
+								}
+								result = containercontextfunc(tmp->window, text, x, y, tmp->data, user);
+								tmp = NULL;
+							}
+						}
+						break;
+					case CN_EMPHASIS:
+						{
+							PNOTIFYRECORDEMPHASIS pre = (PNOTIFYRECORDEMPHASIS)mp2;
+							static int emph_recurse = 0;
+
+							if(!emph_recurse)
+							{
+								emph_recurse = 1;
+
+								if(mp2)
+								{
+									if(tmp->window == pre->hwndCnr)
+									{
+										PCNRITEM pci = (PCNRITEM)pre->pRecord;
+
+										if(pci && pre->fEmphasisMask & CRA_CURSORED && (pci->rc.flRecordAttr & CRA_CURSORED))
+										{
+											int (* API treeselectfunc)(HWND, HTREEITEM, char *, void *, void *) = (int (* API)(HWND, HTREEITEM, char *, void *, void *))tmp->signalfunction;
+
+											if(dw_window_get_data(tmp->window, "_dw_container"))
+												result = treeselectfunc(tmp->window, 0, pci->rc.pszIcon, tmp->data, 0);
+											else
+											{
+												if(lasthcnr == tmp->window && lastitem == (HWND)pci)
+												{
+													lasthcnr = 0;
+													lastitem = 0;
+												}
+												else
+												{
+													lasthcnr = tmp->window;
+													lastitem = (HWND)pci;
+													result = treeselectfunc(tmp->window, (HTREEITEM)pci, pci->rc.pszIcon, tmp->data, pci->user);
+												}
+											}
+											tmp = NULL;
+										}
+									}
+								}
+								emph_recurse = 0;
+							}
+						}
+						break;
+					case LN_SELECT:
+						{
+							char classbuf[100];
+
+							WinQueryClassName(tmp->window, 99, classbuf);
+
+							if(strncmp(classbuf, "#38", 4) == 0)
+							{
+								int (* API valuechangedfunc)(HWND, int, void *) = (int (* API)(HWND, int, void *))tmp->signalfunction;
+
+								if(tmp->window == hWnd || WinQueryWindow(tmp->window, QW_PARENT) == hWnd)
+								{
+									static int lastvalue = -1;
+									static HWND lasthwnd = NULLHANDLE;
+									int ulValue = (int)WinSendMsg(tmp->window, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), 0);
+									if(lastvalue != ulValue || lasthwnd != tmp->window)
+									{
+										result = valuechangedfunc(tmp->window, ulValue, tmp->data);
+										lastvalue = ulValue;
+										lasthwnd = tmp->window;
+									}
+									tmp = NULL;
+								}
+							}
+							else
+							{
+								int (* API listboxselectfunc)(HWND, int, void *) = (int (* API )(HWND, int, void *))tmp->signalfunction;
+								int id = SHORT1FROMMP(mp1);
+								HWND conthwnd = dw_window_from_id(hWnd, id);
+								static int _recursing = 0;
+
+								if(_recursing == 0 && (tmp->window == conthwnd || (!id && tmp->window == (HWND)mp2)))
+								{
+									char buf1[500];
+									unsigned int index = dw_listbox_selected(tmp->window);
+
+									dw_listbox_query_text(tmp->window, index, buf1, 500);
+
+									_recursing = 1;
+
+									if(id && strncmp(classbuf, "#2", 3)==0)
+									{
+										char *buf2;
+
+										buf2 = dw_window_get_text(tmp->window);
+
+										/* This is to make sure the listboxselect function doesn't
+										 * get called if the user is modifying the entry text.
+										 */
+										if(buf2 && *buf2 && *buf1 && strncmp(buf1, buf2, 500) == 0)
+											result = listboxselectfunc(tmp->window, index, tmp->data);
+
+										if(buf2)
+											free(buf2);
+									}
+									else
+										result = listboxselectfunc(tmp->window, index, tmp->data);
+
+									_recursing = 0;
+									tmp = NULL;
+								}
+							}
+						}
+						break;
+					case SLN_SLIDERTRACK:
+						{
+							int (* API valuechangedfunc)(HWND, int, void *) = (int (* API)(HWND, int, void *))tmp->signalfunction;
+
+							if(origmsg == WM_CONTROL)
+							{
+								/* Handle Slider control */
+								if(tmp->window == hWnd || WinQueryWindow(tmp->window, QW_PARENT) == hWnd)
+								{
+									static int lastvalue = -1;
+									static HWND lasthwnd = NULLHANDLE;
+									int ulValue = (int)WinSendMsg(tmp->window, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), 0);
+									if(lastvalue != ulValue || lasthwnd != tmp->window)
+									{
+										dw_window_set_data(tmp->window, "_dw_slider_value", (void *)ulValue);
+										result = valuechangedfunc(tmp->window, ulValue, tmp->data);
+										lastvalue = ulValue;
+										lasthwnd = tmp->window;
+									}
+									tmp = NULL;
+								}
+							}
+							else
+							{
+								/* Handle scrollbar control */
+								if(tmp->window > 65535 && tmp->window == WinWindowFromID(hWnd, (ULONG)mp1))
+								{
+									int pos = _HandleScroller(tmp->window, (int)SHORT1FROMMP(mp2), (int)SHORT2FROMMP(mp2));;
+
+									if(pos > -1)
+									{
+										dw_window_set_data(tmp->window, "_dw_scrollbar_value", (void *)pos);
+										result = valuechangedfunc(tmp->window, pos, tmp->data);
+									}
+									result = 0;
+									tmp = NULL;
+								}
+							}
+						}
+						break;
+					case BKN_PAGESELECTED:
+						{
+							PAGESELECTNOTIFY *psn = (PAGESELECTNOTIFY *)mp2;
+
+							if(psn && tmp->window == psn->hwndBook)
+							{
+								int (* API switchpagefunc)(HWND, unsigned long, void *) = (int (* API)(HWND, unsigned long, void *))tmp->signalfunction;
+
+								result = switchpagefunc(tmp->window, psn->ulPageIdNew, tmp->data);
+								tmp = NULL;
+							}
+						}
+						break;
+					}
+				}
+				break;
+			}
+		}
+
+		if(tmp)
+			tmp = tmp->next;
+
+	}
+	return (MRESULT)result;
+}
+
+/* Handles control messages sent to the box (owner). */
+MRESULT EXPENTRY _controlproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+	Box *blah = WinQueryWindowPtr(hWnd, QWP_USER);
+
+	switch(msg)
+	{
+	case WM_VSCROLL:
+	case WM_HSCROLL:
+		if(_run_event(hWnd, msg, mp1, mp2))
+		{
+			HWND window = WinWindowFromID(hWnd, (ULONG)mp1);
+			_HandleScroller(window, (int)SHORT1FROMMP(mp2), (int)SHORT2FROMMP(mp2));
+		}
+		break;
+	case WM_CONTROL:
+		_run_event(hWnd, msg, mp1, mp2);
+		break;
+	}
+
+	if(blah && blah->oldproc)
+		return blah->oldproc(hWnd, msg, mp1, mp2);
+
+	return WinDefWindowProc(hWnd, msg, mp1, mp2);
+}
+
+/* The main window procedure for Dynamic Windows, all the resizing code is done here. */
+MRESULT EXPENTRY _wndproc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+	int result = -1;
+	static int command_active = 0;
+	void (* API windowfunc)(PVOID) = 0L;
+
+	if(!command_active)
+	{
+        /* Make sure we don't end up in infinite recursion */
+		command_active = 1;
+
+		result = (int)_run_event(hWnd, msg, mp1, mp2);
+
+		command_active = 0;
+	}
+
+	/* Now that any handlers are done... do normal processing */
+	switch( msg )
+	{
+   case WM_ERASEBACKGROUND:
+      return 0;
+
+	case WM_PAINT:
+		{
+		HPS    hps;
+		RECTL  rc;
+
+		hps = WinBeginPaint( hWnd, 0L, &rc );
+		WinEndPaint( hps );
+		break;
+		}
+
+	case WM_SIZE:
+		{
+			Box *mybox = (Box *)WinQueryWindowPtr(hWnd, QWP_USER);
+
+			if(!SHORT1FROMMP(mp2) && !SHORT2FROMMP(mp2))
+				return (MPARAM)TRUE;
+
+			if(mybox && mybox->flags != DW_MINIMIZED)
+			{
+				/* Hide the window when recalculating to reduce
+				 * CPU load.
+				 */
+				WinShowWindow(hWnd, FALSE);
+
+				_do_resize(mybox, SHORT1FROMMP(mp2), SHORT2FROMMP(mp2));
+
+				WinShowWindow(hWnd, TRUE);
+			}
+		}
+		break;
+	case WM_MINMAXFRAME:
+		{
+			Box *mybox = (Box *)WinQueryWindowPtr(hWnd, QWP_USER);
+			SWP *swp = (SWP *)mp1;
+
+			if(mybox && (swp->fl & SWP_MINIMIZE))
+				mybox->flags = DW_MINIMIZED;
+
+			if(mybox && (swp->fl & SWP_RESTORE))
+			{
+				if(!mybox->titlebar && mybox->hwndtitle)
+					WinSetParent(mybox->hwndtitle, HWND_OBJECT, FALSE);
+				mybox->flags = 0;
+			}
+
+			if(mybox && (swp->fl & SWP_MAXIMIZE))
+			{
+				int z;
+				SWP swp2;
+
+				WinQueryWindowPos(swp->hwnd, &swp2);
+
+				if(swp2.cx == swp->cx && swp2.cy == swp->cy)
+					return FALSE;
+
+				mybox->flags = 0;
+
+				/* Hide the window when recalculating to reduce
+				 * CPU load.
+				 */
+				WinShowWindow(hWnd, FALSE);
+
+				_do_resize(mybox, swp->cx, swp->cy);
+
+				if(mybox->count == 1 && mybox->items[0].type == TYPEBOX)
+				{
+					mybox = (Box *)WinQueryWindowPtr(mybox->items[0].hwnd, QWP_USER);
+
+					for(z=0;z<mybox->count;z++)
+						_check_resize_notebook(mybox->items[z].hwnd);
+
+				}
+
+				WinShowWindow(hWnd, TRUE);
+			}
+		}
+		break;
+	case WM_CONTROL:
+		switch(SHORT2FROMMP(mp1))
+		{
+		case BKN_PAGESELECTEDPENDING:
+			{
+				PAGESELECTNOTIFY *psn = (PAGESELECTNOTIFY *)mp2;
+				HWND pagehwnd = (HWND)WinSendMsg(psn->hwndBook, BKM_QUERYPAGEWINDOWHWND, MPFROMLONG(psn->ulPageIdNew), 0);
+				Box *pagebox = (Box *)WinQueryWindowPtr(pagehwnd, QWP_USER);
+				unsigned long x, y, width, height;
+				RECTL rc;
+
+				if(pagebox && psn->ulPageIdNew != psn->ulPageIdCur)
+				{
+					dw_window_get_pos_size(psn->hwndBook, &x, &y, &width, &height);
+
+					rc.xLeft = x;
+					rc.yBottom = y;
+					rc.xRight = x + width;
+					rc.yTop = y + height;
+
+					WinSendMsg(psn->hwndBook, BKM_CALCPAGERECT, (MPARAM)&rc, (MPARAM)TRUE);
+
+					_do_resize(pagebox, rc.xRight - rc.xLeft, rc.yTop - rc.yBottom);
+				}
+			}
+			break;
+		}
+		break;
+	case WM_CLOSE:
+		if(result == -1)
+		{
+			dw_window_destroy(WinQueryWindow(hWnd, QW_PARENT));
+			return (MRESULT)TRUE;
+		}
+		break;
+	case WM_MOUSEMOVE:
+		{
+			HPOINTER ptr = (HPOINTER)dw_window_get_data(hWnd, "_dw_pointer");
+
+			if(ptr)
+				WinSetPointer(HWND_DESKTOP, ptr);
+		}
+		break;
+	case WM_USER:
+		windowfunc = (void (* API)(void *))mp1;
+
+		if(windowfunc)
+			windowfunc((void *)mp2);
+		break;
+	case WM_CHAR:
+		if(SHORT1FROMMP(mp2) == '\t')
+		{
+			if(CHARMSG(&msg)->fs & KC_SHIFT)
+				_shift_focus_back(hWnd);
+			else
+				_shift_focus(hWnd);
+			return FALSE;
+		}
+		break;
+	case WM_DESTROY:
+		{
+			HWND parent = WinQueryWindow(hWnd, QW_PARENT);
+
+			/* Free memory before destroying */
+			if(parent && WinWindowFromID(parent, FID_CLIENT) == hWnd)
+				_free_window_memory(parent);
+			else
+				_free_window_memory(hWnd);
+		}
+		break;
+	case WM_MENUEND:
+		_clear_emphasis();
+		if(dw_window_get_data((HWND)mp2, "_dw_popup"))
+			_free_menu_data((HWND)mp2);
+		break;
+	}
+
+	if(result != -1)
+		return (MRESULT)result;
+	else
+		return WinDefWindowProc(hWnd, msg, mp1, mp2);
+}
+
+void _changebox(Box *thisbox, int percent, int type)
+{
+	int z;
+
+	for(z=0;z<thisbox->count;z++)
+	{
+		if(thisbox->items[z].type == TYPEBOX)
+		{
+			Box *tmp = WinQueryWindowPtr(thisbox->items[z].hwnd, QWP_USER);
+			_changebox(tmp, percent, type);
+		}
+		else
+		{
+			if(type == DW_HORZ)
+			{
+				if(thisbox->items[z].hsize == SIZEEXPAND)
+					thisbox->items[z].width = (int)(((float)thisbox->items[z].origwidth) * (((float)percent)/((float)100.0)));
+			}
+			else
+			{
+				if(thisbox->items[z].vsize == SIZEEXPAND)
+					thisbox->items[z].height = (int)(((float)thisbox->items[z].origheight) * (((float)percent)/((float)100.0)));
+			}
+		}
+	}
+}
+
+void _handle_splitbar_resize(HWND hwnd, float percent, int type, int x, int y)
+{
+	if(type == DW_HORZ)
+	{
+		int newx = x;
+		float ratio = (float)percent/(float)100.0;
+		HWND handle1 = (HWND)dw_window_get_data(hwnd, "_dw_topleft");
+		HWND handle2 = (HWND)dw_window_get_data(hwnd, "_dw_bottomright");
+		Box *tmp = WinQueryWindowPtr(handle1, QWP_USER);
+
+		WinShowWindow(handle1, FALSE);
+		WinShowWindow(handle2, FALSE);
+
+		newx = (int)((float)newx * ratio) - (SPLITBAR_WIDTH/2);
+
+		WinSetWindowPos(handle1, NULLHANDLE, 0, 0, newx, y, SWP_MOVE | SWP_SIZE);
+		_do_resize(tmp, newx - 1, y - 1);
+
+		dw_window_set_data(hwnd, "_dw_start", (void *)newx);
+
+		tmp = WinQueryWindowPtr(handle2, QWP_USER);
+
+		newx = x - newx - SPLITBAR_WIDTH;
+
+		WinSetWindowPos(handle2, NULLHANDLE, x - newx, 0, newx, y, SWP_MOVE | SWP_SIZE);
+		_do_resize(tmp, newx - 1, y - 1);
+
+		WinShowWindow(handle1, TRUE);
+		WinShowWindow(handle2, TRUE);
+	}
+	else
+	{
+		int newy = y;
+		float ratio = (float)percent/(float)100.0;
+		HWND handle1 = (HWND)dw_window_get_data(hwnd, "_dw_topleft");
+		HWND handle2 = (HWND)dw_window_get_data(hwnd, "_dw_bottomright");
+		Box *tmp = WinQueryWindowPtr(handle1, QWP_USER);
+
+		WinShowWindow(handle1, FALSE);
+		WinShowWindow(handle2, FALSE);
+
+		newy = (int)((float)newy * ratio) - (SPLITBAR_WIDTH/2);
+
+		WinSetWindowPos(handle1, NULLHANDLE, 0, y - newy, x, newy, SWP_MOVE | SWP_SIZE);
+		_do_resize(tmp, x - 1, newy - 1);
+
+		tmp = WinQueryWindowPtr(handle2, QWP_USER);
+
+		newy = y - newy - SPLITBAR_WIDTH;
+
+		WinSetWindowPos(handle2, NULLHANDLE, 0, 0, x, newy, SWP_MOVE | SWP_SIZE);
+		_do_resize(tmp, x - 1, newy - 1);
+
+		WinShowWindow(handle1, TRUE);
+		WinShowWindow(handle2, TRUE);
+
+		dw_window_set_data(hwnd, "_dw_start", (void *)newy);
+	}
+}
+
+
+/* This handles any activity on the splitbars (sizers) */
+MRESULT EXPENTRY _splitwndproc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+	float *percent = (float *)dw_window_get_data(hwnd, "_dw_percent");
+	int type = (int)dw_window_get_data(hwnd, "_dw_type");
+	int start = (int)dw_window_get_data(hwnd, "_dw_start");
+
+	switch (msg)
+	{
+	case WM_ACTIVATE:
+	case WM_SETFOCUS:
+		return (MRESULT)(FALSE);
+
+	case WM_PAINT:
+		{
+			HPS hps;
+			POINTL ptl[2];
+			RECTL rcl;
+
+			hps = WinBeginPaint(hwnd, 0, 0);
+
+			WinQueryWindowRect(hwnd, &rcl);
+
+			if(type == DW_HORZ)
+			{
+				ptl[0].x = rcl.xLeft + start;
+				ptl[0].y = rcl.yBottom;
+				ptl[1].x = rcl.xRight + start + 3;
+				ptl[1].y = rcl.yTop;
+			}
+			else
+			{
+				ptl[0].x = rcl.xLeft;
+				ptl[0].y = rcl.yBottom + start;
+				ptl[1].x = rcl.xRight;
+				ptl[1].y = rcl.yTop + start + 3;
+			}
+
+
+			GpiSetColor(hps, CLR_PALEGRAY);
+			GpiMove(hps, &ptl[0]);
+			GpiBox(hps, DRO_OUTLINEFILL, &ptl[1], 0, 0);
+			WinEndPaint(hps);
+		}
+		return MRFROMSHORT(FALSE);
+
+	case WM_MOUSEMOVE:
+		{
+			if(type == DW_HORZ)
+				WinSetPointer(HWND_DESKTOP,
+							  WinQuerySysPointer(HWND_DESKTOP,
+												 SPTR_SIZEWE,
+												 FALSE));
+			else
+				WinSetPointer(HWND_DESKTOP,
+							  WinQuerySysPointer(HWND_DESKTOP,
+												 SPTR_SIZENS,
+												 FALSE));
+		}
+		return MRFROMSHORT(FALSE);
+	case WM_BUTTON1DOWN:
+		{
+			APIRET rc;
+			RECTL  rclFrame;
+			RECTL  rclBounds;
+
+			WinQueryWindowRect(hwnd, &rclFrame);
+			WinQueryWindowRect(hwnd, &rclBounds);
+
+			WinMapWindowPoints(hwnd, HWND_DESKTOP,
+							   (PPOINTL)&rclBounds, 2);
+
+
+			if(type == DW_HORZ)
+			{
+				rclFrame.xLeft = start;
+				rclFrame.xRight = start + SPLITBAR_WIDTH;
+			}
+			else
+			{
+				rclFrame.yBottom = start;
+				rclFrame.yTop = start + SPLITBAR_WIDTH;
+			}
+
+			if(percent)
+			{
+				rc = _TrackRectangle(hwnd, &rclFrame, &rclBounds);
+
+				if(rc == TRUE)
+				{
+					int width = (rclBounds.xRight - rclBounds.xLeft);
+					int height = (rclBounds.yTop - rclBounds.yBottom);
+
+					if(type == DW_HORZ)
+					{
+						start = rclFrame.xLeft - rclBounds.xLeft;
+						if(width - SPLITBAR_WIDTH > 1 && start < width - SPLITBAR_WIDTH)
+							*percent = ((float)start / (float)(width - SPLITBAR_WIDTH)) * 100.0;
+					}
+					else
+					{
+						start = rclFrame.yBottom - rclBounds.yBottom;
+						if(height - SPLITBAR_WIDTH > 1 && start < height - SPLITBAR_WIDTH)
+							*percent = 100.0 - (((float)start / (float)(height - SPLITBAR_WIDTH)) * 100.0);
+					}
+					_handle_splitbar_resize(hwnd, *percent, type, width, height);
+				}
+			}
+		}
+		return MRFROMSHORT(FALSE);
+	}
+	return WinDefWindowProc(hwnd, msg, mp1, mp2);
+}
+
+/* Function: BubbleProc
+ * Abstract: Subclass procedure for bubble help
+ */
+MRESULT EXPENTRY _BubbleProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+	MRESULT res;
+	PFNWP proc = (PFNWP)WinQueryWindowPtr(hwnd, QWL_USER);
+
+	if(proc)
+		res = proc(hwnd, msg, mp1, mp2);
+	else
+		res = WinDefWindowProc(hwnd, msg, mp1, mp2);
+
+	if(msg == WM_PAINT)
+	{
+		POINTL ptl;
+		HPS hpsTemp;
+		RECTL rcl;
+		int height, width;
+
+		WinQueryWindowRect(hwnd, &rcl);
+		height = rcl.yTop - rcl.yBottom - 1;
+		width = rcl.xRight - rcl.xLeft - 1;
+
+		/* Draw a border around the bubble help */
+		hpsTemp = WinGetPS(hwnd);
+		GpiSetColor(hpsTemp, CLR_BLACK);
+		ptl.x = ptl.y = 0;
+		GpiMove(hpsTemp, &ptl);
+		ptl.x = 0;
+		ptl.y = height;
+		GpiLine(hpsTemp, &ptl);
+		ptl.x = ptl.y = 0;
+		GpiMove(hpsTemp, &ptl);
+		ptl.y = 0;
+		ptl.x = width;
+		GpiLine(hpsTemp, &ptl);
+		ptl.x = width;
+		ptl.y = height;
+		GpiMove(hpsTemp, &ptl);
+		ptl.x = 0;
+		ptl.y = height;
+		GpiLine(hpsTemp, &ptl);
+		ptl.x = width;
+		ptl.y = height;
+		GpiMove(hpsTemp, &ptl);
+		ptl.y = 0;
+		ptl.x = width;
+		GpiLine(hpsTemp, &ptl);
+		WinReleasePS(hpsTemp);
+	}
+	return res;
+}
+
+MRESULT EXPENTRY _button_draw(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2, PFNWP oldproc, int indent)
+{
+	HPIXMAP pixmap = (HPIXMAP)dw_window_get_data(hwnd, "_dw_hpixmap");
+	HPIXMAP disable = (HPIXMAP)dw_window_get_data(hwnd, "_dw_hpixmap_disabled");
+	MRESULT res;
+
+	if(!oldproc)
+		res = WinDefWindowProc(hwnd, msg, mp1, mp2);
+	res = oldproc(hwnd, msg, mp1, mp2);
+
+	if(pixmap)
+	{
+		unsigned long width, height;
+		int x, y;
+
+		dw_window_get_pos_size(hwnd, NULL, NULL, &width, &height);
+
+		x = (width - pixmap->width)/2;
+		y = (height - pixmap->height)/2;
+
+		if(disable && dw_window_get_data(hwnd, "_dw_disabled"))
+			dw_pixmap_bitblt(hwnd, 0, x + indent, y + indent, pixmap->width, pixmap->height, 0, disable, 0, 0);
+		else
+			dw_pixmap_bitblt(hwnd, 0, x + indent, y + indent, pixmap->width, pixmap->height, 0, pixmap, 0, 0);
+	}
+	return res;
+}
+
+/* Function: BtProc
+ * Abstract: Subclass procedure for buttons
+ */
+
+MRESULT EXPENTRY _BtProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+	BubbleButton *bubble;
+	PFNWP oldproc;
+
+	bubble = (BubbleButton *)WinQueryWindowPtr(hwnd, QWL_USER);
+
+	if(!bubble)
+		return WinDefWindowProc(hwnd, msg, mp1, mp2);
+
+	oldproc = bubble->pOldProc;
+
+	switch(msg)
+	{
+	case WM_PAINT:
+		return _button_draw(hwnd, msg, mp1, mp2, oldproc, 0);
+	case BM_SETHILITE:
+		return _button_draw(hwnd, msg, mp1, mp2, oldproc, (int)mp1);
+	case WM_SETFOCUS:
+		if(mp2)
+			_run_event(hwnd, msg, mp1, mp2);
+		else
+			WinSendMsg(hwnd, BM_SETDEFAULT, 0, 0);
+		break;
+	case WM_BUTTON1DOWN:
+	case WM_BUTTON2DOWN:
+	case WM_BUTTON3DOWN:
+	case WM_BUTTON1DBLCLK:
+	case WM_BUTTON2DBLCLK:
+	case WM_BUTTON3DBLCLK:
+		if(dw_window_get_data(hwnd, "_dw_disabled"))
+			return (MRESULT)FALSE;
+		break;
+	case WM_BUTTON1UP:
+		{
+			SignalHandler *tmp = Root;
+
+			if(WinIsWindowEnabled(hwnd) && !dw_window_get_data(hwnd, "_dw_disabled"))
+			{
+				/* Find any callbacks for this function */
+				while(tmp)
+				{
+					if(tmp->message == WM_COMMAND)
+					{
+						/* Make sure it's the right window, and the right ID */
+						if(tmp->window == hwnd)
+						{
+							/* Due to the fact that if we run the function
+							 * here, finishing actions on the button will occur
+							 * after we run the signal handler.  So we post the
+							 * message so the button can finish what it needs to
+							 * do before we run our handler.
+							 */
+							WinPostMsg(hwnd, WM_USER, (MPARAM)tmp, 0);
+							tmp = NULL;
+						}
+					}
+					if(tmp)
+						tmp= tmp->next;
+				}
+			}
+		}
+		break;
+	case WM_USER:
+		{
+            SignalHandler *tmp = (SignalHandler *)mp1;
+			int (* API clickfunc)(HWND, void *) = NULL;
+
+			if(tmp)
+			{
+				clickfunc = (int (* API)(HWND, void *))tmp->signalfunction;
+
+				clickfunc(tmp->window, tmp->data);
+			}
+		}
+        break;
+	case WM_CHAR:
+		{
+			/* A button press should also occur for an ENTER or SPACE press
+			 * while the button has the active input focus.
+			 */
+			if(SHORT1FROMMP(mp2) == '\r' || SHORT1FROMMP(mp2) == ' ')
+			{
+				SignalHandler *tmp = Root;
+
+				/* Find any callbacks for this function */
+				while(tmp)
+				{
+					if(tmp->message == WM_COMMAND)
+					{
+						/* Make sure it's the right window, and the right ID */
+						if(tmp->window == hwnd)
+						{
+							WinPostMsg(hwnd, WM_USER, (MPARAM)tmp, 0);
+							tmp = NULL;
+						}
+					}
+					if(tmp)
+						tmp= tmp->next;
+				}
+			}
+			if(SHORT1FROMMP(mp2) == '\t')
+			{
+				if(CHARMSG(&msg)->fs & KC_SHIFT)
+					_shift_focus_back(hwnd);
+				else
+					_shift_focus(hwnd);
+				WinSendMsg(hwnd, BM_SETDEFAULT, 0, 0);
+				return FALSE;
+			}
+			else if(!(CHARMSG(&msg)->fs & KC_KEYUP) && (CHARMSG(&msg)->vkey == VK_LEFT || CHARMSG(&msg)->vkey == VK_UP))
+			{
+				_shift_focus_back(hwnd);
+				return FALSE;
+			}
+			else if(!(CHARMSG(&msg)->fs & KC_KEYUP) && (CHARMSG(&msg)->vkey == VK_RIGHT || CHARMSG(&msg)->vkey == VK_DOWN))
+			{
+				_shift_focus(hwnd);
+				return FALSE;
+			}
+		}
+		break;
+	case 0x041f:
+		if (hwndBubble)
+		{
+			WinDestroyWindow(hwndBubble);
+			hwndBubble = 0;
+		}
+		break;
+
+	case 0x041e:
+
+		if(!*bubble->bubbletext)
+			break;
+
+		if(hwndBubble)
+		{
+			WinDestroyWindow(hwndBubble);
+			hwndBubble = 0;
+		}
+
+		if(!hwndBubble)
+		{
+			HPS   hpsTemp = 0;
+			LONG  lHight;
+			LONG  lWidth;
+			POINTL txtPointl[TXTBOX_COUNT];
+			POINTL ptlWork = {0,0};
+			ULONG ulColor = CLR_YELLOW;
+			void *blah;
+
+			hwndBubbleLast   = hwnd;
+			hwndBubble = WinCreateWindow(HWND_DESKTOP,
+										 WC_STATIC,
+										 "",
+										 SS_TEXT |
+										 DT_CENTER |
+										 DT_VCENTER,
+                                         0,0,0,0,
+										 HWND_DESKTOP,
+										 HWND_TOP,
+										 0,
+										 NULL,
+										 NULL);
+
+			WinSetPresParam(hwndBubble,
+							PP_FONTNAMESIZE,
+							strlen(DefaultFont)+1,
+							DefaultFont);
+
+
+			WinSetPresParam(hwndBubble,
+							PP_BACKGROUNDCOLORINDEX,
+							sizeof(ulColor),
+							&ulColor);
+
+			WinSetWindowText(hwndBubble,
+							 bubble->bubbletext);
+
+			WinMapWindowPoints(hwnd, HWND_DESKTOP, &ptlWork, 1);
+
+			hpsTemp = WinGetPS(hwndBubble);
+			GpiQueryTextBox(hpsTemp,
+							strlen(bubble->bubbletext),
+							bubble->bubbletext,
+							TXTBOX_COUNT,
+							txtPointl);
+			WinReleasePS(hpsTemp);
+
+			lWidth = txtPointl[TXTBOX_TOPRIGHT].x -
+				txtPointl[TXTBOX_TOPLEFT ].x + 8;
+
+			lHight = txtPointl[TXTBOX_TOPLEFT].y -
+				txtPointl[TXTBOX_BOTTOMLEFT].y + 8;
+
+			ptlWork.y -= lHight;
+
+			blah = (void *)WinSubclassWindow(hwndBubble, _BubbleProc);
+
+			if(blah)
+				WinSetWindowPtr(hwndBubble, QWP_USER, blah);
+
+			WinSetWindowPos(hwndBubble,
+							HWND_TOP,
+							ptlWork.x,
+							ptlWork.y,
+							lWidth,
+							lHight,
+							SWP_SIZE | SWP_MOVE | SWP_SHOW);
+		}
+		break;
+	}
+
+	if(!oldproc)
+		return WinDefWindowProc(hwnd, msg, mp1, mp2);
+	return oldproc(hwnd, msg, mp1, mp2);
+}
+
+MRESULT EXPENTRY _RendProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+	int res = 0;
+	res = (int)_run_event(hwnd, msg, mp1, mp2);
+	switch(msg)
+	{
+	case WM_BUTTON1DOWN:
+	case WM_BUTTON2DOWN:
+	case WM_BUTTON3DOWN:
+		if(res == -1)
+			WinSetFocus(HWND_DESKTOP, hwnd);
+		else if(res)
+			return (MPARAM)TRUE;
+	}
+	return WinDefWindowProc(hwnd, msg, mp1, mp2);
+}
+
+MRESULT EXPENTRY _TreeProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+	WindowData *blah = (WindowData *)WinQueryWindowPtr(hwnd, QWP_USER);
+	PFNWP oldproc = 0;
+
+	if(blah)
+		oldproc = blah->oldproc;
+
+	switch(msg)
+	{
+	case WM_PAINT:
+		{
+			HPS hps;
+			RECTL rcl;
+			POINTL ptl[2];
+
+			if(oldproc)
+				oldproc(hwnd, msg, mp1, mp2);
+
+			hps = WinBeginPaint(hwnd, 0, 0);
+			WinQueryWindowRect(hwnd, &rcl);
+			ptl[0].x = rcl.xLeft + 1;
+			ptl[0].y = rcl.yBottom + 1;
+			ptl[1].x = rcl.xRight - 1;
+			ptl[1].y = rcl.yTop - 1;
+
+			GpiSetColor(hps, CLR_BLACK);
+			GpiMove(hps, &ptl[0]);
+			GpiBox(hps, DRO_OUTLINE, &ptl[1], 0, 0);
+			WinEndPaint(hps);
+		}
+		return MRFROMSHORT(FALSE);
+	case WM_SETFOCUS:
+		_run_event(hwnd, msg, mp1, mp2);
+		break;
+	case WM_CHAR:
+		if(SHORT1FROMMP(mp2) == '\t')
+		{
+			if(CHARMSG(&msg)->fs & KC_SHIFT)
+				_shift_focus_back(hwnd);
+			else
+				_shift_focus(hwnd);
+			return FALSE;
+		}
+		break;
+	}
+
+	_run_event(hwnd, msg, mp1, mp2);
+
+	if(oldproc)
+		return oldproc(hwnd, msg, mp1, mp2);
+
+	return WinDefWindowProc(hwnd, msg, mp1, mp2);
+}
+
+/*
+ * Initializes the Dynamic Windows engine.
+ * Parameters:
+ *           newthread: True if this is the only thread.
+ *                      False if there is already a message loop running.
+ */
+int API dw_init(int newthread, int argc, char *argv[])
+{
+	APIRET rc;
+
+	argc = argc; /* keep compiler happy */
+	argv = argv; /* keep compiler happy */
+	if(newthread)
+	{
+		dwhab = WinInitialize(0);
+		dwhmq = WinCreateMsgQueue(dwhab, 0);
+	}
+
+	rc = WinRegisterClass(dwhab, ClassName, _wndproc, CS_SIZEREDRAW | CS_CLIPCHILDREN, 32);
+	rc = WinRegisterClass(dwhab, SplitbarClassName, _splitwndproc, 0L, 32);
+
+	/* Get the OS/2 version. */
+	DosQuerySysInfo(QSV_VERSION_MAJOR, QSV_MS_COUNT,(void *)aulBuffer, 4*sizeof(ULONG));
+
+	desktop = WinQueryDesktopWindow(dwhab, NULLHANDLE);
+
+	if(!IS_WARP4())
+		DefaultFont = "8.Helv";
+
+	/* This is a window that hangs around as long as the
+	 * application does and handles menu messages.
+	 */
+	hwndApp = dw_window_new(HWND_OBJECT, "", 0);
+
+	return rc;
+}
+
+/*
+ * Runs a message loop for Dynamic Windows.
+ */
+void API dw_main(void)
+{
+	QMSG qmsg;
+
+	_dwtid = dw_thread_id();
+
+	while(WinGetMsg(dwhab, &qmsg, 0, 0, 0))
+	{
+		if(qmsg.msg == WM_TIMER && qmsg.hwnd == NULLHANDLE)
+			_run_event(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2);
+		WinDispatchMsg(dwhab, &qmsg);
+	}
+
+	WinDestroyMsgQueue(dwhmq);
+	WinTerminate(dwhab);
+}
+
+/*
+ * Runs a message loop for Dynamic Windows, for a period of milliseconds.
+ * Parameters:
+ *           milliseconds: Number of milliseconds to run the loop for.
+ */
+void API dw_main_sleep(int milliseconds)
+{
+	QMSG qmsg;
+#ifdef __EMX__
+	struct timeval tv, start;
+
+	gettimeofday(&start, NULL);
+	gettimeofday(&tv, NULL);
+
+	while(((tv.tv_sec - start.tv_sec)*1000) + ((tv.tv_usec - start.tv_usec)/1000) <= milliseconds)
+	{
+		if(WinPeekMsg(dwhab, &qmsg, 0, 0, 0, PM_NOREMOVE))
+		{
+			WinGetMsg(dwhab, &qmsg, 0, 0, 0);
+			if(qmsg.msg == WM_TIMER && qmsg.hwnd == NULLHANDLE)
+				_run_event(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2);
+			WinDispatchMsg(dwhab, &qmsg);
+		}
+		else
+			DosSleep(1);
+		gettimeofday(&tv, NULL);
+	}
+#else
+	double start = (double)clock();
+
+	while(((clock() - start) / (CLOCKS_PER_SEC/1000)) <= milliseconds)
+	{
+		if(WinPeekMsg(dwhab, &qmsg, 0, 0, 0, PM_NOREMOVE))
+		{
+			WinGetMsg(dwhab, &qmsg, 0, 0, 0);
+			if(qmsg.msg == WM_TIMER && qmsg.hwnd == NULLHANDLE)
+				_run_event(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2);
+			WinDispatchMsg(dwhab, &qmsg);
+		}
+		else
+			DosSleep(1);
+	}
+#endif
+}
+
+/*
+ * Processes a single message iteration and returns.
+ */
+void API dw_main_iteration(void)
+{
+	QMSG qmsg;
+
+	_dwtid = dw_thread_id();
+
+	if(WinGetMsg(dwhab, &qmsg, 0, 0, 0))
+	{
+		if(qmsg.msg == WM_TIMER && qmsg.hwnd == NULLHANDLE)
+			_run_event(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2);
+		WinDispatchMsg(dwhab, &qmsg);
+	}
+}
+
+/*
+ * Free's memory allocated by dynamic windows.
+ * Parameters:
+ *           ptr: Pointer to dynamic windows allocated
+ *                memory to be free()'d.
+ */
+void API dw_free(void *ptr)
+{
+	free(ptr);
+}
+
+/*
+ * Allocates and initializes a dialog struct.
+ * Parameters:
+ *           data: User defined data to be passed to functions.
+ */
+DWDialog * API dw_dialog_new(void *data)
+{
+	DWDialog *tmp = malloc(sizeof(DWDialog));
+
+	tmp->eve = dw_event_new();
+	dw_event_reset(tmp->eve);
+	tmp->data = data;
+	tmp->done = FALSE;
+	tmp->result = NULL;
+
+    return tmp;
+}
+
+/*
+ * Accepts a dialog struct and returns the given data to the
+ * initial called of dw_dialog_wait().
+ * Parameters:
+ *           dialog: Pointer to a dialog struct aquired by dw_dialog_new).
+ *           result: Data to be returned by dw_dialog_wait().
+ */
+int API dw_dialog_dismiss(DWDialog *dialog, void *result)
+{
+	dialog->result = result;
+	dw_event_post(dialog->eve);
+	dialog->done = TRUE;
+	return 0;
+}
+
+/*
+ * Accepts a dialog struct waits for dw_dialog_dismiss() to be
+ * called by a signal handler with the given dialog struct.
+ * Parameters:
+ *           dialog: Pointer to a dialog struct aquired by dw_dialog_new).
+ */
+void * API dw_dialog_wait(DWDialog *dialog)
+{
+	QMSG qmsg;
+	void *tmp;
+
+	while (WinGetMsg(dwhab, &qmsg, 0, 0, 0))
+	{
+		if(qmsg.msg == WM_TIMER && qmsg.hwnd == NULLHANDLE)
+			_run_event(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2);
+		WinDispatchMsg(dwhab, &qmsg);
+		if(dialog->done)
+			break;
+	}
+	dw_event_close(&dialog->eve);
+	tmp = dialog->result;
+	free(dialog);
+	return tmp;
+}
+
+
+/*
+ * Displays a Message Box with given text and title..
+ * Parameters:
+ *           title: The title of the message box.
+ *           flags: flags to indicate buttons and icon
+ *           format: printf style format string.
+ *           ...: Additional variables for use in the format.
+ */
+int API dw_messagebox(char *title, int flags, char *format, ...)
+{
+	va_list args;
+	char outbuf[1024];
+	int rc;
+
+	va_start(args, format);
+	vsprintf(outbuf, format, args);
+	va_end(args);
+
+	rc = WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, outbuf, title, 0, flags | MB_MOVEABLE);
+	if(rc == MBID_OK)
+		return DW_MB_RETURN_OK;
+	else if(rc == MBID_YES)
+		return DW_MB_RETURN_YES;
+	else if(rc == MBID_NO)
+		return DW_MB_RETURN_NO;
+	else if(rc == MBID_CANCEL)
+		return DW_MB_RETURN_CANCEL;
+	else return 0;
+}
+
+/*
+ * Makes the window topmost.
+ * Parameters:
+ *           handle: The window handle to make topmost.
+ */
+int API dw_window_raise(HWND handle)
+{
+	return WinSetWindowPos(handle, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER);
+}
+
+/*
+ * Makes the window bottommost.
+ * Parameters:
+ *           handle: The window handle to make bottommost.
+ */
+int API dw_window_lower(HWND handle)
+{
+	return WinSetWindowPos(handle, HWND_BOTTOM, 0, 0, 0, 0, SWP_ZORDER);
+}
+
+/*
+ * Makes the window visible.
+ * Parameters:
+ *           handle: The window handle to make visible.
+ */
+int API dw_window_show(HWND handle)
+{
+	int rc = WinSetWindowPos(handle, NULLHANDLE, 0, 0, 0, 0, SWP_SHOW);
+	HSWITCH hswitch;
+	SWCNTRL swcntrl;
+
+	_fix_button_owner(_toplevel_window(handle), 0);
+	WinSetFocus(HWND_DESKTOP, handle);
+	_initial_focus(handle);
+
+	/* If this window has a  switch list entry make sure it is visible */
+	hswitch = WinQuerySwitchHandle(handle, 0);
+	if(hswitch)
+	{
+		WinQuerySwitchEntry(hswitch, &swcntrl);
+		swcntrl.uchVisibility = SWL_VISIBLE;
+		WinChangeSwitchEntry(hswitch, &swcntrl);
+	}
+	if(WinWindowFromID(handle, FID_CLIENT))
+	{
+		WindowData *blah = WinQueryWindowPtr(handle, QWP_USER);
+
+		if(blah && !(blah->flags & DW_OS2_NEW_WINDOW))
+		{
+			ULONG cx = dw_screen_width(), cy = dw_screen_height();
+			int newx, newy, changed = 0;
+			SWP swp;
+
+			blah->flags |= DW_OS2_NEW_WINDOW;
+
+			WinQueryWindowPos(handle, &swp);
+
+			newx = swp.x;
+			newy = swp.y;
+
+			if((swp.x+swp.cx) > cx)
+			{
+				newx = (cx - swp.cx)/2;
+				changed = 1;
+			}
+			if((swp.y+swp.cy) > cy)
+			{
+				newy = (cy - swp.cy)/2;
+				changed = 1;
+			}
+			if(changed)
+				WinSetWindowPos(handle, NULLHANDLE, newx, newy, 0, 0, SWP_MOVE);
+		}
+	}
+	return rc;
+}
+
+/*
+ * Minimizes or Iconifies a top-level window.
+ * Parameters:
+ *           handle: The window handle to minimize.
+ */
+int API dw_window_minimize(HWND handle)
+{
+	HWND hwndclient = WinWindowFromID(handle, FID_CLIENT);
+
+	if(hwndclient)
+	{
+		Box *box = (Box *)WinQueryWindowPtr(hwndclient, QWP_USER);
+
+		if(box)
+		{
+			if(!box->titlebar && box->hwndtitle)
+				WinSetParent(box->hwndtitle, handle, FALSE);
+		}
+	}
+
+	return WinSetWindowPos(handle, NULLHANDLE, 0, 0, 0, 0, SWP_MINIMIZE);
+}
+
+/*
+ * Makes the window invisible.
+ * Parameters:
+ *           handle: The window handle to make visible.
+ */
+int API dw_window_hide(HWND handle)
+{
+	HSWITCH hswitch;
+	SWCNTRL swcntrl;
+
+	/* If this window has a  switch list entry make sure it is invisible */
+	hswitch = WinQuerySwitchHandle(handle, 0);
+	if(hswitch)
+	{
+		WinQuerySwitchEntry(hswitch, &swcntrl);
+		swcntrl.uchVisibility = SWL_INVISIBLE;
+		WinChangeSwitchEntry(hswitch, &swcntrl);
+	}
+	return WinShowWindow(handle, FALSE);
+}
+
+/*
+ * Destroys a window and all of it's children.
+ * Parameters:
+ *           handle: The window handle to destroy.
+ */
+int API dw_window_destroy(HWND handle)
+{
+	HWND frame, menu, parent = WinQueryWindow(handle, QW_PARENT);
+	Box *thisbox = WinQueryWindowPtr(parent, QWP_USER);
+
+	if(!handle)
+		return -1;
+
+	frame = (HWND)dw_window_get_data(handle, "_dw_combo_box");
+
+	if((menu = WinWindowFromID(handle, FID_MENU)) != NULLHANDLE)
+		_free_menu_data(menu);
+
+	if(parent != desktop && thisbox && thisbox->count)
+	{
+		int z, index = -1;
+		Item *tmpitem, *thisitem = thisbox->items;
+
+		for(z=0;z<thisbox->count;z++)
+		{
+			if(thisitem[z].hwnd == handle)
+				index = z;
+		}
+
+		if(index == -1)
+			return 0;
+
+		tmpitem = malloc(sizeof(Item)*(thisbox->count-1));
+
+		/* Copy all but the current entry to the new list */
+		for(z=0;z<index;z++)
+		{
+			tmpitem[z] = thisitem[z];
+		}
+		for(z=index+1;z<thisbox->count;z++)
+		{
+			tmpitem[z-1] = thisitem[z];
+		}
+
+		thisbox->items = tmpitem;
+		free(thisitem);
+		thisbox->count--;
+		_free_window_memory(frame ? frame : handle);
+	}
+	return WinDestroyWindow(frame ? frame : handle);
+}
+
+/* Causes entire window to be invalidated and redrawn.
+ * Parameters:
+ *           handle: Toplevel window handle to be redrawn.
+ */
+void API dw_window_redraw(HWND handle)
+{
+	HWND client = WinWindowFromID(handle, FID_CLIENT);
+	HWND window = client ? client : handle;
+	Box *mybox = (Box *)WinQueryWindowPtr(window, QWP_USER);
+
+	if(window && mybox)
+	{
+		unsigned long width, height;
+
+		dw_window_get_pos_size(window, NULL, NULL, &width, &height);
+
+		WinShowWindow(client ? mybox->items[0].hwnd : handle, FALSE);
+		_do_resize(mybox, width, height);
+		WinShowWindow(client ? mybox->items[0].hwnd : handle, TRUE);
+	}
+}
+
+/*
+ * Changes a window's parent to newparent.
+ * Parameters:
+ *           handle: The window handle to destroy.
+ *           newparent: The window's new parent window.
+ */
+void API dw_window_reparent(HWND handle, HWND newparent)
+{
+	HWND blah = WinWindowFromID(newparent, FID_CLIENT);
+	WinSetParent(handle, blah ? blah : newparent, TRUE);
+}
+
+/*
+ * Sets the font used by a specified window (widget) handle.
+ * Parameters:
+ *          handle: The window (widget) handle.
+ *          fontname: Name and size of the font in the form "size.fontname"
+ */
+int API dw_window_set_font(HWND handle, char *fontname)
+{
+	return WinSetPresParam(handle, PP_FONTNAMESIZE, strlen(fontname)+1, fontname);
+}
+
+/* Internal version */
+int _dw_window_set_color(HWND handle, ULONG fore, ULONG back)
+{
+	if((fore & DW_RGB_COLOR) == DW_RGB_COLOR)
+	{
+		RGB2 rgb2;
+
+		rgb2.bBlue = DW_BLUE_VALUE(fore);
+		rgb2.bGreen = DW_GREEN_VALUE(fore);
+		rgb2.bRed = DW_RED_VALUE(fore);
+		rgb2.fcOptions = 0;
+
+		WinSetPresParam(handle, PP_FOREGROUNDCOLOR, sizeof(RGB2), &rgb2);
+
+	}
+	else if(fore != DW_CLR_DEFAULT)
+	{
+		fore = _internal_color(fore);
+
+		WinSetPresParam(handle, PP_FOREGROUNDCOLORINDEX, sizeof(ULONG), &fore);
+	}
+	if((back & DW_RGB_COLOR) == DW_RGB_COLOR)
+	{
+		RGB2 rgb2;
+
+		rgb2.bBlue = DW_BLUE_VALUE(back);
+		rgb2.bGreen = DW_GREEN_VALUE(back);
+		rgb2.bRed = DW_RED_VALUE(back);
+		rgb2.fcOptions = 0;
+
+		WinSetPresParam(handle, PP_BACKGROUNDCOLOR, sizeof(RGB2), &rgb2);
+		return 0;
+	}
+	else if(back != DW_CLR_DEFAULT)
+	{
+		back = _internal_color(back);
+
+		WinSetPresParam(handle, PP_BACKGROUNDCOLORINDEX, sizeof(ULONG), &back);
+	}
+	return 0;
+}
+/*
+ * Sets the colors used by a specified window (widget) handle.
+ * Parameters:
+ *          handle: The window (widget) handle.
+ *          fore: Foreground color in DW_RGB format or a default color index.
+ *          back: Background color in DW_RGB format or a default color index.
+ */
+int API dw_window_set_color(HWND handle, ULONG fore, ULONG back)
+{
+	dw_window_set_data(handle, "_dw_fore", (void *)(fore+1));
+	dw_window_set_data(handle, "_dw_back", (void *)(back+1));
+
+	return _dw_window_set_color(handle, fore, back);
+}
+
+/*
+ * Sets the font used by a specified window (widget) handle.
+ * Parameters:
+ *          handle: The window (widget) handle.
+ *          border: Size of the window border in pixels.
+ */
+int API dw_window_set_border(HWND handle, int border)
+{
+	WinSendMsg(handle, WM_SETBORDERSIZE, MPFROMSHORT(border), MPFROMSHORT(border));
+	return 0;
+}
+
+/*
+ * Captures the mouse input to this window.
+ * Parameters:
+ *       handle: Handle to receive mouse input.
+ */
+void API dw_window_capture(HWND handle)
+{
+	WinSetCapture(HWND_DESKTOP, handle);
+}
+
+/*
+ * Releases previous mouse capture.
+ */
+void API dw_window_release(void)
+{
+	WinSetCapture(HWND_DESKTOP, NULLHANDLE);
+}
+
+/*
+ * Tracks this window movement.
+ * Parameters:
+ *       handle: Handle to frame to be tracked.
+ */
+void API dw_window_track(HWND handle)
+{
+	WinSendMsg(handle, WM_TRACKFRAME, MPFROMSHORT(TF_MOVE), 0);
+}
+
+/*
+ * Changes the appearance of the mouse pointer.
+ * Parameters:
+ *       handle: Handle to widget for which to change.
+ *       cursortype: ID of the pointer you want.
+ */
+void API dw_window_pointer(HWND handle, int pointertype)
+{
+	if(handle == HWND_DESKTOP)
+		WinSetPointer(handle, WinQuerySysPointer(HWND_DESKTOP,pointertype, FALSE));
+	else
+		dw_window_set_data(handle, "_dw_pointer",
+						   pointertype < 65535 ?
+						   (void *)WinQuerySysPointer(HWND_DESKTOP,pointertype, FALSE)
+						   : (void *)pointertype);
+}
+
+/*
+ * Create a new Window Frame.
+ * Parameters:
+ *       owner: The Owner's window handle or HWND_DESKTOP.
+ *       title: The Window title.
+ *       flStyle: Style flags, see the PM reference.
+ */
+HWND API dw_window_new(HWND hwndOwner, char *title, ULONG flStyle)
+{
+	HWND hwndclient = 0, hwndframe;
+	Box *newbox = calloc(1, sizeof(Box));
+	WindowData *blah = calloc(1, sizeof(WindowData));
+	ULONG winStyle = 0L;
+
+	newbox->pad = 0;
+	newbox->type = DW_VERT;
+	newbox->count = 0;
+
+	flStyle |= FCF_NOBYTEALIGN;
+
+	if(flStyle & DW_FCF_TITLEBAR)
+		newbox->titlebar = 1;
+	else
+		flStyle |= FCF_TITLEBAR;
+
+	if(!(flStyle & FCF_SHELLPOSITION))
+		blah->flags |= DW_OS2_NEW_WINDOW;
+
+	if(flStyle & WS_MAXIMIZED)
+	{
+		winStyle |= WS_MAXIMIZED;
+		flStyle &= ~WS_MAXIMIZED;
+	}
+	if(flStyle & WS_MINIMIZED)
+	{
+		winStyle |= WS_MINIMIZED;
+		flStyle &= ~WS_MINIMIZED;
+	}
+
+	hwndframe = WinCreateStdWindow(hwndOwner, winStyle, &flStyle, ClassName, title, 0L, NULLHANDLE, 0L, &hwndclient);
+	newbox->hwndtitle = WinWindowFromID(hwndframe, FID_TITLEBAR);
+	if(!newbox->titlebar && newbox->hwndtitle)
+		WinSetParent(newbox->hwndtitle, HWND_OBJECT, FALSE);
+	blah->oldproc = WinSubclassWindow(hwndframe, _sizeproc);
+	WinSetWindowPtr(hwndframe, QWP_USER, blah);
+	WinSetWindowPtr(hwndclient, QWP_USER, newbox);
+
+	return hwndframe;
+}
+
+/*
+ * Create a new Box to be packed.
+ * Parameters:
+ *       type: Either DW_VERT (vertical) or DW_HORZ (horizontal).
+ *       pad: Number of pixels to pad around the box.
+ */
+HWND API dw_box_new(int type, int pad)
+{
+	Box *newbox = calloc(1, sizeof(Box));
+	HWND hwndframe;
+
+	newbox->pad = pad;
+	newbox->type = type;
+	newbox->count = 0;
+    newbox->grouphwnd = NULLHANDLE;
+
+	hwndframe = WinCreateWindow(HWND_OBJECT,
+								WC_FRAME,
+								NULL,
+								WS_VISIBLE | WS_CLIPCHILDREN |
+								FS_NOBYTEALIGN,
+								0,0,2000,1000,
+								NULLHANDLE,
+								HWND_TOP,
+								0L,
+								NULL,
+								NULL);
+
+	newbox->oldproc = WinSubclassWindow(hwndframe, _controlproc);
+	WinSetWindowPtr(hwndframe, QWP_USER, newbox);
+	dw_window_set_color(hwndframe, DW_CLR_PALEGRAY, DW_CLR_PALEGRAY);
+	return hwndframe;
+}
+
+/*
+ * Create a new Group Box to be packed.
+ * Parameters:
+ *       type: Either DW_VERT (vertical) or DW_HORZ (horizontal).
+ *       pad: Number of pixels to pad around the box.
+ *       title: Text to be displayined in the group outline.
+ */
+HWND API dw_groupbox_new(int type, int pad, char *title)
+{
+	Box *newbox = calloc(1, sizeof(Box));
+	HWND hwndframe;
+
+	newbox->pad = pad;
+	newbox->type = type;
+	newbox->count = 0;
+
+	hwndframe = WinCreateWindow(HWND_OBJECT,
+								WC_FRAME,
+								NULL,
+								WS_VISIBLE |
+								FS_NOBYTEALIGN,
+								0,0,2000,1000,
+								NULLHANDLE,
+								HWND_TOP,
+								0L,
+								NULL,
+								NULL);
+
+	newbox->grouphwnd = WinCreateWindow(hwndframe,
+										WC_STATIC,
+										title,
+										WS_VISIBLE | SS_GROUPBOX |
+										WS_GROUP,
+										0,0,2000,1000,
+										NULLHANDLE,
+										HWND_TOP,
+										0L,
+										NULL,
+										NULL);
+
+	WinSetWindowPtr(hwndframe, QWP_USER, newbox);
+	dw_window_set_color(hwndframe, DW_CLR_PALEGRAY, DW_CLR_PALEGRAY);
+	dw_window_set_color(newbox->grouphwnd, DW_CLR_BLACK, DW_CLR_PALEGRAY);
+	dw_window_set_font(newbox->grouphwnd, DefaultFont);
+	return hwndframe;
+}
+
+/*
+ * Create a new MDI Frame to be packed.
+ * Parameters:
+ *       id: An ID to be used with dw_window_from_id or 0L.
+ */
+HWND API dw_mdi_new(unsigned long id)
+{
+	HWND hwndframe;
+
+	id = id; /* keep compiler happy */
+	hwndframe = WinCreateWindow(HWND_OBJECT,
+								WC_FRAME,
+								NULL,
+								WS_VISIBLE | WS_CLIPCHILDREN |
+								FS_NOBYTEALIGN,
+								0,0,2000,1000,
+								NULLHANDLE,
+								HWND_TOP,
+								0L,
+								NULL,
+								NULL);
+	return hwndframe;
+}
+
+/*
+ * Create a bitmap object to be packed.
+ * Parameters:
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_bitmap_new(ULONG id)
+{
+	return WinCreateWindow(HWND_OBJECT,
+						   WC_STATIC,
+						   NULL,
+						   WS_VISIBLE | SS_TEXT,
+						   0,0,2000,1000,
+						   NULLHANDLE,
+						   HWND_TOP,
+						   id,
+						   NULL,
+						   NULL);
+}
+
+/*
+ * Create a notebook object to be packed.
+ * Parameters:
+ *       id: An ID to be used for getting the resource from the
+ *           resource file.
+ */
+HWND API dw_notebook_new(ULONG id, int top)
+{
+	ULONG flags;
+	HWND tmp;
+
+	if(top)
+		flags = BKS_MAJORTABTOP;
+	else
+		flags = BKS_MAJORTABBOTTOM;
+
+	tmp = WinCreateWindow(HWND_OBJECT,
+						  WC_NOTEBOOK,
+						  NULL,
+						  WS_VISIBLE |
+#ifdef BKS_TABBEDDIALOG
+						  BKS_TABBEDDIALOG |
+#endif
+						  flags,
+						  0,0,2000,1000,
+						  NULLHANDLE,
+						  HWND_TOP,
+						  id,
+						  NULL,
+						  NULL);
+
+	/* Fix tab sizes on Warp 3 */
+	if(!IS_WARP4())
+	{
+		/* best sizes to be determined by trial and error */
+		WinSendMsg(tmp, BKM_SETDIMENSIONS,MPFROM2SHORT(102, 28), MPFROMSHORT( BKA_MAJORTAB));
+	}
+
+	dw_window_set_font(tmp, DefaultFont);
+	return tmp;
+}
+
+/*
+ * Create a menu object to be popped up.
+ * Parameters:
+ *       id: An ID to be used for getting the resource from the
+ *           resource file.
+ */
+HMENUI API dw_menu_new(ULONG id)
+{
+	HMENUI tmp = WinCreateWindow(HWND_OBJECT,
+								 WC_MENU,
+								 NULL,
+								 WS_VISIBLE,
+								 0,0,2000,1000,
+								 NULLHANDLE,
+								 HWND_TOP,
+								 id,
+								 NULL,
+								 NULL);
+	return tmp;
+}
+
+/*
+ * Create a menubar on a window.
+ * Parameters:
+ *       location: Handle of a window frame to be attached to.
+ */
+HMENUI API dw_menubar_new(HWND location)
+{
+	HMENUI tmp = WinCreateWindow(location,
+								 WC_MENU,
+								 NULL,
+								 WS_VISIBLE | MS_ACTIONBAR,
+								 0,0,2000,1000,
+								 location,
+								 HWND_TOP,
+								 FID_MENU,
+								 NULL,
+								 NULL);
+	dw_window_set_data(tmp, "_dw_owner", (void *)location);
+	dw_window_set_data(tmp, "_dw_menubar", (void *)location);
+	return tmp;
+}
+
+/*
+ * Destroys a menu created with dw_menubar_new or dw_menu_new.
+ * Parameters:
+ *       menu: Handle of a menu.
+ */
+void API dw_menu_destroy(HMENUI *menu)
+{
+	if(menu)
+		WinDestroyWindow(*menu);
+}
+
+/*
+ * Adds a menuitem or submenu to an existing menu.
+ * Parameters:
+ *       menu: The handle the the existing menu.
+ *       title: The title text on the menu item to be added.
+ *       id: An ID to be used for message passing.
+ *       flags: Extended attributes to set on the menu.
+ *       end: If TRUE memu is positioned at the end of the menu.
+ *       check: If TRUE menu is "check"able.
+ *       submenu: Handle to an existing menu to be a submenu or NULL.
+ */
+HWND API dw_menu_append_item(HMENUI menux, char *title, ULONG id, ULONG flags, int end, int check, HMENUI submenu)
+{
+	MENUITEM miSubMenu;
+	char buffer[15];
+
+	check = check; /* keep compiler happy */
+	if(!menux || id > 65536)
+		return NULLHANDLE;
+
+	if(end)
+		miSubMenu.iPosition=MIT_END;
+	else
+		miSubMenu.iPosition=0;
+
+	if(strlen(title) == 0)
+		miSubMenu.afStyle=MIS_SEPARATOR | flags;
+	else
+		miSubMenu.afStyle=MIS_TEXT | flags;
+	miSubMenu.afAttribute=0;
+	miSubMenu.id=id;
+	miSubMenu.hwndSubMenu = submenu;
+	miSubMenu.hItem=NULLHANDLE;
+
+	WinSendMsg(menux,
+			   MM_INSERTITEM,
+			   MPFROMP(&miSubMenu),
+			   MPFROMP(title));
+
+	sprintf(buffer, "_dw_id%d", id);
+	dw_window_set_data(hwndApp, buffer, (void *)menux);
+
+	if(submenu)
+		dw_window_set_data(submenu, "_dw_owner", (void *)menux);
+	return (HWND)id;
+}
+
+/*
+ * Sets the state of a menu item check.
+ * Parameters:
+ *       menu: The handle the the existing menu.
+ *       id: Menuitem id.
+ *       check: TRUE for checked FALSE for not checked.
+ */
+void API dw_menu_item_set_check(HMENUI menux, unsigned long id, int check)
+{
+	if(check)
+		WinSendMsg(menux, MM_SETITEMATTR, MPFROM2SHORT(id, TRUE),
+				   MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED));
+	else
+		WinSendMsg(menux, MM_SETITEMATTR, MPFROM2SHORT(id, TRUE),
+				   MPFROM2SHORT(MIA_CHECKED, 0));
+}
+
+/*
+ * Pops up a context menu at given x and y coordinates.
+ * Parameters:
+ *       menu: The handle the the existing menu.
+ *       parent: Handle to the window initiating the popup.
+ *       x: X coordinate.
+ *       y: Y coordinate.
+ */
+void API dw_menu_popup(HMENUI *menu, HWND parent, int x, int y)
+{
+	if(menu)
+	{
+		popup = parent;
+		WinPopupMenu(HWND_DESKTOP, parent, *menu, x, dw_screen_height() - y, 0, PU_KEYBOARD | PU_MOUSEBUTTON1 | PU_VCONSTRAIN | PU_HCONSTRAIN);
+	}
+}
+
+/*
+ * Returns the current X and Y coordinates of the mouse pointer.
+ * Parameters:
+ *       x: Pointer to variable to store X coordinate.
+ *       y: Pointer to variable to store Y coordinate.
+ */
+void API dw_pointer_query_pos(long *x, long *y)
+{
+	POINTL ptl;
+
+	WinQueryPointerPos(HWND_DESKTOP, &ptl);
+	if(x && y)
+	{
+		*x = ptl.x;
+		*y = dw_screen_height() - ptl.y;
+	}
+}
+
+/*
+ * Sets the X and Y coordinates of the mouse pointer.
+ * Parameters:
+ *       x: X coordinate.
+ *       y: Y coordinate.
+ */
+void API dw_pointer_set_pos(long x, long y)
+{
+	WinSetPointerPos(HWND_DESKTOP, x, dw_screen_height() - y);
+}
+
+
+/*
+ * Create a container object to be packed.
+ * Parameters:
+ *       id: An ID to be used for getting the resource from the
+ *           resource file.
+ */
+HWND API dw_container_new(ULONG id, int multi)
+{
+	WindowData *blah = calloc(1, sizeof(WindowData));
+	HWND tmp = WinCreateWindow(HWND_OBJECT,
+							   WC_CONTAINER,
+							   NULL,
+							   WS_VISIBLE | CCS_READONLY |
+							   (multi ? CCS_EXTENDSEL : CCS_SINGLESEL) |
+							   CCS_AUTOPOSITION,
+							   0,0,2000,1000,
+							   NULLHANDLE,
+							   HWND_TOP,
+							   id,
+							   NULL,
+							   NULL);
+	blah->oldproc = WinSubclassWindow(tmp, _TreeProc);
+	WinSetWindowPtr(tmp, QWP_USER, blah);
+	dw_window_set_font(tmp, DefaultFont);
+	dw_window_set_data(tmp, "_dw_container", (void *)1);
+	return tmp;
+}
+
+/*
+ * Create a tree object to be packed.
+ * Parameters:
+ *       id: An ID to be used for getting the resource from the
+ *           resource file.
+ */
+HWND API dw_tree_new(ULONG id)
+{
+	CNRINFO cnrinfo;
+	WindowData *blah = calloc(1, sizeof(WindowData));
+	HWND tmp = WinCreateWindow(HWND_OBJECT,
+							   WC_CONTAINER,
+							   NULL,
+							   WS_VISIBLE | CCS_READONLY |
+							   CCS_SINGLESEL | CCS_AUTOPOSITION,
+							   0,0,2000,1000,
+							   NULLHANDLE,
+							   HWND_TOP,
+							   id,
+							   NULL,
+							   NULL);
+
+	cnrinfo.flWindowAttr = CV_TREE | CA_TREELINE;
+	cnrinfo.slBitmapOrIcon.cx = 16;
+	cnrinfo.slBitmapOrIcon.cy = 16;
+	cnrinfo.cyLineSpacing = 0;
+	cnrinfo.cxTreeIndent = 16;
+	cnrinfo.cxTreeLine = 1;
+
+	WinSendMsg(tmp, CM_SETCNRINFO, &cnrinfo, MPFROMLONG(CMA_FLWINDOWATTR | CMA_SLBITMAPORICON |
+														CMA_LINESPACING | CMA_CXTREEINDENT | CMA_CXTREELINE));
+	blah->oldproc = WinSubclassWindow(tmp, _TreeProc);
+	WinSetWindowPtr(tmp, QWP_USER, blah);
+	dw_window_set_font(tmp, DefaultFont);
+	return tmp;
+}
+
+/*
+ * Create a new static text window (widget) to be packed.
+ * Parameters:
+ *       text: The text to be display by the static text widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_text_new(char *text, ULONG id)
+{
+	HWND tmp = WinCreateWindow(HWND_OBJECT,
+							   WC_STATIC,
+							   text,
+							   WS_VISIBLE | SS_TEXT,
+							   0,0,2000,1000,
+							   NULLHANDLE,
+							   HWND_TOP,
+							   id,
+							   NULL,
+							   NULL);
+	dw_window_set_font(tmp, DefaultFont);
+	dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY);
+	return tmp;
+}
+
+/*
+ * Create a new status text window (widget) to be packed.
+ * Parameters:
+ *       text: The text to be display by the static text widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_status_text_new(char *text, ULONG id)
+{
+	WindowData *blah = calloc(sizeof(WindowData), 1);
+	HWND tmp = WinCreateWindow(HWND_OBJECT,
+							   WC_STATIC,
+							   text,
+							   WS_VISIBLE | SS_TEXT,
+							   0,0,2000,1000,
+							   NULLHANDLE,
+							   HWND_TOP,
+							   id,
+							   NULL,
+							   NULL);
+	blah->oldproc = WinSubclassWindow(tmp, _statusproc);
+	WinSetWindowPtr(tmp, QWP_USER, blah);
+	dw_window_set_font(tmp, DefaultFont);
+	dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY);
+	return tmp;
+}
+
+#ifndef MLS_LIMITVSCROLL
+#define MLS_LIMITVSCROLL           0x00000080L
+#endif
+
+/*
+ * Create a new Multiline Editbox window (widget) to be packed.
+ * Parameters:
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_mle_new(ULONG id)
+{
+	WindowData *blah = calloc(1, sizeof(WindowData));
+	HWND tmp = WinCreateWindow(HWND_OBJECT,
+							   WC_MLE,
+							   "",
+							   WS_VISIBLE |
+							   MLS_BORDER | MLS_IGNORETAB |
+							   MLS_READONLY | MLS_VSCROLL |
+							   MLS_LIMITVSCROLL,
+							   0,0,2000,1000,
+							   NULLHANDLE,
+							   HWND_TOP,
+							   id,
+							   NULL,
+							   NULL);
+	blah->oldproc = WinSubclassWindow(tmp, _mleproc);
+	WinSetWindowPtr(tmp, QWP_USER, blah);
+	dw_window_set_font(tmp, DefaultFont);
+	return tmp;
+}
+
+/*
+ * Create a new Entryfield window (widget) to be packed.
+ * Parameters:
+ *       text: The default text to be in the entryfield widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_entryfield_new(char *text, ULONG id)
+{
+
+	WindowData *blah = calloc(1, sizeof(WindowData));
+	HWND tmp = WinCreateWindow(HWND_OBJECT,
+							   WC_ENTRYFIELD,
+							   text,
+							   WS_VISIBLE | ES_MARGIN |
+							   ES_AUTOSCROLL | WS_TABSTOP,
+							   0,0,2000,1000,
+							   NULLHANDLE,
+							   HWND_TOP,
+							   id,
+							   NULL,
+							   NULL);
+	blah->oldproc = WinSubclassWindow(tmp, _entryproc);
+	WinSetWindowPtr(tmp, QWP_USER, blah);
+	dw_window_set_font(tmp, DefaultFont);
+	dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_WHITE);
+	return tmp;
+}
+
+/*
+ * Create a new Entryfield (password) window (widget) to be packed.
+ * Parameters:
+ *       text: The default text to be in the entryfield widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_entryfield_password_new(char *text, ULONG id)
+{
+	WindowData *blah = calloc(1, sizeof(WindowData));
+	HWND tmp = WinCreateWindow(HWND_OBJECT,
+							   WC_ENTRYFIELD,
+							   text,
+							   WS_VISIBLE | ES_MARGIN | ES_UNREADABLE |
+							   ES_AUTOSCROLL | WS_TABSTOP,
+							   0,0,2000,1000,
+							   NULLHANDLE,
+							   HWND_TOP,
+							   id,
+							   NULL,
+							   NULL);
+	blah->oldproc = WinSubclassWindow(tmp, _entryproc);
+	WinSetWindowPtr(tmp, QWP_USER, blah);
+	dw_window_set_font(tmp, DefaultFont);
+	dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_WHITE);
+	return tmp;
+}
+
+/*
+ * Create a new Combobox window (widget) to be packed.
+ * Parameters:
+ *       text: The default text to be in the combpbox widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_combobox_new(char *text, ULONG id)
+{
+	WindowData *blah = calloc(1, sizeof(WindowData));
+	HWND frame = dw_box_new(DW_HORZ, 0);
+	HWND tmp = WinCreateWindow(frame,
+							   WC_COMBOBOX,
+							   text,
+							   WS_VISIBLE | CBS_DROPDOWN | WS_GROUP,
+							   0,0,2000,1000,
+							   NULLHANDLE,
+							   HWND_TOP,
+							   id,
+							   NULL,
+							   NULL);
+	HENUM henum = WinBeginEnumWindows(tmp);
+	HWND child, last = NULLHANDLE;
+	
+	while((child = WinGetNextWindow(henum)) != NULLHANDLE)
+	{
+		WindowData *moreblah = calloc(1, sizeof(WindowData));
+		moreblah->oldproc = WinSubclassWindow(child, _comboentryproc);
+		WinSetWindowPtr(child, QWP_USER, moreblah);
+		dw_window_set_color(child, DW_CLR_BLACK, DW_CLR_WHITE);
+		last = child;
+	}
+	WinEndEnumWindows(henum);
+	blah->oldproc = WinSubclassWindow(tmp, _comboproc);
+	WinSetWindowPtr(tmp, QWP_USER, blah);
+	dw_window_set_font(tmp, DefaultFont);
+	dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_WHITE);
+	dw_window_set_data(tmp, "_dw_comboentry", (void *)last);
+	dw_window_set_data(tmp, "_dw_combo_box", (void *)frame);
+	WinSetOwner(tmp, frame);
+	return tmp;
+}
+
+/*
+ * Create a new button window (widget) to be packed.
+ * Parameters:
+ *       text: The text to be display by the static text widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_button_new(char *text, ULONG id)
+{
+	BubbleButton *bubble = calloc(sizeof(BubbleButton), 1);
+
+	HWND tmp = WinCreateWindow(HWND_OBJECT,
+							   WC_BUTTON,
+							   text,
+							   WS_VISIBLE,
+							   0,0,2000,1000,
+							   NULLHANDLE,
+							   HWND_TOP,
+							   id,
+							   NULL,
+							   NULL);
+
+	bubble->id = id;
+	bubble->bubbletext[0] = '\0';
+	bubble->pOldProc = WinSubclassWindow(tmp, _BtProc);
+
+	WinSetWindowPtr(tmp, QWP_USER, bubble);
+	dw_window_set_font(tmp, DefaultFont);
+	dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY);
+	return tmp;
+}
+
+/* Function: GenResIDStr
+** Abstract: Generate string '#nnnn' for a given ID for using with Button
+**           controls
+*/
+
+void _GenResIDStr(CHAR *buff, ULONG ulID)
+{
+	char *str;
+	int  slen = 0;
+
+	*buff++ = '#';
+
+	str = buff;
+
+	do
+	{
+		*str++ = (ulID % 10) + '0';
+		ulID /= 10;
+		slen++;
+	}
+	while(ulID);
+
+	*str-- = 0;
+
+	for(; str > buff; str--, buff++)
+	{
+		*buff ^= *str;
+		*str  ^= *buff;
+		*buff ^= *str;
+	}
+}
+
+
+/*
+ * Create a new bitmap button window (widget) to be packed.
+ * Parameters:
+ *       text: Bubble help text to be displayed.
+ *       id: An ID of a bitmap in the resource file.
+ */
+HWND API dw_bitmapbutton_new(char *text, ULONG id)
+{
+	char idbuf[256];
+	HWND tmp;
+	BubbleButton *bubble = calloc(sizeof(BubbleButton), 1);
+
+	_GenResIDStr(idbuf, id);
+
+	tmp = WinCreateWindow(HWND_OBJECT,
+						  WC_BUTTON,
+						  idbuf,
+						  WS_VISIBLE | BS_PUSHBUTTON |
+						  BS_BITMAP | BS_AUTOSIZE |
+						  BS_NOPOINTERFOCUS,
+						  0,0,2000,1000,
+						  NULLHANDLE,
+						  HWND_TOP,
+						  id,
+						  NULL,
+						  NULL);
+
+	bubble->id = id;
+	strncpy(bubble->bubbletext, text, BUBBLE_HELP_MAX - 1);
+	bubble->bubbletext[BUBBLE_HELP_MAX - 1] = '\0';
+	bubble->pOldProc = WinSubclassWindow(tmp, _BtProc);
+
+	WinSetWindowPtr(tmp, QWP_USER, bubble);
+	dw_window_set_data(tmp, "_dw_bitmapbutton", (void *)1);
+	return tmp;
+}
+
+/*
+ * Create a new bitmap button window (widget) to be packed from a file.
+ * Parameters:
+ *       text: Bubble help text to be displayed.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ *       filename: Name of the file, omit extention to have
+ *                 DW pick the appropriate file extension.
+ *                 (BMP on OS/2 or Windows, XPM on Unix)
+ */
+HWND dw_bitmapbutton_new_from_file(char *text, unsigned long id, char *filename)
+{
+	BubbleButton *bubble = calloc(sizeof(BubbleButton), 1);
+	HWND tmp = WinCreateWindow(HWND_OBJECT,
+							   WC_BUTTON,
+							   "",
+							   WS_VISIBLE | BS_PUSHBUTTON |
+							   BS_AUTOSIZE | BS_NOPOINTERFOCUS,
+							   0,0,2000,1000,
+							   NULLHANDLE,
+							   HWND_TOP,
+							   id,
+							   NULL,
+							   NULL);
+	char *file = alloca(strlen(filename) + 5);
+	HPIXMAP pixmap = NULL, disabled = NULL;
+
+	if(file && (pixmap = calloc(1,sizeof(struct _hpixmap))))
+	{
+		int z, j, lim;
+		LONG fore;
+
+		strcpy(file, filename);
+
+		/* check if we can read from this file (it exists and read permission) */
+		if(access(file, 04) != 0)
+		{
+			/* Try with .bmp extention */
+			strcat(file, ".bmp");
+			if(access(file, 04) != 0)
+			{
+#if 0 /* don't free pixmap if bitmap doesn't exist; causes crash several lines below */
+				free(pixmap);
+				pixmap = NULL;
+#endif
+			}
+		}
+
+		/* Try to load the bitmap from file */
+		if(pixmap)
+			_load_bitmap_file(file, tmp, &pixmap->hbm, &pixmap->hdc, &pixmap->hps, &pixmap->width, &pixmap->height);
+
+		/* Create a disabled style pixmap */
+		disabled = dw_pixmap_new(tmp, pixmap->width, pixmap->height, dw_color_depth());
+		dw_pixmap_bitblt(0, disabled, 0, 0, pixmap->width, pixmap->height, 0, pixmap, 0, 0);
+
+		fore = _foreground;
+		dw_color_foreground_set(DW_CLR_PALEGRAY);
+		lim = pixmap->width/2;
+		for(j=0;j<pixmap->height;j++)
+		{
+			int mod = j%2;
+
+			for(z=0;z<lim;z++)
+				dw_draw_point(0, disabled, (z*2)+mod, j);
+		}
+		_foreground = fore;
+	}
+
+	bubble->id = id;
+	strncpy(bubble->bubbletext, text, BUBBLE_HELP_MAX - 1);
+	bubble->bubbletext[BUBBLE_HELP_MAX - 1] = '\0';
+	bubble->pOldProc = WinSubclassWindow(tmp, _BtProc);
+
+	WinSetWindowPtr(tmp, QWP_USER, bubble);
+
+	dw_window_set_data(tmp, "_dw_hpixmap", (void *)pixmap);
+	dw_window_set_data(tmp, "_dw_hpixmap_disabled", (void *)disabled);
+	dw_window_set_data(tmp, "_dw_bitmapbutton", (void *)1);
+	return tmp;
+}
+
+/*
+ * Create a new spinbutton window (widget) to be packed.
+ * Parameters:
+ *       text: The text to be display by the static text widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_spinbutton_new(char *text, ULONG id)
+{
+	WindowData *blah = calloc(sizeof(WindowData), 1);
+	HWND tmp = WinCreateWindow(HWND_OBJECT,
+							   WC_SPINBUTTON,
+							   text,
+							   WS_VISIBLE | SPBS_MASTER,
+							   0,0,2000,1000,
+							   NULLHANDLE,
+							   HWND_TOP,
+							   id,
+							   NULL,
+							   NULL);
+	HWND entry = _find_entryfield(tmp);
+	blah->oldproc = WinSubclassWindow(tmp, _entryproc);
+	WinSetWindowPtr(tmp, QWP_USER, blah);
+	blah = calloc(sizeof(WindowData), 1);
+	blah->oldproc = WinSubclassWindow(entry, _spinentryproc);
+	WinSetWindowPtr(entry, QWP_USER, blah);
+	dw_window_set_font(tmp, DefaultFont);
+	dw_window_set_color(entry, DW_CLR_BLACK, DW_CLR_WHITE);
+	return tmp;
+}
+
+/*
+ * Create a new radiobutton window (widget) to be packed.
+ * Parameters:
+ *       text: The text to be display by the static text widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_radiobutton_new(char *text, ULONG id)
+{
+	WindowData *blah = calloc(sizeof(WindowData), 1);
+	HWND tmp = WinCreateWindow(HWND_OBJECT,
+							   WC_BUTTON,
+							   text,
+							   WS_VISIBLE |
+							   BS_AUTORADIOBUTTON,
+							   0,0,2000,1000,
+							   NULLHANDLE,
+							   HWND_TOP,
+							   id,
+							   NULL,
+							   NULL);
+	blah->oldproc = WinSubclassWindow(tmp, _entryproc);
+	WinSetWindowPtr(tmp, QWP_USER, blah);
+	dw_window_set_font(tmp, DefaultFont);
+	dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY);
+	return tmp;
+}
+
+
+/*
+ * Create a new slider window (widget) to be packed.
+ * Parameters:
+ *       vertical: TRUE or FALSE if slider is vertical.
+ *       increments: Number of increments available.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_slider_new(int vertical, int increments, ULONG id)
+{
+	WindowData *blah = calloc(1, sizeof(WindowData));
+	SLDCDATA sldcData = { 0, 0, 0, 0, 0 };
+	HWND tmp;
+
+	sldcData.cbSize = sizeof(SLDCDATA);
+    sldcData.usScale1Increments = increments;
+
+	tmp = WinCreateWindow(HWND_OBJECT,
+						  WC_SLIDER,
+						  "",
+						  WS_VISIBLE | SLS_SNAPTOINCREMENT |
+						  (vertical ? SLS_VERTICAL : SLS_HORIZONTAL),
+						  0,0,2000,1000,
+						  NULLHANDLE,
+						  HWND_TOP,
+						  id,
+						  &sldcData,
+						  NULL);
+
+	blah->oldproc = WinSubclassWindow(tmp, _entryproc);
+	WinSetWindowPtr(tmp, QWP_USER, blah);
+	return tmp;
+}
+
+/*
+ * Create a new scrollbar window (widget) to be packed.
+ * Parameters:
+ *       vertical: TRUE or FALSE if scrollbar is vertical.
+ *       increments: Number of increments available.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_scrollbar_new(int vertical, int increments, ULONG id)
+{
+	increments = increments; /* keep compiler happy */
+	return WinCreateWindow(HWND_OBJECT,
+						   WC_SCROLLBAR,
+						   "",
+						   WS_VISIBLE | SBS_AUTOTRACK |
+						   (vertical ? SBS_VERT : SBS_HORZ),
+						   0,0,2000,1000,
+						   NULLHANDLE,
+						   HWND_TOP,
+						   id,
+						   NULL,
+						   NULL);
+}
+
+/*
+ * Create a new percent bar window (widget) to be packed.
+ * Parameters:
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_percent_new(ULONG id)
+{
+	WindowData *blah = calloc(1, sizeof(WindowData));
+	HWND tmp = WinCreateWindow(HWND_OBJECT,
+							   WC_SLIDER,
+							   "",
+							   WS_VISIBLE | SLS_READONLY
+							   | SLS_RIBBONSTRIP,
+							   0,0,2000,1000,
+							   NULLHANDLE,
+							   HWND_TOP,
+							   id,
+							   NULL,
+							   NULL);
+	blah->oldproc = WinSubclassWindow(tmp, _percentproc);
+	WinSetWindowPtr(tmp, QWP_USER, blah);
+	dw_window_disable(tmp);
+	return tmp;
+}
+
+/*
+ * Create a new checkbox window (widget) to be packed.
+ * Parameters:
+ *       text: The text to be display by the static text widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_checkbox_new(char *text, ULONG id)
+{
+	BubbleButton *bubble = calloc(sizeof(BubbleButton), 1);
+	HWND tmp = WinCreateWindow(HWND_OBJECT,
+							   WC_BUTTON,
+							   text,
+							   WS_VISIBLE | BS_AUTOCHECKBOX,
+							   0,0,2000,1000,
+							   NULLHANDLE,
+							   HWND_TOP,
+							   id,
+							   NULL,
+							   NULL);
+	bubble->id = id;
+	bubble->bubbletext[0] = '\0';
+	bubble->pOldProc = WinSubclassWindow(tmp, _BtProc);
+	WinSetWindowPtr(tmp, QWP_USER, bubble);
+	dw_window_set_font(tmp, DefaultFont);
+	dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_PALEGRAY);
+	return tmp;
+}
+
+/*
+ * Create a new listbox window (widget) to be packed.
+ * Parameters:
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ *       multi: Multiple select TRUE or FALSE.
+ */
+HWND API dw_listbox_new(ULONG id, int multi)
+{
+	WindowData *blah = calloc(sizeof(WindowData), 1);
+	HWND tmp = WinCreateWindow(HWND_OBJECT,
+							   WC_LISTBOX,
+							   NULL,
+							   WS_VISIBLE | LS_NOADJUSTPOS |
+							   (multi ? LS_MULTIPLESEL : 0),
+							   0,0,2000,1000,
+							   NULLHANDLE,
+							   HWND_TOP,
+							   id,
+							   NULL,
+							   NULL);
+	blah->oldproc = WinSubclassWindow(tmp, _entryproc);
+	WinSetWindowPtr(tmp, QWP_USER, blah);
+	dw_window_set_font(tmp, DefaultFont);
+	dw_window_set_color(tmp, DW_CLR_BLACK, DW_CLR_WHITE);
+	return tmp;
+}
+
+/*
+ * Sets the icon used for a given window.
+ * Parameters:
+ *       handle: Handle to the window.
+ *       id: An ID to be used to specify the icon.
+ */
+void API dw_window_set_icon(HWND handle, ULONG id)
+{
+	HPOINTER icon = id < 65536 ? WinLoadPointer(HWND_DESKTOP,NULLHANDLE,id) : (HPOINTER)id;
+	WinSendMsg(handle, WM_SETICON, (MPARAM)icon, 0);
+}
+
+/* Internal function to load a bitmap from a file and return handles
+ * to the bitmap, presentation space etc.
+ */
+int _load_bitmap_file(char *file, HWND handle, HBITMAP *hbm, HDC *hdc, HPS *hps, unsigned long *width, unsigned long *height)
+{
+	HFILE BitmapFileHandle = NULLHANDLE; /* handle for the file */
+	ULONG OpenAction = 0;
+	PBYTE BitmapFileBegin; /* pointer to the first byte of bitmap data  */
+	FILESTATUS BitmapStatus;
+	ULONG cbRead;
+	PBITMAPFILEHEADER2 pBitmapFileHeader;
+	PBITMAPINFOHEADER2 pBitmapInfoHeader;
+	ULONG ScanLines, ulFlags;
+	HPS hps1;
+	HDC hdc1;
+	SIZEL sizl = { 0, 0 };
+
+	/* open bitmap file */
+	DosOpen(file, &BitmapFileHandle, &OpenAction, 0L,
+			FILE_ARCHIVED | FILE_NORMAL | FILE_READONLY,
+			OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
+			OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY |
+			OPEN_FLAGS_NOINHERIT, 0L);
+
+	if(!BitmapFileHandle)
+		return 0;
+
+	/* find out how big the file is  */
+	DosQueryFileInfo(BitmapFileHandle, 1, &BitmapStatus,
+					 sizeof(BitmapStatus));
+
+	/* allocate memory to load the bitmap */
+	DosAllocMem((PPVOID)&BitmapFileBegin, (ULONG)BitmapStatus.cbFile,
+				PAG_READ | PAG_WRITE | PAG_COMMIT);
+
+	/* read bitmap file into memory buffer */
+	DosRead(BitmapFileHandle, (PVOID)BitmapFileBegin,
+			BitmapStatus.cbFile, &cbRead);
+
+	/* access first bytes as bitmap header */
+	pBitmapFileHeader = (PBITMAPFILEHEADER2)BitmapFileBegin;
+
+	/* check if it's a valid bitmap data file */
+	if((pBitmapFileHeader->usType != BFT_BITMAPARRAY) &&
+	   (pBitmapFileHeader->usType != BFT_BMAP))
+	{
+		/* free memory of bitmap file buffer */
+		DosFreeMem(BitmapFileBegin);
+		/* close the bitmap file */
+		DosClose(BitmapFileHandle);
+		return 0;
+	}
+
+	/* check if it's a file with multiple bitmaps */
+	if(pBitmapFileHeader->usType == BFT_BITMAPARRAY)
+	{
+		/* we'll just use the first bitmap and ignore the others */
+		pBitmapFileHeader = &(((PBITMAPARRAYFILEHEADER2)BitmapFileBegin)->bfh2);
+	}
+
+	/* set pointer to bitmap information block */
+	pBitmapInfoHeader = &pBitmapFileHeader->bmp2;
+
+	/* find out if it's the new 2.0 format or the old format */
+	/* and query number of lines */
+	if(pBitmapInfoHeader->cbFix == sizeof(BITMAPINFOHEADER))
+	{
+		*height = ScanLines = (ULONG)((PBITMAPINFOHEADER)pBitmapInfoHeader)->cy;
+		*width = (ULONG)((PBITMAPINFOHEADER)pBitmapInfoHeader)->cx;
+	}
+	else
+	{
+		*height = ScanLines = pBitmapInfoHeader->cy;
+		*width = pBitmapInfoHeader->cx;
+	}
+
+	/* now we need a presentation space, get it from static control */
+	hps1 = WinGetPS(handle);
+
+	hdc1    = GpiQueryDevice(hps1);
+	ulFlags = GpiQueryPS(hps1, &sizl);
+
+	*hdc = DevOpenDC(dwhab, OD_MEMORY, "*", 0L, NULL, hdc1);
+	*hps = GpiCreatePS (dwhab, *hdc, &sizl, ulFlags | GPIA_ASSOC);
+
+	/* create bitmap now using the parameters from the info block */
+	*hbm = GpiCreateBitmap(*hps, pBitmapInfoHeader, 0L, NULL, NULL);
+
+	/* select the new bitmap into presentation space */
+	GpiSetBitmap(*hps, *hbm);
+
+	/* now copy the bitmap data into the bitmap */
+	GpiSetBitmapBits(*hps, 0L, ScanLines,
+					 BitmapFileBegin + pBitmapFileHeader->offBits,
+					 (PBITMAPINFO2)pBitmapInfoHeader);
+
+	WinReleasePS(hps1);
+
+	/* free memory of bitmap file buffer */
+	DosFreeMem(BitmapFileBegin);
+	/* close the bitmap file */
+	DosClose(BitmapFileHandle);
+	return 1;
+}
+
+/*
+ * Sets the bitmap used for a given static window.
+ * Parameters:
+ *       handle: Handle to the window.
+ *       id: An ID to be used to specify the icon,
+ *           (pass 0 if you use the filename param)
+ *       filename: a path to a file (Bitmap on OS/2 or
+ *                 Windows and a pixmap on Unix, pass
+ *                 NULL if you use the id param)
+ */
+void API dw_window_set_bitmap(HWND handle, unsigned long id, char *filename)
+{
+	HBITMAP hbm;
+	HPS     hps;
+
+	/* Destroy any old bitmap data */
+	_free_bitmap(handle);
+
+	/* If id is non-zero use the resource */
+	if(id)
+	{
+		hps = WinGetPS(handle);
+
+		hbm = GpiLoadBitmap(hps, NULLHANDLE, id, 0, 0);
+	}
+	else if(filename)
+	{
+		HDC hdc;
+		unsigned long width, height;
+		char *file = alloca(strlen(filename) + 5);
+
+		if(!file)
+			return;
+
+		strcpy(file, filename);
+
+		/* check if we can read from this file (it exists and read permission) */
+		if(access(file, 04) != 0)
+		{
+			/* Try with .bmp extention */
+			strcat(file, ".bmp");
+			if(access(file, 04) != 0)
+				return;
+		}
+
+		if(!_load_bitmap_file(file, handle, &hbm, &hdc, &hps, &width, &height))
+			return;
+
+		dw_window_set_data(handle, "_dw_hps", (void *)hps);
+		dw_window_set_data(handle, "_dw_hdc", (void *)hdc);
+		dw_window_set_data(handle, "_dw_width", (void *)width);
+		dw_window_set_data(handle, "_dw_height", (void *)height);
+	}
+	else
+		return;
+
+	WinSetWindowBits(handle,QWL_STYLE,SS_BITMAP,SS_BITMAP | 0x7f);
+	WinSendMsg( handle, SM_SETHANDLE, MPFROMP(hbm), NULL );
+	if(id)
+		WinReleasePS(hps);
+	dw_window_set_data(handle, "_dw_bitmap", (void *)hbm);
+}
+
+/*
+ * Sets the text used for a given window.
+ * Parameters:
+ *       handle: Handle to the window.
+ *       text: The text associsated with a given window.
+ */
+void API dw_window_set_text(HWND handle, char *text)
+{
+	WinSetWindowText(handle, text);
+}
+
+/*
+ * Gets the text used for a given window.
+ * Parameters:
+ *       handle: Handle to the window.
+ * Returns:
+ *       text: The text associsated with a given window.
+ */
+char * API dw_window_get_text(HWND handle)
+{
+	int len = WinQueryWindowTextLength(handle);
+	char *tempbuf = calloc(1, len + 2);
+
+	WinQueryWindowText(handle, len + 1, tempbuf);
+
+	return tempbuf;
+}
+
+/*
+ * Disables given window (widget).
+ * Parameters:
+ *       handle: Handle to the window.
+ */
+void API dw_window_disable(HWND handle)
+{
+	char tmpbuf[100];
+
+	if(dw_window_get_data(handle, "_dw_disabled"))
+		return;
+
+	WinQueryClassName(handle, 99, tmpbuf);
+	dw_window_set_data(handle, "_dw_disabled", (void *)1);
+
+	if(tmpbuf[0] == '#')
+	{
+		int val = atoi(&tmpbuf[1]);
+		HWND hwnd;
+
+		switch(val)
+		{
+		case 2:
+		case 6:
+		case 10:
+		case 32:
+		case 7:
+			hwnd = _find_entryfield(handle);
+			_dw_window_set_color(hwnd ? hwnd : handle, DW_CLR_BLACK, DW_CLR_PALEGRAY);
+			dw_signal_connect(hwnd ? hwnd : handle, DW_SIGNAL_KEY_PRESS, DW_SIGNAL_FUNC(_null_key), (void *)100);
+            if(val == 2)
+				dw_signal_connect(handle, DW_SIGNAL_BUTTON_PRESS, DW_SIGNAL_FUNC(_null_key), (void *)100);
+			if(hwnd)
+				dw_window_set_data(hwnd, "_dw_disabled", (void *)1);
+			return;
+		case 3:
+			if(dw_window_get_data(handle, "_dw_bitmapbutton") && !dw_window_get_data(handle, "_dw_hpixmap"))
+				WinEnableWindow(handle, FALSE);
+			else if(dw_window_get_data(handle, "_dw_bitmapbutton") && dw_window_get_data(handle, "_dw_hpixmap_disabled"))
+				WinInvalidateRect(handle, NULL, FALSE);
+			else
+				_dw_window_set_color(handle, DW_CLR_DARKGRAY, DW_CLR_PALEGRAY);
+			dw_signal_connect(handle, DW_SIGNAL_KEY_PRESS, DW_SIGNAL_FUNC(_null_key), (void *)100);
+			dw_signal_connect(handle, DW_SIGNAL_BUTTON_PRESS, DW_SIGNAL_FUNC(_null_key), (void *)100);
+			return;
+		}
+	}
+	WinEnableWindow(handle, FALSE);
+}
+
+/*
+ * Enables given window (widget).
+ * Parameters:
+ *       handle: Handle to the window.
+ */
+void API dw_window_enable(HWND handle)
+{
+	ULONG fore = (ULONG)dw_window_get_data(handle, "_dw_fore");
+	ULONG back = (ULONG)dw_window_get_data(handle, "_dw_back");
+	HWND hwnd = _find_entryfield(handle);
+
+	dw_window_set_data(handle, "_dw_disabled", 0);
+	if(hwnd)
+		dw_window_set_data(hwnd, "_dw_disabled", 0);
+	if(fore && back)
+		_dw_window_set_color(hwnd ? hwnd : handle, fore-1, back-1);
+	dw_signal_disconnect_by_data(handle, (void *)100);
+	WinEnableWindow(handle, TRUE);
+	if(dw_window_get_data(handle, "_dw_bitmapbutton") && dw_window_get_data(handle, "_dw_hpixmap_disabled"))
+		WinInvalidateRect(handle, NULL, FALSE);
+}
+
+/*
+ * Gets the child window handle with specified ID.
+ * Parameters:
+ *       handle: Handle to the parent window.
+ *       id: Integer ID of the child.
+ */
+HWND API dw_window_from_id(HWND handle, int id)
+{
+	HENUM henum;
+	HWND child;
+	char tmpbuf[100];
+
+	henum = WinBeginEnumWindows(handle);
+	while((child = WinGetNextWindow(henum)) != NULLHANDLE)
+	{
+		int windowid = WinQueryWindowUShort(child, QWS_ID);
+		HWND found;
+
+		WinQueryClassName(child, 99, tmpbuf);
+
+		/* If the child is a box (frame) then recurse into it */
+		if(strncmp(tmpbuf, "#1", 3)==0)
+			if((found = dw_window_from_id(child, id)) != NULLHANDLE)
+				return found;
+
+		if(windowid && windowid == id)
+		{
+			WinEndEnumWindows(henum);
+			return child;
+		}
+	}
+	WinEndEnumWindows(henum);
+	return NULLHANDLE;
+}
+
+/*
+ * Pack windows (widgets) into a box from the end (or bottom).
+ * Parameters:
+ *       box: Window handle of the box to be packed into.
+ *       item: Window handle of the item to be back.
+ *       width: Width in pixels of the item or -1 to be self determined.
+ *       height: Height in pixels of the item or -1 to be self determined.
+ *       hsize: TRUE if the window (widget) should expand horizontally to fill space given.
+ *       vsize: TRUE if the window (widget) should expand vertically to fill space given.
+ *       pad: Number of pixels of padding around the item.
+ */
+void API dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad)
+{
+	Box *thisbox;
+	char *funcname = "dw_box_pack_end()";
+
+		/*
+		 * If you try and pack an item into itself VERY bad things can happen; like at least an
+		 * infinite loop on GTK! Lets be safe!
+		 */
+	if(box == item)
+	{
+		dw_messagebox(funcname, DW_MB_OK|DW_MB_ERROR, "Danger! Danger! Will Robinson; box and item are the same!",box,item);
+		return;
+	}
+
+	if(WinWindowFromID(box, FID_CLIENT))
+	{
+		box = WinWindowFromID(box, FID_CLIENT);
+		thisbox = WinQueryWindowPtr(box, QWP_USER);
+		hsize = TRUE;
+		vsize = TRUE;
+	}
+	else
+		thisbox = WinQueryWindowPtr(box, QWP_USER);
+	if(thisbox)
+	{
+		if(thisbox->type == DW_HORZ)
+			_dw_box_pack_start(box, item, width, height, hsize, vsize, pad, funcname);
+		else
+			_dw_box_pack_end(box, item, width, height, hsize, vsize, pad, funcname);
+	}
+}
+
+void _dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad, char *functionname)
+{
+	Box *thisbox = WinQueryWindowPtr(box, QWP_USER);
+
+	if(thisbox)
+	{
+		int z;
+		Item *tmpitem, *thisitem = thisbox->items;
+		char tmpbuf[100];
+		HWND frame = (HWND)dw_window_get_data(item, "_dw_combo_box");
+
+		tmpitem = malloc(sizeof(Item)*(thisbox->count+1));
+
+		for(z=0;z<thisbox->count;z++)
+		{
+			tmpitem[z] = thisitem[z];
+		}
+
+		WinQueryClassName(item, 99, tmpbuf);
+
+		if(vsize && !height)
+			height = 1;
+		if(hsize && !width)
+			width = 1;
+
+		if(strncmp(tmpbuf, "#1", 3)==0)
+			tmpitem[thisbox->count].type = TYPEBOX;
+		else
+		{
+			if ( width == 0 && hsize == FALSE )
+				dw_messagebox(functionname, DW_MB_OK|DW_MB_ERROR, "Width and expand Horizonal both unset for box: %x item: %x",box,item);
+			if ( height == 0 && vsize == FALSE )
+				dw_messagebox(functionname, DW_MB_OK|DW_MB_ERROR, "Height and expand Vertical both unset for box: %x item: %x",box,item);
+
+			tmpitem[thisbox->count].type = TYPEITEM;
+		}
+
+		tmpitem[thisbox->count].hwnd = item;
+		tmpitem[thisbox->count].origwidth = tmpitem[thisbox->count].width = width;
+		tmpitem[thisbox->count].origheight = tmpitem[thisbox->count].height = height;
+		tmpitem[thisbox->count].pad = pad;
+		if(hsize)
+			tmpitem[thisbox->count].hsize = SIZEEXPAND;
+		else
+			tmpitem[thisbox->count].hsize = SIZESTATIC;
+
+		if(vsize)
+			tmpitem[thisbox->count].vsize = SIZEEXPAND;
+		else
+			tmpitem[thisbox->count].vsize = SIZESTATIC;
+
+		thisbox->items = tmpitem;
+
+		if(thisbox->count)
+			free(thisitem);
+
+		thisbox->count++;
+
+        /* Don't set the ownership if it's an entryfield  or spinbutton */
+		WinQueryClassName(item, 99, tmpbuf);
+		if(strncmp(tmpbuf, "#6", 3)!=0 && strncmp(tmpbuf, "#32", 4)!=0 && strncmp(tmpbuf, "#2", 3)!=0)
+			WinSetOwner(item, box);
+		WinSetParent(frame ? frame : item, box, FALSE);
+	}
+}
+
+/*
+ * Sets the size of a given window (widget).
+ * Parameters:
+ *          handle: Window (widget) handle.
+ *          width: New width in pixels.
+ *          height: New height in pixels.
+ */
+void API dw_window_set_usize(HWND handle, ULONG width, ULONG height)
+{
+	WinSetWindowPos(handle, NULLHANDLE, 0, 0, width, height, SWP_SHOW | SWP_SIZE);
+}
+
+/*
+ * Returns the width of the screen.
+ */
+int API dw_screen_width(void)
+{
+	return WinQuerySysValue(HWND_DESKTOP,SV_CXSCREEN);
+}
+
+/*
+ * Returns the height of the screen.
+ */
+int API dw_screen_height(void)
+{
+	return WinQuerySysValue(HWND_DESKTOP,SV_CYSCREEN);
+}
+
+/* This should return the current color depth */
+unsigned long API dw_color_depth(void)
+{
+	HDC hdc = WinOpenWindowDC(HWND_DESKTOP);
+	long colors;
+
+	DevQueryCaps(hdc, CAPS_COLOR_BITCOUNT, 1, &colors);
+	DevCloseDC(hdc);
+	return colors;
+}
+
+
+/*
+ * Sets the position of a given window (widget).
+ * Parameters:
+ *          handle: Window (widget) handle.
+ *          x: X location from the bottom left.
+ *          y: Y location from the bottom left.
+ */
+void API dw_window_set_pos(HWND handle, ULONG x, ULONG y)
+{
+	int myy = _get_frame_height(handle) - (y + _get_height(handle));
+
+	WinSetWindowPos(handle, NULLHANDLE, x, myy, 0, 0, SWP_MOVE);
+}
+
+/*
+ * Sets the position and size of a given window (widget).
+ * Parameters:
+ *          handle: Window (widget) handle.
+ *          x: X location from the bottom left.
+ *          y: Y location from the bottom left.
+ *          width: Width of the widget.
+ *          height: Height of the widget.
+ */
+void API dw_window_set_pos_size(HWND handle, ULONG x, ULONG y, ULONG width, ULONG height)
+{
+	int myy = _get_frame_height(handle) - (y + height);
+
+	WinSetWindowPos(handle, NULLHANDLE, x, myy, width, height, SWP_MOVE | SWP_SIZE | SWP_SHOW);
+}
+
+/*
+ * Gets the position and size of a given window (widget).
+ * Parameters:
+ *          handle: Window (widget) handle.
+ *          x: X location from the bottom left.
+ *          y: Y location from the bottom left.
+ *          width: Width of the widget.
+ *          height: Height of the widget.
+ */
+void API dw_window_get_pos_size(HWND handle, ULONG *x, ULONG *y, ULONG *width, ULONG *height)
+{
+	SWP swp;
+	WinQueryWindowPos(handle, &swp);
+	if(x)
+		*x = swp.x;
+	if(y)
+		*y = _get_frame_height(handle) - (swp.y + swp.cy);
+	if(width)
+		*width = swp.cx;
+	if(height)
+		*height = swp.cy;
+}
+
+/*
+ * Sets the style of a given window (widget).
+ * Parameters:
+ *          handle: Window (widget) handle.
+ *          width: New width in pixels.
+ *          height: New height in pixels.
+ */
+void API dw_window_set_style(HWND handle, ULONG style, ULONG mask)
+{
+	WinSetWindowBits(handle, QWL_STYLE, style, mask);
+}
+
+/*
+ * Adds a new page to specified notebook.
+ * Parameters:
+ *          handle: Window (widget) handle.
+ *          flags: Any additional page creation flags.
+ *          front: If TRUE page is added at the beginning.
+ */
+unsigned long API dw_notebook_page_new(HWND handle, ULONG flags, int front)
+{
+	return (ULONG)WinSendMsg(handle, BKM_INSERTPAGE, 0L,
+							 MPFROM2SHORT((BKA_STATUSTEXTON | BKA_AUTOPAGESIZE | BKA_MAJOR | flags), front ? BKA_FIRST : BKA_LAST));
+}
+
+/*
+ * Remove a page from a notebook.
+ * Parameters:
+ *          handle: Handle to the notebook widget.
+ *          pageid: ID of the page to be destroyed.
+ */
+void API dw_notebook_page_destroy(HWND handle, unsigned int pageid)
+{
+	WinSendMsg(handle, BKM_DELETEPAGE,
+			   MPFROMLONG(pageid),	(MPARAM)BKA_SINGLE);
+}
+
+/*
+ * Queries the currently visible page ID.
+ * Parameters:
+ *          handle: Handle to the notebook widget.
+ */
+unsigned long API dw_notebook_page_query(HWND handle)
+{
+	return (unsigned long)WinSendMsg(handle, BKM_QUERYPAGEID,0L, MPFROM2SHORT(BKA_TOP, BKA_MAJOR));
+}
+
+/*
+ * Sets the currently visibale page ID.
+ * Parameters:
+ *          handle: Handle to the notebook widget.
+ *          pageid: ID of the page to be made visible.
+ */
+void API dw_notebook_page_set(HWND handle, unsigned int pageid)
+{
+	WinSendMsg(handle, BKM_TURNTOPAGE, MPFROMLONG(pageid), 0L);
+}
+
+/*
+ * Sets the text on the specified notebook tab.
+ * Parameters:
+ *          handle: Notebook handle.
+ *          pageid: Page ID of the tab to set.
+ *          text: Pointer to the text to set.
+ */
+void API dw_notebook_page_set_text(HWND handle, ULONG pageid, char *text)
+{
+	WinSendMsg(handle, BKM_SETTABTEXT,
+			   MPFROMLONG(pageid),	MPFROMP(text));
+}
+
+/*
+ * Sets the text on the specified notebook tab status area.
+ * Parameters:
+ *          handle: Notebook handle.
+ *          pageid: Page ID of the tab to set.
+ *          text: Pointer to the text to set.
+ */
+void API dw_notebook_page_set_status_text(HWND handle, ULONG pageid, char *text)
+{
+	WinSendMsg(handle, BKM_SETSTATUSLINETEXT,
+			   MPFROMLONG(pageid),	MPFROMP(text));
+}
+
+/*
+ * Packs the specified box into the notebook page.
+ * Parameters:
+ *          handle: Handle to the notebook to be packed.
+ *          pageid: Page ID in the notebook which is being packed.
+ *          page: Box handle to be packed.
+ */
+void API dw_notebook_pack(HWND handle, ULONG pageid, HWND page)
+{
+	HWND tmpbox = dw_box_new(DW_VERT, 0);
+
+	dw_box_pack_start(tmpbox, page, 0, 0, TRUE, TRUE, 0);
+	WinSubclassWindow(tmpbox, _wndproc);
+	WinSendMsg(handle, BKM_SETPAGEWINDOWHWND,
+			   MPFROMLONG(pageid),	MPFROMHWND(tmpbox));
+}
+
+/*
+ * Appends the specified text to the listbox's (or combobox) entry list.
+ * Parameters:
+ *          handle: Handle to the listbox to be appended to.
+ *          text: Text to append into listbox.
+ */
+void API dw_listbox_append(HWND handle, char *text)
+{
+	WinSendMsg(handle,
+			   LM_INSERTITEM,
+			   MPFROMSHORT(LIT_END),
+			   MPFROMP(text));
+}
+
+/*
+ * Clears the listbox's (or combobox) list of all entries.
+ * Parameters:
+ *          handle: Handle to the listbox to be cleared.
+ */
+void API dw_listbox_clear(HWND handle)
+{
+	WinSendMsg(handle,
+			   LM_DELETEALL, 0L, 0L);
+}
+
+/*
+ * Returns the listbox's item count.
+ * Parameters:
+ *          handle: Handle to the listbox to be cleared.
+ */
+int API dw_listbox_count(HWND handle)
+{
+	return (int)WinSendMsg(handle,
+						   LM_QUERYITEMCOUNT,0L, 0L);
+}
+
+/*
+ * Sets the topmost item in the viewport.
+ * Parameters:
+ *          handle: Handle to the listbox to be cleared.
+ *          top: Index to the top item.
+ */
+void API dw_listbox_set_top(HWND handle, int top)
+{
+	WinSendMsg(handle,
+			   LM_SETTOPINDEX,
+			   MPFROMSHORT(top),
+			   0L);
+}
+
+/*
+ * Copies the given index item's text into buffer.
+ * Parameters:
+ *          handle: Handle to the listbox to be queried.
+ *          index: Index into the list to be queried.
+ *          buffer: Buffer where text will be copied.
+ *          length: Length of the buffer (including NULL).
+ */
+void API dw_listbox_query_text(HWND handle, unsigned int index, char *buffer, unsigned int length)
+{
+	WinSendMsg(handle, LM_QUERYITEMTEXT, MPFROM2SHORT(index, length), (MPARAM)buffer);
+}
+
+/*
+ * Sets the text of a given listbox entry.
+ * Parameters:
+ *          handle: Handle to the listbox to be queried.
+ *          index: Index into the list to be queried.
+ *          buffer: Buffer where text will be copied.
+ */
+void API dw_listbox_set_text(HWND handle, unsigned int index, char *buffer)
+{
+	WinSendMsg(handle, LM_SETITEMTEXT, MPFROMSHORT(index), (MPARAM)buffer);
+}
+
+/*
+ * Returns the index to the item in the list currently selected.
+ * Parameters:
+ *          handle: Handle to the listbox to be queried.
+ */
+unsigned int API dw_listbox_selected(HWND handle)
+{
+		return (unsigned int)WinSendMsg(handle,
+										LM_QUERYSELECTION,
+										MPFROMSHORT(LIT_CURSOR),
+										0);
+}
+
+/*
+ * Returns the index to the current selected item or -1 when done.
+ * Parameters:
+ *          handle: Handle to the listbox to be queried.
+ *          where: Either the previous return or -1 to restart.
+ */
+int API dw_listbox_selected_multi(HWND handle, int where)
+{
+	int place = where;
+
+	if(where == -1)
+		place = LIT_FIRST;
+
+	place = (int)WinSendMsg(handle,
+							LM_QUERYSELECTION,
+							MPFROMSHORT(place),0L);
+	if(place == LIT_NONE)
+		return -1;
+	return place;
+}
+
+/*
+ * Sets the selection state of a given index.
+ * Parameters:
+ *          handle: Handle to the listbox to be set.
+ *          index: Item index.
+ *          state: TRUE if selected FALSE if unselected.
+ */
+void API dw_listbox_select(HWND handle, int index, int state)
+{
+	char tmpbuf[100];
+
+	WinSendMsg(handle, LM_SELECTITEM, MPFROMSHORT(index), (MPARAM)state);
+
+	WinQueryClassName(handle, 99, tmpbuf);
+
+	/* If we are setting a combobox call the event handler manually */
+	if(strncmp(tmpbuf, "#6", 3)==0)
+		_run_event(handle, WM_CONTROL, MPFROM2SHORT(0, LN_SELECT), (MPARAM)handle);
+}
+
+/*
+ * Deletes the item with given index from the list.
+ * Parameters:
+ *          handle: Handle to the listbox to be set.
+ *          index: Item index.
+ */
+void API dw_listbox_delete(HWND handle, int index)
+{
+	WinSendMsg(handle, LM_DELETEITEM, MPFROMSHORT(index), 0);
+}
+
+/*
+ * Adds text to an MLE box and returns the current point.
+ * Parameters:
+ *          handle: Handle to the MLE to be queried.
+ *          buffer: Text buffer to be imported.
+ *          startpoint: Point to start entering text.
+ */
+unsigned int API dw_mle_import(HWND handle, char *buffer, int startpoint)
+{
+	unsigned long point = startpoint;
+	PBYTE mlebuf;
+
+	/* Work around 64K limit */
+	if(!DosAllocMem((PPVOID) &mlebuf, 65536, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_TILE))
+	{
+		int amount, len = strlen(buffer), written = 0;
+
+		while(written < len)
+		{
+			if((len - written) > 65535)
+				amount = 65535;
+			else
+				amount = len - written;
+
+			memcpy(mlebuf, &buffer[written], amount);
+			mlebuf[amount] = '\0';
+
+			WinSendMsg(handle, MLM_SETIMPORTEXPORT, MPFROMP(mlebuf), MPFROMLONG(amount+1));
+			WinSendMsg(handle, MLM_IMPORT, MPFROMP(&point), MPFROMLONG(amount + 1));
+			dw_mle_delete(handle, point, 1);
+
+			written += amount;
+		}
+		DosFreeMem(mlebuf);
+	}
+	return point - 1;
+}
+
+/*
+ * Grabs text from an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to be queried.
+ *          buffer: Text buffer to be exported.
+ *          startpoint: Point to start grabbing text.
+ *          length: Amount of text to be grabbed.
+ */
+void API dw_mle_export(HWND handle, char *buffer, int startpoint, int length)
+{
+	PBYTE mlebuf;
+
+	/* Work around 64K limit */
+	if(!DosAllocMem((PPVOID) &mlebuf, 65535, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_TILE))
+	{
+		int amount, copied, written = 0;
+
+		while(written < length)
+		{
+			if((length - written) > 65535)
+				amount = 65535;
+			else
+				amount = length - written;
+
+			WinSendMsg(handle, MLM_SETIMPORTEXPORT, MPFROMP(mlebuf), MPFROMLONG(amount));
+			copied = (int)WinSendMsg(handle, MLM_EXPORT, MPFROMP(&startpoint), MPFROMLONG(&amount));
+
+			if(copied)
+			{
+				memcpy(&buffer[written], mlebuf, copied);
+
+				written += copied;
+			}
+			else
+				break;
+		}
+		DosFreeMem(mlebuf);
+	}
+}
+
+/*
+ * Obtains information about an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to be queried.
+ *          bytes: A pointer to a variable to return the total bytes.
+ *          lines: A pointer to a variable to return the number of lines.
+ */
+void API dw_mle_query(HWND handle, unsigned long *bytes, unsigned long *lines)
+{
+	if(bytes)
+		*bytes = (unsigned long)WinSendMsg(handle, MLM_QUERYTEXTLENGTH, 0, 0);
+	if(lines)
+		*lines = (unsigned long)WinSendMsg(handle, MLM_QUERYLINECOUNT, 0, 0);
+}
+
+/*
+ * Deletes text from an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to be deleted from.
+ *          startpoint: Point to start deleting text.
+ *          length: Amount of text to be deleted.
+ */
+void API dw_mle_delete(HWND handle, int startpoint, int length)
+{
+	char *buf = malloc(length+1);
+	int z, dellen = length;
+
+	dw_mle_export(handle, buf, startpoint, length);
+
+	for(z=0;z<length-1;z++)
+	{
+		if(strncmp(&buf[z], "\r\n", 2) == 0)
+			dellen--;
+	}
+	WinSendMsg(handle, MLM_DELETE, MPFROMLONG(startpoint), MPFROMLONG(dellen));
+	free(buf);
+}
+
+/*
+ * Clears all text from an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to be cleared.
+ */
+void API dw_mle_clear(HWND handle)
+{
+	unsigned long bytes;
+
+	dw_mle_query(handle, &bytes, NULL);
+
+	WinSendMsg(handle, MLM_DELETE, MPFROMLONG(0), MPFROMLONG(bytes));
+}
+
+/*
+ * Sets the visible line of an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to be positioned.
+ *          line: Line to be visible.
+ */
+void API dw_mle_set_visible(HWND handle, int line)
+{
+	int tmppnt = (int)WinSendMsg(handle, MLM_CHARFROMLINE, MPFROMLONG(line), 0);
+	WinSendMsg(handle, MLM_SETSEL, MPFROMLONG(tmppnt), MPFROMLONG(tmppnt));
+}
+
+/*
+ * Sets the editablity of an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE.
+ *          state: TRUE if it can be edited, FALSE for readonly.
+ */
+void API dw_mle_set_editable(HWND handle, int state)
+{
+	WinSendMsg(handle, MLM_SETREADONLY, MPFROMLONG(state ? FALSE : TRUE), 0);
+}
+
+/*
+ * Sets the word wrap state of an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE.
+ *          state: TRUE if it wraps, FALSE if it doesn't.
+ */
+void API dw_mle_set_word_wrap(HWND handle, int state)
+{
+	WinSendMsg(handle, MLM_SETWRAP, MPFROMLONG(state), 0);
+}
+
+/*
+ * Sets the current cursor position of an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to be positioned.
+ *          point: Point to position cursor.
+ */
+void API dw_mle_set(HWND handle, int point)
+{
+	WinSendMsg(handle, MLM_SETSEL, MPFROMLONG(point), MPFROMLONG(point));
+}
+
+/*
+ * Finds text in an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to be cleared.
+ *          text: Text to search for.
+ *          point: Start point of search.
+ *          flags: Search specific flags.
+ */
+int API dw_mle_search(HWND handle, char *text, int point, unsigned long flags)
+{
+	MLE_SEARCHDATA msd;
+
+	/* This code breaks with structure packing set to 1 (/Sp1 in VAC)
+	 * if this is needed we need to add a pragma here.
+	 */
+	msd.cb = sizeof(msd);
+	msd.pchFind = text;
+	msd.pchReplace = NULL;
+	msd.cchFind = strlen(text);
+	msd.cchReplace = 0;
+	msd.iptStart = point;
+	msd.iptStop = -1;
+
+	if(WinSendMsg(handle, MLM_SEARCH, MPFROMLONG(MLFSEARCH_SELECTMATCH | flags), (MPARAM)&msd))
+		return (int)WinSendMsg(handle, MLM_QUERYSEL,(MPARAM)MLFQS_MAXSEL, 0);
+	return 0;
+}
+
+/*
+ * Stops redrawing of an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to freeze.
+ */
+void API dw_mle_freeze(HWND handle)
+{
+	WinSendMsg(handle, MLM_DISABLEREFRESH, 0, 0);
+}
+
+/*
+ * Resumes redrawing of an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to thaw.
+ */
+void API dw_mle_thaw(HWND handle)
+{
+	WinSendMsg(handle, MLM_ENABLEREFRESH, 0, 0);
+}
+
+/*
+ * Returns the range of the percent bar.
+ * Parameters:
+ *          handle: Handle to the percent bar to be queried.
+ */
+unsigned int API dw_percent_query_range(HWND handle)
+{
+	return SHORT2FROMMP(WinSendMsg(handle, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION,SMA_RANGEVALUE), 0));
+}
+
+/*
+ * Sets the percent bar position.
+ * Parameters:
+ *          handle: Handle to the percent bar to be set.
+ *          position: Position of the percent bar withing the range.
+ */
+void API dw_percent_set_pos(HWND handle, unsigned int position)
+{
+	_dw_int_set(handle, position);
+	WinSendMsg(handle, SLM_SETSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION,SMA_RANGEVALUE), (MPARAM)position);
+}
+
+/*
+ * Returns the position of the slider.
+ * Parameters:
+ *          handle: Handle to the slider to be queried.
+ */
+unsigned int API dw_slider_query_pos(HWND handle)
+{
+	return (unsigned int)WinSendMsg(handle, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), 0);
+}
+
+/*
+ * Sets the slider position.
+ * Parameters:
+ *          handle: Handle to the slider to be set.
+ *          position: Position of the slider withing the range.
+ */
+void API dw_slider_set_pos(HWND handle, unsigned int position)
+{
+	dw_window_set_data(handle, "_dw_slider_value", (void *)position);
+	WinSendMsg(handle, SLM_SETSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE), (MPARAM)position);
+}
+
+/*
+ * Returns the position of the scrollbar.
+ * Parameters:
+ *          handle: Handle to the scrollbar to be queried.
+ */
+unsigned int API dw_scrollbar_query_pos(HWND handle)
+{
+	return (unsigned int)WinSendMsg(handle, SBM_QUERYPOS, 0, 0);
+}
+
+/*
+ * Sets the scrollbar position.
+ * Parameters:
+ *          handle: Handle to the scrollbar to be set.
+ *          position: Position of the scrollbar withing the range.
+ */
+void API dw_scrollbar_set_pos(HWND handle, unsigned int position)
+{
+	dw_window_set_data(handle, "_dw_scrollbar_value", (void *)position);
+	WinSendMsg(handle, SBM_SETPOS, (MPARAM)position, 0);
+}
+
+/*
+ * Sets the scrollbar range.
+ * Parameters:
+ *          handle: Handle to the scrollbar to be set.
+ *          range: Maximum range value.
+ *          visible: Visible area relative to the range.
+ */
+void API dw_scrollbar_set_range(HWND handle, unsigned int range, unsigned int visible)
+{
+	unsigned int pos = (unsigned int)dw_window_get_data(handle, "_dw_scrollbar_value");
+	WinSendMsg(handle, SBM_SETSCROLLBAR, (MPARAM)pos, MPFROM2SHORT(0, (unsigned short)range - visible));
+	WinSendMsg(handle, SBM_SETTHUMBSIZE, MPFROM2SHORT((unsigned short)visible, range), 0);
+	dw_window_set_data(handle, "_dw_scrollbar_visible", (void *)visible);
+}
+
+/*
+ * Sets the spinbutton value.
+ * Parameters:
+ *          handle: Handle to the spinbutton to be set.
+ *          position: Current value of the spinbutton.
+ */
+void API dw_spinbutton_set_pos(HWND handle, long position)
+{
+	WinSendMsg(handle, SPBM_SETCURRENTVALUE, MPFROMLONG((long)position), 0L);
+}
+
+/*
+ * Sets the spinbutton limits.
+ * Parameters:
+ *          handle: Handle to the spinbutton to be set.
+ *          upper: Upper limit.
+ *          lower: Lower limit.
+ */
+void API dw_spinbutton_set_limits(HWND handle, long upper, long lower)
+{
+	WinSendMsg(handle, SPBM_SETLIMITS, MPFROMLONG(upper), MPFROMLONG(lower));
+}
+
+/*
+ * Sets the entryfield character limit.
+ * Parameters:
+ *          handle: Handle to the spinbutton to be set.
+ *          limit: Number of characters the entryfield will take.
+ */
+void API dw_entryfield_set_limit(HWND handle, ULONG limit)
+{
+	WinSendMsg(handle, EM_SETTEXTLIMIT, (MPARAM)limit, (MPARAM)0);
+}
+
+
+/*
+ * Returns the current value of the spinbutton.
+ * Parameters:
+ *          handle: Handle to the spinbutton to be queried.
+ */
+long API dw_spinbutton_query(HWND handle)
+{
+	long tmpval = 0L;
+
+	WinSendMsg(handle, SPBM_QUERYVALUE, (MPARAM)&tmpval,0L);
+    return tmpval;
+}
+
+/*
+ * Returns the state of the checkbox.
+ * Parameters:
+ *          handle: Handle to the checkbox to be queried.
+ */
+int API dw_checkbox_query(HWND handle)
+{
+	return (int)WinSendMsg(handle,BM_QUERYCHECK,0,0);
+}
+
+/*
+ * Sets the state of the checkbox.
+ * Parameters:
+ *          handle: Handle to the checkbox to be queried.
+ *          value: TRUE for checked, FALSE for unchecked.
+ */
+void API dw_checkbox_set(HWND handle, int value)
+{
+	WinSendMsg(handle,BM_SETCHECK,MPFROMSHORT(value),0);
+}
+
+/*
+ * Inserts an item into a tree window (widget) after another item.
+ * Parameters:
+ *          handle: Handle to the tree to be inserted.
+ *          item: Handle to the item to be positioned after.
+ *          title: The text title of the entry.
+ *          icon: Handle to coresponding icon.
+ *          parent: Parent handle or 0 if root.
+ *          itemdata: Item specific data.
+ */
+HTREEITEM API dw_tree_insert_after(HWND handle, HTREEITEM item, char *title, unsigned long icon, HTREEITEM parent, void *itemdata)
+{
+	ULONG        cbExtra;
+	PCNRITEM     pci;
+	RECORDINSERT ri;
+
+	if(!item)
+		item = (HTREEITEM)CMA_FIRST;
+
+	/* Calculate extra bytes needed for each record besides that needed for the
+	 * MINIRECORDCORE structure
+	 */
+
+	cbExtra = sizeof(CNRITEM) - sizeof(MINIRECORDCORE);
+
+	/* Allocate memory for the parent record */
+
+	if((pci = (PCNRITEM)_dw_send_msg(handle, CM_ALLOCRECORD, MPFROMLONG(cbExtra), MPFROMSHORT(1), 0)) == 0)
+		return 0;
+
+	/* Fill in the parent record data */
+
+	pci->rc.cb          = sizeof(MINIRECORDCORE);
+	pci->rc.pszIcon     = strdup(title);
+	pci->rc.hptrIcon    = icon;
+
+	pci->hptrIcon       = icon;
+	pci->user           = itemdata;
+	pci->parent         = parent;
+
+	memset(&ri, 0, sizeof(RECORDINSERT));
+
+	ri.cb                 = sizeof(RECORDINSERT);
+	ri.pRecordOrder       = (PRECORDCORE)item;
+	ri.zOrder             = (USHORT)CMA_TOP;
+	ri.cRecordsInsert     = 1;
+	ri.fInvalidateRecord  = TRUE;
+
+	/* We are about to insert the child records. Set the parent record to be
+	 * the one we just inserted.
+	 */
+	ri.pRecordParent = (PRECORDCORE)parent;
+
+	/* Insert the record */
+	WinSendMsg(handle, CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri));
+
+	return (HTREEITEM)pci;
+}
+
+/*
+ * Inserts an item into a tree window (widget).
+ * Parameters:
+ *          handle: Handle to the tree to be inserted.
+ *          title: The text title of the entry.
+ *          icon: Handle to coresponding icon.
+ *          parent: Parent handle or 0 if root.
+ *          itemdata: Item specific data.
+ */
+HTREEITEM API dw_tree_insert(HWND handle, char *title, unsigned long icon, HTREEITEM parent, void *itemdata)
+{
+	return dw_tree_insert_after(handle, (HTREEITEM)CMA_END, title, icon, parent, itemdata);
+}
+
+/*
+ * Sets the text and icon of an item in a tree window (widget).
+ * Parameters:
+ *          handle: Handle to the tree containing the item.
+ *          item: Handle of the item to be modified.
+ *          title: The text title of the entry.
+ *          icon: Handle to coresponding icon.
+ */
+void API dw_tree_set(HWND handle, HTREEITEM item, char *title, unsigned long icon)
+{
+	PCNRITEM pci = (PCNRITEM)item;
+
+	if(!pci)
+		return;
+
+	if(pci->rc.pszIcon)
+		free(pci->rc.pszIcon);
+
+	pci->rc.pszIcon     = strdup(title);
+	pci->rc.hptrIcon    = icon;
+
+	pci->hptrIcon       = icon;
+
+	WinSendMsg(handle, CM_INVALIDATERECORD, (MPARAM)&pci, MPFROM2SHORT(1, CMA_TEXTCHANGED));
+}
+
+/*
+ * Gets the text an item in a tree window (widget).
+ * Parameters:
+ *          handle: Handle to the tree containing the item.
+ *          item: Handle of the item to be modified.
+ */
+char * API dw_tree_get_title(HWND handle, HTREEITEM item)
+{
+	PCNRITEM pci = (PCNRITEM)item;
+
+	handle = handle; /* keep compiler happy */
+	if(pci)
+		return pci->rc.pszIcon;
+	return NULL;
+}
+
+/*
+ * Gets the text an item in a tree window (widget).
+ * Parameters:
+ *          handle: Handle to the tree containing the item.
+ *          item: Handle of the item to be modified.
+ */
+HTREEITEM API dw_tree_get_parent(HWND handle, HTREEITEM item)
+{
+	PCNRITEM pci = (PCNRITEM)item;
+
+	handle = handle; /* keep compiler happy */
+	if(pci)
+		return pci->parent;
+	return (HTREEITEM)0;
+}
+
+/*
+ * Sets the item data of a tree item.
+ * Parameters:
+ *          handle: Handle to the tree containing the item.
+ *          item: Handle of the item to be modified.
+ *          itemdata: User defined data to be associated with item.
+ */
+void API dw_tree_set_data(HWND handle, HTREEITEM item, void *itemdata)
+{
+	PCNRITEM pci = (PCNRITEM)item;
+
+	handle = handle; /* keep compiler happy */
+	if(!pci)
+		return;
+
+	pci->user = itemdata;
+}
+
+/*
+ * Gets the item data of a tree item.
+ * Parameters:
+ *          handle: Handle to the tree containing the item.
+ *          item: Handle of the item to be modified.
+ */
+void * API dw_tree_get_data(HWND handle, HTREEITEM item)
+{
+	PCNRITEM pci = (PCNRITEM)item;
+
+	handle = handle; /* keep compiler happy */
+	if(!pci)
+		return NULL;
+	return pci->user;
+}
+
+/*
+ * Sets this item as the active selection.
+ * Parameters:
+ *       handle: Handle to the tree window (widget) to be selected.
+ *       item: Handle to the item to be selected.
+ */
+void API dw_tree_item_select(HWND handle, HTREEITEM item)
+{
+	PRECORDCORE pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
+
+	while(pCore)
+	{
+		if(pCore->flRecordAttr & CRA_SELECTED)
+			WinSendMsg(handle, CM_SETRECORDEMPHASIS, (MPARAM)pCore, MPFROM2SHORT(FALSE, CRA_SELECTED | CRA_CURSORED));
+		pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
+	}
+	WinSendMsg(handle, CM_SETRECORDEMPHASIS, (MPARAM)item, MPFROM2SHORT(TRUE, CRA_SELECTED | CRA_CURSORED));
+	lastitem = 0;
+	lasthcnr = 0;
+}
+
+/*
+ * Removes all nodes from a tree.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be cleared.
+ */
+void API dw_tree_clear(HWND handle)
+{
+	dw_container_clear(handle, TRUE);
+}
+
+/*
+ * Expands a node on a tree.
+ * Parameters:
+ *       handle: Handle to the tree window (widget).
+ *       item: Handle to node to be expanded.
+ */
+void API dw_tree_expand(HWND handle, HTREEITEM item)
+{
+	WinSendMsg(handle, CM_EXPANDTREE, MPFROMP(item), 0);
+}
+
+/*
+ * Collapses a node on a tree.
+ * Parameters:
+ *       handle: Handle to the tree window (widget).
+ *       item: Handle to node to be collapsed.
+ */
+void API dw_tree_collapse(HWND handle, HTREEITEM item)
+{
+	WinSendMsg(handle, CM_COLLAPSETREE, MPFROMP(item), 0);
+}
+
+/*
+ * Removes a node from a tree.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be cleared.
+ *       item: Handle to node to be deleted.
+ */
+void API dw_tree_delete(HWND handle, HTREEITEM item)
+{
+	PCNRITEM     pci = (PCNRITEM)item;
+
+	if(!item)
+		return;
+
+	if(pci->rc.pszIcon)
+	{
+		free(pci->rc.pszIcon);
+		pci->rc.pszIcon = 0;
+	}
+
+	WinSendMsg(handle, CM_REMOVERECORD, (MPARAM)&pci, MPFROM2SHORT(1, CMA_INVALIDATE | CMA_FREE));
+}
+
+/* Some OS/2 specific container structs */
+typedef struct _containerinfo {
+	int count;
+	void *data;
+	HWND handle;
+} ContainerInfo;
+
+/*
+ * Sets up the container columns.
+ * Parameters:
+ *          handle: Handle to the container to be configured.
+ *          flags: An array of unsigned longs with column flags.
+ *          titles: An array of strings with column text titles.
+ *          count: The number of columns (this should match the arrays).
+ *          separator: The column number that contains the main separator.
+ *                     (this item may only be used in OS/2)
+ */
+int API dw_container_setup(HWND handle, unsigned long *flags, char **titles, int count, int separator)
+{
+	PFIELDINFO details, first, left = NULL;
+	FIELDINFOINSERT detin;
+	CNRINFO cnri;
+	int z;
+	ULONG size = sizeof(RECORDCORE);
+	ULONG *offStruct = malloc(count * sizeof(ULONG));
+	ULONG *tempflags = malloc((count+1) * sizeof(ULONG));
+	WindowData *blah = (WindowData *)WinQueryWindowPtr(handle, QWP_USER);
+	ULONG *oldflags = blah ? blah->data : 0;
+
+	if(!offStruct || !tempflags)
+		return FALSE;
+
+	memcpy(tempflags, flags, count * sizeof(ULONG));
+	tempflags[count] = 0;
+
+	blah->data = tempflags;
+	blah->flags = separator;
+
+	if(oldflags)
+		free(oldflags);
+
+	while((first = (PFIELDINFO)WinSendMsg(handle, CM_QUERYDETAILFIELDINFO,  0, MPFROMSHORT(CMA_FIRST))) != NULL)
+	{
+		WinSendMsg(handle, CM_REMOVEDETAILFIELDINFO, (MPARAM)&first, MPFROM2SHORT(1, CMA_FREE));
+	}
+
+	/* Figure out the offsets to the items in the struct */
+	for(z=0;z<count;z++)
+	{
+		offStruct[z] = size;
+		if(flags[z] & DW_CFA_BITMAPORICON)
+			size += sizeof(HPOINTER);
+		else if(flags[z] & DW_CFA_STRING)
+			size += sizeof(char *);
+		else if(flags[z] & DW_CFA_ULONG)
+			size += sizeof(ULONG);
+		else if(flags[z] & DW_CFA_DATE)
+			size += sizeof(CDATE);
+		else if(flags[z] & DW_CFA_TIME)
+			size += sizeof(CTIME);
+	}
+
+	first = details = (PFIELDINFO)WinSendMsg(handle, CM_ALLOCDETAILFIELDINFO, MPFROMLONG(count), 0L);
+
+	if(!first)
+	{
+		free(offStruct);
+		return FALSE;
+	}
+
+	for(z=0;z<count;z++)
+	{
+		if(z==separator-1)
+			left=details;
+		details->cb = sizeof(FIELDINFO);
+		details->flData = flags[z];
+		details->flTitle = CFA_FITITLEREADONLY;
+		details->pTitleData = titles[z];
+		details->offStruct = offStruct[z];
+		details = details->pNextFieldInfo;
+	}
+
+	detin.cb = sizeof(FIELDINFOINSERT);
+	detin.fInvalidateFieldInfo = FALSE;
+	detin.pFieldInfoOrder = (PFIELDINFO) CMA_FIRST;
+	detin.cFieldInfoInsert = (ULONG)count;
+
+	WinSendMsg(handle, CM_INSERTDETAILFIELDINFO, MPFROMP(first), MPFROMP(&detin));
+
+	if(count > separator && separator > 0)
+	{
+		cnri.cb = sizeof(CNRINFO);
+		cnri.pFieldInfoLast = left;
+		cnri.xVertSplitbar  = 150;
+
+		WinSendMsg(handle, CM_SETCNRINFO, MPFROMP(&cnri),  MPFROMLONG(CMA_PFIELDINFOLAST | CMA_XVERTSPLITBAR));
+	}
+
+	cnri.flWindowAttr = CV_DETAIL | CV_MINI | CA_DETAILSVIEWTITLES;
+	cnri.slBitmapOrIcon.cx = 16;
+	cnri.slBitmapOrIcon.cy = 16;
+
+	WinSendMsg(handle, CM_SETCNRINFO, &cnri, MPFROMLONG(CMA_FLWINDOWATTR | CMA_SLBITMAPORICON));
+
+	free(offStruct);
+	return TRUE;
+}
+
+/*
+ * Sets up the filesystem columns, note: filesystem always has an icon/filename field.
+ * Parameters:
+ *          handle: Handle to the container to be configured.
+ *          flags: An array of unsigned longs with column flags.
+ *          titles: An array of strings with column text titles.
+ *          count: The number of columns (this should match the arrays).
+ */
+int API dw_filesystem_setup(HWND handle, unsigned long *flags, char **titles, int count)
+{
+	char **newtitles = malloc(sizeof(char *) * (count + 2));
+	unsigned long *newflags = malloc(sizeof(unsigned long) * (count + 2));
+
+	newtitles[0] = "Icon";
+	newtitles[1] = "Filename";
+
+	newflags[0] = DW_CFA_BITMAPORICON | DW_CFA_CENTER | DW_CFA_HORZSEPARATOR | DW_CFA_SEPARATOR;
+	newflags[1] = DW_CFA_STRING | DW_CFA_LEFT | DW_CFA_HORZSEPARATOR;
+
+	memcpy(&newtitles[2], titles, sizeof(char *) * count);
+	memcpy(&newflags[2], flags, sizeof(unsigned long) * count);
+
+	dw_container_setup(handle, newflags, newtitles, count + 2, count ? 2 : 0);
+
+	free(newtitles);
+	free(newflags);
+	return TRUE;
+}
+
+/*
+ * Obtains an icon from a module (or header in GTK).
+ * Parameters:
+ *          module: Handle to module (DLL) in OS/2 and Windows.
+ *          id: A unsigned long id int the resources on OS/2 and
+ *              Windows, on GTK this is converted to a pointer
+ *              to an embedded XPM.
+ */
+unsigned long API dw_icon_load(unsigned long module, unsigned long id)
+{
+	return WinLoadPointer(HWND_DESKTOP,module,id);
+}
+
+/*
+ * Obtains an icon from a file.
+ * Parameters:
+ *       filename: Name of the file, omit extention to have
+ *                 DW pick the appropriate file extension.
+ *                 (ICO on OS/2 or Windows, XPM on Unix)
+ */
+unsigned long API dw_icon_load_from_file(char *filename)
+{
+	char *file = alloca(strlen(filename) + 5);
+
+	if(!file)
+		return 0;
+
+	strcpy(file, filename);
+
+	/* check if we can read from this file (it exists and read permission) */
+	if(access(file, 04) != 0)
+	{
+		/* Try with .bmp extention */
+		strcat(file, ".ico");
+		if(access(file, 04) != 0)
+			return 0;
+	}
+	return WinLoadFileIcon(file, FALSE);
+}
+
+/*
+ * Frees a loaded resource in OS/2 and Windows.
+ * Parameters:
+ *          handle: Handle to icon returned by dw_icon_load().
+ */
+void API dw_icon_free(unsigned long handle)
+{
+	WinDestroyPointer(handle);
+}
+
+/*
+ * Allocates memory used to populate a container.
+ * Parameters:
+ *          handle: Handle to the container window (widget).
+ *          rowcount: The number of items to be populated.
+ */
+void * API dw_container_alloc(HWND handle, int rowcount)
+{
+	WindowData *wd = (WindowData *)WinQueryWindowPtr(handle, QWP_USER);
+	ULONG *flags = wd ? wd->data : 0;
+	int z, size = 0, totalsize, count = 0;
+	PRECORDCORE temp;
+	ContainerInfo *ci;
+	void *blah = NULL;
+
+	if(!flags || rowcount < 1)
+		return NULL;
+
+	while(flags[count])
+		count++;
+
+	/* Figure out the offsets to the items in the struct */
+	for(z=0;z<count;z++)
+	{
+		if(flags[z] & DW_CFA_BITMAPORICON)
+			size += sizeof(HPOINTER);
+		else if(flags[z] & DW_CFA_STRING)
+			size += sizeof(char *);
+		else if(flags[z] & DW_CFA_ULONG)
+			size += sizeof(ULONG);
+		else if(flags[z] & DW_CFA_DATE)
+			size += sizeof(CDATE);
+		else if(flags[z] & DW_CFA_TIME)
+			size += sizeof(CTIME);
+	}
+
+	totalsize = size + sizeof(RECORDCORE);
+
+	z = 0;
+
+	if(!(blah = (void *)_dw_send_msg(handle, CM_ALLOCRECORD, MPFROMLONG(size), MPFROMLONG(rowcount), 0)))
+		return NULL;
+
+	temp = (PRECORDCORE)blah;
+
+	for(z=0;z<rowcount;z++)
+	{
+		temp->cb = totalsize;
+		temp = temp->preccNextRecord;
+	}
+
+	ci = malloc(sizeof(struct _containerinfo));
+
+	ci->count = rowcount;
+	ci->data = blah;
+	ci->handle = handle;
+
+	return (void *)ci;
+}
+
+/* Internal function that does the work for set_item and change_item */
+void _dw_container_set_item(HWND handle, PRECORDCORE temp, int column, int row, void *data)
+{
+	WindowData *blah = (WindowData *)WinQueryWindowPtr(handle, QWP_USER);
+	ULONG totalsize, size = 0, *flags = blah ? blah->data : 0;
+	int z, currentcount;
+	CNRINFO cnr;
+    void *dest;
+
+	if(!flags)
+		return;
+
+	if(!_dw_send_msg(handle, CM_QUERYCNRINFO, (MPARAM)&cnr, MPFROMSHORT(sizeof(CNRINFO)), 0))
+		return;
+
+	currentcount = cnr.cRecords;
+
+	/* Figure out the offsets to the items in the struct */
+	for(z=0;z<column;z++)
+	{
+		if(flags[z] & DW_CFA_BITMAPORICON)
+			size += sizeof(HPOINTER);
+		else if(flags[z] & DW_CFA_STRING)
+			size += sizeof(char *);
+		else if(flags[z] & DW_CFA_ULONG)
+			size += sizeof(ULONG);
+		else if(flags[z] & DW_CFA_DATE)
+			size += sizeof(CDATE);
+		else if(flags[z] & DW_CFA_TIME)
+			size += sizeof(CTIME);
+	}
+
+	totalsize = size + sizeof(RECORDCORE);
+
+	for(z=0;z<(row-currentcount);z++)
+		temp = temp->preccNextRecord;
+
+	dest = (void *)(((ULONG)temp)+((ULONG)totalsize));
+
+	if(flags[column] & DW_CFA_BITMAPORICON)
+		memcpy(dest, data, sizeof(HPOINTER));
+	else if(flags[column] & DW_CFA_STRING)
+	{
+		char **newstr = (char **)data, **str = dest;
+
+		if(*str)
+			free(*str);
+
+		if(newstr && *newstr)
+			*str = strdup(*newstr);
+		else
+			*str = NULL;
+	}
+	else if(flags[column] & DW_CFA_ULONG)
+		memcpy(dest, data, sizeof(ULONG));
+	else if(flags[column] & DW_CFA_DATE)
+		memcpy(dest, data, sizeof(CDATE));
+	else if(flags[column] & DW_CFA_TIME)
+		memcpy(dest, data, sizeof(CTIME));
+}
+
+/* Internal function that free()s any strings allocated for a container item */
+void _dw_container_free_strings(HWND handle, PRECORDCORE temp)
+{
+	WindowData *blah = (WindowData *)WinQueryWindowPtr(handle, QWP_USER);
+	ULONG totalsize, size = 0, *flags = blah ? blah->data : 0;
+	int z, count = 0;
+
+	if(!flags)
+		return;
+
+	while(flags[count])
+		count++;
+
+	/* Figure out the offsets to the items in the struct */
+	for(z=0;z<count;z++)
+	{
+		if(flags[z] & DW_CFA_BITMAPORICON)
+			size += sizeof(HPOINTER);
+		else if(flags[z] & DW_CFA_STRING)
+		{
+			char **str;
+
+			totalsize = size + sizeof(RECORDCORE);
+
+			str = (char **)(((ULONG)temp)+((ULONG)totalsize));
+
+			if(*str)
+			{
+				free(*str);
+				*str = NULL;
+			}
+			size += sizeof(char *);
+		}
+		else if(flags[z] & DW_CFA_ULONG)
+			size += sizeof(ULONG);
+		else if(flags[z] & DW_CFA_DATE)
+			size += sizeof(CDATE);
+		else if(flags[z] & DW_CFA_TIME)
+			size += sizeof(CTIME);
+	}
+}
+
+/*
+ * Sets an item in specified row and column to the given data.
+ * Parameters:
+ *          handle: Handle to the container window (widget).
+ *          pointer: Pointer to the allocated memory in dw_container_alloc().
+ *          column: Zero based column of data being set.
+ *          row: Zero based row of data being set.
+ *          data: Pointer to the data to be added.
+ */
+void API dw_container_set_item(HWND handle, void *pointer, int column, int row, void *data)
+{
+	ContainerInfo *ci = (ContainerInfo *)pointer;
+
+	if(!ci)
+		return;
+
+	_dw_container_set_item(handle, (PRECORDCORE)ci->data, column, row, data);
+}
+
+/*
+ * Changes an existing item in specified row and column to the given data.
+ * Parameters:
+ *          handle: Handle to the container window (widget).
+ *          column: Zero based column of data being set.
+ *          row: Zero based row of data being set.
+ *          data: Pointer to the data to be added.
+ */
+void API dw_container_change_item(HWND handle, int column, int row, void *data)
+{
+	PRECORDCORE pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
+	int count = 0;
+
+	while(pCore)
+	{
+		if(count == row)
+		{
+			_dw_container_set_item(handle, pCore, column, 0, data);
+			WinSendMsg(handle, CM_INVALIDATERECORD, (MPARAM)&pCore, MPFROM2SHORT(1, CMA_NOREPOSITION | CMA_TEXTCHANGED));
+			return;
+		}
+		pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
+		count++;
+	}
+}
+
+/*
+ * Sets an item in specified row and column to the given data.
+ * Parameters:
+ *          handle: Handle to the container window (widget).
+ *          pointer: Pointer to the allocated memory in dw_container_alloc().
+ *          column: Zero based column of data being set.
+ *          row: Zero based row of data being set.
+ *          data: Pointer to the data to be added.
+ */
+void API dw_filesystem_set_file(HWND handle, void *pointer, int row, char *filename, unsigned long icon)
+{
+	dw_container_set_item(handle, pointer, 0, row, (void *)&icon);
+	dw_container_set_item(handle, pointer, 1, row, (void *)&filename);
+}
+
+/*
+ * Sets an item in specified row and column to the given data.
+ * Parameters:
+ *          handle: Handle to the container window (widget).
+ *          pointer: Pointer to the allocated memory in dw_container_alloc().
+ *          column: Zero based column of data being set.
+ *          row: Zero based row of data being set.
+ *          data: Pointer to the data to be added.
+ */
+void API dw_filesystem_set_item(HWND handle, void *pointer, int column, int row, void *data)
+{
+	dw_container_set_item(handle, pointer, column + 2, row, data);
+}
+
+/*
+ * Sets the width of a column in the container.
+ * Parameters:
+ *          handle: Handle to window (widget) of container.
+ *          column: Zero based column of width being set.
+ *          width: Width of column in pixels.
+ */
+void API dw_container_set_column_width(HWND handle, int column, int width)
+{
+	handle = handle; /* keep compiler happy */
+	column = column; /* keep compiler happy */
+	width = width; /* keep compiler happy */
+}
+
+/*
+ * Sets the title of a row in the container.
+ * Parameters:
+ *          pointer: Pointer to the allocated memory in dw_container_alloc().
+ *          row: Zero based row of data being set.
+ *          title: String title of the item.
+ */
+void API dw_container_set_row_title(void *pointer, int row, char *title)
+{
+	ContainerInfo *ci = (ContainerInfo *)pointer;
+	PRECORDCORE temp;
+	int z, currentcount;
+	CNRINFO cnr;
+
+	if(!ci)
+		return;
+
+	temp = (PRECORDCORE)ci->data;
+
+	z = 0;
+
+	if(!_dw_send_msg(ci->handle, CM_QUERYCNRINFO, (MPARAM)&cnr, MPFROMSHORT(sizeof(CNRINFO)), 0))
+		return;
+
+	currentcount = cnr.cRecords;
+
+	for(z=0;z<(row-currentcount);z++)
+		temp = temp->preccNextRecord;
+
+	temp->pszIcon = title;
+	temp->pszName = title;
+	temp->pszText = title;
+}
+
+/*
+ * Sets the title of a row in the container.
+ * Parameters:
+ *          handle: Handle to the container window (widget).
+ *          pointer: Pointer to the allocated memory in dw_container_alloc().
+ *          rowcount: The number of rows to be inserted.
+ */
+void API dw_container_insert(HWND handle, void *pointer, int rowcount)
+{
+	RECORDINSERT recin;
+	ContainerInfo *ci = (ContainerInfo *)pointer;
+
+	if(!ci)
+		return;
+
+	recin.cb = sizeof(RECORDINSERT);
+	recin.pRecordOrder = (PRECORDCORE)CMA_END;
+	recin.pRecordParent = NULL;
+	recin.zOrder = CMA_TOP;
+	recin.fInvalidateRecord = TRUE;
+	recin.cRecordsInsert = rowcount;
+
+	_dw_send_msg(handle, CM_INSERTRECORD, MPFROMP(ci->data), MPFROMP(&recin), 0);
+
+	free(ci);
+}
+
+/*
+ * Removes all rows from a container.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be cleared.
+ *       redraw: TRUE to cause the container to redraw immediately.
+ */
+void API dw_container_clear(HWND handle, int redraw)
+{
+	PCNRITEM pCore;
+	int container = (int)dw_window_get_data(handle, "_dw_container");
+
+	if(hwndEmph == handle)
+		_clear_emphasis();
+
+	pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
+
+	while(pCore)
+	{
+		if(container)
+			_dw_container_free_strings(handle, (PRECORDCORE)pCore);
+		else
+		{
+			/* Free icon text */
+			if(pCore->rc.pszIcon)
+			{
+				free(pCore->rc.pszIcon);
+				pCore->rc.pszIcon = 0;
+			}
+		}
+		pCore = (PCNRITEM)pCore->rc.preccNextRecord;/*WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));*/
+	}
+	_dw_send_msg(handle, CM_REMOVERECORD, (MPARAM)0L, MPFROM2SHORT(0, (redraw ? CMA_INVALIDATE : 0) | CMA_FREE), -1);
+}
+
+/*
+ * Removes the first x rows from a container.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be deleted from.
+ *       rowcount: The number of rows to be deleted.
+ */
+void API dw_container_delete(HWND handle, int rowcount)
+{
+	RECORDCORE *last, **prc = malloc(sizeof(RECORDCORE *) * rowcount);
+	int current = 1;
+
+	prc[0] = last = (RECORDCORE *)WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
+
+	while(last && current < rowcount)
+	{
+		_dw_container_free_strings(handle, last);
+		prc[current] = last = (RECORDCORE *)WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)last, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
+		current++;
+	}
+
+	_dw_send_msg(handle, CM_REMOVERECORD, (MPARAM)prc, MPFROM2SHORT(current, CMA_INVALIDATE | CMA_FREE), -1);
+	
+	free(prc);
+}
+
+/*
+ * Scrolls container up or down.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be scrolled.
+ *       direction: DW_SCROLL_UP, DW_SCROLL_DOWN, DW_SCROLL_TOP or
+ *                  DW_SCROLL_BOTTOM. (rows is ignored for last two)
+ *       rows: The number of rows to be scrolled.
+ */
+void API dw_container_scroll(HWND handle, int direction, long rows)
+{
+	rows = rows; /* keep compiler happy */
+	switch(direction)
+	{
+	case DW_SCROLL_TOP:
+		WinSendMsg(handle, CM_SCROLLWINDOW, MPFROMSHORT(CMA_VERTICAL), MPFROMLONG(-10000000));
+        break;
+	case DW_SCROLL_BOTTOM:
+		WinSendMsg(handle, CM_SCROLLWINDOW, MPFROMSHORT(CMA_VERTICAL), MPFROMLONG(10000000));
+		break;
+	}
+}
+
+/*
+ * Starts a new query of a container.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be queried.
+ *       flags: If this parameter is DW_CRA_SELECTED it will only
+ *              return items that are currently selected.  Otherwise
+ *              it will return all records in the container.
+ */
+char * API dw_container_query_start(HWND handle, unsigned long flags)
+{
+	pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
+	if(pCore)
+	{
+		if(flags)
+		{
+			while(pCore)
+			{
+				if(pCore->flRecordAttr & flags)
+					return pCore->pszIcon;
+				pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
+			}
+		}
+		else
+			return pCore->pszIcon;
+	}
+    return NULL;
+}
+
+/*
+ * Continues an existing query of a container.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be queried.
+ *       flags: If this parameter is DW_CRA_SELECTED it will only
+ *              return items that are currently selected.  Otherwise
+ *              it will return all records in the container.
+ */
+char * API dw_container_query_next(HWND handle, unsigned long flags)
+{
+	pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
+	if(pCore)
+	{
+		if(flags)
+		{
+			while(pCore)
+			{
+				if(pCore->flRecordAttr & flags)
+					return pCore->pszIcon;
+
+				pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
+			}
+		}
+		else
+			return pCore->pszIcon;
+	}
+    return NULL;
+}
+
+/*
+ * Cursors the item with the text speficied, and scrolls to that item.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be queried.
+ *       text:  Text usually returned by dw_container_query().
+ */
+void API dw_container_cursor(HWND handle, char *text)
+{
+	RECTL viewport, item;
+
+	pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
+	while(pCore)
+	{
+		if((char *)pCore->pszIcon == text)
+		{
+			QUERYRECORDRECT qrr;
+			int scrollpixels = 0, midway;
+
+			qrr.cb = sizeof(QUERYRECORDRECT);
+			qrr.pRecord = pCore;
+			qrr.fRightSplitWindow = 0;
+			qrr.fsExtent = CMA_TEXT;
+
+			WinSendMsg(handle, CM_SETRECORDEMPHASIS, (MPARAM)pCore, MPFROM2SHORT(TRUE, CRA_CURSORED));
+			WinSendMsg(handle, CM_QUERYVIEWPORTRECT, (MPARAM)&viewport, MPFROM2SHORT(CMA_WORKSPACE, FALSE));
+			WinSendMsg(handle, CM_QUERYRECORDRECT, (MPARAM)&item, (MPARAM)&qrr);
+
+			midway = (viewport.yTop - viewport.yBottom)/2;
+			scrollpixels = viewport.yTop - (item.yTop + midway);
+
+			WinSendMsg(handle, CM_SCROLLWINDOW, MPFROMSHORT(CMA_VERTICAL),  MPFROMLONG(scrollpixels));
+			return;
+		}
+
+		pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
+	}
+}
+
+/*
+ * Deletes the item with the text speficied.
+ * Parameters:
+ *       handle: Handle to the window (widget).
+ *       text:  Text usually returned by dw_container_query().
+ */
+void API dw_container_delete_row(HWND handle, char *text)
+{
+	PRECORDCORE pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
+
+	while(pCore)
+	{
+		if((char *)pCore->pszIcon == text)
+		{
+			WinSendMsg(handle, CM_REMOVERECORD, (MPARAM)&pCore, MPFROM2SHORT(1, CMA_FREE | CMA_INVALIDATE));
+			return;
+		}
+		pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
+	}
+}
+
+/*
+ * Optimizes the column widths so that all data is visible.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be optimized.
+ */
+void API dw_container_optimize(HWND handle)
+{
+	WindowData *blah = (WindowData *)WinQueryWindowPtr(handle, QWP_USER);
+	RECTL item;
+	PRECORDCORE pCore = NULL;
+	int max = 0;
+
+	if(blah && !blah->flags)
+		return;
+
+	pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)0L, MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
+	while(pCore)
+	{
+		QUERYRECORDRECT qrr;
+		int vector;
+
+		qrr.cb = sizeof(QUERYRECORDRECT);
+		qrr.pRecord = pCore;
+		qrr.fRightSplitWindow = 0;
+		qrr.fsExtent = CMA_TEXT;
+
+		WinSendMsg(handle, CM_QUERYRECORDRECT, (MPARAM)&item, (MPARAM)&qrr);
+
+		vector = item.xRight - item.xLeft;
+
+		if(vector > max)
+			max = vector;
+
+		pCore = WinSendMsg(handle, CM_QUERYRECORD, (MPARAM)pCore, MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
+	}
+
+	if(max)
+	{
+		CNRINFO cnri;
+
+		cnri.cb = sizeof(CNRINFO);
+		cnri.xVertSplitbar  = max;
+
+		WinSendMsg(handle, CM_SETCNRINFO, MPFROMP(&cnri),  MPFROMLONG(CMA_XVERTSPLITBAR));
+	}
+}
+
+/*
+ * Inserts an icon into the taskbar.
+ * Parameters:
+ *       handle: Window handle that will handle taskbar icon messages.
+ *       icon: Icon handle to display in the taskbar.
+ *       bubbletext: Text to show when the mouse is above the icon.
+ */
+void dw_taskbar_insert(HWND handle, unsigned long icon, char *bubbletext)
+{
+	handle = handle;
+	icon = icon;
+	bubbletext = bubbletext;
+	/* TODO */
+}
+
+/*
+ * Deletes an icon from the taskbar.
+ * Parameters:
+ *       handle: Window handle that was used with dw_taskbar_insert().
+ *       icon: Icon handle that was used with dw_taskbar_insert().
+ */
+void dw_taskbar_delete(HWND handle, unsigned long icon)
+{
+	handle = handle;
+	icon = icon;
+	/* TODO */
+}
+
+/*
+ * Creates a rendering context widget (window) to be packed.
+ * Parameters:
+ *       id: An id to be used with dw_window_from_id.
+ * Returns:
+ *       A handle to the widget or NULL on failure.
+ */
+HWND API dw_render_new(unsigned long id)
+{
+	HWND hwndframe = WinCreateWindow(HWND_OBJECT,
+									 WC_FRAME,
+									 NULL,
+									 WS_VISIBLE |
+									 FS_NOBYTEALIGN,
+									 0,0,2000,1000,
+									 NULLHANDLE,
+									 HWND_TOP,
+									 id,
+									 NULL,
+									 NULL);
+	WinSubclassWindow(hwndframe, _RendProc);
+	return hwndframe;
+}
+
+/* Sets the current foreground drawing color.
+ * Parameters:
+ *       red: red value.
+ *       green: green value.
+ *       blue: blue value.
+ */
+void API dw_color_foreground_set(unsigned long value)
+{
+	_foreground = value;
+}
+
+/* Sets the current background drawing color.
+ * Parameters:
+ *       red: red value.
+ *       green: green value.
+ *       blue: blue value.
+ */
+void API dw_color_background_set(unsigned long value)
+{
+	_background = value;
+}
+
+HPS _set_hps(HPS hps)
+{
+	LONG alTable[2];
+
+	alTable[0] = DW_RED_VALUE(_foreground) << 16 | DW_GREEN_VALUE(_foreground) << 8 | DW_BLUE_VALUE(_foreground);
+	alTable[1] = DW_RED_VALUE(_background) << 16 | DW_GREEN_VALUE(_background) << 8 | DW_BLUE_VALUE(_background);
+
+	GpiCreateLogColorTable(hps,
+						   LCOL_RESET,
+						   LCOLF_CONSECRGB,
+						   16,
+						   2,
+						   alTable);
+	if(_foreground & DW_RGB_COLOR)
+		GpiSetColor(hps, 16);
+	else
+		GpiSetColor(hps, _internal_color(_foreground));
+	if(_background & DW_RGB_COLOR)
+		GpiSetBackColor(hps, 17);
+	else
+		GpiSetBackColor(hps, _internal_color(_background));
+	return hps;
+}
+
+HPS _set_colors(HWND handle)
+{
+	HPS hps = WinGetPS(handle);
+
+	_set_hps(hps);
+	return hps;
+}
+
+/* Draw a point on a window (preferably a render window).
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       x: X coordinate.
+ *       y: Y coordinate.
+ */
+void API dw_draw_point(HWND handle, HPIXMAP pixmap, int x, int y)
+{
+	HPS hps;
+	int height;
+	POINTL ptl;
+
+	if(handle)
+	{
+		hps = _set_colors(handle);
+        height = _get_height(handle);
+	}
+	else if(pixmap)
+	{
+		hps = _set_hps(pixmap->hps);
+		height = pixmap->height;
+	}
+	else
+		return;
+
+	ptl.x = x;
+	ptl.y = height - y - 1;
+
+	GpiSetPel(hps, &ptl);
+	if(!pixmap)
+		WinReleasePS(hps);
+}
+
+/* Draw a line on a window (preferably a render window).
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       x1: First X coordinate.
+ *       y1: First Y coordinate.
+ *       x2: Second X coordinate.
+ *       y2: Second Y coordinate.
+ */
+void API dw_draw_line(HWND handle, HPIXMAP pixmap, int x1, int y1, int x2, int y2)
+{
+	HPS hps;
+	int height;
+	POINTL ptl[2];
+
+	if(handle)
+	{
+		hps = _set_colors(handle);
+        height = _get_height(handle);
+	}
+	else if(pixmap)
+	{
+		hps = _set_hps(pixmap->hps);
+		height = pixmap->height;
+	}
+	else
+		return;
+
+	ptl[0].x = x1;
+	ptl[0].y = height - y1 - 1;
+	ptl[1].x = x2;
+	ptl[1].y = height - y2 - 1;
+
+	GpiMove(hps, &ptl[0]);
+	GpiLine(hps, &ptl[1]);
+	
+	if(!pixmap)
+		WinReleasePS(hps);
+}
+
+
+void _CopyFontSettings(HPS hpsSrc, HPS hpsDst)
+{
+	FONTMETRICS fm;
+	FATTRS fat;
+	SIZEF sizf;
+
+	GpiQueryFontMetrics(hpsSrc, sizeof(FONTMETRICS), &fm);
+
+    memset(&fat, 0, sizeof(fat));
+
+	fat.usRecordLength  = sizeof(FATTRS);
+	fat.lMatch          = fm.lMatch;
+	strcpy(fat.szFacename, fm.szFacename);
+
+	GpiCreateLogFont(hpsDst, 0, 1L, &fat);
+	GpiSetCharSet(hpsDst, 1L);
+
+	sizf.cx = MAKEFIXED(fm.lEmInc,0);
+	sizf.cy = MAKEFIXED(fm.lMaxBaselineExt,0);
+	GpiSetCharBox(hpsDst, &sizf );
+}
+
+/* Draw text on a window (preferably a render window).
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       x: X coordinate.
+ *       y: Y coordinate.
+ *       text: Text to be displayed.
+ */
+void API dw_draw_text(HWND handle, HPIXMAP pixmap, int x, int y, char *text)
+{
+	HPS hps;
+	int z, height;
+	RECTL rcl;
+	char fontname[128];
+	POINTL aptl[TXTBOX_COUNT];
+
+	if(handle)
+	{
+		hps = _set_colors(handle);
+		height = _get_height(handle);
+		_GetPPFont(handle, fontname);
+	}
+	else if(pixmap)
+	{
+		HPS pixmaphps = WinGetPS(pixmap->handle);
+
+		hps = _set_hps(pixmap->hps);
+		height = pixmap->height;
+		_GetPPFont(pixmap->handle, fontname);
+		_CopyFontSettings(pixmaphps, hps);
+		WinReleasePS(pixmaphps);
+	}
+	else
+		return;
+
+	for(z=0;z<strlen(fontname);z++)
+	{
+		if(fontname[z]=='.')
+			break;
+	}
+
+	GpiQueryTextBox(hps, strlen(text), text, TXTBOX_COUNT, aptl);
+
+	rcl.xLeft = x;
+	rcl.yTop = height - y;
+	rcl.yBottom = rcl.yTop - (aptl[TXTBOX_TOPLEFT].y - aptl[TXTBOX_BOTTOMLEFT].y);
+	rcl.xRight = rcl.xLeft + (aptl[TXTBOX_TOPRIGHT].x - aptl[TXTBOX_TOPLEFT].x);
+
+	if(_background == DW_CLR_DEFAULT)
+		WinDrawText(hps, -1, text, &rcl, DT_TEXTATTRS, DT_TEXTATTRS, DT_VCENTER | DT_LEFT | DT_TEXTATTRS);
+	else
+		WinDrawText(hps, -1, text, &rcl, _internal_color(_foreground), _internal_color(_background), DT_VCENTER | DT_LEFT | DT_ERASERECT);
+
+	if(!pixmap)
+		WinReleasePS(hps);
+}
+
+/* Query the width and height of a text string.
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       text: Text to be queried.
+ *       width: Pointer to a variable to be filled in with the width.
+ *       height Pointer to a variable to be filled in with the height.
+ */
+void API dw_font_text_extents(HWND handle, HPIXMAP pixmap, char *text, int *width, int *height)
+{
+	HPS hps;
+	POINTL aptl[TXTBOX_COUNT];
+
+	if(handle)
+	{
+		hps = _set_colors(handle);
+	}
+	else if(pixmap)
+	{
+		HPS pixmaphps = WinGetPS(pixmap->handle);
+
+		hps = _set_hps(pixmap->hps);
+		_CopyFontSettings(pixmaphps, hps);
+		WinReleasePS(pixmaphps);
+	}
+	else
+		return;
+
+	GpiQueryTextBox(hps, strlen(text), text, TXTBOX_COUNT, aptl);
+
+	if(width)
+		*width = aptl[TXTBOX_TOPRIGHT].x - aptl[TXTBOX_TOPLEFT].x;
+
+	if(height)
+		*height = aptl[TXTBOX_TOPLEFT].y - aptl[TXTBOX_BOTTOMLEFT].y;
+
+	if(!pixmap)
+		WinReleasePS(hps);
+}
+
+/* Draw a rectangle on a window (preferably a render window).
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       fill: Fill box TRUE or FALSE.
+ *       x: X coordinate.
+ *       y: Y coordinate.
+ *       width: Width of rectangle.
+ *       height: Height of rectangle.
+ */
+void API dw_draw_rect(HWND handle, HPIXMAP pixmap, int fill, int x, int y, int width, int height)
+{
+	HPS hps;
+	int thisheight;
+	POINTL ptl[2];
+
+	if(handle)
+	{
+		hps = _set_colors(handle);
+        thisheight = _get_height(handle);
+	}
+	else if(pixmap)
+	{
+		hps = _set_hps(pixmap->hps);
+		thisheight = pixmap->height;
+	}
+	else
+		return;
+
+	ptl[0].x = x;
+	ptl[0].y = thisheight - y - 1;
+	ptl[1].x = x + width - 1;
+	ptl[1].y = thisheight - y - height;
+
+	GpiMove(hps, &ptl[0]);
+	GpiBox(hps, fill ? DRO_OUTLINEFILL : DRO_OUTLINE, &ptl[1], 0, 0);
+	
+	if(!pixmap)
+		WinReleasePS(hps);
+}
+
+/* Call this after drawing to the screen to make sure
+ * anything you have drawn is visible.
+ */
+void API dw_flush(void)
+{
+}
+
+/*
+ * Creates a pixmap with given parameters.
+ * Parameters:
+ *       handle: Window handle the pixmap is associated with.
+ *       width: Width of the pixmap in pixels.
+ *       height: Height of the pixmap in pixels.
+ *       depth: Color depth of the pixmap.
+ * Returns:
+ *       A handle to a pixmap or NULL on failure.
+ */
+HPIXMAP API dw_pixmap_new(HWND handle, unsigned long width, unsigned long height, int depth)
+{
+	BITMAPINFOHEADER bmih;
+	SIZEL sizl = { 0, 0 };
+	HPIXMAP pixmap;
+	HDC hdc;
+	HPS hps;
+	ULONG ulFlags;
+    LONG cPlanes, cBitCount;
+
+	if (!(pixmap = calloc(1,sizeof(struct _hpixmap))))
+		return NULL;
+
+	hps = WinGetPS(handle);
+
+	hdc     = GpiQueryDevice(hps);
+	ulFlags = GpiQueryPS(hps, &sizl);
+
+	pixmap->handle = handle;
+	pixmap->hdc = DevOpenDC(dwhab, OD_MEMORY, "*", 0L, NULL, hdc);
+	pixmap->hps = GpiCreatePS (dwhab, pixmap->hdc, &sizl, ulFlags | GPIA_ASSOC);
+
+	DevQueryCaps(hdc, CAPS_COLOR_PLANES  , 1L, &cPlanes);
+	if (!depth)
+	{
+		DevQueryCaps(hdc, CAPS_COLOR_BITCOUNT, 1L, &cBitCount);
+		depth = cBitCount;
+	}
+
+	memset(&bmih, 0, sizeof(BITMAPINFOHEADER));
+	bmih.cbFix     = sizeof(BITMAPINFOHEADER);
+	bmih.cx        = (SHORT)width;
+	bmih.cy        = (SHORT)height;
+	bmih.cPlanes   = (SHORT)cPlanes;
+	bmih.cBitCount = (SHORT)depth;
+
+	pixmap->width = width; pixmap->height = height;
+
+	pixmap->hbm = GpiCreateBitmap(pixmap->hps, (PBITMAPINFOHEADER2)&bmih, 0L, NULL, NULL);
+
+	GpiSetBitmap(pixmap->hps, pixmap->hbm);
+
+	if (depth>8)
+		GpiCreateLogColorTable(pixmap->hps, LCOL_PURECOLOR, LCOLF_RGB, 0, 0, NULL );
+
+	WinReleasePS(hps);
+
+	return pixmap;
+}
+
+/*
+ * Creates a pixmap from a file.
+ * Parameters:
+ *       handle: Window handle the pixmap is associated with.
+ *       filename: Name of the file, omit extention to have
+ *                 DW pick the appropriate file extension.
+ *                 (BMP on OS/2 or Windows, XPM on Unix)
+ * Returns:
+ *       A handle to a pixmap or NULL on failure.
+ */
+HPIXMAP API dw_pixmap_new_from_file(HWND handle, char *filename)
+{
+	HPIXMAP pixmap;
+	char *file = alloca(strlen(filename) + 5);
+
+	if(!file || !(pixmap = calloc(1,sizeof(struct _hpixmap))))
+		return NULL;
+
+	strcpy(file, filename);
+
+	/* check if we can read from this file (it exists and read permission) */
+	if(access(file, 04) != 0)
+	{
+		/* Try with .bmp extention */
+		strcat(file, ".bmp");
+		if(access(file, 04) != 0)
+		{
+			free(pixmap);
+			return NULL;
+		}
+	}
+
+	/* Try to load the bitmap from file */
+	if(!_load_bitmap_file(file, handle, &pixmap->hbm, &pixmap->hdc, &pixmap->hps, &pixmap->width, &pixmap->height))
+	{
+		free(pixmap);
+		return NULL;
+	}
+
+	/* Success fill in other values */
+	pixmap->handle = handle;
+
+	return pixmap;
+}
+
+/*
+ * Creates a pixmap from internal resource graphic specified by id.
+ * Parameters:
+ *       handle: Window handle the pixmap is associated with.
+ *       id: Resource ID associated with requested pixmap.
+ * Returns:
+ *       A handle to a pixmap or NULL on failure.
+ */
+HPIXMAP API dw_pixmap_grab(HWND handle, ULONG id)
+{
+	BITMAPINFOHEADER bmih;
+	SIZEL sizl = { 0, 0 };
+	HPIXMAP pixmap;
+	HDC hdc;
+	HPS hps;
+	ULONG ulFlags;
+
+	if (!(pixmap = calloc(1,sizeof(struct _hpixmap))))
+		return NULL;
+
+	hps = WinGetPS(handle);
+
+	hdc     = GpiQueryDevice(hps);
+	ulFlags = GpiQueryPS(hps, &sizl);
+
+	pixmap->hdc = DevOpenDC(dwhab, OD_MEMORY, "*", 0L, NULL, hdc);
+	pixmap->hps = GpiCreatePS (dwhab, pixmap->hdc, &sizl, ulFlags | GPIA_ASSOC);
+
+	pixmap->hbm = GpiLoadBitmap(pixmap->hps, NULLHANDLE, id, 0, 0);
+
+	GpiQueryBitmapParameters(pixmap->hbm, &bmih);
+
+	GpiSetBitmap(pixmap->hps, pixmap->hbm);
+
+	pixmap->width = bmih.cx; pixmap->height = bmih.cy;
+
+	WinReleasePS(hps);
+
+	return pixmap;
+}
+
+/*
+ * Destroys an allocated pixmap.
+ * Parameters:
+ *       pixmap: Handle to a pixmap returned by
+ *               dw_pixmap_new..
+ */
+void API dw_pixmap_destroy(HPIXMAP pixmap)
+{
+	GpiSetBitmap(pixmap->hps, NULLHANDLE);
+	GpiDeleteBitmap(pixmap->hbm);
+	GpiAssociate(pixmap->hps, NULLHANDLE);
+	GpiDestroyPS(pixmap->hps);
+	DevCloseDC(pixmap->hdc);
+	free(pixmap);
+}
+
+/*
+ * Copies from one item to another.
+ * Parameters:
+ *       dest: Destination window handle.
+ *       destp: Destination pixmap. (choose only one).
+ *       xdest: X coordinate of destination.
+ *       ydest: Y coordinate of destination.
+ *       width: Width of area to copy.
+ *       height: Height of area to copy.
+ *       src: Source window handle.
+ *       srcp: Source pixmap. (choose only one).
+ *       xsrc: X coordinate of source.
+ *       ysrc: Y coordinate of source.
+ */
+void API dw_pixmap_bitblt(HWND dest, HPIXMAP destp, int xdest, int ydest, int width, int height, HWND src, HPIXMAP srcp, int xsrc, int ysrc)
+{
+	HPS hpsdest;
+	HPS hpssrc;
+	POINTL ptl[4];
+    int destheight, srcheight;
+
+	if(dest)
+	{
+		hpsdest = WinGetPS(dest);
+		destheight = _get_height(dest);
+	}
+	else if(destp)
+	{
+		hpsdest = destp->hps;
+		destheight = destp->height;
+	}
+	else
+		return;
+
+	if(src)
+	{
+		hpssrc = WinGetPS(src);
+		srcheight = _get_height(src);
+	}
+	else if(srcp)
+	{
+		hpssrc = srcp->hps;
+		srcheight = srcp->height;
+	}
+	else
+	{
+		if(!destp)
+			WinReleasePS(hpsdest);
+		return;
+	}
+
+	ptl[0].x = xdest;
+	ptl[0].y = (destheight - ydest) - height;
+	ptl[1].x = ptl[0].x + width;
+	ptl[1].y = destheight - ydest;
+	ptl[2].x = xsrc;
+	ptl[2].y = srcheight - (ysrc + height);
+	ptl[3].x = ptl[2].x + width;
+	ptl[3].y = ptl[2].y + height;
+
+	GpiBitBlt(hpsdest, hpssrc, 4, ptl, ROP_SRCCOPY, BBO_IGNORE);
+
+	if(!destp)
+		WinReleasePS(hpsdest);
+	if(!srcp)
+		WinReleasePS(hpssrc);
+}
+
+/*
+ * Emits a beep.
+ * Parameters:
+ *       freq: Frequency.
+ *       dur: Duration.
+ */
+void API dw_beep(int freq, int dur)
+{
+	DosBeep(freq, dur);
+}
+
+/* Open a shared library and return a handle.
+ * Parameters:
+ *         name: Base name of the shared library.
+ *         handle: Pointer to a module handle,
+ *                 will be filled in with the handle.
+ */
+int API dw_module_load(char *name, HMOD *handle)
+{
+	char objnamebuf[300] = "";
+
+	return DosLoadModule(objnamebuf, sizeof(objnamebuf), name, handle);
+}
+
+/* Queries the address of a symbol within open handle.
+ * Parameters:
+ *         handle: Module handle returned by dw_module_load()
+ *         name: Name of the symbol you want the address of.
+ *         func: A pointer to a function pointer, to obtain
+ *               the address.
+ */
+int API dw_module_symbol(HMOD handle, char *name, void**func)
+{
+	return DosQueryProcAddr(handle, 0, name, (PFN*)func);
+}
+
+/* Frees the shared library previously opened.
+ * Parameters:
+ *         handle: Module handle returned by dw_module_load()
+ */
+int API dw_module_close(HMOD handle)
+{
+	DosFreeModule(handle);
+	return 0;
+}
+
+/*
+ * Returns the handle to an unnamed mutex semaphore.
+ */
+HMTX API dw_mutex_new(void)
+{
+	HMTX mutex;
+
+	DosCreateMutexSem(NULL, &mutex, 0, FALSE);
+	return mutex;
+}
+
+/*
+ * Closes a semaphore created by dw_mutex_new().
+ * Parameters:
+ *       mutex: The handle to the mutex returned by dw_mutex_new().
+ */
+void API dw_mutex_close(HMTX mutex)
+{
+	DosCloseMutexSem(mutex);
+}
+
+/*
+ * Tries to gain access to the semaphore, if it can't it blocks.
+ * If we are in a callback we must keep the message loop running
+ * while blocking.
+ * Parameters:
+ *       mutex: The handle to the mutex returned by dw_mutex_new().
+ */
+void API dw_mutex_lock(HMTX mutex)
+{
+	if(_dwtid == dw_thread_id())
+	{
+		int rc = DosRequestMutexSem(mutex, SEM_IMMEDIATE_RETURN);
+
+		while(rc == ERROR_TIMEOUT)
+		{
+			dw_main_sleep(10);
+			rc = DosRequestMutexSem(mutex, SEM_IMMEDIATE_RETURN);
+		}
+	}
+    else
+		DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT);
+}
+
+/*
+ * Reliquishes the access to the semaphore.
+ * Parameters:
+ *       mutex: The handle to the mutex returned by dw_mutex_new().
+ */
+void API dw_mutex_unlock(HMTX mutex)
+{
+	DosReleaseMutexSem(mutex);
+}
+
+/*
+ * Returns the handle to an unnamed event semaphore.
+ */
+HEV API dw_event_new(void)
+{
+	HEV blah;
+
+	if(DosCreateEventSem (NULL, &blah, 0L, FALSE))
+		return 0;
+
+	return blah;
+}
+
+/*
+ * Resets a semaphore created by dw_event_new().
+ * Parameters:
+ *       eve: The handle to the event returned by dw_event_new().
+ */
+int API dw_event_reset(HEV eve)
+{
+	ULONG count;
+
+	if(DosResetEventSem(eve, &count))
+		return FALSE;
+	return TRUE;
+}
+
+/*
+ * Posts a semaphore created by dw_event_new(). Causing all threads
+ * waiting on this event in dw_event_wait to continue.
+ * Parameters:
+ *       eve: The handle to the event returned by dw_event_new().
+ */
+int API dw_event_post(HEV eve)
+{
+	if(DosPostEventSem(eve))
+		return FALSE;
+	return TRUE;
+}
+
+
+/*
+ * Waits on a semaphore created by dw_event_new(), until the
+ * event gets posted or until the timeout expires.
+ * Parameters:
+ *       eve: The handle to the event returned by dw_event_new().
+ */
+int API dw_event_wait(HEV eve, unsigned long timeout)
+{
+	int rc = DosWaitEventSem(eve, timeout);
+	if(!rc)
+		return 1;
+	if(rc == ERROR_TIMEOUT)
+		return -1;
+	return 0;
+}
+
+/*
+ * Closes a semaphore created by dw_event_new().
+ * Parameters:
+ *       eve: The handle to the event returned by dw_event_new().
+ */
+int API dw_event_close(HEV *eve)
+{
+	if(!eve || ~DosCloseEventSem(*eve))
+		return FALSE;
+	return TRUE;
+}
+
+/*
+ * Encapsulate the message queues on OS/2.
+ */
+void _dwthreadstart(void *data)
+{
+	HAB thishab = WinInitialize(0);
+	HMQ thishmq = WinCreateMsgQueue(dwhab, 0);
+	void (*threadfunc)(void *) = NULL;
+	void **tmp = (void **)data;
+
+	threadfunc = (void (*)(void *))tmp[0];
+	threadfunc(tmp[1]);
+
+	free(tmp);
+
+	WinDestroyMsgQueue(thishmq);
+	WinTerminate(thishab);
+}
+
+/*
+ * Creates a new thread with a starting point of func.
+ * Parameters:
+ *       func: Function which will be run in the new thread.
+ *       data: Parameter(s) passed to the function.
+ *       stack: Stack size of new thread (OS/2 and Windows only).
+ */
+DWTID API dw_thread_new(void *func, void *data, int stack)
+{
+	void **tmp = malloc(sizeof(void *) * 2);
+
+	tmp[0] = func;
+	tmp[1] = data;
+
+	return (DWTID)_beginthread((void (*)(void *))_dwthreadstart, NULL, stack, (void *)tmp);
+}
+
+/*
+ * Ends execution of current thread immediately.
+ */
+void API dw_thread_end(void)
+{
+	_endthread();
+}
+
+/*
+ * Returns the current thread's ID.
+ */
+DWTID API dw_thread_id(void)
+{
+	return (DWTID)_threadid;
+}
+
+/*
+ * Cleanly terminates a DW session, should be signal handler safe.
+ * Parameters:
+ *       exitcode: Exit code reported to the operating system.
+ */
+void API dw_exit(int exitcode)
+{
+	/* Destroy the menu message window */
+	dw_window_destroy(hwndApp);
+
+	/* In case we are in a signal handler, don't
+	 * try to free memory that could possibly be
+	 * free()'d by the runtime already.
+	 */
+	Root = NULL;
+
+	exit(exitcode);
+}
+
+/*
+ * Creates a splitbar window (widget) with given parameters.
+ * Parameters:
+ *       type: Value can be DW_VERT or DW_HORZ.
+ *       topleft: Handle to the window to be top or left.
+ *       bottomright:  Handle to the window to be bottom or right.
+ * Returns:
+ *       A handle to a splitbar window or NULL on failure.
+ */
+HWND API dw_splitbar_new(int type, HWND topleft, HWND bottomright, unsigned long id)
+{
+	HWND tmp = WinCreateWindow(HWND_OBJECT,
+							   SplitbarClassName,
+							   NULL,
+							   WS_VISIBLE | WS_CLIPCHILDREN,
+							   0,0,2000,1000,
+							   NULLHANDLE,
+							   HWND_TOP,
+							   id,
+							   NULL,
+							   NULL);
+	if(tmp)
+	{
+		HWND tmpbox = dw_box_new(DW_VERT, 0);
+        float *percent = malloc(sizeof(float));
+
+		dw_box_pack_start(tmpbox, topleft, 1, 1, TRUE, TRUE, 0);
+		WinSetParent(tmpbox, tmp, FALSE);
+		dw_window_set_data(tmp, "_dw_topleft", (void *)tmpbox);
+
+		tmpbox = dw_box_new(DW_VERT, 0);
+		dw_box_pack_start(tmpbox, bottomright, 1, 1, TRUE, TRUE, 0);
+		WinSetParent(tmpbox, tmp, FALSE);
+		*percent = 50.0;
+		dw_window_set_data(tmp, "_dw_bottomright", (void *)tmpbox);
+		dw_window_set_data(tmp, "_dw_percent", (void *)percent);
+		dw_window_set_data(tmp, "_dw_type", (void *)type);
+	}
+	return tmp;
+}
+
+/*
+ * Sets the position of a splitbar (pecentage).
+ * Parameters:
+ *       handle: The handle to the splitbar returned by dw_splitbar_new().
+ */
+void API dw_splitbar_set(HWND handle, float percent)
+{
+	float *mypercent = (float *)dw_window_get_data(handle, "_dw_percent");
+	int type = (int)dw_window_get_data(handle, "_dw_type");
+    unsigned long width, height;
+
+	if(mypercent)
+		*mypercent = percent;
+
+	dw_window_get_pos_size(handle, NULL, NULL, &width, &height);
+
+	_handle_splitbar_resize(handle, percent, type, width, height);
+}
+
+/*
+ * Gets the position of a splitbar (pecentage).
+ * Parameters:
+ *       handle: The handle to the splitbar returned by dw_splitbar_new().
+ */
+float API dw_splitbar_get(HWND handle)
+{
+	float *percent = (float *)dw_window_get_data(handle, "_dw_percent");
+
+	if(percent)
+		return *percent;
+	return 0.0;
+}
+
+/*
+ * Pack windows (widgets) into a box from the start (or top).
+ * Parameters:
+ *       box: Window handle of the box to be packed into.
+ *       item: Window handle of the item to be back.
+ *       width: Width in pixels of the item or -1 to be self determined.
+ *       height: Height in pixels of the item or -1 to be self determined.
+ *       hsize: TRUE if the window (widget) should expand horizontally to fill space given.
+ *       vsize: TRUE if the window (widget) should expand vertically to fill space given.
+ *       pad: Number of pixels of padding around the item.
+ */
+void API dw_box_pack_start(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad)
+{
+	Box *thisbox;
+	char *funcname = "dw_box_pack_start()";
+
+		/*
+		 * If you try and pack an item into itself VERY bad things can happen; like at least an
+		 * infinite loop on GTK! Lets be safe!
+		 */
+	if(box == item)
+	{
+		dw_messagebox(funcname, DW_MB_OK|DW_MB_ERROR, "Danger! Danger! Will Robinson; box and item are the same!",box,item);
+		return;
+	}
+
+	if(WinWindowFromID(box, FID_CLIENT))
+	{
+		box = WinWindowFromID(box, FID_CLIENT);
+		thisbox = WinQueryWindowPtr(box, QWP_USER);
+		hsize = TRUE;
+		vsize = TRUE;
+	}
+	else
+		thisbox = WinQueryWindowPtr(box, QWP_USER);
+	if(thisbox)
+	{
+		if(thisbox->type == DW_HORZ)
+			_dw_box_pack_end(box, item, width, height, hsize, vsize, pad, funcname);
+		else
+			_dw_box_pack_start(box, item, width, height, hsize, vsize, pad, funcname);
+	}
+}
+
+void _dw_box_pack_start(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad, char *functionname)
+{
+	Box *thisbox = WinQueryWindowPtr(box, QWP_USER);
+
+	if(thisbox)
+	{
+		int z;
+		Item *tmpitem, *thisitem = thisbox->items;
+		char tmpbuf[100];
+		HWND frame = (HWND)dw_window_get_data(item, "_dw_combo_box");
+
+		tmpitem = malloc(sizeof(Item)*(thisbox->count+1));
+
+		for(z=0;z<thisbox->count;z++)
+		{
+			tmpitem[z+1] = thisitem[z];
+		}
+
+		WinQueryClassName(item, 99, tmpbuf);
+
+		if(vsize && !height)
+			height = 1;
+		if(hsize && !width)
+			width = 1;
+
+		if(strncmp(tmpbuf, "#1", 3)==0)
+			tmpitem[0].type = TYPEBOX;
+		else
+		{
+			if ( width == 0 && hsize == FALSE )
+				dw_messagebox(functionname, DW_MB_OK|DW_MB_ERROR, "Width and expand Horizonal both unset for box: %x item: %x",box,item);
+			if ( height == 0 && vsize == FALSE )
+				dw_messagebox(functionname, DW_MB_OK|DW_MB_ERROR, "Height and expand Vertical both unset for box: %x item: %x",box,item);
+
+			tmpitem[0].type = TYPEITEM;
+		}
+
+		tmpitem[0].hwnd = item;
+		tmpitem[0].origwidth = tmpitem[0].width = width;
+		tmpitem[0].origheight = tmpitem[0].height = height;
+		tmpitem[0].pad = pad;
+		if(hsize)
+			tmpitem[0].hsize = SIZEEXPAND;
+		else
+			tmpitem[0].hsize = SIZESTATIC;
+
+		if(vsize)
+			tmpitem[0].vsize = SIZEEXPAND;
+		else
+			tmpitem[0].vsize = SIZESTATIC;
+
+		thisbox->items = tmpitem;
+
+		if(thisbox->count)
+			free(thisitem);
+
+		thisbox->count++;
+
+		WinQueryClassName(item, 99, tmpbuf);
+		/* Don't set the ownership if it's an entryfield or spinbutton */
+		if(strncmp(tmpbuf, "#6", 3)!=0 && strncmp(tmpbuf, "#32", 4)!=0 && strncmp(tmpbuf, "#2", 3)!=0)
+			WinSetOwner(item, box);
+		WinSetParent(frame ? frame : item, box, FALSE);
+	}
+}
+
+/* The following two functions graciously contributed by Peter Nielsen. */
+static ULONG _ParseBuildLevel (char* pchBuffer, ULONG ulSize) {
+	char* pchStart = pchBuffer;
+	char* pchEnd = pchStart + ulSize - 2;
+
+	while (pchEnd >= pchStart)
+	{
+		if ((pchEnd[0] == '#') && (pchEnd[1] == '@'))
+		{
+			*pchEnd-- = '\0';
+			while (pchEnd >= pchStart)
+			{
+				if ((pchEnd[0] == '@') && (pchEnd[1] == '#'))
+				{
+					ULONG ulMajor = 0;
+					ULONG ulMinor = 0;
+
+					char* pch = pchEnd + 2;
+					while (!isdigit ((int)*pch) && *pch)
+						pch++;
+
+					while (isdigit ((int)*pch))
+						ulMajor = ulMajor * 10 + *pch++ - '0';
+
+					if (*pch == '.')
+					{
+						while (isdigit ((int)*++pch))
+							ulMinor = ulMinor * 10 + *pch - '0';
+					}
+					return ((ulMajor << 16) | ulMinor);
+				}
+				pchEnd--;
+			}
+		}
+		pchEnd--;
+	}
+	return (0);
+}
+
+ULONG _GetSystemBuildLevel(void) {
+	/* The build level info is normally available in the end of the OS2KRNL file. However, this is not the case in some beta versions of OS/2.
+	 * We first try to find the info in the 256 last bytes of the file. If that fails, we load the entire file and search it completely.
+	 */
+	ULONG ulBootDrive = 0;
+	ULONG ulBuild = 0;
+	if (DosQuerySysInfo (QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &ulBootDrive, sizeof (ulBootDrive)) == NO_ERROR)
+	{
+		char achFileName[11] = "C:\\OS2KRNL";
+		HFILE hfile;
+		ULONG ulResult;
+
+        achFileName[0] = (char)('A'+ulBootDrive-1);
+
+		if (DosOpen (achFileName, &hfile, &ulResult, 0, 0, OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS, OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_SEQUENTIAL | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, NULL) == NO_ERROR)
+		{
+			ULONG ulFileSize = 0;
+			if (DosSetFilePtr (hfile, 0, FILE_END, &ulFileSize) == NO_ERROR)
+			{
+				const ULONG ulFirstTry = min (256, ulFileSize);
+				if (DosSetFilePtr (hfile, -(LONG)ulFirstTry, FILE_END, &ulResult) == NO_ERROR)
+				{
+					char *pchBuffer = malloc(ulFirstTry);
+					if (DosRead (hfile, pchBuffer, ulFirstTry, &ulResult) == NO_ERROR)
+					{
+						ulBuild = _ParseBuildLevel (pchBuffer, ulFirstTry);
+						if (ulBuild == 0)
+						{
+							if (DosSetFilePtr (hfile, 0, FILE_BEGIN, &ulResult) == NO_ERROR)
+							{
+								free(pchBuffer);
+								pchBuffer = malloc(ulFileSize);
+
+								if (DosRead (hfile, pchBuffer, ulFileSize, &ulResult) == NO_ERROR)
+									ulBuild = _ParseBuildLevel (pchBuffer, ulFileSize);
+							}
+						}
+					}
+					free(pchBuffer);
+				}
+			}
+			DosClose (hfile);
+		}
+	}
+	return (ulBuild);
+}
+
+/*
+ * Sets the default focus item for a window/dialog.
+ * Parameters:
+ *         window: Toplevel window or dialog.
+ *         defaultitem: Handle to the dialog item to be default.
+ */
+void API dw_window_default(HWND window, HWND defaultitem)
+{
+	Box *thisbox = NULL;
+	HWND box;
+
+	box = WinWindowFromID(window, FID_CLIENT);
+	if(box)
+		thisbox = WinQueryWindowPtr(box, QWP_USER);
+
+	if(thisbox)
+		thisbox->defaultitem = defaultitem;
+}
+
+/*
+ * Sets window to click the default dialog item when an ENTER is pressed.
+ * Parameters:
+ *         window: Window (widget) to look for the ENTER press.
+ *         next: Window (widget) to move to next (or click)
+ */
+void API dw_window_click_default(HWND window, HWND next)
+{
+	WindowData *blah = (WindowData *)WinQueryWindowPtr(window, QWP_USER);
+
+	if(blah)
+		blah->clickdefault = next;
+}
+
+/*
+ * Returns some information about the current operating environment.
+ * Parameters:
+ *       env: Pointer to a DWEnv struct.
+ */
+void API dw_environment_query(DWEnv *env)
+{
+	ULONG Build;
+
+	if(!env)
+		return;
+
+	/* The default is OS/2 2.0 */
+	strcpy(env->osName,"OS/2");
+	env->MajorVersion = 2;
+	env->MinorVersion = 0;
+
+	Build = _GetSystemBuildLevel();
+	env->MinorBuild =  Build & 0xFFFF;
+	env->MajorBuild =  Build >> 16;
+
+	if (aulBuffer[0] == 20)
+	{
+		int i = (unsigned int)aulBuffer[1];
+		if (i > 20)
+		{
+			strcpy(env->osName,"Warp");
+			env->MajorVersion = (int)i/10;
+			env->MinorVersion = i-(((int)i/10)*10);
+		}
+		else if (i == 10)
+			env->MinorVersion = 1;
+	}
+	strcpy(env->buildDate, __DATE__);
+	strcpy(env->buildTime, __TIME__);
+	env->DWMajorVersion = DW_MAJOR_VERSION;
+	env->DWMinorVersion = DW_MINOR_VERSION;
+	env->DWSubVersion = DW_SUB_VERSION;
+}
+
+/* The next few functions are support functions for the OS/2 folder browser */
+void _populate_directory(HWND tree, HTREEITEM parent, char *path)
+{
+	FILEFINDBUF3 ffbuf;
+	HTREEITEM item;
+	ULONG count = 1;
+	HDIR hdir = HDIR_CREATE;
+
+	if(DosFindFirst(path, &hdir, FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_ARCHIVED | MUST_HAVE_DIRECTORY,
+					&ffbuf, sizeof(FILEFINDBUF3), &count, FIL_STANDARD) == NO_ERROR)
+	{
+		while(DosFindNext(hdir, &ffbuf, sizeof(FILEFINDBUF3), &count) == NO_ERROR)
+		{
+			if(strcmp(ffbuf.achName, ".") && strcmp(ffbuf.achName, ".."))
+			{
+				int len = strlen(path);
+				char *folder = malloc(len + ffbuf.cchName + 2);
+				HTREEITEM tempitem;
+
+				strcpy(folder, path);
+				strcpy(&folder[len-1], ffbuf.achName);
+
+				item = dw_tree_insert(tree, ffbuf.achName, WinLoadFileIcon(folder, TRUE), parent, (void *)parent);
+				tempitem = dw_tree_insert(tree, "", 0, item, 0);
+				dw_tree_set_data(tree, item, (void *)tempitem);
+			}
+		}
+		DosFindClose(hdir);
+	}
+}
+
+void _populate_tree_thread(void *data)
+{
+	HWND window = (HWND)data, tree = (HWND)dw_window_get_data(window, "_dw_tree");
+	HMTX mtx = (HMTX)dw_window_get_data(window, "_dw_mutex");
+	int drive;
+	HTREEITEM items[26];
+	FSINFO  volinfo;
+
+	DosError(FERR_DISABLEHARDERR);
+
+	dw_mutex_lock(mtx);
+	for(drive=0;drive<26;drive++)
+	{
+		if(DosQueryFSInfo(drive+1, FSIL_VOLSER,(PVOID)&volinfo, sizeof(FSINFO)) == NO_ERROR)
+		{
+			char folder[5] = "C:\\", name[9] = "Drive C:";
+			HTREEITEM tempitem;
+
+			folder[0] = name[6] = 'A' + drive;
+
+			items[drive] = dw_tree_insert(tree, name, WinLoadFileIcon(folder, TRUE), NULL, 0);
+			tempitem = dw_tree_insert(tree, "", 0, items[drive], 0);
+			dw_tree_set_data(tree, items[drive], (void *)tempitem);
+		}
+		else
+			items[drive] = 0;
+	}
+	dw_mutex_unlock(mtx);
+
+	DosError(FERR_ENABLEHARDERR);
+}
+
+int DWSIGNAL _dw_ok_func(HWND window, void *data)
+{
+	DWDialog *dwwait = (DWDialog *)data;
+	HMTX mtx = (HMTX)dw_window_get_data((HWND)dwwait->data, "_dw_mutex");
+	void *treedata;
+
+	window = window;
+	if(!dwwait)
+		return FALSE;
+
+	dw_mutex_lock(mtx);
+	treedata = dw_window_get_data((HWND)dwwait->data, "_dw_tree_selected");
+	dw_mutex_close(mtx);
+	dw_window_destroy((HWND)dwwait->data);
+	dw_dialog_dismiss((DWDialog *)data, treedata);
+	return FALSE;
+}
+
+int DWSIGNAL _dw_cancel_func(HWND window, void *data)
+{
+	DWDialog *dwwait = (DWDialog *)data;
+	HMTX mtx = (HMTX)dw_window_get_data((HWND)dwwait->data, "_dw_mutex");
+
+	window = window;
+	if(!dwwait)
+		return FALSE;
+
+	dw_mutex_lock(mtx);
+	dw_mutex_close(mtx);
+	dw_window_destroy((HWND)dwwait->data);
+	dw_dialog_dismiss((DWDialog *)data, NULL);
+	return FALSE;
+}
+
+char *_tree_folder(HWND tree, HTREEITEM item)
+{
+	char *folder=strdup("");
+	HTREEITEM parent = item;
+
+	while(parent)
+	{
+		char *temp, *text = dw_tree_get_title(tree, parent);
+
+		if(text)
+		{
+			if(strncmp(text, "Drive ", 6) == 0)
+				text = &text[6];
+
+			temp = malloc(strlen(text) + strlen(folder) + 3);
+			strcpy(temp, text);
+			strcat(temp, "\\");
+			strcat(temp, folder);
+			free(folder);
+			folder = temp;
+		}
+		parent = dw_tree_get_parent(tree, parent);
+	}
+	return folder;
+}
+
+int DWSIGNAL _item_select(HWND window, HTREEITEM item, char *text, void *data, void *itemdata)
+{
+	DWDialog *dwwait = (DWDialog *)data;
+	char *treedata = (char *)dw_window_get_data((HWND)dwwait->data, "_dw_tree_selected");
+
+	text = text; itemdata = itemdata;
+	if(treedata)
+		free(treedata);
+
+	treedata = _tree_folder(window, item);
+	dw_window_set_data((HWND)dwwait->data, "_dw_tree_selected", (void *)treedata);
+
+	return FALSE;
+}
+
+int DWSIGNAL _tree_expand(HWND window, HTREEITEM item, void *data)
+{
+	HTREEITEM tempitem = (HTREEITEM)dw_tree_get_data(window, item);
+
+	data = data;
+	if(tempitem)
+	{
+		char *folder = _tree_folder(window, item);
+
+		dw_tree_set_data(window, item, 0);
+		dw_tree_delete(window, tempitem);
+
+		if(*folder)
+		{
+			strcat(folder, "*");
+			_populate_directory(window, item, folder);
+		}
+		free(folder);
+	}
+
+	return FALSE;
+}
+
+/*
+ * Opens a file dialog and queries user selection.
+ * Parameters:
+ *       title: Title bar text for dialog.
+ *       defpath: The default path of the open dialog.
+ *       ext: Default file extention.
+ *       flags: DW_FILE_OPEN or DW_FILE_SAVE.
+ * Returns:
+ *       NULL on error. A malloced buffer containing
+ *       the file path on success.
+ *       
+ */
+char * API dw_file_browse(char *title, char *defpath, char *ext, int flags)
+{
+	if(flags == DW_DIRECTORY_OPEN)
+	{
+		HWND window, hbox, vbox, tree, button;
+		DWDialog *dwwait;
+		HMTX mtx = dw_mutex_new();
+
+		window = dw_window_new( HWND_DESKTOP, title, FCF_SHELLPOSITION | FCF_TITLEBAR | FCF_SIZEBORDER | FCF_MINMAX);
+
+		vbox = dw_box_new(DW_VERT, 5);
+
+		dw_box_pack_start(window, vbox, 0, 0, TRUE, TRUE, 0);
+
+		tree = dw_tree_new(60);
+
+		dw_box_pack_start(vbox, tree, 1, 1, TRUE, TRUE, 0);
+		dw_window_set_data(window, "_dw_mutex", (void *)mtx);
+		dw_window_set_data(window, "_dw_tree", (void *)tree);
+
+		hbox = dw_box_new(DW_HORZ, 0);
+
+		dw_box_pack_start(vbox, hbox, 0, 0, TRUE, FALSE, 0);
+
+		dwwait = dw_dialog_new((void *)window);
+
+		dw_signal_connect(tree, DW_SIGNAL_ITEM_SELECT, DW_SIGNAL_FUNC(_item_select), (void *)dwwait);
+		dw_signal_connect(tree, DW_SIGNAL_TREE_EXPAND, DW_SIGNAL_FUNC(_tree_expand), (void *)dwwait);
+
+		button = dw_button_new("Ok", 1001L);
+		dw_box_pack_start(hbox, button, 50, 30, TRUE, FALSE, 3);
+		dw_signal_connect(button, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_ok_func), (void *)dwwait);
+
+		button = dw_button_new("Cancel", 1002L);
+		dw_box_pack_start(hbox, button, 50, 30, TRUE, FALSE, 3);
+		dw_signal_connect(button, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(_dw_cancel_func), (void *)dwwait);
+
+		dw_window_set_usize(window, 225, 300);
+		dw_window_show(window);
+
+		dw_thread_new((void *)_populate_tree_thread, (void *)window, 0xff);
+		return (char *)dw_dialog_wait(dwwait);
+	}
+	else
+	{
+		FILEDLG fild;
+		HWND hwndFile;
+		int len;
+
+		if(defpath)
+			strcpy(fild.szFullFile, defpath);
+		else
+			strcpy(fild.szFullFile, "");
+
+		len = strlen(fild.szFullFile);
+
+		if(len)
+		{
+			if(fild.szFullFile[len-1] != '\\')
+				strcat(fild.szFullFile, "\\");
+		}
+		strcat(fild.szFullFile, "*");
+
+		if(ext)
+		{
+			strcat(fild.szFullFile, ".");
+			strcat(fild.szFullFile, ext);
+		}
+
+		memset(&fild, 0, sizeof(FILEDLG));
+		fild.cbSize = sizeof(FILEDLG);
+		fild.fl = FDS_CENTER | FDS_OPEN_DIALOG;
+		fild.pszTitle = title;
+		fild.pszOKButton = ((flags & DW_FILE_SAVE) ? "Save" : "Open");
+		fild.pfnDlgProc = (PFNWP)WinDefFileDlgProc;
+
+		hwndFile = WinFileDlg(HWND_DESKTOP, HWND_DESKTOP, &fild);
+		if(hwndFile)
+		{
+			switch(fild.lReturn)
+			{
+			case DID_OK:
+				return strdup(fild.szFullFile);
+			case DID_CANCEL:
+				return NULL;
+			}
+		}
+	}
+	return NULL;
+}
+
+/* Internal function to set drive and directory */
+int _SetPath(char *path)
+{
+#ifndef __WATCOMC__
+	if(strlen(path)	> 2)
+	{
+		if(path[1] == ':')
+		{
+			char drive = toupper(path[0]);
+			_chdrive((drive - 'A')+1);
+		}
+	}
+#endif
+	return chdir(path);
+}
+
+/*
+ * Execute and external program in a seperate session.
+ * Parameters:
+ *       program: Program name with optional path.
+ *       type: Either DW_EXEC_CON or DW_EXEC_GUI.
+ *       params: An array of pointers to string arguements.
+ * Returns:
+ *       -1 on error.
+ */
+int API dw_exec(char *program, int type, char **params)
+{
+	type = type; /* keep compiler happy */
+	return spawnvp(P_NOWAIT, program, (const char **)params);
+}
+
+/*
+ * Loads a web browser pointed at the given URL.
+ * Parameters:
+ *       url: Uniform resource locator.
+ */
+int API dw_browse(char *url)
+{
+	char *execargs[3], browser[1024], *olddir, *newurl = NULL;
+	int len, ret;
+
+	olddir = _getcwd(NULL, 1024);
+
+	PrfQueryProfileString(HINI_USERPROFILE, "WPURLDEFAULTSETTINGS",
+						  "DefaultWorkingDir", NULL, browser, 1024);
+
+	if(browser[0])
+		_SetPath(browser);
+
+	PrfQueryProfileString(HINI_USERPROFILE, "WPURLDEFAULTSETTINGS",
+						  "DefaultBrowserExe", NULL, browser, 1024);
+
+	len = strlen(browser) - strlen("explore.exe");
+
+	execargs[0] = browser;
+	execargs[1] = url;
+	execargs[2] = NULL;
+
+	/* Special case for Web Explorer, it requires file:/// instead
+	 * of file:// so I am handling it here.
+	 */
+	if(len > 0)
+	{
+		if(stricmp(&browser[len], "explore.exe") == 0 && stricmp(url, "file://") == 0)
+		{
+			int newlen, z;
+			newurl = malloc(strlen(url) + 2);
+			sprintf(newurl, "file:///%s", &url[7]);
+			newlen = strlen(newurl);
+			for(z=8;z<(newlen-8);z++)
+			{
+				if(newurl[z] == '|')
+					newurl[z] = ':';
+				if(newurl[z] == '/')
+					newurl[z] = '\\';
+			}
+			execargs[1] = newurl;
+		}
+	}
+
+	ret = dw_exec(browser, DW_EXEC_GUI, execargs);
+
+	if(olddir)
+	{
+		_SetPath(olddir);
+		free(olddir);
+	}
+	if(newurl)
+		free(newurl);
+	return ret;
+}
+
+/*
+ * Returns a pointer to a static buffer which containes the
+ * current user directory.  Or the root directory (C:\ on
+ * OS/2 and Windows).
+ */
+char * API dw_user_dir(void)
+{
+	static char _user_dir[1024] = "";
+
+	if(!_user_dir[0])
+	{
+		char *home = getenv("HOME");
+
+		if(home)
+			strcpy(_user_dir, home);
+		else
+			strcpy(_user_dir, "C:\\");
+	}
+	return _user_dir;
+}
+
+/*
+ * Call a function from the window (widget)'s context.
+ * Parameters:
+ *       handle: Window handle of the widget.
+ *       function: Function pointer to be called.
+ *       data: Pointer to the data to be passed to the function.
+ */
+void API dw_window_function(HWND handle, void *function, void *data)
+{
+	WinSendMsg(handle, WM_USER, (MPARAM)function, (MPARAM)data);
+}
+
+/* Functions for managing the user data lists that are associated with
+ * a given window handle.  Used in dw_window_set_data() and
+ * dw_window_get_data().
+ */
+UserData *_find_userdata(UserData **root, char *varname)
+{
+	UserData *tmp = *root;
+
+	while(tmp)
+	{
+		if(stricmp(tmp->varname, varname) == 0)
+			return tmp;
+		tmp = tmp->next;
+	}
+	return NULL;
+}
+
+int _new_userdata(UserData **root, char *varname, void *data)
+{
+	UserData *new = _find_userdata(root, varname);
+
+	if(new)
+	{
+		new->data = data;
+		return TRUE;
+	}
+	else
+	{
+		new = malloc(sizeof(UserData));
+		if(new)
+		{
+			new->varname = strdup(varname);
+			new->data = data;
+
+			new->next = NULL;
+
+			if (!*root)
+				*root = new;
+			else
+			{
+				UserData *prev = NULL, *tmp = *root;
+				while(tmp)
+				{
+					prev = tmp;
+					tmp = tmp->next;
+				}
+				if(prev)
+					prev->next = new;
+				else
+					*root = new;
+			}
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+int _remove_userdata(UserData **root, char *varname, int all)
+{
+	UserData *prev = NULL, *tmp = *root;
+
+	while(tmp)
+	{
+		if(all || stricmp(tmp->varname, varname) == 0)
+		{
+			if(!prev)
+			{
+				*root = tmp->next;
+				free(tmp->varname);
+				free(tmp);
+				if(!all)
+					return 0;
+				tmp = *root;
+			}
+			else
+			{
+				/* If all is true we should
+				 * never get here.
+				 */
+				prev->next = tmp->next;
+				free(tmp->varname);
+				free(tmp);
+				return 0;
+			}
+		}
+		else
+		{
+			prev = tmp;
+			tmp = tmp->next;
+		}
+	}
+	return 0;
+}
+
+/*
+ * Add a named user data item to a window handle.
+ * Parameters:
+ *       window: Window handle of signal to be called back.
+ *       dataname: A string pointer identifying which signal to be hooked.
+ *       data: User data to be passed to the handler function.
+ */
+void API dw_window_set_data(HWND window, char *dataname, void *data)
+{
+	WindowData *blah = (WindowData *)WinQueryWindowPtr(window, QWP_USER);
+
+	if(!blah)
+	{
+		if(!dataname)
+			return;
+
+		blah = calloc(1, sizeof(WindowData));
+		WinSetWindowPtr(window, QWP_USER, blah);
+	}
+
+	if(data)
+		_new_userdata(&(blah->root), dataname, data);
+	else
+	{
+		if(dataname)
+			_remove_userdata(&(blah->root), dataname, FALSE);
+		else
+			_remove_userdata(&(blah->root), NULL, TRUE);
+	}
+}
+
+/*
+ * Gets a named user data item to a window handle.
+ * Parameters:
+ *       window: Window handle of signal to be called back.
+ *       dataname: A string pointer identifying which signal to be hooked.
+ *       data: User data to be passed to the handler function.
+ */
+void *dw_window_get_data(HWND window, char *dataname)
+{
+	WindowData *blah = (WindowData *)WinQueryWindowPtr(window, QWP_USER);
+
+	if(blah && blah->root && dataname)
+	{
+		UserData *ud = _find_userdata(&(blah->root), dataname);
+		if(ud)
+			return ud->data;
+	}
+	return NULL;
+}
+
+/*
+ * Add a callback to a timer event.
+ * Parameters:
+ *       interval: Milliseconds to delay between calls.
+ *       sigfunc: The pointer to the function to be used as the callback.
+ *       data: User data to be passed to the handler function.
+ * Returns:
+ *       Timer ID for use with dw_timer_disconnect(), 0 on error.
+ */
+int API dw_timer_connect(int interval, void *sigfunc, void *data)
+{
+	if(sigfunc)
+	{
+		int timerid = WinStartTimer(dwhab, NULLHANDLE, 0, interval);
+
+		if(timerid)
+		{
+			_new_signal(WM_TIMER, NULLHANDLE, timerid, sigfunc, data);
+			return timerid;
+		}
+	}
+	return 0;
+}
+
+/*
+ * Removes timer callback.
+ * Parameters:
+ *       id: Timer ID returned by dw_timer_connect().
+ */
+void API dw_timer_disconnect(int id)
+{
+	SignalHandler *prev = NULL, *tmp = Root;
+
+	/* 0 is an invalid timer ID */
+	if(!id)
+		return;
+
+	WinStopTimer(dwhab, NULLHANDLE, id);
+
+	while(tmp)
+	{
+		if(tmp->id == id)
+		{
+			if(prev)
+			{
+				prev->next = tmp->next;
+				free(tmp);
+				tmp = prev->next;
+			}
+			else
+			{
+				Root = tmp->next;
+				free(tmp);
+				tmp = Root;
+			}
+		}
+		else
+		{
+			prev = tmp;
+			tmp = tmp->next;
+		}
+	}
+}
+
+/*
+ * Add a callback to a window event.
+ * Parameters:
+ *       window: Window handle of signal to be called back.
+ *       signame: A string pointer identifying which signal to be hooked.
+ *       sigfunc: The pointer to the function to be used as the callback.
+ *       data: User data to be passed to the handler function.
+ */
+void API dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data)
+{
+	ULONG message = 0, id = 0;
+
+	if(window && signame && sigfunc)
+	{
+		if((message = _findsigmessage(signame)) != 0)
+		{
+			/* Handle special case of the menu item */
+			if(message == WM_COMMAND && window < 65536)
+			{
+				char buffer[15];
+				HWND owner;
+
+				sprintf(buffer, "_dw_id%d", (int)window);
+				owner = (HWND)dw_window_get_data(hwndApp, buffer);
+
+				if(owner)
+				{
+					id = window;
+					window = owner;
+					dw_window_set_data(hwndApp, buffer, 0);
+				}
+				else
+				{
+					/* If it is a popup menu clear all entries */
+					dw_signal_disconnect_by_window(window);
+				}
+			}
+			_new_signal(message, window, id, sigfunc, data);
+		}
+	}
+}
+
+/*
+ * Removes callbacks for a given window with given name.
+ * Parameters:
+ *       window: Window handle of callback to be removed.
+ */
+void API dw_signal_disconnect_by_name(HWND window, char *signame)
+{
+	SignalHandler *prev = NULL, *tmp = Root;
+	ULONG message;
+
+	if(!window || !signame || (message = _findsigmessage(signame)) == 0)
+		return;
+
+	while(tmp)
+	{
+		if(tmp->window == window && tmp->message == message)
+		{
+			if(prev)
+			{
+				prev->next = tmp->next;
+				free(tmp);
+				tmp = prev->next;
+			}
+			else
+			{
+				Root = tmp->next;
+				free(tmp);
+				tmp = Root;
+			}
+		}
+		else
+		{
+			prev = tmp;
+			tmp = tmp->next;
+		}
+	}
+}
+
+/*
+ * Removes all callbacks for a given window.
+ * Parameters:
+ *       window: Window handle of callback to be removed.
+ */
+void API dw_signal_disconnect_by_window(HWND window)
+{
+	SignalHandler *prev = NULL, *tmp = Root;
+
+	while(tmp)
+	{
+		if(tmp->window == window)
+		{
+			if(prev)
+			{
+				prev->next = tmp->next;
+				free(tmp);
+				tmp = prev->next;
+			}
+			else
+			{
+				Root = tmp->next;
+				free(tmp);
+				tmp = Root;
+			}
+		}
+		else
+		{
+			prev = tmp;
+			tmp = tmp->next;
+		}
+	}
+}
+
+/*
+ * Removes all callbacks for a given window with specified data.
+ * Parameters:
+ *       window: Window handle of callback to be removed.
+ *       data: Pointer to the data to be compared against.
+ */
+void API dw_signal_disconnect_by_data(HWND window, void *data)
+{
+	SignalHandler *prev = NULL, *tmp = Root;
+
+	while(tmp)
+	{
+		if(tmp->window == window && tmp->data == data)
+		{
+			if(prev)
+			{
+				prev->next = tmp->next;
+				free(tmp);
+				tmp = prev->next;
+			}
+			else
+			{
+				Root = tmp->next;
+				free(tmp);
+				tmp = Root;
+			}
+		}
+		else
+		{
+			prev = tmp;
+			tmp = tmp->next;
+		}
+	}
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packace/Makefile.in	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,41 @@
+# Installer Makefile
+
+CC = @CC@
+RM = @RM@ -f
+MAKE = @MAKE@
+
+DEFS =
+LIBS =
+
+CFLAGS = -I../incace -D__UNIX__ -I.. @CFLAGS@
+LDFLAGS = 
+
+
+OBJECTS = globals.o packinst.o uac_comm.o uac_crc.o \
+          uac_crt.o uac_dcpr.o uac_sys.o unace.o
+
+SOURCES = globals.c ../packinst/packinst.c uac_comm.c \
+	  uac_crc.c uac_crt.c uac_dcpr.c uac_sys.c unace.c
+
+all: packinst
+
+$(OBJECTS):
+	$(CC) $(CFLAGS) -c $<	
+
+packinst:  $(OBJECTS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $(DEFS) -o packinst $(OBJECTS)
+
+clean: 
+	$(RM) $(OBJECTS) packinst *~
+
+globals.o: globals.c ../incace/globals.h ../incace/acestruc.h ../incace/unace.h
+packinst.o: ../packinst/packinst.c
+uac_comm.o: uac_comm.c ../incace/globals.h ../incace/uac_dcpr.h ../incace/uac_comm.h
+uac_crc.o: uac_crc.c ../incace/uac_crc.h
+uac_crt.o: uac_crt.c ../incace/os.h ../incace/attribs.h ../incace/globals.h ../incace/uac_crt.h ../incace/uac_sys.h
+uac_dcpr.o: uac_dcpr.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h \
+	      ../incace/uac_dcpr.h ../incace/uac_sys.h
+uac_sys.o: uac_sys.c ../incace/os.h ../incace/globals.h ../incace/uac_sys.h
+unace.o: unace.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h ../incace/uac_crt.h \
+           ../incace/uac_dcpr.h ../incace/uac_sys.h
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packace/globals.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,134 @@
+/* ------------------------------------------------------------------------ */
+/*                                                                          */
+/*      Global variable declarations                                        */
+/*                                                                          */
+/* ------------------------------------------------------------------------ */
+
+#include "os.h"
+
+#include "acestruc.h"
+#include "unace.h"
+
+#include <string.h>
+#include <stdio.h>
+
+//-------- Ace sign
+const char *acesign = "**ACE**";
+
+//-------- Version string for program
+const char *version="UNACE v1.1    public version\n";
+
+#ifdef AMIGA
+//-------- Version string for VERSION program
+static char *_version="$VER: Unace Amiga 1.1  "__AMIGADATE__"\n\n";
+#endif
+
+//-------- header buffer and pointers
+thead head;
+
+tmhead *t_mhead = (tmhead *) & head;
+tfhead *t_fhead = (tfhead *) & head;
+
+//-------- buffers
+ULONG *buf_rd        =0;
+CHAR  *buf           =0;
+CHAR  *buf_wr        =0;
+UCHAR *readbuf       =0;
+
+//-------- decompressor variables
+SHORT rpos           =0,
+      dcpr_do        =0,
+      dcpr_do_max    =0,
+      blocksize      =0,
+      dcpr_dic       =0,
+      dcpr_oldnum    =0,
+      bits_rd        =0,
+      dcpr_frst_file =0;
+USHORT dcpr_code_mn[1 << maxwd_mn],
+       dcpr_code_lg[1 << maxwd_lg];
+UCHAR dcpr_wd_mn[maxcode + 2],
+      dcpr_wd_lg[maxcode + 2],
+      wd_svwd[svwd_cnt];
+ULONG dcpr_dpos      =0,
+      cpr_dpos2      =0,
+      dcpr_dicsiz    =0,
+      dcpr_dican     =0,
+      dcpr_size      =0,
+      dcpr_olddist[4]={0,0,0,0},
+      code_rd        =0;
+
+CHAR *dcpr_text      =0;
+
+//-------- quicksort
+USHORT sort_org[maxcode + 2];
+UCHAR sort_freq[(maxcode + 2) * 2];
+
+//-------- file handling
+CHAR aname[PATH_MAX];
+INT  archan,
+     wrhan;
+#if !defined(__EMX__) && !defined(__OS2__)
+FILE *farchan = NULL;
+#endif
+LONG skipsize=0;
+
+//-------- structures for archive handling
+struct tadat adat;
+
+//-------- flags
+INT  f_err      =0,
+     f_ovrall   =0,
+     f_allvol_pr=0,
+     f_curpas   =0,
+     f_criterr  =0;
+
+
+void resetglobals(void)
+{
+	t_mhead = (tmhead *) & head;
+	t_fhead = (tfhead *) & head;
+
+	buf_rd        =0;
+	buf           =0;
+	buf_wr        =0;
+	readbuf       =0;
+
+	rpos           =0;
+	dcpr_do        =0;
+	dcpr_do_max    =0;
+	blocksize      =0;
+	dcpr_dic       =0;
+	dcpr_oldnum    =0;
+	bits_rd        =0;
+	dcpr_frst_file =0;
+
+	memset(&dcpr_code_mn, 0, sizeof(dcpr_code_mn));
+	memset(&dcpr_code_lg, 0, sizeof(dcpr_code_lg));
+	memset(&dcpr_wd_mn, 0, sizeof(dcpr_wd_mn));
+	memset(&dcpr_wd_lg, 0, sizeof(dcpr_wd_lg));
+	memset(&wd_svwd, 0, sizeof(wd_svwd));
+	dcpr_dpos      =0;
+	cpr_dpos2      =0;
+	dcpr_dicsiz    =0;
+	dcpr_dican     =0;
+	dcpr_size      =0;
+
+	memset(&dcpr_olddist, 0, sizeof(dcpr_olddist));
+
+	code_rd        =0;
+	dcpr_text      =0;
+
+	memset(&sort_org, 0, sizeof(sort_org));
+	memset(&sort_freq, 0, sizeof(sort_freq));
+
+	archan=0;
+	wrhan=0;
+	skipsize=0;
+
+	f_err      =0;
+	f_ovrall   =0;
+	f_allvol_pr=0;
+	f_curpas   =0;
+	f_criterr  =0;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packace/makefile.b32	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,41 @@
+# Common settings for Borland 32-bit compilation (makefile.b32 files)
+
+LINK=ilink32
+
+OPT = -O2
+LDFLAGS = -lxncd -l-P
+CPPFLAGS = /I"..\incace" /DWIN32
+LINKFLAGS=/aa -L$(BCCDIR)\lib\psdk
+
+DUMMY=dummy
+
+SRCSUFF = cpp
+OBJSUFF = obj
+
+TARGET = packinst
+OBJECTS = globals.obj uac_comm.obj uac_crc.obj uac_crt.obj uac_dcpr.obj uac_sys.obj unace.obj packinst.obj
+
+all: $(TARGET).exe
+
+packinst.exe:      $(OBJECTS)
+	bcc32 $(LDFLAGS) -epackinst.exe @&&|
+$(OBJECTS)
+|
+
+.$(SRCSUFF).obj:
+	bcc32 $(CPPFLAGS) -c {$< }
+
+packinst.obj: ..\packinst\packinst.c
+	bcc32 $(CPPFLAGS) -P- -c ..\packinst\packinst.c
+        
+.c.obj:
+	bcc32 $(CPPFLAGS) -P- -c {$< }
+        
+clean:
+        -erase *.obj
+        -erase *.exe
+        -erase *.res
+        -erase *.map
+        -erase *.rws
+        -erase *.tds
+        -erase *.il?
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packace/makefile.g95	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,46 @@
+# Installer Makefile
+
+CC = gcc
+RM = rm -f
+RC = rc
+MAKE = make
+
+DEFS =
+LIBS =
+
+CFLAGS = -mno-cygwin -O -g -I../incace -Wall -DWIN32
+LDFLAGS = -mno-cygwin
+
+
+OBJECTS = globals.o packinst.o uac_comm.o uac_crc.o \
+          uac_crt.o uac_dcpr.o uac_sys.o unace.o
+
+SOURCES = globals.c ../packinst/packinst.c uac_comm.c \
+	  uac_crc.c uac_crt.c uac_dcpr.c uac_sys.c unace.c
+
+all: packinst
+
+$(OBJECTS):
+	$(CC) $(CFLAGS) -c $<	
+
+Include: ../incace/Makefile Makefile
+#	cd include
+#	$(MAKE) -f Makefile all
+
+packinst:  $(OBJECTS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $(DEFS) -o packinst $(OBJECTS)
+
+clean: 
+	$(RM) $(OBJECTS) packinst *~
+
+globals.o: globals.c ../incace/globals.h ../incace/acestruc.h ../incace/unace.h
+packinst.o: ../packinst/packinst.c
+uac_comm.o: uac_comm.c ../incace/globals.h ../incace/uac_dcpr.h ../incace/uac_comm.h
+uac_crc.o: uac_crc.c ../incace/uac_crc.h
+uac_crt.o: uac_crt.c ../incace/os.h ../incace/attribs.h ../incace/globals.h ../incace/uac_crt.h ../incace/uac_sys.h
+uac_dcpr.o: uac_dcpr.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h \
+	      ../incace/uac_dcpr.h ../incace/uac_sys.h
+uac_sys.o: uac_sys.c ../incace/os.h ../incace/globals.h ../incace/uac_sys.h
+unace.o: unace.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h ../incace/uac_crt.h \
+           ../incace/uac_dcpr.h ../incace/uac_sys.h
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packace/makefile.gcc	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,46 @@
+# Installer Makefile
+
+CC = gcc
+RM = rm -f
+RC = rc
+MAKE = make
+
+DEFS =
+LIBS =
+
+CFLAGS = -O -g -I../incace -Wall
+LDFLAGS = 
+
+
+OBJECTS = globals.o packinst.o uac_comm.o uac_crc.o \
+          uac_crt.o uac_dcpr.o uac_sys.o unace.o
+
+SOURCES = globals.c ../packinst/packinst.c uac_comm.c \
+	  uac_crc.c uac_crt.c uac_dcpr.c uac_sys.c unace.c
+
+all: packinst
+
+$(OBJECTS):
+	$(CC) $(CFLAGS) -c $<	
+
+Include: ../incace/Makefile Makefile
+#	cd include
+#	$(MAKE) -f Makefile all
+
+packinst:  $(OBJECTS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $(DEFS) -o packinst $(OBJECTS)
+
+clean: 
+	$(RM) $(OBJECTS) packinst *~
+
+globals.o: globals.c ../incace/globals.h ../incace/acestruc.h ../incace/unace.h
+packinst.o: ../packinst/packinst.c
+uac_comm.o: uac_comm.c ../incace/globals.h ../incace/uac_dcpr.h ../incace/uac_comm.h
+uac_crc.o: uac_crc.c ../incace/uac_crc.h
+uac_crt.o: uac_crt.c ../incace/os.h ../incace/attribs.h ../incace/globals.h ../incace/uac_crt.h ../incace/uac_sys.h
+uac_dcpr.o: uac_dcpr.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h \
+	      ../incace/uac_dcpr.h ../incace/uac_sys.h
+uac_sys.o: uac_sys.c ../incace/os.h ../incace/globals.h ../incace/uac_sys.h
+unace.o: unace.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h ../incace/uac_crt.h \
+           ../incace/uac_dcpr.h ../incace/uac_sys.h
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packace/makefile.vac	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,40 @@
+# Installer Makefile
+
+CFLAGS = /Ss /I. /I.. /I../incace /C
+
+
+OBJECTS = globals.obj uac_comm.obj uac_crc.obj \
+          uac_crt.obj uac_dcpr.obj uac_sys.obj unace.obj
+
+SOURCES = globals.c ..\packinst\packinst.c uac_comm.c uac_crc.c \
+          uac_crt.c uac_dcpr.c uac_sys.c unace.c
+
+all: packinst.exe
+
+$(OBJECTS):
+	icc $(CFLAGS) %s
+
+packinst.exe:  $(OBJECTS) packinst.obj
+	icc @<<
+	 /B" /de /optfunc"
+	 /Fepackinst.exe
+	 rexx.lib
+	 $(OBJECTS) packinst.obj
+<<
+
+clean: 
+	rm $(OBJECTS) install.exe install.res sfx.exe
+
+packinst.obj:
+	icc $(CFLAGS) ..\packinst\packinst.c
+
+globals.obj: globals.c ../incace/globals.h ../incace/acestruc.h ../incace/unace.h
+uac_comm.obj: uac_comm.c ../incace/globals.h ../incace/uac_dcpr.h ../incace/uac_comm.h
+uac_crc.obj: uac_crc.c ../incace/uac_crc.h
+uac_crt.obj: uac_crt.c ../incace/os.h ../incace/attribs.h ../incace/globals.h ../incace/uac_crt.h ../incace/uac_sys.h
+uac_dcpr.obj: uac_dcpr.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h \
+	      ../incace/uac_dcpr.h ../incace/uac_sys.h
+uac_sys.obj: uac_sys.c ../incace/os.h ../incace/globals.h ../incace/uac_sys.h
+unace.obj: unace.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h ../incace/uac_crt.h \
+           ../incace/uac_dcpr.h ../incace/uac_sys.h
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packace/makefile.vc	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,54 @@
+#
+CC = cl
+CFLAGS = -c -G5 -GD -Zp1 -DWIN32 -D__WIN32__ -DMSVC -I. -I.. -I..\incace
+CFLAGS_DEBUG = -Zi
+CFLAGS_COMPILE = -MTd
+LIBS = kernel32.lib advapi32.lib user32.lib
+RES = 
+LINKFLAGS = -machine:i386 -debug:full -debugtype:cv
+DLLLINKFLAGS = -dll
+LINK = link
+
+OBJS = 	globals.obj \
+       	uac_comm.obj \
+       	uac_crc.obj \
+       	uac_crt.obj \
+       	uac_dcpr.obj \
+       	uac_sys.obj \
+       	unace.obj \
+       	..\packinst\packinst.obj
+                
+LINKOBJS = 	globals.obj \
+	       	uac_comm.obj \
+	       	uac_crc.obj \
+       		uac_crt.obj \
+	       	uac_dcpr.obj \
+       		uac_sys.obj \
+	       	unace.obj \
+       		packinst.obj
+                
+all: packinst.exe
+
+clean:
+	-erase *.dll
+        -erase *.exe
+        -erase *.opt
+        -erase *.lib
+        -erase *.obj
+        -erase *.map
+        -erase *.pdb
+        -erase *.ilk
+        -erase *.exp
+        -erase *.res
+        -erase *~
+        
+packinst.exe: $(OBJS)
+	$(LINK) @<<
+-out:$(@) -subsystem:console
+$(LINKFLAGS)
+$(LINKOBJS)
+$(LIBS)
+<<
+
+.c.obj:
+	$(CC) $(CFLAGS) $(CFLAGS_DEBUG) $(CFLAGS_COMPILE) $*.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packace/uac_comm.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,51 @@
+/* ------------------------------------------------------------------------ */
+/*                                                                          */
+/*      Decompresses and outputs comment if present.                        */
+/*                                                                          */
+/* ------------------------------------------------------------------------ */
+
+#include <stdio.h>    // printf()
+
+#include "globals.h"
+#include "uac_dcpr.h"
+#include "uac_comm.h"
+
+INT  comm_cpr_size=0;
+CHAR *comm;
+
+void comment_out(CHAR *top)      // outputs comment if present
+{
+	INT  i;
+
+	if (head.HEAD_FLAGS & ACE_COMM)
+	{                             // comment present?
+		if (head.HEAD_TYPE == MAIN_BLK)
+		{                          // get begin and size of comment data
+			comm = (CHAR *)MCOMM;
+			comm_cpr_size = MCOMM_SIZE;
+		}
+		else
+		{
+			comm = (CHAR *)FCOMM;
+			comm_cpr_size = FCOMM_SIZE;
+		}                          // limit comment size if too big
+		i = sizeof(head) - (INT)(comm - (CHAR*) &head);
+		if (comm_cpr_size > i)
+			comm_cpr_size = i;
+		dcpr_comm(i);              // decompress comment
+
+#ifdef AMIGA
+		{
+			char *p=comm;
+			while (*p)
+			{
+				if (*p==0x0D)
+					*p=0x0A;          // Replace ms-dos line termination
+				p++;
+			}
+		}
+#endif
+
+		pipeit("%s\n\n%s\n\n", top, comm); // output comment
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packace/uac_crc.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,36 @@
+/* ------------------------------------------------------------------------ */
+/*                                                                          */
+/*      CRC-calculation routines.                                           */
+/*                                                                          */
+/* ------------------------------------------------------------------------ */
+
+#include "uac_crc.h"
+
+
+ULONG crctable[256];
+ULONG rd_crc=0;
+
+
+void make_crctable(void)   // initializes CRC table
+{
+	ULONG r,
+	i,
+	j;
+
+	for (i = 0; i <= 255; i++)
+	{
+		for (r = i, j = 8; j; j--)
+			r = (r & 1) ? (r >> 1) ^ CRCPOLY : (r >> 1);
+		crctable[i] = r;
+	}
+}
+
+// Updates crc from addr till addr+len-1
+//
+ULONG getcrc(ULONG crc, UCHAR * addr, INT len)
+{
+	while (len--)
+		crc = crctable[(unsigned char) crc ^ (*addr++)] ^ (crc >> 8);
+	return (crc);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packace/uac_crt.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,149 @@
+/* ------------------------------------------------------------------------ */
+/*                                                                          */
+/*      Creates/Replaces files or directories.                              */
+/*                                                                          */
+/* ------------------------------------------------------------------------ */
+
+#include "os.h"
+
+#include <stdlib.h>
+#include <fcntl.h>     // AMIGA: open()
+#include <stdio.h>     // pipeit() remove()
+#include <string.h>    // strncpy()
+#include <sys/types.h>
+#include <sys/stat.h>  // struct stat
+#include <string.h>
+
+
+#if defined(DOS) || defined(WINNT) || defined(WIN16) || defined(__OS2__)
+ #include <io.h>       // access()
+#endif
+#if defined(__IBMC__)
+ #include <direct.h>
+#endif
+
+#define DIRSEP 	'\\'
+
+#include "attribs.h"
+#include "globals.h"
+#include "uac_crt.h"
+#include "uac_sys.h"
+
+/* gets file name from header
+ */
+CHAR *ace_fname(CHAR * s, thead * head, INT nopath)
+{
+	INT  i;
+	char *cp;
+
+	strncpy(s, (CHAR *)(*(tfhead *) head).FNAME, i = (*(tfhead *) head).FNAME_SIZE);
+	s[i] = 0;
+
+	if (nopath)
+	{
+		cp=strrchr(s, '\\');
+		if (cp)
+			memmove(s, cp+1, strlen(cp));
+	}
+
+	return s;
+}
+
+void check_ext_dir(CHAR * f)        // checks/creates path of file
+{
+	CHAR *cp,
+	d[PATH_MAX];
+	INT  i;
+
+	d[0] = 0;
+
+	for (;;)
+	{
+		if ((cp = (CHAR *) strchr(&f[strlen(d) + 1], DIRSEP))!=NULL)
+		{
+			i = cp - f;
+			strncpy(d, f, i);
+			d[i] = 0;
+		}
+		else
+			return;
+
+		if (!fileexists(d))
+#if (defined(__OS2__) && !defined(__EMX__)) || (defined(WINNT) && !defined(__CYGWIN__))
+			if (mkdir(d))
+#else
+				if (mkdir(d, 0))
+#endif
+				{
+					f_err = ERR_WRITE;
+					pipeit("\n    Error while creating directory.\n");
+				}
+	}
+}
+
+INT  ovr_delete(CHAR * n)           // deletes directory or file
+{
+	if (remove(n) && rmdir(n))
+	{
+		pipeit("\n    Could not delete file or directory. Access denied.\n");
+		return (1);
+	}
+	return (0);
+}
+
+INT  create_dest_file(CHAR * file, INT a)  // creates file or directory
+{
+	INT  han,
+	i  = 0,
+	ex = fileexists(file);
+	struct stat st;
+
+	check_ext_dir(file);
+	if (f_err)
+		return (-1);
+	if (a & _A_SUBDIR)
+	{                                // create dir or file?
+		if (ex)
+			stat(file, &st);
+#if (defined(__OS2__) && !defined(__EMX__)) || (!defined(__CYGWIN__) && defined(WINNT))
+		if ((!ex && mkdir(file)) || (ex && (st.st_mode & S_IFDIR)))
+#else
+			if ((!ex && mkdir(file, 0)) || (ex && (st.st_mode & S_IFDIR)))
+#endif
+			{
+				pipeit("\n    Could not create directory.\n");
+				return (-1);
+			}
+#ifdef DOS
+		_dos_setfileattr(file, a);    // set directory attributes
+#endif
+		return (-1);
+	}
+	else
+	{
+		if (ex)
+		{                             // does the file already exist
+			if (!f_ovrall)
+			{
+				i = wrask("Overwrite existing file?");  // prompt for overwrite
+				f_ovrall = (i == 1);
+				if (i == 3)
+					f_err = ERR_USER;
+			}
+			if ((i && !f_ovrall) || ovr_delete(file))
+				return (-1);            // delete?
+		}
+#if defined(__OS2_) || defined(__EMX__) || defined(WIN32)
+		if ((han = open(file, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY,
+						S_IREAD | S_IWRITE | S_IEXEC | S_IDELETE |
+						S_IRGRP | S_IWGRP  | S_IROTH | S_IWOTH )) < 0)
+#else
+			if ((han = open(file, O_WRONLY | O_TRUNC | O_CREAT,
+							S_IREAD | S_IWRITE | S_IEXEC | S_IDELETE |
+							S_IRGRP | S_IWGRP  | S_IROTH | S_IWOTH )) < 0)
+#endif
+				pipeit("\n    Could not create destination file.\n");
+		return (han);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packace/uac_dcpr.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,553 @@
+/* ------------------------------------------------------------------------ */
+/*                                                                          */
+/*      These are the decompression algorithms.                             */
+/*      Don't change here anything (apart from memory allocation perhaps).  */
+/*      Any changes will very likely cause bugs!                            */
+/*                                                                          */
+/* ------------------------------------------------------------------------ */
+
+#include "os.h"
+
+#if defined(AMIGA)
+ #include <string.h> // mem*()
+#endif
+#if defined(DOS) || defined(WIN16) || defined(WINNT) || defined(OS2) || defined(UNIX)
+#if !defined(__CYGWIN__)
+ #include <mem.h>    // mem*()
+#endif 
+#endif
+
+#include <stdio.h>   // pipeit()
+#include <stdlib.h>  // malloc()
+#include <string.h>
+
+#include "globals.h"
+#include "portable.h"
+#include "uac_comm.h"
+#include "uac_crc.h"
+#include "uac_dcpr.h"
+#include "uac_sys.h"
+#ifdef CRYPT
+ #include "unace_ps.h"
+#endif /* CRYPT */
+
+
+//------------------------------ QUICKSORT ---------------------------------//
+#define xchg_def(v1,v2) {INT dummy;\
+                         dummy=v1; \
+                         v1=v2;    \
+                         v2=dummy;}
+
+void sortrange(INT left, INT right)
+{
+	INT  zl = left,
+	zr = right,
+	hyphen;
+
+	hyphen = sort_freq[right];
+
+	//divides by hyphen the given range into 2 parts
+	do
+	{
+		while (sort_freq[zl] > hyphen)
+			zl++;
+		while (sort_freq[zr] < hyphen)
+			zr--;
+		//found a too small (left side) and
+		//a too big (right side) element-->exchange them
+		if (zl <= zr)
+		{
+			xchg_def(sort_freq[zl], sort_freq[zr]);
+			xchg_def(sort_org[zl], sort_org[zr]);
+			zl++;
+			zr--;
+		}
+	}
+	while (zl < zr);
+
+	//sort partial ranges - when very small, sort directly
+	if (left < zr)
+	{
+		if (left < zr - 1)
+			sortrange(left, zr);
+		else if (sort_freq[left] < sort_freq[zr])
+		{
+			xchg_def(sort_freq[left], sort_freq[zr]);
+			xchg_def(sort_org[left], sort_org[zr]);
+		}
+	}
+
+	if (right > zl)
+	{
+		if (zl < right - 1)
+			sortrange(zl, right);
+		else if (sort_freq[zl] < sort_freq[right])
+		{
+			xchg_def(sort_freq[zl], sort_freq[right]);
+			xchg_def(sort_org[zl], sort_org[right]);
+		}
+	}
+}
+
+void quicksort(INT n)
+{
+	INT  i;
+
+	for (i = n + 1; i--;)
+		sort_org[i] = i;
+	sortrange(0, n);
+}
+
+//------------------------------ read bits ---------------------------------//
+void readdat(void)
+{
+	UINT i;
+
+	i = (size_rdb - 2) << 2;
+	rpos -= size_rdb - 2;
+	buf_rd[0] = buf_rd[size_rdb - 2];
+	buf_rd[1] = buf_rd[size_rdb - 1];
+	read_adds_blk((CHAR *) & buf_rd[2], i);
+#ifdef HI_LO_BYTE_ORDER
+	{
+		ULONG *p;
+		i>>=2;    // count LONGs not BYTEs
+		p=&buf_rd[2];
+		while (i--)
+		{
+			LONGswap(p);
+			p++;
+		}
+	}
+#endif
+}
+
+#define addbits(bits)                                   \
+{                                                       \
+	rpos+=(bits_rd+=bits)>>5;                             \
+	bits_rd&=31;                                          \
+	if (rpos==(size_rdb-2)) readdat();                    \
+	code_rd=(buf_rd[rpos] << bits_rd)                     \
+	+((buf_rd[rpos+1] >> (32-bits_rd))&(!bits_rd-1));   \
+	}
+
+
+//---------------------- COMMENT DECOMPRESSION -----------------------------//
+
+#define comm_cpr_hf(a,b) (a+b)
+
+void dcpr_comm_init(void)
+{
+	INT  i;
+
+	i = comm_cpr_size > size_rdb * sizeof(LONG) ? size_rdb * sizeof(LONG) : comm_cpr_size;
+	if (!f_err)
+		memcpy(buf_rd, comm, i);
+#ifdef HI_LO_BYTE_ORDER
+	{
+		ULONG *p;
+		i>>=2;    // count LONGs not BYTEs
+		p=buf_rd;
+		while (i--)
+		{
+			LONGswap(p);
+			p++;
+		}
+	}
+#endif
+	code_rd = buf_rd[0];
+	rpos = bits_rd = 0;
+}
+
+void dcpr_comm(INT comm_size)
+{
+	SHORT hash[comm_cpr_hf(255, 255) + 1];
+	INT  dpos = 0,
+		c,
+	pos = 0,
+	len,
+	hs;
+
+	memset(&hash, 0, sizeof(hash));
+	if (comm_cpr_size)
+	{
+		dcpr_comm_init();
+		len = code_rd >> (32 - 15);
+		addbits(15);
+		if (len >= comm_size)
+			len = comm_size - 1;
+		if (read_wd(maxwd_mn, dcpr_code_mn, dcpr_wd_mn, max_cd_mn))
+			do
+		{
+			if (dpos > 1)
+			{
+				pos = hash[hs = comm_cpr_hf(comm[dpos - 1], comm[dpos - 2])];
+				hash[hs] = dpos;
+			}
+			addbits(dcpr_wd_mn[(c = dcpr_code_mn[code_rd >> (32 - maxwd_mn)])]);
+			if (rpos == size_rdb - 3)
+				rpos = 0;
+			if (c > 255)
+			{
+				c -= 256;
+				c += 2;
+				while (c--)
+					comm[dpos++] = comm[pos++];
+			}
+			else
+			{
+				comm[dpos++] = c;
+			}
+		}
+		while (dpos < len);
+		comm[len] = 0;
+	}
+}
+
+//------------------------- LZW1 DECOMPRESSION -----------------------------//
+void wrchar(CHAR ch)
+{
+	dcpr_do++;
+
+	dcpr_text[dcpr_dpos] = ch;
+	dcpr_dpos++;
+	dcpr_dpos &= dcpr_dican;
+}
+
+void copystr(LONG d, INT l)
+{
+	INT  mpos;
+
+	dcpr_do += l;
+
+	mpos = dcpr_dpos - d;
+	mpos &= dcpr_dican;
+
+	if ((mpos >= dcpr_dicsiz - maxlength) || (dcpr_dpos >= dcpr_dicsiz - maxlength))
+	{
+		while (l--)
+		{
+			dcpr_text[dcpr_dpos] = dcpr_text[mpos];
+			dcpr_dpos++;
+			dcpr_dpos &= dcpr_dican;
+			mpos++;
+			mpos &= dcpr_dican;
+		}
+	}
+	else
+	{
+		while (l--)
+			dcpr_text[dcpr_dpos++] = dcpr_text[mpos++];
+		dcpr_dpos &= dcpr_dican;
+	}
+}
+
+void decompress(void)
+{
+	INT  c,
+	lg,
+	i,
+	k;
+	ULONG dist;
+
+	while (dcpr_do < dcpr_do_max)
+	{
+		if (!blocksize)
+			if (!calc_dectabs())
+				return;
+
+		addbits(dcpr_wd_mn[(c = dcpr_code_mn[code_rd >> (32 - maxwd_mn)])]);
+		blocksize--;
+		if (c > 255)
+		{
+			if (c > 259)
+			{
+				if ((c -= 260) > 1)
+				{
+					dist = (code_rd >> (33 - c)) + (1L << (c - 1));
+					addbits(c - 1);
+				}
+				else
+					dist = c;
+				dcpr_olddist[(dcpr_oldnum = (dcpr_oldnum + 1) & 3)] = dist;
+				i = 2;
+				if (dist > maxdis2)
+				{
+					i++;
+					if (dist > maxdis3)
+						i++;
+				}
+			}
+			else
+			{
+				dist = dcpr_olddist[(dcpr_oldnum - (c &= 255)) & 3];
+				for (k = c + 1; k--;)
+					dcpr_olddist[(dcpr_oldnum - k) & 3] = dcpr_olddist[(dcpr_oldnum - k + 1) & 3];
+				dcpr_olddist[dcpr_oldnum] = dist;
+				i = 2;
+				if (c > 1)
+					i++;
+			}
+			addbits(dcpr_wd_lg[(lg = dcpr_code_lg[code_rd >> (32 - maxwd_lg)])]);
+			dist++;
+			lg += i;
+			copystr(dist, lg);
+		}
+		else
+			wrchar(c);
+	}
+}
+
+//-------------------------- HUFFMAN ROUTINES ------------------------------//
+INT  makecode(UINT maxwd, UINT size1_t, UCHAR * wd, USHORT * code)
+{
+	UINT maxc,
+	size2_t,
+	l,
+	c,
+	i,
+	max_make_code;
+
+	memcpy(&sort_freq, wd, (size1_t + 1) * sizeof(CHAR));
+	if (size1_t)
+		quicksort(size1_t);
+	else
+		sort_org[0] = 0;
+	sort_freq[size1_t + 1] = size2_t = c = 0;
+	while (sort_freq[size2_t])
+		size2_t++;
+	if (size2_t < 2)
+	{
+		i = sort_org[0];
+		wd[i] = 1;
+		size2_t += (size2_t == 0);
+	}
+	size2_t--;
+
+	max_make_code = 1 << maxwd;
+	for (i = size2_t + 1; i-- && c < max_make_code;)
+	{
+		maxc = 1 << (maxwd - sort_freq[i]);
+		l = sort_org[i];
+		if (c + maxc > max_make_code)
+		{
+			dcpr_do = dcpr_do_max;
+			return (0);
+		}
+		memset16(&code[c], l, maxc);
+		c += maxc;
+	}
+	return (1);
+}
+
+INT  read_wd(UINT maxwd, USHORT * code, UCHAR * wd, INT max_el)
+{
+	UINT c,
+	i,
+	j,
+	num_el,
+	l,
+	uplim,
+	lolim;
+
+	memset(wd, 0, max_el * sizeof(CHAR));
+	memset(code, 0, (1 << maxwd) * sizeof(SHORT));
+
+	num_el = code_rd >> (32 - 9);
+	addbits(9);
+	if (num_el > max_el)
+		num_el = max_el;
+
+	lolim = code_rd >> (32 - 4);
+	addbits(4);
+	uplim = code_rd >> (32 - 4);
+	addbits(4);
+
+	for (i = -1; ++i <= uplim;)
+	{
+		wd_svwd[i] = code_rd >> (32 - 3);
+		addbits(3);
+	}
+	if (!makecode(maxwd_svwd, uplim, wd_svwd, code))
+		return (0);
+	j = 0;
+	while (j <= num_el)
+	{
+		c = code[code_rd >> (32 - maxwd_svwd)];
+		addbits(wd_svwd[c]);
+		if (c < uplim)
+			wd[j++] = c;
+		else
+		{
+			l = (code_rd >> 28) + 4;
+			addbits(4);
+			while (l-- && j <= num_el)
+				wd[j++] = 0;
+		}
+	}
+	if (uplim)
+		for (i = 0; ++i <= num_el;)
+			wd[i] = (wd[i] + wd[i - 1]) % uplim;
+	for (i = -1; ++i <= num_el;)
+		if (wd[i])
+			wd[i] += lolim;
+
+	return (makecode(maxwd, num_el, wd, code));
+
+}
+
+INT  calc_dectabs(void)
+{
+	if (!read_wd(maxwd_mn, dcpr_code_mn, dcpr_wd_mn, max_cd_mn)
+		|| !read_wd(maxwd_lg, dcpr_code_lg, dcpr_wd_lg, max_cd_lg))
+		return (0);
+
+	blocksize = code_rd >> (32 - 15);
+	addbits(15);
+
+	return (1);
+}
+
+//---------------------------- BLOCK ROUTINES ------------------------------//
+INT  decompress_blk(CHAR * buf, UINT len)
+{
+	LONG old_pos = dcpr_dpos;
+	INT  i;
+
+	dcpr_do = 0;
+	if ((dcpr_do_max = len - maxlength) > dcpr_size)
+		dcpr_do_max = dcpr_size;
+	if ((LONG) dcpr_size > 0 && dcpr_do_max)
+	{
+		decompress();
+		if (old_pos + dcpr_do > dcpr_dicsiz)
+		{
+			i = dcpr_dicsiz - old_pos;
+			memcpy(buf, &dcpr_text[old_pos], i);
+			memcpy(&buf[i], dcpr_text, dcpr_do - i);
+		}
+		else
+			memcpy(buf, &dcpr_text[old_pos], dcpr_do);
+	}
+	dcpr_size -= dcpr_do;
+	return (dcpr_do);
+}
+
+INT unstore(CHAR * buf, UINT len)
+{
+	UINT rd = 0,
+	i,
+	pos = 0;
+
+#ifdef CRYPT
+	len = crypt_len(len - 8);    /* because of decryption */
+#endif /* CRYPT */
+
+	while ((i = read_adds_blk((CHAR *) buf_rd, (INT) ((i = ((len > dcpr_size) ? dcpr_size : len)) > size_rdb ? size_rdb : i))) != 0)
+	{
+		rd += i;
+		len -= i;
+		memcpy(&buf[pos], buf_rd, i);
+		pos += i;
+	}
+	dcpr_size -= rd;
+	for (i = 0; i < rd; i++)
+	{
+		dcpr_text[dcpr_dpos] = buf[i];
+		dcpr_dpos++;
+		dcpr_dpos &= dcpr_dican;
+	}
+	return (INT)rd;
+}
+
+INT  dcpr_adds_blk(CHAR * buf, UINT len)
+{
+	INT  r;
+
+	switch (fhead.TECH.TYPE)
+	{
+	case TYPE_STORE:
+		r = unstore(buf, len);
+		break;
+	case TYPE_LZW1:
+		r = decompress_blk(buf, len);
+		break;
+	default:
+		pipeit("\nFile compressed with unknown method. Decompression not possible.\n");
+		f_err = ERR_OTHER;
+		r = 0;
+	}
+	rd_crc = getcrc(rd_crc, (UCHAR *)buf, r);
+	return r;
+}
+
+
+//----------------------------- INIT ROUTINES ------------------------------//
+void dcpr_init(void)
+{
+	dcpr_frst_file = 1;
+
+	dcpr_dic = 20;
+	while ((dcpr_text = malloc(dcpr_dicsiz = (LONG) 1 << dcpr_dic))==NULL)
+		dcpr_dic--;
+	dcpr_dican = dcpr_dicsiz - 1;
+}
+
+void dcpr_init_file(void)
+{
+	UINT i;
+
+#ifdef CRYPT
+
+	reset_cryptkey();
+
+#else /* CRYPT */
+
+	if (head.HEAD_FLAGS & ACE_PASSW)
+	{
+		pipeit("\nFound passworded file. Decryption not supported.\n");
+		f_err = ERR_OTHER;
+		return;
+	}
+
+#endif /* CRYPT */
+
+	rd_crc = CRC_MASK;
+	dcpr_size = fhead.SIZE;
+	if (fhead.TECH.TYPE == TYPE_LZW1)
+	{
+		if ((fhead.TECH.PARM & 15) + 10 > dcpr_dic)
+		{
+			pipeit("\nNot enough memory or dictionary of archive too large.\n");
+			f_err = ERR_MEM;
+			return;
+		}
+
+		i = size_rdb * sizeof(LONG);
+		read_adds_blk((CHAR *) buf_rd, i);
+#ifdef HI_LO_BYTE_ORDER
+		{
+			ULONG *p;
+			i>>=2;    // count LONGs not BYTEs
+			p=buf_rd;
+			while (i--)
+			{
+				LONGswap(p);
+				p++;
+			}
+		}
+#endif
+		code_rd = buf_rd[0];
+		bits_rd = rpos = 0;
+
+		blocksize = 0;
+	}
+	if (!adat.sol || dcpr_frst_file)
+		dcpr_dpos = 0;
+
+	dcpr_oldnum = 0;
+	memset(&dcpr_olddist, 0, sizeof(dcpr_olddist));
+
+	dcpr_frst_file = 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packace/uac_sys.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,105 @@
+/* ------------------------------------------------------------------------ */
+/*                                                                          */
+/*      Some basic things.                                                  */
+/*                                                                          */
+/* ------------------------------------------------------------------------ */
+
+#include "os.h"
+
+#include <signal.h>  // signal()
+#include <stdio.h>   // fprintf() fflush() getch() putc()
+
+#if defined(DOS) || defined(WINNT) || defined(WIN16)
+#if !defined(__CYGWIN__)
+ #include <conio.h>  // getch()
+#endif 
+#endif
+#if defined(DOS)
+ #include <dos.h>    // delay() sound()
+#endif
+
+#include "globals.h"
+#include "uac_sys.h"
+
+
+void memset16(USHORT * dest, SHORT val, INT len)  // fills short-array with
+{                                                 // value
+	while (len--)
+		*(dest++) = val;
+}
+
+INT  cancel(void)               // checks whether to interrupt the program
+{
+#ifdef DOS
+	while (kbhit())
+	{
+		if (getch() == 27)
+			f_err = ERR_USER;
+	}
+#endif
+	return (f_err);
+}
+
+INT  wrask(CHAR * s)            // prompt-routine
+{
+	CHAR ch = 0;
+
+	fprintf(stderr, "\n %s (Yes,Always,No,Cancel) ", s);
+	fflush(stderr);
+	do
+	{
+		/*ch = getch();
+		 ch = upcase(ch);*/
+	}
+	while (ch != 'Y' && ch != 'A' && ch != 'N' && ch != 'C' && ch != 27);
+	fprintf(stderr, "%s", ch == 'Y' ? "Yes" : (ch == 'A' ? "Always" : (ch == 'N' ? "No" : "Cancel")));
+	fflush(stderr);
+	return (ch == 'Y' ? 0 : (ch == 'A' ? 1 : (ch == 'N' ? 2 : 3)));
+}
+
+void beep(void)                           // makes some noise
+{
+#ifdef DOS
+	sound(800);
+	delay(250);
+	nosound();
+#endif
+#ifdef AMIGA
+	putc(0x07, stderr);
+#endif
+}
+
+void my_signalhandler(INT sig_number)     // sets f_err if ctrl+c or ctrl+brk
+{
+	f_err = ERR_USER;
+	pipeit("\nUser break\n");
+}
+
+#ifdef DOS                                // handles hardware errors
+#ifdef __BORLANDC__
+INT harderrhandler(UINT deverr, UINT errc, UINT * devhdr)
+#else
+INT __far harderrhandler(UINT deverr, UINT errc, UINT * devhdr)
+#endif
+{
+	f_criterr = 'A' + deverr & 0xff;
+	f_err = ERR_OTHER;
+	return (0x3);
+}
+#endif
+
+void set_handler(void)                    // initializes handlers
+{
+#if defined(DOS) && !defined(__BORLANDC__)
+	signal(SIGBREAK, my_signalhandler);    // set ctrl-break/-c handlers
+#endif
+	signal(SIGINT, my_signalhandler);
+#if defined(DOS) && !defined(__CONSOLE__) // set hardware error handler
+#ifdef __BORLANDC__
+	harderr(harderrhandler);
+#else
+	_harderr(harderrhandler);
+#endif
+#endif
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packace/unace.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,588 @@
+/* ------------------------------------------------------------------------ */
+/*                                                                          */
+/*      Main file of public UNACE.                                          */
+/*                                                                          */
+/* ------------------------------------------------------------------------ */
+
+
+//--------------- include general files ------------------------------------//
+#include <ctype.h>      // tolower()
+#include <fcntl.h>      // open()
+#include <stdio.h>      // printf() sprintf() remove()
+#include <stdlib.h>     // malloc()
+#include <string.h>     // str*()
+#include <sys/types.h>
+#include <sys/stat.h>   // S_I*  AMIGA: fstat()
+
+#ifdef __OS2__
+#include <io.h>
+#endif
+
+#define DIRSEP	'\\'
+
+#if (!defined(__EMX__) && !defined(__OS2__) && !defined(WINNT) && !defined(WIN32)) ||  defined(__CYGWIN__)
+#include <sys/errno.h>
+#endif
+
+
+//--------------- include unace specific header files ----------------------//
+#include "os.h"
+
+#include "globals.h"
+#include "portable.h"
+#include "uac_comm.h"
+#include "uac_crc.h"
+#include "uac_crt.h"
+#include "uac_dcpr.h"
+#include "uac_sys.h"
+
+#ifdef CRYPT
+ #include "unace_ps.h"
+#endif /* CRYPT */
+int files=0;
+
+//--------------- BEGIN OF UNACE ROUTINES ----------------------------------//
+
+int pipeit(char *format, ...) {
+	/* Do nothing ... perhaps pipe this somewhere in the future */
+	return 0;
+}
+
+void init_unace(void)           // initializes unace
+{
+	buf_rd =malloc(size_rdb * sizeof(ULONG));  // Allocate buffers: increase
+	buf    =malloc(size_buf);                  // sizes when possible to speed
+	buf_wr =malloc(size_wrb);                  // up the program
+	readbuf=malloc(size_headrdb);
+
+	if (buf_rd ==NULL ||
+		buf    ==NULL ||
+		buf_wr ==NULL ||
+		readbuf==NULL )
+		f_err = ERR_MEM;
+
+	make_crctable();             // initialize CRC table
+	dcpr_init();                 // initialize decompression
+
+	set_handler();               // ctrl+break etc.
+}
+
+void done_unace(void)
+{
+	if (buf_rd   ) free(buf_rd   );
+	if (buf      ) free(buf      );
+	if (buf_wr   ) free(buf_wr   );
+	if (readbuf  ) free(readbuf  );
+	if (dcpr_text) free(dcpr_text);
+}
+
+INT  read_header(INT print_err)         // reads any header from archive
+{
+	USHORT rd,
+	head_size,
+	crc_ok;
+	LONG crc;
+	UCHAR *tp=readbuf;
+
+	lseek(archan, skipsize, SEEK_CUR);   // skip ADDSIZE block
+
+	if (read(archan, &head, 4)<4)
+		return (0);                       // read CRC and header size
+
+#ifdef HI_LO_BYTE_ORDER
+	WORDswap(&head.HEAD_CRC);
+	WORDswap(&head.HEAD_SIZE);
+#endif
+	// read size_headrdb bytes into
+	head_size = head.HEAD_SIZE;          // header structure
+	rd = (head_size > size_headrdb) ? size_headrdb : head_size;
+	if (read(archan, readbuf, rd) < rd)
+		return (0);
+	head_size -= rd;
+	crc = getcrc(CRC_MASK, readbuf, rd);
+
+	while (head_size)                    // skip rest of header
+	{
+		rd = (head_size > size_buf) ? size_buf : head_size;
+		if (read(archan, buf, rd) < rd)
+			return (0);
+		head_size -= rd;
+		crc = getcrc(crc, (UCHAR *)buf, rd);
+	}
+
+	head.HEAD_TYPE =*tp++;               // generic buffer to head conversion
+	head.HEAD_FLAGS=BUFP2WORD(tp);
+
+	if (head.HEAD_FLAGS & ACE_ADDSIZE)
+		skipsize = head.ADDSIZE = BUF2LONG(tp);   // get ADDSIZE
+	else
+		skipsize = 0;
+
+	// check header CRC
+	if (!(crc_ok = head.HEAD_CRC == (crc & 0xffff)) && print_err)
+		pipeit("\nError: archive is broken\n");
+	else
+		switch (head.HEAD_TYPE)              // specific buffer to head conversion
+		{
+		case MAIN_BLK:
+			memcpy(mhead.ACESIGN, tp, acesign_len); tp+=acesign_len;
+			mhead.VER_MOD=*tp++;
+			mhead.VER_CR =*tp++;
+			mhead.HOST_CR=*tp++;
+			mhead.VOL_NUM=*tp++;
+			mhead.TIME_CR=BUFP2LONG(tp);
+			mhead.RES1   =BUFP2WORD(tp);
+			mhead.RES2   =BUFP2WORD(tp);
+			mhead.RES    =BUFP2LONG(tp);
+			mhead.AV_SIZE=*tp++;
+			memcpy(mhead.AV, tp, rd-(USHORT)(tp-readbuf));
+			break;
+		case FILE_BLK:
+			fhead.PSIZE     =BUFP2LONG(tp);
+			fhead.SIZE      =BUFP2LONG(tp);
+			fhead.FTIME     =BUFP2LONG(tp);
+			fhead.ATTR      =BUFP2LONG(tp);
+			fhead.CRC32     =BUFP2LONG(tp);
+			fhead.TECH.TYPE =*tp++;
+			fhead.TECH.QUAL =*tp++;
+			fhead.TECH.PARM =BUFP2WORD(tp);
+			fhead.RESERVED  =BUFP2WORD(tp);
+			fhead.FNAME_SIZE=BUFP2WORD(tp);
+			memcpy(fhead.FNAME, tp, rd-(USHORT)(tp-readbuf));
+			break;
+			//    default: (REC_BLK and future things):
+			//              do nothing 'cause isn't needed for extraction
+		}
+
+	return (crc_ok);
+}
+// maximum SFX module size
+#define max_sfx_size 65536      // (needed by read_arc_head)
+
+INT read_arc_head(void)         // searches for the archive header and reads it
+{
+	INT  i,
+	flags,
+	buf_pos = 0;
+	LONG arc_head_pos,
+		old_fpos,
+	fpos = 0;
+	struct stat st;
+
+	fstat(archan, &st);
+
+	memset(buf, 0, size_buf);
+
+#if !defined(__EMX__) && !defined(__OS2__)
+	while (ftell(farchan)<st.st_size && fpos < max_sfx_size)
+#else
+		while (tell(archan)<st.st_size && fpos < max_sfx_size)
+#endif
+		{
+			old_fpos = fpos;
+			fpos += read(archan, &buf[buf_pos], size_buf - buf_pos);
+
+			for (i = 0; i < size_buf; i++)    // look for the acesign
+			{
+				if (!memcmp(acesign, &buf[i], acesign_len))
+				{
+					// seek to the probable begin
+					// of the archive
+					arc_head_pos = old_fpos + i - buf_pos -  bytes_before_acesign;
+					lseek(archan, arc_head_pos, SEEK_SET);
+					if (read_header(0))         // try to read archive header
+					{
+						flags = mhead.HEAD_FLAGS;
+						adat.sol     = (flags & ACE_SOLID) > 0;
+						adat.vol     = (flags & ACE_MULT_VOL) > 0;
+						adat.vol_num = mhead.VOL_NUM;
+						adat.time_cr = mhead.TIME_CR;
+						return (1);
+					}
+				}
+			}
+			// was no archive header,
+			// continue search
+			lseek(archan, fpos, SEEK_SET);
+			memcpy(buf, &buf[size_buf - 512], 512);
+			buf_pos = 512;                    // keep 512 old bytes
+		}
+	return (0);
+}
+
+INT  open_archive(INT print_err)        // opens archive (or volume)
+{
+	CHAR av_str[80];
+
+
+#if defined(__OS2_) || defined(__EMX__) || defined(WIN32)
+	archan = open(aname, O_RDONLY | O_BINARY);   // open file
+#else
+	archan = open(aname, O_RDONLY);   // open file
+#endif
+#if !defined(__EMX__) && !defined(__OS2__)
+	farchan = fdopen(archan, "rb");
+#endif
+	if (archan == -1)
+	{
+		pipeit("\nError opening file %s", aname);
+		return (0);
+	}
+	if (!read_arc_head())                        // read archive header
+	{
+		if (print_err)
+			pipeit("\nInvalid archive file: %s\n", aname);
+#if !defined(__EMX__) && !defined(__OS2__)
+		fclose(farchan);
+#endif
+		close(archan);
+		return (0);
+	}
+
+	pipeit("\nProcessing archive: %s\n\n", aname);
+	if (head.HEAD_FLAGS & ACE_AV)
+	{
+	   pipeit("Authenticity Verification:");   // print the AV
+	   sprintf(av_str, "\ncreated on %d.%d.%d by ",
+			   ts_day(adat.time_cr), ts_month(adat.time_cr), ts_year(adat.time_cr));
+	   pipeit(av_str);
+	   strncpy(av_str, (char *)mhead.AV, mhead.AV_SIZE);
+	   av_str[mhead.AV_SIZE] = 0;
+	   pipeit("%s\n\n", av_str);
+	}
+	comment_out("Main comment:");        // print main comment
+	return (1);
+}
+
+void get_next_volname(void)             // get file name of next volume
+{
+	CHAR *cp;
+	INT  num;
+
+	if ((cp = (CHAR *) strrchr(aname, '.')) == NULL || !*(cp + 1))
+		num = -1;
+	else
+	{
+		cp++;
+		num = (*(cp + 1) - '0') * 10 + *(cp + 2) - '0';
+		if (!in(num, 0, 99))
+			num = -1;
+		if (in(*cp, '0', '9'))
+			num += (*cp - '0') * 100;
+	}
+	num++;
+
+	if (num < 100)
+		*cp = 'C';
+	else
+		*cp = num / 100 + '0';
+	*(cp + 1) = (num / 10) % 10 + '0';
+	*(cp + 2) = num % 10 + '0';
+}
+
+INT  proc_vol(void)                     // opens volume
+{
+	INT  i;
+	CHAR s[80];
+
+	if (!fileexists(aname) || !f_allvol_pr)
+	{
+		do
+		{
+			sprintf(s, "Ready to process %s?", aname);
+#if !defined(__MINGW32__)
+			beep();
+#else
+			beep(500,500);
+#endif
+			i = wrask(s);                  // ask whether ready or not
+			f_allvol_pr = (i == 1);        // "Always" --> process all volumes
+			if (i >= 2)
+			{
+				f_err = ERR_FOUND;
+				return (0);
+			}
+		}
+		while (!fileexists(aname));
+	}
+
+	if (!open_archive(1))                // open volume
+	{
+		pipeit("\nError while opening archive. File not found or archive broken.\n");
+		f_err = ERR_OPEN;
+		return (0);
+	}
+
+	return (1);
+}
+
+INT  proc_next_vol(void)        // opens next volume to process
+{
+#if !defined(__EMX__) && !defined(__OS2__)
+	fclose(farchan);
+#endif
+	close(archan);               // close handle
+	get_next_volname();          // get file name of next volume
+
+	if (!proc_vol())             // try to open volume, read archive header
+		return 0;
+	if (!read_header(1))         // read 2nd header
+	{
+		f_err=ERR_READ;
+		return 0;
+	}
+	return 1;
+}
+
+INT  read_adds_blk(CHAR * buffer, INT len)      // reads part of ADD_SIZE block
+{
+	INT  rd = 0,
+	l = len;
+	LONG i;
+
+#ifdef CRYPT
+	char *cbuffer=buffer;
+
+	if (head.HEAD_TYPE == FILE_BLK && (head.HEAD_FLAGS & ACE_PASSW))
+		len = crypt_len(len);
+#endif /* CRYPT */
+	while (!f_err && len && skipsize)
+	{
+		i = (skipsize > len) ? len : skipsize;
+		skipsize -= i;
+
+		/* How do I check error condition when comping -mno-cygwin? */
+#if !defined(__MINGW32__)
+		errno = 0;
+#endif
+		rd += read(archan, buffer, i);
+#if !defined(__MINGW32__)
+		if (errno)
+		{
+			pipeit("\nRead error\n");
+			f_err = ERR_READ;
+		}
+#endif
+
+		buffer += i;
+		len -= i;
+
+		if (!skipsize)            // if block is continued on next volume
+			if (head.HEAD_FLAGS & ACE_SP_AFTER && !proc_next_vol())
+				break;
+	}
+#ifdef CRYPT
+	if (head.HEAD_TYPE == FILE_BLK && (head.HEAD_FLAGS & ACE_PASSW))
+		decrypt(cbuffer, rd);
+#endif /* CRYPT */
+
+	return (rd > l ? l : rd);
+}
+
+void crc_print(void)            // checks CRC, prints message
+{
+	INT  crc_not_ok = rd_crc != fhead.CRC32;  /* check CRC of file */
+
+	if (!f_err)                  // print message
+	{
+		pipeit(crc_not_ok ? "          CRC-check error" : "          CRC OK");
+		flush;
+	}
+}
+
+void analyze_file(void)         // analyzes one file (for solid archives)
+{
+	pipeit("\n Analyzing");
+	flush;
+	while (!cancel() && (dcpr_adds_blk(buf_wr, size_wrb))) // decompress only
+		;
+	crc_print();
+}
+
+void extract_file(void)         // extracts one file
+{
+	INT  rd;
+
+	pipeit("\n Extracting");
+	flush;                       // decompress block
+	while (!cancel() && (rd = dcpr_adds_blk(buf_wr, size_wrb)))
+	{
+		if (write(wrhan, buf_wr, rd) != rd)       // write block
+		{
+			pipeit("\nWrite error\n");
+			f_err = ERR_WRITE;
+		}
+	}
+	crc_print();
+}
+
+/* extracts or tests all files of the archive
+ */
+void extract_files(int nopath, int test)
+{
+	CHAR file[PATH_MAX];
+
+	while (!cancel() && read_header(1))
+	{
+		if (head.HEAD_TYPE == FILE_BLK)
+		{
+			comment_out("File comment:");   // show file comment
+			ace_fname(file, &head, nopath); // get file name
+			pipeit("\n%s", file);
+			flush;
+			dcpr_init_file();               // initialize decompression of file
+			if (!f_err)
+			{
+				if (test ||
+					(wrhan = create_dest_file(file, (INT) fhead.ATTR))<0)
+				{
+					if (test || adat.sol)
+						analyze_file();        // analyze file
+				}
+				else
+				{
+					extract_file();           // extract it
+#ifdef DOS                               // set file time
+					_dos_setftime(wrhan, (USHORT) (fhead.FTIME >> 16), (USHORT) fhead.FTIME);
+#endif
+					close(wrhan);
+#ifdef DOS                               // set file attributes
+					_dos_setfileattr(file, (UINT) fhead.ATTR);
+#endif
+#ifdef AMIGA
+					{                         // set file date and time
+						struct DateTime dt;
+						char Date[9], Time[9];
+						ULONG tstamp=fhead.FTIME;
+
+						sprintf(Date, "%02d-%02d-%02d", ts_year(tstamp)-1900, ts_month(tstamp), ts_day(tstamp));
+						sprintf(Time, "%02d:%02d:%02d", ts_hour(tstamp), ts_min(tstamp), ts_sec(tstamp));
+
+						dt.dat_Format = FORMAT_INT;
+						dt.dat_Flags  = 0;
+						dt.dat_StrDate= Date;
+						dt.dat_StrTime= Time;
+
+						if (StrToDate(&dt))
+							SetFileDate(file, &dt.dat_Stamp);
+					}
+#endif
+					if (f_err)
+						remove(file);
+				}
+			}
+		}
+	}
+}
+
+unsigned percentage(ULONG p, ULONG d)
+{
+	return (unsigned)( d ? (d/2+p*100)/d : 100 );
+}
+
+void list_files(int verbose)
+{
+	ULONG    size =0,
+	psize=0,
+	tpsize;
+	CHAR     file[PATH_MAX];
+
+	pipeit("Date    |Time |Packed     |Size     |Ratio|File\n");
+
+	while (!cancel() && read_header(1))
+	{
+		if (head.HEAD_TYPE == FILE_BLK)
+		{
+			ULONG ti=fhead.FTIME;
+			ace_fname(file, &head, verbose ? 0 : 1); // get file name
+
+			size  += fhead.SIZE;
+			psize +=
+				tpsize = fhead.PSIZE;
+			files++;
+
+			while (head.HEAD_FLAGS & ACE_SP_AFTER)
+			{
+				skipsize=0;
+				if (!proc_next_vol())
+					break;
+				psize += fhead.PSIZE;
+				tpsize+= fhead.PSIZE;
+			}
+			if (!f_err)
+				pipeit("%02u.%02u.%02u|%02u:%02u|%c%c%9lu|%9lu|%4u%%|%c%s\n",
+					   ts_day (ti), ts_month(ti), ts_year(ti)%100,
+					   ts_hour(ti), ts_min  (ti),
+					   fhead.HEAD_FLAGS & ACE_SP_BEF   ? '<' : ' ',
+					   fhead.HEAD_FLAGS & ACE_SP_AFTER ? '>' : ' ',
+					   tpsize, fhead.SIZE, percentage(tpsize, fhead.SIZE),
+					   fhead.HEAD_FLAGS & ACE_PASSW    ? '*'    : ' ',
+					   file
+					  );
+		}
+	}
+	if (!f_err)
+	{
+		pipeit("\n                 %9lu|%9lu|%4u%%| %u file%s",
+			   psize,
+			   size,
+			   percentage(psize, size),
+			   files,
+			   (char*)(files == 1 ? "" : "s")
+			  );
+	}
+}
+
+void showhelp(void)
+{
+	pipeit("\n"
+		   "Usage: UNACE <command> <archive[.ace]>\n"
+		   "\n"
+		   "Where <command> is one of:\n"
+		   "\n"
+		   "  e   Extract files\n"
+		   "  l   List archive\n"
+		   "  t   Test archive integrity\n"
+		   "  v   List archive (verbose)\n"
+		   "  x   Extract files with full path"
+		  );
+}
+
+int include_unpack(char *bleah)              // processes the archive
+{
+	CHAR *s;
+
+	strcpy(aname, bleah);
+
+	init_unace();                              // initialize unace
+
+	if (!(s = (CHAR *) strrchr(aname, DIRSEP)))
+		s = aname;
+	if (!strrchr(s, '.'))
+		strcat(aname, ".ACE");
+
+	if (open_archive(1))                       // open archive to process
+	{
+		if (adat.vol_num)
+			pipeit("\nFirst volume of archive required!\n");
+		else
+			list_files   (0   );
+
+#if !defined(__EMX__) && !defined(__OS2__)
+		fclose(farchan);
+#endif
+		close(archan);
+		if (f_err)
+		{
+			pipeit("\nError occurred\n");
+			if (f_criterr)
+				pipeit("Critical error on drive %c\n", f_criterr);
+		}
+	}
+	else
+		f_err = ERR_CLINE;
+
+	done_unace();
+	return (f_err);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packinst/packinst.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,206 @@
+/* $Id: packinst.c,v 1.5 2003/11/22 00:50:28 bsmith Exp $ */
+
+/*
+ * include.c (c) 1998-2001 Brian Smith
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#ifndef __UNIX__
+#include <conio.h>
+#include <io.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+
+#ifndef __UNIX__
+#define strcasecmp stricmp
+#endif
+
+/* Handle binary extensions on differnt platforms */
+#ifdef __UNIX__
+#define BINEXT
+#else
+#define BINEXT ".exe"
+#endif
+
+extern int files;
+
+FILE *cfgfile, *installfile;
+char *INSTALLER_APPLICATION;
+char *INSTALLER_VERSION;
+char *INSTALLER_TITLE;
+char *INSTALLER_PATH;
+char *INSTALLER_FOLDER;
+char *INSTALLER_PROGRAM;
+char *INSTALLER_SHADOW;
+char *INSTALLER_OBJECT;
+char *INSTALLER_SETS;
+char *INSTALLER_SYSVAR;
+char *INSTALLER_SYSLINE;
+char *INSTALLER_PACKAGES[20];
+char *INSTALLER_CONFIRM_WPS;
+char *INSTALLER_CONFIRM_CONFIGSYS;
+char *INSTALLER_CONFIRM_OVERWRITE;
+int INSTALLER_BITMAP_WIDTH;
+int INSTALLER_BITMAP_HEIGHT;
+int INSTALLER_PACKAGE_COUNT=0;
+
+int packagefiles[20];
+char *packagefilename[20];
+
+void resetglobals(void);
+
+int include_unpack(char *aname);
+
+void append_file(char *filename)
+{
+   FILE *appendfile;
+   int amnt;
+   char buffer[512];
+
+   if((appendfile = fopen(filename, "rb"))==NULL)
+      {
+         printf("Error opening %s for reading!\n", filename);
+         exit(3);
+      }
+   while(!feof(appendfile))
+      {
+         amnt = fread(buffer, 1, 512, appendfile);
+         fwrite(buffer, 1, amnt, installfile);
+      }
+   fclose(appendfile);
+}
+
+void getline(FILE *f, char *entry, char *entrydata)
+{
+char in[4096];
+int z;
+
+    memset(in, 0, 4096);
+    fgets(in, 4095, f);
+
+    if(in[strlen(in)-1] == '\n')
+       in[strlen(in)-1] = 0;
+
+    if(in[0] != '#')
+       {
+       for(z=0;z<strlen(in);z++)
+           {
+              if(in[z] == '=')
+                 {
+                    in[z] = 0;
+                    strcpy(entry, in);
+                    strcpy(entrydata, &in[z+1]);
+                    return;
+                 }
+           }
+      }
+   strcpy(entry, "");
+   strcpy(entrydata, "");
+}
+
+int main(int argc, char *argv[])
+{
+   char entry[8096], entrydata[8096];
+   int z;
+
+   printf("Packinst- version 2.1 (c) 1999-2003 DBSoft\n\n");
+   if(argc!=2)
+      {
+         printf("Usage: Packinst <filename.cfg>\n");
+         exit(1);
+      }
+   if((cfgfile = fopen(argv[1], "r"))==NULL)
+      {
+         printf("Error opening config file \"%s\"!\n", argv[1]);
+         exit(2);
+      }
+   if((installfile = fopen("install" BINEXT, "wb"))==NULL)
+      {
+         printf("Error opening install" BINEXT " for writing!\n");
+         exit(3);
+      }
+#if 0
+   printf("Adding resources to sfx" BINEXT "...\n");
+   system("rc install.rc sfx" BINEXT " > NUL");
+#endif
+   printf("Creating installer...\n");
+   append_file("sfx" BINEXT);
+   fwrite("DBSOFT-HEADER", 1, 13, installfile);
+   while(!feof(cfgfile))
+      {
+        getline(cfgfile, entry, entrydata);
+        if(strcasecmp(entry, "INSTALLER_APPLICATION") == 0)
+           INSTALLER_APPLICATION = (char *)strdup(entrydata);
+        if(strcasecmp(entry, "INSTALLER_VERSION") == 0)
+           INSTALLER_VERSION = (char *)strdup(entrydata);
+        if(strcasecmp(entry, "INSTALLER_TITLE") == 0)
+           INSTALLER_TITLE = (char *)strdup(entrydata);
+        if(strcasecmp(entry, "INSTALLER_PATH") == 0)
+           INSTALLER_PATH = (char *)strdup(entrydata);
+        if(strcasecmp(entry, "INSTALLER_FOLDER") == 0)
+           INSTALLER_FOLDER = (char *)strdup(entrydata);
+        if(strcasecmp(entry, "INSTALLER_PROGRAM") == 0)
+           INSTALLER_PROGRAM = (char *)strdup(entrydata);
+        if(strcasecmp(entry, "INSTALLER_SHADOW") == 0)
+           INSTALLER_SHADOW = (char *)strdup(entrydata);
+        if(strcasecmp(entry, "INSTALLER_OBJECT") == 0)
+           INSTALLER_OBJECT = (char *)strdup(entrydata);
+        if(strcasecmp(entry, "INSTALLER_SETS") == 0)
+           INSTALLER_SETS = (char *)strdup(entrydata);
+        if(strcasecmp(entry, "INSTALLER_SYSVAR") == 0)
+           INSTALLER_SYSVAR = (char *)strdup(entrydata);
+        if(strcasecmp(entry, "INSTALLER_SYSLINE") == 0)
+           INSTALLER_SYSLINE = (char *)strdup(entrydata);
+        if(strcasecmp(entry, "INSTALLER_CONFIRM_WPS") == 0)
+           INSTALLER_CONFIRM_WPS = (char *)strdup(entrydata);
+        if(strcasecmp(entry, "INSTALLER_CONFIRM_CONFIGSYS") == 0)
+           INSTALLER_CONFIRM_CONFIGSYS = (char *)strdup(entrydata);
+        if(strcasecmp(entry, "INSTALLER_CONFIRM_OVERWRITE") == 0)
+           INSTALLER_CONFIRM_OVERWRITE = (char *)strdup(entrydata);
+        if(strcasecmp(entry, "INSTALLER_PACKAGE") == 0)
+           {
+              for(z=0;z<strlen(entrydata);z++)
+                 {
+                    if(entrydata[z] == ',')
+                       {
+                          entrydata[z] = 0;
+                          packagefilename[INSTALLER_PACKAGE_COUNT] = (char *)strdup(entrydata);
+                          INSTALLER_PACKAGES[INSTALLER_PACKAGE_COUNT] = (char *)strdup(&entrydata[z+1]);
+                       }
+                 }
+              resetglobals();
+              files=0;
+              include_unpack(packagefilename[INSTALLER_PACKAGE_COUNT]);
+              packagefiles[INSTALLER_PACKAGE_COUNT] = files;
+              INSTALLER_PACKAGE_COUNT++;
+           }
+      }
+   fclose(cfgfile);
+   fprintf(installfile, "%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%d",
+		   INSTALLER_APPLICATION, INSTALLER_VERSION, INSTALLER_TITLE,
+		   INSTALLER_PATH, INSTALLER_FOLDER, INSTALLER_PROGRAM,
+		   INSTALLER_SHADOW, INSTALLER_OBJECT, INSTALLER_SETS, INSTALLER_SYSVAR,
+		   INSTALLER_SYSLINE, INSTALLER_CONFIRM_WPS, INSTALLER_CONFIRM_CONFIGSYS,
+		   INSTALLER_CONFIRM_OVERWRITE, INSTALLER_PACKAGE_COUNT);
+   for(z=0;z<INSTALLER_PACKAGE_COUNT;z++)
+      fprintf(installfile, "-%s", INSTALLER_PACKAGES[z]);
+   fwrite("~", 1, 1, installfile);
+   for(z=0;z<INSTALLER_PACKAGE_COUNT;z++)
+      {
+         struct stat blah;
+
+         stat(packagefilename[z], &blah);
+         fprintf(installfile, "DBSOFT-ACE%d%d-%lu~", z, packagefiles[z], blah.st_size);
+         append_file(packagefilename[z]);
+         printf("Package: %s - %d files in %s (%lu bytes).\n", INSTALLER_PACKAGES[z], packagefiles[z], packagefilename[z], blah.st_size);
+      }
+   fclose(installfile);
+   fclose(cfgfile);
+#ifdef __UNIX__
+   chmod("install" BINEXT,  S_IRWXU);
+#endif
+   return 0;
+   }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/Makefile.in	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,146 @@
+#==============================================================================
+# Makefile for UnZip, UnZipSFX and fUnZip:  Unix and MS-DOS ("real" makes only)
+# Version:  5.4                                                19 November 1998
+#==============================================================================
+
+
+# INSTRUCTIONS (such as they are):
+#
+# "make sunos"	-- makes UnZip in current directory on a generic SunOS 4.x Sun
+# "make list"	-- lists all supported systems (targets)
+# "make help"	-- provides pointers on what targets to try if problems occur
+# "make wombat" -- chokes and dies if you haven't added the specifics for your
+#		    Wombat 68000 (or whatever) to the systems list
+#
+# CF are flags for the C compiler.  LF are flags for the loader.  LF2 are more
+# flags for the loader, if they need to be at the end of the line instead of at
+# the beginning (for example, some libraries).  FL and FL2 are the corre-
+# sponding flags for fUnZip.  LOCAL_UNZIP is an environment variable that can
+# be used to add default C flags to your compile without editing the Makefile
+# (e.g., -DDEBUG_STRUC, or -FPi87 on PCs using Microsoft C).
+#
+# Some versions of make do not define the macro "$(MAKE)"; this is rare, but
+# if things don't work, try using "make" instead of "$(MAKE)" in your system's
+# makerule.  Or try adding the following line to your .login file:
+#	setenv MAKE "make"
+# (That never works--makes that are too stupid to define MAKE are also too
+# stupid to look in the environment--but try it anyway for kicks. :-) )
+#
+# Memcpy and memset are provided for those systems that don't have them; they
+# are in fileio.c and will be used if -DZMEM is included in CF.  These days
+# almost all systems have them.
+#
+# Be sure to test your new UnZip (and UnZipSFX and fUnZip); successful compila-
+# tion does not always imply a working program.
+
+
+#####################
+# MACRO DEFINITIONS #
+#####################
+
+# Defaults most systems use (use LOCAL_UNZIP in environment to add flags,
+# such as -DDOSWILD).
+
+# UnZip flags
+CC = cc#	try using "gcc" target rather than changing this (CC and LD
+LD = $(CC)#	must match, else "unresolved symbol:  ___main" is possible)
+AS = as
+LOC = $(LOCAL_UNZIP)
+AF = $(LOC)
+CF = -O -I. -I.. -I../inczip -D__UNIX__ $(LOC)
+LF = -o packinst
+LF2 = -s
+
+# general-purpose stuff
+#CP = cp
+CP = ln
+LN = ln
+RM = rm -f
+CHMOD = chmod
+BINPERMS = 755
+MANPERMS = 644
+STRIP = strip
+E =
+O = .o
+M = unix
+SHELL = /bin/sh
+
+# defaults for crc32 stuff and system dependent headers
+CRC32 = crc32
+
+# object files
+OBJS1 = unzip$O $(CRC32)$O crctab$O crypt$O envargs$O explode$O
+OBJS2 = extract$O fileio$O globals$O inflate$O list$O match$O
+OBJS3 = process$O ttyio$O unreduce$O unshrink$O zipinfo$O
+OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O packinst$O
+#OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O install$O wxmain$O instsup$O
+UNZIP_H = ../inczip/unzip.h ../inczip/unzpriv.h ../inczip/globals.h
+
+# installation
+# (probably can change next two to `install' and `install -d' if you have it)
+INSTALL = cp
+INSTALL_D = mkdir -p
+
+###############################################
+# BASIC COMPILE INSTRUCTIONS AND DEPENDENCIES #
+###############################################
+
+# this is for GNU make; comment out and notify zip-bugs if it causes errors
+.SUFFIXES:	.c .o .obj .pic.o
+
+# yes, we should be able to use the $O macro to combine these two, but it
+# fails on some brain-damaged makes (e.g., AIX's)...no big deal
+.c.o:
+	$(CC) -c $(CF) $*.c
+
+.c.obj:
+	$(CC) -c $(CF) $*.c
+
+.c.pic.o:
+	$(CC) -c $(CF) -o $@ $*.c
+
+all:	        sfx
+
+
+# EDIT HERE FOR PARALLEL MAKES on Sequent (and others?)--screws up MS-DOS
+# make utilities if default:  change "unzip$E:" to "unzip$E:&"
+
+sfx$E:	$(OBJS)			# add `&' for parallel makes
+	$(LD) $(LF) $(OBJS)
+
+crc32$O:	crc32.c $(UNZIP_H) ../inczip/zip.h
+crctab$O:	crctab.c $(UNZIP_H)  ../inczip/zip.h
+crypt$O:	crypt.c $(UNZIP_H)  ../inczip/zip.h  ../inczip/crypt.h  ../inczip/ttyio.h
+envargs$O:	envargs.c $(UNZIP_H)
+explode$O:	explode.c $(UNZIP_H)
+extract$O:	extract.c $(UNZIP_H)  ../inczip/crypt.h
+fileio$O:	fileio.c $(UNZIP_H)  ../inczip/crypt.h  ../inczip/ttyio.h  ../inczip/ebcdic.h
+funzip$O:	funzip.c $(UNZIP_H)  ../inczip/crypt.h  ../inczip/ttyio.h  ../inczip/tables.h
+globals$O:	globals.c $(UNZIP_H)
+inflate$O:	inflate.c  ../inczip/inflate.h $(UNZIP_H)
+list$O:		list.c $(UNZIP_H)
+match$O:	match.c $(UNZIP_H)
+process$O:	process.c $(UNZIP_H)
+ttyio$O:	ttyio.c $(UNZIP_H)  ../inczip/zip.h  ../inczip/crypt.h  ../inczip/ttyio.h
+unreduce$O:	unreduce.c $(UNZIP_H)
+unshrink$O:	unshrink.c $(UNZIP_H)
+unzip$O:	unzip.c $(UNZIP_H)  ../inczip/crypt.h  ../inczip/version.h  ../inczip/consts.h
+zipinfo$O:	zipinfo.c $(UNZIP_H)
+
+unix$O:		unix.c $(UNZIP_H)  ../inczip/version.h		# Unix only
+	$(CC) -c $(CF)  unix.c
+
+packinst$O:		../packinst/packinst.c	      
+	$(CC) -c $(CF)  ../packinst/packinst.c
+
+#install$O:		../install.c	      
+#	$(CC) -c $(CF)  ../install.c
+#
+#unix$O:		../wxmain.cpp
+#	$(CC) -c $(CF)  ../wxmain.cpp
+#
+#unix$O:	        ../instsup.cpp 
+#	$(CC) -c $(CF)  ../instsup.cpp
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/api.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,601 @@
+/*---------------------------------------------------------------------------
+
+  api.c
+
+  This module supplies an UnZip engine for use directly from C/C++
+  programs.  The functions are:
+
+    UzpVer *UzpVersion(void);
+    void UzpVersion2(UzpVer2 *version)
+    int UzpMain(int argc, char *argv[]);
+    int UzpAltMain(int argc, char *argv[], UzpInit *init);
+    int UzpValidate(char *archive, int AllCodes);
+    void UzpFreeMemBuffer(UzpBuffer *retstr);
+    int UzpUnzipToMemory(char *zip, char *file, UzpOpts *optflgs,
+                         UzpCB *UsrFuncts, UzpBuffer *retstr);
+
+  non-WINDLL only (a special WINDLL variant is defined in windll/windll.c):
+    int UzpGrep(char *archive, char *file, char *pattern, int cmd, int SkipBin,
+                UzpCB *UsrFuncts);
+
+  OS/2 only (for now):
+    int UzpFileTree(char *name, cbList(callBack), char *cpInclude[],
+          char *cpExclude[]);
+
+  You must define `DLL' in order to include the API extensions.
+
+  ---------------------------------------------------------------------------*/
+
+
+#ifdef OS2
+#  define  INCL_DOSMEMMGR
+#  include <os2.h>
+#endif
+#include <setjmp.h>
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#include "version.h"
+#ifdef WINDLL
+#  include "windll/windll.h"
+#endif
+
+#ifdef DLL      /* This source file supplies DLL-only interface code. */
+
+jmp_buf dll_error_return;
+
+/*---------------------------------------------------------------------------
+    Documented API entry points
+  ---------------------------------------------------------------------------*/
+
+
+UzpVer * UZ_EXP UzpVersion()   /* should be pointer to const struct */
+{
+    static UzpVer version;     /* doesn't change between calls */
+
+
+    version.structlen = UZPVER_LEN;
+
+#ifdef BETA
+    version.flag = 1;
+#else
+    version.flag = 0;
+#endif
+    version.betalevel = BETALEVEL;
+    version.date = VERSION_DATE;
+
+#ifdef ZLIB_VERSION
+    version.zlib_version = ZLIB_VERSION;
+    version.flag |= 2;
+#else
+    version.zlib_version = NULL;
+#endif
+
+    /* someday each of these may have a separate patchlevel: */
+    version.unzip.major = UZ_MAJORVER;
+    version.unzip.minor = UZ_MINORVER;
+    version.unzip.patchlevel = PATCHLEVEL;
+
+    version.zipinfo.major = ZI_MAJORVER;
+    version.zipinfo.minor = ZI_MINORVER;
+    version.zipinfo.patchlevel = PATCHLEVEL;
+
+    /* these are retained for backward compatibility only: */
+    version.os2dll.major = UZ_MAJORVER;
+    version.os2dll.minor = UZ_MINORVER;
+    version.os2dll.patchlevel = PATCHLEVEL;
+
+    version.windll.major = UZ_MAJORVER;
+    version.windll.minor = UZ_MINORVER;
+    version.windll.patchlevel = PATCHLEVEL;
+
+    return &version;
+}
+
+void UZ_EXP UzpVersion2(UzpVer2 *version)
+{
+
+    version->structlen = UZPVER_LEN;
+
+#ifdef BETA
+    version->flag = 1;
+#else
+    version->flag = 0;
+#endif
+    strcpy(version->betalevel, BETALEVEL);
+    strcpy(version->date, VERSION_DATE);
+
+#ifdef ZLIB_VERSION
+    strcpy(version->zlib_version, ZLIB_VERSION);
+    version->flag |= 2;
+#else
+    version->zlib_version[0] = '\0';
+#endif
+
+    /* someday each of these may have a separate patchlevel: */
+    version->unzip.major = UZ_MAJORVER;
+    version->unzip.minor = UZ_MINORVER;
+    version->unzip.patchlevel = PATCHLEVEL;
+
+    version->zipinfo.major = ZI_MAJORVER;
+    version->zipinfo.minor = ZI_MINORVER;
+    version->zipinfo.patchlevel = PATCHLEVEL;
+
+    /* these are retained for backward compatibility only: */
+    version->os2dll.major = UZ_MAJORVER;
+    version->os2dll.minor = UZ_MINORVER;
+    version->os2dll.patchlevel = PATCHLEVEL;
+
+    version->windll.major = UZ_MAJORVER;
+    version->windll.minor = UZ_MINORVER;
+    version->windll.patchlevel = PATCHLEVEL;
+}
+
+
+
+
+
+#ifndef WINDLL
+
+int UZ_EXP UzpAltMain(int argc, char *argv[], UzpInit *init)
+{
+    int r, (*dummyfn)();
+
+
+    CONSTRUCTGLOBALS();
+
+    if (init->structlen >= (sizeof(ulg) + sizeof(dummyfn)) && init->msgfn)
+        G.message = init->msgfn;
+
+    if (init->structlen >= (sizeof(ulg) + 2*sizeof(dummyfn)) && init->inputfn)
+        G.input = init->inputfn;
+
+    if (init->structlen >= (sizeof(ulg) + 3*sizeof(dummyfn)) && init->pausefn)
+        G.mpause = init->pausefn;
+
+    if (init->structlen >= (sizeof(ulg) + 4*sizeof(dummyfn)) && init->userfn)
+        (*init->userfn)();    /* allow void* arg? */
+
+    r = unzip(__G__ argc, argv);
+    DESTROYGLOBALS()
+    RETURN(r);
+}
+
+#endif /* !WINDLL */
+
+
+
+
+#ifndef __16BIT__
+
+void UZ_EXP UzpFreeMemBuffer(UzpBuffer *retstr)
+{
+    if (retstr->strptr != NULL) {
+        free(retstr->strptr);
+        retstr->strptr = NULL;
+    }
+}
+
+
+
+
+#ifndef WINDLL
+
+static int UzpDLL_Init OF((zvoid *pG, UzpCB *UsrFuncts));
+
+static int UzpDLL_Init(pG, UsrFuncts)
+zvoid *pG;
+UzpCB *UsrFuncts;
+{
+    int (*dummyfn)();
+
+    if (UsrFuncts->structlen >= (sizeof(ulg) + sizeof(dummyfn)) &&
+        UsrFuncts->msgfn)
+        ((Uz_Globs *)pG)->message = UsrFuncts->msgfn;
+    else
+        return FALSE;
+
+    if (UsrFuncts->structlen >= (sizeof(ulg) + 2*sizeof(dummyfn)) &&
+        UsrFuncts->inputfn)
+        ((Uz_Globs *)pG)->input = UsrFuncts->inputfn;
+
+    if (UsrFuncts->structlen >= (sizeof(ulg) + 3*sizeof(dummyfn)) &&
+        UsrFuncts->pausefn)
+        ((Uz_Globs *)pG)->mpause = UsrFuncts->pausefn;
+
+    if (UsrFuncts->structlen >= (sizeof(ulg) + 4*sizeof(dummyfn)) &&
+        UsrFuncts->passwdfn)
+        ((Uz_Globs *)pG)->decr_passwd = UsrFuncts->passwdfn;
+
+    if (UsrFuncts->structlen >= (sizeof(ulg) + 5*sizeof(dummyfn)) &&
+        UsrFuncts->statrepfn)
+        ((Uz_Globs *)pG)->statreportcb = UsrFuncts->statrepfn;
+
+    return TRUE;
+}
+
+
+int UZ_EXP UzpUnzipToMemory(char *zip, char *file, UzpOpts *optflgs,
+    UzpCB *UsrFuncts, UzpBuffer *retstr)
+{
+    int r;
+#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
+    char *intern_zip, *intern_file;
+#endif
+
+    CONSTRUCTGLOBALS();
+#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
+    intern_zip = (char *)malloc(strlen(zip)+1);
+    if (intern_zip == NULL) {
+       DESTROYGLOBALS()
+       return PK_MEM;
+    }
+    intern_file = (char *)malloc(strlen(file)+1);
+    if (intern_file == NULL) {
+       DESTROYGLOBALS()
+       free(intern_zip);
+       return PK_MEM;
+    }
+    ISO_TO_INTERN(zip, intern_zip);
+    ISO_TO_INTERN(file, intern_file);
+#   define zip intern_zip
+#   define file intern_file
+#endif
+    /* Copy those options that are meaningful for UzpUnzipToMemory, instead of
+     * a simple "memcpy(G.UzO, optflgs, sizeof(UzpOpts));"
+     */
+    uO.pwdarg = optflgs->pwdarg;
+    uO.aflag = optflgs->aflag;
+    uO.C_flag = optflgs->C_flag;
+    uO.qflag = optflgs->qflag;  /* currently,  overridden in unzipToMemory */
+
+    if (!UzpDLL_Init((zvoid *)&G, UsrFuncts)) {
+       DESTROYGLOBALS();
+       return PK_BADERR;
+    }
+    G.redirect_data = 1;
+
+    r = (unzipToMemory(__G__ zip, file, retstr) <= PK_WARN);
+
+    DESTROYGLOBALS()
+#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
+#  undef file
+#  undef zip
+    free(intern_file);
+    free(intern_zip);
+#endif
+    if (!r && retstr->strlength) {
+       free(retstr->strptr);
+       retstr->strptr = NULL;
+    }
+    return r;
+}
+#endif /* !WINDLL */
+#endif /* !__16BIT__ */
+
+
+
+
+
+#ifdef OS2DLL
+
+int UZ_EXP UzpFileTree(char *name, cbList(callBack), char *cpInclude[],
+                char *cpExclude[])
+{
+    int r;
+
+    CONSTRUCTGLOBALS();
+    uO.qflag = 2;
+    uO.vflag = 1;
+    uO.C_flag = 1;
+    G.wildzipfn = name;
+    G.process_all_files = TRUE;
+    if (cpInclude) {
+        char **ptr = cpInclude;
+
+        while (*ptr != NULL) ptr++;
+        G.filespecs = ptr - cpInclude;
+        G.pfnames = cpInclude, G.process_all_files = FALSE;
+    }
+    if (cpExclude) {
+        char **ptr = cpExclude;
+
+        while (*ptr != NULL) ptr++;
+        G.xfilespecs = ptr - cpExclude;
+        G.pxnames = cpExclude, G.process_all_files = FALSE;
+    }
+
+    G.processExternally = callBack;
+    r = process_zipfiles(__G)==0;
+    DESTROYGLOBALS()
+    return r;
+}
+
+#endif /* OS2DLL */
+
+
+
+
+/*---------------------------------------------------------------------------
+    Helper functions
+  ---------------------------------------------------------------------------*/
+
+
+void setFileNotFound(__G)
+    __GDEF
+{
+    G.filenotfound++;
+}
+
+
+
+int unzipToMemory(__GPRO__ char *zip, char *file, UzpBuffer *retstr)
+{
+    int r;
+    char *incname[2];
+
+    G.process_all_files = FALSE;
+    G.extract_flag = TRUE;
+    uO.qflag = 2;
+    G.wildzipfn = zip;
+
+    G.pfnames = incname;
+    incname[0] = file;
+    incname[1] = NULL;
+    G.filespecs = 1;
+
+    r = process_zipfiles(__G);
+    if (retstr) {
+        retstr->strptr = (char *)G.redirect_buffer;
+        retstr->strlength = G.redirect_size;
+    }
+    return r;                   /* returns `PK_???' error values */
+}
+
+
+
+int redirect_outfile(__G)
+     __GDEF
+{
+    if (G.redirect_size != 0 || G.redirect_buffer != NULL)
+        return FALSE;
+
+#ifndef NO_SLIDE_REDIR
+    G.redirect_slide = !G.pInfo->textmode;
+#endif
+    G.redirect_size = (G.pInfo->textmode ?
+                       G.lrec.ucsize * lenEOL : G.lrec.ucsize);
+#ifdef OS2
+    DosAllocMem((void **)&G.redirect_buffer, G.redirect_size+1,
+      PAG_READ|PAG_WRITE|PAG_COMMIT);
+    G.redirect_pointer = G.redirect_buffer;
+#else
+#ifdef __16BIT__
+    if ((ulg)((extent)G.redirect_size) != G.redirect_size)
+        return FALSE;
+#endif
+    G.redirect_pointer = G.redirect_buffer = malloc(G.redirect_size+1);
+#endif
+    if (!G.redirect_buffer)
+        return FALSE;
+    G.redirect_pointer[G.redirect_size] = '\0';
+    return TRUE;
+}
+
+
+
+int writeToMemory(__GPRO__ uch *rawbuf, ulg size)
+{
+    if (rawbuf != G.redirect_pointer)
+        memcpy(G.redirect_pointer,rawbuf,size);
+    G.redirect_pointer += size;
+    return 0;
+}
+
+
+
+
+int close_redirect(__G)
+     __GDEF
+{
+    if (G.pInfo->textmode) {
+        *G.redirect_pointer = '\0';
+        G.redirect_size = G.redirect_pointer - G.redirect_buffer;
+        if ((G.redirect_buffer =
+             realloc(G.redirect_buffer, G.redirect_size + 1)) == NULL) {
+            G.redirect_size = 0;
+            return EOF;
+        }
+    }
+    return 0;
+}
+
+
+
+
+#ifndef __16BIT__
+#ifndef WINDLL
+
+/* Purpose: Determine if file in archive contains the string szSearch
+
+   Parameters: archive  = archive name
+               file     = file contained in the archive. This cannot be
+                          a wild card to be meaningful
+               pattern  = string to search for
+               cmd      = 0 - case-insensitive search
+                          1 - case-sensitve search
+                          2 - case-insensitive, whole words only
+                          3 - case-sensitive, whole words only
+               SkipBin  = if true, skip any files that have control
+                          characters other than CR, LF, or tab in the first
+                          100 characters.
+
+   Returns:    TRUE if a match is found
+               FALSE if no match is found
+               -1 on error
+
+   Comments: This does not pretend to be as useful as the standard
+             Unix grep, which returns the strings associated with a
+             particular pattern, nor does it search past the first
+             matching occurrence of the pattern.
+ */
+
+int UZ_EXP UzpGrep(char *archive, char *file, char *pattern, int cmd,
+                   int SkipBin, UzpCB *UsrFuncts)
+{
+    int retcode = FALSE, compare;
+    ulg i, j, patternLen, buflen;
+    char * sz, *p;
+    UzpOpts flgopts;
+    UzpBuffer retstr;
+
+    memzero(&flgopts, sizeof(UzpOpts));         /* no special options */
+
+    if (!UzpUnzipToMemory(archive, file, &flgopts, UsrFuncts, &retstr)) {
+       return -1;   /* not enough memory, file not found, or other error */
+    }
+
+    if (SkipBin) {
+        if (retstr.strlength < 100)
+            buflen = retstr.strlength;
+        else
+            buflen = 100;
+        for (i = 0; i < buflen; i++) {
+            if (iscntrl(retstr.strptr[i])) {
+                if ((retstr.strptr[i] != 0x0A) &&
+                    (retstr.strptr[i] != 0x0D) &&
+                    (retstr.strptr[i] != 0x09))
+                {
+                    /* OK, we now think we have a binary file of some sort */
+                    free(retstr.strptr);
+                    return FALSE;
+                }
+            }
+        }
+    }
+
+    patternLen = strlen(pattern);
+
+    if (retstr.strlength < patternLen) {
+        free(retstr.strptr);
+        return FALSE;
+    }
+
+    sz = malloc(patternLen + 3); /* add two in case doing whole words only */
+    if (cmd > 1) {
+        strcpy(sz, " ");
+        strcat(sz, pattern);
+        strcat(sz, " ");
+    } else
+        strcpy(sz, pattern);
+
+    if ((cmd == 0) || (cmd == 2)) {
+        for (i = 0; i < strlen(sz); i++)
+            sz[i] = toupper(sz[i]);
+        for (i = 0; i < retstr.strlength; i++)
+            retstr.strptr[i] = toupper(retstr.strptr[i]);
+    }
+
+    for (i = 0; i < (retstr.strlength - patternLen); i++) {
+        p = &retstr.strptr[i];
+        compare = TRUE;
+        for (j = 0; j < patternLen; j++) {
+            /* We cannot do strncmp here, as we may be dealing with a
+             * "binary" file, such as a word processing file, or perhaps
+             * even a true executable of some sort. */
+            if (p[j] != sz[j]) {
+                compare = FALSE;
+                break;
+            }
+        }
+        if (compare == TRUE) {
+            retcode = TRUE;
+            break;
+        }
+    }
+
+    free(sz);
+    free(retstr.strptr);
+
+    return retcode;
+}
+#endif /* !WINDLL */
+#endif /* !__16BIT__ */
+
+
+
+
+int UZ_EXP UzpValidate(char *archive, int AllCodes)
+{
+    int retcode;
+    CONSTRUCTGLOBALS();
+
+    uO.jflag = 1;
+    uO.tflag = 1;
+    uO.overwrite_none = 0;
+    G.extract_flag = (!uO.zipinfo_mode &&
+                      !uO.cflag && !uO.tflag && !uO.vflag && !uO.zflag
+#ifdef TIMESTAMP
+                      && !uO.T_flag
+#endif
+                     );
+
+    uO.qflag = 2;                        /* turn off all messages */
+    G.fValidate = TRUE;
+    G.pfnames = (char **)&fnames[0];    /* assign default filename vector */
+#ifdef WINDLL
+    Wiz_NoPrinting(TRUE);
+#endif
+
+    if (archive == NULL) {      /* something is screwed up:  no filename */
+        DESTROYGLOBALS();
+        return PK_NOZIP;
+    }
+
+    G.wildzipfn = (char *)malloc(FILNAMSIZ + 1);
+    strcpy(G.wildzipfn, archive);
+#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
+    _ISO_INTERN(G.wildzipfn);
+#endif
+
+    G.process_all_files = TRUE;         /* for speed */
+
+    retcode = setjmp(dll_error_return);
+
+    if (retcode) {
+#ifdef WINDLL
+        Wiz_NoPrinting(FALSE);
+#endif
+        free(G.wildzipfn);
+        DESTROYGLOBALS();
+        return PK_BADERR;
+    }
+
+    retcode = process_zipfiles(__G);
+
+    free(G.wildzipfn);
+#ifdef WINDLL
+    Wiz_NoPrinting(FALSE);
+#endif
+    DESTROYGLOBALS();
+
+    /* PK_WARN == 1 and PK_FIND == 11. When we are just looking at an
+       archive, we should still be able to see the files inside it,
+       even if we can't decode them for some reason.
+
+       We also still want to be able to get at files even if there is
+       something odd about the zip archive, hence allow PK_WARN,
+       PK_FIND, IZ_UNSUP as well as PK_ERR
+     */
+
+    if (AllCodes)
+        return retcode;
+
+    if ((retcode == PK_OK) || (retcode == PK_WARN) || (retcode == PK_ERR) ||
+        (retcode == IZ_UNSUP) || (retcode == PK_FIND))
+        return TRUE;
+    else
+        return FALSE;
+}
+
+#endif /* DLL */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/apihelp.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,147 @@
+/* apihelp.c */
+
+#ifdef API_DOC
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#include "version.h"
+
+
+APIDocStruct APIDoc[] = {
+    {
+        "UZPVERSION"  , "UzpVersion"  ,
+        "UzpVer *UzpVersion(void);",
+        "Get version numbers of the API and the underlying UnZip code.\n\n"
+        "\t\tThis is used for comparing the version numbers of the run-time\n"
+        "\t\tDLL code with those expected from the unzip.h at compile time.\n"
+        "\t\tIf the version numbers do not match, there may be compatibility\n"
+        "\t\tproblems with further use of the DLL.\n\n"
+        "  Example:\t/* Check the major version number of the DLL code. */\n"
+        "\t\tUzpVer *pVersion;\n"
+        "\t\tpVersion = UzpVersion();\n"
+        "\t\tif (pVersion->unzip.major != UZ_MAJORVER)\n"
+        "\t\t  fprintf(stderr, \"error: using wrong version of DLL\\n\");\n\n"
+        "\t\tSee unzip.h for details and unzipstb.c for an example.\n"
+    },
+
+    {
+        "UZPMAIN"  , "UzpMain"  ,
+        "int UzpMain(int argc, char *argv[]);",
+        "Provide a direct entry point to the command line interface.\n\n"
+        "\t\tThis is used by the UnZip stub but you can use it in your\n"
+        "\t\town program as well.  Output is sent to stdout.\n"
+        "\t\t0 on return indicates success.\n\n"
+        "  Example:\t/* Extract 'test.zip' silently, junking paths. */\n"
+        "\t\tchar *argv[] = { \"-q\", \"-j\", \"test.zip\" };\n"
+        "\t\tint argc = 3;\n"
+        "\t\tif (UzpMain(argc,argv))\n"
+        "\t\t  printf(\"error: unzip failed\\n\");\n\n"
+        "\t\tSee unzip.h for details.\n"
+    },
+
+    {
+        "UZPALTMAIN"  , "UzpAltMain"  ,
+        "int UzpAltMain(int argc, char *argv[], UzpInit *init);",
+        "Provide a direct entry point to the command line interface,\n"
+        "optionally installing replacement I/O handler functions.\n\n"
+        "\t\tAs with UzpMain(), output is sent to stdout by default.\n"
+        "\t\t`InputFn *inputfn' is not yet implemented.  0 on return\n"
+        "\t\tindicates success.\n\n"
+        "  Example:\t/* Replace normal output and `more' functions. */\n"
+        "\t\tchar *argv[] = { \"-q\", \"-j\", \"test.zip\" };\n"
+        "\t\tint argc = 3;\n"
+        "\t\tUzpInit init = { 16, MyMessageFn, NULL, MyPauseFn };\n"
+        "\t\tif (UzpAltMain(argc,argv,&init))\n"
+        "\t\t  printf(\"error: unzip failed\\n\");\n\n"
+        "\t\tSee unzip.h for details.\n"
+    },
+
+    {
+        "UZPUNZIPTOMEMORY", "UzpUnzipToMemory",
+        "int UzpUnzipToMemory(char *zip, char *file, UzpBuffer *retstr);",
+        "Pass the name of the zip file and the name of the file\n"
+        "\t\tyou wish to extract.  UzpUnzipToMemory will create a\n"
+        "\t\tbuffer and return it in *retstr;  0 on return indicates\n"
+        "\t\tfailure.\n\n"
+        "\t\tSee unzip.h for details.\n"
+    },
+
+    {
+        "UZPFILETREE", "UzpFileTree",
+        "int UzpFileTree(char *name, cbList(callBack),\n"
+        "\t\t\tchar *cpInclude[], char *cpExclude[]);",
+        "Pass the name of the zip file, a callback function, an\n"
+        "\t\tinclude and exclude file list. UzpFileTree calls the\n"
+        "\t\tcallback for each valid file found in the zip file.\n"
+        "\t\t0 on return indicates failure.\n\n"
+        "\t\tSee unzip.h for details.\n"
+    },
+
+    { 0 }
+};
+
+
+static int function_help OF((__GPRO__ APIDocStruct *doc, char *fname));
+
+
+
+static int function_help(__G__ doc, fname)
+    __GDEF
+    APIDocStruct *doc;
+    char *fname;
+{
+    strcpy(slide, fname);
+    /* strupr(slide);    non-standard */
+    while (doc->compare && STRNICMP(doc->compare,slide,strlen(fname)))
+        doc++;
+    if (!doc->compare)
+        return 0;
+    else
+        Info(slide, 0, ((char *)slide,
+          "  Function:\t%s\n\n  Syntax:\t%s\n\n  Purpose:\t%s",
+          doc->function, doc->syntax, doc->purpose));
+
+    return 1;
+}
+
+
+
+void APIhelp(__G__ argc, argv)
+    __GDEF
+    int argc;
+    char **argv;
+{
+    if (argc > 1) {
+        struct APIDocStruct *doc;
+
+        if (function_help(__G__ APIDoc, argv[1]))
+            return;
+#ifdef SYSTEM_API_DETAILS
+        if (function_help(__G__ SYSTEM_API_DETAILS, argv[1]))
+            return;
+#endif
+        Info(slide, 0, ((char *)slide,
+          "%s is not a documented command.\n\n", argv[1]));
+    }
+
+    Info(slide, 0, ((char *)slide, "\
+This API provides a number of external C and REXX functions for handling\n\
+zipfiles in OS/2.  Programmers are encouraged to expand this API.\n\
+\n\
+C functions: -- See unzip.h for details\n\
+  UzpVer *UzpVersion(void);\n\
+  int UzpMain(int argc, char *argv[]);\n\
+  int UzpAltMain(int argc, char *argv[], UzpInit *init);\n\
+  int UzpUnzipToMemory(char *zip, char *file, UzpBuffer *retstr);\n\
+  int UzpFileTree(char *name, cbList(callBack),\n\
+                  char *cpInclude[], char *cpExclude[]);\n\n"));
+
+#ifdef SYSTEM_API_BRIEF
+    Info(slide, 0, ((char *)slide, SYSTEM_API_BRIEF));
+#endif
+
+    Info(slide, 0, ((char *)slide,
+      "\nFor more information, type 'unzip -A <function-name>'\n"));
+}
+
+#endif /* API_DOC */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/crc32.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,56 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $Id: crc32.c,v 1.1 2001/04/03 20:58:11 bsmith Exp $ */
+
+#define __CRC32_C       /* identifies this source module */
+
+#include "zip.h"
+
+#ifndef USE_ZLIB
+#ifndef ASM_CRC
+
+#ifndef ZCONST
+#  define ZCONST const
+#endif
+
+#ifdef CRC32
+#  undef CRC32
+#endif
+#define CRC32(c, b) (crc_table[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))
+#define DO1(buf)  crc = CRC32(crc, *buf++)
+#define DO2(buf)  DO1(buf); DO1(buf)
+#define DO4(buf)  DO2(buf); DO2(buf)
+#define DO8(buf)  DO4(buf); DO4(buf)
+
+/* ========================================================================= */
+ulg crc32(crc, buf, len)
+    register ulg crc;           /* crc shift register */
+    register ZCONST uch *buf;   /* pointer to bytes to pump through */
+    extent len;                 /* number of bytes in buf[] */
+/* Run a set of bytes through the crc shift register.  If buf is a NULL
+   pointer, then initialize the crc shift register contents instead.
+   Return the current crc in either case. */
+{
+  register ZCONST ulg near *crc_table;
+
+  if (buf == NULL) return 0L;
+
+  crc_table = get_crc_table();
+
+  crc = crc ^ 0xffffffffL;
+#ifndef NO_UNROLLED_LOOPS
+  while (len >= 8) {
+    DO8(buf);
+    len -= 8;
+  }
+#endif
+  if (len) do {
+    DO1(buf);
+  } while (--len);
+  return crc ^ 0xffffffffL;     /* (instead of ~c for 64-bit machines) */
+}
+#endif /* !ASM_CRC */
+#endif /* !USE_ZLIB */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/crc_i386.S	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,230 @@
+/*
+ * crc_i386.S, optimized CRC calculation function for Zip and UnZip, not
+ * copyrighted by Paul Kienitz and Christian Spieler.  Last revised 12 Oct 97.
+ *
+ * GRR 961110:  incorporated Scott Field optimizations from win32/crc_i386.asm
+ *              => overall 6% speedup in "unzip -tq" on 9MB zipfile (486-66)
+ *
+ * SPC 970402:  revised for Rodney Brown's optimizations (32-bit-wide
+ *              aligned reads for most of the data from buffer), can be
+ *              disabled by defining the macro NO_32_BIT_LOADS
+ *
+ * SPC 971012:  added Rodney Brown's additional tweaks for 32-bit-optimized
+ *              CPUs (like the Pentium Pro, Pentium II, and probably some
+ *              Pentium clones). This optimization is controlled by the
+ *              preprocessor switch "__686" and is disabled by default.
+ *              (This default is based on the assumption that most users
+ *              do not yet work on a Pentium Pro or Pentium II machine ...)
+ *
+ * FLAT memory model assumed.  Calling interface:
+ *   - args are pushed onto the stack from right to left,
+ *   - return value is given in the EAX register,
+ *   - all other registers (with exception of EFLAGS) are preserved. (With
+ *     GNU C 2.7.x, %edx and %ecx are `scratch' registers, but preserving
+ *     them nevertheless adds only 4 single byte instructions.)
+ *
+ * This source generates the function
+ * ulg crc32(ulg crc, ZCONST uch *buf, ulg len).
+ *
+ * The loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS.
+ * This results in shorter code at the expense of reduced performance.
+ */
+
+/* This file is NOT used in conjunction with zlib. */
+#ifndef USE_ZLIB
+
+/* Preprocess with -DNO_UNDERLINE if your C compiler does not prefix
+ * external symbols with an underline character '_'.
+ */
+#if defined(NO_UNDERLINE) || defined(__ELF__)
+#  define _crc32            crc32
+#  define _get_crc_table    get_crc_table
+#endif
+/* Use 16-byte alignment if your assembler supports it. Warning: gas
+ * uses a log(x) parameter (.align 4 means 16-byte alignment). On SVR4
+ * the parameter is a number of bytes.
+ */
+#ifndef ALIGNMENT
+#  define ALIGNMENT .align 4,0x90
+#endif
+
+#if defined(i386) || defined(_i386) || defined(_I386) || defined(__i386)
+
+/* This version is for 386 Unix, OS/2, MSDOS in 32 bit mode (gcc & gas).
+ * Warning: it uses the AT&T syntax: mov source,dest
+ * This file is only optional. If you want to use the C version,
+ * remove -DASM_CRC from CFLAGS in Makefile and set OBJA to an empty string.
+ */
+
+                .file   "crc_i386.S"
+
+#if defined(NO_STD_STACKFRAME) && defined(USE_STD_STACKFRAME)
+#  undef USE_STACKFRAME
+#else
+   /* The default is to use standard stack frame entry, because it
+    * results in smaller code!
+    */
+#  ifndef USE_STD_STACKFRAME
+#    define USE_STD_STACKFRAME
+#  endif
+#endif
+
+#ifdef USE_STD_STACKFRAME
+#  define _STD_ENTRY    pushl   %ebp ; movl   %esp,%ebp
+#  define arg1  8(%ebp)
+#  define arg2  12(%ebp)
+#  define arg3  16(%ebp)
+#  define _STD_LEAVE    popl    %ebp
+#else /* !USE_STD_STACKFRAME */
+#  define _STD_ENTRY
+#  define arg1  24(%esp)
+#  define arg2  28(%esp)
+#  define arg3  32(%esp)
+#  define _STD_LEAVE
+#endif /* ?USE_STD_STACKFRAME */
+
+/*
+ * These two (three) macros make up the loop body of the CRC32 cruncher.
+ * registers modified:
+ *   eax  : crc value "c"
+ *   esi  : pointer to next data byte (or lword) "buf++"
+ * registers read:
+ *   edi  : pointer to base of crc_table array
+ * scratch registers:
+ *   ebx  : index into crc_table array
+ *          (requires upper three bytes = 0 when __686 is undefined)
+ */
+#ifndef __686   /* optimize for 386, 486, Pentium */
+#define Do_CRC          /* c = (c >> 8) ^ table[c & 0xFF] */\
+                movb    %al, %bl                ;/* tmp = c & 0xFF  */\
+                shrl    $8, %eax                ;/* c = (c >> 8)    */\
+                xorl    (%edi, %ebx, 4), %eax   ;/* c ^= table[tmp] */
+#else   /* __686 : optimize for Pentium Pro and compatible CPUs */
+#define Do_CRC          /* c = (c >> 8) ^ table[c & 0xFF] */\
+                movzbl  %al, %ebx               ;/* tmp = c & 0xFF  */\
+                shrl    $8, %eax                ;/* c = (c >> 8)    */\
+                xorl    (%edi, %ebx, 4), %eax   ;/* c ^=table[tmp]  */
+#endif  /* ?__686 */
+
+#define Do_CRC_byte     /* c = (c >> 8) ^ table[(c^*buf++)&0xFF] */\
+                xorb    (%esi), %al     ;/* c ^= *buf  */\
+                incl    %esi            ;/* buf++      */\
+                Do_CRC
+
+#ifndef  NO_32_BIT_LOADS
+#define Do_CRC_lword \
+                xorl    (%esi), %eax    ;/* c ^= *(ulg *)buf */\
+                addl    $4, %esi        ;/* ((ulg *)buf)++   */\
+                Do_CRC \
+                Do_CRC \
+                Do_CRC \
+                Do_CRC
+#endif  /* !NO_32_BIT_LOADS */
+
+
+                .text
+
+                .globl  _crc32
+
+_crc32:                         /* ulg crc32(ulg crc, uch *buf, extent len) */
+                _STD_ENTRY
+                pushl   %edi
+                pushl   %esi
+                pushl   %ebx
+                pushl   %edx
+                pushl   %ecx
+
+                movl    arg2, %esi           /* 2nd arg: uch *buf            */
+                subl    %eax, %eax           /* > if (!buf)                  */
+                testl   %esi, %esi           /* >   return 0;                */
+                jz      .L_fine              /* > else {                     */
+                call    _get_crc_table
+                movl    %eax, %edi
+                movl    arg1, %eax           /* 1st arg: ulg crc             */
+#ifndef __686
+                subl    %ebx, %ebx           /* ebx=0; bl usable as dword    */
+#endif
+                movl    arg3, %ecx           /* 3rd arg: extent len          */
+                notl    %eax                 /* >   c = ~crc;                */
+
+#ifndef  NO_UNROLLED_LOOPS
+#  ifndef  NO_32_BIT_LOADS
+                testl   %ecx, %ecx
+                jz      .L_bail
+                /* Assert now have positive length */
+.L_align_loop:
+                testl   $3, %esi        /* Align buf on lword boundary */
+                jz      .L_aligned_now
+                Do_CRC_byte
+                decl    %ecx
+                jnz     .L_align_loop
+.L_aligned_now:
+#  endif  /* !NO_32_BIT_LOADS */
+                movl    %ecx, %edx           /* save len in edx          */
+                andl    $7, %edx             /* edx = len % 8            */
+                shrl    $3, %ecx             /* ecx = len / 8            */
+                jz      .L_No_Eights
+/*  align loop head at start of 486 internal cache line !! */
+                ALIGNMENT
+.L_Next_Eight:
+#  ifndef NO_32_BIT_LOADS
+                 /* Do_CRC_lword */
+                 xorl    (%esi), %eax    ;/* c ^= *(ulg *)buf */
+                 addl    $4, %esi        ;/* ((ulg *)buf)++   */
+                 Do_CRC
+                 Do_CRC
+                 Do_CRC
+                 Do_CRC
+                 /* Do_CRC_lword */
+                 xorl    (%esi), %eax    ;/* c ^= *(ulg *)buf */
+                 addl    $4, %esi        ;/* ((ulg *)buf)++   */
+                 Do_CRC
+                 Do_CRC
+                 Do_CRC
+                 Do_CRC
+#  else   /* NO_32_BIT_LOADS */
+                 Do_CRC_byte
+                 Do_CRC_byte
+                 Do_CRC_byte
+                 Do_CRC_byte
+                 Do_CRC_byte
+                 Do_CRC_byte
+                 Do_CRC_byte
+                 Do_CRC_byte
+#  endif  /* ?NO_32_BIT_LOADS */
+                decl    %ecx
+                jnz     .L_Next_Eight
+
+.L_No_Eights:
+                movl    %edx, %ecx
+#endif /* NO_UNROLLED_LOOPS */
+
+#ifndef NO_JECXZ_SUPPORT
+                jecxz   .L_bail              /* > if (len)                   */
+#else
+                testl   %ecx, %ecx           /* > if (len)                   */
+                jz      .L_bail
+#endif
+/* align loop head at start of 486 internal cache line !! */
+                ALIGNMENT
+.L_loupe:                                    /* >   do {                     */
+                 Do_CRC_byte                 /*       c = CRC32(c, *buf++);  */
+                decl    %ecx                 /* >   } while (--len);         */
+                jnz     .L_loupe
+
+.L_bail:                                     /* > }                          */
+                notl    %eax                 /* > return ~c;                 */
+.L_fine:
+                popl    %ecx
+                popl    %edx
+                popl    %ebx
+                popl    %esi
+                popl    %edi
+                _STD_LEAVE
+                ret
+
+#else
+ error: this asm version is for 386 only
+#endif /* i386 || _i386 || _I386 || __i386 */
+
+#endif /* !USE_ZLIB */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/crc_i386.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,215 @@
+/* crc_i386.c -- Microsoft 32-bit C/C++ adaptation of crc_i386.asm
+ * Created by Rodney Brown from crc_i386.asm, modified by Chr. Spieler.
+ * Last revised: 22-Mai-1998
+ *
+ * Original coded (in crc_i386.asm) and put into the public domain
+ * by Paul Kienitz and Christian Spieler.
+ *
+ * Revised 06-Oct-96, Scott Field (sfield@microsoft.com)
+ *   fixed to assemble with masm by not using .model directive which makes
+ *   assumptions about segment alignment.  Also,
+ *   avoid using loop, and j[e]cxz where possible.  Use mov + inc, rather
+ *   than lodsb, and other misc. changes resulting in the following performance
+ *   increases:
+ *
+ *      unrolled loops                NO_UNROLLED_LOOPS
+ *      *8    >8      <8              *8      >8      <8
+ *
+ *      +54%  +42%    +35%            +82%    +52%    +25%
+ *
+ *   first item in each table is input buffer length, even multiple of 8
+ *   second item in each table is input buffer length, > 8
+ *   third item in each table is input buffer length, < 8
+ *
+ * Revised 02-Apr-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au)
+ *   Incorporated Rodney Brown's 32-bit-reads optimization as found in the
+ *   UNIX AS source crc_i386.S. This new code can be disabled by defining
+ *   the macro symbol NO_32_BIT_LOADS.
+ *
+ * Revised 12-Oct-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au)
+ *   Incorporated Rodney Brown's additional tweaks for 32-bit-optimized CPUs
+ *   (like the Pentium Pro, Pentium II, and probably some Pentium clones).
+ *   This optimization is controlled by the macro symbol __686 and is disabled
+ *   by default. (This default is based on the assumption that most users
+ *   do not yet work on a Pentium Pro or Pentium II machine ...)
+ *
+ * Revised 16-Nov-97, Chr. Spieler: Made code compatible with Borland C++
+ *   32-bit, removed unneeded kludge for potentially unknown movzx mnemonic,
+ *   confirmed correct working with MS VC++ (32-bit).
+ *
+ * Revised 22-Mai-98, Peter Kunath, Chr. Spieler : The 16-Nov-97 revision broke
+ *   MSVC 5.0. Inside preprocessor macros, each instruction is enclosed in its
+ *   own __asm {...} construct.  For MSVC, a "#pragma warning" was added to
+ *   shut up the "no return value" warning message.
+ *
+ * FLAT memory model assumed.
+ *
+ * The loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS.
+ * This results in shorter code at the expense of reduced performance.
+ *
+ */
+
+#include "zip.h"
+
+#ifndef USE_ZLIB
+
+#ifndef ZCONST
+#  define ZCONST const
+#endif
+
+/* Select wether the following inline-assember code is supported. */
+#if (defined(_MSC_VER) && _MSC_VER >= 700)
+#if (defined(_M_IX86) && _M_IX86 >= 300)
+#  define MSC_INLINE_ASM_32BIT_SUPPORT
+   /* Disable warning for no return value, typical of asm functions */
+#  pragma warning( disable : 4035 )
+#endif
+#endif
+
+#if (defined(__BORLANDC__) && __BORLANDC__ >= 452)
+#  define MSC_INLINE_ASM_32BIT_SUPPORT
+#endif
+
+#ifdef MSC_INLINE_ASM_32BIT_SUPPORT
+/* This code is intended for Microsoft C/C++ (32-bit) compatible compilers. */
+
+/*
+ * These two (three) macros make up the loop body of the CRC32 cruncher.
+ * registers modified:
+ *   eax  : crc value "c"
+ *   esi  : pointer to next data byte (or dword) "buf++"
+ * registers read:
+ *   edi  : pointer to base of crc_table array
+ * scratch registers:
+ *   ebx  : index into crc_table array
+ *          (requires upper three bytes = 0 when __686 is undefined)
+ */
+#ifndef __686
+#define Do_CRC { \
+  __asm { mov   bl, al }; \
+  __asm { shr   eax, 8 }; \
+  __asm { xor   eax, [edi+ebx*4] }; }
+#else /* __686 */
+#define Do_CRC { \
+  __asm { movzx ebx, al }; \
+  __asm { shr   eax, 8  }; \
+  __asm { xor   eax, [edi+ebx*4] }; }
+#endif /* ?__686 */
+
+#define Do_CRC_byte { \
+  __asm { xor   al, byte ptr [esi] }; \
+  __asm { inc   esi }; \
+  Do_CRC; }
+
+#ifndef NO_32_BIT_LOADS
+#define Do_CRC_dword { \
+  __asm { xor   eax, dword ptr [esi] }; \
+  __asm { add   esi, 4 }; \
+  Do_CRC; \
+  Do_CRC; \
+  Do_CRC; \
+  Do_CRC; }
+#endif /* !NO_32_BIT_LOADS */
+
+/* ========================================================================= */
+ulg crc32(crc, buf, len)
+    ulg crc;                    /* crc shift register */
+    ZCONST uch *buf;            /* pointer to bytes to pump through */
+    extent len;                 /* number of bytes in buf[] */
+/* Run a set of bytes through the crc shift register.  If buf is a NULL
+   pointer, then initialize the crc shift register contents instead.
+   Return the current crc in either case. */
+{
+    __asm {
+                push    edx
+                push    ecx
+
+                mov     esi,buf         ;/* 2nd arg: uch *buf              */
+                sub     eax,eax         ;/*> if (!buf)                     */
+                test    esi,esi         ;/*>   return 0;                   */
+                jz      fine            ;/*> else {                        */
+
+                call    get_crc_table
+                mov     edi,eax
+                mov     eax,crc         ;/* 1st arg: ulg crc               */
+#ifndef __686
+                sub     ebx,ebx         ;/* ebx=0; => bl usable as a dword */
+#endif
+                mov     ecx,len         ;/* 3rd arg: extent len            */
+                not     eax             ;/*>   c = ~crc;                   */
+
+#ifndef NO_UNROLLED_LOOPS
+#  ifndef NO_32_BIT_LOADS
+                test    ecx,ecx
+                je      bail
+align_loop:
+                test    esi,3           ;/* align buf pointer on next      */
+                jz      aligned_now     ;/*  dword boundary                */
+    }
+                Do_CRC_byte             ;
+    __asm {
+                dec     ecx
+                jnz     align_loop
+aligned_now:
+#  endif /* !NO_32_BIT_LOADS */
+                mov     edx,ecx         ;/* save len in edx  */
+                and     edx,000000007H  ;/* edx = len % 8    */
+                shr     ecx,3           ;/* ecx = len / 8    */
+                jz      No_Eights
+; align loop head at start of 486 internal cache line !!
+                align   16
+Next_Eight:
+    }
+#  ifndef NO_32_BIT_LOADS
+                Do_CRC_dword ;
+                Do_CRC_dword ;
+#  else /* NO_32_BIT_LOADS */
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+#  endif /* ?NO_32_BIT_LOADS */
+    __asm {
+                dec     ecx
+                jnz     Next_Eight
+No_Eights:
+                mov     ecx,edx
+
+#endif /* NO_UNROLLED_LOOPS */
+#ifndef NO_JECXZ_SUPPORT
+                jecxz   bail            ;/*>  if (len)                     */
+#else
+                test    ecx,ecx         ;/*>  if (len)                     */
+                jz      bail
+#endif
+; align loop head at start of 486 internal cache line !!
+                align   16
+loupe:                                  ;/*>    do { */
+    }
+                Do_CRC_byte             ;/*       c = CRC32(c, *buf++);    */
+    __asm {
+                dec     ecx             ;/*>    } while (--len);           */
+                jnz     loupe
+
+bail:                                   ;/*> }                             */
+                not     eax             ;/*> return ~c;                    */
+fine:
+                pop     ecx
+                pop     edx
+    }
+#ifdef NEED_RETURN
+    return _EAX;
+#endif
+}
+#endif /* MSC_INLINE_ASM_32BIT_SUPPORT */
+#if (defined(_MSC_VER) && _MSC_VER >= 700)
+#if (defined(_M_IX86) && _M_IX86 >= 300)
+   /* Reenable missing return value warning */
+#  pragma warning( default : 4035 )
+#endif
+#endif
+#endif /* !USE_ZLIB */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/crc_lcc.asm	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,108 @@
+; crc_lcc.asm, optimized CRC calculation function for Zip and UnZip, not
+; copyrighted by Paul Kienitz and Christian Spieler.  Last revised 25 Mar 98.
+;
+; The code in this file has been copied verbatim from crc_i386.{asm|S};
+; only the assembler syntax and metacommands have been adapted to
+; the habits of the free LCC-Win32 C compiler package.
+; This version of the code uses the "optimized for i686" variant of
+; crc_i386.{asm|S}.
+;
+; For more information (and a revision log), look into the original
+; source files.
+;
+	.text
+	.file "crc32.c"
+	.text
+	.type	_crc32,function
+_crc32:
+	pushl	%ebp
+	movl	%esp,%ebp
+	pushl	%ecx
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+	.line	34
+	.line	37
+	movl	12(%ebp),%esi
+	subl	%eax,%eax
+	testl	%esi,%esi
+	jz	_$3
+	.line	39
+	call	_get_crc_table
+	movl	%eax,%edi
+	.line	41
+	movl	8(%ebp),%eax
+	movl	16(%ebp),%ecx
+	notl	%eax
+	testl	%ecx,%ecx
+	jz	_$4
+_$5:
+	testl	$3,%esi
+	jz	_$6
+	xorb    (%esi),%al
+	incl	%esi
+	movzbl	%al,%ebx
+	shrl	$8,%eax
+	xorl	(%edi,%ebx,4),%eax
+	decl	%ecx
+	jnz	_$5
+_$6:
+	movl	%ecx,%edx
+	andl	$7,%edx
+	shrl	$3,%ecx
+	jz	_$8
+_$7:
+	xorl	(%esi),%eax
+	addl	$4,%esi
+	movzbl	%al,%ebx
+	shrl	$8,%eax
+	xorl	(%edi,%ebx,4),%eax
+	movzbl	%al,%ebx
+	shrl	$8,%eax
+	xorl	(%edi,%ebx,4),%eax
+	movzbl	%al,%ebx
+	shrl	$8,%eax
+	xorl	(%edi,%ebx,4),%eax
+	movzbl	%al,%ebx
+	shrl	$8,%eax
+	xorl	(%edi,%ebx,4),%eax
+	xorl	(%esi),%eax
+	addl	$4,%esi
+	movzbl	%al,%ebx
+	shrl	$8,%eax
+	xorl	(%edi,%ebx,4),%eax
+	movzbl	%al,%ebx
+	shrl	$8,%eax
+	xorl	(%edi,%ebx,4),%eax
+	movzbl	%al,%ebx
+	shrl	$8,%eax
+	xorl	(%edi,%ebx,4),%eax
+	movzbl	%al,%ebx
+	shrl	$8,%eax
+	xorl	(%edi,%ebx,4),%eax
+	decl	%ecx
+	jnz	_$7
+_$8:
+	movl	%edx,%ecx
+	jecxz	_$4
+_$9:
+	xorb    (%esi),%al
+	incl    %esi
+	movzbl	%al,%ebx
+	shrl	$8,%eax
+	xorl	(%edi,%ebx,4),%eax
+	decl	%ecx
+	jnz	_$9
+_$4:
+	xorl	$0xffffffff,%eax
+_$3:
+	.line	52
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	leave
+	ret
+_$34:
+	.size	_crc32,_$34-_crc32
+	.globl	_crc32
+	.extern	_get_crc_table
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/crctab.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,219 @@
+/* crctab.c -- supply the CRC table needed for CRC-32 calculations.
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $Id: crctab.c,v 1.1 2001/04/03 20:58:11 bsmith Exp $ */
+
+/*
+  Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
+  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+  Polynomials over GF(2) are represented in binary, one bit per coefficient,
+  with the lowest powers in the most significant bit.  Then adding polynomials
+  is just exclusive-or, and multiplying a polynomial by x is a right shift by
+  one.  If we call the above polynomial p, and represent a byte as the
+  polynomial q, also with the lowest power in the most significant bit (so the
+  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+  where a mod b means the remainder after dividing a by b.
+
+  This calculation is done using the shift-register method of multiplying and
+  taking the remainder.  The register is initialized to zero, and for each
+  incoming bit, x^32 is added mod p to the register if the bit is a one (where
+  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+  x (which is shifting right by one and adding x^32 mod p if the bit shifted
+  out is a one).  We start with the highest power (least significant bit) of
+  q and repeat for all eight bits of q.
+
+  The table is simply the CRC of all possible eight bit values.  This is all
+  the information needed to generate CRC's on data a byte at a time for all
+  combinations of CRC register values and incoming bytes.
+*/
+
+#define __CRCTAB_C      /* identifies this source module */
+
+#include "zip.h"
+
+#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))
+
+#ifndef ZCONST
+#  define ZCONST const
+#endif
+
+#ifdef DYNAMIC_CRC_TABLE
+
+/* =========================================================================
+ * Make the crc table. This function is needed only if you want to compute
+ * the table dynamically.
+ */
+
+local void make_crc_table OF((void));
+
+#if (defined(DYNALLOC_CRCTAB) && defined(REENTRANT))
+   error: Dynamic allocation of CRC table not safe with reentrant code.
+#endif /* DYNALLOC_CRCTAB && REENTRANT */
+
+#ifdef DYNALLOC_CRCTAB
+   local ulg near *crc_table = NULL;
+# if 0          /* not used, since sizeof("near *") <= sizeof(int) */
+   /* Use this section when access to a "local int" is faster than access to
+      a "local pointer" (e.g.: i86 16bit code with far pointers). */
+   local int crc_table_empty = 1;
+#  define CRC_TABLE_IS_EMPTY    (crc_table_empty != 0)
+#  define MARK_CRCTAB_FILLED    crc_table_empty = 0
+#  define MARK_CRCTAB_EMPTY     crc_table_empty = 1
+# else
+   /* Use this section on systems where the size of pointers and ints is
+      equal (e.g.: all 32bit systems). */
+#  define CRC_TABLE_IS_EMPTY    (crc_table == NULL)
+#  define MARK_CRCTAB_FILLED    crc_table = crctab_p
+#  define MARK_CRCTAB_EMPTY     crc_table = NULL
+# endif
+#else /* !DYNALLOC_CRCTAB */
+   local ulg near crc_table[256];
+   local int crc_table_empty = 1;
+#  define CRC_TABLE_IS_EMPTY    (crc_table_empty != 0)
+#  define MARK_CRCTAB_FILLED    crc_table_empty = 0
+#endif /* ?DYNALLOC_CRCTAB */
+
+
+local void make_crc_table()
+{
+  ulg c;                /* crc shift register */
+  int n;                /* counter for all possible eight bit values */
+  int k;                /* byte being shifted into crc apparatus */
+#ifdef DYNALLOC_CRCTAB
+  ulg near *crctab_p;   /* temporary pointer to allocated crc_table area */
+#else /* !DYNALLOC_CRCTAB */
+# define crctab_p crc_table
+#endif /* DYNALLOC_CRCTAB */
+
+#ifdef COMPUTE_XOR_PATTERN
+  /* This piece of code has been left here to explain how the XOR pattern
+   * used in the creation of the crc_table values can be recomputed.
+   * For production versions of this function, it is more efficient to
+   * supply the resultant pattern at compile time.
+   */
+  ulg xor;              /* polynomial exclusive-or pattern */
+  /* terms of polynomial defining this crc (except x^32): */
+  static uch p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+  /* make exclusive-or pattern from polynomial (0xedb88320L) */
+  xor = 0L;
+  for (i = 0; i < sizeof(p)/sizeof(uch); i++)
+    xor |= 1L << (31 - p[i]);
+#else
+# define xor 0xedb88320L
+#endif
+
+#ifdef DYNALLOC_CRCTAB
+  crctab_p = (ulg near *) nearmalloc (256*sizeof(ulg));
+  if (crctab_p == NULL) {
+    ziperr(ZE_MEM, "crc_table allocation");
+  }
+#endif /* DYNALLOC_CRCTAB */
+
+  for (n = 0; n < 256; n++) {
+    c = (ulg)n;
+    for (k = 8; k; k--)
+      c = c & 1 ? xor ^ (c >> 1) : c >> 1;
+    crctab_p[n] = c;
+  }
+  MARK_CRCTAB_FILLED;
+}
+
+#else /* !DYNAMIC_CRC_TABLE */
+
+#ifdef DYNALLOC_CRCTAB
+   error: Inconsistent flags, DYNALLOC_CRCTAB without DYNAMIC_CRC_TABLE.
+#endif
+
+/* ========================================================================
+ * Table of CRC-32's of all single-byte values (made by make_crc_table)
+ */
+local ZCONST ulg near crc_table[256] = {
+  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+  0x2d02ef8dL
+};
+#endif /* ?DYNAMIC_CRC_TABLE */
+
+/* use "OF((void))" here to work around a Borland TC++ 1.0 problem */
+#ifdef USE_ZLIB
+ZCONST uLongf *get_crc_table OF((void))
+#else
+ZCONST ulg near *get_crc_table OF((void))
+#endif
+{
+#ifdef DYNAMIC_CRC_TABLE
+  if (CRC_TABLE_IS_EMPTY)
+    make_crc_table();
+#endif
+#ifdef USE_ZLIB
+  return (ZCONST uLongf *)crc_table;
+#else
+  return (ZCONST ulg near *)crc_table;
+#endif
+}
+
+#ifdef DYNALLOC_CRCTAB
+void free_crc_table()
+{
+  if (!CRC_TABLE_IS_EMPTY)
+  {
+    nearfree((ulg near *)crc_table);
+    MARK_CRCTAB_EMPTY;
+  }
+}
+#endif
+
+#endif /* !USE_ZLIB || USE_OWN_CRCTAB */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/crypt.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,12 @@
+/*
+   crypt.c (dummy version) by Info-ZIP.      Last revised: 15 Aug 98
+
+   This is a non-functional version of Info-ZIP's crypt.c encryption/
+   decryption code for Zip, ZipCloak, UnZip and fUnZip.  This file is
+   not copyrighted and may be distributed freely. :-)  See the "WHERE"
+   file for sites from which to obtain the full encryption/decryption
+   sources (zcrypt28.zip or later).
+ */
+
+/* something "externally visible" to shut up compiler/linker warnings */
+int zcr_dummy;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/envargs.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,314 @@
+/*----------------------------------------------------------------*
+ | envargs - add default options from environment to command line
+ |----------------------------------------------------------------
+ | Author: Bill Davidsen, original 10/13/91, revised 23 Oct 1991.
+ | This program is in the public domain.
+ |----------------------------------------------------------------
+ | Minor program notes:
+ |  1. Yes, the indirection is a tad complex
+ |  2. Parentheses were added where not needed in some cases
+ |     to make the action of the code less obscure.
+ |----------------------------------------------------------------
+ | UnZip notes: 24 May 92 ("v1.4"):
+ |  1. #include "unzip.h" for prototypes (24 May 92)
+ |  2. changed ch to type char (24 May 92)
+ |  3. added an ifdef to avoid Borland warnings (24 May 92)
+ |  4. included Rich Wales' mksargs() routine (for MS-DOS, maybe
+ |     OS/2? NT?) (4 Dec 93)
+ |  5. added alternate-variable string envstr2 (21 Apr 94)
+ |  6. added support for quoted arguments (6 Jul 96)
+ *----------------------------------------------------------------*/
+
+
+#define ENVARGS_C
+#define UNZIP_INTERNAL
+#include "unzip.h"
+
+#ifdef __EMX__          /* emx isspace() returns TRUE on extended ASCII !! */
+#  define ISspace(c) ((c) & 0x80 ? 0 : isspace((unsigned)c))
+#else
+#  define ISspace(c) isspace((unsigned)c)
+#endif /* ?__EMX__ */
+
+static int count_args OF((ZCONST char *));
+static void mem_err OF((__GPRO));
+
+static ZCONST char Far NoMemArguments[] =
+  "envargs:  cannot get memory for arguments";
+
+
+void envargs(__G__ Pargc, Pargv, envstr, envstr2)
+    __GDEF
+    int *Pargc;
+    char ***Pargv;
+    ZCONST char *envstr, *envstr2;
+{
+#ifndef RISCOS
+    char *getenv();
+#endif
+    char *envptr;       /* value returned by getenv */
+    char *bufptr;       /* copy of env info */
+    int argc = 0;       /* internal arg count */
+    register int ch;    /* spare temp value */
+    char **argv;        /* internal arg vector */
+    char **argvect;     /* copy of vector address */
+
+    /* see if anything in the environment */
+    if ((envptr = getenv(envstr)) != (char *)NULL)        /* usual var */
+        while (ISspace(*envptr))        /* must discard leading spaces */
+            envptr++;
+    if (envptr == (char *)NULL || *envptr == '\0')
+        if ((envptr = getenv(envstr2)) != (char *)NULL)   /* alternate var */
+            while (ISspace(*envptr))
+                envptr++;
+    if (envptr == (char *)NULL || *envptr == '\0')
+        return;
+
+    bufptr = malloc(1 + strlen(envptr));
+    if (bufptr == (char *)NULL)
+        mem_err(__G);
+#if (defined(WIN32) || defined(WINDLL))
+# ifdef WIN32
+    if (IsWinNT()) {
+        /* SPC: don't know codepage of 'real' WinNT console */
+        strcpy(bufptr, envptr);
+    } else {
+        /* Win95 environment is DOS and uses OEM character coding */
+        OEM_TO_INTERN(envptr, bufptr);
+    }
+# else /* !WIN32 */
+    /* DOS environment uses OEM codepage */
+    OEM_TO_INTERN(envptr, bufptr);
+# endif
+#else /* !(WIN32 || WINDLL) */
+    strcpy(bufptr, envptr);
+#endif /* ?(WIN32 || WINDLL) */
+
+    /* count the args so we can allocate room for them */
+    argc = count_args(bufptr);
+    /* allocate a vector large enough for all args */
+    argv = (char **)malloc((argc + *Pargc + 1) * sizeof(char *));
+    if (argv == (char **)NULL) {
+        free(bufptr);
+        mem_err(__G);
+    }
+    argvect = argv;
+
+    /* copy the program name first, that's always true */
+    *(argv++) = *((*Pargv)++);
+
+    /* copy the environment args next, may be changed */
+    do {
+#if defined(AMIGA) || defined(UNIX)
+        if (*bufptr == '"') {
+            char *argstart = ++bufptr;
+
+            *(argv++) = argstart;
+            for (ch = *bufptr; ch != '\0' && ch != '\"'; ch = *(++bufptr))
+                if (ch == '\\' && bufptr[1] != '\0')
+                    ++bufptr;           /* skip char after backslash */
+            if (ch != '\0')
+                *(bufptr++) = '\0';     /* overwrite trailing " */
+
+            /* remove escape characters */
+            while ((argstart = strchr(argstart, '\\')) != (char *)NULL) {
+                strcpy(argstart, argstart + 1);
+                if (*argstart)
+                    ++argstart;
+            }
+        } else {
+            *(argv++) = bufptr;
+            while ((ch = *bufptr) != '\0' && !ISspace(ch))
+                ++bufptr;
+            if (ch != '\0')
+                *(bufptr++) = '\0';
+        }
+#else
+#ifdef DOS_FLX_OS2_W32
+        /* we do not support backslash-quoting of quotes in quoted
+         * strings under DOS_OS2_W32, because backslashes are directory
+         * separators and double quotes are illegal in filenames */
+        if (*bufptr == '"') {
+            *(argv++) = ++bufptr;
+            while ((ch = *bufptr) != '\0' && ch != '\"')
+                ++bufptr;
+            if (ch != '\0')
+                *(bufptr++) = '\0';
+        } else {
+            *(argv++) = bufptr;
+            while ((ch = *bufptr) != '\0' && !ISspace(ch))
+                ++bufptr;
+            if (ch != '\0')
+                *(bufptr++) = '\0';
+        }
+#else
+        *(argv++) = bufptr;
+        while ((ch = *bufptr) != '\0' && !ISspace(ch))
+            ++bufptr;
+        if (ch != '\0')
+            *(bufptr++) = '\0';
+#endif /* ?DOS_FLX_OS2_W32 */
+#endif /* ?(AMIGA || UNIX) */
+        while ((ch = *bufptr) != '\0' && ISspace(ch))
+            ++bufptr;
+    } while (ch);
+
+    /* now save old argc and copy in the old args */
+    argc += *Pargc;
+    while (--(*Pargc))
+        *(argv++) = *((*Pargv)++);
+
+    /* finally, add a NULL after the last arg, like Unix */
+    *argv = (char *)NULL;
+
+    /* save the values and return */
+    *Pargv = argvect;
+    *Pargc = argc;
+}
+
+
+
+static int count_args(s)
+    ZCONST char *s;
+{
+    int count = 0;
+    char ch;
+
+    do {
+        /* count and skip args */
+        ++count;
+#if defined(AMIGA) || defined(UNIX)
+        if (*s == '\"') {
+            for (ch = *(++s);  ch != '\0' && ch != '\"';  ch = *(++s))
+                if (ch == '\\' && s[1] != '\0')
+                    ++s;
+            if (*s)
+                ++s;        /* trailing quote */
+        } else
+#else
+#ifdef DOS_FLX_OS2_W32
+        if (*s == '\"') {
+            ++s;                /* leading quote */
+            while ((ch = *s) != '\0' && ch != '\"')
+                ++s;
+            if (*s)
+                ++s;        /* trailing quote */
+        } else
+#endif /* DOS_FLX_OS2_W32 */
+#endif /* ?(AMIGA || UNIX) */
+        while ((ch = *s) != '\0' && !ISspace(ch))  /* note else-clauses above */
+            ++s;
+        while ((ch = *s) != '\0' && ISspace(ch))
+            ++s;
+    } while (ch);
+
+    return count;
+}
+
+
+
+static void mem_err(__G)
+    __GDEF
+{
+    perror(LoadFarString(NoMemArguments));
+    DESTROYGLOBALS()
+    EXIT(PK_MEM);
+}
+
+
+
+#ifdef TEST
+
+main(argc, argv)
+    int argc;
+    char **argv;
+{
+    int i;
+
+    pipeit("Orig argv: %p\n", argv);
+    dump_args(argc, argv);
+    envargs(__G__ &argc, &argv, "ENVTEST");
+    pipeit(" New argv: %p\n", argv);
+    dump_args(argc, argv);
+}
+
+
+
+dump_args(argc, argv)
+    int argc;
+    char *argv[];
+{
+    int i;
+
+    pipeit("\nDump %d args:\n", argc);
+    for (i = 0; i < argc; ++i)
+        pipeit("%3d %s\n", i, argv[i]);
+}
+
+#endif /* TEST */
+
+
+
+#ifdef MSDOS   /* DOS_OS2?  DOS_OS2_W32? */
+
+/*
+ * void mksargs(int *argcp, char ***argvp)
+ *
+ *    Substitutes the extended command line argument list produced by
+ *    the MKS Korn Shell in place of the command line info from DOS.
+ *
+ *    The MKS shell gets around DOS's 128-byte limit on the length of
+ *    a command line by passing the "real" command line in the envi-
+ *    ronment.  The "real" arguments are flagged by prepending a tilde
+ *    (~) to each one.
+ *
+ *    This "mksargs" routine creates a new argument list by scanning
+ *    the environment from the beginning, looking for strings begin-
+ *    ning with a tilde character.  The new list replaces the original
+ *    "argv" (pointed to by "argvp"), and the number of arguments
+ *    in the new list replaces the original "argc" (pointed to by
+ *    "argcp").
+ *
+ *    Rich Wales
+ */
+void mksargs(argcp, argvp)
+    int *argcp;
+    char ***argvp;
+{
+#ifndef MSC /* declared differently in MSC 7.0 headers, at least */
+#ifndef __WATCOMC__
+    extern char **environ;          /* environment */
+#endif
+#endif
+    char        **envp;             /* pointer into environment */
+    char        **newargv;          /* new argument list */
+    char        **argp;             /* pointer into new arg list */
+    int         newargc;            /* new argument count */
+
+    /* sanity check */
+    if (environ == NULL || argcp == NULL || argvp == NULL || *argvp == NULL)
+        return;
+
+    /* find out how many environment arguments there are */
+    for (envp = environ, newargc = 0; *envp != NULL && (*envp)[0] == '~';
+         envp++, newargc++)
+        ;
+    if (newargc == 0)
+        return;     /* no environment arguments */
+
+    /* set up new argument list */
+    newargv = (char **) malloc(sizeof(char **) * (newargc+1));
+    if (newargv == NULL)
+        return;     /* malloc failed */
+
+    for (argp = newargv, envp = environ; *envp != NULL && (*envp)[0] == '~';
+         *argp++ = &(*envp++)[1])
+        ;
+    *argp = NULL;   /* null-terminate the list */
+
+    /* substitute new argument list in place of old one */
+    *argcp = newargc;
+    *argvp = newargv;
+}
+
+#endif /* MSDOS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/explode.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,871 @@
+/* explode.c -- put in the public domain by Mark Adler
+   version c15, 6 July 1996 */
+
+
+/* You can do whatever you like with this source file, though I would
+   prefer that if you modify it and redistribute it that you include
+   comments to that effect with your name and the date.  Thank you.
+
+   History:
+   vers    date          who           what
+   ----  ---------  --------------  ------------------------------------
+    c1   30 Mar 92  M. Adler        explode that uses huft_build from inflate
+                                    (this gives over a 70% speed improvement
+                                    over the original unimplode.c, which
+                                    decoded a bit at a time)
+    c2    4 Apr 92  M. Adler        fixed bug for file sizes a multiple of 32k.
+    c3   10 Apr 92  M. Adler        added a little memory tracking if DEBUG
+    c4   11 Apr 92  M. Adler        added NOMEMCPY do kill use of memcpy()
+    c5   21 Apr 92  M. Adler        added the WSIZE #define to allow reducing
+                                    the 32K window size for specialized
+                                    applications.
+    c6   31 May 92  M. Adler        added typecasts to eliminate some warnings
+    c7   27 Jun 92  G. Roelofs      added more typecasts.
+    c8   17 Oct 92  G. Roelofs      changed ULONG/UWORD/byte to ulg/ush/uch.
+    c9   19 Jul 93  J. Bush         added more typecasts (to return values);
+                                    made l[256] array static for Amiga.
+    c10   8 Oct 93  G. Roelofs      added used_csize for diagnostics; added
+                                    buf and unshrink arguments to flush();
+                                    undef'd various macros at end for Turbo C;
+                                    removed NEXTBYTE macro (now in unzip.h)
+                                    and bytebuf variable (not used); changed
+                                    memset() to memzero().
+    c11   9 Jan 94  M. Adler        fixed incorrect used_csize calculation.
+    c12   9 Apr 94  G. Roelofs      fixed split comments on preprocessor lines
+                                    to avoid bug in Encore compiler.
+    c13  25 Aug 94  M. Adler        fixed distance-length comment (orig c9 fix)
+    c14  22 Nov 95  S. Maxwell      removed unnecessary "static" on auto array
+    c15   6 Jul 96  W. Haidinger    added ulg typecasts to flush() calls.
+    c16   8 Feb 98  C. Spieler      added ZCONST modifiers to const tables
+                                    and #ifdef DEBUG around debugging code.
+    c16b 25 Mar 98  C. Spieler      modified DLL code for slide redirection.
+ */
+
+
+/*
+   Explode imploded (PKZIP method 6 compressed) data.  This compression
+   method searches for as much of the current string of bytes (up to a length
+   of ~320) in the previous 4K or 8K bytes.  If it doesn't find any matches
+   (of at least length 2 or 3), it codes the next byte.  Otherwise, it codes
+   the length of the matched string and its distance backwards from the
+   current position.  Single bytes ("literals") are preceded by a one (a
+   single bit) and are either uncoded (the eight bits go directly into the
+   compressed stream for a total of nine bits) or Huffman coded with a
+   supplied literal code tree.  If literals are coded, then the minimum match
+   length is three, otherwise it is two.
+
+   There are therefore four kinds of imploded streams: 8K search with coded
+   literals (min match = 3), 4K search with coded literals (min match = 3),
+   8K with uncoded literals (min match = 2), and 4K with uncoded literals
+   (min match = 2).  The kind of stream is identified in two bits of a
+   general purpose bit flag that is outside of the compressed stream.
+
+   Distance-length pairs for matched strings are preceded by a zero bit (to
+   distinguish them from literals) and are always coded.  The distance comes
+   first and is either the low six (4K) or low seven (8K) bits of the
+   distance (uncoded), followed by the high six bits of the distance coded.
+   Then the length is six bits coded (0..63 + min match length), and if the
+   maximum such length is coded, then it's followed by another eight bits
+   (uncoded) to be added to the coded length.  This gives a match length
+   range of 2..320 or 3..321 bytes.
+
+   The literal, length, and distance codes are all represented in a slightly
+   compressed form themselves.  What is sent are the lengths of the codes for
+   each value, which is sufficient to construct the codes.  Each byte of the
+   code representation is the code length (the low four bits representing
+   1..16), and the number of values sequentially with that length (the high
+   four bits also representing 1..16).  There are 256 literal code values (if
+   literals are coded), 64 length code values, and 64 distance code values,
+   in that order at the beginning of the compressed stream.  Each set of code
+   values is preceded (redundantly) with a byte indicating how many bytes are
+   in the code description that follows, in the range 1..256.
+
+   The codes themselves are decoded using tables made by huft_build() from
+   the bit lengths.  That routine and its comments are in the inflate.c
+   module.
+ */
+
+#define UNZIP_INTERNAL
+#include "unzip.h"      /* must supply slide[] (uch) array and NEXTBYTE macro */
+
+#ifndef WSIZE
+#  define WSIZE 0x8000  /* window size--must be a power of two, and */
+#endif                  /* at least 8K for zip's implode method */
+
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+#  define wsize G._wsize
+#else
+#  define wsize WSIZE
+#endif
+
+/* routines here */
+static int get_tree OF((__GPRO__ unsigned *l, unsigned n));
+static int explode_lit8 OF((__GPRO__ struct huft *tb, struct huft *tl,
+                            struct huft *td, int bb, int bl, int bd));
+static int explode_lit4 OF((__GPRO__ struct huft *tb, struct huft *tl,
+                            struct huft *td, int bb, int bl, int bd));
+static int explode_nolit8 OF((__GPRO__ struct huft *tl, struct huft *td,
+                              int bl, int bd));
+static int explode_nolit4 OF((__GPRO__ struct huft *tl, struct huft *td,
+                              int bl, int bd));
+int explode OF((__GPRO));
+
+
+/* The implode algorithm uses a sliding 4K or 8K byte window on the
+   uncompressed stream to find repeated byte strings.  This is implemented
+   here as a circular buffer.  The index is updated simply by incrementing
+   and then and'ing with 0x0fff (4K-1) or 0x1fff (8K-1).  Here, the 32K
+   buffer of inflate is used, and it works just as well to always have
+   a 32K circular buffer, so the index is anded with 0x7fff.  This is
+   done to allow the window to also be used as the output buffer. */
+/* This must be supplied in an external module useable like "uch slide[8192];"
+   or "uch *slide;", where the latter would be malloc'ed.  In unzip, slide[]
+   is actually a 32K area for use by inflate, which uses a 32K sliding window.
+ */
+
+
+/* Tables for length and distance */
+static ZCONST ush cplen2[] =
+        {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+        18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+        35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65};
+static ZCONST ush cplen3[] =
+        {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+        19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+        36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+        53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66};
+static ZCONST ush extra[] =
+        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        8};
+static ZCONST ush cpdist4[] =
+        {1, 65, 129, 193, 257, 321, 385, 449, 513, 577, 641, 705,
+        769, 833, 897, 961, 1025, 1089, 1153, 1217, 1281, 1345, 1409, 1473,
+        1537, 1601, 1665, 1729, 1793, 1857, 1921, 1985, 2049, 2113, 2177,
+        2241, 2305, 2369, 2433, 2497, 2561, 2625, 2689, 2753, 2817, 2881,
+        2945, 3009, 3073, 3137, 3201, 3265, 3329, 3393, 3457, 3521, 3585,
+        3649, 3713, 3777, 3841, 3905, 3969, 4033};
+static ZCONST ush cpdist8[] =
+        {1, 129, 257, 385, 513, 641, 769, 897, 1025, 1153, 1281,
+        1409, 1537, 1665, 1793, 1921, 2049, 2177, 2305, 2433, 2561, 2689,
+        2817, 2945, 3073, 3201, 3329, 3457, 3585, 3713, 3841, 3969, 4097,
+        4225, 4353, 4481, 4609, 4737, 4865, 4993, 5121, 5249, 5377, 5505,
+        5633, 5761, 5889, 6017, 6145, 6273, 6401, 6529, 6657, 6785, 6913,
+        7041, 7169, 7297, 7425, 7553, 7681, 7809, 7937, 8065};
+
+
+/* Macros for inflate() bit peeking and grabbing.
+   The usage is:
+
+        NEEDBITS(j)
+        x = b & mask_bits[j];
+        DUMPBITS(j)
+
+   where NEEDBITS makes sure that b has at least j bits in it, and
+   DUMPBITS removes the bits from b.  The macros use the variable k
+   for the number of bits in b.  Normally, b and k are register
+   variables for speed.
+ */
+
+#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<<k;k+=8;}}
+#define DUMPBITS(n) {b>>=(n);k-=(n);}
+
+
+
+static int get_tree(__G__ l, n)
+     __GDEF
+unsigned *l;            /* bit lengths */
+unsigned n;             /* number expected */
+/* Get the bit lengths for a code representation from the compressed
+   stream.  If get_tree() returns 4, then there is an error in the data.
+   Otherwise zero is returned. */
+{
+  unsigned i;           /* bytes remaining in list */
+  unsigned k;           /* lengths entered */
+  unsigned j;           /* number of codes */
+  unsigned b;           /* bit length for those codes */
+
+
+  /* get bit lengths */
+  i = NEXTBYTE + 1;                     /* length/count pairs to read */
+  k = 0;                                /* next code */
+  do {
+    b = ((j = NEXTBYTE) & 0xf) + 1;     /* bits in code (1..16) */
+    j = ((j & 0xf0) >> 4) + 1;          /* codes with those bits (1..16) */
+    if (k + j > n)
+      return 4;                         /* don't overflow l[] */
+    do {
+      l[k++] = b;
+    } while (--j);
+  } while (--i);
+  return k != n ? 4 : 0;                /* should have read n of them */
+}
+
+
+
+static int explode_lit8(__G__ tb, tl, td, bb, bl, bd)
+     __GDEF
+struct huft *tb, *tl, *td;      /* literal, length, and distance tables */
+int bb, bl, bd;                 /* number of bits decoded by those */
+/* Decompress the imploded data using coded literals and an 8K sliding
+   window. */
+{
+  long s;               /* bytes to decompress */
+  register unsigned e;  /* table entry flag/number of extra bits */
+  unsigned n, d;        /* length and index for copy */
+  unsigned w;           /* current window position */
+  struct huft *t;       /* pointer to table entry */
+  unsigned mb, ml, md;  /* masks for bb, bl, and bd bits */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+  unsigned u;           /* true if unflushed */
+
+
+  /* explode the coded data */
+  b = k = w = 0;                /* initialize bit buffer, window */
+  u = 1;                        /* buffer unflushed */
+  mb = mask_bits[bb];           /* precompute masks for speed */
+  ml = mask_bits[bl];
+  md = mask_bits[bd];
+  s = G.ucsize;
+  while (s > 0)                 /* do until ucsize bytes uncompressed */
+  {
+    NEEDBITS(1)
+    if (b & 1)                  /* then literal--decode it */
+    {
+      DUMPBITS(1)
+      s--;
+      NEEDBITS((unsigned)bb)    /* get coded literal */
+      if ((e = (t = tb + ((~(unsigned)b) & mb))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      redirSlide[w++] = (uch)t->v.n;
+      if (w == wsize)
+      {
+        flush(__G__ redirSlide, (ulg)w, 0);
+        w = u = 0;
+      }
+    }
+    else                        /* else distance/length */
+    {
+      DUMPBITS(1)
+      NEEDBITS(7)               /* get distance low bits */
+      d = (unsigned)b & 0x7f;
+      DUMPBITS(7)
+      NEEDBITS((unsigned)bd)    /* get coded distance high bits */
+      if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      d = w - d - t->v.n;       /* construct offset */
+      NEEDBITS((unsigned)bl)    /* get coded length */
+      if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      n = t->v.n;
+      if (e)                    /* get length extra bits */
+      {
+        NEEDBITS(8)
+        n += (unsigned)b & 0xff;
+        DUMPBITS(8)
+      }
+
+      /* do the copy */
+      s -= n;
+      do {
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+        if (G.redirect_slide) {
+          /* &= w/ wsize not needed and wrong if redirect */
+          if (d >= wsize)
+            return 1;
+          n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e);
+        } else
+#endif
+        n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e);
+        if (u && w <= d)
+        {
+          memzero(redirSlide + w, e);
+          w += e;
+          d += e;
+        }
+        else
+#ifndef NOMEMCPY
+          if (w - d >= e)       /* (this test assumes unsigned comparison) */
+          {
+            memcpy(redirSlide + w, redirSlide + d, e);
+            w += e;
+            d += e;
+          }
+          else                  /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+            do {
+              redirSlide[w++] = redirSlide[d++];
+            } while (--e);
+        if (w == wsize)
+        {
+          flush(__G__ redirSlide, (ulg)w, 0);
+          w = u = 0;
+        }
+      } while (n);
+    }
+  }
+
+  /* flush out redirSlide */
+  flush(__G__ redirSlide, (ulg)w, 0);
+  if (G.csize + G.incnt + (k >> 3))   /* should have read csize bytes, but */
+  {                        /* sometimes read one too many:  k>>3 compensates */
+    G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3);
+    return 5;
+  }
+  return 0;
+}
+
+
+
+static int explode_lit4(__G__ tb, tl, td, bb, bl, bd)
+     __GDEF
+struct huft *tb, *tl, *td;      /* literal, length, and distance tables */
+int bb, bl, bd;                 /* number of bits decoded by those */
+/* Decompress the imploded data using coded literals and a 4K sliding
+   window. */
+{
+  long s;               /* bytes to decompress */
+  register unsigned e;  /* table entry flag/number of extra bits */
+  unsigned n, d;        /* length and index for copy */
+  unsigned w;           /* current window position */
+  struct huft *t;       /* pointer to table entry */
+  unsigned mb, ml, md;  /* masks for bb, bl, and bd bits */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+  unsigned u;           /* true if unflushed */
+
+
+  /* explode the coded data */
+  b = k = w = 0;                /* initialize bit buffer, window */
+  u = 1;                        /* buffer unflushed */
+  mb = mask_bits[bb];           /* precompute masks for speed */
+  ml = mask_bits[bl];
+  md = mask_bits[bd];
+  s = G.ucsize;
+  while (s > 0)                 /* do until ucsize bytes uncompressed */
+  {
+    NEEDBITS(1)
+    if (b & 1)                  /* then literal--decode it */
+    {
+      DUMPBITS(1)
+      s--;
+      NEEDBITS((unsigned)bb)    /* get coded literal */
+      if ((e = (t = tb + ((~(unsigned)b) & mb))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      redirSlide[w++] = (uch)t->v.n;
+      if (w == wsize)
+      {
+        flush(__G__ redirSlide, (ulg)w, 0);
+        w = u = 0;
+      }
+    }
+    else                        /* else distance/length */
+    {
+      DUMPBITS(1)
+      NEEDBITS(6)               /* get distance low bits */
+      d = (unsigned)b & 0x3f;
+      DUMPBITS(6)
+      NEEDBITS((unsigned)bd)    /* get coded distance high bits */
+      if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      d = w - d - t->v.n;       /* construct offset */
+      NEEDBITS((unsigned)bl)    /* get coded length */
+      if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      n = t->v.n;
+      if (e)                    /* get length extra bits */
+      {
+        NEEDBITS(8)
+        n += (unsigned)b & 0xff;
+        DUMPBITS(8)
+      }
+
+      /* do the copy */
+      s -= n;
+      do {
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+        if (G.redirect_slide) {
+          /* &= w/ wsize not needed and wrong if redirect */
+          if (d >= wsize)
+            return 1;
+          n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e);
+        } else
+#endif
+        n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e);
+        if (u && w <= d)
+        {
+          memzero(redirSlide + w, e);
+          w += e;
+          d += e;
+        }
+        else
+#ifndef NOMEMCPY
+          if (w - d >= e)       /* (this test assumes unsigned comparison) */
+          {
+            memcpy(redirSlide + w, redirSlide + d, e);
+            w += e;
+            d += e;
+          }
+          else                  /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+            do {
+              redirSlide[w++] = redirSlide[d++];
+            } while (--e);
+        if (w == wsize)
+        {
+          flush(__G__ redirSlide, (ulg)w, 0);
+          w = u = 0;
+        }
+      } while (n);
+    }
+  }
+
+  /* flush out redirSlide */
+  flush(__G__ redirSlide, (ulg)w, 0);
+  if (G.csize + G.incnt + (k >> 3))   /* should have read csize bytes, but */
+  {                        /* sometimes read one too many:  k>>3 compensates */
+    G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3);
+    return 5;
+  }
+  return 0;
+}
+
+
+
+static int explode_nolit8(__G__ tl, td, bl, bd)
+     __GDEF
+struct huft *tl, *td;   /* length and distance decoder tables */
+int bl, bd;             /* number of bits decoded by tl[] and td[] */
+/* Decompress the imploded data using uncoded literals and an 8K sliding
+   window. */
+{
+  long s;               /* bytes to decompress */
+  register unsigned e;  /* table entry flag/number of extra bits */
+  unsigned n, d;        /* length and index for copy */
+  unsigned w;           /* current window position */
+  struct huft *t;       /* pointer to table entry */
+  unsigned ml, md;      /* masks for bl and bd bits */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+  unsigned u;           /* true if unflushed */
+
+
+  /* explode the coded data */
+  b = k = w = 0;                /* initialize bit buffer, window */
+  u = 1;                        /* buffer unflushed */
+  ml = mask_bits[bl];           /* precompute masks for speed */
+  md = mask_bits[bd];
+  s = G.ucsize;
+  while (s > 0)                 /* do until ucsize bytes uncompressed */
+  {
+    NEEDBITS(1)
+    if (b & 1)                  /* then literal--get eight bits */
+    {
+      DUMPBITS(1)
+      s--;
+      NEEDBITS(8)
+      redirSlide[w++] = (uch)b;
+      if (w == wsize)
+      {
+        flush(__G__ redirSlide, (ulg)w, 0);
+        w = u = 0;
+      }
+      DUMPBITS(8)
+    }
+    else                        /* else distance/length */
+    {
+      DUMPBITS(1)
+      NEEDBITS(7)               /* get distance low bits */
+      d = (unsigned)b & 0x7f;
+      DUMPBITS(7)
+      NEEDBITS((unsigned)bd)    /* get coded distance high bits */
+      if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      d = w - d - t->v.n;       /* construct offset */
+      NEEDBITS((unsigned)bl)    /* get coded length */
+      if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      n = t->v.n;
+      if (e)                    /* get length extra bits */
+      {
+        NEEDBITS(8)
+        n += (unsigned)b & 0xff;
+        DUMPBITS(8)
+      }
+
+      /* do the copy */
+      s -= n;
+      do {
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+        if (G.redirect_slide) {
+          /* &= w/ wsize not needed and wrong if redirect */
+          if (d >= wsize)
+            return 1;
+          n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e);
+        } else
+#endif
+        n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e);
+        if (u && w <= d)
+        {
+          memzero(redirSlide + w, e);
+          w += e;
+          d += e;
+        }
+        else
+#ifndef NOMEMCPY
+          if (w - d >= e)       /* (this test assumes unsigned comparison) */
+          {
+            memcpy(redirSlide + w, redirSlide + d, e);
+            w += e;
+            d += e;
+          }
+          else                  /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+            do {
+              redirSlide[w++] = redirSlide[d++];
+            } while (--e);
+        if (w == wsize)
+        {
+          flush(__G__ redirSlide, (ulg)w, 0);
+          w = u = 0;
+        }
+      } while (n);
+    }
+  }
+
+  /* flush out redirSlide */
+  flush(__G__ redirSlide, (ulg)w, 0);
+  if (G.csize + G.incnt + (k >> 3))   /* should have read csize bytes, but */
+  {                        /* sometimes read one too many:  k>>3 compensates */
+    G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3);
+    return 5;
+  }
+  return 0;
+}
+
+
+
+static int explode_nolit4(__G__ tl, td, bl, bd)
+     __GDEF
+struct huft *tl, *td;   /* length and distance decoder tables */
+int bl, bd;             /* number of bits decoded by tl[] and td[] */
+/* Decompress the imploded data using uncoded literals and a 4K sliding
+   window. */
+{
+  long s;               /* bytes to decompress */
+  register unsigned e;  /* table entry flag/number of extra bits */
+  unsigned n, d;        /* length and index for copy */
+  unsigned w;           /* current window position */
+  struct huft *t;       /* pointer to table entry */
+  unsigned ml, md;      /* masks for bl and bd bits */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+  unsigned u;           /* true if unflushed */
+
+
+  /* explode the coded data */
+  b = k = w = 0;                /* initialize bit buffer, window */
+  u = 1;                        /* buffer unflushed */
+  ml = mask_bits[bl];           /* precompute masks for speed */
+  md = mask_bits[bd];
+  s = G.ucsize;
+  while (s > 0)                 /* do until ucsize bytes uncompressed */
+  {
+    NEEDBITS(1)
+    if (b & 1)                  /* then literal--get eight bits */
+    {
+      DUMPBITS(1)
+      s--;
+      NEEDBITS(8)
+      redirSlide[w++] = (uch)b;
+      if (w == wsize)
+      {
+        flush(__G__ redirSlide, (ulg)w, 0);
+        w = u = 0;
+      }
+      DUMPBITS(8)
+    }
+    else                        /* else distance/length */
+    {
+      DUMPBITS(1)
+      NEEDBITS(6)               /* get distance low bits */
+      d = (unsigned)b & 0x3f;
+      DUMPBITS(6)
+      NEEDBITS((unsigned)bd)    /* get coded distance high bits */
+      if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      d = w - d - t->v.n;       /* construct offset */
+      NEEDBITS((unsigned)bl)    /* get coded length */
+      if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      n = t->v.n;
+      if (e)                    /* get length extra bits */
+      {
+        NEEDBITS(8)
+        n += (unsigned)b & 0xff;
+        DUMPBITS(8)
+      }
+
+      /* do the copy */
+      s -= n;
+      do {
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+        if (G.redirect_slide) {
+          /* &= w/ wsize not needed and wrong if redirect */
+          if (d >= wsize)
+            return 1;
+          n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e);
+        } else
+#endif
+        n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e);
+        if (u && w <= d)
+        {
+          memzero(redirSlide + w, e);
+          w += e;
+          d += e;
+        }
+        else
+#ifndef NOMEMCPY
+          if (w - d >= e)       /* (this test assumes unsigned comparison) */
+          {
+            memcpy(redirSlide + w, redirSlide + d, e);
+            w += e;
+            d += e;
+          }
+          else                  /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+            do {
+              redirSlide[w++] = redirSlide[d++];
+            } while (--e);
+        if (w == wsize)
+        {
+          flush(__G__ redirSlide, (ulg)w, 0);
+          w = u = 0;
+        }
+      } while (n);
+    }
+  }
+
+  /* flush out redirSlide */
+  flush(__G__ redirSlide, (ulg)w, 0);
+  if (G.csize + G.incnt + (k >> 3))   /* should have read csize bytes, but */
+  {                        /* sometimes read one too many:  k>>3 compensates */
+    G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3);
+    return 5;
+  }
+  return 0;
+}
+
+
+
+int explode(__G)
+     __GDEF
+/* Explode an imploded compressed stream.  Based on the general purpose
+   bit flag, decide on coded or uncoded literals, and an 8K or 4K sliding
+   window.  Construct the literal (if any), length, and distance codes and
+   the tables needed to decode them (using huft_build() from inflate.c),
+   and call the appropriate routine for the type of data in the remainder
+   of the stream.  The four routines are nearly identical, differing only
+   in whether the literal is decoded or simply read in, and in how many
+   bits are read in, uncoded, for the low distance bits. */
+{
+  unsigned r;           /* return codes */
+  struct huft *tb;      /* literal code table */
+  struct huft *tl;      /* length code table */
+  struct huft *td;      /* distance code table */
+  int bb;               /* bits for tb */
+  int bl;               /* bits for tl */
+  int bd;               /* bits for td */
+  unsigned l[256];      /* bit lengths for codes */
+
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+  if (G.redirect_slide)
+    wsize = G.redirect_size, redirSlide = G.redirect_buffer;
+  else
+    wsize = WSIZE, redirSlide = slide;
+#endif
+
+  /* Tune base table sizes.  Note: I thought that to truly optimize speed,
+     I would have to select different bl, bd, and bb values for different
+     compressed file sizes.  I was surprised to find out that the values of
+     7, 7, and 9 worked best over a very wide range of sizes, except that
+     bd = 8 worked marginally better for large compressed sizes. */
+  bl = 7;
+  bd = (G.csize + G.incnt) > 200000L ? 8 : 7;
+
+
+  /* With literal tree--minimum match length is 3 */
+#ifdef DEBUG
+  G.hufts = 0;                    /* initialize huft's malloc'ed */
+#endif
+  if (G.lrec.general_purpose_bit_flag & 4)
+  {
+    bb = 9;                     /* base table size for literals */
+    if ((r = get_tree(__G__ l, 256)) != 0)
+      return (int)r;
+    if ((r = huft_build(__G__ l, 256, 256, NULL, NULL, &tb, &bb)) != 0)
+    {
+      if (r == 1)
+        huft_free(tb);
+      return (int)r;
+    }
+    if ((r = get_tree(__G__ l, 64)) != 0)
+      return (int)r;
+    if ((r = huft_build(__G__ l, 64, 0, cplen3, extra, &tl, &bl)) != 0)
+    {
+      if (r == 1)
+        huft_free(tl);
+      huft_free(tb);
+      return (int)r;
+    }
+    if ((r = get_tree(__G__ l, 64)) != 0)
+      return (int)r;
+    if (G.lrec.general_purpose_bit_flag & 2)      /* true if 8K */
+    {
+      if ((r = huft_build(__G__ l, 64, 0, cpdist8, extra, &td, &bd)) != 0)
+      {
+        if (r == 1)
+          huft_free(td);
+        huft_free(tl);
+        huft_free(tb);
+        return (int)r;
+      }
+      r = explode_lit8(__G__ tb, tl, td, bb, bl, bd);
+    }
+    else                                        /* else 4K */
+    {
+      if ((r = huft_build(__G__ l, 64, 0, cpdist4, extra, &td, &bd)) != 0)
+      {
+        if (r == 1)
+          huft_free(td);
+        huft_free(tl);
+        huft_free(tb);
+        return (int)r;
+      }
+      r = explode_lit4(__G__ tb, tl, td, bb, bl, bd);
+    }
+    huft_free(td);
+    huft_free(tl);
+    huft_free(tb);
+  }
+  else
+
+
+  /* No literal tree--minimum match length is 2 */
+  {
+    if ((r = get_tree(__G__ l, 64)) != 0)
+      return (int)r;
+    if ((r = huft_build(__G__ l, 64, 0, cplen2, extra, &tl, &bl)) != 0)
+    {
+      if (r == 1)
+        huft_free(tl);
+      return (int)r;
+    }
+    if ((r = get_tree(__G__ l, 64)) != 0)
+      return (int)r;
+    if (G.lrec.general_purpose_bit_flag & 2)      /* true if 8K */
+    {
+      if ((r = huft_build(__G__ l, 64, 0, cpdist8, extra, &td, &bd)) != 0)
+      {
+        if (r == 1)
+          huft_free(td);
+        huft_free(tl);
+        return (int)r;
+      }
+      r = explode_nolit8(__G__ tl, td, bl, bd);
+    }
+    else                                        /* else 4K */
+    {
+      if ((r = huft_build(__G__ l, 64, 0, cpdist4, extra, &td, &bd)) != 0)
+      {
+        if (r == 1)
+          huft_free(td);
+        huft_free(tl);
+        return (int)r;
+      }
+      r = explode_nolit4(__G__ tl, td, bl, bd);
+    }
+    huft_free(td);
+    huft_free(tl);
+  }
+  Trace((stderr, "<%u > ", G.hufts));
+  return (int)r;
+}
+
+/* so explode.c and inflate.c can be compiled together into one object: */
+#undef NEXTBYTE
+#undef NEEDBITS
+#undef DUMPBITS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/extract.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,1985 @@
+/*---------------------------------------------------------------------------
+
+  extract.c
+
+  This file contains the high-level routines ("driver routines") for extrac-
+  ting and testing zipfile members.  It calls the low-level routines in files
+  explode.c, inflate.c, unreduce.c and unshrink.c.
+
+  Contains:  extract_or_test_files()
+             store_info()
+             extract_or_test_member()
+             TestExtraField()
+             test_compr_eb()
+             memextract()
+             memflush()
+             fnfilter()
+
+  ---------------------------------------------------------------------------*/
+
+
+#define EXTRACT_C
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#include "crypt.h"
+#ifdef WINDLL
+#  ifdef POCKET_UNZIP
+#    include "wince/intrface.h"
+#  else
+#    include "windll/windll.h"
+#  endif
+#endif
+
+#define GRRDUMP(buf,len) { \
+    int i, j; \
+ \
+    for (j = 0;  j < (len)/16;  ++j) { \
+        pipeit("        "); \
+        for (i = 0;  i < 16;  ++i) \
+            pipeit("%02x ", (uch)(buf)[i+(j<<4)]); \
+        pipeit("\n        "); \
+        for (i = 0;  i < 16;  ++i) { \
+            char c = (char)(buf)[i+(j<<4)]; \
+ \
+            if (c == '\n') \
+                pipeit("\\n "); \
+            else if (c == '\r') \
+                pipeit("\\r "); \
+            else \
+                pipeit(" %c ", c); \
+        } \
+        pipeit("\n"); \
+    } \
+    if ((len) % 16) { \
+        pipeit("        "); \
+        for (i = j<<4;  i < (len);  ++i) \
+            pipeit("%02x ", (uch)(buf)[i]); \
+        pipeit("\n        "); \
+        for (i = j<<4;  i < (len);  ++i) { \
+            char c = (char)(buf)[i]; \
+ \
+            if (c == '\n') \
+                pipeit("\\n "); \
+            else if (c == '\r') \
+                pipeit("\\r "); \
+            else \
+                pipeit(" %c ", c); \
+        } \
+        pipeit("\n"); \
+    } \
+}
+
+static int store_info OF((__GPRO));
+static int extract_or_test_member OF((__GPRO));
+#ifndef SFX
+   static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len));
+   static int test_compr_eb OF((__GPRO__ uch *eb, unsigned eb_size,
+        unsigned compr_offset,
+        int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size,
+                              uch *eb_ucptr, ulg eb_ucsize)));
+#endif
+#ifdef SET_DIR_ATTRIB
+   static int dircomp OF((ZCONST zvoid *a, ZCONST zvoid *b));
+#endif
+
+
+
+/*******************************/
+/*  Strings used in extract.c  */
+/*******************************/
+
+static ZCONST char Far VersionMsg[] =
+  "   skipping: %-22s  need %s compat. v%u.%u (can do v%u.%u)\n";
+static ZCONST char Far ComprMsgNum[] =
+  "   skipping: %-22s  unsupported compression method %u\n";
+#ifndef SFX
+   static ZCONST char Far ComprMsgName[] =
+     "   skipping: %-22s  `%s' method not supported\n";
+   static ZCONST char Far CmprNone[]       = "store";
+   static ZCONST char Far CmprShrink[]     = "shrink";
+   static ZCONST char Far CmprReduce[]     = "reduce";
+   static ZCONST char Far CmprImplode[]    = "implode";
+   static ZCONST char Far CmprTokenize[]   = "tokenize";
+   static ZCONST char Far CmprDeflate[]    = "deflate";
+   static ZCONST char Far CmprEnDeflate[]  = "enhanced deflate";
+   static ZCONST char Far CmprDCLImplode[] = "DCL implode";
+   static ZCONST char Far *ComprNames[NUM_METHODS] = {
+     CmprNone, CmprShrink, CmprReduce, CmprReduce, CmprReduce, CmprReduce,
+     CmprImplode, CmprTokenize, CmprDeflate, CmprEnDeflate, CmprDCLImplode
+   };
+#endif /* !SFX */
+static ZCONST char Far FilNamMsg[] =
+  "%s:  bad filename length (%s)\n";
+static ZCONST char Far ExtFieldMsg[] =
+  "%s:  bad extra field length (%s)\n";
+static ZCONST char Far OffsetMsg[] =
+  "file #%u:  bad zipfile offset (%s):  %ld\n";
+static ZCONST char Far ExtractMsg[] =
+  "%8sing: %-22s  %s%s";
+#ifndef SFX
+   static ZCONST char Far LengthMsg[] =
+     "%s  %s:  %ld bytes required to uncompress to %lu bytes;\n    %s\
+      supposed to require %lu bytes%s%s%s\n";
+#endif
+
+static ZCONST char Far BadFileCommLength[] = "%s:  bad file comment length\n";
+static ZCONST char Far LocalHdrSig[] = "local header sig";
+static ZCONST char Far BadLocalHdr[] = "file #%u:  bad local header\n";
+static ZCONST char Far AttemptRecompensate[] =
+  "  (attempting to re-compensate)\n";
+#ifndef SFX
+   static ZCONST char Far BackslashPathSep[] =
+     "warning:  %s appears to use backslashes as path separators\n";
+#endif
+static ZCONST char Far SkipVolumeLabel[] =
+  "   skipping: %-22s  %svolume label\n";
+
+#ifdef SET_DIR_ATTRIB  /* messages of code for setting directory attributes */
+   static ZCONST char Far DirlistEntryNoMem[] =
+     "warning:  cannot alloc memory for dir times/permissions/UID/GID\n";
+   static ZCONST char Far DirlistSortNoMem[] =
+     "warning:  cannot alloc memory to sort dir times/perms/etc.\n";
+   static ZCONST char Far DirlistSetAttrFailed[] =
+     "warning:  set times/attribs failed for %s\n";
+#endif
+
+#ifndef WINDLL
+   static ZCONST char Far ReplaceQuery[] =
+     "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ";
+   static ZCONST char Far AssumeNone[] = " NULL\n(assuming [N]one)\n";
+   static ZCONST char Far NewNameQuery[] = "new name: ";
+   static ZCONST char Far InvalidResponse[] = "error:  invalid response [%c]\n";
+#endif /* !WINDLL */
+
+static ZCONST char Far ErrorInArchive[] =
+  "At least one %serror was detected in %s.\n";
+static ZCONST char Far ZeroFilesTested[] =
+  "Caution:  zero files tested in %s.\n";
+
+#ifndef VMS
+   static ZCONST char Far VMSFormatQuery[] =
+     "\n%s:  stored in VMS format.  Extract anyway? (y/n) ";
+#endif
+
+#if CRYPT
+   static ZCONST char Far SkipCannotGetPasswd[] =
+     "   skipping: %-22s  unable to get password\n";
+   static ZCONST char Far SkipIncorrectPasswd[] =
+     "   skipping: %-22s  incorrect password\n";
+   static ZCONST char Far FilesSkipBadPasswd[] =
+     "%u file%s skipped because of incorrect password.\n";
+   static ZCONST char Far MaybeBadPasswd[] =
+     "    (may instead be incorrect password)\n";
+#else
+   static ZCONST char Far SkipEncrypted[] =
+     "   skipping: %-22s  encrypted (not supported)\n";
+#endif
+
+static ZCONST char Far NoErrInCompData[] =
+  "No errors detected in compressed data of %s.\n";
+static ZCONST char Far NoErrInTestedFiles[] =
+  "No errors detected in %s for the %u file%s tested.\n";
+static ZCONST char Far FilesSkipped[] =
+  "%u file%s skipped because of unsupported compression or encoding.\n";
+
+static ZCONST char Far ErrUnzipFile[] = "  error:  %s%s %s\n";
+static ZCONST char Far ErrUnzipNoFile[] = "\n  error:  %s%s\n";
+static ZCONST char Far NotEnoughMem[] = "not enough memory to ";
+static ZCONST char Far InvalidComprData[] = "invalid compressed data to ";
+static ZCONST char Far Inflate[] = "inflate";
+
+#ifndef SFX
+   static ZCONST char Far Explode[] = "explode";
+#ifndef LZW_CLEAN
+   static ZCONST char Far Unshrink[] = "unshrink";
+#endif
+#endif
+
+#if (!defined(DELETE_IF_FULL) || !defined(HAVE_UNLINK))
+   static ZCONST char Far FileTruncated[] =
+     "warning:  %s is probably truncated\n";
+#endif
+
+static ZCONST char Far FileUnknownCompMethod[] =
+  "%s:  unknown compression method\n";
+static ZCONST char Far BadCRC[] = " bad CRC %08lx  (should be %08lx)\n";
+
+      /* TruncEAs[] also used in OS/2 mapname(), close_outfile() */
+char ZCONST Far TruncEAs[] = " compressed EA data missing (%d bytes)%s";
+char ZCONST Far TruncNTSD[] =
+  " compressed WinNT security data missing (%d bytes)%s";
+
+#ifndef SFX
+   static ZCONST char Far InconsistEFlength[] = "bad extra-field entry:\n \
+     EF block length (%u bytes) exceeds remaining EF data (%u bytes)\n";
+   static ZCONST char Far InvalidComprDataEAs[] =
+     " invalid compressed data for EAs\n";
+#  if (defined(WIN32) && defined(NTSD_EAS))
+     static ZCONST char Far InvalidSecurityEAs[] =
+       " EAs fail security check\n";
+#  endif
+   static ZCONST char Far UnsuppNTSDVersEAs[] =
+     " unsupported NTSD EAs version %d\n";
+   static ZCONST char Far BadCRC_EAs[] = " bad CRC for extended attributes\n";
+   static ZCONST char Far UnknComprMethodEAs[] =
+     " unknown compression method for EAs (%u)\n";
+   static ZCONST char Far NotEnoughMemEAs[] =
+     " out of memory while inflating EAs\n";
+   static ZCONST char Far UnknErrorEAs[] =
+     " unknown error on extended attributes\n";
+#endif /* !SFX */
+
+static ZCONST char Far UnsupportedExtraField[] =
+  "\nerror:  unsupported extra-field compression type (%u)--skipping\n";
+static ZCONST char Far BadExtraFieldCRC[] =
+  "error [%s]:  bad extra-field CRC %08lx (should be %08lx)\n";
+
+
+
+
+
+/**************************************/
+/*  Function extract_or_test_files()  */
+/**************************************/
+
+int extract_or_test_files(__G)    /* return PK-type error code */
+     __GDEF
+{
+    uch *cd_inptr;
+    unsigned i, j, filnum=0, blknum=0;
+    int cd_incnt, renamed, query;
+    int error, error_in_archive=PK_COOL, *fn_matched=NULL, *xn_matched=NULL;
+#ifdef WINDLL
+    int done_once = 0;
+#else
+    extent len;
+#endif
+    unsigned members_remaining, num_skipped=0, num_bad_pwd=0;
+    long cd_bufstart, bufstart, inbuf_offset, request;
+    LONGINT old_extra_bytes = 0L;
+#ifdef SET_DIR_ATTRIB
+    unsigned num_dirs=0;
+    dirtime *dirlist=(dirtime *)NULL, **sorted_dirlist=(dirtime **)NULL;
+#endif
+
+
+/*---------------------------------------------------------------------------
+    The basic idea of this function is as follows.  Since the central di-
+    rectory lies at the end of the zipfile and the member files lie at the
+    beginning or middle or wherever, it is not very desirable to simply
+    read a central directory entry, jump to the member and extract it, and
+    then jump back to the central directory.  In the case of a large zipfile
+    this would lead to a whole lot of disk-grinding, especially if each mem-
+    ber file is small.  Instead, we read from the central directory the per-
+    tinent information for a block of files, then go extract/test the whole
+    block.  Thus this routine contains two small(er) loops within a very
+    large outer loop:  the first of the small ones reads a block of files
+    from the central directory; the second extracts or tests each file; and
+    the outer one loops over blocks.  There's some file-pointer positioning
+    stuff in between, but that's about it.  Btw, it's because of this jump-
+    ing around that we can afford to be lenient if an error occurs in one of
+    the member files:  we should still be able to go find the other members,
+    since we know the offset of each from the beginning of the zipfile.
+  ---------------------------------------------------------------------------*/
+
+    G.pInfo = G.info;
+    members_remaining = (unsigned)G.ecrec.total_entries_central_dir;
+
+#if CRYPT
+    G.newzip = TRUE;
+#endif
+#ifndef SFX
+    G.reported_backslash = FALSE;
+#endif
+
+    /* malloc space for check on unmatched filespecs (OK if one or both NULL) */
+    if (G.filespecs > 0  &&
+        (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != (int *)NULL)
+        for (i = 0;  i < G.filespecs;  ++i)
+            fn_matched[i] = FALSE;
+    if (G.xfilespecs > 0  &&
+        (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != (int *)NULL)
+        for (i = 0;  i < G.xfilespecs;  ++i)
+            xn_matched[i] = FALSE;
+
+/*---------------------------------------------------------------------------
+    Begin main loop over blocks of member files.  We know the entire central
+    directory is on this disk:  we would not have any of this information un-
+    less the end-of-central-directory record was on this disk, and we would
+    not have gotten to this routine unless this is also the disk on which
+    the central directory starts.  In practice, this had better be the ONLY
+    disk in the archive, but we'll add multi-disk support soon.
+  ---------------------------------------------------------------------------*/
+
+    while (members_remaining) {
+        j = 0;
+#ifdef AMIGA
+        memzero(G.filenotes, DIR_BLKSIZ * sizeof(char *));
+#endif
+
+        /*
+         * Loop through files in central directory, storing offsets, file
+         * attributes, case-conversion and text-conversion flags until block
+         * size is reached.
+         */
+
+        while (members_remaining && (j < DIR_BLKSIZ)) {
+            --members_remaining;
+            G.pInfo = &G.info[j];
+
+            if (readbuf(__G__ G.sig, 4) == 0) {
+                error_in_archive = PK_EOF;
+                members_remaining = 0;  /* ...so no more left to do */
+                break;
+            }
+            if (strncmp(G.sig, central_hdr_sig, 4)) {  /* just to make sure */
+                Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg),
+                  j + blknum*DIR_BLKSIZ + 1));
+                Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
+                error_in_archive = PK_BADERR;
+                members_remaining = 0;  /* ...so no more left to do */
+                break;
+            }
+            /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */
+            if ((error = process_cdir_file_hdr(__G)) != PK_COOL) {
+                error_in_archive = error;   /* only PK_EOF defined */
+                members_remaining = 0;  /* ...so no more left to do */
+                break;
+            }
+            if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=
+                 PK_COOL)
+            {
+                if (error > error_in_archive)
+                    error_in_archive = error;
+                if (error > PK_WARN) {  /* fatal:  no more left to do */
+                    Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg),
+                      FnFilter1(G.filename), "central"));
+                    members_remaining = 0;
+                    break;
+                }
+            }
+            if ((error = do_string(__G__ G.crec.extra_field_length,
+                EXTRA_FIELD)) != 0)
+            {
+                if (error > error_in_archive)
+                    error_in_archive = error;
+                if (error > PK_WARN) {  /* fatal */
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarString(ExtFieldMsg),
+                      FnFilter1(G.filename), "central"));
+                    members_remaining = 0;
+                    break;
+                }
+            }
+#ifdef AMIGA
+            G.filenote_slot = j;
+            if ((error = do_string(__G__ G.crec.file_comment_length,
+                                   uO.N_flag ? FILENOTE : SKIP)) != PK_COOL)
+#else
+            if ((error = do_string(__G__ G.crec.file_comment_length, SKIP))
+                != PK_COOL)
+#endif
+            {
+                if (error > error_in_archive)
+                    error_in_archive = error;
+                if (error > PK_WARN) {  /* fatal */
+                    Info(slide, 0x421, ((char *)slide,
+                      LoadFarString(BadFileCommLength),
+                      FnFilter1(G.filename)));
+                    members_remaining = 0;
+                    break;
+                }
+            }
+            if (G.process_all_files) {
+                if (store_info(__G))
+                    ++j;  /* file is OK; info[] stored; continue with next */
+                else
+                    ++num_skipped;
+            } else {
+                int   do_this_file;
+
+                if (G.filespecs == 0)
+                    do_this_file = TRUE;
+                else {  /* check if this entry matches an `include' argument */
+                    do_this_file = FALSE;
+                    for (i = 0; i < G.filespecs; i++)
+                        if (match(G.filename, G.pfnames[i], uO.C_flag)) {
+                            do_this_file = TRUE;  /* ^-- ignore case or not? */
+                            if (fn_matched)
+                                fn_matched[i] = TRUE;
+                            break;       /* found match, so stop looping */
+                        }
+                }
+                if (do_this_file) {  /* check if this is an excluded file */
+                    for (i = 0; i < G.xfilespecs; i++)
+                        if (match(G.filename, G.pxnames[i], uO.C_flag)) {
+                            do_this_file = FALSE; /* ^-- ignore case or not? */
+                            if (xn_matched)
+                                xn_matched[i] = TRUE;
+                            break;
+                        }
+                }
+                if (do_this_file) {
+                    if (store_info(__G))
+                        ++j;            /* file is OK */
+                    else
+                        ++num_skipped;  /* unsupp. compression or encryption */
+                }
+            } /* end if (process_all_files) */
+
+
+        } /* end while-loop (adding files to current block) */
+
+        /* save position in central directory so can come back later */
+        cd_bufstart = G.cur_zipfile_bufstart;
+        cd_inptr = G.inptr;
+        cd_incnt = G.incnt;
+
+    /*-----------------------------------------------------------------------
+        Second loop:  process files in current block, extracting or testing
+        each one.
+      -----------------------------------------------------------------------*/
+
+        for (i = 0; i < j; ++i) {
+            filnum++;   /* filnum = i + blknum*DIR_BLKSIZ + 1; */
+            G.pInfo = &G.info[i];
+#ifdef NOVELL_BUG_FAILSAFE
+            G.dne = FALSE;  /* assume file exists until stat() says otherwise */
+#endif
+
+            /* if the target position is not within the current input buffer
+             * (either haven't yet read far enough, or (maybe) skipping back-
+             * ward), skip to the target position and reset readbuf(). */
+
+            /* ZLSEEK(pInfo->offset):  */
+            request = G.pInfo->offset + G.extra_bytes;
+            inbuf_offset = request % INBUFSIZ;
+            bufstart = request - inbuf_offset;
+
+            Trace((stderr, "\ndebug: request = %ld, inbuf_offset = %ld\n",
+              request, inbuf_offset));
+            Trace((stderr,
+              "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
+              bufstart, G.cur_zipfile_bufstart));
+            if (request < 0) {
+                Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg),
+                  G.zipfn, LoadFarString(ReportMsg)));
+                error_in_archive = PK_ERR;
+                if (filnum == 1 && G.extra_bytes != 0L) {
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarString(AttemptRecompensate)));
+                    old_extra_bytes = G.extra_bytes;
+                    G.extra_bytes = 0L;
+                    request = G.pInfo->offset;  /* could also check if != 0 */
+                    inbuf_offset = request % INBUFSIZ;
+                    bufstart = request - inbuf_offset;
+                    Trace((stderr, "debug: request = %ld, inbuf_offset = %ld\n",
+                      request, inbuf_offset));
+                    Trace((stderr,
+                      "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
+                      bufstart, G.cur_zipfile_bufstart));
+                } else {
+                    error_in_archive = PK_BADERR;
+                    continue;  /* this one hosed; try next */
+                }
+            }
+            /* try again */
+            if (request < 0) {
+                Trace((stderr, "debug: recompensated request still < 0\n"));
+                Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg),
+                  G.zipfn, LoadFarString(ReportMsg)));
+                error_in_archive = PK_BADERR;
+                continue;
+            } else if (bufstart != G.cur_zipfile_bufstart) {
+                Trace((stderr, "debug: bufstart != cur_zipfile_bufstart\n"));
+#ifdef USE_STRM_INPUT
+                fseek((FILE *)G.zipfd,(LONGINT)bufstart,SEEK_SET);
+                G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd);
+#else /* !USE_STRM_INPUT */
+                G.cur_zipfile_bufstart =
+                  lseek(G.zipfd,(LONGINT)bufstart,SEEK_SET);
+#endif /* ?USE_STRM_INPUT */
+                if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ)) <= 0)
+                {
+                    Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
+                      filnum, "lseek", bufstart));
+                    error_in_archive = PK_BADERR;
+                    continue;   /* can still do next file */
+                }
+                G.inptr = G.inbuf + (int)inbuf_offset;
+                G.incnt -= (int)inbuf_offset;
+            } else {
+                G.incnt += (int)(G.inptr-G.inbuf) - (int)inbuf_offset;
+                G.inptr = G.inbuf + (int)inbuf_offset;
+            }
+
+            /* should be in proper position now, so check for sig */
+            if (readbuf(__G__ G.sig, 4) == 0) {  /* bad offset */
+                Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
+                  filnum, "EOF", request));
+                error_in_archive = PK_BADERR;
+                continue;   /* but can still try next one */
+            }
+            if (strncmp(G.sig, local_hdr_sig, 4)) {
+                Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
+                  filnum, LoadFarStringSmall(LocalHdrSig), request));
+                /*
+                    GRRDUMP(G.sig, 4)
+                    GRRDUMP(local_hdr_sig, 4)
+                 */
+                error_in_archive = PK_ERR;
+                if ((filnum == 1 && G.extra_bytes != 0L) ||
+                    (G.extra_bytes == 0L && old_extra_bytes != 0L)) {
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarString(AttemptRecompensate)));
+                    if (G.extra_bytes) {
+                        old_extra_bytes = G.extra_bytes;
+                        G.extra_bytes = 0L;
+                    } else
+                        G.extra_bytes = old_extra_bytes;  /* third attempt */
+                    ZLSEEK(G.pInfo->offset)
+                    if (readbuf(__G__ G.sig, 4) == 0) {  /* bad offset */
+                        Info(slide, 0x401, ((char *)slide,
+                          LoadFarString(OffsetMsg), filnum, "EOF", request));
+                        error_in_archive = PK_BADERR;
+                        continue;   /* but can still try next one */
+                    }
+                    if (strncmp(G.sig, local_hdr_sig, 4)) {
+                        Info(slide, 0x401, ((char *)slide,
+                          LoadFarString(OffsetMsg), filnum,
+                          LoadFarStringSmall(LocalHdrSig), request));
+                        error_in_archive = PK_BADERR;
+                        continue;
+                    }
+                } else
+                    continue;  /* this one hosed; try next */
+            }
+            if ((error = process_local_file_hdr(__G)) != PK_COOL) {
+                Info(slide, 0x421, ((char *)slide, LoadFarString(BadLocalHdr),
+                  filnum));
+                error_in_archive = error;   /* only PK_EOF defined */
+                continue;   /* can still try next one */
+            }
+            if ((error = do_string(__G__ G.lrec.filename_length, DS_FN)) !=
+                 PK_COOL)
+            {
+                if (error > error_in_archive)
+                    error_in_archive = error;
+                if (error > PK_WARN) {
+                    Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg),
+                      FnFilter1(G.filename), "local"));
+                    continue;   /* go on to next one */
+                }
+            }
+            if (G.extra_field != (uch *)NULL) {
+                free(G.extra_field);
+                G.extra_field = (uch *)NULL;
+            }
+            if ((error =
+                 do_string(__G__ G.lrec.extra_field_length, EXTRA_FIELD)) != 0)
+            {
+                if (error > error_in_archive)
+                    error_in_archive = error;
+                if (error > PK_WARN) {
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarString(ExtFieldMsg),
+                      FnFilter1(G.filename), "local"));
+                    continue;   /* go on */
+                }
+            }
+
+#if CRYPT
+            if (G.pInfo->encrypted &&
+                (error = decrypt(__G__ uO.pwdarg)) != PK_COOL) {
+                if (error == PK_WARN) {
+                    if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
+                        Info(slide, 0x401, ((char *)slide,
+                          LoadFarString(SkipIncorrectPasswd),
+                          FnFilter1(G.filename)));
+                    ++num_bad_pwd;
+                } else {  /* (error > PK_WARN) */
+                    if (error > error_in_archive)
+                        error_in_archive = error;
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarString(SkipCannotGetPasswd),
+                      FnFilter1(G.filename)));
+                }
+                continue;   /* go on to next file */
+            }
+#endif /* CRYPT */
+
+            /*
+             * just about to extract file:  if extracting to disk, check if
+             * already exists, and if so, take appropriate action according to
+             * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper
+             * loop because we don't store the possibly renamed filename[] in
+             * info[])
+             */
+#ifdef DLL
+            if (!uO.tflag && !uO.cflag && !G.redirect_data)
+#else
+            if (!uO.tflag && !uO.cflag)
+#endif
+            {
+                renamed = FALSE;   /* user hasn't renamed output file yet */
+
+startover:
+                query = FALSE;
+                /* for files from DOS FAT, check for use of backslash instead
+                 *  of slash as directory separator (bug in some zipper(s); so
+                 *  far, not a problem in HPFS, NTFS or VFAT systems)
+                 */
+#ifndef SFX
+                if (G.pInfo->hostnum == FS_FAT_ && !strchr(G.filename, '/')) {
+                    char *p=G.filename-1;
+
+                    while (*++p) {
+                        if (*p == '\\') {
+                            if (!G.reported_backslash) {
+                                Info(slide, 0x21, ((char *)slide,
+                                  LoadFarString(BackslashPathSep), G.zipfn));
+                                G.reported_backslash = TRUE;
+                                if (!error_in_archive)
+                                    error_in_archive = PK_WARN;
+                            }
+                            *p = '/';
+                        }
+                    }
+                }
+#endif /* !SFX */
+
+                /* mapname can create dirs if not freshening or if renamed */
+                if ((error = mapname(__G__ renamed)) > PK_WARN) {
+                    if (error == IZ_CREATED_DIR) {
+#ifdef SET_DIR_ATTRIB
+                        dirtime *d_entry;
+
+                        d_entry = (dirtime *)malloc(sizeof(dirtime));
+                        if (d_entry == (dirtime *)NULL) {
+                            Info(slide, 0x401, ((char *)slide,
+                                 LoadFarString(DirlistEntryNoMem)));
+                        } else {
+                            unsigned eb_izux_flg;
+
+                            d_entry->next = dirlist;
+                            dirlist = d_entry;
+                            dirlist->fn =
+                              (char *)malloc(strlen(G.filename) + 1);
+                            if (dirlist->fn == (char *)NULL) {
+                                Info(slide, 0x401, ((char *)slide,
+                                  LoadFarString(DirlistEntryNoMem)));
+                                dirlist = d_entry->next;
+                                free(d_entry);
+                                if (!error_in_archive)
+                                    error_in_archive = PK_WARN;
+                                continue;
+                            }
+                            strcpy(dirlist->fn, G.filename);
+                            dirlist->perms = G.pInfo->file_attr;
+#ifdef USE_EF_UT_TIME
+                            eb_izux_flg = G.extra_field? ef_scan_for_izux(
+                              G.extra_field, G.lrec.extra_field_length, 0,
+                              G.lrec.last_mod_dos_datetime,
+#ifdef IZ_CHECK_TZ
+                              (G.tz_is_valid ? &(dirlist->u.t3) : NULL),
+#else
+                              &(dirlist->u.t3),
+#endif
+                              dirlist->uidgid)
+                              : 0;
+#else /* !USE_EF_UT_TIME */
+                            eb_izux_flg = 0;
+#endif /* ?USE_EF_UT_TIME */
+                            if (eb_izux_flg & EB_UT_FL_MTIME) {
+                                TTrace((stderr,
+                                  "\nextract:  Unix dir e.f. modtime = %ld\n",
+                                  dirlist->u.t3.mtime));
+                            } else {
+                                dirlist->u.t3.mtime = dos_to_unix_time(
+                                  G.lrec.last_mod_dos_datetime);
+                            }
+                            if (eb_izux_flg & EB_UT_FL_ATIME) {
+                                TTrace((stderr,
+                                  "\nextract:  Unix dir e.f. actime = %ld\n",
+                                  dirlist->u.t3.atime));
+                            } else {
+                                dirlist->u.t3.atime =
+                                  dirlist->u.t3.mtime;
+                            }
+                            dirlist->have_uidgid =
+                                (uO.X_flag && (eb_izux_flg & EB_UX2_VALID));
+                            ++num_dirs;
+                        }
+#endif /* SET_DIR_ATTRIB */
+                    } else if (error == IZ_VOL_LABEL) {
+#ifdef DOS_OS2_W32
+                        Info(slide, 0x401, ((char *)slide,
+                          LoadFarString(SkipVolumeLabel),
+                          FnFilter1(G.filename),
+                          uO.volflag? "hard disk " : ""));
+#else
+                        Info(slide, 1, ((char *)slide,
+                          LoadFarString(SkipVolumeLabel),
+                          FnFilter1(G.filename), ""));
+#endif
+                    /*  if (!error_in_archive)
+                            error_in_archive = PK_WARN;  */
+                    } else if (error > PK_ERR  &&  error_in_archive < PK_ERR)
+                        error_in_archive = PK_ERR;
+                    Trace((stderr, "mapname(%s) returns error = %d\n",
+                      FnFilter1(G.filename), error));
+                    continue;   /* go on to next file */
+                }
+
+#ifdef QDOS
+                QFilename(__G__ G.filename);
+#endif
+                switch (check_for_newer(__G__ G.filename)) {
+                    case DOES_NOT_EXIST:
+#ifdef NOVELL_BUG_FAILSAFE
+                        G.dne = TRUE;   /* stat() says file DOES NOT EXIST */
+#endif
+                        /* if freshening, don't skip if just renamed */
+                        if (uO.fflag && !renamed)
+                            continue;   /* freshen (no new files):  skip */
+                        break;
+                    case EXISTS_AND_OLDER:
+                        if (uO.overwrite_none) {
+#ifdef WINDLL
+                            char szStr[FILNAMSIZ+40]; /* add. space for text */
+
+                            if ((!G.prompt_always) || (done_once)) {
+                                sprintf(szStr,
+                                  "Target file exists.\nSkipping %s\n",
+                                  FnFilter1(G.filename));
+                                win_fprintf((zvoid *)&G, stdout,
+                                  strlen(szStr), szStr);
+                            } else {
+                                query = TRUE;
+                                break;
+                            }
+#endif /* WINDLL */
+                            continue;   /* never overwrite:  skip file */
+                        }
+#ifdef UNIXBACKUP
+                        if (!uO.overwrite_all && !uO.B_flag)
+#else
+                        if (!uO.overwrite_all)
+#endif
+                            query = TRUE;
+                        break;
+                    case EXISTS_AND_NEWER:             /* (or equal) */
+                        if (uO.overwrite_none || (uO.uflag && !renamed)) {
+#ifdef WINDLL
+                            char szStr[FILNAMSIZ+40]; /* add. space for text */
+
+                            if ((!G.prompt_always) || (done_once)) {
+                                sprintf(szStr,
+                                  "Target file newer.\nSkipping %s\n",
+                                  FnFilter1(G.filename));
+                                win_fprintf((zvoid *)&G, stdout,
+                                  strlen(szStr), szStr);
+                            } else {
+                                query = TRUE;
+                                break;
+                            }
+#endif /* WINDLL */
+                            continue;  /* skip if update/freshen & orig name */
+                        }
+#ifdef UNIXBACKUP
+                        if (!uO.overwrite_all && !uO.B_flag)
+#else
+                        if (!uO.overwrite_all)
+#endif
+                            query = TRUE;
+                        break;
+                }
+                if (query) {
+#ifdef WINDLL
+                    switch (G.lpUserFunctions->replace != NULL ?
+                            (*G.lpUserFunctions->replace)(G.filename) :
+                            IDM_REPLACE_NONE) {
+                        case IDM_REPLACE_RENAME:
+                            _ISO_INTERN(G.filename);
+                            renamed = TRUE;
+                            goto startover;
+                        case IDM_REPLACE_YES:
+                            break;
+                        case IDM_REPLACE_ALL:
+                            uO.overwrite_all = TRUE;
+                            uO.overwrite_none = FALSE;  /* just to make sure */
+                            break;
+                        case IDM_REPLACE_NONE:
+                            uO.overwrite_none = TRUE;
+                            uO.overwrite_all = FALSE;   /* make sure */
+                            done_once = TRUE;
+                            /* FALL THROUGH, skip */
+                        case IDM_REPLACE_NO:
+                            {
+                                char szStr[FILNAMSIZ+40];
+
+                                sprintf(szStr,
+                                  "Target file newer.\nSkipping %s\n",
+                                  FnFilter1(G.filename));
+                                win_fprintf((zvoid *)&G, stdout,
+                                  strlen(szStr), szStr);
+                            }
+                            continue;
+                    }
+#else /* !WINDLL */
+reprompt:
+                    Info(slide, 0x81, ((char *)slide,
+                      LoadFarString(ReplaceQuery),
+                      FnFilter1(G.filename)));
+                    if (fgets(G.answerbuf, 9, stdin) == (char *)NULL) {
+                        Info(slide, 1, ((char *)slide,
+                          LoadFarString(AssumeNone)));
+                        *G.answerbuf = 'N';
+                        if (!error_in_archive)
+                            error_in_archive = 1;  /* not extracted:  warning */
+                    }
+                    switch (*G.answerbuf) {
+                        case 'A':   /* dangerous option:  force caps */
+                            uO.overwrite_all = TRUE;
+                            uO.overwrite_none = FALSE;  /* just to make sure */
+                            break;
+                        case 'r':
+                        case 'R':
+                            do {
+                                Info(slide, 0x81, ((char *)slide,
+                                  LoadFarString(NewNameQuery)));
+                                fgets(G.filename, FILNAMSIZ, stdin);
+                                /* usually get \n here:  better check for it */
+                                len = strlen(G.filename);
+                                if (G.filename[len-1] == '\n')
+                                    G.filename[--len] = '\0';
+                            } while (len == 0);
+#ifdef WIN32  /* WIN32 fgets( ... , stdin) returns OEM coded strings */
+                            _OEM_INTERN(G.filename);
+#endif
+                            renamed = TRUE;
+                            goto startover;   /* sorry for a goto */
+                        case 'y':
+                        case 'Y':
+                            break;
+                        case 'N':
+                            uO.overwrite_none = TRUE;
+                            uO.overwrite_all = FALSE;   /* make sure */
+                            /* FALL THROUGH, skip */
+                        case 'n':
+                            continue;   /* skip file */
+                        default:
+                            Info(slide, 1, ((char *)slide,
+                              LoadFarString(InvalidResponse), *G.answerbuf));
+                            goto reprompt;   /* yet another goto? */
+                    } /* end switch (*answerbuf) */
+#endif /* ?WINDLL */
+                } /* end if (query) */
+            } /* end if (extracting to disk) */
+
+#ifdef DLL
+            if ((G.statreportcb != NULL) &&
+                (*G.statreportcb)(__G__ UZ_ST_START_EXTRACT, G.zipfn,
+                                  G.filename, NULL)) {
+                if (fn_matched)
+                    free((zvoid *)fn_matched);
+                if (xn_matched)
+                    free((zvoid *)xn_matched);
+                return IZ_CTRLC;        /* cancel operation by user request */
+            }
+#endif
+#ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */
+            UserStop();
+#endif
+#ifdef AMIGA
+            G.filenote_slot = i;
+#endif
+            G.disk_full = 0;
+            if ((error = extract_or_test_member(__G)) != PK_COOL) {
+                if (error > error_in_archive)
+                    error_in_archive = error;       /* ...and keep going */
+#ifdef DLL
+                if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) {
+#else
+                if (G.disk_full > 1) {
+#endif
+                    if (fn_matched)
+                        free((zvoid *)fn_matched);
+                    if (xn_matched)
+                        free((zvoid *)xn_matched);
+                    return error_in_archive;        /* (unless disk full) */
+                }
+            }
+#ifdef DLL
+            if ((G.statreportcb != NULL) &&
+                (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn,
+                                  G.filename, (zvoid *)&G.lrec.ucsize)) {
+                if (fn_matched)
+                    free((zvoid *)fn_matched);
+                if (xn_matched)
+                    free((zvoid *)xn_matched);
+                return IZ_CTRLC;        /* cancel operation by user request */
+            }
+#endif
+#ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */
+            UserStop();
+#endif
+        } /* end for-loop (i:  files in current block) */
+
+
+        /*
+         * Jump back to where we were in the central directory, then go and do
+         * the next batch of files.
+         */
+
+#ifdef USE_STRM_INPUT
+        fseek((FILE *)G.zipfd, (LONGINT)cd_bufstart, SEEK_SET);
+        G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd);
+#else /* !USE_STRM_INPUT */
+        G.cur_zipfile_bufstart = lseek(G.zipfd,(LONGINT)cd_bufstart,SEEK_SET);
+#endif /* ?USE_STRM_INPUT */
+        read(G.zipfd, (char *)G.inbuf, INBUFSIZ);  /* been here before... */
+        G.inptr = cd_inptr;
+        G.incnt = cd_incnt;
+        ++blknum;
+
+#ifdef TEST
+        pipeit("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart);
+        pipeit("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart,
+          cur_zipfile_bufstart);
+        pipeit("inptr-inbuf = %d\n", G.inptr-G.inbuf);
+        pipeit("incnt = %d\n\n", G.incnt);
+#endif
+
+    } /* end while-loop (blocks of files in central directory) */
+
+/*---------------------------------------------------------------------------
+    Go back through saved list of directories, sort and set times/perms/UIDs
+    and GIDs from the deepest level on up.
+  ---------------------------------------------------------------------------*/
+
+#ifdef SET_DIR_ATTRIB
+    if (num_dirs > 0) {
+        sorted_dirlist = (dirtime **)malloc(num_dirs*sizeof(dirtime *));
+        if (sorted_dirlist == (dirtime **)NULL) {
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(DirlistSortNoMem)));
+            while (dirlist != (dirtime *)NULL) {
+                dirtime *d = dirlist;
+
+                dirlist = dirlist->next;
+                free(d);
+            }
+        } else {
+            if (num_dirs == 1)
+                sorted_dirlist[0] = dirlist;
+            else {
+                for (i = 0;  i < num_dirs;  ++i) {
+                    sorted_dirlist[i] = dirlist;
+                    dirlist = dirlist->next;
+                }
+                qsort((char *)sorted_dirlist, num_dirs, sizeof(dirtime *),
+                  dircomp);
+            }
+
+            Trace((stderr, "setting directory times/perms/attributes\n"));
+            for (i = 0;  i < num_dirs;  ++i) {
+                dirtime *d = sorted_dirlist[i];
+
+                Trace((stderr, "dir = %s\n", d->fn));
+                if ((error = set_direc_attribs(__G__ d)) != PK_OK) {
+                    Info(slide, 0x201, ((char *)slide,
+                      LoadFarString(DirlistSetAttrFailed), d->fn));
+                    if (!error_in_archive)
+                        error_in_archive = error;
+                }
+                free(d->fn);
+                free(d);
+            }
+            free(sorted_dirlist);
+        }
+    }
+#endif /* SET_DIR_ATTRIB */
+
+#if (defined(WIN32) && defined(NTSD_EAS))
+    process_defer_NT(__G);  /* process any deferred items for this .zip file */
+#endif
+
+/*---------------------------------------------------------------------------
+    Check for unmatched filespecs on command line and print warning if any
+    found.  Free allocated memory.
+  ---------------------------------------------------------------------------*/
+
+    if (fn_matched) {
+        for (i = 0;  i < G.filespecs;  ++i)
+            if (!fn_matched[i]) {
+#ifdef DLL
+                if (!G.redirect_data && !G.redirect_text)
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarString(FilenameNotMatched), G.pfnames[i]));
+                else
+                    setFileNotFound(__G);
+#else
+                Info(slide, 1, ((char *)slide,
+                  LoadFarString(FilenameNotMatched), G.pfnames[i]));
+#endif
+                if (error_in_archive <= PK_WARN)
+                    error_in_archive = PK_FIND;   /* some files not found */
+            }
+        free((zvoid *)fn_matched);
+    }
+    if (xn_matched) {
+        for (i = 0;  i < G.xfilespecs;  ++i)
+            if (!xn_matched[i])
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(ExclFilenameNotMatched), G.pxnames[i]));
+        free((zvoid *)xn_matched);
+    }
+
+/*---------------------------------------------------------------------------
+    Double-check that we're back at the end-of-central-directory record, and
+    print quick summary of results, if we were just testing the archive.  We
+    send the summary to stdout so that people doing the testing in the back-
+    ground and redirecting to a file can just do a "tail" on the output file.
+  ---------------------------------------------------------------------------*/
+
+#ifndef SFX
+    if (readbuf(__G__ G.sig, 4) == 0)
+        error_in_archive = PK_EOF;
+    if (strncmp(G.sig, end_central_sig, 4)) {   /* just to make sure */
+        Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
+        Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
+        if (!error_in_archive)       /* don't overwrite stronger error */
+            error_in_archive = PK_WARN;
+    }
+#endif /* !SFX */
+    if (uO.tflag) {
+        unsigned num = filnum - num_bad_pwd;
+
+        if (uO.qflag < 2) {        /* GRR 930710:  was (uO.qflag == 1) */
+            if (error_in_archive)
+                Info(slide, 0, ((char *)slide, LoadFarString(ErrorInArchive),
+                  (error_in_archive == 1)? "warning-" : "", G.zipfn));
+            else if (num == 0)
+                Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested),
+                  G.zipfn));
+            else if (G.process_all_files && (num_skipped+num_bad_pwd == 0))
+                Info(slide, 0, ((char *)slide, LoadFarString(NoErrInCompData),
+                  G.zipfn));
+            else
+                Info(slide, 0, ((char *)slide, LoadFarString(NoErrInTestedFiles)
+                  , G.zipfn, num, (num==1)? "":"s"));
+            if (num_skipped > 0)
+                Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipped),
+                  num_skipped, (num_skipped==1)? "":"s"));
+#if CRYPT
+            if (num_bad_pwd > 0)
+                Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipBadPasswd)
+                  , num_bad_pwd, (num_bad_pwd==1)? "":"s"));
+#endif /* CRYPT */
+        } else if ((uO.qflag == 0) && !error_in_archive && (num == 0))
+            Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested),
+              G.zipfn));
+    }
+
+    /* give warning if files not tested or extracted (first condition can still
+     * happen if zipfile is empty and no files specified on command line) */
+
+    if ((filnum == 0) && error_in_archive <= PK_WARN) {
+        if (num_skipped > 0)
+            error_in_archive = IZ_UNSUP; /* unsupport. compression/encryption */
+        else
+            error_in_archive = PK_FIND;  /* no files found at all */
+    }
+#if CRYPT
+    else if ((filnum == num_bad_pwd) && error_in_archive <= PK_WARN)
+        error_in_archive = IZ_BADPWD;    /* bad passwd => all files skipped */
+#endif
+    else if ((num_skipped > 0) && error_in_archive <= PK_WARN)
+        error_in_archive = IZ_UNSUP;     /* was PK_WARN; Jean-loup complained */
+#if CRYPT
+    else if ((num_bad_pwd > 0) && !error_in_archive)
+        error_in_archive = PK_WARN;
+#endif
+
+    return error_in_archive;
+
+} /* end function extract_or_test_files() */
+
+
+
+
+
+/***************************/
+/*  Function store_info()  */
+/***************************/
+
+static int store_info(__G)   /* return 0 if skipping, 1 if OK */
+    __GDEF
+{
+#ifdef SFX
+#  define UNKN_COMPR \
+   (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED)
+#else
+#  ifdef COPYRIGHT_CLEAN  /* no reduced files */
+#    define UNKN_RED (G.crec.compression_method >= REDUCED1 && \
+                      G.crec.compression_method <= REDUCED4)
+#  else
+#    define UNKN_RED  FALSE  /* reducing not unknown */
+#  endif
+#  ifdef LZW_CLEAN  /* no shrunk files */
+#    define UNKN_SHR (G.crec.compression_method == SHRUNK)
+#  else
+#    define UNKN_SHR  FALSE  /* unshrinking not unknown */
+#  endif
+#  define UNKN_COMPR (UNKN_RED || UNKN_SHR || \
+   G.crec.compression_method==TOKENIZED || G.crec.compression_method>DEFLATED)
+#endif
+
+/*---------------------------------------------------------------------------
+    Check central directory info for version/compatibility requirements.
+  ---------------------------------------------------------------------------*/
+
+    G.pInfo->encrypted = G.crec.general_purpose_bit_flag & 1;   /* bit field */
+    G.pInfo->ExtLocHdr = (G.crec.general_purpose_bit_flag & 8) == 8;  /* bit */
+    G.pInfo->textfile = G.crec.internal_file_attributes & 1;    /* bit field */
+    G.pInfo->crc = G.crec.crc32;
+    G.pInfo->compr_size = G.crec.csize;
+    G.pInfo->uncompr_size = G.crec.ucsize;
+
+    switch (uO.aflag) {
+        case 0:
+            G.pInfo->textmode = FALSE;   /* bit field */
+            break;
+        case 1:
+            G.pInfo->textmode = G.pInfo->textfile;   /* auto-convert mode */
+            break;
+        default:  /* case 2: */
+            G.pInfo->textmode = TRUE;
+            break;
+    }
+
+    if (G.crec.version_needed_to_extract[1] == VMS_) {
+        if (G.crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) {
+            if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
+                Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
+                  FnFilter1(G.filename), "VMS",
+                  G.crec.version_needed_to_extract[0] / 10,
+                  G.crec.version_needed_to_extract[0] % 10,
+                  VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10));
+            return 0;
+        }
+#ifndef VMS   /* won't be able to use extra field, but still have data */
+        else if (!uO.tflag && !uO.overwrite_all) { /* if -o, extract anyway */
+            Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery),
+              FnFilter1(G.filename)));
+            fgets(G.answerbuf, 9, stdin);
+            if ((*G.answerbuf != 'y') && (*G.answerbuf != 'Y'))
+                return 0;
+        }
+#endif /* !VMS */
+    /* usual file type:  don't need VMS to extract */
+    } else if (G.crec.version_needed_to_extract[0] > UNZIP_VERSION) {
+        if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
+            Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
+              FnFilter1(G.filename), "PK",
+              G.crec.version_needed_to_extract[0] / 10,
+              G.crec.version_needed_to_extract[0] % 10,
+              UNZIP_VERSION / 10, UNZIP_VERSION % 10));
+        return 0;
+    }
+
+    if UNKN_COMPR {
+        if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) {
+#ifndef SFX
+            if (G.crec.compression_method < NUM_METHODS)
+                Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName),
+                  FnFilter1(G.filename),
+                  LoadFarStringSmall(ComprNames[G.crec.compression_method])));
+            else
+#endif
+                Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgNum),
+                  FnFilter1(G.filename),
+                  G.crec.compression_method));
+        }
+        return 0;
+    }
+#if (!CRYPT)
+    if (G.pInfo->encrypted) {
+        if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
+            Info(slide, 0x401, ((char *)slide, LoadFarString(SkipEncrypted),
+              FnFilter1(G.filename)));
+        return 0;
+    }
+#endif /* !CRYPT */
+
+    /* map whatever file attributes we have into the local format */
+    mapattr(__G);   /* GRR:  worry about return value later */
+
+    G.pInfo->offset = (long)G.crec.relative_offset_local_header;
+    return 1;
+
+} /* end function store_info() */
+
+
+
+
+
+/***************************************/
+/*  Function extract_or_test_member()  */
+/***************************************/
+
+static int extract_or_test_member(__G)    /* return PK-type error code */
+     __GDEF
+{
+    char *nul="[empty] ", *txt="[text]  ", *bin="[binary]";
+#ifdef CMS_MVS
+    char *ebc="[ebcdic]";
+#endif
+    register int b;
+    int r, error=PK_COOL;
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+    ulg wsize;
+#else
+#   define wsize WSIZE
+#endif
+
+
+/*---------------------------------------------------------------------------
+    Initialize variables, buffers, etc.
+  ---------------------------------------------------------------------------*/
+
+    G.bits_left = 0;
+    G.bitbuf = 0L;       /* unreduce and unshrink only */
+    G.zipeof = 0;
+    G.newfile = TRUE;
+    G.crc32val = CRCVAL_INITIAL;
+
+#ifdef SYMLINKS
+    /* if file came from Unix and is a symbolic link and we are extracting
+     * to disk, prepare to restore the link */
+    if (S_ISLNK(G.pInfo->file_attr) &&
+        (G.pInfo->hostnum == UNIX_ || G.pInfo->hostnum == ATARI_ ||
+         G.pInfo->hostnum == BEOS_) &&
+        !uO.tflag && !uO.cflag && (G.lrec.ucsize > 0))
+        G.symlnk = TRUE;
+    else
+        G.symlnk = FALSE;
+#endif /* SYMLINKS */
+
+    if (uO.tflag) {
+        if (!uO.qflag)
+            Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "test",
+              FnFilter1(G.filename), "", ""));
+    } else {
+#ifdef DLL
+        if (uO.cflag && !G.redirect_data)
+#else
+        if (uO.cflag)
+#endif
+        {
+#if (defined(OS2) && defined(__IBMC__) && (__IBMC__ >= 200))
+            G.outfile = freopen("", "wb", stdout);   /* VAC++ ignores setmode */
+#else
+            G.outfile = stdout;
+#endif
+#ifdef DOS_FLX_H68_OS2_W32
+#if (defined(__HIGHC__) && !defined(FLEXOS))
+            setmode(G.outfile, _BINARY);
+#else /* !(defined(__HIGHC__) && !defined(FLEXOS)) */
+            setmode(fileno(G.outfile), O_BINARY);
+#endif /* ?(defined(__HIGHC__) && !defined(FLEXOS)) */
+#           define NEWLINE "\r\n"
+#else /* !DOS_FLX_H68_OS2_W32 */
+#           define NEWLINE "\n"
+#endif /* ?DOS_FLX_H68_OS2_W32 */
+#ifdef VMS
+            if (open_outfile(__G))   /* VMS:  required even for stdout! */
+                return PK_DISK;
+#endif
+        } else if (open_outfile(__G))
+            return PK_DISK;
+    }
+
+/*---------------------------------------------------------------------------
+    Unpack the file.
+  ---------------------------------------------------------------------------*/
+
+    defer_leftover_input(__G);    /* so NEXTBYTE bounds check will work */
+    switch (G.lrec.compression_method) {
+        case STORED:
+            if (!uO.tflag && QCOND2) {
+#ifdef SYMLINKS
+                if (G.symlnk)   /* can also be deflated, but rarer... */
+                    Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
+                      "link", FnFilter1(G.filename), "", ""));
+                else
+#endif /* SYMLINKS */
+                Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
+                  "extract", FnFilter1(G.filename),
+                  (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
+                  "" : (G.lrec.ucsize == 0L? nul : (G.pInfo->textfile? txt :
+                  bin)), uO.cflag? NEWLINE : ""));
+            }
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+            if (G.redirect_slide) {
+                wsize = G.redirect_size; redirSlide = G.redirect_buffer;
+            } else {
+                wsize = WSIZE; redirSlide = slide;
+            }
+#endif
+            G.outptr = redirSlide;
+            G.outcnt = 0L;
+            while ((b = NEXTBYTE) != EOF && !G.disk_full) {
+                *G.outptr++ = (uch)b;
+                if (++G.outcnt == wsize) {
+                    flush(__G__ redirSlide, G.outcnt, 0);
+                    G.outptr = redirSlide;
+                    G.outcnt = 0L;
+                }
+            }
+            if (G.outcnt)          /* flush final (partial) buffer */
+                flush(__G__ redirSlide, G.outcnt, 0);
+            break;
+
+#ifndef SFX
+#ifndef LZW_CLEAN
+        case SHRUNK:
+            if (!uO.tflag && QCOND2) {
+                Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
+                  LoadFarStringSmall(Unshrink), FnFilter1(G.filename),
+                  (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
+                  "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
+            }
+            if ((r = unshrink(__G)) != PK_COOL) {
+                if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarStringSmall(ErrUnzipFile),
+                      LoadFarString(NotEnoughMem),
+                      LoadFarStringSmall2(Unshrink),
+                      FnFilter1(G.filename)));
+                else
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarStringSmall(ErrUnzipNoFile),
+                      LoadFarString(NotEnoughMem),
+                      LoadFarStringSmall2(Unshrink)));
+                error = r;
+            }
+            break;
+#endif /* !LZW_CLEAN */
+
+#ifndef COPYRIGHT_CLEAN
+        case REDUCED1:
+        case REDUCED2:
+        case REDUCED3:
+        case REDUCED4:
+            if (!uO.tflag && QCOND2) {
+                Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
+                  "unreduc", FnFilter1(G.filename),
+                  (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
+                  "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
+            }
+            unreduce(__G);
+            break;
+#endif /* !COPYRIGHT_CLEAN */
+
+        case IMPLODED:
+            if (!uO.tflag && QCOND2) {
+                Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
+                  "explod", FnFilter1(G.filename),
+                  (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
+                  "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
+            }
+            if (((r = explode(__G)) != 0) && (r != 5)) { /* treat 5 specially */
+                if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarStringSmall(ErrUnzipFile), r == 3?
+                      LoadFarString(NotEnoughMem) :
+                      LoadFarString(InvalidComprData),
+                      LoadFarStringSmall2(Explode),
+                      FnFilter1(G.filename)));
+                else
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarStringSmall(ErrUnzipNoFile), r == 3?
+                      LoadFarString(NotEnoughMem) :
+                      LoadFarString(InvalidComprData),
+                      LoadFarStringSmall2(Explode)));
+                error = (r == 3)? PK_MEM3 : PK_ERR;
+            }
+            if (r == 5) {
+                int warning = ((ulg)G.used_csize <= G.lrec.csize);
+
+                if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
+                    Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg),
+                      "", warning?  "warning" : "error", G.used_csize,
+                      G.lrec.ucsize, warning?  "  " : "", G.lrec.csize,
+                      " [", FnFilter1(G.filename), "]"));
+                else
+                    Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg),
+                      "\n", warning? "warning" : "error", G.used_csize,
+                      G.lrec.ucsize, warning? "  ":"", G.lrec.csize,
+                      "", "", "."));
+                error = warning? PK_WARN : PK_ERR;
+            }
+            break;
+#endif /* !SFX */
+
+        case DEFLATED:
+            if (!uO.tflag && QCOND2) {
+                Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
+                  "inflat", FnFilter1(G.filename),
+                  (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
+                  "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
+            }
+#ifndef USE_ZLIB  /* zlib's function is called inflate(), too */
+#  define UZinflate inflate
+#endif
+            if ((r = UZinflate(__G)) != 0) {
+                if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarStringSmall(ErrUnzipFile), r == 3?
+                      LoadFarString(NotEnoughMem) :
+                      LoadFarString(InvalidComprData),
+                      LoadFarStringSmall2(Inflate),
+                      FnFilter1(G.filename)));
+                else
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarStringSmall(ErrUnzipNoFile), r == 3?
+                      LoadFarString(NotEnoughMem) :
+                      LoadFarString(InvalidComprData),
+                      LoadFarStringSmall2(Inflate)));
+                error = (r == 3)? PK_MEM3 : PK_ERR;
+            }
+            break;
+
+        default:   /* should never get to this point */
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(FileUnknownCompMethod), FnFilter1(G.filename)));
+            /* close and delete file before return? */
+            undefer_input(__G);
+            return PK_WARN;
+
+    } /* end switch (compression method) */
+
+/*---------------------------------------------------------------------------
+    Close the file and set its date and time (not necessarily in that order),
+    and make sure the CRC checked out OK.  Logical-AND the CRC for 64-bit
+    machines (redundant on 32-bit machines).
+  ---------------------------------------------------------------------------*/
+
+#ifdef VMS                  /* VMS:  required even for stdout! (final flush) */
+    if (!uO.tflag)           /* don't close NULL file */
+        close_outfile(__G);
+#else
+#ifdef DLL
+    if (!uO.tflag && (!uO.cflag || G.redirect_data)) {
+        if (G.redirect_data)
+            FINISH_REDIRECT();
+        else
+            close_outfile(__G);
+    }
+#else
+    if (!uO.tflag && !uO.cflag)   /* don't close NULL file or stdout */
+        close_outfile(__G);
+#endif
+#endif /* VMS */
+
+            /* GRR: CONVERT close_outfile() TO NON-VOID:  CHECK FOR ERRORS! */
+
+
+    if (G.disk_full) {            /* set by flush() */
+        if (G.disk_full > 1) {
+#if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK))
+            /* delete the incomplete file if we can */
+            if (unlink(G.filename) != 0)
+                Trace((stderr, "extract.c:  could not delete %s\n",
+                  FnFilter1(G.filename)));
+#else
+            /* warn user about the incomplete file */
+            Info(slide, 0x421, ((char *)slide, LoadFarString(FileTruncated),
+              FnFilter1(G.filename)));
+#endif
+            error = PK_DISK;
+        } else {
+            error = PK_WARN;
+        }
+    }
+
+    if (error > PK_WARN) {/* don't print redundant CRC error if error already */
+        undefer_input(__G);
+        return error;
+    }
+    if (G.crc32val != G.lrec.crc32) {
+        /* if quiet enough, we haven't output the filename yet:  do it */
+        if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
+            Info(slide, 0x401, ((char *)slide, "%-22s ",
+              FnFilter1(G.filename)));
+        Info(slide, 0x401, ((char *)slide, LoadFarString(BadCRC), G.crc32val,
+          G.lrec.crc32));
+#if CRYPT
+        if (G.pInfo->encrypted)
+            Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeBadPasswd)));
+#endif
+        error = PK_ERR;
+    } else if (uO.tflag) {
+#ifndef SFX
+        if (G.extra_field) {
+            if ((r = TestExtraField(__G__ G.extra_field,
+                                    G.lrec.extra_field_length)) > error)
+                error = r;
+        } else
+#endif /* !SFX */
+        if (!uO.qflag)
+            Info(slide, 0, ((char *)slide, " OK\n"));
+    } else {
+        if (QCOND2 && !error)   /* GRR:  is stdout reset to text mode yet? */
+            Info(slide, 0, ((char *)slide, "\n"));
+    }
+
+    undefer_input(__G);
+    return error;
+
+} /* end function extract_or_test_member() */
+
+
+
+
+
+#ifndef SFX
+
+/*******************************/
+/*  Function TestExtraField()  */
+/*******************************/
+
+static int TestExtraField(__G__ ef, ef_len)
+    __GDEF
+    uch *ef;
+    unsigned ef_len;
+{
+    ush ebID;
+    unsigned ebLen;
+    unsigned eb_cmpr_offs = 0;
+    int r;
+
+    /* we know the regular compressed file data tested out OK, or else we
+     * wouldn't be here ==> print filename if any extra-field errors found
+     */
+    while (ef_len >= EB_HEADSIZE) {
+        ebID = makeword(ef);
+        ebLen = (unsigned)makeword(ef+EB_LEN);
+
+        if (ebLen > (ef_len - EB_HEADSIZE)) {
+           /* Discovered some extra field inconsistency! */
+            if (uO.qflag)
+                Info(slide, 1, ((char *)slide, "%-22s ",
+                  FnFilter1(G.filename)));
+            Info(slide, 1, ((char *)slide, LoadFarString(InconsistEFlength),
+              ebLen, (ef_len - EB_HEADSIZE)));
+            return PK_ERR;
+        }
+
+        switch (ebID) {
+            case EF_OS2:
+            case EF_ACL:
+            case EF_MAC3:
+            case EF_BEOS:
+                switch (ebID) {
+                  case EF_OS2:
+                  case EF_ACL:
+                    eb_cmpr_offs = EB_OS2_HLEN;
+                    break;
+                  case EF_MAC3:
+                    if (ebLen >= EB_MAC3_HLEN &&
+                        (makeword(ef+(EB_HEADSIZE+EB_FLGS_OFFS))
+                         & EB_M3_FL_UNCMPR) &&
+                        (makelong(ef+EB_HEADSIZE) == ebLen - EB_MAC3_HLEN))
+                        eb_cmpr_offs = 0;
+                    else
+                        eb_cmpr_offs = EB_MAC3_HLEN;
+                    break;
+                  case EF_BEOS:
+                    if (ebLen >= EB_BEOS_HLEN &&
+                        (*(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) & EB_BE_FL_UNCMPR) &&
+                        (makelong(ef+EB_HEADSIZE) == ebLen - EB_BEOS_HLEN))
+                        eb_cmpr_offs = 0;
+                    else
+                        eb_cmpr_offs = EB_BEOS_HLEN;
+                    break;
+                }
+                if ((r = test_compr_eb(__G__ ef, ebLen, eb_cmpr_offs, NULL))
+                    != PK_OK) {
+                    if (uO.qflag)
+                        Info(slide, 1, ((char *)slide, "%-22s ",
+                          FnFilter1(G.filename)));
+                    switch (r) {
+                        case IZ_EF_TRUNC:
+                            Info(slide, 1, ((char *)slide,
+                              LoadFarString(TruncEAs),
+                              ebLen-(eb_cmpr_offs+EB_CMPRHEADLEN), "\n"));
+                            break;
+                        case PK_ERR:
+                            Info(slide, 1, ((char *)slide,
+                              LoadFarString(InvalidComprDataEAs)));
+                            break;
+                        case PK_MEM3:
+                        case PK_MEM4:
+                            Info(slide, 1, ((char *)slide,
+                              LoadFarString(NotEnoughMemEAs)));
+                            break;
+                        default:
+                            if ((r & 0xff) != PK_ERR)
+                                Info(slide, 1, ((char *)slide,
+                                  LoadFarString(UnknErrorEAs)));
+                            else {
+                                ush m = (ush)(r >> 8);
+                                if (m == DEFLATED)            /* GRR KLUDGE! */
+                                    Info(slide, 1, ((char *)slide,
+                                      LoadFarString(BadCRC_EAs)));
+                                else
+                                    Info(slide, 1, ((char *)slide,
+                                      LoadFarString(UnknComprMethodEAs), m));
+                            }
+                            break;
+                    }
+                    return r;
+                }
+                break;
+
+            case EF_NTSD:
+                Trace((stderr, "ebID: %i / ebLen: %u\n", ebID, ebLen));
+                r = ebLen < EB_NTSD_L_LEN ? IZ_EF_TRUNC :
+                    ((ef[EB_HEADSIZE+EB_NTSD_VERSION] > EB_NTSD_MAX_VER) ?
+                     (PK_WARN | 0x4000) :
+                     test_compr_eb(__G__ ef, ebLen, EB_NTSD_L_LEN, TEST_NTSD));
+                if (r != PK_OK) {
+                    if (uO.qflag)
+                        Info(slide, 1, ((char *)slide, "%-22s ",
+                          FnFilter1(G.filename)));
+                    switch (r) {
+                        case IZ_EF_TRUNC:
+                            Info(slide, 1, ((char *)slide,
+                              LoadFarString(TruncNTSD),
+                              ebLen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), "\n"));
+                            break;
+#if (defined(WIN32) && defined(NTSD_EAS))
+                        case PK_WARN:
+                            Info(slide, 1, ((char *)slide,
+                              LoadFarString(InvalidSecurityEAs)));
+                            break;
+#endif
+                        case PK_ERR:
+                            Info(slide, 1, ((char *)slide,
+                              LoadFarString(InvalidComprDataEAs)));
+                            break;
+                        case PK_MEM3:
+                        case PK_MEM4:
+                            Info(slide, 1, ((char *)slide,
+                              LoadFarString(NotEnoughMemEAs)));
+                            break;
+                        case (PK_WARN | 0x4000):
+                            Info(slide, 1, ((char *)slide,
+                              LoadFarString(UnsuppNTSDVersEAs),
+                              (int)ef[EB_HEADSIZE+EB_NTSD_VERSION]));
+                            r = PK_WARN;
+                            break;
+                        default:
+                            if ((r & 0xff) != PK_ERR)
+                                Info(slide, 1, ((char *)slide,
+                                  LoadFarString(UnknErrorEAs)));
+                            else {
+                                ush m = (ush)(r >> 8);
+                                if (m == DEFLATED)            /* GRR KLUDGE! */
+                                    Info(slide, 1, ((char *)slide,
+                                      LoadFarString(BadCRC_EAs)));
+                                else
+                                    Info(slide, 1, ((char *)slide,
+                                      LoadFarString(UnknComprMethodEAs), m));
+                            }
+                            break;
+                    }
+                    return r;
+                }
+                break;
+            case EF_PKVMS:
+            case EF_PKW32:
+            case EF_PKUNIX:
+            case EF_ASIUNIX:
+            case EF_IZVMS:
+            case EF_IZUNIX:
+            case EF_VMCMS:
+            case EF_MVS:
+            case EF_SPARK:
+            case EF_AV:
+            default:
+                break;
+        }
+        ef_len -= (ebLen + EB_HEADSIZE);
+        ef += (ebLen + EB_HEADSIZE);
+    }
+
+    if (!uO.qflag)
+        Info(slide, 0, ((char *)slide, " OK\n"));
+
+    return PK_COOL;
+
+} /* end function TestExtraField() */
+
+
+
+
+
+/******************************/
+/*  Function test_compr_eb()  */
+/******************************/
+
+#ifdef PROTO
+static int test_compr_eb(
+    __GPRO__
+    uch *eb,
+    unsigned eb_size,
+    unsigned compr_offset,
+    int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size,
+                          uch *eb_ucptr, ulg eb_ucsize))
+#else /* !PROTO */
+static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata)
+    __GDEF
+    uch *eb;
+    unsigned eb_size;
+    unsigned compr_offset;
+    int (*test_uc_ebdata)();
+#endif /* ?PROTO */
+{
+    ulg eb_ucsize;
+    uch *eb_ucptr;
+    int r;
+
+    if (compr_offset < 4)                /* field is not compressed: */
+        return PK_OK;                    /* do nothing and signal OK */
+
+    if ((eb_size < (EB_UCSIZE_P + 4)) ||
+        ((eb_ucsize = makelong(eb+(EB_HEADSIZE+EB_UCSIZE_P))) > 0L &&
+         eb_size <= (compr_offset + EB_CMPRHEADLEN)))
+        return IZ_EF_TRUNC;               /* no compressed data! */
+
+    if ((eb_ucptr = (uch *)malloc((extent)eb_ucsize)) == (uch *)NULL)
+        return PK_MEM4;
+
+    r = memextract(__G__ eb_ucptr, eb_ucsize,
+                   eb + (EB_HEADSIZE + compr_offset),
+                   (ulg)(eb_size - compr_offset));
+
+    if (r == PK_OK && test_uc_ebdata != NULL)
+        r = (*test_uc_ebdata)(__G__ eb, eb_size, eb_ucptr, eb_ucsize);
+
+    free(eb_ucptr);
+    return r;
+
+} /* end function test_compr_eb() */
+
+#endif /* !SFX */
+
+
+
+
+
+/***************************/
+/*  Function memextract()  */
+/***************************/
+
+int memextract(__G__ tgt, tgtsize, src, srcsize)  /* extract compressed */
+    __GDEF                                        /*  extra field block; */
+    uch *tgt, *src;                               /*  return PK-type error */
+    ulg tgtsize, srcsize;                         /*  level */
+{
+    long old_csize=G.csize;
+    uch *old_inptr=G.inptr;
+    int  old_incnt=G.incnt;
+    int  r, error=PK_OK;
+    ush  method;
+    ulg  extra_field_crc;
+
+
+    method = makeword(src);
+    extra_field_crc = makelong(src+2);
+
+    /* compressed extra field exists completely in memory at this location: */
+    G.inptr = src + 2 + 4;      /* method and extra_field_crc */
+    G.incnt = (int)(G.csize = (long)(srcsize - (2 + 4)));
+    G.mem_mode = TRUE;
+    G.outbufptr = tgt;
+    G.outsize = tgtsize;
+
+    switch (method) {
+        case STORED:
+            memcpy((char *)tgt, (char *)G.inptr, (extent)G.incnt);
+            G.outcnt = G.csize;   /* for CRC calculation */
+            break;
+        case DEFLATED:
+            G.outcnt = 0L;
+            if ((r = UZinflate(__G)) != 0) {
+                if (!uO.tflag)
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarStringSmall(ErrUnzipNoFile), r == 3?
+                      LoadFarString(NotEnoughMem) :
+                      LoadFarString(InvalidComprData),
+                      LoadFarStringSmall2(Inflate)));
+                error = (r == 3)? PK_MEM3 : PK_ERR;
+            }
+            if (G.outcnt == 0L)   /* inflate's final FLUSH sets outcnt */
+                break;
+            break;
+        default:
+            if (uO.tflag)
+                error = PK_ERR | ((int)method << 8);
+            else {
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(UnsupportedExtraField), method));
+                error = PK_ERR;  /* GRR:  should be passed on up via SetEAs() */
+            }
+            break;
+    }
+
+    G.inptr = old_inptr;
+    G.incnt = old_incnt;
+    G.csize = old_csize;
+    G.mem_mode = FALSE;
+
+    if (!error) {
+        register ulg crcval = crc32(CRCVAL_INITIAL, tgt, (extent)G.outcnt);
+
+        if (crcval != extra_field_crc) {
+            if (uO.tflag)
+                error = PK_ERR | (DEFLATED << 8);  /* kludge for now */
+            else {
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(BadExtraFieldCRC), G.zipfn, crcval,
+                  extra_field_crc));
+                error = PK_ERR;
+            }
+        }
+    }
+    return error;
+
+} /* end function memextract() */
+
+
+
+
+
+/*************************/
+/*  Function memflush()  */
+/*************************/
+
+int memflush(__G__ rawbuf, size)
+    __GDEF
+    uch *rawbuf;
+    ulg size;
+{
+    if (size > G.outsize)
+        return 50;   /* more data than output buffer can hold */
+
+    memcpy((char *)G.outbufptr, (char *)rawbuf, (extent)size);
+    G.outbufptr += (unsigned int)size;
+    G.outsize -= size;
+    G.outcnt += size;
+
+    return 0;
+
+} /* end function memflush() */
+
+
+
+
+
+/*************************/
+/*  Function fnfilter()  */        /* here instead of in list.c for SFX */
+/*************************/
+
+char *fnfilter(raw, space)         /* convert name to safely printable form */
+    ZCONST char *raw;
+    uch *space;
+{
+#ifndef NATIVE   /* ASCII:  filter ANSI escape codes, etc. */
+    uch *r=(uch *)raw, *s=space;
+
+    while (*r) {
+#ifdef QDOS
+        if (qlflag & 2) {
+            if (*r == '/' || *r == '.') {
+                ++r;
+                *s++ = '_';
+                continue;
+            }
+        } else
+#endif
+        if (*r < 32)
+            *s++ = '^', *s++ = (uch)(64 + *r++);
+        else
+            *s++ = *r++;
+    }
+    *s = 0;
+
+#ifdef WINDLL
+    INTERN_TO_ISO((char *)space, (char *)space);  /* translate to ANSI */
+#else
+#ifdef WIN32
+    /* Win9x console always uses OEM character coding, and
+       WinNT console is set to OEM charset by default, too */
+    INTERN_TO_OEM((char *)space, (char *)space);
+#endif /* WIN32 */
+#endif /* ?WINDLL */
+
+    return (char *)space;
+
+#else /* NATIVE:  EBCDIC or whatever */
+    return (char *)raw;
+#endif
+
+} /* end function fnfilter() */
+
+
+
+
+
+#ifdef SET_DIR_ATTRIB
+/* must sort saved directories so can set perms from bottom up */
+
+/************************/
+/*  Function dircomp()  */
+/************************/
+
+static int dircomp(a, b)   /* used by qsort(); swiped from Zip */
+    ZCONST zvoid *a, *b;
+{
+    /* order is significant:  this sorts in reverse order (deepest first) */
+    return strcmp((*(dirtime **)b)->fn, (*(dirtime **)a)->fn);
+ /* return namecmp((*(dirtime **)b)->fn, (*(dirtime **)a)->fn); */
+}
+
+
+
+#if 0   /* not used in Unix, but maybe for future OSes? */
+
+/************************/
+/*  Function namecmp()  */
+/************************/
+
+static int namecmp(s1, s2)   /* [not] used by dircomp(); swiped from Zip */
+    ZCONST char *s1, *s2;
+{
+    int d;
+
+    for (;;) {
+        d = (int)(uch)case_map(*s1)
+          - (int)(uch)case_map(*s2);
+
+        if (d || *s1 == 0 || *s2 == 0)
+            return d;
+
+        s1++;
+        s2++;
+    }
+}
+
+#endif /* 0 */
+#endif /* SET_DIR_ATTRIB */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/fileio.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,2153 @@
+/*---------------------------------------------------------------------------
+
+  fileio.c
+
+  This file contains routines for doing direct but relatively generic input/
+  output, file-related sorts of things, plus some miscellaneous stuff.  Most
+  of the stuff has to do with opening, closing, reading and/or writing files.
+
+  Contains:  open_input_file()
+             open_outfile()           (non-VMS, non-AOS/VS, non-CMS_MVS)
+             undefer_input()
+             defer_leftover_input()
+             readbuf()
+             readbyte()
+             fillinbuf()
+             flush()                  (non-VMS)
+             disk_error()             (non-VMS)
+             UzpMessagePrnt()
+             UzpMessageNull()         (DLL only)
+             UzpInput()
+             UzpMorePause()
+             UzpPassword()            (non-WINDLL)
+             handler()
+             dos_to_unix_time()       (non-VMS, non-VM/CMS, non-MVS)
+             check_for_newer()        (non-VMS, non-OS/2, non-VM/CMS, non-MVS)
+             do_string()
+             makeword()
+             makelong()
+             str2iso()                (CRYPT && NEED_STR2ISO, only)
+             str2oem()                (CRYPT && NEED_STR2OEM, only)
+             memset()                 (ZMEM only)
+             memcpy()                 (ZMEM only)
+             zstrnicmp()
+             zstat()                  (REGULUS only)
+             fLoadFarString()         (SMALL_MEM only)
+             fLoadFarStringSmall()    (SMALL_MEM only)
+             fLoadFarStringSmall2()   (SMALL_MEM only)
+             zfstrcpy()               (SMALL_MEM only)
+
+  ---------------------------------------------------------------------------*/
+
+
+#define FILEIO_C
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#ifdef WINDLL
+#  include "windll/windll.h"
+#  include <setjmp.h>
+#endif
+#include "crypt.h"
+#include "ttyio.h"
+
+/* setup of codepage conversion for decryption passwords */
+#if CRYPT
+#  if (defined(CRYP_USES_ISO2OEM) && !defined(IZ_ISO2OEM_ARRAY))
+#    define IZ_ISO2OEM_ARRAY            /* pull in iso2oem[] table */
+#  endif
+#  if (defined(CRYP_USES_OEM2ISO) && !defined(IZ_OEM2ISO_ARRAY))
+#    define IZ_OEM2ISO_ARRAY            /* pull in oem2iso[] table */
+#  endif
+#endif
+#include "ebcdic.h"   /* definition/initialization of ebcdic[] */
+
+
+/*
+   Note: Under Windows, the maximum size of the buffer that can be used
+   with any of the *printf calls is 16,384, so win_fprintf was used to
+   feed the fprintf clone no more than 16K chunks at a time. This should
+   be valid for anything up to 64K (and probably beyond, assuming your
+   buffers are that big).
+*/
+#ifdef WINDLL
+#  define WriteError(buf,len,strm) \
+   (win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len))
+#else /* !WINDLL */
+#  ifdef USE_FWRITE
+#    define WriteError(buf,len,strm) \
+     ((extent)fwrite((char *)(buf),1,(extent)(len),strm) != (extent)(len))
+#  else
+#    define WriteError(buf,len,strm) \
+     ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len))
+#  endif
+#endif /* ?WINDLL */
+
+static int disk_error OF((__GPRO));
+
+
+/****************************/
+/* Strings used in fileio.c */
+/****************************/
+
+#if (defined(UNIX) || defined(DOS_FLX_OS2_W32) || defined(__BEOS__))
+   static ZCONST char Far CannotDeleteOldFile[] =
+     "error:  cannot delete old %s\n";
+#ifdef UNIXBACKUP
+   static ZCONST char Far CannotRenameOldFile[] =
+     "error:  cannot rename old %s\n";
+   static ZCONST char Far BackupSuffix[] = "~";
+#endif
+#endif /* UNIX || DOS_FLX_OS2_W32 || __BEOS__ */
+
+static ZCONST char Far CannotOpenZipfile[] =
+  "error:  cannot open zipfile [ %s ]\n";
+#if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
+   static ZCONST char Far CannotCreateFile[] = "error:  cannot create %s\n";
+#endif
+#ifdef NOVELL_BUG_FAILSAFE
+   static ZCONST char Far NovellBug[] =
+     "error:  %s: stat() says does not exist, but fopen() found anyway\n";
+#endif
+static ZCONST char Far ReadError[] = "error:  zipfile read error\n";
+static ZCONST char Far FilenameTooLongTrunc[] =
+  "warning:  filename too long--truncating.\n";
+static ZCONST char Far ExtraFieldTooLong[] =
+  "warning:  extra field too long (%d).  Ignoring...\n";
+
+#ifdef WINDLL
+   static ZCONST char Far DiskFullQuery[] =
+     "%s:  write error (disk full?).\n";
+#else
+   static ZCONST char Far DiskFullQuery[] =
+     "%s:  write error (disk full?).  Continue? (y/n/^C) ";
+   static ZCONST char Far ZipfileCorrupt[] =
+     "error:  zipfile probably corrupt (%s)\n";
+#  ifdef SYMLINKS
+     static ZCONST char Far FileIsSymLink[] =
+       "%s exists and is a symbolic link%s.\n";
+#  endif
+#  ifdef MORE
+     static ZCONST char Far MorePrompt[] = "--More--(%lu)";
+#  endif
+   static ZCONST char Far QuitPrompt[] =
+     "--- Press `Q' to quit, or any other key to continue ---";
+   static ZCONST char Far HidePrompt[] = /* "\r                       \r"; */
+     "\r                                                         \r";
+#  if CRYPT
+#    ifdef MACOS
+       /* SPC: are names on MacOS REALLY so much longer than elsewhere ??? */
+       static ZCONST char Far PasswPrompt[] = "[%s]\n %s password: ";
+#    else
+       static ZCONST char Far PasswPrompt[] = "[%s] %s password: ";
+#    endif
+     static ZCONST char Far PasswPrompt2[] = "Enter password: ";
+     static ZCONST char Far PasswRetry[] = "password incorrect--reenter: ";
+#  endif /* CRYPT */
+#endif /* !WINDLL */
+
+
+
+
+
+/******************************/
+/* Function open_input_file() */
+/******************************/
+
+int open_input_file(__G)    /* return 1 if open failed */
+    __GDEF
+{
+    /*
+     *  open the zipfile for reading and in BINARY mode to prevent cr/lf
+     *  translation, which would corrupt the bitstreams
+     */
+
+#if (defined(UNIX) || defined(TOPS20) || defined(AOS_VS) || defined(__BEOS__))
+    G.zipfd = open(G.zipfn, O_RDONLY);
+#else /* !(UNIX || TOPS20 || AOS_VS || __BEOS__) */
+#ifdef VMS
+    G.zipfd = open(G.zipfn, O_RDONLY, 0, "ctx=stm");
+#else /* !VMS */
+#ifdef MACOS
+    G.zipfd = open(G.zipfn, 0);
+#else /* !MACOS */
+#ifdef RISCOS
+    G.zipfd = fopen(G.zipfn, "rb");
+#else /* !RISCOS */
+#ifdef CMS_MVS
+    G.zipfd = vmmvs_open_infile(__G);
+#else /* !CMS_MVS */
+    G.zipfd = open(G.zipfn, O_RDONLY | O_BINARY);
+#endif /* ?CMS_MVS */
+#endif /* ?RISCOS */
+#endif /* ?MACOS */
+#endif /* ?VMS */
+#endif /* ?(UNIX || TOPS20 || AOS_VS || __BEOS__) */
+
+#ifdef USE_STRM_INPUT
+    if (G.zipfd == NULL)
+#else
+    /* if (G.zipfd < 0) */  /* no good for Windows CE port */
+    if (G.zipfd == -1)
+#endif
+    {
+        Info(slide, 0x401, ((char *)slide, LoadFarString(CannotOpenZipfile),
+          G.zipfn));
+        return 1;
+    }
+    return 0;
+
+} /* end function open_input_file() */
+
+
+
+
+#if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
+
+/***************************/
+/* Function open_outfile() */
+/***************************/
+
+int open_outfile(__G)         /* return 1 if fail */
+    __GDEF
+{
+#ifdef DLL
+    if (G.redirect_data)
+        return (redirect_outfile(__G) == FALSE);
+#endif
+#ifdef QDOS
+    QFilename(__G__ G.filename);
+#endif
+#if (defined(DOS_FLX_OS2_W32) || defined(UNIX) || defined(__BEOS__))
+#ifdef BORLAND_STAT_BUG
+    /* Borland 5.0's stat() barfs if the filename has no extension and the
+     * file doesn't exist. */
+    if (access(G.filename, 0) == -1) {
+        FILE *tmp = fopen(G.filename, "wb+");
+
+        /* file doesn't exist, so create a dummy file to keep stat() from
+         * failing (will be over-written anyway) */
+        fputc('0', tmp);  /* just to have something in the file */
+        fclose(tmp);
+    }
+#endif /* BORLAND_STAT_BUG */
+#ifdef SYMLINKS
+    if (SSTAT(G.filename, &G.statbuf) == 0 || lstat(G.filename,&G.statbuf) == 0)
+#else
+    if (SSTAT(G.filename, &G.statbuf) == 0)
+#endif /* ?SYMLINKS */
+    {
+        Trace((stderr, "open_outfile:  stat(%s) returns 0:  file exists\n",
+          FnFilter1(G.filename)));
+#ifdef UNIXBACKUP
+        if (uO.B_flag) {    /* do backup */
+            char *tname;
+            int blen, flen, tlen;
+
+            blen = strlen(BackupSuffix);
+            flen = strlen(G.filename);
+            tlen = flen + blen + 1;
+            if (tlen >= FILNAMSIZ) {   /* in case name is too long, truncate */
+                tname = (char *)malloc(FILNAMSIZ);
+                if (tname == NULL)
+                    return 1;                 /* in case we run out of space */
+                tlen = FILNAMSIZ - 1 - blen;
+                strcpy(tname, G.filename);    /* make backup name */
+                tname[tlen] = '\0';
+            } else {
+                tname = (char *)malloc(tlen);
+                if (tname == NULL)
+                    return 1;                 /* in case we run out of space */
+                strcpy(tname, G.filename);    /* make backup name */
+            }
+            strcpy(tname+flen, BackupSuffix);
+
+            /* GRR:  should check if backup file exists, apply -n/-o to that */
+            if (rename(G.filename, tname) < 0) {   /* move file */
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(CannotRenameOldFile), FnFilter1(G.filename)));
+                free(tname);
+                return 1;
+            }
+            free(tname);
+        } else
+#endif /* UNIXBACKUP */
+#ifdef DOS_FLX_OS2_W32
+        if (!(G.statbuf.st_mode & S_IWRITE)) {
+            Trace((stderr, "open_outfile:  existing file %s is read-only\n",
+              FnFilter1(G.filename)));
+            chmod(G.filename, S_IREAD | S_IWRITE);
+            Trace((stderr, "open_outfile:  %s now writable\n",
+              FnFilter1(G.filename)));
+        }
+#endif /* DOS_FLX_OS2_W32 */
+        if (unlink(G.filename) != 0) {
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(CannotDeleteOldFile), FnFilter1(G.filename)));
+            return 1;
+        }
+        Trace((stderr, "open_outfile:  %s now deleted\n",
+          FnFilter1(G.filename)));
+    }
+#endif /* DOS_FLX_OS2_W32 || UNIX || __BEOS__ */
+#ifdef RISCOS
+    if (SWI_OS_File_7(G.filename,0xDEADDEAD,0xDEADDEAD,G.lrec.ucsize)!=NULL) {
+        Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
+          FnFilter1(G.filename)));
+        return 1;
+    }
+#endif /* RISCOS */
+#ifdef TOPS20
+    char *tfilnam;
+
+    if ((tfilnam = (char *)malloc(2*strlen(G.filename)+1)) == (char *)NULL)
+        return 1;
+    strcpy(tfilnam, G.filename);
+    upper(tfilnam);
+    enquote(tfilnam);
+    if ((G.outfile = fopen(tfilnam, FOPW)) == (FILE *)NULL) {
+        Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
+          tfilnam));
+        free(tfilnam);
+        return 1;
+    }
+    free(tfilnam);
+#else /* !TOPS20 */
+#ifdef MTS
+    if (uO.aflag)
+        G.outfile = fopen(G.filename, FOPWT);
+    else
+        G.outfile = fopen(G.filename, FOPW);
+    if (G.outfile == (FILE *)NULL) {
+        Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
+          FnFilter1(G.filename)));
+        return 1;
+    }
+#else /* !MTS */
+#ifdef TANDEM
+    if (SSTAT(G.filename, &G.statbuf) == 0) {
+        Trace((stderr, "open_outfile:  stat(%s) returns 0 (file exists)\n",
+          FnFilter1(G.filename)));
+        if (unlink(G.filename) != 0) {
+            Trace((stderr, "open_outfile:  existing file %s is read-only\n",
+              FnFilter1(G.filename)));
+            chmod(G.filename, S_IRUSR | S_IWUSR);
+            Trace((stderr, "open_outfile:  %s now writable\n",
+              FnFilter1(G.filename)));
+            if (unlink(G.filename) != 0)
+                return 1;
+        }
+        Trace((stderr, "open_outfile:  %s now deleted\n",
+          FnFilter1(G.filename)));
+    }
+    if (G.pInfo->textmode)
+        G.outfile = fopen(G.filename, FOPWT);
+    else
+        G.outfile = fopen(G.filename, FOPW);
+    if (G.outfile == (FILE *)NULL) {
+        Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
+          FnFilter1(G.filename)));
+        return 1;
+    }
+#else /* !TANDEM */
+#ifdef DEBUG
+    Info(slide, 1, ((char *)slide,
+      "open_outfile:  doing fopen(%s) for reading\n", FnFilter1(G.filename)));
+    if ((G.outfile = fopen(G.filename, FOPR)) == (FILE *)NULL)
+        Info(slide, 1, ((char *)slide,
+          "open_outfile:  fopen(%s) for reading failed:  does not exist\n",
+          FnFilter1(G.filename)));
+    else {
+        Info(slide, 1, ((char *)slide,
+          "open_outfile:  fopen(%s) for reading succeeded:  file exists\n",
+          FnFilter1(G.filename)));
+        fclose(G.outfile);
+    }
+#endif /* DEBUG */
+#ifdef NOVELL_BUG_FAILSAFE
+    if (G.dne && ((G.outfile = fopen(G.filename, FOPR)) != (FILE *)NULL)) {
+        Info(slide, 0x401, ((char *)slide, LoadFarString(NovellBug),
+          FnFilter1(G.filename)));
+        fclose(G.outfile);
+        return 1;   /* with "./" fix in checkdir(), should never reach here */
+    }
+#endif /* NOVELL_BUG_FAILSAFE */
+    Trace((stderr, "open_outfile:  doing fopen(%s) for writing\n",
+      FnFilter1(G.filename)));
+    if ((G.outfile = fopen(G.filename, FOPW)) == (FILE *)NULL) {
+        Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile),
+          FnFilter1(G.filename)));
+        return 1;
+    }
+    Trace((stderr, "open_outfile:  fopen(%s) for writing succeeded\n",
+      FnFilter1(G.filename)));
+#endif /* !TANDEM */
+#endif /* !MTS */
+#endif /* !TOPS20 */
+
+#ifdef USE_FWRITE
+#ifdef DOS_OS2_W32
+    /* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE):  bogus */
+    setbuf(G.outfile, (char *)NULL);   /* make output unbuffered */
+#else /* !DOS_OS2_W32 */
+#ifndef RISCOS
+#ifdef _IOFBF  /* make output fully buffered (works just about like write()) */
+    setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE);
+#else
+    setbuf(G.outfile, (char *)slide);
+#endif
+#endif /* !RISCOS */
+#endif /* ?DOS_OS2_W32 */
+#endif /* USE_FWRITE */
+    return 0;
+
+} /* end function open_outfile() */
+
+#endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */
+
+
+
+
+
+/*
+ * These functions allow NEXTBYTE to function without needing two bounds
+ * checks.  Call defer_leftover_input() if you ever have filled G.inbuf
+ * by some means other than readbyte(), and you then want to start using
+ * NEXTBYTE.  When going back to processing bytes without NEXTBYTE, call
+ * undefer_input().  For example, extract_or_test_member brackets its
+ * central section that does the decompression with these two functions.
+ * If you need to check the number of bytes remaining in the current
+ * file while using NEXTBYTE, check (G.csize + G.incnt), not G.csize.
+ */
+
+/****************************/
+/* function undefer_input() */
+/****************************/
+
+void undefer_input(__G)
+    __GDEF
+{
+    if (G.incnt > 0)
+        G.csize += G.incnt;
+    if (G.incnt_leftover > 0) {
+        /* We know that "(G.csize < MAXINT)" so we can cast G.csize to int:
+         * This condition was checked when G.incnt_leftover was set > 0 in
+         * defer_leftover_input(), and it is NOT allowed to touch G.csize
+         * before calling undefer_input() when (G.incnt_leftover > 0)
+         * (single exception: see read_byte()'s  "G.csize <= 0" handling) !!
+         */
+        G.incnt = G.incnt_leftover + (int)G.csize;
+        G.inptr = G.inptr_leftover - (int)G.csize;
+        G.incnt_leftover = 0;
+    } else if (G.incnt < 0)
+        G.incnt = 0;
+} /* end function undefer_input() */
+
+
+
+
+
+/***********************************/
+/* function defer_leftover_input() */
+/***********************************/
+
+void defer_leftover_input(__G)
+    __GDEF
+{
+    if ((long)G.incnt > G.csize) {
+        /* (G.csize < MAXINT), we can safely cast it to int !! */
+        if (G.csize < 0L)
+            G.csize = 0L;
+        G.inptr_leftover = G.inptr + (int)G.csize;
+        G.incnt_leftover = G.incnt - (int)G.csize;
+        G.incnt = (int)G.csize;
+    } else
+        G.incnt_leftover = 0;
+    G.csize -= G.incnt;
+} /* end function defer_leftover_input() */
+
+
+
+
+
+/**********************/
+/* Function readbuf() */
+/**********************/
+
+unsigned readbuf(__G__ buf, size)   /* return number of bytes read into buf */
+    __GDEF
+    char *buf;
+    register unsigned size;
+{
+    register unsigned count;
+    unsigned n;
+
+    n = size;
+    while (size) {
+        if (G.incnt <= 0) {
+            if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0)
+                return (n-size);
+            else if (G.incnt < 0) {
+                /* another hack, but no real harm copying same thing twice */
+                (*G.message)((zvoid *)&G,
+                  (uch *)LoadFarString(ReadError),  /* CANNOT use slide */
+                  (ulg)strlen(LoadFarString(ReadError)), 0x401);
+                return 0;  /* discarding some data; better than lock-up */
+            }
+            /* buffer ALWAYS starts on a block boundary:  */
+            G.cur_zipfile_bufstart += INBUFSIZ;
+            G.inptr = G.inbuf;
+        }
+        count = MIN(size, (unsigned)G.incnt);
+        memcpy(buf, G.inptr, count);
+        buf += count;
+        G.inptr += count;
+        G.incnt -= count;
+        size -= count;
+    }
+    return n;
+
+} /* end function readbuf() */
+
+
+
+
+
+/***********************/
+/* Function readbyte() */
+/***********************/
+
+int readbyte(__G)   /* refill inbuf and return a byte if available, else EOF */
+    __GDEF
+{
+    if (G.mem_mode)
+        return EOF;
+    if (G.csize <= 0) {
+        G.csize--;             /* for tests done after exploding */
+        G.incnt = 0;
+        return EOF;
+    }
+    if (G.incnt <= 0) {
+        if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) {
+            G.incnt = 0;       /* do not allow negative value to affect stuff */
+            return EOF;
+        } else if (G.incnt < 0) {  /* "fail" (abort, retry, ...) returns this */
+            /* another hack, but no real harm copying same thing twice */
+            (*G.message)((zvoid *)&G,
+              (uch *)LoadFarString(ReadError),
+              (ulg)strlen(LoadFarString(ReadError)), 0x401);
+            echon();
+#ifdef WINDLL
+            longjmp(dll_error_return, 1);
+#else
+            DESTROYGLOBALS()
+            EXIT(PK_BADERR);    /* totally bailing; better than lock-up */
+#endif
+        }
+        G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on block bndry */
+        G.inptr = G.inbuf;
+        defer_leftover_input(__G);           /* decrements G.csize */
+    }
+
+#if CRYPT
+    if (G.pInfo->encrypted) {
+        uch *p;
+        int n;
+
+        /* This was previously set to decrypt one byte beyond G.csize, when
+         * incnt reached that far.  GRR said, "but it's required:  why?"  This
+         * was a bug in fillinbuf() -- was it also a bug here?
+         */
+        for (n = G.incnt, p = G.inptr;  n--;  p++)
+            zdecode(*p);
+    }
+#endif /* CRYPT */
+
+    --G.incnt;
+    return *G.inptr++;
+
+} /* end function readbyte() */
+
+
+
+
+
+#ifdef USE_ZLIB
+
+/************************/
+/* Function fillinbuf() */
+/************************/
+
+int fillinbuf(__G) /* like readbyte() except returns number of bytes in inbuf */
+    __GDEF
+{
+    if (G.mem_mode ||
+                  (G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0)
+        return 0;
+    G.cur_zipfile_bufstart += INBUFSIZ;  /* always starts on a block boundary */
+    G.inptr = G.inbuf;
+    defer_leftover_input(__G);           /* decrements G.csize */
+
+#if CRYPT
+    if (G.pInfo->encrypted) {
+        uch *p;
+        int n;
+
+        for (n = G.incnt, p = G.inptr;  n--;  p++)
+            zdecode(*p);
+    }
+#endif /* CRYPT */
+
+    return G.incnt;
+
+} /* end function fillinbuf() */
+
+#endif /* USE_ZLIB */
+
+
+
+
+
+#ifndef VMS  /* for VMS use code in vms.c */
+
+/********************/
+/* Function flush() */   /* returns PK error codes: */
+/********************/   /* if cflag => always 0; PK_DISK if write error */
+
+int flush(__G__ rawbuf, size, unshrink)
+    __GDEF
+    uch *rawbuf;
+    ulg size;
+    int unshrink;
+{
+    register uch *p, *q;
+    uch *transbuf;
+#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
+    ulg transbufsiz;
+#endif
+    /* static int didCRlast = FALSE;    moved to globals.h */
+
+
+/*---------------------------------------------------------------------------
+    Compute the CRC first; if testing or if disk is full, that's it.
+  ---------------------------------------------------------------------------*/
+
+    G.crc32val = crc32(G.crc32val, rawbuf, (extent)size);
+
+#ifdef DLL
+    if ((G.statreportcb != NULL) &&
+        (*G.statreportcb)(__G__ UZ_ST_IN_PROGRESS, G.zipfn, G.filename, NULL))
+        return IZ_CTRLC;        /* cancel operation by user request */
+#endif
+
+    if (uO.tflag || size == 0L)  /* testing or nothing to write:  all done */
+        return PK_OK;
+
+    if (G.disk_full)
+        return PK_DISK;         /* disk already full:  ignore rest of file */
+
+/*---------------------------------------------------------------------------
+    Write the bytes rawbuf[0..size-1] to the output device, first converting
+    end-of-lines and ASCII/EBCDIC as needed.  If SMALL_MEM or MED_MEM are NOT
+    defined, outbuf is assumed to be at least as large as rawbuf and is not
+    necessarily checked for overflow.
+  ---------------------------------------------------------------------------*/
+
+    if (!G.pInfo->textmode) {   /* write raw binary data */
+        /* GRR:  note that for standard MS-DOS compilers, size argument to
+         * fwrite() can never be more than 65534, so WriteError macro will
+         * have to be rewritten if size can ever be that large.  For now,
+         * never more than 32K.  Also note that write() returns an int, which
+         * doesn't necessarily limit size to 32767 bytes if write() is used
+         * on 16-bit systems but does make it more of a pain; however, because
+         * at least MSC 5.1 has a lousy implementation of fwrite() (as does
+         * DEC Ultrix cc), write() is used anyway.
+         */
+#ifdef DLL
+        if (G.redirect_data)
+            writeToMemory(__G__ rawbuf, size);
+        else
+#endif
+        if (!uO.cflag && WriteError(rawbuf, size, G.outfile))
+            return disk_error(__G);
+        else if (uO.cflag && (*G.message)((zvoid *)&G, rawbuf, size, 0))
+            return 0;
+    } else {   /* textmode:  aflag is true */
+        if (unshrink) {
+            /* rawbuf = outbuf */
+            transbuf = G.outbuf2;
+#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
+            transbufsiz = TRANSBUFSIZ;
+#endif
+        } else {
+            /* rawbuf = slide */
+            transbuf = G.outbuf;
+#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
+            transbufsiz = OUTBUFSIZ;
+            Trace((stderr, "\ntransbufsiz = OUTBUFSIZ = %u\n", OUTBUFSIZ));
+#endif
+        }
+        if (G.newfile) {
+#ifdef VMS_TEXT_CONV
+            /* GRR: really want to check if -aa (or -aaa?) was given... */
+            if (rawbuf[1]) {       /* first line is more than 255 chars long */
+                Trace((stderr,
+      "\nfirst line of VMS `text' too long; switching to normal extraction\n"));
+                G.VMS_line_state = -1;   /* -1: don't treat as VMS text */
+            } else
+                G.VMS_line_state = 0;    /* 0: ready to read line length */
+#endif
+            G.didCRlast = FALSE;         /* no previous buffers written */
+            G.newfile = FALSE;
+        }
+
+#ifdef VMS_TEXT_CONV
+        if (G.pInfo->hostnum == VMS_ && G.extra_field && G.VMS_line_state >= 0)
+        {
+            /* GRR: really want to check for actual VMS extra field, and
+             *      ideally for variable-length record format */
+/*
+            printf("\n>>>>>> GRR:  file is VMS text and has an extra field\n");
+ */
+
+            p = rawbuf;
+            q = transbuf;
+            while(p < rawbuf+(unsigned)size) {
+                switch (G.VMS_line_state) {
+
+                    /* 0: ready to read line length */
+                    case 0:
+                        G.VMS_line_length = 0;
+                        G.VMS_line_pad = 0;
+                        if (p == rawbuf+(unsigned)size-1) {    /* last char */
+                            G.VMS_line_length = (int)((uch)(*p++));
+                            G.VMS_line_state = 1;
+                        } else {
+                            G.VMS_line_length = makeword(p);
+                            p += 2;
+                            G.VMS_line_state = 2;
+                        }
+                        if (G.VMS_line_length & 1)   /* odd */
+                            G.VMS_line_pad = 1;
+                        break;
+
+                    /* 1: read one byte of length, need second */
+                    case 1:
+                        G.VMS_line_length += ((int)((uch)(*p++)) << 8);
+                        G.VMS_line_state = 2;
+                        break;
+
+                    /* 2: ready to read VMS_line_length chars */
+                    case 2:
+                        if (G.VMS_line_length < rawbuf+(unsigned)size-p) {
+                            if (G.VMS_line_length >=
+                                transbuf+(unsigned)transbufsiz-q)
+                            {
+                                int outroom = transbuf+(unsigned)transbufsiz-q;
+
+/* GRR:  need to change this to *q++ = native(*p++); loop or something */
+                                memcpy(q, p, outroom);
+#ifdef DLL
+                                if (G.redirect_data)
+                                    writeToMemory(__G__ transbuf,
+                                      (unsigned)outroom);
+                                else
+#endif
+                                if (!uO.cflag && WriteError(transbuf,
+                                    (unsigned)outroom, G.outfile))
+                                    return disk_error(__G);
+                                else if (uO.cflag && (*G.message)((zvoid *)&G,
+                                         transbuf, (ulg)outroom, 0))
+                                    return 0;
+                                q = transbuf;
+                                p += outroom;
+                                G.VMS_line_length -= outroom;
+                                /* fall through to normal case */
+                            }
+/* GRR:  need to change this to *q++ = native(*p++); loop or something */
+                            memcpy(q, p, G.VMS_line_length);
+                            q += G.VMS_line_length;
+                            p += G.VMS_line_length;
+                            G.VMS_line_length = 0;   /* necessary?? */
+                            G.VMS_line_state = 3;
+
+                        } else {  /* remaining input is less than full line */
+                            int remaining = rawbuf+(unsigned)size-p;
+
+                            if (remaining <
+                                transbuf+(unsigned)transbufsiz-q)
+                            {
+                                int outroom = transbuf+(unsigned)transbufsiz-q;
+
+/* GRR:  need to change this to *q++ = native(*p++); loop or something */
+                                memcpy(q, p, outroom);
+#ifdef DLL
+                                if (G.redirect_data)
+                                    writeToMemory(__G__ transbuf,
+                                      (unsigned)(outroom));
+                                else
+#endif
+                                if (!uO.cflag && WriteError(transbuf,
+                                    (unsigned)outroom, G.outfile))
+                                    return disk_error(__G);
+                                else if (uO.cflag && (*G.message)((zvoid *)&G,
+                                         transbuf, (ulg)outroom, 0))
+                                    return 0;
+                                q = transbuf;
+                                p += outroom;
+                                remaining -= outroom;
+                            }
+/* GRR:  need to change this to *q++ = native(*p++); loop or something */
+                            memcpy(q, p, remaining);
+                            q += remaining;
+                            p += remaining;
+                            G.VMS_line_length -= remaining;
+                            /* no change in G.VMS_line_state */
+                        }
+                        break;
+
+                    /* 3: ready to PutNativeEOL */
+                    case 3:
+                        if (q > transbuf+(unsigned)transbufsiz-lenEOL) {
+#ifdef DLL
+                            if (G.redirect_data)
+                                writeToMemory(__G__ transbuf,
+                                  (unsigned)(q-transbuf));
+                            else
+#endif
+                            if (!uO.cflag &&
+                                WriteError(transbuf, (unsigned)(q-transbuf),
+                                  G.outfile))
+                                return disk_error(__G);
+                            else if (uO.cflag && (*G.message)((zvoid *)&G,
+                                     transbuf, (ulg)(q-transbuf), 0))
+                                return 0;
+                            q = transbuf;
+                        }
+                        PutNativeEOL
+                        if (G.VMS_line_pad)
+                            if (p < rawbuf+(unsigned)size) {
+                                ++p;
+                                G.VMS_line_state = 0;
+                            } else
+                                G.VMS_line_state = 4;
+                        else
+                            G.VMS_line_state = 0;
+                        break;
+
+                    /* 4: ready to read pad byte */
+                    case 4:
+                        ++p;
+                        G.VMS_line_state = 0;
+                        break;
+                }
+            } /* end while */
+
+        } else
+#endif /* VMS_TEXT_CONV */
+
+    /*-----------------------------------------------------------------------
+        Algorithm:  CR/LF => native; lone CR => native; lone LF => native.
+        This routine is only for non-raw-VMS, non-raw-VM/CMS files (i.e.,
+        stream-oriented files, not record-oriented).
+      -----------------------------------------------------------------------*/
+
+        /* else not VMS text */ {
+            p = rawbuf;
+            if (*p == LF && G.didCRlast)
+                ++p;
+            G.didCRlast = FALSE;
+            for (q = transbuf;  p < rawbuf+(unsigned)size;  ++p) {
+                if (*p == CR) {           /* lone CR or CR/LF: EOL either way */
+                    PutNativeEOL
+                    if (p == rawbuf+(unsigned)size-1)  /* last char in buffer */
+                        G.didCRlast = TRUE;
+                    else if (p[1] == LF)  /* get rid of accompanying LF */
+                        ++p;
+                } else if (*p == LF)      /* lone LF */
+                    PutNativeEOL
+                else
+#ifndef DOS_FLX_OS2_W32
+                if (*p != CTRLZ)          /* lose all ^Z's */
+#endif
+                    *q++ = native(*p);
+
+#if (defined(SMALL_MEM) || defined(MED_MEM))
+# if (lenEOL == 1)   /* don't check unshrink:  both buffers small but equal */
+                if (!unshrink)
+# endif
+                    /* check for danger of buffer overflow and flush */
+                    if (q > transbuf+(unsigned)transbufsiz-lenEOL) {
+                        Trace((stderr,
+                          "p - rawbuf = %u   q-transbuf = %u   size = %lu\n",
+                          (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size));
+                        if (!uO.cflag && WriteError(transbuf,
+                            (unsigned)(q-transbuf), G.outfile))
+                            return disk_error(__G);
+                        else if (uO.cflag && (*G.message)((zvoid *)&G,
+                                 transbuf, (ulg)(q-transbuf), 0))
+                            return 0;
+                        q = transbuf;
+                        continue;
+                    }
+#endif /* SMALL_MEM || MED_MEM */
+            }
+        }
+
+    /*-----------------------------------------------------------------------
+        Done translating:  write whatever we've got to file (or screen).
+      -----------------------------------------------------------------------*/
+
+        Trace((stderr, "p - rawbuf = %u   q-transbuf = %u   size = %lu\n",
+          (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size));
+        if (q > transbuf) {
+#ifdef DLL
+            if (G.redirect_data)
+                writeToMemory(__G__ transbuf, (unsigned)(q-transbuf));
+            else
+#endif
+            if (!uO.cflag && WriteError(transbuf, (unsigned)(q-transbuf),
+                G.outfile))
+                return disk_error(__G);
+            else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf,
+                (ulg)(q-transbuf), 0))
+                return 0;
+        }
+    }
+
+    return 0;
+
+} /* end function flush() */
+
+
+
+
+
+/*************************/
+/* Function disk_error() */
+/*************************/
+
+static int disk_error(__G)
+    __GDEF
+{
+    /* OK to use slide[] here because this file is finished regardless */
+    Info(slide, 0x4a1, ((char *)slide, LoadFarString(DiskFullQuery),
+      FnFilter1(G.filename)));
+
+#ifndef WINDLL
+    fgets(G.answerbuf, 9, stdin);
+    if (*G.answerbuf == 'y')   /* stop writing to this file */
+        G.disk_full = 1;       /*  (outfile bad?), but new OK */
+    else
+#endif
+        G.disk_full = 2;       /* no:  exit program */
+
+    return PK_DISK;
+
+} /* end function disk_error() */
+
+#endif /* !VMS */
+
+
+
+
+
+/*****************************/
+/* Function UzpMessagePrnt() */
+/*****************************/
+
+int UZ_EXP UzpMessagePrnt(pG, buf, size, flag)
+    zvoid *pG;   /* globals struct:  always passed */
+    uch *buf;    /* preformatted string to be printed */
+    ulg size;    /* length of string (may include nulls) */
+    int flag;    /* flag bits */
+{
+    /* IMPORTANT NOTE:
+     *    The name of the first parameter of UzpMessagePrnt(), which passes
+     *    the "Uz_Globs" address, >>> MUST <<< be identical to the string
+     *    expansion of the __G__ macro in the REENTRANT case (see globals.h).
+     *    This name identity is mandatory for the LoadFarString() macro
+     *    (in the SMALL_MEM case) !!!
+     */
+    int error;
+    uch *q=buf, *endbuf=buf+(unsigned)size;
+#ifdef MORE
+    uch *p=buf-1;
+#endif
+    FILE *outfp;
+
+
+/*---------------------------------------------------------------------------
+    These tests are here to allow fine-tuning of UnZip's output messages,
+    but none of them will do anything without setting the appropriate bit
+    in the flag argument of every Info() statement which is to be turned
+    *off*.  That is, all messages are currently turned on for all ports.
+    To turn off *all* messages, use the UzpMessageNull() function instead
+    of this one.
+  ---------------------------------------------------------------------------*/
+
+#if (defined(OS2) && defined(DLL))
+    if (MSG_NO_DLL2(flag))  /* if OS/2 DLL bit is set, do NOT print this msg */
+        return 0;
+#endif
+#ifdef WINDLL
+    if (MSG_NO_WDLL(flag))
+        return 0;
+#endif
+#ifdef WINDLL
+    if (MSG_NO_WGUI(flag))
+        return 0;
+#endif
+/*
+#ifdef ACORN_GUI
+    if (MSG_NO_AGUI(flag))
+        return 0;
+#endif
+ */
+#ifdef DLL                 /* don't display message if data is redirected */
+    if (((Uz_Globs *)pG)->redirect_data &&
+        !((Uz_Globs *)pG)->redirect_text)
+        return 0;
+#endif
+
+    if (MSG_STDERR(flag) && !((Uz_Globs *)pG)->UzO.tflag)
+        outfp = (FILE *)stderr;
+    else
+        outfp = (FILE *)stdout;
+
+#ifdef QUERY_TRNEWLN
+    /* some systems require termination of query prompts with '\n' to force
+     * immediate display */
+    if (MSG_MNEWLN(flag)) {   /* assumes writable buffer (e.g., slide[]) */
+        *endbuf++ = '\n';     /*  with room for one more char at end of buf */
+        ++size;               /*  (safe assumption:  only used for four */
+    }                         /*  short queries in extract.c and fileio.c) */
+#endif
+
+    if (MSG_TNEWLN(flag)) {   /* again assumes writable buffer:  fragile... */
+        if ((!size && !((Uz_Globs *)pG)->sol) ||
+            (size && (endbuf[-1] != '\n')))
+        {
+            *endbuf++ = '\n';
+            ++size;
+        }
+    }
+
+#ifdef MORE
+    /* room for --More-- and one line of overlap: */
+    ((Uz_Globs *)pG)->height = SCREENLINES - 2;
+#endif
+
+    if (MSG_LNEWLN(flag) && !((Uz_Globs *)pG)->sol) {
+        /* not at start of line:  want newline */
+#ifdef OS2DLL
+        if (!((Uz_Globs *)pG)->redirect_text) {
+#endif
+            putc('\n', outfp);
+            fflush(outfp);
+#ifdef MORE
+            if (((Uz_Globs *)pG)->M_flag)
+            {
+                ++((Uz_Globs *)pG)->numlines;
+                if (((Uz_Globs *)pG)->numlines %
+                    ((Uz_Globs *)pG)->height == 0L)    /* GRR: fix */
+                    (*((Uz_Globs *)pG)->mpause)((zvoid *)pG,
+                      LoadFarString(MorePrompt), 1);
+            }
+#endif /* MORE */
+            if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag &&
+                !isatty(1) && isatty(2))
+            {
+                /* error output from testing redirected:  also send to stderr */
+                putc('\n', stderr);
+                fflush(stderr);
+            }
+#ifdef OS2DLL
+        } else
+           REDIRECTC('\n');
+#endif
+        ((Uz_Globs *)pG)->sol = TRUE;
+    }
+
+    /* put zipfile name, filename and/or error/warning keywords here */
+
+#ifdef MORE
+    if (((Uz_Globs *)pG)->M_flag
+#ifdef OS2DLL
+         && !((Uz_Globs *)pG)->redirect_text
+#endif
+                                                 )
+    {
+        while (++p < endbuf) {
+            if (*p == '\n') {
+                ++((Uz_Globs *)pG)->numlines;
+                if (((Uz_Globs *)pG)->numlines %
+                    ((Uz_Globs *)pG)->height == 0L)    /* GRR: fix */
+                {
+                    if ((error = WriteError(q, p-q+1, outfp)) != 0)
+                        return error;
+                    fflush(outfp);
+                    ((Uz_Globs *)pG)->sol = TRUE;
+                    q = p + 1;
+                    (*((Uz_Globs *)pG)->mpause)((zvoid *)pG,
+                      LoadFarString(MorePrompt), 1);
+                }
+            }
+        } /* end while */
+        size = (ulg)(p - q);   /* remaining text */
+    }
+#endif /* MORE */
+
+    if (size) {
+#ifdef OS2DLL
+        if (!((Uz_Globs *)pG)->redirect_text) {
+#endif
+            if ((error = WriteError(q, size, outfp)) != 0)
+                return error;
+            fflush(outfp);
+            if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag &&
+                !isatty(1) && isatty(2))
+            {
+                /* error output from testing redirected:  also send to stderr */
+                if ((error = WriteError(q, size, stderr)) != 0)
+                    return error;
+                fflush(stderr);
+            }
+#ifdef OS2DLL
+        } else {                /* GRR:  this is ugly:  hide with macro */
+            if ((error = REDIRECTPRINT(q, size)) != 0)
+                return error;
+        }
+#endif
+        ((Uz_Globs *)pG)->sol = (endbuf[-1] == '\n');
+    }
+    return 0;
+
+} /* end function UzpMessagePrnt() */
+
+
+
+
+
+#ifdef DLL
+
+/*****************************/
+/* Function UzpMessageNull() */  /* convenience routine for no output at all */
+/*****************************/
+
+int UZ_EXP UzpMessageNull(pG, buf, size, flag)
+    zvoid *pG;    /* globals struct:  always passed */
+    uch *buf;     /* preformatted string to be printed */
+    ulg size;     /* length of string (may include nulls) */
+    int flag;     /* flag bits */
+{
+    return 0;
+
+} /* end function UzpMessageNull() */
+
+#endif /* DLL */
+
+
+
+
+
+/***********************/
+/* Function UzpInput() */   /* GRR:  this is a placeholder for now */
+/***********************/
+
+int UZ_EXP UzpInput(pG, buf, size, flag)
+    zvoid *pG;    /* globals struct:  always passed */
+    uch *buf;     /* preformatted string to be printed */
+    int *size;    /* (address of) size of buf and of returned string */
+    int flag;     /* flag bits (bit 0: no echo) */
+{
+    /* tell picky compilers to shut up about "unused variable" warnings */
+    pG = pG; buf = buf; flag = flag;
+
+    *size = 0;
+    return 0;
+
+} /* end function UzpInput() */
+
+
+
+
+
+#if (!defined(WINDLL) && !defined(MACOS))
+
+/***************************/
+/* Function UzpMorePause() */
+/***************************/
+
+void UZ_EXP UzpMorePause(pG, prompt, flag)
+    zvoid *pG;            /* globals struct:  always passed */
+    ZCONST char *prompt;  /* "--More--" prompt */
+    int flag;             /* 0 = any char OK; 1 = accept only '\n', ' ', q */
+	{
+#if 0
+    uch c;
+
+/*---------------------------------------------------------------------------
+    Print a prompt and wait for the user to press a key, then erase prompt
+    if possible.
+  ---------------------------------------------------------------------------*/
+
+    if (!((Uz_Globs *)pG)->sol)
+        fprintf(stderr, "\n");
+    /* numlines may or may not be used: */
+    fprintf(stderr, prompt, ((Uz_Globs *)pG)->numlines);
+    fflush(stderr);
+    if (flag & 1) {
+        do {
+            c = (uch)FGETCH(0);
+        } while (c != '\r' && c != '\n' && c != ' ' && c != 'q' && c != 'Q');
+    } else
+        c = (uch)FGETCH(0);
+
+    /* newline was not echoed, so cover up prompt line */
+    fprintf(stderr, LoadFarString(HidePrompt));
+    fflush(stderr);
+
+    if (ToLower(c) == 'q') {
+        DESTROYGLOBALS()
+        EXIT(PK_COOL);
+    }
+
+    ((Uz_Globs *)pG)->sol = TRUE;
+
+#endif
+} /* end function UzpMorePause() */
+
+#endif /* !WINDLL && !MACOS */
+
+
+
+
+#ifndef WINDLL
+
+/**************************/
+/* Function UzpPassword() */
+/**************************/
+
+int UZ_EXP UzpPassword (pG, rcnt, pwbuf, size, zfn, efn)
+    zvoid *pG;         /* pointer to UnZip's internal global vars */
+    int *rcnt;         /* retry counter */
+    char *pwbuf;       /* buffer for password */
+    int size;          /* size of password buffer */
+    ZCONST char *zfn;  /* name of zip archive */
+    ZCONST char *efn;  /* name of archive entry being processed */
+	{
+#if CRYPT
+    int r = IZ_PW_ENTERED;
+    char *m;
+    char *prompt;
+
+#ifndef REENTRANT
+    /* tell picky compilers to shut up about "unused variable" warnings */
+    pG = pG;
+#endif
+
+    if (*rcnt == 0) {           /* First call for current entry */
+        *rcnt = 2;
+        if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) {
+            sprintf(prompt, LoadFarString(PasswPrompt),
+                    FnFilter1(zfn), FnFilter2(efn));
+            m = prompt;
+        } else
+            m = (char *)LoadFarString(PasswPrompt2);
+    } else {                    /* Retry call, previous password was wrong */
+        (*rcnt)--;
+        prompt = NULL;
+        m = (char *)LoadFarString(PasswRetry);
+    }
+
+    m = getp(__G__ m, pwbuf, size);
+    if (prompt != (char *)NULL) {
+        free(prompt);
+    }
+    if (m == (char *)NULL) {
+        r = IZ_PW_ERROR;
+    }
+    else if (*pwbuf == '\0') {
+        r = IZ_PW_CANCELALL;
+    }
+    return r;
+
+#else /* !CRYPT */
+    /* tell picky compilers to shut up about "unused variable" warnings */
+    pG = pG; rcnt = rcnt; pwbuf = pwbuf; size = size; zfn = zfn; efn = efn;
+
+    return IZ_PW_ERROR;  /* internal error; function should never get called */
+#endif /* ?CRYPT */
+
+} /* end function UzpPassword() */
+
+
+
+
+
+/**********************/
+/* Function handler() */
+/**********************/
+
+void handler(signal)   /* upon interrupt, turn on echo and exit cleanly */
+    int signal;
+{
+    GETGLOBALS();
+
+#if !(defined(SIGBUS) || defined(SIGSEGV))      /* add a newline if not at */
+    (*G.message)((zvoid *)&G, slide, 0L, 0x41); /*  start of line (to stderr; */
+#endif                                          /*  slide[] should be safe) */
+
+    echon();
+
+#ifdef SIGBUS
+    if (signal == SIGBUS) {
+        Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),
+          "bus error"));
+        DESTROYGLOBALS()
+        EXIT(PK_BADERR);
+    }
+#endif /* SIGBUS */
+
+#ifdef SIGSEGV
+    if (signal == SIGSEGV) {
+        Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),
+          "segmentation violation"));
+        DESTROYGLOBALS()
+        EXIT(PK_BADERR);
+    }
+#endif /* SIGSEGV */
+
+    /* probably ctrl-C */
+    DESTROYGLOBALS()
+#if defined(AMIGA) && defined(__SASC)
+    _abort();
+#endif
+    EXIT(IZ_CTRLC);       /* was EXIT(0), then EXIT(PK_ERR) */
+}
+
+#endif /* !WINDLL */
+
+
+
+
+#if (!defined(VMS) && !defined(CMS_MVS))
+#if (!defined(OS2) || defined(TIMESTAMP))
+
+#if (!defined(HAVE_MKTIME) || defined(AMIGA) || defined(WIN32))
+/* also used in amiga/filedate.c and win32/win32.c */
+ZCONST ush ydays[] =
+    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
+#endif
+
+/*******************************/
+/* Function dos_to_unix_time() */ /* used for freshening/updating/timestamps */
+/*******************************/
+
+time_t dos_to_unix_time(dosdatetime)
+    ulg dosdatetime;
+{
+    time_t m_time;
+
+#ifdef HAVE_MKTIME
+
+    ZCONST time_t now = time(NULL);
+    struct tm *tm;
+#   define YRBASE  1900
+
+    tm = localtime(&now);
+    tm->tm_isdst = -1;          /* let mktime determine if DST is in effect */
+
+    /* dissect date */
+    tm->tm_year = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE);
+    tm->tm_mon  = ((int)(dosdatetime >> 21) & 0x0f) - 1;
+    tm->tm_mday = ((int)(dosdatetime >> 16) & 0x1f);
+
+    /* dissect time */
+    tm->tm_hour = (int)((unsigned)dosdatetime >> 11) & 0x1f;
+    tm->tm_min  = (int)((unsigned)dosdatetime >> 5) & 0x3f;
+    tm->tm_sec  = (int)((unsigned)dosdatetime << 1) & 0x3e;
+
+    m_time = mktime(tm);
+    NATIVE_TO_TIMET(m_time)     /* NOP unless MSC 7.0 or Macintosh */
+    TTrace((stderr, "  final m_time  =       %lu\n", (ulg)m_time));
+
+#else /* !HAVE_MKTIME */
+
+    int yr, mo, dy, hh, mm, ss;
+#ifdef TOPS20
+#   define YRBASE  1900
+    struct tmx *tmx;
+    char temp[20];
+#else /* !TOPS20 */
+#   define YRBASE  1970
+    int leap;
+    unsigned days;
+    struct tm *tm;
+#if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
+#ifdef WIN32
+    TIME_ZONE_INFORMATION tzinfo;
+    DWORD res;
+#else /* ! WIN32 */
+#ifndef BSD4_4   /* GRR:  change to !defined(MODERN) ? */
+#if (defined(BSD) || defined(MTS) || defined(__GO32__))
+    struct timeb tbp;
+#else /* !(BSD || MTS || __GO32__) */
+#ifdef DECLARE_TIMEZONE
+    extern time_t timezone;
+#endif
+#endif /* ?(BSD || MTS || __GO32__) */
+#endif /* !BSD4_4 */
+#endif /* ?WIN32 */
+#endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
+#endif /* ?TOPS20 */
+
+
+    /* dissect date */
+    yr = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE);
+    mo = ((int)(dosdatetime >> 21) & 0x0f) - 1;
+    dy = ((int)(dosdatetime >> 16) & 0x1f) - 1;
+
+    /* dissect time */
+    hh = (int)((unsigned)dosdatetime >> 11) & 0x1f;
+    mm = (int)((unsigned)dosdatetime >> 5) & 0x3f;
+    ss = (int)((unsigned)dosdatetime & 0x1f) * 2;
+
+#ifdef TOPS20
+    tmx = (struct tmx *)malloc(sizeof(struct tmx));
+    sprintf (temp, "%02d/%02d/%02d %02d:%02d:%02d", mo+1, dy+1, yr, hh, mm, ss);
+    time_parse(temp, tmx, (char *)0);
+    m_time = time_make(tmx);
+    free(tmx);
+
+#else /* !TOPS20 */
+
+/*---------------------------------------------------------------------------
+    Calculate the number of seconds since the epoch, usually 1 January 1970.
+  ---------------------------------------------------------------------------*/
+
+    /* leap = # of leap yrs from YRBASE up to but not including current year */
+    leap = ((yr + YRBASE - 1) / 4);   /* leap year base factor */
+
+    /* calculate days from BASE to this year and add expired days this year */
+    days = (yr * 365) + (leap - 492) + ydays[mo];
+
+    /* if year is a leap year and month is after February, add another day */
+    if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100))
+        ++days;                 /* OK through 2199 */
+
+    /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
+    m_time = (time_t)((unsigned long)(days + dy) * 86400L +
+                      (unsigned long)hh * 3600L +
+                      (unsigned long)(mm * 60 + ss));
+      /* - 1;   MS-DOS times always rounded up to nearest even second */
+    TTrace((stderr, "dos_to_unix_time:\n"));
+    TTrace((stderr, "  m_time before timezone = %lu\n", (ulg)m_time));
+
+/*---------------------------------------------------------------------------
+    Adjust for local standard timezone offset.
+  ---------------------------------------------------------------------------*/
+
+#if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
+#ifdef WIN32
+    /* account for timezone differences */
+    res = GetTimeZoneInformation(&tzinfo);
+    if (res != TIME_ZONE_ID_UNKNOWN)
+    {
+    m_time += 60*(tzinfo.Bias);
+#else /* !WIN32 */
+#if (defined(BSD) || defined(MTS) || defined(__GO32__))
+#ifdef BSD4_4
+    if ( (dosdatetime >= DOSTIME_2038_01_18) &&
+         (m_time < (time_t)0x70000000L) )
+        m_time = U_TIME_T_MAX;  /* saturate in case of (unsigned) overflow */
+    if (m_time < (time_t)0L)    /* a converted DOS time cannot be negative */
+        m_time = S_TIME_T_MAX;  /*  -> saturate at max signed time_t value */
+    if ((tm = localtime(&m_time)) != (struct tm *)NULL)
+        m_time -= tm->tm_gmtoff;                /* sec. EAST of GMT: subtr. */
+#else /* !(BSD4_4 */
+    ftime(&tbp);                                /* get `timezone' */
+    m_time += tbp.timezone * 60L;               /* seconds WEST of GMT:  add */
+#endif /* ?(BSD4_4 || __EMX__) */
+#else /* !(BSD || MTS || __GO32__) */
+    /* tzset was already called at start of process_zipfiles() */
+    /* tzset(); */              /* set `timezone' variable */
+#ifndef __BEOS__                /* BeOS DR8 has no timezones... */
+    m_time += timezone;         /* seconds WEST of GMT:  add */
+#endif
+#endif /* ?(BSD || MTS || __GO32__) */
+#endif /* ?WIN32 */
+    TTrace((stderr, "  m_time after timezone =  %lu\n", (ulg)m_time));
+
+/*---------------------------------------------------------------------------
+    Adjust for local daylight savings (summer) time.
+  ---------------------------------------------------------------------------*/
+
+#ifndef BSD4_4  /* (DST already added to tm_gmtoff, so skip tm_isdst) */
+    if ( (dosdatetime >= DOSTIME_2038_01_18) &&
+         (m_time < (time_t)0x70000000L) )
+        m_time = U_TIME_T_MAX;  /* saturate in case of (unsigned) overflow */
+    if (m_time < (time_t)0L)    /* a converted DOS time cannot be negative */
+        m_time = S_TIME_T_MAX;  /*  -> saturate at max signed time_t value */
+    TIMET_TO_NATIVE(m_time)     /* NOP unless MSC 7.0 or Macintosh */
+    if (((tm = localtime((time_t *)&m_time)) != NULL) && tm->tm_isdst)
+#ifdef WIN32
+        m_time += 60L * tzinfo.DaylightBias;    /* adjust with DST bias */
+    else
+        m_time += 60L * tzinfo.StandardBias;    /* add StdBias (normally 0) */
+#else
+        m_time -= 60L * 60L;    /* adjust for daylight savings time */
+#endif
+    NATIVE_TO_TIMET(m_time)     /* NOP unless MSC 7.0 or Macintosh */
+    TTrace((stderr, "  m_time after DST =       %lu\n", (ulg)m_time));
+#endif /* !BSD4_4 */
+#ifdef WIN32
+    }
+#endif
+#endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
+#endif /* ?TOPS20 */
+
+#endif /* ?HAVE_MKTIME */
+
+    if ( (dosdatetime >= DOSTIME_2038_01_18) &&
+         (m_time < (time_t)0x70000000L) )
+        m_time = U_TIME_T_MAX;  /* saturate in case of (unsigned) overflow */
+    if (m_time < (time_t)0L)    /* a converted DOS time cannot be negative */
+        m_time = S_TIME_T_MAX;  /*  -> saturate at max signed time_t value */
+
+    return m_time;
+
+} /* end function dos_to_unix_time() */
+
+#endif /* !OS2 || TIMESTAMP */
+#endif /* !VMS && !CMS_MVS */
+
+
+
+#if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS))
+
+/******************************/
+/* Function check_for_newer() */  /* used for overwriting/freshening/updating */
+/******************************/
+
+int check_for_newer(__G__ filename)  /* return 1 if existing file is newer */
+    __GDEF                           /*  or equal; 0 if older; -1 if doesn't */
+    char *filename;                  /*  exist yet */
+{
+    time_t existing, archive;
+#ifdef USE_EF_UT_TIME
+    iztimes z_utime;
+#endif
+#ifdef AOS_VS
+    long    dyy, dmm, ddd, dhh, dmin, dss;
+
+
+    dyy = (lrec.last_mod_dos_datetime >> 25) + 1980;
+    dmm = (lrec.last_mod_dos_datetime >> 21) & 0x0f;
+    ddd = (lrec.last_mod_dos_datetime >> 16) & 0x1f;
+    dhh = (lrec.last_mod_dos_datetime >> 11) & 0x1f;
+    dmin = (lrec.last_mod_dos_datetime >> 5) & 0x3f;
+    dss = (lrec.last_mod_dos_datetime & 0x1f) * 2;
+
+    /* under AOS/VS, file times can only be set at creation time,
+     * with the info in a special DG format.  Make sure we can create
+     * it here - we delete it later & re-create it, whether or not
+     * it exists now.
+     */
+    if (!zvs_create(filename, (((ulg)dgdate(dmm, ddd, dyy)) << 16) |
+        (dhh*1800L + dmin*30L + dss/2L), -1L, -1L, (char *) -1, -1, -1, -1))
+        return DOES_NOT_EXIST;
+#endif /* AOS_VS */
+
+    Trace((stderr, "check_for_newer:  doing stat(%s)\n", FnFilter1(filename)));
+    if (SSTAT(filename, &G.statbuf)) {
+        Trace((stderr,
+          "check_for_newer:  stat(%s) returns %d:  file does not exist\n",
+          FnFilter1(filename), SSTAT(filename, &G.statbuf)));
+#ifdef SYMLINKS
+        Trace((stderr, "check_for_newer:  doing lstat(%s)\n",
+          FnFilter1(filename)));
+        /* GRR OPTION:  could instead do this test ONLY if G.symlnk is true */
+        if (lstat(filename, &G.statbuf) == 0) {
+            Trace((stderr,
+              "check_for_newer:  lstat(%s) returns 0:  symlink does exist\n",
+              FnFilter1(filename)));
+            if (QCOND2 && !uO.overwrite_all)
+                Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink),
+                  FnFilter1(filename), " with no real file"));
+            return EXISTS_AND_OLDER;   /* symlink dates are meaningless */
+        }
+#endif /* SYMLINKS */
+        return DOES_NOT_EXIST;
+    }
+    Trace((stderr, "check_for_newer:  stat(%s) returns 0:  file exists\n",
+      FnFilter1(filename)));
+
+#ifdef SYMLINKS
+    /* GRR OPTION:  could instead do this test ONLY if G.symlnk is true */
+    if (lstat(filename, &G.statbuf) == 0 && S_ISLNK(G.statbuf.st_mode)) {
+        Trace((stderr, "check_for_newer:  %s is a symbolic link\n",
+          FnFilter1(filename)));
+        if (QCOND2 && !uO.overwrite_all)
+            Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink),
+              FnFilter1(filename), ""));
+        return EXISTS_AND_OLDER;   /* symlink dates are meaningless */
+    }
+#endif /* SYMLINKS */
+
+    NATIVE_TO_TIMET(G.statbuf.st_mtime)   /* NOP unless MSC 7.0 or Macintosh */
+
+#ifdef USE_EF_UT_TIME
+    /* The `Unix extra field mtime' should be used for comparison with the
+     * time stamp of the existing file >>>ONLY<<< when the EF info is also
+     * used to set the modification time of the extracted file.
+     */
+    if (G.extra_field &&
+#ifdef IZ_CHECK_TZ
+        G.tz_is_valid &&
+#endif
+        (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,
+                          G.lrec.last_mod_dos_datetime, &z_utime, NULL)
+         & EB_UT_FL_MTIME))
+    {
+        TTrace((stderr, "check_for_newer:  using Unix extra field mtime\n"));
+        existing = G.statbuf.st_mtime;
+        archive  = z_utime.mtime;
+    } else {
+        /* round up existing filetime to nearest 2 seconds for comparison,
+         * but saturate in case of arithmetic overflow
+         */
+        existing = ((G.statbuf.st_mtime & 1) &&
+                    (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ?
+                   G.statbuf.st_mtime + 1 : G.statbuf.st_mtime;
+        archive  = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
+    }
+#else /* !USE_EF_UT_TIME */
+    /* round up existing filetime to nearest 2 seconds for comparison,
+     * but saturate in case of arithmetic overflow
+     */
+    existing = ((G.statbuf.st_mtime & 1) &&
+                (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ?
+               G.statbuf.st_mtime + 1 : G.statbuf.st_mtime;
+    archive  = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
+#endif /* ?USE_EF_UT_TIME */
+
+    TTrace((stderr, "check_for_newer:  existing %lu, archive %lu, e-a %ld\n",
+      (ulg)existing, (ulg)archive, (long)(existing-archive)));
+
+    return (existing >= archive);
+
+} /* end function check_for_newer() */
+
+#endif /* !VMS && !OS2 && !CMS_MVS */
+
+
+
+
+
+/************************/
+/* Function do_string() */
+/************************/
+
+int do_string(__G__ len, option)      /* return PK-type error code */
+    __GDEF
+    unsigned int len;           /* without prototype, ush converted to this */
+    int option;
+{
+    long comment_bytes_left, block_length;
+    int error=PK_OK;
+    ush extra_len;
+#ifdef AMIGA
+    char tmp_fnote[2 * AMIGA_FILENOTELEN];   /* extra room for squozen chars */
+#endif
+
+
+/*---------------------------------------------------------------------------
+    This function processes arbitrary-length (well, usually) strings.  Four
+    options are allowed:  SKIP, wherein the string is skipped (pretty logical,
+    eh?); DISPLAY, wherein the string is printed to standard output after un-
+    dergoing any necessary or unnecessary character conversions; DS_FN,
+    wherein the string is put into the filename[] array after undergoing ap-
+    propriate conversions (including case-conversion, if that is indicated:
+    see the global variable pInfo->lcflag); and EXTRA_FIELD, wherein the
+    `string' is assumed to be an extra field and is copied to the (freshly
+    malloced) buffer G.extra_field.  The third option should be OK since
+    filename is dimensioned at 1025, but we check anyway.
+
+    The string, by the way, is assumed to start at the current file-pointer
+    position; its length is given by len.  So start off by checking length
+    of string:  if zero, we're already done.
+  ---------------------------------------------------------------------------*/
+
+    if (!len)
+        return PK_COOL;
+
+    switch (option) {
+
+    /*
+     * First case:  print string on standard output.  First set loop vari-
+     * ables, then loop through the comment in chunks of OUTBUFSIZ bytes,
+     * converting formats and printing as we go.  The second half of the
+     * loop conditional was added because the file might be truncated, in
+     * which case comment_bytes_left will remain at some non-zero value for
+     * all time.  outbuf and slide are used as scratch buffers because they
+     * are available (we should be either before or in between any file pro-
+     * cessing).
+     */
+
+    case DISPLAY:
+    case DISPL_8:
+        comment_bytes_left = len;
+        block_length = OUTBUFSIZ;    /* for the while statement, first time */
+        while (comment_bytes_left > 0 && block_length > 0) {
+            register uch *p = G.outbuf;
+            register uch *q = G.outbuf;
+
+            if ((block_length = readbuf(__G__ (char *)G.outbuf,
+                   (unsigned) MIN((long)OUTBUFSIZ, comment_bytes_left))) == 0)
+                return PK_EOF;
+            comment_bytes_left -= block_length;
+
+            /* this is why we allocated an extra byte for outbuf:  terminate
+             *  with zero (ASCIIZ) */
+            G.outbuf[(unsigned)block_length] = '\0';
+
+            /* remove all ASCII carriage returns from comment before printing
+             * (since used before A_TO_N(), check for CR instead of '\r')
+             */
+            while (*p) {
+                while (*p == CR)
+                    ++p;
+                *q++ = *p++;
+            }
+            /* could check whether (p - outbuf) == block_length here */
+            *q = '\0';
+
+            if (option == DISPL_8) {
+                /* translate the text coded in the entry's host-dependent
+                   "extended ASCII" charset into the compiler's (system's)
+                   internal text code page */
+                Ext_ASCII_TO_Native((char *)G.outbuf, G.pInfo->hostnum,
+                                    G.crec.version_made_by[0]);
+#ifdef WINDLL
+                /* translate to ANSI (RTL internal codepage may be OEM) */
+                INTERN_TO_ISO((char *)G.outbuf, (char *)G.outbuf);
+#else /* !WINDLL */
+#ifdef WIN32
+                /* Win9x console always uses OEM character coding, and
+                   WinNT console is set to OEM charset by default, too */
+                INTERN_TO_OEM((char *)G.outbuf, (char *)G.outbuf);
+#endif /* WIN32 */
+#endif /* ?WINDLL */
+            } else {
+                A_TO_N(G.outbuf);   /* translate string to native */
+            }
+
+#ifdef WINDLL
+            /* ran out of local mem -- had to cheat */
+            win_fprintf((zvoid *)&G, stdout, len, (char *)G.outbuf);
+            win_fprintf((zvoid *)&G, stdout, 2, (char *)"\n\n");
+#else /* !WINDLL */
+#ifdef NOANSIFILT       /* GRR:  can ANSI be used with EBCDIC? */
+            (*G.message)((zvoid *)&G, G.outbuf, (ulg)(q-G.outbuf), 0);
+#else /* ASCII, filter out ANSI escape sequences and handle ^S (pause) */
+            p = G.outbuf - 1;
+            q = slide;
+            while (*++p) {
+                int pause = FALSE;
+
+                if (*p == 0x1B) {          /* ASCII escape char */
+                    *q++ = '^';
+                    *q++ = '[';
+                } else if (*p == 0x13) {   /* ASCII ^S (pause) */
+                    pause = TRUE;
+                    if (p[1] == LF)        /* ASCII LF */
+                        *q++ = *++p;
+                    else if (p[1] == CR && p[2] == LF) {  /* ASCII CR LF */
+                        *q++ = *++p;
+                        *q++ = *++p;
+                    }
+                } else
+                    *q++ = *p;
+                if ((unsigned)(q-slide) > WSIZE-3 || pause) {   /* flush */
+                    (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);
+                    q = slide;
+                    if (pause && G.extract_flag) /* don't pause for list/test */
+                        (*G.mpause)((zvoid *)&G, LoadFarString(QuitPrompt), 0);
+                }
+            }
+            (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);
+#endif /* ?NOANSIFILT */
+#endif /* ?WINDLL */
+        }
+        /* add '\n' if not at start of line */
+        (*G.message)((zvoid *)&G, slide, 0L, 0x40);
+        break;
+
+    /*
+     * Second case:  read string into filename[] array.  The filename should
+     * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check,
+     * just to be sure.
+     */
+
+    case DS_FN:
+        extra_len = 0;
+        if (len >= FILNAMSIZ) {
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(FilenameTooLongTrunc)));
+            error = PK_WARN;
+            extra_len = (ush)(len - FILNAMSIZ + 1);
+            len = FILNAMSIZ - 1;
+        }
+        if (readbuf(__G__  G.filename, len) == 0)
+            return PK_EOF;
+        G.filename[len] = '\0';   /* terminate w/zero:  ASCIIZ */
+
+        /* translate the Zip entry filename coded in host-dependent "extended
+           ASCII" into the compiler's (system's) internal text code page */
+        Ext_ASCII_TO_Native(G.filename, G.pInfo->hostnum,
+                            G.crec.version_made_by[0]);
+
+        if (G.pInfo->lcflag)      /* replace with lowercase filename */
+            TOLOWER(G.filename, G.filename);
+
+        if (G.pInfo->vollabel && len > 8 && G.filename[8] == '.') {
+            char *p = G.filename+8;
+            while (*p++)
+                p[-1] = *p;  /* disk label, and 8th char is dot:  remove dot */
+        }
+
+        if (!extra_len)         /* we're done here */
+            break;
+
+        /*
+         * We truncated the filename, so print what's left and then fall
+         * through to the SKIP routine.
+         */
+        Info(slide, 0x401, ((char *)slide, "[ %s ]\n", FnFilter1(G.filename)));
+        len = extra_len;
+        /*  FALL THROUGH...  */
+
+    /*
+     * Third case:  skip string, adjusting readbuf's internal variables
+     * as necessary (and possibly skipping to and reading a new block of
+     * data).
+     */
+
+    case SKIP:
+        /* cur_zipfile_bufstart already takes account of extra_bytes, so don't
+         * correct for it twice: */
+        ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes +
+               (G.inptr-G.inbuf) + len)
+        break;
+
+    /*
+     * Fourth case:  assume we're at the start of an "extra field"; malloc
+     * storage for it and read data into the allocated space.
+     */
+
+    case EXTRA_FIELD:
+        if (G.extra_field != (uch *)NULL)
+            free(G.extra_field);
+        if ((G.extra_field = (uch *)malloc(len)) == (uch *)NULL) {
+            Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraFieldTooLong),
+              len));
+            /* cur_zipfile_bufstart already takes account of extra_bytes,
+             * so don't correct for it twice: */
+            ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes +
+                   (G.inptr-G.inbuf) + len)
+        } else
+            if (readbuf(__G__  (char *)G.extra_field, len) == 0)
+                return PK_EOF;
+        break;
+
+#ifdef AMIGA
+    /*
+     * Fifth case, for the Amiga only:  take the comment that would ordinarily
+     * be skipped over, and turn it into a 79 character string that will be
+     * attached to the file as a "filenote" after it is extracted.
+     */
+
+    case FILENOTE:
+        if ((extra_len = readbuf(__G__ tmp_fnote, (unsigned)
+                                 MIN(len, 2 * AMIGA_FILENOTELEN - 1))) == 0)
+            return PK_EOF;
+        if ((len -= extra_len) > 0)     /* treat remainder as in case SKIP: */
+            ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes
+                   + (G.inptr - G.inbuf) + len)
+        /* convert multi-line text into single line with no ctl-chars: */
+        tmp_fnote[extra_len] = '\0';
+        while ((short int) --extra_len >= 0)
+            if ((unsigned) tmp_fnote[extra_len] < ' ')
+                if (tmp_fnote[extra_len+1] == ' ')     /* no excess */
+                    strcpy(tmp_fnote+extra_len, tmp_fnote+extra_len+1);
+                else
+                    tmp_fnote[extra_len] = ' ';
+        tmp_fnote[AMIGA_FILENOTELEN - 1] = '\0';
+        if (G.filenotes[G.filenote_slot])
+            free(G.filenotes[G.filenote_slot]);     /* should not happen */
+        G.filenotes[G.filenote_slot] = NULL;
+        if (tmp_fnote[0]) {
+            if (!(G.filenotes[G.filenote_slot] = malloc(strlen(tmp_fnote)+1)))
+                return PK_MEM;
+            strcpy(G.filenotes[G.filenote_slot], tmp_fnote);
+        }
+        break;
+#endif /* AMIGA */
+
+    } /* end switch (option) */
+
+    return error;
+
+} /* end function do_string() */
+
+
+
+
+
+/***********************/
+/* Function makeword() */
+/***********************/
+
+ush makeword(b)
+    ZCONST uch *b;
+{
+    /*
+     * Convert Intel style 'short' integer to non-Intel non-16-bit
+     * host format.  This routine also takes care of byte-ordering.
+     */
+    return (ush)((b[1] << 8) | b[0]);
+}
+
+
+
+
+
+/***********************/
+/* Function makelong() */
+/***********************/
+
+ulg makelong(sig)
+    ZCONST uch *sig;
+{
+    /*
+     * Convert intel style 'long' variable to non-Intel non-16-bit
+     * host format.  This routine also takes care of byte-ordering.
+     */
+    return (((ulg)sig[3]) << 24)
+        + (((ulg)sig[2]) << 16)
+        + (((ulg)sig[1]) << 8)
+        + ((ulg)sig[0]);
+}
+
+
+
+#if CRYPT
+
+#ifdef NEED_STR2ISO
+/**********************/
+/* Function str2iso() */
+/**********************/
+
+char *str2iso(dst, src)
+    char *dst;                          /* destination buffer */
+    register ZCONST char *src;          /* source string */
+{
+#ifdef INTERN_TO_ISO
+    INTERN_TO_ISO(src, dst);
+#else
+    register uch c;
+    register char *dstp = dst;
+
+    do {
+        c = (uch)foreign(*src++);
+        *dstp++ = (char)ASCII2ISO(c);
+    } while (c != '\0');
+#endif
+
+    return dst;
+}
+#endif /* NEED_STR2ISO */
+
+
+#ifdef NEED_STR2OEM
+/**********************/
+/* Function str2oem() */
+/**********************/
+
+char *str2oem(dst, src)
+    char *dst;                          /* destination buffer */
+    register ZCONST char *src;          /* source string */
+{
+#ifdef INTERN_TO_OEM
+    INTERN_TO_OEM(src, dst);
+#else
+    register uch c;
+    register char *dstp = dst;
+
+    do {
+        c = (uch)foreign(*src++);
+        *dstp++ = (char)ASCII2OEM(c);
+    } while (c != '\0');
+#endif
+
+    return dst;
+}
+#endif /* NEED_STR2OEM */
+
+#endif /* CRYPT */
+
+
+#ifdef ZMEM  /* memset/memcmp/memcpy for systems without either them or */
+             /* bzero/bcmp/bcopy */
+             /* (no known systems as of 960211) */
+
+/*********************/
+/* Function memset() */
+/*********************/
+
+zvoid *memset(buf, init, len)
+    register zvoid *buf;        /* buffer location */
+    register int init;          /* initializer character */
+    register unsigned int len;  /* length of the buffer */
+{
+    zvoid *start;
+
+    start = buf;
+    while (len--)
+        *((char *)buf++) = (char)init;
+    return start;
+}
+
+
+
+/*********************/
+/* Function memcmp() */
+/*********************/
+
+int memcmp(b1, b2, len)
+    register ZCONST zvoid *b1;
+    register ZCONST zvoid *b2;
+    register unsigned int len;
+{
+    register int c;
+
+    if (len > 0) do {
+        if ((c = (int)(*((ZCONST unsigned char *)b1)++) -
+                 (int)(*((ZCONST unsigned char *)b2)++)) != 0)
+           return c;
+    } while (--len > 0)
+    return 0;
+}
+
+
+
+/*********************/
+/* Function memcpy() */
+/*********************/
+
+zvoid *memcpy(dst, src, len)
+    register zvoid *dst;
+    register ZCONST zvoid *src;
+    register unsigned int len;
+{
+    zvoid *start;
+
+    start = dst;
+    while (len-- > 0)
+        *((char *)dst)++ = *((ZCONST char *)src)++;
+    return start;
+}
+
+#endif /* ZMEM */
+
+
+
+
+
+/************************/
+/* Function zstrnicmp() */
+/************************/
+
+int zstrnicmp(s1, s2, n)
+    register ZCONST char *s1, *s2;
+    register unsigned n;
+{
+    for (; n > 0;  --n, ++s1, ++s2) {
+
+        if (ToLower(*s1) != ToLower(*s2))
+            /* test includes early termination of one string */
+            return (ToLower(*s1) < ToLower(*s2))? -1 : 1;
+
+        if (*s1 == '\0')   /* both strings terminate early */
+            return 0;
+    }
+    return 0;
+}
+
+
+
+
+
+#ifdef REGULUS  /* returns the inode number on success(!)...argh argh argh */
+#  undef stat
+
+/********************/
+/* Function zstat() */
+/********************/
+
+int zstat(p, s)
+    char *p;
+    struct stat *s;
+{
+    return (stat(p,s) >= 0? 0 : (-1));
+}
+
+#endif /* REGULUS */
+
+
+
+
+
+#ifdef SMALL_MEM
+
+/*******************************/
+/*  Function fLoadFarString()  */   /* (and friends...) */
+/*******************************/
+
+char *fLoadFarString(__GPRO__ const char Far *sz)
+{
+    (void)zfstrcpy(G.rgchBigBuffer, sz);
+    return G.rgchBigBuffer;
+}
+
+char *fLoadFarStringSmall(__GPRO__ const char Far *sz)
+{
+    (void)zfstrcpy(G.rgchSmallBuffer, sz);
+    return G.rgchSmallBuffer;
+}
+
+char *fLoadFarStringSmall2(__GPRO__ const char Far *sz)
+{
+    (void)zfstrcpy(G.rgchSmallBuffer2, sz);
+    return G.rgchSmallBuffer2;
+}
+
+
+
+
+#if (!defined(_MSC_VER) || (_MSC_VER < 600))
+/*************************/
+/*  Function zfstrcpy()  */   /* portable clone of _fstrcpy() */
+/*************************/
+
+char Far * Far zfstrcpy(char Far *s1, const char Far *s2)
+{
+    char Far *p = s1;
+
+    while ((*s1++ = *s2++) != '\0');
+    return p;
+}
+#endif /* !_MSC_VER || (_MSC_VER < 600) */
+
+#endif /* SMALL_MEM */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/funzip.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,468 @@
+/* funzip.c -- put in the public domain by Mark Adler */
+
+#define VERSION "3.93 of 21 November 1998"
+
+
+/* You can do whatever you like with this source file, though I would
+   prefer that if you modify it and redistribute it that you include
+   comments to that effect with your name and the date.  Thank you.
+
+   History:
+   vers     date          who           what
+   ----   ---------  --------------  ------------------------------------
+   1.0    13 Aug 92  M. Adler        really simple unzip filter.
+   1.1    13 Aug 92  M. Adler        cleaned up somewhat, give help if
+                                     stdin not redirected, warn if more
+                                     zip file entries after the first.
+   1.2    15 Aug 92  M. Adler        added check of lengths for stored
+                                     entries, added more help.
+   1.3    16 Aug 92  M. Adler        removed redundant #define's, added
+                                     decryption.
+   1.4    27 Aug 92  G. Roelofs      added exit(0).
+   1.5     1 Sep 92  K. U. Rommel    changed read/write modes for OS/2.
+   1.6     6 Sep 92  G. Roelofs      modified to use dummy crypt.c and
+                                     crypt.h instead of -DCRYPT.
+   1.7    23 Sep 92  G. Roelofs      changed to use DOS_OS2; included
+                                     crypt.c under MS-DOS.
+   1.8     9 Oct 92  M. Adler        improved inflation error msgs.
+   1.9    17 Oct 92  G. Roelofs      changed ULONG/UWORD/byte to ulg/ush/uch;
+                                     renamed inflate_entry() to inflate();
+                                     adapted to use new, in-place zdecode.
+   2.0    22 Oct 92  M. Adler        allow filename argument, prompt for
+                                     passwords and don't echo, still allow
+                                     command-line password entry, but as an
+                                     option.
+   2.1    23 Oct 92  J-l. Gailly     fixed crypt/store bug,
+                     G. Roelofs      removed crypt.c under MS-DOS, fixed
+                                     decryption check to compare single byte.
+   2.2    28 Oct 92  G. Roelofs      removed declaration of key.
+   2.3    14 Dec 92  M. Adler        replaced fseek (fails on stdin for SCO
+                                     Unix V.3.2.4).  added quietflg for
+                                     inflate.c.
+   3.0    11 May 93  M. Adler        added gzip support
+   3.1     9 Jul 93  K. U. Rommel    fixed OS/2 pipe bug (PIPE_ERROR)
+   3.2     4 Sep 93  G. Roelofs      moved crc_32_tab[] to tables.h; used FOPx
+                                     from unzip.h; nuked OUTB macro and outbuf;
+                                     replaced flush(); inlined FlushOutput();
+                                     renamed decrypt to encrypted
+   3.3    29 Sep 93  G. Roelofs      replaced ReadByte() with NEXTBYTE macro;
+                                     revised (restored?) flush(); added FUNZIP
+   3.4    21 Oct 93  G. Roelofs      renamed quietflg to qflag; changed outcnt,
+                     H. Gessau       second updcrc() arg and flush() arg to ulg;
+                                     added inflate_free(); added "g =" to null
+                                     getc(in) to avoid compiler warnings
+   3.5    31 Oct 93  H. Gessau       changed DOS_OS2 to DOS_NT_OS2
+   3.6     6 Dec 93  H. Gessau       added "near" to mask_bits[]
+   3.7     9 Dec 93  G. Roelofs      added extent typecasts to fwrite() checks
+   3.8    28 Jan 94  GRR/JlG         initialized g variable in main() for gcc
+   3.81   22 Feb 94  M. Hanning-Lee  corrected usage message
+   3.82   27 Feb 94  G. Roelofs      added some typecasts to avoid warnings
+   3.83   22 Jul 94  G. Roelofs      changed fprintf to macro for DLLs
+    -      2 Aug 94  -               public release with UnZip 5.11
+    -     28 Aug 94  -               public release with UnZip 5.12
+   3.84    1 Oct 94  K. U. Rommel    changes for Metaware High C
+   3.85   29 Oct 94  G. Roelofs      changed fprintf macro to Info
+   3.86    7 May 95  K. Davis        RISCOS patches;
+                     P. Kienitz      Amiga patches
+   3.87   12 Aug 95  G. Roelofs      inflate_free(), DESTROYGLOBALS fixes
+   3.88    4 Sep 95  C. Spieler      reordered macro to work around MSC 5.1 bug
+   3.89   22 Nov 95  PK/CS           ifdef'd out updcrc() for ASM_CRC
+   3.9    17 Dec 95  G. Roelofs      modified for USE_ZLIB (new fillinbuf())
+    -     30 Apr 96  -               public release with UnZip 5.2
+   3.91   17 Aug 96  G. Roelofs      main() -> return int (Peter Seebach)
+   3.92   13 Apr 97  G. Roelofs      minor cosmetic fixes to messages
+    -     22 Apr 97  -               public release with UnZip 5.3
+    -     31 May 97  -               public release with UnZip 5.31
+   3.93   20 Sep 97  G. Roelofs      minor cosmetic fixes to messages
+    -      3 Nov 97  -               public release with UnZip 5.32
+    -     28 Nov 98  -               public release with UnZip 5.4
+ */
+
+
+/*
+
+   All funzip does is take a zipfile from stdin and decompress the
+   first entry to stdout.  The entry has to be either deflated or
+   stored.  If the entry is encrypted, then the decryption password
+   must be supplied on the command line as the first argument.
+
+   funzip needs to be linked with inflate.o and crypt.o compiled from
+   the unzip source.  If decryption is desired, the full version of
+   crypt.c (and crypt.h) from zcrypt21.zip or later must be used.
+
+ */
+
+#define FUNZIP
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#include "crypt.h"
+#include "ttyio.h"
+
+#ifdef EBCDIC
+#  undef EBCDIC                 /* don't need ebcdic[] */
+#endif
+#include "tables.h"             /* crc_32_tab[] */
+
+#ifndef USE_ZLIB  /* zlib's function is called inflate(), too */
+#  define UZinflate inflate
+#endif
+
+/* PKZIP header definitions */
+#define ZIPMAG 0x4b50           /* two-byte zip lead-in */
+#define LOCREM 0x0403           /* remaining two bytes in zip signature */
+#define LOCSIG 0x04034b50L      /* full signature */
+#define LOCFLG 4                /* offset of bit flag */
+#define  CRPFLG 1               /*  bit for encrypted entry */
+#define  EXTFLG 8               /*  bit for extended local header */
+#define LOCHOW 6                /* offset of compression method */
+#define LOCTIM 8                /* file mod time (for decryption) */
+#define LOCCRC 12               /* offset of crc */
+#define LOCSIZ 16               /* offset of compressed size */
+#define LOCLEN 20               /* offset of uncompressed length */
+#define LOCFIL 24               /* offset of file name field length */
+#define LOCEXT 26               /* offset of extra field length */
+#define LOCHDR 28               /* size of local header, including LOCREM */
+#define EXTHDR 16               /* size of extended local header, inc sig */
+
+/* GZIP header definitions */
+#define GZPMAG 0x8b1f           /* two-byte gzip lead-in */
+#define GZPHOW 0                /* offset of method number */
+#define GZPFLG 1                /* offset of gzip flags */
+#define  GZPMUL 2               /* bit for multiple-part gzip file */
+#define  GZPISX 4               /* bit for extra field present */
+#define  GZPISF 8               /* bit for filename present */
+#define  GZPISC 16              /* bit for comment present */
+#define  GZPISE 32              /* bit for encryption */
+#define GZPTIM 2                /* offset of Unix file modification time */
+#define GZPEXF 6                /* offset of extra flags */
+#define GZPCOS 7                /* offset of operating system compressed on */
+#define GZPHDR 8                /* length of minimal gzip header */
+
+/* Macros for getting two-byte and four-byte header values */
+#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))
+#define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16))
+
+/* Function prototypes */
+void err OF((int, char *));
+int main OF((int, char **));
+
+/* Globals */
+FILE *out;                      /* output file (*in moved to G struct) */
+ulg outsiz;                     /* total bytes written to out */
+int encrypted;                  /* flag to turn on decryption */
+
+/* Masks for inflate.c */
+ZCONST ush near mask_bits[] = {
+    0x0000,
+    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+
+#ifdef USE_ZLIB
+
+int fillinbuf(__G)
+__GDEF
+/* Fill input buffer for pull-model inflate() in zlib.  Return the number of
+ * bytes in inbuf. */
+{
+/*   GRR: check return value from fread(): same as read()?  check errno? */
+  if ((G.incnt = fread((char *)G.inbuf, 1, INBUFSIZ, G.in)) <= 0)
+    return 0;
+  G.inptr = G.inbuf;
+
+#if CRYPT
+  if (encrypted) {
+    uch *p;
+    int n;
+
+    for (n = G.incnt, p = G.inptr;  n--;  p++)
+      zdecode(*p);
+  }
+#endif /* CRYPT */
+
+  return G.incnt;
+
+}
+
+#endif /* USE_ZLIB */
+
+
+#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))
+#ifdef USE_ZLIB
+ZCONST uLongf *get_crc_table()
+{
+  return (ZCONST uLongf *)crc_32_tab;
+}
+#else /* !USE_ZLIB */
+ZCONST ulg near *get_crc_table()
+{
+  return crc_32_tab;
+}
+#endif /* ?USE_ZLIB */
+#endif /* !USE_ZLIB || USE_OWN_CRCTAB */
+
+
+void err(n, m)
+int n;
+char *m;
+/* Exit on error with a message and a code */
+{
+  Info(slide, 1, ((char *)slide, "funzip error: %s\n", m));
+  DESTROYGLOBALS()
+  EXIT(n);
+}
+
+
+int flush(w)    /* used by inflate.c (FLUSH macro) */
+ulg w;          /* number of bytes to flush */
+{
+  G.crc32val = crc32(G.crc32val, slide, (extent)w);
+  if (fwrite((char *)slide,1,(extent)w,out) != (extent)w && !PIPE_ERROR)
+    err(9, "out of space on stdout");
+  outsiz += w;
+  return 0;
+}
+
+
+int main(argc, argv)
+int argc;
+char **argv;
+/* Given a zipfile on stdin, decompress the first entry to stdout. */
+{
+  ush n;
+  uch h[LOCHDR];                /* first local header (GZPHDR < LOCHDR) */
+  int g = 0;                    /* true if gzip format */
+#if CRYPT
+  char *s = " [-password]";
+  char *p;                      /* password */
+#else /* !CRYPT */
+  char *s = "";
+#endif /* ?CRYPT */
+  CONSTRUCTGLOBALS();
+
+  /* skip executable name */
+  argc--;
+  argv++;
+
+#if CRYPT
+  /* get the command line password, if any */
+  p = (char *)NULL;
+  if (argc && **argv == '-')
+  {
+    argc--;
+    p = 1 + *argv++;
+  }
+#endif /* CRYPT */
+
+#ifdef MALLOC_WORK
+  G.area.Slide = (uch *)calloc(8193, sizeof(short)+sizeof(char)+sizeof(char));
+#endif
+
+  /* if no file argument and stdin not redirected, give the user help */
+  if (argc == 0 && isatty(0))
+  {
+    Info(slide, 1, ((char *)slide, "fUnZip (filter UnZip), version %s\n",
+      VERSION));
+    Info(slide, 1, ((char *)slide, "usage: ... | funzip%s | ...\n", s));
+    Info(slide, 1, ((char *)slide, "       ... | funzip%s > outfile\n", s));
+    Info(slide, 1, ((char *)slide, "       funzip%s infile.zip > outfile\n",s));
+    Info(slide, 1, ((char *)slide, "       funzip%s infile.gz > outfile\n", s));
+    Info(slide, 1, ((char *)slide, "Extracts to stdout the gzip file or first\
+ zip entry of stdin or the given file.\n"));
+    DESTROYGLOBALS()
+    EXIT(3);
+  }
+
+  /* prepare to be a binary filter */
+  if (argc)
+  {
+    if ((G.in = fopen(*argv, FOPR)) == (FILE *)NULL)
+      err(2, "cannot find input file");
+  }
+  else
+  {
+#ifdef DOS_FLX_H68_OS2_W32
+#if (defined(__HIGHC__) && !defined(FLEXOS))
+    setmode(stdin, _BINARY);
+#else
+    setmode(0, O_BINARY);  /* some buggy C libraries require BOTH setmode() */
+#endif                     /*  call AND the fdopen() in binary mode :-( */
+#endif /* DOS_FLX_H68_OS2_W32 */
+
+#ifdef RISCOS
+    G.in = stdin;
+#else
+    if ((G.in = fdopen(0, FOPR)) == (FILE *)NULL)
+      err(2, "cannot find stdin");
+#endif
+  }
+
+#ifdef DOS_FLX_H68_OS2_W32
+#if (defined(__HIGHC__) && !defined(FLEXOS))
+  setmode(stdout, _BINARY);
+#else
+  setmode(1, O_BINARY);
+#endif
+#endif /* DOS_FLX_H68_OS2_W32 */
+
+#ifdef RISCOS
+  out = stdout;
+#else
+  if ((out = fdopen(1, FOPW)) == (FILE *)NULL)
+    err(2, "cannot write to stdout");
+#endif
+
+  /* read local header, check validity, and skip name and extra fields */
+  n = getc(G.in);  n |= getc(G.in) << 8;
+  if (n == ZIPMAG)
+  {
+    if (fread((char *)h, 1, LOCHDR, G.in) != LOCHDR || SH(h) != LOCREM)
+      err(3, "invalid zipfile");
+    if (SH(h + LOCHOW) != STORED && SH(h + LOCHOW) != DEFLATED)
+      err(3, "first entry not deflated or stored--cannot unpack");
+    for (n = SH(h + LOCFIL); n--; ) g = getc(G.in);
+    for (n = SH(h + LOCEXT); n--; ) g = getc(G.in);
+    g = 0;
+    encrypted = h[LOCFLG] & CRPFLG;
+  }
+  else if (n == GZPMAG)
+  {
+    if (fread((char *)h, 1, GZPHDR, G.in) != GZPHDR)
+      err(3, "invalid gzip file");
+    if (h[GZPHOW] != DEFLATED)
+      err(3, "gzip file not deflated");
+    if (h[GZPFLG] & GZPMUL)
+      err(3, "cannot handle multi-part gzip files");
+    if (h[GZPFLG] & GZPISX)
+    {
+      n = getc(G.in);  n |= getc(G.in) << 8;
+      while (n--) g = getc(G.in);
+    }
+    if (h[GZPFLG] & GZPISF)
+      while ((g = getc(G.in)) != 0 && g != EOF) ;
+    if (h[GZPFLG] & GZPISC)
+      while ((g = getc(G.in)) != 0 && g != EOF) ;
+    g = 1;
+    encrypted = h[GZPFLG] & GZPISE;
+  }
+  else
+    err(3, "input not a zip or gzip file");
+
+  /* if entry encrypted, decrypt and validate encryption header */
+  if (encrypted)
+#if CRYPT
+    {
+      ush i, e;
+
+      if (p == (char *)NULL) {
+        if ((p = (char *)malloc(IZ_PWLEN+1)) == (char *)NULL)
+          err(1, "out of memory");
+        else if ((p = getp("Enter password: ", p, IZ_PWLEN+1)) == (char *)NULL)
+          err(1, "no tty to prompt for password");
+      }
+#if (defined(USE_ZLIB) && !defined(USE_OWN_CRCTAB))
+      /* initialize crc_32_tab pointer for decryption */
+      CRC_32_TAB = (ZCONST ulg Far *)get_crc_table();
+#endif
+      init_keys(p);
+      for (i = 0; i < RAND_HEAD_LEN; i++)
+        e = NEXTBYTE;
+      if (e != (ush)(h[LOCFLG] & EXTFLG ? h[LOCTIM + 1] : h[LOCCRC + 3]))
+        err(3, "incorrect password for first entry");
+    }
+#else /* !CRYPT */
+    err(3, "cannot decrypt entry (need to recompile with full crypt.c)");
+#endif /* ?CRYPT */
+
+  /* prepare output buffer and crc */
+  G.outptr = slide;
+  G.outcnt = 0L;
+  outsiz = 0L;
+  G.crc32val = CRCVAL_INITIAL;
+
+  /* decompress */
+  if (g || h[LOCHOW])
+  {                             /* deflated entry */
+    int r;
+
+#ifdef USE_ZLIB
+    /* need to allocate and prepare input buffer */
+    if ((G.inbuf = (uch *)malloc(INBUFSIZ)) == (uch *)NULL)
+       err(1, "out of memory");
+#endif /* USE_ZLIB */
+    if ((r = UZinflate(__G)) != 0) {
+      if (r == 3)
+        err(1, "out of memory");
+      else
+        err(4, "invalid compressed data--format violated");
+    }
+    inflate_free(__G);
+  }
+  else
+  {                             /* stored entry */
+    register ulg n;
+
+    n = LG(h + LOCLEN);
+#if CRYPT
+    if (n != LG(h + LOCSIZ) - (encrypted ? RAND_HEAD_LEN : 0)) {
+#else
+    if (n != LG(h + LOCSIZ)) {
+#endif
+      Info(slide, 1, ((char *)slide, "len %ld, siz %ld\n", n, LG(h + LOCSIZ)));
+      err(4, "invalid compressed data--length mismatch");
+    }
+    while (n--) {
+      ush c = getc(G.in);
+#if CRYPT
+      if (encrypted)
+        zdecode(c);
+#endif
+      *G.outptr++ = (uch)c;
+      if (++G.outcnt == WSIZE)    /* do FlushOutput() */
+      {
+        G.crc32val = crc32(G.crc32val, slide, (extent)G.outcnt);
+        if (fwrite((char *)slide, 1,(extent)G.outcnt,out) != (extent)G.outcnt
+            && !PIPE_ERROR)
+          err(9, "out of space on stdout");
+        outsiz += G.outcnt;
+        G.outptr = slide;
+        G.outcnt = 0L;
+      }
+    }
+  }
+  if (G.outcnt)   /* flush one last time; no need to reset G.outptr/outcnt */
+  {
+    G.crc32val = crc32(G.crc32val, slide, (extent)G.outcnt);
+    if (fwrite((char *)slide, 1,(extent)G.outcnt,out) != (extent)G.outcnt
+        && !PIPE_ERROR)
+      err(9, "out of space on stdout");
+    outsiz += G.outcnt;
+  }
+  fflush(out);
+
+  /* if extended header, get it */
+  if (g)
+  {
+    if (fread((char *)h + LOCCRC, 1, 8, G.in) != 8)
+      err(3, "gzip file ended prematurely");
+  }
+  else
+    if ((h[LOCFLG] & EXTFLG) &&
+        fread((char *)h + LOCCRC - 4, 1, EXTHDR, G.in) != EXTHDR)
+      err(3, "zipfile ended prematurely");
+
+  /* validate decompression */
+  if (LG(h + LOCCRC) != G.crc32val)
+    err(4, "invalid compressed data--crc error");
+  if (LG((g ? (h + LOCSIZ) : (h + LOCLEN))) != outsiz)
+    err(4, "invalid compressed data--length error");
+
+  /* check if there are more entries */
+  if (!g && fread((char *)h, 1, 4, G.in) == 4 && LG(h) == LOCSIG)
+    Info(slide, 1, ((char *)slide,
+      "funzip warning: zipfile has more than one entry--rest ignored\n"));
+
+  DESTROYGLOBALS()
+  RETURN (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/globals.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,204 @@
+/*---------------------------------------------------------------------------
+
+  globals.c
+
+  Routines to allocate and initialize globals, with or without threads.
+
+  Contents:  registerGlobalPointer()
+             deregisterGlobalPointer()
+             getGlobalPointer()
+             globalsCtor()
+
+  ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+
+#ifndef FUNZIP
+/* initialization of sigs is completed at runtime so unzip(sfx) executable
+ * won't look like a zipfile
+ */
+char central_hdr_sig[4] = {0, 0, 0x01, 0x02};
+char local_hdr_sig[4]   = {0, 0, 0x03, 0x04};
+char end_central_sig[4] = {0, 0, 0x05, 0x06};
+/* extern char extd_local_sig[4] = {0, 0, 0x07, 0x08};  NOT USED YET */
+
+ZCONST char *fnames[2] = {"*", NULL};   /* default filenames vector */
+#endif
+
+
+#ifndef REENTRANT
+   Uz_Globs G;
+#else /* REENTRANT */
+
+#  ifndef USETHREADID
+     Uz_Globs *GG;
+#  else /* USETHREADID */
+#    define THREADID_ENTRIES  0x40
+
+     int lastScan;
+     Uz_Globs  *threadPtrTable[THREADID_ENTRIES];
+     ulg        threadIdTable [THREADID_ENTRIES] = {
+         0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
+         0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,    /* Make sure there are */
+         0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,    /* THREADID_ENTRIES 0s */
+         0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
+     };
+
+     static ZCONST char Far TooManyThreads[] =
+       "error:  more than %d simultaneous threads.\n\
+        Some threads are probably not calling DESTROYTHREAD()\n";
+     static ZCONST char Far EntryNotFound[] =
+       "error:  couldn't find global pointer in table.\n\
+        Maybe somebody accidentally called DESTROYTHREAD() twice.\n";
+     static ZCONST char Far GlobalPointerMismatch[] =
+       "error:  global pointer in table does not match pointer passed as\
+ parameter\n";
+
+static void registerGlobalPointer OF((__GPRO));
+
+
+
+static void registerGlobalPointer(__G)
+    __GDEF
+{
+    int scan=0;
+    ulg tid = GetThreadId();
+
+    while (threadIdTable[scan] && scan < THREADID_ENTRIES)
+        scan++;
+
+    if (scan == THREADID_ENTRIES) {
+        ZCONST char *tooMany = LoadFarString(TooManyThreads);
+        Info(slide, 0x421, ((char *)slide, tooMany, THREADID_ENTRIES));
+        free(pG);
+        EXIT(PK_MEM);   /* essentially memory error before we've started */
+    }
+
+    threadIdTable [scan] = tid;
+    threadPtrTable[scan] = pG;
+    lastScan = scan;
+}
+
+
+
+void deregisterGlobalPointer(__G)
+    __GDEF
+{
+    int scan=0;
+    ulg tid = GetThreadId();
+
+
+    while (threadIdTable[scan] != tid && scan < THREADID_ENTRIES)
+        scan++;
+
+/*---------------------------------------------------------------------------
+    There are two things we can do if we can't find the entry:  ignore it or
+    scream.  The most likely reason for it not to be here is the user calling
+    this routine twice.  Since this could cause BIG problems if any globals
+    are accessed after the first call, we'd better scream.
+  ---------------------------------------------------------------------------*/
+
+    if (scan == THREADID_ENTRIES || threadPtrTable[scan] != pG) {
+        ZCONST char *noEntry;
+        if (scan == THREADID_ENTRIES)
+            noEntry = LoadFarString(EntryNotFound);
+        else
+            noEntry = LoadFarString(GlobalPointerMismatch);
+        Info(slide, 0x421, ((char *)slide, noEntry));
+        EXIT(PK_WARN);   /* programming error, but after we're all done */
+    }
+
+    threadIdTable [scan] = 0;
+    lastScan = scan;
+    free(threadPtrTable[scan]);
+}
+
+
+
+Uz_Globs *getGlobalPointer()
+{
+    int scan=0;
+    ulg tid = GetThreadId();
+
+    while (threadIdTable[scan] != tid && scan < THREADID_ENTRIES)
+        scan++;
+
+/*---------------------------------------------------------------------------
+    There are two things we can do if we can't find the entry:  ignore it or
+    scream.  The most likely reason for it not to be here is the user calling
+    this routine twice.  Since this could cause BIG problems if any globals
+    are accessed after the first call, we'd better scream.
+  ---------------------------------------------------------------------------*/
+
+    if (scan == THREADID_ENTRIES) {
+        ZCONST char *noEntry = LoadFarString(EntryNotFound);
+        fprintf(stderr, noEntry);  /* can't use Info w/o a global pointer */
+        EXIT(PK_ERR);   /* programming error while still working */
+    }
+
+    return threadPtrTable[scan];
+}
+
+#  endif /* ?USETHREADID */
+#endif /* ?REENTRANT */
+
+
+
+Uz_Globs *globalsCtor()
+{
+#ifdef REENTRANT
+    Uz_Globs *pG = (Uz_Globs *)malloc(sizeof(Uz_Globs));
+
+    if (!pG)
+        return (Uz_Globs *)NULL;
+#endif /* REENTRANT */
+
+    /* for REENTRANT version, G is defined as (*pG) */
+
+    memzero(&G, sizeof(Uz_Globs));
+
+#ifndef FUNZIP
+#ifdef CMS_MVS
+    uO.aflag=1;
+    uO.C_flag=1;
+#endif
+
+    uO.lflag=(-1);
+    G.wildzipfn = "";
+    G.pfnames = (char **)fnames;
+    G.pxnames = (char **)&fnames[1];
+    G.pInfo = G.info;
+    G.sol = TRUE;          /* at start of line */
+
+    G.message = UzpMessagePrnt;
+    G.input = UzpInput;           /* not used by anyone at the moment... */
+#if defined(WINDLL) || defined(MACOS)
+    G.mpause = NULL;              /* has scrollbars:  no need for pausing */
+#else
+    G.mpause = UzpMorePause;
+#endif
+    G.decr_passwd = UzpPassword;
+#endif /* !FUNZIP */
+
+#if (!defined(DOS_FLX_H68_OS2_W32) && !defined(AMIGA) && !defined(RISCOS))
+#if (!defined(MACOS) && !defined(ATARI) && !defined(VMS))
+    G.echofd = -1;
+#endif /* !(MACOS || ATARI || VMS) */
+#endif /* !(DOS_FLX_H68_OS2_W32 || AMIGA || RISCOS) */
+
+#ifdef SYSTEM_SPECIFIC_CTOR
+    SYSTEM_SPECIFIC_CTOR(__G);
+#endif
+
+#ifdef REENTRANT
+#ifdef USETHREADID
+    registerGlobalPointer(__G);
+#else
+    GG = &G;
+#endif /* ?USETHREADID */
+#endif /* REENTRANT */
+
+    return &G;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/inflate.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,1305 @@
+/* inflate.c -- put in the public domain by Mark Adler
+   version c16b, 29 March 1998 */
+
+
+/* You can do whatever you like with this source file, though I would
+   prefer that if you modify it and redistribute it that you include
+   comments to that effect with your name and the date.  Thank you.
+
+   History:
+   vers    date          who           what
+   ----  ---------  --------------  ------------------------------------
+    a    ~~ Feb 92  M. Adler        used full (large, one-step) lookup table
+    b1   21 Mar 92  M. Adler        first version with partial lookup tables
+    b2   21 Mar 92  M. Adler        fixed bug in fixed-code blocks
+    b3   22 Mar 92  M. Adler        sped up match copies, cleaned up some
+    b4   25 Mar 92  M. Adler        added prototypes; removed window[] (now
+                                    is the responsibility of unzip.h--also
+                                    changed name to slide[]), so needs diffs
+                                    for unzip.c and unzip.h (this allows
+                                    compiling in the small model on MSDOS);
+                                    fixed cast of q in huft_build();
+    b5   26 Mar 92  M. Adler        got rid of unintended macro recursion.
+    b6   27 Mar 92  M. Adler        got rid of nextbyte() routine.  fixed
+                                    bug in inflate_fixed().
+    c1   30 Mar 92  M. Adler        removed lbits, dbits environment variables.
+                                    changed BMAX to 16 for explode.  Removed
+                                    OUTB usage, and replaced it with flush()--
+                                    this was a 20% speed improvement!  Added
+                                    an explode.c (to replace unimplod.c) that
+                                    uses the huft routines here.  Removed
+                                    register union.
+    c2    4 Apr 92  M. Adler        fixed bug for file sizes a multiple of 32k.
+    c3   10 Apr 92  M. Adler        reduced memory of code tables made by
+                                    huft_build significantly (factor of two to
+                                    three).
+    c4   15 Apr 92  M. Adler        added NOMEMCPY do kill use of memcpy().
+                                    worked around a Turbo C optimization bug.
+    c5   21 Apr 92  M. Adler        added the WSIZE #define to allow reducing
+                                    the 32K window size for specialized
+                                    applications.
+    c6   31 May 92  M. Adler        added some typecasts to eliminate warnings
+    c7   27 Jun 92  G. Roelofs      added some more typecasts (444:  MSC bug).
+    c8    5 Oct 92  J-l. Gailly     added ifdef'd code to deal with PKZIP bug.
+    c9    9 Oct 92  M. Adler        removed a memory error message (~line 416).
+    c10  17 Oct 92  G. Roelofs      changed ULONG/UWORD/byte to ulg/ush/uch,
+                                    removed old inflate, renamed inflate_entry
+                                    to inflate, added Mark's fix to a comment.
+   c10.5 14 Dec 92  M. Adler        fix up error messages for incomplete trees.
+    c11   2 Jan 93  M. Adler        fixed bug in detection of incomplete
+                                    tables, and removed assumption that EOB is
+                                    the longest code (bad assumption).
+    c12   3 Jan 93  M. Adler        make tables for fixed blocks only once.
+    c13   5 Jan 93  M. Adler        allow all zero length codes (pkzip 2.04c
+                                    outputs one zero length code for an empty
+                                    distance tree).
+    c14  12 Mar 93  M. Adler        made inflate.c standalone with the
+                                    introduction of inflate.h.
+   c14b  16 Jul 93  G. Roelofs      added (unsigned) typecast to w at 470.
+   c14c  19 Jul 93  J. Bush         changed v[N_MAX], l[288], ll[28x+3x] arrays
+                                    to static for Amiga.
+   c14d  13 Aug 93  J-l. Gailly     de-complicatified Mark's c[*p++]++ thing.
+   c14e   8 Oct 93  G. Roelofs      changed memset() to memzero().
+   c14f  22 Oct 93  G. Roelofs      renamed quietflg to qflag; made Trace()
+                                    conditional; added inflate_free().
+   c14g  28 Oct 93  G. Roelofs      changed l/(lx+1) macro to pointer (Cray bug)
+   c14h   7 Dec 93  C. Ghisler      huft_build() optimizations.
+   c14i   9 Jan 94  A. Verheijen    set fixed_t{d,l} to NULL after freeing;
+                    G. Roelofs      check NEXTBYTE macro for EOF.
+   c14j  23 Jan 94  G. Roelofs      removed Ghisler "optimizations"; ifdef'd
+                                    EOF check.
+   c14k  27 Feb 94  G. Roelofs      added some typecasts to avoid warnings.
+   c14l   9 Apr 94  G. Roelofs      fixed split comments on preprocessor lines
+                                    to avoid bug in Encore compiler.
+   c14m   7 Jul 94  P. Kienitz      modified to allow assembler version of
+                                    inflate_codes() (define ASM_INFLATECODES)
+   c14n  22 Jul 94  G. Roelofs      changed fprintf to macro for DLL versions
+   c14o  23 Aug 94  C. Spieler      added a newline to a debug statement;
+                    G. Roelofs      added another typecast to avoid MSC warning
+   c14p   4 Oct 94  G. Roelofs      added (voidp *) cast to free() argument
+   c14q  30 Oct 94  G. Roelofs      changed fprintf macro to MESSAGE()
+   c14r   1 Nov 94  G. Roelofs      fixed possible redefinition of CHECK_EOF
+   c14s   7 May 95  S. Maxwell      OS/2 DLL globals stuff incorporated;
+                    P. Kienitz      "fixed" ASM_INFLATECODES macro/prototype
+   c14t  18 Aug 95  G. Roelofs      added UZinflate() to use zlib functions;
+                                    changed voidp to zvoid; moved huft_build()
+                                    and huft_free() to end of file
+   c14u   1 Oct 95  G. Roelofs      moved G into definition of MESSAGE macro
+   c14v   8 Nov 95  P. Kienitz      changed ASM_INFLATECODES to use a regular
+                                    call with __G__ instead of a macro
+    c15   3 Aug 96  M. Adler        fixed bomb-bug on random input data (Adobe)
+   c15b  24 Aug 96  M. Adler        more fixes for random input data
+   c15c  28 Mar 97  G. Roelofs      changed USE_ZLIB fatal exit code from
+                                    PK_MEM2 to PK_MEM3
+    c16  20 Apr 97  J. Altman       added memzero(v[]) in huft_build()
+   c16b  29 Mar 98  C. Spieler      modified DLL code for slide redirection
+ */
+
+
+/*
+   Inflate deflated (PKZIP's method 8 compressed) data.  The compression
+   method searches for as much of the current string of bytes (up to a
+   length of 258) in the previous 32K bytes.  If it doesn't find any
+   matches (of at least length 3), it codes the next byte.  Otherwise, it
+   codes the length of the matched string and its distance backwards from
+   the current position.  There is a single Huffman code that codes both
+   single bytes (called "literals") and match lengths.  A second Huffman
+   code codes the distance information, which follows a length code.  Each
+   length or distance code actually represents a base value and a number
+   of "extra" (sometimes zero) bits to get to add to the base value.  At
+   the end of each deflated block is a special end-of-block (EOB) literal/
+   length code.  The decoding process is basically: get a literal/length
+   code; if EOB then done; if a literal, emit the decoded byte; if a
+   length then get the distance and emit the referred-to bytes from the
+   sliding window of previously emitted data.
+
+   There are (currently) three kinds of inflate blocks: stored, fixed, and
+   dynamic.  The compressor outputs a chunk of data at a time and decides
+   which method to use on a chunk-by-chunk basis.  A chunk might typically
+   be 32K to 64K, uncompressed.  If the chunk is uncompressible, then the
+   "stored" method is used.  In this case, the bytes are simply stored as
+   is, eight bits per byte, with none of the above coding.  The bytes are
+   preceded by a count, since there is no longer an EOB code.
+
+   If the data are compressible, then either the fixed or dynamic methods
+   are used.  In the dynamic method, the compressed data are preceded by
+   an encoding of the literal/length and distance Huffman codes that are
+   to be used to decode this block.  The representation is itself Huffman
+   coded, and so is preceded by a description of that code.  These code
+   descriptions take up a little space, and so for small blocks, there is
+   a predefined set of codes, called the fixed codes.  The fixed method is
+   used if the block ends up smaller that way (usually for quite small
+   chunks); otherwise the dynamic method is used.  In the latter case, the
+   codes are customized to the probabilities in the current block and so
+   can code it much better than the pre-determined fixed codes can.
+
+   The Huffman codes themselves are decoded using a multi-level table
+   lookup, in order to maximize the speed of decoding plus the speed of
+   building the decoding tables.  See the comments below that precede the
+   lbits and dbits tuning parameters.
+
+   GRR:  return values(?)
+           0  OK
+           1  incomplete table
+           2  bad input
+           3  not enough memory
+ */
+
+
+/*
+   Notes beyond the 1.93a appnote.txt:
+
+   1. Distance pointers never point before the beginning of the output
+      stream.
+   2. Distance pointers can point back across blocks, up to 32k away.
+   3. There is an implied maximum of 7 bits for the bit length table and
+      15 bits for the actual data.
+   4. If only one code exists, then it is encoded using one bit.  (Zero
+      would be more efficient, but perhaps a little confusing.)  If two
+      codes exist, they are coded using one bit each (0 and 1).
+   5. There is no way of sending zero distance codes--a dummy must be
+      sent if there are none.  (History: a pre 2.0 version of PKZIP would
+      store blocks with no distance codes, but this was discovered to be
+      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
+      zero distance codes, which is sent as one code of zero bits in
+      length.
+   6. There are up to 286 literal/length codes.  Code 256 represents the
+      end-of-block.  Note however that the static length tree defines
+      288 codes just to fill out the Huffman codes.  Codes 286 and 287
+      cannot be used though, since there is no length base or extra bits
+      defined for them.  Similarily, there are up to 30 distance codes.
+      However, static trees define 32 codes (all 5 bits) to fill out the
+      Huffman codes, but the last two had better not show up in the data.
+   7. Unzip can check dynamic Huffman blocks for complete code sets.
+      The exception is that a single code would not be complete (see #4).
+   8. The five bits following the block type is really the number of
+      literal codes sent minus 257.
+   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+      (1+6+6).  Therefore, to output three times the length, you output
+      three codes (1+1+1), whereas to output four times the same length,
+      you only need two codes (1+3).  Hmm.
+  10. In the tree reconstruction algorithm, Code = Code + Increment
+      only if BitLength(i) is not zero.  (Pretty obvious.)
+  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
+  12. Note: length code 284 can represent 227-258, but length code 285
+      really is 258.  The last length deserves its own, short code
+      since it gets used a lot in very redundant files.  The length
+      258 is special since 258 - 3 (the min match length) is 255.
+  13. The literal/length and distance code bit lengths are read as a
+      single stream of lengths.  It is possible (and advantageous) for
+      a repeat code (16, 17, or 18) to go across the boundary between
+      the two sets of lengths.
+ */
+
+
+#define PKZIP_BUG_WORKAROUND    /* PKZIP 1.93a problem--live with it */
+
+/*
+    inflate.h must supply the uch slide[WSIZE] array, the zvoid typedef
+    (void if (void *) is accepted, else char) and the NEXTBYTE,
+    FLUSH() and memzero macros.  If the window size is not 32K, it
+    should also define WSIZE.  If INFMOD is defined, it can include
+    compiled functions to support the NEXTBYTE and/or FLUSH() macros.
+    There are defaults for NEXTBYTE and FLUSH() below for use as
+    examples of what those functions need to do.  Normally, you would
+    also want FLUSH() to compute a crc on the data.  inflate.h also
+    needs to provide these typedefs:
+
+        typedef unsigned char uch;
+        typedef unsigned short ush;
+        typedef unsigned long ulg;
+
+    This module uses the external functions malloc() and free() (and
+    probably memset() or bzero() in the memzero() macro).  Their
+    prototypes are normally found in <string.h> and <stdlib.h>.
+ */
+
+/* #define DEBUG */
+#define INFMOD          /* tell inflate.h to include code to be compiled */
+#include "inflate.h"
+
+
+#ifndef WSIZE           /* default is 32K */
+#  define WSIZE 0x8000  /* window size--must be a power of two, and at least */
+#endif                  /* 32K for zip's deflate method */
+
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+#  define wsize G._wsize    /* wsize is a variable */
+#else
+#  define wsize WSIZE       /* wsize is a constant */
+#endif
+
+
+#ifndef NEXTBYTE        /* default is to simply get a byte from stdin */
+#  define NEXTBYTE getchar()
+#endif
+
+#ifndef MESSAGE   /* only used twice, for fixed strings--NOT general-purpose */
+#  define MESSAGE(str,len,flag)  pipeit((char *)(str))
+#endif
+
+#ifndef FLUSH           /* default is to simply write the buffer to stdout */
+#  define FLUSH(n) fwrite(redirSlide, 1, n, stdout)  /* return value not used */
+#endif
+/* Warning: the fwrite above might not work on 16-bit compilers, since
+   0x8000 might be interpreted as -32,768 by the library function. */
+
+#ifndef Trace
+#  ifdef DEBUG
+#    define Trace(x) fprintf x
+#  else
+#    define Trace(x)
+#  endif
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+#ifdef USE_ZLIB
+
+
+/*
+   GRR:  return values for both original inflate() and UZinflate()
+           0  OK
+           1  incomplete table(?)
+           2  bad input
+           3  not enough memory
+ */
+
+/**************************/
+/*  Function UZinflate()  */
+/**************************/
+
+int UZinflate(__G)   /* decompress an inflated entry using the zlib routines */
+    __GDEF
+{
+    int err=Z_OK;
+
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+    if (G.redirect_slide)
+        wsize = G.redirect_size, redirSlide = G.redirect_buffer;
+    else
+        wsize = WSIZE, redirSlide = slide;
+#endif
+
+    G.dstrm.next_out = redirSlide;
+    G.dstrm.avail_out = wsize;
+
+    G.dstrm.next_in = G.inptr;
+    G.dstrm.avail_in = G.incnt;
+
+    if (!G.inflInit) {
+        unsigned i;
+        int windowBits;
+
+        /* only need to test this stuff once */
+        if (zlib_version[0] != ZLIB_VERSION[0]) {
+            Info(slide, 0x21, ((char *)slide,
+              "error:  incompatible zlib version (expected %s, found %s)\n",
+              ZLIB_VERSION, zlib_version));
+            return 3;
+        } else if (strcmp(zlib_version, ZLIB_VERSION) != 0)
+            Info(slide, 0x21, ((char *)slide,
+              "warning:  different zlib version (expected %s, using %s)\n",
+              ZLIB_VERSION, zlib_version));
+
+        /* windowBits = log2(wsize) */
+        for (i = ((unsigned)wsize * 2 - 1), windowBits = 0;
+             !(i & 1);  i >>= 1, ++windowBits);
+        if ((unsigned)windowBits > (unsigned)15)
+            windowBits = 15;
+        else if (windowBits < 8)
+            windowBits = 8;
+
+        G.dstrm.zalloc = (alloc_func)Z_NULL;
+        G.dstrm.zfree = (free_func)Z_NULL;
+
+        Trace((stderr, "initializing inflate()\n"));
+        err = inflateInit2(&G.dstrm, -windowBits);
+
+        if (err == Z_MEM_ERROR)
+            return 3;
+        else if (err != Z_OK)
+            Trace((stderr, "oops!  (inflateInit2() err = %d)\n", err));
+        G.inflInit = 1;
+    }
+
+#ifdef FUNZIP
+    while (err != Z_STREAM_END) {
+#else /* !FUNZIP */
+    while (G.csize > 0) {
+        Trace((stderr, "first loop:  G.csize = %ld\n", G.csize));
+#endif /* ?FUNZIP */
+        while (G.dstrm.avail_out > 0) {
+            err = inflate(&G.dstrm, Z_PARTIAL_FLUSH);
+
+            if (err == Z_DATA_ERROR)
+                return 2;
+            else if (err == Z_MEM_ERROR)
+                return 3;
+            else if (err != Z_OK && err != Z_STREAM_END)
+                Trace((stderr, "oops!  (inflate(first loop) err = %d)\n", err));
+
+#ifdef FUNZIP
+            if (err == Z_STREAM_END)    /* "END-of-entry-condition" ? */
+#else /* !FUNZIP */
+            if (G.csize <= 0L)          /* "END-of-entry-condition" ? */
+#endif /* ?FUNZIP */
+                break;
+
+            if (G.dstrm.avail_in <= 0) {
+                if (fillinbuf(__G) == 0)
+                    return 2;  /* no "END-condition" yet, but no more data */
+
+                G.dstrm.next_in = G.inptr;
+                G.dstrm.avail_in = G.incnt;
+            }
+            Trace((stderr, "     avail_in = %d\n", G.dstrm.avail_in));
+        }
+        FLUSH(wsize - G.dstrm.avail_out);   /* flush slide[] */
+        Trace((stderr, "inside loop:  flushing %ld bytes (ptr diff = %ld)\n",
+          (long)(wsize - G.dstrm.avail_out),
+          (long)(G.dstrm.next_out-(Bytef *)redirSlide)));
+        G.dstrm.next_out = redirSlide;
+        G.dstrm.avail_out = wsize;
+    }
+
+    /* no more input, so loop until we have all output */
+    Trace((stderr, "beginning final loop:  err = %d\n", err));
+    while (err != Z_STREAM_END) {
+        err = inflate(&G.dstrm, Z_PARTIAL_FLUSH);
+        if (err == Z_DATA_ERROR)
+            return 2;
+        else if (err == Z_MEM_ERROR)
+            return 3;
+        else if (err == Z_BUF_ERROR) {              /* DEBUG */
+            Trace((stderr, "zlib inflate() did not detect stream end (%s, %s)\n"
+              , G.zipfn, G.filename));
+            break;
+        } else if (err != Z_OK && err != Z_STREAM_END) {
+            Trace((stderr, "oops!  (inflate(final loop) err = %d)\n", err));
+            DESTROYGLOBALS()
+            EXIT(PK_MEM3);
+        }
+        FLUSH(wsize - G.dstrm.avail_out);   /* final flush of slide[] */
+        Trace((stderr, "final loop:  flushing %ld bytes (ptr diff = %ld)\n",
+          (long)(wsize - G.dstrm.avail_out),
+          (long)(G.dstrm.next_out-(Bytef *)redirSlide)));
+        G.dstrm.next_out = redirSlide;
+        G.dstrm.avail_out = wsize;
+    }
+    Trace((stderr, "total in = %ld, total out = %ld\n", G.dstrm.total_in,
+      G.dstrm.total_out));
+
+    G.inptr = (uch *)G.dstrm.next_in;
+    G.incnt = (G.inbuf + INBUFSIZ) - G.inptr;  /* reset for other routines */
+
+    err = inflateReset(&G.dstrm);
+    if (err != Z_OK)
+        Trace((stderr, "oops!  (inflateReset() err = %d)\n", err));
+
+    return 0;
+}
+
+
+/*---------------------------------------------------------------------------*/
+#else /* !USE_ZLIB */
+
+
+/* Function prototypes */
+#ifndef OF
+#  ifdef __STDC__
+#    define OF(a) a
+#  else
+#    define OF(a) ()
+#  endif
+#endif /* !OF */
+int inflate_codes OF((__GPRO__ struct huft *tl, struct huft *td,
+                      int bl, int bd));
+static int inflate_stored OF((__GPRO));
+static int inflate_fixed OF((__GPRO));
+static int inflate_dynamic OF((__GPRO));
+static int inflate_block OF((__GPRO__ int *e));
+
+
+/* The inflate algorithm uses a sliding 32K byte window on the uncompressed
+   stream to find repeated byte strings.  This is implemented here as a
+   circular buffer.  The index is updated simply by incrementing and then
+   and'ing with 0x7fff (32K-1). */
+/* It is left to other modules to supply the 32K area.  It is assumed
+   to be usable as if it were declared "uch slide[32768];" or as just
+   "uch *slide;" and then malloc'ed in the latter case.  The definition
+   must be in unzip.h, included above. */
+
+
+/* unsigned wp;  moved to globals.h */     /* current position in slide */
+
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+static ZCONST unsigned border[] = { /* Order of the bit length code lengths */
+        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+static ZCONST ush cplens[] = {  /* Copy lengths for literal codes 257..285 */
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+        /* note: see note #13 above about the 258 in this list. */
+static ZCONST ush cplext[] = {  /* Extra bits for literal codes 257..285 */
+        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, 99, 99}; /* 99==invalid */
+static ZCONST ush cpdist[] = {  /* Copy offsets for distance codes 0..29 */
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+        8193, 12289, 16385, 24577};
+static ZCONST ush cpdext[] = {  /* Extra bits for distance codes */
+        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};
+
+
+/* moved to consts.h (included in unzip.c), resp. funzip.c */
+#if 0
+/* And'ing with mask_bits[n] masks the lower n bits */
+ZCONST ush near mask_bits[] = {
+    0x0000,
+    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+#endif /* 0 */
+
+
+/* Macros for inflate() bit peeking and grabbing.
+   The usage is:
+
+        NEEDBITS(j)
+        x = b & mask_bits[j];
+        DUMPBITS(j)
+
+   where NEEDBITS makes sure that b has at least j bits in it, and
+   DUMPBITS removes the bits from b.  The macros use the variable k
+   for the number of bits in b.  Normally, b and k are register
+   variables for speed and are initialized at the begining of a
+   routine that uses these macros from a global bit buffer and count.
+
+   In order to not ask for more bits than there are in the compressed
+   stream, the Huffman tables are constructed to only ask for just
+   enough bits to make up the end-of-block code (value 256).  Then no
+   bytes need to be "returned" to the buffer at the end of the last
+   block.  See the huft_build() routine.
+ */
+
+/* These have been moved to globals.h */
+#if 0
+ulg bb;                         /* bit buffer */
+unsigned bk;                    /* bits in bit buffer */
+#endif
+
+#ifndef CHECK_EOF
+#  define CHECK_EOF   /* default as of 5.13/5.2 */
+#endif
+
+#ifndef CHECK_EOF
+#  define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<<k;k+=8;}}
+#else
+#  define NEEDBITS(n) {while(k<(n)){int c=NEXTBYTE;if(c==EOF)return 1;\
+    b|=((ulg)c)<<k;k+=8;}}
+#endif                      /* Piet Plomp:  change "return 1" to "break" */
+
+#define DUMPBITS(n) {b>>=(n);k-=(n);}
+
+
+/*
+   Huffman code decoding is performed using a multi-level table lookup.
+   The fastest way to decode is to simply build a lookup table whose
+   size is determined by the longest code.  However, the time it takes
+   to build this table can also be a factor if the data being decoded
+   are not very long.  The most common codes are necessarily the
+   shortest codes, so those codes dominate the decoding time, and hence
+   the speed.  The idea is you can have a shorter table that decodes the
+   shorter, more probable codes, and then point to subsidiary tables for
+   the longer codes.  The time it costs to decode the longer codes is
+   then traded against the time it takes to make longer tables.
+
+   This results of this trade are in the variables lbits and dbits
+   below.  lbits is the number of bits the first level table for literal/
+   length codes can decode in one step, and dbits is the same thing for
+   the distance codes.  Subsequent tables are also less than or equal to
+   those sizes.  These values may be adjusted either when all of the
+   codes are shorter than that, in which case the longest code length in
+   bits is used, or when the shortest code is *longer* than the requested
+   table size, in which case the length of the shortest code in bits is
+   used.
+
+   There are two different values for the two tables, since they code a
+   different number of possibilities each.  The literal/length table
+   codes 286 possible values, or in a flat code, a little over eight
+   bits.  The distance table codes 30 possible values, or a little less
+   than five bits, flat.  The optimum values for speed end up being
+   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+   The optimum values may differ though from machine to machine, and
+   possibly even between compilers.  Your mileage may vary.
+ */
+
+
+static ZCONST int lbits = 9;    /* bits in base literal/length lookup table */
+static ZCONST int dbits = 6;    /* bits in base distance lookup table */
+
+
+#ifndef ASM_INFLATECODES
+
+int inflate_codes(__G__ tl, td, bl, bd)
+     __GDEF
+struct huft *tl, *td;   /* literal/length and distance decoder tables */
+int bl, bd;             /* number of bits decoded by tl[] and td[] */
+/* inflate (decompress) the codes in a deflated (compressed) block.
+   Return an error code or zero if it all goes ok. */
+{
+  register unsigned e;  /* table entry flag/number of extra bits */
+  unsigned n, d;        /* length and index for copy */
+  unsigned w;           /* current window position */
+  struct huft *t;       /* pointer to table entry */
+  unsigned ml, md;      /* masks for bl and bd bits */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+
+
+  /* make local copies of globals */
+  b = G.bb;                       /* initialize bit buffer */
+  k = G.bk;
+  w = G.wp;                       /* initialize window position */
+
+
+  /* inflate the coded data */
+  ml = mask_bits[bl];           /* precompute masks for speed */
+  md = mask_bits[bd];
+  while (1)                     /* do until end of block */
+  {
+    NEEDBITS((unsigned)bl)
+    if ((e = (t = tl + ((unsigned)b & ml))->e) > 16)
+      do {
+        if (e == 99)
+          return 1;
+        DUMPBITS(t->b)
+        e -= 16;
+        NEEDBITS(e)
+      } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
+    DUMPBITS(t->b)
+    if (e == 16)                /* then it's a literal */
+    {
+      redirSlide[w++] = (uch)t->v.n;
+      if (w == wsize)
+      {
+        FLUSH(w);
+        w = 0;
+      }
+    }
+    else                        /* it's an EOB or a length */
+    {
+      /* exit if end of block */
+      if (e == 15)
+        break;
+
+      /* get length of block to copy */
+      NEEDBITS(e)
+      n = t->v.n + ((unsigned)b & mask_bits[e]);
+      DUMPBITS(e);
+
+      /* decode distance of block to copy */
+      NEEDBITS((unsigned)bd)
+      if ((e = (t = td + ((unsigned)b & md))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      NEEDBITS(e)
+      d = w - t->v.n - ((unsigned)b & mask_bits[e]);
+      DUMPBITS(e)
+
+      /* do the copy */
+      do {
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+        if (G.redirect_slide) {/* &= w/ wsize unnecessary & wrong if redirect */
+          if (d >= wsize)
+            return 1;           /* invalid compressed data */
+          n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e);
+        }
+        else
+#endif
+          n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e);
+#ifndef NOMEMCPY
+        if (w - d >= e)         /* (this test assumes unsigned comparison) */
+        {
+          memcpy(redirSlide + w, redirSlide + d, e);
+          w += e;
+          d += e;
+        }
+        else                    /* do it slowly to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+          do {
+            redirSlide[w++] = redirSlide[d++];
+          } while (--e);
+        if (w == wsize)
+        {
+          FLUSH(w);
+          w = 0;
+        }
+      } while (n);
+    }
+  }
+
+
+  /* restore the globals from the locals */
+  G.wp = w;                       /* restore global window pointer */
+  G.bb = b;                       /* restore global bit buffer */
+  G.bk = k;
+
+
+  /* done */
+  return 0;
+}
+
+#endif /* ASM_INFLATECODES */
+
+
+
+static int inflate_stored(__G)
+     __GDEF
+/* "decompress" an inflated type 0 (stored) block. */
+{
+  unsigned n;           /* number of bytes in block */
+  unsigned w;           /* current window position */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+
+
+  /* make local copies of globals */
+  Trace((stderr, "\nstored block"));
+  b = G.bb;                       /* initialize bit buffer */
+  k = G.bk;
+  w = G.wp;                       /* initialize window position */
+
+
+  /* go to byte boundary */
+  n = k & 7;
+  DUMPBITS(n);
+
+
+  /* get the length and its complement */
+  NEEDBITS(16)
+  n = ((unsigned)b & 0xffff);
+  DUMPBITS(16)
+  NEEDBITS(16)
+  if (n != (unsigned)((~b) & 0xffff))
+    return 1;                   /* error in compressed data */
+  DUMPBITS(16)
+
+
+  /* read and output the compressed data */
+  while (n--)
+  {
+    NEEDBITS(8)
+    redirSlide[w++] = (uch)b;
+    if (w == wsize)
+    {
+      FLUSH(w);
+      w = 0;
+    }
+    DUMPBITS(8)
+  }
+
+
+  /* restore the globals from the locals */
+  G.wp = w;                       /* restore global window pointer */
+  G.bb = b;                       /* restore global bit buffer */
+  G.bk = k;
+  return 0;
+}
+
+
+/* Globals for literal tables (built once) */
+/* Moved to globals.h                      */
+#if 0
+struct huft *fixed_tl = (struct huft *)NULL;
+struct huft *fixed_td;
+int fixed_bl, fixed_bd;
+#endif
+
+static int inflate_fixed(__G)
+     __GDEF
+/* decompress an inflated type 1 (fixed Huffman codes) block.  We should
+   either replace this with a custom decoder, or at least precompute the
+   Huffman tables. */
+{
+  /* if first time, set up tables for fixed blocks */
+  Trace((stderr, "\nliteral block"));
+  if (G.fixed_tl == (struct huft *)NULL)
+  {
+    int i;                /* temporary variable */
+    unsigned l[288];      /* length list for huft_build */
+
+    /* literal table */
+    for (i = 0; i < 144; i++)
+      l[i] = 8;
+    for (; i < 256; i++)
+      l[i] = 9;
+    for (; i < 280; i++)
+      l[i] = 7;
+    for (; i < 288; i++)          /* make a complete, but wrong code set */
+      l[i] = 8;
+    G.fixed_bl = 7;
+    if ((i = huft_build(__G__ l, 288, 257, cplens, cplext,
+                        &G.fixed_tl, &G.fixed_bl)) != 0)
+    {
+      G.fixed_tl = (struct huft *)NULL;
+      return i;
+    }
+
+    /* distance table */
+    for (i = 0; i < 30; i++)      /* make an incomplete code set */
+      l[i] = 5;
+    G.fixed_bd = 5;
+    if ((i = huft_build(__G__ l, 30, 0, cpdist, cpdext,
+                        &G.fixed_td, &G.fixed_bd)) > 1)
+    {
+      huft_free(G.fixed_tl);
+      G.fixed_tl = (struct huft *)NULL;
+      return i;
+    }
+  }
+
+  /* decompress until an end-of-block code */
+  return inflate_codes(__G__ G.fixed_tl, G.fixed_td,
+                             G.fixed_bl, G.fixed_bd) != 0;
+}
+
+
+
+static int inflate_dynamic(__G)
+  __GDEF
+/* decompress an inflated type 2 (dynamic Huffman codes) block. */
+{
+  int i;                /* temporary variables */
+  unsigned j;
+  unsigned l;           /* last length */
+  unsigned m;           /* mask for bit lengths table */
+  unsigned n;           /* number of lengths to get */
+  struct huft *tl;      /* literal/length code table */
+  struct huft *td;      /* distance code table */
+  int bl;               /* lookup bits for tl */
+  int bd;               /* lookup bits for td */
+  unsigned nb;          /* number of bit length codes */
+  unsigned nl;          /* number of literal/length codes */
+  unsigned nd;          /* number of distance codes */
+#ifdef PKZIP_BUG_WORKAROUND
+  unsigned ll[288+32]; /* literal/length and distance code lengths */
+#else
+  unsigned ll[286+30]; /* literal/length and distance code lengths */
+#endif
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+
+
+  /* make local bit buffer */
+  Trace((stderr, "\ndynamic block"));
+  b = G.bb;
+  k = G.bk;
+
+
+  /* read in table lengths */
+  NEEDBITS(5)
+  nl = 257 + ((unsigned)b & 0x1f);      /* number of literal/length codes */
+  DUMPBITS(5)
+  NEEDBITS(5)
+  nd = 1 + ((unsigned)b & 0x1f);        /* number of distance codes */
+  DUMPBITS(5)
+  NEEDBITS(4)
+  nb = 4 + ((unsigned)b & 0xf);         /* number of bit length codes */
+  DUMPBITS(4)
+#ifdef PKZIP_BUG_WORKAROUND
+  if (nl > 288 || nd > 32)
+#else
+  if (nl > 286 || nd > 30)
+#endif
+    return 1;                   /* bad lengths */
+
+
+  /* read in bit-length-code lengths */
+  for (j = 0; j < nb; j++)
+  {
+    NEEDBITS(3)
+    ll[border[j]] = (unsigned)b & 7;
+    DUMPBITS(3)
+  }
+  for (; j < 19; j++)
+    ll[border[j]] = 0;
+
+
+  /* build decoding table for trees--single level, 7 bit lookup */
+  bl = 7;
+  i = huft_build(__G__ ll, 19, 19, NULL, NULL, &tl, &bl);
+  if (bl == 0)                        /* no bit lengths */
+    i = 1;
+  if (i)
+  {
+    if (i == 1)
+      huft_free(tl);
+    return i;                   /* incomplete code set */
+  }
+
+
+  /* read in literal and distance code lengths */
+  n = nl + nd;
+  m = mask_bits[bl];
+  i = l = 0;
+  while ((unsigned)i < n)
+  {
+    NEEDBITS((unsigned)bl)
+    j = (td = tl + ((unsigned)b & m))->b;
+    DUMPBITS(j)
+    j = td->v.n;
+    if (j < 16)                 /* length of code in bits (0..15) */
+      ll[i++] = l = j;          /* save last length in l */
+    else if (j == 16)           /* repeat last length 3 to 6 times */
+    {
+      NEEDBITS(2)
+      j = 3 + ((unsigned)b & 3);
+      DUMPBITS(2)
+      if ((unsigned)i + j > n)
+        return 1;
+      while (j--)
+        ll[i++] = l;
+    }
+    else if (j == 17)           /* 3 to 10 zero length codes */
+    {
+      NEEDBITS(3)
+      j = 3 + ((unsigned)b & 7);
+      DUMPBITS(3)
+      if ((unsigned)i + j > n)
+        return 1;
+      while (j--)
+        ll[i++] = 0;
+      l = 0;
+    }
+    else                        /* j == 18: 11 to 138 zero length codes */
+    {
+      NEEDBITS(7)
+      j = 11 + ((unsigned)b & 0x7f);
+      DUMPBITS(7)
+      if ((unsigned)i + j > n)
+        return 1;
+      while (j--)
+        ll[i++] = 0;
+      l = 0;
+    }
+  }
+
+
+  /* free decoding table for trees */
+  huft_free(tl);
+
+
+  /* restore the global bit buffer */
+  G.bb = b;
+  G.bk = k;
+
+
+  /* build the decoding tables for literal/length and distance codes */
+  bl = lbits;
+  i = huft_build(__G__ ll, nl, 257, cplens, cplext, &tl, &bl);
+  if (bl == 0)                        /* no literals or lengths */
+    i = 1;
+  if (i)
+  {
+    if (i == 1) {
+      if (!uO.qflag)
+        MESSAGE((uch *)"(incomplete l-tree)  ", 21L, 1);
+      huft_free(tl);
+    }
+    return i;                   /* incomplete code set */
+  }
+  bd = dbits;
+  i = huft_build(__G__ ll + nl, nd, 0, cpdist, cpdext, &td, &bd);
+  if (bd == 0 && nl > 257)    /* lengths but no distances */
+  {
+    if (!uO.qflag)
+      MESSAGE((uch *)"(incomplete d-tree)  ", 21L, 1);
+    huft_free(tl);
+    return 1;
+  }
+  if (i == 1) {
+#ifdef PKZIP_BUG_WORKAROUND
+    i = 0;
+#else
+    if (!uO.qflag)
+      MESSAGE((uch *)"(incomplete d-tree)  ", 21L, 1);
+    huft_free(td);
+#endif
+  }
+  if (i)
+  {
+    huft_free(tl);
+    return i;
+  }
+
+
+  /* decompress until an end-of-block code */
+  if (inflate_codes(__G__ tl, td, bl, bd))
+    return 1;
+
+
+  /* free the decoding tables, return */
+  huft_free(tl);
+  huft_free(td);
+  return 0;
+}
+
+
+
+static int inflate_block(__G__ e)
+  __GDEF
+  int *e;               /* last block flag */
+/* decompress an inflated block */
+{
+  unsigned t;           /* block type */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+
+
+  /* make local bit buffer */
+  b = G.bb;
+  k = G.bk;
+
+
+  /* read in last block bit */
+  NEEDBITS(1)
+  *e = (int)b & 1;
+  DUMPBITS(1)
+
+
+  /* read in block type */
+  NEEDBITS(2)
+  t = (unsigned)b & 3;
+  DUMPBITS(2)
+
+
+  /* restore the global bit buffer */
+  G.bb = b;
+  G.bk = k;
+
+
+  /* inflate that block type */
+  if (t == 2)
+    return inflate_dynamic(__G);
+  if (t == 0)
+    return inflate_stored(__G);
+  if (t == 1)
+    return inflate_fixed(__G);
+
+
+  /* bad block type */
+  return 2;
+}
+
+
+
+int inflate(__G)
+     __GDEF
+/* decompress an inflated entry */
+{
+  int e;                /* last block flag */
+  int r;                /* result code */
+#ifdef DEBUG
+  unsigned h = 0;       /* maximum struct huft's malloc'ed */
+#endif
+
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+  if (G.redirect_slide)
+    wsize = G.redirect_size, redirSlide = G.redirect_buffer;
+  else
+    wsize = WSIZE, redirSlide = slide;   /* how they're #defined if !DLL */
+#endif
+
+  /* initialize window, bit buffer */
+  G.wp = 0;
+  G.bk = 0;
+  G.bb = 0;
+
+
+  /* decompress until the last block */
+  do {
+#ifdef DEBUG
+    G.hufts = 0;
+#endif
+    if ((r = inflate_block(__G__ &e)) != 0)
+      return r;
+#ifdef DEBUG
+    if (G.hufts > h)
+      h = G.hufts;
+#endif
+  } while (!e);
+
+
+  /* flush out redirSlide */
+  FLUSH(G.wp);
+
+
+  /* return success */
+  Trace((stderr, "\n%u bytes in Huffman tables (%d/entry)\n",
+         h * sizeof(struct huft), sizeof(struct huft)));
+  return 0;
+}
+
+
+
+int inflate_free(__G)
+     __GDEF
+{
+  if (G.fixed_tl != (struct huft *)NULL)
+  {
+    huft_free(G.fixed_td);
+    huft_free(G.fixed_tl);
+    G.fixed_td = G.fixed_tl = (struct huft *)NULL;
+  }
+  return 0;
+}
+
+#endif /* ?USE_ZLIB */
+
+
+/*
+ * GRR:  moved huft_build() and huft_free() down here; used by explode()
+ *       and fUnZip regardless of whether USE_ZLIB defined or not
+ */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
+#define BMAX 16         /* maximum bit length of any code (16 for explode) */
+#define N_MAX 288       /* maximum number of codes in any set */
+
+
+int huft_build(__G__ b, n, s, d, e, t, m)
+  __GDEF
+  ZCONST unsigned *b;   /* code lengths in bits (all assumed <= BMAX) */
+  unsigned n;           /* number of codes (assumed <= N_MAX) */
+  unsigned s;           /* number of simple-valued codes (0..s-1) */
+  ZCONST ush *d;        /* list of base values for non-simple codes */
+  ZCONST ush *e;        /* list of extra bits for non-simple codes */
+  struct huft **t;      /* result: starting table */
+  int *m;               /* maximum lookup bits, returns actual */
+/* Given a list of code lengths and a maximum table size, make a set of
+   tables to decode that set of codes.  Return zero on success, one if
+   the given code set is incomplete (the tables are still built in this
+   case), two if the input is invalid (all zero length codes or an
+   oversubscribed set of lengths), and three if not enough memory.
+   The code with value 256 is special, and the tables are constructed
+   so that no bits beyond that code are fetched when that code is
+   decoded. */
+{
+  unsigned a;                   /* counter for codes of length k */
+  unsigned c[BMAX+1];           /* bit length count table */
+  unsigned el;                  /* length of EOB code (value 256) */
+  unsigned f;                   /* i repeats in table every f entries */
+  int g;                        /* maximum code length */
+  int h;                        /* table level */
+  register unsigned i;          /* counter, current code */
+  register unsigned j;          /* counter */
+  register int k;               /* number of bits in current code */
+  int lx[BMAX+1];               /* memory for l[-1..BMAX-1] */
+  int *l = lx+1;                /* stack of bits per table */
+  register unsigned *p;         /* pointer into c[], b[], or v[] */
+  register struct huft *q;      /* points to current table */
+  struct huft r;                /* table entry for structure assignment */
+  struct huft *u[BMAX];         /* table stack */
+  unsigned v[N_MAX];            /* values in order of bit length */
+  register int w;               /* bits before this table == (l * h) */
+  unsigned x[BMAX+1];           /* bit offsets, then code stack */
+  unsigned *xp;                 /* pointer into x */
+  int y;                        /* number of dummy codes added */
+  unsigned z;                   /* number of entries in current table */
+
+
+  /* Generate counts for each bit length */
+  el = n > 256 ? b[256] : BMAX; /* set length of EOB code, if any */
+  memzero((char *)c, sizeof(c));
+  p = (unsigned *)b;  i = n;
+  do {
+    c[*p]++; p++;               /* assume all entries <= BMAX */
+  } while (--i);
+  if (c[0] == n)                /* null input--all zero length codes */
+  {
+    *t = (struct huft *)NULL;
+    *m = 0;
+    return 0;
+  }
+
+
+  /* Find minimum and maximum length, bound *m by those */
+  for (j = 1; j <= BMAX; j++)
+    if (c[j])
+      break;
+  k = j;                        /* minimum code length */
+  if ((unsigned)*m < j)
+    *m = j;
+  for (i = BMAX; i; i--)
+    if (c[i])
+      break;
+  g = i;                        /* maximum code length */
+  if ((unsigned)*m > i)
+    *m = i;
+
+
+  /* Adjust last length count to fill out codes, if needed */
+  for (y = 1 << j; j < i; j++, y <<= 1)
+    if ((y -= c[j]) < 0)
+      return 2;                 /* bad input: more codes than bits */
+  if ((y -= c[i]) < 0)
+    return 2;
+  c[i] += y;
+
+
+  /* Generate starting offsets into the value table for each length */
+  x[1] = j = 0;
+  p = c + 1;  xp = x + 2;
+  while (--i) {                 /* note that i == g from above */
+    *xp++ = (j += *p++);
+  }
+
+
+  /* Make a table of values in order of bit lengths */
+  memzero((char *)v, sizeof(v));
+  p = (unsigned *)b;  i = 0;
+  do {
+    if ((j = *p++) != 0)
+      v[x[j]++] = i;
+  } while (++i < n);
+  n = x[g];                     /* set n to length of v */
+
+
+  /* Generate the Huffman codes and for each, make the table entries */
+  x[0] = i = 0;                 /* first Huffman code is zero */
+  p = v;                        /* grab values in bit order */
+  h = -1;                       /* no tables yet--level -1 */
+  w = l[-1] = 0;                /* no bits decoded yet */
+  u[0] = (struct huft *)NULL;   /* just to keep compilers happy */
+  q = (struct huft *)NULL;      /* ditto */
+  z = 0;                        /* ditto */
+
+  /* go through the bit lengths (k already is bits in shortest code) */
+  for (; k <= g; k++)
+  {
+    a = c[k];
+    while (a--)
+    {
+      /* here i is the Huffman code of length k bits for value *p */
+      /* make tables up to required level */
+      while (k > w + l[h])
+      {
+        w += l[h++];            /* add bits already decoded */
+
+        /* compute minimum size table less than or equal to *m bits */
+        z = (z = g - w) > (unsigned)*m ? *m : z;        /* upper limit */
+        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
+        {                       /* too few codes for k-w bit table */
+          f -= a + 1;           /* deduct codes from patterns left */
+          xp = c + k;
+          while (++j < z)       /* try smaller tables up to z bits */
+          {
+            if ((f <<= 1) <= *++xp)
+              break;            /* enough codes to use up j bits */
+            f -= *xp;           /* else deduct codes from patterns */
+          }
+        }
+        if ((unsigned)w + j > el && (unsigned)w < el)
+          j = el - w;           /* make EOB code end at table */
+        z = 1 << j;             /* table entries for j-bit table */
+        l[h] = j;               /* set table size in stack */
+
+        /* allocate and link in new table */
+        if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) ==
+            (struct huft *)NULL)
+        {
+          if (h)
+            huft_free(u[0]);
+          return 3;             /* not enough memory */
+        }
+#ifdef DEBUG
+        G.hufts += z + 1;         /* track memory usage */
+#endif
+        *t = q + 1;             /* link to list for huft_free() */
+        *(t = &(q->v.t)) = (struct huft *)NULL;
+        u[h] = ++q;             /* table starts after link */
+
+        /* connect to last table, if there is one */
+        if (h)
+        {
+          x[h] = i;             /* save pattern for backing up */
+          r.b = (uch)l[h-1];    /* bits to dump before this table */
+          r.e = (uch)(16 + j);  /* bits in this table */
+          r.v.t = q;            /* pointer to this table */
+          j = (i & ((1 << w) - 1)) >> (w - l[h-1]);
+          u[h-1][j] = r;        /* connect to last table */
+        }
+      }
+
+      /* set up table entry in r */
+      r.b = (uch)(k - w);
+      if (p >= v + n)
+        r.e = 99;               /* out of values--invalid code */
+      else if (*p < s)
+      {
+        r.e = (uch)(*p < 256 ? 16 : 15);  /* 256 is end-of-block code */
+        r.v.n = (ush)*p++;                /* simple code is just the value */
+      }
+      else
+      {
+        r.e = (uch)e[*p - s];   /* non-simple--look up in lists */
+        r.v.n = d[*p++ - s];
+      }
+
+      /* fill code-like entries with r */
+      f = 1 << (k - w);
+      for (j = i >> w; j < z; j += f)
+        q[j] = r;
+
+      /* backwards increment the k-bit code i */
+      for (j = 1 << (k - 1); i & j; j >>= 1)
+        i ^= j;
+      i ^= j;
+
+      /* backup over finished tables */
+      while ((i & ((1 << w) - 1)) != x[h])
+        w -= l[--h];            /* don't need to update q */
+    }
+  }
+
+
+  /* return actual size of base table */
+  *m = l[0];
+
+
+  /* Return true (1) if we were given an incomplete table */
+  return y != 0 && g != 1;
+}
+
+
+
+int huft_free(t)
+struct huft *t;         /* table to free */
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+   list of the tables it made, with the links in a dummy first entry of
+   each table. */
+{
+  register struct huft *p, *q;
+
+
+  /* Go through linked list, freeing from the malloced (t[-1]) address. */
+  p = t;
+  while (p != (struct huft *)NULL)
+  {
+    q = (--p)->v.t;
+    free((zvoid *)p);
+    p = q;
+  }
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/list.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,649 @@
+/*---------------------------------------------------------------------------
+
+  list.c
+
+  This file contains the non-ZipInfo-specific listing routines for UnZip.
+
+  Contains:  list_files()
+             get_time_stamp()   [optional feature]
+             ratio()
+             fnprint()
+
+  ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#ifdef WINDLL
+#  ifdef POCKET_UNZIP
+#    include "wince/intrface.h"
+#  else
+#    include "windll/windll.h"
+#  endif
+#endif
+
+
+#ifdef TIMESTAMP
+   static int  fn_is_dir   OF((__GPRO));
+#endif
+
+#ifndef WINDLL
+   static ZCONST char Far CompFactorStr[] = "%c%d%%";
+   static ZCONST char Far CompFactor100[] = "100%%";
+
+#ifdef OS2_EAS
+   static ZCONST char Far HeadersS[]  =
+     "  Length     EAs   ACLs    Date   Time    Name";
+   static ZCONST char Far HeadersS1[] =
+     " --------    ---   ----    ----   ----    ----";
+#else
+   static ZCONST char Far HeadersS[]  = "  Length     Date   Time    Name";
+   static ZCONST char Far HeadersS1[] = " --------    ----   ----    ----";
+#endif
+
+   static ZCONST char Far HeadersL[]  =
+     " Length   Method    Size  Ratio   Date   Time   CRC-32    Name";
+   static ZCONST char Far HeadersL1[] =
+     "--------  ------  ------- -----   ----   ----   ------    ----";
+   static ZCONST char Far *Headers[][2] =
+     { {HeadersS, HeadersS1}, {HeadersL, HeadersL1} };
+
+   static ZCONST char Far CaseConversion[] =
+     "%s (\"^\" ==> case\n%s   conversion)\n";
+   static ZCONST char Far LongHdrStats[] =
+     "%8lu  %-7s%8lu %4s  %02u-%02u-%02u %02u:%02u  %08lx %c";
+   static ZCONST char Far LongFileTrailer[] =
+     "--------          -------  ---                       \
+     -------\n%8lu         %8lu %4s                            %u file%s\n";
+#ifdef OS2_EAS
+   static ZCONST char Far ShortHdrStats[] =
+     "%9lu %6lu %6lu  %02u-%02u-%02u %02u:%02u  %c";
+   static ZCONST char Far ShortFileTrailer[] = " --------  -----  -----       \
+            -------\n%9lu %6lu %6lu                   %u file%s\n";
+   static ZCONST char Far OS2ExtAttrTrailer[] =
+     "%ld file%s %ld bytes of OS/2 extended attributes attached.\n";
+   static ZCONST char Far OS2ACLTrailer[] =
+     "%ld file%s %ld bytes of access control lists attached.\n";
+#else
+   static ZCONST char Far ShortHdrStats[] =
+     "%9lu  %02u-%02u-%02u %02u:%02u  %c";
+   static ZCONST char Far ShortFileTrailer[] =
+     " --------                   -------\n%9lu                   %u file%s\n";
+#endif /* ?OS2_EAS */
+#endif /* !WINDLL */
+
+
+
+
+
+/*************************/
+/* Function list_files() */
+/*************************/
+
+int list_files(__G)    /* return PK-type error code */
+    __GDEF
+{
+    int do_this_file=FALSE, cfactor, error, error_in_archive=PK_COOL;
+#ifndef WINDLL
+    char sgn, cfactorstr[10];
+    int longhdr=(uO.vflag>1);
+#endif
+    int date_format;
+    unsigned j, methnum, members=0;
+#ifdef USE_EF_UT_TIME
+    iztimes z_utime;
+    struct tm *t;
+#endif
+    unsigned yr, mo, dy, hh, mm;
+    ulg csiz, tot_csize=0L, tot_ucsize=0L;
+#ifdef OS2_EAS
+    ulg ea_size, tot_easize=0L, tot_eafiles=0L;
+    ulg acl_size, tot_aclsize=0L, tot_aclfiles=0L;
+#endif
+    min_info info;
+    char methbuf[8];
+    static ZCONST char dtype[]="NXFS";  /* see zi_short() */
+    static ZCONST char Far method[NUM_METHODS+1][8] =
+        {"Stored", "Shrunk", "Reduce1", "Reduce2", "Reduce3", "Reduce4",
+         "Implode", "Token", "Defl:#", "EnhDefl", "ImplDCL", "Unk:###"};
+
+extern int files;
+
+
+/*---------------------------------------------------------------------------
+    Unlike extract_or_test_files(), this routine confines itself to the cen-
+    tral directory.  Thus its structure is somewhat simpler, since we can do
+    just a single loop through the entire directory, listing files as we go.
+
+    So to start off, print the heading line and then begin main loop through
+    the central directory.  The results will look vaguely like the following:
+
+ Length   Method    Size  Ratio   Date   Time   CRC-32    Name ("^" ==> case
+--------  ------  ------- -----   ----   ----   ------    ----   conversion)
+   44004  Implode   13041  71%  11-02-89 19:34  8b4207f7  Makefile.UNIX
+    3438  Shrunk     2209  36%  09-15-90 14:07  a2394fd8 ^dos-file.ext
+   16717  Defl:X     5252  69%  11-03-97 06:40  1ce0f189  WHERE
+--------          -------  ---                            -------
+   64159            20502  68%                            3 files
+  ---------------------------------------------------------------------------*/
+
+
+    G.pInfo = &info;
+    date_format = DATE_FORMAT;
+
+	files = 0;
+
+#ifndef WINDLL
+    if (uO.qflag < 2) {
+        if (uO.L_flag)
+            Info(slide, 0, ((char *)slide, LoadFarString(CaseConversion),
+              LoadFarStringSmall(Headers[longhdr][0]),
+              LoadFarStringSmall2(Headers[longhdr][1])));
+        else
+            Info(slide, 0, ((char *)slide, "%s\n%s\n",
+               LoadFarString(Headers[longhdr][0]),
+               LoadFarStringSmall(Headers[longhdr][1])));
+    }
+#endif /* !WINDLL */
+
+    for (j = 0; j++ < (unsigned)G.ecrec.total_entries_central_dir;) {
+
+        if (readbuf(__G__ G.sig, 4) == 0)
+            return PK_EOF;
+        if (strncmp(G.sig, central_hdr_sig, 4)) {  /* just to make sure */
+            Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), j));
+            Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
+            return PK_BADERR;   /* sig not found */
+        }
+        /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag, ...: */
+        if ((error = process_cdir_file_hdr(__G)) != PK_COOL)
+            return error;       /* only PK_EOF defined */
+
+        /*
+         * We could DISPLAY the filename instead of storing (and possibly trun-
+         * cating, in the case of a very long name) and printing it, but that
+         * has the disadvantage of not allowing case conversion--and it's nice
+         * to be able to see in the listing precisely how you have to type each
+         * filename in order for unzip to consider it a match.  Speaking of
+         * which, if member names were specified on the command line, check in
+         * with match() to see if the current file is one of them, and make a
+         * note of it if it is.
+         */
+
+        if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=
+             PK_COOL)   /*  ^--(uses pInfo->lcflag) */
+        {
+            error_in_archive = error;
+            if (error > PK_WARN)   /* fatal:  can't continue */
+                return error;
+        }
+        if (G.extra_field != (uch *)NULL) {
+            free(G.extra_field);
+            G.extra_field = (uch *)NULL;
+        }
+        if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD))
+            != 0)
+        {
+            error_in_archive = error;
+            if (error > PK_WARN)      /* fatal */
+                return error;
+        }
+        if (!G.process_all_files) {   /* check if specified on command line */
+            unsigned i;
+
+            do_this_file = FALSE;
+            for (i = 0; i < G.filespecs; i++)
+                if (match(G.filename, G.pfnames[i], uO.C_flag)) {
+                    do_this_file = TRUE;
+                    break;       /* found match, so stop looping */
+                }
+            if (do_this_file) {  /* check if this is an excluded file */
+                for (i = 0; i < G.xfilespecs; i++)
+                    if (match(G.filename, G.pxnames[i], uO.C_flag)) {
+                        do_this_file = FALSE;  /* ^-- ignore case in match */
+                        break;
+                    }
+            }
+        }
+        /*
+         * If current file was specified on command line, or if no names were
+         * specified, do the listing for this file.  Otherwise, get rid of the
+         * file comment and go back for the next file.
+         */
+
+        if (G.process_all_files || do_this_file) {
+
+#ifdef OS2DLL
+            /* this is used by UzpFileTree() to allow easy processing of lists
+             * of zip directory contents */
+            if (G.processExternally) {
+                if ((G.processExternally)(G.filename, &G.crec))
+                    break;
+                ++members;
+            } else {
+#endif
+#ifdef OS2_EAS
+            {
+                uch *ef_ptr = G.extra_field;
+                int ef_size, ef_len = G.crec.extra_field_length;
+                ea_size = acl_size = 0;
+
+                while (ef_len >= EB_HEADSIZE) {
+                    ef_size = makeword(&ef_ptr[EB_LEN]);
+                    switch (makeword(&ef_ptr[EB_ID])) {
+                        case EF_OS2:
+                            ea_size = makelong(&ef_ptr[EB_HEADSIZE]);
+                            break;
+                        case EF_ACL:
+                            acl_size = makelong(&ef_ptr[EB_HEADSIZE]);
+                            break;
+                    }
+                    ef_ptr += (ef_size + EB_HEADSIZE);
+                    ef_len -= (ef_size + EB_HEADSIZE);
+                }
+            }
+#endif
+#ifdef USE_EF_UT_TIME
+            if (G.extra_field &&
+#ifdef IZ_CHECK_TZ
+                G.tz_is_valid &&
+#endif
+                (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,
+                                  G.crec.last_mod_dos_datetime, &z_utime, NULL)
+                 & EB_UT_FL_MTIME))
+            {
+                TIMET_TO_NATIVE(z_utime.mtime)   /* NOP unless MSC 7.0, Mac */
+                t = localtime(&(z_utime.mtime));
+            } else
+                t = (struct tm *)NULL;
+            if (t != (struct tm *)NULL) {
+                mo = (unsigned)(t->tm_mon + 1);
+                dy = (unsigned)(t->tm_mday);
+                yr = (unsigned)(t->tm_year % 100);
+                hh = (unsigned)(t->tm_hour);
+                mm = (unsigned)(t->tm_min);
+            } else
+#endif /* USE_EF_UT_TIME */
+            {
+                yr = ((((unsigned)(G.crec.last_mod_dos_datetime >> 25) & 0x7f)
+                       + 80) % (unsigned)100);
+                mo = ((unsigned)(G.crec.last_mod_dos_datetime >> 21) & 0x0f);
+                dy = ((unsigned)(G.crec.last_mod_dos_datetime >> 16) & 0x1f);
+                hh = (((unsigned)G.crec.last_mod_dos_datetime >> 11) & 0x1f);
+                mm = (((unsigned)G.crec.last_mod_dos_datetime >> 5) & 0x3f);
+            }
+            /* permute date so it displays according to nat'l convention
+             * ('methnum' is not yet set, it is used as temporary buffer) */
+            switch (date_format) {
+                case DF_YMD:
+                    methnum = (unsigned)mo;
+                    mo = yr; yr = dy; dy = (ush)methnum;
+                    break;
+                case DF_DMY:
+                    methnum = (unsigned)mo;
+                    mo = dy; dy = (ush)methnum;
+            }
+
+            csiz = G.crec.csize;
+            if (G.crec.general_purpose_bit_flag & 1)
+                csiz -= 12;   /* if encrypted, don't count encryption header */
+            if ((cfactor = ratio(G.crec.ucsize, csiz)) < 0) {
+#ifndef WINDLL
+                sgn = '-';
+#endif
+                cfactor = (-cfactor + 5) / 10;
+            } else {
+#ifndef WINDLL
+                sgn = ' ';
+#endif
+                cfactor = (cfactor + 5) / 10;
+            }
+
+            methnum = MIN(G.crec.compression_method, NUM_METHODS);
+            zfstrcpy(methbuf, method[methnum]);
+            if (methnum == DEFLATED) {
+                methbuf[5] = dtype[(G.crec.general_purpose_bit_flag>>1) & 3];
+            } else if (methnum >= NUM_METHODS) {
+                sprintf(&methbuf[4], "%03u", G.crec.compression_method);
+            }
+
+#if 0       /* GRR/Euro:  add this? */
+#if defined(DOS_FLX_OS2_W32) || defined(UNIX)
+            for (p = G.filename;  *p;  ++p)
+                if (!isprint(*p))
+                    *p = '?';  /* change non-printable chars to '?' */
+#endif /* DOS_FLX_OS2_W32 || UNIX */
+#endif /* 0 */
+
+#ifdef WINDLL
+            /* send data to application for formatting and printing */
+            (*G.lpUserFunctions->SendApplicationMessage)(G.crec.ucsize, csiz,
+              (ush)cfactor, mo, dy, yr, hh, mm,
+              (char)(G.pInfo->lcflag ? '^' : ' '),
+              (LPSTR)fnfilter(G.filename, slide), (LPSTR)methbuf, G.crec.crc32,
+              (char)((G.crec.general_purpose_bit_flag & 1) ? 'E' : ' '));
+#else /* !WINDLL */
+            if (cfactor == 100)
+                sprintf(cfactorstr, LoadFarString(CompFactor100));
+            else
+                sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
+            if (longhdr)
+                Info(slide, 0, ((char *)slide, LoadFarString(LongHdrStats),
+                  G.crec.ucsize, methbuf, csiz, cfactorstr, mo, dy,
+                  yr, hh, mm, G.crec.crc32, (G.pInfo->lcflag? '^':' ')));
+            else
+#ifdef OS2_EAS
+                Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats),
+                  G.crec.ucsize, ea_size, acl_size,
+                  mo, dy, yr, hh, mm, (G.pInfo->lcflag? '^':' ')));
+#else
+                Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats),
+                  G.crec.ucsize,
+                  mo, dy, yr, hh, mm, (G.pInfo->lcflag? '^':' ')));
+#endif
+				/* fnprint(__G);*/
+				files++;
+#endif /* ?WINDLL */
+
+            if ((error = do_string(__G__ G.crec.file_comment_length,
+                                   QCOND? DISPL_8 : SKIP)) != 0)
+            {
+                error_in_archive = error;  /* might be just warning */
+                if (error > PK_WARN)       /* fatal */
+                    return error;
+            }
+            tot_ucsize += G.crec.ucsize;
+            tot_csize += csiz;
+            ++members;
+#ifdef OS2_EAS
+            if (ea_size) {
+                tot_easize += ea_size;
+                ++tot_eafiles;
+            }
+            if (acl_size) {
+                tot_aclsize += acl_size;
+                ++tot_aclfiles;
+            }
+#endif
+#ifdef OS2DLL
+            } /* end of "if (G.processExternally) {...} else {..." */
+#endif
+        } else {        /* not listing this file */
+            SKIP_(G.crec.file_comment_length)
+        }
+    } /* end for-loop (j: files in central directory) */
+
+/*---------------------------------------------------------------------------
+    Print footer line and totals (compressed size, uncompressed size, number
+    of members in zipfile).
+  ---------------------------------------------------------------------------*/
+
+    if (uO.qflag < 2
+#ifdef OS2DLL
+                     && !G.processExternally
+#endif
+                                            ) {
+        if ((cfactor = ratio(tot_ucsize, tot_csize)) < 0) {
+#ifndef WINDLL
+            sgn = '-';
+#endif
+            cfactor = (-cfactor + 5) / 10;
+        } else {
+#ifndef WINDLL
+            sgn = ' ';
+#endif
+            cfactor = (cfactor + 5) / 10;
+        }
+#ifdef WINDLL
+        /* pass the totals back to the calling application */
+        G.lpUserFunctions->TotalSizeComp = tot_csize;
+        G.lpUserFunctions->TotalSize = tot_ucsize;
+        G.lpUserFunctions->CompFactor = cfactor;
+        G.lpUserFunctions->NumMembers = members;
+
+#else /* !WINDLL */
+        if (cfactor == 100)
+            sprintf(cfactorstr, LoadFarString(CompFactor100));
+        else
+            sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
+        if (longhdr) {
+            Info(slide, 0, ((char *)slide, LoadFarString(LongFileTrailer),
+              tot_ucsize, tot_csize, cfactorstr, members, members==1? "":"s"));
+#ifdef OS2_EAS
+            if (tot_easize || tot_aclsize)
+                Info(slide, 0, ((char *)slide, "\n"));
+            if (tot_eafiles && tot_easize)
+                Info(slide, 0, ((char *)slide, LoadFarString(OS2ExtAttrTrailer),
+                  tot_eafiles, tot_eafiles == 1? " has" : "s have a total of",
+                  tot_easize));
+            if (tot_aclfiles && tot_aclsize)
+                Info(slide, 0, ((char *)slide, LoadFarString(OS2ACLTrailer),
+                  tot_aclfiles, tot_aclfiles == 1? " has" : "s have a total of",
+                  tot_aclsize));
+#endif /* OS2_EAS */
+        } else
+#ifdef OS2_EAS
+            Info(slide, 0, ((char *)slide, LoadFarString(ShortFileTrailer),
+              tot_ucsize, tot_easize, tot_aclsize, members, members == 1?
+              "" : "s"));
+#else
+            Info(slide, 0, ((char *)slide, LoadFarString(ShortFileTrailer),
+              tot_ucsize, members, members == 1? "" : "s"));
+#endif /* OS2_EAS */
+#endif /* ?WINDLL */
+    }
+
+/*---------------------------------------------------------------------------
+    Double check that we're back at the end-of-central-directory record.
+  ---------------------------------------------------------------------------*/
+
+    if (readbuf(__G__ G.sig, 4) == 0)  /* disk error? */
+        return PK_EOF;
+    if (strncmp(G.sig, end_central_sig, 4)) {   /* just to make sure again */
+        Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
+        error_in_archive = PK_WARN;   /* didn't find sig */
+    }
+    if (members == 0 && error_in_archive <= PK_WARN)
+        error_in_archive = PK_FIND;
+
+    return error_in_archive;
+
+} /* end function list_files() */
+
+
+
+
+
+#ifdef TIMESTAMP
+
+/************************/
+/* Function fn_is_dir() */
+/************************/
+
+static int fn_is_dir(__G)    /* returns TRUE if G.filename is directory */
+    __GDEF
+{
+    extent fn_len = strlen(G.filename);
+    register char   endc;
+
+    return  fn_len > 0 &&
+            ((endc = G.filename[fn_len-1]) == '/' ||
+             (G.pInfo->hostnum == FS_FAT_ && !strchr(G.filename, '/') &&
+              endc == '\\'));
+}
+
+
+
+
+
+/*****************************/
+/* Function get_time_stamp() */
+/*****************************/
+
+int get_time_stamp(__G__ last_modtime, nmember)  /* return PK-type error code */
+    __GDEF
+    time_t *last_modtime;
+    unsigned *nmember;
+{
+    int do_this_file=FALSE, error, error_in_archive=PK_COOL;
+    unsigned j;
+#ifdef USE_EF_UT_TIME
+    iztimes z_utime;
+#endif
+    min_info info;
+
+
+/*---------------------------------------------------------------------------
+    Unlike extract_or_test_files() but like list_files(), this function works
+    on information in the central directory alone.  Thus we have a single,
+    large loop through the entire directory, searching for the latest time
+    stamp.
+  ---------------------------------------------------------------------------*/
+
+    *last_modtime = 0L;         /* assuming no zipfile data older than 1970 */
+    *nmember = 0;
+    G.pInfo = &info;
+
+    for (j = 0; j++ < (unsigned)G.ecrec.total_entries_central_dir;) {
+
+        if (readbuf(__G__ G.sig, 4) == 0)
+            return PK_EOF;
+        if (strncmp(G.sig, central_hdr_sig, 4)) {  /* just to make sure */
+            Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), j));
+            Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
+            return PK_BADERR;
+        }
+        /* process_cdir_file_hdr() sets pInfo->lcflag: */
+        if ((error = process_cdir_file_hdr(__G)) != PK_COOL)
+            return error;       /* only PK_EOF defined */
+        if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) != PK_OK)
+        {        /*  ^-- (uses pInfo->lcflag) */
+            error_in_archive = error;
+            if (error > PK_WARN)   /* fatal:  can't continue */
+                return error;
+        }
+        if (G.extra_field != (uch *)NULL) {
+            free(G.extra_field);
+            G.extra_field = (uch *)NULL;
+        }
+        if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD))
+            != 0)
+        {
+            error_in_archive = error;
+            if (error > PK_WARN)      /* fatal */
+                return error;
+        }
+        if (!G.process_all_files) {   /* check if specified on command line */
+            unsigned i;
+
+            do_this_file = FALSE;
+            for (i = 0; i < G.filespecs; i++)
+                if (match(G.filename, G.pfnames[i], uO.C_flag)) {
+                    do_this_file = TRUE;
+                    break;       /* found match, so stop looping */
+                }
+            if (do_this_file) {  /* check if this is an excluded file */
+                for (i = 0; i < G.xfilespecs; i++)
+                    if (match(G.filename, G.pxnames[i], uO.C_flag)) {
+                        do_this_file = FALSE;  /* ^-- ignore case in match */
+                        break;
+                    }
+            }
+        }
+
+        /* If current file was specified on command line, or if no names were
+         * specified, check the time for this file.  Either way, get rid of the
+         * file comment and go back for the next file.
+         * Directory entries are always ignored, to stay compatible with both
+         * Zip and PKZIP.
+         */
+        if ((G.process_all_files || do_this_file) && !fn_is_dir(__G)) {
+#ifdef USE_EF_UT_TIME
+            if (G.extra_field &&
+#ifdef IZ_CHECK_TZ
+                G.tz_is_valid &&
+#endif
+                (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,
+                                  G.crec.last_mod_dos_datetime, &z_utime, NULL)
+                 & EB_UT_FL_MTIME))
+            {
+                if (*last_modtime < z_utime.mtime)
+                    *last_modtime = z_utime.mtime;
+            } else
+#endif /* USE_EF_UT_TIME */
+            {
+                time_t modtime = dos_to_unix_time(G.crec.last_mod_dos_datetime);
+
+                if (*last_modtime < modtime)
+                    *last_modtime = modtime;
+            }
+            ++*nmember;
+        }
+        SKIP_(G.crec.file_comment_length)
+
+    } /* end for-loop (j: files in central directory) */
+
+/*---------------------------------------------------------------------------
+    Double check that we're back at the end-of-central-directory record.
+  ---------------------------------------------------------------------------*/
+
+    if (readbuf(__G__ G.sig, 4) == 0)
+        return PK_EOF;
+    if (strncmp(G.sig, end_central_sig, 4)) {   /* just to make sure again */
+        Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
+        error_in_archive = PK_WARN;
+    }
+    if (*nmember == 0 && error_in_archive <= PK_WARN)
+        error_in_archive = PK_FIND;
+
+    return error_in_archive;
+
+} /* end function get_time_stamp() */
+
+#endif /* TIMESTAMP */
+
+
+
+
+
+/********************/
+/* Function ratio() */    /* also used by ZipInfo routines */
+/********************/
+
+int ratio(uc, c)
+    ulg uc, c;
+{
+    ulg denom;
+
+    if (uc == 0)
+        return 0;
+    if (uc > 2000000L) {    /* risk signed overflow if multiply numerator */
+        denom = uc / 1000L;
+        return ((uc >= c) ?
+            (int) ((uc-c + (denom>>1)) / denom) :
+          -((int) ((c-uc + (denom>>1)) / denom)));
+    } else {             /* ^^^^^^^^ rounding */
+        denom = uc;
+        return ((uc >= c) ?
+            (int) ((1000L*(uc-c) + (denom>>1)) / denom) :
+          -((int) ((1000L*(c-uc) + (denom>>1)) / denom)));
+    }                            /* ^^^^^^^^ rounding */
+}
+
+
+
+
+
+/************************/
+/*  Function fnprint()  */    /* also used by ZipInfo routines */
+/************************/
+
+void fnprint(__G)    /* print filename (after filtering) and newline */
+    __GDEF
+{
+    char *name = fnfilter(G.filename, slide);
+
+    (*G.message)((zvoid *)&G, (uch *)name, (ulg)strlen(name), 0);
+    (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
+
+} /* end function fnprint() */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/makefile.b32	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,118 @@
+# Makefile for UnZip(SFX) and fUnZip for Borland C++ for Windows 95/NT
+# Version: 5.4 and later        Alvin Koh, Jim Knoble, Christian Spieler, etc.
+# Adapted from the MS-DOS makefile by E-Yen Tan
+#
+# Last revised:  24 Nov 98
+#
+#
+
+
+#    Optional nonstandard preprocessor flags (as -DCHECK_EOF or -DDOS_WILD)
+#    should be added to the environment via "set LOCAL_UNZIP=-DFOO" or added
+#    to the declaration of LOC here:
+LOC = $(LOCAL_UNZIP)
+
+# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc.
+CPU_TYP = 4
+
+# (De)Select inclusion of optimized assembler CRC32 routine:
+USE_ASMCRC = 0
+
+# If you have bcc32i, you should define:
+# CC = bcc32i
+# This compiler generates a faster code.
+CC = bcc32
+AS = tasm32
+
+!if $(USE_ASMCRC)
+ASMFLG = -DASM_CRC
+ASMOBJS = crc_i386.obj
+!else
+ASMFLG =
+ASMOBJS =
+!endif
+
+!if $(UNCLEAN)
+DIRT = -DUSE_SMITH_CODE -DUSE_UNSHRINK
+!else
+DIRT =
+!endif
+
+# compiler flags
+
+ASCPUFLAG = __$(CPU_TYP)86
+!if $(CPU_TYP) != 0
+CC_CPUFLG = -$(CPU_TYP)
+!endif
+ASFLAGS = -ml -m2 -w0 -D$(ASCPUFLAG) $(LOC)
+CFLAGS = -O2 -w- $(CC_CPUFLG) -ff- -k- -P-.C -I. -I.. -I..\inczip -DWIN32 $(ASMFLG) $(LOC) $(DIRT)
+LDFLAGS = -lxncd -l-P		# for bcc
+UNFLAGS = $(CFLAGS)
+
+# implicit rules
+
+.asm.obj:
+	$(AS) $(ASFLAGS) $<
+
+.c.obj:
+	$(CC) -c $(UNFLAGS) {$< }
+
+# list macros
+
+OBJU1 = unzip.obj crc32.obj crctab.obj crypt.obj envargs.obj explode.obj
+OBJU2 = extract.obj fileio.obj globals.obj inflate.obj list.obj match.obj
+OBJU3 = process.obj ttyio.obj unreduce.obj unshrink.obj zipinfo.obj
+OBJUS = win32.obj nt.obj $(ASMOBJS) packinst.obj
+OBJU  = $(OBJU1) $(OBJU2) $(OBJU3) $(OBJUS)
+
+UNZIP_H = ..\inczip\unzip.h ..\inczip\unzpriv.h ..\inczip\globals.h ..\inczip\w32cfg.h
+
+# explicit rules
+
+all:    packinst.exe
+
+packinst.exe:      $(OBJU)
+	$(CC) $(LDFLAGS) -epackinst.exe @&&|
+$(OBJU)
+|
+
+clean:
+        -erase *.obj
+        -erase *.exe
+        -erase *.res
+        -erase *.map
+        -erase *.rws
+        -erase *.tds
+        -erase *.il?
+
+# individual file dependencies
+
+crc32.obj:      crc32.c $(UNZIP_H) ..\inczip\zip.h
+crctab.obj:     crctab.c $(UNZIP_H) ..\inczip\zip.h
+crypt.obj:      crypt.c $(UNZIP_H) ..\inczip\zip.h ..\inczip\crypt.h ..\inczip\ttyio.h
+envargs.obj:    envargs.c $(UNZIP_H)
+explode.obj:    explode.c $(UNZIP_H)
+extract.obj:    extract.c $(UNZIP_H) ..\inczip\crypt.h
+fileio.obj:     fileio.c $(UNZIP_H) ..\inczip\crypt.h ..\inczip\ttyio.h ..\inczip\ebcdic.h
+globals.obj:    globals.c $(UNZIP_H)
+inflate.obj:    inflate.c ..\inczip\inflate.h $(UNZIP_H)
+list.obj:       list.c $(UNZIP_H)
+match.obj:      match.c $(UNZIP_H)
+process.obj:    process.c $(UNZIP_H)
+ttyio.obj:      ttyio.c $(UNZIP_H) ..\inczip\zip.h ..\inczip\crypt.h ..\inczip\ttyio.h
+unreduce.obj:   unreduce.c $(UNZIP_H)
+unshrink.obj:   unshrink.c $(UNZIP_H)
+unzip.obj:      unzip.c $(UNZIP_H) ..\inczip\crypt.h ..\inczip\version.h ..\inczip\consts.h
+zipinfo.obj:    zipinfo.c $(UNZIP_H)
+
+crc_i386.obj:   crc_i386.asm
+	$(AS) $(ASFLAGS) crc_i386.asm, $*.obj ;
+
+win32.obj:      win32.c $(UNZIP_H)
+	$(CC) -c $(UNFLAGS) win32.c
+
+packinst.obj:      ..\packinst\packinst.c $(UNZIP_H)
+	$(CC) -c $(UNFLAGS) ..\packinst\packinst.c
+        
+nt.obj:         nt.c $(UNZIP_H)
+	$(CC) -c $(UNFLAGS) nt.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/makefile.g95	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,158 @@
+# Makefile for UnZip, fUnZip and UnZipSFX for native Win32-Intel ports of gcc.
+# Currently supported implementations: Cygnus/Win32 and MinGW32.
+#
+# First version: Cosmin Truta <cosmint@cs.ubbcluj.ro>, Dec 1997.
+# Last revision: Christian Spieler, 29-Apr-1998
+#
+# To use, do "make -f win32/makefile.gcc".
+
+
+### Optional section
+
+# Optional nonstandard preprocessor flags (as -DUSE_ZLIB or -DUSE_SMITH_CODE)
+# should be added to the environment via "set LOCAL_UNZIP=-DFOO" or added
+# to the declaration of LOCFLAGS here:
+LOCFLAGS = $(LOCAL_UNZIP)
+
+
+### Compiler-specific section
+
+# ------------ GNU C ------------
+CC = gcc
+
+#AS = as
+AS = $(CC)
+
+#LD = ld
+LD = $(CC)
+
+# Quiet
+CC_QUIET_OPT =
+AS_QUIET_OPT = $(CC_QUIET_OPT)
+LD_QUIET_OPT = $(CC_QUIET_OPT)
+
+# Warnings
+CC_WARN_OPT = -Wall
+AS_WARN_OPT = $(CC_WARN_OPT)
+LD_WARN_OPT =
+
+# Debug version
+CC_DEBUG_OPT = -g
+AS_DEBUG_OPT = $(CC_DEBUG_OPT)
+LD_DEBUG_OPT = $(CC_DEBUG_OPT)
+
+# Release version
+CC_RELEASE_OPT =
+AS_RELEASE_OPT =
+LD_RELEASE_OPT = -s
+
+# Smallest code
+CC_SIZE_OPT = -O1
+
+# Fastest code
+CC_SPEED_OPT = -O2
+
+# Output object file name
+CC_OUT_OPT = -o
+
+# Other specific options
+#CC_SPECIFIC_OPT = -c -DASM_CRC -DWIN32 -mno-cygwin
+CC_SPECIFIC_OPT = -c -DWIN32 -mno-cygwin -I../inczip
+AS_SPECIFIC_OPT = -c
+LD_SPECIFIC_OPT = -mno-cygwin -o $@
+
+# Libraries for the debug & release version
+LD_RELEASE_LIBS = -luser32 -ladvapi32
+LD_DEBUG_LIBS = $(LD_RELEASE_LIBS)
+
+
+### System-specific section
+
+# Suffixes
+OBJ = .o
+EXE = .exe
+
+.SUFFIXES: .c .S $(OBJ) $(EXE)
+
+# Commands
+RM = rm -f
+
+
+### General section
+
+CFLAGS  = $(CC_SPECIFIC_OPT) $(CC_QUIET_OPT) $(CC_WARN_OPT) $(LOCFLAGS) \
+ $(CC_OUT_OPT) $@
+ASFLAGS = $(AS_SPECIFIC_OPT) $(AS_QUIET_OPT) $(AS_WARN_OPT) $(LOCFLAGS)
+LDFLAGS = $(LD_SPECIFIC_OPT) $(LD_QUIET_OPT) $(LD_WARN_OPT)
+
+# To build with debug info, use 'make DEBUG=1'.
+ifdef DEBUG
+CVER     = $(CC_DEBUG_OPT)
+ASVER    = $(AS_DEBUG_OPT)
+LDVER    = $(LD_DEBUG_OPT)
+GENFLAGS =
+FFLAGS   = -DFUNZIP
+SFXFLAGS = -DSFX
+LDLIBS   = $(LD_DEBUG_LIBS)
+else
+CVER     = $(CC_RELEASE_OPT)
+ASVER    = $(AS_RELEASE_OPT)
+LDVER    = $(LD_RELEASE_OPT)
+GENFLAGS = $(CC_SPEED_OPT)
+FFLAGS   = $(CC_SPEED_OPT) -DFUNZIP
+SFXFLAGS = $(CC_SIZE_OPT) -DSFX
+LDLIBS   = $(LD_RELEASE_LIBS)
+endif
+
+# Object files
+OBJA  = crc_i386$(OBJ) packinst$(OBJ)
+OBJS1 = unzip$(OBJ) crc32$(OBJ) crctab$(OBJ) crypt$(OBJ) envargs$(OBJ)
+OBJS2 = explode$(OBJ) extract$(OBJ) fileio$(OBJ) globals$(OBJ) inflate$(OBJ)
+OBJS3 = list$(OBJ) match$(OBJ) process$(OBJ) ttyio$(OBJ) unreduce$(OBJ)
+OBJS4 = unshrink$(OBJ) zipinfo$(OBJ) win32$(OBJ) nt$(OBJ)
+OBJS  = $(OBJS1) $(OBJS2) $(OBJS3) $(OBJS4) $(OBJA)
+
+UNZIP_H = ../inczip/unzip.h ../inczip/unzpriv.h ../inczip/globals.h ../inczip/w32cfg.h
+
+
+# Default target is all the executables
+unzips: packinst$(EXE)
+
+packinst$(EXE): $(OBJS)
+	$(LD) $(LDFLAGS) $(LDVER) $(OBJS) $(LDLIBS)
+
+# How to compile sources
+.c$(OBJ):
+	$(CC) $(CFLAGS) $(CVER) $(GENFLAGS) $<
+.S$(OBJ):
+	$(AS) $(ASFLAGS) $(ASVER) $(GENFLAGS) $<
+
+# Dependencies
+crc32$(OBJ):    crc32.c $(UNZIP_H) ../inczip/zip.h
+crctab$(OBJ):   crctab.c $(UNZIP_H) ../inczip/zip.h
+crypt$(OBJ):    crypt.c $(UNZIP_H) ../inczip/zip.h ../inczip/crypt.h ../inczip/ttyio.h
+envargs$(OBJ):  envargs.c $(UNZIP_H)
+explode$(OBJ):  explode.c $(UNZIP_H)
+extract$(OBJ):  extract.c $(UNZIP_H) ../inczip/crypt.h
+fileio$(OBJ):   fileio.c $(UNZIP_H) ../inczip/crypt.h ../inczip/ttyio.h ../inczip/ebcdic.h
+funzip$(OBJ):   funzip.c $(UNZIP_H) ../inczip/crypt.h ../inczip/ttyio.h ../inczip/tables.h
+globals$(OBJ):  globals.c $(UNZIP_H)
+inflate$(OBJ):  inflate.c ../inczip/inflate.h $(UNZIP_H)
+list$(OBJ):     list.c $(UNZIP_H)
+match$(OBJ):    match.c $(UNZIP_H)
+process$(OBJ):  process.c $(UNZIP_H)
+ttyio$(OBJ):    ttyio.c $(UNZIP_H) ../inczip/zip.h ../inczip/crypt.h ../inczip/ttyio.h
+unreduce$(OBJ): unreduce.c $(UNZIP_H)
+unshrink$(OBJ): unshrink.c $(UNZIP_H)
+unzip$(OBJ):    unzip.c $(UNZIP_H) ../inczip/crypt.h ../inczip/version.h ../inczip/consts.h
+zipinfo$(OBJ):  zipinfo.c $(UNZIP_H)
+crc_i386$(OBJ): crc_i386.S
+win32$(OBJ): win32.c $(UNZIP_H) ../inczip/nt.h
+nt$(OBJ): nt.c ../inczip/nt.h
+        
+packinst$(OBJ): ../packinst/packinst.c
+	$(CC) $(CFLAGS) $(CVER) $(GENFLAGS) $<
+
+clean:
+	$(RM) *$(OBJ)
+	$(RM) *$(EXE)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/makefile.gcc	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,146 @@
+#==============================================================================
+# Makefile for UnZip, UnZipSFX and fUnZip:  Unix and MS-DOS ("real" makes only)
+# Version:  5.4                                                19 November 1998
+#==============================================================================
+
+
+# INSTRUCTIONS (such as they are):
+#
+# "make sunos"	-- makes UnZip in current directory on a generic SunOS 4.x Sun
+# "make list"	-- lists all supported systems (targets)
+# "make help"	-- provides pointers on what targets to try if problems occur
+# "make wombat" -- chokes and dies if you haven't added the specifics for your
+#		    Wombat 68000 (or whatever) to the systems list
+#
+# CF are flags for the C compiler.  LF are flags for the loader.  LF2 are more
+# flags for the loader, if they need to be at the end of the line instead of at
+# the beginning (for example, some libraries).  FL and FL2 are the corre-
+# sponding flags for fUnZip.  LOCAL_UNZIP is an environment variable that can
+# be used to add default C flags to your compile without editing the Makefile
+# (e.g., -DDEBUG_STRUC, or -FPi87 on PCs using Microsoft C).
+#
+# Some versions of make do not define the macro "$(MAKE)"; this is rare, but
+# if things don't work, try using "make" instead of "$(MAKE)" in your system's
+# makerule.  Or try adding the following line to your .login file:
+#	setenv MAKE "make"
+# (That never works--makes that are too stupid to define MAKE are also too
+# stupid to look in the environment--but try it anyway for kicks. :-) )
+#
+# Memcpy and memset are provided for those systems that don't have them; they
+# are in fileio.c and will be used if -DZMEM is included in CF.  These days
+# almost all systems have them.
+#
+# Be sure to test your new UnZip (and UnZipSFX and fUnZip); successful compila-
+# tion does not always imply a working program.
+
+
+#####################
+# MACRO DEFINITIONS #
+#####################
+
+# Defaults most systems use (use LOCAL_UNZIP in environment to add flags,
+# such as -DDOSWILD).
+
+# UnZip flags
+CC = cc#	try using "gcc" target rather than changing this (CC and LD
+LD = $(CC)#	must match, else "unresolved symbol:  ___main" is possible)
+AS = as
+LOC = $(LOCAL_UNZIP)
+AF = $(LOC)
+CF = -O -I. -I.. -I../inczip $(LOC)
+LF = -o packinst
+LF2 = -s
+
+# general-purpose stuff
+#CP = cp
+CP = ln
+LN = ln
+RM = rm -f
+CHMOD = chmod
+BINPERMS = 755
+MANPERMS = 644
+STRIP = strip
+E =
+O = .o
+M = unix
+SHELL = /bin/sh
+
+# defaults for crc32 stuff and system dependent headers
+CRC32 = crc32
+
+# object files
+OBJS1 = unzip$O $(CRC32)$O crctab$O crypt$O envargs$O explode$O
+OBJS2 = extract$O fileio$O globals$O inflate$O list$O match$O
+OBJS3 = process$O ttyio$O unreduce$O unshrink$O zipinfo$O
+OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O packinst$O
+#OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O install$O wxmain$O instsup$O
+UNZIP_H = ../inczip/unzip.h ../inczip/unzpriv.h ../inczip/globals.h
+
+# installation
+# (probably can change next two to `install' and `install -d' if you have it)
+INSTALL = cp
+INSTALL_D = mkdir -p
+
+###############################################
+# BASIC COMPILE INSTRUCTIONS AND DEPENDENCIES #
+###############################################
+
+# this is for GNU make; comment out and notify zip-bugs if it causes errors
+.SUFFIXES:	.c .o .obj .pic.o
+
+# yes, we should be able to use the $O macro to combine these two, but it
+# fails on some brain-damaged makes (e.g., AIX's)...no big deal
+.c.o:
+	$(CC) -c $(CF) $*.c
+
+.c.obj:
+	$(CC) -c $(CF) $*.c
+
+.c.pic.o:
+	$(CC) -c $(CF) -o $@ $*.c
+
+all:	        sfx
+
+
+# EDIT HERE FOR PARALLEL MAKES on Sequent (and others?)--screws up MS-DOS
+# make utilities if default:  change "unzip$E:" to "unzip$E:&"
+
+sfx$E:	$(OBJS)			# add `&' for parallel makes
+	$(LD) $(LF) $(OBJS)
+
+crc32$O:	crc32.c $(UNZIP_H) ../inczip/zip.h
+crctab$O:	crctab.c $(UNZIP_H)  ../inczip/zip.h
+crypt$O:	crypt.c $(UNZIP_H)  ../inczip/zip.h  ../inczip/crypt.h  ../inczip/ttyio.h
+envargs$O:	envargs.c $(UNZIP_H)
+explode$O:	explode.c $(UNZIP_H)
+extract$O:	extract.c $(UNZIP_H)  ../inczip/crypt.h
+fileio$O:	fileio.c $(UNZIP_H)  ../inczip/crypt.h  ../inczip/ttyio.h  ../inczip/ebcdic.h
+funzip$O:	funzip.c $(UNZIP_H)  ../inczip/crypt.h  ../inczip/ttyio.h  ../inczip/tables.h
+globals$O:	globals.c $(UNZIP_H)
+inflate$O:	inflate.c  ../inczip/inflate.h $(UNZIP_H)
+list$O:		list.c $(UNZIP_H)
+match$O:	match.c $(UNZIP_H)
+process$O:	process.c $(UNZIP_H)
+ttyio$O:	ttyio.c $(UNZIP_H)  ../inczip/zip.h  ../inczip/crypt.h  ../inczip/ttyio.h
+unreduce$O:	unreduce.c $(UNZIP_H)
+unshrink$O:	unshrink.c $(UNZIP_H)
+unzip$O:	unzip.c $(UNZIP_H)  ../inczip/crypt.h  ../inczip/version.h  ../inczip/consts.h
+zipinfo$O:	zipinfo.c $(UNZIP_H)
+
+unix$O:		unix.c $(UNZIP_H)  ../inczip/version.h		# Unix only
+	$(CC) -c $(CF)  unix.c
+
+packinst$O:		../packinst/packinst.c	      
+	$(CC) -c $(CF)  ../packinst/packinst.c
+
+#install$O:		../install.c	      
+#	$(CC) -c $(CF)  ../install.c
+#
+#unix$O:		../wxmain.cpp
+#	$(CC) -c $(CF)  ../wxmain.cpp
+#
+#unix$O:	        ../instsup.cpp 
+#	$(CC) -c $(CF)  ../instsup.cpp
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/makefile.os2	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,670 @@
+# Makefile for UnZip, UnZipSFX and fUnZip                     24 November 1998
+#
+#  supported compilers:
+#  - Microsoft C, version 6.00 or higher, for use under OS/2 1.x (16-bit)
+#  - Watcom C/C++, version 9.0+, for use under OS/2 1.x or 2.x+ (16/32-bit)
+#  - emx+gcc, version 0.9c or higher, for use under OS/2 2.x+ (32-bit)
+#  - IBM C Set++, for use under OS/2 2.x+ (32-bit)
+#  - Borland C++, for use under OS/2 2.x+ (32-bit)
+#  - Metaware High C/C++, for use under OS/2 2.x+ (32-bit)
+#
+#  supported cross-compilers:
+#  - Microsoft C, version 6.0 or 7.0, for use under DOS (16-bit)
+#  - Watcom C/C++, version 9.0+, for use under DOS/Win95/NT (16/32-bit)
+#  - GNU gcc (emx), version 0.9c or higher, for use under DOS/Win95/NT (32-bit)
+#
+#  supported assemblers:
+#  - Microsoft MASM 6.00 with Microsoft C
+#  - Watcom WASM with Watcom C/C++
+#  - GNU as with GNU gcc
+
+# To use MASM 5.x instead of MASM 6.00:
+#  - set AS="masm -t -Ml"
+#  - set ASEOL=";"
+
+# To use, enter "{d,n}make -f os2/makefile.os2" (this makefile depends on its
+# name being "makefile.os2", and it must be in the os2 subdirectory).
+
+# Notes on Microsoft C 6.00 compilation for OS/2:
+#
+#   The resulting programs can be used under OS/2 protected mode only, not
+#   under DOS.  A larger stack has to be used for OS/2 because system calls
+#   use more stack than under DOS; 8k is recommended by Microsoft.
+
+# Notes on IBM C Set++, Watcom C/C++, Borland C++ or emx+gcc compilation:
+#
+#   The resulting programs can be used under protected mode of OS/2 2.x or
+#   higher only, not under OS/2 1.x and not under DOS.
+#
+#   The NFLAGS macro is used to work around an optimization bug in the IBM
+#   C++ Set compiler; this is fixed by CSD #4, so NFLAGS="" can be used for
+#   all targets below.
+
+# Notes on Watcom C/C++ compilation for DOS with the PMODE/W extender:
+#
+#   You need to add the following section to your \watcom\binb\wlsystem.lnk
+#   file and also need to copy pmodew.exe to the same directory:
+#
+#   system begin pmodew
+#       option osname='PMODE/W'
+#       libpath %WATCOM%\lib386
+#       libpath %WATCOM%\lib386\dos
+#       op stub=pmodew.exe
+#       format os2 le
+#   end
+#
+#   PMODE/W 1.16 or higher is required.  See also msdos/README for important
+#   notes about PMODE/W bugs.
+
+default:
+	@echo "Enter `$(MAKE) -f os2/makefile.os2 target' from the main"
+	@echo "UnZip directory, where target is one of:"
+	@echo "   msc mscdebug mscdos ibm ibmdyn ibmdebug ibmprof"
+	@echo "   ibmdll ibmdyndll ibmdebugdll ibmprofdll"
+	@echo "   metaware borland gcc gccdyn gccdebug gccdos gccwin32"
+	@echo "   watcom watcom16 watcomdos watcom16dos pmodew watcomwin32"
+
+# MS C 6.00 for OS/2, 16-bit (should figure out way to split unzip/funzip
+# compiles so former is always large model and latter always small model...)
+msc:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="cl -nologo -AL -Ocegit -Gs -I. $(FP)" \
+	CFLAGS="-G2 -Zp1 -W3 -DOS2 -DMSC -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="ml -nologo -c -Zm -Cp" \
+	ASFLAGS="-D__LARGE__ -D__286" \
+	LDFLAGS="-F 2000 -Lp -Fe" \
+	LDFLAGS2="-link /noe" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	CRC32="crc_i86" \
+	CRC32F="crc_i86" \
+	CRC32X="crc_i86" \
+	DEF="os2\unzip.def"
+
+# MS C 6.00 for OS/2, debug version
+mscdebug:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="cl -nologo -AL -Zi -Od -I. $(FP)" \
+	CFLAGS="-G2 -Zp1 -W3 -DOS2 -DMSC -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="ml -nologo -c -Zim -Cp" \
+	ASFLAGS="-D__LARGE__ -D__286" \
+	LDFLAGS="-F 2000 -Lp -Fe" \
+	LDFLAGS2="-link /noe" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	CRC32="crc_i86" \
+	CRC32F="crc_i86" \
+	CRC32X="crc_i86" \
+	DEF="os2\unzip.def"
+
+# cross-compilation for MS-DOS with MS C 6.00 (same comment as above...formerly;
+# now unzip is medium model again, with [almost] all strings in far memory)
+mscdos:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="cl -nologo -AM -Oaict -Gs -I. $(FP)" \
+	CFLAGS="-Zp1 -W3 -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="ml -nologo -c -Zm -Cp" \
+	ASFLAGS="-D__MEDIUM__" \
+	LDFLAGS="-F 0C00 -Lr -Fe" \
+	LDFLAGS2="-link /noe /exe" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	CRC32="crc_i86" \
+	CRC32F="crc_i86" \
+	CRC32X="crc_i86" \
+	OBJU2="msdos.obj" \
+	OBJX2="msdos_.obj" \
+	OSDEP_H="msdos/doscfg.h"
+
+# IBM C Set, statically linked runtime
+ibm:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="icc -Q -O -Gs -I." \
+	CFLAGS="-Sm -Sp1 -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	LDFLAGS="-B/ST:0x50000 -Fe" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	DEF="os2\unzip.def"
+
+# IBM C Set, dynamically linked runtime
+ibmdyn:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="icc -Q -O -Gs -Gd -I." \
+	CFLAGS="-Sm -Sp1 -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	LDFLAGS="-B/ST:0x50000 -Fe" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	DEF="os2\unzip.def"
+
+# IBM C Set, debug version
+ibmdebug:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="icc -Q -Ti -I." \
+	CFLAGS="-Sm -Sp1 -D__DEBUG_ALLOC__ -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	LDFLAGS="-B/ST:0x50000 -Fe" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	DEF="os2\unzip.def"
+
+# IBM C Set, profiling version for PROFIT
+ibmprof:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="icc -Q -O -Gs -Gh -Ti -I." \
+	CFLAGS="-Sm -Sp1 -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	LDFLAGS="-B/ST:0x50000 -Fe" \
+	LDFLAGS2="cppopa3.obj" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	DEF="os2\unzip.def"
+
+# IBM C Set, statically linked runtime
+ibmdll:
+	$(MAKE) -f os2/makefile.os2 dll \
+	CC="icc -Q -O -Gs -I." \
+	CFLAGS="-Sm -Sp1 -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="-Gm -Ge- -DDLL -DOS2DLL -DAPI_DOC" \
+	LDFLAGS="-Fe" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	DLLDEF="os2\rexxapi.def" \
+	STUBDEF="os2\stub.def" \
+	DEF="os2\unzip.def" \
+	APILIB="REXX.lib"
+
+# IBM C Set, dynamically linked runtime
+ibmdyndll:
+	$(MAKE) -f os2/makefile.os2 dll \
+	CC="icc -Q -O -Gs -Gd -I." \
+	CFLAGS="-Sm -Sp1 -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="-Gm -Ge- -DDLL -DOS2DLL -DAPI_DOC" \
+	LDFLAGS="-Fe" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	DLLDEF="os2\rexxapi.def" \
+	STUBDEF="os2\stub.def" \
+	DEF="os2\unzip.def" \
+	APILIB="REXX.lib"
+
+# IBM C Set, debug version
+ibmdebugdll:
+	$(MAKE) -f os2/makefile.os2 dll \
+	CC="icc -Q -Ti -I." \
+	CFLAGS="-Sm -Sp1 -D__DEBUG_ALLOC__ -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="-Gm -Ge- -DDLL -DOS2DLL -DAPI_DOC" \
+	LDFLAGS="-Fe" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	DLLDEF="os2\rexxapi.def" \
+	STUBDEF="os2\stub.def" \
+	DEF="os2\unzip.def" \
+	APILIB="REXX.lib"
+
+# IBM C Set, profiling version for PROFIT
+ibmprofdll:
+	$(MAKE) -f os2/makefile.os2 dll \
+	CC="icc -Q -O -Gs -Gh -Ti -I." \
+	CFLAGS="-Gm -Sm -Sp1 -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="-Gm -Ge- -DDLL -DOS2DLL -DAPI_DOC" \
+	LDFLAGS="-Fe" \
+	LDFLAGS2="profit.obj" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	DLLDEF="os2\rexxapi.def" \
+	STUBDEF="os2\stub.def" \
+	DEF="os2\unzip.def" \
+	APILIB="REXX.lib"
+
+# Watcom C/386 9.0 or higher
+watcom:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="wcl386 -bt=os2v2 -zq -Ox -s -I." \
+	CFLAGS="-Zp1 -DOS2 -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="wasm -bt=os2v2 -zq -3 -mf" \
+	ASFLAGS="" \
+	LDFLAGS="-k0x50000 -x -l=os2v2 -Fe=" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	CRC32="crc_i386" \
+	CRC32F="crc_i386" \
+	CRC32X="crc_i386" \
+	DEF="" \
+	DIRSEP="\\" \
+	AS_DIRSEP="\\"
+
+# Watcom C/286 9.0 or higher
+watcom16:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="wcl -bt=os2 -zq -ml -Ox -s -I." \
+	CFLAGS="-Zp1 -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="wasm -bt=os2 -zq -2 -ml" \
+	ASFLAGS="" \
+	LDFLAGS="-k0x2000 -x -l=os2 -Fe=" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	CRC32="crc_i86" \
+	CRC32F="crc_i86" \
+	CRC32X="crc_i86" \
+	DIRSEP="\\" \
+	AS_DIRSEP="\\"
+
+# Watcom C/386 9.0 or higher, crosscompilation for DOS, DOS4GW extender
+watcomdos:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="wcl386 -bt=dos4g -zq -Ox -s -I." \
+	CFLAGS="-Zp1 -DMSDOS -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="wasm -bt=dos4g -zq -3 -mf" \
+	ASFLAGS="" \
+	LDFLAGS="-k0x50000 -x -l=dos4g -Fe=" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	CRC32="crc_i386" \
+	CRC32F="crc_i386" \
+	CRC32X="crc_i386" \
+	OBJU2="msdos.obj" \
+	OBJX2="msdos_.obj" \
+	OSDEP_H="msdos/doscfg.h" \
+	DIRSEP="\\" \
+	AS_DIRSEP="\\"
+
+# Watcom C/386 9.0 or higher, crosscompilation for DOS, PMODE/W extender
+pmodew:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="wcl386 -bt=dos4g -zq -Ox -s -I." \
+	CFLAGS="-Zp1 -DMSDOS -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="wasm -bt=dos4g -zq -3 -mf" \
+	ASFLAGS="" \
+	LDFLAGS="-k0x50000 -x -l=pmodew -Fe=" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	CRC32="crc_i386" \
+	CRC32F="crc_i386" \
+	CRC32X="crc_i386" \
+	OBJU2="msdos.obj" \
+	OBJX2="msdos_.obj" \
+	OSDEP_H="msdos/doscfg.h" \
+	DIRSEP="\\" \
+	AS_DIRSEP="\\"
+
+# Watcom C/286 9.0 or higher, crosscompilation for DOS
+watcom16dos:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="wcl -bt=dos -zq -ml -Ox -s -I." \
+	CFLAGS="-Zp1 -DMSDOS $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="wasm -bt=dos -0 -mm" \
+	ASFLAGS="-D__MEDIUM__" \
+	LDFLAGS="-k0xC00 -x -l=dos -Fe=" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	OBJU2="msdos.obj" \
+	OBJX2="msdos_.obj" \
+	OSDEP_H="msdos/doscfg.h" \
+	DIRSEP="\\" \
+	AS_DIRSEP="\\"
+
+# Watcom C/386 9.0 or higher, crosscompilation for Win95/NT
+watcomwin32:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="wcl386 -bt=NT -zq -Ox -s -I." \
+	CFLAGS="-Zp1 -DWIN32 -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="wasm -bt=NT -zq -3 -mf" \
+	ASFLAGS="" \
+	LDFLAGS="-k0x50000 -x -l=NT -Fe=" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	OBJU2="win32.obj nt.obj" \
+	OBJX2="win32_.obj nt_.obj" \
+	CRC32="crc_i386" \
+	CRC32F="crc_i386" \
+	CRC32X="crc_i386" \
+	DEF="" \
+	DIRSEP="\\" \
+	AS_DIRSEP="\\"
+
+# MetaWare High C/C++ 3.2
+metaware:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="hc -O2 -I." \
+	CFLAGS="-D__32BIT__ -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	LDFLAGS="-o " \
+	LDFLAGS2="" \
+	OUT="-o ./" \
+	OBJ=".obj" \
+	DEF="-Hdef=os2\unzip.def"
+
+# Borland C++
+borland:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="bcc -O -I. -Ios2" \
+	CFLAGS="-w- -D__cdecl -D__32BIT__ -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	LDFLAGS="-e" \
+	LDFLAGS2="" \
+	OUT="-o" \
+	OBJ=".obj" \
+	DEF="-sDos2\unzip.def"
+
+# emx, gcc, OMF format, statically linked C runtime
+gcc:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="gcc -Zomf -O -I." \
+	CFLAGS="-Wall -DOS2 -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="gcc -Zomf" \
+	ASFLAGS="-Di386" \
+	LDFLAGS="-o ./" \
+	LDFLAGS2="-Zsmall-conv -Zstack 320 -Zsys -s" \
+	OUT="-o" \
+	OBJ=".obj" \
+	CRC32="crc_gcc" \
+	CRC32F="crc_gcc" \
+	CRC32X="crc_gcc" \
+	DEF="os2/unzip.def"
+
+# emx, gcc, OMF format, dynamically linked C runtime
+gccdyn:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="gcc -Zomf -O -I." \
+	CFLAGS="-Wall -DOS2 -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="gcc -Zomf" \
+	ASFLAGS="-Di386" \
+	LDFLAGS="-o ./" \
+	LDFLAGS2="-Zstack 320 -Zcrtdll -s" \
+	OUT="-o" \
+	OBJ=".obj" \
+	CRC32="crc_gcc" \
+	CRC32F="crc_gcc" \
+	CRC32X="crc_gcc" \
+	DEF="os2/unzip.def"
+
+# emx, gcc, a.out format, with debug info for gdb
+gccdebug:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="gcc -g -I." \
+	CFLAGS="-Wall -DOS2 -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="gcc -g" \
+	ASFLAGS="-Di386" \
+	LDFLAGS="-o ./" \
+	LDFLAGS2="-Zsmall-conv" \
+	OUT="-o" \
+	OBJ=".o" \
+	CRC32="crc_gcc" \
+	CRC32F="crc_gcc" \
+	CRC32X="crc_gcc"
+
+# emx, gcc, a.out format, cross-compilation for MS-DOS
+gccdos:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="gcc -O -I." \
+	CFLAGS="-Wall -DMSDOS -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="gcc" \
+	ASFLAGS="-Di386" \
+	LDFLAGS="-o ./" \
+	LDFLAGS2="-Zsmall-conv -s" \
+	OUT="-o" \
+	OBJ=".o" \
+	CRC32="crc_gcc" \
+	CRC32F="crc_gcc" \
+	CRC32X="crc_gcc" \
+	OBJU2="msdos.o" \
+	OBJX2="msdos_.o" \
+	OSDEP_H="msdos/doscfg.h"
+
+# emx, gcc, RSXNT, cross-compilation for Win32, statically linked C runtime
+gccwin32:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="gcc -Zwin32 -O2 -I." \
+	CFLAGS="-Wall -DWIN32 -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="gcc" \
+	ASFLAGS="-Di386" \
+	LDFLAGS="-Zsys -o ./" \
+	LDFLAGS2="-ladvapi32 -Zsmall-conv -s" \
+	OUT="-o" \
+	OBJ=".o" \
+	CRC32="crc_gcc" \
+	CRC32F="crc_gcc" \
+	CRC32X="crc_gcc" \
+	OBJU2="win32.o nt.o" \
+	OBJX2="win32_.o nt_.o" \
+	OBJF2="win32f.o" \
+	OSDEP_H="win32/w32cfg.h"
+
+# variables
+
+# LOCAL_UNZIP = -DREENTRANT
+
+# default settings for target dependent macros:
+DIRSEP = /
+AS_DIRSEP = /
+
+OSDEP_H = os2/os2data.h os2/os2cfg.h
+CRC32   = crc32
+CRC32F  = crc32f
+CRC32X  = crc32_
+
+OBJU  = unzip$(OBJ) $(CRC32)$(OBJ) crctab$(OBJ) crypt$(OBJ) envargs$(OBJ) \
+	explode$(OBJ) extract$(OBJ) fileio$(OBJ) globals$(OBJ) \
+	inflate$(OBJ) list$(OBJ) match$(OBJ) process$(OBJ) ttyio$(OBJ) \
+	unreduce$(OBJ) unshrink$(OBJ) zipinfo$(OBJ)
+OBJU2 = os2$(OBJ) os2acl$(OBJ)
+OBJX  = unzipsf_$(OBJ) $(CRC32X)$(OBJ) crctab_$(OBJ) crypt_$(OBJ) \
+        extract_$(OBJ) fileio_$(OBJ) globals_$(OBJ) inflate_$(OBJ) \
+	match_$(OBJ) process_$(OBJ) ttyio_$(OBJ)
+OBJX2 = os2_$(OBJ) os2acl_$(OBJ)
+OBJDLL= api$(OBJ) apihelp$(OBJ) rexxhelp$(OBJ) rexxapi$(OBJ)
+OBJF  = funzip$(OBJ) $(CRC32F)$(OBJ) cryptf$(OBJ) inflatef$(OBJ) \
+	globalsf$(OBJ) ttyiof$(OBJ)
+OBJF2 =
+
+UNZIP_H = unzip.h unzpriv.h globals.h $(OSDEP_H)
+
+# rules
+
+.SUFFIXES:	.c .asm $(OBJ)
+
+.c$(OBJ):
+	$(CC) -c $(CFLAGS) $(DLLFLAG) $<
+
+.asm$(OBJ):
+	$(AS) $(ASFLAGS) $< $(ASEOL)
+
+# targets
+
+all:	unzip.exe funzip.exe unzipsfx.exe
+dll:	unzip32.dll unzip.stb funzip.exe unzipsfx.exe
+
+unzip.exe: $(OBJU) $(OBJU2)
+	$(CC) $(LDFLAGS)$@ $(DEF) $(OBJU) $(OBJU2) $(LDFLAGS2)
+
+funzip.exe: $(OBJF) $(OBJF2)
+	$(CC) $(LDFLAGS)$@ $(DEF) $(OBJF) $(OBJF2) $(LDFLAGS2)
+
+unzipsfx.exe:	$(OBJX) $(OBJX2)
+	$(CC) $(LDFLAGS)$@ $(DEF) $(OBJX) $(OBJX2) $(LDFLAGS2)
+
+unzip32.dll: $(DLLDEF) $(OBJU) $(OBJU2) $(OBJDLL)
+	$(CC) $(DLLFLAG) $(LDFLAGS)$@ $(DLLDEF) $(OBJU) $(OBJDLL) $(OBJU2) $(APILIB) $(LDFLAGS2)
+
+unzip.stb: unzipstb$(OBJ) $(STUBDEF)
+	$(CC) $(LDFLAGS)$@ $(STUBDEF) unzipstb$(OBJ) $(LDFLAGS2)
+	copy unzip.stb unzip.exe
+
+# dependencies
+
+apihelp$(OBJ):	apihelp.c $(UNZIP_H) version.h
+crc32$(OBJ):	crc32.c $(UNZIP_H) zip.h
+crctab$(OBJ):	crctab.c $(UNZIP_H) zip.h
+envargs$(OBJ):	envargs.c $(UNZIP_H)
+explode$(OBJ):	explode.c $(UNZIP_H)
+extract$(OBJ):	extract.c $(UNZIP_H) crypt.h
+fileio$(OBJ):	fileio.c $(UNZIP_H) crypt.h ttyio.h ebcdic.h
+globals$(OBJ):	globals.c $(UNZIP_H)
+inflate$(OBJ):	inflate.c $(UNZIP_H)
+list$(OBJ):	list.c $(UNZIP_H)
+match$(OBJ):	match.c $(UNZIP_H)
+process$(OBJ):	process.c $(UNZIP_H)
+ttyio$(OBJ):	ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h
+unreduce$(OBJ):	unreduce.c $(UNZIP_H)
+unshrink$(OBJ):	unshrink.c $(UNZIP_H)
+unzip$(OBJ):	unzip.c $(UNZIP_H) crypt.h version.h consts.h
+api$(OBJ):	api.c $(UNZIP_H) version.h
+zipinfo$(OBJ):	zipinfo.c $(UNZIP_H)
+
+funzip$(OBJ):	funzip.c $(UNZIP_H) crypt.h ttyio.h tables.h	# funzip only
+	$(CC) -c $(CFLAGS) funzip.c
+
+unzipstb$(OBJ):	unzipstb.c					# DLL version
+	$(CC) -c $(CFLAGS) unzipstb.c
+
+msdos$(OBJ):	msdos/msdos.c $(UNZIP_H) version.h		# DOS only
+	$(CC) -c $(CFLAGS) msdos$(DIRSEP)msdos.c
+
+msdos_$(OBJ):	msdos/msdos.c $(UNZIP_H)			# DOS unzipsfx
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ msdos$(DIRSEP)msdos.c
+
+win32$(OBJ):	win32/win32.c $(UNZIP_H) win32/nt.h version.h	# Win32 only
+	$(CC) -c $(CFLAGS) win32$(DIRSEP)win32.c
+
+nt$(OBJ):	win32/nt.c $(UNZIP_H) win32/nt.h		# Win32 only
+	$(CC) -c $(CFLAGS) win32$(DIRSEP)nt.c
+
+win32_$(OBJ):	win32/win32.c $(UNZIP_H) win32/nt.h		# Win32 unzipsfx
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ win32$(DIRSEP)win32.c
+
+nt_$(OBJ):	win32/nt.c $(UNZIP_H) win32/nt.h		# Win32 unzipsfx
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ win32$(DIRSEP)nt.c
+
+win32f$(OBJ):	win32/win32.c $(UNZIP_H) win32/nt.h		# Win32 funzip
+	$(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ win32$(DIRSEP)win32.c
+
+os2$(OBJ):	os2/os2.c $(UNZIP_H) version.h			# OS/2 only
+	$(CC) -c $(CFLAGS) $(DLLFLAG) os2$(DIRSEP)os2.c
+
+os2_$(OBJ):	os2/os2.c $(UNZIP_H)				# OS/2 unzipsfx
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ os2$(DIRSEP)os2.c
+
+os2acl$(OBJ):	os2/os2acl.c $(UNZIP_H) version.h		# OS/2 only
+	$(CC) -c $(CFLAGS) $(DLLFLAG) os2$(DIRSEP)os2acl.c
+
+os2acl_$(OBJ):	os2/os2acl.c $(UNZIP_H) version.h		# OS/2 unzipsfx
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ os2$(DIRSEP)os2acl.c
+
+rexxhelp$(OBJ):	os2/rexxhelp.c					# OS/2 DLL only
+	$(CC) -c $(CFLAGS) $(DLLFLAG) os2$(DIRSEP)rexxhelp.c
+
+rexxapi$(OBJ):	os2/rexxapi.c					# OS/2 DLL only
+	$(CC) -c $(CFLAGS) $(DLLFLAG) os2$(DIRSEP)rexxapi.c
+
+crc_i86$(OBJ):	msdos/crc_i86.asm				# 16bit only
+	$(AS) $(ASFLAGS) msdos$(AS_DIRSEP)crc_i86.asm $(ASEOL)
+
+crc_i386$(OBJ):	win32/crc_i386.asm				# 32bit, MASM
+	$(AS) $(ASFLAGS) win32$(AS_DIRSEP)crc_i386.asm $(ASEOL)
+
+crc_gcc$(OBJ):	crc_i386.S					# 32bit, GNU AS
+	$(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S
+
+# NFLAGS are solely used as work-around for optimization bug in IBM C++ Set
+crypt$(OBJ):	crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h
+	$(CC) -c $(CFLAGS) $(DLLFLAG) $(NFLAGS) crypt.c
+
+cryptf$(OBJ):	crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h	# funzip only
+	$(CC) -c $(CFLAGS) $(NFLAGS) -DFUNZIP $(OUT)$@ crypt.c
+
+crc32f$(OBJ):	crc32.c $(UNZIP_H) zip.h			# funzip only
+	$(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ crc32.c
+
+globalsf$(OBJ):	globals.c $(UNZIP_H)				# funzip only
+	$(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ globals.c
+
+inflatef$(OBJ):	inflate.c inflate.h $(UNZIP_H) crypt.h		# funzip only
+	$(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ inflate.c
+
+ttyiof$(OBJ):	ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h	# funzip only
+	$(CC) -c $(CFLAGS) $(NFLAGS) -DFUNZIP $(OUT)$@ ttyio.c
+
+crc32_$(OBJ):	crc32.c $(UNZIP_H) zip.h			# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ crc32.c
+
+crctab_$(OBJ):	crctab.c $(UNZIP_H) zip.h			# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ crctab.c
+
+crypt_$(OBJ):	crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h	# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ crypt.c
+
+extract_$(OBJ):	extract.c $(UNZIP_H) crypt.h			# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ extract.c
+
+fileio_$(OBJ):	fileio.c $(UNZIP_H) crypt.h ttyio.h ebcdic.h	# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ fileio.c
+
+globals_$(OBJ):	globals.c $(UNZIP_H)				# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ globals.c
+
+inflate_$(OBJ):	inflate.c inflate.h $(UNZIP_H) crypt.h		# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ inflate.c
+
+match_$(OBJ):	match.c $(UNZIP_H)				# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ match.c
+
+process_$(OBJ):	process.c $(UNZIP_H)				# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ process.c
+
+ttyio_$(OBJ):	ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h	# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ ttyio.c
+
+unzipsf_$(OBJ):	unzip.c $(UNZIP_H) crypt.h version.h consts.h	# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ unzip.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/makefile.vc	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,80 @@
+#
+CC = cl
+CFLAGS = -c -G5 -GD -Zp1 -DWIN32 -D__WIN32__ -DMSVC -I. -I.. -I..\inczip
+CFLAGS_DEBUG = -Zi
+CFLAGS_COMPILE = -MTd
+LIBS = kernel32.lib advapi32.lib user32.lib
+RES = 
+LINKFLAGS = -machine:i386 -debug:full -debugtype:cv
+DLLLINKFLAGS = -dll
+LINK = link
+
+OBJS = 	api.obj \
+	apihelp.obj \
+	crc32.obj \
+	crctab.obj \
+	crypt.obj \
+	envargs.obj \
+	explode.obj \
+	extract.obj \
+	fileio.obj \
+	globals.obj \
+	inflate.obj \
+	list.obj \
+	match.obj \
+	nt.obj \
+	..\packinst\packinst.obj \
+	process.obj \
+	unreduce.obj \
+	unshrink.obj \
+	unzip.obj \
+	win32.obj \
+	zipinfo.obj
+
+LINKOBJS = 	api.obj \
+		apihelp.obj \
+		crc32.obj \
+		crctab.obj \
+		crypt.obj \
+		envargs.obj \
+		explode.obj \
+		extract.obj \
+		fileio.obj \
+		globals.obj \
+		inflate.obj \
+		list.obj \
+		match.obj \
+		nt.obj \
+		packinst.obj \
+		process.obj \
+		unreduce.obj \
+		unshrink.obj \
+		unzip.obj \
+		win32.obj \
+		zipinfo.obj
+                
+all: packinst.exe
+
+clean:
+	-erase *.dll
+        -erase *.exe
+        -erase *.opt
+        -erase *.lib
+        -erase *.obj
+        -erase *.map
+        -erase *.pdb
+        -erase *.ilk
+        -erase *.exp
+        -erase *.res
+        -erase *~
+        
+packinst.exe: $(OBJS)
+	$(LINK) @<<
+-out:$(@) -subsystem:console
+$(LINKFLAGS)
+$(LINKOBJS)
+$(LIBS)
+<<
+
+.c.obj:
+	$(CC) $(CFLAGS) $(CFLAGS_DEBUG) $(CFLAGS_COMPILE) $*.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/match.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,294 @@
+/*---------------------------------------------------------------------------
+
+  match.c
+
+  The match() routine recursively compares a string to a "pattern" (regular
+  expression), returning TRUE if a match is found or FALSE if not.  This
+  version is specifically for use with unzip.c:  as did the previous match()
+  routines from SEA and J. Kercheval, it leaves the case (upper, lower, or
+  mixed) of the string alone, but converts any uppercase characters in the
+  pattern to lowercase if indicated by the global var pInfo->lcflag (which
+  is to say, string is assumed to have been converted to lowercase already,
+  if such was necessary).
+
+  GRR:  reversed order of text, pattern in matche() (now same as match());
+        added ignore_case/ic flags, Case() macro.
+
+  PaulK:  replaced matche() with recmatch() from Zip, modified to have an
+          ignore_case argument; replaced test frame with simpler one.
+
+  ---------------------------------------------------------------------------
+
+  Copyright on recmatch() from Zip's util.c (although recmatch() was almost
+  certainly written by Mark Adler...ask me how I can tell :-) ):
+
+     Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly,
+     Kai Uwe Rommel and Igor Mandrichenko.
+
+     Permission is granted to any individual or institution to use, copy,
+     or redistribute this software so long as all of the original files are
+     included unmodified, that it is not sold for profit, and that this copy-
+     right notice is retained.
+
+  ---------------------------------------------------------------------------
+
+  Match the pattern (wildcard) against the string (fixed):
+
+     match(string, pattern, ignore_case);
+
+  returns TRUE if string matches pattern, FALSE otherwise.  In the pattern:
+
+     `*' matches any sequence of characters (zero or more)
+     `?' matches any single character
+     [SET] matches any character in the specified set,
+     [!SET] or [^SET] matches any character not in the specified set.
+
+  A set is composed of characters or ranges; a range looks like ``character
+  hyphen character'' (as in 0-9 or A-Z).  [0-9a-zA-Z_] is the minimal set of
+  characters allowed in the [..] pattern construct.  Other characters are
+  allowed (i.e., 8-bit characters) if your system will support them.
+
+  To suppress the special syntactic significance of any of ``[]*?!^-\'', in-
+  side or outside a [..] construct, and match the character exactly, precede
+  it with a ``\'' (backslash).
+
+  Note that "*.*" and "*." are treated specially under MS-DOS if DOSWILD is
+  defined.  See the DOSWILD section below for an explanation.  Note also
+  that with VMSWILD defined, '%' is used instead of '?', and sets (ranges)
+  are delimited by () instead of [].
+
+  ---------------------------------------------------------------------------*/
+
+
+
+/* define ToLower() in here (for Unix, define ToLower to be macro (using
+ * isupper()); otherwise just use tolower() */
+#define UNZIP_INTERNAL
+#include "unzip.h"
+
+#if 0  /* this is not useful until it matches Amiga names insensitively */
+#ifdef AMIGA        /* some other platforms might also want to use this */
+#  define ANSI_CHARSET       /* MOVE INTO UNZIP.H EVENTUALLY */
+#endif
+#endif /* 0 */
+  
+#ifdef ANSI_CHARSET
+#  ifdef ToLower
+#    undef ToLower
+#  endif
+   /* uppercase letters are values 41 thru 5A, C0 thru D6, and D8 thru DE */
+#  define IsUpper(c) (c>=0xC0 ? c<=0xDE && c!=0xD7 : c>=0x41 && c<=0x5A)
+#  define ToLower(c) (IsUpper((uch) c) ? (unsigned) c | 0x20 : (unsigned) c)
+#endif
+#define Case(x)  (ic? ToLower(x) : (x))
+
+#ifdef VMSWILD
+#  define WILDCHAR   '%'
+#  define BEG_RANGE  '('
+#  define END_RANGE  ')'
+#else
+#  define WILDCHAR   '?'
+#  define BEG_RANGE  '['
+#  define END_RANGE  ']'
+#endif
+
+#if 0                /* GRR:  add this to unzip.h someday... */
+#if !(defined(MSDOS) && defined(DOSWILD))
+#define match(s,p,ic)   (recmatch((ZCONST uch *)p,(ZCONST uch *)s,ic) == 1)
+int recmatch OF((ZCONST uch *pattern, ZCONST uch *string, int ignore_case));
+#endif
+#endif /* 0 */
+static int recmatch OF((ZCONST uch *pattern, ZCONST uch *string,
+                        int ignore_case));
+
+
+
+/* match() is a shell to recmatch() to return only Boolean values. */
+
+int match(string, pattern, ignore_case)
+    ZCONST char *string, *pattern;
+    int ignore_case;
+{
+#if (defined(MSDOS) && defined(DOSWILD))
+    char *dospattern;
+    int j = strlen(pattern);
+
+/*---------------------------------------------------------------------------
+    Optional MS-DOS preprocessing section:  compare last three chars of the
+    wildcard to "*.*" and translate to "*" if found; else compare the last
+    two characters to "*." and, if found, scan the non-wild string for dots.
+    If in the latter case a dot is found, return failure; else translate the
+    "*." to "*".  In either case, continue with the normal (Unix-like) match
+    procedure after translation.  (If not enough memory, default to normal
+    match.)  This causes "a*.*" and "a*." to behave as MS-DOS users expect.
+  ---------------------------------------------------------------------------*/
+
+    if ((dospattern = (char *)malloc(j+1)) != NULL) {
+        strcpy(dospattern, pattern);
+        if (!strcmp(dospattern+j-3, "*.*")) {
+            dospattern[j-2] = '\0';                    /* nuke the ".*" */
+        } else if (!strcmp(dospattern+j-2, "*.")) {
+            char *p = strchr(string, '.');
+
+            if (p) {   /* found a dot:  match fails */
+                free(dospattern);
+                return 0;
+            }
+            dospattern[j-1] = '\0';                    /* nuke the end "." */
+        }
+        j = recmatch((uch *)dospattern, (uch *)string, ignore_case);
+        free(dospattern);
+        return j == 1;
+    } else
+#endif /* MSDOS && DOSWILD */
+    return recmatch((uch *)pattern, (uch *)string, ignore_case) == 1;
+}
+
+
+
+static int recmatch(p, s, ic)
+    ZCONST uch *p;        /* sh pattern to match */
+    ZCONST uch *s;        /* string to which to match it */
+    int ic;               /* true for case insensitivity */
+/* Recursively compare the sh pattern p with the string s and return 1 if
+ * they match, and 0 or 2 if they don't or if there is a syntax error in the
+ * pattern.  This routine recurses on itself no more deeply than the number
+ * of characters in the pattern. */
+{
+    unsigned int c;       /* pattern char or start of range in [-] loop */ 
+
+    /* Get first character, the pattern for new recmatch calls follows */
+    c = *p++;
+
+    /* If that was the end of the pattern, match if string empty too */
+    if (c == 0)
+        return *s == 0;
+
+    /* '?' (or '%') matches any character (but not an empty string) */
+    if (c == WILDCHAR)
+        return *s ? recmatch(p, s + 1, ic) : 0;
+
+    /* '*' matches any number of characters, including zero */
+#ifdef AMIGA
+    if (c == '#' && *p == '?')     /* "#?" is Amiga-ese for "*" */
+        c = '*', p++;
+#endif /* AMIGA */
+    if (c == '*') {
+        if (*p == 0)
+            return 1;
+        for (; *s; s++)
+            if ((c = recmatch(p, s, ic)) != 0)
+                return (int)c;
+        return 2;       /* 2 means give up--match will return false */
+    }
+
+    /* Parse and process the list of characters and ranges in brackets */
+    if (c == BEG_RANGE) {
+        int e;          /* flag true if next char to be taken literally */
+        ZCONST uch *q;  /* pointer to end of [-] group */
+        int r;          /* flag true to match anything but the range */
+
+        if (*s == 0)                           /* need a character to match */
+            return 0;
+        p += (r = (*p == '!' || *p == '^'));   /* see if reverse */
+        for (q = p, e = 0; *q; q++)            /* find closing bracket */
+            if (e)
+                e = 0;
+            else
+                if (*q == '\\')      /* GRR:  change to ^ for MS-DOS, OS/2? */
+                    e = 1;
+                else if (*q == END_RANGE)
+                    break;
+        if (*q != END_RANGE)         /* nothing matches if bad syntax */
+            return 0;
+        for (c = 0, e = *p == '-'; p < q; p++) {  /* go through the list */
+            if (e == 0 && *p == '\\')             /* set escape flag if \ */
+                e = 1;
+            else if (e == 0 && *p == '-')         /* set start of range if - */
+                c = *(p-1);
+            else {
+                unsigned int cc = Case(*s);
+
+                if (*(p+1) != '-')
+                    for (c = c ? c : *p; c <= *p; c++)  /* compare range */
+                        if ((unsigned)Case(c) == cc)  /* typecast for MSC bug */
+                            return r ? 0 : recmatch(q + 1, s + 1, ic);
+                c = e = 0;   /* clear range, escape flags */
+            }
+        }
+        return r ? recmatch(q + 1, s + 1, ic) : 0;  /* bracket match failed */
+    }
+
+    /* if escape ('\'), just compare next character */
+    if (c == '\\' && (c = *p++) == 0)     /* if \ at end, then syntax error */
+        return 0;
+
+    /* just a character--compare it */
+#ifdef QDOS
+    return QMatch(Case((uch)c), Case(*s)) ? recmatch(p, ++s, ic) : 0;
+#else
+    return Case((uch)c) == Case(*s) ? recmatch(p, ++s, ic) : 0;
+#endif
+
+} /* end function recmatch() */
+
+
+
+
+
+int iswild(p)        /* originally only used for stat()-bug workaround in */
+    ZCONST char *p;  /*  VAX C, Turbo/Borland C, Watcom C, Atari MiNT libs; */
+{                    /*  now used in process_zipfiles() as well */
+    for (; *p; ++p)
+        if (*p == '\\' && *(p+1))
+            ++p;
+#ifdef VMS
+        else if (*p == '%' || *p == '*')
+#else /* !VMS */
+#ifdef AMIGA
+        else if (*p == '?' || *p == '*' || (*p=='#' && p[1]=='?') || *p == '[')
+#else /* !AMIGA */
+        else if (*p == '?' || *p == '*' || *p == '[')
+#endif /* ?AMIGA */
+#endif /* ?VMS */
+#ifdef QDOS
+            return (int)p;
+#else
+            return TRUE;
+#endif
+
+    return FALSE;
+
+} /* end function iswild() */
+
+
+
+
+
+#ifdef TEST_MATCH
+
+#define put(s) {fputs(s,stdout); fflush(stdout);}
+
+void main()
+{
+    char pat[256], str[256];
+
+    for (;;) {
+        put("Pattern (return to exit): ");
+        gets(pat);
+        if (!pat[0])
+            break;
+        for (;;) {
+            put("String (return for new pattern): ");
+            gets(str);
+            if (!str[0])
+                break;
+            pipeit("Case sensitive: %s  insensitive: %s\n",
+              match(str, pat, 0) ? "YES" : "NO",
+              match(str, pat, 1) ? "YES" : "NO");
+        }
+    }
+    EXIT(0);
+}
+
+#endif /* TEST_MATCH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/nt.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,659 @@
+/*
+
+  Copyright (c) 1996  Scott Field
+
+  Module Name:
+
+    nt.c
+
+  Abstract:
+
+    This module implements WinNT security descriptor operations for the
+    Win32 Info-ZIP project.  Operation such as setting file security,
+    using/querying local and remote privileges, and queuing of operations
+    is performed here.  The contents of this module are only relevant
+    when the code is running on Windows NT, and the target volume supports
+    persistent Acl storage.
+
+    User privileges that allow accessing certain privileged aspects of the
+    security descriptor (such as the Sacl) are only used if the user specified
+    to do so.
+
+  Author:
+
+    Scott Field (sfield@microsoft.com)
+
+  Last revised:  18 Jan 97
+
+ */
+
+#define WIN32_LEAN_AND_MEAN
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#include <windows.h>
+#ifdef __RSXNT__
+#  include "rsxntwin.h"
+#endif
+#include "nt.h"
+
+
+#ifdef NTSD_EAS         /* This file is only needed for NTSD handling */
+
+/* Borland C++ does not define FILE_SHARE_DELETE. Others also? */
+#ifndef FILE_SHARE_DELETE
+#  define FILE_SHARE_DELETE 0x00000004
+#endif
+
+
+/* private prototypes */
+
+static BOOL Initialize(VOID);
+#if 0   /* currently unused */
+static BOOL Shutdown(VOID);
+#endif
+static BOOL DeferSet(char *resource, PVOLUMECAPS VolumeCaps, uch *buffer);
+static VOID GetRemotePrivilegesSet(CHAR *FileName, PDWORD dwRemotePrivileges);
+static VOID InitLocalPrivileges(VOID);
+
+
+BOOL bInitialized = FALSE;  /* module level stuff initialized? */
+HANDLE hInitMutex = NULL;   /* prevent multiple initialization */
+
+BOOL g_bRestorePrivilege = FALSE;   /* for local set file security override */
+BOOL g_bSaclPrivilege = FALSE;      /* for local set sacl operations, only when
+                                       restore privilege not present */
+
+/* our single cached volume capabilities structure that describes the last
+   volume root we encountered.  A single entry like this works well in the
+   zip/unzip scenario for a number of reasons:
+   1. typically one extraction path during unzip.
+   2. typically process one volume at a time during zip, and then move
+      on to the next.
+   3. no cleanup code required and no memory leaks.
+   4. simple code.
+
+   This approach should be reworked to a linked list approach if we expect to
+   be called by many threads which are processing a variety of input/output
+   volumes, since lock contention and stale data may become a bottleneck. */
+
+VOLUMECAPS g_VolumeCaps;
+CRITICAL_SECTION VolumeCapsLock;
+
+
+/* our deferred set structure linked list element, used for making a copy
+   of input data which is used at a later time to process the original input
+   at a time when it makes more sense. eg, applying security to newly created
+   directories, after all files have been placed in such directories. */
+
+CRITICAL_SECTION SetDeferLock;
+
+typedef struct _DEFERRED_SET {
+    struct _DEFERRED_SET *Next;
+    uch *buffer;                /* must point to DWORD aligned block */
+    PVOLUMECAPS VolumeCaps;
+    char *resource;
+} DEFERRED_SET, *PDEFERRED_SET, *LPDEFERRED_SET;
+
+PDEFERRED_SET pSetHead = NULL;
+PDEFERRED_SET pSetTail;
+
+static BOOL Initialize(VOID)
+{
+    HANDLE hMutex;
+    HANDLE hOldMutex;
+
+    if(bInitialized) return TRUE;
+
+    hMutex = CreateMutex(NULL, TRUE, NULL);
+    if(hMutex == NULL) return FALSE;
+
+    hOldMutex = (HANDLE)InterlockedExchange((LPLONG)&hInitMutex, (LONG)hMutex);
+
+    if(hOldMutex != NULL) {
+        /* somebody setup the mutex already */
+        InterlockedExchange((LPLONG)&hInitMutex, (LONG)hOldMutex);
+
+        CloseHandle(hMutex); /* close new, un-needed mutex */
+
+        /* wait for initialization to complete and return status */
+        WaitForSingleObject(hOldMutex, INFINITE);
+        ReleaseMutex(hOldMutex);
+
+        return bInitialized;
+    }
+
+    /* initialize module level resources */
+
+    InitializeCriticalSection( &SetDeferLock );
+
+    InitializeCriticalSection( &VolumeCapsLock );
+    memset(&g_VolumeCaps, 0, sizeof(VOLUMECAPS));
+
+    InitLocalPrivileges();
+
+    bInitialized = TRUE;
+
+    ReleaseMutex(hMutex); /* release correct mutex */
+
+    return TRUE;
+}
+
+#if 0   /* currently not used ! */
+static BOOL Shutdown(VOID)
+{
+    /* really need to free critical sections, disable enabled privilges, etc,
+       but doing so brings up possibility of race conditions if those resources
+       are about to be used.  The easiest way to handle this is let these
+       resources be freed when the process terminates... */
+
+    return TRUE;
+}
+#endif /* never */
+
+
+static BOOL DeferSet(char *resource, PVOLUMECAPS VolumeCaps, uch *buffer)
+{
+    PDEFERRED_SET psd;
+    DWORD cbDeferSet;
+    DWORD cbResource;
+    DWORD cbBuffer;
+
+    if(!bInitialized) if(!Initialize()) return FALSE;
+
+    cbResource = lstrlenA(resource) + 1;
+    cbBuffer = GetSecurityDescriptorLength((PSECURITY_DESCRIPTOR)buffer);
+    cbDeferSet = sizeof(DEFERRED_SET) + cbBuffer + sizeof(VOLUMECAPS) +
+      cbResource;
+
+    psd = (PDEFERRED_SET)HeapAlloc(GetProcessHeap(), 0, cbDeferSet);
+    if(psd == NULL) return FALSE;
+
+    psd->Next = NULL;
+    psd->buffer = (uch *)(psd+1);
+    psd->VolumeCaps = (PVOLUMECAPS)((char *)psd->buffer + cbBuffer);
+    psd->resource = (char *)((char *)psd->VolumeCaps + sizeof(VOLUMECAPS));
+
+    memcpy(psd->buffer, buffer, cbBuffer);
+    memcpy(psd->VolumeCaps, VolumeCaps, sizeof(VOLUMECAPS));
+    psd->VolumeCaps->bProcessDefer = TRUE;
+    memcpy(psd->resource, resource, cbResource);
+
+    /* take defer lock */
+    EnterCriticalSection( &SetDeferLock );
+
+    /* add element at tail of list */
+
+    if(pSetHead == NULL) {
+        pSetHead = psd;
+    } else {
+        pSetTail->Next = psd;
+    }
+
+    pSetTail = psd;
+
+    /* release defer lock */
+    LeaveCriticalSection( &SetDeferLock );
+
+    return TRUE;
+}
+
+BOOL ProcessDefer(PDWORD dwDirectoryCount, PDWORD dwBytesProcessed,
+                  PDWORD dwDirectoryFail, PDWORD dwBytesFail)
+{
+    PDEFERRED_SET This;
+    PDEFERRED_SET Next;
+
+    *dwDirectoryCount = 0;
+    *dwBytesProcessed = 0;
+
+    *dwDirectoryFail = 0;
+    *dwBytesFail = 0;
+
+    if(!bInitialized) return TRUE; /* nothing to do */
+
+    EnterCriticalSection( &SetDeferLock );
+
+    This = pSetHead;
+
+    while(This) {
+
+        if(SecuritySet(This->resource, This->VolumeCaps, This->buffer)) {
+            (*dwDirectoryCount)++;
+            *dwBytesProcessed +=
+              GetSecurityDescriptorLength((PSECURITY_DESCRIPTOR)This->buffer);
+        } else {
+            (*dwDirectoryFail)++;
+            *dwBytesFail +=
+              GetSecurityDescriptorLength((PSECURITY_DESCRIPTOR)This->buffer);
+        }
+
+        Next = This->Next;
+        HeapFree(GetProcessHeap(), 0, This);
+        This = Next;
+    }
+
+    pSetHead = NULL;
+
+    LeaveCriticalSection( &SetDeferLock );
+
+    return TRUE;
+}
+
+BOOL ValidateSecurity(uch *securitydata)
+{
+    PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)securitydata;
+    PACL pAcl;
+    PSID pSid;
+    BOOL bAclPresent;
+    BOOL bDefaulted;
+
+    if(!IsWinNT()) return TRUE; /* don't do anything if not on WinNT */
+
+    if(!IsValidSecurityDescriptor(sd)) return FALSE;
+
+    /* verify Dacl integrity */
+
+    if(!GetSecurityDescriptorDacl(sd, &bAclPresent, &pAcl, &bDefaulted))
+        return FALSE;
+
+    if(bAclPresent) {
+        if(!IsValidAcl(pAcl)) return FALSE;
+    }
+
+    /* verify Sacl integrity */
+
+    if(!GetSecurityDescriptorSacl(sd, &bAclPresent, &pAcl, &bDefaulted))
+        return FALSE;
+
+    if(bAclPresent) {
+        if(!IsValidAcl(pAcl)) return FALSE;
+    }
+
+    /* verify owner integrity */
+
+    if(!GetSecurityDescriptorOwner(sd, &pSid, &bDefaulted))
+        return FALSE;
+
+    if(pSid != NULL) {
+        if(!IsValidSid(pSid)) return FALSE;
+    }
+
+    /* verify group integrity */
+
+    if(!GetSecurityDescriptorGroup(sd, &pSid, &bDefaulted))
+        return FALSE;
+
+    if(pSid != NULL) {
+        if(!IsValidSid(pSid)) return FALSE;
+    }
+
+    return TRUE;
+}
+
+static VOID GetRemotePrivilegesSet(char *FileName, PDWORD dwRemotePrivileges)
+{
+    HANDLE hFile;
+
+    *dwRemotePrivileges = 0;
+
+    /* see if we have the SeRestorePrivilege */
+
+    hFile = CreateFileA(
+        FileName,
+        ACCESS_SYSTEM_SECURITY | WRITE_DAC | WRITE_OWNER | READ_CONTROL,
+        FILE_SHARE_READ | FILE_SHARE_DELETE, /* no sd updating allowed here */
+        NULL,
+        OPEN_EXISTING,
+        FILE_FLAG_BACKUP_SEMANTICS,
+        NULL
+        );
+
+    if(hFile != INVALID_HANDLE_VALUE) {
+        /* no remote way to determine SeRestorePrivilege -- just try a
+           read/write to simulate it */
+        SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION |
+          SACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION |
+          GROUP_SECURITY_INFORMATION;
+        PSECURITY_DESCRIPTOR sd;
+        DWORD cbBuf = 0;
+
+        GetKernelObjectSecurity(hFile, si, NULL, cbBuf, &cbBuf);
+
+        if(ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
+            if((sd = HeapAlloc(GetProcessHeap(), 0, cbBuf)) != NULL) {
+                if(GetKernelObjectSecurity(hFile, si, sd, cbBuf, &cbBuf)) {
+                    if(SetKernelObjectSecurity(hFile, si, sd))
+                        *dwRemotePrivileges |= OVERRIDE_RESTORE;
+                }
+                HeapFree(GetProcessHeap(), 0, sd);
+            }
+        }
+
+        CloseHandle(hFile);
+    } else {
+
+        /* see if we have the SeSecurityPrivilege */
+        /* note we don't need this if we have SeRestorePrivilege */
+
+        hFile = CreateFileA(
+            FileName,
+            ACCESS_SYSTEM_SECURITY,
+            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, /* max */
+            NULL,
+            OPEN_EXISTING,
+            0,
+            NULL
+            );
+
+        if(hFile != INVALID_HANDLE_VALUE) {
+            CloseHandle(hFile);
+            *dwRemotePrivileges |= OVERRIDE_SACL;
+        }
+    }
+}
+
+
+BOOL GetVolumeCaps(
+    char *rootpath,         /* filepath, or NULL */
+    char *name,             /* filename associated with rootpath */
+    PVOLUMECAPS VolumeCaps  /* result structure describing capabilities */
+    )
+{
+    char TempRootPath[MAX_PATH + 1];
+    DWORD cchTempRootPath = 0;
+    BOOL bSuccess = TRUE;   /* assume success until told otherwise */
+
+    if(!bInitialized) if(!Initialize()) return FALSE;
+
+    /* process the input path to produce a consistent path suitable for
+       compare operations and also suitable for certain picky Win32 API
+       that don't like forward slashes */
+
+    if(rootpath != NULL && rootpath[0] != '\0') {
+        DWORD i;
+
+        cchTempRootPath = lstrlen(rootpath);
+        if(cchTempRootPath > MAX_PATH) return FALSE;
+
+        /* copy input, converting forward slashes to back slashes as we go */
+
+        for(i = 0 ; i <= cchTempRootPath ; i++) {
+            if(rootpath[i] == '/') TempRootPath[i] = '\\';
+            else TempRootPath[i] = rootpath[i];
+        }
+
+        /* check for UNC and Null terminate or append trailing \ as
+           appropriate */
+
+        /* possible valid UNCs we are passed follow:
+           \\machine\foo\bar (path is \\machine\foo\)
+           \\machine\foo     (path is \\machine\foo\)
+           \\machine\foo\
+           \\.\c$\     (FIXFIX: Win32API doesn't like this - GetComputerName())
+           LATERLATER: handling mounted DFS drives in the future will require
+                       slightly different logic which isn't available today.
+                       This is required because directories can point at
+                       different servers which have differing capabilities.
+         */
+
+        if(TempRootPath[0] == '\\' && TempRootPath[1] == '\\') {
+            DWORD slash = 0;
+
+            for(i = 2 ; i < cchTempRootPath ; i++) {
+                if(TempRootPath[i] == '\\') {
+                    slash++;
+
+                    if(slash == 2) {
+                        i++;
+                        TempRootPath[i] = '\0';
+                        cchTempRootPath = i;
+                        break;
+                    }
+                }
+            }
+
+            /* if there was only one slash found, just tack another onto the
+               end */
+
+            if(slash == 1 && TempRootPath[cchTempRootPath] != '\\') {
+                TempRootPath[cchTempRootPath] = TempRootPath[0]; /* '\' */
+                TempRootPath[cchTempRootPath+1] = '\0';
+                cchTempRootPath++;
+            }
+
+        } else {
+
+            if(TempRootPath[1] == ':') {
+
+                /* drive letter specified, truncate to root */
+                TempRootPath[2] = '\\';
+                TempRootPath[3] = '\0';
+                cchTempRootPath = 3;
+            } else {
+
+                /* must be file on current drive */
+                TempRootPath[0] = '\0';
+                cchTempRootPath = 0;
+            }
+
+        }
+
+    } /* if path != NULL */
+
+    /* grab lock protecting cached entry */
+    EnterCriticalSection( &VolumeCapsLock );
+
+    if(!g_VolumeCaps.bValid ||
+       lstrcmpi(g_VolumeCaps.RootPath, TempRootPath) != 0)
+    {
+
+        /* no match found, build up new entry */
+
+        DWORD dwFileSystemFlags;
+        DWORD dwRemotePrivileges = 0;
+        BOOL bRemote = FALSE;
+
+        /* release lock during expensive operations */
+        LeaveCriticalSection( &VolumeCapsLock );
+
+        bSuccess = GetVolumeInformation(
+            (TempRootPath[0] == '\0') ? NULL : TempRootPath,
+            NULL, 0,
+            NULL, NULL,
+            &dwFileSystemFlags,
+            NULL, 0);
+
+
+        /* only if target volume supports Acls, and we were told to use
+           privileges do we need to go out and test for the remote case */
+
+        if(bSuccess && (dwFileSystemFlags & FS_PERSISTENT_ACLS) &&
+           VolumeCaps->bUsePrivileges)
+        {
+            if(GetDriveType( (TempRootPath[0] == '\0') ? NULL : TempRootPath )
+               == DRIVE_REMOTE)
+            {
+                bRemote = TRUE;
+
+                /* make a determination about our remote capabilities */
+
+                GetRemotePrivilegesSet(name, &dwRemotePrivileges);
+            }
+        }
+
+        /* always take the lock again, since we release it below */
+        EnterCriticalSection( &VolumeCapsLock );
+
+        /* replace the existing data if successful */
+        if(bSuccess) {
+
+            lstrcpynA(g_VolumeCaps.RootPath, TempRootPath, cchTempRootPath+1);
+            g_VolumeCaps.bProcessDefer = FALSE;
+            g_VolumeCaps.dwFileSystemFlags = dwFileSystemFlags;
+            g_VolumeCaps.bRemote = bRemote;
+            g_VolumeCaps.dwRemotePrivileges = dwRemotePrivileges;
+            g_VolumeCaps.bValid = TRUE;
+        }
+    }
+
+    if(bSuccess) {
+        /* copy input elements */
+        g_VolumeCaps.bUsePrivileges = VolumeCaps->bUsePrivileges;
+        g_VolumeCaps.dwFileAttributes = VolumeCaps->dwFileAttributes;
+
+        /* give caller results */
+        memcpy(VolumeCaps, &g_VolumeCaps, sizeof(VOLUMECAPS));
+    } else {
+        g_VolumeCaps.bValid = FALSE;
+    }
+
+    LeaveCriticalSection( &VolumeCapsLock ); /* release lock */
+
+    return bSuccess;
+}
+
+
+BOOL SecuritySet(char *resource, PVOLUMECAPS VolumeCaps, uch *securitydata)
+{
+    HANDLE hFile;
+    DWORD dwDesiredAccess = 0;
+    DWORD dwFlags = 0;
+    PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)securitydata;
+    SECURITY_DESCRIPTOR_CONTROL sdc;
+    SECURITY_INFORMATION RequestedInfo = 0;
+    DWORD dwRev;
+    BOOL bRestorePrivilege = FALSE;
+    BOOL bSaclPrivilege = FALSE;
+    BOOL bSuccess;
+
+    if(!bInitialized) if(!Initialize()) return FALSE;
+
+    /* defer directory processing */
+
+    if(VolumeCaps->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+        if(!VolumeCaps->bProcessDefer) {
+            return DeferSet(resource, VolumeCaps, securitydata);
+        } else {
+            /* opening a directory requires FILE_FLAG_BACKUP_SEMANTICS */
+            dwFlags |= FILE_FLAG_BACKUP_SEMANTICS;
+        }
+    }
+
+    /* evaluate the input security desriptor and act accordingly */
+
+    if(!IsValidSecurityDescriptor(sd))
+        return FALSE;
+
+    if(!GetSecurityDescriptorControl(sd, &sdc, &dwRev))
+        return FALSE;
+
+    /* setup privilege usage based on if told we can use privileges, and if so,
+       what privileges we have */
+
+    if(VolumeCaps->bUsePrivileges) {
+        if(VolumeCaps->bRemote) {
+            /* use remotely determined privileges */
+            if(VolumeCaps->dwRemotePrivileges & OVERRIDE_RESTORE)
+                bRestorePrivilege = TRUE;
+
+            if(VolumeCaps->dwRemotePrivileges & OVERRIDE_SACL)
+                bSaclPrivilege = TRUE;
+
+        } else {
+            /* use local privileges */
+            bRestorePrivilege = g_bRestorePrivilege;
+            bSaclPrivilege = g_bSaclPrivilege;
+        }
+    }
+
+
+    /* if a Dacl is present write Dacl out */
+    /* if we have SeRestorePrivilege, write owner and group info out */
+
+    if(sdc & SE_DACL_PRESENT) {
+        dwDesiredAccess |= WRITE_DAC;
+        RequestedInfo |= DACL_SECURITY_INFORMATION;
+
+        if(bRestorePrivilege) {
+            dwDesiredAccess |= WRITE_OWNER;
+            RequestedInfo |= (OWNER_SECURITY_INFORMATION |
+              GROUP_SECURITY_INFORMATION);
+        }
+    }
+
+    /* if a Sacl is present and we have either SeRestorePrivilege or
+       SeSystemSecurityPrivilege try to write Sacl out */
+
+    if((sdc & SE_SACL_PRESENT) && (bRestorePrivilege || bSaclPrivilege)) {
+        dwDesiredAccess |= ACCESS_SYSTEM_SECURITY;
+        RequestedInfo |= SACL_SECURITY_INFORMATION;
+    }
+
+    if(RequestedInfo == 0)  /* nothing to do */
+        return FALSE;
+
+    if(bRestorePrivilege)
+        dwFlags |= FILE_FLAG_BACKUP_SEMANTICS;
+
+    hFile = CreateFileA(
+        resource,
+        dwDesiredAccess,
+        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,/* max sharing */
+        NULL,
+        OPEN_EXISTING,
+        dwFlags,
+        NULL
+        );
+
+    if(hFile == INVALID_HANDLE_VALUE)
+        return FALSE;
+
+    bSuccess = SetKernelObjectSecurity(hFile, RequestedInfo, sd);
+
+    CloseHandle(hFile);
+
+    return bSuccess;
+}
+
+static VOID InitLocalPrivileges(VOID)
+{
+    HANDLE hToken;
+    TOKEN_PRIVILEGES tp;
+
+    /* try to enable some interesting privileges that give us the ability
+       to get some security information that we normally cannot.
+
+       note that enabling privileges is only relevant on the local machine;
+       when accessing files that are on a remote machine, any privileges
+       that are present on the remote machine get enabled by default. */
+
+    if(!OpenProcessToken(GetCurrentProcess(),
+        TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
+        return;
+
+    tp.PrivilegeCount = 1;
+    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+    if(LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tp.Privileges[0].Luid)) {
+
+        /* try to enable SeRestorePrivilege; if this succeeds, we can write
+           all aspects of the security descriptor */
+
+        if(AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) &&
+           GetLastError() == ERROR_SUCCESS) g_bRestorePrivilege = TRUE;
+
+    }
+
+    /* try to enable SeSystemSecurityPrivilege, if SeRestorePrivilege not
+       present; if this succeeds, we can write the Sacl */
+
+    if(!g_bRestorePrivilege &&
+        LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tp.Privileges[0].Luid)) {
+
+        if(AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) &&
+           GetLastError() == ERROR_SUCCESS) g_bSaclPrivilege = TRUE;
+    }
+
+    CloseHandle(hToken);
+}
+#endif /* NTSD_EAS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/os2.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,2187 @@
+/*---------------------------------------------------------------------------
+
+  os2.c
+
+  OS/2-specific routines for use with Info-ZIP's UnZip 5.1 and later.
+
+  This file contains the OS/2 versions of the file name/attribute/time/etc
+  code.  Most or all of the routines which make direct use of OS/2 system
+  calls (i.e., the non-lowercase routines) are Kai Uwe Rommel's.  The read-
+  dir() suite was written by Michael Rendell and ported to OS/2 by Kai Uwe;
+  it is in the public domain.
+
+  Contains:  GetCountryInfo()
+             GetFileTime()
+             SetFileTime()              (TIMESTAMP only)
+             stamp_file()               (TIMESTAMP only)
+             Utime2DosDateTime()
+             SetPathAttrTimes()
+             SetEAs()
+             GetLoadPath()
+             opendir()
+             closedir()
+             readdir()
+             [ seekdir() ]             not used
+             [ telldir() ]             not used
+             free_dircontents()
+             getdirent()
+             IsFileSystemFAT()
+             do_wild()
+             mapattr()
+             mapname()
+             checkdir()
+             isfloppy()
+             IsFileNameValid()
+             map2fat()
+             SetLongNameEA()
+             close_outfile()
+             check_for_newer()
+             dateformat()
+             version()
+             InitNLS()
+             IsUpperNLS()
+             ToLowerNLS()
+             StringLower()
+             DebugMalloc()
+
+  ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#include "os2acl.h"
+
+extern ZCONST char Far TruncEAs[];
+
+/* local prototypes */
+
+#ifdef TIMESTAMP
+  static int SetFileTime(ZCONST char *name, ulg stamp);
+#endif
+#if defined(USE_EF_UT_TIME) || defined(TIMESTAMP)
+  static ulg Utime2DosDateTime  OF((time_t uxtime));
+#endif
+static int   getOS2filetimes    OF((__GPRO__
+                                    ulg *pM_dt, ulg *pA_dt, ulg *pC_dt));
+static void  SetPathAttrTimes   OF((__GPRO__ int flags, int dir));
+static int   SetEAs             OF((__GPRO__ const char *path,
+                                    void *ef_block));
+static int   SetACL             OF((__GPRO__ const char *path,
+                                    void *ef_block));
+static int   EvalExtraFields    OF((__GPRO__ const char *path,
+                                    void *extra_field, unsigned ef_len));
+static int   isfloppy           OF((int nDrive));
+static int   IsFileNameValid    OF((const char *name));
+static void  map2fat            OF((char *pathcomp, char **pEndFAT));
+static int   SetLongNameEA      OF((char *name, char *longname));
+static void  InitNLS            OF((void));
+
+
+/*****************************/
+/*  Strings used in os2.c  */
+/*****************************/
+
+#ifndef SFX
+  static char Far CantAllocateWildcard[] =
+    "warning:  cannot allocate wildcard buffers\n";
+#endif
+static char Far Creating[] = "   creating: %-22s ";
+static char Far ConversionFailed[] = "mapname:  conversion of %s failed\n";
+static char Far Labelling[] = "labelling %c: %-22s\n";
+static char Far ErrSetVolLabel[] = "mapname:  error setting volume label\n";
+static char Far PathTooLong[] = "checkdir error:  path too long: %s\n";
+static char Far CantCreateDir[] = "checkdir error:  cannot create %s\n\
+                 unable to process %s.\n";
+static char Far DirIsntDirectory[] =
+  "checkdir error:  %s exists but is not directory\n\
+                 unable to process %s.\n";
+static char Far PathTooLongTrunc[] =
+  "checkdir warning:  path too long; truncating\n                   %s\n\
+                -> %s\n";
+#if (!defined(SFX) || defined(SFX_EXDIR))
+   static char Far CantCreateExtractDir[] =
+     "checkdir:  cannot create extraction directory: %s\n";
+#endif
+
+#ifndef __EMX__
+#  if (_MSC_VER >= 600) || defined(__IBMC__)
+#    include <direct.h>          /* have special MSC/IBM C mkdir prototype */
+#  else                          /* own prototype because dir.h conflicts? */
+     int mkdir(const char *path);
+#  endif
+#  define MKDIR(path,mode)   mkdir(path)
+#else
+#  define MKDIR(path,mode)   mkdir(path,mode)
+#endif
+
+
+#ifdef __32BIT__
+
+USHORT DosDevIOCtl32(PVOID pData, USHORT cbData, PVOID pParms, USHORT cbParms,
+                     USHORT usFunction, USHORT usCategory, HFILE hDevice)
+{
+  ULONG ulParmLengthInOut = cbParms, ulDataLengthInOut = cbData;
+  return (USHORT) DosDevIOCtl(hDevice, usCategory, usFunction,
+                              pParms, cbParms, &ulParmLengthInOut,
+                              pData, cbData, &ulDataLengthInOut);
+}
+
+#  define DosDevIOCtl DosDevIOCtl32
+#else
+#  define DosDevIOCtl DosDevIOCtl2
+#endif
+
+
+typedef struct
+{
+  ush nID;
+  ush nSize;
+  ulg lSize;
+}
+EFHEADER, *PEFHEADER;
+
+
+#ifdef __32BIT__
+
+#define DosFindFirst(p1, p2, p3, p4, p5, p6) \
+        DosFindFirst(p1, p2, p3, p4, p5, p6, 1)
+
+#else
+
+typedef struct
+{
+  ULONG oNextEntryOffset;
+  BYTE fEA;
+  BYTE cbName;
+  USHORT cbValue;
+  CHAR szName[1];
+}
+FEA2, *PFEA2;
+
+typedef struct
+{
+  ULONG cbList;
+  FEA2 list[1];
+}
+FEA2LIST, *PFEA2LIST;
+
+#define DosQueryCurrentDisk DosQCurDisk
+#define DosQueryFSAttach(p1, p2, p3, p4, p5) \
+        DosQFSAttach(p1, p2, p3, p4, p5, 0)
+#define DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7) \
+        DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7, 0)
+#define DosFindFirst(p1, p2, p3, p4, p5, p6) \
+        DosFindFirst(p1, p2, p3, p4, p5, p6, 0)
+#define DosMapCase DosCaseMap
+#define DosSetPathInfo(p1, p2, p3, p4, p5) \
+        DosSetPathInfo(p1, p2, p3, p4, p5, 0)
+#define DosQueryPathInfo(p1, p2, p3, p4) \
+        DosQPathInfo(p1, p2, p3, p4, 0)
+#define DosQueryFileInfo DosQFileInfo
+#define DosMapCase DosCaseMap
+#define DosQueryCtryInfo DosGetCtryInfo
+
+#endif /* !__32BIT__ */
+
+
+
+
+
+/*
+ * @(#) dir.h 1.4 87/11/06   Public Domain.
+ */
+
+#define A_RONLY    0x01
+#define A_HIDDEN   0x02
+#define A_SYSTEM   0x04
+#define A_LABEL    0x08
+#define A_DIR      0x10
+#define A_ARCHIVE  0x20
+
+
+const int attributes = A_DIR | A_HIDDEN | A_SYSTEM;
+
+
+extern DIR *opendir(__GPRO__ ZCONST char *);
+extern struct direct *readdir(__GPRO__ DIR *);
+extern void seekdir(DIR *, long);
+extern long telldir(DIR *);
+extern void closedir(DIR *);
+#define rewinddir(dirp) seekdir(dirp, 0L)
+
+int IsFileSystemFAT(__GPRO__ ZCONST char *dir);
+char *StringLower(char *szArg);
+
+
+
+
+/*
+ * @(#)dir.c 1.4 87/11/06 Public Domain.
+ */
+
+
+#ifndef S_IFMT
+#  define S_IFMT 0xF000
+#endif
+
+
+#ifndef SFX
+   static char *getdirent(__GPRO__ ZCONST char *);
+   static void free_dircontents(struct _dircontents *);
+#endif /* !SFX */
+
+
+
+
+int GetCountryInfo(void)
+{
+    COUNTRYINFO ctryi;
+    COUNTRYCODE ctryc;
+#ifdef __32BIT__
+    ULONG cbInfo;
+#else
+    USHORT cbInfo;
+#endif
+
+  ctryc.country = ctryc.codepage = 0;
+
+  if ( DosQueryCtryInfo(sizeof(ctryi), &ctryc, &ctryi, &cbInfo) != NO_ERROR )
+    return 0;
+
+  return ctryi.fsDateFmt;
+}
+
+
+long GetFileTime(ZCONST char *name)
+{
+#ifdef __32BIT__
+  FILESTATUS3 fs;
+#else
+  FILESTATUS fs;
+#endif
+  USHORT nDate, nTime;
+
+  if ( DosQueryPathInfo((PSZ) name, 1, (PBYTE) &fs, sizeof(fs)) )
+    return -1;
+
+  nDate = * (USHORT *) &fs.fdateLastWrite;
+  nTime = * (USHORT *) &fs.ftimeLastWrite;
+
+  return ((ULONG) nDate) << 16 | nTime;
+}
+
+
+#ifdef TIMESTAMP
+
+static int SetFileTime(ZCONST char *name, ulg stamp)   /* swiped from Zip */
+{
+  FILESTATUS fs;
+  USHORT fd, ft;
+
+  if (DosQueryPathInfo((PSZ) name, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)))
+    return -1;
+
+  fd = (USHORT) (stamp >> 16);
+  ft = (USHORT) stamp;
+  fs.fdateLastWrite = fs.fdateCreation = * (FDATE *) &fd;
+  fs.ftimeLastWrite = fs.ftimeCreation = * (FTIME *) &ft;
+
+  if (DosSetPathInfo((PSZ) name, FIL_STANDARD, (PBYTE) &fs, sizeof(fs), 0))
+    return -1;
+
+  return 0;
+}
+
+
+int stamp_file(ZCONST char *fname, time_t modtime)
+{
+    return SetFileTime(fname, Utime2DosDateTime(modtime));
+}
+
+#endif /* TIMESTAMP */
+
+
+/* The following DOS date/time structures are machine-dependent as they
+ * assume "little-endian" byte order.  For OS/2-specific code, which
+ * is run on x86 CPUs (or emulators?), this assumption is valid; but
+ * care should be taken when using this code as template for other ports.
+ */
+typedef union {
+  ULONG timevalue;          /* combined value, useful for comparisons */
+  struct {
+    FTIME ft;               /* system file time record:
+                             *    USHORT twosecs : 5
+                             *    USHORT minutes : 6;
+                             *    USHORT hours   : 5;   */
+    FDATE fd;               /* system file date record:
+                             *    USHORT day     : 5
+                             *    USHORT month   : 4;
+                             *    USHORT year    : 7;   */
+  } _fdt;
+} F_DATE_TIME, *PF_DATE_TIME;
+
+
+#if defined(USE_EF_UT_TIME) || defined(TIMESTAMP)
+
+static ulg Utime2DosDateTime(uxtime)
+    time_t uxtime;
+{
+    F_DATE_TIME dosfiletime;
+    struct tm *t;
+
+    /* round up to even seconds */
+    /* round up (down if "up" overflows) to even seconds */
+    if (((ulg)uxtime) & 1)
+        uxtime = (uxtime + 1 > uxtime) ? uxtime + 1 : uxtime - 1;
+
+    t = localtime(&(uxtime));
+    if (t == (struct tm *)NULL) {
+        /* time conversion error; use current time instead, hoping
+           that localtime() does not reject it as well! */
+        time_t now = time(NULL);
+        t = localtime(&now);
+    }
+    if (t->tm_year < 80) {
+        dosfiletime._fdt.ft.twosecs = 0;
+        dosfiletime._fdt.ft.minutes = 0;
+        dosfiletime._fdt.ft.hours   = 0;
+        dosfiletime._fdt.fd.day     = 1;
+        dosfiletime._fdt.fd.month   = 1;
+        dosfiletime._fdt.fd.year    = 0;
+    } else {
+        dosfiletime._fdt.ft.twosecs = t->tm_sec >> 1;
+        dosfiletime._fdt.ft.minutes = t->tm_min;
+        dosfiletime._fdt.ft.hours   = t->tm_hour;
+        dosfiletime._fdt.fd.day     = t->tm_mday;
+        dosfiletime._fdt.fd.month   = t->tm_mon + 1;
+        dosfiletime._fdt.fd.year    = t->tm_year - 80;
+    }
+    return dosfiletime.timevalue;
+
+} /* end function Utime2DosDateTime() */
+
+#endif /* USE_EF_UT_TIME || TIMESTAMP */
+
+
+static int getOS2filetimes(__GPRO__ ulg *pM_dt, ulg *pA_dt, ulg *pC_dt)
+{
+#ifdef USE_EF_UT_TIME
+    unsigned eb_izux_flg;
+    iztimes z_utime;
+#endif
+
+    /* Copy and/or convert time and date variables, if necessary;   */
+    /* return a flag indicating which time stamps are available.    */
+#ifdef USE_EF_UT_TIME
+    if (G.extra_field &&
+#ifdef IZ_CHECK_TZ
+        G.tz_is_valid &&
+#endif
+        ((eb_izux_flg = ef_scan_for_izux(G.extra_field,
+          G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime,
+          &z_utime, NULL)) & EB_UT_FL_MTIME))
+    {
+        TTrace((stderr, "getOS2filetimes: UT e.f. modif. time = %lu\n",
+                z_utime.mtime));
+        *pM_dt = Utime2DosDateTime(z_utime.mtime);
+        if (eb_izux_flg & EB_UT_FL_ATIME) {
+            TTrace((stderr, "getOS2filetimes: UT e.f. access time = %lu\n",
+                    z_utime.atime));
+            *pA_dt = Utime2DosDateTime(z_utime.atime);
+        }
+        if (eb_izux_flg & EB_UT_FL_CTIME) {
+            TTrace((stderr, "getOS2filetimes: UT e.f. creation time = %lu\n",
+                    z_utime.ctime));
+            *pC_dt = Utime2DosDateTime(z_utime.ctime);
+        } else {
+            /* no creation time value supplied, set it to modification time */
+            *pC_dt = *pM_dt;
+            eb_izux_flg |= EB_UT_FL_CTIME;
+        }
+        return (int)eb_izux_flg;
+    }
+#endif /* USE_EF_UT_TIME */
+    *pC_dt = *pM_dt = G.lrec.last_mod_dos_datetime;
+    TTrace((stderr, "\ngetOS2filetimes: DOS dir modific./creation time = %lu\n",
+            *pM_dt));
+    return (EB_UT_FL_MTIME | EB_UT_FL_CTIME);
+}
+
+
+static void SetPathAttrTimes(__GPRO__ int flags, int dir)
+{
+  HFILE hFile;
+#ifdef __32BIT__
+  ULONG nAction;
+#else
+  USHORT nAction;
+#endif
+  FILESTATUS fs;
+  USHORT nLength;
+  char szName[CCHMAXPATH];
+  ulg Mod_dt, Acc_dt, Cre_dt;
+  int gotTimes;
+
+  strcpy(szName, G.filename);
+  nLength = strlen(szName);
+  if (szName[nLength - 1] == '/')
+    szName[nLength - 1] = 0;
+
+  if (dir)
+  {
+    if ( DosQueryPathInfo(szName, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)) )
+      return;
+  }
+  else
+  {
+    /* for regular files, open them and operate on the file handle, to
+       work around certain network operating system bugs ... */
+
+    if ( DosOpen(szName, &hFile, &nAction, 0, 0,
+                 OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW,
+                 OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE, 0) )
+      return;
+
+    if ( DosQueryFileInfo(hFile, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)) )
+      return;
+  }
+
+  /* set date/time stamps */
+  gotTimes = getOS2filetimes(__G__ &Mod_dt, &Acc_dt, &Cre_dt);
+  if (gotTimes & EB_UT_FL_MTIME) {
+    fs.fdateLastWrite = ((F_DATE_TIME *)&Mod_dt)->_fdt.fd;
+    fs.ftimeLastWrite = ((F_DATE_TIME *)&Mod_dt)->_fdt.ft;
+  }
+  if (gotTimes & EB_UT_FL_ATIME) {
+    fs.fdateLastAccess = ((F_DATE_TIME *)&Acc_dt)->_fdt.fd;
+    fs.ftimeLastAccess = ((F_DATE_TIME *)&Acc_dt)->_fdt.ft;
+  }
+  if (gotTimes & EB_UT_FL_CTIME) {
+    fs.fdateCreation = ((F_DATE_TIME *)&Cre_dt)->_fdt.fd;
+    fs.ftimeCreation = ((F_DATE_TIME *)&Cre_dt)->_fdt.ft;
+  }
+
+  if ( flags != -1 )
+    fs.attrFile = flags; /* hidden, system, archive, read-only */
+
+  if (dir)
+  {
+    DosSetPathInfo(szName, FIL_STANDARD, (PBYTE) &fs, sizeof(fs), 0);
+  }
+  else
+  {
+    DosSetFileInfo(hFile, FIL_STANDARD, (PBYTE) &fs, sizeof(fs));
+    DosClose(hFile);
+  }
+}
+
+
+typedef struct
+{
+  ULONG cbList;               /* length of value + 22 */
+#ifdef __32BIT__
+  ULONG oNext;
+#endif
+  BYTE fEA;                   /* 0 */
+  BYTE cbName;                /* length of ".LONGNAME" = 9 */
+  USHORT cbValue;             /* length of value + 4 */
+  BYTE szName[10];            /* ".LONGNAME" */
+  USHORT eaType;              /* 0xFFFD for length-preceded ASCII */
+  USHORT eaSize;              /* length of value */
+  BYTE szValue[CCHMAXPATH];
+}
+FEALST;
+
+
+static int SetEAs(__GPRO__ const char *path, void *ef_block)
+{                                               /* returns almost-PK errors */
+  EFHEADER *pEAblock = (PEFHEADER) ef_block;
+#ifdef __32BIT__
+  EAOP2 eaop;
+  PFEA2LIST pFEA2list;
+#else
+  EAOP eaop;
+  PFEALIST pFEAlist;
+  PFEA pFEA;
+  PFEA2LIST pFEA2list;
+  PFEA2 pFEA2;
+  ULONG nLength2;
+#endif
+  USHORT nLength;
+  char szName[CCHMAXPATH];
+  int error;
+
+  if ( ef_block == NULL || pEAblock -> nID != EF_OS2 )
+    return PK_OK;  /* not an OS/2 extra field:  assume OK */
+
+  if ( pEAblock->nSize < 4 || (pEAblock->lSize > 0L && pEAblock->nSize <= 10) )
+    return IZ_EF_TRUNC;  /* no compressed data! */
+
+  strcpy(szName, path);
+  nLength = strlen(szName);
+  if (szName[nLength - 1] == '/')
+    szName[nLength - 1] = 0;
+
+  if ( (pFEA2list = (PFEA2LIST) malloc((size_t) pEAblock -> lSize)) == NULL )
+    return PK_MEM4;
+
+  if ( (error = memextract(__G__ (uch *)pFEA2list, pEAblock->lSize,
+       (uch *)(pEAblock+1), (ulg)(pEAblock->nSize - 4))) != PK_OK )
+  {
+    free(pFEA2list);
+    return error;
+  }
+
+#ifdef __32BIT__
+  eaop.fpGEA2List = NULL;
+  eaop.fpFEA2List = pFEA2list;
+#else
+  pFEAlist  = (PVOID) pFEA2list;
+  pFEA2 = pFEA2list -> list;
+  pFEA  = pFEAlist  -> list;
+
+  do
+  {
+    nLength2 = pFEA2 -> oNextEntryOffset;
+    nLength = sizeof(FEA) + pFEA2 -> cbName + 1 + pFEA2 -> cbValue;
+
+    memcpy(pFEA, (PCH) pFEA2 + sizeof(pFEA2 -> oNextEntryOffset), nLength);
+
+    pFEA2 = (PFEA2) ((PCH) pFEA2 + nLength2);
+    pFEA = (PFEA) ((PCH) pFEA + nLength);
+  }
+  while ( nLength2 != 0 );
+
+  pFEAlist -> cbList = (PCH) pFEA - (PCH) pFEAlist;
+
+  eaop.fpGEAList = NULL;
+  eaop.fpFEAList = pFEAlist;
+#endif
+
+  eaop.oError = 0;
+  DosSetPathInfo(szName, FIL_QUERYEASIZE, (PBYTE) &eaop, sizeof(eaop), 0);
+
+  if (!uO.tflag && QCOND2)
+    Info(slide, 0, ((char *)slide, " (%ld bytes EAs)", pFEA2list -> cbList));
+
+  free(pFEA2list);
+  return PK_COOL;
+}
+
+
+static int SetACL(__GPRO__ const char *path, void *ef_block)
+{                                               /* returns almost-PK errors */
+  EFHEADER *pACLblock = (PEFHEADER) ef_block;
+  char *szACL;
+  int error;
+
+  if ( ef_block == NULL || pACLblock -> nID != EF_ACL )
+    return PK_OK;  /* not an OS/2 extra field:  assume OK */
+
+  if (pACLblock->nSize < 4 || (pACLblock->lSize > 0L && pACLblock->nSize <= 10))
+    return IZ_EF_TRUNC;  /* no compressed data! */
+
+  if ( (szACL = malloc((size_t) pACLblock -> lSize)) == NULL )
+    return PK_MEM4;
+
+  if ( (error = memextract(__G__ (uch *)szACL, pACLblock->lSize,
+       (uch *)(pACLblock+1), (ulg)(pACLblock->nSize - 4))) != PK_OK )
+  {
+    free(szACL);
+    return error;
+  }
+
+  if (acl_set(NULL, path, szACL) == 0)
+    if (!uO.tflag && QCOND2)
+      Info(slide, 0, ((char *)slide, " (%ld bytes ACL)", strlen(szACL)));
+
+  free(szACL);
+  return PK_COOL;
+}
+
+
+#ifdef SFX
+
+char *GetLoadPath(__GPRO)
+{
+#ifdef __32BIT__ /* generic for 32-bit API */
+  PTIB pptib;
+  PPIB pppib;
+  char *szPath;
+
+  DosGetInfoBlocks(&pptib, &pppib);
+  szPath = pppib -> pib_pchenv;
+#else /* 16-bit, note: requires large data model */
+  SEL selEnv;
+  USHORT offCmd;
+  char *szPath;
+
+  DosGetEnv(&selEnv, &offCmd);
+  szPath = MAKEP(selEnv, 0);
+#endif
+
+  while (*szPath) /* find end of process environment */
+    szPath = strchr(szPath, 0) + 1;
+
+  return szPath + 1; /* .exe file name follows environment */
+
+} /* end function GetLoadPath() */
+
+
+
+
+
+#else /* !SFX */
+
+DIR *opendir(__GPRO__ const char *name)
+{
+  struct stat statb;
+  DIR *dirp;
+  char c;
+  char *s;
+  struct _dircontents *dp;
+  char nbuf[MAXPATHLEN + 1];
+  int len;
+
+  strcpy(nbuf, name);
+  if ((len = strlen(nbuf)) == 0)
+    return NULL;
+
+  if ( ((c = nbuf[len - 1]) == '\\' || c == '/') && (len > 1) )
+  {
+    nbuf[len - 1] = 0;
+    --len;
+
+    if ( nbuf[len - 1] == ':' )
+    {
+      strcpy(nbuf+len, "\\.");
+      len += 2;
+    }
+  }
+  else
+    if ( nbuf[len - 1] == ':' )
+    {
+      strcpy(nbuf+len, ".");
+      ++len;
+    }
+
+  /* GRR:  Borland and Watcom C return non-zero on wildcards... < 0 ? */
+  if (stat(nbuf, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
+  {
+    Trace((stderr, "opendir:  stat(%s) returns negative or not directory\n",
+      nbuf));
+    return NULL;
+  }
+
+  if ( (dirp = malloc(sizeof(DIR))) == NULL )
+    return NULL;
+
+  if ( nbuf[len - 1] == '.' && (len == 1 || nbuf[len - 2] != '.') )
+    strcpy(nbuf+len-1, "*");
+  else
+    if ( ((c = nbuf[len - 1]) == '\\' || c == '/') && (len == 1) )
+      strcpy(nbuf+len, "*");
+    else
+      strcpy(nbuf+len, "\\*");
+
+  /* len is no longer correct (but no longer needed) */
+  Trace((stderr, "opendir:  nbuf = [%s]\n", nbuf));
+
+  dirp -> dd_loc = 0;
+  dirp -> dd_contents = dirp -> dd_cp = NULL;
+
+  if ((s = getdirent(__G__ nbuf)) == NULL)
+    return dirp;
+
+  do
+  {
+    if (((dp = malloc(sizeof(struct _dircontents))) == NULL) ||
+        ((dp -> _d_entry = malloc(strlen(s) + 1)) == NULL)      )
+    {
+      if (dp)
+        free(dp);
+      free_dircontents(dirp -> dd_contents);
+
+      return NULL;
+    }
+
+    if (dirp -> dd_contents)
+    {
+      dirp -> dd_cp -> _d_next = dp;
+      dirp -> dd_cp = dirp -> dd_cp -> _d_next;
+    }
+    else
+      dirp -> dd_contents = dirp -> dd_cp = dp;
+
+    strcpy(dp -> _d_entry, s);
+    dp -> _d_next = NULL;
+
+    dp -> _d_size = G.os2.find.cbFile;
+    dp -> _d_mode = G.os2.find.attrFile;
+    dp -> _d_time = *(unsigned *) &(G.os2.find.ftimeLastWrite);
+    dp -> _d_date = *(unsigned *) &(G.os2.find.fdateLastWrite);
+  }
+  while ((s = getdirent(__G__ NULL)) != NULL);
+
+  dirp -> dd_cp = dirp -> dd_contents;
+
+  return dirp;
+}
+
+
+void closedir(DIR * dirp)
+{
+  free_dircontents(dirp -> dd_contents);
+  free(dirp);
+}
+
+
+struct direct *readdir(__GPRO__ DIR * dirp)
+{
+  /* moved to os2data.h so it can be global */
+  /* static struct direct dp; */
+
+  if (dirp -> dd_cp == NULL)
+    return NULL;
+
+  G.os2.dp.d_namlen = G.os2.dp.d_reclen =
+    strlen(strcpy(G.os2.dp.d_name, dirp -> dd_cp -> _d_entry));
+
+  G.os2.dp.d_ino = 0;
+
+  G.os2.dp.d_size = dirp -> dd_cp -> _d_size;
+  G.os2.dp.d_mode = dirp -> dd_cp -> _d_mode;
+  G.os2.dp.d_time = dirp -> dd_cp -> _d_time;
+  G.os2.dp.d_date = dirp -> dd_cp -> _d_date;
+
+  dirp -> dd_cp = dirp -> dd_cp -> _d_next;
+  dirp -> dd_loc++;
+
+  return &G.os2.dp;
+}
+
+
+
+#if 0  /* not used in unzip; retained for possibly future use */
+
+void seekdir(DIR * dirp, long off)
+{
+  long i = off;
+  struct _dircontents *dp;
+
+  if (off >= 0)
+  {
+    for (dp = dirp -> dd_contents; --i >= 0 && dp; dp = dp -> _d_next);
+
+    dirp -> dd_loc = off - (i + 1);
+    dirp -> dd_cp = dp;
+  }
+}
+
+
+long telldir(DIR * dirp)
+{
+  return dirp -> dd_loc;
+}
+
+#endif /* 0 */
+
+
+
+static void free_dircontents(struct _dircontents * dp)
+{
+  struct _dircontents *odp;
+
+  while (dp)
+  {
+    if (dp -> _d_entry)
+      free(dp -> _d_entry);
+
+    dp = (odp = dp) -> _d_next;
+    free(odp);
+  }
+}
+
+
+static char *getdirent(__GPRO__ ZCONST char *dir)
+{
+  int done;
+  /* moved to os2data.h so it can be global */
+  /* static int lower; */
+
+  if (dir != NULL)
+  {                                    /* get first entry */
+    G.os2.hdir = HDIR_SYSTEM;
+    G.os2.count = 1;
+    done = DosFindFirst((PSZ) dir, &G.os2.hdir, attributes,
+                        &G.os2.find, sizeof(G.os2.find), &G.os2.count);
+    G.os2.lower = IsFileSystemFAT(__G__ dir);
+  }
+  else                                 /* get next entry */
+    done = DosFindNext(G.os2.hdir,
+                       &G.os2.find, sizeof(G.os2.find), &G.os2.count);
+
+  if (done == 0)
+  {
+    if ( G.os2.lower )
+      StringLower(G.os2.find.achName);
+    return G.os2.find.achName;
+  }
+  else
+  {
+    DosFindClose(G.os2.hdir);
+    return NULL;
+  }
+}
+
+
+
+int IsFileSystemFAT(__GPRO__ ZCONST char *dir)  /* FAT / HPFS detection */
+{
+  /* moved to os2data.h so they can be global */
+  /* static USHORT nLastDrive=(USHORT)(-1), nResult; */
+  ULONG lMap;
+  BYTE bData[64];
+  char bName[3];
+#ifdef __32BIT__
+  ULONG nDrive, cbData;
+  PFSQBUFFER2 pData = (PFSQBUFFER2) bData;
+#else
+  USHORT nDrive, cbData;
+  PFSQBUFFER pData = (PFSQBUFFER) bData;
+#endif
+
+    /* We separate FAT and HPFS+other file systems here.
+       at the moment I consider other systems to be similar to HPFS,
+       i.e. support long file names and case sensitive */
+
+    if ( isalpha(dir[0]) && (dir[1] == ':') )
+      nDrive = toupper(dir[0]) - '@';
+    else
+      DosQueryCurrentDisk(&nDrive, &lMap);
+
+    if ( nDrive == G.os2.nLastDrive )
+      return G.os2.nResult;
+
+    bName[0] = (char) (nDrive + '@');
+    bName[1] = ':';
+    bName[2] = 0;
+
+    G.os2.nLastDrive = nDrive;
+    cbData = sizeof(bData);
+
+    if ( !DosQueryFSAttach(bName, 0, FSAIL_QUERYNAME, (PVOID) pData, &cbData) )
+      G.os2.nResult = !strcmp((char *) (pData -> szFSDName) + pData -> cbName,
+                              "FAT");
+    else
+      G.os2.nResult = FALSE;
+
+    /* End of this ugly code */
+    return G.os2.nResult;
+} /* end function IsFileSystemFAT() */
+
+
+
+
+
+/************************/
+/*  Function do_wild()  */
+/************************/
+
+char *do_wild(__G__ wildspec)
+    __GDEF
+    char *wildspec;         /* only used first time on a given dir */
+{
+  /* moved to os2data.h so they can be global */
+#if 0
+  static DIR *dir = NULL;
+  static char *dirname, *wildname, matchname[FILNAMSIZ];
+  static int firstcall=TRUE, have_dirname, dirnamelen;
+#endif
+    char *fnamestart;
+    struct direct *file;
+
+
+    /* Even when we're just returning wildspec, we *always* do so in
+     * matchname[]--calling routine is allowed to append four characters
+     * to the returned string, and wildspec may be a pointer to argv[].
+     */
+    if (G.os2.firstcall) {        /* first call:  must initialize everything */
+        G.os2.firstcall = FALSE;
+
+        if (!iswild(wildspec)) {
+            strcpy(G.os2.matchname, wildspec);
+            G.os2.have_dirname = FALSE;
+            G.os2.dir = NULL;
+            return G.os2.matchname;
+        }
+
+        /* break the wildspec into a directory part and a wildcard filename */
+        if ((G.os2.wildname = strrchr(wildspec, '/')) == NULL &&
+            (G.os2.wildname = strrchr(wildspec, ':')) == NULL) {
+            G.os2.dirname = ".";
+            G.os2.dirnamelen = 1;
+            G.os2.have_dirname = FALSE;
+            G.os2.wildname = wildspec;
+        } else {
+            ++G.os2.wildname;     /* point at character after '/' or ':' */
+            G.os2.dirnamelen = G.os2.wildname - wildspec;
+            if ((G.os2.dirname = (char *)malloc(G.os2.dirnamelen+1)) == NULL) {
+                Info(slide, 1, ((char *)slide,
+                  LoadFarString(CantAllocateWildcard)));
+                strcpy(G.os2.matchname, wildspec);
+                return G.os2.matchname;   /* but maybe filespec was not a wildcard */
+            }
+            strncpy(G.os2.dirname, wildspec, G.os2.dirnamelen);
+            G.os2.dirname[G.os2.dirnamelen] = '\0';   /* terminate for strcpy below */
+            G.os2.have_dirname = TRUE;
+        }
+        Trace((stderr, "do_wild:  dirname = [%s]\n", G.os2.dirname));
+
+        if ((G.os2.dir = opendir(__G__ G.os2.dirname)) != NULL) {
+            if (G.os2.have_dirname) {
+                strcpy(G.os2.matchname, G.os2.dirname);
+                fnamestart = G.os2.matchname + G.os2.dirnamelen;
+            } else
+                fnamestart = G.os2.matchname;
+            while ((file = readdir(__G__ G.os2.dir)) != NULL) {
+                Trace((stderr, "do_wild:  readdir returns %s\n", file->d_name));
+                strcpy(fnamestart, file->d_name);
+                if (strrchr(fnamestart, '.') == (char *)NULL)
+                    strcat(fnamestart, ".");
+                if (match(fnamestart, G.os2.wildname, 1) &&  /* 1 == ignore case */
+                    /* skip "." and ".." directory entries */
+                    strcmp(fnamestart, ".") && strcmp(fnamestart, "..")) {
+                    Trace((stderr, "do_wild:  match() succeeds\n"));
+                    /* remove trailing dot */
+                    fnamestart += strlen(fnamestart) - 1;
+                    if (*fnamestart == '.')
+                        *fnamestart = '\0';
+                    return G.os2.matchname;
+                }
+            }
+            /* if we get to here directory is exhausted, so close it */
+            closedir(G.os2.dir);
+            G.os2.dir = NULL;
+        }
+#ifdef DEBUG
+        else {
+            Trace((stderr, "do_wild:  opendir(%s) returns NULL\n", G.os2.dirname));
+        }
+#endif /* DEBUG */
+
+        /* return the raw wildspec in case that works (e.g., directory not
+         * searchable, but filespec was not wild and file is readable) */
+        strcpy(G.os2.matchname, wildspec);
+        return G.os2.matchname;
+    }
+
+    /* last time through, might have failed opendir but returned raw wildspec */
+    if (G.os2.dir == NULL) {
+        G.os2.firstcall = TRUE;  /* nothing left to try--reset for new wildspec */
+        if (G.os2.have_dirname)
+            free(G.os2.dirname);
+        return (char *)NULL;
+    }
+
+    /* If we've gotten this far, we've read and matched at least one entry
+     * successfully (in a previous call), so dirname has been copied into
+     * matchname already.
+     */
+    if (G.os2.have_dirname) {
+        /* strcpy(G.os2.matchname, G.os2.dirname); */
+        fnamestart = G.os2.matchname + G.os2.dirnamelen;
+    } else
+        fnamestart = G.os2.matchname;
+    while ((file = readdir(__G__ G.os2.dir)) != NULL) {
+        Trace((stderr, "do_wild:  readdir returns %s\n", file->d_name));
+        strcpy(fnamestart, file->d_name);
+        if (strrchr(fnamestart, '.') == (char *)NULL)
+            strcat(fnamestart, ".");
+        if (match(fnamestart, G.os2.wildname, 1)) {     /* 1 == ignore case */
+            Trace((stderr, "do_wild:  match() succeeds\n"));
+            /* remove trailing dot */
+            fnamestart += strlen(fnamestart) - 1;
+            if (*fnamestart == '.')
+                *fnamestart = '\0';
+            return G.os2.matchname;
+        }
+    }
+
+    closedir(G.os2.dir);     /* have read at least one dir entry; nothing left */
+    G.os2.dir = NULL;
+    G.os2.firstcall = TRUE;  /* reset for new wildspec */
+    if (G.os2.have_dirname)
+        free(G.os2.dirname);
+    return (char *)NULL;
+
+} /* end function do_wild() */
+
+#endif /* !SFX */
+
+
+/* scan extra fields for something we happen to know */
+
+static int EvalExtraFields(__GPRO__ const char *path,
+                           void *extra_field, unsigned ef_len)
+{
+  char *ef_ptr = extra_field;
+  PEFHEADER pEFblock;
+  int rc = PK_OK;
+
+  while (ef_len >= sizeof(EFHEADER))
+  {
+    pEFblock = (PEFHEADER) ef_ptr;
+
+    if (pEFblock -> nSize > (ef_len - EB_HEADSIZE))
+      return PK_ERR;            /* claimed EFblock length exceeds EF size! */
+
+    switch (pEFblock -> nID)
+    {
+    case EF_OS2:
+      rc = SetEAs(__G__ path, ef_ptr);
+      break;
+    case EF_ACL:
+      rc = (uO.X_flag) ? SetACL(__G__ path, ef_ptr) : PK_OK;
+      break;
+#if 0
+    case EF_IZUNIX:
+    case EF_PKUNIX:
+      /* handled elsewhere */
+      break;
+#endif
+    default:
+      TTrace((stderr,"EvalExtraFields: unknown extra field block, ID=%d\n",
+              pEFblock -> nID));
+      break;
+    }
+
+    ef_ptr += (pEFblock -> nSize + EB_HEADSIZE);
+    ef_len -= (pEFblock -> nSize + EB_HEADSIZE);
+
+    if (rc != PK_OK)
+      break;
+  }
+
+  return rc;
+}
+
+
+
+/************************/
+/*  Function mapattr()  */
+/************************/
+
+int mapattr(__G)
+    __GDEF
+{
+    /* set archive bit (file is not backed up): */
+    G.pInfo->file_attr = (unsigned)(G.crec.external_file_attributes | 32) & 0xff;
+    return 0;
+}
+
+
+
+
+
+/************************/
+/*  Function mapname()  */
+/************************/
+
+/*
+ * There are presently two possibilities in OS/2:  the output filesystem is
+ * FAT, or it is HPFS.  If the former, we need to map to FAT, obviously, but
+ * we *also* must map to HPFS and store that version of the name in extended
+ * attributes.  Either way, we need to map to HPFS, so the main mapname
+ * routine does that.  In the case that the output file system is FAT, an
+ * extra filename-mapping routine is called in checkdir().  While it should
+ * be possible to determine the filesystem immediately upon entry to mapname(),
+ * it is conceivable that the DOS APPEND utility could be added to OS/2 some-
+ * day, allowing a FAT directory to be APPENDed to an HPFS drive/path.  There-
+ * fore we simply check the filesystem at each path component.
+ *
+ * Note that when alternative IFSes become available/popular, everything will
+ * become immensely more complicated.  For example, a Minix filesystem would
+ * have limited filename lengths like FAT but no extended attributes in which
+ * to store the longer versions of the names.  A BSD Unix filesystem would
+ * support paths of length 1024 bytes or more, but it is not clear that FAT
+ * EAs would allow such long .LONGNAME fields or that OS/2 would properly
+ * restore such fields when moving files from FAT to the new filesystem.
+ *
+ * GRR:  some or all of the following chars should be checked in either
+ *       mapname (HPFS) or map2fat (FAT), depending:  ,=^+'"[]<>|\t&
+ */
+                             /* return 0 if no error, 1 if caution (filename */
+int mapname(__G__ renamed)   /*  truncated), 2 if warning (skip file because */
+    __GDEF                   /*  dir doesn't exist), 3 if error (skip file), */
+    int renamed;             /*  or 10 if out of memory (skip file) */
+{                            /*  [also IZ_VOL_LABEL, IZ_CREATED_DIR] */
+    char pathcomp[FILNAMSIZ];      /* path-component buffer */
+    char *pp, *cp=(char *)NULL;    /* character pointers */
+    char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */
+    int quote = FALSE;             /* flag:  next char is literal */
+    int error = 0;
+    register unsigned workch;      /* hold the character being tested */
+
+
+/*---------------------------------------------------------------------------
+    Initialize various pointers and counters and stuff.
+  ---------------------------------------------------------------------------*/
+
+    /* can create path as long as not just freshening, or if user told us */
+    G.create_dirs = (!uO.fflag || renamed);
+
+    G.os2.created_dir = FALSE;  /* not yet */
+    G.os2.renamed_fullpath = FALSE;
+    G.os2.fnlen = strlen(G.filename);
+
+/* GRR:  for VMS, convert to internal format now or later? or never? */
+    if (renamed) {
+        cp = G.filename - 1;    /* point to beginning of renamed name... */
+        while (*++cp)
+            if (*cp == '\\')    /* convert backslashes to forward */
+                *cp = '/';
+        cp = G.filename;
+        /* use temporary rootpath if user gave full pathname */
+        if (G.filename[0] == '/') {
+            G.os2.renamed_fullpath = TRUE;
+            pathcomp[0] = '/';  /* copy the '/' and terminate */
+            pathcomp[1] = '\0';
+            ++cp;
+        } else if (isalpha(G.filename[0]) && G.filename[1] == ':') {
+            G.os2.renamed_fullpath = TRUE;
+            pp = pathcomp;
+            *pp++ = *cp++;      /* copy the "d:" (+ '/', possibly) */
+            *pp++ = *cp++;
+            if (*cp == '/')
+                *pp++ = *cp++;  /* otherwise add "./"? */
+            *pp = '\0';
+        }
+    }
+
+    /* pathcomp is ignored unless renamed_fullpath is TRUE: */
+    if ((error = checkdir(__G__ pathcomp, INIT)) != 0)    /* init path buffer */
+        return error;           /* ...unless no mem or vol label on hard disk */
+
+    *pathcomp = '\0';           /* initialize translation buffer */
+    pp = pathcomp;              /* point to translation buffer */
+    if (!renamed) {             /* cp already set if renamed */
+        if (uO.jflag)           /* junking directories */
+/* GRR:  watch out for VMS version... */
+            cp = (char *)strrchr(G.filename, '/');
+        if (cp == (char *)NULL) /* no '/' or not junking dirs */
+            cp = G.filename;    /* point to internal zipfile-member pathname */
+        else
+            ++cp;               /* point to start of last component of path */
+    }
+
+/*---------------------------------------------------------------------------
+    Begin main loop through characters in filename.
+  ---------------------------------------------------------------------------*/
+
+    while ((workch = (uch)*cp++) != 0) {
+
+        if (quote) {              /* if character quoted, */
+            *pp++ = (char)workch; /*  include it literally */
+            quote = FALSE;
+        } else
+            switch (workch) {
+            case '/':             /* can assume -j flag not given */
+                *pp = '\0';
+                if ((error = checkdir(__G__ pathcomp, APPEND_DIR)) > 1)
+                    return error;
+                pp = pathcomp;    /* reset conversion buffer for next piece */
+                lastsemi = (char *)NULL; /* leave directory semi-colons alone */
+                break;
+
+            case ':':
+                *pp++ = '_';      /* drive names not stored in zipfile, */
+                break;            /*  so no colons allowed */
+
+            case ';':             /* start of VMS version? */
+                lastsemi = pp;    /* remove VMS version later... */
+                *pp++ = ';';      /*  but keep semicolon for now */
+                break;
+
+            case '\026':          /* control-V quote for special chars */
+                quote = TRUE;     /* set flag for next character */
+                break;
+
+            case ' ':             /* keep spaces unless specifically */
+                if (uO.sflag)     /*  requested to change to underscore */
+                    *pp++ = '_';
+                else
+                    *pp++ = ' ';
+                break;
+
+            default:
+                /* allow ASCII 255 and European characters in filenames: */
+                if (isprint(workch) || workch >= 127)
+                    *pp++ = (char)workch;
+            } /* end switch */
+
+    } /* end while loop */
+
+    *pp = '\0';                   /* done with pathcomp:  terminate it */
+
+    /* if not saving them, remove VMS version numbers (appended "###") */
+    if (!uO.V_flag && lastsemi) {
+        pp = lastsemi + 1;        /* semi-colon was kept:  expect #s after */
+        while (isdigit((uch)(*pp)))
+            ++pp;
+        if (*pp == '\0')          /* only digits between ';' and end:  nuke */
+            *lastsemi = '\0';
+    }
+
+/*---------------------------------------------------------------------------
+    Report if directory was created (and no file to create:  filename ended
+    in '/'), check name to be sure it exists, and combine path and name be-
+    fore exiting.
+  ---------------------------------------------------------------------------*/
+
+    if (G.filename[G.os2.fnlen-1] == '/') {
+        checkdir(__G__ G.filename, GETPATH);
+        if (G.os2.created_dir) {
+            if (!uO.qflag)
+                Info(slide, 0, ((char *)slide, LoadFarString(Creating),
+                  G.filename));
+            if (G.extra_field) { /* zipfile extra field has extended attribs */
+                int err = EvalExtraFields(__G__ G.filename, G.extra_field,
+                                          G.lrec.extra_field_length);
+
+                if (err == IZ_EF_TRUNC) {
+                    if (uO.qflag)
+                        Info(slide, 1, ((char *)slide, "%-22s ", G.filename));
+                    Info(slide, 1, ((char *)slide, LoadFarString(TruncEAs),
+                      makeword(G.extra_field+2)-10, "\n"));
+                } else if (!uO.qflag)
+                    (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
+            } else if (!uO.qflag)
+                (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
+
+            /* set date/time stamps */
+            SetPathAttrTimes(__G__ G.pInfo->file_attr & ~A_ARCHIVE, 1);
+
+            return IZ_CREATED_DIR;   /* dir time already set */
+
+        } else if (G.extra_field && uO.overwrite_all) {
+            /* overwrite EAs of existing directory since user requested it */
+            int err = EvalExtraFields(__G__ G.filename, G.extra_field,
+                                      G.lrec.extra_field_length);
+
+            if (err == IZ_EF_TRUNC) {
+                Info(slide, 0x421, ((char *)slide, "%-22s ", G.filename));
+                Info(slide, 0x401, ((char *)slide, LoadFarString(TruncEAs),
+                  makeword(G.extra_field+2)-10, "\n"));
+            }
+
+            /* set date/time stamps (dirs only have creation times) */
+            SetPathAttrTimes(__G__ G.pInfo->file_attr & ~A_ARCHIVE, 1);
+        }
+        return 2;   /* dir existed already; don't look for data to extract */
+    }
+
+    if (*pathcomp == '\0') {
+        Info(slide, 1, ((char *)slide, LoadFarString(ConversionFailed),
+          G.filename));
+        return 3;
+    }
+
+    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */
+    checkdir(__G__ G.filename, GETPATH);
+    Trace((stderr, "mapname returns with filename = [%s] (error = %d)\n\n",
+      G.filename, error));
+
+    if (G.pInfo->vollabel) {    /* set the volume label now */
+        VOLUMELABEL FSInfoBuf;
+/* GRR:  "VOLUMELABEL" defined for IBM C and emx, but haven't checked MSC... */
+
+        strcpy(FSInfoBuf.szVolLabel, G.filename);
+        FSInfoBuf.cch = (BYTE)strlen(FSInfoBuf.szVolLabel);
+
+        if (!uO.qflag)
+            Info(slide, 0, ((char *)slide, LoadFarString(Labelling),
+              (char)(G.os2.nLabelDrive + 'a' - 1), G.filename));
+        if (DosSetFSInfo(G.os2.nLabelDrive, FSIL_VOLSER, (PBYTE)&FSInfoBuf,
+                         sizeof(VOLUMELABEL)))
+        {
+            Info(slide, 1, ((char *)slide, LoadFarString(ErrSetVolLabel)));
+            return 3;
+        }
+        return 2;   /* success:  skip the "extraction" quietly */
+    }
+
+    return error;
+
+} /* end function mapname() */
+
+
+
+
+
+/***********************/
+/* Function checkdir() */
+/***********************/
+
+int checkdir(__G__ pathcomp, flag)
+    __GDEF
+    char *pathcomp;
+    int flag;
+/*
+ * returns:  1 - (on APPEND_NAME) truncated filename
+ *           2 - path doesn't exist, not allowed to create
+ *           3 - path doesn't exist, tried to create and failed; or
+ *               path exists and is not a directory, but is supposed to be
+ *           4 - path is too long
+ *          10 - can't allocate memory for filename buffers
+ */
+{
+  /* moved to os2data.h so they can be global */
+#if 0
+    static int rootlen = 0;      /* length of rootpath */
+    static char *rootpath;       /* user's "extract-to" directory */
+    static char *buildpathHPFS;  /* full path (so far) to extracted file, */
+    static char *buildpathFAT;   /*  both HPFS/EA (main) and FAT versions */
+    static char *endHPFS;        /* corresponding pointers to end of */
+    static char *endFAT;         /*  buildpath ('\0') */
+#endif
+
+#   define FN_MASK   7
+#   define FUNCTION  (flag & FN_MASK)
+
+
+
+/*---------------------------------------------------------------------------
+    APPEND_DIR:  append the path component to the path being built and check
+    for its existence.  If doesn't exist and we are creating directories, do
+    so for this one; else signal success or error as appropriate.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == APPEND_DIR) {
+        char *p = pathcomp;
+        int longdirEA, too_long=FALSE;
+
+        Trace((stderr, "appending dir segment [%s]\n", pathcomp));
+        while ((*G.os2.endHPFS = *p++) != '\0')     /* copy to HPFS filename */
+            ++G.os2.endHPFS;
+        if (IsFileNameValid(G.os2.buildpathHPFS)) {
+            longdirEA = FALSE;
+            p = pathcomp;
+            while ((*G.os2.endFAT = *p++) != '\0')  /* copy to FAT filename, too */
+                ++G.os2.endFAT;
+        } else {
+            longdirEA = TRUE;
+/* GRR:  check error return? */
+            map2fat(pathcomp, &G.os2.endFAT);  /* map, put in FAT fn, update endFAT */
+        }
+
+        /* GRR:  could do better check, see if overrunning buffer as we go:
+         * check endHPFS-G.os2.buildpathHPFS after each append, set warning variable
+         * if within 20 of FILNAMSIZ; then if var set, do careful check when
+         * appending.  Clear variable when begin new path. */
+
+        /* next check:  need to append '/', at least one-char name, '\0' */
+        if ((G.os2.endHPFS-G.os2.buildpathHPFS) > FILNAMSIZ-3)
+            too_long = TRUE;                 /* check if extracting dir? */
+#ifdef MSC /* MSC 6.00 bug:  stat(non-existent-dir) == 0 [exists!] */
+        if (GetFileTime(G.os2.buildpathFAT) == -1 || stat(G.os2.buildpathFAT, &G.statbuf))
+#else
+        if (stat(G.os2.buildpathFAT, &G.statbuf))    /* path doesn't exist */
+#endif
+        {
+            if (!G.create_dirs) { /* told not to create (freshening) */
+                free(G.os2.buildpathHPFS);
+                free(G.os2.buildpathFAT);
+                return 2;         /* path doesn't exist:  nothing to do */
+            }
+            if (too_long) {   /* GRR:  should allow FAT extraction w/o EAs */
+                Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong),
+                  G.os2.buildpathHPFS));
+                free(G.os2.buildpathHPFS);
+                free(G.os2.buildpathFAT);
+                return 4;         /* no room for filenames:  fatal */
+            }
+            if (MKDIR(G.os2.buildpathFAT, 0777) == -1) {   /* create the directory */
+                Info(slide, 1, ((char *)slide, LoadFarString(CantCreateDir),
+                  G.os2.buildpathFAT, G.filename));
+                free(G.os2.buildpathHPFS);
+                free(G.os2.buildpathFAT);
+                return 3;      /* path didn't exist, tried to create, failed */
+            }
+            G.os2.created_dir = TRUE;
+            /* only set EA if creating directory */
+/* GRR:  need trailing '/' before function call? */
+            if (longdirEA) {
+#ifdef DEBUG
+                int e =
+#endif
+                  SetLongNameEA(G.os2.buildpathFAT, pathcomp);
+                Trace((stderr, "APPEND_DIR:  SetLongNameEA() returns %d\n", e));
+            }
+        } else if (!S_ISDIR(G.statbuf.st_mode)) {
+            Info(slide, 1, ((char *)slide, LoadFarString(DirIsntDirectory),
+              G.os2.buildpathFAT, G.filename));
+            free(G.os2.buildpathHPFS);
+            free(G.os2.buildpathFAT);
+            return 3;          /* path existed but wasn't dir */
+        }
+        if (too_long) {
+            Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong),
+              G.os2.buildpathHPFS));
+            free(G.os2.buildpathHPFS);
+            free(G.os2.buildpathFAT);
+            return 4;         /* no room for filenames:  fatal */
+        }
+        *G.os2.endHPFS++ = '/';
+        *G.os2.endFAT++ = '/';
+        *G.os2.endHPFS = *G.os2.endFAT = '\0';
+        Trace((stderr, "buildpathHPFS now = [%s]\n", G.os2.buildpathHPFS));
+        Trace((stderr, "buildpathFAT now =  [%s]\n", G.os2.buildpathFAT));
+        return 0;
+
+    } /* end if (FUNCTION == APPEND_DIR) */
+
+/*---------------------------------------------------------------------------
+    GETPATH:  copy full FAT path to the string pointed at by pathcomp (want
+    filename to reflect name used on disk, not EAs; if full path is HPFS,
+    buildpathFAT and buildpathHPFS will be identical).  Also free both paths.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == GETPATH) {
+        Trace((stderr, "getting and freeing FAT path [%s]\n", G.os2.buildpathFAT));
+        Trace((stderr, "freeing HPFS path [%s]\n", G.os2.buildpathHPFS));
+        strcpy(pathcomp, G.os2.buildpathFAT);
+        free(G.os2.buildpathFAT);
+        free(G.os2.buildpathHPFS);
+        G.os2.buildpathHPFS = G.os2.buildpathFAT = G.os2.endHPFS = G.os2.endFAT = (char *)NULL;
+        return 0;
+    }
+
+/*---------------------------------------------------------------------------
+    APPEND_NAME:  assume the path component is the filename; append it and
+    return without checking for existence.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == APPEND_NAME) {
+        char *p = pathcomp;
+        int error = 0;
+
+        Trace((stderr, "appending filename [%s]\n", pathcomp));
+        while ((*G.os2.endHPFS = *p++) != '\0') {    /* copy to HPFS filename */
+            ++G.os2.endHPFS;
+            if ((G.os2.endHPFS-G.os2.buildpathHPFS) >= FILNAMSIZ) {
+                *--G.os2.endHPFS = '\0';
+                Info(slide, 1, ((char *)slide, LoadFarString(PathTooLongTrunc),
+                  G.filename, G.os2.buildpathHPFS));
+                error = 1;   /* filename truncated */
+            }
+        }
+
+/* GRR:  how can longnameEA ever be set before this point???  we don't want
+ * to save the original name to EAs if user renamed it, do we?
+ *
+ * if (!G.os2.longnameEA && ((G.os2.longnameEA = !IsFileNameValid(name)) != 0))
+ */
+        if (G.pInfo->vollabel || IsFileNameValid(G.os2.buildpathHPFS)) {
+            G.os2.longnameEA = FALSE;
+            p = pathcomp;
+            while ((*G.os2.endFAT = *p++) != '\0')   /* copy to FAT filename, too */
+                ++G.os2.endFAT;
+        } else {
+            G.os2.longnameEA = TRUE;
+            if ((G.os2.lastpathcomp = (char *)malloc(strlen(pathcomp)+1)) ==
+                (char *)NULL)
+            {
+                Info(slide, 1, ((char *)slide,
+                 "checkdir warning:  cannot save longname EA: out of memory\n"));
+                G.os2.longnameEA = FALSE;
+                error = 1;   /* can't set .LONGNAME extended attribute */
+            } else           /* used and freed in close_outfile() */
+                strcpy(G.os2.lastpathcomp, pathcomp);
+            map2fat(pathcomp, &G.os2.endFAT);  /* map, put in FAT fn, update endFAT */
+        }
+        Trace((stderr, "buildpathHPFS: %s\nbuildpathFAT:  %s\n",
+          G.os2.buildpathHPFS, G.os2.buildpathFAT));
+
+        return error;  /* could check for existence, prompt for new name... */
+
+    } /* end if (FUNCTION == APPEND_NAME) */
+
+/*---------------------------------------------------------------------------
+    INIT:  allocate and initialize buffer space for the file currently being
+    extracted.  If file was renamed with an absolute path, don't prepend the
+    extract-to path.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == INIT) {
+        Trace((stderr, "initializing buildpathHPFS and buildpathFAT to "));
+        if ((G.os2.buildpathHPFS = (char *)malloc(G.os2.fnlen+G.os2.rootlen+1)) == (char *)NULL)
+            return 10;
+        if ((G.os2.buildpathFAT = (char *)malloc(G.os2.fnlen+G.os2.rootlen+1)) == (char *)NULL) {
+            free(G.os2.buildpathHPFS);
+            return 10;
+        }
+        if (G.pInfo->vollabel) {  /* use root or renamed path, but don't store */
+/* GRR:  for network drives, do strchr() and return IZ_VOL_LABEL if not [1] */
+            if (G.os2.renamed_fullpath && pathcomp[1] == ':')
+                *G.os2.buildpathHPFS = (char)ToLower(*pathcomp);
+            else if (!G.os2.renamed_fullpath && G.os2.rootlen > 1 && G.os2.rootpath[1] == ':')
+                *G.os2.buildpathHPFS = (char)ToLower(*G.os2.rootpath);
+            else {
+                ULONG lMap;
+                DosQueryCurrentDisk(&G.os2.nLabelDrive, &lMap);
+                *G.os2.buildpathHPFS = (char)(G.os2.nLabelDrive - 1 + 'a');
+            }
+            G.os2.nLabelDrive = *G.os2.buildpathHPFS - 'a' + 1; /* save for mapname() */
+            if (uO.volflag == 0 || *G.os2.buildpathHPFS < 'a' ||  /* no labels/bogus? */
+                (uO.volflag == 1 && !isfloppy(G.os2.nLabelDrive))) { /* -$:  no fixed */
+                free(G.os2.buildpathHPFS);
+                free(G.os2.buildpathFAT);
+                return IZ_VOL_LABEL;   /* skipping with message */
+            }
+            *G.os2.buildpathHPFS = '\0';
+        } else if (G.os2.renamed_fullpath)   /* pathcomp = valid data */
+            strcpy(G.os2.buildpathHPFS, pathcomp);
+        else if (G.os2.rootlen > 0)
+            strcpy(G.os2.buildpathHPFS, G.os2.rootpath);
+        else
+            *G.os2.buildpathHPFS = '\0';
+        G.os2.endHPFS = G.os2.buildpathHPFS;
+        G.os2.endFAT = G.os2.buildpathFAT;
+        while ((*G.os2.endFAT = *G.os2.endHPFS) != '\0') {
+            ++G.os2.endFAT;
+            ++G.os2.endHPFS;
+        }
+        Trace((stderr, "[%s]\n", G.os2.buildpathHPFS));
+        return 0;
+    }
+
+/*---------------------------------------------------------------------------
+    ROOT:  if appropriate, store the path in rootpath and create it if neces-
+    sary; else assume it's a zipfile member and return.  This path segment
+    gets used in extracting all members from every zipfile specified on the
+    command line.  Note that under OS/2 and MS-DOS, if a candidate extract-to
+    directory specification includes a drive letter (leading "x:"), it is
+    treated just as if it had a trailing '/'--that is, one directory level
+    will be created if the path doesn't exist, unless this is otherwise pro-
+    hibited (e.g., freshening).
+  ---------------------------------------------------------------------------*/
+
+#if (!defined(SFX) || defined(SFX_EXDIR))
+    if (FUNCTION == ROOT) {
+        Trace((stderr, "initializing root path to [%s]\n", pathcomp));
+        if (pathcomp == (char *)NULL) {
+            G.os2.rootlen = 0;
+            return 0;
+        }
+        if ((G.os2.rootlen = strlen(pathcomp)) > 0) {
+            int had_trailing_pathsep=FALSE, has_drive=FALSE, xtra=2;
+
+            if (isalpha(pathcomp[0]) && pathcomp[1] == ':')
+                has_drive = TRUE;   /* drive designator */
+            if (pathcomp[G.os2.rootlen-1] == '/') {
+                pathcomp[--G.os2.rootlen] = '\0';
+                had_trailing_pathsep = TRUE;
+            }
+            if (has_drive && (G.os2.rootlen == 2)) {
+                if (!had_trailing_pathsep)   /* i.e., original wasn't "x:/" */
+                    xtra = 3;      /* room for '.' + '/' + 0 at end of "x:" */
+            } else if (G.os2.rootlen > 0) {     /* need not check "x:." and "x:/" */
+#ifdef MSC      /* MSC 6.00 bug:  stat(non-existent-dir) == 0 [exists!] */
+                if (GetFileTime(pathcomp) == -1 ||
+                    SSTAT(pathcomp, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))
+#else
+                if (SSTAT(pathcomp, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))
+#endif
+                {   /* path does not exist */
+                    if (!G.create_dirs                 /* || iswild(pathcomp) */
+                                       ) {
+                        G.os2.rootlen = 0;
+                        return 2;   /* treat as stored file */
+                    }
+                    /* create directory (could add loop here to scan pathcomp
+                     * and create more than one level, but really necessary?) */
+                    if (MKDIR(pathcomp, 0777) == -1) {
+                        Info(slide, 1, ((char *)slide,
+                          LoadFarString(CantCreateExtractDir), pathcomp));
+                        G.os2.rootlen = 0;   /* path didn't exist, tried to create, */
+                        return 3;  /* failed:  file exists, or need 2+ levels */
+                    }
+                }
+            }
+            if ((G.os2.rootpath = (char *)malloc(G.os2.rootlen+xtra)) == (char *)NULL) {
+                G.os2.rootlen = 0;
+                return 10;
+            }
+            strcpy(G.os2.rootpath, pathcomp);
+            if (xtra == 3)                  /* had just "x:", make "x:." */
+                G.os2.rootpath[G.os2.rootlen++] = '.';
+            G.os2.rootpath[G.os2.rootlen++] = '/';
+            G.os2.rootpath[G.os2.rootlen] = '\0';
+            Trace((stderr, "rootpath now = [%s]\n", G.os2.rootpath));
+        }
+        return 0;
+    }
+#endif /* !SFX || SFX_EXDIR */
+
+/*---------------------------------------------------------------------------
+    END:  free rootpath, immediately prior to program exit.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == END) {
+        Trace((stderr, "freeing rootpath\n"));
+        if (G.os2.rootlen > 0) {
+            free(G.os2.rootpath);
+            G.os2.rootlen = 0;
+        }
+        return 0;
+    }
+
+    return 99;  /* should never reach */
+
+} /* end function checkdir() */
+
+
+
+
+
+/***********************/
+/* Function isfloppy() */   /* more precisely, is it removable? */
+/***********************/
+
+static int isfloppy(nDrive)
+    int nDrive;   /* 1 == A:, 2 == B:, etc. */
+{
+    uch ParmList[1] = {0};
+    uch DataArea[1] = {0};
+    char Name[3];
+    HFILE handle;
+#ifdef __32BIT__
+    ULONG rc;
+    ULONG action;
+#else
+    USHORT rc;
+    USHORT action;
+#endif
+
+
+    Name[0] = (char) (nDrive + 'A' - 1);
+    Name[1] = ':';
+    Name[2] = 0;
+
+    rc = DosOpen(Name, &handle, &action, 0L, FILE_NORMAL, FILE_OPEN,
+                 OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR |
+                 OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0L);
+
+    if (rc == ERROR_NOT_READY)   /* must be removable */
+      return TRUE;
+    else if (rc) {   /* other error:  do default a/b heuristic instead */
+      Trace((stderr, "error in DosOpen(DASD):  guessing...\n", rc));
+      return (nDrive == 1 || nDrive == 2)? TRUE : FALSE;
+    }
+
+    rc = DosDevIOCtl(DataArea, sizeof(DataArea), ParmList, sizeof(ParmList),
+                     DSK_BLOCKREMOVABLE, IOCTL_DISK, handle);
+    DosClose(handle);
+
+    if (rc) {   /* again, just check for a/b */
+        Trace((stderr, "error in DosDevIOCtl category IOCTL_DISK, function "
+          "DSK_BLOCKREMOVABLE\n  (rc = 0x%04x):  guessing...\n", rc));
+        return (nDrive == 1 || nDrive == 2)? TRUE : FALSE;
+    } else {
+        return DataArea[0] ? FALSE : TRUE;
+    }
+} /* end function isfloppy() */
+
+
+
+
+
+static int IsFileNameValid(const char *name)
+{
+  HFILE hf;
+#ifdef __32BIT__
+  ULONG uAction;
+#else
+  USHORT uAction;
+#endif
+
+  switch( DosOpen((PSZ) name, &hf, &uAction, 0, 0, FILE_OPEN,
+                  OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0) )
+  {
+  case ERROR_INVALID_NAME:
+  case ERROR_FILENAME_EXCED_RANGE:
+    return FALSE;
+  case NO_ERROR:
+    DosClose(hf);
+  default:
+    return TRUE;
+  }
+}
+
+
+
+
+
+/**********************/
+/* Function map2fat() */
+/**********************/
+
+static void map2fat(pathcomp, pEndFAT)
+    char *pathcomp, **pEndFAT;
+{
+    char *ppc = pathcomp;          /* variable pointer to pathcomp */
+    char *pEnd = *pEndFAT;         /* variable pointer to buildpathFAT */
+    char *pBegin = *pEndFAT;       /* constant pointer to start of this comp. */
+    char *last_dot = (char *)NULL; /* last dot not converted to underscore */
+    int dotname = FALSE;           /* flag:  path component begins with dot */
+                                   /*  ("." and ".." don't count) */
+    register unsigned workch;      /* hold the character being tested */
+
+
+    /* Only need check those characters which are legal in HPFS but not
+     * in FAT:  to get here, must already have passed through mapname.
+     * (GRR:  oops, small bug--if char was quoted, no longer have any
+     * knowledge of that.)  Also must truncate path component to ensure
+     * 8.3 compliance...
+     */
+    while ((workch = (uch)*ppc++) != 0) {
+        switch (workch) {
+            case '[':               /* add  '"'  '+'  ','  '='  ?? */
+            case ']':
+                *pEnd++ = '_';      /* convert brackets to underscores */
+                break;
+
+            case '.':
+                if (pEnd == *pEndFAT) {   /* nothing appended yet... */
+                    if (*ppc == '\0')     /* don't bother appending a */
+                        break;            /*  "./" component to the path */
+                    else if (*ppc == '.' && ppc[1] == '\0') {   /* "../" */
+                        *pEnd++ = '.';    /* add first dot, unchanged... */
+                        ++ppc;            /* skip second dot, since it will */
+                    } else {              /*  be "added" at end of if-block */
+                        *pEnd++ = '_';    /* FAT doesn't allow null filename */
+                        dotname = TRUE;   /*  bodies, so map .exrc -> _.exrc */
+                    }                     /*  (extra '_' now, "dot" below) */
+                } else if (dotname) {     /* found a second dot, but still */
+                    dotname = FALSE;      /*  have extra leading underscore: */
+                    *pEnd = '\0';         /*  remove it by shifting chars */
+                    pEnd = *pEndFAT + 1;  /*  left one space (e.g., .p1.p2: */
+                    while (pEnd[1]) {     /*  __p1 -> _p1_p2 -> _p1.p2 when */
+                        *pEnd = pEnd[1];  /*  finished) [opt.:  since first */
+                        ++pEnd;           /*  two chars are same, can start */
+                    }                     /*  shifting at second position] */
+                }
+                last_dot = pEnd;    /* point at last dot so far... */
+                *pEnd++ = '_';      /* convert dot to underscore for now */
+                break;
+
+            default:
+                *pEnd++ = (char)workch;
+
+        } /* end switch */
+    } /* end while loop */
+
+    *pEnd = '\0';                 /* terminate buildpathFAT */
+
+    /* NOTE:  keep in mind that pEnd points to the end of the path
+     * component, and *pEndFAT still points to the *beginning* of it...
+     * Also note that the algorithm does not try to get too fancy:
+     * if there are no dots already, the name either gets truncated
+     * at 8 characters or the last underscore is converted to a dot
+     * (only if more characters are saved that way).  In no case is
+     * a dot inserted between existing characters.
+     */
+    if (last_dot == (char *)NULL) {  /* no dots:  check for underscores... */
+        char *plu = strrchr(pBegin, '_');    /* pointer to last underscore */
+
+        if (plu == (char *)NULL) { /* no dots, no underscores:  truncate at 8 */
+            *pEndFAT += 8;         /* chars (could insert '.' and keep 11...) */
+            if (*pEndFAT > pEnd)
+                *pEndFAT = pEnd;   /* oops...didn't have 8 chars to truncate */
+            else
+                **pEndFAT = '\0';
+        } else if (MIN(plu - pBegin, 8) + MIN(pEnd - plu - 1, 3) > 8) {
+            last_dot = plu;        /* be lazy:  drop through to next if-block */
+        } else if ((pEnd - *pEndFAT) > 8) {
+            *pEndFAT += 8;         /* more fits into just basename than if */
+            **pEndFAT = '\0';      /*  convert last underscore to dot */
+        } else
+            *pEndFAT = pEnd;       /* whole thing fits into 8 chars or less */
+    }
+
+    if (last_dot != (char *)NULL) {   /* one dot (or two, in the case of */
+        *last_dot = '.';              /*  "..") is OK:  put it back in */
+
+        if ((last_dot - pBegin) > 8) {
+            char *p, *q;
+            int i;
+
+            p = last_dot;
+            q = last_dot = pBegin + 8;
+            for (i = 0;  (i < 4) && *p;  ++i)  /* too many chars in basename: */
+                *q++ = *p++;                   /*  shift ".ext" left and */
+            *q = '\0';                         /*  truncate/terminate it */
+            *pEndFAT = q;
+        } else if ((pEnd - last_dot) > 4) {    /* too many chars in extension */
+            *pEndFAT = last_dot + 4;
+            **pEndFAT = '\0';
+        } else
+            *pEndFAT = pEnd;   /* filename is fine; point at terminating zero */
+
+        if ((last_dot - pBegin) > 0 && last_dot[-1] == ' ')
+            last_dot[-1] = '_';                /* NO blank in front of '.'! */
+    }
+} /* end function map2fat() */
+
+
+
+
+
+static int SetLongNameEA(char *name, char *longname)
+{
+  EAOP eaop;
+  FEALST fealst;
+
+  eaop.fpFEAList = (PFEALIST) &fealst;
+  eaop.fpGEAList = NULL;
+  eaop.oError = 0;
+
+  strcpy((char *) fealst.szName, ".LONGNAME");
+  strcpy((char *) fealst.szValue, longname);
+
+  fealst.cbList  = sizeof(fealst) - CCHMAXPATH + strlen((char *) fealst.szValue);
+  fealst.cbName  = (BYTE) strlen((char *) fealst.szName);
+  fealst.cbValue = sizeof(USHORT) * 2 + strlen((char *) fealst.szValue);
+
+#ifdef __32BIT__
+  fealst.oNext   = 0;
+#endif
+  fealst.fEA     = 0;
+  fealst.eaType  = 0xFFFD;
+  fealst.eaSize  = strlen((char *) fealst.szValue);
+
+  return DosSetPathInfo(name, FIL_QUERYEASIZE,
+                        (PBYTE) &eaop, sizeof(eaop), 0);
+}
+
+
+
+
+
+/****************************/
+/* Function close_outfile() */
+/****************************/
+
+           /* GRR:  need to return error level!! */
+
+void close_outfile(__G)   /* only for extracted files, not directories */
+    __GDEF
+{
+    fclose(G.outfile);
+
+    /* set extra fields, both stored-in-zipfile and .LONGNAME flavors */
+    if (G.extra_field) {    /* zipfile extra field may have extended attribs */
+        int err = EvalExtraFields(__G__ G.filename, G.extra_field,
+                                  G.lrec.extra_field_length);
+
+        if (err == IZ_EF_TRUNC) {
+            if (uO.qflag)
+                Info(slide, 1, ((char *)slide, "%-22s ", G.filename));
+            Info(slide, 1, ((char *)slide, LoadFarString(TruncEAs),
+              makeword(G.extra_field+2)-10, uO.qflag? "\n" : ""));
+        }
+    }
+
+    if (G.os2.longnameEA) {
+#ifdef DEBUG
+        int e =
+#endif
+          SetLongNameEA(G.filename, G.os2.lastpathcomp);
+        Trace((stderr, "close_outfile:  SetLongNameEA() returns %d\n", e));
+        free(G.os2.lastpathcomp);
+    }
+
+    /* set date/time and permissions */
+    SetPathAttrTimes(__G__ G.pInfo->file_attr, 0);
+
+} /* end function close_outfile() */
+
+
+
+
+
+/******************************/
+/* Function check_for_newer() */
+/******************************/
+
+int check_for_newer(__G__ filename)   /* return 1 if existing file newer or equal; */
+    __GDEF
+    char *filename;             /*  0 if older; -1 if doesn't exist yet */
+{
+    ulg existing, archive;
+#ifdef USE_EF_UT_TIME
+    iztimes z_utime;
+#endif
+
+    if ((existing = (ulg)GetFileTime(filename)) == (ulg)-1)
+        return DOES_NOT_EXIST;
+
+#ifdef USE_EF_UT_TIME
+    if (G.extra_field &&
+#ifdef IZ_CHECK_TZ
+        G.tz_is_valid &&
+#endif
+        (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,
+                          G.lrec.last_mod_dos_datetime, &z_utime, NULL)
+         & EB_UT_FL_MTIME))
+    {
+        TTrace((stderr, "check_for_newer:  using Unix extra field mtime\n"));
+        archive = Utime2DosDateTime(z_utime.mtime);
+    } else {
+        archive = G.lrec.last_mod_dos_datetime;
+    }
+#else /* !USE_EF_UT_TIME */
+    archive = G.lrec.last_mod_dos_datetime;
+#endif /* ?USE_EF_UT_TIME */
+
+    return (existing >= archive);
+} /* end function check_for_newer() */
+
+
+
+
+
+#ifndef SFX
+
+/*************************/
+/* Function dateformat() */
+/*************************/
+
+int dateformat()
+{
+/*-----------------------------------------------------------------------------
+  For those operating systems which support it, this function returns a value
+  which tells how national convention says that numeric dates are displayed.
+  Return values are DF_YMD, DF_DMY and DF_MDY.
+ -----------------------------------------------------------------------------*/
+
+    switch (GetCountryInfo()) {
+        case 0:
+            return DF_MDY;
+        case 1:
+            return DF_DMY;
+        case 2:
+            return DF_YMD;
+    }
+    return DF_MDY;   /* default if error */
+
+} /* end function dateformat() */
+
+
+
+
+
+/************************/
+/*  Function version()  */
+/************************/
+
+void version(__G)
+    __GDEF
+{
+    int len;
+#if defined(__IBMC__) || defined(__WATCOMC__) || defined(_MSC_VER)
+    char buf[80];
+#endif
+
+    len = sprintf((char *)slide, LoadFarString(CompiledWith),
+
+#if defined(__GNUC__)
+#  ifdef __EMX__  /* __EMX__ is defined as "1" only (sigh) */
+      "emx+gcc ", __VERSION__,
+#  else
+      "gcc/2 ", __VERSION__,
+#  endif
+#elif defined(__IBMC__)
+      "IBM ",
+#  if (__IBMC__ < 200)
+      (sprintf(buf, "C Set/2 %d.%02d", __IBMC__/100,__IBMC__%100), buf),
+#  elif (__IBMC__ < 300)
+      (sprintf(buf, "C Set++ %d.%02d", __IBMC__/100,__IBMC__%100), buf),
+#  else
+      (sprintf(buf, "Visual Age C++ %d.%02d", __IBMC__/100,__IBMC__%100), buf),
+#  endif
+#elif defined(__WATCOMC__)
+      "Watcom C", (sprintf(buf, " (__WATCOMC__ = %d)", __WATCOMC__), buf),
+#elif defined(__TURBOC__)
+#  ifdef __BORLANDC__
+      "Borland C++",
+#    if (__BORLANDC__ < 0x0460)
+        " 1.0",
+#    elif (__BORLANDC__ == 0x0460)
+        " 1.5",                     /* from Kai Uwe:  three less than DOS */
+#    else
+        " 2.0",                     /* (__BORLANDC__ == 0x0500)? */
+#    endif
+#  else
+      "Turbo C",                    /* these are probably irrelevant */
+#    if (__TURBOC__ >= 661)
+       "++ 1.0 or later",
+#    elif (__TURBOC__ == 661)
+       " 3.0?",
+#    elif (__TURBOC__ == 397)
+       " 2.0",
+#    else
+       " 1.0 or 1.5?",
+#    endif
+#  endif
+#elif defined(MSC)
+      "Microsoft C ",
+#  ifdef _MSC_VER
+      (sprintf(buf, "%d.%02d", _MSC_VER/100, _MSC_VER%100), buf),
+#  else
+      "5.1 or earlier",
+#  endif
+#else
+      "unknown compiler", "",
+#endif /* ?compilers */
+
+      "OS/2",
+
+/* GRR:  does IBM C/2 identify itself as IBM rather than Microsoft? */
+#if (defined(MSC) || (defined(__WATCOMC__) && !defined(__386__)))
+#  if defined(M_I86HM) || defined(__HUGE__)
+      " (16-bit, huge)",
+#  elif defined(M_I86LM) || defined(__LARGE__)
+      " (16-bit, large)",
+#  elif defined(M_I86MM) || defined(__MEDIUM__)
+      " (16-bit, medium)",
+#  elif defined(M_I86CM) || defined(__COMPACT__)
+      " (16-bit, compact)",
+#  elif defined(M_I86SM) || defined(__SMALL__)
+      " (16-bit, small)",
+#  elif defined(M_I86TM) || defined(__TINY__)
+      " (16-bit, tiny)",
+#  else
+      " (16-bit)",
+#  endif
+#else
+      " 2.x/3.x (32-bit)",
+#endif
+
+#ifdef __DATE__
+      " on ", __DATE__
+#else
+      "", ""
+#endif
+    );
+
+    (*G.message)((zvoid *)&G, slide, (ulg)len, 0);
+                                /* MSC can't handle huge macro expansions */
+
+    /* temporary debugging code for Borland compilers only */
+    /* __TCPLUSPLUS__, __BCPLUSPLUS__ not defined for v1.5 */
+#if (defined(__TURBOC__) && defined(DEBUG))
+    Info(slide, 0, ((char *)slide, "\t(__TURBOC__ = 0x%04x = %d)\n", __TURBOC__,
+      __TURBOC__));
+#ifdef __BORLANDC__
+    Info(slide, 0, ((char *)slide, "\t(__BORLANDC__ = 0x%04x)\n",__BORLANDC__));
+#else
+    Info(slide, 0, ((char *)slide, "\tdebug(__BORLANDC__ not defined)\n"));
+#endif
+#endif /* __TURBOC__ && DEBUG */
+
+} /* end function version() */
+
+#endif /* !SFX */
+
+
+
+/* This table can be static because it is pseudo-constant */
+static unsigned char cUpperCase[256], cLowerCase[256];
+static BOOL bInitialized=FALSE;
+
+/* Initialize the tables of upper- and lowercase characters, including
+   handling of country-dependent characters. */
+
+static void InitNLS(void)
+{
+  unsigned nCnt, nU;
+  COUNTRYCODE cc;
+
+  if (bInitialized == FALSE) {
+    bInitialized = TRUE;
+
+    for ( nCnt = 0; nCnt < 256; nCnt++ )
+      cUpperCase[nCnt] = cLowerCase[nCnt] = (unsigned char) nCnt;
+
+    cc.country = cc.codepage = 0;
+    DosMapCase(sizeof(cUpperCase), &cc, (PCHAR) cUpperCase);
+
+    for ( nCnt = 0; nCnt < 256; nCnt++ ) {
+      nU = cUpperCase[nCnt];
+      if (nU != nCnt && cLowerCase[nU] == (unsigned char) nU)
+        cLowerCase[nU] = (unsigned char) nCnt;
+    }
+
+    for ( nCnt = 'A'; nCnt <= 'Z'; nCnt++ )
+      cLowerCase[nCnt] = (unsigned char) (nCnt - 'A' + 'a');
+  }
+}
+
+
+int IsUpperNLS(int nChr)
+{
+  return (cUpperCase[nChr] == (unsigned char) nChr);
+}
+
+
+int ToLowerNLS(int nChr)
+{
+  return cLowerCase[nChr];
+}
+
+
+char *StringLower(char *szArg)
+{
+  unsigned char *szPtr;
+
+  for ( szPtr = (unsigned char *) szArg; *szPtr; szPtr++ )
+    *szPtr = cLowerCase[*szPtr];
+  return szArg;
+}
+
+
+#if defined(__IBMC__) && defined(__DEBUG_ALLOC__)
+void DebugMalloc(void)
+{
+  _dump_allocated(0); /* print out debug malloc memory statistics */
+}
+#endif
+
+
+#if defined(REENTRANT) && defined(USETHREADID)
+ulg GetThreadId(void)
+{
+  PTIB   pptib;       /* Address of a pointer to the
+                         Thread Information Block */
+  PPIB   pppib;       /* Address of a pointer to the
+                         Process Information Block */
+
+  DosGetInfoBlocks(&pptib, &pppib);
+  return pptib->tib_ptib2->tib2_ultid;
+}
+#endif /* defined(REENTRANT) && defined(USETHREADID) */
+
+
+void os2GlobalsCtor(__GPRO)
+{
+  G.os2.nLastDrive = (USHORT)(-1);
+  G.os2.firstcall = TRUE;
+
+#ifdef OS2DLL
+  G.os2.rexx_mes = "0";
+#endif
+
+  InitNLS();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/os2acl.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,387 @@
+/* os2acl.c - access to OS/2 (LAN Server) ACLs
+ *
+ * Author:  Kai Uwe Rommel <rommel@ars.de>
+ * Created: Mon Aug 08 1994
+ *
+ * This code is in the public domain.
+ */
+
+/*
+ * supported 32-bit compilers:
+ * - emx+gcc
+ * - IBM C Set++ 2.1 or newer
+ * - Watcom C/C++ 10.0 or newer
+ *
+ * supported 16-bit compilers:
+ * - MS C 6.00A
+ * - Watcom C/C++ 10.0 or newer
+ *
+ * supported OS/2 LAN environments:
+ * - IBM LAN Server/Requester 3.0, 4.0 and 5.0 (Warp Server)
+ * - IBM Peer 1.0 (Warp Connect)
+ */
+
+#ifdef KUR
+   static char *rcsid =
+   "$Id: os2acl.c,v 1.1 2001/04/03 20:58:16 bsmith Exp $";
+   static char *rcsrev = "$Revision: 1.1 $";
+#endif
+
+/*
+ * $Log: os2acl.c,v $
+ * Revision 1.1  2001/04/03 20:58:16  bsmith
+ * Added dual decompressor backends.
+ *
+ * Revision 1.2  2000/07/15 19:50:45  cvsuser
+ * merged 2.2 branch
+ *
+ * Revision 1.1.2.1  2000/04/11 12:38:06  BS
+ * Added wxInstall a self extracting installation program using wxWindows.
+ *
+ * Revision 1.3  1996/04/03 19:18:27  rommel
+ * minor fixes
+ *
+ * Revision 1.2  1996/03/30 22:03:52  rommel
+ * avoid frequent dynamic allocation for every call
+ * streamlined code
+ *
+ * Revision 1.1  1996/03/30 09:35:00  rommel
+ * Initial revision
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <malloc.h>
+
+#define INCL_NOPM
+#define INCL_DOS
+#define INCL_DOSERRORS
+#include <os2.h>
+
+#include "os2/os2acl.h"
+
+#define UNLEN 20
+
+#if defined(__WATCOMC__) && defined(__386__) && !defined(__32BIT__)
+#define __32BIT__
+#endif
+
+#ifdef __32BIT__
+typedef ULONG U_INT;
+#ifdef __EMX__
+#define PSTR16 _far16ptr
+#define PTR16(x) _emx_32to16(x)
+#else /* other 32-bit */
+#define PSTR16 PCHAR16
+#define PTR16(x) ((PCHAR16)(x))
+#endif
+#else /* 16-bit */
+typedef USHORT U_INT;
+#define PSTR16 PSZ
+#define PTR16(x) (x)
+#endif
+
+typedef struct access_list
+{
+  char acl_ugname[UNLEN+1];
+  char acl_pad;
+  USHORT acl_access;
+}
+ACCLIST;
+
+typedef struct access_info
+{
+  PSTR16 acc_resource_name;
+  USHORT acc_attr;
+  USHORT acc_count;
+}
+ACCINFO;
+
+static ACCINFO *ai;
+static char *path, *data;
+
+#ifdef __32BIT__
+
+#ifdef __EMX__
+
+static USHORT (APIENTRY *_NetAccessGetInfo)(PSZ pszServer, PSZ pszResource,
+  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail);
+static USHORT (APIENTRY *_NetAccessSetInfo)(PSZ pszServer, PSZ pszResource,
+  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum);
+static USHORT (APIENTRY *_NetAccessAdd)(PSZ pszServer,
+  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer);
+
+USHORT NetAccessGetInfo(PSZ pszServer, PSZ pszResource, USHORT sLevel,
+                        PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail)
+{
+  return (USHORT)
+          (_THUNK_PROLOG (4+4+2+4+2+4);
+           _THUNK_FLAT (pszServer);
+           _THUNK_FLAT (pszResource);
+           _THUNK_SHORT (sLevel);
+           _THUNK_FLAT (pbBuffer);
+           _THUNK_SHORT (cbBuffer);
+           _THUNK_FLAT (pcbTotalAvail);
+           _THUNK_CALLI (_emx_32to16(_NetAccessGetInfo)));
+}
+
+USHORT NetAccessSetInfo(PSZ pszServer, PSZ pszResource, USHORT sLevel,
+                        PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum)
+{
+  return (USHORT)
+          (_THUNK_PROLOG (4+4+2+4+2+2);
+           _THUNK_FLAT (pszServer);
+           _THUNK_FLAT (pszResource);
+           _THUNK_SHORT (sLevel);
+           _THUNK_FLAT (pbBuffer);
+           _THUNK_SHORT (cbBuffer);
+           _THUNK_SHORT (sParmNum);
+           _THUNK_CALLI (_emx_32to16(_NetAccessSetInfo)));
+}
+
+USHORT NetAccessAdd(PSZ pszServer, USHORT sLevel,
+                    PVOID pbBuffer, USHORT cbBuffer)
+{
+  return (USHORT)
+          (_THUNK_PROLOG (4+2+4+2);
+           _THUNK_FLAT (pszServer);
+           _THUNK_SHORT (sLevel);
+           _THUNK_FLAT (pbBuffer);
+           _THUNK_SHORT (cbBuffer);
+           _THUNK_CALLI (_emx_32to16(_NetAccessAdd)));
+}
+
+#else /* other 32-bit */
+
+APIRET16 (* APIENTRY16 NetAccessGetInfo)(PCHAR16 pszServer, PCHAR16 pszResource,
+  USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer, PVOID16 pcbTotalAvail);
+APIRET16 (* APIENTRY16 NetAccessSetInfo)(PCHAR16 pszServer, PCHAR16 pszResource,
+  USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer, USHORT sParmNum);
+APIRET16 (* APIENTRY16 NetAccessAdd)(PCHAR16 pszServer,
+  USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer);
+
+#define _NetAccessGetInfo NetAccessGetInfo
+#define _NetAccessSetInfo NetAccessSetInfo
+#define _NetAccessAdd NetAccessAdd
+
+#if !defined(__IBMC__) || !defined(__TILED__)
+#define _tmalloc malloc
+#define _tfree free
+#endif
+
+#endif
+#else /* 16-bit */
+
+USHORT (APIENTRY *NetAccessGetInfo)(PSZ pszServer, PSZ pszResource,
+  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail);
+USHORT (APIENTRY *NetAccessSetInfo)(PSZ pszServer, PSZ pszResource,
+  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum);
+USHORT (APIENTRY *NetAccessAdd)(PSZ pszServer,
+  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer);
+
+#define _NetAccessGetInfo NetAccessGetInfo
+#define _NetAccessSetInfo NetAccessSetInfo
+#define _NetAccessAdd NetAccessAdd
+
+#define _tmalloc malloc
+#define _tfree free
+
+#define DosQueryProcAddr(handle, ord, name, funcptr) \
+        DosGetProcAddr(handle, name, funcptr)
+#define DosQueryCurrentDir DosQCurDir
+#define DosQueryCurrentDisk DosQCurDisk
+
+#endif
+
+
+static BOOL acl_init(void)
+{
+  static BOOL initialized, netapi_avail;
+  HMODULE netapi;
+  char buf[256];
+
+  if (initialized)
+    return netapi_avail;
+
+  initialized = TRUE;
+
+  if (DosLoadModule(buf, sizeof(buf), "NETAPI", &netapi))
+    return FALSE;
+
+  if (DosQueryProcAddr(netapi, 0, "NETACCESSGETINFO", (PFN *) &_NetAccessGetInfo) ||
+      DosQueryProcAddr(netapi, 0, "NETACCESSSETINFO", (PFN *) &_NetAccessSetInfo) ||
+      DosQueryProcAddr(netapi, 0, "NETACCESSADD", (PFN *) &_NetAccessAdd))
+    return FALSE;
+
+#if defined(__WATCOMC__) && defined(__386__)
+  NetAccessGetInfo = (PVOID) (ULONG) (PVOID16) NetAccessGetInfo;
+  NetAccessSetInfo = (PVOID) (ULONG) (PVOID16) NetAccessSetInfo;
+  NetAccessAdd     = (PVOID) (ULONG) (PVOID16) NetAccessAdd;
+#endif
+
+  if ((path = _tmalloc(CCHMAXPATH)) == NULL)
+    return FALSE;
+  if ((data = _tmalloc(ACL_BUFFERSIZE)) == NULL)
+    return FALSE;
+  if ((ai = _tmalloc(sizeof(ACCINFO))) == NULL)
+    return -1;
+
+  netapi_avail = TRUE;
+
+  return netapi_avail;
+}
+
+static void acl_mkpath(char *buffer, const char *source)
+{
+  char *ptr;
+  static char cwd[CCHMAXPATH];
+  static U_INT cwdlen;
+  U_INT cdrive;
+  ULONG drivemap;
+
+  if (isalpha(source[0]) && source[1] == ':')
+    buffer[0] = 0; /* fully qualified names */
+  else
+  {
+    if (cwd[0] == 0)
+    {
+      DosQueryCurrentDisk(&cdrive, &drivemap);
+      cwd[0] = (char)(cdrive + '@');
+      cwd[1] = ':';
+      cwd[2] = '\\';
+      cwdlen = sizeof(cwd) - 3;
+      DosQueryCurrentDir(0, cwd + 3, &cwdlen);
+      cwdlen = strlen(cwd);
+    }
+
+    if (source[0] == '/' || source[0] == '\\')
+    {
+      if (source[1] == '/' || source[1] == '\\')
+        buffer[0] = 0; /* UNC names */
+      else
+      {
+        strncpy(buffer, cwd, 2);
+        buffer[2] = 0;
+      }
+    }
+    else
+    {
+      strcpy(buffer, cwd);
+      if (cwd[cwdlen - 1] != '\\' && cwd[cwdlen - 1] != '/')
+        strcat(buffer, "/");
+    }
+  }
+
+  strcat(buffer, source);
+
+  for (ptr = buffer; *ptr; ptr++)
+    if (*ptr == '/')
+      *ptr = '\\';
+
+  if (ptr[-1] == '\\')
+    ptr[-1] = 0;
+
+  strupr(buffer);
+}
+
+static int acl_bin2text(char *data, char *text)
+{
+  ACCINFO *ai;
+  ACCLIST *al;
+  U_INT cnt, offs;
+
+  ai = (ACCINFO *) data;
+  al = (ACCLIST *) (data + sizeof(ACCINFO));
+
+  offs = sprintf(text, "ACL1:%X,%d\n",
+                 ai -> acc_attr, ai -> acc_count);
+
+  for (cnt = 0; cnt < ai -> acc_count; cnt++)
+    offs += sprintf(text + offs, "%s,%X\n",
+                    al[cnt].acl_ugname, al[cnt].acl_access);
+
+  return strlen(text);
+}
+
+int acl_get(char *server, const char *resource, char *buffer)
+{
+  USHORT datalen;
+  PSZ srv = NULL;
+  int rc;
+
+  if (!acl_init())
+    return -1;
+
+  if (server)
+    srv = server;
+
+  acl_mkpath(path, resource);
+  datalen = 0;
+
+  rc = NetAccessGetInfo(srv, path, 1, data, ACL_BUFFERSIZE, &datalen);
+
+  if (rc == 0)
+    acl_bin2text(data, buffer);
+
+  return rc;
+}
+
+static int acl_text2bin(char *data, char *text, char *path)
+{
+  ACCINFO *ai;
+  ACCLIST *al;
+  char *ptr, *ptr2;
+  U_INT cnt;
+
+  ai = (ACCINFO *) data;
+  ai -> acc_resource_name = PTR16(path);
+
+  if (sscanf(text, "ACL1:%hX,%hd",
+             &ai -> acc_attr, &ai -> acc_count) != 2)
+    return ERROR_INVALID_PARAMETER;
+
+  al = (ACCLIST *) (data + sizeof(ACCINFO));
+  ptr = strchr(text, '\n') + 1;
+
+  for (cnt = 0; cnt < ai -> acc_count; cnt++)
+  {
+    ptr2 = strchr(ptr, ',');
+    strncpy(al[cnt].acl_ugname, ptr, ptr2 - ptr);
+    al[cnt].acl_ugname[ptr2 - ptr] = 0;
+    sscanf(ptr2 + 1, "%hx", &al[cnt].acl_access);
+    ptr = strchr(ptr, '\n') + 1;
+  }
+
+  return sizeof(ACCINFO) + ai -> acc_count * sizeof(ACCLIST);
+}
+
+int acl_set(char *server, const char *resource, char *buffer)
+{
+  USHORT datalen;
+  PSZ srv = NULL;
+
+  if (!acl_init())
+    return -1;
+
+  if (server)
+    srv = server;
+
+  acl_mkpath(path, resource);
+
+  ai -> acc_resource_name = PTR16(path);
+  ai -> acc_attr = 0;
+  ai -> acc_count = 0;
+
+  NetAccessAdd(srv, 1, ai, sizeof(ACCINFO));
+  /* Ignore any errors, most probably because ACL already exists. */
+  /* In any such case, try updating the existing ACL. */
+
+  datalen = acl_text2bin(data, buffer, path);
+
+  return NetAccessSetInfo(srv, path, 1, data, datalen, 0);
+}
+
+/* end of os2acl.c */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/process.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,1383 @@
+/*---------------------------------------------------------------------------
+
+  process.c
+
+  This file contains the top-level routines for processing multiple zipfiles.
+
+  Contains:  process_zipfiles()
+             free_G_buffers()
+             do_seekable()
+             find_ecrec()
+             uz_end_central()
+             process_cdir_file_hdr()
+             get_cdir_ent()
+             process_local_file_hdr()
+             ef_scan_for_izux()
+
+  ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#ifdef WINDLL
+#  ifdef POCKET_UNZIP
+#    include "wince/intrface.h"
+#  else
+#    include "windll/windll.h"
+#  endif
+#endif
+
+static int    do_seekable        OF((__GPRO__ int lastchance));
+static int    find_ecrec         OF((__GPRO__ long searchlen));
+
+int files = 0;
+
+static ZCONST char Far CannotAllocateBuffers[] =
+  "error:  cannot allocate unzip buffers\n";
+
+#ifdef SFX
+   static ZCONST char Far CannotFindMyself[] =
+     "unzipsfx:  cannot find myself! [%s]\n";
+
+#else /* !SFX */
+   /* process_zipfiles() strings */
+# if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME))
+     static ZCONST char Far WarnInvalidTZ[] =
+       "Warning: TZ environment variable not found, cannot use UTC times!!\n";
+# endif
+   static ZCONST char Far FilesProcessOK[] =
+     "%d archive%s successfully processed.\n";
+   static ZCONST char Far ArchiveWarning[] =
+     "%d archive%s had warnings but no fatal errors.\n";
+   static ZCONST char Far ArchiveFatalError[] =
+     "%d archive%s had fatal errors.\n";
+   static ZCONST char Far FileHadNoZipfileDir[] =
+     "%d file%s had no zipfile directory.\n";
+   static ZCONST char Far ZipfileWasDir[] = "1 \"zipfile\" was a directory.\n";
+   static ZCONST char Far ManyZipfilesWereDir[] =
+     "%d \"zipfiles\" were directories.\n";
+   static ZCONST char Far NoZipfileFound[] = "No zipfiles found.\n";
+
+   /* do_seekable() strings */
+# ifdef UNIX
+   static ZCONST char Far CannotFindZipfileDirMsg[] =
+     "%s:  cannot find zipfile directory in one of %s or\n\
+        %s%s.zip, and cannot find %s, period.\n";
+   static ZCONST char Far CannotFindEitherZipfile[] =
+     "%s:  cannot find %s, %s.zip or %s.\n";   /* ", so there" removed 970918 */
+# else /* !UNIX */
+# ifndef AMIGA
+   static ZCONST char Far CannotFindWildcardMatch[] =
+     "%s:  cannot find any matches for wildcard specification \"%s\".\n";
+# endif /* !AMIGA */
+   static ZCONST char Far CannotFindZipfileDirMsg[] =
+     "%s:  cannot find zipfile directory in %s,\n\
+        %sand cannot find %s, period.\n";
+   static ZCONST char Far CannotFindEitherZipfile[] =
+     "%s:  cannot find either %s or %s.\n";    /* ", so there" removed 970918 */
+# endif /* ?UNIX */
+   extern ZCONST char Far Zipnfo[];       /* in unzip.c */
+#ifndef WINDLL
+   static ZCONST char Far Unzip[] = "unzip";
+#else
+   static ZCONST char Far Unzip[] = "UnZip DLL";
+#endif
+   static ZCONST char Far MaybeExe[] =
+     "note:  %s may be a plain executable, not an archive\n";
+   static ZCONST char Far CentDirNotInZipMsg[] = "\n\
+   [%s]:\n\
+     Zipfile is disk %u of a multi-disk archive, and this is not the disk on\n\
+     which the central zipfile directory begins (disk %u).\n";
+   static ZCONST char Far EndCentDirBogus[] =
+     "\nwarning [%s]:  end-of-central-directory record claims this\n\
+  is disk %u but that the central directory starts on disk %u; this is a\n\
+  contradiction.  Attempting to process anyway.\n";
+# ifdef NO_MULTIPART
+   static ZCONST char Far NoMultiDiskArcSupport[] =
+     "\nerror [%s]:  zipfile is part of multi-disk archive\n\
+  (sorry, not yet supported).\n";
+   static ZCONST char Far MaybePakBug[] = "warning [%s]:\
+  zipfile claims to be 2nd disk of a 2-part archive;\n\
+  attempting to process anyway.  If no further errors occur, this archive\n\
+  was probably created by PAK v2.51 or earlier.  This bug was reported to\n\
+  NoGate in March 1991 and was supposed to have been fixed by mid-1991; as\n\
+  of mid-1992 it still hadn't been.  (If further errors do occur, archive\n\
+  was probably created by PKZIP 2.04c or later; UnZip does not yet support\n\
+  multi-part archives.)\n";
+# else
+   static ZCONST char Far MaybePakBug[] = "warning [%s]:\
+  zipfile claims to be last disk of a multi-part archive;\n\
+  attempting to process anyway, assuming all parts have been concatenated\n\
+  together in order.  Expect \"errors\" and warnings...true multi-part support\
+\n  doesn't exist yet (coming soon).\n";
+# endif
+   static ZCONST char Far ExtraBytesAtStart[] =
+     "warning [%s]:  %ld extra byte%s at beginning or within zipfile\n\
+  (attempting to process anyway)\n";
+#endif /* ?SFX */
+
+static ZCONST char Far MissingBytes[] =
+  "error [%s]:  missing %ld bytes in zipfile\n\
+  (attempting to process anyway)\n";
+static ZCONST char Far NullCentDirOffset[] =
+  "error [%s]:  NULL central directory offset\n\
+  (attempting to process anyway)\n";
+static ZCONST char Far ZipfileEmpty[] = "warning [%s]:  zipfile is empty\n";
+static ZCONST char Far CentDirStartNotFound[] =
+  "error [%s]:  start of central directory not found;\n\
+  zipfile corrupt.\n%s";
+#ifndef SFX
+   static ZCONST char Far CentDirTooLong[] =
+     "error [%s]:  reported length of central directory is\n\
+  %ld bytes too long (Atari STZip zipfile?  J.H.Holm ZIPSPLIT 1.1\n\
+  zipfile?).  Compensating...\n";
+   static ZCONST char Far CentDirEndSigNotFound[] = "\
+  End-of-central-directory signature not found.  Either this file is not\n\
+  a zipfile, or it constitutes one disk of a multi-part archive.  In the\n\
+  latter case the central directory and zipfile comment will be found on\n\
+  the last disk(s) of this archive.\n";
+#else /* SFX */
+   static ZCONST char Far CentDirEndSigNotFound[] =
+     "  End-of-central-directory signature not found.\n";
+#endif /* ?SFX */
+static ZCONST char Far ZipfileCommTrunc1[] =
+  "\ncaution:  zipfile comment truncated\n";
+
+
+
+
+/*******************************/
+/* Function process_zipfiles() */
+/*******************************/
+
+int process_zipfiles(__G)    /* return PK-type error code */
+    __GDEF
+{
+#ifndef SFX
+    char *lastzipfn = (char *)NULL;
+    int NumWinFiles, NumLoseFiles, NumWarnFiles;
+    int NumMissDirs, NumMissFiles;
+#endif
+    int error=0, error_in_archive=0;
+
+
+/*---------------------------------------------------------------------------
+    Start by allocating buffers and (re)constructing the various PK signature
+    strings.
+  ---------------------------------------------------------------------------*/
+
+    G.inbuf = (uch *)malloc(INBUFSIZ + 4);    /* 4 extra for hold[] (below) */
+    G.outbuf = (uch *)malloc(OUTBUFSIZ + 1);  /* 1 extra for string term. */
+
+    if ((G.inbuf == (uch *)NULL) || (G.outbuf == (uch *)NULL)) {
+        Info(slide, 0x401, ((char *)slide,
+          LoadFarString(CannotAllocateBuffers)));
+        return(PK_MEM);
+    }
+    G.hold = G.inbuf + INBUFSIZ;     /* to check for boundary-spanning sigs */
+#ifndef VMS     /* VMS uses its own buffer scheme for textmode flush(). */
+#ifdef SMALL_MEM
+    G.outbuf2 = G.outbuf+RAWBUFSIZ;  /* never changes */
+#endif
+#endif /* !VMS */
+
+#if 0 /* CRC_32_TAB has been NULLified by CONSTRUCTGLOBALS !!!! */
+    /* allocate the CRC table only later when we know we have a zipfile */
+    CRC_32_TAB = NULL;
+#endif /* 0 */
+
+    /* finish up initialization of magic signature strings */
+    local_hdr_sig[0]  /* = extd_local_sig[0] */  = 0x50;   /* ASCII 'P', */
+    central_hdr_sig[0] = end_central_sig[0] = 0x50;     /* not EBCDIC */
+
+    local_hdr_sig[1]  /* = extd_local_sig[1] */  = 0x4B;   /* ASCII 'K', */
+    central_hdr_sig[1] = end_central_sig[1] = 0x4B;     /* not EBCDIC */
+
+/*---------------------------------------------------------------------------
+    Make sure timezone info is set correctly; localtime() returns GMT on
+    some OSes (e.g., Solaris 2.x) if this isn't done first.  The ifdefs were
+    initially copied from dos_to_unix_time() in fileio.c. probably, they are
+    still too strict; any listed OS that supplies tzset(), regardless of
+    whether the function does anything, should be removed from the ifdefs.
+  ---------------------------------------------------------------------------*/
+
+#if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME))
+#  ifndef VALID_TIMEZONE
+#     define VALID_TIMEZONE(tmp) \
+             (((tmp = getenv("TZ")) != NULL) && (*tmp != '\0'))
+#  endif
+    {
+        char *p;
+        G.tz_is_valid = VALID_TIMEZONE(p);
+#  ifndef SFX
+        if (!G.tz_is_valid) {
+            Info(slide, 0x401, ((char *)slide, LoadFarString(WarnInvalidTZ)));
+            error_in_archive = error = PK_WARN;
+        }
+#  endif /* !SFX */
+    }
+#endif /* IZ_CHECK_TZ && USE_EF_UT_TIME */
+
+/* For systems that do not have tzset() but supply this function using another
+   name (_tzset() or something similar), an appropiate "#define tzset ..."
+   should be added to the system specifc configuration section.  */
+#if (!defined(T20_VMS) && !defined(MACOS) && !defined(RISCOS) && !defined(QDOS))
+#if (!defined(BSD) && !defined(MTS) && !defined(CMS_MVS) && !defined(TANDEM))
+    tzset();
+#endif
+#endif
+
+/*---------------------------------------------------------------------------
+    Match (possible) wildcard zipfile specification with existing files and
+    attempt to process each.  If no hits, try again after appending ".zip"
+    suffix.  If still no luck, give up.
+  ---------------------------------------------------------------------------*/
+
+#ifdef SFX
+    if ((error = do_seekable(__G__ 0)) == PK_NOZIP) {
+#ifdef EXE_EXTENSION
+        int len=strlen(G.argv0);
+
+        /* append .exe if appropriate; also .sfx? */
+        if ( (G.zipfn = (char *)malloc(len+sizeof(EXE_EXTENSION))) !=
+             (char *)NULL ) {
+            strcpy(G.zipfn, G.argv0);
+            strcpy(G.zipfn+len, EXE_EXTENSION);
+            error = do_seekable(__G__ 0);
+            free(G.zipfn);
+            G.zipfn = G.argv0;  /* for "cannot find myself" message only */
+        }
+#endif /* EXE_EXTENSION */
+#ifdef WIN32
+        G.zipfn = G.argv0;  /* for "cannot find myself" message only */
+#endif
+    }
+    if (error) {
+        if (error == IZ_DIR)
+            error_in_archive = PK_NOZIP;
+        else
+            error_in_archive = error;
+        if (error == PK_NOZIP)
+            Info(slide, 1, ((char *)slide, LoadFarString(CannotFindMyself),
+              G.zipfn));
+    }
+
+#else /* !SFX */
+    NumWinFiles = NumLoseFiles = NumWarnFiles = 0;
+    files = NumMissDirs = NumMissFiles = 0;
+
+    while ((G.zipfn = do_wild(__G__ G.wildzipfn)) != (char *)NULL) {
+        Trace((stderr, "do_wild( %s ) returns %s\n", G.wildzipfn, G.zipfn));
+
+        lastzipfn = G.zipfn;
+
+        /* print a blank line between the output of different zipfiles */
+        if (!uO.qflag  &&  error != PK_NOZIP  &&  error != IZ_DIR
+#ifdef TIMESTAMP
+            && (!uO.T_flag || uO.zipinfo_mode)
+#endif
+            && (NumWinFiles+NumLoseFiles+NumWarnFiles+NumMissFiles) > 0)
+            (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
+
+        if ((error = do_seekable(__G__ 0)) == PK_WARN)
+            ++NumWarnFiles;
+        else if (error == IZ_DIR)
+            ++NumMissDirs;
+        else if (error == PK_NOZIP)
+            ++NumMissFiles;
+        else if (error)
+            ++NumLoseFiles;
+        else
+			++NumWinFiles;
+
+        if(!uO.vflag)
+			files = NumWinFiles;
+
+        if (error != IZ_DIR && error > error_in_archive)
+            error_in_archive = error;
+        Trace((stderr, "do_seekable(0) returns %d\n", error));
+#ifdef WINDLL
+        if (error == IZ_CTRLC) {
+            free_G_buffers(__G);
+            return error;
+        }
+#endif
+
+    } /* end while-loop (wildcard zipfiles) */
+
+    if ((NumWinFiles + NumWarnFiles + NumLoseFiles) == 0  &&
+        (NumMissDirs + NumMissFiles) == 1  &&  lastzipfn != (char *)NULL)
+    {
+        NumMissDirs = NumMissFiles = 0;
+        if (error_in_archive == PK_NOZIP)
+            error_in_archive = PK_COOL;
+
+#if (!defined(UNIX) && !defined(AMIGA)) /* filenames with wildcard characters */
+        if (iswild(G.wildzipfn))
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(CannotFindWildcardMatch), uO.zipinfo_mode?
+              LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
+              G.wildzipfn));
+        else
+#endif
+        {
+            char *p = lastzipfn + strlen(lastzipfn);
+
+            G.zipfn = lastzipfn;
+            strcpy(p, ZSUFX);
+
+#if defined(UNIX) || defined(QDOS)
+   /* only Unix has case-sensitive filesystems */
+   /* Well FlexOS (sometimes) also has them,  but support is per media */
+   /* and a pig to code for,  so treat as case insensitive for now */
+   /* we do this under QDOS to check for .zip as well as _zip */
+            if ((error = do_seekable(__G__ 0)) == PK_NOZIP || error == IZ_DIR) {
+                if (error == IZ_DIR)
+                    ++NumMissDirs;
+                strcpy(p, ALT_ZSUFX);
+                error = do_seekable(__G__ 1);
+            }
+#else
+            error = do_seekable(__G__ 1);
+#endif
+            if (error == PK_WARN)   /* GRR: make this a switch/case stmt ... */
+                ++NumWarnFiles;
+            else if (error == IZ_DIR)
+                ++NumMissDirs;
+            else if (error == PK_NOZIP)
+                /* increment again => bug: "1 file had no zipfile directory." */
+                /* ++NumMissFiles */ ;
+            else if (error)
+                ++NumLoseFiles;
+            else
+                ++NumWinFiles;
+
+            if (error > error_in_archive)
+                error_in_archive = error;
+            Trace((stderr, "do_seekable(1) returns %d\n", error));
+#ifdef WINDLL
+            if (error == IZ_CTRLC) {
+                free_G_buffers(__G);
+                return error;
+            }
+#endif
+        }
+    }
+#endif /* ?SFX */
+
+/*---------------------------------------------------------------------------
+    Print summary of all zipfiles, assuming zipfile spec was a wildcard (no
+    need for a summary if just one zipfile).
+  ---------------------------------------------------------------------------*/
+
+#ifndef SFX
+    if (iswild(G.wildzipfn) && uO.qflag < 3
+#ifdef TIMESTAMP
+        && !(uO.T_flag && uO.qflag && !uO.zipinfo_mode)
+#endif
+                                                    )
+    {
+        if ((NumMissFiles + NumLoseFiles + NumWarnFiles > 0 || NumWinFiles != 1)
+#ifdef TIMESTAMP
+            && !(uO.T_flag && !uO.zipinfo_mode)
+#endif
+            && !(uO.tflag && uO.qflag > 1))
+            (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0x401);
+        if ((NumWinFiles > 1) || (NumWinFiles == 1 &&
+            NumMissDirs + NumMissFiles + NumLoseFiles + NumWarnFiles > 0))
+            Info(slide, 0x401, ((char *)slide, LoadFarString(FilesProcessOK),
+              NumWinFiles, (NumWinFiles == 1)? " was" : "s were"));
+        if (NumWarnFiles > 0)
+            Info(slide, 0x401, ((char *)slide, LoadFarString(ArchiveWarning),
+              NumWarnFiles, (NumWarnFiles == 1)? "" : "s"));
+        if (NumLoseFiles > 0)
+            Info(slide, 0x401, ((char *)slide, LoadFarString(ArchiveFatalError),
+              NumLoseFiles, (NumLoseFiles == 1)? "" : "s"));
+        if (NumMissFiles > 0)
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(FileHadNoZipfileDir), NumMissFiles,
+              (NumMissFiles == 1)? "" : "s"));
+        if (NumMissDirs == 1)
+            Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileWasDir)));
+        else if (NumMissDirs > 0)
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(ManyZipfilesWereDir), NumMissDirs));
+        if (NumWinFiles + NumLoseFiles + NumWarnFiles == 0)
+            Info(slide, 0x401, ((char *)slide, LoadFarString(NoZipfileFound)));
+    }
+#endif /* !SFX */
+
+    /* free allocated memory */
+    free_G_buffers(__G);
+
+    return error_in_archive;
+
+} /* end function process_zipfiles() */
+
+
+
+
+
+/*****************************/
+/* Function free_G_buffers() */
+/*****************************/
+
+void free_G_buffers(__G)     /* releases all memory allocated in global vars */
+    __GDEF
+{
+    inflate_free(__G);
+    checkdir(__G__ (char *)NULL, END);
+
+#ifdef DYNALLOC_CRCTAB
+    if (CRC_32_TAB) {
+        free_crc_table();
+        CRC_32_TAB = NULL;
+    }
+#endif
+
+   if (G.key != (char *)NULL) {
+        free(G.key);
+        G.key = (char *)NULL;
+   }
+
+#if (!defined(VMS) && !defined(SMALL_MEM))
+    /* VMS uses its own buffer scheme for textmode flush() */
+    if (G.outbuf2) {
+        free(G.outbuf2);   /* malloc'd ONLY if unshrink and -a */
+        G.outbuf2 = (uch *)NULL;
+    }
+#endif
+
+    if (G.outbuf)
+        free(G.outbuf);
+    if (G.inbuf)
+        free(G.inbuf);
+    G.inbuf = G.outbuf = (uch *)NULL;
+
+#ifdef MALLOC_WORK
+    if (G.area.Slide) {
+        free(G.area.Slide);
+        G.area.Slide = (uch *)NULL;
+    }
+#endif
+
+} /* end function free_G_buffers() */
+
+
+
+
+
+/**************************/
+/* Function do_seekable() */
+/**************************/
+
+static int do_seekable(__G__ lastchance)        /* return PK-type error code */
+    __GDEF
+    int lastchance;
+{
+#ifndef SFX
+    /* static int no_ecrec = FALSE;  SKM: moved to globals.h */
+    int maybe_exe=FALSE;
+    int too_weird_to_continue=FALSE;
+#ifdef TIMESTAMP
+    time_t uxstamp;
+    unsigned nmember = 0;
+#endif
+#endif
+    int error=0, error_in_archive;
+
+
+/*---------------------------------------------------------------------------
+    Open the zipfile for reading in BINARY mode to prevent CR/LF translation,
+    which would corrupt the bit streams.
+  ---------------------------------------------------------------------------*/
+
+    if (SSTAT(G.zipfn, &G.statbuf) ||
+        (error = S_ISDIR(G.statbuf.st_mode)) != 0)
+    {
+#ifndef SFX
+        if (lastchance) {
+#if defined(UNIX) || defined(QDOS)
+            if (G.no_ecrec)
+                Info(slide, 1, ((char *)slide,
+                  LoadFarString(CannotFindZipfileDirMsg), uO.zipinfo_mode?
+                  LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
+                  G.wildzipfn, uO.zipinfo_mode? "  " : "", G.wildzipfn,
+                  G.zipfn));
+            else
+                Info(slide, 1, ((char *)slide,
+                  LoadFarString(CannotFindEitherZipfile), uO.zipinfo_mode?
+                  LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
+                  G.wildzipfn, G.wildzipfn, G.zipfn));
+#else /* !UNIX */
+            if (G.no_ecrec)
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(CannotFindZipfileDirMsg), uO.zipinfo_mode?
+                  LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
+                  G.wildzipfn, uO.zipinfo_mode? "  " : "", G.zipfn));
+            else
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(CannotFindEitherZipfile), uO.zipinfo_mode?
+                  LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
+                  G.wildzipfn, G.zipfn));
+#endif /* ?UNIX */
+        }
+#endif /* !SFX */
+        return error? IZ_DIR : PK_NOZIP;
+    }
+    G.ziplen = G.statbuf.st_size;
+
+#ifndef SFX
+#if defined(UNIX) || defined(DOS_OS2_W32)
+    if (G.statbuf.st_mode & S_IEXEC)   /* no extension on Unix exes:  might */
+        maybe_exe = TRUE;               /*  find unzip, not unzip.zip; etc. */
+#endif
+#endif /* !SFX */
+
+#ifdef VMS
+    if (check_format(__G))              /* check for variable-length format */
+        return PK_ERR;
+#endif
+
+    if (open_input_file(__G))   /* this should never happen, given */
+        return PK_NOZIP;        /*  the stat() test above, but... */
+
+/*---------------------------------------------------------------------------
+    Find and process the end-of-central-directory header.  UnZip need only
+    check last 65557 bytes of zipfile:  comment may be up to 65535, end-of-
+    central-directory record is 18 bytes, and signature itself is 4 bytes;
+    add some to allow for appended garbage.  Since ZipInfo is often used as
+    a debugging tool, search the whole zipfile if zipinfo_mode is true.
+  ---------------------------------------------------------------------------*/
+
+    /* initialize the CRC table pointer (once) */
+    if (CRC_32_TAB == NULL) {
+        if ((CRC_32_TAB = get_crc_table()) == NULL)
+            return PK_MEM;
+    }
+
+#if (!defined(SFX) || defined(SFX_EXDIR))
+    /* check out if specified extraction root directory exists */
+    if (uO.exdir != (char *)NULL && G.extract_flag) {
+        G.create_dirs = !uO.fflag;
+        if ((error = checkdir(__G__ uO.exdir, ROOT)) > 2)
+            return error;   /* out of memory, or file in way */
+    }
+#endif /* !SFX || SFX_EXDIR */
+
+    G.cur_zipfile_bufstart = 0;
+    G.inptr = G.inbuf;
+
+#if (!defined(WINDLL) && !defined(SFX))
+#ifdef TIMESTAMP
+    if (!uO.zipinfo_mode && !uO.qflag && !uO.T_flag)
+#else
+    if (!uO.zipinfo_mode && !uO.qflag)
+#endif
+#ifdef WIN32    /* Win32 console may require codepage conversion for G.zipfn */
+        Info(slide, 0, ((char *)slide, "Archive:  %s\n", FnFilter1(G.zipfn)));
+#else
+        Info(slide, 0, ((char *)slide, "Archive:  %s\n", G.zipfn));
+#endif
+#endif /* !WINDLL && !SFX */
+
+    if ((
+#ifndef NO_ZIPINFO
+         uO.zipinfo_mode &&
+          ((error_in_archive = find_ecrec(__G__ G.ziplen)) != 0 ||
+          (error_in_archive = zi_end_central(__G)) > PK_WARN))
+        || (!uO.zipinfo_mode &&
+#endif
+          ((error_in_archive = find_ecrec(__G__ MIN(G.ziplen,66000L))) != 0 ||
+          (error_in_archive = uz_end_central(__G)) > PK_WARN)))
+    {
+        CLOSE_INFILE();
+
+#ifdef SFX
+        ++lastchance;   /* avoid picky compiler warnings */
+        return error_in_archive;
+#else
+        if (maybe_exe)
+            Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeExe),
+            G.zipfn));
+        if (lastchance)
+            return error_in_archive;
+        else {
+            G.no_ecrec = TRUE;    /* assume we found wrong file:  e.g., */
+            return PK_NOZIP;       /*  unzip instead of unzip.zip */
+        }
+#endif /* ?SFX */
+    }
+
+    if ((uO.zflag > 0) && !uO.zipinfo_mode) { /* unzip: zflag = comment ONLY */
+        CLOSE_INFILE();
+        return error_in_archive;
+    }
+
+/*---------------------------------------------------------------------------
+    Test the end-of-central-directory info for incompatibilities (multi-disk
+    archives) or inconsistencies (missing or extra bytes in zipfile).
+  ---------------------------------------------------------------------------*/
+
+#ifdef NO_MULTIPART
+    error = !uO.zipinfo_mode && (G.ecrec.number_this_disk == 1) &&
+            (G.ecrec.num_disk_start_cdir == 1);
+#else
+    error = !uO.zipinfo_mode && (G.ecrec.number_this_disk != 0);
+#endif
+
+#ifndef SFX
+    if (uO.zipinfo_mode &&
+        G.ecrec.number_this_disk != G.ecrec.num_disk_start_cdir)
+    {
+        if (G.ecrec.number_this_disk > G.ecrec.num_disk_start_cdir) {
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(CentDirNotInZipMsg), G.zipfn,
+              G.ecrec.number_this_disk, G.ecrec.num_disk_start_cdir));
+            error_in_archive = PK_FIND;
+            too_weird_to_continue = TRUE;
+        } else {
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(EndCentDirBogus), G.zipfn,
+              G.ecrec.number_this_disk, G.ecrec.num_disk_start_cdir));
+            error_in_archive = PK_WARN;
+        }
+#ifdef NO_MULTIPART   /* concatenation of multiple parts works in some cases */
+    } else if (!uO.zipinfo_mode && !error && G.ecrec.number_this_disk != 0) {
+        Info(slide, 0x401, ((char *)slide, LoadFarString(NoMultiDiskArcSupport),
+          G.zipfn));
+        error_in_archive = PK_FIND;
+        too_weird_to_continue = TRUE;
+#endif
+    }
+
+    if (!too_weird_to_continue) {  /* (relatively) normal zipfile:  go for it */
+        if (error) {
+            Info(slide, 0x401, ((char *)slide, LoadFarString(MaybePakBug),
+              G.zipfn));
+            error_in_archive = PK_WARN;
+        }
+#endif /* !SFX */
+        if ((G.extra_bytes = G.real_ecrec_offset-G.expect_ecrec_offset) <
+            (LONGINT)0)
+        {
+            Info(slide, 0x401, ((char *)slide, LoadFarString(MissingBytes),
+              G.zipfn, (long)(-G.extra_bytes)));
+            error_in_archive = PK_ERR;
+        } else if (G.extra_bytes > 0) {
+            if ((G.ecrec.offset_start_central_directory == 0) &&
+                (G.ecrec.size_central_directory != 0))   /* zip 1.5 -go bug */
+            {
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(NullCentDirOffset), G.zipfn));
+                G.ecrec.offset_start_central_directory = G.extra_bytes;
+                G.extra_bytes = 0;
+                error_in_archive = PK_ERR;
+            }
+#ifndef SFX
+            else {
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(ExtraBytesAtStart), G.zipfn,
+                  (long)G.extra_bytes, (G.extra_bytes == 1)? "":"s"));
+                error_in_archive = PK_WARN;
+            }
+#endif /* !SFX */
+        }
+
+    /*-----------------------------------------------------------------------
+        Check for empty zipfile and exit now if so.
+      -----------------------------------------------------------------------*/
+
+        if (G.expect_ecrec_offset==0L && G.ecrec.size_central_directory==0) {
+            if (uO.zipinfo_mode)
+                Info(slide, 0, ((char *)slide, "%sEmpty zipfile.\n",
+                  uO.lflag>9? "\n  " : ""));
+            else
+                Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileEmpty),
+                                    G.zipfn));
+            CLOSE_INFILE();
+            return (error_in_archive > PK_WARN)? error_in_archive : PK_WARN;
+        }
+
+    /*-----------------------------------------------------------------------
+        Compensate for missing or extra bytes, and seek to where the start
+        of central directory should be.  If header not found, uncompensate
+        and try again (necessary for at least some Atari archives created
+        with STZip, as well as archives created by J.H. Holm's ZIPSPLIT 1.1).
+      -----------------------------------------------------------------------*/
+
+        ZLSEEK( G.ecrec.offset_start_central_directory )
+#ifdef OLD_SEEK_TEST
+        if (readbuf(G.sig, 4) == 0) {
+            CLOSE_INFILE();
+            return PK_ERR;  /* file may be locked, or possibly disk error(?) */
+        }
+        if (strncmp(G.sig, central_hdr_sig, 4))
+#else
+        if ((readbuf(__G__ G.sig, 4) == 0) ||
+             strncmp(G.sig, central_hdr_sig, 4))
+#endif
+        {
+#ifndef SFX
+            long tmp = G.extra_bytes;
+#endif
+
+            G.extra_bytes = 0;
+            ZLSEEK( G.ecrec.offset_start_central_directory )
+            if ((readbuf(__G__ G.sig, 4) == 0) ||
+                strncmp(G.sig, central_hdr_sig, 4))
+            {
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(CentDirStartNotFound), G.zipfn,
+                  LoadFarStringSmall(ReportMsg)));
+                CLOSE_INFILE();
+                return PK_BADERR;
+            }
+#ifndef SFX
+            Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirTooLong),
+              G.zipfn, -tmp));
+#endif
+            error_in_archive = PK_ERR;
+        }
+
+    /*-----------------------------------------------------------------------
+        Seek to the start of the central directory one last time, since we
+        have just read the first entry's signature bytes; then list, extract
+        or test member files as instructed, and close the zipfile.
+      -----------------------------------------------------------------------*/
+
+        Trace((stderr, "about to extract/list files (error = %d)\n",
+          error_in_archive));
+
+        ZLSEEK( G.ecrec.offset_start_central_directory )
+
+#ifdef DLL
+        /* G.fValidate is used only to look at an archive to see if
+           it appears to be a valid archive.  There is no interest
+           in what the archive contains, nor in validating that the
+           entries in the archive are in good condition.  This is
+           currently used only in the Windows DLLs for purposes of
+           checking archives within an archive to determine whether
+           or not to display the inner archives.
+         */
+        if (!G.fValidate)
+#endif
+        {
+#ifndef NO_ZIPINFO
+            if (uO.zipinfo_mode)
+                error = zipinfo(__G);                     /* ZIPINFO 'EM */
+            else
+#endif
+#ifndef SFX
+#ifdef TIMESTAMP
+            if (uO.T_flag)
+                error = get_time_stamp(__G__ &uxstamp, &nmember);
+            else
+#endif
+            if (uO.vflag && !uO.tflag && !uO.cflag)
+                error = list_files(__G);              /* LIST 'EM */
+            else
+#endif /* !SFX */
+                error = extract_or_test_files(__G);   /* EXTRACT OR TEST 'EM */
+
+            Trace((stderr, "done with extract/list files (error = %d)\n",
+                   error));
+        }
+
+        if (error > error_in_archive)   /* don't overwrite stronger error */
+            error_in_archive = error;   /*  with (for example) a warning */
+#ifndef SFX
+    } /* end if (!too_weird_to_continue) */
+#endif
+
+    CLOSE_INFILE();
+
+#ifdef TIMESTAMP
+    if (uO.T_flag && !uO.zipinfo_mode && (nmember > 0)) {
+# ifdef WIN32
+        if (stamp_file(__G__ G.zipfn, uxstamp)) {       /* TIME-STAMP 'EM */
+# else
+        if (stamp_file(G.zipfn, uxstamp)) {             /* TIME-STAMP 'EM */
+# endif
+            Info(slide, 0x201, ((char *)slide,
+              "warning:  cannot set time for %s\n", G.zipfn));
+            if (error_in_archive < PK_WARN)
+                error_in_archive = PK_WARN;
+        }
+    }
+#endif
+    return error_in_archive;
+
+} /* end function do_seekable() */
+
+
+
+
+
+/*************************/
+/* Function find_ecrec() */
+/*************************/
+
+static int find_ecrec(__G__ searchlen)          /* return PK-class error */
+    __GDEF
+    long searchlen;
+{
+    int i, numblks, found=FALSE;
+    LONGINT tail_len;
+    ec_byte_rec byterec;
+
+
+/*---------------------------------------------------------------------------
+    Treat case of short zipfile separately.
+  ---------------------------------------------------------------------------*/
+
+    if (G.ziplen <= INBUFSIZ) {
+        lseek(G.zipfd, 0L, SEEK_SET);
+        if ((G.incnt = read(G.zipfd,(char *)G.inbuf,(unsigned int)G.ziplen))
+            == (int)G.ziplen)
+
+            /* 'P' must be at least 22 bytes from end of zipfile */
+            for (G.inptr = G.inbuf+(int)G.ziplen-22;  G.inptr >= G.inbuf;
+                 --G.inptr)
+                if ((native(*G.inptr) == 'P')  &&
+                     !strncmp((char *)G.inptr, end_central_sig, 4)) {
+                    G.incnt -= (int)(G.inptr - G.inbuf);
+                    found = TRUE;
+                    break;
+                }
+
+/*---------------------------------------------------------------------------
+    Zipfile is longer than INBUFSIZ:  may need to loop.  Start with short
+    block at end of zipfile (if not TOO short).
+  ---------------------------------------------------------------------------*/
+
+    } else {
+        if ((tail_len = G.ziplen % INBUFSIZ) > ECREC_SIZE) {
+#ifdef USE_STRM_INPUT
+            fseek((FILE *)G.zipfd, G.ziplen-tail_len, SEEK_SET);
+            G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd);
+#else /* !USE_STRM_INPUT */
+            G.cur_zipfile_bufstart = lseek(G.zipfd, G.ziplen-tail_len,
+              SEEK_SET);
+#endif /* ?USE_STRM_INPUT */
+            if ((G.incnt = read(G.zipfd, (char *)G.inbuf,
+                (unsigned int)tail_len)) != (int)tail_len)
+                goto fail;      /* it's expedient... */
+
+            /* 'P' must be at least 22 bytes from end of zipfile */
+            for (G.inptr = G.inbuf+(int)tail_len-22;  G.inptr >= G.inbuf;
+                 --G.inptr)
+                if ((native(*G.inptr) == 'P')  &&
+                     !strncmp((char *)G.inptr, end_central_sig, 4)) {
+                    G.incnt -= (int)(G.inptr - G.inbuf);
+                    found = TRUE;
+                    break;
+                }
+            /* sig may span block boundary: */
+            strncpy((char *)G.hold, (char *)G.inbuf, 3);
+        } else
+            G.cur_zipfile_bufstart = G.ziplen - tail_len;
+
+    /*-----------------------------------------------------------------------
+        Loop through blocks of zipfile data, starting at the end and going
+        toward the beginning.  In general, need not check whole zipfile for
+        signature, but may want to do so if testing.
+      -----------------------------------------------------------------------*/
+
+        numblks = (int)((searchlen - tail_len + (INBUFSIZ-1)) / INBUFSIZ);
+        /*               ==amount=   ==done==   ==rounding==    =blksiz=  */
+
+        for (i = 1;  !found && (i <= numblks);  ++i) {
+            G.cur_zipfile_bufstart -= INBUFSIZ;
+            lseek(G.zipfd, G.cur_zipfile_bufstart, SEEK_SET);
+            if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ))
+                != INBUFSIZ)
+                break;          /* fall through and fail */
+
+            for (G.inptr = G.inbuf+INBUFSIZ-1;  G.inptr >= G.inbuf;
+                 --G.inptr)
+                if ((native(*G.inptr) == 'P')  &&
+                     !strncmp((char *)G.inptr, end_central_sig, 4)) {
+                    G.incnt -= (int)(G.inptr - G.inbuf);
+                    found = TRUE;
+                    break;
+                }
+            /* sig may span block boundary: */
+            strncpy((char *)G.hold, (char *)G.inbuf, 3);
+        }
+    } /* end if (ziplen > INBUFSIZ) */
+
+/*---------------------------------------------------------------------------
+    Searched through whole region where signature should be without finding
+    it.  Print informational message and die a horrible death.
+  ---------------------------------------------------------------------------*/
+
+fail:
+    if (!found) {
+        if (uO.qflag || uO.zipinfo_mode)
+            Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn));
+        Info(slide, 0x401, ((char *)slide,
+          LoadFarString(CentDirEndSigNotFound)));
+        return PK_ERR;   /* failed */
+    }
+
+/*---------------------------------------------------------------------------
+    Found the signature, so get the end-central data before returning.  Do
+    any necessary machine-type conversions (byte ordering, structure padding
+    compensation) by reading data into character array and copying to struct.
+  ---------------------------------------------------------------------------*/
+
+    G.real_ecrec_offset = G.cur_zipfile_bufstart + (G.inptr-G.inbuf);
+#ifdef TEST
+    pipeit("\n  found end-of-central-dir signature at offset %ld (%.8lXh)\n",
+      G.real_ecrec_offset, G.real_ecrec_offset);
+    pipeit("    from beginning of file; offset %d (%.4Xh) within block\n",
+      G.inptr-G.inbuf, G.inptr-G.inbuf);
+#endif
+
+    if (readbuf(__G__ (char *)byterec, ECREC_SIZE+4) == 0)
+        return PK_EOF;
+
+    G.ecrec.number_this_disk =
+      makeword(&byterec[NUMBER_THIS_DISK]);
+    G.ecrec.num_disk_start_cdir =
+      makeword(&byterec[NUM_DISK_WITH_START_CENTRAL_DIR]);
+    G.ecrec.num_entries_centrl_dir_ths_disk =
+      makeword(&byterec[NUM_ENTRIES_CENTRL_DIR_THS_DISK]);
+    G.ecrec.total_entries_central_dir =
+      makeword(&byterec[TOTAL_ENTRIES_CENTRAL_DIR]);
+    G.ecrec.size_central_directory =
+      makelong(&byterec[SIZE_CENTRAL_DIRECTORY]);
+    G.ecrec.offset_start_central_directory =
+      makelong(&byterec[OFFSET_START_CENTRAL_DIRECTORY]);
+    G.ecrec.zipfile_comment_length =
+      makeword(&byterec[ZIPFILE_COMMENT_LENGTH]);
+
+    G.expect_ecrec_offset = G.ecrec.offset_start_central_directory +
+                          G.ecrec.size_central_directory;
+    return PK_COOL;
+
+} /* end function find_ecrec() */
+
+
+
+
+
+/*****************************/
+/* Function uz_end_central() */
+/*****************************/
+
+int uz_end_central(__G)    /* return PK-type error code */
+    __GDEF
+{
+    int error = PK_COOL;
+
+
+/*---------------------------------------------------------------------------
+    Get the zipfile comment (up to 64KB long), if any, and print it out.
+    Then position the file pointer to the beginning of the central directory
+    and fill buffer.
+  ---------------------------------------------------------------------------*/
+
+#ifdef WINDLL
+    /* for comment button: */
+    if ((!G.fValidate) && (G.lpUserFunctions != NULL))
+       G.lpUserFunctions->cchComment = G.ecrec.zipfile_comment_length;
+    if (G.ecrec.zipfile_comment_length && (uO.zflag > 0))
+#else /* !WINDLL */
+    if (G.ecrec.zipfile_comment_length && (uO.zflag > 0 ||
+        (uO.zflag == 0 &&
+#ifdef TIMESTAMP
+                          !uO.T_flag &&
+#endif
+                                        !uO.qflag)))
+#endif /* ?WINDLL */
+    {
+        if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) {
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(ZipfileCommTrunc1)));
+            error = PK_WARN;
+        }
+    }
+    return error;
+
+} /* end function uz_end_central() */
+
+
+
+
+
+/************************************/
+/* Function process_cdir_file_hdr() */
+/************************************/
+
+int process_cdir_file_hdr(__G)    /* return PK-type error code */
+    __GDEF
+{
+    int error;
+
+
+/*---------------------------------------------------------------------------
+    Get central directory info, save host and method numbers, and set flag
+    for lowercase conversion of filename, depending on the OS from which the
+    file is coming.
+  ---------------------------------------------------------------------------*/
+
+    if ((error = get_cdir_ent(__G)) != 0)
+        return error;
+
+    G.pInfo->hostnum = MIN(G.crec.version_made_by[1], NUM_HOSTS);
+/*  extnum = MIN(crec.version_needed_to_extract[1], NUM_HOSTS); */
+
+    G.pInfo->lcflag = 0;
+    if (uO.L_flag)            /* user specified case-conversion */
+        switch (G.pInfo->hostnum) {
+            case FS_FAT_:     /* PKZIP and zip -k store in uppercase */
+            case CPM_:        /* like MS-DOS, right? */
+            case VM_CMS_:     /* all caps? */
+            case MVS_:        /* all caps? */
+            case TANDEM_:
+            case TOPS20_:
+            case VMS_:        /* our Zip uses lowercase, but ASi's doesn't */
+        /*  case Z_SYSTEM_:   ? */
+        /*  case QDOS_:       ? */
+                G.pInfo->lcflag = 1;   /* convert filename to lowercase */
+                break;
+
+            default:     /* AMIGA_, FS_HPFS_, FS_NTFS_, MAC_, UNIX_, ATARI_, */
+                break;   /*  FS_VFAT_, BEOS_ (Z_SYSTEM_):  no conversion */
+        }
+
+    /* do Amigas (AMIGA_) also have volume labels? */
+    if (IS_VOLID(G.crec.external_file_attributes) &&
+        (G.pInfo->hostnum == FS_FAT_ || G.pInfo->hostnum == FS_HPFS_ ||
+         G.pInfo->hostnum == FS_NTFS_ || G.pInfo->hostnum == ATARI_))
+    {
+        G.pInfo->vollabel = TRUE;
+        G.pInfo->lcflag = 0;        /* preserve case of volume labels */
+    } else
+        G.pInfo->vollabel = FALSE;
+
+    return PK_COOL;
+
+} /* end function process_cdir_file_hdr() */
+
+
+
+
+
+/***************************/
+/* Function get_cdir_ent() */
+/***************************/
+
+int get_cdir_ent(__G)   /* return PK-type error code */
+    __GDEF
+{
+    cdir_byte_hdr byterec;
+
+
+/*---------------------------------------------------------------------------
+    Read the next central directory entry and do any necessary machine-type
+    conversions (byte ordering, structure padding compensation--do so by
+    copying the data from the array into which it was read (byterec) to the
+    usable struct (crec)).
+  ---------------------------------------------------------------------------*/
+
+    if (readbuf(__G__ (char *)byterec, CREC_SIZE) == 0)
+        return PK_EOF;
+
+    G.crec.version_made_by[0] = byterec[C_VERSION_MADE_BY_0];
+    G.crec.version_made_by[1] = byterec[C_VERSION_MADE_BY_1];
+    G.crec.version_needed_to_extract[0] =
+      byterec[C_VERSION_NEEDED_TO_EXTRACT_0];
+    G.crec.version_needed_to_extract[1] =
+      byterec[C_VERSION_NEEDED_TO_EXTRACT_1];
+
+    G.crec.general_purpose_bit_flag =
+      makeword(&byterec[C_GENERAL_PURPOSE_BIT_FLAG]);
+    G.crec.compression_method =
+      makeword(&byterec[C_COMPRESSION_METHOD]);
+    G.crec.last_mod_dos_datetime =
+      makelong(&byterec[C_LAST_MOD_DOS_DATETIME]);
+    G.crec.crc32 =
+      makelong(&byterec[C_CRC32]);
+    G.crec.csize =
+      makelong(&byterec[C_COMPRESSED_SIZE]);
+    G.crec.ucsize =
+      makelong(&byterec[C_UNCOMPRESSED_SIZE]);
+    G.crec.filename_length =
+      makeword(&byterec[C_FILENAME_LENGTH]);
+    G.crec.extra_field_length =
+      makeword(&byterec[C_EXTRA_FIELD_LENGTH]);
+    G.crec.file_comment_length =
+      makeword(&byterec[C_FILE_COMMENT_LENGTH]);
+    G.crec.disk_number_start =
+      makeword(&byterec[C_DISK_NUMBER_START]);
+    G.crec.internal_file_attributes =
+      makeword(&byterec[C_INTERNAL_FILE_ATTRIBUTES]);
+    G.crec.external_file_attributes =
+      makelong(&byterec[C_EXTERNAL_FILE_ATTRIBUTES]);  /* LONG, not word! */
+    G.crec.relative_offset_local_header =
+      makelong(&byterec[C_RELATIVE_OFFSET_LOCAL_HEADER]);
+
+    return PK_COOL;
+
+} /* end function get_cdir_ent() */
+
+
+
+
+
+/*************************************/
+/* Function process_local_file_hdr() */
+/*************************************/
+
+int process_local_file_hdr(__G)    /* return PK-type error code */
+    __GDEF
+{
+    local_byte_hdr byterec;
+
+
+/*---------------------------------------------------------------------------
+    Read the next local file header and do any necessary machine-type con-
+    versions (byte ordering, structure padding compensation--do so by copy-
+    ing the data from the array into which it was read (byterec) to the
+    usable struct (lrec)).
+  ---------------------------------------------------------------------------*/
+
+    if (readbuf(__G__ (char *)byterec, LREC_SIZE) == 0)
+        return PK_EOF;
+
+    G.lrec.version_needed_to_extract[0] =
+      byterec[L_VERSION_NEEDED_TO_EXTRACT_0];
+    G.lrec.version_needed_to_extract[1] =
+      byterec[L_VERSION_NEEDED_TO_EXTRACT_1];
+
+    G.lrec.general_purpose_bit_flag =
+      makeword(&byterec[L_GENERAL_PURPOSE_BIT_FLAG]);
+    G.lrec.compression_method = makeword(&byterec[L_COMPRESSION_METHOD]);
+    G.lrec.last_mod_dos_datetime = makelong(&byterec[L_LAST_MOD_DOS_DATETIME]);
+    G.lrec.crc32 = makelong(&byterec[L_CRC32]);
+    G.lrec.csize = makelong(&byterec[L_COMPRESSED_SIZE]);
+    G.lrec.ucsize = makelong(&byterec[L_UNCOMPRESSED_SIZE]);
+    G.lrec.filename_length = makeword(&byterec[L_FILENAME_LENGTH]);
+    G.lrec.extra_field_length = makeword(&byterec[L_EXTRA_FIELD_LENGTH]);
+
+    G.csize = (long) G.lrec.csize;
+    G.ucsize = (long) G.lrec.ucsize;
+
+    if ((G.lrec.general_purpose_bit_flag & 8) != 0) {
+        /* can't trust local header, use central directory: */
+        G.lrec.crc32 = G.pInfo->crc;
+        G.csize = (long)(G.lrec.csize = G.pInfo->compr_size);
+        G.ucsize = (long)(G.lrec.ucsize = G.pInfo->uncompr_size);
+    }
+
+    return PK_COOL;
+
+} /* end function process_local_file_hdr() */
+
+
+#ifdef USE_EF_UT_TIME
+
+/*******************************/
+/* Function ef_scan_for_izux() */
+/*******************************/
+
+unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos_mdatetime,
+                          z_utim, z_uidgid)
+    uch *ef_buf;        /* buffer containing extra field */
+    unsigned ef_len;    /* total length of extra field */
+    int ef_is_c;        /* flag indicating "is central extra field" */
+    ulg dos_mdatetime;  /* last_mod_file_date_time in DOS format */
+    iztimes *z_utim;    /* return storage: atime, mtime, ctime */
+    ush *z_uidgid;      /* return storage: uid and gid */
+{
+    unsigned flags = 0;
+    unsigned eb_id;
+    unsigned eb_len;
+    int have_new_type_eb = FALSE;
+    int ut_zip_unzip_compatible = FALSE;
+
+/*---------------------------------------------------------------------------
+    This function scans the extra field for EF_TIME, EF_IZUNIX2, EF_IZUNIX, or
+    EF_PKUNIX blocks containing Unix-style time_t (GMT) values for the entry's
+    access, creation, and modification time.
+    If a valid block is found, the time stamps are copied to the iztimes
+    structure (provided the z_utim pointer is not NULL).
+    If a IZUNIX2 block is found or the IZUNIX block contains UID/GID fields,
+    and the z_uidgid array pointer is valid (!= NULL), the owner info is
+    transfered as well.
+    The presence of an EF_TIME or EF_IZUNIX2 block results in ignoring all
+    data from probably present obsolete EF_IZUNIX blocks.
+    If multiple blocks of the same type are found, only the information from
+    the last block is used.
+    The return value is a combination of the EF_TIME Flags field with an
+    additional flag bit indicating the presence of valid UID/GID info,
+    or 0 in case of failure.
+  ---------------------------------------------------------------------------*/
+
+    if (ef_len == 0 || ef_buf == NULL || (z_utim == 0 && z_uidgid == NULL))
+        return 0;
+
+    TTrace((stderr,"\nef_scan_for_izux: scanning extra field of length %u\n",
+      ef_len));
+
+    while (ef_len >= EB_HEADSIZE) {
+        eb_id = makeword(EB_ID + ef_buf);
+        eb_len = makeword(EB_LEN + ef_buf);
+
+        if (eb_len > (ef_len - EB_HEADSIZE)) {
+            /* discovered some extra field inconsistency! */
+            TTrace((stderr,
+              "ef_scan_for_izux: block length %u > rest ef_size %u\n", eb_len,
+              ef_len - EB_HEADSIZE));
+            break;
+        }
+
+        switch (eb_id) {
+          case EF_TIME:
+            flags &= ~0x0ff;    /* ignore previous IZUNIX or EF_TIME fields */
+            have_new_type_eb = TRUE;
+            if ( eb_len >= EB_UT_MINLEN && z_utim != NULL) {
+                unsigned eb_idx = EB_UT_TIME1;
+                TTrace((stderr,"ef_scan_for_izux: found TIME extra field\n"));
+                flags |= (ef_buf[EB_HEADSIZE+EB_UT_FLAGS] & 0x0ff);
+                if ((flags & EB_UT_FL_MTIME)) {
+                    if ((eb_idx+4) <= eb_len) {
+                        z_utim->mtime = makelong((EB_HEADSIZE+eb_idx) + ef_buf);
+                        eb_idx += 4;
+                        TTrace((stderr,"  UT e.f. modification time = %ld\n",
+                                z_utim->mtime));
+
+                        if ((ulg)(z_utim->mtime) & (ulg)(0x80000000L)) {
+                            ut_zip_unzip_compatible =
+                              ((time_t)0x80000000L < (time_t)0L)
+                              ? (dos_mdatetime == DOSTIME_MINIMUM)
+                              : (dos_mdatetime >= DOSTIME_2038_01_18);
+                            if (!ut_zip_unzip_compatible) {
+                            /* UnZip interpretes mtime differently than Zip;
+                               without modtime: ignore complete UT field */
+                              flags &= ~0x0ff;  /* no time_t times available */
+                              TTrace((stderr,
+                                "  UT modtime range error; ignore e.f.!\n"));
+                              break;            /* stop scanning this field */
+                            }
+                        } else {
+                            /* cannot determine, safe assumption is FALSE */
+                            ut_zip_unzip_compatible = FALSE;
+                        }
+                    } else {
+                        flags &= ~EB_UT_FL_MTIME;
+                        TTrace((stderr,"  UT e.f. truncated; no modtime\n"));
+                    }
+                }
+                if (ef_is_c) {
+                    break;      /* central version of TIME field ends here */
+                }
+
+                if (flags & EB_UT_FL_ATIME) {
+                    if ((eb_idx+4) <= eb_len) {
+                        z_utim->atime = makelong((EB_HEADSIZE+eb_idx) + ef_buf);
+                        eb_idx += 4;
+                        TTrace((stderr,"  UT e.f. access time = %ld\n",
+                                z_utim->atime));
+                        if (((ulg)(z_utim->atime) & (ulg)(0x80000000L)) &&
+                            !ut_zip_unzip_compatible) {
+                            flags &= ~EB_UT_FL_ATIME;
+                            TTrace((stderr,
+                              "  UT access time range error: skip time!\n"));
+                        }
+                    } else {
+                        flags &= ~EB_UT_FL_ATIME;
+                    }
+                }
+                if (flags & EB_UT_FL_CTIME) {
+                    if ((eb_idx+4) <= eb_len) {
+                        z_utim->ctime = makelong((EB_HEADSIZE+eb_idx) + ef_buf);
+                        TTrace((stderr,"  UT e.f. creation time = %ld\n",
+                                z_utim->ctime));
+                        if (((ulg)(z_utim->ctime) & (ulg)(0x80000000L)) &&
+                            !ut_zip_unzip_compatible) {
+                            flags &= ~EB_UT_FL_CTIME;
+                            TTrace((stderr,
+                              "  UT creation time range error: skip time!\n"));
+                        }
+                    } else {
+                        flags &= ~EB_UT_FL_CTIME;
+                    }
+                }
+            }
+            break;
+
+          case EF_IZUNIX2:
+            if (!have_new_type_eb) {
+                flags &= ~0x0ff;        /* ignore any previous IZUNIX field */
+                have_new_type_eb = TRUE;
+            }
+            if (eb_len >= EB_UX2_MINLEN && z_uidgid != NULL) {
+                z_uidgid[0] = makeword((EB_HEADSIZE+EB_UX2_UID) + ef_buf);
+                z_uidgid[1] = makeword((EB_HEADSIZE+EB_UX2_GID) + ef_buf);
+                flags |= EB_UX2_VALID;   /* signal success */
+            }
+            break;
+
+          case EF_IZUNIX:
+          case EF_PKUNIX:       /* PKUNIX e.f. layout is identical to IZUNIX */
+            if (eb_len >= EB_UX_MINLEN) {
+                TTrace((stderr,"ef_scan_for_izux: found %s extra field\n",
+                        (eb_id == EF_IZUNIX ? "IZUNIX" : "PKUNIX")));
+                if (have_new_type_eb) {
+                    break;      /* Ignore IZUNIX extra field block ! */
+                }
+                if (z_utim != NULL) {
+                    z_utim->atime = makelong((EB_HEADSIZE+EB_UX_ATIME)+ef_buf);
+                    z_utim->mtime = makelong((EB_HEADSIZE+EB_UX_MTIME)+ef_buf);
+                    TTrace((stderr,"  Unix EF actime = %ld\n", z_utim->atime));
+                    TTrace((stderr,"  Unix EF modtime = %ld\n", z_utim->mtime));
+                    flags |= (EB_UT_FL_MTIME | EB_UT_FL_ATIME);
+                    if ((ulg)(z_utim->mtime) & (ulg)(0x80000000L)) {
+                        ut_zip_unzip_compatible =
+                          ((time_t)0x80000000L < (time_t)0L)
+                          ? (dos_mdatetime == DOSTIME_MINIMUM)
+                          : (dos_mdatetime >= DOSTIME_2038_01_18);
+                        if (!ut_zip_unzip_compatible) {
+                            /* UnZip interpretes mtime differently than Zip;
+                               without modtime: ignore complete UT field */
+                            flags &= ~0x0ff;    /* no time_t times available */
+                            TTrace((stderr,
+                                  "  UX modtime range error: ignore e.f.!\n"));
+                        }
+                    } else {
+                        /* cannot determine, safe assumption is FALSE */
+                        ut_zip_unzip_compatible = FALSE;
+                    }
+                    if ((ulg)(z_utim->atime) & (ulg)(0x80000000L) &&
+                        !ut_zip_unzip_compatible && (flags & 0x0ff)) {
+                        /* atime not in range of UnZip's time_t */
+                        flags &= ~EB_UT_FL_ATIME;
+                        TTrace((stderr,
+                                "  UX access time range error: skip time!\n"));
+                    }
+                }
+                if (eb_len >= EB_UX_FULLSIZE && z_uidgid != NULL) {
+                    z_uidgid[0] = makeword((EB_HEADSIZE+EB_UX_UID) + ef_buf);
+                    z_uidgid[1] = makeword((EB_HEADSIZE+EB_UX_GID) + ef_buf);
+                    flags |= EB_UX2_VALID;
+                }
+            }
+            break;
+
+          default:
+            break;
+        }
+
+        /* Skip this extra field block */
+        ef_buf += (eb_len + EB_HEADSIZE);
+        ef_len -= (eb_len + EB_HEADSIZE);
+    }
+
+    return flags;
+}
+
+#endif /* USE_EF_UT_TIME */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/rexxapi.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,886 @@
+/**********************************************************************
+*   REXXAPI.C                                                         *
+*                                                                     *
+*   This program adds a ZIP engine directly to the REXX language.     *
+*   The functions are:                                                *
+*       UZDropFuncs         -- Makes all functions in this package    *
+*                              unknown to REXX.                       *
+*       UZLoadFuncs         -- Makes all functions in this package    *
+*                              known to REXX so REXX programs may     *
+*                              call them.                             *
+*       UZFileTree          -- Searches for files matching a given    *
+*                              filespec, including files in           *
+*                              subdirectories.                        *
+*       UZUnZip             -- Unzip command-line entry point.        *
+*                              This is functionally equivalent to     *
+*                              using Unzip as an external program.    *
+*       UZUnZipToVar            -- Unzip one file to a variable       *
+*       UZUnZipToStem       -- Unzip files to a variable array        *
+*       UZVer               -- Returns the Unzip version number       *
+*                                                                     *
+**********************************************************************/
+/* Include files */
+
+#ifdef OS2DLL
+
+#define  INCL_DOS
+#define  INCL_DOSMEMMGR
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#define UNZIP_INTERNAL
+#include "../unzip.h"
+#include "../version.h"
+
+
+/*********************************************************************/
+/*  Various definitions used by various functions.                   */
+/*********************************************************************/
+
+RexxFunctionHandler UZDropFuncs;
+RexxFunctionHandler UZLoadFuncs;
+RexxFunctionHandler UZFileTree;
+RexxFunctionHandler UZUnZip;
+RexxFunctionHandler UZUnZipToVar;
+RexxFunctionHandler UZUnZipToStem;
+RexxFunctionHandler UZVer;
+RexxFunctionHandler UZAPIVer;
+
+
+int SetOutputVar(__GPRO__ const char *name);
+int SetOutputVarStem(__GPRO__ const char *name);
+int SetOutputVarLength(__GPRO);
+int WriteToVariable(__GPRO__ const char *name, char *buffer, int len);
+int PrintToSubVariable(__GPRO__ int idx, const char *format,...);
+int PrintToVariable(__GPRO__ const char *name, const char *format,...);
+int _PrintToVariable(__GPRO__ const char *name, const char *format, va_list arg_ptr);
+int TextSetNext(__GPRO__ char *format, int len, int all);
+
+#define EZRXSTRING(r,p)  {(r).strptr=(PCH)p;(r).strlength=(ULONG)strlen((r).strptr);}
+
+
+/*********************************************************************/
+/* RxFncTable                                                        */
+/*   Array of names of the UNZIPAPI functions.                       */
+/*   This list is used for registration and deregistration.          */
+/*********************************************************************/
+
+static PSZ  RxFncTable[] =
+   {
+      "UZDropFuncs",
+      "UZLoadFuncs",
+      "UZFileSearch",
+      "UZFileTree",
+      "UZUnZip",
+      "UZUnZipToVar",
+      "UZUnZipToStem",
+      "UZVer",
+   };
+
+/*********************************************************************/
+/* Numeric Error Return Strings                                      */
+/*********************************************************************/
+
+#define  NO_UTIL_ERROR    "0"          /* No error whatsoever        */
+#define  ERROR_NOMEM      "2"          /* Insufficient memory        */
+
+/*********************************************************************/
+/* Numeric Return calls                                              */
+/*********************************************************************/
+
+#define  INVALID_ROUTINE 40            /* Raise Rexx error           */
+#define  VALID_ROUTINE    0            /* Successful completion      */
+
+/*********************************************************************/
+/* Some useful macros                                                */
+/*********************************************************************/
+
+#define BUILDRXSTRING(t, s) { \
+  strcpy((t)->strptr,(s));\
+  (t)->strlength = strlen((s)); \
+}
+
+
+/*********************************************************************/
+/****************  UNZIPAPI Supporting Functions  ********************/
+/****************  UNZIPAPI Supporting Functions  ********************/
+/****************  UNZIPAPI Supporting Functions  ********************/
+/*********************************************************************/
+
+
+int RexxReturn(__GPRO__ int nodefault, RXSTRING *retstr)
+{
+  int ret = G.os2.rexx_error;
+  if (G.filenotfound)
+    G.os2.rexx_mes = "file not found";
+  if (*G.os2.rexx_mes != '0') {
+    if (retstr->strlength > 255) {
+      DosFreeMem(retstr->strptr);
+      retstr->strptr = NULL;
+    }
+  } else if (nodefault)
+    goto noBuild;
+  BUILDRXSTRING(retstr, G.os2.rexx_mes);
+ noBuild:
+  DESTROYGLOBALS();
+  return ret;
+}
+
+/* Get a variable from REXX, return 0 if OK */
+int GetVariable(__GPRO__ const char *name)
+{
+  G.os2.request.shvnext = NULL;
+  EZRXSTRING(G.os2.request.shvname, name);
+  G.os2.request.shvnamelen = G.os2.request.shvname.strlength;
+  G.os2.request.shvvalue.strptr = G.os2.buffer;
+  G.os2.request.shvvalue.strlength = IBUF_LEN;
+  G.os2.request.shvvaluelen = IBUF_LEN;
+  G.os2.request.shvcode = RXSHV_SYFET;
+  G.os2.request.shvret = 0;
+  switch (RexxVariablePool(&G.os2.request)) {
+  case RXSHV_MEMFL:
+    G.os2.rexx_mes = ERROR_NOMEM;
+    break;
+  case RXSHV_BADN:
+  case RXSHV_NEWV:
+    G.os2.request.shvvaluelen = 0;
+  case RXSHV_OK:
+    *(G.os2.buffer+G.os2.request.shvvaluelen) = 0;
+    return G.os2.request.shvvaluelen;
+  }
+  return 0;
+}
+
+
+/* Get REXX compound variable */
+/* Stem must exist in G.os2.getvar_buf w/ length in G.os2.getvar_len */
+int GetVariableIndex(__GPRO__ int index)
+{
+  sprintf(G.os2.getvar_buf+G.os2.getvar_len,"%d",index);
+  return GetVariable(__G__ G.os2.getvar_buf);
+}
+
+
+/* Transfer REXX array to standard C string array */
+/* Returns number of elements */
+/* User is responsible for calling KillStringArray */
+
+int CompoundToStringArray(__GPRO__ char ***pointer, const char *name)
+{
+  int count;
+  int total;
+  char **trav;
+
+  G.os2.getvar_len = strlen(name);
+  memcpy(G.os2.getvar_buf,name,G.os2.getvar_len+1);
+  if (*(G.os2.getvar_buf+G.os2.getvar_len-1) != '.')
+    *(G.os2.getvar_buf+G.os2.getvar_len++) = '.', *(G.os2.getvar_buf+G.os2.getvar_len) = 0;
+
+  if (GetVariableIndex(__G__ 0))
+    return 0;
+
+  total = atoi(G.os2.buffer);
+  *pointer = (char **)malloc((total+1)<<2);
+  trav = *pointer;
+  for (count = 1; count <= total; count++) {
+    GetVariableIndex(__G__ count);
+    trav[count-1] = (char *)malloc(strlen(G.os2.buffer)+1);
+    strcpy(trav[count-1],G.os2.buffer);
+  }
+  trav[count-1] = NULL;
+  return total;
+}
+
+
+/* Kill string array created by CompoundToStringArray */
+
+void KillStringArray(char **pointer)
+{
+  char **trav=pointer;
+  while (*trav != NULL) {
+    free(*trav);
+    trav++;
+  }
+  free(pointer);
+}
+
+
+/*************************************************************************
+* Function:  UZDropFuncs                                                 *
+*                                                                        *
+* Syntax:    call UZDropFuncs                                            *
+*                                                                        *
+* Return:    NO_UTIL_ERROR - Successful.                                 *
+*************************************************************************/
+
+ULONG UZDropFuncs(CHAR *name, ULONG numargs, RXSTRING args[],
+                  CHAR *queuename, RXSTRING *retstr)
+{
+  INT     entries;                     /* Num of entries             */
+  INT     j;                           /* Counter                    */
+
+  if (numargs != 0)                    /* no arguments for this      */
+    return INVALID_ROUTINE;            /* raise an error             */
+
+  retstr->strlength = 0;               /* return a null string result*/
+
+  entries = sizeof(RxFncTable)/sizeof(PSZ);
+
+  for (j = 0; j < entries; j++)
+    RexxDeregisterFunction(RxFncTable[j]);
+
+  return VALID_ROUTINE;                /* no error on call           */
+}
+
+
+/*************************************************************************
+* Function:  UZFileTree                                                  *
+*                                                                        *
+* Syntax:    call UZFileTree zipfile, stem[, include-filespec]           *
+*                                [, exclude-filespec][, options]         *
+*                                                                        *
+* Params:    zipfile  - Name of zip file to search.                      *
+*            stem     - Name of stem var to store results in.            *
+*            include  - Filespec to search for (may include * and ?).    *
+*            exclude  - Filespec to exclude (may include * and ?).       *
+*            options  - Either of the following:                         *
+*                       'F' - Give file statistics.                      *
+*                          Length Date Time Name                         *
+*                       'Z' - Give zip statistics, too.                  *
+*                          Length Method Size Ratio Date Time CRC-32 Name*
+*                       Default is to return only filenames              *
+*                                                                        *
+* Return:    NO_UTIL_ERROR   - Successful.                               *
+*            ERROR_NOMEM     - Out of memory.                            *
+*************************************************************************/
+
+ULONG UZFileTree(CHAR *name, ULONG numargs, RXSTRING args[],
+                 CHAR *queuename, RXSTRING *retstr)
+{
+                                       /* validate arguments         */
+  char *incname[2];
+  char *excname[2];
+  CONSTRUCTGLOBALS();
+
+  if (numargs < 2 || numargs > 5 ||
+      !RXVALIDSTRING(args[0]) ||
+      !RXVALIDSTRING(args[1]) ||
+      args[0].strlength > 255) {
+    DESTROYGLOBALS();
+    return INVALID_ROUTINE;            /* Invalid call to routine    */
+  }
+                                       /* initialize data area       */
+  SetOutputVarStem(__G__ args[1].strptr);
+  G.wildzipfn = args[0].strptr;
+  G.process_all_files = TRUE;
+
+  uO.lflag = 1;
+  uO.zipinfo_mode = TRUE;
+  uO.C_flag = 1;
+  G.extract_flag = FALSE;
+  uO.qflag = 2;
+
+  if (numargs >= 3 &&                  /* check third option         */
+      !RXNULLSTRING(args[2]) &&
+      args[2].strlength > 0) {            /* a zero length string isn't */
+    if (!(G.filespecs = CompoundToStringArray(__G__ &G.pfnames,args[2].strptr))) {
+      G.pfnames = incname;
+      incname[0] = args[2].strptr;
+      incname[1] = NULL;
+      G.filespecs = 1;
+    }
+    G.process_all_files = FALSE;
+  }
+
+  if (numargs >= 4 &&                  /* check third option         */
+      !RXNULLSTRING(args[3]) &&
+      args[3].strlength > 0) {            /* a zero length string isn't */
+    if (!(G.xfilespecs = CompoundToStringArray(__G__ &G.pxnames,args[3].strptr))) {
+      G.pxnames = excname;
+      excname[0] = args[3].strptr;
+      excname[1] = NULL;
+      G.xfilespecs = 1;
+    }
+    G.process_all_files = FALSE;
+  }
+
+  if (numargs == 5 &&                  /* check third option         */
+      !RXNULLSTRING(args[4]) &&
+      args[4].strlength > 0) {            /* a zero length string isn't */
+    int first = *args[4].strptr & 0x5f;
+
+    if (first == 'Z')
+      uO.vflag = 2, uO.lflag = 0, uO.zipinfo_mode = FALSE;
+    else if (first == 'F')
+      uO.vflag = 1, uO.lflag = 0, uO.zipinfo_mode = FALSE;
+  }
+
+  process_zipfiles(__G);
+  SetOutputVarLength(__G);
+  if (G.filespecs > 0 && G.pfnames != incname)
+    KillStringArray(G.pfnames);
+  if (G.xfilespecs > 0 && G.pxnames != excname)
+    KillStringArray(G.pxnames);
+  return RexxReturn(__G__ 0,retstr);        /* no error on call           */
+}
+
+
+/*************************************************************************
+* Function:  UZUnZipToVar                                                *
+*                                                                        *
+* Syntax:    call UZUnZipToVar zipfile, filespec [, stem]                *
+*                                                                        *
+* Params:    zipfile  - Name of zip file to search.                      *
+*            filespec - File to extract                                  *
+*            stem     - If you specify a stem variable, the file will be *
+*                       extracted to the variable, one line per index    *
+*                       In this case, 0 will be returned                 *
+*                                                                        *
+* Return:    Extracted file                                              *
+*            ERROR_NOMEM     - Out of memory.                            *
+*************************************************************************/
+
+ULONG UZUnZipToVar(CHAR *name, ULONG numargs, RXSTRING args[],
+                          CHAR *queuename, RXSTRING *retstr)
+{
+  CONSTRUCTGLOBALS();
+  UzpBuffer *ub = (UzpBuffer *)retstr;
+                                       /* validate arguments         */
+  if (numargs < 2 || numargs > 3 ||
+      !RXVALIDSTRING(args[0]) ||
+      !RXVALIDSTRING(args[1]) ||
+      args[0].strlength == 0 ||
+      args[1].strlength == 0) {
+    DESTROYGLOBALS();
+    return INVALID_ROUTINE;            /* Invalid call to routine    */
+  }
+
+  uO.C_flag = 1;
+  G.redirect_data=1;
+  if (numargs == 3) {
+    if (!RXVALIDSTRING(args[2]) ||
+        RXNULLSTRING(args[1]) ||
+        args[2].strlength == 0) {
+      DESTROYGLOBALS();
+      return INVALID_ROUTINE;            /* Invalid call to routine    */
+    }
+    SetOutputVarStem(__G__ args[2].strptr);
+    G.redirect_text = 0;
+    G.redirect_data++;
+  }
+  unzipToMemory(__G__ args[0].strptr, args[1].strptr,
+                G.redirect_data==1 ? ub : NULL);
+  return RexxReturn(__G__ G.redirect_data==1,retstr);
+}
+
+
+/*************************************************************************
+* Function:  UZUnZipToStem                                               *
+*                                                                        *
+* Syntax:    call UZUnZipToStem zipfile, stem[, include-filespec]        *
+*                                [, exclude-filespec][, mode]            *
+*                                                                        *
+* Params:    zipfile  - Name of zip file to search.                      *
+*            stem     - Name of stem var to store files in.              *
+*            include  - Filespec to search for (may include * and ?).    *
+*            exclude  - Filespec to exclude (may include * and ?).       *
+*            mode     - Specifies 'F'lat or 'T'ree mode.  Umm, this is   *
+*                        hard to explain so I'll give an example, too.   *
+*                       Assuming a file unzip.zip containing:            *
+*                               unzip.c                                  *
+*                               unshrink.c                               *
+*                               extract.c                                *
+*                               os2/makefile.os2                         *
+*                               os2/os2.c                                *
+*                               os2/dll/dll.def                          *
+*                               os2/dll/unzipapi.c                       *
+*                                                                        *
+*                       -- In flat mode, each file is stored in          *
+*                          stem.fullname i.e. stem."os2/dll/unzipapi.c"  *
+*                          A list of files is created in stem.<index>    *
+*                                                                        *
+*                       Flat mode returns:                               *
+*                               stem.0 = 7                               *
+*                               stem.1 = unzip.c                         *
+*                               stem.2 = unshrink.c                      *
+*                               stem.3 = extract.c                       *
+*                               stem.4 = os2/makefile.os2                *
+*                               stem.5 = os2/os2.c                       *
+*                               stem.6 = os2/dll/dll.def                 *
+*                               stem.7 = os2/dll/unzipapi.c              *
+*                                                                        *
+*                       And the following contain the contents of the    *
+*                       various programs:                                *
+*                               stem.unzip.c                             *
+*                               stem.unshrink.c                          *
+*                               stem.extract.c                           *
+*                               stem.os2/makefile.os2                    *
+*                               stem.os2/os2.c                           *
+*                               stem.os2/dll/dll.def                     *
+*                               stem.os2/dll/unzipapi.c                  *
+*                                                                        *
+*                       -- In tree mode, slashes are converted to periods*
+*                          in the pathname thus the above file would have*
+*                          been stored in stem.os2.dll.unzipapi.c        *
+*                          The index would then be stored in stem.OS2.   *
+*                          DLL.<index>.                                  *
+*                                                                        *
+*                       NOTE: All path names are converted to uppercase  *
+*                                                                        *
+*                       Tree mode returns:                               *
+*                               stem.0 = 4                               *
+*                               stem.1 = unzip.c                         *
+*                               stem.2 = unshrink.c                      *
+*                               stem.3 = extract.c                       *
+*                               stem.4 = OS2/                            *
+*                                                                        *
+*                               stem.OS2.0 = 3                           *
+*                               stem.OS2.1 = makefile.os2                *
+*                               stem.OS2.2 = os2.c                       *
+*                               stem.OS2.3 = DLL/                        *
+*                                                                        *
+*                               stem.OS2.DLL.0 = 2                       *
+*                               stem.OS2.DLL.1 = def                     *
+*                               stem.OS2.DLL.2 = unzipapi.c              *
+*                                                                        *
+*                       And the following contain the contents of the    *
+*                       various programs:                                *
+*                               stem.unzip.c                             *
+*                               stem.unshrink.c                          *
+*                               stem.extract.c                           *
+*                               stem.OS2.makefile.os2                    *
+*                               stem.OS2.os2.c                           *
+*                               stem.OS2.DLL.dll.def                     *
+*                               stem.OS2.DLL.unzipapi.c                  *
+*                                                                        *
+*                                                                        *
+* Return:    NO_UTIL_ERROR   - Successful.                               *
+*            ERROR_NOMEM     - Out of memory.                            *
+*************************************************************************/
+
+ULONG UZUnZipToStem(CHAR *name, ULONG numargs, RXSTRING args[],
+                          CHAR *queuename, RXSTRING *retstr)
+{
+  char *incname[2];
+  char *excname[2];
+  CONSTRUCTGLOBALS();
+                                       /* validate arguments         */
+  if (numargs < 2 || numargs > 5 ||
+      !RXVALIDSTRING(args[0]) ||
+      !RXVALIDSTRING(args[1]) ||
+      args[0].strlength > 255) {
+    DESTROYGLOBALS();
+    return INVALID_ROUTINE;            /* Invalid call to routine    */
+  }
+                                       /* initialize data area       */
+  G.wildzipfn = args[0].strptr;
+  G.process_all_files = TRUE;
+
+  uO.C_flag = 1;
+  G.extract_flag = TRUE;
+  SetOutputVarStem(__G__ args[1].strptr);
+  G.redirect_data = 3;
+  G.redirect_text = 0;
+
+  if (numargs >= 3 &&                  /* check third option         */
+      !RXNULLSTRING(args[2]) &&
+      args[2].strlength > 0) {            /* a zero length string isn't */
+    if (!(G.filespecs = CompoundToStringArray(__G__ &G.pfnames,args[2].strptr))) {
+      G.pfnames = incname;
+      incname[0] = args[2].strptr;
+      incname[1] = NULL;
+      G.filespecs = 1;
+    }
+    G.process_all_files = FALSE;
+  }
+
+  if (numargs >= 4 &&                  /* check third option         */
+      !RXNULLSTRING(args[3]) &&
+      args[3].strlength > 0) {            /* a zero length string isn't */
+    if (!(G.xfilespecs = CompoundToStringArray(__G__ &G.pxnames,args[3].strptr))) {
+      G.pxnames = excname;
+      excname[0] = args[3].strptr;
+      excname[1] = NULL;
+      G.xfilespecs = 1;
+    }
+    G.process_all_files = FALSE;
+  }
+
+  if (numargs == 5 &&                  /* check third option         */
+      !RXNULLSTRING(args[4]) &&
+      (*args[4].strptr & 0x5f) == 'T') {
+    G.redirect_data++;
+    G.os2.request.shvnext = NULL;
+    EZRXSTRING(G.os2.request.shvname, args[4].strptr);
+    G.os2.request.shvnamelen = G.os2.request.shvname.strlength;
+    G.os2.request.shvcode = RXSHV_SYDRO;
+    G.os2.request.shvret = 0;
+    RexxVariablePool(&G.os2.request);
+  }
+
+
+  uO.qflag = 2;
+
+  process_zipfiles(__G);
+  if (G.filespecs > 0 && G.pfnames != incname)
+    KillStringArray(G.pfnames);
+  if (G.xfilespecs > 0 && G.pxnames != excname)
+    KillStringArray(G.pxnames);
+  if (G.redirect_data == 3)
+    SetOutputVarLength(__G);
+  return RexxReturn(__G__ 0,retstr);            /* no error on call           */
+}
+
+
+/*************************************************************************
+* Function:  UZLoadFuncs                                                 *
+*                                                                        *
+* Syntax:    call UZLoadFuncs [option]                                   *
+*                                                                        *
+* Params:    none                                                        *
+*                                                                        *
+* Return:    null string                                                 *
+*************************************************************************/
+
+ULONG UZLoadFuncs(CHAR *name, ULONG numargs, RXSTRING args[],
+                           CHAR *queuename, RXSTRING *retstr)
+{
+  INT    entries;                      /* Num of entries             */
+  INT    j;                            /* Counter                    */
+
+  retstr->strlength = 0;               /* set return value           */
+                                       /* check arguments            */
+  if (numargs > 0)
+    return INVALID_ROUTINE;
+
+  entries = sizeof(RxFncTable)/sizeof(PSZ);
+
+  for (j = 0; j < entries; j++) {
+    RexxRegisterFunctionDll(RxFncTable[j],
+          "UNZIP32", RxFncTable[j]);
+  }
+  return VALID_ROUTINE;
+}
+
+
+
+/*************************************************************************
+* Function:  UZVer                                                       *
+*                                                                        *
+* Syntax:    call UZVer                                                  *
+*                                                                        *
+* Return:    Version of Unzip                                            *
+*************************************************************************/
+
+ULONG UZVer(CHAR *name, ULONG numargs, RXSTRING args[],
+                        CHAR *queuename, RXSTRING *retstr)
+{
+  if (numargs > 1)                    /* validate arg count         */
+    return INVALID_ROUTINE;
+
+  if (numargs == 0 || (*args[0].strptr & 0x5f) != 'L')
+    /* strcpy( retstr->strptr, UZ_VERNUM );    "5.13a BETA" */
+    sprintf( retstr->strptr, "%d.%d%d%s", UZ_MAJORVER, UZ_MINORVER,
+      PATCHLEVEL, BETALEVEL );
+  else
+    /* strcpy( retstr->strptr, UZ_VERSION );   UZ_VERNUM" of 26 Sep 94" */
+    sprintf( retstr->strptr, "%d.%d%d%s of %s", UZ_MAJORVER, UZ_MINORVER,
+      PATCHLEVEL, BETALEVEL, VERSION_DATE );
+  retstr->strlength = strlen(retstr->strptr);
+  return VALID_ROUTINE;
+}
+
+
+/*************************************************************************
+* Function:  UZUnZip                                                     *
+*                                                                        *
+* Syntax:    call UZUnZip                                                *
+*                                                                        *
+* Return:    Unzip return code                                           *
+*************************************************************************/
+
+ULONG UZUnZip(CHAR *name, ULONG numargs, RXSTRING args[],
+                        CHAR *queuename, RXSTRING *retstr)
+{
+  char *argv[30];
+  char *scan;
+  int argc=0;
+  int idx;
+  CONSTRUCTGLOBALS();
+
+  if (numargs < 1 || numargs > 2 ||
+      args[0].strlength > 255) {
+    DESTROYGLOBALS();
+    return INVALID_ROUTINE;            /* Invalid call to routine    */
+  }
+                                       /* initialize data area       */
+  if (numargs == 2)
+    SetOutputVarStem(__G__ args[1].strptr);
+
+  scan = args[0].strptr;
+  argv[argc++] = "";         /* D:\\SOURCECODE\\UNZIP51S\\UNZIP.COM"; */
+  while (*scan == ' ')
+    scan++;
+  argv[argc++] = scan;
+  while ( (scan = strchr(scan,' ')) != NULL) {
+    *scan++ = 0;
+    while (*scan == ' ')
+      scan++;
+    argv[argc++] = scan;
+  }
+  if (*argv[argc-1] == 0)
+    argc--;
+  argv[argc] = 0;
+
+         /* GRR:  should resetMainFlags() be called in here somewhere? */
+
+  sprintf(retstr->strptr, "%d", unzip(__G__ argc, argv));   /* a.k.a. MAIN() */
+  if (numargs == 2)
+    SetOutputVarLength(__G);
+  retstr->strlength = strlen(retstr->strptr);
+  return RexxReturn(__G__ 1,retstr);
+}
+
+int varmessage(__GPRO__ uch *buf, ulg size)
+{
+  if (size > 0)
+    memcpy(G.os2.buffer+G.os2.putchar_idx,buf,size);
+    G.os2.putchar_idx = TextSetNext(__G__ G.os2.buffer, size+G.os2.putchar_idx,0);
+  return 0;
+}
+
+int varputchar(__GPRO__ int c)
+{
+  G.os2.buffer[G.os2.putchar_idx++] = c;
+  if (c == '\n') {
+    G.os2.buffer[G.os2.putchar_idx] = 0;
+    if (G.os2.output_var[0])
+      G.os2.putchar_idx = TextSetNext(__G__ G.os2.buffer, G.os2.putchar_idx,0);
+    else {
+      G.os2.buffer[--G.os2.putchar_idx] = 0;
+      puts(G.os2.buffer);
+      G.os2.putchar_idx = 0;
+    }
+  }
+  return 1;
+}
+
+
+
+int SetOutputVarStem(__GPRO__ const char *name)
+{
+  int len=strlen(name);
+  G.redirect_text=1;
+  G.os2.output_idx = 0;
+  strcpy(G.os2.output_var, name);
+  if (len) {
+    strupr(G.os2.output_var);                 /* uppercase the name         */
+    if (*(G.os2.output_var+len-1) != '.') {
+      *(G.os2.output_var+len) = '.';
+      len++;
+      *(G.os2.output_var+len) = 0;
+    }
+    WriteToVariable(__G__ G.os2.output_var,"",0);
+  }
+  G.os2.stem_len = len;
+  return G.os2.stem_len;
+}
+
+int SetOutputVar(__GPRO__ const char *name)
+{
+  int len=strlen(name);
+  G.redirect_text=1;
+  G.os2.output_idx = 0;
+  strcpy(G.os2.output_var, name);
+  strupr(G.os2.output_var);                 /* uppercase the name         */
+  if (*(name+len-1) == '.')
+    G.os2.stem_len = len;
+  else
+    G.os2.stem_len = 0;
+  return G.os2.stem_len;
+}
+
+int SetOutputVarLength(__GPRO)
+{
+  if (G.os2.stem_len > 0) {
+    if (G.os2.putchar_idx)
+      TextSetNext(__G__ G.os2.buffer,G.os2.putchar_idx,1);
+    return PrintToSubVariable(__G__ 0,"%d",G.os2.output_idx);
+  }
+  return 0;
+}
+
+int PrintToVariable(__GPRO__ const char *name, const char *format,...)
+{
+  va_list arg_ptr;
+  int ret;
+
+  va_start(arg_ptr, format);
+  ret = _PrintToVariable(__G__ name, format, arg_ptr);
+  va_end(arg_ptr);
+  return ret;
+}
+
+int WriteToVariable(__GPRO__ const char *name, char *buffer, int len)
+{
+  G.os2.request.shvnext = NULL;
+  EZRXSTRING(G.os2.request.shvname, name);
+  G.os2.request.shvnamelen = G.os2.request.shvname.strlength;
+  G.os2.request.shvvalue.strptr = buffer;
+  G.os2.request.shvvalue.strlength = len;
+  G.os2.request.shvvaluelen = len;
+  G.os2.request.shvcode = RXSHV_SET;
+  G.os2.request.shvret = 0;
+  switch (RexxVariablePool(&G.os2.request)) {
+  case RXSHV_BADN:
+    G.os2.rexx_error = INVALID_ROUTINE;
+    break;
+  case RXSHV_MEMFL:
+    G.os2.rexx_mes = ERROR_NOMEM;
+    break;
+  case RXSHV_OK:
+    return 0;
+  }
+  return INVALID_ROUTINE;      /* error on non-zero          */
+}
+
+int _PrintToVariable(__GPRO__ const char *name, const char *format, va_list arg_ptr)
+{
+  int ret = vsprintf(G.os2.buffer, format, arg_ptr);
+  WriteToVariable(__G__ name, G.os2.buffer, strlen(G.os2.buffer));
+  return ret;
+}
+
+int PrintToSubVariable(__GPRO__ int idx, const char *format, ...)
+{
+  va_list arg_ptr;
+  int ret;
+
+  if (G.os2.stem_len == 0)
+    return INVALID_ROUTINE;      /* error on non-zero          */
+  sprintf(G.os2.output_var+G.os2.stem_len,"%d",idx);
+
+  va_start(arg_ptr, format);
+  ret = _PrintToVariable(__G__ G.os2.output_var, format, arg_ptr);
+  va_end(arg_ptr);
+  return ret;
+}
+
+
+int WriteToNextVariable(__GPRO__ char *buffer, int len)
+{
+  if (G.os2.stem_len > 0) {
+    G.os2.output_idx++;
+    sprintf(G.os2.output_var+G.os2.stem_len,"%d",G.os2.output_idx);
+  }
+  return WriteToVariable(__G__ G.os2.output_var, buffer, len);
+}
+
+
+int TextSetNext(__GPRO__ char *buffer, int len, int all)
+{
+  char *scan = buffer, *next, *base=buffer;
+  int remaining=len;
+  int ret;
+
+  while ((next = strchr(scan,'\n')) != NULL && remaining > 0) {
+    if (next > scan && *(next-1) == 0xd)
+      *(next-1) = 0;
+    else
+      *next = 0;
+    if (WriteToNextVariable(__G__ scan,strlen(scan)))
+      return 0;
+    next++;
+    remaining -= (next-scan);
+    scan = next;
+  }
+  if (remaining > 0)
+    if (all) {
+      *(scan+remaining) = 0;
+      WriteToNextVariable(__G__ scan,remaining);
+    } else {
+      memcpy(buffer,scan,remaining);
+      return remaining;
+    }
+
+  return 0;
+}
+
+int finish_REXX_redirect(__GPRO)
+{
+  char *scan, *ptr;
+  int idx=0, first=1, offset;
+
+  if (!G.redirect_size)
+    return 0;
+  switch(G.redirect_data) {
+  case 1:
+    break;
+  case 2:
+    TextSetNext(__G__ G.redirect_buffer, G.redirect_size, 1);
+    SetOutputVarLength(__G);
+    DosFreeMem(G.redirect_buffer);
+    G.redirect_buffer = NULL;
+    G.redirect_size = 0;
+    break;
+  case 3:
+    WriteToNextVariable(__G__ G.filename,strlen(G.filename));
+    sprintf(G.os2.output_var+G.os2.stem_len,G.filename);
+    WriteToVariable(__G__ G.os2.output_var, G.redirect_buffer, G.redirect_size);
+    DosFreeMem(G.redirect_buffer);
+    G.redirect_buffer = NULL;
+    G.redirect_size = 0;
+    break;
+  case 4:
+    if ((scan = strrchr(G.filename,'/')) != NULL) {
+      idx = *scan;
+      *scan = 0;
+      strupr(G.filename);
+      *scan = idx;
+    }
+    scan = G.os2.output_var+G.os2.stem_len;
+    strcpy(scan,G.filename);
+    while ((scan = strchr(scan,'/')) != NULL)
+      *scan = '.';
+    WriteToVariable(__G__ G.os2.output_var, G.redirect_buffer, G.redirect_size);
+    DosFreeMem(G.redirect_buffer);
+    G.redirect_buffer = NULL;
+    G.redirect_size = 0;
+    strcpy(G.os2.getvar_buf, G.os2.output_var);
+    do {
+      if ((scan = strrchr(G.filename,'/')) == NULL)
+        offset = 0;
+      else
+        offset = scan-G.filename+1;
+      if (first || !GetVariable(__G__ G.os2.output_var)) {
+        ptr = G.os2.getvar_buf+offset+G.os2.stem_len;
+        *ptr = '0';
+        *(ptr+1) = 0;
+        if (!GetVariable(__G__ G.os2.getvar_buf))
+          idx = 1;
+        else
+          idx = atoi(G.os2.buffer)+1;
+        PrintToVariable(__G__ G.os2.getvar_buf,"%d",idx);
+        sprintf(ptr,"%d",idx);
+        if (!first) {
+          PrintToVariable(__G__ G.os2.output_var,"%d",idx);
+          idx = strlen(G.filename);
+          *(G.filename+idx)   = '/';
+          *(G.filename+idx+1) = 0;
+        }
+        WriteToVariable(__G__ G.os2.getvar_buf,G.filename+offset,strlen(G.filename+offset));
+        first=0;
+      }
+      if (offset) {
+        *(G.os2.output_var+G.os2.stem_len+offset-1)   = 0;
+        *scan = 0;
+      }
+    } while (offset);
+    break;
+  }
+  return 0;
+}
+
+#endif /* OS2DLL */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/rexxapi.def	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,18 @@
+LIBRARY UNZIP32 INITINSTANCE LONGNAMES
+PROTMODE
+DESCRIPTION 'Info-ZIP UnZip API - Copyright Scott Maxwell 1994, Info-ZIP 1995-1997'
+DATA MULTIPLE NONSHARED
+EXPORTS
+     UzpVersion		@1
+     UzpUnzipToMemory	@2
+     UzpFileTree	@3
+     UzpMain		@4
+     UzpAltMain		@5
+     UzpVersion2	@6
+     UZDROPFUNCS	= UZDropFuncs      @2000
+     UZLOADFUNCS	= UZLoadFuncs      @2001
+     UZFILETREE		= UZFileTree       @2002
+     UZUNZIPTOVAR	= UZUnZipToVar     @2003
+     UZUNZIPTOSTEM	= UZUnZipToStem    @2004
+     UZVER		= UZVer            @2005
+     UZUNZIP		= UZUnZip	   @2007
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/rexxhelp.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,178 @@
+/* rexxhelp.c */
+
+#if defined(API_DOC) && defined(OS2DLL)
+
+#define UNZIP_INTERNAL
+#include "../unzip.h"
+#include "../version.h"
+
+APIDocStruct REXXDetails[] = {
+  { "UZDROPFUNCS"  , "UZDropFuncs"  ,
+               "call UZDropFuncs",
+               "Use this function to drop all the loaded UnZip functions.\n"
+"\t\tOnce this function is processed by a REXX program, the\n"
+"\t\tUnZip functions are not accessible in any OS/2 sessions.\n" },
+
+  { "UZLOADFUNCS"  , "UZLoadFuncs"  ,
+               "call UZLoadFuncs",
+               "Use this function to make all of the UnZip functions\n"
+"		in this package available to all OS/2 sessions.\n\n"
+"  Example:	call RxFuncAdd 'UZLoadFuncs', 'UNZIPAPI', 'UZLoadFuncs'\n"
+"		call UZLoadFuncs\n" },
+
+  { "UZFILETREE"   , "UZFileTree"   ,
+               "rc = UZFileTree(zipfile, stem, [include], [exclude], [options])\n\n"
+"	zipfile	- Name of ZIP file to search\n"
+"	stem	- Name of the stem variable for results\n"
+"		  Note: stem.0 contains the number of files found.\n"
+"	include - Optional stem variable specifying a list of files (including\n"
+"		  wildcards) to include.  stem.0 must indicate number of items.\n"
+"	exclude - Optional stem variable specifying a list of files (including\n"
+"		  wildcards) to exclude.  stem.0 must indicate number of items.\n"
+"	    NOTE: If lists are not needed, filespec strings may be passed.\n"
+"	options - One of the following:\n"
+"		  'O' - Give file names only.  This is the default.\n"
+"		  'F' - Give file statistics in the form:\n"
+"			Length Date Time Name\n"
+"		  'Z' - Also give ZIP statistics in the form:\n"
+"			Length Method Size Ratio Date Time CRC-32 Name",
+               "Finds all files in the specified ZIP with the specified\n"
+"		filespec and places their descriptions in a stem variable.\n\n"
+"	rc:	Return codes\n"
+"		0	Successful\n"
+"		2	Error.  Not enough memory.\n\n"
+"	Examples:\n"
+"		/* Return a list of all .NDX files in pcboard.qwk */\n"
+"		rc = UZFileTree('pcboard.qwk', 'stem.', '*.ndx')\n\n"
+"		/* Return a list of all files except *.NDX and *.DAT */\n"
+"		exc.0 = 2; exc.1 = '*.ndx'; exc.2 = '*.dat'\n"
+"		rc = UZFileTree('pcboard.qwk', 'stem.',,'exc.')\n" },
+
+  { "UZUNZIP"      , "UZUnZip"      ,
+               "rc = UZUnZip('parameters', [stem])\n\n"
+"	parameters	- The entire list of parameters you would use from\n"
+"			  the command-line\n"
+"	stem		- The name of an optional stem variable where any\n"
+"			  output should be redirected.\n"
+"			  NOTE: If a stem is not specified, all output will\n"
+"				go to the console.",
+               "Provide a direct entry point to the command line interface.\n\n"
+"	rc:	UnZip return code\n\n"
+"  Examples:	/* Test the archive 'unzip51s.zip' and return output in stem.*/\n"
+"		rc = UZUnZip('-t unzip51s.zip','stem.')\n"
+"		/* Extract the archive, display output on screen */\n"
+"		call UZUnZip 'doom.zip'\n"
+"		/* Extract all .NDX files from the archive */\n"
+"		call UZUnZip 'pcboard.qwk *.ndx','stem.'\n" },
+
+  { "UZUNZIPTOVAR" , "UZUnZipToVar" ,
+               "rc = UZUnZipToVar('zipfile', 'filename', [stem])\n\n"
+"	zipfile	 - Name of ZIP file to search\n"
+"	filename - Name of file to extract from zipfile\n"
+"	stem	 - Optional stem variable to extract the file to.\n"
+"		   If you specify a stem variable, the file will be extracted\n"
+"		   to the variable, one line per index, stem.0 containing a\n"
+"		   line count.  In this case, 0 will be returned in rc.\n"
+"		   If NO stem variable is specified, the entire file will be\n"
+"		   extracted to rc.",
+               "Unzip one file to a variable.\n\n"
+"	rc:	If no stem variable is specified, rc contains the contents of\n"
+"		the extracted file if successful or an error-code if not.\n"
+"		If a stem variable IS specified, rc contains 0 if successful.\n"},
+
+  /* GRR:  "include" and "exclude" used to be identified as stem variables
+   *       (Daniel H bug report)
+   */
+  { "UZUNZIPTOSTEM", "UZUnZipToStem",
+               "rc = UZUnZipToStem(zipfile, stem, [include], [exclude], [mode])\n"
+"	zipfile	- Name of ZIP file to search\n"
+"	stem	- Stem variable used to store the extracted files\n"
+"	include - Optional string variable specifying a list of files (including\n"
+"		  wildcards) to include.  stem.0 must indicate number of items.\n"
+"	exclude - Optional string variable specifying a list of files (including\n"
+"		  wildcards) to exclude.  stem.0 must indicate number of items.\n"
+"	    NOTE: If lists are not needed, filespec strings may be passed.\n"
+"	mode	- Optional mode parameter specifies either 'F'lat (the default)\n"
+"		  or 'T'ree mode.\n"
+"		-- In flat mode, each file is stored in stem.fullname i.e.\n"
+"		   stem.os2/dll/unzipapi.c.  A list of files is created in\n"
+"		   stem.<index>\n"
+"		-- In tree mode, slashes are converted to periods in the\n"
+"		   pathname thus the above file would have been stored in\n"
+"		   stem.OS2.DLL.unzipapi.c and an index stored for each\n"
+"		   directory, i.e. stem.OS2.DLL.<index> = \"unzipapi.c\",\n"
+"		   stem.OS2.<index> = \"DLL/\", stem.<index> = \"OS2/\"",
+               "Unzip files to a stem variable.\n\n"
+"	Example:	Assuming a file unzip.zip containing:\n"
+"			  unzip.c, unshrink.c, extract.c,\n"
+"			  os2/makefile.os2, os2/os2.c\n"
+"			  os2/dll/dll.def, os2/dll/unzipapi.c\n\n"
+"		rc = UZUnZipToStem('unzip.zip', 'stem.')\n"
+"		Returns:	stem.0 = 7\n"
+"				stem.1 = unzip.c\n"
+"				stem.2 = unshrink.c\n"
+"				stem.3 = extract.c\n"
+"				stem.4 = os2/makefile.os2\n"
+"				stem.5 = os2/os2.c\n"
+"				stem.6 = os2/dll/dll.def\n"
+"				stem.7 = os2/dll/unzipapi.c\n"
+"			And the following contain the contents of the\n"
+"			various files:\n"
+"				stem.unzip.c\n"
+"				stem.unshrink.c\n"
+"				stem.extract.c\n"
+"				stem.os2/makefile.os2\n"
+"				stem.os2/os2.c\n"
+"				stem.os2/dll/dll.def\n"
+"				stem.os2/dll/unzipapi.c\n\n"
+"		rc = UZUnZipToStem('unzip.zip', 'stem.',,,'TREE')\n"
+"		Returns:	stem.0 = 4\n"
+"				stem.1 = unzip.c\n"
+"				stem.2 = unshrink.c\n"
+"				stem.3 = extract.c\n"
+"				stem.4 = OS2/\n"
+"				stem.OS2.0 = 3\n"
+"				stem.OS2.1 = makefile.os2\n"
+"				stem.OS2.2 = os2.c\n"
+"				stem.OS2.3 = DLL/\n"
+"				stem.OS2.DLL.0 = 2\n"
+"				stem.OS2.DLL.1 = def\n"
+"				stem.OS2.DLL.2 = unzipapi.c\n"
+"\n"
+"			And the following contain the contents of the\n"
+"			various programs:\n"
+"				stem.unzip.c\n"
+"				stem.unshrink.c\n"
+"				stem.extract.c\n"
+"				stem.OS2.makefile.os2\n"
+"				stem.OS2.os2.c\n"
+"				stem.OS2.DLL.dll.def\n"
+"				stem.OS2.DLL.unzipapi.c\n" },
+
+  { "UZVER"        , "UZVer"        ,
+               "rc = UZVer([option])\n\n"
+"	rc	String containing UnZip version info in the form 'x.xx'\n"
+"		If option is 'L' then info is in the form 'x.xx of <date>",
+               "Returns the version number of UnZip\n" },
+
+  { "UZAPIVER"     , "UZAPIVer"     ,
+               "rc = UZAPIVer([option])\n\n"
+"	rc	String containing API version info in the form 'x.xx'\n"
+"		If option is 'L' then info is in the form 'x.xx of <date>",
+               "Returns the version number of the API\n" },
+  { 0 }
+};
+
+char *REXXBrief = "\
+REXX functions:\n\
+  UZDropFuncs     -- Makes all functions in this package unknown to REXX\n\
+  UZLoadFuncs     -- Makes all functions in this package known to REXX\n\
+  UZFileTree      -- Searches for files matching a given filespec\n\
+  UZUnZip	  -- UnZip command-line entry point\n\
+  UZUnZipToVar    -- Unzip one file to a variable\n\
+  UZUnZipToStem   -- Unzip files to a variable array\n\
+  UZVer           -- Returns the UnZip version number\n\
+  UZAPIVer        -- Returns the API version number\n";
+
+
+#endif /* API_DOC && OS2DLL */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/stub.def	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,6 @@
+DESCRIPTION 'The world-famous Info-ZIP unarchiving utilities'
+STACKSIZE 0x50000
+IMPORTS
+     UNZIP32.UzpVersion
+     UNZIP32.UzpMain
+     UNZIP32.UzpVersion2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/ttyio.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,625 @@
+/*---------------------------------------------------------------------------
+
+  ttyio.c
+
+  This file contains routines for doing console input/output, including code
+  for non-echoing input.  It is used by the encryption/decryption code but
+  does not contain any restricted code itself.  This file is shared between
+  Info-ZIP's Zip and UnZip.
+
+  Contains:  echo()         (VMS only)
+             Echon()        (Unix only)
+             Echoff()       (Unix only)
+             screenlines()  (Unix only)
+             zgetch()       (Unix and non-Unix versions)
+             getp()         ("PC," Unix/Atari/Be, VMS/VMCMS/MVS)
+
+  ---------------------------------------------------------------------------*/
+
+#define __TTYIO_C       /* identifies this source module */
+
+#include "zip.h"
+#include "crypt.h"
+
+#if (CRYPT || (defined(UNZIP) && !defined(FUNZIP)))
+/* Non-echo console/keyboard input is needed for (en/de)cryption's password
+ * entry, and for UnZip(SFX)'s MORE and Pause features.
+ * (The corresponding #endif is found at the end of this module.)
+ */
+
+#include "ttyio.h"
+
+#ifndef PUTC
+#  define PUTC putc
+#endif
+
+#ifdef ZIP
+#  ifdef GLOBAL          /* used in Amiga system headers, maybe others too */
+#    undef GLOBAL
+#  endif
+#  define GLOBAL(g) g
+#else
+#  define GLOBAL(g) G.g
+#endif
+
+#ifdef __BEOS__                /* why yes, we do */
+#  define HAVE_TERMIOS_H
+#endif
+
+#ifdef _POSIX_VERSION
+#  ifndef USE_POSIX_TERMIOS
+#    define USE_POSIX_TERMIOS  /* use POSIX style termio (termios) */
+#  endif
+#  ifndef HAVE_TERMIOS_H
+#    define HAVE_TERMIOS_H     /* POSIX termios.h */
+#  endif
+#endif /* _POSIX_VERSION */
+
+#ifdef UNZIP            /* Zip handles this with the unix/configure script */
+#  ifndef _POSIX_VERSION
+#    if (defined(SYSV) || defined(CRAY)) &&  !defined(__MINT__)
+#      ifndef USE_SYSV_TERMIO
+#        define USE_SYSV_TERMIO
+#      endif
+#      ifdef COHERENT
+#        ifndef HAVE_TERMIO_H
+#          define HAVE_TERMIO_H
+#        endif
+#        ifdef HAVE_SYS_TERMIO_H
+#          undef HAVE_SYS_TERMIO_H
+#        endif
+#      else /* !COHERENT */
+#        ifdef HAVE_TERMIO_H
+#          undef HAVE_TERMIO_H
+#        endif
+#        ifndef HAVE_SYS_TERMIO_H
+#           define HAVE_SYS_TERMIO_H
+#        endif
+#      endif /* ?COHERENT */
+#    endif /* (SYSV || CRAY) && !__MINT__ */
+#  endif /* !_POSIX_VERSION */
+#  if !(defined(BSD4_4) || defined(SYSV) || defined(__convexc__))
+#    ifndef NO_FCNTL_H
+#      define NO_FCNTL_H
+#    endif
+#  endif /* !(BSD4_4 || SYSV || __convexc__) */
+#endif /* UNZIP */
+
+#ifdef HAVE_TERMIOS_H
+#  ifndef USE_POSIX_TERMIOS
+#    define USE_POSIX_TERMIOS
+#  endif
+#endif
+
+#if (defined(HAVE_TERMIO_H) || defined(HAVE_SYS_TERMIO_H))
+#  ifndef USE_SYSV_TERMIO
+#    define USE_SYSV_TERMIO
+#  endif
+#endif
+
+#if (defined(UNZIP) && !defined(FUNZIP) && defined(UNIX) && defined(MORE))
+#  include <sys/ioctl.h>
+#  define GOT_IOCTL_H
+   /* int ioctl OF((int, int, zvoid *));   GRR: may need for some systems */
+#endif
+
+#ifndef HAVE_WORKING_GETCH
+   /* include system support for switching of console echo */
+#  ifdef VMS
+#    include <descrip.h>
+#    include <iodef.h>
+#    include <ttdef.h>
+#    include <starlet.h>
+#    include <ssdef.h>
+#  else /* !VMS */
+#    ifdef HAVE_TERMIOS_H
+#      include <termios.h>
+#      define sgttyb termios
+#      define sg_flags c_lflag
+#      define GTTY(f, s) tcgetattr(f, (zvoid *) s)
+#      define STTY(f, s) tcsetattr(f, TCSAFLUSH, (zvoid *) s)
+#    else /* !HAVE_TERMIOS_H */
+#      ifdef USE_SYSV_TERMIO           /* Amdahl, Cray, all SysV? */
+#        ifdef HAVE_TERMIO_H
+#          include <termio.h>
+#        endif
+#        ifdef HAVE_SYS_TERMIO_H
+#          include <sys/termio.h>
+#        endif
+#        ifdef NEED_PTEM
+#          include <sys/stream.h>
+#          include <sys/ptem.h>
+#        endif
+#        define sgttyb termio
+#        define sg_flags c_lflag
+#        define GTTY(f,s) ioctl(f,TCGETA,(zvoid *)s)
+#        define STTY(f,s) ioctl(f,TCSETAW,(zvoid *)s)
+#      else /* !USE_SYSV_TERMIO */
+#        ifndef CMS_MVS
+#          if (!defined(MINIX) && !defined(GOT_IOCTL_H))
+#            include <sys/ioctl.h>
+#          endif
+#          include <sgtty.h>
+#          define GTTY gtty
+#          define STTY stty
+#          ifdef UNZIP
+             /*
+              * XXX : Are these declarations needed at all ????
+              */
+             /*
+              * GRR: let's find out...   Hmmm, appears not...
+             int gtty OF((int, struct sgttyb *));
+             int stty OF((int, struct sgttyb *));
+              */
+#          endif
+#        endif /* !CMS_MVS */
+#      endif /* ?USE_SYSV_TERMIO */
+#    endif /* ?HAVE_TERMIOS_H */
+#    ifndef NO_FCNTL_H
+#      ifndef UNZIP
+#        include <fcntl.h>
+#      endif
+#    else
+       char *ttyname OF((int));
+#    endif
+#  endif /* ?VMS */
+#endif /* !HAVE_WORKING_GETCH */
+
+
+
+#ifndef HAVE_WORKING_GETCH
+#ifdef VMS
+
+/*
+ * Turn keyboard echoing on or off (VMS).  Loosely based on VMSmunch.c
+ * and hence on Joe Meadows' file.c code.
+ */
+int echo(opt)
+    int opt;
+{
+    /*
+     * For VMS v5.x:
+     *   IO$_SENSEMODE/SETMODE info:  Programming, Vol. 7A, System Programming,
+     *     I/O User's: Part I, sec. 8.4.1.1, 8.4.3, 8.4.5, 8.6
+     *   sys$assign(), sys$qio() info:  Programming, Vol. 4B, System Services,
+     *     System Services Reference Manual, pp. sys-23, sys-379
+     *   fixed-length descriptor info:  Programming, Vol. 3, System Services,
+     *     Intro to System Routines, sec. 2.9.2
+     * Greg Roelofs, 15 Aug 91
+     */
+
+    /* SKM: make global? */
+    static struct dsc$descriptor_s DevDesc =
+        {11, DSC$K_DTYPE_T, DSC$K_CLASS_S, "SYS$COMMAND"};
+     /* {dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer}; */
+    static short           DevChan, iosb[4];
+    static long            status;
+    static unsigned long   oldmode[2], newmode[2];   /* each = 8 bytes */
+
+
+    /* assign a channel to standard input */
+    status = sys$assign(&DevDesc, &DevChan, 0, 0);
+    if (!(status & 1))
+        return status;
+
+    /* use sys$qio and the IO$_SENSEMODE function to determine the current
+     * tty status (for password reading, could use IO$_READVBLK function
+     * instead, but echo on/off will be more general)
+     */
+    status = sys$qiow(0, DevChan, IO$_SENSEMODE, &iosb, 0, 0,
+                     oldmode, 8, 0, 0, 0, 0);
+    if (!(status & 1))
+        return status;
+    status = iosb[0];
+    if (!(status & 1))
+        return status;
+
+    /* copy old mode into new-mode buffer, then modify to be either NOECHO or
+     * ECHO (depending on function argument opt)
+     */
+    newmode[0] = oldmode[0];
+    newmode[1] = oldmode[1];
+    if (opt == 0)   /* off */
+        newmode[1] |= TT$M_NOECHO;                      /* set NOECHO bit */
+    else
+        newmode[1] &= ~((unsigned long) TT$M_NOECHO);   /* clear NOECHO bit */
+
+    /* use the IO$_SETMODE function to change the tty status */
+    status = sys$qiow(0, DevChan, IO$_SETMODE, &iosb, 0, 0,
+                     newmode, 8, 0, 0, 0, 0);
+    if (!(status & 1))
+        return status;
+    status = iosb[0];
+    if (!(status & 1))
+        return status;
+
+    /* deassign the sys$input channel by way of clean-up */
+    status = sys$dassgn(DevChan);
+    if (!(status & 1))
+        return status;
+
+    return SS$_NORMAL;   /* we be happy */
+
+} /* end function echo() */
+
+
+#else /* !VMS:  basically Unix */
+
+
+/* For VM/CMS and MVS, non-echo terminal input is not (yet?) supported. */
+#ifndef CMS_MVS
+
+#ifdef ZIP                      /* moved to globals.h for UnZip */
+   static int echofd=(-1);      /* file descriptor whose echo is off */
+#endif
+
+/*
+ * Turn echo off for file descriptor f.  Assumes that f is a tty device.
+ */
+void Echoff(__G__ f)
+    __GDEF
+    int f;                    /* file descriptor for which to turn echo off */
+{
+    struct sgttyb sg;         /* tty device structure */
+
+    GLOBAL(echofd) = f;
+    GTTY(f, &sg);             /* get settings */
+    sg.sg_flags &= ~ECHO;     /* turn echo off */
+    STTY(f, &sg);
+}
+
+/*
+ * Turn echo back on for file descriptor echofd.
+ */
+void Echon(__G)
+    __GDEF
+{
+    struct sgttyb sg;         /* tty device structure */
+
+    if (GLOBAL(echofd) != -1) {
+        GTTY(GLOBAL(echofd), &sg);    /* get settings */
+        sg.sg_flags |= ECHO;  /* turn echo on */
+        STTY(GLOBAL(echofd), &sg);
+        GLOBAL(echofd) = -1;
+    }
+}
+
+#endif /* !CMS_MVS */
+#endif /* ?VMS */
+
+
+#if (defined(UNZIP) && !defined(FUNZIP))
+
+#if (defined(UNIX) || defined(__BEOS__))
+#ifdef MORE
+
+/*
+ * Get the number of lines on the output terminal.  SCO Unix apparently
+ * defines TIOCGWINSZ but doesn't support it (!M_UNIX).
+ *
+ * GRR:  will need to know width of terminal someday, too, to account for
+ *       line-wrapping.
+ */
+
+#if (defined(TIOCGWINSZ) && !defined(M_UNIX))
+
+int screenlines()
+{
+    struct winsize wsz;
+#ifdef DEBUG_WINSZ
+    static int firsttime = TRUE;
+#endif
+
+    /* see termio(4) under, e.g., SunOS */
+    if (ioctl(1, TIOCGWINSZ, &wsz) == 0) {
+#ifdef DEBUG_WINSZ
+        if (firsttime) {
+            firsttime = FALSE;
+            fprintf(stderr, "ttyio.c screenlines():  ws_row = %d\n",
+              wsz.ws_row);
+        }
+#endif
+        /* number of columns = ws_col */
+        return (wsz.ws_row > 0)? wsz.ws_row : 24;   /* number of rows */
+
+    } else {         /* this happens when piping to more(1), for example */
+#ifdef DEBUG_WINSZ
+        if (firsttime) {
+            firsttime = FALSE;
+            fprintf(stderr,
+              "ttyio.c screenlines():  ioctl(TIOCGWINSZ) failed\n"));
+        }
+#endif
+        return 24;   /* VT-100 assumed to be minimal hardware */
+    }
+}
+
+#else /* !TIOCGWINSZ: service not available, fall back to semi-bogus method */
+
+int screenlines()
+{
+    char *envptr, *getenv();
+    int n;
+
+    /* GRR:  this is overly simplistic, but don't have access to stty/gtty
+     * system anymore
+     */
+    envptr = getenv("LINES");
+    if (envptr == (char *)NULL || (n = atoi(envptr)) < 5)
+        return 24;   /* VT-100 assumed to be minimal hardware */
+    else
+        return n;
+}
+
+#endif /* ?(TIOCGWINSZ && !M_UNIX) */
+#endif /* MORE */
+
+
+/*
+ * Get a character from the given file descriptor without echo or newline.
+ */
+int zgetch(__G__ f)
+    __GDEF
+    int f;                      /* file descriptor from which to read */
+{
+#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
+    char oldmin, oldtim;
+#endif
+    char c;
+    struct sgttyb sg;           /* tty device structure */
+
+    GTTY(f, &sg);               /* get settings */
+#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
+    oldmin = sg.c_cc[VMIN];     /* save old values */
+    oldtim = sg.c_cc[VTIME];
+    sg.c_cc[VMIN] = 1;          /* need only one char to return read() */
+    sg.c_cc[VTIME] = 0;         /* no timeout */
+    sg.sg_flags &= ~ICANON;     /* canonical mode off */
+#else
+    sg.sg_flags |= CBREAK;      /* cbreak mode on */
+#endif
+    sg.sg_flags &= ~ECHO;       /* turn echo off, too */
+    STTY(f, &sg);               /* set cbreak mode */
+    GLOBAL(echofd) = f;         /* in case ^C hit (not perfect: still CBREAK) */
+
+    read(f, &c, 1);             /* read our character */
+
+#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
+    sg.c_cc[VMIN] = oldmin;     /* restore old values */
+    sg.c_cc[VTIME] = oldtim;
+    sg.sg_flags |= ICANON;      /* canonical mode on */
+#else
+    sg.sg_flags &= ~CBREAK;     /* cbreak mode off */
+#endif
+    sg.sg_flags |= ECHO;        /* turn echo on */
+    STTY(f, &sg);               /* restore canonical mode */
+    GLOBAL(echofd) = -1;
+
+    return (int)c;
+}
+
+
+#else /* !UNIX && !__BEOS__ */
+
+
+int zgetch(__G__ f)
+    __GDEF
+    int f;    /* file descriptor from which to read (must be open already) */
+{
+    char c, c2;
+
+/*---------------------------------------------------------------------------
+    Get a character from the given file descriptor without echo; can't fake
+    CBREAK mode (i.e., newline required), but can get rid of all chars up to
+    and including newline.
+  ---------------------------------------------------------------------------*/
+
+    echoff(f);
+    read(f, &c, 1);
+    if (c != '\n')
+        do {
+            read(f, &c2, 1);   /* throw away all other chars up thru newline */
+        } while (c2 != '\n');
+    echon();
+    return (int)c;
+}
+
+#endif /* ?(UNIX || __BEOS__) */
+
+#endif /* UNZIP && !FUNZIP */
+#endif /* !HAVE_WORKING_GETCH */
+
+
+#if CRYPT                       /* getp() is only used with full encryption */
+
+/*
+ * Simple compile-time check for source compatibility between
+ * zcrypt and ttyio:
+ */
+#if (!defined(CR_MAJORVER) || (CR_MAJORVER < 2) || (CR_MINORVER < 7))
+   error:  This Info-ZIP tool requires zcrypt 2.7 or later.
+#endif
+
+/*
+ * Get a password of length n-1 or less into *p using the prompt *m.
+ * The entered password is not echoed.
+ */
+
+#ifdef HAVE_WORKING_GETCH
+/*
+ * For the AMIGA, getch() is defined as Agetch(), which is in
+ * amiga/filedate.c; SAS/C 6.x provides a getch(), but since Agetch()
+ * uses the infrastructure that is already in place in filedate.c, it is
+ * smaller.  With this function, echoff() and echon() are not needed.
+ *
+ * For the MAC, a non-echo macgetch() function is defined in the MacOS
+ * specific sources which uses the event handling mechanism of the
+ * desktop window manager to get a character from the keyboard.
+ *
+ * For the other systems in this section, a non-echo getch() function
+ * is either contained the C runtime library (conio package), or getch()
+ * is defined as an alias for a similar system specific RTL function.
+ */
+
+#ifndef WINDLL   /* WINDLL does not support a console interface */
+#ifndef QDOS     /* QDOS supplies a variant of this function */
+
+/* This is the getp() function for all systems (with TTY type user interface)
+ * that supply a working `non-echo' getch() function for "raw" console input.
+ */
+char *getp(__G__ m, p, n)
+    __GDEF
+    ZCONST char *m;             /* prompt for password */
+    char *p;                    /* return value: line input */
+    int n;                      /* bytes available in p[] */
+{
+    char c;                     /* one-byte buffer for read() to use */
+    int i;                      /* number of characters input */
+    char *w;                    /* warning on retry */
+
+    /* get password */
+    w = "";
+    do {
+        fputs(w, stderr);       /* warning if back again */
+        fputs(m, stderr);       /* display prompt and flush */
+        fflush(stderr);
+        i = 0;
+        do {                    /* read line, keeping first n characters */
+            if ((c = (char)getch()) == '\r')
+                c = '\n';       /* until user hits CR */
+            if (c == 8 || c == 127) {
+                if (i > 0) i--; /* the `backspace' and `del' keys works */
+            }
+            else if (i < n)
+                p[i++] = c;     /* truncate past n */
+        } while (c != '\n');
+        PUTC('\n', stderr);  fflush(stderr);
+        w = "(line too long--try again)\n";
+    } while (p[i-1] != '\n');
+    p[i-1] = 0;                 /* terminate at newline */
+
+    return p;                   /* return pointer to password */
+
+} /* end function getp() */
+
+#endif /* !QDOS */
+#endif /* !WINDLL */
+
+
+#else /* !HAVE_WORKING_GETCH */
+
+
+#if (defined(UNIX) || defined(__MINT__) || defined(__BEOS__))
+
+#ifndef _PATH_TTY
+#  ifdef __MINT__
+#    define _PATH_TTY ttyname(2)
+#  else
+#    define _PATH_TTY "/dev/tty"
+#  endif
+#endif
+
+char *getp(__G__ m, p, n)
+    __GDEF
+    ZCONST char *m;             /* prompt for password */
+    char *p;                    /* return value: line input */
+    int n;                      /* bytes available in p[] */
+{
+    char c;                     /* one-byte buffer for read() to use */
+    int i;                      /* number of characters input */
+    char *w;                    /* warning on retry */
+    int f;                      /* file descriptor for tty device */
+
+#ifdef PASSWD_FROM_STDIN
+    /* Read from stdin. This is unsafe if the password is stored on disk. */
+    f = 0;
+#else
+    /* turn off echo on tty */
+
+    if ((f = open(_PATH_TTY, 0)) == -1)
+        return NULL;
+#endif
+    /* get password */
+    w = "";
+    do {
+        fputs(w, stderr);       /* warning if back again */
+        fputs(m, stderr);       /* prompt */
+        fflush(stderr);
+        i = 0;
+        echoff(f);
+        do {                    /* read line, keeping n */
+            read(f, &c, 1);
+            if (i < n)
+                p[i++] = c;
+        } while (c != '\n');
+        echon();
+        PUTC('\n', stderr);  fflush(stderr);
+        w = "(line too long--try again)\n";
+    } while (p[i-1] != '\n');
+    p[i-1] = 0;                 /* terminate at newline */
+
+#ifndef PASSWD_FROM_STDIN
+    close(f);
+#endif
+
+    return p;                   /* return pointer to password */
+
+} /* end function getp() */
+
+#endif /* UNIX || __MINT__ || __BEOS__ */
+
+
+
+#if (defined(VMS) || defined(CMS_MVS))
+
+char *getp(__G__ m, p, n)
+    __GDEF
+    ZCONST char *m;             /* prompt for password */
+    char *p;                    /* return value: line input */
+    int n;                      /* bytes available in p[] */
+{
+    char c;                     /* one-byte buffer for read() to use */
+    int i;                      /* number of characters input */
+    char *w;                    /* warning on retry */
+    FILE *f;                    /* file structure for SYS$COMMAND device */
+
+#ifdef PASSWD_FROM_STDIN
+    f = stdin;
+#else
+    if ((f = fopen(ctermid(NULL), "r")) == NULL)
+        return NULL;
+#endif
+
+    /* get password */
+    fflush(stdout);
+    w = "";
+    do {
+        if (*w)                 /* bug: VMS apparently adds \n to NULL fputs */
+            fputs(w, stderr);   /* warning if back again */
+        fputs(m, stderr);       /* prompt */
+        fflush(stderr);
+        i = 0;
+        echoff(f);
+        do {                    /* read line, keeping n */
+            if ((c = (char)getc(f)) == '\r')
+                c = '\n';
+            if (i < n)
+                p[i++] = c;
+        } while (c != '\n');
+        echon();
+        PUTC('\n', stderr);  fflush(stderr);
+        w = "(line too long--try again)\n";
+    } while (p[i-1] != '\n');
+    p[i-1] = 0;                 /* terminate at newline */
+#ifndef PASSWD_FROM_STDIN
+    fclose(f);
+#endif
+
+    return p;                   /* return pointer to password */
+
+} /* end function getp() */
+
+#endif /* VMS || CMS_MVS */
+#endif /* ?HAVE_WORKING_GETCH */
+#endif /* CRYPT */
+#endif /* CRYPT || (UNZIP && !FUNZIP) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/unix.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,1424 @@
+/*---------------------------------------------------------------------------
+
+  unix.c
+
+  Unix-specific routines for use with Info-ZIP's UnZip 5.3 and later.
+
+  Contains:  readdir()
+             do_wild()           <-- generic enough to put in fileio.c?
+             mapattr()
+             mapname()
+             checkdir()
+             mkdir()
+             close_outfile()
+             set_direc_attribs()
+             stamp_file()
+             version()
+
+  ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+
+#ifdef SCO_XENIX
+#  define SYSNDIR
+#else  /* SCO Unix, AIX, DNIX, TI SysV, Coherent 4.x, ... */
+#  if defined(__convexc__) || defined(SYSV) || defined(CRAY) || defined(BSD4_4)
+#    define DIRENT
+#  endif
+#endif
+#if defined(_AIX)
+#  define DIRENT
+#endif
+#ifdef COHERENT
+#  if defined(_I386) || (defined(__COHERENT__) && (__COHERENT__ >= 0x420))
+#    define DIRENT
+#  endif
+#endif
+
+/* GRR:  may need to uncomment this: */
+#if 0
+#if defined(_POSIX_VERSION)
+#  define DIRENT
+#endif
+#endif
+
+#ifdef DIRENT
+#  include <dirent.h>
+#else
+#  ifdef SYSV
+#    ifdef SYSNDIR
+#      include <sys/ndir.h>
+#    else
+#      include <ndir.h>
+#    endif
+#  else /* !SYSV */
+#    ifndef NO_SYSDIR
+#      include <sys/dir.h>
+#    endif
+#  endif /* ?SYSV */
+#  ifndef dirent
+#    define dirent direct
+#  endif
+#endif /* ?DIRENT */
+
+#ifdef ACORN_FTYPE_NFS
+/* Acorn bits for NFS filetyping */
+typedef struct {
+  uch ID[2];
+  uch size[2];
+  uch ID_2[4];
+  uch loadaddr[4];
+  uch execaddr[4];
+  uch attr[4];
+} RO_extra_block;
+
+static int isRISCOSexfield OF((uch *extra_field));
+#endif /* ACORN_FTYPE_NFS */
+
+static int created_dir;        /* used in mapname(), checkdir() */
+static int renamed_fullpath;   /* ditto */
+
+
+#ifndef SFX
+#ifdef NO_DIR                  /* for AT&T 3B1 */
+
+#define opendir(path) fopen(path,"r")
+#define closedir(dir) fclose(dir)
+typedef FILE DIR;
+
+/*
+ *  Apparently originally by Rich Salz.
+ *  Cleaned up and modified by James W. Birdsall.
+ */
+struct dirent *readdir(dirp)
+    DIR *dirp;
+{
+    static struct dirent entry;
+
+    if (dirp == NULL)
+        return NULL;
+
+    for (;;)
+        if (fread(&entry, sizeof (struct dirent), 1, dirp) == 0)
+            return (struct dirent *)NULL;
+        else if (entry.d_ino)
+            return &entry;
+
+} /* end function readdir() */
+
+#endif /* NO_DIR */
+
+
+/**********************/
+/* Function do_wild() */   /* for porting:  dir separator; match(ignore_case) */
+/**********************/
+
+char *do_wild(__G__ wildspec)
+    __GDEF
+    char *wildspec;         /* only used first time on a given dir */
+{
+    static DIR *dir = (DIR *)NULL;
+    static char *dirname, *wildname, matchname[FILNAMSIZ];
+    static int firstcall=TRUE, have_dirname, dirnamelen;
+    struct dirent *file;
+
+
+    /* Even when we're just returning wildspec, we *always* do so in
+     * matchname[]--calling routine is allowed to append four characters
+     * to the returned string, and wildspec may be a pointer to argv[].
+     */
+    if (firstcall) {        /* first call:  must initialize everything */
+        firstcall = FALSE;
+
+        if (!iswild(wildspec)) {
+            strcpy(matchname, wildspec);
+            have_dirname = FALSE;
+            dir = NULL;
+            return matchname;
+        }
+
+        /* break the wildspec into a directory part and a wildcard filename */
+        if ((wildname = strrchr(wildspec, '/')) == (char *)NULL) {
+            dirname = ".";
+            dirnamelen = 1;
+            have_dirname = FALSE;
+            wildname = wildspec;
+        } else {
+            ++wildname;     /* point at character after '/' */
+            dirnamelen = wildname - wildspec;
+            if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) {
+                Info(slide, 0x201, ((char *)slide,
+                  "warning:  cannot allocate wildcard buffers\n"));
+                strcpy(matchname, wildspec);
+                return matchname;   /* but maybe filespec was not a wildcard */
+            }
+            strncpy(dirname, wildspec, dirnamelen);
+            dirname[dirnamelen] = '\0';   /* terminate for strcpy below */
+            have_dirname = TRUE;
+        }
+
+        if ((dir = opendir(dirname)) != (DIR *)NULL) {
+            while ((file = readdir(dir)) != (struct dirent *)NULL) {
+                Trace((stderr, "do_wild:  readdir returns %s\n", file->d_name));
+                if (file->d_name[0] == '.' && wildname[0] != '.')
+                    continue;  /* Unix:  '*' and '?' do not match leading dot */
+                if (match(file->d_name, wildname, 0) &&  /* 0 == case sens. */
+                    /* skip "." and ".." directory entries */
+                    strcmp(file->d_name, ".") && strcmp(file->d_name, "..")) {
+                    Trace((stderr, "do_wild:  match() succeeds\n"));
+                    if (have_dirname) {
+                        strcpy(matchname, dirname);
+                        strcpy(matchname+dirnamelen, file->d_name);
+                    } else
+                        strcpy(matchname, file->d_name);
+                    return matchname;
+                }
+            }
+            /* if we get to here directory is exhausted, so close it */
+            closedir(dir);
+            dir = (DIR *)NULL;
+        }
+
+        /* return the raw wildspec in case that works (e.g., directory not
+         * searchable, but filespec was not wild and file is readable) */
+        strcpy(matchname, wildspec);
+        return matchname;
+    }
+
+    /* last time through, might have failed opendir but returned raw wildspec */
+    if (dir == (DIR *)NULL) {
+        firstcall = TRUE;  /* nothing left to try--reset for new wildspec */
+        if (have_dirname)
+            free(dirname);
+        return (char *)NULL;
+    }
+
+    /* If we've gotten this far, we've read and matched at least one entry
+     * successfully (in a previous call), so dirname has been copied into
+     * matchname already.
+     */
+    while ((file = readdir(dir)) != (struct dirent *)NULL) {
+        Trace((stderr, "do_wild:  readdir returns %s\n", file->d_name));
+        if (file->d_name[0] == '.' && wildname[0] != '.')
+            continue;   /* Unix:  '*' and '?' do not match leading dot */
+        if (match(file->d_name, wildname, 0)) {   /* 0 == don't ignore case */
+            Trace((stderr, "do_wild:  match() succeeds\n"));
+            if (have_dirname) {
+                /* strcpy(matchname, dirname); */
+                strcpy(matchname+dirnamelen, file->d_name);
+            } else
+                strcpy(matchname, file->d_name);
+            return matchname;
+        }
+    }
+
+    closedir(dir);     /* have read at least one dir entry; nothing left */
+    dir = (DIR *)NULL;
+    firstcall = TRUE;  /* reset for new wildspec */
+    if (have_dirname)
+        free(dirname);
+    return (char *)NULL;
+
+} /* end function do_wild() */
+
+#endif /* !SFX */
+
+
+
+
+
+/**********************/
+/* Function mapattr() */
+/**********************/
+
+int mapattr(__G)
+    __GDEF
+{
+    ulg tmp = G.crec.external_file_attributes;
+
+    G.pInfo->file_attr = 0;
+    /* initialized to 0 for check in "default" branch below... */
+
+    switch (G.pInfo->hostnum) {
+        case AMIGA_:
+            tmp = (unsigned)(tmp>>17 & 7);   /* Amiga RWE bits */
+            G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp);
+            break;
+        case UNIX_:
+        case VMS_:
+        case ACORN_:
+        case ATARI_:
+        case BEOS_:
+        case QDOS_:
+        case TANDEM_:
+            G.pInfo->file_attr = (unsigned)(tmp >> 16);
+            if (G.pInfo->file_attr != 0 || !G.extra_field) {
+                return 0;
+            } else {
+                /* Some (non-Info-ZIP) implementations of Zip for Unix and
+                 * VMS (and probably others ??) leave 0 in the upper 16-bit
+                 * part of the external_file_attributes field. Instead, they
+                 * store file permission attributes in some extra field.
+                 * As a work-around, we search for the presence of one of
+                 * these extra fields and fall back to the MSDOS compatible
+                 * part of external_file_attributes if one of the known
+                 * e.f. types has been detected.
+                 * Later, we might implement extraction of the permission
+                 * bits from the VMS extra field. But for now, the work-around
+                 * should be sufficient to provide "readable" extracted files.
+                 * (For ASI Unix e.f., an experimental remap from the e.f.
+                 * mode value IS already provided!)
+                 */
+                ush ebID;
+                unsigned ebLen;
+                uch *ef = G.extra_field;
+                unsigned ef_len = G.crec.extra_field_length;
+                int r = FALSE;
+
+                while (!r && ef_len >= EB_HEADSIZE) {
+                    ebID = makeword(ef);
+                    ebLen = (unsigned)makeword(ef+EB_LEN);
+                    if (ebLen > (ef_len - EB_HEADSIZE))
+                        /* discoverd some e.f. inconsistency! */
+                        break;
+                    switch (ebID) {
+                      case EF_ASIUNIX:
+                        if (ebLen >= (EB_ASI_MODE+2)) {
+                            G.pInfo->file_attr =
+                              (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE));
+                            /* force stop of loop: */
+                            ef_len = (ebLen + EB_HEADSIZE);
+                            break;
+                        }
+                        /* else: fall through! */
+                      case EF_PKVMS:
+                        /* "found nondecypherable e.f. with perm. attr" */
+                        r = TRUE;
+                      default:
+                        break;
+                    }
+                    ef_len -= (ebLen + EB_HEADSIZE);
+                    ef += (ebLen + EB_HEADSIZE);
+                }
+                if (!r)
+                    return 0;
+            }
+            /* fall through! */
+        /* all remaining cases:  expand MSDOS read-only bit into write perms */
+        case FS_FAT_:
+            /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the
+             * Unix attributes in the upper 16 bits of the external attributes
+             * field, just like Info-ZIP's Zip for Unix.  We try to use that
+             * value, after a check for consistency with the MSDOS attribute
+             * bits (see below).
+             */
+            G.pInfo->file_attr = (unsigned)(tmp >> 16);
+            /* fall through! */
+        case FS_HPFS_:
+        case FS_NTFS_:
+        case MAC_:
+        case TOPS20_:
+        default:
+            /* read-only bit --> write perms; subdir bit --> dir exec bit */
+            tmp = !(tmp & 1) << 1  |  (tmp & 0x10) >> 4;
+            if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6))
+                /* keep previous G.pInfo->file_attr setting, when its "owner"
+                 * part appears to be consistent with DOS attribute flags!
+                 */
+                return 0;
+            G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp);
+            break;
+    } /* end switch (host-OS-created-by) */
+
+    /* for originating systems with no concept of "group," "other," "system": */
+    umask( (int)(tmp=umask(0)) );    /* apply mask to expanded r/w(/x) perms */
+    G.pInfo->file_attr &= ~tmp;
+
+    return 0;
+
+} /* end function mapattr() */
+
+
+
+
+
+/************************/
+/*  Function mapname()  */
+/************************/
+                             /* return 0 if no error, 1 if caution (filename */
+int mapname(__G__ renamed)   /*  truncated), 2 if warning (skip file because */
+    __GDEF                   /*  dir doesn't exist), 3 if error (skip file), */
+    int renamed;             /*  or 10 if out of memory (skip file) */
+{                            /*  [also IZ_VOL_LABEL, IZ_CREATED_DIR] */
+    char pathcomp[FILNAMSIZ];      /* path-component buffer */
+    char *pp, *cp=(char *)NULL;    /* character pointers */
+    char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */
+#ifdef ACORN_FTYPE_NFS
+    char *lastcomma=(char *)NULL;  /* pointer to last comma in pathcomp */
+#endif
+    int quote = FALSE;             /* flags */
+    int error = 0;
+    register unsigned workch;      /* hold the character being tested */
+
+
+/*---------------------------------------------------------------------------
+    Initialize various pointers and counters and stuff.
+  ---------------------------------------------------------------------------*/
+
+    if (G.pInfo->vollabel)
+        return IZ_VOL_LABEL;    /* can't set disk volume labels in Unix */
+
+    /* can create path as long as not just freshening, or if user told us */
+    G.create_dirs = (!uO.fflag || renamed);
+
+    created_dir = FALSE;        /* not yet */
+
+    /* user gave full pathname:  don't prepend rootpath */
+    renamed_fullpath = (renamed && (*G.filename == '/'));
+
+    if (checkdir(__G__ (char *)NULL, INIT) == 10)
+        return 10;              /* initialize path buffer, unless no memory */
+
+    *pathcomp = '\0';           /* initialize translation buffer */
+    pp = pathcomp;              /* point to translation buffer */
+    if (uO.jflag)               /* junking directories */
+        cp = (char *)strrchr(G.filename, '/');
+    if (cp == (char *)NULL)     /* no '/' or not junking dirs */
+        cp = G.filename;        /* point to internal zipfile-member pathname */
+    else
+        ++cp;                   /* point to start of last component of path */
+
+/*---------------------------------------------------------------------------
+    Begin main loop through characters in filename.
+  ---------------------------------------------------------------------------*/
+
+    while ((workch = (uch)*cp++) != 0) {
+
+        if (quote) {                 /* if character quoted, */
+            *pp++ = (char)workch;    /*  include it literally */
+            quote = FALSE;
+        } else
+            switch (workch) {
+            case '/':             /* can assume -j flag not given */
+                *pp = '\0';
+                if ((error = checkdir(__G__ pathcomp, APPEND_DIR)) > 1)
+                    return error;
+                pp = pathcomp;    /* reset conversion buffer for next piece */
+                lastsemi = (char *)NULL; /* leave directory semi-colons alone */
+                break;
+
+            case ';':             /* VMS version (or DEC-20 attrib?) */
+                lastsemi = pp;
+                *pp++ = ';';      /* keep for now; remove VMS ";##" */
+                break;            /*  later, if requested */
+
+#ifdef ACORN_FTYPE_NFS
+            case ',':             /* NFS filetype extension */
+                lastcomma = pp;
+                *pp++ = ',';      /* keep for now; may need to remove */
+                break;            /*  later, if requested */
+#endif
+
+            case '\026':          /* control-V quote for special chars */
+                quote = TRUE;     /* set flag for next character */
+                break;
+
+#ifdef MTS
+            case ' ':             /* change spaces to underscore under */
+                *pp++ = '_';      /*  MTS; leave as spaces under Unix */
+                break;
+#endif
+
+            default:
+                /* allow European characters in filenames: */
+                if (isprint(workch) || (128 <= workch && workch <= 254))
+                    *pp++ = (char)workch;
+            } /* end switch */
+
+    } /* end while loop */
+
+    *pp = '\0';                   /* done with pathcomp:  terminate it */
+
+    /* if not saving them, remove VMS version numbers (appended ";###") */
+    if (!uO.V_flag && lastsemi) {
+        pp = lastsemi + 1;
+        while (isdigit((uch)(*pp)))
+            ++pp;
+        if (*pp == '\0')          /* only digits between ';' and end:  nuke */
+            *lastsemi = '\0';
+    }
+
+#ifdef ACORN_FTYPE_NFS
+    /* translate Acorn filetype information if asked to do so */
+    if (uO.acorn_nfs_ext && isRISCOSexfield(G.extra_field)) {
+        /* file *must* have a RISC OS extra field */
+        int ft = (int)makelong(((RO_extra_block *)G.extra_field)->loadaddr);
+        /*32-bit*/
+        if (lastcomma) {
+            pp = lastcomma + 1;
+            while (isxdigit((uch)(*pp))) ++pp;
+            if (pp == lastcomma+4 && *pp == '\0') *lastcomma='\0'; /* nuke */
+        }
+        if ((ft & 1<<31)==0) ft=0x000FFD00;
+        sprintf(pathcomp+strlen(pathcomp), ",%03x", ft>>8 & 0xFFF);
+    }
+#endif /* ACORN_FTYPE_NFS */
+
+/*---------------------------------------------------------------------------
+    Report if directory was created (and no file to create:  filename ended
+    in '/'), check name to be sure it exists, and combine path and name be-
+    fore exiting.
+  ---------------------------------------------------------------------------*/
+
+    if (G.filename[strlen(G.filename) - 1] == '/') {
+        checkdir(__G__ G.filename, GETPATH);
+        if (created_dir) {
+            if (QCOND2) {
+                Info(slide, 0, ((char *)slide, "   creating: %s\n",
+                  G.filename));
+            }
+#ifndef NO_CHMOD
+            /* set approx. dir perms (make sure can still read/write in dir) */
+            if (chmod(G.filename, (0xffff & G.pInfo->file_attr) | 0700))
+                perror("chmod (directory attributes) error");
+#endif
+            return IZ_CREATED_DIR;   /* set dir time (note trailing '/') */
+        }
+        return 2;   /* dir existed already; don't look for data to extract */
+    }
+
+    if (*pathcomp == '\0') {
+        Info(slide, 1, ((char *)slide, "mapname:  conversion of %s failed\n",
+          G.filename));
+        return 3;
+    }
+
+    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */
+    checkdir(__G__ G.filename, GETPATH);
+
+    return error;
+
+} /* end function mapname() */
+
+
+
+
+#if 0  /*========== NOTES ==========*/
+
+  extract-to dir:      a:path/
+  buildpath:           path1/path2/ ...   (NULL-terminated)
+  pathcomp:                filename
+
+  mapname():
+    loop over chars in zipfile member name
+      checkdir(path component, COMPONENT | CREATEDIR) --> map as required?
+        (d:/tmp/unzip/)                    (disk:[tmp.unzip.)
+        (d:/tmp/unzip/jj/)                 (disk:[tmp.unzip.jj.)
+        (d:/tmp/unzip/jj/temp/)            (disk:[tmp.unzip.jj.temp.)
+    finally add filename itself and check for existence? (could use with rename)
+        (d:/tmp/unzip/jj/temp/msg.outdir)  (disk:[tmp.unzip.jj.temp]msg.outdir)
+    checkdir(name, GETPATH)     -->  copy path to name and free space
+
+#endif /* 0 */
+
+
+
+
+/***********************/
+/* Function checkdir() */
+/***********************/
+
+int checkdir(__G__ pathcomp, flag)
+    __GDEF
+    char *pathcomp;
+    int flag;
+/*
+ * returns:  1 - (on APPEND_NAME) truncated filename
+ *           2 - path doesn't exist, not allowed to create
+ *           3 - path doesn't exist, tried to create and failed; or
+ *               path exists and is not a directory, but is supposed to be
+ *           4 - path is too long
+ *          10 - can't allocate memory for filename buffers
+ */
+{
+    static int rootlen = 0;   /* length of rootpath */
+    static char *rootpath;    /* user's "extract-to" directory */
+    static char *buildpath;   /* full path (so far) to extracted file */
+    static char *end;         /* pointer to end of buildpath ('\0') */
+
+#   define FN_MASK   7
+#   define FUNCTION  (flag & FN_MASK)
+
+
+
+/*---------------------------------------------------------------------------
+    APPEND_DIR:  append the path component to the path being built and check
+    for its existence.  If doesn't exist and we are creating directories, do
+    so for this one; else signal success or error as appropriate.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == APPEND_DIR) {
+        int too_long = FALSE;
+#ifdef SHORT_NAMES
+        char *old_end = end;
+#endif
+
+        Trace((stderr, "appending dir segment [%s]\n", pathcomp));
+        while ((*end = *pathcomp++) != '\0')
+            ++end;
+#ifdef SHORT_NAMES   /* path components restricted to 14 chars, typically */
+        if ((end-old_end) > FILENAME_MAX)  /* GRR:  proper constant? */
+            *(end = old_end + FILENAME_MAX) = '\0';
+#endif
+
+        /* GRR:  could do better check, see if overrunning buffer as we go:
+         * check end-buildpath after each append, set warning variable if
+         * within 20 of FILNAMSIZ; then if var set, do careful check when
+         * appending.  Clear variable when begin new path. */
+
+        if ((end-buildpath) > FILNAMSIZ-3)  /* need '/', one-char name, '\0' */
+            too_long = TRUE;                /* check if extracting directory? */
+        if (stat(buildpath, &G.statbuf)) {  /* path doesn't exist */
+            if (!G.create_dirs) { /* told not to create (freshening) */
+                free(buildpath);
+                return 2;         /* path doesn't exist:  nothing to do */
+            }
+            if (too_long) {
+                Info(slide, 1, ((char *)slide,
+                  "checkdir error:  path too long: %s\n", buildpath));
+                free(buildpath);
+                return 4;         /* no room for filenames:  fatal */
+            }
+            if (mkdir(buildpath, 0777) == -1) {   /* create the directory */
+                Info(slide, 1, ((char *)slide,
+                  "checkdir error:  cannot create %s\n\
+                 unable to process %s.\n", buildpath, G.filename));
+                free(buildpath);
+                return 3;      /* path didn't exist, tried to create, failed */
+            }
+            created_dir = TRUE;
+        } else if (!S_ISDIR(G.statbuf.st_mode)) {
+            Info(slide, 1, ((char *)slide,
+              "checkdir error:  %s exists but is not directory\n\
+                 unable to process %s.\n", buildpath, G.filename));
+            free(buildpath);
+            return 3;          /* path existed but wasn't dir */
+        }
+        if (too_long) {
+            Info(slide, 1, ((char *)slide,
+              "checkdir error:  path too long: %s\n", buildpath));
+            free(buildpath);
+            return 4;         /* no room for filenames:  fatal */
+        }
+        *end++ = '/';
+        *end = '\0';
+        Trace((stderr, "buildpath now = [%s]\n", buildpath));
+        return 0;
+
+    } /* end if (FUNCTION == APPEND_DIR) */
+
+/*---------------------------------------------------------------------------
+    GETPATH:  copy full path to the string pointed at by pathcomp, and free
+    buildpath.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == GETPATH) {
+        strcpy(pathcomp, buildpath);
+        Trace((stderr, "getting and freeing path [%s]\n", pathcomp));
+        free(buildpath);
+        buildpath = end = (char *)NULL;
+        return 0;
+    }
+
+/*---------------------------------------------------------------------------
+    APPEND_NAME:  assume the path component is the filename; append it and
+    return without checking for existence.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == APPEND_NAME) {
+#ifdef SHORT_NAMES
+        char *old_end = end;
+#endif
+
+        Trace((stderr, "appending filename [%s]\n", pathcomp));
+        while ((*end = *pathcomp++) != '\0') {
+            ++end;
+#ifdef SHORT_NAMES  /* truncate name at 14 characters, typically */
+            if ((end-old_end) > FILENAME_MAX)      /* GRR:  proper constant? */
+                *(end = old_end + FILENAME_MAX) = '\0';
+#endif
+            if ((end-buildpath) >= FILNAMSIZ) {
+                *--end = '\0';
+                Info(slide, 0x201, ((char *)slide,
+                  "checkdir warning:  path too long; truncating\n\
+                   %s\n                -> %s\n", G.filename, buildpath));
+                return 1;   /* filename truncated */
+            }
+        }
+        Trace((stderr, "buildpath now = [%s]\n", buildpath));
+        return 0;  /* could check for existence here, prompt for new name... */
+    }
+
+/*---------------------------------------------------------------------------
+    INIT:  allocate and initialize buffer space for the file currently being
+    extracted.  If file was renamed with an absolute path, don't prepend the
+    extract-to path.
+  ---------------------------------------------------------------------------*/
+
+/* GRR:  for VMS and TOPS-20, add up to 13 to strlen */
+
+    if (FUNCTION == INIT) {
+        Trace((stderr, "initializing buildpath to "));
+#ifdef ACORN_FTYPE_NFS
+        if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+
+                                        (uO.acorn_nfs_ext ? 5 : 1)))
+#else
+        if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+1))
+#endif
+            == (char *)NULL)
+            return 10;
+        if ((rootlen > 0) && !renamed_fullpath) {
+            strcpy(buildpath, rootpath);
+            end = buildpath + rootlen;
+        } else {
+            *buildpath = '\0';
+            end = buildpath;
+        }
+        Trace((stderr, "[%s]\n", buildpath));
+        return 0;
+    }
+
+/*---------------------------------------------------------------------------
+    ROOT:  if appropriate, store the path in rootpath and create it if neces-
+    sary; else assume it's a zipfile member and return.  This path segment
+    gets used in extracting all members from every zipfile specified on the
+    command line.
+  ---------------------------------------------------------------------------*/
+
+#if (!defined(SFX) || defined(SFX_EXDIR))
+    if (FUNCTION == ROOT) {
+        Trace((stderr, "initializing root path to [%s]\n", pathcomp));
+        if (pathcomp == (char *)NULL) {
+            rootlen = 0;
+            return 0;
+        }
+        if ((rootlen = strlen(pathcomp)) > 0) {
+            if (pathcomp[rootlen-1] == '/') {
+                pathcomp[--rootlen] = '\0';
+            }
+            if (rootlen > 0 && (stat(pathcomp, &G.statbuf) ||
+                !S_ISDIR(G.statbuf.st_mode)))       /* path does not exist */
+            {
+                if (!G.create_dirs /* || iswild(pathcomp) */ ) {
+                    rootlen = 0;
+                    return 2;   /* skip (or treat as stored file) */
+                }
+                /* create the directory (could add loop here to scan pathcomp
+                 * and create more than one level, but why really necessary?) */
+                if (mkdir(pathcomp, 0777) == -1) {
+                    Info(slide, 1, ((char *)slide,
+                      "checkdir:  cannot create extraction directory: %s\n",
+                      pathcomp));
+                    rootlen = 0;   /* path didn't exist, tried to create, and */
+                    return 3;  /* failed:  file exists, or 2+ levels required */
+                }
+            }
+            if ((rootpath = (char *)malloc(rootlen+2)) == (char *)NULL) {
+                rootlen = 0;
+                return 10;
+            }
+            strcpy(rootpath, pathcomp);
+            rootpath[rootlen++] = '/';
+            rootpath[rootlen] = '\0';
+            Trace((stderr, "rootpath now = [%s]\n", rootpath));
+        }
+        return 0;
+    }
+#endif /* !SFX || SFX_EXDIR */
+
+/*---------------------------------------------------------------------------
+    END:  free rootpath, immediately prior to program exit.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == END) {
+        Trace((stderr, "freeing rootpath\n"));
+        if (rootlen > 0) {
+            free(rootpath);
+            rootlen = 0;
+        }
+        return 0;
+    }
+
+    return 99;  /* should never reach */
+
+} /* end function checkdir() */
+
+
+
+
+
+#ifdef NO_MKDIR
+
+/********************/
+/* Function mkdir() */
+/********************/
+
+int mkdir(path, mode)
+    char *path;
+    int mode;   /* ignored */
+/*
+ * returns:   0 - successful
+ *           -1 - failed (errno not set, however)
+ */
+{
+    char command[FILNAMSIZ+40]; /* buffer for system() call */
+
+    /* GRR 930416:  added single quotes around path to avoid bug with
+     * creating directories with ampersands in name; not yet tested */
+    sprintf(command, "IFS=\" \t\n\" /bin/mkdir '%s' 2>/dev/null", path);
+    if (system(command))
+        return -1;
+    return 0;
+}
+
+#endif /* NO_MKDIR */
+
+
+
+
+
+#if 0
+#ifdef MORE
+
+/**************************/
+/* Function screenlines() */
+/**************************/
+
+int screenlines()
+{
+    char *envptr, *getenv();
+    int n;
+
+    /* GRR:  this is overly simplistic; should use winsize struct and
+     * appropriate TIOCGWINSZ ioctl(), assuming exists on enough systems
+     */
+    envptr = getenv("LINES");
+    if (envptr == (char *)NULL || (n = atoi(envptr)) < 5)
+        return 24;   /* VT-100 assumed to be minimal hardware */
+    else
+        return n;
+}
+
+#endif /* MORE */
+#endif /* 0 */
+
+
+
+
+
+#ifndef MTS
+
+/****************************/
+/* Function close_outfile() */
+/****************************/
+
+void close_outfile(__G)    /* GRR: change to return PK-style warning level */
+    __GDEF
+{
+    iztimes zt;
+    ush z_uidgid[2];
+    unsigned eb_izux_flg;
+
+/*---------------------------------------------------------------------------
+    If symbolic links are supported, allocate a storage area, put the uncom-
+    pressed "data" in it, and create the link.  Since we know it's a symbolic
+    link to start with, we shouldn't have to worry about overflowing unsigned
+    ints with unsigned longs.
+  ---------------------------------------------------------------------------*/
+
+#ifdef SYMLINKS
+    if (G.symlnk) {
+        unsigned ucsize = (unsigned)G.lrec.ucsize;
+        char *linktarget = (char *)malloc((unsigned)G.lrec.ucsize+1);
+
+        fclose(G.outfile);                      /* close "data" file... */
+        G.outfile = fopen(G.filename, FOPR);    /* ...and reopen for reading */
+        if (!linktarget || fread(linktarget, 1, ucsize, G.outfile) !=
+                           (int)ucsize)
+        {
+            Info(slide, 0x201, ((char *)slide,
+              "warning:  symbolic link (%s) failed\n", G.filename));
+            if (linktarget)
+                free(linktarget);
+            fclose(G.outfile);
+            return;
+        }
+        fclose(G.outfile);                  /* close "data" file for good... */
+        unlink(G.filename);                 /* ...and delete it */
+        linktarget[ucsize] = '\0';
+        if (QCOND2)
+            Info(slide, 0, ((char *)slide, "-> %s ", linktarget));
+        if (symlink(linktarget, G.filename))  /* create the real link */
+            perror("symlink error");
+        free(linktarget);
+        return;                             /* can't set time on symlinks */
+    }
+#endif /* SYMLINKS */
+
+    fclose(G.outfile);
+#ifdef QLZIP
+    if (G.extra_field) {
+        static void qlfix OF((__GPRO__ uch *ef_ptr, unsigned ef_len));
+
+        qlfix(__G__ G.extra_field, G.lrec.extra_field_length);
+    }
+#endif
+
+/*---------------------------------------------------------------------------
+    Convert from MSDOS-format local time and date to Unix-format 32-bit GMT
+    time:  adjust base year from 1980 to 1970, do usual conversions from
+    yy/mm/dd hh:mm:ss to elapsed seconds, and account for timezone and day-
+    light savings time differences.  If we have a Unix extra field, however,
+    we're laughing:  both mtime and atime are ours.  On the other hand, we
+    then have to check for restoration of UID/GID.
+  ---------------------------------------------------------------------------*/
+
+    eb_izux_flg = (G.extra_field ? ef_scan_for_izux(G.extra_field,
+                   G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime,
+#ifdef IZ_CHECK_TZ
+                   (G.tz_is_valid ? &zt : NULL),
+#else
+                   &zt,
+#endif
+                   z_uidgid) : 0);
+    if (eb_izux_flg & EB_UT_FL_MTIME) {
+        TTrace((stderr, "\nclose_outfile:  Unix e.f. modif. time = %ld\n",
+          zt.mtime));
+    } else {
+        zt.mtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
+    }
+    if (eb_izux_flg & EB_UT_FL_ATIME) {
+        TTrace((stderr, "close_outfile:  Unix e.f. access time = %ld\n",
+          zt.atime));
+    } else {
+        zt.atime = zt.mtime;
+        TTrace((stderr, "\nclose_outfile:  modification/access times = %ld\n",
+          zt.mtime));
+    }
+
+    /* if -X option was specified and we have UID/GID info, restore it */
+    if (uO.X_flag && eb_izux_flg & EB_UX2_VALID) {
+        TTrace((stderr, "close_outfile:  restoring Unix UID/GID info\n"));
+        if (chown(G.filename, (uid_t)z_uidgid[0], (gid_t)z_uidgid[1]))
+        {
+            if (uO.qflag)
+                Info(slide, 0x201, ((char *)slide,
+                  "warning:  cannot set UID %d and/or GID %d for %s\n",
+                  z_uidgid[0], z_uidgid[1], G.filename));
+            else
+                Info(slide, 0x201, ((char *)slide,
+                  " (warning) cannot set UID %d and/or GID %d",
+                  z_uidgid[0], z_uidgid[1]));
+        }
+    }
+
+    /* set the file's access and modification times */
+    if (utime(G.filename, (ztimbuf *)&zt)) {
+#ifdef AOS_VS
+        if (uO.qflag)
+            Info(slide, 0x201, ((char *)slide, "... cannot set time for %s\n",
+              G.filename));
+        else
+            Info(slide, 0x201, ((char *)slide, "... cannot set time"));
+#else
+        if (uO.qflag)
+            Info(slide, 0x201, ((char *)slide,
+              "warning:  cannot set times for %s\n", G.filename));
+        else
+            Info(slide, 0x201, ((char *)slide,
+              " (warning) cannot set times"));
+#endif /* ?AOS_VS */
+    }
+
+/*---------------------------------------------------------------------------
+    Change the file permissions from default ones to those stored in the
+    zipfile.
+  ---------------------------------------------------------------------------*/
+
+#ifndef NO_CHMOD
+    if (chmod(G.filename, 0xffff & G.pInfo->file_attr))
+        perror("chmod (file attributes) error");
+#endif
+
+} /* end function close_outfile() */
+
+#endif /* !MTS */
+
+
+
+
+#ifdef SET_DIR_ATTRIB
+/* messages of code for setting directory attributes */
+static char Far DirlistUidGidFailed[] =
+  "warning:  cannot set UID %d and/or GID %d for %s\n";
+static char Far DirlistUtimeFailed[] =
+  "warning:  cannot set modification, access times for %s\n";
+#  ifndef NO_CHMOD
+  static char Far DirlistChmodFailed[] =
+    "warning:  cannot set permissions for %s\n";
+#  endif
+
+
+int set_direc_attribs(__G__ d)
+    __GDEF
+    dirtime *d;
+{
+    int errval = PK_OK;
+
+    if (d->have_uidgid &&
+        chown(d->fn, (uid_t)d->uidgid[0], (gid_t)d->uidgid[1]))
+    {
+        Info(slide, 0x201, ((char *)slide,
+          LoadFarString(DirlistUidGidFailed),
+          d->uidgid[0], d->uidgid[1], d->fn));
+        if (!errval)
+            errval = PK_WARN;
+    }
+    if (utime(d->fn, &d->u.t2)) {
+        Info(slide, 0x201, ((char *)slide,
+          LoadFarString(DirlistUtimeFailed), d->fn));
+        if (!errval)
+            errval = PK_WARN;
+    }
+#ifndef NO_CHMOD
+    if (chmod(d->fn, 0xffff & d->perms)) {
+        Info(slide, 0x201, ((char *)slide,
+          LoadFarString(DirlistChmodFailed), d->fn));
+        /* perror("chmod (file attributes) error"); */
+        if (!errval)
+            errval = PK_WARN;
+    }
+#endif /* !NO_CHMOD */
+    return errval;
+} /* end function set_directory_attributes() */
+
+#endif /* SET_DIR_ATTRIB */
+
+
+
+
+#ifdef TIMESTAMP
+
+/***************************/
+/*  Function stamp_file()  */
+/***************************/
+
+int stamp_file(fname, modtime)
+    ZCONST char *fname;
+    time_t modtime;
+{
+    ztimbuf tp;
+
+    tp.modtime = tp.actime = modtime;
+    return (utime(fname, &tp));
+
+} /* end function stamp_file() */
+
+#endif /* TIMESTAMP */
+
+
+
+
+#ifndef SFX
+
+/************************/
+/*  Function version()  */
+/************************/
+
+void version(__G)
+    __GDEF
+{
+#if defined(CRAY) || defined(NX_CURRENT_COMPILER_RELEASE) || defined(NetBSD)
+    char buf1[40];
+#if defined(CRAY) || defined(NX_CURRENT_COMPILER_RELEASE)
+    char buf2[40];
+#endif
+#endif
+
+    /* Pyramid, NeXT have problems with huge macro expansion, too:  no Info() */
+    sprintf((char *)slide, LoadFarString(CompiledWith),
+
+#ifdef __GNUC__
+#  ifdef NX_CURRENT_COMPILER_RELEASE
+      (sprintf(buf1, "NeXT DevKit %d.%02d ", NX_CURRENT_COMPILER_RELEASE/100,
+        NX_CURRENT_COMPILER_RELEASE%100), buf1),
+      (strlen(__VERSION__) > 8)? "(gcc)" :
+        (sprintf(buf2, "(gcc %s)", __VERSION__), buf2),
+#  else
+      "gcc ", __VERSION__,
+#  endif
+#else
+#  if defined(CRAY) && defined(_RELEASE)
+      "cc ", (sprintf(buf1, "version %d", _RELEASE), buf1),
+#  else
+#  ifdef __VERSION__
+      "cc ", __VERSION__,
+#  else
+      "cc", "",
+#  endif
+#  endif
+#endif
+
+      "Unix",
+
+#if defined(sgi) || defined(__sgi)
+      " (Silicon Graphics IRIX)",
+#else
+#ifdef sun
+#  ifdef sparc
+#    ifdef __SVR4
+      " (Sun SPARC/Solaris)",
+#    else /* may or may not be SunOS */
+      " (Sun SPARC)",
+#    endif
+#  else
+#  if defined(sun386) || defined(i386)
+      " (Sun 386i)",
+#  else
+#  if defined(mc68020) || defined(__mc68020__)
+      " (Sun 3)",
+#  else /* mc68010 or mc68000:  Sun 2 or earlier */
+      " (Sun 2)",
+#  endif
+#  endif
+#  endif
+#else
+#ifdef __hpux
+      " (HP/UX)",
+#else
+#ifdef __osf__
+      " (DEC OSF/1)",
+#else
+#ifdef _AIX
+      " (IBM AIX)",
+#else
+#ifdef aiws
+      " (IBM RT/AIX)",
+#else
+#if defined(CRAY) || defined(cray)
+#  ifdef _UNICOS
+      (sprintf(buf2, " (Cray UNICOS release %d)", _UNICOS), buf2),
+#  else
+      " (Cray UNICOS)",
+#  endif
+#else
+#if defined(uts) || defined(UTS)
+      " (Amdahl UTS)",
+#else
+#ifdef NeXT
+#  ifdef mc68000
+      " (NeXTStep/black)",
+#  else
+      " (NeXTStep for Intel)",
+#  endif
+#else              /* the next dozen or so are somewhat order-dependent */
+#ifdef LINUX
+#  ifdef __ELF__
+      " (Linux ELF)",
+#  else
+      " (Linux a.out)",
+#  endif
+#else
+#ifdef MINIX
+      " (Minix)",
+#else
+#ifdef M_UNIX
+      " (SCO Unix)",
+#else
+#ifdef M_XENIX
+      " (SCO Xenix)",
+#else
+#ifdef __NetBSD__
+#  ifdef NetBSD0_8
+      (sprintf(buf1, " (NetBSD 0.8%c)", (char)(NetBSD0_8 - 1 + 'A')), buf1),
+#  else
+#  ifdef NetBSD0_9
+      (sprintf(buf1, " (NetBSD 0.9%c)", (char)(NetBSD0_9 - 1 + 'A')), buf1),
+#  else
+#  ifdef NetBSD1_0
+      (sprintf(buf1, " (NetBSD 1.0%c)", (char)(NetBSD1_0 - 1 + 'A')), buf1),
+#  else
+      (BSD4_4 == 0.5)? " (NetBSD before 0.9)" : " (NetBSD 1.1 or later)",
+#  endif
+#  endif
+#  endif
+#else
+#ifdef __FreeBSD__
+      (BSD4_4 == 0.5)? " (FreeBSD 1.x)" : " (FreeBSD 2.0 or later)",
+#else
+#ifdef __bsdi__
+      (BSD4_4 == 0.5)? " (BSD/386 1.0)" : " (BSD/386 1.1 or later)",
+#else
+#ifdef __386BSD__
+      (BSD4_4 == 1)? " (386BSD, post-4.4 release)" : " (386BSD)",
+#else
+#if defined(i486) || defined(__i486) || defined(__i486__)
+      " (Intel 486)",
+#else
+#if defined(i386) || defined(__i386) || defined(__i386__)
+      " (Intel 386)",
+#else
+#ifdef pyr
+      " (Pyramid)",
+#else
+#ifdef ultrix
+#  ifdef mips
+      " (DEC/MIPS)",
+#  else
+#  ifdef vax
+      " (DEC/VAX)",
+#  else /* __alpha? */
+      " (DEC/Alpha)",
+#  endif
+#  endif
+#else
+#ifdef gould
+      " (Gould)",
+#else
+#ifdef MTS
+      " (MTS)",
+#else
+#ifdef __convexc__
+      " (Convex)",
+#else
+#ifdef __QNX__
+      " (QNX 4)",
+#else
+#ifdef __QNXNTO__
+      " (QNX Neutrino)",
+#else
+#ifdef Lynx
+      " (LynxOS)",
+#else
+      "",
+#endif /* Lynx */
+#endif /* QNX Neutrino */
+#endif /* QNX 4 */
+#endif /* Convex */
+#endif /* MTS */
+#endif /* Gould */
+#endif /* DEC */
+#endif /* Pyramid */
+#endif /* 386 */
+#endif /* 486 */
+#endif /* 386BSD */
+#endif /* BSDI BSD/386 */
+#endif /* NetBSD */
+#endif /* FreeBSD */
+#endif /* SCO Xenix */
+#endif /* SCO Unix */
+#endif /* Minix */
+#endif /* Linux */
+#endif /* NeXT */
+#endif /* Amdahl */
+#endif /* Cray */
+#endif /* RT/AIX */
+#endif /* AIX */
+#endif /* OSF/1 */
+#endif /* HP/UX */
+#endif /* Sun */
+#endif /* SGI */
+
+#ifdef __DATE__
+      " on ", __DATE__
+#else
+      "", ""
+#endif
+    );
+
+    (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0);
+
+} /* end function version() */
+
+#endif /* !SFX */
+
+
+
+
+#ifdef QLZIP
+
+struct qdirect  {
+    long            d_length __attribute__ ((packed));  /* file length */
+    unsigned char   d_access __attribute__ ((packed));  /* file access type */
+    unsigned char   d_type __attribute__ ((packed));    /* file type */
+    long            d_datalen __attribute__ ((packed)); /* data length */
+    long            d_reserved __attribute__ ((packed));/* Unused */
+    short           d_szname __attribute__ ((packed));  /* size of name */
+    char            d_name[36] __attribute__ ((packed));/* name area */
+    long            d_update __attribute__ ((packed));  /* last update */
+    long            d_refdate __attribute__ ((packed));
+    long            d_backup __attribute__ ((packed));   /* EOD */
+};
+
+#define LONGID  "QDOS02"
+#define EXTRALEN (sizeof(struct qdirect) + 8)
+#define JBLONGID    "QZHD"
+#define JBEXTRALEN  (sizeof(jbextra)  - 4 * sizeof(char))
+
+typedef struct {
+    char        eb_header[4] __attribute__ ((packed));  /* place_holder */
+    char        longid[8] __attribute__ ((packed));
+    struct      qdirect     header __attribute__ ((packed));
+} qdosextra;
+
+typedef struct {
+    char        eb_header[4];                           /* place_holder */
+    char        longid[4];
+    struct      qdirect     header;
+} jbextra;
+
+
+
+/*  The following two functions SH() and LG() convert big-endian short
+ *  and long numbers into native byte order.  They are some kind of
+ *  counterpart to the generic UnZip's makeword() and makelong() functions.
+ */
+static ush SH(ush val)
+{
+    uch swapbuf[2];
+
+    swapbuf[1] = (uch)(val & 0xff);
+    swapbuf[0] = (uch)(val >> 8);
+    return (*(ush *)swapbuf);
+}
+
+
+
+static ulg LG(ulg val)
+{
+    /*  convert the big-endian unsigned long number `val' to the machine
+     *  dependant representation
+     */
+    ush swapbuf[2];
+
+    swapbuf[1] = SH((ush)(val & 0xffff));
+    swapbuf[0] = SH((ush)(val >> 16));
+    return (*(ulg *)swapbuf);
+}
+
+
+
+static void qlfix(__G__ ef_ptr, ef_len)
+    __GDEF
+    uch *ef_ptr;
+    unsigned ef_len;
+{
+    while (ef_len >= EB_HEADSIZE)
+    {
+        unsigned    eb_id  = makeword(EB_ID + ef_ptr);
+        unsigned    eb_len = makeword(EB_LEN + ef_ptr);
+
+        if (eb_len > (ef_len - EB_HEADSIZE)) {
+            /* discovered some extra field inconsistency! */
+            Trace((stderr,
+              "qlfix: block length %u > rest ef_size %u\n", eb_len,
+              ef_len - EB_HEADSIZE));
+            break;
+        }
+
+        switch (eb_id) {
+          case EF_QDOS:
+          {
+            struct _ntc_
+            {
+                long id;
+                long dlen;
+            } ntc;
+            long dlen = 0;
+
+            qdosextra   *extra = (qdosextra *)ef_ptr;
+            jbextra     *jbp   = (jbextra   *)ef_ptr;
+
+            if (!strncmp(extra->longid, LONGID, strlen(LONGID)))
+            {
+                if (eb_len != EXTRALEN)
+                    if (uO.qflag)
+                        Info(slide, 0x201, ((char *)slide,
+                          "warning:  invalid length in Qdos field for %s\n",
+                          G.filename));
+                    else
+                        Info(slide, 0x201, ((char *)slide,
+                          "warning:  invalid length in Qdos field"));
+
+                if (extra->header.d_type)
+                {
+                    dlen = extra->header.d_datalen;
+                }
+            }
+
+            if (!strncmp(jbp->longid, JBLONGID, strlen(JBLONGID)))
+            {
+                if (eb_len != JBEXTRALEN)
+                    if (uO.qflag)
+                        Info(slide, 0x201, ((char *)slide,
+                          "warning:  invalid length in QZ field for %s\n",
+                          G.filename));
+                    else
+                        Info(slide, 0x201, ((char *)slide,
+                          "warning:  invalid length in QZ field"));
+                if(jbp->header.d_type)
+                {
+                    dlen = jbp->header.d_datalen;
+                }
+            }
+
+            if ((long)LG(dlen) > 0)
+            {
+                G.outfile = fopen(G.filename,"r+");
+                fseek(G.outfile, -8, SEEK_END);
+                fread(&ntc, 8, 1, G.outfile);
+                if(ntc.id != *(long *)"XTcc")
+                {
+                    ntc.id = *(long *)"XTcc";
+                    ntc.dlen = dlen;
+                    fwrite (&ntc, 8, 1, G.outfile);
+                }
+                Info(slide, 0x201, ((char *)slide, "QData = %d", LG(dlen)));
+                fclose(G.outfile);
+            }
+            return;     /* finished, cancel further extra field scanning */
+          }
+
+          default:
+            Trace((stderr,"qlfix: unknown extra field block, ID=%d\n",
+               eb_id));
+        }
+
+        /* Skip this extra field block */
+        ef_ptr += (eb_len + EB_HEADSIZE);
+        ef_len -= (eb_len + EB_HEADSIZE);
+    }
+}
+#endif /* QLZIP */
+
+
+
+
+#ifdef ACORN_FTYPE_NFS
+
+/* Acorn bits for NFS filetyping */
+
+static int isRISCOSexfield(uch *extra_field)
+{
+ if (extra_field != NULL) {
+   RO_extra_block *block = (RO_extra_block *)extra_field;
+   return (
+     makeword(block->ID) == EF_SPARK &&
+     (makeword(block->size) == 24 || makeword(block->size) == 20) &&
+     makelong(block->ID_2) == 0x30435241 /* ARC0 */);
+ }
+ return FALSE;
+}
+#endif /* ACORN_FTYPE_NFS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/unreduce.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,230 @@
+/*---------------------------------------------------------------------------
+
+  unreduce.c
+
+  The Reducing algorithm is actually a combination of two distinct algorithms.
+  The first algorithm compresses repeated byte sequences, and the second al-
+  gorithm takes the compressed stream from the first algorithm and applies a
+  probabilistic compression method.
+
+     * Copyright 1989 Samuel H. Smith;  All rights reserved
+     *
+     * Do not distribute modified versions without my permission.
+     * Do not remove or alter this notice or any other copyright notice.
+     * If you use this in your own program you must distribute source code.
+     * Do not use any of this in a commercial product.
+
+  See the accompanying file "COPYING" in UnZip source and binary distributions
+  for further information.  This code is NOT used unless USE_SMITH_CODE is
+  explicitly defined (==> COPYRIGHT_CLEAN is not defined).
+
+  ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"   /* defines COPYRIGHT_CLEAN by default */
+
+
+#ifndef COPYRIGHT_CLEAN
+
+/**************************************/
+/*  UnReduce Defines, Typedefs, etc.  */
+/**************************************/
+
+#define DLE    144
+
+typedef uch f_array[64];        /* for followers[256][64] */
+
+
+
+/******************************/
+/*  UnReduce Local Functions  */
+/******************************/
+
+static void LoadFollowers OF((__GPRO__ f_array *followers, uch *Slen));
+
+
+
+/*******************************/
+/*  UnReduce Global Constants  */
+/*******************************/
+
+static ZCONST shrint L_table[] =
+{0, 0x7f, 0x3f, 0x1f, 0x0f};
+
+static ZCONST shrint D_shift[] =
+{0, 0x07, 0x06, 0x05, 0x04};
+static ZCONST shrint D_mask[] =
+{0, 0x01, 0x03, 0x07, 0x0f};
+
+static ZCONST shrint B_table[] =
+{8, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8};
+
+
+
+
+
+/*************************/
+/*  Function unreduce()  */
+/*************************/
+
+void unreduce(__G)   /* expand probabilistically reduced data */
+     __GDEF
+{
+    register int lchar = 0;
+    shrint nchar;
+    shrint ExState = 0;
+    shrint V = 0;
+    shrint Len = 0;
+    long s = G.ucsize;  /* number of bytes left to decompress */
+    unsigned w = 0;      /* position in output window slide[] */
+    unsigned u = 1;      /* true if slide[] unflushed */
+    uch Slen[256];
+
+    f_array *followers = (f_array *)(slide + 0x4000);
+    int factor = G.lrec.compression_method - 1;
+
+    LoadFollowers(__G__ followers, Slen);
+
+    while (s > 0 /* && (!zipeof) */) {
+        if (Slen[lchar] == 0)
+            READBITS(8, nchar)   /* ; */
+        else {
+            READBITS(1, nchar)   /* ; */
+            if (nchar != 0)
+                READBITS(8, nchar)       /* ; */
+            else {
+                shrint follower;
+                int bitsneeded = B_table[Slen[lchar]];
+
+                READBITS(bitsneeded, follower)   /* ; */
+                nchar = followers[lchar][follower];
+            }
+        }
+        /* expand the resulting byte */
+        switch (ExState) {
+
+        case 0:
+            if (nchar != DLE) {
+                s--;
+                slide[w++] = (uch)nchar;
+                if (w == 0x4000) {
+                    flush(__G__ slide, (ulg)w, 0);
+                    w = u = 0;
+                }
+            }
+            else
+                ExState = 1;
+            break;
+
+        case 1:
+            if (nchar != 0) {
+                V = nchar;
+                Len = V & L_table[factor];
+                if (Len == L_table[factor])
+                    ExState = 2;
+                else
+                    ExState = 3;
+            } else {
+                s--;
+                slide[w++] = DLE;
+                if (w == 0x4000)
+                {
+                  flush(__G__ slide, (ulg)w, 0);
+                  w = u = 0;
+                }
+                ExState = 0;
+            }
+            break;
+
+        case 2:{
+                Len += nchar;
+                ExState = 3;
+            }
+            break;
+
+        case 3:{
+                register unsigned e;
+                register unsigned n = Len + 3;
+                register unsigned d = w - ((((V >> D_shift[factor]) &
+                               D_mask[factor]) << 8) + nchar + 1);
+
+                s -= n;
+                do {
+                  n -= (e = (e = 0x4000 - ((d &= 0x3fff) > w ? d : w)) > n ?
+                        n : e);
+                  if (u && w <= d)
+                  {
+                    memzero(slide + w, e);
+                    w += e;
+                    d += e;
+                  }
+                  else
+                    if (w - d < e)      /* (assume unsigned comparison) */
+                      do {              /* slow to avoid memcpy() overlap */
+                        slide[w++] = slide[d++];
+                      } while (--e);
+                    else
+                    {
+                      memcpy(slide + w, slide + d, e);
+                      w += e;
+                      d += e;
+                    }
+                  if (w == 0x4000)
+                  {
+                    flush(__G__ slide, (ulg)w, 0);
+                    w = u = 0;
+                  }
+                } while (n);
+
+                ExState = 0;
+            }
+            break;
+        }
+
+        /* store character for next iteration */
+        lchar = nchar;
+    }
+
+    /* flush out slide */
+    flush(__G__ slide, (ulg)w, 0);
+}
+
+
+
+
+
+/******************************/
+/*  Function LoadFollowers()  */
+/******************************/
+
+static void LoadFollowers(__G__ followers, Slen)
+     __GDEF
+     f_array *followers;
+     uch *Slen;
+{
+    register int x;
+    register int i;
+
+    for (x = 255; x >= 0; x--) {
+        READBITS(6, Slen[x])   /* ; */
+        for (i = 0; (uch)i < Slen[x]; i++)
+            READBITS(8, followers[x][i])   /* ; */
+    }
+}
+
+#endif /* !COPYRIGHT_CLEAN */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/unshrink.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,301 @@
+/*---------------------------------------------------------------------------
+
+  unshrink.c                     version 1.21                     23 Nov 95
+
+
+       NOTE:  This code may or may not infringe on the so-called "Welch
+       patent" owned by Unisys.  (From reading the patent, it appears
+       that a pure LZW decompressor is *not* covered, but this claim has
+       not been tested in court, and Unisys is reported to believe other-
+       wise.)  It is therefore the responsibility of the user to acquire
+       whatever license(s) may be required for legal use of this code.
+
+       THE INFO-ZIP GROUP DISCLAIMS ALL LIABILITY FOR USE OF THIS CODE
+       IN VIOLATION OF APPLICABLE PATENT LAW.
+
+
+  Shrinking is basically a dynamic LZW algorithm with allowed code sizes of
+  up to 13 bits; in addition, there is provision for partial clearing of
+  leaf nodes.  PKWARE uses the special code 256 (decimal) to indicate a
+  change in code size or a partial clear of the code tree:  256,1 for the
+  former and 256,2 for the latter.  [Note that partial clearing can "orphan"
+  nodes:  the parent-to-be can be cleared before its new child is added,
+  but the child is added anyway (as an orphan, as though the parent still
+  existed).  When the tree fills up to the point where the parent node is
+  reused, the orphan is effectively "adopted."  Versions prior to 1.05 were
+  affected more due to greater use of pointers (to children and siblings
+  as well as parents).]
+
+  This replacement version of unshrink.c was written from scratch.  It is
+  based only on the algorithms described in Mark Nelson's _The Data Compres-
+  sion Book_ and in Terry Welch's original paper in the June 1984 issue of
+  IEEE _Computer_; no existing source code, including any in Nelson's book,
+  was used.
+
+  Memory requirements have been reduced in this version and are now no more
+  than the original Sam Smith code.  This is still larger than any of the
+  other algorithms:  at a minimum, 8K+8K+16K (stack+values+parents) assuming
+  16-bit short ints, and this does not even include the output buffer (the
+  other algorithms leave the uncompressed data in the work area, typically
+  called slide[]).  For machines with a 64KB data space this is a problem,
+  particularly when text conversion is required and line endings have more
+  than one character.  UnZip's solution is to use two roughly equal halves
+  of outbuf for the ASCII conversion in such a case; the "unshrink" argument
+  to flush() signals that this is the case.
+
+  For large-memory machines, a second outbuf is allocated for translations,
+  but only if unshrinking and only if translations are required.
+
+              | binary mode  |        text mode
+    ---------------------------------------------------
+    big mem   |  big outbuf  | big outbuf + big outbuf2  <- malloc'd here
+    small mem | small outbuf | half + half small outbuf
+
+  Copyright 1994, 1995 Greg Roelofs.  See the accompanying file "COPYING"
+  in UnZip 5.20 (or later) source or binary distributions.
+
+  ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"       /* defines LZW_CLEAN by default */
+
+
+#ifndef LZW_CLEAN
+
+static void  partial_clear  OF((__GPRO));
+
+#ifdef DEBUG
+#  define OUTDBG(c) \
+	if ((c)<32 || (c)>=127) pipeit("\\x%02x",(c)); else { } 
+#else
+#  define OUTDBG(c)
+#endif
+
+/* HSIZE is defined as 2^13 (8192) in unzip.h */
+#define BOGUSCODE  256
+#define FLAG_BITS  parent        /* upper bits of parent[] used as flag bits */
+#define CODE_MASK  (HSIZE - 1)   /* 0x1fff (lower bits are parent's index) */
+#define FREE_CODE  HSIZE         /* 0x2000 (code is unused or was cleared) */
+#define HAS_CHILD  (HSIZE << 1)  /* 0x4000 (code has a child--do not clear) */
+
+#define parent G.area.shrink.Parent
+#define Value  G.area.shrink.value /* "value" conflicts with Pyramid ioctl.h */
+#define stack  G.area.shrink.Stack
+
+
+/***********************/
+/* Function unshrink() */
+/***********************/
+
+int unshrink(__G)
+     __GDEF
+{
+    int offset = (HSIZE - 1);
+    uch *stacktop = stack + offset;
+    register uch *newstr;
+    int codesize=9, len, KwKwK, error;
+    shrint code, oldcode, freecode, curcode;
+    shrint lastfreecode;
+    unsigned int outbufsiz;
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+    /* Normally realbuf and outbuf will be the same.  However, if the data
+     * are redirected to a large memory buffer, realbuf will point to the
+     * new location while outbuf will remain pointing to the malloc'd
+     * memory buffer. */
+    uch *realbuf = G.outbuf;
+#else
+#   define realbuf G.outbuf
+#endif
+
+
+/*---------------------------------------------------------------------------
+    Initialize various variables.
+  ---------------------------------------------------------------------------*/
+
+    lastfreecode = BOGUSCODE;
+
+#ifndef VMS     /* VMS uses its own buffer scheme for textmode flush(). */
+#ifndef SMALL_MEM
+    /* non-memory-limited machines:  allocate second (large) buffer for
+     * textmode conversion in flush(), but only if needed */
+    if (G.pInfo->textmode && !G.outbuf2 &&
+        (G.outbuf2 = (uch *)malloc(TRANSBUFSIZ)) == (uch *)NULL)
+        return PK_MEM3;
+#endif
+#endif /* !VMS */
+
+    for (code = 0;  code < BOGUSCODE;  ++code) {
+        Value[code] = (uch)code;
+        parent[code] = BOGUSCODE;
+    }
+    for (code = BOGUSCODE+1;  code < HSIZE;  ++code)
+        parent[code] = FREE_CODE;
+
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+    if (G.redirect_slide) { /* use normal outbuf unless we're a DLL routine */
+        realbuf = G.redirect_buffer;
+        outbufsiz = G.redirect_size;
+    } else
+#endif
+#ifdef DLL
+    if (G.pInfo->textmode && !G.redirect_data)
+#else
+    if (G.pInfo->textmode)
+#endif
+        outbufsiz = RAWBUFSIZ;
+    else
+        outbufsiz = OUTBUFSIZ;
+    G.outptr = realbuf;
+    G.outcnt = 0L;
+
+/*---------------------------------------------------------------------------
+    Get and output first code, then loop over remaining ones.
+  ---------------------------------------------------------------------------*/
+
+    READBITS(codesize, oldcode)
+    if (!G.zipeof) {
+        *G.outptr++ = (uch)oldcode;
+        OUTDBG((uch)oldcode)
+        ++G.outcnt;
+    }
+
+    do {
+        READBITS(codesize, code)
+        if (G.zipeof)
+            break;
+        if (code == BOGUSCODE) {   /* possible to have consecutive escapes? */
+            READBITS(codesize, code)
+            if (code == 1) {
+                ++codesize;
+                Trace((stderr, " (codesize now %d bits)\n", codesize));
+            } else if (code == 2) {
+                Trace((stderr, " (partial clear code)\n"));
+                partial_clear(__G);   /* clear leafs (nodes with no children) */
+                Trace((stderr, " (done with partial clear)\n"));
+                lastfreecode = BOGUSCODE;  /* reset start of free-node search */
+            }
+            continue;
+        }
+
+    /*-----------------------------------------------------------------------
+        Translate code:  traverse tree from leaf back to root.
+      -----------------------------------------------------------------------*/
+
+        newstr = stacktop;
+        curcode = code;
+
+        if (parent[curcode] == FREE_CODE) {
+            /* or (FLAG_BITS[curcode] & FREE_CODE)? */
+            KwKwK = TRUE;
+            Trace((stderr, " (found a KwKwK code %d; oldcode = %d)\n", code,
+              oldcode));
+            --newstr;   /* last character will be same as first character */
+            curcode = oldcode;
+        } else
+            KwKwK = FALSE;
+
+        do {
+            *newstr-- = Value[curcode];
+            curcode = (shrint)(parent[curcode] & CODE_MASK);
+        } while (curcode != BOGUSCODE);
+
+        len = (int)(stacktop - newstr++);
+        if (KwKwK)
+            *stacktop = *newstr;
+
+    /*-----------------------------------------------------------------------
+        Write expanded string in reverse order to output buffer.
+      -----------------------------------------------------------------------*/
+
+        Trace((stderr, "code %4d; oldcode %4d; char %3d (%c); string [", code,
+          oldcode, (int)(*newstr), (*newstr<32 || *newstr>=127)? ' ':*newstr));
+
+        {
+            register uch *p;
+
+            for (p = newstr;  p < newstr+len;  ++p) {
+                *G.outptr++ = *p;
+                OUTDBG(*p)
+                if (++G.outcnt == outbufsiz) {
+                    Trace((stderr, "doing flush(), outcnt = %lu\n", G.outcnt));
+                    if ((error = flush(__G__ realbuf, G.outcnt, TRUE)) != 0)
+                        pipeit("unshrink:  flush() error (%d)\n",
+                          error);
+                    Trace((stderr, "done with flush()\n"));
+                    G.outptr = realbuf;
+                    G.outcnt = 0L;
+                }
+            }
+        }
+
+    /*-----------------------------------------------------------------------
+        Add new leaf (first character of newstr) to tree as child of oldcode.
+      -----------------------------------------------------------------------*/
+
+        /* search for freecode */
+        freecode = (shrint)(lastfreecode + 1);
+        /* add if-test before loop for speed? */
+        while (parent[freecode] != FREE_CODE)
+            ++freecode;
+        lastfreecode = freecode;
+        Trace((stderr, "]; newcode %d\n", freecode));
+
+        Value[freecode] = *newstr;
+        parent[freecode] = oldcode;
+        oldcode = code;
+
+    } while (!G.zipeof);
+
+/*---------------------------------------------------------------------------
+    Flush any remaining data and return to sender...
+  ---------------------------------------------------------------------------*/
+
+    if (G.outcnt > 0L) {
+        Trace((stderr, "doing final flush(), outcnt = %lu\n", G.outcnt));
+        if ((error = flush(__G__ realbuf, G.outcnt, TRUE)) != 0)
+            pipeit("unshrink:  flush() error (%d)\n", error);
+        Trace((stderr, "done with flush()\n"));
+    }
+
+    return PK_OK;
+
+} /* end function unshrink() */
+
+
+
+
+
+/****************************/
+/* Function partial_clear() */      /* no longer recursive... */
+/****************************/
+
+static void partial_clear(__G)
+     __GDEF
+{
+    register shrint code;
+
+    /* clear all nodes which have no children (i.e., leaf nodes only) */
+
+    /* first loop:  mark each parent as such */
+    for (code = BOGUSCODE+1;  code < HSIZE;  ++code) {
+        register shrint cparent = (shrint)(parent[code] & CODE_MASK);
+
+        if (cparent > BOGUSCODE && cparent != FREE_CODE)
+            FLAG_BITS[cparent] |= HAS_CHILD;   /* set parent's child-bit */
+    }
+
+    /* second loop:  clear all nodes *not* marked as parents; reset flag bits */
+    for (code = BOGUSCODE+1;  code < HSIZE;  ++code) {
+        if (FLAG_BITS[code] & HAS_CHILD)    /* just clear child-bit */
+            FLAG_BITS[code] &= ~HAS_CHILD;
+        else {                              /* leaf:  lose it */
+            Trace((stderr, "%d\n", code));
+            parent[code] = FREE_CODE;
+        }
+    }
+
+    return;
+}
+
+#endif /* !LZW_CLEAN */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/unzip.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,1744 @@
+/*---------------------------------------------------------------------------
+
+  unzip.c
+
+  UnZip - a zipfile extraction utility.  See below for make instructions, or
+  read the comments in Makefile and the various Contents files for more de-
+  tailed explanations.  To report a bug, send a *complete* description to
+  Zip-Bugs@lists.wku.edu; include machine type, operating system and ver-
+  sion, compiler and version, and reasonably detailed error messages or prob-
+  lem report.  To join Info-ZIP, see the instructions in README.
+
+  UnZip 5.x is a greatly expanded and partially rewritten successor to 4.x,
+  which in turn was almost a complete rewrite of version 3.x.  For a detailed
+  revision history, see UnzpHist.zip at quest.jpl.nasa.gov.  For a list of
+  the many (near infinite) contributors, see "CONTRIBS" in the UnZip source
+  distribution.
+
+  ---------------------------------------------------------------------------
+
+  [from original zipinfo.c]
+
+  This program reads great gobs of totally nifty information, including the
+  central directory stuff, from ZIP archives ("zipfiles" for short).  It
+  started as just a testbed for fooling with zipfiles, but at this point it
+  is actually a useful utility.  It also became the basis for the rewrite of
+  UnZip (3.16 -> 4.0), using the central directory for processing rather than
+  the individual (local) file headers.
+
+  As of ZipInfo v2.0 and UnZip v5.1, the two programs are combined into one.
+  If the executable is named "unzip" (or "unzip.exe", depending), it behaves
+  like UnZip by default; if it is named "zipinfo" or "ii", it behaves like
+  ZipInfo.  The ZipInfo behavior may also be triggered by use of unzip's -Z
+  option; for example, "unzip -Z [zipinfo_options] archive.zip".
+
+  Another dandy product from your buddies at Newtware!
+
+  Author:  Greg Roelofs, newt@pobox.com, http://pobox.com/~newt/
+           23 August 1990 -> April 1997
+
+  ---------------------------------------------------------------------------
+
+  Version:  unzip5??.{tar.Z | tar.gz | zip} for Unix, VMS, OS/2, MS-DOS, Amiga,
+              Atari, Windows 3.x/95/NT/CE, Macintosh, Human68K, Acorn RISC OS,
+              BeOS, SMS/QDOS, VM/CMS, MVS, AOS/VS and TOPS-20.  Decryption
+              requires sources in zcrypt28.zip.  See the accompanying "WHERE"
+              file in the main source distribution for ftp, uucp, BBS and mail-
+              server sites, or see http://www.cdrom.com/pub/infozip/UnZip.html .
+
+  Copyrights:  see accompanying file "COPYING" in UnZip source distribution.
+               (This software is free but NOT IN THE PUBLIC DOMAIN.  There
+               are some restrictions on commercial use.)
+
+  ---------------------------------------------------------------------------*/
+
+
+
+#define UNZIP_C
+#define UNZIP_INTERNAL
+#include "unzip.h"        /* includes, typedefs, macros, prototypes, etc. */
+#include "crypt.h"
+#include "version.h"
+
+#ifndef WINDLL            /* The WINDLL port uses windll/windll.c instead... */
+
+/*******************/
+/* Local Functions */
+/*******************/
+
+#ifndef SFX
+static void  show_version_info  OF((__GPRO));
+#endif
+
+
+/*************/
+/* Constants */
+/*************/
+
+#include "consts.h"  /* all constant global variables are in here */
+                     /* (non-constant globals were moved to globals.c) */
+
+/* constant local variables: */
+
+#ifndef SFX
+   static ZCONST char Far EnvUnZip[] = ENV_UNZIP;
+   static ZCONST char Far EnvUnZip2[] = ENV_UNZIP2;
+   static ZCONST char Far EnvZipInfo[] = ENV_ZIPINFO;
+   static ZCONST char Far EnvZipInfo2[] = ENV_ZIPINFO2;
+#ifdef RISCOS
+   static ZCONST char Far EnvUnZipExts[] = ENV_UNZIPEXTS;
+#endif /* RISCOS */
+#endif
+
+#if (!defined(SFX) || defined(SFX_EXDIR))
+   static ZCONST char Far NotExtracting[] =
+     "caution:  not extracting; -d ignored\n";
+   static ZCONST char Far MustGiveExdir[] =
+     "error:  must specify directory to which to extract with -d option\n";
+   static ZCONST char Far OnlyOneExdir[] =
+     "error:  -d option used more than once (only one exdir allowed)\n";
+#endif
+
+#if CRYPT
+   static ZCONST char Far MustGivePasswd[] =
+     "error:  must give decryption password with -P option\n";
+#endif
+
+#ifndef SFX
+   static ZCONST char Far Zfirst[] =
+   "error:  -Z must be first option for ZipInfo mode (check UNZIP variable?)\n";
+#endif
+static ZCONST char Far InvalidOptionsMsg[] = "error:\
+  -fn or any combination of -c, -l, -p, -t, -u and -v options invalid\n";
+static ZCONST char Far IgnoreOOptionMsg[] =
+  "caution:  both -n and -o specified; ignoring -o\n";
+
+/* usage() strings */
+#ifndef SFX
+#ifdef VMS
+   static ZCONST char Far Example3[] = "vms.c";
+   static ZCONST char Far Example2[] = "  unzip\
+ \"-V\" foo \"Bar\" => must quote uppercase options and filenames in VMS\n";
+#else /* !VMS */
+   static ZCONST char Far Example3[] = "ReadMe";
+#ifdef RISCOS
+   static ZCONST char Far Example2[] =
+"  unzip foo -d RAM:$   => extract all files from foo into RAMDisc\n";
+#else /* !RISCOS */
+#if (defined(OS2) || (defined(DOS_FLX_OS2_W32) && defined(MORE)))
+   static ZCONST char Far Example2[] =
+     "";                /* no room:  too many local3[] items */
+#else /* !OS2 */
+#ifdef MACOS
+   static ZCONST char Far Example2[] = ""; /* not needed */
+#else /* !MACOS */
+   static ZCONST char Far Example2[] = " \
+ unzip -p foo | more  => send contents of foo.zip via pipe into program more\n";
+#endif /* ?MACOS */
+#endif /* ?OS2 */
+#endif /* ?RISCOS */
+#endif /* ?VMS */
+
+/* local1[]:  command options */
+#if (defined(DLL) && defined(API_DOC))
+   static ZCONST char Far local1[] =
+     "  -A  print extended help for API functions";
+#else /* !(DLL && API_DOC) */
+   static ZCONST char Far local1[] = "";
+#endif /* ?(DLL && API_DOC) */
+
+/* local2[] and local3[]:  modifier options */
+#ifdef DOS_FLX_OS2_W32
+#ifdef FLEXOS
+   static ZCONST char Far local2[] = "";
+#else
+   static ZCONST char Far local2[] =
+     " -$  label removables (-$$ => fixed disks)";
+#endif
+#ifdef OS2
+#ifdef MORE
+   static ZCONST char Far local3[] = "\
+  -X  restore ACLs if supported              -s  spaces in filenames => '_'\n\
+                                             -M  pipe through \"more\" pager\n";
+#else
+   static ZCONST char Far local3[] = " \
+ -X  restore ACLs if supported              -s  spaces in filenames => '_'\n\n";
+#endif /* ?MORE */
+#else /* !OS2 */
+#ifdef WIN32
+#ifdef MORE
+   static ZCONST char Far local3[] = "\
+  -X  restore ACLs (-XX => use privileges)   -s  spaces in filenames => '_'\n\
+                                             -M  pipe through \"more\" pager\n";
+#else
+   static ZCONST char Far local3[] = " \
+ -X  restore ACLs (-XX => use privileges)   -s  spaces in filenames => '_'\n\n";
+#endif /* ?MORE */
+#else /* !WIN32 */
+#ifdef MORE
+   static ZCONST char Far local3[] = "  -\
+M  pipe through \"more\" pager              -s  spaces in filenames => '_'\n\n";
+#else
+   static ZCONST char Far local3[] = "\
+                                             -s  spaces in filenames => '_'\n";
+#endif
+#endif /* ?WIN32 */
+#endif /* ?OS2 || ?WIN32 */
+#else /* !DOS_FLX_OS2_W32 */
+#ifdef VMS
+   static ZCONST char Far local2[] = "\"-X\" restore owner/protection info";
+#ifdef MORE
+   static ZCONST char Far local3[] = "  \
+                                          \"-M\" pipe through \"more\" pager\n";
+#else
+   static ZCONST char Far local3[] = "\n";
+#endif
+#else /* !VMS */
+#if (defined(__BEOS__) || defined(TANDEM) || defined(UNIX))
+   static ZCONST char Far local2[] = " -X  restore UID/GID info";
+#ifdef MORE
+   static ZCONST char Far local3[] = "\
+                                             -M  pipe through \"more\" pager\n";
+#else
+   static ZCONST char Far local3[] = "\n";
+#endif
+#else /* !(__BEOS__ || TANDEM || UNIX) */
+#ifdef AMIGA
+   static ZCONST char Far local2[] = " -N  restore comments as filenotes";
+#ifdef MORE
+   static ZCONST char Far local3[] = "\
+                                             -M  pipe through \"more\" pager\n";
+#else
+   static ZCONST char Far local3[] = "\n";
+#endif
+#else /* !AMIGA */
+#ifdef MACOS
+   static ZCONST char Far local2[] = " -E  show Mac info during extraction";
+   static ZCONST char Far local3[] = " \
+ -i  ignore filenames in mac extra info     -J  junk (ignore) Mac extra info\n\n";
+#else /* !MACOS */
+#ifdef MORE
+   static ZCONST char Far local2[] = " -M  pipe through \"more\" pager";
+   static ZCONST char Far local3[] = "\n";
+#else
+   static ZCONST char Far local2[] = "";   /* Atari, Mac, CMS/MVS etc. */
+   static ZCONST char Far local3[] = "";
+#endif
+#endif /* ?MACOS */
+#endif /* ?AMIGA */
+#endif /* ?(__BEOS__ || TANDEM || UNIX) */
+#endif /* ?VMS */
+#endif /* ?DOS_FLX_OS2_W32 */
+#endif /* !SFX */
+
+#ifndef NO_ZIPINFO
+#ifdef VMS
+   static ZCONST char Far ZipInfoExample[] = "* or % (e.g., \"*font-%.zip\")";
+#else
+   static ZCONST char Far ZipInfoExample[] = "*, ?, [] (e.g., \"[a-j]*.zip\")";
+#endif
+
+static ZCONST char Far ZipInfoUsageLine1[] = "\
+ZipInfo %d.%d%d%s of %s, by Greg Roelofs and the Info-ZIP group.\n\
+\n\
+List name, date/time, attribute, size, compression method, etc., about files\n\
+in list (excluding those in xlist) contained in the specified .zip archive(s).\
+\n\"file[.zip]\" may be a wildcard name containing %s.\n\n\
+   usage:  zipinfo [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\n\
+      or:  unzip %s-Z%s [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\n";
+
+static ZCONST char Far ZipInfoUsageLine2[] = "\nmain\
+ listing-format options:             -s  short Unix \"ls -l\" format (def.)\n\
+  -1  filenames ONLY, one per line       -m  medium Unix \"ls -l\" format\n\
+  -2  just filenames but allow -h/-t/-z  -l  long Unix \"ls -l\" format\n\
+                                         -v  verbose, multi-page format\n";
+
+static ZCONST char Far ZipInfoUsageLine3[] = "miscellaneous options:\n\
+  -h  print header line       -t  print totals for listed files or for all\n\
+  -z  print zipfile comment  %c-T%c print file times in sortable decimal format\
+\n %c-C%c be case-insensitive   %s\
+  -x  exclude filenames that follow from listing\n";
+#ifdef MORE
+#ifdef VMS
+   static ZCONST char Far ZipInfoUsageLine4[] =
+     " \"-M\" page output through built-in \"more\"\n";
+#else
+   static ZCONST char Far ZipInfoUsageLine4[] =
+     "  -M  page output through built-in \"more\"\n";
+#endif
+#else /* !MORE */
+   static ZCONST char Far ZipInfoUsageLine4[] = "";
+#endif /* ?MORE */
+#endif /* !NO_ZIPINFO */
+
+#ifdef BETA
+#  ifdef VMSCLI
+   /* BetaVersion[] is also used in vms/cmdline.c:  do not make it static */
+     ZCONST char Far BetaVersion[] = "%s\
+        THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n";
+#  else
+     static ZCONST char Far BetaVersion[] = "%s\
+        THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n";
+#  endif
+#endif
+
+#ifdef SFX
+#  ifdef VMSCLI
+   /* UnzipSFXBanner[] is also used in vms/cmdline.c:  do not make it static */
+     ZCONST char Far UnzipSFXBanner[] =
+#  else
+     static ZCONST char Far UnzipSFXBanner[] =
+#  endif
+     "UnZipSFX %d.%d%d%s of %s, by Info-ZIP (Zip-Bugs@lists.wku.edu).\n";
+#  ifdef SFX_EXDIR
+     static ZCONST char Far UnzipSFXOpts[] =
+    "Valid options are -tfupcz and -d <exdir>; modifiers are -abjnoqCL%sV%s.\n";
+#  else
+     static ZCONST char Far UnzipSFXOpts[] =
+       "Valid options are -tfupcz; modifiers are -abjnoqCL%sV%s.\n";
+#  endif
+#else /* !SFX */
+   static ZCONST char Far CompileOptions[] =
+     "UnZip special compilation options:\n";
+   static ZCONST char Far CompileOptFormat[] = "\t%s\n";
+   static ZCONST char Far EnvOptions[] =
+     "\nUnZip and ZipInfo environment options:\n";
+   static ZCONST char Far EnvOptFormat[] = "%16s:  %s\n";
+   static ZCONST char Far None[] = "[none]";
+#  ifdef ACORN_FTYPE_NFS
+     static ZCONST char Far AcornFtypeNFS[] = "ACORN_FTYPE_NFS";
+#  endif
+#  ifdef ASM_CRC
+     static ZCONST char Far AsmCRC[] = "ASM_CRC";
+#  endif
+#  ifdef ASM_INFLATECODES
+     static ZCONST char Far AsmInflateCodes[] = "ASM_INFLATECODES";
+#  endif
+#  ifdef CHECK_VERSIONS
+     static ZCONST char Far Check_Versions[] = "CHECK_VERSIONS";
+#  endif
+#  ifdef COPYRIGHT_CLEAN
+     static ZCONST char Far Copyright_Clean[] =
+     "COPYRIGHT_CLEAN (PKZIP 0.9x unreducing method not supported)";
+#  endif
+#  ifdef DEBUG
+     static ZCONST char Far UDebug[] = "DEBUG";
+#  endif
+#  ifdef DEBUG_TIME
+     static ZCONST char Far DebugTime[] = "DEBUG_TIME";
+#  endif
+#  ifdef DLL
+     static ZCONST char Far Dll[] = "DLL";
+#  endif
+#  ifdef DOSWILD
+     static ZCONST char Far DosWild[] = "DOSWILD";
+#  endif
+#  ifdef LZW_CLEAN
+     static ZCONST char Far LZW_Clean[] =
+     "LZW_CLEAN (PKZIP/Zip 1.x unshrinking method not supported)";
+#  endif
+#  ifndef MORE
+     static ZCONST char Far No_More[] = "NO_MORE";
+#  endif
+#  ifdef NO_ZIPINFO
+     static ZCONST char Far No_ZipInfo[] = "NO_ZIPINFO";
+#  endif
+#  ifdef NTSD_EAS
+     static ZCONST char Far NTSDExtAttrib[] = "NTSD_EAS";
+#  endif
+#  ifdef OS2_EAS
+     static ZCONST char Far OS2ExtAttrib[] = "OS2_EAS";
+#  endif
+#  ifdef QLZIP
+     static ZCONST char Far SMSExFldOnUnix[] = "QLZIP";
+#  endif
+#  ifdef REENTRANT
+     static ZCONST char Far Reentrant[] = "REENTRANT";
+#  endif
+#  ifdef REGARGS
+     static ZCONST char Far RegArgs[] = "REGARGS";
+#  endif
+#  ifdef RETURN_CODES
+     static ZCONST char Far Return_Codes[] = "RETURN_CODES";
+#  endif
+#  ifdef SET_DIR_ATTRIB
+     static ZCONST char Far SetDirAttrib[] = "SET_DIR_ATTRIB";
+#  endif
+#  ifdef TIMESTAMP
+     static ZCONST char Far TimeStamp[] = "TIMESTAMP";
+#  endif
+#  ifdef UNIXBACKUP
+     static ZCONST char Far UnixBackup[] = "UNIXBACKUP";
+#  endif
+#  ifdef USE_EF_UT_TIME
+     static ZCONST char Far Use_EF_UT_time[] = "USE_EF_UT_TIME";
+#  endif
+#  ifndef LZW_CLEAN
+     static ZCONST char Far Use_Unshrink[] =
+     "USE_UNSHRINK (PKZIP/Zip 1.x unshrinking method supported)";
+#  endif
+#  ifndef COPYRIGHT_CLEAN
+     static ZCONST char Far Use_Smith_Code[] =
+     "USE_SMITH_CODE (PKZIP 0.9x unreducing method supported)";
+#  endif
+#  ifdef USE_VFAT
+     static ZCONST char Far Use_VFAT_support[] = "USE_VFAT";
+#  endif
+#  ifdef USE_ZLIB
+     static ZCONST char Far UseZlib[] =
+     "USE_ZLIB (compiled with version %s; using version %s)";
+#  endif
+#  ifdef VMS_TEXT_CONV
+     static ZCONST char Far VmsTextConv[] = "VMS_TEXT_CONV";
+#  endif
+#  ifdef VMSCLI
+     static ZCONST char Far VmsCLI[] = "VMSCLI";
+#  endif
+#  ifdef VMSWILD
+     static ZCONST char Far VmsWild[] = "VMSWILD";
+#  endif
+#  if CRYPT
+#    ifdef PASSWD_FROM_STDIN
+       static ZCONST char Far PasswdStdin[] = "PASSWD_FROM_STDIN";
+#    endif
+     static ZCONST char Far Decryption[] =
+       "\t[decryption, version %d.%d%s of %s]\n";
+     static ZCONST char Far CryptDate[] = CR_VERSION_DATE;
+#  endif
+#  ifndef __RSXNT__
+#    ifdef __EMX__
+       static ZCONST char Far EnvEMX[] = "EMX";
+       static ZCONST char Far EnvEMXOPT[] = "EMXOPT";
+#    endif
+#    if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2)))
+       static ZCONST char Far EnvGO32[] = "GO32";
+       static ZCONST char Far EnvGO32TMP[] = "GO32TMP";
+#    endif
+#  endif /* !__RSXNT__ */
+
+#ifdef VMS
+/* UnzipUsageLine1[] is also used in vms/cmdline.c:  do not make it static */
+   ZCONST char Far UnzipUsageLine1[] = "\
+UnZip %d.%d%d%s of %s, by Info-ZIP.  For more details see: unzip -v.\n\n";
+#ifdef COPYRIGHT_CLEAN
+   static ZCONST char Far UnzipUsageLine1v[] = "\
+UnZip %d.%d%d%s of %s, by Info-ZIP.  Maintained by C. Spieler.  Send\n\
+bug reports to the authors at Zip-Bugs@lists.wku.edu; see README for details.\
+\n\n";
+#else
+   static ZCONST char Far UnzipUsageLine1v[] = "\
+UnZip %d.%d%d%s of %s, by Info-ZIP.  UnReduce (c) 1989 by S. H. Smith.\n\
+Send bug reports to authors at Zip-Bugs@lists.wku.edu; see README for details.\
+\n\n";
+#endif /* ?COPYRIGHT_CLEAN */
+#else /* !VMS */
+#ifdef COPYRIGHT_CLEAN
+   static ZCONST char Far UnzipUsageLine1[] = "\
+UnZip %d.%d%d%s of %s, by Info-ZIP.  Maintained by C. Spieler.  Send\n\
+bug reports to the authors at Zip-Bugs@lists.wku.edu; see README for details.\
+\n\n";
+#else
+   static ZCONST char Far UnzipUsageLine1[] = "\
+UnZip %d.%d%d%s of %s, by Info-ZIP.  UnReduce (c) 1989 by S. H. Smith.\n\
+Send bug reports to authors at Zip-Bugs@lists.wku.edu; see README for details.\
+\n\n";
+#endif /* ?COPYRIGHT_CLEAN */
+#define UnzipUsageLine1v        UnzipUsageLine1
+#endif /* ?VMS */
+
+static ZCONST char Far UnzipUsageLine2v[] = "\
+Latest sources and executables are at ftp://ftp.cdrom.com/pub/infozip/ , as of\
+\nabove date; see http://www.cdrom.com/pub/infozip/UnZip.html for other sites.\
+\n\n";
+
+#ifdef MACOS
+static ZCONST char Far UnzipUsageLine2[] = "\
+Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-d exdir]\n \
+ Default action is to extract files in list, to exdir;\n\
+  file[.zip] may be a wildcard.  %s\n";
+#else /* !MACOS */
+#ifdef VM_CMS
+static ZCONST char Far UnzipUsageLine2[] = "\
+Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d fm]\n \
+ Default action is to extract files in list, except those in xlist, to disk fm;\n\
+  file[.zip] may be a wildcard.  %s\n";
+#else /* !VM_CMS */
+static ZCONST char Far UnzipUsageLine2[] = "\
+Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]\n \
+ Default action is to extract files in list, except those in xlist, to exdir;\n\
+  file[.zip] may be a wildcard.  %s\n";
+#endif /* ?VM_CMS */
+#endif /* ?MACOS */
+
+#ifdef NO_ZIPINFO
+#  define ZIPINFO_MODE_OPTION  ""
+   static ZCONST char Far ZipInfoMode[] =
+     "(ZipInfo mode is disabled in this version.)";
+#else
+#  define ZIPINFO_MODE_OPTION  "[-Z] "
+#  ifdef VMS
+     static ZCONST char Far ZipInfoMode[] =
+       "\"-Z\" => ZipInfo mode (`unzip \"-Z\"' for usage).";
+#  else
+     static ZCONST char Far ZipInfoMode[] =
+       "-Z => ZipInfo mode (\"unzip -Z\" for usage).";
+#  endif
+#endif /* ?NO_ZIPINFO */
+
+#ifdef VMS
+   static ZCONST char Far VMSusageLine2b[] = "\
+=> define foreign command symbol in LOGIN.COM:  $ unzip :== $dev:[dir]unzip.exe\
+\n";
+#endif
+
+#ifdef MACOS
+static ZCONST char Far UnzipUsageLine3[] = "\n\
+  -d  extract files into exdir               -l  list files (short format)\n\
+  -f  freshen existing files, create none    -t  test compressed archive data\n\
+  -u  update files, create if necessary      -z  display archive comment\n\
+%s\n";
+#else /* !MACOS */
+#ifdef VM_CMS
+static ZCONST char Far UnzipUsageLine3[] = "\n\
+  -p  extract files to pipe, no messages     -l  list files (short format)\n\
+  -f  freshen existing files, create none    -t  test compressed archive data\n\
+  -u  update files, create if necessary      -z  display archive comment\n\
+  -x  exclude files that follow (in xlist)   -d  extract files onto disk fm\n\
+%s\n";
+#else /* !VM_CMS */
+static ZCONST char Far UnzipUsageLine3[] = "\n\
+  -p  extract files to pipe, no messages     -l  list files (short format)\n\
+  -f  freshen existing files, create none    -t  test compressed archive data\n\
+  -u  update files, create if necessary      -z  display archive comment\n\
+  -x  exclude files that follow (in xlist)   -d  extract files into exdir\n\
+%s\n";
+#endif /* ?VM_CMS */
+#endif /* ?MACOS */
+
+static ZCONST char Far UnzipUsageLine4[] = "\
+modifiers:                                   -q  quiet mode (-qq => quieter)\n\
+  -n  never overwrite existing files         -a  auto-convert any text files\n\
+  -o  overwrite files WITHOUT prompting      -aa treat ALL files as text\n \
+ -j  junk paths (do not make directories)   -v  be verbose/print version info\n\
+ %c-C%c match filenames case-insensitively    %c-L%c make (some) names \
+lowercase\n %-42s %c-V%c retain VMS version numbers\n%s";
+
+static ZCONST char Far UnzipUsageLine5[] = "\
+Examples (see unzip.doc for more info):\n\
+  unzip data1 -x joe   => extract all files except joe from zipfile data1.zip\n\
+%s\
+  unzip -fo foo %-6s => quietly replace existing %s if archive file newer\n";
+#endif /* ?SFX */
+
+
+
+
+
+/*****************************/
+/*  main() / UzpMain() stub  */
+/*****************************/
+
+int include_unpack(char *aname)   /* return PK-type error code (except under VMS) */
+{
+    int r, argc = 3;
+	char *argv[4];
+
+	argv[0] = "install.exe";
+	argv[1] = "-v";
+	argv[2] = aname;
+    argv[3] = NULL;
+
+    CONSTRUCTGLOBALS();
+	r = unzip(__G__ argc, argv);
+    DESTROYGLOBALS()
+    RETURN(r);
+}
+
+void resetglobals(void) { }
+
+int pipeit(char *format, ...)
+{
+    return 0;
+}
+
+int confirm(char *format, ...)
+{
+	return 1;
+}
+
+
+
+/*******************************/
+/*  Primary UnZip entry point  */
+/*******************************/
+
+int unzip(__G__ argc, argv)
+    __GDEF
+    int argc;
+    char *argv[];
+{
+#ifndef NO_ZIPINFO
+    char *p;
+#endif
+#ifdef DOS_FLX_H68_OS2_W32
+    int i;
+#endif
+    int retcode, error=FALSE;
+
+#if (defined(__IBMC__) && defined(__DEBUG_ALLOC__))
+    extern void DebugMalloc(void);
+
+    atexit(DebugMalloc);
+#endif
+
+#ifdef MALLOC_WORK
+    G.area.Slide =(uch *)calloc(8193, sizeof(shrint)+sizeof(uch)+sizeof(uch));
+    G.area.shrink.Parent = (shrint *)G.area.Slide;
+    G.area.shrink.value = G.area.Slide + (sizeof(shrint)*(HSIZE+1));
+    G.area.shrink.Stack = G.area.Slide +
+                           (sizeof(shrint) + sizeof(uch))*(HSIZE+1);
+#endif
+
+/*---------------------------------------------------------------------------
+    Macintosh initialization code.
+  ---------------------------------------------------------------------------*/
+
+#ifdef MACOS
+    {
+        int a;
+
+        for (a = 0;  a < 4;  ++a)
+            G.rghCursor[a] = GetCursor(a+128);
+        G.giCursor = 0;
+    }
+#endif
+
+/*---------------------------------------------------------------------------
+    Human68K initialization code.
+  ---------------------------------------------------------------------------*/
+
+#ifdef __human68k__
+    InitTwentyOne();
+#endif
+
+/*---------------------------------------------------------------------------
+    Acorn RISC OS initialization code.
+  ---------------------------------------------------------------------------*/
+
+#ifdef RISCOS
+    set_prefix();
+#endif
+
+/*---------------------------------------------------------------------------
+    Set signal handler for restoring echo, warn of zipfile corruption, etc.
+  ---------------------------------------------------------------------------*/
+
+#ifdef SIGINT
+    signal(SIGINT, handler);
+#endif
+#ifdef SIGTERM                 /* some systems really have no SIGTERM */
+    signal(SIGTERM, handler);
+#endif
+#ifdef SIGBUS
+    signal(SIGBUS, handler);
+#endif
+#ifdef SIGSEGV
+    signal(SIGSEGV, handler);
+#endif
+
+#if (defined(WIN32) && defined(__RSXNT__))
+    for (i = 0 ; i < argc; i++) {
+       _ISO_INTERN(argv[i]);
+    }
+#endif
+
+/*---------------------------------------------------------------------------
+    First figure out if we're running in UnZip mode or ZipInfo mode, and put
+    the appropriate environment-variable options into the queue.  Then rip
+    through any command-line options lurking about...
+  ---------------------------------------------------------------------------*/
+
+#ifdef SFX
+    G.argv0 = argv[0];
+#if (defined(OS2) || defined(WIN32))
+    G.zipfn = GetLoadPath(__G);/* non-MSC NT puts path into G.filename[] */
+#else
+    G.zipfn = G.argv0;
+#endif
+
+#ifdef VMSCLI
+    {
+        ulg status = vms_unzip_cmdline(&argc, &argv);
+        if (!(status & 1))
+            return status;
+    }
+#endif /* VMSCLI */
+
+    uO.zipinfo_mode = FALSE;
+    error = uz_opts(__G__ &argc, &argv);   /* UnZipSFX call only */
+
+#else /* !SFX */
+
+#ifdef RISCOS
+    /* get the extensions to swap from environment */
+    getRISCOSexts(ENV_UNZIPEXTS);
+#endif
+
+#ifdef MSDOS
+    /* extract MKS extended argument list from environment (before envargs!) */
+    mksargs(&argc, &argv);
+#endif
+
+#ifdef VMSCLI
+    {
+        ulg status = vms_unzip_cmdline(&argc, &argv);
+        if (!(status & 1))
+            return status;
+    }
+#endif /* VMSCLI */
+
+    G.noargs = (argc == 1);   /* no options, no zipfile, no anything */
+
+#ifndef NO_ZIPINFO
+    for (p = argv[0] + strlen(argv[0]); p >= argv[0]; --p) {
+        if (*p == DIR_END
+#ifdef DIR_END2
+            || *p == DIR_END2
+#endif
+           )
+            break;
+    }
+    ++p;
+
+    if (STRNICMP(p, LoadFarStringSmall(Zipnfo), 7) == 0 ||
+        STRNICMP(p, "ii", 2) == 0 ||
+        (argc > 1 && strncmp(argv[1], "-Z", 2) == 0))
+    {
+        uO.zipinfo_mode = TRUE;
+        envargs(__G__ &argc, &argv, LoadFarStringSmall(EnvZipInfo),
+          LoadFarStringSmall2(EnvZipInfo2));
+        error = zi_opts(__G__ &argc, &argv);
+    } else
+#endif /* NO_ZIPINFO */
+    {
+        uO.zipinfo_mode = FALSE;
+        envargs(__G__ &argc, &argv, LoadFarStringSmall(EnvUnZip),
+          LoadFarStringSmall2(EnvUnZip2));
+        error = uz_opts(__G__ &argc, &argv);
+    }
+
+#endif /* ?SFX */
+
+    if ((argc < 0) || error)
+        return error;
+
+/*---------------------------------------------------------------------------
+    Now get the zipfile name from the command line and then process any re-
+    maining options and file specifications.
+  ---------------------------------------------------------------------------*/
+
+#ifdef DOS_FLX_H68_OS2_W32
+    /* convert MSDOS-style directory separators to Unix-style ones for
+     * user's convenience (include zipfile name itself)
+     */
+#ifdef SFX
+    for (G.pfnames = argv, i = argc;  i > 0;  --i) {
+#else
+    /* argc does not include the zipfile specification */
+    for (G.pfnames = argv, i = argc+1;  i > 0;  --i) {
+#endif
+        char *q;
+
+        for (q = *G.pfnames;  *q;  ++q)
+            if (*q == '\\')
+                *q = '/';
+        ++G.pfnames;
+    }
+#endif /* DOS_FLX_H68_OS2_W32 */
+
+#ifndef SFX
+    G.wildzipfn = *argv++;
+#endif
+
+#if (defined(SFX) && !defined(SFX_EXDIR)) /* only check for -x */
+
+    G.filespecs = argc;
+    G.xfilespecs = 0;
+
+    if (argc > 0) {
+        char **pp = argv-1;
+
+        G.pfnames = argv;
+        while (*++pp)
+            if (strcmp(*pp, "-x") == 0) {
+                if (pp > argv) {
+                    *pp = 0;              /* terminate G.pfnames */
+                    G.filespecs = pp - G.pfnames;
+                } else {
+                    G.pfnames = (char **)fnames;  /* defaults */
+                    G.filespecs = 0;
+                }
+                G.pxnames = pp + 1;      /* excluded-names ptr: _after_ -x */
+                G.xfilespecs = argc - G.filespecs - 1;
+                break;                    /* skip rest of args */
+            }
+        G.process_all_files = FALSE;
+    } else
+        G.process_all_files = TRUE;      /* for speed */
+
+#else /* !SFX || SFX_EXDIR */             /* check for -x or -d */
+
+    G.filespecs = argc;
+    G.xfilespecs = 0;
+
+    if (argc > 0) {
+        int in_files=FALSE, in_xfiles=FALSE;
+        char **pp = argv-1;
+
+        G.process_all_files = FALSE;
+        G.pfnames = argv;
+        while (*++pp) {
+            Trace((stderr, "pp - argv = %d\n", pp-argv));
+#ifdef CMS_MVS
+            if (!uO.exdir && STRNICMP(*pp, "-d", 2) == 0) {
+#else
+            if (!uO.exdir && strncmp(*pp, "-d", 2) == 0) {
+#endif
+                int firstarg = (pp == argv);
+
+                uO.exdir = (*pp) + 2;
+                if (in_files) {      /* ... zipfile ... -d exdir ... */
+                    *pp = (char *)NULL;         /* terminate G.pfnames */
+                    G.filespecs = pp - G.pfnames;
+                    in_files = FALSE;
+                } else if (in_xfiles) {
+                    *pp = (char *)NULL;         /* terminate G.pxnames */
+                    G.xfilespecs = pp - G.pxnames;
+                    /* "... -x xlist -d exdir":  nothing left */
+                }
+                /* first check for "-dexdir", then for "-d exdir" */
+                if (*uO.exdir == '\0') {
+                    if (*++pp)
+                        uO.exdir = *pp;
+                    else {
+                        Info(slide, 0x401, ((char *)slide,
+                          LoadFarString(MustGiveExdir)));
+                        return(PK_PARAM);  /* don't extract here by accident */
+                    }
+                }
+                if (firstarg) { /* ... zipfile -d exdir ... */
+                    if (pp[1]) {
+                        G.pfnames = pp + 1;  /* argv+2 */
+                        G.filespecs = argc - (G.pfnames-argv);  /* for now... */
+                    } else {
+                        G.process_all_files = TRUE;
+                        G.pfnames = (char **)fnames;  /* GRR: necessary? */
+                        G.filespecs = 0;     /* GRR: necessary? */
+                        break;
+                    }
+                }
+            } else if (!in_xfiles) {
+                if (strcmp(*pp, "-x") == 0) {
+                    in_xfiles = TRUE;
+                    if (pp == G.pfnames) {
+                        G.pfnames = (char **)fnames;  /* defaults */
+                        G.filespecs = 0;
+                    } else if (in_files) {
+                        *pp = 0;                   /* terminate G.pfnames */
+                        G.filespecs = pp - G.pfnames;  /* adjust count */
+                        in_files = FALSE;
+                    }
+                    G.pxnames = pp + 1; /* excluded-names ptr starts after -x */
+                    G.xfilespecs = argc - (G.pxnames-argv);  /* anything left */
+                } else
+                    in_files = TRUE;
+            }
+        }
+    } else
+        G.process_all_files = TRUE;      /* for speed */
+
+    if (uO.exdir != (char *)NULL && !G.extract_flag)    /* -d ignored */
+        Info(slide, 0x401, ((char *)slide, LoadFarString(NotExtracting)));
+#endif /* ?(SFX && !SFX_EXDIR) */
+
+/*---------------------------------------------------------------------------
+    Okey dokey, we have everything we need to get started.  Let's roll.
+  ---------------------------------------------------------------------------*/
+
+    retcode = process_zipfiles(__G);
+    return(retcode);
+
+} /* end main()/unzip() */
+
+
+
+
+
+/**********************/
+/* Function uz_opts() */
+/**********************/
+
+int uz_opts(__G__ pargc, pargv)
+    __GDEF
+    int *pargc;
+    char ***pargv;
+{
+    char **argv, *s;
+    int argc, c, error=FALSE, negative=0;
+
+
+    argc = *pargc;
+    argv = *pargv;
+
+    while (++argv, (--argc > 0 && *argv != NULL && **argv == '-')) {
+        s = *argv + 1;
+        while ((c = *s++) != 0) {    /* "!= 0":  prevent Turbo C warning */
+#ifdef CMS_MVS
+            switch (tolower(c))
+#else
+            switch (c)
+#endif
+            {
+                case ('-'):
+                    ++negative;
+                    break;
+                case ('a'):
+                    if (negative) {
+                        uO.aflag = MAX(uO.aflag-negative,0);
+                        negative = 0;
+                    } else
+                        ++uO.aflag;
+                    break;
+#if (defined(DLL) && defined(API_DOC))
+                case ('A'):    /* extended help for API */
+                    APIhelp(__G__ argc, argv);
+                    *pargc = -1;  /* signal to exit successfully */
+                    return 0;
+#endif
+                case ('b'):
+                    if (negative) {
+#ifdef VMS
+                        uO.bflag = MAX(uO.bflag-negative,0);
+#endif
+                        negative = 0;   /* do nothing:  "-b" is default */
+                    } else {
+#ifdef VMS
+                        if (uO.aflag == 0)
+                           ++uO.bflag;
+#endif
+                        uO.aflag = 0;
+                    }
+                    break;
+#ifdef UNIXBACKUP
+                case ('B'): /* -B: back up existing files */
+                    if (negative)
+                        uO.B_flag = FALSE, negative = 0;
+                    else
+                        uO.B_flag = TRUE;
+                    break;
+#endif
+                case ('c'):
+                    if (negative) {
+                        uO.cflag = FALSE, negative = 0;
+#ifdef NATIVE
+                        uO.aflag = 0;
+#endif
+                    } else {
+                        uO.cflag = TRUE;
+#ifdef NATIVE
+                        uO.aflag = 2;   /* so you can read it on the screen */
+#endif
+#ifdef DLL
+                        if (G.redirect_text)
+                            G.redirect_data = 2;
+#endif
+                    }
+                    break;
+#ifndef CMS_MVS
+                case ('C'):    /* -C:  match filenames case-insensitively */
+                    if (negative)
+                        uO.C_flag = FALSE, negative = 0;
+                    else
+                        uO.C_flag = TRUE;
+                    break;
+#endif /* !CMS_MVS */
+#if (!defined(SFX) || defined(SFX_EXDIR))
+                case ('d'):
+                    if (negative) {   /* negative not allowed with -d exdir */
+                        Info(slide, 0x401, ((char *)slide,
+                          LoadFarString(MustGiveExdir)));
+                        return(PK_PARAM);  /* don't extract here by accident */
+                    }
+                    if (uO.exdir != (char *)NULL) {
+                        Info(slide, 0x401, ((char *)slide,
+                          LoadFarString(OnlyOneExdir)));
+                        return(PK_PARAM);    /* GRR:  stupid restriction? */
+                    } else {
+                        /* first check for "-dexdir", then for "-d exdir" */
+                        uO.exdir = s;
+                        if (*uO.exdir == '\0') {
+                            if (argc > 1) {
+                                --argc;
+                                uO.exdir = *++argv;
+                                if (*uO.exdir == '-') {
+                                    Info(slide, 0x401, ((char *)slide,
+                                      LoadFarString(MustGiveExdir)));
+                                    return(PK_PARAM);
+                                }
+                                /* else uO.exdir points at extraction dir */
+                            } else {
+                                Info(slide, 0x401, ((char *)slide,
+                                  LoadFarString(MustGiveExdir)));
+                                return(PK_PARAM);
+                            }
+                        }
+                        /* uO.exdir now points at extraction dir (-dexdir or
+                         *  -d exdir); point s at end of exdir to avoid mis-
+                         *  interpretation of exdir characters as more options
+                         */
+                        if (*s != 0)
+                            while (*++s != 0)
+                                ;
+                    }
+                    break;
+#endif /* !SFX || SFX_EXDIR */
+                case ('e'):    /* just ignore -e, -x options (extract) */
+                    break;
+#ifdef MACOS
+                case ('E'): /* -E [MacOS] display Mac e.f. when restoring */
+                    if( negative ) {
+                        uO.E_flag = FALSE, negative = 0;
+                    } else {
+                        uO.E_flag = TRUE;
+                    }
+                    break;
+#endif /* MACOS */
+                case ('f'):    /* "freshen" (extract only newer files) */
+                    if (negative)
+                        uO.fflag = uO.uflag = FALSE, negative = 0;
+                    else
+                        uO.fflag = uO.uflag = TRUE;
+                    break;
+#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))
+                case ('F'):    /* Acorn filetype & NFS extension handling */
+                    if (negative)
+                        uO.acorn_nfs_ext = FALSE, negative = 0;
+                    else
+                        uO.acorn_nfs_ext = TRUE;
+                    break;
+#endif /* RISCOS || ACORN_FTYPE_NFS */
+                case ('h'):    /* just print help message and quit */
+                    *pargc = -1;
+                    return USAGE(PK_OK);
+#ifdef MACOS
+                case ('i'): /* -i [MacOS] ignore filenames stored in Mac ef */
+                    if( negative ) {
+                        uO.i_flag = FALSE, negative = 0;
+                    } else {
+                        uO.i_flag = TRUE;
+                    }
+                    break;
+#endif  /* MACOS */
+                case ('j'):    /* junk pathnames/directory structure */
+                    if (negative)
+                        uO.jflag = FALSE, negative = 0;
+                    else
+                        uO.jflag = TRUE;
+                    break;
+#if (defined(__BEOS__) || defined(MACOS))
+                case ('J'):    /* Junk BeOS or MacOS file attributes */
+                    if( negative ) {
+                        uO.J_flag = FALSE, negative = 0;
+                    } else {
+                        uO.J_flag = TRUE;
+                    }
+                    break;
+#endif /* __BEOS__ || MACOS */
+#ifndef SFX
+                case ('l'):
+                    if (negative) {
+                        uO.vflag = MAX(uO.vflag-negative,0);
+                        negative = 0;
+                    } else
+                        ++uO.vflag;
+                    break;
+#endif /* !SFX */
+#ifndef CMS_MVS
+                case ('L'):    /* convert (some) filenames to lowercase */
+                    if (negative)
+                        uO.L_flag = FALSE, negative = 0;
+                    else
+                        uO.L_flag = TRUE;
+                    break;
+#endif /* !CMS_MVS */
+#ifdef MORE
+#ifdef CMS_MVS
+                case ('m'):
+#endif
+                case ('M'):    /* send all screen output through "more" fn. */
+/* GRR:  eventually check for numerical argument => height */
+                    if (negative)
+                        G.M_flag = FALSE, negative = 0;
+                    else
+                        G.M_flag = TRUE;
+                    break;
+#endif /* MORE */
+                case ('n'):    /* don't overwrite any files */
+                    if (negative)
+                        uO.overwrite_none = FALSE, negative = 0;
+                    else
+                        uO.overwrite_none = TRUE;
+                    break;
+#ifdef AMIGA
+                case ('N'):    /* restore comments as filenotes */
+                    if (negative)
+                        uO.N_flag = FALSE, negative = 0;
+                    else
+                        uO.N_flag = TRUE;
+                    break;
+#endif /* AMIGA */
+                case ('o'):    /* OK to overwrite files without prompting */
+                    if (negative) {
+                        uO.overwrite_all = MAX(uO.overwrite_all-negative,0);
+                        negative = 0;
+                    } else
+                        ++uO.overwrite_all;
+                    break;
+                case ('p'):    /* pipes:  extract to stdout, no messages */
+                    if (negative) {
+                        uO.cflag = FALSE;
+                        uO.qflag = MAX(uO.qflag-999,0);
+                        negative = 0;
+                    } else {
+                        uO.cflag = TRUE;
+                        uO.qflag += 999;
+                    }
+                    break;
+#if CRYPT
+                /* GRR:  yes, this is highly insecure, but dozens of people
+                 * have pestered us for this, so here we go... */
+                case ('P'):
+                    if (negative) {   /* negative not allowed with -P passwd */
+                        Info(slide, 0x401, ((char *)slide,
+                          LoadFarString(MustGivePasswd)));
+                        return(PK_PARAM);  /* don't extract here by accident */
+                    }
+                    if (uO.pwdarg != (char *)NULL) {
+/*
+                        GRR:  eventually support multiple passwords?
+                        Info(slide, 0x401, ((char *)slide,
+                          LoadFarString(OnlyOnePasswd)));
+                        return(PK_PARAM);
+ */
+                    } else {
+                        /* first check for "-Ppasswd", then for "-P passwd" */
+                        uO.pwdarg = s;
+                        if (*uO.pwdarg == '\0') {
+                            if (argc > 1) {
+                                --argc;
+                                uO.pwdarg = *++argv;
+                                if (*uO.pwdarg == '-') {
+                                    Info(slide, 0x401, ((char *)slide,
+                                      LoadFarString(MustGivePasswd)));
+                                    return(PK_PARAM);
+                                }
+                                /* else pwdarg points at decryption password */
+                            } else {
+                                Info(slide, 0x401, ((char *)slide,
+                                  LoadFarString(MustGivePasswd)));
+                                return(PK_PARAM);
+                            }
+                        }
+                        /* pwdarg now points at decryption password (-Ppasswd or
+                         *  -P passwd); point s at end of passwd to avoid mis-
+                         *  interpretation of passwd characters as more options
+                         */
+                        if (*s != 0)
+                            while (*++s != 0)
+                                ;
+                    }
+                    break;
+#endif /* CRYPT */
+                case ('q'):    /* quiet:  fewer comments/messages */
+                    if (negative) {
+                        uO.qflag = MAX(uO.qflag-negative,0);
+                        negative = 0;
+                    } else
+                        ++uO.qflag;
+                    break;
+#ifdef QDOS
+                case ('Q'):   /* QDOS flags */
+                    qlflag ^= strtol(s, &s, 10);
+                    break;    /* we XOR this as we can config qlflags */
+#endif
+#ifdef DOS_FLX_OS2_W32
+                case ('s'):    /* spaces in filenames:  allow by default */
+                    if (negative)
+                        uO.sflag = FALSE, negative = 0;
+                    else
+                        uO.sflag = TRUE;
+                    break;
+#endif /* DOS_FLX_OS2_W32 */
+                case ('t'):
+                    if (negative)
+                        uO.tflag = FALSE, negative = 0;
+                    else
+                        uO.tflag = TRUE;
+                    break;
+#ifdef TIMESTAMP
+                case ('T'):
+                    if (negative)
+                        uO.T_flag = FALSE, negative = 0;
+                    else
+                        uO.T_flag = TRUE;
+                    break;
+#endif
+                case ('u'):    /* update (extract only new and newer files) */
+                    if (negative)
+                        uO.uflag = FALSE, negative = 0;
+                    else
+                        uO.uflag = TRUE;
+                    break;
+#ifndef CMS_MVS
+                case ('U'):    /* obsolete; to be removed in version 6.0 */
+                    if (negative)
+                        uO.L_flag = TRUE, negative = 0;
+                    else
+                        uO.L_flag = FALSE;
+                    break;
+#endif /* !CMS_MVS */
+#ifndef SFX
+                case ('v'):    /* verbose */
+                    if (negative) {
+                        uO.vflag = MAX(uO.vflag-negative,0);
+                        negative = 0;
+                    } else if (uO.vflag)
+                        ++uO.vflag;
+                    else
+                        uO.vflag = 2;
+                    break;
+#endif /* !SFX */
+#ifndef CMS_MVS
+                case ('V'):    /* Version (retain VMS/DEC-20 file versions) */
+                    if (negative)
+                        uO.V_flag = FALSE, negative = 0;
+                    else
+                        uO.V_flag = TRUE;
+                    break;
+#endif /* !CMS_MVS */
+                case ('x'):    /* extract:  default */
+#ifdef SFX
+                    /* when 'x' is the only option in this argument, and the
+                     * next arg is not an option, assume this initiates an
+                     * exclusion list (-x xlist):  terminate option-scanning
+                     * and leave uz_opts with argv still pointing to "-x";
+                     * the xlist is processed later
+                     */
+                    if (s - argv[0] == 2 && *s == '\0' &&
+                        argc > 1 && argv[1][0] != '-') {
+                        /* break out of nested loops without "++argv;--argc" */
+                        goto opts_done;
+                    }
+#endif /* SFX */
+                    break;
+#if (defined(RESTORE_UIDGID) || defined(OS2_W32))
+                case ('X'):   /* restore owner/protection info (need privs?) */
+                    if (negative) {
+                        uO.X_flag = MAX(uO.X_flag-negative,0);
+                        negative = 0;
+                    } else
+                        ++uO.X_flag;
+                    break;
+#endif /* RESTORE_UIDGID || OS2_W32 */
+                case ('z'):    /* display only the archive comment */
+                    if (negative) {
+                        uO.zflag = MAX(uO.zflag-negative,0);
+                        negative = 0;
+                    } else
+                        ++uO.zflag;
+                    break;
+#ifndef SFX
+                case ('Z'):    /* should have been first option (ZipInfo) */
+                    Info(slide, 0x401, ((char *)slide, LoadFarString(Zfirst)));
+                    error = TRUE;
+                    break;
+#endif /* !SFX */
+#ifdef DOS_OS2_W32
+                case ('$'):
+                    if (negative) {
+                        uO.volflag = MAX(uO.volflag-negative,0);
+                        negative = 0;
+                    } else
+                        ++uO.volflag;
+                    break;
+#endif /* DOS_OS2_W32 */
+                default:
+                    error = TRUE;
+                    break;
+
+            } /* end switch */
+        } /* end while (not end of argument string) */
+    } /* end while (not done with switches) */
+
+/*---------------------------------------------------------------------------
+    Check for nonsensical combinations of options.
+  ---------------------------------------------------------------------------*/
+
+#ifdef SFX
+opts_done:  /* yes, very ugly...but only used by UnZipSFX with -x xlist */
+#endif
+
+    if ((uO.cflag && uO.tflag) || (uO.cflag && uO.uflag) ||
+        (uO.tflag && uO.uflag) || (uO.fflag && uO.overwrite_none))
+    {
+        Info(slide, 0x401, ((char *)slide, LoadFarString(InvalidOptionsMsg)));
+        error = TRUE;
+    }
+    if (uO.aflag > 2)
+        uO.aflag = 2;
+#ifdef VMS
+    if (uO.bflag > 2)
+        uO.bflag = 2;
+#endif
+    if (uO.overwrite_all && uO.overwrite_none) {
+        Info(slide, 0x401, ((char *)slide, LoadFarString(IgnoreOOptionMsg)));
+        uO.overwrite_all = FALSE;
+    }
+#ifdef MORE
+    if (G.M_flag && !isatty(1))  /* stdout redirected: "more" func. useless */
+        G.M_flag = 0;
+#endif
+
+#ifdef SFX
+    if (error)
+#else
+    if ((argc-- == 0) || error)
+#endif
+    {
+        *pargc = argc;
+        *pargv = argv;
+#ifndef SFX
+        if (uO.vflag >= 2 && argc == -1) {              /* "unzip -v" */
+            show_version_info(__G);
+            return PK_OK;
+        }
+        if (!G.noargs && !error)
+            error = PK_PARAM;   /* had options (not -h or -v) but no zipfile */
+#endif /* !SFX */
+        return USAGE(error);
+    }
+
+#ifdef SFX
+    /* print our banner unless we're being fairly quiet */
+    if (uO.qflag < 2)
+        Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner),
+          UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, BETALEVEL,
+          LoadFarStringSmall(VersionDate)));
+#ifdef BETA
+    /* always print the beta warning:  no unauthorized distribution!! */
+    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n",
+      "SFX"));
+#endif
+#endif /* SFX */
+
+    if (uO.cflag || uO.tflag || uO.vflag || uO.zflag
+#ifdef TIMESTAMP
+                                                     || uO.T_flag
+#endif
+                                                                 )
+        G.extract_flag = FALSE;
+    else
+        G.extract_flag = TRUE;
+
+    *pargc = argc;
+    *pargv = argv;
+    return PK_OK;
+
+} /* end function uz_opts() */
+
+
+
+
+/********************/
+/* Function usage() */
+/********************/
+
+#ifdef SFX
+#  ifdef VMS
+#    define LOCAL "X.  Quote uppercase options"
+#  endif
+#  ifdef UNIX
+#    define LOCAL "X"
+#  endif
+#  ifdef DOS_OS2_W32
+#    define LOCAL "s$"
+#  endif
+#  ifdef FLEXOS
+#    define LOCAL "s"
+#  endif
+#  ifdef AMIGA
+#    define LOCAL "N"
+#  endif
+   /* Default for all other systems: */
+#  ifndef LOCAL
+#    define LOCAL ""
+#  endif
+
+#  ifdef MORE
+#    define SFXOPT1 "M"
+#  else
+#    define SFXOPT1 ""
+#  endif
+
+int usage(__G__ error)   /* return PK-type error code */
+    __GDEF
+    int error;
+{
+    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner),
+      UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, BETALEVEL,
+      LoadFarStringSmall(VersionDate)));
+    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXOpts),
+      SFXOPT1, LOCAL));
+#ifdef BETA
+    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n",
+      "SFX"));
+#endif
+
+    if (error)
+        return PK_PARAM;
+    else
+        return PK_COOL;     /* just wanted usage screen: no error */
+
+} /* end function usage() */
+
+
+
+
+
+#else /* !SFX */
+#  ifdef VMS
+#    define QUOT '\"'
+#    define QUOTS "\""
+#  else
+#    define QUOT ' '
+#    define QUOTS ""
+#  endif
+
+int usage(__G__ error)   /* return PK-type error code */
+    __GDEF
+    int error;
+{
+    int flag = (error? 1 : 0);
+
+
+/*---------------------------------------------------------------------------
+    Print either ZipInfo usage or UnZip usage, depending on incantation.
+    (Strings must be no longer than 512 bytes for Turbo C, apparently.)
+  ---------------------------------------------------------------------------*/
+
+    if (uO.zipinfo_mode) {
+
+#ifndef NO_ZIPINFO
+
+        Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine1),
+          ZI_MAJORVER, ZI_MINORVER, PATCHLEVEL, BETALEVEL,
+          LoadFarStringSmall(VersionDate),
+          LoadFarStringSmall2(ZipInfoExample), QUOTS,QUOTS));
+        Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine2)));
+        Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine3),
+          QUOT,QUOT, QUOT,QUOT, LoadFarStringSmall(ZipInfoUsageLine4)));
+#ifdef VMS
+        Info(slide, flag, ((char *)slide, "\nRemember that non-lowercase\
+ filespecs must be quoted in VMS (e.g., \"Makefile\").\n"));
+#endif
+
+#endif /* !NO_ZIPINFO */
+
+    } else {   /* UnZip mode */
+
+        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine1),
+          UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, BETALEVEL,
+          LoadFarStringSmall(VersionDate)));
+#ifdef BETA
+        Info(slide, flag, ((char *)slide, LoadFarString(BetaVersion), "", ""));
+#endif
+
+        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine2),
+          ZIPINFO_MODE_OPTION, LoadFarStringSmall(ZipInfoMode)));
+#ifdef VMS
+        if (!error)  /* maybe no command-line tail found; show extra help */
+            Info(slide, flag, ((char *)slide, LoadFarString(VMSusageLine2b)));
+#endif
+
+        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine3),
+          LoadFarStringSmall(local1)));
+
+        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine4),
+          QUOT,QUOT, QUOT,QUOT, LoadFarStringSmall(local2), QUOT,QUOT,
+          LoadFarStringSmall2(local3)));
+
+        /* This is extra work for SMALL_MEM, but it will work since
+         * LoadFarStringSmall2 uses the same buffer.  Remember, this
+         * is a hack. */
+        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine5),
+          LoadFarStringSmall(Example2), LoadFarStringSmall2(Example3),
+          LoadFarStringSmall2(Example3)));
+
+    } /* end if (uO.zipinfo_mode) */
+
+    if (error)
+        return PK_PARAM;
+    else
+        return PK_COOL;     /* just wanted usage screen: no error */
+
+} /* end function usage() */
+
+#endif /* ?SFX */
+
+
+
+
+#ifndef SFX
+
+/********************************/
+/* Function show_version_info() */
+/********************************/
+
+static void show_version_info(__G)
+    __GDEF
+{
+    if (uO.qflag > 3)                           /* "unzip -vqqqq" */
+        Info(slide, 0, ((char *)slide, "%d\n",
+          (UZ_MAJORVER*100 + UZ_MINORVER*10 + PATCHLEVEL)));
+    else {
+        char *envptr, *getenv();
+        int numopts = 0;
+
+        Info(slide, 0, ((char *)slide, LoadFarString(UnzipUsageLine1v),
+          UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, BETALEVEL,
+          LoadFarStringSmall(VersionDate)));
+        Info(slide, 0, ((char *)slide,
+          LoadFarString(UnzipUsageLine2v)));
+        version(__G);
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptions)));
+#ifdef ACORN_FTYPE_NFS
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(AcornFtypeNFS)));
+        ++numopts;
+#endif
+#ifdef ASM_CRC
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(AsmCRC)));
+        ++numopts;
+#endif
+#ifdef ASM_INFLATECODES
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(AsmInflateCodes)));
+        ++numopts;
+#endif
+#ifdef CHECK_VERSIONS
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(Check_Versions)));
+        ++numopts;
+#endif
+#ifdef COPYRIGHT_CLEAN
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(Copyright_Clean)));
+        ++numopts;
+#endif
+#ifdef DEBUG
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(UDebug)));
+        ++numopts;
+#endif
+#ifdef DEBUG_TIME
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(DebugTime)));
+        ++numopts;
+#endif
+#ifdef DLL
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(Dll)));
+        ++numopts;
+#endif
+#ifdef DOSWILD
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(DosWild)));
+        ++numopts;
+#endif
+#ifdef LZW_CLEAN
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(LZW_Clean)));
+        ++numopts;
+#endif
+#ifndef MORE
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(No_More)));
+        ++numopts;
+#endif
+#ifdef NO_ZIPINFO
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(No_ZipInfo)));
+        ++numopts;
+#endif
+#ifdef NTSD_EAS
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(NTSDExtAttrib)));
+        ++numopts;
+#endif
+#ifdef OS2_EAS
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(OS2ExtAttrib)));
+        ++numopts;
+#endif
+#ifdef QLZIP
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(SMSExFldOnUnix)));
+        ++numopts;
+#endif
+#ifdef REENTRANT
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(Reentrant)));
+        ++numopts;
+#endif
+#ifdef REGARGS
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(RegArgs)));
+        ++numopts;
+#endif
+#ifdef RETURN_CODES
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(Return_Codes)));
+        ++numopts;
+#endif
+#ifdef SET_DIR_ATTRIB
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(SetDirAttrib)));
+        ++numopts;
+#endif
+#ifdef TIMESTAMP
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(TimeStamp)));
+        ++numopts;
+#endif
+#ifdef UNIXBACKUP
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(UnixBackup)));
+        ++numopts;
+#endif
+#ifdef USE_EF_UT_TIME
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(Use_EF_UT_time)));
+        ++numopts;
+#endif
+#ifndef COPYRIGHT_CLEAN
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(Use_Smith_Code)));
+        ++numopts;
+#endif
+#ifndef LZW_CLEAN
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(Use_Unshrink)));
+        ++numopts;
+#endif
+#ifdef USE_VFAT
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(Use_VFAT_support)));
+        ++numopts;
+#endif
+#ifdef USE_ZLIB
+        sprintf((char *)(slide+256), LoadFarStringSmall(UseZlib),
+          ZLIB_VERSION, zlib_version);
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          (char *)(slide+256)));
+        ++numopts;
+#endif
+#ifdef VMS_TEXT_CONV
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(VmsTextConv)));
+        ++numopts;
+#endif
+#ifdef VMSCLI
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(VmsCLI)));
+        ++numopts;
+#endif
+#ifdef VMSWILD
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(VmsWild)));
+        ++numopts;
+#endif
+#if CRYPT
+# ifdef PASSWD_FROM_STDIN
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(PasswdStdin)));
+# endif
+        Info(slide, 0, ((char *)slide, LoadFarString(Decryption),
+          CR_MAJORVER, CR_MINORVER, CR_BETA_VER,
+          LoadFarStringSmall(CryptDate)));
+        ++numopts;
+#endif /* CRYPT */
+        if (numopts == 0)
+            Info(slide, 0, ((char *)slide,
+              LoadFarString(CompileOptFormat),
+              LoadFarStringSmall(None)));
+
+        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptions)));
+        envptr = getenv(LoadFarStringSmall(EnvUnZip));
+        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
+          LoadFarStringSmall(EnvUnZip),
+          (envptr == (char *)NULL || *envptr == 0)?
+          LoadFarStringSmall2(None) : envptr));
+        envptr = getenv(LoadFarStringSmall(EnvUnZip2));
+        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
+          LoadFarStringSmall(EnvUnZip2),
+          (envptr == (char *)NULL || *envptr == 0)?
+          LoadFarStringSmall2(None) : envptr));
+        envptr = getenv(LoadFarStringSmall(EnvZipInfo));
+        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
+          LoadFarStringSmall(EnvZipInfo),
+          (envptr == (char *)NULL || *envptr == 0)?
+          LoadFarStringSmall2(None) : envptr));
+        envptr = getenv(LoadFarStringSmall(EnvZipInfo2));
+        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
+          LoadFarStringSmall(EnvZipInfo2),
+          (envptr == (char *)NULL || *envptr == 0)?
+          LoadFarStringSmall2(None) : envptr));
+#ifndef __RSXNT__
+#ifdef __EMX__
+        envptr = getenv(LoadFarStringSmall(EnvEMX));
+        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
+          LoadFarStringSmall(EnvEMX),
+          (envptr == (char *)NULL || *envptr == 0)?
+          LoadFarStringSmall2(None) : envptr));
+        envptr = getenv(LoadFarStringSmall(EnvEMXOPT));
+        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
+          LoadFarStringSmall(EnvEMXOPT),
+          (envptr == (char *)NULL || *envptr == 0)?
+          LoadFarStringSmall2(None) : envptr));
+#endif /* __EMX__ */
+#if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2)))
+        envptr = getenv(LoadFarStringSmall(EnvGO32));
+        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
+          LoadFarStringSmall(EnvGO32),
+          (envptr == (char *)NULL || *envptr == 0)?
+          LoadFarStringSmall2(None) : envptr));
+        envptr = getenv(LoadFarStringSmall(EnvGO32TMP));
+        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
+          LoadFarStringSmall(EnvGO32TMP),
+          (envptr == (char *)NULL || *envptr == 0)?
+          LoadFarStringSmall2(None) : envptr));
+#endif /* __GO32__ && !(__DJGPP__ >= 2) */
+#endif /* !__RSXNT__ */
+#ifdef RISCOS
+        envptr = getenv(LoadFarStringSmall(EnvUnZipExts));
+        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
+          LoadFarStringSmall(EnvUnZipExts),
+          (envptr == (char *)NULL || *envptr == 0)?
+          LoadFarStringSmall2(None) : envptr));
+#endif /* RISCOS */
+    }
+} /* end function show_version() */
+
+#endif /* !SFX */
+#endif /* !WINDLL */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/unzip.def	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,4 @@
+NAME WINDOWCOMPAT NEWFILES
+DESCRIPTION 'The world-famous Info-ZIP unarchiving utilities'
+; SEGMENTS
+;   _MSGSEG32 CLASS 'CODE'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/unzipstb.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,48 @@
+/*---------------------------------------------------------------------------
+
+  unzipstb.c
+
+  Simple stub function for UnZip DLL (or shared library, whatever); does
+  exactly the same thing as normal UnZip, except for additional printf()s
+  of various version numbers, solely as a demonstration of what can/should
+  be checked when using the DLL.  (If major version numbers ever differ,
+  assume program is incompatible with DLL--especially if DLL version is
+  older.  This is not likely to be a problem with *this* simple program,
+  but most user programs will be much more complex.)
+
+  ---------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include "unzip.h"
+#include "version.h"
+
+int main(int argc, char *argv[])
+{
+    static UzpVer *pVersion;   /* no pervert jokes, please... */
+
+    pVersion = UzpVersion();
+
+    printf("UnZip stub:  checking version numbers (DLL is dated %s)\n",
+      pVersion->date);
+    printf("   UnZip versions:    expecting %d.%d%d, using %d.%d%d%s\n",
+      UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, pVersion->unzip.major,
+      pVersion->unzip.minor, pVersion->unzip.patchlevel, pVersion->betalevel);
+    printf("   ZipInfo versions:  expecting %d.%d%d, using %d.%d%d\n",
+      ZI_MAJORVER, ZI_MINORVER, PATCHLEVEL, pVersion->zipinfo.major,
+      pVersion->zipinfo.minor, pVersion->zipinfo.patchlevel);
+
+/*
+    D2_M*VER and os2dll.* are obsolete, though retained for compatibility:
+
+    printf("   OS2 DLL versions:  expecting %d.%d%d, using %d.%d%d\n",
+      D2_MAJORVER, D2_MINORVER, PATCHLEVEL, pVersion->os2dll.major,
+      pVersion->os2dll.minor, pVersion->os2dll.patchlevel);
+ */
+
+    if (pVersion->flag & 2)
+        printf("   using zlib version %s\n", pVersion->zlib_version);
+    printf("\n");
+
+    /* call the actual UnZip routine (string-arguments version) */
+    return UzpMain(argc, argv);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/win32.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,2390 @@
+/*---------------------------------------------------------------------------
+
+  win32.c
+
+  32-bit Windows-specific (NT/95) routines for use with Info-ZIP's UnZip 5.3
+  and later.
+
+  Contains:  GetLoadPath()
+             Opendir()
+             Readdir()
+             Closedir()
+             process_defer_NT()   process any deferred items
+             SetSD()              set security descriptor on file
+             EvalExtraFields()    evaluate and process and extra field NOW
+             IsWinNT()            indicate type of WIN32 platform
+             test_NTSD()          test integrity of NT security data
+             utime2FileTime()
+             FStampIsLocTime()
+             FileTime2utime()
+             VFatFileTime2utime()
+             UTCtime2Localtime()
+             NTtzbugWorkaround()
+             getNTfiletime()
+             close_outfile()
+             stamp_file()
+             isfloppy()
+             NTQueryVolInfo()
+             IsVolumeOldFAT()
+             do_wild()
+             mapattr()
+             mapname()
+             map2fat()
+             checkdir()
+             version()
+             zstat_win32()
+             getch_win32()
+
+  ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#include <windows.h>    /* must be AFTER unzip.h to avoid struct G problems */
+#ifdef __RSXNT__
+#  include "rsxntwin.h"
+#endif
+#include "nt.h"
+
+#ifndef FUNZIP          /* most of this file is not used with fUnZip */
+
+#if (defined(__GO32__) || defined(__EMX__) || defined(__CYGWIN32__))
+#  define MKDIR(path,mode)   mkdir(path,mode)
+#else
+#  define MKDIR(path,mode)   mkdir(path)
+#endif
+
+#ifdef HAVE_WORKING_DIRENT_H
+#  undef HAVE_WORKING_DIRENT_H
+#endif
+/* The emxrtl dirent support of (__GO32__ || __EMX__) converts to lowercase! */
+#if defined(__CYGWIN32__)
+#  define HAVE_WORKING_DIRENT_H
+#endif
+
+#ifndef SFX
+#  ifdef HAVE_WORKING_DIRENT_H
+#    include <dirent.h>         /* use readdir() */
+#    define zdirent  dirent
+#    define zDIR     DIR
+#    define Opendir  opendir
+#    define Readdir  readdir
+#    define Closedir closedir
+#  else /* !HAVE_WORKING_DIRENT_H */
+     typedef struct zdirent {
+         char    reserved [21];
+         char    ff_attrib;
+         short   ff_ftime;
+         short   ff_fdate;
+         long    size;
+         char    d_name[MAX_PATH];
+         int     d_first;
+         HANDLE  d_hFindFile;
+     } zDIR;
+
+     static zDIR           *Opendir  (const char *n);
+     static struct zdirent *Readdir  (zDIR *d);
+     static void            Closedir (zDIR *d);
+#  endif /* ?HAVE_WORKING_DIRENT_H */
+#endif /* !SFX */
+
+
+/* Function prototypes */
+#ifdef NTSD_EAS
+   static int  SetSD(__GPRO__ char *path, PVOLUMECAPS VolumeCaps,
+                     uch *eb_ptr, unsigned eb_len);
+   static int  EvalExtraFields(__GPRO__ char *path, uch *ef_ptr,
+                               unsigned ef_len);
+#endif
+
+#if (defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND) || \
+     defined(TIMESTAMP))
+   static void utime2FileTime(time_t ut, FILETIME *pft);
+   static int FStampIsLocTime(__GPRO__ const char *path);
+#endif /* USE_EF_UT_TIME || NT_TZBUG_WORKAROUND || TIMESTAMP */
+#ifdef NT_TZBUG_WORKAROUND
+   static int FileTime2utime(const FILETIME *pft, time_t *ut);
+#ifdef W32_STAT_BANDAID
+   static int VFatFileTime2utime(const FILETIME *pft, time_t *ut);
+#endif
+   static time_t UTCtime2Localtime(time_t utctime);
+   static void NTtzbugWorkaround(time_t ut, FILETIME *pft);
+#endif /* NT_TZBUG_WORKAROUND */
+
+static int  getNTfiletime   (__GPRO__ FILETIME *pModFT, FILETIME *pAccFT,
+                             FILETIME *pCreFT);
+static int  isfloppy        (int nDrive);
+static int  NTQueryVolInfo  (__GPRO__ const char *name);
+static int  IsVolumeOldFAT  (__GPRO__ const char *name);
+static void map2fat         (char *pathcomp, char **pEndFAT);
+
+
+#ifdef __MINGW32__
+   int _CRT_glob = 0;   /* suppress command line globbing by C RTL */
+#endif
+
+/* static int created_dir;      */     /* used by mapname(), checkdir() */
+/* static int renamed_fullpath; */     /* ditto */
+/* static int fnlen;            */     /* ditto */
+/* static unsigned nLabelDrive; */     /* ditto */
+
+extern char Far TruncNTSD[];    /* in extract.c */
+
+
+
+#ifdef SFX
+
+/**************************/
+/* Function GetLoadPath() */
+/**************************/
+
+char *GetLoadPath(__GPRO)
+{
+#ifdef MSC
+    extern char *_pgmptr;
+    return _pgmptr;
+
+#else    /* use generic API call */
+
+    GetModuleFileName(NULL, G.filename, FILNAMSIZ-1);
+    _ISO_INTERN(G.filename);    /* translate to codepage of C rtl's stdio */
+    return G.filename;
+#endif
+
+} /* end function GetLoadPath() */
+
+
+
+
+
+#else /* !SFX */
+
+#ifndef HAVE_WORKING_DIRENT_H
+
+/**********************/        /* Borrowed from ZIP 2.0 sources            */
+/* Function Opendir() */        /* Difference: no special handling for      */
+/**********************/        /*             hidden or system files.      */
+
+static zDIR *Opendir(n)
+    const char *n;          /* directory to open */
+{
+    zDIR *d;                /* malloc'd return value */
+    char *p;                /* malloc'd temporary string */
+    WIN32_FIND_DATA fd;
+    extent len = strlen(n);
+
+    /* Start searching for files in directory n */
+
+    if ((d = (zDIR *)malloc(sizeof(zDIR))) == NULL ||
+        (p = malloc(strlen(n) + 5)) == NULL)
+    {
+        if (d != (zDIR *)NULL)
+            free((void *)d);
+        return (zDIR *)NULL;
+    }
+    INTERN_TO_ISO(n, p);
+    if (len > 0) {
+        if (p[len-1] == ':')
+            p[len++] = '.';     /* x: => x:. */
+        else if (p[len-1] == '/' || p[len-1] == '\\')
+            --len;              /* foo/ => foo */
+    }
+    strcpy(p+len, "/*");
+
+    if (INVALID_HANDLE_VALUE == (d->d_hFindFile = FindFirstFile(p, &fd))) {
+        free((zvoid *)d);
+        free((zvoid *)p);
+        return NULL;
+    }
+    strcpy(d->d_name, fd.cFileName);
+
+    free((zvoid *)p);
+    d->d_first = 1;
+    return d;
+
+} /* end of function Opendir() */
+
+
+
+
+/**********************/        /* Borrowed from ZIP 2.0 sources            */
+/* Function Readdir() */        /* Difference: no special handling for      */
+/**********************/        /*             hidden or system files.      */
+
+static struct zdirent *Readdir(d)
+    zDIR *d;                    /* directory stream from which to read */
+{
+    /* Return pointer to first or next directory entry, or NULL if end. */
+
+    if ( d->d_first )
+        d->d_first = 0;
+    else
+    {
+        WIN32_FIND_DATA fd;
+
+        if ( !FindNextFile(d->d_hFindFile, &fd) )
+            return NULL;
+
+        ISO_TO_INTERN(fd.cFileName, d->d_name);
+    }
+    return (struct zdirent *)d;
+
+} /* end of function Readdir() */
+
+
+
+
+/***********************/
+/* Function Closedir() */       /* Borrowed from ZIP 2.0 sources */
+/***********************/
+
+static void Closedir(d)
+    zDIR *d;                    /* directory stream to close */
+{
+    FindClose(d->d_hFindFile);
+    free(d);
+}
+
+#endif /* !HAVE_WORKING_DIRENT_H */
+#endif /* ?SFX */
+
+
+
+
+#ifdef NTSD_EAS
+
+/*********************************/
+/*  Function process_defer_NT()  */
+/*********************************/
+
+void process_defer_NT(__G)
+    __GDEF
+{
+    /* process deferred items */
+
+    DWORD dir, bytes;
+    DWORD dirfail, bytesfail;
+
+    ProcessDefer(&dir, &bytes, &dirfail, &bytesfail);
+
+    if (!uO.tflag && (uO.qflag < 2)) {
+        if (dir)
+            Info(slide, 0, ((char *)slide,
+              "    updated: %lu directory entries with %lu bytes security",
+              (ulg)dir, (ulg)bytes));
+        if (dirfail)
+            Info(slide, 0, ((char *)slide,
+              "     failed: %lu directory entries with %lu bytes security",
+              (ulg)dirfail, (ulg)bytesfail));
+    }
+}
+
+
+
+/**********************/
+/*  Function SetSD()  */   /* return almost-PK errors */
+/**********************/
+
+static int SetSD(__G__ path, VolumeCaps, eb_ptr, eb_len)
+    __GDEF
+    char *path;
+    PVOLUMECAPS VolumeCaps;
+    uch *eb_ptr;
+    unsigned eb_len;
+{
+    ulg ntsd_ucSize;
+    uch *security_data;
+    int error;
+
+    if (eb_ptr == NULL || eb_len < EB_NTSD_L_LEN)
+        return PK_OK;  /* not a valid NTSD extra field:  assume OK */
+
+    /* check if we know how to handle this version */
+    if (*(eb_ptr + (EB_HEADSIZE+EB_NTSD_VERSION)) > (uch)EB_NTSD_MAX_VER)
+        return PK_OK;
+
+    ntsd_ucSize = makelong(eb_ptr + (EB_HEADSIZE+EB_UCSIZE_P));
+    if (ntsd_ucSize > 0L && eb_len <= (EB_NTSD_L_LEN + EB_CMPRHEADLEN))
+        return IZ_EF_TRUNC;               /* no compressed data! */
+
+    /* allocate storage for uncompressed data */
+    security_data = (uch *)malloc((extent)ntsd_ucSize);
+    if (security_data == (uch *)NULL)
+        return PK_MEM4;
+
+    error = memextract(__G__ security_data, ntsd_ucSize,
+      (eb_ptr + (EB_HEADSIZE+EB_NTSD_L_LEN)), (ulg)(eb_len - EB_NTSD_L_LEN));
+
+    if (error == PK_OK) {
+        if (SecuritySet(path, VolumeCaps, security_data)) {
+            error = PK_COOL;
+            if (!uO.tflag && (uO.qflag < 2) &&
+                (!(VolumeCaps->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)))
+                Info(slide, 0, ((char *)slide, " (%ld bytes security)",
+                  ntsd_ucSize));
+        }
+    }
+
+    free(security_data);
+    return error;
+}
+
+
+
+
+/********************************/   /* scan extra fields for something */
+/*  Function EvalExtraFields()  */   /*  we happen to know */
+/********************************/
+
+static int EvalExtraFields(__G__ path, ef_ptr, ef_len)
+    __GDEF
+    char *path;
+    uch *ef_ptr;
+    unsigned ef_len;
+{
+    int rc = PK_OK;
+
+    if (!uO.X_flag)
+        return PK_OK;  /* user said don't process ACLs; for now, no other
+                          extra block types are handled here */
+
+    while (ef_len >= EB_HEADSIZE)
+    {
+        unsigned eb_id = makeword(EB_ID + ef_ptr);
+        unsigned eb_len = makeword(EB_LEN + ef_ptr);
+
+        if (eb_len > (ef_len - EB_HEADSIZE)) {
+            /* discovered some extra field inconsistency! */
+            Trace((stderr,
+              "EvalExtraFields: block length %u > rest ef_size %u\n", eb_len,
+              ef_len - EB_HEADSIZE));
+            break;
+        }
+
+        switch (eb_id)
+        {
+            /* process security descriptor extra data if:
+                 Caller is WinNT AND
+                 Target local/remote drive supports acls AND
+                 Target file is not a directory (else we defer processing
+                   until later)
+             */
+            case EF_NTSD:
+                if (IsWinNT()) {
+                    VOLUMECAPS VolumeCaps;
+
+                    /* provide useful input */
+                    VolumeCaps.dwFileAttributes = G.pInfo->file_attr;
+                    VolumeCaps.bUsePrivileges = (uO.X_flag > 1);
+
+                    /* check target volume capabilities - just fall through
+                     * and try if fail */
+                    if (GetVolumeCaps(G.rootpath, path, &VolumeCaps) &&
+                        !(VolumeCaps.dwFileSystemFlags & FS_PERSISTENT_ACLS))
+                    {
+                        rc = PK_OK;
+                        break;
+                    }
+                    rc = SetSD(__G__ path, &VolumeCaps, ef_ptr, eb_len);
+                } else
+                    rc = PK_OK;
+                break;
+
+#if 0
+            /* perhaps later we can add support for unzipping OS/2 EAs to NT */
+            case EF_OS2:
+                rc = SetEAs(__G__ path, ef_ptr);
+                break;
+
+            case EF_PKUNIX:
+            case EF_IZUNIX:
+            case EF_IZUNIX2:
+            case EF_TIME:
+                break;          /* handled elsewhere */
+#else /* ! 0 */
+#ifdef DEBUG
+            case EF_AV:
+            case EF_OS2:
+            case EF_PKVMS:
+            case EF_PKW32:
+            case EF_PKUNIX:
+            case EF_IZVMS:
+            case EF_IZUNIX:
+            case EF_IZUNIX2:
+            case EF_TIME:
+            case EF_MAC3:
+            case EF_JLMAC:
+            case EF_ZIPIT:
+            case EF_VMCMS:
+            case EF_MVS:
+            case EF_ACL:
+            case EF_BEOS:
+            case EF_QDOS:
+            case EF_AOSVS:
+            case EF_SPARK:
+            case EF_MD5:
+            case EF_ASIUNIX:
+                break;          /* shut up for other known e.f. blocks  */
+#endif /* DEBUG */
+#endif /* ? 0 */
+
+            default:
+                Trace((stderr,
+                  "EvalExtraFields: unknown extra field block, ID=%u\n",
+                  eb_id));
+                break;
+        }
+
+        ef_ptr += (eb_len + EB_HEADSIZE);
+        ef_len -= (eb_len + EB_HEADSIZE);
+
+        if (rc != PK_OK)
+            break;
+    }
+
+    return rc;
+}
+
+
+
+
+#ifndef SFX
+
+/**************************/
+/*  Function test_NTSD()  */   /*  returns PK_WARN when NTSD data is invalid */
+/**************************/
+
+#ifdef __BORLANDC__
+/* Turn off warning about not using all parameters for this function only */
+#pragma argsused
+#endif
+int test_NTSD(__G__ eb, eb_size, eb_ucptr, eb_ucsize)
+    __GDEF
+    uch *eb;
+    unsigned eb_size;
+    uch *eb_ucptr;
+    ulg eb_ucsize;
+{
+    int r = PK_OK;
+
+    if (!ValidateSecurity(eb_ucptr))
+        r = PK_WARN;
+    return r;
+
+} /* end function test_NTSD() */
+
+#endif /* !SFX */
+#endif /* NTSD_EAS */
+
+
+
+
+/**********************/
+/* Function IsWinNT() */
+/**********************/
+
+int IsWinNT(void)       /* returns TRUE if real NT, FALSE if Win95 or Win32s */
+{
+    static DWORD g_PlatformId = 0xFFFFFFFF; /* saved platform indicator */
+
+    if (g_PlatformId == 0xFFFFFFFF) {
+        /* note: GetVersionEx() doesn't exist on WinNT 3.1 */
+        if (GetVersion() < 0x80000000)
+            g_PlatformId = TRUE;
+        else
+            g_PlatformId = FALSE;
+    }
+    return (int)g_PlatformId;
+}
+
+
+/* DEBUG_TIME insertion: */
+#ifdef DEBUG_TIME
+static int show_NTFileTime(FILE *hdo, char *TTmsg, int isloc, FILETIME *pft);
+
+static int show_NTFileTime(FILE *hdo, char *TTmsg, int isloc, FILETIME *pft)
+{
+    SYSTEMTIME w32tm;
+    int rval;
+
+    rval = FileTimeToSystemTime(pft, &w32tm);
+    if (!rval) {
+        fprintf(hdo, "%s\n %08lX,%08lX (%s) -> Conversion failed !!!\n",
+                TTmsg, (ulg)(pft->dwHighDateTime), (ulg)(pft->dwLowDateTime),
+                (isloc ? "local" : "UTC"));
+    } else {
+        fprintf(hdo, "%s\n %08lx,%08lx -> %04u-%02u-%02u, %02u:%02u:%02u %s\n",
+                TTmsg, (ulg)(pft->dwHighDateTime), (ulg)(pft->dwLowDateTime),
+                w32tm.wYear, w32tm.wMonth, w32tm.wDay, w32tm.wHour,
+                w32tm.wMinute, w32tm.wSecond, (isloc ? "local" : "UTC"));
+    }
+    return rval;
+}
+#define FTTrace(x)   show_NTFileTime x
+#else
+#define FTTrace(x)
+#endif /* DEBUG_TIME */
+/* end of TIME_DEBUG insertion */
+
+#if (defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND) || \
+     defined(TIMESTAMP))
+
+#if ((defined(__GNUC__) || defined(ULONG_LONG_MAX)) && !defined(HAVE_INT64))
+   typedef long long            LLONG64;
+   typedef unsigned long long   ULLNG64;
+#  define HAVE_INT64
+#endif
+#if (defined(__WATCOMC__) && (__WATCOMC__ >= 1100) && !defined(HAVE_INT64))
+   typedef __int64              LLONG64;
+   typedef unsigned __int64     ULLNG64;
+#  define HAVE_INT64
+#endif
+#if (defined(_MSC_VER) && (_MSC_VER >= 1100) && !defined(HAVE_INT64))
+   typedef __int64              LLONG64;
+   typedef unsigned __int64     ULLNG64;
+#  define HAVE_INT64
+#endif
+
+/*****************************/
+/* Function utime2FileTime() */     /* convert Unix time_t format into the */
+/*****************************/     /* form used by SetFileTime() in NT/95 */
+
+#define UNIX_TIME_ZERO_HI  0x019DB1DEUL
+#define UNIX_TIME_ZERO_LO  0xD53E8000UL
+#define NT_QUANTA_PER_UNIX 10000000L
+
+static void utime2FileTime(time_t ut, FILETIME *pft)
+{
+#ifdef HAVE_INT64
+    ULLNG64 NTtime;
+
+    /* NT_QUANTA_PER_UNIX is small enough so that "ut * NT_QUANTA_PER_UNIX"
+     * cannot overflow in 64-bit signed calculation, regardless wether "ut"
+     * is signed or unsigned.  */
+    NTtime = ((LLONG64)ut * NT_QUANTA_PER_UNIX) +
+             ((ULLNG64)UNIX_TIME_ZERO_LO + ((ULLNG64)UNIX_TIME_ZERO_HI << 32));
+    pft->dwLowDateTime = (DWORD)NTtime;
+    pft->dwHighDateTime = (DWORD)(NTtime >> 32);
+
+#else /* !HAVE_INT64 (64-bit integer arithmetics may not be supported) */
+    unsigned int b1, b2, carry = 0;
+    unsigned long r0, r1, r2, r3;
+    long r4;            /* signed, to catch environments with signed time_t */
+
+    b1 = ut & 0xFFFF;
+    b2 = (ut >> 16) & 0xFFFF;       /* if ut is over 32 bits, too bad */
+    r1 = b1 * (NT_QUANTA_PER_UNIX & 0xFFFF);
+    r2 = b1 * (NT_QUANTA_PER_UNIX >> 16);
+    r3 = b2 * (NT_QUANTA_PER_UNIX & 0xFFFF);
+    r4 = b2 * (NT_QUANTA_PER_UNIX >> 16);
+    r0 = (r1 + (r2 << 16)) & 0xFFFFFFFFL;
+    if (r0 < r1)
+        carry++;
+    r1 = r0;
+    r0 = (r0 + (r3 << 16)) & 0xFFFFFFFFL;
+    if (r0 < r1)
+        carry++;
+    pft->dwLowDateTime = r0 + UNIX_TIME_ZERO_LO;
+    if (pft->dwLowDateTime < r0)
+        carry++;
+    pft->dwHighDateTime = r4 + (r2 >> 16) + (r3 >> 16)
+                            + UNIX_TIME_ZERO_HI + carry;
+#endif /* ?HAVE_INT64 */
+
+} /* end function utime2FileTime() */
+
+
+
+/******************************/
+/* Function FStampIsLocTime() */
+/******************************/
+
+static int FStampIsLocTime(__GPRO__ const char *path)
+{
+    return (NTQueryVolInfo(__G__ path) ? G.lastVolLocTim : FALSE);
+}
+
+#endif /* USE_EF_UT_TIME || NT_TZBUG_WORKAROUND || TIMESTAMP */
+
+
+
+#ifndef NT_TZBUG_WORKAROUND
+#  define UTIME_BOUNDCHECK_1(utimval) \
+     if (fs_uses_loctime) { \
+         utime_dosmin = dos_to_unix_time(DOSTIME_MINIMUM); \
+         if ((ulg)utimval < (ulg)utime_dosmin) \
+             utimval = utime_dosmin; \
+     }
+#  define UTIME_BOUNDCHECK_N(utimval) \
+     if (fs_uses_loctime && ((ulg)utimval < (ulg)utime_dosmin)) \
+         utimval = utime_dosmin;
+#  define NT_TZBUG_PRECOMPENSATE(ut, pft)
+
+#else /* NT_TZBUG_WORKAROUND */
+#  define UNIX_TIME_UMAX_HI  0x0236485EUL
+#  define UNIX_TIME_UMAX_LO  0xD4A5E980UL
+#  define UNIX_TIME_SMIN_HI  0x0151669EUL
+#  define UNIX_TIME_SMIN_LO  0xD53E8000UL
+#  define UNIX_TIME_SMAX_HI  0x01E9FD1EUL
+#  define UNIX_TIME_SMAX_LO  0xD4A5E980UL
+#  define UTIME_1980_JAN_01_00_00   315532800L
+#  define UTIME_BOUNDCHECK_1(utimval)
+#  define UTIME_BOUNDCHECK_N(utimval)
+#  define NT_TZBUG_PRECOMPENSATE(ut, pft) \
+     if (fs_uses_loctime) NTtzbugWorkaround(ut, pft);
+
+   /* nonzero if `y' is a leap year, else zero */
+#  define leap(y) (((y)%4 == 0 && (y)%100 != 0) || (y)%400 == 0)
+   /* number of leap years from 1970 to `y' (not including `y' itself) */
+#  define nleap(y) (((y)-1969)/4 - ((y)-1901)/100 + ((y)-1601)/400)
+
+extern ZCONST ush ydays[];              /* defined in fileio.c */
+
+/*****************************/
+/* Function FileTime2utime() */
+/*****************************/
+
+static int FileTime2utime(const FILETIME *pft, time_t *ut)
+{
+#ifdef HAVE_INT64
+    ULLNG64 NTtime;
+
+    NTtime = ((ULLNG64)pft->dwLowDateTime +
+              ((ULLNG64)pft->dwHighDateTime << 32));
+
+    /* underflow and overflow handling */
+#ifdef CHECK_UTIME_SIGNED_UNSIGNED
+    if ((time_t)0x80000000L < (time_t)0L)
+    {
+        if (NTtime < ((ULLNG64)UNIX_TIME_SMIN_LO +
+                      ((ULLNG64)UNIX_TIME_SMIN_HI << 32))) {
+            *ut = (time_t)LONG_MIN;
+            return FALSE;
+        }
+        if (NTtime > ((ULLNG64)UNIX_TIME_SMAX_LO +
+                      ((ULLNG64)UNIX_TIME_SMAX_HI << 32))) {
+            *ut = (time_t)LONG_MAX;
+            return FALSE;
+        }
+    }
+    else
+#endif /* CHECK_UTIME_SIGNED_UNSIGNED */
+    {
+        if (NTtime < ((ULLNG64)UNIX_TIME_ZERO_LO +
+                      ((ULLNG64)UNIX_TIME_ZERO_HI << 32))) {
+            *ut = (time_t)0;
+            return FALSE;
+        }
+        if (NTtime > ((ULLNG64)UNIX_TIME_UMAX_LO +
+                      ((ULLNG64)UNIX_TIME_UMAX_HI << 32))) {
+            *ut = (time_t)ULONG_MAX;
+            return FALSE;
+        }
+    }
+
+    NTtime -= ((ULLNG64)UNIX_TIME_ZERO_LO +
+               ((ULLNG64)UNIX_TIME_ZERO_HI << 32));
+    *ut = (time_t)(NTtime / (unsigned long)NT_QUANTA_PER_UNIX);
+    return TRUE;
+#else /* !HAVE_INT64 (64-bit integer arithmetics may not be supported) */
+    time_t days;
+    SYSTEMTIME w32tm;
+
+    /* underflow and overflow handling */
+#ifdef CHECK_UTIME_SIGNED_UNSIGNED
+    if ((time_t)0x80000000L < (time_t)0L)
+    {
+        if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) &&
+             (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) {
+            *ut = (time_t)LONG_MIN;
+            return FALSE;
+        if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) &&
+             (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) {
+            *ut = (time_t)LONG_MAX;
+            return FALSE;
+        }
+    }
+    else
+#endif /* CHECK_UTIME_SIGNED_UNSIGNED */
+    {
+        if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) &&
+             (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) {
+            *ut = (time_t)0;
+            return FALSE;
+        }
+        if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) &&
+             (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) {
+            *ut = (time_t)ULONG_MAX;
+            return FALSE;
+        }
+    }
+
+    FileTimeToSystemTime(pft, &w32tm);
+
+    /* set `days' to the number of days into the year */
+    days = w32tm.wDay - 1 + ydays[w32tm.wMonth-1] +
+           (w32tm.wMonth > 2 && leap (w32tm.wYear));
+
+    /* now set `days' to the number of days since 1 Jan 1970 */
+    days += 365 * (time_t)(w32tm.wYear - 1970) +
+            (time_t)(nleap(w32tm.wYear));
+
+    *ut = (time_t)(86400L * days + 3600L * (time_t)w32tm.wHour +
+                   (time_t)(60 * w32tm.wMinute + w32tm.wSecond));
+    return TRUE;
+#endif /* ?HAVE_INT64 */
+} /* end function FileTime2utime() */
+
+
+
+#ifdef W32_STAT_BANDAID
+/*********************************/
+/* Function VFatFileTime2utime() */
+/*********************************/
+
+static int VFatFileTime2utime(const FILETIME *pft, time_t *ut)
+{
+    FILETIME lft;
+#ifndef HAVE_MKTIME
+    WORD wDOSDate, wDOSTime;
+#else
+    SYSTEMTIME w32tm;
+    struct tm ltm;
+#endif
+
+    FileTimeToLocalFileTime(pft, &lft);
+    FTTrace((stdout, "VFatFT2utime, feed for mktime()", 1, &lft));
+#ifndef HAVE_MKTIME
+    /* This version of the FILETIME-to-UNIXTIME conversion function
+     * uses DOS-DATE-TIME format as intermediate stage. For modification
+     * and access times, this is no problem. But, the extra fine resolution
+     * of the VFAT-stored creation time gets lost.
+     */
+    FileTimeToDosDateTime(&lft, &wDOSDate, &wDOSTime);
+    TTrace((stdout,"DosDateTime is %04u-%02u-%02u %02u:%02u:%02u\n",
+      (unsigned)((wDOSDate>>9)&0x7f)+1980,(unsigned)((wDOSDate>>5)&0x0f),
+      (unsigned)(wDOSDate&0x1f),(unsigned)((wDOSTime>>11)&0x1f),
+      (unsigned)((wDOSTime>>5)&0x3f),(unsigned)((wDOSTime<<1)&0x3e)));
+    *ut = dos_to_unix_time(((ulg)wDOSDate << 16) | (ulg)wDOSTime);
+
+    /* a cheap error check: dos_to_unix_time() only returns an odd time
+     * when clipping at maximum time_t value. DOS_DATE_TIME values have
+     * a resolution of 2 seconds and are therefore even numbers.
+     */
+    return (((*ut)&1) == (time_t)0);
+#else /* HAVE_MKTIME */
+    FileTimeToSystemTime(&lft, &w32tm);
+    /* underflow and overflow handling */
+    /* TODO: The range checks are not accurate, the actual limits may
+     *       be off by one daylight-saving-time shift (typically 1 hour),
+     *       depending on the current state of "is_dst".
+     */
+#ifdef CHECK_UTIME_SIGNED_UNSIGNED
+    if ((time_t)0x80000000L < (time_t)0L)
+    {
+        if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) &&
+             (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) {
+            *ut = (time_t)LONG_MIN;
+            return FALSE;
+        if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) &&
+             (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) {
+            *ut = (time_t)LONG_MAX;
+            return FALSE;
+        }
+    }
+    else
+#endif /* CHECK_UTIME_SIGNED_UNSIGNED */
+    {
+        if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) &&
+             (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) {
+            *ut = (time_t)0;
+            return FALSE;
+        }
+        if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) &&
+             (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) {
+            *ut = (time_t)ULONG_MAX;
+            return FALSE;
+        }
+    }
+    ltm.tm_year = w32tm.wYear - 1900;
+    ltm.tm_mon = w32tm.wMonth - 1;
+    ltm.tm_mday = w32tm.wDay;
+    ltm.tm_hour = w32tm.wHour;
+    ltm.tm_min = w32tm.wMinute;
+    ltm.tm_sec = w32tm.wSecond;
+    ltm.tm_isdst = -1;  /* let mktime determine if DST is in effect */
+    *ut = mktime(&ltm);
+
+    /* a cheap error check: mktime returns "(time_t)-1L" on conversion errors.
+     * Normally, we would have to apply a consistency check because "-1"
+     * could also be a valid time. But, it is quite unlikely to read back odd
+     * time numbers from file systems that store time stamps in DOS format.
+     * (The only known exception is creation time on VFAT partitions.)
+     */
+    return (*ut != (time_t)-1L);
+#endif /* ?HAVE_MKTIME */
+
+} /* end function VFatFileTime2utime() */
+#endif /* W32_STAT_BANDAID */
+
+
+
+/********************************/
+/* Function UTCtime2Localtime() */      /* borrowed from Zip's mkgmtime() */
+/********************************/
+
+static time_t UTCtime2Localtime(time_t utctime)
+{
+    time_t utc = utctime;
+    struct tm *tm;
+    unsigned years, months, days, hours, minutes, seconds;
+
+
+#ifdef __BORLANDC__   /* Borland C++ 5.x crashes when trying to reference tm */
+    if (utc < UTIME_1980_JAN_01_00_00)
+        utc = UTIME_1980_JAN_01_00_00;
+#endif
+    tm = localtime(&utc);
+    if (tm == (struct tm *)NULL)
+        /* localtime() did not accept given utc time value; as an emergency
+           exit, the unconverted utctime value is returned */
+        return utctime;
+
+    years = tm->tm_year + 1900; /* year - 1900 -> year */
+    months = tm->tm_mon;        /* 0..11 */
+    days = tm->tm_mday - 1;     /* 1..31 -> 0..30 */
+    hours = tm->tm_hour;        /* 0..23 */
+    minutes = tm->tm_min;       /* 0..59 */
+    seconds = tm->tm_sec;       /* 0..61 in ANSI C */
+
+    /* set `days' to the number of days into the year */
+    days += ydays[months] + (months > 1 && leap(years));
+
+    /* now set `days' to the number of days since 1 Jan 1970 */
+    days += 365 * (years - 1970) + nleap(years);
+
+    return (time_t)(86400L * (ulg)days + 3600L * (ulg)hours +
+                    (ulg)(60 * minutes + seconds));
+
+} /* end function UTCtime2Localtime() */
+
+
+
+/********************************/
+/* Function NTtzbugWorkaround() */
+/********************************/
+
+static void NTtzbugWorkaround(time_t ut, FILETIME *pft)
+{
+    FILETIME C_RTL_locft, NTAPI_locft;
+    time_t ux_loctime = UTCtime2Localtime(ut);
+
+    /* This routine is only used when the target file system stores time-
+     * stamps as local time in MSDOS format.  Thus we make sure that the
+     * resulting timestamp is within the range of MSDOS date-time values. */
+    if (ux_loctime < UTIME_1980_JAN_01_00_00)
+        ux_loctime = UTIME_1980_JAN_01_00_00;
+
+    utime2FileTime(ux_loctime, &C_RTL_locft);
+    if (!FileTimeToLocalFileTime(pft, &NTAPI_locft))
+        return;
+    else {
+        long time_shift_l, time_shift_h;
+        int carry = 0;
+
+        time_shift_l = C_RTL_locft.dwLowDateTime - NTAPI_locft.dwLowDateTime;
+        if (C_RTL_locft.dwLowDateTime < NTAPI_locft.dwLowDateTime)
+            carry--;
+        time_shift_h = C_RTL_locft.dwHighDateTime - NTAPI_locft.dwHighDateTime;
+        pft->dwLowDateTime += time_shift_l;
+        if (pft->dwLowDateTime < (ulg)time_shift_l)
+            carry++;
+        pft->dwHighDateTime += time_shift_h + carry;
+        TTrace((stdout, "FileTime shift: %08lx:%08lx\n",
+                time_shift_h+carry,time_shift_l));
+    }
+} /* end function NTtzbugWorkaround() */
+
+#endif /* ?NT_TZBUG_WORKAROUND */
+
+
+
+/****************************/      /* Get the file time in a format that */
+/* Function getNTfiletime() */      /*  can be used by SetFileTime() in NT */
+/****************************/
+
+static int getNTfiletime(__G__ pModFT, pAccFT, pCreFT)
+    __GDEF
+    FILETIME *pModFT;
+    FILETIME *pAccFT;
+    FILETIME *pCreFT;
+{
+#ifdef NT_TZBUG_WORKAROUND
+    time_t ux_modtime;
+#else /* !NT_TZBUG_WORKAROUND */
+    FILETIME locft;    /* 64-bit value made up of two 32-bit [low & high] */
+    WORD wDOSDate;     /* for converting from DOS date to Windows NT */
+    WORD wDOSTime;
+#endif /* ?NT_TZBUG_WORKAROUND */
+#ifdef USE_EF_UT_TIME
+    unsigned eb_izux_flg;
+    iztimes z_utime;   /* struct for Unix-style actime & modtime, + creatime */
+#endif
+#if (defined(USE_EF_UT_TIME) && !defined(NT_TZBUG_WORKAROUND))
+    time_t utime_dosmin;
+# endif
+#if (defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND))
+    int fs_uses_loctime = FStampIsLocTime(__G__ G.filename);
+#endif
+
+    /* Copy and/or convert time and date variables, if necessary;
+     * return a flag indicating which time stamps are available. */
+#ifdef USE_EF_UT_TIME
+    if (G.extra_field &&
+#ifdef IZ_CHECK_TZ
+        G.tz_is_valid &&
+#endif
+        ((eb_izux_flg = ef_scan_for_izux(G.extra_field,
+          G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime,
+          &z_utime, NULL)) & EB_UT_FL_MTIME))
+    {
+        TTrace((stderr, "getNTfiletime:  Unix e.f. modif. time = %lu\n",
+          z_utime.mtime));
+        UTIME_BOUNDCHECK_1(z_utime.mtime)
+        utime2FileTime(z_utime.mtime, pModFT);
+        NT_TZBUG_PRECOMPENSATE(z_utime.mtime, pModFT)
+        if (eb_izux_flg & EB_UT_FL_ATIME) {
+            UTIME_BOUNDCHECK_N(z_utime.atime)
+            utime2FileTime(z_utime.atime, pAccFT);
+            NT_TZBUG_PRECOMPENSATE(z_utime.atime, pAccFT)
+        }
+        if (eb_izux_flg & EB_UT_FL_CTIME) {
+            UTIME_BOUNDCHECK_N(z_utime.ctime)
+            utime2FileTime(z_utime.ctime, pCreFT);
+            NT_TZBUG_PRECOMPENSATE(z_utime.ctime, pCreFT)
+        }
+        return (int)eb_izux_flg;
+    }
+#endif /* USE_EF_UT_TIME */
+#ifdef NT_TZBUG_WORKAROUND
+    ux_modtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
+    utime2FileTime(ux_modtime, pModFT);
+    NT_TZBUG_PRECOMPENSATE(ux_modtime, pModFT)
+#else /* !NT_TZBUG_WORKAROUND */
+
+    wDOSTime = (WORD)(G.lrec.last_mod_dos_datetime);
+    wDOSDate = (WORD)(G.lrec.last_mod_dos_datetime >> 16);
+
+    /* The DosDateTimeToFileTime() function converts a DOS date/time
+     * into a 64-bit Windows NT file time */
+    if (!DosDateTimeToFileTime(wDOSDate, wDOSTime, &locft))
+    {
+        Info(slide, 0, ((char *)slide, "DosDateTime failed: %d\n",
+          (int)GetLastError()));
+        return 0;
+    }
+    if (!LocalFileTimeToFileTime(&locft, pModFT))
+    {
+        Info(slide, 0, ((char *)slide, "LocalFileTime failed: %d\n",
+          (int)GetLastError()));
+        *pModFT = locft;
+    }
+#endif /* ?NT_TZBUG_WORKAROUND */
+    *pAccFT = *pModFT;
+    return (EB_UT_FL_MTIME | EB_UT_FL_ATIME);
+
+} /* end function getNTfiletime() */
+
+
+
+
+/****************************/
+/* Function close_outfile() */
+/****************************/
+
+void close_outfile(__G)
+    __GDEF
+{
+    FILETIME Modft;    /* File time type defined in NT, `last modified' time */
+    FILETIME Accft;    /* NT file time type, `last access' time */
+    FILETIME Creft;    /* NT file time type, `file creation' time */
+    HANDLE hFile;      /* File handle defined in NT    */
+    int gotTime;
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+    char *ansi_name = (char *)alloca(strlen(G.filename) + 1);
+
+    INTERN_TO_ISO(G.filename, ansi_name);
+#   define Ansi_Fname  ansi_name
+#else
+#   define Ansi_Fname  G.filename
+#endif
+
+    /* Close the file and then re-open it using the Win32
+     * CreateFile call, so that the file can be created
+     * with GENERIC_WRITE access, otherwise the SetFileTime
+     * call will fail. */
+    fclose(G.outfile);
+
+    /* don't set the time stamp and attributes on standard output */
+    if (uO.cflag)
+        return;
+
+    gotTime = getNTfiletime(__G__ &Modft, &Accft, &Creft);
+
+    /* open a handle to the file before processing extra fields;
+       we do this in case new security on file prevents us from updating
+       time stamps */
+    hFile = CreateFile(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
+         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+
+    /* sfield@microsoft.com: set attributes before time in case we decide to
+       support other filetime members later.  This also allows us to apply
+       attributes before the security is changed, which may prevent this
+       from succeeding otherwise.  Also, since most files don't have
+       any interesting attributes, only change them if something other than
+       FILE_ATTRIBUTE_ARCHIVE appears in the attributes.  This works well
+       as an optimization because FILE_ATTRIBUTE_ARCHIVE gets applied to the
+       file anyway, when it's created new. */
+    if((G.pInfo->file_attr & 0x7F) & ~FILE_ATTRIBUTE_ARCHIVE) {
+        if (!SetFileAttributes(Ansi_Fname, G.pInfo->file_attr & 0x7F))
+            Info(slide, 1, ((char *)slide,
+              "\nwarning (%d): could not set file attributes\n",
+              (int)GetLastError()));
+    }
+
+#ifdef NTSD_EAS
+    /* set extra fields, both stored-in-zipfile and .LONGNAME flavors */
+    if (G.extra_field) {    /* zipfile extra field may have extended attribs */
+        int err = EvalExtraFields(__G__ G.filename, G.extra_field,
+                                  G.lrec.extra_field_length);
+
+        if (err == IZ_EF_TRUNC) {
+            if (uO.qflag)
+                Info(slide, 1, ((char *)slide, "%-22s ",
+                  FnFilter1(G.filename)));
+            Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD),
+              makeword(G.extra_field+2)-10, uO.qflag? "\n":""));
+        }
+    }
+#endif /* NTSD_EAS */
+
+    if ( hFile == INVALID_HANDLE_VALUE )
+        Info(slide, 1, ((char *)slide,
+          "\nCreateFile error %d when trying set file time\n",
+          (int)GetLastError()));
+    else {
+        if (gotTime) {
+            FILETIME *pModft = (gotTime & EB_UT_FL_MTIME) ? &Modft : NULL;
+            FILETIME *pAccft = (gotTime & EB_UT_FL_ATIME) ? &Accft : NULL;
+            FILETIME *pCreft = (gotTime & EB_UT_FL_CTIME) ? &Creft : NULL;
+
+            if (!SetFileTime(hFile, pCreft, pAccft, pModft))
+                Info(slide, 0, ((char *)slide, "\nSetFileTime failed: %d\n",
+                  (int)GetLastError()));
+        }
+        CloseHandle(hFile);
+    }
+
+    return;
+
+#undef Ansi_Fname
+
+} /* end function close_outfile() */
+
+
+
+
+#ifdef TIMESTAMP
+
+/*************************/
+/* Function stamp_file() */
+/*************************/
+
+int stamp_file(__GPRO__ ZCONST char *fname, time_t modtime)
+{
+    FILETIME Modft;    /* File time type defined in NT, `last modified' time */
+    HANDLE hFile;      /* File handle defined in NT    */
+    int errstat = 0;   /* return status: 0 == "OK", -1 == "Failure" */
+#ifndef NT_TZBUG_WORKAROUND
+    time_t utime_dosmin;        /* internal variable for UTIME_BOUNDCHECK_1 */
+#endif
+    int fs_uses_loctime = FStampIsLocTime(__G__ fname);
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+    char *ansi_name = (char *)alloca(strlen(fname) + 1);
+
+    INTERN_TO_ISO(fname, ansi_name);
+#   define Ansi_Fname  ansi_name
+#else
+#   define Ansi_Fname  fname
+#endif
+
+    /* open a handle to the file to prepare setting the mod-time stamp */
+    hFile = CreateFile(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
+         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    if ( hFile == INVALID_HANDLE_VALUE ) {
+        errstat = -1;
+    } else {
+        /* convert time_t modtime into WIN32 native 64bit format */
+        UTIME_BOUNDCHECK_1(modtime)
+        utime2FileTime(modtime, &Modft);
+        NT_TZBUG_PRECOMPENSATE(modtime, &Modft)
+        /* set Access and Modification times of the file to modtime */
+        if (!SetFileTime(hFile, NULL, &Modft, &Modft)) {
+            errstat = -1;
+        }
+        CloseHandle(hFile);
+    }
+
+    return errstat;
+
+#undef Ansi_Fname
+} /* end function stamp_file() */
+
+#endif /* TIMESTAMP */
+
+
+
+
+/***********************/
+/* Function isfloppy() */   /* more precisely, is it removable? */
+/***********************/
+
+static int isfloppy(int nDrive)   /* 1 == A:, 2 == B:, etc. */
+{
+    char rootPathName[4];
+
+    rootPathName[0] = (char)('A' + nDrive - 1);   /* build the root path */
+    rootPathName[1] = ':';                        /*  name, e.g. "A:/" */
+    rootPathName[2] = '/';
+    rootPathName[3] = '\0';
+
+    return (GetDriveType(rootPathName) == DRIVE_REMOVABLE);
+
+} /* end function isfloppy() */
+
+
+
+
+/*****************************/
+/* Function NTQueryVolInfo() */
+/*****************************/
+
+/*
+ * Note:  8.3 limits on filenames apply only to old-style FAT filesystems.
+ *        More recent versions of Windows (Windows NT 3.5 / Windows 4.0)
+ *        can support long filenames (LFN) on FAT filesystems.  Check the
+ *        filesystem maximum component length field to detect LFN support.
+ */
+
+static int NTQueryVolInfo(__GPRO__ const char *name)
+{
+ /* static char lastRootPath[4] = ""; */
+ /* static int lastVolOldFAT; */
+ /* static int lastVolLocTim; */
+    char     *tmp0;
+    char      tmp1[MAX_PATH], tmp2[MAX_PATH];
+    unsigned  volSerNo, maxCompLen, fileSysFlags;
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+    char *ansi_name = (char *)alloca(strlen(name) + 1);
+
+    INTERN_TO_ISO(name, ansi_name);
+    name = ansi_name;
+#endif
+
+    if ((!strncmp(name, "//", 2) || !strncmp(name,"\\\\", 2)) &&
+        (name[2] != '\0' && name[2] != '/' && name[2] != '\\')) {
+        /* GetFullPathname() and GetVolumeInformation() do not work
+         * on UNC names. For now, we return "error".
+         * **FIXME**: check if UNC name is mapped to a drive letter
+         *            and use mapped drive for volume info query.
+         */
+        return FALSE;
+    }
+    if (isalpha((uch)name[0]) && (name[1] == ':'))
+        tmp0 = (char *)name;
+    else
+    {
+        if (!GetFullPathName(name, MAX_PATH, tmp1, &tmp0))
+            return FALSE;
+        tmp0 = &tmp1[0];
+    }
+    if (strncmp(G.lastRootPath, tmp0, 2) != 0) {
+        /* For speed, we skip repeated queries for the same device */
+        strncpy(G.lastRootPath, tmp0, 2);   /* Build the root path name, */
+        G.lastRootPath[2] = '/';            /* e.g. "A:/"                */
+        G.lastRootPath[3] = '\0';
+
+        if (!GetVolumeInformation((LPCTSTR)G.lastRootPath,
+              (LPTSTR)tmp1, (DWORD)MAX_PATH,
+              (LPDWORD)&volSerNo, (LPDWORD)&maxCompLen,
+              (LPDWORD)&fileSysFlags, (LPTSTR)tmp2, (DWORD)MAX_PATH)) {
+            G.lastRootPath[0] = '\0';
+            return FALSE;
+        }
+
+        /*  LFNs are available if the component length is > 12 */
+        G.lastVolOldFAT = (maxCompLen <= 12);
+/*      G.lastVolOldFAT = !strncmp(strupr(tmp2), "FAT", 3);   old version */
+
+        /* Volumes in (V)FAT and (OS/2) HPFS format store file timestamps in
+         * local time!
+         */
+        G.lastVolLocTim = !strncmp(strupr(tmp2), "VFAT", 4) ||
+                          !strncmp(tmp2, "HPFS", 4) ||
+                          !strncmp(tmp2, "FAT", 3);
+    }
+
+    return TRUE;
+
+} /* end function NTQueryVolInfo() */
+
+
+
+
+/*****************************/
+/* Function IsVolumeOldFAT() */
+/*****************************/
+
+static int IsVolumeOldFAT(__GPRO__ const char *name)
+{
+    return (NTQueryVolInfo(__G__ name) ? G.lastVolOldFAT : FALSE);
+}
+
+
+
+
+#ifndef SFX
+
+/************************/
+/*  Function do_wild()  */   /* identical to OS/2 version */
+/************************/
+
+char *do_wild(__G__ wildspec)
+    __GDEF
+    char *wildspec;         /* only used first time on a given dir */
+{
+ /* static zDIR *wild_dir = NULL;                               */
+ /* static char *dirname, *wildname, matchname[FILNAMSIZ]; */
+ /* static int firstcall=TRUE, have_dirname, dirnamelen;   */
+    char *fnamestart;
+    struct zdirent *file;
+
+    /* Even when we're just returning wildspec, we *always* do so in
+     * matchname[]--calling routine is allowed to append four characters
+     * to the returned string, and wildspec may be a pointer to argv[].
+     */
+    if (!G.notfirstcall) {  /* first call:  must initialize everything */
+        G.notfirstcall = TRUE;
+
+        if (!iswild(wildspec)) {
+            strcpy(G.matchname, wildspec);
+            G.have_dirname = FALSE;
+            G.wild_dir = NULL;
+            return G.matchname;
+        }
+
+        /* break the wildspec into a directory part and a wildcard filename */
+        if ((G.wildname = strrchr(wildspec, '/')) == NULL &&
+            (G.wildname = strrchr(wildspec, ':')) == NULL) {
+            G.dirname = ".";
+            G.dirnamelen = 1;
+            G.have_dirname = FALSE;
+            G.wildname = wildspec;
+        } else {
+            ++G.wildname;     /* point at character after '/' or ':' */
+            G.dirnamelen = G.wildname - wildspec;
+            if ((G.dirname = (char *)malloc(G.dirnamelen+1)) == NULL) {
+                Info(slide, 1, ((char *)slide,
+                  "warning:  cannot allocate wildcard buffers\n"));
+                strcpy(G.matchname, wildspec);
+                return G.matchname; /* but maybe filespec was not a wildcard */
+            }
+            strncpy(G.dirname, wildspec, G.dirnamelen);
+            G.dirname[G.dirnamelen] = '\0';    /* terminate for strcpy below */
+            G.have_dirname = TRUE;
+        }
+        Trace((stderr, "do_wild:  dirname = [%s]\n", G.dirname));
+
+        if ((G.wild_dir = (zvoid *)Opendir(G.dirname)) != NULL) {
+            if (G.have_dirname) {
+                strcpy(G.matchname, G.dirname);
+                fnamestart = G.matchname + G.dirnamelen;
+            } else
+                fnamestart = G.matchname;
+            while ((file = Readdir((zDIR *)G.wild_dir)) != NULL) {
+                Trace((stderr, "do_wild:  Readdir returns %s\n", file->d_name));
+                strcpy(fnamestart, file->d_name);
+                if (strrchr(fnamestart, '.') == (char *)NULL)
+                    strcat(fnamestart, ".");
+                if (match(fnamestart, G.wildname, 1) &&  /* 1 == ignore case */
+                    /* skip "." and ".." directory entries */
+                    strcmp(fnamestart, ".") && strcmp(fnamestart, "..")) {
+                    Trace((stderr, "do_wild:  match() succeeds\n"));
+                    /* remove trailing dot */
+                    fnamestart += strlen(fnamestart) - 1;
+                    if (*fnamestart == '.')
+                        *fnamestart = '\0';
+                    return G.matchname;
+                }
+            }
+            /* if we get to here directory is exhausted, so close it */
+            Closedir((zDIR *)G.wild_dir);
+            G.wild_dir = NULL;
+        }
+        Trace((stderr, "do_wild:  Opendir(%s) returns NULL\n", G.dirname));
+
+        /* return the raw wildspec in case that works (e.g., directory not
+         * searchable, but filespec was not wild and file is readable) */
+        strcpy(G.matchname, wildspec);
+        return G.matchname;
+    }
+
+    /* last time through, might have failed opendir but returned raw wildspec */
+    if (G.wild_dir == NULL) {
+        G.notfirstcall = FALSE;    /* reset for new wildspec */
+        if (G.have_dirname)
+            free(G.dirname);
+        return (char *)NULL;
+    }
+
+    /* If we've gotten this far, we've read and matched at least one entry
+     * successfully (in a previous call), so dirname has been copied into
+     * matchname already.
+     */
+    if (G.have_dirname) {
+        /* strcpy(G.matchname, G.dirname); */
+        fnamestart = G.matchname + G.dirnamelen;
+    } else
+        fnamestart = G.matchname;
+    while ((file = Readdir((zDIR *)G.wild_dir)) != NULL) {
+        Trace((stderr, "do_wild:  readdir returns %s\n", file->d_name));
+        strcpy(fnamestart, file->d_name);
+        if (strrchr(fnamestart, '.') == (char *)NULL)
+            strcat(fnamestart, ".");
+        if (match(fnamestart, G.wildname, 1)) {     /* 1 == ignore case */
+            Trace((stderr, "do_wild:  match() succeeds\n"));
+            /* remove trailing dot */
+            fnamestart += strlen(fnamestart) - 1;
+            if (*fnamestart == '.')
+                *fnamestart = '\0';
+            return G.matchname;
+        }
+    }
+
+    Closedir((zDIR *)G.wild_dir);  /* at least one entry read; nothing left */
+    G.wild_dir = NULL;
+    G.notfirstcall = FALSE;        /* reset for new wildspec */
+    if (G.have_dirname)
+        free(G.dirname);
+    return (char *)NULL;
+
+} /* end function do_wild() */
+
+#endif /* !SFX */
+
+
+
+/**********************/
+/* Function mapattr() */
+/**********************/
+
+/* Identical to MS-DOS, OS/2 versions.  However, NT has a lot of extra
+ * permission stuff, so this function should probably be extended in the
+ * future. */
+
+int mapattr(__G)
+    __GDEF
+{
+    /* set archive bit for file entries (file is not backed up): */
+    G.pInfo->file_attr = ((unsigned)G.crec.external_file_attributes |
+      (G.crec.external_file_attributes & FILE_ATTRIBUTE_DIRECTORY ?
+       0 : FILE_ATTRIBUTE_ARCHIVE)) & 0xff;
+    return 0;
+
+} /* end function mapattr() */
+
+
+
+
+/************************/
+/*  Function mapname()  */
+/************************/
+                             /* return 0 if no error, 1 if caution (filename */
+int mapname(__G__ renamed)   /*  truncated), 2 if warning (skip file because */
+    __GDEF                   /*  dir doesn't exist), 3 if error (skip file), */
+    int renamed;             /*  or 10 if out of memory (skip file) */
+{                            /*  [also IZ_VOL_LABEL, IZ_CREATED_DIR] */
+    char pathcomp[FILNAMSIZ];   /* path-component buffer */
+    char *pp, *cp=NULL;         /* character pointers */
+    char *lastsemi = NULL;      /* pointer to last semi-colon in pathcomp */
+    int error;
+    register unsigned workch;   /* hold the character being tested */
+
+
+/*---------------------------------------------------------------------------
+    Initialize various pointers and counters and stuff.
+  ---------------------------------------------------------------------------*/
+
+    /* can create path as long as not just freshening, or if user told us */
+    G.create_dirs = (!uO.fflag || renamed);
+
+    G.created_dir = FALSE;      /* not yet */
+    G.renamed_fullpath = FALSE;
+    G.fnlen = strlen(G.filename);
+
+    if (renamed) {
+        cp = G.filename - 1;    /* point to beginning of renamed name... */
+        while (*++cp)
+            if (*cp == '\\')    /* convert backslashes to forward */
+                *cp = '/';
+        cp = G.filename;
+        /* use temporary rootpath if user gave full pathname */
+        if (G.filename[0] == '/') {
+            G.renamed_fullpath = TRUE;
+            pathcomp[0] = '/';  /* copy the '/' and terminate */
+            pathcomp[1] = '\0';
+            ++cp;
+        } else if (isalpha((uch)G.filename[0]) && G.filename[1] == ':') {
+            G.renamed_fullpath = TRUE;
+            pp = pathcomp;
+            *pp++ = *cp++;      /* copy the "d:" (+ '/', possibly) */
+            *pp++ = *cp++;
+            if (*cp == '/')
+                *pp++ = *cp++;  /* otherwise add "./"? */
+            *pp = '\0';
+        }
+    }
+
+    /* pathcomp is ignored unless renamed_fullpath is TRUE: */
+    if ((error = checkdir(__G__ pathcomp, INIT)) != 0)    /* init path buffer */
+        return error;           /* ...unless no mem or vol label on hard disk */
+
+    *pathcomp = '\0';           /* initialize translation buffer */
+    pp = pathcomp;              /* point to translation buffer */
+    if (!renamed) {             /* cp already set if renamed */
+        if (uO.jflag)           /* junking directories */
+            cp = (char *)strrchr(G.filename, '/');
+        if (cp == NULL)         /* no '/' or not junking dirs */
+            cp = G.filename;    /* point to internal zipfile-member pathname */
+        else
+            ++cp;               /* point to start of last component of path */
+    }
+
+/*---------------------------------------------------------------------------
+    Begin main loop through characters in filename.
+  ---------------------------------------------------------------------------*/
+
+    while ((workch = (uch)*cp++) != 0) {
+
+        switch (workch) {
+        case '/':             /* can assume -j flag not given */
+            *pp = '\0';
+            if ((error = checkdir(__G__ pathcomp, APPEND_DIR)) > 1)
+                return error;
+            pp = pathcomp;    /* reset conversion buffer for next piece */
+            lastsemi = NULL;  /* leave directory semi-colons alone */
+            break;
+
+        case ':':             /* drive names not stored in zipfile, */
+        case '<':             /*  so no colons allowed */
+        case '>':             /* no redirection symbols allowed either */
+        case '|':             /* no pipe signs allowed */
+        case '"':             /* no double quotes allowed */
+        case '?':             /* no wildcards allowed */
+        case '*':
+            *pp++ = '_';      /* these rules apply equally to FAT and NTFS */
+            break;
+        case ';':             /* start of VMS version? */
+            lastsemi = pp;    /* remove VMS version later... */
+            *pp++ = ';';      /*  but keep semicolon for now */
+            break;
+
+        case ' ':             /* keep spaces unless specifically */
+            /* NT cannot create filenames with spaces on FAT volumes */
+            if (uO.sflag || IsVolumeOldFAT(__G__ G.filename))
+                *pp++ = '_';
+            else
+                *pp++ = ' ';
+            break;
+
+        default:
+            /* allow European characters in filenames: */
+            if (isprint(workch) || workch >= 127)
+                *pp++ = (char)workch;
+        } /* end switch */
+    } /* end while loop */
+
+    *pp = '\0';                   /* done with pathcomp:  terminate it */
+
+    /* if not saving them, remove VMS version numbers (appended "###") */
+    if (!uO.V_flag && lastsemi) {
+        pp = lastsemi + 1;        /* semi-colon was kept:  expect #'s after */
+        while (isdigit((uch)(*pp)))
+            ++pp;
+        if (*pp == '\0')          /* only digits between ';' and end:  nuke */
+            *lastsemi = '\0';
+    }
+
+/*---------------------------------------------------------------------------
+    Report if directory was created (and no file to create:  filename ended
+    in '/'), check name to be sure it exists, and combine path and name be-
+    fore exiting.
+  ---------------------------------------------------------------------------*/
+
+    if (G.filename[G.fnlen-1] == '/') {
+        checkdir(__G__ G.filename, GETPATH);
+        if (G.created_dir) {
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+            char *ansi_name = (char *)alloca(strlen(G.filename) + 1);
+
+            INTERN_TO_ISO(G.filename, ansi_name);
+#           define Ansi_Fname  ansi_name
+#else
+#           define Ansi_Fname  G.filename
+#endif
+            if (QCOND2) {
+                Info(slide, 0, ((char *)slide, "   creating: %-22s\n",
+                  FnFilter1(G.filename)));
+            }
+
+            /* set file attributes:
+               The default for newly created directories is "DIR attribute
+               flags set", so there is no need to change attributes unless
+               one of the DOS style attribute flags is set. The readonly
+               attribute need not be masked, since it does not prevent
+               modifications in the new directory. */
+            if(G.pInfo->file_attr & (0x7F & ~FILE_ATTRIBUTE_DIRECTORY)) {
+                if (!SetFileAttributes(Ansi_Fname, G.pInfo->file_attr & 0x7F))
+                    Info(slide, 1, ((char *)slide,
+                      "\nwarning (%d): could not set file attributes for %s\n",
+                      (int)GetLastError(), G.filename));
+            }
+
+#ifdef NTSD_EAS
+            /* set extra fields, both stored-in-zipfile and .LONGNAME flavors */
+            if (G.extra_field) { /* zipfile e.f. may have extended attribs */
+                int err = EvalExtraFields(__G__ G.filename, G.extra_field,
+                                          G.lrec.extra_field_length);
+
+                if (err == IZ_EF_TRUNC) {
+                    if (uO.qflag)
+                        Info(slide, 1, ((char *)slide, "%-22s ",
+                          FnFilter1(G.filename)));
+                    Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD),
+                      makeword(G.extra_field+2)-10, uO.qflag? "\n":""));
+                }
+            }
+#endif /* NTSD_EAS */
+            return IZ_CREATED_DIR;      /* set dir time (note trailing '/') */
+        }
+        return 2;   /* dir existed already; don't look for data to extract */
+    }
+
+    if (*pathcomp == '\0') {
+        Info(slide, 1, ((char *)slide, "mapname:  conversion of %s failed\n",
+          FnFilter1(G.filename)));
+        return 3;
+    }
+
+    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */
+    checkdir(__G__ G.filename, GETPATH);
+    Trace((stderr, "mapname returns with filename = [%s] (error = %d)\n\n",
+      FnFilter1(G.filename), error));
+
+    if (G.pInfo->vollabel) {    /* set the volume label now */
+        char drive[4];
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+        char *ansi_name = (char *)alloca(strlen(G.filename) + 1);
+        INTERN_TO_ISO(G.filename, ansi_name);
+#       define Ansi_Fname  ansi_name
+#else
+#       define Ansi_Fname  G.filename
+#endif
+
+        /* Build a drive string, e.g. "b:" */
+        drive[0] = (char)('a' + G.nLabelDrive - 1);
+        strcpy(drive + 1, ":\\");
+        if (QCOND2)
+            Info(slide, 0, ((char *)slide, "labelling %s %-22s\n", drive,
+              FnFilter1(G.filename)));
+        if (!SetVolumeLabel(drive, Ansi_Fname)) {
+            Info(slide, 1, ((char *)slide,
+              "mapname:  error setting volume label\n"));
+            return 3;
+        }
+        return 2;   /* success:  skip the "extraction" quietly */
+#undef Ansi_Fname
+    }
+
+    return error;
+
+} /* end function mapname() */
+
+
+
+
+/**********************/
+/* Function map2fat() */        /* Not quite identical to OS/2 version */
+/**********************/
+
+static void map2fat(pathcomp, pEndFAT)
+    char *pathcomp, **pEndFAT;
+{
+    char *ppc = pathcomp;       /* variable pointer to pathcomp */
+    char *pEnd = *pEndFAT;      /* variable pointer to buildpathFAT */
+    char *pBegin = *pEndFAT;    /* constant pointer to start of this comp. */
+    char *last_dot = NULL;      /* last dot not converted to underscore */
+    int dotname = FALSE;        /* flag:  path component begins with dot */
+                                /*  ("." and ".." don't count) */
+    register unsigned workch;   /* hold the character being tested */
+
+
+    /* Only need check those characters which are legal in NTFS but not
+     * in FAT:  to get here, must already have passed through mapname.
+     * Also must truncate path component to ensure 8.3 compliance.
+     */
+    while ((workch = (uch)*ppc++) != 0) {
+        switch (workch) {
+            case '[':
+            case ']':
+            case '+':
+            case ',':
+            case ';':
+            case '=':
+                *pEnd++ = '_';      /* convert brackets to underscores */
+                break;
+
+            case '.':
+                if (pEnd == *pEndFAT) {   /* nothing appended yet... */
+                    if (*ppc == '\0')     /* don't bother appending a */
+                        break;            /*  "./" component to the path */
+                    else if (*ppc == '.' && ppc[1] == '\0') {   /* "../" */
+                        *pEnd++ = '.';    /* add first dot, unchanged... */
+                        ++ppc;            /* skip second dot, since it will */
+                    } else {              /*  be "added" at end of if-block */
+                        *pEnd++ = '_';    /* FAT doesn't allow null filename */
+                        dotname = TRUE;   /*  bodies, so map .exrc -> _.exrc */
+                    }                     /*  (extra '_' now, "dot" below) */
+                } else if (dotname) {     /* found a second dot, but still */
+                    dotname = FALSE;      /*  have extra leading underscore: */
+                    *pEnd = '\0';         /*  remove it by shifting chars */
+                    pEnd = *pEndFAT + 1;  /*  left one space (e.g., .p1.p2: */
+                    while (pEnd[1]) {     /*  __p1 -> _p1_p2 -> _p1.p2 when */
+                        *pEnd = pEnd[1];  /*  finished) [opt.:  since first */
+                        ++pEnd;           /*  two chars are same, can start */
+                    }                     /*  shifting at second position] */
+                }
+                last_dot = pEnd;    /* point at last dot so far... */
+                *pEnd++ = '_';      /* convert dot to underscore for now */
+                break;
+
+            default:
+                *pEnd++ = (char)workch;
+
+        } /* end switch */
+    } /* end while loop */
+
+    *pEnd = '\0';                 /* terminate buildpathFAT */
+
+    /* NOTE:  keep in mind that pEnd points to the end of the path
+     * component, and *pEndFAT still points to the *beginning* of it...
+     * Also note that the algorithm does not try to get too fancy:
+     * if there are no dots already, the name either gets truncated
+     * at 8 characters or the last underscore is converted to a dot
+     * (only if more characters are saved that way).  In no case is
+     * a dot inserted between existing characters.
+     */
+    if (last_dot == NULL) {       /* no dots:  check for underscores... */
+        char *plu = strrchr(pBegin, '_');   /* pointer to last underscore */
+
+        if (plu == NULL) {   /* no dots, no underscores:  truncate at 8 chars */
+            *pEndFAT += 8;        /* (or could insert '.' and keep 11...?) */
+            if (*pEndFAT > pEnd)
+                *pEndFAT = pEnd;  /* oops...didn't have 8 chars to truncate */
+            else
+                **pEndFAT = '\0';
+        } else if (MIN(plu - pBegin, 8) + MIN(pEnd - plu - 1, 3) > 8) {
+            last_dot = plu;       /* be lazy:  drop through to next if-blk */
+        } else if ((pEnd - *pEndFAT) > 8) {
+            *pEndFAT += 8;        /* more fits into just basename than if */
+            **pEndFAT = '\0';     /*  convert last underscore to dot */
+        } else
+            *pEndFAT = pEnd;      /* whole thing fits into 8 chars or less */
+    }
+
+    if (last_dot != NULL) {       /* one dot (or two, in the case of */
+        *last_dot = '.';          /*  "..") is OK:  put it back in */
+
+        if ((last_dot - pBegin) > 8) {
+            char *p, *q;
+            int i;
+
+            p = last_dot;
+            q = last_dot = pBegin + 8;
+            for (i = 0;  (i < 4) && *p;  ++i)  /* too many chars in basename: */
+                *q++ = *p++;                   /*  shift .ext left and trun- */
+            *q = '\0';                         /*  cate/terminate it */
+            *pEndFAT = q;
+        } else if ((pEnd - last_dot) > 4) {    /* too many chars in extension */
+            *pEndFAT = last_dot + 4;
+            **pEndFAT = '\0';
+        } else
+            *pEndFAT = pEnd;   /* filename is fine; point at terminating zero */
+
+        if ((last_dot - pBegin) > 0 && last_dot[-1] == ' ')
+            last_dot[-1] = '_';                /* NO blank in front of '.'! */
+    }
+} /* end function map2fat() */
+
+
+
+
+/***********************/       /* Borrowed from os2.c for UnZip 5.1.        */
+/* Function checkdir() */       /* Difference: no EA stuff                   */
+/***********************/       /*             HPFS stuff works on NTFS too  */
+
+int checkdir(__G__ pathcomp, flag)
+    __GDEF
+    char *pathcomp;
+    int flag;
+/*
+ * returns:  1 - (on APPEND_NAME) truncated filename
+ *           2 - path doesn't exist, not allowed to create
+ *           3 - path doesn't exist, tried to create and failed; or
+ *               path exists and is not a directory, but is supposed to be
+ *           4 - path is too long
+ *          10 - can't allocate memory for filename buffers
+ */
+{
+ /* static int rootlen = 0;     */   /* length of rootpath */
+ /* static char *rootpath;      */   /* user's "extract-to" directory */
+ /* static char *buildpathHPFS; */   /* full path (so far) to extracted file, */
+ /* static char *buildpathFAT;  */   /*  both HPFS/EA (main) and FAT versions */
+ /* static char *endHPFS;       */   /* corresponding pointers to end of */
+ /* static char *endFAT;        */   /*  buildpath ('\0') */
+
+#   define FN_MASK   7
+#   define FUNCTION  (flag & FN_MASK)
+
+
+
+/*---------------------------------------------------------------------------
+    APPEND_DIR:  append the path component to the path being built and check
+    for its existence.  If doesn't exist and we are creating directories, do
+    so for this one; else signal success or error as appropriate.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == APPEND_DIR) {
+        char *p = pathcomp;
+        int too_long=FALSE;
+
+        Trace((stderr, "appending dir segment [%s]\n", pathcomp));
+        while ((*G.endHPFS = *p++) != '\0')     /* copy to HPFS filename */
+            ++G.endHPFS;
+        if (!IsVolumeOldFAT(__G__ G.buildpathHPFS)) {
+            p = pathcomp;
+            while ((*G.endFAT = *p++) != '\0')  /* copy to FAT filename, too */
+                ++G.endFAT;
+        } else
+            map2fat(pathcomp, &G.endFAT);   /* map into FAT fn, update endFAT */
+
+        /* GRR:  could do better check, see if overrunning buffer as we go:
+         * check endHPFS-buildpathHPFS after each append, set warning variable
+         * if within 20 of FILNAMSIZ; then if var set, do careful check when
+         * appending.  Clear variable when begin new path. */
+
+        /* next check:  need to append '/', at least one-char name, '\0' */
+        if ((G.endHPFS-G.buildpathHPFS) > FILNAMSIZ-3)
+            too_long = TRUE;                    /* check if extracting dir? */
+#ifdef FIX_STAT_BUG
+        /* Borland C++ 5.0 does not handle a call to stat() well if the
+         * directory does not exist (it tends to crash in strange places.)
+         * This is apparently a problem only when compiling for GUI rather
+         * than console. The code below attempts to work around this problem.
+         */
+        if (access(G.buildpathFAT, 0) != 0) {
+            if (!G.create_dirs) { /* told not to create (freshening) */
+                free(G.buildpathHPFS);
+                free(G.buildpathFAT);
+                return 2;         /* path doesn't exist:  nothing to do */
+            }
+            if (too_long) {   /* GRR:  should allow FAT extraction w/o EAs */
+                Info(slide, 1, ((char *)slide,
+                  "checkdir error:  path too long: %s\n",
+                  FnFilter1(G.buildpathHPFS)));
+                free(G.buildpathHPFS);
+                free(G.buildpathFAT);
+                return 4;         /* no room for filenames:  fatal */
+            }
+            if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */
+                Info(slide, 1, ((char *)slide,
+                  "checkdir error:  cannot create %s\n\
+                 unable to process %s.\n",
+                  FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));
+                free(G.buildpathHPFS);
+                free(G.buildpathFAT);
+                return 3;      /* path didn't exist, tried to create, failed */
+            }
+            G.created_dir = TRUE;
+        }
+#endif /* FIX_STAT_BUG */
+        if (SSTAT(G.buildpathFAT, &G.statbuf))   /* path doesn't exist */
+        {
+            if (!G.create_dirs) { /* told not to create (freshening) */
+                free(G.buildpathHPFS);
+                free(G.buildpathFAT);
+                return 2;         /* path doesn't exist:  nothing to do */
+            }
+            if (too_long) {   /* GRR:  should allow FAT extraction w/o EAs */
+                Info(slide, 1, ((char *)slide,
+                  "checkdir error:  path too long: %s\n",
+                  FnFilter1(G.buildpathHPFS)));
+                free(G.buildpathHPFS);
+                free(G.buildpathFAT);
+                return 4;         /* no room for filenames:  fatal */
+            }
+            if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */
+                Info(slide, 1, ((char *)slide,
+                  "checkdir error:  cannot create %s\n\
+                 unable to process %s.\n",
+                  FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));
+                free(G.buildpathHPFS);
+                free(G.buildpathFAT);
+                return 3;      /* path didn't exist, tried to create, failed */
+            }
+            G.created_dir = TRUE;
+        } else if (!S_ISDIR(G.statbuf.st_mode)) {
+            Info(slide, 1, ((char *)slide,
+              "checkdir error:  %s exists but is not directory\n   \
+              unable to process %s.\n",
+              FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));
+            free(G.buildpathHPFS);
+            free(G.buildpathFAT);
+            return 3;          /* path existed but wasn't dir */
+        }
+        if (too_long) {
+            Info(slide, 1, ((char *)slide,
+              "checkdir error:  path too long: %s\n",
+               FnFilter1(G.buildpathHPFS)));
+            free(G.buildpathHPFS);
+            free(G.buildpathFAT);
+            return 4;         /* no room for filenames:  fatal */
+        }
+        *G.endHPFS++ = '/';
+        *G.endFAT++ = '/';
+        *G.endHPFS = *G.endFAT = '\0';
+        Trace((stderr, "buildpathHPFS now = [%s]\nbuildpathFAT now =  [%s]\n",
+          FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT)));
+        return 0;
+
+    } /* end if (FUNCTION == APPEND_DIR) */
+
+/*---------------------------------------------------------------------------
+    GETPATH:  copy full FAT path to the string pointed at by pathcomp (want
+    filename to reflect name used on disk, not EAs; if full path is HPFS,
+    buildpathFAT and buildpathHPFS will be identical).  Also free both paths.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == GETPATH) {
+        Trace((stderr, "getting and freeing FAT path [%s]\n",
+          FnFilter1(G.buildpathFAT)));
+        Trace((stderr, "freeing HPFS path [%s]\n",
+          FnFilter1(G.buildpathHPFS)));
+        strcpy(pathcomp, G.buildpathFAT);
+        free(G.buildpathFAT);
+        free(G.buildpathHPFS);
+        G.buildpathHPFS = G.buildpathFAT = G.endHPFS = G.endFAT = NULL;
+        return 0;
+    }
+
+/*---------------------------------------------------------------------------
+    APPEND_NAME:  assume the path component is the filename; append it and
+    return without checking for existence.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == APPEND_NAME) {
+        char *p = pathcomp;
+        int error = 0;
+
+        Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp)));
+        while ((*G.endHPFS = *p++) != '\0') {   /* copy to HPFS filename */
+            ++G.endHPFS;
+            if ((G.endHPFS-G.buildpathHPFS) >= FILNAMSIZ) {
+                *--G.endHPFS = '\0';
+                Info(slide, 1, ((char *)slide,
+                  "checkdir warning:  path too long; truncating\n \
+                  %s\n                -> %s\n",
+                  FnFilter1(G.filename), FnFilter2(G.buildpathHPFS)));
+                error = 1;   /* filename truncated */
+            }
+        }
+
+        if ( G.pInfo->vollabel || !IsVolumeOldFAT(__G__ G.buildpathHPFS)) {
+            p = pathcomp;
+            while ((*G.endFAT = *p++) != '\0')  /* copy to FAT filename, too */
+                ++G.endFAT;
+        } else
+            map2fat(pathcomp, &G.endFAT);   /* map into FAT fn, update endFAT */
+        Trace((stderr, "buildpathHPFS: %s\nbuildpathFAT:  %s\n",
+          FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT)));
+
+        return error;  /* could check for existence, prompt for new name... */
+
+    } /* end if (FUNCTION == APPEND_NAME) */
+
+/*---------------------------------------------------------------------------
+    INIT:  allocate and initialize buffer space for the file currently being
+    extracted.  If file was renamed with an absolute path, don't prepend the
+    extract-to path.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == INIT) {
+        Trace((stderr, "initializing buildpathHPFS and buildpathFAT to "));
+        if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+1)) == NULL)
+            return 10;
+        if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+1)) == NULL) {
+            free(G.buildpathHPFS);
+            return 10;
+        }
+        if (G.pInfo->vollabel) { /* use root or renamed path, but don't store */
+/* GRR:  for network drives, do strchr() and return IZ_VOL_LABEL if not [1] */
+            if (G.renamed_fullpath && pathcomp[1] == ':')
+                *G.buildpathHPFS = (char)ToLower(*pathcomp);
+            else if (!G.renamed_fullpath && G.rootlen > 1 &&
+                     G.rootpath[1] == ':')
+                *G.buildpathHPFS = (char)ToLower(*G.rootpath);
+            else {
+                char tmpN[MAX_PATH], *tmpP;
+                if (GetFullPathName(".", MAX_PATH, tmpN, &tmpP) > MAX_PATH)
+                { /* by definition of MAX_PATH we should never get here */
+                    Info(slide, 1, ((char *)slide,
+                      "checkdir warning: current dir path too long\n"));
+                    return 1;   /* can't get drive letter */
+                }
+                G.nLabelDrive = *tmpN - 'a' + 1;
+                *G.buildpathHPFS = (char)(G.nLabelDrive - 1 + 'a');
+            }
+            G.nLabelDrive = *G.buildpathHPFS - 'a' + 1; /* save for mapname() */
+            if (uO.volflag == 0 || *G.buildpathHPFS < 'a' /* no labels/bogus? */
+                || (uO.volflag == 1 && !isfloppy(G.nLabelDrive))) { /* !fixed */
+                free(G.buildpathHPFS);
+                free(G.buildpathFAT);
+                return IZ_VOL_LABEL;   /* skipping with message */
+            }
+            *G.buildpathHPFS = '\0';
+        } else if (G.renamed_fullpath) /* pathcomp = valid data */
+            strcpy(G.buildpathHPFS, pathcomp);
+        else if (G.rootlen > 0)
+            strcpy(G.buildpathHPFS, G.rootpath);
+        else
+            *G.buildpathHPFS = '\0';
+        G.endHPFS = G.buildpathHPFS;
+        G.endFAT = G.buildpathFAT;
+        while ((*G.endFAT = *G.endHPFS) != '\0') {
+            ++G.endFAT;
+            ++G.endHPFS;
+        }
+        Trace((stderr, "[%s]\n", FnFilter1(G.buildpathHPFS)));
+        return 0;
+    }
+
+/*---------------------------------------------------------------------------
+    ROOT:  if appropriate, store the path in rootpath and create it if neces-
+    sary; else assume it's a zipfile member and return.  This path segment
+    gets used in extracting all members from every zipfile specified on the
+    command line.  Note that under OS/2 and MS-DOS, if a candidate extract-to
+    directory specification includes a drive letter (leading "x:"), it is
+    treated just as if it had a trailing '/'--that is, one directory level
+    will be created if the path doesn't exist, unless this is otherwise pro-
+    hibited (e.g., freshening).
+  ---------------------------------------------------------------------------*/
+
+#if (!defined(SFX) || defined(SFX_EXDIR))
+    if (FUNCTION == ROOT) {
+        Trace((stderr, "initializing root path to [%s]\n",
+          FnFilter1(pathcomp)));
+        if (pathcomp == NULL) {
+            G.rootlen = 0;
+            return 0;
+        }
+        if ((G.rootlen = strlen(pathcomp)) > 0) {
+            int had_trailing_pathsep=FALSE, has_drive=FALSE, xtra=2;
+
+            if (isalpha((uch)pathcomp[0]) && pathcomp[1] == ':')
+                has_drive = TRUE;   /* drive designator */
+            if (pathcomp[G.rootlen-1] == '/' || pathcomp[G.rootlen-1] == '\\') {
+                pathcomp[--G.rootlen] = '\0';
+                had_trailing_pathsep = TRUE;
+            }
+            if (has_drive && (G.rootlen == 2)) {
+                if (!had_trailing_pathsep)   /* i.e., original wasn't "x:/" */
+                    xtra = 3;      /* room for '.' + '/' + 0 at end of "x:" */
+            } else if (G.rootlen > 0) {   /* need not check "x:." and "x:/" */
+                if (SSTAT(pathcomp, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))
+                {
+                    /* path does not exist */
+                    if (!G.create_dirs /* || iswild(pathcomp) */ ) {
+                        G.rootlen = 0;
+                        return 2;   /* treat as stored file */
+                    }
+                    /* create directory (could add loop here to scan pathcomp
+                     * and create more than one level, but really necessary?) */
+                    if (MKDIR(pathcomp, 0777) == -1) {
+                        Info(slide, 1, ((char *)slide,
+                          "checkdir:  cannot create extraction directory: %s\n",
+                          FnFilter1(pathcomp)));
+                        G.rootlen = 0; /* path didn't exist, tried to create, */
+                        return 3;  /* failed:  file exists, or need 2+ levels */
+                    }
+                }
+            }
+            if ((G.rootpath = (char *)malloc(G.rootlen+xtra)) == NULL) {
+                G.rootlen = 0;
+                return 10;
+            }
+            strcpy(G.rootpath, pathcomp);
+            if (xtra == 3)                  /* had just "x:", make "x:." */
+                G.rootpath[G.rootlen++] = '.';
+            G.rootpath[G.rootlen++] = '/';
+            G.rootpath[G.rootlen] = '\0';
+            Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.rootpath)));
+        }
+        return 0;
+    }
+#endif /* !SFX || SFX_EXDIR */
+
+/*---------------------------------------------------------------------------
+    END:  free rootpath, immediately prior to program exit.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == END) {
+        Trace((stderr, "freeing rootpath\n"));
+        if (G.rootlen > 0) {
+            free(G.rootpath);
+            G.rootlen = 0;
+        }
+        return 0;
+    }
+
+    return 99;  /* should never reach */
+
+} /* end function checkdir() */
+
+
+
+
+
+#ifndef SFX
+#ifndef WINDLL
+
+/************************/
+/*  Function version()  */
+/************************/
+
+void version(__G)
+    __GDEF
+{
+    int len;
+#if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DJGPP__))
+    char buf[80];
+#if (defined(_MSC_VER) && (_MSC_VER > 900))
+    char buf2[80];
+#endif
+#endif
+
+    len = sprintf((char *)slide, CompiledWith,
+
+#if defined(_MSC_VER)  /* MSC == VC++, but what about SDK compiler? */
+      (sprintf(buf, "Microsoft C %d.%02d ", _MSC_VER/100, _MSC_VER%100), buf),
+#  if (_MSC_VER == 800)
+      "(Visual C++ v1.1)",
+#  elif (_MSC_VER == 850)
+      "(Windows NT v3.5 SDK)",
+#  elif (_MSC_VER == 900)
+      "(Visual C++ v2.x)",
+#  elif (_MSC_VER > 900)
+      (sprintf(buf2, "(Visual C++ %d.%d)", _MSC_VER/100 - 6, _MSC_VER%100/10),
+        buf2),
+#  else
+      "(bad version)",
+#  endif
+#elif defined(__WATCOMC__)
+#  if (__WATCOMC__ % 10 > 0)
+      (sprintf(buf, "Watcom C/C++ %d.%02d", __WATCOMC__ / 100,
+       __WATCOMC__ % 100), buf), "",
+#  else
+      (sprintf(buf, "Watcom C/C++ %d.%d", __WATCOMC__ / 100,
+       (__WATCOMC__ % 100) / 10), buf), "",
+#  endif
+#elif defined(__BORLANDC__)
+      "Borland C++",
+#  if (__BORLANDC__ < 0x0200)
+      " 1.0",
+#  elif (__BORLANDC__ == 0x0200)
+      " 2.0",
+#  elif (__BORLANDC__ == 0x0400)
+      " 3.0",
+#  elif (__BORLANDC__ == 0x0410)   /* __BCPLUSPLUS__ = 0x0310 */
+      " 3.1",
+#  elif (__BORLANDC__ == 0x0452)   /* __BCPLUSPLUS__ = 0x0320 */
+      " 4.0 or 4.02",
+#  elif (__BORLANDC__ == 0x0460)   /* __BCPLUSPLUS__ = 0x0340 */
+      " 4.5",
+#  elif (__BORLANDC__ == 0x0500)   /* __BCPLUSPLUS__ = 0x0340 */
+      " 5.0",
+#  elif (__BORLANDC__ == 0x0520)   /* __BCPLUSPLUS__ = 0x0520 */
+      " 5.2 (C++ Builder)",        /* GRR:  assume this will stay sync'd? */
+#  else
+      " later than 5.2",
+#  endif
+#elif defined(__LCC__)
+      "LCC-Win32", "",
+#elif defined(__GNUC__)
+#  if defined(__RSXNT__)
+#    if (defined(__DJGPP__) && !defined(__EMX__))
+      (sprintf(buf, "rsxnt(djgpp v%d.%02d) / gcc ",
+        __DJGPP__, __DJGPP_MINOR__), buf),
+#    elif defined(__DJGPP__)
+      (sprintf(buf, "rsxnt(emx+djgpp v%d.%02d) / gcc ",
+        __DJGPP__, __DJGPP_MINOR__), buf),
+#    elif (defined(__GO32__) && !defined(__EMX__))
+      "rsxnt(djgpp v1.x) / gcc ",
+#    elif defined(__GO32__)
+      "rsxnt(emx + djgpp v1.x) / gcc ",
+#    elif defined(__EMX__)
+      "rsxnt(emx)+gcc ",
+#    else
+      "rsxnt(unknown) / gcc ",
+#    endif
+#  elif defined(__CYGWIN32__)
+      "cygnus win32 / gcc ",
+#  elif defined(__MINGW32__)
+      "mingw32 / gcc ",
+#  else
+      "gcc ",
+#  endif
+      __VERSION__,
+#else /* !_MSC_VER, !__WATCOMC__, !__BORLANDC__, !__LCC__, !__GNUC__ */
+      "unknown compiler (SDK?)", "",
+#endif /* ?compilers */
+
+      "Windows 95 / Windows NT", "\n(32-bit)",
+
+#ifdef __DATE__
+      " on ", __DATE__
+#else
+      "", ""
+#endif
+    );
+
+    (*G.message)((zvoid *)&G, slide, (ulg)len, 0);
+
+    return;
+
+} /* end function version() */
+
+#endif /* !WINDLL */
+#endif /* !SFX */
+
+
+
+#ifdef W32_STAT_BANDAID
+
+/* All currently known variants of WIN32 operating systems (Windows 95/98,
+ * WinNT 3.x, 4.0, 5.0) have a nasty bug in the OS kernel concerning
+ * conversions between UTC and local time: In the time conversion functions
+ * of the Win32 API, the timezone offset (including seasonal daylight saving
+ * shift) between UTC and local time evaluation is erratically based on the
+ * current system time. The correct evaluation must determine the offset
+ * value as it {was/is/will be} for the actual time to be converted.
+ *
+ * Some versions of MS C runtime lib's stat() returns utc time-stamps so
+ * that localtime(timestamp) corresponds to the (potentially false) local
+ * time shown by the OS' system programs (Explorer, command shell dir, etc.)
+ * The RSXNT port follows the same strategy, but fails to recognize the
+ * access-time attribute.
+ *
+ * For the NTFS file system (and other filesystems that store time-stamps
+ * as UTC values), this results in st_mtime (, st_{c|a}time) fields which
+ * are not stable but vary according to the seasonal change of "daylight
+ * saving time in effect / not in effect".
+ *
+ * Other C runtime libs (CygWin, or the CRT DLLs supplied with Win95/NT
+ * return the unix-time equivalent of the UTC FILETIME values as got back
+ * from the Win32 API call. This time, return values from NTFS are correct
+ * whereas utimes from files on (V)FAT volumes vary according to the DST
+ * switches.
+ *
+ * To achieve timestamp consistency of UTC (UT extra field) values in
+ * Zip archives, the Info-ZIP programs require work-around code for
+ * proper time handling in stat() (and other time handling routines).
+ */
+/* stat() functions under Windows95 tend to fail for root directories.   *
+ * Watcom and Borland, at least, are affected by this bug.  Watcom made  *
+ * a partial fix for 11.0 but still missed some cases.  This substitute  *
+ * detects the case and fills in reasonable values.  Otherwise we get    *
+ * effects like failure to extract to a root dir because it's not found. */
+
+int zstat_win32(__W32STAT_GLOBALS__ const char *path, struct stat *buf)
+{
+    if (!stat(path, buf))
+    {
+#ifdef NT_TZBUG_WORKAROUND
+        /* stat was successful, now redo the time-stamp fetches */
+        int fs_uses_loctime = FStampIsLocTime(__G__ path);
+        HANDLE h;
+        FILETIME Modft, Accft, Creft;
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+        char *ansi_path = (char *)alloca(strlen(path) + 1);
+
+        INTERN_TO_ISO(path, ansi_path);
+#       define Ansi_Path  ansi_path
+#else
+#       define Ansi_Path  path
+#endif
+
+        TTrace((stdout, "stat(%s) finds modtime %08lx\n", path, buf->st_mtime));
+        h = CreateFile(Ansi_Path, GENERIC_READ,
+                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+                       OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+        if (h != INVALID_HANDLE_VALUE) {
+            BOOL ftOK = GetFileTime(h, &Creft, &Accft, &Modft);
+            CloseHandle(h);
+
+            if (ftOK) {
+                FTTrace((stdout, "GetFileTime returned Modft", 0, &Modft));
+                FTTrace((stdout, "GetFileTime returned Creft", 0, &Creft));
+                if (!fs_uses_loctime) {
+                    /*  On a filesystem that stores UTC timestamps, we refill
+                     *  the time fields of the struct stat buffer by directly
+                     *  using the UTC values as returned by the Win32
+                     *  GetFileTime() API call.
+                     */
+                    FileTime2utime(&Modft, &(buf->st_mtime));
+                    if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)
+                        FileTime2utime(&Accft, &(buf->st_atime));
+                    else
+                        buf->st_atime = buf->st_mtime;
+                    if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)
+                        FileTime2utime(&Creft, &(buf->st_ctime));
+                    else
+                        buf->st_ctime = buf->st_mtime;
+                    TTrace((stdout,"NTFS, recalculated modtime %08lx\n",
+                            buf->st_mtime));
+                } else {
+                    /*  On VFAT and FAT-like filesystems, the FILETIME values
+                     *  are converted back to the stable local time before
+                     *  converting them to UTC unix time-stamps.
+                     */
+                    VFatFileTime2utime(&Modft, &(buf->st_mtime));
+                    if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)
+                        VFatFileTime2utime(&Accft, &(buf->st_atime));
+                    else
+                        buf->st_atime = buf->st_mtime;
+                    if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)
+                        VFatFileTime2utime(&Creft, &(buf->st_ctime));
+                    else
+                        buf->st_ctime = buf->st_mtime;
+                    TTrace((stdout, "VFAT, recalculated modtime %08lx\n",
+                            buf->st_mtime));
+                }
+            }
+        }
+#       undef Ansi_Path
+#endif /* NT_TZBUG_WORKAROUND */
+        return 0;
+    }
+#ifdef W32_STATROOT_FIX
+    else
+    {
+        DWORD flags;
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+        char *ansi_path = (char *)alloca(strlen(path) + 1);
+
+        INTERN_TO_ISO(path, ansi_path);
+#       define Ansi_Path  ansi_path
+#else
+#       define Ansi_Path  path
+#endif
+
+        flags = GetFileAttributes(Ansi_Path);
+        if (flags != 0xFFFFFFFF && flags & FILE_ATTRIBUTE_DIRECTORY) {
+            Trace((stderr, "\nstat(\"%s\",...) failed on existing directory\n",
+                   path));
+            memset(buf, 0, sizeof(struct stat));
+            buf->st_atime = buf->st_ctime = buf->st_mtime =
+              dos_to_unix_time(DOSTIME_MINIMUM);        /* 1-1-80 */
+            buf->st_mode = S_IFDIR | S_IREAD |
+                           ((flags & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE);
+            return 0;
+        } /* assumes: stat() won't fail on non-dirs without good reason */
+#       undef Ansi_Path
+    }
+#endif /* W32_STATROOT_FIX */
+    return -1;
+}
+
+#endif /* W32_STAT_BANDAID */
+
+#endif /* !FUNZIP */
+
+
+
+#ifndef WINDLL
+/* This replacement getch() function was originally created for Watcom C
+ * and then additionally used with CYGWIN. Since UnZip 5.4, all other Win32
+ * ports apply this replacement rather that their supplied getch() (or
+ * alike) function.  There are problems with unabsorbed LF characters left
+ * over in the keyboard buffer under Win95 (and 98) when ENTER was pressed.
+ * (Under Win95, ENTER returns two(!!) characters: CR-LF.)  This problem
+ * does not appear when run on a WinNT console prompt!
+ */
+
+/* Watcom 10.6's getch() does not handle Alt+<digit><digit><digit>. */
+/* Note that if PASSWD_FROM_STDIN is defined, the file containing   */
+/* the password must have a carriage return after the word, not a   */
+/* Unix-style newline (linefeed only).  This discards linefeeds.    */
+
+int getch_win32(void)
+{
+  HANDLE stin;
+  DWORD rc;
+  unsigned char buf[2];
+  int ret = -1;
+  DWORD odemode = ~(DWORD)0;
+
+#  ifdef PASSWD_FROM_STDIN
+  stin = GetStdHandle(STD_INPUT_HANDLE);
+#  else
+  stin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
+                    FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+  if (stin == INVALID_HANDLE_VALUE)
+    return -1;
+#  endif
+  if (GetConsoleMode(stin, &odemode))
+    SetConsoleMode(stin, ENABLE_PROCESSED_INPUT);  /* raw except ^C noticed */
+  if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1)
+    ret = buf[0];
+  /* when the user hits return we get CR LF.  We discard the LF, not the CR,
+   * because when we call this for the first time after a previous input
+   * such as the one for "replace foo? [y]es, ..." the LF may still be in
+   * the input stream before whatever the user types at our prompt. */
+  if (ret == '\n')
+    if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1)
+      ret = buf[0];
+  if (odemode != ~(DWORD)0)
+    SetConsoleMode(stin, odemode);
+#  ifndef PASSWD_FROM_STDIN
+  CloseHandle(stin);
+#  endif
+  return ret;
+}
+#endif /* !WINDLL */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/packzip/zipinfo.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,1912 @@
+/*---------------------------------------------------------------------------
+
+  zipinfo.c                                              Greg Roelofs et al.
+
+  This file contains all of the ZipInfo-specific listing routines for UnZip.
+
+  Contains:  zi_opts()
+             zi_end_central()
+             zipinfo()
+             zi_long()
+             zi_short()
+             zi_time()
+
+  ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+
+
+#ifndef NO_ZIPINFO  /* strings use up too much space in small-memory systems */
+
+/* Define OS-specific attributes for use on ALL platforms--the S_xxxx
+ * versions of these are defined differently (or not defined) by different
+ * compilers and operating systems. */
+
+#define UNX_IFMT       0170000     /* Unix file type mask */
+#define UNX_IFDIR      0040000     /* Unix directory */
+#define UNX_IFREG      0100000     /* Unix regular file */
+#define UNX_IFSOCK     0140000     /* Unix socket (BSD, not SysV or Amiga) */
+#define UNX_IFLNK      0120000     /* Unix symbolic link (not SysV, Amiga) */
+#define UNX_IFBLK      0060000     /* Unix block special       (not Amiga) */
+#define UNX_IFCHR      0020000     /* Unix character special   (not Amiga) */
+#define UNX_IFIFO      0010000     /* Unix fifo    (BCC, not MSC or Amiga) */
+#define UNX_ISUID      04000       /* Unix set user id on execution */
+#define UNX_ISGID      02000       /* Unix set group id on execution */
+#define UNX_ISVTX      01000       /* Unix directory permissions control */
+#define UNX_ENFMT      UNX_ISGID   /* Unix record locking enforcement flag */
+#define UNX_IRWXU      00700       /* Unix read, write, execute: owner */
+#define UNX_IRUSR      00400       /* Unix read permission: owner */
+#define UNX_IWUSR      00200       /* Unix write permission: owner */
+#define UNX_IXUSR      00100       /* Unix execute permission: owner */
+#define UNX_IRWXG      00070       /* Unix read, write, execute: group */
+#define UNX_IRGRP      00040       /* Unix read permission: group */
+#define UNX_IWGRP      00020       /* Unix write permission: group */
+#define UNX_IXGRP      00010       /* Unix execute permission: group */
+#define UNX_IRWXO      00007       /* Unix read, write, execute: other */
+#define UNX_IROTH      00004       /* Unix read permission: other */
+#define UNX_IWOTH      00002       /* Unix write permission: other */
+#define UNX_IXOTH      00001       /* Unix execute permission: other */
+
+#define VMS_IRUSR      UNX_IRUSR   /* VMS read/owner */
+#define VMS_IWUSR      UNX_IWUSR   /* VMS write/owner */
+#define VMS_IXUSR      UNX_IXUSR   /* VMS execute/owner */
+#define VMS_IRGRP      UNX_IRGRP   /* VMS read/group */
+#define VMS_IWGRP      UNX_IWGRP   /* VMS write/group */
+#define VMS_IXGRP      UNX_IXGRP   /* VMS execute/group */
+#define VMS_IROTH      UNX_IROTH   /* VMS read/other */
+#define VMS_IWOTH      UNX_IWOTH   /* VMS write/other */
+#define VMS_IXOTH      UNX_IXOTH   /* VMS execute/other */
+
+#define AMI_IFMT       06000       /* Amiga file type mask */
+#define AMI_IFDIR      04000       /* Amiga directory */
+#define AMI_IFREG      02000       /* Amiga regular file */
+#define AMI_IHIDDEN    00200       /* to be supported in AmigaDOS 3.x */
+#define AMI_ISCRIPT    00100       /* executable script (text command file) */
+#define AMI_IPURE      00040       /* allow loading into resident memory */
+#define AMI_IARCHIVE   00020       /* not modified since bit was last set */
+#define AMI_IREAD      00010       /* can be opened for reading */
+#define AMI_IWRITE     00004       /* can be opened for writing */
+#define AMI_IEXECUTE   00002       /* executable image, a loadable runfile */
+#define AMI_IDELETE    00001       /* can be deleted */
+
+#define LFLAG  3   /* short "ls -l" type listing */
+
+static int   zi_long   OF((__GPRO__ ulg *pEndprev));
+static int   zi_short  OF((__GPRO));
+static void  zi_showMacTypeCreator
+                       OF((__GPRO__ uch *ebfield));
+static char *zi_time   OF((__GPRO__ ZCONST ulg *datetimez,
+                           ZCONST time_t *modtimez, char *d_t_str));
+
+
+/**********************************************/
+/*  Strings used in zipinfo.c (ZipInfo half)  */
+/**********************************************/
+
+static char nullStr[] = "";
+
+static ZCONST char Far LongHeader[] = "Archive:  %s   %ld bytes   %d file%s\n";
+static ZCONST char Far ShortHeader[] = "Archive:  %s   %ld   %d\n";
+static ZCONST char Far EndCentDirRec[] = "\nEnd-of-central-directory record:\n";
+static ZCONST char Far LineSeparators[] = "-------------------------------\n\n";
+static ZCONST char Far ActOffsetCentDir[] = "\
+  Actual offset of end-of-central-dir record:   %9ld (%.8lXh)\n\
+  Expected offset of end-of-central-dir record: %9ld (%.8lXh)\n\
+  (based on the length of the central directory and its expected offset)\n\n";
+static ZCONST char Far SinglePartArchive1[] = "\
+  This zipfile constitutes the sole disk of a single-part archive; its\n\
+  central directory contains %u %s.  The central directory is %lu\n\
+  (%.8lXh) bytes long, and its (expected) offset in bytes from the\n";
+static ZCONST char Far SinglePartArchive2[] = "\
+  beginning of the zipfile is %lu (%.8lXh).\n\n";
+static ZCONST char Far MultiPartArchive1[] = "\
+  This zipfile constitutes disk %u of a multi-part archive.  The central\n\
+  directory starts on disk %u; %u of its entries %s contained within\n";
+static ZCONST char Far MultiPartArchive2[] = "\
+  this zipfile, out of a total of %u %s.  The entire central\n\
+  directory is %lu (%.8lXh) bytes long, and its offset in bytes from\n";
+static ZCONST char Far MultiPartArchive3[] = "\
+  the beginning of the zipfile in which it begins is %lu (%.8lXh).\n\n";
+static ZCONST char Far NoZipfileComment[] = "  There is no zipfile comment.\n";
+static ZCONST char Far ZipfileCommentDesc[] =
+  "  The zipfile comment is %u bytes long and contains the following text:\n\n";
+static ZCONST char Far ZipfileCommBegin[] =
+ "======================== zipfile comment begins ==========================\n";
+static ZCONST char Far ZipfileCommEnd[] =
+ "========================= zipfile comment ends ===========================\n";
+static ZCONST char Far ZipfileCommTrunc2[] = "\n  The zipfile comment is truncated.\n";
+static ZCONST char Far ZipfileCommTruncMsg[] =
+  "\ncaution:  zipfile comment truncated\n";
+
+static ZCONST char Far CentralDirEntry[] =
+  "\nCentral directory entry #%d:\n---------------------------\n\n";
+static ZCONST char Far ZipfileStats[] =
+  "%d file%s, %lu bytes uncompressed, %lu bytes compressed:  %s%d.%d%%\n";
+
+/* zi_long() strings */
+static ZCONST char Far OS_FAT[] = "MS-DOS, OS/2 or NT FAT";
+static ZCONST char Far OS_Amiga[] = "Amiga";
+static ZCONST char Far OS_VMS[] = "VMS";
+static ZCONST char Far OS_Unix[] = "Unix";
+static ZCONST char Far OS_VMCMS[] = "VM/CMS";
+static ZCONST char Far OS_AtariST[] = "Atari ST";
+static ZCONST char Far OS_HPFS[] = "OS/2 or NT HPFS";
+static ZCONST char Far OS_Macintosh[] = "Macintosh HFS";
+static ZCONST char Far OS_ZSystem[] = "Z-System";
+static ZCONST char Far OS_CPM[] = "CP/M";
+static ZCONST char Far OS_TOPS20[] = "TOPS-20";
+static ZCONST char Far OS_NTFS[] = "NTFS";
+static ZCONST char Far OS_QDOS[] = "SMS/QDOS";
+static ZCONST char Far OS_Acorn[] = "Acorn RISC OS";
+static ZCONST char Far OS_MVS[] = "MVS";
+static ZCONST char Far OS_VFAT[] = "Win32 VFAT";
+static ZCONST char Far OS_BeOS[] = "BeOS";
+static ZCONST char Far OS_Tandem[] = "Tandem NSK";
+
+static ZCONST char Far MthdNone[] = "none (stored)";
+static ZCONST char Far MthdShrunk[] = "shrunk";
+static ZCONST char Far MthdRedF1[] = "reduced (factor 1)";
+static ZCONST char Far MthdRedF2[] = "reduced (factor 2)";
+static ZCONST char Far MthdRedF3[] = "reduced (factor 3)";
+static ZCONST char Far MthdRedF4[] = "reduced (factor 4)";
+static ZCONST char Far MthdImplode[] = "imploded";
+static ZCONST char Far MthdToken[] = "tokenized";
+static ZCONST char Far MthdDeflate[] = "deflated";
+static ZCONST char Far MthdEnDeflate[] = "deflated (enhanced)";
+static ZCONST char Far MthdDCLImplode[] = "imploded (PK DCL)";
+
+static ZCONST char Far DeflNorm[] = "normal";
+static ZCONST char Far DeflMax[] = "maximum";
+static ZCONST char Far DeflFast[] = "fast";
+static ZCONST char Far DeflSFast[] = "superfast";
+
+static ZCONST char Far ExtraBytesPreceding[] =
+  "  There are an extra %ld bytes preceding this file.\n\n";
+
+static ZCONST char Far UnknownNo[] = "unknown (%d)";
+
+static ZCONST char Far LocalHeaderOffset[] =
+  "\n  offset of local header from start of archive:     %lu (%.8lXh) bytes\n";
+static ZCONST char Far HostOS[] =
+  "  file system or operating system of origin:        %s\n";
+static ZCONST char Far EncodeSWVer[] =
+  "  version of encoding software:                     %d.%d\n";
+static ZCONST char Far MinOSCompReq[] =
+  "  minimum file system compatibility required:       %s\n";
+static ZCONST char Far MinSWVerReq[] =
+  "  minimum software version required to extract:     %d.%d\n";
+static ZCONST char Far CompressMethod[] =
+  "  compression method:                               %s\n";
+static ZCONST char Far SlideWindowSizeImplode[] =
+  "  size of sliding dictionary (implosion):           %cK\n";
+static ZCONST char Far ShannonFanoTrees[] =
+  "  number of Shannon-Fano trees (implosion):         %c\n";
+static ZCONST char Far CompressSubtype[] =
+  "  compression sub-type (deflation):                 %s\n";
+static ZCONST char Far FileSecurity[] =
+  "  file security status:                             %sencrypted\n";
+static ZCONST char Far ExtendedLocalHdr[] =
+  "  extended local header:                            %s\n";
+static ZCONST char Far FileModDate[] =
+  "  file last modified on (DOS date/time):            %s\n";
+#ifdef USE_EF_UT_TIME
+  static ZCONST char Far UT_FileModDate[] =
+    "  file last modified on (UT extra field modtime):   %s %s\n";
+  static ZCONST char Far LocalTime[] = "local";
+#ifndef NO_GMTIME
+  static ZCONST char Far GMTime[] = "UTC";
+#endif
+#endif /* USE_EF_UT_TIME */
+static ZCONST char Far CRC32Value[] =
+  "  32-bit CRC value (hex):                           %.8lx\n";
+static ZCONST char Far CompressedFileSize[] =
+  "  compressed size:                                  %lu bytes\n";
+static ZCONST char Far UncompressedFileSize[] =
+  "  uncompressed size:                                %lu bytes\n";
+static ZCONST char Far FilenameLength[] =
+  "  length of filename:                               %u characters\n";
+static ZCONST char Far ExtraFieldLength[] =
+  "  length of extra field:                            %u bytes\n";
+static ZCONST char Far FileCommentLength[] =
+  "  length of file comment:                           %u characters\n";
+static ZCONST char Far FileDiskNum[] =
+  "  disk number on which file begins:                 disk %u\n";
+static ZCONST char Far ApparentFileType[] =
+  "  apparent file type:                               %s\n";
+static ZCONST char Far VMSFileAttributes[] =
+  "  VMS file attributes (%06o octal):               %s\n";
+static ZCONST char Far AmigaFileAttributes[] =
+  "  Amiga file attributes (%06o octal):             %s\n";
+static ZCONST char Far UnixFileAttributes[] =
+  "  Unix file attributes (%06o octal):              %s\n";
+static ZCONST char Far NonMSDOSFileAttributes[] =
+  "  non-MSDOS external file attributes:               %06lX hex\n";
+static ZCONST char Far MSDOSFileAttributes[] =
+  "  MS-DOS file attributes (%02X hex):                  none\n";
+static ZCONST char Far MSDOSFileAttributesRO[] =
+  "  MS-DOS file attributes (%02X hex):                  read-only\n";
+static ZCONST char Far MSDOSFileAttributesAlpha[] =
+  "  MS-DOS file attributes (%02X hex):                  %s%s%s%s%s%s\n";
+
+
+static ZCONST char Far ExtraFieldTrunc[] = "\n\
+  error: EF data block (type 0x%04x) size %u exceeds remaining extra field\n\
+         space %u; block length has been truncated.\n";
+static ZCONST char Far ExtraFields[] = "\n\
+  The central-directory extra field contains:";
+static ZCONST char Far ExtraFieldType[] = "\n\
+  - A subfield with ID 0x%04x (%s) and %u data bytes";
+static ZCONST char Far efAV[] = "PKWARE AV";
+static ZCONST char Far efOS2[] = "OS/2";
+static ZCONST char Far efPKVMS[] = "PKWARE VMS";
+static ZCONST char Far efPKWin32[] = "PKWARE Win32";
+static ZCONST char Far efPKUnix[] = "PKWARE Unix";
+static ZCONST char Far efIZVMS[] = "Info-ZIP VMS";
+static ZCONST char Far efIZUnix[] = "old Info-ZIP Unix/OS2/NT";
+static ZCONST char Far efIZUnix2[] = "Unix UID/GID";
+static ZCONST char Far efTime[] = "universal time";
+static ZCONST char Far efJLMac[] = "old Info-ZIP Macintosh";
+static ZCONST char Far efMac3[] = "new Info-ZIP Macintosh";
+static ZCONST char Far efZipIt[] = "ZipIt Macintosh";
+static ZCONST char Far efZipIt2[] = "ZipIt Macintosh (short)";
+static ZCONST char Far efVMCMS[] = "VM/CMS";
+static ZCONST char Far efMVS[] = "MVS";
+static ZCONST char Far efACL[] = "OS/2 ACL";
+static ZCONST char Far efNTSD[] = "Security Descriptor";
+static ZCONST char Far efBeOS[] = "BeOS";
+static ZCONST char Far efQDOS[] = "SMS/QDOS";
+static ZCONST char Far efAOSVS[] = "AOS/VS";
+static ZCONST char Far efSpark[] = "Acorn SparkFS";
+static ZCONST char Far efMD5[] = "Fred Kantor MD5";
+static ZCONST char Far efASiUnix[] = "ASi Unix";
+static ZCONST char Far efUnknown[] = "unknown";
+
+static ZCONST char Far OS2EAs[] = ".\n\
+    The local extra field has %lu bytes of OS/2 extended attributes.\n\
+    (May not match OS/2 \"dir\" amount due to storage method)";
+static ZCONST char Far izVMSdata[] = ".  The extra\n\
+    field is %s and has %lu bytes of VMS %s information%s";
+static ZCONST char Far izVMSstored[] = "stored";
+static ZCONST char Far izVMSrleenc[] = "run-length encoded";
+static ZCONST char Far izVMSdeflat[] = "deflated";
+static ZCONST char Far izVMScunknw[] = "compressed(?)";
+static ZCONST char Far *izVMScomp[4] =
+  {izVMSstored, izVMSrleenc, izVMSdeflat, izVMScunknw};
+static ZCONST char Far ACLdata[] = ".\n\
+    The local extra field has %lu bytes of access control list information";
+static ZCONST char Far NTSDData[] = ".\n\
+    The local extra field has %lu bytes of NT security descriptor data";
+static ZCONST char Far UTdata[] = ".\n\
+    The local extra field has UTC/GMT %s time%s";
+static ZCONST char Far UTmodification[] = "modification";
+static ZCONST char Far UTaccess[] = "access";
+static ZCONST char Far UTcreation[] = "creation";
+static ZCONST char Far ZipItFname[] = ".\n\
+    The Mac long filename is %s.\n";
+static ZCONST char Far Mac3data[] = ".\n\
+    The local extra field has %lu bytes of %scompressed Macintosh\n\
+    finder attributes";
+ /* MacOSdata[] is used by EF_MAC3, EF_ZIPIT, EF_ZIPIT2 and EF_JLEE e. f. */
+static ZCONST char Far MacOSdata[] = ".\n\
+    The associated file has type code `%c%c%c%c' and creator code `%c%c%c%c'";
+static ZCONST char Far MacOSdata1[] = ".\n\
+    The associated file has type code `0x%lx' and creator code `0x%lx'";
+static ZCONST char Far MacOSJLEEflags[] = "\n    File is marked as %s";
+static ZCONST char Far MacOS_RF[] = "Resource-fork";
+static ZCONST char Far MacOS_DF[] = "Data-fork";
+static ZCONST char Far MacOSMAC3flags[] = ".\n\
+    File is marked as %s, File Dates are in %d Bit";
+static ZCONST char Far BeOSdata[] = ".\n\
+    The local extra field has %lu bytes of %scompressed BeOS file attributes";
+ /* The associated file has type code `%c%c%c%c' and creator code `%c%c%c%c'" */
+static ZCONST char Far QDOSdata[] = ".\n\
+    The QDOS extra field subtype is `%c%c%c%c'";
+static ZCONST char Far AOSVSdata[] = ".\n\
+    The AOS/VS extra field revision is %d.%d";
+static ZCONST char Far MD5data[] = ".\n\
+    The 128-bit MD5 signature is %s";
+#ifdef CMS_MVS
+   static ZCONST char Far VmMvsExtraField[] = ".\n\
+    The stored file open mode (FLDATA TYPE) is \"%s\"";
+   static ZCONST char Far VmMvsInvalid[] = "[invalid]";
+#endif /* CMS_MVS */
+
+static ZCONST char Far First20[] = ".  The first\n    20 are:  ";
+static ZCONST char Far ColonIndent[] = ":\n   ";
+static ZCONST char Far efFormat[] = " %02x";
+
+static ZCONST char Far lExtraFieldType[] = "\n\
+  There %s a local extra field with ID 0x%04x (%s) and\n\
+  %u data bytes (%s).\n";
+static ZCONST char Far efIZuid[] =
+  "GMT modification/access times and Unix UID/GID";
+static ZCONST char Far efIZnouid[] = "GMT modification/access times only";
+
+
+static ZCONST char Far NoFileComment[] = "\n  There is no file comment.\n";
+static ZCONST char Far FileCommBegin[] = "\n\
+------------------------- file comment begins ----------------------------\n";
+static ZCONST char Far FileCommEnd[] = "\
+-------------------------- file comment ends -----------------------------\n";
+
+/* zi_time() strings */
+static ZCONST char Far BogusFmt[] = "%03d";
+static ZCONST char Far DMYHMTime[] = "%2u-%s-%02u %02u:%02u";
+static ZCONST char Far YMDHMSTime[] = "%u %s %u %02u:%02u:%02u";
+static ZCONST char Far DecimalTime[] = "%04u%02u%02u.%02u%02u%02u";
+static ZCONST char Far YMDHMSTimeError[] = "???? ??? ?? ??:??:??";
+
+
+
+
+
+#ifndef WINDLL
+
+/************************/
+/*  Function zi_opts()  */
+/************************/
+
+int zi_opts(__G__ pargc, pargv)
+    int *pargc;
+    char ***pargv;
+    __GDEF
+{
+    char   **argv, *s;
+    int    argc, c, error=FALSE, negative=0;
+    int    hflag_slmv=TRUE, hflag_2=FALSE;  /* diff options => diff defaults */
+    int    tflag_slm=TRUE, tflag_2v=FALSE;
+    int    explicit_h=FALSE, explicit_t=FALSE;
+
+
+#ifdef MACOS
+    uO.lflag = LFLAG;         /* reset default on each call */
+#endif
+    G.extract_flag = FALSE;   /* zipinfo does not extract to disk */
+    argc = *pargc;
+    argv = *pargv;
+
+    while (--argc > 0 && (*++argv)[0] == '-') {
+        s = argv[0] + 1;
+        while ((c = *s++) != 0) {    /* "!= 0":  prevent Turbo C warning */
+            switch (c) {
+                case '-':
+                    ++negative;
+                    break;
+                case '1':      /* shortest listing:  JUST filenames */
+                    if (negative)
+                        uO.lflag = -2, negative = 0;
+                    else
+                        uO.lflag = 1;
+                    break;
+                case '2':      /* just filenames, plus headers if specified */
+                    if (negative)
+                        uO.lflag = -2, negative = 0;
+                    else
+                        uO.lflag = 2;
+                    break;
+#ifndef CMS_MVS
+                case ('C'):    /* -C:  match filenames case-insensitively */
+                    if (negative)
+                        uO.C_flag = FALSE, negative = 0;
+                    else
+                        uO.C_flag = TRUE;
+                    break;
+#endif /* !CMS_MVS */
+                case 'h':      /* header line */
+                    if (negative)
+                        hflag_2 = hflag_slmv = FALSE, negative = 0;
+                    else {
+                        hflag_2 = hflag_slmv = explicit_h = TRUE;
+                        if (uO.lflag == -1)
+                            uO.lflag = 0;
+                    }
+                    break;
+                case 'l':      /* longer form of "ls -l" type listing */
+                    if (negative)
+                        uO.lflag = -2, negative = 0;
+                    else
+                        uO.lflag = 5;
+                    break;
+                case 'm':      /* medium form of "ls -l" type listing */
+                    if (negative)
+                        uO.lflag = -2, negative = 0;
+                    else
+                        uO.lflag = 4;
+                    break;
+#ifdef MORE
+                case 'M':      /* send output through built-in "more" */
+                    if (negative)
+                        G.M_flag = FALSE, negative = 0;
+                    else
+                        G.M_flag = TRUE;
+                    break;
+#endif
+                case 's':      /* default:  shorter "ls -l" type listing */
+                    if (negative)
+                        uO.lflag = -2, negative = 0;
+                    else
+                        uO.lflag = 3;
+                    break;
+                case 't':      /* totals line */
+                    if (negative)
+                        tflag_2v = tflag_slm = FALSE, negative = 0;
+                    else {
+                        tflag_2v = tflag_slm = explicit_t = TRUE;
+                        if (uO.lflag == -1)
+                            uO.lflag = 0;
+                    }
+                    break;
+                case ('T'):    /* use (sortable) decimal time format */
+                    if (negative)
+                        uO.T_flag = FALSE, negative = 0;
+                    else
+                        uO.T_flag = TRUE;
+                    break;
+                case 'v':      /* turbo-verbose listing */
+                    if (negative)
+                        uO.lflag = -2, negative = 0;
+                    else
+                        uO.lflag = 10;
+                    break;
+                case 'z':      /* print zipfile comment */
+                    if (negative)
+                        uO.zflag = negative = 0;
+                    else
+                        uO.zflag = 1;
+                    break;
+                case 'Z':      /* ZipInfo mode:  ignore */
+                    break;
+                default:
+                    error = TRUE;
+                    break;
+            }
+        }
+    }
+    if ((argc-- == 0) || error) {
+        *pargc = argc;
+        *pargv = argv;
+        return USAGE(error);
+    }
+
+#ifdef MORE
+    if (G.M_flag && !isatty(1))  /* stdout redirected: "more" func useless */
+        G.M_flag = 0;
+#endif
+
+    /* if no listing options given (or all negated), or if only -h/-t given
+     * with individual files specified, use default listing format */
+    if ((uO.lflag < 0) || ((argc > 0) && (uO.lflag == 0)))
+        uO.lflag = LFLAG;
+
+    /* set header and totals flags to default or specified values */
+    switch (uO.lflag) {
+        case 0:   /* 0:  can only occur if either -t or -h explicitly given; */
+        case 2:   /*  therefore set both flags equal to normally false value */
+            uO.hflag = hflag_2;
+            uO.tflag = tflag_2v;
+            break;
+        case 1:   /* only filenames, *always* */
+            uO.hflag = FALSE;
+            uO.tflag = FALSE;
+            uO.zflag = FALSE;
+            break;
+        case 3:
+        case 4:
+        case 5:
+            uO.hflag = ((argc > 0) && !explicit_h)? FALSE : hflag_slmv;
+            uO.tflag = ((argc > 0) && !explicit_t)? FALSE : tflag_slm;
+            break;
+        case 10:
+            uO.hflag = hflag_slmv;
+            uO.tflag = tflag_2v;
+            break;
+    }
+
+    *pargc = argc;
+    *pargv = argv;
+    return 0;
+
+} /* end function zi_opts() */
+
+#endif /* !WINDLL */
+
+
+
+
+
+/*******************************/
+/*  Function zi_end_central()  */
+/*******************************/
+
+int zi_end_central(__G)   /* return PK-type error code */
+    __GDEF
+{
+    int  error = PK_COOL;
+
+
+/*---------------------------------------------------------------------------
+    Print out various interesting things about the zipfile.
+  ---------------------------------------------------------------------------*/
+
+    /* header fits on one line, for anything up to 10GB and 10000 files: */
+    if (uO.hflag)
+        Info(slide, 0, ((char *)slide, ((int)strlen(G.zipfn) < 39)?
+          LoadFarString(LongHeader) : LoadFarString(ShortHeader), G.zipfn,
+          (long)G.ziplen, G.ecrec.total_entries_central_dir,
+          (G.ecrec.total_entries_central_dir==1)?
+          nullStr : "s"));
+
+    /* verbose format */
+    if (uO.lflag > 9) {
+        Info(slide, 0, ((char *)slide, LoadFarString(EndCentDirRec)));
+        Info(slide, 0, ((char *)slide, LoadFarString(LineSeparators)));
+
+        Info(slide, 0, ((char *)slide, LoadFarString(ActOffsetCentDir),
+          (long)G.real_ecrec_offset, (long)G.real_ecrec_offset,
+          (long)G.expect_ecrec_offset, (long)G.expect_ecrec_offset));
+
+        if (G.ecrec.number_this_disk == 0) {
+            Info(slide, 0, ((char *)slide, LoadFarString(SinglePartArchive1),
+              G.ecrec.total_entries_central_dir,
+              (G.ecrec.total_entries_central_dir == 1)? "entry" : "entries",
+              G.ecrec.size_central_directory,
+              G.ecrec.size_central_directory));
+            Info(slide, 0, ((char *)slide, LoadFarString(SinglePartArchive2),
+              G.ecrec.offset_start_central_directory,
+              G.ecrec.offset_start_central_directory));
+        } else {
+            Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive1),
+              G.ecrec.number_this_disk + 1,
+              G.ecrec.num_disk_start_cdir + 1,
+              G.ecrec.num_entries_centrl_dir_ths_disk,
+              (G.ecrec.num_entries_centrl_dir_ths_disk == 1)? "is" : "are"));
+            Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive2),
+              G.ecrec.total_entries_central_dir,
+              (G.ecrec.total_entries_central_dir == 1) ? "entry" : "entries",
+              G.ecrec.size_central_directory,
+              G.ecrec.size_central_directory));
+            Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive3),
+              G.ecrec.offset_start_central_directory,
+              G.ecrec.offset_start_central_directory));
+        }
+
+    /*-----------------------------------------------------------------------
+        Get the zipfile comment, if any, and print it out.  (Comment may be
+        up to 64KB long.  May the fleas of a thousand camels infest the arm-
+        pits of anyone who actually takes advantage of this fact.)
+      -----------------------------------------------------------------------*/
+
+        if (!G.ecrec.zipfile_comment_length)
+            Info(slide, 0, ((char *)slide, LoadFarString(NoZipfileComment)));
+        else {
+            Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommentDesc),
+              G.ecrec.zipfile_comment_length));
+            Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommBegin)));
+            if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY))
+                error = PK_WARN;
+            Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommEnd)));
+            if (error)
+                Info(slide, 0, ((char *)slide,
+                  LoadFarString(ZipfileCommTrunc2)));
+        } /* endif (comment exists) */
+
+    /* non-verbose mode:  print zipfile comment only if requested */
+    } else if (uO.zflag && G.ecrec.zipfile_comment_length) {
+        if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) {
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(ZipfileCommTruncMsg)));
+            error = PK_WARN;
+        }
+    } /* endif (verbose) */
+
+    return error;
+
+} /* end function zi_end_central() */
+
+
+
+
+
+/************************/
+/*  Function zipinfo()  */
+/************************/
+
+int zipinfo(__G)   /* return PK-type error code */
+    __GDEF
+{
+    int do_this_file=FALSE, error, error_in_archive=PK_COOL;
+    int *fn_matched=NULL, *xn_matched=NULL;
+    unsigned j, members=0;
+    ulg tot_csize=0L, tot_ucsize=0L;
+    ulg endprev;   /* buffers end of previous entry for zi_long()'s check
+                    *  of extra bytes */
+
+
+/*---------------------------------------------------------------------------
+    Malloc space for check on unmatched filespecs (no big deal if one or both
+    are NULL).
+  ---------------------------------------------------------------------------*/
+
+    if (G.filespecs > 0  &&
+        (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != NULL)
+        for (j = 0;  j < G.filespecs;  ++j)
+            fn_matched[j] = FALSE;
+
+    if (G.xfilespecs > 0  &&
+        (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != NULL)
+        for (j = 0;  j < G.xfilespecs;  ++j)
+            xn_matched[j] = FALSE;
+
+/*---------------------------------------------------------------------------
+    Set file pointer to start of central directory, then loop through cen-
+    tral directory entries.  Check that directory-entry signature bytes are
+    actually there (just a precaution), then process the entry.  We know
+    the entire central directory is on this disk:  we wouldn't have any of
+    this information unless the end-of-central-directory record was on this
+    disk, and we wouldn't have gotten to this routine unless this is also
+    the disk on which the central directory starts.  In practice, this had
+    better be the *only* disk in the archive, but maybe someday we'll add
+    multi-disk support.
+  ---------------------------------------------------------------------------*/
+
+    uO.L_flag = FALSE;      /* zipinfo mode: never convert name to lowercase */
+    G.pInfo = G.info;       /* (re-)initialize, (just to make sure) */
+    G.pInfo->textmode = 0;  /* so one can read on screen (is this ever used?) */
+
+    /* reset endprev for new zipfile; account for multi-part archives (?) */
+    endprev = (G.crec.relative_offset_local_header == 4L)? 4L : 0L;
+
+
+    for (j = 0; j++ < (unsigned)G.ecrec.total_entries_central_dir;) {
+        if (readbuf(__G__ G.sig, 4) == 0)
+            return PK_EOF;
+        if (strncmp(G.sig, central_hdr_sig, 4)) {  /* just to make sure */
+            Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), j));
+            return PK_BADERR;   /* sig not found */
+        }
+        /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag, ...: */
+        if ((error = process_cdir_file_hdr(__G)) != PK_COOL)
+            return error;       /* only PK_EOF defined */
+
+        if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=
+             PK_COOL)
+        {
+          error_in_archive = error;   /* might be warning */
+          if (error > PK_WARN)        /* fatal */
+              return error;
+        }
+
+        if (!G.process_all_files) {   /* check if specified on command line */
+            unsigned i;
+
+            do_this_file = FALSE;
+            for (i = 0; i < G.filespecs; i++)
+                if (match(G.filename, G.pfnames[i], uO.C_flag)) {
+                    do_this_file = TRUE;
+                    if (fn_matched)
+                        fn_matched[i] = TRUE;
+                    break;       /* found match, so stop looping */
+                }
+            if (do_this_file) {  /* check if this is an excluded file */
+                for (i = 0; i < G.xfilespecs; i++)
+                    if (match(G.filename, G.pxnames[i], uO.C_flag)) {
+                        do_this_file = FALSE;  /* ^-- ignore case in match */
+                        if (xn_matched)
+                            xn_matched[i] = TRUE;
+                        break;
+                    }
+            }
+        }
+
+    /*-----------------------------------------------------------------------
+        If current file was specified on command line, or if no names were
+        specified, do the listing for this file.  Otherwise, get rid of the
+        file comment and go back for the next file.
+      -----------------------------------------------------------------------*/
+
+        if (G.process_all_files || do_this_file) {
+
+            switch (uO.lflag) {
+                case 1:
+                case 2:
+                    fnprint(__G);
+                    SKIP_(G.crec.extra_field_length)
+                    SKIP_(G.crec.file_comment_length)
+                    break;
+
+                case 3:
+                case 4:
+                case 5:
+                    if ((error = zi_short(__G)) != PK_COOL) {
+                        error_in_archive = error;   /* might be warning */
+                        if (error > PK_WARN)        /* fatal */
+                            return error;
+                    }
+                    break;
+
+                case 10:
+                    Info(slide, 0, ((char *)slide,
+                      LoadFarString(CentralDirEntry), j));
+                    if ((error = zi_long(__G__ &endprev)) != PK_COOL) {
+                        error_in_archive = error;   /* might be warning */
+                        if (error > PK_WARN)        /* fatal */
+                            return error;
+                    }
+                    break;
+
+                default:
+                    SKIP_(G.crec.extra_field_length)
+                    SKIP_(G.crec.file_comment_length)
+                    break;
+
+            } /* end switch (lflag) */
+
+            tot_csize += G.crec.csize;
+            tot_ucsize += G.crec.ucsize;
+            if (G.crec.general_purpose_bit_flag & 1)
+                tot_csize -= 12;   /* don't count encryption header */
+            ++members;
+
+#ifdef DLL
+            if ((G.statreportcb != NULL) &&
+                (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn,
+                                  G.filename, NULL)) {
+                if (fn_matched)
+                    free((zvoid *)fn_matched);
+                if (xn_matched)
+                    free((zvoid *)xn_matched);
+                return IZ_CTRLC;        /* cancel operation by user request */
+            }
+#endif
+#ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */
+            UserStop();
+#endif
+
+        } else {        /* not listing this file */
+            SKIP_(G.crec.extra_field_length)
+            SKIP_(G.crec.file_comment_length)
+
+        } /* end if (list member?) */
+
+    } /* end for-loop (j: member files) */
+
+/*---------------------------------------------------------------------------
+    Check that we actually found requested files; if so, print totals.
+  ---------------------------------------------------------------------------*/
+
+    if (uO.tflag) {
+        char *sgn = "";
+        int cfactor = ratio(tot_ucsize, tot_csize);
+
+        if (cfactor < 0) {
+            sgn = "-";
+            cfactor = -cfactor;
+        }
+        Info(slide, 0, ((char *)slide, LoadFarString(ZipfileStats),
+          members, (members==1)? nullStr:"s", tot_ucsize,
+          tot_csize, sgn, cfactor/10, cfactor%10));
+    }
+
+/*---------------------------------------------------------------------------
+    Check for unmatched filespecs on command line and print warning if any
+    found.
+  ---------------------------------------------------------------------------*/
+
+    if (fn_matched) {
+        for (j = 0;  j < G.filespecs;  ++j)
+            if (!fn_matched[j])
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(FilenameNotMatched), G.pfnames[j]));
+        free((zvoid *)fn_matched);
+    }
+    if (xn_matched) {
+        for (j = 0;  j < G.xfilespecs;  ++j)
+            if (!xn_matched[j])
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(ExclFilenameNotMatched), G.pxnames[j]));
+        free((zvoid *)xn_matched);
+    }
+
+/*---------------------------------------------------------------------------
+    Double check that we're back at the end-of-central-directory record.
+  ---------------------------------------------------------------------------*/
+
+    if (readbuf(__G__ G.sig, 4) == 0)  /* disk error? */
+        return PK_EOF;
+    if (strncmp(G.sig, end_central_sig, 4)) {   /* just to make sure again */
+        Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
+        error_in_archive = PK_WARN;   /* didn't find sig */
+    }
+    if (members == 0 && error_in_archive <= PK_WARN)
+        error_in_archive = PK_FIND;
+
+    if (uO.lflag >= 10)
+        (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
+
+    return error_in_archive;
+
+} /* end function zipinfo() */
+
+
+
+
+
+/************************/
+/*  Function zi_long()  */
+/************************/
+
+static int zi_long(__G__ pEndprev)   /* return PK-type error code */
+    __GDEF
+    ulg *pEndprev;                   /* for zi_long() check of extra bytes */
+{
+#ifdef USE_EF_UT_TIME
+    iztimes z_utime;
+#endif
+    int  error, error_in_archive=PK_COOL;
+    ush  hostnum, hostver, extnum, extver, methnum, xattr;
+    char workspace[12], attribs[22];
+    ZCONST char *varmsg_str;
+    char unkn[16];
+    static ZCONST char Far *os[NUM_HOSTS] = {
+        OS_FAT, OS_Amiga, OS_VMS, OS_Unix, OS_VMCMS, OS_AtariST, OS_HPFS,
+        OS_Macintosh, OS_ZSystem, OS_CPM, OS_TOPS20, OS_NTFS, OS_QDOS,
+        OS_Acorn, OS_VFAT, OS_MVS, OS_BeOS, OS_Tandem
+    };
+    static ZCONST char Far *method[NUM_METHODS] = {
+        MthdNone, MthdShrunk, MthdRedF1, MthdRedF2, MthdRedF3, MthdRedF4,
+        MthdImplode, MthdToken, MthdDeflate, MthdEnDeflate, MthdDCLImplode
+    };
+    static ZCONST char Far *dtypelng[4] = {
+        DeflNorm, DeflMax, DeflFast, DeflSFast
+    };
+
+
+/*---------------------------------------------------------------------------
+    Check whether there's any extra space inside the zipfile.  If *pEndprev is
+    zero, it's probably a signal that OS/2 extra fields are involved (with
+    unknown compressed size).  We won't worry about prepended junk here...
+  ---------------------------------------------------------------------------*/
+
+    if (G.crec.relative_offset_local_header != *pEndprev && *pEndprev > 0L) {
+        /*  GRR DEBUG
+        Info(slide, 0, ((char *)slide,
+          "  [crec.relative_offset_local_header = %lu, endprev = %lu]\n",
+          G.crec.relative_offset_local_header, *pEndprev));
+         */
+        Info(slide, 0, ((char *)slide, LoadFarString(ExtraBytesPreceding),
+          (long)G.crec.relative_offset_local_header - (long)(*pEndprev)));
+    }
+
+    /* calculate endprev for next time around (problem:  extra fields may
+     * differ in length between local and central-directory records) */
+    *pEndprev = G.crec.relative_offset_local_header + 4L + LREC_SIZE +
+      G.crec.filename_length + G.crec.extra_field_length +
+      G.crec.file_comment_length + G.crec.csize;
+
+/*---------------------------------------------------------------------------
+    Read the extra field, if any. It may be used to get UNIX style modtime.
+  ---------------------------------------------------------------------------*/
+
+    if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) != 0)
+    {
+        if (G.extra_field != NULL) {
+            free(G.extra_field);
+            G.extra_field = NULL;
+        }
+        error_in_archive = error;
+        /* The premature return in case of a "fatal" error (PK_EOF) is
+         * delayed until we analyze the extra field contents.
+         * This allows us to display all the other info that has been
+         * successfully read in.
+         */
+    }
+
+/*---------------------------------------------------------------------------
+    Print out various interesting things about the compressed file.
+  ---------------------------------------------------------------------------*/
+
+    hostnum = (ush)(G.pInfo->hostnum);
+    hostver = G.crec.version_made_by[0];
+    extnum = (ush)MIN(G.crec.version_needed_to_extract[1], NUM_HOSTS);
+    extver = G.crec.version_needed_to_extract[0];
+    methnum = (ush)MIN(G.crec.compression_method, NUM_METHODS);
+
+    (*G.message)((zvoid *)&G, (uch *)"  ", 2L, 0);  fnprint(__G);
+
+    Info(slide, 0, ((char *)slide, LoadFarString(LocalHeaderOffset),
+      G.crec.relative_offset_local_header,
+      G.crec.relative_offset_local_header));
+
+    if (hostnum >= NUM_HOSTS) {
+        sprintf(unkn, LoadFarString(UnknownNo),
+                (int)G.crec.version_made_by[1]);
+        varmsg_str = unkn;
+    } else {
+        varmsg_str = LoadFarStringSmall(os[hostnum]);
+    }
+    Info(slide, 0, ((char *)slide, LoadFarString(HostOS), varmsg_str));
+    Info(slide, 0, ((char *)slide, LoadFarString(EncodeSWVer), hostver/10,
+      hostver%10));
+
+    if (extnum >= NUM_HOSTS) {
+        sprintf(unkn, LoadFarString(UnknownNo),
+                (int)G.crec.version_needed_to_extract[1]);
+        varmsg_str = unkn;
+    } else {
+        varmsg_str = LoadFarStringSmall(os[extnum]);
+    }
+    Info(slide, 0, ((char *)slide, LoadFarString(MinOSCompReq), varmsg_str));
+    Info(slide, 0, ((char *)slide, LoadFarString(MinSWVerReq), extver/10,
+      extver%10));
+
+    if (methnum >= NUM_METHODS) {
+        sprintf(unkn, LoadFarString(UnknownNo), G.crec.compression_method);
+        varmsg_str = unkn;
+    } else {
+        varmsg_str = LoadFarStringSmall(method[methnum]);
+    }
+    Info(slide, 0, ((char *)slide, LoadFarString(CompressMethod), varmsg_str));
+    if (methnum == IMPLODED) {
+        Info(slide, 0, ((char *)slide, LoadFarString(SlideWindowSizeImplode),
+          (G.crec.general_purpose_bit_flag & 2)? '8' : '4'));
+        Info(slide, 0, ((char *)slide, LoadFarString(ShannonFanoTrees),
+          (G.crec.general_purpose_bit_flag & 4)? '3' : '2'));
+    } else if (methnum == DEFLATED) {
+        ush  dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3);
+
+        Info(slide, 0, ((char *)slide, LoadFarString(CompressSubtype),
+          LoadFarStringSmall(dtypelng[dnum])));
+    }
+
+    Info(slide, 0, ((char *)slide, LoadFarString(FileSecurity),
+      (G.crec.general_purpose_bit_flag & 1) ? nullStr : "not "));
+    Info(slide, 0, ((char *)slide, LoadFarString(ExtendedLocalHdr),
+      (G.crec.general_purpose_bit_flag & 8) ? "yes" : "no"));
+    /* print upper 3 bits for amusement? */
+
+    /* For printing of date & time, a "char d_t_buf[21]" is required.
+     * To save stack space, we reuse the "char attribs[22]" buffer which
+     * is not used yet.
+     */
+#   define d_t_buf attribs
+
+    zi_time(__G__ &G.crec.last_mod_dos_datetime, NULL, d_t_buf);
+    Info(slide, 0, ((char *)slide, LoadFarString(FileModDate), d_t_buf));
+#ifdef USE_EF_UT_TIME
+    if (G.extra_field &&
+#ifdef IZ_CHECK_TZ
+        G.tz_is_valid &&
+#endif
+        (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,
+                          G.crec.last_mod_dos_datetime, &z_utime, NULL)
+         & EB_UT_FL_MTIME))
+    {
+        TIMET_TO_NATIVE(z_utime.mtime)   /* NOP unless MSC 7.0 or Macintosh */
+        d_t_buf[0] = (char)0;               /* signal "show local time" */
+        zi_time(__G__ &G.crec.last_mod_dos_datetime, &(z_utime.mtime), d_t_buf);
+        Info(slide, 0, ((char *)slide, LoadFarString(UT_FileModDate),
+          d_t_buf, LoadFarStringSmall(LocalTime)));
+#ifndef NO_GMTIME
+        d_t_buf[0] = (char)1;           /* signal "show UTC (GMT) time" */
+        zi_time(__G__ &G.crec.last_mod_dos_datetime, &(z_utime.mtime), d_t_buf);
+        Info(slide, 0, ((char *)slide, LoadFarString(UT_FileModDate),
+          d_t_buf, LoadFarStringSmall(GMTime)));
+#endif /* !NO_GMTIME */
+    }
+#endif /* USE_EF_UT_TIME */
+
+    Info(slide, 0, ((char *)slide, LoadFarString(CRC32Value), G.crec.crc32));
+    Info(slide, 0, ((char *)slide, LoadFarString(CompressedFileSize),
+      G.crec.csize));
+    Info(slide, 0, ((char *)slide, LoadFarString(UncompressedFileSize),
+      G.crec.ucsize));
+    Info(slide, 0, ((char *)slide, LoadFarString(FilenameLength),
+      G.crec.filename_length));
+    Info(slide, 0, ((char *)slide, LoadFarString(ExtraFieldLength),
+      G.crec.extra_field_length));
+    Info(slide, 0, ((char *)slide, LoadFarString(FileCommentLength),
+      G.crec.file_comment_length));
+    Info(slide, 0, ((char *)slide, LoadFarString(FileDiskNum),
+      G.crec.disk_number_start + 1));
+    Info(slide, 0, ((char *)slide, LoadFarString(ApparentFileType),
+      (G.crec.internal_file_attributes & 1)? "text"
+         : (G.crec.internal_file_attributes & 2)? "ebcdic"
+              : "binary"));             /* changed to accept EBCDIC */
+#ifdef ATARI
+    printf("  external file attributes (hex):                   %.8lx\n",
+      G.crec.external_file_attributes);
+#endif
+    xattr = (ush)((G.crec.external_file_attributes >> 16) & 0xFFFF);
+    if (hostnum == VMS_) {
+        char   *p=attribs, *q=attribs+1;
+        int    i, j, k;
+
+        for (k = 0;  k < 12;  ++k)
+            workspace[k] = 0;
+        if (xattr & VMS_IRUSR)
+            workspace[0] = 'R';
+        if (xattr & VMS_IWUSR) {
+            workspace[1] = 'W';
+            workspace[3] = 'D';
+        }
+        if (xattr & VMS_IXUSR)
+            workspace[2] = 'E';
+        if (xattr & VMS_IRGRP)
+            workspace[4] = 'R';
+        if (xattr & VMS_IWGRP) {
+            workspace[5] = 'W';
+            workspace[7] = 'D';
+        }
+        if (xattr & VMS_IXGRP)
+            workspace[6] = 'E';
+        if (xattr & VMS_IROTH)
+            workspace[8] = 'R';
+        if (xattr & VMS_IWOTH) {
+            workspace[9] = 'W';
+            workspace[11] = 'D';
+        }
+        if (xattr & VMS_IXOTH)
+            workspace[10] = 'E';
+
+        *p++ = '(';
+        for (k = j = 0;  j < 3;  ++j) {    /* loop over groups of permissions */
+            for (i = 0;  i < 4;  ++i, ++k)  /* loop over perms within a group */
+                if (workspace[k])
+                    *p++ = workspace[k];
+            *p++ = ',';                       /* group separator */
+            if (j == 0)
+                while ((*p++ = *q++) != ',')
+                    ;                         /* system, owner perms are same */
+        }
+        *p-- = 0;
+        *p = ')';   /* overwrite last comma */
+        Info(slide, 0, ((char *)slide, LoadFarString(VMSFileAttributes), xattr,
+          attribs));
+
+    } else if (hostnum == AMIGA_) {
+        switch (xattr & AMI_IFMT) {
+            case AMI_IFDIR:  attribs[0] = 'd';  break;
+            case AMI_IFREG:  attribs[0] = '-';  break;
+            default:         attribs[0] = '?';  break;
+        }
+        attribs[1] = (xattr & AMI_IHIDDEN)?   'h' : '-';
+        attribs[2] = (xattr & AMI_ISCRIPT)?   's' : '-';
+        attribs[3] = (xattr & AMI_IPURE)?     'p' : '-';
+        attribs[4] = (xattr & AMI_IARCHIVE)?  'a' : '-';
+        attribs[5] = (xattr & AMI_IREAD)?     'r' : '-';
+        attribs[6] = (xattr & AMI_IWRITE)?    'w' : '-';
+        attribs[7] = (xattr & AMI_IEXECUTE)?  'e' : '-';
+        attribs[8] = (xattr & AMI_IDELETE)?   'd' : '-';
+        attribs[9] = 0;   /* better dlm the string */
+        Info(slide, 0, ((char *)slide, LoadFarString(AmigaFileAttributes),
+          xattr, attribs));
+
+    } else if ((hostnum != FS_FAT_) && (hostnum != FS_HPFS_) &&
+               (hostnum != FS_NTFS_) && (hostnum != FS_VFAT_) &&
+               (hostnum != ACORN_) &&
+               (hostnum != VM_CMS_) && (hostnum != MVS_))
+    {                                 /* assume Unix-like */
+        switch ((unsigned)(xattr & UNX_IFMT)) {
+            case (unsigned)UNX_IFDIR:   attribs[0] = 'd';  break;
+            case (unsigned)UNX_IFREG:   attribs[0] = '-';  break;
+            case (unsigned)UNX_IFLNK:   attribs[0] = 'l';  break;
+            case (unsigned)UNX_IFBLK:   attribs[0] = 'b';  break;
+            case (unsigned)UNX_IFCHR:   attribs[0] = 'c';  break;
+            case (unsigned)UNX_IFIFO:   attribs[0] = 'p';  break;
+            case (unsigned)UNX_IFSOCK:  attribs[0] = 's';  break;
+            default:          attribs[0] = '?';  break;
+        }
+        attribs[1] = (xattr & UNX_IRUSR)? 'r' : '-';
+        attribs[4] = (xattr & UNX_IRGRP)? 'r' : '-';
+        attribs[7] = (xattr & UNX_IROTH)? 'r' : '-';
+
+        attribs[2] = (xattr & UNX_IWUSR)? 'w' : '-';
+        attribs[5] = (xattr & UNX_IWGRP)? 'w' : '-';
+        attribs[8] = (xattr & UNX_IWOTH)? 'w' : '-';
+
+        if (xattr & UNX_IXUSR)
+            attribs[3] = (xattr & UNX_ISUID)? 's' : 'x';
+        else
+            attribs[3] = (xattr & UNX_ISUID)? 'S' : '-';   /* S = undefined */
+        if (xattr & UNX_IXGRP)
+            attribs[6] = (xattr & UNX_ISGID)? 's' : 'x';   /* == UNX_ENFMT */
+        else
+            attribs[6] = (xattr & UNX_ISGID)? 'l' : '-';
+        if (xattr & UNX_IXOTH)
+            attribs[9] = (xattr & UNX_ISVTX)? 't' : 'x';   /* "sticky bit" */
+        else
+            attribs[9] = (xattr & UNX_ISVTX)? 'T' : '-';   /* T = undefined */
+        attribs[10] = 0;
+
+        Info(slide, 0, ((char *)slide, LoadFarString(UnixFileAttributes), xattr,
+          attribs));
+
+    } else {
+        Info(slide, 0, ((char *)slide, LoadFarString(NonMSDOSFileAttributes),
+            G.crec.external_file_attributes >> 8));
+
+    } /* endif (hostnum: external attributes format) */
+
+    if ((xattr=(ush)(G.crec.external_file_attributes & 0xFF)) == 0)
+        Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributes),
+          xattr));
+    else if (xattr == 1)
+        Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributesRO),
+          xattr));
+    else
+        Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributesAlpha),
+          xattr, (xattr&1)? "rdo " : nullStr,
+          (xattr&2)? "hid " : nullStr,
+          (xattr&4)? "sys " : nullStr,
+          (xattr&8)? "lab " : nullStr,
+          (xattr&16)? "dir " : nullStr,
+          (xattr&32)? "arc" : nullStr));
+
+/*---------------------------------------------------------------------------
+    Analyze the extra field, if any, and print the file comment, if any (the
+    filename has already been printed, above).  That finishes up this file
+    entry...
+  ---------------------------------------------------------------------------*/
+
+    if (G.crec.extra_field_length > 0) {
+        uch *ef_ptr = G.extra_field;
+        ush ef_len = G.crec.extra_field_length;
+        ush eb_id, eb_datalen;
+        ZCONST char Far *ef_fieldname;
+
+        if (error_in_archive > PK_WARN)   /* fatal:  can't continue */
+            /* delayed "fatal error" return from extra field reading */
+            return error;
+        if (G.extra_field == (uch *)NULL)
+            return PK_ERR;   /* not consistent with crec length */
+
+        Info(slide, 0, ((char *)slide, LoadFarString(ExtraFields)));
+
+        while (ef_len >= EB_HEADSIZE) {
+            eb_id = makeword(&ef_ptr[EB_ID]);
+            eb_datalen = makeword(&ef_ptr[EB_LEN]);
+            ef_ptr += EB_HEADSIZE;
+            ef_len -= EB_HEADSIZE;
+
+            if (eb_datalen > (ush)ef_len) {
+                Info(slide, 0x421, ((char *)slide,
+                  LoadFarString(ExtraFieldTrunc), eb_id, eb_datalen, ef_len));
+                eb_datalen = ef_len;
+            }
+
+            switch (eb_id) {
+                case EF_AV:
+                    ef_fieldname = efAV;
+                    break;
+                case EF_OS2:
+                    ef_fieldname = efOS2;
+                    break;
+                case EF_ACL:
+                    ef_fieldname = efACL;
+                    break;
+                case EF_NTSD:
+                    ef_fieldname = efNTSD;
+                    break;
+                case EF_PKVMS:
+                    ef_fieldname = efPKVMS;
+                    break;
+                case EF_IZVMS:
+                    ef_fieldname = efIZVMS;
+                    break;
+                case EF_PKW32:
+                    ef_fieldname = efPKWin32;
+                    break;
+                case EF_PKUNIX:
+                    ef_fieldname = efPKUnix;
+                    break;
+                case EF_IZUNIX:
+                    ef_fieldname = efIZUnix;
+                    if (G.crec.version_made_by[1] == UNIX_ && *pEndprev > 0L)
+                        *pEndprev += 4L;  /* also have UID/GID in local copy */
+                    break;
+                case EF_IZUNIX2:
+                    ef_fieldname = efIZUnix2;
+                    if (*pEndprev > 0L)
+                        *pEndprev += 4L;  /* 4 byte UID/GID in local copy */
+                    break;
+                case EF_TIME:
+                    ef_fieldname = efTime;
+                    break;
+                case EF_MAC3:
+                    ef_fieldname = efMac3;
+                    break;
+                case EF_JLMAC:
+                    ef_fieldname = efJLMac;
+                    break;
+                case EF_ZIPIT:
+                    ef_fieldname = efZipIt;
+                    break;
+                case EF_ZIPIT2:
+                    ef_fieldname = efZipIt2;
+                    break;
+                case EF_VMCMS:
+                    ef_fieldname = efVMCMS;
+                    break;
+                case EF_MVS:
+                    ef_fieldname = efMVS;
+                    break;
+                case EF_BEOS:
+                    ef_fieldname = efBeOS;
+                    break;
+                case EF_QDOS:
+                    ef_fieldname = efQDOS;
+                    break;
+                case EF_AOSVS:
+                    ef_fieldname = efAOSVS;
+                    break;
+                case EF_SPARK:   /* from RISC OS */
+                    ef_fieldname = efSpark;
+                    break;
+                case EF_MD5:
+                    ef_fieldname = efMD5;
+                    break;
+                case EF_ASIUNIX:
+                    ef_fieldname = efASiUnix;
+                    break;
+                default:
+                    ef_fieldname = efUnknown;
+                    break;
+            }
+            Info(slide, 0, ((char *)slide, LoadFarString(ExtraFieldType),
+                 eb_id, LoadFarStringSmall(ef_fieldname), eb_datalen));
+
+            /* additional, field-specific information: */
+            switch (eb_id) {
+                case EF_OS2:
+                case EF_ACL:
+                    if (eb_datalen >= EB_OS2_HLEN) {
+                        if (eb_id == EF_OS2)
+                            ef_fieldname = OS2EAs;
+                        else
+                            ef_fieldname = ACLdata;
+                        Info(slide, 0, ((char *)slide,
+                          LoadFarString(ef_fieldname), makelong(ef_ptr)));
+                        *pEndprev = 0L;   /* no clue about csize of local */
+                    }
+                    break;
+                case EF_NTSD:
+                    if (eb_datalen >= EB_NTSD_C_LEN) {
+                        Info(slide, 0, ((char *)slide, LoadFarString(NTSDData),
+                          makelong(ef_ptr)));
+                        *pEndprev = 0L;   /* no clue about csize of local */
+                    }
+                    break;
+                case EF_IZVMS:
+                    if (eb_datalen >= 8) {
+                        char *p, q[8];
+                        int compr = makeword(ef_ptr+4) & 7;
+
+                        *q = '\0';
+                        if (compr > 3)
+                            compr = 3;
+                        if (strncmp((char *)ef_ptr, "VFAB", 4) == 0)
+                            p = "FAB";
+                        else if (strncmp((char *)ef_ptr, "VALL", 4) == 0)
+                            p = "XABALL";
+                        else if (strncmp((char *)ef_ptr, "VFHC", 4) == 0)
+                            p = "XABFHC";
+                        else if (strncmp((char *)ef_ptr, "VDAT", 4) == 0)
+                            p = "XABDAT";
+                        else if (strncmp((char *)ef_ptr, "VRDT", 4) == 0)
+                            p = "XABRDT";
+                        else if (strncmp((char *)ef_ptr, "VPRO", 4) == 0)
+                            p = "XABPRO";
+                        else if (strncmp((char *)ef_ptr, "VKEY", 4) == 0)
+                            p = "XABKEY";
+                        else if (strncmp((char *)ef_ptr, "VMSV", 4) == 0) {
+                            p = "version";
+                            if (eb_datalen >= 16) {
+                                q[0] = ' ';
+                                q[1] = '(';
+                                strncpy(q+2, (char *)ef_ptr+12, 4);
+                                q[6] = ')';
+                                q[7] = '\0';
+                            }
+                        } else
+                            p = "version";
+                        Info(slide, 0, ((char *)slide, LoadFarString(izVMSdata),
+                          LoadFarStringSmall(izVMScomp[compr]),
+                          makeword(ef_ptr+6), p, q));
+                    }
+                    break;
+                case EF_TIME:
+                    if (eb_datalen >= 1) {
+                        char types[80];
+                        int num = 0, len;
+
+                        *types = '\0';
+                        if (*ef_ptr & 1) {
+                            strcpy(types, LoadFarString(UTmodification));
+                            ++num;
+                        }
+                        if (*ef_ptr & 2) {
+                            len = strlen(types);
+                            if (num)
+                                types[len++] = '/';
+                            strcpy(types+len, LoadFarString(UTaccess));
+                            ++num;
+                            if (*pEndprev > 0L)
+                                *pEndprev += 4L;
+                        }
+                        if (*ef_ptr & 4) {
+                            len = strlen(types);
+                            if (num)
+                                types[len++] = '/';
+                            strcpy(types+len, LoadFarString(UTcreation));
+                            ++num;
+                            if (*pEndprev > 0L)
+                                *pEndprev += 4L;
+                        }
+                        if (num > 0)
+                            Info(slide, 0, ((char *)slide,
+                              LoadFarString(UTdata), types,
+                              num == 1? nullStr : "s"));
+                    }
+                    break;
+                case EF_MAC3:
+                    if (eb_datalen >= EB_MAC3_HLEN) {
+                        ulg eb_uc = makelong(ef_ptr);
+                        unsigned mac3_flgs = makeword(ef_ptr+EB_FLGS_OFFS);
+                        unsigned eb_is_uc = mac3_flgs & EB_M3_FL_UNCMPR;
+
+                        Info(slide, 0, ((char *)slide, LoadFarString(Mac3data),
+                          eb_uc, eb_is_uc ? "un" : nullStr));
+                        if (eb_is_uc) {
+                            if (*pEndprev > 0L)
+                                *pEndprev += makelong(ef_ptr);
+                        } else {
+                            *pEndprev = 0L; /* no clue about csize of local */
+                        }
+
+                        Info(slide, 0, ((char *)slide,
+                          LoadFarString(MacOSMAC3flags),
+                          LoadFarStringSmall(mac3_flgs & EB_M3_FL_DATFRK ?
+                                             MacOS_DF : MacOS_RF),
+                          (mac3_flgs & EB_M3_FL_TIME64 ? 64 : 32)));
+                        zi_showMacTypeCreator(__G__ &ef_ptr[6]);
+                    }
+                    break;
+                case EF_ZIPIT2:
+                    if (eb_datalen >= 5 &&
+                        strncmp((char *)ef_ptr, "ZPIT", 4) == 0) {
+
+                        if (eb_datalen >= 12) {
+                            zi_showMacTypeCreator(__G__ &ef_ptr[4]);
+                        }
+                    }
+
+                case EF_ZIPIT:
+                    if (eb_datalen >= 5 &&
+                        strncmp((char *)ef_ptr, "ZPIT", 4) == 0) {
+                        unsigned fnlen = ef_ptr[4];
+
+                        if (eb_datalen >= fnlen + (5 + 8)) {
+                            uch nullchar = ef_ptr[fnlen+5];
+
+                            ef_ptr[fnlen+5] = '\0'; /* terminate filename */
+                            Info(slide, 0, ((char *)slide,
+                              LoadFarString(ZipItFname), (char *)ef_ptr+5));
+                            ef_ptr[fnlen+5] = nullchar;
+                            zi_showMacTypeCreator(__G__ &ef_ptr[fnlen+5]);
+                        }
+                    }
+                    break;
+                case EF_JLMAC:
+                    if (eb_datalen >= 40 &&
+                        strncmp((char *)ef_ptr, "JLEE", 4) == 0)
+                    {
+                        zi_showMacTypeCreator(__G__ &ef_ptr[4]);
+
+                        Info(slide, 0, ((char *)slide,
+                          LoadFarString(MacOSJLEEflags),
+                          LoadFarStringSmall(ef_ptr[31] & 1 ?
+                                             MacOS_DF : MacOS_RF)));
+                    }
+                    break;
+#ifdef CMS_MVS
+                case EF_VMCMS:
+                case EF_MVS:
+                    {
+                        char type[100];
+
+                        Info(slide, 0, ((char *)slide,
+                             LoadFarString(VmMvsExtraField),
+                             (getVMMVSexfield(type, ef_ptr-EB_HEADSIZE,
+                             (unsigned)eb_datalen) > 0)?
+                             type : LoadFarStringSmall(VmMvsInvalid)));
+                    }
+                    break;
+#endif /* CMS_MVS */
+                case EF_BEOS:
+                    if (eb_datalen >= EB_BEOS_HLEN) {
+                        ulg eb_uc = makelong(ef_ptr);
+                        unsigned eb_is_uc =
+                          *(ef_ptr+EB_FLGS_OFFS) & EB_BE_FL_UNCMPR;
+
+                        Info(slide, 0, ((char *)slide, LoadFarString(BeOSdata),
+                          eb_uc, eb_is_uc ? "un" : nullStr));
+                        if (eb_is_uc) {
+                            if (*pEndprev > 0L)
+                                *pEndprev += makelong(ef_ptr);
+                        } else {
+                            *pEndprev = 0L; /* no clue about csize of local */
+                        }
+                    }
+                    break;
+                case EF_QDOS:
+                    if (eb_datalen >= 4) {
+                        Info(slide, 0, ((char *)slide, LoadFarString(QDOSdata),
+                          ef_ptr[0], ef_ptr[1], ef_ptr[2], ef_ptr[3]));
+                    }
+                    break;
+                case EF_AOSVS:
+                    if (eb_datalen >= 5) {
+                        Info(slide, 0, ((char *)slide, LoadFarString(AOSVSdata),
+                          ((int)(uch)ef_ptr[4])/10, ((int)(uch)ef_ptr[4])%10));
+                    }
+                    break;
+                case EF_MD5:
+                    if (eb_datalen >= 19) {
+                        char md5[33];
+                        int i;
+
+                        for (i = 0;  i < 16;  ++i)
+                            sprintf(&md5[i<<1], "%02x", ef_ptr[15-i]);
+                        md5[32] = '\0';
+                        Info(slide, 0, ((char *)slide, LoadFarString(MD5data),
+                          md5));
+                        break;
+                    }   /* else: fall through !! */
+                default:
+                    if (eb_datalen > 0) {
+                        ush i, n;
+
+                        if (eb_datalen <= 24) {
+                            Info(slide, 0, ((char *)slide,
+                                 LoadFarString(ColonIndent)));
+                            n = eb_datalen;
+                        } else {
+                            Info(slide, 0, ((char *)slide,
+                                 LoadFarString(First20)));
+                            n = 20;
+                        }
+                        for (i = 0;  i < n;  ++i)
+                            Info(slide, 0, ((char *)slide,
+                                 LoadFarString(efFormat), ef_ptr[i]));
+                    }
+                    break;
+            }
+            (*G.message)((zvoid *)&G, (uch *)".", 1L, 0);
+
+            ef_ptr += eb_datalen;
+            ef_len -= eb_datalen;
+        }
+        (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
+    }
+
+    /* high bit == Unix/OS2/NT GMT times (mtime, atime); next bit == UID/GID */
+    if ((xattr = (ush)((G.crec.external_file_attributes & 0xC000) >> 12)) & 8)
+    {
+        if (hostnum == UNIX_ || hostnum == FS_HPFS_ || hostnum == FS_NTFS_)
+        {
+            Info(slide, 0, ((char *)slide, LoadFarString(lExtraFieldType),
+              "is", EF_IZUNIX, LoadFarStringSmall(efIZUnix),
+              (unsigned)(xattr&12), (xattr&4)? efIZuid : efIZnouid));
+            if (*pEndprev > 0L)
+                *pEndprev += (ulg)(xattr&12);
+        }
+        else if (hostnum == FS_FAT_ && !(xattr&4))
+            Info(slide, 0, ((char *)slide, LoadFarString(lExtraFieldType),
+              "may be", EF_IZUNIX, LoadFarStringSmall(efIZUnix), 8,
+              efIZnouid));
+    }
+
+    if (!G.crec.file_comment_length)
+        Info(slide, 0, ((char *)slide, LoadFarString(NoFileComment)));
+    else {
+        Info(slide, 0, ((char *)slide, LoadFarString(FileCommBegin)));
+        if ((error = do_string(__G__ G.crec.file_comment_length, DISPL_8)) !=
+            PK_COOL)
+        {
+            error_in_archive = error;   /* might be warning */
+            if (error > PK_WARN)   /* fatal */
+                return error;
+        }
+        Info(slide, 0, ((char *)slide, LoadFarString(FileCommEnd)));
+    }
+
+    return error_in_archive;
+
+} /* end function zi_long() */
+
+
+
+
+
+/*************************/
+/*  Function zi_short()  */
+/*************************/
+
+static int zi_short(__G)   /* return PK-type error code */
+    __GDEF
+{
+#ifdef USE_EF_UT_TIME
+    iztimes     z_utime;
+    time_t      *z_modtim;
+#endif
+    int         k, error, error_in_archive=PK_COOL;
+    ush         methnum, hostnum, hostver, xattr;
+    char        *p, workspace[12], attribs[16];
+    char        methbuf[5];
+    static ZCONST char dtype[5]="NXFS"; /* normal, maximum, fast, superfast */
+    static ZCONST char Far os[NUM_HOSTS+1][4] = {
+        "fat", "ami", "vms", "unx", "cms", "atr", "hpf", "mac", "zzz",
+        "cpm", "t20", "ntf", "qds", "aco", "vft", "mvs", "be ", "nsk",
+        "???"
+    };
+    static ZCONST char Far method[NUM_METHODS+1][5] = {
+        "stor", "shrk", "re:1", "re:2", "re:3", "re:4", "i#:#", "tokn",
+        "def#", "edef", "dcli", "u###"
+    };
+
+
+/*---------------------------------------------------------------------------
+    Print out various interesting things about the compressed file.
+  ---------------------------------------------------------------------------*/
+
+    methnum = (ush)MIN(G.crec.compression_method, NUM_METHODS);
+    hostnum = (ush)(G.pInfo->hostnum);
+    hostver = G.crec.version_made_by[0];
+/*
+    extnum = MIN(G.crec.version_needed_to_extract[1], NUM_HOSTS);
+    extver = G.crec.version_needed_to_extract[0];
+ */
+
+    zfstrcpy(methbuf, method[methnum]);
+    if (methnum == IMPLODED) {
+        methbuf[1] = (char)((G.crec.general_purpose_bit_flag & 2)? '8' : '4');
+        methbuf[3] = (char)((G.crec.general_purpose_bit_flag & 4)? '3' : '2');
+    } else if (methnum == DEFLATED) {
+        ush  dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3);
+        methbuf[3] = dtype[dnum];
+    } else if (methnum >= NUM_METHODS) {   /* unknown */
+        sprintf(&methbuf[1], "%03u", G.crec.compression_method);
+    }
+
+    for (k = 0;  k < 15;  ++k)
+        attribs[k] = ' ';
+    attribs[15] = 0;
+
+    xattr = (ush)((G.crec.external_file_attributes >> 16) & 0xFFFF);
+    switch (hostnum) {
+        case VMS_:
+            {   int    i, j;
+
+                for (k = 0;  k < 12;  ++k)
+                    workspace[k] = 0;
+                if (xattr & VMS_IRUSR)
+                    workspace[0] = 'R';
+                if (xattr & VMS_IWUSR) {
+                    workspace[1] = 'W';
+                    workspace[3] = 'D';
+                }
+                if (xattr & VMS_IXUSR)
+                    workspace[2] = 'E';
+                if (xattr & VMS_IRGRP)
+                    workspace[4] = 'R';
+                if (xattr & VMS_IWGRP) {
+                    workspace[5] = 'W';
+                    workspace[7] = 'D';
+                }
+                if (xattr & VMS_IXGRP)
+                  workspace[6] = 'E';
+                if (xattr & VMS_IROTH)
+                    workspace[8] = 'R';
+                if (xattr & VMS_IWOTH) {
+                    workspace[9] = 'W';
+                    workspace[11] = 'D';
+                }
+                if (xattr & VMS_IXOTH)
+                    workspace[10] = 'E';
+
+                p = attribs;
+                for (k = j = 0;  j < 3;  ++j) {     /* groups of permissions */
+                    for (i = 0;  i < 4;  ++i, ++k)  /* perms within a group */
+                        if (workspace[k])
+                            *p++ = workspace[k];
+                    *p++ = ',';                     /* group separator */
+                }
+                *--p = ' ';   /* overwrite last comma */
+                if ((p - attribs) < 12)
+                    sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10);
+            }
+            break;
+
+        case FS_FAT_:
+        case FS_HPFS_:
+        case FS_NTFS_:
+        case VM_CMS_:
+        case FS_VFAT_:
+        case MVS_:
+        case ACORN_:
+            xattr = (ush)(G.crec.external_file_attributes & 0xFF);
+            sprintf(attribs, ".r.-...     %d.%d", hostver/10, hostver%10);
+            attribs[2] = (xattr & 0x01)? '-' : 'w';
+            attribs[5] = (xattr & 0x02)? 'h' : '-';
+            attribs[6] = (xattr & 0x04)? 's' : '-';
+            attribs[4] = (xattr & 0x20)? 'a' : '-';
+            if (xattr & 0x10) {
+                attribs[0] = 'd';
+                attribs[3] = 'x';
+            } else
+                attribs[0] = '-';
+            if (IS_VOLID(xattr))
+                attribs[0] = 'V';
+            else if ((p = strrchr(G.filename, '.')) != (char *)NULL) {
+                ++p;
+                if (STRNICMP(p, "com", 3) == 0 || STRNICMP(p, "exe", 3) == 0 ||
+                    STRNICMP(p, "btm", 3) == 0 || STRNICMP(p, "cmd", 3) == 0 ||
+                    STRNICMP(p, "bat", 3) == 0)
+                    attribs[3] = 'x';
+            }
+            break;
+
+        case AMIGA_:
+            switch (xattr & AMI_IFMT) {
+                case AMI_IFDIR:  attribs[0] = 'd';  break;
+                case AMI_IFREG:  attribs[0] = '-';  break;
+                default:         attribs[0] = '?';  break;
+            }
+            attribs[1] = (xattr & AMI_IHIDDEN)?   'h' : '-';
+            attribs[2] = (xattr & AMI_ISCRIPT)?   's' : '-';
+            attribs[3] = (xattr & AMI_IPURE)?     'p' : '-';
+            attribs[4] = (xattr & AMI_IARCHIVE)?  'a' : '-';
+            attribs[5] = (xattr & AMI_IREAD)?     'r' : '-';
+            attribs[6] = (xattr & AMI_IWRITE)?    'w' : '-';
+            attribs[7] = (xattr & AMI_IEXECUTE)?  'e' : '-';
+            attribs[8] = (xattr & AMI_IDELETE)?   'd' : '-';
+            sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10);
+            break;
+
+        default:   /* assume Unix-like */
+            switch ((unsigned)(xattr & UNX_IFMT)) {
+                case (unsigned)UNX_IFDIR:   attribs[0] = 'd';  break;
+                case (unsigned)UNX_IFREG:   attribs[0] = '-';  break;
+                case (unsigned)UNX_IFLNK:   attribs[0] = 'l';  break;
+                case (unsigned)UNX_IFBLK:   attribs[0] = 'b';  break;
+                case (unsigned)UNX_IFCHR:   attribs[0] = 'c';  break;
+                case (unsigned)UNX_IFIFO:   attribs[0] = 'p';  break;
+                case (unsigned)UNX_IFSOCK:  attribs[0] = 's';  break;
+                default:          attribs[0] = '?';  break;
+            }
+            attribs[1] = (xattr & UNX_IRUSR)? 'r' : '-';
+            attribs[4] = (xattr & UNX_IRGRP)? 'r' : '-';
+            attribs[7] = (xattr & UNX_IROTH)? 'r' : '-';
+            attribs[2] = (xattr & UNX_IWUSR)? 'w' : '-';
+            attribs[5] = (xattr & UNX_IWGRP)? 'w' : '-';
+            attribs[8] = (xattr & UNX_IWOTH)? 'w' : '-';
+
+            if (xattr & UNX_IXUSR)
+                attribs[3] = (xattr & UNX_ISUID)? 's' : 'x';
+            else
+                attribs[3] = (xattr & UNX_ISUID)? 'S' : '-';  /* S==undefined */
+            if (xattr & UNX_IXGRP)
+                attribs[6] = (xattr & UNX_ISGID)? 's' : 'x';  /* == UNX_ENFMT */
+            else
+                /* attribs[6] = (xattr & UNX_ISGID)? 'l' : '-';  real 4.3BSD */
+                attribs[6] = (xattr & UNX_ISGID)? 'S' : '-';  /* SunOS 4.1.x */
+            if (xattr & UNX_IXOTH)
+                attribs[9] = (xattr & UNX_ISVTX)? 't' : 'x';  /* "sticky bit" */
+            else
+                attribs[9] = (xattr & UNX_ISVTX)? 'T' : '-';  /* T==undefined */
+
+            sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10);
+            break;
+
+    } /* end switch (hostnum: external attributes format) */
+
+    Info(slide, 0, ((char *)slide, "%s %s %8lu ", attribs,
+      LoadFarStringSmall(os[hostnum]), G.crec.ucsize));
+    Info(slide, 0, ((char *)slide, "%c",
+      (G.crec.general_purpose_bit_flag & 1)?
+      ((G.crec.internal_file_attributes & 1)? 'T' : 'B') :  /* encrypted */
+      ((G.crec.internal_file_attributes & 1)? 't' : 'b'))); /* plaintext */
+    k = (G.crec.extra_field_length ||
+         /* a local-only "UX" (old Unix/OS2/NT GMT times "IZUNIX") e.f.? */
+         ((G.crec.external_file_attributes & 0x8000) &&
+          (hostnum == UNIX_ || hostnum == FS_HPFS_ || hostnum == FS_NTFS_)));
+    Info(slide, 0, ((char *)slide, "%c", k?
+      ((G.crec.general_purpose_bit_flag & 8)? 'X' : 'x') :  /* extra field */
+      ((G.crec.general_purpose_bit_flag & 8)? 'l' : '-'))); /* no extra field */
+      /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ extended local header or not */
+
+    if (uO.lflag == 4) {
+        ulg csiz = G.crec.csize;
+
+        if (G.crec.general_purpose_bit_flag & 1)
+            csiz -= 12;    /* if encrypted, don't count encryption header */
+        Info(slide, 0, ((char *)slide, "%3d%%",
+          (ratio(G.crec.ucsize,csiz)+5)/10));
+    } else if (uO.lflag == 5)
+        Info(slide, 0, ((char *)slide, " %8lu", G.crec.csize));
+
+    /* Read the extra field, if any.  The extra field info may be used
+     * in the file modification time section, below.
+     */
+    if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) != 0)
+    {
+        if (G.extra_field != NULL) {
+            free(G.extra_field);
+            G.extra_field = NULL;
+        }
+        error_in_archive = error;
+        /* We do not return prematurely in case of a "fatal" error (PK_EOF).
+         * This does not hurt here, because we do not need to read from the
+         * zipfile again before the end of this function.
+         */
+    }
+
+    /* For printing of date & time, a "char d_t_buf[16]" is required.
+     * To save stack space, we reuse the "char attribs[16]" buffer whose
+     * content is no longer needed.
+     */
+#   define d_t_buf attribs
+#ifdef USE_EF_UT_TIME
+    z_modtim = G.extra_field &&
+#ifdef IZ_CHECK_TZ
+               G.tz_is_valid &&
+#endif
+               (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,
+                                 G.crec.last_mod_dos_datetime, &z_utime, NULL)
+                & EB_UT_FL_MTIME)
+              ? &z_utime.mtime : NULL;
+    TIMET_TO_NATIVE(z_utime.mtime)     /* NOP unless MSC 7.0 or Macintosh */
+    d_t_buf[0] = (char)0;              /* signal "show local time" */
+#else
+#   define z_modtim NULL
+#endif
+    Info(slide, 0, ((char *)slide, " %s %s ", methbuf,
+      zi_time(__G__ &G.crec.last_mod_dos_datetime, z_modtim, d_t_buf)));
+    fnprint(__G);
+
+/*---------------------------------------------------------------------------
+    Skip the file comment, if any (the filename has already been printed,
+    above).  That finishes up this file entry...
+  ---------------------------------------------------------------------------*/
+
+    SKIP_(G.crec.file_comment_length)
+
+    return error_in_archive;
+
+} /* end function zi_short() */
+
+
+
+
+
+/**************************************/
+/*  Function zi_showMacTypeCreator()  */
+/**************************************/
+
+static void zi_showMacTypeCreator(__G__ ebfield)
+    __GDEF
+    uch *ebfield;
+{
+    /* not every Type / Creator character is printable */
+    if (isprint(ebfield[0]) && isprint(ebfield[1]) &&
+        isprint(ebfield[2]) && isprint(ebfield[3]) &&
+        isprint(ebfield[4]) && isprint(ebfield[5]) &&
+        isprint(ebfield[6]) && isprint(ebfield[7])) {
+       Info(slide, 0, ((char *)slide, LoadFarString(MacOSdata),
+            ebfield[0], ebfield[1], ebfield[2], ebfield[3],
+            ebfield[4], ebfield[5], ebfield[6], ebfield[7]));
+    } else {
+       Info(slide, 0, ((char *)slide, LoadFarString(MacOSdata1),
+            (((ulg)ebfield[0]) << 24) +
+            (((ulg)ebfield[1]) << 16) +
+            (((ulg)ebfield[2]) << 8)  +
+            ((ulg)ebfield[3]),
+            (((ulg)ebfield[4]) << 24) +
+            (((ulg)ebfield[5]) << 16) +
+            (((ulg)ebfield[6]) << 8)  +
+            ((ulg)ebfield[7])));
+    }
+} /* end function zi_showMacTypeCreator() */
+
+
+
+
+
+/************************/
+/*  Function zi_time()  */
+/************************/
+
+static char *zi_time(__G__ datetimez, modtimez, d_t_str)
+    __GDEF
+    ZCONST ulg *datetimez;
+    ZCONST time_t *modtimez;
+    char *d_t_str;
+{
+    unsigned yr, mo, dy, hh, mm, ss;
+    char monthbuf[4];
+    ZCONST char *monthstr;
+    static ZCONST char Far month[12][4] = {
+        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+    };
+#ifdef USE_EF_UT_TIME
+    struct tm *t;
+#endif
+
+
+
+/*---------------------------------------------------------------------------
+    Convert the file-modification date and time info to a string of the form
+    "1991 Feb 23 17:15:00", "23-Feb-91 17:15" or "19910223.171500", depending
+    on values of lflag and T_flag.  If using Unix-time extra fields, convert
+    to local time or not, depending on value of first character in d_t_str[].
+  ---------------------------------------------------------------------------*/
+
+#ifdef USE_EF_UT_TIME
+    if (modtimez != NULL) {
+#ifndef NO_GMTIME
+        /* check for our secret message from above... */
+        t = (d_t_str[0] == (char)1)? gmtime(modtimez) : localtime(modtimez);
+#else
+        t = localtime(modtimez);
+#endif
+        if (uO.lflag > 9 && t == (struct tm *)NULL)
+            /* time conversion error in verbose listing format,
+             * return string with '?' instead of data
+             */
+            return (strcpy(d_t_str, LoadFarString(YMDHMSTimeError)));
+    } else
+        t = (struct tm *)NULL;
+    if (t != (struct tm *)NULL) {
+        mo = (unsigned)(t->tm_mon + 1);
+        dy = (unsigned)(t->tm_mday);
+        yr = (unsigned)(t->tm_year);
+
+        hh = (unsigned)(t->tm_hour);
+        mm = (unsigned)(t->tm_min);
+        ss = (unsigned)(t->tm_sec);
+    } else
+#endif /* USE_EF_UT_TIME */
+    {
+        yr = ((unsigned)(*datetimez >> 25) & 0x7f) + 80;
+        mo = ((unsigned)(*datetimez >> 21) & 0x0f);
+        dy = ((unsigned)(*datetimez >> 16) & 0x1f);
+
+        hh = (((unsigned)*datetimez >> 11) & 0x1f);
+        mm = (((unsigned)*datetimez >> 5) & 0x3f);
+        ss = (((unsigned)*datetimez << 1) & 0x3e);
+    }
+
+    if (mo == 0 || mo > 12) {
+        sprintf(monthbuf, LoadFarString(BogusFmt), mo);
+        monthstr = monthbuf;
+    } else
+        monthstr = LoadFarStringSmall(month[mo-1]);
+
+    if (uO.lflag > 9)   /* verbose listing format */
+        sprintf(d_t_str, LoadFarString(YMDHMSTime), yr+1900, monthstr, dy, hh,
+          mm, ss);
+    else if (uO.T_flag)
+        sprintf(d_t_str, LoadFarString(DecimalTime), yr+1900, mo, dy, hh, mm,
+          ss);
+    else   /* was:  if ((uO.lflag >= 3) && (uO.lflag <= 5)) */
+        sprintf(d_t_str, LoadFarString(DMYHMTime), dy, monthstr, yr%100, hh,
+          mm);
+
+    return d_t_str;
+
+} /* end function zi_time() */
+
+#endif /* !NO_ZIPINFO */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/dirent.h	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,76 @@
+#ifdef __UNIX__
+#include <dirent.h>
+#else
+#ifndef __DIRENT_H__
+#define __DIRENT_H__
+
+#include <stdio.h>
+#ifdef MAXPATHLEN
+	#undef MAXPATHLEN
+#endif
+#define MAXPATHLEN (FILENAME_MAX*4)
+#define MAXNAMLEN FILENAME_MAX
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* attribute stuff */
+#ifndef A_RONLY
+# define A_RONLY   0x01
+# define A_HIDDEN  0x02
+# define A_SYSTEM  0x04
+# define A_LABEL   0x08
+# define A_DIR     0x10
+# define A_ARCHIVE 0x20
+#endif
+
+struct dirent {
+    int            d_ino;                 /* Dummy */
+    int            d_reclen;		  /* Dummy, same as d_namlen */
+    int            d_namlen;              /* length of name */
+    char           d_name[MAXNAMLEN + 1];
+    unsigned long  d_size;
+    unsigned short d_attribute;           /* attributes (see above) */
+    unsigned short d_time;                /* modification time */
+    unsigned short d_date;                /* modification date */
+};
+
+typedef struct _dirdescr DIR;
+/* the structs do not have to be defined here */
+
+extern DIR		*_opendir(const char *);
+#define opendir(a) _opendir(a)
+extern DIR		*_openxdir(const char *, unsigned);
+#define openxdir(a, b) _openxdir(a, b)
+extern struct dirent	*_readdir(DIR *);
+#define readdir(a) _readdir(a)
+extern void		_seekdir(DIR *, long);
+#define seekdir(a, b) _seekdir(a, b)
+extern long		_telldir(DIR *);
+#define telldir(a) _telldir(a)
+extern void 		_closedir(DIR *);
+#define closedir(a) _closedir(a)
+
+#define			rewinddir(dirp) _seekdir(dirp, 0L)
+extern char *		_abs_path(const char *name, char *buffer, int len);
+#define abs_path(a, b, c) _abs_path(a, b, c)
+
+#ifndef S_IFMT
+#define S_IFMT ( S_IFDIR | S_IFREG )
+#endif
+
+#ifndef S_ISDIR
+#define S_ISDIR( m )                    (((m) & S_IFMT) == S_IFDIR)
+#endif
+
+#ifndef S_ISREG
+#define S_ISREG( m )                    (((m) & S_IFMT) == S_IFREG)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rexx.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,1609 @@
+/* $Id: rexx.c,v 1.47 2003/11/24 18:56:44 bsmith Exp $ */
+
+/*
+ *  rexx.c (C) 1999-2003 Brian Smith <dbsoft@technologist.com>
+ *         (C) 2000 Achim Hasenmueller <achimha@innotek.de>
+ */
+
+#define INCL_RXFUNC
+#define INCL_RXMACRO
+#define INCL_RXARI
+#define INCL_RXSYSEXIT
+#define INCL_RXSUBCOM
+#define INCL_RXSHV
+
+#define __INSTSUP_PRIVATE__ 1
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <fcntl.h>
+#ifndef __UNIX__
+#include <process.h>
+#endif
+#include <sys/types.h>
+#include "dw.h"
+#include "compat.h"
+#ifndef __EMX__
+#include <rexxsaa.h>
+#endif
+#ifdef __OS2__
+#include <direct.h>
+#endif
+#include <ctype.h>
+#include "install.h"
+#include "instsup.h"
+
+#ifndef EXPENTRY
+#define EXPENTRY
+#endif
+
+extern HWND hwnddir, hwndentry, hwndcombo, hwndper, hwndstatus, mainhwnd, hwndHidden;
+extern char finishedscript[], installdir[], installdir2[];
+extern int INSTALLER_PACKAGE_COUNT, packagesselected[], packagechosen;
+extern char *INSTALLER_APPLICATION, *INSTALLER_VERSION, *INSTALLER_TITLE, *INSTALLER_PATH;
+
+#ifdef __OS2__
+char platform[] = "OS2";
+#elif defined(__WIN32__)
+char platform[] = "WIN32";
+#elif defined(__linux__)
+char platform[] = "LINUX";
+#elif defined(__FreeBSD__)
+char platform[] = "FREEBSD";
+#elif defined(__sun__)
+char platform[] = "Solaris";
+#elif defined(__UNIX__)
+char platform[] = "UNIX";
+#else
+char platform[] = "UNKNOWN";
+#endif
+
+char sysdefines[] = "/* REXX Script */\r\n\
+PLATFORM = \"%s\"\r\n\
+BOXHORZ = 0\r\n\
+BOXVERT = 1\r\n\
+HWND_DESKTOP = %d\r\n\
+DW_FCF_TITLEBAR = %d\r\n\
+DW_FCF_SYSMENU = %d\r\n\
+DW_FCF_SIZEBORDER = %d\r\n\
+DW_FCF_MINBUTTON = %d\r\n\
+DW_FCF_MAXBUTTON = %d\r\n\
+DW_FCF_MINMAX = %d\r\n\
+DW_FCF_DLGBORDER = %d\r\n\
+DW_FCF_BORDER = %d\r\n\
+DW_FCF_SHELLPOSITION = %d\r\n\
+DW_FCF_TASKLIST = %d\r\n\
+DW_FCF_SYSMODAL = %d\r\n\
+DW_FCF_HIDEBUTTON = %d\r\n\
+DW_FCF_HIDEMAX = %d\r\n\
+DW_DT_LEFT = %d\r\n\
+DW_DT_UNDERSCORE = %d\r\n\
+DW_DT_STRIKEOUT = %d\r\n\
+DW_DT_CENTER = %d\r\n\
+DW_DT_RIGHT = %d\r\n\
+DW_DT_TOP = %d\r\n\
+DW_DT_VCENTER = %d\r\n\
+DW_DT_BOTTOM = %d\r\n\
+DW_DT_HALFTONE = %d\r\n\
+DW_DT_MNEMONIC = %d\r\n\
+DW_DT_WORDBREAK = %d\r\n\
+DW_CLR_WHITE = %d\r\n\
+DW_CLR_BLACK = %d\r\n\
+DW_CLR_BLUE = %d\r\n\
+DW_CLR_RED = %d\r\n\
+DW_CLR_PINK = %d\r\n\
+DW_CLR_GREEN = %d\r\n\
+DW_CLR_CYAN = %d\r\n\
+DW_CLR_YELLOW = %d\r\n\
+DW_CLR_DARKGRAY = %d\r\n\
+DW_CLR_DARKBLUE = %d\r\n\
+DW_CLR_DARKRED = %d\r\n\
+DW_CLR_DARKPINK = %d\r\n\
+DW_CLR_DARKGREEN = %d\r\n\
+DW_CLR_DARKCYAN = %d\r\n\
+DW_CLR_BROWN = %d\r\n\
+DW_CLR_PALEGRAY = %d\r\n\
+INSTALLER_APPLICATION = \"%s\"\r\n\
+INSTALLER_VERSION = \"%s\"\r\n\
+INSTALLER_TITLE = \"%s\"\r\n\
+INSTALLER_PATH = \"%s\"\r\n\
+TRUE = 1\r\n\
+FALSE = 0\r\n";
+
+unsigned long savedx = 0, savedy = 0, savedwidth = 0, savedheight = 0;
+HWND windowhandle;
+
+RexxVar *root = NULL;
+
+int _count_lines(char *buf)
+{
+	int count = 0;
+
+	while(*buf)
+	{
+		if(*buf == '\n')
+			count++;
+		buf++;
+	}
+	return count;
+}
+
+RexxVar *find_rexxvar(char *varname)
+{
+	RexxVar *tmp = root;
+
+	while(tmp)
+	{
+		if(strcasecmp(tmp->varname, varname) == 0)
+			return tmp;
+		tmp = tmp->next;
+	}
+	return NULL;
+}
+
+char *find_var(char *varname)
+{
+	RexxVar *tmp = find_rexxvar(varname);
+
+	if(tmp)
+		return tmp->rxstring.strptr;
+	return NULL;
+}
+
+int new_rexxvar(char *varname, RXSTRING rxstring)
+{
+	RexxVar *new = find_rexxvar(varname);
+
+	if(new)
+	{
+		free(new->rxstring.strptr);
+		new->rxstring.strlength = rxstring.strlength;
+		new->rxstring.strptr = strdup(rxstring.strptr);
+		return TRUE;
+	}
+	else
+	{
+		new = malloc(sizeof(RexxVar));
+		if(new)
+		{
+			new->varname = strdup(varname);
+			new->rxstring.strlength = rxstring.strlength;
+			new->rxstring.strptr = strdup(rxstring.strptr);
+
+			new->next = root;
+
+			root = new;
+
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+int new_var(char *varname, char *data)
+{
+	RXSTRING rxstring;
+
+	rxstring.strptr = data;
+	rxstring.strlength = strlen(data);
+
+	return new_rexxvar(varname, rxstring);
+}
+
+int remove_rexxvar(char *varname)
+{
+	RexxVar *prev = NULL, *tmp = root;
+
+	while(tmp)
+	{
+		if(strcasecmp(tmp->varname, varname) == 0)
+		{
+			if(!prev)
+			{
+				root = tmp->next;
+				free(tmp->rxstring.strptr);
+				free(tmp->varname);
+				free(tmp);
+				return 0;
+			}
+			else
+			{
+				prev->next = tmp->next;
+				free(tmp->rxstring.strptr);
+				free(tmp->varname);
+				free(tmp);
+				return 0;
+			}
+		}
+		prev = tmp;
+		tmp = tmp->next;
+	}
+	return 0;
+}
+
+int EXPENTRY rexx_dw_box_pack_start(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 7)
+		return 40;
+
+	dw_box_pack_start((HWND)atol(Args[0].strptr),(HWND)atol(Args[1].strptr),(int)atoi(Args[2].strptr),
+					  (int)atoi(Args[3].strptr),(int)atoi(Args[4].strptr),(int)atoi(Args[5].strptr),
+					  (int)atoi(Args[6].strptr));
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_dw_box_pack_end(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 7)
+		return 40;
+
+	dw_box_pack_end((HWND)atol(Args[0].strptr),(HWND)atol(Args[1].strptr),(int)atoi(Args[2].strptr),
+					(int)atoi(Args[3].strptr),(int)atoi(Args[4].strptr),(int)atoi(Args[5].strptr),
+				    (int)atoi(Args[6].strptr));
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+void DWSIGNAL my_box_new(void *mydata)
+{
+	void **data = (void **)mydata;
+
+	windowhandle = dw_box_new((unsigned long)data[0], (unsigned long)data[1]);
+}
+
+int EXPENTRY rexx_dw_box_new(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	void **data;
+
+	if(ArgCount < 2)
+		return 40;
+
+	data = malloc(sizeof(void *) * 2);
+
+	data[0] = (void *)atol(Args[0].strptr);
+	data[1] = (void *)atol(Args[1].strptr);
+
+	dw_window_function(hwndHidden, (void *)my_box_new, (void *)data);
+	free(data);
+
+	sprintf(Retstr->strptr, "%lu", (ULONG)windowhandle);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+void DWSIGNAL my_groupbox_new(void *mydata)
+{
+	void **data = (void **)mydata;
+
+	windowhandle = dw_groupbox_new((int)data[0], (int)data[1], (char *)data[2]);
+}
+
+int EXPENTRY rexx_dw_groupbox_new(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	void **data;
+
+	if(ArgCount < 3)
+		return 40;
+
+	data = malloc(sizeof(void *) * 3);
+
+	data[0] = (void *)atoi(Args[0].strptr);
+	data[1] = (void *)atoi(Args[1].strptr);
+	data[2] = (void *)Args[2].strptr;
+
+	dw_window_function(hwndHidden, (void *)my_groupbox_new, (void *)data);
+	free(data);
+
+	sprintf(Retstr->strptr, "%lu", (ULONG)windowhandle);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+int EXPENTRY rexx_dw_window_show(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	int ret;
+
+	if(ArgCount < 1)
+		return 40;
+
+	ret = dw_window_show((HWND)atol(Args[0].strptr));
+
+	sprintf(Retstr->strptr, "%d", ret);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+int EXPENTRY rexx_dw_window_hide(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	int ret;
+
+	if(ArgCount < 1)
+		return 40;
+
+	ret = dw_window_hide((HWND)atol(Args[0].strptr));
+
+	sprintf(Retstr->strptr, "%d", ret);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+int EXPENTRY rexx_dw_window_destroy(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	int ret = 0;
+
+	if(ArgCount < 1)
+		return 40;
+
+	dw_window_function(hwndHidden, (void *)dw_window_destroy, (void *)atol(Args[0].strptr));
+
+	sprintf(Retstr->strptr, "%d", ret);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+int EXPENTRY rexx_dw_window_set_font(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	int ret;
+
+	if(ArgCount < 2)
+		return 40;
+
+	ret = dw_window_set_font((HWND)atol(Args[0].strptr), Args[1].strptr);
+
+	sprintf(Retstr->strptr, "%d", ret);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+int EXPENTRY rexx_dw_window_set_color(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	int ret;
+
+	if(ArgCount < 3)
+		return 40;
+
+	ret = dw_window_set_color((HWND)atol(Args[0].strptr), atol(Args[1].strptr), atol(Args[2].strptr));
+
+	sprintf(Retstr->strptr, "%d", ret);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+/* Delete event */
+int DWSIGNAL my_delete_event(HWND hwnd, void *data)
+{
+	rexx_deinit();
+	exit(0);
+	return TRUE;
+}
+
+void DWSIGNAL my_window_new(void *mydata)
+{
+	void **data = (void **)mydata;
+
+	windowhandle = dw_window_new((HWND)data[0], (char *)data[1], (unsigned long)data[2]);
+	dw_signal_connect(windowhandle, DW_SIGNAL_DELETE, DW_SIGNAL_FUNC(my_delete_event), NULL);
+}
+
+int EXPENTRY rexx_dw_window_new(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	void **data;
+
+	if(ArgCount < 3)
+		return 40;
+
+	data = malloc(sizeof(void *) * 3);
+
+	data[0] = (void *)atol(Args[0].strptr);
+	data[1] = Args[1].strptr;
+	data[2] = (void *)atol(Args[2].strptr);
+
+	dw_window_function(hwndHidden, (void *)my_window_new, (void *)data);
+	free(data);
+
+	sprintf(Retstr->strptr, "%lu", (ULONG)windowhandle);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+void DWSIGNAL my_bitmap_new(void *mydata)
+{
+	windowhandle = dw_bitmap_new((int)mydata);
+}
+
+int EXPENTRY rexx_dw_bitmap_new(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 1)
+		return 40;
+
+	dw_window_function(hwndHidden, (void *)my_bitmap_new, (void *)atol(Args[0].strptr));
+
+	sprintf(Retstr->strptr, "%lu", (ULONG)windowhandle);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+void DWSIGNAL my_percent_new(void *mydata)
+{
+	windowhandle = dw_percent_new((int)mydata);
+}
+
+int EXPENTRY rexx_dw_percent_new(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 1)
+		return 40;
+
+	dw_window_function(hwndHidden, (void *)my_percent_new, (void *)atol(Args[0].strptr));
+
+	sprintf(Retstr->strptr, "%lu", (ULONG)windowhandle);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+void DWSIGNAL my_container_new(void *mydata)
+{
+	windowhandle = dw_container_new((int)mydata, FALSE);
+}
+
+int EXPENTRY rexx_dw_container_new(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 1)
+		return 40;
+
+	dw_window_function(hwndHidden, (void *)my_container_new, (void *)atol(Args[0].strptr));
+
+	sprintf(Retstr->strptr, "%lu", (ULONG)windowhandle);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+void DWSIGNAL my_text_new(void *mydata)
+{
+	void **data = (void **)mydata;
+
+	windowhandle = dw_text_new((char *)data[0], (unsigned long)data[1]);
+}
+
+int EXPENTRY rexx_dw_text_new(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	void **data;
+
+	if(ArgCount < 2)
+		return 40;
+
+	data = malloc(sizeof(void *) * 2);
+
+	data[0] = Args[0].strptr;
+	data[1] = (void *)atol(Args[1].strptr);
+
+	dw_window_function(hwndHidden, (void *)my_text_new, (void *)data);
+	free(data);
+
+	sprintf(Retstr->strptr, "%lu", (ULONG)windowhandle);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+void DWSIGNAL my_mle_new(void *mydata)
+{
+	windowhandle = dw_mle_new((int)mydata);
+	dw_mle_set_word_wrap(windowhandle, TRUE);
+}
+
+int EXPENTRY rexx_dw_mle_new(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 1)
+		return 40;
+
+	dw_window_function(hwndHidden, (void *)my_mle_new, (void *)atol(Args[0].strptr));
+
+	sprintf(Retstr->strptr, "%lu", (ULONG)windowhandle);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+void DWSIGNAL my_entryfield_new(void *mydata)
+{
+	void **data = (void **)mydata;
+
+	windowhandle = dw_entryfield_new((char *)data[0], (unsigned long)data[1]);
+}
+
+int EXPENTRY rexx_dw_entryfield_new(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	void **data;
+
+	if(ArgCount < 2)
+		return 40;
+
+	data = malloc(sizeof(void *) * 2);
+
+	data[0] = Args[0].strptr;
+	data[1] = (void *)atol(Args[1].strptr);
+
+	dw_window_function(hwndHidden, (void *)my_entryfield_new, (void *)data);
+	free(data);
+
+	sprintf(Retstr->strptr, "%lu", (ULONG)windowhandle);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+void DWSIGNAL my_entryfield_password_new(void *mydata)
+{
+	void **data = (void **)mydata;
+
+	windowhandle = dw_entryfield_password_new((char *)data[0], (unsigned long)data[1]);
+}
+
+int EXPENTRY rexx_dw_entryfield_password_new(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	void **data;
+
+	if(ArgCount < 2)
+		return 40;
+
+	data = malloc(sizeof(void *) * 2);
+
+	data[0] = Args[0].strptr;
+	data[1] = (void *)atol(Args[1].strptr);
+
+	dw_window_function(hwndHidden, (void *)my_entryfield_password_new, (void *)data);
+	free(data);
+
+	sprintf(Retstr->strptr, "%lu", (ULONG)windowhandle);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+void DWSIGNAL my_combobox_new(void *mydata)
+{
+	void **data = (void **)mydata;
+
+	windowhandle = dw_combobox_new((char *)data[0], (unsigned long)data[1]);
+}
+
+int EXPENTRY rexx_dw_combobox_new(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	void **data;
+
+	if(ArgCount < 2)
+		return 40;
+
+	data = malloc(sizeof(void *) * 2);
+
+	data[0] = Args[0].strptr;
+	data[1] = (void *)atol(Args[1].strptr);
+
+	dw_window_function(hwndHidden, (void *)my_combobox_new, (void *)data);
+	free(data);
+
+	sprintf(Retstr->strptr, "%lu", (ULONG)windowhandle);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+void DWSIGNAL my_button_new(void *mydata)
+{
+	void **data = (void **)mydata;
+
+	windowhandle = dw_button_new((char *)data[0], (unsigned long)data[1]);
+}
+
+int EXPENTRY rexx_dw_button_new(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	void **data;
+
+	if(ArgCount < 2)
+		return 40;
+
+	data = malloc(sizeof(void *) * 2);
+
+	data[0] = Args[0].strptr;
+	data[1] = (void *)atol(Args[1].strptr);
+
+	dw_window_function(hwndHidden, (void *)my_button_new, (void *)data);
+	free(data);
+
+	sprintf(Retstr->strptr, "%lu", (ULONG)windowhandle);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+void DWSIGNAL my_spinbutton_new(void *mydata)
+{
+	void **data = (void **)mydata;
+
+	windowhandle = dw_spinbutton_new((char *)data[0], (unsigned long)data[1]);
+}
+
+int EXPENTRY rexx_dw_spinbutton_new(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	void **data;
+
+	if(ArgCount < 2)
+		return 40;
+
+	data = malloc(sizeof(void *) * 2);
+
+	data[0] = Args[0].strptr;
+	data[1] = (void *)atol(Args[1].strptr);
+
+	dw_window_function(hwndHidden, (void *)my_spinbutton_new, (void *)data);
+	free(data);
+
+	sprintf(Retstr->strptr, "%lu", (ULONG)windowhandle);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+void DWSIGNAL my_checkbox_new(void *mydata)
+{
+	void **data = (void **)mydata;
+
+	windowhandle = dw_checkbox_new((char *)data[0], (unsigned long)data[1]);
+}
+
+int EXPENTRY rexx_dw_checkbox_new(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	void **data;
+
+	if(ArgCount < 2)
+		return 40;
+
+	data = malloc(sizeof(void *) * 2);
+
+	data[0] = Args[0].strptr;
+	data[1] = (void *)atol(Args[1].strptr);
+
+	dw_window_function(hwndHidden, (void *)my_checkbox_new, (void *)data);
+	free(data);
+
+	sprintf(Retstr->strptr, "%lu", (ULONG)windowhandle);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+void DWSIGNAL my_radiobutton_new(void *mydata)
+{
+	void **data = (void **)mydata;
+
+	windowhandle = dw_radiobutton_new((char *)data[0], (unsigned long)data[1]);
+}
+
+int EXPENTRY rexx_dw_radiobutton_new(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	void **data;
+
+	if(ArgCount < 2)
+		return 40;
+
+	data = malloc(sizeof(void *) * 2);
+
+	data[0] = Args[0].strptr;
+	data[1] = (void *)atol(Args[1].strptr);
+
+	dw_window_function(hwndHidden, (void *)my_radiobutton_new, (void *)data);
+	free(data);
+
+	sprintf(Retstr->strptr, "%lu", (ULONG)windowhandle);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+void DWSIGNAL my_listbox_new(void *mydata)
+{
+	void **data = (void **)mydata;
+
+	windowhandle = dw_listbox_new((unsigned long)data[0], (unsigned long)data[1]);
+}
+
+int EXPENTRY rexx_dw_listbox_new(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	void **data;
+
+	if(ArgCount < 2)
+		return 40;
+
+	data = malloc(sizeof(void *) * 2);
+
+	data[0] = (void *)atol(Args[0].strptr);
+	data[1] = (void *)atol(Args[1].strptr);
+
+	dw_window_function(hwndHidden, (void *)my_listbox_new, (void *)data);
+	free(data);
+
+	sprintf(Retstr->strptr, "%lu", (ULONG)windowhandle);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+int EXPENTRY rexx_dw_listbox_append(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	HWND handle;
+
+	if(ArgCount < 2)
+		return 40;
+
+	dw_listbox_append((HWND)atol(Args[0].strptr), Args[1].strptr);
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_dw_listbox_select(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	HWND handle;
+
+	if(ArgCount < 3)
+		return 40;
+
+	dw_listbox_select((HWND)atol(Args[0].strptr), atol(Args[1].strptr), atol(Args[2].strptr));
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_dw_listbox_selected(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	int selected;
+
+	if(ArgCount < 1)
+		return 40;
+
+	selected = dw_listbox_selected((HWND)atol(Args[0].strptr));
+
+	sprintf(Retstr->strptr, "%d", selected);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+int EXPENTRY rexx_dw_window_set_usize(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 3)
+		return 40;
+
+	dw_window_set_usize((HWND)atol(Args[0].strptr),atol(Args[1].strptr),atol(Args[2].strptr));
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_dw_window_set_pos_size(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 5)
+		return 40;
+
+	dw_window_set_pos_size((HWND)atol(Args[0].strptr),atol(Args[1].strptr),atol(Args[2].strptr),atol(Args[3].strptr),atol(Args[4].strptr));
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_dw_window_set_style(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 3)
+		return 40;
+
+	dw_window_set_style((HWND)atol(Args[0].strptr),atol(Args[1].strptr),atol(Args[2].strptr));
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_dw_window_set_icon(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 2)
+		return 40;
+
+	dw_window_set_icon((HWND)atol(Args[0].strptr),atol(Args[1].strptr));
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_dw_window_set_bitmap(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 3)
+		return 40;
+
+	dw_window_set_bitmap((HWND)atol(Args[0].strptr),atol(Args[1].strptr), *Args[2].strptr ? Args[2].strptr : NULL);
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_dw_window_set_text(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 2)
+		return 40;
+
+	dw_window_set_text((HWND)atol(Args[0].strptr),Args[1].strptr);
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_dw_window_disable(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 1)
+		return 40;
+
+	dw_window_disable((HWND)atol(Args[0].strptr));
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_dw_window_enable(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 1)
+		return 40;
+
+	dw_window_enable((HWND)atol(Args[0].strptr));
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_dw_window_set_pos(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 3)
+		return 40;
+
+	dw_window_set_pos((HWND)atol(Args[0].strptr),atol(Args[1].strptr),atol(Args[2].strptr));
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_dw_screen_width(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	sprintf(Retstr->strptr, "%lu", (ULONG)dw_screen_width());
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+int EXPENTRY rexx_dw_screen_height(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	sprintf(Retstr->strptr, "%lu", (ULONG)dw_screen_height());
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+int EXPENTRY rexx_dw_checkbox_query(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 1)
+		return 40;
+
+	sprintf(Retstr->strptr, "%lu", (ULONG)dw_checkbox_query((HWND)atol(Args[0].strptr)));
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+int EXPENTRY rexx_dw_checkbox_set(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 2)
+		return 40;
+
+	dw_checkbox_set((HWND)atol(Args[0].strptr), atol(Args[1].strptr));
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_dw_yesno(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 2)
+		return 40;
+
+	sprintf(Retstr->strptr, "%lu", (ULONG)dw_messagebox(Args[0].strptr, DW_MB_YESNO | DW_MB_QUESTION, Args[1].strptr));
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+#if 0
+int EXPENTRY rexx_bitmapfile_new(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ QueueName, PRXSTRING Retstr)
+{
+	HWND handle;
+	if (ArgCount != 1)
+		return 40;
+	handle = dw_bitmapfile_new(atol(Args[0].strptr));
+	sprintf(Retstr->strptr, "%lu", (ULONG)handle);
+
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+int EXPENTRY rexx_bitmapfile_set_bitmap(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ QueueName, PRXSTRING Retstr)
+{
+	if (ArgCount != 2)
+		return 40;
+	dw_bitmapfile_set_bitmap(atol(Args[0].strptr), Args[1].strptr);
+	Retstr->strlength = 0;
+	return 0;
+}
+#endif
+
+int EXPENTRY rexx_grabfile(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 1)
+		return 40;
+
+	grabfile(Args[0].strptr);
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_viewfile(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 1)
+		return 40;
+
+	dw_window_function(hwndHidden, (void *)readme, (void *)Args[0].strptr);
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_mleview(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	FILE *f;
+	ULONG bytes, point = -1;
+	char *buffer;
+    HWND hwndMLE;
+
+	if(ArgCount < 2)
+		return 40;
+
+	hwndMLE = (HWND)atol(Args[1].strptr);
+
+	buffer = grabimage(Args[0].strptr, NULL, 0);
+	if(buffer)
+	{
+		point = dw_mle_import(hwndMLE, buffer, point);
+		dw_mle_set(hwndMLE, 0);
+		free(buffer);
+	}
+
+	Retstr->strlength = 0;
+    return 0;
+}
+
+int EXPENTRY rexx_setwindow(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 1)
+		return 40;
+
+	mainhwnd = (HWND)atol(Args[0].strptr);
+
+	return 0;
+}
+
+int EXPENTRY rexx_setdircontainer(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	int j, count = 0, choose = 0;
+	unsigned long spacefree;
+	char buffer[_MAX_PATH+1];
+	extern int drivelist[26];
+	extern char browsedir[];
+
+
+	if(ArgCount < 3)
+		return 40;
+
+	hwnddir = (HWND)atol(Args[0].strptr);
+	hwndentry = (HWND)atol(Args[1].strptr);
+	hwndcombo = (HWND)atol(Args[2].strptr);
+
+	setdir(hwnddir);
+	populatedir(hwnddir);
+
+	if(hwndcombo)
+	{
+		for(j=3;j<27;j++)
+		{
+			spacefree = (unsigned long)(drivefree(j)/(1024.0*1024.0));
+			if(spacefree > 0)
+			{
+				drivelist[count] = j;
+
+				if((('A'+j)-1) == toupper(browsedir[0]) && browsedir[1] == ':')
+					choose = count;
+
+				count++;
+
+				sprintf(buffer, "Drive %c: %lu megabytes free.", ('A'+j)-1, spacefree);
+				dw_listbox_append(hwndcombo, buffer);
+			}
+		}
+		dw_listbox_select(hwndcombo, choose, TRUE);
+	}
+
+	strcpy(buffer, browsedir);
+	dirappend(buffer);
+	dw_window_set_text(hwndentry, buffer);
+
+	if(hwndcombo)
+		dw_signal_connect(hwndcombo, DW_SIGNAL_LIST_SELECT, DW_SIGNAL_FUNC(listboxselect), NULL);
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_setslider(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+
+	if(ArgCount < 2)
+		return 40;
+
+	hwndper = (HWND)atol(Args[0].strptr);
+	hwndstatus = (HWND)atol(Args[1].strptr);
+
+	Retstr->strlength = 0;
+    return 0;
+}
+
+void DWSIGNAL run_button(HWND window, void *data)
+{
+	char *name = (char *)data;
+
+	if(name)
+		dw_thread_new((void *)rexx_run, name, THREAD_STACK_SIZE);
+}
+
+int EXPENTRY rexx_setbutton(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	HWND handle;
+    char *name;
+
+	if(ArgCount < 2)
+		return 40;
+
+	handle = (HWND)atol(Args[0].strptr);
+	if(handle)
+	{
+		name = strdup(Args[1].strptr);
+		if(name)
+			dw_signal_connect(handle, DW_SIGNAL_CLICKED, DW_SIGNAL_FUNC(run_button), name);
+	}
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_start(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 1)
+		return 40;
+
+	strcpy(finishedscript, Args[0].strptr);
+
+	dw_thread_new((void *)install_thread, NULL, THREAD_STACK_SIZE);
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_packages(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	strcpy(Retstr->strptr, "1");
+
+	if(INSTALLER_PACKAGE_COUNT > 2)
+	{
+		if(package_dialog() || packagechosen == FALSE)
+		{
+			if(packagechosen == FALSE)
+			{
+				mesg("No packages selected for installation!");
+				*(Retstr->strptr) = '0';
+			}
+		}
+	}
+	else
+		packagesselected[1] = TRUE;
+
+	Retstr->strlength = 1;
+	return 0;
+}
+
+int EXPENTRY rexx_updateentry(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 1)
+		return 40;
+
+	strcpy(installdir2, Args[0].strptr);
+	strcpy(installdir, installdir2);
+	getsuffix(installdir2);
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_savevar(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 2)
+		return 40;
+
+	new_rexxvar(Args[0].strptr, Args[1]);
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_removevar(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 1)
+		return 40;
+
+	remove_rexxvar(Args[0].strptr);
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+char *mystrdup(char *str)
+{
+#ifdef __OS2__
+	int len = str ? strlen(str) : 0;
+	char *newstr = NULL;
+
+	DosAllocMem(&newstr, len+1, PAG_READ|PAG_WRITE|PAG_COMMIT);
+
+	if(newstr)
+		strncpy(newstr, str, len+1);
+	return newstr;
+#else
+	return strdup(str);
+#endif
+}
+
+int EXPENTRY rexx_findvar(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	RexxVar *tmp;
+
+	if(ArgCount < 1)
+		return 40;
+
+	tmp = find_rexxvar(Args[0].strptr);
+	if(tmp)
+	{
+		Retstr->strptr = mystrdup(tmp->rxstring.strptr);
+		Retstr->strlength = tmp->rxstring.strlength;
+	}
+	else
+	{
+		strcpy(Retstr->strptr, "");
+		Retstr->strlength = 0;
+	}
+
+	return 0;
+}
+
+int EXPENTRY rexx_mesg(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if(ArgCount < 1)
+		return 40;
+
+	mesg(Args[0].strptr);
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_querycheck(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	HWND checkbox;
+
+	if(ArgCount < 1)
+		return 40;
+
+	checkbox  = (HWND)atol(Args[0].strptr);
+
+	if(dw_checkbox_query(checkbox))
+		strcpy(Retstr->strptr, "1");
+	else
+		strcpy(Retstr->strptr, "0");
+
+	Retstr->strlength = 1;
+	return 0;
+}
+
+int EXPENTRY rexx_setdir(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ QueueName, PRXSTRING Retstr)
+{
+	if (ArgCount != 1)
+		return 40;
+
+	strcpy(installdir2, Args[0].strptr);
+	getsuffix(installdir2);
+
+	Retstr->strptr = NULL;
+	Retstr->strlength = 0;
+	return 0;	
+}
+
+int EXPENTRY rexx_querytext(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ QueueName, PRXSTRING Retstr)
+{
+	char *tmpbuf;
+
+	if (ArgCount != 1)
+		return 40;
+	tmpbuf = dw_window_get_text((HWND)atol(Args[0].strptr));
+	if(tmpbuf)
+	{
+		strcpy(Retstr->strptr, tmpbuf);
+		free(tmpbuf);
+	}
+	else
+		strcpy(Retstr->strptr, "");
+	Retstr->strlength = strlen(Retstr->strptr);
+	return 0;
+}
+
+int EXPENTRY rexx_bitor(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	int z;
+    ULONG ret = 0L;
+
+	for(z=0;z < ArgCount;z++)
+		ret |= atol(Args[z].strptr);
+
+	sprintf(Retstr->strptr, "%lu", ret);
+	Retstr->strlength = strlen(Retstr->strptr);
+
+	return 0;
+}
+
+int EXPENTRY rexx_reboot(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	sys_reboot();
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+
+int EXPENTRY rexx_exit(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	rexx_deinit();
+	exit(0);
+
+	return 0;
+}
+
+int EXPENTRY rexx_save_pos(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if (ArgCount != 1)
+		return 40;
+
+	dw_window_get_pos_size((HWND)atol(Args[0].strptr), &savedx, &savedy, &savedwidth, &savedheight);
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_restore_pos(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	if (ArgCount != 1)
+		return 40;
+
+	dw_window_set_pos_size((HWND)atol(Args[0].strptr), savedx, savedy, savedwidth, savedheight);
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+int EXPENTRY rexx_chdir(PCSZ Name, ULONG ArgCount, RXSTRING Args[], PCSZ Queuename, PRXSTRING Retstr)
+{
+	char *path;
+
+	if (ArgCount != 1)
+		return 40;
+
+	path = Args[0].strptr;
+
+#ifndef __UNIX__
+	if(path[1] == ':')
+	{
+		char drive = toupper(path[0]);
+		_chdrive((drive - 'A')+1);
+	}
+#endif
+	chdir(path);
+
+	Retstr->strlength = 0;
+	return 0;
+}
+
+
+void rexx_init(void)
+{
+	RexxRegisterFunctionExe("dw_box_pack_start", &rexx_dw_box_pack_start);
+	RexxRegisterFunctionExe("dw_box_pack_end", &rexx_dw_box_pack_end);
+	RexxRegisterFunctionExe("dw_box_new", &rexx_dw_box_new);
+	RexxRegisterFunctionExe("dw_groupbox_new", &rexx_dw_groupbox_new);
+	RexxRegisterFunctionExe("dw_window_hide", &rexx_dw_window_hide);
+	RexxRegisterFunctionExe("dw_window_show", &rexx_dw_window_show);
+	RexxRegisterFunctionExe("dw_window_destroy", &rexx_dw_window_destroy);
+	RexxRegisterFunctionExe("dw_window_set_font", &rexx_dw_window_set_font);
+	RexxRegisterFunctionExe("dw_window_set_color", &rexx_dw_window_set_color);
+	RexxRegisterFunctionExe("dw_window_new", &rexx_dw_window_new);
+	RexxRegisterFunctionExe("dw_bitmap_new", &rexx_dw_bitmap_new);
+	RexxRegisterFunctionExe("dw_container_new", &rexx_dw_container_new);
+	RexxRegisterFunctionExe("dw_text_new", &rexx_dw_text_new);
+	RexxRegisterFunctionExe("dw_mle_new", &rexx_dw_mle_new);
+	RexxRegisterFunctionExe("dw_entryfield_new", &rexx_dw_entryfield_new);
+	RexxRegisterFunctionExe("dw_entryfield_password_new", &rexx_dw_entryfield_password_new);
+	RexxRegisterFunctionExe("dw_combobox_new", &rexx_dw_combobox_new);
+	RexxRegisterFunctionExe("dw_button_new", &rexx_dw_button_new);
+	RexxRegisterFunctionExe("dw_spinbutton_new", &rexx_dw_spinbutton_new);
+	RexxRegisterFunctionExe("dw_percent_new", &rexx_dw_percent_new);
+	RexxRegisterFunctionExe("dw_checkbox_new", &rexx_dw_checkbox_new);
+	RexxRegisterFunctionExe("dw_radiobutton_new", &rexx_dw_radiobutton_new);
+	RexxRegisterFunctionExe("dw_listbox_new", &rexx_dw_listbox_new);
+	RexxRegisterFunctionExe("dw_listbox_append", &rexx_dw_listbox_append);
+	RexxRegisterFunctionExe("dw_listbox_select", &rexx_dw_listbox_select);
+	RexxRegisterFunctionExe("dw_listbox_selected", &rexx_dw_listbox_selected);
+	RexxRegisterFunctionExe("dw_window_set_pos", &rexx_dw_window_set_pos);
+	RexxRegisterFunctionExe("dw_window_set_usize", &rexx_dw_window_set_usize);
+	RexxRegisterFunctionExe("dw_window_set_pos_size", &rexx_dw_window_set_pos_size);
+	RexxRegisterFunctionExe("dw_window_set_style", &rexx_dw_window_set_style);
+	RexxRegisterFunctionExe("dw_window_set_icon", &rexx_dw_window_set_icon);
+	RexxRegisterFunctionExe("dw_window_set_bitmap", &rexx_dw_window_set_bitmap);
+	RexxRegisterFunctionExe("dw_window_set_text", &rexx_dw_window_set_text);
+	RexxRegisterFunctionExe("dw_window_enable", &rexx_dw_window_enable);
+	RexxRegisterFunctionExe("dw_window_disable", &rexx_dw_window_disable);
+	RexxRegisterFunctionExe("dw_checkbox_query", &rexx_dw_checkbox_query);
+	RexxRegisterFunctionExe("dw_checkbox_set", &rexx_dw_checkbox_set);
+	RexxRegisterFunctionExe("dw_screen_width", &rexx_dw_screen_width);
+	RexxRegisterFunctionExe("dw_screen_height", &rexx_dw_screen_height);
+	RexxRegisterFunctionExe("dw_yesno", &rexx_dw_yesno);
+#if 0
+	RexxRegisterFunctionExe("dw_bitmapfile_new", &rexx_bitmapfile_new);
+	RexxRegisterFunctionExe("dw_bitmapfile_set_bitmap", &rexx_bitmapfile_set_bitmap);
+#endif
+	RexxRegisterFunctionExe("inst_grabfile", &rexx_grabfile);
+	RexxRegisterFunctionExe("inst_viewfile", &rexx_viewfile);
+	RexxRegisterFunctionExe("inst_mleview", &rexx_mleview);
+	RexxRegisterFunctionExe("inst_setdircontainer", &rexx_setdircontainer);
+	RexxRegisterFunctionExe("inst_setwindow", &rexx_setwindow);
+	RexxRegisterFunctionExe("inst_setbutton", &rexx_setbutton);
+	RexxRegisterFunctionExe("inst_setslider", &rexx_setslider);
+	RexxRegisterFunctionExe("inst_start", &rexx_start);
+	RexxRegisterFunctionExe("inst_packages", &rexx_packages);
+	RexxRegisterFunctionExe("inst_updateentry", &rexx_updateentry);
+	RexxRegisterFunctionExe("inst_savevar", &rexx_savevar);
+	RexxRegisterFunctionExe("inst_removevar", &rexx_removevar);
+	RexxRegisterFunctionExe("inst_findvar", &rexx_findvar);
+	RexxRegisterFunctionExe("inst_mesg", &rexx_mesg);
+	RexxRegisterFunctionExe("inst_querycheck", &rexx_querycheck);
+	RexxRegisterFunctionExe("inst_setdir", &rexx_setdir);
+	RexxRegisterFunctionExe("inst_querytext", &rexx_querytext);
+	RexxRegisterFunctionExe("inst_bitor", &rexx_bitor);
+	RexxRegisterFunctionExe("inst_reboot", &rexx_reboot);
+	RexxRegisterFunctionExe("inst_exit", &rexx_exit);
+	RexxRegisterFunctionExe("inst_save_pos", &rexx_save_pos);
+	RexxRegisterFunctionExe("inst_restore_pos", &rexx_restore_pos);
+	RexxRegisterFunctionExe("inst_chdir", &rexx_chdir);
+}
+
+void rexx_deinit(void)
+{
+	RexxDeregisterFunction("dw_box_pack_start");
+	RexxDeregisterFunction("dw_box_pack_end");
+	RexxDeregisterFunction("dw_box_new");
+	RexxDeregisterFunction("dw_groupbox_new");
+	RexxDeregisterFunction("dw_window_show");
+	RexxDeregisterFunction("dw_window_hide");
+	RexxDeregisterFunction("dw_window_destroy");
+	RexxDeregisterFunction("dw_window_set_font");
+	RexxDeregisterFunction("dw_window_set_color");
+	RexxDeregisterFunction("dw_window_new");
+	RexxDeregisterFunction("dw_bitmap_new");
+	RexxDeregisterFunction("dw_container_new");
+	RexxDeregisterFunction("dw_text_new");
+	RexxDeregisterFunction("dw_mle_new");
+	RexxDeregisterFunction("dw_entryfield_new");
+	RexxDeregisterFunction("dw_entryfield_password_new");
+	RexxDeregisterFunction("dw_combobox_new");
+	RexxDeregisterFunction("dw_button_new");
+	RexxDeregisterFunction("dw_spinbutton_new");
+	RexxDeregisterFunction("dw_percent_new");
+	RexxDeregisterFunction("dw_checkbox_new");
+	RexxDeregisterFunction("dw_radiobutton_new");
+	RexxDeregisterFunction("dw_listbox_new");
+	RexxDeregisterFunction("dw_listbox_append");
+	RexxDeregisterFunction("dw_listbox_select");
+	RexxDeregisterFunction("dw_listbox_selected");
+	RexxDeregisterFunction("dw_window_set_pos");
+	RexxDeregisterFunction("dw_window_set_usize");
+	RexxDeregisterFunction("dw_window_set_pos_size");
+	RexxDeregisterFunction("dw_window_set_style");
+	RexxDeregisterFunction("dw_window_set_icon");
+	RexxDeregisterFunction("dw_window_set_bitmap");
+	RexxDeregisterFunction("dw_window_set_text");
+	RexxDeregisterFunction("dw_window_enable");
+	RexxDeregisterFunction("dw_window_disable");
+	RexxDeregisterFunction("dw_checkbox_set");
+	RexxDeregisterFunction("dw_checkbox_query");
+	RexxDeregisterFunction("dw_screen_width");
+	RexxDeregisterFunction("dw_screen_height");
+	RexxDeregisterFunction("dw_yesno");
+#if 0
+	RexxDeregisterFunction("dw_bitmapfile_new");
+	RexxDeregisterFunction("dw_bitmapfile_set_bitmap");
+#endif
+	RexxDeregisterFunction("inst_grabfile");
+	RexxDeregisterFunction("inst_viewfile");
+	RexxDeregisterFunction("inst_mleview");
+	RexxDeregisterFunction("inst_setdircontainer");
+	RexxDeregisterFunction("inst_setwindow");
+	RexxDeregisterFunction("inst_setbutton");
+	RexxDeregisterFunction("inst_setslider");
+	RexxDeregisterFunction("inst_start");
+	RexxDeregisterFunction("inst_packages");
+	RexxDeregisterFunction("inst_updateentry");
+	RexxDeregisterFunction("inst_savevar");
+	RexxDeregisterFunction("inst_removevar");
+	RexxDeregisterFunction("inst_findvar");
+	RexxDeregisterFunction("inst_mesg");
+	RexxDeregisterFunction("inst_querycheck");
+	RexxDeregisterFunction("inst_setdir");
+	RexxDeregisterFunction("inst_querytext");
+	RexxDeregisterFunction("inst_bitor");
+	RexxDeregisterFunction("inst_reboot");
+	RexxDeregisterFunction("inst_exit");
+	RexxDeregisterFunction("inst_save_pos");
+	RexxDeregisterFunction("inst_restore_pos");
+	RexxDeregisterFunction("inst_chdir");
+}
+
+int rexx_run(char *filename)
+{
+	LONG rc;
+	SHORT retCode;
+	RXSTRING rxString;
+	RXSTRING args[1];
+	char tmpbuffer[50];
+	int b;
+	char *imagebuf;
+	RXSTRING instore[2];
+	static HMTX rexx_mtx;
+	static int firsttime = 1;
+	static DWTID threadid = (DWTID)-1;
+
+	if(strcasecmp(filename, "exit") == 0)
+	{
+		dw_window_destroy(mainhwnd);
+		exit(0);
+		return 0;
+	}
+
+	if(firsttime)
+	{
+		rexx_mtx = dw_mutex_new();
+		firsttime = 0;
+	}
+
+	dw_mutex_lock(rexx_mtx);
+	if(threadid != dw_thread_id())
+	{
+		rexx_init();
+		threadid = dw_thread_id();
+	}
+
+	rxString.strlength = 0;
+	rxString.strptr = NULL;
+
+	sprintf(tmpbuffer, "%lu", (ULONG)mainhwnd);
+	args[0].strlength = strlen(tmpbuffer);
+	args[0].strptr = malloc(args[0].strlength+1);
+	strcpy(args[0].strptr, tmpbuffer);
+
+	imagebuf = malloc(strlen(sysdefines) + strlen(platform) + strlen(INSTALLER_APPLICATION) + strlen(INSTALLER_VERSION)
+					  + strlen(INSTALLER_TITLE) + strlen(INSTALLER_PATH) + strlen(filename) + (_count_lines(sysdefines) * 16));
+
+	sprintf(imagebuf, sysdefines,
+			platform,
+			HWND_DESKTOP,
+			DW_FCF_TITLEBAR,
+			DW_FCF_SYSMENU,
+			DW_FCF_SIZEBORDER,
+			DW_FCF_MINBUTTON,
+			DW_FCF_MAXBUTTON,
+			DW_FCF_MINMAX,
+			DW_FCF_DLGBORDER,
+			DW_FCF_BORDER,
+			DW_FCF_SHELLPOSITION,
+			DW_FCF_TASKLIST,
+			DW_FCF_SYSMODAL,
+			DW_FCF_HIDEBUTTON,
+			DW_FCF_HIDEMAX,
+			DW_DT_LEFT,
+			DW_DT_UNDERSCORE,
+			DW_DT_STRIKEOUT,
+			DW_DT_CENTER,
+			DW_DT_RIGHT,
+			DW_DT_TOP,
+			DW_DT_VCENTER,
+			DW_DT_BOTTOM,
+			DW_DT_HALFTONE,
+			DW_DT_MNEMONIC,
+			DW_DT_WORDBREAK,
+			DW_CLR_WHITE,
+			DW_CLR_BLACK,
+			DW_CLR_BLUE,
+			DW_CLR_RED,
+			DW_CLR_PINK,
+			DW_CLR_GREEN,
+			DW_CLR_CYAN,
+			DW_CLR_YELLOW,
+			DW_CLR_DARKGRAY,
+			DW_CLR_DARKBLUE,
+			DW_CLR_DARKRED,
+			DW_CLR_DARKPINK,
+			DW_CLR_DARKGREEN,
+			DW_CLR_DARKCYAN,
+			DW_CLR_BROWN,
+			DW_CLR_PALEGRAY,
+			INSTALLER_APPLICATION,
+			INSTALLER_VERSION,
+			INSTALLER_TITLE,
+			INSTALLER_PATH);
+
+	imagebuf = grabimage(filename, imagebuf, strlen(imagebuf));
+
+	instore[0].strptr = imagebuf;
+	instore[0].strlength = strlen(imagebuf);
+	instore[1].strptr = NULL;
+	instore[1].strlength = 0;
+
+	rc = RexxStart(1, args, filename, instore, NULL, RXCOMMAND, NULL, &retCode, &rxString);
+
+	free(imagebuf);
+	free(args[0].strptr);
+
+	dw_mutex_unlock(rexx_mtx);
+
+	if(rc)
+	{
+		dw_messagebox("Installer", DW_MB_OK | DW_MB_ERROR, "%s error 0x%x (%d) executing REXX script \"%s\"", rc > 0 ? "System" : "Script", abs(rc), abs(rc), filename);
+		rexx_deinit();
+		exit(-1);
+	}
+
+	return retCode;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/finished.cmd	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,106 @@
+/* REXX script to create last installer dialog page. */
+
+if arg(1) > 0 then do
+        call inst_save_pos arg(1)
+        call dw_window_destroy arg(1)
+end
+
+flStyle = inst_bitor(DW_FCF_SYSMENU, DW_FCF_TITLEBAR, DW_FCF_SHELLPOSITION, DW_FCF_TASKLIST, DW_FCF_DLGBORDER)
+
+mainwindow = dw_window_new(HWND_DESKTOP, INSTALLER_TITLE, flStyle)
+
+/* This number must corespond to a resource ID in the bound resources */
+call dw_window_set_icon mainwindow, 2000
+
+bigbox = dw_box_new(BOXVERT, 10)
+
+call dw_box_pack_start mainwindow, bigbox, 0, 0, TRUE, TRUE, 0
+
+mainbox = dw_box_new(BOXHORZ, 0)
+
+call dw_box_pack_start bigbox, mainbox, 0, 0, TRUE, TRUE, 0
+
+logo = dw_bitmap_new(1001)
+
+/* This number must corespond to a resource ID in the bound resources */
+call dw_window_set_bitmap logo, 2001, ""
+
+call dw_box_pack_start mainbox, logo, 100, 275, FALSE, FALSE, 10
+
+custombox = dw_box_new(BOXVERT, 0)
+
+call dw_box_pack_start mainbox, custombox, 0, 0, TRUE, TRUE, 0
+
+stext = dw_text_new(INSTALLER_APPLICATION || " " || INSTALLER_VERSION || " installation finished.", 0)
+
+call dw_window_set_style stext, DW_DT_VCENTER, DW_DT_VCENTER
+
+call dw_box_pack_start custombox, stext, 300, 15, TRUE, TRUE, 10
+
+desctext = dw_text_new("Thanks for trying " || INSTALLER_APPLICATION || " " || INSTALLER_VERSION || "! Press finish to exit the installation program.",0)
+
+call dw_window_set_style desctext, DW_DT_WORDBREAK, DW_DT_WORDBREAK
+
+call dw_box_pack_start custombox, desctext, 300, 60, TRUE, TRUE, 10
+
+groupbox = dw_groupbox_new(BOXVERT, 20, "Reboot?")
+
+call dw_box_pack_start custombox, groupbox, 0, 0, TRUE, TRUE, 0
+
+rnow = dw_radiobutton_new("Reboot Now", 0)
+
+call dw_box_pack_start groupbox, rnow, 50, 25, TRUE, TRUE, 0
+
+rlater = dw_radiobutton_new("Reboot Later", 0)
+
+call dw_box_pack_start groupbox, rlater, 50, 25, TRUE, TRUE, 0
+
+call inst_savevar "rnow", rnow
+call inst_savevar "rlater", rlater
+
+call dw_checkbox_set rnow, 1
+
+call dw_box_pack_start custombox, 0, 300, 70, TRUE, TRUE, 10
+
+buttonbox = dw_box_new(BOXHORZ, 5)
+
+call dw_box_pack_start bigbox, buttonbox, 0, 0, TRUE, FALSE, 0
+
+exitbutton = dw_button_new("Exit Installer", 1003)
+
+call inst_setbutton exitbutton, "exit"
+
+call dw_box_pack_start buttonbox, exitbutton, 100, 30, TRUE, FALSE, 0
+
+blanktext = dw_text_new("", 0)
+
+call dw_box_pack_start buttonbox, blanktext, 150, 30, TRUE, FALSE, 0
+
+backbutton = dw_button_new("<< Back", 1002)
+
+call dw_window_disable backbutton
+
+call dw_box_pack_start buttonbox, backbutton, 60, 30, TRUE, FALSE, 0
+
+nextbutton = dw_button_new("Finish", 1001)
+
+call inst_setbutton nextbutton, "reboot.cmd"
+
+call dw_box_pack_start buttonbox, nextbutton, 60, 30, TRUE, FALSE, 0
+
+/* Set some nice fonts and colors */
+if PLATFORM = "OS2" then do
+   call dw_window_set_font stext, "9.WarpSans Bold"
+end
+if PLATFORM = "WIN32" then do
+   call dw_window_set_font stext, "14.Arial Bold"
+end
+
+call inst_restore_pos mainwindow
+
+call dw_window_show mainwindow
+
+call inst_setwindow mainwindow 
+
+exit
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/license.txt	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,1 @@
+This is a sample license file.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/page1.cmd	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,108 @@
+/* REXX script to create first installer dialog page. */
+
+if arg(1) > 0 then do
+        call inst_save_pos arg(1)
+        call dw_window_destroy arg(1)
+end
+
+flStyle = inst_bitor(DW_FCF_SYSMENU, DW_FCF_TITLEBAR, DW_FCF_SHELLPOSITION, DW_FCF_TASKLIST, DW_FCF_DLGBORDER)
+
+mainwindow = dw_window_new(HWND_DESKTOP, INSTALLER_TITLE, flStyle)
+
+/* This number must corespond to a resource ID in the bound resources */
+call dw_window_set_icon mainwindow, 2000
+
+bigbox = dw_box_new(BOXVERT, 10)
+
+call dw_box_pack_start mainwindow, bigbox, 0, 0, TRUE, TRUE, 0
+
+mainbox = dw_box_new(BOXHORZ, 0)
+
+call dw_box_pack_start bigbox, mainbox, 0, 0, TRUE, TRUE, 0
+
+logo = dw_bitmap_new(1001)
+
+/* This number must corespond to a resource ID in the bound resources */
+call dw_window_set_bitmap logo, 2001, ""
+
+call dw_box_pack_start mainbox, logo, 100, 275, FALSE, FALSE, 10
+
+custombox = dw_box_new(BOXVERT, 0)
+
+call dw_box_pack_start mainbox, custombox, 0, 0, TRUE, TRUE, 0
+
+stext = dw_text_new("Welcome to " || INSTALLER_APPLICATION || " " || INSTALLER_VERSION, 0)
+
+call dw_window_set_style stext, DW_DT_VCENTER, DW_DT_VCENTER
+
+call dw_box_pack_start custombox, stext, 300, 15, TRUE, TRUE, 10
+
+mle = dw_mle_new(100)
+
+call inst_mleview "license.txt", mle
+
+call dw_box_pack_start custombox, mle, 300, 200, TRUE, TRUE, 10
+
+checkbox = dw_checkbox_new("I accept the terms of this license.", 2020)
+
+call dw_box_pack_start custombox, checkbox, 300, 20, TRUE, TRUE, 10
+
+buttonbox = dw_box_new(BOXHORZ, 5)
+
+call dw_box_pack_start bigbox, buttonbox, 0, 0, TRUE, FALSE, 0
+
+exitbutton = dw_button_new("Exit Installer", 1003)
+
+call inst_setbutton exitbutton, "exit"
+
+call dw_box_pack_start buttonbox, exitbutton, 100, 30, TRUE, FALSE, 0
+
+blanktext = dw_text_new("", 0)
+
+call dw_box_pack_start buttonbox, blanktext, 150, 30, TRUE, FALSE, 0
+
+backbutton = dw_button_new("<< Back", 1002)
+
+call dw_window_disable backbutton
+
+call dw_box_pack_start buttonbox, backbutton, 60, 30, TRUE, FALSE, 0
+
+nextbutton = dw_button_new("Next >>", 1001)
+
+call inst_setbutton nextbutton, "page2.cmd"
+
+call dw_box_pack_start buttonbox, nextbutton, 60, 30, TRUE, FALSE, 0
+
+call inst_savevar "checkbox", checkbox
+call inst_savevar "frompage", "1"
+
+ischecked = inst_findvar("ischecked")
+
+if ischecked > 0 then
+        call dw_checkbox_set checkbox, 1
+
+/* Set some nice fonts and colors */
+if PLATFORM = "OS2" then do
+   call dw_window_set_font stext, "9.WarpSans Bold"
+end
+if PLATFORM = "WIN32" then do
+   call dw_window_set_font stext, "14.Arial Bold"
+end
+
+newx = (dw_screen_width()-550)/2
+newy = (dw_screen_height()-375)/2
+
+firstrun = inst_findvar("firstrun")
+
+if firstrun > 0 then
+   call inst_restore_pos mainwindow
+else
+   call dw_window_set_pos_size mainwindow, newx, newy, 550, 375
+
+call inst_savevar "firstrun", 1
+
+call dw_window_show mainwindow
+
+call inst_setwindow mainwindow
+
+exit
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/page2.cmd	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,122 @@
+/* REXX script to create second installer dialog page. */
+
+/* Read the checkbox variable we saved from the first script */
+checkbox = inst_findvar("checkbox")
+
+frompage = inst_findvar("frompage")
+
+if frompage = 1 then do
+   if inst_querycheck(checkbox) = 0 then do
+        call inst_mesg "Please accept the terms of the agreement or exit."
+        exit 0
+   end /* do */
+   call inst_savevar "ischecked", 1
+end
+
+installdir = inst_findvar("installdir")
+
+if arg(1) > 0 then do
+        call inst_save_pos arg(1)
+        call dw_window_destroy arg(1)
+end
+
+flStyle = inst_bitor(DW_FCF_SYSMENU, DW_FCF_TITLEBAR, DW_FCF_SHELLPOSITION, DW_FCF_TASKLIST, DW_FCF_DLGBORDER)
+
+mainwindow = dw_window_new(HWND_DESKTOP, INSTALLER_TITLE, flStyle)
+
+/* This number must corespond to a resource ID in the bound resources */
+call dw_window_set_icon mainwindow, 2000
+
+bigbox = dw_box_new(BOXVERT, 10)
+
+call dw_box_pack_start mainwindow, bigbox, 0, 0, TRUE, TRUE, 0
+
+mainbox = dw_box_new(BOXHORZ, 0)
+
+call dw_box_pack_start bigbox, mainbox, 0, 0, TRUE, TRUE, 0
+
+logo = dw_bitmap_new(1001)
+
+/* This number must corespond to a resource ID in the bound resources */
+call dw_window_set_bitmap logo, 2001, ""
+
+call dw_box_pack_start mainbox, logo, 100, 275, FALSE, FALSE, 10
+
+custombox = dw_box_new(BOXVERT, 10)
+
+call dw_box_pack_start mainbox, custombox, 0, 0, TRUE, TRUE, 0
+
+stext = dw_text_new("Choose installation directory", 0)
+
+call dw_window_set_style stext, DW_DT_VCENTER, DW_DT_VCENTER
+
+call dw_box_pack_start custombox, stext, 300, 15, TRUE, TRUE, 2
+
+if installdir == "" then
+    entryfield = dw_entryfield_new(INSTALLER_PATH, 104)
+else
+    entryfield = dw_entryfield_new(installdir, 104)
+
+call inst_savevar "entryfield", entryfield
+
+call dw_box_pack_start custombox, entryfield, 300, 20, TRUE, FALSE, 2
+
+container = dw_container_new(106)
+
+call dw_box_pack_start custombox, container, 300, 200, TRUE, TRUE, 2
+
+if PLATFORM = "OS2" | PLATFORM = "WIN32" then do
+    combobox = dw_combobox_new("", 105)
+
+    call dw_box_pack_start custombox, combobox, 300, 22, TRUE, FALSE, 2
+end
+else do
+    combobox = 0
+end
+
+buttonbox = dw_box_new(BOXHORZ, 5)
+
+call dw_box_pack_start bigbox, buttonbox, 0, 0, TRUE, FALSE, 0
+
+exitbutton = dw_button_new("Exit Installer", 1003)
+
+call inst_setbutton exitbutton, "exit"
+
+call dw_box_pack_start buttonbox, exitbutton, 100, 30, TRUE, FALSE, 0
+
+blanktext = dw_text_new("", 0)
+
+call dw_box_pack_start buttonbox, blanktext, 150, 30, TRUE, FALSE, 0
+
+backbutton = dw_button_new("<< Back", 1002)
+
+call inst_setbutton backbutton, "page1.cmd"
+
+call dw_box_pack_start buttonbox, backbutton, 60, 30, TRUE, FALSE, 0
+
+nextbutton = dw_button_new("Next >>", 1001)
+
+call inst_setbutton nextbutton, "page3.cmd"
+
+call dw_box_pack_start buttonbox, nextbutton, 60, 30, TRUE, FALSE, 0
+
+/* Set some nice fonts and colors */
+if PLATFORM = "OS2" then do
+   call dw_window_set_font stext, "9.WarpSans Bold"
+end
+if PLATFORM = "WIN32" then do
+   call dw_window_set_font stext, "14.Arial Bold"
+end
+
+call inst_savevar "frompage", "2"
+
+call inst_setdircontainer container, entryfield, combobox
+
+call inst_restore_pos mainwindow
+
+call dw_window_show mainwindow
+
+call inst_setwindow mainwindow
+
+exit
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/page3.cmd	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,107 @@
+/* REXX script to create third installer dialog page. */
+
+entryfield = inst_findvar("entryfield")
+
+installdir = inst_querytext(entryfield)
+
+call inst_savevar "installdir", installdir
+
+call inst_updateentry installdir
+
+if arg(1) > 0 then do
+        call inst_save_pos arg(1)
+        call dw_window_destroy arg(1)
+end
+
+flStyle = inst_bitor(DW_FCF_SYSMENU, DW_FCF_TITLEBAR, DW_FCF_SHELLPOSITION, DW_FCF_TASKLIST, DW_FCF_DLGBORDER)
+
+mainwindow = dw_window_new(HWND_DESKTOP, INSTALLER_TITLE, flStyle)
+
+/* This number must corespond to a resource ID in the bound resources */
+call dw_window_set_icon mainwindow, 2000
+
+bigbox = dw_box_new(BOXVERT, 10)
+
+call dw_box_pack_start mainwindow, bigbox, 0, 0, TRUE, TRUE, 0
+
+mainbox = dw_box_new(BOXHORZ, 0)
+
+call dw_box_pack_start bigbox, mainbox, 0, 0, TRUE, TRUE, 0
+
+logo = dw_bitmap_new(1001)
+
+/* This number must corespond to a resource ID in the bound resources */
+call dw_window_set_bitmap logo, 2001, ""
+
+call dw_box_pack_start mainbox, logo, 100, 275, FALSE, FALSE, 10
+
+custombox = dw_box_new(BOXVERT, 0)
+
+call dw_box_pack_start mainbox, custombox, 0, 0, TRUE, TRUE, 0
+
+stext = dw_text_new("Ready to begin installation.", 0)
+
+call dw_window_set_style stext, DW_DT_VCENTER, DW_DT_VCENTER
+
+call dw_box_pack_start custombox, stext, 300, 20, TRUE, TRUE, 10
+
+desctext = dw_text_new("Thanks for trying " || INSTALLER_APPLICATION || ".  Feel free to contact me at dbsoft@technologist.com with comments, questions or bug reports.",0)
+
+call dw_window_set_style desctext, DW_DT_WORDBREAK, DW_DT_WORDBREAK
+
+call dw_box_pack_start custombox, desctext, 300, 100, TRUE, TRUE, 10
+
+readmebutton = dw_button_new("View Readme", 1005)
+
+call dw_box_pack_start custombox, readmebutton, 300, 30, TRUE, FALSE, 10
+
+call inst_setbutton readmebutton, "readme.cmd"
+
+blanktext = dw_text_new("", 0)
+
+call dw_box_pack_start custombox, blanktext, 300, 100, TRUE, TRUE, 10
+
+buttonbox = dw_box_new(BOXHORZ, 5)
+
+call dw_box_pack_start bigbox, buttonbox, 0, 0, TRUE, FALSE, 0
+
+exitbutton = dw_button_new("Exit Installer", 1003)
+
+call inst_setbutton exitbutton, "exit"
+
+call dw_box_pack_start buttonbox, exitbutton, 100, 30, TRUE, FALSE, 0
+
+blanktext = dw_text_new("", 0)
+
+call dw_box_pack_start buttonbox, blanktext, 150, 30, TRUE, FALSE, 0
+
+backbutton = dw_button_new("<< Back", 1002)
+
+call dw_box_pack_start buttonbox, backbutton, 60, 30, TRUE, FALSE, 0
+
+call inst_setbutton backbutton, "page2.cmd"
+
+nextbutton = dw_button_new("Start", 1001)
+
+call inst_setbutton nextbutton, "page4.cmd"
+
+call dw_box_pack_start buttonbox, nextbutton, 60, 30, TRUE, FALSE, 0
+
+/* Set some nice fonts and colors */
+if PLATFORM = "OS2" then do
+   call dw_window_set_font stext, "9.WarpSans Bold"
+end
+if PLATFORM = "WIN32" then do
+   call dw_window_set_font stext, "14.Arial Bold"
+end
+
+call inst_savevar "frompage", "3"
+
+call inst_restore_pos mainwindow
+
+call dw_window_show mainwindow
+
+call inst_setwindow mainwindow
+
+exit
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/page4.cmd	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,104 @@
+/* REXX script to create fourth installer dialog page. */
+
+if inst_packages() < 1 then
+        exit
+
+if arg(1) > 0 then do
+        call inst_save_pos arg(1)
+        call dw_window_destroy arg(1)
+end
+
+flStyle = inst_bitor(DW_FCF_SYSMENU, DW_FCF_TITLEBAR, DW_FCF_SHELLPOSITION, DW_FCF_TASKLIST, DW_FCF_DLGBORDER)
+
+mainwindow = dw_window_new(HWND_DESKTOP, INSTALLER_TITLE, flStyle)
+
+/* This number must corespond to a resource ID in the bound resources */
+call dw_window_set_icon mainwindow, 2000
+
+bigbox = dw_box_new(BOXVERT, 10)
+
+call dw_box_pack_start mainwindow, bigbox, 0, 0, TRUE, TRUE, 0
+
+mainbox = dw_box_new(BOXHORZ, 0)
+
+call dw_box_pack_start bigbox, mainbox, 0, 0, TRUE, TRUE, 0
+
+logo = dw_bitmap_new(1001)
+
+/* This number must corespond to a resource ID in the bound resources */
+call dw_window_set_bitmap logo, 2001, ""
+
+call dw_box_pack_start mainbox, logo, 100, 275, FALSE, FALSE, 10
+
+custombox = dw_box_new(BOXVERT, 0)
+
+call dw_box_pack_start mainbox, custombox, 0, 0, TRUE, TRUE, 0
+
+stext = dw_text_new("Please wait while installing " || INSTALLER_APPLICATION || " " || INSTALLER_VERSION || "...", 0)
+
+call dw_window_set_style stext, DW_DT_VCENTER, DW_DT_VCENTER
+
+call dw_box_pack_start custombox, stext, 300, 50, TRUE, TRUE, 10
+
+groupbox = dw_groupbox_new(BOXHORZ, 10, "Progress")
+
+call dw_box_pack_start custombox, groupbox, 0, 0, TRUE, FALSE, 10
+
+slider = dw_percent_new(1010)
+
+call dw_box_pack_start groupbox, slider, 300, 20, TRUE, FALSE, 10
+
+status = dw_text_new("", 0)
+
+call dw_box_pack_start custombox, status, 300, 50, TRUE, TRUE, 10
+
+call dw_box_pack_start custombox, 0, 300, 100, TRUE, TRUE, 10
+
+call inst_setslider slider, status
+
+buttonbox = dw_box_new(BOXHORZ, 5)
+
+call dw_box_pack_start bigbox, buttonbox, 0, 0, TRUE, FALSE, 0
+
+exitbutton = dw_button_new("Exit Installer", 1003)
+
+call inst_setbutton exitbutton, "exit"
+
+call dw_box_pack_start buttonbox, exitbutton, 100, 30, TRUE, FALSE, 0
+
+blanktext = dw_text_new("", 0)
+
+call dw_box_pack_start buttonbox, blanktext, 150, 30, TRUE, FALSE, 0
+
+backbutton = dw_button_new("<< Back", 1002)
+
+call dw_window_disable backbutton
+
+call dw_box_pack_start buttonbox, backbutton, 60, 30, TRUE, FALSE, 0
+
+nextbutton = dw_button_new("Next >>", 1001)
+
+call dw_window_disable nextbutton
+
+call dw_box_pack_start buttonbox, nextbutton, 60, 30, TRUE, FALSE, 0
+
+/* Set some nice fonts and colors */
+if PLATFORM = "OS2" then do
+   call dw_window_set_font stext, "9.WarpSans Bold"
+end
+if PLATFORM = "WIN32" then do
+   call dw_window_set_font stext, "14.Arial Bold"
+end
+
+call inst_savevar "frompage", "4"
+
+call inst_restore_pos mainwindow
+
+call dw_window_show mainwindow
+
+call inst_setwindow mainwindow
+
+call inst_start "finished.cmd"
+
+exit
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/readme.cmd	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,6 @@
+/* This handles the Readme dialog */
+
+call inst_viewfile "readme.txt"
+
+exit
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/readme.txt	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,1 @@
+This is a sample readme file.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/reboot.cmd	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,17 @@
+/* REXX script to create last installer dialog page. */
+
+rnow = inst_findvar("rnow")
+rlater = inst_findvar("rlater")
+
+rebootflag = dw_checkbox_query(rnow)
+
+if arg(1) > 0 then
+        call dw_window_destroy arg(1)
+
+if rebootflag > 0 then
+        call inst_reboot
+
+call inst_exit
+
+exit
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxace/Makefile.in	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,44 @@
+# Installer Makefile
+
+CC = @CC@
+RM = @RM@ -f
+MAKE = @MAKE@
+
+DEFS =
+LIBS = @LIBS@ -lregina
+
+CFLAGS = -I../incace -D__UNIX__ -I.. @CFLAGS@
+LDFLAGS = 
+
+OBJECTS = globals.o install.o uac_comm.o uac_crc.o instsup.o \
+          uac_crt.o uac_dcpr.o uac_sys.o unace.o rexx.o dw.o resources.o
+
+SOURCES = globals.c ../install.c uac_comm.c uac_crc.c ../instsup.c \
+          uac_crt.c uac_dcpr.c uac_sys.c unace.c rexx.c ../gtk/dw.o ../gtk/resources.c
+
+all: sfx
+
+$(OBJECTS):
+	$(CC) $(CFLAGS) -c $<	
+
+sfx:  $(OBJECTS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $(DEFS) -o sfx $(OBJECTS) $(LIBS)
+
+clean: 
+	$(RM) $(OBJECTS) install sfx *~
+
+globals.o: globals.c ../incace/globals.h ../incace/acestruc.h ../incace/unace.h
+install.o: ../install.c ../install.h ../instsup.h
+instsup.o: ../instsup.c
+uac_comm.o: uac_comm.c ../incace/globals.h ../incace/uac_dcpr.h ../incace/uac_comm.h
+uac_crc.o: uac_crc.c ../incace/uac_crc.h
+uac_crt.o: uac_crt.c ../incace/os.h ../incace/attribs.h ../incace/globals.h ../incace/uac_crt.h ../incace/uac_sys.h
+uac_dcpr.o: uac_dcpr.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h \
+	      ../incace/uac_dcpr.h ../incace/uac_sys.h
+uac_sys.o: uac_sys.c ../incace/os.h ../incace/globals.h ../incace/uac_sys.h
+unace.o: unace.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h ../incace/uac_crt.h \
+           ../incace/uac_dcpr.h ../incace/uac_sys.h
+rexx.o: ../rexx.c ../gtk/dw.c ../dw.h
+dw.o: ../gtk/dw.c ../dw.h
+resources.o: ../gtk/resources.c ../install.h
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxace/globals.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,137 @@
+/* ------------------------------------------------------------------------ */
+/*                                                                          */
+/*      Global variable declarations                                        */
+/*                                                                          */
+/* ------------------------------------------------------------------------ */
+
+#include "os.h"
+
+#if defined(__CYGWIN__)
+#include <Windows32/Base.h>
+#endif 
+#include "acestruc.h"
+#include "unace.h"
+#include <string.h>
+#include <stdio.h>
+
+//-------- Ace sign
+const char *acesign = "**ACE**";
+
+//-------- Version string for program
+const char *version="UNACE v1.1    public version\n";
+
+#ifdef AMIGA
+//-------- Version string for VERSION program
+static char *_version="$VER: Unace Amiga 1.1  "__AMIGADATE__"\n\n";
+#endif
+
+//-------- header buffer and pointers
+thead head;
+
+tmhead *t_mhead = (tmhead *) & head;
+tfhead *t_fhead = (tfhead *) & head;
+
+//-------- buffers
+ULONG *buf_rd        =0;
+CHAR  *buf           =0;
+CHAR  *buf_wr        =0;
+UCHAR *readbuf       =0;
+
+//-------- decompressor variables
+SHORT rpos           =0,
+      dcpr_do        =0,
+      dcpr_do_max    =0,
+      blocksize      =0,
+      dcpr_dic       =0,
+      dcpr_oldnum    =0,
+      bits_rd        =0,
+      dcpr_frst_file =0;
+USHORT dcpr_code_mn[1 << maxwd_mn],
+       dcpr_code_lg[1 << maxwd_lg];
+UCHAR dcpr_wd_mn[maxcode + 2],
+      dcpr_wd_lg[maxcode + 2],
+      wd_svwd[svwd_cnt];
+ULONG dcpr_dpos      =0,
+      cpr_dpos2      =0,
+      dcpr_dicsiz    =0,
+      dcpr_dican     =0,
+      dcpr_size      =0,
+      dcpr_olddist[4]={0,0,0,0},
+      code_rd        =0;
+
+CHAR *dcpr_text      =0;
+
+//-------- quicksort
+USHORT sort_org[maxcode + 2];
+UCHAR sort_freq[(maxcode + 2) * 2];
+
+//-------- file handling
+CHAR aname[PATH_MAX];
+INT  archan,
+	wrhan;
+#if !defined(__EMX__) && !defined(__OS2__)
+FILE *farchan = NULL;
+#endif
+
+LONG skipsize=0;
+
+//-------- structures for archive handling
+struct tadat adat;
+
+//-------- flags
+INT  f_err      =0,
+     f_ovrall   =0,
+     f_allvol_pr=0,
+     f_curpas   =0,
+     f_criterr  =0;
+
+
+void resetglobals(void)
+{
+	t_mhead = (tmhead *) & head;
+	t_fhead = (tfhead *) & head;
+
+	buf_rd        =0;
+	buf           =0;
+	buf_wr        =0;
+	readbuf       =0;
+
+	rpos           =0;
+	dcpr_do        =0;
+	dcpr_do_max    =0;
+	blocksize      =0;
+	dcpr_dic       =0;
+	dcpr_oldnum    =0;
+	bits_rd        =0;
+	dcpr_frst_file =0;
+
+	memset(&dcpr_code_mn, 0, sizeof(dcpr_code_mn));
+	memset(&dcpr_code_lg, 0, sizeof(dcpr_code_lg));
+	memset(&dcpr_wd_mn, 0, sizeof(dcpr_wd_mn));
+	memset(&dcpr_wd_lg, 0, sizeof(dcpr_wd_lg));
+	memset(&wd_svwd, 0, sizeof(wd_svwd));
+	dcpr_dpos      =0;
+	cpr_dpos2      =0;
+	dcpr_dicsiz    =0;
+	dcpr_dican     =0;
+	dcpr_size      =0;
+
+	memset(&dcpr_olddist, 0, sizeof(dcpr_olddist));
+
+	code_rd        =0;
+	dcpr_text      =0;
+
+	memset(&sort_org, 0, sizeof(sort_org));
+	memset(&sort_freq, 0, sizeof(sort_freq));
+
+	archan=0;
+	wrhan=0;
+	skipsize=0;
+
+	f_err      =0;
+	f_ovrall   =0;
+	f_allvol_pr=0;
+	f_curpas   =0;
+	f_criterr  =0;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxace/install.PRJ	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,50 @@
+[Project ID]
+Signature=UE Proj: v.1
+[Files]
+0=C:\Program Files\wx2\samples\Install\install.c
+1=C:\Program Files\wx2\samples\Install\install.h
+2=C:\Program Files\wx2\samples\Install\instsup.c
+3=C:\Program Files\wx2\samples\Install\makefile
+4=C:\Program Files\wx2\samples\Install\wxmain.cpp
+[Open Files]
+Open File0=C:\Program Files\wx2\samples\Install\makefile
+Open File Pos0=2487
+Open File Line0=1545
+Open File Window Pos0=0,1,0,0,-4,-23,22,22,646,423
+Open File1=C:\Program Files\wx2\samples\Install\wxmain.cpp
+Open File Pos1=2953
+Open File Line1=0
+Open File Window Pos1=0,1,0,0,-4,-23,110,110,734,511
+Open File2=C:\Program Files\wx2\samples\Install\install.c
+Open File Pos2=9875
+Open File Line2=9111
+Open File Window Pos2=0,1,0,0,-4,-23,176,176,800,577
+Open File3=C:\insttmp\winbitchx.cfg
+Open File Pos3=229
+Open File Line3=0
+Open File Window Pos3=0,1,0,0,-4,-23,0,0,612,364
+Open File4=C:\Program Files\wx2\samples\Install\instsup.cpp
+Open File Pos4=2
+Open File Line4=0
+Open File Window Pos4=0,1,0,0,-4,-23,154,154,788,507
+Open File5=C:\Program Files\wx2\samples\controls\controls.cpp
+Open File Pos5=34608
+Open File Line5=34168
+Open File Window Pos5=2,3,0,0,-4,-23,88,88,722,437
+Open File6=
+Open File Pos6=203
+Open File Line6=0
+Open File Window Pos6=0,1,0,0,-4,-23,154,154,788,502
+Open File7=C:\Program Files\wx2\src\makeg95.env
+Open File Pos7=357
+Open File Line7=0
+Open File Window Pos7=0,1,0,0,-4,-23,0,0,634,348
+Open File8=c:\error.log
+Open File Pos8=0
+Open File Line8=0
+Active File Index=5
+Open File Window Pos8=2,3,0,0,-4,-23,22,22,656,370
+Open File9=
+Active File Display Mode=3
+[File View]
+Current Select=Open Files\
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxace/makefile.b32	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,76 @@
+#
+# File:		makefile.b32
+# Author:	Julian Smart
+# Created:	1999
+# Updated:	
+# Copyright:
+#
+# Makefile : Builds sample for 32-bit BC++
+
+WXDIR = $(WXWIN)
+
+EXTRACPPFLAGS = /I"..\incace" /I".."
+TARGET=sfx
+OBJECTS = wxmain.obj instsup.obj install.obj globals.obj uac_comm.obj uac_crc.obj uac_crt.obj uac_dcpr.obj uac_sys.obj unace.obj
+
+WXDIR = $(WXWIN)
+!include $(WXDIR)\src\makeb32.env
+
+LIBS=$(WXLIB) $(EXTRALIBS) cw32mt import32 ole2w32 winpng zlib jpeg xpm tiff odbc32
+
+# Note: you may need to remove some libraries for earlier versions of BC++, as below
+#LIBS=$(WXLIB) $(EXTRALIBS) cw32mt import32 ole2w32 winpng zlib xpm tiff
+
+!if "$(FINAL)" == "0"
+#LINKFLAGS=/v /c /Tpe $(LNKCFG) $(EXTRALINKFLAGS)
+LINKFLAGS=/v /c /aa -L$(WXLIBDIR);$(WXLIBDIR2);$(BCCDIR)\lib;$(BCCDIR)\lib\psdk $(EXTRALINKFLAGS)
+OPT = -Od
+DEBUG_FLAGS= -v
+!else
+#LINKFLAGS=/Tpe +$(LNKCFG) $(EXTRALINKFLAGS)
+LINKFLAGS=/aa -L$(WXLIBDIR);$(WXLIBDIR2);$(BCCDIR)\lib;$(BCCDIR)\lib\psdk $(EXTRALINKFLAGS)
+OPT = -O2
+DEBUG_FLAGS =
+!endif
+
+CPPFLAGS=$(DEBUG_FLAGS) $(EXTRACPPFLAGS) $(OPT) @$(CFG)
+
+all: $(TARGET).exe $(EXTRATARGETS)
+
+$(TARGET).exe:	$(OBJECTS) $(TARGET).res
+  $(LINK) $(LINKFLAGS) @&&!
+c0w32.obj $(OBJECTS)
+$(TARGET)
+nul
+$(LIBS)
+
+$(TARGET).res
+!
+
+.$(SRCSUFF).obj:
+	bcc32 $(CPPFLAGS) -c {$< }
+
+install.obj: ..\install.c
+	bcc32 $(CPPFLAGS) -P- -c ..\install.c
+        
+wxmain.obj: ..\wxmain.cpp
+	bcc32 $(CPPFLAGS) -P- -c ..\wxmain.cpp
+        
+instsup.obj: ..\instsup.cpp
+	bcc32 $(CPPFLAGS) -P- -c ..\instsup.cpp
+        
+.c.obj:
+	bcc32 $(CPPFLAGS) -P- -c {$< }
+
+$(TARGET).res :      $(TARGET).rc $(WXDIR)\include\wx\msw\wx.rc
+	    brc32 -r /i$(BCCDIR)\include /i$(WXDIR)\include /i$(WXDIR)\contrib\include $(TARGET)
+
+clean:
+        -erase *.obj
+        -erase *.exe
+        -erase *.res
+        -erase *.map
+        -erase *.rws
+        -erase *.tds
+        -erase *.il?
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxace/makefile.emx	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,60 @@
+# $Id: makefile.emx,v 1.1 2001/04/03 22:18:21 bsmith Exp $ 
+
+# Installer Makefile
+
+CC = gcc
+RM = rm -f
+RC = rc
+MAKE = make
+COMPRESS = lxlite
+
+DEFS =
+LIBS =
+
+CFLAGS = -O2 -Zomf -Zsys -Zmt -D__ST_MT_ERRNO__ -I./include -Wall -DNO_SIGNALS
+LDFLAGS = -lrexx
+RCFLAGS = -r
+
+
+OBJECTS = globals.obj install.obj uac_comm.obj uac_crc.obj instsup.obj \
+          uac_crt.obj uac_dcpr.obj uac_sys.obj unace.obj dw.obj rexx.obj \
+          picture.obj
+
+SOURCES = globals.c install.c uac_comm.c uac_crc.c instsup.c \
+          uac_crt.c uac_dcpr.c uac_sys.c unace.c dw.c rexx.c \
+          picture.c
+
+#all: sfx.exe packinst
+all: sfx.exe
+
+$(OBJECTS):
+	$(CC) $(CFLAGS) -c $<	
+
+packinst: packinst/Makefile Makefile
+	@cd packinst
+	$(MAKE) -f Makefile all
+
+sfx.exe:  $(OBJECTS)
+	$(RC) $(RCFLAGS) install.rc
+	$(CC) $(CFLAGS) $(LDFLAGS) $(DEFS) -o sfx.exe $(OBJECTS) install.def install.res
+	$(COMPRESS) sfx.exe
+
+clean: 
+	$(RM) $(OBJECTS) install.exe install.res sfx.exe
+
+globals.obj: globals.c include/globals.h include/acestruc.h include/unace.h
+install.obj: install.c install.h instsup.h
+instsup.obj: instsup.c
+rexx.obj: rexx.c
+uac_comm.obj: uac_comm.c include/globals.h include/uac_dcpr.h include/uac_comm.h
+uac_crc.obj: uac_crc.c include/uac_crc.h
+uac_crt.obj: uac_crt.c include/os.h include/attribs.h include/globals.h include/uac_crt.h include/uac_sys.h
+uac_dcpr.obj: uac_dcpr.c include/os.h include/globals.h include/portable.h include/uac_comm.h include/uac_crc.h \
+	      include/uac_dcpr.h include/uac_sys.h
+uac_sys.obj: uac_sys.c include/os.h include/globals.h include/uac_sys.h
+unace.obj: unace.c include/os.h include/globals.h include/portable.h include/uac_comm.h include/uac_crc.h include/uac_crt.h \
+           include/uac_dcpr.h include/uac_sys.h
+dw.obj: dw.c
+picture.obj: picture.c picture.h
+install.res: install.rc install.h
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxace/makefile.g95	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,53 @@
+# Installer Makefile
+
+CC = gcc
+RM = rm -f
+RC = windres
+
+
+DEFS =
+LIBS = ../../../lib/libwx.a -lpng -ljpeg -lzlib -lxpm -lstdc++ -lgcc -lwinspool -lwinmm -lshell32 -lcomctl32 -lctl3d32 -lodbc32 -ladvapi32 -lole32 -loleaut32 -luuid -lodbc32 -lwsock32
+
+#CFLAGS = -I./include -mno-cygwin -D_X86_=1 -DWIN32 -D_WIN32 -DWINVER=0x0400 -D__WIN95__ -D__GNUWIN32__ -D__WIN32__ -I../../include -I../../src/png -I../../src/jpeg -I../../src/zlib   -I../../include/wx/msw/gnuwin32  -DSTRICT  -D__WXMSW__ -D__WINDOWS__ -D__WXDEBUG__ -Wall -fno-pcc-struct-return -O2 -fno-rtti -fno-exceptions
+#LDFLAGS = -mno-cygwin -Wl,--subsystem,windows -mwindows -L../../lib
+CFLAGS = -g -I../incace -I.. -D_X86_=1 -DWIN32 -D_WIN32 -DWINVER=0x0400 -D__WIN95__ -D__GNUWIN32__ -D__WIN32__ -I../../../include -I../../../src/png -I../../../src/jpeg -I../../../src/zlib   -I../../../include/wx/msw/gnuwin32  -DSTRICT  -D__WXMSW__ -D__WINDOWS__ -D__WXDEBUG__ -Wall -fno-pcc-struct-return -O2 -fno-rtti -fno-exceptions
+LDFLAGS = -Wl,--subsystem,windows -mwindows -L../../../lib
+
+OBJECTS = globals.o install.o uac_comm.o uac_crc.o instsup.o \
+          uac_crt.o uac_dcpr.o uac_sys.o unace.o wxmain.o instres.o
+
+SOURCES = globals.c ../install.c uac_comm.c uac_crc.c ../instsup.cpp \
+          uac_crt.c uac_dcpr.c uac_sys.c unace.c ../wxmain.cpp
+
+#all: sfx.exe packinst
+all: sfx.exe
+
+$(OBJECTS):
+	$(CC) $(CFLAGS) -c $<	
+
+packinst: packinst/Makefile Makefile
+	@cd packinst
+	$(MAKE) -f Makefile all
+
+sfx.exe:  $(OBJECTS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $(DEFS) -o sfx.exe $(OBJECTS) $(LIBS)
+
+clean: 
+	$(RM) $(OBJECTS) install.exe install.res sfx.exe
+
+instres.o: install.rc
+	$(RC) install.rc instres.o --include-dir ../../../include
+ 
+globals.o: globals.c ../incace/globals.h ../incace/acestruc.h ../incace/unace.h
+install.o: ../install.c ../install.h ../instsup.h
+instsup.o: ../instsup.cpp
+uac_comm.o: uac_comm.c ../incace/globals.h ../incace/uac_dcpr.h ../incace/uac_comm.h
+uac_crc.o: uac_crc.c ../incace/uac_crc.h
+uac_crt.o: uac_crt.c ../incace/os.h ../incace/attribs.h ../incace/globals.h ../incace/uac_crt.h ../incace/uac_sys.h
+uac_dcpr.o: uac_dcpr.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h \
+	      ../incace/uac_dcpr.h ../incace/uac_sys.h
+uac_sys.o: uac_sys.c ../incace/os.h ../incace/globals.h ../incace/uac_sys.h
+unace.o: unace.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h ../incace/uac_crt.h \
+           ../incace/uac_dcpr.h ../incace/uac_sys.h
+wxmain.o: ../wxmain.cpp           
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxace/makefile.gcc	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,47 @@
+# Installer Makefile
+
+CC = gcc
+RM = rm -f
+RC = windres
+
+
+DEFS =
+LIBS = -lwx_gtk -lpng -ljpeg -lstdc++ -lgcc  -lc_r  -lgtk -lgdk -lgmodule -lglib -lXext -lX11 -lm -lgthread
+
+CFLAGS = -g -I.. -I../incace -I/usr/local//include  -I/usr/X11R6/include -I/usr/local/lib/glib/include -DSTRICT  -D__WXGTK__ -DGTK_NO_CHECK_CASTS -D_REENTRANT -D_IODBC_ -Wall
+LDFLAGS = -L/usr/local/lib -L/usr/X11R6/lib -L/usr
+
+OBJECTS = globals.o install.o uac_comm.o uac_crc.o instsup.o \
+          uac_crt.o uac_dcpr.o uac_sys.o unace.o wxmain.o
+
+SOURCES = globals.c ../install.c uac_comm.c uac_crc.c ../instsup.cpp \
+          uac_crt.c uac_dcpr.c uac_sys.c unace.c ../wxmain.cpp
+
+all: sfx
+
+$(OBJECTS):
+	$(CC) $(CFLAGS) -c $<	
+
+packinst: packinst/Makefile Makefile
+	@cd packinst
+	$(MAKE) -f Makefile all
+
+sfx:  $(OBJECTS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $(DEFS) -o sfx $(OBJECTS) $(LIBS)
+
+clean: 
+	$(RM) $(OBJECTS) install sfx *~
+
+globals.o: globals.c ../incace/globals.h ../incace/acestruc.h ../incace/unace.h
+install.o: ../install.c ../install.h ../instsup.h
+instsup.o: ../instsup.cpp
+uac_comm.o: uac_comm.c ../incace/globals.h ../incace/uac_dcpr.h ../incace/uac_comm.h
+uac_crc.o: uac_crc.c ../incace/uac_crc.h
+uac_crt.o: uac_crt.c ../incace/os.h ../incace/attribs.h ../incace/globals.h ../incace/uac_crt.h ../incace/uac_sys.h
+uac_dcpr.o: uac_dcpr.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h \
+	      ../incace/uac_dcpr.h ../incace/uac_sys.h
+uac_sys.o: uac_sys.c ../incace/os.h ../incace/globals.h ../incace/uac_sys.h
+unace.o: unace.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h ../incace/uac_crt.h \
+           ../incace/uac_dcpr.h ../incace/uac_sys.h
+wxmain.o: ../wxmain.cpp
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxace/makefile.vac	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,66 @@
+# Installer Makefile
+
+.SUFFIXES: \
+	.c .obj
+
+#CFLAGS = /Ss /Gm+ /I..\incace /I.. /Ti /C
+CFLAGS = /Ti /I..\incace /I.. /DOS2 /DTCPV40HDRS /DENABLE_LOGGING /Sm /Ss /Q /Gm /Gt /C
+LDFLAGS = /de /optfunc
+
+
+OBJECTS = globals.obj uac_comm.obj uac_crc.obj \
+          uac_crt.obj uac_dcpr.obj uac_sys.obj unace.obj 
+
+SOURCES = globals.c uac_comm.c uac_crc.c \
+          uac_crt.c uac_dcpr.c uac_sys.c unace.c 
+
+all: sfxos2.exe
+
+$(OBJECTS):
+	icc $(CFLAGS) %s
+
+dw.obj:
+	icc $(CFLAGS) ..\os2\dw.c
+
+dirent.obj:
+	icc $(CFLAGS) ..\os2\dirent.c
+
+install.obj:
+	icc $(CFLAGS) ..\install.c
+
+instsup.obj:
+	icc $(CFLAGS) ..\instsup.c
+
+rexx.obj:
+	icc $(CFLAGS) ..\rexx.c
+
+packinst: packinst/Makefile Makefile
+	@cd packinst
+	nmake /f makefile.vac all
+
+sfxos2.exe:  $(OBJECTS) dw.obj install.obj instsup.obj rexx.obj dirent.obj
+	rc -r -i .. ..\sfxos2.rc
+	icc @<<
+	 /B" $(LDFLAGS)"
+	 /Fesfxos2.exe
+	 rexx.lib
+	 $(OBJECTS) dw.obj install.obj instsup.obj rexx.obj dirent.obj
+	 ..\install.def
+<<
+	rc -x2 ..\sfxos2.res sfxos2.exe
+#	lxlite sfxos2.exe
+
+clean: 
+	rm -f $(OBJECTS) *.obj install.exe ..\sfxos2.res sfxos2.exe
+
+globals.obj: globals.c ../incace/globals.h ../incace/acestruc.h ../incace/unace.h
+uac_comm.obj: uac_comm.c ../incace/globals.h ../incace/uac_dcpr.h ../incace/uac_comm.h
+uac_crc.obj: uac_crc.c ../incace/uac_crc.h
+uac_crt.obj: uac_crt.c ../incace/os.h ../incace/attribs.h ../incace/globals.h ../incace/uac_crt.h ../incace/uac_sys.h
+uac_dcpr.obj: uac_dcpr.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h \
+	      ../incace/uac_dcpr.h ../incace/uac_sys.h
+uac_sys.obj: uac_sys.c ../incace/os.h ../incace/globals.h ../incace/uac_sys.h
+unace.obj: unace.c ../incace/os.h ../incace/globals.h ../incace/portable.h ../incace/uac_comm.h ../incace/uac_crc.h ../incace/uac_crt.h \
+           ../incace/uac_dcpr.h ../incace/uac_sys.h
+sfxos2.res: sfxos2.rc install.h
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxace/makefile.vc	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,73 @@
+#
+WXDIR = $(WXWIN)
+CC = cl
+CFLAGS = -c -G5 -GD -Zp1 -DWIN32 -D__WIN32__ -DMSVC -DENABLE_LOGGING -I. -I.. -I..\incace -I..\platform
+CFLAGS_DEBUG = -Zi
+CFLAGS_COMPILE = -MT
+LIBS = wsock32.lib kernel32.lib user32.lib comctl32.lib gdi32.lib advapi32.lib shell32.lib comdlg32.lib ole32.lib rexx.lib
+
+RES = 
+LINKFLAGS = -machine:i386 -debug:full -debugtype:cv
+DLLLINKFLAGS = -dll
+LINK = link
+
+OBJS = 	globals.obj \
+       	uac_comm.obj \
+       	uac_crc.obj \
+       	uac_crt.obj \
+       	uac_dcpr.obj \
+       	uac_sys.obj \
+       	unace.obj \
+        ..\win\dirent.obj \
+        ..\win\dw.obj \
+	..\install.obj \
+        ..\rexx.obj \
+        ..\instsup.obj \
+        ..\win32sup.obj
+                
+LINKOBJS = 	globals.obj \
+	       	uac_comm.obj \
+	       	uac_crc.obj \
+       		uac_crt.obj \
+	       	uac_dcpr.obj \
+       		uac_sys.obj \
+	       	unace.obj \
+                dirent.obj \
+                dw.obj \
+		install.obj \
+        	rexx.obj \
+	        instsup.obj \
+                win32sup.obj
+                
+all: sfxwin.exe
+
+clean:
+	-erase *.dll
+        -erase *.exe
+        -erase *.opt
+        -erase *.lib
+        -erase *.obj
+        -erase *.map
+        -erase *.pdb
+        -erase *.ilk
+        -erase *.exp
+        -erase *.res
+        -erase *~
+        
+sfxwin.exe: $(OBJS) sfxwin.res
+	$(LINK) @<<
+-out:$(@) -subsystem:windows -entry:WinMainCRTStartup
+$(LINKFLAGS)
+$(LINKOBJS)
+$(LIBS)
+..\sfxwin.res
+<<
+
+sfxwin.res: ..\sfxwin.rc
+	rc -r -i.. ..\sfxwin.rc
+        
+.c.obj:
+	$(CC) $(CFLAGS) $(CFLAGS_DEBUG) $(CFLAGS_COMPILE) $*.c
+        
+.cpp.obj:
+	$(CC) $(CFLAGS) $(CFLAGS_DEBUG) $(CFLAGS_COMPILE) $*.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxace/sfx.rc	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,2 @@
+#include "wx/msw/wx.rc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxace/uac_comm.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,51 @@
+/* ------------------------------------------------------------------------ */
+/*                                                                          */
+/*      Decompresses and outputs comment if present.                        */
+/*                                                                          */
+/* ------------------------------------------------------------------------ */
+
+#include <stdio.h>    // printf()
+
+#include "globals.h"
+#include "uac_dcpr.h"
+#include "uac_comm.h"
+
+INT  comm_cpr_size=0;
+CHAR *comm;
+
+void comment_out(CHAR *top)      // outputs comment if present
+{
+	INT  i;
+
+	if (head.HEAD_FLAGS & ACE_COMM)
+	{                             // comment present?
+		if (head.HEAD_TYPE == MAIN_BLK)
+		{                          // get begin and size of comment data
+			comm = (CHAR*)MCOMM;
+			comm_cpr_size = MCOMM_SIZE;
+		}
+		else
+		{
+		 comm = (CHAR*)FCOMM;
+		 comm_cpr_size = FCOMM_SIZE;
+		}                          // limit comment size if too big
+		i = sizeof(head) - (INT)(comm - (CHAR*) &head);
+		if (comm_cpr_size > i)
+			comm_cpr_size = i;
+		dcpr_comm(i);              // decompress comment
+
+#ifdef AMIGA
+		{
+			char *p=comm;
+			while (*p)
+			{
+				if (*p==0x0D)
+					*p=0x0A;          // Replace ms-dos line termination
+				p++;
+			}
+		}
+#endif
+
+		pipeit("%s\n\n%s\n\n", top, comm); // output comment
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxace/uac_crc.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,36 @@
+/* ------------------------------------------------------------------------ */
+/*                                                                          */
+/*      CRC-calculation routines.                                           */
+/*                                                                          */
+/* ------------------------------------------------------------------------ */
+
+#include "uac_crc.h"
+
+
+ULONG crctable[256];
+ULONG rd_crc=0;
+
+
+void make_crctable(void)   // initializes CRC table
+{
+	ULONG r,
+	i,
+	j;
+
+	for (i = 0; i <= 255; i++)
+	{
+		for (r = i, j = 8; j; j--)
+			r = (r & 1) ? (r >> 1) ^ CRCPOLY : (r >> 1);
+		crctable[i] = r;
+	}
+}
+
+// Updates crc from addr till addr+len-1
+//
+ULONG getcrc(ULONG crc, UCHAR * addr, INT len)
+{
+	while (len--)
+		crc = crctable[(unsigned char) crc ^ (*addr++)] ^ (crc >> 8);
+	return (crc);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxace/uac_crt.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,314 @@
+/* ------------------------------------------------------------------------ */
+/*                                                                          */
+/*      Creates/Replaces files or directories.                              */
+/*                                                                          */
+/* ------------------------------------------------------------------------ */
+
+#include "os.h"
+
+#ifdef __EMX__
+#include <sys/types.h>
+#include <sys/dirent.h>
+#include <stdlib.h>
+#endif
+#include <fcntl.h>
+#include <stdio.h>     // printf() remove()
+#include <string.h>    // strncpy()
+#include <sys/types.h>
+#include <sys/stat.h>  // struct stat
+#include <time.h>
+
+#include "dw.h"
+
+#ifdef __OS2__
+#define OS2_H_INCLUDED
+#include <direct.h>
+#endif
+
+#include "install.h"
+
+#if defined(DOS) || defined(WINNT) || defined(WIN16)  || defined(__OS2__)
+ #include <io.h>       // access()
+#endif
+#if defined(__CYGWIN__)
+#include <Windows32/Base.h>
+#endif 
+
+#include "attribs.h"
+#include "globals.h"
+#include "uac_crt.h"
+#include "uac_sys.h"
+
+#ifdef ENABLE_LOGGING
+extern FILE *logfile;
+#endif
+extern char installdir[400];
+extern int installstate;
+
+/* Undocumented functions */
+#if defined(__OS2__) || defined(__EMX__)
+APIRET APIENTRY DosReplaceModule(PSZ pszOldModule,PSZ pszNewModule,PSZ pszBackupModule);
+#endif
+
+
+/* gets file name from header
+ */
+CHAR *ace_fname(CHAR * s, thead * head, INT nopath)
+{
+	INT  i;
+	char *cp;
+
+	strncpy(s, (CHAR*)(*(tfhead *) head).FNAME, i = (*(tfhead *) head).FNAME_SIZE);
+	s[i] = 0;
+
+	if (nopath)
+	{
+		cp=strrchr(s, '\\');
+		if (cp)
+			memmove(s, cp+1, strlen(cp));
+	}
+#ifdef __UNIX__
+	else
+    {                                // by current OS seperator
+		cp=s;
+		while ((cp=strchr(cp, '\\'))!=NULL)
+			*cp++='/';
+	}
+#endif
+
+	return s;
+}
+
+void check_ext_dir(CHAR * f)        // checks/creates path of file
+{
+	char d[1024];
+	char buffer[1024];
+	int z, flag = 0, len = strlen(f);
+
+	strcpy(buffer, f);
+	for(z=len;z>-1;z--)
+	{
+		if(buffer[z] == '\\')
+		{
+			buffer[z+1] = 0;
+			flag = 1;
+			z = -1;
+		}
+	}
+	if(!flag)
+		return;
+	for(z=0;z<strlen(buffer);z++)
+	{
+		if(buffer[z] == '\\')
+		{
+			if(!(z == 2 && buffer[1] == ':'))
+			{
+				strcpy(d, buffer);
+				d[z] = 0;
+				if (!fileexists(d))
+				{
+#if (defined(__OS2__) && !defined(__EMX__)) || (defined(WINNT) && !defined(__CYGWIN__))
+					if (mkdir(d))
+#else
+					if (mkdir(d, 0))
+#endif
+
+					{
+#if 0
+						f_err = ERR_WRITE;
+						error("Error while creating directory \"%s\".", d);
+					}
+					else
+#else
+				}
+#endif
+				{
+#ifdef ENABLE_LOGGING
+					if(logfile)
+					{
+						if(strlen(d) > 1 && d[1] == ':')
+							fprintf(logfile, "<NewDir>,%s\r\n", d);
+						else
+						{
+							if(installdir[strlen(installdir)-1] == '\\')
+								fprintf(logfile, "<NewDir>,%s%s\r\n", installdir, d);
+							else
+								fprintf(logfile, "<NewDir>,%s\\%s\r\n", installdir, d);
+						}
+					}
+#endif
+				}
+			}
+		}
+	}
+
+}
+}
+
+extern char *reason;
+
+INT  ovr_delete(CHAR * n)           // deletes directory or file
+{
+	if (remove(n) && rmdir(n))
+	{
+#if defined(__OS2__) || defined(__EMX__)
+		DosReplaceModule(n, NULL, NULL);
+#endif
+		if (remove(n) && rmdir(n))
+		{
+			error("Could not delete file or directory: \"%s\" Access denied.", n);
+			reason = "One or more files could not be overwritten.  This could mean the files are in use or you don't have adequate permissions.";
+			return (1);
+		}
+	}
+	return (0);
+}
+
+INT  create_dest_file(CHAR * file, INT a)  // creates file or directory
+{
+	INT  han,
+	i  = 0,
+	ex = fileexists(file);
+	struct stat st;
+	extern int no_update;
+
+	check_ext_dir(file);
+	if (f_err)
+		return (-1);
+	if (a & _A_SUBDIR)
+	{                                // create dir or file?
+		if (ex)
+			stat(file, &st);
+
+#ifdef ENABLE_LOGGING
+		if(logfile)
+			fprintf(logfile, "<NewDir>,%s\\%s\r\n", installdir, file);
+#endif
+
+#if (defined(__OS2__) && !defined(__EMX__)) || (!defined(__CYGWIN__) && defined(__WIN32__))
+		if ((!ex && mkdir(file)) || (ex && !(st.st_mode & S_IFDIR)))
+#else
+			if ((!ex && mkdir(file, 0)) || (ex && !(st.st_mode & S_IFDIR)))
+#endif
+			{
+				error("Could not create directory \"%s\".", file);
+				return (-1);
+			}
+
+#ifdef DOS
+		_dos_setfileattr(file, a);    // set directory attributes
+#endif
+		return (-1);
+	}
+	else
+	{
+		if (ex)
+		{                             // does the file already exist
+#if defined(__OS2__) || defined(__EMX__)
+			static int sddall = 0;
+			FILESTATUS3 fileinfo;
+
+			f_ovrall = 1;
+
+			DosQueryPathInfo(file, FIL_STANDARD, &fileinfo, sizeof(FILESTATUS3));
+			if(!sddall)
+			{
+				FDATE fdate;
+				FTIME ftime;
+				struct tm 	tc, tc2;
+				time_t 		tt, tt2;
+
+				*((USHORT*)&fdate) = (USHORT)(fhead.FTIME >> 16);
+				*((USHORT*)&ftime) = (USHORT)fhead.FTIME;
+
+				tc.tm_year = fileinfo.fdateLastWrite.year + 80;
+				tc.tm_mon = fileinfo.fdateLastWrite.month - 1;
+				tc.tm_mday = fileinfo.fdateLastWrite.day;
+				tc.tm_hour = fileinfo.ftimeLastWrite.hours;
+				tc.tm_min = fileinfo.ftimeLastWrite.minutes;
+				tc.tm_sec = fileinfo.ftimeLastWrite.twosecs * 2;
+
+				tc2.tm_year = fdate.year + 80;
+				tc2.tm_mon = fdate.month - 1;
+				tc2.tm_mday = fdate.day;
+				tc2.tm_hour = ftime.hours;
+				tc2.tm_min = ftime.minutes;
+				tc2.tm_sec = ftime.twosecs * 2;
+
+				if((tt = mktime(&tc)) == -1 || (tt2 = mktime(&tc2)) == -1 || tt > tt2)
+				{
+
+					if(file[1] == ':')
+						i = confirm("File \"%s\" has a newer modification time. Overwrite?", file);  // prompt for overwrite
+					else
+					{
+						if(installdir[strlen(installdir)-1] == '\\')
+							i = confirm("File \"%s%s\" has a newer modification time. Overwrite?", installdir, file);  // prompt for overwrite
+						else
+							i = confirm("File \"%s\\%s\" has a newer modification time. Overwrite?", installdir, file);  // prompt for overwrite
+					}
+					if(i == 1)
+					{
+						sddall = 1;
+						i = 0;
+					}
+					if (i == 3)
+					{
+						f_err = ERR_USER;
+						installstate = ABORTED;
+					}
+					if(i)
+						return -1;
+				}
+			}
+			fileinfo.attrFile = FILE_NORMAL;
+			DosSetPathInfo(file, FIL_STANDARD, (PVOID)&fileinfo, sizeof(FILESTATUS3), 0);
+#endif
+			if (!f_ovrall)
+			{
+				if(installdir[strlen(installdir)-1] == '\\')
+					i = confirm("Overwrite file \"%s%s\"?", installdir, file);  // prompt for overwrite
+				else
+					i = confirm("Overwrite file \"%s\\%s\"?", installdir, file);  // prompt for overwrite
+				f_ovrall = (i == 1);
+				if (i == 3)
+					f_err = ERR_USER;
+			}
+			if ((i && !f_ovrall) || ovr_delete(file))
+				return (-1);            // delete?
+		}
+#if defined(__OS2__) || defined(__EMX__) || defined(__WIN32__)
+		if ((han = open(file, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY,
+						S_IREAD | S_IWRITE | S_IEXEC | S_IDELETE |
+						S_IRGRP | S_IWGRP  | S_IROTH | S_IWOTH )) < 0)
+#else
+			if ((han = open(file, O_WRONLY | O_TRUNC | O_CREAT,
+						   S_IREAD | S_IWRITE | S_IEXEC | S_IDELETE |
+						   S_IRGRP | S_IWGRP  | S_IROTH | S_IWOTH )) < 0)
+#endif
+				error("Could not create destination file \"%s\".", file);
+		else
+		{
+#ifdef ENABLE_LOGGING
+			if(logfile)
+			{
+				if(!no_update)
+				{
+					if(strlen(file) > 1 && file[1] == ':')
+						fprintf(logfile, "<FileInst>,%s\r\n", file);
+					else
+					{
+						if(installdir[strlen(installdir)-1] == '\\')
+							fprintf(logfile, "<FileInst>,%s%s\r\n", installdir, file);
+						else
+							fprintf(logfile, "<FileInst>,%s\\%s\r\n", installdir, file);
+					}
+				}
+			}
+#endif
+		}
+
+		return (han);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxace/uac_dcpr.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,554 @@
+/* ------------------------------------------------------------------------ */
+/*                                                                          */
+/*      These are the decompression algorithms.                             */
+/*      Don't change here anything (apart from memory allocation perhaps).  */
+/*      Any changes will very likely cause bugs!                            */
+/*                                                                          */
+/* ------------------------------------------------------------------------ */
+
+#include "os.h"
+
+#if defined(AMIGA)
+ #include <string.h> // mem*()
+#endif
+#if defined(DOS) || defined(WIN16) || defined(WINNT) || defined(UNIX)
+#if !defined(__CYGWIN__)
+ #include <mem.h>    // mem*()
+#endif 
+#endif
+
+#include <stdio.h>   // printf()
+#include <stdlib.h>  // malloc()
+#include <string.h>
+
+
+#include "globals.h"
+#include "portable.h"
+#include "uac_comm.h"
+#include "uac_crc.h"
+#include "uac_dcpr.h"
+#include "uac_sys.h"
+#ifdef CRYPT
+ #include "unace_ps.h"
+#endif /* CRYPT */
+
+
+//------------------------------ QUICKSORT ---------------------------------//
+#define xchg_def(v1,v2) {INT dummy;\
+                         dummy=v1; \
+                         v1=v2;    \
+                         v2=dummy;}
+
+void sortrange(INT left, INT right)
+{
+	INT  zl = left,
+	zr = right,
+	hyphen;
+
+	hyphen = sort_freq[right];
+
+	//divides by hyphen the given range into 2 parts
+	do
+	{
+		while (sort_freq[zl] > hyphen)
+			zl++;
+		while (sort_freq[zr] < hyphen)
+			zr--;
+		//found a too small (left side) and
+		//a too big (right side) element-->exchange them
+		if (zl <= zr)
+		{
+			xchg_def(sort_freq[zl], sort_freq[zr]);
+			xchg_def(sort_org[zl], sort_org[zr]);
+			zl++;
+			zr--;
+		}
+	}
+	while (zl < zr);
+
+	//sort partial ranges - when very small, sort directly
+	if (left < zr)
+	{
+		if (left < zr - 1)
+			sortrange(left, zr);
+		else if (sort_freq[left] < sort_freq[zr])
+		{
+			xchg_def(sort_freq[left], sort_freq[zr]);
+			xchg_def(sort_org[left], sort_org[zr]);
+		}
+	}
+
+	if (right > zl)
+	{
+		if (zl < right - 1)
+			sortrange(zl, right);
+		else if (sort_freq[zl] < sort_freq[right])
+		{
+			xchg_def(sort_freq[zl], sort_freq[right]);
+			xchg_def(sort_org[zl], sort_org[right]);
+		}
+	}
+}
+
+void quicksort(INT n)
+{
+	INT  i;
+
+	for (i = n + 1; i--;)
+		sort_org[i] = i;
+	sortrange(0, n);
+}
+
+//------------------------------ read bits ---------------------------------//
+void readdat(void)
+{
+	UINT i;
+
+	i = (size_rdb - 2) << 2;
+	rpos -= size_rdb - 2;
+	buf_rd[0] = buf_rd[size_rdb - 2];
+	buf_rd[1] = buf_rd[size_rdb - 1];
+	read_adds_blk((CHAR *) & buf_rd[2], i);
+#ifdef HI_LO_BYTE_ORDER
+	{
+		ULONG *p;
+		i>>=2;    // count LONGs not BYTEs
+		p=&buf_rd[2];
+		while (i--)
+		{
+			LONGswap(p);
+			p++;
+		}
+	}
+#endif
+}
+
+#define addbits(bits)                                   \
+{                                                       \
+	rpos+=(bits_rd+=bits)>>5;                             \
+	bits_rd&=31;                                          \
+	if (rpos==(size_rdb-2)) readdat();                    \
+	code_rd=(buf_rd[rpos] << bits_rd)                     \
+	+((buf_rd[rpos+1] >> (32-bits_rd))&(!bits_rd-1));   \
+	}
+
+
+//---------------------- COMMENT DECOMPRESSION -----------------------------//
+
+#define comm_cpr_hf(a,b) (a+b)
+
+void dcpr_comm_init(void)
+{
+	INT  i;
+
+	i = comm_cpr_size > size_rdb * sizeof(LONG) ? size_rdb * sizeof(LONG) : comm_cpr_size;
+	if (!f_err)
+		memcpy(buf_rd, comm, i);
+#ifdef HI_LO_BYTE_ORDER
+	{
+		ULONG *p;
+		i>>=2;    // count LONGs not BYTEs
+		p=buf_rd;
+		while (i--)
+		{
+			LONGswap(p);
+			p++;
+		}
+	}
+#endif
+	code_rd = buf_rd[0];
+	rpos = bits_rd = 0;
+}
+
+void dcpr_comm(INT comm_size)
+{
+	SHORT hash[comm_cpr_hf(255, 255) + 1];
+	INT  dpos = 0,
+		c,
+	pos = 0,
+	len,
+	hs;
+
+	memset(&hash, 0, sizeof(hash));
+	if (comm_cpr_size)
+	{
+		dcpr_comm_init();
+		len = code_rd >> (32 - 15);
+		addbits(15);
+		if (len >= comm_size)
+			len = comm_size - 1;
+		if (read_wd(maxwd_mn, dcpr_code_mn, dcpr_wd_mn, max_cd_mn))
+			do
+		{
+			if (dpos > 1)
+			{
+				pos = hash[hs = comm_cpr_hf(comm[dpos - 1], comm[dpos - 2])];
+				hash[hs] = dpos;
+			}
+			addbits(dcpr_wd_mn[(c = dcpr_code_mn[code_rd >> (32 - maxwd_mn)])]);
+			if (rpos == size_rdb - 3)
+				rpos = 0;
+			if (c > 255)
+			{
+				c -= 256;
+				c += 2;
+				while (c--)
+					comm[dpos++] = comm[pos++];
+			}
+			else
+			{
+				comm[dpos++] = c;
+			}
+		}
+		while (dpos < len);
+		comm[len] = 0;
+	}
+}
+
+//------------------------- LZW1 DECOMPRESSION -----------------------------//
+void wrchar(CHAR ch)
+{
+	dcpr_do++;
+
+	dcpr_text[dcpr_dpos] = ch;
+	dcpr_dpos++;
+	dcpr_dpos &= dcpr_dican;
+}
+
+void copystr(LONG d, INT l)
+{
+	INT  mpos;
+
+	dcpr_do += l;
+
+	mpos = dcpr_dpos - d;
+	mpos &= dcpr_dican;
+
+	if ((mpos >= dcpr_dicsiz - maxlength) || (dcpr_dpos >= dcpr_dicsiz - maxlength))
+	{
+		while (l--)
+		{
+			dcpr_text[dcpr_dpos] = dcpr_text[mpos];
+			dcpr_dpos++;
+			dcpr_dpos &= dcpr_dican;
+			mpos++;
+			mpos &= dcpr_dican;
+		}
+	}
+	else
+	{
+		while (l--)
+			dcpr_text[dcpr_dpos++] = dcpr_text[mpos++];
+		dcpr_dpos &= dcpr_dican;
+	}
+}
+
+void decompress(void)
+{
+	INT  c,
+	lg,
+	i,
+	k;
+	ULONG dist;
+
+	while (dcpr_do < dcpr_do_max)
+	{
+		if (!blocksize)
+			if (!calc_dectabs())
+				return;
+
+		addbits(dcpr_wd_mn[(c = dcpr_code_mn[code_rd >> (32 - maxwd_mn)])]);
+		blocksize--;
+		if (c > 255)
+		{
+			if (c > 259)
+			{
+				if ((c -= 260) > 1)
+				{
+					dist = (code_rd >> (33 - c)) + (1L << (c - 1));
+					addbits(c - 1);
+				}
+				else
+					dist = c;
+				dcpr_olddist[(dcpr_oldnum = (dcpr_oldnum + 1) & 3)] = dist;
+				i = 2;
+				if (dist > maxdis2)
+				{
+					i++;
+					if (dist > maxdis3)
+						i++;
+				}
+			}
+			else
+			{
+				dist = dcpr_olddist[(dcpr_oldnum - (c &= 255)) & 3];
+				for (k = c + 1; k--;)
+					dcpr_olddist[(dcpr_oldnum - k) & 3] = dcpr_olddist[(dcpr_oldnum - k + 1) & 3];
+				dcpr_olddist[dcpr_oldnum] = dist;
+				i = 2;
+				if (c > 1)
+					i++;
+			}
+			addbits(dcpr_wd_lg[(lg = dcpr_code_lg[code_rd >> (32 - maxwd_lg)])]);
+			dist++;
+			lg += i;
+			copystr(dist, lg);
+		}
+		else
+			wrchar(c);
+	}
+}
+
+//-------------------------- HUFFMAN ROUTINES ------------------------------//
+INT  makecode(UINT maxwd, UINT size1_t, UCHAR * wd, USHORT * code)
+{
+	UINT maxc,
+	size2_t,
+	l,
+	c,
+	i,
+	max_make_code;
+
+	memcpy(&sort_freq, wd, (size1_t + 1) * sizeof(CHAR));
+	if (size1_t)
+		quicksort(size1_t);
+	else
+		sort_org[0] = 0;
+	sort_freq[size1_t + 1] = size2_t = c = 0;
+	while (sort_freq[size2_t])
+		size2_t++;
+	if (size2_t < 2)
+	{
+		i = sort_org[0];
+		wd[i] = 1;
+		size2_t += (size2_t == 0);
+	}
+	size2_t--;
+
+	max_make_code = 1 << maxwd;
+	for (i = size2_t + 1; i-- && c < max_make_code;)
+	{
+		maxc = 1 << (maxwd - sort_freq[i]);
+		l = sort_org[i];
+		if (c + maxc > max_make_code)
+		{
+			dcpr_do = dcpr_do_max;
+			return (0);
+		}
+		memset16(&code[c], l, maxc);
+		c += maxc;
+	}
+	return (1);
+}
+
+INT  read_wd(UINT maxwd, USHORT * code, UCHAR * wd, INT max_el)
+{
+	UINT c,
+	i,
+	j,
+	num_el,
+	l,
+	uplim,
+	lolim;
+
+	memset(wd, 0, max_el * sizeof(CHAR));
+	memset(code, 0, (1 << maxwd) * sizeof(SHORT));
+
+	num_el = code_rd >> (32 - 9);
+	addbits(9);
+	if (num_el > max_el)
+		num_el = max_el;
+
+	lolim = code_rd >> (32 - 4);
+	addbits(4);
+	uplim = code_rd >> (32 - 4);
+	addbits(4);
+
+	for (i = -1; ++i <= uplim;)
+	{
+		wd_svwd[i] = code_rd >> (32 - 3);
+		addbits(3);
+	}
+	if (!makecode(maxwd_svwd, uplim, wd_svwd, code))
+		return (0);
+	j = 0;
+	while (j <= num_el)
+	{
+		c = code[code_rd >> (32 - maxwd_svwd)];
+		addbits(wd_svwd[c]);
+		if (c < uplim)
+			wd[j++] = c;
+		else
+		{
+			l = (code_rd >> 28) + 4;
+			addbits(4);
+			while (l-- && j <= num_el)
+				wd[j++] = 0;
+		}
+	}
+	if (uplim)
+		for (i = 0; ++i <= num_el;)
+			wd[i] = (wd[i] + wd[i - 1]) % uplim;
+	for (i = -1; ++i <= num_el;)
+		if (wd[i])
+			wd[i] += lolim;
+
+	return (makecode(maxwd, num_el, wd, code));
+
+}
+
+INT  calc_dectabs(void)
+{
+	if (!read_wd(maxwd_mn, dcpr_code_mn, dcpr_wd_mn, max_cd_mn)
+		|| !read_wd(maxwd_lg, dcpr_code_lg, dcpr_wd_lg, max_cd_lg))
+		return (0);
+
+	blocksize = code_rd >> (32 - 15);
+	addbits(15);
+
+	return (1);
+}
+
+//---------------------------- BLOCK ROUTINES ------------------------------//
+INT  decompress_blk(CHAR * buf, UINT len)
+{
+	LONG old_pos = dcpr_dpos;
+	INT  i;
+
+	dcpr_do = 0;
+	if ((dcpr_do_max = len - maxlength) > dcpr_size)
+		dcpr_do_max = dcpr_size;
+	if ((LONG) dcpr_size > 0 && dcpr_do_max)
+	{
+		decompress();
+		if (old_pos + dcpr_do > dcpr_dicsiz)
+		{
+			i = dcpr_dicsiz - old_pos;
+			memcpy(buf, &dcpr_text[old_pos], i);
+			memcpy(&buf[i], dcpr_text, dcpr_do - i);
+		}
+		else
+			memcpy(buf, &dcpr_text[old_pos], dcpr_do);
+	}
+	dcpr_size -= dcpr_do;
+	return (dcpr_do);
+}
+
+INT unstore(CHAR * buf, UINT len)
+{
+	UINT rd = 0,
+	i,
+	pos = 0;
+
+#ifdef CRYPT
+	len = crypt_len(len - 8);    /* because of decryption */
+#endif /* CRYPT */
+
+	while ((i = read_adds_blk((CHAR *) buf_rd, (INT) ((i = ((len > dcpr_size) ? dcpr_size : len)) > size_rdb ? size_rdb : i))) != 0)
+	{
+		rd += i;
+		len -= i;
+		memcpy(&buf[pos], buf_rd, i);
+		pos += i;
+	}
+	dcpr_size -= rd;
+	for (i = 0; i < rd; i++)
+	{
+		dcpr_text[dcpr_dpos] = buf[i];
+		dcpr_dpos++;
+		dcpr_dpos &= dcpr_dican;
+	}
+	return (INT)rd;
+}
+
+INT  dcpr_adds_blk(CHAR * buf, UINT len)
+{
+	INT  r;
+
+	switch (fhead.TECH.TYPE)
+	{
+	case TYPE_STORE:
+		r = unstore(buf, len);
+		break;
+	case TYPE_LZW1:
+		r = decompress_blk(buf, len);
+		break;
+	default:
+		error("\nFile compressed with unknown method. Decompression not possible.\n");
+		f_err = ERR_OTHER;
+		r = 0;
+	}
+	rd_crc = getcrc(rd_crc, (UCHAR*)buf, r);
+	return r;
+}
+
+
+//----------------------------- INIT ROUTINES ------------------------------//
+void dcpr_init(void)
+{
+	dcpr_frst_file = 1;
+
+	dcpr_dic = 20;
+	while ((dcpr_text = malloc(dcpr_dicsiz = (LONG) 1 << dcpr_dic))==NULL)
+		dcpr_dic--;
+	dcpr_dican = dcpr_dicsiz - 1;
+}
+
+void dcpr_init_file(void)
+{
+	UINT i;
+
+#ifdef CRYPT
+
+	reset_cryptkey();
+
+#else /* CRYPT */
+
+	if (head.HEAD_FLAGS & ACE_PASSW)
+	{
+		error("\nFound passworded file. Decryption not supported.\n");
+		f_err = ERR_OTHER;
+		return;
+	}
+
+#endif /* CRYPT */
+
+	rd_crc = CRC_MASK;
+	dcpr_size = fhead.SIZE;
+	if (fhead.TECH.TYPE == TYPE_LZW1)
+	{
+		if ((fhead.TECH.PARM & 15) + 10 > dcpr_dic)
+		{
+			error("\nNot enough memory or dictionary of archive too large.\n");
+			f_err = ERR_MEM;
+			return;
+		}
+
+		i = size_rdb * sizeof(LONG);
+		read_adds_blk((CHAR *) buf_rd, i);
+#ifdef HI_LO_BYTE_ORDER
+		{
+			ULONG *p;
+			i>>=2;    // count LONGs not BYTEs
+			p=buf_rd;
+			while (i--)
+			{
+				LONGswap(p);
+				p++;
+			}
+		}
+#endif
+		code_rd = buf_rd[0];
+		bits_rd = rpos = 0;
+
+		blocksize = 0;
+	}
+	if (!adat.sol || dcpr_frst_file)
+		dcpr_dpos = 0;
+
+	dcpr_oldnum = 0;
+	memset(&dcpr_olddist, 0, sizeof(dcpr_olddist));
+
+	dcpr_frst_file = 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxace/uac_sys.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,96 @@
+/* ------------------------------------------------------------------------ */
+/*                                                                          */
+/*      Some basic things.                                                  */
+/*                                                                          */
+/* ------------------------------------------------------------------------ */
+
+#include "os.h"
+
+#include <signal.h>  // signal()
+#include <stdio.h>   // fprintf() fflush() getch() putc()
+
+#include "globals.h"
+#include "uac_sys.h"
+
+
+void memset16(USHORT * dest, SHORT val, INT len)  // fills short-array with
+{                                                 // value
+	while (len--)
+		*(dest++) = val;
+}
+
+INT  cancel(void)               // checks whether to interrupt the program
+{
+#ifdef DOS
+	while (kbhit())
+	{
+		if (getch() == 27)
+			f_err = ERR_USER;
+	}
+#endif
+	return (f_err);
+}
+
+/*INT  wrask(CHAR * s)            // prompt-routine
+{
+   INT  ch;
+
+   fprintf(stderr, "\n %s (Yes,Always,No,Cancel) ", s);
+   fflush(stderr);
+   do
+   {
+      ch = getch();
+      ch = upcase(ch);
+   }
+   while (ch != 'Y' && ch != 'A' && ch != 'N' && ch != 'C' && ch != 27);
+   fprintf(stderr, "%s", ch == 'Y' ? "Yes" : (ch == 'A' ? "Always" : (ch == 'N' ? "No" : "Cancel")));
+   fflush(stderr);
+   return (ch == 'Y' ? 0 : (ch == 'A' ? 1 : (ch == 'N' ? 2 : 3)));
+} */
+
+void beep(void)                           // makes some noise
+{
+#ifdef DOS
+	sound(800);
+	delay(250);
+	nosound();
+#endif
+#ifdef AMIGA
+	putc(0x07, stderr);
+#endif
+}
+
+void my_signalhandler(INT sig_number)     // sets f_err if ctrl+c or ctrl+brk
+{
+	f_err = ERR_USER;
+	error("\nUser break\n");
+}
+
+#ifdef DOS                                // handles hardware errors
+#ifdef __BORLANDC__
+INT harderrhandler(UINT deverr, UINT errc, UINT * devhdr)
+#else
+INT __far harderrhandler(UINT deverr, UINT errc, UINT * devhdr)
+#endif
+{
+   f_criterr = 'A' + deverr & 0xff;
+   f_err = ERR_OTHER;
+   return (0x3);
+}
+#endif
+
+void set_handler(void)                    // initializes handlers
+{
+#if defined(DOS) && !defined(__BORLANDC__)
+	signal(SIGBREAK, my_signalhandler);    // set ctrl-break/-c handlers
+#endif
+	signal(SIGINT, my_signalhandler);
+#if defined(DOS) && !defined(__CONSOLE__) // set hardware error handler
+#ifdef __BORLANDC__
+	harderr(harderrhandler);
+#else
+	_harderr(harderrhandler);
+#endif
+#endif
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxace/unace.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,572 @@
+/* ------------------------------------------------------------------------ */
+/*                                                                          */
+/*      Main file of public UNACE.                                          */
+/*                                                                          */
+/* ------------------------------------------------------------------------ */
+
+
+
+//--------------- include general files ------------------------------------//
+#include <ctype.h>      // tolower()
+#include <fcntl.h>      // open()
+#include <stdio.h>      // printf() sprintf() remove()
+#include <stdlib.h>     // malloc()
+#include <string.h>     // str*()
+#include <sys/types.h>
+#include <sys/stat.h>   // S_I*  AMIGA: fstat()
+#if (!defined(__EMX__) && !defined(__OS2__) && !defined(WINNT) && !defined(WIN32)) ||  defined(__CYGWIN__)
+#include <sys/errno.h>
+#endif
+
+#if !defined(__EMX__) && !defined(__OS2__) && !defined(WIN32) && !defined(WINNT)
+#define stricmp strcasecmp
+#endif
+
+#include "dw.h"
+
+#ifdef  __OS2__
+#define OS2_H_INCLUDED
+#include <io.h>
+#endif
+
+#include "install.h"
+#include "instsup.h"
+extern int installstate;
+
+off_t acelseek(off_t offset, int whence);
+int aceread(void *buf, size_t count);
+int aceopen(const char *path, int flags);
+int aceclose(int fd);
+int acesize(void);
+int acetell(int fd);
+char *replacestr(char *str1, char *str2, char *str3);
+
+//--------------- include unace specific header files ----------------------//
+#include "os.h"
+
+#include "globals.h"
+#include "portable.h"
+#include "uac_comm.h"
+#include "uac_crc.h"
+#include "uac_crt.h"
+#include "uac_dcpr.h"
+#include "uac_sys.h"
+
+#ifdef CRYPT
+ #include "unace_ps.h"
+#endif /* CRYPT */
+
+
+
+
+//--------------- BEGIN OF UNACE ROUTINES ----------------------------------//
+
+int pipeit(char *format, ...)
+{
+	/* Do nothing ... perhaps pipe this somewhere in the future */
+	return 0;
+} 
+
+void init_unace(void)           // initializes unace
+{
+	buf_rd =malloc(size_rdb * sizeof(ULONG));  // Allocate buffers: increase
+	buf    =malloc(size_buf);                  // sizes when possible to speed
+	buf_wr =malloc(size_wrb);                  // up the program
+	readbuf=malloc(size_headrdb);
+
+	if (buf_rd ==NULL ||
+		buf    ==NULL ||
+		buf_wr ==NULL ||
+		readbuf==NULL )
+		f_err = ERR_MEM;
+
+	make_crctable();             // initialize CRC table
+	dcpr_init();                 // initialize decompression
+
+	set_handler();               // ctrl+break etc.
+}
+
+void done_unace(void)
+{
+	if (buf_rd   ) free(buf_rd   );
+	if (buf      ) free(buf      );
+	if (buf_wr   ) free(buf_wr   );
+	if (readbuf  ) free(readbuf  );
+	if (dcpr_text) free(dcpr_text);
+}
+
+INT  read_header(INT print_err)         // reads any header from archive
+{
+	USHORT rd,
+	head_size,
+	crc_ok;
+	LONG crc;
+	UCHAR *tp=readbuf;
+
+	acelseek(skipsize, SEEK_CUR);   // skip ADDSIZE block
+
+	if (aceread(&head, 4)<4)
+		return (0);                       // read CRC and header size
+
+#ifdef HI_LO_BYTE_ORDER
+	WORDswap(&head.HEAD_CRC);
+	WORDswap(&head.HEAD_SIZE);
+#endif
+	// read size_headrdb bytes into
+	head_size = head.HEAD_SIZE;          // header structure
+	rd = (head_size > size_headrdb) ? size_headrdb : head_size;
+	if (aceread(readbuf, rd) < rd)
+		return (0);
+	head_size -= rd;
+	crc = getcrc(CRC_MASK, readbuf, rd);
+
+	while (head_size)                    // skip rest of header
+	{
+		rd = (head_size > size_buf) ? size_buf : head_size;
+		if (aceread(buf, rd) < rd)
+			return (0);
+		head_size -= rd;
+		crc = getcrc(crc, (UCHAR*)buf, rd);
+	}
+
+	head.HEAD_TYPE =*tp++;               // generic buffer to head conversion
+	head.HEAD_FLAGS=BUFP2WORD(tp);
+
+	if (head.HEAD_FLAGS & ACE_ADDSIZE)
+		skipsize = head.ADDSIZE = BUF2LONG(tp);   // get ADDSIZE
+	else
+		skipsize = 0;
+
+	// check header CRC
+	if (!(crc_ok = head.HEAD_CRC == (crc & 0xffff)) && print_err)
+		pipeit("\nError: archive is broken\n");
+	else
+		switch (head.HEAD_TYPE)              // specific buffer to head conversion
+		{
+		case MAIN_BLK:
+			memcpy(mhead.ACESIGN, tp, acesign_len); tp+=acesign_len;
+			mhead.VER_MOD=*tp++;
+			mhead.VER_CR =*tp++;
+			mhead.HOST_CR=*tp++;
+			mhead.VOL_NUM=*tp++;
+			mhead.TIME_CR=BUFP2LONG(tp);
+			mhead.RES1   =BUFP2WORD(tp);
+			mhead.RES2   =BUFP2WORD(tp);
+			mhead.RES    =BUFP2LONG(tp);
+			mhead.AV_SIZE=*tp++;
+			memcpy(mhead.AV, tp, rd-(USHORT)(tp-readbuf));
+			break;
+		case FILE_BLK:
+			fhead.PSIZE     =BUFP2LONG(tp);
+			fhead.SIZE      =BUFP2LONG(tp);
+			fhead.FTIME     =BUFP2LONG(tp);
+			fhead.ATTR      =BUFP2LONG(tp);
+			fhead.CRC32     =BUFP2LONG(tp);
+			fhead.TECH.TYPE =*tp++;
+			fhead.TECH.QUAL =*tp++;
+			fhead.TECH.PARM =BUFP2WORD(tp);
+			fhead.RESERVED  =BUFP2WORD(tp);
+			fhead.FNAME_SIZE=BUFP2WORD(tp);
+			memcpy(fhead.FNAME, tp, rd-(USHORT)(tp-readbuf));
+			break;
+			//    default: (REC_BLK and future things):
+			//              do nothing 'cause isn't needed for extraction
+		}
+
+	return (crc_ok);
+}
+// maximum SFX module size
+#define max_sfx_size 65536      // (needed by read_arc_head)
+
+INT read_arc_head(void)         // searches for the archive header and reads it
+{
+	INT  i,
+	flags,
+	buf_pos = 0;
+	LONG arc_head_pos,
+		old_fpos,
+	fpos = 0;
+	struct stat st;
+
+	fstat(archan, &st);
+
+	memset(buf, 0, size_buf);
+
+	while (acetell(archan)<acesize() && fpos < max_sfx_size)
+	{
+		old_fpos = fpos;
+		fpos += aceread(&buf[buf_pos], size_buf - buf_pos);
+
+		for (i = 0; i < size_buf; i++)    // look for the acesign
+		{
+			if (!memcmp(acesign, &buf[i], acesign_len))
+			{
+				// seek to the probable begin
+				// of the archive
+				arc_head_pos = old_fpos + i - buf_pos -  bytes_before_acesign;
+				acelseek(arc_head_pos, SEEK_SET);
+				if (read_header(0))         // try to read archive header
+				{
+					flags = mhead.HEAD_FLAGS;
+					adat.sol     = (flags & ACE_SOLID) > 0;
+					adat.vol     = (flags & ACE_MULT_VOL) > 0;
+					adat.vol_num = mhead.VOL_NUM;
+					adat.time_cr = mhead.TIME_CR;
+					return (1);
+				}
+			}
+		}
+		// was no archive header,
+		// continue search
+		acelseek(fpos, SEEK_SET);
+		memcpy(buf, &buf[size_buf - 512], 512);
+		buf_pos = 512;                    // keep 512 old bytes
+	}
+	return (0);
+}
+
+INT  open_archive(INT print_err)        // opens archive (or volume)
+{
+	CHAR av_str[80];
+
+#if defined(__OS2_) || defined(__EMX__) || defined(WIN32)
+	archan = aceopen(aname, O_RDONLY | O_BINARY);   // open file
+#else
+	archan = aceopen(aname, O_RDONLY);   // open file
+#endif
+
+	if (archan == -1)
+	{
+		error("\nError opening file %s", aname);
+		return (0);
+	}
+	if (!read_arc_head())                        // read archive header
+	{
+		error("Invalid embedded archive file.");
+		aceclose(archan);
+		return (0);
+	}
+
+	pipeit("\nProcessing archive: %s\n\n", aname);
+	if (head.HEAD_FLAGS & ACE_AV)
+	{
+		pipeit("Authenticity Verification:");   // print the AV
+		sprintf(av_str, "\ncreated on %d.%d.%d by ",
+				ts_day(adat.time_cr), ts_month(adat.time_cr), ts_year(adat.time_cr));
+		pipeit(av_str);
+		strncpy(av_str, (CHAR*)mhead.AV, mhead.AV_SIZE);
+		av_str[mhead.AV_SIZE] = 0;
+		pipeit("%s\n\n", av_str);
+	}
+	comment_out("Main comment:");        // print main comment
+	return (1);
+}
+
+void get_next_volname(void)             // get file name of next volume
+{
+	CHAR *cp;
+	INT  num;
+
+	if ((cp = (CHAR *) strrchr(aname, '.')) == NULL || !*(cp + 1))
+		num = -1;
+	else
+	{
+		cp++;
+		num = (*(cp + 1) - '0') * 10 + *(cp + 2) - '0';
+		if (!in(num, 0, 99))
+			num = -1;
+		if (in(*cp, '0', '9'))
+			num += (*cp - '0') * 100;
+	}
+	num++;
+
+	if (num < 100)
+		*cp = 'C';
+	else
+		*cp = num / 100 + '0';
+	*(cp + 1) = (num / 10) % 10 + '0';
+	*(cp + 2) = num % 10 + '0';
+}
+
+INT  proc_vol(void)                     // opens volume
+{
+	INT  i;
+	CHAR s[80];
+
+	if (!fileexists(aname) || !f_allvol_pr)
+	{
+		do
+		{
+			sprintf(s, "Ready to process %s?", aname);
+#if defined(__MINGW32__)
+			beep(500,500);
+#else
+			beep();
+#endif
+			i = confirm(s);                  // ask whether ready or not
+			f_allvol_pr = (i == 1);        // "Always" --> process all volumes
+			if (i >= 2)
+			{
+				f_err = ERR_FOUND;
+				return (0);
+			}
+		}
+		while (!fileexists(aname));
+	}
+
+	if (!open_archive(1))                // open volume
+	{
+		pipeit("\nError while opening archive. File not found or archive broken.\n");
+		f_err = ERR_OPEN;
+		return (0);
+	}
+
+	return (1);
+}
+
+INT  proc_next_vol(void)        // opens next volume to process
+{
+	aceclose(archan);               // close handle
+	get_next_volname();          // get file name of next volume
+
+	if (!proc_vol())             // try to open volume, read archive header
+		return 0;
+	if (!read_header(1))         // read 2nd header
+	{
+		f_err=ERR_READ;
+		return 0;
+	}
+	return 1;
+}
+
+INT  read_adds_blk(CHAR * buffer, INT len)      // reads part of ADD_SIZE block
+{
+	INT  rd = 0,
+	l = len;
+	LONG i;
+
+#ifdef CRYPT
+	char *cbuffer=buffer;
+
+	if (head.HEAD_TYPE == FILE_BLK && (head.HEAD_FLAGS & ACE_PASSW))
+		len = crypt_len(len);
+#endif /* CRYPT */
+	while (!f_err && len && skipsize)
+	{
+		i = (skipsize > len) ? len : skipsize;
+		skipsize -= i;
+
+		/* How do I test failure when compiling -mno-cygwin? */
+#if !defined(__MINGW32__)
+		errno = 0;
+#endif
+		rd += aceread(buffer, i);
+#if !defined(__MINGW32__)
+		if (errno)
+		{
+			error("\nRead error\n");
+			f_err = ERR_READ;
+		}
+#endif
+
+		buffer += i;
+		len -= i;
+
+		if (!skipsize)            // if block is continued on next volume
+			if (head.HEAD_FLAGS & ACE_SP_AFTER && !proc_next_vol())
+				break;
+	}
+#ifdef CRYPT
+	if (head.HEAD_TYPE == FILE_BLK && (head.HEAD_FLAGS & ACE_PASSW))
+		decrypt(cbuffer, rd);
+#endif /* CRYPT */
+
+	return (rd > l ? l : rd);
+}
+
+void crc_print(void)            // checks CRC, prints message
+{
+	INT  crc_not_ok = rd_crc != fhead.CRC32;  /* check CRC of file */
+
+	if(crc_not_ok && installstate != ABORTED)
+		error("CRC error reading archive!");
+}
+
+void analyze_file(void)         // analyzes one file (for solid archives)
+{
+	pipeit("\n Analyzing");
+	flush;
+	while (!cancel() && (dcpr_adds_blk(buf_wr, size_wrb))) // decompress only
+		;
+	crc_print();
+}
+
+void extract_file(void)         // extracts one file
+{
+	INT  rd;
+	extern char *image_data;
+	extern int get_image, image_size;
+
+	pipeit("\n Extracting");
+	flush;                       // decompress block
+	while (!cancel() && (rd = dcpr_adds_blk(buf_wr, size_wrb)))
+	{
+		if(get_image)
+		{
+			char *tmp = malloc(image_size+rd+1);
+			if(image_size && image_data)
+			{
+				memcpy(tmp, image_data, image_size);
+				free(image_data);
+			}
+			image_data = tmp;
+
+			memcpy(&image_data[image_size], buf_wr, rd);
+			image_size+=rd;
+			image_data[image_size] = '\0';
+		}
+		else
+		{
+			if (write(wrhan, buf_wr, rd) != rd)       // write block
+			{
+				error("\nWrite error\n");
+				f_err = ERR_WRITE;
+			}
+		}
+	}
+	crc_print();
+}
+
+
+/* extracts or tests all files of the archive
+ */
+void extract_files(int nopath, int test, char *getfilename)
+{
+	CHAR file[PATH_MAX];
+	char *tmpfile;
+	extern unsigned current_file;
+	extern char installdir2[];
+	extern int get_image;
+
+	while (!cancel() && read_header(1))
+	{
+		if (head.HEAD_TYPE == FILE_BLK)
+		{
+			if(installstate == ABORTED)
+				return;
+			current_file++;
+			if(installstate == INSTALLING)
+				DoGUI();
+
+			comment_out("File comment:");   // show file comment
+			ace_fname(file, &head, nopath); // get file name
+
+			/* We allow expansion of "userdir" to the selected directory by the user */
+			tmpfile = replacestr(file, "USERDIR", installdir2);
+			strcpy(file, tmpfile);
+			free(tmpfile);
+
+			if(!getfilename || (getfilename && stricmp(getfilename, file) == 0))
+			{
+				pipeit("\n%s", file);
+				flush;
+				dcpr_init_file();               // initialize decompression of file
+				if (!f_err)
+				{
+#if 0
+					if (test ||
+						(wrhan = create_dest_file(file, (INT) fhead.ATTR))<0)
+					{
+						if (test || adat.sol)
+							analyze_file();        // analyze file
+					}
+					else
+#endif
+						if(!get_image)
+							wrhan = create_dest_file(file, (INT) fhead.ATTR);
+					if(wrhan > -1)
+					{
+						extract_file();           // extract it
+#ifdef DOS                               // set file time
+						_dos_setftime(wrhan, (USHORT) (fhead.FTIME >> 16), (USHORT) fhead.FTIME);
+#endif
+						if(!get_image)
+							close(wrhan);
+#if defined(__OS2__) || defined(__EMX__)
+						{
+							FILESTATUS3 fileinfo;
+
+							DosQueryPathInfo(file, FIL_STANDARD, &fileinfo, sizeof(FILESTATUS3));
+							*((USHORT*)&fileinfo.fdateCreation)   = (USHORT)(fhead.FTIME >> 16);
+							*((USHORT*)&fileinfo.ftimeCreation)   = (USHORT)fhead.FTIME;
+							*((USHORT*)&fileinfo.fdateLastAccess) = (USHORT)(fhead.FTIME >> 16);
+							*((USHORT*)&fileinfo.ftimeLastAccess) = (USHORT)fhead.FTIME;
+							*((USHORT*)&fileinfo.fdateLastWrite)  = (USHORT)(fhead.FTIME >> 16);
+							*((USHORT*)&fileinfo.ftimeLastWrite)  = (USHORT)fhead.FTIME;
+							DosSetPathInfo(file, FIL_STANDARD, (PVOID)&fileinfo, sizeof(FILESTATUS3), 0);
+						}
+#endif
+#ifdef DOS                               // set file attributes
+						_dos_setfileattr(file, (UINT) fhead.ATTR);
+#endif
+#ifdef AMIGA
+						{                         // set file date and time
+							struct DateTime dt;
+							char Date[9], Time[9];
+							ULONG tstamp=fhead.FTIME;
+
+							sprintf(Date, "%02d-%02d-%02d", ts_year(tstamp)-1900, ts_month(tstamp), ts_day(tstamp));
+							sprintf(Time, "%02d:%02d:%02d", ts_hour(tstamp), ts_min(tstamp), ts_sec(tstamp));
+
+							dt.dat_Format = FORMAT_INT;
+							dt.dat_Flags  = 0;
+							dt.dat_StrDate= Date;
+							dt.dat_StrTime= Time;
+
+							if (StrToDate(&dt))
+								SetFileDate(file, &dt.dat_Stamp);
+						}
+#endif
+						if (f_err)
+							remove(file);
+					}
+				}
+			}
+		}
+	}
+}
+
+unsigned percentage(ULONG p, ULONG d)
+{
+	return (unsigned)( d ? (d/2+p*100)/d : 100 );
+}
+
+int installer_unpack(CHAR * filename, int operation)              // processes the archive
+{
+	init_unace();                              // initialize unace
+	strcpy(aname, "installer");                    // get archive name
+
+	if(filename)
+		f_ovrall=1;
+
+	if (open_archive(1))                       // open archive to process
+	{
+		if (adat.vol_num)
+			pipeit("\nFirst volume of archive required!\n");
+		else
+		{
+			if(operation == 2)
+				extract_files(0, 0, filename);
+		}
+		aceclose(archan);
+		if (f_err)
+		{
+			pipeit("\nError occurred\n");
+			if (f_criterr)
+				pipeit("Critical error on drive %c\n", f_criterr);
+		}
+	}
+
+	done_unace();
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxos2.rc	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,22 @@
+
+/* OS/2 Warp Resource Script File - Created by Universal Resource Editor */
+
+#define INCL_WINSYS
+#define INCL_WINSTDDLGS
+#define INCL_WINSTDSPIN
+#define INCL_NLS
+#define INCL_SW
+
+#include <os2.h>
+
+#include "install.h"
+
+/* User defined resources */
+ICON        2000        "..\\os2\\bitmaps\\install.ico"
+
+BITMAP      2001 	"..\\os2\\bitmaps\\install.bmp"
+
+/* Installer required resources. */
+ICON		FOLDERICON 	"..\\os2\\bitmaps\\folder.ico"
+ICON		FILEICON	"..\\os2\\bitmaps\\file.ico"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxwin.rc	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,12 @@
+#include <windows.h>
+#include "install.h"
+
+/* User defined resources */
+2000	ICON	"..\\win\\bitmaps\\install.ico"
+
+2001	BITMAP	"..\\win\\bitmaps\\install.bmp"
+
+/* Installer required resources. */
+FOLDERICON	ICON		"..\\win\\bitmaps\\folder.ico"
+FILEICON	ICON       	"..\\win\\bitmaps\\file.ico"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/Makefile.in	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,148 @@
+#==============================================================================
+# Makefile for UnZip, UnZipSFX and fUnZip:  Unix and MS-DOS ("real" makes only)
+# Version:  5.4                                                19 November 1998
+#==============================================================================
+
+
+# INSTRUCTIONS (such as they are):
+#
+# "make sunos"	-- makes UnZip in current directory on a generic SunOS 4.x Sun
+# "make list"	-- lists all supported systems (targets)
+# "make help"	-- provides pointers on what targets to try if problems occur
+# "make wombat" -- chokes and dies if you haven't added the specifics for your
+#		    Wombat 68000 (or whatever) to the systems list
+#
+# CF are flags for the C compiler.  LF are flags for the loader.  LF2 are more
+# flags for the loader, if they need to be at the end of the line instead of at
+# the beginning (for example, some libraries).  FL and FL2 are the corre-
+# sponding flags for fUnZip.  LOCAL_UNZIP is an environment variable that can
+# be used to add default C flags to your compile without editing the Makefile
+# (e.g., -DDEBUG_STRUC, or -FPi87 on PCs using Microsoft C).
+#
+# Some versions of make do not define the macro "$(MAKE)"; this is rare, but
+# if things don't work, try using "make" instead of "$(MAKE)" in your system's
+# makerule.  Or try adding the following line to your .login file:
+#	setenv MAKE "make"
+# (That never works--makes that are too stupid to define MAKE are also too
+# stupid to look in the environment--but try it anyway for kicks. :-) )
+#
+# Memcpy and memset are provided for those systems that don't have them; they
+# are in fileio.c and will be used if -DZMEM is included in CF.  These days
+# almost all systems have them.
+#
+# Be sure to test your new UnZip (and UnZipSFX and fUnZip); successful compila-
+# tion does not always imply a working program.
+
+
+#####################
+# MACRO DEFINITIONS #
+#####################
+
+# Defaults most systems use (use LOCAL_UNZIP in environment to add flags,
+# such as -DDOSWILD).
+
+# UnZip flags
+CC = cc#	try using "gcc" target rather than changing this (CC and LD
+LD = $(CC)#	must match, else "unresolved symbol:  ___main" is possible)
+AS = as
+LOC = $(LOCAL_UNZIP)
+AF = $(LOC)
+CF = -O -g -I. -I.. -I../inczip -D__UNIX__ -DDW_RESOURCES $(LOC) @CFLAGS@
+LF = -o sfx @LIBS@ -lregina
+LF2 = -s
+
+# general-purpose stuff
+#CP = cp
+CP = ln
+LN = ln
+RM = rm -f
+CHMOD = chmod
+BINPERMS = 755
+MANPERMS = 644
+STRIP = strip
+E =
+O = .o
+M = unix
+SHELL = /bin/sh
+
+# defaults for crc32 stuff and system dependent headers
+CRC32 = crc32
+
+# object files
+OBJS1 = unzip$O $(CRC32)$O crctab$O crypt$O envargs$O explode$O
+OBJS2 = extract$O fileio$O globals$O inflate$O list$O match$O
+OBJS3 = process$O ttyio$O unreduce$O unshrink$O zipinfo$O
+OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O install$O rexx$O instsup$O dw$O resources$O
+UNZIP_H = ../inczip/unzip.h ../inczip/unzpriv.h ../inczip/globals.h
+
+# installation
+# (probably can change next two to `install' and `install -d' if you have it)
+INSTALL = cp
+INSTALL_D = mkdir -p
+
+###############################################
+# BASIC COMPILE INSTRUCTIONS AND DEPENDENCIES #
+###############################################
+
+# this is for GNU make; comment out and notify zip-bugs if it causes errors
+.SUFFIXES:	.c .o .obj .pic.o
+
+# yes, we should be able to use the $O macro to combine these two, but it
+# fails on some brain-damaged makes (e.g., AIX's)...no big deal
+.c.o:
+	$(CC) -c $(CF) $*.c
+
+.c.obj:
+	$(CC) -c $(CF) $*.c
+
+.c.pic.o:
+	$(CC) -c $(CF) -o $@ $*.c
+
+all:	        sfx
+
+
+# EDIT HERE FOR PARALLEL MAKES on Sequent (and others?)--screws up MS-DOS
+# make utilities if default:  change "unzip$E:" to "unzip$E:&"
+
+sfx$E:	$(OBJS)			# add `&' for parallel makes
+	$(LD) $(LF) $(OBJS)
+
+crc32$O:	crc32.c $(UNZIP_H) ../inczip/zip.h
+crctab$O:	crctab.c $(UNZIP_H)  ../inczip/zip.h
+crypt$O:	crypt.c $(UNZIP_H)  ../inczip/zip.h  ../inczip/crypt.h  ../inczip/ttyio.h
+envargs$O:	envargs.c $(UNZIP_H)
+explode$O:	explode.c $(UNZIP_H)
+extract$O:	extract.c $(UNZIP_H)  ../inczip/crypt.h
+fileio$O:	fileio.c $(UNZIP_H)  ../inczip/crypt.h  ../inczip/ttyio.h  ../inczip/ebcdic.h
+funzip$O:	funzip.c $(UNZIP_H)  ../inczip/crypt.h  ../inczip/ttyio.h  ../inczip/tables.h
+globals$O:	globals.c $(UNZIP_H)
+inflate$O:	inflate.c  ../inczip/inflate.h $(UNZIP_H)
+list$O:		list.c $(UNZIP_H)
+match$O:	match.c $(UNZIP_H)
+process$O:	process.c $(UNZIP_H)
+ttyio$O:	ttyio.c $(UNZIP_H)  ../inczip/zip.h  ../inczip/crypt.h  ../inczip/ttyio.h
+unreduce$O:	unreduce.c $(UNZIP_H)
+unshrink$O:	unshrink.c $(UNZIP_H)
+unzip$O:	unzip.c $(UNZIP_H)  ../inczip/crypt.h  ../inczip/version.h  ../inczip/consts.h
+zipinfo$O:	zipinfo.c $(UNZIP_H)
+
+unix$O:		unix.c $(UNZIP_H)  ../inczip/version.h		# Unix only
+	$(CC) -c $(CF)  unix.c
+
+install$O:		../install.c	      
+	$(CC) -c $(CF)  ../install.c
+
+rexx$O:		../rexx.c
+	$(CC) -c $(CF)  ../rexx.c
+
+instsup$O:	        ../instsup.c 
+	$(CC) -c $(CF)  ../instsup.c
+
+dw$O:	        ../gtk/dw.c 
+	$(CC) -c $(CF)  ../gtk/dw.c
+
+resources$O:	        ../gtk/resources.c 
+	$(CC) -c $(CF)  ../gtk/resources.c
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/api.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,601 @@
+/*---------------------------------------------------------------------------
+
+  api.c
+
+  This module supplies an UnZip engine for use directly from C/C++
+  programs.  The functions are:
+
+    UzpVer *UzpVersion(void);
+    void UzpVersion2(UzpVer2 *version)
+    int UzpMain(int argc, char *argv[]);
+    int UzpAltMain(int argc, char *argv[], UzpInit *init);
+    int UzpValidate(char *archive, int AllCodes);
+    void UzpFreeMemBuffer(UzpBuffer *retstr);
+    int UzpUnzipToMemory(char *zip, char *file, UzpOpts *optflgs,
+                         UzpCB *UsrFuncts, UzpBuffer *retstr);
+
+  non-WINDLL only (a special WINDLL variant is defined in windll/windll.c):
+    int UzpGrep(char *archive, char *file, char *pattern, int cmd, int SkipBin,
+                UzpCB *UsrFuncts);
+
+  OS/2 only (for now):
+    int UzpFileTree(char *name, cbList(callBack), char *cpInclude[],
+          char *cpExclude[]);
+
+  You must define `DLL' in order to include the API extensions.
+
+  ---------------------------------------------------------------------------*/
+
+
+#ifdef OS2
+#  define  INCL_DOSMEMMGR
+#  include <os2.h>
+#endif
+#include <setjmp.h>
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#include "version.h"
+#ifdef WINDLL
+#  include "windll/windll.h"
+#endif
+
+#ifdef DLL      /* This source file supplies DLL-only interface code. */
+
+jmp_buf dll_error_return;
+
+/*---------------------------------------------------------------------------
+    Documented API entry points
+  ---------------------------------------------------------------------------*/
+
+
+UzpVer * UZ_EXP UzpVersion()   /* should be pointer to const struct */
+{
+    static UzpVer version;     /* doesn't change between calls */
+
+
+    version.structlen = UZPVER_LEN;
+
+#ifdef BETA
+    version.flag = 1;
+#else
+    version.flag = 0;
+#endif
+    version.betalevel = BETALEVEL;
+    version.date = VERSION_DATE;
+
+#ifdef ZLIB_VERSION
+    version.zlib_version = ZLIB_VERSION;
+    version.flag |= 2;
+#else
+    version.zlib_version = NULL;
+#endif
+
+    /* someday each of these may have a separate patchlevel: */
+    version.unzip.major = UZ_MAJORVER;
+    version.unzip.minor = UZ_MINORVER;
+    version.unzip.patchlevel = PATCHLEVEL;
+
+    version.zipinfo.major = ZI_MAJORVER;
+    version.zipinfo.minor = ZI_MINORVER;
+    version.zipinfo.patchlevel = PATCHLEVEL;
+
+    /* these are retained for backward compatibility only: */
+    version.os2dll.major = UZ_MAJORVER;
+    version.os2dll.minor = UZ_MINORVER;
+    version.os2dll.patchlevel = PATCHLEVEL;
+
+    version.windll.major = UZ_MAJORVER;
+    version.windll.minor = UZ_MINORVER;
+    version.windll.patchlevel = PATCHLEVEL;
+
+    return &version;
+}
+
+void UZ_EXP UzpVersion2(UzpVer2 *version)
+{
+
+    version->structlen = UZPVER_LEN;
+
+#ifdef BETA
+    version->flag = 1;
+#else
+    version->flag = 0;
+#endif
+    strcpy(version->betalevel, BETALEVEL);
+    strcpy(version->date, VERSION_DATE);
+
+#ifdef ZLIB_VERSION
+    strcpy(version->zlib_version, ZLIB_VERSION);
+    version->flag |= 2;
+#else
+    version->zlib_version[0] = '\0';
+#endif
+
+    /* someday each of these may have a separate patchlevel: */
+    version->unzip.major = UZ_MAJORVER;
+    version->unzip.minor = UZ_MINORVER;
+    version->unzip.patchlevel = PATCHLEVEL;
+
+    version->zipinfo.major = ZI_MAJORVER;
+    version->zipinfo.minor = ZI_MINORVER;
+    version->zipinfo.patchlevel = PATCHLEVEL;
+
+    /* these are retained for backward compatibility only: */
+    version->os2dll.major = UZ_MAJORVER;
+    version->os2dll.minor = UZ_MINORVER;
+    version->os2dll.patchlevel = PATCHLEVEL;
+
+    version->windll.major = UZ_MAJORVER;
+    version->windll.minor = UZ_MINORVER;
+    version->windll.patchlevel = PATCHLEVEL;
+}
+
+
+
+
+
+#ifndef WINDLL
+
+int UZ_EXP UzpAltMain(int argc, char *argv[], UzpInit *init)
+{
+    int r, (*dummyfn)();
+
+
+    CONSTRUCTGLOBALS();
+
+    if (init->structlen >= (sizeof(ulg) + sizeof(dummyfn)) && init->msgfn)
+        G.message = init->msgfn;
+
+    if (init->structlen >= (sizeof(ulg) + 2*sizeof(dummyfn)) && init->inputfn)
+        G.input = init->inputfn;
+
+    if (init->structlen >= (sizeof(ulg) + 3*sizeof(dummyfn)) && init->pausefn)
+        G.mpause = init->pausefn;
+
+    if (init->structlen >= (sizeof(ulg) + 4*sizeof(dummyfn)) && init->userfn)
+        (*init->userfn)();    /* allow void* arg? */
+
+    r = unzip(__G__ argc, argv);
+    DESTROYGLOBALS()
+    RETURN(r);
+}
+
+#endif /* !WINDLL */
+
+
+
+
+#ifndef __16BIT__
+
+void UZ_EXP UzpFreeMemBuffer(UzpBuffer *retstr)
+{
+    if (retstr->strptr != NULL) {
+        free(retstr->strptr);
+        retstr->strptr = NULL;
+    }
+}
+
+
+
+
+#ifndef WINDLL
+
+static int UzpDLL_Init OF((zvoid *pG, UzpCB *UsrFuncts));
+
+static int UzpDLL_Init(pG, UsrFuncts)
+zvoid *pG;
+UzpCB *UsrFuncts;
+{
+    int (*dummyfn)();
+
+    if (UsrFuncts->structlen >= (sizeof(ulg) + sizeof(dummyfn)) &&
+        UsrFuncts->msgfn)
+        ((Uz_Globs *)pG)->message = UsrFuncts->msgfn;
+    else
+        return FALSE;
+
+    if (UsrFuncts->structlen >= (sizeof(ulg) + 2*sizeof(dummyfn)) &&
+        UsrFuncts->inputfn)
+        ((Uz_Globs *)pG)->input = UsrFuncts->inputfn;
+
+    if (UsrFuncts->structlen >= (sizeof(ulg) + 3*sizeof(dummyfn)) &&
+        UsrFuncts->pausefn)
+        ((Uz_Globs *)pG)->mpause = UsrFuncts->pausefn;
+
+    if (UsrFuncts->structlen >= (sizeof(ulg) + 4*sizeof(dummyfn)) &&
+        UsrFuncts->passwdfn)
+        ((Uz_Globs *)pG)->decr_passwd = UsrFuncts->passwdfn;
+
+    if (UsrFuncts->structlen >= (sizeof(ulg) + 5*sizeof(dummyfn)) &&
+        UsrFuncts->statrepfn)
+        ((Uz_Globs *)pG)->statreportcb = UsrFuncts->statrepfn;
+
+    return TRUE;
+}
+
+
+int UZ_EXP UzpUnzipToMemory(char *zip, char *file, UzpOpts *optflgs,
+    UzpCB *UsrFuncts, UzpBuffer *retstr)
+{
+    int r;
+#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
+    char *intern_zip, *intern_file;
+#endif
+
+    CONSTRUCTGLOBALS();
+#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
+    intern_zip = (char *)malloc(strlen(zip)+1);
+    if (intern_zip == NULL) {
+       DESTROYGLOBALS()
+       return PK_MEM;
+    }
+    intern_file = (char *)malloc(strlen(file)+1);
+    if (intern_file == NULL) {
+       DESTROYGLOBALS()
+       free(intern_zip);
+       return PK_MEM;
+    }
+    ISO_TO_INTERN(zip, intern_zip);
+    ISO_TO_INTERN(file, intern_file);
+#   define zip intern_zip
+#   define file intern_file
+#endif
+    /* Copy those options that are meaningful for UzpUnzipToMemory, instead of
+     * a simple "memcpy(G.UzO, optflgs, sizeof(UzpOpts));"
+     */
+    uO.pwdarg = optflgs->pwdarg;
+    uO.aflag = optflgs->aflag;
+    uO.C_flag = optflgs->C_flag;
+    uO.qflag = optflgs->qflag;  /* currently,  overridden in unzipToMemory */
+
+    if (!UzpDLL_Init((zvoid *)&G, UsrFuncts)) {
+       DESTROYGLOBALS();
+       return PK_BADERR;
+    }
+    G.redirect_data = 1;
+
+    r = (unzipToMemory(__G__ zip, file, retstr) <= PK_WARN);
+
+    DESTROYGLOBALS()
+#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
+#  undef file
+#  undef zip
+    free(intern_file);
+    free(intern_zip);
+#endif
+    if (!r && retstr->strlength) {
+       free(retstr->strptr);
+       retstr->strptr = NULL;
+    }
+    return r;
+}
+#endif /* !WINDLL */
+#endif /* !__16BIT__ */
+
+
+
+
+
+#ifdef OS2DLL
+
+int UZ_EXP UzpFileTree(char *name, cbList(callBack), char *cpInclude[],
+                char *cpExclude[])
+{
+    int r;
+
+    CONSTRUCTGLOBALS();
+    uO.qflag = 2;
+    uO.vflag = 1;
+    uO.C_flag = 1;
+    G.wildzipfn = name;
+    G.process_all_files = TRUE;
+    if (cpInclude) {
+        char **ptr = cpInclude;
+
+        while (*ptr != NULL) ptr++;
+        G.filespecs = ptr - cpInclude;
+        G.pfnames = cpInclude, G.process_all_files = FALSE;
+    }
+    if (cpExclude) {
+        char **ptr = cpExclude;
+
+        while (*ptr != NULL) ptr++;
+        G.xfilespecs = ptr - cpExclude;
+        G.pxnames = cpExclude, G.process_all_files = FALSE;
+    }
+
+    G.processExternally = callBack;
+    r = process_zipfiles(__G)==0;
+    DESTROYGLOBALS()
+    return r;
+}
+
+#endif /* OS2DLL */
+
+
+
+
+/*---------------------------------------------------------------------------
+    Helper functions
+  ---------------------------------------------------------------------------*/
+
+
+void setFileNotFound(__G)
+    __GDEF
+{
+    G.filenotfound++;
+}
+
+
+
+int unzipToMemory(__GPRO__ char *zip, char *file, UzpBuffer *retstr)
+{
+    int r;
+    char *incname[2];
+
+    G.process_all_files = FALSE;
+    G.extract_flag = TRUE;
+    uO.qflag = 2;
+    G.wildzipfn = zip;
+
+    G.pfnames = incname;
+    incname[0] = file;
+    incname[1] = NULL;
+    G.filespecs = 1;
+
+    r = process_zipfiles(__G);
+    if (retstr) {
+        retstr->strptr = (char *)G.redirect_buffer;
+        retstr->strlength = G.redirect_size;
+    }
+    return r;                   /* returns `PK_???' error values */
+}
+
+
+
+int redirect_outfile(__G)
+     __GDEF
+{
+    if (G.redirect_size != 0 || G.redirect_buffer != NULL)
+        return FALSE;
+
+#ifndef NO_SLIDE_REDIR
+    G.redirect_slide = !G.pInfo->textmode;
+#endif
+    G.redirect_size = (G.pInfo->textmode ?
+                       G.lrec.ucsize * lenEOL : G.lrec.ucsize);
+#ifdef OS2
+    DosAllocMem((void **)&G.redirect_buffer, G.redirect_size+1,
+      PAG_READ|PAG_WRITE|PAG_COMMIT);
+    G.redirect_pointer = G.redirect_buffer;
+#else
+#ifdef __16BIT__
+    if ((ulg)((extent)G.redirect_size) != G.redirect_size)
+        return FALSE;
+#endif
+    G.redirect_pointer = G.redirect_buffer = malloc(G.redirect_size+1);
+#endif
+    if (!G.redirect_buffer)
+        return FALSE;
+    G.redirect_pointer[G.redirect_size] = '\0';
+    return TRUE;
+}
+
+
+
+int writeToMemory(__GPRO__ uch *rawbuf, ulg size)
+{
+    if (rawbuf != G.redirect_pointer)
+        memcpy(G.redirect_pointer,rawbuf,size);
+    G.redirect_pointer += size;
+    return 0;
+}
+
+
+
+
+int close_redirect(__G)
+     __GDEF
+{
+    if (G.pInfo->textmode) {
+        *G.redirect_pointer = '\0';
+        G.redirect_size = G.redirect_pointer - G.redirect_buffer;
+        if ((G.redirect_buffer =
+             realloc(G.redirect_buffer, G.redirect_size + 1)) == NULL) {
+            G.redirect_size = 0;
+            return EOF;
+        }
+    }
+    return 0;
+}
+
+
+
+
+#ifndef __16BIT__
+#ifndef WINDLL
+
+/* Purpose: Determine if file in archive contains the string szSearch
+
+   Parameters: archive  = archive name
+               file     = file contained in the archive. This cannot be
+                          a wild card to be meaningful
+               pattern  = string to search for
+               cmd      = 0 - case-insensitive search
+                          1 - case-sensitve search
+                          2 - case-insensitive, whole words only
+                          3 - case-sensitive, whole words only
+               SkipBin  = if true, skip any files that have control
+                          characters other than CR, LF, or tab in the first
+                          100 characters.
+
+   Returns:    TRUE if a match is found
+               FALSE if no match is found
+               -1 on error
+
+   Comments: This does not pretend to be as useful as the standard
+             Unix grep, which returns the strings associated with a
+             particular pattern, nor does it search past the first
+             matching occurrence of the pattern.
+ */
+
+int UZ_EXP UzpGrep(char *archive, char *file, char *pattern, int cmd,
+                   int SkipBin, UzpCB *UsrFuncts)
+{
+    int retcode = FALSE, compare;
+    ulg i, j, patternLen, buflen;
+    char * sz, *p;
+    UzpOpts flgopts;
+    UzpBuffer retstr;
+
+    memzero(&flgopts, sizeof(UzpOpts));         /* no special options */
+
+    if (!UzpUnzipToMemory(archive, file, &flgopts, UsrFuncts, &retstr)) {
+       return -1;   /* not enough memory, file not found, or other error */
+    }
+
+    if (SkipBin) {
+        if (retstr.strlength < 100)
+            buflen = retstr.strlength;
+        else
+            buflen = 100;
+        for (i = 0; i < buflen; i++) {
+            if (iscntrl(retstr.strptr[i])) {
+                if ((retstr.strptr[i] != 0x0A) &&
+                    (retstr.strptr[i] != 0x0D) &&
+                    (retstr.strptr[i] != 0x09))
+                {
+                    /* OK, we now think we have a binary file of some sort */
+                    free(retstr.strptr);
+                    return FALSE;
+                }
+            }
+        }
+    }
+
+    patternLen = strlen(pattern);
+
+    if (retstr.strlength < patternLen) {
+        free(retstr.strptr);
+        return FALSE;
+    }
+
+    sz = malloc(patternLen + 3); /* add two in case doing whole words only */
+    if (cmd > 1) {
+        strcpy(sz, " ");
+        strcat(sz, pattern);
+        strcat(sz, " ");
+    } else
+        strcpy(sz, pattern);
+
+    if ((cmd == 0) || (cmd == 2)) {
+        for (i = 0; i < strlen(sz); i++)
+            sz[i] = toupper(sz[i]);
+        for (i = 0; i < retstr.strlength; i++)
+            retstr.strptr[i] = toupper(retstr.strptr[i]);
+    }
+
+    for (i = 0; i < (retstr.strlength - patternLen); i++) {
+        p = &retstr.strptr[i];
+        compare = TRUE;
+        for (j = 0; j < patternLen; j++) {
+            /* We cannot do strncmp here, as we may be dealing with a
+             * "binary" file, such as a word processing file, or perhaps
+             * even a true executable of some sort. */
+            if (p[j] != sz[j]) {
+                compare = FALSE;
+                break;
+            }
+        }
+        if (compare == TRUE) {
+            retcode = TRUE;
+            break;
+        }
+    }
+
+    free(sz);
+    free(retstr.strptr);
+
+    return retcode;
+}
+#endif /* !WINDLL */
+#endif /* !__16BIT__ */
+
+
+
+
+int UZ_EXP UzpValidate(char *archive, int AllCodes)
+{
+    int retcode;
+    CONSTRUCTGLOBALS();
+
+    uO.jflag = 1;
+    uO.tflag = 1;
+    uO.overwrite_none = 0;
+    G.extract_flag = (!uO.zipinfo_mode &&
+                      !uO.cflag && !uO.tflag && !uO.vflag && !uO.zflag
+#ifdef TIMESTAMP
+                      && !uO.T_flag
+#endif
+                     );
+
+    uO.qflag = 2;                        /* turn off all messages */
+    G.fValidate = TRUE;
+    G.pfnames = (char **)&fnames[0];    /* assign default filename vector */
+#ifdef WINDLL
+    Wiz_NoPrinting(TRUE);
+#endif
+
+    if (archive == NULL) {      /* something is screwed up:  no filename */
+        DESTROYGLOBALS();
+        return PK_NOZIP;
+    }
+
+    G.wildzipfn = (char *)malloc(FILNAMSIZ + 1);
+    strcpy(G.wildzipfn, archive);
+#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
+    _ISO_INTERN(G.wildzipfn);
+#endif
+
+    G.process_all_files = TRUE;         /* for speed */
+
+    retcode = setjmp(dll_error_return);
+
+    if (retcode) {
+#ifdef WINDLL
+        Wiz_NoPrinting(FALSE);
+#endif
+        free(G.wildzipfn);
+        DESTROYGLOBALS();
+        return PK_BADERR;
+    }
+
+    retcode = process_zipfiles(__G);
+
+    free(G.wildzipfn);
+#ifdef WINDLL
+    Wiz_NoPrinting(FALSE);
+#endif
+    DESTROYGLOBALS();
+
+    /* PK_WARN == 1 and PK_FIND == 11. When we are just looking at an
+       archive, we should still be able to see the files inside it,
+       even if we can't decode them for some reason.
+
+       We also still want to be able to get at files even if there is
+       something odd about the zip archive, hence allow PK_WARN,
+       PK_FIND, IZ_UNSUP as well as PK_ERR
+     */
+
+    if (AllCodes)
+        return retcode;
+
+    if ((retcode == PK_OK) || (retcode == PK_WARN) || (retcode == PK_ERR) ||
+        (retcode == IZ_UNSUP) || (retcode == PK_FIND))
+        return TRUE;
+    else
+        return FALSE;
+}
+
+#endif /* DLL */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/apihelp.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,147 @@
+/* apihelp.c */
+
+#ifdef API_DOC
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#include "version.h"
+
+
+APIDocStruct APIDoc[] = {
+    {
+        "UZPVERSION"  , "UzpVersion"  ,
+        "UzpVer *UzpVersion(void);",
+        "Get version numbers of the API and the underlying UnZip code.\n\n"
+        "\t\tThis is used for comparing the version numbers of the run-time\n"
+        "\t\tDLL code with those expected from the unzip.h at compile time.\n"
+        "\t\tIf the version numbers do not match, there may be compatibility\n"
+        "\t\tproblems with further use of the DLL.\n\n"
+        "  Example:\t/* Check the major version number of the DLL code. */\n"
+        "\t\tUzpVer *pVersion;\n"
+        "\t\tpVersion = UzpVersion();\n"
+        "\t\tif (pVersion->unzip.major != UZ_MAJORVER)\n"
+        "\t\t  fprintf(stderr, \"error: using wrong version of DLL\\n\");\n\n"
+        "\t\tSee unzip.h for details and unzipstb.c for an example.\n"
+    },
+
+    {
+        "UZPMAIN"  , "UzpMain"  ,
+        "int UzpMain(int argc, char *argv[]);",
+        "Provide a direct entry point to the command line interface.\n\n"
+        "\t\tThis is used by the UnZip stub but you can use it in your\n"
+        "\t\town program as well.  Output is sent to stdout.\n"
+        "\t\t0 on return indicates success.\n\n"
+        "  Example:\t/* Extract 'test.zip' silently, junking paths. */\n"
+        "\t\tchar *argv[] = { \"-q\", \"-j\", \"test.zip\" };\n"
+        "\t\tint argc = 3;\n"
+        "\t\tif (UzpMain(argc,argv))\n"
+        "\t\t  printf(\"error: unzip failed\\n\");\n\n"
+        "\t\tSee unzip.h for details.\n"
+    },
+
+    {
+        "UZPALTMAIN"  , "UzpAltMain"  ,
+        "int UzpAltMain(int argc, char *argv[], UzpInit *init);",
+        "Provide a direct entry point to the command line interface,\n"
+        "optionally installing replacement I/O handler functions.\n\n"
+        "\t\tAs with UzpMain(), output is sent to stdout by default.\n"
+        "\t\t`InputFn *inputfn' is not yet implemented.  0 on return\n"
+        "\t\tindicates success.\n\n"
+        "  Example:\t/* Replace normal output and `more' functions. */\n"
+        "\t\tchar *argv[] = { \"-q\", \"-j\", \"test.zip\" };\n"
+        "\t\tint argc = 3;\n"
+        "\t\tUzpInit init = { 16, MyMessageFn, NULL, MyPauseFn };\n"
+        "\t\tif (UzpAltMain(argc,argv,&init))\n"
+        "\t\t  printf(\"error: unzip failed\\n\");\n\n"
+        "\t\tSee unzip.h for details.\n"
+    },
+
+    {
+        "UZPUNZIPTOMEMORY", "UzpUnzipToMemory",
+        "int UzpUnzipToMemory(char *zip, char *file, UzpBuffer *retstr);",
+        "Pass the name of the zip file and the name of the file\n"
+        "\t\tyou wish to extract.  UzpUnzipToMemory will create a\n"
+        "\t\tbuffer and return it in *retstr;  0 on return indicates\n"
+        "\t\tfailure.\n\n"
+        "\t\tSee unzip.h for details.\n"
+    },
+
+    {
+        "UZPFILETREE", "UzpFileTree",
+        "int UzpFileTree(char *name, cbList(callBack),\n"
+        "\t\t\tchar *cpInclude[], char *cpExclude[]);",
+        "Pass the name of the zip file, a callback function, an\n"
+        "\t\tinclude and exclude file list. UzpFileTree calls the\n"
+        "\t\tcallback for each valid file found in the zip file.\n"
+        "\t\t0 on return indicates failure.\n\n"
+        "\t\tSee unzip.h for details.\n"
+    },
+
+    { 0 }
+};
+
+
+static int function_help OF((__GPRO__ APIDocStruct *doc, char *fname));
+
+
+
+static int function_help(__G__ doc, fname)
+    __GDEF
+    APIDocStruct *doc;
+    char *fname;
+{
+    strcpy(slide, fname);
+    /* strupr(slide);    non-standard */
+    while (doc->compare && STRNICMP(doc->compare,slide,strlen(fname)))
+        doc++;
+    if (!doc->compare)
+        return 0;
+    else
+        Info(slide, 0, ((char *)slide,
+          "  Function:\t%s\n\n  Syntax:\t%s\n\n  Purpose:\t%s",
+          doc->function, doc->syntax, doc->purpose));
+
+    return 1;
+}
+
+
+
+void APIhelp(__G__ argc, argv)
+    __GDEF
+    int argc;
+    char **argv;
+{
+    if (argc > 1) {
+        struct APIDocStruct *doc;
+
+        if (function_help(__G__ APIDoc, argv[1]))
+            return;
+#ifdef SYSTEM_API_DETAILS
+        if (function_help(__G__ SYSTEM_API_DETAILS, argv[1]))
+            return;
+#endif
+        Info(slide, 0, ((char *)slide,
+          "%s is not a documented command.\n\n", argv[1]));
+    }
+
+    Info(slide, 0, ((char *)slide, "\
+This API provides a number of external C and REXX functions for handling\n\
+zipfiles in OS/2.  Programmers are encouraged to expand this API.\n\
+\n\
+C functions: -- See unzip.h for details\n\
+  UzpVer *UzpVersion(void);\n\
+  int UzpMain(int argc, char *argv[]);\n\
+  int UzpAltMain(int argc, char *argv[], UzpInit *init);\n\
+  int UzpUnzipToMemory(char *zip, char *file, UzpBuffer *retstr);\n\
+  int UzpFileTree(char *name, cbList(callBack),\n\
+                  char *cpInclude[], char *cpExclude[]);\n\n"));
+
+#ifdef SYSTEM_API_BRIEF
+    Info(slide, 0, ((char *)slide, SYSTEM_API_BRIEF));
+#endif
+
+    Info(slide, 0, ((char *)slide,
+      "\nFor more information, type 'unzip -A <function-name>'\n"));
+}
+
+#endif /* API_DOC */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/crc32.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,56 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $Id: crc32.c,v 1.1 2001/04/03 22:18:23 bsmith Exp $ */
+
+#define __CRC32_C       /* identifies this source module */
+
+#include "zip.h"
+
+#ifndef USE_ZLIB
+#ifndef ASM_CRC
+
+#ifndef ZCONST
+#  define ZCONST const
+#endif
+
+#ifdef CRC32
+#  undef CRC32
+#endif
+#define CRC32(c, b) (crc_table[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))
+#define DO1(buf)  crc = CRC32(crc, *buf++)
+#define DO2(buf)  DO1(buf); DO1(buf)
+#define DO4(buf)  DO2(buf); DO2(buf)
+#define DO8(buf)  DO4(buf); DO4(buf)
+
+/* ========================================================================= */
+ulg crc32(crc, buf, len)
+    register ulg crc;           /* crc shift register */
+    register ZCONST uch *buf;   /* pointer to bytes to pump through */
+    extent len;                 /* number of bytes in buf[] */
+/* Run a set of bytes through the crc shift register.  If buf is a NULL
+   pointer, then initialize the crc shift register contents instead.
+   Return the current crc in either case. */
+{
+  register ZCONST ulg near *crc_table;
+
+  if (buf == NULL) return 0L;
+
+  crc_table = get_crc_table();
+
+  crc = crc ^ 0xffffffffL;
+#ifndef NO_UNROLLED_LOOPS
+  while (len >= 8) {
+    DO8(buf);
+    len -= 8;
+  }
+#endif
+  if (len) do {
+    DO1(buf);
+  } while (--len);
+  return crc ^ 0xffffffffL;     /* (instead of ~c for 64-bit machines) */
+}
+#endif /* !ASM_CRC */
+#endif /* !USE_ZLIB */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/crc_i386.S	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,230 @@
+/*
+ * crc_i386.S, optimized CRC calculation function for Zip and UnZip, not
+ * copyrighted by Paul Kienitz and Christian Spieler.  Last revised 12 Oct 97.
+ *
+ * GRR 961110:  incorporated Scott Field optimizations from win32/crc_i386.asm
+ *              => overall 6% speedup in "unzip -tq" on 9MB zipfile (486-66)
+ *
+ * SPC 970402:  revised for Rodney Brown's optimizations (32-bit-wide
+ *              aligned reads for most of the data from buffer), can be
+ *              disabled by defining the macro NO_32_BIT_LOADS
+ *
+ * SPC 971012:  added Rodney Brown's additional tweaks for 32-bit-optimized
+ *              CPUs (like the Pentium Pro, Pentium II, and probably some
+ *              Pentium clones). This optimization is controlled by the
+ *              preprocessor switch "__686" and is disabled by default.
+ *              (This default is based on the assumption that most users
+ *              do not yet work on a Pentium Pro or Pentium II machine ...)
+ *
+ * FLAT memory model assumed.  Calling interface:
+ *   - args are pushed onto the stack from right to left,
+ *   - return value is given in the EAX register,
+ *   - all other registers (with exception of EFLAGS) are preserved. (With
+ *     GNU C 2.7.x, %edx and %ecx are `scratch' registers, but preserving
+ *     them nevertheless adds only 4 single byte instructions.)
+ *
+ * This source generates the function
+ * ulg crc32(ulg crc, ZCONST uch *buf, ulg len).
+ *
+ * The loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS.
+ * This results in shorter code at the expense of reduced performance.
+ */
+
+/* This file is NOT used in conjunction with zlib. */
+#ifndef USE_ZLIB
+
+/* Preprocess with -DNO_UNDERLINE if your C compiler does not prefix
+ * external symbols with an underline character '_'.
+ */
+#if defined(NO_UNDERLINE) || defined(__ELF__)
+#  define _crc32            crc32
+#  define _get_crc_table    get_crc_table
+#endif
+/* Use 16-byte alignment if your assembler supports it. Warning: gas
+ * uses a log(x) parameter (.align 4 means 16-byte alignment). On SVR4
+ * the parameter is a number of bytes.
+ */
+#ifndef ALIGNMENT
+#  define ALIGNMENT .align 4,0x90
+#endif
+
+#if defined(i386) || defined(_i386) || defined(_I386) || defined(__i386)
+
+/* This version is for 386 Unix, OS/2, MSDOS in 32 bit mode (gcc & gas).
+ * Warning: it uses the AT&T syntax: mov source,dest
+ * This file is only optional. If you want to use the C version,
+ * remove -DASM_CRC from CFLAGS in Makefile and set OBJA to an empty string.
+ */
+
+                .file   "crc_i386.S"
+
+#if defined(NO_STD_STACKFRAME) && defined(USE_STD_STACKFRAME)
+#  undef USE_STACKFRAME
+#else
+   /* The default is to use standard stack frame entry, because it
+    * results in smaller code!
+    */
+#  ifndef USE_STD_STACKFRAME
+#    define USE_STD_STACKFRAME
+#  endif
+#endif
+
+#ifdef USE_STD_STACKFRAME
+#  define _STD_ENTRY    pushl   %ebp ; movl   %esp,%ebp
+#  define arg1  8(%ebp)
+#  define arg2  12(%ebp)
+#  define arg3  16(%ebp)
+#  define _STD_LEAVE    popl    %ebp
+#else /* !USE_STD_STACKFRAME */
+#  define _STD_ENTRY
+#  define arg1  24(%esp)
+#  define arg2  28(%esp)
+#  define arg3  32(%esp)
+#  define _STD_LEAVE
+#endif /* ?USE_STD_STACKFRAME */
+
+/*
+ * These two (three) macros make up the loop body of the CRC32 cruncher.
+ * registers modified:
+ *   eax  : crc value "c"
+ *   esi  : pointer to next data byte (or lword) "buf++"
+ * registers read:
+ *   edi  : pointer to base of crc_table array
+ * scratch registers:
+ *   ebx  : index into crc_table array
+ *          (requires upper three bytes = 0 when __686 is undefined)
+ */
+#ifndef __686   /* optimize for 386, 486, Pentium */
+#define Do_CRC          /* c = (c >> 8) ^ table[c & 0xFF] */\
+                movb    %al, %bl                ;/* tmp = c & 0xFF  */\
+                shrl    $8, %eax                ;/* c = (c >> 8)    */\
+                xorl    (%edi, %ebx, 4), %eax   ;/* c ^= table[tmp] */
+#else   /* __686 : optimize for Pentium Pro and compatible CPUs */
+#define Do_CRC          /* c = (c >> 8) ^ table[c & 0xFF] */\
+                movzbl  %al, %ebx               ;/* tmp = c & 0xFF  */\
+                shrl    $8, %eax                ;/* c = (c >> 8)    */\
+                xorl    (%edi, %ebx, 4), %eax   ;/* c ^=table[tmp]  */
+#endif  /* ?__686 */
+
+#define Do_CRC_byte     /* c = (c >> 8) ^ table[(c^*buf++)&0xFF] */\
+                xorb    (%esi), %al     ;/* c ^= *buf  */\
+                incl    %esi            ;/* buf++      */\
+                Do_CRC
+
+#ifndef  NO_32_BIT_LOADS
+#define Do_CRC_lword \
+                xorl    (%esi), %eax    ;/* c ^= *(ulg *)buf */\
+                addl    $4, %esi        ;/* ((ulg *)buf)++   */\
+                Do_CRC \
+                Do_CRC \
+                Do_CRC \
+                Do_CRC
+#endif  /* !NO_32_BIT_LOADS */
+
+
+                .text
+
+                .globl  _crc32
+
+_crc32:                         /* ulg crc32(ulg crc, uch *buf, extent len) */
+                _STD_ENTRY
+                pushl   %edi
+                pushl   %esi
+                pushl   %ebx
+                pushl   %edx
+                pushl   %ecx
+
+                movl    arg2, %esi           /* 2nd arg: uch *buf            */
+                subl    %eax, %eax           /* > if (!buf)                  */
+                testl   %esi, %esi           /* >   return 0;                */
+                jz      .L_fine              /* > else {                     */
+                call    _get_crc_table
+                movl    %eax, %edi
+                movl    arg1, %eax           /* 1st arg: ulg crc             */
+#ifndef __686
+                subl    %ebx, %ebx           /* ebx=0; bl usable as dword    */
+#endif
+                movl    arg3, %ecx           /* 3rd arg: extent len          */
+                notl    %eax                 /* >   c = ~crc;                */
+
+#ifndef  NO_UNROLLED_LOOPS
+#  ifndef  NO_32_BIT_LOADS
+                testl   %ecx, %ecx
+                jz      .L_bail
+                /* Assert now have positive length */
+.L_align_loop:
+                testl   $3, %esi        /* Align buf on lword boundary */
+                jz      .L_aligned_now
+                Do_CRC_byte
+                decl    %ecx
+                jnz     .L_align_loop
+.L_aligned_now:
+#  endif  /* !NO_32_BIT_LOADS */
+                movl    %ecx, %edx           /* save len in edx          */
+                andl    $7, %edx             /* edx = len % 8            */
+                shrl    $3, %ecx             /* ecx = len / 8            */
+                jz      .L_No_Eights
+/*  align loop head at start of 486 internal cache line !! */
+                ALIGNMENT
+.L_Next_Eight:
+#  ifndef NO_32_BIT_LOADS
+                 /* Do_CRC_lword */
+                 xorl    (%esi), %eax    ;/* c ^= *(ulg *)buf */
+                 addl    $4, %esi        ;/* ((ulg *)buf)++   */
+                 Do_CRC
+                 Do_CRC
+                 Do_CRC
+                 Do_CRC
+                 /* Do_CRC_lword */
+                 xorl    (%esi), %eax    ;/* c ^= *(ulg *)buf */
+                 addl    $4, %esi        ;/* ((ulg *)buf)++   */
+                 Do_CRC
+                 Do_CRC
+                 Do_CRC
+                 Do_CRC
+#  else   /* NO_32_BIT_LOADS */
+                 Do_CRC_byte
+                 Do_CRC_byte
+                 Do_CRC_byte
+                 Do_CRC_byte
+                 Do_CRC_byte
+                 Do_CRC_byte
+                 Do_CRC_byte
+                 Do_CRC_byte
+#  endif  /* ?NO_32_BIT_LOADS */
+                decl    %ecx
+                jnz     .L_Next_Eight
+
+.L_No_Eights:
+                movl    %edx, %ecx
+#endif /* NO_UNROLLED_LOOPS */
+
+#ifndef NO_JECXZ_SUPPORT
+                jecxz   .L_bail              /* > if (len)                   */
+#else
+                testl   %ecx, %ecx           /* > if (len)                   */
+                jz      .L_bail
+#endif
+/* align loop head at start of 486 internal cache line !! */
+                ALIGNMENT
+.L_loupe:                                    /* >   do {                     */
+                 Do_CRC_byte                 /*       c = CRC32(c, *buf++);  */
+                decl    %ecx                 /* >   } while (--len);         */
+                jnz     .L_loupe
+
+.L_bail:                                     /* > }                          */
+                notl    %eax                 /* > return ~c;                 */
+.L_fine:
+                popl    %ecx
+                popl    %edx
+                popl    %ebx
+                popl    %esi
+                popl    %edi
+                _STD_LEAVE
+                ret
+
+#else
+ error: this asm version is for 386 only
+#endif /* i386 || _i386 || _I386 || __i386 */
+
+#endif /* !USE_ZLIB */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/crc_i386.asm	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,229 @@
+; crc_i386.asm, optimized CRC calculation function for Zip and UnZip, not
+; copyrighted by Paul Kienitz and Christian Spieler.  Last revised 25 Mar 98.
+;
+; Revised 06-Oct-96, Scott Field (sfield@microsoft.com)
+;   fixed to assemble with masm by not using .model directive which makes
+;   assumptions about segment alignment.  Also,
+;   avoid using loop, and j[e]cxz where possible.  Use mov + inc, rather
+;   than lodsb, and other misc. changes resulting in the following performance
+;   increases:
+;
+;      unrolled loops                NO_UNROLLED_LOOPS
+;      *8    >8      <8              *8      >8      <8
+;
+;      +54%  +42%    +35%            +82%    +52%    +25%
+;
+;   first item in each table is input buffer length, even multiple of 8
+;   second item in each table is input buffer length, > 8
+;   third item in each table is input buffer length, < 8
+;
+; Revised 02-Apr-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au)
+;   Incorporated Rodney Brown's 32-bit-reads optimization as found in the
+;   UNIX AS source crc_i386.S. This new code can be disabled by defining
+;   the macro symbol NO_32_BIT_LOADS.
+;
+; Revised 12-Oct-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au)
+;   Incorporated Rodney Brown's additional tweaks for 32-bit-optimized CPUs
+;   (like the Pentium Pro, Pentium II, and probably some Pentium clones).
+;   This optimization is controlled by the macro symbol __686 and is disabled
+;   by default. (This default is based on the assumption that most users
+;   do not yet work on a Pentium Pro or Pentium II machine ...)
+;
+; FLAT memory model assumed.
+;
+; The loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS.
+; This results in shorter code at the expense of reduced performance.
+;
+; Revised 25-Mar-98, Cosmin Truta (cosmint@cs.ubbcluj.ro)
+;   Working without .model directive caused tasm32 version 5.0 to produce
+;   bad object code. The optimized alignments can be optionally disabled
+;   by defining NO_ALIGN, thus allowing to use .model flat. There is no need
+;   to define this macro if using other version of tasm.
+;
+;==============================================================================
+;
+; Do NOT assemble this source if external crc32 routine from zlib gets used.
+;
+    IFNDEF USE_ZLIB
+;
+        .386p
+        name    crc_i386
+
+    IFDEF NO_ALIGN
+        .model flat
+    ENDIF
+
+extrn   _get_crc_table:near    ; ZCONST ulg near *get_crc_table(void);
+
+;
+    IFNDEF NO_STD_STACKFRAME
+        ; Use a `standard' stack frame setup on routine entry and exit.
+        ; Actually, this option is set as default, because it results
+        ; in smaller code !!
+STD_ENTRY       MACRO
+                push    ebp
+                mov     ebp,esp
+        ENDM
+
+        Arg1    EQU     08H[ebp]
+        Arg2    EQU     0CH[ebp]
+        Arg3    EQU     10H[ebp]
+
+STD_LEAVE       MACRO
+                pop     ebp
+        ENDM
+
+    ELSE  ; NO_STD_STACKFRAME
+
+STD_ENTRY       MACRO
+        ENDM
+
+        Arg1    EQU     18H[esp]
+        Arg2    EQU     1CH[esp]
+        Arg3    EQU     20H[esp]
+
+STD_LEAVE       MACRO
+        ENDM
+
+    ENDIF ; ?NO_STD_STACKFRAME
+
+; These two (three) macros make up the loop body of the CRC32 cruncher.
+; registers modified:
+;   eax  : crc value "c"
+;   esi  : pointer to next data byte (or dword) "buf++"
+; registers read:
+;   edi  : pointer to base of crc_table array
+; scratch registers:
+;   ebx  : index into crc_table array
+;          (requires upper three bytes = 0 when __686 is undefined)
+    IFNDEF  __686 ; optimize for 386, 486, Pentium
+Do_CRC  MACRO
+                mov     bl,al                ; tmp = c & 0xFF
+                shr     eax,8                ; c = (c >> 8)
+                xor     eax,[edi+ebx*4]      ;  ^ table[tmp]
+        ENDM
+    ELSE ; __686 : optimize for Pentium Pro, Pentium II and compatible CPUs
+Do_CRC  MACRO
+                movzx   ebx,al               ; tmp = c & 0xFF
+                shr     eax,8                ; c = (c >> 8)
+                xor     eax,[edi+ebx*4]      ;  ^ table[tmp]
+        ENDM
+    ENDIF ; ?__686
+Do_CRC_byte     MACRO
+                xor     al, byte ptr [esi]   ; c ^= *buf
+                inc     esi                  ; buf++
+                Do_CRC                       ; c = (c >> 8) ^ table[c & 0xFF]
+        ENDM
+    IFNDEF  NO_32_BIT_LOADS
+Do_CRC_dword    MACRO
+                xor     eax, dword ptr [esi] ; c ^= *(ulg *)buf
+                add     esi, 4               ; ((ulg *)buf)++
+                Do_CRC
+                Do_CRC
+                Do_CRC
+                Do_CRC
+        ENDM
+    ENDIF ; !NO_32_BIT_LOADS
+
+    IFNDEF NO_ALIGN
+_TEXT   segment use32 para public 'CODE'
+    ELSE
+_TEXT   segment use32
+    ENDIF
+        assume  CS: _TEXT
+
+        public  _crc32
+_crc32          proc    near  ; ulg crc32(ulg crc, ZCONST uch *buf, extent len)
+                STD_ENTRY
+                push    edi
+                push    esi
+                push    ebx
+                push    edx
+                push    ecx
+
+                mov     esi,Arg2             ; 2nd arg: uch *buf
+                sub     eax,eax              ;> if (!buf)
+                test    esi,esi              ;>   return 0;
+                jz      fine                 ;> else {
+
+                call    _get_crc_table
+                mov     edi,eax
+                mov     eax,Arg1             ; 1st arg: ulg crc
+    IFNDEF __686
+                sub     ebx,ebx              ; ebx=0; make bl usable as a dword
+    ENDIF
+                mov     ecx,Arg3             ; 3rd arg: extent len
+                not     eax                  ;>   c = ~crc;
+
+    IFNDEF  NO_UNROLLED_LOOPS
+    IFNDEF  NO_32_BIT_LOADS
+                test    ecx,ecx
+                je      bail
+align_loop:
+                test    esi,3                ; align buf pointer on next
+                jz      SHORT aligned_now    ;  dword boundary
+                Do_CRC_byte
+                dec     ecx
+                jnz     align_loop
+aligned_now:
+    ENDIF ; !NO_32_BIT_LOADS
+                mov     edx,ecx              ; save len in edx
+                and     edx,000000007H       ; edx = len % 8
+                shr     ecx,3                ; ecx = len / 8
+                jz      SHORT No_Eights
+    IFNDEF NO_ALIGN
+; align loop head at start of 486 internal cache line !!
+                align   16
+    ENDIF
+Next_Eight:
+    IFNDEF  NO_32_BIT_LOADS
+                Do_CRC_dword
+                Do_CRC_dword
+    ELSE ; NO_32_BIT_LOADS
+                Do_CRC_byte
+                Do_CRC_byte
+                Do_CRC_byte
+                Do_CRC_byte
+                Do_CRC_byte
+                Do_CRC_byte
+                Do_CRC_byte
+                Do_CRC_byte
+    ENDIF ; ?NO_32_BIT_LOADS
+                dec     ecx
+                jnz     Next_Eight
+No_Eights:
+                mov     ecx,edx
+
+    ENDIF ; NO_UNROLLED_LOOPS
+    IFNDEF  NO_JECXZ_SUPPORT
+                jecxz   bail                 ;>   if (len)
+    ELSE
+                test    ecx,ecx              ;>   if (len)
+                jz      SHORT bail
+    ENDIF
+    IFNDEF NO_ALIGN
+; align loop head at start of 486 internal cache line !!
+                align   16
+    ENDIF
+loupe:                                       ;>     do {
+                Do_CRC_byte                  ;        c = CRC32(c, *buf++);
+                dec     ecx                  ;>     } while (--len);
+                jnz     loupe
+
+bail:                                        ;> }
+                not     eax                  ;> return ~c;
+fine:
+                pop     ecx
+                pop     edx
+                pop     ebx
+                pop     esi
+                pop     edi
+                STD_LEAVE
+                ret
+_crc32          endp
+
+_TEXT   ends
+;
+    ENDIF ; !USE_ZLIB
+;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/crc_i386.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,215 @@
+/* crc_i386.c -- Microsoft 32-bit C/C++ adaptation of crc_i386.asm
+ * Created by Rodney Brown from crc_i386.asm, modified by Chr. Spieler.
+ * Last revised: 22-Mai-1998
+ *
+ * Original coded (in crc_i386.asm) and put into the public domain
+ * by Paul Kienitz and Christian Spieler.
+ *
+ * Revised 06-Oct-96, Scott Field (sfield@microsoft.com)
+ *   fixed to assemble with masm by not using .model directive which makes
+ *   assumptions about segment alignment.  Also,
+ *   avoid using loop, and j[e]cxz where possible.  Use mov + inc, rather
+ *   than lodsb, and other misc. changes resulting in the following performance
+ *   increases:
+ *
+ *      unrolled loops                NO_UNROLLED_LOOPS
+ *      *8    >8      <8              *8      >8      <8
+ *
+ *      +54%  +42%    +35%            +82%    +52%    +25%
+ *
+ *   first item in each table is input buffer length, even multiple of 8
+ *   second item in each table is input buffer length, > 8
+ *   third item in each table is input buffer length, < 8
+ *
+ * Revised 02-Apr-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au)
+ *   Incorporated Rodney Brown's 32-bit-reads optimization as found in the
+ *   UNIX AS source crc_i386.S. This new code can be disabled by defining
+ *   the macro symbol NO_32_BIT_LOADS.
+ *
+ * Revised 12-Oct-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au)
+ *   Incorporated Rodney Brown's additional tweaks for 32-bit-optimized CPUs
+ *   (like the Pentium Pro, Pentium II, and probably some Pentium clones).
+ *   This optimization is controlled by the macro symbol __686 and is disabled
+ *   by default. (This default is based on the assumption that most users
+ *   do not yet work on a Pentium Pro or Pentium II machine ...)
+ *
+ * Revised 16-Nov-97, Chr. Spieler: Made code compatible with Borland C++
+ *   32-bit, removed unneeded kludge for potentially unknown movzx mnemonic,
+ *   confirmed correct working with MS VC++ (32-bit).
+ *
+ * Revised 22-Mai-98, Peter Kunath, Chr. Spieler : The 16-Nov-97 revision broke
+ *   MSVC 5.0. Inside preprocessor macros, each instruction is enclosed in its
+ *   own __asm {...} construct.  For MSVC, a "#pragma warning" was added to
+ *   shut up the "no return value" warning message.
+ *
+ * FLAT memory model assumed.
+ *
+ * The loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS.
+ * This results in shorter code at the expense of reduced performance.
+ *
+ */
+
+#include "zip.h"
+
+#ifndef USE_ZLIB
+
+#ifndef ZCONST
+#  define ZCONST const
+#endif
+
+/* Select wether the following inline-assember code is supported. */
+#if (defined(_MSC_VER) && _MSC_VER >= 700)
+#if (defined(_M_IX86) && _M_IX86 >= 300)
+#  define MSC_INLINE_ASM_32BIT_SUPPORT
+   /* Disable warning for no return value, typical of asm functions */
+#  pragma warning( disable : 4035 )
+#endif
+#endif
+
+#if (defined(__BORLANDC__) && __BORLANDC__ >= 452)
+#  define MSC_INLINE_ASM_32BIT_SUPPORT
+#endif
+
+#ifdef MSC_INLINE_ASM_32BIT_SUPPORT
+/* This code is intended for Microsoft C/C++ (32-bit) compatible compilers. */
+
+/*
+ * These two (three) macros make up the loop body of the CRC32 cruncher.
+ * registers modified:
+ *   eax  : crc value "c"
+ *   esi  : pointer to next data byte (or dword) "buf++"
+ * registers read:
+ *   edi  : pointer to base of crc_table array
+ * scratch registers:
+ *   ebx  : index into crc_table array
+ *          (requires upper three bytes = 0 when __686 is undefined)
+ */
+#ifndef __686
+#define Do_CRC { \
+  __asm { mov   bl, al }; \
+  __asm { shr   eax, 8 }; \
+  __asm { xor   eax, [edi+ebx*4] }; }
+#else /* __686 */
+#define Do_CRC { \
+  __asm { movzx ebx, al }; \
+  __asm { shr   eax, 8  }; \
+  __asm { xor   eax, [edi+ebx*4] }; }
+#endif /* ?__686 */
+
+#define Do_CRC_byte { \
+  __asm { xor   al, byte ptr [esi] }; \
+  __asm { inc   esi }; \
+  Do_CRC; }
+
+#ifndef NO_32_BIT_LOADS
+#define Do_CRC_dword { \
+  __asm { xor   eax, dword ptr [esi] }; \
+  __asm { add   esi, 4 }; \
+  Do_CRC; \
+  Do_CRC; \
+  Do_CRC; \
+  Do_CRC; }
+#endif /* !NO_32_BIT_LOADS */
+
+/* ========================================================================= */
+ulg crc32(crc, buf, len)
+    ulg crc;                    /* crc shift register */
+    ZCONST uch *buf;            /* pointer to bytes to pump through */
+    extent len;                 /* number of bytes in buf[] */
+/* Run a set of bytes through the crc shift register.  If buf is a NULL
+   pointer, then initialize the crc shift register contents instead.
+   Return the current crc in either case. */
+{
+    __asm {
+                push    edx
+                push    ecx
+
+                mov     esi,buf         ;/* 2nd arg: uch *buf              */
+                sub     eax,eax         ;/*> if (!buf)                     */
+                test    esi,esi         ;/*>   return 0;                   */
+                jz      fine            ;/*> else {                        */
+
+                call    get_crc_table
+                mov     edi,eax
+                mov     eax,crc         ;/* 1st arg: ulg crc               */
+#ifndef __686
+                sub     ebx,ebx         ;/* ebx=0; => bl usable as a dword */
+#endif
+                mov     ecx,len         ;/* 3rd arg: extent len            */
+                not     eax             ;/*>   c = ~crc;                   */
+
+#ifndef NO_UNROLLED_LOOPS
+#  ifndef NO_32_BIT_LOADS
+                test    ecx,ecx
+                je      bail
+align_loop:
+                test    esi,3           ;/* align buf pointer on next      */
+                jz      aligned_now     ;/*  dword boundary                */
+    }
+                Do_CRC_byte             ;
+    __asm {
+                dec     ecx
+                jnz     align_loop
+aligned_now:
+#  endif /* !NO_32_BIT_LOADS */
+                mov     edx,ecx         ;/* save len in edx  */
+                and     edx,000000007H  ;/* edx = len % 8    */
+                shr     ecx,3           ;/* ecx = len / 8    */
+                jz      No_Eights
+; align loop head at start of 486 internal cache line !!
+                align   16
+Next_Eight:
+    }
+#  ifndef NO_32_BIT_LOADS
+                Do_CRC_dword ;
+                Do_CRC_dword ;
+#  else /* NO_32_BIT_LOADS */
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+                Do_CRC_byte ;
+#  endif /* ?NO_32_BIT_LOADS */
+    __asm {
+                dec     ecx
+                jnz     Next_Eight
+No_Eights:
+                mov     ecx,edx
+
+#endif /* NO_UNROLLED_LOOPS */
+#ifndef NO_JECXZ_SUPPORT
+                jecxz   bail            ;/*>  if (len)                     */
+#else
+                test    ecx,ecx         ;/*>  if (len)                     */
+                jz      bail
+#endif
+; align loop head at start of 486 internal cache line !!
+                align   16
+loupe:                                  ;/*>    do { */
+    }
+                Do_CRC_byte             ;/*       c = CRC32(c, *buf++);    */
+    __asm {
+                dec     ecx             ;/*>    } while (--len);           */
+                jnz     loupe
+
+bail:                                   ;/*> }                             */
+                not     eax             ;/*> return ~c;                    */
+fine:
+                pop     ecx
+                pop     edx
+    }
+#ifdef NEED_RETURN
+    return _EAX;
+#endif
+}
+#endif /* MSC_INLINE_ASM_32BIT_SUPPORT */
+#if (defined(_MSC_VER) && _MSC_VER >= 700)
+#if (defined(_M_IX86) && _M_IX86 >= 300)
+   /* Reenable missing return value warning */
+#  pragma warning( default : 4035 )
+#endif
+#endif
+#endif /* !USE_ZLIB */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/crc_lcc.asm	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,108 @@
+; crc_lcc.asm, optimized CRC calculation function for Zip and UnZip, not
+; copyrighted by Paul Kienitz and Christian Spieler.  Last revised 25 Mar 98.
+;
+; The code in this file has been copied verbatim from crc_i386.{asm|S};
+; only the assembler syntax and metacommands have been adapted to
+; the habits of the free LCC-Win32 C compiler package.
+; This version of the code uses the "optimized for i686" variant of
+; crc_i386.{asm|S}.
+;
+; For more information (and a revision log), look into the original
+; source files.
+;
+	.text
+	.file "crc32.c"
+	.text
+	.type	_crc32,function
+_crc32:
+	pushl	%ebp
+	movl	%esp,%ebp
+	pushl	%ecx
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+	.line	34
+	.line	37
+	movl	12(%ebp),%esi
+	subl	%eax,%eax
+	testl	%esi,%esi
+	jz	_$3
+	.line	39
+	call	_get_crc_table
+	movl	%eax,%edi
+	.line	41
+	movl	8(%ebp),%eax
+	movl	16(%ebp),%ecx
+	notl	%eax
+	testl	%ecx,%ecx
+	jz	_$4
+_$5:
+	testl	$3,%esi
+	jz	_$6
+	xorb    (%esi),%al
+	incl	%esi
+	movzbl	%al,%ebx
+	shrl	$8,%eax
+	xorl	(%edi,%ebx,4),%eax
+	decl	%ecx
+	jnz	_$5
+_$6:
+	movl	%ecx,%edx
+	andl	$7,%edx
+	shrl	$3,%ecx
+	jz	_$8
+_$7:
+	xorl	(%esi),%eax
+	addl	$4,%esi
+	movzbl	%al,%ebx
+	shrl	$8,%eax
+	xorl	(%edi,%ebx,4),%eax
+	movzbl	%al,%ebx
+	shrl	$8,%eax
+	xorl	(%edi,%ebx,4),%eax
+	movzbl	%al,%ebx
+	shrl	$8,%eax
+	xorl	(%edi,%ebx,4),%eax
+	movzbl	%al,%ebx
+	shrl	$8,%eax
+	xorl	(%edi,%ebx,4),%eax
+	xorl	(%esi),%eax
+	addl	$4,%esi
+	movzbl	%al,%ebx
+	shrl	$8,%eax
+	xorl	(%edi,%ebx,4),%eax
+	movzbl	%al,%ebx
+	shrl	$8,%eax
+	xorl	(%edi,%ebx,4),%eax
+	movzbl	%al,%ebx
+	shrl	$8,%eax
+	xorl	(%edi,%ebx,4),%eax
+	movzbl	%al,%ebx
+	shrl	$8,%eax
+	xorl	(%edi,%ebx,4),%eax
+	decl	%ecx
+	jnz	_$7
+_$8:
+	movl	%edx,%ecx
+	jecxz	_$4
+_$9:
+	xorb    (%esi),%al
+	incl    %esi
+	movzbl	%al,%ebx
+	shrl	$8,%eax
+	xorl	(%edi,%ebx,4),%eax
+	decl	%ecx
+	jnz	_$9
+_$4:
+	xorl	$0xffffffff,%eax
+_$3:
+	.line	52
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	leave
+	ret
+_$34:
+	.size	_crc32,_$34-_crc32
+	.globl	_crc32
+	.extern	_get_crc_table
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/crctab.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,219 @@
+/* crctab.c -- supply the CRC table needed for CRC-32 calculations.
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $Id: crctab.c,v 1.1 2001/04/03 22:18:24 bsmith Exp $ */
+
+/*
+  Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
+  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+  Polynomials over GF(2) are represented in binary, one bit per coefficient,
+  with the lowest powers in the most significant bit.  Then adding polynomials
+  is just exclusive-or, and multiplying a polynomial by x is a right shift by
+  one.  If we call the above polynomial p, and represent a byte as the
+  polynomial q, also with the lowest power in the most significant bit (so the
+  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+  where a mod b means the remainder after dividing a by b.
+
+  This calculation is done using the shift-register method of multiplying and
+  taking the remainder.  The register is initialized to zero, and for each
+  incoming bit, x^32 is added mod p to the register if the bit is a one (where
+  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+  x (which is shifting right by one and adding x^32 mod p if the bit shifted
+  out is a one).  We start with the highest power (least significant bit) of
+  q and repeat for all eight bits of q.
+
+  The table is simply the CRC of all possible eight bit values.  This is all
+  the information needed to generate CRC's on data a byte at a time for all
+  combinations of CRC register values and incoming bytes.
+*/
+
+#define __CRCTAB_C      /* identifies this source module */
+
+#include "zip.h"
+
+#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))
+
+#ifndef ZCONST
+#  define ZCONST const
+#endif
+
+#ifdef DYNAMIC_CRC_TABLE
+
+/* =========================================================================
+ * Make the crc table. This function is needed only if you want to compute
+ * the table dynamically.
+ */
+
+local void make_crc_table OF((void));
+
+#if (defined(DYNALLOC_CRCTAB) && defined(REENTRANT))
+   error: Dynamic allocation of CRC table not safe with reentrant code.
+#endif /* DYNALLOC_CRCTAB && REENTRANT */
+
+#ifdef DYNALLOC_CRCTAB
+   local ulg near *crc_table = NULL;
+# if 0          /* not used, since sizeof("near *") <= sizeof(int) */
+   /* Use this section when access to a "local int" is faster than access to
+      a "local pointer" (e.g.: i86 16bit code with far pointers). */
+   local int crc_table_empty = 1;
+#  define CRC_TABLE_IS_EMPTY    (crc_table_empty != 0)
+#  define MARK_CRCTAB_FILLED    crc_table_empty = 0
+#  define MARK_CRCTAB_EMPTY     crc_table_empty = 1
+# else
+   /* Use this section on systems where the size of pointers and ints is
+      equal (e.g.: all 32bit systems). */
+#  define CRC_TABLE_IS_EMPTY    (crc_table == NULL)
+#  define MARK_CRCTAB_FILLED    crc_table = crctab_p
+#  define MARK_CRCTAB_EMPTY     crc_table = NULL
+# endif
+#else /* !DYNALLOC_CRCTAB */
+   local ulg near crc_table[256];
+   local int crc_table_empty = 1;
+#  define CRC_TABLE_IS_EMPTY    (crc_table_empty != 0)
+#  define MARK_CRCTAB_FILLED    crc_table_empty = 0
+#endif /* ?DYNALLOC_CRCTAB */
+
+
+local void make_crc_table()
+{
+  ulg c;                /* crc shift register */
+  int n;                /* counter for all possible eight bit values */
+  int k;                /* byte being shifted into crc apparatus */
+#ifdef DYNALLOC_CRCTAB
+  ulg near *crctab_p;   /* temporary pointer to allocated crc_table area */
+#else /* !DYNALLOC_CRCTAB */
+# define crctab_p crc_table
+#endif /* DYNALLOC_CRCTAB */
+
+#ifdef COMPUTE_XOR_PATTERN
+  /* This piece of code has been left here to explain how the XOR pattern
+   * used in the creation of the crc_table values can be recomputed.
+   * For production versions of this function, it is more efficient to
+   * supply the resultant pattern at compile time.
+   */
+  ulg xor;              /* polynomial exclusive-or pattern */
+  /* terms of polynomial defining this crc (except x^32): */
+  static uch p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+  /* make exclusive-or pattern from polynomial (0xedb88320L) */
+  xor = 0L;
+  for (i = 0; i < sizeof(p)/sizeof(uch); i++)
+    xor |= 1L << (31 - p[i]);
+#else
+# define xor 0xedb88320L
+#endif
+
+#ifdef DYNALLOC_CRCTAB
+  crctab_p = (ulg near *) nearmalloc (256*sizeof(ulg));
+  if (crctab_p == NULL) {
+    ziperr(ZE_MEM, "crc_table allocation");
+  }
+#endif /* DYNALLOC_CRCTAB */
+
+  for (n = 0; n < 256; n++) {
+    c = (ulg)n;
+    for (k = 8; k; k--)
+      c = c & 1 ? xor ^ (c >> 1) : c >> 1;
+    crctab_p[n] = c;
+  }
+  MARK_CRCTAB_FILLED;
+}
+
+#else /* !DYNAMIC_CRC_TABLE */
+
+#ifdef DYNALLOC_CRCTAB
+   error: Inconsistent flags, DYNALLOC_CRCTAB without DYNAMIC_CRC_TABLE.
+#endif
+
+/* ========================================================================
+ * Table of CRC-32's of all single-byte values (made by make_crc_table)
+ */
+local ZCONST ulg near crc_table[256] = {
+  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+  0x2d02ef8dL
+};
+#endif /* ?DYNAMIC_CRC_TABLE */
+
+/* use "OF((void))" here to work around a Borland TC++ 1.0 problem */
+#ifdef USE_ZLIB
+ZCONST uLongf *get_crc_table OF((void))
+#else
+ZCONST ulg near *get_crc_table OF((void))
+#endif
+{
+#ifdef DYNAMIC_CRC_TABLE
+  if (CRC_TABLE_IS_EMPTY)
+    make_crc_table();
+#endif
+#ifdef USE_ZLIB
+  return (ZCONST uLongf *)crc_table;
+#else
+  return (ZCONST ulg near *)crc_table;
+#endif
+}
+
+#ifdef DYNALLOC_CRCTAB
+void free_crc_table()
+{
+  if (!CRC_TABLE_IS_EMPTY)
+  {
+    nearfree((ulg near *)crc_table);
+    MARK_CRCTAB_EMPTY;
+  }
+}
+#endif
+
+#endif /* !USE_ZLIB || USE_OWN_CRCTAB */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/crypt.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,12 @@
+/*
+   crypt.c (dummy version) by Info-ZIP.      Last revised: 15 Aug 98
+
+   This is a non-functional version of Info-ZIP's crypt.c encryption/
+   decryption code for Zip, ZipCloak, UnZip and fUnZip.  This file is
+   not copyrighted and may be distributed freely. :-)  See the "WHERE"
+   file for sites from which to obtain the full encryption/decryption
+   sources (zcrypt28.zip or later).
+ */
+
+/* something "externally visible" to shut up compiler/linker warnings */
+int zcr_dummy;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/envargs.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,314 @@
+/*----------------------------------------------------------------*
+ | envargs - add default options from environment to command line
+ |----------------------------------------------------------------
+ | Author: Bill Davidsen, original 10/13/91, revised 23 Oct 1991.
+ | This program is in the public domain.
+ |----------------------------------------------------------------
+ | Minor program notes:
+ |  1. Yes, the indirection is a tad complex
+ |  2. Parentheses were added where not needed in some cases
+ |     to make the action of the code less obscure.
+ |----------------------------------------------------------------
+ | UnZip notes: 24 May 92 ("v1.4"):
+ |  1. #include "unzip.h" for prototypes (24 May 92)
+ |  2. changed ch to type char (24 May 92)
+ |  3. added an ifdef to avoid Borland warnings (24 May 92)
+ |  4. included Rich Wales' mksargs() routine (for MS-DOS, maybe
+ |     OS/2? NT?) (4 Dec 93)
+ |  5. added alternate-variable string envstr2 (21 Apr 94)
+ |  6. added support for quoted arguments (6 Jul 96)
+ *----------------------------------------------------------------*/
+
+
+#define ENVARGS_C
+#define UNZIP_INTERNAL
+#include "unzip.h"
+
+#ifdef __EMX__          /* emx isspace() returns TRUE on extended ASCII !! */
+#  define ISspace(c) ((c) & 0x80 ? 0 : isspace((unsigned)c))
+#else
+#  define ISspace(c) isspace((unsigned)c)
+#endif /* ?__EMX__ */
+
+static int count_args OF((ZCONST char *));
+static void mem_err OF((__GPRO));
+
+static ZCONST char Far NoMemArguments[] =
+  "envargs:  cannot get memory for arguments";
+
+
+void envargs(__G__ Pargc, Pargv, envstr, envstr2)
+    __GDEF
+    int *Pargc;
+    char ***Pargv;
+    ZCONST char *envstr, *envstr2;
+{
+#ifndef RISCOS
+    char *getenv();
+#endif
+    char *envptr;       /* value returned by getenv */
+    char *bufptr;       /* copy of env info */
+    int argc = 0;       /* internal arg count */
+    register int ch;    /* spare temp value */
+    char **argv;        /* internal arg vector */
+    char **argvect;     /* copy of vector address */
+
+    /* see if anything in the environment */
+    if ((envptr = getenv(envstr)) != (char *)NULL)        /* usual var */
+        while (ISspace(*envptr))        /* must discard leading spaces */
+            envptr++;
+    if (envptr == (char *)NULL || *envptr == '\0')
+        if ((envptr = getenv(envstr2)) != (char *)NULL)   /* alternate var */
+            while (ISspace(*envptr))
+                envptr++;
+    if (envptr == (char *)NULL || *envptr == '\0')
+        return;
+
+    bufptr = malloc(1 + strlen(envptr));
+    if (bufptr == (char *)NULL)
+        mem_err(__G);
+#if (defined(WIN32) || defined(WINDLL))
+# ifdef WIN32
+    if (IsWinNT()) {
+        /* SPC: don't know codepage of 'real' WinNT console */
+        strcpy(bufptr, envptr);
+    } else {
+        /* Win95 environment is DOS and uses OEM character coding */
+        OEM_TO_INTERN(envptr, bufptr);
+    }
+# else /* !WIN32 */
+    /* DOS environment uses OEM codepage */
+    OEM_TO_INTERN(envptr, bufptr);
+# endif
+#else /* !(WIN32 || WINDLL) */
+    strcpy(bufptr, envptr);
+#endif /* ?(WIN32 || WINDLL) */
+
+    /* count the args so we can allocate room for them */
+    argc = count_args(bufptr);
+    /* allocate a vector large enough for all args */
+    argv = (char **)malloc((argc + *Pargc + 1) * sizeof(char *));
+    if (argv == (char **)NULL) {
+        free(bufptr);
+        mem_err(__G);
+    }
+    argvect = argv;
+
+    /* copy the program name first, that's always true */
+    *(argv++) = *((*Pargv)++);
+
+    /* copy the environment args next, may be changed */
+    do {
+#if defined(AMIGA) || defined(UNIX)
+        if (*bufptr == '"') {
+            char *argstart = ++bufptr;
+
+            *(argv++) = argstart;
+            for (ch = *bufptr; ch != '\0' && ch != '\"'; ch = *(++bufptr))
+                if (ch == '\\' && bufptr[1] != '\0')
+                    ++bufptr;           /* skip char after backslash */
+            if (ch != '\0')
+                *(bufptr++) = '\0';     /* overwrite trailing " */
+
+            /* remove escape characters */
+            while ((argstart = strchr(argstart, '\\')) != (char *)NULL) {
+                strcpy(argstart, argstart + 1);
+                if (*argstart)
+                    ++argstart;
+            }
+        } else {
+            *(argv++) = bufptr;
+            while ((ch = *bufptr) != '\0' && !ISspace(ch))
+                ++bufptr;
+            if (ch != '\0')
+                *(bufptr++) = '\0';
+        }
+#else
+#ifdef DOS_FLX_OS2_W32
+        /* we do not support backslash-quoting of quotes in quoted
+         * strings under DOS_OS2_W32, because backslashes are directory
+         * separators and double quotes are illegal in filenames */
+        if (*bufptr == '"') {
+            *(argv++) = ++bufptr;
+            while ((ch = *bufptr) != '\0' && ch != '\"')
+                ++bufptr;
+            if (ch != '\0')
+                *(bufptr++) = '\0';
+        } else {
+            *(argv++) = bufptr;
+            while ((ch = *bufptr) != '\0' && !ISspace(ch))
+                ++bufptr;
+            if (ch != '\0')
+                *(bufptr++) = '\0';
+        }
+#else
+        *(argv++) = bufptr;
+        while ((ch = *bufptr) != '\0' && !ISspace(ch))
+            ++bufptr;
+        if (ch != '\0')
+            *(bufptr++) = '\0';
+#endif /* ?DOS_FLX_OS2_W32 */
+#endif /* ?(AMIGA || UNIX) */
+        while ((ch = *bufptr) != '\0' && ISspace(ch))
+            ++bufptr;
+    } while (ch);
+
+    /* now save old argc and copy in the old args */
+    argc += *Pargc;
+    while (--(*Pargc))
+        *(argv++) = *((*Pargv)++);
+
+    /* finally, add a NULL after the last arg, like Unix */
+    *argv = (char *)NULL;
+
+    /* save the values and return */
+    *Pargv = argvect;
+    *Pargc = argc;
+}
+
+
+
+static int count_args(s)
+    ZCONST char *s;
+{
+    int count = 0;
+    char ch;
+
+    do {
+        /* count and skip args */
+        ++count;
+#if defined(AMIGA) || defined(UNIX)
+        if (*s == '\"') {
+            for (ch = *(++s);  ch != '\0' && ch != '\"';  ch = *(++s))
+                if (ch == '\\' && s[1] != '\0')
+                    ++s;
+            if (*s)
+                ++s;        /* trailing quote */
+        } else
+#else
+#ifdef DOS_FLX_OS2_W32
+        if (*s == '\"') {
+            ++s;                /* leading quote */
+            while ((ch = *s) != '\0' && ch != '\"')
+                ++s;
+            if (*s)
+                ++s;        /* trailing quote */
+        } else
+#endif /* DOS_FLX_OS2_W32 */
+#endif /* ?(AMIGA || UNIX) */
+        while ((ch = *s) != '\0' && !ISspace(ch))  /* note else-clauses above */
+            ++s;
+        while ((ch = *s) != '\0' && ISspace(ch))
+            ++s;
+    } while (ch);
+
+    return count;
+}
+
+
+
+static void mem_err(__G)
+    __GDEF
+{
+    perror(LoadFarString(NoMemArguments));
+    DESTROYGLOBALS()
+    EXIT(PK_MEM);
+}
+
+
+
+#ifdef TEST
+
+main(argc, argv)
+    int argc;
+    char **argv;
+{
+    int i;
+
+    pipeit("Orig argv: %p\n", argv);
+    dump_args(argc, argv);
+    envargs(__G__ &argc, &argv, "ENVTEST");
+    pipeit(" New argv: %p\n", argv);
+    dump_args(argc, argv);
+}
+
+
+
+dump_args(argc, argv)
+    int argc;
+    char *argv[];
+{
+    int i;
+
+    pipeit("\nDump %d args:\n", argc);
+    for (i = 0; i < argc; ++i)
+        pipeit("%3d %s\n", i, argv[i]);
+}
+
+#endif /* TEST */
+
+
+
+#ifdef MSDOS   /* DOS_OS2?  DOS_OS2_W32? */
+
+/*
+ * void mksargs(int *argcp, char ***argvp)
+ *
+ *    Substitutes the extended command line argument list produced by
+ *    the MKS Korn Shell in place of the command line info from DOS.
+ *
+ *    The MKS shell gets around DOS's 128-byte limit on the length of
+ *    a command line by passing the "real" command line in the envi-
+ *    ronment.  The "real" arguments are flagged by prepending a tilde
+ *    (~) to each one.
+ *
+ *    This "mksargs" routine creates a new argument list by scanning
+ *    the environment from the beginning, looking for strings begin-
+ *    ning with a tilde character.  The new list replaces the original
+ *    "argv" (pointed to by "argvp"), and the number of arguments
+ *    in the new list replaces the original "argc" (pointed to by
+ *    "argcp").
+ *
+ *    Rich Wales
+ */
+void mksargs(argcp, argvp)
+    int *argcp;
+    char ***argvp;
+{
+#ifndef MSC /* declared differently in MSC 7.0 headers, at least */
+#ifndef __WATCOMC__
+    extern char **environ;          /* environment */
+#endif
+#endif
+    char        **envp;             /* pointer into environment */
+    char        **newargv;          /* new argument list */
+    char        **argp;             /* pointer into new arg list */
+    int         newargc;            /* new argument count */
+
+    /* sanity check */
+    if (environ == NULL || argcp == NULL || argvp == NULL || *argvp == NULL)
+        return;
+
+    /* find out how many environment arguments there are */
+    for (envp = environ, newargc = 0; *envp != NULL && (*envp)[0] == '~';
+         envp++, newargc++)
+        ;
+    if (newargc == 0)
+        return;     /* no environment arguments */
+
+    /* set up new argument list */
+    newargv = (char **) malloc(sizeof(char **) * (newargc+1));
+    if (newargv == NULL)
+        return;     /* malloc failed */
+
+    for (argp = newargv, envp = environ; *envp != NULL && (*envp)[0] == '~';
+         *argp++ = &(*envp++)[1])
+        ;
+    *argp = NULL;   /* null-terminate the list */
+
+    /* substitute new argument list in place of old one */
+    *argcp = newargc;
+    *argvp = newargv;
+}
+
+#endif /* MSDOS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/explode.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,871 @@
+/* explode.c -- put in the public domain by Mark Adler
+   version c15, 6 July 1996 */
+
+
+/* You can do whatever you like with this source file, though I would
+   prefer that if you modify it and redistribute it that you include
+   comments to that effect with your name and the date.  Thank you.
+
+   History:
+   vers    date          who           what
+   ----  ---------  --------------  ------------------------------------
+    c1   30 Mar 92  M. Adler        explode that uses huft_build from inflate
+                                    (this gives over a 70% speed improvement
+                                    over the original unimplode.c, which
+                                    decoded a bit at a time)
+    c2    4 Apr 92  M. Adler        fixed bug for file sizes a multiple of 32k.
+    c3   10 Apr 92  M. Adler        added a little memory tracking if DEBUG
+    c4   11 Apr 92  M. Adler        added NOMEMCPY do kill use of memcpy()
+    c5   21 Apr 92  M. Adler        added the WSIZE #define to allow reducing
+                                    the 32K window size for specialized
+                                    applications.
+    c6   31 May 92  M. Adler        added typecasts to eliminate some warnings
+    c7   27 Jun 92  G. Roelofs      added more typecasts.
+    c8   17 Oct 92  G. Roelofs      changed ULONG/UWORD/byte to ulg/ush/uch.
+    c9   19 Jul 93  J. Bush         added more typecasts (to return values);
+                                    made l[256] array static for Amiga.
+    c10   8 Oct 93  G. Roelofs      added used_csize for diagnostics; added
+                                    buf and unshrink arguments to flush();
+                                    undef'd various macros at end for Turbo C;
+                                    removed NEXTBYTE macro (now in unzip.h)
+                                    and bytebuf variable (not used); changed
+                                    memset() to memzero().
+    c11   9 Jan 94  M. Adler        fixed incorrect used_csize calculation.
+    c12   9 Apr 94  G. Roelofs      fixed split comments on preprocessor lines
+                                    to avoid bug in Encore compiler.
+    c13  25 Aug 94  M. Adler        fixed distance-length comment (orig c9 fix)
+    c14  22 Nov 95  S. Maxwell      removed unnecessary "static" on auto array
+    c15   6 Jul 96  W. Haidinger    added ulg typecasts to flush() calls.
+    c16   8 Feb 98  C. Spieler      added ZCONST modifiers to const tables
+                                    and #ifdef DEBUG around debugging code.
+    c16b 25 Mar 98  C. Spieler      modified DLL code for slide redirection.
+ */
+
+
+/*
+   Explode imploded (PKZIP method 6 compressed) data.  This compression
+   method searches for as much of the current string of bytes (up to a length
+   of ~320) in the previous 4K or 8K bytes.  If it doesn't find any matches
+   (of at least length 2 or 3), it codes the next byte.  Otherwise, it codes
+   the length of the matched string and its distance backwards from the
+   current position.  Single bytes ("literals") are preceded by a one (a
+   single bit) and are either uncoded (the eight bits go directly into the
+   compressed stream for a total of nine bits) or Huffman coded with a
+   supplied literal code tree.  If literals are coded, then the minimum match
+   length is three, otherwise it is two.
+
+   There are therefore four kinds of imploded streams: 8K search with coded
+   literals (min match = 3), 4K search with coded literals (min match = 3),
+   8K with uncoded literals (min match = 2), and 4K with uncoded literals
+   (min match = 2).  The kind of stream is identified in two bits of a
+   general purpose bit flag that is outside of the compressed stream.
+
+   Distance-length pairs for matched strings are preceded by a zero bit (to
+   distinguish them from literals) and are always coded.  The distance comes
+   first and is either the low six (4K) or low seven (8K) bits of the
+   distance (uncoded), followed by the high six bits of the distance coded.
+   Then the length is six bits coded (0..63 + min match length), and if the
+   maximum such length is coded, then it's followed by another eight bits
+   (uncoded) to be added to the coded length.  This gives a match length
+   range of 2..320 or 3..321 bytes.
+
+   The literal, length, and distance codes are all represented in a slightly
+   compressed form themselves.  What is sent are the lengths of the codes for
+   each value, which is sufficient to construct the codes.  Each byte of the
+   code representation is the code length (the low four bits representing
+   1..16), and the number of values sequentially with that length (the high
+   four bits also representing 1..16).  There are 256 literal code values (if
+   literals are coded), 64 length code values, and 64 distance code values,
+   in that order at the beginning of the compressed stream.  Each set of code
+   values is preceded (redundantly) with a byte indicating how many bytes are
+   in the code description that follows, in the range 1..256.
+
+   The codes themselves are decoded using tables made by huft_build() from
+   the bit lengths.  That routine and its comments are in the inflate.c
+   module.
+ */
+
+#define UNZIP_INTERNAL
+#include "unzip.h"      /* must supply slide[] (uch) array and NEXTBYTE macro */
+
+#ifndef WSIZE
+#  define WSIZE 0x8000  /* window size--must be a power of two, and */
+#endif                  /* at least 8K for zip's implode method */
+
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+#  define wsize G._wsize
+#else
+#  define wsize WSIZE
+#endif
+
+/* routines here */
+static int get_tree OF((__GPRO__ unsigned *l, unsigned n));
+static int explode_lit8 OF((__GPRO__ struct huft *tb, struct huft *tl,
+                            struct huft *td, int bb, int bl, int bd));
+static int explode_lit4 OF((__GPRO__ struct huft *tb, struct huft *tl,
+                            struct huft *td, int bb, int bl, int bd));
+static int explode_nolit8 OF((__GPRO__ struct huft *tl, struct huft *td,
+                              int bl, int bd));
+static int explode_nolit4 OF((__GPRO__ struct huft *tl, struct huft *td,
+                              int bl, int bd));
+int explode OF((__GPRO));
+
+
+/* The implode algorithm uses a sliding 4K or 8K byte window on the
+   uncompressed stream to find repeated byte strings.  This is implemented
+   here as a circular buffer.  The index is updated simply by incrementing
+   and then and'ing with 0x0fff (4K-1) or 0x1fff (8K-1).  Here, the 32K
+   buffer of inflate is used, and it works just as well to always have
+   a 32K circular buffer, so the index is anded with 0x7fff.  This is
+   done to allow the window to also be used as the output buffer. */
+/* This must be supplied in an external module useable like "uch slide[8192];"
+   or "uch *slide;", where the latter would be malloc'ed.  In unzip, slide[]
+   is actually a 32K area for use by inflate, which uses a 32K sliding window.
+ */
+
+
+/* Tables for length and distance */
+static ZCONST ush cplen2[] =
+        {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+        18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+        35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65};
+static ZCONST ush cplen3[] =
+        {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+        19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+        36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+        53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66};
+static ZCONST ush extra[] =
+        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        8};
+static ZCONST ush cpdist4[] =
+        {1, 65, 129, 193, 257, 321, 385, 449, 513, 577, 641, 705,
+        769, 833, 897, 961, 1025, 1089, 1153, 1217, 1281, 1345, 1409, 1473,
+        1537, 1601, 1665, 1729, 1793, 1857, 1921, 1985, 2049, 2113, 2177,
+        2241, 2305, 2369, 2433, 2497, 2561, 2625, 2689, 2753, 2817, 2881,
+        2945, 3009, 3073, 3137, 3201, 3265, 3329, 3393, 3457, 3521, 3585,
+        3649, 3713, 3777, 3841, 3905, 3969, 4033};
+static ZCONST ush cpdist8[] =
+        {1, 129, 257, 385, 513, 641, 769, 897, 1025, 1153, 1281,
+        1409, 1537, 1665, 1793, 1921, 2049, 2177, 2305, 2433, 2561, 2689,
+        2817, 2945, 3073, 3201, 3329, 3457, 3585, 3713, 3841, 3969, 4097,
+        4225, 4353, 4481, 4609, 4737, 4865, 4993, 5121, 5249, 5377, 5505,
+        5633, 5761, 5889, 6017, 6145, 6273, 6401, 6529, 6657, 6785, 6913,
+        7041, 7169, 7297, 7425, 7553, 7681, 7809, 7937, 8065};
+
+
+/* Macros for inflate() bit peeking and grabbing.
+   The usage is:
+
+        NEEDBITS(j)
+        x = b & mask_bits[j];
+        DUMPBITS(j)
+
+   where NEEDBITS makes sure that b has at least j bits in it, and
+   DUMPBITS removes the bits from b.  The macros use the variable k
+   for the number of bits in b.  Normally, b and k are register
+   variables for speed.
+ */
+
+#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<<k;k+=8;}}
+#define DUMPBITS(n) {b>>=(n);k-=(n);}
+
+
+
+static int get_tree(__G__ l, n)
+     __GDEF
+unsigned *l;            /* bit lengths */
+unsigned n;             /* number expected */
+/* Get the bit lengths for a code representation from the compressed
+   stream.  If get_tree() returns 4, then there is an error in the data.
+   Otherwise zero is returned. */
+{
+  unsigned i;           /* bytes remaining in list */
+  unsigned k;           /* lengths entered */
+  unsigned j;           /* number of codes */
+  unsigned b;           /* bit length for those codes */
+
+
+  /* get bit lengths */
+  i = NEXTBYTE + 1;                     /* length/count pairs to read */
+  k = 0;                                /* next code */
+  do {
+    b = ((j = NEXTBYTE) & 0xf) + 1;     /* bits in code (1..16) */
+    j = ((j & 0xf0) >> 4) + 1;          /* codes with those bits (1..16) */
+    if (k + j > n)
+      return 4;                         /* don't overflow l[] */
+    do {
+      l[k++] = b;
+    } while (--j);
+  } while (--i);
+  return k != n ? 4 : 0;                /* should have read n of them */
+}
+
+
+
+static int explode_lit8(__G__ tb, tl, td, bb, bl, bd)
+     __GDEF
+struct huft *tb, *tl, *td;      /* literal, length, and distance tables */
+int bb, bl, bd;                 /* number of bits decoded by those */
+/* Decompress the imploded data using coded literals and an 8K sliding
+   window. */
+{
+  long s;               /* bytes to decompress */
+  register unsigned e;  /* table entry flag/number of extra bits */
+  unsigned n, d;        /* length and index for copy */
+  unsigned w;           /* current window position */
+  struct huft *t;       /* pointer to table entry */
+  unsigned mb, ml, md;  /* masks for bb, bl, and bd bits */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+  unsigned u;           /* true if unflushed */
+
+
+  /* explode the coded data */
+  b = k = w = 0;                /* initialize bit buffer, window */
+  u = 1;                        /* buffer unflushed */
+  mb = mask_bits[bb];           /* precompute masks for speed */
+  ml = mask_bits[bl];
+  md = mask_bits[bd];
+  s = G.ucsize;
+  while (s > 0)                 /* do until ucsize bytes uncompressed */
+  {
+    NEEDBITS(1)
+    if (b & 1)                  /* then literal--decode it */
+    {
+      DUMPBITS(1)
+      s--;
+      NEEDBITS((unsigned)bb)    /* get coded literal */
+      if ((e = (t = tb + ((~(unsigned)b) & mb))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      redirSlide[w++] = (uch)t->v.n;
+      if (w == wsize)
+      {
+        flush(__G__ redirSlide, (ulg)w, 0);
+        w = u = 0;
+      }
+    }
+    else                        /* else distance/length */
+    {
+      DUMPBITS(1)
+      NEEDBITS(7)               /* get distance low bits */
+      d = (unsigned)b & 0x7f;
+      DUMPBITS(7)
+      NEEDBITS((unsigned)bd)    /* get coded distance high bits */
+      if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      d = w - d - t->v.n;       /* construct offset */
+      NEEDBITS((unsigned)bl)    /* get coded length */
+      if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      n = t->v.n;
+      if (e)                    /* get length extra bits */
+      {
+        NEEDBITS(8)
+        n += (unsigned)b & 0xff;
+        DUMPBITS(8)
+      }
+
+      /* do the copy */
+      s -= n;
+      do {
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+        if (G.redirect_slide) {
+          /* &= w/ wsize not needed and wrong if redirect */
+          if (d >= wsize)
+            return 1;
+          n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e);
+        } else
+#endif
+        n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e);
+        if (u && w <= d)
+        {
+          memzero(redirSlide + w, e);
+          w += e;
+          d += e;
+        }
+        else
+#ifndef NOMEMCPY
+          if (w - d >= e)       /* (this test assumes unsigned comparison) */
+          {
+            memcpy(redirSlide + w, redirSlide + d, e);
+            w += e;
+            d += e;
+          }
+          else                  /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+            do {
+              redirSlide[w++] = redirSlide[d++];
+            } while (--e);
+        if (w == wsize)
+        {
+          flush(__G__ redirSlide, (ulg)w, 0);
+          w = u = 0;
+        }
+      } while (n);
+    }
+  }
+
+  /* flush out redirSlide */
+  flush(__G__ redirSlide, (ulg)w, 0);
+  if (G.csize + G.incnt + (k >> 3))   /* should have read csize bytes, but */
+  {                        /* sometimes read one too many:  k>>3 compensates */
+    G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3);
+    return 5;
+  }
+  return 0;
+}
+
+
+
+static int explode_lit4(__G__ tb, tl, td, bb, bl, bd)
+     __GDEF
+struct huft *tb, *tl, *td;      /* literal, length, and distance tables */
+int bb, bl, bd;                 /* number of bits decoded by those */
+/* Decompress the imploded data using coded literals and a 4K sliding
+   window. */
+{
+  long s;               /* bytes to decompress */
+  register unsigned e;  /* table entry flag/number of extra bits */
+  unsigned n, d;        /* length and index for copy */
+  unsigned w;           /* current window position */
+  struct huft *t;       /* pointer to table entry */
+  unsigned mb, ml, md;  /* masks for bb, bl, and bd bits */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+  unsigned u;           /* true if unflushed */
+
+
+  /* explode the coded data */
+  b = k = w = 0;                /* initialize bit buffer, window */
+  u = 1;                        /* buffer unflushed */
+  mb = mask_bits[bb];           /* precompute masks for speed */
+  ml = mask_bits[bl];
+  md = mask_bits[bd];
+  s = G.ucsize;
+  while (s > 0)                 /* do until ucsize bytes uncompressed */
+  {
+    NEEDBITS(1)
+    if (b & 1)                  /* then literal--decode it */
+    {
+      DUMPBITS(1)
+      s--;
+      NEEDBITS((unsigned)bb)    /* get coded literal */
+      if ((e = (t = tb + ((~(unsigned)b) & mb))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      redirSlide[w++] = (uch)t->v.n;
+      if (w == wsize)
+      {
+        flush(__G__ redirSlide, (ulg)w, 0);
+        w = u = 0;
+      }
+    }
+    else                        /* else distance/length */
+    {
+      DUMPBITS(1)
+      NEEDBITS(6)               /* get distance low bits */
+      d = (unsigned)b & 0x3f;
+      DUMPBITS(6)
+      NEEDBITS((unsigned)bd)    /* get coded distance high bits */
+      if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      d = w - d - t->v.n;       /* construct offset */
+      NEEDBITS((unsigned)bl)    /* get coded length */
+      if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      n = t->v.n;
+      if (e)                    /* get length extra bits */
+      {
+        NEEDBITS(8)
+        n += (unsigned)b & 0xff;
+        DUMPBITS(8)
+      }
+
+      /* do the copy */
+      s -= n;
+      do {
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+        if (G.redirect_slide) {
+          /* &= w/ wsize not needed and wrong if redirect */
+          if (d >= wsize)
+            return 1;
+          n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e);
+        } else
+#endif
+        n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e);
+        if (u && w <= d)
+        {
+          memzero(redirSlide + w, e);
+          w += e;
+          d += e;
+        }
+        else
+#ifndef NOMEMCPY
+          if (w - d >= e)       /* (this test assumes unsigned comparison) */
+          {
+            memcpy(redirSlide + w, redirSlide + d, e);
+            w += e;
+            d += e;
+          }
+          else                  /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+            do {
+              redirSlide[w++] = redirSlide[d++];
+            } while (--e);
+        if (w == wsize)
+        {
+          flush(__G__ redirSlide, (ulg)w, 0);
+          w = u = 0;
+        }
+      } while (n);
+    }
+  }
+
+  /* flush out redirSlide */
+  flush(__G__ redirSlide, (ulg)w, 0);
+  if (G.csize + G.incnt + (k >> 3))   /* should have read csize bytes, but */
+  {                        /* sometimes read one too many:  k>>3 compensates */
+    G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3);
+    return 5;
+  }
+  return 0;
+}
+
+
+
+static int explode_nolit8(__G__ tl, td, bl, bd)
+     __GDEF
+struct huft *tl, *td;   /* length and distance decoder tables */
+int bl, bd;             /* number of bits decoded by tl[] and td[] */
+/* Decompress the imploded data using uncoded literals and an 8K sliding
+   window. */
+{
+  long s;               /* bytes to decompress */
+  register unsigned e;  /* table entry flag/number of extra bits */
+  unsigned n, d;        /* length and index for copy */
+  unsigned w;           /* current window position */
+  struct huft *t;       /* pointer to table entry */
+  unsigned ml, md;      /* masks for bl and bd bits */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+  unsigned u;           /* true if unflushed */
+
+
+  /* explode the coded data */
+  b = k = w = 0;                /* initialize bit buffer, window */
+  u = 1;                        /* buffer unflushed */
+  ml = mask_bits[bl];           /* precompute masks for speed */
+  md = mask_bits[bd];
+  s = G.ucsize;
+  while (s > 0)                 /* do until ucsize bytes uncompressed */
+  {
+    NEEDBITS(1)
+    if (b & 1)                  /* then literal--get eight bits */
+    {
+      DUMPBITS(1)
+      s--;
+      NEEDBITS(8)
+      redirSlide[w++] = (uch)b;
+      if (w == wsize)
+      {
+        flush(__G__ redirSlide, (ulg)w, 0);
+        w = u = 0;
+      }
+      DUMPBITS(8)
+    }
+    else                        /* else distance/length */
+    {
+      DUMPBITS(1)
+      NEEDBITS(7)               /* get distance low bits */
+      d = (unsigned)b & 0x7f;
+      DUMPBITS(7)
+      NEEDBITS((unsigned)bd)    /* get coded distance high bits */
+      if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      d = w - d - t->v.n;       /* construct offset */
+      NEEDBITS((unsigned)bl)    /* get coded length */
+      if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      n = t->v.n;
+      if (e)                    /* get length extra bits */
+      {
+        NEEDBITS(8)
+        n += (unsigned)b & 0xff;
+        DUMPBITS(8)
+      }
+
+      /* do the copy */
+      s -= n;
+      do {
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+        if (G.redirect_slide) {
+          /* &= w/ wsize not needed and wrong if redirect */
+          if (d >= wsize)
+            return 1;
+          n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e);
+        } else
+#endif
+        n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e);
+        if (u && w <= d)
+        {
+          memzero(redirSlide + w, e);
+          w += e;
+          d += e;
+        }
+        else
+#ifndef NOMEMCPY
+          if (w - d >= e)       /* (this test assumes unsigned comparison) */
+          {
+            memcpy(redirSlide + w, redirSlide + d, e);
+            w += e;
+            d += e;
+          }
+          else                  /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+            do {
+              redirSlide[w++] = redirSlide[d++];
+            } while (--e);
+        if (w == wsize)
+        {
+          flush(__G__ redirSlide, (ulg)w, 0);
+          w = u = 0;
+        }
+      } while (n);
+    }
+  }
+
+  /* flush out redirSlide */
+  flush(__G__ redirSlide, (ulg)w, 0);
+  if (G.csize + G.incnt + (k >> 3))   /* should have read csize bytes, but */
+  {                        /* sometimes read one too many:  k>>3 compensates */
+    G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3);
+    return 5;
+  }
+  return 0;
+}
+
+
+
+static int explode_nolit4(__G__ tl, td, bl, bd)
+     __GDEF
+struct huft *tl, *td;   /* length and distance decoder tables */
+int bl, bd;             /* number of bits decoded by tl[] and td[] */
+/* Decompress the imploded data using uncoded literals and a 4K sliding
+   window. */
+{
+  long s;               /* bytes to decompress */
+  register unsigned e;  /* table entry flag/number of extra bits */
+  unsigned n, d;        /* length and index for copy */
+  unsigned w;           /* current window position */
+  struct huft *t;       /* pointer to table entry */
+  unsigned ml, md;      /* masks for bl and bd bits */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+  unsigned u;           /* true if unflushed */
+
+
+  /* explode the coded data */
+  b = k = w = 0;                /* initialize bit buffer, window */
+  u = 1;                        /* buffer unflushed */
+  ml = mask_bits[bl];           /* precompute masks for speed */
+  md = mask_bits[bd];
+  s = G.ucsize;
+  while (s > 0)                 /* do until ucsize bytes uncompressed */
+  {
+    NEEDBITS(1)
+    if (b & 1)                  /* then literal--get eight bits */
+    {
+      DUMPBITS(1)
+      s--;
+      NEEDBITS(8)
+      redirSlide[w++] = (uch)b;
+      if (w == wsize)
+      {
+        flush(__G__ redirSlide, (ulg)w, 0);
+        w = u = 0;
+      }
+      DUMPBITS(8)
+    }
+    else                        /* else distance/length */
+    {
+      DUMPBITS(1)
+      NEEDBITS(6)               /* get distance low bits */
+      d = (unsigned)b & 0x3f;
+      DUMPBITS(6)
+      NEEDBITS((unsigned)bd)    /* get coded distance high bits */
+      if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      d = w - d - t->v.n;       /* construct offset */
+      NEEDBITS((unsigned)bl)    /* get coded length */
+      if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      n = t->v.n;
+      if (e)                    /* get length extra bits */
+      {
+        NEEDBITS(8)
+        n += (unsigned)b & 0xff;
+        DUMPBITS(8)
+      }
+
+      /* do the copy */
+      s -= n;
+      do {
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+        if (G.redirect_slide) {
+          /* &= w/ wsize not needed and wrong if redirect */
+          if (d >= wsize)
+            return 1;
+          n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e);
+        } else
+#endif
+        n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e);
+        if (u && w <= d)
+        {
+          memzero(redirSlide + w, e);
+          w += e;
+          d += e;
+        }
+        else
+#ifndef NOMEMCPY
+          if (w - d >= e)       /* (this test assumes unsigned comparison) */
+          {
+            memcpy(redirSlide + w, redirSlide + d, e);
+            w += e;
+            d += e;
+          }
+          else                  /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+            do {
+              redirSlide[w++] = redirSlide[d++];
+            } while (--e);
+        if (w == wsize)
+        {
+          flush(__G__ redirSlide, (ulg)w, 0);
+          w = u = 0;
+        }
+      } while (n);
+    }
+  }
+
+  /* flush out redirSlide */
+  flush(__G__ redirSlide, (ulg)w, 0);
+  if (G.csize + G.incnt + (k >> 3))   /* should have read csize bytes, but */
+  {                        /* sometimes read one too many:  k>>3 compensates */
+    G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3);
+    return 5;
+  }
+  return 0;
+}
+
+
+
+int explode(__G)
+     __GDEF
+/* Explode an imploded compressed stream.  Based on the general purpose
+   bit flag, decide on coded or uncoded literals, and an 8K or 4K sliding
+   window.  Construct the literal (if any), length, and distance codes and
+   the tables needed to decode them (using huft_build() from inflate.c),
+   and call the appropriate routine for the type of data in the remainder
+   of the stream.  The four routines are nearly identical, differing only
+   in whether the literal is decoded or simply read in, and in how many
+   bits are read in, uncoded, for the low distance bits. */
+{
+  unsigned r;           /* return codes */
+  struct huft *tb;      /* literal code table */
+  struct huft *tl;      /* length code table */
+  struct huft *td;      /* distance code table */
+  int bb;               /* bits for tb */
+  int bl;               /* bits for tl */
+  int bd;               /* bits for td */
+  unsigned l[256];      /* bit lengths for codes */
+
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+  if (G.redirect_slide)
+    wsize = G.redirect_size, redirSlide = G.redirect_buffer;
+  else
+    wsize = WSIZE, redirSlide = slide;
+#endif
+
+  /* Tune base table sizes.  Note: I thought that to truly optimize speed,
+     I would have to select different bl, bd, and bb values for different
+     compressed file sizes.  I was surprised to find out that the values of
+     7, 7, and 9 worked best over a very wide range of sizes, except that
+     bd = 8 worked marginally better for large compressed sizes. */
+  bl = 7;
+  bd = (G.csize + G.incnt) > 200000L ? 8 : 7;
+
+
+  /* With literal tree--minimum match length is 3 */
+#ifdef DEBUG
+  G.hufts = 0;                    /* initialize huft's malloc'ed */
+#endif
+  if (G.lrec.general_purpose_bit_flag & 4)
+  {
+    bb = 9;                     /* base table size for literals */
+    if ((r = get_tree(__G__ l, 256)) != 0)
+      return (int)r;
+    if ((r = huft_build(__G__ l, 256, 256, NULL, NULL, &tb, &bb)) != 0)
+    {
+      if (r == 1)
+        huft_free(tb);
+      return (int)r;
+    }
+    if ((r = get_tree(__G__ l, 64)) != 0)
+      return (int)r;
+    if ((r = huft_build(__G__ l, 64, 0, cplen3, extra, &tl, &bl)) != 0)
+    {
+      if (r == 1)
+        huft_free(tl);
+      huft_free(tb);
+      return (int)r;
+    }
+    if ((r = get_tree(__G__ l, 64)) != 0)
+      return (int)r;
+    if (G.lrec.general_purpose_bit_flag & 2)      /* true if 8K */
+    {
+      if ((r = huft_build(__G__ l, 64, 0, cpdist8, extra, &td, &bd)) != 0)
+      {
+        if (r == 1)
+          huft_free(td);
+        huft_free(tl);
+        huft_free(tb);
+        return (int)r;
+      }
+      r = explode_lit8(__G__ tb, tl, td, bb, bl, bd);
+    }
+    else                                        /* else 4K */
+    {
+      if ((r = huft_build(__G__ l, 64, 0, cpdist4, extra, &td, &bd)) != 0)
+      {
+        if (r == 1)
+          huft_free(td);
+        huft_free(tl);
+        huft_free(tb);
+        return (int)r;
+      }
+      r = explode_lit4(__G__ tb, tl, td, bb, bl, bd);
+    }
+    huft_free(td);
+    huft_free(tl);
+    huft_free(tb);
+  }
+  else
+
+
+  /* No literal tree--minimum match length is 2 */
+  {
+    if ((r = get_tree(__G__ l, 64)) != 0)
+      return (int)r;
+    if ((r = huft_build(__G__ l, 64, 0, cplen2, extra, &tl, &bl)) != 0)
+    {
+      if (r == 1)
+        huft_free(tl);
+      return (int)r;
+    }
+    if ((r = get_tree(__G__ l, 64)) != 0)
+      return (int)r;
+    if (G.lrec.general_purpose_bit_flag & 2)      /* true if 8K */
+    {
+      if ((r = huft_build(__G__ l, 64, 0, cpdist8, extra, &td, &bd)) != 0)
+      {
+        if (r == 1)
+          huft_free(td);
+        huft_free(tl);
+        return (int)r;
+      }
+      r = explode_nolit8(__G__ tl, td, bl, bd);
+    }
+    else                                        /* else 4K */
+    {
+      if ((r = huft_build(__G__ l, 64, 0, cpdist4, extra, &td, &bd)) != 0)
+      {
+        if (r == 1)
+          huft_free(td);
+        huft_free(tl);
+        return (int)r;
+      }
+      r = explode_nolit4(__G__ tl, td, bl, bd);
+    }
+    huft_free(td);
+    huft_free(tl);
+  }
+  Trace((stderr, "<%u > ", G.hufts));
+  return (int)r;
+}
+
+/* so explode.c and inflate.c can be compiled together into one object: */
+#undef NEXTBYTE
+#undef NEEDBITS
+#undef DUMPBITS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/extract.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,2005 @@
+/*---------------------------------------------------------------------------
+
+  extract.c
+
+  This file contains the high-level routines ("driver routines") for extrac-
+  ting and testing zipfile members.  It calls the low-level routines in files
+  explode.c, inflate.c, unreduce.c and unshrink.c.
+
+  Contains:  extract_or_test_files()
+             store_info()
+             extract_or_test_member()
+             TestExtraField()
+             test_compr_eb()
+             memextract()
+             memflush()
+             fnfilter()
+
+  ---------------------------------------------------------------------------*/
+
+
+#define EXTRACT_C
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#include "crypt.h"
+#ifdef WINDLL
+#  ifdef POCKET_UNZIP
+#    include "wince/intrface.h"
+#  else
+#    include "windll/windll.h"
+#  endif
+#endif
+
+off_t acelseek(off_t offset, int whence);
+int aceread(void *buf, size_t count);
+int aceopen(const char *path, int flags);
+int aceclose(int fd);
+int acesize(void);
+int acetell(int fd);
+char *replacestr(char *str1, char *str2, char *str3);
+
+#define GRRDUMP(buf,len) { \
+    int i, j; \
+ \
+    for (j = 0;  j < (len)/16;  ++j) { \
+        pipeit("        "); \
+        for (i = 0;  i < 16;  ++i) \
+            pipeit("%02x ", (uch)(buf)[i+(j<<4)]); \
+        pipeit("\n        "); \
+        for (i = 0;  i < 16;  ++i) { \
+            char c = (char)(buf)[i+(j<<4)]; \
+ \
+            if (c == '\n') \
+                pipeit("\\n "); \
+            else if (c == '\r') \
+                pipeit("\\r "); \
+            else \
+                pipeit(" %c ", c); \
+        } \
+        pipeit("\n"); \
+    } \
+    if ((len) % 16) { \
+        pipeit("        "); \
+        for (i = j<<4;  i < (len);  ++i) \
+            pipeit("%02x ", (uch)(buf)[i]); \
+        pipeit("\n        "); \
+        for (i = j<<4;  i < (len);  ++i) { \
+            char c = (char)(buf)[i]; \
+ \
+            if (c == '\n') \
+                pipeit("\\n "); \
+            else if (c == '\r') \
+                pipeit("\\r "); \
+            else \
+                pipeit(" %c ", c); \
+        } \
+        pipeit("\n"); \
+    } \
+}
+
+static int store_info OF((__GPRO));
+static int extract_or_test_member OF((__GPRO));
+#ifndef SFX
+   static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len));
+   static int test_compr_eb OF((__GPRO__ uch *eb, unsigned eb_size,
+        unsigned compr_offset,
+        int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size,
+                              uch *eb_ucptr, ulg eb_ucsize)));
+#endif
+#ifdef SET_DIR_ATTRIB
+   static int dircomp OF((ZCONST zvoid *a, ZCONST zvoid *b));
+#endif
+
+
+
+/*******************************/
+/*  Strings used in extract.c  */
+/*******************************/
+
+static ZCONST char Far VersionMsg[] =
+  "   skipping: %-22s  need %s compat. v%u.%u (can do v%u.%u)\n";
+static ZCONST char Far ComprMsgNum[] =
+  "   skipping: %-22s  unsupported compression method %u\n";
+#ifndef SFX
+   static ZCONST char Far ComprMsgName[] =
+     "   skipping: %-22s  `%s' method not supported\n";
+   static ZCONST char Far CmprNone[]       = "store";
+   static ZCONST char Far CmprShrink[]     = "shrink";
+   static ZCONST char Far CmprReduce[]     = "reduce";
+   static ZCONST char Far CmprImplode[]    = "implode";
+   static ZCONST char Far CmprTokenize[]   = "tokenize";
+   static ZCONST char Far CmprDeflate[]    = "deflate";
+   static ZCONST char Far CmprEnDeflate[]  = "enhanced deflate";
+   static ZCONST char Far CmprDCLImplode[] = "DCL implode";
+   static ZCONST char Far *ComprNames[NUM_METHODS] = {
+     CmprNone, CmprShrink, CmprReduce, CmprReduce, CmprReduce, CmprReduce,
+     CmprImplode, CmprTokenize, CmprDeflate, CmprEnDeflate, CmprDCLImplode
+   };
+#endif /* !SFX */
+static ZCONST char Far FilNamMsg[] =
+  "%s:  bad filename length (%s)\n";
+static ZCONST char Far ExtFieldMsg[] =
+  "%s:  bad extra field length (%s)\n";
+static ZCONST char Far OffsetMsg[] =
+  "file #%u:  bad zipfile offset (%s):  %ld\n";
+static ZCONST char Far ExtractMsg[] =
+  "%8sing: %-22s  %s%s";
+#ifndef SFX
+   static ZCONST char Far LengthMsg[] =
+     "%s  %s:  %ld bytes required to uncompress to %lu bytes;\n    %s\
+      supposed to require %lu bytes%s%s%s\n";
+#endif
+
+static ZCONST char Far BadFileCommLength[] = "%s:  bad file comment length\n";
+static ZCONST char Far LocalHdrSig[] = "local header sig";
+static ZCONST char Far BadLocalHdr[] = "file #%u:  bad local header\n";
+static ZCONST char Far AttemptRecompensate[] =
+  "  (attempting to re-compensate)\n";
+#ifndef SFX
+   static ZCONST char Far BackslashPathSep[] =
+     "warning:  %s appears to use backslashes as path separators\n";
+#endif
+static ZCONST char Far SkipVolumeLabel[] =
+  "   skipping: %-22s  %svolume label\n";
+
+#ifdef SET_DIR_ATTRIB  /* messages of code for setting directory attributes */
+   static ZCONST char Far DirlistEntryNoMem[] =
+     "warning:  cannot alloc memory for dir times/permissions/UID/GID\n";
+   static ZCONST char Far DirlistSortNoMem[] =
+     "warning:  cannot alloc memory to sort dir times/perms/etc.\n";
+   static ZCONST char Far DirlistSetAttrFailed[] =
+     "warning:  set times/attribs failed for %s\n";
+#endif
+
+#ifndef WINDLL
+   static ZCONST char Far ReplaceQuery[] =
+     "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ";
+   static ZCONST char Far AssumeNone[] = " NULL\n(assuming [N]one)\n";
+   static ZCONST char Far NewNameQuery[] = "new name: ";
+   static ZCONST char Far InvalidResponse[] = "error:  invalid response [%c]\n";
+#endif /* !WINDLL */
+
+static ZCONST char Far ErrorInArchive[] =
+  "At least one %serror was detected in %s.\n";
+static ZCONST char Far ZeroFilesTested[] =
+  "Caution:  zero files tested in %s.\n";
+
+#ifndef VMS
+   static ZCONST char Far VMSFormatQuery[] =
+     "\n%s:  stored in VMS format.  Extract anyway? (y/n) ";
+#endif
+
+#if CRYPT
+   static ZCONST char Far SkipCannotGetPasswd[] =
+     "   skipping: %-22s  unable to get password\n";
+   static ZCONST char Far SkipIncorrectPasswd[] =
+     "   skipping: %-22s  incorrect password\n";
+   static ZCONST char Far FilesSkipBadPasswd[] =
+     "%u file%s skipped because of incorrect password.\n";
+   static ZCONST char Far MaybeBadPasswd[] =
+     "    (may instead be incorrect password)\n";
+#else
+   static ZCONST char Far SkipEncrypted[] =
+     "   skipping: %-22s  encrypted (not supported)\n";
+#endif
+
+static ZCONST char Far NoErrInCompData[] =
+  "No errors detected in compressed data of %s.\n";
+static ZCONST char Far NoErrInTestedFiles[] =
+  "No errors detected in %s for the %u file%s tested.\n";
+static ZCONST char Far FilesSkipped[] =
+  "%u file%s skipped because of unsupported compression or encoding.\n";
+
+static ZCONST char Far ErrUnzipFile[] = "  error:  %s%s %s\n";
+static ZCONST char Far ErrUnzipNoFile[] = "\n  error:  %s%s\n";
+static ZCONST char Far NotEnoughMem[] = "not enough memory to ";
+static ZCONST char Far InvalidComprData[] = "invalid compressed data to ";
+static ZCONST char Far Inflate[] = "inflate";
+
+#ifndef SFX
+   static ZCONST char Far Explode[] = "explode";
+#ifndef LZW_CLEAN
+   static ZCONST char Far Unshrink[] = "unshrink";
+#endif
+#endif
+
+#if (!defined(DELETE_IF_FULL) || !defined(HAVE_UNLINK))
+   static ZCONST char Far FileTruncated[] =
+     "warning:  %s is probably truncated\n";
+#endif
+
+static ZCONST char Far FileUnknownCompMethod[] =
+  "%s:  unknown compression method\n";
+static ZCONST char Far BadCRC[] = " bad CRC %08lx  (should be %08lx)\n";
+
+      /* TruncEAs[] also used in OS/2 mapname(), close_outfile() */
+char ZCONST Far TruncEAs[] = " compressed EA data missing (%d bytes)%s";
+char ZCONST Far TruncNTSD[] =
+  " compressed WinNT security data missing (%d bytes)%s";
+
+#ifndef SFX
+   static ZCONST char Far InconsistEFlength[] = "bad extra-field entry:\n \
+     EF block length (%u bytes) exceeds remaining EF data (%u bytes)\n";
+   static ZCONST char Far InvalidComprDataEAs[] =
+     " invalid compressed data for EAs\n";
+#  if (defined(WIN32) && defined(NTSD_EAS))
+     static ZCONST char Far InvalidSecurityEAs[] =
+       " EAs fail security check\n";
+#  endif
+   static ZCONST char Far UnsuppNTSDVersEAs[] =
+     " unsupported NTSD EAs version %d\n";
+   static ZCONST char Far BadCRC_EAs[] = " bad CRC for extended attributes\n";
+   static ZCONST char Far UnknComprMethodEAs[] =
+     " unknown compression method for EAs (%u)\n";
+   static ZCONST char Far NotEnoughMemEAs[] =
+     " out of memory while inflating EAs\n";
+   static ZCONST char Far UnknErrorEAs[] =
+     " unknown error on extended attributes\n";
+#endif /* !SFX */
+
+static ZCONST char Far UnsupportedExtraField[] =
+  "\nerror:  unsupported extra-field compression type (%u)--skipping\n";
+static ZCONST char Far BadExtraFieldCRC[] =
+  "error [%s]:  bad extra-field CRC %08lx (should be %08lx)\n";
+
+
+char conversionTable[] = { 'Y', 'A', 'n', 'C' };
+
+
+/**************************************/
+/*  Function extract_or_test_files()  */
+/**************************************/
+
+int extract_or_test_files(__G)    /* return PK-type error code */
+     __GDEF
+{
+    uch *cd_inptr;
+    unsigned i, j, filnum=0, blknum=0;
+	int cd_incnt, renamed, query;
+	extern int get_image;
+    int error, error_in_archive=PK_COOL, *fn_matched=NULL, *xn_matched=NULL;
+#ifdef WINDLL
+    int done_once = 0;
+#else
+    extent len;
+#endif
+    unsigned members_remaining, num_skipped=0, num_bad_pwd=0;
+    long cd_bufstart, bufstart, inbuf_offset, request;
+    LONGINT old_extra_bytes = 0L;
+#ifdef SET_DIR_ATTRIB
+    unsigned num_dirs=0;
+    dirtime *dirlist=(dirtime *)NULL, **sorted_dirlist=(dirtime **)NULL;
+#endif
+
+
+/*---------------------------------------------------------------------------
+    The basic idea of this function is as follows.  Since the central di-
+    rectory lies at the end of the zipfile and the member files lie at the
+    beginning or middle or wherever, it is not very desirable to simply
+    read a central directory entry, jump to the member and extract it, and
+    then jump back to the central directory.  In the case of a large zipfile
+    this would lead to a whole lot of disk-grinding, especially if each mem-
+    ber file is small.  Instead, we read from the central directory the per-
+    tinent information for a block of files, then go extract/test the whole
+    block.  Thus this routine contains two small(er) loops within a very
+    large outer loop:  the first of the small ones reads a block of files
+    from the central directory; the second extracts or tests each file; and
+    the outer one loops over blocks.  There's some file-pointer positioning
+    stuff in between, but that's about it.  Btw, it's because of this jump-
+    ing around that we can afford to be lenient if an error occurs in one of
+    the member files:  we should still be able to go find the other members,
+    since we know the offset of each from the beginning of the zipfile.
+  ---------------------------------------------------------------------------*/
+
+    G.pInfo = G.info;
+    members_remaining = (unsigned)G.ecrec.total_entries_central_dir;
+
+#if CRYPT
+    G.newzip = TRUE;
+#endif
+#ifndef SFX
+    G.reported_backslash = FALSE;
+#endif
+
+    /* malloc space for check on unmatched filespecs (OK if one or both NULL) */
+    if (G.filespecs > 0  &&
+        (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != (int *)NULL)
+        for (i = 0;  i < G.filespecs;  ++i)
+            fn_matched[i] = FALSE;
+    if (G.xfilespecs > 0  &&
+        (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != (int *)NULL)
+        for (i = 0;  i < G.xfilespecs;  ++i)
+            xn_matched[i] = FALSE;
+
+/*---------------------------------------------------------------------------
+    Begin main loop over blocks of member files.  We know the entire central
+    directory is on this disk:  we would not have any of this information un-
+    less the end-of-central-directory record was on this disk, and we would
+    not have gotten to this routine unless this is also the disk on which
+    the central directory starts.  In practice, this had better be the ONLY
+    disk in the archive, but we'll add multi-disk support soon.
+  ---------------------------------------------------------------------------*/
+
+    while (members_remaining) {
+        j = 0;
+#ifdef AMIGA
+        memzero(G.filenotes, DIR_BLKSIZ * sizeof(char *));
+#endif
+
+        /*
+         * Loop through files in central directory, storing offsets, file
+         * attributes, case-conversion and text-conversion flags until block
+         * size is reached.
+         */
+
+        while (members_remaining && (j < DIR_BLKSIZ)) {
+            --members_remaining;
+            G.pInfo = &G.info[j];
+
+            if (readbuf(__G__ G.sig, 4) == 0) {
+                error_in_archive = PK_EOF;
+                members_remaining = 0;  /* ...so no more left to do */
+                break;
+            }
+            if (strncmp(G.sig, central_hdr_sig, 4)) {  /* just to make sure */
+                Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg),
+                  j + blknum*DIR_BLKSIZ + 1));
+                Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
+                error_in_archive = PK_BADERR;
+                members_remaining = 0;  /* ...so no more left to do */
+                break;
+            }
+            /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */
+            if ((error = process_cdir_file_hdr(__G)) != PK_COOL) {
+                error_in_archive = error;   /* only PK_EOF defined */
+                members_remaining = 0;  /* ...so no more left to do */
+                break;
+            }
+            if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=
+                 PK_COOL)
+            {
+                if (error > error_in_archive)
+                    error_in_archive = error;
+                if (error > PK_WARN) {  /* fatal:  no more left to do */
+                    Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg),
+                      FnFilter1(G.filename), "central"));
+                    members_remaining = 0;
+                    break;
+                }
+            }
+            if ((error = do_string(__G__ G.crec.extra_field_length,
+                EXTRA_FIELD)) != 0)
+            {
+                if (error > error_in_archive)
+                    error_in_archive = error;
+                if (error > PK_WARN) {  /* fatal */
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarString(ExtFieldMsg),
+                      FnFilter1(G.filename), "central"));
+                    members_remaining = 0;
+                    break;
+                }
+            }
+#ifdef AMIGA
+            G.filenote_slot = j;
+            if ((error = do_string(__G__ G.crec.file_comment_length,
+                                   uO.N_flag ? FILENOTE : SKIP)) != PK_COOL)
+#else
+            if ((error = do_string(__G__ G.crec.file_comment_length, SKIP))
+                != PK_COOL)
+#endif
+            {
+                if (error > error_in_archive)
+                    error_in_archive = error;
+                if (error > PK_WARN) {  /* fatal */
+                    Info(slide, 0x421, ((char *)slide,
+                      LoadFarString(BadFileCommLength),
+                      FnFilter1(G.filename)));
+                    members_remaining = 0;
+                    break;
+                }
+            }
+            if (G.process_all_files) {
+                if (store_info(__G))
+                    ++j;  /* file is OK; info[] stored; continue with next */
+                else
+                    ++num_skipped;
+            } else {
+                int   do_this_file;
+
+                if (G.filespecs == 0)
+                    do_this_file = TRUE;
+                else {  /* check if this entry matches an `include' argument */
+                    do_this_file = FALSE;
+                    for (i = 0; i < G.filespecs; i++)
+                        if (match(G.filename, G.pfnames[i], uO.C_flag)) {
+                            do_this_file = TRUE;  /* ^-- ignore case or not? */
+                            if (fn_matched)
+                                fn_matched[i] = TRUE;
+                            break;       /* found match, so stop looping */
+                        }
+                }
+                if (do_this_file) {  /* check if this is an excluded file */
+                    for (i = 0; i < G.xfilespecs; i++)
+                        if (match(G.filename, G.pxnames[i], uO.C_flag)) {
+                            do_this_file = FALSE; /* ^-- ignore case or not? */
+                            if (xn_matched)
+                                xn_matched[i] = TRUE;
+                            break;
+                        }
+                }
+                if (do_this_file) {
+                    if (store_info(__G))
+                        ++j;            /* file is OK */
+                    else
+                        ++num_skipped;  /* unsupp. compression or encryption */
+                }
+            } /* end if (process_all_files) */
+
+
+        } /* end while-loop (adding files to current block) */
+
+        /* save position in central directory so can come back later */
+        cd_bufstart = G.cur_zipfile_bufstart;
+        cd_inptr = G.inptr;
+        cd_incnt = G.incnt;
+
+    /*-----------------------------------------------------------------------
+        Second loop:  process files in current block, extracting or testing
+        each one.
+      -----------------------------------------------------------------------*/
+
+        for (i = 0; i < j; ++i) {
+            filnum++;   /* filnum = i + blknum*DIR_BLKSIZ + 1; */
+            G.pInfo = &G.info[i];
+#ifdef NOVELL_BUG_FAILSAFE
+            G.dne = FALSE;  /* assume file exists until stat() says otherwise */
+#endif
+
+            /* if the target position is not within the current input buffer
+             * (either haven't yet read far enough, or (maybe) skipping back-
+             * ward), skip to the target position and reset readbuf(). */
+
+            /* ZLSEEK(pInfo->offset):  */
+            request = G.pInfo->offset + G.extra_bytes;
+            inbuf_offset = request % INBUFSIZ;
+            bufstart = request - inbuf_offset;
+
+            Trace((stderr, "\ndebug: request = %ld, inbuf_offset = %ld\n",
+              request, inbuf_offset));
+            Trace((stderr,
+              "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
+              bufstart, G.cur_zipfile_bufstart));
+            if (request < 0) {
+                Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg),
+                  G.zipfn, LoadFarString(ReportMsg)));
+                error_in_archive = PK_ERR;
+                if (filnum == 1 && G.extra_bytes != 0L) {
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarString(AttemptRecompensate)));
+                    old_extra_bytes = G.extra_bytes;
+                    G.extra_bytes = 0L;
+                    request = G.pInfo->offset;  /* could also check if != 0 */
+                    inbuf_offset = request % INBUFSIZ;
+                    bufstart = request - inbuf_offset;
+                    Trace((stderr, "debug: request = %ld, inbuf_offset = %ld\n",
+                      request, inbuf_offset));
+                    Trace((stderr,
+                      "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
+                      bufstart, G.cur_zipfile_bufstart));
+                } else {
+                    error_in_archive = PK_BADERR;
+                    continue;  /* this one hosed; try next */
+                }
+            }
+            /* try again */
+            if (request < 0) {
+                Trace((stderr, "debug: recompensated request still < 0\n"));
+                Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg),
+                  G.zipfn, LoadFarString(ReportMsg)));
+                error_in_archive = PK_BADERR;
+                continue;
+            } else if (bufstart != G.cur_zipfile_bufstart) {
+                Trace((stderr, "debug: bufstart != cur_zipfile_bufstart\n"));
+#ifdef USE_STRM_INPUT
+                fseek((FILE *)G.zipfd,(LONGINT)bufstart,SEEK_SET);
+                G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd);
+#else /* !USE_STRM_INPUT */
+                G.cur_zipfile_bufstart =
+                  acelseek((LONGINT)bufstart,SEEK_SET);
+#endif /* ?USE_STRM_INPUT */
+                if ((G.incnt = aceread((char *)G.inbuf,INBUFSIZ)) <= 0)
+                {
+                    Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
+                      filnum, "lseek", bufstart));
+                    error_in_archive = PK_BADERR;
+                    continue;   /* can still do next file */
+                }
+                G.inptr = G.inbuf + (int)inbuf_offset;
+                G.incnt -= (int)inbuf_offset;
+            } else {
+                G.incnt += (int)(G.inptr-G.inbuf) - (int)inbuf_offset;
+                G.inptr = G.inbuf + (int)inbuf_offset;
+            }
+
+            /* should be in proper position now, so check for sig */
+            if (readbuf(__G__ G.sig, 4) == 0) {  /* bad offset */
+                Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
+                  filnum, "EOF", request));
+                error_in_archive = PK_BADERR;
+                continue;   /* but can still try next one */
+            }
+            if (strncmp(G.sig, local_hdr_sig, 4)) {
+                Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
+                  filnum, LoadFarStringSmall(LocalHdrSig), request));
+                /*
+                    GRRDUMP(G.sig, 4)
+                    GRRDUMP(local_hdr_sig, 4)
+                 */
+                error_in_archive = PK_ERR;
+                if ((filnum == 1 && G.extra_bytes != 0L) ||
+                    (G.extra_bytes == 0L && old_extra_bytes != 0L)) {
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarString(AttemptRecompensate)));
+                    if (G.extra_bytes) {
+                        old_extra_bytes = G.extra_bytes;
+                        G.extra_bytes = 0L;
+                    } else
+                        G.extra_bytes = old_extra_bytes;  /* third attempt */
+                    ZLSEEK(G.pInfo->offset)
+                    if (readbuf(__G__ G.sig, 4) == 0) {  /* bad offset */
+                        Info(slide, 0x401, ((char *)slide,
+                          LoadFarString(OffsetMsg), filnum, "EOF", request));
+                        error_in_archive = PK_BADERR;
+                        continue;   /* but can still try next one */
+                    }
+                    if (strncmp(G.sig, local_hdr_sig, 4)) {
+                        Info(slide, 0x401, ((char *)slide,
+                          LoadFarString(OffsetMsg), filnum,
+                          LoadFarStringSmall(LocalHdrSig), request));
+                        error_in_archive = PK_BADERR;
+                        continue;
+                    }
+                } else
+                    continue;  /* this one hosed; try next */
+            }
+            if ((error = process_local_file_hdr(__G)) != PK_COOL) {
+                Info(slide, 0x421, ((char *)slide, LoadFarString(BadLocalHdr),
+                  filnum));
+                error_in_archive = error;   /* only PK_EOF defined */
+                continue;   /* can still try next one */
+            }
+            if ((error = do_string(__G__ G.lrec.filename_length, DS_FN)) !=
+                 PK_COOL)
+            {
+                if (error > error_in_archive)
+                    error_in_archive = error;
+                if (error > PK_WARN) {
+                    Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg),
+                      FnFilter1(G.filename), "local"));
+                    continue;   /* go on to next one */
+                }
+            }
+            if (G.extra_field != (uch *)NULL) {
+                free(G.extra_field);
+                G.extra_field = (uch *)NULL;
+            }
+            if ((error =
+                 do_string(__G__ G.lrec.extra_field_length, EXTRA_FIELD)) != 0)
+            {
+                if (error > error_in_archive)
+                    error_in_archive = error;
+                if (error > PK_WARN) {
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarString(ExtFieldMsg),
+                      FnFilter1(G.filename), "local"));
+                    continue;   /* go on */
+                }
+            }
+
+#if CRYPT
+            if (G.pInfo->encrypted &&
+                (error = decrypt(__G__ uO.pwdarg)) != PK_COOL) {
+                if (error == PK_WARN) {
+                    if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
+                        Info(slide, 0x401, ((char *)slide,
+                          LoadFarString(SkipIncorrectPasswd),
+                          FnFilter1(G.filename)));
+                    ++num_bad_pwd;
+                } else {  /* (error > PK_WARN) */
+                    if (error > error_in_archive)
+                        error_in_archive = error;
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarString(SkipCannotGetPasswd),
+                      FnFilter1(G.filename)));
+                }
+                continue;   /* go on to next file */
+            }
+#endif /* CRYPT */
+
+            /*
+             * just about to extract file:  if extracting to disk, check if
+             * already exists, and if so, take appropriate action according to
+             * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper
+             * loop because we don't store the possibly renamed filename[] in
+             * info[])
+             */
+#ifdef DLL
+            if (!uO.tflag && !uO.cflag && !G.redirect_data)
+#else
+            if (!uO.tflag && !uO.cflag)
+#endif
+            {
+                renamed = FALSE;   /* user hasn't renamed output file yet */
+
+startover:
+                query = FALSE;
+                /* for files from DOS FAT, check for use of backslash instead
+                 *  of slash as directory separator (bug in some zipper(s); so
+                 *  far, not a problem in HPFS, NTFS or VFAT systems)
+                 */
+#ifndef SFX
+                if (G.pInfo->hostnum == FS_FAT_ && !strchr(G.filename, '/')) {
+                    char *p=G.filename-1;
+
+                    while (*++p) {
+                        if (*p == '\\') {
+                            if (!G.reported_backslash) {
+                                Info(slide, 0x21, ((char *)slide,
+                                  LoadFarString(BackslashPathSep), G.zipfn));
+                                G.reported_backslash = TRUE;
+                                if (!error_in_archive)
+                                    error_in_archive = PK_WARN;
+                            }
+                            *p = '/';
+                        }
+                    }
+                }
+#endif /* !SFX */
+
+                /* mapname can create dirs if not freshening or if renamed */
+                if ((error = mapname(__G__ renamed)) > PK_WARN) {
+                    if (error == IZ_CREATED_DIR) {
+#ifdef SET_DIR_ATTRIB
+                        dirtime *d_entry;
+
+                        d_entry = (dirtime *)malloc(sizeof(dirtime));
+                        if (d_entry == (dirtime *)NULL) {
+                            Info(slide, 0x401, ((char *)slide,
+                                 LoadFarString(DirlistEntryNoMem)));
+                        } else {
+                            unsigned eb_izux_flg;
+
+                            d_entry->next = dirlist;
+                            dirlist = d_entry;
+                            dirlist->fn =
+                              (char *)malloc(strlen(G.filename) + 1);
+                            if (dirlist->fn == (char *)NULL) {
+                                Info(slide, 0x401, ((char *)slide,
+                                  LoadFarString(DirlistEntryNoMem)));
+                                dirlist = d_entry->next;
+                                free(d_entry);
+                                if (!error_in_archive)
+                                    error_in_archive = PK_WARN;
+                                continue;
+                            }
+                            strcpy(dirlist->fn, G.filename);
+                            dirlist->perms = G.pInfo->file_attr;
+#ifdef USE_EF_UT_TIME
+                            eb_izux_flg = G.extra_field? ef_scan_for_izux(
+                              G.extra_field, G.lrec.extra_field_length, 0,
+                              G.lrec.last_mod_dos_datetime,
+#ifdef IZ_CHECK_TZ
+                              (G.tz_is_valid ? &(dirlist->u.t3) : NULL),
+#else
+                              &(dirlist->u.t3),
+#endif
+                              dirlist->uidgid)
+                              : 0;
+#else /* !USE_EF_UT_TIME */
+                            eb_izux_flg = 0;
+#endif /* ?USE_EF_UT_TIME */
+                            if (eb_izux_flg & EB_UT_FL_MTIME) {
+                                TTrace((stderr,
+                                  "\nextract:  Unix dir e.f. modtime = %ld\n",
+                                  dirlist->u.t3.mtime));
+                            } else {
+                                dirlist->u.t3.mtime = dos_to_unix_time(
+                                  G.lrec.last_mod_dos_datetime);
+                            }
+                            if (eb_izux_flg & EB_UT_FL_ATIME) {
+                                TTrace((stderr,
+                                  "\nextract:  Unix dir e.f. actime = %ld\n",
+                                  dirlist->u.t3.atime));
+                            } else {
+                                dirlist->u.t3.atime =
+                                  dirlist->u.t3.mtime;
+                            }
+                            dirlist->have_uidgid =
+                                (uO.X_flag && (eb_izux_flg & EB_UX2_VALID));
+                            ++num_dirs;
+                        }
+#endif /* SET_DIR_ATTRIB */
+                    } else if (error == IZ_VOL_LABEL) {
+#ifdef DOS_OS2_W32
+                        Info(slide, 0x401, ((char *)slide,
+                          LoadFarString(SkipVolumeLabel),
+                          FnFilter1(G.filename),
+                          uO.volflag? "hard disk " : ""));
+#else
+                        Info(slide, 1, ((char *)slide,
+                          LoadFarString(SkipVolumeLabel),
+                          FnFilter1(G.filename), ""));
+#endif
+                    /*  if (!error_in_archive)
+                            error_in_archive = PK_WARN;  */
+                    } else if (error > PK_ERR  &&  error_in_archive < PK_ERR)
+                        error_in_archive = PK_ERR;
+                    Trace((stderr, "mapname(%s) returns error = %d\n",
+                      FnFilter1(G.filename), error));
+                    continue;   /* go on to next file */
+                }
+
+#ifdef QDOS
+                QFilename(__G__ G.filename);
+#endif
+				if(get_image)
+					goto skip_newer_check;
+
+                switch (check_for_newer(__G__ G.filename)) {
+                    case DOES_NOT_EXIST:
+#ifdef NOVELL_BUG_FAILSAFE
+                        G.dne = TRUE;   /* stat() says file DOES NOT EXIST */
+#endif
+                        /* if freshening, don't skip if just renamed */
+                        if (uO.fflag && !renamed)
+                            continue;   /* freshen (no new files):  skip */
+                        break;
+                    case EXISTS_AND_OLDER:
+                        if (uO.overwrite_none) {
+#ifdef WINDLL
+                            char szStr[FILNAMSIZ+40]; /* add. space for text */
+
+                            if ((!G.prompt_always) || (done_once)) {
+                                sprintf(szStr,
+                                  "Target file exists.\nSkipping %s\n",
+                                  FnFilter1(G.filename));
+                                win_fprintf((zvoid *)&G, stdout,
+                                  strlen(szStr), szStr);
+                            } else {
+                                query = TRUE;
+                                break;
+                            }
+#endif /* WINDLL */
+                            continue;   /* never overwrite:  skip file */
+                        }
+#ifdef UNIXBACKUP
+                        if (!uO.overwrite_all && !uO.B_flag)
+#else
+                        if (!uO.overwrite_all)
+#endif
+                            query = TRUE;
+                        break;
+                    case EXISTS_AND_NEWER:             /* (or equal) */
+                        if (uO.overwrite_none || (uO.uflag && !renamed)) {
+#ifdef WINDLL
+                            char szStr[FILNAMSIZ+40]; /* add. space for text */
+
+                            if ((!G.prompt_always) || (done_once)) {
+                                sprintf(szStr,
+                                  "Target file newer.\nSkipping %s\n",
+                                  FnFilter1(G.filename));
+                                win_fprintf((zvoid *)&G, stdout,
+                                  strlen(szStr), szStr);
+                            } else {
+                                query = TRUE;
+                                break;
+                            }
+#endif /* WINDLL */
+                            continue;  /* skip if update/freshen & orig name */
+                        }
+#ifdef UNIXBACKUP
+                        if (!uO.overwrite_all && !uO.B_flag)
+#else
+                        if (!uO.overwrite_all)
+#endif
+                            query = TRUE;
+                        break;
+				}
+                if (query) {
+#ifdef WINDLL
+                    switch (G.lpUserFunctions->replace != NULL ?
+                            (*G.lpUserFunctions->replace)(G.filename) :
+                            IDM_REPLACE_NONE) {
+                        case IDM_REPLACE_RENAME:
+                            _ISO_INTERN(G.filename);
+                            renamed = TRUE;
+                            goto startover;
+                        case IDM_REPLACE_YES:
+                            break;
+                        case IDM_REPLACE_ALL:
+                            uO.overwrite_all = TRUE;
+                            uO.overwrite_none = FALSE;  /* just to make sure */
+                            break;
+                        case IDM_REPLACE_NONE:
+                            uO.overwrite_none = TRUE;
+                            uO.overwrite_all = FALSE;   /* make sure */
+                            done_once = TRUE;
+                            /* FALL THROUGH, skip */
+                        case IDM_REPLACE_NO:
+                            {
+                                char szStr[FILNAMSIZ+40];
+
+                                sprintf(szStr,
+                                  "Target file newer.\nSkipping %s\n",
+                                  FnFilter1(G.filename));
+                                win_fprintf((zvoid *)&G, stdout,
+                                  strlen(szStr), szStr);
+                            }
+                            continue;
+                    }
+#else /* !WINDLL */
+reprompt:
+                    Info(slide, 0x81, ((char *)slide,
+                      LoadFarString(ReplaceQuery),
+									   FnFilter1(G.filename)));
+#if 0
+                    if (fgets(G.answerbuf, 9, stdin) == (char *)NULL) {
+                        Info(slide, 1, ((char *)slide,
+                          LoadFarString(AssumeNone)));
+                        *G.answerbuf = 'N';
+                        if (!error_in_archive)
+                            error_in_archive = 1;  /* not extracted:  warning */
+					}
+#endif
+					*G.answerbuf = conversionTable[confirm("Overwrite file \"%s\"?", G.filename)];
+                    switch (*G.answerbuf) {
+                        case 'A':   /* dangerous option:  force caps */
+                            uO.overwrite_all = TRUE;
+                            uO.overwrite_none = FALSE;  /* just to make sure */
+                            break;
+                        case 'r':
+                        case 'R':
+                            do {
+                                Info(slide, 0x81, ((char *)slide,
+                                  LoadFarString(NewNameQuery)));
+                                fgets(G.filename, FILNAMSIZ, stdin);
+                                /* usually get \n here:  better check for it */
+                                len = strlen(G.filename);
+                                if (G.filename[len-1] == '\n')
+                                    G.filename[--len] = '\0';
+                            } while (len == 0);
+#ifdef WIN32  /* WIN32 fgets( ... , stdin) returns OEM coded strings */
+                            _OEM_INTERN(G.filename);
+#endif
+                            renamed = TRUE;
+                            goto startover;   /* sorry for a goto */
+                        case 'y':
+                        case 'Y':
+                            break;
+                        case 'N':
+                            uO.overwrite_none = TRUE;
+                            uO.overwrite_all = FALSE;   /* make sure */
+                            /* FALL THROUGH, skip */
+                        case 'n':
+							continue;   /* skip file */
+                        case 'C':
+                            members_remaining = 0;
+							continue;   /* skip file */
+                        default:
+                            Info(slide, 1, ((char *)slide,
+                              LoadFarString(InvalidResponse), *G.answerbuf));
+                            goto reprompt;   /* yet another goto? */
+                    } /* end switch (*answerbuf) */
+#endif /* ?WINDLL */
+				} /* end if (query) */
+			skip_newer_check:
+
+            } /* end if (extracting to disk) */
+
+#ifdef DLL
+            if ((G.statreportcb != NULL) &&
+                (*G.statreportcb)(__G__ UZ_ST_START_EXTRACT, G.zipfn,
+                                  G.filename, NULL)) {
+                if (fn_matched)
+                    free((zvoid *)fn_matched);
+                if (xn_matched)
+                    free((zvoid *)xn_matched);
+                return IZ_CTRLC;        /* cancel operation by user request */
+            }
+#endif
+#ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */
+            UserStop();
+#endif
+#ifdef AMIGA
+            G.filenote_slot = i;
+#endif
+            G.disk_full = 0;
+            if ((error = extract_or_test_member(__G)) != PK_COOL) {
+                if (error > error_in_archive)
+                    error_in_archive = error;       /* ...and keep going */
+#ifdef DLL
+                if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) {
+#else
+                if (G.disk_full > 1) {
+#endif
+                    if (fn_matched)
+                        free((zvoid *)fn_matched);
+                    if (xn_matched)
+                        free((zvoid *)xn_matched);
+                    return error_in_archive;        /* (unless disk full) */
+                }
+            }
+#ifdef DLL
+            if ((G.statreportcb != NULL) &&
+                (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn,
+                                  G.filename, (zvoid *)&G.lrec.ucsize)) {
+                if (fn_matched)
+                    free((zvoid *)fn_matched);
+                if (xn_matched)
+                    free((zvoid *)xn_matched);
+                return IZ_CTRLC;        /* cancel operation by user request */
+            }
+#endif
+#ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */
+            UserStop();
+#endif
+        } /* end for-loop (i:  files in current block) */
+
+
+        /*
+         * Jump back to where we were in the central directory, then go and do
+         * the next batch of files.
+         */
+
+#ifdef USE_STRM_INPUT
+        fseek((FILE *)G.zipfd, (LONGINT)cd_bufstart, SEEK_SET);
+        G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd);
+#else /* !USE_STRM_INPUT */
+        G.cur_zipfile_bufstart = acelseek((LONGINT)cd_bufstart,SEEK_SET);
+#endif /* ?USE_STRM_INPUT */
+        aceread((char *)G.inbuf, INBUFSIZ);  /* been here before... */
+        G.inptr = cd_inptr;
+        G.incnt = cd_incnt;
+        ++blknum;
+
+#ifdef TEST
+        pipeit("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart);
+        pipeit("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart,
+          cur_zipfile_bufstart);
+        pipeit("inptr-inbuf = %d\n", G.inptr-G.inbuf);
+        pipeit("incnt = %d\n\n", G.incnt);
+#endif
+
+    } /* end while-loop (blocks of files in central directory) */
+
+/*---------------------------------------------------------------------------
+    Go back through saved list of directories, sort and set times/perms/UIDs
+    and GIDs from the deepest level on up.
+  ---------------------------------------------------------------------------*/
+
+#ifdef SET_DIR_ATTRIB
+    if (num_dirs > 0) {
+        sorted_dirlist = (dirtime **)malloc(num_dirs*sizeof(dirtime *));
+        if (sorted_dirlist == (dirtime **)NULL) {
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(DirlistSortNoMem)));
+            while (dirlist != (dirtime *)NULL) {
+                dirtime *d = dirlist;
+
+                dirlist = dirlist->next;
+                free(d);
+            }
+        } else {
+            if (num_dirs == 1)
+                sorted_dirlist[0] = dirlist;
+            else {
+                for (i = 0;  i < num_dirs;  ++i) {
+                    sorted_dirlist[i] = dirlist;
+                    dirlist = dirlist->next;
+                }
+                qsort((char *)sorted_dirlist, num_dirs, sizeof(dirtime *),
+                  dircomp);
+            }
+
+            Trace((stderr, "setting directory times/perms/attributes\n"));
+            for (i = 0;  i < num_dirs;  ++i) {
+                dirtime *d = sorted_dirlist[i];
+
+                Trace((stderr, "dir = %s\n", d->fn));
+                if ((error = set_direc_attribs(__G__ d)) != PK_OK) {
+                    Info(slide, 0x201, ((char *)slide,
+                      LoadFarString(DirlistSetAttrFailed), d->fn));
+                    if (!error_in_archive)
+                        error_in_archive = error;
+                }
+                free(d->fn);
+                free(d);
+            }
+            free(sorted_dirlist);
+        }
+    }
+#endif /* SET_DIR_ATTRIB */
+
+#if (defined(WIN32) && defined(NTSD_EAS))
+    process_defer_NT(__G);  /* process any deferred items for this .zip file */
+#endif
+
+/*---------------------------------------------------------------------------
+    Check for unmatched filespecs on command line and print warning if any
+    found.  Free allocated memory.
+  ---------------------------------------------------------------------------*/
+
+    if (fn_matched) {
+        for (i = 0;  i < G.filespecs;  ++i)
+            if (!fn_matched[i]) {
+#ifdef DLL
+                if (!G.redirect_data && !G.redirect_text)
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarString(FilenameNotMatched), G.pfnames[i]));
+                else
+                    setFileNotFound(__G);
+#else
+                Info(slide, 1, ((char *)slide,
+                  LoadFarString(FilenameNotMatched), G.pfnames[i]));
+#endif
+                if (error_in_archive <= PK_WARN)
+                    error_in_archive = PK_FIND;   /* some files not found */
+            }
+        free((zvoid *)fn_matched);
+    }
+    if (xn_matched) {
+        for (i = 0;  i < G.xfilespecs;  ++i)
+            if (!xn_matched[i])
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(ExclFilenameNotMatched), G.pxnames[i]));
+        free((zvoid *)xn_matched);
+    }
+
+/*---------------------------------------------------------------------------
+    Double-check that we're back at the end-of-central-directory record, and
+    print quick summary of results, if we were just testing the archive.  We
+    send the summary to stdout so that people doing the testing in the back-
+    ground and redirecting to a file can just do a "tail" on the output file.
+  ---------------------------------------------------------------------------*/
+
+#ifndef SFX
+    if (readbuf(__G__ G.sig, 4) == 0)
+        error_in_archive = PK_EOF;
+    if (strncmp(G.sig, end_central_sig, 4)) {   /* just to make sure */
+        Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
+        Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
+        if (!error_in_archive)       /* don't overwrite stronger error */
+            error_in_archive = PK_WARN;
+    }
+#endif /* !SFX */
+    if (uO.tflag) {
+        unsigned num = filnum - num_bad_pwd;
+
+        if (uO.qflag < 2) {        /* GRR 930710:  was (uO.qflag == 1) */
+            if (error_in_archive)
+                Info(slide, 0, ((char *)slide, LoadFarString(ErrorInArchive),
+                  (error_in_archive == 1)? "warning-" : "", G.zipfn));
+            else if (num == 0)
+                Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested),
+                  G.zipfn));
+            else if (G.process_all_files && (num_skipped+num_bad_pwd == 0))
+                Info(slide, 0, ((char *)slide, LoadFarString(NoErrInCompData),
+                  G.zipfn));
+            else
+                Info(slide, 0, ((char *)slide, LoadFarString(NoErrInTestedFiles)
+                  , G.zipfn, num, (num==1)? "":"s"));
+            if (num_skipped > 0)
+                Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipped),
+                  num_skipped, (num_skipped==1)? "":"s"));
+#if CRYPT
+            if (num_bad_pwd > 0)
+                Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipBadPasswd)
+                  , num_bad_pwd, (num_bad_pwd==1)? "":"s"));
+#endif /* CRYPT */
+        } else if ((uO.qflag == 0) && !error_in_archive && (num == 0))
+            Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested),
+              G.zipfn));
+    }
+
+    /* give warning if files not tested or extracted (first condition can still
+     * happen if zipfile is empty and no files specified on command line) */
+
+    if ((filnum == 0) && error_in_archive <= PK_WARN) {
+        if (num_skipped > 0)
+            error_in_archive = IZ_UNSUP; /* unsupport. compression/encryption */
+        else
+            error_in_archive = PK_FIND;  /* no files found at all */
+    }
+#if CRYPT
+    else if ((filnum == num_bad_pwd) && error_in_archive <= PK_WARN)
+        error_in_archive = IZ_BADPWD;    /* bad passwd => all files skipped */
+#endif
+    else if ((num_skipped > 0) && error_in_archive <= PK_WARN)
+        error_in_archive = IZ_UNSUP;     /* was PK_WARN; Jean-loup complained */
+#if CRYPT
+    else if ((num_bad_pwd > 0) && !error_in_archive)
+        error_in_archive = PK_WARN;
+#endif
+
+    return error_in_archive;
+
+} /* end function extract_or_test_files() */
+
+
+
+
+
+/***************************/
+/*  Function store_info()  */
+/***************************/
+
+static int store_info(__G)   /* return 0 if skipping, 1 if OK */
+    __GDEF
+{
+#ifdef SFX
+#  define UNKN_COMPR \
+   (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED)
+#else
+#  ifdef COPYRIGHT_CLEAN  /* no reduced files */
+#    define UNKN_RED (G.crec.compression_method >= REDUCED1 && \
+                      G.crec.compression_method <= REDUCED4)
+#  else
+#    define UNKN_RED  FALSE  /* reducing not unknown */
+#  endif
+#  ifdef LZW_CLEAN  /* no shrunk files */
+#    define UNKN_SHR (G.crec.compression_method == SHRUNK)
+#  else
+#    define UNKN_SHR  FALSE  /* unshrinking not unknown */
+#  endif
+#  define UNKN_COMPR (UNKN_RED || UNKN_SHR || \
+   G.crec.compression_method==TOKENIZED || G.crec.compression_method>DEFLATED)
+#endif
+
+/*---------------------------------------------------------------------------
+    Check central directory info for version/compatibility requirements.
+  ---------------------------------------------------------------------------*/
+
+    G.pInfo->encrypted = G.crec.general_purpose_bit_flag & 1;   /* bit field */
+    G.pInfo->ExtLocHdr = (G.crec.general_purpose_bit_flag & 8) == 8;  /* bit */
+    G.pInfo->textfile = G.crec.internal_file_attributes & 1;    /* bit field */
+    G.pInfo->crc = G.crec.crc32;
+    G.pInfo->compr_size = G.crec.csize;
+    G.pInfo->uncompr_size = G.crec.ucsize;
+
+    switch (uO.aflag) {
+        case 0:
+            G.pInfo->textmode = FALSE;   /* bit field */
+            break;
+        case 1:
+            G.pInfo->textmode = G.pInfo->textfile;   /* auto-convert mode */
+            break;
+        default:  /* case 2: */
+            G.pInfo->textmode = TRUE;
+            break;
+    }
+
+    if (G.crec.version_needed_to_extract[1] == VMS_) {
+        if (G.crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) {
+            if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
+                Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
+                  FnFilter1(G.filename), "VMS",
+                  G.crec.version_needed_to_extract[0] / 10,
+                  G.crec.version_needed_to_extract[0] % 10,
+                  VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10));
+            return 0;
+        }
+#ifndef VMS   /* won't be able to use extra field, but still have data */
+        else if (!uO.tflag && !uO.overwrite_all) { /* if -o, extract anyway */
+            Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery),
+              FnFilter1(G.filename)));
+            fgets(G.answerbuf, 9, stdin);
+            if ((*G.answerbuf != 'y') && (*G.answerbuf != 'Y'))
+                return 0;
+        }
+#endif /* !VMS */
+    /* usual file type:  don't need VMS to extract */
+    } else if (G.crec.version_needed_to_extract[0] > UNZIP_VERSION) {
+        if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
+            Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
+              FnFilter1(G.filename), "PK",
+              G.crec.version_needed_to_extract[0] / 10,
+              G.crec.version_needed_to_extract[0] % 10,
+              UNZIP_VERSION / 10, UNZIP_VERSION % 10));
+        return 0;
+    }
+
+    if UNKN_COMPR {
+        if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) {
+#ifndef SFX
+            if (G.crec.compression_method < NUM_METHODS)
+                Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName),
+                  FnFilter1(G.filename),
+                  LoadFarStringSmall(ComprNames[G.crec.compression_method])));
+            else
+#endif
+                Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgNum),
+                  FnFilter1(G.filename),
+                  G.crec.compression_method));
+        }
+        return 0;
+    }
+#if (!CRYPT)
+    if (G.pInfo->encrypted) {
+        if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
+            Info(slide, 0x401, ((char *)slide, LoadFarString(SkipEncrypted),
+              FnFilter1(G.filename)));
+        return 0;
+    }
+#endif /* !CRYPT */
+
+    /* map whatever file attributes we have into the local format */
+    mapattr(__G);   /* GRR:  worry about return value later */
+
+    G.pInfo->offset = (long)G.crec.relative_offset_local_header;
+    return 1;
+
+} /* end function store_info() */
+
+
+
+
+
+/***************************************/
+/*  Function extract_or_test_member()  */
+/***************************************/
+
+static int extract_or_test_member(__G)    /* return PK-type error code */
+     __GDEF
+{
+    char *nul="[empty] ", *txt="[text]  ", *bin="[binary]";
+#ifdef CMS_MVS
+    char *ebc="[ebcdic]";
+#endif
+    register int b;
+    int r, error=PK_COOL;
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+    ulg wsize;
+#else
+#   define wsize WSIZE
+#endif
+
+
+/*---------------------------------------------------------------------------
+    Initialize variables, buffers, etc.
+  ---------------------------------------------------------------------------*/
+
+    G.bits_left = 0;
+    G.bitbuf = 0L;       /* unreduce and unshrink only */
+    G.zipeof = 0;
+    G.newfile = TRUE;
+    G.crc32val = CRCVAL_INITIAL;
+
+#ifdef SYMLINKS
+    /* if file came from Unix and is a symbolic link and we are extracting
+     * to disk, prepare to restore the link */
+    if (S_ISLNK(G.pInfo->file_attr) &&
+        (G.pInfo->hostnum == UNIX_ || G.pInfo->hostnum == ATARI_ ||
+         G.pInfo->hostnum == BEOS_) &&
+        !uO.tflag && !uO.cflag && (G.lrec.ucsize > 0))
+        G.symlnk = TRUE;
+    else
+        G.symlnk = FALSE;
+#endif /* SYMLINKS */
+
+    if (uO.tflag) {
+        if (!uO.qflag)
+            Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "test",
+              FnFilter1(G.filename), "", ""));
+    } else {
+#ifdef DLL
+        if (uO.cflag && !G.redirect_data)
+#else
+        if (uO.cflag)
+#endif
+        {
+#if (defined(OS2) && defined(__IBMC__) && (__IBMC__ >= 200))
+            G.outfile = freopen("", "wb", stdout);   /* VAC++ ignores setmode */
+#else
+            G.outfile = stdout;
+#endif
+#ifdef DOS_FLX_H68_OS2_W32
+#if (defined(__HIGHC__) && !defined(FLEXOS))
+            setmode(G.outfile, _BINARY);
+#else /* !(defined(__HIGHC__) && !defined(FLEXOS)) */
+            setmode(fileno(G.outfile), O_BINARY);
+#endif /* ?(defined(__HIGHC__) && !defined(FLEXOS)) */
+#           define NEWLINE "\r\n"
+#else /* !DOS_FLX_H68_OS2_W32 */
+#           define NEWLINE "\n"
+#endif /* ?DOS_FLX_H68_OS2_W32 */
+#ifdef VMS
+            if (open_outfile(__G))   /* VMS:  required even for stdout! */
+                return PK_DISK;
+#endif
+        } else if (open_outfile(__G))
+            return PK_DISK;
+    }
+
+/*---------------------------------------------------------------------------
+    Unpack the file.
+  ---------------------------------------------------------------------------*/
+
+    defer_leftover_input(__G);    /* so NEXTBYTE bounds check will work */
+    switch (G.lrec.compression_method) {
+        case STORED:
+            if (!uO.tflag && QCOND2) {
+#ifdef SYMLINKS
+                if (G.symlnk)   /* can also be deflated, but rarer... */
+                    Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
+                      "link", FnFilter1(G.filename), "", ""));
+                else
+#endif /* SYMLINKS */
+                Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
+                  "extract", FnFilter1(G.filename),
+                  (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
+                  "" : (G.lrec.ucsize == 0L? nul : (G.pInfo->textfile? txt :
+                  bin)), uO.cflag? NEWLINE : ""));
+            }
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+            if (G.redirect_slide) {
+                wsize = G.redirect_size; redirSlide = G.redirect_buffer;
+            } else {
+                wsize = WSIZE; redirSlide = slide;
+            }
+#endif
+            G.outptr = redirSlide;
+            G.outcnt = 0L;
+            while ((b = NEXTBYTE) != EOF && !G.disk_full) {
+                *G.outptr++ = (uch)b;
+                if (++G.outcnt == wsize) {
+                    flush(__G__ redirSlide, G.outcnt, 0);
+                    G.outptr = redirSlide;
+                    G.outcnt = 0L;
+                }
+            }
+            if (G.outcnt)          /* flush final (partial) buffer */
+                flush(__G__ redirSlide, G.outcnt, 0);
+            break;
+
+#ifndef SFX
+#ifndef LZW_CLEAN
+        case SHRUNK:
+            if (!uO.tflag && QCOND2) {
+                Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
+                  LoadFarStringSmall(Unshrink), FnFilter1(G.filename),
+                  (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
+                  "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
+            }
+            if ((r = unshrink(__G)) != PK_COOL) {
+                if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarStringSmall(ErrUnzipFile),
+                      LoadFarString(NotEnoughMem),
+                      LoadFarStringSmall2(Unshrink),
+                      FnFilter1(G.filename)));
+                else
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarStringSmall(ErrUnzipNoFile),
+                      LoadFarString(NotEnoughMem),
+                      LoadFarStringSmall2(Unshrink)));
+                error = r;
+            }
+            break;
+#endif /* !LZW_CLEAN */
+
+#ifndef COPYRIGHT_CLEAN
+        case REDUCED1:
+        case REDUCED2:
+        case REDUCED3:
+        case REDUCED4:
+            if (!uO.tflag && QCOND2) {
+                Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
+                  "unreduc", FnFilter1(G.filename),
+                  (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
+                  "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
+            }
+            unreduce(__G);
+            break;
+#endif /* !COPYRIGHT_CLEAN */
+
+        case IMPLODED:
+            if (!uO.tflag && QCOND2) {
+                Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
+                  "explod", FnFilter1(G.filename),
+                  (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
+                  "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
+            }
+            if (((r = explode(__G)) != 0) && (r != 5)) { /* treat 5 specially */
+                if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarStringSmall(ErrUnzipFile), r == 3?
+                      LoadFarString(NotEnoughMem) :
+                      LoadFarString(InvalidComprData),
+                      LoadFarStringSmall2(Explode),
+                      FnFilter1(G.filename)));
+                else
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarStringSmall(ErrUnzipNoFile), r == 3?
+                      LoadFarString(NotEnoughMem) :
+                      LoadFarString(InvalidComprData),
+                      LoadFarStringSmall2(Explode)));
+                error = (r == 3)? PK_MEM3 : PK_ERR;
+            }
+            if (r == 5) {
+                int warning = ((ulg)G.used_csize <= G.lrec.csize);
+
+                if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
+                    Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg),
+                      "", warning?  "warning" : "error", G.used_csize,
+                      G.lrec.ucsize, warning?  "  " : "", G.lrec.csize,
+                      " [", FnFilter1(G.filename), "]"));
+                else
+                    Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg),
+                      "\n", warning? "warning" : "error", G.used_csize,
+                      G.lrec.ucsize, warning? "  ":"", G.lrec.csize,
+                      "", "", "."));
+                error = warning? PK_WARN : PK_ERR;
+            }
+            break;
+#endif /* !SFX */
+
+        case DEFLATED:
+            if (!uO.tflag && QCOND2) {
+                Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
+                  "inflat", FnFilter1(G.filename),
+                  (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
+                  "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
+            }
+#ifndef USE_ZLIB  /* zlib's function is called inflate(), too */
+#  define UZinflate inflate
+#endif
+            if ((r = UZinflate(__G)) != 0) {
+                if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarStringSmall(ErrUnzipFile), r == 3?
+                      LoadFarString(NotEnoughMem) :
+                      LoadFarString(InvalidComprData),
+                      LoadFarStringSmall2(Inflate),
+                      FnFilter1(G.filename)));
+                else
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarStringSmall(ErrUnzipNoFile), r == 3?
+                      LoadFarString(NotEnoughMem) :
+                      LoadFarString(InvalidComprData),
+                      LoadFarStringSmall2(Inflate)));
+                error = (r == 3)? PK_MEM3 : PK_ERR;
+            }
+            break;
+
+        default:   /* should never get to this point */
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(FileUnknownCompMethod), FnFilter1(G.filename)));
+            /* close and delete file before return? */
+            undefer_input(__G);
+            return PK_WARN;
+
+    } /* end switch (compression method) */
+
+/*---------------------------------------------------------------------------
+    Close the file and set its date and time (not necessarily in that order),
+    and make sure the CRC checked out OK.  Logical-AND the CRC for 64-bit
+    machines (redundant on 32-bit machines).
+  ---------------------------------------------------------------------------*/
+
+#ifdef VMS                  /* VMS:  required even for stdout! (final flush) */
+    if (!uO.tflag)           /* don't close NULL file */
+        close_outfile(__G);
+#else
+#ifdef DLL
+    if (!uO.tflag && (!uO.cflag || G.redirect_data)) {
+        if (G.redirect_data)
+            FINISH_REDIRECT();
+        else
+            close_outfile(__G);
+    }
+#else
+    if (!uO.tflag && !uO.cflag)   /* don't close NULL file or stdout */
+        close_outfile(__G);
+#endif
+#endif /* VMS */
+
+            /* GRR: CONVERT close_outfile() TO NON-VOID:  CHECK FOR ERRORS! */
+
+
+    if (G.disk_full) {            /* set by flush() */
+        if (G.disk_full > 1) {
+#if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK))
+            /* delete the incomplete file if we can */
+            if (unlink(G.filename) != 0)
+                Trace((stderr, "extract.c:  could not delete %s\n",
+                  FnFilter1(G.filename)));
+#else
+            /* warn user about the incomplete file */
+            Info(slide, 0x421, ((char *)slide, LoadFarString(FileTruncated),
+              FnFilter1(G.filename)));
+#endif
+            error = PK_DISK;
+        } else {
+            error = PK_WARN;
+        }
+    }
+
+    if (error > PK_WARN) {/* don't print redundant CRC error if error already */
+        undefer_input(__G);
+        return error;
+    }
+    if (G.crc32val != G.lrec.crc32) {
+        /* if quiet enough, we haven't output the filename yet:  do it */
+        if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
+            Info(slide, 0x401, ((char *)slide, "%-22s ",
+              FnFilter1(G.filename)));
+        Info(slide, 0x401, ((char *)slide, LoadFarString(BadCRC), G.crc32val,
+          G.lrec.crc32));
+#if CRYPT
+        if (G.pInfo->encrypted)
+            Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeBadPasswd)));
+#endif
+        error = PK_ERR;
+    } else if (uO.tflag) {
+#ifndef SFX
+        if (G.extra_field) {
+            if ((r = TestExtraField(__G__ G.extra_field,
+                                    G.lrec.extra_field_length)) > error)
+                error = r;
+        } else
+#endif /* !SFX */
+        if (!uO.qflag)
+            Info(slide, 0, ((char *)slide, " OK\n"));
+    } else {
+        if (QCOND2 && !error)   /* GRR:  is stdout reset to text mode yet? */
+            Info(slide, 0, ((char *)slide, "\n"));
+    }
+
+    undefer_input(__G);
+    return error;
+
+} /* end function extract_or_test_member() */
+
+
+
+
+
+#ifndef SFX
+
+/*******************************/
+/*  Function TestExtraField()  */
+/*******************************/
+
+static int TestExtraField(__G__ ef, ef_len)
+    __GDEF
+    uch *ef;
+    unsigned ef_len;
+{
+    ush ebID;
+    unsigned ebLen;
+    unsigned eb_cmpr_offs = 0;
+    int r;
+
+    /* we know the regular compressed file data tested out OK, or else we
+     * wouldn't be here ==> print filename if any extra-field errors found
+     */
+    while (ef_len >= EB_HEADSIZE) {
+        ebID = makeword(ef);
+        ebLen = (unsigned)makeword(ef+EB_LEN);
+
+        if (ebLen > (ef_len - EB_HEADSIZE)) {
+           /* Discovered some extra field inconsistency! */
+            if (uO.qflag)
+                Info(slide, 1, ((char *)slide, "%-22s ",
+                  FnFilter1(G.filename)));
+            Info(slide, 1, ((char *)slide, LoadFarString(InconsistEFlength),
+              ebLen, (ef_len - EB_HEADSIZE)));
+            return PK_ERR;
+        }
+
+        switch (ebID) {
+            case EF_OS2:
+            case EF_ACL:
+            case EF_MAC3:
+            case EF_BEOS:
+                switch (ebID) {
+                  case EF_OS2:
+                  case EF_ACL:
+                    eb_cmpr_offs = EB_OS2_HLEN;
+                    break;
+                  case EF_MAC3:
+                    if (ebLen >= EB_MAC3_HLEN &&
+                        (makeword(ef+(EB_HEADSIZE+EB_FLGS_OFFS))
+                         & EB_M3_FL_UNCMPR) &&
+                        (makelong(ef+EB_HEADSIZE) == ebLen - EB_MAC3_HLEN))
+                        eb_cmpr_offs = 0;
+                    else
+                        eb_cmpr_offs = EB_MAC3_HLEN;
+                    break;
+                  case EF_BEOS:
+                    if (ebLen >= EB_BEOS_HLEN &&
+                        (*(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) & EB_BE_FL_UNCMPR) &&
+                        (makelong(ef+EB_HEADSIZE) == ebLen - EB_BEOS_HLEN))
+                        eb_cmpr_offs = 0;
+                    else
+                        eb_cmpr_offs = EB_BEOS_HLEN;
+                    break;
+                }
+                if ((r = test_compr_eb(__G__ ef, ebLen, eb_cmpr_offs, NULL))
+                    != PK_OK) {
+                    if (uO.qflag)
+                        Info(slide, 1, ((char *)slide, "%-22s ",
+                          FnFilter1(G.filename)));
+                    switch (r) {
+                        case IZ_EF_TRUNC:
+                            Info(slide, 1, ((char *)slide,
+                              LoadFarString(TruncEAs),
+                              ebLen-(eb_cmpr_offs+EB_CMPRHEADLEN), "\n"));
+                            break;
+                        case PK_ERR:
+                            Info(slide, 1, ((char *)slide,
+                              LoadFarString(InvalidComprDataEAs)));
+                            break;
+                        case PK_MEM3:
+                        case PK_MEM4:
+                            Info(slide, 1, ((char *)slide,
+                              LoadFarString(NotEnoughMemEAs)));
+                            break;
+                        default:
+                            if ((r & 0xff) != PK_ERR)
+                                Info(slide, 1, ((char *)slide,
+                                  LoadFarString(UnknErrorEAs)));
+                            else {
+                                ush m = (ush)(r >> 8);
+                                if (m == DEFLATED)            /* GRR KLUDGE! */
+                                    Info(slide, 1, ((char *)slide,
+                                      LoadFarString(BadCRC_EAs)));
+                                else
+                                    Info(slide, 1, ((char *)slide,
+                                      LoadFarString(UnknComprMethodEAs), m));
+                            }
+                            break;
+                    }
+                    return r;
+                }
+                break;
+
+            case EF_NTSD:
+                Trace((stderr, "ebID: %i / ebLen: %u\n", ebID, ebLen));
+                r = ebLen < EB_NTSD_L_LEN ? IZ_EF_TRUNC :
+                    ((ef[EB_HEADSIZE+EB_NTSD_VERSION] > EB_NTSD_MAX_VER) ?
+                     (PK_WARN | 0x4000) :
+                     test_compr_eb(__G__ ef, ebLen, EB_NTSD_L_LEN, TEST_NTSD));
+                if (r != PK_OK) {
+                    if (uO.qflag)
+                        Info(slide, 1, ((char *)slide, "%-22s ",
+                          FnFilter1(G.filename)));
+                    switch (r) {
+                        case IZ_EF_TRUNC:
+                            Info(slide, 1, ((char *)slide,
+                              LoadFarString(TruncNTSD),
+                              ebLen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), "\n"));
+                            break;
+#if (defined(WIN32) && defined(NTSD_EAS))
+                        case PK_WARN:
+                            Info(slide, 1, ((char *)slide,
+                              LoadFarString(InvalidSecurityEAs)));
+                            break;
+#endif
+                        case PK_ERR:
+                            Info(slide, 1, ((char *)slide,
+                              LoadFarString(InvalidComprDataEAs)));
+                            break;
+                        case PK_MEM3:
+                        case PK_MEM4:
+                            Info(slide, 1, ((char *)slide,
+                              LoadFarString(NotEnoughMemEAs)));
+                            break;
+                        case (PK_WARN | 0x4000):
+                            Info(slide, 1, ((char *)slide,
+                              LoadFarString(UnsuppNTSDVersEAs),
+                              (int)ef[EB_HEADSIZE+EB_NTSD_VERSION]));
+                            r = PK_WARN;
+                            break;
+                        default:
+                            if ((r & 0xff) != PK_ERR)
+                                Info(slide, 1, ((char *)slide,
+                                  LoadFarString(UnknErrorEAs)));
+                            else {
+                                ush m = (ush)(r >> 8);
+                                if (m == DEFLATED)            /* GRR KLUDGE! */
+                                    Info(slide, 1, ((char *)slide,
+                                      LoadFarString(BadCRC_EAs)));
+                                else
+                                    Info(slide, 1, ((char *)slide,
+                                      LoadFarString(UnknComprMethodEAs), m));
+                            }
+                            break;
+                    }
+                    return r;
+                }
+                break;
+            case EF_PKVMS:
+            case EF_PKW32:
+            case EF_PKUNIX:
+            case EF_ASIUNIX:
+            case EF_IZVMS:
+            case EF_IZUNIX:
+            case EF_VMCMS:
+            case EF_MVS:
+            case EF_SPARK:
+            case EF_AV:
+            default:
+                break;
+        }
+        ef_len -= (ebLen + EB_HEADSIZE);
+        ef += (ebLen + EB_HEADSIZE);
+    }
+
+    if (!uO.qflag)
+        Info(slide, 0, ((char *)slide, " OK\n"));
+
+    return PK_COOL;
+
+} /* end function TestExtraField() */
+
+
+
+
+
+/******************************/
+/*  Function test_compr_eb()  */
+/******************************/
+
+#ifdef PROTO
+static int test_compr_eb(
+    __GPRO__
+    uch *eb,
+    unsigned eb_size,
+    unsigned compr_offset,
+    int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size,
+                          uch *eb_ucptr, ulg eb_ucsize))
+#else /* !PROTO */
+static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata)
+    __GDEF
+    uch *eb;
+    unsigned eb_size;
+    unsigned compr_offset;
+    int (*test_uc_ebdata)();
+#endif /* ?PROTO */
+{
+    ulg eb_ucsize;
+    uch *eb_ucptr;
+    int r;
+
+    if (compr_offset < 4)                /* field is not compressed: */
+        return PK_OK;                    /* do nothing and signal OK */
+
+    if ((eb_size < (EB_UCSIZE_P + 4)) ||
+        ((eb_ucsize = makelong(eb+(EB_HEADSIZE+EB_UCSIZE_P))) > 0L &&
+         eb_size <= (compr_offset + EB_CMPRHEADLEN)))
+        return IZ_EF_TRUNC;               /* no compressed data! */
+
+    if ((eb_ucptr = (uch *)malloc((extent)eb_ucsize)) == (uch *)NULL)
+        return PK_MEM4;
+
+    r = memextract(__G__ eb_ucptr, eb_ucsize,
+                   eb + (EB_HEADSIZE + compr_offset),
+                   (ulg)(eb_size - compr_offset));
+
+    if (r == PK_OK && test_uc_ebdata != NULL)
+        r = (*test_uc_ebdata)(__G__ eb, eb_size, eb_ucptr, eb_ucsize);
+
+    free(eb_ucptr);
+    return r;
+
+} /* end function test_compr_eb() */
+
+#endif /* !SFX */
+
+
+
+
+
+/***************************/
+/*  Function memextract()  */
+/***************************/
+
+int memextract(__G__ tgt, tgtsize, src, srcsize)  /* extract compressed */
+    __GDEF                                        /*  extra field block; */
+    uch *tgt, *src;                               /*  return PK-type error */
+    ulg tgtsize, srcsize;                         /*  level */
+{
+    long old_csize=G.csize;
+    uch *old_inptr=G.inptr;
+    int  old_incnt=G.incnt;
+    int  r, error=PK_OK;
+    ush  method;
+    ulg  extra_field_crc;
+
+
+    method = makeword(src);
+    extra_field_crc = makelong(src+2);
+
+    /* compressed extra field exists completely in memory at this location: */
+    G.inptr = src + 2 + 4;      /* method and extra_field_crc */
+    G.incnt = (int)(G.csize = (long)(srcsize - (2 + 4)));
+    G.mem_mode = TRUE;
+    G.outbufptr = tgt;
+    G.outsize = tgtsize;
+
+    switch (method) {
+        case STORED:
+            memcpy((char *)tgt, (char *)G.inptr, (extent)G.incnt);
+            G.outcnt = G.csize;   /* for CRC calculation */
+            break;
+        case DEFLATED:
+            G.outcnt = 0L;
+            if ((r = UZinflate(__G)) != 0) {
+                if (!uO.tflag)
+                    Info(slide, 0x401, ((char *)slide,
+                      LoadFarStringSmall(ErrUnzipNoFile), r == 3?
+                      LoadFarString(NotEnoughMem) :
+                      LoadFarString(InvalidComprData),
+                      LoadFarStringSmall2(Inflate)));
+                error = (r == 3)? PK_MEM3 : PK_ERR;
+            }
+            if (G.outcnt == 0L)   /* inflate's final FLUSH sets outcnt */
+                break;
+            break;
+        default:
+            if (uO.tflag)
+                error = PK_ERR | ((int)method << 8);
+            else {
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(UnsupportedExtraField), method));
+                error = PK_ERR;  /* GRR:  should be passed on up via SetEAs() */
+            }
+            break;
+    }
+
+    G.inptr = old_inptr;
+    G.incnt = old_incnt;
+    G.csize = old_csize;
+    G.mem_mode = FALSE;
+
+    if (!error) {
+        register ulg crcval = crc32(CRCVAL_INITIAL, tgt, (extent)G.outcnt);
+
+        if (crcval != extra_field_crc) {
+            if (uO.tflag)
+                error = PK_ERR | (DEFLATED << 8);  /* kludge for now */
+            else {
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(BadExtraFieldCRC), G.zipfn, crcval,
+                  extra_field_crc));
+                error = PK_ERR;
+            }
+        }
+    }
+    return error;
+
+} /* end function memextract() */
+
+
+
+
+
+/*************************/
+/*  Function memflush()  */
+/*************************/
+
+int memflush(__G__ rawbuf, size)
+    __GDEF
+    uch *rawbuf;
+    ulg size;
+{
+    if (size > G.outsize)
+        return 50;   /* more data than output buffer can hold */
+
+    memcpy((char *)G.outbufptr, (char *)rawbuf, (extent)size);
+    G.outbufptr += (unsigned int)size;
+    G.outsize -= size;
+    G.outcnt += size;
+
+    return 0;
+
+} /* end function memflush() */
+
+
+
+
+
+/*************************/
+/*  Function fnfilter()  */        /* here instead of in list.c for SFX */
+/*************************/
+
+char *fnfilter(raw, space)         /* convert name to safely printable form */
+    ZCONST char *raw;
+    uch *space;
+{
+#ifndef NATIVE   /* ASCII:  filter ANSI escape codes, etc. */
+    uch *r=(uch *)raw, *s=space;
+
+    while (*r) {
+#ifdef QDOS
+        if (qlflag & 2) {
+            if (*r == '/' || *r == '.') {
+                ++r;
+                *s++ = '_';
+                continue;
+            }
+        } else
+#endif
+        if (*r < 32)
+            *s++ = '^', *s++ = (uch)(64 + *r++);
+        else
+            *s++ = *r++;
+    }
+    *s = 0;
+
+#ifdef WINDLL
+    INTERN_TO_ISO((char *)space, (char *)space);  /* translate to ANSI */
+#else
+#ifdef WIN32
+    /* Win9x console always uses OEM character coding, and
+       WinNT console is set to OEM charset by default, too */
+    INTERN_TO_OEM((char *)space, (char *)space);
+#endif /* WIN32 */
+#endif /* ?WINDLL */
+
+    return (char *)space;
+
+#else /* NATIVE:  EBCDIC or whatever */
+    return (char *)raw;
+#endif
+
+} /* end function fnfilter() */
+
+
+
+
+
+#ifdef SET_DIR_ATTRIB
+/* must sort saved directories so can set perms from bottom up */
+
+/************************/
+/*  Function dircomp()  */
+/************************/
+
+static int dircomp(a, b)   /* used by qsort(); swiped from Zip */
+    ZCONST zvoid *a, *b;
+{
+    /* order is significant:  this sorts in reverse order (deepest first) */
+    return strcmp((*(dirtime **)b)->fn, (*(dirtime **)a)->fn);
+ /* return namecmp((*(dirtime **)b)->fn, (*(dirtime **)a)->fn); */
+}
+
+
+
+#if 0   /* not used in Unix, but maybe for future OSes? */
+
+/************************/
+/*  Function namecmp()  */
+/************************/
+
+static int namecmp(s1, s2)   /* [not] used by dircomp(); swiped from Zip */
+    ZCONST char *s1, *s2;
+{
+    int d;
+
+    for (;;) {
+        d = (int)(uch)case_map(*s1)
+          - (int)(uch)case_map(*s2);
+
+        if (d || *s1 == 0 || *s2 == 0)
+            return d;
+
+        s1++;
+        s2++;
+    }
+}
+
+#endif /* 0 */
+#endif /* SET_DIR_ATTRIB */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/fileio.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,2189 @@
+/*---------------------------------------------------------------------------
+
+  fileio.c
+
+  This file contains routines for doing direct but relatively generic input/
+  output, file-related sorts of things, plus some miscellaneous stuff.  Most
+  of the stuff has to do with opening, closing, reading and/or writing files.
+
+  Contains:  open_input_file()
+             open_outfile()           (non-VMS, non-AOS/VS, non-CMS_MVS)
+             undefer_input()
+             defer_leftover_input()
+             readbuf()
+             readbyte()
+             fillinbuf()
+             flush()                  (non-VMS)
+             disk_error()             (non-VMS)
+             UzpMessagePrnt()
+             UzpMessageNull()         (DLL only)
+             UzpInput()
+             UzpMorePause()
+             UzpPassword()            (non-WINDLL)
+             handler()
+             dos_to_unix_time()       (non-VMS, non-VM/CMS, non-MVS)
+             check_for_newer()        (non-VMS, non-OS/2, non-VM/CMS, non-MVS)
+             do_string()
+             makeword()
+             makelong()
+             str2iso()                (CRYPT && NEED_STR2ISO, only)
+             str2oem()                (CRYPT && NEED_STR2OEM, only)
+             memset()                 (ZMEM only)
+             memcpy()                 (ZMEM only)
+             zstrnicmp()
+             zstat()                  (REGULUS only)
+             fLoadFarString()         (SMALL_MEM only)
+             fLoadFarStringSmall()    (SMALL_MEM only)
+             fLoadFarStringSmall2()   (SMALL_MEM only)
+             zfstrcpy()               (SMALL_MEM only)
+
+  ---------------------------------------------------------------------------*/
+
+
+#define FILEIO_C
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#ifdef WINDLL
+#  include "windll/windll.h"
+#  include <setjmp.h>
+#endif
+#include "crypt.h"
+#include "ttyio.h"
+
+off_t acelseek(off_t offset, int whence);
+int aceread(void *buf, size_t count);
+int aceopen(const char *path, int flags);
+int aceclose(int fd);
+int acesize(void);
+int acetell(int fd);
+char *replacestr(char *str1, char *str2, char *str3);
+
+/* setup of codepage conversion for decryption passwords */
+#if CRYPT
+#  if (defined(CRYP_USES_ISO2OEM) && !defined(IZ_ISO2OEM_ARRAY))
+#    define IZ_ISO2OEM_ARRAY            /* pull in iso2oem[] table */
+#  endif
+#  if (defined(CRYP_USES_OEM2ISO) && !defined(IZ_OEM2ISO_ARRAY))
+#    define IZ_OEM2ISO_ARRAY            /* pull in oem2iso[] table */
+#  endif
+#endif
+#include "ebcdic.h"   /* definition/initialization of ebcdic[] */
+
+
+/*
+   Note: Under Windows, the maximum size of the buffer that can be used
+   with any of the *printf calls is 16,384, so win_fprintf was used to
+   feed the fprintf clone no more than 16K chunks at a time. This should
+   be valid for anything up to 64K (and probably beyond, assuming your
+   buffers are that big).
+*/
+#ifdef WINDLL
+#  define Write_Error(buf,len,strm) \
+   (win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len))
+#else /* !WINDLL */
+#  ifdef USE_FWRITE
+#    define Write_Error(buf,len,strm) \
+     ((extent)fwrite((char *)(buf),1,(extent)(len),strm) != (extent)(len))
+#  else
+#    define Write_Error(buf,len,strm) \
+     ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len))
+#  endif
+#endif /* ?WINDLL */
+
+int WriteError(char *buf, int len, FILE *fp)
+{
+	extern char *image_data;
+	extern int get_image, image_size;
+
+	if(get_image)
+	{
+		char *tmp = malloc(image_size+len+1);
+		if(image_size && image_data)
+		{
+			memcpy(tmp, image_data, image_size);
+			free(image_data);
+		}
+		image_data = tmp;
+
+		memcpy(&image_data[image_size], buf, len);
+		image_size+=len;
+		image_data[image_size] = '\0';
+		return 0;
+	}
+	return Write_Error(buf, len, fp);
+}
+
+static int disk_error OF((__GPRO));
+
+
+/****************************/
+/* Strings used in fileio.c */
+/****************************/
+
+#if (defined(UNIX) || defined(DOS_FLX_OS2_W32) || defined(__BEOS__))
+   static ZCONST char Far CannotDeleteOldFile[] =
+     "error:  cannot delete old %s\n";
+#ifdef UNIXBACKUP
+   static ZCONST char Far CannotRenameOldFile[] =
+     "error:  cannot rename old %s\n";
+   static ZCONST char Far BackupSuffix[] = "~";
+#endif
+#endif /* UNIX || DOS_FLX_OS2_W32 || __BEOS__ */
+
+static ZCONST char Far CannotOpenZipfile[] =
+  "error:  cannot open zipfile [ %s ]\n";
+#if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
+   static ZCONST char Far CannotCreateFile[] = "error:  cannot create %s\n";
+#endif
+#ifdef NOVELL_BUG_FAILSAFE
+   static ZCONST char Far NovellBug[] =
+     "error:  %s: stat() says does not exist, but fopen() found anyway\n";
+#endif
+static ZCONST char Far ReadError[] = "error:  zipfile read error\n";
+static ZCONST char Far FilenameTooLongTrunc[] =
+  "warning:  filename too long--truncating.\n";
+static ZCONST char Far ExtraFieldTooLong[] =
+  "warning:  extra field too long (%d).  Ignoring...\n";
+
+#ifdef WINDLL
+   static ZCONST char Far DiskFullQuery[] =
+     "%s:  write error (disk full?).\n";
+#else
+   static ZCONST char Far DiskFullQuery[] =
+     "%s:  write error (disk full?).  Continue? (y/n/^C) ";
+   static ZCONST char Far ZipfileCorrupt[] =
+     "error:  zipfile probably corrupt (%s)\n";
+#  ifdef SYMLINKS
+     static ZCONST char Far FileIsSymLink[] =
+       "%s exists and is a symbolic link%s.\n";
+#  endif
+#  ifdef MORE
+     static ZCONST char Far MorePrompt[] = "--More--(%lu)";
+#  endif
+   static ZCONST char Far QuitPrompt[] =
+     "--- Press `Q' to quit, or any other key to continue ---";
+   static ZCONST char Far HidePrompt[] = /* "\r                       \r"; */
+     "\r                                                         \r";
+#  if CRYPT
+#    ifdef MACOS
+       /* SPC: are names on MacOS REALLY so much longer than elsewhere ??? */
+       static ZCONST char Far PasswPrompt[] = "[%s]\n %s password: ";
+#    else
+       static ZCONST char Far PasswPrompt[] = "[%s] %s password: ";
+#    endif
+     static ZCONST char Far PasswPrompt2[] = "Enter password: ";
+     static ZCONST char Far PasswRetry[] = "password incorrect--reenter: ";
+#  endif /* CRYPT */
+#endif /* !WINDLL */
+
+
+
+
+
+/******************************/
+/* Function open_input_file() */
+/******************************/
+
+int open_input_file(__G)    /* return 1 if open failed */
+    __GDEF
+{
+    /*
+     *  open the zipfile for reading and in BINARY mode to prevent cr/lf
+     *  translation, which would corrupt the bitstreams
+     */
+
+#if (defined(UNIX) || defined(TOPS20) || defined(AOS_VS) || defined(__BEOS__))
+    G.zipfd = aceopen(G.zipfn, O_RDONLY);
+#else /* !(UNIX || TOPS20 || AOS_VS || __BEOS__) */
+#ifdef VMS
+    G.zipfd = open(G.zipfn, O_RDONLY, 0, "ctx=stm");
+#else /* !VMS */
+#ifdef MACOS
+    G.zipfd = aceopen(G.zipfn, 0);
+#else /* !MACOS */
+#ifdef RISCOS
+    G.zipfd = fopen(G.zipfn, "rb");
+#else /* !RISCOS */
+#ifdef CMS_MVS
+    G.zipfd = vmmvs_open_infile(__G);
+#else /* !CMS_MVS */
+    G.zipfd = aceopen(G.zipfn, O_RDONLY | O_BINARY);
+#endif /* ?CMS_MVS */
+#endif /* ?RISCOS */
+#endif /* ?MACOS */
+#endif /* ?VMS */
+#endif /* ?(UNIX || TOPS20 || AOS_VS || __BEOS__) */
+
+#ifdef USE_STRM_INPUT
+    if (G.zipfd == NULL)
+#else
+    /* if (G.zipfd < 0) */  /* no good for Windows CE port */
+    if (G.zipfd == -1)
+#endif
+    {
+        Info(slide, 0x401, ((char *)slide, LoadFarString(CannotOpenZipfile),
+          G.zipfn));
+        return 1;
+    }
+    return 0;
+
+} /* end function open_input_file() */
+
+
+
+
+#if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
+
+/***************************/
+/* Function open_outfile() */
+/***************************/
+
+int open_outfile(__G)         /* return 1 if fail */
+    __GDEF
+{
+	extern int get_image;
+
+	if(get_image)
+		return 0;
+
+#ifdef DLL
+    if (G.redirect_data)
+        return (redirect_outfile(__G) == FALSE);
+#endif
+#ifdef QDOS
+    QFilename(__G__ G.filename);
+#endif
+#if (defined(DOS_FLX_OS2_W32) || defined(UNIX) || defined(__BEOS__))
+#ifdef BORLAND_STAT_BUG
+    /* Borland 5.0's stat() barfs if the filename has no extension and the
+     * file doesn't exist. */
+    if (access(G.filename, 0) == -1) {
+        FILE *tmp = fopen(G.filename, "wb+");
+
+        /* file doesn't exist, so create a dummy file to keep stat() from
+         * failing (will be over-written anyway) */
+        fputc('0', tmp);  /* just to have something in the file */
+        fclose(tmp);
+    }
+#endif /* BORLAND_STAT_BUG */
+#ifdef SYMLINKS
+    if (SSTAT(G.filename, &G.statbuf) == 0 || lstat(G.filename,&G.statbuf) == 0)
+#else
+    if (SSTAT(G.filename, &G.statbuf) == 0)
+#endif /* ?SYMLINKS */
+    {
+        Trace((stderr, "open_outfile:  stat(%s) returns 0:  file exists\n",
+          FnFilter1(G.filename)));
+#ifdef UNIXBACKUP
+        if (uO.B_flag) {    /* do backup */
+            char *tname;
+            int blen, flen, tlen;
+
+            blen = strlen(BackupSuffix);
+            flen = strlen(G.filename);
+            tlen = flen + blen + 1;
+            if (tlen >= FILNAMSIZ) {   /* in case name is too long, truncate */
+                tname = (char *)malloc(FILNAMSIZ);
+                if (tname == NULL)
+                    return 1;                 /* in case we run out of space */
+                tlen = FILNAMSIZ - 1 - blen;
+                strcpy(tname, G.filename);    /* make backup name */
+                tname[tlen] = '\0';
+            } else {
+                tname = (char *)malloc(tlen);
+                if (tname == NULL)
+                    return 1;                 /* in case we run out of space */
+                strcpy(tname, G.filename);    /* make backup name */
+            }
+            strcpy(tname+flen, BackupSuffix);
+
+            /* GRR:  should check if backup file exists, apply -n/-o to that */
+            if (rename(G.filename, tname) < 0) {   /* move file */
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(CannotRenameOldFile), FnFilter1(G.filename)));
+                free(tname);
+                return 1;
+            }
+            free(tname);
+        } else
+#endif /* UNIXBACKUP */
+#ifdef DOS_FLX_OS2_W32
+        if (!(G.statbuf.st_mode & S_IWRITE)) {
+            Trace((stderr, "open_outfile:  existing file %s is read-only\n",
+              FnFilter1(G.filename)));
+            chmod(G.filename, S_IREAD | S_IWRITE);
+            Trace((stderr, "open_outfile:  %s now writable\n",
+              FnFilter1(G.filename)));
+        }
+#endif /* DOS_FLX_OS2_W32 */
+        if (unlink(G.filename) != 0) {
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(CannotDeleteOldFile), FnFilter1(G.filename)));
+            return 1;
+        }
+        Trace((stderr, "open_outfile:  %s now deleted\n",
+          FnFilter1(G.filename)));
+    }
+#endif /* DOS_FLX_OS2_W32 || UNIX || __BEOS__ */
+#ifdef RISCOS
+    if (SWI_OS_File_7(G.filename,0xDEADDEAD,0xDEADDEAD,G.lrec.ucsize)!=NULL) {
+        Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
+          FnFilter1(G.filename)));
+        return 1;
+    }
+#endif /* RISCOS */
+#ifdef TOPS20
+    char *tfilnam;
+
+    if ((tfilnam = (char *)malloc(2*strlen(G.filename)+1)) == (char *)NULL)
+        return 1;
+    strcpy(tfilnam, G.filename);
+    upper(tfilnam);
+    enquote(tfilnam);
+    if ((G.outfile = fopen(tfilnam, FOPW)) == (FILE *)NULL) {
+        Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
+          tfilnam));
+        free(tfilnam);
+        return 1;
+    }
+    free(tfilnam);
+#else /* !TOPS20 */
+#ifdef MTS
+    if (uO.aflag)
+        G.outfile = fopen(G.filename, FOPWT);
+    else
+        G.outfile = fopen(G.filename, FOPW);
+    if (G.outfile == (FILE *)NULL) {
+        Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
+          FnFilter1(G.filename)));
+        return 1;
+    }
+#else /* !MTS */
+#ifdef TANDEM
+    if (SSTAT(G.filename, &G.statbuf) == 0) {
+        Trace((stderr, "open_outfile:  stat(%s) returns 0 (file exists)\n",
+          FnFilter1(G.filename)));
+        if (unlink(G.filename) != 0) {
+            Trace((stderr, "open_outfile:  existing file %s is read-only\n",
+              FnFilter1(G.filename)));
+            chmod(G.filename, S_IRUSR | S_IWUSR);
+            Trace((stderr, "open_outfile:  %s now writable\n",
+              FnFilter1(G.filename)));
+            if (unlink(G.filename) != 0)
+                return 1;
+        }
+        Trace((stderr, "open_outfile:  %s now deleted\n",
+          FnFilter1(G.filename)));
+    }
+    if (G.pInfo->textmode)
+        G.outfile = fopen(G.filename, FOPWT);
+    else
+        G.outfile = fopen(G.filename, FOPW);
+    if (G.outfile == (FILE *)NULL) {
+        Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
+          FnFilter1(G.filename)));
+        return 1;
+    }
+#else /* !TANDEM */
+#ifdef DEBUG
+    Info(slide, 1, ((char *)slide,
+      "open_outfile:  doing fopen(%s) for reading\n", FnFilter1(G.filename)));
+    if ((G.outfile = fopen(G.filename, FOPR)) == (FILE *)NULL)
+        Info(slide, 1, ((char *)slide,
+          "open_outfile:  fopen(%s) for reading failed:  does not exist\n",
+          FnFilter1(G.filename)));
+    else {
+        Info(slide, 1, ((char *)slide,
+          "open_outfile:  fopen(%s) for reading succeeded:  file exists\n",
+          FnFilter1(G.filename)));
+        fclose(G.outfile);
+    }
+#endif /* DEBUG */
+#ifdef NOVELL_BUG_FAILSAFE
+    if (G.dne && ((G.outfile = fopen(G.filename, FOPR)) != (FILE *)NULL)) {
+        Info(slide, 0x401, ((char *)slide, LoadFarString(NovellBug),
+          FnFilter1(G.filename)));
+        fclose(G.outfile);
+        return 1;   /* with "./" fix in checkdir(), should never reach here */
+    }
+#endif /* NOVELL_BUG_FAILSAFE */
+    Trace((stderr, "open_outfile:  doing fopen(%s) for writing\n",
+      FnFilter1(G.filename)));
+    if ((G.outfile = fopen(G.filename, FOPW)) == (FILE *)NULL) {
+        Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile),
+          FnFilter1(G.filename)));
+        return 1;
+    }
+    Trace((stderr, "open_outfile:  fopen(%s) for writing succeeded\n",
+      FnFilter1(G.filename)));
+#endif /* !TANDEM */
+#endif /* !MTS */
+#endif /* !TOPS20 */
+
+#ifdef USE_FWRITE
+#ifdef DOS_OS2_W32
+    /* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE):  bogus */
+    setbuf(G.outfile, (char *)NULL);   /* make output unbuffered */
+#else /* !DOS_OS2_W32 */
+#ifndef RISCOS
+#ifdef _IOFBF  /* make output fully buffered (works just about like write()) */
+    setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE);
+#else
+    setbuf(G.outfile, (char *)slide);
+#endif
+#endif /* !RISCOS */
+#endif /* ?DOS_OS2_W32 */
+#endif /* USE_FWRITE */
+    return 0;
+
+} /* end function open_outfile() */
+
+#endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */
+
+
+
+
+
+/*
+ * These functions allow NEXTBYTE to function without needing two bounds
+ * checks.  Call defer_leftover_input() if you ever have filled G.inbuf
+ * by some means other than readbyte(), and you then want to start using
+ * NEXTBYTE.  When going back to processing bytes without NEXTBYTE, call
+ * undefer_input().  For example, extract_or_test_member brackets its
+ * central section that does the decompression with these two functions.
+ * If you need to check the number of bytes remaining in the current
+ * file while using NEXTBYTE, check (G.csize + G.incnt), not G.csize.
+ */
+
+/****************************/
+/* function undefer_input() */
+/****************************/
+
+void undefer_input(__G)
+    __GDEF
+{
+    if (G.incnt > 0)
+        G.csize += G.incnt;
+    if (G.incnt_leftover > 0) {
+        /* We know that "(G.csize < MAXINT)" so we can cast G.csize to int:
+         * This condition was checked when G.incnt_leftover was set > 0 in
+         * defer_leftover_input(), and it is NOT allowed to touch G.csize
+         * before calling undefer_input() when (G.incnt_leftover > 0)
+         * (single exception: see read_byte()'s  "G.csize <= 0" handling) !!
+         */
+        G.incnt = G.incnt_leftover + (int)G.csize;
+        G.inptr = G.inptr_leftover - (int)G.csize;
+        G.incnt_leftover = 0;
+    } else if (G.incnt < 0)
+        G.incnt = 0;
+} /* end function undefer_input() */
+
+
+
+
+
+/***********************************/
+/* function defer_leftover_input() */
+/***********************************/
+
+void defer_leftover_input(__G)
+    __GDEF
+{
+    if ((long)G.incnt > G.csize) {
+        /* (G.csize < MAXINT), we can safely cast it to int !! */
+        if (G.csize < 0L)
+            G.csize = 0L;
+        G.inptr_leftover = G.inptr + (int)G.csize;
+        G.incnt_leftover = G.incnt - (int)G.csize;
+        G.incnt = (int)G.csize;
+    } else
+        G.incnt_leftover = 0;
+    G.csize -= G.incnt;
+} /* end function defer_leftover_input() */
+
+
+
+
+
+/**********************/
+/* Function readbuf() */
+/**********************/
+
+unsigned readbuf(__G__ buf, size)   /* return number of bytes read into buf */
+    __GDEF
+    char *buf;
+    register unsigned size;
+{
+    register unsigned count;
+    unsigned n;
+
+    n = size;
+    while (size) {
+        if (G.incnt <= 0) {
+            if ((G.incnt = aceread((char *)G.inbuf, INBUFSIZ)) == 0)
+                return (n-size);
+            else if (G.incnt < 0) {
+                /* another hack, but no real harm copying same thing twice */
+                (*G.message)((zvoid *)&G,
+                  (uch *)LoadFarString(ReadError),  /* CANNOT use slide */
+                  (ulg)strlen(LoadFarString(ReadError)), 0x401);
+                return 0;  /* discarding some data; better than lock-up */
+            }
+            /* buffer ALWAYS starts on a block boundary:  */
+            G.cur_zipfile_bufstart += INBUFSIZ;
+            G.inptr = G.inbuf;
+        }
+        count = MIN(size, (unsigned)G.incnt);
+        memcpy(buf, G.inptr, count);
+        buf += count;
+        G.inptr += count;
+        G.incnt -= count;
+        size -= count;
+    }
+    return n;
+
+} /* end function readbuf() */
+
+
+
+
+
+/***********************/
+/* Function readbyte() */
+/***********************/
+
+int readbyte(__G)   /* refill inbuf and return a byte if available, else EOF */
+    __GDEF
+{
+    if (G.mem_mode)
+        return EOF;
+    if (G.csize <= 0) {
+        G.csize--;             /* for tests done after exploding */
+        G.incnt = 0;
+        return EOF;
+    }
+    if (G.incnt <= 0) {
+        if ((G.incnt = aceread((char *)G.inbuf, INBUFSIZ)) == 0) {
+            G.incnt = 0;       /* do not allow negative value to affect stuff */
+            return EOF;
+        } else if (G.incnt < 0) {  /* "fail" (abort, retry, ...) returns this */
+            /* another hack, but no real harm copying same thing twice */
+            (*G.message)((zvoid *)&G,
+              (uch *)LoadFarString(ReadError),
+              (ulg)strlen(LoadFarString(ReadError)), 0x401);
+            echon();
+#ifdef WINDLL
+            longjmp(dll_error_return, 1);
+#else
+            DESTROYGLOBALS()
+            EXIT(PK_BADERR);    /* totally bailing; better than lock-up */
+#endif
+        }
+        G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on block bndry */
+        G.inptr = G.inbuf;
+        defer_leftover_input(__G);           /* decrements G.csize */
+    }
+
+#if CRYPT
+    if (G.pInfo->encrypted) {
+        uch *p;
+        int n;
+
+        /* This was previously set to decrypt one byte beyond G.csize, when
+         * incnt reached that far.  GRR said, "but it's required:  why?"  This
+         * was a bug in fillinbuf() -- was it also a bug here?
+         */
+        for (n = G.incnt, p = G.inptr;  n--;  p++)
+            zdecode(*p);
+    }
+#endif /* CRYPT */
+
+    --G.incnt;
+    return *G.inptr++;
+
+} /* end function readbyte() */
+
+
+
+
+
+#ifdef USE_ZLIB
+
+/************************/
+/* Function fillinbuf() */
+/************************/
+
+int fillinbuf(__G) /* like readbyte() except returns number of bytes in inbuf */
+    __GDEF
+{
+    if (G.mem_mode ||
+                  (G.incnt = aceread((char *)G.inbuf, INBUFSIZ)) <= 0)
+        return 0;
+    G.cur_zipfile_bufstart += INBUFSIZ;  /* always starts on a block boundary */
+    G.inptr = G.inbuf;
+    defer_leftover_input(__G);           /* decrements G.csize */
+
+#if CRYPT
+    if (G.pInfo->encrypted) {
+        uch *p;
+        int n;
+
+        for (n = G.incnt, p = G.inptr;  n--;  p++)
+            zdecode(*p);
+    }
+#endif /* CRYPT */
+
+    return G.incnt;
+
+} /* end function fillinbuf() */
+
+#endif /* USE_ZLIB */
+
+
+
+
+
+#ifndef VMS  /* for VMS use code in vms.c */
+
+/********************/
+/* Function flush() */   /* returns PK error codes: */
+/********************/   /* if cflag => always 0; PK_DISK if write error */
+
+int flush(__G__ rawbuf, size, unshrink)
+    __GDEF
+    uch *rawbuf;
+    ulg size;
+    int unshrink;
+{
+    register uch *p, *q;
+    uch *transbuf;
+#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
+    ulg transbufsiz;
+#endif
+    /* static int didCRlast = FALSE;    moved to globals.h */
+
+
+/*---------------------------------------------------------------------------
+    Compute the CRC first; if testing or if disk is full, that's it.
+  ---------------------------------------------------------------------------*/
+
+    G.crc32val = crc32(G.crc32val, rawbuf, (extent)size);
+
+#ifdef DLL
+    if ((G.statreportcb != NULL) &&
+        (*G.statreportcb)(__G__ UZ_ST_IN_PROGRESS, G.zipfn, G.filename, NULL))
+        return IZ_CTRLC;        /* cancel operation by user request */
+#endif
+
+    if (uO.tflag || size == 0L)  /* testing or nothing to write:  all done */
+        return PK_OK;
+
+    if (G.disk_full)
+        return PK_DISK;         /* disk already full:  ignore rest of file */
+
+/*---------------------------------------------------------------------------
+    Write the bytes rawbuf[0..size-1] to the output device, first converting
+    end-of-lines and ASCII/EBCDIC as needed.  If SMALL_MEM or MED_MEM are NOT
+    defined, outbuf is assumed to be at least as large as rawbuf and is not
+    necessarily checked for overflow.
+  ---------------------------------------------------------------------------*/
+
+    if (!G.pInfo->textmode) {   /* write raw binary data */
+        /* GRR:  note that for standard MS-DOS compilers, size argument to
+         * fwrite() can never be more than 65534, so WriteError macro will
+         * have to be rewritten if size can ever be that large.  For now,
+         * never more than 32K.  Also note that write() returns an int, which
+         * doesn't necessarily limit size to 32767 bytes if write() is used
+         * on 16-bit systems but does make it more of a pain; however, because
+         * at least MSC 5.1 has a lousy implementation of fwrite() (as does
+         * DEC Ultrix cc), write() is used anyway.
+         */
+#ifdef DLL
+        if (G.redirect_data)
+            writeToMemory(__G__ rawbuf, size);
+        else
+#endif
+        if (!uO.cflag && WriteError(rawbuf, size, G.outfile))
+            return disk_error(__G);
+        else if (uO.cflag && (*G.message)((zvoid *)&G, rawbuf, size, 0))
+            return 0;
+    } else {   /* textmode:  aflag is true */
+        if (unshrink) {
+            /* rawbuf = outbuf */
+            transbuf = G.outbuf2;
+#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
+            transbufsiz = TRANSBUFSIZ;
+#endif
+        } else {
+            /* rawbuf = slide */
+            transbuf = G.outbuf;
+#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
+            transbufsiz = OUTBUFSIZ;
+            Trace((stderr, "\ntransbufsiz = OUTBUFSIZ = %u\n", OUTBUFSIZ));
+#endif
+        }
+        if (G.newfile) {
+#ifdef VMS_TEXT_CONV
+            /* GRR: really want to check if -aa (or -aaa?) was given... */
+            if (rawbuf[1]) {       /* first line is more than 255 chars long */
+                Trace((stderr,
+      "\nfirst line of VMS `text' too long; switching to normal extraction\n"));
+                G.VMS_line_state = -1;   /* -1: don't treat as VMS text */
+            } else
+                G.VMS_line_state = 0;    /* 0: ready to read line length */
+#endif
+            G.didCRlast = FALSE;         /* no previous buffers written */
+            G.newfile = FALSE;
+        }
+
+#ifdef VMS_TEXT_CONV
+        if (G.pInfo->hostnum == VMS_ && G.extra_field && G.VMS_line_state >= 0)
+        {
+            /* GRR: really want to check for actual VMS extra field, and
+             *      ideally for variable-length record format */
+/*
+            printf("\n>>>>>> GRR:  file is VMS text and has an extra field\n");
+ */
+
+            p = rawbuf;
+            q = transbuf;
+            while(p < rawbuf+(unsigned)size) {
+                switch (G.VMS_line_state) {
+
+                    /* 0: ready to read line length */
+                    case 0:
+                        G.VMS_line_length = 0;
+                        G.VMS_line_pad = 0;
+                        if (p == rawbuf+(unsigned)size-1) {    /* last char */
+                            G.VMS_line_length = (int)((uch)(*p++));
+                            G.VMS_line_state = 1;
+                        } else {
+                            G.VMS_line_length = makeword(p);
+                            p += 2;
+                            G.VMS_line_state = 2;
+                        }
+                        if (G.VMS_line_length & 1)   /* odd */
+                            G.VMS_line_pad = 1;
+                        break;
+
+                    /* 1: read one byte of length, need second */
+                    case 1:
+                        G.VMS_line_length += ((int)((uch)(*p++)) << 8);
+                        G.VMS_line_state = 2;
+                        break;
+
+                    /* 2: ready to read VMS_line_length chars */
+                    case 2:
+                        if (G.VMS_line_length < rawbuf+(unsigned)size-p) {
+                            if (G.VMS_line_length >=
+                                transbuf+(unsigned)transbufsiz-q)
+                            {
+                                int outroom = transbuf+(unsigned)transbufsiz-q;
+
+/* GRR:  need to change this to *q++ = native(*p++); loop or something */
+                                memcpy(q, p, outroom);
+#ifdef DLL
+                                if (G.redirect_data)
+                                    writeToMemory(__G__ transbuf,
+                                      (unsigned)outroom);
+                                else
+#endif
+                                if (!uO.cflag && WriteError(transbuf,
+                                    (unsigned)outroom, G.outfile))
+                                    return disk_error(__G);
+                                else if (uO.cflag && (*G.message)((zvoid *)&G,
+                                         transbuf, (ulg)outroom, 0))
+                                    return 0;
+                                q = transbuf;
+                                p += outroom;
+                                G.VMS_line_length -= outroom;
+                                /* fall through to normal case */
+                            }
+/* GRR:  need to change this to *q++ = native(*p++); loop or something */
+                            memcpy(q, p, G.VMS_line_length);
+                            q += G.VMS_line_length;
+                            p += G.VMS_line_length;
+                            G.VMS_line_length = 0;   /* necessary?? */
+                            G.VMS_line_state = 3;
+
+                        } else {  /* remaining input is less than full line */
+                            int remaining = rawbuf+(unsigned)size-p;
+
+                            if (remaining <
+                                transbuf+(unsigned)transbufsiz-q)
+                            {
+                                int outroom = transbuf+(unsigned)transbufsiz-q;
+
+/* GRR:  need to change this to *q++ = native(*p++); loop or something */
+                                memcpy(q, p, outroom);
+#ifdef DLL
+                                if (G.redirect_data)
+                                    writeToMemory(__G__ transbuf,
+                                      (unsigned)(outroom));
+                                else
+#endif
+                                if (!uO.cflag && WriteError(transbuf,
+                                    (unsigned)outroom, G.outfile))
+                                    return disk_error(__G);
+                                else if (uO.cflag && (*G.message)((zvoid *)&G,
+                                         transbuf, (ulg)outroom, 0))
+                                    return 0;
+                                q = transbuf;
+                                p += outroom;
+                                remaining -= outroom;
+                            }
+/* GRR:  need to change this to *q++ = native(*p++); loop or something */
+                            memcpy(q, p, remaining);
+                            q += remaining;
+                            p += remaining;
+                            G.VMS_line_length -= remaining;
+                            /* no change in G.VMS_line_state */
+                        }
+                        break;
+
+                    /* 3: ready to PutNativeEOL */
+                    case 3:
+                        if (q > transbuf+(unsigned)transbufsiz-lenEOL) {
+#ifdef DLL
+                            if (G.redirect_data)
+                                writeToMemory(__G__ transbuf,
+                                  (unsigned)(q-transbuf));
+                            else
+#endif
+                            if (!uO.cflag &&
+                                WriteError(transbuf, (unsigned)(q-transbuf),
+                                  G.outfile))
+                                return disk_error(__G);
+                            else if (uO.cflag && (*G.message)((zvoid *)&G,
+                                     transbuf, (ulg)(q-transbuf), 0))
+                                return 0;
+                            q = transbuf;
+                        }
+                        PutNativeEOL
+                        if (G.VMS_line_pad)
+                            if (p < rawbuf+(unsigned)size) {
+                                ++p;
+                                G.VMS_line_state = 0;
+                            } else
+                                G.VMS_line_state = 4;
+                        else
+                            G.VMS_line_state = 0;
+                        break;
+
+                    /* 4: ready to read pad byte */
+                    case 4:
+                        ++p;
+                        G.VMS_line_state = 0;
+                        break;
+                }
+            } /* end while */
+
+        } else
+#endif /* VMS_TEXT_CONV */
+
+    /*-----------------------------------------------------------------------
+        Algorithm:  CR/LF => native; lone CR => native; lone LF => native.
+        This routine is only for non-raw-VMS, non-raw-VM/CMS files (i.e.,
+        stream-oriented files, not record-oriented).
+      -----------------------------------------------------------------------*/
+
+        /* else not VMS text */ {
+            p = rawbuf;
+            if (*p == LF && G.didCRlast)
+                ++p;
+            G.didCRlast = FALSE;
+            for (q = transbuf;  p < rawbuf+(unsigned)size;  ++p) {
+                if (*p == CR) {           /* lone CR or CR/LF: EOL either way */
+                    PutNativeEOL
+                    if (p == rawbuf+(unsigned)size-1)  /* last char in buffer */
+                        G.didCRlast = TRUE;
+                    else if (p[1] == LF)  /* get rid of accompanying LF */
+                        ++p;
+                } else if (*p == LF)      /* lone LF */
+                    PutNativeEOL
+                else
+#ifndef DOS_FLX_OS2_W32
+                if (*p != CTRLZ)          /* lose all ^Z's */
+#endif
+                    *q++ = native(*p);
+
+#if (defined(SMALL_MEM) || defined(MED_MEM))
+# if (lenEOL == 1)   /* don't check unshrink:  both buffers small but equal */
+                if (!unshrink)
+# endif
+                    /* check for danger of buffer overflow and flush */
+                    if (q > transbuf+(unsigned)transbufsiz-lenEOL) {
+                        Trace((stderr,
+                          "p - rawbuf = %u   q-transbuf = %u   size = %lu\n",
+                          (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size));
+                        if (!uO.cflag && WriteError(transbuf,
+                            (unsigned)(q-transbuf), G.outfile))
+                            return disk_error(__G);
+                        else if (uO.cflag && (*G.message)((zvoid *)&G,
+                                 transbuf, (ulg)(q-transbuf), 0))
+                            return 0;
+                        q = transbuf;
+                        continue;
+                    }
+#endif /* SMALL_MEM || MED_MEM */
+            }
+        }
+
+    /*-----------------------------------------------------------------------
+        Done translating:  write whatever we've got to file (or screen).
+      -----------------------------------------------------------------------*/
+
+        Trace((stderr, "p - rawbuf = %u   q-transbuf = %u   size = %lu\n",
+          (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size));
+        if (q > transbuf) {
+#ifdef DLL
+            if (G.redirect_data)
+                writeToMemory(__G__ transbuf, (unsigned)(q-transbuf));
+            else
+#endif
+            if (!uO.cflag && WriteError(transbuf, (unsigned)(q-transbuf),
+                G.outfile))
+                return disk_error(__G);
+            else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf,
+                (ulg)(q-transbuf), 0))
+                return 0;
+        }
+    }
+
+    return 0;
+
+} /* end function flush() */
+
+
+
+
+
+/*************************/
+/* Function disk_error() */
+/*************************/
+
+static int disk_error(__G)
+    __GDEF
+{
+    /* OK to use slide[] here because this file is finished regardless */
+    Info(slide, 0x4a1, ((char *)slide, LoadFarString(DiskFullQuery),
+      FnFilter1(G.filename)));
+
+#ifndef WINDLL
+    fgets(G.answerbuf, 9, stdin);
+    if (*G.answerbuf == 'y')   /* stop writing to this file */
+        G.disk_full = 1;       /*  (outfile bad?), but new OK */
+    else
+#endif
+        G.disk_full = 2;       /* no:  exit program */
+
+    return PK_DISK;
+
+} /* end function disk_error() */
+
+#endif /* !VMS */
+
+
+
+
+
+/*****************************/
+/* Function UzpMessagePrnt() */
+/*****************************/
+
+int UZ_EXP UzpMessagePrnt(pG, buf, size, flag)
+    zvoid *pG;   /* globals struct:  always passed */
+    uch *buf;    /* preformatted string to be printed */
+    ulg size;    /* length of string (may include nulls) */
+    int flag;    /* flag bits */
+{
+    /* IMPORTANT NOTE:
+     *    The name of the first parameter of UzpMessagePrnt(), which passes
+     *    the "Uz_Globs" address, >>> MUST <<< be identical to the string
+     *    expansion of the __G__ macro in the REENTRANT case (see globals.h).
+     *    This name identity is mandatory for the LoadFarString() macro
+     *    (in the SMALL_MEM case) !!!
+     */
+    int error;
+    uch *q=buf, *endbuf=buf+(unsigned)size;
+#ifdef MORE
+    uch *p=buf-1;
+#endif
+    FILE *outfp;
+
+
+/*---------------------------------------------------------------------------
+    These tests are here to allow fine-tuning of UnZip's output messages,
+    but none of them will do anything without setting the appropriate bit
+    in the flag argument of every Info() statement which is to be turned
+    *off*.  That is, all messages are currently turned on for all ports.
+    To turn off *all* messages, use the UzpMessageNull() function instead
+    of this one.
+  ---------------------------------------------------------------------------*/
+
+#if (defined(OS2) && defined(DLL))
+    if (MSG_NO_DLL2(flag))  /* if OS/2 DLL bit is set, do NOT print this msg */
+        return 0;
+#endif
+#ifdef WINDLL
+    if (MSG_NO_WDLL(flag))
+        return 0;
+#endif
+#ifdef WINDLL
+    if (MSG_NO_WGUI(flag))
+        return 0;
+#endif
+/*
+#ifdef ACORN_GUI
+    if (MSG_NO_AGUI(flag))
+        return 0;
+#endif
+ */
+#ifdef DLL                 /* don't display message if data is redirected */
+    if (((Uz_Globs *)pG)->redirect_data &&
+        !((Uz_Globs *)pG)->redirect_text)
+        return 0;
+#endif
+
+    if (MSG_STDERR(flag) && !((Uz_Globs *)pG)->UzO.tflag)
+        outfp = (FILE *)stderr;
+    else
+        outfp = (FILE *)stdout;
+
+#ifdef QUERY_TRNEWLN
+    /* some systems require termination of query prompts with '\n' to force
+     * immediate display */
+    if (MSG_MNEWLN(flag)) {   /* assumes writable buffer (e.g., slide[]) */
+        *endbuf++ = '\n';     /*  with room for one more char at end of buf */
+        ++size;               /*  (safe assumption:  only used for four */
+    }                         /*  short queries in extract.c and fileio.c) */
+#endif
+
+    if (MSG_TNEWLN(flag)) {   /* again assumes writable buffer:  fragile... */
+        if ((!size && !((Uz_Globs *)pG)->sol) ||
+            (size && (endbuf[-1] != '\n')))
+        {
+            *endbuf++ = '\n';
+            ++size;
+        }
+    }
+
+#ifdef MORE
+    /* room for --More-- and one line of overlap: */
+    ((Uz_Globs *)pG)->height = SCREENLINES - 2;
+#endif
+
+    if (MSG_LNEWLN(flag) && !((Uz_Globs *)pG)->sol) {
+        /* not at start of line:  want newline */
+#ifdef OS2DLL
+        if (!((Uz_Globs *)pG)->redirect_text) {
+#endif
+            putc('\n', outfp);
+            fflush(outfp);
+#ifdef MORE
+            if (((Uz_Globs *)pG)->M_flag)
+            {
+                ++((Uz_Globs *)pG)->numlines;
+                if (((Uz_Globs *)pG)->numlines %
+                    ((Uz_Globs *)pG)->height == 0L)    /* GRR: fix */
+                    (*((Uz_Globs *)pG)->mpause)((zvoid *)pG,
+                      LoadFarString(MorePrompt), 1);
+            }
+#endif /* MORE */
+            if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag &&
+                !isatty(1) && isatty(2))
+            {
+                /* error output from testing redirected:  also send to stderr */
+                putc('\n', stderr);
+                fflush(stderr);
+            }
+#ifdef OS2DLL
+        } else
+           REDIRECTC('\n');
+#endif
+        ((Uz_Globs *)pG)->sol = TRUE;
+    }
+
+    /* put zipfile name, filename and/or error/warning keywords here */
+
+#ifdef MORE
+    if (((Uz_Globs *)pG)->M_flag
+#ifdef OS2DLL
+         && !((Uz_Globs *)pG)->redirect_text
+#endif
+                                                 )
+    {
+        while (++p < endbuf) {
+            if (*p == '\n') {
+                ++((Uz_Globs *)pG)->numlines;
+                if (((Uz_Globs *)pG)->numlines %
+                    ((Uz_Globs *)pG)->height == 0L)    /* GRR: fix */
+                {
+                    if ((error = WriteError(q, p-q+1, outfp)) != 0)
+                        return error;
+                    fflush(outfp);
+                    ((Uz_Globs *)pG)->sol = TRUE;
+                    q = p + 1;
+                    (*((Uz_Globs *)pG)->mpause)((zvoid *)pG,
+                      LoadFarString(MorePrompt), 1);
+                }
+            }
+        } /* end while */
+        size = (ulg)(p - q);   /* remaining text */
+    }
+#endif /* MORE */
+
+    if (size) {
+#ifdef OS2DLL
+        if (!((Uz_Globs *)pG)->redirect_text) {
+#endif
+            if ((error = WriteError(q, size, outfp)) != 0)
+                return error;
+            fflush(outfp);
+            if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag &&
+                !isatty(1) && isatty(2))
+            {
+                /* error output from testing redirected:  also send to stderr */
+                if ((error = WriteError(q, size, stderr)) != 0)
+                    return error;
+                fflush(stderr);
+            }
+#ifdef OS2DLL
+        } else {                /* GRR:  this is ugly:  hide with macro */
+            if ((error = REDIRECTPRINT(q, size)) != 0)
+                return error;
+        }
+#endif
+        ((Uz_Globs *)pG)->sol = (endbuf[-1] == '\n');
+    }
+    return 0;
+
+} /* end function UzpMessagePrnt() */
+
+
+
+
+
+#ifdef DLL
+
+/*****************************/
+/* Function UzpMessageNull() */  /* convenience routine for no output at all */
+/*****************************/
+
+int UZ_EXP UzpMessageNull(pG, buf, size, flag)
+    zvoid *pG;    /* globals struct:  always passed */
+    uch *buf;     /* preformatted string to be printed */
+    ulg size;     /* length of string (may include nulls) */
+    int flag;     /* flag bits */
+{
+    return 0;
+
+} /* end function UzpMessageNull() */
+
+#endif /* DLL */
+
+
+
+
+
+/***********************/
+/* Function UzpInput() */   /* GRR:  this is a placeholder for now */
+/***********************/
+
+int UZ_EXP UzpInput(pG, buf, size, flag)
+    zvoid *pG;    /* globals struct:  always passed */
+    uch *buf;     /* preformatted string to be printed */
+    int *size;    /* (address of) size of buf and of returned string */
+    int flag;     /* flag bits (bit 0: no echo) */
+{
+    /* tell picky compilers to shut up about "unused variable" warnings */
+    pG = pG; buf = buf; flag = flag;
+
+    *size = 0;
+    return 0;
+
+} /* end function UzpInput() */
+
+
+
+
+
+#if (!defined(WINDLL) && !defined(MACOS))
+
+/***************************/
+/* Function UzpMorePause() */
+/***************************/
+
+void UZ_EXP UzpMorePause(pG, prompt, flag)
+    zvoid *pG;            /* globals struct:  always passed */
+    ZCONST char *prompt;  /* "--More--" prompt */
+    int flag;             /* 0 = any char OK; 1 = accept only '\n', ' ', q */
+	{
+#if 0
+    uch c;
+
+/*---------------------------------------------------------------------------
+    Print a prompt and wait for the user to press a key, then erase prompt
+    if possible.
+  ---------------------------------------------------------------------------*/
+
+    if (!((Uz_Globs *)pG)->sol)
+        fprintf(stderr, "\n");
+    /* numlines may or may not be used: */
+    fprintf(stderr, prompt, ((Uz_Globs *)pG)->numlines);
+    fflush(stderr);
+    if (flag & 1) {
+        do {
+            c = (uch)FGETCH(0);
+        } while (c != '\r' && c != '\n' && c != ' ' && c != 'q' && c != 'Q');
+    } else
+        c = (uch)FGETCH(0);
+
+    /* newline was not echoed, so cover up prompt line */
+    fprintf(stderr, LoadFarString(HidePrompt));
+    fflush(stderr);
+
+    if (ToLower(c) == 'q') {
+        DESTROYGLOBALS()
+        EXIT(PK_COOL);
+    }
+
+    ((Uz_Globs *)pG)->sol = TRUE;
+
+#endif
+} /* end function UzpMorePause() */
+
+#endif /* !WINDLL && !MACOS */
+
+
+
+
+#ifndef WINDLL
+
+/**************************/
+/* Function UzpPassword() */
+/**************************/
+
+int UZ_EXP UzpPassword (pG, rcnt, pwbuf, size, zfn, efn)
+    zvoid *pG;         /* pointer to UnZip's internal global vars */
+    int *rcnt;         /* retry counter */
+    char *pwbuf;       /* buffer for password */
+    int size;          /* size of password buffer */
+    ZCONST char *zfn;  /* name of zip archive */
+    ZCONST char *efn;  /* name of archive entry being processed */
+	{
+#if CRYPT
+    int r = IZ_PW_ENTERED;
+    char *m;
+    char *prompt;
+
+#ifndef REENTRANT
+    /* tell picky compilers to shut up about "unused variable" warnings */
+    pG = pG;
+#endif
+
+    if (*rcnt == 0) {           /* First call for current entry */
+        *rcnt = 2;
+        if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) {
+            sprintf(prompt, LoadFarString(PasswPrompt),
+                    FnFilter1(zfn), FnFilter2(efn));
+            m = prompt;
+        } else
+            m = (char *)LoadFarString(PasswPrompt2);
+    } else {                    /* Retry call, previous password was wrong */
+        (*rcnt)--;
+        prompt = NULL;
+        m = (char *)LoadFarString(PasswRetry);
+    }
+
+    m = getp(__G__ m, pwbuf, size);
+    if (prompt != (char *)NULL) {
+        free(prompt);
+    }
+    if (m == (char *)NULL) {
+        r = IZ_PW_ERROR;
+    }
+    else if (*pwbuf == '\0') {
+        r = IZ_PW_CANCELALL;
+    }
+    return r;
+
+#else /* !CRYPT */
+    /* tell picky compilers to shut up about "unused variable" warnings */
+    pG = pG; rcnt = rcnt; pwbuf = pwbuf; size = size; zfn = zfn; efn = efn;
+
+    return IZ_PW_ERROR;  /* internal error; function should never get called */
+#endif /* ?CRYPT */
+
+} /* end function UzpPassword() */
+
+
+
+
+
+/**********************/
+/* Function handler() */
+/**********************/
+
+void handler(signal)   /* upon interrupt, turn on echo and exit cleanly */
+    int signal;
+{
+    GETGLOBALS();
+
+#if !(defined(SIGBUS) || defined(SIGSEGV))      /* add a newline if not at */
+    (*G.message)((zvoid *)&G, slide, 0L, 0x41); /*  start of line (to stderr; */
+#endif                                          /*  slide[] should be safe) */
+
+    echon();
+
+#ifdef SIGBUS
+    if (signal == SIGBUS) {
+        Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),
+          "bus error"));
+        DESTROYGLOBALS()
+        EXIT(PK_BADERR);
+    }
+#endif /* SIGBUS */
+
+#ifdef SIGSEGV
+    if (signal == SIGSEGV) {
+        Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),
+          "segmentation violation"));
+        DESTROYGLOBALS()
+        EXIT(PK_BADERR);
+    }
+#endif /* SIGSEGV */
+
+    /* probably ctrl-C */
+    DESTROYGLOBALS()
+#if defined(AMIGA) && defined(__SASC)
+    _abort();
+#endif
+    EXIT(IZ_CTRLC);       /* was EXIT(0), then EXIT(PK_ERR) */
+}
+
+#endif /* !WINDLL */
+
+
+
+
+#if (!defined(VMS) && !defined(CMS_MVS))
+#if (!defined(OS2) || defined(TIMESTAMP))
+
+#if (!defined(HAVE_MKTIME) || defined(AMIGA) || defined(WIN32))
+/* also used in amiga/filedate.c and win32/win32.c */
+ZCONST ush ydays[] =
+    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
+#endif
+
+/*******************************/
+/* Function dos_to_unix_time() */ /* used for freshening/updating/timestamps */
+/*******************************/
+
+time_t dos_to_unix_time(dosdatetime)
+    ulg dosdatetime;
+{
+    time_t m_time;
+
+#ifdef HAVE_MKTIME
+
+    ZCONST time_t now = time(NULL);
+    struct tm *tm;
+#   define YRBASE  1900
+
+    tm = localtime(&now);
+    tm->tm_isdst = -1;          /* let mktime determine if DST is in effect */
+
+    /* dissect date */
+    tm->tm_year = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE);
+    tm->tm_mon  = ((int)(dosdatetime >> 21) & 0x0f) - 1;
+    tm->tm_mday = ((int)(dosdatetime >> 16) & 0x1f);
+
+    /* dissect time */
+    tm->tm_hour = (int)((unsigned)dosdatetime >> 11) & 0x1f;
+    tm->tm_min  = (int)((unsigned)dosdatetime >> 5) & 0x3f;
+    tm->tm_sec  = (int)((unsigned)dosdatetime << 1) & 0x3e;
+
+    m_time = mktime(tm);
+    NATIVE_TO_TIMET(m_time)     /* NOP unless MSC 7.0 or Macintosh */
+    TTrace((stderr, "  final m_time  =       %lu\n", (ulg)m_time));
+
+#else /* !HAVE_MKTIME */
+
+    int yr, mo, dy, hh, mm, ss;
+#ifdef TOPS20
+#   define YRBASE  1900
+    struct tmx *tmx;
+    char temp[20];
+#else /* !TOPS20 */
+#   define YRBASE  1970
+    int leap;
+    unsigned days;
+    struct tm *tm;
+#if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
+#ifdef WIN32
+    TIME_ZONE_INFORMATION tzinfo;
+    DWORD res;
+#else /* ! WIN32 */
+#ifndef BSD4_4   /* GRR:  change to !defined(MODERN) ? */
+#if (defined(BSD) || defined(MTS) || defined(__GO32__))
+    struct timeb tbp;
+#else /* !(BSD || MTS || __GO32__) */
+#ifdef DECLARE_TIMEZONE
+    extern time_t timezone;
+#endif
+#endif /* ?(BSD || MTS || __GO32__) */
+#endif /* !BSD4_4 */
+#endif /* ?WIN32 */
+#endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
+#endif /* ?TOPS20 */
+
+
+    /* dissect date */
+    yr = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE);
+    mo = ((int)(dosdatetime >> 21) & 0x0f) - 1;
+    dy = ((int)(dosdatetime >> 16) & 0x1f) - 1;
+
+    /* dissect time */
+    hh = (int)((unsigned)dosdatetime >> 11) & 0x1f;
+    mm = (int)((unsigned)dosdatetime >> 5) & 0x3f;
+    ss = (int)((unsigned)dosdatetime & 0x1f) * 2;
+
+#ifdef TOPS20
+    tmx = (struct tmx *)malloc(sizeof(struct tmx));
+    sprintf (temp, "%02d/%02d/%02d %02d:%02d:%02d", mo+1, dy+1, yr, hh, mm, ss);
+    time_parse(temp, tmx, (char *)0);
+    m_time = time_make(tmx);
+    free(tmx);
+
+#else /* !TOPS20 */
+
+/*---------------------------------------------------------------------------
+    Calculate the number of seconds since the epoch, usually 1 January 1970.
+  ---------------------------------------------------------------------------*/
+
+    /* leap = # of leap yrs from YRBASE up to but not including current year */
+    leap = ((yr + YRBASE - 1) / 4);   /* leap year base factor */
+
+    /* calculate days from BASE to this year and add expired days this year */
+    days = (yr * 365) + (leap - 492) + ydays[mo];
+
+    /* if year is a leap year and month is after February, add another day */
+    if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100))
+        ++days;                 /* OK through 2199 */
+
+    /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
+    m_time = (time_t)((unsigned long)(days + dy) * 86400L +
+                      (unsigned long)hh * 3600L +
+                      (unsigned long)(mm * 60 + ss));
+      /* - 1;   MS-DOS times always rounded up to nearest even second */
+    TTrace((stderr, "dos_to_unix_time:\n"));
+    TTrace((stderr, "  m_time before timezone = %lu\n", (ulg)m_time));
+
+/*---------------------------------------------------------------------------
+    Adjust for local standard timezone offset.
+  ---------------------------------------------------------------------------*/
+
+#if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
+#ifdef WIN32
+    /* account for timezone differences */
+    res = GetTimeZoneInformation(&tzinfo);
+    if (res != TIME_ZONE_ID_UNKNOWN)
+    {
+    m_time += 60*(tzinfo.Bias);
+#else /* !WIN32 */
+#if (defined(BSD) || defined(MTS) || defined(__GO32__))
+#ifdef BSD4_4
+    if ( (dosdatetime >= DOSTIME_2038_01_18) &&
+         (m_time < (time_t)0x70000000L) )
+        m_time = U_TIME_T_MAX;  /* saturate in case of (unsigned) overflow */
+    if (m_time < (time_t)0L)    /* a converted DOS time cannot be negative */
+        m_time = S_TIME_T_MAX;  /*  -> saturate at max signed time_t value */
+    if ((tm = localtime(&m_time)) != (struct tm *)NULL)
+        m_time -= tm->tm_gmtoff;                /* sec. EAST of GMT: subtr. */
+#else /* !(BSD4_4 */
+    ftime(&tbp);                                /* get `timezone' */
+    m_time += tbp.timezone * 60L;               /* seconds WEST of GMT:  add */
+#endif /* ?(BSD4_4 || __EMX__) */
+#else /* !(BSD || MTS || __GO32__) */
+    /* tzset was already called at start of process_zipfiles() */
+    /* tzset(); */              /* set `timezone' variable */
+#ifndef __BEOS__                /* BeOS DR8 has no timezones... */
+    m_time += timezone;         /* seconds WEST of GMT:  add */
+#endif
+#endif /* ?(BSD || MTS || __GO32__) */
+#endif /* ?WIN32 */
+    TTrace((stderr, "  m_time after timezone =  %lu\n", (ulg)m_time));
+
+/*---------------------------------------------------------------------------
+    Adjust for local daylight savings (summer) time.
+  ---------------------------------------------------------------------------*/
+
+#ifndef BSD4_4  /* (DST already added to tm_gmtoff, so skip tm_isdst) */
+    if ( (dosdatetime >= DOSTIME_2038_01_18) &&
+         (m_time < (time_t)0x70000000L) )
+        m_time = U_TIME_T_MAX;  /* saturate in case of (unsigned) overflow */
+    if (m_time < (time_t)0L)    /* a converted DOS time cannot be negative */
+        m_time = S_TIME_T_MAX;  /*  -> saturate at max signed time_t value */
+    TIMET_TO_NATIVE(m_time)     /* NOP unless MSC 7.0 or Macintosh */
+    if (((tm = localtime((time_t *)&m_time)) != NULL) && tm->tm_isdst)
+#ifdef WIN32
+        m_time += 60L * tzinfo.DaylightBias;    /* adjust with DST bias */
+    else
+        m_time += 60L * tzinfo.StandardBias;    /* add StdBias (normally 0) */
+#else
+        m_time -= 60L * 60L;    /* adjust for daylight savings time */
+#endif
+    NATIVE_TO_TIMET(m_time)     /* NOP unless MSC 7.0 or Macintosh */
+    TTrace((stderr, "  m_time after DST =       %lu\n", (ulg)m_time));
+#endif /* !BSD4_4 */
+#ifdef WIN32
+    }
+#endif
+#endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
+#endif /* ?TOPS20 */
+
+#endif /* ?HAVE_MKTIME */
+
+    if ( (dosdatetime >= DOSTIME_2038_01_18) &&
+         (m_time < (time_t)0x70000000L) )
+        m_time = U_TIME_T_MAX;  /* saturate in case of (unsigned) overflow */
+    if (m_time < (time_t)0L)    /* a converted DOS time cannot be negative */
+        m_time = S_TIME_T_MAX;  /*  -> saturate at max signed time_t value */
+
+    return m_time;
+
+} /* end function dos_to_unix_time() */
+
+#endif /* !OS2 || TIMESTAMP */
+#endif /* !VMS && !CMS_MVS */
+
+
+
+#if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS))
+
+/******************************/
+/* Function check_for_newer() */  /* used for overwriting/freshening/updating */
+/******************************/
+
+int check_for_newer(__G__ filename)  /* return 1 if existing file is newer */
+    __GDEF                           /*  or equal; 0 if older; -1 if doesn't */
+    char *filename;                  /*  exist yet */
+{
+    time_t existing, archive;
+#ifdef USE_EF_UT_TIME
+    iztimes z_utime;
+#endif
+#ifdef AOS_VS
+    long    dyy, dmm, ddd, dhh, dmin, dss;
+
+
+    dyy = (lrec.last_mod_dos_datetime >> 25) + 1980;
+    dmm = (lrec.last_mod_dos_datetime >> 21) & 0x0f;
+    ddd = (lrec.last_mod_dos_datetime >> 16) & 0x1f;
+    dhh = (lrec.last_mod_dos_datetime >> 11) & 0x1f;
+    dmin = (lrec.last_mod_dos_datetime >> 5) & 0x3f;
+    dss = (lrec.last_mod_dos_datetime & 0x1f) * 2;
+
+    /* under AOS/VS, file times can only be set at creation time,
+     * with the info in a special DG format.  Make sure we can create
+     * it here - we delete it later & re-create it, whether or not
+     * it exists now.
+     */
+    if (!zvs_create(filename, (((ulg)dgdate(dmm, ddd, dyy)) << 16) |
+        (dhh*1800L + dmin*30L + dss/2L), -1L, -1L, (char *) -1, -1, -1, -1))
+        return DOES_NOT_EXIST;
+#endif /* AOS_VS */
+
+    Trace((stderr, "check_for_newer:  doing stat(%s)\n", FnFilter1(filename)));
+    if (SSTAT(filename, &G.statbuf)) {
+        Trace((stderr,
+          "check_for_newer:  stat(%s) returns %d:  file does not exist\n",
+          FnFilter1(filename), SSTAT(filename, &G.statbuf)));
+#ifdef SYMLINKS
+        Trace((stderr, "check_for_newer:  doing lstat(%s)\n",
+          FnFilter1(filename)));
+        /* GRR OPTION:  could instead do this test ONLY if G.symlnk is true */
+        if (lstat(filename, &G.statbuf) == 0) {
+            Trace((stderr,
+              "check_for_newer:  lstat(%s) returns 0:  symlink does exist\n",
+              FnFilter1(filename)));
+            if (QCOND2 && !uO.overwrite_all)
+                Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink),
+                  FnFilter1(filename), " with no real file"));
+            return EXISTS_AND_OLDER;   /* symlink dates are meaningless */
+        }
+#endif /* SYMLINKS */
+        return DOES_NOT_EXIST;
+    }
+    Trace((stderr, "check_for_newer:  stat(%s) returns 0:  file exists\n",
+      FnFilter1(filename)));
+
+#ifdef SYMLINKS
+    /* GRR OPTION:  could instead do this test ONLY if G.symlnk is true */
+    if (lstat(filename, &G.statbuf) == 0 && S_ISLNK(G.statbuf.st_mode)) {
+        Trace((stderr, "check_for_newer:  %s is a symbolic link\n",
+          FnFilter1(filename)));
+        if (QCOND2 && !uO.overwrite_all)
+            Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink),
+              FnFilter1(filename), ""));
+        return EXISTS_AND_OLDER;   /* symlink dates are meaningless */
+    }
+#endif /* SYMLINKS */
+
+    NATIVE_TO_TIMET(G.statbuf.st_mtime)   /* NOP unless MSC 7.0 or Macintosh */
+
+#ifdef USE_EF_UT_TIME
+    /* The `Unix extra field mtime' should be used for comparison with the
+     * time stamp of the existing file >>>ONLY<<< when the EF info is also
+     * used to set the modification time of the extracted file.
+     */
+    if (G.extra_field &&
+#ifdef IZ_CHECK_TZ
+        G.tz_is_valid &&
+#endif
+        (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,
+                          G.lrec.last_mod_dos_datetime, &z_utime, NULL)
+         & EB_UT_FL_MTIME))
+    {
+        TTrace((stderr, "check_for_newer:  using Unix extra field mtime\n"));
+        existing = G.statbuf.st_mtime;
+        archive  = z_utime.mtime;
+    } else {
+        /* round up existing filetime to nearest 2 seconds for comparison,
+         * but saturate in case of arithmetic overflow
+         */
+        existing = ((G.statbuf.st_mtime & 1) &&
+                    (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ?
+                   G.statbuf.st_mtime + 1 : G.statbuf.st_mtime;
+        archive  = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
+    }
+#else /* !USE_EF_UT_TIME */
+    /* round up existing filetime to nearest 2 seconds for comparison,
+     * but saturate in case of arithmetic overflow
+     */
+    existing = ((G.statbuf.st_mtime & 1) &&
+                (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ?
+               G.statbuf.st_mtime + 1 : G.statbuf.st_mtime;
+    archive  = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
+#endif /* ?USE_EF_UT_TIME */
+
+    TTrace((stderr, "check_for_newer:  existing %lu, archive %lu, e-a %ld\n",
+      (ulg)existing, (ulg)archive, (long)(existing-archive)));
+
+    return (existing >= archive);
+
+} /* end function check_for_newer() */
+
+#endif /* !VMS && !OS2 && !CMS_MVS */
+
+
+
+
+
+/************************/
+/* Function do_string() */
+/************************/
+
+int do_string(__G__ len, option)      /* return PK-type error code */
+    __GDEF
+    unsigned int len;           /* without prototype, ush converted to this */
+    int option;
+{
+    long comment_bytes_left, block_length;
+    int error=PK_OK;
+    ush extra_len;
+#ifdef AMIGA
+    char tmp_fnote[2 * AMIGA_FILENOTELEN];   /* extra room for squozen chars */
+#endif
+
+
+/*---------------------------------------------------------------------------
+    This function processes arbitrary-length (well, usually) strings.  Four
+    options are allowed:  SKIP, wherein the string is skipped (pretty logical,
+    eh?); DISPLAY, wherein the string is printed to standard output after un-
+    dergoing any necessary or unnecessary character conversions; DS_FN,
+    wherein the string is put into the filename[] array after undergoing ap-
+    propriate conversions (including case-conversion, if that is indicated:
+    see the global variable pInfo->lcflag); and EXTRA_FIELD, wherein the
+    `string' is assumed to be an extra field and is copied to the (freshly
+    malloced) buffer G.extra_field.  The third option should be OK since
+    filename is dimensioned at 1025, but we check anyway.
+
+    The string, by the way, is assumed to start at the current file-pointer
+    position; its length is given by len.  So start off by checking length
+    of string:  if zero, we're already done.
+  ---------------------------------------------------------------------------*/
+
+    if (!len)
+        return PK_COOL;
+
+    switch (option) {
+
+    /*
+     * First case:  print string on standard output.  First set loop vari-
+     * ables, then loop through the comment in chunks of OUTBUFSIZ bytes,
+     * converting formats and printing as we go.  The second half of the
+     * loop conditional was added because the file might be truncated, in
+     * which case comment_bytes_left will remain at some non-zero value for
+     * all time.  outbuf and slide are used as scratch buffers because they
+     * are available (we should be either before or in between any file pro-
+     * cessing).
+     */
+
+    case DISPLAY:
+    case DISPL_8:
+        comment_bytes_left = len;
+        block_length = OUTBUFSIZ;    /* for the while statement, first time */
+        while (comment_bytes_left > 0 && block_length > 0) {
+            register uch *p = G.outbuf;
+            register uch *q = G.outbuf;
+
+            if ((block_length = readbuf(__G__ (char *)G.outbuf,
+                   (unsigned) MIN((long)OUTBUFSIZ, comment_bytes_left))) == 0)
+                return PK_EOF;
+            comment_bytes_left -= block_length;
+
+            /* this is why we allocated an extra byte for outbuf:  terminate
+             *  with zero (ASCIIZ) */
+            G.outbuf[(unsigned)block_length] = '\0';
+
+            /* remove all ASCII carriage returns from comment before printing
+             * (since used before A_TO_N(), check for CR instead of '\r')
+             */
+            while (*p) {
+                while (*p == CR)
+                    ++p;
+                *q++ = *p++;
+            }
+            /* could check whether (p - outbuf) == block_length here */
+            *q = '\0';
+
+            if (option == DISPL_8) {
+                /* translate the text coded in the entry's host-dependent
+                   "extended ASCII" charset into the compiler's (system's)
+                   internal text code page */
+                Ext_ASCII_TO_Native((char *)G.outbuf, G.pInfo->hostnum,
+                                    G.crec.version_made_by[0]);
+#ifdef WINDLL
+                /* translate to ANSI (RTL internal codepage may be OEM) */
+                INTERN_TO_ISO((char *)G.outbuf, (char *)G.outbuf);
+#else /* !WINDLL */
+#ifdef WIN32
+                /* Win9x console always uses OEM character coding, and
+                   WinNT console is set to OEM charset by default, too */
+                INTERN_TO_OEM((char *)G.outbuf, (char *)G.outbuf);
+#endif /* WIN32 */
+#endif /* ?WINDLL */
+            } else {
+                A_TO_N(G.outbuf);   /* translate string to native */
+            }
+
+#ifdef WINDLL
+            /* ran out of local mem -- had to cheat */
+            win_fprintf((zvoid *)&G, stdout, len, (char *)G.outbuf);
+            win_fprintf((zvoid *)&G, stdout, 2, (char *)"\n\n");
+#else /* !WINDLL */
+#ifdef NOANSIFILT       /* GRR:  can ANSI be used with EBCDIC? */
+            (*G.message)((zvoid *)&G, G.outbuf, (ulg)(q-G.outbuf), 0);
+#else /* ASCII, filter out ANSI escape sequences and handle ^S (pause) */
+            p = G.outbuf - 1;
+            q = slide;
+            while (*++p) {
+                int pause = FALSE;
+
+                if (*p == 0x1B) {          /* ASCII escape char */
+                    *q++ = '^';
+                    *q++ = '[';
+                } else if (*p == 0x13) {   /* ASCII ^S (pause) */
+                    pause = TRUE;
+                    if (p[1] == LF)        /* ASCII LF */
+                        *q++ = *++p;
+                    else if (p[1] == CR && p[2] == LF) {  /* ASCII CR LF */
+                        *q++ = *++p;
+                        *q++ = *++p;
+                    }
+                } else
+                    *q++ = *p;
+                if ((unsigned)(q-slide) > WSIZE-3 || pause) {   /* flush */
+                    (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);
+                    q = slide;
+                    if (pause && G.extract_flag) /* don't pause for list/test */
+                        (*G.mpause)((zvoid *)&G, LoadFarString(QuitPrompt), 0);
+                }
+            }
+            (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);
+#endif /* ?NOANSIFILT */
+#endif /* ?WINDLL */
+        }
+        /* add '\n' if not at start of line */
+        (*G.message)((zvoid *)&G, slide, 0L, 0x40);
+        break;
+
+    /*
+     * Second case:  read string into filename[] array.  The filename should
+     * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check,
+     * just to be sure.
+     */
+
+    case DS_FN:
+        extra_len = 0;
+        if (len >= FILNAMSIZ) {
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(FilenameTooLongTrunc)));
+            error = PK_WARN;
+            extra_len = (ush)(len - FILNAMSIZ + 1);
+            len = FILNAMSIZ - 1;
+        }
+        if (readbuf(__G__  G.filename, len) == 0)
+            return PK_EOF;
+        G.filename[len] = '\0';   /* terminate w/zero:  ASCIIZ */
+
+        /* translate the Zip entry filename coded in host-dependent "extended
+           ASCII" into the compiler's (system's) internal text code page */
+        Ext_ASCII_TO_Native(G.filename, G.pInfo->hostnum,
+                            G.crec.version_made_by[0]);
+
+        if (G.pInfo->lcflag)      /* replace with lowercase filename */
+            TOLOWER(G.filename, G.filename);
+
+        if (G.pInfo->vollabel && len > 8 && G.filename[8] == '.') {
+            char *p = G.filename+8;
+            while (*p++)
+                p[-1] = *p;  /* disk label, and 8th char is dot:  remove dot */
+        }
+
+        if (!extra_len)         /* we're done here */
+            break;
+
+        /*
+         * We truncated the filename, so print what's left and then fall
+         * through to the SKIP routine.
+         */
+        Info(slide, 0x401, ((char *)slide, "[ %s ]\n", FnFilter1(G.filename)));
+        len = extra_len;
+        /*  FALL THROUGH...  */
+
+    /*
+     * Third case:  skip string, adjusting readbuf's internal variables
+     * as necessary (and possibly skipping to and reading a new block of
+     * data).
+     */
+
+    case SKIP:
+        /* cur_zipfile_bufstart already takes account of extra_bytes, so don't
+         * correct for it twice: */
+        ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes +
+               (G.inptr-G.inbuf) + len)
+        break;
+
+    /*
+     * Fourth case:  assume we're at the start of an "extra field"; malloc
+     * storage for it and read data into the allocated space.
+     */
+
+    case EXTRA_FIELD:
+        if (G.extra_field != (uch *)NULL)
+            free(G.extra_field);
+        if ((G.extra_field = (uch *)malloc(len)) == (uch *)NULL) {
+            Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraFieldTooLong),
+              len));
+            /* cur_zipfile_bufstart already takes account of extra_bytes,
+             * so don't correct for it twice: */
+            ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes +
+                   (G.inptr-G.inbuf) + len)
+        } else
+            if (readbuf(__G__  (char *)G.extra_field, len) == 0)
+                return PK_EOF;
+        break;
+
+#ifdef AMIGA
+    /*
+     * Fifth case, for the Amiga only:  take the comment that would ordinarily
+     * be skipped over, and turn it into a 79 character string that will be
+     * attached to the file as a "filenote" after it is extracted.
+     */
+
+    case FILENOTE:
+        if ((extra_len = readbuf(__G__ tmp_fnote, (unsigned)
+                                 MIN(len, 2 * AMIGA_FILENOTELEN - 1))) == 0)
+            return PK_EOF;
+        if ((len -= extra_len) > 0)     /* treat remainder as in case SKIP: */
+            ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes
+                   + (G.inptr - G.inbuf) + len)
+        /* convert multi-line text into single line with no ctl-chars: */
+        tmp_fnote[extra_len] = '\0';
+        while ((short int) --extra_len >= 0)
+            if ((unsigned) tmp_fnote[extra_len] < ' ')
+                if (tmp_fnote[extra_len+1] == ' ')     /* no excess */
+                    strcpy(tmp_fnote+extra_len, tmp_fnote+extra_len+1);
+                else
+                    tmp_fnote[extra_len] = ' ';
+        tmp_fnote[AMIGA_FILENOTELEN - 1] = '\0';
+        if (G.filenotes[G.filenote_slot])
+            free(G.filenotes[G.filenote_slot]);     /* should not happen */
+        G.filenotes[G.filenote_slot] = NULL;
+        if (tmp_fnote[0]) {
+            if (!(G.filenotes[G.filenote_slot] = malloc(strlen(tmp_fnote)+1)))
+                return PK_MEM;
+            strcpy(G.filenotes[G.filenote_slot], tmp_fnote);
+        }
+        break;
+#endif /* AMIGA */
+
+    } /* end switch (option) */
+
+    return error;
+
+} /* end function do_string() */
+
+
+
+
+
+/***********************/
+/* Function makeword() */
+/***********************/
+
+ush makeword(b)
+    ZCONST uch *b;
+{
+    /*
+     * Convert Intel style 'short' integer to non-Intel non-16-bit
+     * host format.  This routine also takes care of byte-ordering.
+     */
+    return (ush)((b[1] << 8) | b[0]);
+}
+
+
+
+
+
+/***********************/
+/* Function makelong() */
+/***********************/
+
+ulg makelong(sig)
+    ZCONST uch *sig;
+{
+    /*
+     * Convert intel style 'long' variable to non-Intel non-16-bit
+     * host format.  This routine also takes care of byte-ordering.
+     */
+    return (((ulg)sig[3]) << 24)
+        + (((ulg)sig[2]) << 16)
+        + (((ulg)sig[1]) << 8)
+        + ((ulg)sig[0]);
+}
+
+
+
+#if CRYPT
+
+#ifdef NEED_STR2ISO
+/**********************/
+/* Function str2iso() */
+/**********************/
+
+char *str2iso(dst, src)
+    char *dst;                          /* destination buffer */
+    register ZCONST char *src;          /* source string */
+{
+#ifdef INTERN_TO_ISO
+    INTERN_TO_ISO(src, dst);
+#else
+    register uch c;
+    register char *dstp = dst;
+
+    do {
+        c = (uch)foreign(*src++);
+        *dstp++ = (char)ASCII2ISO(c);
+    } while (c != '\0');
+#endif
+
+    return dst;
+}
+#endif /* NEED_STR2ISO */
+
+
+#ifdef NEED_STR2OEM
+/**********************/
+/* Function str2oem() */
+/**********************/
+
+char *str2oem(dst, src)
+    char *dst;                          /* destination buffer */
+    register ZCONST char *src;          /* source string */
+{
+#ifdef INTERN_TO_OEM
+    INTERN_TO_OEM(src, dst);
+#else
+    register uch c;
+    register char *dstp = dst;
+
+    do {
+        c = (uch)foreign(*src++);
+        *dstp++ = (char)ASCII2OEM(c);
+    } while (c != '\0');
+#endif
+
+    return dst;
+}
+#endif /* NEED_STR2OEM */
+
+#endif /* CRYPT */
+
+
+#ifdef ZMEM  /* memset/memcmp/memcpy for systems without either them or */
+             /* bzero/bcmp/bcopy */
+             /* (no known systems as of 960211) */
+
+/*********************/
+/* Function memset() */
+/*********************/
+
+zvoid *memset(buf, init, len)
+    register zvoid *buf;        /* buffer location */
+    register int init;          /* initializer character */
+    register unsigned int len;  /* length of the buffer */
+{
+    zvoid *start;
+
+    start = buf;
+    while (len--)
+        *((char *)buf++) = (char)init;
+    return start;
+}
+
+
+
+/*********************/
+/* Function memcmp() */
+/*********************/
+
+int memcmp(b1, b2, len)
+    register ZCONST zvoid *b1;
+    register ZCONST zvoid *b2;
+    register unsigned int len;
+{
+    register int c;
+
+    if (len > 0) do {
+        if ((c = (int)(*((ZCONST unsigned char *)b1)++) -
+                 (int)(*((ZCONST unsigned char *)b2)++)) != 0)
+           return c;
+    } while (--len > 0)
+    return 0;
+}
+
+
+
+/*********************/
+/* Function memcpy() */
+/*********************/
+
+zvoid *memcpy(dst, src, len)
+    register zvoid *dst;
+    register ZCONST zvoid *src;
+    register unsigned int len;
+{
+    zvoid *start;
+
+    start = dst;
+    while (len-- > 0)
+        *((char *)dst)++ = *((ZCONST char *)src)++;
+    return start;
+}
+
+#endif /* ZMEM */
+
+
+
+
+
+/************************/
+/* Function zstrnicmp() */
+/************************/
+
+int zstrnicmp(s1, s2, n)
+    register ZCONST char *s1, *s2;
+    register unsigned n;
+{
+    for (; n > 0;  --n, ++s1, ++s2) {
+
+        if (ToLower(*s1) != ToLower(*s2))
+            /* test includes early termination of one string */
+            return (ToLower(*s1) < ToLower(*s2))? -1 : 1;
+
+        if (*s1 == '\0')   /* both strings terminate early */
+            return 0;
+    }
+    return 0;
+}
+
+
+
+
+
+#ifdef REGULUS  /* returns the inode number on success(!)...argh argh argh */
+#  undef stat
+
+/********************/
+/* Function zstat() */
+/********************/
+
+int zstat(p, s)
+    char *p;
+    struct stat *s;
+{
+    return (stat(p,s) >= 0? 0 : (-1));
+}
+
+#endif /* REGULUS */
+
+
+
+
+
+#ifdef SMALL_MEM
+
+/*******************************/
+/*  Function fLoadFarString()  */   /* (and friends...) */
+/*******************************/
+
+char *fLoadFarString(__GPRO__ const char Far *sz)
+{
+    (void)zfstrcpy(G.rgchBigBuffer, sz);
+    return G.rgchBigBuffer;
+}
+
+char *fLoadFarStringSmall(__GPRO__ const char Far *sz)
+{
+    (void)zfstrcpy(G.rgchSmallBuffer, sz);
+    return G.rgchSmallBuffer;
+}
+
+char *fLoadFarStringSmall2(__GPRO__ const char Far *sz)
+{
+    (void)zfstrcpy(G.rgchSmallBuffer2, sz);
+    return G.rgchSmallBuffer2;
+}
+
+
+
+
+#if (!defined(_MSC_VER) || (_MSC_VER < 600))
+/*************************/
+/*  Function zfstrcpy()  */   /* portable clone of _fstrcpy() */
+/*************************/
+
+char Far * Far zfstrcpy(char Far *s1, const char Far *s2)
+{
+    char Far *p = s1;
+
+    while ((*s1++ = *s2++) != '\0');
+    return p;
+}
+#endif /* !_MSC_VER || (_MSC_VER < 600) */
+
+#endif /* SMALL_MEM */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/funzip.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,468 @@
+/* funzip.c -- put in the public domain by Mark Adler */
+
+#define VERSION "3.93 of 21 November 1998"
+
+
+/* You can do whatever you like with this source file, though I would
+   prefer that if you modify it and redistribute it that you include
+   comments to that effect with your name and the date.  Thank you.
+
+   History:
+   vers     date          who           what
+   ----   ---------  --------------  ------------------------------------
+   1.0    13 Aug 92  M. Adler        really simple unzip filter.
+   1.1    13 Aug 92  M. Adler        cleaned up somewhat, give help if
+                                     stdin not redirected, warn if more
+                                     zip file entries after the first.
+   1.2    15 Aug 92  M. Adler        added check of lengths for stored
+                                     entries, added more help.
+   1.3    16 Aug 92  M. Adler        removed redundant #define's, added
+                                     decryption.
+   1.4    27 Aug 92  G. Roelofs      added exit(0).
+   1.5     1 Sep 92  K. U. Rommel    changed read/write modes for OS/2.
+   1.6     6 Sep 92  G. Roelofs      modified to use dummy crypt.c and
+                                     crypt.h instead of -DCRYPT.
+   1.7    23 Sep 92  G. Roelofs      changed to use DOS_OS2; included
+                                     crypt.c under MS-DOS.
+   1.8     9 Oct 92  M. Adler        improved inflation error msgs.
+   1.9    17 Oct 92  G. Roelofs      changed ULONG/UWORD/byte to ulg/ush/uch;
+                                     renamed inflate_entry() to inflate();
+                                     adapted to use new, in-place zdecode.
+   2.0    22 Oct 92  M. Adler        allow filename argument, prompt for
+                                     passwords and don't echo, still allow
+                                     command-line password entry, but as an
+                                     option.
+   2.1    23 Oct 92  J-l. Gailly     fixed crypt/store bug,
+                     G. Roelofs      removed crypt.c under MS-DOS, fixed
+                                     decryption check to compare single byte.
+   2.2    28 Oct 92  G. Roelofs      removed declaration of key.
+   2.3    14 Dec 92  M. Adler        replaced fseek (fails on stdin for SCO
+                                     Unix V.3.2.4).  added quietflg for
+                                     inflate.c.
+   3.0    11 May 93  M. Adler        added gzip support
+   3.1     9 Jul 93  K. U. Rommel    fixed OS/2 pipe bug (PIPE_ERROR)
+   3.2     4 Sep 93  G. Roelofs      moved crc_32_tab[] to tables.h; used FOPx
+                                     from unzip.h; nuked OUTB macro and outbuf;
+                                     replaced flush(); inlined FlushOutput();
+                                     renamed decrypt to encrypted
+   3.3    29 Sep 93  G. Roelofs      replaced ReadByte() with NEXTBYTE macro;
+                                     revised (restored?) flush(); added FUNZIP
+   3.4    21 Oct 93  G. Roelofs      renamed quietflg to qflag; changed outcnt,
+                     H. Gessau       second updcrc() arg and flush() arg to ulg;
+                                     added inflate_free(); added "g =" to null
+                                     getc(in) to avoid compiler warnings
+   3.5    31 Oct 93  H. Gessau       changed DOS_OS2 to DOS_NT_OS2
+   3.6     6 Dec 93  H. Gessau       added "near" to mask_bits[]
+   3.7     9 Dec 93  G. Roelofs      added extent typecasts to fwrite() checks
+   3.8    28 Jan 94  GRR/JlG         initialized g variable in main() for gcc
+   3.81   22 Feb 94  M. Hanning-Lee  corrected usage message
+   3.82   27 Feb 94  G. Roelofs      added some typecasts to avoid warnings
+   3.83   22 Jul 94  G. Roelofs      changed fprintf to macro for DLLs
+    -      2 Aug 94  -               public release with UnZip 5.11
+    -     28 Aug 94  -               public release with UnZip 5.12
+   3.84    1 Oct 94  K. U. Rommel    changes for Metaware High C
+   3.85   29 Oct 94  G. Roelofs      changed fprintf macro to Info
+   3.86    7 May 95  K. Davis        RISCOS patches;
+                     P. Kienitz      Amiga patches
+   3.87   12 Aug 95  G. Roelofs      inflate_free(), DESTROYGLOBALS fixes
+   3.88    4 Sep 95  C. Spieler      reordered macro to work around MSC 5.1 bug
+   3.89   22 Nov 95  PK/CS           ifdef'd out updcrc() for ASM_CRC
+   3.9    17 Dec 95  G. Roelofs      modified for USE_ZLIB (new fillinbuf())
+    -     30 Apr 96  -               public release with UnZip 5.2
+   3.91   17 Aug 96  G. Roelofs      main() -> return int (Peter Seebach)
+   3.92   13 Apr 97  G. Roelofs      minor cosmetic fixes to messages
+    -     22 Apr 97  -               public release with UnZip 5.3
+    -     31 May 97  -               public release with UnZip 5.31
+   3.93   20 Sep 97  G. Roelofs      minor cosmetic fixes to messages
+    -      3 Nov 97  -               public release with UnZip 5.32
+    -     28 Nov 98  -               public release with UnZip 5.4
+ */
+
+
+/*
+
+   All funzip does is take a zipfile from stdin and decompress the
+   first entry to stdout.  The entry has to be either deflated or
+   stored.  If the entry is encrypted, then the decryption password
+   must be supplied on the command line as the first argument.
+
+   funzip needs to be linked with inflate.o and crypt.o compiled from
+   the unzip source.  If decryption is desired, the full version of
+   crypt.c (and crypt.h) from zcrypt21.zip or later must be used.
+
+ */
+
+#define FUNZIP
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#include "crypt.h"
+#include "ttyio.h"
+
+#ifdef EBCDIC
+#  undef EBCDIC                 /* don't need ebcdic[] */
+#endif
+#include "tables.h"             /* crc_32_tab[] */
+
+#ifndef USE_ZLIB  /* zlib's function is called inflate(), too */
+#  define UZinflate inflate
+#endif
+
+/* PKZIP header definitions */
+#define ZIPMAG 0x4b50           /* two-byte zip lead-in */
+#define LOCREM 0x0403           /* remaining two bytes in zip signature */
+#define LOCSIG 0x04034b50L      /* full signature */
+#define LOCFLG 4                /* offset of bit flag */
+#define  CRPFLG 1               /*  bit for encrypted entry */
+#define  EXTFLG 8               /*  bit for extended local header */
+#define LOCHOW 6                /* offset of compression method */
+#define LOCTIM 8                /* file mod time (for decryption) */
+#define LOCCRC 12               /* offset of crc */
+#define LOCSIZ 16               /* offset of compressed size */
+#define LOCLEN 20               /* offset of uncompressed length */
+#define LOCFIL 24               /* offset of file name field length */
+#define LOCEXT 26               /* offset of extra field length */
+#define LOCHDR 28               /* size of local header, including LOCREM */
+#define EXTHDR 16               /* size of extended local header, inc sig */
+
+/* GZIP header definitions */
+#define GZPMAG 0x8b1f           /* two-byte gzip lead-in */
+#define GZPHOW 0                /* offset of method number */
+#define GZPFLG 1                /* offset of gzip flags */
+#define  GZPMUL 2               /* bit for multiple-part gzip file */
+#define  GZPISX 4               /* bit for extra field present */
+#define  GZPISF 8               /* bit for filename present */
+#define  GZPISC 16              /* bit for comment present */
+#define  GZPISE 32              /* bit for encryption */
+#define GZPTIM 2                /* offset of Unix file modification time */
+#define GZPEXF 6                /* offset of extra flags */
+#define GZPCOS 7                /* offset of operating system compressed on */
+#define GZPHDR 8                /* length of minimal gzip header */
+
+/* Macros for getting two-byte and four-byte header values */
+#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))
+#define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16))
+
+/* Function prototypes */
+void err OF((int, char *));
+int main OF((int, char **));
+
+/* Globals */
+FILE *out;                      /* output file (*in moved to G struct) */
+ulg outsiz;                     /* total bytes written to out */
+int encrypted;                  /* flag to turn on decryption */
+
+/* Masks for inflate.c */
+ZCONST ush near mask_bits[] = {
+    0x0000,
+    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+
+#ifdef USE_ZLIB
+
+int fillinbuf(__G)
+__GDEF
+/* Fill input buffer for pull-model inflate() in zlib.  Return the number of
+ * bytes in inbuf. */
+{
+/*   GRR: check return value from fread(): same as read()?  check errno? */
+  if ((G.incnt = fread((char *)G.inbuf, 1, INBUFSIZ, G.in)) <= 0)
+    return 0;
+  G.inptr = G.inbuf;
+
+#if CRYPT
+  if (encrypted) {
+    uch *p;
+    int n;
+
+    for (n = G.incnt, p = G.inptr;  n--;  p++)
+      zdecode(*p);
+  }
+#endif /* CRYPT */
+
+  return G.incnt;
+
+}
+
+#endif /* USE_ZLIB */
+
+
+#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))
+#ifdef USE_ZLIB
+ZCONST uLongf *get_crc_table()
+{
+  return (ZCONST uLongf *)crc_32_tab;
+}
+#else /* !USE_ZLIB */
+ZCONST ulg near *get_crc_table()
+{
+  return crc_32_tab;
+}
+#endif /* ?USE_ZLIB */
+#endif /* !USE_ZLIB || USE_OWN_CRCTAB */
+
+
+void err(n, m)
+int n;
+char *m;
+/* Exit on error with a message and a code */
+{
+  Info(slide, 1, ((char *)slide, "funzip error: %s\n", m));
+  DESTROYGLOBALS()
+  EXIT(n);
+}
+
+
+int flush(w)    /* used by inflate.c (FLUSH macro) */
+ulg w;          /* number of bytes to flush */
+{
+  G.crc32val = crc32(G.crc32val, slide, (extent)w);
+  if (fwrite((char *)slide,1,(extent)w,out) != (extent)w && !PIPE_ERROR)
+    err(9, "out of space on stdout");
+  outsiz += w;
+  return 0;
+}
+
+
+int main(argc, argv)
+int argc;
+char **argv;
+/* Given a zipfile on stdin, decompress the first entry to stdout. */
+{
+  ush n;
+  uch h[LOCHDR];                /* first local header (GZPHDR < LOCHDR) */
+  int g = 0;                    /* true if gzip format */
+#if CRYPT
+  char *s = " [-password]";
+  char *p;                      /* password */
+#else /* !CRYPT */
+  char *s = "";
+#endif /* ?CRYPT */
+  CONSTRUCTGLOBALS();
+
+  /* skip executable name */
+  argc--;
+  argv++;
+
+#if CRYPT
+  /* get the command line password, if any */
+  p = (char *)NULL;
+  if (argc && **argv == '-')
+  {
+    argc--;
+    p = 1 + *argv++;
+  }
+#endif /* CRYPT */
+
+#ifdef MALLOC_WORK
+  G.area.Slide = (uch *)calloc(8193, sizeof(short)+sizeof(char)+sizeof(char));
+#endif
+
+  /* if no file argument and stdin not redirected, give the user help */
+  if (argc == 0 && isatty(0))
+  {
+    Info(slide, 1, ((char *)slide, "fUnZip (filter UnZip), version %s\n",
+      VERSION));
+    Info(slide, 1, ((char *)slide, "usage: ... | funzip%s | ...\n", s));
+    Info(slide, 1, ((char *)slide, "       ... | funzip%s > outfile\n", s));
+    Info(slide, 1, ((char *)slide, "       funzip%s infile.zip > outfile\n",s));
+    Info(slide, 1, ((char *)slide, "       funzip%s infile.gz > outfile\n", s));
+    Info(slide, 1, ((char *)slide, "Extracts to stdout the gzip file or first\
+ zip entry of stdin or the given file.\n"));
+    DESTROYGLOBALS()
+    EXIT(3);
+  }
+
+  /* prepare to be a binary filter */
+  if (argc)
+  {
+    if ((G.in = fopen(*argv, FOPR)) == (FILE *)NULL)
+      err(2, "cannot find input file");
+  }
+  else
+  {
+#ifdef DOS_FLX_H68_OS2_W32
+#if (defined(__HIGHC__) && !defined(FLEXOS))
+    setmode(stdin, _BINARY);
+#else
+    setmode(0, O_BINARY);  /* some buggy C libraries require BOTH setmode() */
+#endif                     /*  call AND the fdopen() in binary mode :-( */
+#endif /* DOS_FLX_H68_OS2_W32 */
+
+#ifdef RISCOS
+    G.in = stdin;
+#else
+    if ((G.in = fdopen(0, FOPR)) == (FILE *)NULL)
+      err(2, "cannot find stdin");
+#endif
+  }
+
+#ifdef DOS_FLX_H68_OS2_W32
+#if (defined(__HIGHC__) && !defined(FLEXOS))
+  setmode(stdout, _BINARY);
+#else
+  setmode(1, O_BINARY);
+#endif
+#endif /* DOS_FLX_H68_OS2_W32 */
+
+#ifdef RISCOS
+  out = stdout;
+#else
+  if ((out = fdopen(1, FOPW)) == (FILE *)NULL)
+    err(2, "cannot write to stdout");
+#endif
+
+  /* read local header, check validity, and skip name and extra fields */
+  n = getc(G.in);  n |= getc(G.in) << 8;
+  if (n == ZIPMAG)
+  {
+    if (fread((char *)h, 1, LOCHDR, G.in) != LOCHDR || SH(h) != LOCREM)
+      err(3, "invalid zipfile");
+    if (SH(h + LOCHOW) != STORED && SH(h + LOCHOW) != DEFLATED)
+      err(3, "first entry not deflated or stored--cannot unpack");
+    for (n = SH(h + LOCFIL); n--; ) g = getc(G.in);
+    for (n = SH(h + LOCEXT); n--; ) g = getc(G.in);
+    g = 0;
+    encrypted = h[LOCFLG] & CRPFLG;
+  }
+  else if (n == GZPMAG)
+  {
+    if (fread((char *)h, 1, GZPHDR, G.in) != GZPHDR)
+      err(3, "invalid gzip file");
+    if (h[GZPHOW] != DEFLATED)
+      err(3, "gzip file not deflated");
+    if (h[GZPFLG] & GZPMUL)
+      err(3, "cannot handle multi-part gzip files");
+    if (h[GZPFLG] & GZPISX)
+    {
+      n = getc(G.in);  n |= getc(G.in) << 8;
+      while (n--) g = getc(G.in);
+    }
+    if (h[GZPFLG] & GZPISF)
+      while ((g = getc(G.in)) != 0 && g != EOF) ;
+    if (h[GZPFLG] & GZPISC)
+      while ((g = getc(G.in)) != 0 && g != EOF) ;
+    g = 1;
+    encrypted = h[GZPFLG] & GZPISE;
+  }
+  else
+    err(3, "input not a zip or gzip file");
+
+  /* if entry encrypted, decrypt and validate encryption header */
+  if (encrypted)
+#if CRYPT
+    {
+      ush i, e;
+
+      if (p == (char *)NULL) {
+        if ((p = (char *)malloc(IZ_PWLEN+1)) == (char *)NULL)
+          err(1, "out of memory");
+        else if ((p = getp("Enter password: ", p, IZ_PWLEN+1)) == (char *)NULL)
+          err(1, "no tty to prompt for password");
+      }
+#if (defined(USE_ZLIB) && !defined(USE_OWN_CRCTAB))
+      /* initialize crc_32_tab pointer for decryption */
+      CRC_32_TAB = (ZCONST ulg Far *)get_crc_table();
+#endif
+      init_keys(p);
+      for (i = 0; i < RAND_HEAD_LEN; i++)
+        e = NEXTBYTE;
+      if (e != (ush)(h[LOCFLG] & EXTFLG ? h[LOCTIM + 1] : h[LOCCRC + 3]))
+        err(3, "incorrect password for first entry");
+    }
+#else /* !CRYPT */
+    err(3, "cannot decrypt entry (need to recompile with full crypt.c)");
+#endif /* ?CRYPT */
+
+  /* prepare output buffer and crc */
+  G.outptr = slide;
+  G.outcnt = 0L;
+  outsiz = 0L;
+  G.crc32val = CRCVAL_INITIAL;
+
+  /* decompress */
+  if (g || h[LOCHOW])
+  {                             /* deflated entry */
+    int r;
+
+#ifdef USE_ZLIB
+    /* need to allocate and prepare input buffer */
+    if ((G.inbuf = (uch *)malloc(INBUFSIZ)) == (uch *)NULL)
+       err(1, "out of memory");
+#endif /* USE_ZLIB */
+    if ((r = UZinflate(__G)) != 0) {
+      if (r == 3)
+        err(1, "out of memory");
+      else
+        err(4, "invalid compressed data--format violated");
+    }
+    inflate_free(__G);
+  }
+  else
+  {                             /* stored entry */
+    register ulg n;
+
+    n = LG(h + LOCLEN);
+#if CRYPT
+    if (n != LG(h + LOCSIZ) - (encrypted ? RAND_HEAD_LEN : 0)) {
+#else
+    if (n != LG(h + LOCSIZ)) {
+#endif
+      Info(slide, 1, ((char *)slide, "len %ld, siz %ld\n", n, LG(h + LOCSIZ)));
+      err(4, "invalid compressed data--length mismatch");
+    }
+    while (n--) {
+      ush c = getc(G.in);
+#if CRYPT
+      if (encrypted)
+        zdecode(c);
+#endif
+      *G.outptr++ = (uch)c;
+      if (++G.outcnt == WSIZE)    /* do FlushOutput() */
+      {
+        G.crc32val = crc32(G.crc32val, slide, (extent)G.outcnt);
+        if (fwrite((char *)slide, 1,(extent)G.outcnt,out) != (extent)G.outcnt
+            && !PIPE_ERROR)
+          err(9, "out of space on stdout");
+        outsiz += G.outcnt;
+        G.outptr = slide;
+        G.outcnt = 0L;
+      }
+    }
+  }
+  if (G.outcnt)   /* flush one last time; no need to reset G.outptr/outcnt */
+  {
+    G.crc32val = crc32(G.crc32val, slide, (extent)G.outcnt);
+    if (fwrite((char *)slide, 1,(extent)G.outcnt,out) != (extent)G.outcnt
+        && !PIPE_ERROR)
+      err(9, "out of space on stdout");
+    outsiz += G.outcnt;
+  }
+  fflush(out);
+
+  /* if extended header, get it */
+  if (g)
+  {
+    if (fread((char *)h + LOCCRC, 1, 8, G.in) != 8)
+      err(3, "gzip file ended prematurely");
+  }
+  else
+    if ((h[LOCFLG] & EXTFLG) &&
+        fread((char *)h + LOCCRC - 4, 1, EXTHDR, G.in) != EXTHDR)
+      err(3, "zipfile ended prematurely");
+
+  /* validate decompression */
+  if (LG(h + LOCCRC) != G.crc32val)
+    err(4, "invalid compressed data--crc error");
+  if (LG((g ? (h + LOCSIZ) : (h + LOCLEN))) != outsiz)
+    err(4, "invalid compressed data--length error");
+
+  /* check if there are more entries */
+  if (!g && fread((char *)h, 1, 4, G.in) == 4 && LG(h) == LOCSIG)
+    Info(slide, 1, ((char *)slide,
+      "funzip warning: zipfile has more than one entry--rest ignored\n"));
+
+  DESTROYGLOBALS()
+  RETURN (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/globals.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,204 @@
+/*---------------------------------------------------------------------------
+
+  globals.c
+
+  Routines to allocate and initialize globals, with or without threads.
+
+  Contents:  registerGlobalPointer()
+             deregisterGlobalPointer()
+             getGlobalPointer()
+             globalsCtor()
+
+  ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+
+#ifndef FUNZIP
+/* initialization of sigs is completed at runtime so unzip(sfx) executable
+ * won't look like a zipfile
+ */
+char central_hdr_sig[4] = {0, 0, 0x01, 0x02};
+char local_hdr_sig[4]   = {0, 0, 0x03, 0x04};
+char end_central_sig[4] = {0, 0, 0x05, 0x06};
+/* extern char extd_local_sig[4] = {0, 0, 0x07, 0x08};  NOT USED YET */
+
+ZCONST char *fnames[2] = {"*", NULL};   /* default filenames vector */
+#endif
+
+
+#ifndef REENTRANT
+   Uz_Globs G;
+#else /* REENTRANT */
+
+#  ifndef USETHREADID
+     Uz_Globs *GG;
+#  else /* USETHREADID */
+#    define THREADID_ENTRIES  0x40
+
+     int lastScan;
+     Uz_Globs  *threadPtrTable[THREADID_ENTRIES];
+     ulg        threadIdTable [THREADID_ENTRIES] = {
+         0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
+         0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,    /* Make sure there are */
+         0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,    /* THREADID_ENTRIES 0s */
+         0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
+     };
+
+     static ZCONST char Far TooManyThreads[] =
+       "error:  more than %d simultaneous threads.\n\
+        Some threads are probably not calling DESTROYTHREAD()\n";
+     static ZCONST char Far EntryNotFound[] =
+       "error:  couldn't find global pointer in table.\n\
+        Maybe somebody accidentally called DESTROYTHREAD() twice.\n";
+     static ZCONST char Far GlobalPointerMismatch[] =
+       "error:  global pointer in table does not match pointer passed as\
+ parameter\n";
+
+static void registerGlobalPointer OF((__GPRO));
+
+
+
+static void registerGlobalPointer(__G)
+    __GDEF
+{
+    int scan=0;
+    ulg tid = GetThreadId();
+
+    while (threadIdTable[scan] && scan < THREADID_ENTRIES)
+        scan++;
+
+    if (scan == THREADID_ENTRIES) {
+        ZCONST char *tooMany = LoadFarString(TooManyThreads);
+        Info(slide, 0x421, ((char *)slide, tooMany, THREADID_ENTRIES));
+        free(pG);
+        EXIT(PK_MEM);   /* essentially memory error before we've started */
+    }
+
+    threadIdTable [scan] = tid;
+    threadPtrTable[scan] = pG;
+    lastScan = scan;
+}
+
+
+
+void deregisterGlobalPointer(__G)
+    __GDEF
+{
+    int scan=0;
+    ulg tid = GetThreadId();
+
+
+    while (threadIdTable[scan] != tid && scan < THREADID_ENTRIES)
+        scan++;
+
+/*---------------------------------------------------------------------------
+    There are two things we can do if we can't find the entry:  ignore it or
+    scream.  The most likely reason for it not to be here is the user calling
+    this routine twice.  Since this could cause BIG problems if any globals
+    are accessed after the first call, we'd better scream.
+  ---------------------------------------------------------------------------*/
+
+    if (scan == THREADID_ENTRIES || threadPtrTable[scan] != pG) {
+        ZCONST char *noEntry;
+        if (scan == THREADID_ENTRIES)
+            noEntry = LoadFarString(EntryNotFound);
+        else
+            noEntry = LoadFarString(GlobalPointerMismatch);
+        Info(slide, 0x421, ((char *)slide, noEntry));
+        EXIT(PK_WARN);   /* programming error, but after we're all done */
+    }
+
+    threadIdTable [scan] = 0;
+    lastScan = scan;
+    free(threadPtrTable[scan]);
+}
+
+
+
+Uz_Globs *getGlobalPointer()
+{
+    int scan=0;
+    ulg tid = GetThreadId();
+
+    while (threadIdTable[scan] != tid && scan < THREADID_ENTRIES)
+        scan++;
+
+/*---------------------------------------------------------------------------
+    There are two things we can do if we can't find the entry:  ignore it or
+    scream.  The most likely reason for it not to be here is the user calling
+    this routine twice.  Since this could cause BIG problems if any globals
+    are accessed after the first call, we'd better scream.
+  ---------------------------------------------------------------------------*/
+
+    if (scan == THREADID_ENTRIES) {
+        ZCONST char *noEntry = LoadFarString(EntryNotFound);
+        fprintf(stderr, noEntry);  /* can't use Info w/o a global pointer */
+        EXIT(PK_ERR);   /* programming error while still working */
+    }
+
+    return threadPtrTable[scan];
+}
+
+#  endif /* ?USETHREADID */
+#endif /* ?REENTRANT */
+
+
+
+Uz_Globs *globalsCtor()
+{
+#ifdef REENTRANT
+    Uz_Globs *pG = (Uz_Globs *)malloc(sizeof(Uz_Globs));
+
+    if (!pG)
+        return (Uz_Globs *)NULL;
+#endif /* REENTRANT */
+
+    /* for REENTRANT version, G is defined as (*pG) */
+
+    memzero(&G, sizeof(Uz_Globs));
+
+#ifndef FUNZIP
+#ifdef CMS_MVS
+    uO.aflag=1;
+    uO.C_flag=1;
+#endif
+
+    uO.lflag=(-1);
+    G.wildzipfn = "";
+    G.pfnames = (char **)fnames;
+    G.pxnames = (char **)&fnames[1];
+    G.pInfo = G.info;
+    G.sol = TRUE;          /* at start of line */
+
+    G.message = UzpMessagePrnt;
+    G.input = UzpInput;           /* not used by anyone at the moment... */
+#if defined(WINDLL) || defined(MACOS)
+    G.mpause = NULL;              /* has scrollbars:  no need for pausing */
+#else
+    G.mpause = UzpMorePause;
+#endif
+    G.decr_passwd = UzpPassword;
+#endif /* !FUNZIP */
+
+#if (!defined(DOS_FLX_H68_OS2_W32) && !defined(AMIGA) && !defined(RISCOS))
+#if (!defined(MACOS) && !defined(ATARI) && !defined(VMS))
+    G.echofd = -1;
+#endif /* !(MACOS || ATARI || VMS) */
+#endif /* !(DOS_FLX_H68_OS2_W32 || AMIGA || RISCOS) */
+
+#ifdef SYSTEM_SPECIFIC_CTOR
+    SYSTEM_SPECIFIC_CTOR(__G);
+#endif
+
+#ifdef REENTRANT
+#ifdef USETHREADID
+    registerGlobalPointer(__G);
+#else
+    GG = &G;
+#endif /* ?USETHREADID */
+#endif /* REENTRANT */
+
+    return &G;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/inflate.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,1305 @@
+/* inflate.c -- put in the public domain by Mark Adler
+   version c16b, 29 March 1998 */
+
+
+/* You can do whatever you like with this source file, though I would
+   prefer that if you modify it and redistribute it that you include
+   comments to that effect with your name and the date.  Thank you.
+
+   History:
+   vers    date          who           what
+   ----  ---------  --------------  ------------------------------------
+    a    ~~ Feb 92  M. Adler        used full (large, one-step) lookup table
+    b1   21 Mar 92  M. Adler        first version with partial lookup tables
+    b2   21 Mar 92  M. Adler        fixed bug in fixed-code blocks
+    b3   22 Mar 92  M. Adler        sped up match copies, cleaned up some
+    b4   25 Mar 92  M. Adler        added prototypes; removed window[] (now
+                                    is the responsibility of unzip.h--also
+                                    changed name to slide[]), so needs diffs
+                                    for unzip.c and unzip.h (this allows
+                                    compiling in the small model on MSDOS);
+                                    fixed cast of q in huft_build();
+    b5   26 Mar 92  M. Adler        got rid of unintended macro recursion.
+    b6   27 Mar 92  M. Adler        got rid of nextbyte() routine.  fixed
+                                    bug in inflate_fixed().
+    c1   30 Mar 92  M. Adler        removed lbits, dbits environment variables.
+                                    changed BMAX to 16 for explode.  Removed
+                                    OUTB usage, and replaced it with flush()--
+                                    this was a 20% speed improvement!  Added
+                                    an explode.c (to replace unimplod.c) that
+                                    uses the huft routines here.  Removed
+                                    register union.
+    c2    4 Apr 92  M. Adler        fixed bug for file sizes a multiple of 32k.
+    c3   10 Apr 92  M. Adler        reduced memory of code tables made by
+                                    huft_build significantly (factor of two to
+                                    three).
+    c4   15 Apr 92  M. Adler        added NOMEMCPY do kill use of memcpy().
+                                    worked around a Turbo C optimization bug.
+    c5   21 Apr 92  M. Adler        added the WSIZE #define to allow reducing
+                                    the 32K window size for specialized
+                                    applications.
+    c6   31 May 92  M. Adler        added some typecasts to eliminate warnings
+    c7   27 Jun 92  G. Roelofs      added some more typecasts (444:  MSC bug).
+    c8    5 Oct 92  J-l. Gailly     added ifdef'd code to deal with PKZIP bug.
+    c9    9 Oct 92  M. Adler        removed a memory error message (~line 416).
+    c10  17 Oct 92  G. Roelofs      changed ULONG/UWORD/byte to ulg/ush/uch,
+                                    removed old inflate, renamed inflate_entry
+                                    to inflate, added Mark's fix to a comment.
+   c10.5 14 Dec 92  M. Adler        fix up error messages for incomplete trees.
+    c11   2 Jan 93  M. Adler        fixed bug in detection of incomplete
+                                    tables, and removed assumption that EOB is
+                                    the longest code (bad assumption).
+    c12   3 Jan 93  M. Adler        make tables for fixed blocks only once.
+    c13   5 Jan 93  M. Adler        allow all zero length codes (pkzip 2.04c
+                                    outputs one zero length code for an empty
+                                    distance tree).
+    c14  12 Mar 93  M. Adler        made inflate.c standalone with the
+                                    introduction of inflate.h.
+   c14b  16 Jul 93  G. Roelofs      added (unsigned) typecast to w at 470.
+   c14c  19 Jul 93  J. Bush         changed v[N_MAX], l[288], ll[28x+3x] arrays
+                                    to static for Amiga.
+   c14d  13 Aug 93  J-l. Gailly     de-complicatified Mark's c[*p++]++ thing.
+   c14e   8 Oct 93  G. Roelofs      changed memset() to memzero().
+   c14f  22 Oct 93  G. Roelofs      renamed quietflg to qflag; made Trace()
+                                    conditional; added inflate_free().
+   c14g  28 Oct 93  G. Roelofs      changed l/(lx+1) macro to pointer (Cray bug)
+   c14h   7 Dec 93  C. Ghisler      huft_build() optimizations.
+   c14i   9 Jan 94  A. Verheijen    set fixed_t{d,l} to NULL after freeing;
+                    G. Roelofs      check NEXTBYTE macro for EOF.
+   c14j  23 Jan 94  G. Roelofs      removed Ghisler "optimizations"; ifdef'd
+                                    EOF check.
+   c14k  27 Feb 94  G. Roelofs      added some typecasts to avoid warnings.
+   c14l   9 Apr 94  G. Roelofs      fixed split comments on preprocessor lines
+                                    to avoid bug in Encore compiler.
+   c14m   7 Jul 94  P. Kienitz      modified to allow assembler version of
+                                    inflate_codes() (define ASM_INFLATECODES)
+   c14n  22 Jul 94  G. Roelofs      changed fprintf to macro for DLL versions
+   c14o  23 Aug 94  C. Spieler      added a newline to a debug statement;
+                    G. Roelofs      added another typecast to avoid MSC warning
+   c14p   4 Oct 94  G. Roelofs      added (voidp *) cast to free() argument
+   c14q  30 Oct 94  G. Roelofs      changed fprintf macro to MESSAGE()
+   c14r   1 Nov 94  G. Roelofs      fixed possible redefinition of CHECK_EOF
+   c14s   7 May 95  S. Maxwell      OS/2 DLL globals stuff incorporated;
+                    P. Kienitz      "fixed" ASM_INFLATECODES macro/prototype
+   c14t  18 Aug 95  G. Roelofs      added UZinflate() to use zlib functions;
+                                    changed voidp to zvoid; moved huft_build()
+                                    and huft_free() to end of file
+   c14u   1 Oct 95  G. Roelofs      moved G into definition of MESSAGE macro
+   c14v   8 Nov 95  P. Kienitz      changed ASM_INFLATECODES to use a regular
+                                    call with __G__ instead of a macro
+    c15   3 Aug 96  M. Adler        fixed bomb-bug on random input data (Adobe)
+   c15b  24 Aug 96  M. Adler        more fixes for random input data
+   c15c  28 Mar 97  G. Roelofs      changed USE_ZLIB fatal exit code from
+                                    PK_MEM2 to PK_MEM3
+    c16  20 Apr 97  J. Altman       added memzero(v[]) in huft_build()
+   c16b  29 Mar 98  C. Spieler      modified DLL code for slide redirection
+ */
+
+
+/*
+   Inflate deflated (PKZIP's method 8 compressed) data.  The compression
+   method searches for as much of the current string of bytes (up to a
+   length of 258) in the previous 32K bytes.  If it doesn't find any
+   matches (of at least length 3), it codes the next byte.  Otherwise, it
+   codes the length of the matched string and its distance backwards from
+   the current position.  There is a single Huffman code that codes both
+   single bytes (called "literals") and match lengths.  A second Huffman
+   code codes the distance information, which follows a length code.  Each
+   length or distance code actually represents a base value and a number
+   of "extra" (sometimes zero) bits to get to add to the base value.  At
+   the end of each deflated block is a special end-of-block (EOB) literal/
+   length code.  The decoding process is basically: get a literal/length
+   code; if EOB then done; if a literal, emit the decoded byte; if a
+   length then get the distance and emit the referred-to bytes from the
+   sliding window of previously emitted data.
+
+   There are (currently) three kinds of inflate blocks: stored, fixed, and
+   dynamic.  The compressor outputs a chunk of data at a time and decides
+   which method to use on a chunk-by-chunk basis.  A chunk might typically
+   be 32K to 64K, uncompressed.  If the chunk is uncompressible, then the
+   "stored" method is used.  In this case, the bytes are simply stored as
+   is, eight bits per byte, with none of the above coding.  The bytes are
+   preceded by a count, since there is no longer an EOB code.
+
+   If the data are compressible, then either the fixed or dynamic methods
+   are used.  In the dynamic method, the compressed data are preceded by
+   an encoding of the literal/length and distance Huffman codes that are
+   to be used to decode this block.  The representation is itself Huffman
+   coded, and so is preceded by a description of that code.  These code
+   descriptions take up a little space, and so for small blocks, there is
+   a predefined set of codes, called the fixed codes.  The fixed method is
+   used if the block ends up smaller that way (usually for quite small
+   chunks); otherwise the dynamic method is used.  In the latter case, the
+   codes are customized to the probabilities in the current block and so
+   can code it much better than the pre-determined fixed codes can.
+
+   The Huffman codes themselves are decoded using a multi-level table
+   lookup, in order to maximize the speed of decoding plus the speed of
+   building the decoding tables.  See the comments below that precede the
+   lbits and dbits tuning parameters.
+
+   GRR:  return values(?)
+           0  OK
+           1  incomplete table
+           2  bad input
+           3  not enough memory
+ */
+
+
+/*
+   Notes beyond the 1.93a appnote.txt:
+
+   1. Distance pointers never point before the beginning of the output
+      stream.
+   2. Distance pointers can point back across blocks, up to 32k away.
+   3. There is an implied maximum of 7 bits for the bit length table and
+      15 bits for the actual data.
+   4. If only one code exists, then it is encoded using one bit.  (Zero
+      would be more efficient, but perhaps a little confusing.)  If two
+      codes exist, they are coded using one bit each (0 and 1).
+   5. There is no way of sending zero distance codes--a dummy must be
+      sent if there are none.  (History: a pre 2.0 version of PKZIP would
+      store blocks with no distance codes, but this was discovered to be
+      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
+      zero distance codes, which is sent as one code of zero bits in
+      length.
+   6. There are up to 286 literal/length codes.  Code 256 represents the
+      end-of-block.  Note however that the static length tree defines
+      288 codes just to fill out the Huffman codes.  Codes 286 and 287
+      cannot be used though, since there is no length base or extra bits
+      defined for them.  Similarily, there are up to 30 distance codes.
+      However, static trees define 32 codes (all 5 bits) to fill out the
+      Huffman codes, but the last two had better not show up in the data.
+   7. Unzip can check dynamic Huffman blocks for complete code sets.
+      The exception is that a single code would not be complete (see #4).
+   8. The five bits following the block type is really the number of
+      literal codes sent minus 257.
+   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+      (1+6+6).  Therefore, to output three times the length, you output
+      three codes (1+1+1), whereas to output four times the same length,
+      you only need two codes (1+3).  Hmm.
+  10. In the tree reconstruction algorithm, Code = Code + Increment
+      only if BitLength(i) is not zero.  (Pretty obvious.)
+  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
+  12. Note: length code 284 can represent 227-258, but length code 285
+      really is 258.  The last length deserves its own, short code
+      since it gets used a lot in very redundant files.  The length
+      258 is special since 258 - 3 (the min match length) is 255.
+  13. The literal/length and distance code bit lengths are read as a
+      single stream of lengths.  It is possible (and advantageous) for
+      a repeat code (16, 17, or 18) to go across the boundary between
+      the two sets of lengths.
+ */
+
+
+#define PKZIP_BUG_WORKAROUND    /* PKZIP 1.93a problem--live with it */
+
+/*
+    inflate.h must supply the uch slide[WSIZE] array, the zvoid typedef
+    (void if (void *) is accepted, else char) and the NEXTBYTE,
+    FLUSH() and memzero macros.  If the window size is not 32K, it
+    should also define WSIZE.  If INFMOD is defined, it can include
+    compiled functions to support the NEXTBYTE and/or FLUSH() macros.
+    There are defaults for NEXTBYTE and FLUSH() below for use as
+    examples of what those functions need to do.  Normally, you would
+    also want FLUSH() to compute a crc on the data.  inflate.h also
+    needs to provide these typedefs:
+
+        typedef unsigned char uch;
+        typedef unsigned short ush;
+        typedef unsigned long ulg;
+
+    This module uses the external functions malloc() and free() (and
+    probably memset() or bzero() in the memzero() macro).  Their
+    prototypes are normally found in <string.h> and <stdlib.h>.
+ */
+
+/* #define DEBUG */
+#define INFMOD          /* tell inflate.h to include code to be compiled */
+#include "inflate.h"
+
+
+#ifndef WSIZE           /* default is 32K */
+#  define WSIZE 0x8000  /* window size--must be a power of two, and at least */
+#endif                  /* 32K for zip's deflate method */
+
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+#  define wsize G._wsize    /* wsize is a variable */
+#else
+#  define wsize WSIZE       /* wsize is a constant */
+#endif
+
+
+#ifndef NEXTBYTE        /* default is to simply get a byte from stdin */
+#  define NEXTBYTE getchar()
+#endif
+
+#ifndef MESSAGE   /* only used twice, for fixed strings--NOT general-purpose */
+#  define MESSAGE(str,len,flag)  pipeit((char *)(str))
+#endif
+
+#ifndef FLUSH           /* default is to simply write the buffer to stdout */
+#  define FLUSH(n) fwrite(redirSlide, 1, n, stdout)  /* return value not used */
+#endif
+/* Warning: the fwrite above might not work on 16-bit compilers, since
+   0x8000 might be interpreted as -32,768 by the library function. */
+
+#ifndef Trace
+#  ifdef DEBUG
+#    define Trace(x) fprintf x
+#  else
+#    define Trace(x)
+#  endif
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+#ifdef USE_ZLIB
+
+
+/*
+   GRR:  return values for both original inflate() and UZinflate()
+           0  OK
+           1  incomplete table(?)
+           2  bad input
+           3  not enough memory
+ */
+
+/**************************/
+/*  Function UZinflate()  */
+/**************************/
+
+int UZinflate(__G)   /* decompress an inflated entry using the zlib routines */
+    __GDEF
+{
+    int err=Z_OK;
+
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+    if (G.redirect_slide)
+        wsize = G.redirect_size, redirSlide = G.redirect_buffer;
+    else
+        wsize = WSIZE, redirSlide = slide;
+#endif
+
+    G.dstrm.next_out = redirSlide;
+    G.dstrm.avail_out = wsize;
+
+    G.dstrm.next_in = G.inptr;
+    G.dstrm.avail_in = G.incnt;
+
+    if (!G.inflInit) {
+        unsigned i;
+        int windowBits;
+
+        /* only need to test this stuff once */
+        if (zlib_version[0] != ZLIB_VERSION[0]) {
+            Info(slide, 0x21, ((char *)slide,
+              "error:  incompatible zlib version (expected %s, found %s)\n",
+              ZLIB_VERSION, zlib_version));
+            return 3;
+        } else if (strcmp(zlib_version, ZLIB_VERSION) != 0)
+            Info(slide, 0x21, ((char *)slide,
+              "warning:  different zlib version (expected %s, using %s)\n",
+              ZLIB_VERSION, zlib_version));
+
+        /* windowBits = log2(wsize) */
+        for (i = ((unsigned)wsize * 2 - 1), windowBits = 0;
+             !(i & 1);  i >>= 1, ++windowBits);
+        if ((unsigned)windowBits > (unsigned)15)
+            windowBits = 15;
+        else if (windowBits < 8)
+            windowBits = 8;
+
+        G.dstrm.zalloc = (alloc_func)Z_NULL;
+        G.dstrm.zfree = (free_func)Z_NULL;
+
+        Trace((stderr, "initializing inflate()\n"));
+        err = inflateInit2(&G.dstrm, -windowBits);
+
+        if (err == Z_MEM_ERROR)
+            return 3;
+        else if (err != Z_OK)
+            Trace((stderr, "oops!  (inflateInit2() err = %d)\n", err));
+        G.inflInit = 1;
+    }
+
+#ifdef FUNZIP
+    while (err != Z_STREAM_END) {
+#else /* !FUNZIP */
+    while (G.csize > 0) {
+        Trace((stderr, "first loop:  G.csize = %ld\n", G.csize));
+#endif /* ?FUNZIP */
+        while (G.dstrm.avail_out > 0) {
+            err = inflate(&G.dstrm, Z_PARTIAL_FLUSH);
+
+            if (err == Z_DATA_ERROR)
+                return 2;
+            else if (err == Z_MEM_ERROR)
+                return 3;
+            else if (err != Z_OK && err != Z_STREAM_END)
+                Trace((stderr, "oops!  (inflate(first loop) err = %d)\n", err));
+
+#ifdef FUNZIP
+            if (err == Z_STREAM_END)    /* "END-of-entry-condition" ? */
+#else /* !FUNZIP */
+            if (G.csize <= 0L)          /* "END-of-entry-condition" ? */
+#endif /* ?FUNZIP */
+                break;
+
+            if (G.dstrm.avail_in <= 0) {
+                if (fillinbuf(__G) == 0)
+                    return 2;  /* no "END-condition" yet, but no more data */
+
+                G.dstrm.next_in = G.inptr;
+                G.dstrm.avail_in = G.incnt;
+            }
+            Trace((stderr, "     avail_in = %d\n", G.dstrm.avail_in));
+        }
+        FLUSH(wsize - G.dstrm.avail_out);   /* flush slide[] */
+        Trace((stderr, "inside loop:  flushing %ld bytes (ptr diff = %ld)\n",
+          (long)(wsize - G.dstrm.avail_out),
+          (long)(G.dstrm.next_out-(Bytef *)redirSlide)));
+        G.dstrm.next_out = redirSlide;
+        G.dstrm.avail_out = wsize;
+    }
+
+    /* no more input, so loop until we have all output */
+    Trace((stderr, "beginning final loop:  err = %d\n", err));
+    while (err != Z_STREAM_END) {
+        err = inflate(&G.dstrm, Z_PARTIAL_FLUSH);
+        if (err == Z_DATA_ERROR)
+            return 2;
+        else if (err == Z_MEM_ERROR)
+            return 3;
+        else if (err == Z_BUF_ERROR) {              /* DEBUG */
+            Trace((stderr, "zlib inflate() did not detect stream end (%s, %s)\n"
+              , G.zipfn, G.filename));
+            break;
+        } else if (err != Z_OK && err != Z_STREAM_END) {
+            Trace((stderr, "oops!  (inflate(final loop) err = %d)\n", err));
+            DESTROYGLOBALS()
+            EXIT(PK_MEM3);
+        }
+        FLUSH(wsize - G.dstrm.avail_out);   /* final flush of slide[] */
+        Trace((stderr, "final loop:  flushing %ld bytes (ptr diff = %ld)\n",
+          (long)(wsize - G.dstrm.avail_out),
+          (long)(G.dstrm.next_out-(Bytef *)redirSlide)));
+        G.dstrm.next_out = redirSlide;
+        G.dstrm.avail_out = wsize;
+    }
+    Trace((stderr, "total in = %ld, total out = %ld\n", G.dstrm.total_in,
+      G.dstrm.total_out));
+
+    G.inptr = (uch *)G.dstrm.next_in;
+    G.incnt = (G.inbuf + INBUFSIZ) - G.inptr;  /* reset for other routines */
+
+    err = inflateReset(&G.dstrm);
+    if (err != Z_OK)
+        Trace((stderr, "oops!  (inflateReset() err = %d)\n", err));
+
+    return 0;
+}
+
+
+/*---------------------------------------------------------------------------*/
+#else /* !USE_ZLIB */
+
+
+/* Function prototypes */
+#ifndef OF
+#  ifdef __STDC__
+#    define OF(a) a
+#  else
+#    define OF(a) ()
+#  endif
+#endif /* !OF */
+int inflate_codes OF((__GPRO__ struct huft *tl, struct huft *td,
+                      int bl, int bd));
+static int inflate_stored OF((__GPRO));
+static int inflate_fixed OF((__GPRO));
+static int inflate_dynamic OF((__GPRO));
+static int inflate_block OF((__GPRO__ int *e));
+
+
+/* The inflate algorithm uses a sliding 32K byte window on the uncompressed
+   stream to find repeated byte strings.  This is implemented here as a
+   circular buffer.  The index is updated simply by incrementing and then
+   and'ing with 0x7fff (32K-1). */
+/* It is left to other modules to supply the 32K area.  It is assumed
+   to be usable as if it were declared "uch slide[32768];" or as just
+   "uch *slide;" and then malloc'ed in the latter case.  The definition
+   must be in unzip.h, included above. */
+
+
+/* unsigned wp;  moved to globals.h */     /* current position in slide */
+
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+static ZCONST unsigned border[] = { /* Order of the bit length code lengths */
+        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+static ZCONST ush cplens[] = {  /* Copy lengths for literal codes 257..285 */
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+        /* note: see note #13 above about the 258 in this list. */
+static ZCONST ush cplext[] = {  /* Extra bits for literal codes 257..285 */
+        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, 99, 99}; /* 99==invalid */
+static ZCONST ush cpdist[] = {  /* Copy offsets for distance codes 0..29 */
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+        8193, 12289, 16385, 24577};
+static ZCONST ush cpdext[] = {  /* Extra bits for distance codes */
+        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};
+
+
+/* moved to consts.h (included in unzip.c), resp. funzip.c */
+#if 0
+/* And'ing with mask_bits[n] masks the lower n bits */
+ZCONST ush near mask_bits[] = {
+    0x0000,
+    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+#endif /* 0 */
+
+
+/* Macros for inflate() bit peeking and grabbing.
+   The usage is:
+
+        NEEDBITS(j)
+        x = b & mask_bits[j];
+        DUMPBITS(j)
+
+   where NEEDBITS makes sure that b has at least j bits in it, and
+   DUMPBITS removes the bits from b.  The macros use the variable k
+   for the number of bits in b.  Normally, b and k are register
+   variables for speed and are initialized at the begining of a
+   routine that uses these macros from a global bit buffer and count.
+
+   In order to not ask for more bits than there are in the compressed
+   stream, the Huffman tables are constructed to only ask for just
+   enough bits to make up the end-of-block code (value 256).  Then no
+   bytes need to be "returned" to the buffer at the end of the last
+   block.  See the huft_build() routine.
+ */
+
+/* These have been moved to globals.h */
+#if 0
+ulg bb;                         /* bit buffer */
+unsigned bk;                    /* bits in bit buffer */
+#endif
+
+#ifndef CHECK_EOF
+#  define CHECK_EOF   /* default as of 5.13/5.2 */
+#endif
+
+#ifndef CHECK_EOF
+#  define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<<k;k+=8;}}
+#else
+#  define NEEDBITS(n) {while(k<(n)){int c=NEXTBYTE;if(c==EOF)return 1;\
+    b|=((ulg)c)<<k;k+=8;}}
+#endif                      /* Piet Plomp:  change "return 1" to "break" */
+
+#define DUMPBITS(n) {b>>=(n);k-=(n);}
+
+
+/*
+   Huffman code decoding is performed using a multi-level table lookup.
+   The fastest way to decode is to simply build a lookup table whose
+   size is determined by the longest code.  However, the time it takes
+   to build this table can also be a factor if the data being decoded
+   are not very long.  The most common codes are necessarily the
+   shortest codes, so those codes dominate the decoding time, and hence
+   the speed.  The idea is you can have a shorter table that decodes the
+   shorter, more probable codes, and then point to subsidiary tables for
+   the longer codes.  The time it costs to decode the longer codes is
+   then traded against the time it takes to make longer tables.
+
+   This results of this trade are in the variables lbits and dbits
+   below.  lbits is the number of bits the first level table for literal/
+   length codes can decode in one step, and dbits is the same thing for
+   the distance codes.  Subsequent tables are also less than or equal to
+   those sizes.  These values may be adjusted either when all of the
+   codes are shorter than that, in which case the longest code length in
+   bits is used, or when the shortest code is *longer* than the requested
+   table size, in which case the length of the shortest code in bits is
+   used.
+
+   There are two different values for the two tables, since they code a
+   different number of possibilities each.  The literal/length table
+   codes 286 possible values, or in a flat code, a little over eight
+   bits.  The distance table codes 30 possible values, or a little less
+   than five bits, flat.  The optimum values for speed end up being
+   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+   The optimum values may differ though from machine to machine, and
+   possibly even between compilers.  Your mileage may vary.
+ */
+
+
+static ZCONST int lbits = 9;    /* bits in base literal/length lookup table */
+static ZCONST int dbits = 6;    /* bits in base distance lookup table */
+
+
+#ifndef ASM_INFLATECODES
+
+int inflate_codes(__G__ tl, td, bl, bd)
+     __GDEF
+struct huft *tl, *td;   /* literal/length and distance decoder tables */
+int bl, bd;             /* number of bits decoded by tl[] and td[] */
+/* inflate (decompress) the codes in a deflated (compressed) block.
+   Return an error code or zero if it all goes ok. */
+{
+  register unsigned e;  /* table entry flag/number of extra bits */
+  unsigned n, d;        /* length and index for copy */
+  unsigned w;           /* current window position */
+  struct huft *t;       /* pointer to table entry */
+  unsigned ml, md;      /* masks for bl and bd bits */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+
+
+  /* make local copies of globals */
+  b = G.bb;                       /* initialize bit buffer */
+  k = G.bk;
+  w = G.wp;                       /* initialize window position */
+
+
+  /* inflate the coded data */
+  ml = mask_bits[bl];           /* precompute masks for speed */
+  md = mask_bits[bd];
+  while (1)                     /* do until end of block */
+  {
+    NEEDBITS((unsigned)bl)
+    if ((e = (t = tl + ((unsigned)b & ml))->e) > 16)
+      do {
+        if (e == 99)
+          return 1;
+        DUMPBITS(t->b)
+        e -= 16;
+        NEEDBITS(e)
+      } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
+    DUMPBITS(t->b)
+    if (e == 16)                /* then it's a literal */
+    {
+      redirSlide[w++] = (uch)t->v.n;
+      if (w == wsize)
+      {
+        FLUSH(w);
+        w = 0;
+      }
+    }
+    else                        /* it's an EOB or a length */
+    {
+      /* exit if end of block */
+      if (e == 15)
+        break;
+
+      /* get length of block to copy */
+      NEEDBITS(e)
+      n = t->v.n + ((unsigned)b & mask_bits[e]);
+      DUMPBITS(e);
+
+      /* decode distance of block to copy */
+      NEEDBITS((unsigned)bd)
+      if ((e = (t = td + ((unsigned)b & md))->e) > 16)
+        do {
+          if (e == 99)
+            return 1;
+          DUMPBITS(t->b)
+          e -= 16;
+          NEEDBITS(e)
+        } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
+      DUMPBITS(t->b)
+      NEEDBITS(e)
+      d = w - t->v.n - ((unsigned)b & mask_bits[e]);
+      DUMPBITS(e)
+
+      /* do the copy */
+      do {
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+        if (G.redirect_slide) {/* &= w/ wsize unnecessary & wrong if redirect */
+          if (d >= wsize)
+            return 1;           /* invalid compressed data */
+          n -= (e = (e = wsize - (d > w ? d : w)) > n ? n : e);
+        }
+        else
+#endif
+          n -= (e = (e = wsize - ((d &= wsize-1) > w ? d : w)) > n ? n : e);
+#ifndef NOMEMCPY
+        if (w - d >= e)         /* (this test assumes unsigned comparison) */
+        {
+          memcpy(redirSlide + w, redirSlide + d, e);
+          w += e;
+          d += e;
+        }
+        else                    /* do it slowly to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+          do {
+            redirSlide[w++] = redirSlide[d++];
+          } while (--e);
+        if (w == wsize)
+        {
+          FLUSH(w);
+          w = 0;
+        }
+      } while (n);
+    }
+  }
+
+
+  /* restore the globals from the locals */
+  G.wp = w;                       /* restore global window pointer */
+  G.bb = b;                       /* restore global bit buffer */
+  G.bk = k;
+
+
+  /* done */
+  return 0;
+}
+
+#endif /* ASM_INFLATECODES */
+
+
+
+static int inflate_stored(__G)
+     __GDEF
+/* "decompress" an inflated type 0 (stored) block. */
+{
+  unsigned n;           /* number of bytes in block */
+  unsigned w;           /* current window position */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+
+
+  /* make local copies of globals */
+  Trace((stderr, "\nstored block"));
+  b = G.bb;                       /* initialize bit buffer */
+  k = G.bk;
+  w = G.wp;                       /* initialize window position */
+
+
+  /* go to byte boundary */
+  n = k & 7;
+  DUMPBITS(n);
+
+
+  /* get the length and its complement */
+  NEEDBITS(16)
+  n = ((unsigned)b & 0xffff);
+  DUMPBITS(16)
+  NEEDBITS(16)
+  if (n != (unsigned)((~b) & 0xffff))
+    return 1;                   /* error in compressed data */
+  DUMPBITS(16)
+
+
+  /* read and output the compressed data */
+  while (n--)
+  {
+    NEEDBITS(8)
+    redirSlide[w++] = (uch)b;
+    if (w == wsize)
+    {
+      FLUSH(w);
+      w = 0;
+    }
+    DUMPBITS(8)
+  }
+
+
+  /* restore the globals from the locals */
+  G.wp = w;                       /* restore global window pointer */
+  G.bb = b;                       /* restore global bit buffer */
+  G.bk = k;
+  return 0;
+}
+
+
+/* Globals for literal tables (built once) */
+/* Moved to globals.h                      */
+#if 0
+struct huft *fixed_tl = (struct huft *)NULL;
+struct huft *fixed_td;
+int fixed_bl, fixed_bd;
+#endif
+
+static int inflate_fixed(__G)
+     __GDEF
+/* decompress an inflated type 1 (fixed Huffman codes) block.  We should
+   either replace this with a custom decoder, or at least precompute the
+   Huffman tables. */
+{
+  /* if first time, set up tables for fixed blocks */
+  Trace((stderr, "\nliteral block"));
+  if (G.fixed_tl == (struct huft *)NULL)
+  {
+    int i;                /* temporary variable */
+    unsigned l[288];      /* length list for huft_build */
+
+    /* literal table */
+    for (i = 0; i < 144; i++)
+      l[i] = 8;
+    for (; i < 256; i++)
+      l[i] = 9;
+    for (; i < 280; i++)
+      l[i] = 7;
+    for (; i < 288; i++)          /* make a complete, but wrong code set */
+      l[i] = 8;
+    G.fixed_bl = 7;
+    if ((i = huft_build(__G__ l, 288, 257, cplens, cplext,
+                        &G.fixed_tl, &G.fixed_bl)) != 0)
+    {
+      G.fixed_tl = (struct huft *)NULL;
+      return i;
+    }
+
+    /* distance table */
+    for (i = 0; i < 30; i++)      /* make an incomplete code set */
+      l[i] = 5;
+    G.fixed_bd = 5;
+    if ((i = huft_build(__G__ l, 30, 0, cpdist, cpdext,
+                        &G.fixed_td, &G.fixed_bd)) > 1)
+    {
+      huft_free(G.fixed_tl);
+      G.fixed_tl = (struct huft *)NULL;
+      return i;
+    }
+  }
+
+  /* decompress until an end-of-block code */
+  return inflate_codes(__G__ G.fixed_tl, G.fixed_td,
+                             G.fixed_bl, G.fixed_bd) != 0;
+}
+
+
+
+static int inflate_dynamic(__G)
+  __GDEF
+/* decompress an inflated type 2 (dynamic Huffman codes) block. */
+{
+  int i;                /* temporary variables */
+  unsigned j;
+  unsigned l;           /* last length */
+  unsigned m;           /* mask for bit lengths table */
+  unsigned n;           /* number of lengths to get */
+  struct huft *tl;      /* literal/length code table */
+  struct huft *td;      /* distance code table */
+  int bl;               /* lookup bits for tl */
+  int bd;               /* lookup bits for td */
+  unsigned nb;          /* number of bit length codes */
+  unsigned nl;          /* number of literal/length codes */
+  unsigned nd;          /* number of distance codes */
+#ifdef PKZIP_BUG_WORKAROUND
+  unsigned ll[288+32]; /* literal/length and distance code lengths */
+#else
+  unsigned ll[286+30]; /* literal/length and distance code lengths */
+#endif
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+
+
+  /* make local bit buffer */
+  Trace((stderr, "\ndynamic block"));
+  b = G.bb;
+  k = G.bk;
+
+
+  /* read in table lengths */
+  NEEDBITS(5)
+  nl = 257 + ((unsigned)b & 0x1f);      /* number of literal/length codes */
+  DUMPBITS(5)
+  NEEDBITS(5)
+  nd = 1 + ((unsigned)b & 0x1f);        /* number of distance codes */
+  DUMPBITS(5)
+  NEEDBITS(4)
+  nb = 4 + ((unsigned)b & 0xf);         /* number of bit length codes */
+  DUMPBITS(4)
+#ifdef PKZIP_BUG_WORKAROUND
+  if (nl > 288 || nd > 32)
+#else
+  if (nl > 286 || nd > 30)
+#endif
+    return 1;                   /* bad lengths */
+
+
+  /* read in bit-length-code lengths */
+  for (j = 0; j < nb; j++)
+  {
+    NEEDBITS(3)
+    ll[border[j]] = (unsigned)b & 7;
+    DUMPBITS(3)
+  }
+  for (; j < 19; j++)
+    ll[border[j]] = 0;
+
+
+  /* build decoding table for trees--single level, 7 bit lookup */
+  bl = 7;
+  i = huft_build(__G__ ll, 19, 19, NULL, NULL, &tl, &bl);
+  if (bl == 0)                        /* no bit lengths */
+    i = 1;
+  if (i)
+  {
+    if (i == 1)
+      huft_free(tl);
+    return i;                   /* incomplete code set */
+  }
+
+
+  /* read in literal and distance code lengths */
+  n = nl + nd;
+  m = mask_bits[bl];
+  i = l = 0;
+  while ((unsigned)i < n)
+  {
+    NEEDBITS((unsigned)bl)
+    j = (td = tl + ((unsigned)b & m))->b;
+    DUMPBITS(j)
+    j = td->v.n;
+    if (j < 16)                 /* length of code in bits (0..15) */
+      ll[i++] = l = j;          /* save last length in l */
+    else if (j == 16)           /* repeat last length 3 to 6 times */
+    {
+      NEEDBITS(2)
+      j = 3 + ((unsigned)b & 3);
+      DUMPBITS(2)
+      if ((unsigned)i + j > n)
+        return 1;
+      while (j--)
+        ll[i++] = l;
+    }
+    else if (j == 17)           /* 3 to 10 zero length codes */
+    {
+      NEEDBITS(3)
+      j = 3 + ((unsigned)b & 7);
+      DUMPBITS(3)
+      if ((unsigned)i + j > n)
+        return 1;
+      while (j--)
+        ll[i++] = 0;
+      l = 0;
+    }
+    else                        /* j == 18: 11 to 138 zero length codes */
+    {
+      NEEDBITS(7)
+      j = 11 + ((unsigned)b & 0x7f);
+      DUMPBITS(7)
+      if ((unsigned)i + j > n)
+        return 1;
+      while (j--)
+        ll[i++] = 0;
+      l = 0;
+    }
+  }
+
+
+  /* free decoding table for trees */
+  huft_free(tl);
+
+
+  /* restore the global bit buffer */
+  G.bb = b;
+  G.bk = k;
+
+
+  /* build the decoding tables for literal/length and distance codes */
+  bl = lbits;
+  i = huft_build(__G__ ll, nl, 257, cplens, cplext, &tl, &bl);
+  if (bl == 0)                        /* no literals or lengths */
+    i = 1;
+  if (i)
+  {
+    if (i == 1) {
+      if (!uO.qflag)
+        MESSAGE((uch *)"(incomplete l-tree)  ", 21L, 1);
+      huft_free(tl);
+    }
+    return i;                   /* incomplete code set */
+  }
+  bd = dbits;
+  i = huft_build(__G__ ll + nl, nd, 0, cpdist, cpdext, &td, &bd);
+  if (bd == 0 && nl > 257)    /* lengths but no distances */
+  {
+    if (!uO.qflag)
+      MESSAGE((uch *)"(incomplete d-tree)  ", 21L, 1);
+    huft_free(tl);
+    return 1;
+  }
+  if (i == 1) {
+#ifdef PKZIP_BUG_WORKAROUND
+    i = 0;
+#else
+    if (!uO.qflag)
+      MESSAGE((uch *)"(incomplete d-tree)  ", 21L, 1);
+    huft_free(td);
+#endif
+  }
+  if (i)
+  {
+    huft_free(tl);
+    return i;
+  }
+
+
+  /* decompress until an end-of-block code */
+  if (inflate_codes(__G__ tl, td, bl, bd))
+    return 1;
+
+
+  /* free the decoding tables, return */
+  huft_free(tl);
+  huft_free(td);
+  return 0;
+}
+
+
+
+static int inflate_block(__G__ e)
+  __GDEF
+  int *e;               /* last block flag */
+/* decompress an inflated block */
+{
+  unsigned t;           /* block type */
+  register ulg b;       /* bit buffer */
+  register unsigned k;  /* number of bits in bit buffer */
+
+
+  /* make local bit buffer */
+  b = G.bb;
+  k = G.bk;
+
+
+  /* read in last block bit */
+  NEEDBITS(1)
+  *e = (int)b & 1;
+  DUMPBITS(1)
+
+
+  /* read in block type */
+  NEEDBITS(2)
+  t = (unsigned)b & 3;
+  DUMPBITS(2)
+
+
+  /* restore the global bit buffer */
+  G.bb = b;
+  G.bk = k;
+
+
+  /* inflate that block type */
+  if (t == 2)
+    return inflate_dynamic(__G);
+  if (t == 0)
+    return inflate_stored(__G);
+  if (t == 1)
+    return inflate_fixed(__G);
+
+
+  /* bad block type */
+  return 2;
+}
+
+
+
+int inflate(__G)
+     __GDEF
+/* decompress an inflated entry */
+{
+  int e;                /* last block flag */
+  int r;                /* result code */
+#ifdef DEBUG
+  unsigned h = 0;       /* maximum struct huft's malloc'ed */
+#endif
+
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+  if (G.redirect_slide)
+    wsize = G.redirect_size, redirSlide = G.redirect_buffer;
+  else
+    wsize = WSIZE, redirSlide = slide;   /* how they're #defined if !DLL */
+#endif
+
+  /* initialize window, bit buffer */
+  G.wp = 0;
+  G.bk = 0;
+  G.bb = 0;
+
+
+  /* decompress until the last block */
+  do {
+#ifdef DEBUG
+    G.hufts = 0;
+#endif
+    if ((r = inflate_block(__G__ &e)) != 0)
+      return r;
+#ifdef DEBUG
+    if (G.hufts > h)
+      h = G.hufts;
+#endif
+  } while (!e);
+
+
+  /* flush out redirSlide */
+  FLUSH(G.wp);
+
+
+  /* return success */
+  Trace((stderr, "\n%u bytes in Huffman tables (%d/entry)\n",
+         h * sizeof(struct huft), sizeof(struct huft)));
+  return 0;
+}
+
+
+
+int inflate_free(__G)
+     __GDEF
+{
+  if (G.fixed_tl != (struct huft *)NULL)
+  {
+    huft_free(G.fixed_td);
+    huft_free(G.fixed_tl);
+    G.fixed_td = G.fixed_tl = (struct huft *)NULL;
+  }
+  return 0;
+}
+
+#endif /* ?USE_ZLIB */
+
+
+/*
+ * GRR:  moved huft_build() and huft_free() down here; used by explode()
+ *       and fUnZip regardless of whether USE_ZLIB defined or not
+ */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
+#define BMAX 16         /* maximum bit length of any code (16 for explode) */
+#define N_MAX 288       /* maximum number of codes in any set */
+
+
+int huft_build(__G__ b, n, s, d, e, t, m)
+  __GDEF
+  ZCONST unsigned *b;   /* code lengths in bits (all assumed <= BMAX) */
+  unsigned n;           /* number of codes (assumed <= N_MAX) */
+  unsigned s;           /* number of simple-valued codes (0..s-1) */
+  ZCONST ush *d;        /* list of base values for non-simple codes */
+  ZCONST ush *e;        /* list of extra bits for non-simple codes */
+  struct huft **t;      /* result: starting table */
+  int *m;               /* maximum lookup bits, returns actual */
+/* Given a list of code lengths and a maximum table size, make a set of
+   tables to decode that set of codes.  Return zero on success, one if
+   the given code set is incomplete (the tables are still built in this
+   case), two if the input is invalid (all zero length codes or an
+   oversubscribed set of lengths), and three if not enough memory.
+   The code with value 256 is special, and the tables are constructed
+   so that no bits beyond that code are fetched when that code is
+   decoded. */
+{
+  unsigned a;                   /* counter for codes of length k */
+  unsigned c[BMAX+1];           /* bit length count table */
+  unsigned el;                  /* length of EOB code (value 256) */
+  unsigned f;                   /* i repeats in table every f entries */
+  int g;                        /* maximum code length */
+  int h;                        /* table level */
+  register unsigned i;          /* counter, current code */
+  register unsigned j;          /* counter */
+  register int k;               /* number of bits in current code */
+  int lx[BMAX+1];               /* memory for l[-1..BMAX-1] */
+  int *l = lx+1;                /* stack of bits per table */
+  register unsigned *p;         /* pointer into c[], b[], or v[] */
+  register struct huft *q;      /* points to current table */
+  struct huft r;                /* table entry for structure assignment */
+  struct huft *u[BMAX];         /* table stack */
+  unsigned v[N_MAX];            /* values in order of bit length */
+  register int w;               /* bits before this table == (l * h) */
+  unsigned x[BMAX+1];           /* bit offsets, then code stack */
+  unsigned *xp;                 /* pointer into x */
+  int y;                        /* number of dummy codes added */
+  unsigned z;                   /* number of entries in current table */
+
+
+  /* Generate counts for each bit length */
+  el = n > 256 ? b[256] : BMAX; /* set length of EOB code, if any */
+  memzero((char *)c, sizeof(c));
+  p = (unsigned *)b;  i = n;
+  do {
+    c[*p]++; p++;               /* assume all entries <= BMAX */
+  } while (--i);
+  if (c[0] == n)                /* null input--all zero length codes */
+  {
+    *t = (struct huft *)NULL;
+    *m = 0;
+    return 0;
+  }
+
+
+  /* Find minimum and maximum length, bound *m by those */
+  for (j = 1; j <= BMAX; j++)
+    if (c[j])
+      break;
+  k = j;                        /* minimum code length */
+  if ((unsigned)*m < j)
+    *m = j;
+  for (i = BMAX; i; i--)
+    if (c[i])
+      break;
+  g = i;                        /* maximum code length */
+  if ((unsigned)*m > i)
+    *m = i;
+
+
+  /* Adjust last length count to fill out codes, if needed */
+  for (y = 1 << j; j < i; j++, y <<= 1)
+    if ((y -= c[j]) < 0)
+      return 2;                 /* bad input: more codes than bits */
+  if ((y -= c[i]) < 0)
+    return 2;
+  c[i] += y;
+
+
+  /* Generate starting offsets into the value table for each length */
+  x[1] = j = 0;
+  p = c + 1;  xp = x + 2;
+  while (--i) {                 /* note that i == g from above */
+    *xp++ = (j += *p++);
+  }
+
+
+  /* Make a table of values in order of bit lengths */
+  memzero((char *)v, sizeof(v));
+  p = (unsigned *)b;  i = 0;
+  do {
+    if ((j = *p++) != 0)
+      v[x[j]++] = i;
+  } while (++i < n);
+  n = x[g];                     /* set n to length of v */
+
+
+  /* Generate the Huffman codes and for each, make the table entries */
+  x[0] = i = 0;                 /* first Huffman code is zero */
+  p = v;                        /* grab values in bit order */
+  h = -1;                       /* no tables yet--level -1 */
+  w = l[-1] = 0;                /* no bits decoded yet */
+  u[0] = (struct huft *)NULL;   /* just to keep compilers happy */
+  q = (struct huft *)NULL;      /* ditto */
+  z = 0;                        /* ditto */
+
+  /* go through the bit lengths (k already is bits in shortest code) */
+  for (; k <= g; k++)
+  {
+    a = c[k];
+    while (a--)
+    {
+      /* here i is the Huffman code of length k bits for value *p */
+      /* make tables up to required level */
+      while (k > w + l[h])
+      {
+        w += l[h++];            /* add bits already decoded */
+
+        /* compute minimum size table less than or equal to *m bits */
+        z = (z = g - w) > (unsigned)*m ? *m : z;        /* upper limit */
+        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
+        {                       /* too few codes for k-w bit table */
+          f -= a + 1;           /* deduct codes from patterns left */
+          xp = c + k;
+          while (++j < z)       /* try smaller tables up to z bits */
+          {
+            if ((f <<= 1) <= *++xp)
+              break;            /* enough codes to use up j bits */
+            f -= *xp;           /* else deduct codes from patterns */
+          }
+        }
+        if ((unsigned)w + j > el && (unsigned)w < el)
+          j = el - w;           /* make EOB code end at table */
+        z = 1 << j;             /* table entries for j-bit table */
+        l[h] = j;               /* set table size in stack */
+
+        /* allocate and link in new table */
+        if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) ==
+            (struct huft *)NULL)
+        {
+          if (h)
+            huft_free(u[0]);
+          return 3;             /* not enough memory */
+        }
+#ifdef DEBUG
+        G.hufts += z + 1;         /* track memory usage */
+#endif
+        *t = q + 1;             /* link to list for huft_free() */
+        *(t = &(q->v.t)) = (struct huft *)NULL;
+        u[h] = ++q;             /* table starts after link */
+
+        /* connect to last table, if there is one */
+        if (h)
+        {
+          x[h] = i;             /* save pattern for backing up */
+          r.b = (uch)l[h-1];    /* bits to dump before this table */
+          r.e = (uch)(16 + j);  /* bits in this table */
+          r.v.t = q;            /* pointer to this table */
+          j = (i & ((1 << w) - 1)) >> (w - l[h-1]);
+          u[h-1][j] = r;        /* connect to last table */
+        }
+      }
+
+      /* set up table entry in r */
+      r.b = (uch)(k - w);
+      if (p >= v + n)
+        r.e = 99;               /* out of values--invalid code */
+      else if (*p < s)
+      {
+        r.e = (uch)(*p < 256 ? 16 : 15);  /* 256 is end-of-block code */
+        r.v.n = (ush)*p++;                /* simple code is just the value */
+      }
+      else
+      {
+        r.e = (uch)e[*p - s];   /* non-simple--look up in lists */
+        r.v.n = d[*p++ - s];
+      }
+
+      /* fill code-like entries with r */
+      f = 1 << (k - w);
+      for (j = i >> w; j < z; j += f)
+        q[j] = r;
+
+      /* backwards increment the k-bit code i */
+      for (j = 1 << (k - 1); i & j; j >>= 1)
+        i ^= j;
+      i ^= j;
+
+      /* backup over finished tables */
+      while ((i & ((1 << w) - 1)) != x[h])
+        w -= l[--h];            /* don't need to update q */
+    }
+  }
+
+
+  /* return actual size of base table */
+  *m = l[0];
+
+
+  /* Return true (1) if we were given an incomplete table */
+  return y != 0 && g != 1;
+}
+
+
+
+int huft_free(t)
+struct huft *t;         /* table to free */
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+   list of the tables it made, with the links in a dummy first entry of
+   each table. */
+{
+  register struct huft *p, *q;
+
+
+  /* Go through linked list, freeing from the malloced (t[-1]) address. */
+  p = t;
+  while (p != (struct huft *)NULL)
+  {
+    q = (--p)->v.t;
+    free((zvoid *)p);
+    p = q;
+  }
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/list.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,644 @@
+/*---------------------------------------------------------------------------
+
+  list.c
+
+  This file contains the non-ZipInfo-specific listing routines for UnZip.
+
+  Contains:  list_files()
+             get_time_stamp()   [optional feature]
+             ratio()
+             fnprint()
+
+  ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#ifdef WINDLL
+#  ifdef POCKET_UNZIP
+#    include "wince/intrface.h"
+#  else
+#    include "windll/windll.h"
+#  endif
+#endif
+
+
+#ifdef TIMESTAMP
+   static int  fn_is_dir   OF((__GPRO));
+#endif
+
+#ifndef WINDLL
+   static ZCONST char Far CompFactorStr[] = "%c%d%%";
+   static ZCONST char Far CompFactor100[] = "100%%";
+
+#ifdef OS2_EAS
+   static ZCONST char Far HeadersS[]  =
+     "  Length     EAs   ACLs    Date   Time    Name";
+   static ZCONST char Far HeadersS1[] =
+     " --------    ---   ----    ----   ----    ----";
+#else
+   static ZCONST char Far HeadersS[]  = "  Length     Date   Time    Name";
+   static ZCONST char Far HeadersS1[] = " --------    ----   ----    ----";
+#endif
+
+   static ZCONST char Far HeadersL[]  =
+     " Length   Method    Size  Ratio   Date   Time   CRC-32    Name";
+   static ZCONST char Far HeadersL1[] =
+     "--------  ------  ------- -----   ----   ----   ------    ----";
+   static ZCONST char Far *Headers[][2] =
+     { {HeadersS, HeadersS1}, {HeadersL, HeadersL1} };
+
+   static ZCONST char Far CaseConversion[] =
+     "%s (\"^\" ==> case\n%s   conversion)\n";
+   static ZCONST char Far LongHdrStats[] =
+     "%8lu  %-7s%8lu %4s  %02u-%02u-%02u %02u:%02u  %08lx %c";
+   static ZCONST char Far LongFileTrailer[] =
+     "--------          -------  ---                       \
+     -------\n%8lu         %8lu %4s                            %u file%s\n";
+#ifdef OS2_EAS
+   static ZCONST char Far ShortHdrStats[] =
+     "%9lu %6lu %6lu  %02u-%02u-%02u %02u:%02u  %c";
+   static ZCONST char Far ShortFileTrailer[] = " --------  -----  -----       \
+            -------\n%9lu %6lu %6lu                   %u file%s\n";
+   static ZCONST char Far OS2ExtAttrTrailer[] =
+     "%ld file%s %ld bytes of OS/2 extended attributes attached.\n";
+   static ZCONST char Far OS2ACLTrailer[] =
+     "%ld file%s %ld bytes of access control lists attached.\n";
+#else
+   static ZCONST char Far ShortHdrStats[] =
+     "%9lu  %02u-%02u-%02u %02u:%02u  %c";
+   static ZCONST char Far ShortFileTrailer[] =
+     " --------                   -------\n%9lu                   %u file%s\n";
+#endif /* ?OS2_EAS */
+#endif /* !WINDLL */
+
+
+
+
+
+/*************************/
+/* Function list_files() */
+/*************************/
+
+int list_files(__G)    /* return PK-type error code */
+    __GDEF
+{
+    int do_this_file=FALSE, cfactor, error, error_in_archive=PK_COOL;
+#ifndef WINDLL
+    char sgn, cfactorstr[10];
+    int longhdr=(uO.vflag>1);
+#endif
+    int date_format;
+    unsigned j, methnum, members=0;
+#ifdef USE_EF_UT_TIME
+    iztimes z_utime;
+    struct tm *t;
+#endif
+    unsigned yr, mo, dy, hh, mm;
+    ulg csiz, tot_csize=0L, tot_ucsize=0L;
+#ifdef OS2_EAS
+    ulg ea_size, tot_easize=0L, tot_eafiles=0L;
+    ulg acl_size, tot_aclsize=0L, tot_aclfiles=0L;
+#endif
+    min_info info;
+    char methbuf[8];
+    static ZCONST char dtype[]="NXFS";  /* see zi_short() */
+    static ZCONST char Far method[NUM_METHODS+1][8] =
+        {"Stored", "Shrunk", "Reduce1", "Reduce2", "Reduce3", "Reduce4",
+         "Implode", "Token", "Defl:#", "EnhDefl", "ImplDCL", "Unk:###"};
+
+
+/*---------------------------------------------------------------------------
+    Unlike extract_or_test_files(), this routine confines itself to the cen-
+    tral directory.  Thus its structure is somewhat simpler, since we can do
+    just a single loop through the entire directory, listing files as we go.
+
+    So to start off, print the heading line and then begin main loop through
+    the central directory.  The results will look vaguely like the following:
+
+ Length   Method    Size  Ratio   Date   Time   CRC-32    Name ("^" ==> case
+--------  ------  ------- -----   ----   ----   ------    ----   conversion)
+   44004  Implode   13041  71%  11-02-89 19:34  8b4207f7  Makefile.UNIX
+    3438  Shrunk     2209  36%  09-15-90 14:07  a2394fd8 ^dos-file.ext
+   16717  Defl:X     5252  69%  11-03-97 06:40  1ce0f189  WHERE
+--------          -------  ---                            -------
+   64159            20502  68%                            3 files
+  ---------------------------------------------------------------------------*/
+
+
+    G.pInfo = &info;
+    date_format = DATE_FORMAT;
+
+#ifndef WINDLL
+    if (uO.qflag < 2) {
+        if (uO.L_flag)
+            Info(slide, 0, ((char *)slide, LoadFarString(CaseConversion),
+              LoadFarStringSmall(Headers[longhdr][0]),
+              LoadFarStringSmall2(Headers[longhdr][1])));
+        else
+            Info(slide, 0, ((char *)slide, "%s\n%s\n",
+               LoadFarString(Headers[longhdr][0]),
+               LoadFarStringSmall(Headers[longhdr][1])));
+    }
+#endif /* !WINDLL */
+
+    for (j = 0; j++ < (unsigned)G.ecrec.total_entries_central_dir;) {
+
+        if (readbuf(__G__ G.sig, 4) == 0)
+            return PK_EOF;
+        if (strncmp(G.sig, central_hdr_sig, 4)) {  /* just to make sure */
+            Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), j));
+            Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
+            return PK_BADERR;   /* sig not found */
+        }
+        /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag, ...: */
+        if ((error = process_cdir_file_hdr(__G)) != PK_COOL)
+            return error;       /* only PK_EOF defined */
+
+        /*
+         * We could DISPLAY the filename instead of storing (and possibly trun-
+         * cating, in the case of a very long name) and printing it, but that
+         * has the disadvantage of not allowing case conversion--and it's nice
+         * to be able to see in the listing precisely how you have to type each
+         * filename in order for unzip to consider it a match.  Speaking of
+         * which, if member names were specified on the command line, check in
+         * with match() to see if the current file is one of them, and make a
+         * note of it if it is.
+         */
+
+        if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=
+             PK_COOL)   /*  ^--(uses pInfo->lcflag) */
+        {
+            error_in_archive = error;
+            if (error > PK_WARN)   /* fatal:  can't continue */
+                return error;
+        }
+        if (G.extra_field != (uch *)NULL) {
+            free(G.extra_field);
+            G.extra_field = (uch *)NULL;
+        }
+        if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD))
+            != 0)
+        {
+            error_in_archive = error;
+            if (error > PK_WARN)      /* fatal */
+                return error;
+        }
+        if (!G.process_all_files) {   /* check if specified on command line */
+            unsigned i;
+
+            do_this_file = FALSE;
+            for (i = 0; i < G.filespecs; i++)
+                if (match(G.filename, G.pfnames[i], uO.C_flag)) {
+                    do_this_file = TRUE;
+                    break;       /* found match, so stop looping */
+                }
+            if (do_this_file) {  /* check if this is an excluded file */
+                for (i = 0; i < G.xfilespecs; i++)
+                    if (match(G.filename, G.pxnames[i], uO.C_flag)) {
+                        do_this_file = FALSE;  /* ^-- ignore case in match */
+                        break;
+                    }
+            }
+        }
+        /*
+         * If current file was specified on command line, or if no names were
+         * specified, do the listing for this file.  Otherwise, get rid of the
+         * file comment and go back for the next file.
+         */
+
+        if (G.process_all_files || do_this_file) {
+
+#ifdef OS2DLL
+            /* this is used by UzpFileTree() to allow easy processing of lists
+             * of zip directory contents */
+            if (G.processExternally) {
+                if ((G.processExternally)(G.filename, &G.crec))
+                    break;
+                ++members;
+            } else {
+#endif
+#ifdef OS2_EAS
+            {
+                uch *ef_ptr = G.extra_field;
+                int ef_size, ef_len = G.crec.extra_field_length;
+                ea_size = acl_size = 0;
+
+                while (ef_len >= EB_HEADSIZE) {
+                    ef_size = makeword(&ef_ptr[EB_LEN]);
+                    switch (makeword(&ef_ptr[EB_ID])) {
+                        case EF_OS2:
+                            ea_size = makelong(&ef_ptr[EB_HEADSIZE]);
+                            break;
+                        case EF_ACL:
+                            acl_size = makelong(&ef_ptr[EB_HEADSIZE]);
+                            break;
+                    }
+                    ef_ptr += (ef_size + EB_HEADSIZE);
+                    ef_len -= (ef_size + EB_HEADSIZE);
+                }
+            }
+#endif
+#ifdef USE_EF_UT_TIME
+            if (G.extra_field &&
+#ifdef IZ_CHECK_TZ
+                G.tz_is_valid &&
+#endif
+                (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,
+                                  G.crec.last_mod_dos_datetime, &z_utime, NULL)
+                 & EB_UT_FL_MTIME))
+            {
+                TIMET_TO_NATIVE(z_utime.mtime)   /* NOP unless MSC 7.0, Mac */
+                t = localtime(&(z_utime.mtime));
+            } else
+                t = (struct tm *)NULL;
+            if (t != (struct tm *)NULL) {
+                mo = (unsigned)(t->tm_mon + 1);
+                dy = (unsigned)(t->tm_mday);
+                yr = (unsigned)(t->tm_year % 100);
+                hh = (unsigned)(t->tm_hour);
+                mm = (unsigned)(t->tm_min);
+            } else
+#endif /* USE_EF_UT_TIME */
+            {
+                yr = ((((unsigned)(G.crec.last_mod_dos_datetime >> 25) & 0x7f)
+                       + 80) % (unsigned)100);
+                mo = ((unsigned)(G.crec.last_mod_dos_datetime >> 21) & 0x0f);
+                dy = ((unsigned)(G.crec.last_mod_dos_datetime >> 16) & 0x1f);
+                hh = (((unsigned)G.crec.last_mod_dos_datetime >> 11) & 0x1f);
+                mm = (((unsigned)G.crec.last_mod_dos_datetime >> 5) & 0x3f);
+            }
+            /* permute date so it displays according to nat'l convention
+             * ('methnum' is not yet set, it is used as temporary buffer) */
+            switch (date_format) {
+                case DF_YMD:
+                    methnum = (unsigned)mo;
+                    mo = yr; yr = dy; dy = (ush)methnum;
+                    break;
+                case DF_DMY:
+                    methnum = (unsigned)mo;
+                    mo = dy; dy = (ush)methnum;
+            }
+
+            csiz = G.crec.csize;
+            if (G.crec.general_purpose_bit_flag & 1)
+                csiz -= 12;   /* if encrypted, don't count encryption header */
+            if ((cfactor = ratio(G.crec.ucsize, csiz)) < 0) {
+#ifndef WINDLL
+                sgn = '-';
+#endif
+                cfactor = (-cfactor + 5) / 10;
+            } else {
+#ifndef WINDLL
+                sgn = ' ';
+#endif
+                cfactor = (cfactor + 5) / 10;
+            }
+
+            methnum = MIN(G.crec.compression_method, NUM_METHODS);
+            zfstrcpy(methbuf, method[methnum]);
+            if (methnum == DEFLATED) {
+                methbuf[5] = dtype[(G.crec.general_purpose_bit_flag>>1) & 3];
+            } else if (methnum >= NUM_METHODS) {
+                sprintf(&methbuf[4], "%03u", G.crec.compression_method);
+            }
+
+#if 0       /* GRR/Euro:  add this? */
+#if defined(DOS_FLX_OS2_W32) || defined(UNIX)
+            for (p = G.filename;  *p;  ++p)
+                if (!isprint(*p))
+                    *p = '?';  /* change non-printable chars to '?' */
+#endif /* DOS_FLX_OS2_W32 || UNIX */
+#endif /* 0 */
+
+#ifdef WINDLL
+            /* send data to application for formatting and printing */
+            (*G.lpUserFunctions->SendApplicationMessage)(G.crec.ucsize, csiz,
+              (ush)cfactor, mo, dy, yr, hh, mm,
+              (char)(G.pInfo->lcflag ? '^' : ' '),
+              (LPSTR)fnfilter(G.filename, slide), (LPSTR)methbuf, G.crec.crc32,
+              (char)((G.crec.general_purpose_bit_flag & 1) ? 'E' : ' '));
+#else /* !WINDLL */
+            if (cfactor == 100)
+                sprintf(cfactorstr, LoadFarString(CompFactor100));
+            else
+                sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
+            if (longhdr)
+                Info(slide, 0, ((char *)slide, LoadFarString(LongHdrStats),
+                  G.crec.ucsize, methbuf, csiz, cfactorstr, mo, dy,
+                  yr, hh, mm, G.crec.crc32, (G.pInfo->lcflag? '^':' ')));
+            else
+#ifdef OS2_EAS
+                Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats),
+                  G.crec.ucsize, ea_size, acl_size,
+                  mo, dy, yr, hh, mm, (G.pInfo->lcflag? '^':' ')));
+#else
+                Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats),
+                  G.crec.ucsize,
+                  mo, dy, yr, hh, mm, (G.pInfo->lcflag? '^':' ')));
+#endif
+				/* fnprint(__G);*/
+#endif /* ?WINDLL */
+
+            if ((error = do_string(__G__ G.crec.file_comment_length,
+                                   QCOND? DISPL_8 : SKIP)) != 0)
+            {
+                error_in_archive = error;  /* might be just warning */
+                if (error > PK_WARN)       /* fatal */
+                    return error;
+            }
+            tot_ucsize += G.crec.ucsize;
+            tot_csize += csiz;
+            ++members;
+#ifdef OS2_EAS
+            if (ea_size) {
+                tot_easize += ea_size;
+                ++tot_eafiles;
+            }
+            if (acl_size) {
+                tot_aclsize += acl_size;
+                ++tot_aclfiles;
+            }
+#endif
+#ifdef OS2DLL
+            } /* end of "if (G.processExternally) {...} else {..." */
+#endif
+        } else {        /* not listing this file */
+            SKIP_(G.crec.file_comment_length)
+        }
+    } /* end for-loop (j: files in central directory) */
+
+/*---------------------------------------------------------------------------
+    Print footer line and totals (compressed size, uncompressed size, number
+    of members in zipfile).
+  ---------------------------------------------------------------------------*/
+
+    if (uO.qflag < 2
+#ifdef OS2DLL
+                     && !G.processExternally
+#endif
+                                            ) {
+        if ((cfactor = ratio(tot_ucsize, tot_csize)) < 0) {
+#ifndef WINDLL
+            sgn = '-';
+#endif
+            cfactor = (-cfactor + 5) / 10;
+        } else {
+#ifndef WINDLL
+            sgn = ' ';
+#endif
+            cfactor = (cfactor + 5) / 10;
+        }
+#ifdef WINDLL
+        /* pass the totals back to the calling application */
+        G.lpUserFunctions->TotalSizeComp = tot_csize;
+        G.lpUserFunctions->TotalSize = tot_ucsize;
+        G.lpUserFunctions->CompFactor = cfactor;
+        G.lpUserFunctions->NumMembers = members;
+
+#else /* !WINDLL */
+        if (cfactor == 100)
+            sprintf(cfactorstr, LoadFarString(CompFactor100));
+        else
+            sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
+        if (longhdr) {
+            Info(slide, 0, ((char *)slide, LoadFarString(LongFileTrailer),
+              tot_ucsize, tot_csize, cfactorstr, members, members==1? "":"s"));
+#ifdef OS2_EAS
+            if (tot_easize || tot_aclsize)
+                Info(slide, 0, ((char *)slide, "\n"));
+            if (tot_eafiles && tot_easize)
+                Info(slide, 0, ((char *)slide, LoadFarString(OS2ExtAttrTrailer),
+                  tot_eafiles, tot_eafiles == 1? " has" : "s have a total of",
+                  tot_easize));
+            if (tot_aclfiles && tot_aclsize)
+                Info(slide, 0, ((char *)slide, LoadFarString(OS2ACLTrailer),
+                  tot_aclfiles, tot_aclfiles == 1? " has" : "s have a total of",
+                  tot_aclsize));
+#endif /* OS2_EAS */
+        } else
+#ifdef OS2_EAS
+            Info(slide, 0, ((char *)slide, LoadFarString(ShortFileTrailer),
+              tot_ucsize, tot_easize, tot_aclsize, members, members == 1?
+              "" : "s"));
+#else
+            Info(slide, 0, ((char *)slide, LoadFarString(ShortFileTrailer),
+              tot_ucsize, members, members == 1? "" : "s"));
+#endif /* OS2_EAS */
+#endif /* ?WINDLL */
+    }
+
+/*---------------------------------------------------------------------------
+    Double check that we're back at the end-of-central-directory record.
+  ---------------------------------------------------------------------------*/
+
+    if (readbuf(__G__ G.sig, 4) == 0)  /* disk error? */
+        return PK_EOF;
+    if (strncmp(G.sig, end_central_sig, 4)) {   /* just to make sure again */
+        Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
+        error_in_archive = PK_WARN;   /* didn't find sig */
+    }
+    if (members == 0 && error_in_archive <= PK_WARN)
+        error_in_archive = PK_FIND;
+
+    return error_in_archive;
+
+} /* end function list_files() */
+
+
+
+
+
+#ifdef TIMESTAMP
+
+/************************/
+/* Function fn_is_dir() */
+/************************/
+
+static int fn_is_dir(__G)    /* returns TRUE if G.filename is directory */
+    __GDEF
+{
+    extent fn_len = strlen(G.filename);
+    register char   endc;
+
+    return  fn_len > 0 &&
+            ((endc = G.filename[fn_len-1]) == '/' ||
+             (G.pInfo->hostnum == FS_FAT_ && !strchr(G.filename, '/') &&
+              endc == '\\'));
+}
+
+
+
+
+
+/*****************************/
+/* Function get_time_stamp() */
+/*****************************/
+
+int get_time_stamp(__G__ last_modtime, nmember)  /* return PK-type error code */
+    __GDEF
+    time_t *last_modtime;
+    unsigned *nmember;
+{
+    int do_this_file=FALSE, error, error_in_archive=PK_COOL;
+    unsigned j;
+#ifdef USE_EF_UT_TIME
+    iztimes z_utime;
+#endif
+    min_info info;
+
+
+/*---------------------------------------------------------------------------
+    Unlike extract_or_test_files() but like list_files(), this function works
+    on information in the central directory alone.  Thus we have a single,
+    large loop through the entire directory, searching for the latest time
+    stamp.
+  ---------------------------------------------------------------------------*/
+
+    *last_modtime = 0L;         /* assuming no zipfile data older than 1970 */
+    *nmember = 0;
+    G.pInfo = &info;
+
+    for (j = 0; j++ < (unsigned)G.ecrec.total_entries_central_dir;) {
+
+        if (readbuf(__G__ G.sig, 4) == 0)
+            return PK_EOF;
+        if (strncmp(G.sig, central_hdr_sig, 4)) {  /* just to make sure */
+            Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), j));
+            Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
+            return PK_BADERR;
+        }
+        /* process_cdir_file_hdr() sets pInfo->lcflag: */
+        if ((error = process_cdir_file_hdr(__G)) != PK_COOL)
+            return error;       /* only PK_EOF defined */
+        if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) != PK_OK)
+        {        /*  ^-- (uses pInfo->lcflag) */
+            error_in_archive = error;
+            if (error > PK_WARN)   /* fatal:  can't continue */
+                return error;
+        }
+        if (G.extra_field != (uch *)NULL) {
+            free(G.extra_field);
+            G.extra_field = (uch *)NULL;
+        }
+        if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD))
+            != 0)
+        {
+            error_in_archive = error;
+            if (error > PK_WARN)      /* fatal */
+                return error;
+        }
+        if (!G.process_all_files) {   /* check if specified on command line */
+            unsigned i;
+
+            do_this_file = FALSE;
+            for (i = 0; i < G.filespecs; i++)
+                if (match(G.filename, G.pfnames[i], uO.C_flag)) {
+                    do_this_file = TRUE;
+                    break;       /* found match, so stop looping */
+                }
+            if (do_this_file) {  /* check if this is an excluded file */
+                for (i = 0; i < G.xfilespecs; i++)
+                    if (match(G.filename, G.pxnames[i], uO.C_flag)) {
+                        do_this_file = FALSE;  /* ^-- ignore case in match */
+                        break;
+                    }
+            }
+        }
+
+        /* If current file was specified on command line, or if no names were
+         * specified, check the time for this file.  Either way, get rid of the
+         * file comment and go back for the next file.
+         * Directory entries are always ignored, to stay compatible with both
+         * Zip and PKZIP.
+         */
+        if ((G.process_all_files || do_this_file) && !fn_is_dir(__G)) {
+#ifdef USE_EF_UT_TIME
+            if (G.extra_field &&
+#ifdef IZ_CHECK_TZ
+                G.tz_is_valid &&
+#endif
+                (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,
+                                  G.crec.last_mod_dos_datetime, &z_utime, NULL)
+                 & EB_UT_FL_MTIME))
+            {
+                if (*last_modtime < z_utime.mtime)
+                    *last_modtime = z_utime.mtime;
+            } else
+#endif /* USE_EF_UT_TIME */
+            {
+                time_t modtime = dos_to_unix_time(G.crec.last_mod_dos_datetime);
+
+                if (*last_modtime < modtime)
+                    *last_modtime = modtime;
+            }
+            ++*nmember;
+        }
+        SKIP_(G.crec.file_comment_length)
+
+    } /* end for-loop (j: files in central directory) */
+
+/*---------------------------------------------------------------------------
+    Double check that we're back at the end-of-central-directory record.
+  ---------------------------------------------------------------------------*/
+
+    if (readbuf(__G__ G.sig, 4) == 0)
+        return PK_EOF;
+    if (strncmp(G.sig, end_central_sig, 4)) {   /* just to make sure again */
+        Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
+        error_in_archive = PK_WARN;
+    }
+    if (*nmember == 0 && error_in_archive <= PK_WARN)
+        error_in_archive = PK_FIND;
+
+    return error_in_archive;
+
+} /* end function get_time_stamp() */
+
+#endif /* TIMESTAMP */
+
+
+
+
+
+/********************/
+/* Function ratio() */    /* also used by ZipInfo routines */
+/********************/
+
+int ratio(uc, c)
+    ulg uc, c;
+{
+    ulg denom;
+
+    if (uc == 0)
+        return 0;
+    if (uc > 2000000L) {    /* risk signed overflow if multiply numerator */
+        denom = uc / 1000L;
+        return ((uc >= c) ?
+            (int) ((uc-c + (denom>>1)) / denom) :
+          -((int) ((c-uc + (denom>>1)) / denom)));
+    } else {             /* ^^^^^^^^ rounding */
+        denom = uc;
+        return ((uc >= c) ?
+            (int) ((1000L*(uc-c) + (denom>>1)) / denom) :
+          -((int) ((1000L*(c-uc) + (denom>>1)) / denom)));
+    }                            /* ^^^^^^^^ rounding */
+}
+
+
+
+
+
+/************************/
+/*  Function fnprint()  */    /* also used by ZipInfo routines */
+/************************/
+
+void fnprint(__G)    /* print filename (after filtering) and newline */
+    __GDEF
+{
+    char *name = fnfilter(G.filename, slide);
+
+    (*G.message)((zvoid *)&G, (uch *)name, (ulg)strlen(name), 0);
+    (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
+
+} /* end function fnprint() */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/makefile.b32	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,135 @@
+# Makefile for UnZip(SFX) and fUnZip for Borland C++ for Windows 95/NT
+# Version: 5.4 and later        Alvin Koh, Jim Knoble, Christian Spieler, etc.
+# Adapted from the MS-DOS makefile by E-Yen Tan
+#
+# Last revised:  24 Nov 98
+#
+#
+
+
+#    Optional nonstandard preprocessor flags (as -DCHECK_EOF or -DDOS_WILD)
+#    should be added to the environment via "set LOCAL_UNZIP=-DFOO" or added
+#    to the declaration of LOC here:
+LOC = $(LOCAL_UNZIP)
+
+# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc.
+CPU_TYP = 4
+
+# (De)Select inclusion of optimized assembler CRC32 routine:
+USE_ASMCRC = 0
+
+# If you have bcc32i, you should define:
+# CC = bcc32i
+# This compiler generates a faster code.
+CC = bcc32
+AS = tasm32
+
+!if $(USE_ASMCRC)
+ASMFLG = -DASM_CRC
+ASMOBJS = crc_i386.obj
+!else
+ASMFLG =
+ASMOBJS =
+!endif
+
+!if $(UNCLEAN)
+DIRT = -DUSE_SMITH_CODE -DUSE_UNSHRINK
+!else
+DIRT =
+!endif
+
+# compiler flags
+
+ASCPUFLAG = __$(CPU_TYP)86
+!if $(CPU_TYP) != 0
+CC_CPUFLG = -$(CPU_TYP)
+!endif
+ASFLAGS = -ml -m2 -w0 -D$(ASCPUFLAG) $(LOC)
+CFLAGS = -Od -w- $(CC_CPUFLG) -ff- -k- -P-.C -I. -I.. -I../inczip -I../../../include $(ASMFLG) $(LOC) $(DIRT) -v -D__WXMSW__ -DWXDEBUG=1 -D__WXDEBUG__ -DUSE_DEFINE -DWIN32 -D__WIN95__ -D__WINDOWS__ -I$(WXDIR)\include
+LDFLAGS = -L$(WXWIN)\lib -aa -c		# for bcc
+LINK = ilink32
+LIBS = wx32 cw32mt import32 ole2w32 winpng zlib jpeg xpm tiff
+
+UNFLAGS = $(CFLAGS)
+
+# implicit rules
+
+.asm.obj:
+	$(AS) $(ASFLAGS) $<
+
+.c.obj:
+	$(CC) -c $(UNFLAGS) {$< }
+
+# list macros
+
+OBJU1 = unzip.obj crc32.obj crctab.obj crypt.obj envargs.obj explode.obj
+OBJU2 = extract.obj fileio.obj globals.obj inflate.obj list.obj match.obj
+OBJU3 = process.obj ttyio.obj unreduce.obj unshrink.obj zipinfo.obj
+OBJUS = win32.obj nt.obj install.obj wxmain.obj instsup.obj $(ASMOBJS)
+OBJU  = $(OBJU1) $(OBJU2) $(OBJU3) $(OBJUS)
+
+UNZIP_H = ../inczip/unzip.h ../inczip/unzpriv.h ../inczip/globals.h ../inczip/w32cfg.h
+
+# explicit rules
+
+all:    sfx.exe
+
+sfx.exe:	$(OBJU) sfx.res
+  $(LINK) $(LDFLAGS) @&&!
+c0w32.obj $(OBJU)
+sfx.exe
+nul
+$(LIBS)
+
+sfx.res
+!
+
+clean:
+        -erase *.obj
+        -erase *.exe
+        -erase *.res
+        -erase *.map
+        -erase *.rws
+        -erase *.tds
+        -erase *.il?
+
+# individual file dependencies
+
+crc32.obj:      crc32.c $(UNZIP_H) ../inczip/zip.h
+crctab.obj:     crctab.c $(UNZIP_H) ../inczip/zip.h
+crypt.obj:      crypt.c $(UNZIP_H) ../inczip/zip.h ../inczip/crypt.h ../inczip/ttyio.h
+envargs.obj:    envargs.c $(UNZIP_H)
+explode.obj:    explode.c $(UNZIP_H)
+extract.obj:    extract.c $(UNZIP_H) ../inczip/crypt.h
+fileio.obj:     fileio.c $(UNZIP_H) ../inczip/crypt.h ../inczip/ttyio.h ../inczip/ebcdic.h
+globals.obj:    globals.c $(UNZIP_H)
+inflate.obj:    inflate.c ../inczip/inflate.h $(UNZIP_H)
+list.obj:       list.c $(UNZIP_H)
+match.obj:      match.c $(UNZIP_H)
+process.obj:    process.c $(UNZIP_H)
+ttyio.obj:      ttyio.c $(UNZIP_H) ../inczip/zip.h ../inczip/crypt.h ../inczip/ttyio.h
+unreduce.obj:   unreduce.c $(UNZIP_H)
+unshrink.obj:   unshrink.c $(UNZIP_H)
+unzip.obj:      unzip.c $(UNZIP_H) ../inczip/crypt.h ../inczip/version.h ../inczip/consts.h
+zipinfo.obj:    zipinfo.c $(UNZIP_H)
+
+#crc_i386.obj:   win32/crc_i386.asm
+#	$(AS) $(ASFLAGS) win32\crc_i386.asm, $*.obj ;
+
+win32.obj:      win32.c $(UNZIP_H)
+	$(CC) -c $(UNFLAGS) win32.c
+
+nt.obj:         nt.c $(UNZIP_H)
+	$(CC) -c $(UNFLAGS) nt.c
+
+install.obj:         ../install.c $(UNZIP_H)
+	$(CC) -c $(UNFLAGS) ../install.c
+        
+wxmain.obj:         ../wxmain.cpp $(UNZIP_H)
+	$(CC) -P- -c $(UNFLAGS) ../wxmain.cpp
+        
+instsup.obj:         ../instsup.cpp $(UNZIP_H)
+	$(CC) -P- -c $(UNFLAGS) ../instsup.cpp
+
+sfx.res :      sfx.rc $(WXWIN)\include\wx\msw\wx.rc
+	    brc32 -r /i$(BCCDIR)\include /i$(WXWIN)\include /i$(WXWIN)\contrib\include sfx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/makefile.g95	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,164 @@
+# Makefile for UnZip, fUnZip and UnZipSFX for native Win32-Intel ports of gcc.
+# Currently supported implementations: Cygnus/Win32 and MinGW32.
+#
+# First version: Cosmin Truta <cosmint@cs.ubbcluj.ro>, Dec 1997.
+# Last revision: Christian Spieler, 29-Apr-1998
+#
+# To use, do "make -f win32/makefile.gcc".
+
+
+### Optional section
+
+# Optional nonstandard preprocessor flags (as -DUSE_ZLIB or -DUSE_SMITH_CODE)
+# should be added to the environment via "set LOCAL_UNZIP=-DFOO" or added
+# to the declaration of LOCFLAGS here:
+LOCFLAGS = $(LOCAL_UNZIP)
+
+
+### Compiler-specific section
+
+# ------------ GNU C ------------
+CC = gcc
+
+#AS = as
+AS = $(CC)
+
+#LD = ld
+LD = $(CC)
+
+# Quiet
+CC_QUIET_OPT =
+AS_QUIET_OPT = $(CC_QUIET_OPT)
+LD_QUIET_OPT = $(CC_QUIET_OPT)
+
+# Warnings
+CC_WARN_OPT = -Wall
+AS_WARN_OPT = $(CC_WARN_OPT)
+LD_WARN_OPT =
+
+# Debug version
+CC_DEBUG_OPT = -g
+AS_DEBUG_OPT = $(CC_DEBUG_OPT)
+LD_DEBUG_OPT = $(CC_DEBUG_OPT)
+
+# Release version
+CC_RELEASE_OPT =
+AS_RELEASE_OPT =
+#LD_RELEASE_OPT = -s
+
+# Smallest code
+CC_SIZE_OPT = -O1
+
+# Fastest code
+CC_SPEED_OPT = -O2
+
+# Output object file name
+CC_OUT_OPT = -o
+
+# Other specific options
+#CC_SPECIFIC_OPT = -c -DASM_CRC -DWIN32 -mno-cygwin
+CC_SPECIFIC_OPT = -c -DWIN32 -I../inczip -g  -I.. -D_X86_=1 -DWIN32 -D_WIN32 -DWINVER=0x0400 -D__WIN95__ -D__GNUWIN32__ -D__WIN32__ -I../../../include -I../../../src/png -I../../../src/jpeg -I../../../src/zlib   -I../../../include/wx/msw/gnuwin32  -DSTRICT  -D__WXMSW__ -D__WINDOWS__ -D__WXDEBUG__ -Wall -fno-pcc-struct-return -O2 -fno-rtti -fno-exceptions
+AS_SPECIFIC_OPT = -c
+LD_SPECIFIC_OPT = -Wl,--subsystem,windows -mwindows -L../../../lib -o $@
+
+# Libraries for the debug & release version
+LD_RELEASE_LIBS = ../../../lib/libwx.a -lpng -ljpeg -lzlib -lxpm -lstdc++ -lgcc -lwinspool -lwinmm -lshell32 -lcomctl32 -lctl3d32 -lodbc32 -ladvapi32 -lole32 -loleaut32 -luuid -lodbc32 -lwsock32
+LD_DEBUG_LIBS = $(LD_RELEASE_LIBS)
+
+
+### System-specific section
+
+# Suffixes
+OBJ = .o
+EXE = .exe
+
+.SUFFIXES: .c .S $(OBJ) $(EXE)
+
+# Commands
+RM = rm -f
+
+
+### General section
+
+CFLAGS  = $(CC_SPECIFIC_OPT) $(CC_QUIET_OPT) $(CC_WARN_OPT) $(LOCFLAGS) \
+ $(CC_OUT_OPT) $@
+ASFLAGS = $(AS_SPECIFIC_OPT) $(AS_QUIET_OPT) $(AS_WARN_OPT) $(LOCFLAGS)
+LDFLAGS = $(LD_SPECIFIC_OPT) $(LD_QUIET_OPT) $(LD_WARN_OPT)
+
+# To build with debug info, use 'make DEBUG=1'.
+ifdef DEBUG
+CVER     = $(CC_DEBUG_OPT)
+ASVER    = $(AS_DEBUG_OPT)
+LDVER    = $(LD_DEBUG_OPT)
+GENFLAGS =
+FFLAGS   = -DFUNZIP
+SFXFLAGS = -DSFX
+LDLIBS   = $(LD_DEBUG_LIBS)
+else
+CVER     = $(CC_RELEASE_OPT)
+ASVER    = $(AS_RELEASE_OPT)
+LDVER    = $(LD_RELEASE_OPT)
+GENFLAGS = $(CC_SPEED_OPT)
+FFLAGS   = $(CC_SPEED_OPT) -DFUNZIP
+SFXFLAGS = $(CC_SIZE_OPT) -DSFX
+LDLIBS   = $(LD_RELEASE_LIBS)
+endif
+
+# Object files
+OBJA  = crc_i386$(OBJ) install$(OBJ) wxmain$(OBJ) instsup$(OBJ)
+OBJS1 = unzip$(OBJ) crc32$(OBJ) crctab$(OBJ) crypt$(OBJ) envargs$(OBJ)
+OBJS2 = explode$(OBJ) extract$(OBJ) fileio$(OBJ) globals$(OBJ) inflate$(OBJ)
+OBJS3 = list$(OBJ) match$(OBJ) process$(OBJ) ttyio$(OBJ) unreduce$(OBJ)
+OBJS4 = unshrink$(OBJ) zipinfo$(OBJ) win32$(OBJ) nt$(OBJ)
+OBJS  = $(OBJS1) $(OBJS2) $(OBJS3) $(OBJS4) $(OBJA)
+
+UNZIP_H = ../inczip/unzip.h ../inczip/unzpriv.h ../inczip/globals.h ../inczip/w32cfg.h
+
+
+# Default target is all the executables
+unzips: sfx$(EXE)
+
+sfx$(EXE): $(OBJS)
+	$(LD) $(LDFLAGS) $(LDVER) $(OBJS) $(LDLIBS)
+
+# How to compile sources
+.c$(OBJ):
+	$(CC) $(CFLAGS) $(CVER) $(GENFLAGS) $<
+.S$(OBJ):
+	$(AS) $(ASFLAGS) $(ASVER) $(GENFLAGS) $<
+
+# Dependencies
+crc32$(OBJ):    crc32.c $(UNZIP_H) ../inczip/zip.h
+crctab$(OBJ):   crctab.c $(UNZIP_H) ../inczip/zip.h
+crypt$(OBJ):    crypt.c $(UNZIP_H) ../inczip/zip.h ../inczip/crypt.h ../inczip/ttyio.h
+envargs$(OBJ):  envargs.c $(UNZIP_H)
+explode$(OBJ):  explode.c $(UNZIP_H)
+extract$(OBJ):  extract.c $(UNZIP_H) ../inczip/crypt.h
+fileio$(OBJ):   fileio.c $(UNZIP_H) ../inczip/crypt.h ../inczip/ttyio.h ../inczip/ebcdic.h
+funzip$(OBJ):   funzip.c $(UNZIP_H) ../inczip/crypt.h ../inczip/ttyio.h ../inczip/tables.h
+globals$(OBJ):  globals.c $(UNZIP_H)
+inflate$(OBJ):  inflate.c ../inczip/inflate.h $(UNZIP_H)
+list$(OBJ):     list.c $(UNZIP_H)
+match$(OBJ):    match.c $(UNZIP_H)
+process$(OBJ):  process.c $(UNZIP_H)
+ttyio$(OBJ):    ttyio.c $(UNZIP_H) ../inczip/zip.h ../inczip/crypt.h ../inczip/ttyio.h
+unreduce$(OBJ): unreduce.c $(UNZIP_H)
+unshrink$(OBJ): unshrink.c $(UNZIP_H)
+unzip$(OBJ):    unzip.c $(UNZIP_H) ../inczip/crypt.h ../inczip/version.h ../inczip/consts.h
+zipinfo$(OBJ):  zipinfo.c $(UNZIP_H)
+crc_i386$(OBJ): crc_i386.S
+win32$(OBJ): win32.c $(UNZIP_H) ../inczip/nt.h
+nt$(OBJ): nt.c ../inczip/nt.h
+        
+install$(OBJ): ../install.c
+	$(CC) $(CFLAGS) $(CVER) $(GENFLAGS) $<
+        
+wxmain$(OBJ): ../wxmain.cpp
+	$(CC) $(CFLAGS) $(CVER) $(GENFLAGS) $<
+        
+instsup$(OBJ): ../instsup.cpp
+	$(CC) $(CFLAGS) $(CVER) $(GENFLAGS) $<
+
+clean:
+	$(RM) *$(OBJ)
+	$(RM) *$(EXE)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/makefile.gcc	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,142 @@
+#==============================================================================
+# Makefile for UnZip, UnZipSFX and fUnZip:  Unix and MS-DOS ("real" makes only)
+# Version:  5.4                                                19 November 1998
+#==============================================================================
+
+
+# INSTRUCTIONS (such as they are):
+#
+# "make sunos"	-- makes UnZip in current directory on a generic SunOS 4.x Sun
+# "make list"	-- lists all supported systems (targets)
+# "make help"	-- provides pointers on what targets to try if problems occur
+# "make wombat" -- chokes and dies if you haven't added the specifics for your
+#		    Wombat 68000 (or whatever) to the systems list
+#
+# CF are flags for the C compiler.  LF are flags for the loader.  LF2 are more
+# flags for the loader, if they need to be at the end of the line instead of at
+# the beginning (for example, some libraries).  FL and FL2 are the corre-
+# sponding flags for fUnZip.  LOCAL_UNZIP is an environment variable that can
+# be used to add default C flags to your compile without editing the Makefile
+# (e.g., -DDEBUG_STRUC, or -FPi87 on PCs using Microsoft C).
+#
+# Some versions of make do not define the macro "$(MAKE)"; this is rare, but
+# if things don't work, try using "make" instead of "$(MAKE)" in your system's
+# makerule.  Or try adding the following line to your .login file:
+#	setenv MAKE "make"
+# (That never works--makes that are too stupid to define MAKE are also too
+# stupid to look in the environment--but try it anyway for kicks. :-) )
+#
+# Memcpy and memset are provided for those systems that don't have them; they
+# are in fileio.c and will be used if -DZMEM is included in CF.  These days
+# almost all systems have them.
+#
+# Be sure to test your new UnZip (and UnZipSFX and fUnZip); successful compila-
+# tion does not always imply a working program.
+
+
+#####################
+# MACRO DEFINITIONS #
+#####################
+
+# Defaults most systems use (use LOCAL_UNZIP in environment to add flags,
+# such as -DDOSWILD).
+
+# UnZip flags
+CC = cc#	try using "gcc" target rather than changing this (CC and LD
+LD = $(CC)#	must match, else "unresolved symbol:  ___main" is possible)
+AS = as
+LOC = $(LOCAL_UNZIP)
+AF = $(LOC)
+CF = -O -g -I. -I.. -I../inczip $(LOC) -I/usr/local//include  -I/usr/X11R6/include -I/usr/local/lib/glib/include -DSTRICT  -D__WXGTK__ -DGTK_NO_CHECK_CASTS -D_REENTRANT -D_IODBC_ -Wall
+LF = -o sfx -L/usr/local/lib -L/usr/X11R6/lib -L/usr -lwx_gtk -lpng -ljpeg -lstdc++ -lgcc  -lc_r  -lgtk -lgdk -lgmodule -lglib -lXext -lX11 -lm -lgthread
+LF2 = -s
+
+# general-purpose stuff
+#CP = cp
+CP = ln
+LN = ln
+RM = rm -f
+CHMOD = chmod
+BINPERMS = 755
+MANPERMS = 644
+STRIP = strip
+E =
+O = .o
+M = unix
+SHELL = /bin/sh
+
+# defaults for crc32 stuff and system dependent headers
+CRC32 = crc32
+
+# object files
+OBJS1 = unzip$O $(CRC32)$O crctab$O crypt$O envargs$O explode$O
+OBJS2 = extract$O fileio$O globals$O inflate$O list$O match$O
+OBJS3 = process$O ttyio$O unreduce$O unshrink$O zipinfo$O
+OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O install$O wxmain$O instsup$O
+UNZIP_H = ../inczip/unzip.h ../inczip/unzpriv.h ../inczip/globals.h
+
+# installation
+# (probably can change next two to `install' and `install -d' if you have it)
+INSTALL = cp
+INSTALL_D = mkdir -p
+
+###############################################
+# BASIC COMPILE INSTRUCTIONS AND DEPENDENCIES #
+###############################################
+
+# this is for GNU make; comment out and notify zip-bugs if it causes errors
+.SUFFIXES:	.c .o .obj .pic.o
+
+# yes, we should be able to use the $O macro to combine these two, but it
+# fails on some brain-damaged makes (e.g., AIX's)...no big deal
+.c.o:
+	$(CC) -c $(CF) $*.c
+
+.c.obj:
+	$(CC) -c $(CF) $*.c
+
+.c.pic.o:
+	$(CC) -c $(CF) -o $@ $*.c
+
+all:	        sfx
+
+
+# EDIT HERE FOR PARALLEL MAKES on Sequent (and others?)--screws up MS-DOS
+# make utilities if default:  change "unzip$E:" to "unzip$E:&"
+
+sfx$E:	$(OBJS)			# add `&' for parallel makes
+	$(LD) $(LF) $(OBJS)
+
+crc32$O:	crc32.c $(UNZIP_H) ../inczip/zip.h
+crctab$O:	crctab.c $(UNZIP_H)  ../inczip/zip.h
+crypt$O:	crypt.c $(UNZIP_H)  ../inczip/zip.h  ../inczip/crypt.h  ../inczip/ttyio.h
+envargs$O:	envargs.c $(UNZIP_H)
+explode$O:	explode.c $(UNZIP_H)
+extract$O:	extract.c $(UNZIP_H)  ../inczip/crypt.h
+fileio$O:	fileio.c $(UNZIP_H)  ../inczip/crypt.h  ../inczip/ttyio.h  ../inczip/ebcdic.h
+funzip$O:	funzip.c $(UNZIP_H)  ../inczip/crypt.h  ../inczip/ttyio.h  ../inczip/tables.h
+globals$O:	globals.c $(UNZIP_H)
+inflate$O:	inflate.c  ../inczip/inflate.h $(UNZIP_H)
+list$O:		list.c $(UNZIP_H)
+match$O:	match.c $(UNZIP_H)
+process$O:	process.c $(UNZIP_H)
+ttyio$O:	ttyio.c $(UNZIP_H)  ../inczip/zip.h  ../inczip/crypt.h  ../inczip/ttyio.h
+unreduce$O:	unreduce.c $(UNZIP_H)
+unshrink$O:	unshrink.c $(UNZIP_H)
+unzip$O:	unzip.c $(UNZIP_H)  ../inczip/crypt.h  ../inczip/version.h  ../inczip/consts.h
+zipinfo$O:	zipinfo.c $(UNZIP_H)
+
+unix$O:		unix.c $(UNZIP_H)  ../inczip/version.h		# Unix only
+	$(CC) -c $(CF)  unix.c
+
+install$O:		../install.c	      
+	$(CC) -c $(CF)  ../install.c
+
+wxmain$O:		../wxmain.cpp
+	$(CC) -c $(CF)  ../wxmain.cpp
+
+instsup$O:	        ../instsup.cpp 
+	$(CC) -c $(CF)  ../instsup.cpp
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/makefile.os2	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,670 @@
+# Makefile for UnZip, UnZipSFX and fUnZip                     24 November 1998
+#
+#  supported compilers:
+#  - Microsoft C, version 6.00 or higher, for use under OS/2 1.x (16-bit)
+#  - Watcom C/C++, version 9.0+, for use under OS/2 1.x or 2.x+ (16/32-bit)
+#  - emx+gcc, version 0.9c or higher, for use under OS/2 2.x+ (32-bit)
+#  - IBM C Set++, for use under OS/2 2.x+ (32-bit)
+#  - Borland C++, for use under OS/2 2.x+ (32-bit)
+#  - Metaware High C/C++, for use under OS/2 2.x+ (32-bit)
+#
+#  supported cross-compilers:
+#  - Microsoft C, version 6.0 or 7.0, for use under DOS (16-bit)
+#  - Watcom C/C++, version 9.0+, for use under DOS/Win95/NT (16/32-bit)
+#  - GNU gcc (emx), version 0.9c or higher, for use under DOS/Win95/NT (32-bit)
+#
+#  supported assemblers:
+#  - Microsoft MASM 6.00 with Microsoft C
+#  - Watcom WASM with Watcom C/C++
+#  - GNU as with GNU gcc
+
+# To use MASM 5.x instead of MASM 6.00:
+#  - set AS="masm -t -Ml"
+#  - set ASEOL=";"
+
+# To use, enter "{d,n}make -f os2/makefile.os2" (this makefile depends on its
+# name being "makefile.os2", and it must be in the os2 subdirectory).
+
+# Notes on Microsoft C 6.00 compilation for OS/2:
+#
+#   The resulting programs can be used under OS/2 protected mode only, not
+#   under DOS.  A larger stack has to be used for OS/2 because system calls
+#   use more stack than under DOS; 8k is recommended by Microsoft.
+
+# Notes on IBM C Set++, Watcom C/C++, Borland C++ or emx+gcc compilation:
+#
+#   The resulting programs can be used under protected mode of OS/2 2.x or
+#   higher only, not under OS/2 1.x and not under DOS.
+#
+#   The NFLAGS macro is used to work around an optimization bug in the IBM
+#   C++ Set compiler; this is fixed by CSD #4, so NFLAGS="" can be used for
+#   all targets below.
+
+# Notes on Watcom C/C++ compilation for DOS with the PMODE/W extender:
+#
+#   You need to add the following section to your \watcom\binb\wlsystem.lnk
+#   file and also need to copy pmodew.exe to the same directory:
+#
+#   system begin pmodew
+#       option osname='PMODE/W'
+#       libpath %WATCOM%\lib386
+#       libpath %WATCOM%\lib386\dos
+#       op stub=pmodew.exe
+#       format os2 le
+#   end
+#
+#   PMODE/W 1.16 or higher is required.  See also msdos/README for important
+#   notes about PMODE/W bugs.
+
+default:
+	@echo "Enter `$(MAKE) -f os2/makefile.os2 target' from the main"
+	@echo "UnZip directory, where target is one of:"
+	@echo "   msc mscdebug mscdos ibm ibmdyn ibmdebug ibmprof"
+	@echo "   ibmdll ibmdyndll ibmdebugdll ibmprofdll"
+	@echo "   metaware borland gcc gccdyn gccdebug gccdos gccwin32"
+	@echo "   watcom watcom16 watcomdos watcom16dos pmodew watcomwin32"
+
+# MS C 6.00 for OS/2, 16-bit (should figure out way to split unzip/funzip
+# compiles so former is always large model and latter always small model...)
+msc:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="cl -nologo -AL -Ocegit -Gs -I. $(FP)" \
+	CFLAGS="-G2 -Zp1 -W3 -DOS2 -DMSC -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="ml -nologo -c -Zm -Cp" \
+	ASFLAGS="-D__LARGE__ -D__286" \
+	LDFLAGS="-F 2000 -Lp -Fe" \
+	LDFLAGS2="-link /noe" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	CRC32="crc_i86" \
+	CRC32F="crc_i86" \
+	CRC32X="crc_i86" \
+	DEF="os2\unzip.def"
+
+# MS C 6.00 for OS/2, debug version
+mscdebug:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="cl -nologo -AL -Zi -Od -I. $(FP)" \
+	CFLAGS="-G2 -Zp1 -W3 -DOS2 -DMSC -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="ml -nologo -c -Zim -Cp" \
+	ASFLAGS="-D__LARGE__ -D__286" \
+	LDFLAGS="-F 2000 -Lp -Fe" \
+	LDFLAGS2="-link /noe" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	CRC32="crc_i86" \
+	CRC32F="crc_i86" \
+	CRC32X="crc_i86" \
+	DEF="os2\unzip.def"
+
+# cross-compilation for MS-DOS with MS C 6.00 (same comment as above...formerly;
+# now unzip is medium model again, with [almost] all strings in far memory)
+mscdos:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="cl -nologo -AM -Oaict -Gs -I. $(FP)" \
+	CFLAGS="-Zp1 -W3 -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="ml -nologo -c -Zm -Cp" \
+	ASFLAGS="-D__MEDIUM__" \
+	LDFLAGS="-F 0C00 -Lr -Fe" \
+	LDFLAGS2="-link /noe /exe" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	CRC32="crc_i86" \
+	CRC32F="crc_i86" \
+	CRC32X="crc_i86" \
+	OBJU2="msdos.obj" \
+	OBJX2="msdos_.obj" \
+	OSDEP_H="msdos/doscfg.h"
+
+# IBM C Set, statically linked runtime
+ibm:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="icc -Q -O -Gs -I." \
+	CFLAGS="-Sm -Sp1 -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	LDFLAGS="-B/ST:0x50000 -Fe" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	DEF="os2\unzip.def"
+
+# IBM C Set, dynamically linked runtime
+ibmdyn:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="icc -Q -O -Gs -Gd -I." \
+	CFLAGS="-Sm -Sp1 -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	LDFLAGS="-B/ST:0x50000 -Fe" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	DEF="os2\unzip.def"
+
+# IBM C Set, debug version
+ibmdebug:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="icc -Q -Ti -I." \
+	CFLAGS="-Sm -Sp1 -D__DEBUG_ALLOC__ -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	LDFLAGS="-B/ST:0x50000 -Fe" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	DEF="os2\unzip.def"
+
+# IBM C Set, profiling version for PROFIT
+ibmprof:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="icc -Q -O -Gs -Gh -Ti -I." \
+	CFLAGS="-Sm -Sp1 -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	LDFLAGS="-B/ST:0x50000 -Fe" \
+	LDFLAGS2="cppopa3.obj" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	DEF="os2\unzip.def"
+
+# IBM C Set, statically linked runtime
+ibmdll:
+	$(MAKE) -f os2/makefile.os2 dll \
+	CC="icc -Q -O -Gs -I." \
+	CFLAGS="-Sm -Sp1 -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="-Gm -Ge- -DDLL -DOS2DLL -DAPI_DOC" \
+	LDFLAGS="-Fe" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	DLLDEF="os2\rexxapi.def" \
+	STUBDEF="os2\stub.def" \
+	DEF="os2\unzip.def" \
+	APILIB="REXX.lib"
+
+# IBM C Set, dynamically linked runtime
+ibmdyndll:
+	$(MAKE) -f os2/makefile.os2 dll \
+	CC="icc -Q -O -Gs -Gd -I." \
+	CFLAGS="-Sm -Sp1 -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="-Gm -Ge- -DDLL -DOS2DLL -DAPI_DOC" \
+	LDFLAGS="-Fe" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	DLLDEF="os2\rexxapi.def" \
+	STUBDEF="os2\stub.def" \
+	DEF="os2\unzip.def" \
+	APILIB="REXX.lib"
+
+# IBM C Set, debug version
+ibmdebugdll:
+	$(MAKE) -f os2/makefile.os2 dll \
+	CC="icc -Q -Ti -I." \
+	CFLAGS="-Sm -Sp1 -D__DEBUG_ALLOC__ -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="-Gm -Ge- -DDLL -DOS2DLL -DAPI_DOC" \
+	LDFLAGS="-Fe" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	DLLDEF="os2\rexxapi.def" \
+	STUBDEF="os2\stub.def" \
+	DEF="os2\unzip.def" \
+	APILIB="REXX.lib"
+
+# IBM C Set, profiling version for PROFIT
+ibmprofdll:
+	$(MAKE) -f os2/makefile.os2 dll \
+	CC="icc -Q -O -Gs -Gh -Ti -I." \
+	CFLAGS="-Gm -Sm -Sp1 -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="-Gm -Ge- -DDLL -DOS2DLL -DAPI_DOC" \
+	LDFLAGS="-Fe" \
+	LDFLAGS2="profit.obj" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	DLLDEF="os2\rexxapi.def" \
+	STUBDEF="os2\stub.def" \
+	DEF="os2\unzip.def" \
+	APILIB="REXX.lib"
+
+# Watcom C/386 9.0 or higher
+watcom:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="wcl386 -bt=os2v2 -zq -Ox -s -I." \
+	CFLAGS="-Zp1 -DOS2 -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="wasm -bt=os2v2 -zq -3 -mf" \
+	ASFLAGS="" \
+	LDFLAGS="-k0x50000 -x -l=os2v2 -Fe=" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	CRC32="crc_i386" \
+	CRC32F="crc_i386" \
+	CRC32X="crc_i386" \
+	DEF="" \
+	DIRSEP="\\" \
+	AS_DIRSEP="\\"
+
+# Watcom C/286 9.0 or higher
+watcom16:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="wcl -bt=os2 -zq -ml -Ox -s -I." \
+	CFLAGS="-Zp1 -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="wasm -bt=os2 -zq -2 -ml" \
+	ASFLAGS="" \
+	LDFLAGS="-k0x2000 -x -l=os2 -Fe=" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	CRC32="crc_i86" \
+	CRC32F="crc_i86" \
+	CRC32X="crc_i86" \
+	DIRSEP="\\" \
+	AS_DIRSEP="\\"
+
+# Watcom C/386 9.0 or higher, crosscompilation for DOS, DOS4GW extender
+watcomdos:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="wcl386 -bt=dos4g -zq -Ox -s -I." \
+	CFLAGS="-Zp1 -DMSDOS -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="wasm -bt=dos4g -zq -3 -mf" \
+	ASFLAGS="" \
+	LDFLAGS="-k0x50000 -x -l=dos4g -Fe=" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	CRC32="crc_i386" \
+	CRC32F="crc_i386" \
+	CRC32X="crc_i386" \
+	OBJU2="msdos.obj" \
+	OBJX2="msdos_.obj" \
+	OSDEP_H="msdos/doscfg.h" \
+	DIRSEP="\\" \
+	AS_DIRSEP="\\"
+
+# Watcom C/386 9.0 or higher, crosscompilation for DOS, PMODE/W extender
+pmodew:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="wcl386 -bt=dos4g -zq -Ox -s -I." \
+	CFLAGS="-Zp1 -DMSDOS -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="wasm -bt=dos4g -zq -3 -mf" \
+	ASFLAGS="" \
+	LDFLAGS="-k0x50000 -x -l=pmodew -Fe=" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	CRC32="crc_i386" \
+	CRC32F="crc_i386" \
+	CRC32X="crc_i386" \
+	OBJU2="msdos.obj" \
+	OBJX2="msdos_.obj" \
+	OSDEP_H="msdos/doscfg.h" \
+	DIRSEP="\\" \
+	AS_DIRSEP="\\"
+
+# Watcom C/286 9.0 or higher, crosscompilation for DOS
+watcom16dos:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="wcl -bt=dos -zq -ml -Ox -s -I." \
+	CFLAGS="-Zp1 -DMSDOS $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="wasm -bt=dos -0 -mm" \
+	ASFLAGS="-D__MEDIUM__" \
+	LDFLAGS="-k0xC00 -x -l=dos -Fe=" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	OBJU2="msdos.obj" \
+	OBJX2="msdos_.obj" \
+	OSDEP_H="msdos/doscfg.h" \
+	DIRSEP="\\" \
+	AS_DIRSEP="\\"
+
+# Watcom C/386 9.0 or higher, crosscompilation for Win95/NT
+watcomwin32:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="wcl386 -bt=NT -zq -Ox -s -I." \
+	CFLAGS="-Zp1 -DWIN32 -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="wasm -bt=NT -zq -3 -mf" \
+	ASFLAGS="" \
+	LDFLAGS="-k0x50000 -x -l=NT -Fe=" \
+	LDFLAGS2="" \
+	OUT="-Fo" \
+	OBJ=".obj" \
+	OBJU2="win32.obj nt.obj" \
+	OBJX2="win32_.obj nt_.obj" \
+	CRC32="crc_i386" \
+	CRC32F="crc_i386" \
+	CRC32X="crc_i386" \
+	DEF="" \
+	DIRSEP="\\" \
+	AS_DIRSEP="\\"
+
+# MetaWare High C/C++ 3.2
+metaware:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="hc -O2 -I." \
+	CFLAGS="-D__32BIT__ -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	LDFLAGS="-o " \
+	LDFLAGS2="" \
+	OUT="-o ./" \
+	OBJ=".obj" \
+	DEF="-Hdef=os2\unzip.def"
+
+# Borland C++
+borland:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="bcc -O -I. -Ios2" \
+	CFLAGS="-w- -D__cdecl -D__32BIT__ -DOS2 $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	LDFLAGS="-e" \
+	LDFLAGS2="" \
+	OUT="-o" \
+	OBJ=".obj" \
+	DEF="-sDos2\unzip.def"
+
+# emx, gcc, OMF format, statically linked C runtime
+gcc:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="gcc -Zomf -O -I." \
+	CFLAGS="-Wall -DOS2 -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="gcc -Zomf" \
+	ASFLAGS="-Di386" \
+	LDFLAGS="-o ./" \
+	LDFLAGS2="-Zsmall-conv -Zstack 320 -Zsys -s" \
+	OUT="-o" \
+	OBJ=".obj" \
+	CRC32="crc_gcc" \
+	CRC32F="crc_gcc" \
+	CRC32X="crc_gcc" \
+	DEF="os2/unzip.def"
+
+# emx, gcc, OMF format, dynamically linked C runtime
+gccdyn:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="gcc -Zomf -O -I." \
+	CFLAGS="-Wall -DOS2 -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="gcc -Zomf" \
+	ASFLAGS="-Di386" \
+	LDFLAGS="-o ./" \
+	LDFLAGS2="-Zstack 320 -Zcrtdll -s" \
+	OUT="-o" \
+	OBJ=".obj" \
+	CRC32="crc_gcc" \
+	CRC32F="crc_gcc" \
+	CRC32X="crc_gcc" \
+	DEF="os2/unzip.def"
+
+# emx, gcc, a.out format, with debug info for gdb
+gccdebug:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="gcc -g -I." \
+	CFLAGS="-Wall -DOS2 -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="gcc -g" \
+	ASFLAGS="-Di386" \
+	LDFLAGS="-o ./" \
+	LDFLAGS2="-Zsmall-conv" \
+	OUT="-o" \
+	OBJ=".o" \
+	CRC32="crc_gcc" \
+	CRC32F="crc_gcc" \
+	CRC32X="crc_gcc"
+
+# emx, gcc, a.out format, cross-compilation for MS-DOS
+gccdos:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="gcc -O -I." \
+	CFLAGS="-Wall -DMSDOS -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="gcc" \
+	ASFLAGS="-Di386" \
+	LDFLAGS="-o ./" \
+	LDFLAGS2="-Zsmall-conv -s" \
+	OUT="-o" \
+	OBJ=".o" \
+	CRC32="crc_gcc" \
+	CRC32F="crc_gcc" \
+	CRC32X="crc_gcc" \
+	OBJU2="msdos.o" \
+	OBJX2="msdos_.o" \
+	OSDEP_H="msdos/doscfg.h"
+
+# emx, gcc, RSXNT, cross-compilation for Win32, statically linked C runtime
+gccwin32:
+	$(MAKE) -f os2/makefile.os2 all \
+	CC="gcc -Zwin32 -O2 -I." \
+	CFLAGS="-Wall -DWIN32 -DASM_CRC $(LOCAL_UNZIP)" \
+	NFLAGS="" \
+	DLLFLAG="" \
+	AS="gcc" \
+	ASFLAGS="-Di386" \
+	LDFLAGS="-Zsys -o ./" \
+	LDFLAGS2="-ladvapi32 -Zsmall-conv -s" \
+	OUT="-o" \
+	OBJ=".o" \
+	CRC32="crc_gcc" \
+	CRC32F="crc_gcc" \
+	CRC32X="crc_gcc" \
+	OBJU2="win32.o nt.o" \
+	OBJX2="win32_.o nt_.o" \
+	OBJF2="win32f.o" \
+	OSDEP_H="win32/w32cfg.h"
+
+# variables
+
+# LOCAL_UNZIP = -DREENTRANT
+
+# default settings for target dependent macros:
+DIRSEP = /
+AS_DIRSEP = /
+
+OSDEP_H = os2/os2data.h os2/os2cfg.h
+CRC32   = crc32
+CRC32F  = crc32f
+CRC32X  = crc32_
+
+OBJU  = unzip$(OBJ) $(CRC32)$(OBJ) crctab$(OBJ) crypt$(OBJ) envargs$(OBJ) \
+	explode$(OBJ) extract$(OBJ) fileio$(OBJ) globals$(OBJ) \
+	inflate$(OBJ) list$(OBJ) match$(OBJ) process$(OBJ) ttyio$(OBJ) \
+	unreduce$(OBJ) unshrink$(OBJ) zipinfo$(OBJ)
+OBJU2 = os2$(OBJ) os2acl$(OBJ)
+OBJX  = unzipsf_$(OBJ) $(CRC32X)$(OBJ) crctab_$(OBJ) crypt_$(OBJ) \
+        extract_$(OBJ) fileio_$(OBJ) globals_$(OBJ) inflate_$(OBJ) \
+	match_$(OBJ) process_$(OBJ) ttyio_$(OBJ)
+OBJX2 = os2_$(OBJ) os2acl_$(OBJ)
+OBJDLL= api$(OBJ) apihelp$(OBJ) rexxhelp$(OBJ) rexxapi$(OBJ)
+OBJF  = funzip$(OBJ) $(CRC32F)$(OBJ) cryptf$(OBJ) inflatef$(OBJ) \
+	globalsf$(OBJ) ttyiof$(OBJ)
+OBJF2 =
+
+UNZIP_H = unzip.h unzpriv.h globals.h $(OSDEP_H)
+
+# rules
+
+.SUFFIXES:	.c .asm $(OBJ)
+
+.c$(OBJ):
+	$(CC) -c $(CFLAGS) $(DLLFLAG) $<
+
+.asm$(OBJ):
+	$(AS) $(ASFLAGS) $< $(ASEOL)
+
+# targets
+
+all:	unzip.exe funzip.exe unzipsfx.exe
+dll:	unzip32.dll unzip.stb funzip.exe unzipsfx.exe
+
+unzip.exe: $(OBJU) $(OBJU2)
+	$(CC) $(LDFLAGS)$@ $(DEF) $(OBJU) $(OBJU2) $(LDFLAGS2)
+
+funzip.exe: $(OBJF) $(OBJF2)
+	$(CC) $(LDFLAGS)$@ $(DEF) $(OBJF) $(OBJF2) $(LDFLAGS2)
+
+unzipsfx.exe:	$(OBJX) $(OBJX2)
+	$(CC) $(LDFLAGS)$@ $(DEF) $(OBJX) $(OBJX2) $(LDFLAGS2)
+
+unzip32.dll: $(DLLDEF) $(OBJU) $(OBJU2) $(OBJDLL)
+	$(CC) $(DLLFLAG) $(LDFLAGS)$@ $(DLLDEF) $(OBJU) $(OBJDLL) $(OBJU2) $(APILIB) $(LDFLAGS2)
+
+unzip.stb: unzipstb$(OBJ) $(STUBDEF)
+	$(CC) $(LDFLAGS)$@ $(STUBDEF) unzipstb$(OBJ) $(LDFLAGS2)
+	copy unzip.stb unzip.exe
+
+# dependencies
+
+apihelp$(OBJ):	apihelp.c $(UNZIP_H) version.h
+crc32$(OBJ):	crc32.c $(UNZIP_H) zip.h
+crctab$(OBJ):	crctab.c $(UNZIP_H) zip.h
+envargs$(OBJ):	envargs.c $(UNZIP_H)
+explode$(OBJ):	explode.c $(UNZIP_H)
+extract$(OBJ):	extract.c $(UNZIP_H) crypt.h
+fileio$(OBJ):	fileio.c $(UNZIP_H) crypt.h ttyio.h ebcdic.h
+globals$(OBJ):	globals.c $(UNZIP_H)
+inflate$(OBJ):	inflate.c $(UNZIP_H)
+list$(OBJ):	list.c $(UNZIP_H)
+match$(OBJ):	match.c $(UNZIP_H)
+process$(OBJ):	process.c $(UNZIP_H)
+ttyio$(OBJ):	ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h
+unreduce$(OBJ):	unreduce.c $(UNZIP_H)
+unshrink$(OBJ):	unshrink.c $(UNZIP_H)
+unzip$(OBJ):	unzip.c $(UNZIP_H) crypt.h version.h consts.h
+api$(OBJ):	api.c $(UNZIP_H) version.h
+zipinfo$(OBJ):	zipinfo.c $(UNZIP_H)
+
+funzip$(OBJ):	funzip.c $(UNZIP_H) crypt.h ttyio.h tables.h	# funzip only
+	$(CC) -c $(CFLAGS) funzip.c
+
+unzipstb$(OBJ):	unzipstb.c					# DLL version
+	$(CC) -c $(CFLAGS) unzipstb.c
+
+msdos$(OBJ):	msdos/msdos.c $(UNZIP_H) version.h		# DOS only
+	$(CC) -c $(CFLAGS) msdos$(DIRSEP)msdos.c
+
+msdos_$(OBJ):	msdos/msdos.c $(UNZIP_H)			# DOS unzipsfx
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ msdos$(DIRSEP)msdos.c
+
+win32$(OBJ):	win32/win32.c $(UNZIP_H) win32/nt.h version.h	# Win32 only
+	$(CC) -c $(CFLAGS) win32$(DIRSEP)win32.c
+
+nt$(OBJ):	win32/nt.c $(UNZIP_H) win32/nt.h		# Win32 only
+	$(CC) -c $(CFLAGS) win32$(DIRSEP)nt.c
+
+win32_$(OBJ):	win32/win32.c $(UNZIP_H) win32/nt.h		# Win32 unzipsfx
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ win32$(DIRSEP)win32.c
+
+nt_$(OBJ):	win32/nt.c $(UNZIP_H) win32/nt.h		# Win32 unzipsfx
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ win32$(DIRSEP)nt.c
+
+win32f$(OBJ):	win32/win32.c $(UNZIP_H) win32/nt.h		# Win32 funzip
+	$(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ win32$(DIRSEP)win32.c
+
+os2$(OBJ):	os2/os2.c $(UNZIP_H) version.h			# OS/2 only
+	$(CC) -c $(CFLAGS) $(DLLFLAG) os2$(DIRSEP)os2.c
+
+os2_$(OBJ):	os2/os2.c $(UNZIP_H)				# OS/2 unzipsfx
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ os2$(DIRSEP)os2.c
+
+os2acl$(OBJ):	os2/os2acl.c $(UNZIP_H) version.h		# OS/2 only
+	$(CC) -c $(CFLAGS) $(DLLFLAG) os2$(DIRSEP)os2acl.c
+
+os2acl_$(OBJ):	os2/os2acl.c $(UNZIP_H) version.h		# OS/2 unzipsfx
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ os2$(DIRSEP)os2acl.c
+
+rexxhelp$(OBJ):	os2/rexxhelp.c					# OS/2 DLL only
+	$(CC) -c $(CFLAGS) $(DLLFLAG) os2$(DIRSEP)rexxhelp.c
+
+rexxapi$(OBJ):	os2/rexxapi.c					# OS/2 DLL only
+	$(CC) -c $(CFLAGS) $(DLLFLAG) os2$(DIRSEP)rexxapi.c
+
+crc_i86$(OBJ):	msdos/crc_i86.asm				# 16bit only
+	$(AS) $(ASFLAGS) msdos$(AS_DIRSEP)crc_i86.asm $(ASEOL)
+
+crc_i386$(OBJ):	win32/crc_i386.asm				# 32bit, MASM
+	$(AS) $(ASFLAGS) win32$(AS_DIRSEP)crc_i386.asm $(ASEOL)
+
+crc_gcc$(OBJ):	crc_i386.S					# 32bit, GNU AS
+	$(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S
+
+# NFLAGS are solely used as work-around for optimization bug in IBM C++ Set
+crypt$(OBJ):	crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h
+	$(CC) -c $(CFLAGS) $(DLLFLAG) $(NFLAGS) crypt.c
+
+cryptf$(OBJ):	crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h	# funzip only
+	$(CC) -c $(CFLAGS) $(NFLAGS) -DFUNZIP $(OUT)$@ crypt.c
+
+crc32f$(OBJ):	crc32.c $(UNZIP_H) zip.h			# funzip only
+	$(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ crc32.c
+
+globalsf$(OBJ):	globals.c $(UNZIP_H)				# funzip only
+	$(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ globals.c
+
+inflatef$(OBJ):	inflate.c inflate.h $(UNZIP_H) crypt.h		# funzip only
+	$(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ inflate.c
+
+ttyiof$(OBJ):	ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h	# funzip only
+	$(CC) -c $(CFLAGS) $(NFLAGS) -DFUNZIP $(OUT)$@ ttyio.c
+
+crc32_$(OBJ):	crc32.c $(UNZIP_H) zip.h			# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ crc32.c
+
+crctab_$(OBJ):	crctab.c $(UNZIP_H) zip.h			# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ crctab.c
+
+crypt_$(OBJ):	crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h	# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ crypt.c
+
+extract_$(OBJ):	extract.c $(UNZIP_H) crypt.h			# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ extract.c
+
+fileio_$(OBJ):	fileio.c $(UNZIP_H) crypt.h ttyio.h ebcdic.h	# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ fileio.c
+
+globals_$(OBJ):	globals.c $(UNZIP_H)				# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ globals.c
+
+inflate_$(OBJ):	inflate.c inflate.h $(UNZIP_H) crypt.h		# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ inflate.c
+
+match_$(OBJ):	match.c $(UNZIP_H)				# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ match.c
+
+process_$(OBJ):	process.c $(UNZIP_H)				# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ process.c
+
+ttyio_$(OBJ):	ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h	# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ ttyio.c
+
+unzipsf_$(OBJ):	unzip.c $(UNZIP_H) crypt.h version.h consts.h	# unzipsfx only
+	$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ unzip.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/makefile.vc	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,95 @@
+#
+WXDIR = $(WXWIN)
+CC = cl
+CFLAGS = -c -Od -Gy -GX -DWIN32 -D__WIN32__ -DMSVC -I. -I.. -I..\inczip  -I$(WXDIR)\include -D__WXMSW__ -DWXDEBUG=1 -D__WXDEBUG__ -DUSE_DEFINE -DWIN32 -D__WIN95__ -D__WINDOWS__
+CFLAGS_DEBUG = -Zi
+CFLAGS_COMPILE = -MDd
+LIBS=kernel32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib winmm.lib shell32.lib oldnames.lib\
+ comctl32.lib ctl3d32.lib odbc32.lib ole32.lib oleaut32.lib uuid.lib rpcrt4.lib advapi32.lib wsock32.lib \
+  $(WXDIR)\lib\wxd.lib $(WXDIR)\lib\xpmd.lib # libci.lib # libci.lib required for VC++ 4.2
+
+RES = 
+LINKFLAGS = -machine:i386 -debug:full -debugtype:cv -nodefaultlib:libcmtd
+DLLLINKFLAGS = -dll
+LINK = link
+
+OBJS = 	api.obj \
+	apihelp.obj \
+	crc32.obj \
+	crctab.obj \
+	crypt.obj \
+	envargs.obj \
+	explode.obj \
+	extract.obj \
+	fileio.obj \
+	globals.obj \
+	inflate.obj \
+	list.obj \
+	match.obj \
+	nt.obj \
+	..\install.obj \
+        ..\wxmain.obj \
+        ..\instsup.obj \
+	process.obj \
+	unreduce.obj \
+	unshrink.obj \
+	unzip.obj \
+	win32.obj \
+	zipinfo.obj
+
+LINKOBJS = 	api.obj \
+		apihelp.obj \
+		crc32.obj \
+		crctab.obj \
+		crypt.obj \
+		envargs.obj \
+		explode.obj \
+		extract.obj \
+		fileio.obj \
+		globals.obj \
+		inflate.obj \
+		list.obj \
+		match.obj \
+		nt.obj \
+		install.obj \
+        	wxmain.obj \
+	        instsup.obj \
+		process.obj \
+		unreduce.obj \
+		unshrink.obj \
+		unzip.obj \
+		win32.obj \
+		zipinfo.obj
+                
+all: sfx.exe
+
+clean:
+	-erase *.dll
+        -erase *.exe
+        -erase *.opt
+        -erase *.lib
+        -erase *.obj
+        -erase *.map
+        -erase *.pdb
+        -erase *.ilk
+        -erase *.exp
+        -erase *.res
+        -erase *~
+        
+sfx.exe: $(OBJS) sfx.res
+	$(LINK) @<<
+-out:$(@) -subsystem:windows -entry:WinMainCRTStartup
+$(LINKFLAGS)
+$(LINKOBJS)
+$(LIBS)
+sfx.res
+<<
+
+sfx.res: sfx.rc $(WXWIN)\include\wx\msw\wx.rc
+	rc -r -i$(WXWIN)\include sfx.rc
+        
+.c.obj:
+	$(CC) $(CFLAGS) $(CFLAGS_DEBUG) $(CFLAGS_COMPILE) $*.c
+        
+.cpp.obj:
+	$(CC) $(CFLAGS) $(CFLAGS_DEBUG) $(CFLAGS_COMPILE) $*.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/match.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,294 @@
+/*---------------------------------------------------------------------------
+
+  match.c
+
+  The match() routine recursively compares a string to a "pattern" (regular
+  expression), returning TRUE if a match is found or FALSE if not.  This
+  version is specifically for use with unzip.c:  as did the previous match()
+  routines from SEA and J. Kercheval, it leaves the case (upper, lower, or
+  mixed) of the string alone, but converts any uppercase characters in the
+  pattern to lowercase if indicated by the global var pInfo->lcflag (which
+  is to say, string is assumed to have been converted to lowercase already,
+  if such was necessary).
+
+  GRR:  reversed order of text, pattern in matche() (now same as match());
+        added ignore_case/ic flags, Case() macro.
+
+  PaulK:  replaced matche() with recmatch() from Zip, modified to have an
+          ignore_case argument; replaced test frame with simpler one.
+
+  ---------------------------------------------------------------------------
+
+  Copyright on recmatch() from Zip's util.c (although recmatch() was almost
+  certainly written by Mark Adler...ask me how I can tell :-) ):
+
+     Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly,
+     Kai Uwe Rommel and Igor Mandrichenko.
+
+     Permission is granted to any individual or institution to use, copy,
+     or redistribute this software so long as all of the original files are
+     included unmodified, that it is not sold for profit, and that this copy-
+     right notice is retained.
+
+  ---------------------------------------------------------------------------
+
+  Match the pattern (wildcard) against the string (fixed):
+
+     match(string, pattern, ignore_case);
+
+  returns TRUE if string matches pattern, FALSE otherwise.  In the pattern:
+
+     `*' matches any sequence of characters (zero or more)
+     `?' matches any single character
+     [SET] matches any character in the specified set,
+     [!SET] or [^SET] matches any character not in the specified set.
+
+  A set is composed of characters or ranges; a range looks like ``character
+  hyphen character'' (as in 0-9 or A-Z).  [0-9a-zA-Z_] is the minimal set of
+  characters allowed in the [..] pattern construct.  Other characters are
+  allowed (i.e., 8-bit characters) if your system will support them.
+
+  To suppress the special syntactic significance of any of ``[]*?!^-\'', in-
+  side or outside a [..] construct, and match the character exactly, precede
+  it with a ``\'' (backslash).
+
+  Note that "*.*" and "*." are treated specially under MS-DOS if DOSWILD is
+  defined.  See the DOSWILD section below for an explanation.  Note also
+  that with VMSWILD defined, '%' is used instead of '?', and sets (ranges)
+  are delimited by () instead of [].
+
+  ---------------------------------------------------------------------------*/
+
+
+
+/* define ToLower() in here (for Unix, define ToLower to be macro (using
+ * isupper()); otherwise just use tolower() */
+#define UNZIP_INTERNAL
+#include "unzip.h"
+
+#if 0  /* this is not useful until it matches Amiga names insensitively */
+#ifdef AMIGA        /* some other platforms might also want to use this */
+#  define ANSI_CHARSET       /* MOVE INTO UNZIP.H EVENTUALLY */
+#endif
+#endif /* 0 */
+  
+#ifdef ANSI_CHARSET
+#  ifdef ToLower
+#    undef ToLower
+#  endif
+   /* uppercase letters are values 41 thru 5A, C0 thru D6, and D8 thru DE */
+#  define IsUpper(c) (c>=0xC0 ? c<=0xDE && c!=0xD7 : c>=0x41 && c<=0x5A)
+#  define ToLower(c) (IsUpper((uch) c) ? (unsigned) c | 0x20 : (unsigned) c)
+#endif
+#define Case(x)  (ic? ToLower(x) : (x))
+
+#ifdef VMSWILD
+#  define WILDCHAR   '%'
+#  define BEG_RANGE  '('
+#  define END_RANGE  ')'
+#else
+#  define WILDCHAR   '?'
+#  define BEG_RANGE  '['
+#  define END_RANGE  ']'
+#endif
+
+#if 0                /* GRR:  add this to unzip.h someday... */
+#if !(defined(MSDOS) && defined(DOSWILD))
+#define match(s,p,ic)   (recmatch((ZCONST uch *)p,(ZCONST uch *)s,ic) == 1)
+int recmatch OF((ZCONST uch *pattern, ZCONST uch *string, int ignore_case));
+#endif
+#endif /* 0 */
+static int recmatch OF((ZCONST uch *pattern, ZCONST uch *string,
+                        int ignore_case));
+
+
+
+/* match() is a shell to recmatch() to return only Boolean values. */
+
+int match(string, pattern, ignore_case)
+    ZCONST char *string, *pattern;
+    int ignore_case;
+{
+#if (defined(MSDOS) && defined(DOSWILD))
+    char *dospattern;
+    int j = strlen(pattern);
+
+/*---------------------------------------------------------------------------
+    Optional MS-DOS preprocessing section:  compare last three chars of the
+    wildcard to "*.*" and translate to "*" if found; else compare the last
+    two characters to "*." and, if found, scan the non-wild string for dots.
+    If in the latter case a dot is found, return failure; else translate the
+    "*." to "*".  In either case, continue with the normal (Unix-like) match
+    procedure after translation.  (If not enough memory, default to normal
+    match.)  This causes "a*.*" and "a*." to behave as MS-DOS users expect.
+  ---------------------------------------------------------------------------*/
+
+    if ((dospattern = (char *)malloc(j+1)) != NULL) {
+        strcpy(dospattern, pattern);
+        if (!strcmp(dospattern+j-3, "*.*")) {
+            dospattern[j-2] = '\0';                    /* nuke the ".*" */
+        } else if (!strcmp(dospattern+j-2, "*.")) {
+            char *p = strchr(string, '.');
+
+            if (p) {   /* found a dot:  match fails */
+                free(dospattern);
+                return 0;
+            }
+            dospattern[j-1] = '\0';                    /* nuke the end "." */
+        }
+        j = recmatch((uch *)dospattern, (uch *)string, ignore_case);
+        free(dospattern);
+        return j == 1;
+    } else
+#endif /* MSDOS && DOSWILD */
+    return recmatch((uch *)pattern, (uch *)string, ignore_case) == 1;
+}
+
+
+
+static int recmatch(p, s, ic)
+    ZCONST uch *p;        /* sh pattern to match */
+    ZCONST uch *s;        /* string to which to match it */
+    int ic;               /* true for case insensitivity */
+/* Recursively compare the sh pattern p with the string s and return 1 if
+ * they match, and 0 or 2 if they don't or if there is a syntax error in the
+ * pattern.  This routine recurses on itself no more deeply than the number
+ * of characters in the pattern. */
+{
+    unsigned int c;       /* pattern char or start of range in [-] loop */ 
+
+    /* Get first character, the pattern for new recmatch calls follows */
+    c = *p++;
+
+    /* If that was the end of the pattern, match if string empty too */
+    if (c == 0)
+        return *s == 0;
+
+    /* '?' (or '%') matches any character (but not an empty string) */
+    if (c == WILDCHAR)
+        return *s ? recmatch(p, s + 1, ic) : 0;
+
+    /* '*' matches any number of characters, including zero */
+#ifdef AMIGA
+    if (c == '#' && *p == '?')     /* "#?" is Amiga-ese for "*" */
+        c = '*', p++;
+#endif /* AMIGA */
+    if (c == '*') {
+        if (*p == 0)
+            return 1;
+        for (; *s; s++)
+            if ((c = recmatch(p, s, ic)) != 0)
+                return (int)c;
+        return 2;       /* 2 means give up--match will return false */
+    }
+
+    /* Parse and process the list of characters and ranges in brackets */
+    if (c == BEG_RANGE) {
+        int e;          /* flag true if next char to be taken literally */
+        ZCONST uch *q;  /* pointer to end of [-] group */
+        int r;          /* flag true to match anything but the range */
+
+        if (*s == 0)                           /* need a character to match */
+            return 0;
+        p += (r = (*p == '!' || *p == '^'));   /* see if reverse */
+        for (q = p, e = 0; *q; q++)            /* find closing bracket */
+            if (e)
+                e = 0;
+            else
+                if (*q == '\\')      /* GRR:  change to ^ for MS-DOS, OS/2? */
+                    e = 1;
+                else if (*q == END_RANGE)
+                    break;
+        if (*q != END_RANGE)         /* nothing matches if bad syntax */
+            return 0;
+        for (c = 0, e = *p == '-'; p < q; p++) {  /* go through the list */
+            if (e == 0 && *p == '\\')             /* set escape flag if \ */
+                e = 1;
+            else if (e == 0 && *p == '-')         /* set start of range if - */
+                c = *(p-1);
+            else {
+                unsigned int cc = Case(*s);
+
+                if (*(p+1) != '-')
+                    for (c = c ? c : *p; c <= *p; c++)  /* compare range */
+                        if ((unsigned)Case(c) == cc)  /* typecast for MSC bug */
+                            return r ? 0 : recmatch(q + 1, s + 1, ic);
+                c = e = 0;   /* clear range, escape flags */
+            }
+        }
+        return r ? recmatch(q + 1, s + 1, ic) : 0;  /* bracket match failed */
+    }
+
+    /* if escape ('\'), just compare next character */
+    if (c == '\\' && (c = *p++) == 0)     /* if \ at end, then syntax error */
+        return 0;
+
+    /* just a character--compare it */
+#ifdef QDOS
+    return QMatch(Case((uch)c), Case(*s)) ? recmatch(p, ++s, ic) : 0;
+#else
+    return Case((uch)c) == Case(*s) ? recmatch(p, ++s, ic) : 0;
+#endif
+
+} /* end function recmatch() */
+
+
+
+
+
+int iswild(p)        /* originally only used for stat()-bug workaround in */
+    ZCONST char *p;  /*  VAX C, Turbo/Borland C, Watcom C, Atari MiNT libs; */
+{                    /*  now used in process_zipfiles() as well */
+    for (; *p; ++p)
+        if (*p == '\\' && *(p+1))
+            ++p;
+#ifdef VMS
+        else if (*p == '%' || *p == '*')
+#else /* !VMS */
+#ifdef AMIGA
+        else if (*p == '?' || *p == '*' || (*p=='#' && p[1]=='?') || *p == '[')
+#else /* !AMIGA */
+        else if (*p == '?' || *p == '*' || *p == '[')
+#endif /* ?AMIGA */
+#endif /* ?VMS */
+#ifdef QDOS
+            return (int)p;
+#else
+            return TRUE;
+#endif
+
+    return FALSE;
+
+} /* end function iswild() */
+
+
+
+
+
+#ifdef TEST_MATCH
+
+#define put(s) {fputs(s,stdout); fflush(stdout);}
+
+void main()
+{
+    char pat[256], str[256];
+
+    for (;;) {
+        put("Pattern (return to exit): ");
+        gets(pat);
+        if (!pat[0])
+            break;
+        for (;;) {
+            put("String (return for new pattern): ");
+            gets(str);
+            if (!str[0])
+                break;
+            pipeit("Case sensitive: %s  insensitive: %s\n",
+              match(str, pat, 0) ? "YES" : "NO",
+              match(str, pat, 1) ? "YES" : "NO");
+        }
+    }
+    EXIT(0);
+}
+
+#endif /* TEST_MATCH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/nt.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,659 @@
+/*
+
+  Copyright (c) 1996  Scott Field
+
+  Module Name:
+
+    nt.c
+
+  Abstract:
+
+    This module implements WinNT security descriptor operations for the
+    Win32 Info-ZIP project.  Operation such as setting file security,
+    using/querying local and remote privileges, and queuing of operations
+    is performed here.  The contents of this module are only relevant
+    when the code is running on Windows NT, and the target volume supports
+    persistent Acl storage.
+
+    User privileges that allow accessing certain privileged aspects of the
+    security descriptor (such as the Sacl) are only used if the user specified
+    to do so.
+
+  Author:
+
+    Scott Field (sfield@microsoft.com)
+
+  Last revised:  18 Jan 97
+
+ */
+
+#define WIN32_LEAN_AND_MEAN
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#include <windows.h>
+#ifdef __RSXNT__
+#  include "rsxntwin.h"
+#endif
+#include "nt.h"
+
+
+#ifdef NTSD_EAS         /* This file is only needed for NTSD handling */
+
+/* Borland C++ does not define FILE_SHARE_DELETE. Others also? */
+#ifndef FILE_SHARE_DELETE
+#  define FILE_SHARE_DELETE 0x00000004
+#endif
+
+
+/* private prototypes */
+
+static BOOL Initialize(VOID);
+#if 0   /* currently unused */
+static BOOL Shutdown(VOID);
+#endif
+static BOOL DeferSet(char *resource, PVOLUMECAPS VolumeCaps, uch *buffer);
+static VOID GetRemotePrivilegesSet(CHAR *FileName, PDWORD dwRemotePrivileges);
+static VOID InitLocalPrivileges(VOID);
+
+
+BOOL bInitialized = FALSE;  /* module level stuff initialized? */
+HANDLE hInitMutex = NULL;   /* prevent multiple initialization */
+
+BOOL g_bRestorePrivilege = FALSE;   /* for local set file security override */
+BOOL g_bSaclPrivilege = FALSE;      /* for local set sacl operations, only when
+                                       restore privilege not present */
+
+/* our single cached volume capabilities structure that describes the last
+   volume root we encountered.  A single entry like this works well in the
+   zip/unzip scenario for a number of reasons:
+   1. typically one extraction path during unzip.
+   2. typically process one volume at a time during zip, and then move
+      on to the next.
+   3. no cleanup code required and no memory leaks.
+   4. simple code.
+
+   This approach should be reworked to a linked list approach if we expect to
+   be called by many threads which are processing a variety of input/output
+   volumes, since lock contention and stale data may become a bottleneck. */
+
+VOLUMECAPS g_VolumeCaps;
+CRITICAL_SECTION VolumeCapsLock;
+
+
+/* our deferred set structure linked list element, used for making a copy
+   of input data which is used at a later time to process the original input
+   at a time when it makes more sense. eg, applying security to newly created
+   directories, after all files have been placed in such directories. */
+
+CRITICAL_SECTION SetDeferLock;
+
+typedef struct _DEFERRED_SET {
+    struct _DEFERRED_SET *Next;
+    uch *buffer;                /* must point to DWORD aligned block */
+    PVOLUMECAPS VolumeCaps;
+    char *resource;
+} DEFERRED_SET, *PDEFERRED_SET, *LPDEFERRED_SET;
+
+PDEFERRED_SET pSetHead = NULL;
+PDEFERRED_SET pSetTail;
+
+static BOOL Initialize(VOID)
+{
+    HANDLE hMutex;
+    HANDLE hOldMutex;
+
+    if(bInitialized) return TRUE;
+
+    hMutex = CreateMutex(NULL, TRUE, NULL);
+    if(hMutex == NULL) return FALSE;
+
+    hOldMutex = (HANDLE)InterlockedExchange((LPLONG)&hInitMutex, (LONG)hMutex);
+
+    if(hOldMutex != NULL) {
+        /* somebody setup the mutex already */
+        InterlockedExchange((LPLONG)&hInitMutex, (LONG)hOldMutex);
+
+        CloseHandle(hMutex); /* close new, un-needed mutex */
+
+        /* wait for initialization to complete and return status */
+        WaitForSingleObject(hOldMutex, INFINITE);
+        ReleaseMutex(hOldMutex);
+
+        return bInitialized;
+    }
+
+    /* initialize module level resources */
+
+    InitializeCriticalSection( &SetDeferLock );
+
+    InitializeCriticalSection( &VolumeCapsLock );
+    memset(&g_VolumeCaps, 0, sizeof(VOLUMECAPS));
+
+    InitLocalPrivileges();
+
+    bInitialized = TRUE;
+
+    ReleaseMutex(hMutex); /* release correct mutex */
+
+    return TRUE;
+}
+
+#if 0   /* currently not used ! */
+static BOOL Shutdown(VOID)
+{
+    /* really need to free critical sections, disable enabled privilges, etc,
+       but doing so brings up possibility of race conditions if those resources
+       are about to be used.  The easiest way to handle this is let these
+       resources be freed when the process terminates... */
+
+    return TRUE;
+}
+#endif /* never */
+
+
+static BOOL DeferSet(char *resource, PVOLUMECAPS VolumeCaps, uch *buffer)
+{
+    PDEFERRED_SET psd;
+    DWORD cbDeferSet;
+    DWORD cbResource;
+    DWORD cbBuffer;
+
+    if(!bInitialized) if(!Initialize()) return FALSE;
+
+    cbResource = lstrlenA(resource) + 1;
+    cbBuffer = GetSecurityDescriptorLength((PSECURITY_DESCRIPTOR)buffer);
+    cbDeferSet = sizeof(DEFERRED_SET) + cbBuffer + sizeof(VOLUMECAPS) +
+      cbResource;
+
+    psd = (PDEFERRED_SET)HeapAlloc(GetProcessHeap(), 0, cbDeferSet);
+    if(psd == NULL) return FALSE;
+
+    psd->Next = NULL;
+    psd->buffer = (uch *)(psd+1);
+    psd->VolumeCaps = (PVOLUMECAPS)((char *)psd->buffer + cbBuffer);
+    psd->resource = (char *)((char *)psd->VolumeCaps + sizeof(VOLUMECAPS));
+
+    memcpy(psd->buffer, buffer, cbBuffer);
+    memcpy(psd->VolumeCaps, VolumeCaps, sizeof(VOLUMECAPS));
+    psd->VolumeCaps->bProcessDefer = TRUE;
+    memcpy(psd->resource, resource, cbResource);
+
+    /* take defer lock */
+    EnterCriticalSection( &SetDeferLock );
+
+    /* add element at tail of list */
+
+    if(pSetHead == NULL) {
+        pSetHead = psd;
+    } else {
+        pSetTail->Next = psd;
+    }
+
+    pSetTail = psd;
+
+    /* release defer lock */
+    LeaveCriticalSection( &SetDeferLock );
+
+    return TRUE;
+}
+
+BOOL ProcessDefer(PDWORD dwDirectoryCount, PDWORD dwBytesProcessed,
+                  PDWORD dwDirectoryFail, PDWORD dwBytesFail)
+{
+    PDEFERRED_SET This;
+    PDEFERRED_SET Next;
+
+    *dwDirectoryCount = 0;
+    *dwBytesProcessed = 0;
+
+    *dwDirectoryFail = 0;
+    *dwBytesFail = 0;
+
+    if(!bInitialized) return TRUE; /* nothing to do */
+
+    EnterCriticalSection( &SetDeferLock );
+
+    This = pSetHead;
+
+    while(This) {
+
+        if(SecuritySet(This->resource, This->VolumeCaps, This->buffer)) {
+            (*dwDirectoryCount)++;
+            *dwBytesProcessed +=
+              GetSecurityDescriptorLength((PSECURITY_DESCRIPTOR)This->buffer);
+        } else {
+            (*dwDirectoryFail)++;
+            *dwBytesFail +=
+              GetSecurityDescriptorLength((PSECURITY_DESCRIPTOR)This->buffer);
+        }
+
+        Next = This->Next;
+        HeapFree(GetProcessHeap(), 0, This);
+        This = Next;
+    }
+
+    pSetHead = NULL;
+
+    LeaveCriticalSection( &SetDeferLock );
+
+    return TRUE;
+}
+
+BOOL ValidateSecurity(uch *securitydata)
+{
+    PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)securitydata;
+    PACL pAcl;
+    PSID pSid;
+    BOOL bAclPresent;
+    BOOL bDefaulted;
+
+    if(!IsWinNT()) return TRUE; /* don't do anything if not on WinNT */
+
+    if(!IsValidSecurityDescriptor(sd)) return FALSE;
+
+    /* verify Dacl integrity */
+
+    if(!GetSecurityDescriptorDacl(sd, &bAclPresent, &pAcl, &bDefaulted))
+        return FALSE;
+
+    if(bAclPresent) {
+        if(!IsValidAcl(pAcl)) return FALSE;
+    }
+
+    /* verify Sacl integrity */
+
+    if(!GetSecurityDescriptorSacl(sd, &bAclPresent, &pAcl, &bDefaulted))
+        return FALSE;
+
+    if(bAclPresent) {
+        if(!IsValidAcl(pAcl)) return FALSE;
+    }
+
+    /* verify owner integrity */
+
+    if(!GetSecurityDescriptorOwner(sd, &pSid, &bDefaulted))
+        return FALSE;
+
+    if(pSid != NULL) {
+        if(!IsValidSid(pSid)) return FALSE;
+    }
+
+    /* verify group integrity */
+
+    if(!GetSecurityDescriptorGroup(sd, &pSid, &bDefaulted))
+        return FALSE;
+
+    if(pSid != NULL) {
+        if(!IsValidSid(pSid)) return FALSE;
+    }
+
+    return TRUE;
+}
+
+static VOID GetRemotePrivilegesSet(char *FileName, PDWORD dwRemotePrivileges)
+{
+    HANDLE hFile;
+
+    *dwRemotePrivileges = 0;
+
+    /* see if we have the SeRestorePrivilege */
+
+    hFile = CreateFileA(
+        FileName,
+        ACCESS_SYSTEM_SECURITY | WRITE_DAC | WRITE_OWNER | READ_CONTROL,
+        FILE_SHARE_READ | FILE_SHARE_DELETE, /* no sd updating allowed here */
+        NULL,
+        OPEN_EXISTING,
+        FILE_FLAG_BACKUP_SEMANTICS,
+        NULL
+        );
+
+    if(hFile != INVALID_HANDLE_VALUE) {
+        /* no remote way to determine SeRestorePrivilege -- just try a
+           read/write to simulate it */
+        SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION |
+          SACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION |
+          GROUP_SECURITY_INFORMATION;
+        PSECURITY_DESCRIPTOR sd;
+        DWORD cbBuf = 0;
+
+        GetKernelObjectSecurity(hFile, si, NULL, cbBuf, &cbBuf);
+
+        if(ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
+            if((sd = HeapAlloc(GetProcessHeap(), 0, cbBuf)) != NULL) {
+                if(GetKernelObjectSecurity(hFile, si, sd, cbBuf, &cbBuf)) {
+                    if(SetKernelObjectSecurity(hFile, si, sd))
+                        *dwRemotePrivileges |= OVERRIDE_RESTORE;
+                }
+                HeapFree(GetProcessHeap(), 0, sd);
+            }
+        }
+
+        CloseHandle(hFile);
+    } else {
+
+        /* see if we have the SeSecurityPrivilege */
+        /* note we don't need this if we have SeRestorePrivilege */
+
+        hFile = CreateFileA(
+            FileName,
+            ACCESS_SYSTEM_SECURITY,
+            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, /* max */
+            NULL,
+            OPEN_EXISTING,
+            0,
+            NULL
+            );
+
+        if(hFile != INVALID_HANDLE_VALUE) {
+            CloseHandle(hFile);
+            *dwRemotePrivileges |= OVERRIDE_SACL;
+        }
+    }
+}
+
+
+BOOL GetVolumeCaps(
+    char *rootpath,         /* filepath, or NULL */
+    char *name,             /* filename associated with rootpath */
+    PVOLUMECAPS VolumeCaps  /* result structure describing capabilities */
+    )
+{
+    char TempRootPath[MAX_PATH + 1];
+    DWORD cchTempRootPath = 0;
+    BOOL bSuccess = TRUE;   /* assume success until told otherwise */
+
+    if(!bInitialized) if(!Initialize()) return FALSE;
+
+    /* process the input path to produce a consistent path suitable for
+       compare operations and also suitable for certain picky Win32 API
+       that don't like forward slashes */
+
+    if(rootpath != NULL && rootpath[0] != '\0') {
+        DWORD i;
+
+        cchTempRootPath = lstrlen(rootpath);
+        if(cchTempRootPath > MAX_PATH) return FALSE;
+
+        /* copy input, converting forward slashes to back slashes as we go */
+
+        for(i = 0 ; i <= cchTempRootPath ; i++) {
+            if(rootpath[i] == '/') TempRootPath[i] = '\\';
+            else TempRootPath[i] = rootpath[i];
+        }
+
+        /* check for UNC and Null terminate or append trailing \ as
+           appropriate */
+
+        /* possible valid UNCs we are passed follow:
+           \\machine\foo\bar (path is \\machine\foo\)
+           \\machine\foo     (path is \\machine\foo\)
+           \\machine\foo\
+           \\.\c$\     (FIXFIX: Win32API doesn't like this - GetComputerName())
+           LATERLATER: handling mounted DFS drives in the future will require
+                       slightly different logic which isn't available today.
+                       This is required because directories can point at
+                       different servers which have differing capabilities.
+         */
+
+        if(TempRootPath[0] == '\\' && TempRootPath[1] == '\\') {
+            DWORD slash = 0;
+
+            for(i = 2 ; i < cchTempRootPath ; i++) {
+                if(TempRootPath[i] == '\\') {
+                    slash++;
+
+                    if(slash == 2) {
+                        i++;
+                        TempRootPath[i] = '\0';
+                        cchTempRootPath = i;
+                        break;
+                    }
+                }
+            }
+
+            /* if there was only one slash found, just tack another onto the
+               end */
+
+            if(slash == 1 && TempRootPath[cchTempRootPath] != '\\') {
+                TempRootPath[cchTempRootPath] = TempRootPath[0]; /* '\' */
+                TempRootPath[cchTempRootPath+1] = '\0';
+                cchTempRootPath++;
+            }
+
+        } else {
+
+            if(TempRootPath[1] == ':') {
+
+                /* drive letter specified, truncate to root */
+                TempRootPath[2] = '\\';
+                TempRootPath[3] = '\0';
+                cchTempRootPath = 3;
+            } else {
+
+                /* must be file on current drive */
+                TempRootPath[0] = '\0';
+                cchTempRootPath = 0;
+            }
+
+        }
+
+    } /* if path != NULL */
+
+    /* grab lock protecting cached entry */
+    EnterCriticalSection( &VolumeCapsLock );
+
+    if(!g_VolumeCaps.bValid ||
+       lstrcmpi(g_VolumeCaps.RootPath, TempRootPath) != 0)
+    {
+
+        /* no match found, build up new entry */
+
+        DWORD dwFileSystemFlags;
+        DWORD dwRemotePrivileges = 0;
+        BOOL bRemote = FALSE;
+
+        /* release lock during expensive operations */
+        LeaveCriticalSection( &VolumeCapsLock );
+
+        bSuccess = GetVolumeInformation(
+            (TempRootPath[0] == '\0') ? NULL : TempRootPath,
+            NULL, 0,
+            NULL, NULL,
+            &dwFileSystemFlags,
+            NULL, 0);
+
+
+        /* only if target volume supports Acls, and we were told to use
+           privileges do we need to go out and test for the remote case */
+
+        if(bSuccess && (dwFileSystemFlags & FS_PERSISTENT_ACLS) &&
+           VolumeCaps->bUsePrivileges)
+        {
+            if(GetDriveType( (TempRootPath[0] == '\0') ? NULL : TempRootPath )
+               == DRIVE_REMOTE)
+            {
+                bRemote = TRUE;
+
+                /* make a determination about our remote capabilities */
+
+                GetRemotePrivilegesSet(name, &dwRemotePrivileges);
+            }
+        }
+
+        /* always take the lock again, since we release it below */
+        EnterCriticalSection( &VolumeCapsLock );
+
+        /* replace the existing data if successful */
+        if(bSuccess) {
+
+            lstrcpynA(g_VolumeCaps.RootPath, TempRootPath, cchTempRootPath+1);
+            g_VolumeCaps.bProcessDefer = FALSE;
+            g_VolumeCaps.dwFileSystemFlags = dwFileSystemFlags;
+            g_VolumeCaps.bRemote = bRemote;
+            g_VolumeCaps.dwRemotePrivileges = dwRemotePrivileges;
+            g_VolumeCaps.bValid = TRUE;
+        }
+    }
+
+    if(bSuccess) {
+        /* copy input elements */
+        g_VolumeCaps.bUsePrivileges = VolumeCaps->bUsePrivileges;
+        g_VolumeCaps.dwFileAttributes = VolumeCaps->dwFileAttributes;
+
+        /* give caller results */
+        memcpy(VolumeCaps, &g_VolumeCaps, sizeof(VOLUMECAPS));
+    } else {
+        g_VolumeCaps.bValid = FALSE;
+    }
+
+    LeaveCriticalSection( &VolumeCapsLock ); /* release lock */
+
+    return bSuccess;
+}
+
+
+BOOL SecuritySet(char *resource, PVOLUMECAPS VolumeCaps, uch *securitydata)
+{
+    HANDLE hFile;
+    DWORD dwDesiredAccess = 0;
+    DWORD dwFlags = 0;
+    PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)securitydata;
+    SECURITY_DESCRIPTOR_CONTROL sdc;
+    SECURITY_INFORMATION RequestedInfo = 0;
+    DWORD dwRev;
+    BOOL bRestorePrivilege = FALSE;
+    BOOL bSaclPrivilege = FALSE;
+    BOOL bSuccess;
+
+    if(!bInitialized) if(!Initialize()) return FALSE;
+
+    /* defer directory processing */
+
+    if(VolumeCaps->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+        if(!VolumeCaps->bProcessDefer) {
+            return DeferSet(resource, VolumeCaps, securitydata);
+        } else {
+            /* opening a directory requires FILE_FLAG_BACKUP_SEMANTICS */
+            dwFlags |= FILE_FLAG_BACKUP_SEMANTICS;
+        }
+    }
+
+    /* evaluate the input security desriptor and act accordingly */
+
+    if(!IsValidSecurityDescriptor(sd))
+        return FALSE;
+
+    if(!GetSecurityDescriptorControl(sd, &sdc, &dwRev))
+        return FALSE;
+
+    /* setup privilege usage based on if told we can use privileges, and if so,
+       what privileges we have */
+
+    if(VolumeCaps->bUsePrivileges) {
+        if(VolumeCaps->bRemote) {
+            /* use remotely determined privileges */
+            if(VolumeCaps->dwRemotePrivileges & OVERRIDE_RESTORE)
+                bRestorePrivilege = TRUE;
+
+            if(VolumeCaps->dwRemotePrivileges & OVERRIDE_SACL)
+                bSaclPrivilege = TRUE;
+
+        } else {
+            /* use local privileges */
+            bRestorePrivilege = g_bRestorePrivilege;
+            bSaclPrivilege = g_bSaclPrivilege;
+        }
+    }
+
+
+    /* if a Dacl is present write Dacl out */
+    /* if we have SeRestorePrivilege, write owner and group info out */
+
+    if(sdc & SE_DACL_PRESENT) {
+        dwDesiredAccess |= WRITE_DAC;
+        RequestedInfo |= DACL_SECURITY_INFORMATION;
+
+        if(bRestorePrivilege) {
+            dwDesiredAccess |= WRITE_OWNER;
+            RequestedInfo |= (OWNER_SECURITY_INFORMATION |
+              GROUP_SECURITY_INFORMATION);
+        }
+    }
+
+    /* if a Sacl is present and we have either SeRestorePrivilege or
+       SeSystemSecurityPrivilege try to write Sacl out */
+
+    if((sdc & SE_SACL_PRESENT) && (bRestorePrivilege || bSaclPrivilege)) {
+        dwDesiredAccess |= ACCESS_SYSTEM_SECURITY;
+        RequestedInfo |= SACL_SECURITY_INFORMATION;
+    }
+
+    if(RequestedInfo == 0)  /* nothing to do */
+        return FALSE;
+
+    if(bRestorePrivilege)
+        dwFlags |= FILE_FLAG_BACKUP_SEMANTICS;
+
+    hFile = CreateFileA(
+        resource,
+        dwDesiredAccess,
+        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,/* max sharing */
+        NULL,
+        OPEN_EXISTING,
+        dwFlags,
+        NULL
+        );
+
+    if(hFile == INVALID_HANDLE_VALUE)
+        return FALSE;
+
+    bSuccess = SetKernelObjectSecurity(hFile, RequestedInfo, sd);
+
+    CloseHandle(hFile);
+
+    return bSuccess;
+}
+
+static VOID InitLocalPrivileges(VOID)
+{
+    HANDLE hToken;
+    TOKEN_PRIVILEGES tp;
+
+    /* try to enable some interesting privileges that give us the ability
+       to get some security information that we normally cannot.
+
+       note that enabling privileges is only relevant on the local machine;
+       when accessing files that are on a remote machine, any privileges
+       that are present on the remote machine get enabled by default. */
+
+    if(!OpenProcessToken(GetCurrentProcess(),
+        TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
+        return;
+
+    tp.PrivilegeCount = 1;
+    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+    if(LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tp.Privileges[0].Luid)) {
+
+        /* try to enable SeRestorePrivilege; if this succeeds, we can write
+           all aspects of the security descriptor */
+
+        if(AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) &&
+           GetLastError() == ERROR_SUCCESS) g_bRestorePrivilege = TRUE;
+
+    }
+
+    /* try to enable SeSystemSecurityPrivilege, if SeRestorePrivilege not
+       present; if this succeeds, we can write the Sacl */
+
+    if(!g_bRestorePrivilege &&
+        LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tp.Privileges[0].Luid)) {
+
+        if(AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) &&
+           GetLastError() == ERROR_SUCCESS) g_bSaclPrivilege = TRUE;
+    }
+
+    CloseHandle(hToken);
+}
+#endif /* NTSD_EAS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/os2.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,2187 @@
+/*---------------------------------------------------------------------------
+
+  os2.c
+
+  OS/2-specific routines for use with Info-ZIP's UnZip 5.1 and later.
+
+  This file contains the OS/2 versions of the file name/attribute/time/etc
+  code.  Most or all of the routines which make direct use of OS/2 system
+  calls (i.e., the non-lowercase routines) are Kai Uwe Rommel's.  The read-
+  dir() suite was written by Michael Rendell and ported to OS/2 by Kai Uwe;
+  it is in the public domain.
+
+  Contains:  GetCountryInfo()
+             GetFileTime()
+             SetFileTime()              (TIMESTAMP only)
+             stamp_file()               (TIMESTAMP only)
+             Utime2DosDateTime()
+             SetPathAttrTimes()
+             SetEAs()
+             GetLoadPath()
+             opendir()
+             closedir()
+             readdir()
+             [ seekdir() ]             not used
+             [ telldir() ]             not used
+             free_dircontents()
+             getdirent()
+             IsFileSystemFAT()
+             do_wild()
+             mapattr()
+             mapname()
+             checkdir()
+             isfloppy()
+             IsFileNameValid()
+             map2fat()
+             SetLongNameEA()
+             close_outfile()
+             check_for_newer()
+             dateformat()
+             version()
+             InitNLS()
+             IsUpperNLS()
+             ToLowerNLS()
+             StringLower()
+             DebugMalloc()
+
+  ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#include "os2acl.h"
+
+extern ZCONST char Far TruncEAs[];
+
+/* local prototypes */
+
+#ifdef TIMESTAMP
+  static int SetFileTime(ZCONST char *name, ulg stamp);
+#endif
+#if defined(USE_EF_UT_TIME) || defined(TIMESTAMP)
+  static ulg Utime2DosDateTime  OF((time_t uxtime));
+#endif
+static int   getOS2filetimes    OF((__GPRO__
+                                    ulg *pM_dt, ulg *pA_dt, ulg *pC_dt));
+static void  SetPathAttrTimes   OF((__GPRO__ int flags, int dir));
+static int   SetEAs             OF((__GPRO__ const char *path,
+                                    void *ef_block));
+static int   SetACL             OF((__GPRO__ const char *path,
+                                    void *ef_block));
+static int   EvalExtraFields    OF((__GPRO__ const char *path,
+                                    void *extra_field, unsigned ef_len));
+static int   isfloppy           OF((int nDrive));
+static int   IsFileNameValid    OF((const char *name));
+static void  map2fat            OF((char *pathcomp, char **pEndFAT));
+static int   SetLongNameEA      OF((char *name, char *longname));
+static void  InitNLS            OF((void));
+
+
+/*****************************/
+/*  Strings used in os2.c  */
+/*****************************/
+
+#ifndef SFX
+  static char Far CantAllocateWildcard[] =
+    "warning:  cannot allocate wildcard buffers\n";
+#endif
+static char Far Creating[] = "   creating: %-22s ";
+static char Far ConversionFailed[] = "mapname:  conversion of %s failed\n";
+static char Far Labelling[] = "labelling %c: %-22s\n";
+static char Far ErrSetVolLabel[] = "mapname:  error setting volume label\n";
+static char Far PathTooLong[] = "checkdir error:  path too long: %s\n";
+static char Far CantCreateDir[] = "checkdir error:  cannot create %s\n\
+                 unable to process %s.\n";
+static char Far DirIsntDirectory[] =
+  "checkdir error:  %s exists but is not directory\n\
+                 unable to process %s.\n";
+static char Far PathTooLongTrunc[] =
+  "checkdir warning:  path too long; truncating\n                   %s\n\
+                -> %s\n";
+#if (!defined(SFX) || defined(SFX_EXDIR))
+   static char Far CantCreateExtractDir[] =
+     "checkdir:  cannot create extraction directory: %s\n";
+#endif
+
+#ifndef __EMX__
+#  if (_MSC_VER >= 600) || defined(__IBMC__)
+#    include <direct.h>          /* have special MSC/IBM C mkdir prototype */
+#  else                          /* own prototype because dir.h conflicts? */
+     int mkdir(const char *path);
+#  endif
+#  define MKDIR(path,mode)   mkdir(path)
+#else
+#  define MKDIR(path,mode)   mkdir(path,mode)
+#endif
+
+
+#ifdef __32BIT__
+
+USHORT DosDevIOCtl32(PVOID pData, USHORT cbData, PVOID pParms, USHORT cbParms,
+                     USHORT usFunction, USHORT usCategory, HFILE hDevice)
+{
+  ULONG ulParmLengthInOut = cbParms, ulDataLengthInOut = cbData;
+  return (USHORT) DosDevIOCtl(hDevice, usCategory, usFunction,
+                              pParms, cbParms, &ulParmLengthInOut,
+                              pData, cbData, &ulDataLengthInOut);
+}
+
+#  define DosDevIOCtl DosDevIOCtl32
+#else
+#  define DosDevIOCtl DosDevIOCtl2
+#endif
+
+
+typedef struct
+{
+  ush nID;
+  ush nSize;
+  ulg lSize;
+}
+EFHEADER, *PEFHEADER;
+
+
+#ifdef __32BIT__
+
+#define DosFindFirst(p1, p2, p3, p4, p5, p6) \
+        DosFindFirst(p1, p2, p3, p4, p5, p6, 1)
+
+#else
+
+typedef struct
+{
+  ULONG oNextEntryOffset;
+  BYTE fEA;
+  BYTE cbName;
+  USHORT cbValue;
+  CHAR szName[1];
+}
+FEA2, *PFEA2;
+
+typedef struct
+{
+  ULONG cbList;
+  FEA2 list[1];
+}
+FEA2LIST, *PFEA2LIST;
+
+#define DosQueryCurrentDisk DosQCurDisk
+#define DosQueryFSAttach(p1, p2, p3, p4, p5) \
+        DosQFSAttach(p1, p2, p3, p4, p5, 0)
+#define DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7) \
+        DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7, 0)
+#define DosFindFirst(p1, p2, p3, p4, p5, p6) \
+        DosFindFirst(p1, p2, p3, p4, p5, p6, 0)
+#define DosMapCase DosCaseMap
+#define DosSetPathInfo(p1, p2, p3, p4, p5) \
+        DosSetPathInfo(p1, p2, p3, p4, p5, 0)
+#define DosQueryPathInfo(p1, p2, p3, p4) \
+        DosQPathInfo(p1, p2, p3, p4, 0)
+#define DosQueryFileInfo DosQFileInfo
+#define DosMapCase DosCaseMap
+#define DosQueryCtryInfo DosGetCtryInfo
+
+#endif /* !__32BIT__ */
+
+
+
+
+
+/*
+ * @(#) dir.h 1.4 87/11/06   Public Domain.
+ */
+
+#define A_RONLY    0x01
+#define A_HIDDEN   0x02
+#define A_SYSTEM   0x04
+#define A_LABEL    0x08
+#define A_DIR      0x10
+#define A_ARCHIVE  0x20
+
+
+const int attributes = A_DIR | A_HIDDEN | A_SYSTEM;
+
+
+extern DIR *opendir(__GPRO__ ZCONST char *);
+extern struct direct *readdir(__GPRO__ DIR *);
+extern void seekdir(DIR *, long);
+extern long telldir(DIR *);
+extern void closedir(DIR *);
+#define rewinddir(dirp) seekdir(dirp, 0L)
+
+int IsFileSystemFAT(__GPRO__ ZCONST char *dir);
+char *StringLower(char *szArg);
+
+
+
+
+/*
+ * @(#)dir.c 1.4 87/11/06 Public Domain.
+ */
+
+
+#ifndef S_IFMT
+#  define S_IFMT 0xF000
+#endif
+
+
+#ifndef SFX
+   static char *getdirent(__GPRO__ ZCONST char *);
+   static void free_dircontents(struct _dircontents *);
+#endif /* !SFX */
+
+
+
+
+int GetCountryInfo(void)
+{
+    COUNTRYINFO ctryi;
+    COUNTRYCODE ctryc;
+#ifdef __32BIT__
+    ULONG cbInfo;
+#else
+    USHORT cbInfo;
+#endif
+
+  ctryc.country = ctryc.codepage = 0;
+
+  if ( DosQueryCtryInfo(sizeof(ctryi), &ctryc, &ctryi, &cbInfo) != NO_ERROR )
+    return 0;
+
+  return ctryi.fsDateFmt;
+}
+
+
+long GetFileTime(ZCONST char *name)
+{
+#ifdef __32BIT__
+  FILESTATUS3 fs;
+#else
+  FILESTATUS fs;
+#endif
+  USHORT nDate, nTime;
+
+  if ( DosQueryPathInfo((PSZ) name, 1, (PBYTE) &fs, sizeof(fs)) )
+    return -1;
+
+  nDate = * (USHORT *) &fs.fdateLastWrite;
+  nTime = * (USHORT *) &fs.ftimeLastWrite;
+
+  return ((ULONG) nDate) << 16 | nTime;
+}
+
+
+#ifdef TIMESTAMP
+
+static int SetFileTime(ZCONST char *name, ulg stamp)   /* swiped from Zip */
+{
+  FILESTATUS fs;
+  USHORT fd, ft;
+
+  if (DosQueryPathInfo((PSZ) name, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)))
+    return -1;
+
+  fd = (USHORT) (stamp >> 16);
+  ft = (USHORT) stamp;
+  fs.fdateLastWrite = fs.fdateCreation = * (FDATE *) &fd;
+  fs.ftimeLastWrite = fs.ftimeCreation = * (FTIME *) &ft;
+
+  if (DosSetPathInfo((PSZ) name, FIL_STANDARD, (PBYTE) &fs, sizeof(fs), 0))
+    return -1;
+
+  return 0;
+}
+
+
+int stamp_file(ZCONST char *fname, time_t modtime)
+{
+    return SetFileTime(fname, Utime2DosDateTime(modtime));
+}
+
+#endif /* TIMESTAMP */
+
+
+/* The following DOS date/time structures are machine-dependent as they
+ * assume "little-endian" byte order.  For OS/2-specific code, which
+ * is run on x86 CPUs (or emulators?), this assumption is valid; but
+ * care should be taken when using this code as template for other ports.
+ */
+typedef union {
+  ULONG timevalue;          /* combined value, useful for comparisons */
+  struct {
+    FTIME ft;               /* system file time record:
+                             *    USHORT twosecs : 5
+                             *    USHORT minutes : 6;
+                             *    USHORT hours   : 5;   */
+    FDATE fd;               /* system file date record:
+                             *    USHORT day     : 5
+                             *    USHORT month   : 4;
+                             *    USHORT year    : 7;   */
+  } _fdt;
+} F_DATE_TIME, *PF_DATE_TIME;
+
+
+#if defined(USE_EF_UT_TIME) || defined(TIMESTAMP)
+
+static ulg Utime2DosDateTime(uxtime)
+    time_t uxtime;
+{
+    F_DATE_TIME dosfiletime;
+    struct tm *t;
+
+    /* round up to even seconds */
+    /* round up (down if "up" overflows) to even seconds */
+    if (((ulg)uxtime) & 1)
+        uxtime = (uxtime + 1 > uxtime) ? uxtime + 1 : uxtime - 1;
+
+    t = localtime(&(uxtime));
+    if (t == (struct tm *)NULL) {
+        /* time conversion error; use current time instead, hoping
+           that localtime() does not reject it as well! */
+        time_t now = time(NULL);
+        t = localtime(&now);
+    }
+    if (t->tm_year < 80) {
+        dosfiletime._fdt.ft.twosecs = 0;
+        dosfiletime._fdt.ft.minutes = 0;
+        dosfiletime._fdt.ft.hours   = 0;
+        dosfiletime._fdt.fd.day     = 1;
+        dosfiletime._fdt.fd.month   = 1;
+        dosfiletime._fdt.fd.year    = 0;
+    } else {
+        dosfiletime._fdt.ft.twosecs = t->tm_sec >> 1;
+        dosfiletime._fdt.ft.minutes = t->tm_min;
+        dosfiletime._fdt.ft.hours   = t->tm_hour;
+        dosfiletime._fdt.fd.day     = t->tm_mday;
+        dosfiletime._fdt.fd.month   = t->tm_mon + 1;
+        dosfiletime._fdt.fd.year    = t->tm_year - 80;
+    }
+    return dosfiletime.timevalue;
+
+} /* end function Utime2DosDateTime() */
+
+#endif /* USE_EF_UT_TIME || TIMESTAMP */
+
+
+static int getOS2filetimes(__GPRO__ ulg *pM_dt, ulg *pA_dt, ulg *pC_dt)
+{
+#ifdef USE_EF_UT_TIME
+    unsigned eb_izux_flg;
+    iztimes z_utime;
+#endif
+
+    /* Copy and/or convert time and date variables, if necessary;   */
+    /* return a flag indicating which time stamps are available.    */
+#ifdef USE_EF_UT_TIME
+    if (G.extra_field &&
+#ifdef IZ_CHECK_TZ
+        G.tz_is_valid &&
+#endif
+        ((eb_izux_flg = ef_scan_for_izux(G.extra_field,
+          G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime,
+          &z_utime, NULL)) & EB_UT_FL_MTIME))
+    {
+        TTrace((stderr, "getOS2filetimes: UT e.f. modif. time = %lu\n",
+                z_utime.mtime));
+        *pM_dt = Utime2DosDateTime(z_utime.mtime);
+        if (eb_izux_flg & EB_UT_FL_ATIME) {
+            TTrace((stderr, "getOS2filetimes: UT e.f. access time = %lu\n",
+                    z_utime.atime));
+            *pA_dt = Utime2DosDateTime(z_utime.atime);
+        }
+        if (eb_izux_flg & EB_UT_FL_CTIME) {
+            TTrace((stderr, "getOS2filetimes: UT e.f. creation time = %lu\n",
+                    z_utime.ctime));
+            *pC_dt = Utime2DosDateTime(z_utime.ctime);
+        } else {
+            /* no creation time value supplied, set it to modification time */
+            *pC_dt = *pM_dt;
+            eb_izux_flg |= EB_UT_FL_CTIME;
+        }
+        return (int)eb_izux_flg;
+    }
+#endif /* USE_EF_UT_TIME */
+    *pC_dt = *pM_dt = G.lrec.last_mod_dos_datetime;
+    TTrace((stderr, "\ngetOS2filetimes: DOS dir modific./creation time = %lu\n",
+            *pM_dt));
+    return (EB_UT_FL_MTIME | EB_UT_FL_CTIME);
+}
+
+
+static void SetPathAttrTimes(__GPRO__ int flags, int dir)
+{
+  HFILE hFile;
+#ifdef __32BIT__
+  ULONG nAction;
+#else
+  USHORT nAction;
+#endif
+  FILESTATUS fs;
+  USHORT nLength;
+  char szName[CCHMAXPATH];
+  ulg Mod_dt, Acc_dt, Cre_dt;
+  int gotTimes;
+
+  strcpy(szName, G.filename);
+  nLength = strlen(szName);
+  if (szName[nLength - 1] == '/')
+    szName[nLength - 1] = 0;
+
+  if (dir)
+  {
+    if ( DosQueryPathInfo(szName, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)) )
+      return;
+  }
+  else
+  {
+    /* for regular files, open them and operate on the file handle, to
+       work around certain network operating system bugs ... */
+
+    if ( DosOpen(szName, &hFile, &nAction, 0, 0,
+                 OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW,
+                 OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE, 0) )
+      return;
+
+    if ( DosQueryFileInfo(hFile, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)) )
+      return;
+  }
+
+  /* set date/time stamps */
+  gotTimes = getOS2filetimes(__G__ &Mod_dt, &Acc_dt, &Cre_dt);
+  if (gotTimes & EB_UT_FL_MTIME) {
+    fs.fdateLastWrite = ((F_DATE_TIME *)&Mod_dt)->_fdt.fd;
+    fs.ftimeLastWrite = ((F_DATE_TIME *)&Mod_dt)->_fdt.ft;
+  }
+  if (gotTimes & EB_UT_FL_ATIME) {
+    fs.fdateLastAccess = ((F_DATE_TIME *)&Acc_dt)->_fdt.fd;
+    fs.ftimeLastAccess = ((F_DATE_TIME *)&Acc_dt)->_fdt.ft;
+  }
+  if (gotTimes & EB_UT_FL_CTIME) {
+    fs.fdateCreation = ((F_DATE_TIME *)&Cre_dt)->_fdt.fd;
+    fs.ftimeCreation = ((F_DATE_TIME *)&Cre_dt)->_fdt.ft;
+  }
+
+  if ( flags != -1 )
+    fs.attrFile = flags; /* hidden, system, archive, read-only */
+
+  if (dir)
+  {
+    DosSetPathInfo(szName, FIL_STANDARD, (PBYTE) &fs, sizeof(fs), 0);
+  }
+  else
+  {
+    DosSetFileInfo(hFile, FIL_STANDARD, (PBYTE) &fs, sizeof(fs));
+    DosClose(hFile);
+  }
+}
+
+
+typedef struct
+{
+  ULONG cbList;               /* length of value + 22 */
+#ifdef __32BIT__
+  ULONG oNext;
+#endif
+  BYTE fEA;                   /* 0 */
+  BYTE cbName;                /* length of ".LONGNAME" = 9 */
+  USHORT cbValue;             /* length of value + 4 */
+  BYTE szName[10];            /* ".LONGNAME" */
+  USHORT eaType;              /* 0xFFFD for length-preceded ASCII */
+  USHORT eaSize;              /* length of value */
+  BYTE szValue[CCHMAXPATH];
+}
+FEALST;
+
+
+static int SetEAs(__GPRO__ const char *path, void *ef_block)
+{                                               /* returns almost-PK errors */
+  EFHEADER *pEAblock = (PEFHEADER) ef_block;
+#ifdef __32BIT__
+  EAOP2 eaop;
+  PFEA2LIST pFEA2list;
+#else
+  EAOP eaop;
+  PFEALIST pFEAlist;
+  PFEA pFEA;
+  PFEA2LIST pFEA2list;
+  PFEA2 pFEA2;
+  ULONG nLength2;
+#endif
+  USHORT nLength;
+  char szName[CCHMAXPATH];
+  int error;
+
+  if ( ef_block == NULL || pEAblock -> nID != EF_OS2 )
+    return PK_OK;  /* not an OS/2 extra field:  assume OK */
+
+  if ( pEAblock->nSize < 4 || (pEAblock->lSize > 0L && pEAblock->nSize <= 10) )
+    return IZ_EF_TRUNC;  /* no compressed data! */
+
+  strcpy(szName, path);
+  nLength = strlen(szName);
+  if (szName[nLength - 1] == '/')
+    szName[nLength - 1] = 0;
+
+  if ( (pFEA2list = (PFEA2LIST) malloc((size_t) pEAblock -> lSize)) == NULL )
+    return PK_MEM4;
+
+  if ( (error = memextract(__G__ (uch *)pFEA2list, pEAblock->lSize,
+       (uch *)(pEAblock+1), (ulg)(pEAblock->nSize - 4))) != PK_OK )
+  {
+    free(pFEA2list);
+    return error;
+  }
+
+#ifdef __32BIT__
+  eaop.fpGEA2List = NULL;
+  eaop.fpFEA2List = pFEA2list;
+#else
+  pFEAlist  = (PVOID) pFEA2list;
+  pFEA2 = pFEA2list -> list;
+  pFEA  = pFEAlist  -> list;
+
+  do
+  {
+    nLength2 = pFEA2 -> oNextEntryOffset;
+    nLength = sizeof(FEA) + pFEA2 -> cbName + 1 + pFEA2 -> cbValue;
+
+    memcpy(pFEA, (PCH) pFEA2 + sizeof(pFEA2 -> oNextEntryOffset), nLength);
+
+    pFEA2 = (PFEA2) ((PCH) pFEA2 + nLength2);
+    pFEA = (PFEA) ((PCH) pFEA + nLength);
+  }
+  while ( nLength2 != 0 );
+
+  pFEAlist -> cbList = (PCH) pFEA - (PCH) pFEAlist;
+
+  eaop.fpGEAList = NULL;
+  eaop.fpFEAList = pFEAlist;
+#endif
+
+  eaop.oError = 0;
+  DosSetPathInfo(szName, FIL_QUERYEASIZE, (PBYTE) &eaop, sizeof(eaop), 0);
+
+  if (!uO.tflag && QCOND2)
+    Info(slide, 0, ((char *)slide, " (%ld bytes EAs)", pFEA2list -> cbList));
+
+  free(pFEA2list);
+  return PK_COOL;
+}
+
+
+static int SetACL(__GPRO__ const char *path, void *ef_block)
+{                                               /* returns almost-PK errors */
+  EFHEADER *pACLblock = (PEFHEADER) ef_block;
+  char *szACL;
+  int error;
+
+  if ( ef_block == NULL || pACLblock -> nID != EF_ACL )
+    return PK_OK;  /* not an OS/2 extra field:  assume OK */
+
+  if (pACLblock->nSize < 4 || (pACLblock->lSize > 0L && pACLblock->nSize <= 10))
+    return IZ_EF_TRUNC;  /* no compressed data! */
+
+  if ( (szACL = malloc((size_t) pACLblock -> lSize)) == NULL )
+    return PK_MEM4;
+
+  if ( (error = memextract(__G__ (uch *)szACL, pACLblock->lSize,
+       (uch *)(pACLblock+1), (ulg)(pACLblock->nSize - 4))) != PK_OK )
+  {
+    free(szACL);
+    return error;
+  }
+
+  if (acl_set(NULL, path, szACL) == 0)
+    if (!uO.tflag && QCOND2)
+      Info(slide, 0, ((char *)slide, " (%ld bytes ACL)", strlen(szACL)));
+
+  free(szACL);
+  return PK_COOL;
+}
+
+
+#ifdef SFX
+
+char *GetLoadPath(__GPRO)
+{
+#ifdef __32BIT__ /* generic for 32-bit API */
+  PTIB pptib;
+  PPIB pppib;
+  char *szPath;
+
+  DosGetInfoBlocks(&pptib, &pppib);
+  szPath = pppib -> pib_pchenv;
+#else /* 16-bit, note: requires large data model */
+  SEL selEnv;
+  USHORT offCmd;
+  char *szPath;
+
+  DosGetEnv(&selEnv, &offCmd);
+  szPath = MAKEP(selEnv, 0);
+#endif
+
+  while (*szPath) /* find end of process environment */
+    szPath = strchr(szPath, 0) + 1;
+
+  return szPath + 1; /* .exe file name follows environment */
+
+} /* end function GetLoadPath() */
+
+
+
+
+
+#else /* !SFX */
+
+DIR *opendir(__GPRO__ const char *name)
+{
+  struct stat statb;
+  DIR *dirp;
+  char c;
+  char *s;
+  struct _dircontents *dp;
+  char nbuf[MAXPATHLEN + 1];
+  int len;
+
+  strcpy(nbuf, name);
+  if ((len = strlen(nbuf)) == 0)
+    return NULL;
+
+  if ( ((c = nbuf[len - 1]) == '\\' || c == '/') && (len > 1) )
+  {
+    nbuf[len - 1] = 0;
+    --len;
+
+    if ( nbuf[len - 1] == ':' )
+    {
+      strcpy(nbuf+len, "\\.");
+      len += 2;
+    }
+  }
+  else
+    if ( nbuf[len - 1] == ':' )
+    {
+      strcpy(nbuf+len, ".");
+      ++len;
+    }
+
+  /* GRR:  Borland and Watcom C return non-zero on wildcards... < 0 ? */
+  if (stat(nbuf, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
+  {
+    Trace((stderr, "opendir:  stat(%s) returns negative or not directory\n",
+      nbuf));
+    return NULL;
+  }
+
+  if ( (dirp = malloc(sizeof(DIR))) == NULL )
+    return NULL;
+
+  if ( nbuf[len - 1] == '.' && (len == 1 || nbuf[len - 2] != '.') )
+    strcpy(nbuf+len-1, "*");
+  else
+    if ( ((c = nbuf[len - 1]) == '\\' || c == '/') && (len == 1) )
+      strcpy(nbuf+len, "*");
+    else
+      strcpy(nbuf+len, "\\*");
+
+  /* len is no longer correct (but no longer needed) */
+  Trace((stderr, "opendir:  nbuf = [%s]\n", nbuf));
+
+  dirp -> dd_loc = 0;
+  dirp -> dd_contents = dirp -> dd_cp = NULL;
+
+  if ((s = getdirent(__G__ nbuf)) == NULL)
+    return dirp;
+
+  do
+  {
+    if (((dp = malloc(sizeof(struct _dircontents))) == NULL) ||
+        ((dp -> _d_entry = malloc(strlen(s) + 1)) == NULL)      )
+    {
+      if (dp)
+        free(dp);
+      free_dircontents(dirp -> dd_contents);
+
+      return NULL;
+    }
+
+    if (dirp -> dd_contents)
+    {
+      dirp -> dd_cp -> _d_next = dp;
+      dirp -> dd_cp = dirp -> dd_cp -> _d_next;
+    }
+    else
+      dirp -> dd_contents = dirp -> dd_cp = dp;
+
+    strcpy(dp -> _d_entry, s);
+    dp -> _d_next = NULL;
+
+    dp -> _d_size = G.os2.find.cbFile;
+    dp -> _d_mode = G.os2.find.attrFile;
+    dp -> _d_time = *(unsigned *) &(G.os2.find.ftimeLastWrite);
+    dp -> _d_date = *(unsigned *) &(G.os2.find.fdateLastWrite);
+  }
+  while ((s = getdirent(__G__ NULL)) != NULL);
+
+  dirp -> dd_cp = dirp -> dd_contents;
+
+  return dirp;
+}
+
+
+void closedir(DIR * dirp)
+{
+  free_dircontents(dirp -> dd_contents);
+  free(dirp);
+}
+
+
+struct direct *readdir(__GPRO__ DIR * dirp)
+{
+  /* moved to os2data.h so it can be global */
+  /* static struct direct dp; */
+
+  if (dirp -> dd_cp == NULL)
+    return NULL;
+
+  G.os2.dp.d_namlen = G.os2.dp.d_reclen =
+    strlen(strcpy(G.os2.dp.d_name, dirp -> dd_cp -> _d_entry));
+
+  G.os2.dp.d_ino = 0;
+
+  G.os2.dp.d_size = dirp -> dd_cp -> _d_size;
+  G.os2.dp.d_mode = dirp -> dd_cp -> _d_mode;
+  G.os2.dp.d_time = dirp -> dd_cp -> _d_time;
+  G.os2.dp.d_date = dirp -> dd_cp -> _d_date;
+
+  dirp -> dd_cp = dirp -> dd_cp -> _d_next;
+  dirp -> dd_loc++;
+
+  return &G.os2.dp;
+}
+
+
+
+#if 0  /* not used in unzip; retained for possibly future use */
+
+void seekdir(DIR * dirp, long off)
+{
+  long i = off;
+  struct _dircontents *dp;
+
+  if (off >= 0)
+  {
+    for (dp = dirp -> dd_contents; --i >= 0 && dp; dp = dp -> _d_next);
+
+    dirp -> dd_loc = off - (i + 1);
+    dirp -> dd_cp = dp;
+  }
+}
+
+
+long telldir(DIR * dirp)
+{
+  return dirp -> dd_loc;
+}
+
+#endif /* 0 */
+
+
+
+static void free_dircontents(struct _dircontents * dp)
+{
+  struct _dircontents *odp;
+
+  while (dp)
+  {
+    if (dp -> _d_entry)
+      free(dp -> _d_entry);
+
+    dp = (odp = dp) -> _d_next;
+    free(odp);
+  }
+}
+
+
+static char *getdirent(__GPRO__ ZCONST char *dir)
+{
+  int done;
+  /* moved to os2data.h so it can be global */
+  /* static int lower; */
+
+  if (dir != NULL)
+  {                                    /* get first entry */
+    G.os2.hdir = HDIR_SYSTEM;
+    G.os2.count = 1;
+    done = DosFindFirst((PSZ) dir, &G.os2.hdir, attributes,
+                        &G.os2.find, sizeof(G.os2.find), &G.os2.count);
+    G.os2.lower = IsFileSystemFAT(__G__ dir);
+  }
+  else                                 /* get next entry */
+    done = DosFindNext(G.os2.hdir,
+                       &G.os2.find, sizeof(G.os2.find), &G.os2.count);
+
+  if (done == 0)
+  {
+    if ( G.os2.lower )
+      StringLower(G.os2.find.achName);
+    return G.os2.find.achName;
+  }
+  else
+  {
+    DosFindClose(G.os2.hdir);
+    return NULL;
+  }
+}
+
+
+
+int IsFileSystemFAT(__GPRO__ ZCONST char *dir)  /* FAT / HPFS detection */
+{
+  /* moved to os2data.h so they can be global */
+  /* static USHORT nLastDrive=(USHORT)(-1), nResult; */
+  ULONG lMap;
+  BYTE bData[64];
+  char bName[3];
+#ifdef __32BIT__
+  ULONG nDrive, cbData;
+  PFSQBUFFER2 pData = (PFSQBUFFER2) bData;
+#else
+  USHORT nDrive, cbData;
+  PFSQBUFFER pData = (PFSQBUFFER) bData;
+#endif
+
+    /* We separate FAT and HPFS+other file systems here.
+       at the moment I consider other systems to be similar to HPFS,
+       i.e. support long file names and case sensitive */
+
+    if ( isalpha(dir[0]) && (dir[1] == ':') )
+      nDrive = toupper(dir[0]) - '@';
+    else
+      DosQueryCurrentDisk(&nDrive, &lMap);
+
+    if ( nDrive == G.os2.nLastDrive )
+      return G.os2.nResult;
+
+    bName[0] = (char) (nDrive + '@');
+    bName[1] = ':';
+    bName[2] = 0;
+
+    G.os2.nLastDrive = nDrive;
+    cbData = sizeof(bData);
+
+    if ( !DosQueryFSAttach(bName, 0, FSAIL_QUERYNAME, (PVOID) pData, &cbData) )
+      G.os2.nResult = !strcmp((char *) (pData -> szFSDName) + pData -> cbName,
+                              "FAT");
+    else
+      G.os2.nResult = FALSE;
+
+    /* End of this ugly code */
+    return G.os2.nResult;
+} /* end function IsFileSystemFAT() */
+
+
+
+
+
+/************************/
+/*  Function do_wild()  */
+/************************/
+
+char *do_wild(__G__ wildspec)
+    __GDEF
+    char *wildspec;         /* only used first time on a given dir */
+{
+  /* moved to os2data.h so they can be global */
+#if 0
+  static DIR *dir = NULL;
+  static char *dirname, *wildname, matchname[FILNAMSIZ];
+  static int firstcall=TRUE, have_dirname, dirnamelen;
+#endif
+    char *fnamestart;
+    struct direct *file;
+
+
+    /* Even when we're just returning wildspec, we *always* do so in
+     * matchname[]--calling routine is allowed to append four characters
+     * to the returned string, and wildspec may be a pointer to argv[].
+     */
+    if (G.os2.firstcall) {        /* first call:  must initialize everything */
+        G.os2.firstcall = FALSE;
+
+        if (!iswild(wildspec)) {
+            strcpy(G.os2.matchname, wildspec);
+            G.os2.have_dirname = FALSE;
+            G.os2.dir = NULL;
+            return G.os2.matchname;
+        }
+
+        /* break the wildspec into a directory part and a wildcard filename */
+        if ((G.os2.wildname = strrchr(wildspec, '/')) == NULL &&
+            (G.os2.wildname = strrchr(wildspec, ':')) == NULL) {
+            G.os2.dirname = ".";
+            G.os2.dirnamelen = 1;
+            G.os2.have_dirname = FALSE;
+            G.os2.wildname = wildspec;
+        } else {
+            ++G.os2.wildname;     /* point at character after '/' or ':' */
+            G.os2.dirnamelen = G.os2.wildname - wildspec;
+            if ((G.os2.dirname = (char *)malloc(G.os2.dirnamelen+1)) == NULL) {
+                Info(slide, 1, ((char *)slide,
+                  LoadFarString(CantAllocateWildcard)));
+                strcpy(G.os2.matchname, wildspec);
+                return G.os2.matchname;   /* but maybe filespec was not a wildcard */
+            }
+            strncpy(G.os2.dirname, wildspec, G.os2.dirnamelen);
+            G.os2.dirname[G.os2.dirnamelen] = '\0';   /* terminate for strcpy below */
+            G.os2.have_dirname = TRUE;
+        }
+        Trace((stderr, "do_wild:  dirname = [%s]\n", G.os2.dirname));
+
+        if ((G.os2.dir = opendir(__G__ G.os2.dirname)) != NULL) {
+            if (G.os2.have_dirname) {
+                strcpy(G.os2.matchname, G.os2.dirname);
+                fnamestart = G.os2.matchname + G.os2.dirnamelen;
+            } else
+                fnamestart = G.os2.matchname;
+            while ((file = readdir(__G__ G.os2.dir)) != NULL) {
+                Trace((stderr, "do_wild:  readdir returns %s\n", file->d_name));
+                strcpy(fnamestart, file->d_name);
+                if (strrchr(fnamestart, '.') == (char *)NULL)
+                    strcat(fnamestart, ".");
+                if (match(fnamestart, G.os2.wildname, 1) &&  /* 1 == ignore case */
+                    /* skip "." and ".." directory entries */
+                    strcmp(fnamestart, ".") && strcmp(fnamestart, "..")) {
+                    Trace((stderr, "do_wild:  match() succeeds\n"));
+                    /* remove trailing dot */
+                    fnamestart += strlen(fnamestart) - 1;
+                    if (*fnamestart == '.')
+                        *fnamestart = '\0';
+                    return G.os2.matchname;
+                }
+            }
+            /* if we get to here directory is exhausted, so close it */
+            closedir(G.os2.dir);
+            G.os2.dir = NULL;
+        }
+#ifdef DEBUG
+        else {
+            Trace((stderr, "do_wild:  opendir(%s) returns NULL\n", G.os2.dirname));
+        }
+#endif /* DEBUG */
+
+        /* return the raw wildspec in case that works (e.g., directory not
+         * searchable, but filespec was not wild and file is readable) */
+        strcpy(G.os2.matchname, wildspec);
+        return G.os2.matchname;
+    }
+
+    /* last time through, might have failed opendir but returned raw wildspec */
+    if (G.os2.dir == NULL) {
+        G.os2.firstcall = TRUE;  /* nothing left to try--reset for new wildspec */
+        if (G.os2.have_dirname)
+            free(G.os2.dirname);
+        return (char *)NULL;
+    }
+
+    /* If we've gotten this far, we've read and matched at least one entry
+     * successfully (in a previous call), so dirname has been copied into
+     * matchname already.
+     */
+    if (G.os2.have_dirname) {
+        /* strcpy(G.os2.matchname, G.os2.dirname); */
+        fnamestart = G.os2.matchname + G.os2.dirnamelen;
+    } else
+        fnamestart = G.os2.matchname;
+    while ((file = readdir(__G__ G.os2.dir)) != NULL) {
+        Trace((stderr, "do_wild:  readdir returns %s\n", file->d_name));
+        strcpy(fnamestart, file->d_name);
+        if (strrchr(fnamestart, '.') == (char *)NULL)
+            strcat(fnamestart, ".");
+        if (match(fnamestart, G.os2.wildname, 1)) {     /* 1 == ignore case */
+            Trace((stderr, "do_wild:  match() succeeds\n"));
+            /* remove trailing dot */
+            fnamestart += strlen(fnamestart) - 1;
+            if (*fnamestart == '.')
+                *fnamestart = '\0';
+            return G.os2.matchname;
+        }
+    }
+
+    closedir(G.os2.dir);     /* have read at least one dir entry; nothing left */
+    G.os2.dir = NULL;
+    G.os2.firstcall = TRUE;  /* reset for new wildspec */
+    if (G.os2.have_dirname)
+        free(G.os2.dirname);
+    return (char *)NULL;
+
+} /* end function do_wild() */
+
+#endif /* !SFX */
+
+
+/* scan extra fields for something we happen to know */
+
+static int EvalExtraFields(__GPRO__ const char *path,
+                           void *extra_field, unsigned ef_len)
+{
+  char *ef_ptr = extra_field;
+  PEFHEADER pEFblock;
+  int rc = PK_OK;
+
+  while (ef_len >= sizeof(EFHEADER))
+  {
+    pEFblock = (PEFHEADER) ef_ptr;
+
+    if (pEFblock -> nSize > (ef_len - EB_HEADSIZE))
+      return PK_ERR;            /* claimed EFblock length exceeds EF size! */
+
+    switch (pEFblock -> nID)
+    {
+    case EF_OS2:
+      rc = SetEAs(__G__ path, ef_ptr);
+      break;
+    case EF_ACL:
+      rc = (uO.X_flag) ? SetACL(__G__ path, ef_ptr) : PK_OK;
+      break;
+#if 0
+    case EF_IZUNIX:
+    case EF_PKUNIX:
+      /* handled elsewhere */
+      break;
+#endif
+    default:
+      TTrace((stderr,"EvalExtraFields: unknown extra field block, ID=%d\n",
+              pEFblock -> nID));
+      break;
+    }
+
+    ef_ptr += (pEFblock -> nSize + EB_HEADSIZE);
+    ef_len -= (pEFblock -> nSize + EB_HEADSIZE);
+
+    if (rc != PK_OK)
+      break;
+  }
+
+  return rc;
+}
+
+
+
+/************************/
+/*  Function mapattr()  */
+/************************/
+
+int mapattr(__G)
+    __GDEF
+{
+    /* set archive bit (file is not backed up): */
+    G.pInfo->file_attr = (unsigned)(G.crec.external_file_attributes | 32) & 0xff;
+    return 0;
+}
+
+
+
+
+
+/************************/
+/*  Function mapname()  */
+/************************/
+
+/*
+ * There are presently two possibilities in OS/2:  the output filesystem is
+ * FAT, or it is HPFS.  If the former, we need to map to FAT, obviously, but
+ * we *also* must map to HPFS and store that version of the name in extended
+ * attributes.  Either way, we need to map to HPFS, so the main mapname
+ * routine does that.  In the case that the output file system is FAT, an
+ * extra filename-mapping routine is called in checkdir().  While it should
+ * be possible to determine the filesystem immediately upon entry to mapname(),
+ * it is conceivable that the DOS APPEND utility could be added to OS/2 some-
+ * day, allowing a FAT directory to be APPENDed to an HPFS drive/path.  There-
+ * fore we simply check the filesystem at each path component.
+ *
+ * Note that when alternative IFSes become available/popular, everything will
+ * become immensely more complicated.  For example, a Minix filesystem would
+ * have limited filename lengths like FAT but no extended attributes in which
+ * to store the longer versions of the names.  A BSD Unix filesystem would
+ * support paths of length 1024 bytes or more, but it is not clear that FAT
+ * EAs would allow such long .LONGNAME fields or that OS/2 would properly
+ * restore such fields when moving files from FAT to the new filesystem.
+ *
+ * GRR:  some or all of the following chars should be checked in either
+ *       mapname (HPFS) or map2fat (FAT), depending:  ,=^+'"[]<>|\t&
+ */
+                             /* return 0 if no error, 1 if caution (filename */
+int mapname(__G__ renamed)   /*  truncated), 2 if warning (skip file because */
+    __GDEF                   /*  dir doesn't exist), 3 if error (skip file), */
+    int renamed;             /*  or 10 if out of memory (skip file) */
+{                            /*  [also IZ_VOL_LABEL, IZ_CREATED_DIR] */
+    char pathcomp[FILNAMSIZ];      /* path-component buffer */
+    char *pp, *cp=(char *)NULL;    /* character pointers */
+    char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */
+    int quote = FALSE;             /* flag:  next char is literal */
+    int error = 0;
+    register unsigned workch;      /* hold the character being tested */
+
+
+/*---------------------------------------------------------------------------
+    Initialize various pointers and counters and stuff.
+  ---------------------------------------------------------------------------*/
+
+    /* can create path as long as not just freshening, or if user told us */
+    G.create_dirs = (!uO.fflag || renamed);
+
+    G.os2.created_dir = FALSE;  /* not yet */
+    G.os2.renamed_fullpath = FALSE;
+    G.os2.fnlen = strlen(G.filename);
+
+/* GRR:  for VMS, convert to internal format now or later? or never? */
+    if (renamed) {
+        cp = G.filename - 1;    /* point to beginning of renamed name... */
+        while (*++cp)
+            if (*cp == '\\')    /* convert backslashes to forward */
+                *cp = '/';
+        cp = G.filename;
+        /* use temporary rootpath if user gave full pathname */
+        if (G.filename[0] == '/') {
+            G.os2.renamed_fullpath = TRUE;
+            pathcomp[0] = '/';  /* copy the '/' and terminate */
+            pathcomp[1] = '\0';
+            ++cp;
+        } else if (isalpha(G.filename[0]) && G.filename[1] == ':') {
+            G.os2.renamed_fullpath = TRUE;
+            pp = pathcomp;
+            *pp++ = *cp++;      /* copy the "d:" (+ '/', possibly) */
+            *pp++ = *cp++;
+            if (*cp == '/')
+                *pp++ = *cp++;  /* otherwise add "./"? */
+            *pp = '\0';
+        }
+    }
+
+    /* pathcomp is ignored unless renamed_fullpath is TRUE: */
+    if ((error = checkdir(__G__ pathcomp, INIT)) != 0)    /* init path buffer */
+        return error;           /* ...unless no mem or vol label on hard disk */
+
+    *pathcomp = '\0';           /* initialize translation buffer */
+    pp = pathcomp;              /* point to translation buffer */
+    if (!renamed) {             /* cp already set if renamed */
+        if (uO.jflag)           /* junking directories */
+/* GRR:  watch out for VMS version... */
+            cp = (char *)strrchr(G.filename, '/');
+        if (cp == (char *)NULL) /* no '/' or not junking dirs */
+            cp = G.filename;    /* point to internal zipfile-member pathname */
+        else
+            ++cp;               /* point to start of last component of path */
+    }
+
+/*---------------------------------------------------------------------------
+    Begin main loop through characters in filename.
+  ---------------------------------------------------------------------------*/
+
+    while ((workch = (uch)*cp++) != 0) {
+
+        if (quote) {              /* if character quoted, */
+            *pp++ = (char)workch; /*  include it literally */
+            quote = FALSE;
+        } else
+            switch (workch) {
+            case '/':             /* can assume -j flag not given */
+                *pp = '\0';
+                if ((error = checkdir(__G__ pathcomp, APPEND_DIR)) > 1)
+                    return error;
+                pp = pathcomp;    /* reset conversion buffer for next piece */
+                lastsemi = (char *)NULL; /* leave directory semi-colons alone */
+                break;
+
+            case ':':
+                *pp++ = '_';      /* drive names not stored in zipfile, */
+                break;            /*  so no colons allowed */
+
+            case ';':             /* start of VMS version? */
+                lastsemi = pp;    /* remove VMS version later... */
+                *pp++ = ';';      /*  but keep semicolon for now */
+                break;
+
+            case '\026':          /* control-V quote for special chars */
+                quote = TRUE;     /* set flag for next character */
+                break;
+
+            case ' ':             /* keep spaces unless specifically */
+                if (uO.sflag)     /*  requested to change to underscore */
+                    *pp++ = '_';
+                else
+                    *pp++ = ' ';
+                break;
+
+            default:
+                /* allow ASCII 255 and European characters in filenames: */
+                if (isprint(workch) || workch >= 127)
+                    *pp++ = (char)workch;
+            } /* end switch */
+
+    } /* end while loop */
+
+    *pp = '\0';                   /* done with pathcomp:  terminate it */
+
+    /* if not saving them, remove VMS version numbers (appended "###") */
+    if (!uO.V_flag && lastsemi) {
+        pp = lastsemi + 1;        /* semi-colon was kept:  expect #s after */
+        while (isdigit((uch)(*pp)))
+            ++pp;
+        if (*pp == '\0')          /* only digits between ';' and end:  nuke */
+            *lastsemi = '\0';
+    }
+
+/*---------------------------------------------------------------------------
+    Report if directory was created (and no file to create:  filename ended
+    in '/'), check name to be sure it exists, and combine path and name be-
+    fore exiting.
+  ---------------------------------------------------------------------------*/
+
+    if (G.filename[G.os2.fnlen-1] == '/') {
+        checkdir(__G__ G.filename, GETPATH);
+        if (G.os2.created_dir) {
+            if (!uO.qflag)
+                Info(slide, 0, ((char *)slide, LoadFarString(Creating),
+                  G.filename));
+            if (G.extra_field) { /* zipfile extra field has extended attribs */
+                int err = EvalExtraFields(__G__ G.filename, G.extra_field,
+                                          G.lrec.extra_field_length);
+
+                if (err == IZ_EF_TRUNC) {
+                    if (uO.qflag)
+                        Info(slide, 1, ((char *)slide, "%-22s ", G.filename));
+                    Info(slide, 1, ((char *)slide, LoadFarString(TruncEAs),
+                      makeword(G.extra_field+2)-10, "\n"));
+                } else if (!uO.qflag)
+                    (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
+            } else if (!uO.qflag)
+                (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
+
+            /* set date/time stamps */
+            SetPathAttrTimes(__G__ G.pInfo->file_attr & ~A_ARCHIVE, 1);
+
+            return IZ_CREATED_DIR;   /* dir time already set */
+
+        } else if (G.extra_field && uO.overwrite_all) {
+            /* overwrite EAs of existing directory since user requested it */
+            int err = EvalExtraFields(__G__ G.filename, G.extra_field,
+                                      G.lrec.extra_field_length);
+
+            if (err == IZ_EF_TRUNC) {
+                Info(slide, 0x421, ((char *)slide, "%-22s ", G.filename));
+                Info(slide, 0x401, ((char *)slide, LoadFarString(TruncEAs),
+                  makeword(G.extra_field+2)-10, "\n"));
+            }
+
+            /* set date/time stamps (dirs only have creation times) */
+            SetPathAttrTimes(__G__ G.pInfo->file_attr & ~A_ARCHIVE, 1);
+        }
+        return 2;   /* dir existed already; don't look for data to extract */
+    }
+
+    if (*pathcomp == '\0') {
+        Info(slide, 1, ((char *)slide, LoadFarString(ConversionFailed),
+          G.filename));
+        return 3;
+    }
+
+    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */
+    checkdir(__G__ G.filename, GETPATH);
+    Trace((stderr, "mapname returns with filename = [%s] (error = %d)\n\n",
+      G.filename, error));
+
+    if (G.pInfo->vollabel) {    /* set the volume label now */
+        VOLUMELABEL FSInfoBuf;
+/* GRR:  "VOLUMELABEL" defined for IBM C and emx, but haven't checked MSC... */
+
+        strcpy(FSInfoBuf.szVolLabel, G.filename);
+        FSInfoBuf.cch = (BYTE)strlen(FSInfoBuf.szVolLabel);
+
+        if (!uO.qflag)
+            Info(slide, 0, ((char *)slide, LoadFarString(Labelling),
+              (char)(G.os2.nLabelDrive + 'a' - 1), G.filename));
+        if (DosSetFSInfo(G.os2.nLabelDrive, FSIL_VOLSER, (PBYTE)&FSInfoBuf,
+                         sizeof(VOLUMELABEL)))
+        {
+            Info(slide, 1, ((char *)slide, LoadFarString(ErrSetVolLabel)));
+            return 3;
+        }
+        return 2;   /* success:  skip the "extraction" quietly */
+    }
+
+    return error;
+
+} /* end function mapname() */
+
+
+
+
+
+/***********************/
+/* Function checkdir() */
+/***********************/
+
+int checkdir(__G__ pathcomp, flag)
+    __GDEF
+    char *pathcomp;
+    int flag;
+/*
+ * returns:  1 - (on APPEND_NAME) truncated filename
+ *           2 - path doesn't exist, not allowed to create
+ *           3 - path doesn't exist, tried to create and failed; or
+ *               path exists and is not a directory, but is supposed to be
+ *           4 - path is too long
+ *          10 - can't allocate memory for filename buffers
+ */
+{
+  /* moved to os2data.h so they can be global */
+#if 0
+    static int rootlen = 0;      /* length of rootpath */
+    static char *rootpath;       /* user's "extract-to" directory */
+    static char *buildpathHPFS;  /* full path (so far) to extracted file, */
+    static char *buildpathFAT;   /*  both HPFS/EA (main) and FAT versions */
+    static char *endHPFS;        /* corresponding pointers to end of */
+    static char *endFAT;         /*  buildpath ('\0') */
+#endif
+
+#   define FN_MASK   7
+#   define FUNCTION  (flag & FN_MASK)
+
+
+
+/*---------------------------------------------------------------------------
+    APPEND_DIR:  append the path component to the path being built and check
+    for its existence.  If doesn't exist and we are creating directories, do
+    so for this one; else signal success or error as appropriate.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == APPEND_DIR) {
+        char *p = pathcomp;
+        int longdirEA, too_long=FALSE;
+
+        Trace((stderr, "appending dir segment [%s]\n", pathcomp));
+        while ((*G.os2.endHPFS = *p++) != '\0')     /* copy to HPFS filename */
+            ++G.os2.endHPFS;
+        if (IsFileNameValid(G.os2.buildpathHPFS)) {
+            longdirEA = FALSE;
+            p = pathcomp;
+            while ((*G.os2.endFAT = *p++) != '\0')  /* copy to FAT filename, too */
+                ++G.os2.endFAT;
+        } else {
+            longdirEA = TRUE;
+/* GRR:  check error return? */
+            map2fat(pathcomp, &G.os2.endFAT);  /* map, put in FAT fn, update endFAT */
+        }
+
+        /* GRR:  could do better check, see if overrunning buffer as we go:
+         * check endHPFS-G.os2.buildpathHPFS after each append, set warning variable
+         * if within 20 of FILNAMSIZ; then if var set, do careful check when
+         * appending.  Clear variable when begin new path. */
+
+        /* next check:  need to append '/', at least one-char name, '\0' */
+        if ((G.os2.endHPFS-G.os2.buildpathHPFS) > FILNAMSIZ-3)
+            too_long = TRUE;                 /* check if extracting dir? */
+#ifdef MSC /* MSC 6.00 bug:  stat(non-existent-dir) == 0 [exists!] */
+        if (GetFileTime(G.os2.buildpathFAT) == -1 || stat(G.os2.buildpathFAT, &G.statbuf))
+#else
+        if (stat(G.os2.buildpathFAT, &G.statbuf))    /* path doesn't exist */
+#endif
+        {
+            if (!G.create_dirs) { /* told not to create (freshening) */
+                free(G.os2.buildpathHPFS);
+                free(G.os2.buildpathFAT);
+                return 2;         /* path doesn't exist:  nothing to do */
+            }
+            if (too_long) {   /* GRR:  should allow FAT extraction w/o EAs */
+                Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong),
+                  G.os2.buildpathHPFS));
+                free(G.os2.buildpathHPFS);
+                free(G.os2.buildpathFAT);
+                return 4;         /* no room for filenames:  fatal */
+            }
+            if (MKDIR(G.os2.buildpathFAT, 0777) == -1) {   /* create the directory */
+                Info(slide, 1, ((char *)slide, LoadFarString(CantCreateDir),
+                  G.os2.buildpathFAT, G.filename));
+                free(G.os2.buildpathHPFS);
+                free(G.os2.buildpathFAT);
+                return 3;      /* path didn't exist, tried to create, failed */
+            }
+            G.os2.created_dir = TRUE;
+            /* only set EA if creating directory */
+/* GRR:  need trailing '/' before function call? */
+            if (longdirEA) {
+#ifdef DEBUG
+                int e =
+#endif
+                  SetLongNameEA(G.os2.buildpathFAT, pathcomp);
+                Trace((stderr, "APPEND_DIR:  SetLongNameEA() returns %d\n", e));
+            }
+        } else if (!S_ISDIR(G.statbuf.st_mode)) {
+            Info(slide, 1, ((char *)slide, LoadFarString(DirIsntDirectory),
+              G.os2.buildpathFAT, G.filename));
+            free(G.os2.buildpathHPFS);
+            free(G.os2.buildpathFAT);
+            return 3;          /* path existed but wasn't dir */
+        }
+        if (too_long) {
+            Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong),
+              G.os2.buildpathHPFS));
+            free(G.os2.buildpathHPFS);
+            free(G.os2.buildpathFAT);
+            return 4;         /* no room for filenames:  fatal */
+        }
+        *G.os2.endHPFS++ = '/';
+        *G.os2.endFAT++ = '/';
+        *G.os2.endHPFS = *G.os2.endFAT = '\0';
+        Trace((stderr, "buildpathHPFS now = [%s]\n", G.os2.buildpathHPFS));
+        Trace((stderr, "buildpathFAT now =  [%s]\n", G.os2.buildpathFAT));
+        return 0;
+
+    } /* end if (FUNCTION == APPEND_DIR) */
+
+/*---------------------------------------------------------------------------
+    GETPATH:  copy full FAT path to the string pointed at by pathcomp (want
+    filename to reflect name used on disk, not EAs; if full path is HPFS,
+    buildpathFAT and buildpathHPFS will be identical).  Also free both paths.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == GETPATH) {
+        Trace((stderr, "getting and freeing FAT path [%s]\n", G.os2.buildpathFAT));
+        Trace((stderr, "freeing HPFS path [%s]\n", G.os2.buildpathHPFS));
+        strcpy(pathcomp, G.os2.buildpathFAT);
+        free(G.os2.buildpathFAT);
+        free(G.os2.buildpathHPFS);
+        G.os2.buildpathHPFS = G.os2.buildpathFAT = G.os2.endHPFS = G.os2.endFAT = (char *)NULL;
+        return 0;
+    }
+
+/*---------------------------------------------------------------------------
+    APPEND_NAME:  assume the path component is the filename; append it and
+    return without checking for existence.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == APPEND_NAME) {
+        char *p = pathcomp;
+        int error = 0;
+
+        Trace((stderr, "appending filename [%s]\n", pathcomp));
+        while ((*G.os2.endHPFS = *p++) != '\0') {    /* copy to HPFS filename */
+            ++G.os2.endHPFS;
+            if ((G.os2.endHPFS-G.os2.buildpathHPFS) >= FILNAMSIZ) {
+                *--G.os2.endHPFS = '\0';
+                Info(slide, 1, ((char *)slide, LoadFarString(PathTooLongTrunc),
+                  G.filename, G.os2.buildpathHPFS));
+                error = 1;   /* filename truncated */
+            }
+        }
+
+/* GRR:  how can longnameEA ever be set before this point???  we don't want
+ * to save the original name to EAs if user renamed it, do we?
+ *
+ * if (!G.os2.longnameEA && ((G.os2.longnameEA = !IsFileNameValid(name)) != 0))
+ */
+        if (G.pInfo->vollabel || IsFileNameValid(G.os2.buildpathHPFS)) {
+            G.os2.longnameEA = FALSE;
+            p = pathcomp;
+            while ((*G.os2.endFAT = *p++) != '\0')   /* copy to FAT filename, too */
+                ++G.os2.endFAT;
+        } else {
+            G.os2.longnameEA = TRUE;
+            if ((G.os2.lastpathcomp = (char *)malloc(strlen(pathcomp)+1)) ==
+                (char *)NULL)
+            {
+                Info(slide, 1, ((char *)slide,
+                 "checkdir warning:  cannot save longname EA: out of memory\n"));
+                G.os2.longnameEA = FALSE;
+                error = 1;   /* can't set .LONGNAME extended attribute */
+            } else           /* used and freed in close_outfile() */
+                strcpy(G.os2.lastpathcomp, pathcomp);
+            map2fat(pathcomp, &G.os2.endFAT);  /* map, put in FAT fn, update endFAT */
+        }
+        Trace((stderr, "buildpathHPFS: %s\nbuildpathFAT:  %s\n",
+          G.os2.buildpathHPFS, G.os2.buildpathFAT));
+
+        return error;  /* could check for existence, prompt for new name... */
+
+    } /* end if (FUNCTION == APPEND_NAME) */
+
+/*---------------------------------------------------------------------------
+    INIT:  allocate and initialize buffer space for the file currently being
+    extracted.  If file was renamed with an absolute path, don't prepend the
+    extract-to path.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == INIT) {
+        Trace((stderr, "initializing buildpathHPFS and buildpathFAT to "));
+        if ((G.os2.buildpathHPFS = (char *)malloc(G.os2.fnlen+G.os2.rootlen+1)) == (char *)NULL)
+            return 10;
+        if ((G.os2.buildpathFAT = (char *)malloc(G.os2.fnlen+G.os2.rootlen+1)) == (char *)NULL) {
+            free(G.os2.buildpathHPFS);
+            return 10;
+        }
+        if (G.pInfo->vollabel) {  /* use root or renamed path, but don't store */
+/* GRR:  for network drives, do strchr() and return IZ_VOL_LABEL if not [1] */
+            if (G.os2.renamed_fullpath && pathcomp[1] == ':')
+                *G.os2.buildpathHPFS = (char)ToLower(*pathcomp);
+            else if (!G.os2.renamed_fullpath && G.os2.rootlen > 1 && G.os2.rootpath[1] == ':')
+                *G.os2.buildpathHPFS = (char)ToLower(*G.os2.rootpath);
+            else {
+                ULONG lMap;
+                DosQueryCurrentDisk(&G.os2.nLabelDrive, &lMap);
+                *G.os2.buildpathHPFS = (char)(G.os2.nLabelDrive - 1 + 'a');
+            }
+            G.os2.nLabelDrive = *G.os2.buildpathHPFS - 'a' + 1; /* save for mapname() */
+            if (uO.volflag == 0 || *G.os2.buildpathHPFS < 'a' ||  /* no labels/bogus? */
+                (uO.volflag == 1 && !isfloppy(G.os2.nLabelDrive))) { /* -$:  no fixed */
+                free(G.os2.buildpathHPFS);
+                free(G.os2.buildpathFAT);
+                return IZ_VOL_LABEL;   /* skipping with message */
+            }
+            *G.os2.buildpathHPFS = '\0';
+        } else if (G.os2.renamed_fullpath)   /* pathcomp = valid data */
+            strcpy(G.os2.buildpathHPFS, pathcomp);
+        else if (G.os2.rootlen > 0)
+            strcpy(G.os2.buildpathHPFS, G.os2.rootpath);
+        else
+            *G.os2.buildpathHPFS = '\0';
+        G.os2.endHPFS = G.os2.buildpathHPFS;
+        G.os2.endFAT = G.os2.buildpathFAT;
+        while ((*G.os2.endFAT = *G.os2.endHPFS) != '\0') {
+            ++G.os2.endFAT;
+            ++G.os2.endHPFS;
+        }
+        Trace((stderr, "[%s]\n", G.os2.buildpathHPFS));
+        return 0;
+    }
+
+/*---------------------------------------------------------------------------
+    ROOT:  if appropriate, store the path in rootpath and create it if neces-
+    sary; else assume it's a zipfile member and return.  This path segment
+    gets used in extracting all members from every zipfile specified on the
+    command line.  Note that under OS/2 and MS-DOS, if a candidate extract-to
+    directory specification includes a drive letter (leading "x:"), it is
+    treated just as if it had a trailing '/'--that is, one directory level
+    will be created if the path doesn't exist, unless this is otherwise pro-
+    hibited (e.g., freshening).
+  ---------------------------------------------------------------------------*/
+
+#if (!defined(SFX) || defined(SFX_EXDIR))
+    if (FUNCTION == ROOT) {
+        Trace((stderr, "initializing root path to [%s]\n", pathcomp));
+        if (pathcomp == (char *)NULL) {
+            G.os2.rootlen = 0;
+            return 0;
+        }
+        if ((G.os2.rootlen = strlen(pathcomp)) > 0) {
+            int had_trailing_pathsep=FALSE, has_drive=FALSE, xtra=2;
+
+            if (isalpha(pathcomp[0]) && pathcomp[1] == ':')
+                has_drive = TRUE;   /* drive designator */
+            if (pathcomp[G.os2.rootlen-1] == '/') {
+                pathcomp[--G.os2.rootlen] = '\0';
+                had_trailing_pathsep = TRUE;
+            }
+            if (has_drive && (G.os2.rootlen == 2)) {
+                if (!had_trailing_pathsep)   /* i.e., original wasn't "x:/" */
+                    xtra = 3;      /* room for '.' + '/' + 0 at end of "x:" */
+            } else if (G.os2.rootlen > 0) {     /* need not check "x:." and "x:/" */
+#ifdef MSC      /* MSC 6.00 bug:  stat(non-existent-dir) == 0 [exists!] */
+                if (GetFileTime(pathcomp) == -1 ||
+                    SSTAT(pathcomp, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))
+#else
+                if (SSTAT(pathcomp, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))
+#endif
+                {   /* path does not exist */
+                    if (!G.create_dirs                 /* || iswild(pathcomp) */
+                                       ) {
+                        G.os2.rootlen = 0;
+                        return 2;   /* treat as stored file */
+                    }
+                    /* create directory (could add loop here to scan pathcomp
+                     * and create more than one level, but really necessary?) */
+                    if (MKDIR(pathcomp, 0777) == -1) {
+                        Info(slide, 1, ((char *)slide,
+                          LoadFarString(CantCreateExtractDir), pathcomp));
+                        G.os2.rootlen = 0;   /* path didn't exist, tried to create, */
+                        return 3;  /* failed:  file exists, or need 2+ levels */
+                    }
+                }
+            }
+            if ((G.os2.rootpath = (char *)malloc(G.os2.rootlen+xtra)) == (char *)NULL) {
+                G.os2.rootlen = 0;
+                return 10;
+            }
+            strcpy(G.os2.rootpath, pathcomp);
+            if (xtra == 3)                  /* had just "x:", make "x:." */
+                G.os2.rootpath[G.os2.rootlen++] = '.';
+            G.os2.rootpath[G.os2.rootlen++] = '/';
+            G.os2.rootpath[G.os2.rootlen] = '\0';
+            Trace((stderr, "rootpath now = [%s]\n", G.os2.rootpath));
+        }
+        return 0;
+    }
+#endif /* !SFX || SFX_EXDIR */
+
+/*---------------------------------------------------------------------------
+    END:  free rootpath, immediately prior to program exit.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == END) {
+        Trace((stderr, "freeing rootpath\n"));
+        if (G.os2.rootlen > 0) {
+            free(G.os2.rootpath);
+            G.os2.rootlen = 0;
+        }
+        return 0;
+    }
+
+    return 99;  /* should never reach */
+
+} /* end function checkdir() */
+
+
+
+
+
+/***********************/
+/* Function isfloppy() */   /* more precisely, is it removable? */
+/***********************/
+
+static int isfloppy(nDrive)
+    int nDrive;   /* 1 == A:, 2 == B:, etc. */
+{
+    uch ParmList[1] = {0};
+    uch DataArea[1] = {0};
+    char Name[3];
+    HFILE handle;
+#ifdef __32BIT__
+    ULONG rc;
+    ULONG action;
+#else
+    USHORT rc;
+    USHORT action;
+#endif
+
+
+    Name[0] = (char) (nDrive + 'A' - 1);
+    Name[1] = ':';
+    Name[2] = 0;
+
+    rc = DosOpen(Name, &handle, &action, 0L, FILE_NORMAL, FILE_OPEN,
+                 OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR |
+                 OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0L);
+
+    if (rc == ERROR_NOT_READY)   /* must be removable */
+      return TRUE;
+    else if (rc) {   /* other error:  do default a/b heuristic instead */
+      Trace((stderr, "error in DosOpen(DASD):  guessing...\n", rc));
+      return (nDrive == 1 || nDrive == 2)? TRUE : FALSE;
+    }
+
+    rc = DosDevIOCtl(DataArea, sizeof(DataArea), ParmList, sizeof(ParmList),
+                     DSK_BLOCKREMOVABLE, IOCTL_DISK, handle);
+    DosClose(handle);
+
+    if (rc) {   /* again, just check for a/b */
+        Trace((stderr, "error in DosDevIOCtl category IOCTL_DISK, function "
+          "DSK_BLOCKREMOVABLE\n  (rc = 0x%04x):  guessing...\n", rc));
+        return (nDrive == 1 || nDrive == 2)? TRUE : FALSE;
+    } else {
+        return DataArea[0] ? FALSE : TRUE;
+    }
+} /* end function isfloppy() */
+
+
+
+
+
+static int IsFileNameValid(const char *name)
+{
+  HFILE hf;
+#ifdef __32BIT__
+  ULONG uAction;
+#else
+  USHORT uAction;
+#endif
+
+  switch( DosOpen((PSZ) name, &hf, &uAction, 0, 0, FILE_OPEN,
+                  OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0) )
+  {
+  case ERROR_INVALID_NAME:
+  case ERROR_FILENAME_EXCED_RANGE:
+    return FALSE;
+  case NO_ERROR:
+    DosClose(hf);
+  default:
+    return TRUE;
+  }
+}
+
+
+
+
+
+/**********************/
+/* Function map2fat() */
+/**********************/
+
+static void map2fat(pathcomp, pEndFAT)
+    char *pathcomp, **pEndFAT;
+{
+    char *ppc = pathcomp;          /* variable pointer to pathcomp */
+    char *pEnd = *pEndFAT;         /* variable pointer to buildpathFAT */
+    char *pBegin = *pEndFAT;       /* constant pointer to start of this comp. */
+    char *last_dot = (char *)NULL; /* last dot not converted to underscore */
+    int dotname = FALSE;           /* flag:  path component begins with dot */
+                                   /*  ("." and ".." don't count) */
+    register unsigned workch;      /* hold the character being tested */
+
+
+    /* Only need check those characters which are legal in HPFS but not
+     * in FAT:  to get here, must already have passed through mapname.
+     * (GRR:  oops, small bug--if char was quoted, no longer have any
+     * knowledge of that.)  Also must truncate path component to ensure
+     * 8.3 compliance...
+     */
+    while ((workch = (uch)*ppc++) != 0) {
+        switch (workch) {
+            case '[':               /* add  '"'  '+'  ','  '='  ?? */
+            case ']':
+                *pEnd++ = '_';      /* convert brackets to underscores */
+                break;
+
+            case '.':
+                if (pEnd == *pEndFAT) {   /* nothing appended yet... */
+                    if (*ppc == '\0')     /* don't bother appending a */
+                        break;            /*  "./" component to the path */
+                    else if (*ppc == '.' && ppc[1] == '\0') {   /* "../" */
+                        *pEnd++ = '.';    /* add first dot, unchanged... */
+                        ++ppc;            /* skip second dot, since it will */
+                    } else {              /*  be "added" at end of if-block */
+                        *pEnd++ = '_';    /* FAT doesn't allow null filename */
+                        dotname = TRUE;   /*  bodies, so map .exrc -> _.exrc */
+                    }                     /*  (extra '_' now, "dot" below) */
+                } else if (dotname) {     /* found a second dot, but still */
+                    dotname = FALSE;      /*  have extra leading underscore: */
+                    *pEnd = '\0';         /*  remove it by shifting chars */
+                    pEnd = *pEndFAT + 1;  /*  left one space (e.g., .p1.p2: */
+                    while (pEnd[1]) {     /*  __p1 -> _p1_p2 -> _p1.p2 when */
+                        *pEnd = pEnd[1];  /*  finished) [opt.:  since first */
+                        ++pEnd;           /*  two chars are same, can start */
+                    }                     /*  shifting at second position] */
+                }
+                last_dot = pEnd;    /* point at last dot so far... */
+                *pEnd++ = '_';      /* convert dot to underscore for now */
+                break;
+
+            default:
+                *pEnd++ = (char)workch;
+
+        } /* end switch */
+    } /* end while loop */
+
+    *pEnd = '\0';                 /* terminate buildpathFAT */
+
+    /* NOTE:  keep in mind that pEnd points to the end of the path
+     * component, and *pEndFAT still points to the *beginning* of it...
+     * Also note that the algorithm does not try to get too fancy:
+     * if there are no dots already, the name either gets truncated
+     * at 8 characters or the last underscore is converted to a dot
+     * (only if more characters are saved that way).  In no case is
+     * a dot inserted between existing characters.
+     */
+    if (last_dot == (char *)NULL) {  /* no dots:  check for underscores... */
+        char *plu = strrchr(pBegin, '_');    /* pointer to last underscore */
+
+        if (plu == (char *)NULL) { /* no dots, no underscores:  truncate at 8 */
+            *pEndFAT += 8;         /* chars (could insert '.' and keep 11...) */
+            if (*pEndFAT > pEnd)
+                *pEndFAT = pEnd;   /* oops...didn't have 8 chars to truncate */
+            else
+                **pEndFAT = '\0';
+        } else if (MIN(plu - pBegin, 8) + MIN(pEnd - plu - 1, 3) > 8) {
+            last_dot = plu;        /* be lazy:  drop through to next if-block */
+        } else if ((pEnd - *pEndFAT) > 8) {
+            *pEndFAT += 8;         /* more fits into just basename than if */
+            **pEndFAT = '\0';      /*  convert last underscore to dot */
+        } else
+            *pEndFAT = pEnd;       /* whole thing fits into 8 chars or less */
+    }
+
+    if (last_dot != (char *)NULL) {   /* one dot (or two, in the case of */
+        *last_dot = '.';              /*  "..") is OK:  put it back in */
+
+        if ((last_dot - pBegin) > 8) {
+            char *p, *q;
+            int i;
+
+            p = last_dot;
+            q = last_dot = pBegin + 8;
+            for (i = 0;  (i < 4) && *p;  ++i)  /* too many chars in basename: */
+                *q++ = *p++;                   /*  shift ".ext" left and */
+            *q = '\0';                         /*  truncate/terminate it */
+            *pEndFAT = q;
+        } else if ((pEnd - last_dot) > 4) {    /* too many chars in extension */
+            *pEndFAT = last_dot + 4;
+            **pEndFAT = '\0';
+        } else
+            *pEndFAT = pEnd;   /* filename is fine; point at terminating zero */
+
+        if ((last_dot - pBegin) > 0 && last_dot[-1] == ' ')
+            last_dot[-1] = '_';                /* NO blank in front of '.'! */
+    }
+} /* end function map2fat() */
+
+
+
+
+
+static int SetLongNameEA(char *name, char *longname)
+{
+  EAOP eaop;
+  FEALST fealst;
+
+  eaop.fpFEAList = (PFEALIST) &fealst;
+  eaop.fpGEAList = NULL;
+  eaop.oError = 0;
+
+  strcpy((char *) fealst.szName, ".LONGNAME");
+  strcpy((char *) fealst.szValue, longname);
+
+  fealst.cbList  = sizeof(fealst) - CCHMAXPATH + strlen((char *) fealst.szValue);
+  fealst.cbName  = (BYTE) strlen((char *) fealst.szName);
+  fealst.cbValue = sizeof(USHORT) * 2 + strlen((char *) fealst.szValue);
+
+#ifdef __32BIT__
+  fealst.oNext   = 0;
+#endif
+  fealst.fEA     = 0;
+  fealst.eaType  = 0xFFFD;
+  fealst.eaSize  = strlen((char *) fealst.szValue);
+
+  return DosSetPathInfo(name, FIL_QUERYEASIZE,
+                        (PBYTE) &eaop, sizeof(eaop), 0);
+}
+
+
+
+
+
+/****************************/
+/* Function close_outfile() */
+/****************************/
+
+           /* GRR:  need to return error level!! */
+
+void close_outfile(__G)   /* only for extracted files, not directories */
+    __GDEF
+{
+    fclose(G.outfile);
+
+    /* set extra fields, both stored-in-zipfile and .LONGNAME flavors */
+    if (G.extra_field) {    /* zipfile extra field may have extended attribs */
+        int err = EvalExtraFields(__G__ G.filename, G.extra_field,
+                                  G.lrec.extra_field_length);
+
+        if (err == IZ_EF_TRUNC) {
+            if (uO.qflag)
+                Info(slide, 1, ((char *)slide, "%-22s ", G.filename));
+            Info(slide, 1, ((char *)slide, LoadFarString(TruncEAs),
+              makeword(G.extra_field+2)-10, uO.qflag? "\n" : ""));
+        }
+    }
+
+    if (G.os2.longnameEA) {
+#ifdef DEBUG
+        int e =
+#endif
+          SetLongNameEA(G.filename, G.os2.lastpathcomp);
+        Trace((stderr, "close_outfile:  SetLongNameEA() returns %d\n", e));
+        free(G.os2.lastpathcomp);
+    }
+
+    /* set date/time and permissions */
+    SetPathAttrTimes(__G__ G.pInfo->file_attr, 0);
+
+} /* end function close_outfile() */
+
+
+
+
+
+/******************************/
+/* Function check_for_newer() */
+/******************************/
+
+int check_for_newer(__G__ filename)   /* return 1 if existing file newer or equal; */
+    __GDEF
+    char *filename;             /*  0 if older; -1 if doesn't exist yet */
+{
+    ulg existing, archive;
+#ifdef USE_EF_UT_TIME
+    iztimes z_utime;
+#endif
+
+    if ((existing = (ulg)GetFileTime(filename)) == (ulg)-1)
+        return DOES_NOT_EXIST;
+
+#ifdef USE_EF_UT_TIME
+    if (G.extra_field &&
+#ifdef IZ_CHECK_TZ
+        G.tz_is_valid &&
+#endif
+        (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,
+                          G.lrec.last_mod_dos_datetime, &z_utime, NULL)
+         & EB_UT_FL_MTIME))
+    {
+        TTrace((stderr, "check_for_newer:  using Unix extra field mtime\n"));
+        archive = Utime2DosDateTime(z_utime.mtime);
+    } else {
+        archive = G.lrec.last_mod_dos_datetime;
+    }
+#else /* !USE_EF_UT_TIME */
+    archive = G.lrec.last_mod_dos_datetime;
+#endif /* ?USE_EF_UT_TIME */
+
+    return (existing >= archive);
+} /* end function check_for_newer() */
+
+
+
+
+
+#ifndef SFX
+
+/*************************/
+/* Function dateformat() */
+/*************************/
+
+int dateformat()
+{
+/*-----------------------------------------------------------------------------
+  For those operating systems which support it, this function returns a value
+  which tells how national convention says that numeric dates are displayed.
+  Return values are DF_YMD, DF_DMY and DF_MDY.
+ -----------------------------------------------------------------------------*/
+
+    switch (GetCountryInfo()) {
+        case 0:
+            return DF_MDY;
+        case 1:
+            return DF_DMY;
+        case 2:
+            return DF_YMD;
+    }
+    return DF_MDY;   /* default if error */
+
+} /* end function dateformat() */
+
+
+
+
+
+/************************/
+/*  Function version()  */
+/************************/
+
+void version(__G)
+    __GDEF
+{
+    int len;
+#if defined(__IBMC__) || defined(__WATCOMC__) || defined(_MSC_VER)
+    char buf[80];
+#endif
+
+    len = sprintf((char *)slide, LoadFarString(CompiledWith),
+
+#if defined(__GNUC__)
+#  ifdef __EMX__  /* __EMX__ is defined as "1" only (sigh) */
+      "emx+gcc ", __VERSION__,
+#  else
+      "gcc/2 ", __VERSION__,
+#  endif
+#elif defined(__IBMC__)
+      "IBM ",
+#  if (__IBMC__ < 200)
+      (sprintf(buf, "C Set/2 %d.%02d", __IBMC__/100,__IBMC__%100), buf),
+#  elif (__IBMC__ < 300)
+      (sprintf(buf, "C Set++ %d.%02d", __IBMC__/100,__IBMC__%100), buf),
+#  else
+      (sprintf(buf, "Visual Age C++ %d.%02d", __IBMC__/100,__IBMC__%100), buf),
+#  endif
+#elif defined(__WATCOMC__)
+      "Watcom C", (sprintf(buf, " (__WATCOMC__ = %d)", __WATCOMC__), buf),
+#elif defined(__TURBOC__)
+#  ifdef __BORLANDC__
+      "Borland C++",
+#    if (__BORLANDC__ < 0x0460)
+        " 1.0",
+#    elif (__BORLANDC__ == 0x0460)
+        " 1.5",                     /* from Kai Uwe:  three less than DOS */
+#    else
+        " 2.0",                     /* (__BORLANDC__ == 0x0500)? */
+#    endif
+#  else
+      "Turbo C",                    /* these are probably irrelevant */
+#    if (__TURBOC__ >= 661)
+       "++ 1.0 or later",
+#    elif (__TURBOC__ == 661)
+       " 3.0?",
+#    elif (__TURBOC__ == 397)
+       " 2.0",
+#    else
+       " 1.0 or 1.5?",
+#    endif
+#  endif
+#elif defined(MSC)
+      "Microsoft C ",
+#  ifdef _MSC_VER
+      (sprintf(buf, "%d.%02d", _MSC_VER/100, _MSC_VER%100), buf),
+#  else
+      "5.1 or earlier",
+#  endif
+#else
+      "unknown compiler", "",
+#endif /* ?compilers */
+
+      "OS/2",
+
+/* GRR:  does IBM C/2 identify itself as IBM rather than Microsoft? */
+#if (defined(MSC) || (defined(__WATCOMC__) && !defined(__386__)))
+#  if defined(M_I86HM) || defined(__HUGE__)
+      " (16-bit, huge)",
+#  elif defined(M_I86LM) || defined(__LARGE__)
+      " (16-bit, large)",
+#  elif defined(M_I86MM) || defined(__MEDIUM__)
+      " (16-bit, medium)",
+#  elif defined(M_I86CM) || defined(__COMPACT__)
+      " (16-bit, compact)",
+#  elif defined(M_I86SM) || defined(__SMALL__)
+      " (16-bit, small)",
+#  elif defined(M_I86TM) || defined(__TINY__)
+      " (16-bit, tiny)",
+#  else
+      " (16-bit)",
+#  endif
+#else
+      " 2.x/3.x (32-bit)",
+#endif
+
+#ifdef __DATE__
+      " on ", __DATE__
+#else
+      "", ""
+#endif
+    );
+
+    (*G.message)((zvoid *)&G, slide, (ulg)len, 0);
+                                /* MSC can't handle huge macro expansions */
+
+    /* temporary debugging code for Borland compilers only */
+    /* __TCPLUSPLUS__, __BCPLUSPLUS__ not defined for v1.5 */
+#if (defined(__TURBOC__) && defined(DEBUG))
+    Info(slide, 0, ((char *)slide, "\t(__TURBOC__ = 0x%04x = %d)\n", __TURBOC__,
+      __TURBOC__));
+#ifdef __BORLANDC__
+    Info(slide, 0, ((char *)slide, "\t(__BORLANDC__ = 0x%04x)\n",__BORLANDC__));
+#else
+    Info(slide, 0, ((char *)slide, "\tdebug(__BORLANDC__ not defined)\n"));
+#endif
+#endif /* __TURBOC__ && DEBUG */
+
+} /* end function version() */
+
+#endif /* !SFX */
+
+
+
+/* This table can be static because it is pseudo-constant */
+static unsigned char cUpperCase[256], cLowerCase[256];
+static BOOL bInitialized=FALSE;
+
+/* Initialize the tables of upper- and lowercase characters, including
+   handling of country-dependent characters. */
+
+static void InitNLS(void)
+{
+  unsigned nCnt, nU;
+  COUNTRYCODE cc;
+
+  if (bInitialized == FALSE) {
+    bInitialized = TRUE;
+
+    for ( nCnt = 0; nCnt < 256; nCnt++ )
+      cUpperCase[nCnt] = cLowerCase[nCnt] = (unsigned char) nCnt;
+
+    cc.country = cc.codepage = 0;
+    DosMapCase(sizeof(cUpperCase), &cc, (PCHAR) cUpperCase);
+
+    for ( nCnt = 0; nCnt < 256; nCnt++ ) {
+      nU = cUpperCase[nCnt];
+      if (nU != nCnt && cLowerCase[nU] == (unsigned char) nU)
+        cLowerCase[nU] = (unsigned char) nCnt;
+    }
+
+    for ( nCnt = 'A'; nCnt <= 'Z'; nCnt++ )
+      cLowerCase[nCnt] = (unsigned char) (nCnt - 'A' + 'a');
+  }
+}
+
+
+int IsUpperNLS(int nChr)
+{
+  return (cUpperCase[nChr] == (unsigned char) nChr);
+}
+
+
+int ToLowerNLS(int nChr)
+{
+  return cLowerCase[nChr];
+}
+
+
+char *StringLower(char *szArg)
+{
+  unsigned char *szPtr;
+
+  for ( szPtr = (unsigned char *) szArg; *szPtr; szPtr++ )
+    *szPtr = cLowerCase[*szPtr];
+  return szArg;
+}
+
+
+#if defined(__IBMC__) && defined(__DEBUG_ALLOC__)
+void DebugMalloc(void)
+{
+  _dump_allocated(0); /* print out debug malloc memory statistics */
+}
+#endif
+
+
+#if defined(REENTRANT) && defined(USETHREADID)
+ulg GetThreadId(void)
+{
+  PTIB   pptib;       /* Address of a pointer to the
+                         Thread Information Block */
+  PPIB   pppib;       /* Address of a pointer to the
+                         Process Information Block */
+
+  DosGetInfoBlocks(&pptib, &pppib);
+  return pptib->tib_ptib2->tib2_ultid;
+}
+#endif /* defined(REENTRANT) && defined(USETHREADID) */
+
+
+void os2GlobalsCtor(__GPRO)
+{
+  G.os2.nLastDrive = (USHORT)(-1);
+  G.os2.firstcall = TRUE;
+
+#ifdef OS2DLL
+  G.os2.rexx_mes = "0";
+#endif
+
+  InitNLS();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/os2acl.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,387 @@
+/* os2acl.c - access to OS/2 (LAN Server) ACLs
+ *
+ * Author:  Kai Uwe Rommel <rommel@ars.de>
+ * Created: Mon Aug 08 1994
+ *
+ * This code is in the public domain.
+ */
+
+/*
+ * supported 32-bit compilers:
+ * - emx+gcc
+ * - IBM C Set++ 2.1 or newer
+ * - Watcom C/C++ 10.0 or newer
+ *
+ * supported 16-bit compilers:
+ * - MS C 6.00A
+ * - Watcom C/C++ 10.0 or newer
+ *
+ * supported OS/2 LAN environments:
+ * - IBM LAN Server/Requester 3.0, 4.0 and 5.0 (Warp Server)
+ * - IBM Peer 1.0 (Warp Connect)
+ */
+
+#ifdef KUR
+   static char *rcsid =
+   "$Id: os2acl.c,v 1.1 2001/04/03 22:18:28 bsmith Exp $";
+   static char *rcsrev = "$Revision: 1.1 $";
+#endif
+
+/*
+ * $Log: os2acl.c,v $
+ * Revision 1.1  2001/04/03 22:18:28  bsmith
+ * Added multidecompressor sfx code, and modified build scheme.
+ *
+ * Revision 1.2  2000/07/15 19:50:50  cvsuser
+ * merged 2.2 branch
+ *
+ * Revision 1.1.2.1  2000/04/11 12:38:06  BS
+ * Added wxInstall a self extracting installation program using wxWindows.
+ *
+ * Revision 1.3  1996/04/03 19:18:27  rommel
+ * minor fixes
+ *
+ * Revision 1.2  1996/03/30 22:03:52  rommel
+ * avoid frequent dynamic allocation for every call
+ * streamlined code
+ *
+ * Revision 1.1  1996/03/30 09:35:00  rommel
+ * Initial revision
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <malloc.h>
+
+#define INCL_NOPM
+#define INCL_DOS
+#define INCL_DOSERRORS
+#include <os2.h>
+
+#include "os2/os2acl.h"
+
+#define UNLEN 20
+
+#if defined(__WATCOMC__) && defined(__386__) && !defined(__32BIT__)
+#define __32BIT__
+#endif
+
+#ifdef __32BIT__
+typedef ULONG U_INT;
+#ifdef __EMX__
+#define PSTR16 _far16ptr
+#define PTR16(x) _emx_32to16(x)
+#else /* other 32-bit */
+#define PSTR16 PCHAR16
+#define PTR16(x) ((PCHAR16)(x))
+#endif
+#else /* 16-bit */
+typedef USHORT U_INT;
+#define PSTR16 PSZ
+#define PTR16(x) (x)
+#endif
+
+typedef struct access_list
+{
+  char acl_ugname[UNLEN+1];
+  char acl_pad;
+  USHORT acl_access;
+}
+ACCLIST;
+
+typedef struct access_info
+{
+  PSTR16 acc_resource_name;
+  USHORT acc_attr;
+  USHORT acc_count;
+}
+ACCINFO;
+
+static ACCINFO *ai;
+static char *path, *data;
+
+#ifdef __32BIT__
+
+#ifdef __EMX__
+
+static USHORT (APIENTRY *_NetAccessGetInfo)(PSZ pszServer, PSZ pszResource,
+  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail);
+static USHORT (APIENTRY *_NetAccessSetInfo)(PSZ pszServer, PSZ pszResource,
+  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum);
+static USHORT (APIENTRY *_NetAccessAdd)(PSZ pszServer,
+  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer);
+
+USHORT NetAccessGetInfo(PSZ pszServer, PSZ pszResource, USHORT sLevel,
+                        PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail)
+{
+  return (USHORT)
+          (_THUNK_PROLOG (4+4+2+4+2+4);
+           _THUNK_FLAT (pszServer);
+           _THUNK_FLAT (pszResource);
+           _THUNK_SHORT (sLevel);
+           _THUNK_FLAT (pbBuffer);
+           _THUNK_SHORT (cbBuffer);
+           _THUNK_FLAT (pcbTotalAvail);
+           _THUNK_CALLI (_emx_32to16(_NetAccessGetInfo)));
+}
+
+USHORT NetAccessSetInfo(PSZ pszServer, PSZ pszResource, USHORT sLevel,
+                        PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum)
+{
+  return (USHORT)
+          (_THUNK_PROLOG (4+4+2+4+2+2);
+           _THUNK_FLAT (pszServer);
+           _THUNK_FLAT (pszResource);
+           _THUNK_SHORT (sLevel);
+           _THUNK_FLAT (pbBuffer);
+           _THUNK_SHORT (cbBuffer);
+           _THUNK_SHORT (sParmNum);
+           _THUNK_CALLI (_emx_32to16(_NetAccessSetInfo)));
+}
+
+USHORT NetAccessAdd(PSZ pszServer, USHORT sLevel,
+                    PVOID pbBuffer, USHORT cbBuffer)
+{
+  return (USHORT)
+          (_THUNK_PROLOG (4+2+4+2);
+           _THUNK_FLAT (pszServer);
+           _THUNK_SHORT (sLevel);
+           _THUNK_FLAT (pbBuffer);
+           _THUNK_SHORT (cbBuffer);
+           _THUNK_CALLI (_emx_32to16(_NetAccessAdd)));
+}
+
+#else /* other 32-bit */
+
+APIRET16 (* APIENTRY16 NetAccessGetInfo)(PCHAR16 pszServer, PCHAR16 pszResource,
+  USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer, PVOID16 pcbTotalAvail);
+APIRET16 (* APIENTRY16 NetAccessSetInfo)(PCHAR16 pszServer, PCHAR16 pszResource,
+  USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer, USHORT sParmNum);
+APIRET16 (* APIENTRY16 NetAccessAdd)(PCHAR16 pszServer,
+  USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer);
+
+#define _NetAccessGetInfo NetAccessGetInfo
+#define _NetAccessSetInfo NetAccessSetInfo
+#define _NetAccessAdd NetAccessAdd
+
+#if !defined(__IBMC__) || !defined(__TILED__)
+#define _tmalloc malloc
+#define _tfree free
+#endif
+
+#endif
+#else /* 16-bit */
+
+USHORT (APIENTRY *NetAccessGetInfo)(PSZ pszServer, PSZ pszResource,
+  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail);
+USHORT (APIENTRY *NetAccessSetInfo)(PSZ pszServer, PSZ pszResource,
+  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum);
+USHORT (APIENTRY *NetAccessAdd)(PSZ pszServer,
+  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer);
+
+#define _NetAccessGetInfo NetAccessGetInfo
+#define _NetAccessSetInfo NetAccessSetInfo
+#define _NetAccessAdd NetAccessAdd
+
+#define _tmalloc malloc
+#define _tfree free
+
+#define DosQueryProcAddr(handle, ord, name, funcptr) \
+        DosGetProcAddr(handle, name, funcptr)
+#define DosQueryCurrentDir DosQCurDir
+#define DosQueryCurrentDisk DosQCurDisk
+
+#endif
+
+
+static BOOL acl_init(void)
+{
+  static BOOL initialized, netapi_avail;
+  HMODULE netapi;
+  char buf[256];
+
+  if (initialized)
+    return netapi_avail;
+
+  initialized = TRUE;
+
+  if (DosLoadModule(buf, sizeof(buf), "NETAPI", &netapi))
+    return FALSE;
+
+  if (DosQueryProcAddr(netapi, 0, "NETACCESSGETINFO", (PFN *) &_NetAccessGetInfo) ||
+      DosQueryProcAddr(netapi, 0, "NETACCESSSETINFO", (PFN *) &_NetAccessSetInfo) ||
+      DosQueryProcAddr(netapi, 0, "NETACCESSADD", (PFN *) &_NetAccessAdd))
+    return FALSE;
+
+#if defined(__WATCOMC__) && defined(__386__)
+  NetAccessGetInfo = (PVOID) (ULONG) (PVOID16) NetAccessGetInfo;
+  NetAccessSetInfo = (PVOID) (ULONG) (PVOID16) NetAccessSetInfo;
+  NetAccessAdd     = (PVOID) (ULONG) (PVOID16) NetAccessAdd;
+#endif
+
+  if ((path = _tmalloc(CCHMAXPATH)) == NULL)
+    return FALSE;
+  if ((data = _tmalloc(ACL_BUFFERSIZE)) == NULL)
+    return FALSE;
+  if ((ai = _tmalloc(sizeof(ACCINFO))) == NULL)
+    return -1;
+
+  netapi_avail = TRUE;
+
+  return netapi_avail;
+}
+
+static void acl_mkpath(char *buffer, const char *source)
+{
+  char *ptr;
+  static char cwd[CCHMAXPATH];
+  static U_INT cwdlen;
+  U_INT cdrive;
+  ULONG drivemap;
+
+  if (isalpha(source[0]) && source[1] == ':')
+    buffer[0] = 0; /* fully qualified names */
+  else
+  {
+    if (cwd[0] == 0)
+    {
+      DosQueryCurrentDisk(&cdrive, &drivemap);
+      cwd[0] = (char)(cdrive + '@');
+      cwd[1] = ':';
+      cwd[2] = '\\';
+      cwdlen = sizeof(cwd) - 3;
+      DosQueryCurrentDir(0, cwd + 3, &cwdlen);
+      cwdlen = strlen(cwd);
+    }
+
+    if (source[0] == '/' || source[0] == '\\')
+    {
+      if (source[1] == '/' || source[1] == '\\')
+        buffer[0] = 0; /* UNC names */
+      else
+      {
+        strncpy(buffer, cwd, 2);
+        buffer[2] = 0;
+      }
+    }
+    else
+    {
+      strcpy(buffer, cwd);
+      if (cwd[cwdlen - 1] != '\\' && cwd[cwdlen - 1] != '/')
+        strcat(buffer, "/");
+    }
+  }
+
+  strcat(buffer, source);
+
+  for (ptr = buffer; *ptr; ptr++)
+    if (*ptr == '/')
+      *ptr = '\\';
+
+  if (ptr[-1] == '\\')
+    ptr[-1] = 0;
+
+  strupr(buffer);
+}
+
+static int acl_bin2text(char *data, char *text)
+{
+  ACCINFO *ai;
+  ACCLIST *al;
+  U_INT cnt, offs;
+
+  ai = (ACCINFO *) data;
+  al = (ACCLIST *) (data + sizeof(ACCINFO));
+
+  offs = sprintf(text, "ACL1:%X,%d\n",
+                 ai -> acc_attr, ai -> acc_count);
+
+  for (cnt = 0; cnt < ai -> acc_count; cnt++)
+    offs += sprintf(text + offs, "%s,%X\n",
+                    al[cnt].acl_ugname, al[cnt].acl_access);
+
+  return strlen(text);
+}
+
+int acl_get(char *server, const char *resource, char *buffer)
+{
+  USHORT datalen;
+  PSZ srv = NULL;
+  int rc;
+
+  if (!acl_init())
+    return -1;
+
+  if (server)
+    srv = server;
+
+  acl_mkpath(path, resource);
+  datalen = 0;
+
+  rc = NetAccessGetInfo(srv, path, 1, data, ACL_BUFFERSIZE, &datalen);
+
+  if (rc == 0)
+    acl_bin2text(data, buffer);
+
+  return rc;
+}
+
+static int acl_text2bin(char *data, char *text, char *path)
+{
+  ACCINFO *ai;
+  ACCLIST *al;
+  char *ptr, *ptr2;
+  U_INT cnt;
+
+  ai = (ACCINFO *) data;
+  ai -> acc_resource_name = PTR16(path);
+
+  if (sscanf(text, "ACL1:%hX,%hd",
+             &ai -> acc_attr, &ai -> acc_count) != 2)
+    return ERROR_INVALID_PARAMETER;
+
+  al = (ACCLIST *) (data + sizeof(ACCINFO));
+  ptr = strchr(text, '\n') + 1;
+
+  for (cnt = 0; cnt < ai -> acc_count; cnt++)
+  {
+    ptr2 = strchr(ptr, ',');
+    strncpy(al[cnt].acl_ugname, ptr, ptr2 - ptr);
+    al[cnt].acl_ugname[ptr2 - ptr] = 0;
+    sscanf(ptr2 + 1, "%hx", &al[cnt].acl_access);
+    ptr = strchr(ptr, '\n') + 1;
+  }
+
+  return sizeof(ACCINFO) + ai -> acc_count * sizeof(ACCLIST);
+}
+
+int acl_set(char *server, const char *resource, char *buffer)
+{
+  USHORT datalen;
+  PSZ srv = NULL;
+
+  if (!acl_init())
+    return -1;
+
+  if (server)
+    srv = server;
+
+  acl_mkpath(path, resource);
+
+  ai -> acc_resource_name = PTR16(path);
+  ai -> acc_attr = 0;
+  ai -> acc_count = 0;
+
+  NetAccessAdd(srv, 1, ai, sizeof(ACCINFO));
+  /* Ignore any errors, most probably because ACL already exists. */
+  /* In any such case, try updating the existing ACL. */
+
+  datalen = acl_text2bin(data, buffer, path);
+
+  return NetAccessSetInfo(srv, path, 1, data, datalen, 0);
+}
+
+/* end of os2acl.c */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/process.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,1401 @@
+/*---------------------------------------------------------------------------
+
+  process.c
+
+  This file contains the top-level routines for processing multiple zipfiles.
+
+  Contains:  process_zipfiles()
+             free_G_buffers()
+             do_seekable()
+             find_ecrec()
+             uz_end_central()
+             process_cdir_file_hdr()
+             get_cdir_ent()
+             process_local_file_hdr()
+             ef_scan_for_izux()
+
+  ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "dw.h"
+#include "install.h"
+#include "instsup.h"
+#include "unzip.h"
+#ifdef WINDLL
+#  ifdef POCKET_UNZIP
+#    include "wince/intrface.h"
+#  else
+#    include "windll/windll.h"
+#  endif
+#endif
+
+extern int installstate;
+
+off_t acelseek(off_t offset, int whence);
+int aceread(void *buf, size_t count);
+int aceopen(const char *path, int flags);
+int aceclose(int fd);
+int acesize(void);
+int acetell(int fd);
+char *replacestr(char *str1, char *str2, char *str3);
+
+static int    do_seekable        OF((__GPRO__ int lastchance));
+static int    find_ecrec         OF((__GPRO__ long searchlen));
+
+static ZCONST char Far CannotAllocateBuffers[] =
+  "error:  cannot allocate unzip buffers\n";
+
+#ifdef SFX
+   static ZCONST char Far CannotFindMyself[] =
+     "unzipsfx:  cannot find myself! [%s]\n";
+
+#else /* !SFX */
+   /* process_zipfiles() strings */
+# if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME))
+     static ZCONST char Far WarnInvalidTZ[] =
+       "Warning: TZ environment variable not found, cannot use UTC times!!\n";
+# endif
+   static ZCONST char Far FilesProcessOK[] =
+     "%d archive%s successfully processed.\n";
+   static ZCONST char Far ArchiveWarning[] =
+     "%d archive%s had warnings but no fatal errors.\n";
+   static ZCONST char Far ArchiveFatalError[] =
+     "%d archive%s had fatal errors.\n";
+   static ZCONST char Far FileHadNoZipfileDir[] =
+     "%d file%s had no zipfile directory.\n";
+   static ZCONST char Far ZipfileWasDir[] = "1 \"zipfile\" was a directory.\n";
+   static ZCONST char Far ManyZipfilesWereDir[] =
+     "%d \"zipfiles\" were directories.\n";
+   static ZCONST char Far NoZipfileFound[] = "No zipfiles found.\n";
+
+   /* do_seekable() strings */
+# ifdef UNIX
+   static ZCONST char Far CannotFindZipfileDirMsg[] =
+     "%s:  cannot find zipfile directory in one of %s or\n\
+        %s%s.zip, and cannot find %s, period.\n";
+   static ZCONST char Far CannotFindEitherZipfile[] =
+     "%s:  cannot find %s, %s.zip or %s.\n";   /* ", so there" removed 970918 */
+# else /* !UNIX */
+# ifndef AMIGA
+   static ZCONST char Far CannotFindWildcardMatch[] =
+     "%s:  cannot find any matches for wildcard specification \"%s\".\n";
+# endif /* !AMIGA */
+   static ZCONST char Far CannotFindZipfileDirMsg[] =
+     "%s:  cannot find zipfile directory in %s,\n\
+        %sand cannot find %s, period.\n";
+   static ZCONST char Far CannotFindEitherZipfile[] =
+     "%s:  cannot find either %s or %s.\n";    /* ", so there" removed 970918 */
+# endif /* ?UNIX */
+   extern ZCONST char Far Zipnfo[];       /* in unzip.c */
+#ifndef WINDLL
+   static ZCONST char Far Unzip[] = "unzip";
+#else
+   static ZCONST char Far Unzip[] = "UnZip DLL";
+#endif
+   static ZCONST char Far MaybeExe[] =
+     "note:  %s may be a plain executable, not an archive\n";
+   static ZCONST char Far CentDirNotInZipMsg[] = "\n\
+   [%s]:\n\
+     Zipfile is disk %u of a multi-disk archive, and this is not the disk on\n\
+     which the central zipfile directory begins (disk %u).\n";
+   static ZCONST char Far EndCentDirBogus[] =
+     "\nwarning [%s]:  end-of-central-directory record claims this\n\
+  is disk %u but that the central directory starts on disk %u; this is a\n\
+  contradiction.  Attempting to process anyway.\n";
+# ifdef NO_MULTIPART
+   static ZCONST char Far NoMultiDiskArcSupport[] =
+     "\nerror [%s]:  zipfile is part of multi-disk archive\n\
+  (sorry, not yet supported).\n";
+   static ZCONST char Far MaybePakBug[] = "warning [%s]:\
+  zipfile claims to be 2nd disk of a 2-part archive;\n\
+  attempting to process anyway.  If no further errors occur, this archive\n\
+  was probably created by PAK v2.51 or earlier.  This bug was reported to\n\
+  NoGate in March 1991 and was supposed to have been fixed by mid-1991; as\n\
+  of mid-1992 it still hadn't been.  (If further errors do occur, archive\n\
+  was probably created by PKZIP 2.04c or later; UnZip does not yet support\n\
+  multi-part archives.)\n";
+# else
+   static ZCONST char Far MaybePakBug[] = "warning [%s]:\
+  zipfile claims to be last disk of a multi-part archive;\n\
+  attempting to process anyway, assuming all parts have been concatenated\n\
+  together in order.  Expect \"errors\" and warnings...true multi-part support\
+\n  doesn't exist yet (coming soon).\n";
+# endif
+   static ZCONST char Far ExtraBytesAtStart[] =
+     "warning [%s]:  %ld extra byte%s at beginning or within zipfile\n\
+  (attempting to process anyway)\n";
+#endif /* ?SFX */
+
+static ZCONST char Far MissingBytes[] =
+  "error [%s]:  missing %ld bytes in zipfile\n\
+  (attempting to process anyway)\n";
+static ZCONST char Far NullCentDirOffset[] =
+  "error [%s]:  NULL central directory offset\n\
+  (attempting to process anyway)\n";
+static ZCONST char Far ZipfileEmpty[] = "warning [%s]:  zipfile is empty\n";
+static ZCONST char Far CentDirStartNotFound[] =
+  "error [%s]:  start of central directory not found;\n\
+  zipfile corrupt.\n%s";
+#ifndef SFX
+   static ZCONST char Far CentDirTooLong[] =
+     "error [%s]:  reported length of central directory is\n\
+  %ld bytes too long (Atari STZip zipfile?  J.H.Holm ZIPSPLIT 1.1\n\
+  zipfile?).  Compensating...\n";
+   static ZCONST char Far CentDirEndSigNotFound[] = "\
+  End-of-central-directory signature not found.  Either this file is not\n\
+  a zipfile, or it constitutes one disk of a multi-part archive.  In the\n\
+  latter case the central directory and zipfile comment will be found on\n\
+  the last disk(s) of this archive.\n";
+#else /* SFX */
+   static ZCONST char Far CentDirEndSigNotFound[] =
+     "  End-of-central-directory signature not found.\n";
+#endif /* ?SFX */
+static ZCONST char Far ZipfileCommTrunc1[] =
+  "\ncaution:  zipfile comment truncated\n";
+
+
+
+
+/*******************************/
+/* Function process_zipfiles() */
+/*******************************/
+
+int process_zipfiles(__G)    /* return PK-type error code */
+    __GDEF
+{
+#ifndef SFX
+    char *lastzipfn = (char *)NULL;
+    int NumWinFiles, NumLoseFiles, NumWarnFiles;
+    int NumMissDirs, NumMissFiles;
+#endif
+    int error=0, error_in_archive=0;
+	extern unsigned current_file;
+	extern char installdir2[];
+
+
+/*---------------------------------------------------------------------------
+    Start by allocating buffers and (re)constructing the various PK signature
+    strings.
+  ---------------------------------------------------------------------------*/
+
+    G.inbuf = (uch *)malloc(INBUFSIZ + 4);    /* 4 extra for hold[] (below) */
+    G.outbuf = (uch *)malloc(OUTBUFSIZ + 1);  /* 1 extra for string term. */
+
+    if ((G.inbuf == (uch *)NULL) || (G.outbuf == (uch *)NULL)) {
+        Info(slide, 0x401, ((char *)slide,
+          LoadFarString(CannotAllocateBuffers)));
+        return(PK_MEM);
+    }
+    G.hold = G.inbuf + INBUFSIZ;     /* to check for boundary-spanning sigs */
+#ifndef VMS     /* VMS uses its own buffer scheme for textmode flush(). */
+#ifdef SMALL_MEM
+    G.outbuf2 = G.outbuf+RAWBUFSIZ;  /* never changes */
+#endif
+#endif /* !VMS */
+
+#if 0 /* CRC_32_TAB has been NULLified by CONSTRUCTGLOBALS !!!! */
+    /* allocate the CRC table only later when we know we have a zipfile */
+    CRC_32_TAB = NULL;
+#endif /* 0 */
+
+    /* finish up initialization of magic signature strings */
+    local_hdr_sig[0]  /* = extd_local_sig[0] */  = 0x50;   /* ASCII 'P', */
+    central_hdr_sig[0] = end_central_sig[0] = 0x50;     /* not EBCDIC */
+
+    local_hdr_sig[1]  /* = extd_local_sig[1] */  = 0x4B;   /* ASCII 'K', */
+    central_hdr_sig[1] = end_central_sig[1] = 0x4B;     /* not EBCDIC */
+
+/*---------------------------------------------------------------------------
+    Make sure timezone info is set correctly; localtime() returns GMT on
+    some OSes (e.g., Solaris 2.x) if this isn't done first.  The ifdefs were
+    initially copied from dos_to_unix_time() in fileio.c. probably, they are
+    still too strict; any listed OS that supplies tzset(), regardless of
+    whether the function does anything, should be removed from the ifdefs.
+  ---------------------------------------------------------------------------*/
+
+#if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME))
+#  ifndef VALID_TIMEZONE
+#     define VALID_TIMEZONE(tmp) \
+             (((tmp = getenv("TZ")) != NULL) && (*tmp != '\0'))
+#  endif
+    {
+        char *p;
+        G.tz_is_valid = VALID_TIMEZONE(p);
+#  ifndef SFX
+        if (!G.tz_is_valid) {
+            Info(slide, 0x401, ((char *)slide, LoadFarString(WarnInvalidTZ)));
+            error_in_archive = error = PK_WARN;
+        }
+#  endif /* !SFX */
+    }
+#endif /* IZ_CHECK_TZ && USE_EF_UT_TIME */
+
+/* For systems that do not have tzset() but supply this function using another
+   name (_tzset() or something similar), an appropiate "#define tzset ..."
+   should be added to the system specifc configuration section.  */
+#if (!defined(T20_VMS) && !defined(MACOS) && !defined(RISCOS) && !defined(QDOS))
+#if (!defined(BSD) && !defined(MTS) && !defined(CMS_MVS) && !defined(TANDEM))
+    tzset();
+#endif
+#endif
+
+/*---------------------------------------------------------------------------
+    Match (possible) wildcard zipfile specification with existing files and
+    attempt to process each.  If no hits, try again after appending ".zip"
+    suffix.  If still no luck, give up.
+  ---------------------------------------------------------------------------*/
+
+#ifdef SFX
+    if ((error = do_seekable(__G__ 0)) == PK_NOZIP) {
+#ifdef EXE_EXTENSION
+        int len=strlen(G.argv0);
+
+        /* append .exe if appropriate; also .sfx? */
+        if ( (G.zipfn = (char *)malloc(len+sizeof(EXE_EXTENSION))) !=
+             (char *)NULL ) {
+            strcpy(G.zipfn, G.argv0);
+            strcpy(G.zipfn+len, EXE_EXTENSION);
+            error = do_seekable(__G__ 0);
+            free(G.zipfn);
+            G.zipfn = G.argv0;  /* for "cannot find myself" message only */
+        }
+#endif /* EXE_EXTENSION */
+#ifdef WIN32
+        G.zipfn = G.argv0;  /* for "cannot find myself" message only */
+#endif
+    }
+    if (error) {
+        if (error == IZ_DIR)
+            error_in_archive = PK_NOZIP;
+        else
+            error_in_archive = error;
+        if (error == PK_NOZIP)
+            Info(slide, 1, ((char *)slide, LoadFarString(CannotFindMyself),
+              G.zipfn));
+    }
+
+#else /* !SFX */
+    NumWinFiles = NumLoseFiles = NumWarnFiles = 0;
+    current_file = NumMissDirs = NumMissFiles = 0;
+
+    while ((G.zipfn = do_wild(__G__ G.wildzipfn)) != (char *)NULL) {
+        Trace((stderr, "do_wild( %s ) returns %s\n", G.wildzipfn, G.zipfn));
+
+        lastzipfn = G.zipfn;
+
+        /* print a blank line between the output of different zipfiles */
+        if (!uO.qflag  &&  error != PK_NOZIP  &&  error != IZ_DIR
+#ifdef TIMESTAMP
+            && (!uO.T_flag || uO.zipinfo_mode)
+#endif
+            && (NumWinFiles+NumLoseFiles+NumWarnFiles+NumMissFiles) > 0)
+            (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
+
+        if ((error = do_seekable(__G__ 0)) == PK_WARN)
+            ++NumWarnFiles;
+        else if (error == IZ_DIR)
+            ++NumMissDirs;
+        else if (error == PK_NOZIP)
+            ++NumMissFiles;
+        else if (error)
+            ++NumLoseFiles;
+        else
+			++NumWinFiles;
+
+		current_file = NumWinFiles;
+
+		if(installstate == INSTALLING)
+			DoGUI();
+
+        if (error != IZ_DIR && error > error_in_archive)
+            error_in_archive = error;
+        Trace((stderr, "do_seekable(0) returns %d\n", error));
+#ifdef WINDLL
+        if (error == IZ_CTRLC) {
+            free_G_buffers(__G);
+            return error;
+        }
+#endif
+
+    } /* end while-loop (wildcard zipfiles) */
+
+    if ((NumWinFiles + NumWarnFiles + NumLoseFiles) == 0  &&
+        (NumMissDirs + NumMissFiles) == 1  &&  lastzipfn != (char *)NULL)
+    {
+        NumMissDirs = NumMissFiles = 0;
+        if (error_in_archive == PK_NOZIP)
+            error_in_archive = PK_COOL;
+
+#if (!defined(UNIX) && !defined(AMIGA)) /* filenames with wildcard characters */
+        if (iswild(G.wildzipfn))
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(CannotFindWildcardMatch), uO.zipinfo_mode?
+              LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
+              G.wildzipfn));
+        else
+#endif
+        {
+            char *p = lastzipfn + strlen(lastzipfn);
+
+            G.zipfn = lastzipfn;
+            strcpy(p, ZSUFX);
+
+#if defined(UNIX) || defined(QDOS)
+   /* only Unix has case-sensitive filesystems */
+   /* Well FlexOS (sometimes) also has them,  but support is per media */
+   /* and a pig to code for,  so treat as case insensitive for now */
+   /* we do this under QDOS to check for .zip as well as _zip */
+            if ((error = do_seekable(__G__ 0)) == PK_NOZIP || error == IZ_DIR) {
+                if (error == IZ_DIR)
+                    ++NumMissDirs;
+                strcpy(p, ALT_ZSUFX);
+                error = do_seekable(__G__ 1);
+            }
+#else
+            error = do_seekable(__G__ 1);
+#endif
+            if (error == PK_WARN)   /* GRR: make this a switch/case stmt ... */
+                ++NumWarnFiles;
+            else if (error == IZ_DIR)
+                ++NumMissDirs;
+            else if (error == PK_NOZIP)
+                /* increment again => bug: "1 file had no zipfile directory." */
+                /* ++NumMissFiles */ ;
+            else if (error)
+                ++NumLoseFiles;
+            else
+                ++NumWinFiles;
+
+            if (error > error_in_archive)
+                error_in_archive = error;
+            Trace((stderr, "do_seekable(1) returns %d\n", error));
+#ifdef WINDLL
+            if (error == IZ_CTRLC) {
+                free_G_buffers(__G);
+                return error;
+            }
+#endif
+        }
+    }
+#endif /* ?SFX */
+
+/*---------------------------------------------------------------------------
+    Print summary of all zipfiles, assuming zipfile spec was a wildcard (no
+    need for a summary if just one zipfile).
+  ---------------------------------------------------------------------------*/
+
+#ifndef SFX
+    if (iswild(G.wildzipfn) && uO.qflag < 3
+#ifdef TIMESTAMP
+        && !(uO.T_flag && uO.qflag && !uO.zipinfo_mode)
+#endif
+                                                    )
+    {
+        if ((NumMissFiles + NumLoseFiles + NumWarnFiles > 0 || NumWinFiles != 1)
+#ifdef TIMESTAMP
+            && !(uO.T_flag && !uO.zipinfo_mode)
+#endif
+            && !(uO.tflag && uO.qflag > 1))
+            (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0x401);
+        if ((NumWinFiles > 1) || (NumWinFiles == 1 &&
+            NumMissDirs + NumMissFiles + NumLoseFiles + NumWarnFiles > 0))
+            Info(slide, 0x401, ((char *)slide, LoadFarString(FilesProcessOK),
+              NumWinFiles, (NumWinFiles == 1)? " was" : "s were"));
+        if (NumWarnFiles > 0)
+            Info(slide, 0x401, ((char *)slide, LoadFarString(ArchiveWarning),
+              NumWarnFiles, (NumWarnFiles == 1)? "" : "s"));
+        if (NumLoseFiles > 0)
+            Info(slide, 0x401, ((char *)slide, LoadFarString(ArchiveFatalError),
+              NumLoseFiles, (NumLoseFiles == 1)? "" : "s"));
+        if (NumMissFiles > 0)
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(FileHadNoZipfileDir), NumMissFiles,
+              (NumMissFiles == 1)? "" : "s"));
+        if (NumMissDirs == 1)
+            Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileWasDir)));
+        else if (NumMissDirs > 0)
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(ManyZipfilesWereDir), NumMissDirs));
+        if (NumWinFiles + NumLoseFiles + NumWarnFiles == 0)
+            Info(slide, 0x401, ((char *)slide, LoadFarString(NoZipfileFound)));
+    }
+#endif /* !SFX */
+
+    /* free allocated memory */
+    free_G_buffers(__G);
+
+    return error_in_archive;
+
+} /* end function process_zipfiles() */
+
+
+
+
+
+/*****************************/
+/* Function free_G_buffers() */
+/*****************************/
+
+void free_G_buffers(__G)     /* releases all memory allocated in global vars */
+    __GDEF
+{
+    inflate_free(__G);
+    checkdir(__G__ (char *)NULL, END);
+
+#ifdef DYNALLOC_CRCTAB
+    if (CRC_32_TAB) {
+        free_crc_table();
+        CRC_32_TAB = NULL;
+    }
+#endif
+
+   if (G.key != (char *)NULL) {
+        free(G.key);
+        G.key = (char *)NULL;
+   }
+
+#if (!defined(VMS) && !defined(SMALL_MEM))
+    /* VMS uses its own buffer scheme for textmode flush() */
+    if (G.outbuf2) {
+        free(G.outbuf2);   /* malloc'd ONLY if unshrink and -a */
+        G.outbuf2 = (uch *)NULL;
+    }
+#endif
+
+    if (G.outbuf)
+        free(G.outbuf);
+    if (G.inbuf)
+        free(G.inbuf);
+    G.inbuf = G.outbuf = (uch *)NULL;
+
+#ifdef MALLOC_WORK
+    if (G.area.Slide) {
+        free(G.area.Slide);
+        G.area.Slide = (uch *)NULL;
+    }
+#endif
+
+} /* end function free_G_buffers() */
+
+
+
+
+
+/**************************/
+/* Function do_seekable() */
+/**************************/
+
+static int do_seekable(__G__ lastchance)        /* return PK-type error code */
+    __GDEF
+    int lastchance;
+{
+#ifndef SFX
+    /* static int no_ecrec = FALSE;  SKM: moved to globals.h */
+    int maybe_exe=FALSE;
+    int too_weird_to_continue=FALSE;
+#ifdef TIMESTAMP
+    time_t uxstamp;
+    unsigned nmember = 0;
+#endif
+#endif
+    int error=0, error_in_archive;
+
+
+/*---------------------------------------------------------------------------
+    Open the zipfile for reading in BINARY mode to prevent CR/LF translation,
+    which would corrupt the bit streams.
+  ---------------------------------------------------------------------------*/
+
+#if 0
+    if (SSTAT(G.zipfn, &G.statbuf) ||
+        (error = S_ISDIR(G.statbuf.st_mode)) != 0)
+    {
+#ifndef SFX
+        if (lastchance) {
+#if defined(UNIX) || defined(QDOS)
+            if (G.no_ecrec)
+                Info(slide, 1, ((char *)slide,
+                  LoadFarString(CannotFindZipfileDirMsg), uO.zipinfo_mode?
+                  LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
+                  G.wildzipfn, uO.zipinfo_mode? "  " : "", G.wildzipfn,
+                  G.zipfn));
+            else
+                Info(slide, 1, ((char *)slide,
+                  LoadFarString(CannotFindEitherZipfile), uO.zipinfo_mode?
+                  LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
+                  G.wildzipfn, G.wildzipfn, G.zipfn));
+#else /* !UNIX */
+            if (G.no_ecrec)
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(CannotFindZipfileDirMsg), uO.zipinfo_mode?
+                  LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
+                  G.wildzipfn, uO.zipinfo_mode? "  " : "", G.zipfn));
+            else
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(CannotFindEitherZipfile), uO.zipinfo_mode?
+                  LoadFarStringSmall(Zipnfo) : LoadFarStringSmall(Unzip),
+                  G.wildzipfn, G.zipfn));
+#endif /* ?UNIX */
+        }
+#endif /* !SFX */
+        return error? IZ_DIR : PK_NOZIP;
+	}
+    G.ziplen = G.statbuf.st_size;
+#endif
+	G.ziplen = acesize();
+
+#ifndef SFX
+#if defined(UNIX) || defined(DOS_OS2_W32)
+    if (G.statbuf.st_mode & S_IEXEC)   /* no extension on Unix exes:  might */
+        maybe_exe = TRUE;               /*  find unzip, not unzip.zip; etc. */
+#endif
+#endif /* !SFX */
+
+#ifdef VMS
+    if (check_format(__G))              /* check for variable-length format */
+        return PK_ERR;
+#endif
+
+    if (open_input_file(__G))   /* this should never happen, given */
+        return PK_NOZIP;        /*  the stat() test above, but... */
+
+/*---------------------------------------------------------------------------
+    Find and process the end-of-central-directory header.  UnZip need only
+    check last 65557 bytes of zipfile:  comment may be up to 65535, end-of-
+    central-directory record is 18 bytes, and signature itself is 4 bytes;
+    add some to allow for appended garbage.  Since ZipInfo is often used as
+    a debugging tool, search the whole zipfile if zipinfo_mode is true.
+  ---------------------------------------------------------------------------*/
+
+    /* initialize the CRC table pointer (once) */
+    if (CRC_32_TAB == NULL) {
+        if ((CRC_32_TAB = get_crc_table()) == NULL)
+            return PK_MEM;
+    }
+
+#if (!defined(SFX) || defined(SFX_EXDIR))
+    /* check out if specified extraction root directory exists */
+    if (uO.exdir != (char *)NULL && G.extract_flag) {
+        G.create_dirs = !uO.fflag;
+        if ((error = checkdir(__G__ uO.exdir, ROOT)) > 2)
+            return error;   /* out of memory, or file in way */
+    }
+#endif /* !SFX || SFX_EXDIR */
+
+    G.cur_zipfile_bufstart = 0;
+    G.inptr = G.inbuf;
+
+#if (!defined(WINDLL) && !defined(SFX))
+#ifdef TIMESTAMP
+    if (!uO.zipinfo_mode && !uO.qflag && !uO.T_flag)
+#else
+    if (!uO.zipinfo_mode && !uO.qflag)
+#endif
+#ifdef WIN32    /* Win32 console may require codepage conversion for G.zipfn */
+        Info(slide, 0, ((char *)slide, "Archive:  %s\n", FnFilter1(G.zipfn)));
+#else
+        Info(slide, 0, ((char *)slide, "Archive:  %s\n", G.zipfn));
+#endif
+#endif /* !WINDLL && !SFX */
+
+    if ((
+#ifndef NO_ZIPINFO
+         uO.zipinfo_mode &&
+          ((error_in_archive = find_ecrec(__G__ G.ziplen)) != 0 ||
+          (error_in_archive = zi_end_central(__G)) > PK_WARN))
+        || (!uO.zipinfo_mode &&
+#endif
+          ((error_in_archive = find_ecrec(__G__ MIN(G.ziplen,66000L))) != 0 ||
+          (error_in_archive = uz_end_central(__G)) > PK_WARN)))
+    {
+        CLOSE_INFILE();
+
+#ifdef SFX
+        ++lastchance;   /* avoid picky compiler warnings */
+        return error_in_archive;
+#else
+        if (maybe_exe)
+            Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeExe),
+            G.zipfn));
+        if (lastchance)
+            return error_in_archive;
+        else {
+            G.no_ecrec = TRUE;    /* assume we found wrong file:  e.g., */
+            return PK_NOZIP;       /*  unzip instead of unzip.zip */
+        }
+#endif /* ?SFX */
+    }
+
+    if ((uO.zflag > 0) && !uO.zipinfo_mode) { /* unzip: zflag = comment ONLY */
+        CLOSE_INFILE();
+        return error_in_archive;
+    }
+
+/*---------------------------------------------------------------------------
+    Test the end-of-central-directory info for incompatibilities (multi-disk
+    archives) or inconsistencies (missing or extra bytes in zipfile).
+  ---------------------------------------------------------------------------*/
+
+#ifdef NO_MULTIPART
+    error = !uO.zipinfo_mode && (G.ecrec.number_this_disk == 1) &&
+            (G.ecrec.num_disk_start_cdir == 1);
+#else
+    error = !uO.zipinfo_mode && (G.ecrec.number_this_disk != 0);
+#endif
+
+#ifndef SFX
+    if (uO.zipinfo_mode &&
+        G.ecrec.number_this_disk != G.ecrec.num_disk_start_cdir)
+    {
+        if (G.ecrec.number_this_disk > G.ecrec.num_disk_start_cdir) {
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(CentDirNotInZipMsg), G.zipfn,
+              G.ecrec.number_this_disk, G.ecrec.num_disk_start_cdir));
+            error_in_archive = PK_FIND;
+            too_weird_to_continue = TRUE;
+        } else {
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(EndCentDirBogus), G.zipfn,
+              G.ecrec.number_this_disk, G.ecrec.num_disk_start_cdir));
+            error_in_archive = PK_WARN;
+        }
+#ifdef NO_MULTIPART   /* concatenation of multiple parts works in some cases */
+    } else if (!uO.zipinfo_mode && !error && G.ecrec.number_this_disk != 0) {
+        Info(slide, 0x401, ((char *)slide, LoadFarString(NoMultiDiskArcSupport),
+          G.zipfn));
+        error_in_archive = PK_FIND;
+        too_weird_to_continue = TRUE;
+#endif
+    }
+
+    if (!too_weird_to_continue) {  /* (relatively) normal zipfile:  go for it */
+        if (error) {
+            Info(slide, 0x401, ((char *)slide, LoadFarString(MaybePakBug),
+              G.zipfn));
+            error_in_archive = PK_WARN;
+        }
+#endif /* !SFX */
+        if ((G.extra_bytes = G.real_ecrec_offset-G.expect_ecrec_offset) <
+            (LONGINT)0)
+        {
+            Info(slide, 0x401, ((char *)slide, LoadFarString(MissingBytes),
+              G.zipfn, (long)(-G.extra_bytes)));
+            error_in_archive = PK_ERR;
+        } else if (G.extra_bytes > 0) {
+            if ((G.ecrec.offset_start_central_directory == 0) &&
+                (G.ecrec.size_central_directory != 0))   /* zip 1.5 -go bug */
+            {
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(NullCentDirOffset), G.zipfn));
+                G.ecrec.offset_start_central_directory = G.extra_bytes;
+                G.extra_bytes = 0;
+                error_in_archive = PK_ERR;
+            }
+#ifndef SFX
+            else {
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(ExtraBytesAtStart), G.zipfn,
+                  (long)G.extra_bytes, (G.extra_bytes == 1)? "":"s"));
+                error_in_archive = PK_WARN;
+            }
+#endif /* !SFX */
+        }
+
+    /*-----------------------------------------------------------------------
+        Check for empty zipfile and exit now if so.
+      -----------------------------------------------------------------------*/
+
+        if (G.expect_ecrec_offset==0L && G.ecrec.size_central_directory==0) {
+            if (uO.zipinfo_mode)
+                Info(slide, 0, ((char *)slide, "%sEmpty zipfile.\n",
+                  uO.lflag>9? "\n  " : ""));
+            else
+                Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileEmpty),
+                                    G.zipfn));
+            CLOSE_INFILE();
+            return (error_in_archive > PK_WARN)? error_in_archive : PK_WARN;
+        }
+
+    /*-----------------------------------------------------------------------
+        Compensate for missing or extra bytes, and seek to where the start
+        of central directory should be.  If header not found, uncompensate
+        and try again (necessary for at least some Atari archives created
+        with STZip, as well as archives created by J.H. Holm's ZIPSPLIT 1.1).
+      -----------------------------------------------------------------------*/
+
+        ZLSEEK( G.ecrec.offset_start_central_directory )
+#ifdef OLD_SEEK_TEST
+        if (readbuf(G.sig, 4) == 0) {
+            CLOSE_INFILE();
+            return PK_ERR;  /* file may be locked, or possibly disk error(?) */
+        }
+        if (strncmp(G.sig, central_hdr_sig, 4))
+#else
+        if ((readbuf(__G__ G.sig, 4) == 0) ||
+             strncmp(G.sig, central_hdr_sig, 4))
+#endif
+        {
+#ifndef SFX
+            long tmp = G.extra_bytes;
+#endif
+
+            G.extra_bytes = 0;
+            ZLSEEK( G.ecrec.offset_start_central_directory )
+            if ((readbuf(__G__ G.sig, 4) == 0) ||
+                strncmp(G.sig, central_hdr_sig, 4))
+            {
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(CentDirStartNotFound), G.zipfn,
+                  LoadFarStringSmall(ReportMsg)));
+                CLOSE_INFILE();
+                return PK_BADERR;
+            }
+#ifndef SFX
+            Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirTooLong),
+              G.zipfn, -tmp));
+#endif
+            error_in_archive = PK_ERR;
+        }
+
+    /*-----------------------------------------------------------------------
+        Seek to the start of the central directory one last time, since we
+        have just read the first entry's signature bytes; then list, extract
+        or test member files as instructed, and close the zipfile.
+      -----------------------------------------------------------------------*/
+
+        Trace((stderr, "about to extract/list files (error = %d)\n",
+          error_in_archive));
+
+        ZLSEEK( G.ecrec.offset_start_central_directory )
+
+#ifdef DLL
+        /* G.fValidate is used only to look at an archive to see if
+           it appears to be a valid archive.  There is no interest
+           in what the archive contains, nor in validating that the
+           entries in the archive are in good condition.  This is
+           currently used only in the Windows DLLs for purposes of
+           checking archives within an archive to determine whether
+           or not to display the inner archives.
+         */
+        if (!G.fValidate)
+#endif
+        {
+#ifndef NO_ZIPINFO
+            if (uO.zipinfo_mode)
+                error = zipinfo(__G);                     /* ZIPINFO 'EM */
+            else
+#endif
+#ifndef SFX
+#ifdef TIMESTAMP
+            if (uO.T_flag)
+                error = get_time_stamp(__G__ &uxstamp, &nmember);
+            else
+#endif
+            if (uO.vflag && !uO.tflag && !uO.cflag)
+                error = list_files(__G);              /* LIST 'EM */
+            else
+#endif /* !SFX */
+                error = extract_or_test_files(__G);   /* EXTRACT OR TEST 'EM */
+
+            Trace((stderr, "done with extract/list files (error = %d)\n",
+                   error));
+        }
+
+        if (error > error_in_archive)   /* don't overwrite stronger error */
+            error_in_archive = error;   /*  with (for example) a warning */
+#ifndef SFX
+    } /* end if (!too_weird_to_continue) */
+#endif
+
+    CLOSE_INFILE();
+
+#ifdef TIMESTAMP
+    if (uO.T_flag && !uO.zipinfo_mode && (nmember > 0)) {
+# ifdef WIN32
+        if (stamp_file(__G__ G.zipfn, uxstamp)) {       /* TIME-STAMP 'EM */
+# else
+        if (stamp_file(G.zipfn, uxstamp)) {             /* TIME-STAMP 'EM */
+# endif
+            Info(slide, 0x201, ((char *)slide,
+              "warning:  cannot set time for %s\n", G.zipfn));
+            if (error_in_archive < PK_WARN)
+                error_in_archive = PK_WARN;
+        }
+    }
+#endif
+    return error_in_archive;
+
+} /* end function do_seekable() */
+
+
+
+
+
+/*************************/
+/* Function find_ecrec() */
+/*************************/
+
+static int find_ecrec(__G__ searchlen)          /* return PK-class error */
+    __GDEF
+    long searchlen;
+{
+    int i, numblks, found=FALSE;
+    LONGINT tail_len;
+    ec_byte_rec byterec;
+
+
+/*---------------------------------------------------------------------------
+    Treat case of short zipfile separately.
+  ---------------------------------------------------------------------------*/
+
+    if (G.ziplen <= INBUFSIZ) {
+        acelseek(0L, SEEK_SET);
+        if ((G.incnt = aceread((char *)G.inbuf,(unsigned int)G.ziplen))
+            == (int)G.ziplen)
+
+            /* 'P' must be at least 22 bytes from end of zipfile */
+            for (G.inptr = G.inbuf+(int)G.ziplen-22;  G.inptr >= G.inbuf;
+                 --G.inptr)
+                if ((native(*G.inptr) == 'P')  &&
+                     !strncmp((char *)G.inptr, end_central_sig, 4)) {
+                    G.incnt -= (int)(G.inptr - G.inbuf);
+                    found = TRUE;
+                    break;
+                }
+
+/*---------------------------------------------------------------------------
+    Zipfile is longer than INBUFSIZ:  may need to loop.  Start with short
+    block at end of zipfile (if not TOO short).
+  ---------------------------------------------------------------------------*/
+
+    } else {
+        if ((tail_len = G.ziplen % INBUFSIZ) > ECREC_SIZE) {
+#ifdef USE_STRM_INPUT
+            fseek((FILE *)G.zipfd, G.ziplen-tail_len, SEEK_SET);
+            G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd);
+#else /* !USE_STRM_INPUT */
+            G.cur_zipfile_bufstart = acelseek(G.ziplen-tail_len,
+              SEEK_SET);
+#endif /* ?USE_STRM_INPUT */
+            if ((G.incnt = aceread((char *)G.inbuf,
+                (unsigned int)tail_len)) != (int)tail_len)
+                goto fail;      /* it's expedient... */
+
+            /* 'P' must be at least 22 bytes from end of zipfile */
+            for (G.inptr = G.inbuf+(int)tail_len-22;  G.inptr >= G.inbuf;
+                 --G.inptr)
+                if ((native(*G.inptr) == 'P')  &&
+                     !strncmp((char *)G.inptr, end_central_sig, 4)) {
+                    G.incnt -= (int)(G.inptr - G.inbuf);
+                    found = TRUE;
+                    break;
+                }
+            /* sig may span block boundary: */
+            strncpy((char *)G.hold, (char *)G.inbuf, 3);
+        } else
+            G.cur_zipfile_bufstart = G.ziplen - tail_len;
+
+    /*-----------------------------------------------------------------------
+        Loop through blocks of zipfile data, starting at the end and going
+        toward the beginning.  In general, need not check whole zipfile for
+        signature, but may want to do so if testing.
+      -----------------------------------------------------------------------*/
+
+        numblks = (int)((searchlen - tail_len + (INBUFSIZ-1)) / INBUFSIZ);
+        /*               ==amount=   ==done==   ==rounding==    =blksiz=  */
+
+        for (i = 1;  !found && (i <= numblks);  ++i) {
+            G.cur_zipfile_bufstart -= INBUFSIZ;
+            acelseek(G.cur_zipfile_bufstart, SEEK_SET);
+            if ((G.incnt = aceread((char *)G.inbuf,INBUFSIZ))
+                != INBUFSIZ)
+                break;          /* fall through and fail */
+
+            for (G.inptr = G.inbuf+INBUFSIZ-1;  G.inptr >= G.inbuf;
+                 --G.inptr)
+                if ((native(*G.inptr) == 'P')  &&
+                     !strncmp((char *)G.inptr, end_central_sig, 4)) {
+                    G.incnt -= (int)(G.inptr - G.inbuf);
+                    found = TRUE;
+                    break;
+                }
+            /* sig may span block boundary: */
+            strncpy((char *)G.hold, (char *)G.inbuf, 3);
+        }
+    } /* end if (ziplen > INBUFSIZ) */
+
+/*---------------------------------------------------------------------------
+    Searched through whole region where signature should be without finding
+    it.  Print informational message and die a horrible death.
+  ---------------------------------------------------------------------------*/
+
+fail:
+    if (!found) {
+        if (uO.qflag || uO.zipinfo_mode)
+            Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn));
+        Info(slide, 0x401, ((char *)slide,
+          LoadFarString(CentDirEndSigNotFound)));
+        return PK_ERR;   /* failed */
+    }
+
+/*---------------------------------------------------------------------------
+    Found the signature, so get the end-central data before returning.  Do
+    any necessary machine-type conversions (byte ordering, structure padding
+    compensation) by reading data into character array and copying to struct.
+  ---------------------------------------------------------------------------*/
+
+    G.real_ecrec_offset = G.cur_zipfile_bufstart + (G.inptr-G.inbuf);
+#ifdef TEST
+    pipeit("\n  found end-of-central-dir signature at offset %ld (%.8lXh)\n",
+      G.real_ecrec_offset, G.real_ecrec_offset);
+    pipeit("    from beginning of file; offset %d (%.4Xh) within block\n",
+      G.inptr-G.inbuf, G.inptr-G.inbuf);
+#endif
+
+    if (readbuf(__G__ (char *)byterec, ECREC_SIZE+4) == 0)
+        return PK_EOF;
+
+    G.ecrec.number_this_disk =
+      makeword(&byterec[NUMBER_THIS_DISK]);
+    G.ecrec.num_disk_start_cdir =
+      makeword(&byterec[NUM_DISK_WITH_START_CENTRAL_DIR]);
+    G.ecrec.num_entries_centrl_dir_ths_disk =
+      makeword(&byterec[NUM_ENTRIES_CENTRL_DIR_THS_DISK]);
+    G.ecrec.total_entries_central_dir =
+      makeword(&byterec[TOTAL_ENTRIES_CENTRAL_DIR]);
+    G.ecrec.size_central_directory =
+      makelong(&byterec[SIZE_CENTRAL_DIRECTORY]);
+    G.ecrec.offset_start_central_directory =
+      makelong(&byterec[OFFSET_START_CENTRAL_DIRECTORY]);
+    G.ecrec.zipfile_comment_length =
+      makeword(&byterec[ZIPFILE_COMMENT_LENGTH]);
+
+    G.expect_ecrec_offset = G.ecrec.offset_start_central_directory +
+                          G.ecrec.size_central_directory;
+    return PK_COOL;
+
+} /* end function find_ecrec() */
+
+
+
+
+
+/*****************************/
+/* Function uz_end_central() */
+/*****************************/
+
+int uz_end_central(__G)    /* return PK-type error code */
+    __GDEF
+{
+    int error = PK_COOL;
+
+
+/*---------------------------------------------------------------------------
+    Get the zipfile comment (up to 64KB long), if any, and print it out.
+    Then position the file pointer to the beginning of the central directory
+    and fill buffer.
+  ---------------------------------------------------------------------------*/
+
+#ifdef WINDLL
+    /* for comment button: */
+    if ((!G.fValidate) && (G.lpUserFunctions != NULL))
+       G.lpUserFunctions->cchComment = G.ecrec.zipfile_comment_length;
+    if (G.ecrec.zipfile_comment_length && (uO.zflag > 0))
+#else /* !WINDLL */
+    if (G.ecrec.zipfile_comment_length && (uO.zflag > 0 ||
+        (uO.zflag == 0 &&
+#ifdef TIMESTAMP
+                          !uO.T_flag &&
+#endif
+                                        !uO.qflag)))
+#endif /* ?WINDLL */
+    {
+        if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) {
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(ZipfileCommTrunc1)));
+            error = PK_WARN;
+        }
+    }
+    return error;
+
+} /* end function uz_end_central() */
+
+
+
+
+
+/************************************/
+/* Function process_cdir_file_hdr() */
+/************************************/
+
+int process_cdir_file_hdr(__G)    /* return PK-type error code */
+    __GDEF
+{
+    int error;
+
+
+/*---------------------------------------------------------------------------
+    Get central directory info, save host and method numbers, and set flag
+    for lowercase conversion of filename, depending on the OS from which the
+    file is coming.
+  ---------------------------------------------------------------------------*/
+
+    if ((error = get_cdir_ent(__G)) != 0)
+        return error;
+
+    G.pInfo->hostnum = MIN(G.crec.version_made_by[1], NUM_HOSTS);
+/*  extnum = MIN(crec.version_needed_to_extract[1], NUM_HOSTS); */
+
+    G.pInfo->lcflag = 0;
+    if (uO.L_flag)            /* user specified case-conversion */
+        switch (G.pInfo->hostnum) {
+            case FS_FAT_:     /* PKZIP and zip -k store in uppercase */
+            case CPM_:        /* like MS-DOS, right? */
+            case VM_CMS_:     /* all caps? */
+            case MVS_:        /* all caps? */
+            case TANDEM_:
+            case TOPS20_:
+            case VMS_:        /* our Zip uses lowercase, but ASi's doesn't */
+        /*  case Z_SYSTEM_:   ? */
+        /*  case QDOS_:       ? */
+                G.pInfo->lcflag = 1;   /* convert filename to lowercase */
+                break;
+
+            default:     /* AMIGA_, FS_HPFS_, FS_NTFS_, MAC_, UNIX_, ATARI_, */
+                break;   /*  FS_VFAT_, BEOS_ (Z_SYSTEM_):  no conversion */
+        }
+
+    /* do Amigas (AMIGA_) also have volume labels? */
+    if (IS_VOLID(G.crec.external_file_attributes) &&
+        (G.pInfo->hostnum == FS_FAT_ || G.pInfo->hostnum == FS_HPFS_ ||
+         G.pInfo->hostnum == FS_NTFS_ || G.pInfo->hostnum == ATARI_))
+    {
+        G.pInfo->vollabel = TRUE;
+        G.pInfo->lcflag = 0;        /* preserve case of volume labels */
+    } else
+        G.pInfo->vollabel = FALSE;
+
+    return PK_COOL;
+
+} /* end function process_cdir_file_hdr() */
+
+
+
+
+
+/***************************/
+/* Function get_cdir_ent() */
+/***************************/
+
+int get_cdir_ent(__G)   /* return PK-type error code */
+    __GDEF
+{
+    cdir_byte_hdr byterec;
+
+
+/*---------------------------------------------------------------------------
+    Read the next central directory entry and do any necessary machine-type
+    conversions (byte ordering, structure padding compensation--do so by
+    copying the data from the array into which it was read (byterec) to the
+    usable struct (crec)).
+  ---------------------------------------------------------------------------*/
+
+    if (readbuf(__G__ (char *)byterec, CREC_SIZE) == 0)
+        return PK_EOF;
+
+    G.crec.version_made_by[0] = byterec[C_VERSION_MADE_BY_0];
+    G.crec.version_made_by[1] = byterec[C_VERSION_MADE_BY_1];
+    G.crec.version_needed_to_extract[0] =
+      byterec[C_VERSION_NEEDED_TO_EXTRACT_0];
+    G.crec.version_needed_to_extract[1] =
+      byterec[C_VERSION_NEEDED_TO_EXTRACT_1];
+
+    G.crec.general_purpose_bit_flag =
+      makeword(&byterec[C_GENERAL_PURPOSE_BIT_FLAG]);
+    G.crec.compression_method =
+      makeword(&byterec[C_COMPRESSION_METHOD]);
+    G.crec.last_mod_dos_datetime =
+      makelong(&byterec[C_LAST_MOD_DOS_DATETIME]);
+    G.crec.crc32 =
+      makelong(&byterec[C_CRC32]);
+    G.crec.csize =
+      makelong(&byterec[C_COMPRESSED_SIZE]);
+    G.crec.ucsize =
+      makelong(&byterec[C_UNCOMPRESSED_SIZE]);
+    G.crec.filename_length =
+      makeword(&byterec[C_FILENAME_LENGTH]);
+    G.crec.extra_field_length =
+      makeword(&byterec[C_EXTRA_FIELD_LENGTH]);
+    G.crec.file_comment_length =
+      makeword(&byterec[C_FILE_COMMENT_LENGTH]);
+    G.crec.disk_number_start =
+      makeword(&byterec[C_DISK_NUMBER_START]);
+    G.crec.internal_file_attributes =
+      makeword(&byterec[C_INTERNAL_FILE_ATTRIBUTES]);
+    G.crec.external_file_attributes =
+      makelong(&byterec[C_EXTERNAL_FILE_ATTRIBUTES]);  /* LONG, not word! */
+    G.crec.relative_offset_local_header =
+      makelong(&byterec[C_RELATIVE_OFFSET_LOCAL_HEADER]);
+
+    return PK_COOL;
+
+} /* end function get_cdir_ent() */
+
+
+
+
+
+/*************************************/
+/* Function process_local_file_hdr() */
+/*************************************/
+
+int process_local_file_hdr(__G)    /* return PK-type error code */
+    __GDEF
+{
+    local_byte_hdr byterec;
+
+
+/*---------------------------------------------------------------------------
+    Read the next local file header and do any necessary machine-type con-
+    versions (byte ordering, structure padding compensation--do so by copy-
+    ing the data from the array into which it was read (byterec) to the
+    usable struct (lrec)).
+  ---------------------------------------------------------------------------*/
+
+    if (readbuf(__G__ (char *)byterec, LREC_SIZE) == 0)
+        return PK_EOF;
+
+    G.lrec.version_needed_to_extract[0] =
+      byterec[L_VERSION_NEEDED_TO_EXTRACT_0];
+    G.lrec.version_needed_to_extract[1] =
+      byterec[L_VERSION_NEEDED_TO_EXTRACT_1];
+
+    G.lrec.general_purpose_bit_flag =
+      makeword(&byterec[L_GENERAL_PURPOSE_BIT_FLAG]);
+    G.lrec.compression_method = makeword(&byterec[L_COMPRESSION_METHOD]);
+    G.lrec.last_mod_dos_datetime = makelong(&byterec[L_LAST_MOD_DOS_DATETIME]);
+    G.lrec.crc32 = makelong(&byterec[L_CRC32]);
+    G.lrec.csize = makelong(&byterec[L_COMPRESSED_SIZE]);
+    G.lrec.ucsize = makelong(&byterec[L_UNCOMPRESSED_SIZE]);
+    G.lrec.filename_length = makeword(&byterec[L_FILENAME_LENGTH]);
+    G.lrec.extra_field_length = makeword(&byterec[L_EXTRA_FIELD_LENGTH]);
+
+    G.csize = (long) G.lrec.csize;
+    G.ucsize = (long) G.lrec.ucsize;
+
+    if ((G.lrec.general_purpose_bit_flag & 8) != 0) {
+        /* can't trust local header, use central directory: */
+        G.lrec.crc32 = G.pInfo->crc;
+        G.csize = (long)(G.lrec.csize = G.pInfo->compr_size);
+        G.ucsize = (long)(G.lrec.ucsize = G.pInfo->uncompr_size);
+    }
+
+    return PK_COOL;
+
+} /* end function process_local_file_hdr() */
+
+
+#ifdef USE_EF_UT_TIME
+
+/*******************************/
+/* Function ef_scan_for_izux() */
+/*******************************/
+
+unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos_mdatetime,
+                          z_utim, z_uidgid)
+    uch *ef_buf;        /* buffer containing extra field */
+    unsigned ef_len;    /* total length of extra field */
+    int ef_is_c;        /* flag indicating "is central extra field" */
+    ulg dos_mdatetime;  /* last_mod_file_date_time in DOS format */
+    iztimes *z_utim;    /* return storage: atime, mtime, ctime */
+    ush *z_uidgid;      /* return storage: uid and gid */
+{
+    unsigned flags = 0;
+    unsigned eb_id;
+    unsigned eb_len;
+    int have_new_type_eb = FALSE;
+    int ut_zip_unzip_compatible = FALSE;
+
+/*---------------------------------------------------------------------------
+    This function scans the extra field for EF_TIME, EF_IZUNIX2, EF_IZUNIX, or
+    EF_PKUNIX blocks containing Unix-style time_t (GMT) values for the entry's
+    access, creation, and modification time.
+    If a valid block is found, the time stamps are copied to the iztimes
+    structure (provided the z_utim pointer is not NULL).
+    If a IZUNIX2 block is found or the IZUNIX block contains UID/GID fields,
+    and the z_uidgid array pointer is valid (!= NULL), the owner info is
+    transfered as well.
+    The presence of an EF_TIME or EF_IZUNIX2 block results in ignoring all
+    data from probably present obsolete EF_IZUNIX blocks.
+    If multiple blocks of the same type are found, only the information from
+    the last block is used.
+    The return value is a combination of the EF_TIME Flags field with an
+    additional flag bit indicating the presence of valid UID/GID info,
+    or 0 in case of failure.
+  ---------------------------------------------------------------------------*/
+
+    if (ef_len == 0 || ef_buf == NULL || (z_utim == 0 && z_uidgid == NULL))
+        return 0;
+
+    TTrace((stderr,"\nef_scan_for_izux: scanning extra field of length %u\n",
+      ef_len));
+
+    while (ef_len >= EB_HEADSIZE) {
+        eb_id = makeword(EB_ID + ef_buf);
+        eb_len = makeword(EB_LEN + ef_buf);
+
+        if (eb_len > (ef_len - EB_HEADSIZE)) {
+            /* discovered some extra field inconsistency! */
+            TTrace((stderr,
+              "ef_scan_for_izux: block length %u > rest ef_size %u\n", eb_len,
+              ef_len - EB_HEADSIZE));
+            break;
+        }
+
+        switch (eb_id) {
+          case EF_TIME:
+            flags &= ~0x0ff;    /* ignore previous IZUNIX or EF_TIME fields */
+            have_new_type_eb = TRUE;
+            if ( eb_len >= EB_UT_MINLEN && z_utim != NULL) {
+                unsigned eb_idx = EB_UT_TIME1;
+                TTrace((stderr,"ef_scan_for_izux: found TIME extra field\n"));
+                flags |= (ef_buf[EB_HEADSIZE+EB_UT_FLAGS] & 0x0ff);
+                if ((flags & EB_UT_FL_MTIME)) {
+                    if ((eb_idx+4) <= eb_len) {
+                        z_utim->mtime = makelong((EB_HEADSIZE+eb_idx) + ef_buf);
+                        eb_idx += 4;
+                        TTrace((stderr,"  UT e.f. modification time = %ld\n",
+                                z_utim->mtime));
+
+                        if ((ulg)(z_utim->mtime) & (ulg)(0x80000000L)) {
+                            ut_zip_unzip_compatible =
+                              ((time_t)0x80000000L < (time_t)0L)
+                              ? (dos_mdatetime == DOSTIME_MINIMUM)
+                              : (dos_mdatetime >= DOSTIME_2038_01_18);
+                            if (!ut_zip_unzip_compatible) {
+                            /* UnZip interpretes mtime differently than Zip;
+                               without modtime: ignore complete UT field */
+                              flags &= ~0x0ff;  /* no time_t times available */
+                              TTrace((stderr,
+                                "  UT modtime range error; ignore e.f.!\n"));
+                              break;            /* stop scanning this field */
+                            }
+                        } else {
+                            /* cannot determine, safe assumption is FALSE */
+                            ut_zip_unzip_compatible = FALSE;
+                        }
+                    } else {
+                        flags &= ~EB_UT_FL_MTIME;
+                        TTrace((stderr,"  UT e.f. truncated; no modtime\n"));
+                    }
+                }
+                if (ef_is_c) {
+                    break;      /* central version of TIME field ends here */
+                }
+
+                if (flags & EB_UT_FL_ATIME) {
+                    if ((eb_idx+4) <= eb_len) {
+                        z_utim->atime = makelong((EB_HEADSIZE+eb_idx) + ef_buf);
+                        eb_idx += 4;
+                        TTrace((stderr,"  UT e.f. access time = %ld\n",
+                                z_utim->atime));
+                        if (((ulg)(z_utim->atime) & (ulg)(0x80000000L)) &&
+                            !ut_zip_unzip_compatible) {
+                            flags &= ~EB_UT_FL_ATIME;
+                            TTrace((stderr,
+                              "  UT access time range error: skip time!\n"));
+                        }
+                    } else {
+                        flags &= ~EB_UT_FL_ATIME;
+                    }
+                }
+                if (flags & EB_UT_FL_CTIME) {
+                    if ((eb_idx+4) <= eb_len) {
+                        z_utim->ctime = makelong((EB_HEADSIZE+eb_idx) + ef_buf);
+                        TTrace((stderr,"  UT e.f. creation time = %ld\n",
+                                z_utim->ctime));
+                        if (((ulg)(z_utim->ctime) & (ulg)(0x80000000L)) &&
+                            !ut_zip_unzip_compatible) {
+                            flags &= ~EB_UT_FL_CTIME;
+                            TTrace((stderr,
+                              "  UT creation time range error: skip time!\n"));
+                        }
+                    } else {
+                        flags &= ~EB_UT_FL_CTIME;
+                    }
+                }
+            }
+            break;
+
+          case EF_IZUNIX2:
+            if (!have_new_type_eb) {
+                flags &= ~0x0ff;        /* ignore any previous IZUNIX field */
+                have_new_type_eb = TRUE;
+            }
+            if (eb_len >= EB_UX2_MINLEN && z_uidgid != NULL) {
+                z_uidgid[0] = makeword((EB_HEADSIZE+EB_UX2_UID) + ef_buf);
+                z_uidgid[1] = makeword((EB_HEADSIZE+EB_UX2_GID) + ef_buf);
+                flags |= EB_UX2_VALID;   /* signal success */
+            }
+            break;
+
+          case EF_IZUNIX:
+          case EF_PKUNIX:       /* PKUNIX e.f. layout is identical to IZUNIX */
+            if (eb_len >= EB_UX_MINLEN) {
+                TTrace((stderr,"ef_scan_for_izux: found %s extra field\n",
+                        (eb_id == EF_IZUNIX ? "IZUNIX" : "PKUNIX")));
+                if (have_new_type_eb) {
+                    break;      /* Ignore IZUNIX extra field block ! */
+                }
+                if (z_utim != NULL) {
+                    z_utim->atime = makelong((EB_HEADSIZE+EB_UX_ATIME)+ef_buf);
+                    z_utim->mtime = makelong((EB_HEADSIZE+EB_UX_MTIME)+ef_buf);
+                    TTrace((stderr,"  Unix EF actime = %ld\n", z_utim->atime));
+                    TTrace((stderr,"  Unix EF modtime = %ld\n", z_utim->mtime));
+                    flags |= (EB_UT_FL_MTIME | EB_UT_FL_ATIME);
+                    if ((ulg)(z_utim->mtime) & (ulg)(0x80000000L)) {
+                        ut_zip_unzip_compatible =
+                          ((time_t)0x80000000L < (time_t)0L)
+                          ? (dos_mdatetime == DOSTIME_MINIMUM)
+                          : (dos_mdatetime >= DOSTIME_2038_01_18);
+                        if (!ut_zip_unzip_compatible) {
+                            /* UnZip interpretes mtime differently than Zip;
+                               without modtime: ignore complete UT field */
+                            flags &= ~0x0ff;    /* no time_t times available */
+                            TTrace((stderr,
+                                  "  UX modtime range error: ignore e.f.!\n"));
+                        }
+                    } else {
+                        /* cannot determine, safe assumption is FALSE */
+                        ut_zip_unzip_compatible = FALSE;
+                    }
+                    if ((ulg)(z_utim->atime) & (ulg)(0x80000000L) &&
+                        !ut_zip_unzip_compatible && (flags & 0x0ff)) {
+                        /* atime not in range of UnZip's time_t */
+                        flags &= ~EB_UT_FL_ATIME;
+                        TTrace((stderr,
+                                "  UX access time range error: skip time!\n"));
+                    }
+                }
+                if (eb_len >= EB_UX_FULLSIZE && z_uidgid != NULL) {
+                    z_uidgid[0] = makeword((EB_HEADSIZE+EB_UX_UID) + ef_buf);
+                    z_uidgid[1] = makeword((EB_HEADSIZE+EB_UX_GID) + ef_buf);
+                    flags |= EB_UX2_VALID;
+                }
+            }
+            break;
+
+          default:
+            break;
+        }
+
+        /* Skip this extra field block */
+        ef_buf += (eb_len + EB_HEADSIZE);
+        ef_len -= (eb_len + EB_HEADSIZE);
+    }
+
+    return flags;
+}
+
+#endif /* USE_EF_UT_TIME */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/rexxapi.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,886 @@
+/**********************************************************************
+*   REXXAPI.C                                                         *
+*                                                                     *
+*   This program adds a ZIP engine directly to the REXX language.     *
+*   The functions are:                                                *
+*       UZDropFuncs         -- Makes all functions in this package    *
+*                              unknown to REXX.                       *
+*       UZLoadFuncs         -- Makes all functions in this package    *
+*                              known to REXX so REXX programs may     *
+*                              call them.                             *
+*       UZFileTree          -- Searches for files matching a given    *
+*                              filespec, including files in           *
+*                              subdirectories.                        *
+*       UZUnZip             -- Unzip command-line entry point.        *
+*                              This is functionally equivalent to     *
+*                              using Unzip as an external program.    *
+*       UZUnZipToVar            -- Unzip one file to a variable       *
+*       UZUnZipToStem       -- Unzip files to a variable array        *
+*       UZVer               -- Returns the Unzip version number       *
+*                                                                     *
+**********************************************************************/
+/* Include files */
+
+#ifdef OS2DLL
+
+#define  INCL_DOS
+#define  INCL_DOSMEMMGR
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#define UNZIP_INTERNAL
+#include "../unzip.h"
+#include "../version.h"
+
+
+/*********************************************************************/
+/*  Various definitions used by various functions.                   */
+/*********************************************************************/
+
+RexxFunctionHandler UZDropFuncs;
+RexxFunctionHandler UZLoadFuncs;
+RexxFunctionHandler UZFileTree;
+RexxFunctionHandler UZUnZip;
+RexxFunctionHandler UZUnZipToVar;
+RexxFunctionHandler UZUnZipToStem;
+RexxFunctionHandler UZVer;
+RexxFunctionHandler UZAPIVer;
+
+
+int SetOutputVar(__GPRO__ const char *name);
+int SetOutputVarStem(__GPRO__ const char *name);
+int SetOutputVarLength(__GPRO);
+int WriteToVariable(__GPRO__ const char *name, char *buffer, int len);
+int PrintToSubVariable(__GPRO__ int idx, const char *format,...);
+int PrintToVariable(__GPRO__ const char *name, const char *format,...);
+int _PrintToVariable(__GPRO__ const char *name, const char *format, va_list arg_ptr);
+int TextSetNext(__GPRO__ char *format, int len, int all);
+
+#define EZRXSTRING(r,p)  {(r).strptr=(PCH)p;(r).strlength=(ULONG)strlen((r).strptr);}
+
+
+/*********************************************************************/
+/* RxFncTable                                                        */
+/*   Array of names of the UNZIPAPI functions.                       */
+/*   This list is used for registration and deregistration.          */
+/*********************************************************************/
+
+static PSZ  RxFncTable[] =
+   {
+      "UZDropFuncs",
+      "UZLoadFuncs",
+      "UZFileSearch",
+      "UZFileTree",
+      "UZUnZip",
+      "UZUnZipToVar",
+      "UZUnZipToStem",
+      "UZVer",
+   };
+
+/*********************************************************************/
+/* Numeric Error Return Strings                                      */
+/*********************************************************************/
+
+#define  NO_UTIL_ERROR    "0"          /* No error whatsoever        */
+#define  ERROR_NOMEM      "2"          /* Insufficient memory        */
+
+/*********************************************************************/
+/* Numeric Return calls                                              */
+/*********************************************************************/
+
+#define  INVALID_ROUTINE 40            /* Raise Rexx error           */
+#define  VALID_ROUTINE    0            /* Successful completion      */
+
+/*********************************************************************/
+/* Some useful macros                                                */
+/*********************************************************************/
+
+#define BUILDRXSTRING(t, s) { \
+  strcpy((t)->strptr,(s));\
+  (t)->strlength = strlen((s)); \
+}
+
+
+/*********************************************************************/
+/****************  UNZIPAPI Supporting Functions  ********************/
+/****************  UNZIPAPI Supporting Functions  ********************/
+/****************  UNZIPAPI Supporting Functions  ********************/
+/*********************************************************************/
+
+
+int RexxReturn(__GPRO__ int nodefault, RXSTRING *retstr)
+{
+  int ret = G.os2.rexx_error;
+  if (G.filenotfound)
+    G.os2.rexx_mes = "file not found";
+  if (*G.os2.rexx_mes != '0') {
+    if (retstr->strlength > 255) {
+      DosFreeMem(retstr->strptr);
+      retstr->strptr = NULL;
+    }
+  } else if (nodefault)
+    goto noBuild;
+  BUILDRXSTRING(retstr, G.os2.rexx_mes);
+ noBuild:
+  DESTROYGLOBALS();
+  return ret;
+}
+
+/* Get a variable from REXX, return 0 if OK */
+int GetVariable(__GPRO__ const char *name)
+{
+  G.os2.request.shvnext = NULL;
+  EZRXSTRING(G.os2.request.shvname, name);
+  G.os2.request.shvnamelen = G.os2.request.shvname.strlength;
+  G.os2.request.shvvalue.strptr = G.os2.buffer;
+  G.os2.request.shvvalue.strlength = IBUF_LEN;
+  G.os2.request.shvvaluelen = IBUF_LEN;
+  G.os2.request.shvcode = RXSHV_SYFET;
+  G.os2.request.shvret = 0;
+  switch (RexxVariablePool(&G.os2.request)) {
+  case RXSHV_MEMFL:
+    G.os2.rexx_mes = ERROR_NOMEM;
+    break;
+  case RXSHV_BADN:
+  case RXSHV_NEWV:
+    G.os2.request.shvvaluelen = 0;
+  case RXSHV_OK:
+    *(G.os2.buffer+G.os2.request.shvvaluelen) = 0;
+    return G.os2.request.shvvaluelen;
+  }
+  return 0;
+}
+
+
+/* Get REXX compound variable */
+/* Stem must exist in G.os2.getvar_buf w/ length in G.os2.getvar_len */
+int GetVariableIndex(__GPRO__ int index)
+{
+  sprintf(G.os2.getvar_buf+G.os2.getvar_len,"%d",index);
+  return GetVariable(__G__ G.os2.getvar_buf);
+}
+
+
+/* Transfer REXX array to standard C string array */
+/* Returns number of elements */
+/* User is responsible for calling KillStringArray */
+
+int CompoundToStringArray(__GPRO__ char ***pointer, const char *name)
+{
+  int count;
+  int total;
+  char **trav;
+
+  G.os2.getvar_len = strlen(name);
+  memcpy(G.os2.getvar_buf,name,G.os2.getvar_len+1);
+  if (*(G.os2.getvar_buf+G.os2.getvar_len-1) != '.')
+    *(G.os2.getvar_buf+G.os2.getvar_len++) = '.', *(G.os2.getvar_buf+G.os2.getvar_len) = 0;
+
+  if (GetVariableIndex(__G__ 0))
+    return 0;
+
+  total = atoi(G.os2.buffer);
+  *pointer = (char **)malloc((total+1)<<2);
+  trav = *pointer;
+  for (count = 1; count <= total; count++) {
+    GetVariableIndex(__G__ count);
+    trav[count-1] = (char *)malloc(strlen(G.os2.buffer)+1);
+    strcpy(trav[count-1],G.os2.buffer);
+  }
+  trav[count-1] = NULL;
+  return total;
+}
+
+
+/* Kill string array created by CompoundToStringArray */
+
+void KillStringArray(char **pointer)
+{
+  char **trav=pointer;
+  while (*trav != NULL) {
+    free(*trav);
+    trav++;
+  }
+  free(pointer);
+}
+
+
+/*************************************************************************
+* Function:  UZDropFuncs                                                 *
+*                                                                        *
+* Syntax:    call UZDropFuncs                                            *
+*                                                                        *
+* Return:    NO_UTIL_ERROR - Successful.                                 *
+*************************************************************************/
+
+ULONG UZDropFuncs(CHAR *name, ULONG numargs, RXSTRING args[],
+                  CHAR *queuename, RXSTRING *retstr)
+{
+  INT     entries;                     /* Num of entries             */
+  INT     j;                           /* Counter                    */
+
+  if (numargs != 0)                    /* no arguments for this      */
+    return INVALID_ROUTINE;            /* raise an error             */
+
+  retstr->strlength = 0;               /* return a null string result*/
+
+  entries = sizeof(RxFncTable)/sizeof(PSZ);
+
+  for (j = 0; j < entries; j++)
+    RexxDeregisterFunction(RxFncTable[j]);
+
+  return VALID_ROUTINE;                /* no error on call           */
+}
+
+
+/*************************************************************************
+* Function:  UZFileTree                                                  *
+*                                                                        *
+* Syntax:    call UZFileTree zipfile, stem[, include-filespec]           *
+*                                [, exclude-filespec][, options]         *
+*                                                                        *
+* Params:    zipfile  - Name of zip file to search.                      *
+*            stem     - Name of stem var to store results in.            *
+*            include  - Filespec to search for (may include * and ?).    *
+*            exclude  - Filespec to exclude (may include * and ?).       *
+*            options  - Either of the following:                         *
+*                       'F' - Give file statistics.                      *
+*                          Length Date Time Name                         *
+*                       'Z' - Give zip statistics, too.                  *
+*                          Length Method Size Ratio Date Time CRC-32 Name*
+*                       Default is to return only filenames              *
+*                                                                        *
+* Return:    NO_UTIL_ERROR   - Successful.                               *
+*            ERROR_NOMEM     - Out of memory.                            *
+*************************************************************************/
+
+ULONG UZFileTree(CHAR *name, ULONG numargs, RXSTRING args[],
+                 CHAR *queuename, RXSTRING *retstr)
+{
+                                       /* validate arguments         */
+  char *incname[2];
+  char *excname[2];
+  CONSTRUCTGLOBALS();
+
+  if (numargs < 2 || numargs > 5 ||
+      !RXVALIDSTRING(args[0]) ||
+      !RXVALIDSTRING(args[1]) ||
+      args[0].strlength > 255) {
+    DESTROYGLOBALS();
+    return INVALID_ROUTINE;            /* Invalid call to routine    */
+  }
+                                       /* initialize data area       */
+  SetOutputVarStem(__G__ args[1].strptr);
+  G.wildzipfn = args[0].strptr;
+  G.process_all_files = TRUE;
+
+  uO.lflag = 1;
+  uO.zipinfo_mode = TRUE;
+  uO.C_flag = 1;
+  G.extract_flag = FALSE;
+  uO.qflag = 2;
+
+  if (numargs >= 3 &&                  /* check third option         */
+      !RXNULLSTRING(args[2]) &&
+      args[2].strlength > 0) {            /* a zero length string isn't */
+    if (!(G.filespecs = CompoundToStringArray(__G__ &G.pfnames,args[2].strptr))) {
+      G.pfnames = incname;
+      incname[0] = args[2].strptr;
+      incname[1] = NULL;
+      G.filespecs = 1;
+    }
+    G.process_all_files = FALSE;
+  }
+
+  if (numargs >= 4 &&                  /* check third option         */
+      !RXNULLSTRING(args[3]) &&
+      args[3].strlength > 0) {            /* a zero length string isn't */
+    if (!(G.xfilespecs = CompoundToStringArray(__G__ &G.pxnames,args[3].strptr))) {
+      G.pxnames = excname;
+      excname[0] = args[3].strptr;
+      excname[1] = NULL;
+      G.xfilespecs = 1;
+    }
+    G.process_all_files = FALSE;
+  }
+
+  if (numargs == 5 &&                  /* check third option         */
+      !RXNULLSTRING(args[4]) &&
+      args[4].strlength > 0) {            /* a zero length string isn't */
+    int first = *args[4].strptr & 0x5f;
+
+    if (first == 'Z')
+      uO.vflag = 2, uO.lflag = 0, uO.zipinfo_mode = FALSE;
+    else if (first == 'F')
+      uO.vflag = 1, uO.lflag = 0, uO.zipinfo_mode = FALSE;
+  }
+
+  process_zipfiles(__G);
+  SetOutputVarLength(__G);
+  if (G.filespecs > 0 && G.pfnames != incname)
+    KillStringArray(G.pfnames);
+  if (G.xfilespecs > 0 && G.pxnames != excname)
+    KillStringArray(G.pxnames);
+  return RexxReturn(__G__ 0,retstr);        /* no error on call           */
+}
+
+
+/*************************************************************************
+* Function:  UZUnZipToVar                                                *
+*                                                                        *
+* Syntax:    call UZUnZipToVar zipfile, filespec [, stem]                *
+*                                                                        *
+* Params:    zipfile  - Name of zip file to search.                      *
+*            filespec - File to extract                                  *
+*            stem     - If you specify a stem variable, the file will be *
+*                       extracted to the variable, one line per index    *
+*                       In this case, 0 will be returned                 *
+*                                                                        *
+* Return:    Extracted file                                              *
+*            ERROR_NOMEM     - Out of memory.                            *
+*************************************************************************/
+
+ULONG UZUnZipToVar(CHAR *name, ULONG numargs, RXSTRING args[],
+                          CHAR *queuename, RXSTRING *retstr)
+{
+  CONSTRUCTGLOBALS();
+  UzpBuffer *ub = (UzpBuffer *)retstr;
+                                       /* validate arguments         */
+  if (numargs < 2 || numargs > 3 ||
+      !RXVALIDSTRING(args[0]) ||
+      !RXVALIDSTRING(args[1]) ||
+      args[0].strlength == 0 ||
+      args[1].strlength == 0) {
+    DESTROYGLOBALS();
+    return INVALID_ROUTINE;            /* Invalid call to routine    */
+  }
+
+  uO.C_flag = 1;
+  G.redirect_data=1;
+  if (numargs == 3) {
+    if (!RXVALIDSTRING(args[2]) ||
+        RXNULLSTRING(args[1]) ||
+        args[2].strlength == 0) {
+      DESTROYGLOBALS();
+      return INVALID_ROUTINE;            /* Invalid call to routine    */
+    }
+    SetOutputVarStem(__G__ args[2].strptr);
+    G.redirect_text = 0;
+    G.redirect_data++;
+  }
+  unzipToMemory(__G__ args[0].strptr, args[1].strptr,
+                G.redirect_data==1 ? ub : NULL);
+  return RexxReturn(__G__ G.redirect_data==1,retstr);
+}
+
+
+/*************************************************************************
+* Function:  UZUnZipToStem                                               *
+*                                                                        *
+* Syntax:    call UZUnZipToStem zipfile, stem[, include-filespec]        *
+*                                [, exclude-filespec][, mode]            *
+*                                                                        *
+* Params:    zipfile  - Name of zip file to search.                      *
+*            stem     - Name of stem var to store files in.              *
+*            include  - Filespec to search for (may include * and ?).    *
+*            exclude  - Filespec to exclude (may include * and ?).       *
+*            mode     - Specifies 'F'lat or 'T'ree mode.  Umm, this is   *
+*                        hard to explain so I'll give an example, too.   *
+*                       Assuming a file unzip.zip containing:            *
+*                               unzip.c                                  *
+*                               unshrink.c                               *
+*                               extract.c                                *
+*                               os2/makefile.os2                         *
+*                               os2/os2.c                                *
+*                               os2/dll/dll.def                          *
+*                               os2/dll/unzipapi.c                       *
+*                                                                        *
+*                       -- In flat mode, each file is stored in          *
+*                          stem.fullname i.e. stem."os2/dll/unzipapi.c"  *
+*                          A list of files is created in stem.<index>    *
+*                                                                        *
+*                       Flat mode returns:                               *
+*                               stem.0 = 7                               *
+*                               stem.1 = unzip.c                         *
+*                               stem.2 = unshrink.c                      *
+*                               stem.3 = extract.c                       *
+*                               stem.4 = os2/makefile.os2                *
+*                               stem.5 = os2/os2.c                       *
+*                               stem.6 = os2/dll/dll.def                 *
+*                               stem.7 = os2/dll/unzipapi.c              *
+*                                                                        *
+*                       And the following contain the contents of the    *
+*                       various programs:                                *
+*                               stem.unzip.c                             *
+*                               stem.unshrink.c                          *
+*                               stem.extract.c                           *
+*                               stem.os2/makefile.os2                    *
+*                               stem.os2/os2.c                           *
+*                               stem.os2/dll/dll.def                     *
+*                               stem.os2/dll/unzipapi.c                  *
+*                                                                        *
+*                       -- In tree mode, slashes are converted to periods*
+*                          in the pathname thus the above file would have*
+*                          been stored in stem.os2.dll.unzipapi.c        *
+*                          The index would then be stored in stem.OS2.   *
+*                          DLL.<index>.                                  *
+*                                                                        *
+*                       NOTE: All path names are converted to uppercase  *
+*                                                                        *
+*                       Tree mode returns:                               *
+*                               stem.0 = 4                               *
+*                               stem.1 = unzip.c                         *
+*                               stem.2 = unshrink.c                      *
+*                               stem.3 = extract.c                       *
+*                               stem.4 = OS2/                            *
+*                                                                        *
+*                               stem.OS2.0 = 3                           *
+*                               stem.OS2.1 = makefile.os2                *
+*                               stem.OS2.2 = os2.c                       *
+*                               stem.OS2.3 = DLL/                        *
+*                                                                        *
+*                               stem.OS2.DLL.0 = 2                       *
+*                               stem.OS2.DLL.1 = def                     *
+*                               stem.OS2.DLL.2 = unzipapi.c              *
+*                                                                        *
+*                       And the following contain the contents of the    *
+*                       various programs:                                *
+*                               stem.unzip.c                             *
+*                               stem.unshrink.c                          *
+*                               stem.extract.c                           *
+*                               stem.OS2.makefile.os2                    *
+*                               stem.OS2.os2.c                           *
+*                               stem.OS2.DLL.dll.def                     *
+*                               stem.OS2.DLL.unzipapi.c                  *
+*                                                                        *
+*                                                                        *
+* Return:    NO_UTIL_ERROR   - Successful.                               *
+*            ERROR_NOMEM     - Out of memory.                            *
+*************************************************************************/
+
+ULONG UZUnZipToStem(CHAR *name, ULONG numargs, RXSTRING args[],
+                          CHAR *queuename, RXSTRING *retstr)
+{
+  char *incname[2];
+  char *excname[2];
+  CONSTRUCTGLOBALS();
+                                       /* validate arguments         */
+  if (numargs < 2 || numargs > 5 ||
+      !RXVALIDSTRING(args[0]) ||
+      !RXVALIDSTRING(args[1]) ||
+      args[0].strlength > 255) {
+    DESTROYGLOBALS();
+    return INVALID_ROUTINE;            /* Invalid call to routine    */
+  }
+                                       /* initialize data area       */
+  G.wildzipfn = args[0].strptr;
+  G.process_all_files = TRUE;
+
+  uO.C_flag = 1;
+  G.extract_flag = TRUE;
+  SetOutputVarStem(__G__ args[1].strptr);
+  G.redirect_data = 3;
+  G.redirect_text = 0;
+
+  if (numargs >= 3 &&                  /* check third option         */
+      !RXNULLSTRING(args[2]) &&
+      args[2].strlength > 0) {            /* a zero length string isn't */
+    if (!(G.filespecs = CompoundToStringArray(__G__ &G.pfnames,args[2].strptr))) {
+      G.pfnames = incname;
+      incname[0] = args[2].strptr;
+      incname[1] = NULL;
+      G.filespecs = 1;
+    }
+    G.process_all_files = FALSE;
+  }
+
+  if (numargs >= 4 &&                  /* check third option         */
+      !RXNULLSTRING(args[3]) &&
+      args[3].strlength > 0) {            /* a zero length string isn't */
+    if (!(G.xfilespecs = CompoundToStringArray(__G__ &G.pxnames,args[3].strptr))) {
+      G.pxnames = excname;
+      excname[0] = args[3].strptr;
+      excname[1] = NULL;
+      G.xfilespecs = 1;
+    }
+    G.process_all_files = FALSE;
+  }
+
+  if (numargs == 5 &&                  /* check third option         */
+      !RXNULLSTRING(args[4]) &&
+      (*args[4].strptr & 0x5f) == 'T') {
+    G.redirect_data++;
+    G.os2.request.shvnext = NULL;
+    EZRXSTRING(G.os2.request.shvname, args[4].strptr);
+    G.os2.request.shvnamelen = G.os2.request.shvname.strlength;
+    G.os2.request.shvcode = RXSHV_SYDRO;
+    G.os2.request.shvret = 0;
+    RexxVariablePool(&G.os2.request);
+  }
+
+
+  uO.qflag = 2;
+
+  process_zipfiles(__G);
+  if (G.filespecs > 0 && G.pfnames != incname)
+    KillStringArray(G.pfnames);
+  if (G.xfilespecs > 0 && G.pxnames != excname)
+    KillStringArray(G.pxnames);
+  if (G.redirect_data == 3)
+    SetOutputVarLength(__G);
+  return RexxReturn(__G__ 0,retstr);            /* no error on call           */
+}
+
+
+/*************************************************************************
+* Function:  UZLoadFuncs                                                 *
+*                                                                        *
+* Syntax:    call UZLoadFuncs [option]                                   *
+*                                                                        *
+* Params:    none                                                        *
+*                                                                        *
+* Return:    null string                                                 *
+*************************************************************************/
+
+ULONG UZLoadFuncs(CHAR *name, ULONG numargs, RXSTRING args[],
+                           CHAR *queuename, RXSTRING *retstr)
+{
+  INT    entries;                      /* Num of entries             */
+  INT    j;                            /* Counter                    */
+
+  retstr->strlength = 0;               /* set return value           */
+                                       /* check arguments            */
+  if (numargs > 0)
+    return INVALID_ROUTINE;
+
+  entries = sizeof(RxFncTable)/sizeof(PSZ);
+
+  for (j = 0; j < entries; j++) {
+    RexxRegisterFunctionDll(RxFncTable[j],
+          "UNZIP32", RxFncTable[j]);
+  }
+  return VALID_ROUTINE;
+}
+
+
+
+/*************************************************************************
+* Function:  UZVer                                                       *
+*                                                                        *
+* Syntax:    call UZVer                                                  *
+*                                                                        *
+* Return:    Version of Unzip                                            *
+*************************************************************************/
+
+ULONG UZVer(CHAR *name, ULONG numargs, RXSTRING args[],
+                        CHAR *queuename, RXSTRING *retstr)
+{
+  if (numargs > 1)                    /* validate arg count         */
+    return INVALID_ROUTINE;
+
+  if (numargs == 0 || (*args[0].strptr & 0x5f) != 'L')
+    /* strcpy( retstr->strptr, UZ_VERNUM );    "5.13a BETA" */
+    sprintf( retstr->strptr, "%d.%d%d%s", UZ_MAJORVER, UZ_MINORVER,
+      PATCHLEVEL, BETALEVEL );
+  else
+    /* strcpy( retstr->strptr, UZ_VERSION );   UZ_VERNUM" of 26 Sep 94" */
+    sprintf( retstr->strptr, "%d.%d%d%s of %s", UZ_MAJORVER, UZ_MINORVER,
+      PATCHLEVEL, BETALEVEL, VERSION_DATE );
+  retstr->strlength = strlen(retstr->strptr);
+  return VALID_ROUTINE;
+}
+
+
+/*************************************************************************
+* Function:  UZUnZip                                                     *
+*                                                                        *
+* Syntax:    call UZUnZip                                                *
+*                                                                        *
+* Return:    Unzip return code                                           *
+*************************************************************************/
+
+ULONG UZUnZip(CHAR *name, ULONG numargs, RXSTRING args[],
+                        CHAR *queuename, RXSTRING *retstr)
+{
+  char *argv[30];
+  char *scan;
+  int argc=0;
+  int idx;
+  CONSTRUCTGLOBALS();
+
+  if (numargs < 1 || numargs > 2 ||
+      args[0].strlength > 255) {
+    DESTROYGLOBALS();
+    return INVALID_ROUTINE;            /* Invalid call to routine    */
+  }
+                                       /* initialize data area       */
+  if (numargs == 2)
+    SetOutputVarStem(__G__ args[1].strptr);
+
+  scan = args[0].strptr;
+  argv[argc++] = "";         /* D:\\SOURCECODE\\UNZIP51S\\UNZIP.COM"; */
+  while (*scan == ' ')
+    scan++;
+  argv[argc++] = scan;
+  while ( (scan = strchr(scan,' ')) != NULL) {
+    *scan++ = 0;
+    while (*scan == ' ')
+      scan++;
+    argv[argc++] = scan;
+  }
+  if (*argv[argc-1] == 0)
+    argc--;
+  argv[argc] = 0;
+
+         /* GRR:  should resetMainFlags() be called in here somewhere? */
+
+  sprintf(retstr->strptr, "%d", unzip(__G__ argc, argv));   /* a.k.a. MAIN() */
+  if (numargs == 2)
+    SetOutputVarLength(__G);
+  retstr->strlength = strlen(retstr->strptr);
+  return RexxReturn(__G__ 1,retstr);
+}
+
+int varmessage(__GPRO__ uch *buf, ulg size)
+{
+  if (size > 0)
+    memcpy(G.os2.buffer+G.os2.putchar_idx,buf,size);
+    G.os2.putchar_idx = TextSetNext(__G__ G.os2.buffer, size+G.os2.putchar_idx,0);
+  return 0;
+}
+
+int varputchar(__GPRO__ int c)
+{
+  G.os2.buffer[G.os2.putchar_idx++] = c;
+  if (c == '\n') {
+    G.os2.buffer[G.os2.putchar_idx] = 0;
+    if (G.os2.output_var[0])
+      G.os2.putchar_idx = TextSetNext(__G__ G.os2.buffer, G.os2.putchar_idx,0);
+    else {
+      G.os2.buffer[--G.os2.putchar_idx] = 0;
+      puts(G.os2.buffer);
+      G.os2.putchar_idx = 0;
+    }
+  }
+  return 1;
+}
+
+
+
+int SetOutputVarStem(__GPRO__ const char *name)
+{
+  int len=strlen(name);
+  G.redirect_text=1;
+  G.os2.output_idx = 0;
+  strcpy(G.os2.output_var, name);
+  if (len) {
+    strupr(G.os2.output_var);                 /* uppercase the name         */
+    if (*(G.os2.output_var+len-1) != '.') {
+      *(G.os2.output_var+len) = '.';
+      len++;
+      *(G.os2.output_var+len) = 0;
+    }
+    WriteToVariable(__G__ G.os2.output_var,"",0);
+  }
+  G.os2.stem_len = len;
+  return G.os2.stem_len;
+}
+
+int SetOutputVar(__GPRO__ const char *name)
+{
+  int len=strlen(name);
+  G.redirect_text=1;
+  G.os2.output_idx = 0;
+  strcpy(G.os2.output_var, name);
+  strupr(G.os2.output_var);                 /* uppercase the name         */
+  if (*(name+len-1) == '.')
+    G.os2.stem_len = len;
+  else
+    G.os2.stem_len = 0;
+  return G.os2.stem_len;
+}
+
+int SetOutputVarLength(__GPRO)
+{
+  if (G.os2.stem_len > 0) {
+    if (G.os2.putchar_idx)
+      TextSetNext(__G__ G.os2.buffer,G.os2.putchar_idx,1);
+    return PrintToSubVariable(__G__ 0,"%d",G.os2.output_idx);
+  }
+  return 0;
+}
+
+int PrintToVariable(__GPRO__ const char *name, const char *format,...)
+{
+  va_list arg_ptr;
+  int ret;
+
+  va_start(arg_ptr, format);
+  ret = _PrintToVariable(__G__ name, format, arg_ptr);
+  va_end(arg_ptr);
+  return ret;
+}
+
+int WriteToVariable(__GPRO__ const char *name, char *buffer, int len)
+{
+  G.os2.request.shvnext = NULL;
+  EZRXSTRING(G.os2.request.shvname, name);
+  G.os2.request.shvnamelen = G.os2.request.shvname.strlength;
+  G.os2.request.shvvalue.strptr = buffer;
+  G.os2.request.shvvalue.strlength = len;
+  G.os2.request.shvvaluelen = len;
+  G.os2.request.shvcode = RXSHV_SET;
+  G.os2.request.shvret = 0;
+  switch (RexxVariablePool(&G.os2.request)) {
+  case RXSHV_BADN:
+    G.os2.rexx_error = INVALID_ROUTINE;
+    break;
+  case RXSHV_MEMFL:
+    G.os2.rexx_mes = ERROR_NOMEM;
+    break;
+  case RXSHV_OK:
+    return 0;
+  }
+  return INVALID_ROUTINE;      /* error on non-zero          */
+}
+
+int _PrintToVariable(__GPRO__ const char *name, const char *format, va_list arg_ptr)
+{
+  int ret = vsprintf(G.os2.buffer, format, arg_ptr);
+  WriteToVariable(__G__ name, G.os2.buffer, strlen(G.os2.buffer));
+  return ret;
+}
+
+int PrintToSubVariable(__GPRO__ int idx, const char *format, ...)
+{
+  va_list arg_ptr;
+  int ret;
+
+  if (G.os2.stem_len == 0)
+    return INVALID_ROUTINE;      /* error on non-zero          */
+  sprintf(G.os2.output_var+G.os2.stem_len,"%d",idx);
+
+  va_start(arg_ptr, format);
+  ret = _PrintToVariable(__G__ G.os2.output_var, format, arg_ptr);
+  va_end(arg_ptr);
+  return ret;
+}
+
+
+int WriteToNextVariable(__GPRO__ char *buffer, int len)
+{
+  if (G.os2.stem_len > 0) {
+    G.os2.output_idx++;
+    sprintf(G.os2.output_var+G.os2.stem_len,"%d",G.os2.output_idx);
+  }
+  return WriteToVariable(__G__ G.os2.output_var, buffer, len);
+}
+
+
+int TextSetNext(__GPRO__ char *buffer, int len, int all)
+{
+  char *scan = buffer, *next, *base=buffer;
+  int remaining=len;
+  int ret;
+
+  while ((next = strchr(scan,'\n')) != NULL && remaining > 0) {
+    if (next > scan && *(next-1) == 0xd)
+      *(next-1) = 0;
+    else
+      *next = 0;
+    if (WriteToNextVariable(__G__ scan,strlen(scan)))
+      return 0;
+    next++;
+    remaining -= (next-scan);
+    scan = next;
+  }
+  if (remaining > 0)
+    if (all) {
+      *(scan+remaining) = 0;
+      WriteToNextVariable(__G__ scan,remaining);
+    } else {
+      memcpy(buffer,scan,remaining);
+      return remaining;
+    }
+
+  return 0;
+}
+
+int finish_REXX_redirect(__GPRO)
+{
+  char *scan, *ptr;
+  int idx=0, first=1, offset;
+
+  if (!G.redirect_size)
+    return 0;
+  switch(G.redirect_data) {
+  case 1:
+    break;
+  case 2:
+    TextSetNext(__G__ G.redirect_buffer, G.redirect_size, 1);
+    SetOutputVarLength(__G);
+    DosFreeMem(G.redirect_buffer);
+    G.redirect_buffer = NULL;
+    G.redirect_size = 0;
+    break;
+  case 3:
+    WriteToNextVariable(__G__ G.filename,strlen(G.filename));
+    sprintf(G.os2.output_var+G.os2.stem_len,G.filename);
+    WriteToVariable(__G__ G.os2.output_var, G.redirect_buffer, G.redirect_size);
+    DosFreeMem(G.redirect_buffer);
+    G.redirect_buffer = NULL;
+    G.redirect_size = 0;
+    break;
+  case 4:
+    if ((scan = strrchr(G.filename,'/')) != NULL) {
+      idx = *scan;
+      *scan = 0;
+      strupr(G.filename);
+      *scan = idx;
+    }
+    scan = G.os2.output_var+G.os2.stem_len;
+    strcpy(scan,G.filename);
+    while ((scan = strchr(scan,'/')) != NULL)
+      *scan = '.';
+    WriteToVariable(__G__ G.os2.output_var, G.redirect_buffer, G.redirect_size);
+    DosFreeMem(G.redirect_buffer);
+    G.redirect_buffer = NULL;
+    G.redirect_size = 0;
+    strcpy(G.os2.getvar_buf, G.os2.output_var);
+    do {
+      if ((scan = strrchr(G.filename,'/')) == NULL)
+        offset = 0;
+      else
+        offset = scan-G.filename+1;
+      if (first || !GetVariable(__G__ G.os2.output_var)) {
+        ptr = G.os2.getvar_buf+offset+G.os2.stem_len;
+        *ptr = '0';
+        *(ptr+1) = 0;
+        if (!GetVariable(__G__ G.os2.getvar_buf))
+          idx = 1;
+        else
+          idx = atoi(G.os2.buffer)+1;
+        PrintToVariable(__G__ G.os2.getvar_buf,"%d",idx);
+        sprintf(ptr,"%d",idx);
+        if (!first) {
+          PrintToVariable(__G__ G.os2.output_var,"%d",idx);
+          idx = strlen(G.filename);
+          *(G.filename+idx)   = '/';
+          *(G.filename+idx+1) = 0;
+        }
+        WriteToVariable(__G__ G.os2.getvar_buf,G.filename+offset,strlen(G.filename+offset));
+        first=0;
+      }
+      if (offset) {
+        *(G.os2.output_var+G.os2.stem_len+offset-1)   = 0;
+        *scan = 0;
+      }
+    } while (offset);
+    break;
+  }
+  return 0;
+}
+
+#endif /* OS2DLL */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/rexxhelp.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,178 @@
+/* rexxhelp.c */
+
+#if defined(API_DOC) && defined(OS2DLL)
+
+#define UNZIP_INTERNAL
+#include "../unzip.h"
+#include "../version.h"
+
+APIDocStruct REXXDetails[] = {
+  { "UZDROPFUNCS"  , "UZDropFuncs"  ,
+               "call UZDropFuncs",
+               "Use this function to drop all the loaded UnZip functions.\n"
+"\t\tOnce this function is processed by a REXX program, the\n"
+"\t\tUnZip functions are not accessible in any OS/2 sessions.\n" },
+
+  { "UZLOADFUNCS"  , "UZLoadFuncs"  ,
+               "call UZLoadFuncs",
+               "Use this function to make all of the UnZip functions\n"
+"		in this package available to all OS/2 sessions.\n\n"
+"  Example:	call RxFuncAdd 'UZLoadFuncs', 'UNZIPAPI', 'UZLoadFuncs'\n"
+"		call UZLoadFuncs\n" },
+
+  { "UZFILETREE"   , "UZFileTree"   ,
+               "rc = UZFileTree(zipfile, stem, [include], [exclude], [options])\n\n"
+"	zipfile	- Name of ZIP file to search\n"
+"	stem	- Name of the stem variable for results\n"
+"		  Note: stem.0 contains the number of files found.\n"
+"	include - Optional stem variable specifying a list of files (including\n"
+"		  wildcards) to include.  stem.0 must indicate number of items.\n"
+"	exclude - Optional stem variable specifying a list of files (including\n"
+"		  wildcards) to exclude.  stem.0 must indicate number of items.\n"
+"	    NOTE: If lists are not needed, filespec strings may be passed.\n"
+"	options - One of the following:\n"
+"		  'O' - Give file names only.  This is the default.\n"
+"		  'F' - Give file statistics in the form:\n"
+"			Length Date Time Name\n"
+"		  'Z' - Also give ZIP statistics in the form:\n"
+"			Length Method Size Ratio Date Time CRC-32 Name",
+               "Finds all files in the specified ZIP with the specified\n"
+"		filespec and places their descriptions in a stem variable.\n\n"
+"	rc:	Return codes\n"
+"		0	Successful\n"
+"		2	Error.  Not enough memory.\n\n"
+"	Examples:\n"
+"		/* Return a list of all .NDX files in pcboard.qwk */\n"
+"		rc = UZFileTree('pcboard.qwk', 'stem.', '*.ndx')\n\n"
+"		/* Return a list of all files except *.NDX and *.DAT */\n"
+"		exc.0 = 2; exc.1 = '*.ndx'; exc.2 = '*.dat'\n"
+"		rc = UZFileTree('pcboard.qwk', 'stem.',,'exc.')\n" },
+
+  { "UZUNZIP"      , "UZUnZip"      ,
+               "rc = UZUnZip('parameters', [stem])\n\n"
+"	parameters	- The entire list of parameters you would use from\n"
+"			  the command-line\n"
+"	stem		- The name of an optional stem variable where any\n"
+"			  output should be redirected.\n"
+"			  NOTE: If a stem is not specified, all output will\n"
+"				go to the console.",
+               "Provide a direct entry point to the command line interface.\n\n"
+"	rc:	UnZip return code\n\n"
+"  Examples:	/* Test the archive 'unzip51s.zip' and return output in stem.*/\n"
+"		rc = UZUnZip('-t unzip51s.zip','stem.')\n"
+"		/* Extract the archive, display output on screen */\n"
+"		call UZUnZip 'doom.zip'\n"
+"		/* Extract all .NDX files from the archive */\n"
+"		call UZUnZip 'pcboard.qwk *.ndx','stem.'\n" },
+
+  { "UZUNZIPTOVAR" , "UZUnZipToVar" ,
+               "rc = UZUnZipToVar('zipfile', 'filename', [stem])\n\n"
+"	zipfile	 - Name of ZIP file to search\n"
+"	filename - Name of file to extract from zipfile\n"
+"	stem	 - Optional stem variable to extract the file to.\n"
+"		   If you specify a stem variable, the file will be extracted\n"
+"		   to the variable, one line per index, stem.0 containing a\n"
+"		   line count.  In this case, 0 will be returned in rc.\n"
+"		   If NO stem variable is specified, the entire file will be\n"
+"		   extracted to rc.",
+               "Unzip one file to a variable.\n\n"
+"	rc:	If no stem variable is specified, rc contains the contents of\n"
+"		the extracted file if successful or an error-code if not.\n"
+"		If a stem variable IS specified, rc contains 0 if successful.\n"},
+
+  /* GRR:  "include" and "exclude" used to be identified as stem variables
+   *       (Daniel H bug report)
+   */
+  { "UZUNZIPTOSTEM", "UZUnZipToStem",
+               "rc = UZUnZipToStem(zipfile, stem, [include], [exclude], [mode])\n"
+"	zipfile	- Name of ZIP file to search\n"
+"	stem	- Stem variable used to store the extracted files\n"
+"	include - Optional string variable specifying a list of files (including\n"
+"		  wildcards) to include.  stem.0 must indicate number of items.\n"
+"	exclude - Optional string variable specifying a list of files (including\n"
+"		  wildcards) to exclude.  stem.0 must indicate number of items.\n"
+"	    NOTE: If lists are not needed, filespec strings may be passed.\n"
+"	mode	- Optional mode parameter specifies either 'F'lat (the default)\n"
+"		  or 'T'ree mode.\n"
+"		-- In flat mode, each file is stored in stem.fullname i.e.\n"
+"		   stem.os2/dll/unzipapi.c.  A list of files is created in\n"
+"		   stem.<index>\n"
+"		-- In tree mode, slashes are converted to periods in the\n"
+"		   pathname thus the above file would have been stored in\n"
+"		   stem.OS2.DLL.unzipapi.c and an index stored for each\n"
+"		   directory, i.e. stem.OS2.DLL.<index> = \"unzipapi.c\",\n"
+"		   stem.OS2.<index> = \"DLL/\", stem.<index> = \"OS2/\"",
+               "Unzip files to a stem variable.\n\n"
+"	Example:	Assuming a file unzip.zip containing:\n"
+"			  unzip.c, unshrink.c, extract.c,\n"
+"			  os2/makefile.os2, os2/os2.c\n"
+"			  os2/dll/dll.def, os2/dll/unzipapi.c\n\n"
+"		rc = UZUnZipToStem('unzip.zip', 'stem.')\n"
+"		Returns:	stem.0 = 7\n"
+"				stem.1 = unzip.c\n"
+"				stem.2 = unshrink.c\n"
+"				stem.3 = extract.c\n"
+"				stem.4 = os2/makefile.os2\n"
+"				stem.5 = os2/os2.c\n"
+"				stem.6 = os2/dll/dll.def\n"
+"				stem.7 = os2/dll/unzipapi.c\n"
+"			And the following contain the contents of the\n"
+"			various files:\n"
+"				stem.unzip.c\n"
+"				stem.unshrink.c\n"
+"				stem.extract.c\n"
+"				stem.os2/makefile.os2\n"
+"				stem.os2/os2.c\n"
+"				stem.os2/dll/dll.def\n"
+"				stem.os2/dll/unzipapi.c\n\n"
+"		rc = UZUnZipToStem('unzip.zip', 'stem.',,,'TREE')\n"
+"		Returns:	stem.0 = 4\n"
+"				stem.1 = unzip.c\n"
+"				stem.2 = unshrink.c\n"
+"				stem.3 = extract.c\n"
+"				stem.4 = OS2/\n"
+"				stem.OS2.0 = 3\n"
+"				stem.OS2.1 = makefile.os2\n"
+"				stem.OS2.2 = os2.c\n"
+"				stem.OS2.3 = DLL/\n"
+"				stem.OS2.DLL.0 = 2\n"
+"				stem.OS2.DLL.1 = def\n"
+"				stem.OS2.DLL.2 = unzipapi.c\n"
+"\n"
+"			And the following contain the contents of the\n"
+"			various programs:\n"
+"				stem.unzip.c\n"
+"				stem.unshrink.c\n"
+"				stem.extract.c\n"
+"				stem.OS2.makefile.os2\n"
+"				stem.OS2.os2.c\n"
+"				stem.OS2.DLL.dll.def\n"
+"				stem.OS2.DLL.unzipapi.c\n" },
+
+  { "UZVER"        , "UZVer"        ,
+               "rc = UZVer([option])\n\n"
+"	rc	String containing UnZip version info in the form 'x.xx'\n"
+"		If option is 'L' then info is in the form 'x.xx of <date>",
+               "Returns the version number of UnZip\n" },
+
+  { "UZAPIVER"     , "UZAPIVer"     ,
+               "rc = UZAPIVer([option])\n\n"
+"	rc	String containing API version info in the form 'x.xx'\n"
+"		If option is 'L' then info is in the form 'x.xx of <date>",
+               "Returns the version number of the API\n" },
+  { 0 }
+};
+
+char *REXXBrief = "\
+REXX functions:\n\
+  UZDropFuncs     -- Makes all functions in this package unknown to REXX\n\
+  UZLoadFuncs     -- Makes all functions in this package known to REXX\n\
+  UZFileTree      -- Searches for files matching a given filespec\n\
+  UZUnZip	  -- UnZip command-line entry point\n\
+  UZUnZipToVar    -- Unzip one file to a variable\n\
+  UZUnZipToStem   -- Unzip files to a variable array\n\
+  UZVer           -- Returns the UnZip version number\n\
+  UZAPIVer        -- Returns the API version number\n";
+
+
+#endif /* API_DOC && OS2DLL */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/sfx.def	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,8 @@
+NAME         SFX
+DESCRIPTION  'Installer'
+EXETYPE      WINDOWS
+STUB         'WINSTUB.EXE'
+CODE         PRELOAD MOVEABLE DISCARDABLE
+DATA         PRELOAD MOVEABLE MULTIPLE
+HEAPSIZE     1024
+STACKSIZE    8192
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/sfx.rc	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,2 @@
+#include "wx/msw/wx.rc"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/ttyio.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,625 @@
+/*---------------------------------------------------------------------------
+
+  ttyio.c
+
+  This file contains routines for doing console input/output, including code
+  for non-echoing input.  It is used by the encryption/decryption code but
+  does not contain any restricted code itself.  This file is shared between
+  Info-ZIP's Zip and UnZip.
+
+  Contains:  echo()         (VMS only)
+             Echon()        (Unix only)
+             Echoff()       (Unix only)
+             screenlines()  (Unix only)
+             zgetch()       (Unix and non-Unix versions)
+             getp()         ("PC," Unix/Atari/Be, VMS/VMCMS/MVS)
+
+  ---------------------------------------------------------------------------*/
+
+#define __TTYIO_C       /* identifies this source module */
+
+#include "zip.h"
+#include "crypt.h"
+
+#if (CRYPT || (defined(UNZIP) && !defined(FUNZIP)))
+/* Non-echo console/keyboard input is needed for (en/de)cryption's password
+ * entry, and for UnZip(SFX)'s MORE and Pause features.
+ * (The corresponding #endif is found at the end of this module.)
+ */
+
+#include "ttyio.h"
+
+#ifndef PUTC
+#  define PUTC putc
+#endif
+
+#ifdef ZIP
+#  ifdef GLOBAL          /* used in Amiga system headers, maybe others too */
+#    undef GLOBAL
+#  endif
+#  define GLOBAL(g) g
+#else
+#  define GLOBAL(g) G.g
+#endif
+
+#ifdef __BEOS__                /* why yes, we do */
+#  define HAVE_TERMIOS_H
+#endif
+
+#ifdef _POSIX_VERSION
+#  ifndef USE_POSIX_TERMIOS
+#    define USE_POSIX_TERMIOS  /* use POSIX style termio (termios) */
+#  endif
+#  ifndef HAVE_TERMIOS_H
+#    define HAVE_TERMIOS_H     /* POSIX termios.h */
+#  endif
+#endif /* _POSIX_VERSION */
+
+#ifdef UNZIP            /* Zip handles this with the unix/configure script */
+#  ifndef _POSIX_VERSION
+#    if (defined(SYSV) || defined(CRAY)) &&  !defined(__MINT__)
+#      ifndef USE_SYSV_TERMIO
+#        define USE_SYSV_TERMIO
+#      endif
+#      ifdef COHERENT
+#        ifndef HAVE_TERMIO_H
+#          define HAVE_TERMIO_H
+#        endif
+#        ifdef HAVE_SYS_TERMIO_H
+#          undef HAVE_SYS_TERMIO_H
+#        endif
+#      else /* !COHERENT */
+#        ifdef HAVE_TERMIO_H
+#          undef HAVE_TERMIO_H
+#        endif
+#        ifndef HAVE_SYS_TERMIO_H
+#           define HAVE_SYS_TERMIO_H
+#        endif
+#      endif /* ?COHERENT */
+#    endif /* (SYSV || CRAY) && !__MINT__ */
+#  endif /* !_POSIX_VERSION */
+#  if !(defined(BSD4_4) || defined(SYSV) || defined(__convexc__))
+#    ifndef NO_FCNTL_H
+#      define NO_FCNTL_H
+#    endif
+#  endif /* !(BSD4_4 || SYSV || __convexc__) */
+#endif /* UNZIP */
+
+#ifdef HAVE_TERMIOS_H
+#  ifndef USE_POSIX_TERMIOS
+#    define USE_POSIX_TERMIOS
+#  endif
+#endif
+
+#if (defined(HAVE_TERMIO_H) || defined(HAVE_SYS_TERMIO_H))
+#  ifndef USE_SYSV_TERMIO
+#    define USE_SYSV_TERMIO
+#  endif
+#endif
+
+#if (defined(UNZIP) && !defined(FUNZIP) && defined(UNIX) && defined(MORE))
+#  include <sys/ioctl.h>
+#  define GOT_IOCTL_H
+   /* int ioctl OF((int, int, zvoid *));   GRR: may need for some systems */
+#endif
+
+#ifndef HAVE_WORKING_GETCH
+   /* include system support for switching of console echo */
+#  ifdef VMS
+#    include <descrip.h>
+#    include <iodef.h>
+#    include <ttdef.h>
+#    include <starlet.h>
+#    include <ssdef.h>
+#  else /* !VMS */
+#    ifdef HAVE_TERMIOS_H
+#      include <termios.h>
+#      define sgttyb termios
+#      define sg_flags c_lflag
+#      define GTTY(f, s) tcgetattr(f, (zvoid *) s)
+#      define STTY(f, s) tcsetattr(f, TCSAFLUSH, (zvoid *) s)
+#    else /* !HAVE_TERMIOS_H */
+#      ifdef USE_SYSV_TERMIO           /* Amdahl, Cray, all SysV? */
+#        ifdef HAVE_TERMIO_H
+#          include <termio.h>
+#        endif
+#        ifdef HAVE_SYS_TERMIO_H
+#          include <sys/termio.h>
+#        endif
+#        ifdef NEED_PTEM
+#          include <sys/stream.h>
+#          include <sys/ptem.h>
+#        endif
+#        define sgttyb termio
+#        define sg_flags c_lflag
+#        define GTTY(f,s) ioctl(f,TCGETA,(zvoid *)s)
+#        define STTY(f,s) ioctl(f,TCSETAW,(zvoid *)s)
+#      else /* !USE_SYSV_TERMIO */
+#        ifndef CMS_MVS
+#          if (!defined(MINIX) && !defined(GOT_IOCTL_H))
+#            include <sys/ioctl.h>
+#          endif
+#          include <sgtty.h>
+#          define GTTY gtty
+#          define STTY stty
+#          ifdef UNZIP
+             /*
+              * XXX : Are these declarations needed at all ????
+              */
+             /*
+              * GRR: let's find out...   Hmmm, appears not...
+             int gtty OF((int, struct sgttyb *));
+             int stty OF((int, struct sgttyb *));
+              */
+#          endif
+#        endif /* !CMS_MVS */
+#      endif /* ?USE_SYSV_TERMIO */
+#    endif /* ?HAVE_TERMIOS_H */
+#    ifndef NO_FCNTL_H
+#      ifndef UNZIP
+#        include <fcntl.h>
+#      endif
+#    else
+       char *ttyname OF((int));
+#    endif
+#  endif /* ?VMS */
+#endif /* !HAVE_WORKING_GETCH */
+
+
+
+#ifndef HAVE_WORKING_GETCH
+#ifdef VMS
+
+/*
+ * Turn keyboard echoing on or off (VMS).  Loosely based on VMSmunch.c
+ * and hence on Joe Meadows' file.c code.
+ */
+int echo(opt)
+    int opt;
+{
+    /*
+     * For VMS v5.x:
+     *   IO$_SENSEMODE/SETMODE info:  Programming, Vol. 7A, System Programming,
+     *     I/O User's: Part I, sec. 8.4.1.1, 8.4.3, 8.4.5, 8.6
+     *   sys$assign(), sys$qio() info:  Programming, Vol. 4B, System Services,
+     *     System Services Reference Manual, pp. sys-23, sys-379
+     *   fixed-length descriptor info:  Programming, Vol. 3, System Services,
+     *     Intro to System Routines, sec. 2.9.2
+     * Greg Roelofs, 15 Aug 91
+     */
+
+    /* SKM: make global? */
+    static struct dsc$descriptor_s DevDesc =
+        {11, DSC$K_DTYPE_T, DSC$K_CLASS_S, "SYS$COMMAND"};
+     /* {dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer}; */
+    static short           DevChan, iosb[4];
+    static long            status;
+    static unsigned long   oldmode[2], newmode[2];   /* each = 8 bytes */
+
+
+    /* assign a channel to standard input */
+    status = sys$assign(&DevDesc, &DevChan, 0, 0);
+    if (!(status & 1))
+        return status;
+
+    /* use sys$qio and the IO$_SENSEMODE function to determine the current
+     * tty status (for password reading, could use IO$_READVBLK function
+     * instead, but echo on/off will be more general)
+     */
+    status = sys$qiow(0, DevChan, IO$_SENSEMODE, &iosb, 0, 0,
+                     oldmode, 8, 0, 0, 0, 0);
+    if (!(status & 1))
+        return status;
+    status = iosb[0];
+    if (!(status & 1))
+        return status;
+
+    /* copy old mode into new-mode buffer, then modify to be either NOECHO or
+     * ECHO (depending on function argument opt)
+     */
+    newmode[0] = oldmode[0];
+    newmode[1] = oldmode[1];
+    if (opt == 0)   /* off */
+        newmode[1] |= TT$M_NOECHO;                      /* set NOECHO bit */
+    else
+        newmode[1] &= ~((unsigned long) TT$M_NOECHO);   /* clear NOECHO bit */
+
+    /* use the IO$_SETMODE function to change the tty status */
+    status = sys$qiow(0, DevChan, IO$_SETMODE, &iosb, 0, 0,
+                     newmode, 8, 0, 0, 0, 0);
+    if (!(status & 1))
+        return status;
+    status = iosb[0];
+    if (!(status & 1))
+        return status;
+
+    /* deassign the sys$input channel by way of clean-up */
+    status = sys$dassgn(DevChan);
+    if (!(status & 1))
+        return status;
+
+    return SS$_NORMAL;   /* we be happy */
+
+} /* end function echo() */
+
+
+#else /* !VMS:  basically Unix */
+
+
+/* For VM/CMS and MVS, non-echo terminal input is not (yet?) supported. */
+#ifndef CMS_MVS
+
+#ifdef ZIP                      /* moved to globals.h for UnZip */
+   static int echofd=(-1);      /* file descriptor whose echo is off */
+#endif
+
+/*
+ * Turn echo off for file descriptor f.  Assumes that f is a tty device.
+ */
+void Echoff(__G__ f)
+    __GDEF
+    int f;                    /* file descriptor for which to turn echo off */
+{
+    struct sgttyb sg;         /* tty device structure */
+
+    GLOBAL(echofd) = f;
+    GTTY(f, &sg);             /* get settings */
+    sg.sg_flags &= ~ECHO;     /* turn echo off */
+    STTY(f, &sg);
+}
+
+/*
+ * Turn echo back on for file descriptor echofd.
+ */
+void Echon(__G)
+    __GDEF
+{
+    struct sgttyb sg;         /* tty device structure */
+
+    if (GLOBAL(echofd) != -1) {
+        GTTY(GLOBAL(echofd), &sg);    /* get settings */
+        sg.sg_flags |= ECHO;  /* turn echo on */
+        STTY(GLOBAL(echofd), &sg);
+        GLOBAL(echofd) = -1;
+    }
+}
+
+#endif /* !CMS_MVS */
+#endif /* ?VMS */
+
+
+#if (defined(UNZIP) && !defined(FUNZIP))
+
+#if (defined(UNIX) || defined(__BEOS__))
+#ifdef MORE
+
+/*
+ * Get the number of lines on the output terminal.  SCO Unix apparently
+ * defines TIOCGWINSZ but doesn't support it (!M_UNIX).
+ *
+ * GRR:  will need to know width of terminal someday, too, to account for
+ *       line-wrapping.
+ */
+
+#if (defined(TIOCGWINSZ) && !defined(M_UNIX))
+
+int screenlines()
+{
+    struct winsize wsz;
+#ifdef DEBUG_WINSZ
+    static int firsttime = TRUE;
+#endif
+
+    /* see termio(4) under, e.g., SunOS */
+    if (ioctl(1, TIOCGWINSZ, &wsz) == 0) {
+#ifdef DEBUG_WINSZ
+        if (firsttime) {
+            firsttime = FALSE;
+            fprintf(stderr, "ttyio.c screenlines():  ws_row = %d\n",
+              wsz.ws_row);
+        }
+#endif
+        /* number of columns = ws_col */
+        return (wsz.ws_row > 0)? wsz.ws_row : 24;   /* number of rows */
+
+    } else {         /* this happens when piping to more(1), for example */
+#ifdef DEBUG_WINSZ
+        if (firsttime) {
+            firsttime = FALSE;
+            fprintf(stderr,
+              "ttyio.c screenlines():  ioctl(TIOCGWINSZ) failed\n"));
+        }
+#endif
+        return 24;   /* VT-100 assumed to be minimal hardware */
+    }
+}
+
+#else /* !TIOCGWINSZ: service not available, fall back to semi-bogus method */
+
+int screenlines()
+{
+    char *envptr, *getenv();
+    int n;
+
+    /* GRR:  this is overly simplistic, but don't have access to stty/gtty
+     * system anymore
+     */
+    envptr = getenv("LINES");
+    if (envptr == (char *)NULL || (n = atoi(envptr)) < 5)
+        return 24;   /* VT-100 assumed to be minimal hardware */
+    else
+        return n;
+}
+
+#endif /* ?(TIOCGWINSZ && !M_UNIX) */
+#endif /* MORE */
+
+
+/*
+ * Get a character from the given file descriptor without echo or newline.
+ */
+int zgetch(__G__ f)
+    __GDEF
+    int f;                      /* file descriptor from which to read */
+{
+#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
+    char oldmin, oldtim;
+#endif
+    char c;
+    struct sgttyb sg;           /* tty device structure */
+
+    GTTY(f, &sg);               /* get settings */
+#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
+    oldmin = sg.c_cc[VMIN];     /* save old values */
+    oldtim = sg.c_cc[VTIME];
+    sg.c_cc[VMIN] = 1;          /* need only one char to return read() */
+    sg.c_cc[VTIME] = 0;         /* no timeout */
+    sg.sg_flags &= ~ICANON;     /* canonical mode off */
+#else
+    sg.sg_flags |= CBREAK;      /* cbreak mode on */
+#endif
+    sg.sg_flags &= ~ECHO;       /* turn echo off, too */
+    STTY(f, &sg);               /* set cbreak mode */
+    GLOBAL(echofd) = f;         /* in case ^C hit (not perfect: still CBREAK) */
+
+    read(f, &c, 1);             /* read our character */
+
+#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))
+    sg.c_cc[VMIN] = oldmin;     /* restore old values */
+    sg.c_cc[VTIME] = oldtim;
+    sg.sg_flags |= ICANON;      /* canonical mode on */
+#else
+    sg.sg_flags &= ~CBREAK;     /* cbreak mode off */
+#endif
+    sg.sg_flags |= ECHO;        /* turn echo on */
+    STTY(f, &sg);               /* restore canonical mode */
+    GLOBAL(echofd) = -1;
+
+    return (int)c;
+}
+
+
+#else /* !UNIX && !__BEOS__ */
+
+
+int zgetch(__G__ f)
+    __GDEF
+    int f;    /* file descriptor from which to read (must be open already) */
+{
+    char c, c2;
+
+/*---------------------------------------------------------------------------
+    Get a character from the given file descriptor without echo; can't fake
+    CBREAK mode (i.e., newline required), but can get rid of all chars up to
+    and including newline.
+  ---------------------------------------------------------------------------*/
+
+    echoff(f);
+    read(f, &c, 1);
+    if (c != '\n')
+        do {
+            read(f, &c2, 1);   /* throw away all other chars up thru newline */
+        } while (c2 != '\n');
+    echon();
+    return (int)c;
+}
+
+#endif /* ?(UNIX || __BEOS__) */
+
+#endif /* UNZIP && !FUNZIP */
+#endif /* !HAVE_WORKING_GETCH */
+
+
+#if CRYPT                       /* getp() is only used with full encryption */
+
+/*
+ * Simple compile-time check for source compatibility between
+ * zcrypt and ttyio:
+ */
+#if (!defined(CR_MAJORVER) || (CR_MAJORVER < 2) || (CR_MINORVER < 7))
+   error:  This Info-ZIP tool requires zcrypt 2.7 or later.
+#endif
+
+/*
+ * Get a password of length n-1 or less into *p using the prompt *m.
+ * The entered password is not echoed.
+ */
+
+#ifdef HAVE_WORKING_GETCH
+/*
+ * For the AMIGA, getch() is defined as Agetch(), which is in
+ * amiga/filedate.c; SAS/C 6.x provides a getch(), but since Agetch()
+ * uses the infrastructure that is already in place in filedate.c, it is
+ * smaller.  With this function, echoff() and echon() are not needed.
+ *
+ * For the MAC, a non-echo macgetch() function is defined in the MacOS
+ * specific sources which uses the event handling mechanism of the
+ * desktop window manager to get a character from the keyboard.
+ *
+ * For the other systems in this section, a non-echo getch() function
+ * is either contained the C runtime library (conio package), or getch()
+ * is defined as an alias for a similar system specific RTL function.
+ */
+
+#ifndef WINDLL   /* WINDLL does not support a console interface */
+#ifndef QDOS     /* QDOS supplies a variant of this function */
+
+/* This is the getp() function for all systems (with TTY type user interface)
+ * that supply a working `non-echo' getch() function for "raw" console input.
+ */
+char *getp(__G__ m, p, n)
+    __GDEF
+    ZCONST char *m;             /* prompt for password */
+    char *p;                    /* return value: line input */
+    int n;                      /* bytes available in p[] */
+{
+    char c;                     /* one-byte buffer for read() to use */
+    int i;                      /* number of characters input */
+    char *w;                    /* warning on retry */
+
+    /* get password */
+    w = "";
+    do {
+        fputs(w, stderr);       /* warning if back again */
+        fputs(m, stderr);       /* display prompt and flush */
+        fflush(stderr);
+        i = 0;
+        do {                    /* read line, keeping first n characters */
+            if ((c = (char)getch()) == '\r')
+                c = '\n';       /* until user hits CR */
+            if (c == 8 || c == 127) {
+                if (i > 0) i--; /* the `backspace' and `del' keys works */
+            }
+            else if (i < n)
+                p[i++] = c;     /* truncate past n */
+        } while (c != '\n');
+        PUTC('\n', stderr);  fflush(stderr);
+        w = "(line too long--try again)\n";
+    } while (p[i-1] != '\n');
+    p[i-1] = 0;                 /* terminate at newline */
+
+    return p;                   /* return pointer to password */
+
+} /* end function getp() */
+
+#endif /* !QDOS */
+#endif /* !WINDLL */
+
+
+#else /* !HAVE_WORKING_GETCH */
+
+
+#if (defined(UNIX) || defined(__MINT__) || defined(__BEOS__))
+
+#ifndef _PATH_TTY
+#  ifdef __MINT__
+#    define _PATH_TTY ttyname(2)
+#  else
+#    define _PATH_TTY "/dev/tty"
+#  endif
+#endif
+
+char *getp(__G__ m, p, n)
+    __GDEF
+    ZCONST char *m;             /* prompt for password */
+    char *p;                    /* return value: line input */
+    int n;                      /* bytes available in p[] */
+{
+    char c;                     /* one-byte buffer for read() to use */
+    int i;                      /* number of characters input */
+    char *w;                    /* warning on retry */
+    int f;                      /* file descriptor for tty device */
+
+#ifdef PASSWD_FROM_STDIN
+    /* Read from stdin. This is unsafe if the password is stored on disk. */
+    f = 0;
+#else
+    /* turn off echo on tty */
+
+    if ((f = open(_PATH_TTY, 0)) == -1)
+        return NULL;
+#endif
+    /* get password */
+    w = "";
+    do {
+        fputs(w, stderr);       /* warning if back again */
+        fputs(m, stderr);       /* prompt */
+        fflush(stderr);
+        i = 0;
+        echoff(f);
+        do {                    /* read line, keeping n */
+            read(f, &c, 1);
+            if (i < n)
+                p[i++] = c;
+        } while (c != '\n');
+        echon();
+        PUTC('\n', stderr);  fflush(stderr);
+        w = "(line too long--try again)\n";
+    } while (p[i-1] != '\n');
+    p[i-1] = 0;                 /* terminate at newline */
+
+#ifndef PASSWD_FROM_STDIN
+    close(f);
+#endif
+
+    return p;                   /* return pointer to password */
+
+} /* end function getp() */
+
+#endif /* UNIX || __MINT__ || __BEOS__ */
+
+
+
+#if (defined(VMS) || defined(CMS_MVS))
+
+char *getp(__G__ m, p, n)
+    __GDEF
+    ZCONST char *m;             /* prompt for password */
+    char *p;                    /* return value: line input */
+    int n;                      /* bytes available in p[] */
+{
+    char c;                     /* one-byte buffer for read() to use */
+    int i;                      /* number of characters input */
+    char *w;                    /* warning on retry */
+    FILE *f;                    /* file structure for SYS$COMMAND device */
+
+#ifdef PASSWD_FROM_STDIN
+    f = stdin;
+#else
+    if ((f = fopen(ctermid(NULL), "r")) == NULL)
+        return NULL;
+#endif
+
+    /* get password */
+    fflush(stdout);
+    w = "";
+    do {
+        if (*w)                 /* bug: VMS apparently adds \n to NULL fputs */
+            fputs(w, stderr);   /* warning if back again */
+        fputs(m, stderr);       /* prompt */
+        fflush(stderr);
+        i = 0;
+        echoff(f);
+        do {                    /* read line, keeping n */
+            if ((c = (char)getc(f)) == '\r')
+                c = '\n';
+            if (i < n)
+                p[i++] = c;
+        } while (c != '\n');
+        echon();
+        PUTC('\n', stderr);  fflush(stderr);
+        w = "(line too long--try again)\n";
+    } while (p[i-1] != '\n');
+    p[i-1] = 0;                 /* terminate at newline */
+#ifndef PASSWD_FROM_STDIN
+    fclose(f);
+#endif
+
+    return p;                   /* return pointer to password */
+
+} /* end function getp() */
+
+#endif /* VMS || CMS_MVS */
+#endif /* ?HAVE_WORKING_GETCH */
+#endif /* CRYPT */
+#endif /* CRYPT || (UNZIP && !FUNZIP) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/unix.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,1428 @@
+/*---------------------------------------------------------------------------
+
+  unix.c
+
+  Unix-specific routines for use with Info-ZIP's UnZip 5.3 and later.
+
+  Contains:  readdir()
+             do_wild()           <-- generic enough to put in fileio.c?
+             mapattr()
+             mapname()
+             checkdir()
+             mkdir()
+             close_outfile()
+             set_direc_attribs()
+             stamp_file()
+             version()
+
+  ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+
+#ifdef SCO_XENIX
+#  define SYSNDIR
+#else  /* SCO Unix, AIX, DNIX, TI SysV, Coherent 4.x, ... */
+#  if defined(__convexc__) || defined(SYSV) || defined(CRAY) || defined(BSD4_4)
+#    define DIRENT
+#  endif
+#endif
+#if defined(_AIX)
+#  define DIRENT
+#endif
+#ifdef COHERENT
+#  if defined(_I386) || (defined(__COHERENT__) && (__COHERENT__ >= 0x420))
+#    define DIRENT
+#  endif
+#endif
+
+/* GRR:  may need to uncomment this: */
+#if 0
+#if defined(_POSIX_VERSION)
+#  define DIRENT
+#endif
+#endif
+
+#ifdef DIRENT
+#  include <dirent.h>
+#else
+#  ifdef SYSV
+#    ifdef SYSNDIR
+#      include <sys/ndir.h>
+#    else
+#      include <ndir.h>
+#    endif
+#  else /* !SYSV */
+#    ifndef NO_SYSDIR
+#      include <sys/dir.h>
+#    endif
+#  endif /* ?SYSV */
+#  ifndef dirent
+#    define dirent direct
+#  endif
+#endif /* ?DIRENT */
+
+#ifdef ACORN_FTYPE_NFS
+/* Acorn bits for NFS filetyping */
+typedef struct {
+  uch ID[2];
+  uch size[2];
+  uch ID_2[4];
+  uch loadaddr[4];
+  uch execaddr[4];
+  uch attr[4];
+} RO_extra_block;
+
+static int isRISCOSexfield OF((uch *extra_field));
+#endif /* ACORN_FTYPE_NFS */
+
+static int created_dir;        /* used in mapname(), checkdir() */
+static int renamed_fullpath;   /* ditto */
+
+
+#ifndef SFX
+#ifdef NO_DIR                  /* for AT&T 3B1 */
+
+#define opendir(path) fopen(path,"r")
+#define closedir(dir) fclose(dir)
+typedef FILE DIR;
+
+/*
+ *  Apparently originally by Rich Salz.
+ *  Cleaned up and modified by James W. Birdsall.
+ */
+struct dirent *readdir(dirp)
+    DIR *dirp;
+{
+    static struct dirent entry;
+
+    if (dirp == NULL)
+        return NULL;
+
+    for (;;)
+        if (fread(&entry, sizeof (struct dirent), 1, dirp) == 0)
+            return (struct dirent *)NULL;
+        else if (entry.d_ino)
+            return &entry;
+
+} /* end function readdir() */
+
+#endif /* NO_DIR */
+
+
+/**********************/
+/* Function do_wild() */   /* for porting:  dir separator; match(ignore_case) */
+/**********************/
+
+char *do_wild(__G__ wildspec)
+    __GDEF
+    char *wildspec;         /* only used first time on a given dir */
+{
+    static DIR *dir = (DIR *)NULL;
+    static char *dirname, *wildname, matchname[FILNAMSIZ];
+    static int firstcall=TRUE, have_dirname, dirnamelen;
+    struct dirent *file;
+
+
+    /* Even when we're just returning wildspec, we *always* do so in
+     * matchname[]--calling routine is allowed to append four characters
+     * to the returned string, and wildspec may be a pointer to argv[].
+     */
+    if (firstcall) {        /* first call:  must initialize everything */
+        firstcall = FALSE;
+
+        if (!iswild(wildspec)) {
+            strcpy(matchname, wildspec);
+            have_dirname = FALSE;
+            dir = NULL;
+            return matchname;
+        }
+
+        /* break the wildspec into a directory part and a wildcard filename */
+        if ((wildname = strrchr(wildspec, '/')) == (char *)NULL) {
+            dirname = ".";
+            dirnamelen = 1;
+            have_dirname = FALSE;
+            wildname = wildspec;
+        } else {
+            ++wildname;     /* point at character after '/' */
+            dirnamelen = wildname - wildspec;
+            if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) {
+                Info(slide, 0x201, ((char *)slide,
+                  "warning:  cannot allocate wildcard buffers\n"));
+                strcpy(matchname, wildspec);
+                return matchname;   /* but maybe filespec was not a wildcard */
+            }
+            strncpy(dirname, wildspec, dirnamelen);
+            dirname[dirnamelen] = '\0';   /* terminate for strcpy below */
+            have_dirname = TRUE;
+        }
+
+        if ((dir = opendir(dirname)) != (DIR *)NULL) {
+            while ((file = readdir(dir)) != (struct dirent *)NULL) {
+                Trace((stderr, "do_wild:  readdir returns %s\n", file->d_name));
+                if (file->d_name[0] == '.' && wildname[0] != '.')
+                    continue;  /* Unix:  '*' and '?' do not match leading dot */
+                if (match(file->d_name, wildname, 0) &&  /* 0 == case sens. */
+                    /* skip "." and ".." directory entries */
+                    strcmp(file->d_name, ".") && strcmp(file->d_name, "..")) {
+                    Trace((stderr, "do_wild:  match() succeeds\n"));
+                    if (have_dirname) {
+                        strcpy(matchname, dirname);
+                        strcpy(matchname+dirnamelen, file->d_name);
+                    } else
+                        strcpy(matchname, file->d_name);
+                    return matchname;
+                }
+            }
+            /* if we get to here directory is exhausted, so close it */
+            closedir(dir);
+            dir = (DIR *)NULL;
+        }
+
+        /* return the raw wildspec in case that works (e.g., directory not
+         * searchable, but filespec was not wild and file is readable) */
+        strcpy(matchname, wildspec);
+        return matchname;
+    }
+
+    /* last time through, might have failed opendir but returned raw wildspec */
+    if (dir == (DIR *)NULL) {
+        firstcall = TRUE;  /* nothing left to try--reset for new wildspec */
+        if (have_dirname)
+            free(dirname);
+        return (char *)NULL;
+    }
+
+    /* If we've gotten this far, we've read and matched at least one entry
+     * successfully (in a previous call), so dirname has been copied into
+     * matchname already.
+     */
+    while ((file = readdir(dir)) != (struct dirent *)NULL) {
+        Trace((stderr, "do_wild:  readdir returns %s\n", file->d_name));
+        if (file->d_name[0] == '.' && wildname[0] != '.')
+            continue;   /* Unix:  '*' and '?' do not match leading dot */
+        if (match(file->d_name, wildname, 0)) {   /* 0 == don't ignore case */
+            Trace((stderr, "do_wild:  match() succeeds\n"));
+            if (have_dirname) {
+                /* strcpy(matchname, dirname); */
+                strcpy(matchname+dirnamelen, file->d_name);
+            } else
+                strcpy(matchname, file->d_name);
+            return matchname;
+        }
+    }
+
+    closedir(dir);     /* have read at least one dir entry; nothing left */
+    dir = (DIR *)NULL;
+    firstcall = TRUE;  /* reset for new wildspec */
+    if (have_dirname)
+        free(dirname);
+    return (char *)NULL;
+
+} /* end function do_wild() */
+
+#endif /* !SFX */
+
+
+
+
+
+/**********************/
+/* Function mapattr() */
+/**********************/
+
+int mapattr(__G)
+    __GDEF
+{
+    ulg tmp = G.crec.external_file_attributes;
+
+    G.pInfo->file_attr = 0;
+    /* initialized to 0 for check in "default" branch below... */
+
+    switch (G.pInfo->hostnum) {
+        case AMIGA_:
+            tmp = (unsigned)(tmp>>17 & 7);   /* Amiga RWE bits */
+            G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp);
+            break;
+        case UNIX_:
+        case VMS_:
+        case ACORN_:
+        case ATARI_:
+        case BEOS_:
+        case QDOS_:
+        case TANDEM_:
+            G.pInfo->file_attr = (unsigned)(tmp >> 16);
+            if (G.pInfo->file_attr != 0 || !G.extra_field) {
+                return 0;
+            } else {
+                /* Some (non-Info-ZIP) implementations of Zip for Unix and
+                 * VMS (and probably others ??) leave 0 in the upper 16-bit
+                 * part of the external_file_attributes field. Instead, they
+                 * store file permission attributes in some extra field.
+                 * As a work-around, we search for the presence of one of
+                 * these extra fields and fall back to the MSDOS compatible
+                 * part of external_file_attributes if one of the known
+                 * e.f. types has been detected.
+                 * Later, we might implement extraction of the permission
+                 * bits from the VMS extra field. But for now, the work-around
+                 * should be sufficient to provide "readable" extracted files.
+                 * (For ASI Unix e.f., an experimental remap from the e.f.
+                 * mode value IS already provided!)
+                 */
+                ush ebID;
+                unsigned ebLen;
+                uch *ef = G.extra_field;
+                unsigned ef_len = G.crec.extra_field_length;
+                int r = FALSE;
+
+                while (!r && ef_len >= EB_HEADSIZE) {
+                    ebID = makeword(ef);
+                    ebLen = (unsigned)makeword(ef+EB_LEN);
+                    if (ebLen > (ef_len - EB_HEADSIZE))
+                        /* discoverd some e.f. inconsistency! */
+                        break;
+                    switch (ebID) {
+                      case EF_ASIUNIX:
+                        if (ebLen >= (EB_ASI_MODE+2)) {
+                            G.pInfo->file_attr =
+                              (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE));
+                            /* force stop of loop: */
+                            ef_len = (ebLen + EB_HEADSIZE);
+                            break;
+                        }
+                        /* else: fall through! */
+                      case EF_PKVMS:
+                        /* "found nondecypherable e.f. with perm. attr" */
+                        r = TRUE;
+                      default:
+                        break;
+                    }
+                    ef_len -= (ebLen + EB_HEADSIZE);
+                    ef += (ebLen + EB_HEADSIZE);
+                }
+                if (!r)
+                    return 0;
+            }
+            /* fall through! */
+        /* all remaining cases:  expand MSDOS read-only bit into write perms */
+        case FS_FAT_:
+            /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the
+             * Unix attributes in the upper 16 bits of the external attributes
+             * field, just like Info-ZIP's Zip for Unix.  We try to use that
+             * value, after a check for consistency with the MSDOS attribute
+             * bits (see below).
+             */
+            G.pInfo->file_attr = (unsigned)(tmp >> 16);
+            /* fall through! */
+        case FS_HPFS_:
+        case FS_NTFS_:
+        case MAC_:
+        case TOPS20_:
+        default:
+            /* read-only bit --> write perms; subdir bit --> dir exec bit */
+            tmp = !(tmp & 1) << 1  |  (tmp & 0x10) >> 4;
+            if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6))
+                /* keep previous G.pInfo->file_attr setting, when its "owner"
+                 * part appears to be consistent with DOS attribute flags!
+                 */
+                return 0;
+            G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp);
+            break;
+    } /* end switch (host-OS-created-by) */
+
+    /* for originating systems with no concept of "group," "other," "system": */
+    umask( (int)(tmp=umask(0)) );    /* apply mask to expanded r/w(/x) perms */
+    G.pInfo->file_attr &= ~tmp;
+
+    return 0;
+
+} /* end function mapattr() */
+
+
+
+
+
+/************************/
+/*  Function mapname()  */
+/************************/
+                             /* return 0 if no error, 1 if caution (filename */
+int mapname(__G__ renamed)   /*  truncated), 2 if warning (skip file because */
+    __GDEF                   /*  dir doesn't exist), 3 if error (skip file), */
+    int renamed;             /*  or 10 if out of memory (skip file) */
+{                            /*  [also IZ_VOL_LABEL, IZ_CREATED_DIR] */
+    char pathcomp[FILNAMSIZ];      /* path-component buffer */
+    char *pp, *cp=(char *)NULL;    /* character pointers */
+    char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */
+#ifdef ACORN_FTYPE_NFS
+    char *lastcomma=(char *)NULL;  /* pointer to last comma in pathcomp */
+#endif
+    int quote = FALSE;             /* flags */
+    int error = 0;
+    register unsigned workch;      /* hold the character being tested */
+
+
+/*---------------------------------------------------------------------------
+    Initialize various pointers and counters and stuff.
+  ---------------------------------------------------------------------------*/
+
+    if (G.pInfo->vollabel)
+        return IZ_VOL_LABEL;    /* can't set disk volume labels in Unix */
+
+    /* can create path as long as not just freshening, or if user told us */
+    G.create_dirs = (!uO.fflag || renamed);
+
+    created_dir = FALSE;        /* not yet */
+
+    /* user gave full pathname:  don't prepend rootpath */
+    renamed_fullpath = (renamed && (*G.filename == '/'));
+
+    if (checkdir(__G__ (char *)NULL, INIT) == 10)
+        return 10;              /* initialize path buffer, unless no memory */
+
+    *pathcomp = '\0';           /* initialize translation buffer */
+    pp = pathcomp;              /* point to translation buffer */
+    if (uO.jflag)               /* junking directories */
+        cp = (char *)strrchr(G.filename, '/');
+    if (cp == (char *)NULL)     /* no '/' or not junking dirs */
+        cp = G.filename;        /* point to internal zipfile-member pathname */
+    else
+        ++cp;                   /* point to start of last component of path */
+
+/*---------------------------------------------------------------------------
+    Begin main loop through characters in filename.
+  ---------------------------------------------------------------------------*/
+
+    while ((workch = (uch)*cp++) != 0) {
+
+        if (quote) {                 /* if character quoted, */
+            *pp++ = (char)workch;    /*  include it literally */
+            quote = FALSE;
+        } else
+            switch (workch) {
+            case '/':             /* can assume -j flag not given */
+                *pp = '\0';
+                if ((error = checkdir(__G__ pathcomp, APPEND_DIR)) > 1)
+                    return error;
+                pp = pathcomp;    /* reset conversion buffer for next piece */
+                lastsemi = (char *)NULL; /* leave directory semi-colons alone */
+                break;
+
+            case ';':             /* VMS version (or DEC-20 attrib?) */
+                lastsemi = pp;
+                *pp++ = ';';      /* keep for now; remove VMS ";##" */
+                break;            /*  later, if requested */
+
+#ifdef ACORN_FTYPE_NFS
+            case ',':             /* NFS filetype extension */
+                lastcomma = pp;
+                *pp++ = ',';      /* keep for now; may need to remove */
+                break;            /*  later, if requested */
+#endif
+
+            case '\026':          /* control-V quote for special chars */
+                quote = TRUE;     /* set flag for next character */
+                break;
+
+#ifdef MTS
+            case ' ':             /* change spaces to underscore under */
+                *pp++ = '_';      /*  MTS; leave as spaces under Unix */
+                break;
+#endif
+
+            default:
+                /* allow European characters in filenames: */
+                if (isprint(workch) || (128 <= workch && workch <= 254))
+                    *pp++ = (char)workch;
+            } /* end switch */
+
+    } /* end while loop */
+
+    *pp = '\0';                   /* done with pathcomp:  terminate it */
+
+    /* if not saving them, remove VMS version numbers (appended ";###") */
+    if (!uO.V_flag && lastsemi) {
+        pp = lastsemi + 1;
+        while (isdigit((uch)(*pp)))
+            ++pp;
+        if (*pp == '\0')          /* only digits between ';' and end:  nuke */
+            *lastsemi = '\0';
+    }
+
+#ifdef ACORN_FTYPE_NFS
+    /* translate Acorn filetype information if asked to do so */
+    if (uO.acorn_nfs_ext && isRISCOSexfield(G.extra_field)) {
+        /* file *must* have a RISC OS extra field */
+        int ft = (int)makelong(((RO_extra_block *)G.extra_field)->loadaddr);
+        /*32-bit*/
+        if (lastcomma) {
+            pp = lastcomma + 1;
+            while (isxdigit((uch)(*pp))) ++pp;
+            if (pp == lastcomma+4 && *pp == '\0') *lastcomma='\0'; /* nuke */
+        }
+        if ((ft & 1<<31)==0) ft=0x000FFD00;
+        sprintf(pathcomp+strlen(pathcomp), ",%03x", ft>>8 & 0xFFF);
+    }
+#endif /* ACORN_FTYPE_NFS */
+
+/*---------------------------------------------------------------------------
+    Report if directory was created (and no file to create:  filename ended
+    in '/'), check name to be sure it exists, and combine path and name be-
+    fore exiting.
+  ---------------------------------------------------------------------------*/
+
+    if (G.filename[strlen(G.filename) - 1] == '/') {
+        checkdir(__G__ G.filename, GETPATH);
+        if (created_dir) {
+            if (QCOND2) {
+                Info(slide, 0, ((char *)slide, "   creating: %s\n",
+                  G.filename));
+            }
+#ifndef NO_CHMOD
+            /* set approx. dir perms (make sure can still read/write in dir) */
+            if (chmod(G.filename, (0xffff & G.pInfo->file_attr) | 0700))
+                perror("chmod (directory attributes) error");
+#endif
+            return IZ_CREATED_DIR;   /* set dir time (note trailing '/') */
+        }
+        return 2;   /* dir existed already; don't look for data to extract */
+    }
+
+    if (*pathcomp == '\0') {
+        Info(slide, 1, ((char *)slide, "mapname:  conversion of %s failed\n",
+          G.filename));
+        return 3;
+    }
+
+    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */
+    checkdir(__G__ G.filename, GETPATH);
+
+    return error;
+
+} /* end function mapname() */
+
+
+
+
+#if 0  /*========== NOTES ==========*/
+
+  extract-to dir:      a:path/
+  buildpath:           path1/path2/ ...   (NULL-terminated)
+  pathcomp:                filename
+
+  mapname():
+    loop over chars in zipfile member name
+      checkdir(path component, COMPONENT | CREATEDIR) --> map as required?
+        (d:/tmp/unzip/)                    (disk:[tmp.unzip.)
+        (d:/tmp/unzip/jj/)                 (disk:[tmp.unzip.jj.)
+        (d:/tmp/unzip/jj/temp/)            (disk:[tmp.unzip.jj.temp.)
+    finally add filename itself and check for existence? (could use with rename)
+        (d:/tmp/unzip/jj/temp/msg.outdir)  (disk:[tmp.unzip.jj.temp]msg.outdir)
+    checkdir(name, GETPATH)     -->  copy path to name and free space
+
+#endif /* 0 */
+
+
+
+
+/***********************/
+/* Function checkdir() */
+/***********************/
+
+int checkdir(__G__ pathcomp, flag)
+    __GDEF
+    char *pathcomp;
+    int flag;
+/*
+ * returns:  1 - (on APPEND_NAME) truncated filename
+ *           2 - path doesn't exist, not allowed to create
+ *           3 - path doesn't exist, tried to create and failed; or
+ *               path exists and is not a directory, but is supposed to be
+ *           4 - path is too long
+ *          10 - can't allocate memory for filename buffers
+ */
+{
+    static int rootlen = 0;   /* length of rootpath */
+    static char *rootpath;    /* user's "extract-to" directory */
+    static char *buildpath;   /* full path (so far) to extracted file */
+    static char *end;         /* pointer to end of buildpath ('\0') */
+
+#   define FN_MASK   7
+#   define FUNCTION  (flag & FN_MASK)
+
+
+
+/*---------------------------------------------------------------------------
+    APPEND_DIR:  append the path component to the path being built and check
+    for its existence.  If doesn't exist and we are creating directories, do
+    so for this one; else signal success or error as appropriate.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == APPEND_DIR) {
+        int too_long = FALSE;
+#ifdef SHORT_NAMES
+        char *old_end = end;
+#endif
+
+        Trace((stderr, "appending dir segment [%s]\n", pathcomp));
+        while ((*end = *pathcomp++) != '\0')
+            ++end;
+#ifdef SHORT_NAMES   /* path components restricted to 14 chars, typically */
+        if ((end-old_end) > FILENAME_MAX)  /* GRR:  proper constant? */
+            *(end = old_end + FILENAME_MAX) = '\0';
+#endif
+
+        /* GRR:  could do better check, see if overrunning buffer as we go:
+         * check end-buildpath after each append, set warning variable if
+         * within 20 of FILNAMSIZ; then if var set, do careful check when
+         * appending.  Clear variable when begin new path. */
+
+        if ((end-buildpath) > FILNAMSIZ-3)  /* need '/', one-char name, '\0' */
+            too_long = TRUE;                /* check if extracting directory? */
+        if (stat(buildpath, &G.statbuf)) {  /* path doesn't exist */
+            if (!G.create_dirs) { /* told not to create (freshening) */
+                free(buildpath);
+                return 2;         /* path doesn't exist:  nothing to do */
+            }
+            if (too_long) {
+                Info(slide, 1, ((char *)slide,
+                  "checkdir error:  path too long: %s\n", buildpath));
+                free(buildpath);
+                return 4;         /* no room for filenames:  fatal */
+            }
+            if (mkdir(buildpath, 0777) == -1) {   /* create the directory */
+                Info(slide, 1, ((char *)slide,
+                  "checkdir error:  cannot create %s\n\
+                 unable to process %s.\n", buildpath, G.filename));
+                free(buildpath);
+                return 3;      /* path didn't exist, tried to create, failed */
+            }
+            created_dir = TRUE;
+        } else if (!S_ISDIR(G.statbuf.st_mode)) {
+            Info(slide, 1, ((char *)slide,
+              "checkdir error:  %s exists but is not directory\n\
+                 unable to process %s.\n", buildpath, G.filename));
+            free(buildpath);
+            return 3;          /* path existed but wasn't dir */
+        }
+        if (too_long) {
+            Info(slide, 1, ((char *)slide,
+              "checkdir error:  path too long: %s\n", buildpath));
+            free(buildpath);
+            return 4;         /* no room for filenames:  fatal */
+        }
+        *end++ = '/';
+        *end = '\0';
+        Trace((stderr, "buildpath now = [%s]\n", buildpath));
+        return 0;
+
+    } /* end if (FUNCTION == APPEND_DIR) */
+
+/*---------------------------------------------------------------------------
+    GETPATH:  copy full path to the string pointed at by pathcomp, and free
+    buildpath.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == GETPATH) {
+        strcpy(pathcomp, buildpath);
+        Trace((stderr, "getting and freeing path [%s]\n", pathcomp));
+        free(buildpath);
+        buildpath = end = (char *)NULL;
+        return 0;
+    }
+
+/*---------------------------------------------------------------------------
+    APPEND_NAME:  assume the path component is the filename; append it and
+    return without checking for existence.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == APPEND_NAME) {
+#ifdef SHORT_NAMES
+        char *old_end = end;
+#endif
+
+        Trace((stderr, "appending filename [%s]\n", pathcomp));
+        while ((*end = *pathcomp++) != '\0') {
+            ++end;
+#ifdef SHORT_NAMES  /* truncate name at 14 characters, typically */
+            if ((end-old_end) > FILENAME_MAX)      /* GRR:  proper constant? */
+                *(end = old_end + FILENAME_MAX) = '\0';
+#endif
+            if ((end-buildpath) >= FILNAMSIZ) {
+                *--end = '\0';
+                Info(slide, 0x201, ((char *)slide,
+                  "checkdir warning:  path too long; truncating\n\
+                   %s\n                -> %s\n", G.filename, buildpath));
+                return 1;   /* filename truncated */
+            }
+        }
+        Trace((stderr, "buildpath now = [%s]\n", buildpath));
+        return 0;  /* could check for existence here, prompt for new name... */
+    }
+
+/*---------------------------------------------------------------------------
+    INIT:  allocate and initialize buffer space for the file currently being
+    extracted.  If file was renamed with an absolute path, don't prepend the
+    extract-to path.
+  ---------------------------------------------------------------------------*/
+
+/* GRR:  for VMS and TOPS-20, add up to 13 to strlen */
+
+    if (FUNCTION == INIT) {
+        Trace((stderr, "initializing buildpath to "));
+#ifdef ACORN_FTYPE_NFS
+        if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+
+                                        (uO.acorn_nfs_ext ? 5 : 1)))
+#else
+        if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+1))
+#endif
+            == (char *)NULL)
+            return 10;
+        if ((rootlen > 0) && !renamed_fullpath) {
+            strcpy(buildpath, rootpath);
+            end = buildpath + rootlen;
+        } else {
+            *buildpath = '\0';
+            end = buildpath;
+        }
+        Trace((stderr, "[%s]\n", buildpath));
+        return 0;
+    }
+
+/*---------------------------------------------------------------------------
+    ROOT:  if appropriate, store the path in rootpath and create it if neces-
+    sary; else assume it's a zipfile member and return.  This path segment
+    gets used in extracting all members from every zipfile specified on the
+    command line.
+  ---------------------------------------------------------------------------*/
+
+#if (!defined(SFX) || defined(SFX_EXDIR))
+    if (FUNCTION == ROOT) {
+        Trace((stderr, "initializing root path to [%s]\n", pathcomp));
+        if (pathcomp == (char *)NULL) {
+            rootlen = 0;
+            return 0;
+        }
+        if ((rootlen = strlen(pathcomp)) > 0) {
+            if (pathcomp[rootlen-1] == '/') {
+                pathcomp[--rootlen] = '\0';
+            }
+            if (rootlen > 0 && (stat(pathcomp, &G.statbuf) ||
+                !S_ISDIR(G.statbuf.st_mode)))       /* path does not exist */
+            {
+                if (!G.create_dirs /* || iswild(pathcomp) */ ) {
+                    rootlen = 0;
+                    return 2;   /* skip (or treat as stored file) */
+                }
+                /* create the directory (could add loop here to scan pathcomp
+                 * and create more than one level, but why really necessary?) */
+                if (mkdir(pathcomp, 0777) == -1) {
+                    Info(slide, 1, ((char *)slide,
+                      "checkdir:  cannot create extraction directory: %s\n",
+                      pathcomp));
+                    rootlen = 0;   /* path didn't exist, tried to create, and */
+                    return 3;  /* failed:  file exists, or 2+ levels required */
+                }
+            }
+            if ((rootpath = (char *)malloc(rootlen+2)) == (char *)NULL) {
+                rootlen = 0;
+                return 10;
+            }
+            strcpy(rootpath, pathcomp);
+            rootpath[rootlen++] = '/';
+            rootpath[rootlen] = '\0';
+            Trace((stderr, "rootpath now = [%s]\n", rootpath));
+        }
+        return 0;
+    }
+#endif /* !SFX || SFX_EXDIR */
+
+/*---------------------------------------------------------------------------
+    END:  free rootpath, immediately prior to program exit.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == END) {
+        Trace((stderr, "freeing rootpath\n"));
+        if (rootlen > 0) {
+            free(rootpath);
+            rootlen = 0;
+        }
+        return 0;
+    }
+
+    return 99;  /* should never reach */
+
+} /* end function checkdir() */
+
+
+
+
+
+#ifdef NO_MKDIR
+
+/********************/
+/* Function mkdir() */
+/********************/
+
+int mkdir(path, mode)
+    char *path;
+    int mode;   /* ignored */
+/*
+ * returns:   0 - successful
+ *           -1 - failed (errno not set, however)
+ */
+{
+    char command[FILNAMSIZ+40]; /* buffer for system() call */
+
+    /* GRR 930416:  added single quotes around path to avoid bug with
+     * creating directories with ampersands in name; not yet tested */
+    sprintf(command, "IFS=\" \t\n\" /bin/mkdir '%s' 2>/dev/null", path);
+    if (system(command))
+        return -1;
+    return 0;
+}
+
+#endif /* NO_MKDIR */
+
+
+
+
+
+#if 0
+#ifdef MORE
+
+/**************************/
+/* Function screenlines() */
+/**************************/
+
+int screenlines()
+{
+    char *envptr, *getenv();
+    int n;
+
+    /* GRR:  this is overly simplistic; should use winsize struct and
+     * appropriate TIOCGWINSZ ioctl(), assuming exists on enough systems
+     */
+    envptr = getenv("LINES");
+    if (envptr == (char *)NULL || (n = atoi(envptr)) < 5)
+        return 24;   /* VT-100 assumed to be minimal hardware */
+    else
+        return n;
+}
+
+#endif /* MORE */
+#endif /* 0 */
+
+
+
+
+
+#ifndef MTS
+
+/****************************/
+/* Function close_outfile() */
+/****************************/
+
+void close_outfile(__G)    /* GRR: change to return PK-style warning level */
+    __GDEF
+{
+    iztimes zt;
+    ush z_uidgid[2];
+	unsigned eb_izux_flg;
+	extern int get_image;
+
+	if(get_image)
+		return;
+
+/*---------------------------------------------------------------------------
+    If symbolic links are supported, allocate a storage area, put the uncom-
+    pressed "data" in it, and create the link.  Since we know it's a symbolic
+    link to start with, we shouldn't have to worry about overflowing unsigned
+    ints with unsigned longs.
+  ---------------------------------------------------------------------------*/
+
+#ifdef SYMLINKS
+    if (G.symlnk) {
+        unsigned ucsize = (unsigned)G.lrec.ucsize;
+        char *linktarget = (char *)malloc((unsigned)G.lrec.ucsize+1);
+
+        fclose(G.outfile);                      /* close "data" file... */
+        G.outfile = fopen(G.filename, FOPR);    /* ...and reopen for reading */
+        if (!linktarget || fread(linktarget, 1, ucsize, G.outfile) !=
+                           (int)ucsize)
+        {
+            Info(slide, 0x201, ((char *)slide,
+              "warning:  symbolic link (%s) failed\n", G.filename));
+            if (linktarget)
+                free(linktarget);
+            fclose(G.outfile);
+            return;
+        }
+        fclose(G.outfile);                  /* close "data" file for good... */
+        unlink(G.filename);                 /* ...and delete it */
+        linktarget[ucsize] = '\0';
+        if (QCOND2)
+            Info(slide, 0, ((char *)slide, "-> %s ", linktarget));
+        if (symlink(linktarget, G.filename))  /* create the real link */
+            perror("symlink error");
+        free(linktarget);
+        return;                             /* can't set time on symlinks */
+    }
+#endif /* SYMLINKS */
+
+    fclose(G.outfile);
+#ifdef QLZIP
+    if (G.extra_field) {
+        static void qlfix OF((__GPRO__ uch *ef_ptr, unsigned ef_len));
+
+        qlfix(__G__ G.extra_field, G.lrec.extra_field_length);
+    }
+#endif
+
+/*---------------------------------------------------------------------------
+    Convert from MSDOS-format local time and date to Unix-format 32-bit GMT
+    time:  adjust base year from 1980 to 1970, do usual conversions from
+    yy/mm/dd hh:mm:ss to elapsed seconds, and account for timezone and day-
+    light savings time differences.  If we have a Unix extra field, however,
+    we're laughing:  both mtime and atime are ours.  On the other hand, we
+    then have to check for restoration of UID/GID.
+  ---------------------------------------------------------------------------*/
+
+    eb_izux_flg = (G.extra_field ? ef_scan_for_izux(G.extra_field,
+                   G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime,
+#ifdef IZ_CHECK_TZ
+                   (G.tz_is_valid ? &zt : NULL),
+#else
+                   &zt,
+#endif
+                   z_uidgid) : 0);
+    if (eb_izux_flg & EB_UT_FL_MTIME) {
+        TTrace((stderr, "\nclose_outfile:  Unix e.f. modif. time = %ld\n",
+          zt.mtime));
+    } else {
+        zt.mtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
+    }
+    if (eb_izux_flg & EB_UT_FL_ATIME) {
+        TTrace((stderr, "close_outfile:  Unix e.f. access time = %ld\n",
+          zt.atime));
+    } else {
+        zt.atime = zt.mtime;
+        TTrace((stderr, "\nclose_outfile:  modification/access times = %ld\n",
+          zt.mtime));
+    }
+
+    /* if -X option was specified and we have UID/GID info, restore it */
+    if (uO.X_flag && eb_izux_flg & EB_UX2_VALID) {
+        TTrace((stderr, "close_outfile:  restoring Unix UID/GID info\n"));
+        if (chown(G.filename, (uid_t)z_uidgid[0], (gid_t)z_uidgid[1]))
+        {
+            if (uO.qflag)
+                Info(slide, 0x201, ((char *)slide,
+                  "warning:  cannot set UID %d and/or GID %d for %s\n",
+                  z_uidgid[0], z_uidgid[1], G.filename));
+            else
+                Info(slide, 0x201, ((char *)slide,
+                  " (warning) cannot set UID %d and/or GID %d",
+                  z_uidgid[0], z_uidgid[1]));
+        }
+    }
+
+    /* set the file's access and modification times */
+    if (utime(G.filename, (ztimbuf *)&zt)) {
+#ifdef AOS_VS
+        if (uO.qflag)
+            Info(slide, 0x201, ((char *)slide, "... cannot set time for %s\n",
+              G.filename));
+        else
+            Info(slide, 0x201, ((char *)slide, "... cannot set time"));
+#else
+        if (uO.qflag)
+            Info(slide, 0x201, ((char *)slide,
+              "warning:  cannot set times for %s\n", G.filename));
+        else
+            Info(slide, 0x201, ((char *)slide,
+              " (warning) cannot set times"));
+#endif /* ?AOS_VS */
+    }
+
+/*---------------------------------------------------------------------------
+    Change the file permissions from default ones to those stored in the
+    zipfile.
+  ---------------------------------------------------------------------------*/
+
+#ifndef NO_CHMOD
+    if (chmod(G.filename, 0xffff & G.pInfo->file_attr))
+        perror("chmod (file attributes) error");
+#endif
+
+} /* end function close_outfile() */
+
+#endif /* !MTS */
+
+
+
+
+#ifdef SET_DIR_ATTRIB
+/* messages of code for setting directory attributes */
+static char Far DirlistUidGidFailed[] =
+  "warning:  cannot set UID %d and/or GID %d for %s\n";
+static char Far DirlistUtimeFailed[] =
+  "warning:  cannot set modification, access times for %s\n";
+#  ifndef NO_CHMOD
+  static char Far DirlistChmodFailed[] =
+    "warning:  cannot set permissions for %s\n";
+#  endif
+
+
+int set_direc_attribs(__G__ d)
+    __GDEF
+    dirtime *d;
+{
+    int errval = PK_OK;
+
+    if (d->have_uidgid &&
+        chown(d->fn, (uid_t)d->uidgid[0], (gid_t)d->uidgid[1]))
+    {
+        Info(slide, 0x201, ((char *)slide,
+          LoadFarString(DirlistUidGidFailed),
+          d->uidgid[0], d->uidgid[1], d->fn));
+        if (!errval)
+            errval = PK_WARN;
+    }
+    if (utime(d->fn, &d->u.t2)) {
+        Info(slide, 0x201, ((char *)slide,
+          LoadFarString(DirlistUtimeFailed), d->fn));
+        if (!errval)
+            errval = PK_WARN;
+    }
+#ifndef NO_CHMOD
+    if (chmod(d->fn, 0xffff & d->perms)) {
+        Info(slide, 0x201, ((char *)slide,
+          LoadFarString(DirlistChmodFailed), d->fn));
+        /* perror("chmod (file attributes) error"); */
+        if (!errval)
+            errval = PK_WARN;
+    }
+#endif /* !NO_CHMOD */
+    return errval;
+} /* end function set_directory_attributes() */
+
+#endif /* SET_DIR_ATTRIB */
+
+
+
+
+#ifdef TIMESTAMP
+
+/***************************/
+/*  Function stamp_file()  */
+/***************************/
+
+int stamp_file(fname, modtime)
+    ZCONST char *fname;
+    time_t modtime;
+{
+    ztimbuf tp;
+
+    tp.modtime = tp.actime = modtime;
+    return (utime(fname, &tp));
+
+} /* end function stamp_file() */
+
+#endif /* TIMESTAMP */
+
+
+
+
+#ifndef SFX
+
+/************************/
+/*  Function version()  */
+/************************/
+
+void version(__G)
+    __GDEF
+{
+#if defined(CRAY) || defined(NX_CURRENT_COMPILER_RELEASE) || defined(NetBSD)
+    char buf1[40];
+#if defined(CRAY) || defined(NX_CURRENT_COMPILER_RELEASE)
+    char buf2[40];
+#endif
+#endif
+
+    /* Pyramid, NeXT have problems with huge macro expansion, too:  no Info() */
+    sprintf((char *)slide, LoadFarString(CompiledWith),
+
+#ifdef __GNUC__
+#  ifdef NX_CURRENT_COMPILER_RELEASE
+      (sprintf(buf1, "NeXT DevKit %d.%02d ", NX_CURRENT_COMPILER_RELEASE/100,
+        NX_CURRENT_COMPILER_RELEASE%100), buf1),
+      (strlen(__VERSION__) > 8)? "(gcc)" :
+        (sprintf(buf2, "(gcc %s)", __VERSION__), buf2),
+#  else
+      "gcc ", __VERSION__,
+#  endif
+#else
+#  if defined(CRAY) && defined(_RELEASE)
+      "cc ", (sprintf(buf1, "version %d", _RELEASE), buf1),
+#  else
+#  ifdef __VERSION__
+      "cc ", __VERSION__,
+#  else
+      "cc", "",
+#  endif
+#  endif
+#endif
+
+      "Unix",
+
+#if defined(sgi) || defined(__sgi)
+      " (Silicon Graphics IRIX)",
+#else
+#ifdef sun
+#  ifdef sparc
+#    ifdef __SVR4
+      " (Sun SPARC/Solaris)",
+#    else /* may or may not be SunOS */
+      " (Sun SPARC)",
+#    endif
+#  else
+#  if defined(sun386) || defined(i386)
+      " (Sun 386i)",
+#  else
+#  if defined(mc68020) || defined(__mc68020__)
+      " (Sun 3)",
+#  else /* mc68010 or mc68000:  Sun 2 or earlier */
+      " (Sun 2)",
+#  endif
+#  endif
+#  endif
+#else
+#ifdef __hpux
+      " (HP/UX)",
+#else
+#ifdef __osf__
+      " (DEC OSF/1)",
+#else
+#ifdef _AIX
+      " (IBM AIX)",
+#else
+#ifdef aiws
+      " (IBM RT/AIX)",
+#else
+#if defined(CRAY) || defined(cray)
+#  ifdef _UNICOS
+      (sprintf(buf2, " (Cray UNICOS release %d)", _UNICOS), buf2),
+#  else
+      " (Cray UNICOS)",
+#  endif
+#else
+#if defined(uts) || defined(UTS)
+      " (Amdahl UTS)",
+#else
+#ifdef NeXT
+#  ifdef mc68000
+      " (NeXTStep/black)",
+#  else
+      " (NeXTStep for Intel)",
+#  endif
+#else              /* the next dozen or so are somewhat order-dependent */
+#ifdef LINUX
+#  ifdef __ELF__
+      " (Linux ELF)",
+#  else
+      " (Linux a.out)",
+#  endif
+#else
+#ifdef MINIX
+      " (Minix)",
+#else
+#ifdef M_UNIX
+      " (SCO Unix)",
+#else
+#ifdef M_XENIX
+      " (SCO Xenix)",
+#else
+#ifdef __NetBSD__
+#  ifdef NetBSD0_8
+      (sprintf(buf1, " (NetBSD 0.8%c)", (char)(NetBSD0_8 - 1 + 'A')), buf1),
+#  else
+#  ifdef NetBSD0_9
+      (sprintf(buf1, " (NetBSD 0.9%c)", (char)(NetBSD0_9 - 1 + 'A')), buf1),
+#  else
+#  ifdef NetBSD1_0
+      (sprintf(buf1, " (NetBSD 1.0%c)", (char)(NetBSD1_0 - 1 + 'A')), buf1),
+#  else
+      (BSD4_4 == 0.5)? " (NetBSD before 0.9)" : " (NetBSD 1.1 or later)",
+#  endif
+#  endif
+#  endif
+#else
+#ifdef __FreeBSD__
+      (BSD4_4 == 0.5)? " (FreeBSD 1.x)" : " (FreeBSD 2.0 or later)",
+#else
+#ifdef __bsdi__
+      (BSD4_4 == 0.5)? " (BSD/386 1.0)" : " (BSD/386 1.1 or later)",
+#else
+#ifdef __386BSD__
+      (BSD4_4 == 1)? " (386BSD, post-4.4 release)" : " (386BSD)",
+#else
+#if defined(i486) || defined(__i486) || defined(__i486__)
+      " (Intel 486)",
+#else
+#if defined(i386) || defined(__i386) || defined(__i386__)
+      " (Intel 386)",
+#else
+#ifdef pyr
+      " (Pyramid)",
+#else
+#ifdef ultrix
+#  ifdef mips
+      " (DEC/MIPS)",
+#  else
+#  ifdef vax
+      " (DEC/VAX)",
+#  else /* __alpha? */
+      " (DEC/Alpha)",
+#  endif
+#  endif
+#else
+#ifdef gould
+      " (Gould)",
+#else
+#ifdef MTS
+      " (MTS)",
+#else
+#ifdef __convexc__
+      " (Convex)",
+#else
+#ifdef __QNX__
+      " (QNX 4)",
+#else
+#ifdef __QNXNTO__
+      " (QNX Neutrino)",
+#else
+#ifdef Lynx
+      " (LynxOS)",
+#else
+      "",
+#endif /* Lynx */
+#endif /* QNX Neutrino */
+#endif /* QNX 4 */
+#endif /* Convex */
+#endif /* MTS */
+#endif /* Gould */
+#endif /* DEC */
+#endif /* Pyramid */
+#endif /* 386 */
+#endif /* 486 */
+#endif /* 386BSD */
+#endif /* BSDI BSD/386 */
+#endif /* NetBSD */
+#endif /* FreeBSD */
+#endif /* SCO Xenix */
+#endif /* SCO Unix */
+#endif /* Minix */
+#endif /* Linux */
+#endif /* NeXT */
+#endif /* Amdahl */
+#endif /* Cray */
+#endif /* RT/AIX */
+#endif /* AIX */
+#endif /* OSF/1 */
+#endif /* HP/UX */
+#endif /* Sun */
+#endif /* SGI */
+
+#ifdef __DATE__
+      " on ", __DATE__
+#else
+      "", ""
+#endif
+    );
+
+    (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0);
+
+} /* end function version() */
+
+#endif /* !SFX */
+
+
+
+
+#ifdef QLZIP
+
+struct qdirect  {
+    long            d_length __attribute__ ((packed));  /* file length */
+    unsigned char   d_access __attribute__ ((packed));  /* file access type */
+    unsigned char   d_type __attribute__ ((packed));    /* file type */
+    long            d_datalen __attribute__ ((packed)); /* data length */
+    long            d_reserved __attribute__ ((packed));/* Unused */
+    short           d_szname __attribute__ ((packed));  /* size of name */
+    char            d_name[36] __attribute__ ((packed));/* name area */
+    long            d_update __attribute__ ((packed));  /* last update */
+    long            d_refdate __attribute__ ((packed));
+    long            d_backup __attribute__ ((packed));   /* EOD */
+};
+
+#define LONGID  "QDOS02"
+#define EXTRALEN (sizeof(struct qdirect) + 8)
+#define JBLONGID    "QZHD"
+#define JBEXTRALEN  (sizeof(jbextra)  - 4 * sizeof(char))
+
+typedef struct {
+    char        eb_header[4] __attribute__ ((packed));  /* place_holder */
+    char        longid[8] __attribute__ ((packed));
+    struct      qdirect     header __attribute__ ((packed));
+} qdosextra;
+
+typedef struct {
+    char        eb_header[4];                           /* place_holder */
+    char        longid[4];
+    struct      qdirect     header;
+} jbextra;
+
+
+
+/*  The following two functions SH() and LG() convert big-endian short
+ *  and long numbers into native byte order.  They are some kind of
+ *  counterpart to the generic UnZip's makeword() and makelong() functions.
+ */
+static ush SH(ush val)
+{
+    uch swapbuf[2];
+
+    swapbuf[1] = (uch)(val & 0xff);
+    swapbuf[0] = (uch)(val >> 8);
+    return (*(ush *)swapbuf);
+}
+
+
+
+static ulg LG(ulg val)
+{
+    /*  convert the big-endian unsigned long number `val' to the machine
+     *  dependant representation
+     */
+    ush swapbuf[2];
+
+    swapbuf[1] = SH((ush)(val & 0xffff));
+    swapbuf[0] = SH((ush)(val >> 16));
+    return (*(ulg *)swapbuf);
+}
+
+
+
+static void qlfix(__G__ ef_ptr, ef_len)
+    __GDEF
+    uch *ef_ptr;
+    unsigned ef_len;
+{
+    while (ef_len >= EB_HEADSIZE)
+    {
+        unsigned    eb_id  = makeword(EB_ID + ef_ptr);
+        unsigned    eb_len = makeword(EB_LEN + ef_ptr);
+
+        if (eb_len > (ef_len - EB_HEADSIZE)) {
+            /* discovered some extra field inconsistency! */
+            Trace((stderr,
+              "qlfix: block length %u > rest ef_size %u\n", eb_len,
+              ef_len - EB_HEADSIZE));
+            break;
+        }
+
+        switch (eb_id) {
+          case EF_QDOS:
+          {
+            struct _ntc_
+            {
+                long id;
+                long dlen;
+            } ntc;
+            long dlen = 0;
+
+            qdosextra   *extra = (qdosextra *)ef_ptr;
+            jbextra     *jbp   = (jbextra   *)ef_ptr;
+
+            if (!strncmp(extra->longid, LONGID, strlen(LONGID)))
+            {
+                if (eb_len != EXTRALEN)
+                    if (uO.qflag)
+                        Info(slide, 0x201, ((char *)slide,
+                          "warning:  invalid length in Qdos field for %s\n",
+                          G.filename));
+                    else
+                        Info(slide, 0x201, ((char *)slide,
+                          "warning:  invalid length in Qdos field"));
+
+                if (extra->header.d_type)
+                {
+                    dlen = extra->header.d_datalen;
+                }
+            }
+
+            if (!strncmp(jbp->longid, JBLONGID, strlen(JBLONGID)))
+            {
+                if (eb_len != JBEXTRALEN)
+                    if (uO.qflag)
+                        Info(slide, 0x201, ((char *)slide,
+                          "warning:  invalid length in QZ field for %s\n",
+                          G.filename));
+                    else
+                        Info(slide, 0x201, ((char *)slide,
+                          "warning:  invalid length in QZ field"));
+                if(jbp->header.d_type)
+                {
+                    dlen = jbp->header.d_datalen;
+                }
+            }
+
+            if ((long)LG(dlen) > 0)
+            {
+                G.outfile = fopen(G.filename,"r+");
+                fseek(G.outfile, -8, SEEK_END);
+                fread(&ntc, 8, 1, G.outfile);
+                if(ntc.id != *(long *)"XTcc")
+                {
+                    ntc.id = *(long *)"XTcc";
+                    ntc.dlen = dlen;
+                    fwrite (&ntc, 8, 1, G.outfile);
+                }
+                Info(slide, 0x201, ((char *)slide, "QData = %d", LG(dlen)));
+                fclose(G.outfile);
+            }
+            return;     /* finished, cancel further extra field scanning */
+          }
+
+          default:
+            Trace((stderr,"qlfix: unknown extra field block, ID=%d\n",
+               eb_id));
+        }
+
+        /* Skip this extra field block */
+        ef_ptr += (eb_len + EB_HEADSIZE);
+        ef_len -= (eb_len + EB_HEADSIZE);
+    }
+}
+#endif /* QLZIP */
+
+
+
+
+#ifdef ACORN_FTYPE_NFS
+
+/* Acorn bits for NFS filetyping */
+
+static int isRISCOSexfield(uch *extra_field)
+{
+ if (extra_field != NULL) {
+   RO_extra_block *block = (RO_extra_block *)extra_field;
+   return (
+     makeword(block->ID) == EF_SPARK &&
+     (makeword(block->size) == 24 || makeword(block->size) == 20) &&
+     makelong(block->ID_2) == 0x30435241 /* ARC0 */);
+ }
+ return FALSE;
+}
+#endif /* ACORN_FTYPE_NFS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/unreduce.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,230 @@
+/*---------------------------------------------------------------------------
+
+  unreduce.c
+
+  The Reducing algorithm is actually a combination of two distinct algorithms.
+  The first algorithm compresses repeated byte sequences, and the second al-
+  gorithm takes the compressed stream from the first algorithm and applies a
+  probabilistic compression method.
+
+     * Copyright 1989 Samuel H. Smith;  All rights reserved
+     *
+     * Do not distribute modified versions without my permission.
+     * Do not remove or alter this notice or any other copyright notice.
+     * If you use this in your own program you must distribute source code.
+     * Do not use any of this in a commercial product.
+
+  See the accompanying file "COPYING" in UnZip source and binary distributions
+  for further information.  This code is NOT used unless USE_SMITH_CODE is
+  explicitly defined (==> COPYRIGHT_CLEAN is not defined).
+
+  ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"   /* defines COPYRIGHT_CLEAN by default */
+
+
+#ifndef COPYRIGHT_CLEAN
+
+/**************************************/
+/*  UnReduce Defines, Typedefs, etc.  */
+/**************************************/
+
+#define DLE    144
+
+typedef uch f_array[64];        /* for followers[256][64] */
+
+
+
+/******************************/
+/*  UnReduce Local Functions  */
+/******************************/
+
+static void LoadFollowers OF((__GPRO__ f_array *followers, uch *Slen));
+
+
+
+/*******************************/
+/*  UnReduce Global Constants  */
+/*******************************/
+
+static ZCONST shrint L_table[] =
+{0, 0x7f, 0x3f, 0x1f, 0x0f};
+
+static ZCONST shrint D_shift[] =
+{0, 0x07, 0x06, 0x05, 0x04};
+static ZCONST shrint D_mask[] =
+{0, 0x01, 0x03, 0x07, 0x0f};
+
+static ZCONST shrint B_table[] =
+{8, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8};
+
+
+
+
+
+/*************************/
+/*  Function unreduce()  */
+/*************************/
+
+void unreduce(__G)   /* expand probabilistically reduced data */
+     __GDEF
+{
+    register int lchar = 0;
+    shrint nchar;
+    shrint ExState = 0;
+    shrint V = 0;
+    shrint Len = 0;
+    long s = G.ucsize;  /* number of bytes left to decompress */
+    unsigned w = 0;      /* position in output window slide[] */
+    unsigned u = 1;      /* true if slide[] unflushed */
+    uch Slen[256];
+
+    f_array *followers = (f_array *)(slide + 0x4000);
+    int factor = G.lrec.compression_method - 1;
+
+    LoadFollowers(__G__ followers, Slen);
+
+    while (s > 0 /* && (!zipeof) */) {
+        if (Slen[lchar] == 0)
+            READBITS(8, nchar)   /* ; */
+        else {
+            READBITS(1, nchar)   /* ; */
+            if (nchar != 0)
+                READBITS(8, nchar)       /* ; */
+            else {
+                shrint follower;
+                int bitsneeded = B_table[Slen[lchar]];
+
+                READBITS(bitsneeded, follower)   /* ; */
+                nchar = followers[lchar][follower];
+            }
+        }
+        /* expand the resulting byte */
+        switch (ExState) {
+
+        case 0:
+            if (nchar != DLE) {
+                s--;
+                slide[w++] = (uch)nchar;
+                if (w == 0x4000) {
+                    flush(__G__ slide, (ulg)w, 0);
+                    w = u = 0;
+                }
+            }
+            else
+                ExState = 1;
+            break;
+
+        case 1:
+            if (nchar != 0) {
+                V = nchar;
+                Len = V & L_table[factor];
+                if (Len == L_table[factor])
+                    ExState = 2;
+                else
+                    ExState = 3;
+            } else {
+                s--;
+                slide[w++] = DLE;
+                if (w == 0x4000)
+                {
+                  flush(__G__ slide, (ulg)w, 0);
+                  w = u = 0;
+                }
+                ExState = 0;
+            }
+            break;
+
+        case 2:{
+                Len += nchar;
+                ExState = 3;
+            }
+            break;
+
+        case 3:{
+                register unsigned e;
+                register unsigned n = Len + 3;
+                register unsigned d = w - ((((V >> D_shift[factor]) &
+                               D_mask[factor]) << 8) + nchar + 1);
+
+                s -= n;
+                do {
+                  n -= (e = (e = 0x4000 - ((d &= 0x3fff) > w ? d : w)) > n ?
+                        n : e);
+                  if (u && w <= d)
+                  {
+                    memzero(slide + w, e);
+                    w += e;
+                    d += e;
+                  }
+                  else
+                    if (w - d < e)      /* (assume unsigned comparison) */
+                      do {              /* slow to avoid memcpy() overlap */
+                        slide[w++] = slide[d++];
+                      } while (--e);
+                    else
+                    {
+                      memcpy(slide + w, slide + d, e);
+                      w += e;
+                      d += e;
+                    }
+                  if (w == 0x4000)
+                  {
+                    flush(__G__ slide, (ulg)w, 0);
+                    w = u = 0;
+                  }
+                } while (n);
+
+                ExState = 0;
+            }
+            break;
+        }
+
+        /* store character for next iteration */
+        lchar = nchar;
+    }
+
+    /* flush out slide */
+    flush(__G__ slide, (ulg)w, 0);
+}
+
+
+
+
+
+/******************************/
+/*  Function LoadFollowers()  */
+/******************************/
+
+static void LoadFollowers(__G__ followers, Slen)
+     __GDEF
+     f_array *followers;
+     uch *Slen;
+{
+    register int x;
+    register int i;
+
+    for (x = 255; x >= 0; x--) {
+        READBITS(6, Slen[x])   /* ; */
+        for (i = 0; (uch)i < Slen[x]; i++)
+            READBITS(8, followers[x][i])   /* ; */
+    }
+}
+
+#endif /* !COPYRIGHT_CLEAN */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/unshrink.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,301 @@
+/*---------------------------------------------------------------------------
+
+  unshrink.c                     version 1.21                     23 Nov 95
+
+
+       NOTE:  This code may or may not infringe on the so-called "Welch
+       patent" owned by Unisys.  (From reading the patent, it appears
+       that a pure LZW decompressor is *not* covered, but this claim has
+       not been tested in court, and Unisys is reported to believe other-
+       wise.)  It is therefore the responsibility of the user to acquire
+       whatever license(s) may be required for legal use of this code.
+
+       THE INFO-ZIP GROUP DISCLAIMS ALL LIABILITY FOR USE OF THIS CODE
+       IN VIOLATION OF APPLICABLE PATENT LAW.
+
+
+  Shrinking is basically a dynamic LZW algorithm with allowed code sizes of
+  up to 13 bits; in addition, there is provision for partial clearing of
+  leaf nodes.  PKWARE uses the special code 256 (decimal) to indicate a
+  change in code size or a partial clear of the code tree:  256,1 for the
+  former and 256,2 for the latter.  [Note that partial clearing can "orphan"
+  nodes:  the parent-to-be can be cleared before its new child is added,
+  but the child is added anyway (as an orphan, as though the parent still
+  existed).  When the tree fills up to the point where the parent node is
+  reused, the orphan is effectively "adopted."  Versions prior to 1.05 were
+  affected more due to greater use of pointers (to children and siblings
+  as well as parents).]
+
+  This replacement version of unshrink.c was written from scratch.  It is
+  based only on the algorithms described in Mark Nelson's _The Data Compres-
+  sion Book_ and in Terry Welch's original paper in the June 1984 issue of
+  IEEE _Computer_; no existing source code, including any in Nelson's book,
+  was used.
+
+  Memory requirements have been reduced in this version and are now no more
+  than the original Sam Smith code.  This is still larger than any of the
+  other algorithms:  at a minimum, 8K+8K+16K (stack+values+parents) assuming
+  16-bit short ints, and this does not even include the output buffer (the
+  other algorithms leave the uncompressed data in the work area, typically
+  called slide[]).  For machines with a 64KB data space this is a problem,
+  particularly when text conversion is required and line endings have more
+  than one character.  UnZip's solution is to use two roughly equal halves
+  of outbuf for the ASCII conversion in such a case; the "unshrink" argument
+  to flush() signals that this is the case.
+
+  For large-memory machines, a second outbuf is allocated for translations,
+  but only if unshrinking and only if translations are required.
+
+              | binary mode  |        text mode
+    ---------------------------------------------------
+    big mem   |  big outbuf  | big outbuf + big outbuf2  <- malloc'd here
+    small mem | small outbuf | half + half small outbuf
+
+  Copyright 1994, 1995 Greg Roelofs.  See the accompanying file "COPYING"
+  in UnZip 5.20 (or later) source or binary distributions.
+
+  ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"       /* defines LZW_CLEAN by default */
+
+
+#ifndef LZW_CLEAN
+
+static void  partial_clear  OF((__GPRO));
+
+#ifdef DEBUG
+#  define OUTDBG(c) \
+	if ((c)<32 || (c)>=127) pipeit("\\x%02x",(c)); else { } 
+#else
+#  define OUTDBG(c)
+#endif
+
+/* HSIZE is defined as 2^13 (8192) in unzip.h */
+#define BOGUSCODE  256
+#define FLAG_BITS  parent        /* upper bits of parent[] used as flag bits */
+#define CODE_MASK  (HSIZE - 1)   /* 0x1fff (lower bits are parent's index) */
+#define FREE_CODE  HSIZE         /* 0x2000 (code is unused or was cleared) */
+#define HAS_CHILD  (HSIZE << 1)  /* 0x4000 (code has a child--do not clear) */
+
+#define parent G.area.shrink.Parent
+#define Value  G.area.shrink.value /* "value" conflicts with Pyramid ioctl.h */
+#define stack  G.area.shrink.Stack
+
+
+/***********************/
+/* Function unshrink() */
+/***********************/
+
+int unshrink(__G)
+     __GDEF
+{
+    int offset = (HSIZE - 1);
+    uch *stacktop = stack + offset;
+    register uch *newstr;
+    int codesize=9, len, KwKwK, error;
+    shrint code, oldcode, freecode, curcode;
+    shrint lastfreecode;
+    unsigned int outbufsiz;
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+    /* Normally realbuf and outbuf will be the same.  However, if the data
+     * are redirected to a large memory buffer, realbuf will point to the
+     * new location while outbuf will remain pointing to the malloc'd
+     * memory buffer. */
+    uch *realbuf = G.outbuf;
+#else
+#   define realbuf G.outbuf
+#endif
+
+
+/*---------------------------------------------------------------------------
+    Initialize various variables.
+  ---------------------------------------------------------------------------*/
+
+    lastfreecode = BOGUSCODE;
+
+#ifndef VMS     /* VMS uses its own buffer scheme for textmode flush(). */
+#ifndef SMALL_MEM
+    /* non-memory-limited machines:  allocate second (large) buffer for
+     * textmode conversion in flush(), but only if needed */
+    if (G.pInfo->textmode && !G.outbuf2 &&
+        (G.outbuf2 = (uch *)malloc(TRANSBUFSIZ)) == (uch *)NULL)
+        return PK_MEM3;
+#endif
+#endif /* !VMS */
+
+    for (code = 0;  code < BOGUSCODE;  ++code) {
+        Value[code] = (uch)code;
+        parent[code] = BOGUSCODE;
+    }
+    for (code = BOGUSCODE+1;  code < HSIZE;  ++code)
+        parent[code] = FREE_CODE;
+
+#if (defined(DLL) && !defined(NO_SLIDE_REDIR))
+    if (G.redirect_slide) { /* use normal outbuf unless we're a DLL routine */
+        realbuf = G.redirect_buffer;
+        outbufsiz = G.redirect_size;
+    } else
+#endif
+#ifdef DLL
+    if (G.pInfo->textmode && !G.redirect_data)
+#else
+    if (G.pInfo->textmode)
+#endif
+        outbufsiz = RAWBUFSIZ;
+    else
+        outbufsiz = OUTBUFSIZ;
+    G.outptr = realbuf;
+    G.outcnt = 0L;
+
+/*---------------------------------------------------------------------------
+    Get and output first code, then loop over remaining ones.
+  ---------------------------------------------------------------------------*/
+
+    READBITS(codesize, oldcode)
+    if (!G.zipeof) {
+        *G.outptr++ = (uch)oldcode;
+        OUTDBG((uch)oldcode)
+        ++G.outcnt;
+    }
+
+    do {
+        READBITS(codesize, code)
+        if (G.zipeof)
+            break;
+        if (code == BOGUSCODE) {   /* possible to have consecutive escapes? */
+            READBITS(codesize, code)
+            if (code == 1) {
+                ++codesize;
+                Trace((stderr, " (codesize now %d bits)\n", codesize));
+            } else if (code == 2) {
+                Trace((stderr, " (partial clear code)\n"));
+                partial_clear(__G);   /* clear leafs (nodes with no children) */
+                Trace((stderr, " (done with partial clear)\n"));
+                lastfreecode = BOGUSCODE;  /* reset start of free-node search */
+            }
+            continue;
+        }
+
+    /*-----------------------------------------------------------------------
+        Translate code:  traverse tree from leaf back to root.
+      -----------------------------------------------------------------------*/
+
+        newstr = stacktop;
+        curcode = code;
+
+        if (parent[curcode] == FREE_CODE) {
+            /* or (FLAG_BITS[curcode] & FREE_CODE)? */
+            KwKwK = TRUE;
+            Trace((stderr, " (found a KwKwK code %d; oldcode = %d)\n", code,
+              oldcode));
+            --newstr;   /* last character will be same as first character */
+            curcode = oldcode;
+        } else
+            KwKwK = FALSE;
+
+        do {
+            *newstr-- = Value[curcode];
+            curcode = (shrint)(parent[curcode] & CODE_MASK);
+        } while (curcode != BOGUSCODE);
+
+        len = (int)(stacktop - newstr++);
+        if (KwKwK)
+            *stacktop = *newstr;
+
+    /*-----------------------------------------------------------------------
+        Write expanded string in reverse order to output buffer.
+      -----------------------------------------------------------------------*/
+
+        Trace((stderr, "code %4d; oldcode %4d; char %3d (%c); string [", code,
+          oldcode, (int)(*newstr), (*newstr<32 || *newstr>=127)? ' ':*newstr));
+
+        {
+            register uch *p;
+
+            for (p = newstr;  p < newstr+len;  ++p) {
+                *G.outptr++ = *p;
+                OUTDBG(*p)
+                if (++G.outcnt == outbufsiz) {
+                    Trace((stderr, "doing flush(), outcnt = %lu\n", G.outcnt));
+                    if ((error = flush(__G__ realbuf, G.outcnt, TRUE)) != 0)
+                        pipeit("unshrink:  flush() error (%d)\n",
+                          error);
+                    Trace((stderr, "done with flush()\n"));
+                    G.outptr = realbuf;
+                    G.outcnt = 0L;
+                }
+            }
+        }
+
+    /*-----------------------------------------------------------------------
+        Add new leaf (first character of newstr) to tree as child of oldcode.
+      -----------------------------------------------------------------------*/
+
+        /* search for freecode */
+        freecode = (shrint)(lastfreecode + 1);
+        /* add if-test before loop for speed? */
+        while (parent[freecode] != FREE_CODE)
+            ++freecode;
+        lastfreecode = freecode;
+        Trace((stderr, "]; newcode %d\n", freecode));
+
+        Value[freecode] = *newstr;
+        parent[freecode] = oldcode;
+        oldcode = code;
+
+    } while (!G.zipeof);
+
+/*---------------------------------------------------------------------------
+    Flush any remaining data and return to sender...
+  ---------------------------------------------------------------------------*/
+
+    if (G.outcnt > 0L) {
+        Trace((stderr, "doing final flush(), outcnt = %lu\n", G.outcnt));
+        if ((error = flush(__G__ realbuf, G.outcnt, TRUE)) != 0)
+            pipeit("unshrink:  flush() error (%d)\n", error);
+        Trace((stderr, "done with flush()\n"));
+    }
+
+    return PK_OK;
+
+} /* end function unshrink() */
+
+
+
+
+
+/****************************/
+/* Function partial_clear() */      /* no longer recursive... */
+/****************************/
+
+static void partial_clear(__G)
+     __GDEF
+{
+    register shrint code;
+
+    /* clear all nodes which have no children (i.e., leaf nodes only) */
+
+    /* first loop:  mark each parent as such */
+    for (code = BOGUSCODE+1;  code < HSIZE;  ++code) {
+        register shrint cparent = (shrint)(parent[code] & CODE_MASK);
+
+        if (cparent > BOGUSCODE && cparent != FREE_CODE)
+            FLAG_BITS[cparent] |= HAS_CHILD;   /* set parent's child-bit */
+    }
+
+    /* second loop:  clear all nodes *not* marked as parents; reset flag bits */
+    for (code = BOGUSCODE+1;  code < HSIZE;  ++code) {
+        if (FLAG_BITS[code] & HAS_CHILD)    /* just clear child-bit */
+            FLAG_BITS[code] &= ~HAS_CHILD;
+        else {                              /* leaf:  lose it */
+            Trace((stderr, "%d\n", code));
+            parent[code] = FREE_CODE;
+        }
+    }
+
+    return;
+}
+
+#endif /* !LZW_CLEAN */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/unzip.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,1744 @@
+/*---------------------------------------------------------------------------
+
+  unzip.c
+
+  UnZip - a zipfile extraction utility.  See below for make instructions, or
+  read the comments in Makefile and the various Contents files for more de-
+  tailed explanations.  To report a bug, send a *complete* description to
+  Zip-Bugs@lists.wku.edu; include machine type, operating system and ver-
+  sion, compiler and version, and reasonably detailed error messages or prob-
+  lem report.  To join Info-ZIP, see the instructions in README.
+
+  UnZip 5.x is a greatly expanded and partially rewritten successor to 4.x,
+  which in turn was almost a complete rewrite of version 3.x.  For a detailed
+  revision history, see UnzpHist.zip at quest.jpl.nasa.gov.  For a list of
+  the many (near infinite) contributors, see "CONTRIBS" in the UnZip source
+  distribution.
+
+  ---------------------------------------------------------------------------
+
+  [from original zipinfo.c]
+
+  This program reads great gobs of totally nifty information, including the
+  central directory stuff, from ZIP archives ("zipfiles" for short).  It
+  started as just a testbed for fooling with zipfiles, but at this point it
+  is actually a useful utility.  It also became the basis for the rewrite of
+  UnZip (3.16 -> 4.0), using the central directory for processing rather than
+  the individual (local) file headers.
+
+  As of ZipInfo v2.0 and UnZip v5.1, the two programs are combined into one.
+  If the executable is named "unzip" (or "unzip.exe", depending), it behaves
+  like UnZip by default; if it is named "zipinfo" or "ii", it behaves like
+  ZipInfo.  The ZipInfo behavior may also be triggered by use of unzip's -Z
+  option; for example, "unzip -Z [zipinfo_options] archive.zip".
+
+  Another dandy product from your buddies at Newtware!
+
+  Author:  Greg Roelofs, newt@pobox.com, http://pobox.com/~newt/
+           23 August 1990 -> April 1997
+
+  ---------------------------------------------------------------------------
+
+  Version:  unzip5??.{tar.Z | tar.gz | zip} for Unix, VMS, OS/2, MS-DOS, Amiga,
+              Atari, Windows 3.x/95/NT/CE, Macintosh, Human68K, Acorn RISC OS,
+              BeOS, SMS/QDOS, VM/CMS, MVS, AOS/VS and TOPS-20.  Decryption
+              requires sources in zcrypt28.zip.  See the accompanying "WHERE"
+              file in the main source distribution for ftp, uucp, BBS and mail-
+              server sites, or see http://www.cdrom.com/pub/infozip/UnZip.html .
+
+  Copyrights:  see accompanying file "COPYING" in UnZip source distribution.
+               (This software is free but NOT IN THE PUBLIC DOMAIN.  There
+               are some restrictions on commercial use.)
+
+  ---------------------------------------------------------------------------*/
+
+
+
+#define UNZIP_C
+#define UNZIP_INTERNAL
+#include "unzip.h"        /* includes, typedefs, macros, prototypes, etc. */
+#include "crypt.h"
+#include "version.h"
+
+#ifndef WINDLL            /* The WINDLL port uses windll/windll.c instead... */
+
+/*******************/
+/* Local Functions */
+/*******************/
+
+#ifndef SFX
+static void  show_version_info  OF((__GPRO));
+#endif
+
+
+/*************/
+/* Constants */
+/*************/
+
+#include "consts.h"  /* all constant global variables are in here */
+                     /* (non-constant globals were moved to globals.c) */
+
+/* constant local variables: */
+
+#ifndef SFX
+   static ZCONST char Far EnvUnZip[] = ENV_UNZIP;
+   static ZCONST char Far EnvUnZip2[] = ENV_UNZIP2;
+   static ZCONST char Far EnvZipInfo[] = ENV_ZIPINFO;
+   static ZCONST char Far EnvZipInfo2[] = ENV_ZIPINFO2;
+#ifdef RISCOS
+   static ZCONST char Far EnvUnZipExts[] = ENV_UNZIPEXTS;
+#endif /* RISCOS */
+#endif
+
+#if (!defined(SFX) || defined(SFX_EXDIR))
+   static ZCONST char Far NotExtracting[] =
+     "caution:  not extracting; -d ignored\n";
+   static ZCONST char Far MustGiveExdir[] =
+     "error:  must specify directory to which to extract with -d option\n";
+   static ZCONST char Far OnlyOneExdir[] =
+     "error:  -d option used more than once (only one exdir allowed)\n";
+#endif
+
+#if CRYPT
+   static ZCONST char Far MustGivePasswd[] =
+     "error:  must give decryption password with -P option\n";
+#endif
+
+#ifndef SFX
+   static ZCONST char Far Zfirst[] =
+   "error:  -Z must be first option for ZipInfo mode (check UNZIP variable?)\n";
+#endif
+static ZCONST char Far InvalidOptionsMsg[] = "error:\
+  -fn or any combination of -c, -l, -p, -t, -u and -v options invalid\n";
+static ZCONST char Far IgnoreOOptionMsg[] =
+  "caution:  both -n and -o specified; ignoring -o\n";
+
+/* usage() strings */
+#ifndef SFX
+#ifdef VMS
+   static ZCONST char Far Example3[] = "vms.c";
+   static ZCONST char Far Example2[] = "  unzip\
+ \"-V\" foo \"Bar\" => must quote uppercase options and filenames in VMS\n";
+#else /* !VMS */
+   static ZCONST char Far Example3[] = "ReadMe";
+#ifdef RISCOS
+   static ZCONST char Far Example2[] =
+"  unzip foo -d RAM:$   => extract all files from foo into RAMDisc\n";
+#else /* !RISCOS */
+#if (defined(OS2) || (defined(DOS_FLX_OS2_W32) && defined(MORE)))
+   static ZCONST char Far Example2[] =
+     "";                /* no room:  too many local3[] items */
+#else /* !OS2 */
+#ifdef MACOS
+   static ZCONST char Far Example2[] = ""; /* not needed */
+#else /* !MACOS */
+   static ZCONST char Far Example2[] = " \
+ unzip -p foo | more  => send contents of foo.zip via pipe into program more\n";
+#endif /* ?MACOS */
+#endif /* ?OS2 */
+#endif /* ?RISCOS */
+#endif /* ?VMS */
+
+/* local1[]:  command options */
+#if (defined(DLL) && defined(API_DOC))
+   static ZCONST char Far local1[] =
+     "  -A  print extended help for API functions";
+#else /* !(DLL && API_DOC) */
+   static ZCONST char Far local1[] = "";
+#endif /* ?(DLL && API_DOC) */
+
+/* local2[] and local3[]:  modifier options */
+#ifdef DOS_FLX_OS2_W32
+#ifdef FLEXOS
+   static ZCONST char Far local2[] = "";
+#else
+   static ZCONST char Far local2[] =
+     " -$  label removables (-$$ => fixed disks)";
+#endif
+#ifdef OS2
+#ifdef MORE
+   static ZCONST char Far local3[] = "\
+  -X  restore ACLs if supported              -s  spaces in filenames => '_'\n\
+                                             -M  pipe through \"more\" pager\n";
+#else
+   static ZCONST char Far local3[] = " \
+ -X  restore ACLs if supported              -s  spaces in filenames => '_'\n\n";
+#endif /* ?MORE */
+#else /* !OS2 */
+#ifdef WIN32
+#ifdef MORE
+   static ZCONST char Far local3[] = "\
+  -X  restore ACLs (-XX => use privileges)   -s  spaces in filenames => '_'\n\
+                                             -M  pipe through \"more\" pager\n";
+#else
+   static ZCONST char Far local3[] = " \
+ -X  restore ACLs (-XX => use privileges)   -s  spaces in filenames => '_'\n\n";
+#endif /* ?MORE */
+#else /* !WIN32 */
+#ifdef MORE
+   static ZCONST char Far local3[] = "  -\
+M  pipe through \"more\" pager              -s  spaces in filenames => '_'\n\n";
+#else
+   static ZCONST char Far local3[] = "\
+                                             -s  spaces in filenames => '_'\n";
+#endif
+#endif /* ?WIN32 */
+#endif /* ?OS2 || ?WIN32 */
+#else /* !DOS_FLX_OS2_W32 */
+#ifdef VMS
+   static ZCONST char Far local2[] = "\"-X\" restore owner/protection info";
+#ifdef MORE
+   static ZCONST char Far local3[] = "  \
+                                          \"-M\" pipe through \"more\" pager\n";
+#else
+   static ZCONST char Far local3[] = "\n";
+#endif
+#else /* !VMS */
+#if (defined(__BEOS__) || defined(TANDEM) || defined(UNIX))
+   static ZCONST char Far local2[] = " -X  restore UID/GID info";
+#ifdef MORE
+   static ZCONST char Far local3[] = "\
+                                             -M  pipe through \"more\" pager\n";
+#else
+   static ZCONST char Far local3[] = "\n";
+#endif
+#else /* !(__BEOS__ || TANDEM || UNIX) */
+#ifdef AMIGA
+   static ZCONST char Far local2[] = " -N  restore comments as filenotes";
+#ifdef MORE
+   static ZCONST char Far local3[] = "\
+                                             -M  pipe through \"more\" pager\n";
+#else
+   static ZCONST char Far local3[] = "\n";
+#endif
+#else /* !AMIGA */
+#ifdef MACOS
+   static ZCONST char Far local2[] = " -E  show Mac info during extraction";
+   static ZCONST char Far local3[] = " \
+ -i  ignore filenames in mac extra info     -J  junk (ignore) Mac extra info\n\n";
+#else /* !MACOS */
+#ifdef MORE
+   static ZCONST char Far local2[] = " -M  pipe through \"more\" pager";
+   static ZCONST char Far local3[] = "\n";
+#else
+   static ZCONST char Far local2[] = "";   /* Atari, Mac, CMS/MVS etc. */
+   static ZCONST char Far local3[] = "";
+#endif
+#endif /* ?MACOS */
+#endif /* ?AMIGA */
+#endif /* ?(__BEOS__ || TANDEM || UNIX) */
+#endif /* ?VMS */
+#endif /* ?DOS_FLX_OS2_W32 */
+#endif /* !SFX */
+
+#ifndef NO_ZIPINFO
+#ifdef VMS
+   static ZCONST char Far ZipInfoExample[] = "* or % (e.g., \"*font-%.zip\")";
+#else
+   static ZCONST char Far ZipInfoExample[] = "*, ?, [] (e.g., \"[a-j]*.zip\")";
+#endif
+
+static ZCONST char Far ZipInfoUsageLine1[] = "\
+ZipInfo %d.%d%d%s of %s, by Greg Roelofs and the Info-ZIP group.\n\
+\n\
+List name, date/time, attribute, size, compression method, etc., about files\n\
+in list (excluding those in xlist) contained in the specified .zip archive(s).\
+\n\"file[.zip]\" may be a wildcard name containing %s.\n\n\
+   usage:  zipinfo [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\n\
+      or:  unzip %s-Z%s [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\n";
+
+static ZCONST char Far ZipInfoUsageLine2[] = "\nmain\
+ listing-format options:             -s  short Unix \"ls -l\" format (def.)\n\
+  -1  filenames ONLY, one per line       -m  medium Unix \"ls -l\" format\n\
+  -2  just filenames but allow -h/-t/-z  -l  long Unix \"ls -l\" format\n\
+                                         -v  verbose, multi-page format\n";
+
+static ZCONST char Far ZipInfoUsageLine3[] = "miscellaneous options:\n\
+  -h  print header line       -t  print totals for listed files or for all\n\
+  -z  print zipfile comment  %c-T%c print file times in sortable decimal format\
+\n %c-C%c be case-insensitive   %s\
+  -x  exclude filenames that follow from listing\n";
+#ifdef MORE
+#ifdef VMS
+   static ZCONST char Far ZipInfoUsageLine4[] =
+     " \"-M\" page output through built-in \"more\"\n";
+#else
+   static ZCONST char Far ZipInfoUsageLine4[] =
+     "  -M  page output through built-in \"more\"\n";
+#endif
+#else /* !MORE */
+   static ZCONST char Far ZipInfoUsageLine4[] = "";
+#endif /* ?MORE */
+#endif /* !NO_ZIPINFO */
+
+#ifdef BETA
+#  ifdef VMSCLI
+   /* BetaVersion[] is also used in vms/cmdline.c:  do not make it static */
+     ZCONST char Far BetaVersion[] = "%s\
+        THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n";
+#  else
+     static ZCONST char Far BetaVersion[] = "%s\
+        THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n";
+#  endif
+#endif
+
+#ifdef SFX
+#  ifdef VMSCLI
+   /* UnzipSFXBanner[] is also used in vms/cmdline.c:  do not make it static */
+     ZCONST char Far UnzipSFXBanner[] =
+#  else
+     static ZCONST char Far UnzipSFXBanner[] =
+#  endif
+     "UnZipSFX %d.%d%d%s of %s, by Info-ZIP (Zip-Bugs@lists.wku.edu).\n";
+#  ifdef SFX_EXDIR
+     static ZCONST char Far UnzipSFXOpts[] =
+    "Valid options are -tfupcz and -d <exdir>; modifiers are -abjnoqCL%sV%s.\n";
+#  else
+     static ZCONST char Far UnzipSFXOpts[] =
+       "Valid options are -tfupcz; modifiers are -abjnoqCL%sV%s.\n";
+#  endif
+#else /* !SFX */
+   static ZCONST char Far CompileOptions[] =
+     "UnZip special compilation options:\n";
+   static ZCONST char Far CompileOptFormat[] = "\t%s\n";
+   static ZCONST char Far EnvOptions[] =
+     "\nUnZip and ZipInfo environment options:\n";
+   static ZCONST char Far EnvOptFormat[] = "%16s:  %s\n";
+   static ZCONST char Far None[] = "[none]";
+#  ifdef ACORN_FTYPE_NFS
+     static ZCONST char Far AcornFtypeNFS[] = "ACORN_FTYPE_NFS";
+#  endif
+#  ifdef ASM_CRC
+     static ZCONST char Far AsmCRC[] = "ASM_CRC";
+#  endif
+#  ifdef ASM_INFLATECODES
+     static ZCONST char Far AsmInflateCodes[] = "ASM_INFLATECODES";
+#  endif
+#  ifdef CHECK_VERSIONS
+     static ZCONST char Far Check_Versions[] = "CHECK_VERSIONS";
+#  endif
+#  ifdef COPYRIGHT_CLEAN
+     static ZCONST char Far Copyright_Clean[] =
+     "COPYRIGHT_CLEAN (PKZIP 0.9x unreducing method not supported)";
+#  endif
+#  ifdef DEBUG
+     static ZCONST char Far UDebug[] = "DEBUG";
+#  endif
+#  ifdef DEBUG_TIME
+     static ZCONST char Far DebugTime[] = "DEBUG_TIME";
+#  endif
+#  ifdef DLL
+     static ZCONST char Far Dll[] = "DLL";
+#  endif
+#  ifdef DOSWILD
+     static ZCONST char Far DosWild[] = "DOSWILD";
+#  endif
+#  ifdef LZW_CLEAN
+     static ZCONST char Far LZW_Clean[] =
+     "LZW_CLEAN (PKZIP/Zip 1.x unshrinking method not supported)";
+#  endif
+#  ifndef MORE
+     static ZCONST char Far No_More[] = "NO_MORE";
+#  endif
+#  ifdef NO_ZIPINFO
+     static ZCONST char Far No_ZipInfo[] = "NO_ZIPINFO";
+#  endif
+#  ifdef NTSD_EAS
+     static ZCONST char Far NTSDExtAttrib[] = "NTSD_EAS";
+#  endif
+#  ifdef OS2_EAS
+     static ZCONST char Far OS2ExtAttrib[] = "OS2_EAS";
+#  endif
+#  ifdef QLZIP
+     static ZCONST char Far SMSExFldOnUnix[] = "QLZIP";
+#  endif
+#  ifdef REENTRANT
+     static ZCONST char Far Reentrant[] = "REENTRANT";
+#  endif
+#  ifdef REGARGS
+     static ZCONST char Far RegArgs[] = "REGARGS";
+#  endif
+#  ifdef RETURN_CODES
+     static ZCONST char Far Return_Codes[] = "RETURN_CODES";
+#  endif
+#  ifdef SET_DIR_ATTRIB
+     static ZCONST char Far SetDirAttrib[] = "SET_DIR_ATTRIB";
+#  endif
+#  ifdef TIMESTAMP
+     static ZCONST char Far TimeStamp[] = "TIMESTAMP";
+#  endif
+#  ifdef UNIXBACKUP
+     static ZCONST char Far UnixBackup[] = "UNIXBACKUP";
+#  endif
+#  ifdef USE_EF_UT_TIME
+     static ZCONST char Far Use_EF_UT_time[] = "USE_EF_UT_TIME";
+#  endif
+#  ifndef LZW_CLEAN
+     static ZCONST char Far Use_Unshrink[] =
+     "USE_UNSHRINK (PKZIP/Zip 1.x unshrinking method supported)";
+#  endif
+#  ifndef COPYRIGHT_CLEAN
+     static ZCONST char Far Use_Smith_Code[] =
+     "USE_SMITH_CODE (PKZIP 0.9x unreducing method supported)";
+#  endif
+#  ifdef USE_VFAT
+     static ZCONST char Far Use_VFAT_support[] = "USE_VFAT";
+#  endif
+#  ifdef USE_ZLIB
+     static ZCONST char Far UseZlib[] =
+     "USE_ZLIB (compiled with version %s; using version %s)";
+#  endif
+#  ifdef VMS_TEXT_CONV
+     static ZCONST char Far VmsTextConv[] = "VMS_TEXT_CONV";
+#  endif
+#  ifdef VMSCLI
+     static ZCONST char Far VmsCLI[] = "VMSCLI";
+#  endif
+#  ifdef VMSWILD
+     static ZCONST char Far VmsWild[] = "VMSWILD";
+#  endif
+#  if CRYPT
+#    ifdef PASSWD_FROM_STDIN
+       static ZCONST char Far PasswdStdin[] = "PASSWD_FROM_STDIN";
+#    endif
+     static ZCONST char Far Decryption[] =
+       "\t[decryption, version %d.%d%s of %s]\n";
+     static ZCONST char Far CryptDate[] = CR_VERSION_DATE;
+#  endif
+#  ifndef __RSXNT__
+#    ifdef __EMX__
+       static ZCONST char Far EnvEMX[] = "EMX";
+       static ZCONST char Far EnvEMXOPT[] = "EMXOPT";
+#    endif
+#    if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2)))
+       static ZCONST char Far EnvGO32[] = "GO32";
+       static ZCONST char Far EnvGO32TMP[] = "GO32TMP";
+#    endif
+#  endif /* !__RSXNT__ */
+
+#ifdef VMS
+/* UnzipUsageLine1[] is also used in vms/cmdline.c:  do not make it static */
+   ZCONST char Far UnzipUsageLine1[] = "\
+UnZip %d.%d%d%s of %s, by Info-ZIP.  For more details see: unzip -v.\n\n";
+#ifdef COPYRIGHT_CLEAN
+   static ZCONST char Far UnzipUsageLine1v[] = "\
+UnZip %d.%d%d%s of %s, by Info-ZIP.  Maintained by C. Spieler.  Send\n\
+bug reports to the authors at Zip-Bugs@lists.wku.edu; see README for details.\
+\n\n";
+#else
+   static ZCONST char Far UnzipUsageLine1v[] = "\
+UnZip %d.%d%d%s of %s, by Info-ZIP.  UnReduce (c) 1989 by S. H. Smith.\n\
+Send bug reports to authors at Zip-Bugs@lists.wku.edu; see README for details.\
+\n\n";
+#endif /* ?COPYRIGHT_CLEAN */
+#else /* !VMS */
+#ifdef COPYRIGHT_CLEAN
+   static ZCONST char Far UnzipUsageLine1[] = "\
+UnZip %d.%d%d%s of %s, by Info-ZIP.  Maintained by C. Spieler.  Send\n\
+bug reports to the authors at Zip-Bugs@lists.wku.edu; see README for details.\
+\n\n";
+#else
+   static ZCONST char Far UnzipUsageLine1[] = "\
+UnZip %d.%d%d%s of %s, by Info-ZIP.  UnReduce (c) 1989 by S. H. Smith.\n\
+Send bug reports to authors at Zip-Bugs@lists.wku.edu; see README for details.\
+\n\n";
+#endif /* ?COPYRIGHT_CLEAN */
+#define UnzipUsageLine1v        UnzipUsageLine1
+#endif /* ?VMS */
+
+static ZCONST char Far UnzipUsageLine2v[] = "\
+Latest sources and executables are at ftp://ftp.cdrom.com/pub/infozip/ , as of\
+\nabove date; see http://www.cdrom.com/pub/infozip/UnZip.html for other sites.\
+\n\n";
+
+#ifdef MACOS
+static ZCONST char Far UnzipUsageLine2[] = "\
+Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-d exdir]\n \
+ Default action is to extract files in list, to exdir;\n\
+  file[.zip] may be a wildcard.  %s\n";
+#else /* !MACOS */
+#ifdef VM_CMS
+static ZCONST char Far UnzipUsageLine2[] = "\
+Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d fm]\n \
+ Default action is to extract files in list, except those in xlist, to disk fm;\n\
+  file[.zip] may be a wildcard.  %s\n";
+#else /* !VM_CMS */
+static ZCONST char Far UnzipUsageLine2[] = "\
+Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]\n \
+ Default action is to extract files in list, except those in xlist, to exdir;\n\
+  file[.zip] may be a wildcard.  %s\n";
+#endif /* ?VM_CMS */
+#endif /* ?MACOS */
+
+#ifdef NO_ZIPINFO
+#  define ZIPINFO_MODE_OPTION  ""
+   static ZCONST char Far ZipInfoMode[] =
+     "(ZipInfo mode is disabled in this version.)";
+#else
+#  define ZIPINFO_MODE_OPTION  "[-Z] "
+#  ifdef VMS
+     static ZCONST char Far ZipInfoMode[] =
+       "\"-Z\" => ZipInfo mode (`unzip \"-Z\"' for usage).";
+#  else
+     static ZCONST char Far ZipInfoMode[] =
+       "-Z => ZipInfo mode (\"unzip -Z\" for usage).";
+#  endif
+#endif /* ?NO_ZIPINFO */
+
+#ifdef VMS
+   static ZCONST char Far VMSusageLine2b[] = "\
+=> define foreign command symbol in LOGIN.COM:  $ unzip :== $dev:[dir]unzip.exe\
+\n";
+#endif
+
+#ifdef MACOS
+static ZCONST char Far UnzipUsageLine3[] = "\n\
+  -d  extract files into exdir               -l  list files (short format)\n\
+  -f  freshen existing files, create none    -t  test compressed archive data\n\
+  -u  update files, create if necessary      -z  display archive comment\n\
+%s\n";
+#else /* !MACOS */
+#ifdef VM_CMS
+static ZCONST char Far UnzipUsageLine3[] = "\n\
+  -p  extract files to pipe, no messages     -l  list files (short format)\n\
+  -f  freshen existing files, create none    -t  test compressed archive data\n\
+  -u  update files, create if necessary      -z  display archive comment\n\
+  -x  exclude files that follow (in xlist)   -d  extract files onto disk fm\n\
+%s\n";
+#else /* !VM_CMS */
+static ZCONST char Far UnzipUsageLine3[] = "\n\
+  -p  extract files to pipe, no messages     -l  list files (short format)\n\
+  -f  freshen existing files, create none    -t  test compressed archive data\n\
+  -u  update files, create if necessary      -z  display archive comment\n\
+  -x  exclude files that follow (in xlist)   -d  extract files into exdir\n\
+%s\n";
+#endif /* ?VM_CMS */
+#endif /* ?MACOS */
+
+static ZCONST char Far UnzipUsageLine4[] = "\
+modifiers:                                   -q  quiet mode (-qq => quieter)\n\
+  -n  never overwrite existing files         -a  auto-convert any text files\n\
+  -o  overwrite files WITHOUT prompting      -aa treat ALL files as text\n \
+ -j  junk paths (do not make directories)   -v  be verbose/print version info\n\
+ %c-C%c match filenames case-insensitively    %c-L%c make (some) names \
+lowercase\n %-42s %c-V%c retain VMS version numbers\n%s";
+
+static ZCONST char Far UnzipUsageLine5[] = "\
+Examples (see unzip.doc for more info):\n\
+  unzip data1 -x joe   => extract all files except joe from zipfile data1.zip\n\
+%s\
+  unzip -fo foo %-6s => quietly replace existing %s if archive file newer\n";
+#endif /* ?SFX */
+
+
+
+
+
+/*****************************/
+/*  main() / UzpMain() stub  */
+/*****************************/
+
+int installer_unpack(char *aname, int depricated)   /* return PK-type error code (except under VMS) */
+{
+	int r, argc = 3;
+    char tempfile[256];
+	char *argv[4];
+
+	argv[0] = "install.exe";
+	argv[1] = "install.exe";
+	argv[2] = tempfile;
+    argv[3] = NULL;
+
+    if(aname)
+		strcpy(tempfile, aname);
+    else
+		argc = 2;
+
+    CONSTRUCTGLOBALS();
+	r = unzip(__G__ argc, argv);
+    DESTROYGLOBALS()
+    RETURN(r);
+}
+
+void resetglobals(void) { }
+
+int pipeit(char *format, ...)
+{
+    return 0;
+}
+
+
+/*******************************/
+/*  Primary UnZip entry point  */
+/*******************************/
+
+int unzip(__G__ argc, argv)
+    __GDEF
+    int argc;
+    char *argv[];
+{
+#ifndef NO_ZIPINFO
+    char *p;
+#endif
+#ifdef DOS_FLX_H68_OS2_W32
+    int i;
+#endif
+    int retcode, error=FALSE;
+
+#if (defined(__IBMC__) && defined(__DEBUG_ALLOC__))
+    extern void DebugMalloc(void);
+
+    atexit(DebugMalloc);
+#endif
+
+#ifdef MALLOC_WORK
+    G.area.Slide =(uch *)calloc(8193, sizeof(shrint)+sizeof(uch)+sizeof(uch));
+    G.area.shrink.Parent = (shrint *)G.area.Slide;
+    G.area.shrink.value = G.area.Slide + (sizeof(shrint)*(HSIZE+1));
+    G.area.shrink.Stack = G.area.Slide +
+                           (sizeof(shrint) + sizeof(uch))*(HSIZE+1);
+#endif
+
+/*---------------------------------------------------------------------------
+    Macintosh initialization code.
+  ---------------------------------------------------------------------------*/
+
+#ifdef MACOS
+    {
+        int a;
+
+        for (a = 0;  a < 4;  ++a)
+            G.rghCursor[a] = GetCursor(a+128);
+        G.giCursor = 0;
+    }
+#endif
+
+/*---------------------------------------------------------------------------
+    Human68K initialization code.
+  ---------------------------------------------------------------------------*/
+
+#ifdef __human68k__
+    InitTwentyOne();
+#endif
+
+/*---------------------------------------------------------------------------
+    Acorn RISC OS initialization code.
+  ---------------------------------------------------------------------------*/
+
+#ifdef RISCOS
+    set_prefix();
+#endif
+
+/*---------------------------------------------------------------------------
+    Set signal handler for restoring echo, warn of zipfile corruption, etc.
+  ---------------------------------------------------------------------------*/
+
+#ifdef SIGINT
+    signal(SIGINT, handler);
+#endif
+#ifdef SIGTERM                 /* some systems really have no SIGTERM */
+    signal(SIGTERM, handler);
+#endif
+#ifdef SIGBUS
+    signal(SIGBUS, handler);
+#endif
+#ifdef SIGSEGV
+    signal(SIGSEGV, handler);
+#endif
+
+#if (defined(WIN32) && defined(__RSXNT__))
+    for (i = 0 ; i < argc; i++) {
+       _ISO_INTERN(argv[i]);
+    }
+#endif
+
+/*---------------------------------------------------------------------------
+    First figure out if we're running in UnZip mode or ZipInfo mode, and put
+    the appropriate environment-variable options into the queue.  Then rip
+    through any command-line options lurking about...
+  ---------------------------------------------------------------------------*/
+
+#ifdef SFX
+    G.argv0 = argv[0];
+#if (defined(OS2) || defined(WIN32))
+    G.zipfn = GetLoadPath(__G);/* non-MSC NT puts path into G.filename[] */
+#else
+    G.zipfn = G.argv0;
+#endif
+
+#ifdef VMSCLI
+    {
+        ulg status = vms_unzip_cmdline(&argc, &argv);
+        if (!(status & 1))
+            return status;
+    }
+#endif /* VMSCLI */
+
+    uO.zipinfo_mode = FALSE;
+    error = uz_opts(__G__ &argc, &argv);   /* UnZipSFX call only */
+
+#else /* !SFX */
+
+#ifdef RISCOS
+    /* get the extensions to swap from environment */
+    getRISCOSexts(ENV_UNZIPEXTS);
+#endif
+
+#ifdef MSDOS
+    /* extract MKS extended argument list from environment (before envargs!) */
+    mksargs(&argc, &argv);
+#endif
+
+#ifdef VMSCLI
+    {
+        ulg status = vms_unzip_cmdline(&argc, &argv);
+        if (!(status & 1))
+            return status;
+    }
+#endif /* VMSCLI */
+
+    G.noargs = (argc == 1);   /* no options, no zipfile, no anything */
+
+#ifndef NO_ZIPINFO
+    for (p = argv[0] + strlen(argv[0]); p >= argv[0]; --p) {
+        if (*p == DIR_END
+#ifdef DIR_END2
+            || *p == DIR_END2
+#endif
+           )
+            break;
+    }
+    ++p;
+
+    if (STRNICMP(p, LoadFarStringSmall(Zipnfo), 7) == 0 ||
+        STRNICMP(p, "ii", 2) == 0 ||
+        (argc > 1 && strncmp(argv[1], "-Z", 2) == 0))
+    {
+        uO.zipinfo_mode = TRUE;
+        envargs(__G__ &argc, &argv, LoadFarStringSmall(EnvZipInfo),
+          LoadFarStringSmall2(EnvZipInfo2));
+        error = zi_opts(__G__ &argc, &argv);
+    } else
+#endif /* NO_ZIPINFO */
+    {
+        uO.zipinfo_mode = FALSE;
+        envargs(__G__ &argc, &argv, LoadFarStringSmall(EnvUnZip),
+          LoadFarStringSmall2(EnvUnZip2));
+        error = uz_opts(__G__ &argc, &argv);
+    }
+
+#endif /* ?SFX */
+
+    if ((argc < 0) || error)
+        return error;
+
+/*---------------------------------------------------------------------------
+    Now get the zipfile name from the command line and then process any re-
+    maining options and file specifications.
+  ---------------------------------------------------------------------------*/
+
+#ifdef DOS_FLX_H68_OS2_W32
+    /* convert MSDOS-style directory separators to Unix-style ones for
+     * user's convenience (include zipfile name itself)
+     */
+#ifdef SFX
+    for (G.pfnames = argv, i = argc;  i > 0;  --i) {
+#else
+    /* argc does not include the zipfile specification */
+    for (G.pfnames = argv, i = argc+1;  i > 0;  --i) {
+#endif
+        char *q;
+
+        for (q = *G.pfnames;  *q;  ++q)
+            if (*q == '\\')
+                *q = '/';
+        ++G.pfnames;
+    }
+#endif /* DOS_FLX_H68_OS2_W32 */
+
+#ifndef SFX
+    G.wildzipfn = *argv++;
+#endif
+
+#if (defined(SFX) && !defined(SFX_EXDIR)) /* only check for -x */
+
+    G.filespecs = argc;
+    G.xfilespecs = 0;
+
+    if (argc > 0) {
+        char **pp = argv-1;
+
+        G.pfnames = argv;
+        while (*++pp)
+            if (strcmp(*pp, "-x") == 0) {
+                if (pp > argv) {
+                    *pp = 0;              /* terminate G.pfnames */
+                    G.filespecs = pp - G.pfnames;
+                } else {
+                    G.pfnames = (char **)fnames;  /* defaults */
+                    G.filespecs = 0;
+                }
+                G.pxnames = pp + 1;      /* excluded-names ptr: _after_ -x */
+                G.xfilespecs = argc - G.filespecs - 1;
+                break;                    /* skip rest of args */
+            }
+        G.process_all_files = FALSE;
+    } else
+        G.process_all_files = TRUE;      /* for speed */
+
+#else /* !SFX || SFX_EXDIR */             /* check for -x or -d */
+
+    G.filespecs = argc;
+    G.xfilespecs = 0;
+
+    if (argc > 0) {
+        int in_files=FALSE, in_xfiles=FALSE;
+        char **pp = argv-1;
+
+        G.process_all_files = FALSE;
+        G.pfnames = argv;
+        while (*++pp) {
+            Trace((stderr, "pp - argv = %d\n", pp-argv));
+#ifdef CMS_MVS
+            if (!uO.exdir && STRNICMP(*pp, "-d", 2) == 0) {
+#else
+            if (!uO.exdir && strncmp(*pp, "-d", 2) == 0) {
+#endif
+                int firstarg = (pp == argv);
+
+                uO.exdir = (*pp) + 2;
+                if (in_files) {      /* ... zipfile ... -d exdir ... */
+                    *pp = (char *)NULL;         /* terminate G.pfnames */
+                    G.filespecs = pp - G.pfnames;
+                    in_files = FALSE;
+                } else if (in_xfiles) {
+                    *pp = (char *)NULL;         /* terminate G.pxnames */
+                    G.xfilespecs = pp - G.pxnames;
+                    /* "... -x xlist -d exdir":  nothing left */
+                }
+                /* first check for "-dexdir", then for "-d exdir" */
+                if (*uO.exdir == '\0') {
+                    if (*++pp)
+                        uO.exdir = *pp;
+                    else {
+                        Info(slide, 0x401, ((char *)slide,
+                          LoadFarString(MustGiveExdir)));
+                        return(PK_PARAM);  /* don't extract here by accident */
+                    }
+                }
+                if (firstarg) { /* ... zipfile -d exdir ... */
+                    if (pp[1]) {
+                        G.pfnames = pp + 1;  /* argv+2 */
+                        G.filespecs = argc - (G.pfnames-argv);  /* for now... */
+                    } else {
+                        G.process_all_files = TRUE;
+                        G.pfnames = (char **)fnames;  /* GRR: necessary? */
+                        G.filespecs = 0;     /* GRR: necessary? */
+                        break;
+                    }
+                }
+            } else if (!in_xfiles) {
+                if (strcmp(*pp, "-x") == 0) {
+                    in_xfiles = TRUE;
+                    if (pp == G.pfnames) {
+                        G.pfnames = (char **)fnames;  /* defaults */
+                        G.filespecs = 0;
+                    } else if (in_files) {
+                        *pp = 0;                   /* terminate G.pfnames */
+                        G.filespecs = pp - G.pfnames;  /* adjust count */
+                        in_files = FALSE;
+                    }
+                    G.pxnames = pp + 1; /* excluded-names ptr starts after -x */
+                    G.xfilespecs = argc - (G.pxnames-argv);  /* anything left */
+                } else
+                    in_files = TRUE;
+            }
+        }
+    } else
+        G.process_all_files = TRUE;      /* for speed */
+
+    if (uO.exdir != (char *)NULL && !G.extract_flag)    /* -d ignored */
+        Info(slide, 0x401, ((char *)slide, LoadFarString(NotExtracting)));
+#endif /* ?(SFX && !SFX_EXDIR) */
+
+/*---------------------------------------------------------------------------
+    Okey dokey, we have everything we need to get started.  Let's roll.
+  ---------------------------------------------------------------------------*/
+
+    retcode = process_zipfiles(__G);
+    return(retcode);
+
+} /* end main()/unzip() */
+
+
+
+
+
+/**********************/
+/* Function uz_opts() */
+/**********************/
+
+int uz_opts(__G__ pargc, pargv)
+    __GDEF
+    int *pargc;
+    char ***pargv;
+{
+    char **argv, *s;
+    int argc, c, error=FALSE, negative=0;
+
+
+    argc = *pargc;
+    argv = *pargv;
+
+    while (++argv, (--argc > 0 && *argv != NULL && **argv == '-')) {
+        s = *argv + 1;
+        while ((c = *s++) != 0) {    /* "!= 0":  prevent Turbo C warning */
+#ifdef CMS_MVS
+            switch (tolower(c))
+#else
+            switch (c)
+#endif
+            {
+                case ('-'):
+                    ++negative;
+                    break;
+                case ('a'):
+                    if (negative) {
+                        uO.aflag = MAX(uO.aflag-negative,0);
+                        negative = 0;
+                    } else
+                        ++uO.aflag;
+                    break;
+#if (defined(DLL) && defined(API_DOC))
+                case ('A'):    /* extended help for API */
+                    APIhelp(__G__ argc, argv);
+                    *pargc = -1;  /* signal to exit successfully */
+                    return 0;
+#endif
+                case ('b'):
+                    if (negative) {
+#ifdef VMS
+                        uO.bflag = MAX(uO.bflag-negative,0);
+#endif
+                        negative = 0;   /* do nothing:  "-b" is default */
+                    } else {
+#ifdef VMS
+                        if (uO.aflag == 0)
+                           ++uO.bflag;
+#endif
+                        uO.aflag = 0;
+                    }
+                    break;
+#ifdef UNIXBACKUP
+                case ('B'): /* -B: back up existing files */
+                    if (negative)
+                        uO.B_flag = FALSE, negative = 0;
+                    else
+                        uO.B_flag = TRUE;
+                    break;
+#endif
+                case ('c'):
+                    if (negative) {
+                        uO.cflag = FALSE, negative = 0;
+#ifdef NATIVE
+                        uO.aflag = 0;
+#endif
+                    } else {
+                        uO.cflag = TRUE;
+#ifdef NATIVE
+                        uO.aflag = 2;   /* so you can read it on the screen */
+#endif
+#ifdef DLL
+                        if (G.redirect_text)
+                            G.redirect_data = 2;
+#endif
+                    }
+                    break;
+#ifndef CMS_MVS
+                case ('C'):    /* -C:  match filenames case-insensitively */
+                    if (negative)
+                        uO.C_flag = FALSE, negative = 0;
+                    else
+                        uO.C_flag = TRUE;
+                    break;
+#endif /* !CMS_MVS */
+#if (!defined(SFX) || defined(SFX_EXDIR))
+                case ('d'):
+                    if (negative) {   /* negative not allowed with -d exdir */
+                        Info(slide, 0x401, ((char *)slide,
+                          LoadFarString(MustGiveExdir)));
+                        return(PK_PARAM);  /* don't extract here by accident */
+                    }
+                    if (uO.exdir != (char *)NULL) {
+                        Info(slide, 0x401, ((char *)slide,
+                          LoadFarString(OnlyOneExdir)));
+                        return(PK_PARAM);    /* GRR:  stupid restriction? */
+                    } else {
+                        /* first check for "-dexdir", then for "-d exdir" */
+                        uO.exdir = s;
+                        if (*uO.exdir == '\0') {
+                            if (argc > 1) {
+                                --argc;
+                                uO.exdir = *++argv;
+                                if (*uO.exdir == '-') {
+                                    Info(slide, 0x401, ((char *)slide,
+                                      LoadFarString(MustGiveExdir)));
+                                    return(PK_PARAM);
+                                }
+                                /* else uO.exdir points at extraction dir */
+                            } else {
+                                Info(slide, 0x401, ((char *)slide,
+                                  LoadFarString(MustGiveExdir)));
+                                return(PK_PARAM);
+                            }
+                        }
+                        /* uO.exdir now points at extraction dir (-dexdir or
+                         *  -d exdir); point s at end of exdir to avoid mis-
+                         *  interpretation of exdir characters as more options
+                         */
+                        if (*s != 0)
+                            while (*++s != 0)
+                                ;
+                    }
+                    break;
+#endif /* !SFX || SFX_EXDIR */
+                case ('e'):    /* just ignore -e, -x options (extract) */
+                    break;
+#ifdef MACOS
+                case ('E'): /* -E [MacOS] display Mac e.f. when restoring */
+                    if( negative ) {
+                        uO.E_flag = FALSE, negative = 0;
+                    } else {
+                        uO.E_flag = TRUE;
+                    }
+                    break;
+#endif /* MACOS */
+                case ('f'):    /* "freshen" (extract only newer files) */
+                    if (negative)
+                        uO.fflag = uO.uflag = FALSE, negative = 0;
+                    else
+                        uO.fflag = uO.uflag = TRUE;
+                    break;
+#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))
+                case ('F'):    /* Acorn filetype & NFS extension handling */
+                    if (negative)
+                        uO.acorn_nfs_ext = FALSE, negative = 0;
+                    else
+                        uO.acorn_nfs_ext = TRUE;
+                    break;
+#endif /* RISCOS || ACORN_FTYPE_NFS */
+                case ('h'):    /* just print help message and quit */
+                    *pargc = -1;
+                    return USAGE(PK_OK);
+#ifdef MACOS
+                case ('i'): /* -i [MacOS] ignore filenames stored in Mac ef */
+                    if( negative ) {
+                        uO.i_flag = FALSE, negative = 0;
+                    } else {
+                        uO.i_flag = TRUE;
+                    }
+                    break;
+#endif  /* MACOS */
+                case ('j'):    /* junk pathnames/directory structure */
+                    if (negative)
+                        uO.jflag = FALSE, negative = 0;
+                    else
+                        uO.jflag = TRUE;
+                    break;
+#if (defined(__BEOS__) || defined(MACOS))
+                case ('J'):    /* Junk BeOS or MacOS file attributes */
+                    if( negative ) {
+                        uO.J_flag = FALSE, negative = 0;
+                    } else {
+                        uO.J_flag = TRUE;
+                    }
+                    break;
+#endif /* __BEOS__ || MACOS */
+#ifndef SFX
+                case ('l'):
+                    if (negative) {
+                        uO.vflag = MAX(uO.vflag-negative,0);
+                        negative = 0;
+                    } else
+                        ++uO.vflag;
+                    break;
+#endif /* !SFX */
+#ifndef CMS_MVS
+                case ('L'):    /* convert (some) filenames to lowercase */
+                    if (negative)
+                        uO.L_flag = FALSE, negative = 0;
+                    else
+                        uO.L_flag = TRUE;
+                    break;
+#endif /* !CMS_MVS */
+#ifdef MORE
+#ifdef CMS_MVS
+                case ('m'):
+#endif
+                case ('M'):    /* send all screen output through "more" fn. */
+/* GRR:  eventually check for numerical argument => height */
+                    if (negative)
+                        G.M_flag = FALSE, negative = 0;
+                    else
+                        G.M_flag = TRUE;
+                    break;
+#endif /* MORE */
+                case ('n'):    /* don't overwrite any files */
+                    if (negative)
+                        uO.overwrite_none = FALSE, negative = 0;
+                    else
+                        uO.overwrite_none = TRUE;
+                    break;
+#ifdef AMIGA
+                case ('N'):    /* restore comments as filenotes */
+                    if (negative)
+                        uO.N_flag = FALSE, negative = 0;
+                    else
+                        uO.N_flag = TRUE;
+                    break;
+#endif /* AMIGA */
+                case ('o'):    /* OK to overwrite files without prompting */
+                    if (negative) {
+                        uO.overwrite_all = MAX(uO.overwrite_all-negative,0);
+                        negative = 0;
+                    } else
+                        ++uO.overwrite_all;
+                    break;
+                case ('p'):    /* pipes:  extract to stdout, no messages */
+                    if (negative) {
+                        uO.cflag = FALSE;
+                        uO.qflag = MAX(uO.qflag-999,0);
+                        negative = 0;
+                    } else {
+                        uO.cflag = TRUE;
+                        uO.qflag += 999;
+                    }
+                    break;
+#if CRYPT
+                /* GRR:  yes, this is highly insecure, but dozens of people
+                 * have pestered us for this, so here we go... */
+                case ('P'):
+                    if (negative) {   /* negative not allowed with -P passwd */
+                        Info(slide, 0x401, ((char *)slide,
+                          LoadFarString(MustGivePasswd)));
+                        return(PK_PARAM);  /* don't extract here by accident */
+                    }
+                    if (uO.pwdarg != (char *)NULL) {
+/*
+                        GRR:  eventually support multiple passwords?
+                        Info(slide, 0x401, ((char *)slide,
+                          LoadFarString(OnlyOnePasswd)));
+                        return(PK_PARAM);
+ */
+                    } else {
+                        /* first check for "-Ppasswd", then for "-P passwd" */
+                        uO.pwdarg = s;
+                        if (*uO.pwdarg == '\0') {
+                            if (argc > 1) {
+                                --argc;
+                                uO.pwdarg = *++argv;
+                                if (*uO.pwdarg == '-') {
+                                    Info(slide, 0x401, ((char *)slide,
+                                      LoadFarString(MustGivePasswd)));
+                                    return(PK_PARAM);
+                                }
+                                /* else pwdarg points at decryption password */
+                            } else {
+                                Info(slide, 0x401, ((char *)slide,
+                                  LoadFarString(MustGivePasswd)));
+                                return(PK_PARAM);
+                            }
+                        }
+                        /* pwdarg now points at decryption password (-Ppasswd or
+                         *  -P passwd); point s at end of passwd to avoid mis-
+                         *  interpretation of passwd characters as more options
+                         */
+                        if (*s != 0)
+                            while (*++s != 0)
+                                ;
+                    }
+                    break;
+#endif /* CRYPT */
+                case ('q'):    /* quiet:  fewer comments/messages */
+                    if (negative) {
+                        uO.qflag = MAX(uO.qflag-negative,0);
+                        negative = 0;
+                    } else
+                        ++uO.qflag;
+                    break;
+#ifdef QDOS
+                case ('Q'):   /* QDOS flags */
+                    qlflag ^= strtol(s, &s, 10);
+                    break;    /* we XOR this as we can config qlflags */
+#endif
+#ifdef DOS_FLX_OS2_W32
+                case ('s'):    /* spaces in filenames:  allow by default */
+                    if (negative)
+                        uO.sflag = FALSE, negative = 0;
+                    else
+                        uO.sflag = TRUE;
+                    break;
+#endif /* DOS_FLX_OS2_W32 */
+                case ('t'):
+                    if (negative)
+                        uO.tflag = FALSE, negative = 0;
+                    else
+                        uO.tflag = TRUE;
+                    break;
+#ifdef TIMESTAMP
+                case ('T'):
+                    if (negative)
+                        uO.T_flag = FALSE, negative = 0;
+                    else
+                        uO.T_flag = TRUE;
+                    break;
+#endif
+                case ('u'):    /* update (extract only new and newer files) */
+                    if (negative)
+                        uO.uflag = FALSE, negative = 0;
+                    else
+                        uO.uflag = TRUE;
+                    break;
+#ifndef CMS_MVS
+                case ('U'):    /* obsolete; to be removed in version 6.0 */
+                    if (negative)
+                        uO.L_flag = TRUE, negative = 0;
+                    else
+                        uO.L_flag = FALSE;
+                    break;
+#endif /* !CMS_MVS */
+#ifndef SFX
+                case ('v'):    /* verbose */
+                    if (negative) {
+                        uO.vflag = MAX(uO.vflag-negative,0);
+                        negative = 0;
+                    } else if (uO.vflag)
+                        ++uO.vflag;
+                    else
+                        uO.vflag = 2;
+                    break;
+#endif /* !SFX */
+#ifndef CMS_MVS
+                case ('V'):    /* Version (retain VMS/DEC-20 file versions) */
+                    if (negative)
+                        uO.V_flag = FALSE, negative = 0;
+                    else
+                        uO.V_flag = TRUE;
+                    break;
+#endif /* !CMS_MVS */
+                case ('x'):    /* extract:  default */
+#ifdef SFX
+                    /* when 'x' is the only option in this argument, and the
+                     * next arg is not an option, assume this initiates an
+                     * exclusion list (-x xlist):  terminate option-scanning
+                     * and leave uz_opts with argv still pointing to "-x";
+                     * the xlist is processed later
+                     */
+                    if (s - argv[0] == 2 && *s == '\0' &&
+                        argc > 1 && argv[1][0] != '-') {
+                        /* break out of nested loops without "++argv;--argc" */
+                        goto opts_done;
+                    }
+#endif /* SFX */
+                    break;
+#if (defined(RESTORE_UIDGID) || defined(OS2_W32))
+                case ('X'):   /* restore owner/protection info (need privs?) */
+                    if (negative) {
+                        uO.X_flag = MAX(uO.X_flag-negative,0);
+                        negative = 0;
+                    } else
+                        ++uO.X_flag;
+                    break;
+#endif /* RESTORE_UIDGID || OS2_W32 */
+                case ('z'):    /* display only the archive comment */
+                    if (negative) {
+                        uO.zflag = MAX(uO.zflag-negative,0);
+                        negative = 0;
+                    } else
+                        ++uO.zflag;
+                    break;
+#ifndef SFX
+                case ('Z'):    /* should have been first option (ZipInfo) */
+                    Info(slide, 0x401, ((char *)slide, LoadFarString(Zfirst)));
+                    error = TRUE;
+                    break;
+#endif /* !SFX */
+#ifdef DOS_OS2_W32
+                case ('$'):
+                    if (negative) {
+                        uO.volflag = MAX(uO.volflag-negative,0);
+                        negative = 0;
+                    } else
+                        ++uO.volflag;
+                    break;
+#endif /* DOS_OS2_W32 */
+                default:
+                    error = TRUE;
+                    break;
+
+            } /* end switch */
+        } /* end while (not end of argument string) */
+    } /* end while (not done with switches) */
+
+/*---------------------------------------------------------------------------
+    Check for nonsensical combinations of options.
+  ---------------------------------------------------------------------------*/
+
+#ifdef SFX
+opts_done:  /* yes, very ugly...but only used by UnZipSFX with -x xlist */
+#endif
+
+    if ((uO.cflag && uO.tflag) || (uO.cflag && uO.uflag) ||
+        (uO.tflag && uO.uflag) || (uO.fflag && uO.overwrite_none))
+    {
+        Info(slide, 0x401, ((char *)slide, LoadFarString(InvalidOptionsMsg)));
+        error = TRUE;
+    }
+    if (uO.aflag > 2)
+        uO.aflag = 2;
+#ifdef VMS
+    if (uO.bflag > 2)
+        uO.bflag = 2;
+#endif
+    if (uO.overwrite_all && uO.overwrite_none) {
+        Info(slide, 0x401, ((char *)slide, LoadFarString(IgnoreOOptionMsg)));
+        uO.overwrite_all = FALSE;
+    }
+#ifdef MORE
+    if (G.M_flag && !isatty(1))  /* stdout redirected: "more" func. useless */
+        G.M_flag = 0;
+#endif
+
+#ifdef SFX
+    if (error)
+#else
+    if ((argc-- == 0) || error)
+#endif
+    {
+        *pargc = argc;
+        *pargv = argv;
+#ifndef SFX
+        if (uO.vflag >= 2 && argc == -1) {              /* "unzip -v" */
+            show_version_info(__G);
+            return PK_OK;
+        }
+        if (!G.noargs && !error)
+            error = PK_PARAM;   /* had options (not -h or -v) but no zipfile */
+#endif /* !SFX */
+        return USAGE(error);
+    }
+
+#ifdef SFX
+    /* print our banner unless we're being fairly quiet */
+    if (uO.qflag < 2)
+        Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner),
+          UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, BETALEVEL,
+          LoadFarStringSmall(VersionDate)));
+#ifdef BETA
+    /* always print the beta warning:  no unauthorized distribution!! */
+    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n",
+      "SFX"));
+#endif
+#endif /* SFX */
+
+    if (uO.cflag || uO.tflag || uO.vflag || uO.zflag
+#ifdef TIMESTAMP
+                                                     || uO.T_flag
+#endif
+                                                                 )
+        G.extract_flag = FALSE;
+    else
+        G.extract_flag = TRUE;
+
+    *pargc = argc;
+    *pargv = argv;
+    return PK_OK;
+
+} /* end function uz_opts() */
+
+
+
+
+/********************/
+/* Function usage() */
+/********************/
+
+#ifdef SFX
+#  ifdef VMS
+#    define LOCAL "X.  Quote uppercase options"
+#  endif
+#  ifdef UNIX
+#    define LOCAL "X"
+#  endif
+#  ifdef DOS_OS2_W32
+#    define LOCAL "s$"
+#  endif
+#  ifdef FLEXOS
+#    define LOCAL "s"
+#  endif
+#  ifdef AMIGA
+#    define LOCAL "N"
+#  endif
+   /* Default for all other systems: */
+#  ifndef LOCAL
+#    define LOCAL ""
+#  endif
+
+#  ifdef MORE
+#    define SFXOPT1 "M"
+#  else
+#    define SFXOPT1 ""
+#  endif
+
+int usage(__G__ error)   /* return PK-type error code */
+    __GDEF
+    int error;
+{
+    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner),
+      UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, BETALEVEL,
+      LoadFarStringSmall(VersionDate)));
+    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXOpts),
+      SFXOPT1, LOCAL));
+#ifdef BETA
+    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n",
+      "SFX"));
+#endif
+
+    if (error)
+        return PK_PARAM;
+    else
+        return PK_COOL;     /* just wanted usage screen: no error */
+
+} /* end function usage() */
+
+
+
+
+
+#else /* !SFX */
+#  ifdef VMS
+#    define QUOT '\"'
+#    define QUOTS "\""
+#  else
+#    define QUOT ' '
+#    define QUOTS ""
+#  endif
+
+int usage(__G__ error)   /* return PK-type error code */
+    __GDEF
+    int error;
+{
+    int flag = (error? 1 : 0);
+
+
+/*---------------------------------------------------------------------------
+    Print either ZipInfo usage or UnZip usage, depending on incantation.
+    (Strings must be no longer than 512 bytes for Turbo C, apparently.)
+  ---------------------------------------------------------------------------*/
+
+    if (uO.zipinfo_mode) {
+
+#ifndef NO_ZIPINFO
+
+        Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine1),
+          ZI_MAJORVER, ZI_MINORVER, PATCHLEVEL, BETALEVEL,
+          LoadFarStringSmall(VersionDate),
+          LoadFarStringSmall2(ZipInfoExample), QUOTS,QUOTS));
+        Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine2)));
+        Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine3),
+          QUOT,QUOT, QUOT,QUOT, LoadFarStringSmall(ZipInfoUsageLine4)));
+#ifdef VMS
+        Info(slide, flag, ((char *)slide, "\nRemember that non-lowercase\
+ filespecs must be quoted in VMS (e.g., \"Makefile\").\n"));
+#endif
+
+#endif /* !NO_ZIPINFO */
+
+    } else {   /* UnZip mode */
+
+        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine1),
+          UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, BETALEVEL,
+          LoadFarStringSmall(VersionDate)));
+#ifdef BETA
+        Info(slide, flag, ((char *)slide, LoadFarString(BetaVersion), "", ""));
+#endif
+
+        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine2),
+          ZIPINFO_MODE_OPTION, LoadFarStringSmall(ZipInfoMode)));
+#ifdef VMS
+        if (!error)  /* maybe no command-line tail found; show extra help */
+            Info(slide, flag, ((char *)slide, LoadFarString(VMSusageLine2b)));
+#endif
+
+        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine3),
+          LoadFarStringSmall(local1)));
+
+        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine4),
+          QUOT,QUOT, QUOT,QUOT, LoadFarStringSmall(local2), QUOT,QUOT,
+          LoadFarStringSmall2(local3)));
+
+        /* This is extra work for SMALL_MEM, but it will work since
+         * LoadFarStringSmall2 uses the same buffer.  Remember, this
+         * is a hack. */
+        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine5),
+          LoadFarStringSmall(Example2), LoadFarStringSmall2(Example3),
+          LoadFarStringSmall2(Example3)));
+
+    } /* end if (uO.zipinfo_mode) */
+
+    if (error)
+        return PK_PARAM;
+    else
+        return PK_COOL;     /* just wanted usage screen: no error */
+
+} /* end function usage() */
+
+#endif /* ?SFX */
+
+
+
+
+#ifndef SFX
+
+/********************************/
+/* Function show_version_info() */
+/********************************/
+
+static void show_version_info(__G)
+    __GDEF
+{
+    if (uO.qflag > 3)                           /* "unzip -vqqqq" */
+        Info(slide, 0, ((char *)slide, "%d\n",
+          (UZ_MAJORVER*100 + UZ_MINORVER*10 + PATCHLEVEL)));
+    else {
+        char *envptr, *getenv();
+        int numopts = 0;
+
+        Info(slide, 0, ((char *)slide, LoadFarString(UnzipUsageLine1v),
+          UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, BETALEVEL,
+          LoadFarStringSmall(VersionDate)));
+        Info(slide, 0, ((char *)slide,
+          LoadFarString(UnzipUsageLine2v)));
+        version(__G);
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptions)));
+#ifdef ACORN_FTYPE_NFS
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(AcornFtypeNFS)));
+        ++numopts;
+#endif
+#ifdef ASM_CRC
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(AsmCRC)));
+        ++numopts;
+#endif
+#ifdef ASM_INFLATECODES
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(AsmInflateCodes)));
+        ++numopts;
+#endif
+#ifdef CHECK_VERSIONS
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(Check_Versions)));
+        ++numopts;
+#endif
+#ifdef COPYRIGHT_CLEAN
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(Copyright_Clean)));
+        ++numopts;
+#endif
+#ifdef DEBUG
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(UDebug)));
+        ++numopts;
+#endif
+#ifdef DEBUG_TIME
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(DebugTime)));
+        ++numopts;
+#endif
+#ifdef DLL
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(Dll)));
+        ++numopts;
+#endif
+#ifdef DOSWILD
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(DosWild)));
+        ++numopts;
+#endif
+#ifdef LZW_CLEAN
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(LZW_Clean)));
+        ++numopts;
+#endif
+#ifndef MORE
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(No_More)));
+        ++numopts;
+#endif
+#ifdef NO_ZIPINFO
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(No_ZipInfo)));
+        ++numopts;
+#endif
+#ifdef NTSD_EAS
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(NTSDExtAttrib)));
+        ++numopts;
+#endif
+#ifdef OS2_EAS
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(OS2ExtAttrib)));
+        ++numopts;
+#endif
+#ifdef QLZIP
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(SMSExFldOnUnix)));
+        ++numopts;
+#endif
+#ifdef REENTRANT
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(Reentrant)));
+        ++numopts;
+#endif
+#ifdef REGARGS
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(RegArgs)));
+        ++numopts;
+#endif
+#ifdef RETURN_CODES
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(Return_Codes)));
+        ++numopts;
+#endif
+#ifdef SET_DIR_ATTRIB
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(SetDirAttrib)));
+        ++numopts;
+#endif
+#ifdef TIMESTAMP
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(TimeStamp)));
+        ++numopts;
+#endif
+#ifdef UNIXBACKUP
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(UnixBackup)));
+        ++numopts;
+#endif
+#ifdef USE_EF_UT_TIME
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(Use_EF_UT_time)));
+        ++numopts;
+#endif
+#ifndef COPYRIGHT_CLEAN
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(Use_Smith_Code)));
+        ++numopts;
+#endif
+#ifndef LZW_CLEAN
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(Use_Unshrink)));
+        ++numopts;
+#endif
+#ifdef USE_VFAT
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(Use_VFAT_support)));
+        ++numopts;
+#endif
+#ifdef USE_ZLIB
+        sprintf((char *)(slide+256), LoadFarStringSmall(UseZlib),
+          ZLIB_VERSION, zlib_version);
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          (char *)(slide+256)));
+        ++numopts;
+#endif
+#ifdef VMS_TEXT_CONV
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(VmsTextConv)));
+        ++numopts;
+#endif
+#ifdef VMSCLI
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(VmsCLI)));
+        ++numopts;
+#endif
+#ifdef VMSWILD
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(VmsWild)));
+        ++numopts;
+#endif
+#if CRYPT
+# ifdef PASSWD_FROM_STDIN
+        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
+          LoadFarStringSmall(PasswdStdin)));
+# endif
+        Info(slide, 0, ((char *)slide, LoadFarString(Decryption),
+          CR_MAJORVER, CR_MINORVER, CR_BETA_VER,
+          LoadFarStringSmall(CryptDate)));
+        ++numopts;
+#endif /* CRYPT */
+        if (numopts == 0)
+            Info(slide, 0, ((char *)slide,
+              LoadFarString(CompileOptFormat),
+              LoadFarStringSmall(None)));
+
+        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptions)));
+        envptr = getenv(LoadFarStringSmall(EnvUnZip));
+        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
+          LoadFarStringSmall(EnvUnZip),
+          (envptr == (char *)NULL || *envptr == 0)?
+          LoadFarStringSmall2(None) : envptr));
+        envptr = getenv(LoadFarStringSmall(EnvUnZip2));
+        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
+          LoadFarStringSmall(EnvUnZip2),
+          (envptr == (char *)NULL || *envptr == 0)?
+          LoadFarStringSmall2(None) : envptr));
+        envptr = getenv(LoadFarStringSmall(EnvZipInfo));
+        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
+          LoadFarStringSmall(EnvZipInfo),
+          (envptr == (char *)NULL || *envptr == 0)?
+          LoadFarStringSmall2(None) : envptr));
+        envptr = getenv(LoadFarStringSmall(EnvZipInfo2));
+        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
+          LoadFarStringSmall(EnvZipInfo2),
+          (envptr == (char *)NULL || *envptr == 0)?
+          LoadFarStringSmall2(None) : envptr));
+#ifndef __RSXNT__
+#ifdef __EMX__
+        envptr = getenv(LoadFarStringSmall(EnvEMX));
+        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
+          LoadFarStringSmall(EnvEMX),
+          (envptr == (char *)NULL || *envptr == 0)?
+          LoadFarStringSmall2(None) : envptr));
+        envptr = getenv(LoadFarStringSmall(EnvEMXOPT));
+        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
+          LoadFarStringSmall(EnvEMXOPT),
+          (envptr == (char *)NULL || *envptr == 0)?
+          LoadFarStringSmall2(None) : envptr));
+#endif /* __EMX__ */
+#if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2)))
+        envptr = getenv(LoadFarStringSmall(EnvGO32));
+        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
+          LoadFarStringSmall(EnvGO32),
+          (envptr == (char *)NULL || *envptr == 0)?
+          LoadFarStringSmall2(None) : envptr));
+        envptr = getenv(LoadFarStringSmall(EnvGO32TMP));
+        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
+          LoadFarStringSmall(EnvGO32TMP),
+          (envptr == (char *)NULL || *envptr == 0)?
+          LoadFarStringSmall2(None) : envptr));
+#endif /* __GO32__ && !(__DJGPP__ >= 2) */
+#endif /* !__RSXNT__ */
+#ifdef RISCOS
+        envptr = getenv(LoadFarStringSmall(EnvUnZipExts));
+        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
+          LoadFarStringSmall(EnvUnZipExts),
+          (envptr == (char *)NULL || *envptr == 0)?
+          LoadFarStringSmall2(None) : envptr));
+#endif /* RISCOS */
+    }
+} /* end function show_version() */
+
+#endif /* !SFX */
+#endif /* !WINDLL */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/unzipstb.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,48 @@
+/*---------------------------------------------------------------------------
+
+  unzipstb.c
+
+  Simple stub function for UnZip DLL (or shared library, whatever); does
+  exactly the same thing as normal UnZip, except for additional printf()s
+  of various version numbers, solely as a demonstration of what can/should
+  be checked when using the DLL.  (If major version numbers ever differ,
+  assume program is incompatible with DLL--especially if DLL version is
+  older.  This is not likely to be a problem with *this* simple program,
+  but most user programs will be much more complex.)
+
+  ---------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include "unzip.h"
+#include "version.h"
+
+int main(int argc, char *argv[])
+{
+    static UzpVer *pVersion;   /* no pervert jokes, please... */
+
+    pVersion = UzpVersion();
+
+    printf("UnZip stub:  checking version numbers (DLL is dated %s)\n",
+      pVersion->date);
+    printf("   UnZip versions:    expecting %d.%d%d, using %d.%d%d%s\n",
+      UZ_MAJORVER, UZ_MINORVER, PATCHLEVEL, pVersion->unzip.major,
+      pVersion->unzip.minor, pVersion->unzip.patchlevel, pVersion->betalevel);
+    printf("   ZipInfo versions:  expecting %d.%d%d, using %d.%d%d\n",
+      ZI_MAJORVER, ZI_MINORVER, PATCHLEVEL, pVersion->zipinfo.major,
+      pVersion->zipinfo.minor, pVersion->zipinfo.patchlevel);
+
+/*
+    D2_M*VER and os2dll.* are obsolete, though retained for compatibility:
+
+    printf("   OS2 DLL versions:  expecting %d.%d%d, using %d.%d%d\n",
+      D2_MAJORVER, D2_MINORVER, PATCHLEVEL, pVersion->os2dll.major,
+      pVersion->os2dll.minor, pVersion->os2dll.patchlevel);
+ */
+
+    if (pVersion->flag & 2)
+        printf("   using zlib version %s\n", pVersion->zlib_version);
+    printf("\n");
+
+    /* call the actual UnZip routine (string-arguments version) */
+    return UzpMain(argc, argv);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/win32.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,2390 @@
+/*---------------------------------------------------------------------------
+
+  win32.c
+
+  32-bit Windows-specific (NT/95) routines for use with Info-ZIP's UnZip 5.3
+  and later.
+
+  Contains:  GetLoadPath()
+             Opendir()
+             Readdir()
+             Closedir()
+             process_defer_NT()   process any deferred items
+             SetSD()              set security descriptor on file
+             EvalExtraFields()    evaluate and process and extra field NOW
+             IsWinNT()            indicate type of WIN32 platform
+             test_NTSD()          test integrity of NT security data
+             utime2FileTime()
+             FStampIsLocTime()
+             FileTime2utime()
+             VFatFileTime2utime()
+             UTCtime2Localtime()
+             NTtzbugWorkaround()
+             getNTfiletime()
+             close_outfile()
+             stamp_file()
+             isfloppy()
+             NTQueryVolInfo()
+             IsVolumeOldFAT()
+             do_wild()
+             mapattr()
+             mapname()
+             map2fat()
+             checkdir()
+             version()
+             zstat_win32()
+             getch_win32()
+
+  ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+#include <windows.h>    /* must be AFTER unzip.h to avoid struct G problems */
+#ifdef __RSXNT__
+#  include "rsxntwin.h"
+#endif
+#include "nt.h"
+
+#ifndef FUNZIP          /* most of this file is not used with fUnZip */
+
+#if (defined(__GO32__) || defined(__EMX__) || defined(__CYGWIN32__))
+#  define MKDIR(path,mode)   mkdir(path,mode)
+#else
+#  define MKDIR(path,mode)   mkdir(path)
+#endif
+
+#ifdef HAVE_WORKING_DIRENT_H
+#  undef HAVE_WORKING_DIRENT_H
+#endif
+/* The emxrtl dirent support of (__GO32__ || __EMX__) converts to lowercase! */
+#if defined(__CYGWIN32__)
+#  define HAVE_WORKING_DIRENT_H
+#endif
+
+#ifndef SFX
+#  ifdef HAVE_WORKING_DIRENT_H
+#    include <dirent.h>         /* use readdir() */
+#    define zdirent  dirent
+#    define zDIR     DIR
+#    define Opendir  opendir
+#    define Readdir  readdir
+#    define Closedir closedir
+#  else /* !HAVE_WORKING_DIRENT_H */
+     typedef struct zdirent {
+         char    reserved [21];
+         char    ff_attrib;
+         short   ff_ftime;
+         short   ff_fdate;
+         long    size;
+         char    d_name[MAX_PATH];
+         int     d_first;
+         HANDLE  d_hFindFile;
+     } zDIR;
+
+     static zDIR           *Opendir  (const char *n);
+     static struct zdirent *Readdir  (zDIR *d);
+     static void            Closedir (zDIR *d);
+#  endif /* ?HAVE_WORKING_DIRENT_H */
+#endif /* !SFX */
+
+
+/* Function prototypes */
+#ifdef NTSD_EAS
+   static int  SetSD(__GPRO__ char *path, PVOLUMECAPS VolumeCaps,
+                     uch *eb_ptr, unsigned eb_len);
+   static int  EvalExtraFields(__GPRO__ char *path, uch *ef_ptr,
+                               unsigned ef_len);
+#endif
+
+#if (defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND) || \
+     defined(TIMESTAMP))
+   static void utime2FileTime(time_t ut, FILETIME *pft);
+   static int FStampIsLocTime(__GPRO__ const char *path);
+#endif /* USE_EF_UT_TIME || NT_TZBUG_WORKAROUND || TIMESTAMP */
+#ifdef NT_TZBUG_WORKAROUND
+   static int FileTime2utime(const FILETIME *pft, time_t *ut);
+#ifdef W32_STAT_BANDAID
+   static int VFatFileTime2utime(const FILETIME *pft, time_t *ut);
+#endif
+   static time_t UTCtime2Localtime(time_t utctime);
+   static void NTtzbugWorkaround(time_t ut, FILETIME *pft);
+#endif /* NT_TZBUG_WORKAROUND */
+
+static int  getNTfiletime   (__GPRO__ FILETIME *pModFT, FILETIME *pAccFT,
+                             FILETIME *pCreFT);
+static int  isfloppy        (int nDrive);
+static int  NTQueryVolInfo  (__GPRO__ const char *name);
+static int  IsVolumeOldFAT  (__GPRO__ const char *name);
+static void map2fat         (char *pathcomp, char **pEndFAT);
+
+
+#ifdef __MINGW32__
+   int _CRT_glob = 0;   /* suppress command line globbing by C RTL */
+#endif
+
+/* static int created_dir;      */     /* used by mapname(), checkdir() */
+/* static int renamed_fullpath; */     /* ditto */
+/* static int fnlen;            */     /* ditto */
+/* static unsigned nLabelDrive; */     /* ditto */
+
+extern char Far TruncNTSD[];    /* in extract.c */
+
+
+
+#ifdef SFX
+
+/**************************/
+/* Function GetLoadPath() */
+/**************************/
+
+char *GetLoadPath(__GPRO)
+{
+#ifdef MSC
+    extern char *_pgmptr;
+    return _pgmptr;
+
+#else    /* use generic API call */
+
+    GetModuleFileName(NULL, G.filename, FILNAMSIZ-1);
+    _ISO_INTERN(G.filename);    /* translate to codepage of C rtl's stdio */
+    return G.filename;
+#endif
+
+} /* end function GetLoadPath() */
+
+
+
+
+
+#else /* !SFX */
+
+#ifndef HAVE_WORKING_DIRENT_H
+
+/**********************/        /* Borrowed from ZIP 2.0 sources            */
+/* Function Opendir() */        /* Difference: no special handling for      */
+/**********************/        /*             hidden or system files.      */
+
+static zDIR *Opendir(n)
+    const char *n;          /* directory to open */
+{
+    zDIR *d;                /* malloc'd return value */
+    char *p;                /* malloc'd temporary string */
+    WIN32_FIND_DATA fd;
+    extent len = strlen(n);
+
+    /* Start searching for files in directory n */
+
+    if ((d = (zDIR *)malloc(sizeof(zDIR))) == NULL ||
+        (p = malloc(strlen(n) + 5)) == NULL)
+    {
+        if (d != (zDIR *)NULL)
+            free((void *)d);
+        return (zDIR *)NULL;
+    }
+    INTERN_TO_ISO(n, p);
+    if (len > 0) {
+        if (p[len-1] == ':')
+            p[len++] = '.';     /* x: => x:. */
+        else if (p[len-1] == '/' || p[len-1] == '\\')
+            --len;              /* foo/ => foo */
+    }
+    strcpy(p+len, "/*");
+
+    if (INVALID_HANDLE_VALUE == (d->d_hFindFile = FindFirstFile(p, &fd))) {
+        free((zvoid *)d);
+        free((zvoid *)p);
+        return NULL;
+    }
+    strcpy(d->d_name, fd.cFileName);
+
+    free((zvoid *)p);
+    d->d_first = 1;
+    return d;
+
+} /* end of function Opendir() */
+
+
+
+
+/**********************/        /* Borrowed from ZIP 2.0 sources            */
+/* Function Readdir() */        /* Difference: no special handling for      */
+/**********************/        /*             hidden or system files.      */
+
+static struct zdirent *Readdir(d)
+    zDIR *d;                    /* directory stream from which to read */
+{
+    /* Return pointer to first or next directory entry, or NULL if end. */
+
+    if ( d->d_first )
+        d->d_first = 0;
+    else
+    {
+        WIN32_FIND_DATA fd;
+
+        if ( !FindNextFile(d->d_hFindFile, &fd) )
+            return NULL;
+
+        ISO_TO_INTERN(fd.cFileName, d->d_name);
+    }
+    return (struct zdirent *)d;
+
+} /* end of function Readdir() */
+
+
+
+
+/***********************/
+/* Function Closedir() */       /* Borrowed from ZIP 2.0 sources */
+/***********************/
+
+static void Closedir(d)
+    zDIR *d;                    /* directory stream to close */
+{
+    FindClose(d->d_hFindFile);
+    free(d);
+}
+
+#endif /* !HAVE_WORKING_DIRENT_H */
+#endif /* ?SFX */
+
+
+
+
+#ifdef NTSD_EAS
+
+/*********************************/
+/*  Function process_defer_NT()  */
+/*********************************/
+
+void process_defer_NT(__G)
+    __GDEF
+{
+    /* process deferred items */
+
+    DWORD dir, bytes;
+    DWORD dirfail, bytesfail;
+
+    ProcessDefer(&dir, &bytes, &dirfail, &bytesfail);
+
+    if (!uO.tflag && (uO.qflag < 2)) {
+        if (dir)
+            Info(slide, 0, ((char *)slide,
+              "    updated: %lu directory entries with %lu bytes security",
+              (ulg)dir, (ulg)bytes));
+        if (dirfail)
+            Info(slide, 0, ((char *)slide,
+              "     failed: %lu directory entries with %lu bytes security",
+              (ulg)dirfail, (ulg)bytesfail));
+    }
+}
+
+
+
+/**********************/
+/*  Function SetSD()  */   /* return almost-PK errors */
+/**********************/
+
+static int SetSD(__G__ path, VolumeCaps, eb_ptr, eb_len)
+    __GDEF
+    char *path;
+    PVOLUMECAPS VolumeCaps;
+    uch *eb_ptr;
+    unsigned eb_len;
+{
+    ulg ntsd_ucSize;
+    uch *security_data;
+    int error;
+
+    if (eb_ptr == NULL || eb_len < EB_NTSD_L_LEN)
+        return PK_OK;  /* not a valid NTSD extra field:  assume OK */
+
+    /* check if we know how to handle this version */
+    if (*(eb_ptr + (EB_HEADSIZE+EB_NTSD_VERSION)) > (uch)EB_NTSD_MAX_VER)
+        return PK_OK;
+
+    ntsd_ucSize = makelong(eb_ptr + (EB_HEADSIZE+EB_UCSIZE_P));
+    if (ntsd_ucSize > 0L && eb_len <= (EB_NTSD_L_LEN + EB_CMPRHEADLEN))
+        return IZ_EF_TRUNC;               /* no compressed data! */
+
+    /* allocate storage for uncompressed data */
+    security_data = (uch *)malloc((extent)ntsd_ucSize);
+    if (security_data == (uch *)NULL)
+        return PK_MEM4;
+
+    error = memextract(__G__ security_data, ntsd_ucSize,
+      (eb_ptr + (EB_HEADSIZE+EB_NTSD_L_LEN)), (ulg)(eb_len - EB_NTSD_L_LEN));
+
+    if (error == PK_OK) {
+        if (SecuritySet(path, VolumeCaps, security_data)) {
+            error = PK_COOL;
+            if (!uO.tflag && (uO.qflag < 2) &&
+                (!(VolumeCaps->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)))
+                Info(slide, 0, ((char *)slide, " (%ld bytes security)",
+                  ntsd_ucSize));
+        }
+    }
+
+    free(security_data);
+    return error;
+}
+
+
+
+
+/********************************/   /* scan extra fields for something */
+/*  Function EvalExtraFields()  */   /*  we happen to know */
+/********************************/
+
+static int EvalExtraFields(__G__ path, ef_ptr, ef_len)
+    __GDEF
+    char *path;
+    uch *ef_ptr;
+    unsigned ef_len;
+{
+    int rc = PK_OK;
+
+    if (!uO.X_flag)
+        return PK_OK;  /* user said don't process ACLs; for now, no other
+                          extra block types are handled here */
+
+    while (ef_len >= EB_HEADSIZE)
+    {
+        unsigned eb_id = makeword(EB_ID + ef_ptr);
+        unsigned eb_len = makeword(EB_LEN + ef_ptr);
+
+        if (eb_len > (ef_len - EB_HEADSIZE)) {
+            /* discovered some extra field inconsistency! */
+            Trace((stderr,
+              "EvalExtraFields: block length %u > rest ef_size %u\n", eb_len,
+              ef_len - EB_HEADSIZE));
+            break;
+        }
+
+        switch (eb_id)
+        {
+            /* process security descriptor extra data if:
+                 Caller is WinNT AND
+                 Target local/remote drive supports acls AND
+                 Target file is not a directory (else we defer processing
+                   until later)
+             */
+            case EF_NTSD:
+                if (IsWinNT()) {
+                    VOLUMECAPS VolumeCaps;
+
+                    /* provide useful input */
+                    VolumeCaps.dwFileAttributes = G.pInfo->file_attr;
+                    VolumeCaps.bUsePrivileges = (uO.X_flag > 1);
+
+                    /* check target volume capabilities - just fall through
+                     * and try if fail */
+                    if (GetVolumeCaps(G.rootpath, path, &VolumeCaps) &&
+                        !(VolumeCaps.dwFileSystemFlags & FS_PERSISTENT_ACLS))
+                    {
+                        rc = PK_OK;
+                        break;
+                    }
+                    rc = SetSD(__G__ path, &VolumeCaps, ef_ptr, eb_len);
+                } else
+                    rc = PK_OK;
+                break;
+
+#if 0
+            /* perhaps later we can add support for unzipping OS/2 EAs to NT */
+            case EF_OS2:
+                rc = SetEAs(__G__ path, ef_ptr);
+                break;
+
+            case EF_PKUNIX:
+            case EF_IZUNIX:
+            case EF_IZUNIX2:
+            case EF_TIME:
+                break;          /* handled elsewhere */
+#else /* ! 0 */
+#ifdef DEBUG
+            case EF_AV:
+            case EF_OS2:
+            case EF_PKVMS:
+            case EF_PKW32:
+            case EF_PKUNIX:
+            case EF_IZVMS:
+            case EF_IZUNIX:
+            case EF_IZUNIX2:
+            case EF_TIME:
+            case EF_MAC3:
+            case EF_JLMAC:
+            case EF_ZIPIT:
+            case EF_VMCMS:
+            case EF_MVS:
+            case EF_ACL:
+            case EF_BEOS:
+            case EF_QDOS:
+            case EF_AOSVS:
+            case EF_SPARK:
+            case EF_MD5:
+            case EF_ASIUNIX:
+                break;          /* shut up for other known e.f. blocks  */
+#endif /* DEBUG */
+#endif /* ? 0 */
+
+            default:
+                Trace((stderr,
+                  "EvalExtraFields: unknown extra field block, ID=%u\n",
+                  eb_id));
+                break;
+        }
+
+        ef_ptr += (eb_len + EB_HEADSIZE);
+        ef_len -= (eb_len + EB_HEADSIZE);
+
+        if (rc != PK_OK)
+            break;
+    }
+
+    return rc;
+}
+
+
+
+
+#ifndef SFX
+
+/**************************/
+/*  Function test_NTSD()  */   /*  returns PK_WARN when NTSD data is invalid */
+/**************************/
+
+#ifdef __BORLANDC__
+/* Turn off warning about not using all parameters for this function only */
+#pragma argsused
+#endif
+int test_NTSD(__G__ eb, eb_size, eb_ucptr, eb_ucsize)
+    __GDEF
+    uch *eb;
+    unsigned eb_size;
+    uch *eb_ucptr;
+    ulg eb_ucsize;
+{
+    int r = PK_OK;
+
+    if (!ValidateSecurity(eb_ucptr))
+        r = PK_WARN;
+    return r;
+
+} /* end function test_NTSD() */
+
+#endif /* !SFX */
+#endif /* NTSD_EAS */
+
+
+
+
+/**********************/
+/* Function IsWinNT() */
+/**********************/
+
+int IsWinNT(void)       /* returns TRUE if real NT, FALSE if Win95 or Win32s */
+{
+    static DWORD g_PlatformId = 0xFFFFFFFF; /* saved platform indicator */
+
+    if (g_PlatformId == 0xFFFFFFFF) {
+        /* note: GetVersionEx() doesn't exist on WinNT 3.1 */
+        if (GetVersion() < 0x80000000)
+            g_PlatformId = TRUE;
+        else
+            g_PlatformId = FALSE;
+    }
+    return (int)g_PlatformId;
+}
+
+
+/* DEBUG_TIME insertion: */
+#ifdef DEBUG_TIME
+static int show_NTFileTime(FILE *hdo, char *TTmsg, int isloc, FILETIME *pft);
+
+static int show_NTFileTime(FILE *hdo, char *TTmsg, int isloc, FILETIME *pft)
+{
+    SYSTEMTIME w32tm;
+    int rval;
+
+    rval = FileTimeToSystemTime(pft, &w32tm);
+    if (!rval) {
+        fprintf(hdo, "%s\n %08lX,%08lX (%s) -> Conversion failed !!!\n",
+                TTmsg, (ulg)(pft->dwHighDateTime), (ulg)(pft->dwLowDateTime),
+                (isloc ? "local" : "UTC"));
+    } else {
+        fprintf(hdo, "%s\n %08lx,%08lx -> %04u-%02u-%02u, %02u:%02u:%02u %s\n",
+                TTmsg, (ulg)(pft->dwHighDateTime), (ulg)(pft->dwLowDateTime),
+                w32tm.wYear, w32tm.wMonth, w32tm.wDay, w32tm.wHour,
+                w32tm.wMinute, w32tm.wSecond, (isloc ? "local" : "UTC"));
+    }
+    return rval;
+}
+#define FTTrace(x)   show_NTFileTime x
+#else
+#define FTTrace(x)
+#endif /* DEBUG_TIME */
+/* end of TIME_DEBUG insertion */
+
+#if (defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND) || \
+     defined(TIMESTAMP))
+
+#if ((defined(__GNUC__) || defined(ULONG_LONG_MAX)) && !defined(HAVE_INT64))
+   typedef long long            LLONG64;
+   typedef unsigned long long   ULLNG64;
+#  define HAVE_INT64
+#endif
+#if (defined(__WATCOMC__) && (__WATCOMC__ >= 1100) && !defined(HAVE_INT64))
+   typedef __int64              LLONG64;
+   typedef unsigned __int64     ULLNG64;
+#  define HAVE_INT64
+#endif
+#if (defined(_MSC_VER) && (_MSC_VER >= 1100) && !defined(HAVE_INT64))
+   typedef __int64              LLONG64;
+   typedef unsigned __int64     ULLNG64;
+#  define HAVE_INT64
+#endif
+
+/*****************************/
+/* Function utime2FileTime() */     /* convert Unix time_t format into the */
+/*****************************/     /* form used by SetFileTime() in NT/95 */
+
+#define UNIX_TIME_ZERO_HI  0x019DB1DEUL
+#define UNIX_TIME_ZERO_LO  0xD53E8000UL
+#define NT_QUANTA_PER_UNIX 10000000L
+
+static void utime2FileTime(time_t ut, FILETIME *pft)
+{
+#ifdef HAVE_INT64
+    ULLNG64 NTtime;
+
+    /* NT_QUANTA_PER_UNIX is small enough so that "ut * NT_QUANTA_PER_UNIX"
+     * cannot overflow in 64-bit signed calculation, regardless wether "ut"
+     * is signed or unsigned.  */
+    NTtime = ((LLONG64)ut * NT_QUANTA_PER_UNIX) +
+             ((ULLNG64)UNIX_TIME_ZERO_LO + ((ULLNG64)UNIX_TIME_ZERO_HI << 32));
+    pft->dwLowDateTime = (DWORD)NTtime;
+    pft->dwHighDateTime = (DWORD)(NTtime >> 32);
+
+#else /* !HAVE_INT64 (64-bit integer arithmetics may not be supported) */
+    unsigned int b1, b2, carry = 0;
+    unsigned long r0, r1, r2, r3;
+    long r4;            /* signed, to catch environments with signed time_t */
+
+    b1 = ut & 0xFFFF;
+    b2 = (ut >> 16) & 0xFFFF;       /* if ut is over 32 bits, too bad */
+    r1 = b1 * (NT_QUANTA_PER_UNIX & 0xFFFF);
+    r2 = b1 * (NT_QUANTA_PER_UNIX >> 16);
+    r3 = b2 * (NT_QUANTA_PER_UNIX & 0xFFFF);
+    r4 = b2 * (NT_QUANTA_PER_UNIX >> 16);
+    r0 = (r1 + (r2 << 16)) & 0xFFFFFFFFL;
+    if (r0 < r1)
+        carry++;
+    r1 = r0;
+    r0 = (r0 + (r3 << 16)) & 0xFFFFFFFFL;
+    if (r0 < r1)
+        carry++;
+    pft->dwLowDateTime = r0 + UNIX_TIME_ZERO_LO;
+    if (pft->dwLowDateTime < r0)
+        carry++;
+    pft->dwHighDateTime = r4 + (r2 >> 16) + (r3 >> 16)
+                            + UNIX_TIME_ZERO_HI + carry;
+#endif /* ?HAVE_INT64 */
+
+} /* end function utime2FileTime() */
+
+
+
+/******************************/
+/* Function FStampIsLocTime() */
+/******************************/
+
+static int FStampIsLocTime(__GPRO__ const char *path)
+{
+    return (NTQueryVolInfo(__G__ path) ? G.lastVolLocTim : FALSE);
+}
+
+#endif /* USE_EF_UT_TIME || NT_TZBUG_WORKAROUND || TIMESTAMP */
+
+
+
+#ifndef NT_TZBUG_WORKAROUND
+#  define UTIME_BOUNDCHECK_1(utimval) \
+     if (fs_uses_loctime) { \
+         utime_dosmin = dos_to_unix_time(DOSTIME_MINIMUM); \
+         if ((ulg)utimval < (ulg)utime_dosmin) \
+             utimval = utime_dosmin; \
+     }
+#  define UTIME_BOUNDCHECK_N(utimval) \
+     if (fs_uses_loctime && ((ulg)utimval < (ulg)utime_dosmin)) \
+         utimval = utime_dosmin;
+#  define NT_TZBUG_PRECOMPENSATE(ut, pft)
+
+#else /* NT_TZBUG_WORKAROUND */
+#  define UNIX_TIME_UMAX_HI  0x0236485EUL
+#  define UNIX_TIME_UMAX_LO  0xD4A5E980UL
+#  define UNIX_TIME_SMIN_HI  0x0151669EUL
+#  define UNIX_TIME_SMIN_LO  0xD53E8000UL
+#  define UNIX_TIME_SMAX_HI  0x01E9FD1EUL
+#  define UNIX_TIME_SMAX_LO  0xD4A5E980UL
+#  define UTIME_1980_JAN_01_00_00   315532800L
+#  define UTIME_BOUNDCHECK_1(utimval)
+#  define UTIME_BOUNDCHECK_N(utimval)
+#  define NT_TZBUG_PRECOMPENSATE(ut, pft) \
+     if (fs_uses_loctime) NTtzbugWorkaround(ut, pft);
+
+   /* nonzero if `y' is a leap year, else zero */
+#  define leap(y) (((y)%4 == 0 && (y)%100 != 0) || (y)%400 == 0)
+   /* number of leap years from 1970 to `y' (not including `y' itself) */
+#  define nleap(y) (((y)-1969)/4 - ((y)-1901)/100 + ((y)-1601)/400)
+
+extern ZCONST ush ydays[];              /* defined in fileio.c */
+
+/*****************************/
+/* Function FileTime2utime() */
+/*****************************/
+
+static int FileTime2utime(const FILETIME *pft, time_t *ut)
+{
+#ifdef HAVE_INT64
+    ULLNG64 NTtime;
+
+    NTtime = ((ULLNG64)pft->dwLowDateTime +
+              ((ULLNG64)pft->dwHighDateTime << 32));
+
+    /* underflow and overflow handling */
+#ifdef CHECK_UTIME_SIGNED_UNSIGNED
+    if ((time_t)0x80000000L < (time_t)0L)
+    {
+        if (NTtime < ((ULLNG64)UNIX_TIME_SMIN_LO +
+                      ((ULLNG64)UNIX_TIME_SMIN_HI << 32))) {
+            *ut = (time_t)LONG_MIN;
+            return FALSE;
+        }
+        if (NTtime > ((ULLNG64)UNIX_TIME_SMAX_LO +
+                      ((ULLNG64)UNIX_TIME_SMAX_HI << 32))) {
+            *ut = (time_t)LONG_MAX;
+            return FALSE;
+        }
+    }
+    else
+#endif /* CHECK_UTIME_SIGNED_UNSIGNED */
+    {
+        if (NTtime < ((ULLNG64)UNIX_TIME_ZERO_LO +
+                      ((ULLNG64)UNIX_TIME_ZERO_HI << 32))) {
+            *ut = (time_t)0;
+            return FALSE;
+        }
+        if (NTtime > ((ULLNG64)UNIX_TIME_UMAX_LO +
+                      ((ULLNG64)UNIX_TIME_UMAX_HI << 32))) {
+            *ut = (time_t)ULONG_MAX;
+            return FALSE;
+        }
+    }
+
+    NTtime -= ((ULLNG64)UNIX_TIME_ZERO_LO +
+               ((ULLNG64)UNIX_TIME_ZERO_HI << 32));
+    *ut = (time_t)(NTtime / (unsigned long)NT_QUANTA_PER_UNIX);
+    return TRUE;
+#else /* !HAVE_INT64 (64-bit integer arithmetics may not be supported) */
+    time_t days;
+    SYSTEMTIME w32tm;
+
+    /* underflow and overflow handling */
+#ifdef CHECK_UTIME_SIGNED_UNSIGNED
+    if ((time_t)0x80000000L < (time_t)0L)
+    {
+        if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) &&
+             (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) {
+            *ut = (time_t)LONG_MIN;
+            return FALSE;
+        if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) &&
+             (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) {
+            *ut = (time_t)LONG_MAX;
+            return FALSE;
+        }
+    }
+    else
+#endif /* CHECK_UTIME_SIGNED_UNSIGNED */
+    {
+        if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) &&
+             (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) {
+            *ut = (time_t)0;
+            return FALSE;
+        }
+        if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) &&
+             (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) {
+            *ut = (time_t)ULONG_MAX;
+            return FALSE;
+        }
+    }
+
+    FileTimeToSystemTime(pft, &w32tm);
+
+    /* set `days' to the number of days into the year */
+    days = w32tm.wDay - 1 + ydays[w32tm.wMonth-1] +
+           (w32tm.wMonth > 2 && leap (w32tm.wYear));
+
+    /* now set `days' to the number of days since 1 Jan 1970 */
+    days += 365 * (time_t)(w32tm.wYear - 1970) +
+            (time_t)(nleap(w32tm.wYear));
+
+    *ut = (time_t)(86400L * days + 3600L * (time_t)w32tm.wHour +
+                   (time_t)(60 * w32tm.wMinute + w32tm.wSecond));
+    return TRUE;
+#endif /* ?HAVE_INT64 */
+} /* end function FileTime2utime() */
+
+
+
+#ifdef W32_STAT_BANDAID
+/*********************************/
+/* Function VFatFileTime2utime() */
+/*********************************/
+
+static int VFatFileTime2utime(const FILETIME *pft, time_t *ut)
+{
+    FILETIME lft;
+#ifndef HAVE_MKTIME
+    WORD wDOSDate, wDOSTime;
+#else
+    SYSTEMTIME w32tm;
+    struct tm ltm;
+#endif
+
+    FileTimeToLocalFileTime(pft, &lft);
+    FTTrace((stdout, "VFatFT2utime, feed for mktime()", 1, &lft));
+#ifndef HAVE_MKTIME
+    /* This version of the FILETIME-to-UNIXTIME conversion function
+     * uses DOS-DATE-TIME format as intermediate stage. For modification
+     * and access times, this is no problem. But, the extra fine resolution
+     * of the VFAT-stored creation time gets lost.
+     */
+    FileTimeToDosDateTime(&lft, &wDOSDate, &wDOSTime);
+    TTrace((stdout,"DosDateTime is %04u-%02u-%02u %02u:%02u:%02u\n",
+      (unsigned)((wDOSDate>>9)&0x7f)+1980,(unsigned)((wDOSDate>>5)&0x0f),
+      (unsigned)(wDOSDate&0x1f),(unsigned)((wDOSTime>>11)&0x1f),
+      (unsigned)((wDOSTime>>5)&0x3f),(unsigned)((wDOSTime<<1)&0x3e)));
+    *ut = dos_to_unix_time(((ulg)wDOSDate << 16) | (ulg)wDOSTime);
+
+    /* a cheap error check: dos_to_unix_time() only returns an odd time
+     * when clipping at maximum time_t value. DOS_DATE_TIME values have
+     * a resolution of 2 seconds and are therefore even numbers.
+     */
+    return (((*ut)&1) == (time_t)0);
+#else /* HAVE_MKTIME */
+    FileTimeToSystemTime(&lft, &w32tm);
+    /* underflow and overflow handling */
+    /* TODO: The range checks are not accurate, the actual limits may
+     *       be off by one daylight-saving-time shift (typically 1 hour),
+     *       depending on the current state of "is_dst".
+     */
+#ifdef CHECK_UTIME_SIGNED_UNSIGNED
+    if ((time_t)0x80000000L < (time_t)0L)
+    {
+        if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) &&
+             (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) {
+            *ut = (time_t)LONG_MIN;
+            return FALSE;
+        if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) &&
+             (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) {
+            *ut = (time_t)LONG_MAX;
+            return FALSE;
+        }
+    }
+    else
+#endif /* CHECK_UTIME_SIGNED_UNSIGNED */
+    {
+        if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) &&
+             (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) {
+            *ut = (time_t)0;
+            return FALSE;
+        }
+        if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) ||
+            ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) &&
+             (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) {
+            *ut = (time_t)ULONG_MAX;
+            return FALSE;
+        }
+    }
+    ltm.tm_year = w32tm.wYear - 1900;
+    ltm.tm_mon = w32tm.wMonth - 1;
+    ltm.tm_mday = w32tm.wDay;
+    ltm.tm_hour = w32tm.wHour;
+    ltm.tm_min = w32tm.wMinute;
+    ltm.tm_sec = w32tm.wSecond;
+    ltm.tm_isdst = -1;  /* let mktime determine if DST is in effect */
+    *ut = mktime(&ltm);
+
+    /* a cheap error check: mktime returns "(time_t)-1L" on conversion errors.
+     * Normally, we would have to apply a consistency check because "-1"
+     * could also be a valid time. But, it is quite unlikely to read back odd
+     * time numbers from file systems that store time stamps in DOS format.
+     * (The only known exception is creation time on VFAT partitions.)
+     */
+    return (*ut != (time_t)-1L);
+#endif /* ?HAVE_MKTIME */
+
+} /* end function VFatFileTime2utime() */
+#endif /* W32_STAT_BANDAID */
+
+
+
+/********************************/
+/* Function UTCtime2Localtime() */      /* borrowed from Zip's mkgmtime() */
+/********************************/
+
+static time_t UTCtime2Localtime(time_t utctime)
+{
+    time_t utc = utctime;
+    struct tm *tm;
+    unsigned years, months, days, hours, minutes, seconds;
+
+
+#ifdef __BORLANDC__   /* Borland C++ 5.x crashes when trying to reference tm */
+    if (utc < UTIME_1980_JAN_01_00_00)
+        utc = UTIME_1980_JAN_01_00_00;
+#endif
+    tm = localtime(&utc);
+    if (tm == (struct tm *)NULL)
+        /* localtime() did not accept given utc time value; as an emergency
+           exit, the unconverted utctime value is returned */
+        return utctime;
+
+    years = tm->tm_year + 1900; /* year - 1900 -> year */
+    months = tm->tm_mon;        /* 0..11 */
+    days = tm->tm_mday - 1;     /* 1..31 -> 0..30 */
+    hours = tm->tm_hour;        /* 0..23 */
+    minutes = tm->tm_min;       /* 0..59 */
+    seconds = tm->tm_sec;       /* 0..61 in ANSI C */
+
+    /* set `days' to the number of days into the year */
+    days += ydays[months] + (months > 1 && leap(years));
+
+    /* now set `days' to the number of days since 1 Jan 1970 */
+    days += 365 * (years - 1970) + nleap(years);
+
+    return (time_t)(86400L * (ulg)days + 3600L * (ulg)hours +
+                    (ulg)(60 * minutes + seconds));
+
+} /* end function UTCtime2Localtime() */
+
+
+
+/********************************/
+/* Function NTtzbugWorkaround() */
+/********************************/
+
+static void NTtzbugWorkaround(time_t ut, FILETIME *pft)
+{
+    FILETIME C_RTL_locft, NTAPI_locft;
+    time_t ux_loctime = UTCtime2Localtime(ut);
+
+    /* This routine is only used when the target file system stores time-
+     * stamps as local time in MSDOS format.  Thus we make sure that the
+     * resulting timestamp is within the range of MSDOS date-time values. */
+    if (ux_loctime < UTIME_1980_JAN_01_00_00)
+        ux_loctime = UTIME_1980_JAN_01_00_00;
+
+    utime2FileTime(ux_loctime, &C_RTL_locft);
+    if (!FileTimeToLocalFileTime(pft, &NTAPI_locft))
+        return;
+    else {
+        long time_shift_l, time_shift_h;
+        int carry = 0;
+
+        time_shift_l = C_RTL_locft.dwLowDateTime - NTAPI_locft.dwLowDateTime;
+        if (C_RTL_locft.dwLowDateTime < NTAPI_locft.dwLowDateTime)
+            carry--;
+        time_shift_h = C_RTL_locft.dwHighDateTime - NTAPI_locft.dwHighDateTime;
+        pft->dwLowDateTime += time_shift_l;
+        if (pft->dwLowDateTime < (ulg)time_shift_l)
+            carry++;
+        pft->dwHighDateTime += time_shift_h + carry;
+        TTrace((stdout, "FileTime shift: %08lx:%08lx\n",
+                time_shift_h+carry,time_shift_l));
+    }
+} /* end function NTtzbugWorkaround() */
+
+#endif /* ?NT_TZBUG_WORKAROUND */
+
+
+
+/****************************/      /* Get the file time in a format that */
+/* Function getNTfiletime() */      /*  can be used by SetFileTime() in NT */
+/****************************/
+
+static int getNTfiletime(__G__ pModFT, pAccFT, pCreFT)
+    __GDEF
+    FILETIME *pModFT;
+    FILETIME *pAccFT;
+    FILETIME *pCreFT;
+{
+#ifdef NT_TZBUG_WORKAROUND
+    time_t ux_modtime;
+#else /* !NT_TZBUG_WORKAROUND */
+    FILETIME locft;    /* 64-bit value made up of two 32-bit [low & high] */
+    WORD wDOSDate;     /* for converting from DOS date to Windows NT */
+    WORD wDOSTime;
+#endif /* ?NT_TZBUG_WORKAROUND */
+#ifdef USE_EF_UT_TIME
+    unsigned eb_izux_flg;
+    iztimes z_utime;   /* struct for Unix-style actime & modtime, + creatime */
+#endif
+#if (defined(USE_EF_UT_TIME) && !defined(NT_TZBUG_WORKAROUND))
+    time_t utime_dosmin;
+# endif
+#if (defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND))
+    int fs_uses_loctime = FStampIsLocTime(__G__ G.filename);
+#endif
+
+    /* Copy and/or convert time and date variables, if necessary;
+     * return a flag indicating which time stamps are available. */
+#ifdef USE_EF_UT_TIME
+    if (G.extra_field &&
+#ifdef IZ_CHECK_TZ
+        G.tz_is_valid &&
+#endif
+        ((eb_izux_flg = ef_scan_for_izux(G.extra_field,
+          G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime,
+          &z_utime, NULL)) & EB_UT_FL_MTIME))
+    {
+        TTrace((stderr, "getNTfiletime:  Unix e.f. modif. time = %lu\n",
+          z_utime.mtime));
+        UTIME_BOUNDCHECK_1(z_utime.mtime)
+        utime2FileTime(z_utime.mtime, pModFT);
+        NT_TZBUG_PRECOMPENSATE(z_utime.mtime, pModFT)
+        if (eb_izux_flg & EB_UT_FL_ATIME) {
+            UTIME_BOUNDCHECK_N(z_utime.atime)
+            utime2FileTime(z_utime.atime, pAccFT);
+            NT_TZBUG_PRECOMPENSATE(z_utime.atime, pAccFT)
+        }
+        if (eb_izux_flg & EB_UT_FL_CTIME) {
+            UTIME_BOUNDCHECK_N(z_utime.ctime)
+            utime2FileTime(z_utime.ctime, pCreFT);
+            NT_TZBUG_PRECOMPENSATE(z_utime.ctime, pCreFT)
+        }
+        return (int)eb_izux_flg;
+    }
+#endif /* USE_EF_UT_TIME */
+#ifdef NT_TZBUG_WORKAROUND
+    ux_modtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
+    utime2FileTime(ux_modtime, pModFT);
+    NT_TZBUG_PRECOMPENSATE(ux_modtime, pModFT)
+#else /* !NT_TZBUG_WORKAROUND */
+
+    wDOSTime = (WORD)(G.lrec.last_mod_dos_datetime);
+    wDOSDate = (WORD)(G.lrec.last_mod_dos_datetime >> 16);
+
+    /* The DosDateTimeToFileTime() function converts a DOS date/time
+     * into a 64-bit Windows NT file time */
+    if (!DosDateTimeToFileTime(wDOSDate, wDOSTime, &locft))
+    {
+        Info(slide, 0, ((char *)slide, "DosDateTime failed: %d\n",
+          (int)GetLastError()));
+        return 0;
+    }
+    if (!LocalFileTimeToFileTime(&locft, pModFT))
+    {
+        Info(slide, 0, ((char *)slide, "LocalFileTime failed: %d\n",
+          (int)GetLastError()));
+        *pModFT = locft;
+    }
+#endif /* ?NT_TZBUG_WORKAROUND */
+    *pAccFT = *pModFT;
+    return (EB_UT_FL_MTIME | EB_UT_FL_ATIME);
+
+} /* end function getNTfiletime() */
+
+
+
+
+/****************************/
+/* Function close_outfile() */
+/****************************/
+
+void close_outfile(__G)
+    __GDEF
+{
+    FILETIME Modft;    /* File time type defined in NT, `last modified' time */
+    FILETIME Accft;    /* NT file time type, `last access' time */
+    FILETIME Creft;    /* NT file time type, `file creation' time */
+    HANDLE hFile;      /* File handle defined in NT    */
+    int gotTime;
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+    char *ansi_name = (char *)alloca(strlen(G.filename) + 1);
+
+    INTERN_TO_ISO(G.filename, ansi_name);
+#   define Ansi_Fname  ansi_name
+#else
+#   define Ansi_Fname  G.filename
+#endif
+
+    /* Close the file and then re-open it using the Win32
+     * CreateFile call, so that the file can be created
+     * with GENERIC_WRITE access, otherwise the SetFileTime
+     * call will fail. */
+    fclose(G.outfile);
+
+    /* don't set the time stamp and attributes on standard output */
+    if (uO.cflag)
+        return;
+
+    gotTime = getNTfiletime(__G__ &Modft, &Accft, &Creft);
+
+    /* open a handle to the file before processing extra fields;
+       we do this in case new security on file prevents us from updating
+       time stamps */
+    hFile = CreateFile(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
+         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+
+    /* sfield@microsoft.com: set attributes before time in case we decide to
+       support other filetime members later.  This also allows us to apply
+       attributes before the security is changed, which may prevent this
+       from succeeding otherwise.  Also, since most files don't have
+       any interesting attributes, only change them if something other than
+       FILE_ATTRIBUTE_ARCHIVE appears in the attributes.  This works well
+       as an optimization because FILE_ATTRIBUTE_ARCHIVE gets applied to the
+       file anyway, when it's created new. */
+    if((G.pInfo->file_attr & 0x7F) & ~FILE_ATTRIBUTE_ARCHIVE) {
+        if (!SetFileAttributes(Ansi_Fname, G.pInfo->file_attr & 0x7F))
+            Info(slide, 1, ((char *)slide,
+              "\nwarning (%d): could not set file attributes\n",
+              (int)GetLastError()));
+    }
+
+#ifdef NTSD_EAS
+    /* set extra fields, both stored-in-zipfile and .LONGNAME flavors */
+    if (G.extra_field) {    /* zipfile extra field may have extended attribs */
+        int err = EvalExtraFields(__G__ G.filename, G.extra_field,
+                                  G.lrec.extra_field_length);
+
+        if (err == IZ_EF_TRUNC) {
+            if (uO.qflag)
+                Info(slide, 1, ((char *)slide, "%-22s ",
+                  FnFilter1(G.filename)));
+            Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD),
+              makeword(G.extra_field+2)-10, uO.qflag? "\n":""));
+        }
+    }
+#endif /* NTSD_EAS */
+
+    if ( hFile == INVALID_HANDLE_VALUE )
+        Info(slide, 1, ((char *)slide,
+          "\nCreateFile error %d when trying set file time\n",
+          (int)GetLastError()));
+    else {
+        if (gotTime) {
+            FILETIME *pModft = (gotTime & EB_UT_FL_MTIME) ? &Modft : NULL;
+            FILETIME *pAccft = (gotTime & EB_UT_FL_ATIME) ? &Accft : NULL;
+            FILETIME *pCreft = (gotTime & EB_UT_FL_CTIME) ? &Creft : NULL;
+
+            if (!SetFileTime(hFile, pCreft, pAccft, pModft))
+                Info(slide, 0, ((char *)slide, "\nSetFileTime failed: %d\n",
+                  (int)GetLastError()));
+        }
+        CloseHandle(hFile);
+    }
+
+    return;
+
+#undef Ansi_Fname
+
+} /* end function close_outfile() */
+
+
+
+
+#ifdef TIMESTAMP
+
+/*************************/
+/* Function stamp_file() */
+/*************************/
+
+int stamp_file(__GPRO__ ZCONST char *fname, time_t modtime)
+{
+    FILETIME Modft;    /* File time type defined in NT, `last modified' time */
+    HANDLE hFile;      /* File handle defined in NT    */
+    int errstat = 0;   /* return status: 0 == "OK", -1 == "Failure" */
+#ifndef NT_TZBUG_WORKAROUND
+    time_t utime_dosmin;        /* internal variable for UTIME_BOUNDCHECK_1 */
+#endif
+    int fs_uses_loctime = FStampIsLocTime(__G__ fname);
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+    char *ansi_name = (char *)alloca(strlen(fname) + 1);
+
+    INTERN_TO_ISO(fname, ansi_name);
+#   define Ansi_Fname  ansi_name
+#else
+#   define Ansi_Fname  fname
+#endif
+
+    /* open a handle to the file to prepare setting the mod-time stamp */
+    hFile = CreateFile(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
+         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    if ( hFile == INVALID_HANDLE_VALUE ) {
+        errstat = -1;
+    } else {
+        /* convert time_t modtime into WIN32 native 64bit format */
+        UTIME_BOUNDCHECK_1(modtime)
+        utime2FileTime(modtime, &Modft);
+        NT_TZBUG_PRECOMPENSATE(modtime, &Modft)
+        /* set Access and Modification times of the file to modtime */
+        if (!SetFileTime(hFile, NULL, &Modft, &Modft)) {
+            errstat = -1;
+        }
+        CloseHandle(hFile);
+    }
+
+    return errstat;
+
+#undef Ansi_Fname
+} /* end function stamp_file() */
+
+#endif /* TIMESTAMP */
+
+
+
+
+/***********************/
+/* Function isfloppy() */   /* more precisely, is it removable? */
+/***********************/
+
+static int isfloppy(int nDrive)   /* 1 == A:, 2 == B:, etc. */
+{
+    char rootPathName[4];
+
+    rootPathName[0] = (char)('A' + nDrive - 1);   /* build the root path */
+    rootPathName[1] = ':';                        /*  name, e.g. "A:/" */
+    rootPathName[2] = '/';
+    rootPathName[3] = '\0';
+
+    return (GetDriveType(rootPathName) == DRIVE_REMOVABLE);
+
+} /* end function isfloppy() */
+
+
+
+
+/*****************************/
+/* Function NTQueryVolInfo() */
+/*****************************/
+
+/*
+ * Note:  8.3 limits on filenames apply only to old-style FAT filesystems.
+ *        More recent versions of Windows (Windows NT 3.5 / Windows 4.0)
+ *        can support long filenames (LFN) on FAT filesystems.  Check the
+ *        filesystem maximum component length field to detect LFN support.
+ */
+
+static int NTQueryVolInfo(__GPRO__ const char *name)
+{
+ /* static char lastRootPath[4] = ""; */
+ /* static int lastVolOldFAT; */
+ /* static int lastVolLocTim; */
+    char     *tmp0;
+    char      tmp1[MAX_PATH], tmp2[MAX_PATH];
+    unsigned  volSerNo, maxCompLen, fileSysFlags;
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+    char *ansi_name = (char *)alloca(strlen(name) + 1);
+
+    INTERN_TO_ISO(name, ansi_name);
+    name = ansi_name;
+#endif
+
+    if ((!strncmp(name, "//", 2) || !strncmp(name,"\\\\", 2)) &&
+        (name[2] != '\0' && name[2] != '/' && name[2] != '\\')) {
+        /* GetFullPathname() and GetVolumeInformation() do not work
+         * on UNC names. For now, we return "error".
+         * **FIXME**: check if UNC name is mapped to a drive letter
+         *            and use mapped drive for volume info query.
+         */
+        return FALSE;
+    }
+    if (isalpha((uch)name[0]) && (name[1] == ':'))
+        tmp0 = (char *)name;
+    else
+    {
+        if (!GetFullPathName(name, MAX_PATH, tmp1, &tmp0))
+            return FALSE;
+        tmp0 = &tmp1[0];
+    }
+    if (strncmp(G.lastRootPath, tmp0, 2) != 0) {
+        /* For speed, we skip repeated queries for the same device */
+        strncpy(G.lastRootPath, tmp0, 2);   /* Build the root path name, */
+        G.lastRootPath[2] = '/';            /* e.g. "A:/"                */
+        G.lastRootPath[3] = '\0';
+
+        if (!GetVolumeInformation((LPCTSTR)G.lastRootPath,
+              (LPTSTR)tmp1, (DWORD)MAX_PATH,
+              (LPDWORD)&volSerNo, (LPDWORD)&maxCompLen,
+              (LPDWORD)&fileSysFlags, (LPTSTR)tmp2, (DWORD)MAX_PATH)) {
+            G.lastRootPath[0] = '\0';
+            return FALSE;
+        }
+
+        /*  LFNs are available if the component length is > 12 */
+        G.lastVolOldFAT = (maxCompLen <= 12);
+/*      G.lastVolOldFAT = !strncmp(strupr(tmp2), "FAT", 3);   old version */
+
+        /* Volumes in (V)FAT and (OS/2) HPFS format store file timestamps in
+         * local time!
+         */
+        G.lastVolLocTim = !strncmp(strupr(tmp2), "VFAT", 4) ||
+                          !strncmp(tmp2, "HPFS", 4) ||
+                          !strncmp(tmp2, "FAT", 3);
+    }
+
+    return TRUE;
+
+} /* end function NTQueryVolInfo() */
+
+
+
+
+/*****************************/
+/* Function IsVolumeOldFAT() */
+/*****************************/
+
+static int IsVolumeOldFAT(__GPRO__ const char *name)
+{
+    return (NTQueryVolInfo(__G__ name) ? G.lastVolOldFAT : FALSE);
+}
+
+
+
+
+#ifndef SFX
+
+/************************/
+/*  Function do_wild()  */   /* identical to OS/2 version */
+/************************/
+
+char *do_wild(__G__ wildspec)
+    __GDEF
+    char *wildspec;         /* only used first time on a given dir */
+{
+ /* static zDIR *wild_dir = NULL;                               */
+ /* static char *dirname, *wildname, matchname[FILNAMSIZ]; */
+ /* static int firstcall=TRUE, have_dirname, dirnamelen;   */
+    char *fnamestart;
+    struct zdirent *file;
+
+    /* Even when we're just returning wildspec, we *always* do so in
+     * matchname[]--calling routine is allowed to append four characters
+     * to the returned string, and wildspec may be a pointer to argv[].
+     */
+    if (!G.notfirstcall) {  /* first call:  must initialize everything */
+        G.notfirstcall = TRUE;
+
+        if (!iswild(wildspec)) {
+            strcpy(G.matchname, wildspec);
+            G.have_dirname = FALSE;
+            G.wild_dir = NULL;
+            return G.matchname;
+        }
+
+        /* break the wildspec into a directory part and a wildcard filename */
+        if ((G.wildname = strrchr(wildspec, '/')) == NULL &&
+            (G.wildname = strrchr(wildspec, ':')) == NULL) {
+            G.dirname = ".";
+            G.dirnamelen = 1;
+            G.have_dirname = FALSE;
+            G.wildname = wildspec;
+        } else {
+            ++G.wildname;     /* point at character after '/' or ':' */
+            G.dirnamelen = G.wildname - wildspec;
+            if ((G.dirname = (char *)malloc(G.dirnamelen+1)) == NULL) {
+                Info(slide, 1, ((char *)slide,
+                  "warning:  cannot allocate wildcard buffers\n"));
+                strcpy(G.matchname, wildspec);
+                return G.matchname; /* but maybe filespec was not a wildcard */
+            }
+            strncpy(G.dirname, wildspec, G.dirnamelen);
+            G.dirname[G.dirnamelen] = '\0';    /* terminate for strcpy below */
+            G.have_dirname = TRUE;
+        }
+        Trace((stderr, "do_wild:  dirname = [%s]\n", G.dirname));
+
+        if ((G.wild_dir = (zvoid *)Opendir(G.dirname)) != NULL) {
+            if (G.have_dirname) {
+                strcpy(G.matchname, G.dirname);
+                fnamestart = G.matchname + G.dirnamelen;
+            } else
+                fnamestart = G.matchname;
+            while ((file = Readdir((zDIR *)G.wild_dir)) != NULL) {
+                Trace((stderr, "do_wild:  Readdir returns %s\n", file->d_name));
+                strcpy(fnamestart, file->d_name);
+                if (strrchr(fnamestart, '.') == (char *)NULL)
+                    strcat(fnamestart, ".");
+                if (match(fnamestart, G.wildname, 1) &&  /* 1 == ignore case */
+                    /* skip "." and ".." directory entries */
+                    strcmp(fnamestart, ".") && strcmp(fnamestart, "..")) {
+                    Trace((stderr, "do_wild:  match() succeeds\n"));
+                    /* remove trailing dot */
+                    fnamestart += strlen(fnamestart) - 1;
+                    if (*fnamestart == '.')
+                        *fnamestart = '\0';
+                    return G.matchname;
+                }
+            }
+            /* if we get to here directory is exhausted, so close it */
+            Closedir((zDIR *)G.wild_dir);
+            G.wild_dir = NULL;
+        }
+        Trace((stderr, "do_wild:  Opendir(%s) returns NULL\n", G.dirname));
+
+        /* return the raw wildspec in case that works (e.g., directory not
+         * searchable, but filespec was not wild and file is readable) */
+        strcpy(G.matchname, wildspec);
+        return G.matchname;
+    }
+
+    /* last time through, might have failed opendir but returned raw wildspec */
+    if (G.wild_dir == NULL) {
+        G.notfirstcall = FALSE;    /* reset for new wildspec */
+        if (G.have_dirname)
+            free(G.dirname);
+        return (char *)NULL;
+    }
+
+    /* If we've gotten this far, we've read and matched at least one entry
+     * successfully (in a previous call), so dirname has been copied into
+     * matchname already.
+     */
+    if (G.have_dirname) {
+        /* strcpy(G.matchname, G.dirname); */
+        fnamestart = G.matchname + G.dirnamelen;
+    } else
+        fnamestart = G.matchname;
+    while ((file = Readdir((zDIR *)G.wild_dir)) != NULL) {
+        Trace((stderr, "do_wild:  readdir returns %s\n", file->d_name));
+        strcpy(fnamestart, file->d_name);
+        if (strrchr(fnamestart, '.') == (char *)NULL)
+            strcat(fnamestart, ".");
+        if (match(fnamestart, G.wildname, 1)) {     /* 1 == ignore case */
+            Trace((stderr, "do_wild:  match() succeeds\n"));
+            /* remove trailing dot */
+            fnamestart += strlen(fnamestart) - 1;
+            if (*fnamestart == '.')
+                *fnamestart = '\0';
+            return G.matchname;
+        }
+    }
+
+    Closedir((zDIR *)G.wild_dir);  /* at least one entry read; nothing left */
+    G.wild_dir = NULL;
+    G.notfirstcall = FALSE;        /* reset for new wildspec */
+    if (G.have_dirname)
+        free(G.dirname);
+    return (char *)NULL;
+
+} /* end function do_wild() */
+
+#endif /* !SFX */
+
+
+
+/**********************/
+/* Function mapattr() */
+/**********************/
+
+/* Identical to MS-DOS, OS/2 versions.  However, NT has a lot of extra
+ * permission stuff, so this function should probably be extended in the
+ * future. */
+
+int mapattr(__G)
+    __GDEF
+{
+    /* set archive bit for file entries (file is not backed up): */
+    G.pInfo->file_attr = ((unsigned)G.crec.external_file_attributes |
+      (G.crec.external_file_attributes & FILE_ATTRIBUTE_DIRECTORY ?
+       0 : FILE_ATTRIBUTE_ARCHIVE)) & 0xff;
+    return 0;
+
+} /* end function mapattr() */
+
+
+
+
+/************************/
+/*  Function mapname()  */
+/************************/
+                             /* return 0 if no error, 1 if caution (filename */
+int mapname(__G__ renamed)   /*  truncated), 2 if warning (skip file because */
+    __GDEF                   /*  dir doesn't exist), 3 if error (skip file), */
+    int renamed;             /*  or 10 if out of memory (skip file) */
+{                            /*  [also IZ_VOL_LABEL, IZ_CREATED_DIR] */
+    char pathcomp[FILNAMSIZ];   /* path-component buffer */
+    char *pp, *cp=NULL;         /* character pointers */
+    char *lastsemi = NULL;      /* pointer to last semi-colon in pathcomp */
+    int error;
+    register unsigned workch;   /* hold the character being tested */
+
+
+/*---------------------------------------------------------------------------
+    Initialize various pointers and counters and stuff.
+  ---------------------------------------------------------------------------*/
+
+    /* can create path as long as not just freshening, or if user told us */
+    G.create_dirs = (!uO.fflag || renamed);
+
+    G.created_dir = FALSE;      /* not yet */
+    G.renamed_fullpath = FALSE;
+    G.fnlen = strlen(G.filename);
+
+    if (renamed) {
+        cp = G.filename - 1;    /* point to beginning of renamed name... */
+        while (*++cp)
+            if (*cp == '\\')    /* convert backslashes to forward */
+                *cp = '/';
+        cp = G.filename;
+        /* use temporary rootpath if user gave full pathname */
+        if (G.filename[0] == '/') {
+            G.renamed_fullpath = TRUE;
+            pathcomp[0] = '/';  /* copy the '/' and terminate */
+            pathcomp[1] = '\0';
+            ++cp;
+        } else if (isalpha((uch)G.filename[0]) && G.filename[1] == ':') {
+            G.renamed_fullpath = TRUE;
+            pp = pathcomp;
+            *pp++ = *cp++;      /* copy the "d:" (+ '/', possibly) */
+            *pp++ = *cp++;
+            if (*cp == '/')
+                *pp++ = *cp++;  /* otherwise add "./"? */
+            *pp = '\0';
+        }
+    }
+
+    /* pathcomp is ignored unless renamed_fullpath is TRUE: */
+    if ((error = checkdir(__G__ pathcomp, INIT)) != 0)    /* init path buffer */
+        return error;           /* ...unless no mem or vol label on hard disk */
+
+    *pathcomp = '\0';           /* initialize translation buffer */
+    pp = pathcomp;              /* point to translation buffer */
+    if (!renamed) {             /* cp already set if renamed */
+        if (uO.jflag)           /* junking directories */
+            cp = (char *)strrchr(G.filename, '/');
+        if (cp == NULL)         /* no '/' or not junking dirs */
+            cp = G.filename;    /* point to internal zipfile-member pathname */
+        else
+            ++cp;               /* point to start of last component of path */
+    }
+
+/*---------------------------------------------------------------------------
+    Begin main loop through characters in filename.
+  ---------------------------------------------------------------------------*/
+
+    while ((workch = (uch)*cp++) != 0) {
+
+        switch (workch) {
+        case '/':             /* can assume -j flag not given */
+            *pp = '\0';
+            if ((error = checkdir(__G__ pathcomp, APPEND_DIR)) > 1)
+                return error;
+            pp = pathcomp;    /* reset conversion buffer for next piece */
+            lastsemi = NULL;  /* leave directory semi-colons alone */
+            break;
+
+        case ':':             /* drive names not stored in zipfile, */
+        case '<':             /*  so no colons allowed */
+        case '>':             /* no redirection symbols allowed either */
+        case '|':             /* no pipe signs allowed */
+        case '"':             /* no double quotes allowed */
+        case '?':             /* no wildcards allowed */
+        case '*':
+            *pp++ = '_';      /* these rules apply equally to FAT and NTFS */
+            break;
+        case ';':             /* start of VMS version? */
+            lastsemi = pp;    /* remove VMS version later... */
+            *pp++ = ';';      /*  but keep semicolon for now */
+            break;
+
+        case ' ':             /* keep spaces unless specifically */
+            /* NT cannot create filenames with spaces on FAT volumes */
+            if (uO.sflag || IsVolumeOldFAT(__G__ G.filename))
+                *pp++ = '_';
+            else
+                *pp++ = ' ';
+            break;
+
+        default:
+            /* allow European characters in filenames: */
+            if (isprint(workch) || workch >= 127)
+                *pp++ = (char)workch;
+        } /* end switch */
+    } /* end while loop */
+
+    *pp = '\0';                   /* done with pathcomp:  terminate it */
+
+    /* if not saving them, remove VMS version numbers (appended "###") */
+    if (!uO.V_flag && lastsemi) {
+        pp = lastsemi + 1;        /* semi-colon was kept:  expect #'s after */
+        while (isdigit((uch)(*pp)))
+            ++pp;
+        if (*pp == '\0')          /* only digits between ';' and end:  nuke */
+            *lastsemi = '\0';
+    }
+
+/*---------------------------------------------------------------------------
+    Report if directory was created (and no file to create:  filename ended
+    in '/'), check name to be sure it exists, and combine path and name be-
+    fore exiting.
+  ---------------------------------------------------------------------------*/
+
+    if (G.filename[G.fnlen-1] == '/') {
+        checkdir(__G__ G.filename, GETPATH);
+        if (G.created_dir) {
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+            char *ansi_name = (char *)alloca(strlen(G.filename) + 1);
+
+            INTERN_TO_ISO(G.filename, ansi_name);
+#           define Ansi_Fname  ansi_name
+#else
+#           define Ansi_Fname  G.filename
+#endif
+            if (QCOND2) {
+                Info(slide, 0, ((char *)slide, "   creating: %-22s\n",
+                  FnFilter1(G.filename)));
+            }
+
+            /* set file attributes:
+               The default for newly created directories is "DIR attribute
+               flags set", so there is no need to change attributes unless
+               one of the DOS style attribute flags is set. The readonly
+               attribute need not be masked, since it does not prevent
+               modifications in the new directory. */
+            if(G.pInfo->file_attr & (0x7F & ~FILE_ATTRIBUTE_DIRECTORY)) {
+                if (!SetFileAttributes(Ansi_Fname, G.pInfo->file_attr & 0x7F))
+                    Info(slide, 1, ((char *)slide,
+                      "\nwarning (%d): could not set file attributes for %s\n",
+                      (int)GetLastError(), G.filename));
+            }
+
+#ifdef NTSD_EAS
+            /* set extra fields, both stored-in-zipfile and .LONGNAME flavors */
+            if (G.extra_field) { /* zipfile e.f. may have extended attribs */
+                int err = EvalExtraFields(__G__ G.filename, G.extra_field,
+                                          G.lrec.extra_field_length);
+
+                if (err == IZ_EF_TRUNC) {
+                    if (uO.qflag)
+                        Info(slide, 1, ((char *)slide, "%-22s ",
+                          FnFilter1(G.filename)));
+                    Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD),
+                      makeword(G.extra_field+2)-10, uO.qflag? "\n":""));
+                }
+            }
+#endif /* NTSD_EAS */
+            return IZ_CREATED_DIR;      /* set dir time (note trailing '/') */
+        }
+        return 2;   /* dir existed already; don't look for data to extract */
+    }
+
+    if (*pathcomp == '\0') {
+        Info(slide, 1, ((char *)slide, "mapname:  conversion of %s failed\n",
+          FnFilter1(G.filename)));
+        return 3;
+    }
+
+    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */
+    checkdir(__G__ G.filename, GETPATH);
+    Trace((stderr, "mapname returns with filename = [%s] (error = %d)\n\n",
+      FnFilter1(G.filename), error));
+
+    if (G.pInfo->vollabel) {    /* set the volume label now */
+        char drive[4];
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+        char *ansi_name = (char *)alloca(strlen(G.filename) + 1);
+        INTERN_TO_ISO(G.filename, ansi_name);
+#       define Ansi_Fname  ansi_name
+#else
+#       define Ansi_Fname  G.filename
+#endif
+
+        /* Build a drive string, e.g. "b:" */
+        drive[0] = (char)('a' + G.nLabelDrive - 1);
+        strcpy(drive + 1, ":\\");
+        if (QCOND2)
+            Info(slide, 0, ((char *)slide, "labelling %s %-22s\n", drive,
+              FnFilter1(G.filename)));
+        if (!SetVolumeLabel(drive, Ansi_Fname)) {
+            Info(slide, 1, ((char *)slide,
+              "mapname:  error setting volume label\n"));
+            return 3;
+        }
+        return 2;   /* success:  skip the "extraction" quietly */
+#undef Ansi_Fname
+    }
+
+    return error;
+
+} /* end function mapname() */
+
+
+
+
+/**********************/
+/* Function map2fat() */        /* Not quite identical to OS/2 version */
+/**********************/
+
+static void map2fat(pathcomp, pEndFAT)
+    char *pathcomp, **pEndFAT;
+{
+    char *ppc = pathcomp;       /* variable pointer to pathcomp */
+    char *pEnd = *pEndFAT;      /* variable pointer to buildpathFAT */
+    char *pBegin = *pEndFAT;    /* constant pointer to start of this comp. */
+    char *last_dot = NULL;      /* last dot not converted to underscore */
+    int dotname = FALSE;        /* flag:  path component begins with dot */
+                                /*  ("." and ".." don't count) */
+    register unsigned workch;   /* hold the character being tested */
+
+
+    /* Only need check those characters which are legal in NTFS but not
+     * in FAT:  to get here, must already have passed through mapname.
+     * Also must truncate path component to ensure 8.3 compliance.
+     */
+    while ((workch = (uch)*ppc++) != 0) {
+        switch (workch) {
+            case '[':
+            case ']':
+            case '+':
+            case ',':
+            case ';':
+            case '=':
+                *pEnd++ = '_';      /* convert brackets to underscores */
+                break;
+
+            case '.':
+                if (pEnd == *pEndFAT) {   /* nothing appended yet... */
+                    if (*ppc == '\0')     /* don't bother appending a */
+                        break;            /*  "./" component to the path */
+                    else if (*ppc == '.' && ppc[1] == '\0') {   /* "../" */
+                        *pEnd++ = '.';    /* add first dot, unchanged... */
+                        ++ppc;            /* skip second dot, since it will */
+                    } else {              /*  be "added" at end of if-block */
+                        *pEnd++ = '_';    /* FAT doesn't allow null filename */
+                        dotname = TRUE;   /*  bodies, so map .exrc -> _.exrc */
+                    }                     /*  (extra '_' now, "dot" below) */
+                } else if (dotname) {     /* found a second dot, but still */
+                    dotname = FALSE;      /*  have extra leading underscore: */
+                    *pEnd = '\0';         /*  remove it by shifting chars */
+                    pEnd = *pEndFAT + 1;  /*  left one space (e.g., .p1.p2: */
+                    while (pEnd[1]) {     /*  __p1 -> _p1_p2 -> _p1.p2 when */
+                        *pEnd = pEnd[1];  /*  finished) [opt.:  since first */
+                        ++pEnd;           /*  two chars are same, can start */
+                    }                     /*  shifting at second position] */
+                }
+                last_dot = pEnd;    /* point at last dot so far... */
+                *pEnd++ = '_';      /* convert dot to underscore for now */
+                break;
+
+            default:
+                *pEnd++ = (char)workch;
+
+        } /* end switch */
+    } /* end while loop */
+
+    *pEnd = '\0';                 /* terminate buildpathFAT */
+
+    /* NOTE:  keep in mind that pEnd points to the end of the path
+     * component, and *pEndFAT still points to the *beginning* of it...
+     * Also note that the algorithm does not try to get too fancy:
+     * if there are no dots already, the name either gets truncated
+     * at 8 characters or the last underscore is converted to a dot
+     * (only if more characters are saved that way).  In no case is
+     * a dot inserted between existing characters.
+     */
+    if (last_dot == NULL) {       /* no dots:  check for underscores... */
+        char *plu = strrchr(pBegin, '_');   /* pointer to last underscore */
+
+        if (plu == NULL) {   /* no dots, no underscores:  truncate at 8 chars */
+            *pEndFAT += 8;        /* (or could insert '.' and keep 11...?) */
+            if (*pEndFAT > pEnd)
+                *pEndFAT = pEnd;  /* oops...didn't have 8 chars to truncate */
+            else
+                **pEndFAT = '\0';
+        } else if (MIN(plu - pBegin, 8) + MIN(pEnd - plu - 1, 3) > 8) {
+            last_dot = plu;       /* be lazy:  drop through to next if-blk */
+        } else if ((pEnd - *pEndFAT) > 8) {
+            *pEndFAT += 8;        /* more fits into just basename than if */
+            **pEndFAT = '\0';     /*  convert last underscore to dot */
+        } else
+            *pEndFAT = pEnd;      /* whole thing fits into 8 chars or less */
+    }
+
+    if (last_dot != NULL) {       /* one dot (or two, in the case of */
+        *last_dot = '.';          /*  "..") is OK:  put it back in */
+
+        if ((last_dot - pBegin) > 8) {
+            char *p, *q;
+            int i;
+
+            p = last_dot;
+            q = last_dot = pBegin + 8;
+            for (i = 0;  (i < 4) && *p;  ++i)  /* too many chars in basename: */
+                *q++ = *p++;                   /*  shift .ext left and trun- */
+            *q = '\0';                         /*  cate/terminate it */
+            *pEndFAT = q;
+        } else if ((pEnd - last_dot) > 4) {    /* too many chars in extension */
+            *pEndFAT = last_dot + 4;
+            **pEndFAT = '\0';
+        } else
+            *pEndFAT = pEnd;   /* filename is fine; point at terminating zero */
+
+        if ((last_dot - pBegin) > 0 && last_dot[-1] == ' ')
+            last_dot[-1] = '_';                /* NO blank in front of '.'! */
+    }
+} /* end function map2fat() */
+
+
+
+
+/***********************/       /* Borrowed from os2.c for UnZip 5.1.        */
+/* Function checkdir() */       /* Difference: no EA stuff                   */
+/***********************/       /*             HPFS stuff works on NTFS too  */
+
+int checkdir(__G__ pathcomp, flag)
+    __GDEF
+    char *pathcomp;
+    int flag;
+/*
+ * returns:  1 - (on APPEND_NAME) truncated filename
+ *           2 - path doesn't exist, not allowed to create
+ *           3 - path doesn't exist, tried to create and failed; or
+ *               path exists and is not a directory, but is supposed to be
+ *           4 - path is too long
+ *          10 - can't allocate memory for filename buffers
+ */
+{
+ /* static int rootlen = 0;     */   /* length of rootpath */
+ /* static char *rootpath;      */   /* user's "extract-to" directory */
+ /* static char *buildpathHPFS; */   /* full path (so far) to extracted file, */
+ /* static char *buildpathFAT;  */   /*  both HPFS/EA (main) and FAT versions */
+ /* static char *endHPFS;       */   /* corresponding pointers to end of */
+ /* static char *endFAT;        */   /*  buildpath ('\0') */
+
+#   define FN_MASK   7
+#   define FUNCTION  (flag & FN_MASK)
+
+
+
+/*---------------------------------------------------------------------------
+    APPEND_DIR:  append the path component to the path being built and check
+    for its existence.  If doesn't exist and we are creating directories, do
+    so for this one; else signal success or error as appropriate.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == APPEND_DIR) {
+        char *p = pathcomp;
+        int too_long=FALSE;
+
+        Trace((stderr, "appending dir segment [%s]\n", pathcomp));
+        while ((*G.endHPFS = *p++) != '\0')     /* copy to HPFS filename */
+            ++G.endHPFS;
+        if (!IsVolumeOldFAT(__G__ G.buildpathHPFS)) {
+            p = pathcomp;
+            while ((*G.endFAT = *p++) != '\0')  /* copy to FAT filename, too */
+                ++G.endFAT;
+        } else
+            map2fat(pathcomp, &G.endFAT);   /* map into FAT fn, update endFAT */
+
+        /* GRR:  could do better check, see if overrunning buffer as we go:
+         * check endHPFS-buildpathHPFS after each append, set warning variable
+         * if within 20 of FILNAMSIZ; then if var set, do careful check when
+         * appending.  Clear variable when begin new path. */
+
+        /* next check:  need to append '/', at least one-char name, '\0' */
+        if ((G.endHPFS-G.buildpathHPFS) > FILNAMSIZ-3)
+            too_long = TRUE;                    /* check if extracting dir? */
+#ifdef FIX_STAT_BUG
+        /* Borland C++ 5.0 does not handle a call to stat() well if the
+         * directory does not exist (it tends to crash in strange places.)
+         * This is apparently a problem only when compiling for GUI rather
+         * than console. The code below attempts to work around this problem.
+         */
+        if (access(G.buildpathFAT, 0) != 0) {
+            if (!G.create_dirs) { /* told not to create (freshening) */
+                free(G.buildpathHPFS);
+                free(G.buildpathFAT);
+                return 2;         /* path doesn't exist:  nothing to do */
+            }
+            if (too_long) {   /* GRR:  should allow FAT extraction w/o EAs */
+                Info(slide, 1, ((char *)slide,
+                  "checkdir error:  path too long: %s\n",
+                  FnFilter1(G.buildpathHPFS)));
+                free(G.buildpathHPFS);
+                free(G.buildpathFAT);
+                return 4;         /* no room for filenames:  fatal */
+            }
+            if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */
+                Info(slide, 1, ((char *)slide,
+                  "checkdir error:  cannot create %s\n\
+                 unable to process %s.\n",
+                  FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));
+                free(G.buildpathHPFS);
+                free(G.buildpathFAT);
+                return 3;      /* path didn't exist, tried to create, failed */
+            }
+            G.created_dir = TRUE;
+        }
+#endif /* FIX_STAT_BUG */
+        if (SSTAT(G.buildpathFAT, &G.statbuf))   /* path doesn't exist */
+        {
+            if (!G.create_dirs) { /* told not to create (freshening) */
+                free(G.buildpathHPFS);
+                free(G.buildpathFAT);
+                return 2;         /* path doesn't exist:  nothing to do */
+            }
+            if (too_long) {   /* GRR:  should allow FAT extraction w/o EAs */
+                Info(slide, 1, ((char *)slide,
+                  "checkdir error:  path too long: %s\n",
+                  FnFilter1(G.buildpathHPFS)));
+                free(G.buildpathHPFS);
+                free(G.buildpathFAT);
+                return 4;         /* no room for filenames:  fatal */
+            }
+            if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */
+                Info(slide, 1, ((char *)slide,
+                  "checkdir error:  cannot create %s\n\
+                 unable to process %s.\n",
+                  FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));
+                free(G.buildpathHPFS);
+                free(G.buildpathFAT);
+                return 3;      /* path didn't exist, tried to create, failed */
+            }
+            G.created_dir = TRUE;
+        } else if (!S_ISDIR(G.statbuf.st_mode)) {
+            Info(slide, 1, ((char *)slide,
+              "checkdir error:  %s exists but is not directory\n   \
+              unable to process %s.\n",
+              FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));
+            free(G.buildpathHPFS);
+            free(G.buildpathFAT);
+            return 3;          /* path existed but wasn't dir */
+        }
+        if (too_long) {
+            Info(slide, 1, ((char *)slide,
+              "checkdir error:  path too long: %s\n",
+               FnFilter1(G.buildpathHPFS)));
+            free(G.buildpathHPFS);
+            free(G.buildpathFAT);
+            return 4;         /* no room for filenames:  fatal */
+        }
+        *G.endHPFS++ = '/';
+        *G.endFAT++ = '/';
+        *G.endHPFS = *G.endFAT = '\0';
+        Trace((stderr, "buildpathHPFS now = [%s]\nbuildpathFAT now =  [%s]\n",
+          FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT)));
+        return 0;
+
+    } /* end if (FUNCTION == APPEND_DIR) */
+
+/*---------------------------------------------------------------------------
+    GETPATH:  copy full FAT path to the string pointed at by pathcomp (want
+    filename to reflect name used on disk, not EAs; if full path is HPFS,
+    buildpathFAT and buildpathHPFS will be identical).  Also free both paths.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == GETPATH) {
+        Trace((stderr, "getting and freeing FAT path [%s]\n",
+          FnFilter1(G.buildpathFAT)));
+        Trace((stderr, "freeing HPFS path [%s]\n",
+          FnFilter1(G.buildpathHPFS)));
+        strcpy(pathcomp, G.buildpathFAT);
+        free(G.buildpathFAT);
+        free(G.buildpathHPFS);
+        G.buildpathHPFS = G.buildpathFAT = G.endHPFS = G.endFAT = NULL;
+        return 0;
+    }
+
+/*---------------------------------------------------------------------------
+    APPEND_NAME:  assume the path component is the filename; append it and
+    return without checking for existence.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == APPEND_NAME) {
+        char *p = pathcomp;
+        int error = 0;
+
+        Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp)));
+        while ((*G.endHPFS = *p++) != '\0') {   /* copy to HPFS filename */
+            ++G.endHPFS;
+            if ((G.endHPFS-G.buildpathHPFS) >= FILNAMSIZ) {
+                *--G.endHPFS = '\0';
+                Info(slide, 1, ((char *)slide,
+                  "checkdir warning:  path too long; truncating\n \
+                  %s\n                -> %s\n",
+                  FnFilter1(G.filename), FnFilter2(G.buildpathHPFS)));
+                error = 1;   /* filename truncated */
+            }
+        }
+
+        if ( G.pInfo->vollabel || !IsVolumeOldFAT(__G__ G.buildpathHPFS)) {
+            p = pathcomp;
+            while ((*G.endFAT = *p++) != '\0')  /* copy to FAT filename, too */
+                ++G.endFAT;
+        } else
+            map2fat(pathcomp, &G.endFAT);   /* map into FAT fn, update endFAT */
+        Trace((stderr, "buildpathHPFS: %s\nbuildpathFAT:  %s\n",
+          FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT)));
+
+        return error;  /* could check for existence, prompt for new name... */
+
+    } /* end if (FUNCTION == APPEND_NAME) */
+
+/*---------------------------------------------------------------------------
+    INIT:  allocate and initialize buffer space for the file currently being
+    extracted.  If file was renamed with an absolute path, don't prepend the
+    extract-to path.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == INIT) {
+        Trace((stderr, "initializing buildpathHPFS and buildpathFAT to "));
+        if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+1)) == NULL)
+            return 10;
+        if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+1)) == NULL) {
+            free(G.buildpathHPFS);
+            return 10;
+        }
+        if (G.pInfo->vollabel) { /* use root or renamed path, but don't store */
+/* GRR:  for network drives, do strchr() and return IZ_VOL_LABEL if not [1] */
+            if (G.renamed_fullpath && pathcomp[1] == ':')
+                *G.buildpathHPFS = (char)ToLower(*pathcomp);
+            else if (!G.renamed_fullpath && G.rootlen > 1 &&
+                     G.rootpath[1] == ':')
+                *G.buildpathHPFS = (char)ToLower(*G.rootpath);
+            else {
+                char tmpN[MAX_PATH], *tmpP;
+                if (GetFullPathName(".", MAX_PATH, tmpN, &tmpP) > MAX_PATH)
+                { /* by definition of MAX_PATH we should never get here */
+                    Info(slide, 1, ((char *)slide,
+                      "checkdir warning: current dir path too long\n"));
+                    return 1;   /* can't get drive letter */
+                }
+                G.nLabelDrive = *tmpN - 'a' + 1;
+                *G.buildpathHPFS = (char)(G.nLabelDrive - 1 + 'a');
+            }
+            G.nLabelDrive = *G.buildpathHPFS - 'a' + 1; /* save for mapname() */
+            if (uO.volflag == 0 || *G.buildpathHPFS < 'a' /* no labels/bogus? */
+                || (uO.volflag == 1 && !isfloppy(G.nLabelDrive))) { /* !fixed */
+                free(G.buildpathHPFS);
+                free(G.buildpathFAT);
+                return IZ_VOL_LABEL;   /* skipping with message */
+            }
+            *G.buildpathHPFS = '\0';
+        } else if (G.renamed_fullpath) /* pathcomp = valid data */
+            strcpy(G.buildpathHPFS, pathcomp);
+        else if (G.rootlen > 0)
+            strcpy(G.buildpathHPFS, G.rootpath);
+        else
+            *G.buildpathHPFS = '\0';
+        G.endHPFS = G.buildpathHPFS;
+        G.endFAT = G.buildpathFAT;
+        while ((*G.endFAT = *G.endHPFS) != '\0') {
+            ++G.endFAT;
+            ++G.endHPFS;
+        }
+        Trace((stderr, "[%s]\n", FnFilter1(G.buildpathHPFS)));
+        return 0;
+    }
+
+/*---------------------------------------------------------------------------
+    ROOT:  if appropriate, store the path in rootpath and create it if neces-
+    sary; else assume it's a zipfile member and return.  This path segment
+    gets used in extracting all members from every zipfile specified on the
+    command line.  Note that under OS/2 and MS-DOS, if a candidate extract-to
+    directory specification includes a drive letter (leading "x:"), it is
+    treated just as if it had a trailing '/'--that is, one directory level
+    will be created if the path doesn't exist, unless this is otherwise pro-
+    hibited (e.g., freshening).
+  ---------------------------------------------------------------------------*/
+
+#if (!defined(SFX) || defined(SFX_EXDIR))
+    if (FUNCTION == ROOT) {
+        Trace((stderr, "initializing root path to [%s]\n",
+          FnFilter1(pathcomp)));
+        if (pathcomp == NULL) {
+            G.rootlen = 0;
+            return 0;
+        }
+        if ((G.rootlen = strlen(pathcomp)) > 0) {
+            int had_trailing_pathsep=FALSE, has_drive=FALSE, xtra=2;
+
+            if (isalpha((uch)pathcomp[0]) && pathcomp[1] == ':')
+                has_drive = TRUE;   /* drive designator */
+            if (pathcomp[G.rootlen-1] == '/' || pathcomp[G.rootlen-1] == '\\') {
+                pathcomp[--G.rootlen] = '\0';
+                had_trailing_pathsep = TRUE;
+            }
+            if (has_drive && (G.rootlen == 2)) {
+                if (!had_trailing_pathsep)   /* i.e., original wasn't "x:/" */
+                    xtra = 3;      /* room for '.' + '/' + 0 at end of "x:" */
+            } else if (G.rootlen > 0) {   /* need not check "x:." and "x:/" */
+                if (SSTAT(pathcomp, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))
+                {
+                    /* path does not exist */
+                    if (!G.create_dirs /* || iswild(pathcomp) */ ) {
+                        G.rootlen = 0;
+                        return 2;   /* treat as stored file */
+                    }
+                    /* create directory (could add loop here to scan pathcomp
+                     * and create more than one level, but really necessary?) */
+                    if (MKDIR(pathcomp, 0777) == -1) {
+                        Info(slide, 1, ((char *)slide,
+                          "checkdir:  cannot create extraction directory: %s\n",
+                          FnFilter1(pathcomp)));
+                        G.rootlen = 0; /* path didn't exist, tried to create, */
+                        return 3;  /* failed:  file exists, or need 2+ levels */
+                    }
+                }
+            }
+            if ((G.rootpath = (char *)malloc(G.rootlen+xtra)) == NULL) {
+                G.rootlen = 0;
+                return 10;
+            }
+            strcpy(G.rootpath, pathcomp);
+            if (xtra == 3)                  /* had just "x:", make "x:." */
+                G.rootpath[G.rootlen++] = '.';
+            G.rootpath[G.rootlen++] = '/';
+            G.rootpath[G.rootlen] = '\0';
+            Trace((stderr, "rootpath now = [%s]\n", FnFilter1(G.rootpath)));
+        }
+        return 0;
+    }
+#endif /* !SFX || SFX_EXDIR */
+
+/*---------------------------------------------------------------------------
+    END:  free rootpath, immediately prior to program exit.
+  ---------------------------------------------------------------------------*/
+
+    if (FUNCTION == END) {
+        Trace((stderr, "freeing rootpath\n"));
+        if (G.rootlen > 0) {
+            free(G.rootpath);
+            G.rootlen = 0;
+        }
+        return 0;
+    }
+
+    return 99;  /* should never reach */
+
+} /* end function checkdir() */
+
+
+
+
+
+#ifndef SFX
+#ifndef WINDLL
+
+/************************/
+/*  Function version()  */
+/************************/
+
+void version(__G)
+    __GDEF
+{
+    int len;
+#if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DJGPP__))
+    char buf[80];
+#if (defined(_MSC_VER) && (_MSC_VER > 900))
+    char buf2[80];
+#endif
+#endif
+
+    len = sprintf((char *)slide, CompiledWith,
+
+#if defined(_MSC_VER)  /* MSC == VC++, but what about SDK compiler? */
+      (sprintf(buf, "Microsoft C %d.%02d ", _MSC_VER/100, _MSC_VER%100), buf),
+#  if (_MSC_VER == 800)
+      "(Visual C++ v1.1)",
+#  elif (_MSC_VER == 850)
+      "(Windows NT v3.5 SDK)",
+#  elif (_MSC_VER == 900)
+      "(Visual C++ v2.x)",
+#  elif (_MSC_VER > 900)
+      (sprintf(buf2, "(Visual C++ %d.%d)", _MSC_VER/100 - 6, _MSC_VER%100/10),
+        buf2),
+#  else
+      "(bad version)",
+#  endif
+#elif defined(__WATCOMC__)
+#  if (__WATCOMC__ % 10 > 0)
+      (sprintf(buf, "Watcom C/C++ %d.%02d", __WATCOMC__ / 100,
+       __WATCOMC__ % 100), buf), "",
+#  else
+      (sprintf(buf, "Watcom C/C++ %d.%d", __WATCOMC__ / 100,
+       (__WATCOMC__ % 100) / 10), buf), "",
+#  endif
+#elif defined(__BORLANDC__)
+      "Borland C++",
+#  if (__BORLANDC__ < 0x0200)
+      " 1.0",
+#  elif (__BORLANDC__ == 0x0200)
+      " 2.0",
+#  elif (__BORLANDC__ == 0x0400)
+      " 3.0",
+#  elif (__BORLANDC__ == 0x0410)   /* __BCPLUSPLUS__ = 0x0310 */
+      " 3.1",
+#  elif (__BORLANDC__ == 0x0452)   /* __BCPLUSPLUS__ = 0x0320 */
+      " 4.0 or 4.02",
+#  elif (__BORLANDC__ == 0x0460)   /* __BCPLUSPLUS__ = 0x0340 */
+      " 4.5",
+#  elif (__BORLANDC__ == 0x0500)   /* __BCPLUSPLUS__ = 0x0340 */
+      " 5.0",
+#  elif (__BORLANDC__ == 0x0520)   /* __BCPLUSPLUS__ = 0x0520 */
+      " 5.2 (C++ Builder)",        /* GRR:  assume this will stay sync'd? */
+#  else
+      " later than 5.2",
+#  endif
+#elif defined(__LCC__)
+      "LCC-Win32", "",
+#elif defined(__GNUC__)
+#  if defined(__RSXNT__)
+#    if (defined(__DJGPP__) && !defined(__EMX__))
+      (sprintf(buf, "rsxnt(djgpp v%d.%02d) / gcc ",
+        __DJGPP__, __DJGPP_MINOR__), buf),
+#    elif defined(__DJGPP__)
+      (sprintf(buf, "rsxnt(emx+djgpp v%d.%02d) / gcc ",
+        __DJGPP__, __DJGPP_MINOR__), buf),
+#    elif (defined(__GO32__) && !defined(__EMX__))
+      "rsxnt(djgpp v1.x) / gcc ",
+#    elif defined(__GO32__)
+      "rsxnt(emx + djgpp v1.x) / gcc ",
+#    elif defined(__EMX__)
+      "rsxnt(emx)+gcc ",
+#    else
+      "rsxnt(unknown) / gcc ",
+#    endif
+#  elif defined(__CYGWIN32__)
+      "cygnus win32 / gcc ",
+#  elif defined(__MINGW32__)
+      "mingw32 / gcc ",
+#  else
+      "gcc ",
+#  endif
+      __VERSION__,
+#else /* !_MSC_VER, !__WATCOMC__, !__BORLANDC__, !__LCC__, !__GNUC__ */
+      "unknown compiler (SDK?)", "",
+#endif /* ?compilers */
+
+      "Windows 95 / Windows NT", "\n(32-bit)",
+
+#ifdef __DATE__
+      " on ", __DATE__
+#else
+      "", ""
+#endif
+    );
+
+    (*G.message)((zvoid *)&G, slide, (ulg)len, 0);
+
+    return;
+
+} /* end function version() */
+
+#endif /* !WINDLL */
+#endif /* !SFX */
+
+
+
+#ifdef W32_STAT_BANDAID
+
+/* All currently known variants of WIN32 operating systems (Windows 95/98,
+ * WinNT 3.x, 4.0, 5.0) have a nasty bug in the OS kernel concerning
+ * conversions between UTC and local time: In the time conversion functions
+ * of the Win32 API, the timezone offset (including seasonal daylight saving
+ * shift) between UTC and local time evaluation is erratically based on the
+ * current system time. The correct evaluation must determine the offset
+ * value as it {was/is/will be} for the actual time to be converted.
+ *
+ * Some versions of MS C runtime lib's stat() returns utc time-stamps so
+ * that localtime(timestamp) corresponds to the (potentially false) local
+ * time shown by the OS' system programs (Explorer, command shell dir, etc.)
+ * The RSXNT port follows the same strategy, but fails to recognize the
+ * access-time attribute.
+ *
+ * For the NTFS file system (and other filesystems that store time-stamps
+ * as UTC values), this results in st_mtime (, st_{c|a}time) fields which
+ * are not stable but vary according to the seasonal change of "daylight
+ * saving time in effect / not in effect".
+ *
+ * Other C runtime libs (CygWin, or the CRT DLLs supplied with Win95/NT
+ * return the unix-time equivalent of the UTC FILETIME values as got back
+ * from the Win32 API call. This time, return values from NTFS are correct
+ * whereas utimes from files on (V)FAT volumes vary according to the DST
+ * switches.
+ *
+ * To achieve timestamp consistency of UTC (UT extra field) values in
+ * Zip archives, the Info-ZIP programs require work-around code for
+ * proper time handling in stat() (and other time handling routines).
+ */
+/* stat() functions under Windows95 tend to fail for root directories.   *
+ * Watcom and Borland, at least, are affected by this bug.  Watcom made  *
+ * a partial fix for 11.0 but still missed some cases.  This substitute  *
+ * detects the case and fills in reasonable values.  Otherwise we get    *
+ * effects like failure to extract to a root dir because it's not found. */
+
+int zstat_win32(__W32STAT_GLOBALS__ const char *path, struct stat *buf)
+{
+    if (!stat(path, buf))
+    {
+#ifdef NT_TZBUG_WORKAROUND
+        /* stat was successful, now redo the time-stamp fetches */
+        int fs_uses_loctime = FStampIsLocTime(__G__ path);
+        HANDLE h;
+        FILETIME Modft, Accft, Creft;
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+        char *ansi_path = (char *)alloca(strlen(path) + 1);
+
+        INTERN_TO_ISO(path, ansi_path);
+#       define Ansi_Path  ansi_path
+#else
+#       define Ansi_Path  path
+#endif
+
+        TTrace((stdout, "stat(%s) finds modtime %08lx\n", path, buf->st_mtime));
+        h = CreateFile(Ansi_Path, GENERIC_READ,
+                       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+                       OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+        if (h != INVALID_HANDLE_VALUE) {
+            BOOL ftOK = GetFileTime(h, &Creft, &Accft, &Modft);
+            CloseHandle(h);
+
+            if (ftOK) {
+                FTTrace((stdout, "GetFileTime returned Modft", 0, &Modft));
+                FTTrace((stdout, "GetFileTime returned Creft", 0, &Creft));
+                if (!fs_uses_loctime) {
+                    /*  On a filesystem that stores UTC timestamps, we refill
+                     *  the time fields of the struct stat buffer by directly
+                     *  using the UTC values as returned by the Win32
+                     *  GetFileTime() API call.
+                     */
+                    FileTime2utime(&Modft, &(buf->st_mtime));
+                    if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)
+                        FileTime2utime(&Accft, &(buf->st_atime));
+                    else
+                        buf->st_atime = buf->st_mtime;
+                    if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)
+                        FileTime2utime(&Creft, &(buf->st_ctime));
+                    else
+                        buf->st_ctime = buf->st_mtime;
+                    TTrace((stdout,"NTFS, recalculated modtime %08lx\n",
+                            buf->st_mtime));
+                } else {
+                    /*  On VFAT and FAT-like filesystems, the FILETIME values
+                     *  are converted back to the stable local time before
+                     *  converting them to UTC unix time-stamps.
+                     */
+                    VFatFileTime2utime(&Modft, &(buf->st_mtime));
+                    if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)
+                        VFatFileTime2utime(&Accft, &(buf->st_atime));
+                    else
+                        buf->st_atime = buf->st_mtime;
+                    if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)
+                        VFatFileTime2utime(&Creft, &(buf->st_ctime));
+                    else
+                        buf->st_ctime = buf->st_mtime;
+                    TTrace((stdout, "VFAT, recalculated modtime %08lx\n",
+                            buf->st_mtime));
+                }
+            }
+        }
+#       undef Ansi_Path
+#endif /* NT_TZBUG_WORKAROUND */
+        return 0;
+    }
+#ifdef W32_STATROOT_FIX
+    else
+    {
+        DWORD flags;
+#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */
+        char *ansi_path = (char *)alloca(strlen(path) + 1);
+
+        INTERN_TO_ISO(path, ansi_path);
+#       define Ansi_Path  ansi_path
+#else
+#       define Ansi_Path  path
+#endif
+
+        flags = GetFileAttributes(Ansi_Path);
+        if (flags != 0xFFFFFFFF && flags & FILE_ATTRIBUTE_DIRECTORY) {
+            Trace((stderr, "\nstat(\"%s\",...) failed on existing directory\n",
+                   path));
+            memset(buf, 0, sizeof(struct stat));
+            buf->st_atime = buf->st_ctime = buf->st_mtime =
+              dos_to_unix_time(DOSTIME_MINIMUM);        /* 1-1-80 */
+            buf->st_mode = S_IFDIR | S_IREAD |
+                           ((flags & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE);
+            return 0;
+        } /* assumes: stat() won't fail on non-dirs without good reason */
+#       undef Ansi_Path
+    }
+#endif /* W32_STATROOT_FIX */
+    return -1;
+}
+
+#endif /* W32_STAT_BANDAID */
+
+#endif /* !FUNZIP */
+
+
+
+#ifndef WINDLL
+/* This replacement getch() function was originally created for Watcom C
+ * and then additionally used with CYGWIN. Since UnZip 5.4, all other Win32
+ * ports apply this replacement rather that their supplied getch() (or
+ * alike) function.  There are problems with unabsorbed LF characters left
+ * over in the keyboard buffer under Win95 (and 98) when ENTER was pressed.
+ * (Under Win95, ENTER returns two(!!) characters: CR-LF.)  This problem
+ * does not appear when run on a WinNT console prompt!
+ */
+
+/* Watcom 10.6's getch() does not handle Alt+<digit><digit><digit>. */
+/* Note that if PASSWD_FROM_STDIN is defined, the file containing   */
+/* the password must have a carriage return after the word, not a   */
+/* Unix-style newline (linefeed only).  This discards linefeeds.    */
+
+int getch_win32(void)
+{
+  HANDLE stin;
+  DWORD rc;
+  unsigned char buf[2];
+  int ret = -1;
+  DWORD odemode = ~(DWORD)0;
+
+#  ifdef PASSWD_FROM_STDIN
+  stin = GetStdHandle(STD_INPUT_HANDLE);
+#  else
+  stin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
+                    FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+  if (stin == INVALID_HANDLE_VALUE)
+    return -1;
+#  endif
+  if (GetConsoleMode(stin, &odemode))
+    SetConsoleMode(stin, ENABLE_PROCESSED_INPUT);  /* raw except ^C noticed */
+  if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1)
+    ret = buf[0];
+  /* when the user hits return we get CR LF.  We discard the LF, not the CR,
+   * because when we call this for the first time after a previous input
+   * such as the one for "replace foo? [y]es, ..." the LF may still be in
+   * the input stream before whatever the user types at our prompt. */
+  if (ret == '\n')
+    if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1)
+      ret = buf[0];
+  if (odemode != ~(DWORD)0)
+    SetConsoleMode(stin, odemode);
+#  ifndef PASSWD_FROM_STDIN
+  CloseHandle(stin);
+#  endif
+  return ret;
+}
+#endif /* !WINDLL */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sfxzip/zipinfo.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,1912 @@
+/*---------------------------------------------------------------------------
+
+  zipinfo.c                                              Greg Roelofs et al.
+
+  This file contains all of the ZipInfo-specific listing routines for UnZip.
+
+  Contains:  zi_opts()
+             zi_end_central()
+             zipinfo()
+             zi_long()
+             zi_short()
+             zi_time()
+
+  ---------------------------------------------------------------------------*/
+
+
+#define UNZIP_INTERNAL
+#include "unzip.h"
+
+
+#ifndef NO_ZIPINFO  /* strings use up too much space in small-memory systems */
+
+/* Define OS-specific attributes for use on ALL platforms--the S_xxxx
+ * versions of these are defined differently (or not defined) by different
+ * compilers and operating systems. */
+
+#define UNX_IFMT       0170000     /* Unix file type mask */
+#define UNX_IFDIR      0040000     /* Unix directory */
+#define UNX_IFREG      0100000     /* Unix regular file */
+#define UNX_IFSOCK     0140000     /* Unix socket (BSD, not SysV or Amiga) */
+#define UNX_IFLNK      0120000     /* Unix symbolic link (not SysV, Amiga) */
+#define UNX_IFBLK      0060000     /* Unix block special       (not Amiga) */
+#define UNX_IFCHR      0020000     /* Unix character special   (not Amiga) */
+#define UNX_IFIFO      0010000     /* Unix fifo    (BCC, not MSC or Amiga) */
+#define UNX_ISUID      04000       /* Unix set user id on execution */
+#define UNX_ISGID      02000       /* Unix set group id on execution */
+#define UNX_ISVTX      01000       /* Unix directory permissions control */
+#define UNX_ENFMT      UNX_ISGID   /* Unix record locking enforcement flag */
+#define UNX_IRWXU      00700       /* Unix read, write, execute: owner */
+#define UNX_IRUSR      00400       /* Unix read permission: owner */
+#define UNX_IWUSR      00200       /* Unix write permission: owner */
+#define UNX_IXUSR      00100       /* Unix execute permission: owner */
+#define UNX_IRWXG      00070       /* Unix read, write, execute: group */
+#define UNX_IRGRP      00040       /* Unix read permission: group */
+#define UNX_IWGRP      00020       /* Unix write permission: group */
+#define UNX_IXGRP      00010       /* Unix execute permission: group */
+#define UNX_IRWXO      00007       /* Unix read, write, execute: other */
+#define UNX_IROTH      00004       /* Unix read permission: other */
+#define UNX_IWOTH      00002       /* Unix write permission: other */
+#define UNX_IXOTH      00001       /* Unix execute permission: other */
+
+#define VMS_IRUSR      UNX_IRUSR   /* VMS read/owner */
+#define VMS_IWUSR      UNX_IWUSR   /* VMS write/owner */
+#define VMS_IXUSR      UNX_IXUSR   /* VMS execute/owner */
+#define VMS_IRGRP      UNX_IRGRP   /* VMS read/group */
+#define VMS_IWGRP      UNX_IWGRP   /* VMS write/group */
+#define VMS_IXGRP      UNX_IXGRP   /* VMS execute/group */
+#define VMS_IROTH      UNX_IROTH   /* VMS read/other */
+#define VMS_IWOTH      UNX_IWOTH   /* VMS write/other */
+#define VMS_IXOTH      UNX_IXOTH   /* VMS execute/other */
+
+#define AMI_IFMT       06000       /* Amiga file type mask */
+#define AMI_IFDIR      04000       /* Amiga directory */
+#define AMI_IFREG      02000       /* Amiga regular file */
+#define AMI_IHIDDEN    00200       /* to be supported in AmigaDOS 3.x */
+#define AMI_ISCRIPT    00100       /* executable script (text command file) */
+#define AMI_IPURE      00040       /* allow loading into resident memory */
+#define AMI_IARCHIVE   00020       /* not modified since bit was last set */
+#define AMI_IREAD      00010       /* can be opened for reading */
+#define AMI_IWRITE     00004       /* can be opened for writing */
+#define AMI_IEXECUTE   00002       /* executable image, a loadable runfile */
+#define AMI_IDELETE    00001       /* can be deleted */
+
+#define LFLAG  3   /* short "ls -l" type listing */
+
+static int   zi_long   OF((__GPRO__ ulg *pEndprev));
+static int   zi_short  OF((__GPRO));
+static void  zi_showMacTypeCreator
+                       OF((__GPRO__ uch *ebfield));
+static char *zi_time   OF((__GPRO__ ZCONST ulg *datetimez,
+                           ZCONST time_t *modtimez, char *d_t_str));
+
+
+/**********************************************/
+/*  Strings used in zipinfo.c (ZipInfo half)  */
+/**********************************************/
+
+static char nullStr[] = "";
+
+static ZCONST char Far LongHeader[] = "Archive:  %s   %ld bytes   %d file%s\n";
+static ZCONST char Far ShortHeader[] = "Archive:  %s   %ld   %d\n";
+static ZCONST char Far EndCentDirRec[] = "\nEnd-of-central-directory record:\n";
+static ZCONST char Far LineSeparators[] = "-------------------------------\n\n";
+static ZCONST char Far ActOffsetCentDir[] = "\
+  Actual offset of end-of-central-dir record:   %9ld (%.8lXh)\n\
+  Expected offset of end-of-central-dir record: %9ld (%.8lXh)\n\
+  (based on the length of the central directory and its expected offset)\n\n";
+static ZCONST char Far SinglePartArchive1[] = "\
+  This zipfile constitutes the sole disk of a single-part archive; its\n\
+  central directory contains %u %s.  The central directory is %lu\n\
+  (%.8lXh) bytes long, and its (expected) offset in bytes from the\n";
+static ZCONST char Far SinglePartArchive2[] = "\
+  beginning of the zipfile is %lu (%.8lXh).\n\n";
+static ZCONST char Far MultiPartArchive1[] = "\
+  This zipfile constitutes disk %u of a multi-part archive.  The central\n\
+  directory starts on disk %u; %u of its entries %s contained within\n";
+static ZCONST char Far MultiPartArchive2[] = "\
+  this zipfile, out of a total of %u %s.  The entire central\n\
+  directory is %lu (%.8lXh) bytes long, and its offset in bytes from\n";
+static ZCONST char Far MultiPartArchive3[] = "\
+  the beginning of the zipfile in which it begins is %lu (%.8lXh).\n\n";
+static ZCONST char Far NoZipfileComment[] = "  There is no zipfile comment.\n";
+static ZCONST char Far ZipfileCommentDesc[] =
+  "  The zipfile comment is %u bytes long and contains the following text:\n\n";
+static ZCONST char Far ZipfileCommBegin[] =
+ "======================== zipfile comment begins ==========================\n";
+static ZCONST char Far ZipfileCommEnd[] =
+ "========================= zipfile comment ends ===========================\n";
+static ZCONST char Far ZipfileCommTrunc2[] = "\n  The zipfile comment is truncated.\n";
+static ZCONST char Far ZipfileCommTruncMsg[] =
+  "\ncaution:  zipfile comment truncated\n";
+
+static ZCONST char Far CentralDirEntry[] =
+  "\nCentral directory entry #%d:\n---------------------------\n\n";
+static ZCONST char Far ZipfileStats[] =
+  "%d file%s, %lu bytes uncompressed, %lu bytes compressed:  %s%d.%d%%\n";
+
+/* zi_long() strings */
+static ZCONST char Far OS_FAT[] = "MS-DOS, OS/2 or NT FAT";
+static ZCONST char Far OS_Amiga[] = "Amiga";
+static ZCONST char Far OS_VMS[] = "VMS";
+static ZCONST char Far OS_Unix[] = "Unix";
+static ZCONST char Far OS_VMCMS[] = "VM/CMS";
+static ZCONST char Far OS_AtariST[] = "Atari ST";
+static ZCONST char Far OS_HPFS[] = "OS/2 or NT HPFS";
+static ZCONST char Far OS_Macintosh[] = "Macintosh HFS";
+static ZCONST char Far OS_ZSystem[] = "Z-System";
+static ZCONST char Far OS_CPM[] = "CP/M";
+static ZCONST char Far OS_TOPS20[] = "TOPS-20";
+static ZCONST char Far OS_NTFS[] = "NTFS";
+static ZCONST char Far OS_QDOS[] = "SMS/QDOS";
+static ZCONST char Far OS_Acorn[] = "Acorn RISC OS";
+static ZCONST char Far OS_MVS[] = "MVS";
+static ZCONST char Far OS_VFAT[] = "Win32 VFAT";
+static ZCONST char Far OS_BeOS[] = "BeOS";
+static ZCONST char Far OS_Tandem[] = "Tandem NSK";
+
+static ZCONST char Far MthdNone[] = "none (stored)";
+static ZCONST char Far MthdShrunk[] = "shrunk";
+static ZCONST char Far MthdRedF1[] = "reduced (factor 1)";
+static ZCONST char Far MthdRedF2[] = "reduced (factor 2)";
+static ZCONST char Far MthdRedF3[] = "reduced (factor 3)";
+static ZCONST char Far MthdRedF4[] = "reduced (factor 4)";
+static ZCONST char Far MthdImplode[] = "imploded";
+static ZCONST char Far MthdToken[] = "tokenized";
+static ZCONST char Far MthdDeflate[] = "deflated";
+static ZCONST char Far MthdEnDeflate[] = "deflated (enhanced)";
+static ZCONST char Far MthdDCLImplode[] = "imploded (PK DCL)";
+
+static ZCONST char Far DeflNorm[] = "normal";
+static ZCONST char Far DeflMax[] = "maximum";
+static ZCONST char Far DeflFast[] = "fast";
+static ZCONST char Far DeflSFast[] = "superfast";
+
+static ZCONST char Far ExtraBytesPreceding[] =
+  "  There are an extra %ld bytes preceding this file.\n\n";
+
+static ZCONST char Far UnknownNo[] = "unknown (%d)";
+
+static ZCONST char Far LocalHeaderOffset[] =
+  "\n  offset of local header from start of archive:     %lu (%.8lXh) bytes\n";
+static ZCONST char Far HostOS[] =
+  "  file system or operating system of origin:        %s\n";
+static ZCONST char Far EncodeSWVer[] =
+  "  version of encoding software:                     %d.%d\n";
+static ZCONST char Far MinOSCompReq[] =
+  "  minimum file system compatibility required:       %s\n";
+static ZCONST char Far MinSWVerReq[] =
+  "  minimum software version required to extract:     %d.%d\n";
+static ZCONST char Far CompressMethod[] =
+  "  compression method:                               %s\n";
+static ZCONST char Far SlideWindowSizeImplode[] =
+  "  size of sliding dictionary (implosion):           %cK\n";
+static ZCONST char Far ShannonFanoTrees[] =
+  "  number of Shannon-Fano trees (implosion):         %c\n";
+static ZCONST char Far CompressSubtype[] =
+  "  compression sub-type (deflation):                 %s\n";
+static ZCONST char Far FileSecurity[] =
+  "  file security status:                             %sencrypted\n";
+static ZCONST char Far ExtendedLocalHdr[] =
+  "  extended local header:                            %s\n";
+static ZCONST char Far FileModDate[] =
+  "  file last modified on (DOS date/time):            %s\n";
+#ifdef USE_EF_UT_TIME
+  static ZCONST char Far UT_FileModDate[] =
+    "  file last modified on (UT extra field modtime):   %s %s\n";
+  static ZCONST char Far LocalTime[] = "local";
+#ifndef NO_GMTIME
+  static ZCONST char Far GMTime[] = "UTC";
+#endif
+#endif /* USE_EF_UT_TIME */
+static ZCONST char Far CRC32Value[] =
+  "  32-bit CRC value (hex):                           %.8lx\n";
+static ZCONST char Far CompressedFileSize[] =
+  "  compressed size:                                  %lu bytes\n";
+static ZCONST char Far UncompressedFileSize[] =
+  "  uncompressed size:                                %lu bytes\n";
+static ZCONST char Far FilenameLength[] =
+  "  length of filename:                               %u characters\n";
+static ZCONST char Far ExtraFieldLength[] =
+  "  length of extra field:                            %u bytes\n";
+static ZCONST char Far FileCommentLength[] =
+  "  length of file comment:                           %u characters\n";
+static ZCONST char Far FileDiskNum[] =
+  "  disk number on which file begins:                 disk %u\n";
+static ZCONST char Far ApparentFileType[] =
+  "  apparent file type:                               %s\n";
+static ZCONST char Far VMSFileAttributes[] =
+  "  VMS file attributes (%06o octal):               %s\n";
+static ZCONST char Far AmigaFileAttributes[] =
+  "  Amiga file attributes (%06o octal):             %s\n";
+static ZCONST char Far UnixFileAttributes[] =
+  "  Unix file attributes (%06o octal):              %s\n";
+static ZCONST char Far NonMSDOSFileAttributes[] =
+  "  non-MSDOS external file attributes:               %06lX hex\n";
+static ZCONST char Far MSDOSFileAttributes[] =
+  "  MS-DOS file attributes (%02X hex):                  none\n";
+static ZCONST char Far MSDOSFileAttributesRO[] =
+  "  MS-DOS file attributes (%02X hex):                  read-only\n";
+static ZCONST char Far MSDOSFileAttributesAlpha[] =
+  "  MS-DOS file attributes (%02X hex):                  %s%s%s%s%s%s\n";
+
+
+static ZCONST char Far ExtraFieldTrunc[] = "\n\
+  error: EF data block (type 0x%04x) size %u exceeds remaining extra field\n\
+         space %u; block length has been truncated.\n";
+static ZCONST char Far ExtraFields[] = "\n\
+  The central-directory extra field contains:";
+static ZCONST char Far ExtraFieldType[] = "\n\
+  - A subfield with ID 0x%04x (%s) and %u data bytes";
+static ZCONST char Far efAV[] = "PKWARE AV";
+static ZCONST char Far efOS2[] = "OS/2";
+static ZCONST char Far efPKVMS[] = "PKWARE VMS";
+static ZCONST char Far efPKWin32[] = "PKWARE Win32";
+static ZCONST char Far efPKUnix[] = "PKWARE Unix";
+static ZCONST char Far efIZVMS[] = "Info-ZIP VMS";
+static ZCONST char Far efIZUnix[] = "old Info-ZIP Unix/OS2/NT";
+static ZCONST char Far efIZUnix2[] = "Unix UID/GID";
+static ZCONST char Far efTime[] = "universal time";
+static ZCONST char Far efJLMac[] = "old Info-ZIP Macintosh";
+static ZCONST char Far efMac3[] = "new Info-ZIP Macintosh";
+static ZCONST char Far efZipIt[] = "ZipIt Macintosh";
+static ZCONST char Far efZipIt2[] = "ZipIt Macintosh (short)";
+static ZCONST char Far efVMCMS[] = "VM/CMS";
+static ZCONST char Far efMVS[] = "MVS";
+static ZCONST char Far efACL[] = "OS/2 ACL";
+static ZCONST char Far efNTSD[] = "Security Descriptor";
+static ZCONST char Far efBeOS[] = "BeOS";
+static ZCONST char Far efQDOS[] = "SMS/QDOS";
+static ZCONST char Far efAOSVS[] = "AOS/VS";
+static ZCONST char Far efSpark[] = "Acorn SparkFS";
+static ZCONST char Far efMD5[] = "Fred Kantor MD5";
+static ZCONST char Far efASiUnix[] = "ASi Unix";
+static ZCONST char Far efUnknown[] = "unknown";
+
+static ZCONST char Far OS2EAs[] = ".\n\
+    The local extra field has %lu bytes of OS/2 extended attributes.\n\
+    (May not match OS/2 \"dir\" amount due to storage method)";
+static ZCONST char Far izVMSdata[] = ".  The extra\n\
+    field is %s and has %lu bytes of VMS %s information%s";
+static ZCONST char Far izVMSstored[] = "stored";
+static ZCONST char Far izVMSrleenc[] = "run-length encoded";
+static ZCONST char Far izVMSdeflat[] = "deflated";
+static ZCONST char Far izVMScunknw[] = "compressed(?)";
+static ZCONST char Far *izVMScomp[4] =
+  {izVMSstored, izVMSrleenc, izVMSdeflat, izVMScunknw};
+static ZCONST char Far ACLdata[] = ".\n\
+    The local extra field has %lu bytes of access control list information";
+static ZCONST char Far NTSDData[] = ".\n\
+    The local extra field has %lu bytes of NT security descriptor data";
+static ZCONST char Far UTdata[] = ".\n\
+    The local extra field has UTC/GMT %s time%s";
+static ZCONST char Far UTmodification[] = "modification";
+static ZCONST char Far UTaccess[] = "access";
+static ZCONST char Far UTcreation[] = "creation";
+static ZCONST char Far ZipItFname[] = ".\n\
+    The Mac long filename is %s.\n";
+static ZCONST char Far Mac3data[] = ".\n\
+    The local extra field has %lu bytes of %scompressed Macintosh\n\
+    finder attributes";
+ /* MacOSdata[] is used by EF_MAC3, EF_ZIPIT, EF_ZIPIT2 and EF_JLEE e. f. */
+static ZCONST char Far MacOSdata[] = ".\n\
+    The associated file has type code `%c%c%c%c' and creator code `%c%c%c%c'";
+static ZCONST char Far MacOSdata1[] = ".\n\
+    The associated file has type code `0x%lx' and creator code `0x%lx'";
+static ZCONST char Far MacOSJLEEflags[] = "\n    File is marked as %s";
+static ZCONST char Far MacOS_RF[] = "Resource-fork";
+static ZCONST char Far MacOS_DF[] = "Data-fork";
+static ZCONST char Far MacOSMAC3flags[] = ".\n\
+    File is marked as %s, File Dates are in %d Bit";
+static ZCONST char Far BeOSdata[] = ".\n\
+    The local extra field has %lu bytes of %scompressed BeOS file attributes";
+ /* The associated file has type code `%c%c%c%c' and creator code `%c%c%c%c'" */
+static ZCONST char Far QDOSdata[] = ".\n\
+    The QDOS extra field subtype is `%c%c%c%c'";
+static ZCONST char Far AOSVSdata[] = ".\n\
+    The AOS/VS extra field revision is %d.%d";
+static ZCONST char Far MD5data[] = ".\n\
+    The 128-bit MD5 signature is %s";
+#ifdef CMS_MVS
+   static ZCONST char Far VmMvsExtraField[] = ".\n\
+    The stored file open mode (FLDATA TYPE) is \"%s\"";
+   static ZCONST char Far VmMvsInvalid[] = "[invalid]";
+#endif /* CMS_MVS */
+
+static ZCONST char Far First20[] = ".  The first\n    20 are:  ";
+static ZCONST char Far ColonIndent[] = ":\n   ";
+static ZCONST char Far efFormat[] = " %02x";
+
+static ZCONST char Far lExtraFieldType[] = "\n\
+  There %s a local extra field with ID 0x%04x (%s) and\n\
+  %u data bytes (%s).\n";
+static ZCONST char Far efIZuid[] =
+  "GMT modification/access times and Unix UID/GID";
+static ZCONST char Far efIZnouid[] = "GMT modification/access times only";
+
+
+static ZCONST char Far NoFileComment[] = "\n  There is no file comment.\n";
+static ZCONST char Far FileCommBegin[] = "\n\
+------------------------- file comment begins ----------------------------\n";
+static ZCONST char Far FileCommEnd[] = "\
+-------------------------- file comment ends -----------------------------\n";
+
+/* zi_time() strings */
+static ZCONST char Far BogusFmt[] = "%03d";
+static ZCONST char Far DMYHMTime[] = "%2u-%s-%02u %02u:%02u";
+static ZCONST char Far YMDHMSTime[] = "%u %s %u %02u:%02u:%02u";
+static ZCONST char Far DecimalTime[] = "%04u%02u%02u.%02u%02u%02u";
+static ZCONST char Far YMDHMSTimeError[] = "???? ??? ?? ??:??:??";
+
+
+
+
+
+#ifndef WINDLL
+
+/************************/
+/*  Function zi_opts()  */
+/************************/
+
+int zi_opts(__G__ pargc, pargv)
+    int *pargc;
+    char ***pargv;
+    __GDEF
+{
+    char   **argv, *s;
+    int    argc, c, error=FALSE, negative=0;
+    int    hflag_slmv=TRUE, hflag_2=FALSE;  /* diff options => diff defaults */
+    int    tflag_slm=TRUE, tflag_2v=FALSE;
+    int    explicit_h=FALSE, explicit_t=FALSE;
+
+
+#ifdef MACOS
+    uO.lflag = LFLAG;         /* reset default on each call */
+#endif
+    G.extract_flag = FALSE;   /* zipinfo does not extract to disk */
+    argc = *pargc;
+    argv = *pargv;
+
+    while (--argc > 0 && (*++argv)[0] == '-') {
+        s = argv[0] + 1;
+        while ((c = *s++) != 0) {    /* "!= 0":  prevent Turbo C warning */
+            switch (c) {
+                case '-':
+                    ++negative;
+                    break;
+                case '1':      /* shortest listing:  JUST filenames */
+                    if (negative)
+                        uO.lflag = -2, negative = 0;
+                    else
+                        uO.lflag = 1;
+                    break;
+                case '2':      /* just filenames, plus headers if specified */
+                    if (negative)
+                        uO.lflag = -2, negative = 0;
+                    else
+                        uO.lflag = 2;
+                    break;
+#ifndef CMS_MVS
+                case ('C'):    /* -C:  match filenames case-insensitively */
+                    if (negative)
+                        uO.C_flag = FALSE, negative = 0;
+                    else
+                        uO.C_flag = TRUE;
+                    break;
+#endif /* !CMS_MVS */
+                case 'h':      /* header line */
+                    if (negative)
+                        hflag_2 = hflag_slmv = FALSE, negative = 0;
+                    else {
+                        hflag_2 = hflag_slmv = explicit_h = TRUE;
+                        if (uO.lflag == -1)
+                            uO.lflag = 0;
+                    }
+                    break;
+                case 'l':      /* longer form of "ls -l" type listing */
+                    if (negative)
+                        uO.lflag = -2, negative = 0;
+                    else
+                        uO.lflag = 5;
+                    break;
+                case 'm':      /* medium form of "ls -l" type listing */
+                    if (negative)
+                        uO.lflag = -2, negative = 0;
+                    else
+                        uO.lflag = 4;
+                    break;
+#ifdef MORE
+                case 'M':      /* send output through built-in "more" */
+                    if (negative)
+                        G.M_flag = FALSE, negative = 0;
+                    else
+                        G.M_flag = TRUE;
+                    break;
+#endif
+                case 's':      /* default:  shorter "ls -l" type listing */
+                    if (negative)
+                        uO.lflag = -2, negative = 0;
+                    else
+                        uO.lflag = 3;
+                    break;
+                case 't':      /* totals line */
+                    if (negative)
+                        tflag_2v = tflag_slm = FALSE, negative = 0;
+                    else {
+                        tflag_2v = tflag_slm = explicit_t = TRUE;
+                        if (uO.lflag == -1)
+                            uO.lflag = 0;
+                    }
+                    break;
+                case ('T'):    /* use (sortable) decimal time format */
+                    if (negative)
+                        uO.T_flag = FALSE, negative = 0;
+                    else
+                        uO.T_flag = TRUE;
+                    break;
+                case 'v':      /* turbo-verbose listing */
+                    if (negative)
+                        uO.lflag = -2, negative = 0;
+                    else
+                        uO.lflag = 10;
+                    break;
+                case 'z':      /* print zipfile comment */
+                    if (negative)
+                        uO.zflag = negative = 0;
+                    else
+                        uO.zflag = 1;
+                    break;
+                case 'Z':      /* ZipInfo mode:  ignore */
+                    break;
+                default:
+                    error = TRUE;
+                    break;
+            }
+        }
+    }
+    if ((argc-- == 0) || error) {
+        *pargc = argc;
+        *pargv = argv;
+        return USAGE(error);
+    }
+
+#ifdef MORE
+    if (G.M_flag && !isatty(1))  /* stdout redirected: "more" func useless */
+        G.M_flag = 0;
+#endif
+
+    /* if no listing options given (or all negated), or if only -h/-t given
+     * with individual files specified, use default listing format */
+    if ((uO.lflag < 0) || ((argc > 0) && (uO.lflag == 0)))
+        uO.lflag = LFLAG;
+
+    /* set header and totals flags to default or specified values */
+    switch (uO.lflag) {
+        case 0:   /* 0:  can only occur if either -t or -h explicitly given; */
+        case 2:   /*  therefore set both flags equal to normally false value */
+            uO.hflag = hflag_2;
+            uO.tflag = tflag_2v;
+            break;
+        case 1:   /* only filenames, *always* */
+            uO.hflag = FALSE;
+            uO.tflag = FALSE;
+            uO.zflag = FALSE;
+            break;
+        case 3:
+        case 4:
+        case 5:
+            uO.hflag = ((argc > 0) && !explicit_h)? FALSE : hflag_slmv;
+            uO.tflag = ((argc > 0) && !explicit_t)? FALSE : tflag_slm;
+            break;
+        case 10:
+            uO.hflag = hflag_slmv;
+            uO.tflag = tflag_2v;
+            break;
+    }
+
+    *pargc = argc;
+    *pargv = argv;
+    return 0;
+
+} /* end function zi_opts() */
+
+#endif /* !WINDLL */
+
+
+
+
+
+/*******************************/
+/*  Function zi_end_central()  */
+/*******************************/
+
+int zi_end_central(__G)   /* return PK-type error code */
+    __GDEF
+{
+    int  error = PK_COOL;
+
+
+/*---------------------------------------------------------------------------
+    Print out various interesting things about the zipfile.
+  ---------------------------------------------------------------------------*/
+
+    /* header fits on one line, for anything up to 10GB and 10000 files: */
+    if (uO.hflag)
+        Info(slide, 0, ((char *)slide, ((int)strlen(G.zipfn) < 39)?
+          LoadFarString(LongHeader) : LoadFarString(ShortHeader), G.zipfn,
+          (long)G.ziplen, G.ecrec.total_entries_central_dir,
+          (G.ecrec.total_entries_central_dir==1)?
+          nullStr : "s"));
+
+    /* verbose format */
+    if (uO.lflag > 9) {
+        Info(slide, 0, ((char *)slide, LoadFarString(EndCentDirRec)));
+        Info(slide, 0, ((char *)slide, LoadFarString(LineSeparators)));
+
+        Info(slide, 0, ((char *)slide, LoadFarString(ActOffsetCentDir),
+          (long)G.real_ecrec_offset, (long)G.real_ecrec_offset,
+          (long)G.expect_ecrec_offset, (long)G.expect_ecrec_offset));
+
+        if (G.ecrec.number_this_disk == 0) {
+            Info(slide, 0, ((char *)slide, LoadFarString(SinglePartArchive1),
+              G.ecrec.total_entries_central_dir,
+              (G.ecrec.total_entries_central_dir == 1)? "entry" : "entries",
+              G.ecrec.size_central_directory,
+              G.ecrec.size_central_directory));
+            Info(slide, 0, ((char *)slide, LoadFarString(SinglePartArchive2),
+              G.ecrec.offset_start_central_directory,
+              G.ecrec.offset_start_central_directory));
+        } else {
+            Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive1),
+              G.ecrec.number_this_disk + 1,
+              G.ecrec.num_disk_start_cdir + 1,
+              G.ecrec.num_entries_centrl_dir_ths_disk,
+              (G.ecrec.num_entries_centrl_dir_ths_disk == 1)? "is" : "are"));
+            Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive2),
+              G.ecrec.total_entries_central_dir,
+              (G.ecrec.total_entries_central_dir == 1) ? "entry" : "entries",
+              G.ecrec.size_central_directory,
+              G.ecrec.size_central_directory));
+            Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive3),
+              G.ecrec.offset_start_central_directory,
+              G.ecrec.offset_start_central_directory));
+        }
+
+    /*-----------------------------------------------------------------------
+        Get the zipfile comment, if any, and print it out.  (Comment may be
+        up to 64KB long.  May the fleas of a thousand camels infest the arm-
+        pits of anyone who actually takes advantage of this fact.)
+      -----------------------------------------------------------------------*/
+
+        if (!G.ecrec.zipfile_comment_length)
+            Info(slide, 0, ((char *)slide, LoadFarString(NoZipfileComment)));
+        else {
+            Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommentDesc),
+              G.ecrec.zipfile_comment_length));
+            Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommBegin)));
+            if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY))
+                error = PK_WARN;
+            Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommEnd)));
+            if (error)
+                Info(slide, 0, ((char *)slide,
+                  LoadFarString(ZipfileCommTrunc2)));
+        } /* endif (comment exists) */
+
+    /* non-verbose mode:  print zipfile comment only if requested */
+    } else if (uO.zflag && G.ecrec.zipfile_comment_length) {
+        if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) {
+            Info(slide, 0x401, ((char *)slide,
+              LoadFarString(ZipfileCommTruncMsg)));
+            error = PK_WARN;
+        }
+    } /* endif (verbose) */
+
+    return error;
+
+} /* end function zi_end_central() */
+
+
+
+
+
+/************************/
+/*  Function zipinfo()  */
+/************************/
+
+int zipinfo(__G)   /* return PK-type error code */
+    __GDEF
+{
+    int do_this_file=FALSE, error, error_in_archive=PK_COOL;
+    int *fn_matched=NULL, *xn_matched=NULL;
+    unsigned j, members=0;
+    ulg tot_csize=0L, tot_ucsize=0L;
+    ulg endprev;   /* buffers end of previous entry for zi_long()'s check
+                    *  of extra bytes */
+
+
+/*---------------------------------------------------------------------------
+    Malloc space for check on unmatched filespecs (no big deal if one or both
+    are NULL).
+  ---------------------------------------------------------------------------*/
+
+    if (G.filespecs > 0  &&
+        (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != NULL)
+        for (j = 0;  j < G.filespecs;  ++j)
+            fn_matched[j] = FALSE;
+
+    if (G.xfilespecs > 0  &&
+        (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != NULL)
+        for (j = 0;  j < G.xfilespecs;  ++j)
+            xn_matched[j] = FALSE;
+
+/*---------------------------------------------------------------------------
+    Set file pointer to start of central directory, then loop through cen-
+    tral directory entries.  Check that directory-entry signature bytes are
+    actually there (just a precaution), then process the entry.  We know
+    the entire central directory is on this disk:  we wouldn't have any of
+    this information unless the end-of-central-directory record was on this
+    disk, and we wouldn't have gotten to this routine unless this is also
+    the disk on which the central directory starts.  In practice, this had
+    better be the *only* disk in the archive, but maybe someday we'll add
+    multi-disk support.
+  ---------------------------------------------------------------------------*/
+
+    uO.L_flag = FALSE;      /* zipinfo mode: never convert name to lowercase */
+    G.pInfo = G.info;       /* (re-)initialize, (just to make sure) */
+    G.pInfo->textmode = 0;  /* so one can read on screen (is this ever used?) */
+
+    /* reset endprev for new zipfile; account for multi-part archives (?) */
+    endprev = (G.crec.relative_offset_local_header == 4L)? 4L : 0L;
+
+
+    for (j = 0; j++ < (unsigned)G.ecrec.total_entries_central_dir;) {
+        if (readbuf(__G__ G.sig, 4) == 0)
+            return PK_EOF;
+        if (strncmp(G.sig, central_hdr_sig, 4)) {  /* just to make sure */
+            Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg), j));
+            return PK_BADERR;   /* sig not found */
+        }
+        /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag, ...: */
+        if ((error = process_cdir_file_hdr(__G)) != PK_COOL)
+            return error;       /* only PK_EOF defined */
+
+        if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=
+             PK_COOL)
+        {
+          error_in_archive = error;   /* might be warning */
+          if (error > PK_WARN)        /* fatal */
+              return error;
+        }
+
+        if (!G.process_all_files) {   /* check if specified on command line */
+            unsigned i;
+
+            do_this_file = FALSE;
+            for (i = 0; i < G.filespecs; i++)
+                if (match(G.filename, G.pfnames[i], uO.C_flag)) {
+                    do_this_file = TRUE;
+                    if (fn_matched)
+                        fn_matched[i] = TRUE;
+                    break;       /* found match, so stop looping */
+                }
+            if (do_this_file) {  /* check if this is an excluded file */
+                for (i = 0; i < G.xfilespecs; i++)
+                    if (match(G.filename, G.pxnames[i], uO.C_flag)) {
+                        do_this_file = FALSE;  /* ^-- ignore case in match */
+                        if (xn_matched)
+                            xn_matched[i] = TRUE;
+                        break;
+                    }
+            }
+        }
+
+    /*-----------------------------------------------------------------------
+        If current file was specified on command line, or if no names were
+        specified, do the listing for this file.  Otherwise, get rid of the
+        file comment and go back for the next file.
+      -----------------------------------------------------------------------*/
+
+        if (G.process_all_files || do_this_file) {
+
+            switch (uO.lflag) {
+                case 1:
+                case 2:
+                    fnprint(__G);
+                    SKIP_(G.crec.extra_field_length)
+                    SKIP_(G.crec.file_comment_length)
+                    break;
+
+                case 3:
+                case 4:
+                case 5:
+                    if ((error = zi_short(__G)) != PK_COOL) {
+                        error_in_archive = error;   /* might be warning */
+                        if (error > PK_WARN)        /* fatal */
+                            return error;
+                    }
+                    break;
+
+                case 10:
+                    Info(slide, 0, ((char *)slide,
+                      LoadFarString(CentralDirEntry), j));
+                    if ((error = zi_long(__G__ &endprev)) != PK_COOL) {
+                        error_in_archive = error;   /* might be warning */
+                        if (error > PK_WARN)        /* fatal */
+                            return error;
+                    }
+                    break;
+
+                default:
+                    SKIP_(G.crec.extra_field_length)
+                    SKIP_(G.crec.file_comment_length)
+                    break;
+
+            } /* end switch (lflag) */
+
+            tot_csize += G.crec.csize;
+            tot_ucsize += G.crec.ucsize;
+            if (G.crec.general_purpose_bit_flag & 1)
+                tot_csize -= 12;   /* don't count encryption header */
+            ++members;
+
+#ifdef DLL
+            if ((G.statreportcb != NULL) &&
+                (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn,
+                                  G.filename, NULL)) {
+                if (fn_matched)
+                    free((zvoid *)fn_matched);
+                if (xn_matched)
+                    free((zvoid *)xn_matched);
+                return IZ_CTRLC;        /* cancel operation by user request */
+            }
+#endif
+#ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */
+            UserStop();
+#endif
+
+        } else {        /* not listing this file */
+            SKIP_(G.crec.extra_field_length)
+            SKIP_(G.crec.file_comment_length)
+
+        } /* end if (list member?) */
+
+    } /* end for-loop (j: member files) */
+
+/*---------------------------------------------------------------------------
+    Check that we actually found requested files; if so, print totals.
+  ---------------------------------------------------------------------------*/
+
+    if (uO.tflag) {
+        char *sgn = "";
+        int cfactor = ratio(tot_ucsize, tot_csize);
+
+        if (cfactor < 0) {
+            sgn = "-";
+            cfactor = -cfactor;
+        }
+        Info(slide, 0, ((char *)slide, LoadFarString(ZipfileStats),
+          members, (members==1)? nullStr:"s", tot_ucsize,
+          tot_csize, sgn, cfactor/10, cfactor%10));
+    }
+
+/*---------------------------------------------------------------------------
+    Check for unmatched filespecs on command line and print warning if any
+    found.
+  ---------------------------------------------------------------------------*/
+
+    if (fn_matched) {
+        for (j = 0;  j < G.filespecs;  ++j)
+            if (!fn_matched[j])
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(FilenameNotMatched), G.pfnames[j]));
+        free((zvoid *)fn_matched);
+    }
+    if (xn_matched) {
+        for (j = 0;  j < G.xfilespecs;  ++j)
+            if (!xn_matched[j])
+                Info(slide, 0x401, ((char *)slide,
+                  LoadFarString(ExclFilenameNotMatched), G.pxnames[j]));
+        free((zvoid *)xn_matched);
+    }
+
+/*---------------------------------------------------------------------------
+    Double check that we're back at the end-of-central-directory record.
+  ---------------------------------------------------------------------------*/
+
+    if (readbuf(__G__ G.sig, 4) == 0)  /* disk error? */
+        return PK_EOF;
+    if (strncmp(G.sig, end_central_sig, 4)) {   /* just to make sure again */
+        Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
+        error_in_archive = PK_WARN;   /* didn't find sig */
+    }
+    if (members == 0 && error_in_archive <= PK_WARN)
+        error_in_archive = PK_FIND;
+
+    if (uO.lflag >= 10)
+        (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
+
+    return error_in_archive;
+
+} /* end function zipinfo() */
+
+
+
+
+
+/************************/
+/*  Function zi_long()  */
+/************************/
+
+static int zi_long(__G__ pEndprev)   /* return PK-type error code */
+    __GDEF
+    ulg *pEndprev;                   /* for zi_long() check of extra bytes */
+{
+#ifdef USE_EF_UT_TIME
+    iztimes z_utime;
+#endif
+    int  error, error_in_archive=PK_COOL;
+    ush  hostnum, hostver, extnum, extver, methnum, xattr;
+    char workspace[12], attribs[22];
+    ZCONST char *varmsg_str;
+    char unkn[16];
+    static ZCONST char Far *os[NUM_HOSTS] = {
+        OS_FAT, OS_Amiga, OS_VMS, OS_Unix, OS_VMCMS, OS_AtariST, OS_HPFS,
+        OS_Macintosh, OS_ZSystem, OS_CPM, OS_TOPS20, OS_NTFS, OS_QDOS,
+        OS_Acorn, OS_VFAT, OS_MVS, OS_BeOS, OS_Tandem
+    };
+    static ZCONST char Far *method[NUM_METHODS] = {
+        MthdNone, MthdShrunk, MthdRedF1, MthdRedF2, MthdRedF3, MthdRedF4,
+        MthdImplode, MthdToken, MthdDeflate, MthdEnDeflate, MthdDCLImplode
+    };
+    static ZCONST char Far *dtypelng[4] = {
+        DeflNorm, DeflMax, DeflFast, DeflSFast
+    };
+
+
+/*---------------------------------------------------------------------------
+    Check whether there's any extra space inside the zipfile.  If *pEndprev is
+    zero, it's probably a signal that OS/2 extra fields are involved (with
+    unknown compressed size).  We won't worry about prepended junk here...
+  ---------------------------------------------------------------------------*/
+
+    if (G.crec.relative_offset_local_header != *pEndprev && *pEndprev > 0L) {
+        /*  GRR DEBUG
+        Info(slide, 0, ((char *)slide,
+          "  [crec.relative_offset_local_header = %lu, endprev = %lu]\n",
+          G.crec.relative_offset_local_header, *pEndprev));
+         */
+        Info(slide, 0, ((char *)slide, LoadFarString(ExtraBytesPreceding),
+          (long)G.crec.relative_offset_local_header - (long)(*pEndprev)));
+    }
+
+    /* calculate endprev for next time around (problem:  extra fields may
+     * differ in length between local and central-directory records) */
+    *pEndprev = G.crec.relative_offset_local_header + 4L + LREC_SIZE +
+      G.crec.filename_length + G.crec.extra_field_length +
+      G.crec.file_comment_length + G.crec.csize;
+
+/*---------------------------------------------------------------------------
+    Read the extra field, if any. It may be used to get UNIX style modtime.
+  ---------------------------------------------------------------------------*/
+
+    if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) != 0)
+    {
+        if (G.extra_field != NULL) {
+            free(G.extra_field);
+            G.extra_field = NULL;
+        }
+        error_in_archive = error;
+        /* The premature return in case of a "fatal" error (PK_EOF) is
+         * delayed until we analyze the extra field contents.
+         * This allows us to display all the other info that has been
+         * successfully read in.
+         */
+    }
+
+/*---------------------------------------------------------------------------
+    Print out various interesting things about the compressed file.
+  ---------------------------------------------------------------------------*/
+
+    hostnum = (ush)(G.pInfo->hostnum);
+    hostver = G.crec.version_made_by[0];
+    extnum = (ush)MIN(G.crec.version_needed_to_extract[1], NUM_HOSTS);
+    extver = G.crec.version_needed_to_extract[0];
+    methnum = (ush)MIN(G.crec.compression_method, NUM_METHODS);
+
+    (*G.message)((zvoid *)&G, (uch *)"  ", 2L, 0);  fnprint(__G);
+
+    Info(slide, 0, ((char *)slide, LoadFarString(LocalHeaderOffset),
+      G.crec.relative_offset_local_header,
+      G.crec.relative_offset_local_header));
+
+    if (hostnum >= NUM_HOSTS) {
+        sprintf(unkn, LoadFarString(UnknownNo),
+                (int)G.crec.version_made_by[1]);
+        varmsg_str = unkn;
+    } else {
+        varmsg_str = LoadFarStringSmall(os[hostnum]);
+    }
+    Info(slide, 0, ((char *)slide, LoadFarString(HostOS), varmsg_str));
+    Info(slide, 0, ((char *)slide, LoadFarString(EncodeSWVer), hostver/10,
+      hostver%10));
+
+    if (extnum >= NUM_HOSTS) {
+        sprintf(unkn, LoadFarString(UnknownNo),
+                (int)G.crec.version_needed_to_extract[1]);
+        varmsg_str = unkn;
+    } else {
+        varmsg_str = LoadFarStringSmall(os[extnum]);
+    }
+    Info(slide, 0, ((char *)slide, LoadFarString(MinOSCompReq), varmsg_str));
+    Info(slide, 0, ((char *)slide, LoadFarString(MinSWVerReq), extver/10,
+      extver%10));
+
+    if (methnum >= NUM_METHODS) {
+        sprintf(unkn, LoadFarString(UnknownNo), G.crec.compression_method);
+        varmsg_str = unkn;
+    } else {
+        varmsg_str = LoadFarStringSmall(method[methnum]);
+    }
+    Info(slide, 0, ((char *)slide, LoadFarString(CompressMethod), varmsg_str));
+    if (methnum == IMPLODED) {
+        Info(slide, 0, ((char *)slide, LoadFarString(SlideWindowSizeImplode),
+          (G.crec.general_purpose_bit_flag & 2)? '8' : '4'));
+        Info(slide, 0, ((char *)slide, LoadFarString(ShannonFanoTrees),
+          (G.crec.general_purpose_bit_flag & 4)? '3' : '2'));
+    } else if (methnum == DEFLATED) {
+        ush  dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3);
+
+        Info(slide, 0, ((char *)slide, LoadFarString(CompressSubtype),
+          LoadFarStringSmall(dtypelng[dnum])));
+    }
+
+    Info(slide, 0, ((char *)slide, LoadFarString(FileSecurity),
+      (G.crec.general_purpose_bit_flag & 1) ? nullStr : "not "));
+    Info(slide, 0, ((char *)slide, LoadFarString(ExtendedLocalHdr),
+      (G.crec.general_purpose_bit_flag & 8) ? "yes" : "no"));
+    /* print upper 3 bits for amusement? */
+
+    /* For printing of date & time, a "char d_t_buf[21]" is required.
+     * To save stack space, we reuse the "char attribs[22]" buffer which
+     * is not used yet.
+     */
+#   define d_t_buf attribs
+
+    zi_time(__G__ &G.crec.last_mod_dos_datetime, NULL, d_t_buf);
+    Info(slide, 0, ((char *)slide, LoadFarString(FileModDate), d_t_buf));
+#ifdef USE_EF_UT_TIME
+    if (G.extra_field &&
+#ifdef IZ_CHECK_TZ
+        G.tz_is_valid &&
+#endif
+        (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,
+                          G.crec.last_mod_dos_datetime, &z_utime, NULL)
+         & EB_UT_FL_MTIME))
+    {
+        TIMET_TO_NATIVE(z_utime.mtime)   /* NOP unless MSC 7.0 or Macintosh */
+        d_t_buf[0] = (char)0;               /* signal "show local time" */
+        zi_time(__G__ &G.crec.last_mod_dos_datetime, &(z_utime.mtime), d_t_buf);
+        Info(slide, 0, ((char *)slide, LoadFarString(UT_FileModDate),
+          d_t_buf, LoadFarStringSmall(LocalTime)));
+#ifndef NO_GMTIME
+        d_t_buf[0] = (char)1;           /* signal "show UTC (GMT) time" */
+        zi_time(__G__ &G.crec.last_mod_dos_datetime, &(z_utime.mtime), d_t_buf);
+        Info(slide, 0, ((char *)slide, LoadFarString(UT_FileModDate),
+          d_t_buf, LoadFarStringSmall(GMTime)));
+#endif /* !NO_GMTIME */
+    }
+#endif /* USE_EF_UT_TIME */
+
+    Info(slide, 0, ((char *)slide, LoadFarString(CRC32Value), G.crec.crc32));
+    Info(slide, 0, ((char *)slide, LoadFarString(CompressedFileSize),
+      G.crec.csize));
+    Info(slide, 0, ((char *)slide, LoadFarString(UncompressedFileSize),
+      G.crec.ucsize));
+    Info(slide, 0, ((char *)slide, LoadFarString(FilenameLength),
+      G.crec.filename_length));
+    Info(slide, 0, ((char *)slide, LoadFarString(ExtraFieldLength),
+      G.crec.extra_field_length));
+    Info(slide, 0, ((char *)slide, LoadFarString(FileCommentLength),
+      G.crec.file_comment_length));
+    Info(slide, 0, ((char *)slide, LoadFarString(FileDiskNum),
+      G.crec.disk_number_start + 1));
+    Info(slide, 0, ((char *)slide, LoadFarString(ApparentFileType),
+      (G.crec.internal_file_attributes & 1)? "text"
+         : (G.crec.internal_file_attributes & 2)? "ebcdic"
+              : "binary"));             /* changed to accept EBCDIC */
+#ifdef ATARI
+    printf("  external file attributes (hex):                   %.8lx\n",
+      G.crec.external_file_attributes);
+#endif
+    xattr = (ush)((G.crec.external_file_attributes >> 16) & 0xFFFF);
+    if (hostnum == VMS_) {
+        char   *p=attribs, *q=attribs+1;
+        int    i, j, k;
+
+        for (k = 0;  k < 12;  ++k)
+            workspace[k] = 0;
+        if (xattr & VMS_IRUSR)
+            workspace[0] = 'R';
+        if (xattr & VMS_IWUSR) {
+            workspace[1] = 'W';
+            workspace[3] = 'D';
+        }
+        if (xattr & VMS_IXUSR)
+            workspace[2] = 'E';
+        if (xattr & VMS_IRGRP)
+            workspace[4] = 'R';
+        if (xattr & VMS_IWGRP) {
+            workspace[5] = 'W';
+            workspace[7] = 'D';
+        }
+        if (xattr & VMS_IXGRP)
+            workspace[6] = 'E';
+        if (xattr & VMS_IROTH)
+            workspace[8] = 'R';
+        if (xattr & VMS_IWOTH) {
+            workspace[9] = 'W';
+            workspace[11] = 'D';
+        }
+        if (xattr & VMS_IXOTH)
+            workspace[10] = 'E';
+
+        *p++ = '(';
+        for (k = j = 0;  j < 3;  ++j) {    /* loop over groups of permissions */
+            for (i = 0;  i < 4;  ++i, ++k)  /* loop over perms within a group */
+                if (workspace[k])
+                    *p++ = workspace[k];
+            *p++ = ',';                       /* group separator */
+            if (j == 0)
+                while ((*p++ = *q++) != ',')
+                    ;                         /* system, owner perms are same */
+        }
+        *p-- = 0;
+        *p = ')';   /* overwrite last comma */
+        Info(slide, 0, ((char *)slide, LoadFarString(VMSFileAttributes), xattr,
+          attribs));
+
+    } else if (hostnum == AMIGA_) {
+        switch (xattr & AMI_IFMT) {
+            case AMI_IFDIR:  attribs[0] = 'd';  break;
+            case AMI_IFREG:  attribs[0] = '-';  break;
+            default:         attribs[0] = '?';  break;
+        }
+        attribs[1] = (xattr & AMI_IHIDDEN)?   'h' : '-';
+        attribs[2] = (xattr & AMI_ISCRIPT)?   's' : '-';
+        attribs[3] = (xattr & AMI_IPURE)?     'p' : '-';
+        attribs[4] = (xattr & AMI_IARCHIVE)?  'a' : '-';
+        attribs[5] = (xattr & AMI_IREAD)?     'r' : '-';
+        attribs[6] = (xattr & AMI_IWRITE)?    'w' : '-';
+        attribs[7] = (xattr & AMI_IEXECUTE)?  'e' : '-';
+        attribs[8] = (xattr & AMI_IDELETE)?   'd' : '-';
+        attribs[9] = 0;   /* better dlm the string */
+        Info(slide, 0, ((char *)slide, LoadFarString(AmigaFileAttributes),
+          xattr, attribs));
+
+    } else if ((hostnum != FS_FAT_) && (hostnum != FS_HPFS_) &&
+               (hostnum != FS_NTFS_) && (hostnum != FS_VFAT_) &&
+               (hostnum != ACORN_) &&
+               (hostnum != VM_CMS_) && (hostnum != MVS_))
+    {                                 /* assume Unix-like */
+        switch ((unsigned)(xattr & UNX_IFMT)) {
+            case (unsigned)UNX_IFDIR:   attribs[0] = 'd';  break;
+            case (unsigned)UNX_IFREG:   attribs[0] = '-';  break;
+            case (unsigned)UNX_IFLNK:   attribs[0] = 'l';  break;
+            case (unsigned)UNX_IFBLK:   attribs[0] = 'b';  break;
+            case (unsigned)UNX_IFCHR:   attribs[0] = 'c';  break;
+            case (unsigned)UNX_IFIFO:   attribs[0] = 'p';  break;
+            case (unsigned)UNX_IFSOCK:  attribs[0] = 's';  break;
+            default:          attribs[0] = '?';  break;
+        }
+        attribs[1] = (xattr & UNX_IRUSR)? 'r' : '-';
+        attribs[4] = (xattr & UNX_IRGRP)? 'r' : '-';
+        attribs[7] = (xattr & UNX_IROTH)? 'r' : '-';
+
+        attribs[2] = (xattr & UNX_IWUSR)? 'w' : '-';
+        attribs[5] = (xattr & UNX_IWGRP)? 'w' : '-';
+        attribs[8] = (xattr & UNX_IWOTH)? 'w' : '-';
+
+        if (xattr & UNX_IXUSR)
+            attribs[3] = (xattr & UNX_ISUID)? 's' : 'x';
+        else
+            attribs[3] = (xattr & UNX_ISUID)? 'S' : '-';   /* S = undefined */
+        if (xattr & UNX_IXGRP)
+            attribs[6] = (xattr & UNX_ISGID)? 's' : 'x';   /* == UNX_ENFMT */
+        else
+            attribs[6] = (xattr & UNX_ISGID)? 'l' : '-';
+        if (xattr & UNX_IXOTH)
+            attribs[9] = (xattr & UNX_ISVTX)? 't' : 'x';   /* "sticky bit" */
+        else
+            attribs[9] = (xattr & UNX_ISVTX)? 'T' : '-';   /* T = undefined */
+        attribs[10] = 0;
+
+        Info(slide, 0, ((char *)slide, LoadFarString(UnixFileAttributes), xattr,
+          attribs));
+
+    } else {
+        Info(slide, 0, ((char *)slide, LoadFarString(NonMSDOSFileAttributes),
+            G.crec.external_file_attributes >> 8));
+
+    } /* endif (hostnum: external attributes format) */
+
+    if ((xattr=(ush)(G.crec.external_file_attributes & 0xFF)) == 0)
+        Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributes),
+          xattr));
+    else if (xattr == 1)
+        Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributesRO),
+          xattr));
+    else
+        Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributesAlpha),
+          xattr, (xattr&1)? "rdo " : nullStr,
+          (xattr&2)? "hid " : nullStr,
+          (xattr&4)? "sys " : nullStr,
+          (xattr&8)? "lab " : nullStr,
+          (xattr&16)? "dir " : nullStr,
+          (xattr&32)? "arc" : nullStr));
+
+/*---------------------------------------------------------------------------
+    Analyze the extra field, if any, and print the file comment, if any (the
+    filename has already been printed, above).  That finishes up this file
+    entry...
+  ---------------------------------------------------------------------------*/
+
+    if (G.crec.extra_field_length > 0) {
+        uch *ef_ptr = G.extra_field;
+        ush ef_len = G.crec.extra_field_length;
+        ush eb_id, eb_datalen;
+        ZCONST char Far *ef_fieldname;
+
+        if (error_in_archive > PK_WARN)   /* fatal:  can't continue */
+            /* delayed "fatal error" return from extra field reading */
+            return error;
+        if (G.extra_field == (uch *)NULL)
+            return PK_ERR;   /* not consistent with crec length */
+
+        Info(slide, 0, ((char *)slide, LoadFarString(ExtraFields)));
+
+        while (ef_len >= EB_HEADSIZE) {
+            eb_id = makeword(&ef_ptr[EB_ID]);
+            eb_datalen = makeword(&ef_ptr[EB_LEN]);
+            ef_ptr += EB_HEADSIZE;
+            ef_len -= EB_HEADSIZE;
+
+            if (eb_datalen > (ush)ef_len) {
+                Info(slide, 0x421, ((char *)slide,
+                  LoadFarString(ExtraFieldTrunc), eb_id, eb_datalen, ef_len));
+                eb_datalen = ef_len;
+            }
+
+            switch (eb_id) {
+                case EF_AV:
+                    ef_fieldname = efAV;
+                    break;
+                case EF_OS2:
+                    ef_fieldname = efOS2;
+                    break;
+                case EF_ACL:
+                    ef_fieldname = efACL;
+                    break;
+                case EF_NTSD:
+                    ef_fieldname = efNTSD;
+                    break;
+                case EF_PKVMS:
+                    ef_fieldname = efPKVMS;
+                    break;
+                case EF_IZVMS:
+                    ef_fieldname = efIZVMS;
+                    break;
+                case EF_PKW32:
+                    ef_fieldname = efPKWin32;
+                    break;
+                case EF_PKUNIX:
+                    ef_fieldname = efPKUnix;
+                    break;
+                case EF_IZUNIX:
+                    ef_fieldname = efIZUnix;
+                    if (G.crec.version_made_by[1] == UNIX_ && *pEndprev > 0L)
+                        *pEndprev += 4L;  /* also have UID/GID in local copy */
+                    break;
+                case EF_IZUNIX2:
+                    ef_fieldname = efIZUnix2;
+                    if (*pEndprev > 0L)
+                        *pEndprev += 4L;  /* 4 byte UID/GID in local copy */
+                    break;
+                case EF_TIME:
+                    ef_fieldname = efTime;
+                    break;
+                case EF_MAC3:
+                    ef_fieldname = efMac3;
+                    break;
+                case EF_JLMAC:
+                    ef_fieldname = efJLMac;
+                    break;
+                case EF_ZIPIT:
+                    ef_fieldname = efZipIt;
+                    break;
+                case EF_ZIPIT2:
+                    ef_fieldname = efZipIt2;
+                    break;
+                case EF_VMCMS:
+                    ef_fieldname = efVMCMS;
+                    break;
+                case EF_MVS:
+                    ef_fieldname = efMVS;
+                    break;
+                case EF_BEOS:
+                    ef_fieldname = efBeOS;
+                    break;
+                case EF_QDOS:
+                    ef_fieldname = efQDOS;
+                    break;
+                case EF_AOSVS:
+                    ef_fieldname = efAOSVS;
+                    break;
+                case EF_SPARK:   /* from RISC OS */
+                    ef_fieldname = efSpark;
+                    break;
+                case EF_MD5:
+                    ef_fieldname = efMD5;
+                    break;
+                case EF_ASIUNIX:
+                    ef_fieldname = efASiUnix;
+                    break;
+                default:
+                    ef_fieldname = efUnknown;
+                    break;
+            }
+            Info(slide, 0, ((char *)slide, LoadFarString(ExtraFieldType),
+                 eb_id, LoadFarStringSmall(ef_fieldname), eb_datalen));
+
+            /* additional, field-specific information: */
+            switch (eb_id) {
+                case EF_OS2:
+                case EF_ACL:
+                    if (eb_datalen >= EB_OS2_HLEN) {
+                        if (eb_id == EF_OS2)
+                            ef_fieldname = OS2EAs;
+                        else
+                            ef_fieldname = ACLdata;
+                        Info(slide, 0, ((char *)slide,
+                          LoadFarString(ef_fieldname), makelong(ef_ptr)));
+                        *pEndprev = 0L;   /* no clue about csize of local */
+                    }
+                    break;
+                case EF_NTSD:
+                    if (eb_datalen >= EB_NTSD_C_LEN) {
+                        Info(slide, 0, ((char *)slide, LoadFarString(NTSDData),
+                          makelong(ef_ptr)));
+                        *pEndprev = 0L;   /* no clue about csize of local */
+                    }
+                    break;
+                case EF_IZVMS:
+                    if (eb_datalen >= 8) {
+                        char *p, q[8];
+                        int compr = makeword(ef_ptr+4) & 7;
+
+                        *q = '\0';
+                        if (compr > 3)
+                            compr = 3;
+                        if (strncmp((char *)ef_ptr, "VFAB", 4) == 0)
+                            p = "FAB";
+                        else if (strncmp((char *)ef_ptr, "VALL", 4) == 0)
+                            p = "XABALL";
+                        else if (strncmp((char *)ef_ptr, "VFHC", 4) == 0)
+                            p = "XABFHC";
+                        else if (strncmp((char *)ef_ptr, "VDAT", 4) == 0)
+                            p = "XABDAT";
+                        else if (strncmp((char *)ef_ptr, "VRDT", 4) == 0)
+                            p = "XABRDT";
+                        else if (strncmp((char *)ef_ptr, "VPRO", 4) == 0)
+                            p = "XABPRO";
+                        else if (strncmp((char *)ef_ptr, "VKEY", 4) == 0)
+                            p = "XABKEY";
+                        else if (strncmp((char *)ef_ptr, "VMSV", 4) == 0) {
+                            p = "version";
+                            if (eb_datalen >= 16) {
+                                q[0] = ' ';
+                                q[1] = '(';
+                                strncpy(q+2, (char *)ef_ptr+12, 4);
+                                q[6] = ')';
+                                q[7] = '\0';
+                            }
+                        } else
+                            p = "version";
+                        Info(slide, 0, ((char *)slide, LoadFarString(izVMSdata),
+                          LoadFarStringSmall(izVMScomp[compr]),
+                          makeword(ef_ptr+6), p, q));
+                    }
+                    break;
+                case EF_TIME:
+                    if (eb_datalen >= 1) {
+                        char types[80];
+                        int num = 0, len;
+
+                        *types = '\0';
+                        if (*ef_ptr & 1) {
+                            strcpy(types, LoadFarString(UTmodification));
+                            ++num;
+                        }
+                        if (*ef_ptr & 2) {
+                            len = strlen(types);
+                            if (num)
+                                types[len++] = '/';
+                            strcpy(types+len, LoadFarString(UTaccess));
+                            ++num;
+                            if (*pEndprev > 0L)
+                                *pEndprev += 4L;
+                        }
+                        if (*ef_ptr & 4) {
+                            len = strlen(types);
+                            if (num)
+                                types[len++] = '/';
+                            strcpy(types+len, LoadFarString(UTcreation));
+                            ++num;
+                            if (*pEndprev > 0L)
+                                *pEndprev += 4L;
+                        }
+                        if (num > 0)
+                            Info(slide, 0, ((char *)slide,
+                              LoadFarString(UTdata), types,
+                              num == 1? nullStr : "s"));
+                    }
+                    break;
+                case EF_MAC3:
+                    if (eb_datalen >= EB_MAC3_HLEN) {
+                        ulg eb_uc = makelong(ef_ptr);
+                        unsigned mac3_flgs = makeword(ef_ptr+EB_FLGS_OFFS);
+                        unsigned eb_is_uc = mac3_flgs & EB_M3_FL_UNCMPR;
+
+                        Info(slide, 0, ((char *)slide, LoadFarString(Mac3data),
+                          eb_uc, eb_is_uc ? "un" : nullStr));
+                        if (eb_is_uc) {
+                            if (*pEndprev > 0L)
+                                *pEndprev += makelong(ef_ptr);
+                        } else {
+                            *pEndprev = 0L; /* no clue about csize of local */
+                        }
+
+                        Info(slide, 0, ((char *)slide,
+                          LoadFarString(MacOSMAC3flags),
+                          LoadFarStringSmall(mac3_flgs & EB_M3_FL_DATFRK ?
+                                             MacOS_DF : MacOS_RF),
+                          (mac3_flgs & EB_M3_FL_TIME64 ? 64 : 32)));
+                        zi_showMacTypeCreator(__G__ &ef_ptr[6]);
+                    }
+                    break;
+                case EF_ZIPIT2:
+                    if (eb_datalen >= 5 &&
+                        strncmp((char *)ef_ptr, "ZPIT", 4) == 0) {
+
+                        if (eb_datalen >= 12) {
+                            zi_showMacTypeCreator(__G__ &ef_ptr[4]);
+                        }
+                    }
+
+                case EF_ZIPIT:
+                    if (eb_datalen >= 5 &&
+                        strncmp((char *)ef_ptr, "ZPIT", 4) == 0) {
+                        unsigned fnlen = ef_ptr[4];
+
+                        if (eb_datalen >= fnlen + (5 + 8)) {
+                            uch nullchar = ef_ptr[fnlen+5];
+
+                            ef_ptr[fnlen+5] = '\0'; /* terminate filename */
+                            Info(slide, 0, ((char *)slide,
+                              LoadFarString(ZipItFname), (char *)ef_ptr+5));
+                            ef_ptr[fnlen+5] = nullchar;
+                            zi_showMacTypeCreator(__G__ &ef_ptr[fnlen+5]);
+                        }
+                    }
+                    break;
+                case EF_JLMAC:
+                    if (eb_datalen >= 40 &&
+                        strncmp((char *)ef_ptr, "JLEE", 4) == 0)
+                    {
+                        zi_showMacTypeCreator(__G__ &ef_ptr[4]);
+
+                        Info(slide, 0, ((char *)slide,
+                          LoadFarString(MacOSJLEEflags),
+                          LoadFarStringSmall(ef_ptr[31] & 1 ?
+                                             MacOS_DF : MacOS_RF)));
+                    }
+                    break;
+#ifdef CMS_MVS
+                case EF_VMCMS:
+                case EF_MVS:
+                    {
+                        char type[100];
+
+                        Info(slide, 0, ((char *)slide,
+                             LoadFarString(VmMvsExtraField),
+                             (getVMMVSexfield(type, ef_ptr-EB_HEADSIZE,
+                             (unsigned)eb_datalen) > 0)?
+                             type : LoadFarStringSmall(VmMvsInvalid)));
+                    }
+                    break;
+#endif /* CMS_MVS */
+                case EF_BEOS:
+                    if (eb_datalen >= EB_BEOS_HLEN) {
+                        ulg eb_uc = makelong(ef_ptr);
+                        unsigned eb_is_uc =
+                          *(ef_ptr+EB_FLGS_OFFS) & EB_BE_FL_UNCMPR;
+
+                        Info(slide, 0, ((char *)slide, LoadFarString(BeOSdata),
+                          eb_uc, eb_is_uc ? "un" : nullStr));
+                        if (eb_is_uc) {
+                            if (*pEndprev > 0L)
+                                *pEndprev += makelong(ef_ptr);
+                        } else {
+                            *pEndprev = 0L; /* no clue about csize of local */
+                        }
+                    }
+                    break;
+                case EF_QDOS:
+                    if (eb_datalen >= 4) {
+                        Info(slide, 0, ((char *)slide, LoadFarString(QDOSdata),
+                          ef_ptr[0], ef_ptr[1], ef_ptr[2], ef_ptr[3]));
+                    }
+                    break;
+                case EF_AOSVS:
+                    if (eb_datalen >= 5) {
+                        Info(slide, 0, ((char *)slide, LoadFarString(AOSVSdata),
+                          ((int)(uch)ef_ptr[4])/10, ((int)(uch)ef_ptr[4])%10));
+                    }
+                    break;
+                case EF_MD5:
+                    if (eb_datalen >= 19) {
+                        char md5[33];
+                        int i;
+
+                        for (i = 0;  i < 16;  ++i)
+                            sprintf(&md5[i<<1], "%02x", ef_ptr[15-i]);
+                        md5[32] = '\0';
+                        Info(slide, 0, ((char *)slide, LoadFarString(MD5data),
+                          md5));
+                        break;
+                    }   /* else: fall through !! */
+                default:
+                    if (eb_datalen > 0) {
+                        ush i, n;
+
+                        if (eb_datalen <= 24) {
+                            Info(slide, 0, ((char *)slide,
+                                 LoadFarString(ColonIndent)));
+                            n = eb_datalen;
+                        } else {
+                            Info(slide, 0, ((char *)slide,
+                                 LoadFarString(First20)));
+                            n = 20;
+                        }
+                        for (i = 0;  i < n;  ++i)
+                            Info(slide, 0, ((char *)slide,
+                                 LoadFarString(efFormat), ef_ptr[i]));
+                    }
+                    break;
+            }
+            (*G.message)((zvoid *)&G, (uch *)".", 1L, 0);
+
+            ef_ptr += eb_datalen;
+            ef_len -= eb_datalen;
+        }
+        (*G.message)((zvoid *)&G, (uch *)"\n", 1L, 0);
+    }
+
+    /* high bit == Unix/OS2/NT GMT times (mtime, atime); next bit == UID/GID */
+    if ((xattr = (ush)((G.crec.external_file_attributes & 0xC000) >> 12)) & 8)
+    {
+        if (hostnum == UNIX_ || hostnum == FS_HPFS_ || hostnum == FS_NTFS_)
+        {
+            Info(slide, 0, ((char *)slide, LoadFarString(lExtraFieldType),
+              "is", EF_IZUNIX, LoadFarStringSmall(efIZUnix),
+              (unsigned)(xattr&12), (xattr&4)? efIZuid : efIZnouid));
+            if (*pEndprev > 0L)
+                *pEndprev += (ulg)(xattr&12);
+        }
+        else if (hostnum == FS_FAT_ && !(xattr&4))
+            Info(slide, 0, ((char *)slide, LoadFarString(lExtraFieldType),
+              "may be", EF_IZUNIX, LoadFarStringSmall(efIZUnix), 8,
+              efIZnouid));
+    }
+
+    if (!G.crec.file_comment_length)
+        Info(slide, 0, ((char *)slide, LoadFarString(NoFileComment)));
+    else {
+        Info(slide, 0, ((char *)slide, LoadFarString(FileCommBegin)));
+        if ((error = do_string(__G__ G.crec.file_comment_length, DISPL_8)) !=
+            PK_COOL)
+        {
+            error_in_archive = error;   /* might be warning */
+            if (error > PK_WARN)   /* fatal */
+                return error;
+        }
+        Info(slide, 0, ((char *)slide, LoadFarString(FileCommEnd)));
+    }
+
+    return error_in_archive;
+
+} /* end function zi_long() */
+
+
+
+
+
+/*************************/
+/*  Function zi_short()  */
+/*************************/
+
+static int zi_short(__G)   /* return PK-type error code */
+    __GDEF
+{
+#ifdef USE_EF_UT_TIME
+    iztimes     z_utime;
+    time_t      *z_modtim;
+#endif
+    int         k, error, error_in_archive=PK_COOL;
+    ush         methnum, hostnum, hostver, xattr;
+    char        *p, workspace[12], attribs[16];
+    char        methbuf[5];
+    static ZCONST char dtype[5]="NXFS"; /* normal, maximum, fast, superfast */
+    static ZCONST char Far os[NUM_HOSTS+1][4] = {
+        "fat", "ami", "vms", "unx", "cms", "atr", "hpf", "mac", "zzz",
+        "cpm", "t20", "ntf", "qds", "aco", "vft", "mvs", "be ", "nsk",
+        "???"
+    };
+    static ZCONST char Far method[NUM_METHODS+1][5] = {
+        "stor", "shrk", "re:1", "re:2", "re:3", "re:4", "i#:#", "tokn",
+        "def#", "edef", "dcli", "u###"
+    };
+
+
+/*---------------------------------------------------------------------------
+    Print out various interesting things about the compressed file.
+  ---------------------------------------------------------------------------*/
+
+    methnum = (ush)MIN(G.crec.compression_method, NUM_METHODS);
+    hostnum = (ush)(G.pInfo->hostnum);
+    hostver = G.crec.version_made_by[0];
+/*
+    extnum = MIN(G.crec.version_needed_to_extract[1], NUM_HOSTS);
+    extver = G.crec.version_needed_to_extract[0];
+ */
+
+    zfstrcpy(methbuf, method[methnum]);
+    if (methnum == IMPLODED) {
+        methbuf[1] = (char)((G.crec.general_purpose_bit_flag & 2)? '8' : '4');
+        methbuf[3] = (char)((G.crec.general_purpose_bit_flag & 4)? '3' : '2');
+    } else if (methnum == DEFLATED) {
+        ush  dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3);
+        methbuf[3] = dtype[dnum];
+    } else if (methnum >= NUM_METHODS) {   /* unknown */
+        sprintf(&methbuf[1], "%03u", G.crec.compression_method);
+    }
+
+    for (k = 0;  k < 15;  ++k)
+        attribs[k] = ' ';
+    attribs[15] = 0;
+
+    xattr = (ush)((G.crec.external_file_attributes >> 16) & 0xFFFF);
+    switch (hostnum) {
+        case VMS_:
+            {   int    i, j;
+
+                for (k = 0;  k < 12;  ++k)
+                    workspace[k] = 0;
+                if (xattr & VMS_IRUSR)
+                    workspace[0] = 'R';
+                if (xattr & VMS_IWUSR) {
+                    workspace[1] = 'W';
+                    workspace[3] = 'D';
+                }
+                if (xattr & VMS_IXUSR)
+                    workspace[2] = 'E';
+                if (xattr & VMS_IRGRP)
+                    workspace[4] = 'R';
+                if (xattr & VMS_IWGRP) {
+                    workspace[5] = 'W';
+                    workspace[7] = 'D';
+                }
+                if (xattr & VMS_IXGRP)
+                  workspace[6] = 'E';
+                if (xattr & VMS_IROTH)
+                    workspace[8] = 'R';
+                if (xattr & VMS_IWOTH) {
+                    workspace[9] = 'W';
+                    workspace[11] = 'D';
+                }
+                if (xattr & VMS_IXOTH)
+                    workspace[10] = 'E';
+
+                p = attribs;
+                for (k = j = 0;  j < 3;  ++j) {     /* groups of permissions */
+                    for (i = 0;  i < 4;  ++i, ++k)  /* perms within a group */
+                        if (workspace[k])
+                            *p++ = workspace[k];
+                    *p++ = ',';                     /* group separator */
+                }
+                *--p = ' ';   /* overwrite last comma */
+                if ((p - attribs) < 12)
+                    sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10);
+            }
+            break;
+
+        case FS_FAT_:
+        case FS_HPFS_:
+        case FS_NTFS_:
+        case VM_CMS_:
+        case FS_VFAT_:
+        case MVS_:
+        case ACORN_:
+            xattr = (ush)(G.crec.external_file_attributes & 0xFF);
+            sprintf(attribs, ".r.-...     %d.%d", hostver/10, hostver%10);
+            attribs[2] = (xattr & 0x01)? '-' : 'w';
+            attribs[5] = (xattr & 0x02)? 'h' : '-';
+            attribs[6] = (xattr & 0x04)? 's' : '-';
+            attribs[4] = (xattr & 0x20)? 'a' : '-';
+            if (xattr & 0x10) {
+                attribs[0] = 'd';
+                attribs[3] = 'x';
+            } else
+                attribs[0] = '-';
+            if (IS_VOLID(xattr))
+                attribs[0] = 'V';
+            else if ((p = strrchr(G.filename, '.')) != (char *)NULL) {
+                ++p;
+                if (STRNICMP(p, "com", 3) == 0 || STRNICMP(p, "exe", 3) == 0 ||
+                    STRNICMP(p, "btm", 3) == 0 || STRNICMP(p, "cmd", 3) == 0 ||
+                    STRNICMP(p, "bat", 3) == 0)
+                    attribs[3] = 'x';
+            }
+            break;
+
+        case AMIGA_:
+            switch (xattr & AMI_IFMT) {
+                case AMI_IFDIR:  attribs[0] = 'd';  break;
+                case AMI_IFREG:  attribs[0] = '-';  break;
+                default:         attribs[0] = '?';  break;
+            }
+            attribs[1] = (xattr & AMI_IHIDDEN)?   'h' : '-';
+            attribs[2] = (xattr & AMI_ISCRIPT)?   's' : '-';
+            attribs[3] = (xattr & AMI_IPURE)?     'p' : '-';
+            attribs[4] = (xattr & AMI_IARCHIVE)?  'a' : '-';
+            attribs[5] = (xattr & AMI_IREAD)?     'r' : '-';
+            attribs[6] = (xattr & AMI_IWRITE)?    'w' : '-';
+            attribs[7] = (xattr & AMI_IEXECUTE)?  'e' : '-';
+            attribs[8] = (xattr & AMI_IDELETE)?   'd' : '-';
+            sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10);
+            break;
+
+        default:   /* assume Unix-like */
+            switch ((unsigned)(xattr & UNX_IFMT)) {
+                case (unsigned)UNX_IFDIR:   attribs[0] = 'd';  break;
+                case (unsigned)UNX_IFREG:   attribs[0] = '-';  break;
+                case (unsigned)UNX_IFLNK:   attribs[0] = 'l';  break;
+                case (unsigned)UNX_IFBLK:   attribs[0] = 'b';  break;
+                case (unsigned)UNX_IFCHR:   attribs[0] = 'c';  break;
+                case (unsigned)UNX_IFIFO:   attribs[0] = 'p';  break;
+                case (unsigned)UNX_IFSOCK:  attribs[0] = 's';  break;
+                default:          attribs[0] = '?';  break;
+            }
+            attribs[1] = (xattr & UNX_IRUSR)? 'r' : '-';
+            attribs[4] = (xattr & UNX_IRGRP)? 'r' : '-';
+            attribs[7] = (xattr & UNX_IROTH)? 'r' : '-';
+            attribs[2] = (xattr & UNX_IWUSR)? 'w' : '-';
+            attribs[5] = (xattr & UNX_IWGRP)? 'w' : '-';
+            attribs[8] = (xattr & UNX_IWOTH)? 'w' : '-';
+
+            if (xattr & UNX_IXUSR)
+                attribs[3] = (xattr & UNX_ISUID)? 's' : 'x';
+            else
+                attribs[3] = (xattr & UNX_ISUID)? 'S' : '-';  /* S==undefined */
+            if (xattr & UNX_IXGRP)
+                attribs[6] = (xattr & UNX_ISGID)? 's' : 'x';  /* == UNX_ENFMT */
+            else
+                /* attribs[6] = (xattr & UNX_ISGID)? 'l' : '-';  real 4.3BSD */
+                attribs[6] = (xattr & UNX_ISGID)? 'S' : '-';  /* SunOS 4.1.x */
+            if (xattr & UNX_IXOTH)
+                attribs[9] = (xattr & UNX_ISVTX)? 't' : 'x';  /* "sticky bit" */
+            else
+                attribs[9] = (xattr & UNX_ISVTX)? 'T' : '-';  /* T==undefined */
+
+            sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10);
+            break;
+
+    } /* end switch (hostnum: external attributes format) */
+
+    Info(slide, 0, ((char *)slide, "%s %s %8lu ", attribs,
+      LoadFarStringSmall(os[hostnum]), G.crec.ucsize));
+    Info(slide, 0, ((char *)slide, "%c",
+      (G.crec.general_purpose_bit_flag & 1)?
+      ((G.crec.internal_file_attributes & 1)? 'T' : 'B') :  /* encrypted */
+      ((G.crec.internal_file_attributes & 1)? 't' : 'b'))); /* plaintext */
+    k = (G.crec.extra_field_length ||
+         /* a local-only "UX" (old Unix/OS2/NT GMT times "IZUNIX") e.f.? */
+         ((G.crec.external_file_attributes & 0x8000) &&
+          (hostnum == UNIX_ || hostnum == FS_HPFS_ || hostnum == FS_NTFS_)));
+    Info(slide, 0, ((char *)slide, "%c", k?
+      ((G.crec.general_purpose_bit_flag & 8)? 'X' : 'x') :  /* extra field */
+      ((G.crec.general_purpose_bit_flag & 8)? 'l' : '-'))); /* no extra field */
+      /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ extended local header or not */
+
+    if (uO.lflag == 4) {
+        ulg csiz = G.crec.csize;
+
+        if (G.crec.general_purpose_bit_flag & 1)
+            csiz -= 12;    /* if encrypted, don't count encryption header */
+        Info(slide, 0, ((char *)slide, "%3d%%",
+          (ratio(G.crec.ucsize,csiz)+5)/10));
+    } else if (uO.lflag == 5)
+        Info(slide, 0, ((char *)slide, " %8lu", G.crec.csize));
+
+    /* Read the extra field, if any.  The extra field info may be used
+     * in the file modification time section, below.
+     */
+    if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD)) != 0)
+    {
+        if (G.extra_field != NULL) {
+            free(G.extra_field);
+            G.extra_field = NULL;
+        }
+        error_in_archive = error;
+        /* We do not return prematurely in case of a "fatal" error (PK_EOF).
+         * This does not hurt here, because we do not need to read from the
+         * zipfile again before the end of this function.
+         */
+    }
+
+    /* For printing of date & time, a "char d_t_buf[16]" is required.
+     * To save stack space, we reuse the "char attribs[16]" buffer whose
+     * content is no longer needed.
+     */
+#   define d_t_buf attribs
+#ifdef USE_EF_UT_TIME
+    z_modtim = G.extra_field &&
+#ifdef IZ_CHECK_TZ
+               G.tz_is_valid &&
+#endif
+               (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,
+                                 G.crec.last_mod_dos_datetime, &z_utime, NULL)
+                & EB_UT_FL_MTIME)
+              ? &z_utime.mtime : NULL;
+    TIMET_TO_NATIVE(z_utime.mtime)     /* NOP unless MSC 7.0 or Macintosh */
+    d_t_buf[0] = (char)0;              /* signal "show local time" */
+#else
+#   define z_modtim NULL
+#endif
+    Info(slide, 0, ((char *)slide, " %s %s ", methbuf,
+      zi_time(__G__ &G.crec.last_mod_dos_datetime, z_modtim, d_t_buf)));
+    fnprint(__G);
+
+/*---------------------------------------------------------------------------
+    Skip the file comment, if any (the filename has already been printed,
+    above).  That finishes up this file entry...
+  ---------------------------------------------------------------------------*/
+
+    SKIP_(G.crec.file_comment_length)
+
+    return error_in_archive;
+
+} /* end function zi_short() */
+
+
+
+
+
+/**************************************/
+/*  Function zi_showMacTypeCreator()  */
+/**************************************/
+
+static void zi_showMacTypeCreator(__G__ ebfield)
+    __GDEF
+    uch *ebfield;
+{
+    /* not every Type / Creator character is printable */
+    if (isprint(ebfield[0]) && isprint(ebfield[1]) &&
+        isprint(ebfield[2]) && isprint(ebfield[3]) &&
+        isprint(ebfield[4]) && isprint(ebfield[5]) &&
+        isprint(ebfield[6]) && isprint(ebfield[7])) {
+       Info(slide, 0, ((char *)slide, LoadFarString(MacOSdata),
+            ebfield[0], ebfield[1], ebfield[2], ebfield[3],
+            ebfield[4], ebfield[5], ebfield[6], ebfield[7]));
+    } else {
+       Info(slide, 0, ((char *)slide, LoadFarString(MacOSdata1),
+            (((ulg)ebfield[0]) << 24) +
+            (((ulg)ebfield[1]) << 16) +
+            (((ulg)ebfield[2]) << 8)  +
+            ((ulg)ebfield[3]),
+            (((ulg)ebfield[4]) << 24) +
+            (((ulg)ebfield[5]) << 16) +
+            (((ulg)ebfield[6]) << 8)  +
+            ((ulg)ebfield[7])));
+    }
+} /* end function zi_showMacTypeCreator() */
+
+
+
+
+
+/************************/
+/*  Function zi_time()  */
+/************************/
+
+static char *zi_time(__G__ datetimez, modtimez, d_t_str)
+    __GDEF
+    ZCONST ulg *datetimez;
+    ZCONST time_t *modtimez;
+    char *d_t_str;
+{
+    unsigned yr, mo, dy, hh, mm, ss;
+    char monthbuf[4];
+    ZCONST char *monthstr;
+    static ZCONST char Far month[12][4] = {
+        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+    };
+#ifdef USE_EF_UT_TIME
+    struct tm *t;
+#endif
+
+
+
+/*---------------------------------------------------------------------------
+    Convert the file-modification date and time info to a string of the form
+    "1991 Feb 23 17:15:00", "23-Feb-91 17:15" or "19910223.171500", depending
+    on values of lflag and T_flag.  If using Unix-time extra fields, convert
+    to local time or not, depending on value of first character in d_t_str[].
+  ---------------------------------------------------------------------------*/
+
+#ifdef USE_EF_UT_TIME
+    if (modtimez != NULL) {
+#ifndef NO_GMTIME
+        /* check for our secret message from above... */
+        t = (d_t_str[0] == (char)1)? gmtime(modtimez) : localtime(modtimez);
+#else
+        t = localtime(modtimez);
+#endif
+        if (uO.lflag > 9 && t == (struct tm *)NULL)
+            /* time conversion error in verbose listing format,
+             * return string with '?' instead of data
+             */
+            return (strcpy(d_t_str, LoadFarString(YMDHMSTimeError)));
+    } else
+        t = (struct tm *)NULL;
+    if (t != (struct tm *)NULL) {
+        mo = (unsigned)(t->tm_mon + 1);
+        dy = (unsigned)(t->tm_mday);
+        yr = (unsigned)(t->tm_year);
+
+        hh = (unsigned)(t->tm_hour);
+        mm = (unsigned)(t->tm_min);
+        ss = (unsigned)(t->tm_sec);
+    } else
+#endif /* USE_EF_UT_TIME */
+    {
+        yr = ((unsigned)(*datetimez >> 25) & 0x7f) + 80;
+        mo = ((unsigned)(*datetimez >> 21) & 0x0f);
+        dy = ((unsigned)(*datetimez >> 16) & 0x1f);
+
+        hh = (((unsigned)*datetimez >> 11) & 0x1f);
+        mm = (((unsigned)*datetimez >> 5) & 0x3f);
+        ss = (((unsigned)*datetimez << 1) & 0x3e);
+    }
+
+    if (mo == 0 || mo > 12) {
+        sprintf(monthbuf, LoadFarString(BogusFmt), mo);
+        monthstr = monthbuf;
+    } else
+        monthstr = LoadFarStringSmall(month[mo-1]);
+
+    if (uO.lflag > 9)   /* verbose listing format */
+        sprintf(d_t_str, LoadFarString(YMDHMSTime), yr+1900, monthstr, dy, hh,
+          mm, ss);
+    else if (uO.T_flag)
+        sprintf(d_t_str, LoadFarString(DecimalTime), yr+1900, mo, dy, hh, mm,
+          ss);
+    else   /* was:  if ((uO.lflag >= 3) && (uO.lflag <= 5)) */
+        sprintf(d_t_str, LoadFarString(DMYHMTime), dy, monthstr, yr%100, hh,
+          mm);
+
+    return d_t_str;
+
+} /* end function zi_time() */
+
+#endif /* !NO_ZIPINFO */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uninst/Makefile.in	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,30 @@
+# Installer Makefile
+
+CC = @CC@
+RM = @RM@ -f
+
+
+DEFS =
+LIBS = @LIBS@
+
+CFLAGS = -I.. -D__UNIX__ @CFLAGS@
+LDFLAGS = 
+
+OBJECTS = uninst.o dw.o
+
+SOURCES = uninst.c ../gtk/dw.c
+
+all: uninst
+
+$(OBJECTS):
+	$(CC) $(CFLAGS) -c $<	
+
+uninst:  $(OBJECTS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $(DEFS) -o uninst $(OBJECTS) $(LIBS)
+
+clean: 
+	$(RM) $(OBJECTS) install uninst *~
+
+uninst.o: uninst.c
+dw.o: ../gtk/dw.c
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uninst/dbuninst.def	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,3 @@
+NAME DBUNINST WINDOWAPI
+DESCRIPTION "Uninstaller (C) 2002 Brian Smith"
+STACKSIZE 51200
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uninst/makefile.vac	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,37 @@
+# Installer Makefile
+
+.SUFFIXES: \
+	.c .obj
+
+#CFLAGS = /Ss /Gm+ /I..\incace /I.. /Ti /C
+CFLAGS = /Ti /I..\incace /I.. /DOS2 /DTCPV40HDRS /DENABLE_LOGGING /Sm /Ss /Q /Gm /Gt /C
+LDFLAGS = /de /optfunc
+
+
+OBJECTS = uninst.obj
+
+SOURCES = uninst.c
+
+all: dbuninst.exe
+
+$(OBJECTS):
+	icc $(CFLAGS) %s
+
+dw.obj:
+	icc $(CFLAGS) ..\os2\dw.c
+
+dbuninst.exe:  $(OBJECTS) dw.obj
+	rc -r -i .. ..\sfxos2.rc
+	icc @<<
+	 /B" $(LDFLAGS)"
+	 /Fedbuninst.exe
+	 rexx.lib
+	 $(OBJECTS) dw.obj
+	 dbuninst.def
+<<
+	rc -x2 ..\sfxos2.res dbuninst.exe
+#	lxlite sfxos2.exe
+
+clean: 
+	rm -f $(OBJECTS) *.obj dbuninst.exe dbuninst.exe
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uninst/makefile.vc	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,51 @@
+#
+WXDIR = $(WXWIN)
+CC = cl
+CFLAGS = -c -G5 -GD -Zp1 -DWIN32 -D__WIN32__ -DMSVC -DENABLE_LOGGING -I. -I.. -I..\incace
+CFLAGS_DEBUG = -Zi
+CFLAGS_COMPILE = -MT
+LIBS = wsock32.lib kernel32.lib user32.lib comctl32.lib gdi32.lib advapi32.lib shell32.lib comdlg32.lib ole32.lib rexx.lib
+
+RES = 
+LINKFLAGS = -machine:i386 -debug:full -debugtype:cv
+DLLLINKFLAGS = -dll
+LINK = link
+
+OBJS = 	uninst.obj \
+        ..\win\dw.obj
+                
+LINKOBJS = 	uninst.obj \
+                dw.obj
+                
+all: dbuninst.exe
+
+clean:
+	-erase *.dll
+        -erase *.exe
+        -erase *.opt
+        -erase *.lib
+        -erase *.obj
+        -erase *.map
+        -erase *.pdb
+        -erase *.ilk
+        -erase *.exp
+        -erase *.res
+        -erase *~
+        
+dbuninst.exe: $(OBJS) sfxwin.res
+	$(LINK) @<<
+-out:$(@) -subsystem:windows -entry:WinMainCRTStartup
+$(LINKFLAGS)
+$(LINKOBJS)
+$(LIBS)
+..\sfxwin.res
+<<
+
+sfxwin.res: ..\sfxwin.rc
+	rc -r -i.. ..\sfxwin.rc
+        
+.c.obj:
+	$(CC) $(CFLAGS) $(CFLAGS_DEBUG) $(CFLAGS_COMPILE) $*.c
+        
+.cpp.obj:
+	$(CC) $(CFLAGS) $(CFLAGS_DEBUG) $(CFLAGS_COMPILE) $*.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uninst/uninst.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,788 @@
+/* $Id: uninst.c,v 1.24 2003/05/10 09:18:10 bsmith Exp $ */
+
+/*
+ *  uninst.c (c) 2002-2003 Brian Smith
+ */
+
+#ifdef __UNIX__
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#ifndef __UNIX__
+#include <process.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "dw.h"
+#include "compat.h"
+
+#include <string.h>
+#ifndef __UNIX__
+#define strcasecmp stricmp
+#endif
+
+#ifdef __OS2__
+#include <direct.h>
+#include <ctype.h>
+#endif
+
+/* I know I am being excessive but... better safe than sorry ;) */
+char *configsys[8196];
+int configfilecount=-1;
+
+/* Config.Sys -- Note the drive letter gets replaced with the boot drive letter
+                 It is just a place holder. (For the next 3 entries)             */
+char csfile[] = "C:\\CONFIG.SYS";
+/* Backup Config.Sys filename */
+char bufile[] = "C:\\CONFIG.NST";
+/* Installation Log Database -- Used for uninstallation and aborting */
+#ifdef __WIN32__
+char instlog[MAX_PATH+1] = "C:\\DBINST.LOG";
+#elif defined(__OS2__)
+char instlog[] = "C:\\OS2\\INSTALL\\DBINST.LOG";
+#else
+char instlog[] = "/var/log/dbinst";
+#endif
+char installdir[_MAX_PATH];
+
+char bootdrive[2] = "C";
+char empty_string[] = "";
+char currentcf[_MAX_PATH] = "";
+
+char *INSTALLER_APPLICATION, *INSTALLER_VERSION;
+HWND mainwindow, mainbox, slider, stext, bigbox, logo, custombox, groupbox, buttonbox, status, exitbutton, nextbutton, blanktext;
+
+#ifdef __OS2__
+#define UNINSTALL_SCRIPT "uninstal.cmd"
+#elif defined(__WIN32__)
+#define UNINSTALL_SCRIPT "uninstal.bat"
+#else
+#define UNINSTALL_SCRIPT "Uninstall.sh"
+#endif
+
+/* Undocumented functions */
+#if defined(__OS2__) || defined(__EMX__)
+APIRET APIENTRY DosReplaceModule(PSZ pszOldModule,PSZ pszNewModule,PSZ pszBackupModule);
+#endif
+/*
+ * Removes a folder on the desktop.
+ */
+void RemoveFolder(char Title[], char *Icon, char *dest, char *id, char *setup, char *platform)
+{
+#ifdef __OS2__
+	if(id)
+	{
+		HOBJECT ho = WinQueryObject(id);
+
+		if(ho != NULLHANDLE)
+			WinDestroyObject(ho);
+	}
+#elif defined(__WIN32__)
+	if(platform && *platform)
+	{
+		int res;
+
+		res = rmdir(platform);
+		if(res == -1)
+			MoveFileEx(platform, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
+	}
+#else
+	/* Unix? */
+#endif
+}
+
+/*
+ * Makes a Program object on the desktop.
+ */
+void RemoveProgram(char *Title, char *Program, char *Icon, char *dest, char *id, char *setup, char *platform)
+{
+#ifdef __OS2__
+	if(id)
+	{
+		HOBJECT ho = WinQueryObject(id);
+
+		if(ho != NULLHANDLE)
+			WinDestroyObject(ho);
+	}
+#elif defined(__WIN32__)
+	if(platform && *platform)
+	{
+		int res;
+
+		res = remove(platform);
+		if(res == -1)
+			MoveFileEx(platform, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
+	}
+#else
+	/* Unix? */
+#endif
+}
+/*
+ * Makes a user defined object on the desktop.
+ */
+void RemoveObject(char *Title, char *oclass, char *dest, char *id, char *setup, char *platform)
+{
+#ifdef __OS2__
+	if(id)
+	{
+		HOBJECT ho = WinQueryObject(id);
+
+		if(ho != NULLHANDLE)
+			WinDestroyObject(ho);
+	}
+#elif defined(WIN32)
+    /* Not sure if there is an equivilent on Windows */
+#else
+	/* Unix? */
+#endif
+}
+
+/*
+ * Makes a shadow on the desktop.
+ */
+void RemoveShadow(char *Title, char *reference, char *dest, char *id, char *platform)
+{
+#ifdef __OS2__
+	if(id)
+	{
+		HOBJECT ho = WinQueryObject(id);
+
+		if(ho != NULLHANDLE)
+			WinDestroyObject(ho);
+	}
+#elif defined(WIN32)
+	if(platform && *platform)
+	{
+		int res;
+
+		res = remove(platform);
+		if(res == -1)
+			MoveFileEx(platform, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
+	}
+#else
+	/* Unix? */
+#endif
+}
+
+void update_percent(int current, int total)
+{
+	static int pixels = 0;
+	ULONG sliderpos = 0;
+
+	if(total && (pixels = dw_percent_query_range(slider)))
+	{
+		sliderpos = (int)(((float)current/(float)total)*pixels);
+		dw_percent_set_pos(slider, sliderpos);
+	}
+}
+
+/*
+ * Read the generated log file and anything installed.
+ */
+void do_uninstall(void)
+{
+	char tmpbuf[8196], *fileptr, **lines;
+	FILE *tmplf;
+	int linenum=0, found=-1, theend = 0, count = 0, z;
+
+	if((tmplf=fopen(instlog, "rb"))==NULL)
+	{
+		dw_messagebox("Uninstall", DW_MB_OK | DW_MB_ERROR, "Could not open install log.");
+		return;
+	}
+
+	while(!feof(tmplf))
+	{
+		fgets(tmpbuf, 8196, tmplf);
+		linenum++;
+		if(tmpbuf[0]=='[' && (char *)strstr(tmpbuf, INSTALLER_APPLICATION) != NULL && !feof(tmplf))
+		{
+			fgets(tmpbuf, 8196, tmplf);
+			linenum++;
+			if((char *)strstr(tmpbuf, "<Version>") != NULL && (char *)strstr(tmpbuf, INSTALLER_VERSION) != NULL)
+			{
+				found=linenum;
+				theend = 0;
+			}
+		}
+		if(found != -1 && !theend && ((char *)strstr(tmpbuf, "<End>") != NULL || tmpbuf[0] == '['))
+			theend=linenum;
+	}
+	if(found != -1)
+	{
+		if(!theend)
+			theend = linenum;
+
+		if(theend - found > 0)
+			lines = calloc(theend - found, sizeof(char *));
+		else
+			lines = calloc(8096, sizeof(char *));
+
+		rewind(tmplf);
+		for (z=0;z<found;z++)
+			fgets(tmpbuf, 8196, tmplf);
+		while(!feof(tmplf) && count < (theend - found))
+		{
+			tmpbuf[0] = 0;
+			fgets(tmpbuf, 8196, tmplf);
+			lines[count] = strdup(tmpbuf);
+			count++;
+
+		}
+		fclose(tmplf);
+
+		/* The first NewDir should be the installation directory */
+		for(z=0;z<count;z++)
+		{
+			if(lines[z])
+			{
+				int res;
+
+				fileptr = lines[z];
+
+				/* Remove trailing CRLFs */
+				if(fileptr[strlen(fileptr)-1] == '\r' || fileptr[strlen(fileptr)-1] == '\n')
+					fileptr[strlen(fileptr)-1]=0;
+				if(fileptr[strlen(fileptr)-1] == '\r' || fileptr[strlen(fileptr)-1] == '\n')
+					fileptr[strlen(fileptr)-1]=0;
+
+				if((char *)strstr(lines[z], "<NewDir>") != NULL)
+				{
+					char path[_MAX_PATH];
+					struct stat sb;
+
+					fileptr = (char *)strchr(lines[z], ',')+1;
+#ifndef __UNIX__
+					if(fileptr[1] == ':')
+					{
+						char drive = toupper(fileptr[0]);
+						_chdrive((drive - 'A')+1);
+					}
+#endif
+					chdir(fileptr);
+
+#ifdef __UNIX__
+					sprintf(path, "%s/%s", fileptr, UNINSTALL_SCRIPT);
+#else
+					sprintf(path, "%s\\%s", fileptr, UNINSTALL_SCRIPT);
+#endif
+					if(!stat(path, &sb))
+						system(path);
+
+					z = count;
+				}
+			}
+		}
+
+		for(z=count-1;z>-1;z--)
+		{
+			if(lines[z])
+			{
+				int res;
+
+				fileptr = lines[z];
+
+				/* Remove trailing CRLFs */
+				if(fileptr[strlen(fileptr)-1] == '\r' || fileptr[strlen(fileptr)-1] == '\n')
+					fileptr[strlen(fileptr)-1]=0;
+				if(fileptr[strlen(fileptr)-1] == '\r' || fileptr[strlen(fileptr)-1] == '\n')
+					fileptr[strlen(fileptr)-1]=0;
+
+				if((char *)strstr(lines[z], "<FileInst>") != NULL)
+				{
+					fileptr = (char *)strchr(lines[z], ',')+1;
+#ifdef __OS2__
+					DosReplaceModule(fileptr,NULL,NULL);
+#endif
+					res = remove(fileptr);
+#ifdef __WIN32__
+					if(res == -1)
+						MoveFileEx(fileptr, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
+#endif
+				}
+				if((char *)strstr(lines[z], "<NewDir>") != NULL)
+				{
+					fileptr = (char *)strchr(lines[z], ',')+1;
+					res = rmdir(fileptr);
+#ifdef __WIN32__
+					if(res == -1)
+						MoveFileEx(fileptr, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
+#endif
+				}
+				if((char *)strstr(lines[z], "<WPSFolderAdd>") != NULL)
+				{
+					char *args[6], *ptr = lines[z];
+					int x;
+
+					for(x=0;x<6;x++)
+					{
+						if(ptr)
+							ptr = strstr(ptr, ",");
+						if(ptr)
+						{
+							ptr[0] = 0;
+							ptr = args[x] = &ptr[1];
+						}
+						else
+							args[x] = NULL;
+					}
+					RemoveFolder(args[0],args[1],args[2],args[3],args[4],args[5]);
+				}
+				if((char *)strstr(lines[z], "<WPSProgramAdd>") != NULL)
+				{
+					char *args[7], *ptr = lines[z];
+					int x;
+
+					for(x=0;x<7;x++)
+					{
+						if(ptr)
+							ptr = strstr(ptr, ",");
+						if(ptr)
+						{
+							ptr[0] = 0;
+							ptr = args[x] = &ptr[1];
+						}
+						else
+							args[x] = NULL;
+					}
+					RemoveProgram(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
+				}
+				if((char *)strstr(lines[z], "<WPSObjectAdd>") != NULL)
+				{
+					char *args[6], *ptr = lines[z];
+					int x;
+
+					for(x=0;x<6;x++)
+					{
+						if(ptr)
+							ptr = strstr(ptr, ",");
+						if(ptr)
+						{
+							ptr[0] = 0;
+							ptr = args[x] = &ptr[1];
+						}
+						else
+							args[x] = NULL;
+					}
+					RemoveObject(args[0],args[1],args[2],args[3],args[4],args[5]);
+				}
+				if((char *)strstr(lines[z], "<WPSShadowAdd>") != NULL)
+				{
+					char *args[5], *ptr = lines[z];
+					int x;
+
+					for(x=0;x<5;x++)
+					{
+						if(ptr)
+							ptr = strstr(ptr, ",");
+						if(ptr)
+						{
+							ptr[0] = 0;
+							ptr = args[x] = &ptr[1];
+						}
+						else
+							args[x] = NULL;
+					}
+					RemoveShadow(args[0],args[1],args[2],args[3],args[4]);
+				}
+				free(lines[z]);
+				update_percent(count-z, count);
+			}
+		}
+		free(lines);
+		return;
+	}
+	else
+		dw_messagebox("Uninstall", DW_MB_OK | DW_MB_ERROR, "Could not find section in install log.");
+	fclose(tmplf);
+	return;
+}
+
+/*
+ * Removes any carriage returns or line feeds from the buffer.
+ */
+void stripcrlf(char *buffer)
+{
+	int z, len = strlen(buffer);
+
+	for(z=0;z<len;z++)
+	{
+		if(buffer[z] == '\r' || buffer[z] == '\n')
+		{
+			buffer[z] = 0;
+			return;
+		}
+	}
+}
+
+/*
+ * Adds or replaces a SET variable based on the flags (CONFIG.SYS)
+ */
+#if 0
+void updateset(char *setname, char *newvalue, int flag)
+{
+	char *cmpbuf1, *cmpbuf2, *tmpptr, *tmpptr2, *nv;
+	int i, z, t;
+
+    nv=replaceem(newvalue);
+
+	cmpbuf1=malloc(strlen(setname)+2);
+	strcpy(cmpbuf1, setname);
+	strcat(cmpbuf1, "=");
+	for(i=0;i<configfilecount;i++)
+	{
+		if(strlen(cmpbuf1) <= strlen(configsys[i]))
+		{
+			tmpptr=(char *)strdup(configsys[i]);
+			strupr(tmpptr);
+			if((tmpptr2=(char*)strstr(tmpptr, "SET "))!=NULL)
+			{
+				tmpptr2 += 4;
+				cmpbuf2=malloc(strlen(tmpptr2)+1);
+				/* Remove any spaces from the string */
+				z=0;
+				for (t=0;t<strlen(tmpptr2) && z < strlen(cmpbuf1);t++)
+				{
+					if(tmpptr2[t] != ' ')
+					{
+						cmpbuf2[z]=tmpptr2[t];
+						z++;
+					}
+				}
+				cmpbuf2[z]=0;
+				if(strcasecmp(cmpbuf1, cmpbuf2) == 0)
+				{
+					/* Ok we found the entry, and if UPDATE_ALWAYS change it to the
+					 new entry, otherwise exit */
+					if(flag == UPDATE_ALWAYS)
+					{
+						free(configsys[i]);
+						configsys[i] = malloc(strlen(setname)+strlen(nv)+6);
+                        strcpy(configsys[i], "SET ");
+						strcat(configsys[i], setname);
+                        strcat(configsys[i], "=");
+						strcat(configsys[i], nv);
+						free(cmpbuf1);free(cmpbuf2);free(tmpptr);
+					}
+					return;
+				}
+				free(cmpbuf2);
+			}
+			free(tmpptr);
+		}
+	}
+	/* Couldn't find the line so we'll add it */
+	configsys[configfilecount]=malloc(strlen(cmpbuf1)+strlen(nv)+6);
+	strcpy(configsys[configfilecount], "SET ");
+	strcat(configsys[configfilecount], setname);
+	strcat(configsys[configfilecount], "=");
+	strcat(configsys[configfilecount], nv);
+	configfilecount++;
+	free(cmpbuf1);
+    free(nv);
+}     
+
+/*
+ * Adds an entry to a system variable (CONFIG.SYS)
+ */
+void updatesys(char *sysname, char *newvalue)
+{
+	char *cmpbuf1, *cmpbuf2, *tmpptr, *tmpptr2, *capbuf1, *capbuf2, *nv, *brian;
+	int i, z, t;
+
+	nv=replaceem(newvalue);
+
+	cmpbuf1=malloc(strlen(sysname)+2);
+	strcpy(cmpbuf1, sysname);
+	strcat(cmpbuf1, "=");
+	for(i=0;i<configfilecount;i++)
+	{
+		if(strlen(cmpbuf1) <= strlen(configsys[i]))
+		{
+			cmpbuf2=malloc(strlen(configsys[i])+1);
+			/* Remove any spaces from the string */
+			z=0;
+			for (t=0;t<strlen(configsys[i]) && z < strlen(cmpbuf1);t++)
+			{
+				if(configsys[i][t] != ' ')
+				{
+					cmpbuf2[z]=configsys[i][t];
+					z++;
+				}
+			}
+			cmpbuf2[z]=0;
+			if(strcasecmp(cmpbuf1, cmpbuf2) == 0)
+			{
+				/* Do a case insensitive comparison but preserve the case */
+				tmpptr = &configsys[i][t];
+				capbuf1=malloc(strlen(tmpptr)+1);
+				capbuf2=malloc(strlen(nv)+1);
+				strcpy(capbuf1, tmpptr);
+				strcpy(capbuf2, nv);
+				strupr(capbuf1);
+				strupr(capbuf2);
+				/* Ok, we found the line, and it doesn't have an entry so we'll add it */
+				if((tmpptr2=(char *)strstr(capbuf1, capbuf2)) == NULL)
+				{
+					brian = configsys[i];
+					configsys[i] = malloc(strlen(configsys[i])+strlen(nv)+4);
+					strcpy(configsys[i], brian);
+					free(brian);
+					/* Remove any trailing CRLFs */
+					if(configsys[i][strlen(configsys[i])-1]!=';')
+						strcat(configsys[i], ";");
+					strcat(configsys[i], nv);
+					strcat(configsys[i], ";");
+				}
+				free(cmpbuf1);free(cmpbuf2);free(capbuf1);free(capbuf2);
+				return;
+			}
+			free(cmpbuf2);
+		}
+	}
+	/* Couldn't find the line so we'll add it */
+	configsys[configfilecount]=malloc(strlen(cmpbuf1)+strlen(nv)+3);
+	strcpy(configsys[configfilecount], cmpbuf1);
+	strcat(configsys[configfilecount], nv);
+	strcat(configsys[configfilecount], ";");
+	configfilecount++;
+	free(cmpbuf1);
+	free(nv);
+}
+#endif
+
+/*
+ * Removes a line from a config file.
+ */
+void removeline(char *text)
+{
+	int z;
+	for(z=0;z<configfilecount;z++)
+	{
+		if(strcasecmp(configsys[z], text) == 0)
+		{
+			int t;
+
+			free(configsys[z]);
+			for(t=z;t<(configfilecount-1);t++)
+				configsys[t] = configsys[t+1];
+			configfilecount--;
+		}
+	}
+}
+
+
+/*
+ * Reads a line from a file and returns it in raw.
+ */
+void getline(FILE *f, char *raw)
+{
+	memset(raw, 0, 256);
+	fgets(raw, 255, f);
+    stripcrlf(raw);
+}
+
+/*
+ * Removes a character from a buffer by advancing the buffer to the left.
+ */
+void removechar(char *buffer, int thisone, int len)
+{
+	int x;
+
+	for(x=thisone;x<len;x++)
+        buffer[x] = buffer[x+1];
+}
+
+void getbootdrive(void)
+{
+#ifdef __OS2__
+	ULONG   ulSysInfo;
+
+	DosQuerySysInfo(QSV_BOOT_DRIVE,
+			QSV_BOOT_DRIVE,
+			(PVOID)&ulSysInfo,
+			sizeof(ULONG));
+
+	bootdrive[0]=installdir[0]=instlog[0]=csfile[0]=bufile[0]=(char)('A'+(ulSysInfo-1));
+#elif defined(__WIN32__)
+	char winpath[MAX_PATH+1] = "";
+
+	GetWindowsDirectory(winpath, MAX_PATH);
+
+	if(winpath[0] && winpath[1] == ':')
+	{
+		bootdrive[0]=installdir[0]=csfile[0]=bufile[0]=winpath[0];
+		strcpy(instlog, winpath);
+		if(instlog[strlen(instlog)-1] != '\\')
+			strcat(instlog, "\\");
+		strcat(instlog, "DBINST.LOG");
+	}
+#endif
+}
+
+void remove_uninstall_object(void)
+{
+#ifdef __OS2__
+	char binpath[8096], *objectid = strdup(INSTALLER_APPLICATION);
+	HOBJECT ho;
+	int z;
+
+	for(z=0;z<strlen(objectid);z++)
+	{
+		if(objectid[z] == ' ')
+			objectid[z] = '_';
+	}
+
+	sprintf(binpath, "<DBUNINST_%s>", objectid);
+	ho = WinQueryObject(binpath);
+	if(ho != NULLHANDLE)
+		WinDestroyObject(ho);
+	free(objectid);
+#elif defined( __WIN32__)
+	char keyname[1024];
+
+	sprintf(keyname, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s", INSTALLER_APPLICATION);
+	if(RegDeleteKey(HKEY_LOCAL_MACHINE, keyname))
+		return;
+#endif
+}
+
+void actual_install(void *data)
+{
+	getbootdrive();
+
+	do_uninstall();
+
+	remove_uninstall_object();
+
+	dw_messagebox("Uninstall", DW_MB_OK | DW_MB_INFORMATION, "Finished uninstalling.");
+
+	dw_window_destroy(mainwindow);
+
+	exit(0);
+}
+
+void DWSIGNAL start_callback(HWND window, void *data)
+{
+	dw_window_disable(exitbutton);
+	dw_window_disable(nextbutton);
+
+	dw_thread_new((void *)actual_install, NULL, 10000);
+}
+
+void DWSIGNAL exit_callback(HWND window, void *data)
+{
+	dw_window_destroy(mainwindow);
+
+	exit(0);
+}
+
+void uninstall_dialog(void)
+{
+	ULONG flStyle = DW_FCF_SYSMENU | DW_FCF_TITLEBAR | DW_FCF_SHELLPOSITION | DW_FCF_TASKLIST | DW_FCF_DLGBORDER;
+	char text[1024];
+
+	mainwindow = dw_window_new(HWND_DESKTOP, "Uninstall", flStyle);
+
+	/* This number must corespond to a resource ID in the bound resources */
+	dw_window_set_icon(mainwindow, 2000);
+
+	bigbox = dw_box_new(BOXVERT, 10);
+
+	dw_box_pack_start(mainwindow, bigbox, 0, 0, TRUE, TRUE, 0);
+
+	mainbox = dw_box_new(BOXHORZ, 0);
+
+	dw_box_pack_start(bigbox, mainbox, 0, 0, TRUE, TRUE, 0);
+
+	logo = dw_bitmap_new(1001);
+
+	/* This number must corespond to a resource ID in the bound resources */
+	dw_window_set_bitmap(logo, 2001, NULL);
+
+	dw_box_pack_start(mainbox, logo, 100, 275, FALSE, FALSE, 10);
+
+	custombox = dw_box_new(BOXVERT, 0);
+
+	dw_box_pack_start(mainbox, custombox, 0, 0, TRUE, TRUE, 0);
+
+	sprintf(text, "Ready to Uninstall %s %s", INSTALLER_APPLICATION, INSTALLER_VERSION);
+	stext = dw_text_new(text, 0);
+
+	dw_window_set_style(stext, DW_DT_VCENTER, DW_DT_VCENTER);
+
+	dw_box_pack_start(custombox, stext, 300, 50, TRUE, TRUE, 10);
+
+	groupbox = dw_groupbox_new(BOXHORZ, 10, "Progress");
+
+	dw_box_pack_start(custombox, groupbox, 0, 0, TRUE, FALSE, 10);
+
+	slider = dw_percent_new(1010);
+
+	dw_box_pack_start(groupbox, slider, 300, 20, TRUE, FALSE, 10);
+
+	status = dw_text_new("", 0);
+
+	dw_box_pack_start(custombox, status, 300, 50, TRUE, TRUE, 10);
+
+	dw_box_pack_start(custombox, 0, 300, 100, TRUE, TRUE, 10);
+
+	buttonbox = dw_box_new(BOXHORZ, 5);
+
+	dw_box_pack_start(bigbox, buttonbox, 0, 0, TRUE, FALSE, 0);
+
+	exitbutton = dw_button_new("Exit Uninstall", 1003);
+
+	dw_box_pack_start(buttonbox, exitbutton, 100, 30, TRUE, FALSE, 0);
+
+	blanktext = dw_text_new("", 0);
+
+	dw_box_pack_start(buttonbox, blanktext, 150, 30, TRUE, FALSE, 0);
+
+	nextbutton = dw_button_new("Begin >>", 1001);
+
+	dw_box_pack_start(buttonbox, nextbutton, 60, 30, TRUE, FALSE, 0);
+
+	/* Set some nice fonts and colors */
+#ifdef __OS2__
+	dw_window_set_font(stext, "9.WarpSans Bold");
+#elif defined(__WIN32__)
+	dw_window_set_font(stext, "14.Arial Bold");
+#endif
+
+	dw_signal_connect(exitbutton, "clicked", DW_SIGNAL_FUNC(exit_callback), NULL);
+	dw_signal_connect(nextbutton, "clicked", DW_SIGNAL_FUNC(start_callback), NULL);
+
+	dw_window_set_pos_size(mainwindow, (dw_screen_width()-550)/2, (dw_screen_height()-375)/2, 550, 375);
+	dw_window_show(mainwindow);
+}
+
+/*
+ * Main function
+ */
+int main(int argc, char *argv[])
+{
+	dw_init(TRUE, argc, argv);
+
+	if(argc > 2)
+	{
+		INSTALLER_APPLICATION = argv[1];
+		INSTALLER_VERSION = argv[2];
+	}
+	else
+	{
+		dw_messagebox("Uninstall", DW_MB_OK | DW_MB_ERROR, "Error in uninstaller.");
+		return 0;
+	}
+
+	uninstall_dialog();
+
+	dw_main();
+
+	return 0;
+}
Binary file win/bitmaps/file.ico has changed
Binary file win/bitmaps/folder.ico has changed
Binary file win/bitmaps/install.bmp has changed
Binary file win/bitmaps/install.ico has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/win/dirent.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,226 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <windows.h>
+
+#include "dirent.h"
+#include <errno.h>
+
+#define error(rc) errno = 255
+
+struct _dirdescr {
+	HANDLE		handle;		/* DosFindFirst handle */
+	char		fstype;		/* filesystem type */
+	long		count;		/* valid entries in <ffbuf> */
+	long		number;		/* absolute number of next entry */
+	int		index;		/* relative number of next entry */
+	char		name[MAXPATHLEN+3]; /* directory name */
+	unsigned	attrmask;	/* attribute mask for seekdir */
+	struct dirent	entry;		/* buffer for directory entry */
+	WIN32_FIND_DATA data;
+};
+
+/*
+ * Return first char of filesystem type, or 0 if unknown.
+ */
+static char
+getFSType(const char *path)
+{
+	static char cache[1+26];
+	char drive[3];
+	ULONG unit;
+	char r;
+
+	if (isalpha(path[0]) && path[1] == ':') {
+		unit = toupper(path[0]) - '@';
+		path += 2;
+	} else {
+		return 0;
+	}
+
+	if ((path[0] == '\\' || path[0] == '/')
+	 && (path[1] == '\\' || path[1] == '/'))
+		return 0;
+
+	if (cache [unit])
+		return cache [unit];
+
+	drive[0] = '@' + unit;
+	drive[1] = ':';
+	drive[2] = '\0';
+
+	r = GetDriveType(drive);
+
+	return cache [unit] = r;
+}
+
+char *
+abs_path(const char *name, char *buffer, int len)
+{
+	char buf[4];
+	if (isalpha(name[0]) && name[1] == ':' && name[2] == '\0') {
+		buf[0] = name[0];
+		buf[1] = name[1];
+		buf[2] = '.';
+		buf[3] = '\0';
+		name = buf;
+	}
+	if (GetLongPathName(name, buffer, len))
+		return NULL;
+	return buffer;
+}
+
+DIR *
+openxdir(const char *path, unsigned att_mask)
+{
+	DIR *dir;
+	char name[MAXPATHLEN+3];
+
+	dir = malloc(sizeof(DIR));
+	if (dir == NULL) {
+		errno = ENOMEM;
+		return NULL;
+	}
+
+	strncpy(name, path, MAXPATHLEN);
+	name[MAXPATHLEN] = '\0';
+	switch (name[strlen(name)-1]) {
+	default:
+		strcat(name, "\\");
+	case '\\':
+	case '/':
+	case ':':
+		;
+	}
+	strcat(name, ".");
+	if (!abs_path(name, dir->name, MAXPATHLEN+1))
+		strcpy(dir->name, name);
+	if (dir->name[strlen(dir->name)-1] == '\\')
+		strcat(dir->name, "*");
+	else
+		strcat(dir->name, "\\*");
+
+	dir->fstype = getFSType(dir->name);
+	dir->attrmask = att_mask | A_DIR;
+
+	dir->count = 100;
+	if((dir->handle = FindFirstFile(dir->name, &dir->data))==INVALID_HANDLE_VALUE)
+	{
+		free(dir);
+		error(rc);
+		return NULL;
+	}
+
+	dir->number = 0;
+	dir->index = 0;
+
+	return (DIR *)dir;
+}
+
+DIR *
+opendir(const char *pathname)
+{
+	return openxdir(pathname, 0);
+}
+
+struct dirent *
+readdir(DIR *dir)
+{
+	static int dummy_ino = 2;
+
+	if (dir->number)
+	{
+		ULONG rc;
+		dir->count = 100;
+		if(!FindNextFile(dir->handle, &(dir->data)))
+		{
+			error(rc);
+			return NULL;
+		}
+
+		dir->index = 0;
+	}
+
+	strcpy(dir->entry.d_name, dir->data.cFileName);
+	dir->entry.d_ino = dummy_ino++;
+	dir->entry.d_reclen = strlen(dir->data.cFileName);
+	dir->entry.d_namlen = strlen(dir->data.cFileName);
+	dir->entry.d_size = dir->data.nFileSizeLow;
+	dir->entry.d_attribute = dir->data.dwFileAttributes;
+#if 0
+	dir->entry.d_time = *(USHORT *)&dir->next->ftimeLastWrite;
+	dir->entry.d_date = *(USHORT *)&dir->next->fdateLastWrite;
+#endif
+
+	dir->number++;
+	dir->index++;
+	return &dir->entry;
+}
+
+long
+telldir(DIR *dir)
+{
+	return dir->number;
+}
+
+void
+seekdir(DIR *dir, long off)
+{
+	if (dir->number > off) {
+		char name[MAXPATHLEN+2];
+		ULONG rc;
+
+		FindClose(dir->handle);
+
+		strcpy(name, dir->name);
+		strcat(name, "*");
+
+		if((dir->handle = FindFirstFile(name, &(dir->data)))==NULL)
+		{
+			error(rc);
+			return;
+		}
+
+		dir->number = 0;
+		dir->index = 0;
+	}
+
+	while (dir->number < off && readdir(dir))
+		;
+}
+
+void
+closedir(DIR *dir)
+{
+	FindClose(dir->handle);
+	free(dir);
+}
+
+/*****************************************************************************/
+
+#ifdef TEST
+
+main(int argc, char **argv)
+{
+	int i;
+	DIR *dir;
+	struct dirent *ep;
+
+	for (i = 1; i < argc; ++i) {
+		dir = opendir(argv[i]);
+		if (!dir)
+			continue;
+		while (ep = readdir(dir))
+			if (strchr("\\/:", argv[i] [strlen(argv[i]) - 1]))
+				printf("%s%s\n", argv[i], ep->d_name);
+			else
+				printf("%s/%s\n", argv[i], ep->d_name);
+		closedir(dir);
+	}
+
+	return 0;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/win/dw.c	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,8516 @@
+/*
+/*
+ * Dynamic Windows:
+ *          A GTK like implementation of the Win32 GUI
+ *
+ * (C) 2000-2003 Brian Smith <dbsoft@technologist.com>
+ * (C) 2003 Mark Hessling <m.hessling@qut.edu.au>
+ *
+ */
+#define _WIN32_IE 0x0500
+#ifdef WINNT_COMPAT
+#define WINVER 0x400
+#else
+#define WINVER 0x500
+#endif
+#include <windows.h>
+#include <windowsx.h>
+#include <commctrl.h>
+#include <shlwapi.h>
+#include <shlobj.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <process.h>
+#include <time.h>
+#include "dw.h"
+
+HWND popup = (HWND)NULL, hwndBubble = (HWND)NULL, hwndBubbleLast, DW_HWND_OBJECT = (HWND)NULL;
+
+HINSTANCE DWInstance = NULL;
+
+DWORD dwVersion = 0, dwComctlVer = 0;
+DWTID _dwtid = -1;
+
+#define PACKVERSION(major,minor) MAKELONG(minor,major)
+
+#define IS_IE5PLUS (dwComctlVer >= PACKVERSION(5,80))
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+int main(int argc, char *argv[]);
+
+#define ICON_INDEX_LIMIT 200
+HICON lookup[200];
+HIMAGELIST hSmall  = 0, hLarge = 0;
+
+/* Special flag used for internal tracking */
+#define DW_CFA_RESERVED (1 << 30)
+
+#define THREAD_LIMIT 128
+COLORREF _foreground[THREAD_LIMIT];
+COLORREF _background[THREAD_LIMIT];
+HPEN _hPen[THREAD_LIMIT];
+HBRUSH _hBrush[THREAD_LIMIT];
+
+BYTE _red[] = { 	0x00, 0xbb, 0x00, 0xaa, 0x00, 0xbb, 0x00, 0xaa, 0x77,
+			  0xff, 0x00, 0xee, 0x00, 0xff, 0x00, 0xff, 0xaa, 0x00 };
+BYTE _green[] = {	0x00, 0x00, 0xbb, 0xaa, 0x00, 0x00, 0xbb, 0xaa, 0x77,
+			  0x00, 0xff, 0xee, 0x00, 0x00, 0xee, 0xff, 0xaa, 0x00 };
+BYTE _blue[] = { 	0x00, 0x00, 0x00, 0x00, 0xcc, 0xbb, 0xbb, 0xaa, 0x77,
+		      0x00, 0x00, 0x00, 0xff, 0xff, 0xee, 0xff, 0xaa, 0x00};
+
+HBRUSH _colors[18];
+
+
+void _resize_notebook_page(HWND handle, int pageid);
+void _handle_splitbar_resize(HWND hwnd, float percent, int type, int x, int y);
+int _lookup_icon(HWND handle, HICON hicon, int type);
+HFONT _acquire_font(HWND handle, char *fontname);
+
+typedef struct _sighandler
+{
+	struct _sighandler	*next;
+	ULONG message;
+	HWND window;
+	int id;
+	void *signalfunction;
+	void *data;
+
+} SignalHandler;
+
+SignalHandler *Root = NULL;
+int _index;
+
+typedef struct
+{
+	ULONG message;
+	char name[30];
+
+} SignalList;
+
+static int in_checkbox_handler = 0;
+
+/* List of signals and their equivilent Win32 message */
+#define SIGNALMAX 17
+
+SignalList SignalTranslate[SIGNALMAX] = {
+	{ WM_SIZE,         DW_SIGNAL_CONFIGURE },
+	{ WM_CHAR,         DW_SIGNAL_KEY_PRESS },
+	{ WM_LBUTTONDOWN,  DW_SIGNAL_BUTTON_PRESS },
+	{ WM_LBUTTONUP,    DW_SIGNAL_BUTTON_PRESS },
+	{ WM_MOUSEMOVE,    DW_SIGNAL_MOTION_NOTIFY },
+	{ WM_CLOSE,        DW_SIGNAL_DELETE },
+	{ WM_PAINT,        DW_SIGNAL_EXPOSE },
+	{ WM_COMMAND,      DW_SIGNAL_CLICKED },
+	{ NM_DBLCLK,       DW_SIGNAL_ITEM_ENTER },
+	{ NM_RCLICK,       DW_SIGNAL_ITEM_CONTEXT },
+	{ LBN_SELCHANGE,   DW_SIGNAL_LIST_SELECT },
+	{ TVN_SELCHANGED,  DW_SIGNAL_ITEM_SELECT },
+	{ WM_SETFOCUS,     DW_SIGNAL_SET_FOCUS },
+	{ WM_VSCROLL,      DW_SIGNAL_VALUE_CHANGED },
+	{ TCN_SELCHANGE,   DW_SIGNAL_SWITCH_PAGE },
+	{ LVN_COLUMNCLICK, DW_SIGNAL_COLUMN_CLICK },
+	{ TVN_ITEMEXPANDED,DW_SIGNAL_TREE_EXPAND }
+};
+
+#ifdef BUILD_DLL
+void Win32_Set_Instance(HINSTANCE hInstance)
+{
+	DWInstance = hInstance;
+}
+#else
+char **_convertargs(int *count, char *start)
+{
+	char *tmp, *argstart, **argv;
+	int loc = 0, inquotes = 0;
+
+	(*count) = 1;
+
+	tmp = start;
+
+	/* Count the number of entries */
+	if(*start)
+	{
+		(*count)++;
+
+		while(*tmp)
+		{
+			if(*tmp == '"' && inquotes)
+				inquotes = 0;
+			else if(*tmp == '"' && !inquotes)
+				inquotes = 1;
+			else if(*tmp == ' ' && !inquotes)
+			{
+				/* Push past any white space */
+				while(*(tmp+1) == ' ')
+					tmp++;
+				/* If we aren't at the end of the command
+				 * line increment the count.
+				 */
+				if(*(tmp+1))
+					(*count)++;
+			}
+			tmp++;
+		}
+	}
+
+	argv = (char **)malloc(sizeof(char *) * ((*count)+1));
+	argv[0] = malloc(260);
+	GetModuleFileName(DWInstance, argv[0], 260);
+
+	argstart = tmp = start;
+
+	if(*start)
+	{
+		loc = 1;
+
+		while(*tmp)
+		{
+			if(*tmp == '"' && inquotes)
+			{
+				*tmp = 0;
+				inquotes = 0;
+			}
+			else if(*tmp == '"' && !inquotes)
+			{
+				argstart = tmp+1;
+				inquotes = 1;
+			}
+			else if(*tmp == ' ' && !inquotes)
+			{
+				*tmp = 0;
+				argv[loc] = strdup(argstart);
+
+				/* Push past any white space */
+				while(*(tmp+1) == ' ')
+					tmp++;
+
+				/* Move the start pointer */
+				argstart = tmp+1;
+
+				/* If we aren't at the end of the command
+				 * line increment the count.
+				 */
+				if(*(tmp+1))
+					loc++;
+			}
+			tmp++;
+		}
+		if(*argstart)
+			argv[loc] = strdup(argstart);
+	}
+	argv[loc+1] = NULL;
+	return argv;
+}
+
+/* Ok this is a really big hack but what the hell ;) */
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
+{
+	char **argv;
+	int argc;
+
+	DWInstance = hInstance;
+
+	argv = _convertargs(&argc, lpCmdLine);
+
+	return main(argc, argv);
+}
+#endif
+
+/* This should return true for WinNT/2K/XP and false on Win9x */
+int IsWinNT(void)
+{
+	static int isnt = -1;
+
+	if(isnt == -1)
+	{
+		if (GetVersion() < 0x80000000)
+			isnt = 1;
+		else
+			isnt = 0;
+	}
+	return isnt;
+}
+
+DWORD GetDllVersion(LPCTSTR lpszDllName)
+{
+
+	HINSTANCE hinstDll;
+	DWORD dwVersion = 0;
+
+	hinstDll = LoadLibrary(lpszDllName);
+
+	if(hinstDll)
+	{
+		DLLGETVERSIONPROC pDllGetVersion;
+
+		pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hinstDll, "DllGetVersion");
+
+		/* Because some DLLs might not implement this function, you
+		 * must test for it explicitly. Depending on the particular
+		 * DLL, the lack of a DllGetVersion function can be a useful
+		 * indicator of the version.
+		 */
+		if(pDllGetVersion)
+		{
+			DLLVERSIONINFO dvi;
+			HRESULT hr;
+
+			ZeroMemory(&dvi, sizeof(dvi));
+			dvi.cbSize = sizeof(dvi);
+
+            hr = (*pDllGetVersion)(&dvi);
+
+			if(SUCCEEDED(hr))
+			{
+				dwVersion = PACKVERSION(dvi.dwMajorVersion, dvi.dwMinorVersion);
+			}
+		}
+
+		FreeLibrary(hinstDll);
+	}
+    return dwVersion;
+}
+
+/* This function adds a signal handler callback into the linked list.
+ */
+void _new_signal(ULONG message, HWND window, int id, void *signalfunction, void *data)
+{
+	SignalHandler *new = malloc(sizeof(SignalHandler));
+
+	new->message = message;
+	new->window = window;
+	new->id = id;
+	new->signalfunction = signalfunction;
+	new->data = data;
+	new->next = NULL;
+
+	if (!Root)
+		Root = new;
+	else
+	{
+		SignalHandler *prev = NULL, *tmp = Root;
+		while(tmp)
+		{
+			if(tmp->message == message &&
+			   tmp->window == window &&
+			   tmp->id == id &&
+			   tmp->signalfunction == signalfunction)
+			{
+				tmp->data = data;
+				free(new);
+				return;
+			}
+			prev = tmp;
+			tmp = tmp->next;
+		}
+		if(prev)
+			prev->next = new;
+		else
+			Root = new;
+	}
+}
+
+/* Finds the message number for a given signal name */
+ULONG _findsigmessage(char *signame)
+{
+	int z;
+
+	for(z=0;z<SIGNALMAX;z++)
+	{
+		if(stricmp(signame, SignalTranslate[z].name) == 0)
+			return SignalTranslate[z].message;
+	}
+	return 0L;
+}
+
+/* This function removes and handlers on windows and frees
+ * the user memory allocated to it.
+ */
+BOOL CALLBACK _free_window_memory(HWND handle, LPARAM lParam)
+{
+	ColorInfo *thiscinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA);
+	HFONT oldfont = (HFONT)SendMessage(handle, WM_GETFONT, 0, 0);
+	HICON oldicon = (HICON)SendMessage(handle, WM_GETICON, 0, 0);
+	char tmpbuf[100];
+
+	/* Delete font, icon and bitmap GDI objects in use */
+	if(oldfont)
+		DeleteObject(oldfont);
+	if(oldicon)
+		DeleteObject(oldicon);
+
+	GetClassName(handle, tmpbuf, 99);
+
+	if(strnicmp(tmpbuf, STATICCLASSNAME, strlen(STATICCLASSNAME)+1)==0)
+	{
+		HBITMAP oldbitmap = (HBITMAP)SendMessage(handle, STM_GETIMAGE, IMAGE_BITMAP, 0);
+
+		if(oldbitmap)
+			DeleteObject(oldbitmap);
+	}
+	if(strnicmp(tmpbuf, BUTTONCLASSNAME, strlen(BUTTONCLASSNAME)+1)==0)
+	{
+		HBITMAP oldbitmap = (HBITMAP)SendMessage(handle, BM_GETIMAGE, IMAGE_BITMAP, 0);
+
+		if(oldbitmap)
+			DeleteObject(oldbitmap);
+	}
+	else if(strnicmp(tmpbuf, FRAMECLASSNAME, strlen(FRAMECLASSNAME)+1)==0)
+	{
+		Box *box = (Box *)thiscinfo;
+
+		if(box->count && box->items)
+			free(box->items);
+	}
+	else if(strnicmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0)
+	{
+		void *data = dw_window_get_data(handle, "_dw_percent");
+
+		if(data)
+			free(data);
+	}
+	else if(strnicmp(tmpbuf, WC_TREEVIEW, strlen(WC_TREEVIEW)+1)==0)
+	{
+		dw_tree_clear(handle);
+	}
+	else if(strnicmp(tmpbuf, WC_TABCONTROL, strlen(WC_TABCONTROL)+1)==0) /* Notebook */
+	{
+		NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array");
+
+		if(array)
+		{
+			int z, refid = -1;
+
+			for(z=0;z<256;z++)
+			{
+				if(array[z])
+				{
+					_free_window_memory(array[z]->hwnd, 0);
+					EnumChildWindows(array[z]->hwnd, _free_window_memory, 0);
+					DestroyWindow(array[z]->hwnd);
+					free(array[z]);
+				}
+			}
+			free(array);
+		}
+	}
+
+	dw_signal_disconnect_by_window(handle);
+
+	if(thiscinfo)
+	{
+		SubclassWindow(handle, thiscinfo->pOldProc);
+
+		/* Delete the brush so as not to leak GDI objects */
+		if(thiscinfo->hbrush)
+			DeleteObject(thiscinfo->hbrush);
+
+		/* Free user data linked list memory */
+		if(thiscinfo->root)
+			dw_window_set_data(handle, NULL, NULL);
+
+		SetWindowLongPtr(handle, GWLP_USERDATA, 0);
+		free(thiscinfo);
+	}
+	return TRUE;
+}
+
+void _free_menu_data(HMENU menu)
+{
+#ifndef WINNT_COMPAT
+	int i, count = GetMenuItemCount(menu);
+
+	for(i=0;i<count;i++)
+	{
+		MENUITEMINFO mii;
+
+		mii.cbSize = sizeof(MENUITEMINFO);
+		mii.fMask = MIIM_SUBMENU;
+
+		if(GetMenuItemInfo(menu, i, TRUE, &mii)
+		   && mii.hSubMenu)
+			_free_menu_data(mii.hSubMenu);
+	}
+#endif
+	dw_signal_disconnect_by_name((HWND)menu, DW_SIGNAL_CLICKED);
+}
+
+/* Convert to our internal color scheme */
+ULONG _internal_color(ULONG color)
+{
+	if(color == DW_CLR_DEFAULT)
+		return DW_RGB_TRANSPARENT;
+	if(color < 18)
+		return DW_RGB(_red[color], _green[color], _blue[color]);
+	return color;
+}
+
+/* This function returns 1 if the window (widget) handle
+ * passed to it is a valid window that can gain input focus.
+ */
+int _validate_focus(HWND handle)
+{
+	char tmpbuf[100];
+
+	if(!handle)
+		return 0;
+
+	if(!IsWindowEnabled(handle))
+		return 0;
+
+	GetClassName(handle, tmpbuf, 99);
+
+	/* These are the window classes which can
+	 * obtain input focus.
+	 */
+	if(strnicmp(tmpbuf, EDITCLASSNAME, strlen(EDITCLASSNAME)+1)==0 ||          /* Entryfield */
+	   strnicmp(tmpbuf, BUTTONCLASSNAME, strlen(BUTTONCLASSNAME)+1)==0 ||      /* Button */
+	   strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0 ||  /* Combobox */
+	   strnicmp(tmpbuf, LISTBOXCLASSNAME, strlen(LISTBOXCLASSNAME)+1)==0 ||    /* List box */
+	   strnicmp(tmpbuf, UPDOWN_CLASS, strlen(UPDOWN_CLASS)+1)==0 ||            /* Spinbutton */
+	   strnicmp(tmpbuf, TRACKBAR_CLASS, strlen(TRACKBAR_CLASS)+1)==0 ||        /* Slider */
+	   strnicmp(tmpbuf, WC_LISTVIEW, strlen(WC_LISTVIEW)+1)== 0 ||             /* Container */
+	   strnicmp(tmpbuf, WC_TREEVIEW, strlen(WC_TREEVIEW)+1)== 0)               /* Tree */
+		return 1;
+	return 0;
+}
+
+HWND _normalize_handle(HWND handle)
+{
+	char tmpbuf[100] = "";
+
+	GetClassName(handle, tmpbuf, 99);
+	if(strnicmp(tmpbuf, UPDOWN_CLASS, strlen(UPDOWN_CLASS))==0) /* Spinner */
+	{
+		ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA);
+
+		if(cinfo && cinfo->buddy)
+			return cinfo->buddy;
+	}
+	if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME))==0) /* Combobox */
+	{
+		ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA);
+
+		if(cinfo && cinfo->buddy)
+			return cinfo->buddy;
+	}
+	return handle;
+}
+
+int _focus_check_box(Box *box, HWND handle, int start, HWND defaultitem)
+{
+	int z;
+	static HWND lasthwnd, firsthwnd;
+    static int finish_searching;
+
+	/* Start is 2 when we have cycled completely and
+	 * need to set the focus to the last widget we found
+	 * that was valid.
+	 */
+	if(start == 2)
+	{
+		if(lasthwnd)
+			SetFocus(lasthwnd);
+		return 0;
+	}
+
+	/* Start is 1 when we are entering the function
+	 * for the first time, it is zero when entering
+	 * the function recursively.
+	 */
+	if(start == 1)
+	{
+		lasthwnd = handle;
+		finish_searching = 0;
+		firsthwnd = 0;
+	}
+
+	for(z=box->count-1;z>-1;z--)
+	{
+		if(box->items[z].type == TYPEBOX)
+		{
+			Box *thisbox = (Box *)GetWindowLongPtr(box->items[z].hwnd, GWLP_USERDATA);
+
+			if(thisbox && _focus_check_box(thisbox, handle, start == 3 ? 3 : 0, defaultitem))
+				return 1;
+		}
+		else
+		{
+			if(box->items[z].hwnd == handle)
+			{
+				if(lasthwnd == handle && firsthwnd)
+					SetFocus(firsthwnd);
+				else if(lasthwnd == handle && !firsthwnd)
+					finish_searching = 1;
+				else
+					SetFocus(lasthwnd);
+
+				/* If we aren't looking for the last handle,
+				 * return immediately.
+				 */
+				if(!finish_searching)
+					return 1;
+			}
+			if(_validate_focus(box->items[z].hwnd))
+			{
+				/* Start is 3 when we are looking for the
+				 * first valid item in the layout.
+				 */
+				if(start == 3)
+				{
+					if(!defaultitem || (defaultitem && box->items[z].hwnd == defaultitem))
+					{
+						SetFocus(_normalize_handle(box->items[z].hwnd));
+						return 1;
+					}
+				}
+
+				if(!firsthwnd)
+					firsthwnd = _normalize_handle(box->items[z].hwnd);
+
+				lasthwnd = _normalize_handle(box->items[z].hwnd);
+			}
+			else
+			{
+				char tmpbuf[100] = "";
+
+				GetClassName(box->items[z].hwnd, tmpbuf, 99);
+
+				if(strncmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0)
+				{
+					/* Then try the bottom or right box */
+					HWND mybox = (HWND)dw_window_get_data(box->items[z].hwnd, "_dw_bottomright");
+
+					if(mybox)
+					{
+						Box *splitbox = (Box *)GetWindowLongPtr(mybox, GWLP_USERDATA);
+
+						if(splitbox && _focus_check_box(splitbox, handle, start == 3 ? 3 : 0, defaultitem))
+							return 1;
+					}
+
+					/* Try the top or left box */
+					mybox = (HWND)dw_window_get_data(box->items[z].hwnd, "_dw_topleft");
+
+					if(mybox)
+					{
+						Box *splitbox = (Box *)GetWindowLongPtr(mybox, GWLP_USERDATA);
+
+						if(splitbox && _focus_check_box(splitbox, handle, start == 3 ? 3 : 0, defaultitem))
+							return 1;
+					}
+				}
+				else if(strnicmp(tmpbuf, WC_TABCONTROL, strlen(WC_TABCONTROL))==0) /* Notebook */
+				{
+					NotebookPage **array = (NotebookPage **)dw_window_get_data(box->items[z].hwnd, "_dw_array");
+					int pageid = TabCtrl_GetCurSel(box->items[z].hwnd);
+
+					if(pageid > -1 && array && array[pageid])
+					{
+						Box *notebox;
+
+						if(array[pageid]->hwnd)
+						{
+							notebox = (Box *)GetWindowLongPtr(array[pageid]->hwnd, GWLP_USERDATA);
+
+							if(notebox && _focus_check_box(notebox, handle, start == 3 ? 3 : 0, defaultitem))
+								return 1;
+						}
+					}
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+int _focus_check_box_back(Box *box, HWND handle, int start, HWND defaultitem)
+{
+	int z;
+	static HWND lasthwnd, firsthwnd;
+    static int finish_searching;
+
+	/* Start is 2 when we have cycled completely and
+	 * need to set the focus to the last widget we found
+	 * that was valid.
+	 */
+	if(start == 2)
+	{
+		if(lasthwnd)
+			SetFocus(lasthwnd);
+		return 0;
+	}
+
+	/* Start is 1 when we are entering the function
+	 * for the first time, it is zero when entering
+	 * the function recursively.
+	 */
+	if(start == 1)
+	{
+		lasthwnd = handle;
+		finish_searching = 0;
+		firsthwnd = 0;
+	}
+
+	for(z=0;z<box->count;z++)
+	{
+		if(box->items[z].type == TYPEBOX)
+		{
+			Box *thisbox = (Box *)GetWindowLongPtr(box->items[z].hwnd, GWLP_USERDATA);
+
+			if(thisbox && _focus_check_box_back(thisbox, handle, start == 3 ? 3 : 0, defaultitem))
+				return 1;
+		}
+		else
+		{
+			if(box->items[z].hwnd == handle)
+			{
+				if(lasthwnd == handle && firsthwnd)
+					SetFocus(firsthwnd);
+				else if(lasthwnd == handle && !firsthwnd)
+					finish_searching = 1;
+				else
+					SetFocus(lasthwnd);
+
+				/* If we aren't looking for the last handle,
+				 * return immediately.
+				 */
+				if(!finish_searching)
+					return 1;
+			}
+			if(_validate_focus(box->items[z].hwnd))
+			{
+				/* Start is 3 when we are looking for the
+				 * first valid item in the layout.
+				 */
+				if(start == 3)
+				{
+					if(!defaultitem || (defaultitem && box->items[z].hwnd == defaultitem))
+					{
+						SetFocus(_normalize_handle(box->items[z].hwnd));
+						return 1;
+					}
+				}
+
+				if(!firsthwnd)
+					firsthwnd = _normalize_handle(box->items[z].hwnd);
+
+				lasthwnd = _normalize_handle(box->items[z].hwnd);
+			}
+			else
+			{
+				char tmpbuf[100] = "";
+
+				GetClassName(box->items[z].hwnd, tmpbuf, 99);
+
+				if(strncmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0)
+				{
+					/* Try the top or left box */
+					HWND mybox = (HWND)dw_window_get_data(box->items[z].hwnd, "_dw_topleft");
+
+					if(mybox)
+					{
+						Box *splitbox = (Box *)GetWindowLongPtr(mybox, GWLP_USERDATA);
+
+						if(splitbox && _focus_check_box_back(splitbox, handle, start == 3 ? 3 : 0, defaultitem))
+							return 1;
+					}
+
+					/* Then try the bottom or right box */
+					mybox = (HWND)dw_window_get_data(box->items[z].hwnd, "_dw_bottomright");
+
+					if(mybox)
+					{
+						Box *splitbox = (Box *)GetWindowLongPtr(mybox, GWLP_USERDATA);
+
+						if(splitbox && _focus_check_box_back(splitbox, handle, start == 3 ? 3 : 0, defaultitem))
+							return 1;
+					}
+				}
+				else if(strnicmp(tmpbuf, WC_TABCONTROL, strlen(WC_TABCONTROL))==0) /* Notebook */
+				{
+					NotebookPage **array = (NotebookPage **)dw_window_get_data(box->items[z].hwnd, "_dw_array");
+					int pageid = TabCtrl_GetCurSel(box->items[z].hwnd);
+
+					if(pageid > -1 && array && array[pageid])
+					{
+						Box *notebox;
+
+						if(array[pageid]->hwnd)
+						{
+							notebox = (Box *)GetWindowLongPtr(array[pageid]->hwnd, GWLP_USERDATA);
+
+							if(notebox && _focus_check_box_back(notebox, handle, start == 3 ? 3 : 0, defaultitem))
+								return 1;
+						}
+					}
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+/* This function finds the first widget in the
+ * layout and moves the current focus to it.
+ */
+void _initial_focus(HWND handle)
+{
+	Box *thisbox;
+	char tmpbuf[100];
+
+	if(!handle)
+		return;
+
+	GetClassName(handle, tmpbuf, 99);
+
+	if(strnicmp(tmpbuf, ClassName, strlen(ClassName))!=0)
+		return;
+
+
+	if(handle)
+		thisbox = (Box *)GetWindowLongPtr(handle, GWLP_USERDATA);
+
+	if(thisbox)
+	{
+		_focus_check_box(thisbox, handle, 3, thisbox->defaultitem);
+	}
+}
+
+HWND _toplevel_window(HWND handle)
+{
+	HWND box, lastbox = GetParent(handle);
+
+	/* Find the toplevel window */
+	while((box = GetParent(lastbox)))
+	{
+		lastbox = box;
+	}
+	if(lastbox)
+		return lastbox;
+	return handle;
+}
+
+/* This function finds the current widget in the
+ * layout and moves the current focus to the next item.
+ */
+void _shift_focus(HWND handle)
+{
+	Box *thisbox;
+
+	HWND box, lastbox = GetParent(handle);
+
+	/* Find the toplevel window */
+	while((box = GetParent(lastbox)))
+	{
+		lastbox = box;
+	}
+
+	thisbox = (Box *)GetWindowLongPtr(lastbox, GWLP_USERDATA);
+	if(thisbox)
+	{
+		if(_focus_check_box(thisbox, handle, 1, 0)  == 0)
+			_focus_check_box(thisbox, handle, 2, 0);
+	}
+}
+
+/* This function finds the current widget in the
+ * layout and moves the current focus to the next item.
+ */
+void _shift_focus_back(HWND handle)
+{
+	Box *thisbox;
+
+	HWND box, lastbox = GetParent(handle);
+
+	/* Find the toplevel window */
+	while((box = GetParent(lastbox)))
+	{
+		lastbox = box;
+	}
+
+	thisbox = (Box *)GetWindowLongPtr(lastbox, GWLP_USERDATA);
+	if(thisbox)
+	{
+		if(_focus_check_box_back(thisbox, handle, 1, 0)  == 0)
+			_focus_check_box_back(thisbox, handle, 2, 0);
+	}
+}
+
+/* ResetWindow:
+ *         Resizes window to the exact same size to trigger
+ *         recalculation of frame.
+ */
+void _ResetWindow(HWND hwndFrame)
+{
+	RECT rcl;
+
+	GetWindowRect(hwndFrame, &rcl);
+	SetWindowPos(hwndFrame, HWND_TOP, 0, 0, rcl.right - rcl.left,
+				 rcl.bottom - rcl.top - 1, SWP_NOMOVE | SWP_NOZORDER);
+	SetWindowPos(hwndFrame, HWND_TOP, 0, 0, rcl.right - rcl.left,
+				 rcl.bottom - rcl.top, SWP_NOMOVE | SWP_NOZORDER);
+}
+
+/* This function calculates how much space the widgets and boxes require
+ * and does expansion as necessary.
+ */
+int _resize_box(Box *thisbox, int *depth, int x, int y, int *usedx, int *usedy,
+				int pass, int *usedpadx, int *usedpady)
+{
+	int z, currentx = 0, currenty = 0;
+	int uymax = 0, uxmax = 0;
+	int upymax = 0, upxmax = 0;
+	/* Used for the SIZEEXPAND */
+	int nux = *usedx, nuy = *usedy;
+	int nupx = *usedpadx, nupy = *usedpady;
+
+	(*usedx) += (thisbox->pad * 2);
+	(*usedy) += (thisbox->pad * 2);
+
+	if(thisbox->grouphwnd)
+	{
+		char *text = dw_window_get_text(thisbox->grouphwnd);
+
+		thisbox->grouppady = 0;
+
+		if(text)
+		{
+			dw_font_text_extents(thisbox->grouphwnd, 0, text, NULL, &thisbox->grouppady);
+			dw_free(text);
+		}
+
+		if(thisbox->grouppady)
+			thisbox->grouppady += 3;
+		else
+			thisbox->grouppady = 6;
+
+		thisbox->grouppadx = 6;
+
+		(*usedx) += thisbox->grouppadx;
+		(*usedpadx) += thisbox->grouppadx;
+		(*usedy) += thisbox->grouppady;
+		(*usedpady) += thisbox->grouppady;
+	}
+
+	for(z=0;z<thisbox->count;z++)
+	{
+		if(thisbox->items[z].type == TYPEBOX)
+		{
+			int initialx, initialy;
+			Box *tmp = (Box *)GetWindowLongPtr(thisbox->items[z].hwnd, GWLP_USERDATA);
+
+			initialx = x - (*usedx);
+			initialy = y - (*usedy);
+
+			if(tmp)
+			{
+				int newx, newy;
+				int nux = *usedx, nuy = *usedy;
+				int upx = *usedpadx + (tmp->pad*2), upy = *usedpady + (tmp->pad*2);
+
+				/* On the second pass we know how big the box needs to be and how
+				 * much space we have, so we can calculate a ratio for the new box.
+				 */
+				if(pass == 2)
+				{
+					int deep = *depth + 1;
+
+					_resize_box(tmp, &deep, x, y, &nux, &nuy, 1, &upx, &upy);
+
+					tmp->upx = upx - *usedpadx;
+					tmp->upy = upy - *usedpady;
+
+					newx = x - nux;
+					newy = y - nuy;
+
+					tmp->width = thisbox->items[z].width = initialx - newx;
+					tmp->height = thisbox->items[z].height = initialy - newy;
+
+					tmp->parentxratio = thisbox->xratio;
+					tmp->parentyratio = thisbox->yratio;
+
+					tmp->parentpad = tmp->pad;
+
+					/* Just in case */
+					tmp->xratio = thisbox->xratio;
+					tmp->yratio = thisbox->yratio;
+
+					if(thisbox->type == DW_VERT)
+					{
+						int tmppad = (thisbox->items[z].pad*2)+(tmp->pad*2)+tmp->grouppady;
+
+						if((thisbox->items[z].width - tmppad)!=0)
+							tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmppad))/((float)(thisbox->items[z].width-tmppad));
+					}
+					else
+					{
+						if((thisbox->items[z].width-tmp->upx)!=0)
+							tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmp->upx))/((float)(thisbox->items[z].width-tmp->upx));
+					}
+					if(thisbox->type == DW_HORZ)
+					{
+						int tmppad = (thisbox->items[z].pad*2)+(tmp->pad*2)+tmp->grouppadx;
+
+						if((thisbox->items[z].height-tmppad)!=0)
+							tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmppad))/((float)(thisbox->items[z].height-tmppad));
+					}
+					else
+					{
+						if((thisbox->items[z].height-tmp->upy)!=0)
+							tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmp->upy))/((float)(thisbox->items[z].height-tmp->upy));
+					}
+
+					nux = *usedx; nuy = *usedy;
+					upx = *usedpadx + (tmp->pad*2); upy = *usedpady + (tmp->pad*2);
+				}
+
+				(*depth)++;
+
+				_resize_box(tmp, depth, x, y, &nux, &nuy, pass, &upx, &upy);
+
+				(*depth)--;
+
+				newx = x - nux;
+				newy = y - nuy;
+
+				tmp->minwidth = thisbox->items[z].width = initialx - newx;
+				tmp->minheight = thisbox->items[z].height = initialy - newy;
+			}
+		}
+
+		if(pass > 1 && *depth > 0)
+		{
+			if(thisbox->type == DW_VERT)
+			{
+				int tmppad = (thisbox->items[z].pad*2)+(thisbox->parentpad*2)+thisbox->grouppadx;
+
+				if((thisbox->minwidth-tmppad) == 0)
+					thisbox->items[z].xratio = 1.0;
+				else
+					thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-tmppad))/((float)(thisbox->minwidth-tmppad));
+			}
+			else
+			{
+				if(thisbox->minwidth-thisbox->upx == 0)
+					thisbox->items[z].xratio = 1.0;
+				else
+					thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-thisbox->upx))/((float)(thisbox->minwidth-thisbox->upx));
+			}
+
+			if(thisbox->type == DW_HORZ)
+			{
+				int tmppad = (thisbox->items[z].pad*2)+(thisbox->parentpad*2)+thisbox->grouppady;
+
+				if((thisbox->minheight-tmppad) == 0)
+					thisbox->items[z].yratio = 1.0;
+				else
+					thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-tmppad))/((float)(thisbox->minheight-tmppad));
+			}
+			else
+			{
+				if(thisbox->minheight-thisbox->upy == 0)
+					thisbox->items[z].yratio = 1.0;
+				else
+					thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-thisbox->upy))/((float)(thisbox->minheight-thisbox->upy));
+			}
+
+			if(thisbox->items[z].type == TYPEBOX)
+			{
+				Box *tmp = (Box *)GetWindowLongPtr(thisbox->items[z].hwnd, GWLP_USERDATA);
+
+				if(tmp)
+				{
+					tmp->parentxratio = thisbox->items[z].xratio;
+					tmp->parentyratio = thisbox->items[z].yratio;
+				}
+			}
+		}
+		else
+		{
+			thisbox->items[z].xratio = thisbox->xratio;
+			thisbox->items[z].yratio = thisbox->yratio;
+		}
+
+		if(thisbox->type == DW_VERT)
+		{
+			int itemwidth = (thisbox->items[z].pad*2) + thisbox->items[z].width;
+
+			if(itemwidth > uxmax)
+				uxmax = itemwidth;
+			if(thisbox->items[z].hsize != SIZEEXPAND)
+			{
+				if(itemwidth > upxmax)
+					upxmax = itemwidth;
+			}
+			else
+			{
+				if(thisbox->items[z].pad*2 > upxmax)
+					upxmax = thisbox->items[z].pad*2;
+			}
+		}
+		else
+		{
+			if(thisbox->items[z].width == -1)
+			{
+				/* figure out how much space this item requires */
+				/* thisbox->items[z].width = */
+			}
+			else
+			{
+				(*usedx) += thisbox->items[z].width + (thisbox->items[z].pad*2);
+				if(thisbox->items[z].hsize != SIZEEXPAND)
+					(*usedpadx) += (thisbox->items[z].pad*2) + thisbox->items[z].width;
+				else
+					(*usedpadx) += thisbox->items[z].pad*2;
+			}
+		}
+		if(thisbox->type == DW_HORZ)
+		{
+			int itemheight = (thisbox->items[z].pad*2) + thisbox->items[z].height;
+
+			if(itemheight > uymax)
+				uymax = itemheight;
+			if(thisbox->items[z].vsize != SIZEEXPAND)
+			{
+				if(itemheight > upymax)
+					upymax = itemheight;
+			}
+			else
+			{
+				if(thisbox->items[z].pad*2 > upymax)
+					upymax = thisbox->items[z].pad*2;
+			}
+		}
+		else
+		{
+			if(thisbox->items[z].height == -1)
+			{
+				/* figure out how much space this item requires */
+				/* thisbox->items[z].height = */
+			}
+			else
+			{
+				(*usedy) += thisbox->items[z].height + (thisbox->items[z].pad*2);
+				if(thisbox->items[z].vsize != SIZEEXPAND)
+					(*usedpady) += (thisbox->items[z].pad*2) + thisbox->items[z].height;
+				else
+					(*usedpady) += thisbox->items[z].pad*2;
+			}
+		}
+	}
+
+	(*usedx) += uxmax;
+	(*usedy) += uymax;
+	(*usedpadx) += upxmax;
+	(*usedpady) += upymax;
+
+	currentx += thisbox->pad;
+	currenty += thisbox->pad;
+
+	if(thisbox->grouphwnd)
+	{
+		currentx += 3;
+		currenty += thisbox->grouppady - 3;
+	}
+
+	/* The second pass is for expansion and actual placement. */
+	if(pass > 1)
+	{
+		/* Any SIZEEXPAND items should be set to uxmax/uymax */
+		for(z=0;z<thisbox->count;z++)
+		{
+			if(thisbox->items[z].hsize == SIZEEXPAND && thisbox->type == DW_VERT)
+				thisbox->items[z].width = uxmax-(thisbox->items[z].pad*2);
+			if(thisbox->items[z].vsize == SIZEEXPAND && thisbox->type == DW_HORZ)
+				thisbox->items[z].height = uymax-(thisbox->items[z].pad*2);
+			/* Run this code segment again to finalize the sized after setting uxmax/uymax values. */
+			if(thisbox->items[z].type == TYPEBOX)
+			{
+				Box *tmp = (Box *)GetWindowLongPtr(thisbox->items[z].hwnd, GWLP_USERDATA);
+
+				if(tmp)
+				{
+					if(*depth > 0)
+					{
+						float calcval;
+
+						if(thisbox->type == DW_VERT)
+						{
+							calcval = (float)(tmp->minwidth-((thisbox->items[z].pad*2)+(thisbox->pad*2)));
+							if(calcval == 0.0)
+								tmp->xratio = thisbox->xratio;
+							else
+								tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-((thisbox->items[z].pad*2)+(thisbox->pad*2))))/calcval;
+							tmp->width = thisbox->items[z].width;
+						}
+						if(thisbox->type == DW_HORZ)
+						{
+							calcval = (float)(tmp->minheight-((thisbox->items[z].pad*2)+(thisbox->pad*2)));
+							if(calcval == 0.0)
+								tmp->yratio = thisbox->yratio;
+							else
+								tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-((thisbox->items[z].pad*2)+(thisbox->pad*2))))/calcval;
+							tmp->height = thisbox->items[z].height;
+						}
+					}
+
+					(*depth)++;
+
+					_resize_box(tmp, depth, x, y, &nux, &nuy, 3, &nupx, &nupy);
+
+					(*depth)--;
+
+				}
+			}
+		}
+
+		for(z=0;z<(thisbox->count);z++)
+		{
+			int height = thisbox->items[z].height;
+			int width = thisbox->items[z].width;
+			int pad = thisbox->items[z].pad;
+			HWND handle = thisbox->items[z].hwnd;
+			int vectorx, vectory;
+
+			/* When upxmax != pad*2 then ratios are incorrect. */
+			vectorx = (int)((width*thisbox->items[z].xratio)-width);
+			vectory = (int)((height*thisbox->items[z].yratio)-height);
+
+			if(width > 0 && height > 0)
+			{
+				char tmpbuf[100];
+				/* This is a hack to fix rounding of the sizing */
+				if(*depth == 0)
+				{
+					vectorx++;
+					vectory++;
+				}
+
+				/* If this item isn't going to expand... reset the vectors to 0 */
+				if(thisbox->items[z].vsize != SIZEEXPAND)
+					vectory = 0;
+				if(thisbox->items[z].hsize != SIZEEXPAND)
+					vectorx = 0;
+
+				GetClassName(handle, tmpbuf, 99);
+
+				if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0)
+				{
+					/* Handle special case Combobox */
+					MoveWindow(handle, currentx + pad, currenty + pad,
+							   width + vectorx, (height + vectory) + 400, FALSE);
+				}
+				else if(strnicmp(tmpbuf, UPDOWN_CLASS, strlen(UPDOWN_CLASS)+1)==0)
+				{
+					/* Handle special case Spinbutton */
+					ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA);
+
+					MoveWindow(handle, currentx + pad + ((width + vectorx) - 20), currenty + pad,
+							   20, height + vectory, FALSE);
+
+					if(cinfo)
+					{
+						MoveWindow(cinfo->buddy, currentx + pad, currenty + pad,
+								   (width + vectorx) - 20, height + vectory, FALSE);
+					}
+				}
+				else if(strncmp(tmpbuf, SplitbarClassName, strlen(SplitbarClassName)+1)==0)
+				{
+					/* Then try the bottom or right box */
+					float *percent = (float *)dw_window_get_data(handle, "_dw_percent");
+					int type = (int)dw_window_get_data(handle, "_dw_type");
+					int cx = width + vectorx;
+					int cy = height + vectory;
+
+					MoveWindow(handle, currentx + pad, currenty + pad,
+							   cx, cy, FALSE);
+
+					if(cx > 0 && cy > 0 && percent)
+						_handle_splitbar_resize(handle, *percent, type, cx, cy);
+				}
+				else if(strnicmp(tmpbuf, STATICCLASSNAME, strlen(STATICCLASSNAME)+1)==0)
+				{
+					/* Handle special case Vertically Center static text */
+					ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA);
+
+					if(cinfo && cinfo->vcenter)
+					{
+						/* We are centered so calculate a new position */
+						char tmpbuf[1024];
+						int textheight, diff, total = height + vectory;
+
+						GetWindowText(handle, tmpbuf, 1023);
+
+						/* Figure out how big the text is */
+						dw_font_text_extents(handle, 0, tmpbuf, 0, &textheight);
+
+						diff = (total - textheight) / 2;
+
+						MoveWindow(handle, currentx + pad, currenty + pad + diff,
+								   width + vectorx, height + vectory - diff, FALSE);
+					}
+					else
+					{
+						MoveWindow(handle, currentx + pad, currenty + pad,
+								   width + vectorx, height + vectory, FALSE);
+					}
+				}
+				else
+				{
+					/* Everything else */
+					MoveWindow(handle, currentx + pad, currenty + pad,
+							   width + vectorx, height + vectory, FALSE);
+					if(thisbox->items[z].type == TYPEBOX)
+					{
+						Box *boxinfo = (Box *)GetWindowLongPtr(handle, GWLP_USERDATA);
+
+						if(boxinfo && boxinfo->grouphwnd)
+							MoveWindow(boxinfo->grouphwnd, 0, 0,
+									   width + vectorx, height + vectory, FALSE);
+
+					}
+				}
+
+				/* Notebook dialog requires additional processing */
+				if(strncmp(tmpbuf, WC_TABCONTROL, strlen(WC_TABCONTROL))==0)
+				{
+					RECT rect;
+					NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array");
+					int pageid = TabCtrl_GetCurSel(handle);
+
+					if(pageid > -1 && array && array[pageid])
+					{
+						GetClientRect(handle,&rect);
+						TabCtrl_AdjustRect(handle,FALSE,&rect);
+						MoveWindow(array[pageid]->hwnd, rect.left, rect.top,
+								   rect.right - rect.left, rect.bottom-rect.top, FALSE);
+					}
+				}
+
+				if(thisbox->type == DW_HORZ)
+					currentx += width + vectorx + (pad * 2);
+				if(thisbox->type == DW_VERT)
+					currenty += height + vectory + (pad * 2);
+			}
+		}
+	}
+	return 0;
+}
+
+void _do_resize(Box *thisbox, int x, int y)
+{
+	if(x != 0 && y != 0)
+	{
+		if(thisbox)
+		{
+			int usedx = 0, usedy = 0, depth = 0, usedpadx = 0, usedpady = 0;
+
+			_resize_box(thisbox, &depth, x, y, &usedx, &usedy, 1, &usedpadx, &usedpady);
+
+			if(usedx-usedpadx == 0 || usedy-usedpady == 0)
+				return;
+
+			thisbox->xratio = ((float)(x-usedpadx))/((float)(usedx-usedpadx));
+			thisbox->yratio = ((float)(y-usedpady))/((float)(usedy-usedpady));
+
+			usedpadx = usedpady = usedx = usedy = depth = 0;
+
+			_resize_box(thisbox, &depth, x, y, &usedx, &usedy, 2, &usedpadx, &usedpady);
+		}
+	}
+}
+
+int _HandleScroller(HWND handle, int pos, int which)
+{
+	SCROLLINFO si;
+
+	si.cbSize = sizeof(SCROLLINFO);
+	si.fMask = SIF_ALL;
+
+	SendMessage(handle, SBM_GETSCROLLINFO, 0, (LPARAM)&si);
+
+	switch(which)
+	{
+	case SB_THUMBTRACK:
+		return pos;
+	/*case SB_PAGEDOWN:*/
+	case SB_PAGELEFT:
+		pos = si.nPos - si.nPage;
+		if(pos < si.nMin)
+			pos = si.nMin;
+		return pos;
+	/*case SB_PAGEUP:*/
+	case SB_PAGERIGHT:
+		pos = si.nPos + si.nPage;
+		if(pos > (si.nMax - si.nPage) + 1)
+			pos = (si.nMax - si.nPage) + 1;
+		return pos;
+	/*case SB_LINEDOWN:*/
+	case SB_LINELEFT:
+		pos = si.nPos - 1;
+		if(pos < si.nMin)
+			pos = si.nMin;
+		return pos;
+	/*case SB_LINEUP:*/
+	case SB_LINERIGHT:
+		pos = si.nPos + 1;
+		if(pos > (si.nMax - si.nPage) + 1)
+			pos = (si.nMax - si.nPage) + 1;
+		return pos;
+	}
+	return -1;
+}
+
+#ifndef WINNT_COMPAT
+HMENU _get_owner(HMENU menu)
+{
+	MENUINFO mi;
+
+	mi.cbSize = sizeof(MENUINFO);
+	mi.fMask = MIM_MENUDATA;
+
+	if(GetMenuInfo(menu, &mi))
+		return (HMENU)mi.dwMenuData;
+	return (HMENU)0;
+}
+
+/* Find the desktop window handle */
+HMENU _menu_owner(HMENU handle)
+{
+	HMENU menuowner = 0, lastowner = _get_owner(handle);
+
+	/* Find the toplevel menu */
+	while((menuowner = _get_owner(lastowner)) != 0)
+	{
+		if(menuowner == (HMENU)1)
+			return lastowner;
+		lastowner = menuowner;
+	}
+	return (HMENU)0;
+}
+#endif
+
+/* The main window procedure for Dynamic Windows, all the resizing code is done here. */
+BOOL CALLBACK _wndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2)
+{
+	int result = -1, taskbar = FALSE;
+	static int command_active = 0;
+	SignalHandler *tmp = Root;
+	void (*windowfunc)(PVOID);
+	ULONG origmsg = msg;
+
+	/* Deal with translating some messages */
+	if(msg == WM_USER+2)
+	{
+		taskbar = TRUE;
+		origmsg = msg = (UINT)mp2; /* no else here */
+	}
+	if(msg == WM_RBUTTONDOWN || msg == WM_MBUTTONDOWN)
+		msg = WM_LBUTTONDOWN;
+	else if(msg == WM_RBUTTONUP || msg == WM_MBUTTONUP)
+		msg = WM_LBUTTONUP;
+	else if(msg == WM_HSCROLL)
+		msg = WM_VSCROLL;
+	else if(msg == WM_KEYDOWN) /* && mp1 >= VK_F1 && mp1 <= VK_F24) allow ALL special keys */
+		msg = WM_CHAR;
+
+	if(result == -1)
+	{
+		/* Avoid infinite recursion */
+		command_active = 1;
+
+		/* Find any callbacks for this function */
+		while(tmp)
+		{
+			if(tmp->message == msg || msg == WM_COMMAND || msg == WM_NOTIFY || tmp->message == WM_USER+1)
+			{
+				switch(msg)
+				{
+				case WM_TIMER:
+				{
+					int (*timerfunc)(void *) = tmp->signalfunction;
+					if(tmp->id == (int)mp1)
+					{
+						if(!timerfunc(tmp->data))
+							dw_timer_disconnect(tmp->id);
+						tmp = NULL;
+					}
+					result = 0;
+				}
+				break;
+				case WM_SETFOCUS:
+					{
+						int (*setfocusfunc)(HWND, void *) = (int (*)(HWND, void *))tmp->signalfunction;
+
+						if(hWnd == tmp->window)
+						{
+							result = setfocusfunc(tmp->window, tmp->data);
+							tmp = NULL;
+						}
+					}
+					break;
+				case WM_SIZE:
+					{
+						int (*sizefunc)(HWND, int, int, void *) = tmp->signalfunction;
+
+						if(hWnd == tmp->window)
+						{
+							result = sizefunc(tmp->window, LOWORD(mp2), HIWORD(mp2), tmp->data);
+							tmp = NULL;
+						}
+					}
+					break;
+				case WM_LBUTTONDOWN:
+					{
+						int (*buttonfunc)(HWND, int, int, int, void *) = (int (*)(HWND, int, int, int, void *))tmp->signalfunction;
+
+						if(hWnd == tmp->window)
+						{
+							int button;
+
+							switch(origmsg)
+							{
+							case WM_LBUTTONDOWN:
+								button = 1;
+								break;
+							case WM_RBUTTONDOWN:
+								button = 2;
+								break;
+							case WM_MBUTTONDOWN:
+								button = 3;
+								break;
+							}
+							if(taskbar)
+							{
+								POINT ptl;
+								GetCursorPos(&ptl);
+								result = buttonfunc(tmp->window, ptl.x, ptl.y, button, tmp->data);
+							}
+							else
+							{
+								POINTS pts = MAKEPOINTS(mp2);
+								result = buttonfunc(tmp->window, pts.x, pts.y, button, tmp->data);
+							}
+							tmp = NULL;
+						}
+					}
+					break;
+				case WM_LBUTTONUP:
+					{
+						int (*buttonfunc)(HWND, int, int, int, void *) = (int (*)(HWND, int, int, int, void *))tmp->signalfunction;
+
+						if(hWnd == tmp->window)
+						{
+							int button;
+
+							switch(origmsg)
+							{
+							case WM_LBUTTONUP:
+								button = 1;
+								break;
+							case WM_RBUTTONUP:
+								button = 2;
+								break;
+							case WM_MBUTTONUP:
+								button = 3;
+								break;
+							}
+							if(taskbar)
+							{
+								POINT ptl;
+								GetCursorPos(&ptl);
+								result = buttonfunc(tmp->window, ptl.x, ptl.y, button, tmp->data);
+							}
+							else
+							{
+								POINTS pts = MAKEPOINTS(mp2);
+								result = buttonfunc(tmp->window, pts.x, pts.y, button, tmp->data);
+							}
+							tmp = NULL;
+						}
+					}
+					break;
+				case WM_MOUSEMOVE:
+					{
+						POINTS pts = MAKEPOINTS(mp2);
+						int (*motionfunc)(HWND, int, int, int, void *) = (int (*)(HWND, int, int, int, void *))tmp->signalfunction;
+
+						if(hWnd == tmp->window)
+						{
+							int keys = 0;
+
+							if (mp1 & MK_LBUTTON)
+								keys = DW_BUTTON1_MASK;
+							if (mp1 & MK_RBUTTON)
+								keys |= DW_BUTTON2_MASK;
+							if (mp1 & MK_MBUTTON)
+								keys |= DW_BUTTON3_MASK;
+
+							result = motionfunc(tmp->window, pts.x, pts.y, keys, tmp->data);
+							tmp = NULL;
+						}
+					}
+					break;
+				case WM_CHAR:
+					{
+						int (*keypressfunc)(HWND, char, int, int, void *) = tmp->signalfunction;
+
+						if(hWnd == tmp->window || _toplevel_window(hWnd) == tmp->window)
+						{
+							int special = 0;
+							char ch = 0;
+
+							if(GetAsyncKeyState(VK_SHIFT) & 0x8000)
+								special |= KC_SHIFT;
+							if(GetAsyncKeyState(VK_CONTROL) & 0x8000)
+								special |= KC_CTRL;
+                            if(mp2 & (1 << 29))
+								special |= KC_ALT;
+
+							if(origmsg == WM_CHAR && mp1 < 128)
+								ch = (char)mp1;
+
+							result = keypressfunc(tmp->window, ch, mp1, special, tmp->data);
+							tmp = NULL;
+						}
+					}
+					break;
+				case WM_CLOSE:
+					{
+						int (*closefunc)(HWND, void *) = tmp->signalfunction;
+
+						if(hWnd == tmp->window)
+						{
+							result = closefunc(tmp->window, tmp->data);
+							tmp = NULL;
+						}
+					}
+					break;
+				case WM_PAINT:
+					{
+						PAINTSTRUCT ps;
+						DWExpose exp;
+						int (*exposefunc)(HWND, DWExpose *, void *) = tmp->signalfunction;
+
+						if(hWnd == tmp->window)
+						{
+							BeginPaint(hWnd, &ps);
+							exp.x = ps.rcPaint.left;
+							exp.y = ps.rcPaint.top;
+							exp.width = ps.rcPaint.right - ps.rcPaint.left;
+							exp.height = ps.rcPaint.bottom - ps.rcPaint.top;
+							result = exposefunc(hWnd, &exp, tmp->data);
+							EndPaint(hWnd, &ps);
+						}
+					}
+					break;
+				case WM_NOTIFY:
+					{
+						if(tmp->message == TVN_SELCHANGED ||
+						   tmp->message == NM_RCLICK ||
+						   tmp->message == TVN_ITEMEXPANDED)
+						{
+							NMTREEVIEW FAR *tem=(NMTREEVIEW FAR *)mp2;
+							char tmpbuf[100];
+
+							GetClassName(tem->hdr.hwndFrom, tmpbuf, 99);
+
+							if(strnicmp(tmpbuf, WC_TREEVIEW, strlen(WC_TREEVIEW))==0)
+							{
+								if(tem->hdr.code == TVN_SELCHANGED && tmp->message == TVN_SELCHANGED)
+								{
+									if(tmp->window == tem->hdr.hwndFrom && !dw_window_get_data(tmp->window, "_dw_select_item"))
+									{
+										int (*treeselectfunc)(HWND, HTREEITEM, char *, void *, void *) = tmp->signalfunction;
+										TVITEM tvi;
+										void **ptrs;
+
+										tvi.mask = TVIF_HANDLE;
+										tvi.hItem = tem->itemNew.hItem;
+
+										TreeView_GetItem(tmp->window, &tvi);
+
+										ptrs = (void **)tvi.lParam;
+										if(ptrs)
+											result = treeselectfunc(tmp->window, tem->itemNew.hItem, (char *)ptrs[0], tmp->data, (void *)ptrs[1]);
+
+										tmp = NULL;
+									}
+								}
+								else if(tem->hdr.code == TVN_ITEMEXPANDED && tmp->message == TVN_ITEMEXPANDED)
+								{
+									if(tmp->window == tem->hdr.hwndFrom && tem->action == TVE_EXPAND)
+									{
+										int (*treeexpandfunc)(HWND, HTREEITEM, void *) = tmp->signalfunction;
+
+										result = treeexpandfunc(tmp->window, tem->itemNew.hItem, tmp->data);
+										tmp = NULL;
+									}
+								}
+								else if(tem->hdr.code == NM_RCLICK && tmp->message == NM_RCLICK)
+								{
+									if(tmp->window == tem->hdr.hwndFrom)
+									{
+										int (*containercontextfunc)(HWND, char *, int, int, void *, void *) = tmp->signalfunction;
+										HTREEITEM hti, last;
+										TVITEM tvi;
+										TVHITTESTINFO thi;
+										void **ptrs = NULL;
+										LONG x, y;
+
+										dw_pointer_query_pos(&x, &y);
+
+										thi.pt.x = x;
+										thi.pt.y = y;
+
+										MapWindowPoints(HWND_DESKTOP, tmp->window, &thi.pt, 1);
+
+										last = TreeView_GetSelection(tmp->window);
+										hti = TreeView_HitTest(tmp->window, &thi);
+
+										if(hti)
+										{
+											tvi.mask = TVIF_HANDLE;
+											tvi.hItem = hti;
+
+											TreeView_GetItem(tmp->window, &tvi);
+											TreeView_SelectItem(tmp->window, hti);
+
+											ptrs = (void **)tvi.lParam;
+										}
+										containercontextfunc(tmp->window, ptrs ? (char *)ptrs[0] : NULL, x, y, tmp->data, ptrs ? ptrs[1] : NULL);
+										tmp = NULL;
+									}
+								}
+							}
+							else if(strnicmp(tmpbuf, WC_LISTVIEW, strlen(WC_LISTVIEW)+1)==0)
+							{
+								if(tem->hdr.code == LVN_ITEMCHANGED && tmp->message == TVN_SELCHANGED)
+								{
+									if(tmp->window == tem->hdr.hwndFrom)
+									{
+										LV_ITEM lvi;
+										int iItem;
+
+										iItem = ListView_GetNextItem(tmp->window, -1, LVNI_SELECTED);
+
+										memset(&lvi, 0, sizeof(LV_ITEM));
+
+										if(iItem > -1)
+										{
+											int (*treeselectfunc)(HWND, HWND, char *, void *, void *) = tmp->signalfunction;
+
+											lvi.iItem = iItem;
+											lvi.mask = LVIF_PARAM;
+
+											ListView_GetItem(tmp->window, &lvi);
+
+											/* Seems to be having lParam as 1 which really sucks */
+											if(lvi.lParam < 100)
+												lvi.lParam = 0;
+
+											treeselectfunc(tmp->window, 0, (char *)lvi.lParam, tmp->data, 0);
+											tmp = NULL;
+										}
+									}
+								}
+							}
+						}
+						else if(tmp->message == TCN_SELCHANGE)
+						{
+							NMHDR FAR *tem=(NMHDR FAR *)mp2;
+							if(tmp->window == tem->hwndFrom && tem->code == tmp->message)
+							{
+								int (*switchpagefunc)(HWND, unsigned long, void *) = tmp->signalfunction;
+								unsigned long num=dw_notebook_page_query(tem->hwndFrom);
+								result = switchpagefunc(tem->hwndFrom, num, tmp->data);
+								tmp = NULL;
+							}
+						}
+						else if(tmp->message == LVN_COLUMNCLICK)
+						{
+							NMLISTVIEW FAR *tem=(NMLISTVIEW FAR *)mp2;
+							if(tmp->window == tem->hdr.hwndFrom && tem->hdr.code == tmp->message)
+							{
+								int (*columnclickfunc)(HWND, int, void *) = tmp->signalfunction;
+								result = columnclickfunc(tem->hdr.hwndFrom, tem->iSubItem, tmp->data);
+								tmp = NULL;
+							}
+						}
+					}
+					break;
+				case WM_COMMAND:
+					{
+						int (*clickfunc)(HWND, void *) = tmp->signalfunction;
+						HWND command;
+						ULONG passthru = (ULONG)LOWORD(mp1);
+						ULONG message = HIWORD(mp1);
+
+						command = (HWND)passthru;
+
+						if(message == LBN_SELCHANGE || message == CBN_SELCHANGE)
+						{
+							int (*listboxselectfunc)(HWND, int, void *) = tmp->signalfunction;
+
+							if(tmp->message == LBN_SELCHANGE && tmp->window == (HWND)mp2)
+							{
+								result = listboxselectfunc(tmp->window, dw_listbox_selected(tmp->window), tmp->data);
+								tmp = NULL;
+							}
+						}
+#ifndef WINNT_COMPAT
+						else if(tmp->id && passthru == tmp->id)
+						{
+							HMENU hwndmenu = GetMenu(hWnd), menuowner = _menu_owner((HMENU)tmp->window);
+
+							if(menuowner == hwndmenu || !menuowner)
+							{
+								result = clickfunc(tmp->window, tmp->data);
+								tmp = NULL;
+							}
+						} /* Make sure it's the right window, and the right ID */
+#endif
+						else if(tmp->window < (HWND)65536 && command == tmp->window)
+						{
+							result = clickfunc(popup ? popup : tmp->window, tmp->data);
+							tmp = NULL;
+						}
+					}
+					break;
+				case WM_HSCROLL:
+				case WM_VSCROLL:
+					{
+						char tmpbuf[100];
+                        HWND handle = (HWND)mp2;
+						int (*valuechangefunc)(HWND, int, void *) = tmp->signalfunction;
+
+						GetClassName(handle, tmpbuf, 99);
+
+						if(strnicmp(tmpbuf, TRACKBAR_CLASS, strlen(TRACKBAR_CLASS)+1)==0)
+						{
+
+							if(handle == tmp->window)
+							{
+								int value = (int)SendMessage(handle, TBM_GETPOS, 0, 0);
+								int max = (int)SendMessage(handle, TBM_GETRANGEMAX, 0, 0);
+								ULONG currentstyle = GetWindowLong(handle, GWL_STYLE);
+
+								if(currentstyle & TBS_VERT)
+									result = valuechangefunc(tmp->window, max - value, tmp->data);
+								else
+									result = valuechangefunc(tmp->window, value, tmp->data);
+								tmp = NULL;
+							}
+						}
+						else if(strnicmp(tmpbuf, SCROLLBARCLASSNAME, strlen(SCROLLBARCLASSNAME)+1)==0)
+						{
+							if(handle == tmp->window)
+							{
+								int value = _HandleScroller(handle, (int)HIWORD(mp1), (int)LOWORD(mp1));
+
+								if(value > -1)
+								{
+									dw_scrollbar_set_pos(tmp->window, value);
+									result = valuechangefunc(tmp->window, value, tmp->data);
+								}
+								tmp = NULL;
+								msg = 0;
+							}
+						}
+					}
+					break;
+				}
+			}
+			if(tmp)
+				tmp = tmp->next;
+		}
+		command_active = 0;
+	}
+
+	/* Now that any handlers are done... do normal processing */
+	switch( msg )
+	{
+	case WM_PAINT:
+		{
+			PAINTSTRUCT ps;
+
+			BeginPaint(hWnd, &ps);
+			EndPaint(hWnd, &ps);
+		}
+		break;
+	case WM_SIZE:
+		{
+			static int lastx = -1, lasty = -1;
+			static HWND lasthwnd = 0;
+
+			if(lastx != LOWORD(mp2) || lasty != HIWORD(mp2) || lasthwnd != hWnd)
+			{
+				Box *mybox = (Box *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+
+				if(mybox && mybox->count)
+				{
+					lastx = LOWORD(mp2);
+					lasty = HIWORD(mp2);
+					lasthwnd = hWnd;
+
+					ShowWindow(mybox->items[0].hwnd, SW_HIDE);
+					_do_resize(mybox,LOWORD(mp2),HIWORD(mp2));
+					ShowWindow(mybox->items[0].hwnd, SW_SHOW);
+					return 0;
+				}
+			}
+		}
+		break;
+	case WM_CHAR:
+		if(LOWORD(mp1) == '\t')
+		{
+			if(GetAsyncKeyState(VK_SHIFT) & 0x8000)
+				_shift_focus_back(hWnd);
+			else
+				_shift_focus(hWnd);
+			return TRUE;
+		}
+		break;
+	case WM_USER:
+		windowfunc = (void *)mp1;
+
+		if(windowfunc)
+			windowfunc((void *)mp2);
+		break;
+	case WM_USER+5:
+		_free_menu_data((HMENU)mp1);
+		DestroyMenu((HMENU)mp1);
+		break;
+	case WM_NOTIFY:
+		{
+			NMHDR FAR *tem=(NMHDR FAR *)mp2;
+
+			if(tem->code == TCN_SELCHANGING)
+			{
+				int num=TabCtrl_GetCurSel(tem->hwndFrom);
+				NotebookPage **array = (NotebookPage **)dw_window_get_data(tem->hwndFrom, "_dw_array");
+
+				if(num > -1 && array && array[num])
+					SetParent(array[num]->hwnd, DW_HWND_OBJECT);
+
+			}
+			else if(tem->code == TCN_SELCHANGE)
+			{
+				int num=TabCtrl_GetCurSel(tem->hwndFrom);
+				NotebookPage **array = (NotebookPage **)dw_window_get_data(tem->hwndFrom, "_dw_array");
+
+				if(num > -1 && array && array[num])
+					SetParent(array[num]->hwnd, tem->hwndFrom);
+
+				_resize_notebook_page(tem->hwndFrom, num);
+			}
+		}
+		break;
+	case WM_HSCROLL:
+	case WM_VSCROLL:
+		{
+			HWND handle = (HWND)mp2;
+
+			if(dw_window_get_data(handle, "_dw_scrollbar"))
+			{
+				int value = _HandleScroller(handle, (int)HIWORD(mp1), (int)LOWORD(mp1));
+
+				if(value > -1)
+					dw_scrollbar_set_pos(handle, value);
+			}
+		}
+		break;
+	case WM_GETMINMAXINFO:
+		{
+			MINMAXINFO *info = (MINMAXINFO *)mp2;
+			info->ptMinTrackSize.x = 8;
+			info->ptMinTrackSize.y = 8;
+			return 0;
+		}
+		break;
+	case WM_DESTROY:
+		{
+			HMENU menu = GetMenu(hWnd);
+
+			if(menu)
+				_free_menu_data(menu);
+
+			/* Free memory before destroying */
+			_free_window_memory(hWnd, 0);
+			EnumChildWindows(hWnd, _free_window_memory, 0);
+		}
+		break;
+	case WM_CTLCOLORSTATIC:
+	case WM_CTLCOLORLISTBOX:
+	case WM_CTLCOLORBTN:
+	case WM_CTLCOLOREDIT:
+	case WM_CTLCOLORMSGBOX:
+	case WM_CTLCOLORSCROLLBAR:
+	case WM_CTLCOLORDLG:
+		{
+			ColorInfo *thiscinfo = (ColorInfo *)GetWindowLongPtr((HWND)mp2, GWLP_USERDATA);
+			if(thiscinfo && thiscinfo->fore != -1 && thiscinfo->back != -1)
+			{
+				/* Handle foreground */
+				if(thiscinfo->fore > -1 && thiscinfo->fore < 18)
+				{
+					if(thiscinfo->fore != DW_CLR_DEFAULT)
+					{
+						SetTextColor((HDC)mp1, RGB(_red[thiscinfo->fore],
+												   _green[thiscinfo->fore],
+												   _blue[thiscinfo->fore]));
+					}
+				}
+				else if((thiscinfo->fore & DW_RGB_COLOR) == DW_RGB_COLOR)
+				{
+					SetTextColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->fore),
+											   DW_GREEN_VALUE(thiscinfo->fore),
+											   DW_BLUE_VALUE(thiscinfo->fore)));
+				}
+				/* Handle background */
+				if(thiscinfo->back > -1 && thiscinfo->back < 18)
+				{
+					if(thiscinfo->back == DW_CLR_DEFAULT)
+					{
+						HBRUSH hbr = GetSysColorBrush(COLOR_3DFACE);
+
+						SelectObject((HDC)mp1, hbr);
+						return (LONG)hbr;
+					}
+					else
+					{
+						SetBkColor((HDC)mp1, RGB(_red[thiscinfo->back],
+												 _green[thiscinfo->back],
+												 _blue[thiscinfo->back]));
+						if(thiscinfo->hbrush)
+							DeleteObject(thiscinfo->hbrush);
+						thiscinfo->hbrush = CreateSolidBrush(RGB(_red[thiscinfo->back],
+																 _green[thiscinfo->back],
+																 _blue[thiscinfo->back]));
+						SelectObject((HDC)mp1, thiscinfo->hbrush);
+					}
+					return (LONG)thiscinfo->hbrush;
+				}
+				else if((thiscinfo->back & DW_RGB_COLOR) == DW_RGB_COLOR)
+				{
+					SetBkColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->back),
+												 DW_GREEN_VALUE(thiscinfo->back),
+												 DW_BLUE_VALUE(thiscinfo->back)));
+					if(thiscinfo->hbrush)
+						DeleteObject(thiscinfo->hbrush);
+					thiscinfo->hbrush = CreateSolidBrush(RGB(DW_RED_VALUE(thiscinfo->back),
+															 DW_GREEN_VALUE(thiscinfo->back),
+															 DW_BLUE_VALUE(thiscinfo->back)));
+					SelectObject((HDC)mp1, thiscinfo->hbrush);
+					return (LONG)thiscinfo->hbrush;
+				}
+			}
+
+		}
+		break;
+	}
+	if(result != -1)
+		return result;
+	else
+		return DefWindowProc(hWnd, msg, mp1, mp2);
+}
+
+VOID CALLBACK _TimerProc(HWND hwnd, UINT msg, UINT_PTR idEvent, DWORD dwTime)
+{
+	_wndproc(hwnd, msg, (WPARAM)idEvent, 0);
+}
+
+BOOL CALLBACK _framewndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2)
+{
+	switch( msg )
+	{
+	case WM_LBUTTONDOWN:
+	case WM_MBUTTONDOWN:
+	case WM_RBUTTONDOWN:
+		SetActiveWindow(hWnd);
+		SetFocus(hWnd);
+		break;
+	case WM_COMMAND:
+	case WM_NOTIFY:
+		_wndproc(hWnd, msg, mp1, mp2);
+		break;
+#if 0
+	case WM_ERASEBKGND:
+		{
+			ColorInfo *thiscinfo = (ColorInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+
+			if(thiscinfo && thiscinfo->fore != -1 && thiscinfo->back != -1)
+				return FALSE;
+		}
+		break;
+#endif
+	case WM_PAINT:
+		{
+			ColorInfo *thiscinfo = (ColorInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+
+			if(thiscinfo && thiscinfo->fore != -1 && thiscinfo->back != -1)
+			{
+				PAINTSTRUCT ps;
+				HDC hdcPaint = BeginPaint(hWnd, &ps);
+				int success = FALSE;
+
+				if(thiscinfo && thiscinfo->fore != -1 && thiscinfo->back != -1)
+				{
+					/* Handle foreground */
+					if(thiscinfo->fore > -1 && thiscinfo->fore < 18)
+					{
+						if(thiscinfo->fore != DW_CLR_DEFAULT)
+						{
+							SetTextColor((HDC)mp1, RGB(_red[thiscinfo->fore],
+													   _green[thiscinfo->fore],
+													   _blue[thiscinfo->fore]));
+						}
+					}
+					else if((thiscinfo->fore & DW_RGB_COLOR) == DW_RGB_COLOR)
+					{
+						SetTextColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->fore),
+												   DW_GREEN_VALUE(thiscinfo->fore),
+												   DW_BLUE_VALUE(thiscinfo->fore)));
+					}
+					/* Handle background */
+					if(thiscinfo->back > -1 && thiscinfo->back < 18)
+					{
+						if(thiscinfo->back != DW_CLR_DEFAULT)
+						{
+							SetBkColor((HDC)mp1, RGB(_red[thiscinfo->back],
+													 _green[thiscinfo->back],
+													 _blue[thiscinfo->back]));
+							if(thiscinfo->hbrush)
+								DeleteObject(thiscinfo->hbrush);
+							thiscinfo->hbrush = CreateSolidBrush(RGB(_red[thiscinfo->back],
+																	 _green[thiscinfo->back],
+																	 _blue[thiscinfo->back]));
+							SelectObject(hdcPaint, thiscinfo->hbrush);
+							Rectangle(hdcPaint, ps.rcPaint.left - 1, ps.rcPaint.top - 1, ps.rcPaint.right + 1, ps.rcPaint.bottom + 1);
+							success = TRUE;
+						}
+					}
+					else if((thiscinfo->back & DW_RGB_COLOR) == DW_RGB_COLOR)
+					{
+						SetBkColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->back),
+												 DW_GREEN_VALUE(thiscinfo->back),
+												 DW_BLUE_VALUE(thiscinfo->back)));
+						if(thiscinfo->hbrush)
+							DeleteObject(thiscinfo->hbrush);
+						thiscinfo->hbrush = CreateSolidBrush(RGB(DW_RED_VALUE(thiscinfo->back),
+																 DW_GREEN_VALUE(thiscinfo->back),
+																 DW_BLUE_VALUE(thiscinfo->back)));
+						SelectObject(hdcPaint, thiscinfo->hbrush);
+						Rectangle(hdcPaint, ps.rcPaint.left - 1, ps.rcPaint.top - 1, ps.rcPaint.right + 1, ps.rcPaint.bottom + 1);
+						success = TRUE;
+					}
+				}
+
+				EndPaint(hWnd, &ps);
+				if(success)
+					return FALSE;
+			}
+
+		}
+		break;
+	}
+	return DefWindowProc(hWnd, msg, mp1, mp2);
+}
+
+BOOL CALLBACK _rendwndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2)
+{
+	switch( msg )
+	{
+	case WM_LBUTTONDOWN:
+	case WM_MBUTTONDOWN:
+	case WM_RBUTTONDOWN:
+		SetFocus(hWnd);
+		_wndproc(hWnd, msg, mp1, mp2);
+		break;
+	case WM_LBUTTONUP:
+	case WM_MBUTTONUP:
+	case WM_RBUTTONUP:
+	case WM_MOUSEMOVE:
+	case WM_PAINT:
+	case WM_SIZE:
+	case WM_COMMAND:
+	case WM_CHAR:
+	case WM_KEYDOWN:
+		_wndproc(hWnd, msg, mp1, mp2);
+		break;
+	}
+	return DefWindowProc(hWnd, msg, mp1, mp2);
+}
+
+BOOL CALLBACK _spinnerwndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2)
+{
+	ColorInfo *cinfo;
+
+	cinfo = (ColorInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+
+	if(cinfo)
+	{
+		switch( msg )
+		{
+		case WM_LBUTTONDOWN:
+		case WM_MBUTTONDOWN:
+		case WM_RBUTTONDOWN:
+		case WM_KEYDOWN:
+			{
+				BOOL ret;
+
+				if(!cinfo || !cinfo->pOldProc)
+					ret = DefWindowProc(hWnd, msg, mp1, mp2);
+				ret = CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2);
+
+				/* Tell the edit control that a buttonpress has
+				 * occured and to update it's window title.
+				 */
+				if(cinfo && cinfo->buddy)
+					SendMessage(cinfo->buddy, WM_USER+10, 0, 0);
+
+				SetTimer(hWnd, 100, 100, (TIMERPROC)NULL);
+
+				return ret;
+			}
+			break;
+		case WM_LBUTTONUP:
+		case WM_MBUTTONUP:
+		case WM_RBUTTONUP:
+		case WM_KEYUP:
+			{
+				BOOL ret;
+
+				if(!cinfo || !cinfo->pOldProc)
+					ret = DefWindowProc(hWnd, msg, mp1, mp2);
+				ret = CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2);
+
+				/* Tell the edit control that a buttonpress has
+				 * occured and to update it's window title.
+				 */
+				if(cinfo && cinfo->buddy)
+					SendMessage(cinfo->buddy, WM_USER+10, 0, 0);
+
+				KillTimer(hWnd, 100);
+
+				return ret;
+			}
+			break;
+		case WM_TIMER:
+			{
+				if(mp1 == 100)
+				{
+					BOOL ret;
+
+					if(cinfo && cinfo->buddy)
+						SendMessage(cinfo->buddy, WM_USER+10, 0, 0);
+
+					if(!cinfo || !cinfo->pOldProc)
+						ret = DefWindowProc(hWnd, msg, mp1, mp2);
+					ret = CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2);
+
+					/* Tell the edit control that a buttonpress has
+					 * occured and to update it's window title.
+					 */
+					if(cinfo && cinfo->buddy)
+						SendMessage(cinfo->buddy, WM_USER+10, 0, 0);
+
+					return ret;
+				}
+			}
+			break;
+		case WM_USER+10:
+			{
+				if(cinfo->buddy)
+				{
+					char tempbuf[100] = "";
+					long position;
+
+					GetWindowText(cinfo->buddy, tempbuf, 99);
+
+					position = atol(tempbuf);
+
+					if(IS_IE5PLUS)
+						SendMessage(hWnd, UDM_SETPOS32, 0, (LPARAM)position);
+					else
+						SendMessage(hWnd, UDM_SETPOS, 0, (LPARAM)MAKELONG((short)position, 0));
+				}
+			}
+			break;
+		}
+	}
+
+	if(!cinfo || !cinfo->pOldProc)
+		return DefWindowProc(hWnd, msg, mp1, mp2);
+	return CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2);
+}
+
+void _click_default(HWND handle)
+{
+	char tmpbuf[100];
+
+	GetClassName(handle, tmpbuf, 99);
+
+	/* These are the window classes which can
+	 * obtain input focus.
+	 */
+	if(strnicmp(tmpbuf, BUTTONCLASSNAME, strlen(BUTTONCLASSNAME))==0)
+	{
+		/* Generate click on default item */
+		SignalHandler *tmp = Root;
+
+		/* Find any callbacks for this function */
+		while(tmp)
+		{
+			if(tmp->message == WM_COMMAND)
+			{
+				int (*clickfunc)(HWND, void *) = tmp->signalfunction;
+
+				/* Make sure it's the right window, and the right ID */
+				if(tmp->window == handle)
+				{
+					clickfunc(tmp->window, tmp->data);
+					tmp = NULL;
+				}
+			}
+			if(tmp)
+				tmp= tmp->next;
+		}
+	}
+	else
+		SetFocus(handle);
+}
+
+BOOL CALLBACK _colorwndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2)
+{
+	ColorInfo *cinfo;
+	char tmpbuf[100];
+	WNDPROC pOldProc = 0;
+
+	cinfo = (ColorInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+
+	GetClassName(hWnd, tmpbuf, 99);
+	if(strcmp(tmpbuf, FRAMECLASSNAME) == 0)
+		cinfo = &(((Box *)cinfo)->cinfo);
+
+	if(cinfo)
+	{
+		pOldProc = cinfo->pOldProc;
+
+		switch( msg )
+		{
+		case WM_SETFOCUS:
+            if(cinfo->combo)
+				_wndproc(cinfo->combo, msg, mp1, mp2);
+			else
+				_wndproc(hWnd, msg, mp1, mp2);
+			break;
+		case WM_VSCROLL:
+		case WM_HSCROLL:
+			_wndproc(hWnd, msg, mp1, mp2);
+			break;
+		case WM_KEYDOWN:
+		case WM_KEYUP:
+			{
+				if(mp1 == VK_UP || mp1 == VK_DOWN)
+				{
+					BOOL ret;
+
+					if(!cinfo || !cinfo->pOldProc)
+						ret = DefWindowProc(hWnd, msg, mp1, mp2);
+					ret = CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2);
+
+					/* Tell the spinner control that a keypress has
+					 * occured and to update it's internal value.
+					 */
+					if(cinfo && cinfo->buddy && !cinfo->combo)
+						PostMessage(hWnd, WM_USER+10, 0, 0);
+
+                    if(msg == WM_KEYDOWN)
+						SetTimer(hWnd, 101, 100, (TIMERPROC)NULL);
+                    else
+						KillTimer(hWnd, 101);
+
+					return ret;
+				}
+			}
+			break;
+		case WM_TIMER:
+			{
+				if(mp1 == 101)
+				{
+					BOOL ret;
+
+					if(!cinfo || !cinfo->pOldProc)
+						ret = DefWindowProc(hWnd, msg, mp1, mp2);
+					ret = CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2);
+
+					/* Tell the spinner control that a keypress has
+					 * occured and to update it's internal value.
+					 */
+					if(cinfo && cinfo->buddy && !cinfo->combo)
+						PostMessage(hWnd, WM_USER+10, 0, 0);
+
+					return ret;
+				}
+			}
+			break;
+		case WM_CHAR:
+			_wndproc(hWnd, msg, mp1, mp2);
+			if(LOWORD(mp1) == '\t')
+			{
+				if(GetAsyncKeyState(VK_SHIFT) & 0x8000)
+				{
+					if(cinfo->combo)
+						_shift_focus_back(cinfo->combo);
+					else if(cinfo->buddy)
+						_shift_focus_back(cinfo->buddy);
+					else
+						_shift_focus_back(hWnd);
+				}
+				else
+				{
+					if(cinfo->combo)
+						_shift_focus(cinfo->combo);
+					else if(cinfo->buddy)
+						_shift_focus(cinfo->buddy);
+					else
+						_shift_focus(hWnd);
+				}
+				return FALSE;
+			}
+			else if(LOWORD(mp1) == '\r')
+			{
+				if(cinfo->clickdefault)
+					_click_default(cinfo->clickdefault);
+
+			}
+
+			/* Tell the spinner control that a keypress has
+			 * occured and to update it's internal value.
+			 */
+			if(cinfo->buddy && !cinfo->combo)
+			{
+				if(IsWinNT())
+					PostMessage(cinfo->buddy, WM_USER+10, 0, 0);
+				else
+					SendMessage(cinfo->buddy, WM_USER+10, 0, 0);
+			}
+			break;
+		case WM_USER+10:
+			{
+				if(cinfo->buddy)
+				{
+					long val;
+
+					if(IS_IE5PLUS)
+						val = (long)SendMessage(cinfo->buddy, UDM_GETPOS32, 0, 0);
+					else
+						val = (long)SendMessage(cinfo->buddy, UDM_GETPOS, 0, 0);
+
+					sprintf(tmpbuf, "%d", val);
+					SetWindowText(hWnd, tmpbuf);
+				}
+			}
+			break;
+		case WM_CTLCOLORSTATIC:
+		case WM_CTLCOLORLISTBOX:
+		case WM_CTLCOLORBTN:
+		case WM_CTLCOLOREDIT:
+		case WM_CTLCOLORMSGBOX:
+		case WM_CTLCOLORSCROLLBAR:
+		case WM_CTLCOLORDLG:
+			{
+				ColorInfo *thiscinfo = (ColorInfo *)GetWindowLongPtr((HWND)mp2, GWLP_USERDATA);
+				if(thiscinfo && thiscinfo->fore != -1 && thiscinfo->back != -1)
+				{
+					/* Handle foreground */
+					if(thiscinfo->fore > -1 && thiscinfo->fore < 18)
+					{
+						if(thiscinfo->fore != DW_CLR_DEFAULT)
+						{
+							SetTextColor((HDC)mp1, RGB(_red[thiscinfo->fore],
+													   _green[thiscinfo->fore],
+													   _blue[thiscinfo->fore]));
+						}
+					}
+					else if((thiscinfo->fore & DW_RGB_COLOR) == DW_RGB_COLOR)
+					{
+						SetTextColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->fore),
+												   DW_GREEN_VALUE(thiscinfo->fore),
+												   DW_BLUE_VALUE(thiscinfo->fore)));
+					}
+					/* Handle background */
+					if(thiscinfo->back > -1 && thiscinfo->back < 18)
+					{
+						if(thiscinfo->back == DW_CLR_DEFAULT)
+						{
+							HBRUSH hbr = GetSysColorBrush(COLOR_3DFACE);
+
+							SetBkColor((HDC)mp1, GetSysColor(COLOR_3DFACE));
+
+
+							SelectObject((HDC)mp1, hbr);
+							return (LONG)hbr;
+						}
+						else
+						{
+							SetBkColor((HDC)mp1, RGB(_red[thiscinfo->back],
+													 _green[thiscinfo->back],
+													 _blue[thiscinfo->back]));
+							if(thiscinfo->hbrush)
+								DeleteObject(thiscinfo->hbrush);
+							thiscinfo->hbrush = CreateSolidBrush(RGB(_red[thiscinfo->back],
+																	 _green[thiscinfo->back],
+																	 _blue[thiscinfo->back]));
+							SelectObject((HDC)mp1, thiscinfo->hbrush);
+						}
+						return (LONG)thiscinfo->hbrush;
+					}
+					else if((thiscinfo->back & DW_RGB_COLOR) == DW_RGB_COLOR)
+					{
+						SetBkColor((HDC)mp1, RGB(DW_RED_VALUE(thiscinfo->back),
+												 DW_GREEN_VALUE(thiscinfo->back),
+												 DW_BLUE_VALUE(thiscinfo->back)));
+						if(thiscinfo->hbrush)
+							DeleteObject(thiscinfo->hbrush);
+						thiscinfo->hbrush = CreateSolidBrush(RGB(DW_RED_VALUE(thiscinfo->back),
+																 DW_GREEN_VALUE(thiscinfo->back),
+																 DW_BLUE_VALUE(thiscinfo->back)));
+						SelectObject((HDC)mp1, thiscinfo->hbrush);
+						return (LONG)thiscinfo->hbrush;
+					}
+				}
+
+			}
+			break;
+		}
+	}
+
+	if(!pOldProc)
+		return DefWindowProc(hWnd, msg, mp1, mp2);
+	return CallWindowProc(pOldProc, hWnd, msg, mp1, mp2);
+}
+
+BOOL CALLBACK _containerwndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2)
+{
+	ContainerInfo *cinfo;
+
+	cinfo = (ContainerInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+
+	switch( msg )
+	{
+	case WM_COMMAND:
+	case WM_NOTIFY:
+		_wndproc(hWnd, msg, mp1, mp2);
+		break;
+	case WM_LBUTTONDBLCLK:
+	case WM_CHAR:
+		{
+			LV_ITEM lvi;
+			int iItem;
+
+			if(LOWORD(mp1) == '\t')
+			{
+				if(GetAsyncKeyState(VK_SHIFT) & 0x8000)
+					_shift_focus_back(hWnd);
+				else
+					_shift_focus(hWnd);
+				return FALSE;
+			}
+
+			if(msg == WM_CHAR && (char)mp1 != '\r')
+				break;
+
+			iItem = ListView_GetNextItem(hWnd, -1, LVNI_FOCUSED);
+
+			memset(&lvi, 0, sizeof(LV_ITEM));
+
+			if(iItem > -1)
+			{
+				lvi.iItem = iItem;
+				lvi.mask = LVIF_PARAM;
+
+				ListView_GetItem(hWnd, &lvi);
+			}
+
+			{
+				SignalHandler *tmp = Root;
+
+				while(tmp)
+				{
+					if(tmp->message == NM_DBLCLK && tmp->window == hWnd)
+					{
+						int (*containerselectfunc)(HWND, char *, void *) = tmp->signalfunction;
+
+						/* Seems to be having lParam as 1 which really sucks */
+						if(lvi.lParam < 100)
+							lvi.lParam = 0;
+
+						containerselectfunc(tmp->window, (char *)lvi.lParam, tmp->data);
+						tmp = NULL;
+					}
+					if(tmp)
+						tmp = tmp->next;
+				}
+			}
+		}
+		break;
+	case WM_CONTEXTMENU:
+		{
+			SignalHandler *tmp = Root;
+
+			while(tmp)
+			{
+				if(tmp->message == NM_RCLICK && tmp->window == hWnd)
+				{
+					int (*containercontextfunc)(HWND, char *, int, int, void *, void *) = tmp->signalfunction;
+					LONG x,y;
+					LV_ITEM lvi;
+					int iItem;
+					LVHITTESTINFO lhi;
+
+					dw_pointer_query_pos(&x, &y);
+
+					lhi.pt.x = x;
+					lhi.pt.y = y;
+
+					MapWindowPoints(HWND_DESKTOP, tmp->window, &lhi.pt, 1);
+
+					iItem = ListView_HitTest(tmp->window, &lhi);
+
+					memset(&lvi, 0, sizeof(LV_ITEM));
+
+					if(iItem > -1)
+					{
+						lvi.iItem = iItem;
+						lvi.mask = LVIF_PARAM;
+
+						ListView_GetItem(tmp->window, &lvi);
+						ListView_SetSelectionMark(tmp->window, iItem);
+					}
+
+					/* Seems to be having lParam as 1 which really sucks */
+					if(lvi.lParam < 100)
+						lvi.lParam = 0;
+
+					containercontextfunc(tmp->window, (char *)lvi.lParam, x, y, tmp->data, NULL);
+					tmp = NULL;
+				}
+				if(tmp)
+					tmp = tmp->next;
+			}
+		}
+		break;
+	}
+
+	if(!cinfo || !cinfo->pOldProc)
+		return DefWindowProc(hWnd, msg, mp1, mp2);
+	return CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2);
+}
+
+BOOL CALLBACK _treewndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2)
+{
+	ContainerInfo *cinfo;
+
+	cinfo = (ContainerInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+
+	switch( msg )
+	{
+	case WM_CHAR:
+		if(LOWORD(mp1) == '\t')
+		{
+			if(GetAsyncKeyState(VK_SHIFT) & 0x8000)
+				_shift_focus_back(hWnd);
+			else
+				_shift_focus(hWnd);
+			return FALSE;
+		}
+		break;
+	}
+
+	if(!cinfo || !cinfo->pOldProc)
+		return DefWindowProc(hWnd, msg, mp1, mp2);
+	return CallWindowProc(cinfo->pOldProc, hWnd, msg, mp1, mp2);
+}
+
+void _changebox(Box *thisbox, int percent, int type)
+{
+	int z;
+
+	for(z=0;z<thisbox->count;z++)
+	{
+		if(thisbox->items[z].type == TYPEBOX)
+		{
+			Box *tmp = (Box*)GetWindowLongPtr(thisbox->items[z].hwnd, GWLP_USERDATA);
+			_changebox(tmp, percent, type);
+		}
+		else
+		{
+			if(type == DW_HORZ)
+			{
+				if(thisbox->items[z].hsize == SIZEEXPAND)
+					thisbox->items[z].width = (int)(((float)thisbox->items[z].origwidth) * (((float)percent)/((float)100.0)));
+			}
+			else
+			{
+				if(thisbox->items[z].vsize == SIZEEXPAND)
+					thisbox->items[z].height = (int)(((float)thisbox->items[z].origheight) * (((float)percent)/((float)100.0)));
+			}
+		}
+	}
+}
+
+void _handle_splitbar_resize(HWND hwnd, float percent, int type, int x, int y)
+{
+	if(type == DW_HORZ)
+	{
+		int newx = x;
+		float ratio = (float)percent/(float)100.0;
+		HWND handle1 = (HWND)dw_window_get_data(hwnd, "_dw_topleft");
+		HWND handle2 = (HWND)dw_window_get_data(hwnd, "_dw_bottomright");
+		Box *tmp = (Box *)GetWindowLongPtr(handle1, GWLP_USERDATA);
+
+		newx = (int)((float)newx * ratio) - (SPLITBAR_WIDTH/2);
+
+		ShowWindow(handle1, SW_HIDE);
+		ShowWindow(handle2, SW_HIDE);
+
+		MoveWindow(handle1, 0, 0, newx, y, FALSE);
+		_do_resize(tmp, newx - 1, y - 1);
+
+		tmp = (Box *)GetWindowLongPtr(handle2, GWLP_USERDATA);
+
+		newx = x - newx - SPLITBAR_WIDTH;
+
+		MoveWindow(handle2, x - newx, 0, newx, y, FALSE);
+		_do_resize(tmp, newx - 1, y - 1);
+
+		ShowWindow(handle1, SW_SHOW);
+		ShowWindow(handle2, SW_SHOW);
+
+		dw_window_set_data(hwnd, "_dw_start", (void *)newx);
+	}
+	else
+	{
+		int newy = y;
+		float ratio = (float)(100.0-percent)/(float)100.0;
+		HWND handle1 = (HWND)dw_window_get_data(hwnd, "_dw_bottomright");
+		HWND handle2 = (HWND)dw_window_get_data(hwnd, "_dw_topleft");
+		Box *tmp = (Box *)GetWindowLongPtr(handle1, GWLP_USERDATA);
+
+		newy = (int)((float)newy * ratio) - (SPLITBAR_WIDTH/2);
+
+		ShowWindow(handle1, SW_HIDE);
+		ShowWindow(handle2, SW_HIDE);
+
+		MoveWindow(handle1, 0, y - newy, x, newy, FALSE);
+		_do_resize(tmp, x - 1, newy - 1);
+
+		tmp = (Box *)GetWindowLongPtr(handle2, GWLP_USERDATA);
+
+		newy = y - newy - SPLITBAR_WIDTH;
+
+		MoveWindow(handle2, 0, 0, x, newy, FALSE);
+		_do_resize(tmp, x - 1, newy - 1);
+
+		ShowWindow(handle1, SW_SHOW);
+		ShowWindow(handle2, SW_SHOW);
+
+		dw_window_set_data(hwnd, "_dw_start", (void *)newy);
+	}
+}
+
+/* This handles any activity on the splitbars (sizers) */
+BOOL CALLBACK _splitwndproc(HWND hwnd, UINT msg, WPARAM mp1, LPARAM mp2)
+{
+	float *percent = (float *)dw_window_get_data(hwnd, "_dw_percent");
+	int type = (int)dw_window_get_data(hwnd, "_dw_type");
+	int start = (int)dw_window_get_data(hwnd, "_dw_start");
+
+	switch (msg)
+	{
+	case WM_ACTIVATE:
+	case WM_SETFOCUS:
+		return FALSE;
+
+	case WM_PAINT:
+		{
+			PAINTSTRUCT ps;
+			HDC hdcPaint;
+
+			BeginPaint(hwnd, &ps);
+
+			if((hdcPaint = GetDC(hwnd)) != NULL)
+			{
+				int cx, cy;
+				HBRUSH oldBrush = SelectObject(hdcPaint, GetSysColorBrush(COLOR_3DFACE));
+				HPEN oldPen = SelectObject(hdcPaint, CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DFACE)));
+
+				dw_window_get_pos_size(hwnd, NULL, NULL, &cx, &cy);
+
+				if(type == DW_HORZ)
+					Rectangle(hdcPaint, cx - start - SPLITBAR_WIDTH, 0, cx - start, cy);
+				else
+					Rectangle(hdcPaint, 0, start, cx, start + SPLITBAR_WIDTH);
+
+				SelectObject(hdcPaint, oldBrush);
+				DeleteObject(SelectObject(hdcPaint, oldPen));
+				ReleaseDC(hwnd, hdcPaint);
+			}
+			EndPaint(hwnd, &ps);
+		}
+		break;
+	case WM_LBUTTONDOWN:
+		{
+			SetCapture(hwnd);
+			break;
+		}
+	case WM_LBUTTONUP:
+		{
+            if(GetCapture() == hwnd)
+				ReleaseCapture();
+		}
+		break;
+	case WM_MOUSEMOVE:
+		{
+			if(type == DW_HORZ)
+				SetCursor(LoadCursor(NULL, IDC_SIZEWE));
+			else
+				SetCursor(LoadCursor(NULL, IDC_SIZENS));
+
+			if(GetCapture() == hwnd && percent)
+			{
+				POINT point;
+				RECT rect;
+				static POINT lastpoint;
+
+				GetCursorPos(&point);
+				GetWindowRect(hwnd, &rect);
+
+				if(memcmp(&point, &lastpoint, sizeof(POINT)))
+				{
+					if(PtInRect(&rect, point))
+					{
+						int width = (rect.right - rect.left);
+						int height = (rect.bottom - rect.top);
+
+						if(type == DW_HORZ)
+						{
+							start = point.x - rect.left;
+							if(width - SPLITBAR_WIDTH > 1 && start < width - SPLITBAR_WIDTH)
+								*percent = ((float)start / (float)(width - SPLITBAR_WIDTH)) * 100.0;
+						}
+						else
+						{
+							start = point.y - rect.top;
+							if(height - SPLITBAR_WIDTH > 1 && start < height - SPLITBAR_WIDTH)
+								*percent = ((float)start / (float)(height - SPLITBAR_WIDTH)) * 100.0;
+						}
+						_handle_splitbar_resize(hwnd, *percent, type, width, height);
+					}
+					memcpy(&lastpoint, &point, sizeof(POINT));
+				}
+			}
+			break;
+		}
+	}
+	return DefWindowProc(hwnd, msg, mp1, mp2);
+}
+
+/* This handles drawing the status text areas */
+BOOL CALLBACK _statuswndproc(HWND hwnd, UINT msg, WPARAM mp1, LPARAM mp2)
+{
+	switch (msg)
+	{
+	case WM_SETTEXT:
+		{
+			/* Make sure the control redraws when there is a text change */
+			int ret = (int)DefWindowProc(hwnd, msg, mp1, mp2);
+
+			InvalidateRgn(hwnd, NULL, TRUE);
+			return ret;
+		}
+	case WM_PAINT:
+		{
+			HDC hdcPaint;
+			PAINTSTRUCT ps;
+			RECT rc;
+			unsigned long cx, cy;
+			int threadid = dw_thread_id();
+			char tempbuf[1024] = "";
+			ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+			HFONT hfont = _acquire_font(hwnd, cinfo ? cinfo->fontname : NULL);
+			HFONT oldfont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0);
+
+			dw_window_get_pos_size(hwnd, NULL, NULL, &cx, &cy);
+			GetWindowText(hwnd, tempbuf, 1024);
+
+			hdcPaint = BeginPaint(hwnd, &ps);
+			if(hfont)
+				oldfont = (HFONT)SelectObject(hdcPaint, hfont);
+			rc.top = rc.left = 0;
+			rc.right = cx;
+			rc.bottom = cy;
+			DrawStatusText(hdcPaint, &rc, tempbuf, 0);
+			if(hfont && oldfont)
+				SelectObject(hdcPaint, oldfont);
+			if(hfont)
+				DeleteObject(hfont);
+			EndPaint(hwnd, &ps);
+		}
+		return FALSE;
+	}
+	return DefWindowProc(hwnd, msg, mp1, mp2);
+}
+
+/* Function: _BtProc
+ * Abstract: Subclass procedure for buttons
+ */
+
+BOOL CALLBACK _BtProc(HWND hwnd, ULONG msg, WPARAM mp1, LPARAM mp2)
+{
+	BubbleButton *bubble;
+	static int bMouseOver = 0;
+	POINT point;
+	RECT rect;
+	WNDPROC pOldProc;
+
+	bubble = (BubbleButton *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+	if(!bubble)
+		return DefWindowProc(hwnd, msg, mp1, mp2);
+
+	/* We must save a pointer to the old
+	 * window procedure because if a signal
+	 * handler attached here destroys this
+	 * window it will then be invalid.
+	 */
+	pOldProc = bubble->pOldProc;
+
+	switch(msg)
+	{
+	case WM_CTLCOLORSTATIC:
+	case WM_CTLCOLORLISTBOX:
+	case WM_CTLCOLORBTN:
+	case WM_CTLCOLOREDIT:
+	case WM_CTLCOLORMSGBOX:
+	case WM_CTLCOLORSCROLLBAR:
+	case WM_CTLCOLORDLG:
+		_wndproc(hwnd, msg, mp1, mp2);
+		break;
+	case WM_SETFOCUS:
+		_wndproc(hwnd, msg, mp1, mp2);
+		break;
+	case WM_LBUTTONUP:
+		{
+			SignalHandler *tmp = Root;
+
+			/* Find any callbacks for this function */
+			while(tmp)
+			{
+				if(tmp->message == WM_COMMAND)
+				{
+					int (*clickfunc)(HWND, void *) = tmp->signalfunction;
+
+					/* Make sure it's the right window, and the right ID */
+					if(tmp->window == hwnd)
+					{
+						if(bubble->checkbox)
+							in_checkbox_handler = 1;
+
+						clickfunc(tmp->window, tmp->data);
+
+						if(bubble->checkbox)
+							in_checkbox_handler = 0;
+						tmp = NULL;
+					}
+				}
+				if(tmp)
+					tmp= tmp->next;
+			}
+		}
+		break;
+	case WM_CHAR:
+		{
+			/* A button press should also occur for an ENTER or SPACE press
+			 * while the button has the active input focus.
+			 */
+			if(LOWORD(mp1) == '\r' || LOWORD(mp1) == ' ')
+			{
+				SignalHandler *tmp = Root;
+
+				/* Find any callbacks for this function */
+				while(tmp)
+				{
+					if(tmp->message == WM_COMMAND)
+					{
+						int (*clickfunc)(HWND, void *) = tmp->signalfunction;
+
+						/* Make sure it's the right window, and the right ID */
+						if(tmp->window == hwnd)
+						{
+							clickfunc(tmp->window, tmp->data);
+							tmp = NULL;
+						}
+					}
+					if(tmp)
+						tmp= tmp->next;
+				}
+			}
+			if(LOWORD(mp1) == '\t')
+			{
+				if(GetAsyncKeyState(VK_SHIFT) & 0x8000)
+					_shift_focus_back(hwnd);
+				else
+					_shift_focus(hwnd);
+				return FALSE;
+			}
+		}
+		break;
+	case WM_KEYDOWN:
+		if(mp1 == VK_LEFT || mp1 == VK_UP)
+			_shift_focus_back(hwnd);
+		if(mp1 == VK_RIGHT || mp1 == VK_DOWN)
+			_shift_focus(hwnd);
+		break;
+	case WM_TIMER:
+		if (hwndBubble)
+		{
+			_free_window_memory(hwndBubble, 0);
+			DestroyWindow(hwndBubble);
+			hwndBubble = 0;
+			KillTimer(hwnd, 1);
+		}
+		break;
+
+	case WM_MOUSEMOVE:
+		GetCursorPos(&point);
+		GetWindowRect(hwnd, &rect);
+
+		if(PtInRect(&rect, point))
+		{
+			if(hwnd != GetCapture())
+			{
+				SetCapture(hwnd);
+			}
+			if(!bMouseOver)
+			{
+				bMouseOver = 1;
+				if(!*bubble->bubbletext)
+					break;
+
+				if(hwndBubble)
+				{
+					_free_window_memory(hwndBubble, 0);
+					DestroyWindow(hwndBubble);
+					hwndBubble = 0;
+					KillTimer(hwndBubbleLast, 1);
+				}
+
+				if(!hwndBubble)
+				{
+					POINTL ptlWork = {0,0};
+					ULONG ulColor = DW_CLR_YELLOW;
+					SIZE size;
+					HFONT hFont, oldFont = (HFONT)0;
+					HDC hdc;
+					RECT rect;
+					void *oldproc;
+
+					/* Use the WS_EX_TOOLWINDOW extended style
+					 * so the window doesn't get listed in the
+					 * taskbar.
+					 */
+					hwndBubble = CreateWindowEx(WS_EX_TOOLWINDOW,
+												STATICCLASSNAME,
+												bubble->bubbletext,
+												BS_TEXT | WS_POPUP |
+												WS_BORDER |
+												SS_CENTER,
+												0,0,50,20,
+												HWND_DESKTOP,
+												NULL,
+												DWInstance,
+												NULL);
+
+					dw_window_set_font(hwndBubble, DefaultFont);
+					dw_window_set_color(hwndBubble, DW_CLR_BLACK, DW_CLR_YELLOW);
+
+					hwndBubbleLast = hwnd;
+
+					SetTimer(hwnd, 1, 3000, NULL);
+
+					hFont = (HFONT)SendMessage(hwndBubble, WM_GETFONT, 0, 0);
+
+					hdc = GetDC(hwndBubble);
+
+					if(hFont)
+						oldFont = (HFONT)SelectObject(hdc, hFont);
+
+					GetTextExtentPoint32(hdc, bubble->bubbletext, strlen(bubble->bubbletext), &size);
+
+					if(hFont)
+						SelectObject(hdc, oldFont);
+
+					MapWindowPoints(hwnd, HWND_DESKTOP, (LPPOINT)&ptlWork, 1);
+
+					GetWindowRect(hwnd, &rect);
+
+					SetWindowPos(hwndBubble,
+								 HWND_TOP,
+								 ptlWork.x,
+								 ptlWork.y + (rect.bottom-rect.top) + 1,
+								 size.cx + 8,
+								 size.cy + 2,
+								 SWP_NOACTIVATE | SWP_SHOWWINDOW);
+
+					ReleaseDC(hwndBubble, hdc);
+				}
+			}
+		}
+		else{
+			/* Calling ReleaseCapture in Win95 also causes WM_CAPTURECHANGED
+			 * to be sent.  Be sure to account for that.
+			 */
+			ReleaseCapture();
+
+			if(bMouseOver)
+			{
+				bMouseOver = 0;
+				_free_window_memory(hwndBubble, 0);
+				DestroyWindow(hwndBubble);
+				hwndBubble = 0;
+				KillTimer(hwndBubbleLast, 1);
+			}
+		}
+		break;
+	case WM_CAPTURECHANGED:
+		/* This message means we are losing the capture for some reason
+		 * Either because we intentionally lost it or another window
+		 * stole it
+		 */
+		if(bMouseOver)
+		{
+			bMouseOver = 0;
+			_free_window_memory(hwndBubble, 0);
+			DestroyWindow(hwndBubble);
+			hwndBubble = 0;
+			KillTimer(hwndBubbleLast, 1);
+		}
+		break;
+	}
+
+	if(!pOldProc)
+		return DefWindowProc(hwnd, msg, mp1, mp2);
+	return CallWindowProc(pOldProc, hwnd, msg, mp1, mp2);
+}
+
+/* This function recalculates a notebook page for example
+ * during switching of notebook pages.
+ */
+void _resize_notebook_page(HWND handle, int pageid)
+{
+	RECT rect;
+	NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array");
+
+	if(array && array[pageid])
+	{
+		Box *box = (Box *)GetWindowLongPtr(array[pageid]->hwnd, GWLP_USERDATA);
+
+		GetClientRect(handle,&rect);
+		TabCtrl_AdjustRect(handle,FALSE,&rect);
+		MoveWindow(array[pageid]->hwnd, rect.left, rect.top,
+				   rect.right - rect.left, rect.bottom-rect.top, TRUE);
+		if(box && box->count)
+		{
+			ShowWindow(box->items[0].hwnd, SW_HIDE);
+			_do_resize(box, rect.right - rect.left, rect.bottom - rect.top);
+			ShowWindow(box->items[0].hwnd, SW_SHOW);
+		}
+
+		ShowWindow(array[pageid]->hwnd, SW_SHOWNORMAL);
+	}
+}
+
+/*
+ * Initializes the Dynamic Windows engine.
+ * Parameters:
+ *           newthread: True if this is the only thread.
+ *                      False if there is already a message loop running.
+ */
+int API dw_init(int newthread, int argc, char *argv[])
+{
+	WNDCLASS wc;
+	int z;
+	INITCOMMONCONTROLSEX icc;
+
+	icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
+	icc.dwICC = ICC_WIN95_CLASSES;
+
+	InitCommonControlsEx(&icc);
+
+	memset(lookup, 0, sizeof(HICON) * ICON_INDEX_LIMIT);
+
+	/* Register the generic Dynamic Windows class */
+	memset(&wc, 0, sizeof(WNDCLASS));
+	wc.style = CS_DBLCLKS;
+	wc.lpfnWndProc = (WNDPROC)_wndproc;
+	wc.cbClsExtra = 0;
+	wc.cbWndExtra = 32;
+	wc.hbrBackground = NULL;
+	wc.lpszMenuName = NULL;
+	wc.lpszClassName = ClassName;
+
+	RegisterClass(&wc);
+
+	/* Register the splitbar control */
+	memset(&wc, 0, sizeof(WNDCLASS));
+	wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
+	wc.lpfnWndProc = (WNDPROC)_splitwndproc;
+	wc.cbClsExtra = 0;
+	wc.cbWndExtra = 0;
+	wc.hbrBackground = NULL;
+	wc.lpszMenuName = NULL;
+	wc.lpszClassName = SplitbarClassName;
+
+	RegisterClass(&wc);
+
+	/* Register a frame control like on OS/2 */
+	memset(&wc, 0, sizeof(WNDCLASS));
+	wc.style = CS_DBLCLKS;
+	wc.lpfnWndProc = (WNDPROC)_framewndproc;
+	wc.cbClsExtra = 0;
+	wc.cbWndExtra = 32;
+	wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_3DFACE);
+	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+	wc.lpszMenuName = NULL;
+	wc.lpszClassName = FRAMECLASSNAME;
+
+	RegisterClass(&wc);
+
+	/* Create a set of brushes using the default OS/2 and DOS colors */
+	for(z=0;z<18;z++)
+		_colors[z] = CreateSolidBrush(RGB(_red[z],_green[z],_blue[z]));
+
+	/* Register an Object Windows class like OS/2 and Win2k+
+	 * so similar functionality can be used on earlier releases
+	 * of Windows.
+	 */
+	memset(&wc, 0, sizeof(WNDCLASS));
+	wc.style = 0;
+	wc.lpfnWndProc = (WNDPROC)_wndproc;
+	wc.cbClsExtra = 0;
+	wc.cbWndExtra = 0;
+	wc.hbrBackground = NULL;
+	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+	wc.lpszMenuName = NULL;
+	wc.lpszClassName = ObjectClassName;
+
+	RegisterClass(&wc);
+
+	/* Since Windows 95/98/NT don't have a HWND_OBJECT class
+	 * also known as a input only window, I will create a
+	 * temporary window that isn't visible and really does nothing
+	 * except temporarily hold the child windows before they are
+	 * packed into their correct parent.
+	 */
+
+	DW_HWND_OBJECT = CreateWindow(ObjectClassName, "", 0, 0, 0,
+								  0, 0, HWND_DESKTOP, NULL, DWInstance, NULL);
+
+	if(!DW_HWND_OBJECT)
+	{
+		dw_messagebox("Dynamic Windows", DW_MB_OK|DW_MB_ERROR, "Could not initialize the object window. error code %d", GetLastError());
+		exit(1);
+	}
+
+	/* We need the version to check capability like up-down controls */
+	dwVersion = GetVersion();
+	dwComctlVer = GetDllVersion(TEXT("comctl32.dll"));
+
+	for(z=0;z<THREAD_LIMIT;z++)
+	{
+		_foreground[z] = RGB(128,128,128);
+		_background[z] = DW_RGB_TRANSPARENT;
+		_hPen[z] = CreatePen(PS_SOLID, 1, _foreground[z]);
+		_hBrush[z] = CreateSolidBrush(_foreground[z]);
+	}
+
+	return 0;
+}
+
+/*
+ * Runs a message loop for Dynamic Windows.
+ */
+void API dw_main(void)
+{
+	MSG msg;
+
+	_dwtid = dw_thread_id();
+
+	while(GetMessage(&msg, NULL, 0, 0))
+	{
+		TranslateMessage(&msg);
+		DispatchMessage(&msg);
+	}
+}
+
+/*
+ * Runs a message loop for Dynamic Windows, for a period of milliseconds.
+ * Parameters:
+ *           milliseconds: Number of milliseconds to run the loop for.
+ */
+void API dw_main_sleep(int milliseconds)
+{
+	MSG msg;
+	double start = (double)clock();
+
+	while(((clock() - start) / (CLOCKS_PER_SEC/1000)) <= milliseconds)
+	{
+		if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
+		{
+			GetMessage(&msg, NULL, 0, 0);
+			TranslateMessage(&msg);
+			DispatchMessage(&msg);
+		}
+		else
+			Sleep(1);
+	}
+}
+
+/*
+ * Processes a single message iteration and returns.
+ */
+void API dw_main_iteration(void)
+{
+	MSG msg;
+
+	_dwtid = dw_thread_id();
+
+	if(GetMessage(&msg, NULL, 0, 0))
+	{
+		TranslateMessage(&msg);
+		DispatchMessage(&msg);
+	}
+}
+
+/*
+ * Free's memory allocated by dynamic windows.
+ * Parameters:
+ *           ptr: Pointer to dynamic windows allocated
+ *                memory to be free()'d.
+ */
+void API dw_free(void *ptr)
+{
+	free(ptr);
+}
+
+/*
+ * Allocates and initializes a dialog struct.
+ * Parameters:
+ *           data: User defined data to be passed to functions.
+ */
+DWDialog * API dw_dialog_new(void *data)
+{
+	DWDialog *tmp = malloc(sizeof(DWDialog));
+
+	tmp->eve = dw_event_new();
+	dw_event_reset(tmp->eve);
+	tmp->data = data;
+	tmp->done = FALSE;
+	tmp->result = NULL;
+
+    return tmp;
+}
+
+/*
+ * Accepts a dialog struct and returns the given data to the
+ * initial called of dw_dialog_wait().
+ * Parameters:
+ *           dialog: Pointer to a dialog struct aquired by dw_dialog_new).
+ *           result: Data to be returned by dw_dialog_wait().
+ */
+int API dw_dialog_dismiss(DWDialog *dialog, void *result)
+{
+	dialog->result = result;
+	dw_event_post(dialog->eve);
+	dialog->done = TRUE;
+	return 0;
+}
+
+/*
+ * Accepts a dialog struct waits for dw_dialog_dismiss() to be
+ * called by a signal handler with the given dialog struct.
+ * Parameters:
+ *           dialog: Pointer to a dialog struct aquired by dw_dialog_new).
+ */
+void * API dw_dialog_wait(DWDialog *dialog)
+{
+	MSG msg;
+	void *tmp;
+
+	while (GetMessage(&msg,NULL,0,0))
+	{
+		if(msg.hwnd == NULL && msg.message == WM_TIMER)
+			_wndproc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
+		TranslateMessage(&msg);
+		DispatchMessage(&msg);
+		if(dialog->done)
+			break;
+	}
+	dw_event_close(&dialog->eve);
+	tmp = dialog->result;
+	free(dialog);
+	return tmp;
+}
+
+/*
+ * Displays a Message Box with given text and title..
+ * Parameters:
+ *           title: The title of the message box.
+ *           format: printf style format string.
+ *           ...: Additional variables for use in the format.
+ */
+int API dw_messagebox(char *title, int flags, char *format, ...)
+{
+	va_list args;
+	char outbuf[256];
+	int rc;
+
+	va_start(args, format);
+	vsprintf(outbuf, format, args);
+	va_end(args);
+
+	rc = MessageBox(HWND_DESKTOP, outbuf, title, flags);
+	if(rc == IDOK)
+		return DW_MB_RETURN_OK;
+	else if(rc == IDYES)
+		return DW_MB_RETURN_YES;
+	else if(rc == IDNO)
+		return DW_MB_RETURN_NO;
+	else if(rc == IDCANCEL)
+		return DW_MB_RETURN_CANCEL;
+	else return 0;
+}
+
+/*
+ * Minimizes or Iconifies a top-level window.
+ * Parameters:
+ *           handle: The window handle to minimize.
+ */
+int API dw_window_minimize(HWND handle)
+{
+	return ShowWindow(handle, SW_MINIMIZE);
+}
+
+/*
+ * Makes the window topmost.
+ * Parameters:
+ *           handle: The window handle to make topmost.
+ */
+int API dw_window_raise(HWND handle)
+{
+	return SetWindowPos(handle, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+}
+
+/*
+ * Makes the window bottommost.
+ * Parameters:
+ *           handle: The window handle to make bottommost.
+ */
+int API dw_window_lower(HWND handle)
+{
+	return SetWindowPos(handle, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+}
+
+/*
+ * Makes the window visible.
+ * Parameters:
+ *           handle: The window handle to make visible.
+ */
+int API dw_window_show(HWND handle)
+{
+	int rc = ShowWindow(handle, SW_SHOW);
+	SetFocus(handle);
+	_initial_focus(handle);
+	return rc;
+}
+
+/*
+ * Makes the window invisible.
+ * Parameters:
+ *           handle: The window handle to make visible.
+ */
+int API dw_window_hide(HWND handle)
+{
+	return ShowWindow(handle, SW_HIDE);
+}
+
+/*
+ * Destroys a window and all of it's children.
+ * Parameters:
+ *           handle: The window handle to destroy.
+ */
+int API dw_window_destroy(HWND handle)
+{
+	HWND parent = GetParent(handle);
+	Box *thisbox = (Box *)GetWindowLongPtr(parent, GWLP_USERDATA);
+#ifndef WINNT_COMPAT
+	HMENU menu = GetMenu(handle);
+
+	if(menu)
+		_free_menu_data(menu);
+#endif
+
+	if(parent != HWND_DESKTOP && thisbox && thisbox->count)
+	{
+		int z, index = -1;
+		Item *tmpitem, *thisitem = thisbox->items;
+
+		for(z=0;z<thisbox->count;z++)
+		{
+			if(thisitem[z].hwnd == handle)
+				index = z;
+		}
+
+		if(index == -1)
+			return 0;
+
+		tmpitem = malloc(sizeof(Item)*(thisbox->count-1));
+
+		/* Copy all but the current entry to the new list */
+		for(z=0;z<index;z++)
+		{
+			tmpitem[z] = thisitem[z];
+		}
+		for(z=index+1;z<thisbox->count;z++)
+		{
+			tmpitem[z-1] = thisitem[z];
+		}
+
+		thisbox->items = tmpitem;
+		free(thisitem);
+		thisbox->count--;
+		_free_window_memory(handle, 0);
+		EnumChildWindows(handle, _free_window_memory, 0);
+	}
+	return DestroyWindow(handle);
+}
+
+/* Causes entire window to be invalidated and redrawn.
+ * Parameters:
+ *           handle: Toplevel window handle to be redrawn.
+ */
+void API dw_window_redraw(HWND handle)
+{
+	Box *mybox = (Box *)GetWindowLongPtr(handle, GWLP_USERDATA);
+
+	if(mybox)
+	{
+		RECT rect;
+		int istoplevel = (GetParent(handle) == HWND_DESKTOP);
+
+		GetClientRect(handle, &rect);
+
+		ShowWindow(istoplevel ? mybox->items[0].hwnd : handle, SW_HIDE);
+		_do_resize(mybox, rect.right - rect.left, rect.bottom - rect.top);
+		ShowWindow(istoplevel ? mybox->items[0].hwnd : handle, SW_SHOW);
+	}
+}
+
+int instring(char *text, char *buffer)
+{
+	int z, len = strlen(text), buflen = strlen(buffer);
+
+	if(buflen > len)
+	{
+		for(z=0;z<=(buflen-len);z++)
+		{
+			if(memcmp(text, &buffer[z], len) == 0)
+				return z;
+		}
+	}
+	return 0;
+}
+
+/*
+ * Changes a window's parent to newparent.
+ * Parameters:
+ *           handle: The window handle to destroy.
+ *           newparent: The window's new parent window.
+ */
+void API dw_window_reparent(HWND handle, HWND newparent)
+{
+	SetParent(handle, newparent);
+}
+
+HFONT _acquire_font(HWND handle, char *fontname)
+{
+	HFONT hfont = 0;
+
+	if(fontname != DefaultFont && fontname[0])
+	{
+        int Italic, Bold;
+		char *myFontName;
+		int z, size = 9;
+		LOGFONT lf;
+#if 0
+		HDC hDC = GetDC(handle);
+#endif
+		for(z=0;z<strlen(fontname);z++)
+		{
+			if(fontname[z]=='.')
+				break;
+		}
+		size = atoi(fontname) + 5;
+		Italic = instring(" Italic", &fontname[z+1]);
+		Bold = instring(" Bold", &fontname[z+1]);
+#if 0
+		lf.lfHeight = -MulDiv(size, GetDeviceCaps(hDC, LOGPIXELSY), 72);
+#endif
+		lf.lfHeight = size;
+		lf.lfWidth = 0;
+		lf.lfEscapement = 0;
+		lf.lfOrientation = 0;
+		lf.lfItalic = Italic ? TRUE : FALSE;
+		lf.lfUnderline = 0;
+		lf.lfStrikeOut = 0;
+		lf.lfWeight = Bold ? FW_BOLD : FW_NORMAL;
+		lf.lfCharSet = DEFAULT_CHARSET;
+		lf.lfOutPrecision = 0;
+		lf.lfClipPrecision = 0;
+		lf.lfQuality = DEFAULT_QUALITY;
+		lf.lfPitchAndFamily = DEFAULT_PITCH | FW_DONTCARE;
+		/* 
+		 * remove any font modifiers
+		 */
+		myFontName = strdup(&fontname[z+1]);
+		if(Italic)
+			myFontName[Italic] = 0;
+		if(Bold)
+			myFontName[Bold] = 0;
+		strcpy(lf.lfFaceName, myFontName);
+		free(myFontName);
+
+		hfont = CreateFontIndirect(&lf);
+#if 0
+		ReleaseDC(handle, hDC);
+#endif
+	}
+	if(!hfont)
+		hfont = GetStockObject(DEFAULT_GUI_FONT);
+	return hfont;
+}
+
+/*
+ * Sets the font used by a specified window (widget) handle.
+ * Parameters:
+ *          handle: The window (widget) handle.
+ *          fontname: Name and size of the font in the form "size.fontname"
+ */
+int API dw_window_set_font(HWND handle, char *fontname)
+{
+	HFONT oldfont = (HFONT)SendMessage(handle, WM_GETFONT, 0, 0);
+	HFONT hfont = _acquire_font(handle, fontname);
+	ColorInfo *cinfo;
+
+	cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA);
+
+	if(fontname)
+	{
+		if(cinfo)
+		{
+			strcpy(cinfo->fontname, fontname);
+			if(!oldfont)
+				oldfont = cinfo->hfont;
+			cinfo->hfont = hfont;
+		}
+		else
+		{
+			cinfo = calloc(1, sizeof(ColorInfo));
+			cinfo->fore = cinfo->back = -1;
+
+			strcpy(cinfo->fontname, fontname);
+
+			cinfo->pOldProc = SubclassWindow(handle, _colorwndproc);
+			SetWindowLongPtr(handle, GWLP_USERDATA, (LONG_PTR)cinfo);
+		}
+	}
+	SendMessage(handle, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
+	if(oldfont)
+		DeleteObject(oldfont);
+	return 0;
+}
+
+/*
+ * Sets the colors used by a specified window (widget) handle.
+ * Parameters:
+ *          handle: The window (widget) handle.
+ *          fore: Foreground color in RGB format.
+ *          back: Background color in RGB format.
+ */
+int API dw_window_set_color(HWND handle, ULONG fore, ULONG back)
+{
+	ColorInfo *cinfo;
+	char tmpbuf[100];
+
+	cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA);
+
+	GetClassName(handle, tmpbuf, 99);
+
+	if(strnicmp(tmpbuf, WC_LISTVIEW, strlen(WC_LISTVIEW))==0)
+	{
+		fore = _internal_color(fore);
+		back = _internal_color(back);
+
+		ListView_SetTextColor(handle, RGB(DW_RED_VALUE(fore),
+										  DW_GREEN_VALUE(fore),
+										  DW_BLUE_VALUE(fore)));
+		ListView_SetTextBkColor(handle, RGB(DW_RED_VALUE(back),
+											DW_GREEN_VALUE(back),
+											DW_BLUE_VALUE(back)));
+		ListView_SetBkColor(handle, RGB(DW_RED_VALUE(back),
+										DW_GREEN_VALUE(back),
+										DW_BLUE_VALUE(back)));
+		InvalidateRgn(handle, NULL, TRUE);
+		return TRUE;
+	}
+
+	if(cinfo)
+	{
+		cinfo->fore = fore;
+		cinfo->back = back;
+	}
+	else
+	{
+		cinfo = calloc(1, sizeof(ColorInfo));
+
+		cinfo->fore = fore;
+		cinfo->back = back;
+
+		cinfo->pOldProc = SubclassWindow(handle, _colorwndproc);
+		SetWindowLongPtr(handle, GWLP_USERDATA, (LONG_PTR)cinfo);
+	}
+	InvalidateRgn(handle, NULL, TRUE);
+	return TRUE;
+}
+
+/*
+ * Sets the font used by a specified window (widget) handle.
+ * Parameters:
+ *          handle: The window (widget) handle.
+ *          border: Size of the window border in pixels.
+ */
+int API dw_window_set_border(HWND handle, int border)
+{
+	return 0;
+}
+
+/*
+ * Captures the mouse input to this window.
+ * Parameters:
+ *       handle: Handle to receive mouse input.
+ */
+void API dw_window_capture(HWND handle)
+{
+	SetCapture(handle);
+}
+
+/*
+ * Releases previous mouse capture.
+ */
+void API dw_window_release(void)
+{
+	ReleaseCapture();
+}
+
+/*
+ * Changes the appearance of the mouse pointer.
+ * Parameters:
+ *       handle: Handle to widget for which to change.
+ *       cursortype: ID of the pointer you want.
+ */
+void API dw_window_pointer(HWND handle, int pointertype)
+{
+/*
+	if(pointertype == DW_POINTER_ARROW)
+		SetClassLong( handle, GCL_HCURSOR, LoadCursor( NULL, IDC_ARROW));
+	else if(pointertype == DW_POINTER_CLOCK)
+		SetClassLong( handle, GCL_HCURSOR, LoadCursor( NULL, IDC_WAIT));
+	else
+*/
+	SetCursor(pointertype < 65536 ? LoadCursor(NULL, MAKEINTRESOURCE(pointertype)) : (HCURSOR)pointertype);
+}
+
+/*
+ * Create a new Window Frame.
+ * Parameters:
+ *       owner: The Owner's window handle or HWND_DESKTOP.
+ *       title: The Window title.
+ *       flStyle: Style flags, see the DW reference.
+ */
+HWND API dw_window_new(HWND hwndOwner, char *title, ULONG flStyle)
+{
+	HWND hwndframe;
+	Box *newbox = calloc(sizeof(Box), 1);
+	ULONG flStyleEx = 0;
+
+	newbox->pad = 0;
+	newbox->type = DW_VERT;
+	newbox->count = 0;
+	newbox->cinfo.fore = newbox->cinfo.back = -1;
+
+	if(hwndOwner)
+		flStyleEx |= WS_EX_MDICHILD;
+
+	if(!(flStyle & WS_CAPTION))
+		flStyle |= WS_POPUPWINDOW;
+
+	if(flStyle & DW_FCF_TASKLIST)
+	{
+		ULONG newflags = (flStyle | WS_CLIPCHILDREN) & ~DW_FCF_TASKLIST;
+
+		hwndframe = CreateWindowEx(flStyleEx, ClassName, title, newflags, CW_USEDEFAULT, CW_USEDEFAULT,
+								   CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner, NULL, DWInstance, NULL);
+	}
+	else
+	{
+		flStyleEx |= WS_EX_TOOLWINDOW;
+
+		hwndframe = CreateWindowEx(flStyleEx, ClassName, title, flStyle | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT,
+								   CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner, NULL, DWInstance, NULL);
+	}
+	SetWindowLongPtr(hwndframe, GWLP_USERDATA, (LONG_PTR)newbox);
+
+#if 0
+	if(hwndOwner)
+		SetParent(hwndframe, hwndOwner);
+#endif
+
+	return hwndframe;
+}
+
+/*
+ * Create a new Box to be packed.
+ * Parameters:
+ *       type: Either DW_VERT (vertical) or DW_HORZ (horizontal).
+ *       pad: Number of pixels to pad around the box.
+ */
+HWND API dw_box_new(int type, int pad)
+{
+	Box *newbox = calloc(sizeof(Box), 1);
+	HWND hwndframe;
+
+	newbox->pad = pad;
+	newbox->type = type;
+	newbox->count = 0;
+	newbox->grouphwnd = (HWND)NULL;
+	newbox->cinfo.fore = newbox->cinfo.back = -1;
+
+	hwndframe = CreateWindow(FRAMECLASSNAME,
+							 "",
+							 WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN,
+							 0,0,2000,1000,
+							 DW_HWND_OBJECT,
+							 NULL,
+							 DWInstance,
+							 NULL);
+
+	newbox->cinfo.pOldProc = SubclassWindow(hwndframe, _colorwndproc);
+	newbox->cinfo.fore = newbox->cinfo.back = -1;
+
+	SetWindowLongPtr(hwndframe, GWLP_USERDATA, (LONG_PTR)newbox);
+	return hwndframe;
+}
+
+/*
+ * Create a new Group Box to be packed.
+ * Parameters:
+ *       type: Either DW_VERT (vertical) or DW_HORZ (horizontal).
+ *       pad: Number of pixels to pad around the box.
+ *       title: Text to be displayined in the group outline.
+ */
+HWND API dw_groupbox_new(int type, int pad, char *title)
+{
+	Box *newbox = calloc(sizeof(Box), 1);
+	HWND hwndframe;
+
+	newbox->pad = pad;
+	newbox->type = type;
+	newbox->count = 0;
+	newbox->cinfo.fore = newbox->cinfo.back = -1;
+
+	hwndframe = CreateWindow(FRAMECLASSNAME,
+							 "",
+							 WS_VISIBLE | WS_CHILD,
+							 0,0,2000,1000,
+							 DW_HWND_OBJECT,
+							 NULL,
+							 DWInstance,
+							 NULL);
+
+	newbox->grouphwnd = CreateWindow(BUTTONCLASSNAME,
+									 title,
+									 WS_CHILD | BS_GROUPBOX |
+									 WS_VISIBLE | WS_CLIPCHILDREN,
+									 0,0,2000,1000,
+									 hwndframe,
+									 NULL,
+									 DWInstance,
+									 NULL);
+
+	SetWindowLongPtr(hwndframe, GWLP_USERDATA, (LONG_PTR)newbox);
+	dw_window_set_font(newbox->grouphwnd, DefaultFont);
+	return hwndframe;
+}
+
+/*
+ * Create a new MDI Frame to be packed.
+ * Parameters:
+ *       id: An ID to be used with dw_window_from_id or 0L.
+ */
+HWND API dw_mdi_new(unsigned long id)
+{
+	CLIENTCREATESTRUCT ccs;
+	HWND hwndframe;
+
+	ccs.hWindowMenu = NULL;
+	ccs.idFirstChild = 0;
+
+	hwndframe = CreateWindow("MDICLIENT",
+							 "",
+							 WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS,
+							 0,0,2000,1000,
+							 DW_HWND_OBJECT,
+							 (HMENU)id,
+							 DWInstance,
+							 &ccs);
+	return hwndframe;
+}
+
+/*
+ * Create a bitmap object to be packed.
+ * Parameters:
+ *       id: An ID to be used with dw_window_from_id or 0L.
+ */
+HWND API dw_bitmap_new(ULONG id)
+{
+	return CreateWindow(STATICCLASSNAME,
+						"",
+						SS_BITMAP | WS_VISIBLE |
+						WS_CHILD | WS_CLIPCHILDREN,
+						0,0,2000,1000,
+						DW_HWND_OBJECT,
+						(HMENU)id,
+						DWInstance,
+						NULL);
+}
+
+/*
+ * Create a notebook object to be packed.
+ * Parameters:
+ *       id: An ID to be used for getting the resource from the
+ *           resource file.
+ */
+HWND API dw_notebook_new(ULONG id, int top)
+{
+	ULONG flags = 0;
+	HWND tmp;
+	NotebookPage **array = calloc(256, sizeof(NotebookPage *));
+
+	if(!top)
+		flags = TCS_BOTTOM;
+
+	tmp = CreateWindow(WC_TABCONTROL,
+					   "",
+					   WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN,
+					   0,0,2000,1000,
+					   DW_HWND_OBJECT,
+					   (HMENU)id,
+					   DWInstance,
+					   NULL);
+	dw_window_set_data(tmp, "_dw_array", (void *)array);
+	dw_window_set_font(tmp, DefaultFont);
+	return tmp;
+}
+
+/*
+ * Create a menu object to be popped up.
+ * Parameters:
+ *       id: An ID to be used for getting the resource from the
+ *           resource file.
+ */
+HMENUI API dw_menu_new(ULONG id)
+{
+	return (HMENUI)CreatePopupMenu();
+}
+
+/*
+ * Create a menubar on a window.
+ * Parameters:
+ *       location: Handle of a window frame to be attached to.
+ */
+HMENUI API dw_menubar_new(HWND location)
+{
+	HMENUI tmp;
+
+	tmp = (HMENUI)CreateMenu();
+
+#ifndef WINNT_COMPAT
+	{
+		MENUINFO mi;
+
+		mi.cbSize = sizeof(MENUINFO);
+		mi.fMask = MIM_MENUDATA;
+		mi.dwMenuData = (ULONG_PTR)1;
+
+		SetMenuInfo((HMENU)tmp, &mi);
+	}
+#endif
+
+	dw_window_set_data(location, "_dw_menu", (void *)tmp);
+
+	SetMenu(location, (HMENU)tmp);
+	return location;
+}
+
+/*
+ * Destroys a menu created with dw_menubar_new or dw_menu_new.
+ * Parameters:
+ *       menu: Handle of a menu.
+ */
+void API dw_menu_destroy(HMENUI *menu)
+{
+	if(menu)
+	{
+		HMENU mymenu = (HMENU)*menu;
+
+		if(IsWindow((HWND)mymenu) && !IsMenu(mymenu))
+			mymenu = (HMENU)dw_window_get_data((HWND)mymenu, "_dw_menu");
+        if(IsMenu(mymenu))
+			DestroyMenu(mymenu);
+	}
+}
+
+/*
+ * Adds a menuitem or submenu to an existing menu.
+ * Parameters:
+ *       menu: The handle the the existing menu.
+ *       title: The title text on the menu item to be added.
+ *       id: An ID to be used for message passing.
+ *       end: If TRUE memu is positioned at the end of the menu.
+ *       check: If TRUE menu is "check"able.
+ *       flags: Extended attributes to set on the menu.
+ *       submenu: Handle to an existing menu to be a submenu or NULL.
+ */
+HWND API dw_menu_append_item(HMENUI menux, char *title, ULONG id, ULONG flags, int end, int check, HMENUI submenu)
+{
+	MENUITEMINFO mii;
+	HMENU mymenu = (HMENU)menux;
+#ifndef WINNT_COMPAT
+	char buffer[15];
+#endif
+
+	if(IsWindow(menux) && !IsMenu(mymenu))
+		mymenu = (HMENU)dw_window_get_data(menux, "_dw_menu");
+
+	mii.cbSize = sizeof(MENUITEMINFO);
+	mii.fMask = MIIM_ID | MIIM_SUBMENU | MIIM_TYPE;
+
+	/* Convert from OS/2 style accellerators to Win32 style */
+	if(title)
+	{
+		char *tmp = title;
+
+		while(*tmp)
+		{
+			if(*tmp == '~')
+				*tmp = '&';
+			tmp++;
+		}
+	}
+
+	if(title && *title)
+		mii.fType = MFT_STRING;
+	else
+		mii.fType = MFT_SEPARATOR;
+
+	mii.wID = id;
+    if(IsMenu((HMENU)submenu))
+		mii.hSubMenu = (HMENU)submenu;
+	else
+		mii.hSubMenu = 0;
+	mii.dwTypeData = title;
+	mii.cch = strlen(title);
+
+	InsertMenuItem(mymenu, 65535, TRUE, &mii);
+
+#ifndef WINNT_COMPAT
+	sprintf(buffer, "_dw_id%d", id);
+	dw_window_set_data(DW_HWND_OBJECT, buffer, (void *)mymenu);
+
+	/* According to the docs this will only work on Win2k/98 and above */
+	if(submenu)
+	{
+		MENUINFO mi;
+
+		mi.cbSize = sizeof(MENUINFO);
+		mi.fMask = MIM_MENUDATA;
+		mi.dwMenuData = (ULONG_PTR)mymenu;
+
+		SetMenuInfo((HMENU)submenu, &mi);
+	}
+#endif
+
+	if(IsWindow(menux) && !IsMenu((HMENU)menux))
+		DrawMenuBar(menux);
+	return (HWND)id;
+}
+
+/*
+ * Sets the state of a menu item check.
+ * Parameters:
+ *       menu: The handle the the existing menu.
+ *       id: Menuitem id.
+ *       check: TRUE for checked FALSE for not checked.
+ */
+void API dw_menu_item_set_check(HMENUI menux, unsigned long id, int check)
+{
+	MENUITEMINFO mii;
+	HMENU mymenu = (HMENU)menux;
+
+	if(IsWindow(menux) && !IsMenu(mymenu))
+		mymenu = (HMENU)dw_window_get_data(menux, "_dw_menu");
+
+	mii.cbSize = sizeof(MENUITEMINFO);
+	mii.fMask = MIIM_STATE;
+	if(check)
+		mii.fState = MFS_CHECKED;
+	else
+		mii.fState = MFS_UNCHECKED;
+	SetMenuItemInfo(mymenu, id, FALSE, &mii);
+}
+
+/*
+ * Pops up a context menu at given x and y coordinates.
+ * Parameters:
+ *       menu: The handle the the existing menu.
+ *       parent: Handle to the window initiating the popup.
+ *       x: X coordinate.
+ *       y: Y coordinate.
+ */
+void API dw_menu_popup(HMENUI *menu, HWND parent, int x, int y)
+{
+	if(menu)
+	{
+		HMENU mymenu = (HMENU)*menu;
+
+		if(IsWindow(*menu) && !IsMenu(mymenu))
+			mymenu = (HMENU)dw_window_get_data(*menu, "_dw_menu");
+
+		popup = parent;
+		TrackPopupMenu(mymenu, 0, x, y, 0, parent, NULL);
+		PostMessage(DW_HWND_OBJECT, WM_USER+5, (LPARAM)mymenu, 0);
+	}
+}
+
+
+/*
+ * Create a container object to be packed.
+ * Parameters:
+ *       id: An ID to be used for getting the resource from the
+ *           resource file.
+ */
+HWND API dw_container_new(ULONG id, int multi)
+{
+	HWND tmp = CreateWindow(WC_LISTVIEW,
+							"",
+							WS_VISIBLE | WS_CHILD |
+							(multi ? 0 : LVS_SINGLESEL) |
+							LVS_REPORT | LVS_SHOWSELALWAYS |
+							LVS_SHAREIMAGELISTS | WS_BORDER |
+							WS_CLIPCHILDREN,
+							0,0,2000,1000,
+							DW_HWND_OBJECT,
+							(HMENU)id,
+							DWInstance,
+							NULL);
+	ContainerInfo *cinfo = (ContainerInfo *)calloc(1, sizeof(ContainerInfo));
+
+	if(!cinfo)
+	{
+		DestroyWindow(tmp);
+		return NULL;
+	}
+
+	cinfo->pOldProc = (WNDPROC)SubclassWindow(tmp, _containerwndproc);
+	cinfo->cinfo.fore = cinfo->cinfo.back = -1;
+
+	SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo);
+	dw_window_set_font(tmp, DefaultFont);
+	return tmp;
+}
+
+/*
+ * Create a tree object to be packed.
+ * Parameters:
+ *       id: An ID to be used for getting the resource from the
+ *           resource file.
+ */
+HWND API dw_tree_new(ULONG id)
+{
+	HWND tmp = CreateWindow(WC_TREEVIEW,
+							"",
+							WS_VISIBLE | WS_CHILD |
+							TVS_HASLINES | TVS_SHOWSELALWAYS |
+							TVS_HASBUTTONS | TVS_LINESATROOT |
+							WS_BORDER | WS_CLIPCHILDREN,
+							0,0,2000,1000,
+							DW_HWND_OBJECT,
+							(HMENU)id,
+							DWInstance,
+							NULL);
+	ContainerInfo *cinfo = (ContainerInfo *)calloc(1, sizeof(ContainerInfo));
+	TreeView_SetItemHeight(tmp, 16);
+
+	if(!cinfo)
+	{
+		DestroyWindow(tmp);
+		return NULL;
+	}
+
+	cinfo->pOldProc = (WNDPROC)SubclassWindow(tmp, _treewndproc);
+	cinfo->cinfo.fore = cinfo->cinfo.back = -1;
+
+	SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo);
+	dw_window_set_font(tmp, DefaultFont);
+	return tmp;
+}
+
+/*
+ * Returns the current X and Y coordinates of the mouse pointer.
+ * Parameters:
+ *       x: Pointer to variable to store X coordinate.
+ *       y: Pointer to variable to store Y coordinate.
+ */
+void API dw_pointer_query_pos(long *x, long *y)
+{
+	POINT ptl;
+
+	GetCursorPos(&ptl);
+	if(x && y)
+	{
+		*x = ptl.x;
+		*y = ptl.y;
+	}
+}
+
+/*
+ * Sets the X and Y coordinates of the mouse pointer.
+ * Parameters:
+ *       x: X coordinate.
+ *       y: Y coordinate.
+ */
+void API dw_pointer_set_pos(long x, long y)
+{
+	SetCursorPos(x, y);
+}
+
+/*
+ * Create a new static text window (widget) to be packed.
+ * Parameters:
+ *       text: The text to be display by the static text widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_text_new(char *text, ULONG id)
+{
+	HWND tmp = CreateWindow(STATICCLASSNAME,
+							text,
+							BS_TEXT | WS_VISIBLE |
+							WS_CHILD | WS_CLIPCHILDREN,
+							0,0,2000,1000,
+							DW_HWND_OBJECT,
+							(HMENU)id,
+							DWInstance,
+							NULL);
+	dw_window_set_font(tmp, DefaultFont);
+	return tmp;
+}
+
+/*
+ * Create a new status text window (widget) to be packed.
+ * Parameters:
+ *       text: The text to be display by the static text widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_status_text_new(char *text, ULONG id)
+{
+	HWND tmp = CreateWindow(ObjectClassName,
+							text,
+							BS_TEXT | WS_VISIBLE |
+							WS_CHILD | WS_CLIPCHILDREN,
+							0,0,2000,1000,
+							DW_HWND_OBJECT,
+							(HMENU)id,
+							DWInstance,
+							NULL);
+	dw_window_set_font(tmp, DefaultFont);
+	SubclassWindow(tmp, _statuswndproc);
+	return tmp;
+}
+
+/*
+ * Create a new Multiline Editbox window (widget) to be packed.
+ * Parameters:
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_mle_new(ULONG id)
+{
+    
+	HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE,
+							  EDITCLASSNAME,
+							  "",
+							  WS_VISIBLE | WS_BORDER |
+							  WS_VSCROLL | ES_MULTILINE |
+							  ES_WANTRETURN | WS_CHILD |
+							  WS_CLIPCHILDREN,
+							  0,0,2000,1000,
+							  DW_HWND_OBJECT,
+							  (HMENU)id,
+							  DWInstance,
+							  NULL);
+	ContainerInfo *cinfo = (ContainerInfo *)calloc(1, sizeof(ContainerInfo));
+
+	if(!cinfo)
+	{
+		DestroyWindow(tmp);
+		return NULL;
+	}
+
+	cinfo->pOldProc = (WNDPROC)SubclassWindow(tmp, _treewndproc);
+	cinfo->cinfo.fore = cinfo->cinfo.back = -1;
+
+	SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo);
+	dw_window_set_font(tmp, DefaultFont);
+	return tmp;
+}
+
+/*
+ * Create a new Entryfield window (widget) to be packed.
+ * Parameters:
+ *       text: The default text to be in the entryfield widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_entryfield_new(char *text, ULONG id)
+{
+	HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE,
+							  EDITCLASSNAME,
+							  text,
+							  ES_WANTRETURN | WS_CHILD |
+							  WS_BORDER | ES_AUTOHSCROLL |
+							  WS_VISIBLE | WS_CLIPCHILDREN,
+							  0,0,2000,1000,
+							  DW_HWND_OBJECT,
+							  (HMENU)id,
+							  DWInstance,
+							  NULL);
+	ColorInfo *cinfo = calloc(1, sizeof(ColorInfo));
+
+	cinfo->back = cinfo->fore = -1;
+
+	cinfo->pOldProc = SubclassWindow(tmp, _colorwndproc);
+	SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo);
+	dw_window_set_font(tmp, DefaultFont);
+	return tmp;
+}
+
+/*
+ * Create a new Entryfield passwird window (widget) to be packed.
+ * Parameters:
+ *       text: The default text to be in the entryfield widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_entryfield_password_new(char *text, ULONG id)
+{
+	HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE,
+							  EDITCLASSNAME,
+							  text,
+							  ES_WANTRETURN | WS_CHILD |
+							  ES_PASSWORD | WS_BORDER | WS_VISIBLE |
+							  ES_AUTOHSCROLL | WS_CLIPCHILDREN,
+							  0,0,2000,1000,
+							  DW_HWND_OBJECT,
+							  (HMENU)id,
+							  DWInstance,
+							  NULL);
+	ColorInfo *cinfo = calloc(1, sizeof(ColorInfo));
+
+	cinfo->back = cinfo->fore = -1;
+
+	cinfo->pOldProc = SubclassWindow(tmp, _colorwndproc);
+	SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo);
+	dw_window_set_font(tmp, DefaultFont);
+	return tmp;
+}
+
+BOOL CALLBACK _subclass_child(HWND handle, LPARAM lp)
+{
+	ColorInfo *cinfo = (ColorInfo *)lp;
+
+	if(cinfo)
+	{
+		cinfo->buddy = handle;
+		cinfo->pOldProc = (WNDPROC)SubclassWindow(handle, _colorwndproc);
+		SetWindowLongPtr(handle, GWLP_USERDATA, (LONG_PTR)cinfo);
+	}
+	return FALSE;
+}
+
+/*
+ * Create a new Combobox window (widget) to be packed.
+ * Parameters:
+ *       text: The default text to be in the combpbox widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_combobox_new(char *text, ULONG id)
+{
+	HWND tmp = CreateWindow(COMBOBOXCLASSNAME,
+							text,
+							WS_CHILD | CBS_DROPDOWN | WS_VSCROLL |
+							WS_CLIPCHILDREN | CBS_AUTOHSCROLL | WS_VISIBLE,
+							0,0,2000,1000,
+							DW_HWND_OBJECT,
+							(HMENU)id,
+							DWInstance,
+							NULL);
+	ColorInfo *cinfo = (ColorInfo *)calloc(1, sizeof(ColorInfo));
+	ColorInfo *cinfo2 = (ColorInfo *)calloc(1, sizeof(ColorInfo));
+
+	if(!cinfo || !cinfo2)
+	{
+		if(cinfo)
+			free(cinfo);
+		if(cinfo2)
+			free(cinfo2);
+		DestroyWindow(tmp);
+		return NULL;
+	}
+
+	cinfo2->fore = cinfo->fore = -1;
+	cinfo2->back = cinfo->back = -1;
+	cinfo2->combo = cinfo->combo = tmp;
+	EnumChildWindows(tmp, _subclass_child, (LPARAM)cinfo2);
+
+	SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo);
+	dw_window_set_font(tmp, DefaultFont);
+	SetWindowText(tmp, text);
+	return tmp;
+}
+
+/*
+ * Create a new button window (widget) to be packed.
+ * Parameters:
+ *       text: The text to be display by the static text widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_button_new(char *text, ULONG id)
+{
+	BubbleButton *bubble = calloc(1, sizeof(BubbleButton));
+
+	HWND tmp = CreateWindow(BUTTONCLASSNAME,
+							text,
+							WS_CHILD | BS_PUSHBUTTON |
+							WS_VISIBLE | WS_CLIPCHILDREN,
+							0,0,2000,1000,
+							DW_HWND_OBJECT,
+							(HMENU)id,
+							DWInstance,
+							NULL);
+
+	bubble->id = id;
+	bubble->bubbletext[0] = '\0';
+	bubble->pOldProc = (WNDPROC)SubclassWindow(tmp, _BtProc);
+
+	SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)bubble);
+	dw_window_set_font(tmp, DefaultFont);
+	return tmp;
+}
+
+/*
+ * Create a new bitmap button window (widget) to be packed.
+ * Parameters:
+ *       text: Bubble help text to be displayed.
+ *       id: An ID of a bitmap in the resource file.
+ */
+HWND API dw_bitmapbutton_new(char *text, ULONG id)
+{
+	HWND tmp;
+	BubbleButton *bubble = calloc(1, sizeof(BubbleButton));
+	HBITMAP hbitmap = LoadBitmap(DWInstance, MAKEINTRESOURCE(id));
+
+	tmp = CreateWindow(BUTTONCLASSNAME,
+					   "",
+					   WS_CHILD | BS_PUSHBUTTON |
+					   BS_BITMAP | WS_CLIPCHILDREN |
+					   WS_VISIBLE,
+					   0,0,2000,1000,
+					   DW_HWND_OBJECT,
+					   (HMENU)id,
+					   DWInstance,
+					   NULL);
+
+	bubble->id = id;
+	strncpy(bubble->bubbletext, text, BUBBLE_HELP_MAX - 1);
+	bubble->bubbletext[BUBBLE_HELP_MAX - 1] = '\0';
+	bubble->pOldProc = (WNDPROC)SubclassWindow(tmp, _BtProc);
+
+	SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)bubble);
+
+	SendMessage(tmp, BM_SETIMAGE,
+				(WPARAM) IMAGE_BITMAP,
+				(LPARAM) hbitmap);
+	return tmp;
+}
+
+/*
+ * Create a new bitmap button window (widget) to be packed from a file.
+ * Parameters:
+ *       text: Bubble help text to be displayed.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ *       filename: Name of the file, omit extention to have
+ *                 DW pick the appropriate file extension.
+ *                 (BMP on OS/2 or Windows, XPM on Unix)
+ */
+HWND dw_bitmapbutton_new_from_file(char *text, unsigned long id, char *filename)
+{
+	HWND tmp;
+	BubbleButton *bubble;
+	HBITMAP hbitmap = 0;
+	char *file = malloc(strlen(filename) + 5);
+
+	if(!file || !(bubble = calloc(1, sizeof(BubbleButton))))
+	{
+		if(file)
+			free(file);
+		return 0;
+	}
+
+	tmp = CreateWindow(BUTTONCLASSNAME,
+					   "",
+					   WS_CHILD | BS_PUSHBUTTON |
+					   BS_BITMAP | WS_CLIPCHILDREN |
+					   WS_VISIBLE,
+					   0,0,2000,1000,
+					   DW_HWND_OBJECT,
+					   (HMENU)id,
+					   DWInstance,
+					   NULL);
+
+	bubble->id = id;
+	strncpy(bubble->bubbletext, text, BUBBLE_HELP_MAX - 1);
+	bubble->bubbletext[BUBBLE_HELP_MAX - 1] = '\0';
+	bubble->pOldProc = (WNDPROC)SubclassWindow(tmp, _BtProc);
+
+	SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)bubble);
+
+	strcpy(file, filename);
+
+	/* check if we can read from this file (it exists and read permission) */
+	if(access(file, 04) == 0)
+		hbitmap = (HBITMAP)LoadImage(NULL, file, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
+	else
+	{
+		/* Try with .bmp extention */
+		strcat(file, ".bmp");
+		if(access(file, 04) == 0)
+			hbitmap = (HBITMAP)LoadImage(NULL, file, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
+	}
+
+
+	if(hbitmap)
+		SendMessage(tmp, BM_SETIMAGE,
+					(WPARAM) IMAGE_BITMAP,
+					(LPARAM) hbitmap);
+	free(file);
+	return tmp;
+}
+
+/*
+ * Create a new spinbutton window (widget) to be packed.
+ * Parameters:
+ *       text: The text to be display by the static text widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_spinbutton_new(char *text, ULONG id)
+{
+	ULONG *data = malloc(sizeof(ULONG));
+	HWND buddy = CreateWindowEx(WS_EX_CLIENTEDGE,
+								EDITCLASSNAME,
+								text,
+								WS_CHILD | WS_BORDER | WS_VISIBLE |
+								ES_NUMBER | WS_CLIPCHILDREN,
+								0,0,2000,1000,
+								DW_HWND_OBJECT,
+								NULL,
+								DWInstance,
+								NULL);
+	HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE,
+							  UPDOWN_CLASS,
+							  NULL,
+							  WS_CHILD | UDS_ALIGNRIGHT | WS_BORDER |
+							  UDS_ARROWKEYS | UDS_SETBUDDYINT |
+							  UDS_WRAP | UDS_NOTHOUSANDS | WS_VISIBLE,
+							  0,0,2000,1000,
+							  DW_HWND_OBJECT,
+							  (HMENU)id,
+							  DWInstance,
+							  NULL);
+	ColorInfo *cinfo = calloc(1, sizeof(ColorInfo));
+
+	SendMessage(tmp, UDM_SETBUDDY, (WPARAM)buddy, 0);
+	cinfo->back = cinfo->fore = -1;
+	cinfo->buddy = tmp;
+
+	cinfo->pOldProc = SubclassWindow(buddy, _colorwndproc);
+	SetWindowLongPtr(buddy, GWLP_USERDATA, (LONG_PTR)cinfo);
+
+	cinfo = calloc(1, sizeof(ColorInfo));
+	cinfo->buddy = buddy;
+	cinfo->pOldProc = SubclassWindow(tmp, _spinnerwndproc);
+
+	SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo);
+	dw_window_set_font(buddy, DefaultFont);
+	return tmp;
+}
+
+/*
+ * Create a new radiobutton window (widget) to be packed.
+ * Parameters:
+ *       text: The text to be display by the static text widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_radiobutton_new(char *text, ULONG id)
+{
+	HWND tmp = CreateWindow(BUTTONCLASSNAME,
+							text,
+							WS_CHILD | BS_AUTORADIOBUTTON |
+							WS_CLIPCHILDREN | WS_VISIBLE,
+							0,0,2000,1000,
+							DW_HWND_OBJECT,
+							(HMENU)id,
+							DWInstance,
+							NULL);
+	BubbleButton *bubble = calloc(1, sizeof(BubbleButton));
+	bubble->id = id;
+	bubble->pOldProc = (WNDPROC)SubclassWindow(tmp, _BtProc);
+	bubble->cinfo.fore = -1;
+	bubble->cinfo.back = -1;
+	SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)bubble);
+	dw_window_set_font(tmp, DefaultFont);
+	return tmp;
+}
+
+
+/*
+ * Create a new slider window (widget) to be packed.
+ * Parameters:
+ *       vertical: TRUE or FALSE if slider is vertical.
+ *       increments: Number of increments available.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_slider_new(int vertical, int increments, ULONG id)
+{
+	HWND tmp = CreateWindow(TRACKBAR_CLASS,
+							"",
+							WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE |
+							(vertical ? TBS_VERT : TBS_HORZ),
+							0,0,2000,1000,
+							DW_HWND_OBJECT,
+							(HMENU)id,
+							DWInstance,
+							NULL);
+	ColorInfo *cinfo = calloc(1, sizeof(ColorInfo));
+
+	cinfo->back = cinfo->fore = -1;
+
+	cinfo->pOldProc = SubclassWindow(tmp, _colorwndproc);
+	SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo);
+	SendMessage(tmp, TBM_SETRANGE, (WPARAM)FALSE, (LPARAM)MAKELONG(0, increments-1));
+	return tmp;
+}
+
+/*
+ * Create a new scrollbar window (widget) to be packed.
+ * Parameters:
+ *       vertical: TRUE or FALSE if scrollbar is vertical.
+ *       increments: Number of increments available.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_scrollbar_new(int vertical, int increments, ULONG id)
+{
+	HWND tmp = CreateWindow(SCROLLBARCLASSNAME,
+							"",
+							WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE |
+							(vertical ? SBS_VERT : SBS_HORZ),
+							0,0,2000,1000,
+							DW_HWND_OBJECT,
+							(HMENU)id,
+							DWInstance,
+							NULL);
+	ColorInfo *cinfo = calloc(1, sizeof(ColorInfo));
+
+	cinfo->back = cinfo->fore = -1;
+
+	cinfo->pOldProc = SubclassWindow(tmp, _colorwndproc);
+	SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo);
+	dw_window_set_data(tmp, "_dw_scrollbar", (void *)1);
+	return tmp;
+}
+
+/*
+ * Create a new percent bar window (widget) to be packed.
+ * Parameters:
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_percent_new(ULONG id)
+{
+	return CreateWindow(PROGRESS_CLASS,
+						"",
+						WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN,
+						0,0,2000,1000,
+						DW_HWND_OBJECT,
+						(HMENU)id,
+						DWInstance,
+						NULL);
+}
+
+/*
+ * Create a new checkbox window (widget) to be packed.
+ * Parameters:
+ *       text: The text to be display by the static text widget.
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ */
+HWND API dw_checkbox_new(char *text, ULONG id)
+{
+	BubbleButton *bubble = calloc(1, sizeof(BubbleButton));
+	HWND tmp = CreateWindow(BUTTONCLASSNAME,
+							text,
+							WS_CHILD | BS_AUTOCHECKBOX |
+							BS_TEXT | WS_CLIPCHILDREN | WS_VISIBLE,
+							0,0,2000,1000,
+							DW_HWND_OBJECT,
+							(HMENU)id,
+							DWInstance,
+							NULL);
+	bubble->id = id;
+	bubble->checkbox = 1;
+	bubble->pOldProc = (WNDPROC)SubclassWindow(tmp, _BtProc);
+	bubble->cinfo.fore = -1;
+	bubble->cinfo.back = -1;
+	SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)bubble);
+	dw_window_set_font(tmp, DefaultFont);
+	return tmp;
+}
+
+/*
+ * Create a new listbox window (widget) to be packed.
+ * Parameters:
+ *       id: An ID to be used with dw_window_from_id() or 0L.
+ *       multi: Multiple select TRUE or FALSE.
+ */
+HWND API dw_listbox_new(ULONG id, int multi)
+{
+	HWND tmp = CreateWindowEx(WS_EX_CLIENTEDGE,
+							  LISTBOXCLASSNAME,
+							  "",
+							  WS_VISIBLE | LBS_NOINTEGRALHEIGHT |
+							  WS_CHILD | LBS_HASSTRINGS |
+							  LBS_NOTIFY | WS_BORDER  | WS_CLIPCHILDREN |
+							  WS_VSCROLL | (multi ? LBS_MULTIPLESEL : 0) ,
+							  0,0,2000,1000,
+							  DW_HWND_OBJECT,
+							  (HMENU)id,
+							  DWInstance,
+							  NULL);
+	ContainerInfo *cinfo = (ContainerInfo *)calloc(1, sizeof(ContainerInfo));
+
+	if(!cinfo)
+	{
+		DestroyWindow(tmp);
+		return NULL;
+	}
+
+	cinfo->cinfo.fore = -1;
+	cinfo->cinfo.back = -1;
+	cinfo->pOldProc = (WNDPROC)SubclassWindow(tmp, _containerwndproc);
+
+	SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)cinfo);
+	dw_window_set_font(tmp, DefaultFont);
+	return tmp;
+}
+
+/*
+ * Sets the icon used for a given window.
+ * Parameters:
+ *       handle: Handle to the window.
+ *       id: An ID to be used to specify the icon.
+ */
+void API dw_window_set_icon(HWND handle, ULONG id)
+{
+	HICON hicon = id < 65536 ? LoadIcon(DWInstance, MAKEINTRESOURCE(id)) : (HICON)id;
+
+	SendMessage(handle, WM_SETICON,
+				(WPARAM) IMAGE_ICON,
+				(LPARAM) hicon);
+}
+
+/*
+ * Sets the bitmap used for a given static window.
+ * Parameters:
+ *       handle: Handle to the window.
+ *       id: An ID to be used to specify the icon,
+ *           (pass 0 if you use the filename param)
+ *       filename: a path to a file (Bitmap on OS/2 or
+ *                 Windows and a pixmap on Unix, pass
+ *                 NULL if you use the id param)
+ */
+void API dw_window_set_bitmap(HWND handle, unsigned long id, char *filename)
+{
+	HBITMAP hbitmap;
+	HBITMAP oldbitmap = (HBITMAP)SendMessage(handle, STM_GETIMAGE, IMAGE_BITMAP, 0);
+
+	if(id)
+		hbitmap = LoadBitmap(DWInstance, MAKEINTRESOURCE(id));
+	else if(filename)
+	{
+		char *file = malloc(strlen(filename) + 5);
+
+		if (!file)
+			return;
+
+		strcpy(file, filename);
+
+		/* check if we can read from this file (it exists and read permission) */
+		if(access(file, 04) != 0)
+		{
+			/* Try with .bmp extention */
+			strcat(file, ".bmp");
+			if(access(file, 04) != 0)
+			{
+				free(file);
+				return;
+			}
+		}
+
+		hbitmap = (HBITMAP)LoadImage(NULL, file, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
+		free(file);
+	}
+	else
+		return;
+
+	SendMessage(handle, STM_SETIMAGE,
+				(WPARAM) IMAGE_BITMAP,
+				(LPARAM) hbitmap);
+
+	if(oldbitmap)
+		DeleteObject(oldbitmap);
+}
+
+/*
+ * Sets the text used for a given window.
+ * Parameters:
+ *       handle: Handle to the window.
+ *       text: The text associsated with a given window.
+ */
+void API dw_window_set_text(HWND handle, char *text)
+{
+	char tmpbuf[100];
+
+	GetClassName(handle, tmpbuf, 99);
+
+	SetWindowText(handle, text);
+
+	/* Combobox */
+	if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0)
+		SendMessage(handle, CB_SETEDITSEL, 0, MAKELPARAM(-1, 0));
+}
+
+/*
+ * Gets the text used for a given window.
+ * Parameters:
+ *       handle: Handle to the window.
+ * Returns:
+ *       text: The text associsated with a given window.
+ */
+char * API dw_window_get_text(HWND handle)
+{
+	int len = GetWindowTextLength(handle);
+	char *tempbuf = calloc(1, len + 2);
+
+	GetWindowText(handle, tempbuf, len + 1);
+
+	return tempbuf;
+}
+
+/*
+ * Disables given window (widget).
+ * Parameters:
+ *       handle: Handle to the window.
+ */
+void API dw_window_disable(HWND handle)
+{
+	EnableWindow(handle, FALSE);
+}
+
+/*
+ * Enables given window (widget).
+ * Parameters:
+ *       handle: Handle to the window.
+ */
+void API dw_window_enable(HWND handle)
+{
+	EnableWindow(handle, TRUE);
+}
+
+static HWND _dw_wfid_hwnd = NULL;
+
+BOOL CALLBACK _wfid(HWND handle, LPARAM lParam)
+{
+	if(GetWindowLong(handle, GWL_ID) == lParam)
+	{
+		_dw_wfid_hwnd = handle;
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/*
+ * Gets the child window handle with specified ID.
+ * Parameters:
+ *       handle: Handle to the parent window.
+ *       id: Integer ID of the child.
+ */
+HWND API dw_window_from_id(HWND handle, int id)
+{
+	_dw_wfid_hwnd = NULL;
+	EnumChildWindows(handle, _wfid, (LPARAM)id);
+    return _dw_wfid_hwnd;
+}
+
+/*
+ * Pack windows (widgets) into a box from the start (or top).
+ * Parameters:
+ *       box: Window handle of the box to be packed into.
+ *       item: Window handle of the item to be back.
+ *       width: Width in pixels of the item or -1 to be self determined.
+ *       height: Height in pixels of the item or -1 to be self determined.
+ *       hsize: TRUE if the window (widget) should expand horizontally to fill space given.
+ *       vsize: TRUE if the window (widget) should expand vertically to fill space given.
+ *       pad: Number of pixels of padding around the item.
+ */
+void API dw_box_pack_start(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad)
+{
+	Box *thisbox;
+
+		/*
+		 * If you try and pack an item into itself VERY bad things can happen; like at least an
+		 * infinite loop on GTK! Lets be safe!
+		 */
+	if(box == item)
+	{
+		dw_messagebox("dw_box_pack_start()", DW_MB_OK|DW_MB_ERROR, "Danger! Danger! Will Robinson; box and item are the same!",box,item);
+		return;
+	}
+
+	thisbox = (Box *)GetWindowLongPtr(box, GWLP_USERDATA);
+	if(thisbox)
+	{
+		int z;
+		Item *tmpitem, *thisitem = thisbox->items;
+		char tmpbuf[100];
+
+		tmpitem = malloc(sizeof(Item)*(thisbox->count+1));
+
+		for(z=0;z<thisbox->count;z++)
+		{
+			tmpitem[z] = thisitem[z];
+		}
+
+		GetClassName(item, tmpbuf, 99);
+
+		if(vsize && !height)
+			height = 1;
+		if(hsize && !width)
+			width = 1;
+
+		if(strnicmp(tmpbuf, FRAMECLASSNAME, strlen(FRAMECLASSNAME)+1)==0)
+			tmpitem[thisbox->count].type = TYPEBOX;
+		else
+		{
+			if ( width == 0 && hsize == FALSE )
+				dw_messagebox("dw_box_pack_start()", DW_MB_OK|DW_MB_ERROR, "Width and expand Horizonal both unset for box: %x item: %x",box,item);
+			if ( height == 0 && vsize == FALSE )
+				dw_messagebox("dw_box_pack_start()", DW_MB_OK|DW_MB_ERROR, "Height and expand Vertical both unset for box: %x item: %x",box,item);
+
+			tmpitem[thisbox->count].type = TYPEITEM;
+		}
+
+		tmpitem[thisbox->count].hwnd = item;
+		tmpitem[thisbox->count].origwidth = tmpitem[thisbox->count].width = width;
+		tmpitem[thisbox->count].origheight = tmpitem[thisbox->count].height = height;
+		tmpitem[thisbox->count].pad = pad;
+		if(hsize)
+			tmpitem[thisbox->count].hsize = SIZEEXPAND;
+		else
+			tmpitem[thisbox->count].hsize = SIZESTATIC;
+
+		if(vsize)
+			tmpitem[thisbox->count].vsize = SIZEEXPAND;
+		else
+			tmpitem[thisbox->count].vsize = SIZESTATIC;
+
+		thisbox->items = tmpitem;
+
+		if(thisbox->count)
+			free(thisitem);
+
+		thisbox->count++;
+
+		SetParent(item, box);
+		if(strncmp(tmpbuf, UPDOWN_CLASS, strlen(UPDOWN_CLASS)+1)==0)
+		{
+			ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(item, GWLP_USERDATA);
+
+			if(cinfo)
+			{
+				SetParent(cinfo->buddy, box);
+				ShowWindow(cinfo->buddy, SW_SHOW);
+				SendMessage(item, UDM_SETBUDDY, (WPARAM)cinfo->buddy, 0);
+			}
+		}
+	}
+}
+
+/*
+ * Sets the size of a given window (widget).
+ * Parameters:
+ *          handle: Window (widget) handle.
+ *          width: New width in pixels.
+ *          height: New height in pixels.
+ */
+void API dw_window_set_usize(HWND handle, ULONG width, ULONG height)
+{
+	SetWindowPos(handle, (HWND)NULL, 0, 0, width, height, SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOMOVE);
+}
+
+/*
+ * Returns the width of the screen.
+ */
+int API dw_screen_width(void)
+{
+	return GetSystemMetrics(SM_CXSCREEN);
+}
+
+/*
+ * Returns the height of the screen.
+ */
+int API dw_screen_height(void)
+{
+	return GetSystemMetrics(SM_CYSCREEN);
+}
+
+/* This should return the current color depth */
+unsigned long API dw_color_depth(void)
+{
+	int bpp;
+	HDC hdc = GetDC(HWND_DESKTOP);
+    
+	bpp = GetDeviceCaps(hdc, BITSPIXEL);
+
+	ReleaseDC(HWND_DESKTOP, hdc);
+
+	return bpp;
+}
+
+
+/*
+ * Sets the position of a given window (widget).
+ * Parameters:
+ *          handle: Window (widget) handle.
+ *          x: X location from the bottom left.
+ *          y: Y location from the bottom left.
+ */
+void API dw_window_set_pos(HWND handle, ULONG x, ULONG y)
+{
+	SetWindowPos(handle, (HWND)NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
+}
+
+/*
+ * Sets the position and size of a given window (widget).
+ * Parameters:
+ *          handle: Window (widget) handle.
+ *          x: X location from the bottom left.
+ *          y: Y location from the bottom left.
+ *          width: Width of the widget.
+ *          height: Height of the widget.
+ */
+void API dw_window_set_pos_size(HWND handle, ULONG x, ULONG y, ULONG width, ULONG height)
+{
+	SetWindowPos(handle, (HWND)NULL, x, y, width, height, SWP_NOZORDER | SWP_SHOWWINDOW | SWP_NOACTIVATE);
+}
+
+/*
+ * Gets the position and size of a given window (widget).
+ * Parameters:
+ *          handle: Window (widget) handle.
+ *          x: X location from the bottom left.
+ *          y: Y location from the bottom left.
+ *          width: Width of the widget.
+ *          height: Height of the widget.
+ */
+void API dw_window_get_pos_size(HWND handle, ULONG *x, ULONG *y, ULONG *width, ULONG *height)
+{
+	WINDOWPLACEMENT wp;
+
+	wp.length = sizeof(WINDOWPLACEMENT);
+
+	GetWindowPlacement(handle, &wp);
+	if( wp.showCmd == SW_SHOWMAXIMIZED)
+	{
+		if(x)
+			*x=0;
+		if(y)
+			*y=0;
+		if(width)
+			*width=dw_screen_width();
+		if(height)
+			*height=dw_screen_height();
+	}
+else
+	{
+		if(x)
+			*x = wp.rcNormalPosition.left;
+		if(y)
+			*y = wp.rcNormalPosition.top;
+		if(width)
+			*width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
+		if(height)
+			*height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
+	}
+}
+
+/*
+ * Sets the style of a given window (widget).
+ * Parameters:
+ *          handle: Window (widget) handle.
+ *          width: New width in pixels.
+ *          height: New height in pixels.
+ */
+void API dw_window_set_style(HWND handle, ULONG style, ULONG mask)
+{
+	ULONG tmp, currentstyle = GetWindowLong(handle, GWL_STYLE);
+	ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA);
+
+	tmp = currentstyle | mask;
+	tmp ^= mask;
+	tmp |= style;
+
+
+	/* We are using SS_NOPREFIX as a VCENTER flag */
+	if(tmp & SS_NOPREFIX)
+	{
+
+		if(cinfo)
+			cinfo->vcenter = 1;
+		else
+		{
+			cinfo = calloc(1, sizeof(ColorInfo));
+			cinfo->fore = cinfo->back = -1;
+			cinfo->vcenter = 1;
+
+			cinfo->pOldProc = SubclassWindow(handle, _colorwndproc);
+			SetWindowLongPtr(handle, GWLP_USERDATA, (LONG_PTR)cinfo);
+		}
+	}
+	else if(cinfo)
+		cinfo->vcenter = 0;
+
+	SetWindowLong(handle, GWL_STYLE, tmp);
+}
+
+/* Finds the physical ID from the reference ID */
+int _findnotebookid(NotebookPage **array, int pageid)
+{
+	int z;
+
+	for(z=0;z<256;z++)
+	{
+		if(array[z] && array[z]->realid == pageid)
+			return z;
+	}
+	return -1;
+}
+
+/*
+ * Adds a new page to specified notebook.
+ * Parameters:
+ *          handle: Window (widget) handle.
+ *          flags: Any additional page creation flags.
+ *          front: If TRUE page is added at the beginning.
+ */
+unsigned long API dw_notebook_page_new(HWND handle, ULONG flags, int front)
+{
+	NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array");
+
+	if(array)
+	{
+		int z, refid = -1;
+
+		for(z=0;z<256;z++)
+		{
+			if(_findnotebookid(array, z) == -1)
+			{
+				refid = z;
+				break;
+			}
+		}
+
+		if(refid == -1)
+			return -1;
+
+		for(z=0;z<256;z++)
+		{
+			if(!array[z])
+			{
+				int oldpage = TabCtrl_GetCurSel(handle);
+
+				array[z] = calloc(1, sizeof(NotebookPage));
+				array[z]->realid = refid;
+				array[z]->item.mask = TCIF_TEXT;
+				array[z]->item.iImage = -1;
+				array[z]->item.pszText = "";
+				TabCtrl_InsertItem(handle, z, &(array[z]->item));
+
+				if(oldpage > -1 && array[oldpage])
+					SetParent(array[oldpage]->hwnd, DW_HWND_OBJECT);
+
+				TabCtrl_SetCurSel(handle, z);
+				return refid;
+			}
+		}
+	}
+	return -1;
+}
+
+/*
+ * Sets the text on the specified notebook tab.
+ * Parameters:
+ *          handle: Notebook handle.
+ *          pageid: Page ID of the tab to set.
+ *          text: Pointer to the text to set.
+ */
+void API dw_notebook_page_set_text(HWND handle, ULONG pageidx, char *text)
+{
+
+	NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array");
+	int pageid;
+
+	if(!array)
+		return;
+
+	pageid = _findnotebookid(array, pageidx);
+
+	if(pageid > -1 && array[pageid])
+	{
+		array[pageid]->item.mask = TCIF_TEXT;
+		array[pageid]->item.pszText = text;
+		TabCtrl_SetItem(handle, pageid, &(array[pageid]->item));
+		_resize_notebook_page(handle, pageid);
+	}
+}
+
+/*
+ * Sets the text on the specified notebook tab status area.
+ * Parameters:
+ *          handle: Notebook handle.
+ *          pageid: Page ID of the tab to set.
+ *          text: Pointer to the text to set.
+ */
+void API dw_notebook_page_set_status_text(HWND handle, ULONG pageid, char *text)
+{
+}
+
+/*
+ * Packs the specified box into the notebook page.
+ * Parameters:
+ *          handle: Handle to the notebook to be packed.
+ *          pageid: Page ID in the notebook which is being packed.
+ *          page: Box handle to be packed.
+ */
+void API dw_notebook_pack(HWND handle, ULONG pageidx, HWND page)
+{
+	NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array");
+	int pageid;
+
+	if(!array)
+		return;
+
+	pageid = _findnotebookid(array, pageidx);
+
+	if(pageid > -1 && array[pageid])
+	{
+		HWND tmpbox = dw_box_new(DW_VERT, 0);
+
+		dw_box_pack_start(tmpbox, page, 0, 0, TRUE, TRUE, 0);
+		SubclassWindow(tmpbox, _wndproc);
+		if(array[pageid]->hwnd)
+			dw_window_destroy(array[pageid]->hwnd);
+		array[pageid]->hwnd = tmpbox;
+		if(pageidx == dw_notebook_page_query(handle))
+		{
+			SetParent(tmpbox, handle);
+			_resize_notebook_page(handle, pageid);
+		}
+	}
+}
+
+/*
+ * Remove a page from a notebook.
+ * Parameters:
+ *          handle: Handle to the notebook widget.
+ *          pageid: ID of the page to be destroyed.
+ */
+void API dw_notebook_page_destroy(HWND handle, unsigned int pageidx)
+{
+	NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array");
+	int newid = -1, z, pageid;
+
+	if(!array)
+		return;
+
+	pageid = _findnotebookid(array, pageidx);
+
+	if(pageid < 0)
+		return;
+
+	if(array[pageid])
+	{
+		SetParent(array[pageid]->hwnd, DW_HWND_OBJECT);
+		free(array[pageid]);
+		array[pageid] = NULL;
+	}
+
+	TabCtrl_DeleteItem(handle, pageid);
+
+	/* Shift the pages over 1 */
+	for(z=pageid;z<255;z++)
+		array[z] = array[z+1];
+	array[255] = NULL;
+
+	for(z=0;z<256;z++)
+	{
+		if(array[z])
+		{
+			newid = z;
+			break;
+		}
+	}
+	if(newid > -1)
+	{
+		SetParent(array[newid]->hwnd, handle);
+		_resize_notebook_page(handle, newid);
+		dw_notebook_page_set(handle, array[newid]->realid);
+	}
+}
+
+/*
+ * Queries the currently visible page ID.
+ * Parameters:
+ *          handle: Handle to the notebook widget.
+ */
+unsigned long API dw_notebook_page_query(HWND handle)
+{
+	NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array");
+	int physid = TabCtrl_GetCurSel(handle);
+
+	if(physid > -1 && physid < 256 && array && array[physid])
+		return array[physid]->realid;
+	return -1;
+}
+
+/*
+ * Sets the currently visible page ID.
+ * Parameters:
+ *          handle: Handle to the notebook widget.
+ *          pageid: ID of the page to be made visible.
+ */
+void API dw_notebook_page_set(HWND handle, unsigned int pageidx)
+{
+	NotebookPage **array = (NotebookPage **)dw_window_get_data(handle, "_dw_array");
+	int pageid;
+
+	if(!array)
+		return;
+
+	pageid = _findnotebookid(array, pageidx);
+
+	if(pageid > -1 && pageid < 256)
+	{
+		int oldpage = TabCtrl_GetCurSel(handle);
+
+		if(oldpage > -1 && array && array[oldpage])
+			SetParent(array[oldpage]->hwnd, DW_HWND_OBJECT);
+
+		TabCtrl_SetCurSel(handle, pageid);
+
+		SetParent(array[pageid]->hwnd, handle);
+		_resize_notebook_page(handle, pageid);
+	}
+}
+
+/*
+ * Appends the specified text to the listbox's (or combobox) entry list.
+ * Parameters:
+ *          handle: Handle to the listbox to be appended to.
+ *          text: Text to append into listbox.
+ */
+void API dw_listbox_append(HWND handle, char *text)
+{
+	char tmpbuf[100];
+
+	GetClassName(handle, tmpbuf, 99);
+
+	if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0)
+		SendMessage(handle,
+					CB_ADDSTRING,
+					0, (LPARAM)text);
+	else
+		SendMessage(handle,
+					LB_ADDSTRING,
+					0, (LPARAM)text);
+}
+
+/*
+ * Clears the listbox's (or combobox) list of all entries.
+ * Parameters:
+ *          handle: Handle to the listbox to be cleared.
+ */
+void API dw_listbox_clear(HWND handle)
+{
+	char tmpbuf[100];
+
+	GetClassName(handle, tmpbuf, 99);
+
+	if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0)
+	{
+		char *buf = dw_window_get_text(handle);
+
+		SendMessage(handle,
+					CB_RESETCONTENT, 0L, 0L);
+
+		if(buf)
+		{
+			dw_window_set_text(handle, buf);
+			free(buf);
+		}
+	}
+	else
+		SendMessage(handle,
+					LB_RESETCONTENT, 0L, 0L);
+}
+
+/*
+ * Sets the text of a given listbox entry.
+ * Parameters:
+ *          handle: Handle to the listbox to be queried.
+ *          index: Index into the list to be queried.
+ *          buffer: Buffer where text will be copied.
+ */
+void API dw_listbox_set_text(HWND handle, unsigned int index, char *buffer)
+{
+	char tmpbuf[100];
+
+	GetClassName(handle, tmpbuf, 99);
+
+	if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0)
+	{
+		SendMessage(handle,	CB_DELETESTRING, (WPARAM)index, 0);
+		SendMessage(handle, CB_INSERTSTRING, (WPARAM)index, (LPARAM)buffer);
+	}
+	else
+	{
+		unsigned int sel = (unsigned int)SendMessage(handle, LB_GETCURSEL, 0, 0);
+		SendMessage(handle,	LB_DELETESTRING, (WPARAM)index, 0);
+		SendMessage(handle, LB_INSERTSTRING, (WPARAM)index, (LPARAM)buffer);
+		SendMessage(handle, LB_SETCURSEL, (WPARAM)sel, 0);
+		SendMessage(handle, LB_SETSEL, (WPARAM)TRUE, (LPARAM)sel);
+	}
+}
+
+/*
+ * Copies the given index item's text into buffer.
+ * Parameters:
+ *          handle: Handle to the listbox to be queried.
+ *          index: Index into the list to be queried.
+ *          buffer: Buffer where text will be copied.
+ *          length: Length of the buffer (including NULL).
+ */
+void API dw_listbox_query_text(HWND handle, unsigned int index, char *buffer, unsigned int length)
+{
+	char tmpbuf[100];
+	int len;
+
+	if(!buffer || !length)
+		return;
+
+	buffer[0] = 0;
+
+	GetClassName(handle, tmpbuf, 99);
+
+	if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0)
+	{
+		len = (int)SendMessage(handle, CB_GETLBTEXTLEN, (WPARAM)index, 0);
+
+		if(len < length && len != CB_ERR)
+			SendMessage(handle,
+						CB_GETLBTEXT, (WPARAM)index, (LPARAM)buffer);
+	}
+	else
+	{
+		len = (int)SendMessage(handle, LB_GETTEXTLEN, (WPARAM)index, 0);
+
+		if(len < length && len != LB_ERR)
+			SendMessage(handle,
+						LB_GETTEXT, (WPARAM)index, (LPARAM)buffer);
+	}
+}
+
+/*
+ * Returns the index to the item in the list currently selected.
+ * Parameters:
+ *          handle: Handle to the listbox to be queried.
+ */
+unsigned int API dw_listbox_selected(HWND handle)
+{
+	char tmpbuf[100];
+
+	GetClassName(handle, tmpbuf, 99);
+
+	if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0)
+		return (unsigned int)SendMessage(handle,
+										 CB_GETCURSEL,
+										 0, 0);
+
+	return (unsigned int)SendMessage(handle,
+									 LB_GETCURSEL,
+									 0, 0);
+}
+
+/*
+ * Returns the index to the current selected item or -1 when done.
+ * Parameters:
+ *          handle: Handle to the listbox to be queried.
+ *          where: Either the previous return or -1 to restart.
+ */
+int API dw_listbox_selected_multi(HWND handle, int where)
+{
+	int *array, count, z;
+	char tmpbuf[100];
+
+	GetClassName(handle, tmpbuf, 99);
+
+	/* This doesn't work on comboboxes */
+	if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0)
+		return -1;
+
+	count = (int)SendMessage(handle, LB_GETSELCOUNT, 0, 0);
+	if(count > 0)
+	{
+		array = malloc(sizeof(int)*count);
+		SendMessage(handle, LB_GETSELITEMS, (WPARAM)count, (LPARAM)array);
+
+		if(where == -1)
+		{
+			int ret = array[0];
+			free(array);
+			return ret;
+		}
+		for(z=0;z<count;z++)
+		{
+			if(array[z] == where && (z+1) < count)
+			{
+				int ret = array[z+1];
+				free(array);
+				return ret;
+			}
+		}
+		free(array);
+	}
+	return -1;
+}
+
+/*
+ * Sets the selection state of a given index.
+ * Parameters:
+ *          handle: Handle to the listbox to be set.
+ *          index: Item index.
+ *          state: TRUE if selected FALSE if unselected.
+ */
+void API dw_listbox_select(HWND handle, int index, int state)
+{
+	char tmpbuf[100];
+
+	GetClassName(handle, tmpbuf, 99);
+
+	if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0)
+		SendMessage(handle, CB_SETCURSEL, (WPARAM)index, 0);
+	else
+	{
+		SendMessage(handle, LB_SETCURSEL, (WPARAM)index, 0);
+		SendMessage(handle, LB_SETSEL, (WPARAM)state, (LPARAM)index);
+	}
+	_wndproc(handle, WM_COMMAND, (WPARAM)(LBN_SELCHANGE << 16), (LPARAM)handle);
+}
+
+/*
+ * Deletes the item with given index from the list.
+ * Parameters:
+ *          handle: Handle to the listbox to be set.
+ *          index: Item index.
+ */
+void API dw_listbox_delete(HWND handle, int index)
+{
+	char tmpbuf[100];
+
+	GetClassName(handle, tmpbuf, 99);
+
+	if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0)
+		SendMessage(handle, CB_DELETESTRING, (WPARAM)index, 0);
+	else
+		SendMessage(handle, LB_DELETESTRING, (WPARAM)index, 0);
+}
+
+/*
+ * Returns the listbox's item count.
+ * Parameters:
+ *          handle: Handle to the listbox to be cleared.
+ */
+int API dw_listbox_count(HWND handle)
+{
+	char tmpbuf[100];
+
+	GetClassName(handle, tmpbuf, 99);
+
+	if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0)
+		return (int)SendMessage(handle,
+								CB_GETCOUNT,0L, 0L);
+
+	return (int)SendMessage(handle,
+							LB_GETCOUNT,0L, 0L);
+}
+
+/*
+ * Sets the topmost item in the viewport.
+ * Parameters:
+ *          handle: Handle to the listbox to be cleared.
+ *          top: Index to the top item.
+ */
+void API dw_listbox_set_top(HWND handle, int top)
+{
+	char tmpbuf[100];
+
+	GetClassName(handle, tmpbuf, 99);
+
+	/* This doesn't work on comboboxes */
+	if(strnicmp(tmpbuf, COMBOBOXCLASSNAME, strlen(COMBOBOXCLASSNAME)+1)==0)
+		return;
+
+	SendMessage(handle, LB_SETTOPINDEX, (WPARAM)top, 0);
+}
+
+/*
+ * Adds text to an MLE box and returns the current point.
+ * Parameters:
+ *          handle: Handle to the MLE to be queried.
+ *          buffer: Text buffer to be imported.
+ *          startpoint: Point to start entering text.
+ */
+unsigned int API dw_mle_import(HWND handle, char *buffer, int startpoint)
+{
+	int textlen, len = GetWindowTextLength(handle);
+	char *tmpbuf;
+
+	if((textlen = strlen(buffer)) < 1)
+		return startpoint;
+
+	startpoint++;
+	tmpbuf = calloc(1, len + textlen + startpoint + 2);
+
+	if(startpoint < 0)
+		startpoint = 0;
+
+	if(len)
+	{
+		char *dest, *start;
+		int copylen = len - startpoint;
+
+		GetWindowText(handle, tmpbuf, len+1);
+
+		dest = &tmpbuf[startpoint+textlen-1];
+		start = &tmpbuf[startpoint];
+
+		if(copylen > 0)
+			memcpy(dest, start, copylen);
+	}
+	memcpy(&tmpbuf[startpoint], buffer, textlen);
+
+	SetWindowText(handle, tmpbuf);
+
+	free(tmpbuf);
+	return (startpoint + textlen - 1);
+}
+
+/*
+ * Grabs text from an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to be queried.
+ *          buffer: Text buffer to be exported.
+ *          startpoint: Point to start grabbing text.
+ *          length: Amount of text to be grabbed.
+ */
+void API dw_mle_export(HWND handle, char *buffer, int startpoint, int length)
+{
+	int max, len = GetWindowTextLength(handle);
+	char *tmpbuf = calloc(1, len+2);
+
+	if(len)
+		GetWindowText(handle, tmpbuf, len+1);
+
+	buffer[0] = 0;
+
+	if(startpoint < len)
+	{
+		max = MIN(length, len - startpoint);
+
+		memcpy(buffer, &tmpbuf[startpoint], max);
+	}
+
+	free(tmpbuf);
+}
+
+/*
+ * Obtains information about an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to be queried.
+ *          bytes: A pointer to a variable to return the total bytes.
+ *          lines: A pointer to a variable to return the number of lines.
+ */
+void API dw_mle_query(HWND handle, unsigned long *bytes, unsigned long *lines)
+{
+	if(bytes)
+		*bytes = GetWindowTextLength(handle);
+	if(lines)
+		*lines = (unsigned long)SendMessage(handle, EM_GETLINECOUNT, 0, 0);
+}
+
+/*
+ * Deletes text from an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to be deleted from.
+ *          startpoint: Point to start deleting text.
+ *          length: Amount of text to be deleted.
+ */
+void API dw_mle_delete(HWND handle, int startpoint, int length)
+{
+	int len = GetWindowTextLength(handle);
+	char *tmpbuf = calloc(1, len+2);
+
+	GetWindowText(handle, tmpbuf, len+1);
+
+	if(startpoint + length < len)
+	{
+		strcpy(&tmpbuf[startpoint], &tmpbuf[startpoint+length]);
+
+		SetWindowText(handle, tmpbuf);
+	}
+
+	free(tmpbuf);
+}
+
+/*
+ * Clears all text from an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to be cleared.
+ */
+void API dw_mle_clear(HWND handle)
+{
+	SetWindowText(handle, "");
+}
+
+/*
+ * Sets the visible line of an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE.
+ *          line: Line to be visible.
+ */
+void API dw_mle_set_visible(HWND handle, int line)
+{
+	int point = (int)SendMessage(handle, EM_LINEINDEX, (WPARAM)line, 0);
+	dw_mle_set(handle, point);
+}
+
+/*
+ * Sets the editablity of an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE.
+ *          state: TRUE if it can be edited, FALSE for readonly.
+ */
+void API dw_mle_set_editable(HWND handle, int state)
+{
+	SendMessage(handle, EM_SETREADONLY, (WPARAM)(state ? FALSE : TRUE), 0);
+}
+
+/*
+ * Sets the word wrap state of an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE.
+ *          state: TRUE if it wraps, FALSE if it doesn't.
+ */
+void API dw_mle_set_word_wrap(HWND handle, int state)
+{
+	/* If ES_AUTOHSCROLL is not set and there is not
+	 * horizontal scrollbar it word wraps.
+	 */
+	if(state)
+		dw_window_set_style(handle, 0, ES_AUTOHSCROLL);
+	else
+		dw_window_set_style(handle, ES_AUTOHSCROLL, ES_AUTOHSCROLL);
+}
+
+/*
+ * Sets the current cursor position of an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to be positioned.
+ *          point: Point to position cursor.
+ */
+void API dw_mle_set(HWND handle, int point)
+{
+	SendMessage(handle, EM_SETSEL, 0, MAKELONG(point,point));
+	SendMessage(handle, EM_SCROLLCARET, 0, 0);
+}
+
+/*
+ * Finds text in an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to be cleared.
+ *          text: Text to search for.
+ *          point: Start point of search.
+ *          flags: Search specific flags.
+ */
+int API dw_mle_search(HWND handle, char *text, int point, unsigned long flags)
+{
+	int len = GetWindowTextLength(handle);
+	char *tmpbuf = calloc(1, len+2);
+	int z, textlen, retval = 0;
+
+	GetWindowText(handle, tmpbuf, len+1);
+
+	textlen = strlen(text);
+
+	if(flags & DW_MLE_CASESENSITIVE)
+	{
+		for(z=point;z<(len-textlen) && !retval;z++)
+		{
+			if(strncmp(&tmpbuf[z], text, textlen) == 0)
+				retval = z + textlen;
+		}
+	}
+	else
+	{
+		for(z=point;z<(len-textlen) && !retval;z++)
+		{
+			if(strnicmp(&tmpbuf[z], text, textlen) == 0)
+				retval = z + textlen;
+		}
+	}
+
+	if(retval)
+	{
+		SendMessage(handle, EM_SETSEL, (WPARAM)retval - textlen, (LPARAM)retval);
+		SendMessage(handle, EM_SCROLLCARET, 0, 0);
+	}
+
+	free(tmpbuf);
+
+	return retval;
+}
+
+/*
+ * Stops redrawing of an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to freeze.
+ */
+void API dw_mle_freeze(HWND handle)
+{
+}
+
+/*
+ * Resumes redrawing of an MLE box.
+ * Parameters:
+ *          handle: Handle to the MLE to thaw.
+ */
+void API dw_mle_thaw(HWND handle)
+{
+}
+
+/*
+ * Returns the range of the percent bar.
+ * Parameters:
+ *          handle: Handle to the percent bar to be queried.
+ */
+unsigned int API dw_percent_query_range(HWND handle)
+{
+	return (unsigned int)SendMessage(handle, PBM_GETRANGE, (WPARAM)FALSE, 0);
+}
+
+/*
+ * Sets the percent bar position.
+ * Parameters:
+ *          handle: Handle to the percent bar to be set.
+ *          position: Position of the percent bar withing the range.
+ */
+void API dw_percent_set_pos(HWND handle, unsigned int position)
+{
+	SendMessage(handle, PBM_SETPOS, (WPARAM)position, 0);
+}
+
+/*
+ * Returns the position of the slider.
+ * Parameters:
+ *          handle: Handle to the slider to be queried.
+ */
+unsigned int API dw_slider_query_pos(HWND handle)
+{
+	int max = (int)SendMessage(handle, TBM_GETRANGEMAX, 0, 0);
+	ULONG currentstyle = GetWindowLong(handle, GWL_STYLE);
+
+	if(currentstyle & TBS_VERT)
+		return max - (unsigned int)SendMessage(handle, TBM_GETPOS, 0, 0);
+	return (unsigned int)SendMessage(handle, TBM_GETPOS, 0, 0);
+}
+
+/*
+ * Sets the slider position.
+ * Parameters:
+ *          handle: Handle to the slider to be set.
+ *          position: Position of the slider withing the range.
+ */
+void API dw_slider_set_pos(HWND handle, unsigned int position)
+{
+	int max = (int)SendMessage(handle, TBM_GETRANGEMAX, 0, 0);
+	ULONG currentstyle = GetWindowLong(handle, GWL_STYLE);
+
+	if(currentstyle & TBS_VERT)
+		SendMessage(handle, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)max - position);
+	else
+		SendMessage(handle, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)position);
+}
+
+/*
+ * Returns the position of the scrollbar.
+ * Parameters:
+ *          handle: Handle to the scrollbar to be queried.
+ */
+unsigned int API dw_scrollbar_query_pos(HWND handle)
+{
+	return (unsigned int)SendMessage(handle, SBM_GETPOS, 0, 0);
+}
+
+/*
+ * Sets the scrollbar position.
+ * Parameters:
+ *          handle: Handle to the scrollbar to be set.
+ *          position: Position of the scrollbar withing the range.
+ */
+void API dw_scrollbar_set_pos(HWND handle, unsigned int position)
+{
+	dw_window_set_data(handle, "_dw_scrollbar_value", (void *)position);
+	SendMessage(handle, SBM_SETPOS, (WPARAM)position, (LPARAM)TRUE);
+}
+
+/*
+ * Sets the scrollbar range.
+ * Parameters:
+ *          handle: Handle to the scrollbar to be set.
+ *          range: Maximum range value.
+ *          visible: Visible area relative to the range.
+ */
+void API dw_scrollbar_set_range(HWND handle, unsigned int range, unsigned int visible)
+{
+	SCROLLINFO si;
+
+	si.cbSize = sizeof(SCROLLINFO);
+	si.fMask = SIF_RANGE | SIF_PAGE;
+	si.nMin = 0;
+	si.nMax = range - 1;
+	si.nPage = visible;
+	SendMessage(handle, SBM_SETSCROLLINFO, (WPARAM)TRUE, (LPARAM)&si);
+}
+
+/*
+ * Sets the spinbutton value.
+ * Parameters:
+ *          handle: Handle to the spinbutton to be set.
+ *          position: Current value of the spinbutton.
+ */
+void API dw_spinbutton_set_pos(HWND handle, long position)
+{
+	char tmpbuf[100];
+	ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA);
+
+	sprintf(tmpbuf, "%d", position);
+
+	if(cinfo && cinfo->buddy)
+		SetWindowText(cinfo->buddy, tmpbuf);
+
+	if(IS_IE5PLUS)
+		SendMessage(handle, UDM_SETPOS32, 0, (LPARAM)position);
+	else
+		SendMessage(handle, UDM_SETPOS, 0, (LPARAM)MAKELONG((short)position, 0));
+}
+
+/*
+ * Sets the spinbutton limits.
+ * Parameters:
+ *          handle: Handle to the spinbutton to be set.
+ *          position: Current value of the spinbutton.
+ *          position: Current value of the spinbutton.
+ */
+void API dw_spinbutton_set_limits(HWND handle, long upper, long lower)
+{
+	if(IS_IE5PLUS)
+		SendMessage(handle, UDM_SETRANGE32, (WPARAM)lower,(LPARAM)upper);
+	else
+		SendMessage(handle, UDM_SETRANGE32, (WPARAM)((short)lower),
+					(LPARAM)((short)upper));
+}
+
+/*
+ * Sets the entryfield character limit.
+ * Parameters:
+ *          handle: Handle to the spinbutton to be set.
+ *          limit: Number of characters the entryfield will take.
+ */
+void API dw_entryfield_set_limit(HWND handle, ULONG limit)
+{
+	SendMessage(handle, EM_SETLIMITTEXT, (WPARAM)limit, 0);
+}
+
+/*
+ * Returns the current value of the spinbutton.
+ * Parameters:
+ *          handle: Handle to the spinbutton to be queried.
+ */
+long API dw_spinbutton_query(HWND handle)
+{
+	if(IS_IE5PLUS)
+		return (long)SendMessage(handle, UDM_GETPOS32, 0, 0);
+	else
+		return (long)SendMessage(handle, UDM_GETPOS, 0, 0);
+}
+
+/*
+ * Returns the state of the checkbox.
+ * Parameters:
+ *          handle: Handle to the checkbox to be queried.
+ */
+int API dw_checkbox_query(HWND handle)
+{
+	if(SendMessage(handle, BM_GETCHECK, 0, 0) == BST_CHECKED)
+		return (in_checkbox_handler ? FALSE : TRUE);
+	return (in_checkbox_handler ? TRUE : FALSE);
+}
+
+/* This function unchecks all radiobuttons on a box */
+BOOL CALLBACK _uncheck_radios(HWND handle, LPARAM lParam)
+{
+	char tmpbuf[100];
+
+	GetClassName(handle, tmpbuf, 99);
+
+	if(strnicmp(tmpbuf, BUTTONCLASSNAME, strlen(BUTTONCLASSNAME)+1)==0)
+	{
+		BubbleButton *bubble= (BubbleButton *)GetWindowLongPtr(handle, GWLP_USERDATA);
+
+		if(bubble && !bubble->checkbox)
+			SendMessage(handle, BM_SETCHECK, 0, 0);
+	}
+	return TRUE;
+}
+/*
+ * Sets the state of the checkbox.
+ * Parameters:
+ *          handle: Handle to the checkbox to be queried.
+ *          value: TRUE for checked, FALSE for unchecked.
+ */
+void API dw_checkbox_set(HWND handle, int value)
+{
+	BubbleButton *bubble= (BubbleButton *)GetWindowLongPtr(handle, GWLP_USERDATA);
+
+	if(bubble && !bubble->checkbox)
+	{
+		HWND parent = GetParent(handle);
+
+		if(parent)
+			EnumChildWindows(parent, _uncheck_radios, 0);
+	}
+	SendMessage(handle, BM_SETCHECK, (WPARAM)value, 0);
+}
+
+/*
+ * Inserts an item into a tree window (widget) after another item.
+ * Parameters:
+ *          handle: Handle to the tree to be inserted.
+ *          item: Handle to the item to be positioned after.
+ *          title: The text title of the entry.
+ *          icon: Handle to coresponding icon.
+ *          parent: Parent handle or 0 if root.
+ *          itemdata: Item specific data.
+ */
+HTREEITEM API dw_tree_insert_after(HWND handle, HTREEITEM item, char *title, unsigned long icon, HTREEITEM parent, void *itemdata)
+{
+	TVITEM tvi;
+	TVINSERTSTRUCT tvins;
+	HTREEITEM hti;
+	void **ptrs= malloc(sizeof(void *) * 2);
+
+	ptrs[0] = title;
+	ptrs[1] = itemdata;
+
+	tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
+	tvi.pszText = title;
+	tvi.lParam = (LONG)ptrs;
+	tvi.cchTextMax = strlen(title);
+	tvi.iSelectedImage = tvi.iImage = _lookup_icon(handle, (HICON)icon, 1);
+
+	tvins.item = tvi;
+	tvins.hParent = parent;
+	tvins.hInsertAfter = item ? item : TVI_FIRST;
+
+	hti = TreeView_InsertItem(handle, &tvins);
+
+	return hti;
+}
+
+/*
+ * Inserts an item into a tree window (widget).
+ * Parameters:
+ *          handle: Handle to the tree to be inserted.
+ *          title: The text title of the entry.
+ *          icon: Handle to coresponding icon.
+ *          parent: Parent handle or 0 if root.
+ *          itemdata: Item specific data.
+ */
+HTREEITEM API dw_tree_insert(HWND handle, char *title, unsigned long icon, HTREEITEM parent, void *itemdata)
+{
+	TVITEM tvi;
+	TVINSERTSTRUCT tvins;
+	HTREEITEM hti;
+	void **ptrs= malloc(sizeof(void *) * 2);
+
+	ptrs[0] = title;
+	ptrs[1] = itemdata;
+
+	tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
+	tvi.pszText = title;
+	tvi.lParam = (LONG)ptrs;
+	tvi.cchTextMax = strlen(title);
+	tvi.iSelectedImage = tvi.iImage = _lookup_icon(handle, (HICON)icon, 1);
+
+	tvins.item = tvi;
+	tvins.hParent = parent;
+	tvins.hInsertAfter = TVI_LAST;
+
+	hti = TreeView_InsertItem(handle, &tvins);
+
+	return hti;
+}
+
+/*
+ * Sets the text and icon of an item in a tree window (widget).
+ * Parameters:
+ *          handle: Handle to the tree containing the item.
+ *          item: Handle of the item to be modified.
+ *          title: The text title of the entry.
+ *          icon: Handle to coresponding icon.
+ */
+void API dw_tree_set(HWND handle, HTREEITEM item, char *title, unsigned long icon)
+{
+	TVITEM tvi;
+	void **ptrs;
+
+	tvi.mask = TVIF_HANDLE;
+	tvi.hItem = item;
+
+	if(TreeView_GetItem(handle, &tvi))
+	{
+
+		ptrs = (void **)tvi.lParam;
+		ptrs[0] = title;
+
+		tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+		tvi.pszText = title;
+		tvi.cchTextMax = strlen(title);
+		tvi.iSelectedImage = tvi.iImage = _lookup_icon(handle, (HICON)icon, 1);
+		tvi.hItem = (HTREEITEM)item;
+
+		TreeView_SetItem(handle, &tvi);
+	}
+}
+
+/*
+ * Sets the item data of a tree item.
+ * Parameters:
+ *          handle: Handle to the tree containing the item.
+ *          item: Handle of the item to be modified.
+ *          itemdata: User defined data to be associated with item.
+ */
+void API dw_tree_set_data(HWND handle, HTREEITEM item, void *itemdata)
+{
+	TVITEM tvi;
+	void **ptrs;
+
+	tvi.mask = TVIF_HANDLE;
+	tvi.hItem = item;
+
+	if(TreeView_GetItem(handle, &tvi))
+	{
+		ptrs = (void **)tvi.lParam;
+		ptrs[1] = itemdata;
+	}
+}
+
+/*
+ * Gets the item data of a tree item.
+ * Parameters:
+ *          handle: Handle to the tree containing the item.
+ *          item: Handle of the item to be modified.
+ */
+void * API dw_tree_get_data(HWND handle, HTREEITEM item)
+{
+	TVITEM tvi;
+	void **ptrs;
+
+	tvi.mask = TVIF_HANDLE;
+	tvi.hItem = item;
+
+	if(TreeView_GetItem(handle, &tvi))
+	{
+		ptrs = (void **)tvi.lParam;
+		return ptrs[1];
+	}
+	return NULL;
+}
+
+/*
+ * Gets the text an item in a tree window (widget).
+ * Parameters:
+ *          handle: Handle to the tree containing the item.
+ *          item: Handle of the item to be modified.
+ */
+char * API dw_tree_get_title(HWND handle, HTREEITEM item)
+{
+	TVITEM tvi;
+
+	tvi.mask = TVIF_HANDLE;
+	tvi.hItem = item;
+
+	if(TreeView_GetItem(handle, &tvi))
+		return tvi.pszText;
+    return NULL;
+}
+
+/*
+ * Gets the text an item in a tree window (widget).
+ * Parameters:
+ *          handle: Handle to the tree containing the item.
+ *          item: Handle of the item to be modified.
+ */
+HTREEITEM API dw_tree_get_parent(HWND handle, HTREEITEM item)
+{
+	return TreeView_GetParent(handle, item);
+}
+
+/*
+ * Sets this item as the active selection.
+ * Parameters:
+ *       handle: Handle to the tree window (widget) to be selected.
+ *       item: Handle to the item to be selected.
+ */
+void API dw_tree_item_select(HWND handle, HTREEITEM item)
+{
+	dw_window_set_data(handle, "_dw_select_item", (void *)1);
+	TreeView_SelectItem(handle, item);
+	dw_window_set_data(handle, "_dw_select_item", (void *)0);
+}
+
+/* Delete all tree subitems */
+void _dw_tree_delete_recursive(HWND handle, HTREEITEM node)
+{
+	HTREEITEM hti;
+
+	hti = TreeView_GetChild(handle, node);
+
+	while(hti)
+	{
+		HTREEITEM lastitem = hti;
+
+		hti = TreeView_GetNextSibling(handle, hti);
+		dw_tree_delete(handle, lastitem);
+	}
+}
+
+/*
+ * Removes all nodes from a tree.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be cleared.
+ */
+void API dw_tree_clear(HWND handle)
+{
+	HTREEITEM hti = TreeView_GetRoot(handle);
+
+	dw_window_set_data(handle, "_dw_select_item", (void *)1);
+	while(hti)
+	{
+		HTREEITEM lastitem = hti;
+
+		_dw_tree_delete_recursive(handle, hti);
+		hti = TreeView_GetNextSibling(handle, hti);
+		dw_tree_delete(handle, lastitem);
+	}
+	dw_window_set_data(handle, "_dw_select_item", (void *)0);
+}
+
+/*
+ * Expands a node on a tree.
+ * Parameters:
+ *       handle: Handle to the tree window (widget).
+ *       item: Handle to node to be expanded.
+ */
+void API dw_tree_expand(HWND handle, HTREEITEM item)
+{
+	TreeView_Expand(handle, item, TVE_EXPAND);
+}
+
+/*
+ * Collapses a node on a tree.
+ * Parameters:
+ *       handle: Handle to the tree window (widget).
+ *       item: Handle to node to be collapsed.
+ */
+void API dw_tree_collapse(HWND handle, HTREEITEM item)
+{
+	TreeView_Expand(handle, item, TVE_COLLAPSE);
+}
+
+/*
+ * Removes a node from a tree.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be cleared.
+ *       item: Handle to node to be deleted.
+ */
+void API dw_tree_delete(HWND handle, HTREEITEM item)
+{
+	TVITEM tvi;
+	void **ptrs;
+
+	if(item == TVI_ROOT || !item)
+		return;
+
+	tvi.mask = TVIF_HANDLE;
+	tvi.hItem = item;
+
+	if(TreeView_GetItem(handle, &tvi))
+		ptrs = (void **)tvi.lParam;
+
+	_dw_tree_delete_recursive(handle, item);
+	TreeView_DeleteItem(handle, item);
+	if(ptrs)
+		free(ptrs);
+}
+
+/*
+ * Sets up the container columns.
+ * Parameters:
+ *          handle: Handle to the container to be configured.
+ *          flags: An array of unsigned longs with column flags.
+ *          titles: An array of strings with column text titles.
+ *          count: The number of columns (this should match the arrays).
+ *          separator: The column number that contains the main separator.
+ *                     (only used on OS/2 but must be >= 0 on all)
+ */
+int API dw_container_setup(HWND handle, unsigned long *flags, char **titles, int count, int separator)
+{
+	ContainerInfo *cinfo = (ContainerInfo *)GetWindowLongPtr(handle, GWLP_USERDATA);
+	int z, l = 0;
+	unsigned long *tempflags = calloc(sizeof(unsigned long), count + 2);
+	LVCOLUMN lvc;
+
+	if(separator == -1)
+	{
+		tempflags[0] = DW_CFA_RESERVED;
+		l = 1;
+	}
+
+	memcpy(&tempflags[l], flags, sizeof(unsigned long) * count);
+	tempflags[count + l] = 0;
+	cinfo->flags = tempflags;
+	cinfo->columns = count + l;
+
+
+	for(z=0;z<count;z++)
+	{
+		if(titles[z])
+		{
+			lvc.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_FMT;
+			lvc.pszText = titles[z];
+			lvc.cchTextMax = strlen(titles[z]);
+			if(flags[z] & DW_CFA_RIGHT)
+				lvc.fmt = LVCFMT_RIGHT;
+			else if(flags[z] & DW_CFA_CENTER)
+				lvc.fmt = LVCFMT_CENTER;
+			else
+				lvc.fmt = LVCFMT_LEFT;
+			lvc.cx = 75;
+			lvc.iSubItem = count;
+			SendMessage(handle, LVM_INSERTCOLUMN, (WPARAM)z + l, (LPARAM)&lvc);
+		}
+	}
+	ListView_SetExtendedListViewStyle(handle, LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES);
+	return TRUE;
+}
+
+/*
+ * Sets up the filesystem columns, note: filesystem always has an icon/filename field.
+ * Parameters:
+ *          handle: Handle to the container to be configured.
+ *          flags: An array of unsigned longs with column flags.
+ *          titles: An array of strings with column text titles.
+ *          count: The number of columns (this should match the arrays).
+ */
+int API dw_filesystem_setup(HWND handle, unsigned long *flags, char **titles, int count)
+{
+	LV_COLUMN lvc;
+
+	lvc.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
+	lvc.pszText = "Filename";
+	lvc.cchTextMax = 8;
+	lvc.fmt = 0;
+	if(!count)
+		lvc.cx = 300;
+	else
+		lvc.cx = 150;
+	lvc.iSubItem = count;
+	SendMessage(handle, LVM_INSERTCOLUMN, (WPARAM)0, (LPARAM)&lvc);
+	dw_container_setup(handle, flags, titles, count, -1);
+	return TRUE;
+}
+
+/*
+ * Obtains an icon from a module (or header in GTK).
+ * Parameters:
+ *          module: Handle to module (DLL) in OS/2 and Windows.
+ *          id: A unsigned long id int the resources on OS/2 and
+ *              Windows, on GTK this is converted to a pointer
+ *              to an embedded XPM.
+ */
+unsigned long API dw_icon_load(unsigned long module, unsigned long id)
+{
+	return (unsigned long)LoadIcon(DWInstance, MAKEINTRESOURCE(id));
+}
+
+/*
+ * Obtains an icon from a file.
+ * Parameters:
+ *       filename: Name of the file, omit extention to have
+ *                 DW pick the appropriate file extension.
+ *                 (ICO on OS/2 or Windows, XPM on Unix)
+ */
+unsigned long API dw_icon_load_from_file(char *filename)
+{
+	char *file = malloc(strlen(filename) + 5);
+	HANDLE icon;
+
+	if(!file)
+		return 0;
+
+	strcpy(file, filename);
+
+	/* check if we can read from this file (it exists and read permission) */
+	if(access(file, 04) != 0)
+	{
+		/* Try with .bmp extention */
+		strcat(file, ".ico");
+		if(access(file, 04) != 0)
+		{
+			free(file);
+			return 0;
+		}
+	}
+	icon = LoadImage(NULL, file, IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
+	free(file);
+	return (unsigned long)icon;
+}
+
+/*
+ * Frees a loaded resource in OS/2 and Windows.
+ * Parameters:
+ *          handle: Handle to icon returned by dw_icon_load().
+ */
+void API dw_icon_free(unsigned long handle)
+{
+	DestroyIcon((HICON)handle);
+}
+
+/*
+ * Allocates memory used to populate a container.
+ * Parameters:
+ *          handle: Handle to the container window (widget).
+ *          rowcount: The number of items to be populated.
+ */
+void * API dw_container_alloc(HWND handle, int rowcount)
+{
+	LV_ITEM lvi;
+	int z;
+
+	lvi.mask = LVIF_DI_SETITEM | LVIF_TEXT | LVIF_IMAGE;
+	lvi.iSubItem = 0;
+	/* Insert at the end */
+	lvi.iItem = 1000000;
+	lvi.pszText = "";
+	lvi.cchTextMax = 1;
+	lvi.iImage = -1;
+
+	ShowWindow(handle, SW_HIDE);
+	for(z=0;z<rowcount;z++)
+		ListView_InsertItem(handle, &lvi);
+	return (void *)handle;
+}
+
+/* Finds a icon in the table, otherwise it adds it to the table
+ * and returns the index in the table.
+ */
+int _lookup_icon(HWND handle, HICON hicon, int type)
+{
+	int z;
+	static HWND lasthwnd = NULL;
+
+	if(!hSmall || !hLarge)
+	{
+		hSmall = ImageList_Create(16, 16, ILC_COLOR16 | ILC_MASK, ICON_INDEX_LIMIT, 0);
+		hLarge = ImageList_Create(32, 32, ILC_COLOR16 | ILC_MASK, ICON_INDEX_LIMIT, 0);
+	}
+	for(z=0;z<ICON_INDEX_LIMIT;z++)
+	{
+		if(!lookup[z])
+		{
+			lookup[z] = hicon;
+			ImageList_AddIcon(hSmall, hicon);
+			ImageList_AddIcon(hLarge, hicon);
+			if(type)
+			{
+				TreeView_SetImageList(handle, hSmall, TVSIL_NORMAL);
+			}
+			else
+			{
+				ListView_SetImageList(handle, hSmall, LVSIL_SMALL);
+				ListView_SetImageList(handle, hLarge, LVSIL_NORMAL);
+			}
+			lasthwnd = handle;
+			return z;
+		}
+
+		if(hicon == lookup[z])
+		{
+			if(lasthwnd != handle)
+			{
+				if(type)
+				{
+					TreeView_SetImageList(handle, hSmall, TVSIL_NORMAL);
+				}
+				else
+				{
+					ListView_SetImageList(handle, hSmall, LVSIL_SMALL);
+					ListView_SetImageList(handle, hLarge, LVSIL_NORMAL);
+				}
+                lasthwnd = handle;
+			}
+			return z;
+		}
+	}
+	return -1;
+}
+
+/*
+ * Sets an item in specified row and column to the given data.
+ * Parameters:
+ *          handle: Handle to the container window (widget).
+ *          pointer: Pointer to the allocated memory in dw_container_alloc().
+ *          column: Zero based column of data being set.
+ *          row: Zero based row of data being set.
+ *          data: Pointer to the data to be added.
+ */
+void API dw_filesystem_set_file(HWND handle, void *pointer, int row, char *filename, unsigned long icon)
+{
+	LV_ITEM lvi;
+
+	lvi.iItem = row;
+	lvi.iSubItem = 0;
+	lvi.mask = LVIF_DI_SETITEM | LVIF_IMAGE | LVIF_TEXT;
+	lvi.pszText = filename;
+	lvi.cchTextMax = strlen(filename);
+	lvi.iImage = _lookup_icon(handle, (HICON)icon, 0);
+
+	ListView_SetItem(handle, &lvi);
+}
+
+/*
+ * Sets an item in specified row and column to the given data.
+ * Parameters:
+ *          handle: Handle to the container window (widget).
+ *          pointer: Pointer to the allocated memory in dw_container_alloc().
+ *          column: Zero based column of data being set.
+ *          row: Zero based row of data being set.
+ *          data: Pointer to the data to be added.
+ */
+void API dw_filesystem_set_item(HWND handle, void *pointer, int column, int row, void *data)
+{
+	dw_container_set_item(handle, pointer, column + 1, row, data);
+}
+
+/*
+ * Sets an item in specified row and column to the given data.
+ * Parameters:
+ *          handle: Handle to the container window (widget).
+ *          pointer: Pointer to the allocated memory in dw_container_alloc().
+ *          column: Zero based column of data being set.
+ *          row: Zero based row of data being set.
+ *          data: Pointer to the data to be added.
+ */
+void API dw_container_set_item(HWND handle, void *pointer, int column, int row, void *data)
+{
+	ContainerInfo *cinfo = (ContainerInfo *)GetWindowLongPtr(handle, GWLP_USERDATA);
+	ULONG *flags;
+	LV_ITEM lvi;
+	char textbuffer[100], *destptr = textbuffer;
+
+	if(!cinfo || !cinfo->flags || !data)
+		return;
+
+	flags = cinfo->flags;
+
+	lvi.mask = LVIF_DI_SETITEM | LVIF_TEXT;
+	lvi.iItem = row;
+	lvi.iSubItem = column;
+
+	if(flags[column] & DW_CFA_BITMAPORICON)
+	{
+		HICON hicon = *((HICON *)data);
+
+		lvi.mask = LVIF_DI_SETITEM | LVIF_IMAGE;
+		lvi.pszText = NULL;
+		lvi.cchTextMax = 0;
+
+		lvi.iImage = _lookup_icon(handle, hicon, 0);
+	}
+	else if(flags[column] & DW_CFA_STRING)
+	{
+		char *tmp = *((char **)data);
+
+		if(!tmp)
+			tmp = "";
+
+		lvi.pszText = tmp;
+		lvi.cchTextMax = strlen(tmp);
+		destptr = tmp;
+	}
+	else if(flags[column] & DW_CFA_ULONG)
+	{
+		ULONG tmp = *((ULONG *)data);
+
+		sprintf(textbuffer, "%lu", tmp);
+
+		lvi.pszText = textbuffer;
+		lvi.cchTextMax = strlen(textbuffer);
+	}
+	else if(flags[column] & DW_CFA_DATE)
+	{
+		struct tm curtm;
+		CDATE cdate = *((CDATE *)data);
+
+		curtm.tm_mday = cdate.day;
+		curtm.tm_mon = cdate.month - 1;
+		curtm.tm_year = cdate.year - 1900;
+
+		strftime(textbuffer, 100, "%x", &curtm);
+
+		lvi.pszText = textbuffer;
+		lvi.cchTextMax = strlen(textbuffer);
+	}
+	else if(flags[column] & DW_CFA_TIME)
+	{
+		struct tm curtm;
+		CTIME ctime = *((CTIME *)data);
+
+		curtm.tm_hour = ctime.hours;
+		curtm.tm_min = ctime.minutes;
+		curtm.tm_sec = ctime.seconds;
+
+		strftime(textbuffer, 100, "%X", &curtm);
+
+		lvi.pszText = textbuffer;
+		lvi.cchTextMax = strlen(textbuffer);
+	}
+
+	ListView_SetItem(handle, &lvi);
+}
+
+/*
+ * Changes an existing item in specified row and column to the given data.
+ * Parameters:
+ *          handle: Handle to the container window (widget).
+ *          column: Zero based column of data being set.
+ *          row: Zero based row of data being set.
+ *          data: Pointer to the data to be added.
+ */
+void API dw_container_change_item(HWND handle, int column, int row, void *data)
+{
+	dw_container_set_item(handle, NULL, column, row, data);
+}
+
+/*
+ * Sets the width of a column in the container.
+ * Parameters:
+ *          handle: Handle to window (widget) of container.
+ *          column: Zero based column of width being set.
+ *          width: Width of column in pixels.
+ */
+void API dw_container_set_column_width(HWND handle, int column, int width)
+{
+	ListView_SetColumnWidth(handle, column, width);
+}
+
+/*
+ * Sets the title of a row in the container.
+ * Parameters:
+ *          pointer: Pointer to the allocated memory in dw_container_alloc().
+ *          row: Zero based row of data being set.
+ *          title: String title of the item.
+ */
+void API dw_container_set_row_title(void *pointer, int row, char *title)
+{
+	LV_ITEM lvi;
+	HWND container = (HWND)pointer;
+
+	lvi.iItem = row;
+	lvi.iSubItem = 0;
+	lvi.mask = LVIF_PARAM;
+	lvi.lParam = (LPARAM)title;
+
+	if(!ListView_SetItem(container, &lvi) && lvi.lParam)
+		lvi.lParam = 0;
+
+}
+
+/*
+ * Sets the title of a row in the container.
+ * Parameters:
+ *          handle: Handle to the container window (widget).
+ *          pointer: Pointer to the allocated memory in dw_container_alloc().
+ *          rowcount: The number of rows to be inserted.
+ */
+void API dw_container_insert(HWND handle, void *pointer, int rowcount)
+{
+	ShowWindow(handle, SW_SHOW);
+}
+
+/*
+ * Removes all rows from a container.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be cleared.
+ *       redraw: TRUE to cause the container to redraw immediately.
+ */
+void API dw_container_clear(HWND handle, int redraw)
+{
+	ListView_DeleteAllItems(handle);
+}
+
+/*
+ * Removes the first x rows from a container.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be deleted from.
+ *       rowcount: The number of rows to be deleted.
+ */
+void API dw_container_delete(HWND handle, int rowcount)
+{
+	int z;
+
+	for(z=0;z<rowcount;z++)
+	{
+		ListView_DeleteItem(handle, 0);
+	}
+}
+
+/*
+ * Scrolls container up or down.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be scrolled.
+ *       direction: DW_SCROLL_UP, DW_SCROLL_DOWN, DW_SCROLL_TOP or
+ *                  DW_SCROLL_BOTTOM. (rows is ignored for last two)
+ *       rows: The number of rows to be scrolled.
+ */
+void API dw_container_scroll(HWND handle, int direction, long rows)
+{
+	switch(direction)
+	{
+	case DW_SCROLL_TOP:
+		ListView_Scroll(handle, 0, -10000000);
+        break;
+	case DW_SCROLL_BOTTOM:
+		ListView_Scroll(handle, 0, 10000000);
+		break;
+	}
+}
+
+/*
+ * Starts a new query of a container.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be queried.
+ *       flags: If this parameter is DW_CRA_SELECTED it will only
+ *              return items that are currently selected.  Otherwise
+ *              it will return all records in the container.
+ */
+char * API dw_container_query_start(HWND handle, unsigned long flags)
+{
+	LV_ITEM lvi;
+
+	_index = ListView_GetNextItem(handle, -1, flags);
+
+	if(_index == -1)
+		return NULL;
+
+	memset(&lvi, 0, sizeof(LV_ITEM));
+
+	lvi.iItem = _index;
+	lvi.mask = LVIF_PARAM;
+
+	ListView_GetItem(handle, &lvi);
+
+	return (char *)lvi.lParam;
+}
+
+/*
+ * Continues an existing query of a container.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be queried.
+ *       flags: If this parameter is DW_CRA_SELECTED it will only
+ *              return items that are currently selected.  Otherwise
+ *              it will return all records in the container.
+ */
+char * API dw_container_query_next(HWND handle, unsigned long flags)
+{
+	LV_ITEM lvi;
+
+	_index = ListView_GetNextItem(handle, _index, flags);
+
+	if(_index == -1)
+		return NULL;
+
+	memset(&lvi, 0, sizeof(LV_ITEM));
+
+	lvi.iItem = _index;
+	lvi.mask = LVIF_PARAM;
+
+	ListView_GetItem(handle, &lvi);
+
+	return (char *)lvi.lParam;
+}
+
+/*
+ * Cursors the item with the text speficied, and scrolls to that item.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be queried.
+ *       text:  Text usually returned by dw_container_query().
+ */
+void API dw_container_cursor(HWND handle, char *text)
+{
+	int index = ListView_GetNextItem(handle, -1, LVNI_ALL);
+
+	while(index != -1)
+	{
+		LV_ITEM lvi;
+
+		memset(&lvi, 0, sizeof(LV_ITEM));
+
+		lvi.iItem = index;
+		lvi.mask = LVIF_PARAM;
+
+		ListView_GetItem(handle, &lvi);
+
+		if((char *)lvi.lParam == text)
+		{
+			RECT viewport, item;
+
+			ListView_SetItemState(handle, index, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
+			ListView_EnsureVisible(handle, index, TRUE);
+			return;
+		}
+
+        index = ListView_GetNextItem(handle, index, LVNI_ALL);
+	}
+}
+
+/*
+ * Deletes the item with the text speficied.
+ * Parameters:
+ *       handle: Handle to the window (widget).
+ *       text:  Text usually returned by dw_container_query().
+ */
+void API dw_container_delete_row(HWND handle, char *text)
+{
+	int index = ListView_GetNextItem(handle, -1, LVNI_ALL);
+
+	while(index != -1)
+	{
+		LV_ITEM lvi;
+
+		memset(&lvi, 0, sizeof(LV_ITEM));
+
+		lvi.iItem = index;
+		lvi.mask = LVIF_PARAM;
+
+		ListView_GetItem(handle, &lvi);
+
+		if((char *)lvi.lParam == text)
+		{
+			ListView_DeleteItem(handle, index);
+			return;
+		}
+
+        index = ListView_GetNextItem(handle, index, LVNI_ALL);
+	}
+}
+
+/*
+ * Optimizes the column widths so that all data is visible.
+ * Parameters:
+ *       handle: Handle to the window (widget) to be optimized.
+ */
+void API dw_container_optimize(HWND handle)
+{
+	ContainerInfo *cinfo = (ContainerInfo *)GetWindowLongPtr(handle, GWLP_USERDATA);
+	ULONG *flags;
+	LV_ITEM lvi;
+
+	if(cinfo && cinfo->columns == 1)
+	{
+		ListView_SetColumnWidth(handle, 0, LVSCW_AUTOSIZE);
+	}
+	else if(cinfo && cinfo->columns > 1)
+	{
+		int z, index;
+		ULONG *flags = cinfo->flags, *columns = calloc(sizeof(ULONG), cinfo->columns);
+		char *text = malloc(1024);
+
+		/* Initialize with sizes of column labels */
+		for(z=0;z<cinfo->columns;z++)
+		{
+			if(flags[z] & DW_CFA_BITMAPORICON)
+				columns[z] = 5;
+			else
+			{
+				LVCOLUMN lvc;
+
+				lvc.mask = LVCF_TEXT;
+				lvc.cchTextMax = 1023;
+				lvc.pszText = text;
+
+				if(ListView_GetColumn(handle, z, &lvc))
+					columns[z] = ListView_GetStringWidth(handle, lvc.pszText);
+
+				if(flags[z] & DW_CFA_RESERVED)
+					columns[z] += 20;
+			}
+		}
+
+		index = ListView_GetNextItem(handle, -1, LVNI_ALL);
+
+		/* Query all the item texts */
+		while(index != -1)
+		{
+			for(z=0;z<cinfo->columns;z++)
+			{
+				LV_ITEM lvi;
+
+				memset(&lvi, 0, sizeof(LV_ITEM));
+
+				lvi.iItem = index;
+				lvi.iSubItem = z;
+				lvi.mask = LVIF_TEXT;
+				lvi.cchTextMax = 1023;
+				lvi.pszText = text;
+
+				if(ListView_GetItem(handle, &lvi))
+				{
+					int width = ListView_GetStringWidth(handle, lvi.pszText);
+					if(width > columns[z])
+					{
+						if(z == 0)
+							columns[z] = width + 20;
+						else
+							columns[z] = width;
+					}
+				}
+			}
+
+			index = ListView_GetNextItem(handle, index, LVNI_ALL);
+		}
+
+		/* Set the new sizes */
+		for(z=0;z<cinfo->columns;z++)
+			ListView_SetColumnWidth(handle, z, columns[z] + 16);
+
+		free(columns);
+		free(text);
+	}
+}
+
+/*
+ * Inserts an icon into the taskbar.
+ * Parameters:
+ *       handle: Window handle that will handle taskbar icon messages.
+ *       icon: Icon handle to display in the taskbar.
+ *       bubbletext: Text to show when the mouse is above the icon.
+ */
+void dw_taskbar_insert(HWND handle, unsigned long icon, char *bubbletext)
+{
+	NOTIFYICONDATA tnid;
+ 
+	tnid.cbSize = sizeof(NOTIFYICONDATA);
+	tnid.hWnd = handle;
+	tnid.uID = icon;
+	tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
+	tnid.uCallbackMessage = WM_USER+2;
+	tnid.hIcon = (HICON)icon;
+	if(bubbletext)
+		strncpy(tnid.szTip, bubbletext, sizeof(tnid.szTip));
+	else
+		tnid.szTip[0] = 0;
+
+	Shell_NotifyIcon(NIM_ADD, &tnid);
+}
+
+/*
+ * Deletes an icon from the taskbar.
+ * Parameters:
+ *       handle: Window handle that was used with dw_taskbar_insert().
+ *       icon: Icon handle that was used with dw_taskbar_insert().
+ */
+void dw_taskbar_delete(HWND handle, unsigned long icon)
+{
+	NOTIFYICONDATA tnid;
+
+	tnid.cbSize = sizeof(NOTIFYICONDATA);
+	tnid.hWnd = handle;
+	tnid.uID = icon;
+
+	Shell_NotifyIcon(NIM_DELETE, &tnid);
+}
+
+/*
+ * Creates a rendering context widget (window) to be packed.
+ * Parameters:
+ *       id: An id to be used with dw_window_from_id.
+ * Returns:
+ *       A handle to the widget or NULL on failure.
+ */
+HWND API dw_render_new(unsigned long id)
+{
+	Box *newbox = calloc(sizeof(Box), 1);
+	HWND tmp = CreateWindow(ObjectClassName,
+							"",
+							WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN,
+							0,0,2000,1000,
+							DW_HWND_OBJECT,
+							(HMENU)id,
+							DWInstance,
+							NULL);
+	newbox->pad = 0;
+	newbox->type = 0;
+	newbox->count = 0;
+	newbox->grouphwnd = (HWND)NULL;
+	newbox->cinfo.pOldProc = SubclassWindow(tmp, _rendwndproc);
+	newbox->cinfo.fore = newbox->cinfo.back = -1;
+
+	SetWindowLongPtr(tmp, GWLP_USERDATA, (LONG_PTR)newbox);
+	return tmp;
+}
+
+/* Sets the current foreground drawing color.
+ * Parameters:
+ *       red: red value.
+ *       green: green value.
+ *       blue: blue value.
+ */
+void API dw_color_foreground_set(unsigned long value)
+{
+	int threadid = dw_thread_id();
+
+	if(threadid < 0 || threadid >= THREAD_LIMIT)
+		threadid = 0;
+
+	value = _internal_color(value);
+
+	DeleteObject(_hPen[threadid]);
+	DeleteObject(_hBrush[threadid]);
+	_foreground[threadid] = RGB(DW_RED_VALUE(value), DW_GREEN_VALUE(value), DW_BLUE_VALUE(value));
+	_hPen[threadid] = CreatePen(PS_SOLID, 1, _foreground[threadid]);
+	_hBrush[threadid] = CreateSolidBrush(_foreground[threadid]);
+}
+
+/* Sets the current background drawing color.
+ * Parameters:
+ *       red: red value.
+ *       green: green value.
+ *       blue: blue value.
+ */
+void API dw_color_background_set(unsigned long value)
+{
+	int threadid = dw_thread_id();
+
+	if(threadid < 0 || threadid >= THREAD_LIMIT)
+		threadid = 0;
+
+	value = _internal_color(value);
+
+	if(value == DW_RGB_TRANSPARENT)
+		_background[threadid] = DW_RGB_TRANSPARENT;
+	else
+		_background[threadid] = RGB(DW_RED_VALUE(value), DW_GREEN_VALUE(value), DW_BLUE_VALUE(value));
+}
+
+/* Draw a point on a window (preferably a render window).
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       x: X coordinate.
+ *       y: Y coordinate.
+ */
+void API dw_draw_point(HWND handle, HPIXMAP pixmap, int x, int y)
+{
+	HDC hdcPaint;
+	int threadid = dw_thread_id();
+
+	if(threadid < 0 || threadid >= THREAD_LIMIT)
+		threadid = 0;
+
+	if(handle)
+		hdcPaint = GetDC(handle);
+	else if(pixmap)
+		hdcPaint = pixmap->hdc;
+	else
+		return;
+
+	SetPixel(hdcPaint, x, y, _foreground[threadid]);
+	if(!pixmap)
+		ReleaseDC(handle, hdcPaint);
+}
+
+/* Draw a line on a window (preferably a render window).
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       x1: First X coordinate.
+ *       y1: First Y coordinate.
+ *       x2: Second X coordinate.
+ *       y2: Second Y coordinate.
+ */
+void API dw_draw_line(HWND handle, HPIXMAP pixmap, int x1, int y1, int x2, int y2)
+{
+	HDC hdcPaint;
+	HPEN oldPen;
+	int threadid = dw_thread_id();
+
+	if(threadid < 0 || threadid >= THREAD_LIMIT)
+		threadid = 0;
+
+	if(handle)
+		hdcPaint = GetDC(handle);
+	else if(pixmap)
+		hdcPaint = pixmap->hdc;
+	else
+		return;
+
+	oldPen = SelectObject(hdcPaint, _hPen[threadid]);
+	MoveToEx(hdcPaint, x1, y1, NULL);
+	LineTo(hdcPaint, x2, y2);
+	SelectObject(hdcPaint, oldPen);
+	/* For some reason Win98 (at least) fails
+	 * to draw the last pixel.  So I do it myself.
+	 */
+	SetPixel(hdcPaint, x2, y2, _foreground[threadid]);
+	if(!pixmap)
+		ReleaseDC(handle, hdcPaint);
+}
+
+/* Draw a rectangle on a window (preferably a render window).
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       x: X coordinate.
+ *       y: Y coordinate.
+ *       width: Width of rectangle.
+ *       height: Height of rectangle.
+ */
+void API dw_draw_rect(HWND handle, HPIXMAP pixmap, int fill, int x, int y, int width, int height)
+{
+	HDC hdcPaint;
+	HPEN oldPen;
+	HBRUSH oldBrush;
+	RECT Rect;
+	int threadid = dw_thread_id();
+
+	if(threadid < 0 || threadid >= THREAD_LIMIT)
+		threadid = 0;
+
+	if(handle)
+		hdcPaint = GetDC(handle);
+	else if(pixmap)
+		hdcPaint = pixmap->hdc;
+	else
+		return;
+
+	SetRect(&Rect, x, y, x + width , y + height );
+	if(fill)
+		FillRect(hdcPaint, &Rect, _hBrush[threadid]);
+	else
+		FrameRect(hdcPaint, &Rect, _hBrush[threadid]);
+	if(!pixmap)
+		ReleaseDC(handle, hdcPaint);
+}
+
+/* Draw text on a window (preferably a render window).
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       x: X coordinate.
+ *       y: Y coordinate.
+ *       text: Text to be displayed.
+ */
+void API dw_draw_text(HWND handle, HPIXMAP pixmap, int x, int y, char *text)
+{
+	HDC hdc;
+	int size = 9, z, mustdelete = 0;
+	HFONT hFont = 0, oldFont = 0;
+	int threadid = dw_thread_id();
+	ColorInfo *cinfo;
+
+	if(threadid < 0 || threadid >= THREAD_LIMIT)
+		threadid = 0;
+
+	if(handle)
+		hdc = GetDC(handle);
+	else if(pixmap)
+		hdc = pixmap->hdc;
+	else
+		return;
+
+	if(handle)
+		cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA);
+	else
+		cinfo = (ColorInfo *)GetWindowLongPtr(pixmap->handle, GWLP_USERDATA);
+
+	if(cinfo)
+	{
+		hFont = _acquire_font(handle, cinfo->fontname);
+		mustdelete = 1;
+	}
+
+	if(hFont)
+		oldFont = SelectObject(hdc, hFont);
+	SetTextColor(hdc, _foreground[threadid]);
+	if(_background[threadid] == DW_RGB_TRANSPARENT)
+		SetBkMode(hdc, TRANSPARENT);
+	else
+	{
+		SetBkMode(hdc, OPAQUE);
+		SetBkColor(hdc, _background[threadid]);
+	}
+	TextOut(hdc, x, y, text, strlen(text));
+	if(oldFont)
+		SelectObject(hdc, oldFont);
+	if(mustdelete)
+		DeleteObject(hFont);
+	if(!pixmap)
+		ReleaseDC(handle, hdc);
+}
+
+/* Query the width and height of a text string.
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       text: Text to be queried.
+ *       width: Pointer to a variable to be filled in with the width.
+ *       height Pointer to a variable to be filled in with the height.
+ */
+void API dw_font_text_extents(HWND handle, HPIXMAP pixmap, char *text, int *width, int *height)
+{
+	HDC hdc;
+	int mustdelete = 0;
+	HFONT hFont = NULL, oldFont;
+	SIZE sz;
+
+	if(handle)
+		hdc = GetDC(handle);
+	else if(pixmap)
+		hdc = pixmap->hdc;
+	else
+		return;
+
+	{
+		ColorInfo *cinfo;
+
+		if(handle)
+			cinfo = (ColorInfo *)GetWindowLongPtr(handle, GWLP_USERDATA);
+		else
+			cinfo = (ColorInfo *)GetWindowLongPtr(pixmap->handle, GWLP_USERDATA);
+
+		if(cinfo)
+		{
+			hFont = _acquire_font(handle, cinfo->fontname);
+			mustdelete = 1;
+		}
+	}
+	oldFont = SelectObject(hdc, hFont);
+
+	GetTextExtentPoint32(hdc, text, strlen(text), &sz);
+
+	if(width)
+		*width = sz.cx;
+
+	if(height)
+		*height = sz.cy;
+
+	SelectObject(hdc, oldFont);
+	if(mustdelete)
+		DeleteObject(hFont);
+	if(!pixmap)
+		ReleaseDC(handle, hdc);
+}
+
+/* Call this after drawing to the screen to make sure
+ * anything you have drawn is visible.
+ */
+void API dw_flush(void)
+{
+}
+
+/*
+ * Creates a pixmap with given parameters.
+ * Parameters:
+ *       handle: Window handle the pixmap is associated with.
+ *       width: Width of the pixmap in pixels.
+ *       height: Height of the pixmap in pixels.
+ *       depth: Color depth of the pixmap.
+ * Returns:
+ *       A handle to a pixmap or NULL on failure.
+ */
+HPIXMAP API dw_pixmap_new(HWND handle, unsigned long width, unsigned long height, int depth)
+{
+	HPIXMAP pixmap;
+	BITMAP bm;
+	HDC hdc;
+
+	if (!(pixmap = calloc(1,sizeof(struct _hpixmap))))
+		return NULL;
+
+	hdc = GetDC(handle);
+
+	pixmap->width = width; pixmap->height = height;
+
+	pixmap->handle = handle;
+	pixmap->hbm = CreateCompatibleBitmap(hdc, width, height);
+	pixmap->hdc = CreateCompatibleDC(hdc);
+
+	SelectObject(pixmap->hdc, pixmap->hbm);
+
+	ReleaseDC(handle, hdc);
+
+	return pixmap;
+}
+
+/*
+ * Creates a pixmap from a file.
+ * Parameters:
+ *       handle: Window handle the pixmap is associated with.
+ *       filename: Name of the file, omit extention to have
+ *                 DW pick the appropriate file extension.
+ *                 (BMP on OS/2 or Windows, XPM on Unix)
+ * Returns:
+ *       A handle to a pixmap or NULL on failure.
+ */
+HPIXMAP API dw_pixmap_new_from_file(HWND handle, char *filename)
+{
+	HPIXMAP pixmap;
+	BITMAP bm;
+	HDC hdc;
+	char *file = malloc(strlen(filename) + 5);
+
+	if (!file || !(pixmap = calloc(1,sizeof(struct _hpixmap))))
+	{
+		if(file)
+			free(file);
+		return NULL;
+	}
+
+	strcpy(file, filename);
+
+	/* check if we can read from this file (it exists and read permission) */
+	if(access(file, 04) != 0)
+	{
+		/* Try with .bmp extention */
+		strcat(file, ".bmp");
+		if(access(file, 04) != 0)
+		{
+			free(pixmap);
+			free(file);
+			return NULL;
+		}
+	}
+
+	hdc = GetDC(handle);
+
+	pixmap->handle = handle;
+	pixmap->hbm = (HBITMAP)LoadImage(NULL, file, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
+
+	if(!pixmap->hbm)
+	{
+		free(file);
+		free(pixmap);
+		ReleaseDC(handle, hdc);
+		return NULL;
+	}
+
+	pixmap->hdc = CreateCompatibleDC(hdc);
+
+    GetObject(pixmap->hbm, sizeof(bm), &bm);
+
+	pixmap->width = bm.bmWidth; pixmap->height = bm.bmHeight;
+
+	SelectObject(pixmap->hdc, pixmap->hbm);
+
+	ReleaseDC(handle, hdc);
+
+	free(file);
+
+	return pixmap;
+}
+
+/*
+ * Creates a pixmap from internal resource graphic specified by id.
+ * Parameters:
+ *       handle: Window handle the pixmap is associated with.
+ *       id: Resource ID associated with requested pixmap.
+ * Returns:
+ *       A handle to a pixmap or NULL on failure.
+ */
+HPIXMAP API dw_pixmap_grab(HWND handle, ULONG id)
+{
+	HPIXMAP pixmap;
+	BITMAP bm;
+	HDC hdc;
+
+	if (!(pixmap = calloc(1,sizeof(struct _hpixmap))))
+		return NULL;
+
+	hdc = GetDC(handle);
+
+
+	pixmap->hbm = LoadBitmap(DWInstance, MAKEINTRESOURCE(id));
+	pixmap->hdc = CreateCompatibleDC(hdc);
+
+	GetObject(pixmap->hbm, sizeof(BITMAP), (void *)&bm);
+
+	pixmap->width = bm.bmWidth; pixmap->height = bm.bmHeight;
+
+	SelectObject(pixmap->hdc, pixmap->hbm);
+
+	ReleaseDC(handle, hdc);
+
+	return pixmap;
+}
+
+/*
+ * Destroys an allocated pixmap.
+ * Parameters:
+ *       pixmap: Handle to a pixmap returned by
+ *               dw_pixmap_new..
+ */
+void API dw_pixmap_destroy(HPIXMAP pixmap)
+{
+	if(pixmap)
+	{
+		DeleteDC(pixmap->hdc);
+		DeleteObject(pixmap->hbm);
+		free(pixmap);
+	}
+}
+
+/*
+ * Copies from one item to another.
+ * Parameters:
+ *       dest: Destination window handle.
+ *       destp: Destination pixmap. (choose only one).
+ *       xdest: X coordinate of destination.
+ *       ydest: Y coordinate of destination.
+ *       width: Width of area to copy.
+ *       height: Height of area to copy.
+ *       src: Source window handle.
+ *       srcp: Source pixmap. (choose only one).
+ *       xsrc: X coordinate of source.
+ *       ysrc: Y coordinate of source.
+ */
+void API dw_pixmap_bitblt(HWND dest, HPIXMAP destp, int xdest, int ydest, int width, int height, HWND src, HPIXMAP srcp, int xsrc, int ysrc)
+{
+	HDC hdcdest;
+	HDC hdcsrc;
+
+	if(dest)
+		hdcdest = GetDC(dest);
+	else if(destp)
+		hdcdest = destp->hdc;
+	else
+		return;
+
+	if(src)
+		hdcsrc = GetDC(src);
+	else if(srcp)
+		hdcsrc = srcp->hdc;
+	else
+		return;
+
+	BitBlt(hdcdest, xdest, ydest, width, height, hdcsrc, xsrc, ysrc, SRCCOPY);
+
+	if(!destp)
+		ReleaseDC(dest, hdcdest);
+	if(!srcp)
+		ReleaseDC(src, hdcsrc);
+}
+
+/*
+ * Emits a beep.
+ * Parameters:
+ *       freq: Frequency.
+ *       dur: Duration.
+ */
+void API dw_beep(int freq, int dur)
+{
+	Beep(freq, dur);
+}
+
+/* Open a shared library and return a handle.
+ * Parameters:
+ *         name: Base name of the shared library.
+ *         handle: Pointer to a module handle,
+ *                 will be filled in with the handle.
+ */
+int API dw_module_load(char *name, HMOD *handle)
+{
+	if(!handle)
+		return	-1;
+
+	*handle = LoadLibrary(name);
+	return (NULL == *handle);
+}
+
+/* Queries the address of a symbol within open handle.
+ * Parameters:
+ *         handle: Module handle returned by dw_module_load()
+ *         name: Name of the symbol you want the address of.
+ *         func: A pointer to a function pointer, to obtain
+ *               the address.
+ */
+int API dw_module_symbol(HMOD handle, char *name, void**func)
+{
+	if(!func || !name)
+		return	-1;
+
+	if(0 == strlen(name))
+		return	-1;
+
+	*func = (void*)GetProcAddress(handle, name);
+	return	(NULL == *func);
+}
+
+/* Frees the shared library previously opened.
+ * Parameters:
+ *         handle: Module handle returned by dw_module_load()
+ */
+int API dw_module_close(HMOD handle)
+{
+	return FreeLibrary(handle);
+}
+
+/*
+ * Returns the handle to an unnamed mutex semaphore.
+ */
+HMTX API dw_mutex_new(void)
+{
+	return (HMTX)CreateMutex(NULL, FALSE, NULL);
+}
+
+/*
+ * Closes a semaphore created by dw_mutex_new().
+ * Parameters:
+ *       mutex: The handle to the mutex returned by dw_mutex_new().
+ */
+void API dw_mutex_close(HMTX mutex)
+{
+	CloseHandle((HANDLE)mutex);
+}
+
+/*
+ * Tries to gain access to the semaphore, if it can't it blocks.
+ * Parameters:
+ *       mutex: The handle to the mutex returned by dw_mutex_new().
+ */
+void API dw_mutex_lock(HMTX mutex)
+{
+	if(_dwtid == dw_thread_id())
+	{
+		int rc = WaitForSingleObject((HANDLE)mutex, 0);
+
+		while(rc == WAIT_TIMEOUT)
+		{
+			dw_main_sleep(1);
+			rc = WaitForSingleObject((HANDLE)mutex, 0);
+		}
+	}
+    else
+		WaitForSingleObject((HANDLE)mutex, INFINITE);
+}
+
+/*
+ * Reliquishes the access to the semaphore.
+ * Parameters:
+ *       mutex: The handle to the mutex returned by dw_mutex_new().
+ */
+void API dw_mutex_unlock(HMTX mutex)
+{
+	ReleaseMutex((HANDLE)mutex);
+}
+
+/*
+ * Returns the handle to an unnamed event semaphore.
+ */
+HEV API dw_event_new(void)
+{
+    return CreateEvent(NULL, TRUE, FALSE, NULL);
+}
+
+/*
+ * Resets a semaphore created by dw_event_new().
+ * Parameters:
+ *       eve: The handle to the event returned by dw_event_new().
+ */
+int API dw_event_reset(HEV eve)
+{
+	return ResetEvent(eve);
+}
+
+/*
+ * Posts a semaphore created by dw_event_new(). Causing all threads
+ * waiting on this event in dw_event_wait to continue.
+ * Parameters:
+ *       eve: The handle to the event returned by dw_event_new().
+ */
+int API dw_event_post(HEV eve)
+{
+	return SetEvent(eve);
+}
+
+/*
+ * Waits on a semaphore created by dw_event_new(), until the
+ * event gets posted or until the timeout expires.
+ * Parameters:
+ *       eve: The handle to the event returned by dw_event_new().
+ */
+int API dw_event_wait(HEV eve, unsigned long timeout)
+{
+	int rc;
+
+	rc = WaitForSingleObject(eve, timeout);
+	if(rc == WAIT_OBJECT_0)
+		return 1;
+	if(rc == WAIT_ABANDONED)
+		return -1;
+	return 0;
+}
+
+/*
+ * Closes a semaphore created by dw_event_new().
+ * Parameters:
+ *       eve: The handle to the event returned by dw_event_new().
+ */
+int API dw_event_close(HEV *eve)
+{
+	if(eve)
+		return CloseHandle(*eve);
+	return FALSE;
+}
+
+/*
+ * Creates a new thread with a starting point of func.
+ * Parameters:
+ *       func: Function which will be run in the new thread.
+ *       data: Parameter(s) passed to the function.
+ *       stack: Stack size of new thread (OS/2 and Windows only).
+ */
+DWTID API dw_thread_new(void *func, void *data, int stack)
+{
+#if defined(__CYGWIN__)
+	return 0;
+#else
+	return (DWTID)_beginthread((void(*)(void *))func, stack, data);
+#endif
+}
+
+/*
+ * Ends execution of current thread immediately.
+ */
+void API dw_thread_end(void)
+{
+#if !defined(__CYGWIN__)
+	_endthread();
+#endif
+}
+
+/*
+ * Returns the current thread's ID.
+ */
+DWTID API dw_thread_id(void)
+{
+#if defined(__CYGWIN__)
+	return 0;
+#else
+	return (DWTID)GetCurrentThreadId();
+#endif
+}
+
+/*
+ * Cleanly terminates a DW session, should be signal handler safe.
+ * Parameters:
+ *       exitcode: Exit code reported to the operating system.
+ */
+void API dw_exit(int exitcode)
+{
+	exit(exitcode);
+}
+
+/*
+ * Creates a splitbar window (widget) with given parameters.
+ * Parameters:
+ *       type: Value can be DW_VERT or DW_HORZ.
+ *       topleft: Handle to the window to be top or left.
+ *       bottomright:  Handle to the window to be bottom or right.
+ * Returns:
+ *       A handle to a splitbar window or NULL on failure.
+ */
+HWND API dw_splitbar_new(int type, HWND topleft, HWND bottomright, unsigned long id)
+{
+	HWND tmp = CreateWindow(SplitbarClassName,
+							"",
+							WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN,
+							0,0,2000,1000,
+							DW_HWND_OBJECT,
+							(HMENU)id,
+							DWInstance,
+							NULL);
+
+	if(tmp)
+	{
+		HWND tmpbox = dw_box_new(DW_VERT, 0);
+        float *percent = (float *)malloc(sizeof(float));
+
+		dw_box_pack_start(tmpbox, topleft, 1, 1, TRUE, TRUE, 0);
+		SetParent(tmpbox, tmp);
+		dw_window_set_data(tmp, "_dw_topleft", (void *)tmpbox);
+
+		tmpbox = dw_box_new(DW_VERT, 0);
+		dw_box_pack_start(tmpbox, bottomright, 1, 1, TRUE, TRUE, 0);
+		SetParent(tmpbox, tmp);
+		dw_window_set_data(tmp, "_dw_bottomright", (void *)tmpbox);
+		*percent = 50.0;
+		dw_window_set_data(tmp, "_dw_percent", (void *)percent);
+		dw_window_set_data(tmp, "_dw_type", (void *)type);
+	}
+	return tmp;
+}
+
+/*
+ * Sets the position of a splitbar (pecentage).
+ * Parameters:
+ *       handle: The handle to the splitbar returned by dw_splitbar_new().
+ */
+void API dw_splitbar_set(HWND handle, float percent)
+{
+	float *mypercent = (float *)dw_window_get_data(handle, "_dw_percent");
+	int type = (int)dw_window_get_data(handle, "_dw_type");
+    unsigned long width, height;
+
+	if(mypercent)
+		*mypercent = percent;
+
+	dw_window_get_pos_size(handle, NULL, NULL, &width, &height);
+
+	_handle_splitbar_resize(handle, percent, type, width, height);
+}
+
+/*
+ * Gets the position of a splitbar (pecentage).
+ * Parameters:
+ *       handle: The handle to the splitbar returned by dw_splitbar_new().
+ */
+float API dw_splitbar_get(HWND handle)
+{
+	float *percent = (float *)dw_window_get_data(handle, "_dw_percent");
+
+	if(percent)
+		return *percent;
+	return 0.0;
+}
+
+/*
+ * Pack windows (widgets) into a box from the end (or bottom).
+ * Parameters:
+ *       box: Window handle of the box to be packed into.
+ *       item: Window handle of the item to be back.
+ *       width: Width in pixels of the item or -1 to be self determined.
+ *       height: Height in pixels of the item or -1 to be self determined.
+ *       hsize: TRUE if the window (widget) should expand horizontally to fill space given.
+ *       vsize: TRUE if the window (widget) should expand vertically to fill space given.
+ *       pad: Number of pixels of padding around the item.
+ */
+void API dw_box_pack_end(HWND box, HWND item, int width, int height, int hsize, int vsize, int pad)
+{
+	Box *thisbox;
+
+		/*
+		 * If you try and pack an item into itself VERY bad things can happen; like at least an
+		 * infinite loop on GTK! Lets be safe!
+		 */
+	if(box == item)
+	{
+		dw_messagebox("dw_box_pack_end()", DW_MB_OK|DW_MB_ERROR, "Danger! Danger! Will Robinson; box and item are the same!",box,item);
+		return;
+	}
+
+	thisbox = (Box *)GetWindowLongPtr(box, GWLP_USERDATA);
+	if(thisbox)
+	{
+		int z;
+		Item *tmpitem, *thisitem = thisbox->items;
+		char tmpbuf[100];
+
+		tmpitem = malloc(sizeof(Item)*(thisbox->count+1));
+
+		for(z=0;z<thisbox->count;z++)
+		{
+			tmpitem[z+1] = thisitem[z];
+		}
+
+		GetClassName(item, tmpbuf, 99);
+
+		if(vsize && !height)
+			height = 1;
+		if(hsize && !width)
+			width = 1;
+
+		if(strnicmp(tmpbuf, FRAMECLASSNAME, strlen(FRAMECLASSNAME)+1)==0)
+			tmpitem[0].type = TYPEBOX;
+		else
+		{
+			if ( width == 0 && hsize == FALSE )
+				dw_messagebox("dw_box_pack_end()", DW_MB_OK|DW_MB_ERROR, "Width and expand Horizonal both unset for box: %x item: %x",box,item);
+			if ( height == 0 && vsize == FALSE )
+				dw_messagebox("dw_box_pack_end()", DW_MB_OK|DW_MB_ERROR, "Height and expand Vertical both unset for box: %x item: %x",box,item);
+
+			tmpitem[0].type = TYPEITEM;
+		}
+
+		tmpitem[0].hwnd = item;
+		tmpitem[0].origwidth = tmpitem[0].width = width;
+		tmpitem[0].origheight = tmpitem[0].height = height;
+		tmpitem[0].pad = pad;
+		if(hsize)
+			tmpitem[0].hsize = SIZEEXPAND;
+		else
+			tmpitem[0].hsize = SIZESTATIC;
+
+		if(vsize)
+			tmpitem[0].vsize = SIZEEXPAND;
+		else
+			tmpitem[0].vsize = SIZESTATIC;
+
+		thisbox->items = tmpitem;
+
+		if(thisbox->count)
+			free(thisitem);
+
+		thisbox->count++;
+
+		SetParent(item, box);
+		if(strncmp(tmpbuf, UPDOWN_CLASS, strlen(UPDOWN_CLASS)+1)==0)
+		{
+			ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(item, GWLP_USERDATA);
+
+			if(cinfo)
+			{
+				SetParent(cinfo->buddy, box);
+				ShowWindow(cinfo->buddy, SW_SHOW);
+				SendMessage(item, UDM_SETBUDDY, (WPARAM)cinfo->buddy, 0);
+			}
+		}
+	}
+}
+
+/*
+ * Sets the default focus item for a window/dialog.
+ * Parameters:
+ *         window: Toplevel window or dialog.
+ *         defaultitem: Handle to the dialog item to be default.
+ */
+void API dw_window_default(HWND window, HWND defaultitem)
+{
+	Box *thisbox = (Box *)GetWindowLongPtr(window, GWLP_USERDATA);
+
+	if(thisbox)
+		thisbox->defaultitem = defaultitem;
+}
+
+/*
+ * Sets window to click the default dialog item when an ENTER is pressed.
+ * Parameters:
+ *         window: Window (widget) to look for the ENTER press.
+ *         next: Window (widget) to move to next (or click)
+ */
+void API dw_window_click_default(HWND window, HWND next)
+{
+	ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(window, GWLP_USERDATA);
+
+	if(cinfo)
+		cinfo->clickdefault = next;
+}
+
+/*
+ * Returns some information about the current operating environment.
+ * Parameters:
+ *       env: Pointer to a DWEnv struct.
+ */
+void API dw_environment_query(DWEnv *env)
+{
+	if(!env)
+		return;
+
+	/* Get the Windows version. */
+
+	env->MajorVersion =  (DWORD)(LOBYTE(LOWORD(dwVersion)));
+	env->MinorVersion =  (DWORD)(HIBYTE(LOWORD(dwVersion)));
+
+	/* Get the build number for Windows NT/Windows 2000. */
+
+	env->MinorBuild =  0;
+
+	if (dwVersion < 0x80000000)
+	{
+		if(env->MajorVersion == 5 && env->MinorVersion == 1)
+			strcpy(env->osName, "Windows XP");
+		else if(env->MajorVersion == 5 && env->MinorVersion == 0)
+			strcpy(env->osName, "Windows 2000");
+		else
+			strcpy(env->osName, "Windows NT");
+
+		env->MajorBuild = (DWORD)(HIWORD(dwVersion));
+	}
+	else
+	{
+		strcpy(env->osName, "Windows 95/98/ME");
+		env->MajorBuild =  0;
+	}
+
+	strcpy(env->buildDate, __DATE__);
+	strcpy(env->buildTime, __TIME__);
+	env->DWMajorVersion = DW_MAJOR_VERSION;
+	env->DWMinorVersion = DW_MINOR_VERSION;
+	env->DWSubVersion = DW_SUB_VERSION;
+}
+
+/*
+ * Opens a file dialog and queries user selection.
+ * Parameters:
+ *       title: Title bar text for dialog.
+ *       defpath: The default path of the open dialog.
+ *       ext: Default file extention.
+ *       flags: DW_FILE_OPEN or DW_FILE_SAVE or DW_DIRECTORY_OPEN.
+ * Returns:
+ *       NULL on error. A malloced buffer containing
+ *       the file path on success.
+ *       
+ */
+char * API dw_file_browse(char *title, char *defpath, char *ext, int flags)
+{
+	OPENFILENAME of;
+	char filenamebuf[1001] = "";
+	int rc;
+
+	BROWSEINFO bi;
+	TCHAR szDir[MAX_PATH];
+	LPITEMIDLIST pidl;
+	LPMALLOC pMalloc;
+
+	if(flags==DW_DIRECTORY_OPEN)
+	{
+		if (SUCCEEDED(SHGetMalloc(&pMalloc)))
+		{
+			ZeroMemory(&bi,sizeof(bi));
+			bi.hwndOwner = NULL;
+			bi.pszDisplayName = 0;
+			bi.pidlRoot = 0;
+			bi.lpszTitle = title;
+			bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT;
+			bi.lpfn = NULL; /*BrowseCallbackProc*/
+
+			pidl = SHBrowseForFolder(&bi);
+			if (pidl)
+			{
+				if (SHGetPathFromIDList(pidl,szDir))
+				{
+					strcpy(filenamebuf,szDir);
+				}
+
+				// In C++: pMalloc->Free(pidl); pMalloc->Release();
+				pMalloc->lpVtbl->Free(pMalloc,pidl);
+				pMalloc->lpVtbl->Release(pMalloc);
+				return strdup(filenamebuf);
+			}
+		}
+	}
+	else
+	{
+		if(ext)
+		{
+			strcpy(filenamebuf, "*.");
+			strcat(filenamebuf, ext);
+		}
+
+		memset(&of, 0, sizeof(OPENFILENAME));
+
+		of.lStructSize = sizeof(OPENFILENAME);
+		of.hwndOwner = HWND_DESKTOP;
+		of.hInstance = DWInstance;
+		of.lpstrInitialDir = defpath;
+		of.lpstrTitle = title;
+		of.lpstrFile = filenamebuf;
+		of.nMaxFile = 1000;
+		of.lpstrDefExt = ext;
+		of.Flags = 0;
+
+		if(flags & DW_FILE_SAVE)
+			rc = GetSaveFileName(&of);
+		else
+			rc = GetOpenFileName(&of);
+
+		if(rc)
+			return strdup(of.lpstrFile);
+	}
+	return NULL;
+}
+
+/*
+ * Execute and external program in a seperate session.
+ * Parameters:
+ *       program: Program name with optional path.
+ *       type: Either DW_EXEC_CON or DW_EXEC_GUI.
+ *       params: An array of pointers to string arguements.
+ * Returns:
+ *       -1 on error.
+ */
+int API dw_exec(char *program, int type, char **params)
+{
+	char **newparams;
+	int retcode, count = 0, z;
+
+	while(params[count])
+	{
+		count++;
+	}
+
+	newparams = (char **)malloc(sizeof(char *) * (count+1));
+
+	for(z=0;z<count;z++)
+	{
+		newparams[z] = malloc(strlen(params[z])+3);
+		strcpy(newparams[z], "\"");
+		strcat(newparams[z], params[z]);
+		strcat(newparams[z], "\"");
+	}
+	newparams[count] = NULL;
+
+	retcode = spawnvp(P_NOWAIT, program, newparams);
+
+	for(z=0;z<count;z++)
+	{
+		free(newparams[z]);
+	}
+	free(newparams);
+
+	return retcode;
+}
+
+/*
+ * Loads a web browser pointed at the given URL.
+ * Parameters:
+ *       url: Uniform resource locator.
+ */
+int API dw_browse(char *url)
+{
+	char *browseurl = url;
+	int retcode;
+
+	if(strlen(url) > 7 && strncmp(url, "file://", 7) == 0)
+	{
+		int len, z;
+
+		browseurl = &url[7];
+		len = strlen(browseurl);
+
+		for(z=0;z<len;z++)
+		{
+			if(browseurl[z] == '|')
+				browseurl[z] = ':';
+			if(browseurl[z] == '/')
+				browseurl[z] = '\\';
+		}
+	}
+
+	retcode = (int)ShellExecute(NULL, "open", browseurl, NULL, NULL, SW_SHOWNORMAL);
+	if(retcode<33 && retcode != 2)
+		return -1;
+	return 1;
+}
+
+/*
+ * Returns a pointer to a static buffer which containes the
+ * current user directory.  Or the root directory (C:\ on
+ * OS/2 and Windows).
+ */
+char * API dw_user_dir(void)
+{
+	static char _user_dir[1024] = "";
+
+	if(!_user_dir[0])
+	{
+		/* Figure out how to do this the "Windows way" */
+		char *home = getenv("HOME");
+
+		if(home)
+			strcpy(_user_dir, home);
+		else
+			strcpy(_user_dir, "C:\\");
+	}
+	return _user_dir;
+}
+
+/*
+ * Call a function from the window (widget)'s context.
+ * Parameters:
+ *       handle: Window handle of the widget.
+ *       function: Function pointer to be called.
+ *       data: Pointer to the data to be passed to the function.
+ */
+void API dw_window_function(HWND handle, void *function, void *data)
+{
+	SendMessage(handle, WM_USER, (WPARAM)function, (LPARAM)data);
+}
+
+/* Functions for managing the user data lists that are associated with
+ * a given window handle.  Used in dw_window_set_data() and
+ * dw_window_get_data().
+ */
+UserData *_find_userdata(UserData **root, char *varname)
+{
+	UserData *tmp = *root;
+
+	while(tmp)
+	{
+		if(stricmp(tmp->varname, varname) == 0)
+			return tmp;
+		tmp = tmp->next;
+	}
+	return NULL;
+}
+
+int _new_userdata(UserData **root, char *varname, void *data)
+{
+	UserData *new = _find_userdata(root, varname);
+
+	if(new)
+	{
+		new->data = data;
+		return TRUE;
+	}
+	else
+	{
+		new = malloc(sizeof(UserData));
+		if(new)
+		{
+			new->varname = strdup(varname);
+			new->data = data;
+
+			new->next = NULL;
+
+			if (!*root)
+				*root = new;
+			else
+			{
+				UserData *prev = NULL, *tmp = *root;
+				while(tmp)
+				{
+					prev = tmp;
+					tmp = tmp->next;
+				}
+				if(prev)
+					prev->next = new;
+				else
+					*root = new;
+			}
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+int _remove_userdata(UserData **root, char *varname, int all)
+{
+	UserData *prev = NULL, *tmp = *root;
+
+	while(tmp)
+	{
+		if(all || stricmp(tmp->varname, varname) == 0)
+		{
+			if(!prev)
+			{
+				*root = tmp->next;
+				free(tmp->varname);
+				free(tmp);
+				if(!all)
+					return 0;
+				tmp = *root;
+			}
+			else
+			{
+				/* If all is true we should
+				 * never get here.
+				 */
+				prev->next = tmp->next;
+				free(tmp->varname);
+				free(tmp);
+				return 0;
+			}
+		}
+		else
+		{
+			prev = tmp;
+			tmp = tmp->next;
+		}
+	}
+	return 0;
+}
+
+/*
+ * Add a named user data item to a window handle.
+ * Parameters:
+ *       window: Window handle of signal to be called back.
+ *       dataname: A string pointer identifying which signal to be hooked.
+ *       data: User data to be passed to the handler function.
+ */
+void API dw_window_set_data(HWND window, char *dataname, void *data)
+{
+	ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(window, GWLP_USERDATA);
+
+	if(!cinfo)
+	{
+		if(!dataname)
+			return;
+
+		cinfo = calloc(1, sizeof(ColorInfo));
+		cinfo->fore = cinfo->back = -1;
+		SetWindowLongPtr(window, GWLP_USERDATA, (LONG_PTR)cinfo);
+	}
+
+	if(cinfo)
+	{
+		if(data)
+			_new_userdata(&(cinfo->root), dataname, data);
+		else
+		{
+			if(dataname)
+				_remove_userdata(&(cinfo->root), dataname, FALSE);
+			else
+				_remove_userdata(&(cinfo->root), NULL, TRUE);
+		}
+	}
+}
+
+/*
+ * Gets a named user data item to a window handle.
+ * Parameters:
+ *       window: Window handle of signal to be called back.
+ *       dataname: A string pointer identifying which signal to be hooked.
+ *       data: User data to be passed to the handler function.
+ */
+void * API dw_window_get_data(HWND window, char *dataname)
+{
+	ColorInfo *cinfo = (ColorInfo *)GetWindowLongPtr(window, GWLP_USERDATA);
+
+	if(cinfo && cinfo->root && dataname)
+	{
+		UserData *ud = _find_userdata(&(cinfo->root), dataname);
+		if(ud)
+			return ud->data;
+	}
+	return NULL;
+}
+
+/*
+ * Add a callback to a timer event.
+ * Parameters:
+ *       interval: Milliseconds to delay between calls.
+ *       sigfunc: The pointer to the function to be used as the callback.
+ *       data: User data to be passed to the handler function.
+ * Returns:
+ *       Timer ID for use with dw_timer_disconnect(), 0 on error.
+ */
+int API dw_timer_connect(int interval, void *sigfunc, void *data)
+{
+	if(sigfunc)
+	{
+		int timerid = SetTimer(NULL, 0, interval, _TimerProc);
+
+		if(timerid)
+		{
+			_new_signal(WM_TIMER, NULL, timerid, sigfunc, data);
+			return timerid;
+		}
+	}
+	return 0;
+}
+
+/*
+ * Removes timer callback.
+ * Parameters:
+ *       id: Timer ID returned by dw_timer_connect().
+ */
+void API dw_timer_disconnect(int id)
+{
+	SignalHandler *prev = NULL, *tmp = Root;
+
+	/* 0 is an invalid timer ID */
+	if(!id)
+		return;
+
+	KillTimer(NULL, id);
+
+	while(tmp)
+	{
+		if(tmp->id == id)
+		{
+			if(prev)
+			{
+				prev->next = tmp->next;
+				free(tmp);
+				tmp = prev->next;
+			}
+			else
+			{
+				Root = tmp->next;
+				free(tmp);
+				tmp = Root;
+			}
+		}
+		else
+		{
+			prev = tmp;
+			tmp = tmp->next;
+		}
+	}
+}
+
+/*
+ * Add a callback to a window event.
+ * Parameters:
+ *       window: Window handle of signal to be called back.
+ *       signame: A string pointer identifying which signal to be hooked.
+ *       sigfunc: The pointer to the function to be used as the callback.
+ *       data: User data to be passed to the handler function.
+ */
+void API dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data)
+{
+	ULONG message = 0, id = 0;
+
+	if(window && signame && sigfunc)
+	{
+		if(stricmp(signame, DW_SIGNAL_SET_FOCUS) == 0)
+			window = _normalize_handle(window);
+
+		if((message = _findsigmessage(signame)) != 0)
+		{
+			/* Handle special case of the menu item */
+			if(message == WM_COMMAND && window < (HWND)65536)
+			{
+				char buffer[15];
+				HWND owner;
+
+				sprintf(buffer, "_dw_id%d", (int)window);
+				owner = (HWND)dw_window_get_data(DW_HWND_OBJECT, buffer);
+
+				if(owner)
+				{
+					id = (ULONG)window;
+					window = owner;
+					dw_window_set_data(DW_HWND_OBJECT, buffer, 0);
+				}
+				else
+				{
+					/* If it is a popup menu clear all entries */
+					dw_signal_disconnect_by_window(window);
+				}
+			}
+			_new_signal(message, window, id, sigfunc, data);
+		}
+	}
+}
+
+/*
+ * Removes callbacks for a given window with given name.
+ * Parameters:
+ *       window: Window handle of callback to be removed.
+ */
+void API dw_signal_disconnect_by_name(HWND window, char *signame)
+{
+	SignalHandler *prev = NULL, *tmp = Root;
+	ULONG message;
+
+	if(!window || !signame || (message = _findsigmessage(signame)) == 0)
+		return;
+
+	while(tmp)
+	{
+		if(tmp->window == window && tmp->message == message)
+		{
+			if(prev)
+			{
+				prev->next = tmp->next;
+				free(tmp);
+				tmp = prev->next;
+			}
+			else
+			{
+				Root = tmp->next;
+				free(tmp);
+				tmp = Root;
+			}
+		}
+		else
+		{
+			prev = tmp;
+			tmp = tmp->next;
+		}
+	}
+}
+
+/*
+ * Removes all callbacks for a given window.
+ * Parameters:
+ *       window: Window handle of callback to be removed.
+ */
+void API dw_signal_disconnect_by_window(HWND window)
+{
+	SignalHandler *prev = NULL, *tmp = Root;
+
+	while(tmp)
+	{
+		if(tmp->window == window)
+		{
+			if(prev)
+			{
+				prev->next = tmp->next;
+				free(tmp);
+				tmp = prev->next;
+			}
+			else
+			{
+				Root = tmp->next;
+				free(tmp);
+				tmp = Root;
+			}
+		}
+		else
+		{
+			prev = tmp;
+			tmp = tmp->next;
+		}
+	}
+}
+
+/*
+ * Removes all callbacks for a given window with specified data.
+ * Parameters:
+ *       window: Window handle of callback to be removed.
+ *       data: Pointer to the data to be compared against.
+ */
+void API dw_signal_disconnect_by_data(HWND window, void *data)
+{
+	SignalHandler *prev = NULL, *tmp = Root;
+
+	while(tmp)
+	{
+		if(tmp->window == window && tmp->data == data)
+		{
+			if(prev)
+			{
+				prev->next = tmp->next;
+				free(tmp);
+				tmp = prev->next;
+			}
+			else
+			{
+				Root = tmp->next;
+				free(tmp);
+				tmp = Root;
+			}
+		}
+		else
+		{
+			prev = tmp;
+			tmp = tmp->next;
+		}
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/win32sup.cpp	Fri Feb 18 08:45:38 2011 -0600
@@ -0,0 +1,65 @@
+#include <windows.h>
+#include <shlobj.h>
+#include <objbase.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HRESULT CreateLink(LPCSTR lpszPathObj,
+    LPSTR lpszPathLink, LPSTR lpszDesc) 
+{ 
+	HRESULT hres;
+	IShellLink* psl;
+
+	/* Get a pointer to the IShellLink interface. */
+	hres = CoCreateInstance(CLSID_ShellLink, NULL,
+							CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
+	if (SUCCEEDED(hres))
+	{
+		IPersistFile* ppf;
+		char WorkingDir[1024];
+		int len = strlen(lpszPathObj) - 1;
+
+		strcpy(WorkingDir, lpszPathObj);
+
+		while(len > 0 && WorkingDir[len] != '\\')
+			len--;
+
+		WorkingDir[len] = 0;
+
+		/* Set the path to the shortcut target, and add the
+		 * description.
+		 */
+		psl->SetPath(lpszPathObj);
+
+		psl->SetDescription(lpszDesc);
+
+		psl->SetWorkingDirectory(WorkingDir);
+
+		/* Query IShellLink for the IPersistFile interface for saving the
+		 * shortcut in persistent storage.
+		 */
+		hres = psl->QueryInterface(IID_IPersistFile,
+								   (void **)&ppf);
+
+		if (SUCCEEDED(hres))
+		{
+			WCHAR wsz[MAX_PATH];
+
+			/* Ensure that the string is ANSI. */
+			MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1,
+								wsz, MAX_PATH);
+
+			/* Save the link by calling IPersistFile::Save. */
+			hres = ppf->Save(wsz, TRUE);
+			ppf->Release();
+		}
+		psl->Release();
+	}
+	return hres;
+}
+
+#ifdef __cplusplus
+}
+#endif