mirror of
https://github.com/TTimo/GtkRadiant.git
synced 2025-01-10 03:51:18 +00:00
caabb8dceb
* 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
1581 lines
35 KiB
C++
1581 lines
35 KiB
C++
// MainWnd.cpp: implementation of the CMainWnd class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "mainwnd.h"
|
|
#include "memfile.h"
|
|
#include "md3.h"
|
|
#include "wild.h"
|
|
#include "renamedlg.h"
|
|
#ifdef __linux__
|
|
#include <dirent.h>
|
|
#include <stdlib.h>
|
|
#endif
|
|
|
|
extern CMainWnd *g_pMainWnd;
|
|
bool g_bIgnoreCommands=FALSE;
|
|
|
|
GtkWidget* create_menu_in_menu (GtkWidget *menu, gchar *label, GtkAccelGroup *menu_accel,GtkAccelGroup **submenu_accel);
|
|
GtkWidget* create_menu_item (GtkWidget *menu, gchar *label, GtkAccelGroup *menu_accel,GtkSignalFunc func, int id);
|
|
GtkWidget* menu_separator (GtkWidget *menu);
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
static gint mainwnd_delete (GtkWidget *widget, gpointer data)
|
|
{
|
|
return g_pMainWnd->OnClose();
|
|
}
|
|
|
|
static void HandleCommand (GtkWidget *widget, gpointer data)
|
|
{
|
|
int id = GPOINTER_TO_INT (data);
|
|
|
|
if (g_bIgnoreCommands)
|
|
return;
|
|
|
|
switch (id)
|
|
{
|
|
case ID_FILE_NEW: g_pMainWnd->OnFileNew (); break;
|
|
case ID_FILE_OPEN: g_pMainWnd->OnFileOpen (); break;
|
|
case ID_FILE_SAVE: g_pMainWnd->OnFileSave (); break;
|
|
|
|
case ID_WIZARD: g_pMainWnd->OnWizard (); break;
|
|
|
|
case ID_VIEW: g_pMainWnd->OnView (); break;
|
|
case ID_EXTRACT: g_pMainWnd->OnExtract (); break;
|
|
|
|
case ID_ADD: g_pMainWnd->OnAdd (); break;
|
|
case ID_RENAME: g_pMainWnd->OnRename (); break;
|
|
case ID_DELETE: g_pMainWnd->OnDelete (); break;
|
|
}
|
|
}
|
|
|
|
CMainWnd::CMainWnd()
|
|
{
|
|
m_pMainWnd=NULL;
|
|
m_mnuDrop=NULL;
|
|
}
|
|
|
|
CMainWnd::~CMainWnd()
|
|
{
|
|
if (m_pMainWnd)
|
|
delete m_pMainWnd;
|
|
}
|
|
|
|
bool CMainWnd::OnClose()
|
|
{
|
|
if (pak.IsModified())
|
|
{
|
|
//int ret=DoMessageBox("Pk3 has not been saved\n\n Really quit?","Pk3Man",MB_YESNO);
|
|
int ret=g_FuncTable.m_pfnMessageBox(m_pMainWnd,"Pk3 has not been saved\n\n Really quit?","Pk3Man",MB_YESNO, NULL);
|
|
if (ret!=IDYES)
|
|
return 1;
|
|
}
|
|
|
|
FreePakList();
|
|
DeleteTempFiles();
|
|
return 0;
|
|
}
|
|
|
|
void CMainWnd::OnDestroy()
|
|
{
|
|
// NOT CALLED !!!
|
|
}
|
|
|
|
BOOL CMainWnd::Create(GtkWidget *parent)
|
|
{
|
|
GtkWidget *vbox,*window;
|
|
GdkPixmap *pixmap=NULL;
|
|
GdkBitmap *mask=NULL;
|
|
|
|
char * icon_xpm[] = { "32 32 6 1", ". c none", "/ c #ff0ff", "0 c #dddddd", "1 c #e6a0e6", "2 c #333333", "3 c #9d189d", "................................", "................................", "............////////............", "............////////............", "........////////////////........", "........////////////////........", "......////////////////////......", "......////////////////////......", "....//////0000////////0001//....", "....//////0000////////0000//....", "....////00000000////00000001....", "....////00000000////00000001....", "....////00002222////00002223....", "....////00002222////00002223....", "..//////00002222////00002223//..", "..//////00002222////00002222//..", "..////////0000////////0000////..", "..////////0000////////0000////..", "..////////////////////////////..", "..////////////////////////////..", "..////////////////////////////..", "..////////////////////////////..", "..////////////////////////////..", "..////////////////////////////..", "..////////////////////////////..", "..////////////////////////////..", "..////..//////....//////..////..", "..////..//////....//////..////..", "..//......////....////......//..", "..//......////....////......//..", "................................", "................................"};
|
|
|
|
// get bitmap paths
|
|
GetPaths();
|
|
|
|
// create the main widget
|
|
m_pMainWnd = window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
|
gtk_signal_connect (GTK_OBJECT (window), "delete_event", GTK_SIGNAL_FUNC (mainwnd_delete), this);
|
|
//gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (gtk_widget_destroy), this);
|
|
|
|
gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
|
|
gtk_window_set_title (GTK_WINDOW (m_pMainWnd), "Pk3Man - ");
|
|
gtk_window_set_default_size (GTK_WINDOW (m_pMainWnd), 300, 300);
|
|
gtk_widget_show (m_pMainWnd);
|
|
|
|
// load and set the icon
|
|
|
|
pixmap = gdk_pixmap_create_from_xpm_d (window->window, &mask, NULL, icon_xpm);
|
|
gdk_window_set_icon (window->window, NULL, pixmap, mask);
|
|
|
|
// setup the vertical layout box
|
|
vbox=gtk_vbox_new (FALSE, 0);
|
|
gtk_container_add (GTK_CONTAINER (window), vbox);
|
|
gtk_widget_show (vbox);
|
|
|
|
if (!CreateToolbar (window, vbox))
|
|
return FALSE;
|
|
|
|
if (!CreateTreeView (window, vbox))
|
|
return FALSE;
|
|
|
|
if (!CreateStatusBar (window,vbox))
|
|
return FALSE;
|
|
|
|
UpdateStatus();
|
|
UpdateToolBar();
|
|
|
|
LoadExclusions();
|
|
InitPakList();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CMainWnd::CreateTreeView(GtkWidget *window,GtkWidget *vbox)
|
|
{
|
|
// create a scrollable widget to house the tree
|
|
m_ScrolledWin = gtk_scrolled_window_new (NULL, NULL);
|
|
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (m_ScrolledWin),
|
|
GTK_POLICY_AUTOMATIC,
|
|
GTK_POLICY_AUTOMATIC);
|
|
|
|
//gtk_widget_set_usize (m_ScrolledWin, 400, 400);
|
|
gtk_box_pack_start (GTK_BOX (vbox), m_ScrolledWin, TRUE, TRUE, 0);
|
|
gtk_widget_show (m_ScrolledWin);
|
|
|
|
// attach and initialise the tree
|
|
m_Tree.Init(m_ScrolledWin);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CMainWnd::CreateToolbar(GtkWidget *window,GtkWidget *vbox)
|
|
{
|
|
GtkWidget *handle_box, *toolbar, *w;
|
|
|
|
handle_box = gtk_handle_box_new ();
|
|
gtk_box_pack_start (GTK_BOX (vbox), handle_box, FALSE, FALSE, 0);
|
|
gtk_widget_show (handle_box);
|
|
|
|
m_Toolbar = toolbar = gtk_toolbar_new ();
|
|
|
|
// gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), user_rc.toolbar_style);
|
|
gtk_container_add (GTK_CONTAINER (handle_box), toolbar);
|
|
gtk_container_border_width (GTK_CONTAINER (toolbar), 2);
|
|
gtk_widget_show (toolbar);
|
|
|
|
// new
|
|
w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
|
|
"New",
|
|
"Start a new Pk3",
|
|
"",
|
|
CPixMap::new_pixmap(window, "pk3man_tbnew.bmp"),
|
|
//CPixMap::pixmap_from_char(window,xpm_new),
|
|
GTK_SIGNAL_FUNC (HandleCommand),
|
|
GINT_TO_POINTER (ID_FILE_NEW));
|
|
|
|
gtk_object_set_data (GTK_OBJECT (window), "tb_file_new", w);
|
|
|
|
// open
|
|
w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
|
|
"Open",
|
|
"Open an existing Pk3",
|
|
"",
|
|
CPixMap::new_pixmap(window, "pk3man_tbopen.bmp"),
|
|
GTK_SIGNAL_FUNC (HandleCommand),
|
|
GINT_TO_POINTER (ID_FILE_OPEN));
|
|
|
|
gtk_object_set_data (GTK_OBJECT (window), "tb_file_open", w);
|
|
|
|
// save
|
|
w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
|
|
"Save",
|
|
"Save the current Pk3",
|
|
"",
|
|
CPixMap::new_pixmap (window, "pk3man_tbsave.bmp"),
|
|
GTK_SIGNAL_FUNC (HandleCommand),
|
|
GINT_TO_POINTER (ID_FILE_SAVE));
|
|
|
|
gtk_object_set_data (GTK_OBJECT (window), "tb_file_save", w);
|
|
|
|
// space
|
|
gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
|
|
|
|
// wizard
|
|
w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
|
|
"Wizard",
|
|
"Build Pk3 from a Map",
|
|
"",
|
|
CPixMap::new_pixmap (window, "pk3man_tbwizard.bmp"),
|
|
GTK_SIGNAL_FUNC (HandleCommand),
|
|
GINT_TO_POINTER (ID_WIZARD));
|
|
|
|
gtk_object_set_data (GTK_OBJECT (window), "tb_wizard", w);
|
|
|
|
// space
|
|
gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
|
|
|
|
// view
|
|
w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
|
|
"View",
|
|
"View an entry",
|
|
"",
|
|
CPixMap::new_pixmap (window, "pk3man_tbview.bmp"),
|
|
GTK_SIGNAL_FUNC (HandleCommand),
|
|
GINT_TO_POINTER (ID_VIEW));
|
|
|
|
gtk_object_set_data (GTK_OBJECT (window), "tb_view", w);
|
|
|
|
// extract
|
|
w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
|
|
"Extract",
|
|
"Extract an entry",
|
|
"",
|
|
CPixMap::new_pixmap (window, "pk3man_tbextract.bmp"),
|
|
GTK_SIGNAL_FUNC (HandleCommand),
|
|
GINT_TO_POINTER (ID_EXTRACT));
|
|
|
|
gtk_object_set_data (GTK_OBJECT (window), "tb_extract", w);
|
|
|
|
// space
|
|
gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
|
|
|
|
// Add
|
|
w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
|
|
"Wizard",
|
|
"Add a file",
|
|
"",
|
|
CPixMap::new_pixmap (window, "pk3man_tbadd.bmp"),
|
|
GTK_SIGNAL_FUNC (HandleCommand),
|
|
GINT_TO_POINTER (ID_ADD));
|
|
|
|
gtk_object_set_data (GTK_OBJECT (window), "tb_add", w);
|
|
|
|
// rename
|
|
w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
|
|
"Rename",
|
|
"Rename an entry",
|
|
"",
|
|
CPixMap::new_pixmap (window, "pk3man_tbrename.bmp"),
|
|
GTK_SIGNAL_FUNC (HandleCommand),
|
|
GINT_TO_POINTER (ID_RENAME));
|
|
|
|
gtk_object_set_data (GTK_OBJECT (window), "tb_rename", w);
|
|
|
|
|
|
// rename
|
|
w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
|
|
"Delete",
|
|
"Delete an entry",
|
|
"",
|
|
CPixMap::new_pixmap (window, "pk3man_tbdelete.bmp"),
|
|
GTK_SIGNAL_FUNC (HandleCommand),
|
|
GINT_TO_POINTER (ID_DELETE));
|
|
|
|
gtk_object_set_data (GTK_OBJECT (window), "tb_delete", w);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CMainWnd::UpdateToolBar()
|
|
{
|
|
std::string path=m_Tree.GetSelected();
|
|
bool file_selected=TRUE;
|
|
|
|
if (path=="")
|
|
file_selected=FALSE;
|
|
|
|
if (file_selected)
|
|
{
|
|
// enable toolbar buttons
|
|
|
|
GtkWidget *item;
|
|
|
|
item = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_view"));
|
|
//gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), FALSE);
|
|
gtk_widget_set_sensitive (item, TRUE);
|
|
|
|
item = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_extract"));
|
|
//gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), FALSE);
|
|
gtk_widget_set_sensitive (item, TRUE);
|
|
|
|
item = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_delete"));
|
|
//gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), FALSE);
|
|
gtk_widget_set_sensitive (item, TRUE);
|
|
|
|
item = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_rename"));
|
|
//gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), FALSE);
|
|
gtk_widget_set_sensitive (item, TRUE);
|
|
|
|
}
|
|
else
|
|
{
|
|
// disable toolbar buttons
|
|
|
|
GtkWidget *item;
|
|
|
|
item = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_view"));
|
|
//gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), TRUE);
|
|
gtk_widget_set_sensitive (item, TRUE);
|
|
|
|
item = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_extract"));
|
|
//gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), TRUE);
|
|
gtk_widget_set_sensitive (item, TRUE);
|
|
|
|
item = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_delete"));
|
|
//gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), TRUE);
|
|
gtk_widget_set_sensitive (item, TRUE);
|
|
|
|
item = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_rename"));
|
|
//gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), TRUE);
|
|
gtk_widget_set_sensitive (item, TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BOOL CMainWnd::CreateStatusBar(GtkWidget *window,GtkWidget *vbox)
|
|
{
|
|
GtkWidget *hbox, *hbox1;
|
|
GtkWidget *frame;
|
|
GtkWidget *label;
|
|
|
|
hbox = gtk_hbox_new (FALSE, 0);
|
|
gtk_widget_show (hbox);
|
|
gtk_widget_set_usize (hbox, -1, 24);
|
|
gtk_container_border_width (GTK_CONTAINER (hbox), 1);
|
|
gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, TRUE, 2);
|
|
|
|
frame = gtk_frame_new ((char*)NULL);
|
|
gtk_widget_show (frame);
|
|
gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
|
|
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
|
|
|
|
hbox1 = gtk_hbox_new (FALSE, 0);
|
|
gtk_container_add (GTK_CONTAINER (frame), hbox1);
|
|
gtk_container_border_width (GTK_CONTAINER (hbox1), 0);
|
|
gtk_widget_show (hbox1);
|
|
|
|
label = gtk_label_new (" Ready ... ");
|
|
gtk_widget_show (label);
|
|
gtk_box_pack_start (GTK_BOX (hbox1), label, FALSE, TRUE, 0);
|
|
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
|
|
gtk_misc_set_padding (GTK_MISC (label), 3, 0);
|
|
m_pStatusLabel[0] = label;
|
|
|
|
for (int i = 1; i < 3; i++)
|
|
{
|
|
frame = gtk_frame_new ((char*)NULL);
|
|
gtk_widget_show (frame);
|
|
gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
|
|
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
|
|
|
|
label = gtk_label_new (" ");
|
|
gtk_widget_show (label);
|
|
gtk_container_add (GTK_CONTAINER (frame), label);
|
|
m_pStatusLabel[i] = label;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CMainWnd::OnFileOpen()
|
|
{
|
|
// lets pick a file
|
|
const char *filename;
|
|
|
|
if (g_strModPath.GetLength()>0)
|
|
//filename=file_dialog(TRUE,"Choose a Pk3...",g_strModPath.GetBuffer(),"*.pk3");
|
|
filename=g_FuncTable.m_pfnFileDialog (m_pMainWnd, TRUE, "Choose a Pk3...",
|
|
g_strModPath.GetBuffer(), "pk3man");
|
|
else
|
|
//filename=file_dialog(TRUE,"Choose a Pk3...",g_strBasePath.GetBuffer(),"*.pk3");
|
|
filename=g_FuncTable.m_pfnFileDialog (m_pMainWnd, TRUE, "Choose a Pk3...",
|
|
g_strBasePath.GetBuffer(), "pk3man");
|
|
|
|
if (filename==NULL)
|
|
return;
|
|
|
|
Str fname=filename;
|
|
fname=fname.Right(3);
|
|
if (fname!="pk3")
|
|
{
|
|
//DoMessageBox("Please pick a Pk3 file","Pk3Man",MB_OK);
|
|
g_FuncTable.m_pfnMessageBox(m_pMainWnd,"Please pick a Pk3 file","Pk3Man",MB_OK, NULL);
|
|
return;
|
|
}
|
|
|
|
OnFileNew();
|
|
pak.Open(filename);
|
|
UpdateTree();
|
|
|
|
// update window title
|
|
g_FuncTable.m_pfnQE_ConvertDOSToUnixName (filename, filename);
|
|
std::string title=filename;
|
|
g_free (filename);
|
|
long pos=title.find_last_of('/');
|
|
title=title.substr(pos+1);
|
|
title="Pk3Man - "+title;
|
|
gtk_window_set_title (GTK_WINDOW (m_pMainWnd), title.c_str());
|
|
}
|
|
|
|
void CMainWnd::OnFileSave()
|
|
{
|
|
const char *filename;
|
|
|
|
if (g_strModPath.GetLength()>0)
|
|
filename=g_FuncTable.m_pfnFileDialog (m_pMainWnd, FALSE, "Save As...",
|
|
g_strModPath.GetBuffer(), "pk3man");
|
|
else
|
|
filename=g_FuncTable.m_pfnFileDialog (m_pMainWnd, FALSE, "Save As...",
|
|
g_strBasePath.GetBuffer(), "pk3man");
|
|
|
|
if (filename==NULL)
|
|
return;
|
|
|
|
g_FuncTable.m_pfnQE_ConvertDOSToUnixName (filename, filename);
|
|
std::string path=filename;
|
|
g_free (filename);
|
|
long p=path.find_last_of('/');
|
|
std::string name=path.substr(p,-1);
|
|
|
|
std::string tpath=g_strTempPath.GetBuffer() + name;
|
|
|
|
if (!pak.Save(tpath.c_str()))
|
|
{
|
|
// eek, error central
|
|
g_FuncTable.m_pfnMessageBox(m_pMainWnd,"Unable to save the pk3 to temp folder!","Pk3Man",MB_OK, NULL);
|
|
return;
|
|
}
|
|
|
|
// ok, now copy to proper place
|
|
|
|
#ifdef WIN32
|
|
|
|
int ret=CopyFile(tpath.c_str(),path.c_str(),FALSE);
|
|
DeleteFile(tpath.c_str());
|
|
|
|
if (!ret)
|
|
{
|
|
g_FuncTable.m_pfnMessageBox(m_pMainWnd,"Unable to copy pk3 from temp folder!","Pk3Man",MB_OK, NULL);
|
|
return;
|
|
}
|
|
|
|
#endif
|
|
|
|
pak.Close();
|
|
pak.Open(path.c_str());
|
|
m_Tree.Clear();
|
|
UpdateTree();
|
|
|
|
//update title
|
|
name=name.substr(1,-1);
|
|
std::string title="Pk3Man - "+name;
|
|
gtk_window_set_title (GTK_WINDOW (m_pMainWnd), title.c_str());
|
|
}
|
|
|
|
bool CMainWnd::OnFileNew()
|
|
{
|
|
if (pak.IsModified())
|
|
{
|
|
int ret=g_FuncTable.m_pfnMessageBox(m_pMainWnd,"This will lose the current Pk3 contents\n\n Are u sure?","Pk3Man",MB_YESNO, NULL);
|
|
if (ret!=IDYES)
|
|
return FALSE;
|
|
}
|
|
|
|
pak.Close();
|
|
m_Tree.Clear();
|
|
gtk_window_set_title (GTK_WINDOW (m_pMainWnd), "Pk3Man - ");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CMainWnd::LoadExclusions()
|
|
{
|
|
exclusions.clear();
|
|
|
|
FILE *fp;
|
|
std::string filename=g_strAppPath.GetBuffer();
|
|
filename+="plugins/pk3man.exclude";
|
|
|
|
fp=fopen(filename.c_str(),"rb");
|
|
if (!fp)
|
|
return;
|
|
|
|
while (!feof(fp))
|
|
{
|
|
std::string line=GetLine(fp);
|
|
|
|
if (line.length()==0)
|
|
continue;
|
|
|
|
if (line[0]=='/' && line[1]=='/')
|
|
continue;
|
|
|
|
for (int n=0 ; n < (int)line.length() ; n++)
|
|
{
|
|
if (line[n]=='\\')
|
|
line[n]='/';
|
|
}
|
|
|
|
if (line[0]=='/')
|
|
line=line.substr(1,-1);
|
|
|
|
exclusions.push_back(line);
|
|
}
|
|
}
|
|
|
|
bool CMainWnd::IsExcluded(const char *name)
|
|
{
|
|
for (std::list<std::string>::iterator i=exclusions.begin() ; i!=exclusions.end() ; i++)
|
|
{
|
|
std::string t=*i;
|
|
|
|
if (CWild::fpattern_match(t.c_str(),name))
|
|
return TRUE;
|
|
|
|
std::string nm=name;
|
|
if (nm.find(t) != static_cast<size_t>(-1))
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void CMainWnd::OnWizard()
|
|
{
|
|
if (!pak.IsEmpty())
|
|
{
|
|
int ret=g_FuncTable.m_pfnMessageBox(m_pMainWnd,"Add to current pak contents ?","Pk3Man",MB_YESNO, NULL);
|
|
if (ret==IDNO)
|
|
{
|
|
if (!OnFileNew())
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
std::string mappath="maps";
|
|
mappath=g_strBasePath.GetBuffer()+mappath;
|
|
|
|
gchar *filename=g_FuncTable.m_pfnFileDialog(m_pMainWnd,TRUE,"Choose a Map...",mappath.c_str(),"pk3man");
|
|
|
|
if (filename==NULL)
|
|
return;
|
|
|
|
g_FuncTable.m_pfnQE_ConvertDOSToUnixName (filename, filename);
|
|
std::string map=filename;
|
|
long p=map.find_last_of('/');
|
|
map=map.substr(p+1,-1);
|
|
|
|
//update title
|
|
std::string title="Pk3Man - "+map;
|
|
gtk_window_set_title (GTK_WINDOW (m_pMainWnd), title.c_str());
|
|
|
|
// add map and aas
|
|
ProcessFile(map.c_str(),".bsp","maps");
|
|
ProcessFile(map.c_str(),".aas","maps");
|
|
|
|
// add levelshots
|
|
if (!ProcessFile(map.c_str(),".jpg","levelshots"))
|
|
ProcessFile(map.c_str(),".tga","levelshots");
|
|
|
|
// arena file
|
|
ProcessFile(map.c_str(),".arena","scripts");
|
|
|
|
// initialise text list
|
|
texlist.clear();
|
|
|
|
// generate item list
|
|
FILE *fp;
|
|
fp=fopen(filename,"r");
|
|
g_free(filename);
|
|
|
|
if (!fp)
|
|
return;
|
|
|
|
while (!feof(fp))
|
|
{
|
|
std::string line=GetLine(fp);
|
|
|
|
if (line.find("// brush")!=static_cast<size_t>(-1))
|
|
{
|
|
// its a brush
|
|
line=GetLine(fp);
|
|
line=GetLine(fp);
|
|
|
|
if (line.find("patchDef")!=static_cast<size_t>(-1))
|
|
{
|
|
// its a patch
|
|
line=GetLine(fp);
|
|
line=GetLine(fp);
|
|
|
|
// need to trim left and right
|
|
int n=line.find_first_not_of(' ');
|
|
if (n!=static_cast<size_t>(-1))
|
|
line=line.substr(n);
|
|
|
|
std::string tex="textures/"+line;
|
|
AddToTexList(line.c_str());
|
|
}
|
|
else
|
|
{
|
|
// its a standard brush
|
|
while (line.find_first_of('}')==static_cast<size_t>(-1))
|
|
{
|
|
long p=line.find_last_of(')');
|
|
line=line.substr(p+2,-1);
|
|
|
|
p=line.find_first_of(' ');
|
|
line=line.substr(0,p);
|
|
|
|
std::string tex="textures/"+line;
|
|
AddToTexList(line.c_str());
|
|
|
|
// next
|
|
line=GetLine(fp);
|
|
}
|
|
}
|
|
}
|
|
else if (line.find(".md3")!=static_cast<size_t>(-1))
|
|
{
|
|
long p=line.find_first_of(' ');
|
|
std::string tex=line.substr(p+2,-1);
|
|
tex=tex.substr(0,tex.length()-2);
|
|
|
|
AddToTexList(tex.c_str());
|
|
}
|
|
else if (line.find(".wav")!=static_cast<size_t>(-1))
|
|
{
|
|
long p=line.find_first_of(' ');
|
|
std::string tex=line.substr(p+2,-1);
|
|
tex=tex.substr(0,tex.length()-2);
|
|
|
|
AddToTexList(tex.c_str());
|
|
}
|
|
|
|
}
|
|
fclose(fp);
|
|
|
|
// ok, now proccess our texlist
|
|
// if we find a shader we add its textures onto the end of the texlist
|
|
|
|
for ( std::list<std::string>::const_iterator i = texlist.begin() ; i != texlist.end() ; i++)
|
|
{
|
|
std::string tex=*i;
|
|
|
|
if (tex=="")
|
|
continue;
|
|
|
|
std::string suffix=tex.substr(tex.length()-3,-1);
|
|
|
|
// is it a model?
|
|
if (suffix.compare("md3")==0)
|
|
{
|
|
ParseModel(tex.c_str());
|
|
|
|
// dont add md3's
|
|
continue;
|
|
}
|
|
|
|
// does it exist as it is
|
|
if (ProcessFile(tex.c_str()))
|
|
continue;
|
|
|
|
//shader
|
|
std::string shadername=tex;
|
|
const char *sname=NULL;
|
|
|
|
IShader *shader=g_ShadersTable.m_pfnShader_ForName_NoLoad(shadername.c_str());
|
|
|
|
if (shader)
|
|
sname=shader->getShaderFileName();
|
|
|
|
if (strlen(sname)>0)
|
|
{
|
|
ParseShader(sname,tex.c_str());
|
|
|
|
if (ProcessFile(sname))
|
|
continue;
|
|
}
|
|
|
|
// ok we got this far, its a texture
|
|
|
|
if (tex.find(".tga")!=static_cast<size_t>(-1) || tex.find(".jpg")!=static_cast<size_t>(-1))
|
|
tex=tex.substr(0,tex.length()-4);
|
|
|
|
// jpegs
|
|
std::string jpeg=tex;
|
|
if (jpeg.find("textures/")!=0)
|
|
jpeg="textures/"+jpeg;
|
|
|
|
jpeg+=".jpg";
|
|
if (ProcessFile(jpeg.c_str()))
|
|
continue;
|
|
|
|
// tga's
|
|
std::string tga=tex;
|
|
if (tga.find("textures/")!=0)
|
|
tga="textures/"+tga;
|
|
|
|
tga+=".tga";
|
|
if (ProcessFile(tga.c_str()))
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void CMainWnd::ParseModel(const char *pathname)
|
|
{
|
|
char* modelbuff;
|
|
int len = g_FuncTable.m_pfnLoadFile(pathname, (void**)&modelbuff);
|
|
|
|
if (len==0)
|
|
return;
|
|
|
|
CMemFile file(modelbuff,len);
|
|
|
|
md3_header_t header;
|
|
|
|
file.Read(&header,sizeof(header));
|
|
|
|
int n, numtags=header.Tag_num*header.BoneFrame_num;
|
|
|
|
for (n=0 ; n<numtags ; n++)
|
|
{
|
|
md3_tag_t tag;
|
|
file.Read(&tag,sizeof(md3_tag_t));
|
|
}
|
|
|
|
for (n=0 ; n<header.BoneFrame_num ; n++)
|
|
{
|
|
md3_boneframe_t bone;
|
|
file.Read(&bone,sizeof(md3_boneframe_t));
|
|
}
|
|
|
|
for (int m=0 ; m<header.Mesh_num ; m++)
|
|
{
|
|
md3_mesh_t mesh;
|
|
file.Read(&mesh,sizeof(md3_mesh_t));
|
|
|
|
// skins
|
|
for (n=0 ; n<mesh.Skin_num ; n++)
|
|
{
|
|
char SkinName[68];
|
|
file.Read(&SkinName,sizeof(char)*68);
|
|
|
|
// deal with the skin here
|
|
// we add it to the end of the list (if it aint already there)
|
|
// so we catch it later on
|
|
|
|
AddToTexList(SkinName);
|
|
}
|
|
|
|
// triangles
|
|
for (n=0 ; n<mesh.Triangle_num ; n++)
|
|
{
|
|
int Triangle[3];
|
|
file.Read(&Triangle,sizeof(int)*3);
|
|
}
|
|
|
|
// uv's
|
|
for (n=0 ; n<mesh.Vertex_num ; n++)
|
|
{
|
|
float uv[2];
|
|
file.Read(&uv,sizeof(float)*2);
|
|
}
|
|
|
|
// vertices
|
|
int numverts=mesh.Vertex_num*mesh.MeshFrame_num;
|
|
|
|
for (n=0 ; n<numverts ; n++)
|
|
{
|
|
md3_vertices_t verts;
|
|
file.Read(&verts,sizeof(md3_vertices_t));
|
|
}
|
|
|
|
}
|
|
|
|
// http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=491
|
|
g_free(modelbuff);
|
|
}
|
|
|
|
void CMainWnd::AddToTexList(const char *buf)
|
|
{
|
|
std::string tex;
|
|
int c=0;
|
|
|
|
while (buf[c]!=' ' && buf[c]!='\0')
|
|
{
|
|
tex+=buf[c];
|
|
c++;
|
|
}
|
|
|
|
if (!IsInTexList(tex.c_str()))
|
|
texlist.push_back(tex);
|
|
|
|
}
|
|
|
|
void CMainWnd::InitPaksInDir(const char *folder)
|
|
{
|
|
struct dirent *dirlist;
|
|
DIR *dir;
|
|
|
|
dir = opendir (g_strBasePath.GetBuffer());
|
|
|
|
if (dir != NULL)
|
|
{
|
|
while ((dirlist = readdir (dir)) != NULL)
|
|
{
|
|
if (!strstr (dirlist->d_name, ".pk3"))
|
|
continue;
|
|
|
|
std::string path=g_strBasePath.GetBuffer();
|
|
path+=dirlist->d_name;
|
|
|
|
if (IsExcluded(dirlist->d_name))
|
|
continue;
|
|
|
|
CPak *p=new CPak;
|
|
|
|
if (p->Open(path.c_str()))
|
|
paklist.push_back(p);
|
|
else
|
|
delete p;
|
|
}
|
|
closedir (dir);
|
|
}
|
|
}
|
|
|
|
void CMainWnd::InitPakList()
|
|
{
|
|
gtk_label_set_text (GTK_LABEL (m_pStatusLabel[0]), "Building pk3 references");
|
|
|
|
if (g_strModPath.GetLength()>0)
|
|
InitPaksInDir(g_strModPath.GetBuffer());
|
|
|
|
InitPaksInDir(g_strBasePath.GetBuffer());
|
|
|
|
gtk_label_set_text (GTK_LABEL (m_pStatusLabel[0]), "Ready ...");
|
|
}
|
|
|
|
void CMainWnd::FreePakList()
|
|
{
|
|
std::list<CPak*>::iterator i;
|
|
|
|
for ( i = paklist.begin() ; i != paklist.end() ; i++)
|
|
{
|
|
CPak *p=*i;
|
|
delete p;
|
|
}
|
|
|
|
paklist.clear();
|
|
}
|
|
|
|
void CMainWnd::DeleteTempFiles()
|
|
{
|
|
std::list<std::string>::iterator i;
|
|
|
|
for ( i = temp_files.begin() ; i != temp_files.end() ; i++)
|
|
{
|
|
std::string path=*i;
|
|
|
|
remove(path.c_str());
|
|
}
|
|
|
|
temp_files.clear();
|
|
}
|
|
|
|
bool CMainWnd::IsInTexList(const char *tex)
|
|
{
|
|
for ( std::list<std::string>::const_iterator i = texlist.begin() ; i != texlist.end() ; i++)
|
|
{
|
|
std::string str=*i;
|
|
|
|
if (str.compare(tex)==0)
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void CMainWnd::SkipLines(FILE *fp, int n)
|
|
{
|
|
for (int c=0 ; c<n ; c++)
|
|
std::string line=GetLine(fp);
|
|
}
|
|
|
|
std::string CMainWnd::GetLine(FILE *fp)
|
|
{
|
|
std::string line;
|
|
char c='0';
|
|
|
|
// grab a line;
|
|
do
|
|
{
|
|
fread(&c,1,1,fp);
|
|
|
|
if (c!='\n' && c!='\t' && c!='\r')
|
|
line+=c;
|
|
|
|
} while (c!='\n' && !feof(fp));
|
|
|
|
return line;
|
|
|
|
}
|
|
|
|
std::string CMainWnd::TrimString(const char *str)
|
|
{
|
|
std::string out;
|
|
|
|
int c=0;
|
|
while (str[c]==' ' || str[c]=='\t')
|
|
c++;
|
|
|
|
int e=strlen(str);
|
|
while (str[e]==' ' || str[e]=='\n' || str[e]=='\r')
|
|
e--;
|
|
|
|
out=str;
|
|
out=out.substr(c,-1);
|
|
|
|
return out;
|
|
}
|
|
|
|
void CMainWnd::ParseShader(const char *pathname, const char *tex)
|
|
{
|
|
if (pathname==NULL || tex==NULL)
|
|
return;
|
|
|
|
char* shaderbuff;
|
|
int len = g_FuncTable.m_pfnLoadFile(pathname, (void**)&shaderbuff);
|
|
|
|
if (len==0)
|
|
return;
|
|
|
|
std::string shader=shaderbuff;
|
|
|
|
// skip to start of shader
|
|
long pos=shader.find(tex);
|
|
|
|
if (pos==-1) // shader not found????
|
|
return;
|
|
|
|
shader=shader.substr(pos);
|
|
|
|
bool inStage=FALSE;
|
|
bool inShader=FALSE;
|
|
|
|
// step through the lines
|
|
while(1)
|
|
{
|
|
pos=shader.find_first_of('\n');
|
|
if (pos==-1)
|
|
break;
|
|
|
|
std::string line=shader.substr(0,pos-1);
|
|
shader=shader.substr(pos+1,-1);
|
|
|
|
line=TrimString(line.c_str());
|
|
|
|
if (line=="")
|
|
continue;
|
|
|
|
if (line[0]=='/' && line[1]=='/')
|
|
continue;
|
|
|
|
if (line[0]=='}')
|
|
{
|
|
if (!inStage)
|
|
break;
|
|
else
|
|
inStage=FALSE;
|
|
|
|
continue;
|
|
}
|
|
|
|
if (line[0]=='{')
|
|
{
|
|
if (!inShader)
|
|
{
|
|
inShader=TRUE;
|
|
}
|
|
else if (inShader)
|
|
{
|
|
inStage=TRUE;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
// check for map/animmap e.t.c;
|
|
|
|
if (inStage)
|
|
{
|
|
|
|
if (line.substr(0,3).compare("map")==0)
|
|
{
|
|
std::string map=line.substr(4,-1);
|
|
AddToTexList(map.c_str());
|
|
continue;
|
|
}
|
|
|
|
if (line.substr(0,8).compare("skyparms")==0)
|
|
{
|
|
std::string map=line.substr(9,-1);
|
|
AddToTexList(map.c_str());
|
|
continue;
|
|
}
|
|
|
|
if (line.substr(0,8).compare("clampmap")==0)
|
|
{
|
|
std::string map=line.substr(9,-1);
|
|
AddToTexList(map.c_str());
|
|
continue;
|
|
}
|
|
|
|
if (line.substr(0,7).compare("animmap")==0)
|
|
{
|
|
std::string map=line.substr(9,-1);
|
|
map=TrimString(map.c_str());
|
|
|
|
// skip past numbers
|
|
long p=map.find_first_of(' ');
|
|
map=map.substr(p+1,-1);
|
|
|
|
while (1)
|
|
{
|
|
long pos=map.find_first_of(' ');
|
|
|
|
if (pos==-1)
|
|
{
|
|
AddToTexList(map.c_str());
|
|
break;
|
|
}
|
|
|
|
std::string tex=map.substr(0,pos);
|
|
AddToTexList(tex.c_str());
|
|
|
|
map=map.substr(pos+1,-1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=491
|
|
g_free(shaderbuff);
|
|
}
|
|
|
|
bool CMainWnd::ProcessFile(const char *nm,const char *suffix,const char *folder)
|
|
{
|
|
std::string name=nm;
|
|
name=name.substr(0,name.length()-4);
|
|
name+=suffix;
|
|
|
|
std::string path;
|
|
|
|
if (g_strModPath.GetLength()>0)
|
|
path=g_strModPath.GetBuffer();
|
|
else
|
|
path=g_strBasePath.GetBuffer();
|
|
|
|
path+=folder;
|
|
path+="/";
|
|
path+=name;
|
|
|
|
std::string rpath=folder;
|
|
rpath+="/";
|
|
rpath+=name;
|
|
|
|
if (IsExcluded(rpath.c_str())) // quit out with a FALSE so we try others
|
|
return FALSE;
|
|
|
|
FILE *fp;
|
|
fp=fopen(path.c_str(),"rb");
|
|
|
|
if (fp)
|
|
{
|
|
if (!pak.IsInPak(rpath.c_str()))
|
|
{
|
|
m_Tree.AddPath(rpath.c_str());
|
|
pak.AddExternalFile(rpath.c_str(),path.c_str());
|
|
}
|
|
|
|
fclose(fp);
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FindInAPk3(rpath.c_str());
|
|
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
bool CMainWnd::ProcessFile(const char *nm)
|
|
{
|
|
std::string name=nm;
|
|
|
|
if (IsExcluded(name.c_str())) // quit out with a TRUE so we think it was added
|
|
return TRUE;
|
|
|
|
std::string path;
|
|
|
|
if (g_strModPath.GetLength()>0)
|
|
path=g_strModPath.GetBuffer();
|
|
else
|
|
path=g_strBasePath.GetBuffer();
|
|
|
|
path+=name;
|
|
|
|
FILE *fp;
|
|
fp=fopen(path.c_str(),"rb");
|
|
|
|
if (fp)
|
|
{
|
|
if (!pak.IsInPak(name.c_str()))
|
|
{
|
|
m_Tree.AddPath(name.c_str());
|
|
pak.AddExternalFile(name.c_str(),path.c_str());
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FindInAPk3(name.c_str());
|
|
}
|
|
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
bool CMainWnd::FindInAPk3(const char *name)
|
|
{
|
|
std::list<CPak*>::iterator i;
|
|
|
|
for ( i = paklist.begin() ; i != paklist.end() ; i++)
|
|
{
|
|
CPak *p=*i;
|
|
|
|
if (p->m_filename.CompareNoCase(pak.m_filename)==0)
|
|
continue;
|
|
|
|
std::string fname=p->m_filename.GetBuffer();
|
|
long pos=fname.find_last_of('/');
|
|
fname=fname.substr(pos+1,-1);
|
|
|
|
if (IsExcluded(fname.c_str()))
|
|
continue;
|
|
|
|
if (p->IsInPak(name))
|
|
{
|
|
pak_entry pe=p->FindPE(name);
|
|
m_Tree.AddPath(name);
|
|
pak.AddPakFile(name,p->m_filename.GetBuffer(),pe.compressed,pe.uncompressed);
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
void CMainWnd::OnAdd()
|
|
{
|
|
std::string path;
|
|
if (g_strModPath.GetLength()>0)
|
|
path=g_strModPath.GetBuffer();
|
|
else
|
|
path=g_strBasePath.GetBuffer();
|
|
|
|
//char *filename=file_dialog(TRUE,"Choose a file...",path.c_str(),"*.*");
|
|
gchar *filename=g_FuncTable.m_pfnFileDialog(m_pMainWnd,TRUE,"Choose a file...",path.c_str(),"pk3man");
|
|
|
|
if (filename==NULL)
|
|
return;
|
|
|
|
int c=0;
|
|
|
|
while (filename[c]!='\0')
|
|
{
|
|
if (filename[c]=='\\')
|
|
filename[c]='/';
|
|
|
|
c++;
|
|
}
|
|
|
|
std::string fname=filename;
|
|
|
|
long p=path.length();
|
|
fname=fname.substr(p,-1);
|
|
|
|
if (pak.IsInPak((char*)fname.c_str()))
|
|
return;
|
|
|
|
pak.AddExternalFile((char *)fname.c_str(),(char *)filename);
|
|
m_Tree.AddPath((char *)fname.c_str());
|
|
|
|
}
|
|
|
|
void CMainWnd::OnDelete()
|
|
{
|
|
std::string path=m_Tree.GetSelected();
|
|
|
|
if (path=="")
|
|
return;
|
|
|
|
pak.Delete(path.c_str());
|
|
|
|
//m_Tree.RemovePath(path.c_str());
|
|
|
|
// dodgy hack but works for now
|
|
m_Tree.Clear();
|
|
UpdateTree();
|
|
|
|
}
|
|
|
|
void CMainWnd::OnRename()
|
|
{
|
|
std::string path=m_Tree.GetSelected();
|
|
|
|
if (path=="")
|
|
return;
|
|
|
|
CRenameDlg dlg;
|
|
dlg.m_Name=path;
|
|
|
|
if (dlg.DoModal()==IDOK)
|
|
{
|
|
pak.Rename(path.c_str(),dlg.m_Name.c_str());
|
|
m_Tree.Clear();
|
|
UpdateTree();
|
|
}
|
|
|
|
}
|
|
|
|
void CMainWnd::UpdateTree()
|
|
{
|
|
// clear the tree and fill it with the items in the pak
|
|
|
|
for ( std::list<pak_entry>::const_iterator iEntry = pak.entries.begin() ; iEntry != pak.entries.end() ; iEntry++)
|
|
{
|
|
pak_entry pe=*iEntry;
|
|
|
|
std::string name;
|
|
if (pe.rename)
|
|
name=pe.newname;
|
|
else
|
|
name=pe.filename;
|
|
|
|
m_Tree.AddPath(name.c_str());
|
|
}
|
|
|
|
}
|
|
|
|
void CMainWnd::OnExtract()
|
|
{
|
|
std::string path=m_Tree.GetSelected();
|
|
|
|
if (path=="")
|
|
return;
|
|
|
|
pak_entry pe=pak.FindPE((char*)path.c_str());
|
|
|
|
std::string bpath;
|
|
if (g_strModPath.GetLength()>0)
|
|
bpath=g_strModPath.GetBuffer();
|
|
else
|
|
bpath=g_strBasePath.GetBuffer();
|
|
|
|
//char *pathto=dir_dialog("Extract to ...",bpath.c_str());
|
|
gchar *pathto=g_FuncTable.m_pfnDirDialog(m_pMainWnd,"Extract to...",bpath.c_str());
|
|
|
|
if (pathto==NULL)
|
|
return;
|
|
|
|
long pos=path.find_last_of('/');
|
|
std::string name=path.substr(pos+1);
|
|
|
|
std::string cpath=pathto;
|
|
cpath+=name;
|
|
|
|
if (pe.pakname.compare(pak.m_filename.GetBuffer())==0)
|
|
{
|
|
// its in pak
|
|
pak.ExtractTo((char*)path.c_str(),(char*)cpath.c_str());
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
void CMainWnd::OnView()
|
|
{
|
|
std::string path=m_Tree.GetSelected();
|
|
|
|
if (path=="")
|
|
return;
|
|
|
|
pak_entry pe=pak.FindPE(path.c_str());
|
|
|
|
long p=pe.filename.find_last_of('/');
|
|
std::string name=pe.filename.substr(p+1,-1);
|
|
std::string temppath=g_strTempPath.GetBuffer()+name;
|
|
|
|
if (pe.frompak && pe.pakname.compare(pak.m_filename.GetBuffer())==0)
|
|
{
|
|
// its in pak
|
|
if (!pak.ExtractTo(path.c_str(),(char *)temppath.c_str()))
|
|
return;
|
|
|
|
temp_files.push_back(temppath);
|
|
|
|
// view it
|
|
#ifdef WIN32
|
|
HANDLE hInst=ShellExecute(NULL,"open",(LPCTSTR)temppath.c_str(),NULL,NULL,SW_SHOWNORMAL);
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
|
|
if (!pe.frompak)
|
|
{
|
|
#ifdef WIN32
|
|
HANDLE hInst=ShellExecute(NULL,"open",(LPCTSTR)pe.pathname.c_str(),NULL,NULL,SW_SHOWNORMAL);
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
if (pe.frompak)
|
|
{
|
|
CPak p;
|
|
if (!p.Open(pe.pakname.c_str()))
|
|
return;
|
|
|
|
if (!p.ExtractTo(path.c_str(),(char *)temppath.c_str()))
|
|
return;
|
|
|
|
temp_files.push_back(temppath);
|
|
|
|
// view it
|
|
#ifdef WIN32
|
|
HANDLE hInst=ShellExecute(NULL,"open",(LPCTSTR)temppath.c_str(),NULL,NULL,SW_SHOWNORMAL);
|
|
#endif
|
|
return;
|
|
}
|
|
}
|
|
|
|
#ifdef WIN32
|
|
void ShortToLong(CString &thePath)
|
|
{
|
|
WIN32_FIND_DATA wfd;
|
|
std::string spath=thePath.GetBuffer();
|
|
std::string lpath="";
|
|
while(1)
|
|
{
|
|
FindFirstFile(spath.c_str(),&wfd);
|
|
std::string fname=wfd.cFileName;
|
|
lpath=fname+"\\"+lpath;
|
|
long pos=spath.find_last_of('\\');
|
|
spath=spath.substr(0,pos);
|
|
pos=spath.find_last_of('\\');
|
|
|
|
if (pos==-1)
|
|
{
|
|
lpath=spath+"\\"+lpath;
|
|
break;
|
|
}
|
|
}
|
|
thePath=lpath.c_str();
|
|
}
|
|
#endif
|
|
|
|
void CMainWnd::GetPaths()
|
|
{
|
|
#if 0 //mattn
|
|
#ifdef WIN32
|
|
|
|
// convert it to long format
|
|
ShortToLong(g_strBasePath);
|
|
|
|
// mod path
|
|
if (strcmp(mode,"Quake III Team Arena")==0)
|
|
{
|
|
g_strModPath=g_strBasePath;
|
|
long p=g_strModPath.Find("\\baseq3");
|
|
g_strModPath=g_strModPath.Left(p);
|
|
g_strModPath+="\\missionpack\\";
|
|
|
|
g_FuncTable.m_pfnQE_ConvertDOSToUnixName ((char *)g_strModPath.GetBuffer(), g_strModPath.GetBuffer());
|
|
}
|
|
|
|
g_FuncTable.m_pfnQE_ConvertDOSToUnixName ((char *)g_strBasePath.GetBuffer(), g_strBasePath.GetBuffer());
|
|
|
|
// apppath
|
|
// get path to the editor
|
|
char* pBuffer = g_strAppPath.GetBufferSetLength(_MAX_PATH + 1);
|
|
GetModuleFileName(NULL, pBuffer, _MAX_PATH);
|
|
pBuffer[g_strAppPath.ReverseFind('\\') + 1] = '\0';
|
|
g_strAppPath.ReleaseBuffer();
|
|
g_FuncTable.m_pfnQE_ConvertDOSToUnixName ((char *)g_strAppPath.GetBuffer(), g_strAppPath.GetBuffer());
|
|
|
|
char temp_path[_MAX_PATH];
|
|
GetTempPath(_MAX_PATH,temp_path);
|
|
g_strTempPath=temp_path;
|
|
|
|
#endif
|
|
|
|
#ifdef __linux__
|
|
Str tmp;
|
|
tmp = g_strBasePath.GetBuffer();
|
|
tmp += "/../";
|
|
|
|
// NOTE: we build g_strAppPath with a '/' (or '\' on WIN32)
|
|
// it's a general convention in Radiant to have the slash at the end of directories
|
|
char real[PATH_MAX];
|
|
realpath (tmp.GetBuffer(), real);
|
|
if (real[strlen(real)-1] != '/')
|
|
strcat(real, "/");
|
|
g_strAppPath = real;
|
|
|
|
g_strTempPath="~/.tmp";
|
|
#endif
|
|
|
|
extern const char *PLUGIN_NAME;
|
|
g_strBitmapsPath = g_FuncTable.m_pfnPathForPluginName(PLUGIN_NAME);
|
|
g_strBitmapsPath += "bitmaps/";
|
|
#endif
|
|
}
|
|
|
|
void CMainWnd::UpdateStatus()
|
|
{
|
|
std::string path=m_Tree.GetSelected();
|
|
|
|
if (path=="")
|
|
{
|
|
gtk_label_set_text (GTK_LABEL (m_pStatusLabel[0]), "");
|
|
gtk_label_set_text (GTK_LABEL (m_pStatusLabel[1]), "");
|
|
gtk_label_set_text (GTK_LABEL (m_pStatusLabel[2]), "");
|
|
|
|
return;
|
|
}
|
|
|
|
pak_entry pe=pak.FindPE(path.c_str());
|
|
|
|
std::string p=path;
|
|
long pos=p.find_last_of('/');
|
|
p=p.substr(pos+1);
|
|
gtk_label_set_text (GTK_LABEL (m_pStatusLabel[0]), p.c_str());
|
|
|
|
char lbl[255];
|
|
sprintf(lbl," %ldk ",pe.uncompressed/1000);
|
|
gtk_label_set_text (GTK_LABEL (m_pStatusLabel[1]), lbl);
|
|
|
|
sprintf(lbl," %ldk ",pe.compressed/1000);
|
|
gtk_label_set_text (GTK_LABEL (m_pStatusLabel[2]), lbl);
|
|
|
|
}
|
|
|
|
void CMainWnd::HandleDrop()
|
|
{
|
|
std::string path=m_Tree.GetSelected();
|
|
bool file_selected=TRUE;
|
|
|
|
if (path=="")
|
|
file_selected=FALSE;
|
|
|
|
//if (m_mnuDrop == NULL) // first time, load it up
|
|
//{
|
|
GtkAccelGroup *accel;//, *menu_in_menu_accel;
|
|
GtkWidget *menu;//, *menu_in_menu, *item, *submenu;
|
|
|
|
menu = m_mnuDrop = gtk_menu_new ();
|
|
accel = gtk_accel_group_new ();
|
|
gtk_menu_set_accel_group (GTK_MENU (menu), accel);
|
|
|
|
//menu_in_menu = create_menu_in_menu (menu, "Select", accel, &menu_in_menu_accel);
|
|
|
|
create_menu_item (menu, "Add file", accel,
|
|
GTK_SIGNAL_FUNC (HandleCommand), ID_ADD);
|
|
|
|
if (file_selected)
|
|
{
|
|
create_menu_item (menu, "View File", accel,
|
|
GTK_SIGNAL_FUNC (HandleCommand), ID_VIEW);
|
|
|
|
create_menu_item (menu, "Extract file", accel,
|
|
GTK_SIGNAL_FUNC (HandleCommand), ID_EXTRACT);
|
|
|
|
menu_separator (menu);
|
|
|
|
create_menu_item (menu, "Rename File", accel,
|
|
GTK_SIGNAL_FUNC (HandleCommand), ID_RENAME);
|
|
|
|
create_menu_item (menu, "Delete file", accel,
|
|
GTK_SIGNAL_FUNC (HandleCommand), ID_DELETE);
|
|
}
|
|
//}
|
|
|
|
gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 1, GDK_CURRENT_TIME);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////
|
|
// some handy stuff ripped from GtkRadiant
|
|
////////////////////////////////////////////
|
|
|
|
|
|
GtkWidget* create_menu_in_menu (GtkWidget *menu, gchar *label, GtkAccelGroup *menu_accel,
|
|
GtkAccelGroup **submenu_accel)
|
|
{
|
|
GtkWidget *item, *submenu;
|
|
guint tmp_key;
|
|
|
|
item = gtk_menu_item_new_with_label ("");
|
|
tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (item)->child), label);
|
|
gtk_widget_add_accelerator (item, "activate_item", menu_accel, tmp_key, 0, (GtkAccelFlags)0);
|
|
gtk_widget_show (item);
|
|
gtk_container_add (GTK_CONTAINER (menu), item);
|
|
|
|
submenu = gtk_menu_new ();
|
|
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
|
|
*submenu_accel = gtk_accel_group_new ();
|
|
gtk_menu_set_accel_group (GTK_MENU (submenu), *submenu_accel);
|
|
|
|
return submenu;
|
|
}
|
|
|
|
GtkWidget* create_menu_item (GtkWidget *menu, gchar *label, GtkAccelGroup *menu_accel,
|
|
GtkSignalFunc func, int id)
|
|
{
|
|
GtkWidget *item;
|
|
guint tmp_key;
|
|
|
|
#ifdef NO_UNDERSCORE
|
|
char label_tmp[1024];
|
|
strcpy( label_tmp, label );
|
|
if (char* c = strchr (label_tmp, '_'))
|
|
while (*c)
|
|
*c++ = *(c+1);
|
|
item = gtk_menu_item_new_with_label (label_tmp);
|
|
#else
|
|
item = gtk_menu_item_new_with_label ("");
|
|
tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (item)->child), label);
|
|
gtk_widget_add_accelerator (item, "activate_item", menu_accel, tmp_key, 0, (GtkAccelFlags)0);
|
|
#endif
|
|
gtk_widget_show (item);
|
|
gtk_container_add (GTK_CONTAINER (menu), item);
|
|
gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (func), GINT_TO_POINTER (id));
|
|
|
|
|
|
return item;
|
|
}
|
|
|
|
GtkWidget* menu_separator (GtkWidget *menu)
|
|
{
|
|
GtkWidget *menu_item = gtk_menu_item_new ();
|
|
gtk_menu_append (GTK_MENU (menu), menu_item);
|
|
gtk_widget_set_sensitive (menu_item, FALSE);
|
|
gtk_widget_show (menu_item);
|
|
return menu_item;
|
|
}
|