--- /dev/null
+// 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;
+}
--- /dev/null
+// 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_)
--- /dev/null
+// 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;
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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_)
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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_)
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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_)
--- /dev/null
+//-----------------------------------------------------------------------------
+//
+// $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);
+ }
+}
--- /dev/null
+; 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
--- /dev/null
+// 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
+
+
--- /dev/null
+<?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=""$(SolutionDir)\include";"$(SolutionDir)\libs";"$(SolutionDir)\..\STLPort\stlport";"$(SolutionDir)\..\gtk2\include";"$(SolutionDir)\..\gtk2\include\glib-2.0";"$(SolutionDir)\..\gtk2\lib\glib-2.0\include";"$(SolutionDir)\..\libxml2\include"" 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=""$(SolutionDir)\include";"$(SolutionDir)\libs";"$(SolutionDir)\..\STLPort\stlport";"$(SolutionDir)\..\gtk2\include";"$(SolutionDir)\..\gtk2\include\glib-2.0";"$(SolutionDir)\..\gtk2\lib\glib-2.0\include";"$(SolutionDir)\..\libxml2\include"" 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
--- /dev/null
+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.
+-------------------------------------------------------------------------
+
--- /dev/null
+#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
--- /dev/null
+// 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;
+
+}
--- /dev/null
+// 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_)
--- /dev/null
+// 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
--- /dev/null
+// 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_)
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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_)
--- /dev/null
+// 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);
+}
--- /dev/null
+// 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_)
--- /dev/null
+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
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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 */