1 // MainWnd.cpp: implementation of the CMainWnd class.
3 //////////////////////////////////////////////////////////////////////
10 #include "renamedlg.h"
16 extern CMainWnd *g_pMainWnd;
17 bool g_bIgnoreCommands=FALSE;
19 GtkWidget* create_menu_in_menu (GtkWidget *menu, gchar *label, GtkAccelGroup *menu_accel,GtkAccelGroup **submenu_accel);
20 GtkWidget* create_menu_item (GtkWidget *menu, gchar *label, GtkAccelGroup *menu_accel,GtkSignalFunc func, int id);
21 GtkWidget* menu_separator (GtkWidget *menu);
23 //////////////////////////////////////////////////////////////////////
24 // Construction/Destruction
25 //////////////////////////////////////////////////////////////////////
27 static gint mainwnd_delete (GtkWidget *widget, gpointer data)
29 return g_pMainWnd->OnClose();
32 static void HandleCommand (GtkWidget *widget, gpointer data)
34 int id = GPOINTER_TO_INT (data);
36 if (g_bIgnoreCommands)
41 case ID_FILE_NEW: g_pMainWnd->OnFileNew (); break;
42 case ID_FILE_OPEN: g_pMainWnd->OnFileOpen (); break;
43 case ID_FILE_SAVE: g_pMainWnd->OnFileSave (); break;
45 case ID_WIZARD: g_pMainWnd->OnWizard (); break;
47 case ID_VIEW: g_pMainWnd->OnView (); break;
48 case ID_EXTRACT: g_pMainWnd->OnExtract (); break;
50 case ID_ADD: g_pMainWnd->OnAdd (); break;
51 case ID_RENAME: g_pMainWnd->OnRename (); break;
52 case ID_DELETE: g_pMainWnd->OnDelete (); break;
68 bool CMainWnd::OnClose()
72 //int ret=DoMessageBox("Pk3 has not been saved\n\n Really quit?","Pk3Man",MB_YESNO);
73 int ret=g_FuncTable.m_pfnMessageBox(m_pMainWnd,"Pk3 has not been saved\n\n Really quit?","Pk3Man",MB_YESNO, NULL);
83 void CMainWnd::OnDestroy()
88 BOOL CMainWnd::Create(GtkWidget *parent)
90 GtkWidget *vbox,*window;
91 GdkPixmap *pixmap=NULL;
94 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////..", "..////////////////////////////..", "..////////////////////////////..", "..////////////////////////////..", "..////////////////////////////..", "..////////////////////////////..", "..////////////////////////////..", "..////////////////////////////..", "..////////////////////////////..", "..////..//////....//////..////..", "..////..//////....//////..////..", "..//......////....////......//..", "..//......////....////......//..", "................................", "................................"};
99 // create the main widget
100 m_pMainWnd = window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
101 gtk_signal_connect (GTK_OBJECT (window), "delete_event", GTK_SIGNAL_FUNC (mainwnd_delete), this);
102 //gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (gtk_widget_destroy), this);
104 gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
105 gtk_window_set_title (GTK_WINDOW (m_pMainWnd), "Pk3Man - ");
106 gtk_window_set_default_size (GTK_WINDOW (m_pMainWnd), 300, 300);
107 gtk_widget_show (m_pMainWnd);
109 // load and set the icon
111 pixmap = gdk_pixmap_create_from_xpm_d (window->window, &mask, NULL, icon_xpm);
112 gdk_window_set_icon (window->window, NULL, pixmap, mask);
114 // setup the vertical layout box
115 vbox=gtk_vbox_new (FALSE, 0);
116 gtk_container_add (GTK_CONTAINER (window), vbox);
117 gtk_widget_show (vbox);
119 if (!CreateToolbar (window, vbox))
122 if (!CreateTreeView (window, vbox))
125 if (!CreateStatusBar (window,vbox))
137 BOOL CMainWnd::CreateTreeView(GtkWidget *window,GtkWidget *vbox)
139 // create a scrollable widget to house the tree
140 m_ScrolledWin = gtk_scrolled_window_new (NULL, NULL);
141 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (m_ScrolledWin),
142 GTK_POLICY_AUTOMATIC,
143 GTK_POLICY_AUTOMATIC);
145 //gtk_widget_set_usize (m_ScrolledWin, 400, 400);
146 gtk_box_pack_start (GTK_BOX (vbox), m_ScrolledWin, TRUE, TRUE, 0);
147 gtk_widget_show (m_ScrolledWin);
149 // attach and initialise the tree
150 m_Tree.Init(m_ScrolledWin);
155 BOOL CMainWnd::CreateToolbar(GtkWidget *window,GtkWidget *vbox)
157 GtkWidget *handle_box, *toolbar, *w;
159 handle_box = gtk_handle_box_new ();
160 gtk_box_pack_start (GTK_BOX (vbox), handle_box, FALSE, FALSE, 0);
161 gtk_widget_show (handle_box);
163 m_Toolbar = toolbar = gtk_toolbar_new ();
165 // gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), user_rc.toolbar_style);
166 gtk_container_add (GTK_CONTAINER (handle_box), toolbar);
167 gtk_container_border_width (GTK_CONTAINER (toolbar), 2);
168 gtk_widget_show (toolbar);
171 w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
175 CPixMap::new_pixmap(window, "pk3man_tbnew.bmp"),
176 //CPixMap::pixmap_from_char(window,xpm_new),
177 GTK_SIGNAL_FUNC (HandleCommand),
178 GINT_TO_POINTER (ID_FILE_NEW));
180 gtk_object_set_data (GTK_OBJECT (window), "tb_file_new", w);
183 w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
185 "Open an existing Pk3",
187 CPixMap::new_pixmap(window, "pk3man_tbopen.bmp"),
188 GTK_SIGNAL_FUNC (HandleCommand),
189 GINT_TO_POINTER (ID_FILE_OPEN));
191 gtk_object_set_data (GTK_OBJECT (window), "tb_file_open", w);
194 w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
196 "Save the current Pk3",
198 CPixMap::new_pixmap (window, "pk3man_tbsave.bmp"),
199 GTK_SIGNAL_FUNC (HandleCommand),
200 GINT_TO_POINTER (ID_FILE_SAVE));
202 gtk_object_set_data (GTK_OBJECT (window), "tb_file_save", w);
205 gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
208 w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
210 "Build Pk3 from a Map",
212 CPixMap::new_pixmap (window, "pk3man_tbwizard.bmp"),
213 GTK_SIGNAL_FUNC (HandleCommand),
214 GINT_TO_POINTER (ID_WIZARD));
216 gtk_object_set_data (GTK_OBJECT (window), "tb_wizard", w);
219 gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
222 w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
226 CPixMap::new_pixmap (window, "pk3man_tbview.bmp"),
227 GTK_SIGNAL_FUNC (HandleCommand),
228 GINT_TO_POINTER (ID_VIEW));
230 gtk_object_set_data (GTK_OBJECT (window), "tb_view", w);
233 w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
237 CPixMap::new_pixmap (window, "pk3man_tbextract.bmp"),
238 GTK_SIGNAL_FUNC (HandleCommand),
239 GINT_TO_POINTER (ID_EXTRACT));
241 gtk_object_set_data (GTK_OBJECT (window), "tb_extract", w);
244 gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
247 w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
251 CPixMap::new_pixmap (window, "pk3man_tbadd.bmp"),
252 GTK_SIGNAL_FUNC (HandleCommand),
253 GINT_TO_POINTER (ID_ADD));
255 gtk_object_set_data (GTK_OBJECT (window), "tb_add", w);
258 w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
262 CPixMap::new_pixmap (window, "pk3man_tbrename.bmp"),
263 GTK_SIGNAL_FUNC (HandleCommand),
264 GINT_TO_POINTER (ID_RENAME));
266 gtk_object_set_data (GTK_OBJECT (window), "tb_rename", w);
270 w = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
274 CPixMap::new_pixmap (window, "pk3man_tbdelete.bmp"),
275 GTK_SIGNAL_FUNC (HandleCommand),
276 GINT_TO_POINTER (ID_DELETE));
278 gtk_object_set_data (GTK_OBJECT (window), "tb_delete", w);
283 void CMainWnd::UpdateToolBar()
285 std::string path=m_Tree.GetSelected();
286 bool file_selected=TRUE;
293 // enable toolbar buttons
297 item = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_view"));
298 //gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), FALSE);
299 gtk_widget_set_sensitive (item, TRUE);
301 item = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_extract"));
302 //gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), FALSE);
303 gtk_widget_set_sensitive (item, TRUE);
305 item = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_delete"));
306 //gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), FALSE);
307 gtk_widget_set_sensitive (item, TRUE);
309 item = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_rename"));
310 //gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), FALSE);
311 gtk_widget_set_sensitive (item, TRUE);
316 // disable toolbar buttons
320 item = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_view"));
321 //gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), TRUE);
322 gtk_widget_set_sensitive (item, TRUE);
324 item = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_extract"));
325 //gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), TRUE);
326 gtk_widget_set_sensitive (item, TRUE);
328 item = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_delete"));
329 //gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), TRUE);
330 gtk_widget_set_sensitive (item, TRUE);
332 item = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (m_pMainWnd), "tb_rename"));
333 //gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (item), TRUE);
334 gtk_widget_set_sensitive (item, TRUE);
340 BOOL CMainWnd::CreateStatusBar(GtkWidget *window,GtkWidget *vbox)
342 GtkWidget *hbox, *hbox1;
346 hbox = gtk_hbox_new (FALSE, 0);
347 gtk_widget_show (hbox);
348 gtk_widget_set_usize (hbox, -1, 24);
349 gtk_container_border_width (GTK_CONTAINER (hbox), 1);
350 gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, TRUE, 2);
352 frame = gtk_frame_new ((char*)NULL);
353 gtk_widget_show (frame);
354 gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
355 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
357 hbox1 = gtk_hbox_new (FALSE, 0);
358 gtk_container_add (GTK_CONTAINER (frame), hbox1);
359 gtk_container_border_width (GTK_CONTAINER (hbox1), 0);
360 gtk_widget_show (hbox1);
362 label = gtk_label_new (" Ready ... ");
363 gtk_widget_show (label);
364 gtk_box_pack_start (GTK_BOX (hbox1), label, FALSE, TRUE, 0);
365 gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
366 gtk_misc_set_padding (GTK_MISC (label), 3, 0);
367 m_pStatusLabel[0] = label;
369 for (int i = 1; i < 3; i++)
371 frame = gtk_frame_new ((char*)NULL);
372 gtk_widget_show (frame);
373 gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
374 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
376 label = gtk_label_new (" ");
377 gtk_widget_show (label);
378 gtk_container_add (GTK_CONTAINER (frame), label);
379 m_pStatusLabel[i] = label;
385 void CMainWnd::OnFileOpen()
388 const char *filename;
390 if (g_strModPath.GetLength()>0)
391 //filename=file_dialog(TRUE,"Choose a Pk3...",g_strModPath.GetBuffer(),"*.pk3");
392 filename=g_FuncTable.m_pfnFileDialog (m_pMainWnd, TRUE, "Choose a Pk3...",
393 g_strModPath.GetBuffer(), "pk3man");
395 //filename=file_dialog(TRUE,"Choose a Pk3...",g_strBasePath.GetBuffer(),"*.pk3");
396 filename=g_FuncTable.m_pfnFileDialog (m_pMainWnd, TRUE, "Choose a Pk3...",
397 g_strBasePath.GetBuffer(), "pk3man");
403 fname=fname.Right(3);
406 //DoMessageBox("Please pick a Pk3 file","Pk3Man",MB_OK);
407 g_FuncTable.m_pfnMessageBox(m_pMainWnd,"Please pick a Pk3 file","Pk3Man",MB_OK, NULL);
415 // update window title
416 g_FuncTable.m_pfnQE_ConvertDOSToUnixName (filename, filename);
417 std::string title=filename;
419 long pos=title.find_last_of('/');
420 title=title.substr(pos+1);
421 title="Pk3Man - "+title;
422 gtk_window_set_title (GTK_WINDOW (m_pMainWnd), title.c_str());
425 void CMainWnd::OnFileSave()
427 const char *filename;
429 if (g_strModPath.GetLength()>0)
430 filename=g_FuncTable.m_pfnFileDialog (m_pMainWnd, FALSE, "Save As...",
431 g_strModPath.GetBuffer(), "pk3man");
433 filename=g_FuncTable.m_pfnFileDialog (m_pMainWnd, FALSE, "Save As...",
434 g_strBasePath.GetBuffer(), "pk3man");
439 g_FuncTable.m_pfnQE_ConvertDOSToUnixName (filename, filename);
440 std::string path=filename;
442 long p=path.find_last_of('/');
443 std::string name=path.substr(p,-1);
445 std::string tpath=g_strTempPath.GetBuffer() + name;
447 if (!pak.Save(tpath.c_str()))
449 // eek, error central
450 g_FuncTable.m_pfnMessageBox(m_pMainWnd,"Unable to save the pk3 to temp folder!","Pk3Man",MB_OK, NULL);
454 // ok, now copy to proper place
458 int ret=CopyFile(tpath.c_str(),path.c_str(),FALSE);
459 DeleteFile(tpath.c_str());
463 g_FuncTable.m_pfnMessageBox(m_pMainWnd,"Unable to copy pk3 from temp folder!","Pk3Man",MB_OK, NULL);
470 pak.Open(path.c_str());
475 name=name.substr(1,-1);
476 std::string title="Pk3Man - "+name;
477 gtk_window_set_title (GTK_WINDOW (m_pMainWnd), title.c_str());
480 bool CMainWnd::OnFileNew()
482 if (pak.IsModified())
484 int ret=g_FuncTable.m_pfnMessageBox(m_pMainWnd,"This will lose the current Pk3 contents\n\n Are u sure?","Pk3Man",MB_YESNO, NULL);
491 gtk_window_set_title (GTK_WINDOW (m_pMainWnd), "Pk3Man - ");
496 void CMainWnd::LoadExclusions()
501 std::string filename=g_strAppPath.GetBuffer();
502 filename+="plugins/pk3man.exclude";
504 fp=fopen(filename.c_str(),"rb");
510 std::string line=GetLine(fp);
512 if (line.length()==0)
515 if (line[0]=='/' && line[1]=='/')
518 for (int n=0 ; n < (int)line.length() ; n++)
525 line=line.substr(1,-1);
527 exclusions.push_back(line);
531 bool CMainWnd::IsExcluded(const char *name)
533 for (std::list<std::string>::iterator i=exclusions.begin() ; i!=exclusions.end() ; i++)
537 if (CWild::fpattern_match(t.c_str(),name))
541 if (nm.find(t) != static_cast<size_t>(-1))
548 void CMainWnd::OnWizard()
552 int ret=g_FuncTable.m_pfnMessageBox(m_pMainWnd,"Add to current pak contents ?","Pk3Man",MB_YESNO, NULL);
561 std::string mappath="maps";
562 mappath=g_strBasePath.GetBuffer()+mappath;
564 gchar *filename=g_FuncTable.m_pfnFileDialog(m_pMainWnd,TRUE,"Choose a Map...",mappath.c_str(),"pk3man");
569 g_FuncTable.m_pfnQE_ConvertDOSToUnixName (filename, filename);
570 std::string map=filename;
571 long p=map.find_last_of('/');
572 map=map.substr(p+1,-1);
575 std::string title="Pk3Man - "+map;
576 gtk_window_set_title (GTK_WINDOW (m_pMainWnd), title.c_str());
579 ProcessFile(map.c_str(),".bsp","maps");
580 ProcessFile(map.c_str(),".aas","maps");
583 if (!ProcessFile(map.c_str(),".jpg","levelshots"))
584 ProcessFile(map.c_str(),".tga","levelshots");
587 ProcessFile(map.c_str(),".arena","scripts");
589 // initialise text list
592 // generate item list
594 fp=fopen(filename,"r");
602 std::string line=GetLine(fp);
604 if (line.find("// brush")!=static_cast<size_t>(-1))
610 if (line.find("patchDef")!=static_cast<size_t>(-1))
616 // need to trim left and right
617 int n=line.find_first_not_of(' ');
618 if (n!=static_cast<size_t>(-1))
621 std::string tex="textures/"+line;
622 AddToTexList(line.c_str());
626 // its a standard brush
627 while (line.find_first_of('}')==static_cast<size_t>(-1))
629 long p=line.find_last_of(')');
630 line=line.substr(p+2,-1);
632 p=line.find_first_of(' ');
633 line=line.substr(0,p);
635 std::string tex="textures/"+line;
636 AddToTexList(line.c_str());
643 else if (line.find(".md3")!=static_cast<size_t>(-1))
645 long p=line.find_first_of(' ');
646 std::string tex=line.substr(p+2,-1);
647 tex=tex.substr(0,tex.length()-2);
649 AddToTexList(tex.c_str());
651 else if (line.find(".wav")!=static_cast<size_t>(-1))
653 long p=line.find_first_of(' ');
654 std::string tex=line.substr(p+2,-1);
655 tex=tex.substr(0,tex.length()-2);
657 AddToTexList(tex.c_str());
663 // ok, now proccess our texlist
664 // if we find a shader we add its textures onto the end of the texlist
666 for ( std::list<std::string>::const_iterator i = texlist.begin() ; i != texlist.end() ; i++)
673 std::string suffix=tex.substr(tex.length()-3,-1);
676 if (suffix.compare("md3")==0)
678 ParseModel(tex.c_str());
684 // does it exist as it is
685 if (ProcessFile(tex.c_str()))
689 std::string shadername=tex;
690 const char *sname=NULL;
692 IShader *shader=g_ShadersTable.m_pfnShader_ForName_NoLoad(shadername.c_str());
695 sname=shader->getShaderFileName();
699 ParseShader(sname,tex.c_str());
701 if (ProcessFile(sname))
705 // ok we got this far, its a texture
707 if (tex.find(".tga")!=static_cast<size_t>(-1) || tex.find(".jpg")!=static_cast<size_t>(-1))
708 tex=tex.substr(0,tex.length()-4);
711 std::string jpeg=tex;
712 if (jpeg.find("textures/")!=0)
713 jpeg="textures/"+jpeg;
716 if (ProcessFile(jpeg.c_str()))
721 if (tga.find("textures/")!=0)
725 if (ProcessFile(tga.c_str()))
732 void CMainWnd::ParseModel(const char *pathname)
735 int len = g_FuncTable.m_pfnLoadFile(pathname, (void**)&modelbuff);
740 CMemFile file(modelbuff,len);
744 file.Read(&header,sizeof(header));
746 int n, numtags=header.Tag_num*header.BoneFrame_num;
748 for (n=0 ; n<numtags ; n++)
751 file.Read(&tag,sizeof(md3_tag_t));
754 for (n=0 ; n<header.BoneFrame_num ; n++)
756 md3_boneframe_t bone;
757 file.Read(&bone,sizeof(md3_boneframe_t));
760 for (int m=0 ; m<header.Mesh_num ; m++)
763 file.Read(&mesh,sizeof(md3_mesh_t));
766 for (n=0 ; n<mesh.Skin_num ; n++)
769 file.Read(&SkinName,sizeof(char)*68);
771 // deal with the skin here
772 // we add it to the end of the list (if it aint already there)
773 // so we catch it later on
775 AddToTexList(SkinName);
779 for (n=0 ; n<mesh.Triangle_num ; n++)
782 file.Read(&Triangle,sizeof(int)*3);
786 for (n=0 ; n<mesh.Vertex_num ; n++)
789 file.Read(&uv,sizeof(float)*2);
793 int numverts=mesh.Vertex_num*mesh.MeshFrame_num;
795 for (n=0 ; n<numverts ; n++)
797 md3_vertices_t verts;
798 file.Read(&verts,sizeof(md3_vertices_t));
803 // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=491
807 void CMainWnd::AddToTexList(const char *buf)
812 while (buf[c]!=' ' && buf[c]!='\0')
818 if (!IsInTexList(tex.c_str()))
819 texlist.push_back(tex);
823 void CMainWnd::InitPaksInDir(const char *folder)
825 struct dirent *dirlist;
828 dir = opendir (g_strBasePath.GetBuffer());
832 while ((dirlist = readdir (dir)) != NULL)
834 if (!strstr (dirlist->d_name, ".pk3"))
837 std::string path=g_strBasePath.GetBuffer();
838 path+=dirlist->d_name;
840 if (IsExcluded(dirlist->d_name))
845 if (p->Open(path.c_str()))
846 paklist.push_back(p);
854 void CMainWnd::InitPakList()
856 gtk_label_set_text (GTK_LABEL (m_pStatusLabel[0]), "Building pk3 references");
858 if (g_strModPath.GetLength()>0)
859 InitPaksInDir(g_strModPath.GetBuffer());
861 InitPaksInDir(g_strBasePath.GetBuffer());
863 gtk_label_set_text (GTK_LABEL (m_pStatusLabel[0]), "Ready ...");
866 void CMainWnd::FreePakList()
868 std::list<CPak*>::iterator i;
870 for ( i = paklist.begin() ; i != paklist.end() ; i++)
879 void CMainWnd::DeleteTempFiles()
881 std::list<std::string>::iterator i;
883 for ( i = temp_files.begin() ; i != temp_files.end() ; i++)
887 remove(path.c_str());
893 bool CMainWnd::IsInTexList(const char *tex)
895 for ( std::list<std::string>::const_iterator i = texlist.begin() ; i != texlist.end() ; i++)
899 if (str.compare(tex)==0)
906 void CMainWnd::SkipLines(FILE *fp, int n)
908 for (int c=0 ; c<n ; c++)
909 std::string line=GetLine(fp);
912 std::string CMainWnd::GetLine(FILE *fp)
922 if (c!='\n' && c!='\t' && c!='\r')
925 } while (c!='\n' && !feof(fp));
931 std::string CMainWnd::TrimString(const char *str)
936 while (str[c]==' ' || str[c]=='\t')
940 while (str[e]==' ' || str[e]=='\n' || str[e]=='\r')
944 out=out.substr(c,-1);
949 void CMainWnd::ParseShader(const char *pathname, const char *tex)
951 if (pathname==NULL || tex==NULL)
955 int len = g_FuncTable.m_pfnLoadFile(pathname, (void**)&shaderbuff);
960 std::string shader=shaderbuff;
962 // skip to start of shader
963 long pos=shader.find(tex);
965 if (pos==-1) // shader not found????
968 shader=shader.substr(pos);
973 // step through the lines
976 pos=shader.find_first_of('\n');
980 std::string line=shader.substr(0,pos-1);
981 shader=shader.substr(pos+1,-1);
983 line=TrimString(line.c_str());
988 if (line[0]=='/' && line[1]=='/')
1015 // check for map/animmap e.t.c;
1020 if (line.substr(0,3).compare("map")==0)
1022 std::string map=line.substr(4,-1);
1023 AddToTexList(map.c_str());
1027 if (line.substr(0,8).compare("skyparms")==0)
1029 std::string map=line.substr(9,-1);
1030 AddToTexList(map.c_str());
1034 if (line.substr(0,8).compare("clampmap")==0)
1036 std::string map=line.substr(9,-1);
1037 AddToTexList(map.c_str());
1041 if (line.substr(0,7).compare("animmap")==0)
1043 std::string map=line.substr(9,-1);
1044 map=TrimString(map.c_str());
1046 // skip past numbers
1047 long p=map.find_first_of(' ');
1048 map=map.substr(p+1,-1);
1052 long pos=map.find_first_of(' ');
1056 AddToTexList(map.c_str());
1060 std::string tex=map.substr(0,pos);
1061 AddToTexList(tex.c_str());
1063 map=map.substr(pos+1,-1);
1068 // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=491
1072 bool CMainWnd::ProcessFile(const char *nm,const char *suffix,const char *folder)
1074 std::string name=nm;
1075 name=name.substr(0,name.length()-4);
1080 if (g_strModPath.GetLength()>0)
1081 path=g_strModPath.GetBuffer();
1083 path=g_strBasePath.GetBuffer();
1089 std::string rpath=folder;
1093 if (IsExcluded(rpath.c_str())) // quit out with a FALSE so we try others
1097 fp=fopen(path.c_str(),"rb");
1101 if (!pak.IsInPak(rpath.c_str()))
1103 m_Tree.AddPath(rpath.c_str());
1104 pak.AddExternalFile(rpath.c_str(),path.c_str());
1111 return FindInAPk3(rpath.c_str());
1117 bool CMainWnd::ProcessFile(const char *nm)
1119 std::string name=nm;
1121 if (IsExcluded(name.c_str())) // quit out with a TRUE so we think it was added
1126 if (g_strModPath.GetLength()>0)
1127 path=g_strModPath.GetBuffer();
1129 path=g_strBasePath.GetBuffer();
1134 fp=fopen(path.c_str(),"rb");
1138 if (!pak.IsInPak(name.c_str()))
1140 m_Tree.AddPath(name.c_str());
1141 pak.AddExternalFile(name.c_str(),path.c_str());
1148 return FindInAPk3(name.c_str());
1155 bool CMainWnd::FindInAPk3(const char *name)
1157 std::list<CPak*>::iterator i;
1159 for ( i = paklist.begin() ; i != paklist.end() ; i++)
1163 if (p->m_filename.CompareNoCase(pak.m_filename)==0)
1166 std::string fname=p->m_filename.GetBuffer();
1167 long pos=fname.find_last_of('/');
1168 fname=fname.substr(pos+1,-1);
1170 if (IsExcluded(fname.c_str()))
1173 if (p->IsInPak(name))
1175 pak_entry pe=p->FindPE(name);
1176 m_Tree.AddPath(name);
1177 pak.AddPakFile(name,p->m_filename.GetBuffer(),pe.compressed,pe.uncompressed);
1184 void CMainWnd::OnAdd()
1187 if (g_strModPath.GetLength()>0)
1188 path=g_strModPath.GetBuffer();
1190 path=g_strBasePath.GetBuffer();
1192 //char *filename=file_dialog(TRUE,"Choose a file...",path.c_str(),"*.*");
1193 gchar *filename=g_FuncTable.m_pfnFileDialog(m_pMainWnd,TRUE,"Choose a file...",path.c_str(),"pk3man");
1200 while (filename[c]!='\0')
1202 if (filename[c]=='\\')
1208 std::string fname=filename;
1210 long p=path.length();
1211 fname=fname.substr(p,-1);
1213 if (pak.IsInPak((char*)fname.c_str()))
1216 pak.AddExternalFile((char *)fname.c_str(),(char *)filename);
1217 m_Tree.AddPath((char *)fname.c_str());
1221 void CMainWnd::OnDelete()
1223 std::string path=m_Tree.GetSelected();
1228 pak.Delete(path.c_str());
1230 //m_Tree.RemovePath(path.c_str());
1232 // dodgy hack but works for now
1238 void CMainWnd::OnRename()
1240 std::string path=m_Tree.GetSelected();
1248 if (dlg.DoModal()==IDOK)
1250 pak.Rename(path.c_str(),dlg.m_Name.c_str());
1257 void CMainWnd::UpdateTree()
1259 // clear the tree and fill it with the items in the pak
1261 for ( std::list<pak_entry>::const_iterator iEntry = pak.entries.begin() ; iEntry != pak.entries.end() ; iEntry++)
1263 pak_entry pe=*iEntry;
1271 m_Tree.AddPath(name.c_str());
1276 void CMainWnd::OnExtract()
1278 std::string path=m_Tree.GetSelected();
1283 pak_entry pe=pak.FindPE((char*)path.c_str());
1286 if (g_strModPath.GetLength()>0)
1287 bpath=g_strModPath.GetBuffer();
1289 bpath=g_strBasePath.GetBuffer();
1291 //char *pathto=dir_dialog("Extract to ...",bpath.c_str());
1292 gchar *pathto=g_FuncTable.m_pfnDirDialog(m_pMainWnd,"Extract to...",bpath.c_str());
1297 long pos=path.find_last_of('/');
1298 std::string name=path.substr(pos+1);
1300 std::string cpath=pathto;
1303 if (pe.pakname.compare(pak.m_filename.GetBuffer())==0)
1306 pak.ExtractTo((char*)path.c_str(),(char*)cpath.c_str());
1312 void CMainWnd::OnView()
1314 std::string path=m_Tree.GetSelected();
1319 pak_entry pe=pak.FindPE(path.c_str());
1321 long p=pe.filename.find_last_of('/');
1322 std::string name=pe.filename.substr(p+1,-1);
1323 std::string temppath=g_strTempPath.GetBuffer()+name;
1325 if (pe.frompak && pe.pakname.compare(pak.m_filename.GetBuffer())==0)
1328 if (!pak.ExtractTo(path.c_str(),(char *)temppath.c_str()))
1331 temp_files.push_back(temppath);
1335 HANDLE hInst=ShellExecute(NULL,"open",(LPCTSTR)temppath.c_str(),NULL,NULL,SW_SHOWNORMAL);
1344 HANDLE hInst=ShellExecute(NULL,"open",(LPCTSTR)pe.pathname.c_str(),NULL,NULL,SW_SHOWNORMAL);
1352 if (!p.Open(pe.pakname.c_str()))
1355 if (!p.ExtractTo(path.c_str(),(char *)temppath.c_str()))
1358 temp_files.push_back(temppath);
1362 HANDLE hInst=ShellExecute(NULL,"open",(LPCTSTR)temppath.c_str(),NULL,NULL,SW_SHOWNORMAL);
1369 void ShortToLong(CString &thePath)
1371 WIN32_FIND_DATA wfd;
1372 std::string spath=thePath.GetBuffer();
1373 std::string lpath="";
1376 FindFirstFile(spath.c_str(),&wfd);
1377 std::string fname=wfd.cFileName;
1378 lpath=fname+"\\"+lpath;
1379 long pos=spath.find_last_of('\\');
1380 spath=spath.substr(0,pos);
1381 pos=spath.find_last_of('\\');
1385 lpath=spath+"\\"+lpath;
1389 thePath=lpath.c_str();
1393 void CMainWnd::GetPaths()
1398 // convert it to long format
1399 ShortToLong(g_strBasePath);
1402 if (strcmp(mode,"Quake III Team Arena")==0)
1404 g_strModPath=g_strBasePath;
1405 long p=g_strModPath.Find("\\baseq3");
1406 g_strModPath=g_strModPath.Left(p);
1407 g_strModPath+="\\missionpack\\";
1409 g_FuncTable.m_pfnQE_ConvertDOSToUnixName ((char *)g_strModPath.GetBuffer(), g_strModPath.GetBuffer());
1412 g_FuncTable.m_pfnQE_ConvertDOSToUnixName ((char *)g_strBasePath.GetBuffer(), g_strBasePath.GetBuffer());
1415 // get path to the editor
1416 char* pBuffer = g_strAppPath.GetBufferSetLength(_MAX_PATH + 1);
1417 GetModuleFileName(NULL, pBuffer, _MAX_PATH);
1418 pBuffer[g_strAppPath.ReverseFind('\\') + 1] = '\0';
1419 g_strAppPath.ReleaseBuffer();
1420 g_FuncTable.m_pfnQE_ConvertDOSToUnixName ((char *)g_strAppPath.GetBuffer(), g_strAppPath.GetBuffer());
1422 char temp_path[_MAX_PATH];
1423 GetTempPath(_MAX_PATH,temp_path);
1424 g_strTempPath=temp_path;
1430 tmp = g_strBasePath.GetBuffer();
1433 // NOTE: we build g_strAppPath with a '/' (or '\' on WIN32)
1434 // it's a general convention in Radiant to have the slash at the end of directories
1435 char real[PATH_MAX];
1436 realpath (tmp.GetBuffer(), real);
1437 if (real[strlen(real)-1] != '/')
1439 g_strAppPath = real;
1441 g_strTempPath="~/.tmp";
1444 extern const char *PLUGIN_NAME;
1445 g_strBitmapsPath = g_FuncTable.m_pfnPathForPluginName(PLUGIN_NAME);
1446 g_strBitmapsPath += "bitmaps/";
1450 void CMainWnd::UpdateStatus()
1452 std::string path=m_Tree.GetSelected();
1456 gtk_label_set_text (GTK_LABEL (m_pStatusLabel[0]), "");
1457 gtk_label_set_text (GTK_LABEL (m_pStatusLabel[1]), "");
1458 gtk_label_set_text (GTK_LABEL (m_pStatusLabel[2]), "");
1463 pak_entry pe=pak.FindPE(path.c_str());
1466 long pos=p.find_last_of('/');
1468 gtk_label_set_text (GTK_LABEL (m_pStatusLabel[0]), p.c_str());
1471 sprintf(lbl," %ldk ",pe.uncompressed/1000);
1472 gtk_label_set_text (GTK_LABEL (m_pStatusLabel[1]), lbl);
1474 sprintf(lbl," %ldk ",pe.compressed/1000);
1475 gtk_label_set_text (GTK_LABEL (m_pStatusLabel[2]), lbl);
1479 void CMainWnd::HandleDrop()
1481 std::string path=m_Tree.GetSelected();
1482 bool file_selected=TRUE;
1485 file_selected=FALSE;
1487 //if (m_mnuDrop == NULL) // first time, load it up
1489 GtkAccelGroup *accel;//, *menu_in_menu_accel;
1490 GtkWidget *menu;//, *menu_in_menu, *item, *submenu;
1492 menu = m_mnuDrop = gtk_menu_new ();
1493 accel = gtk_accel_group_new ();
1494 gtk_menu_set_accel_group (GTK_MENU (menu), accel);
1496 //menu_in_menu = create_menu_in_menu (menu, "Select", accel, &menu_in_menu_accel);
1498 create_menu_item (menu, "Add file", accel,
1499 GTK_SIGNAL_FUNC (HandleCommand), ID_ADD);
1503 create_menu_item (menu, "View File", accel,
1504 GTK_SIGNAL_FUNC (HandleCommand), ID_VIEW);
1506 create_menu_item (menu, "Extract file", accel,
1507 GTK_SIGNAL_FUNC (HandleCommand), ID_EXTRACT);
1509 menu_separator (menu);
1511 create_menu_item (menu, "Rename File", accel,
1512 GTK_SIGNAL_FUNC (HandleCommand), ID_RENAME);
1514 create_menu_item (menu, "Delete file", accel,
1515 GTK_SIGNAL_FUNC (HandleCommand), ID_DELETE);
1519 gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 1, GDK_CURRENT_TIME);
1523 ////////////////////////////////////////////
1524 // some handy stuff ripped from GtkRadiant
1525 ////////////////////////////////////////////
1528 GtkWidget* create_menu_in_menu (GtkWidget *menu, gchar *label, GtkAccelGroup *menu_accel,
1529 GtkAccelGroup **submenu_accel)
1531 GtkWidget *item, *submenu;
1534 item = gtk_menu_item_new_with_label ("");
1535 tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (item)->child), label);
1536 gtk_widget_add_accelerator (item, "activate_item", menu_accel, tmp_key, 0, (GtkAccelFlags)0);
1537 gtk_widget_show (item);
1538 gtk_container_add (GTK_CONTAINER (menu), item);
1540 submenu = gtk_menu_new ();
1541 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
1542 *submenu_accel = gtk_accel_group_new ();
1543 gtk_menu_set_accel_group (GTK_MENU (submenu), *submenu_accel);
1548 GtkWidget* create_menu_item (GtkWidget *menu, gchar *label, GtkAccelGroup *menu_accel,
1549 GtkSignalFunc func, int id)
1554 #ifdef NO_UNDERSCORE
1555 char label_tmp[1024];
1556 strcpy( label_tmp, label );
1557 if (char* c = strchr (label_tmp, '_'))
1560 item = gtk_menu_item_new_with_label (label_tmp);
1562 item = gtk_menu_item_new_with_label ("");
1563 tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (item)->child), label);
1564 gtk_widget_add_accelerator (item, "activate_item", menu_accel, tmp_key, 0, (GtkAccelFlags)0);
1566 gtk_widget_show (item);
1567 gtk_container_add (GTK_CONTAINER (menu), item);
1568 gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (func), GINT_TO_POINTER (id));
1574 GtkWidget* menu_separator (GtkWidget *menu)
1576 GtkWidget *menu_item = gtk_menu_item_new ();
1577 gtk_menu_append (GTK_MENU (menu), menu_item);
1578 gtk_widget_set_sensitive (menu_item, FALSE);
1579 gtk_widget_show (menu_item);