2 * Test program for PhysicsFS, using wxWidgets. May only work on Unix.
4 * Please see the file LICENSE.txt in the source's root directory.
6 * This file written by Ryan C. Gordon.
9 #if ( (defined(__MACH__)) && (defined(__APPLE__)) )
10 #define PLATFORM_MACOSX 1
11 #include <Carbon/Carbon.h>
21 #include <wx/treectrl.h>
25 #define TEST_VER_MAJOR 1
26 #define TEST_VER_MINOR 1
27 #define TEST_VER_PATCH 1
29 //static PHYSFS_uint32 do_buffer_size = 0;
31 enum WxTestPhysfsMenuCommands
33 // start with standard menu items, since using the wxIDs will map them
34 // to sane things in the platform's UI (gnome icons in GTK+, moves the
35 // about and quit items to the Apple menu on Mac OS X, etc).
36 MENUCMD_About = wxID_ABOUT,
37 MENUCMD_Quit = wxID_EXIT,
39 // non-standard menu items go here.
40 MENUCMD_Init = wxID_HIGHEST,
47 MENUCMD_PermitSymLinks,
48 MENUCMD_SetSaneConfig,
59 { "getdirsep", cmd_getdirsep, 0, NULL },
60 { "getsearchpath", cmd_getsearchpath, 0, NULL },
61 { "getbasedir", cmd_getbasedir, 0, NULL },
62 { "getuserdir", cmd_getuserdir, 0, NULL },
63 { "getwritedir", cmd_getwritedir, 0, NULL },
64 { "getrealdir", cmd_getrealdir, 1, "<fileToFind>" },
65 { "exists", cmd_exists, 1, "<fileToCheck>" },
66 { "isdir", cmd_isdir, 1, "<fileToCheck>" },
67 { "issymlink", cmd_issymlink, 1, "<fileToCheck>" },
68 { "filelength", cmd_filelength, 1, "<fileToCheck>" },
69 { "getlastmodtime", cmd_getlastmodtime, 1, "<fileToExamine>" },
74 class WxTestPhysfsFrame : public wxFrame
77 WxTestPhysfsFrame(const wxChar *argv0);
81 void onMenuInit(wxCommandEvent &evt);
82 void onMenuDeinit(wxCommandEvent &evt);
83 void onMenuAddArchive(wxCommandEvent &evt);
84 void onMenuGetCDs(wxCommandEvent &evt);
85 void onMenuPermitSymLinks(wxCommandEvent &evt);
89 wxTreeItemId stateItem;
93 void fillFileSystemTree(const char *path, const wxTreeItemId &item);
94 void doInit(const char *argv0);
100 BEGIN_EVENT_TABLE(WxTestPhysfsFrame, wxFrame)
101 EVT_MENU(MENUCMD_Init, WxTestPhysfsFrame::onMenuInit)
102 EVT_MENU(MENUCMD_Deinit, WxTestPhysfsFrame::onMenuDeinit)
103 EVT_MENU(MENUCMD_AddArchive, WxTestPhysfsFrame::onMenuAddArchive)
104 EVT_MENU(MENUCMD_GetCDs, WxTestPhysfsFrame::onMenuGetCDs)
105 EVT_MENU(MENUCMD_PermitSymLinks, WxTestPhysfsFrame::onMenuPermitSymLinks)
110 // This is the the Application itself.
111 class WxTestPhysfsApp : public wxApp
114 WxTestPhysfsApp() : mainWindow(NULL) { /* no-op. */ }
115 virtual bool OnInit();
118 WxTestPhysfsFrame *mainWindow;
121 DECLARE_APP(WxTestPhysfsApp)
124 static inline char *newstr(const char *str)
129 retval = new char[strlen(str) + 1];
135 static char *newutf8(const wxString &wxstr)
138 size_t len = wxstr.Len() + 1;
139 char *utf8text = new char[len * 6];
140 wxConvUTF8.WC2MB(utf8text, wxstr, len);
143 return newstr(wxstr);
148 WxTestPhysfsFrame::WxTestPhysfsFrame(const wxChar *argv0)
149 : wxFrame(NULL, -1, wxT("WxTestPhysfs"))
151 this->CreateStatusBar();
153 wxMenuBar *menuBar = new wxMenuBar;
155 wxMenu *stuffMenu = new wxMenu;
156 stuffMenu->Append(MENUCMD_Init, wxT("&Init"));
157 stuffMenu->Append(MENUCMD_Deinit, wxT("&Deinit"));
158 stuffMenu->Append(MENUCMD_AddArchive, wxT("&Add Archive"));
159 stuffMenu->Append(MENUCMD_Mount, wxT("&Mount Archive"));
160 stuffMenu->Append(MENUCMD_Remove, wxT("&Remove Archive"));
161 stuffMenu->Append(MENUCMD_GetCDs, wxT("&Get CD-ROM drives"));
162 stuffMenu->Append(MENUCMD_SetWriteDir, wxT("&Set Write Dir"));
163 stuffMenu->Append(MENUCMD_SetSaneConfig, wxT("Set Sane &Config"));
164 stuffMenu->Append(MENUCMD_MkDir, wxT("M&kDir"));
165 stuffMenu->Append(MENUCMD_Delete, wxT("D&elete"));
166 stuffMenu->Append(MENUCMD_Cat, wxT("&Cat"));
167 stuffMenu->Append(MENUCMD_SetBuffer, wxT("Set &Buffer"));
168 stuffMenu->Append(MENUCMD_StressBuffer, wxT("Stress &Test Buffer"));
169 stuffMenu->Append(MENUCMD_Append, wxT("&Append"));
170 stuffMenu->Append(MENUCMD_Write, wxT("&Write"));
171 stuffMenu->Append(MENUCMD_Write, wxT("&Update getLastError"));
172 stuffMenu->AppendCheckItem(MENUCMD_PermitSymLinks, wxT("&Permit symlinks"));
173 menuBar->Append(stuffMenu, wxT("&Stuff"));
175 //wxMenu *helpMenu = new wxMenu;
176 //helpMenu->Append(MENUCMD_About, wxT("&About\tF1"));
177 //menuBar->Append(helpMenu, wxT("&Help"));
179 this->SetMenuBar(menuBar);
181 this->fileTree = new wxTreeCtrl(this, -1);
183 // The sizer just makes sure that fileTree owns whole client area.
184 wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
185 sizer->Add(this->fileTree, 1, wxALL | wxEXPAND | wxALIGN_CENTRE);
186 sizer->SetItemMinSize(this->fileTree, 1, 1);
187 this->SetSizer(sizer);
189 char *utf8argv0 = newutf8(wxString(argv0));
190 this->doInit(utf8argv0);
192 } // WxTestPhysfsFrame::WxTestPhysfsFrame
195 int WxTestPhysfsFrame::err(int success)
198 this->SetStatusText(wxT(""));
200 this->SetStatusText(wxString(PHYSFS_getLastError(), wxConvUTF8));
202 } // WxTestPhysfsFrame::err
205 void WxTestPhysfsFrame::fillFileSystemTree(const char *path,
206 const wxTreeItemId &item)
208 char **rc = PHYSFS_enumerateFiles(path);
214 const wxString quote(wxT("'"));
215 wxString str(wxT("Enumeration error: "));
216 str << quote << wxString(PHYSFS_getLastError(), wxConvUTF8) << quote;
217 id = this->fileTree->AppendItem(item, str);
218 this->fileTree->SetItemTextColour(id, wxColour(255, 0, 0));
222 for (i = rc; *i != NULL; i++)
224 id = this->fileTree->AppendItem(item, wxString(*i, wxConvUTF8));
225 const int len = strlen(path) + strlen(*i) + 2;
226 char *fname = new char[len];
227 const char *origdir = path;
228 if (strcmp(origdir, "/") == 0)
230 snprintf(fname, len, "%s/%s", origdir, *i);
232 if (PHYSFS_isDirectory(fname))
234 this->fileTree->SetItemTextColour(id, wxColour(0, 0, 255));
235 this->fillFileSystemTree(fname, id);
238 else if (PHYSFS_isSymbolicLink(fname))
240 this->fileTree->SetItemTextColour(id, wxColour(0, 255, 0));
252 } // fillFileSystemTree
255 void WxTestPhysfsFrame::rebuildTree()
257 const wxString dot(wxT("."));
258 const wxString quote(wxT("'"));
261 const char *cstr = NULL;
262 const bool wasInit = PHYSFS_isInit() ? true : false;
264 this->fileTree->DeleteAllItems();
265 wxTreeItemId root = this->fileTree->AddRoot(wxT("PhysicsFS"));
266 this->stateItem = this->fileTree->AppendItem(root, wxT("Library state"));
268 str = wxT("Initialized: ");
269 str << ((wasInit) ? wxT("true") : wxT("false"));
270 this->fileTree->AppendItem(this->stateItem, str);
272 this->fileTree->Expand(this->stateItem);
273 this->fileTree->Expand(root);
275 // Fill in version information...
278 item = this->stateItem;
279 str = wxT("wxtest_physfs version: ");
280 str << TEST_VER_MAJOR << dot << TEST_VER_MINOR << dot << TEST_VER_PATCH;
281 this->fileTree->AppendItem(item, str);
282 PHYSFS_VERSION(&ver);
283 str = wxT("Compiled against PhysicsFS version: ");
284 str << (int) ver.major << dot << (int) ver.minor << dot << ver.patch;
285 this->fileTree->AppendItem(item, str);
286 PHYSFS_getLinkedVersion(&ver);
287 str = wxT("Linked against PhysicsFS version: ");
288 str << (int) ver.major << dot << (int) ver.minor << dot << ver.patch;
289 this->fileTree->AppendItem(item, str);
292 return; // nothing else to do before initialization...
294 str = wxT("Symbolic links permitted: ");
295 str << ((PHYSFS_symbolicLinksPermitted()) ? wxT("true") : wxT("false"));
296 this->fileTree->AppendItem(this->stateItem, str);
298 str = wxT("Native directory separator: ");
299 str << quote << wxString(PHYSFS_getDirSeparator(), wxConvUTF8) << quote;
300 this->fileTree->AppendItem(this->stateItem, str);
302 // Fill in supported archives...
304 item = this->fileTree->AppendItem(this->stateItem, wxT("Archivers"));
305 const PHYSFS_ArchiveInfo **arcs = PHYSFS_supportedArchiveTypes();
307 this->fileTree->AppendItem(item, wxT("(none)"));
310 const PHYSFS_ArchiveInfo **i;
311 for (i = arcs; *i != NULL; i++)
313 const wxString ext((*i)->extension, wxConvUTF8);
314 const wxString desc((*i)->description, wxConvUTF8);
315 const wxString auth((*i)->author, wxConvUTF8);
316 const wxString url((*i)->url, wxConvUTF8);
317 wxTreeItemId arcitem = this->fileTree->AppendItem(item, ext);
318 this->fileTree->AppendItem(arcitem, desc);
319 this->fileTree->AppendItem(arcitem, auth);
320 this->fileTree->AppendItem(arcitem, url);
325 // Fill in the standard paths...
327 item = this->fileTree->AppendItem(this->stateItem, wxT("Paths"));
328 str = wxT("Base directory: ");
329 str << quote << wxString(PHYSFS_getBaseDir(), wxConvUTF8) << quote;
330 this->fileTree->AppendItem(item, str);
331 str = wxT("User directory: ");
332 str << quote << wxString(PHYSFS_getUserDir(), wxConvUTF8) << quote;
333 this->fileTree->AppendItem(item, str);
334 str = wxT("Write directory: ");
335 if ((cstr = PHYSFS_getWriteDir()) == NULL)
336 str << wxT("(NULL)");
338 str << quote << wxString(cstr ? cstr : "(NULL)", wxConvUTF8) << quote;
339 this->fileTree->AppendItem(item, str);
340 //str = wxT("Preference directory: ");
341 //str << wxString(PHYSFS_getUserDir(), wxConvUTF8);
342 //this->fileTree->AppendItem(item, str);
344 // Fill in the CD-ROMs...
346 item = this->fileTree->AppendItem(this->stateItem, wxT("CD-ROMs"));
347 char **cds = PHYSFS_getCdRomDirs();
350 str = wxT("Error: ");
351 str << quote << wxString(PHYSFS_getLastError(), wxConvUTF8) << quote;
352 wxTreeItemId id = this->fileTree->AppendItem(item, str);
353 this->fileTree->SetItemTextColour(id, wxColour(255, 0, 0));
358 this->fileTree->AppendItem(item, wxT("(none)"));
362 for (i = cds; *i != NULL; i++)
363 this->fileTree->AppendItem(item, wxString(*i, wxConvUTF8));
365 PHYSFS_freeList(cds);
368 // Fill in search path...
370 item = this->fileTree->AppendItem(this->stateItem, wxT("Search path"));
371 char **sp = PHYSFS_getSearchPath();
374 str = wxT("Error: ");
375 str << quote << wxString(PHYSFS_getLastError(), wxConvUTF8) << quote;
376 wxTreeItemId id = this->fileTree->AppendItem(item, str);
377 this->fileTree->SetItemTextColour(id, wxColour(255, 0, 0));
382 this->fileTree->AppendItem(item, wxT("(none)"));
386 for (i = sp; *i != NULL; i++)
387 this->fileTree->AppendItem(item, wxString(*i, wxConvUTF8));
392 // Now fill in the filesystem...
394 this->fsItem = this->fileTree->AppendItem(root, wxT("Filesystem"));
395 this->fillFileSystemTree("/", this->fsItem);
396 this->fileTree->Expand(this->fsItem);
397 } // WxTestPhysfsFrame::rebuildTree
400 void WxTestPhysfsFrame::doInit(const char *argv0)
402 if (!this->err(PHYSFS_init(argv0)))
403 ::wxMessageBox(wxT("PHYSFS_init() failed!"), wxT("wxTestPhysfs"));
405 } // WxTestPhysfsFrame::doInit
408 void WxTestPhysfsFrame::doDeinit()
410 if (!this->err(PHYSFS_deinit()))
411 ::wxMessageBox(wxT("PHYSFS_deinit() failed!"), wxT("wxTestPhysfs"));
413 } // WxTestPhysfsFrame::doDeinit
416 void WxTestPhysfsFrame::onMenuInit(wxCommandEvent &evt)
418 wxString argv0(wxGetApp().argv[0] == NULL ? wxT("") : wxGetApp().argv[0]);
419 wxString str(wxGetTextFromUser(wxT("PHYSFS_init"),
420 wxT("argv[0]? (cancel for NULL)"), argv0));
421 char *cstr = str.IsEmpty() ? NULL : newutf8(str);
424 } // WxTestPhysfsFrame::onMenuInit
427 void WxTestPhysfsFrame::onMenuDeinit(wxCommandEvent &evt)
430 } // WxTestPhysfsFrame::onMenuDeinit
433 void WxTestPhysfsFrame::onMenuAddArchive(wxCommandEvent &evt)
435 wxString arc = wxFileSelector(wxT("Choose archive to add"));
438 char *cstr = newutf8(arc);
439 // !!! FIXME: add to start/end?
440 if (!this->err(PHYSFS_addToSearchPath(cstr, 1)))
441 ::wxMessageBox(wxT("PHYSFS_addToSearchPath() failed!"), wxT("wxTestPhysfs"));
445 } // WxTestPhysfsFrame::onMenuAddArchive
448 void WxTestPhysfsFrame::onMenuGetCDs(wxCommandEvent &evt)
450 this->rebuildTree(); // This will call PHYSFS_getCdRomDirs()...
451 } // WxTestPhysfsFrame::onMenuGetCDs
454 void WxTestPhysfsFrame::onMenuPermitSymLinks(wxCommandEvent &evt)
456 PHYSFS_permitSymbolicLinks(evt.IsChecked() ? 1 : 0);
458 } // WxTestPhysfsFrame::onMenuPermitSymLinks
462 IMPLEMENT_APP(WxTestPhysfsApp)
464 bool WxTestPhysfsApp::OnInit()
467 // This lets a stdio app become a GUI app. Otherwise, you won't get
468 // GUI events from the system and other things will fail to work.
469 // Putting the app in an application bundle does the same thing.
470 // TransformProcessType() is a 10.3+ API. SetFrontProcess() is 10.0+.
471 if (TransformProcessType != NULL) // check it as a weak symbol.
473 ProcessSerialNumber psn = { 0, kCurrentProcess };
474 TransformProcessType(&psn, kProcessTransformToForegroundApplication);
475 SetFrontProcess(&psn);
479 this->mainWindow = new WxTestPhysfsFrame(this->argv[0]);
480 this->mainWindow->Show(true);
481 SetTopWindow(this->mainWindow);
483 } // WxTestPhysfsApp::OnInit
485 // end of wxtest_physfs.cpp ...