1
0
Fork 0

Fix #8713: Change OTTD2FS and FS2OTTD to return string objects instead of static buffers

pull/8964/head
Niels Martin Hansen 2021-02-21 17:03:19 +01:00
parent 825867f2c5
commit e0561dbded
17 changed files with 109 additions and 100 deletions

View File

@ -134,7 +134,7 @@ static void debug_print(const char *dbg, const char *buf)
#if defined(_WIN32) #if defined(_WIN32)
wchar_t system_buf[512]; wchar_t system_buf[512];
convert_to_fs(buffer, system_buf, lengthof(system_buf), true); convert_to_fs(buffer, system_buf, lengthof(system_buf), true);
_fputts(system_buf, stderr); fputws(system_buf, stderr);
#else #else
fputs(buffer, stderr); fputs(buffer, stderr);
#endif #endif

View File

@ -279,7 +279,7 @@ bool FioCheckFileExists(const std::string &filename, Subdirectory subdir)
*/ */
bool FileExists(const std::string &filename) bool FileExists(const std::string &filename)
{ {
return access(OTTD2FS(filename.c_str()), 0) == 0; return access(OTTD2FS(filename).c_str(), 0) == 0;
} }
/** /**
@ -358,7 +358,7 @@ static FILE *FioFOpenFileSp(const std::string &filename, const char *mode, Searc
} }
#if defined(_WIN32) #if defined(_WIN32)
if (mode[0] == 'r' && GetFileAttributes(OTTD2FS(buf.c_str())) == INVALID_FILE_ATTRIBUTES) return nullptr; if (mode[0] == 'r' && GetFileAttributes(OTTD2FS(buf).c_str()) == INVALID_FILE_ATTRIBUTES) return nullptr;
#endif #endif
f = fopen(buf.c_str(), mode); f = fopen(buf.c_str(), mode);
@ -506,11 +506,11 @@ void FioCreateDirectory(const std::string &name)
/* Ignore directory creation errors; they'll surface later on, and most /* Ignore directory creation errors; they'll surface later on, and most
* of the time they are 'directory already exists' errors anyhow. */ * of the time they are 'directory already exists' errors anyhow. */
#if defined(_WIN32) #if defined(_WIN32)
CreateDirectory(OTTD2FS(name.c_str()), nullptr); CreateDirectory(OTTD2FS(name).c_str(), nullptr);
#elif defined(OS2) && !defined(__INNOTEK_LIBC__) #elif defined(OS2) && !defined(__INNOTEK_LIBC__)
mkdir(OTTD2FS(name.c_str())); mkdir(OTTD2FS(name).c_str());
#else #else
mkdir(OTTD2FS(name.c_str()), 0755); mkdir(OTTD2FS(name).c_str(), 0755);
#endif #endif
} }
@ -1315,7 +1315,7 @@ static uint ScanPath(FileScanner *fs, const char *extension, const char *path, s
if (path == nullptr || (dir = ttd_opendir(path)) == nullptr) return 0; if (path == nullptr || (dir = ttd_opendir(path)) == nullptr) return 0;
while ((dirent = readdir(dir)) != nullptr) { while ((dirent = readdir(dir)) != nullptr) {
const char *d_name = FS2OTTD(dirent->d_name); std::string d_name = FS2OTTD(dirent->d_name);
if (!FiosIsValidFile(path, dirent, &sb)) continue; if (!FiosIsValidFile(path, dirent, &sb)) continue;
@ -1325,7 +1325,7 @@ static uint ScanPath(FileScanner *fs, const char *extension, const char *path, s
if (S_ISDIR(sb.st_mode)) { if (S_ISDIR(sb.st_mode)) {
/* Directory */ /* Directory */
if (!recursive) continue; if (!recursive) continue;
if (strcmp(d_name, ".") == 0 || strcmp(d_name, "..") == 0) continue; if (d_name == "." || d_name == "..") continue;
AppendPathSeparator(filename); AppendPathSeparator(filename);
num += ScanPath(fs, extension, filename.c_str(), basepath_length, recursive); num += ScanPath(fs, extension, filename.c_str(), basepath_length, recursive);
} else if (S_ISREG(sb.st_mode)) { } else if (S_ISREG(sb.st_mode)) {

View File

@ -132,7 +132,7 @@ int closedir(DIR *d);
*/ */
static inline DIR *ttd_opendir(const char *path) static inline DIR *ttd_opendir(const char *path)
{ {
return opendir(OTTD2FS(path)); return opendir(OTTD2FS(path).c_str());
} }

View File

@ -309,7 +309,7 @@ bool FiosFileScanner::AddFile(const std::string &filename, size_t basepath_lengt
FiosItem *fios = file_list.Append(); FiosItem *fios = file_list.Append();
#ifdef _WIN32 #ifdef _WIN32
// Retrieve the file modified date using GetFileTime rather than stat to work around an obscure MSVC bug that affects Windows XP // Retrieve the file modified date using GetFileTime rather than stat to work around an obscure MSVC bug that affects Windows XP
HANDLE fh = CreateFile(OTTD2FS(filename.c_str()), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr); HANDLE fh = CreateFile(OTTD2FS(filename).c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
if (fh != INVALID_HANDLE_VALUE) { if (fh != INVALID_HANDLE_VALUE) {
FILETIME ft; FILETIME ft;
@ -384,7 +384,7 @@ static void FiosGetFileList(SaveLoadOperation fop, fios_getlist_callback_proc *c
/* Show subdirectories */ /* Show subdirectories */
if ((dir = ttd_opendir(_fios_path->c_str())) != nullptr) { if ((dir = ttd_opendir(_fios_path->c_str())) != nullptr) {
while ((dirent = readdir(dir)) != nullptr) { while ((dirent = readdir(dir)) != nullptr) {
strecpy(d_name, FS2OTTD(dirent->d_name), lastof(d_name)); strecpy(d_name, FS2OTTD(dirent->d_name).c_str(), lastof(d_name));
/* found file must be directory, but not '.' or '..' */ /* found file must be directory, but not '.' or '..' */
if (FiosIsValidFile(_fios_path->c_str(), dirent, &sb) && S_ISDIR(sb.st_mode) && if (FiosIsValidFile(_fios_path->c_str(), dirent, &sb) && S_ISDIR(sb.st_mode) &&

View File

@ -53,7 +53,7 @@ bool IniFile::SaveToDisk(const std::string &filename)
std::string file_new{ filename }; std::string file_new{ filename };
file_new.append(".new"); file_new.append(".new");
std::ofstream os(OTTD2FS(file_new.c_str())); std::ofstream os(OTTD2FS(file_new));
if (os.fail()) return false; if (os.fail()) return false;
for (const IniGroup *group = this->group; group != nullptr; group = group->next) { for (const IniGroup *group = this->group; group != nullptr; group = group->next) {
@ -94,8 +94,8 @@ bool IniFile::SaveToDisk(const std::string &filename)
#if defined(_WIN32) #if defined(_WIN32)
/* Allocate space for one more \0 character. */ /* Allocate space for one more \0 character. */
wchar_t tfilename[MAX_PATH + 1], tfile_new[MAX_PATH + 1]; wchar_t tfilename[MAX_PATH + 1], tfile_new[MAX_PATH + 1];
wcsncpy(tfilename, OTTD2FS(filename.c_str()), MAX_PATH); wcsncpy(tfilename, OTTD2FS(filename).c_str(), MAX_PATH);
wcsncpy(tfile_new, OTTD2FS(file_new.c_str()), MAX_PATH); wcsncpy(tfile_new, OTTD2FS(file_new).c_str(), MAX_PATH);
/* SHFileOperation wants a double '\0' terminated string. */ /* SHFileOperation wants a double '\0' terminated string. */
tfilename[MAX_PATH - 1] = '\0'; tfilename[MAX_PATH - 1] = '\0';
tfile_new[MAX_PATH - 1] = '\0'; tfile_new[MAX_PATH - 1] = '\0';

View File

@ -134,8 +134,8 @@ void MusicDriver_Cocoa::PlaySong(const MusicSongInfo &song)
return; return;
} }
const char *os_file = OTTD2FS(filename.c_str()); std::string os_file = OTTD2FS(filename);
CFAutoRelease<CFURLRef> url(CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8*)os_file, strlen(os_file), false)); CFAutoRelease<CFURLRef> url(CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8*)os_file.c_str(), os_file.length(), false));
if (MusicSequenceFileLoad(_sequence, url.get(), kMusicSequenceFile_AnyType, 0) != noErr) { if (MusicSequenceFileLoad(_sequence, url.get(), kMusicSequenceFile_AnyType, 0) != noErr) {
DEBUG(driver, 0, "cocoa_m: Failed to load MIDI file"); DEBUG(driver, 0, "cocoa_m: Failed to load MIDI file");

View File

@ -430,7 +430,7 @@ bool DLSFile::ReadDLSWaveList(FILE *f, DWORD list_length)
bool DLSFile::LoadFile(const wchar_t *file) bool DLSFile::LoadFile(const wchar_t *file)
{ {
DEBUG(driver, 2, "DMusic: Try to load DLS file %s", FS2OTTD(file)); DEBUG(driver, 2, "DMusic: Try to load DLS file %s", FS2OTTD(file).c_str());
FILE *f = _wfopen(file, L"rb"); FILE *f = _wfopen(file, L"rb");
if (f == nullptr) return false; if (f == nullptr) return false;
@ -881,7 +881,7 @@ static const char *LoadDefaultDLSFile(const char *user_dls)
if (!dls_file.LoadFile(path)) return "Can't load GM DLS collection"; if (!dls_file.LoadFile(path)) return "Can't load GM DLS collection";
} }
} else { } else {
if (!dls_file.LoadFile(OTTD2FS(user_dls))) return "Can't load GM DLS collection"; if (!dls_file.LoadFile(OTTD2FS(user_dls).c_str())) return "Can't load GM DLS collection";
} }
/* Get download port and allocate download IDs. */ /* Get download port and allocate download IDs. */

View File

@ -246,7 +246,7 @@ SOCKET NetworkAddress::Resolve(int family, int socktype, int flags, SocketList *
if (e != 0) { if (e != 0) {
if (func != ResolveLoopProc) { if (func != ResolveLoopProc) {
DEBUG(net, 0, "getaddrinfo for hostname \"%s\", port %s, address family %s and socket type %s failed: %s", DEBUG(net, 0, "getaddrinfo for hostname \"%s\", port %s, address family %s and socket type %s failed: %s",
this->hostname, port_name, AddressFamilyAsString(family), SocketTypeAsString(socktype), FS2OTTD(gai_strerror(e))); this->hostname, port_name, AddressFamilyAsString(family), SocketTypeAsString(socktype), FS2OTTD(gai_strerror(e)).c_str());
} }
return INVALID_SOCKET; return INVALID_SOCKET;
} }

View File

@ -203,9 +203,6 @@ bool GetClipboardContents(char *buffer, const char *last)
} }
const char *FS2OTTD(const char *name) {return name;}
const char *OTTD2FS(const char *name) {return name;}
void OSOpenBrowser(const char *url) void OSOpenBrowser(const char *url)
{ {
// stub only // stub only

View File

@ -146,9 +146,8 @@ static const char *GetLocalCode()
* Convert between locales, which from and which to is set in the calling * Convert between locales, which from and which to is set in the calling
* functions OTTD2FS() and FS2OTTD(). * functions OTTD2FS() and FS2OTTD().
*/ */
static const char *convert_tofrom_fs(iconv_t convd, const char *name) static const char *convert_tofrom_fs(iconv_t convd, const char *name, char *outbuf, size_t outlen)
{ {
static char buf[1024];
/* There are different implementations of iconv. The older ones, /* There are different implementations of iconv. The older ones,
* e.g. SUSv2, pass a const pointer, whereas the newer ones, e.g. * e.g. SUSv2, pass a const pointer, whereas the newer ones, e.g.
* IEEE 1003.1 (2004), pass a non-const pointer. */ * IEEE 1003.1 (2004), pass a non-const pointer. */
@ -158,9 +157,8 @@ static const char *convert_tofrom_fs(iconv_t convd, const char *name)
const char *inbuf = name; const char *inbuf = name;
#endif #endif
char *outbuf = buf;
size_t outlen = sizeof(buf) - 1;
size_t inlen = strlen(name); size_t inlen = strlen(name);
char *buf = outbuf;
strecpy(outbuf, name, outbuf + outlen); strecpy(outbuf, name, outbuf + outlen);
@ -179,9 +177,10 @@ static const char *convert_tofrom_fs(iconv_t convd, const char *name)
* @param name pointer to a valid string that will be converted * @param name pointer to a valid string that will be converted
* @return pointer to a new stringbuffer that contains the converted string * @return pointer to a new stringbuffer that contains the converted string
*/ */
const char *OTTD2FS(const char *name) std::string OTTD2FS(const std::string &name)
{ {
static iconv_t convd = (iconv_t)(-1); static iconv_t convd = (iconv_t)(-1);
char buf[1024] = {};
if (convd == (iconv_t)(-1)) { if (convd == (iconv_t)(-1)) {
const char *env = GetLocalCode(); const char *env = GetLocalCode();
@ -192,17 +191,18 @@ const char *OTTD2FS(const char *name)
} }
} }
return convert_tofrom_fs(convd, name); return convert_tofrom_fs(convd, name.c_str(), buf, lengthof(buf));
} }
/** /**
* Convert to OpenTTD's encoding from that of the local environment * Convert to OpenTTD's encoding from that of the local environment
* @param name pointer to a valid string that will be converted * @param name valid string that will be converted
* @return pointer to a new stringbuffer that contains the converted string * @return pointer to a new stringbuffer that contains the converted string
*/ */
const char *FS2OTTD(const char *name) std::string FS2OTTD(const std::string &name)
{ {
static iconv_t convd = (iconv_t)(-1); static iconv_t convd = (iconv_t)(-1);
char buf[1024] = {};
if (convd == (iconv_t)(-1)) { if (convd == (iconv_t)(-1)) {
const char *env = GetLocalCode(); const char *env = GetLocalCode();
@ -213,12 +213,9 @@ const char *FS2OTTD(const char *name)
} }
} }
return convert_tofrom_fs(convd, name); return convert_tofrom_fs(convd, name.c_str(), buf, lengthof(buf));
} }
#else
const char *FS2OTTD(const char *name) {return name;}
const char *OTTD2FS(const char *name) {return name;}
#endif /* WITH_ICONV */ #endif /* WITH_ICONV */
void ShowInfo(const char *str) void ShowInfo(const char *str)

View File

@ -189,7 +189,7 @@ static char *PrintModuleInfo(char *output, const char *last, HMODULE mod)
GetModuleFileName(mod, buffer, MAX_PATH); GetModuleFileName(mod, buffer, MAX_PATH);
GetFileInfo(&dfi, buffer); GetFileInfo(&dfi, buffer);
output += seprintf(output, last, " %-20s handle: %p size: %d crc: %.8X date: %d-%.2d-%.2d %.2d:%.2d:%.2d\n", output += seprintf(output, last, " %-20s handle: %p size: %d crc: %.8X date: %d-%.2d-%.2d %.2d:%.2d:%.2d\n",
FS2OTTD(buffer), FS2OTTD(buffer).c_str(),
mod, mod,
dfi.size, dfi.size,
dfi.crc32, dfi.crc32,
@ -501,7 +501,7 @@ char *CrashLogWindows::AppendDecodedStacktrace(char *buffer, const char *last) c
MiniDumpWriteDump_t funcMiniDumpWriteDump = (MiniDumpWriteDump_t)GetProcAddress(dbghelp, "MiniDumpWriteDump"); MiniDumpWriteDump_t funcMiniDumpWriteDump = (MiniDumpWriteDump_t)GetProcAddress(dbghelp, "MiniDumpWriteDump");
if (funcMiniDumpWriteDump != nullptr) { if (funcMiniDumpWriteDump != nullptr) {
seprintf(filename, filename_last, "%scrash.dmp", _personal_dir.c_str()); seprintf(filename, filename_last, "%scrash.dmp", _personal_dir.c_str());
HANDLE file = CreateFile(OTTD2FS(filename), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, 0); HANDLE file = CreateFile(OTTD2FS(filename).c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, 0);
HANDLE proc = GetCurrentProcess(); HANDLE proc = GetCurrentProcess();
DWORD procid = GetCurrentProcessId(); DWORD procid = GetCurrentProcessId();
MINIDUMP_EXCEPTION_INFORMATION mdei; MINIDUMP_EXCEPTION_INFORMATION mdei;
@ -689,7 +689,8 @@ static INT_PTR CALLBACK CrashDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARA
switch (msg) { switch (msg) {
case WM_INITDIALOG: { case WM_INITDIALOG: {
/* We need to put the crash-log in a separate buffer because the default /* We need to put the crash-log in a separate buffer because the default
* buffer in OTTD2FS is not large enough (512 chars) */ * buffer in MB_TO_WIDE is not large enough (512 chars) */
wchar_t filenamebuf[MAX_PATH * 2];
wchar_t crash_msgW[lengthof(CrashLogWindows::current->crashlog)]; wchar_t crash_msgW[lengthof(CrashLogWindows::current->crashlog)];
/* Convert unix -> dos newlines because the edit box only supports that properly :( */ /* Convert unix -> dos newlines because the edit box only supports that properly :( */
const char *unix_nl = CrashLogWindows::current->crashlog; const char *unix_nl = CrashLogWindows::current->crashlog;
@ -704,19 +705,23 @@ static INT_PTR CALLBACK CrashDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARA
/* Add path to crash.log and crash.dmp (if any) to the crash window text */ /* Add path to crash.log and crash.dmp (if any) to the crash window text */
size_t len = wcslen(_crash_desc) + 2; size_t len = wcslen(_crash_desc) + 2;
len += wcslen(OTTD2FS(CrashLogWindows::current->crashlog_filename)) + 2; len += wcslen(convert_to_fs(CrashLogWindows::current->crashlog_filename, filenamebuf, lengthof(filenamebuf), false)) + 2;
len += wcslen(OTTD2FS(CrashLogWindows::current->crashdump_filename)) + 2; len += wcslen(convert_to_fs(CrashLogWindows::current->crashdump_filename, filenamebuf, lengthof(filenamebuf), false)) + 2;
len += wcslen(OTTD2FS(CrashLogWindows::current->screenshot_filename)) + 1; len += wcslen(convert_to_fs(CrashLogWindows::current->screenshot_filename, filenamebuf, lengthof(filenamebuf), false)) + 1;
wchar_t *text = AllocaM(wchar_t, len); wchar_t *text = AllocaM(wchar_t, len);
_snwprintf(text, len, _crash_desc, OTTD2FS(CrashLogWindows::current->crashlog_filename)); int printed = _snwprintf(text, len, _crash_desc, convert_to_fs(CrashLogWindows::current->crashlog_filename, filenamebuf, lengthof(filenamebuf), false));
if (OTTD2FS(CrashLogWindows::current->crashdump_filename)[0] != L'\0') { if (printed < 0 || (size_t)printed > len) {
wcscat(text, L"\n"); MessageBox(wnd, L"Catastrophic failure trying to display crash message. Could not perform text formatting.", L"OpenTTD", MB_ICONERROR);
wcscat(text, OTTD2FS(CrashLogWindows::current->crashdump_filename)); return FALSE;
} }
if (OTTD2FS(CrashLogWindows::current->screenshot_filename)[0] != L'\0') { if (convert_to_fs(CrashLogWindows::current->crashdump_filename, filenamebuf, lengthof(filenamebuf), false)[0] != L'\0') {
wcscat(text, L"\n"); wcscat(text, L"\n");
wcscat(text, OTTD2FS(CrashLogWindows::current->screenshot_filename)); wcscat(text, filenamebuf);
}
if (convert_to_fs(CrashLogWindows::current->screenshot_filename, filenamebuf, lengthof(filenamebuf), false)[0] != L'\0') {
wcscat(text, L"\n");
wcscat(text, filenamebuf);
} }
SetDlgItemText(wnd, 10, text); SetDlgItemText(wnd, 10, text);
@ -730,18 +735,20 @@ static INT_PTR CALLBACK CrashDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARA
CrashLog::AfterCrashLogCleanup(); CrashLog::AfterCrashLogCleanup();
ExitProcess(2); ExitProcess(2);
case 13: // Emergency save case 13: // Emergency save
wchar_t filenamebuf[MAX_PATH * 2];
char filename[MAX_PATH]; char filename[MAX_PATH];
if (CrashLogWindows::current->WriteSavegame(filename, lastof(filename))) { if (CrashLogWindows::current->WriteSavegame(filename, lastof(filename))) {
size_t len = wcslen(_save_succeeded) + wcslen(OTTD2FS(filename)) + 1; convert_to_fs(filename, filenamebuf, lengthof(filenamebuf), false);
size_t len = lengthof(_save_succeeded) + wcslen(filenamebuf) + 1;
wchar_t *text = AllocaM(wchar_t, len); wchar_t *text = AllocaM(wchar_t, len);
_snwprintf(text, len, _save_succeeded, OTTD2FS(filename)); _snwprintf(text, len, _save_succeeded, filenamebuf);
MessageBox(wnd, text, L"Save successful", MB_ICONINFORMATION); MessageBox(wnd, text, L"Save successful", MB_ICONINFORMATION);
} else { } else {
MessageBox(wnd, L"Save failed", L"Save failed", MB_ICONINFORMATION); MessageBox(wnd, L"Save failed", L"Save failed", MB_ICONINFORMATION);
} }
break; break;
case 15: // Expand window to show crash-message case 15: // Expand window to show crash-message
_expanded ^= 1; _expanded = !_expanded;
SetWndSize(wnd, _expanded); SetWndSize(wnd, _expanded);
break; break;
} }

View File

@ -83,7 +83,7 @@ FT_Error GetFontByFaceName(const char *font_name, FT_Face *face)
} }
/* Convert font name to file system encoding. */ /* Convert font name to file system encoding. */
wchar_t *font_namep = wcsdup(OTTD2FS(font_name)); wchar_t *font_namep = wcsdup(OTTD2FS(font_name).c_str());
for (index = 0;; index++) { for (index = 0;; index++) {
wchar_t *s; wchar_t *s;
@ -377,6 +377,7 @@ Win32FontCache::Win32FontCache(FontSize fs, const LOGFONT &logfont, int pixels)
{ {
this->dc = CreateCompatibleDC(nullptr); this->dc = CreateCompatibleDC(nullptr);
this->SetFontSize(fs, pixels); this->SetFontSize(fs, pixels);
this->fontname = FS2OTTD(this->logfont.lfFaceName);
} }
Win32FontCache::~Win32FontCache() Win32FontCache::~Win32FontCache()
@ -438,7 +439,7 @@ void Win32FontCache::SetFontSize(FontSize fs, int pixels)
this->glyph_size.cx = otm->otmTextMetrics.tmMaxCharWidth; this->glyph_size.cx = otm->otmTextMetrics.tmMaxCharWidth;
this->glyph_size.cy = otm->otmTextMetrics.tmHeight; this->glyph_size.cy = otm->otmTextMetrics.tmHeight;
DEBUG(freetype, 2, "Loaded font '%s' with size %d", FS2OTTD((LPTSTR)((BYTE *)otm + (ptrdiff_t)otm->otmpFullName)), pixels); DEBUG(freetype, 2, "Loaded font '%s' with size %d", FS2OTTD((LPWSTR)((BYTE *)otm + (ptrdiff_t)otm->otmpFullName)).c_str(), pixels);
} }
/** /**
@ -541,10 +542,10 @@ void Win32FontCache::ClearFontCache()
/* Convert characters outside of the BMP into surrogate pairs. */ /* Convert characters outside of the BMP into surrogate pairs. */
WCHAR chars[2]; WCHAR chars[2];
if (key >= 0x010000U) { if (key >= 0x010000U) {
chars[0] = (WCHAR)(((key - 0x010000U) >> 10) + 0xD800); chars[0] = (wchar_t)(((key - 0x010000U) >> 10) + 0xD800);
chars[1] = (WCHAR)(((key - 0x010000U) & 0x3FF) + 0xDC00); chars[1] = (wchar_t)(((key - 0x010000U) & 0x3FF) + 0xDC00);
} else { } else {
chars[0] = (WCHAR)(key & 0xFFFF); chars[0] = (wchar_t)(key & 0xFFFF);
} }
WORD glyphs[2] = { 0, 0 }; WORD glyphs[2] = { 0, 0 };

View File

@ -21,6 +21,7 @@ private:
HDC dc = nullptr; ///< Cached GDI device context. HDC dc = nullptr; ///< Cached GDI device context.
HGDIOBJ old_font; ///< Old font selected into the GDI context. HGDIOBJ old_font; ///< Old font selected into the GDI context.
SIZE glyph_size; ///< Maximum size of regular glyphs. SIZE glyph_size; ///< Maximum size of regular glyphs.
std::string fontname; ///< Cached copy of this->logfont.lfFaceName
void SetFontSize(FontSize fs, int pixels); void SetFontSize(FontSize fs, int pixels);
@ -33,7 +34,7 @@ public:
~Win32FontCache(); ~Win32FontCache();
void ClearFontCache() override; void ClearFontCache() override;
GlyphID MapCharToGlyph(WChar key) override; GlyphID MapCharToGlyph(WChar key) override;
const char *GetFontName() override { return FS2OTTD(this->logfont.lfFaceName); } const char *GetFontName() override { return this->fontname.c_str(); }
const void *GetOSHandle() override { return &this->logfont; } const void *GetOSHandle() override { return &this->logfont; }
}; };

View File

@ -57,7 +57,7 @@ bool LoadLibraryList(Function proc[], const char *dll)
{ {
while (*dll != '\0') { while (*dll != '\0') {
HMODULE lib; HMODULE lib;
lib = LoadLibrary(OTTD2FS(dll)); lib = LoadLibrary(OTTD2FS(dll).c_str());
if (lib == nullptr) return false; if (lib == nullptr) return false;
for (;;) { for (;;) {
@ -77,12 +77,12 @@ bool LoadLibraryList(Function proc[], const char *dll)
void ShowOSErrorBox(const char *buf, bool system) void ShowOSErrorBox(const char *buf, bool system)
{ {
MyShowCursor(true); MyShowCursor(true);
MessageBox(GetActiveWindow(), OTTD2FS(buf), L"Error!", MB_ICONSTOP | MB_TASKMODAL); MessageBox(GetActiveWindow(), OTTD2FS(buf).c_str(), L"Error!", MB_ICONSTOP | MB_TASKMODAL);
} }
void OSOpenBrowser(const char *url) void OSOpenBrowser(const char *url)
{ {
ShellExecute(GetActiveWindow(), L"open", OTTD2FS(url), nullptr, nullptr, SW_SHOWNORMAL); ShellExecute(GetActiveWindow(), L"open", OTTD2FS(url).c_str(), nullptr, nullptr, SW_SHOWNORMAL);
} }
/* Code below for windows version of opendir/readdir/closedir copied and /* Code below for windows version of opendir/readdir/closedir copied and
@ -141,14 +141,14 @@ DIR *opendir(const wchar_t *path)
if ((fa != INVALID_FILE_ATTRIBUTES) && (fa & FILE_ATTRIBUTE_DIRECTORY)) { if ((fa != INVALID_FILE_ATTRIBUTES) && (fa & FILE_ATTRIBUTE_DIRECTORY)) {
d = dir_calloc(); d = dir_calloc();
if (d != nullptr) { if (d != nullptr) {
wchar_t search_path[MAX_PATH]; std::wstring search_path = path;
bool slash = path[wcslen(path) - 1] == '\\'; bool slash = path[wcslen(path) - 1] == '\\';
/* build search path for FindFirstFile, try not to append additional slashes /* build search path for FindFirstFile, try not to append additional slashes
* as it throws Win9x off its groove for root directories */ * as it throws Win9x off its groove for root directories */
_snwprintf(search_path, lengthof(search_path), L"%s%s*", path, slash ? L"" : L"\\"); if (!slash) search_path += L"\\";
*lastof(search_path) = '\0'; search_path += L"*";
d->hFind = FindFirstFile(search_path, &d->fd); d->hFind = FindFirstFile(search_path.c_str(), &d->fd);
if (d->hFind != INVALID_HANDLE_VALUE || if (d->hFind != INVALID_HANDLE_VALUE ||
GetLastError() == ERROR_NO_MORE_FILES) { // the directory is empty GetLastError() == ERROR_NO_MORE_FILES) { // the directory is empty
@ -246,7 +246,7 @@ bool FiosGetDiskFreeSpace(const char *path, uint64 *tot)
UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS); // disable 'no-disk' message box UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS); // disable 'no-disk' message box
ULARGE_INTEGER bytes_free; ULARGE_INTEGER bytes_free;
bool retval = GetDiskFreeSpaceEx(OTTD2FS(path), &bytes_free, nullptr, nullptr); bool retval = GetDiskFreeSpaceEx(OTTD2FS(path).c_str(), &bytes_free, nullptr, nullptr);
if (retval) *tot = bytes_free.QuadPart; if (retval) *tot = bytes_free.QuadPart;
SetErrorMode(sem); // reset previous setting SetErrorMode(sem); // reset previous setting
@ -415,7 +415,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
/* Convert the command line to UTF-8. We need a dedicated buffer /* Convert the command line to UTF-8. We need a dedicated buffer
* for this because argv[] points into this buffer and this needs to * for this because argv[] points into this buffer and this needs to
* be available between subsequent calls to FS2OTTD(). */ * be available between subsequent calls to FS2OTTD(). */
char *cmdline = stredup(FS2OTTD(GetCommandLine())); char *cmdline = stredup(FS2OTTD(GetCommandLine()).c_str());
#if defined(_DEBUG) #if defined(_DEBUG)
CreateConsole(); CreateConsole();
@ -553,34 +553,40 @@ bool GetClipboardContents(char *buffer, const char *last)
/** /**
* Convert to OpenTTD's encoding from wide characters. * Convert to OpenTTD's encoding from a wide string.
* OpenTTD internal encoding is UTF8. * OpenTTD internal encoding is UTF8.
* The returned value's contents can only be guaranteed until the next call to * @param name valid string that will be converted (local, or wide)
* this function. So if the value is needed for anything else, use convert_from_fs * @return converted string; if failed string is of zero-length
* @param name pointer to a valid string that will be converted (local, or wide)
* @return pointer to the converted string; if failed string is of zero-length
* @see the current code-page comes from video\win32_v.cpp, event-notification * @see the current code-page comes from video\win32_v.cpp, event-notification
* WM_INPUTLANGCHANGE * WM_INPUTLANGCHANGE
*/ */
const char *FS2OTTD(const wchar_t *name) std::string FS2OTTD(const std::wstring &name)
{ {
static char utf8_buf[512]; int name_len = (name.length() >= INT_MAX) ? INT_MAX : (int)name.length();
return convert_from_fs(name, utf8_buf, lengthof(utf8_buf)); int len = WideCharToMultiByte(CP_UTF8, 0, name.c_str(), name_len, nullptr, 0, nullptr, nullptr);
if (len <= 0) return std::string();
char *utf8_buf = AllocaM(char, len + 1);
utf8_buf[len] = '\0';
WideCharToMultiByte(CP_UTF8, 0, name.c_str(), name_len, utf8_buf, len, nullptr, nullptr);
return std::string(utf8_buf, static_cast<size_t>(len));
} }
/** /**
* Convert from OpenTTD's encoding to wide characters. * Convert from OpenTTD's encoding to a wide string.
* OpenTTD internal encoding is UTF8. * OpenTTD internal encoding is UTF8.
* The returned value's contents can only be guaranteed until the next call to * @param name valid string that will be converted (UTF8)
* this function. So if the value is needed for anything else, use convert_from_fs
* @param name pointer to a valid string that will be converted (UTF8)
* @param console_cp convert to the console encoding instead of the normal system encoding. * @param console_cp convert to the console encoding instead of the normal system encoding.
* @return pointer to the converted string; if failed string is of zero-length * @return converted string; if failed string is of zero-length
*/ */
const wchar_t *OTTD2FS(const char *name, bool console_cp) std::wstring OTTD2FS(const std::string &name, bool console_cp)
{ {
static wchar_t system_buf[512]; int name_len = (name.length() >= INT_MAX) ? INT_MAX : (int)name.length();
return convert_to_fs(name, system_buf, lengthof(system_buf), console_cp); int len = MultiByteToWideChar(CP_UTF8, 0, name.c_str(), name_len, nullptr, 0);
if (len <= 0) return std::wstring();
wchar_t *system_buf = AllocaM(wchar_t, len + 1);
system_buf[len] = L'\0';
MultiByteToWideChar(CP_UTF8, 0, name.c_str(), name_len, system_buf, len);
return std::wstring(system_buf, static_cast<size_t>(len));
} }
@ -594,10 +600,8 @@ const wchar_t *OTTD2FS(const char *name, bool console_cp)
*/ */
char *convert_from_fs(const wchar_t *name, char *utf8_buf, size_t buflen) char *convert_from_fs(const wchar_t *name, char *utf8_buf, size_t buflen)
{ {
const wchar_t *wide_buf = name;
/* Convert UTF-16 string to UTF-8. */ /* Convert UTF-16 string to UTF-8. */
int len = WideCharToMultiByte(CP_UTF8, 0, wide_buf, -1, utf8_buf, (int)buflen, nullptr, nullptr); int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, utf8_buf, (int)buflen, nullptr, nullptr);
if (len == 0) utf8_buf[0] = '\0'; if (len == 0) utf8_buf[0] = '\0';
return utf8_buf; return utf8_buf;

View File

@ -93,6 +93,7 @@
#include <climits> #include <climits>
#include <cassert> #include <cassert>
#include <memory> #include <memory>
#include <string>
#ifndef SIZE_MAX #ifndef SIZE_MAX
# define SIZE_MAX ((size_t)-1) # define SIZE_MAX ((size_t)-1)
@ -252,25 +253,26 @@
#endif /* defined(_MSC_VER) */ #endif /* defined(_MSC_VER) */
/* NOTE: the string returned by these functions is only valid until the next
* call to the same function and is not thread- or reentrancy-safe */
#if !defined(STRGEN) && !defined(SETTINGSGEN) #if !defined(STRGEN) && !defined(SETTINGSGEN)
# if defined(_WIN32) # if defined(_WIN32)
char *getcwd(char *buf, size_t size); char *getcwd(char *buf, size_t size);
# include <tchar.h>
# include <io.h> # include <io.h>
# include <tchar.h>
namespace std { using ::_wfopen; } # define fopen(file, mode) _wfopen(OTTD2FS(file).c_str(), _T(mode))
# define fopen(file, mode) _wfopen(OTTD2FS(file), _T(mode)) # define unlink(file) _wunlink(OTTD2FS(file).c_str())
# define unlink(file) _wunlink(OTTD2FS(file))
const char *FS2OTTD(const wchar_t *name); std::string FS2OTTD(const std::wstring &name);
const wchar_t *OTTD2FS(const char *name, bool console_cp = false); std::wstring OTTD2FS(const std::string &name, bool console_cp = false);
# elif defined(WITH_ICONV)
# define fopen(file, mode) fopen(OTTD2FS(file).c_str(), mode)
std::string FS2OTTD(const std::string &name);
std::string OTTD2FS(const std::string &name);
# else # else
# define fopen(file, mode) fopen(OTTD2FS(file), mode) // no override of fopen() since no transformation is required of the filename
const char *FS2OTTD(const char *name); template <typename T> std::string FS2OTTD(T name) { return name; }
const char *OTTD2FS(const char *name); template <typename T> std::string OTTD2FS(T name) { return name; }
# endif /* _WIN32 */ # endif /* _WIN32 or WITH_ICONV */
#endif /* STRGEN || SETTINGSGEN */ #endif /* STRGEN || SETTINGSGEN */
#if defined(_WIN32) || defined(__OS2__) && !defined(__INNOTEK_LIBC__) #if defined(_WIN32) || defined(__OS2__) && !defined(__INNOTEK_LIBC__)

View File

@ -1910,14 +1910,14 @@ static void GetLanguageList(const char *path)
if (dir != nullptr) { if (dir != nullptr) {
struct dirent *dirent; struct dirent *dirent;
while ((dirent = readdir(dir)) != nullptr) { while ((dirent = readdir(dir)) != nullptr) {
const char *d_name = FS2OTTD(dirent->d_name); std::string d_name = FS2OTTD(dirent->d_name);
const char *extension = strrchr(d_name, '.'); const char *extension = strrchr(d_name.c_str(), '.');
/* Not a language file */ /* Not a language file */
if (extension == nullptr || strcmp(extension, ".lng") != 0) continue; if (extension == nullptr || strcmp(extension, ".lng") != 0) continue;
LanguageMetadata lmd; LanguageMetadata lmd;
seprintf(lmd.file, lastof(lmd.file), "%s%s", path, d_name); seprintf(lmd.file, lastof(lmd.file), "%s%s", path, d_name.c_str());
/* Check whether the file is of the correct version */ /* Check whether the file is of the correct version */
if (!GetLanguageFileHeader(lmd.file, &lmd)) { if (!GetLanguageFileHeader(lmd.file, &lmd)) {

View File

@ -214,7 +214,7 @@ bool VideoDriver_Win32Base::MakeWindow(bool full_screen, bool resize)
char window_title[64]; char window_title[64];
seprintf(window_title, lastof(window_title), "OpenTTD %s", _openttd_revision); seprintf(window_title, lastof(window_title), "OpenTTD %s", _openttd_revision);
this->main_wnd = CreateWindow(L"OTTD", OTTD2FS(window_title), style, x, y, w, h, 0, 0, GetModuleHandle(nullptr), this); this->main_wnd = CreateWindow(L"OTTD", OTTD2FS(window_title).c_str(), style, x, y, w, h, 0, 0, GetModuleHandle(nullptr), this);
if (this->main_wnd == nullptr) usererror("CreateWindow failed"); if (this->main_wnd == nullptr) usererror("CreateWindow failed");
ShowWindow(this->main_wnd, showstyle); ShowWindow(this->main_wnd, showstyle);
} }
@ -331,7 +331,7 @@ static LRESULT HandleIMEComposition(HWND hwnd, WPARAM wParam, LPARAM lParam)
/* Transmit text to windowing system. */ /* Transmit text to windowing system. */
if (len > 0) { if (len > 0) {
HandleTextInput(nullptr, true); // Clear marked string. HandleTextInput(nullptr, true); // Clear marked string.
HandleTextInput(FS2OTTD(str)); HandleTextInput(FS2OTTD(str).c_str());
} }
SetCompositionPos(hwnd); SetCompositionPos(hwnd);