From: mattn Date: Tue, 18 Mar 2008 17:11:08 +0000 (+0000) Subject: * added pk3man and fixed it to compile for latest radiant X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=31f39d8b07ff0fe96d8213c157dc8f19177399d7;p=xonotic%2Fnetradiant.git * added pk3man and fixed it to compile for latest radiant * NOTE: Not included in the build chain - doesn't link * NOTE: iepair.h is not used at the moment git-svn-id: https://zerowing.idsoftware.com/svn/radiant/GtkRadiant/branches/ZeroRadiant@225 8a3a26a2-13c4-0310-b231-cf6edde360e5 --- diff --git a/contrib/pk3man/bitmaps/pk3man_tbadd.bmp b/contrib/pk3man/bitmaps/pk3man_tbadd.bmp new file mode 100644 index 00000000..a88ee120 Binary files /dev/null and b/contrib/pk3man/bitmaps/pk3man_tbadd.bmp differ diff --git a/contrib/pk3man/bitmaps/pk3man_tbdelete.bmp b/contrib/pk3man/bitmaps/pk3man_tbdelete.bmp new file mode 100644 index 00000000..a11e0580 Binary files /dev/null and b/contrib/pk3man/bitmaps/pk3man_tbdelete.bmp differ diff --git a/contrib/pk3man/bitmaps/pk3man_tbextract.bmp b/contrib/pk3man/bitmaps/pk3man_tbextract.bmp new file mode 100644 index 00000000..a27214c9 Binary files /dev/null and b/contrib/pk3man/bitmaps/pk3man_tbextract.bmp differ diff --git a/contrib/pk3man/bitmaps/pk3man_tbnew.bmp b/contrib/pk3man/bitmaps/pk3man_tbnew.bmp new file mode 100644 index 00000000..85bb2f16 Binary files /dev/null and b/contrib/pk3man/bitmaps/pk3man_tbnew.bmp differ diff --git a/contrib/pk3man/bitmaps/pk3man_tbopen.bmp b/contrib/pk3man/bitmaps/pk3man_tbopen.bmp new file mode 100644 index 00000000..1f1770c3 Binary files /dev/null and b/contrib/pk3man/bitmaps/pk3man_tbopen.bmp differ diff --git a/contrib/pk3man/bitmaps/pk3man_tbrename.bmp b/contrib/pk3man/bitmaps/pk3man_tbrename.bmp new file mode 100644 index 00000000..0e98175d Binary files /dev/null and b/contrib/pk3man/bitmaps/pk3man_tbrename.bmp differ diff --git a/contrib/pk3man/bitmaps/pk3man_tbsave.bmp b/contrib/pk3man/bitmaps/pk3man_tbsave.bmp new file mode 100644 index 00000000..651afb68 Binary files /dev/null and b/contrib/pk3man/bitmaps/pk3man_tbsave.bmp differ diff --git a/contrib/pk3man/bitmaps/pk3man_tbview.bmp b/contrib/pk3man/bitmaps/pk3man_tbview.bmp new file mode 100644 index 00000000..84eabfaf Binary files /dev/null and b/contrib/pk3man/bitmaps/pk3man_tbview.bmp differ diff --git a/contrib/pk3man/bitmaps/pk3man_tbwizard.bmp b/contrib/pk3man/bitmaps/pk3man_tbwizard.bmp new file mode 100644 index 00000000..036d2aeb Binary files /dev/null and b/contrib/pk3man/bitmaps/pk3man_tbwizard.bmp differ diff --git a/contrib/pk3man/mainwnd.cpp b/contrib/pk3man/mainwnd.cpp new file mode 100644 index 00000000..d8c88a98 --- /dev/null +++ b/contrib/pk3man/mainwnd.cpp @@ -0,0 +1,1581 @@ +// MainWnd.cpp: implementation of the CMainWnd class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "mainwnd.h" +#include "memfile.h" +#include "md3.h" +#include "wild.h" +#include "renamedlg.h" +#ifdef __linux__ +#include +#include +#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::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(-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(-1)) + { + // its a brush + line=GetLine(fp); + line=GetLine(fp); + + if (line.find("patchDef")!=static_cast(-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(-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(-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(-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(-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::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(-1) || tex.find(".jpg")!=static_cast(-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 ; nd_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::iterator i; + + for ( i = paklist.begin() ; i != paklist.end() ; i++) + { + CPak *p=*i; + delete p; + } + + paklist.clear(); +} + +void CMainWnd::DeleteTempFiles() +{ + std::list::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::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 ; c0) + 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::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::const_iterator iEntry = pak.entries.begin() ; iEntry != pak.entries.end() ; iEntry++) + { + pak_entry pe=*iEntry; + + std::string name; + if (pe.rename) + name=pe.newname; + else + name=pe.filename; + + m_Tree.AddPath(name.c_str()); + } + +} + +void CMainWnd::OnExtract() +{ + std::string path=m_Tree.GetSelected(); + + if (path=="") + return; + + pak_entry pe=pak.FindPE((char*)path.c_str()); + + std::string bpath; + if (g_strModPath.GetLength()>0) + bpath=g_strModPath.GetBuffer(); + else + bpath=g_strBasePath.GetBuffer(); + + //char *pathto=dir_dialog("Extract to ...",bpath.c_str()); + gchar *pathto=g_FuncTable.m_pfnDirDialog(m_pMainWnd,"Extract to...",bpath.c_str()); + + if (pathto==NULL) + return; + + long pos=path.find_last_of('/'); + std::string name=path.substr(pos+1); + + std::string cpath=pathto; + cpath+=name; + + if (pe.pakname.compare(pak.m_filename.GetBuffer())==0) + { + // its in pak + pak.ExtractTo((char*)path.c_str(),(char*)cpath.c_str()); + return; + } + +} + +void CMainWnd::OnView() +{ + std::string path=m_Tree.GetSelected(); + + if (path=="") + return; + + pak_entry pe=pak.FindPE(path.c_str()); + + long p=pe.filename.find_last_of('/'); + std::string name=pe.filename.substr(p+1,-1); + std::string temppath=g_strTempPath.GetBuffer()+name; + + if (pe.frompak && pe.pakname.compare(pak.m_filename.GetBuffer())==0) + { + // its in pak + if (!pak.ExtractTo(path.c_str(),(char *)temppath.c_str())) + return; + + temp_files.push_back(temppath); + + // view it + #ifdef WIN32 + HANDLE hInst=ShellExecute(NULL,"open",(LPCTSTR)temppath.c_str(),NULL,NULL,SW_SHOWNORMAL); + #endif + + return; + } + + if (!pe.frompak) + { +#ifdef WIN32 + HANDLE hInst=ShellExecute(NULL,"open",(LPCTSTR)pe.pathname.c_str(),NULL,NULL,SW_SHOWNORMAL); +#endif + return; + } + + if (pe.frompak) + { + CPak p; + if (!p.Open(pe.pakname.c_str())) + return; + + if (!p.ExtractTo(path.c_str(),(char *)temppath.c_str())) + return; + + temp_files.push_back(temppath); + + // view it +#ifdef WIN32 + HANDLE hInst=ShellExecute(NULL,"open",(LPCTSTR)temppath.c_str(),NULL,NULL,SW_SHOWNORMAL); +#endif + return; + } +} + +#ifdef WIN32 +void ShortToLong(CString &thePath) +{ + WIN32_FIND_DATA wfd; + std::string spath=thePath.GetBuffer(); + std::string lpath=""; + while(1) + { + FindFirstFile(spath.c_str(),&wfd); + std::string fname=wfd.cFileName; + lpath=fname+"\\"+lpath; + long pos=spath.find_last_of('\\'); + spath=spath.substr(0,pos); + pos=spath.find_last_of('\\'); + + if (pos==-1) + { + lpath=spath+"\\"+lpath; + break; + } + } + thePath=lpath.c_str(); +} +#endif + +void CMainWnd::GetPaths() +{ +#if 0 //mattn +#ifdef WIN32 + + // convert it to long format + ShortToLong(g_strBasePath); + + // mod path + if (strcmp(mode,"Quake III Team Arena")==0) + { + g_strModPath=g_strBasePath; + long p=g_strModPath.Find("\\baseq3"); + g_strModPath=g_strModPath.Left(p); + g_strModPath+="\\missionpack\\"; + + g_FuncTable.m_pfnQE_ConvertDOSToUnixName ((char *)g_strModPath.GetBuffer(), g_strModPath.GetBuffer()); + } + + g_FuncTable.m_pfnQE_ConvertDOSToUnixName ((char *)g_strBasePath.GetBuffer(), g_strBasePath.GetBuffer()); + + // apppath + // get path to the editor + char* pBuffer = g_strAppPath.GetBufferSetLength(_MAX_PATH + 1); + GetModuleFileName(NULL, pBuffer, _MAX_PATH); + pBuffer[g_strAppPath.ReverseFind('\\') + 1] = '\0'; + g_strAppPath.ReleaseBuffer(); + g_FuncTable.m_pfnQE_ConvertDOSToUnixName ((char *)g_strAppPath.GetBuffer(), g_strAppPath.GetBuffer()); + + char temp_path[_MAX_PATH]; + GetTempPath(_MAX_PATH,temp_path); + g_strTempPath=temp_path; + +#endif + +#ifdef __linux__ + Str tmp; + tmp = g_strBasePath.GetBuffer(); + tmp += "/../"; + + // NOTE: we build g_strAppPath with a '/' (or '\' on WIN32) + // it's a general convention in Radiant to have the slash at the end of directories + char real[PATH_MAX]; + realpath (tmp.GetBuffer(), real); + if (real[strlen(real)-1] != '/') + strcat(real, "/"); + g_strAppPath = real; + + g_strTempPath="~/.tmp"; +#endif + + extern const char *PLUGIN_NAME; + g_strBitmapsPath = g_FuncTable.m_pfnPathForPluginName(PLUGIN_NAME); + g_strBitmapsPath += "bitmaps/"; +#endif +} + +void CMainWnd::UpdateStatus() +{ + std::string path=m_Tree.GetSelected(); + + if (path=="") + { + gtk_label_set_text (GTK_LABEL (m_pStatusLabel[0]), ""); + gtk_label_set_text (GTK_LABEL (m_pStatusLabel[1]), ""); + gtk_label_set_text (GTK_LABEL (m_pStatusLabel[2]), ""); + + return; + } + + pak_entry pe=pak.FindPE(path.c_str()); + + std::string p=path; + long pos=p.find_last_of('/'); + p=p.substr(pos+1); + gtk_label_set_text (GTK_LABEL (m_pStatusLabel[0]), p.c_str()); + + char lbl[255]; + sprintf(lbl," %ldk ",pe.uncompressed/1000); + gtk_label_set_text (GTK_LABEL (m_pStatusLabel[1]), lbl); + + sprintf(lbl," %ldk ",pe.compressed/1000); + gtk_label_set_text (GTK_LABEL (m_pStatusLabel[2]), lbl); + +} + +void CMainWnd::HandleDrop() +{ + std::string path=m_Tree.GetSelected(); + bool file_selected=TRUE; + + if (path=="") + file_selected=FALSE; + + //if (m_mnuDrop == NULL) // first time, load it up + //{ + GtkAccelGroup *accel;//, *menu_in_menu_accel; + GtkWidget *menu;//, *menu_in_menu, *item, *submenu; + + menu = m_mnuDrop = gtk_menu_new (); + accel = gtk_accel_group_new (); + gtk_menu_set_accel_group (GTK_MENU (menu), accel); + + //menu_in_menu = create_menu_in_menu (menu, "Select", accel, &menu_in_menu_accel); + + create_menu_item (menu, "Add file", accel, + GTK_SIGNAL_FUNC (HandleCommand), ID_ADD); + + if (file_selected) + { + create_menu_item (menu, "View File", accel, + GTK_SIGNAL_FUNC (HandleCommand), ID_VIEW); + + create_menu_item (menu, "Extract file", accel, + GTK_SIGNAL_FUNC (HandleCommand), ID_EXTRACT); + + menu_separator (menu); + + create_menu_item (menu, "Rename File", accel, + GTK_SIGNAL_FUNC (HandleCommand), ID_RENAME); + + create_menu_item (menu, "Delete file", accel, + GTK_SIGNAL_FUNC (HandleCommand), ID_DELETE); + } + //} + + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 1, GDK_CURRENT_TIME); +} + + +//////////////////////////////////////////// +// some handy stuff ripped from GtkRadiant +//////////////////////////////////////////// + + +GtkWidget* create_menu_in_menu (GtkWidget *menu, gchar *label, GtkAccelGroup *menu_accel, + GtkAccelGroup **submenu_accel) +{ + GtkWidget *item, *submenu; + guint tmp_key; + + item = gtk_menu_item_new_with_label (""); + tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (item)->child), label); + gtk_widget_add_accelerator (item, "activate_item", menu_accel, tmp_key, 0, (GtkAccelFlags)0); + gtk_widget_show (item); + gtk_container_add (GTK_CONTAINER (menu), item); + + submenu = gtk_menu_new (); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu); + *submenu_accel = gtk_accel_group_new (); + gtk_menu_set_accel_group (GTK_MENU (submenu), *submenu_accel); + + return submenu; +} + +GtkWidget* create_menu_item (GtkWidget *menu, gchar *label, GtkAccelGroup *menu_accel, + GtkSignalFunc func, int id) +{ + GtkWidget *item; + guint tmp_key; + +#ifdef NO_UNDERSCORE + char label_tmp[1024]; + strcpy( label_tmp, label ); + if (char* c = strchr (label_tmp, '_')) + while (*c) + *c++ = *(c+1); + item = gtk_menu_item_new_with_label (label_tmp); +#else + item = gtk_menu_item_new_with_label (""); + tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (item)->child), label); + gtk_widget_add_accelerator (item, "activate_item", menu_accel, tmp_key, 0, (GtkAccelFlags)0); +#endif + gtk_widget_show (item); + gtk_container_add (GTK_CONTAINER (menu), item); + gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (func), GINT_TO_POINTER (id)); + + + return item; +} + +GtkWidget* menu_separator (GtkWidget *menu) +{ + GtkWidget *menu_item = gtk_menu_item_new (); + gtk_menu_append (GTK_MENU (menu), menu_item); + gtk_widget_set_sensitive (menu_item, FALSE); + gtk_widget_show (menu_item); + return menu_item; +} diff --git a/contrib/pk3man/mainwnd.h b/contrib/pk3man/mainwnd.h new file mode 100644 index 00000000..f7cf5dd0 --- /dev/null +++ b/contrib/pk3man/mainwnd.h @@ -0,0 +1,87 @@ +// MainWnd.h: interface for the CMainWnd class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_MAINWND_H__E2FFC5D8_4D6E_4752_8976_811551035B7A__INCLUDED_) +#define AFX_MAINWND_H__E2FFC5D8_4D6E_4752_8976_811551035B7A__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "stdafx.h" +#include "tree.h" +#include "pak.h" + + +//void HandleCommand(GtkWidget *widget, gpointer data); + + +class CMainWnd +{ +public: + CMainWnd(); + virtual ~CMainWnd(); + + GtkWidget* m_pMainWnd; + GtkWidget *m_pStatusLabel[3]; + GtkWidget *m_ScrolledWin; + GtkWidget *m_Toolbar; + + GtkWidget* m_mnuDrop; + + CTree m_Tree; + CPak pak; + + std::list texlist; + std::list paklist; + std::list exclusions; + std::list temp_files; + + BOOL Create(GtkWidget *parent); + BOOL CreateToolbar(GtkWidget *window,GtkWidget *vbox); + BOOL CreateStatusBar(GtkWidget *window,GtkWidget *vbox); + BOOL CreateTreeView(GtkWidget *window,GtkWidget *vbox); + + void GetPaths(); + void UpdateTree(); + void UpdateStatus(); + void UpdateToolBar(); + + void HandleDrop(); + + // command handlers + bool OnFileNew(); + void OnFileOpen(); + void OnFileSave(); + void OnWizard(); + void OnView(); + void OnExtract(); + void OnAdd(); + void OnRename(); + void OnDelete(); + bool OnClose(); + void OnDestroy(); + + bool ProcessFile(const char *name,const char *suffix,const char *folder); + bool ProcessFile(const char *name); + + std::string GetLine(FILE *fp); + void SkipLines(FILE *fp, int n); + void AddToTexList(const char *buf); + bool IsInTexList(const char *tex); + void ParseShader(const char*sname, const char *tex); + std::string TrimString(const char *str); + void ParseModel(const char *pathname); + + void InitPakList(); + void InitPaksInDir(const char *folder); + void FreePakList(); + bool FindInAPk3(const char *name); + + void LoadExclusions(); + bool IsExcluded(const char *name); + void DeleteTempFiles(); +}; + +#endif // !defined(AFX_MAINWND_H__E2FFC5D8_4D6E_4752_8976_811551035B7A__INCLUDED_) diff --git a/contrib/pk3man/md3.h b/contrib/pk3man/md3.h new file mode 100644 index 00000000..805df717 --- /dev/null +++ b/contrib/pk3man/md3.h @@ -0,0 +1,111 @@ +// MD3 file headers + + +typedef struct +{ + char ID[4]; //id of file, always "IDP3" + int Version; //i suspect this is a version + //number, always 15 + char FileName[68]; //sometimes left Blank... + //65 chars, 32bit aligned == + //68 chars + int BoneFrame_num; //number of BoneFrames + int Tag_num; //number of 'tags' per BoneFrame + int Mesh_num; //number of meshes/skins + int MaxSkin_num; //maximum number of unique skins + //used in md3 file + int HeaderLength; //always equal to the length of + //this header + int Tag_Start; //starting position of + //tag-structures + int Tag_End; //ending position of + //tag-structures/starting + //position of mesh-structures + int FileSize; //size of file +} md3_header_t; + + +typedef struct +{ + char Name[64]; //name of 'tag' as it's usually + //called in the md3 files try to + //see it as a sub-mesh/seperate + //mesh-part. + //sometimes this 64 string may + //contain some garbage, but + //i've been told this is because + //some tools leave garbage in + //those strings, but they ARE + //strings... + float Postition[3]; //relative position of tag + float Rotation[3][3]; //the direction the tag is facing relative to the rest of the model +} md3_tag_t; + + +typedef struct +{ + //unverified: + float Mins[3]; + float Maxs[3]; + float Position[3]; + float scale; + char Creator[16]; //i think this is the + //"creator" name.. + //but i'm only guessing. +} md3_boneframe_t; + + +typedef struct +{ + char ID[4]; //id, must be IDP3 + char Name[68]; //name of mesh + //65 chars, + //32 bit aligned == 68 chars + int MeshFrame_num; //number of meshframes + //in mesh + int Skin_num; //number of skins in mesh + int Vertex_num; //number of vertices + int Triangle_num; //number of Triangles + int Triangle_Start; //starting position of + //Triangle data, relative + //to start of Mesh_Header + int HeaderSize; //size of header + int TexVec_Start; //starting position of + //texvector data, relative + //to start of Mesh_Header + int Vertex_Start; //starting position of + //vertex data,relative + //to start of Mesh_Header + int MeshSize; //size of mesh +} md3_mesh_t; + + +typedef struct +{ + char Name[68]; //name of skin used by mesh + //65 chars, + //32 bit aligned == 68 chars +} md3_skin_t; + + +typedef struct +{ + int Triangle[3]; //vertex 1,2,3 of triangle + +} md3_triangles_t; + + +typedef struct +{ + float TexVec[2]; //Texture U/V coordinates of vertex + +} md3_texcoords_t; + + +typedef struct +{ + //!!!important!!! signed! + signed short Vec[3]; //vertex X/Y/Z coordinate + unsigned char EnvTex[2]; //enviromental mapping texture coordinates + +} md3_vertices_t; diff --git a/contrib/pk3man/memfile.cpp b/contrib/pk3man/memfile.cpp new file mode 100644 index 00000000..041781ec --- /dev/null +++ b/contrib/pk3man/memfile.cpp @@ -0,0 +1,36 @@ +// MemFile.cpp: implementation of the CMemFile class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "memfile.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CMemFile::CMemFile() +{ + data=NULL; + ptr=NULL; + end=NULL; +} + +CMemFile::CMemFile(char *block,long len) +{ + data=block; + ptr=block; + end=block+len; +} + + +CMemFile::~CMemFile() +{ + +} + +void CMemFile::Read(void *to,long size) +{ + memcpy(to,ptr,size); + ptr+=size; +} diff --git a/contrib/pk3man/memfile.h b/contrib/pk3man/memfile.h new file mode 100644 index 00000000..15123bd6 --- /dev/null +++ b/contrib/pk3man/memfile.h @@ -0,0 +1,27 @@ +// MemFile.h: interface for the CMemFile class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_MEMFILE_H__FCA4B794_CC06_4F09_8B54_B1BF10291ECA__INCLUDED_) +#define AFX_MEMFILE_H__FCA4B794_CC06_4F09_8B54_B1BF10291ECA__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class CMemFile +{ +public: + CMemFile(); + CMemFile(char *data, long len); + virtual ~CMemFile(); + + char *data; + char *ptr; + char *end; + + void Read(void *to,long size); + +}; + +#endif // !defined(AFX_MEMFILE_H__FCA4B794_CC06_4F09_8B54_B1BF10291ECA__INCLUDED_) diff --git a/contrib/pk3man/pak.cpp b/contrib/pk3man/pak.cpp new file mode 100644 index 00000000..02df3df4 --- /dev/null +++ b/contrib/pk3man/pak.cpp @@ -0,0 +1,421 @@ +// Pak.cpp: implementation of the CPak class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "pak.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CPak::CPak() +{ + m_bModified=FALSE; + +} + +CPak::~CPak() +{ + Close(); +} + + +bool CPak::Open(const char *filename) +{ + Close(); + + unzFile uf=NULL; + + uf = unzOpen(filename); + if (uf==NULL) + return FALSE; + + unz_global_info gi; + int err = unzGetGlobalInfo (uf,&gi); + if (err!=UNZ_OK) + { + Close(); + return FALSE; + } + + m_filename=filename; + + // ok, now build the internal list of entries + + unzGoToFirstFile(uf); + + do + { + pak_entry pe; + + pe.frompak=TRUE; + pe.pakname=m_filename; + pe.rename=FALSE; + + char filename_inzip[256]; + unz_file_info file_info; + // uLong ratio=0; + // const char *string_method; + err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0); + if (err!=UNZ_OK) + { + continue; + } + + pe.filename=filename_inzip; + pe.compressed=file_info.compressed_size; + pe.uncompressed=file_info.uncompressed_size; + + entries.push_back(pe); + + } while (unzGoToNextFile(uf)==UNZ_OK); + + + unzClose(uf); + m_bModified=FALSE; + + return TRUE; +} + +bool CPak::Save(const char *path) +{ + if (!m_bModified) + return FALSE; + + if (path==NULL) + return FALSE; + + // unzFile uf=NULL; + zipFile zf=NULL; + + zf=zipOpen(path,0); + + for ( std::list::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::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::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::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::iterator iEntry = entries.begin() ; iEntry != entries.end() ; iEntry++) + { + pe=*iEntry; + + if ((!pe.rename && pe.filename.compare(path)==0) || (pe.rename && pe.newname.compare(path)==0)) + { + entries.erase(iEntry); + + pe.rename=TRUE; + pe.newname=newname; + + entries.push_back(pe); + m_bModified=TRUE; + + return TRUE; + } + } + + return FALSE; +} diff --git a/contrib/pk3man/pak.h b/contrib/pk3man/pak.h new file mode 100644 index 00000000..f1de00cb --- /dev/null +++ b/contrib/pk3man/pak.h @@ -0,0 +1,74 @@ +// Pak.h: interface for the CPak class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_PAK_H__CB5AFBB6_E37C_4898_AB04_1ABEA6AC9B45__INCLUDED_) +#define AFX_PAK_H__CB5AFBB6_E37C_4898_AB04_1ABEA6AC9B45__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "stdafx.h" + +extern "C" +{ +#include "./zlib/zlib.h" +#include "./zlib/unzip.h" +#include "./zlib/zip.h" +} +#include +#include + +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 entries; + bool m_bModified; + + bool Open(const char *filename); + void Close(); + bool IsModified(); + bool Save(const char *); + bool IsEmpty(); + + pak_entry FindPE(const char *path); + bool IsInPak(const char *path); + + bool AddExternalFile(const char *name,const char *path); + bool AddPakFile(const char *name,const char *pakname,long comp, long uncomp); + bool Delete(const char *path); + bool Rename(const char *path,const char *newname); + + bool ExtractTo(const char *path, char *pathto); + unsigned char *Extract(const char *path, long &size); + +}; + +#endif // !defined(AFX_PAK_H__CB5AFBB6_E37C_4898_AB04_1ABEA6AC9B45__INCLUDED_) diff --git a/contrib/pk3man/pixmap.cpp b/contrib/pk3man/pixmap.cpp new file mode 100644 index 00000000..2ed24b89 --- /dev/null +++ b/contrib/pk3man/pixmap.cpp @@ -0,0 +1,581 @@ +// PixMap.cpp: implementation of the CPixMap class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "pixmap.h" + +#ifdef __linux__ + #include +#else + #include + #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> bit_count) & mask; + + // lookup the color from the colormap - stuff it in our buffer + // swap red and blue + *(outbuf + rowOffset + col * 3 + 2) = colormap[pix].rgbBlue; + *(outbuf + rowOffset + col * 3 + 1) = colormap[pix].rgbGreen; + *(outbuf + rowOffset + col * 3 + 0) = colormap[pix].rgbRed; + } + + // read DWORD padding + while ((m_bytesRead-pixoff)&3) + { + char dummy; + if (fread(&dummy,1,1,fp)!=1) + { + free(imagebits); + if (colormap) + delete [] colormap; + fclose(fp); + return NULL; + } + m_bytesRead++; + } + } + } + } + else + { + int i, x = 0; + unsigned char c, c1 = 0, *pp; + row = 0; + pp = outbuf + (bmHeight-1)*bmWidth*3; + + if (bmBitsPixel == 8) + { + while (row < bmHeight) + { + c = getc(fp); + + if (c) + { + // encoded mode + c1 = getc(fp); + for (i = 0; i < c; x++, i++) + { + *pp = colormap[c1].rgbRed; pp++; + *pp = colormap[c1].rgbGreen; pp++; + *pp = colormap[c1].rgbBlue; pp++; + } + } + else + { + // c==0x00, escape codes + c = getc(fp); + + if (c == 0x00) // end of line + { + row++; + x = 0; + pp = outbuf + (bmHeight-row-1)*bmWidth*3; + } + else if (c == 0x01) + break; // end of pic + else if (c == 0x02) // delta + { + c = getc(fp); + x += c; + c = getc(fp); + row += c; + pp = outbuf + x*3 + (bmHeight-row-1)*bmWidth*3; + } + else // absolute mode + { + for (i = 0; i < c; x++, i++) + { + c1 = getc(fp); + *pp = colormap[c1].rgbRed; pp++; + *pp = colormap[c1].rgbGreen; pp++; + *pp = colormap[c1].rgbBlue; pp++; + } + + if (c & 1) + getc(fp); // odd length run: read an extra pad byte + } + } + } + } + else if (bmBitsPixel == 4) + { + while (row < bmHeight) + { + c = getc(fp); + + if (c) + { + // encoded mode + c1 = getc(fp); + for (i = 0; i < c; x++, i++) + { + *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbRed; pp++; + *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbGreen; pp++; + *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbBlue; pp++; + } + } + else + { + // c==0x00, escape codes + c = getc(fp); + + if (c == 0x00) // end of line + { + row++; + x = 0; + pp = outbuf + (bmHeight-row-1)*bmWidth*3; + } + else if (c == 0x01) + break; // end of pic + else if (c == 0x02) // delta + { + c = getc(fp); + x += c; + c = getc(fp); + row += c; + pp = outbuf + x*3 + (bmHeight-row-1)*bmWidth*3; + } + else // absolute mode + { + for (i = 0; i < c; x++, i++) + { + if ((i&1) == 0) + c1 = getc(fp); + *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbRed; pp++; + *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbGreen; pp++; + *pp = colormap[(i&1) ? (c1 & 0x0f) : ((c1>>4)&0x0f)].rgbBlue; pp++; + } + + if (((c&3) == 1) || ((c&3) == 2)) + getc(fp); // odd length run: read an extra pad byte + } + } + } + } + } + + if (colormap) + delete [] colormap; + + fclose(fp); + } + + return imagebits; +} + +void CPixMap::bmp_to_pixmap (const char* filename, GdkPixmap **pixmap, GdkBitmap **mask) +{ + guint16 width, height; + unsigned char *buf; + GdkWindow *window = GDK_ROOT_PARENT(); + GdkColormap *colormap; + GdkGC* gc = gdk_gc_new (window); + int i, j; + GdkColor c; + + *pixmap = *mask = NULL; + buf = load_bitmap_file (filename, &width, &height); + if (!buf) + return; + + colormap = gdk_window_get_colormap (window); + *pixmap = gdk_pixmap_new (window, width, height, -1); + + typedef struct + { + GdkColor c; + unsigned char *p; + } PAL; + + GPtrArray* pal = g_ptr_array_new (); + GdkColor** col = (GdkColor**)malloc (sizeof (GdkColor*) * height * width); + guint32 k; + + for (i = 0; i < height; i++) + for (j = 0; j < width; j++) + { + unsigned char* p = &buf[(i*width+j)*3]; + + for (k = 0; k < pal->len; k++) + { + PAL *pe = (PAL*)pal->pdata[k]; + if ((pe->p[0] == p[0]) && + (pe->p[1] == p[1]) && + (pe->p[2] == p[2])) + { + col[(i*width+j)] = &pe->c; + break; + } + } + + if (k == pal->len) + { + PAL *pe = (PAL*)malloc (sizeof (PAL)); + + pe->c.red = (gushort)(p[0]*0xFF); + pe->c.green = (gushort)(p[1]*0xFF); + pe->c.blue = (gushort)(p[2]*0xFF); + gdk_color_alloc (colormap, &pe->c); + col[(i*width+j)] = &pe->c; + pe->p = p; + g_ptr_array_add (pal, pe); + } + } + + for (i = 0; i < height; i++) + for (j = 0; j < width; j++) + { + /* + c.red = (gushort)(buf[(i*width+j)*3]*0xFF); + c.green = (gushort)(buf[(i*width+j)*3+1]*0xFF); + c.blue = (gushort)(buf[(i*width+j)*3+2]*0xFF); + gdk_color_alloc (colormap, &c); + gdk_gc_set_foreground(gc, &c); + gdk_draw_point(*pixmap, gc, j, i); + */ + gdk_gc_set_foreground(gc, col[(i*width+j)]); + gdk_draw_point(*pixmap, gc, j, i); + } + + free (col); + for (k = 0; k < pal->len; k++) + free (pal->pdata[k]); + g_ptr_array_free (pal, TRUE); + + gdk_gc_destroy (gc); + *mask = gdk_pixmap_new (window, width, height, 1); + gc = gdk_gc_new (*mask); + + for (i = 0; i < height; i++) + for (j = 0; j < width; j++) + { + GdkColor mask_pattern; + + // pink is transparent + if ((buf[(i*width+j)*3] == 0xff) && + (buf[(i*width+j)*3+1] == 0x00) && + (buf[(i*width+j)*3+2] == 0xff)) + mask_pattern.pixel = 0; + else + mask_pattern.pixel = 1; + + gdk_gc_set_foreground (gc, &mask_pattern); + // possible Win32 Gtk bug here +// gdk_draw_point (*mask, gc, j, i); + gdk_draw_line (*mask, gc, j, i, j + 1, i); + } + + gdk_gc_destroy(gc); + free (buf); +} + +void CPixMap::load_pixmap (const char* filename, GdkPixmap **gdkpixmap, GdkBitmap **mask) +{ + CString str; + + str = g_strBitmapsPath; + str += filename; + bmp_to_pixmap (str.GetBuffer (),gdkpixmap, mask); + + if (*gdkpixmap == NULL) + { + char *dummy[] = { "1 1 1 1", " c None", " " }; + *gdkpixmap = gdk_pixmap_create_from_xpm_d (GDK_ROOT_PARENT(), mask, NULL, dummy); + } +} + +// Load a xpm file and return a pixmap widget. +GtkWidget* CPixMap::new_pixmap (GtkWidget* widget, char* filename) +{ + GdkPixmap *gdkpixmap; + GdkBitmap *mask; + GtkWidget *pixmap; + + load_pixmap (filename, &gdkpixmap, &mask); + pixmap = gtk_pixmap_new (gdkpixmap, mask); + + gdk_pixmap_unref (gdkpixmap); + gdk_pixmap_unref (mask); + + // g_FuncTable.m_pfnLoadBitmap( filename, &pixmap, &mask ) + + return pixmap; +} + +GtkWidget* CPixMap::pixmap_from_char(GtkWidget *window, gchar **xpm_data) +{ + GdkPixmap *pixmap; + GdkBitmap *mask; + GtkStyle *style; + GtkWidget *widget; + + style = gtk_widget_get_style( window ); + pixmap = gdk_pixmap_create_from_xpm_d( window->window, &mask, + &style->bg[GTK_STATE_NORMAL], + (gchar **)xpm_data ); + + widget = gtk_pixmap_new( pixmap, mask ); + + return widget; +} diff --git a/contrib/pk3man/pixmap.h b/contrib/pk3man/pixmap.h new file mode 100644 index 00000000..10acb384 --- /dev/null +++ b/contrib/pk3man/pixmap.h @@ -0,0 +1,28 @@ +// PixMap.h: interface for the CPixMap class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_PIXMAP_H__5B978BDF_7DD1_4BA7_91B5_CCD49AA304AC__INCLUDED_) +#define AFX_PIXMAP_H__5B978BDF_7DD1_4BA7_91B5_CCD49AA304AC__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "stdafx.h" + +class CPixMap +{ +public: + CPixMap(); + virtual ~CPixMap(); + + static void load_pixmap (const char* filename, GdkPixmap **gdkpixmap, GdkBitmap **mask); + static void bmp_to_pixmap (const char* filename, GdkPixmap **pixmap, GdkBitmap **mask); + static unsigned char *load_bitmap_file (const char* filename, guint16* width, guint16* height); + static GtkWidget *new_pixmap (GtkWidget* parent, char* filename); + static GtkWidget* pixmap_from_char(GtkWidget *widget, gchar **xpm_data); + +}; + +#endif // !defined(AFX_PIXMAP_H__5B978BDF_7DD1_4BA7_91B5_CCD49AA304AC__INCLUDED_) diff --git a/contrib/pk3man/pk3man.cpp b/contrib/pk3man/pk3man.cpp new file mode 100644 index 00000000..171462cb --- /dev/null +++ b/contrib/pk3man/pk3man.cpp @@ -0,0 +1,188 @@ +//----------------------------------------------------------------------------- +// +// $LogFile$ +// $Revision: 1.7 $ +// $Author: ttimo $ +// $Date: 2002/05/02 14:41:21 $ +// $Log: pk3man.cpp,v $ +// Revision 1.7 2002/05/02 14:41:21 ttimo +// fixes for 1.2.7 +// +// Revision 1.6 2002/01/27 22:04:06 ttimo +// fixes for linux ver +// +// Revision 1.5 2002/01/21 18:52:24 ttimo +// fixes for 1.2 compile +// +// Revision 1.4 2001/01/24 22:37:19 mickey +// Fixed projects for new radiant layout, +// Changes all file/dir dialogs and messageboxs to use radiant interface. +// +// Revision 1.3 2000/12/22 16:53:28 mickey +// fixed to support TA +// +// Revision 1.2 2000/11/01 14:05:01 lmz +// Linux fixes +// +// Revision 1.1.1.1 2000/10/03 18:36:26 mickey +// initial import +// +// Revision 1.3 2000/10/02 10:22:44 mickey +// added rename dialog and some sanity checks for unsaved/modifed pk3's +// +// Revision 1.2 2000/10/01 20:35:40 mickey +// beta stage +// +// Revision 1.1.1.1 2000/09/26 01:19:38 mickey +// initial import of Gtk module +// +// +// DESCRIPTION: +// main plugin implementation +// texturing tools for Q3Radiant +// + +#include "stdafx.h" +#include "mainwnd.h" + +// plugin interfaces +static bool g_bShaderTableInitDone = false; +_QERShadersTable g_ShadersTable; + +// Radiant function table +_QERFuncTable_1 g_FuncTable; + +bool g_bEpairInitDone = false; +#if 0 //mattn +_QEREpairsTable g_EpairTable; +#endif + +// plugin name +const char *PLUGIN_NAME = "Pk3Man"; + +// commands in the menu +static const char *PLUGIN_COMMANDS = "About...;-;Go..."; + +// globals +GtkWidget *g_pRadiantWnd=NULL; +CMainWnd *g_pMainWnd=NULL; + +CString g_strAppPath; +CString g_strBitmapsPath; +CString g_strBasePath; +CString g_strTempPath; +CString g_strModPath; // are we in TeamArena mode? + +#include "version.h" +static const char *PLUGIN_ABOUT = "Pk3Man for Q3Radiant\n" + "http://pk3man.sourceforge.net\n\n" + "Gtk & Original Version\n" + "by Mike Jackman (mickey@planetquake.com)\n\n" + "Built against GtkRadiant " RADIANT_VERSION "\n" + __DATE__; + +extern "C" LPVOID WINAPI QERPlug_GetFuncTable() +{ + return &g_FuncTable; +} + +extern "C" LPCSTR WINAPI QERPlug_Init(HMODULE hApp, GtkWidget* pMainWidget) +{ + g_pRadiantWnd = pMainWidget; + memset(&g_FuncTable, 0, sizeof(_QERFuncTable_1)); + g_FuncTable.m_nSize = sizeof(_QERFuncTable_1); + + return "Pk3Man for GTKRadiant"; +} + +extern "C" LPCSTR WINAPI QERPlug_GetName() +{ + return (char*)PLUGIN_NAME; +} + +extern "C" LPCSTR WINAPI QERPlug_GetCommandList() +{ + return (char*)PLUGIN_COMMANDS; +} + +char *TranslateString (char *buf) +{ + static char buf2[32768]; + int i, l; + char *out; + + l = strlen(buf); + out = buf2; + for (i=0 ; i(&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(&g_EpairTable) ) ) + g_bEpairInitDone = true; + else + { + Sys_Printf("Pk3Man plugin: _QEREpairsTable interface request failed\n"); + return; + } + } +#endif + + if (!strcmp(p, "About...")) + { + g_FuncTable.m_pfnMessageBox(g_pRadiantWnd,PLUGIN_ABOUT,"About ...",MB_OK, NULL); + } + else if (!strcmp(p, "Go...")) + { + Sys_Printf ("Pk3Man starting ...\n"); + g_pMainWnd = new CMainWnd (); + g_pMainWnd->Create (g_pRadiantWnd); + } +} diff --git a/contrib/pk3man/pk3man.def b/contrib/pk3man/pk3man.def new file mode 100644 index 00000000..3eebeb9c --- /dev/null +++ b/contrib/pk3man/pk3man.def @@ -0,0 +1,12 @@ +; Pk3Man.def : Declares the module parameters for the DLL. + +LIBRARY "Pk3Man" +DESCRIPTION 'Pk3Man Windows Dynamic Link Library' + +EXPORTS + ; Explicit exports can go here + QERPlug_Init @1 + QERPlug_GetName @2 + QERPlug_GetCommandList @3 + QERPlug_Dispatch @4 + QERPlug_GetFuncTable @5 diff --git a/contrib/pk3man/pk3man.exclude b/contrib/pk3man/pk3man.exclude new file mode 100644 index 00000000..87adfbf7 --- /dev/null +++ b/contrib/pk3man/pk3man.exclude @@ -0,0 +1,32 @@ +// pk3man exclusion file +// (c) Mike Jackman 2000 +// +// All files listed below will +// be excluded by the wizzard + + +pak?.pk3 + +scripts/base_door.shader +scripts/base_floor.shader +scripts/base_light.shader +scripts/base_object.shader +scripts/base_support.shader +scripts/base_trim.shader +scripts/base_wall.shader +scripts/common.shader +scripts/ctf.shader +scripts/gothic_block.shader +scripts/gothic_button.shader +scripts/gothic_door.shader +scripts/gothic_floor.shader +scripts/gothic_light.shader +scripts/gothic_trim.shader +scripts/gothic_wall.shader +scripts/liquid.shader +scripts/organics.shader +scripts/sfx.shader +scripts/skin.shader +scripts/sky.shader + + diff --git a/contrib/pk3man/pk3man.vcproj b/contrib/pk3man/pk3man.vcproj new file mode 100644 index 00000000..0ceac05d --- /dev/null +++ b/contrib/pk3man/pk3man.vcproj @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/contrib/pk3man/pk3man_readme.txt b/contrib/pk3man/pk3man_readme.txt new file mode 100644 index 00000000..90da2f68 --- /dev/null +++ b/contrib/pk3man/pk3man_readme.txt @@ -0,0 +1,46 @@ +Pk3Man +------ + +Pk3Man is a plugin for Q3Radiant (GtkEdition). +It allows the creation and editing of Q3 Pk3 files +from within the Q3Radiant Editor. + +It does NOT operate in the same way as WinZip so ill +try to documented the differences here. Please read these +before emailing me with suggestions or problems. + +*************************************************************** + +1. Any modified or newly created Pk3 is only committed to disk, + when you save. + +2. Pk3Man uses your current base folder set in Q3Radiant (ie. BaseQ3) + and adds files using there current path relative to this. This means + that when you have finished your map, you just add the required files, + and their paths are automatically correct (if they were in the correct place for + Q3 to start with) + +4. You can change the stored path of a file using the rename option. Rename + the file with its full new relative path and name. + +5. The wizzard will scan a .map file and add any textures/sounds/env maps e.t.c that + are referenced, except those in the exclusion list. + +6. files that have been added (and not saved) are shown with an appending * in the + statusbar when selected. + +7. The exclusion list applies to Pk3's and to individual files. eg 'pak?.pk3' would + eliminate all ID pk3's, and 'textures/mickey/*.tga' would eliminate all tga's in + a sub folder of textures called 'mickey' + + +************************************************************ + +Please email and bugs/suggestions to me here : mickey@planetquake.com + + +------------------------------------------------------------------------ +Remember this is a beta. I hold no responsibility for any damage done to +files on your computer due to the action of this plugin. +------------------------------------------------------------------------- + diff --git a/contrib/pk3man/pk3str.h b/contrib/pk3man/pk3str.h new file mode 100644 index 00000000..11d7759f --- /dev/null +++ b/contrib/pk3man/pk3str.h @@ -0,0 +1,395 @@ +#ifndef __STR__ +#define __STR__ +// +// class Str +// loose replacement for CString from MFC +// +//#include "cmdlib.h" +//#include +#include +#include + +#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(this)->m_pStr; } + operator void*() { return m_pStr; } + operator char*() { return m_pStr; } + operator const char*(){ return reinterpret_cast(m_pStr); } + operator unsigned char*() { return reinterpret_cast(m_pStr); } + operator const unsigned char*() { return reinterpret_cast(m_pStr); } + Str& operator =(const Str& rhs) + { + if (&rhs != this) + { + delete[] m_pStr; + m_pStr = __StrDup(rhs.m_pStr); + } + return *this; + } + + Str& operator =(const char* pStr) + { + if (m_pStr != pStr) + { + delete[] m_pStr; + m_pStr = __StrDup(pStr); + } + return *this; + } + + Str& operator +=(const char ch) + { + int len = GetLength (); + char *p = new char[len + 1 + 1]; + + if (m_pStr) + { + strcpy(p, m_pStr); + delete[] m_pStr; + } + + m_pStr = p; + m_pStr[len] = ch; + m_pStr[len+1] = '\0'; + + return *this; + } + + Str& operator +=(const char *pStr) + { + if (pStr) + { + if (m_pStr) + { + char *p = new char[strlen(m_pStr) + strlen(pStr) + 1]; + strcpy(p, m_pStr); + strcat(p, pStr); + delete[] m_pStr; + m_pStr = p; + } + else + { + m_pStr = __StrDup(pStr); + } + } + return *this; + } + + bool operator ==(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) == 0 : strcmp(m_pStr, rhs.m_pStr) == 0; } + bool operator ==(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) == 0 : strcmp(m_pStr, pStr) == 0; } + bool operator ==(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) == 0 : strcmp(m_pStr, pStr) == 0; } + bool operator !=(Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) != 0 : strcmp(m_pStr, rhs.m_pStr) != 0; } + bool operator !=(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) != 0 : strcmp(m_pStr, pStr) != 0; } + bool operator !=(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) != 0 : strcmp(m_pStr, pStr) != 0; } + char& operator [](int nIndex) { return m_pStr[nIndex]; } + char& operator [](int nIndex) const { return m_pStr[nIndex]; } + const char GetAt (int nIndex) { return m_pStr[nIndex]; } +}; + +#endif diff --git a/contrib/pk3man/renamedlg.cpp b/contrib/pk3man/renamedlg.cpp new file mode 100644 index 00000000..9851e442 --- /dev/null +++ b/contrib/pk3man/renamedlg.cpp @@ -0,0 +1,113 @@ +// RenameDlg.cpp: implementation of the CRenameDlg class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "renamedlg.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +static void rename_dialog_button_callback (GtkWidget *widget, gpointer data) +{ + GtkWidget *parent; + int *loop, *ret; + + parent = gtk_widget_get_toplevel (widget); + loop = (int*)gtk_object_get_data (GTK_OBJECT (parent), "loop"); + ret = (int*)gtk_object_get_data (GTK_OBJECT (parent), "ret"); + + *loop = 0; + *ret = (int)data; +} + +static gint rename_dialog_delete_callback (GtkWidget *widget, GdkEvent* event, gpointer data) +{ + int *loop; + + gtk_widget_hide (widget); + loop = (int*)gtk_object_get_data (GTK_OBJECT (widget), "loop"); + *loop = 0; + + return TRUE; +} + +CRenameDlg::CRenameDlg() +{ + m_Name="foo"; +} + +CRenameDlg::~CRenameDlg() +{ + +} + +int CRenameDlg::DoModal() +{ + GtkWidget *window, *w, *vbox, *hbox, *edit; + int ret, loop = 1; + char *lpCaption="Rename File"; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_signal_connect (GTK_OBJECT (window), "delete_event", + GTK_SIGNAL_FUNC (rename_dialog_delete_callback), NULL); + gtk_signal_connect (GTK_OBJECT (window), "destroy", + GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL); + gtk_window_set_title (GTK_WINDOW (window), lpCaption); + gtk_container_border_width (GTK_CONTAINER (window), 10); + gtk_object_set_data (GTK_OBJECT (window), "loop", &loop); + gtk_object_set_data (GTK_OBJECT (window), "ret", &ret); + gtk_widget_realize (window); + + vbox = gtk_vbox_new (FALSE, 10); + gtk_container_add (GTK_CONTAINER (window), vbox); + gtk_widget_show (vbox); + + edit = gtk_entry_new (); + gtk_entry_set_text(GTK_ENTRY(edit),m_Name.c_str()); + gtk_box_pack_start (GTK_BOX (vbox), edit, FALSE, FALSE, 2); + gtk_widget_show (edit); + + w = gtk_hseparator_new (); + gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 2); + gtk_widget_show (w); + + hbox = gtk_hbox_new (FALSE, 10); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 2); + gtk_widget_show (hbox); + + // buttons + + w = gtk_button_new_with_label ("Ok"); + gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0); + gtk_signal_connect (GTK_OBJECT (w), "clicked", + GTK_SIGNAL_FUNC (rename_dialog_button_callback), GINT_TO_POINTER (IDOK)); + GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT); + gtk_widget_grab_default (w); + gtk_widget_show (w); + + w = gtk_button_new_with_label ("Cancel"); + gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, TRUE, 0); + gtk_signal_connect (GTK_OBJECT (w), "clicked", + GTK_SIGNAL_FUNC (rename_dialog_button_callback), GINT_TO_POINTER (IDCANCEL)); + gtk_widget_show (w); + ret = IDCANCEL; + + // show it + + gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER); + gtk_widget_show (window); + gtk_grab_add (window); + + while (loop) + gtk_main_iteration (); + + m_Name=gtk_entry_get_text(GTK_ENTRY(edit)); + + gtk_grab_remove (window); + gtk_widget_destroy (window); + + return ret; + +} diff --git a/contrib/pk3man/renamedlg.h b/contrib/pk3man/renamedlg.h new file mode 100644 index 00000000..d76bb9a0 --- /dev/null +++ b/contrib/pk3man/renamedlg.h @@ -0,0 +1,25 @@ +// RenameDlg.h: interface for the CRenameDlg class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_RENAMEDLG_H__6BF675B2_311E_42EE_A926_C52EA685EA75__INCLUDED_) +#define AFX_RENAMEDLG_H__6BF675B2_311E_42EE_A926_C52EA685EA75__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include + +class CRenameDlg +{ +public: + CRenameDlg(); + virtual ~CRenameDlg(); + + std::string m_Name; + + int DoModal(); +}; + +#endif // !defined(AFX_RENAMEDLG_H__6BF675B2_311E_42EE_A926_C52EA685EA75__INCLUDED_) diff --git a/contrib/pk3man/stdafx.cpp b/contrib/pk3man/stdafx.cpp new file mode 100644 index 00000000..0665dede --- /dev/null +++ b/contrib/pk3man/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// pk3man.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/contrib/pk3man/stdafx.h b/contrib/pk3man/stdafx.h new file mode 100644 index 00000000..ff7ff7e1 --- /dev/null +++ b/contrib/pk3man/stdafx.h @@ -0,0 +1,141 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__214D7491_03C8_444D_AAEB_73A8A21B84CB__INCLUDED_) +#define AFX_STDAFX_H__214D7491_03C8_444D_AAEB_73A8A21B84CB__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define GTK_ENABLE_BROKEN + +#include +#include +#include +#include +#include "pk3str.h" +#include "pixmap.h" + +#ifdef __linux__ + +#include + +typedef void* HMODULE; +typedef void* LPVOID; +typedef int BOOL; +typedef char* LPCSTR; + +#define MB_OK 0x00000000L +#define MB_OKCANCEL 0x00000001L +#define MB_ABORTRETRYIGNORE 0x00000002L +#define MB_YESNOCANCEL 0x00000003L +#define MB_YESNO 0x00000004L +#define MB_RETRYCANCEL 0x00000005L + + +#define MB_ICONHAND 0x00000010L +#define MB_ICONQUESTION 0x00000020L +#define MB_ICONEXCLAMATION 0x00000030L +#define MB_ICONASTERISK 0x00000040L + +#define MB_USERICON 0x00000080L +#define MB_ICONWARNING MB_ICONEXCLAMATION +#define MB_ICONERROR MB_ICONHAND +#define MB_ICONINFORMATION MB_ICONASTERISK +#define MB_ICONSTOP MB_ICONHAND + +#define MB_TYPEMASK 0x0000000FL +#define MB_ICONMASK 0x000000F0L +#define MB_DEFMASK 0x00000F00L +#define MB_MODEMASK 0x00003000L +#define MB_MISCMASK 0x0000C000L + +#define IDOK 1 +#define IDCANCEL 2 +#define IDABORT 3 +#define IDRETRY 4 +#define IDIGNORE 5 +#define IDYES 6 +#define IDNO 7 + +#define WINAPI + +#ifndef GUID_DEFINED +#define GUID_DEFINED +typedef struct _GUID +{ + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +} GUID; +#endif + +#if defined(__cplusplus) +#ifndef _REFGUID_DEFINED +#define _REFGUID_DEFINED +#define REFGUID const GUID & +#endif // !_REFGUID_DEFINED +#endif + +typedef struct tagRECT +{ + long left; + long top; + long right; + long bottom; +} RECT, *PRECT, *LPRECT; + +#endif // __linux__ + +#include "qerplugin.h" +#include "igl.h" +#include "iselectedface.h" +#include "isurfaceplugin.h" +#include "ishaders.h" +#if 0 //mattn +#include "iepairs.h" +#endif + +extern _QERFuncTable_1 g_FuncTable; +extern _QERShadersTable g_ShadersTable; +#if 0 //mattn +extern _QEREpairsTable g_EpairTable; +#endif +#define Sys_Printf g_FuncTable.m_pfnSysPrintf +#define Sys_FPrintf g_FuncTable.m_pfnSysFPrintf + +#define CString Str +extern CString g_strBitmapsPath; +extern CString g_strBasePath; +extern CString g_strTempPath; +extern CString g_strAppPath; +extern CString g_strModPath; + + +//extern int DoMessageBox (const char* lpText, const char* lpCaption, guint32 uType); + +#define ID_FILE_OPEN 10000 +#define ID_FILE_SAVE 10001 +#define ID_FILE_NEW 10002 +#define ID_WIZARD 10003 +#define ID_VIEW 10004 +#define ID_EXTRACT 10005 +#define ID_ADD 10006 +#define ID_RENAME 10007 +#define ID_DELETE 10008 +#define ID_SPARE 10009 + +#ifndef __linux__ +#pragma warning(disable : 4786) +#endif + +// TODO: reference additional headers your program requires here + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__214D7491_03C8_444D_AAEB_73A8A21B84CB__INCLUDED_) diff --git a/contrib/pk3man/tree.cpp b/contrib/pk3man/tree.cpp new file mode 100644 index 00000000..c386115e --- /dev/null +++ b/contrib/pk3man/tree.cpp @@ -0,0 +1,271 @@ +// tree.cpp: implementation of the CTree class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "tree.h" +#include +#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 ; cdata)); + + // check item for equality with the folder + // and weather it has a tree attached + + if (GTK_TREE_ITEM_SUBTREE(tree_item)) + { + GtkItem *item=GTK_ITEM(tree_item); + + GList *item_children=gtk_container_children(GTK_CONTAINER(item)); + + GtkLabel *label=GTK_LABEL(item_children->data); + + if (strcmp(label->label,buff)==0) + { + g_list_free(item_children); + g_list_free(children); + + // return tree attached to the item + return GTK_TREE_ITEM_SUBTREE(tree_item); + } + + g_list_free(item_children); + } + + children = g_list_remove_link (children, children); + } + + g_list_free(children); + + // ok, not found so we add it + GtkWidget *item=gtk_tree_item_new_with_label(buff); + gtk_tree_append(GTK_TREE(node),item); + gtk_widget_show(item); + + GtkWidget *tree=gtk_tree_new(); + gtk_tree_item_set_subtree(GTK_TREE_ITEM(item),tree); + gtk_widget_set_name(tree,buff); + + gtk_signal_connect (GTK_OBJECT(tree), "select_child", + GTK_SIGNAL_FUNC(cb_select_child), tree); + + gtk_signal_connect (GTK_OBJECT (item), "button_release_event",GTK_SIGNAL_FUNC (button_release), NULL); + + + //gtk_signal_connect (GTK_OBJECT(tree), "selection_changed", + // GTK_SIGNAL_FUNC(cb_selection_changed), tree, this); + + return tree; +} + + +std::string CTree::GetFullPath(GtkWidget *child) +{ + std::string path; + gchar *name; + + GtkLabel *label = GTK_LABEL (GTK_BIN (child)->child); + gtk_label_get (label, &name); + path=name; + + if (path.compare("root")==0) + return "root"; + + while (1) + { + // this gets an items parent tree + GtkWidget *tr=(child->parent); + + if (GTK_WIDGET(tr)==m_Root) + break; + + // and now its item + child=GTK_TREE(tr)->tree_owner; + + // and now the items label + label = GTK_LABEL (GTK_BIN (child)->child); + gtk_label_get (label, &name); + std::string lbl=name; + path=lbl+"/"+path; + } + + return path; +} + +void CTree::RemovePath(const char *path) +{ + // not used yet +} + + +void CTree::SelectChild(GtkWidget *child) +{ + g_pMainWnd->UpdateStatus(); + g_pMainWnd->UpdateToolBar(); +} + +void cb_select_child (GtkWidget *root_tree, GtkWidget *child, GtkWidget *subtree) +{ + g_pMainWnd->m_Tree.SelectChild(child); +} + + +std::string CTree::GetSelected() +{ + std::string path=""; + + if (!GTK_TREE(m_Tree)->selection) + return path; + + GList *selected = (GTK_TREE(m_Tree)->selection); + + GtkWidget *item=GTK_WIDGET(selected->data); + + if (GTK_TREE_ITEM(item)->subtree) + return path; + + path=GetFullPath(item); + + return path; +} diff --git a/contrib/pk3man/tree.h b/contrib/pk3man/tree.h new file mode 100644 index 00000000..3e50618c --- /dev/null +++ b/contrib/pk3man/tree.h @@ -0,0 +1,41 @@ +// Tree.h: interface for the CTree class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_TREE_H__C0DDC824_48DF_4A80_B393_83FF736FCB98__INCLUDED_) +#define AFX_TREE_H__C0DDC824_48DF_4A80_B393_83FF736FCB98__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "stdafx.h" +#include + +void cb_select_child (GtkWidget *root_tree, GtkWidget *child, GtkWidget *subtree); + +class CTree +{ +public: + CTree(); + virtual ~CTree(); + + GtkWidget *m_pMainWnd; + GtkWidget *m_Tree; + GtkWidget *m_Root; + + void Init(GtkWidget *win); + void AddPath(const char *path); + void AddFile(const char *file,GtkWidget *node=NULL); + GtkWidget *AddFolder(const char *folder, GtkWidget *node=NULL); + void RemovePath(const char*path); + + void SelectChild(GtkWidget *child); + std::string GetSelected(); + std::string GetFullPath(GtkWidget *item); + + void Clear(); + +}; + +#endif // !defined(AFX_TREE_H__C0DDC824_48DF_4A80_B393_83FF736FCB98__INCLUDED_) diff --git a/contrib/pk3man/wild.cpp b/contrib/pk3man/wild.cpp new file mode 100644 index 00000000..2b6a9293 --- /dev/null +++ b/contrib/pk3man/wild.cpp @@ -0,0 +1,338 @@ +// Wild.cpp: implementation of the CWild class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +//#include "pakman.h" +#include "wild.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CWild::CWild() +{ + +} + +CWild::~CWild() +{ + +} + +int CWild::fpattern_isvalid(const char *pat) +{ + int len; + + /* Check args */ + if (pat == NULL) + return (FALSE); + + /* Verify that the pattern is valid */ + for (len = 0; pat[len] != '\0'; len++) + { + switch (pat[len]) + { + case FPAT_SET_L: + /* Char set */ + len++; + if (pat[len] == FPAT_SET_NOT) + len++; /* Set negation */ + + while (pat[len] != FPAT_SET_R) + { + if (pat[len] == QUOTE) + len++; /* Quoted char */ + if (pat[len] == '\0') + return (FALSE); /* Missing closing bracket */ + len++; + + if (pat[len] == FPAT_SET_THRU) + { + /* Char range */ + len++; + if (pat[len] == QUOTE) + len++; /* Quoted char */ + if (pat[len] == '\0') + return (FALSE); /* Missing closing bracket */ + len++; + } + + if (pat[len] == '\0') + return (FALSE); /* Missing closing bracket */ + } + break; + + case QUOTE: + /* Quoted char */ + len++; + if (pat[len] == '\0') + return (FALSE); /* Missing quoted char */ + break; + + case FPAT_NOT: + /* Negated pattern */ + len++; + if (pat[len] == '\0') + return (FALSE); /* Missing subpattern */ + break; + + default: + /* Valid character */ + break; + } + } + + return (TRUE); +} + + +int CWild::fpattern_submatch(const char *pat, const char *fname) +{ + int fch; + int pch; + int i; + int yes, match; + int lo, hi; + + /* Attempt to match subpattern against subfilename */ + while (*pat != '\0') + { + fch = *fname; + pch = *pat; + pat++; + + switch (pch) + { + case FPAT_ANY: + /* Match a single char */ + if (fch == DEL || fch == DEL2 || fch == '\0') + return (FALSE); + fname++; + break; + + case FPAT_CLOS: + /* Match zero or more chars */ + i = 0; + while (fname[i] != '\0')// && fname[i] != DEL && fname[i] != DEL2) + i++; + + while (i >= 0) + { + if (fpattern_submatch(pat, fname+i)) + return (TRUE); + i--; + } + return (FALSE); + + case SUB: + /* Match zero or more chars */ + i = 0; + while (fname[i] != '\0' && fname[i] != DEL && fname[i] != DEL2 && fname[i] != '.') + i++; + while (i >= 0) + { + if (fpattern_submatch(pat, fname+i)) + return (TRUE); + i--; + } + return (FALSE); + + case QUOTE: + /* Match a quoted char */ + pch = *pat; + if (lowercase(fch) != lowercase(pch) || pch == '\0') + return (FALSE); + fname++; + pat++; + break; + + case FPAT_SET_L: + /* Match char set/range */ + yes = TRUE; + if (*pat == FPAT_SET_NOT) + { + pat++; + yes = FALSE; /* Set negation */ + } + + /* Look for [s], [-], [abc], [a-c] */ + match = !yes; + while (*pat != FPAT_SET_R && *pat != '\0') + { + if (*pat == QUOTE) + pat++; /* Quoted char */ + + if (*pat == '\0') + break; + lo = *pat++; + hi = lo; + + if (*pat == FPAT_SET_THRU) + { + /* Range */ + pat++; + + if (*pat == QUOTE) + pat++; /* Quoted char */ + + if (*pat == '\0') + break; + hi = *pat++; + } + + if (*pat == '\0') + break; + + /* Compare character to set range */ + if (lowercase(fch) >= lowercase(lo) && + lowercase(fch) <= lowercase(hi)) + match = yes; + } + + if (!match) + return (FALSE); + + if (*pat == '\0') + return (FALSE); /* Missing closing bracket */ + + fname++; + pat++; + break; + + case FPAT_NOT: + /* Match only if rest of pattern does not match */ + if (*pat == '\0') + return (FALSE); /* Missing subpattern */ + i = fpattern_submatch(pat, fname); + return !i; + + + case DEL: + case DEL2: + + /* Match path delimiter char */ + if (fch != DEL && fch != DEL2) + return (FALSE); + fname++; + break; + + default: + /* Match a (non-null) char exactly */ + if (lowercase(fch) != lowercase(pch)) + return (FALSE); + fname++; + break; + } + } + + /* Check for complete match */ + if (*fname != '\0') + return (FALSE); + + /* Successful match */ + return (TRUE); +} + + +/*----------------------------------------------------------------------------- +* fpattern_match() +* Attempts to match pattern 'pat' to filename 'fname'. +* +* Returns +* 1 (true) if the filename matches, otherwise 0 (false). +* +* Caveats +* If 'fname' is null, zero (false) is returned. +* +* If 'pat' is null, zero (false) is returned. +* +* If 'pat' is empty (""), the only filename it matches is the empty +* string (""). +* +* If 'fname' is empty, the only pattern that will match it is the empty +* string (""). +* +* If 'pat' is not a well-formed pattern, zero (false) is returned. +* +* Upper and lower case letters are treated the same; alphabetic +* characters are converted to lower case before matching occurs. +* Conversion to lower case is dependent upon the current locale setting. +*/ + +int CWild::fpattern_match(const char *pat, const char *fname) +{ + int rc; + + /* Check args */ + if (fname == NULL) + return (FALSE); + + if (pat == NULL) + return (FALSE); + + /* Verify that the pattern is valid, and get its length */ + if (!fpattern_isvalid(pat)) + return (FALSE); + + /* Attempt to match pattern against filename */ + if (fname[0] == '\0') + return (pat[0] == '\0'); /* Special case */ + rc = fpattern_submatch(pat, fname); + + return (rc); +} + + +/*----------------------------------------------------------------------------- +* fpattern_matchn() +* Attempts to match pattern 'pat' to filename 'fname'. +* This operates like fpattern_match() except that it does not verify that +* pattern 'pat' is well-formed, assuming that it has been checked by a +* prior call to fpattern_isvalid(). +* +* Returns +* 1 (true) if the filename matches, otherwise 0 (false). +* +* Caveats +* If 'fname' is null, zero (false) is returned. +* +* If 'pat' is null, zero (false) is returned. +* +* If 'pat' is empty (""), the only filename it matches is the empty ("") +* string. +* +* If 'pat' is not a well-formed pattern, unpredictable results may occur. +* +* Upper and lower case letters are treated the same; alphabetic +* characters are converted to lower case before matching occurs. +* Conversion to lower case is dependent upon the current locale setting. +* +* See also +* fpattern_match(). +*/ + +int CWild::fpattern_matchn(const char *pat, const char *fname) +{ + int rc; + + /* Check args */ + if (fname == NULL) + return (FALSE); + + if (pat == NULL) + return (FALSE); + + /* Assume that pattern is well-formed */ + + /* Attempt to match pattern against filename */ + rc = fpattern_submatch(pat, fname); + + return (rc); +} diff --git a/contrib/pk3man/wild.h b/contrib/pk3man/wild.h new file mode 100644 index 00000000..4c56bd82 --- /dev/null +++ b/contrib/pk3man/wild.h @@ -0,0 +1,47 @@ +// Wild.h: interface for the CWild class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_WILD_H__DC88A1E2_A432_40DE_A5B2_D8EF34272EFC__INCLUDED_) +#define AFX_WILD_H__DC88A1E2_A432_40DE_A5B2_D8EF34272EFC__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define FPAT_QUOTE '\\' /* Quotes a special char */ +#define FPAT_QUOTE2 '`' /* Quotes a special char */ +#define FPAT_DEL '/' /* Path delimiter */ +#define FPAT_DEL2 '\\' /* Path delimiter */ +#define FPAT_DOT '.' /* Dot char */ +#define FPAT_NOT '!' /* Exclusion */ +#define FPAT_ANY '?' /* Any one char */ +#define FPAT_CLOS '*' /* Zero or more chars */ +#define FPAT_CLOSP '\x1A' /* Zero or more nondelimiters */ +#define FPAT_SET_L '[' /* Set/range open bracket */ +#define FPAT_SET_R ']' /* Set/range close bracket */ +#define FPAT_SET_NOT '!' /* Set exclusion */ +#define FPAT_SET_THRU '-' /* Set range of chars */ + +#define DEL FPAT_DEL +#define DEL2 FPAT_DEL2 +#define QUOTE FPAT_QUOTE2 +#define SUB FPAT_CLOSP + +/* Local function macros */ +#define lowercase(c) tolower(c) + +class CWild +{ +public: + CWild(); + virtual ~CWild(); + + static int fpattern_submatch(const char *pat, const char *fname); + static int fpattern_isvalid(const char *pat); + static int fpattern_match(const char *pat, const char *fname); + static int fpattern_matchn(const char *pat, const char *fname); + +}; + +#endif // !defined(AFX_WILD_H__DC88A1E2_A432_40DE_A5B2_D8EF34272EFC__INCLUDED_) diff --git a/contrib/pk3man/zlib/README.linux b/contrib/pk3man/zlib/README.linux new file mode 100644 index 00000000..fbe5a8fc --- /dev/null +++ b/contrib/pk3man/zlib/README.linux @@ -0,0 +1,13 @@ +Precompiled stuff for zip/unzip on linux is in libz-zip.a +Based on zlib + minizip package +The zip.c and unzip.c files will not build out of the box on linux +they are only relevant to the windows version + +How to rebuild libz-zip.a: +download zlib from: http://www.info-zip.org/pub/infozip/zlib/zlib.html +patch the contrib/minizip code with http://www.winimage.com/zLibDll/unzip.html + (I had to replace zip.c by a newer one) +build everything, zlib.a zip.o and unzip.o + +ar -rs libz.a zip.o unzip.o +mv libz.a libz-zip.a diff --git a/contrib/pk3man/zlib/libz-zip.a b/contrib/pk3man/zlib/libz-zip.a new file mode 100644 index 00000000..6c28723a Binary files /dev/null and b/contrib/pk3man/zlib/libz-zip.a differ diff --git a/contrib/pk3man/zlib/unzip.c b/contrib/pk3man/zlib/unzip.c new file mode 100644 index 00000000..ff71a474 --- /dev/null +++ b/contrib/pk3man/zlib/unzip.c @@ -0,0 +1,1294 @@ +/* unzip.c -- IO on .zip files using zlib + Version 0.15 beta, Mar 19th, 1998, + + Read unzip.h for more info +*/ + + +#include +#include +#include +#include "zlib.h" +#include "unzip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#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 (c1c2) + 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 (uBackReaduMaxBack) + 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_pospfile_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_filename0) && (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_extrafile,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_commentfile,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_compressedrest_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;istream.next_out+i) = + *(pfile_in_zip_read_info->stream.next_in+i); + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else + { + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + if (err==Z_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +extern z_off_t ZEXPORT unztell (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +extern int ZEXPORT unzeof (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field that can be read + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ +extern int ZEXPORT unzGetLocalExtrafield (file,buf,len) + unzFile file; + voidp buf; + unsigned len; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uInt read_now; + uLong size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf==NULL) + return (int)size_to_read; + + if (len>size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len ; + + if (read_now==0) + return 0; + + if (fseek(pfile_in_zip_read_info->file, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0) + return UNZ_ERRNO; + + if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzipOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +extern int ZEXPORT unzCloseCurrentFile (file) + unzFile file; +{ + int err=UNZ_OK; + + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised) + inflateEnd(&pfile_in_zip_read_info->stream); + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + return err; +} + + +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ +extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) + unzFile file; + char *szComment; + uLong uSizeBuf; +{ + int err=UNZ_OK; + unz_s* s; + uLong uReadThis ; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (fread(szComment,(uInt)uReadThis,1,s->file)!=1) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} diff --git a/contrib/pk3man/zlib/unzip.h b/contrib/pk3man/zlib/unzip.h new file mode 100644 index 00000000..76692cb7 --- /dev/null +++ b/contrib/pk3man/zlib/unzip.h @@ -0,0 +1,275 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 0.15 beta, Mar 19th, 1998, + + Copyright (C) 1998 Gilles Vollant + + This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + Encryption and multi volume ZipFile (span) are not supported. + Old compressions used by old PKZip 1.x are not supported + + THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE + CAN CHANGE IN FUTURE VERSION !! + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ +/* for more info about .ZIP format, see + ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip */ + +#ifndef _unz_H +#define _unz_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer + "zlib/zlib111.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +extern int ZEXPORT unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _unz_H */ diff --git a/contrib/pk3man/zlib/zconf.h b/contrib/pk3man/zlib/zconf.h new file mode 100644 index 00000000..6a8f33a7 --- /dev/null +++ b/contrib/pk3man/zlib/zconf.h @@ -0,0 +1,279 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.h,v 1.1.1.1 2000/10/03 18:36:29 mickey Exp $ */ + +#ifndef _ZCONF_H +#define _ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) +# ifndef __32BIT__ +# define __32BIT__ +# endif +#endif +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#if defined(MSDOS) && !defined(__32BIT__) +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) +# define STDC +#endif +#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) +# ifndef STDC +# define STDC +# endif +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Old Borland C incorrectly complains about missing returns: */ +#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) +# define NEED_DUMMY_RETURN +#endif + + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +#endif +#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) +# ifndef __32BIT__ +# define SMALL_MEDIUM +# define FAR _far +# endif +#endif + +/* Compile with -DZLIB_DLL for Windows DLL support */ +#if defined(ZLIB_DLL) +# if defined(_WINDOWS) || defined(WINDOWS) +# ifdef FAR +# undef FAR +# endif +# include +# 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 +# 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 /* for off_t */ +# include /* for SEEK_* and off_t */ +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(inflate_blocks,"INBL") +# pragma map(inflate_blocks_new,"INBLNE") +# pragma map(inflate_blocks_free,"INBLFR") +# pragma map(inflate_blocks_reset,"INBLRE") +# pragma map(inflate_codes_free,"INCOFR") +# pragma map(inflate_codes,"INCO") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_flush,"INFLU") +# pragma map(inflate_mask,"INMA") +# pragma map(inflate_set_dictionary,"INSEDI2") +# pragma map(inflate_copyright,"INCOPY") +# pragma map(inflate_trees_bits,"INTRBI") +# pragma map(inflate_trees_dynamic,"INTRDY") +# pragma map(inflate_trees_fixed,"INTRFI") +# pragma map(inflate_trees_free,"INTRFR") +#endif + +#endif /* _ZCONF_H */ diff --git a/contrib/pk3man/zlib/zip.c b/contrib/pk3man/zlib/zip.c new file mode 100644 index 00000000..4942d0fc --- /dev/null +++ b/contrib/pk3man/zlib/zip.c @@ -0,0 +1,720 @@ +/* zip.c -- IO on .zip files using zlib + Version 0.15 beta, Mar 19th, 1998, + + Read zip.h for more info +*/ + + +#include +#include +#include +#include "zlib.h" +#include "zip.h" + +# define DEF_MEM_LEVEL 8 + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#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;ifilled_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;ici.central_header+SIZECENTRALHEADER+i) = *(filename+i); + + for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+i) = + *(((const char*)extrafield_global)+i); + + for (i=0;ici.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;ici.stream.next_out)+i) = + *(((const char*)zi->ci.stream.next_in)+i); + { + zi->ci.stream.avail_in -= copy_this; + zi->ci.stream.avail_out-= copy_this; + zi->ci.stream.next_in+= copy_this; + zi->ci.stream.next_out+= copy_this; + zi->ci.stream.total_in+= copy_this; + zi->ci.stream.total_out+= copy_this; + zi->ci.pos_in_buffered_data += copy_this; + } + } + } + + return 0; +} + +extern int ZEXPORT zipCloseFileInZip (file) + zipFile file; +{ + zip_internal* zi; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + zi->ci.stream.avail_in = 0; + + if (zi->ci.method == Z_DEFLATED) + while (err==ZIP_OK) + { + uLong uTotalOutBefore; + if (zi->ci.stream.avail_out == 0) + { + if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip) + !=1) + err = ZIP_ERRNO; + zi->ci.pos_in_buffered_data = 0; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_FINISH); + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + } + + if (err==Z_STREAM_END) + err=ZIP_OK; /* this is normal */ + + if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) + if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip) + !=1) + err = ZIP_ERRNO; + + if ((zi->ci.method == Z_DEFLATED) && (err==ZIP_OK)) + { + err=deflateEnd(&zi->ci.stream); + zi->ci.stream_initialised = 0; + } + + ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)zi->ci.crc32,4); /*crc*/ + ziplocal_putValue_inmemory(zi->ci.central_header+20, + (uLong)zi->ci.stream.total_out,4); /*compr size*/ + ziplocal_putValue_inmemory(zi->ci.central_header+24, + (uLong)zi->ci.stream.total_in,4); /*uncompr size*/ + + if (err==ZIP_OK) + err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header, + (uLong)zi->ci.size_centralheader); + free(zi->ci.central_header); + + if (err==ZIP_OK) + { + long cur_pos_inzip = ftell(zi->filezip); + if (fseek(zi->filezip, + zi->ci.pos_local_header + 14,SEEK_SET)!=0) + err = ZIP_ERRNO; + + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.crc32,4); /* crc 32, unknown */ + + if (err==ZIP_OK) /* compressed size, unknown */ + err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.stream.total_out,4); + + if (err==ZIP_OK) /* uncompressed size, unknown */ + err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.stream.total_in,4); + + if (fseek(zi->filezip, + cur_pos_inzip,SEEK_SET)!=0) + err = ZIP_ERRNO; + } + + zi->number_entry ++; + zi->in_opened_file_inzip = 0; + + return err; +} + +extern int ZEXPORT zipClose (file, global_comment) + zipFile file; + const char* global_comment; +{ + zip_internal* zi; + int err = 0; + uLong size_centraldir = 0; + uLong centraldir_pos_inzip ; + uInt size_global_comment; + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + } + + if (global_comment==NULL) + size_global_comment = 0; + else + size_global_comment = strlen(global_comment); + + + centraldir_pos_inzip = ftell(zi->filezip); + if (err==ZIP_OK) + { + linkedlist_datablock_internal* ldi = zi->central_dir.first_block ; + while (ldi!=NULL) + { + if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) + if (fwrite(ldi->data,(uInt)ldi->filled_in_this_block, + 1,zi->filezip) !=1 ) + err = ZIP_ERRNO; + + size_centraldir += ldi->filled_in_this_block; + ldi = ldi->next_datablock; + } + } + free_datablock(zi->central_dir.first_block); + + if (err==ZIP_OK) /* Magic End */ + err = ziplocal_putValue(zi->filezip,(uLong)ENDHEADERMAGIC,4); + + if (err==ZIP_OK) /* number of this disk */ + err = ziplocal_putValue(zi->filezip,(uLong)0,2); + + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = ziplocal_putValue(zi->filezip,(uLong)0,2); + + if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ + err = ziplocal_putValue(zi->filezip,(uLong)zi->number_entry,2); + + if (err==ZIP_OK) /* total number of entries in the central dir */ + err = ziplocal_putValue(zi->filezip,(uLong)zi->number_entry,2); + + if (err==ZIP_OK) /* size of the central directory */ + err = ziplocal_putValue(zi->filezip,(uLong)size_centraldir,4); + + if (err==ZIP_OK) /* offset of start of central directory with respect to the + starting disk number */ + err = ziplocal_putValue(zi->filezip,(uLong)centraldir_pos_inzip ,4); + + if (err==ZIP_OK) /* zipfile comment length */ + err = ziplocal_putValue(zi->filezip,(uLong)size_global_comment,2); + + if ((err==ZIP_OK) && (size_global_comment>0)) + if (fwrite(global_comment,(uInt)size_global_comment,1,zi->filezip) !=1 ) + err = ZIP_ERRNO; + fclose(zi->filezip); + TRYFREE(zi); + + return err; +} diff --git a/contrib/pk3man/zlib/zip.h b/contrib/pk3man/zlib/zip.h new file mode 100644 index 00000000..678260b3 --- /dev/null +++ b/contrib/pk3man/zlib/zip.h @@ -0,0 +1,150 @@ +/* zip.h -- IO for compress .zip files using zlib + Version 0.15 alpha, Mar 19th, 1998, + + Copyright (C) 1998 Gilles Vollant + + This unzip package allow creates .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + Encryption and multi volume ZipFile (span) are not supported. + Old compressions used by old PKZip 1.x are not supported + + For uncompress .zip file, look at unzip.h + + THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE + CAN CHANGE IN FUTURE VERSION !! + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/zip.htm for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ + +/* for more info about .ZIP format, see + ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip +*/ + +#ifndef _zip_H +#define _zip_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#if defined(STRICTZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagzipFile__ { int unused; } zipFile__; +typedef zipFile__ *zipFile; +#else +typedef voidp zipFile; +#endif + +#define ZIP_OK (0) +#define ZIP_ERRNO (Z_ERRNO) +#define ZIP_PARAMERROR (-102) +#define ZIP_INTERNALERROR (-104) + +/* tm_zip contain date/time info */ +typedef struct tm_zip_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_zip; + +typedef struct +{ + tm_zip tmz_date; /* date in understandable format */ + uLong dosDate; /* if dos_date == 0, tmu_date is used */ +/* uLong flag; */ /* general purpose bit flag 2 bytes */ + + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ +} zip_fileinfo; + +extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); +/* + Create a zipfile. + pathname contain on Windows NT a filename like "c:\\zlib\\zlib111.zip" or on + an Unix computer "zlib/zlib111.zip". + if the file pathname exist and append=1, the zip will be created at the end + of the file. (useful if the file contain a self extractor code) + If the zipfile cannot be opened, the return value is NULL. + Else, the return value is a zipFile Handle, usable with other function + of this zip package. + + +*/ + +extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level)); +/* + Open a file in the ZIP for writing. + filename : the filename in zip (if NULL, '-' without quote will be used + *zipfi contain supplemental information + if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local + contains the extrafield data the the local header + if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global + contains the extrafield data the the local header + if comment != NULL, comment contain the comment string + method contain the compression method (0 for store, Z_DEFLATED for deflate) + level contain the level of compression (can be Z_DEFAULT_COMPRESSION) +*/ + +extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, + const voidp buf, + unsigned len)); +/* + Write data in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); +/* + Close the current file in the zipfile +*/ + +extern int ZEXPORT zipClose OF((zipFile file, + const char* global_comment)); +/* + Close the zipfile +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _zip_H */ diff --git a/contrib/pk3man/zlib/zlib.h b/contrib/pk3man/zlib/zlib.h new file mode 100644 index 00000000..49f56b43 --- /dev/null +++ b/contrib/pk3man/zlib/zlib.h @@ -0,0 +1,893 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.1.3, July 9th, 1998 + + Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef _ZLIB_H +#define _ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.1.3" + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +/* Allowed flush values; see deflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + 0.1% larger than avail_in plus 12 bytes. If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may some + introduce some output latency (reading input without producing any output) + except when forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much + output as possible to the output buffer. The flushing behavior of inflate is + not specified for values of the flush parameter other than Z_SYNC_FLUSH + and Z_FINISH, but the current implementation actually flushes as much output + as possible anyway. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster routine + may be used for the single inflate() call. + + If a preset dictionary is needed at this point (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the + dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise + it sets strm->adler to the adler32 checksum of all output produced + so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or + an error code as described below. At the end of the stream, inflate() + checks that its computed adler32 checksum is equal to that saved by the + compressor and returns Z_STREAM_END only if the checksum is correct. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect + adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent + (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if no progress is possible or if there was not + enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR + case, the application may then call inflateSync to look for a good + compression block. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match). Filtered data consists mostly of small values with a + somewhat random distribution. In this case, the compression algorithm is + tuned to compress them better. The effect of Z_FILTERED is to force more + Huffman coding and less string matching; it is somewhat intermediate + between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects + the compression ratio but not the correctness of the compressed output even + if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the Adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. If a compressed stream with a larger window size is given as + input, inflate() will return with the error code Z_DATA_ERROR instead of + trying to allocate a larger window. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least 0.1% larger than + sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h". (See the description + of deflateInit2 for more information about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + const voidp buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* _ZLIB_H */ diff --git a/contrib/pk3man/zlib/zlib.lib b/contrib/pk3man/zlib/zlib.lib new file mode 100644 index 00000000..a03e0379 Binary files /dev/null and b/contrib/pk3man/zlib/zlib.lib differ diff --git a/contrib/pk3man/zlib/zlibd.lib b/contrib/pk3man/zlib/zlibd.lib new file mode 100644 index 00000000..4e8915c6 Binary files /dev/null and b/contrib/pk3man/zlib/zlibd.lib differ