From caabb8dcebe23b6c7620c97d66b12a175e0f2f1d Mon Sep 17 00:00:00 2001 From: mattn Date: Tue, 18 Mar 2008 17:11:08 +0000 Subject: [PATCH] * 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: svn://svn.icculus.org/gtkradiant/GtkRadiant/branches/ZeroRadiant@225 8a3a26a2-13c4-0310-b231-cf6edde360e5 --- contrib/pk3man/bitmaps/pk3man_tbadd.bmp | Bin 0 -> 560 bytes contrib/pk3man/bitmaps/pk3man_tbdelete.bmp | Bin 0 -> 556 bytes contrib/pk3man/bitmaps/pk3man_tbextract.bmp | Bin 0 -> 556 bytes contrib/pk3man/bitmaps/pk3man_tbnew.bmp | Bin 0 -> 556 bytes contrib/pk3man/bitmaps/pk3man_tbopen.bmp | Bin 0 -> 238 bytes contrib/pk3man/bitmaps/pk3man_tbrename.bmp | Bin 0 -> 564 bytes contrib/pk3man/bitmaps/pk3man_tbsave.bmp | Bin 0 -> 238 bytes contrib/pk3man/bitmaps/pk3man_tbview.bmp | Bin 0 -> 568 bytes contrib/pk3man/bitmaps/pk3man_tbwizard.bmp | Bin 0 -> 560 bytes contrib/pk3man/mainwnd.cpp | 1581 +++++++++++++++++++ contrib/pk3man/mainwnd.h | 87 + contrib/pk3man/md3.h | 111 ++ contrib/pk3man/memfile.cpp | 36 + contrib/pk3man/memfile.h | 27 + contrib/pk3man/pak.cpp | 421 +++++ contrib/pk3man/pak.h | 74 + contrib/pk3man/pixmap.cpp | 581 +++++++ contrib/pk3man/pixmap.h | 28 + contrib/pk3man/pk3man.cpp | 188 +++ contrib/pk3man/pk3man.def | 12 + contrib/pk3man/pk3man.exclude | 32 + contrib/pk3man/pk3man.vcproj | 101 ++ contrib/pk3man/pk3man_readme.txt | 46 + contrib/pk3man/pk3str.h | 395 +++++ contrib/pk3man/renamedlg.cpp | 113 ++ contrib/pk3man/renamedlg.h | 25 + contrib/pk3man/stdafx.cpp | 8 + contrib/pk3man/stdafx.h | 141 ++ contrib/pk3man/tree.cpp | 271 ++++ contrib/pk3man/tree.h | 41 + contrib/pk3man/wild.cpp | 338 ++++ contrib/pk3man/wild.h | 47 + contrib/pk3man/zlib/README.linux | 13 + contrib/pk3man/zlib/libz-zip.a | Bin 0 -> 79364 bytes contrib/pk3man/zlib/unzip.c | 1294 +++++++++++++++ contrib/pk3man/zlib/unzip.h | 275 ++++ contrib/pk3man/zlib/zconf.h | 279 ++++ contrib/pk3man/zlib/zip.c | 720 +++++++++ contrib/pk3man/zlib/zip.h | 150 ++ contrib/pk3man/zlib/zlib.h | 893 +++++++++++ contrib/pk3man/zlib/zlib.lib | Bin 0 -> 108288 bytes contrib/pk3man/zlib/zlibd.lib | Bin 0 -> 236486 bytes 42 files changed, 8328 insertions(+) create mode 100644 contrib/pk3man/bitmaps/pk3man_tbadd.bmp create mode 100644 contrib/pk3man/bitmaps/pk3man_tbdelete.bmp create mode 100644 contrib/pk3man/bitmaps/pk3man_tbextract.bmp create mode 100644 contrib/pk3man/bitmaps/pk3man_tbnew.bmp create mode 100644 contrib/pk3man/bitmaps/pk3man_tbopen.bmp create mode 100644 contrib/pk3man/bitmaps/pk3man_tbrename.bmp create mode 100644 contrib/pk3man/bitmaps/pk3man_tbsave.bmp create mode 100644 contrib/pk3man/bitmaps/pk3man_tbview.bmp create mode 100644 contrib/pk3man/bitmaps/pk3man_tbwizard.bmp create mode 100644 contrib/pk3man/mainwnd.cpp create mode 100644 contrib/pk3man/mainwnd.h create mode 100644 contrib/pk3man/md3.h create mode 100644 contrib/pk3man/memfile.cpp create mode 100644 contrib/pk3man/memfile.h create mode 100644 contrib/pk3man/pak.cpp create mode 100644 contrib/pk3man/pak.h create mode 100644 contrib/pk3man/pixmap.cpp create mode 100644 contrib/pk3man/pixmap.h create mode 100644 contrib/pk3man/pk3man.cpp create mode 100644 contrib/pk3man/pk3man.def create mode 100644 contrib/pk3man/pk3man.exclude create mode 100644 contrib/pk3man/pk3man.vcproj create mode 100644 contrib/pk3man/pk3man_readme.txt create mode 100644 contrib/pk3man/pk3str.h create mode 100644 contrib/pk3man/renamedlg.cpp create mode 100644 contrib/pk3man/renamedlg.h create mode 100644 contrib/pk3man/stdafx.cpp create mode 100644 contrib/pk3man/stdafx.h create mode 100644 contrib/pk3man/tree.cpp create mode 100644 contrib/pk3man/tree.h create mode 100644 contrib/pk3man/wild.cpp create mode 100644 contrib/pk3man/wild.h create mode 100644 contrib/pk3man/zlib/README.linux create mode 100644 contrib/pk3man/zlib/libz-zip.a create mode 100644 contrib/pk3man/zlib/unzip.c create mode 100644 contrib/pk3man/zlib/unzip.h create mode 100644 contrib/pk3man/zlib/zconf.h create mode 100644 contrib/pk3man/zlib/zip.c create mode 100644 contrib/pk3man/zlib/zip.h create mode 100644 contrib/pk3man/zlib/zlib.h create mode 100644 contrib/pk3man/zlib/zlib.lib create mode 100644 contrib/pk3man/zlib/zlibd.lib diff --git a/contrib/pk3man/bitmaps/pk3man_tbadd.bmp b/contrib/pk3man/bitmaps/pk3man_tbadd.bmp new file mode 100644 index 0000000000000000000000000000000000000000..a88ee120e9132799a73923383c5519ad2f429203 GIT binary patch literal 560 zcmbtPK@NZ*46BS76K_WU;L#6w@vi@Wgnz(x1QQayXqS$yzzW;G1UL@nnViUxY|t@h z3_T#WY(*iZ1jWiY$J6`p1fG48W&2$>yYE(W%wpN7b^O-N0nhR%^UYXgxH-%Ggh&{a bqs(tzyVUcczxvC6gIl^qY-{hmN`=XL!vwb#ArqR?$ zXM2vJ7lB&4LWmfnU>&w_)~B$%CybF_c|fA)r&}#04}nI0-gvRewG^<-c{YgaT!rEI m$~6dQU*7XIKQ-|J&Sh^-D4ZDG(nmY@Uyu#-ib0))637(kd6$OT~#`2YVu0|>?eA&AX{4FJ_) z69!pHfjBc-ib0))637(kd6$OT~#`2YVu0|>?eA&AX{4FJ_) z69!p{SDYCE!0KS?nHgb#c_@oBFfe0vKLZm)7#==Q|3XzWA;h8K0}Di0_`vuunu_8K F3;-Xz4Q&7b literal 0 HcmV?d00001 diff --git a/contrib/pk3man/bitmaps/pk3man_tbopen.bmp b/contrib/pk3man/bitmaps/pk3man_tbopen.bmp new file mode 100644 index 0000000000000000000000000000000000000000..1f1770c33a812e769f0eec75f1333d3a5436baab GIT binary patch literal 238 zcmZ{cu?>JQ3;-zp4B;SZi0+#q2Okt^9FTKQB9X{^CM!MpnV*WX!6&CX3>cf* E1G1zTbpQYW literal 0 HcmV?d00001 diff --git a/contrib/pk3man/bitmaps/pk3man_tbrename.bmp b/contrib/pk3man/bitmaps/pk3man_tbrename.bmp new file mode 100644 index 0000000000000000000000000000000000000000..0e98175d8e127ef8be0bd4a555d40c848f96be4a GIT binary patch literal 564 zcmbVI!4bkR40Bcc;I2Ooc3=P|;NK4euou%XT96W2+FnWzp+=57FtpgzV|4lulLi@93%Dz z@{YVAPc&dJaXk}hDlwXKCS4z_=`vADiDHbT-1P!?dsv_Uk+Z1r;AiF@uekXI02K@y zXATI}Y8RzGi{jve;o_Istx9Re`e_)#y3YUHYjKTD9bsRE?YoYp2x9jAziKzj-0B<- Oyn%K9dx$gUL-Yj+;}qZk literal 0 HcmV?d00001 diff --git a/contrib/pk3man/bitmaps/pk3man_tbwizard.bmp b/contrib/pk3man/bitmaps/pk3man_tbwizard.bmp new file mode 100644 index 0000000000000000000000000000000000000000..036d2aebb1137724e2a7b4de077d6fb4404882a9 GIT binary patch literal 560 zcma)&K@I{j2t^TyF>yE1y-Sy#!TopyukKMgAI37YRwE6hef<2N^giF1ydIcW^cj6Z z@92QJ)^sGY-s5R)RZ1Z{Pn^pOH@taN(2lUh{>jC4A9@jA^!$x`|B5>vxaGoYD3Y^( s!W%bbs6#KTnFeRkBo2R3C2ck}cdUo^7ymYO%k@u8qxvW0*B_i{0er3x)&Kwi literal 0 HcmV?d00001 diff --git a/contrib/pk3man/mainwnd.cpp b/contrib/pk3man/mainwnd.cpp new file mode 100644 index 0000000..d8c88a9 --- /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 0000000..f7cf5dd --- /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 0000000..805df71 --- /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 0000000..041781e --- /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 0000000..15123bd --- /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 0000000..02df3df --- /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 0000000..f1de00c --- /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 0000000..2ed24b8 --- /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 0000000..10acb38 --- /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 0000000..171462c --- /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 0000000..3eebeb9 --- /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 0000000..87adfbf --- /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 0000000..0ceac05 --- /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 0000000..90da2f6 --- /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 0000000..11d7759 --- /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 0000000..9851e44 --- /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 0000000..d76bb9a --- /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 0000000..0665ded --- /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 0000000..ff7ff7e --- /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 0000000..c386115 --- /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 0000000..3e50618 --- /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 0000000..2b6a929 --- /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 0000000..4c56bd8 --- /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 0000000..fbe5a8f --- /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 0000000000000000000000000000000000000000..6c28723a531dedf78a704593977a58f5a8b81eed GIT binary patch literal 79364 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 +#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 0000000..76692cb --- /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 0000000..6a8f33a --- /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 0000000..4942d0f --- /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 0000000..678260b --- /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 0000000..49f56b4 --- /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 0000000000000000000000000000000000000000..a03e03794eeb7800ab6b7dc7660a0d00553e5926 GIT binary patch literal 108288 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 literal 0 HcmV?d00001 diff --git a/contrib/pk3man/zlib/zlibd.lib b/contrib/pk3man/zlib/zlibd.lib new file mode 100644 index 0000000000000000000000000000000000000000..4e8915c699499a477438faf9d3585f1a649d3943 GIT binary patch literal 236486 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%0ASKIy2xO%Yyw%}g2?PPRXAY^^p9%W7$vOcu? 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 literal 0 HcmV?d00001