From c67ccb6e0794f3940666c4712bb90de83d381e13 Mon Sep 17 00:00:00 2001 From: Gondos Date: Mon, 17 Jul 2023 14:27:34 +0200 Subject: [PATCH] Use std::filesystem instead of windows API in Orbiter core --- Sound/XRSound/src/Utils/FileList.cpp | 74 ++---- Sound/XRSound/src/Utils/FileList.h | 14 +- Src/Orbiter/FlightRecorder.cpp | 33 +-- Src/Orbiter/GraphicsAPI.cpp | 18 +- Src/Orbiter/OptionsPages.cpp | 35 +-- Src/Orbiter/Orbiter.cpp | 33 +-- Src/Orbiter/Planet.cpp | 216 ++++++++---------- Src/Orbiter/Planet.h | 25 +- Src/Orbiter/Psys.cpp | 199 +++++++--------- Src/Orbiter/Psys.h | 11 +- Src/Orbiter/TabModule.cpp | 127 +++++----- Src/Orbiter/TabScenario.cpp | 91 +++----- Src/Orbiter/TabScenario.h | 4 +- Src/Orbiter/TabVideo.cpp | 55 ++--- Src/Orbiter/TabVideo.h | 4 +- .../AtmConfig/AtmConfig.cpp | 71 +++--- Src/Plugin/ScnEditor/Editor.cpp | 81 +++---- Src/Plugin/ScnEditor/Editor.h | 4 +- 18 files changed, 463 insertions(+), 632 deletions(-) diff --git a/Sound/XRSound/src/Utils/FileList.cpp b/Sound/XRSound/src/Utils/FileList.cpp index 9d50e0832..2071553a9 100644 --- a/Sound/XRSound/src/Utils/FileList.cpp +++ b/Sound/XRSound/src/Utils/FileList.cpp @@ -53,56 +53,25 @@ void FileList::Scan(const char *pPath, const int recursionLevel) // This code was broken out from XRPayloadClassData::InitializeXRPayloadClassData(). - WIN32_FIND_DATA findFileData; - char pConfigFilespecWildcard[MAX_PATH]; - sprintf_s(pConfigFilespecWildcard, "%s\\*", pPath); // iterate through all files and directories - - HANDLE hFind = ::FindFirstFile(pConfigFilespecWildcard, &findFileData); - if (hFind == INVALID_HANDLE_VALUE) - return; // directory is empty (should really never happen because "." and ".." are always present) - - // found at least one file - goto process_file; // a little goofy, but that's Windows' goofy FindFirstFile/FindNextFile for you... - - // now loop through all remaining files - for (;;) - { - if (::FindNextFile(hFind, &findFileData) != 0) - { - process_file: // entry point from FirstFirstFile - // build the new configdir-relative path - char pNodeFilespec[MAX_PATH]; - sprintf_s(pNodeFilespec, "%s\\%s", pPath, findFileData.cFileName); // e.g., "Vessels\XRParts.cfg" - - if (!STARTSWITH_DOT(findFileData)) // file not "." or ".."? + for (auto& file : fs::directory_iterator(pPath)) { + if (file.path().stem().c_str()[0] != '.') { + if (clbkFilterNode(file)) { - if (clbkFilterNode(pNodeFilespec, findFileData)) + // node should be included + if (file.is_directory()) { - // node should be included - if (IS_DIRECTORY(findFileData)) - { - // this is a directory, so recurse down into it - Scan(pNodeFilespec, recursionLevel + 1); - } - else if (!IS_EMPTY(findFileData)) // it's a file node; is it not empty? - { - // it's a file and it's not empty, so add it to our master list of nodes and invoke the callback for subclasses to hook - m_allFiles.push_back(pNodeFilespec); - clbkProcessFile(pNodeFilespec, findFileData); - } + // this is a directory, so recurse down into it + Scan(file.path().string().c_str(), recursionLevel + 1); + } + else if (file.file_size() > 0) // it's a file node; is it not empty? + { + // it's a file and it's not empty, so add it to our master list of nodes and invoke the callback for subclasses to hook + m_allFiles.push_back(file.path().string().c_str()); + clbkProcessFile(file); } } - } // if (::FindNextFile(hFind, &findFileData) != 0) - else // FindNextFile failed - { - // check the error; continue parsing next file unless "no more files" reached - DWORD dwError = GetLastError(); - if (dwError == ERROR_NO_MORE_FILES) - break; // all done - // else skip this file: fall through and parse the next file } - } // for (;;) - FindClose(hFind); + } } // Invoked for each file or folder node found. The default method here looks at bRecurseSubfolders (for folder nodes) and @@ -110,22 +79,21 @@ void FileList::Scan(const char *pPath, const int recursionLevel) // Subclasses should override this method if they want more advanced filtering. // // Returns true if file node should be included or folder should be recursed into, or false if the node should be skipped. -bool FileList::clbkFilterNode(const char *pPathOfNode, const WIN32_FIND_DATA &fd) +bool FileList::clbkFilterNode(const fs::directory_entry& entry) { - if (IS_DIRECTORY(fd)) - return m_bRecurseSubfolders; + if (entry.is_directory()) + return m_bRecurseSubfolders; // it's a file node bool bAcceptFile = false; if (!m_fileTypesToAccept.empty()) { - const char *pFileExtension = strrchr(fd.cFileName, '.'); - if (pFileExtension) // e.g., ".flac" + if (entry.path().extension().string().length() > 0) // e.g., ".flac" { // see if we have a case-insensitive match for this extension in our master list - for (vector::const_iterator it = m_fileTypesToAccept.begin(); it != m_fileTypesToAccept.end(); it++) + for (auto it = m_fileTypesToAccept.begin(); it != m_fileTypesToAccept.end(); it++) { - if (_stricmp(pFileExtension, *it) == 0) + if (stricmp(entry.path().extension().string().c_str(), *it) == 0) { bAcceptFile = true; break; @@ -140,7 +108,7 @@ bool FileList::clbkFilterNode(const char *pPathOfNode, const WIN32_FIND_DATA &fd } // Callback invoked for non-empty file nodes that passed the clbkFilterNode check; this is here for subclasses to hook. -void FileList::clbkProcessFile(const char *pFilespec, const WIN32_FIND_DATA &fd) +void FileList::clbkProcessFile(const fs::directory_entry& entry) { // no-op; this method is for subclasses to use } diff --git a/Sound/XRSound/src/Utils/FileList.h b/Sound/XRSound/src/Utils/FileList.h index 6daf6dd75..8f20870c7 100644 --- a/Sound/XRSound/src/Utils/FileList.h +++ b/Sound/XRSound/src/Utils/FileList.h @@ -13,6 +13,9 @@ using namespace std; +#include +namespace fs = std::filesystem; + class FileList { public: @@ -23,9 +26,10 @@ class FileList static bool DirectoryExists(const char *pPath) { - DWORD dwAttrib = GetFileAttributes(pPath); - - return (dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); + std::error_code ec; + auto status = fs::status(pPath, ec); + if(ec) return false; + return fs::is_directory(status); } // Scan (or rescan) file tree. @@ -41,10 +45,10 @@ class FileList // Invoked for each file or folder node found; should return true if file node should be included or folder should be // recursed into, or false if the node should be skipped. - virtual bool clbkFilterNode(const char *pPathOfNode, const WIN32_FIND_DATA &fd); + virtual bool clbkFilterNode(const fs::directory_entry &); // Callback invoked for non-empty file nodes that passed the clbkFilterNode check; this is here for subclasses to hook. - virtual void clbkProcessFile(const char *pFilespec, const WIN32_FIND_DATA &fd); + virtual void clbkProcessFile(const fs::directory_entry &); int GetScannedFileCount() const { return static_cast(m_allFiles.size()); } bool IsEmpty() const { return m_allFiles.empty(); } diff --git a/Src/Orbiter/FlightRecorder.cpp b/Src/Orbiter/FlightRecorder.cpp index 990b4fc9b..96c8ffc3c 100644 --- a/Src/Orbiter/FlightRecorder.cpp +++ b/Src/Orbiter/FlightRecorder.cpp @@ -16,11 +16,9 @@ #include "State.h" #include "MenuInfoBar.h" #include -#include -#include -#include -#include #include +#include +namespace fs = std::filesystem; using namespace std; @@ -776,24 +774,17 @@ void Orbiter::FRecorder_Reset () bool Orbiter::FRecorder_PrepareDir (const char *fname, bool force) { - char cbuf[256]; - strcpy (cbuf, "Flights\\"); strcat (cbuf, fname); - if (_mkdir (cbuf) == -1) { - if (errno == EEXIST && !force) return false; - // don't overwrite existing recording - struct _finddata_t fd; - char cb2[256], cb3[256]; - strcpy (cb2, cbuf); strcat (cb2, "\\*"); - intptr_t handle = _findfirst (cb2, &fd), res = handle; - while (res != -1) { - if (!(fd.attrib & _A_SUBDIR)) { - sprintf (cb3, "%s\\%s", cbuf, fd.name); - _unlink (cb3); - } - res = _findnext (handle, &fd); - } - _findclose (handle); + fs::path dir = fs::path("Flights") / fname; + std::error_code ec; + auto status = fs::status(dir, ec); + + // don't overwrite existing recording + if (!ec) { + if(fs::is_directory(status) && !force) return false; + fs::remove_all(dir); } + fs::create_directory(dir); + return true; } diff --git a/Src/Orbiter/GraphicsAPI.cpp b/Src/Orbiter/GraphicsAPI.cpp index f9a6d9921..1387bf422 100644 --- a/Src/Orbiter/GraphicsAPI.cpp +++ b/Src/Orbiter/GraphicsAPI.cpp @@ -17,7 +17,8 @@ #include "Util.h" #include "resource.h" #include -#include +#include +namespace fs = std::filesystem; using std::min; @@ -178,24 +179,17 @@ ScreenAnnotation *GraphicsClient::clbkCreateAnnotation () bool GraphicsClient::TexturePath (const char *fname, char *path) const { - struct _finddata_t fd; - intptr_t fh; - // first try htex directory strcpy (path, g_pOrbiter->Cfg()->CfgDirPrm.HightexDir); strcat (path, fname); - if ((fh = _findfirst (path, &fd)) != -1) { - _findclose (fh); - return true; - } + if (fs::exists(path)) return true; // try tex directory strcpy (path, g_pOrbiter->Cfg()->CfgDirPrm.TextureDir); strcat (path, fname); - if ((fh = _findfirst (path, &fd)) != -1) { - _findclose (fh); - return true; - } + + if (fs::exists(path)) return true; + return false; } diff --git a/Src/Orbiter/OptionsPages.cpp b/Src/Orbiter/OptionsPages.cpp index 1ebdad07b..bb22b42e1 100644 --- a/Src/Orbiter/OptionsPages.cpp +++ b/Src/Orbiter/OptionsPages.cpp @@ -6,7 +6,6 @@ // ====================================================================== #include -#include #include #include "OptionsPages.h" #include "DlgCtrl.h" @@ -1905,19 +1904,13 @@ void OptionsPage_Planetarium::RescanMarkerList(HWND hPage) const std::vector< oapi::GraphicsClient::LABELLIST>& list = g_psys->LabelList(); if (!list.size()) return; - char cbuf[256]; - _finddata_t fdata; - intptr_t fh = g_psys->FindFirst(FILETYPE_MARKER, &fdata, cbuf); - if (fh >= 0) { - int n = 0; - do { - SendDlgItemMessage(hPage, IDC_OPT_PLN_MKRLIST, LB_ADDSTRING, 0, (LPARAM)trim_string(cbuf)); - if (n < list.size() && list[n].active) - SendDlgItemMessage(hPage, IDC_OPT_PLN_MKRLIST, LB_SETSEL, TRUE, n); - n++; - } while (!g_psys->FindNext(fh, &fdata, cbuf)); - _findclose(fh); - } + int n = 0; + g_psys->ForEach(FILETYPE_MARKER, [&](const fs::directory_entry& entry) { + SendDlgItemMessage(hPage, IDC_OPT_PLN_MKRLIST, LB_ADDSTRING, 0, (LPARAM)entry.path().stem().string().c_str()); + if (n < list.size() && list[n].active) + SendDlgItemMessage(hPage, IDC_OPT_PLN_MKRLIST, LB_SETSEL, TRUE, n); + n++; + }); } // ====================================================================== @@ -2084,18 +2077,14 @@ void OptionsPage_Labels::UpdateFeatureList(HWND hPage) if (planet->LabelFormat() < 2) { oapi::GraphicsClient::LABELLIST* list = planet->LabelList(&nlist); if (!nlist) return; - _finddata_t fdata; - long fh = planet->FindFirst(FILETYPE_MARKER, &fdata, cpath, cbuf); - if (fh >= 0) { - n = 0; - do { - SendDlgItemMessage(hPage, IDC_OPT_MKR_FEATURELIST, LB_ADDSTRING, 0, (LPARAM)trim_string(cbuf)); + + n = 0; + planet->ForEach(FILETYPE_MARKER, [&](const fs::directory_entry& entry) { + SendDlgItemMessage(hPage, IDC_OPT_MKR_FEATURELIST, LB_ADDSTRING, 0, (LPARAM)entry.path().stem().string().c_str()); if (n < nlist && list[n].active) SendDlgItemMessage(hPage, IDC_OPT_MKR_FEATURELIST, LB_SETSEL, TRUE, n); n++; - } while (!planet->FindNext(fh, &fdata, cbuf)); - _findclose(fh); - } + }); } else { int nlabel = planet->NumLabelLegend(); diff --git a/Src/Orbiter/Orbiter.cpp b/Src/Orbiter/Orbiter.cpp index b389bc84e..5bd878368 100644 --- a/Src/Orbiter/Orbiter.cpp +++ b/Src/Orbiter/Orbiter.cpp @@ -8,16 +8,11 @@ #pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") #include -#include -#include -#include -#include #include #include #include #include -#include -#include +#include #include "cmdline.h" #include "D3d7util.h" #include "D3dmath.h" @@ -48,6 +43,8 @@ #include "DlgCtrl.h" #include "GraphicsAPI.h" #include "ConsoleManager.h" +#include +namespace fs = std::filesystem; #ifdef INLINEGRAPHICS #include "OGraphics.h" @@ -544,18 +541,13 @@ int Orbiter::GetVersion () const return v; } -static bool FileExists(const char* path) -{ - return access(path, 0) != -1; -} - //! Finds legacy module consisting of a single DLL //! @return true on success //! @param cbufOut returns path to the plugin DLL static bool FindStandaloneDll(const char *path, const char *name, char* cbufOut) { sprintf (cbufOut, "%s\\%s.dll", path, name); - return FileExists(cbufOut); + return fs::exists(cbufOut); } //! Finds module consisting of a plugin DLL inside a plugin-specific folder @@ -564,7 +556,7 @@ static bool FindStandaloneDll(const char *path, const char *name, char* cbufOut) static bool FindDllInPluginFolder(const char *path, const char *name, char* cbufOut) { sprintf(cbufOut, "%s\\%s\\%s.dll", path, name, name); - return FileExists(cbufOut); + return fs::exists(cbufOut); } void Orbiter::LoadModules(const std::string& path, const std::list& names) @@ -573,19 +565,14 @@ void Orbiter::LoadModules(const std::string& path, const std::list& LoadModule(path.c_str(), name.c_str()); } - void Orbiter::LoadModules(const std::string& path) { - struct _finddata_t fdata; - intptr_t fh = _findfirst((path + std::string("\\*.dll")).c_str(), &fdata); - if (fh == -1) return; // no files found - do { - if (strlen(fdata.name) > 4) { - fdata.name[strlen(fdata.name) - 4] = '\0'; // cut off extension - LoadModule(path.c_str(), fdata.name); + for (const auto& entry : fs::directory_iterator(path)) { + auto fpath = entry.path(); + if (fpath.extension().string() == ".dll") { + LoadModule(path.c_str(), fpath.stem().string().c_str()); } - } while (!_findnext(fh, &fdata)); - _findclose(fh); + } } //----------------------------------------------------------------------------- diff --git a/Src/Orbiter/Planet.cpp b/Src/Orbiter/Planet.cpp index 335b787de..9bc6f03b0 100644 --- a/Src/Orbiter/Planet.cpp +++ b/Src/Orbiter/Planet.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include "Orbiter.h" #include "Config.h" #include "State.h" @@ -469,35 +468,6 @@ Planet::~Planet () delete emgr; } -intptr_t Planet::FindFirst (int type, _finddata_t *fdata, char *path, char *fname) -{ - intptr_t fh; - char cbuf[256]; - - switch (type) { - case FILETYPE_MARKER: - if (labelpath) strcpy (path, labelpath); - else sprintf (path, "%s%s/Marker/", g_pOrbiter->Cfg()->CfgDirPrm.ConfigDir, name.c_str()); - break; - } - sprintf (cbuf, "%s*.mkr", path); - if ((fh = _findfirst (cbuf, fdata)) != -1) { - strncpy (fname, fdata->name, strlen(fdata->name)-4); - fname[strlen(fdata->name)-4] = '\0'; - } - return fh; -} - -intptr_t Planet::FindNext (intptr_t fh, _finddata_t *fdata, char *fname) -{ - intptr_t fn = _findnext (fh, fdata); - if (!fn) { - strncpy (fname, fdata->name, strlen(fdata->name)-4); - fname[strlen(fdata->name)-4] = '\0'; - } - return fn; -} - void Planet::ScanBases (char *path) { char cbuf[256], spath[256], *pc, *cut = 0; @@ -525,25 +495,24 @@ void Planet::ScanBases (char *path) trim_string (path); } - intptr_t fh; - _finddata_t fdata; - sprintf (spath, "%s\\*", path); + sprintf (spath, "%s/dummy", path); strcpy (cbuf, g_pOrbiter->ConfigPath(spath)); - if ((fh = _findfirst (cbuf, &fdata)) != -1) { - do { - sprintf (spath, "%s\\%s", path, fdata.name); - spath[strlen(spath)-4] = '\0'; // strip 'cfg' extension - ifstream ifs (g_pOrbiter->ConfigPath (spath)); + fs::path configdir = fs::path(cbuf).parent_path(); + std::error_code ec; + for (const auto& entry : fs::directory_iterator(configdir, ec)) { + if (entry.path().extension().string() == ".cfg") { + ifstream ifs(entry); if (!ifs) continue; do { - if (!ifs.getline (cbuf, 256)) break; - pc = trim_string (cbuf); + if (!ifs.getline(cbuf, 256)) break; + pc = trim_string(cbuf); } while (!pc[0]); - if (_strnicmp (pc, "BASE-V2.0", 9)) continue; - Base *base = new Base (spath, this); TRACENEW - if (!AddBase (base)) + if (_strnicmp(pc, "BASE-V2.0", 9)) continue; + sprintf(spath, "%s\\%s", path, entry.path().stem().string().c_str()); + Base* base = new Base(spath, this); TRACENEW + if (!AddBase(base)) delete base; - } while (!_findnext (fh, &fdata)); + } } } @@ -568,97 +537,94 @@ bool Planet::AddBase (Base *base) void Planet::ScanLabelLists (ifstream &cfg) { int i; - char cbuf[256], fname[256], lbpath[256]; int nlabellistbuf = 0; nlabellist = 0; - _finddata_t fdata; - intptr_t fh = FindFirst (FILETYPE_MARKER, &fdata, lbpath, fname); - if (fh >= 0) { - - oapi::GraphicsClient::LABELLIST *ll; - bool scanheader = (labellist == 0); // only need to parse the headers for the initial scan - - do { - // open marker file - sprintf (cbuf, "%s%s.mkr", lbpath, fname); - ifstream ulf (cbuf); - - // read label header - if (scanheader) { - if (nlabellist == nlabellistbuf) { // increase buffer - oapi::GraphicsClient::LABELLIST *tmp = new oapi::GraphicsClient::LABELLIST[nlabellistbuf += 8]; - for (int i = 0; i < nlabellist; i++) - tmp[i] = labellist[i]; - if (nlabellist) delete []labellist; - labellist = tmp; - } - ll = labellist+nlabellist; - ll->name = fname; - ll->marker.clear(); - ll->colour = 1; - ll->shape = 0; - ll->size = 1.0f; - ll->distfac = 1.0f; - ll->active = false; - ll->flag = 0; - if (FindLine (ulf, "BEGIN_HEADER")) { - char item[256], value[256]; - for (;;) { - if (!ulf.getline (cbuf, 256) || !_strnicmp (cbuf, "END_HEADER", 10)) break; - sscanf (cbuf, "%s %s", item, value); - if (!_stricmp (item, "InitialState")) { - if (!_stricmp (value, "on")) ll->active = true; - } else if (!_stricmp (item, "ColourIdx")) { - int col; - sscanf (value, "%d", &col); - ll->colour = max (0, min (5, col)); - } else if (!_stricmp (item, "ShapeIdx")) { - int shape; - sscanf (value, "%d", &shape); - ll->shape = max (0, min (6, shape)); - } else if (!_stricmp (item, "Size")) { - float size; - sscanf (value, "%f", &size); - ll->size = max (0.1f, min (2.0f, size)); - } else if (!_stricmp (item, "DistanceFactor")) { - float distfac; - sscanf (value, "%f", &distfac); - ll->distfac = max (1e-5f, min (1e3f, distfac)); - } + oapi::GraphicsClient::LABELLIST* ll; + bool scanheader = (labellist == 0); // only need to parse the headers for the initial scan + ForEach(FILETYPE_MARKER, [&](const fs::directory_entry& entry) { + char cbuf[256]; + // open marker file + ifstream ulf(entry); + + // read label header + if (scanheader) { + if (nlabellist == nlabellistbuf) { // increase buffer + oapi::GraphicsClient::LABELLIST* tmp = new oapi::GraphicsClient::LABELLIST[nlabellistbuf += 8]; + for (int i = 0; i < nlabellist; i++) + tmp[i] = labellist[i]; + if (nlabellist) delete[]labellist; + labellist = tmp; + } + ll = labellist + nlabellist; + ll->name = entry.path().filename().string(); + ll->marker.clear(); + ll->colour = 1; + ll->shape = 0; + ll->size = 1.0f; + ll->distfac = 1.0f; + ll->active = false; + ll->flag = 0; + if (FindLine(ulf, "BEGIN_HEADER")) { + char item[256], value[256]; + for (;;) { + if (!ulf.getline(cbuf, 256) || !_strnicmp(cbuf, "END_HEADER", 10)) break; + sscanf(cbuf, "%s %s", item, value); + if (!_stricmp(item, "InitialState")) { + if (!_stricmp(value, "on")) ll->active = true; + } + else if (!_stricmp(item, "ColourIdx")) { + int col; + sscanf(value, "%d", &col); + ll->colour = max(0, min(5, col)); + } + else if (!_stricmp(item, "ShapeIdx")) { + int shape; + sscanf(value, "%d", &shape); + ll->shape = max(0, min(6, shape)); + } + else if (!_stricmp(item, "Size")) { + float size; + sscanf(value, "%f", &size); + ll->size = max(0.1f, min(2.0f, size)); + } + else if (!_stricmp(item, "DistanceFactor")) { + float distfac; + sscanf(value, "%f", &distfac); + ll->distfac = max(1e-5f, min(1e3f, distfac)); } } - } else { - ll = labellist+nlabellist; } + } + else { + ll = labellist + nlabellist; + } - // read label list for active labels, if not already present - if (ll->active && !ll->marker.size()) { - int nlistbuf = 0; - double lng, lat; - int nl; - char *pc; - Vector pos; - FindLine (ulf, "BEGIN_DATA"); - for (nl = 0;; nl++) { - if (!ulf.getline (cbuf, 256)) break; - pc = strtok (cbuf, ":"); - if (!pc || sscanf (pc, "%lf%lf", &lng, &lat) != 2) continue; - EquatorialToLocal (RAD*lng, RAD*lat, size, pos); - oapi::GraphicsClient::LABELSPEC ls; - ls.pos = _V(pos.x, pos.y, pos.z); - for (i = 0; i < 2; i++) { - if (pc = strtok (NULL, ":")) - ls.label[i] = trim_string(pc); - } - ll->marker.push_back(ls); + // read label list for active labels, if not already present + if (ll->active && !ll->marker.size()) { + int nlistbuf = 0; + double lng, lat; + int nl; + char* pc; + Vector pos; + FindLine(ulf, "BEGIN_DATA"); + for (nl = 0;; nl++) { + if (!ulf.getline(cbuf, 256)) break; + pc = strtok(cbuf, ":"); + if (!pc || sscanf(pc, "%lf%lf", &lng, &lat) != 2) continue; + EquatorialToLocal(RAD * lng, RAD * lat, size, pos); + oapi::GraphicsClient::LABELSPEC ls; + ls.pos = _V(pos.x, pos.y, pos.z); + for (i = 0; i < 2; i++) { + if (pc = strtok(NULL, ":")) + ls.label[i] = trim_string(pc); } + ll->marker.push_back(ls); } - nlabellist++; + } + nlabellist++; - } while (!FindNext (fh, &fdata, fname)); - _findclose (fh); - } + }); } void Planet::ScanLabelLegend() diff --git a/Src/Orbiter/Planet.h b/Src/Orbiter/Planet.h index 7172f0f75..773480804 100644 --- a/Src/Orbiter/Planet.h +++ b/Src/Orbiter/Planet.h @@ -21,6 +21,10 @@ #include "Nav.h" #include "GraphicsAPI.h" #include "VObject.h" // temporary +#include "Orbiter.h" +#include +#include +namespace fs = std::filesystem; #define FILETYPE_MARKER 1 @@ -181,9 +185,24 @@ class Planet: public CelestialBody { TileManager2 *SurfMgr2() const { return smgr2; } ElevationManager *ElevMgr() const { return emgr; } TileManager2 *CloudMgr2() const { return cmgr2; } - - intptr_t FindFirst (int type, _finddata_t *fdata, char *path, char *fname); - intptr_t FindNext (intptr_t fh, _finddata_t *fdata, char *fname); + void ForEach(int type, std::function callback) { + extern Orbiter* g_pOrbiter; + fs::path path; + std::string ext; + switch (type) { + case FILETYPE_MARKER: + ext = ".mkr"; + if (labelpath) path = labelpath; + else path = fs::path(g_pOrbiter->Cfg()->CfgDirPrm.ConfigDir) / name / "Marker"; + break; + } + std::error_code ec; + for (const auto& entry : fs::directory_iterator(path, ec)) { + if (entry.path().extension().string() == ext) { + callback(entry); + } + } + } //USERLABELSPEC const *GetUserLabel (int idx) const { return userlabel+idx; } //int nUserLabel () const { return nuserlabel; } diff --git a/Src/Orbiter/Psys.cpp b/Src/Orbiter/Psys.cpp index 78ac22e57..d203e102b 100644 --- a/Src/Orbiter/Psys.cpp +++ b/Src/Orbiter/Psys.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include "Config.h" @@ -220,129 +219,101 @@ void PlanetarySystem::OutputLoadStatus (const char *bname, OutputLoadStatusCallb outputLoadStatus(cbuf, 0, callbackContext); } -intptr_t PlanetarySystem::FindFirst (int type, _finddata_t *fdata, char *fname) -{ - intptr_t fh; - char cbuf[256]; - - std::string searchPath = m_labelPath + "*.mkr"; - if ((fh = _findfirst (searchPath.c_str(), fdata)) != -1) { - strncpy (fname, fdata->name, strlen(fdata->name)-4); - fname[strlen(fdata->name)-4] = '\0'; - } - return fh; -} - -intptr_t PlanetarySystem::FindNext (intptr_t fh, _finddata_t *fdata, char *fname) -{ - intptr_t fn = _findnext (fh, fdata); - if (!fn) { - strncpy (fname, fdata->name, strlen(fdata->name)-4); - fname[strlen(fdata->name)-4] = '\0'; - } - return fn; -} - void PlanetarySystem::ScanLabelLists (ifstream &cfg, bool bScanHeaders) { int i; - char cbuf[256], fname[256]; - - _finddata_t fdata; - intptr_t fh = FindFirst (FILETYPE_MARKER, &fdata, fname); - if (fh >= 0) { - - oapi::GraphicsClient::LABELLIST *ll; - int idx = 0; - - do { - // open marker file - sprintf (cbuf, "%s%s.mkr", m_labelPath.c_str(), fname); - ifstream ulf (cbuf); - - // read label header - if (bScanHeaders) { - oapi::GraphicsClient::LABELLIST list; - //list.marker.clear(); - list.colour = 1; - list.shape = 0; - list.size = 1.0f; - list.distfac = 1.0f; - list.active = false; - list.flag = 0; - if (FindLine (ulf, "BEGIN_HEADER")) { - char item[256], value[256]; - for (;;) { - if (!ulf.getline (cbuf, 256) || !_strnicmp (cbuf, "END_HEADER", 10)) break; - sscanf (cbuf, "%s %s", item, value); - if (!_stricmp (item, "InitialState")) { - if (!_stricmp (value, "on")) list.active = true; - } else if (!_stricmp (item, "ColourIdx")) { - int col; - sscanf (value, "%d", &col); - list.colour = max (0, min (5, col)); - } else if (!_stricmp (item, "ShapeIdx")) { - int shape; - sscanf (value, "%d", &shape); - list.shape = max (0, min (6, shape)); - } else if (!_stricmp (item, "Size")) { - float size; - sscanf (value, "%f", &size); - list.size = max (0.1f, min (2.0f, size)); - } else if (!_stricmp (item, "DistanceFactor")) { - float distfac; - sscanf (value, "%f", &distfac); - list.distfac = max (1e-5f, min (1e3f, distfac)); - } else if (!_stricmp (item, "Frame")) { - if (_stricmp (value, "Ecliptic")) - list.flag = 1; // flag for celestial position data - } + char cbuf[256]; + oapi::GraphicsClient::LABELLIST* ll; + int idx = 0; + ForEach(FILETYPE_MARKER, [&](const fs::directory_entry& entry) { + // open marker file + ifstream ulf(entry); + // read label header + if (bScanHeaders) { + oapi::GraphicsClient::LABELLIST list; + //list.marker.clear(); + list.colour = 1; + list.shape = 0; + list.size = 1.0f; + list.distfac = 1.0f; + list.active = false; + list.flag = 0; + if (FindLine(ulf, "BEGIN_HEADER")) { + char item[256], value[256]; + for (;;) { + if (!ulf.getline(cbuf, 256) || !_strnicmp(cbuf, "END_HEADER", 10)) break; + sscanf(cbuf, "%s %s", item, value); + if (!_stricmp(item, "InitialState")) { + if (!_stricmp(value, "on")) list.active = true; + } + else if (!_stricmp(item, "ColourIdx")) { + int col; + sscanf(value, "%d", &col); + list.colour = max(0, min(5, col)); + } + else if (!_stricmp(item, "ShapeIdx")) { + int shape; + sscanf(value, "%d", &shape); + list.shape = max(0, min(6, shape)); + } + else if (!_stricmp(item, "Size")) { + float size; + sscanf(value, "%f", &size); + list.size = max(0.1f, min(2.0f, size)); + } + else if (!_stricmp(item, "DistanceFactor")) { + float distfac; + sscanf(value, "%f", &distfac); + list.distfac = max(1e-5f, min(1e3f, distfac)); + } + else if (!_stricmp(item, "Frame")) { + if (_stricmp(value, "Ecliptic")) + list.flag = 1; // flag for celestial position data } } - m_labelList.push_back(list); - ll = &m_labelList.back(); - } else { - ll = &m_labelList[idx++]; } + m_labelList.push_back(list); + ll = &m_labelList.back(); + } + else { + ll = &m_labelList[idx++]; + } - // check if positions are in celestial or ecliptic frame - bool celestialpos = ((ll->flag & 1) != 0); - - // read label list for active labels, if not already present - if (ll->active && !ll->marker.size()) { - double lng, lat; - int nl; - char *pc; - FindLine (ulf, "BEGIN_DATA"); - for (nl = 0;; nl++) { - if (!ulf.getline (cbuf, 256)) break; - pc = strtok (cbuf, ":"); - if (!pc || sscanf (pc, "%lf%lf", &lng, &lat) != 2) continue; - lng = Rad(lng); - lat = Rad(lat); - if (celestialpos) { - static double eps = 0.4092797095927; - static double coseps = cos(eps), sineps = sin(eps); - double ra = lng, dc = lat; - Equ2Ecl (coseps, sineps, ra, dc, lng, lat); - } - oapi::GraphicsClient::LABELSPEC ls; - double xz = cos(lat); - ls.pos.y = sin(lat); - ls.pos.x = xz * cos(lng); - ls.pos.z = xz * sin(lng); - for (i = 0; i < 2; i++) { - if (pc = strtok (NULL, ":")) { - ls.label[i] = trim_string(pc); - } + // check if positions are in celestial or ecliptic frame + bool celestialpos = ((ll->flag & 1) != 0); + + // read label list for active labels, if not already present + if (ll->active && !ll->marker.size()) { + double lng, lat; + int nl; + char* pc; + FindLine(ulf, "BEGIN_DATA"); + for (nl = 0;; nl++) { + if (!ulf.getline(cbuf, 256)) break; + pc = strtok(cbuf, ":"); + if (!pc || sscanf(pc, "%lf%lf", &lng, &lat) != 2) continue; + lng = Rad(lng); + lat = Rad(lat); + if (celestialpos) { + static double eps = 0.4092797095927; + static double coseps = cos(eps), sineps = sin(eps); + double ra = lng, dc = lat; + Equ2Ecl(coseps, sineps, ra, dc, lng, lat); + } + oapi::GraphicsClient::LABELSPEC ls; + double xz = cos(lat); + ls.pos.y = sin(lat); + ls.pos.x = xz * cos(lng); + ls.pos.z = xz * sin(lng); + for (i = 0; i < 2; i++) { + if (pc = strtok(NULL, ":")) { + ls.label[i] = trim_string(pc); } - ll->marker.push_back(ls); } + ll->marker.push_back(ls); } - - } while (!FindNext (fh, &fdata, fname)); - _findclose (fh); - } + } + }); } void PlanetarySystem::ActivatePlanetLabels(bool activate) diff --git a/Src/Orbiter/Psys.h b/Src/Orbiter/Psys.h index 503f51e8d..3a8ff22c7 100644 --- a/Src/Orbiter/Psys.h +++ b/Src/Orbiter/Psys.h @@ -9,6 +9,7 @@ #include "Base.h" #include "Star.h" #include "Planet.h" +#include class Vessel; class SuperVessel; @@ -198,8 +199,14 @@ class PlanetarySystem { void ActivatePlanetLabels(bool activate); - intptr_t FindFirst (int type, _finddata_t *fdata, char *fname); - intptr_t FindNext (intptr_t fh, _finddata_t *fdata, char *fname); + void ForEach(int type, std::function callback) { + std::error_code ec; + for (const auto& entry : fs::directory_iterator(m_labelPath, ec)) { + if (entry.path().extension().string() == ".mkr") { + callback(entry); + } + } + } private: std::string m_Name; // system's name diff --git a/Src/Orbiter/TabModule.cpp b/Src/Orbiter/TabModule.cpp index a3336ad5b..145c18890 100644 --- a/Src/Orbiter/TabModule.cpp +++ b/Src/Orbiter/TabModule.cpp @@ -6,12 +6,12 @@ //============================================================================= #include -#include -#include #include "Orbiter.h" #include "Launchpad.h" #include "TabModule.h" #include "resource.h" +#include +namespace fs = std::filesystem; using std::max; @@ -144,7 +144,6 @@ void orbiter::ModuleTab::Show () } //----------------------------------------------------------------------------- - void orbiter::ModuleTab::RefreshLists () { HWND hTree = GetDlgItem (hTab, IDC_MOD_TREE); @@ -154,72 +153,74 @@ void orbiter::ModuleTab::RefreshLists () tvis.item.mask = TVIF_TEXT | TVIF_PARAM; int idx, len; - char cbuf[256], catstr[256]; - struct _finddata_t fdata; - intptr_t fh = _findfirst ("Modules\\Plugin\\*.dll", &fdata); - if (fh == -1) return; // no files found - do { - // add module record - MODULEREC **tmp = new MODULEREC*[nmodulerec+1]; - if (nmodulerec) { - memcpy (tmp, modulerec, nmodulerec*sizeof(MODULEREC*)); - delete []modulerec; - } - modulerec = tmp; - - MODULEREC *rec = modulerec[nmodulerec++] = new MODULEREC; - len = strlen(fdata.name)-4; - rec->name = new char[len+1]; - strncpy (rec->name, fdata.name, len); - rec->name[len] = '\0'; - rec->info = 0; - rec->active = false; - rec->locked = false; - - // check if module is set active in config - if (pCfg->IsActiveModule(rec->name)) - rec->active = true; - - // check if module is set active in command line - if (std::find(pCfg->CfgCmdlinePrm.LoadPlugins.begin(), pCfg->CfgCmdlinePrm.LoadPlugins.end(), rec->name) != pCfg->CfgCmdlinePrm.LoadPlugins.end()) { - rec->active = true; - rec->locked = true; // modules activated from the command line are not to be unloaded - } - - sprintf (cbuf, "Modules\\Plugin\\%s", fdata.name); - HMODULE hMod = LoadLibraryEx (cbuf, 0, LOAD_LIBRARY_AS_DATAFILE); - if (hMod) { - char buf[1024]; - // read module info string - if (LoadString (hMod, 1000, buf, 1024)) { - buf[1023] = '\0'; - rec->info = new char[strlen(buf)+1]; - strcpy (rec->info, buf); + char catstr[256]; + + const fs::path moddir{ "Modules/Plugin" }; + + for (const auto& file : fs::directory_iterator(moddir)) { + if (file.path().extension().string() == ".dll") { + auto name = file.path().filename().string(); + // add module record + MODULEREC** tmp = new MODULEREC * [nmodulerec + 1]; + if (nmodulerec) { + memcpy(tmp, modulerec, nmodulerec * sizeof(MODULEREC*)); + delete[]modulerec; } - // read category string - if (LoadString (hMod, 1001, buf, 1024)) { - strncpy (catstr, buf, 255); - } else { - strcpy (catstr, "Miscellaneous"); + modulerec = tmp; + + MODULEREC* rec = modulerec[nmodulerec++] = new MODULEREC; + len = name.length() - 4; + rec->name = new char[len + 1]; + strncpy(rec->name, name.c_str(), len); + rec->name[len] = '\0'; + rec->info = 0; + rec->active = false; + rec->locked = false; + + // check if module is set active in config + if (pCfg->IsActiveModule(rec->name)) + rec->active = true; + + // check if module is set active in command line + if (std::find(pCfg->CfgCmdlinePrm.LoadPlugins.begin(), pCfg->CfgCmdlinePrm.LoadPlugins.end(), rec->name) != pCfg->CfgCmdlinePrm.LoadPlugins.end()) { + rec->active = true; + rec->locked = true; // modules activated from the command line are not to be unloaded } - FreeLibrary (hMod); - } - if (!strcmp (catstr, "Graphics engines")) - continue; // graphics client modules are loaded via the Video tab + HMODULE hMod = LoadLibraryEx((moddir / name).string().c_str(), 0, LOAD_LIBRARY_AS_DATAFILE); + if (hMod) { + char buf[1024]; + // read module info string + if (LoadString(hMod, 1000, buf, 1024)) { + buf[1023] = '\0'; + rec->info = new char[strlen(buf) + 1]; + strcpy(rec->info, buf); + } + // read category string + if (LoadString(hMod, 1001, buf, 1024)) { + strncpy(catstr, buf, 255); + catstr[255] = '\0'; + } + else { + strcpy(catstr, "Miscellaneous"); + } + FreeLibrary(hMod); + } - // find the category entry - HTREEITEM catItem = GetCategoryItem (catstr); + if (!strcmp(catstr, "Graphics engines")) + continue; // graphics client modules are loaded via the Video tab - // tree view entry - tvis.item.pszText = rec->name; - tvis.item.lParam = (LPARAM)rec; - tvis.hInsertAfter = TVI_SORT; - tvis.hParent = catItem; - HTREEITEM hti = TreeView_InsertItem (hTree, &tvis); + // find the category entry + HTREEITEM catItem = GetCategoryItem(catstr); - } while (!_findnext (fh, &fdata)); - _findclose (fh); + // tree view entry + tvis.item.pszText = rec->name; + tvis.item.lParam = (LPARAM)rec; + tvis.hInsertAfter = TVI_SORT; + tvis.hParent = catItem; + HTREEITEM hti = TreeView_InsertItem(hTree, &tvis); + } + } counter = 0; } diff --git a/Src/Orbiter/TabScenario.cpp b/Src/Orbiter/TabScenario.cpp index 31b5beb64..6765b2e77 100644 --- a/Src/Orbiter/TabScenario.cpp +++ b/Src/Orbiter/TabScenario.cpp @@ -6,7 +6,6 @@ //============================================================================= #include -#include #include #include #include "Orbiter.h" @@ -258,69 +257,57 @@ void orbiter::ScenarioTab::LaunchpadShowing(bool show) } //----------------------------------------------------------------------------- -void orbiter::ScenarioTab::ScanDirectory (const char *ppath, HTREEITEM hti) +void orbiter::ScenarioTab::ScanDirectory (const fs::path& path, HTREEITEM hti) { TV_INSERTSTRUCT tvis; HTREEITEM ht, hts0, ht0; - struct _finddata_t fdata; - intptr_t fh; - char cbuf[256], path[256], *fname; - - strcpy (path, ppath); - fname = path + strlen(path); + char cbuf[256]; tvis.hParent = hti; tvis.item.mask = TVIF_TEXT | TVIF_CHILDREN | TVIF_IMAGE | TVIF_SELECTEDIMAGE; tvis.item.pszText = cbuf; - - // scan for subdirectories - strcpy (fname, "*.*"); - if ((fh = _findfirst (path, &fdata)) != -1) { - tvis.hInsertAfter = TVI_SORT; - tvis.item.cChildren = 1; - tvis.item.iImage = treeicon_idx[0]; - tvis.item.iSelectedImage = treeicon_idx[0]; - do { - if ((fdata.attrib & _A_SUBDIR) && fdata.name[0] != '.') { - strcpy (cbuf, fdata.name); - ht = (HTREEITEM)SendDlgItemMessage (hTab, IDC_SCN_LIST, TVM_INSERTITEM, 0, (LPARAM)&tvis); - strcpy (fname, fdata.name); strcat (fname, "\\"); - ScanDirectory (path, ht); - } - } while (!_findnext (fh, &fdata)); - _findclose (fh); + tvis.hInsertAfter = TVI_SORT; + tvis.item.cChildren = 1; + tvis.item.iImage = treeicon_idx[0]; + tvis.item.iSelectedImage = treeicon_idx[0]; + + for (auto& entry : fs::directory_iterator(path)) { + if (entry.is_directory()) { + strcpy(cbuf, entry.path().stem().string().c_str()); + ht = (HTREEITEM)SendDlgItemMessage(hTab, IDC_SCN_LIST, TVM_INSERTITEM, 0, (LPARAM)&tvis); + ScanDirectory(entry.path(), ht); + } } + hts0 = (HTREEITEM)SendDlgItemMessage (hTab, IDC_SCN_LIST, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hti); // the first subdirectory entry in this folder // scan for files - strcpy (fname, "*.scn"); - if ((fh = _findfirst (path, &fdata)) != -1) { - tvis.hInsertAfter = TVI_FIRST; - tvis.item.cChildren = 0; - tvis.item.iImage = treeicon_idx[2]; - tvis.item.iSelectedImage = treeicon_idx[3]; - do { - strcpy (cbuf, fdata.name); - cbuf[strlen(cbuf)-4] = '\0'; + tvis.hInsertAfter = TVI_FIRST; + tvis.item.cChildren = 0; + tvis.item.iImage = treeicon_idx[2]; + tvis.item.iSelectedImage = treeicon_idx[3]; + for (auto& entry : fs::directory_iterator(path)) { + if (entry.is_regular_file() && entry.path().extension().string() == ".scn") { + strcpy(cbuf, entry.path().stem().string().c_str()); char ch[256]; - TV_ITEM tvi = {TVIF_HANDLE | TVIF_TEXT, 0, 0, 0, ch, 256}; + TV_ITEM tvi = { TVIF_HANDLE | TVIF_TEXT, 0, 0, 0, ch, 256 }; - ht0 = (HTREEITEM)SendDlgItemMessage (hTab, IDC_SCN_LIST, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hti); - for (tvi.hItem = ht0; tvi.hItem && tvi.hItem != hts0; tvi.hItem = (HTREEITEM)SendDlgItemMessage (hTab, IDC_SCN_LIST, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)tvi.hItem)) { - SendDlgItemMessage (hTab, IDC_SCN_LIST, TVM_GETITEM, 0, (LPARAM)&tvi); - if (strcmp (tvi.pszText, cbuf) > 0) break; + ht0 = (HTREEITEM)SendDlgItemMessage(hTab, IDC_SCN_LIST, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hti); + for (tvi.hItem = ht0; tvi.hItem && tvi.hItem != hts0; tvi.hItem = (HTREEITEM)SendDlgItemMessage(hTab, IDC_SCN_LIST, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)tvi.hItem)) { + SendDlgItemMessage(hTab, IDC_SCN_LIST, TVM_GETITEM, 0, (LPARAM)&tvi); + if (strcmp(tvi.pszText, cbuf) > 0) break; } if (tvi.hItem) { - ht = (HTREEITEM)SendDlgItemMessage (hTab, IDC_SCN_LIST, TVM_GETNEXTITEM, TVGN_PREVIOUS, (LPARAM)tvi.hItem); + ht = (HTREEITEM)SendDlgItemMessage(hTab, IDC_SCN_LIST, TVM_GETNEXTITEM, TVGN_PREVIOUS, (LPARAM)tvi.hItem); tvis.hInsertAfter = (ht ? ht : TVI_FIRST); - } else { + } + else { tvis.hInsertAfter = (hts0 ? TVI_FIRST : TVI_LAST); } - (HTREEITEM)SendDlgItemMessage (hTab, IDC_SCN_LIST, TVM_INSERTITEM, 0, (LPARAM)&tvis); - } while (!_findnext (fh, &fdata)); - _findclose (fh); + (HTREEITEM)SendDlgItemMessage(hTab, IDC_SCN_LIST, TVM_INSERTITEM, 0, (LPARAM)&tvis); + } } } @@ -679,15 +666,13 @@ INT_PTR CALLBACK orbiter::ScenarioTab::SaveProc (HWND hWnd, UINT uMsg, WPARAM wP //----------------------------------------------------------------------------- void orbiter::ScenarioTab::ClearQSFolder() { - char filespec[256], fname[256] = "Quicksave\\"; - strcpy (filespec, pLp->App()->ScnPath ("Quicksave\\*")); - struct _finddata_t fd; - intptr_t hf; - while ((hf = _findfirst (filespec, &fd)) != -1) { - strcpy (fname+10, fd.name); - fname[strlen(fname)-4] = '\0'; - _findclose (hf); - remove (pLp->App()->ScnPath (fname)); + fs::path scnpath{ pLp->App()->ScnPath("Quicksave") }; + scnpath.replace_extension(); // remove ".scn" + + std::error_code ec; + fs::remove_all(scnpath, ec); + if (!ec) { + fs::create_directory(scnpath); } } diff --git a/Src/Orbiter/TabScenario.h b/Src/Orbiter/TabScenario.h index e21fc6ea5..35415f119 100644 --- a/Src/Orbiter/TabScenario.h +++ b/Src/Orbiter/TabScenario.h @@ -12,6 +12,8 @@ #include #include "LpadTab.h" #include "CustomControls.h" +#include +namespace fs = std::filesystem; namespace orbiter { @@ -45,7 +47,7 @@ namespace orbiter { void RefreshList(bool preserveSelection); // refresh the scenario list - void ScanDirectory(const char* path, HTREEITEM hti); + void ScanDirectory(const fs::path &path, HTREEITEM hti); // scan scenario files from a subdirectory void ScenarioChanged(); diff --git a/Src/Orbiter/TabVideo.cpp b/Src/Orbiter/TabVideo.cpp index 3e56f8b9d..4c865a881 100644 --- a/Src/Orbiter/TabVideo.cpp +++ b/Src/Orbiter/TabVideo.cpp @@ -8,8 +8,6 @@ #define OAPI_IMPLEMENTATION #include -#include -#include #include "Orbiter.h" #include "TabVideo.h" #include "resource.h" @@ -170,53 +168,27 @@ void orbiter::DefVideoTab::EnumerateClients(HWND hTab) SendDlgItemMessage(hTab, IDC_VID_COMBO_MODULE, CB_SETCURSEL, 0, 0); } -static bool FileExists(const char* path) -{ - return access(path, 0) != -1; -} - -//! @param extension is a file extension without the '.' -static bool HasExtension(const char* filepath, const char* extension) -{ - std::string str(filepath); - return (str.substr(str.find_last_of(".") + 1) == extension); -} - -static std::string GetNameWithoutFileExtension(const char* filepath) -{ - std::string str(filepath); - return str.substr(0, str.find_last_of(".")); -} - //----------------------------------------------------------------------------- //! Find Graphics engine DLLs in dir -void orbiter::DefVideoTab::ScanDir(HWND hTab, PCSTR dir) +void orbiter::DefVideoTab::ScanDir(HWND hTab, const fs::path& dir) { - char pattern[256], filepath[256]; - sprintf(pattern, "%s\\*", dir); - struct _finddata_t fdata; - intptr_t fh = _findfirst(pattern, &fdata); - if (fh == -1) return; // nothing found - do { - if (fdata.attrib & _A_SUBDIR) { // directory found - if (fdata.name[0] == '.') - continue; // skip self and parent directory entries - // Special case: look for DLLs in subdirectories if subdir and DLL names match - sprintf(filepath, "%s\\%s\\%s.dll", dir, fdata.name, fdata.name); - if (!FileExists(filepath)) + for (auto& entry : fs::directory_iterator(dir)) { + fs::path modulepath; + auto clientname = entry.path().stem().string(); + if (entry.is_directory()) { + modulepath = dir / clientname / (clientname + ".dll"); + if (!fs::exists(modulepath)) continue; } - else { // file found - if (!HasExtension(fdata.name, "dll")) // skip if not a DLL - continue; - sprintf(filepath, "%s\\%s", dir, fdata.name); - } + else if (entry.path().extension().string() == ".dll") + modulepath = entry.path(); + else + continue; // We've found a potential module DLL. Load it. - HMODULE hMod = LoadLibraryEx(filepath, 0, LOAD_LIBRARY_AS_DATAFILE); + HMODULE hMod = LoadLibraryEx(modulepath.string().c_str(), 0, LOAD_LIBRARY_AS_DATAFILE); if (hMod) { char catstr[256]; - std::string clientname = GetNameWithoutFileExtension(fdata.name); // read category string if (LoadString(hMod, 1001, catstr, 256)) { if (!strcmp(catstr, "Graphics engines")) { @@ -224,8 +196,7 @@ void orbiter::DefVideoTab::ScanDir(HWND hTab, PCSTR dir) } } } - } while (!_findnext(fh, &fdata)); - _findclose(fh); + } } //----------------------------------------------------------------------------- diff --git a/Src/Orbiter/TabVideo.h b/Src/Orbiter/TabVideo.h index c107ad576..ea92ca240 100644 --- a/Src/Orbiter/TabVideo.h +++ b/Src/Orbiter/TabVideo.h @@ -10,6 +10,8 @@ #define __TABVIDEO_H #include "LpadTab.h" +#include +namespace fs = std::filesystem; namespace orbiter { @@ -35,7 +37,7 @@ namespace orbiter { void EnumerateClients(HWND hTab); - void ScanDir(HWND hTab, PCSTR dir); + void ScanDir(HWND hTab, const fs::path &dir); // scan directory dir (relative to Orbiter root) for graphics clients // and enter them in the combo box diff --git a/Src/Plugin/LaunchpadExtensions/AtmConfig/AtmConfig.cpp b/Src/Plugin/LaunchpadExtensions/AtmConfig/AtmConfig.cpp index a4d6e5fdf..865da603d 100644 --- a/Src/Plugin/LaunchpadExtensions/AtmConfig/AtmConfig.cpp +++ b/Src/Plugin/LaunchpadExtensions/AtmConfig/AtmConfig.cpp @@ -6,13 +6,14 @@ #include "orbitersdk.h" #include "resource.h" -#include +#include +namespace fs = std::filesystem; using namespace std; class AtmConfig; -const char *CelbodyDir = "Modules\\Celbody"; +const fs::path CelbodyDir = fs::path("Modules") / "Celbody"; const char *ModuleItem = "MODULE_ATM"; struct { @@ -214,65 +215,49 @@ void AtmConfig::ScanCelbodies (HWND hWnd) { SendDlgItemMessage (hWnd, IDC_COMBO2, CB_RESETCONTENT, 0, 0); - char filespec[256]; - sprintf (filespec, "%s\\*.*", CelbodyDir); - _finddata_t info, subinfo; - intptr_t id = _findfirst (filespec, &info); - if (id >= 0) { - intptr_t res; - do { - if (info.attrib & _A_SUBDIR) { - sprintf (filespec, "%s\\%s\\atmosphere", CelbodyDir, info.name); - intptr_t id2 = _findfirst (filespec, &subinfo); - if (id2 >= 0 && (subinfo.attrib & _A_SUBDIR)) { - SendDlgItemMessage (hWnd, IDC_COMBO2, CB_ADDSTRING, 0, (LPARAM)info.name); - } - _findclose (id2); + for (auto& dir : fs::directory_iterator(CelbodyDir)) { + auto path = dir.path(); + if (dir.is_directory()) { + std::error_code ec; + auto atmdir = fs::directory_entry(path / "Atmosphere", ec); + if(!ec && atmdir.is_directory()) { + SendDlgItemMessage(hWnd, IDC_COMBO2, CB_ADDSTRING, 0, (LPARAM)path.filename().string().c_str()); } - res = _findnext (id, &info); - } while (!res); + } } - _findclose (id); } void AtmConfig::ScanModules (const char *celbody) { ClearModules (); - char filespec[256]; - sprintf (filespec, "%s\\%s\\Atmosphere\\*.dll", CelbodyDir, celbody); - _finddata_t info; - intptr_t id = _findfirst (filespec, &info); - if (id >= 0) { - int res; - MODULESPEC *module_last = 0; - do { - info.name[strlen(info.name)-4] = '\0'; // cut off '.dll' extension - char path[256]; - sprintf (path, "%s\\%s\\Atmosphere\\%s", CelbodyDir, celbody, info.name); - char *model_name = 0; - MODULESPEC *ms = new MODULESPEC; + auto path = CelbodyDir / celbody / "Atmosphere"; + MODULESPEC* module_last = 0; + for (auto& entry : fs::directory_iterator(path)) { + auto module = entry.path(); + if (module.extension().string() == ".dll") { + const auto name = module.stem().string(); + + MODULESPEC* ms = new MODULESPEC; if (module_last) module_last->next = ms; else module_first = ms; module_last = ms; - strncpy (ms->module_name, info.name, 255); - strncpy (ms->model_name, info.name, 255); + strncpy(ms->module_name, name.c_str(), 255); + strncpy(ms->model_name, name.c_str(), 255); ms->model_desc[0] = '\0'; ms->next = 0; // get info from the module - HINSTANCE hModule = LoadLibrary (path); + HINSTANCE hModule = LoadLibrary(module.string().c_str()); if (hModule) { - char *(*name_func)() = (char*(*)())GetProcAddress (hModule, "ModelName"); - if (name_func) strncpy (ms->model_name, name_func(), 255); - char *(*desc_func)() = (char*(*)())GetProcAddress (hModule, "ModelDesc"); - if (desc_func) strncpy (ms->model_desc, desc_func(), 511); - FreeLibrary (hModule); + char* (*name_func)() = (char* (*)())GetProcAddress(hModule, "ModelName"); + if (name_func) strncpy(ms->model_name, name_func(), 255); + char* (*desc_func)() = (char* (*)())GetProcAddress(hModule, "ModelDesc"); + if (desc_func) strncpy(ms->model_desc, desc_func(), 511); + FreeLibrary(hModule); } - res = _findnext (id, &info); - } while (!res); + } } - _findclose (id); } INT_PTR CALLBACK AtmConfig::DlgProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) diff --git a/Src/Plugin/ScnEditor/Editor.cpp b/Src/Plugin/ScnEditor/Editor.cpp index 74a7f6bd3..cc650e445 100644 --- a/Src/Plugin/ScnEditor/Editor.cpp +++ b/Src/Plugin/ScnEditor/Editor.cpp @@ -17,7 +17,6 @@ #include "DlgCtrl.h" #include #include -#include using std::min; using std::max; @@ -722,87 +721,75 @@ bool EditorTab_New::CreateVessel () return true; } -void EditorTab_New::ScanConfigDir (const char *ppath, HTREEITEM hti) +void EditorTab_New::ScanConfigDir (const fs::path& dir, HTREEITEM hti) { // recursively scans a directory tree and adds to the list TV_INSERTSTRUCT tvis; HTREEITEM ht, hts0, ht0; - struct _finddata_t fdata; - intptr_t fh; - char cbuf[256], path[256], *fname; - - strcpy (path, ppath); - fname = path + strlen(path); + char cbuf[256]; tvis.hParent = hti; tvis.item.mask = TVIF_TEXT | TVIF_CHILDREN | TVIF_IMAGE | TVIF_SELECTEDIMAGE; tvis.item.pszText = cbuf; + tvis.hInsertAfter = TVI_SORT; + tvis.item.cChildren = 1; + tvis.item.iImage = ed->treeicon_idx[0]; + tvis.item.iSelectedImage = ed->treeicon_idx[0]; // scan for subdirectories - strcpy (fname, "*.*"); - if ((fh = _findfirst (path, &fdata)) != -1) { - tvis.hInsertAfter = TVI_SORT; - tvis.item.cChildren = 1; - tvis.item.iImage = ed->treeicon_idx[0]; - tvis.item.iSelectedImage = ed->treeicon_idx[0]; - do { - if ((fdata.attrib & _A_SUBDIR) && fdata.name[0] != '.') { - strcpy (cbuf, fdata.name); - ht = (HTREEITEM)SendDlgItemMessage (hTab, IDC_VESSELTP, TVM_INSERTITEM, 0, (LPARAM)&tvis); - strcpy (fname, fdata.name); strcat (fname, "\\"); - ScanConfigDir (path, ht); - } - } while (!_findnext (fh, &fdata)); - _findclose (fh); + for (const auto& entry : fs::directory_iterator(dir)) { + if (entry.is_directory()) { + strcpy(cbuf, entry.path().filename().string().c_str()); + ht = (HTREEITEM)SendDlgItemMessage(hTab, IDC_VESSELTP, TVM_INSERTITEM, 0, (LPARAM)&tvis); + ScanConfigDir(entry.path(), ht); + } } + hts0 = (HTREEITEM)SendDlgItemMessage (hTab, IDC_VESSELTP, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hti); // the first subdirectory entry in this folder // scan for files - strcpy (fname, "*.cfg"); - if ((fh = _findfirst (path, &fdata)) != -1) { - tvis.hInsertAfter = TVI_FIRST; - tvis.item.cChildren = 0; - tvis.item.iImage = ed->treeicon_idx[2]; - tvis.item.iSelectedImage = ed->treeicon_idx[3]; - do { + tvis.hInsertAfter = TVI_FIRST; + tvis.item.cChildren = 0; + tvis.item.iImage = ed->treeicon_idx[2]; + tvis.item.iSelectedImage = ed->treeicon_idx[3]; + for (const auto& entry : fs::directory_iterator(dir)) { + if (entry.is_regular_file() && entry.path().extension().string() == ".cfg") { bool skip = false; - strcpy (fname, fdata.name); - FILEHANDLE hFile = oapiOpenFile (path, FILE_IN); + FILEHANDLE hFile = oapiOpenFile(entry.path().string().c_str(), FILE_IN); if (hFile) { bool b; - skip = (oapiReadItem_bool (hFile, (char*)"EditorCreate", b) && !b); - oapiCloseFile (hFile, FILE_IN); + skip = (oapiReadItem_bool(hFile, (char*)"EditorCreate", b) && !b); + oapiCloseFile(hFile, FILE_IN); } if (skip) continue; - strcpy (cbuf, fdata.name); - cbuf[strlen(cbuf)-4] = '\0'; + strcpy(cbuf, entry.path().stem().string().c_str()); char ch[256]; - TV_ITEM tvi = {TVIF_HANDLE | TVIF_TEXT, 0, 0, 0, ch, 256}; + TV_ITEM tvi = { TVIF_HANDLE | TVIF_TEXT, 0, 0, 0, ch, 256 }; - ht0 = (HTREEITEM)SendDlgItemMessage (hTab, IDC_VESSELTP, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hti); - for (tvi.hItem = ht0; tvi.hItem && tvi.hItem != hts0; tvi.hItem = (HTREEITEM)SendDlgItemMessage (hTab, IDC_VESSELTP, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)tvi.hItem)) { - SendDlgItemMessage (hTab, IDC_VESSELTP, TVM_GETITEM, 0, (LPARAM)&tvi); - if (strcmp (tvi.pszText, cbuf) > 0) break; + ht0 = (HTREEITEM)SendDlgItemMessage(hTab, IDC_VESSELTP, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hti); + for (tvi.hItem = ht0; tvi.hItem && tvi.hItem != hts0; tvi.hItem = (HTREEITEM)SendDlgItemMessage(hTab, IDC_VESSELTP, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)tvi.hItem)) { + SendDlgItemMessage(hTab, IDC_VESSELTP, TVM_GETITEM, 0, (LPARAM)&tvi); + if (strcmp(tvi.pszText, cbuf) > 0) break; } if (tvi.hItem) { - ht = (HTREEITEM)SendDlgItemMessage (hTab, IDC_VESSELTP, TVM_GETNEXTITEM, TVGN_PREVIOUS, (LPARAM)tvi.hItem); + ht = (HTREEITEM)SendDlgItemMessage(hTab, IDC_VESSELTP, TVM_GETNEXTITEM, TVGN_PREVIOUS, (LPARAM)tvi.hItem); tvis.hInsertAfter = (ht ? ht : TVI_FIRST); - } else { + } + else { tvis.hInsertAfter = (hts0 ? TVI_FIRST : TVI_LAST); } - (HTREEITEM)SendDlgItemMessage (hTab, IDC_VESSELTP, TVM_INSERTITEM, 0, (LPARAM)&tvis); - } while (!_findnext (fh, &fdata)); - _findclose (fh); + (HTREEITEM)SendDlgItemMessage(hTab, IDC_VESSELTP, TVM_INSERTITEM, 0, (LPARAM)&tvis); + } } } void EditorTab_New::RefreshVesselTpList () { SendDlgItemMessage (hTab, IDC_VESSELTP, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT); - ScanConfigDir ("Config\\Vessels\\", NULL); + ScanConfigDir ("Config/Vessels/", NULL); } int EditorTab_New::GetSelVesselTp (char *name, int len) diff --git a/Src/Plugin/ScnEditor/Editor.h b/Src/Plugin/ScnEditor/Editor.h index 7e6d2b842..82234e1d3 100644 --- a/Src/Plugin/ScnEditor/Editor.h +++ b/Src/Plugin/ScnEditor/Editor.h @@ -17,6 +17,8 @@ #include "ScnEditorAPI.h" #include "Convert.h" #include +#include +namespace fs = std::filesystem; class ScnEditorTab; typedef void (*CustomButtonFunc)(OBJHANDLE); @@ -135,7 +137,7 @@ class EditorTab_New: public ScnEditorTab { static INT_PTR CALLBACK DlgProc (HWND, UINT, WPARAM, LPARAM); protected: - void ScanConfigDir (const char *ppath, HTREEITEM hti); + void ScanConfigDir (const fs::path &dir, HTREEITEM hti); void RefreshVesselTpList (); int GetSelVesselTp (char *name, int len); void VesselTpChanged ();