diff --git a/src/LScreens.c b/src/LScreens.c index 4da3bc693..2c41cf0f7 100644 --- a/src/LScreens.c +++ b/src/LScreens.c @@ -1005,10 +1005,8 @@ static struct CheckResourcesScreen { static void CheckResourcesScreen_Yes(void* w, int idx) { FetchResourcesScreen_SetActive(); } static void CheckResourcesScreen_Next(void* w, int idx) { - static const cc_string optionsTxt = String_FromConst("options.txt"); Http_ClearPending(); - - if (File_Exists(&optionsTxt)) { + if (Options_LoadResult != ReturnCode_FileNotFound) { MainScreen_SetActive(); } else { ChooseModeScreen_SetActive(true); diff --git a/src/Options.c b/src/Options.c index a7cf3ac26..20b011e43 100644 --- a/src/Options.c +++ b/src/Options.c @@ -9,6 +9,7 @@ struct StringsBuffer Options; static struct StringsBuffer changedOpts; +cc_result Options_LoadResult; void Options_Free(void) { StringsBuffer_Clear(&Options); @@ -35,8 +36,8 @@ static cc_bool Options_LoadFilter(const cc_string* entry) { void Options_Load(void) { /* Increase from max 512 to 2048 per entry */ StringsBuffer_SetLengthBits(&Options, 11); - EntryList_Load(&Options, "options-default.txt", '=', NULL); - EntryList_Load(&Options, "options.txt", '=', NULL); + Options_LoadResult = EntryList_Load(&Options, "options-default.txt", '=', NULL); + Options_LoadResult = EntryList_Load(&Options, "options.txt", '=', NULL); } void Options_Reload(void) { @@ -52,7 +53,7 @@ void Options_Reload(void) { StringsBuffer_Remove(&Options, i); } /* Load only options which have not changed */ - EntryList_Load(&Options, "options.txt", '=', Options_LoadFilter); + Options_LoadResult = EntryList_Load(&Options, "options.txt", '=', Options_LoadFilter); } static void SaveOptions(void) { diff --git a/src/Options.h b/src/Options.h index b99750c28..f7726dcaa 100644 --- a/src/Options.h +++ b/src/Options.h @@ -87,6 +87,7 @@ struct StringsBuffer; extern struct StringsBuffer Options; +extern cc_result Options_LoadResult; /* Frees any memory allocated in storing options. */ void Options_Free(void); diff --git a/src/Platform.c b/src/Platform.c index d423c6c88..01f09e09d 100644 --- a/src/Platform.c +++ b/src/Platform.c @@ -357,48 +357,68 @@ int File_Exists(const cc_string* path) { return attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY); } +static cc_result Directory_EnumCore(const cc_string* dirPath, const cc_string* file, DWORD attribs, + void* obj, Directory_EnumCallback callback) { + cc_string path; char pathBuffer[MAX_PATH + 10]; + /* ignore . and .. entry */ + if (file->length == 1 && file->buffer[0] == '.') return 0; + if (file->length == 2 && file->buffer[0] == '.' && file->buffer[1] == '.') return 0; + + String_InitArray(path, pathBuffer); + String_Format2(&path, "%s/%s", dirPath, file); + + if (attribs & FILE_ATTRIBUTE_DIRECTORY) return Directory_Enum(&path, obj, callback); + callback(&path, obj); + return 0; +} + cc_result Directory_Enum(const cc_string* dirPath, void* obj, Directory_EnumCallback callback) { cc_string path; char pathBuffer[MAX_PATH + 10]; WCHAR str[NATIVE_STR_LEN]; - WCHAR* src; - WIN32_FIND_DATAW entry; + WIN32_FIND_DATAW eW; + WIN32_FIND_DATAA eA; + int i, ansi = false; HANDLE find; cc_result res; - int i; /* Need to append \* to search for files in directory */ String_InitArray(path, pathBuffer); String_Format1(&path, "%s\\*", dirPath); Platform_EncodeUtf16(str, &path); - find = FindFirstFileW(str, &entry); - if (find == INVALID_HANDLE_VALUE) return GetLastError(); + find = FindFirstFileW(str, &eW); + if (!find || find == INVALID_HANDLE_VALUE) { + if ((res = GetLastError()) != ERROR_CALL_NOT_IMPLEMENTED) return res; + ansi = true; - do { - path.length = 0; - String_Format1(&path, "%s/", dirPath); + /* Windows 9x does not support W API functions */ + Platform_Utf16ToAnsi(str); + find = FindFirstFileA((LPCSTR)str, &eA); + if (find == INVALID_HANDLE_VALUE) return GetLastError(); + } - /* ignore . and .. entry */ - src = entry.cFileName; - if (src[0] == '.' && src[1] == '\0') continue; - if (src[0] == '.' && src[1] == '.' && src[2] == '\0') continue; - - for (i = 0; i < MAX_PATH && src[i]; i++) { - /* TODO: UTF16 to codepoint conversion */ - String_Append(&path, Convert_CodepointToCP437(src[i])); - } - - if (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - res = Directory_Enum(&path, obj, callback); - if (res) { FindClose(find); return res; } - } else { - callback(&path, obj); - } - } while (FindNextFileW(find, &entry)); + if (ansi) { + do { + path.length = 0; + for (i = 0; i < MAX_PATH && eA.cFileName[i]; i++) { + String_Append(&path, Convert_CodepointToCP437(eA.cFileName[i])); + } + if ((res = Directory_EnumCore(dirPath, &path, eA.dwFileAttributes, obj, callback))) return res; + } while (FindNextFileA(find, &eA)); + } else { + do { + path.length = 0; + for (i = 0; i < MAX_PATH && eW.cFileName[i]; i++) { + /* TODO: UTF16 to codepoint conversion */ + String_Append(&path, Convert_CodepointToCP437(eW.cFileName[i])); + } + if ((res = Directory_EnumCore(dirPath, &path, eW.dwFileAttributes, obj, callback))) return res; + } while (FindNextFileW(find, &eW)); + } res = GetLastError(); /* return code from FindNextFile */ FindClose(find); - return res == ERROR_NO_MORE_FILES ? 0 : GetLastError(); + return res == ERROR_NO_MORE_FILES ? 0 : res; } static cc_result DoFile(cc_file* file, const cc_string* path, DWORD access, DWORD createMode) { @@ -1565,7 +1585,7 @@ void Platform_Utf16ToAnsi(void* data) { WCHAR* src = (WCHAR*)data; char* dst = (char*)data; - while (*src) { *dst++ = *src++; } + while (*src) { *dst++ = (char)(*src++); } *dst = '\0'; } diff --git a/src/Utils.c b/src/Utils.c index 2cd71f674..aa70e2980 100644 --- a/src/Utils.c +++ b/src/Utils.c @@ -222,7 +222,7 @@ int Convert_FromBase64(const char* src, int len, cc_uint8* dst) { /*########################################################################################################################* *--------------------------------------------------------EntryList--------------------------------------------------------* *#########################################################################################################################*/ -void EntryList_Load(struct StringsBuffer* list, const char* file, char separator, EntryList_Filter filter) { +cc_result EntryList_Load(struct StringsBuffer* list, const char* file, char separator, EntryList_Filter filter) { cc_string entry; char entryBuffer[1024]; cc_string path; cc_string key, value; @@ -236,8 +236,8 @@ void EntryList_Load(struct StringsBuffer* list, const char* file, char separator maxLen = list->_lenMask ? list->_lenMask : STRINGSBUFFER_DEF_LEN_MASK; res = Stream_OpenFile(&stream, &path); - if (res == ReturnCode_FileNotFound) return; - if (res) { Logger_SysWarn2(res, "opening", &path); return; } + if (res == ReturnCode_FileNotFound) return res; + if (res) { Logger_SysWarn2(res, "opening", &path); return res; } /* ReadLine reads single byte at a time */ Stream_ReadonlyBuffered(&buffered, &stream, buffer, sizeof(buffer)); @@ -274,10 +274,11 @@ void EntryList_Load(struct StringsBuffer* list, const char* file, char separator res = stream.Close(&stream); if (res) { Logger_SysWarn2(res, "closing", &path); } + return res; } -void EntryList_UNSAFE_Load(struct StringsBuffer* list, const char* file) { - EntryList_Load(list, file, '\0', NULL); +cc_result EntryList_UNSAFE_Load(struct StringsBuffer* list, const char* file) { + return EntryList_Load(list, file, '\0', NULL); } void EntryList_Save(struct StringsBuffer* list, const char* file) { diff --git a/src/Utils.h b/src/Utils.h index b76f96df6..5b6aef562 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -59,10 +59,10 @@ typedef cc_bool (*EntryList_Filter)(const cc_string* entry); /* Loads the entries from disc. */ /* NOTE: If separator is \0, does NOT check for duplicate keys when loading. */ /* filter can be used to optionally skip loading some entries from the file. */ -CC_NOINLINE void EntryList_Load(struct StringsBuffer* list, const char* file, char separator, EntryList_Filter filter); +CC_NOINLINE cc_result EntryList_Load(struct StringsBuffer* list, const char* file, char separator, EntryList_Filter filter); /* Shortcut for EntryList_Load with separator of \0 and filter of NULL */ /* NOTE: Does NOT check for duplicate keys */ -CC_NOINLINE void EntryList_UNSAFE_Load(struct StringsBuffer* list, const char* file); +CC_NOINLINE cc_result EntryList_UNSAFE_Load(struct StringsBuffer* list, const char* file); /* Saves the entries in the given list to disc. */ CC_NOINLINE void EntryList_Save(struct StringsBuffer* list, const char* file); /* Removes the entry whose key caselessly equals the given key. */