wxtest_physfs.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. /**
  2. * Test program for PhysicsFS, using wxWidgets. May only work on Unix.
  3. *
  4. * Please see the file LICENSE.txt in the source's root directory.
  5. *
  6. * This file written by Ryan C. Gordon.
  7. */
  8. #if ( (defined(__MACH__)) && (defined(__APPLE__)) )
  9. #define PLATFORM_MACOSX 1
  10. #include <Carbon/Carbon.h>
  11. #endif
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <time.h>
  16. #include <errno.h>
  17. #include <wx/wx.h>
  18. #include <wx/treectrl.h>
  19. #include "physfs.h"
  20. #define TEST_VER_MAJOR 2
  21. #define TEST_VER_MINOR 0
  22. #define TEST_VER_PATCH 3
  23. //static PHYSFS_uint32 do_buffer_size = 0;
  24. enum WxTestPhysfsMenuCommands
  25. {
  26. // start with standard menu items, since using the wxIDs will map them
  27. // to sane things in the platform's UI (gnome icons in GTK+, moves the
  28. // about and quit items to the Apple menu on Mac OS X, etc).
  29. MENUCMD_About = wxID_ABOUT,
  30. MENUCMD_Quit = wxID_EXIT,
  31. // non-standard menu items go here.
  32. MENUCMD_Init = wxID_HIGHEST,
  33. MENUCMD_Deinit,
  34. MENUCMD_AddArchive,
  35. MENUCMD_Mount,
  36. MENUCMD_Remove,
  37. MENUCMD_GetCDs,
  38. MENUCMD_SetWriteDir,
  39. MENUCMD_PermitSymLinks,
  40. MENUCMD_SetSaneConfig,
  41. MENUCMD_MkDir,
  42. MENUCMD_Delete,
  43. MENUCMD_Cat,
  44. MENUCMD_SetBuffer,
  45. MENUCMD_StressBuffer,
  46. MENUCMD_Append,
  47. MENUCMD_Write,
  48. MENUCMD_GetLastError,
  49. /*
  50. { "getdirsep", cmd_getdirsep, 0, NULL },
  51. { "getsearchpath", cmd_getsearchpath, 0, NULL },
  52. { "getbasedir", cmd_getbasedir, 0, NULL },
  53. { "getuserdir", cmd_getuserdir, 0, NULL },
  54. { "getwritedir", cmd_getwritedir, 0, NULL },
  55. { "getrealdir", cmd_getrealdir, 1, "<fileToFind>" },
  56. { "exists", cmd_exists, 1, "<fileToCheck>" },
  57. { "isdir", cmd_isdir, 1, "<fileToCheck>" },
  58. { "issymlink", cmd_issymlink, 1, "<fileToCheck>" },
  59. { "filelength", cmd_filelength, 1, "<fileToCheck>" },
  60. { "getlastmodtime", cmd_getlastmodtime, 1, "<fileToExamine>" },
  61. */
  62. };
  63. class WxTestPhysfsFrame : public wxFrame
  64. {
  65. public:
  66. WxTestPhysfsFrame(const wxChar *argv0);
  67. void rebuildTree();
  68. void onMenuInit(wxCommandEvent &evt);
  69. void onMenuDeinit(wxCommandEvent &evt);
  70. void onMenuAddArchive(wxCommandEvent &evt);
  71. void onMenuGetCDs(wxCommandEvent &evt);
  72. void onMenuPermitSymLinks(wxCommandEvent &evt);
  73. private:
  74. wxTreeCtrl *fileTree;
  75. wxTreeItemId stateItem;
  76. wxTreeItemId fsItem;
  77. int err(int success);
  78. void fillFileSystemTree(const char *path, const wxTreeItemId &item);
  79. void doInit(const char *argv0);
  80. void doDeinit();
  81. DECLARE_EVENT_TABLE()
  82. };
  83. BEGIN_EVENT_TABLE(WxTestPhysfsFrame, wxFrame)
  84. EVT_MENU(MENUCMD_Init, WxTestPhysfsFrame::onMenuInit)
  85. EVT_MENU(MENUCMD_Deinit, WxTestPhysfsFrame::onMenuDeinit)
  86. EVT_MENU(MENUCMD_AddArchive, WxTestPhysfsFrame::onMenuAddArchive)
  87. EVT_MENU(MENUCMD_GetCDs, WxTestPhysfsFrame::onMenuGetCDs)
  88. EVT_MENU(MENUCMD_PermitSymLinks, WxTestPhysfsFrame::onMenuPermitSymLinks)
  89. END_EVENT_TABLE()
  90. // This is the the Application itself.
  91. class WxTestPhysfsApp : public wxApp
  92. {
  93. public:
  94. WxTestPhysfsApp() : mainWindow(NULL) { /* no-op. */ }
  95. virtual bool OnInit();
  96. private:
  97. WxTestPhysfsFrame *mainWindow;
  98. };
  99. DECLARE_APP(WxTestPhysfsApp)
  100. static inline char *newstr(const char *str)
  101. {
  102. char *retval = NULL;
  103. if (str != NULL)
  104. {
  105. retval = new char[strlen(str) + 1];
  106. strcpy(retval, str);
  107. } // if
  108. return retval;
  109. } // newstr
  110. static char *newutf8(const wxString &wxstr)
  111. {
  112. #if wxUSE_UNICODE
  113. size_t len = wxstr.Len() + 1;
  114. char *utf8text = new char[len * 6];
  115. wxConvUTF8.WC2MB(utf8text, wxstr, len);
  116. return utf8text;
  117. #else
  118. return newstr(wxstr);
  119. #endif
  120. } // newutf8
  121. WxTestPhysfsFrame::WxTestPhysfsFrame(const wxChar *argv0)
  122. : wxFrame(NULL, -1, wxT("WxTestPhysfs"))
  123. {
  124. this->CreateStatusBar();
  125. wxMenuBar *menuBar = new wxMenuBar;
  126. wxMenu *stuffMenu = new wxMenu;
  127. stuffMenu->Append(MENUCMD_Init, wxT("&Init"));
  128. stuffMenu->Append(MENUCMD_Deinit, wxT("&Deinit"));
  129. stuffMenu->Append(MENUCMD_AddArchive, wxT("&Add Archive"));
  130. stuffMenu->Append(MENUCMD_Mount, wxT("&Mount Archive"));
  131. stuffMenu->Append(MENUCMD_Remove, wxT("&Remove Archive"));
  132. stuffMenu->Append(MENUCMD_GetCDs, wxT("&Get CD-ROM drives"));
  133. stuffMenu->Append(MENUCMD_SetWriteDir, wxT("&Set Write Dir"));
  134. stuffMenu->Append(MENUCMD_SetSaneConfig, wxT("Set Sane &Config"));
  135. stuffMenu->Append(MENUCMD_MkDir, wxT("M&kDir"));
  136. stuffMenu->Append(MENUCMD_Delete, wxT("D&elete"));
  137. stuffMenu->Append(MENUCMD_Cat, wxT("&Cat"));
  138. stuffMenu->Append(MENUCMD_SetBuffer, wxT("Set &Buffer"));
  139. stuffMenu->Append(MENUCMD_StressBuffer, wxT("Stress &Test Buffer"));
  140. stuffMenu->Append(MENUCMD_Append, wxT("&Append"));
  141. stuffMenu->Append(MENUCMD_Write, wxT("&Write"));
  142. stuffMenu->Append(MENUCMD_Write, wxT("&Update getLastError"));
  143. stuffMenu->AppendCheckItem(MENUCMD_PermitSymLinks, wxT("&Permit symlinks"));
  144. menuBar->Append(stuffMenu, wxT("&Stuff"));
  145. //wxMenu *helpMenu = new wxMenu;
  146. //helpMenu->Append(MENUCMD_About, wxT("&About\tF1"));
  147. //menuBar->Append(helpMenu, wxT("&Help"));
  148. this->SetMenuBar(menuBar);
  149. this->fileTree = new wxTreeCtrl(this, -1);
  150. // The sizer just makes sure that fileTree owns whole client area.
  151. wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
  152. sizer->Add(this->fileTree, 1, wxALL | wxEXPAND | wxALIGN_CENTRE);
  153. sizer->SetItemMinSize(this->fileTree, 1, 1);
  154. this->SetSizer(sizer);
  155. char *utf8argv0 = newutf8(wxString(argv0));
  156. this->doInit(utf8argv0);
  157. delete[] utf8argv0;
  158. } // WxTestPhysfsFrame::WxTestPhysfsFrame
  159. int WxTestPhysfsFrame::err(int success)
  160. {
  161. if (success)
  162. this->SetStatusText(wxT(""));
  163. else
  164. this->SetStatusText(wxString(PHYSFS_getLastError(), wxConvUTF8));
  165. return success;
  166. } // WxTestPhysfsFrame::err
  167. void WxTestPhysfsFrame::fillFileSystemTree(const char *path,
  168. const wxTreeItemId &item)
  169. {
  170. char **rc = PHYSFS_enumerateFiles(path);
  171. char **i;
  172. wxTreeItemId id;
  173. if (rc == NULL)
  174. {
  175. const wxString quote(wxT("'"));
  176. wxString str(wxT("Enumeration error: "));
  177. str << quote << wxString(PHYSFS_getLastError(), wxConvUTF8) << quote;
  178. id = this->fileTree->AppendItem(item, str);
  179. this->fileTree->SetItemTextColour(id, wxColour(255, 0, 0));
  180. } // if
  181. else
  182. {
  183. for (i = rc; *i != NULL; i++)
  184. {
  185. id = this->fileTree->AppendItem(item, wxString(*i, wxConvUTF8));
  186. const int len = strlen(path) + strlen(*i) + 2;
  187. char *fname = new char[len];
  188. const char *origdir = path;
  189. if (strcmp(origdir, "/") == 0)
  190. origdir = "";
  191. snprintf(fname, len, "%s/%s", origdir, *i);
  192. if (PHYSFS_isDirectory(fname))
  193. {
  194. this->fileTree->SetItemTextColour(id, wxColour(0, 0, 255));
  195. this->fillFileSystemTree(fname, id);
  196. } // if
  197. else if (PHYSFS_isSymbolicLink(fname))
  198. {
  199. this->fileTree->SetItemTextColour(id, wxColour(0, 255, 0));
  200. } // else if
  201. else // ...file.
  202. {
  203. } // else
  204. delete[] fname;
  205. } // for
  206. PHYSFS_freeList(rc);
  207. } // else
  208. } // fillFileSystemTree
  209. void WxTestPhysfsFrame::rebuildTree()
  210. {
  211. const wxString dot(wxT("."));
  212. const wxString quote(wxT("'"));
  213. wxTreeItemId item;
  214. wxString str;
  215. const char *cstr = NULL;
  216. const bool wasInit = PHYSFS_isInit() ? true : false;
  217. this->fileTree->DeleteAllItems();
  218. wxTreeItemId root = this->fileTree->AddRoot(wxT("PhysicsFS"));
  219. this->stateItem = this->fileTree->AppendItem(root, wxT("Library state"));
  220. str = wxT("Initialized: ");
  221. str << ((wasInit) ? wxT("true") : wxT("false"));
  222. this->fileTree->AppendItem(this->stateItem, str);
  223. this->fileTree->Expand(this->stateItem);
  224. this->fileTree->Expand(root);
  225. // Fill in version information...
  226. PHYSFS_Version ver;
  227. item = this->stateItem;
  228. str = wxT("wxtest_physfs version: ");
  229. str << TEST_VER_MAJOR << dot << TEST_VER_MINOR << dot << TEST_VER_PATCH;
  230. this->fileTree->AppendItem(item, str);
  231. PHYSFS_VERSION(&ver);
  232. str = wxT("Compiled against PhysicsFS version: ");
  233. str << (int) ver.major << dot << (int) ver.minor << dot << ver.patch;
  234. this->fileTree->AppendItem(item, str);
  235. PHYSFS_getLinkedVersion(&ver);
  236. str = wxT("Linked against PhysicsFS version: ");
  237. str << (int) ver.major << dot << (int) ver.minor << dot << ver.patch;
  238. this->fileTree->AppendItem(item, str);
  239. if (!wasInit)
  240. return; // nothing else to do before initialization...
  241. str = wxT("Symbolic links permitted: ");
  242. str << ((PHYSFS_symbolicLinksPermitted()) ? wxT("true") : wxT("false"));
  243. this->fileTree->AppendItem(this->stateItem, str);
  244. str = wxT("Native directory separator: ");
  245. str << quote << wxString(PHYSFS_getDirSeparator(), wxConvUTF8) << quote;
  246. this->fileTree->AppendItem(this->stateItem, str);
  247. // Fill in supported archives...
  248. item = this->fileTree->AppendItem(this->stateItem, wxT("Archivers"));
  249. const PHYSFS_ArchiveInfo **arcs = PHYSFS_supportedArchiveTypes();
  250. if (*arcs == NULL)
  251. this->fileTree->AppendItem(item, wxT("(none)"));
  252. else
  253. {
  254. const PHYSFS_ArchiveInfo **i;
  255. for (i = arcs; *i != NULL; i++)
  256. {
  257. const wxString ext((*i)->extension, wxConvUTF8);
  258. const wxString desc((*i)->description, wxConvUTF8);
  259. const wxString auth((*i)->author, wxConvUTF8);
  260. const wxString url((*i)->url, wxConvUTF8);
  261. wxTreeItemId arcitem = this->fileTree->AppendItem(item, ext);
  262. this->fileTree->AppendItem(arcitem, desc);
  263. this->fileTree->AppendItem(arcitem, auth);
  264. this->fileTree->AppendItem(arcitem, url);
  265. } // for
  266. } // else
  267. // Fill in the standard paths...
  268. item = this->fileTree->AppendItem(this->stateItem, wxT("Paths"));
  269. str = wxT("Base directory: ");
  270. str << quote << wxString(PHYSFS_getBaseDir(), wxConvUTF8) << quote;
  271. this->fileTree->AppendItem(item, str);
  272. str = wxT("User directory: ");
  273. str << quote << wxString(PHYSFS_getUserDir(), wxConvUTF8) << quote;
  274. this->fileTree->AppendItem(item, str);
  275. str = wxT("Write directory: ");
  276. if ((cstr = PHYSFS_getWriteDir()) == NULL)
  277. str << wxT("(NULL)");
  278. else
  279. str << quote << wxString(cstr ? cstr : "(NULL)", wxConvUTF8) << quote;
  280. this->fileTree->AppendItem(item, str);
  281. //str = wxT("Preference directory: ");
  282. //str << wxString(PHYSFS_getUserDir(), wxConvUTF8);
  283. //this->fileTree->AppendItem(item, str);
  284. // Fill in the CD-ROMs...
  285. item = this->fileTree->AppendItem(this->stateItem, wxT("CD-ROMs"));
  286. char **cds = PHYSFS_getCdRomDirs();
  287. if (cds == NULL)
  288. {
  289. str = wxT("Error: ");
  290. str << quote << wxString(PHYSFS_getLastError(), wxConvUTF8) << quote;
  291. wxTreeItemId id = this->fileTree->AppendItem(item, str);
  292. this->fileTree->SetItemTextColour(id, wxColour(255, 0, 0));
  293. } // if
  294. else
  295. {
  296. if (*cds == NULL)
  297. this->fileTree->AppendItem(item, wxT("(none)"));
  298. else
  299. {
  300. char **i;
  301. for (i = cds; *i != NULL; i++)
  302. this->fileTree->AppendItem(item, wxString(*i, wxConvUTF8));
  303. } // else
  304. PHYSFS_freeList(cds);
  305. } // else
  306. // Fill in search path...
  307. item = this->fileTree->AppendItem(this->stateItem, wxT("Search path"));
  308. char **sp = PHYSFS_getSearchPath();
  309. if (sp == NULL)
  310. {
  311. str = wxT("Error: ");
  312. str << quote << wxString(PHYSFS_getLastError(), wxConvUTF8) << quote;
  313. wxTreeItemId id = this->fileTree->AppendItem(item, str);
  314. this->fileTree->SetItemTextColour(id, wxColour(255, 0, 0));
  315. } // if
  316. else
  317. {
  318. if (*sp == NULL)
  319. this->fileTree->AppendItem(item, wxT("(none)"));
  320. else
  321. {
  322. char **i;
  323. for (i = sp; *i != NULL; i++)
  324. this->fileTree->AppendItem(item, wxString(*i, wxConvUTF8));
  325. } // else
  326. PHYSFS_freeList(sp);
  327. } // else
  328. // Now fill in the filesystem...
  329. this->fsItem = this->fileTree->AppendItem(root, wxT("Filesystem"));
  330. this->fillFileSystemTree("/", this->fsItem);
  331. this->fileTree->Expand(this->fsItem);
  332. } // WxTestPhysfsFrame::rebuildTree
  333. void WxTestPhysfsFrame::doInit(const char *argv0)
  334. {
  335. if (!this->err(PHYSFS_init(argv0)))
  336. ::wxMessageBox(wxT("PHYSFS_init() failed!"), wxT("wxTestPhysfs"));
  337. this->rebuildTree();
  338. } // WxTestPhysfsFrame::doInit
  339. void WxTestPhysfsFrame::doDeinit()
  340. {
  341. if (!this->err(PHYSFS_deinit()))
  342. ::wxMessageBox(wxT("PHYSFS_deinit() failed!"), wxT("wxTestPhysfs"));
  343. this->rebuildTree();
  344. } // WxTestPhysfsFrame::doDeinit
  345. void WxTestPhysfsFrame::onMenuInit(wxCommandEvent &evt)
  346. {
  347. wxString argv0(wxGetApp().argv[0] == NULL ? wxT("") : wxGetApp().argv[0]);
  348. wxString str(wxGetTextFromUser(wxT("PHYSFS_init"),
  349. wxT("argv[0]? (cancel for NULL)"), argv0));
  350. char *cstr = str.IsEmpty() ? NULL : newutf8(str);
  351. this->doInit(cstr);
  352. delete[] cstr;
  353. } // WxTestPhysfsFrame::onMenuInit
  354. void WxTestPhysfsFrame::onMenuDeinit(wxCommandEvent &evt)
  355. {
  356. this->doDeinit();
  357. } // WxTestPhysfsFrame::onMenuDeinit
  358. void WxTestPhysfsFrame::onMenuAddArchive(wxCommandEvent &evt)
  359. {
  360. wxString arc = wxFileSelector(wxT("Choose archive to add"));
  361. if (!arc.IsEmpty())
  362. {
  363. char *cstr = newutf8(arc);
  364. // !!! FIXME: add to start/end?
  365. if (!this->err(PHYSFS_addToSearchPath(cstr, 1)))
  366. ::wxMessageBox(wxT("PHYSFS_addToSearchPath() failed!"), wxT("wxTestPhysfs"));
  367. delete[] cstr;
  368. this->rebuildTree();
  369. } // if
  370. } // WxTestPhysfsFrame::onMenuAddArchive
  371. void WxTestPhysfsFrame::onMenuGetCDs(wxCommandEvent &evt)
  372. {
  373. this->rebuildTree(); // This will call PHYSFS_getCdRomDirs()...
  374. } // WxTestPhysfsFrame::onMenuGetCDs
  375. void WxTestPhysfsFrame::onMenuPermitSymLinks(wxCommandEvent &evt)
  376. {
  377. PHYSFS_permitSymbolicLinks(evt.IsChecked() ? 1 : 0);
  378. this->rebuildTree();
  379. } // WxTestPhysfsFrame::onMenuPermitSymLinks
  380. IMPLEMENT_APP(WxTestPhysfsApp)
  381. bool WxTestPhysfsApp::OnInit()
  382. {
  383. #if PLATFORM_MACOSX
  384. // This lets a stdio app become a GUI app. Otherwise, you won't get
  385. // GUI events from the system and other things will fail to work.
  386. // Putting the app in an application bundle does the same thing.
  387. // TransformProcessType() is a 10.3+ API. SetFrontProcess() is 10.0+.
  388. if (TransformProcessType != NULL) // check it as a weak symbol.
  389. {
  390. ProcessSerialNumber psn = { 0, kCurrentProcess };
  391. TransformProcessType(&psn, kProcessTransformToForegroundApplication);
  392. SetFrontProcess(&psn);
  393. } // if
  394. #endif
  395. this->mainWindow = new WxTestPhysfsFrame(this->argv[0]);
  396. this->mainWindow->Show(true);
  397. SetTopWindow(this->mainWindow);
  398. return true;
  399. } // WxTestPhysfsApp::OnInit
  400. // end of wxtest_physfs.cpp ...