]> git.rm.cloudns.org Git - xonotic/netradiant.git/commitdiff
* added pk3man and fixed it to compile for latest radiant
authormattn <mattn@8a3a26a2-13c4-0310-b231-cf6edde360e5>
Tue, 18 Mar 2008 17:11:08 +0000 (17:11 +0000)
committermattn <mattn@8a3a26a2-13c4-0310-b231-cf6edde360e5>
Tue, 18 Mar 2008 17:11:08 +0000 (17:11 +0000)
* NOTE: Not included in the build chain - doesn't link
* NOTE: iepair.h is not used at the moment

git-svn-id: https://zerowing.idsoftware.com/svn/radiant/GtkRadiant/branches/ZeroRadiant@225 8a3a26a2-13c4-0310-b231-cf6edde360e5

42 files changed:
contrib/pk3man/bitmaps/pk3man_tbadd.bmp [new file with mode: 0644]
contrib/pk3man/bitmaps/pk3man_tbdelete.bmp [new file with mode: 0644]
contrib/pk3man/bitmaps/pk3man_tbextract.bmp [new file with mode: 0644]
contrib/pk3man/bitmaps/pk3man_tbnew.bmp [new file with mode: 0644]
contrib/pk3man/bitmaps/pk3man_tbopen.bmp [new file with mode: 0644]
contrib/pk3man/bitmaps/pk3man_tbrename.bmp [new file with mode: 0644]
contrib/pk3man/bitmaps/pk3man_tbsave.bmp [new file with mode: 0644]
contrib/pk3man/bitmaps/pk3man_tbview.bmp [new file with mode: 0644]
contrib/pk3man/bitmaps/pk3man_tbwizard.bmp [new file with mode: 0644]
contrib/pk3man/mainwnd.cpp [new file with mode: 0644]
contrib/pk3man/mainwnd.h [new file with mode: 0644]
contrib/pk3man/md3.h [new file with mode: 0644]
contrib/pk3man/memfile.cpp [new file with mode: 0644]
contrib/pk3man/memfile.h [new file with mode: 0644]
contrib/pk3man/pak.cpp [new file with mode: 0644]
contrib/pk3man/pak.h [new file with mode: 0644]
contrib/pk3man/pixmap.cpp [new file with mode: 0644]
contrib/pk3man/pixmap.h [new file with mode: 0644]
contrib/pk3man/pk3man.cpp [new file with mode: 0644]
contrib/pk3man/pk3man.def [new file with mode: 0644]
contrib/pk3man/pk3man.exclude [new file with mode: 0644]
contrib/pk3man/pk3man.vcproj [new file with mode: 0644]
contrib/pk3man/pk3man_readme.txt [new file with mode: 0644]
contrib/pk3man/pk3str.h [new file with mode: 0644]
contrib/pk3man/renamedlg.cpp [new file with mode: 0644]
contrib/pk3man/renamedlg.h [new file with mode: 0644]
contrib/pk3man/stdafx.cpp [new file with mode: 0644]
contrib/pk3man/stdafx.h [new file with mode: 0644]
contrib/pk3man/tree.cpp [new file with mode: 0644]
contrib/pk3man/tree.h [new file with mode: 0644]
contrib/pk3man/wild.cpp [new file with mode: 0644]
contrib/pk3man/wild.h [new file with mode: 0644]
contrib/pk3man/zlib/README.linux [new file with mode: 0644]
contrib/pk3man/zlib/libz-zip.a [new file with mode: 0644]
contrib/pk3man/zlib/unzip.c [new file with mode: 0644]
contrib/pk3man/zlib/unzip.h [new file with mode: 0644]
contrib/pk3man/zlib/zconf.h [new file with mode: 0644]
contrib/pk3man/zlib/zip.c [new file with mode: 0644]
contrib/pk3man/zlib/zip.h [new file with mode: 0644]
contrib/pk3man/zlib/zlib.h [new file with mode: 0644]
contrib/pk3man/zlib/zlib.lib [new file with mode: 0644]
contrib/pk3man/zlib/zlibd.lib [new file with mode: 0644]

