diff --git a/Sound/XRSound/src/Utils/FileList.cpp b/Sound/XRSound/src/Utils/FileList.cpp index 2071553a9..9d50e0832 100644 --- a/Sound/XRSound/src/Utils/FileList.cpp +++ b/Sound/XRSound/src/Utils/FileList.cpp @@ -53,25 +53,56 @@ void FileList::Scan(const char *pPath, const int recursionLevel) // This code was broken out from XRPayloadClassData::InitializeXRPayloadClassData(). - for (auto& file : fs::directory_iterator(pPath)) { - if (file.path().stem().c_str()[0] != '.') { - if (clbkFilterNode(file)) + 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 ".."? { - // node should be included - if (file.is_directory()) - { - // 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? + if (clbkFilterNode(pNodeFilespec, findFileData)) { - // 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); + // 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); + } } } + } // 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 @@ -79,21 +110,22 @@ 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 fs::directory_entry& entry) +bool FileList::clbkFilterNode(const char *pPathOfNode, const WIN32_FIND_DATA &fd) { - if (entry.is_directory()) - return m_bRecurseSubfolders; + if (IS_DIRECTORY(fd)) + return m_bRecurseSubfolders; // it's a file node bool bAcceptFile = false; if (!m_fileTypesToAccept.empty()) { - if (entry.path().extension().string().length() > 0) // e.g., ".flac" + const char *pFileExtension = strrchr(fd.cFileName, '.'); + if (pFileExtension) // e.g., ".flac" { // see if we have a case-insensitive match for this extension in our master list - for (auto it = m_fileTypesToAccept.begin(); it != m_fileTypesToAccept.end(); it++) + for (vector::const_iterator it = m_fileTypesToAccept.begin(); it != m_fileTypesToAccept.end(); it++) { - if (stricmp(entry.path().extension().string().c_str(), *it) == 0) + if (_stricmp(pFileExtension, *it) == 0) { bAcceptFile = true; break; @@ -108,7 +140,7 @@ bool FileList::clbkFilterNode(const fs::directory_entry& entry) } // Callback invoked for non-empty file nodes that passed the clbkFilterNode check; this is here for subclasses to hook. -void FileList::clbkProcessFile(const fs::directory_entry& entry) +void FileList::clbkProcessFile(const char *pFilespec, const WIN32_FIND_DATA &fd) { // 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 8f20870c7..6daf6dd75 100644 --- a/Sound/XRSound/src/Utils/FileList.h +++ b/Sound/XRSound/src/Utils/FileList.h @@ -13,9 +13,6 @@ using namespace std; -#include -namespace fs = std::filesystem; - class FileList { public: @@ -26,10 +23,9 @@ class FileList static bool DirectoryExists(const char *pPath) { - std::error_code ec; - auto status = fs::status(pPath, ec); - if(ec) return false; - return fs::is_directory(status); + DWORD dwAttrib = GetFileAttributes(pPath); + + return (dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); } // Scan (or rescan) file tree. @@ -45,10 +41,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 fs::directory_entry &); + virtual bool 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. - virtual void clbkProcessFile(const fs::directory_entry &); + virtual void clbkProcessFile(const char *pFilespec, const WIN32_FIND_DATA &fd); 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 96c8ffc3c..990b4fc9b 100644 --- a/Src/Orbiter/FlightRecorder.cpp +++ b/Src/Orbiter/FlightRecorder.cpp @@ -16,9 +16,11 @@ #include "State.h" #include "MenuInfoBar.h" #include +#include +#include +#include +#include #include -#include -namespace fs = std::filesystem; using namespace std; @@ -774,17 +776,24 @@ void Orbiter::FRecorder_Reset () bool Orbiter::FRecorder_PrepareDir (const char *fname, bool force) { - 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); + 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::create_directory(dir); - return true; } diff --git a/Src/Orbiter/GraphicsAPI.cpp b/Src/Orbiter/GraphicsAPI.cpp index ce337642d..8fd818197 100644 --- a/Src/Orbiter/GraphicsAPI.cpp +++ b/Src/Orbiter/GraphicsAPI.cpp @@ -17,8 +17,7 @@ #include "Util.h" #include "resource.h" #include -#include -namespace fs = std::filesystem; +#include using std::min; @@ -175,17 +174,24 @@ 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 (fs::exists(path)) return true; + if ((fh = _findfirst (path, &fd)) != -1) { + _findclose (fh); + return true; + } // try tex directory strcpy (path, g_pOrbiter->Cfg()->CfgDirPrm.TextureDir); strcat (path, fname); - - if (fs::exists(path)) return true; - + if ((fh = _findfirst (path, &fd)) != -1) { + _findclose (fh); + return true; + } return false; } diff --git a/Src/Orbiter/OptionsPages.cpp b/Src/Orbiter/OptionsPages.cpp index 8a8ae386d..484735b17 100644 --- a/Src/Orbiter/OptionsPages.cpp +++ b/Src/Orbiter/OptionsPages.cpp @@ -6,6 +6,7 @@ // ====================================================================== #include +#include #include #include "OptionsPages.h" #include "DlgCtrl.h" @@ -1705,13 +1706,19 @@ void OptionsPage_Planetarium::RescanMarkerList(HWND hPage) const std::vector< oapi::GraphicsClient::LABELLIST>& list = g_psys->LabelList(); if (!list.size()) return; - 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++; - }); + 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); + } } // ====================================================================== @@ -1878,14 +1885,18 @@ void OptionsPage_Labels::UpdateFeatureList(HWND hPage) if (planet->LabelFormat() < 2) { oapi::GraphicsClient::LABELLIST* list = planet->LabelList(&nlist); if (!nlist) return; - - 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()); + _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)); 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 1ffea8861..76766ed6b 100644 --- a/Src/Orbiter/Orbiter.cpp +++ b/Src/Orbiter/Orbiter.cpp @@ -8,11 +8,17 @@ #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" @@ -43,8 +49,6 @@ #include "DlgCtrl.h" #include "GraphicsAPI.h" #include "ConsoleManager.h" -#include -namespace fs = std::filesystem; #ifdef INLINEGRAPHICS #include "OGraphics.h" @@ -541,13 +545,18 @@ 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 fs::exists(cbufOut); + return FileExists(cbufOut); } //! Finds module consisting of a plugin DLL inside a plugin-specific folder @@ -556,7 +565,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 fs::exists(cbufOut); + return FileExists(cbufOut); } void Orbiter::LoadModules(const std::string& path, const std::list& names) @@ -565,14 +574,19 @@ void Orbiter::LoadModules(const std::string& path, const std::list& LoadModule(path.c_str(), name.c_str()); } + void Orbiter::LoadModules(const std::string& path) { - 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()); + 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); } - } + } while (!_findnext(fh, &fdata)); + _findclose(fh); } //----------------------------------------------------------------------------- diff --git a/Src/Orbiter/Planet.cpp b/Src/Orbiter/Planet.cpp index 9bc6f03b0..335b787de 100644 --- a/Src/Orbiter/Planet.cpp +++ b/Src/Orbiter/Planet.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "Orbiter.h" #include "Config.h" #include "State.h" @@ -468,6 +469,35 @@ 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; @@ -495,24 +525,25 @@ void Planet::ScanBases (char *path) trim_string (path); } - sprintf (spath, "%s/dummy", path); + intptr_t fh; + _finddata_t fdata; + sprintf (spath, "%s\\*", path); strcpy (cbuf, 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 ((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)); 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; - sprintf(spath, "%s\\%s", path, entry.path().stem().string().c_str()); - Base* base = new Base(spath, this); TRACENEW - if (!AddBase(base)) + if (_strnicmp (pc, "BASE-V2.0", 9)) continue; + Base *base = new Base (spath, this); TRACENEW + if (!AddBase (base)) delete base; - } + } while (!_findnext (fh, &fdata)); } } @@ -537,94 +568,97 @@ bool Planet::AddBase (Base *base) void Planet::ScanLabelLists (ifstream &cfg) { int i; + char cbuf[256], fname[256], lbpath[256]; int nlabellistbuf = 0; nlabellist = 0; - 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)); + _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)); + } } } + } 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); + // 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); } - 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 f6cda6b2f..7172f0f75 100644 --- a/Src/Orbiter/Planet.h +++ b/Src/Orbiter/Planet.h @@ -21,9 +21,6 @@ #include "Nav.h" #include "GraphicsAPI.h" #include "VObject.h" // temporary -#include "Orbiter.h" -#include -namespace fs = std::filesystem; #define FILETYPE_MARKER 1 @@ -184,24 +181,9 @@ class Planet: public CelestialBody { TileManager2 *SurfMgr2() const { return smgr2; } ElevationManager *ElevMgr() const { return emgr; } TileManager2 *CloudMgr2() const { return cmgr2; } - void ForEach(int type, auto&& 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); - } - } - } + + intptr_t FindFirst (int type, _finddata_t *fdata, char *path, char *fname); + intptr_t FindNext (intptr_t fh, _finddata_t *fdata, char *fname); //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 d203e102b..78ac22e57 100644 --- a/Src/Orbiter/Psys.cpp +++ b/Src/Orbiter/Psys.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "Config.h" @@ -219,101 +220,129 @@ 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]; - 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 + 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 + } } } + 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 a7d9b43ed..503f51e8d 100644 --- a/Src/Orbiter/Psys.h +++ b/Src/Orbiter/Psys.h @@ -198,14 +198,8 @@ class PlanetarySystem { void ActivatePlanetLabels(bool activate); - void ForEach(int type, auto&& callback) { - std::error_code ec; - for (const auto& entry : fs::directory_iterator(m_labelPath, ec)) { - if (entry.path().extension().string() == ".mkr") { - callback(entry); - } - } - } + intptr_t FindFirst (int type, _finddata_t *fdata, char *fname); + intptr_t FindNext (intptr_t fh, _finddata_t *fdata, char *fname); private: std::string m_Name; // system's name diff --git a/Src/Orbiter/TabModule.cpp b/Src/Orbiter/TabModule.cpp index 145c18890..a3336ad5b 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,6 +144,7 @@ void orbiter::ModuleTab::Show () } //----------------------------------------------------------------------------- + void orbiter::ModuleTab::RefreshLists () { HWND hTree = GetDlgItem (hTab, IDC_MOD_TREE); @@ -153,74 +154,72 @@ void orbiter::ModuleTab::RefreshLists () tvis.item.mask = TVIF_TEXT | TVIF_PARAM; int idx, len; - 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; + 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); } - 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 + // read category string + if (LoadString (hMod, 1001, buf, 1024)) { + strncpy (catstr, buf, 255); + } else { + strcpy (catstr, "Miscellaneous"); } + FreeLibrary (hMod); + } - 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); - } + if (!strcmp (catstr, "Graphics engines")) + continue; // graphics client modules are loaded via the Video tab - if (!strcmp(catstr, "Graphics engines")) - continue; // graphics client modules are loaded via the Video tab + // find the category entry + HTREEITEM catItem = GetCategoryItem (catstr); - // find the category entry - HTREEITEM catItem = GetCategoryItem(catstr); + // 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); - // 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); - } - } + } while (!_findnext (fh, &fdata)); + _findclose (fh); counter = 0; } diff --git a/Src/Orbiter/TabScenario.cpp b/Src/Orbiter/TabScenario.cpp index 6765b2e77..31b5beb64 100644 --- a/Src/Orbiter/TabScenario.cpp +++ b/Src/Orbiter/TabScenario.cpp @@ -6,6 +6,7 @@ //============================================================================= #include +#include #include #include #include "Orbiter.h" @@ -257,57 +258,69 @@ void orbiter::ScenarioTab::LaunchpadShowing(bool show) } //----------------------------------------------------------------------------- -void orbiter::ScenarioTab::ScanDirectory (const fs::path& path, HTREEITEM hti) +void orbiter::ScenarioTab::ScanDirectory (const char *ppath, HTREEITEM hti) { TV_INSERTSTRUCT tvis; HTREEITEM ht, hts0, ht0; - char cbuf[256]; + struct _finddata_t fdata; + intptr_t fh; + char cbuf[256], path[256], *fname; + + strcpy (path, ppath); + fname = path + strlen(path); 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 = 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); - } - } + // 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); + } hts0 = (HTREEITEM)SendDlgItemMessage (hTab, IDC_SCN_LIST, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hti); // the first subdirectory entry in this folder // scan for files - 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()); + 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'; 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); - } + (HTREEITEM)SendDlgItemMessage (hTab, IDC_SCN_LIST, TVM_INSERTITEM, 0, (LPARAM)&tvis); + } while (!_findnext (fh, &fdata)); + _findclose (fh); } } @@ -666,13 +679,15 @@ INT_PTR CALLBACK orbiter::ScenarioTab::SaveProc (HWND hWnd, UINT uMsg, WPARAM wP //----------------------------------------------------------------------------- void orbiter::ScenarioTab::ClearQSFolder() { - 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); + 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)); } } diff --git a/Src/Orbiter/TabScenario.h b/Src/Orbiter/TabScenario.h index 35415f119..e21fc6ea5 100644 --- a/Src/Orbiter/TabScenario.h +++ b/Src/Orbiter/TabScenario.h @@ -12,8 +12,6 @@ #include #include "LpadTab.h" #include "CustomControls.h" -#include -namespace fs = std::filesystem; namespace orbiter { @@ -47,7 +45,7 @@ namespace orbiter { void RefreshList(bool preserveSelection); // refresh the scenario list - void ScanDirectory(const fs::path &path, HTREEITEM hti); + void ScanDirectory(const char* path, HTREEITEM hti); // scan scenario files from a subdirectory void ScenarioChanged(); diff --git a/Src/Orbiter/TabVideo.cpp b/Src/Orbiter/TabVideo.cpp index b0e9554d9..b6e6acbd6 100644 --- a/Src/Orbiter/TabVideo.cpp +++ b/Src/Orbiter/TabVideo.cpp @@ -8,6 +8,8 @@ #define OAPI_IMPLEMENTATION #include +#include +#include #include "Orbiter.h" #include "TabVideo.h" #include "resource.h" @@ -164,27 +166,53 @@ 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, const fs::path& dir) +void orbiter::DefVideoTab::ScanDir(HWND hTab, PCSTR dir) { - 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)) + 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)) continue; } - else if (entry.path().extension().string() == ".dll") - modulepath = entry.path(); - else - continue; + else { // file found + if (!HasExtension(fdata.name, "dll")) // skip if not a DLL + continue; + sprintf(filepath, "%s\\%s", dir, fdata.name); + } // We've found a potential module DLL. Load it. - HMODULE hMod = LoadLibraryEx(modulepath.string().c_str(), 0, LOAD_LIBRARY_AS_DATAFILE); + HMODULE hMod = LoadLibraryEx(filepath, 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")) { @@ -192,7 +220,8 @@ void orbiter::DefVideoTab::ScanDir(HWND hTab, const fs::path& dir) } } } - } + } while (!_findnext(fh, &fdata)); + _findclose(fh); } //----------------------------------------------------------------------------- diff --git a/Src/Orbiter/TabVideo.h b/Src/Orbiter/TabVideo.h index ea92ca240..c107ad576 100644 --- a/Src/Orbiter/TabVideo.h +++ b/Src/Orbiter/TabVideo.h @@ -10,8 +10,6 @@ #define __TABVIDEO_H #include "LpadTab.h" -#include -namespace fs = std::filesystem; namespace orbiter { @@ -37,7 +35,7 @@ namespace orbiter { void EnumerateClients(HWND hTab); - void ScanDir(HWND hTab, const fs::path &dir); + void ScanDir(HWND hTab, PCSTR 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 865da603d..a4d6e5fdf 100644 --- a/Src/Plugin/LaunchpadExtensions/AtmConfig/AtmConfig.cpp +++ b/Src/Plugin/LaunchpadExtensions/AtmConfig/AtmConfig.cpp @@ -6,14 +6,13 @@ #include "orbitersdk.h" #include "resource.h" -#include -namespace fs = std::filesystem; +#include using namespace std; class AtmConfig; -const fs::path CelbodyDir = fs::path("Modules") / "Celbody"; +const char *CelbodyDir = "Modules\\Celbody"; const char *ModuleItem = "MODULE_ATM"; struct { @@ -215,49 +214,65 @@ void AtmConfig::ScanCelbodies (HWND hWnd) { SendDlgItemMessage (hWnd, IDC_COMBO2, CB_RESETCONTENT, 0, 0); - 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()); + 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); } - } + res = _findnext (id, &info); + } while (!res); } + _findclose (id); } void AtmConfig::ScanModules (const char *celbody) { ClearModules (); - 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; + 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; if (module_last) module_last->next = ms; else module_first = ms; module_last = ms; - strncpy(ms->module_name, name.c_str(), 255); - strncpy(ms->model_name, name.c_str(), 255); + strncpy (ms->module_name, info.name, 255); + strncpy (ms->model_name, info.name, 255); ms->model_desc[0] = '\0'; ms->next = 0; // get info from the module - HINSTANCE hModule = LoadLibrary(module.string().c_str()); + HINSTANCE hModule = LoadLibrary (path); 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 cc650e445..74a7f6bd3 100644 --- a/Src/Plugin/ScnEditor/Editor.cpp +++ b/Src/Plugin/ScnEditor/Editor.cpp @@ -17,6 +17,7 @@ #include "DlgCtrl.h" #include #include +#include using std::min; using std::max; @@ -721,75 +722,87 @@ bool EditorTab_New::CreateVessel () return true; } -void EditorTab_New::ScanConfigDir (const fs::path& dir, HTREEITEM hti) +void EditorTab_New::ScanConfigDir (const char *ppath, HTREEITEM hti) { // recursively scans a directory tree and adds to the list TV_INSERTSTRUCT tvis; HTREEITEM ht, hts0, ht0; - char cbuf[256]; + struct _finddata_t fdata; + intptr_t fh; + char cbuf[256], path[256], *fname; + + strcpy (path, ppath); + fname = path + strlen(path); 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 - 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); - } + 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); } - hts0 = (HTREEITEM)SendDlgItemMessage (hTab, IDC_VESSELTP, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hti); // the first subdirectory entry in this folder // scan for files - 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") { + 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 { bool skip = false; - FILEHANDLE hFile = oapiOpenFile(entry.path().string().c_str(), FILE_IN); + strcpy (fname, fdata.name); + FILEHANDLE hFile = oapiOpenFile (path, 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, entry.path().stem().string().c_str()); + strcpy (cbuf, fdata.name); + cbuf[strlen(cbuf)-4] = '\0'; 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); - } + (HTREEITEM)SendDlgItemMessage (hTab, IDC_VESSELTP, TVM_INSERTITEM, 0, (LPARAM)&tvis); + } while (!_findnext (fh, &fdata)); + _findclose (fh); } } 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 82234e1d3..7e6d2b842 100644 --- a/Src/Plugin/ScnEditor/Editor.h +++ b/Src/Plugin/ScnEditor/Editor.h @@ -17,8 +17,6 @@ #include "ScnEditorAPI.h" #include "Convert.h" #include -#include -namespace fs = std::filesystem; class ScnEditorTab; typedef void (*CustomButtonFunc)(OBJHANDLE); @@ -137,7 +135,7 @@ class EditorTab_New: public ScnEditorTab { static INT_PTR CALLBACK DlgProc (HWND, UINT, WPARAM, LPARAM); protected: - void ScanConfigDir (const fs::path &dir, HTREEITEM hti); + void ScanConfigDir (const char *ppath, HTREEITEM hti); void RefreshVesselTpList (); int GetSelVesselTp (char *name, int len); void VesselTpChanged ();