diff --git a/contrib/pk3man/bitmaps/pk3man_tbadd.bmp b/contrib/pk3man/bitmaps/pk3man_tbadd.bmp
new file mode 100644 (file)
index 0000000..a88ee12
Binary files /dev/null and b/contrib/pk3man/bitmaps/pk3man_tbadd.bmp differ
diff --git a/contrib/pk3man/bitmaps/pk3man_tbdelete.bmp b/contrib/pk3man/bitmaps/pk3man_tbdelete.bmp
new file mode 100644 (file)
index 0000000..a11e058
Binary files /dev/null and b/contrib/pk3man/bitmaps/pk3man_tbdelete.bmp differ
diff --git a/contrib/pk3man/bitmaps/pk3man_tbextract.bmp b/contrib/pk3man/bitmaps/pk3man_tbextract.bmp
new file mode 100644 (file)
index 0000000..a27214c
Binary files /dev/null and b/contrib/pk3man/bitmaps/pk3man_tbextract.bmp differ
diff --git a/contrib/pk3man/bitmaps/pk3man_tbnew.bmp b/contrib/pk3man/bitmaps/pk3man_tbnew.bmp
new file mode 100644 (file)
index 0000000..85bb2f1
Binary files /dev/null and b/contrib/pk3man/bitmaps/pk3man_tbnew.bmp differ
diff --git a/contrib/pk3man/bitmaps/pk3man_tbopen.bmp b/contrib/pk3man/bitmaps/pk3man_tbopen.bmp
new file mode 100644 (file)
index 0000000..1f1770c
Binary files /dev/null and b/contrib/pk3man/bitmaps/pk3man_tbopen.bmp differ
diff --git a/contrib/pk3man/bitmaps/pk3man_tbrename.bmp b/contrib/pk3man/bitmaps/pk3man_tbrename.bmp
new file mode 100644 (file)
index 0000000..0e98175
Binary files /dev/null and b/contrib/pk3man/bitmaps/pk3man_tbrename.bmp differ
diff --git a/contrib/pk3man/bitmaps/pk3man_tbsave.bmp b/contrib/pk3man/bitmaps/pk3man_tbsave.bmp
new file mode 100644 (file)
index 0000000..651afb6
Binary files /dev/null and b/contrib/pk3man/bitmaps/pk3man_tbsave.bmp differ
diff --git a/contrib/pk3man/bitmaps/pk3man_tbview.bmp b/contrib/pk3man/bitmaps/pk3man_tbview.bmp
new file mode 100644 (file)
index 0000000..84eabfa
Binary files /dev/null and b/contrib/pk3man/bitmaps/pk3man_tbview.bmp differ
diff --git a/contrib/pk3man/bitmaps/pk3man_tbwizard.bmp b/contrib/pk3man/bitmaps/pk3man_tbwizard.bmp
new file mode 100644 (file)
index 0000000..036d2ae
Binary files /dev/null and b/contrib/pk3man/bitmaps/pk3man_tbwizard.bmp differ
diff --git a/contrib/pk3man/mainwnd.cpp b/contrib/pk3man/mainwnd.cpp
new file mode 100644 (file)
index 0000000..d8c88a9
--- /dev/null
@@ -0,0 +1,1581 @@
+// MainWnd.cpp: implementation of the CMainWnd class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "mainwnd.h"
+#include "memfile.h"
+#include "md3.h"
+#include "wild.h"
+#include "renamedlg.h"
+#ifdef __linux__
+#include <dirent.h>
+#include <stdlib.h>
+#endif
+
+extern CMainWnd *g_pMainWnd;
+bool g_bIgnoreCommands=FALSE;
+
+GtkWidget* create_menu_in_menu (GtkWidget *menu, gchar *label, GtkAccelGroup *menu_accel,GtkAccelGroup **submenu_accel);
+GtkWidget* create_menu_item (GtkWidget *menu, gchar *label, GtkAccelGroup *menu_accel,GtkSignalFunc func, int id);
+GtkWidget* menu_separator (GtkWidget *menu);
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+static gint mainwnd_delete (GtkWidget *widget, gpointer data)
+{
+return g_pMainWnd->OnClose();
+}
+
+static void HandleCommand (GtkWidget *widget, gpointer data)
+{
+       int id = GPOINTER_TO_INT (data);
+
+       if (g_bIgnoreCommands)
+       return;
+
+       switch (id)
+       {
+               case ID_FILE_NEW: g_pMainWnd->OnFileNew (); break;
+               case ID_FILE_OPEN: g_pMainWnd->OnFileOpen (); break;
+               case ID_FILE_SAVE: g_pMainWnd->OnFileSave (); break;
+
+               case ID_WIZARD: g_pMainWnd->OnWizard (); break;
+
+               case ID_VIEW: g_pMainWnd->OnView (); break;
+               case ID_EXTRACT: g_pMainWnd->OnExtract (); break;
+
+               case ID_ADD: g_pMainWnd->OnAdd (); break;
+               case ID_RENAME: g_pMainWnd->OnRename (); break;
+               case ID_DELETE: g_pMainWnd->OnDelete (); break;
+       }
+}
+
+CMainWnd::CMainWnd()
+{
+       m_pMainWnd=NULL;
+       m_mnuDrop=NULL;
+}
+
+CMainWnd::~CMainWnd()
+{
+       if (m_pMainWnd)
+               delete m_pMainWnd;
+}
+
+bool CMainWnd::OnClose()
+{
+       if (pak.IsModified())
+       {
+               //int ret=DoMessageBox("Pk3 has not been saved\n\n    Really quit?","Pk3Man",MB_YESNO);
+               int ret=g_FuncTable.m_pfnMessageBox(m_pMainWnd,"Pk3 has not been saved\n\n    Really quit?","Pk3Man",MB_YESNO, NULL);
+               if (ret!=IDYES)
+                       return 1;
+       }
+
+       FreePakList();
+       DeleteTempFiles();
+       return 0;
+}
+
+void CMainWnd::OnDestroy()
+{
+       // NOT CALLED !!!
+}
+
+BOOL CMainWnd::Create(GtkWidget *parent)
+{
+       GtkWidget *vbox,*window;
+       GdkPixmap *pixmap=NULL;
+       GdkBitmap *mask=NULL;
+
+       char * icon_xpm[] = { "32 32 6 1", ".   c none", "/     c #ff0ff", "0   c #dddddd", "1  c #e6a0e6", "2  c #333333", "3  c #9d189d", "................................", "................................", "............////////............", "............////////............", "........////////////////........", "........////////////////........", "......////////////////////......", "......////////////////////......", "....//////0000////////0001//....", "....//////0000////////0000//....", "....////00000000////00000001....", "....////00000000////00000001....", "....////00002222////00002223....", "....////00002222////00002223....", "..//////00002222////00002223//..", "..//////00002222////00002222//..", "..////////0000////////0000////..", "..////////0000////////0000////..", "..////////////////////////////..", "..////////////////////////////..", "..////////////////////////////..", "..////////////////////////////..", "..////////////////////////////..", "..////////////////////////////..", "..////////////////////////////..", "..////////////////////////////..", "..////..//////....//////..////..", "..////..//////....//////..////..", "..//......////....////......//..", "..//......////....////......//..", "................................", "................................"};
+
+       // get bitmap paths
+       GetPaths();
+
+       // create the main widget
+       m_pMainWnd = window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+       gtk_signal_connect (GTK_OBJECT (window), "delete_event", GTK_SIGNAL_FUNC (mainwnd_delete), this);
+       //gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (gtk_widget_destroy), this);
+
+       gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
+       gtk_window_set_title (GTK_WINDOW (m_pMainWnd), "Pk3Man - ");
+               gtk_window_set_default_size (GTK_WINDOW (m_pMainWnd), 300, 300);
+               gtk_widget_show (m_pMainWnd);
+
+       // load and set the icon
+
+       pixmap = gdk_pixmap_create_from_xpm_d (window->window, &mask, NULL, icon_xpm);
+       gdk_window_set_icon (window->window, NULL, pixmap, mask);
+
+       // setup the vertical layout box
+       vbox=gtk_vbox_new (FALSE, 0);
+       gtk_container_add (GTK_CONTAINER (window), vbox);
+       gtk_widget_show (vbox);
+
+       if (!CreateToolbar (window, vbox))
+               return FALSE;
+
+       if (!CreateTreeView (window, vbox))
+               return FALSE;
+
+       if (!CreateStatusBar (window,vbox))
+               return FALSE;
+
+       UpdateStatus();
+       UpdateToolBar();
+
+       LoadExclusions();
+       InitPakList();
+
+       return TRUE;
+}
+
+BOOL CMainWnd::CreateTreeView(GtkWidget *window,GtkWidget *vbox)
+{
+       // create a scrollable widget to house the tree
+       m_ScrolledWin = gtk_scrolled_window_new (NULL, NULL);
+       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (m_ScrolledWin),
+                                                               GTK_POLICY_AUTOMATIC,
+                                                               GTK_POLICY_AUTOMATIC);
+
+       //gtk_widget_set_usize (m_ScrolledWin, 400, 400);
+       gtk_box_pack_start (GTK_BOX (vbox), m_ScrolledWin, TRUE, TRUE, 0);
+       gtk_widget_show (m_ScrolledWin);
+
+       // attach and initialise the tree
+       m_Tree.Init(m_ScrolledWin);
+
+       return TRUE;
+}
+
+BOOL CMainWnd::CreateToolbar(GtkWidget *window,GtkWidget *vbox)
+{
+       GtkWidget *handle_box, *toolbar, *w;
+
+       handle_box = gtk_handle_box_new ();
+       gtk_box_pack_start (GTK_BOX (vbox), handle_box, FALSE, FALSE, 0);
+       gtk_widget_show (handle_box);
+
+       m_Toolbar = toolbar = gtk_toolbar_new ();
+
+       //  gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), user_rc.toolbar_style);
+       gtk_container_add (GTK_CONTAINER (handle_box), toolbar);
+       gtk_container_border_width (GTK_CONTAINER (toolbar), 2);
+       gtk_widget_show (toolbar);
+
+       // new
+       w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
+                                                               "New",
+                                                               "Start a new Pk3",
+                                                               "",
+                                                               CPixMap::new_pixmap(window, "pk3man_tbnew.bmp"),
+                                                               //CPixMap::pixmap_from_char(window,xpm_new),
+                                                               GTK_SIGNAL_FUNC (HandleCommand),
+                                                               GINT_TO_POINTER (ID_FILE_NEW));
+
+       gtk_object_set_data (GTK_OBJECT (window), "tb_file_new", w);
+
+       // open
+       w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
+                                                               "Open",
+                                                               "Open an existing Pk3",
+                                                               "",
+                                                               CPixMap::new_pixmap(window, "pk3man_tbopen.bmp"),
+                                                               GTK_SIGNAL_FUNC (HandleCommand),
+                                                               GINT_TO_POINTER (ID_FILE_OPEN));
+
+       gtk_object_set_data (GTK_OBJECT (window), "tb_file_open", w);
+
+       // save
+       w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
+                                                               "Save",
+                                                               "Save the current Pk3",
+                                                               "",
+                                                               CPixMap::new_pixmap (window, "pk3man_tbsave.bmp"),
+                                                               GTK_SIGNAL_FUNC (HandleCommand),
+                                                               GINT_TO_POINTER (ID_FILE_SAVE));
+
+       gtk_object_set_data (GTK_OBJECT (window), "tb_file_save", w);
+
+       // space
+       gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
+
+       // wizard
+       w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
+                                                               "Wizard",
+                                                               "Build Pk3 from a Map",
+                                                               "",
+                                                               CPixMap::new_pixmap (window, "pk3man_tbwizard.bmp"),
+                                                               GTK_SIGNAL_FUNC (HandleCommand),
+                                                               GINT_TO_POINTER (ID_WIZARD));
+
+       gtk_object_set_data (GTK_OBJECT (window), "tb_wizard", w);
+
+       // space
+       gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
+
+       // view
+       w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
+                                                               "View",
+                                                               "View an entry",
+                                                               "",
+                                                               CPixMap::new_pixmap (window, "pk3man_tbview.bmp"),
+                                                               GTK_SIGNAL_FUNC (HandleCommand),
+                                                               GINT_TO_POINTER (ID_VIEW));
+
+       gtk_object_set_data (GTK_OBJECT (window), "tb_view", w);
+
+       // extract
+       w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
+                                                               "Extract",
+                                                               "Extract an entry",
+                                                               "",
+                                                               CPixMap::new_pixmap (window, "pk3man_tbextract.bmp"),
+                                                               GTK_SIGNAL_FUNC (HandleCommand),
+                                                               GINT_TO_POINTER (ID_EXTRACT));
+
+       gtk_object_set_data (GTK_OBJECT (window), "tb_extract", w);
+
+       // space
+       gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
+
+       // Add
+       w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
+                                                               "Wizard",
+                                                               "Add a file",
+                                                               "",
+                                                               CPixMap::new_pixmap (window, "pk3man_tbadd.bmp"),
+                                                               GTK_SIGNAL_FUNC (HandleCommand),
+                                                               GINT_TO_POINTER (ID_ADD));
+
+       gtk_object_set_data (GTK_OBJECT (window), "tb_add", w);
+
+       // rename
+       w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
+                                                               "Rename",
+                                                               "Rename an entry",
+                                                               "",
+                                                               CPixMap::new_pixmap (window, "pk3man_tbrename.bmp"),
+                                                               GTK_SIGNAL_FUNC (HandleCommand),
+                                                               GINT_TO_POINTER (ID_RENAME));
+
+       gtk_object_set_data (GTK_OBJECT (window), "tb_rename", w);
+
+
+       // rename
+       w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
+                                                               "Delete",
+                                                               "Delete an entry",
+                                                               "",
+                                                               CPixMap::new_pixmap (window, "pk3man_tbdelete.bmp"),
+                                                               GTK_SIGNAL_FUNC (HandleCommand),
+                                                               GINT_TO_POINTER (ID_DELETE));
+
+       gtk_object_set_data (GTK_OBJECT (window), "tb_delete", w);
+
+       return TRUE;
+}
+
+void CMainWnd::UpdateToolBar()
+{
+       std::string path=m_Tree.GetSelected();
+       bool file_selected=TRUE;
+
+       if (path=="")
+               file_selected=FALSE;
+
+       if (file_selected)
+       {
+               // enable toolbar buttons
+
+               GtkWidget *item;
+
+               item  = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_view"));
+               //gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), FALSE);
+               gtk_widget_set_sensitive (item, TRUE);
+
+               item  = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_extract"));
+               //gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), FALSE);
+               gtk_widget_set_sensitive (item, TRUE);
+
+               item  = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_delete"));
+               //gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), FALSE);
+               gtk_widget_set_sensitive (item, TRUE);
+
+               item  = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_rename"));
+               //gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), FALSE);
+               gtk_widget_set_sensitive (item, TRUE);
+
+       }
+       else
+       {
+               // disable toolbar buttons
+
+               GtkWidget *item;
+
+               item  = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_view"));
+               //gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), TRUE);
+               gtk_widget_set_sensitive (item, TRUE);
+
+               item  = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_extract"));
+               //gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), TRUE);
+               gtk_widget_set_sensitive (item, TRUE);
+
+               item  = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_delete"));
+               //gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), TRUE);
+               gtk_widget_set_sensitive (item, TRUE);
+
+               item  = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_rename"));
+               //gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), TRUE);
+               gtk_widget_set_sensitive (item, TRUE);
+
+       }
+
+}
+
+BOOL CMainWnd::CreateStatusBar(GtkWidget *window,GtkWidget *vbox)
+{
+       GtkWidget *hbox, *hbox1;
+       GtkWidget *frame;
+       GtkWidget *label;
+
+       hbox = gtk_hbox_new (FALSE, 0);
+       gtk_widget_show (hbox);
+       gtk_widget_set_usize (hbox, -1, 24);
+       gtk_container_border_width (GTK_CONTAINER (hbox), 1);
+       gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, TRUE, 2);
+
+       frame = gtk_frame_new ((char*)NULL);
+       gtk_widget_show (frame);
+       gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
+       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+
+       hbox1 = gtk_hbox_new (FALSE, 0);
+       gtk_container_add (GTK_CONTAINER (frame), hbox1);
+       gtk_container_border_width (GTK_CONTAINER (hbox1), 0);
+       gtk_widget_show (hbox1);
+
+       label = gtk_label_new (" Ready ... ");
+       gtk_widget_show (label);
+       gtk_box_pack_start (GTK_BOX (hbox1), label, FALSE, TRUE, 0);
+       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
+       gtk_misc_set_padding (GTK_MISC (label), 3, 0);
+       m_pStatusLabel[0] = label;
+
+       for (int i = 1; i < 3; i++)
+       {
+               frame = gtk_frame_new ((char*)NULL);
+               gtk_widget_show (frame);
+               gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
+               gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+
+               label = gtk_label_new ("             ");
+               gtk_widget_show (label);
+               gtk_container_add (GTK_CONTAINER (frame), label);
+               m_pStatusLabel[i] = label;
+       }
+
+       return TRUE;
+}
+
+void CMainWnd::OnFileOpen()
+{
+       // lets pick a file
+       const char *filename;
+
+       if (g_strModPath.GetLength()>0)
+               //filename=file_dialog(TRUE,"Choose a Pk3...",g_strModPath.GetBuffer(),"*.pk3");
+               filename=g_FuncTable.m_pfnFileDialog (m_pMainWnd, TRUE, "Choose a Pk3...",
+                                                                                       g_strModPath.GetBuffer(), "pk3man");
+       else
+               //filename=file_dialog(TRUE,"Choose a Pk3...",g_strBasePath.GetBuffer(),"*.pk3");
+               filename=g_FuncTable.m_pfnFileDialog (m_pMainWnd, TRUE, "Choose a Pk3...",
+                                                                                       g_strBasePath.GetBuffer(), "pk3man");
+
+       if (filename==NULL)
+               return;
+
+       Str fname=filename;
+       fname=fname.Right(3);
+       if (fname!="pk3")
+       {
+               //DoMessageBox("Please pick a Pk3 file","Pk3Man",MB_OK);
+               g_FuncTable.m_pfnMessageBox(m_pMainWnd,"Please pick a Pk3 file","Pk3Man",MB_OK, NULL);
+               return;
+       }
+
+       OnFileNew();
+       pak.Open(filename);
+       UpdateTree();
+
+       // update window title
+       g_FuncTable.m_pfnQE_ConvertDOSToUnixName (filename, filename);
+       std::string title=filename;
+       g_free (filename);
+       long pos=title.find_last_of('/');
+       title=title.substr(pos+1);
+       title="Pk3Man - "+title;
+       gtk_window_set_title (GTK_WINDOW (m_pMainWnd), title.c_str());
+}
+
+void CMainWnd::OnFileSave()
+{
+       const char *filename;
+
+       if (g_strModPath.GetLength()>0)
+               filename=g_FuncTable.m_pfnFileDialog (m_pMainWnd, FALSE, "Save As...",
+                                                                                       g_strModPath.GetBuffer(), "pk3man");
+       else
+               filename=g_FuncTable.m_pfnFileDialog (m_pMainWnd, FALSE, "Save As...",
+                                                                               g_strBasePath.GetBuffer(), "pk3man");
+
+       if (filename==NULL)
+               return;
+
+       g_FuncTable.m_pfnQE_ConvertDOSToUnixName (filename, filename);
+       std::string path=filename;
+       g_free (filename);
+       long p=path.find_last_of('/');
+       std::string name=path.substr(p,-1);
+
+       std::string tpath=g_strTempPath.GetBuffer() + name;
+
+       if (!pak.Save(tpath.c_str()))
+       {
+               // eek, error central
+               g_FuncTable.m_pfnMessageBox(m_pMainWnd,"Unable to save the pk3 to temp folder!","Pk3Man",MB_OK, NULL);
+               return;
+       }
+
+       // ok, now copy to proper place
+
+#ifdef WIN32
+
+       int ret=CopyFile(tpath.c_str(),path.c_str(),FALSE);
+       DeleteFile(tpath.c_str());
+
+       if (!ret)
+       {
+       g_FuncTable.m_pfnMessageBox(m_pMainWnd,"Unable to copy pk3 from temp folder!","Pk3Man",MB_OK, NULL);
+       return;
+       }
+
+#endif
+
+       pak.Close();
+       pak.Open(path.c_str());
+       m_Tree.Clear();
+       UpdateTree();
+
+       //update title
+       name=name.substr(1,-1);
+       std::string title="Pk3Man - "+name;
+       gtk_window_set_title (GTK_WINDOW (m_pMainWnd), title.c_str());
+}
+
+bool CMainWnd::OnFileNew()
+{
+       if (pak.IsModified())
+       {
+               int ret=g_FuncTable.m_pfnMessageBox(m_pMainWnd,"This will lose the current Pk3 contents\n\n    Are u sure?","Pk3Man",MB_YESNO, NULL);
+               if (ret!=IDYES)
+                       return FALSE;
+       }
+
+       pak.Close();
+       m_Tree.Clear();
+       gtk_window_set_title (GTK_WINDOW (m_pMainWnd), "Pk3Man - ");
+
+       return TRUE;
+}
+
+void CMainWnd::LoadExclusions()
+{
+       exclusions.clear();
+
+       FILE *fp;
+       std::string filename=g_strAppPath.GetBuffer();
+       filename+="plugins/pk3man.exclude";
+
+       fp=fopen(filename.c_str(),"rb");
+       if (!fp)
+               return;
+
+       while (!feof(fp))
+       {
+               std::string line=GetLine(fp);
+
+               if (line.length()==0)
+                       continue;
+
+               if (line[0]=='/' && line[1]=='/')
+                       continue;
+
+               for (int n=0 ; n < (int)line.length() ; n++)
+               {
+                       if (line[n]=='\\')
+                               line[n]='/';
+               }
+
+               if (line[0]=='/')
+                       line=line.substr(1,-1);
+
+               exclusions.push_back(line);
+       }
+}
+
+bool CMainWnd::IsExcluded(const char *name)
+{
+       for (std::list<std::string>::iterator i=exclusions.begin() ; i!=exclusions.end() ; i++)
+       {
+               std::string t=*i;
+
+               if (CWild::fpattern_match(t.c_str(),name))
+                       return TRUE;
+
+               std::string nm=name;
+               if (nm.find(t) != static_cast<size_t>(-1))
+                       return TRUE;
+       }
+
+       return FALSE;
+}
+
+void CMainWnd::OnWizard()
+{
+       if (!pak.IsEmpty())
+       {
+               int ret=g_FuncTable.m_pfnMessageBox(m_pMainWnd,"Add to current pak contents ?","Pk3Man",MB_YESNO, NULL);
+               if (ret==IDNO)
+               {
+                       if (!OnFileNew())
+                               return;
+               }
+
+       }
+
+       std::string mappath="maps";
+       mappath=g_strBasePath.GetBuffer()+mappath;
+
+       gchar *filename=g_FuncTable.m_pfnFileDialog(m_pMainWnd,TRUE,"Choose a Map...",mappath.c_str(),"pk3man");
+
+       if (filename==NULL)
+                       return;
+
+       g_FuncTable.m_pfnQE_ConvertDOSToUnixName (filename, filename);
+       std::string map=filename;
+       long p=map.find_last_of('/');
+       map=map.substr(p+1,-1);
+
+       //update title
+       std::string title="Pk3Man - "+map;
+       gtk_window_set_title (GTK_WINDOW (m_pMainWnd), title.c_str());
+
+       // add map and aas
+       ProcessFile(map.c_str(),".bsp","maps");
+       ProcessFile(map.c_str(),".aas","maps");
+
+       // add levelshots
+       if (!ProcessFile(map.c_str(),".jpg","levelshots"))
+               ProcessFile(map.c_str(),".tga","levelshots");
+
+       // arena file
+       ProcessFile(map.c_str(),".arena","scripts");
+
+       // initialise text list
+       texlist.clear();
+
+       // generate item list
+       FILE *fp;
+       fp=fopen(filename,"r");
+       g_free(filename);
+
+       if (!fp)
+               return;
+
+       while (!feof(fp))
+       {
+               std::string line=GetLine(fp);
+
+               if (line.find("// brush")!=static_cast<size_t>(-1))
+               {
+                       // its a brush
+                       line=GetLine(fp);
+                       line=GetLine(fp);
+
+                       if (line.find("patchDef")!=static_cast<size_t>(-1))
+                       {
+                               // its a patch
+                               line=GetLine(fp);
+                               line=GetLine(fp);
+
+                               // need to trim left and right
+                               int n=line.find_first_not_of(' ');
+                               if (n!=static_cast<size_t>(-1))
+                               line=line.substr(n);
+
+                               std::string tex="textures/"+line;
+                               AddToTexList(line.c_str());
+                       }
+                       else
+                       {
+                               // its a standard brush
+                               while (line.find_first_of('}')==static_cast<size_t>(-1))
+                               {
+                                       long p=line.find_last_of(')');
+                                       line=line.substr(p+2,-1);
+
+                                       p=line.find_first_of(' ');
+                                       line=line.substr(0,p);
+
+                                       std::string tex="textures/"+line;
+                                       AddToTexList(line.c_str());
+
+                                       // next
+                                       line=GetLine(fp);
+                               }
+                       }
+               }
+               else if (line.find(".md3")!=static_cast<size_t>(-1))
+               {
+                       long p=line.find_first_of(' ');
+                       std::string tex=line.substr(p+2,-1);
+                       tex=tex.substr(0,tex.length()-2);
+
+                       AddToTexList(tex.c_str());
+               }
+               else if (line.find(".wav")!=static_cast<size_t>(-1))
+               {
+                       long p=line.find_first_of(' ');
+                       std::string tex=line.substr(p+2,-1);
+                       tex=tex.substr(0,tex.length()-2);
+
+                       AddToTexList(tex.c_str());
+               }
+
+       }
+       fclose(fp);
+
+       // ok, now proccess our texlist
+       // if we find a shader we add its textures onto the end of the texlist
+
+       for ( std::list<std::string>::const_iterator i = texlist.begin() ; i != texlist.end() ; i++)
+       {
+               std::string tex=*i;
+
+               if (tex=="")
+                       continue;
+
+               std::string suffix=tex.substr(tex.length()-3,-1);
+
+               // is it a model?
+               if (suffix.compare("md3")==0)
+               {
+                       ParseModel(tex.c_str());
+
+                       // dont add md3's
+                       continue;
+               }
+
+               // does it exist as it is
+               if (ProcessFile(tex.c_str()))
+                       continue;
+
+               //shader
+               std::string shadername=tex;
+               const char *sname=NULL;
+
+               IShader *shader=g_ShadersTable.m_pfnShader_ForName_NoLoad(shadername.c_str());
+
+               if (shader)
+                       sname=shader->getShaderFileName();
+
+               if (strlen(sname)>0)
+               {
+                       ParseShader(sname,tex.c_str());
+
+                       if (ProcessFile(sname))
+                               continue;
+               }
+
+               // ok we got this far, its a texture
+
+               if (tex.find(".tga")!=static_cast<size_t>(-1) || tex.find(".jpg")!=static_cast<size_t>(-1))
+                       tex=tex.substr(0,tex.length()-4);
+
+               // jpegs
+               std::string jpeg=tex;
+               if (jpeg.find("textures/")!=0)
+                       jpeg="textures/"+jpeg;
+
+               jpeg+=".jpg";
+               if (ProcessFile(jpeg.c_str()))
+                       continue;
+
+               // tga's
+               std::string tga=tex;
+               if (tga.find("textures/")!=0)
+                       tga="textures/"+tga;
+
+               tga+=".tga";
+               if (ProcessFile(tga.c_str()))
+                       continue;
+
+       }
+
+}
+
+void CMainWnd::ParseModel(const char *pathname)
+{
+       char* modelbuff;
+       int len = g_FuncTable.m_pfnLoadFile(pathname, (void**)&modelbuff);
+
+       if (len==0)
+               return;
+
+       CMemFile file(modelbuff,len);
+
+       md3_header_t header;
+
+       file.Read(&header,sizeof(header));
+
+       int n, numtags=header.Tag_num*header.BoneFrame_num;
+
+       for (n=0 ; n<numtags ; n++)
+       {
+               md3_tag_t tag;
+               file.Read(&tag,sizeof(md3_tag_t));
+       }
+
+       for (n=0 ; n<header.BoneFrame_num ; n++)
+       {
+               md3_boneframe_t bone;
+               file.Read(&bone,sizeof(md3_boneframe_t));
+       }
+
+       for (int m=0 ; m<header.Mesh_num ; m++)
+       {
+               md3_mesh_t mesh;
+               file.Read(&mesh,sizeof(md3_mesh_t));
+
+               // skins
+               for (n=0 ; n<mesh.Skin_num ; n++)
+               {
+                       char SkinName[68];
+                       file.Read(&SkinName,sizeof(char)*68);
+
+                       // deal with the skin here
+                       // we add it to the end of the list (if it aint already there)
+                       // so we catch it later on
+
+                       AddToTexList(SkinName);
+               }
+
+               // triangles
+               for (n=0 ; n<mesh.Triangle_num ; n++)
+               {
+                       int Triangle[3];
+                       file.Read(&Triangle,sizeof(int)*3);
+               }
+
+               // uv's
+               for (n=0 ; n<mesh.Vertex_num ; n++)
+               {
+                       float uv[2];
+                       file.Read(&uv,sizeof(float)*2);
+               }
+
+               // vertices
+               int numverts=mesh.Vertex_num*mesh.MeshFrame_num;
+
+               for (n=0 ; n<numverts ; n++)
+               {
+                       md3_vertices_t verts;
+                       file.Read(&verts,sizeof(md3_vertices_t));
+               }
+
+       }
+
+// http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=491
+g_free(modelbuff);
+}
+
+void CMainWnd::AddToTexList(const char *buf)
+{
+       std::string tex;
+       int c=0;
+
+       while (buf[c]!=' ' && buf[c]!='\0')
+       {
+               tex+=buf[c];
+               c++;
+       }
+
+       if (!IsInTexList(tex.c_str()))
+               texlist.push_back(tex);
+
+}
+
+void CMainWnd::InitPaksInDir(const char *folder)
+{
+struct dirent *dirlist;
+DIR *dir;
+
+dir = opendir (g_strBasePath.GetBuffer());
+
+if (dir != NULL)
+{
+       while ((dirlist = readdir (dir)) != NULL)
+       {
+               if (!strstr (dirlist->d_name, ".pk3"))
+                       continue;
+
+               std::string path=g_strBasePath.GetBuffer();
+               path+=dirlist->d_name;
+
+               if (IsExcluded(dirlist->d_name))
+                       continue;
+
+               CPak *p=new CPak;
+
+               if (p->Open(path.c_str()))
+                       paklist.push_back(p);
+               else
+                       delete p;
+       }
+       closedir (dir);
+}
+}
+
+void CMainWnd::InitPakList()
+{
+       gtk_label_set_text (GTK_LABEL (m_pStatusLabel[0]), "Building pk3 references");
+
+       if (g_strModPath.GetLength()>0)
+               InitPaksInDir(g_strModPath.GetBuffer());
+
+       InitPaksInDir(g_strBasePath.GetBuffer());
+
+       gtk_label_set_text (GTK_LABEL (m_pStatusLabel[0]), "Ready ...");
+}
+
+void CMainWnd::FreePakList()
+{
+       std::list<CPak*>::iterator i;
+
+       for ( i = paklist.begin() ; i != paklist.end() ; i++)
+       {
+               CPak *p=*i;
+               delete p;
+       }
+
+       paklist.clear();
+}
+
+void CMainWnd::DeleteTempFiles()
+{
+       std::list<std::string>::iterator i;
+
+       for ( i = temp_files.begin() ; i != temp_files.end() ; i++)
+       {
+               std::string path=*i;
+
+               remove(path.c_str());
+       }
+
+       temp_files.clear();
+}
+
+bool CMainWnd::IsInTexList(const char *tex)
+{
+       for ( std::list<std::string>::const_iterator i = texlist.begin() ; i != texlist.end() ; i++)
+       {
+               std::string str=*i;
+
+               if (str.compare(tex)==0)
+                       return TRUE;
+       }
+
+       return FALSE;
+}
+
+void CMainWnd::SkipLines(FILE *fp, int n)
+{
+       for (int c=0 ; c<n ; c++)
+               std::string line=GetLine(fp);
+}
+
+std::string CMainWnd::GetLine(FILE *fp)
+{
+       std::string line;
+       char c='0';
+
+       // grab a line;
+       do
+       {
+               fread(&c,1,1,fp);
+
+               if (c!='\n' && c!='\t' && c!='\r')
+                       line+=c;
+
+       } while (c!='\n' && !feof(fp));
+
+       return line;
+
+}
+
+std::string CMainWnd::TrimString(const char *str)
+{
+       std::string out;
+
+       int c=0;
+       while (str[c]==' ' || str[c]=='\t')
+               c++;
+
+       int e=strlen(str);
+       while (str[e]==' ' || str[e]=='\n' || str[e]=='\r')
+               e--;
+
+       out=str;
+       out=out.substr(c,-1);
+
+       return out;
+}
+
+void CMainWnd::ParseShader(const char *pathname, const char *tex)
+{
+       if (pathname==NULL || tex==NULL)
+               return;
+
+       char* shaderbuff;
+       int len = g_FuncTable.m_pfnLoadFile(pathname, (void**)&shaderbuff);
+
+       if (len==0)
+               return;
+
+       std::string shader=shaderbuff;
+
+       // skip to start of shader
+       long pos=shader.find(tex);
+
+       if (pos==-1)    // shader not found????
+               return;
+
+       shader=shader.substr(pos);
+
+       bool inStage=FALSE;
+       bool inShader=FALSE;
+
+       // step through the lines
+       while(1)
+       {
+               pos=shader.find_first_of('\n');
+               if (pos==-1)
+                       break;
+
+               std::string line=shader.substr(0,pos-1);
+               shader=shader.substr(pos+1,-1);
+
+               line=TrimString(line.c_str());
+
+               if (line=="")
+                       continue;
+
+               if (line[0]=='/' && line[1]=='/')
+                       continue;
+
+               if (line[0]=='}')
+               {
+                       if (!inStage)
+                               break;
+                       else
+                               inStage=FALSE;
+
+                       continue;
+               }
+
+               if (line[0]=='{')
+               {
+                       if (!inShader)
+                       {
+                               inShader=TRUE;
+                       }
+                       else if (inShader)
+                       {
+                               inStage=TRUE;
+                       }
+
+                       continue;
+               }
+
+               // check for map/animmap e.t.c;
+
+               if (inStage)
+               {
+
+                       if (line.substr(0,3).compare("map")==0)
+                       {
+                               std::string map=line.substr(4,-1);
+                               AddToTexList(map.c_str());
+                               continue;
+                       }
+
+                       if (line.substr(0,8).compare("skyparms")==0)
+                       {
+                               std::string map=line.substr(9,-1);
+                               AddToTexList(map.c_str());
+                               continue;
+                       }
+
+                       if (line.substr(0,8).compare("clampmap")==0)
+                       {
+                               std::string map=line.substr(9,-1);
+                               AddToTexList(map.c_str());
+                               continue;
+                       }
+
+                       if (line.substr(0,7).compare("animmap")==0)
+                       {
+                               std::string map=line.substr(9,-1);
+                               map=TrimString(map.c_str());
+
+                               // skip past numbers
+                               long p=map.find_first_of(' ');
+                               map=map.substr(p+1,-1);
+
+                               while (1)
+                               {
+                                       long pos=map.find_first_of(' ');
+
+                                       if (pos==-1)
+                                       {
+                                               AddToTexList(map.c_str());
+                                               break;
+                                       }
+
+                                       std::string tex=map.substr(0,pos);
+                                       AddToTexList(tex.c_str());
+
+                                       map=map.substr(pos+1,-1);
+                               }
+                       }
+               }
+       }
+// http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=491
+g_free(shaderbuff);
+}
+
+bool CMainWnd::ProcessFile(const char *nm,const char *suffix,const char *folder)
+{
+       std::string name=nm;
+       name=name.substr(0,name.length()-4);
+       name+=suffix;
+
+       std::string path;
+
+       if (g_strModPath.GetLength()>0)
+               path=g_strModPath.GetBuffer();
+       else
+               path=g_strBasePath.GetBuffer();
+
+       path+=folder;
+       path+="/";
+       path+=name;
+
+       std::string rpath=folder;
+       rpath+="/";
+       rpath+=name;
+
+       if (IsExcluded(rpath.c_str()))  // quit out with a FALSE so we try others
+               return FALSE;
+
+       FILE *fp;
+       fp=fopen(path.c_str(),"rb");
+
+       if (fp)
+       {
+               if (!pak.IsInPak(rpath.c_str()))
+               {
+                       m_Tree.AddPath(rpath.c_str());
+                       pak.AddExternalFile(rpath.c_str(),path.c_str());
+               }
+
+               fclose(fp);
+               return TRUE;
+       }
+       else
+               return FindInAPk3(rpath.c_str());
+
+
+       return FALSE;
+}
+
+bool CMainWnd::ProcessFile(const char *nm)
+{
+       std::string name=nm;
+
+       if (IsExcluded(name.c_str()))   // quit out with a TRUE so we think it was added
+               return TRUE;
+
+       std::string path;
+
+       if (g_strModPath.GetLength()>0)
+               path=g_strModPath.GetBuffer();
+       else
+               path=g_strBasePath.GetBuffer();
+
+       path+=name;
+
+       FILE *fp;
+       fp=fopen(path.c_str(),"rb");
+
+       if (fp)
+       {
+               if (!pak.IsInPak(name.c_str()))
+               {
+                       m_Tree.AddPath(name.c_str());
+                       pak.AddExternalFile(name.c_str(),path.c_str());
+               }
+
+               return TRUE;
+       }
+       else
+       {
+               return FindInAPk3(name.c_str());
+       }
+
+
+       return FALSE;
+}
+
+bool CMainWnd::FindInAPk3(const char *name)
+{
+       std::list<CPak*>::iterator i;
+
+       for ( i = paklist.begin() ; i != paklist.end() ; i++)
+       {
+               CPak *p=*i;
+
+               if (p->m_filename.CompareNoCase(pak.m_filename)==0)
+                       continue;
+
+               std::string fname=p->m_filename.GetBuffer();
+               long pos=fname.find_last_of('/');
+               fname=fname.substr(pos+1,-1);
+
+               if (IsExcluded(fname.c_str()))
+                       continue;
+
+               if (p->IsInPak(name))
+               {
+                       pak_entry pe=p->FindPE(name);
+                       m_Tree.AddPath(name);
+                       pak.AddPakFile(name,p->m_filename.GetBuffer(),pe.compressed,pe.uncompressed);
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
+
+void CMainWnd::OnAdd()
+{
+       std::string path;
+       if (g_strModPath.GetLength()>0)
+               path=g_strModPath.GetBuffer();
+       else
+               path=g_strBasePath.GetBuffer();
+
+       //char *filename=file_dialog(TRUE,"Choose a file...",path.c_str(),"*.*");
+       gchar *filename=g_FuncTable.m_pfnFileDialog(m_pMainWnd,TRUE,"Choose a file...",path.c_str(),"pk3man");
+
+       if (filename==NULL)
+               return;
+
+       int c=0;
+
+       while (filename[c]!='\0')
+       {
+               if (filename[c]=='\\')
+                       filename[c]='/';
+
+               c++;
+       }
+
+       std::string fname=filename;
+
+       long p=path.length();
+       fname=fname.substr(p,-1);
+
+       if (pak.IsInPak((char*)fname.c_str()))
+               return;
+
+       pak.AddExternalFile((char *)fname.c_str(),(char *)filename);
+       m_Tree.AddPath((char *)fname.c_str());
+
+}
+
+void CMainWnd::OnDelete()
+{
+       std::string path=m_Tree.GetSelected();
+
+       if (path=="")
+               return;
+
+       pak.Delete(path.c_str());
+
+       //m_Tree.RemovePath(path.c_str());
+
+       // dodgy hack but works for now
+       m_Tree.Clear();
+       UpdateTree();
+
+}
+
+void CMainWnd::OnRename()
+{
+       std::string path=m_Tree.GetSelected();
+
+       if (path=="")
+               return;
+
+       CRenameDlg dlg;
+       dlg.m_Name=path;
+
+       if (dlg.DoModal()==IDOK)
+       {
+               pak.Rename(path.c_str(),dlg.m_Name.c_str());
+               m_Tree.Clear();
+               UpdateTree();
+       }
+
+}
+
+void CMainWnd::UpdateTree()
+{
+       // clear the tree and fill it with the items in the pak
+
+       for ( std::list<pak_entry>::const_iterator iEntry = pak.entries.begin() ; iEntry != pak.entries.end() ; iEntry++)
+       {
+               pak_entry pe=*iEntry;
+
+               std::string name;
+               if (pe.rename)
+                       name=pe.newname;
+               else
+                       name=pe.filename;
+
+               m_Tree.AddPath(name.c_str());
+       }
+
+}
+
+void CMainWnd::OnExtract()
+{
+       std::string path=m_Tree.GetSelected();
+
+       if (path=="")
+               return;
+
+       pak_entry pe=pak.FindPE((char*)path.c_str());
+
+       std::string bpath;
+       if (g_strModPath.GetLength()>0)
+               bpath=g_strModPath.GetBuffer();
+       else
+               bpath=g_strBasePath.GetBuffer();
+
+               //char *pathto=dir_dialog("Extract to ...",bpath.c_str());
+       gchar *pathto=g_FuncTable.m_pfnDirDialog(m_pMainWnd,"Extract to...",bpath.c_str());
+
+       if (pathto==NULL)
+               return;
+
+       long pos=path.find_last_of('/');
+       std::string name=path.substr(pos+1);
+
+       std::string cpath=pathto;
+       cpath+=name;
+
+       if (pe.pakname.compare(pak.m_filename.GetBuffer())==0)
+       {
+               // its in pak
+               pak.ExtractTo((char*)path.c_str(),(char*)cpath.c_str());
+               return;
+       }
+
+}
+
+void CMainWnd::OnView()
+{
+       std::string path=m_Tree.GetSelected();
+
+       if (path=="")
+               return;
+
+       pak_entry pe=pak.FindPE(path.c_str());
+
+       long p=pe.filename.find_last_of('/');
+       std::string name=pe.filename.substr(p+1,-1);
+       std::string temppath=g_strTempPath.GetBuffer()+name;
+
+       if (pe.frompak && pe.pakname.compare(pak.m_filename.GetBuffer())==0)
+       {
+               // its in pak
+               if (!pak.ExtractTo(path.c_str(),(char *)temppath.c_str()))
+                       return;
+
+               temp_files.push_back(temppath);
+
+               // view it
+       #ifdef WIN32
+               HANDLE hInst=ShellExecute(NULL,"open",(LPCTSTR)temppath.c_str(),NULL,NULL,SW_SHOWNORMAL);
+       #endif
+
+               return;
+       }
+
+       if (!pe.frompak)
+       {
+#ifdef WIN32
+               HANDLE hInst=ShellExecute(NULL,"open",(LPCTSTR)pe.pathname.c_str(),NULL,NULL,SW_SHOWNORMAL);
+#endif
+               return;
+       }
+
+       if (pe.frompak)
+       {
+               CPak p;
+               if (!p.Open(pe.pakname.c_str()))
+                       return;
+
+               if (!p.ExtractTo(path.c_str(),(char *)temppath.c_str()))
+                       return;
+
+               temp_files.push_back(temppath);
+
+               // view it
+#ifdef WIN32
+               HANDLE hInst=ShellExecute(NULL,"open",(LPCTSTR)temppath.c_str(),NULL,NULL,SW_SHOWNORMAL);
+#endif
+               return;
+       }
+}
+
+#ifdef WIN32
+void ShortToLong(CString &thePath)
+{
+       WIN32_FIND_DATA wfd;
+       std::string spath=thePath.GetBuffer();
+       std::string lpath="";
+       while(1)
+       {
+               FindFirstFile(spath.c_str(),&wfd);
+               std::string fname=wfd.cFileName;
+               lpath=fname+"\\"+lpath;
+               long pos=spath.find_last_of('\\');
+               spath=spath.substr(0,pos);
+               pos=spath.find_last_of('\\');
+
+               if (pos==-1)
+               {
+                       lpath=spath+"\\"+lpath;
+                       break;
+               }
+       }
+       thePath=lpath.c_str();
+}
+#endif
+
+void CMainWnd::GetPaths()
+{
+#if 0 //mattn
+#ifdef WIN32
+
+       // convert it to long format
+       ShortToLong(g_strBasePath);
+
+       // mod path
+       if (strcmp(mode,"Quake III Team Arena")==0)
+       {
+               g_strModPath=g_strBasePath;
+               long p=g_strModPath.Find("\\baseq3");
+               g_strModPath=g_strModPath.Left(p);
+               g_strModPath+="\\missionpack\\";
+
+               g_FuncTable.m_pfnQE_ConvertDOSToUnixName ((char *)g_strModPath.GetBuffer(), g_strModPath.GetBuffer());
+       }
+
+       g_FuncTable.m_pfnQE_ConvertDOSToUnixName ((char *)g_strBasePath.GetBuffer(), g_strBasePath.GetBuffer());
+
+       // apppath
+       // get path to the editor
+       char* pBuffer = g_strAppPath.GetBufferSetLength(_MAX_PATH + 1);
+       GetModuleFileName(NULL, pBuffer, _MAX_PATH);
+       pBuffer[g_strAppPath.ReverseFind('\\') + 1] = '\0';
+       g_strAppPath.ReleaseBuffer();
+       g_FuncTable.m_pfnQE_ConvertDOSToUnixName ((char *)g_strAppPath.GetBuffer(), g_strAppPath.GetBuffer());
+
+       char temp_path[_MAX_PATH];
+       GetTempPath(_MAX_PATH,temp_path);
+       g_strTempPath=temp_path;
+
+#endif
+
+#ifdef __linux__
+       Str tmp;
+       tmp = g_strBasePath.GetBuffer();
+       tmp += "/../";
+
+       // NOTE: we build g_strAppPath with a '/' (or '\' on WIN32)
+       // it's a general convention in Radiant to have the slash at the end of directories
+       char real[PATH_MAX];
+       realpath (tmp.GetBuffer(), real);
+       if (real[strlen(real)-1] != '/')
+       strcat(real, "/");
+       g_strAppPath = real;
+
+       g_strTempPath="~/.tmp";
+#endif
+
+       extern const char *PLUGIN_NAME;
+       g_strBitmapsPath = g_FuncTable.m_pfnPathForPluginName(PLUGIN_NAME);
+       g_strBitmapsPath += "bitmaps/";
+#endif
+}
+
+void CMainWnd::UpdateStatus()
+{
+       std::string path=m_Tree.GetSelected();
+
+       if (path=="")
+       {
+               gtk_label_set_text (GTK_LABEL (m_pStatusLabel[0]), "");
+               gtk_label_set_text (GTK_LABEL (m_pStatusLabel[1]), "");
+               gtk_label_set_text (GTK_LABEL (m_pStatusLabel[2]), "");
+
+               return;
+       }
+
+       pak_entry pe=pak.FindPE(path.c_str());
+
+       std::string p=path;
+       long pos=p.find_last_of('/');
+       p=p.substr(pos+1);
+       gtk_label_set_text (GTK_LABEL (m_pStatusLabel[0]), p.c_str());
+
+       char lbl[255];
+       sprintf(lbl," %ldk ",pe.uncompressed/1000);
+       gtk_label_set_text (GTK_LABEL (m_pStatusLabel[1]), lbl);
+
+       sprintf(lbl," %ldk ",pe.compressed/1000);
+       gtk_label_set_text (GTK_LABEL (m_pStatusLabel[2]), lbl);
+
+}
+
+void CMainWnd::HandleDrop()
+{
+       std::string path=m_Tree.GetSelected();
+       bool file_selected=TRUE;
+
+       if (path=="")
+               file_selected=FALSE;
+
+       //if (m_mnuDrop == NULL) // first time, load it up
+       //{
+               GtkAccelGroup *accel;//, *menu_in_menu_accel;
+               GtkWidget *menu;//, *menu_in_menu, *item, *submenu;
+
+               menu = m_mnuDrop = gtk_menu_new ();
+               accel = gtk_accel_group_new ();
+               gtk_menu_set_accel_group (GTK_MENU (menu), accel);
+
+               //menu_in_menu = create_menu_in_menu (menu, "Select", accel, &menu_in_menu_accel);
+
+               create_menu_item (menu, "Add file", accel,
+                       GTK_SIGNAL_FUNC (HandleCommand), ID_ADD);
+
+               if (file_selected)
+               {
+                       create_menu_item (menu, "View File", accel,
+                       GTK_SIGNAL_FUNC (HandleCommand), ID_VIEW);
+
+                       create_menu_item (menu, "Extract file", accel,
+                       GTK_SIGNAL_FUNC (HandleCommand), ID_EXTRACT);
+
+                       menu_separator (menu);
+
+                       create_menu_item (menu, "Rename File", accel,
+                       GTK_SIGNAL_FUNC (HandleCommand), ID_RENAME);
+
+                       create_menu_item (menu, "Delete file", accel,
+                       GTK_SIGNAL_FUNC (HandleCommand), ID_DELETE);
+               }
+       //}
+
+       gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 1, GDK_CURRENT_TIME);
+}
+
+
+////////////////////////////////////////////
+// some handy stuff ripped from GtkRadiant
+////////////////////////////////////////////
+
+
+GtkWidget* create_menu_in_menu (GtkWidget *menu, gchar *label, GtkAccelGroup *menu_accel,
+                               GtkAccelGroup **submenu_accel)
+{
+       GtkWidget *item, *submenu;
+       guint tmp_key;
+
+       item = gtk_menu_item_new_with_label ("");
+       tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (item)->child), label);
+       gtk_widget_add_accelerator (item, "activate_item", menu_accel, tmp_key, 0, (GtkAccelFlags)0);
+       gtk_widget_show (item);
+       gtk_container_add (GTK_CONTAINER (menu), item);
+
+       submenu = gtk_menu_new ();
+       gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
+       *submenu_accel = gtk_accel_group_new ();
+       gtk_menu_set_accel_group (GTK_MENU (submenu), *submenu_accel);
+
+       return submenu;
+}
+
+GtkWidget* create_menu_item (GtkWidget *menu, gchar *label, GtkAccelGroup *menu_accel,
+                               GtkSignalFunc func, int id)
+{
+       GtkWidget *item;
+       guint tmp_key;
+
+#ifdef NO_UNDERSCORE
+       char label_tmp[1024];
+       strcpy( label_tmp, label );
+       if (char* c = strchr (label_tmp, '_'))
+               while (*c)
+               *c++ = *(c+1);
+       item = gtk_menu_item_new_with_label (label_tmp);
+#else
+       item = gtk_menu_item_new_with_label ("");
+       tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (item)->child), label);
+       gtk_widget_add_accelerator (item, "activate_item", menu_accel, tmp_key, 0, (GtkAccelFlags)0);
+#endif
+       gtk_widget_show (item);
+       gtk_container_add (GTK_CONTAINER (menu), item);
+       gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (func), GINT_TO_POINTER (id));
+
+
+       return item;
+}
+
+GtkWidget* menu_separator (GtkWidget *menu)
+{
+       GtkWidget *menu_item = gtk_menu_item_new ();
+       gtk_menu_append (GTK_MENU (menu), menu_item);
+       gtk_widget_set_sensitive (menu_item, FALSE);
+       gtk_widget_show (menu_item);
+       return menu_item;
+}
diff --git a/contrib/pk3man/mainwnd.h b/contrib/pk3man/mainwnd.h
new file mode 100644 (file)
index 0000000..f7cf5dd
--- /dev/null
@@ -0,0 +1,87 @@
+// MainWnd.h: interface for the CMainWnd class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_MAINWND_H__E2FFC5D8_4D6E_4752_8976_811551035B7A__INCLUDED_)
+#define AFX_MAINWND_H__E2FFC5D8_4D6E_4752_8976_811551035B7A__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "stdafx.h"
+#include "tree.h"
+#include "pak.h"
+
+
+//void HandleCommand(GtkWidget *widget, gpointer data);
+
+
+class CMainWnd
+{
+public:
+       CMainWnd();
+       virtual ~CMainWnd();
+
+       GtkWidget* m_pMainWnd;
+       GtkWidget *m_pStatusLabel[3];
+       GtkWidget *m_ScrolledWin;
+       GtkWidget *m_Toolbar;
+
+       GtkWidget* m_mnuDrop;
+
+       CTree m_Tree;
+       CPak pak;
+
+       std::list<std::string> texlist;
+       std::list<CPak*> paklist;
+       std::list<std::string> exclusions;
+       std::list<std::string> temp_files;
+
+       BOOL Create(GtkWidget *parent);
+       BOOL CreateToolbar(GtkWidget *window,GtkWidget *vbox);
+       BOOL CreateStatusBar(GtkWidget *window,GtkWidget *vbox);
+       BOOL CreateTreeView(GtkWidget *window,GtkWidget *vbox);
+
+       void GetPaths();
+       void UpdateTree();
+       void UpdateStatus();
+       void UpdateToolBar();
+
+       void HandleDrop();
+
+       // command handlers
+       bool OnFileNew();
+       void OnFileOpen();
+       void OnFileSave();
+       void OnWizard();
+       void OnView();
+       void OnExtract();
+       void OnAdd();
+       void OnRename();
+       void OnDelete();
+       bool OnClose();
+       void OnDestroy();
+
+       bool ProcessFile(const char *name,const char *suffix,const char *folder);
+       bool ProcessFile(const char *name);
+
+       std::string GetLine(FILE *fp);
+       void SkipLines(FILE *fp, int n);
+       void AddToTexList(const char *buf);
+       bool IsInTexList(const char *tex);
+       void ParseShader(const char*sname, const char *tex);
+       std::string TrimString(const char *str);
+       void ParseModel(const char *pathname);
+
+       void InitPakList();
+       void InitPaksInDir(const char *folder);
+       void FreePakList();
+       bool FindInAPk3(const char *name);
+
+       void LoadExclusions();
+       bool IsExcluded(const char *name);
+       void DeleteTempFiles();
+};
+
+#endif // !defined(AFX_MAINWND_H__E2FFC5D8_4D6E_4752_8976_811551035B7A__INCLUDED_)
diff --git a/contrib/pk3man/md3.h b/contrib/pk3man/md3.h
new file mode 100644 (file)
index 0000000..805df71
--- /dev/null
@@ -0,0 +1,111 @@
+// MD3 file headers
+
+
+typedef struct
+{
+       char ID[4];         //id of file, always "IDP3"
+       int  Version;       //i suspect this is a version
+                                               //number, always 15
+       char FileName[68];      //sometimes left Blank...
+                                               //65 chars, 32bit aligned ==
+                                               //68 chars
+       int  BoneFrame_num; //number of BoneFrames
+       int  Tag_num;       //number of 'tags' per BoneFrame
+       int  Mesh_num;      //number of meshes/skins
+       int  MaxSkin_num;   //maximum number of unique skins
+                                               //used in md3 file
+       int  HeaderLength;  //always equal to the length of
+                                               //this header
+       int  Tag_Start;     //starting position of
+                                               //tag-structures
+       int  Tag_End;           //ending position of
+                                               //tag-structures/starting
+                                               //position of mesh-structures
+       int  FileSize;          //size of file
+} md3_header_t;
+
+
+typedef struct
+{
+       char Name[64];          //name of 'tag' as it's usually
+                                               //called in the md3 files try to
+                                               //see it as a sub-mesh/seperate
+                                               //mesh-part.
+                                               //sometimes this 64 string may
+                                               //contain some garbage, but
+                                               //i've been told this is because
+                                               //some tools leave garbage in
+                                               //those strings, but they ARE
+                                               //strings...
+       float Postition[3]; //relative position of tag
+       float Rotation[3][3];   //the direction the tag is facing relative to the rest of the model
+} md3_tag_t;
+
+
+typedef struct
+{
+       //unverified:
+       float  Mins[3];
+       float  Maxs[3];
+       float  Position[3];
+       float  scale;
+       char   Creator[16];     //i think this is the
+                               //"creator" name..
+                               //but i'm only guessing.
+} md3_boneframe_t;
+
+
+typedef struct
+{
+       char ID[4];             //id, must be IDP3
+       char Name[68];          //name of mesh
+                               //65 chars,
+                               //32 bit aligned == 68 chars
+       int  MeshFrame_num;     //number of meshframes
+                               //in mesh
+       int  Skin_num;          //number of skins in mesh
+       int  Vertex_num;        //number of vertices
+       int  Triangle_num;      //number of Triangles
+       int  Triangle_Start;    //starting position of
+                               //Triangle data, relative
+                               //to start of Mesh_Header
+       int  HeaderSize;        //size of header
+       int  TexVec_Start;      //starting position of
+                               //texvector data, relative
+                               //to start of Mesh_Header
+       int  Vertex_Start;      //starting position of
+                               //vertex data,relative
+                               //to start of Mesh_Header
+       int  MeshSize;          //size of mesh
+} md3_mesh_t;
+
+
+typedef struct
+{
+       char Name[68];  //name of skin used by mesh
+                               //65 chars,
+                               //32 bit aligned == 68 chars
+} md3_skin_t;
+
+
+typedef struct
+{
+       int  Triangle[3];       //vertex 1,2,3 of triangle
+
+} md3_triangles_t;
+
+
+typedef struct
+{
+       float  TexVec[2];       //Texture U/V coordinates of vertex
+
+} md3_texcoords_t;
+
+
+typedef struct
+{
+       //!!!important!!! signed!
+       signed short Vec[3];            //vertex X/Y/Z coordinate
+       unsigned char EnvTex[2];        //enviromental mapping texture coordinates
+
+} md3_vertices_t;
diff --git a/contrib/pk3man/memfile.cpp b/contrib/pk3man/memfile.cpp
new file mode 100644 (file)
index 0000000..041781e
--- /dev/null
@@ -0,0 +1,36 @@
+// MemFile.cpp: implementation of the CMemFile class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "memfile.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CMemFile::CMemFile()
+{
+       data=NULL;
+       ptr=NULL;
+       end=NULL;
+}
+
+CMemFile::CMemFile(char *block,long len)
+{
+       data=block;
+       ptr=block;
+       end=block+len;
+}
+
+
+CMemFile::~CMemFile()
+{
+
+}
+
+void CMemFile::Read(void *to,long size)
+{
+       memcpy(to,ptr,size);
+       ptr+=size;
+}
diff --git a/contrib/pk3man/memfile.h b/contrib/pk3man/memfile.h
new file mode 100644 (file)
index 0000000..15123bd
--- /dev/null
@@ -0,0 +1,27 @@
+// MemFile.h: interface for the CMemFile class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_MEMFILE_H__FCA4B794_CC06_4F09_8B54_B1BF10291ECA__INCLUDED_)
+#define AFX_MEMFILE_H__FCA4B794_CC06_4F09_8B54_B1BF10291ECA__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class CMemFile  
+{
+public:
+       CMemFile();
+       CMemFile(char *data, long len);
+       virtual ~CMemFile();
+
+       char *data;
+       char *ptr;
+       char *end;
+       
+       void Read(void *to,long size);
+
+};
+
+#endif // !defined(AFX_MEMFILE_H__FCA4B794_CC06_4F09_8B54_B1BF10291ECA__INCLUDED_)
diff --git a/contrib/pk3man/pak.cpp b/contrib/pk3man/pak.cpp
new file mode 100644 (file)
index 0000000..02df3df
--- /dev/null
@@ -0,0 +1,421 @@
+// Pak.cpp: implementation of the CPak class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "pak.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CPak::CPak()
+{
+       m_bModified=FALSE;
+       
+}
+
+CPak::~CPak()
+{
+       Close();
+}
+
+
+bool CPak::Open(const char *filename)
+{
+       Close();
+       
+       unzFile uf=NULL;
+
+       uf = unzOpen(filename);
+       if (uf==NULL)
+               return FALSE;
+
+       unz_global_info gi;
+       int err = unzGetGlobalInfo (uf,&gi);
+       if (err!=UNZ_OK)
+       {
+               Close();
+               return FALSE;
+       }
+
+       m_filename=filename;
+
+       // ok, now build the internal list of entries
+
+       unzGoToFirstFile(uf);
+
+       do
+       {
+               pak_entry pe;
+
+               pe.frompak=TRUE;
+               pe.pakname=m_filename;
+               pe.rename=FALSE;
+
+               char filename_inzip[256];
+               unz_file_info file_info;
+               //              uLong ratio=0;
+               //              const char *string_method;
+               err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
+               if (err!=UNZ_OK)
+               {
+                       continue;
+               }
+               
+               pe.filename=filename_inzip;
+               pe.compressed=file_info.compressed_size;
+               pe.uncompressed=file_info.uncompressed_size;
+
+               entries.push_back(pe);
+
+       } while (unzGoToNextFile(uf)==UNZ_OK);
+       
+
+       unzClose(uf);
+       m_bModified=FALSE;
+
+       return TRUE;
+}
+
+bool CPak::Save(const char *path)
+{
+       if (!m_bModified)
+               return FALSE;
+
+       if (path==NULL)
+               return FALSE;
+
+       //      unzFile uf=NULL;
+       zipFile zf=NULL;
+       
+       zf=zipOpen(path,0);
+
+       for ( std::list<pak_entry>::const_iterator iEntry = entries.begin() ; iEntry != entries.end() ; iEntry++)
+       {
+               pak_entry pe=*iEntry;
+
+               if (pe.frompak)
+               {
+                       if (pe.pakname.compare(m_filename)==0)
+                       {
+                               // its in this pak
+                               long size;
+                               unsigned char *buf=Extract(pe.filename.c_str(),size);
+
+                               if (!buf)
+                                       continue;
+
+                               zip_fileinfo zipfi;
+
+                               std::string name=pe.filename;
+                               if (pe.rename)
+                                       name=pe.newname;
+
+                               zipOpenNewFileInZip(zf,name.c_str(),&zipfi,NULL,0,NULL,0,NULL,Z_DEFLATED,Z_DEFAULT_COMPRESSION);
+                               zipWriteInFileInZip(zf,buf,size);
+                               zipCloseFileInZip(zf);
+
+                               delete buf;
+                       }
+                       else
+                       {
+                               // its in another pack
+
+                               CPak p;
+                               if (!p.Open(pe.pakname.c_str()))
+                                       continue;
+
+                               long size;
+                               unsigned char *buf=p.Extract(pe.filename.c_str(),size);
+
+                               if (!buf)
+                                       continue;
+
+                               zip_fileinfo zipfi;
+
+                               std::string name=pe.filename;
+                               if (pe.rename)
+                                       name=pe.newname;
+
+                               zipOpenNewFileInZip(zf,name.c_str(),&zipfi,NULL,0,NULL,0,NULL,Z_DEFLATED,Z_DEFAULT_COMPRESSION);
+                               zipWriteInFileInZip(zf,buf,size);
+                               zipCloseFileInZip(zf);
+
+                               delete buf;
+                       }
+
+               }
+               else
+               {
+                       // its an external file
+
+                       FILE *fp;
+                       fp=fopen(pe.pathname.c_str(),"rb");
+
+                       if (!fp)
+                               continue;
+
+                       fseek(fp,0,SEEK_END);
+                       long size=ftell(fp);
+                       fseek(fp,0,0);
+                       unsigned char *buf=new unsigned char[size];
+                       fread(buf,sizeof(unsigned char),size,fp);
+                       fclose(fp);
+
+                       if (!buf)
+                               continue;
+
+                       zip_fileinfo zipfi;
+
+                       std::string name=pe.filename;
+                       if (pe.rename)
+                               name=pe.newname;
+
+                       zipOpenNewFileInZip(zf,name.c_str(),&zipfi,NULL,0,NULL,0,NULL,Z_DEFLATED,Z_DEFAULT_COMPRESSION);
+                       zipWriteInFileInZip(zf,buf,size);
+                       zipCloseFileInZip(zf);
+
+                       delete buf;
+
+               }
+       
+       }
+
+       zipClose(zf,"Created by Pk3man - http://pk3man.sourceforge.net");
+
+       m_bModified=FALSE;
+       return TRUE;
+}
+
+void CPak::Close()
+{
+
+       m_filename="";
+       entries.clear();
+       m_bModified=FALSE;
+
+}
+
+bool CPak::IsModified()
+{
+       return m_bModified;
+}
+
+pak_entry CPak::FindPE(const char *path)
+{
+       pak_entry pe;   
+
+       for ( std::list<pak_entry>::const_iterator iEntry = entries.begin() ; iEntry != entries.end() ; iEntry++)
+       {
+               pe=*iEntry;
+
+               if (!pe.rename && pe.filename.compare(path)==0)
+                       return pe;
+
+               if (pe.rename && pe.newname.compare(path)==0)
+                       return pe;
+       }
+
+       pe.compressed=0;
+       pe.uncompressed=0;
+
+       return pe;
+}
+
+bool CPak::IsEmpty()
+{
+       return entries.empty();
+}
+
+unsigned char *CPak::Extract(const char *path, long &size)
+{
+       unzFile uf=NULL;
+
+       uf = unzOpen(m_filename.GetBuffer());
+       if (uf==NULL)
+               return FALSE;
+
+       unz_global_info gi;
+       int err = unzGetGlobalInfo (uf,&gi);
+       if (err!=UNZ_OK)
+       {
+               Close();
+               return FALSE;
+       }
+       
+       unzGoToFirstFile(uf);
+
+       do
+       {
+               char filename_inzip[256];
+               unz_file_info file_info;
+                               
+               err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
+               
+               if (err!=UNZ_OK)
+               {
+                       unzClose(uf);
+                       return FALSE;
+               }
+               
+               size=file_info.uncompressed_size;
+
+               if (strcmp(path,filename_inzip)==0)
+               {
+                       // found it
+                       // extract it
+                       
+                       if (unzOpenCurrentFile(uf)!=UNZ_OK)
+                       {
+                               unzClose(uf);
+                               return NULL;
+                       }
+                                               
+                       unsigned char *buf=new unsigned char[size];
+                       unzReadCurrentFile(uf,buf,size);
+                       unzCloseCurrentFile(uf);
+                       unzClose(uf);
+                       return buf;
+               }
+
+       } while (unzGoToNextFile(uf)==UNZ_OK);
+
+
+       unzClose(uf);
+       return NULL;
+}
+
+bool CPak::ExtractTo(const char *path, char *pathto)
+{
+       long size;
+       unsigned char *buf=Extract(path,size);
+       
+       if (!buf)
+               return FALSE;
+       
+       FILE *f=fopen(pathto,"wb");
+       if (f)
+       {                               
+               fwrite(buf,sizeof(unsigned char),size,f);
+               fclose(f);
+               delete buf;
+               return TRUE;
+       }       
+
+       delete buf;
+       return FALSE;
+}
+
+bool CPak::IsInPak(const char *path)
+{
+       pak_entry pe;   
+
+       for ( std::list<pak_entry>::const_iterator iEntry = entries.begin() ; iEntry != entries.end() ; iEntry++)
+       {
+               pe=*iEntry;
+
+               if (!pe.rename && pe.filename.compare(path)==0)
+                       return TRUE;
+
+               if (pe.rename && pe.newname.compare(path)==0)
+                       return TRUE;
+       }
+
+       return FALSE;
+}
+
+bool CPak::AddExternalFile(const char *name,const char *path)
+{
+
+       FILE *fp;
+       fp=fopen(path,"rb");
+
+       if (!fp)
+               return FALSE;
+
+       fseek(fp,0,SEEK_END);
+       long size=ftell(fp);
+       fclose(fp);
+       
+       pak_entry pe;
+
+       pe.rename=FALSE;
+       pe.frompak=FALSE;
+       pe.pathname=path;
+       pe.filename=name;
+       pe.compressed=size;
+       pe.uncompressed=size;
+       
+       entries.push_back(pe);
+
+       m_bModified=TRUE;
+
+       return TRUE;
+
+}
+
+bool CPak::AddPakFile(const char *name,const char *pakname,long comp, long uncomp)
+{
+       pak_entry pe;
+
+       pe.rename=FALSE;
+       pe.frompak=TRUE;
+
+       pe.filename=name;
+       pe.pakname=pakname;
+       pe.pathname="";
+       
+       pe.compressed=comp;
+       pe.uncompressed=uncomp;
+       
+       entries.push_back(pe);
+
+       m_bModified=TRUE;
+
+       return TRUE;
+}
+
+bool CPak::Delete(const char *path)
+{
+       pak_entry pe;   
+
+       for ( std::list<pak_entry>::iterator iEntry = entries.begin() ; iEntry != entries.end() ; iEntry++)
+       {
+               pe=*iEntry;
+
+               if ((!pe.rename && pe.filename.compare(path)==0) || (pe.rename && pe.newname.compare(path)==0))
+               {
+                       entries.erase(iEntry);
+                       m_bModified=TRUE;
+                       return TRUE;
+               }
+       }
+
+       return FALSE;
+}
+
+bool CPak::Rename(const char *path,const char *newname)
+{
+       pak_entry pe;   
+
+       for ( std::list<pak_entry>::iterator iEntry = entries.begin() ; iEntry != entries.end() ; iEntry++)
+       {
+               pe=*iEntry;
+
+               if ((!pe.rename && pe.filename.compare(path)==0) || (pe.rename && pe.newname.compare(path)==0))
+               {
+                       entries.erase(iEntry);
+                       
+                       pe.rename=TRUE;
+                       pe.newname=newname;
+
+                       entries.push_back(pe);
+                       m_bModified=TRUE;
+
+                       return TRUE;
+               }
+       }
+
+       return FALSE;
+}
diff --git a/contrib/pk3man/pak.h b/contrib/pk3man/pak.h
new file mode 100644 (file)
index 0000000..f1de00c
--- /dev/null
@@ -0,0 +1,74 @@
+// Pak.h: interface for the CPak class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_PAK_H__CB5AFBB6_E37C_4898_AB04_1ABEA6AC9B45__INCLUDED_)
+#define AFX_PAK_H__CB5AFBB6_E37C_4898_AB04_1ABEA6AC9B45__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "stdafx.h"
+
+extern "C"
+{
+#include "./zlib/zlib.h"
+#include "./zlib/unzip.h"
+#include "./zlib/zip.h" 
+}
+#include <list>
+#include <string>
+
+typedef struct
+{
+       // file
+       std::string filename;
+       std::string pathname;
+       
+       // external pak
+       BOOL frompak;
+       std::string pakname;
+
+       // rename
+       BOOL rename;
+       std::string newname;
+
+       //sizes
+       unsigned long uncompressed;
+       unsigned long compressed;
+
+} pak_entry;
+
+
+class CPak  
+{
+public:
+       CPak();
+       virtual ~CPak();
+
+
+       Str m_filename;
+       std::list<pak_entry> entries;
+       bool m_bModified;
+
+       bool Open(const char *filename);
+       void Close();
+       bool IsModified();
+       bool Save(const char *);
+       bool IsEmpty();
+
+       pak_entry FindPE(const char *path);
+       bool IsInPak(const char *path);
+
+       bool AddExternalFile(const char *name,const char *path);
+       bool AddPakFile(const char *name,const char *pakname,long comp, long uncomp);
+       bool Delete(const char *path);
+       bool Rename(const char *path,const char *newname);
+
+       bool ExtractTo(const char *path, char *pathto);
+       unsigned char *Extract(const char *path, long &size);
+       
+};
+
+#endif // !defined(AFX_PAK_H__CB5AFBB6_E37C_4898_AB04_1ABEA6AC9B45__INCLUDED_)
diff --git a/contrib/pk3man/pixmap.cpp b/contrib/pk3man/pixmap.cpp
new file mode 100644 (file)
index 0000000..2ed24b8
--- /dev/null
@@ -0,0 +1,581 @@
+// PixMap.cpp: implementation of the CPixMap class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "pixmap.h"
+
+#ifdef __linux__
+       #include <gdk/gdkx.h>
+#else
+       #include <gdk/win32/gdkwin32.h>
+       #define NO_UNDERSCORE
+#endif
+
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CPixMap::CPixMap()
+{
+
+}
+
+CPixMap::~CPixMap()
+{
+
+}
+
+unsigned char* CPixMap::load_bitmap_file (const char* filename,guint16* width, guint16* height)
+{
+  gint32 bmWidth, bmHeight;
+  guint16 bmPlanes, bmBitsPixel;
+  typedef struct {
+    unsigned char rgbBlue;
+    unsigned char rgbGreen;
+    unsigned char rgbRed;
+    unsigned char rgbReserved;
+  } RGBQUAD;
+  unsigned char m1,m2;
+  unsigned long sizeimage;
+  short res1,res2;
+  long filesize, pixoff;
+  long bmisize, compression;
+  long xscale, yscale;
+  long colors, impcol;
+  unsigned long m_bytesRead = 0;
+  unsigned char *imagebits = NULL;
+  FILE *fp;
+
+  *width = *height = 0;
+
+  fp = fopen(filename,"rb");
+  if (fp == NULL)
+    return NULL;
+
+  long rc;
+  rc = fread(&m1, 1, 1, fp);
+  m_bytesRead++;
+  if (rc == -1)
+    {
+      fclose(fp);
+      return NULL;
+    }
+
+  rc = fread(&m2, 1, 1, fp);
+  m_bytesRead++;
+  if ((m1!='B') || (m2!='M'))
+    {
+      fclose(fp);
+      return NULL;
+    }
+
+  rc = fread((long*)&(filesize),4,1,fp); m_bytesRead+=4;
+  if (rc != 1) { fclose(fp); return NULL; }
+
+  rc = fread((int*)&(res1),2,1,fp); m_bytesRead+=2;
+  if (rc != 1) { fclose(fp); return NULL; }
+
+  rc = fread((int*)&(res2),2,1,fp); m_bytesRead+=2;
+  if (rc != 1) { fclose(fp); return NULL; }
+
+  rc = fread((long*)&(pixoff),4,1,fp); m_bytesRead+=4;
+  if (rc != 1) { fclose(fp); return NULL; }
+
+  rc = fread((long*)&(bmisize),4,1,fp); m_bytesRead+=4;
+  if (rc != 1) { fclose(fp); return NULL; }
+
+  rc = fread((long*)&(bmWidth),4,1,fp); m_bytesRead+=4;
+  if (rc != 1) { fclose(fp); return NULL; }
+
+  rc = fread((long*)&(bmHeight),4,1,fp); m_bytesRead+=4;
+  if (rc != 1) { fclose(fp); return NULL; }
+
+  rc = fread((int*)&(bmPlanes),2,1,fp); m_bytesRead+=2;
+  if (rc != 1) { fclose(fp); return NULL; }
+
+  rc = fread((int*)&(bmBitsPixel),2,1,fp); m_bytesRead+=2;
+  if (rc != 1) { fclose(fp); return NULL; }
+
+  rc = fread((long*)&(compression),4,1,fp); m_bytesRead+=4;
+  if (rc != 1) { fclose(fp); return NULL; }
+
+  rc = fread((long*)&(sizeimage),4,1,fp); m_bytesRead+=4;
+  if (rc != 1) {fclose(fp); return NULL; }
+
+  rc = fread((long*)&(xscale),4,1,fp); m_bytesRead+=4;
+  if (rc != 1) { fclose(fp); return NULL; }
+
+  rc = fread((long*)&(yscale),4,1,fp); m_bytesRead+=4;
+  if (rc != 1) { fclose(fp); return NULL; }
+
+  rc = fread((long*)&(colors),4,1,fp); m_bytesRead+=4;
+  if (rc != 1) { fclose(fp); return NULL; }
+
+  rc = fread((long*)&(impcol),4,1,fp); m_bytesRead+=4;
+  if (rc != 1) { fclose(fp); return NULL; }
+
+  if (colors == 0)
+    colors = 1 << bmBitsPixel;
+
+  RGBQUAD *colormap = NULL;
+
+  if (bmBitsPixel != 24)
+    {
+      colormap = new RGBQUAD[colors];
+      if (colormap == NULL)
+       {
+         fclose(fp);
+         return NULL;
+       }
+
+      int i;
+      for (i = 0; i < colors; i++)
+       {
+         unsigned char r ,g, b, dummy;
+
+         rc = fread(&b, 1, 1, fp);
+         m_bytesRead++;
+         if (rc!=1)
+           {
+             delete [] colormap;
+             fclose(fp);
+             return NULL;
+           }
+
+         rc = fread(&g, 1, 1, fp); 
+         m_bytesRead++;
+         if (rc!=1)
+           {
+             delete [] colormap;
+             fclose(fp);
+             return NULL;
+           }
+
+         rc = fread(&r, 1, 1, fp); 
+         m_bytesRead++;
+         if (rc != 1)
+           {
+             delete [] colormap;
+             fclose(fp);
+             return NULL;
+           }
+
+         rc = fread(&dummy, 1, 1, fp); 
+         m_bytesRead++;
+         if (rc != 1)
+           {
+             delete [] colormap;
+             fclose(fp);
+             return NULL;
+           }
+
+         colormap[i].rgbRed=r;
+         colormap[i].rgbGreen=g;
+         colormap[i].rgbBlue=b;
+       }
+    }
+
+  if ((long)m_bytesRead > pixoff)
+    {
+      delete [] colormap;
+      fclose(fp);
+      return NULL;
+    }
+
+  while ((long)m_bytesRead < pixoff)
+    {
+      char dummy;
+      fread(&dummy,1,1,fp);
+      m_bytesRead++;
+    }
+
+  int w = bmWidth;
+  int h = bmHeight;
+
+  // set the output params
+  imagebits = (unsigned char*)malloc(w*h*3);
+  long row_size = w * 3;
+
+  if (imagebits != NULL) 
+    {
+      *width = w;
+      *height = h;
+      unsigned char* outbuf = imagebits;
+      long row = 0;
+      long rowOffset = 0;
+
+      if (compression == 0) // BI_RGB
+       {
+         // read rows in reverse order
+         for (row=bmHeight-1;row>=0;row--)
+           {
+             // which row are we working on?
+             rowOffset = (long unsigned)row*row_size;                                                
+
+             if (bmBitsPixel == 24)
+               {
+                 for (int col=0;col<w;col++)
+                   {
+                     long offset = col * 3;
+                     char pixel[3];
+
+                     if (fread((void*)(pixel),1,3,fp)==3)
+                       {
+                         // we swap red and blue here
+                         *(outbuf + rowOffset + offset + 0)=pixel[2];          // r
+                         *(outbuf + rowOffset + offset + 1)=pixel[1];          // g
+                         *(outbuf + rowOffset + offset + 2)=pixel[0];          // b
+                       }
+                   }
+                 m_bytesRead += row_size;
+
+                 // read DWORD padding
+                 while ((m_bytesRead-pixoff)&3)
+                   {
+                     char dummy;
+                     if (fread(&dummy,1,1,fp) != 1)
+                       {
+                         free(imagebits);
+                         fclose(fp);
+                         return NULL;
+                       }
+                     m_bytesRead++;
+                   }
+               }
+             else
+               {
+                 // pixels are packed as 1 , 4 or 8 bit vals. need to unpack them
+                 int bit_count = 0;
+                 unsigned long mask = (1 << bmBitsPixel) - 1;
+                 unsigned char inbyte = 0;
+
+                 for (int col=0;col<w;col++)
+                   {
+                     int pix = 0;
+
+                     // if we need another byte
+                     if (bit_count <= 0)
+                       {
+                         bit_count = 8;
+                         if (fread(&inbyte,1,1,fp) != 1)
+                           {
+                             free(imagebits);
+                             delete [] colormap;
+                             fclose(fp);
+                             return NULL;
+                           }
+                         m_bytesRead++;
+                       }
+
+                     // keep track of where we are in the bytes
+                     bit_count -= bmBitsPixel;
+                     pix = ( inbyte >> bit_count) & mask;
+
+                     // lookup the color from the colormap - stuff it in our buffer
+                     // swap red and blue
+                     *(outbuf + rowOffset + col * 3 + 2) = colormap[pix].rgbBlue;
+                     *(outbuf + rowOffset + col * 3 + 1) = colormap[pix].rgbGreen;
+                     *(outbuf + rowOffset + col * 3 + 0) = colormap[pix].rgbRed;
+                   }
+
+                 // read DWORD padding
+                 while ((m_bytesRead-pixoff)&3)
+                   {
+                     char dummy;
+                     if (fread(&dummy,1,1,fp)!=1)
+                       {
+                         free(imagebits);
+                         if (colormap)
+                           delete [] colormap;
+                         fclose(fp);
+                         return NULL;
+                       }
+                     m_bytesRead++;
+                   }
+               }
+           }
+       }
+      else
+       {
+         int i, x = 0;
+         unsigned char c, c1 = 0, *pp;
+         row = 0;
+         pp = outbuf + (bmHeight-1)*bmWidth*3;
+
+         if (bmBitsPixel == 8)
+           {
+             while (row < bmHeight)
+               {
+                 c = getc(fp);
+
+                 if (c)
+                   {
+                     // encoded mode
+                     c1 = getc(fp);
+                     for (i = 0; i < c; x++, i++)
+                       {
+                         *pp = colormap[c1].rgbRed; pp++;
+                         *pp = colormap[c1].rgbGreen; pp++;
+                         *pp = colormap[c1].rgbBlue; pp++;
+                       }
+                   }
+                 else
+                   {
+                     // c==0x00,  escape codes
+                     c = getc(fp);
+
+                     if (c == 0x00) // end of line
+                       {
+                         row++;
+                         x = 0;
+                         pp = outbuf + (bmHeight-row-1)*bmWidth*3;
+                       }
+                     else if (c == 0x01)
+                       break; // end of pic
+                     else if (c == 0x02) // delta
+                       {
+                         c = getc(fp);
+                         x += c;
+                         c = getc(fp);
+                         row += c;
+                         pp = outbuf + x*3 + (bmHeight-row-1)*bmWidth*3;
+                       }
+                     else // absolute mode
+                       {
+                         for (i = 0; i < c; x++, i++)
+                           {
+                             c1 = getc(fp);
+                             *pp = colormap[c1].rgbRed; pp++;
+                             *pp = colormap[c1].rgbGreen; pp++;
+                             *pp = colormap[c1].rgbBlue; pp++;
+                           }
+
+                         if (c & 1)
+                           getc(fp); // odd length run: read an extra pad byte
+                       }
+                   }
+               }
+           }
+         else if (bmBitsPixel == 4)
+           {
+             while (row < bmHeight)
+               {
+                 c = getc(fp);
+
+                 if (c)
+                   {
+                     // encoded mode
+                     c1 = getc(fp);
+                     for (i = 0; i < c; x++, i++)
+                       {
+                         *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbRed; pp++;
+                         *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbGreen; pp++;
+                         *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbBlue; pp++;
+                       }
+                   }
+                 else
+                   {
+                     // c==0x00,  escape codes
+                     c = getc(fp);
+
+                     if (c == 0x00) // end of line
+                       {
+                         row++;
+                         x = 0;
+                         pp = outbuf + (bmHeight-row-1)*bmWidth*3;
+                       }
+                     else if (c == 0x01)
+                       break; // end of pic
+                     else if (c == 0x02) // delta
+                       {
+                         c = getc(fp);
+                         x += c;
+                         c = getc(fp);
+                         row += c;
+                         pp = outbuf + x*3 + (bmHeight-row-1)*bmWidth*3;
+                       }
+                     else // absolute mode
+                       {
+                         for (i = 0; i < c; x++, i++)
+                           {
+                             if ((i&1) == 0)
+                               c1 = getc(fp);
+                             *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbRed; pp++;
+                             *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbGreen; pp++;
+                             *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbBlue; pp++;
+                           }
+
+                         if (((c&3) == 1) || ((c&3) == 2))
+                           getc(fp); // odd length run: read an extra pad byte
+                       }
+                   }
+               }
+           }
+       }
+
+      if (colormap)
+       delete [] colormap;
+
+      fclose(fp);
+    }
+
+  return imagebits;
+}
+
+void CPixMap::bmp_to_pixmap (const char* filename, GdkPixmap **pixmap, GdkBitmap **mask)
+{
+  guint16 width, height;
+  unsigned char *buf;
+  GdkWindow *window = GDK_ROOT_PARENT();
+  GdkColormap *colormap;
+  GdkGC* gc = gdk_gc_new (window);
+  int i, j;
+  GdkColor c;
+
+  *pixmap = *mask = NULL;
+  buf = load_bitmap_file (filename, &width, &height);
+  if (!buf)
+    return;
+
+  colormap = gdk_window_get_colormap (window);
+  *pixmap = gdk_pixmap_new (window, width, height, -1);
+
+  typedef struct
+  {
+    GdkColor c;
+    unsigned char *p;
+  } PAL;
+
+  GPtrArray* pal = g_ptr_array_new ();
+  GdkColor** col = (GdkColor**)malloc (sizeof (GdkColor*) * height * width);
+  guint32 k;
+
+  for (i = 0; i < height; i++)
+    for (j = 0; j < width; j++)
+    {
+      unsigned char* p = &buf[(i*width+j)*3];
+
+      for (k = 0; k < pal->len; k++)
+      {
+       PAL *pe = (PAL*)pal->pdata[k];
+       if ((pe->p[0] == p[0]) &&
+           (pe->p[1] == p[1]) &&
+           (pe->p[2] == p[2]))
+       {
+         col[(i*width+j)] = &pe->c;
+         break;
+       }
+      }
+
+      if (k == pal->len)
+      {
+       PAL *pe = (PAL*)malloc (sizeof (PAL));
+
+       pe->c.red = (gushort)(p[0]*0xFF);
+       pe->c.green = (gushort)(p[1]*0xFF);
+       pe->c.blue = (gushort)(p[2]*0xFF);
+       gdk_color_alloc (colormap, &pe->c);
+       col[(i*width+j)] = &pe->c;
+       pe->p = p;
+       g_ptr_array_add (pal, pe);
+      }
+    }
+
+  for (i = 0; i < height; i++)
+    for (j = 0; j < width; j++)
+    {
+      /*
+      c.red = (gushort)(buf[(i*width+j)*3]*0xFF);
+      c.green = (gushort)(buf[(i*width+j)*3+1]*0xFF);
+      c.blue = (gushort)(buf[(i*width+j)*3+2]*0xFF);
+      gdk_color_alloc (colormap, &c);
+      gdk_gc_set_foreground(gc, &c);
+      gdk_draw_point(*pixmap, gc, j, i);
+      */
+      gdk_gc_set_foreground(gc, col[(i*width+j)]);
+      gdk_draw_point(*pixmap, gc, j, i);
+    }
+
+  free (col);
+  for (k = 0; k < pal->len; k++)
+    free (pal->pdata[k]);
+  g_ptr_array_free (pal, TRUE);
+
+  gdk_gc_destroy (gc);
+  *mask = gdk_pixmap_new (window, width, height, 1);
+  gc = gdk_gc_new (*mask);
+
+  for (i = 0; i < height; i++)
+    for (j = 0; j < width; j++)
+    {
+      GdkColor mask_pattern;
+
+      // pink is transparent
+      if ((buf[(i*width+j)*3] == 0xff) &&
+         (buf[(i*width+j)*3+1] == 0x00) &&
+         (buf[(i*width+j)*3+2] == 0xff))
+       mask_pattern.pixel = 0;
+      else
+       mask_pattern.pixel = 1;
+
+      gdk_gc_set_foreground (gc, &mask_pattern);
+      // possible Win32 Gtk bug here
+//      gdk_draw_point (*mask, gc, j, i);
+      gdk_draw_line (*mask, gc, j, i, j + 1, i);
+    }
+
+  gdk_gc_destroy(gc);
+  free (buf);
+}
+
+void CPixMap::load_pixmap (const char* filename, GdkPixmap **gdkpixmap, GdkBitmap **mask)
+{
+  CString str;
+
+  str = g_strBitmapsPath;
+  str += filename;
+  bmp_to_pixmap (str.GetBuffer (),gdkpixmap, mask);
+
+  if (*gdkpixmap == NULL)
+  {
+    char *dummy[] = { "1 1 1 1", "  c None", " " };
+    *gdkpixmap = gdk_pixmap_create_from_xpm_d (GDK_ROOT_PARENT(), mask, NULL, dummy);
+  }
+}
+
+// Load a xpm file and return a pixmap widget.
+GtkWidget* CPixMap::new_pixmap (GtkWidget* widget, char* filename)
+{
+  GdkPixmap *gdkpixmap;
+  GdkBitmap *mask;
+  GtkWidget *pixmap;
+
+  load_pixmap (filename, &gdkpixmap, &mask);
+  pixmap = gtk_pixmap_new (gdkpixmap, mask);
+
+  gdk_pixmap_unref (gdkpixmap);
+  gdk_pixmap_unref (mask);
+
+ // g_FuncTable.m_pfnLoadBitmap( filename, &pixmap, &mask )
+
+  return pixmap;
+} 
+
+GtkWidget* CPixMap::pixmap_from_char(GtkWidget *window, gchar **xpm_data)
+{
+       GdkPixmap *pixmap;
+    GdkBitmap *mask;
+       GtkStyle *style;
+    GtkWidget *widget;
+
+       style = gtk_widget_get_style( window );
+    pixmap = gdk_pixmap_create_from_xpm_d( window->window,  &mask,
+                                           &style->bg[GTK_STATE_NORMAL],
+                                           (gchar **)xpm_data );
+
+       widget = gtk_pixmap_new( pixmap, mask );
+
+       return widget;
+}
diff --git a/contrib/pk3man/pixmap.h b/contrib/pk3man/pixmap.h
new file mode 100644 (file)
index 0000000..10acb38
--- /dev/null
@@ -0,0 +1,28 @@
+// PixMap.h: interface for the CPixMap class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_PIXMAP_H__5B978BDF_7DD1_4BA7_91B5_CCD49AA304AC__INCLUDED_)
+#define AFX_PIXMAP_H__5B978BDF_7DD1_4BA7_91B5_CCD49AA304AC__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "stdafx.h"
+
+class CPixMap  
+{
+public:
+       CPixMap();
+       virtual ~CPixMap();
+
+       static void load_pixmap (const char* filename, GdkPixmap **gdkpixmap, GdkBitmap **mask);
+       static void bmp_to_pixmap (const char* filename, GdkPixmap **pixmap, GdkBitmap **mask);
+       static unsigned char *load_bitmap_file (const char* filename, guint16* width, guint16* height);
+       static GtkWidget *new_pixmap (GtkWidget* parent, char* filename);
+       static GtkWidget* pixmap_from_char(GtkWidget *widget, gchar **xpm_data);
+
+};
+
+#endif // !defined(AFX_PIXMAP_H__5B978BDF_7DD1_4BA7_91B5_CCD49AA304AC__INCLUDED_)
diff --git a/contrib/pk3man/pk3man.cpp b/contrib/pk3man/pk3man.cpp
new file mode 100644 (file)
index 0000000..171462c
--- /dev/null
@@ -0,0 +1,188 @@
+//-----------------------------------------------------------------------------
+//
+// $LogFile$
+// $Revision: 1.7 $
+// $Author: ttimo $
+// $Date: 2002/05/02 14:41:21 $
+// $Log: pk3man.cpp,v $
+// Revision 1.7  2002/05/02 14:41:21  ttimo
+// fixes for 1.2.7
+//
+// Revision 1.6  2002/01/27 22:04:06  ttimo
+// fixes for linux ver
+//
+// Revision 1.5  2002/01/21 18:52:24  ttimo
+// fixes for 1.2 compile
+//
+// Revision 1.4  2001/01/24 22:37:19  mickey
+// Fixed projects for new radiant layout,
+// Changes all file/dir dialogs and messageboxs to use radiant interface.
+//
+// Revision 1.3  2000/12/22 16:53:28  mickey
+// fixed to support TA
+//
+// Revision 1.2  2000/11/01 14:05:01  lmz
+// Linux fixes
+//
+// Revision 1.1.1.1  2000/10/03 18:36:26  mickey
+// initial import
+//
+// Revision 1.3  2000/10/02 10:22:44  mickey
+// added rename dialog and some sanity checks for unsaved/modifed pk3's
+//
+// Revision 1.2  2000/10/01 20:35:40  mickey
+// beta stage
+//
+// Revision 1.1.1.1  2000/09/26 01:19:38  mickey
+// initial import of Gtk module
+//
+//
+// DESCRIPTION:
+// main plugin implementation
+// texturing tools for Q3Radiant
+//
+
+#include "stdafx.h"
+#include "mainwnd.h"
+
+// plugin interfaces
+static bool g_bShaderTableInitDone = false;
+_QERShadersTable g_ShadersTable;
+
+// Radiant function table
+_QERFuncTable_1 g_FuncTable;
+
+bool g_bEpairInitDone = false;
+#if 0 //mattn
+_QEREpairsTable         g_EpairTable;
+#endif
+
+// plugin name
+const char *PLUGIN_NAME = "Pk3Man";
+
+// commands in the menu
+static const char *PLUGIN_COMMANDS = "About...;-;Go...";
+
+// globals
+GtkWidget *g_pRadiantWnd=NULL;
+CMainWnd *g_pMainWnd=NULL;
+
+CString g_strAppPath;
+CString g_strBitmapsPath;
+CString g_strBasePath;
+CString g_strTempPath;
+CString g_strModPath;              // are we in TeamArena mode?
+
+#include "version.h"
+static const char *PLUGIN_ABOUT = "Pk3Man for Q3Radiant\n"
+               "http://pk3man.sourceforge.net\n\n"
+               "Gtk & Original Version\n"
+               "by Mike Jackman (mickey@planetquake.com)\n\n"
+               "Built against GtkRadiant " RADIANT_VERSION "\n"
+               __DATE__;
+
+extern "C" LPVOID WINAPI QERPlug_GetFuncTable()
+{
+       return &g_FuncTable;
+}
+
+extern "C" LPCSTR WINAPI QERPlug_Init(HMODULE hApp, GtkWidget* pMainWidget)
+{
+       g_pRadiantWnd = pMainWidget;
+       memset(&g_FuncTable, 0, sizeof(_QERFuncTable_1));
+       g_FuncTable.m_nSize = sizeof(_QERFuncTable_1);
+
+       return "Pk3Man for GTKRadiant";
+}
+
+extern "C" LPCSTR WINAPI QERPlug_GetName()
+{
+       return (char*)PLUGIN_NAME;
+}
+
+extern "C" LPCSTR WINAPI QERPlug_GetCommandList()
+{
+       return (char*)PLUGIN_COMMANDS;
+}
+
+char *TranslateString (char *buf)
+{
+       static  char    buf2[32768];
+       int             i, l;
+       char    *out;
+
+       l = strlen(buf);
+       out = buf2;
+       for (i=0 ; i<l ; i++)
+       {
+               if (buf[i] == '\n')
+               {
+                       *out++ = '\r';
+                       *out++ = '\n';
+               }
+               else
+                       *out++ = buf[i];
+       }
+
+       *out++ = 0;
+       return buf2;
+}
+
+/*
+extern "C" void Sys_Printf (char *text, ...)
+{
+       va_list argptr;
+       char    buf[32768];
+       char    *out;
+
+       va_start (argptr,text);
+       vsprintf (buf, text,argptr);
+       va_end (argptr);
+
+       //out = TranslateString (buf);
+
+       g_FuncTable.m_pfnSysMsg ( buf );
+}
+*/
+
+extern "C" void WINAPI QERPlug_Dispatch (LPCSTR p, vec3_t vMin, vec3_t vMax, bool bSingleBrush)
+{
+       if (!g_bShaderTableInitDone)
+       {
+               g_ShadersTable.m_nSize = sizeof (_QERShadersTable);
+               if ( g_FuncTable.m_pfnRequestInterface( QERShadersTable_GUID, static_cast<LPVOID>(&g_ShadersTable) ) )
+               {
+               g_bShaderTableInitDone = true;
+               }
+               else
+               {
+               Sys_Printf("Pk3Man plugin: _QERShadersTable interface request failed\n");
+               return;
+               }
+       }
+
+#if 0 //mattn
+       if (!g_bEpairInitDone)
+       {
+               g_EpairTable.m_nSize = sizeof(_QEREpairsTable);
+               if ( g_FuncTable.m_pfnRequestInterface( QEREpairsTable_GUID, static_cast<LPVOID>(&g_EpairTable) ) )
+                       g_bEpairInitDone = true;
+               else
+               {
+                       Sys_Printf("Pk3Man plugin: _QEREpairsTable interface request failed\n");
+                       return;
+               }
+       }
+#endif
+
+       if (!strcmp(p, "About..."))
+       {
+               g_FuncTable.m_pfnMessageBox(g_pRadiantWnd,PLUGIN_ABOUT,"About ...",MB_OK, NULL);
+       }
+       else if (!strcmp(p, "Go..."))
+       {
+               Sys_Printf ("Pk3Man starting ...\n");
+               g_pMainWnd = new CMainWnd ();
+               g_pMainWnd->Create (g_pRadiantWnd);
+       }
+}
diff --git a/contrib/pk3man/pk3man.def b/contrib/pk3man/pk3man.def
new file mode 100644 (file)
index 0000000..3eebeb9
--- /dev/null
@@ -0,0 +1,12 @@
+; Pk3Man.def : Declares the module parameters for the DLL.
+
+LIBRARY      "Pk3Man"
+DESCRIPTION  'Pk3Man Windows Dynamic Link Library'
+
+EXPORTS
+    ; Explicit exports can go here
+       QERPlug_Init @1
+       QERPlug_GetName @2
+       QERPlug_GetCommandList @3
+       QERPlug_Dispatch @4
+       QERPlug_GetFuncTable @5
diff --git a/contrib/pk3man/pk3man.exclude b/contrib/pk3man/pk3man.exclude
new file mode 100644 (file)
index 0000000..87adfbf
--- /dev/null
@@ -0,0 +1,32 @@
+// pk3man exclusion file
+// (c) Mike Jackman 2000
+// 
+// All files listed below will
+// be excluded by the wizzard
+
+
+pak?.pk3
+
+scripts/base_door.shader
+scripts/base_floor.shader
+scripts/base_light.shader
+scripts/base_object.shader
+scripts/base_support.shader
+scripts/base_trim.shader
+scripts/base_wall.shader
+scripts/common.shader
+scripts/ctf.shader
+scripts/gothic_block.shader
+scripts/gothic_button.shader
+scripts/gothic_door.shader
+scripts/gothic_floor.shader
+scripts/gothic_light.shader
+scripts/gothic_trim.shader
+scripts/gothic_wall.shader
+scripts/liquid.shader
+scripts/organics.shader
+scripts/sfx.shader
+scripts/skin.shader
+scripts/sky.shader
+
+
diff --git a/contrib/pk3man/pk3man.vcproj b/contrib/pk3man/pk3man.vcproj
new file mode 100644 (file)
index 0000000..0ceac05
--- /dev/null
@@ -0,0 +1,101 @@
+<?xml version="1.0" ?><VisualStudioProject Name="pk3man" ProjectGUID="{65D02375-63EE-4A8A-9F8E-504B1D5A1D02}" ProjectType="Visual C++" RootNamespace="pk3mank" Version="8.00">\r
+       <Platforms>\r
+               <Platform Name="Win32"/>\r
+       </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
+       <Configurations>\r
+               <Configuration CharacterSet="2" ConfigurationType="1" IntermediateDirectory="$(ConfigurationName)" Name="Debug|Win32" OutputDirectory="$(SolutionDir)$(ConfigurationName)">\r
+                       <Tool Name="VCPreBuildEventTool"/>\r
+                       <Tool Name="VCCustomBuildTool"/>\r
+                       <Tool Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool Name="VCMIDLTool"/>\r
+                       <Tool AdditionalIncludeDirectories="&quot;$(SolutionDir)\include&quot;;&quot;$(SolutionDir)\libs&quot;;&quot;$(SolutionDir)\..\STLPort\stlport&quot;;&quot;$(SolutionDir)\..\gtk2\include&quot;;&quot;$(SolutionDir)\..\gtk2\include\glib-2.0&quot;;&quot;$(SolutionDir)\..\gtk2\lib\glib-2.0\include&quot;;&quot;$(SolutionDir)\..\libxml2\include&quot;" BasicRuntimeChecks="3" DebugInformationFormat="4" Detect64BitPortabilityProblems="true" DisableSpecificWarnings="4996;4244;4267" MinimalRebuild="true" Name="VCCLCompilerTool" Optimization="0" PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS" RuntimeLibrary="3" WarningLevel="3"/>\r
+                       <Tool Name="VCManagedResourceCompilerTool"/>\r
+                       <Tool Name="VCResourceCompilerTool"/>\r
+                       <Tool Name="VCPreLinkEventTool"/>\r
+                       <Tool GenerateDebugInformation="true" Name="VCLinkerTool" TargetMachine="1"/>\r
+                       <Tool Name="VCALinkTool"/>\r
+                       <Tool Name="VCManifestTool"/>\r
+                       <Tool Name="VCXDCMakeTool"/>\r
+                       <Tool Name="VCBscMakeTool"/>\r
+                       <Tool Name="VCFxCopTool"/>\r
+                       <Tool Name="VCAppVerifierTool"/>\r
+                       <Tool Name="VCWebDeploymentTool"/>\r
+                       <Tool Name="VCPostBuildEventTool"/>\r
+               </Configuration>\r
+               <Configuration CharacterSet="2" ConfigurationType="1" IntermediateDirectory="$(ConfigurationName)" Name="Release|Win32" OutputDirectory="$(SolutionDir)$(ConfigurationName)" WholeProgramOptimization="1">\r
+                       <Tool Name="VCPreBuildEventTool"/>\r
+                       <Tool Name="VCCustomBuildTool"/>\r
+                       <Tool Name="VCXMLDataGeneratorTool"/>\r
+                       <Tool Name="VCWebServiceProxyGeneratorTool"/>\r
+                       <Tool Name="VCMIDLTool"/>\r
+                       <Tool AdditionalIncludeDirectories="&quot;$(SolutionDir)\include&quot;;&quot;$(SolutionDir)\libs&quot;;&quot;$(SolutionDir)\..\STLPort\stlport&quot;;&quot;$(SolutionDir)\..\gtk2\include&quot;;&quot;$(SolutionDir)\..\gtk2\include\glib-2.0&quot;;&quot;$(SolutionDir)\..\gtk2\lib\glib-2.0\include&quot;;&quot;$(SolutionDir)\..\libxml2\include&quot;" DebugInformationFormat="3" Detect64BitPortabilityProblems="true" DisableSpecificWarnings="4996;4244;4267" Name="VCCLCompilerTool" PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS" RuntimeLibrary="2" WarningLevel="3"/>\r
+                       <Tool Name="VCManagedResourceCompilerTool"/>\r
+                       <Tool Name="VCResourceCompilerTool"/>\r
+                       <Tool Name="VCPreLinkEventTool"/>\r
+                       <Tool EnableCOMDATFolding="2" GenerateDebugInformation="true" Name="VCLinkerTool" OptimizeReferences="2" TargetMachine="1"/>\r
+                       <Tool Name="VCALinkTool"/>\r
+                       <Tool Name="VCManifestTool"/>\r
+                       <Tool Name="VCXDCMakeTool"/>\r
+                       <Tool Name="VCBscMakeTool"/>\r
+                       <Tool Name="VCFxCopTool"/>\r
+                       <Tool Name="VCAppVerifierTool"/>\r
+                       <Tool Name="VCWebDeploymentTool"/>\r
+                       <Tool Name="VCPostBuildEventTool"/>\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <Filter Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" Name="Source Files">\r
+                       <File RelativePath=".\mainwnd.cpp">\r
+                       </File>\r
+                       <File RelativePath=".\memfile.cpp">\r
+                       </File>\r
+                       <File RelativePath=".\pak.cpp">\r
+                       </File>\r
+                       <File RelativePath=".\pixmap.cpp">\r
+                       </File>\r
+                       <File RelativePath=".\pk3man.cpp">\r
+                       </File>\r
+                       <File RelativePath=".\pk3man.def">\r
+                       </File>\r
+                       <File RelativePath=".\renamedlg.cpp">\r
+                       </File>\r
+                       <File RelativePath=".\stdafx.cpp">\r
+                       </File>\r
+                       <File RelativePath=".\tree.cpp">\r
+                       </File>\r
+                       <File RelativePath=".\wild.cpp">\r
+                       </File>\r
+               </Filter>\r
+               <Filter Filter="h;hpp;hxx;hm;inl" Name="Header Files">\r
+                       <File RelativePath=".\mainwnd.h">\r
+                       </File>\r
+                       <File RelativePath=".\md3.h">\r
+                       </File>\r
+                       <File RelativePath=".\memfile.h">\r
+                       </File>\r
+                       <File RelativePath=".\pak.h">\r
+                       </File>\r
+                       <File RelativePath=".\pixmap.h">\r
+                       </File>\r
+                       <File RelativePath=".\pk3str.h">\r
+                       </File>\r
+                       <File RelativePath=".\renamedlg.h">\r
+                       </File>\r
+                       <File RelativePath=".\stdafx.h">\r
+                       </File>\r
+                       <File RelativePath=".\tree.h">\r
+                       </File>\r
+                       <File RelativePath=".\wild.h">\r
+                       </File>\r
+               </Filter>\r
+               <Filter Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" Name="Resource Files">\r
+               </Filter>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>
\ No newline at end of file
diff --git a/contrib/pk3man/pk3man_readme.txt b/contrib/pk3man/pk3man_readme.txt
new file mode 100644 (file)
index 0000000..90da2f6
--- /dev/null
@@ -0,0 +1,46 @@
+Pk3Man
+------
+
+Pk3Man is a plugin for Q3Radiant (GtkEdition).
+It allows the creation and editing of Q3 Pk3 files
+from within the Q3Radiant Editor.
+
+It does NOT operate in the same way as WinZip so ill
+try to documented the differences here. Please read these
+before emailing me with suggestions or problems.
+
+***************************************************************
+
+1. Any modified or newly created Pk3 is only committed to disk,
+   when you save.
+
+2. Pk3Man uses your current base folder set in Q3Radiant (ie. BaseQ3)
+   and adds files using there current path relative to this. This means
+   that when you have finished your map, you just add the required files,
+   and their paths are automatically correct (if they were in the correct place for
+   Q3 to start with)
+
+4. You can change the stored path of a file using the rename option. Rename
+   the file with its full new relative path and name.
+
+5. The wizzard will scan a .map file and add any textures/sounds/env maps e.t.c that
+   are referenced, except those in the exclusion list.
+
+6. files that have been added (and not saved) are shown with an appending * in the
+   statusbar when selected.
+
+7. The exclusion list applies to Pk3's and to individual files. eg 'pak?.pk3' would
+   eliminate all ID pk3's, and 'textures/mickey/*.tga' would eliminate all tga's in
+   a sub folder of textures called 'mickey'
+
+
+************************************************************
+
+Please email and bugs/suggestions to me here : mickey@planetquake.com
+
+
+------------------------------------------------------------------------
+Remember this is a beta. I hold no responsibility for any damage done to
+files on your computer due to the action of this plugin.
+-------------------------------------------------------------------------
+
diff --git a/contrib/pk3man/pk3str.h b/contrib/pk3man/pk3str.h
new file mode 100644 (file)
index 0000000..11d7759
--- /dev/null
@@ -0,0 +1,395 @@
+#ifndef __STR__
+#define __STR__
+//
+// class Str
+// loose replacement for CString from MFC
+//
+//#include "cmdlib.h"
+//#include <glib.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifdef WIN32
+#define strcasecmp strcmpi
+#endif
+
+//char* __StrDup(char* pStr);
+//char* __StrDup(const char* pStr);
+
+#define __StrDup strdup
+
+#ifdef __linux__
+#define strcmpi strcasecmp
+#define stricmp strcasecmp
+#define strnicmp strncasecmp
+
+inline char* strlwr(char* string)
+{
+       char *cp;
+       for (cp = string; *cp; ++cp)
+       {
+               if ('A' <= *cp && *cp <= 'Z')
+               *cp += 'a' - 'A';
+       }
+
+       return string;
+}
+
+inline char* strupr(char* string)
+{
+       char *cp;
+       for (cp = string; *cp; ++cp)
+       {
+               if ('a' <= *cp && *cp <= 'z')
+               *cp += 'A' - 'a';
+       }
+
+       return string;
+}
+#endif
+
+static char *g_pStrWork = NULL;
+
+class Str
+{
+protected:
+       bool m_bIgnoreCase;
+       char *m_pStr;
+
+public:
+       Str()
+       {
+               m_bIgnoreCase = true;
+               m_pStr = new char[1];
+               m_pStr[0] = '\0';
+       }
+
+       Str(char *p)
+       {
+               m_bIgnoreCase = true;
+               m_pStr = __StrDup(p);
+       }
+
+       Str(const char *p)
+       {
+               m_bIgnoreCase = true;
+               m_pStr = __StrDup(p);
+       }
+
+       Str(const char c)
+       {
+               m_bIgnoreCase = true;
+               m_pStr = new char[2];
+               m_pStr[0] = c;
+               m_pStr[1] = '\0';
+       }
+
+       void Deallocate()
+       {
+               delete []m_pStr;
+               m_pStr = NULL;
+       }
+
+       void Allocate(int n)
+       {
+               Deallocate();
+               m_pStr = new char[n];
+       }
+
+       const char* GetBuffer()
+       {
+               return m_pStr;
+       }
+
+       void MakeEmpty()
+       {
+               Deallocate();
+               m_pStr = __StrDup("");
+       }
+
+       ~Str()
+       {
+               Deallocate();
+               delete []g_pStrWork;
+               g_pStrWork = NULL;
+       }
+
+       void MakeLower()
+       {
+               if (m_pStr)
+               {
+                       strlwr(m_pStr);
+               }
+       }
+
+       void MakeUpper()
+       {
+               if (m_pStr)
+               {
+                       strupr(m_pStr);
+               }
+       }
+
+       void TrimRight()
+       {
+               char* lpsz = m_pStr;
+               char* lpszLast = NULL;
+               while (*lpsz != '\0')
+               {
+                       if (isspace(*lpsz))
+                       {
+                               if (lpszLast == NULL)
+                                       lpszLast = lpsz;
+                       }
+                       else
+                               lpszLast = NULL;
+                               lpsz++;
+                       }
+
+                       if (lpszLast != NULL)
+                       {
+                               // truncate at trailing space start
+                               *lpszLast = '\0';
+                       }
+       }
+
+       void TrimLeft()
+       {
+               // find first non-space character
+               char* lpsz = m_pStr;
+               while (isspace(*lpsz))
+                       lpsz++;
+
+               // fix up data and length
+               int nDataLength = GetLength() - (lpsz - m_pStr);
+               memmove(m_pStr, lpsz, (nDataLength+1));
+       }
+
+       int Find(const char *p)
+       {
+               char *pf = strstr(m_pStr, p);
+               return (pf) ? (pf - m_pStr) : -1;
+       }
+
+       // search starting at a given offset
+       int Find(const char *p, int offset)
+       {
+               char *pf = strstr(m_pStr+offset, p);
+               return (pf) ? (pf - m_pStr) : -1;
+       }
+
+       int Find(const char ch)
+       {
+               char *pf = strchr (m_pStr, ch);
+               return (pf) ? (pf - m_pStr) : -1;
+       }
+
+       int ReverseFind(const char ch)
+       {
+               char *pf = strrchr(m_pStr, ch);
+               return (pf) ? (pf - m_pStr) : -1;
+       }
+
+       int CompareNoCase (const char* str) const
+       {
+               return strcasecmp (m_pStr, str);
+       }
+
+       int GetLength()
+       {
+               return (m_pStr) ? strlen(m_pStr) : 0;
+       }
+
+       const char* Left(int n)
+       {
+               delete []g_pStrWork;
+               if (n > 0)
+               {
+                       g_pStrWork = new char[n+1];
+                       strncpy(g_pStrWork, m_pStr, n);
+                       g_pStrWork[n] = '\0';
+               }
+               else
+               {
+                       g_pStrWork = "";
+                       g_pStrWork = new char[1];
+                       g_pStrWork[0] = '\0';
+               }
+               return g_pStrWork;
+       }
+
+       const char* Right(int n)
+       {
+               delete []g_pStrWork;
+               if (n > 0)
+               {
+                       g_pStrWork = new char[n+1];
+                       int nStart = GetLength() - n;
+                       strncpy(g_pStrWork, &m_pStr[nStart], n);
+                       g_pStrWork[n] = '\0';
+               }
+               else
+               {
+                       g_pStrWork = new char[1];
+                       g_pStrWork[0] = '\0';
+               }
+               return g_pStrWork;
+       }
+
+       const char* Mid(int nFirst) const
+       {
+               return Mid(nFirst, strlen (m_pStr) - nFirst);
+       }
+
+       const char* Mid(int first, int n) const
+       {
+               delete []g_pStrWork;
+               if (n > 0)
+               {
+                       g_pStrWork = new char[n+1];
+                       strncpy(g_pStrWork, m_pStr+first, n);
+                       g_pStrWork[n] = '\0';
+               }
+               else
+               {
+                       g_pStrWork = "";
+                       g_pStrWork = new char[1];
+                       g_pStrWork[0] = '\0';
+               }
+               return g_pStrWork;
+       }
+
+#ifdef __G_LIB_H__
+       void Format(const char* fmt, ...)
+       {
+               va_list args;
+               char *buffer;
+
+               va_start (args, fmt);
+               buffer = g_strdup_vprintf (fmt, args);
+               va_end (args);
+
+               delete[] m_pStr;
+               m_pStr = __StrDup(buffer);
+               g_free (buffer);
+       }
+#else
+       void Format(const char* fmt, ...)
+       {
+               va_list args;
+               m_pStr = new char[1024];
+
+               va_start (args, fmt);
+               vsprintf (m_pStr, fmt, args);
+               va_end (args);
+       }
+#endif
+
+       void SetAt(int n, char ch)
+       {
+               if (n >= 0 && n < GetLength ())
+                       m_pStr[n] = ch;
+       }
+
+       // NOTE: unlike CString, this looses the pointer
+       void ReleaseBuffer(int n = -1)
+       {
+               if (n == -1)
+               n = GetLength ();
+
+               char* tmp = m_pStr;
+               tmp[n] = '\0';
+               m_pStr = __StrDup(tmp);
+               delete []tmp;
+       }
+
+       char* GetBufferSetLength(int n)
+       {
+               if (n < 0)
+                       n = 0;
+
+               char *p = new char[n+1];
+               strncpy (p, m_pStr, n);
+               p[n] = '\0';
+               delete []m_pStr;
+               m_pStr = p;
+               return m_pStr;
+       }
+
+       //  char& operator *() { return *m_pStr; }
+       //  char& operator *() const { return *const_cast<Str*>(this)->m_pStr; }
+       operator void*() { return m_pStr; }
+       operator char*() { return m_pStr; }
+       operator const char*(){ return reinterpret_cast<const char*>(m_pStr); }
+       operator unsigned char*() { return reinterpret_cast<unsigned char*>(m_pStr); }
+       operator const unsigned char*() { return reinterpret_cast<const unsigned char*>(m_pStr); }
+       Str& operator =(const Str& rhs)
+       {
+               if (&rhs != this)
+               {
+                       delete[] m_pStr;
+                       m_pStr = __StrDup(rhs.m_pStr);
+               }
+               return *this;
+       }
+
+       Str& operator =(const char* pStr)
+       {
+               if (m_pStr != pStr)
+               {
+                       delete[] m_pStr;
+                       m_pStr = __StrDup(pStr);
+               }
+               return *this;
+       }
+
+       Str& operator +=(const char ch)
+       {
+               int len = GetLength ();
+               char *p = new char[len + 1 + 1];
+
+               if (m_pStr)
+               {
+                       strcpy(p, m_pStr);
+                       delete[] m_pStr;
+               }
+
+               m_pStr = p;
+               m_pStr[len] = ch;
+               m_pStr[len+1] = '\0';
+
+               return *this;
+       }
+
+       Str& operator +=(const char *pStr)
+       {
+               if (pStr)
+               {
+                       if (m_pStr)
+                       {
+                               char *p = new char[strlen(m_pStr) + strlen(pStr) + 1];
+                               strcpy(p, m_pStr);
+                               strcat(p, pStr);
+                               delete[] m_pStr;
+                               m_pStr = p;
+                       }
+                       else
+                       {
+                               m_pStr = __StrDup(pStr);
+                       }
+               }
+               return *this;
+       }
+
+       bool operator ==(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) == 0 : strcmp(m_pStr, rhs.m_pStr) == 0; }
+       bool operator ==(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) == 0 : strcmp(m_pStr, pStr) == 0; }
+       bool operator ==(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) == 0 : strcmp(m_pStr, pStr) == 0; }
+       bool operator !=(Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) != 0 : strcmp(m_pStr, rhs.m_pStr) != 0; }
+       bool operator !=(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) != 0 : strcmp(m_pStr, pStr) != 0; }
+       bool operator !=(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) != 0 : strcmp(m_pStr, pStr) != 0; }
+       char& operator [](int nIndex) { return m_pStr[nIndex]; }
+       char& operator [](int nIndex) const { return m_pStr[nIndex]; }
+       const char GetAt (int nIndex) { return m_pStr[nIndex]; }
+};
+
+#endif
diff --git a/contrib/pk3man/renamedlg.cpp b/contrib/pk3man/renamedlg.cpp
new file mode 100644 (file)
index 0000000..9851e44
--- /dev/null
@@ -0,0 +1,113 @@
+// RenameDlg.cpp: implementation of the CRenameDlg class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "renamedlg.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+static void rename_dialog_button_callback (GtkWidget *widget, gpointer data)
+{
+       GtkWidget *parent;
+       int *loop, *ret;
+
+       parent = gtk_widget_get_toplevel (widget);
+       loop = (int*)gtk_object_get_data (GTK_OBJECT (parent), "loop");
+       ret = (int*)gtk_object_get_data (GTK_OBJECT (parent), "ret");
+
+       *loop = 0;
+       *ret = (int)data;
+}
+
+static gint rename_dialog_delete_callback (GtkWidget *widget, GdkEvent* event, gpointer data)
+{
+       int *loop;
+
+       gtk_widget_hide (widget);
+       loop = (int*)gtk_object_get_data (GTK_OBJECT (widget), "loop");
+       *loop = 0;
+
+       return TRUE;
+}
+
+CRenameDlg::CRenameDlg()
+{
+       m_Name="foo";
+}
+
+CRenameDlg::~CRenameDlg()
+{
+
+}
+
+int CRenameDlg::DoModal()
+{
+       GtkWidget *window, *w, *vbox, *hbox, *edit;
+       int ret, loop = 1;
+       char *lpCaption="Rename File";
+
+       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+       gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+                                       GTK_SIGNAL_FUNC (rename_dialog_delete_callback), NULL);
+       gtk_signal_connect (GTK_OBJECT (window), "destroy",
+                                       GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
+       gtk_window_set_title (GTK_WINDOW (window), lpCaption);
+       gtk_container_border_width (GTK_CONTAINER (window), 10);
+       gtk_object_set_data (GTK_OBJECT (window), "loop", &loop);
+       gtk_object_set_data (GTK_OBJECT (window), "ret", &ret);
+       gtk_widget_realize (window);
+
+       vbox = gtk_vbox_new (FALSE, 10);
+       gtk_container_add (GTK_CONTAINER (window), vbox);
+       gtk_widget_show (vbox);
+
+       edit = gtk_entry_new ();
+       gtk_entry_set_text(GTK_ENTRY(edit),m_Name.c_str());
+       gtk_box_pack_start (GTK_BOX (vbox), edit, FALSE, FALSE, 2);
+       gtk_widget_show (edit);
+
+       w = gtk_hseparator_new ();
+       gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 2);
+       gtk_widget_show (w);
+
+       hbox = gtk_hbox_new (FALSE, 10);
+       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 2);
+       gtk_widget_show (hbox);
+
+       // buttons
+
+       w = gtk_button_new_with_label ("Ok");
+       gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
+       gtk_signal_connect (GTK_OBJECT (w), "clicked",
+                                       GTK_SIGNAL_FUNC (rename_dialog_button_callback), GINT_TO_POINTER (IDOK));
+       GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);
+       gtk_widget_grab_default (w);
+       gtk_widget_show (w);
+
+       w = gtk_button_new_with_label ("Cancel");
+       gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0);
+       gtk_signal_connect (GTK_OBJECT (w), "clicked",
+                                       GTK_SIGNAL_FUNC (rename_dialog_button_callback), GINT_TO_POINTER (IDCANCEL));
+       gtk_widget_show (w);
+       ret = IDCANCEL;
+
+       // show it
+
+       gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
+       gtk_widget_show (window);
+       gtk_grab_add (window);
+
+       while (loop)
+               gtk_main_iteration ();
+
+       m_Name=gtk_entry_get_text(GTK_ENTRY(edit));
+
+       gtk_grab_remove (window);
+       gtk_widget_destroy (window);
+
+       return ret;
+
+}
diff --git a/contrib/pk3man/renamedlg.h b/contrib/pk3man/renamedlg.h
new file mode 100644 (file)
index 0000000..d76bb9a
--- /dev/null
@@ -0,0 +1,25 @@
+// RenameDlg.h: interface for the CRenameDlg class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_RENAMEDLG_H__6BF675B2_311E_42EE_A926_C52EA685EA75__INCLUDED_)
+#define AFX_RENAMEDLG_H__6BF675B2_311E_42EE_A926_C52EA685EA75__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include <string>
+
+class CRenameDlg
+{
+public:
+       CRenameDlg();
+       virtual ~CRenameDlg();
+
+       std::string m_Name;
+
+       int DoModal();
+};
+
+#endif // !defined(AFX_RENAMEDLG_H__6BF675B2_311E_42EE_A926_C52EA685EA75__INCLUDED_)
diff --git a/contrib/pk3man/stdafx.cpp b/contrib/pk3man/stdafx.cpp
new file mode 100644 (file)
index 0000000..0665ded
--- /dev/null
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+//     pk3man.pch will be the pre-compiled header
+//     stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/contrib/pk3man/stdafx.h b/contrib/pk3man/stdafx.h
new file mode 100644 (file)
index 0000000..ff7ff7e
--- /dev/null
@@ -0,0 +1,141 @@
+// stdafx.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+#if !defined(AFX_STDAFX_H__214D7491_03C8_444D_AAEB_73A8A21B84CB__INCLUDED_)
+#define AFX_STDAFX_H__214D7491_03C8_444D_AAEB_73A8A21B84CB__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#define GTK_ENABLE_BROKEN
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "pk3str.h"
+#include "pixmap.h"
+
+#ifdef __linux__
+
+#include <GL/glx.h>
+
+typedef void* HMODULE;
+typedef void* LPVOID;
+typedef int BOOL;
+typedef char* LPCSTR;
+
+#define MB_OK                       0x00000000L
+#define MB_OKCANCEL                 0x00000001L
+#define MB_ABORTRETRYIGNORE         0x00000002L
+#define MB_YESNOCANCEL              0x00000003L
+#define MB_YESNO                    0x00000004L
+#define MB_RETRYCANCEL              0x00000005L
+
+
+#define MB_ICONHAND                 0x00000010L
+#define MB_ICONQUESTION             0x00000020L
+#define MB_ICONEXCLAMATION          0x00000030L
+#define MB_ICONASTERISK             0x00000040L
+
+#define MB_USERICON                 0x00000080L
+#define MB_ICONWARNING              MB_ICONEXCLAMATION
+#define MB_ICONERROR                MB_ICONHAND
+#define MB_ICONINFORMATION          MB_ICONASTERISK
+#define MB_ICONSTOP                 MB_ICONHAND
+
+#define MB_TYPEMASK                 0x0000000FL
+#define MB_ICONMASK                 0x000000F0L
+#define MB_DEFMASK                  0x00000F00L
+#define MB_MODEMASK                 0x00003000L
+#define MB_MISCMASK                 0x0000C000L
+
+#define IDOK                1
+#define IDCANCEL            2
+#define IDABORT             3
+#define IDRETRY             4
+#define IDIGNORE            5
+#define IDYES               6
+#define IDNO                7
+
+#define WINAPI
+
+#ifndef GUID_DEFINED
+#define GUID_DEFINED
+typedef struct _GUID
+{
+  unsigned long  Data1;
+  unsigned short Data2;
+  unsigned short Data3;
+  unsigned char  Data4[8];
+} GUID;
+#endif
+
+#if defined(__cplusplus)
+#ifndef _REFGUID_DEFINED
+#define _REFGUID_DEFINED
+#define REFGUID             const GUID &
+#endif // !_REFGUID_DEFINED
+#endif
+
+typedef struct tagRECT
+{
+       long    left;
+       long    top;
+       long    right;
+       long    bottom;
+} RECT, *PRECT, *LPRECT;
+
+#endif // __linux__
+
+#include "qerplugin.h"
+#include "igl.h"
+#include "iselectedface.h"
+#include "isurfaceplugin.h"
+#include "ishaders.h"
+#if 0 //mattn
+#include "iepairs.h"
+#endif
+
+extern _QERFuncTable_1  g_FuncTable;
+extern _QERShadersTable g_ShadersTable;
+#if 0 //mattn
+extern _QEREpairsTable  g_EpairTable;
+#endif
+#define Sys_Printf g_FuncTable.m_pfnSysPrintf
+#define Sys_FPrintf g_FuncTable.m_pfnSysFPrintf
+
+#define CString Str
+extern CString g_strBitmapsPath;
+extern CString g_strBasePath;
+extern CString g_strTempPath;
+extern CString g_strAppPath;
+extern CString g_strModPath;
+
+
+//extern int DoMessageBox (const char* lpText, const char* lpCaption, guint32 uType);
+
+#define ID_FILE_OPEN   10000
+#define ID_FILE_SAVE   10001
+#define ID_FILE_NEW            10002
+#define ID_WIZARD              10003
+#define ID_VIEW                        10004
+#define ID_EXTRACT             10005
+#define ID_ADD                 10006
+#define ID_RENAME              10007
+#define ID_DELETE              10008
+#define ID_SPARE               10009
+
+#ifndef __linux__
+#pragma warning(disable : 4786)
+#endif
+
+// TODO: reference additional headers your program requires here
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__214D7491_03C8_444D_AAEB_73A8A21B84CB__INCLUDED_)
diff --git a/contrib/pk3man/tree.cpp b/contrib/pk3man/tree.cpp
new file mode 100644 (file)
index 0000000..c386115
--- /dev/null
@@ -0,0 +1,271 @@
+// tree.cpp: implementation of the CTree class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "tree.h"
+#include <string>
+#include "mainwnd.h"
+
+extern CMainWnd *g_pMainWnd;
+
+
+static void button_release (GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+       if (event->button==3)
+               g_pMainWnd->HandleDrop();
+}
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CTree::CTree()
+{
+       m_Tree=NULL;
+       m_Root=NULL;
+
+}
+
+CTree::~CTree()
+{
+
+}
+
+void CTree::Init(GtkWidget *win)
+{
+       m_pMainWnd=win;
+
+       // create the tree
+       m_Tree=gtk_tree_new();
+
+       // Add tree to passed scroll window
+       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(win),(GtkWidget*)m_Tree);
+
+       // Show it
+       gtk_widget_show(m_Tree);
+
+       // connect signal
+       gtk_signal_connect (GTK_OBJECT(m_Tree), "select_child",
+                               GTK_SIGNAL_FUNC(cb_select_child), m_Tree);
+
+       // create the root item
+       GtkWidget *item=gtk_tree_item_new_with_label("root");
+       gtk_tree_append(GTK_TREE(m_Tree),item);
+       gtk_widget_show(item);
+
+       gtk_signal_connect (GTK_OBJECT (item), "button_release_event",GTK_SIGNAL_FUNC (button_release), NULL);
+
+       m_Root=gtk_tree_new();
+       gtk_tree_item_set_subtree(GTK_TREE_ITEM(item),m_Root);
+       gtk_tree_item_expand(GTK_TREE_ITEM(item));
+
+
+       // connect signal
+       gtk_signal_connect (GTK_OBJECT(m_Root), "select_child",
+                               GTK_SIGNAL_FUNC(cb_select_child), m_Tree);
+
+       // ok were done
+       return;
+}
+
+void CTree::Clear()
+{
+       gtk_widget_destroy(m_Tree);
+       Init(m_pMainWnd);
+}
+
+void CTree::AddPath(const char *buff)
+{
+       Str path(buff);
+
+       // convert '\' to '/'
+       for (int c=0 ; c<path.GetLength() ; c++)
+       {
+               if (path.GetAt(c)=='\\')
+                       path.SetAt(c,'/');
+       }
+
+       if (path[0]=='/')
+               path=path.Mid(1);
+
+       // lets tokenize it first
+       if (path.GetAt(path.GetLength()-1)=='/')
+       {
+               // its just a folder path, no file
+               return;
+       }
+
+       GtkWidget *node=m_Root;
+
+       long pos=path.Find('/');
+       while (pos!=-1)
+       {
+               Str folder=path.Left(pos);
+               path=path.Mid(pos+1);
+
+               // add a folder, or retrieve its node if it already exists
+               node=AddFolder(folder.GetBuffer(),node);
+
+               pos=path.Find('/');
+       }
+
+       // add the filename to the final nested node
+       AddFile(path.GetBuffer(),node);
+}
+
+
+void CTree::AddFile(const char *buff, GtkWidget *node)
+{
+       Str file(buff);
+
+       if (node==NULL)
+               node=m_Root;
+
+       GtkWidget *item=gtk_tree_item_new_with_label(buff);
+       gtk_tree_append(GTK_TREE(node),item);
+       gtk_widget_show(item);
+
+       gtk_widget_set_name(item,file);
+
+       //      gtk_signal_connect (GTK_OBJECT(item), "select_child",
+       //                      GTK_SIGNAL_FUNC(cb_select_child), item);
+
+       gtk_signal_connect (GTK_OBJECT (item), "button_release_event",GTK_SIGNAL_FUNC (button_release), NULL);
+
+
+       // a file is the last item in the tree so no tree is needed
+}
+
+GtkWidget* CTree::AddFolder(const char *buff,GtkWidget *node)
+{
+       Str folder(buff);
+
+       if (node==NULL)
+               node=m_Root;
+
+       // search the node's siblings for the folder
+       GList *children = gtk_container_children (GTK_CONTAINER (node));
+    while (children)
+       {
+               GtkTreeItem *tree_item=(GTK_TREE_ITEM (children->data));
+
+               // check item for equality with the folder
+               // and weather it has a tree attached
+
+               if (GTK_TREE_ITEM_SUBTREE(tree_item))
+               {
+                       GtkItem *item=GTK_ITEM(tree_item);
+
+                       GList *item_children=gtk_container_children(GTK_CONTAINER(item));
+
+                       GtkLabel *label=GTK_LABEL(item_children->data);
+
+                       if (strcmp(label->label,buff)==0)
+                       {
+                               g_list_free(item_children);
+                               g_list_free(children);
+
+                               // return tree attached to the item
+                               return GTK_TREE_ITEM_SUBTREE(tree_item);
+                       }
+
+                       g_list_free(item_children);
+               }
+
+               children = g_list_remove_link (children, children);
+       }
+
+       g_list_free(children);
+
+       // ok, not found so we add it
+       GtkWidget *item=gtk_tree_item_new_with_label(buff);
+       gtk_tree_append(GTK_TREE(node),item);
+       gtk_widget_show(item);
+
+       GtkWidget *tree=gtk_tree_new();
+       gtk_tree_item_set_subtree(GTK_TREE_ITEM(item),tree);
+       gtk_widget_set_name(tree,buff);
+
+       gtk_signal_connect (GTK_OBJECT(tree), "select_child",
+                      GTK_SIGNAL_FUNC(cb_select_child), tree);
+
+       gtk_signal_connect (GTK_OBJECT (item), "button_release_event",GTK_SIGNAL_FUNC (button_release), NULL);
+
+
+       //gtk_signal_connect (GTK_OBJECT(tree), "selection_changed",
+      //                GTK_SIGNAL_FUNC(cb_selection_changed), tree, this);
+
+       return tree;
+}
+
+
+std::string CTree::GetFullPath(GtkWidget *child)
+{
+       std::string path;
+       gchar *name;
+
+       GtkLabel *label = GTK_LABEL (GTK_BIN (child)->child);
+       gtk_label_get (label, &name);
+       path=name;
+
+       if (path.compare("root")==0)
+               return "root";
+
+       while (1)
+       {
+               // this gets an items parent tree
+               GtkWidget *tr=(child->parent);
+
+               if (GTK_WIDGET(tr)==m_Root)
+                       break;
+
+               // and now its item
+               child=GTK_TREE(tr)->tree_owner;
+
+               // and now the items label
+               label = GTK_LABEL (GTK_BIN (child)->child);
+               gtk_label_get (label, &name);
+               std::string lbl=name;
+               path=lbl+"/"+path;
+       }
+
+       return path;
+}
+
+void CTree::RemovePath(const char *path)
+{
+       // not used yet
+}
+
+
+void CTree::SelectChild(GtkWidget *child)
+{
+       g_pMainWnd->UpdateStatus();
+       g_pMainWnd->UpdateToolBar();
+}
+
+void cb_select_child (GtkWidget *root_tree, GtkWidget *child, GtkWidget *subtree)
+{
+       g_pMainWnd->m_Tree.SelectChild(child);
+}
+
+
+std::string CTree::GetSelected()
+{
+       std::string path="";
+
+       if (!GTK_TREE(m_Tree)->selection)
+               return path;
+
+       GList *selected = (GTK_TREE(m_Tree)->selection);
+
+       GtkWidget *item=GTK_WIDGET(selected->data);
+
+       if (GTK_TREE_ITEM(item)->subtree)
+               return path;
+
+       path=GetFullPath(item);
+
+       return path;
+}
diff --git a/contrib/pk3man/tree.h b/contrib/pk3man/tree.h
new file mode 100644 (file)
index 0000000..3e50618
--- /dev/null
@@ -0,0 +1,41 @@
+// Tree.h: interface for the CTree class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_TREE_H__C0DDC824_48DF_4A80_B393_83FF736FCB98__INCLUDED_)
+#define AFX_TREE_H__C0DDC824_48DF_4A80_B393_83FF736FCB98__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "stdafx.h"
+#include <string>
+
+void cb_select_child (GtkWidget *root_tree, GtkWidget *child, GtkWidget *subtree);
+
+class CTree
+{
+public:
+       CTree();
+       virtual ~CTree();
+
+       GtkWidget *m_pMainWnd;
+       GtkWidget *m_Tree;
+       GtkWidget *m_Root;
+
+       void Init(GtkWidget *win);
+       void AddPath(const char *path);
+       void AddFile(const char *file,GtkWidget *node=NULL);
+       GtkWidget *AddFolder(const char *folder, GtkWidget *node=NULL);
+       void RemovePath(const char*path);
+
+       void SelectChild(GtkWidget *child);
+       std::string GetSelected();
+       std::string GetFullPath(GtkWidget *item);
+
+       void Clear();
+
+};
+
+#endif // !defined(AFX_TREE_H__C0DDC824_48DF_4A80_B393_83FF736FCB98__INCLUDED_)
diff --git a/contrib/pk3man/wild.cpp b/contrib/pk3man/wild.cpp
new file mode 100644 (file)
index 0000000..2b6a929
--- /dev/null
@@ -0,0 +1,338 @@
+// Wild.cpp: implementation of the CWild class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+//#include "pakman.h"
+#include "wild.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CWild::CWild()
+{
+
+}
+
+CWild::~CWild()
+{
+
+}
+
+int CWild::fpattern_isvalid(const char *pat)
+{
+       int             len;
+
+       /* Check args */
+       if (pat == NULL)
+               return (FALSE);
+
+       /* Verify that the pattern is valid */
+       for (len = 0;  pat[len] != '\0';  len++)
+       {
+               switch (pat[len])
+               {
+               case FPAT_SET_L:
+                       /* Char set */
+                       len++;
+                       if (pat[len] == FPAT_SET_NOT)
+                               len++;                  /* Set negation */
+
+                       while (pat[len] != FPAT_SET_R)
+                       {
+                               if (pat[len] == QUOTE)
+                                       len++;          /* Quoted char */
+                               if (pat[len] == '\0')
+                                       return (FALSE); /* Missing closing bracket */
+                               len++;
+
+                               if (pat[len] == FPAT_SET_THRU)
+                               {
+                                       /* Char range */
+                                       len++;
+                                       if (pat[len] == QUOTE)
+                                               len++;          /* Quoted char */
+                                       if (pat[len] == '\0')
+                                               return (FALSE); /* Missing closing bracket */
+                                       len++;
+                               }
+
+                               if (pat[len] == '\0')
+                                       return (FALSE); /* Missing closing bracket */
+                       }
+                       break;
+
+               case QUOTE:
+                       /* Quoted char */
+                       len++;
+                       if (pat[len] == '\0')
+                               return (FALSE);         /* Missing quoted char */
+                       break;
+
+               case FPAT_NOT:
+                       /* Negated pattern */
+                       len++;
+                       if (pat[len] == '\0')
+                               return (FALSE);         /* Missing subpattern */
+                       break;
+
+               default:
+                       /* Valid character */
+                       break;
+               }
+       }
+
+       return (TRUE);
+}
+
+
+int CWild::fpattern_submatch(const char *pat, const char *fname)
+{
+       int             fch;
+       int             pch;
+       int             i;
+       int             yes, match;
+       int             lo, hi;
+
+       /* Attempt to match subpattern against subfilename */
+       while (*pat != '\0')
+       {
+               fch = *fname;
+               pch = *pat;
+               pat++;
+
+               switch (pch)
+               {
+               case FPAT_ANY:
+                       /* Match a single char */
+                       if (fch == DEL  ||  fch == DEL2  ||  fch == '\0')
+                               return (FALSE);
+                       fname++;
+                       break;
+
+               case FPAT_CLOS:
+                       /* Match zero or more chars */
+                       i = 0;
+                       while (fname[i] != '\0')//  && fname[i] != DEL  &&  fname[i] != DEL2)
+                               i++;
+
+                       while (i >= 0)
+                       {
+                               if (fpattern_submatch(pat, fname+i))
+                                       return (TRUE);
+                               i--;
+                       }
+                       return (FALSE);
+
+               case SUB:
+                       /* Match zero or more chars */
+                       i = 0;
+                       while (fname[i] != '\0'  && fname[i] != DEL  &&  fname[i] != DEL2  && fname[i] != '.')
+                               i++;
+                       while (i >= 0)
+                       {
+                               if (fpattern_submatch(pat, fname+i))
+                                       return (TRUE);
+                               i--;
+                       }
+                       return (FALSE);
+
+               case QUOTE:
+                       /* Match a quoted char */
+                       pch = *pat;
+                       if (lowercase(fch) != lowercase(pch)  ||  pch == '\0')
+                               return (FALSE);
+                       fname++;
+                       pat++;
+                       break;
+
+               case FPAT_SET_L:
+                       /* Match char set/range */
+                       yes = TRUE;
+                       if (*pat == FPAT_SET_NOT)
+                       {
+                       pat++;
+                       yes = FALSE;    /* Set negation */
+                       }
+
+                       /* Look for [s], [-], [abc], [a-c] */
+                       match = !yes;
+                       while (*pat != FPAT_SET_R  &&  *pat != '\0')
+                       {
+                               if (*pat == QUOTE)
+                                       pat++;  /* Quoted char */
+
+                               if (*pat == '\0')
+                                       break;
+                               lo = *pat++;
+                               hi = lo;
+
+                               if (*pat == FPAT_SET_THRU)
+                               {
+                                       /* Range */
+                                       pat++;
+
+                                       if (*pat == QUOTE)
+                                               pat++;  /* Quoted char */
+
+                                       if (*pat == '\0')
+                                               break;
+                                       hi = *pat++;
+                               }
+
+                               if (*pat == '\0')
+                                       break;
+
+                               /* Compare character to set range */
+                               if (lowercase(fch) >= lowercase(lo)  &&
+                                       lowercase(fch) <= lowercase(hi))
+                                       match = yes;
+                       }
+
+                       if (!match)
+                               return (FALSE);
+
+                       if (*pat == '\0')
+                               return (FALSE);         /* Missing closing bracket */
+
+                       fname++;
+                       pat++;
+                       break;
+
+               case FPAT_NOT:
+                       /* Match only if rest of pattern does not match */
+                       if (*pat == '\0')
+                               return (FALSE);         /* Missing subpattern */
+                       i = fpattern_submatch(pat, fname);
+                       return !i;
+
+
+               case DEL:
+               case DEL2:
+
+                       /* Match path delimiter char */
+                       if (fch != DEL  &&  fch != DEL2)
+                               return (FALSE);
+                       fname++;
+                       break;
+
+               default:
+                       /* Match a (non-null) char exactly */
+                       if (lowercase(fch) != lowercase(pch))
+                               return (FALSE);
+                       fname++;
+                       break;
+               }
+       }
+
+       /* Check for complete match */
+       if (*fname != '\0')
+               return (FALSE);
+
+       /* Successful match */
+       return (TRUE);
+}
+
+
+/*-----------------------------------------------------------------------------
+* fpattern_match()
+*      Attempts to match pattern 'pat' to filename 'fname'.
+*
+* Returns
+*      1 (true) if the filename matches, otherwise 0 (false).
+*
+* Caveats
+*      If 'fname' is null, zero (false) is returned.
+*
+*      If 'pat' is null, zero (false) is returned.
+*
+*      If 'pat' is empty (""), the only filename it matches is the empty
+*      string ("").
+*
+*      If 'fname' is empty, the only pattern that will match it is the empty
+*      string ("").
+*
+*      If 'pat' is not a well-formed pattern, zero (false) is returned.
+*
+*      Upper and lower case letters are treated the same; alphabetic
+*      characters are converted to lower case before matching occurs.
+*      Conversion to lower case is dependent upon the current locale setting.
+*/
+
+int CWild::fpattern_match(const char *pat, const char *fname)
+{
+       int             rc;
+
+       /* Check args */
+       if (fname == NULL)
+               return (FALSE);
+
+       if (pat == NULL)
+               return (FALSE);
+
+       /* Verify that the pattern is valid, and get its length */
+       if (!fpattern_isvalid(pat))
+               return (FALSE);
+
+       /* Attempt to match pattern against filename */
+       if (fname[0] == '\0')
+               return (pat[0] == '\0');        /* Special case */
+       rc = fpattern_submatch(pat, fname);
+
+       return (rc);
+}
+
+
+/*-----------------------------------------------------------------------------
+* fpattern_matchn()
+*      Attempts to match pattern 'pat' to filename 'fname'.
+*      This operates like fpattern_match() except that it does not verify that
+*      pattern 'pat' is well-formed, assuming that it has been checked by a
+*      prior call to fpattern_isvalid().
+*
+* Returns
+*      1 (true) if the filename matches, otherwise 0 (false).
+*
+* Caveats
+*      If 'fname' is null, zero (false) is returned.
+*
+*      If 'pat' is null, zero (false) is returned.
+*
+*      If 'pat' is empty (""), the only filename it matches is the empty ("")
+*      string.
+*
+*      If 'pat' is not a well-formed pattern, unpredictable results may occur.
+*
+*      Upper and lower case letters are treated the same; alphabetic
+*      characters are converted to lower case before matching occurs.
+*      Conversion to lower case is dependent upon the current locale setting.
+*
+* See also
+*      fpattern_match().
+*/
+
+int CWild::fpattern_matchn(const char *pat, const char *fname)
+{
+       int             rc;
+
+       /* Check args */
+       if (fname == NULL)
+               return (FALSE);
+
+       if (pat == NULL)
+               return (FALSE);
+
+       /* Assume that pattern is well-formed */
+
+       /* Attempt to match pattern against filename */
+       rc = fpattern_submatch(pat, fname);
+
+       return (rc);
+}
diff --git a/contrib/pk3man/wild.h b/contrib/pk3man/wild.h
new file mode 100644 (file)
index 0000000..4c56bd8
--- /dev/null
@@ -0,0 +1,47 @@
+// Wild.h: interface for the CWild class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_WILD_H__DC88A1E2_A432_40DE_A5B2_D8EF34272EFC__INCLUDED_)
+#define AFX_WILD_H__DC88A1E2_A432_40DE_A5B2_D8EF34272EFC__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#define FPAT_QUOTE     '\\'            /* Quotes a special char        */
+#define FPAT_QUOTE2    '`'             /* Quotes a special char        */
+#define FPAT_DEL       '/'             /* Path delimiter               */
+#define FPAT_DEL2      '\\'            /* Path delimiter               */
+#define FPAT_DOT       '.'             /* Dot char                     */
+#define FPAT_NOT       '!'             /* Exclusion                    */
+#define FPAT_ANY       '?'             /* Any one char                 */
+#define FPAT_CLOS      '*'             /* Zero or more chars           */
+#define FPAT_CLOSP     '\x1A'          /* Zero or more nondelimiters   */
+#define FPAT_SET_L     '['             /* Set/range open bracket       */
+#define FPAT_SET_R     ']'             /* Set/range close bracket      */
+#define FPAT_SET_NOT   '!'             /* Set exclusion                */
+#define FPAT_SET_THRU  '-'             /* Set range of chars           */
+
+#define DEL                    FPAT_DEL
+#define DEL2           FPAT_DEL2
+#define QUOTE          FPAT_QUOTE2
+#define SUB                    FPAT_CLOSP
+
+/* Local function macros */
+#define lowercase(c)   tolower(c)
+
+class CWild  
+{
+public:
+       CWild();
+       virtual ~CWild();
+
+       static int      fpattern_submatch(const char *pat, const char *fname);
+       static int      fpattern_isvalid(const char *pat);
+       static int      fpattern_match(const char *pat, const char *fname);
+       static int      fpattern_matchn(const char *pat, const char *fname);
+
+};
+
+#endif // !defined(AFX_WILD_H__DC88A1E2_A432_40DE_A5B2_D8EF34272EFC__INCLUDED_)
diff --git a/contrib/pk3man/zlib/README.linux b/contrib/pk3man/zlib/README.linux
new file mode 100644 (file)
index 0000000..fbe5a8f
--- /dev/null
@@ -0,0 +1,13 @@
+Precompiled stuff for zip/unzip on linux is in libz-zip.a
+Based on zlib + minizip package
+The zip.c and unzip.c files will not build out of the box on linux
+they are only relevant to the windows version
+
+How to rebuild libz-zip.a:
+download zlib from: http://www.info-zip.org/pub/infozip/zlib/zlib.html
+patch the contrib/minizip code with http://www.winimage.com/zLibDll/unzip.html
+  (I had to replace zip.c by a newer one)
+build everything, zlib.a zip.o and unzip.o
+
+ar -rs libz.a zip.o unzip.o
+mv libz.a libz-zip.a
diff --git a/contrib/pk3man/zlib/libz-zip.a b/contrib/pk3man/zlib/libz-zip.a
new file mode 100644 (file)
index 0000000..6c28723
Binary files /dev/null and b/contrib/pk3man/zlib/libz-zip.a differ
diff --git a/contrib/pk3man/zlib/unzip.c b/contrib/pk3man/zlib/unzip.c
new file mode 100644 (file)
index 0000000..ff71a47
--- /dev/null
@@ -0,0 +1,1294 @@
+/* unzip.c -- IO on .zip files using zlib 
+   Version 0.15 beta, Mar 19th, 1998,
+
+   Read unzip.h for more info
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "zlib.h"
+#include "unzip.h"
+
+#ifdef STDC
+#  include <stddef.h>
+#  include <string.h>
+#  include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+    extern int errno;
+#else
+#   include <errno.h>
+#endif
+
+
+#ifndef local
+#  define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+
+
+#if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \
+                      !defined(CASESENSITIVITYDEFAULT_NO)
+#define CASESENSITIVITYDEFAULT_NO
+#endif
+
+
+#ifndef UNZ_BUFSIZE
+#define UNZ_BUFSIZE (16384)
+#endif
+
+#ifndef UNZ_MAXFILENAMEINZIP
+#define UNZ_MAXFILENAMEINZIP (256)
+#endif
+
+#ifndef ALLOC
+# define ALLOC(size) (malloc(size))
+#endif
+#ifndef TRYFREE
+# define TRYFREE(p) {if (p) free(p);}
+#endif
+
+#define SIZECENTRALDIRITEM (0x2e)
+#define SIZEZIPLOCALHEADER (0x1e)
+
+
+/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
+
+#ifndef SEEK_CUR
+#define SEEK_CUR    1
+#endif
+
+#ifndef SEEK_END
+#define SEEK_END    2
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET    0
+#endif
+
+const char unz_copyright[] =
+   " unzip 0.15 Copyright 1998 Gilles Vollant ";
+
+/* unz_file_info_interntal contain internal info about a file in zipfile*/
+typedef struct unz_file_info_internal_s
+{
+    uLong offset_curfile;/* relative offset of local header 4 bytes */
+} unz_file_info_internal;
+
+
+/* file_in_zip_read_info_s contain internal information about a file in zipfile,
+    when reading and decompress it */
+typedef struct
+{
+       char  *read_buffer;         /* internal buffer for compressed data */
+       z_stream stream;            /* zLib stream structure for inflate */
+
+       uLong pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
+       uLong stream_initialised;   /* flag set if stream structure is initialised*/
+
+       uLong offset_local_extrafield;/* offset of the local extra field */
+       uInt  size_local_extrafield;/* size of the local extra field */
+       uLong pos_local_extrafield;   /* position in the local extra field in read*/
+
+       uLong crc32;                /* crc32 of all data uncompressed */
+       uLong crc32_wait;           /* crc32 we must obtain after decompress all */
+       uLong rest_read_compressed; /* number of byte to be decompressed */
+       uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
+       FILE* file;                 /* io structore of the zipfile */
+       uLong compression_method;   /* compression method (0==store) */
+       uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+} file_in_zip_read_info_s;
+
+
+/* unz_s contain internal information about the zipfile
+*/
+typedef struct
+{
+       FILE* file;                 /* io structore of the zipfile */
+       unz_global_info gi;       /* public global information */
+       uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+       uLong num_file;             /* number of the current file in the zipfile*/
+       uLong pos_in_central_dir;   /* pos of the current file in the central dir*/
+       uLong current_file_ok;      /* flag about the usability of the current file*/
+       uLong central_pos;          /* position of the beginning of the central dir*/
+
+       uLong size_central_dir;     /* size of the central directory  */
+       uLong offset_central_dir;   /* offset of start of central directory with
+                                                                  respect to the starting disk number */
+
+       unz_file_info cur_file_info; /* public info about the current file in zip*/
+       unz_file_info_internal cur_file_info_internal; /* private info about it*/
+    file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
+                                           file if we are decompressing it */
+} unz_s;
+
+
+/* ===========================================================================
+     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
+   for end of file.
+   IN assertion: the stream s has been sucessfully opened for reading.
+*/
+
+
+local int unzlocal_getByte(fin,pi)
+       FILE *fin;
+       int *pi;
+{
+    unsigned char c;
+       int err = fread(&c, 1, 1, fin);
+    if (err==1)
+    {
+        *pi = (int)c;
+        return UNZ_OK;
+    }
+    else
+    {
+        if (ferror(fin)) 
+            return UNZ_ERRNO;
+        else
+            return UNZ_EOF;
+    }
+}
+
+
+/* ===========================================================================
+   Reads a long in LSB order from the given gz_stream. Sets 
+*/
+local int unzlocal_getShort (fin,pX)
+       FILE* fin;
+    uLong *pX;
+{
+    uLong x ;
+    int i;
+    int err;
+
+    err = unzlocal_getByte(fin,&i);
+    x = (uLong)i;
+    
+    if (err==UNZ_OK)
+        err = unzlocal_getByte(fin,&i);
+    x += ((uLong)i)<<8;
+   
+    if (err==UNZ_OK)
+        *pX = x;
+    else
+        *pX = 0;
+    return err;
+}
+
+local int unzlocal_getLong (fin,pX)
+       FILE* fin;
+    uLong *pX;
+{
+    uLong x ;
+    int i;
+    int err;
+
+    err = unzlocal_getByte(fin,&i);
+    x = (uLong)i;
+    
+    if (err==UNZ_OK)
+        err = unzlocal_getByte(fin,&i);
+    x += ((uLong)i)<<8;
+
+    if (err==UNZ_OK)
+        err = unzlocal_getByte(fin,&i);
+    x += ((uLong)i)<<16;
+
+    if (err==UNZ_OK)
+        err = unzlocal_getByte(fin,&i);
+    x += ((uLong)i)<<24;
+   
+    if (err==UNZ_OK)
+        *pX = x;
+    else
+        *pX = 0;
+    return err;
+}
+
+
+/* My own strcmpi / strcasecmp */
+local int strcmpcasenosensitive_internal (fileName1,fileName2)
+       const char* fileName1;
+       const char* fileName2;
+{
+       for (;;)
+       {
+               char c1=*(fileName1++);
+               char c2=*(fileName2++);
+               if ((c1>='a') && (c1<='z'))
+                       c1 -= 0x20;
+               if ((c2>='a') && (c2<='z'))
+                       c2 -= 0x20;
+               if (c1=='\0')
+                       return ((c2=='\0') ? 0 : -1);
+               if (c2=='\0')
+                       return 1;
+               if (c1<c2)
+                       return -1;
+               if (c1>c2)
+                       return 1;
+       }
+}
+
+
+#ifdef  CASESENSITIVITYDEFAULT_NO
+#define CASESENSITIVITYDEFAULTVALUE 2
+#else
+#define CASESENSITIVITYDEFAULTVALUE 1
+#endif
+
+#ifndef STRCMPCASENOSENTIVEFUNCTION
+#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
+#endif
+
+/* 
+   Compare two filename (fileName1,fileName2).
+   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+                                                                or strcasecmp)
+   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+        (like 1 on Unix, 2 on Windows)
+
+*/
+extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
+       const char* fileName1;
+       const char* fileName2;
+       int iCaseSensitivity;
+{
+       if (iCaseSensitivity==0)
+               iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
+
+       if (iCaseSensitivity==1)
+               return strcmp(fileName1,fileName2);
+
+       return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
+} 
+
+#define BUFREADCOMMENT (0x400)
+
+/*
+  Locate the Central directory of a zipfile (at the end, just before
+    the global comment)
+*/
+local uLong unzlocal_SearchCentralDir(fin)
+       FILE *fin;
+{
+       unsigned char* buf;
+       uLong uSizeFile;
+       uLong uBackRead;
+       uLong uMaxBack=0xffff; /* maximum size of global comment */
+       uLong uPosFound=0;
+       
+       if (fseek(fin,0,SEEK_END) != 0)
+               return 0;
+
+
+       uSizeFile = ftell( fin );
+       
+       if (uMaxBack>uSizeFile)
+               uMaxBack = uSizeFile;
+
+       buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+       if (buf==NULL)
+               return 0;
+
+       uBackRead = 4;
+       while (uBackRead<uMaxBack)
+       {
+               uLong uReadSize,uReadPos ;
+               int i;
+               if (uBackRead+BUFREADCOMMENT>uMaxBack) 
+                       uBackRead = uMaxBack;
+               else
+                       uBackRead+=BUFREADCOMMENT;
+               uReadPos = uSizeFile-uBackRead ;
+               
+               uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? 
+                     (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
+               if (fseek(fin,uReadPos,SEEK_SET)!=0)
+                       break;
+
+               if (fread(buf,(uInt)uReadSize,1,fin)!=1)
+                       break;
+
+                for (i=(int)uReadSize-3; (i--)>0;)
+                       if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && 
+                               ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
+                       {
+                               uPosFound = uReadPos+i;
+                               break;
+                       }
+
+               if (uPosFound!=0)
+                       break;
+       }
+       TRYFREE(buf);
+       return uPosFound;
+}
+
+/*
+  Open a Zip file. path contain the full pathname (by example,
+     on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer
+        "zlib/zlib109.zip".
+        If the zipfile cannot be opened (file don't exist or in not valid), the
+          return value is NULL.
+     Else, the return value is a unzFile Handle, usable with other function
+          of this unzip package.
+*/
+extern unzFile ZEXPORT unzOpen (path)
+       const char *path;
+{
+       unz_s us;
+       unz_s *s;
+       uLong central_pos,uL;
+       FILE * fin ;
+
+       uLong number_disk;          /* number of the current dist, used for 
+                                                                  spaning ZIP, unsupported, always 0*/
+       uLong number_disk_with_CD;  /* number the the disk with central dir, used
+                                                                  for spaning ZIP, unsupported, always 0*/
+       uLong number_entry_CD;      /* total number of entries in
+                                      the central dir 
+                                      (same than number_entry on nospan) */
+
+       int err=UNZ_OK;
+
+    if (unz_copyright[0]!=' ')
+        return NULL;
+
+    fin=fopen(path,"rb");
+       if (fin==NULL)
+               return NULL;
+
+       central_pos = unzlocal_SearchCentralDir(fin);
+       if (central_pos==0)
+               err=UNZ_ERRNO;
+
+       if (fseek(fin,central_pos,SEEK_SET)!=0)
+               err=UNZ_ERRNO;
+
+       /* the signature, already checked */
+       if (unzlocal_getLong(fin,&uL)!=UNZ_OK)
+               err=UNZ_ERRNO;
+
+       /* number of this disk */
+       if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK)
+               err=UNZ_ERRNO;
+
+       /* number of the disk with the start of the central directory */
+       if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK)
+               err=UNZ_ERRNO;
+
+       /* total number of entries in the central dir on this disk */
+       if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK)
+               err=UNZ_ERRNO;
+
+       /* total number of entries in the central dir */
+       if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK)
+               err=UNZ_ERRNO;
+
+       if ((number_entry_CD!=us.gi.number_entry) ||
+               (number_disk_with_CD!=0) ||
+               (number_disk!=0))
+               err=UNZ_BADZIPFILE;
+
+       /* size of the central directory */
+       if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK)
+               err=UNZ_ERRNO;
+
+       /* offset of start of central directory with respect to the 
+             starting disk number */
+       if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK)
+               err=UNZ_ERRNO;
+
+       /* zipfile comment length */
+       if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK)
+               err=UNZ_ERRNO;
+
+       if ((central_pos<us.offset_central_dir+us.size_central_dir) && 
+               (err==UNZ_OK))
+               err=UNZ_BADZIPFILE;
+
+       if (err!=UNZ_OK)
+       {
+               fclose(fin);
+               return NULL;
+       }
+
+       us.file=fin;
+       us.byte_before_the_zipfile = central_pos -
+                                   (us.offset_central_dir+us.size_central_dir);
+       us.central_pos = central_pos;
+    us.pfile_in_zip_read = NULL;
+       
+
+       s=(unz_s*)ALLOC(sizeof(unz_s));
+       *s=us;
+       unzGoToFirstFile((unzFile)s);   
+       return (unzFile)s;      
+}
+
+
+/*
+  Close a ZipFile opened with unzipOpen.
+  If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
+    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+  return UNZ_OK if there is no problem. */
+extern int ZEXPORT unzClose (file)
+       unzFile file;
+{
+       unz_s* s;
+       if (file==NULL)
+               return UNZ_PARAMERROR;
+       s=(unz_s*)file;
+
+    if (s->pfile_in_zip_read!=NULL)
+        unzCloseCurrentFile(file);
+
+       fclose(s->file);
+       TRYFREE(s);
+       return UNZ_OK;
+}
+
+
+/*
+  Write info about the ZipFile in the *pglobal_info structure.
+  No preparation of the structure is needed
+  return UNZ_OK if there is no problem. */
+extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
+       unzFile file;
+       unz_global_info *pglobal_info;
+{
+       unz_s* s;
+       if (file==NULL)
+               return UNZ_PARAMERROR;
+       s=(unz_s*)file;
+       *pglobal_info=s->gi;
+       return UNZ_OK;
+}
+
+
+/*
+   Translate date/time from Dos format to tm_unz (readable more easilty)
+*/
+local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
+    uLong ulDosDate;
+    tm_unz* ptm;
+{
+    uLong uDate;
+    uDate = (uLong)(ulDosDate>>16);
+    ptm->tm_mday = (uInt)(uDate&0x1f) ;
+    ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
+    ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
+
+    ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
+    ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
+    ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
+}
+
+/*
+  Get Info about the current file in the zipfile, with internal only info
+*/
+local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
+                                                  unz_file_info *pfile_info,
+                                                  unz_file_info_internal 
+                                                  *pfile_info_internal,
+                                                  char *szFileName,
+                                                                                                 uLong fileNameBufferSize,
+                                                  void *extraField,
+                                                                                                 uLong extraFieldBufferSize,
+                                                  char *szComment,
+                                                                                                 uLong commentBufferSize));
+
+local int unzlocal_GetCurrentFileInfoInternal (file,
+                                              pfile_info,
+                                              pfile_info_internal,
+                                              szFileName, fileNameBufferSize,
+                                              extraField, extraFieldBufferSize,
+                                              szComment,  commentBufferSize)
+       unzFile file;
+       unz_file_info *pfile_info;
+       unz_file_info_internal *pfile_info_internal;
+       char *szFileName;
+       uLong fileNameBufferSize;
+       void *extraField;
+       uLong extraFieldBufferSize;
+       char *szComment;
+       uLong commentBufferSize;
+{
+       unz_s* s;
+       unz_file_info file_info;
+       unz_file_info_internal file_info_internal;
+       int err=UNZ_OK;
+       uLong uMagic;
+       long lSeek=0;
+
+       if (file==NULL)
+               return UNZ_PARAMERROR;
+       s=(unz_s*)file;
+       if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0)
+               err=UNZ_ERRNO;
+
+
+       /* we check the magic */
+       if (err==UNZ_OK)
+               if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
+                       err=UNZ_ERRNO;
+               else if (uMagic!=0x02014b50)
+                       err=UNZ_BADZIPFILE;
+
+       if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK)
+               err=UNZ_ERRNO;
+
+       if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK)
+               err=UNZ_ERRNO;
+
+       if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK)
+               err=UNZ_ERRNO;
+
+       if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK)
+               err=UNZ_ERRNO;
+
+       if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK)
+               err=UNZ_ERRNO;
+
+    unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
+
+       if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK)
+               err=UNZ_ERRNO;
+
+       if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK)
+               err=UNZ_ERRNO;
+
+       if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK)
+               err=UNZ_ERRNO;
+
+       if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK)
+               err=UNZ_ERRNO;
+
+       if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK)
+               err=UNZ_ERRNO;
+
+       if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK)
+               err=UNZ_ERRNO;
+
+       if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK)
+               err=UNZ_ERRNO;
+
+       if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK)
+               err=UNZ_ERRNO;
+
+       if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK)
+               err=UNZ_ERRNO;
+
+       if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK)
+               err=UNZ_ERRNO;
+
+       lSeek+=file_info.size_filename;
+       if ((err==UNZ_OK) && (szFileName!=NULL))
+       {
+               uLong uSizeRead ;
+               if (file_info.size_filename<fileNameBufferSize)
+               {
+                       *(szFileName+file_info.size_filename)='\0';
+                       uSizeRead = file_info.size_filename;
+               }
+               else
+                       uSizeRead = fileNameBufferSize;
+
+               if ((file_info.size_filename>0) && (fileNameBufferSize>0))
+                       if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1)
+                               err=UNZ_ERRNO;
+               lSeek -= uSizeRead;
+       }
+
+       
+       if ((err==UNZ_OK) && (extraField!=NULL))
+       {
+               uLong uSizeRead ;
+               if (file_info.size_file_extra<extraFieldBufferSize)
+                       uSizeRead = file_info.size_file_extra;
+               else
+                       uSizeRead = extraFieldBufferSize;
+
+               if (lSeek!=0)
+                       if (fseek(s->file,lSeek,SEEK_CUR)==0)
+                               lSeek=0;
+                       else
+                               err=UNZ_ERRNO;
+               if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
+                       if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1)
+                               err=UNZ_ERRNO;
+               lSeek += file_info.size_file_extra - uSizeRead;
+       }
+       else
+               lSeek+=file_info.size_file_extra; 
+
+       
+       if ((err==UNZ_OK) && (szComment!=NULL))
+       {
+               uLong uSizeRead ;
+               if (file_info.size_file_comment<commentBufferSize)
+               {
+                       *(szComment+file_info.size_file_comment)='\0';
+                       uSizeRead = file_info.size_file_comment;
+               }
+               else
+                       uSizeRead = commentBufferSize;
+
+               if (lSeek!=0)
+                       if (fseek(s->file,lSeek,SEEK_CUR)==0)
+                               lSeek=0;
+                       else
+                               err=UNZ_ERRNO;
+               if ((file_info.size_file_comment>0) && (commentBufferSize>0))
+                       if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1)
+                               err=UNZ_ERRNO;
+               lSeek+=file_info.size_file_comment - uSizeRead;
+       }
+       else
+               lSeek+=file_info.size_file_comment;
+
+       if ((err==UNZ_OK) && (pfile_info!=NULL))
+               *pfile_info=file_info;
+
+       if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
+               *pfile_info_internal=file_info_internal;
+
+       return err;
+}
+
+
+
+/*
+  Write info about the ZipFile in the *pglobal_info structure.
+  No preparation of the structure is needed
+  return UNZ_OK if there is no problem.
+*/
+extern int ZEXPORT unzGetCurrentFileInfo (file,
+                                                  pfile_info,
+                                                  szFileName, fileNameBufferSize,
+                                                  extraField, extraFieldBufferSize,
+                                                  szComment,  commentBufferSize)
+       unzFile file;
+       unz_file_info *pfile_info;
+       char *szFileName;
+       uLong fileNameBufferSize;
+       void *extraField;
+       uLong extraFieldBufferSize;
+       char *szComment;
+       uLong commentBufferSize;
+{
+       return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
+                                                                                               szFileName,fileNameBufferSize,
+                                                                                               extraField,extraFieldBufferSize,
+                                                                                               szComment,commentBufferSize);
+}
+
+/*
+  Set the current file of the zipfile to the first file.
+  return UNZ_OK if there is no problem
+*/
+extern int ZEXPORT unzGoToFirstFile (file)
+       unzFile file;
+{
+       int err=UNZ_OK;
+       unz_s* s;
+       if (file==NULL)
+               return UNZ_PARAMERROR;
+       s=(unz_s*)file;
+       s->pos_in_central_dir=s->offset_central_dir;
+       s->num_file=0;
+       err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+                                                                                        &s->cur_file_info_internal,
+                                                                                        NULL,0,NULL,0,NULL,0);
+       s->current_file_ok = (err == UNZ_OK);
+       return err;
+}
+
+
+/*
+  Set the current file of the zipfile to the next file.
+  return UNZ_OK if there is no problem
+  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+extern int ZEXPORT unzGoToNextFile (file)
+       unzFile file;
+{
+       unz_s* s;       
+       int err;
+
+       if (file==NULL)
+               return UNZ_PARAMERROR;
+       s=(unz_s*)file;
+       if (!s->current_file_ok)
+               return UNZ_END_OF_LIST_OF_FILE;
+       if (s->num_file+1==s->gi.number_entry)
+               return UNZ_END_OF_LIST_OF_FILE;
+
+       s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
+                       s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
+       s->num_file++;
+       err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+                                                                                          &s->cur_file_info_internal,
+                                                                                          NULL,0,NULL,0,NULL,0);
+       s->current_file_ok = (err == UNZ_OK);
+       return err;
+}
+
+
+/*
+  Try locate the file szFileName in the zipfile.
+  For the iCaseSensitivity signification, see unzipStringFileNameCompare
+
+  return value :
+  UNZ_OK if the file is found. It becomes the current file.
+  UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
+       unzFile file;
+       const char *szFileName;
+       int iCaseSensitivity;
+{
+       unz_s* s;       
+       int err;
+
+       
+       uLong num_fileSaved;
+       uLong pos_in_central_dirSaved;
+
+
+       if (file==NULL)
+               return UNZ_PARAMERROR;
+
+    if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
+        return UNZ_PARAMERROR;
+
+       s=(unz_s*)file;
+       if (!s->current_file_ok)
+               return UNZ_END_OF_LIST_OF_FILE;
+
+       num_fileSaved = s->num_file;
+       pos_in_central_dirSaved = s->pos_in_central_dir;
+
+       err = unzGoToFirstFile(file);
+
+       while (err == UNZ_OK)
+       {
+               char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
+               unzGetCurrentFileInfo(file,NULL,
+                                                               szCurrentFileName,sizeof(szCurrentFileName)-1,
+                                                               NULL,0,NULL,0);
+               if (unzStringFileNameCompare(szCurrentFileName,
+                                                                               szFileName,iCaseSensitivity)==0)
+                       return UNZ_OK;
+               err = unzGoToNextFile(file);
+       }
+
+       s->num_file = num_fileSaved ;
+       s->pos_in_central_dir = pos_in_central_dirSaved ;
+       return err;
+}
+
+
+/*
+  Read the local header of the current zipfile
+  Check the coherency of the local header and info in the end of central
+        directory about this file
+  store in *piSizeVar the size of extra info in local header
+        (filename and size of extra field data)
+*/
+local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
+                                                                                                       poffset_local_extrafield,
+                                                                                                       psize_local_extrafield)
+       unz_s* s;
+       uInt* piSizeVar;
+       uLong *poffset_local_extrafield;
+       uInt  *psize_local_extrafield;
+{
+       uLong uMagic,uData,uFlags;
+       uLong size_filename;
+       uLong size_extra_field;
+       int err=UNZ_OK;
+
+       *piSizeVar = 0;
+       *poffset_local_extrafield = 0;
+       *psize_local_extrafield = 0;
+
+       if (fseek(s->file,s->cur_file_info_internal.offset_curfile +
+                                                               s->byte_before_the_zipfile,SEEK_SET)!=0)
+               return UNZ_ERRNO;
+
+
+       if (err==UNZ_OK)
+               if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
+                       err=UNZ_ERRNO;
+               else if (uMagic!=0x04034b50)
+                       err=UNZ_BADZIPFILE;
+
+       if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
+               err=UNZ_ERRNO;
+/*
+       else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
+               err=UNZ_BADZIPFILE;
+*/
+       if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)
+               err=UNZ_ERRNO;
+
+       if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
+               err=UNZ_ERRNO;
+       else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
+               err=UNZ_BADZIPFILE;
+
+    if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
+                         (s->cur_file_info.compression_method!=Z_DEFLATED))
+        err=UNZ_BADZIPFILE;
+
+       if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */
+               err=UNZ_ERRNO;
+
+       if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */
+               err=UNZ_ERRNO;
+       else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
+                                     ((uFlags & 8)==0))
+               err=UNZ_BADZIPFILE;
+
+       if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */
+               err=UNZ_ERRNO;
+       else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
+                                                         ((uFlags & 8)==0))
+               err=UNZ_BADZIPFILE;
+
+       if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */
+               err=UNZ_ERRNO;
+       else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && 
+                                                         ((uFlags & 8)==0))
+               err=UNZ_BADZIPFILE;
+
+
+       if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)
+               err=UNZ_ERRNO;
+       else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
+               err=UNZ_BADZIPFILE;
+
+       *piSizeVar += (uInt)size_filename;
+
+       if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)
+               err=UNZ_ERRNO;
+       *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
+                                                                       SIZEZIPLOCALHEADER + size_filename;
+       *psize_local_extrafield = (uInt)size_extra_field;
+
+       *piSizeVar += (uInt)size_extra_field;
+
+       return err;
+}
+                                                                                               
+/*
+  Open for reading data the current file in the zipfile.
+  If there is no error and the file is opened, the return value is UNZ_OK.
+*/
+extern int ZEXPORT unzOpenCurrentFile (file)
+       unzFile file;
+{
+       int err=UNZ_OK;
+       int Store;
+       uInt iSizeVar;
+       unz_s* s;
+       file_in_zip_read_info_s* pfile_in_zip_read_info;
+       uLong offset_local_extrafield;  /* offset of the local extra field */
+       uInt  size_local_extrafield;    /* size of the local extra field */
+
+       if (file==NULL)
+               return UNZ_PARAMERROR;
+       s=(unz_s*)file;
+       if (!s->current_file_ok)
+               return UNZ_PARAMERROR;
+
+    if (s->pfile_in_zip_read != NULL)
+        unzCloseCurrentFile(file);
+
+       if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
+                               &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
+               return UNZ_BADZIPFILE;
+
+       pfile_in_zip_read_info = (file_in_zip_read_info_s*)
+                                                                           ALLOC(sizeof(file_in_zip_read_info_s));
+       if (pfile_in_zip_read_info==NULL)
+               return UNZ_INTERNALERROR;
+
+       pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
+       pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
+       pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
+       pfile_in_zip_read_info->pos_local_extrafield=0;
+
+       if (pfile_in_zip_read_info->read_buffer==NULL)
+       {
+               TRYFREE(pfile_in_zip_read_info);
+               return UNZ_INTERNALERROR;
+       }
+
+       pfile_in_zip_read_info->stream_initialised=0;
+       
+       if ((s->cur_file_info.compression_method!=0) &&
+        (s->cur_file_info.compression_method!=Z_DEFLATED))
+               err=UNZ_BADZIPFILE;
+       Store = s->cur_file_info.compression_method==0;
+
+       pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
+       pfile_in_zip_read_info->crc32=0;
+       pfile_in_zip_read_info->compression_method =
+            s->cur_file_info.compression_method;
+       pfile_in_zip_read_info->file=s->file;
+       pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
+
+    pfile_in_zip_read_info->stream.total_out = 0;
+
+       if (!Store)
+       {
+         pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
+         pfile_in_zip_read_info->stream.zfree = (free_func)0;
+         pfile_in_zip_read_info->stream.opaque = (voidpf)0; 
+      
+         err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
+         if (err == Z_OK)
+           pfile_in_zip_read_info->stream_initialised=1;
+        /* windowBits is passed < 0 to tell that there is no zlib header.
+         * Note that in this case inflate *requires* an extra "dummy" byte
+         * after the compressed stream in order to complete decompression and
+         * return Z_STREAM_END. 
+         * In unzip, i don't wait absolutely Z_STREAM_END because I known the 
+         * size of both compressed and uncompressed data
+         */
+       }
+       pfile_in_zip_read_info->rest_read_compressed = 
+            s->cur_file_info.compressed_size ;
+       pfile_in_zip_read_info->rest_read_uncompressed = 
+            s->cur_file_info.uncompressed_size ;
+
+       
+       pfile_in_zip_read_info->pos_in_zipfile = 
+            s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + 
+                         iSizeVar;
+       
+       pfile_in_zip_read_info->stream.avail_in = (uInt)0;
+
+
+       s->pfile_in_zip_read = pfile_in_zip_read_info;
+    return UNZ_OK;
+}
+
+
+/*
+  Read bytes from the current file.
+  buf contain buffer where data must be copied
+  len the size of buf.
+
+  return the number of byte copied if somes bytes are copied
+  return 0 if the end of file was reached
+  return <0 with error code if there is an error
+    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
+       unzFile file;
+       voidp buf;
+       unsigned len;
+{
+       int err=UNZ_OK;
+       uInt iRead = 0;
+       unz_s* s;
+       file_in_zip_read_info_s* pfile_in_zip_read_info;
+       if (file==NULL)
+               return UNZ_PARAMERROR;
+       s=(unz_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+       if (pfile_in_zip_read_info==NULL)
+               return UNZ_PARAMERROR;
+
+
+       if ((pfile_in_zip_read_info->read_buffer == NULL))
+               return UNZ_END_OF_LIST_OF_FILE;
+       if (len==0)
+               return 0;
+
+       pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
+
+       pfile_in_zip_read_info->stream.avail_out = (uInt)len;
+       
+       if (len>pfile_in_zip_read_info->rest_read_uncompressed)
+               pfile_in_zip_read_info->stream.avail_out = 
+                 (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
+
+       while (pfile_in_zip_read_info->stream.avail_out>0)
+       {
+               if ((pfile_in_zip_read_info->stream.avail_in==0) &&
+            (pfile_in_zip_read_info->rest_read_compressed>0))
+               {
+                       uInt uReadThis = UNZ_BUFSIZE;
+                       if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
+                               uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
+                       if (uReadThis == 0)
+                               return UNZ_EOF;
+                       if (fseek(pfile_in_zip_read_info->file,
+                      pfile_in_zip_read_info->pos_in_zipfile + 
+                         pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0)
+                               return UNZ_ERRNO;
+                       if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1,
+                         pfile_in_zip_read_info->file)!=1)
+                               return UNZ_ERRNO;
+                       pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
+
+                       pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
+                       
+                       pfile_in_zip_read_info->stream.next_in = 
+                (Bytef*)pfile_in_zip_read_info->read_buffer;
+                       pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
+               }
+
+               if (pfile_in_zip_read_info->compression_method==0)
+               {
+                       uInt uDoCopy,i ;
+                       if (pfile_in_zip_read_info->stream.avail_out < 
+                            pfile_in_zip_read_info->stream.avail_in)
+                               uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
+                       else
+                               uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
+                               
+                       for (i=0;i<uDoCopy;i++)
+                               *(pfile_in_zip_read_info->stream.next_out+i) =
+                        *(pfile_in_zip_read_info->stream.next_in+i);
+                                       
+                       pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
+                                                               pfile_in_zip_read_info->stream.next_out,
+                                                               uDoCopy);
+                       pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
+                       pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
+                       pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
+                       pfile_in_zip_read_info->stream.next_out += uDoCopy;
+                       pfile_in_zip_read_info->stream.next_in += uDoCopy;
+            pfile_in_zip_read_info->stream.total_out += uDoCopy;
+                       iRead += uDoCopy;
+               }
+               else
+               {
+                       uLong uTotalOutBefore,uTotalOutAfter;
+                       const Bytef *bufBefore;
+                       uLong uOutThis;
+                       int flush=Z_SYNC_FLUSH;
+
+                       uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
+                       bufBefore = pfile_in_zip_read_info->stream.next_out;
+
+                       /*
+                       if ((pfile_in_zip_read_info->rest_read_uncompressed ==
+                                pfile_in_zip_read_info->stream.avail_out) &&
+                               (pfile_in_zip_read_info->rest_read_compressed == 0))
+                               flush = Z_FINISH;
+                       */
+                       err=inflate(&pfile_in_zip_read_info->stream,flush);
+
+                       uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
+                       uOutThis = uTotalOutAfter-uTotalOutBefore;
+                       
+                       pfile_in_zip_read_info->crc32 = 
+                crc32(pfile_in_zip_read_info->crc32,bufBefore,
+                        (uInt)(uOutThis));
+
+                       pfile_in_zip_read_info->rest_read_uncompressed -=
+                uOutThis;
+
+                       iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
+            
+                       if (err==Z_STREAM_END)
+                               return (iRead==0) ? UNZ_EOF : iRead;
+                       if (err!=Z_OK) 
+                               break;
+               }
+       }
+
+       if (err==Z_OK)
+               return iRead;
+       return err;
+}
+
+
+/*
+  Give the current position in uncompressed data
+*/
+extern z_off_t ZEXPORT unztell (file)
+       unzFile file;
+{
+       unz_s* s;
+       file_in_zip_read_info_s* pfile_in_zip_read_info;
+       if (file==NULL)
+               return UNZ_PARAMERROR;
+       s=(unz_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+       if (pfile_in_zip_read_info==NULL)
+               return UNZ_PARAMERROR;
+
+       return (z_off_t)pfile_in_zip_read_info->stream.total_out;
+}
+
+
+/*
+  return 1 if the end of file was reached, 0 elsewhere 
+*/
+extern int ZEXPORT unzeof (file)
+       unzFile file;
+{
+       unz_s* s;
+       file_in_zip_read_info_s* pfile_in_zip_read_info;
+       if (file==NULL)
+               return UNZ_PARAMERROR;
+       s=(unz_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+       if (pfile_in_zip_read_info==NULL)
+               return UNZ_PARAMERROR;
+       
+       if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
+               return 1;
+       else
+               return 0;
+}
+
+
+
+/*
+  Read extra field from the current file (opened by unzOpenCurrentFile)
+  This is the local-header version of the extra field (sometimes, there is
+    more info in the local-header version than in the central-header)
+
+  if buf==NULL, it return the size of the local extra field that can be read
+
+  if buf!=NULL, len is the size of the buffer, the extra header is copied in
+       buf.
+  the return value is the number of bytes copied in buf, or (if <0) 
+       the error code
+*/
+extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
+       unzFile file;
+       voidp buf;
+       unsigned len;
+{
+       unz_s* s;
+       file_in_zip_read_info_s* pfile_in_zip_read_info;
+       uInt read_now;
+       uLong size_to_read;
+
+       if (file==NULL)
+               return UNZ_PARAMERROR;
+       s=(unz_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+       if (pfile_in_zip_read_info==NULL)
+               return UNZ_PARAMERROR;
+
+       size_to_read = (pfile_in_zip_read_info->size_local_extrafield - 
+                               pfile_in_zip_read_info->pos_local_extrafield);
+
+       if (buf==NULL)
+               return (int)size_to_read;
+       
+       if (len>size_to_read)
+               read_now = (uInt)size_to_read;
+       else
+               read_now = (uInt)len ;
+
+       if (read_now==0)
+               return 0;
+       
+       if (fseek(pfile_in_zip_read_info->file,
+              pfile_in_zip_read_info->offset_local_extrafield + 
+                         pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0)
+               return UNZ_ERRNO;
+
+       if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1)
+               return UNZ_ERRNO;
+
+       return (int)read_now;
+}
+
+/*
+  Close the file in zip opened with unzipOpenCurrentFile
+  Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+extern int ZEXPORT unzCloseCurrentFile (file)
+       unzFile file;
+{
+       int err=UNZ_OK;
+
+       unz_s* s;
+       file_in_zip_read_info_s* pfile_in_zip_read_info;
+       if (file==NULL)
+               return UNZ_PARAMERROR;
+       s=(unz_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+       if (pfile_in_zip_read_info==NULL)
+               return UNZ_PARAMERROR;
+
+
+       if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
+       {
+               if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
+                       err=UNZ_CRCERROR;
+       }
+
+
+       TRYFREE(pfile_in_zip_read_info->read_buffer);
+       pfile_in_zip_read_info->read_buffer = NULL;
+       if (pfile_in_zip_read_info->stream_initialised)
+               inflateEnd(&pfile_in_zip_read_info->stream);
+
+       pfile_in_zip_read_info->stream_initialised = 0;
+       TRYFREE(pfile_in_zip_read_info);
+
+    s->pfile_in_zip_read=NULL;
+
+       return err;
+}
+
+
+/*
+  Get the global comment string of the ZipFile, in the szComment buffer.
+  uSizeBuf is the size of the szComment buffer.
+  return the number of byte copied or an error code <0
+*/
+extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
+       unzFile file;
+       char *szComment;
+       uLong uSizeBuf;
+{
+       int err=UNZ_OK;
+       unz_s* s;
+       uLong uReadThis ;
+       if (file==NULL)
+               return UNZ_PARAMERROR;
+       s=(unz_s*)file;
+
+       uReadThis = uSizeBuf;
+       if (uReadThis>s->gi.size_comment)
+               uReadThis = s->gi.size_comment;
+
+       if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0)
+               return UNZ_ERRNO;
+
+       if (uReadThis>0)
+    {
+      *szComment='\0';
+         if (fread(szComment,(uInt)uReadThis,1,s->file)!=1)
+               return UNZ_ERRNO;
+    }
+
+       if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
+               *(szComment+s->gi.size_comment)='\0';
+       return (int)uReadThis;
+}
diff --git a/contrib/pk3man/zlib/unzip.h b/contrib/pk3man/zlib/unzip.h
new file mode 100644 (file)
index 0000000..76692cb
--- /dev/null
@@ -0,0 +1,275 @@
+/* unzip.h -- IO for uncompress .zip files using zlib 
+   Version 0.15 beta, Mar 19th, 1998,
+
+   Copyright (C) 1998 Gilles Vollant
+
+   This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
+     WinZip, InfoZip tools and compatible.
+   Encryption and multi volume ZipFile (span) are not supported.
+   Old compressions used by old PKZip 1.x are not supported
+
+   THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE
+   CAN CHANGE IN FUTURE VERSION !!
+   I WAIT FEEDBACK at mail info@winimage.com
+   Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
+
+   Condition of use and distribution are the same than zlib :
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+
+*/
+/* for more info about .ZIP format, see 
+      ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip
+   PkWare has also a specification at :
+      ftp://ftp.pkware.com/probdesc.zip */
+
+#ifndef _unz_H
+#define _unz_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _ZLIB_H
+#include "zlib.h"
+#endif
+
+#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
+/* like the STRICT of WIN32, we define a pointer that cannot be converted
+    from (void*) without cast */
+typedef struct TagunzFile__ { int unused; } unzFile__; 
+typedef unzFile__ *unzFile;
+#else
+typedef voidp unzFile;
+#endif
+
+
+#define UNZ_OK                                  (0)
+#define UNZ_END_OF_LIST_OF_FILE (-100)
+#define UNZ_ERRNO               (Z_ERRNO)
+#define UNZ_EOF                 (0)
+#define UNZ_PARAMERROR                  (-102)
+#define UNZ_BADZIPFILE                  (-103)
+#define UNZ_INTERNALERROR               (-104)
+#define UNZ_CRCERROR                    (-105)
+
+/* tm_unz contain date/time info */
+typedef struct tm_unz_s 
+{
+       uInt tm_sec;            /* seconds after the minute - [0,59] */
+       uInt tm_min;            /* minutes after the hour - [0,59] */
+       uInt tm_hour;           /* hours since midnight - [0,23] */
+       uInt tm_mday;           /* day of the month - [1,31] */
+       uInt tm_mon;            /* months since January - [0,11] */
+       uInt tm_year;           /* years - [1980..2044] */
+} tm_unz;
+
+/* unz_global_info structure contain global data about the ZIPfile
+   These data comes from the end of central dir */
+typedef struct unz_global_info_s
+{
+       uLong number_entry;         /* total number of entries in
+                                      the central dir on this disk */
+       uLong size_comment;         /* size of the global comment of the zipfile */
+} unz_global_info;
+
+
+/* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_info_s
+{
+    uLong version;              /* version made by                 2 bytes */
+    uLong version_needed;       /* version needed to extract       2 bytes */
+    uLong flag;                 /* general purpose bit flag        2 bytes */
+    uLong compression_method;   /* compression method              2 bytes */
+    uLong dosDate;              /* last mod file date in Dos fmt   4 bytes */
+    uLong crc;                  /* crc-32                          4 bytes */
+    uLong compressed_size;      /* compressed size                 4 bytes */ 
+    uLong uncompressed_size;    /* uncompressed size               4 bytes */ 
+    uLong size_filename;        /* filename length                 2 bytes */
+    uLong size_file_extra;      /* extra field length              2 bytes */
+    uLong size_file_comment;    /* file comment length             2 bytes */
+
+    uLong disk_num_start;       /* disk number start               2 bytes */
+    uLong internal_fa;          /* internal file attributes        2 bytes */
+    uLong external_fa;          /* external file attributes        4 bytes */
+
+    tm_unz tmu_date;
+} unz_file_info;
+
+extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
+                                                                                                const char* fileName2,
+                                                                                                int iCaseSensitivity));
+/*
+   Compare two filename (fileName1,fileName2).
+   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+                                                               or strcasecmp)
+   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+       (like 1 on Unix, 2 on Windows)
+*/
+
+
+extern unzFile ZEXPORT unzOpen OF((const char *path));
+/*
+  Open a Zip file. path contain the full pathname (by example,
+     on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer
+        "zlib/zlib111.zip".
+        If the zipfile cannot be opened (file don't exist or in not valid), the
+          return value is NULL.
+     Else, the return value is a unzFile Handle, usable with other function
+          of this unzip package.
+*/
+
+extern int ZEXPORT unzClose OF((unzFile file));
+/*
+  Close a ZipFile opened with unzipOpen.
+  If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+  return UNZ_OK if there is no problem. */
+
+extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
+                                       unz_global_info *pglobal_info));
+/*
+  Write info about the ZipFile in the *pglobal_info structure.
+  No preparation of the structure is needed
+  return UNZ_OK if there is no problem. */
+
+
+extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
+                                                                                  char *szComment,
+                                          uLong uSizeBuf));
+/*
+  Get the global comment string of the ZipFile, in the szComment buffer.
+  uSizeBuf is the size of the szComment buffer.
+  return the number of byte copied or an error code <0
+*/
+
+
+/***************************************************************************/
+/* Unzip package allow you browse the directory of the zipfile */
+
+extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
+/*
+  Set the current file of the zipfile to the first file.
+  return UNZ_OK if there is no problem
+*/
+
+extern int ZEXPORT unzGoToNextFile OF((unzFile file));
+/*
+  Set the current file of the zipfile to the next file.
+  return UNZ_OK if there is no problem
+  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+
+extern int ZEXPORT unzLocateFile OF((unzFile file, 
+                                    const char *szFileName,
+                                    int iCaseSensitivity));
+/*
+  Try locate the file szFileName in the zipfile.
+  For the iCaseSensitivity signification, see unzStringFileNameCompare
+
+  return value :
+  UNZ_OK if the file is found. It becomes the current file.
+  UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+
+
+extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
+                                            unz_file_info *pfile_info,
+                                            char *szFileName,
+                                            uLong fileNameBufferSize,
+                                            void *extraField,
+                                            uLong extraFieldBufferSize,
+                                            char *szComment,
+                                            uLong commentBufferSize));
+/*
+  Get Info about the current file
+  if pfile_info!=NULL, the *pfile_info structure will contain somes info about
+           the current file
+  if szFileName!=NULL, the filemane string will be copied in szFileName
+                       (fileNameBufferSize is the size of the buffer)
+  if extraField!=NULL, the extra field information will be copied in extraField
+                       (extraFieldBufferSize is the size of the buffer).
+                       This is the Central-header version of the extra field
+  if szComment!=NULL, the comment string of the file will be copied in szComment
+                       (commentBufferSize is the size of the buffer)
+*/
+
+/***************************************************************************/
+/* for reading the content of the current zipfile, you can open it, read data
+   from it, and close it (you can close it before reading all the file)
+   */
+
+extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
+/*
+  Open for reading data the current file in the zipfile.
+  If there is no error, the return value is UNZ_OK.
+*/
+
+extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
+/*
+  Close the file in zip opened with unzOpenCurrentFile
+  Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+
+                                                                                               
+extern int ZEXPORT unzReadCurrentFile OF((unzFile file, 
+                                         voidp buf,
+                                         unsigned len));
+/*
+  Read bytes from the current file (opened by unzOpenCurrentFile)
+  buf contain buffer where data must be copied
+  len the size of buf.
+
+  return the number of byte copied if somes bytes are copied
+  return 0 if the end of file was reached
+  return <0 with error code if there is an error
+    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+
+extern z_off_t ZEXPORT unztell OF((unzFile file));
+/*
+  Give the current position in uncompressed data
+*/
+
+extern int ZEXPORT unzeof OF((unzFile file));
+/*
+  return 1 if the end of file was reached, 0 elsewhere 
+*/
+
+extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
+                                                                                        voidp buf,
+                                                                                        unsigned len));
+/*
+  Read extra field from the current file (opened by unzOpenCurrentFile)
+  This is the local-header version of the extra field (sometimes, there is
+    more info in the local-header version than in the central-header)
+
+  if buf==NULL, it return the size of the local extra field
+
+  if buf!=NULL, len is the size of the buffer, the extra header is copied in
+       buf.
+  the return value is the number of bytes copied in buf, or (if <0) 
+       the error code
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _unz_H */
diff --git a/contrib/pk3man/zlib/zconf.h b/contrib/pk3man/zlib/zconf.h
new file mode 100644 (file)
index 0000000..6a8f33a
--- /dev/null
@@ -0,0 +1,279 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* @(#) $Id: zconf.h,v 1.1.1.1 2000/10/03 18:36:29 mickey Exp $ */
+
+#ifndef _ZCONF_H
+#define _ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+#  define deflateInit_ z_deflateInit_
+#  define deflate      z_deflate
+#  define deflateEnd   z_deflateEnd
+#  define inflateInit_         z_inflateInit_
+#  define inflate      z_inflate
+#  define inflateEnd   z_inflateEnd
+#  define deflateInit2_        z_deflateInit2_
+#  define deflateSetDictionary z_deflateSetDictionary
+#  define deflateCopy  z_deflateCopy
+#  define deflateReset z_deflateReset
+#  define deflateParams        z_deflateParams
+#  define inflateInit2_        z_inflateInit2_
+#  define inflateSetDictionary z_inflateSetDictionary
+#  define inflateSync  z_inflateSync
+#  define inflateSyncPoint z_inflateSyncPoint
+#  define inflateReset z_inflateReset
+#  define compress     z_compress
+#  define compress2    z_compress2
+#  define uncompress   z_uncompress
+#  define adler32      z_adler32
+#  define crc32                z_crc32
+#  define get_crc_table z_get_crc_table
+
+#  define Byte         z_Byte
+#  define uInt         z_uInt
+#  define uLong                z_uLong
+#  define Bytef                z_Bytef
+#  define charf                z_charf
+#  define intf         z_intf
+#  define uIntf                z_uIntf
+#  define uLongf       z_uLongf
+#  define voidpf       z_voidpf
+#  define voidp                z_voidp
+#endif
+
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
+#  define WIN32
+#endif
+#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
+#  ifndef __32BIT__
+#    define __32BIT__
+#  endif
+#endif
+#if defined(__MSDOS__) && !defined(MSDOS)
+#  define MSDOS
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#if defined(MSDOS) && !defined(__32BIT__)
+#  define MAXSEG_64K
+#endif
+#ifdef MSDOS
+#  define UNALIGNED_OK
+#endif
+
+#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32))  && !defined(STDC)
+#  define STDC
+#endif
+#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__)
+#  ifndef STDC
+#    define STDC
+#  endif
+#endif
+
+#ifndef STDC
+#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+#    define const
+#  endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)
+#  define NO_DUMMY_DECL
+#endif
+
+/* Old Borland C incorrectly complains about missing returns: */
+#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
+#  define NEED_DUMMY_RETURN
+#endif
+
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)
+   /* MSC small or medium model */
+#  define SMALL_MEDIUM
+#  ifdef _MSC_VER
+#    define FAR _far
+#  else
+#    define FAR far
+#  endif
+#endif
+#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))
+#  ifndef __32BIT__
+#    define SMALL_MEDIUM
+#    define FAR _far
+#  endif
+#endif
+
+/* Compile with -DZLIB_DLL for Windows DLL support */
+#if defined(ZLIB_DLL)
+#  if defined(_WINDOWS) || defined(WINDOWS)
+#    ifdef FAR
+#      undef FAR
+#    endif
+#    include <windows.h>
+#    define ZEXPORT  WINAPI
+#    ifdef WIN32
+#      define ZEXPORTVA  WINAPIV
+#    else
+#      define ZEXPORTVA  FAR _cdecl _export
+#    endif
+#  endif
+#  if defined (__BORLANDC__)
+#    if (__BORLANDC__ >= 0x0500) && defined (WIN32)
+#      include <windows.h>
+#      define ZEXPORT __declspec(dllexport) WINAPI
+#      define ZEXPORTRVA __declspec(dllexport) WINAPIV
+#    else
+#      if defined (_Windows) && defined (__DLL__)
+#        define ZEXPORT _export
+#        define ZEXPORTVA _export
+#      endif
+#    endif
+#  endif
+#endif
+
+#if defined (__BEOS__)
+#  if defined (ZLIB_DLL)
+#    define ZEXTERN extern __declspec(dllexport)
+#  else
+#    define ZEXTERN extern __declspec(dllimport)
+#  endif
+#endif
+
+#ifndef ZEXPORT
+#  define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA
+#endif
+#ifndef ZEXTERN
+#  define ZEXTERN extern
+#endif
+
+#ifndef FAR
+#   define FAR
+#endif
+
+#if !defined(MACOS) && !defined(TARGET_OS_MAC)
+typedef unsigned char  Byte;  /* 8 bits */
+#endif
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+#  define Bytef Byte FAR
+#else
+   typedef Byte  FAR Bytef;
+#endif
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void FAR *voidpf;
+   typedef void     *voidp;
+#else
+   typedef Byte FAR *voidpf;
+   typedef Byte     *voidp;
+#endif
+
+#ifdef HAVE_UNISTD_H
+#  include <sys/types.h> /* for off_t */
+#  include <unistd.h>    /* for SEEK_* and off_t */
+#  define z_off_t  off_t
+#endif
+#ifndef SEEK_SET
+#  define SEEK_SET        0       /* Seek from beginning of file.  */
+#  define SEEK_CUR        1       /* Seek from current position.  */
+#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+#  define  z_off_t long
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+#   pragma map(deflateInit_,"DEIN")
+#   pragma map(deflateInit2_,"DEIN2")
+#   pragma map(deflateEnd,"DEEND")
+#   pragma map(inflateInit_,"ININ")
+#   pragma map(inflateInit2_,"ININ2")
+#   pragma map(inflateEnd,"INEND")
+#   pragma map(inflateSync,"INSY")
+#   pragma map(inflateSetDictionary,"INSEDI")
+#   pragma map(inflate_blocks,"INBL")
+#   pragma map(inflate_blocks_new,"INBLNE")
+#   pragma map(inflate_blocks_free,"INBLFR")
+#   pragma map(inflate_blocks_reset,"INBLRE")
+#   pragma map(inflate_codes_free,"INCOFR")
+#   pragma map(inflate_codes,"INCO")
+#   pragma map(inflate_fast,"INFA")
+#   pragma map(inflate_flush,"INFLU")
+#   pragma map(inflate_mask,"INMA")
+#   pragma map(inflate_set_dictionary,"INSEDI2")
+#   pragma map(inflate_copyright,"INCOPY")
+#   pragma map(inflate_trees_bits,"INTRBI")
+#   pragma map(inflate_trees_dynamic,"INTRDY")
+#   pragma map(inflate_trees_fixed,"INTRFI")
+#   pragma map(inflate_trees_free,"INTRFR")
+#endif
+
+#endif /* _ZCONF_H */
diff --git a/contrib/pk3man/zlib/zip.c b/contrib/pk3man/zlib/zip.c
new file mode 100644 (file)
index 0000000..4942d0f
--- /dev/null
@@ -0,0 +1,720 @@
+/* zip.c -- IO on .zip files using zlib 
+   Version 0.15 beta, Mar 19th, 1998,
+
+   Read zip.h for more info
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "zlib.h"
+#include "zip.h"
+
+#  define DEF_MEM_LEVEL 8
+
+#ifdef STDC
+#  include <stddef.h>
+#  include <string.h>
+#  include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+    extern int errno;
+#else
+#   include <errno.h>
+#endif
+
+
+#ifndef local
+#  define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+#ifndef VERSIONMADEBY
+# define VERSIONMADEBY   (0x0) /* platform depedent */
+#endif
+
+#ifndef Z_BUFSIZE
+#define Z_BUFSIZE (16384)
+#endif
+
+#ifndef Z_MAXFILENAMEINZIP
+#define Z_MAXFILENAMEINZIP (256)
+#endif
+
+#ifndef ALLOC
+# define ALLOC(size) (malloc(size))
+#endif
+#ifndef TRYFREE
+# define TRYFREE(p) {if (p) free(p);}
+#endif
+
+/*
+#define SIZECENTRALDIRITEM (0x2e)
+#define SIZEZIPLOCALHEADER (0x1e)
+*/
+
+/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
+
+#ifndef SEEK_CUR
+#define SEEK_CUR    1
+#endif
+
+#ifndef SEEK_END
+#define SEEK_END    2
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET    0
+#endif
+
+const char zip_copyright[] =
+   " zip 0.15 Copyright 1998 Gilles Vollant ";
+
+
+#define SIZEDATA_INDATABLOCK (4096-(4*4))
+
+#define LOCALHEADERMAGIC    (0x04034b50)
+#define CENTRALHEADERMAGIC  (0x02014b50)
+#define ENDHEADERMAGIC      (0x06054b50)
+
+#define FLAG_LOCALHEADER_OFFSET (0x06)
+#define CRC_LOCALHEADER_OFFSET  (0x0e)
+
+#define SIZECENTRALHEADER (0x2e) /* 46 */
+
+typedef struct linkedlist_datablock_internal_s
+{
+  struct linkedlist_datablock_internal_s* next_datablock;
+  uLong  avail_in_this_block;
+  uLong  filled_in_this_block;
+  uLong  unused; /* for future use and alignement */
+  unsigned char data[SIZEDATA_INDATABLOCK];
+} linkedlist_datablock_internal;
+
+typedef struct linkedlist_data_s
+{
+    linkedlist_datablock_internal* first_block;
+    linkedlist_datablock_internal* last_block;
+} linkedlist_data;
+
+
+typedef struct
+{
+       z_stream stream;            /* zLib stream structure for inflate */
+    int  stream_initialised;    /* 1 is stream is initialised */
+    uInt pos_in_buffered_data;  /* last written byte in buffered_data */
+
+    uLong pos_local_header;     /* offset of the local header of the file 
+                                     currenty writing */
+    char* central_header;       /* central header data for the current file */
+    uLong size_centralheader;   /* size of the central header for cur file */
+    uLong flag;                 /* flag of the file currently writing */
+
+    int  method;                /* compression method of file currenty wr.*/
+    Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/
+    uLong dosDate;
+    uLong crc32;
+} curfile_info;
+
+typedef struct
+{
+    FILE * filezip;
+    linkedlist_data central_dir;/* datablock with central dir in construction*/
+    int  in_opened_file_inzip;  /* 1 if a file in the zip is currently writ.*/
+    curfile_info ci;            /* info on the file curretly writing */
+
+    uLong begin_pos;            /* position of the beginning of the zipfile */
+    uLong number_entry;
+} zip_internal;
+
+local linkedlist_datablock_internal* allocate_new_datablock()
+{
+    linkedlist_datablock_internal* ldi;
+    ldi = (linkedlist_datablock_internal*)
+                 ALLOC(sizeof(linkedlist_datablock_internal));
+    if (ldi!=NULL)
+    {
+        ldi->next_datablock = NULL ;
+        ldi->filled_in_this_block = 0 ;
+        ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ;
+    }
+    return ldi;
+}
+
+local void free_datablock(ldi)
+    linkedlist_datablock_internal* ldi;
+{
+    while (ldi!=NULL)
+    {
+        linkedlist_datablock_internal* ldinext = ldi->next_datablock;
+        TRYFREE(ldi);
+        ldi = ldinext;
+    }
+}
+
+local void init_linkedlist(ll)
+    linkedlist_data* ll;
+{
+    ll->first_block = ll->last_block = NULL;
+}
+
+local void free_linkedlist(ll)
+    linkedlist_data* ll;
+{
+    free_datablock(ll->first_block);
+    ll->first_block = ll->last_block = NULL;
+}
+
+
+local int add_data_in_datablock(ll,buf,len)
+    linkedlist_data* ll;    
+    const void* buf;
+    uLong len;
+{
+    linkedlist_datablock_internal* ldi;
+    const unsigned char* from_copy;
+
+    if (ll==NULL)
+        return ZIP_INTERNALERROR;
+
+    if (ll->last_block == NULL)
+    {
+        ll->first_block = ll->last_block = allocate_new_datablock();
+        if (ll->first_block == NULL)
+            return ZIP_INTERNALERROR;
+    }
+
+    ldi = ll->last_block;
+    from_copy = (unsigned char*)buf;
+
+    while (len>0)
+    {
+        uInt copy_this;
+        uInt i;
+        unsigned char* to_copy;
+
+        if (ldi->avail_in_this_block==0)
+        {
+            ldi->next_datablock = allocate_new_datablock();
+            if (ldi->next_datablock == NULL)
+                return ZIP_INTERNALERROR;
+            ldi = ldi->next_datablock ;
+            ll->last_block = ldi;
+        }
+
+        if (ldi->avail_in_this_block < len)
+            copy_this = (uInt)ldi->avail_in_this_block;
+        else
+            copy_this = (uInt)len;
+
+        to_copy = &(ldi->data[ldi->filled_in_this_block]);
+
+        for (i=0;i<copy_this;i++)
+            *(to_copy+i)=*(from_copy+i);
+
+        ldi->filled_in_this_block += copy_this;
+        ldi->avail_in_this_block -= copy_this;
+        from_copy += copy_this ;
+        len -= copy_this;
+    }
+    return ZIP_OK;
+}
+
+
+local int write_datablock(fout,ll)
+    FILE * fout;
+    linkedlist_data* ll;    
+{
+    linkedlist_datablock_internal* ldi;
+    ldi = ll->first_block;
+    while (ldi!=NULL)
+    {
+        if (ldi->filled_in_this_block > 0)
+            if (fwrite(ldi->data,(uInt)ldi->filled_in_this_block,1,fout)!=1)
+                return ZIP_ERRNO;
+        ldi = ldi->next_datablock;
+    }
+    return ZIP_OK;
+}
+
+/****************************************************************************/
+
+/* ===========================================================================
+   Outputs a long in LSB order to the given file
+   nbByte == 1, 2 or 4 (byte, short or long)
+*/
+
+local int ziplocal_putValue OF((FILE *file, uLong x, int nbByte));
+local int ziplocal_putValue (file, x, nbByte)
+    FILE *file;
+    uLong x;
+    int nbByte;
+{
+    unsigned char buf[4];
+    int n;
+    for (n = 0; n < nbByte; n++) {
+        buf[n] = (unsigned char)(x & 0xff);
+        x >>= 8;
+    }
+    if (fwrite(buf,nbByte,1,file)!=1)
+        return ZIP_ERRNO;
+    else
+        return ZIP_OK;
+}
+
+local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte));
+local void ziplocal_putValue_inmemory (dest, x, nbByte)
+    void* dest;
+    uLong x;
+    int nbByte;
+{
+    unsigned char* buf=(unsigned char*)dest;
+    int n;
+    for (n = 0; n < nbByte; n++) {
+        buf[n] = (unsigned char)(x & 0xff);
+        x >>= 8;
+    }
+}
+/****************************************************************************/
+
+
+local uLong ziplocal_TmzDateToDosDate(ptm,dosDate)
+    tm_zip* ptm;
+    uLong dosDate;
+{
+    uLong year = (uLong)ptm->tm_year;
+    if (year>1980)
+        year-=1980;
+    else if (year>80)
+        year-=80;
+    return
+      (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) |
+        ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
+}
+
+
+/****************************************************************************/
+
+extern zipFile ZEXPORT zipOpen (pathname, append)
+    const char *pathname;
+    int append;
+{
+    zip_internal ziinit;
+    zip_internal* zi;
+
+    ziinit.filezip = fopen(pathname,(append == 0) ? "wb" : "ab");
+    if (ziinit.filezip == NULL)
+        return NULL;
+    ziinit.begin_pos = ftell(ziinit.filezip);
+    ziinit.in_opened_file_inzip = 0;
+    ziinit.ci.stream_initialised = 0;
+    ziinit.number_entry = 0;
+    init_linkedlist(&(ziinit.central_dir));
+
+
+    zi = (zip_internal*)ALLOC(sizeof(zip_internal));
+    if (zi==NULL)
+    {
+        fclose(ziinit.filezip);
+        return NULL;
+    }
+
+    *zi = ziinit;
+    return (zipFile)zi;
+}
+
+extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi, 
+                                        extrafield_local, size_extrafield_local,
+                                        extrafield_global, size_extrafield_global,
+                                        comment, method, level)
+    zipFile file;
+    const char* filename;
+    const zip_fileinfo* zipfi;
+    const void* extrafield_local;
+    uInt size_extrafield_local;
+    const void* extrafield_global;
+    uInt size_extrafield_global;
+    const char* comment;
+    int method;
+    int level;
+{
+    zip_internal* zi;
+    uInt size_filename;
+    uInt size_comment;
+    uInt i;
+    int err = ZIP_OK;
+
+    if (file == NULL)
+        return ZIP_PARAMERROR;
+    if ((method!=0) && (method!=Z_DEFLATED))
+        return ZIP_PARAMERROR;
+
+    zi = (zip_internal*)file;
+
+    if (zi->in_opened_file_inzip == 1)
+    {
+        err = zipCloseFileInZip (file);
+        if (err != ZIP_OK)
+            return err;
+    }
+
+
+    if (filename==NULL)
+        filename="-";
+
+    if (comment==NULL)
+        size_comment = 0;
+    else
+        size_comment = strlen(comment);
+
+    size_filename = strlen(filename);
+
+    if (zipfi == NULL)
+        zi->ci.dosDate = 0;
+    else
+    {
+        if (zipfi->dosDate != 0)
+            zi->ci.dosDate = zipfi->dosDate;
+        else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate);
+    }
+
+    zi->ci.flag = 0;
+    if ((level==8) || (level==9))
+      zi->ci.flag |= 2;
+    if ((level==2))
+      zi->ci.flag |= 4;
+    if ((level==1))
+      zi->ci.flag |= 6;
+
+    zi->ci.crc32 = 0;
+    zi->ci.method = method;
+    zi->ci.stream_initialised = 0;
+    zi->ci.pos_in_buffered_data = 0;
+    zi->ci.pos_local_header = ftell(zi->filezip);
+    zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + 
+                                      size_extrafield_global + size_comment;
+    zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader);
+
+    ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4);
+    /* version info */
+    ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2);
+    ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2);
+    ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2);
+    ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2);
+    ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4);
+    ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/
+    ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/
+    ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/
+    ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2);
+    ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2);
+    ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2);
+    ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/
+
+    if (zipfi==NULL)
+        ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); 
+    else
+        ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); 
+
+    if (zipfi==NULL)
+        ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); 
+    else
+        ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);
+
+    ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header,4);
+
+    for (i=0;i<size_filename;i++)
+        *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);
+
+    for (i=0;i<size_extrafield_global;i++)
+        *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) =
+              *(((const char*)extrafield_global)+i);
+
+    for (i=0;i<size_comment;i++)
+        *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+
+              size_extrafield_global+i) = *(filename+i);
+    if (zi->ci.central_header == NULL)
+        return ZIP_INTERNALERROR;
+
+    /* write the local header */
+    err = ziplocal_putValue(zi->filezip,(uLong)LOCALHEADERMAGIC,4);
+
+    if (err==ZIP_OK)
+        err = ziplocal_putValue(zi->filezip,(uLong)20,2);/* version needed to extract */
+    if (err==ZIP_OK)
+        err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.flag,2);
+
+    if (err==ZIP_OK)
+        err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.method,2);
+
+    if (err==ZIP_OK)
+        err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.dosDate,4);
+
+    if (err==ZIP_OK)
+        err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* crc 32, unknown */
+    if (err==ZIP_OK)
+        err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* compressed size, unknown */
+    if (err==ZIP_OK)
+        err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* uncompressed size, unknown */
+
+    if (err==ZIP_OK)
+        err = ziplocal_putValue(zi->filezip,(uLong)size_filename,2);
+
+    if (err==ZIP_OK)
+        err = ziplocal_putValue(zi->filezip,(uLong)size_extrafield_local,2);
+
+    if ((err==ZIP_OK) && (size_filename>0))
+        if (fwrite(filename,(uInt)size_filename,1,zi->filezip)!=1)
+                err = ZIP_ERRNO;
+
+    if ((err==ZIP_OK) && (size_extrafield_local>0))
+        if (fwrite(extrafield_local,(uInt)size_extrafield_local,1,zi->filezip)
+                                                                           !=1)
+                err = ZIP_ERRNO;
+
+    zi->ci.stream.avail_in = (uInt)0;
+    zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
+    zi->ci.stream.next_out = zi->ci.buffered_data;
+    zi->ci.stream.total_in = 0;
+    zi->ci.stream.total_out = 0;
+
+    if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED))
+    {
+        zi->ci.stream.zalloc = (alloc_func)0;
+        zi->ci.stream.zfree = (free_func)0;
+        zi->ci.stream.opaque = (voidpf)0;
+
+        err = deflateInit2(&zi->ci.stream, level,
+               Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0);
+
+        if (err==Z_OK)
+            zi->ci.stream_initialised = 1;
+    }
+
+
+    if (err==Z_OK)
+        zi->in_opened_file_inzip = 1;
+    return err;
+}
+
+extern int ZEXPORT zipWriteInFileInZip (file, buf, len)
+    zipFile file;
+    const voidp buf;
+    unsigned len;
+{
+    zip_internal* zi;
+    int err=ZIP_OK;
+
+    if (file == NULL)
+        return ZIP_PARAMERROR;
+    zi = (zip_internal*)file;
+
+    if (zi->in_opened_file_inzip == 0)
+        return ZIP_PARAMERROR;
+
+    zi->ci.stream.next_in = buf;
+    zi->ci.stream.avail_in = len;
+    zi->ci.crc32 = crc32(zi->ci.crc32,buf,len);
+
+    while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))
+    {
+        if (zi->ci.stream.avail_out == 0)
+        {
+            if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip)
+                                                                           !=1)
+                err = ZIP_ERRNO;
+            zi->ci.pos_in_buffered_data = 0;
+            zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
+            zi->ci.stream.next_out = zi->ci.buffered_data;
+        }
+
+        if (zi->ci.method == Z_DEFLATED)
+        {
+            uLong uTotalOutBefore = zi->ci.stream.total_out;
+            err=deflate(&zi->ci.stream,  Z_NO_FLUSH);
+            zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
+
+        }
+        else
+        {
+            uInt copy_this,i;
+            if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
+                copy_this = zi->ci.stream.avail_in;
+            else
+                copy_this = zi->ci.stream.avail_out;
+            for (i=0;i<copy_this;i++)
+                *(((char*)zi->ci.stream.next_out)+i) =
+                    *(((const char*)zi->ci.stream.next_in)+i);
+            {
+                zi->ci.stream.avail_in -= copy_this;
+                zi->ci.stream.avail_out-= copy_this;
+                zi->ci.stream.next_in+= copy_this;
+                zi->ci.stream.next_out+= copy_this;
+                zi->ci.stream.total_in+= copy_this;
+                zi->ci.stream.total_out+= copy_this;
+                zi->ci.pos_in_buffered_data += copy_this;
+            }
+        }
+    }
+
+    return 0;
+}
+
+extern int ZEXPORT zipCloseFileInZip (file)
+    zipFile file;
+{
+    zip_internal* zi;
+    int err=ZIP_OK;
+
+    if (file == NULL)
+        return ZIP_PARAMERROR;
+    zi = (zip_internal*)file;
+
+    if (zi->in_opened_file_inzip == 0)    
+        return ZIP_PARAMERROR;
+    zi->ci.stream.avail_in = 0;
+    
+    if (zi->ci.method == Z_DEFLATED)
+        while (err==ZIP_OK)
+    {
+        uLong uTotalOutBefore;
+        if (zi->ci.stream.avail_out == 0)
+        {
+            if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip)
+                                                                           !=1)
+                err = ZIP_ERRNO;
+            zi->ci.pos_in_buffered_data = 0;
+            zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
+            zi->ci.stream.next_out = zi->ci.buffered_data;
+        }
+        uTotalOutBefore = zi->ci.stream.total_out;
+        err=deflate(&zi->ci.stream,  Z_FINISH);
+        zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
+    }
+
+    if (err==Z_STREAM_END)
+        err=ZIP_OK; /* this is normal */
+
+    if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK))
+        if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip)
+                                                                       !=1)
+            err = ZIP_ERRNO;
+
+    if ((zi->ci.method == Z_DEFLATED) && (err==ZIP_OK))
+    {
+        err=deflateEnd(&zi->ci.stream);
+        zi->ci.stream_initialised = 0;
+    }
+
+    ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)zi->ci.crc32,4); /*crc*/
+    ziplocal_putValue_inmemory(zi->ci.central_header+20,
+                                (uLong)zi->ci.stream.total_out,4); /*compr size*/
+    ziplocal_putValue_inmemory(zi->ci.central_header+24,
+                                (uLong)zi->ci.stream.total_in,4); /*uncompr size*/
+
+    if (err==ZIP_OK)
+        err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header,
+                                       (uLong)zi->ci.size_centralheader);
+    free(zi->ci.central_header);
+
+    if (err==ZIP_OK)
+    {
+        long cur_pos_inzip = ftell(zi->filezip);
+           if (fseek(zi->filezip,
+                  zi->ci.pos_local_header + 14,SEEK_SET)!=0)
+                   err = ZIP_ERRNO;
+
+        if (err==ZIP_OK)
+            err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.crc32,4); /* crc 32, unknown */
+
+        if (err==ZIP_OK) /* compressed size, unknown */
+            err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.stream.total_out,4); 
+
+        if (err==ZIP_OK) /* uncompressed size, unknown */
+            err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.stream.total_in,4);
+
+           if (fseek(zi->filezip,
+                  cur_pos_inzip,SEEK_SET)!=0)
+                   err = ZIP_ERRNO;
+    }
+
+    zi->number_entry ++;
+    zi->in_opened_file_inzip = 0;
+
+    return err;
+}
+
+extern int ZEXPORT zipClose (file, global_comment)
+    zipFile file;
+    const char* global_comment;
+{
+    zip_internal* zi;
+    int err = 0;
+    uLong size_centraldir = 0;
+    uLong centraldir_pos_inzip ;
+    uInt size_global_comment;
+    if (file == NULL)
+        return ZIP_PARAMERROR;
+    zi = (zip_internal*)file;
+
+    if (zi->in_opened_file_inzip == 1)
+    {
+        err = zipCloseFileInZip (file);
+    }
+
+    if (global_comment==NULL)
+        size_global_comment = 0;
+    else
+        size_global_comment = strlen(global_comment);
+
+
+    centraldir_pos_inzip = ftell(zi->filezip);
+    if (err==ZIP_OK)
+    {
+        linkedlist_datablock_internal* ldi = zi->central_dir.first_block ;
+        while (ldi!=NULL)
+        {
+            if ((err==ZIP_OK) && (ldi->filled_in_this_block>0))
+                if (fwrite(ldi->data,(uInt)ldi->filled_in_this_block,
+                                        1,zi->filezip) !=1 )
+                    err = ZIP_ERRNO;
+
+            size_centraldir += ldi->filled_in_this_block;
+            ldi = ldi->next_datablock;
+        }
+    }
+    free_datablock(zi->central_dir.first_block);
+
+    if (err==ZIP_OK) /* Magic End */
+        err = ziplocal_putValue(zi->filezip,(uLong)ENDHEADERMAGIC,4);
+
+    if (err==ZIP_OK) /* number of this disk */
+        err = ziplocal_putValue(zi->filezip,(uLong)0,2);
+
+    if (err==ZIP_OK) /* number of the disk with the start of the central directory */
+        err = ziplocal_putValue(zi->filezip,(uLong)0,2);
+
+    if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
+        err = ziplocal_putValue(zi->filezip,(uLong)zi->number_entry,2);
+
+    if (err==ZIP_OK) /* total number of entries in the central dir */
+        err = ziplocal_putValue(zi->filezip,(uLong)zi->number_entry,2);
+
+    if (err==ZIP_OK) /* size of the central directory */
+        err = ziplocal_putValue(zi->filezip,(uLong)size_centraldir,4);
+
+    if (err==ZIP_OK) /* offset of start of central directory with respect to the 
+                               starting disk number */
+        err = ziplocal_putValue(zi->filezip,(uLong)centraldir_pos_inzip ,4);
+
+    if (err==ZIP_OK) /* zipfile comment length */
+        err = ziplocal_putValue(zi->filezip,(uLong)size_global_comment,2);
+
+    if ((err==ZIP_OK) && (size_global_comment>0))
+        if (fwrite(global_comment,(uInt)size_global_comment,1,zi->filezip) !=1 )
+                err = ZIP_ERRNO;
+    fclose(zi->filezip);
+    TRYFREE(zi);
+
+    return err;
+}
diff --git a/contrib/pk3man/zlib/zip.h b/contrib/pk3man/zlib/zip.h
new file mode 100644 (file)
index 0000000..678260b
--- /dev/null
@@ -0,0 +1,150 @@
+/* zip.h -- IO for compress .zip files using zlib 
+   Version 0.15 alpha, Mar 19th, 1998,
+
+   Copyright (C) 1998 Gilles Vollant
+
+   This unzip package allow creates .ZIP file, compatible with PKZip 2.04g
+     WinZip, InfoZip tools and compatible.
+   Encryption and multi volume ZipFile (span) are not supported.
+   Old compressions used by old PKZip 1.x are not supported
+
+  For uncompress .zip file, look at unzip.h
+
+   THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE
+   CAN CHANGE IN FUTURE VERSION !!
+   I WAIT FEEDBACK at mail info@winimage.com
+   Visit also http://www.winimage.com/zLibDll/zip.htm for evolution
+
+   Condition of use and distribution are the same than zlib :
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+
+*/
+
+/* for more info about .ZIP format, see 
+      ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip
+   PkWare has also a specification at :
+      ftp://ftp.pkware.com/probdesc.zip
+*/
+
+#ifndef _zip_H
+#define _zip_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _ZLIB_H
+#include "zlib.h"
+#endif
+
+#if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
+/* like the STRICT of WIN32, we define a pointer that cannot be converted
+    from (void*) without cast */
+typedef struct TagzipFile__ { int unused; } zipFile__; 
+typedef zipFile__ *zipFile;
+#else
+typedef voidp zipFile;
+#endif
+
+#define ZIP_OK                                  (0)
+#define ZIP_ERRNO               (Z_ERRNO)
+#define ZIP_PARAMERROR                  (-102)
+#define ZIP_INTERNALERROR               (-104)
+
+/* tm_zip contain date/time info */
+typedef struct tm_zip_s 
+{
+       uInt tm_sec;            /* seconds after the minute - [0,59] */
+       uInt tm_min;            /* minutes after the hour - [0,59] */
+       uInt tm_hour;           /* hours since midnight - [0,23] */
+       uInt tm_mday;           /* day of the month - [1,31] */
+       uInt tm_mon;            /* months since January - [0,11] */
+       uInt tm_year;           /* years - [1980..2044] */
+} tm_zip;
+
+typedef struct
+{
+       tm_zip      tmz_date;       /* date in understandable format           */
+    uLong       dosDate;       /* if dos_date == 0, tmu_date is used      */
+/*    uLong       flag;        */   /* general purpose bit flag        2 bytes */
+
+    uLong       internal_fa;    /* internal file attributes        2 bytes */
+    uLong       external_fa;    /* external file attributes        4 bytes */
+} zip_fileinfo;
+
+extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));
+/*
+  Create a zipfile.
+        pathname contain on Windows NT a filename like "c:\\zlib\\zlib111.zip" or on
+          an Unix computer "zlib/zlib111.zip".
+        if the file pathname exist and append=1, the zip will be created at the end
+          of the file. (useful if the file contain a self extractor code)
+        If the zipfile cannot be opened, the return value is NULL.
+     Else, the return value is a zipFile Handle, usable with other function
+          of this zip package.
+
+
+*/
+
+extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
+                                          const char* filename,
+                                          const zip_fileinfo* zipfi,
+                                          const void* extrafield_local,
+                                          uInt size_extrafield_local,
+                                          const void* extrafield_global,
+                                          uInt size_extrafield_global,
+                                          const char* comment,
+                                          int method,
+                                          int level));
+/*
+  Open a file in the ZIP for writing.
+  filename : the filename in zip (if NULL, '-' without quote will be used
+  *zipfi contain supplemental information
+  if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
+    contains the extrafield data the the local header
+  if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
+    contains the extrafield data the the local header
+  if comment != NULL, comment contain the comment string
+  method contain the compression method (0 for store, Z_DEFLATED for deflate)
+  level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
+*/
+
+extern int ZEXPORT zipWriteInFileInZip OF((zipFile file,
+                                          const voidp buf,
+                                          unsigned len));
+/*
+  Write data in the zipfile
+*/
+
+extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
+/*
+  Close the current file in the zipfile
+*/
+
+extern int ZEXPORT zipClose OF((zipFile file,
+                               const char* global_comment));
+/*
+  Close the zipfile
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _zip_H */
diff --git a/contrib/pk3man/zlib/zlib.h b/contrib/pk3man/zlib/zlib.h
new file mode 100644 (file)
index 0000000..49f56b4
--- /dev/null
@@ -0,0 +1,893 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 1.1.3, July 9th, 1998
+
+  Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+
+  The data format used by the zlib library is described by RFCs (Request for
+  Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
+  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef _ZLIB_H
+#define _ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.1.3"
+
+/* 
+     The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed
+  data.  This version of the library supports only one compression method
+  (deflation) but other algorithms will be added later and will have the same
+  stream interface.
+
+     Compression can be done in a single step if the buffers are large
+  enough (for example if an input file is mmap'ed), or can be done by
+  repeated calls of the compression function.  In the latter case, the
+  application must provide more input and/or consume the output
+  (providing more output space) before each call.
+
+     The library also supports reading and writing files in gzip (.gz) format
+  with an interface similar to that of stdio.
+
+     The library does not install any signal handler. The decoder checks
+  the consistency of the compressed data, so the library should never
+  crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    Bytef    *next_in;  /* next input byte */
+    uInt     avail_in;  /* number of bytes available at next_in */
+    uLong    total_in;  /* total nb of input bytes read so far */
+
+    Bytef    *next_out; /* next output byte should be put there */
+    uInt     avail_out; /* remaining free space at next_out */
+    uLong    total_out; /* total nb of bytes output so far */
+
+    char     *msg;      /* last error message, NULL if no error */
+    struct internal_state FAR *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    voidpf     opaque;  /* private data object passed to zalloc and zfree */
+
+    int     data_type;  /* best guess about the data type: ascii or binary */
+    uLong   adler;      /* adler32 value of the uncompressed data */
+    uLong   reserved;   /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+   The application must update next_in and avail_in when avail_in has
+   dropped to zero. It must update next_out and avail_out when avail_out
+   has dropped to zero. The application must initialize zalloc, zfree and
+   opaque before calling the init function. All other fields are set by the
+   compression library and must not be updated by the application.
+
+   The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree. This can be useful for custom
+   memory management. The compression library attaches no meaning to the
+   opaque value.
+
+   zalloc must return Z_NULL if there is not enough memory for the object.
+   If zlib is used in a multi-threaded application, zalloc and zfree must be
+   thread safe.
+
+   On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this
+   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+   pointers returned by zalloc for objects of exactly 65536 bytes *must*
+   have their offset normalized to zero. The default allocation function
+   provided by this library ensures this (see zutil.c). To reduce memory
+   requirements and avoid any allocation of 64K objects, at the expense of
+   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+   The fields total_in and total_out can be used for statistics or
+   progress reports. After compression, total_in holds the total size of
+   the uncompressed data and may be saved for use in the decompressor
+   (particularly if the decompressor wants to decompress everything in
+   a single step).
+*/
+
+                        /* constants */
+
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH    2
+#define Z_FULL_FLUSH    3
+#define Z_FINISH        4
+/* Allowed flush values; see deflate() below for details */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_NEED_DICT     2
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION         0
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_DEFAULT_STRATEGY    0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY   0
+#define Z_ASCII    1
+#define Z_UNKNOWN  2
+/* Possible values of the data_type field */
+
+#define Z_DEFLATED   8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+                        /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+   If the first character differs, the library code actually used is
+   not compatible with the zlib.h header file used by the application.
+   This check is automatically made by deflateInit and inflateInit.
+ */
+
+/* 
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+     Initializes the internal stream state for compression. The fields
+   zalloc, zfree and opaque must be initialized before by the caller.
+   If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+   use default allocation functions.
+
+     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+   1 gives best speed, 9 gives best compression, 0 gives no compression at
+   all (the input data is simply copied a block at a time).
+   Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+   compression (currently equivalent to level 6).
+
+     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+   with the version assumed by the caller (ZLIB_VERSION).
+   msg is set to null if there is no error message.  deflateInit does not
+   perform any compression: this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+    deflate compresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may introduce some
+  output latency (reading input without producing any output) except when
+  forced to flush.
+
+    The detailed semantics are as follows. deflate performs one or both of the
+  following actions:
+
+  - Compress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in and avail_in are updated and
+    processing will resume at this point for the next call of deflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly. This action is forced if the parameter flush is non zero.
+    Forcing flush frequently degrades the compression ratio, so this parameter
+    should be set only when necessary (in interactive applications).
+    Some output may be provided even if flush is not set.
+
+  Before the call of deflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating avail_in or avail_out accordingly; avail_out
+  should never be zero before the call. The application can consume the
+  compressed output when it wants, for example when the output buffer is full
+  (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+  and with zero avail_out, it must be called again after making room in the
+  output buffer because there might be more output pending.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+  flushed to the output buffer and the output is aligned on a byte boundary, so
+  that the decompressor can get all input data available so far. (In particular
+  avail_in is zero after the call if enough output space has been provided
+  before the call.)  Flushing may degrade compression for some compression
+  algorithms and so it should be used only when necessary.
+
+    If flush is set to Z_FULL_FLUSH, all output is flushed as with
+  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+  restart from this point if previous compressed data has been damaged or if
+  random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+  the compression.
+
+    If deflate returns with avail_out == 0, this function must be called again
+  with the same value of the flush parameter and more output space (updated
+  avail_out), until the flush is complete (deflate returns with non-zero
+  avail_out).
+
+    If the parameter flush is set to Z_FINISH, pending input is processed,
+  pending output is flushed and deflate returns with Z_STREAM_END if there
+  was enough output space; if deflate returns with Z_OK, this function must be
+  called again with Z_FINISH and more output space (updated avail_out) but no
+  more input data, until it returns with Z_STREAM_END or an error. After
+  deflate has returned Z_STREAM_END, the only possible operations on the
+  stream are deflateReset or deflateEnd.
+  
+    Z_FINISH can be used immediately after deflateInit if all the compression
+  is to be done in a single step. In this case, avail_out must be at least
+  0.1% larger than avail_in plus 12 bytes.  If deflate does not return
+  Z_STREAM_END, then it must be called again as described above.
+
+    deflate() sets strm->adler to the adler32 checksum of all input read
+  so far (that is, total_in bytes).
+
+    deflate() may update data_type if it can make a good guess about
+  the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
+  binary. This field is only for information purposes and does not affect
+  the compression algorithm in any manner.
+
+    deflate() returns Z_OK if some progress has been made (more input
+  processed or more output produced), Z_STREAM_END if all input has been
+  consumed and all output has been produced (only when flush is set to
+  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+  if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+  (for example avail_in or avail_out was zero).
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+   prematurely (some input or output was discarded). In the error case,
+   msg may be set but then points to a static string (which must not be
+   deallocated).
+*/
+
+
+/* 
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+     Initializes the internal stream state for decompression. The fields
+   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+   the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+   value depends on the compression method), inflateInit determines the
+   compression method from the zlib header and allocates all data structures
+   accordingly; otherwise the allocation will be deferred to the first call of
+   inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+   use default allocation functions.
+
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller.  msg is set to null if there is no error
+   message. inflateInit does not perform any decompression apart from reading
+   the zlib header if present: this will be done by inflate().  (So next_in and
+   avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+    inflate decompresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may some
+  introduce some output latency (reading input without producing any output)
+  except when forced to flush.
+
+  The detailed semantics are as follows. inflate performs one or both of the
+  following actions:
+
+  - Decompress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in is updated and processing
+    will resume at this point for the next call of inflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  inflate() provides as much output as possible, until there
+    is no more input data or no more space in the output buffer (see below
+    about the flush parameter).
+
+  Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating the next_* and avail_* values accordingly.
+  The application can consume the uncompressed output when it wants, for
+  example when the output buffer is full (avail_out == 0), or after each
+  call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+  must be called again after making room in the output buffer because there
+  might be more output pending.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
+  output as possible to the output buffer. The flushing behavior of inflate is
+  not specified for values of the flush parameter other than Z_SYNC_FLUSH
+  and Z_FINISH, but the current implementation actually flushes as much output
+  as possible anyway.
+
+    inflate() should normally be called until it returns Z_STREAM_END or an
+  error. However if all decompression is to be performed in a single step
+  (a single call of inflate), the parameter flush should be set to
+  Z_FINISH. In this case all pending input is processed and all pending
+  output is flushed; avail_out must be large enough to hold all the
+  uncompressed data. (The size of the uncompressed data may have been saved
+  by the compressor for this purpose.) The next operation on this stream must
+  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+  is never required, but can be used to inform inflate that a faster routine
+  may be used for the single inflate() call.
+
+     If a preset dictionary is needed at this point (see inflateSetDictionary
+  below), inflate sets strm-adler to the adler32 checksum of the
+  dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise 
+  it sets strm->adler to the adler32 checksum of all output produced
+  so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
+  an error code as described below. At the end of the stream, inflate()
+  checks that its computed adler32 checksum is equal to that saved by the
+  compressor and returns Z_STREAM_END only if the checksum is correct.
+
+    inflate() returns Z_OK if some progress has been made (more input processed
+  or more output produced), Z_STREAM_END if the end of the compressed data has
+  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+  corrupted (input stream not conforming to the zlib format or incorrect
+  adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
+  (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
+  enough memory, Z_BUF_ERROR if no progress is possible or if there was not
+  enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
+  case, the application may then call inflateSync to look for a good
+  compression block.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+   was inconsistent. In the error case, msg may be set but then points to a
+   static string (which must not be deallocated).
+*/
+
+                        /* Advanced functions */
+
+/*
+    The following functions are needed only in some special applications.
+*/
+
+/*   
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+                                     int  level,
+                                     int  method,
+                                     int  windowBits,
+                                     int  memLevel,
+                                     int  strategy));
+
+     This is another version of deflateInit with more compression options. The
+   fields next_in, zalloc, zfree and opaque must be initialized before by
+   the caller.
+
+     The method parameter is the compression method. It must be Z_DEFLATED in
+   this version of the library.
+
+     The windowBits parameter is the base two logarithm of the window size
+   (the size of the history buffer).  It should be in the range 8..15 for this
+   version of the library. Larger values of this parameter result in better
+   compression at the expense of memory usage. The default value is 15 if
+   deflateInit is used instead.
+
+     The memLevel parameter specifies how much memory should be allocated
+   for the internal compression state. memLevel=1 uses minimum memory but
+   is slow and reduces compression ratio; memLevel=9 uses maximum memory
+   for optimal speed. The default value is 8. See zconf.h for total memory
+   usage as a function of windowBits and memLevel.
+
+     The strategy parameter is used to tune the compression algorithm. Use the
+   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+   filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
+   string match).  Filtered data consists mostly of small values with a
+   somewhat random distribution. In this case, the compression algorithm is
+   tuned to compress them better. The effect of Z_FILTERED is to force more
+   Huffman coding and less string matching; it is somewhat intermediate
+   between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
+   the compression ratio but not the correctness of the compressed output even
+   if it is not set appropriately.
+
+      deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+   method). msg is set to null if there is no error message.  deflateInit2 does
+   not perform any compression: this will be done by deflate().
+*/
+                            
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the compression dictionary from the given byte sequence
+   without producing any compressed output. This function must be called
+   immediately after deflateInit, deflateInit2 or deflateReset, before any
+   call of deflate. The compressor and decompressor must use exactly the same
+   dictionary (see inflateSetDictionary).
+
+     The dictionary should consist of strings (byte sequences) that are likely
+   to be encountered later in the data to be compressed, with the most commonly
+   used strings preferably put towards the end of the dictionary. Using a
+   dictionary is most useful when the data to be compressed is short and can be
+   predicted with good accuracy; the data can then be compressed better than
+   with the default empty dictionary.
+
+     Depending on the size of the compression data structures selected by
+   deflateInit or deflateInit2, a part of the dictionary may in effect be
+   discarded, for example if the dictionary is larger than the window size in
+   deflate or deflate2. Thus the strings most likely to be useful should be
+   put at the end of the dictionary, not at the front.
+
+     Upon return of this function, strm->adler is set to the Adler32 value
+   of the dictionary; the decompressor may later use this value to determine
+   which dictionary has been used by the compressor. (The Adler32 value
+   applies to the whole dictionary even if only a subset of the dictionary is
+   actually used by the compressor.)
+
+     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+   parameter is invalid (such as NULL dictionary) or the stream state is
+   inconsistent (for example if deflate has already been called for this stream
+   or if the compression method is bsort). deflateSetDictionary does not
+   perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when several compression strategies will be
+   tried, for example when there are several ways of pre-processing the input
+   data with a filter. The streams that will be discarded should then be freed
+   by calling deflateEnd.  Note that deflateCopy duplicates the internal
+   compression state which can be quite large, so this strategy is slow and
+   can consume lots of memory.
+
+     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being NULL). msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to deflateEnd followed by deflateInit,
+   but does not free and reallocate all the internal compression state.
+   The stream will keep the same compression level and any other attributes
+   that may have been set by deflateInit2.
+
+      deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+                                     int level,
+                                     int strategy));
+/*
+     Dynamically update the compression level and compression strategy.  The
+   interpretation of level and strategy is as in deflateInit2.  This can be
+   used to switch between compression and straight copy of the input data, or
+   to switch to a different kind of input data requiring a different
+   strategy. If the compression level is changed, the input available so far
+   is compressed with the old level (and may be flushed); the new level will
+   take effect only at the next call of deflate().
+
+     Before the call of deflateParams, the stream state must be set as for
+   a call of deflate(), since the currently available input may have to
+   be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+   if strm->avail_out was zero.
+*/
+
+/*   
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+                                     int  windowBits));
+
+     This is another version of inflateInit with an extra parameter. The
+   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+   before by the caller.
+
+     The windowBits parameter is the base two logarithm of the maximum window
+   size (the size of the history buffer).  It should be in the range 8..15 for
+   this version of the library. The default value is 15 if inflateInit is used
+   instead. If a compressed stream with a larger window size is given as
+   input, inflate() will return with the error code Z_DATA_ERROR instead of
+   trying to allocate a larger window.
+
+      inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
+   memLevel). msg is set to null if there is no error message.  inflateInit2
+   does not perform any decompression apart from reading the zlib header if
+   present: this will be done by inflate(). (So next_in and avail_in may be
+   modified, but next_out and avail_out are unchanged.)
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the decompression dictionary from the given uncompressed byte
+   sequence. This function must be called immediately after a call of inflate
+   if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
+   can be determined from the Adler32 value returned by this call of
+   inflate. The compressor and decompressor must use exactly the same
+   dictionary (see deflateSetDictionary).
+
+     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+   parameter is invalid (such as NULL dictionary) or the stream state is
+   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+   expected one (incorrect Adler32 value). inflateSetDictionary does not
+   perform any decompression: this will be done by subsequent calls of
+   inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/* 
+    Skips invalid compressed data until a full flush point (see above the
+  description of deflate with Z_FULL_FLUSH) can be found, or until all
+  available input is skipped. No output is provided.
+
+    inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+  if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+  case, the application may save the current current value of total_in which
+  indicates where valid compressed data was found. In the error case, the
+  application may repeatedly call inflateSync, providing more input each time,
+  until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to inflateEnd followed by inflateInit,
+   but does not free and reallocate all the internal decompression state.
+   The stream will keep attributes that may have been set by inflateInit2.
+
+      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+
+                        /* utility functions */
+
+/*
+     The following utility functions are implemented on top of the
+   basic stream-oriented functions. To simplify the interface, some
+   default options are assumed (compression level and memory usage,
+   standard memory allocation functions). The source code of these
+   utility functions can easily be modified if you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
+                                 const Bytef *source, uLong sourceLen));
+/*
+     Compresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be at least 0.1% larger than
+   sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
+   compressed buffer.
+     This function can be used to compress a whole file at once if the
+   input file is mmap'ed.
+     compress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
+                                  const Bytef *source, uLong sourceLen,
+                                  int level));
+/*
+     Compresses the source buffer into the destination buffer. The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer. Upon entry, destLen is the total size of the
+   destination buffer, which must be at least 0.1% larger than sourceLen plus
+   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
+                                   const Bytef *source, uLong sourceLen));
+/*
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be large enough to hold the
+   entire uncompressed data. (The size of the uncompressed data must have
+   been saved previously by the compressor and transmitted to the decompressor
+   by some mechanism outside the scope of this compression library.)
+   Upon exit, destLen is the actual size of the compressed buffer.
+     This function can be used to decompress a whole file at once if the
+   input file is mmap'ed.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+
+
+typedef voidp gzFile;
+
+ZEXTERN gzFile ZEXPORT gzopen  OF((const char *path, const char *mode));
+/*
+     Opens a gzip (.gz) file for reading or writing. The mode parameter
+   is as in fopen ("rb" or "wb") but can also include a compression level
+   ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+   Huffman only compression as in "wb1h". (See the description
+   of deflateInit2 for more information about the strategy parameter.)
+
+     gzopen can be used to read a file which is not in gzip format; in this
+   case gzread will directly read from the file without decompression.
+
+     gzopen returns NULL if the file could not be opened or if there was
+   insufficient memory to allocate the (de)compression state; errno
+   can be checked to distinguish the two cases (if errno is zero, the
+   zlib error is Z_MEM_ERROR).  */
+
+ZEXTERN gzFile ZEXPORT gzdopen  OF((int fd, const char *mode));
+/*
+     gzdopen() associates a gzFile with the file descriptor fd.  File
+   descriptors are obtained from calls like open, dup, creat, pipe or
+   fileno (in the file has been previously opened with fopen).
+   The mode parameter is as in gzopen.
+     The next call of gzclose on the returned gzFile will also close the
+   file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+   descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+     gzdopen returns NULL if there was insufficient memory to allocate
+   the (de)compression state.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+     Dynamically update the compression level or strategy. See the description
+   of deflateInit2 for the meaning of these parameters.
+     gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+   opened for writing.
+*/
+
+ZEXTERN int ZEXPORT    gzread  OF((gzFile file, voidp buf, unsigned len));
+/*
+     Reads the given number of uncompressed bytes from the compressed file.
+   If the input file was not in gzip format, gzread copies the given number
+   of bytes into the buffer.
+     gzread returns the number of uncompressed bytes actually read (0 for
+   end of file, -1 for error). */
+
+ZEXTERN int ZEXPORT    gzwrite OF((gzFile file, 
+                                  const voidp buf, unsigned len));
+/*
+     Writes the given number of uncompressed bytes into the compressed file.
+   gzwrite returns the number of uncompressed bytes actually written
+   (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORTVA   gzprintf OF((gzFile file, const char *format, ...));
+/*
+     Converts, formats, and writes the args to the compressed file under
+   control of the format string, as in fprintf. gzprintf returns the number of
+   uncompressed bytes actually written (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+      Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+      gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+      Reads bytes from the compressed file until len-1 characters are read, or
+   a newline character is read and transferred to buf, or an end-of-file
+   condition is encountered.  The string is then terminated with a null
+   character.
+      gzgets returns buf, or Z_NULL in case of error.
+*/
+
+ZEXTERN int ZEXPORT    gzputc OF((gzFile file, int c));
+/*
+      Writes c, converted to an unsigned char, into the compressed file.
+   gzputc returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT    gzgetc OF((gzFile file));
+/*
+      Reads one byte from the compressed file. gzgetc returns this byte
+   or -1 in case of end of file or error.
+*/
+
+ZEXTERN int ZEXPORT    gzflush OF((gzFile file, int flush));
+/*
+     Flushes all pending output into the compressed file. The parameter
+   flush is as in the deflate() function. The return value is the zlib
+   error number (see function gzerror below). gzflush returns Z_OK if
+   the flush parameter is Z_FINISH and all output could be flushed.
+     gzflush should be called only when strictly necessary because it can
+   degrade compression.
+*/
+
+ZEXTERN z_off_t ZEXPORT    gzseek OF((gzFile file,
+                                     z_off_t offset, int whence));
+/* 
+      Sets the starting position for the next gzread or gzwrite on the
+   given compressed file. The offset represents a number of bytes in the
+   uncompressed data stream. The whence parameter is defined as in lseek(2);
+   the value SEEK_END is not supported.
+     If the file is opened for reading, this function is emulated but can be
+   extremely slow. If the file is opened for writing, only forward seeks are
+   supported; gzseek then compresses a sequence of zeroes up to the new
+   starting position.
+
+      gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error, in
+   particular if the file is opened for writing and the new starting position
+   would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
+/*
+     Rewinds the given file. This function is supported only for reading.
+
+   gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
+/*
+     Returns the starting position for the next gzread or gzwrite on the
+   given compressed file. This position represents a number of bytes in the
+   uncompressed data stream.
+
+   gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+     Returns 1 when EOF has previously been detected reading the given
+   input stream, otherwise zero.
+*/
+
+ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
+/*
+     Flushes all pending output if necessary, closes the compressed file
+   and deallocates all the (de)compression state. The return value is the zlib
+   error number (see function gzerror below).
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+     Returns the error message for the last error which occurred on the
+   given compressed file. errnum is set to zlib error number. If an
+   error occurred in the file system and not in the compression library,
+   errnum is set to Z_ERRNO and the application may consult errno
+   to get the exact error code.
+*/
+
+                        /* checksum functions */
+
+/*
+     These functions are not related to compression but are exported
+   anyway because they might be useful in applications using the
+   compression library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum. If buf is NULL, this function returns
+   the required initial value for the checksum.
+   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster. Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
+/*
+     Update a running crc with the bytes buf[0..len-1] and return the updated
+   crc. If buf is NULL, this function returns the required initial value
+   for the crc. Pre- and post-conditioning (one's complement) is performed
+   within this function so it shouldn't be done by the application.
+   Usage example:
+
+     uLong crc = crc32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = crc32(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+*/
+
+
+                        /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
+                                      int windowBits, int memLevel,
+                                      int strategy, const char *version,
+                                      int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
+                                      const char *version, int stream_size));
+#define deflateInit(strm, level) \
+        deflateInit_((strm), (level),       ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+        inflateInit_((strm),                ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+        deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+                      (strategy),           ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+        inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+
+
+#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL)
+    struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+ZEXTERN const char   * ZEXPORT zError           OF((int err));
+ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp z));
+ZEXTERN const uLongf * ZEXPORT get_crc_table    OF((void));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZLIB_H */
diff --git a/contrib/pk3man/zlib/zlib.lib b/contrib/pk3man/zlib/zlib.lib
new file mode 100644 (file)
index 0000000..a03e037
Binary files /dev/null and b/contrib/pk3man/zlib/zlib.lib differ
diff --git a/contrib/pk3man/zlib/zlibd.lib b/contrib/pk3man/zlib/zlibd.lib
new file mode 100644 (file)
index 0000000..4e8915c
Binary files /dev/null and b/contrib/pk3man/zlib/zlibd.lib differ