changeset 20701:db150a402c4d draft

-Fix: [Win32] The ANSI code page is not UTF-8 for non-Unicode builds.
author Michael Lutz <michi@icosahedron.de>
date Thu, 28 Mar 2013 02:46:51 +0100
parents 28e4d872be76
children b098d8af7ec8
files src/fontdetection.cpp src/os/windows/crashlog_win.cpp src/os/windows/win32.cpp src/os/windows/win32.h
diffstat 4 files changed, 42 insertions(+), 91 deletions(-) [+]
line wrap: on
line diff
--- a/src/fontdetection.cpp
+++ b/src/fontdetection.cpp
@@ -42,26 +42,19 @@
  * filename into something that isn't UTF-8 but represents the Unicode file
  * name. This is the short DOS 8.3 format. This does not contain any
  * characters that fopen doesn't support.
- * @param long_path the path in UTF-8.
+ * @param long_path the path in system encoding.
  * @return the short path in ANSI (ASCII).
  */
-char *GetShortPath(const char *long_path)
+const char *GetShortPath(const TCHAR *long_path)
 {
 	static char short_path[MAX_PATH];
 #ifdef UNICODE
-	/* The non-unicode GetShortPath doesn't support UTF-8...,
-	 * so convert the path to wide chars, then get the short
-	 * path and convert it back again. */
-	wchar_t long_path_w[MAX_PATH];
-	MultiByteToWideChar(CP_UTF8, 0, long_path, -1, long_path_w, MAX_PATH);
-
-	wchar_t short_path_w[MAX_PATH];
-	GetShortPathNameW(long_path_w, short_path_w, MAX_PATH);
-
-	WideCharToMultiByte(CP_ACP, 0, short_path_w, -1, short_path, MAX_PATH, NULL, NULL);
+	WCHAR short_path_w[MAX_PATH];
+	GetShortPathName(long_path, short_path_w, lengthof(short_path_w));
+	WideCharToMultiByte(CP_ACP, 0, short_path_w, -1, short_path, lengthof(short_path), NULL, NULL);
 #else
 	/* Technically not needed, but do it for consistency. */
-	GetShortPathNameA(long_path, short_path, MAX_PATH);
+	GetShortPathName(long_path, short_path, lengthof(short_path));
 #endif
 	return short_path;
 }
@@ -82,9 +75,10 @@
 	HKEY hKey;
 	LONG ret;
 	TCHAR vbuffer[MAX_PATH], dbuffer[256];
-	TCHAR *font_namep;
-	char *font_path;
+	TCHAR *pathbuf;
+	const char *font_path;
 	uint index;
+	size_t path_len;
 
 	/* On windows NT (2000, NT3.5, XP, etc.) the fonts are stored in the
 	 * "Windows NT" key, on Windows 9x in the Windows key. To save us having
@@ -97,15 +91,8 @@
 		return err;
 	}
 
-	/* For Unicode we need some conversion between widechar and
-	 * normal char to match the data returned by RegEnumValue,
-	 * otherwise just use parameter */
-#if defined(UNICODE)
-	font_namep = MallocT<TCHAR>(MAX_PATH);
-	MB_TO_WIDE_BUFFER(font_name, font_namep, MAX_PATH * sizeof(TCHAR));
-#else
-	font_namep = const_cast<char *>(font_name); // only cast because in unicode pointer is not const
-#endif
+	/* Convert font name to file system encoding. */
+	TCHAR *font_namep = _tcsdup(OTTD2FS(font_name));
 
 	for (index = 0;; index++) {
 		TCHAR *s;
@@ -142,23 +129,13 @@
 	/* Some fonts are contained in .ttc files, TrueType Collection fonts. These
 	 * contain multiple fonts inside this single file. GetFontData however
 	 * returns the whole file, so we need to check each font inside to get the
-	 * proper font.
-	 * Also note that FreeType does not support UNICODE filenames! */
-#if defined(UNICODE)
-	/* We need a cast here back from wide because FreeType doesn't support
-	 * widechar filenames. Just use the buffer we allocated before for the
-	 * font_name search */
-	font_path = (char*)font_namep;
-	WIDE_TO_MB_BUFFER(vbuffer, font_path, MAX_PATH * sizeof(TCHAR));
-#else
-	font_path = vbuffer;
-#endif
+	 * proper font. */
+	path_len = _tcslen(vbuffer) + _tcslen(dbuffer) + 2; // '\' and terminating nul.
+	pathbuf = AllocaM(TCHAR, path_len);
+	_sntprintf(pathbuf, path_len, _T("%s\\%s"), vbuffer, dbuffer);
 
-	ttd_strlcat(font_path, "\\", MAX_PATH * sizeof(TCHAR));
-	ttd_strlcat(font_path, WIDE_TO_MB(dbuffer), MAX_PATH * sizeof(TCHAR));
-
-	/* Convert the path into something that FreeType understands */
-	font_path = GetShortPath(font_path);
+	/* Convert the path into something that FreeType understands. */
+	font_path = GetShortPath(pathbuf);
 
 	index = 0;
 	do {
@@ -175,9 +152,7 @@
 
 folder_error:
 registry_no_font_found:
-#if defined(UNICODE)
 	free(font_namep);
-#endif
 	RegCloseKey(hKey);
 	return err;
 }
@@ -338,11 +313,7 @@
 	}
 
 	char font_name[MAX_PATH];
-#if defined(UNICODE)
-	WIDE_TO_MB_BUFFER((const TCHAR*)logfont->elfFullName, font_name, lengthof(font_name));
-#else
-	strecpy(font_name, (const TCHAR*)logfont->elfFullName, lastof(font_name));
-#endif
+	convert_from_fs((const TCHAR *)logfont->elfFullName, font_name, lengthof(font_name));
 
 	/* Add english name after font name */
 	const char *english_name = GetEnglishFontName(logfont);
--- a/src/os/windows/crashlog_win.cpp
+++ b/src/os/windows/crashlog_win.cpp
@@ -197,7 +197,7 @@
 	GetModuleFileName(mod, buffer, MAX_PATH);
 	GetFileInfo(&dfi, buffer);
 	output += seprintf(output, last, " %-20s handle: %p size: %d crc: %.8X date: %d-%.2d-%.2d %.2d:%.2d:%.2d\n",
-		WIDE_TO_MB(buffer),
+		FS2OTTD(buffer),
 		mod,
 		dfi.size,
 		dfi.crc32,
@@ -621,11 +621,9 @@
 {
 	switch (msg) {
 		case WM_INITDIALOG: {
-#if defined(UNICODE)
 			/* We need to put the crash-log in a separate buffer because the default
 			 * buffer in MB_TO_WIDE is not large enough (512 chars) */
-			wchar_t crash_msgW[lengthof(CrashLogWindows::current->crashlog)];
-#endif
+			TCHAR crash_msgW[lengthof(CrashLogWindows::current->crashlog)];
 			/* Convert unix -> dos newlines because the edit box only supports that properly :( */
 			const char *unix_nl = CrashLogWindows::current->crashlog;
 			char dos_nl[lengthof(CrashLogWindows::current->crashlog)];
@@ -655,7 +653,7 @@
 			}
 
 			SetDlgItemText(wnd, 10, text);
-			SetDlgItemText(wnd, 11, MB_TO_WIDE_BUFFER(dos_nl, crash_msgW, lengthof(crash_msgW)));
+			SetDlgItemText(wnd, 11, convert_to_fs(dos_nl, crash_msgW, lengthof(crash_msgW)));
 			SendDlgItemMessage(wnd, 11, WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), FALSE);
 			SetWndSize(wnd, -1);
 		} return TRUE;
--- a/src/os/windows/win32.cpp
+++ b/src/os/windows/win32.cpp
@@ -78,12 +78,12 @@
 void ShowOSErrorBox(const char *buf, bool system)
 {
 	MyShowCursor(true);
-	MessageBox(GetActiveWindow(), MB_TO_WIDE(buf), _T("Error!"), MB_ICONSTOP);
+	MessageBox(GetActiveWindow(), OTTD2FS(buf), _T("Error!"), MB_ICONSTOP);
 }
 
 void OSOpenBrowser(const char *url)
 {
-	ShellExecute(GetActiveWindow(), _T("open"), MB_TO_WIDE(url), NULL, NULL, SW_SHOWNORMAL);
+	ShellExecute(GetActiveWindow(), _T("open"), OTTD2FS(url), NULL, NULL, SW_SHOWNORMAL);
 }
 
 /* Code below for windows version of opendir/readdir/closedir copied and
@@ -371,12 +371,10 @@
 				*q++ = *p++;
 			}
 			*q = '\0';
-#if defined(UNICODE)
 			/* We need to put the text in a separate buffer because the default
-			 * buffer in MB_TO_WIDE might not be large enough (512 chars) */
-			wchar_t help_msgW[8192];
-#endif
-			SetDlgItemText(wnd, 11, MB_TO_WIDE_BUFFER(help_msg, help_msgW, lengthof(help_msgW)));
+			 * buffer in OTTD2FS might not be large enough (512 chars). */
+			TCHAR help_msg_buf[8192];
+			SetDlgItemText(wnd, 11, convert_to_fs(help_msg, help_msg_buf, lengthof(help_msg_buf)));
 			SendDlgItemMessage(wnd, 11, WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), FALSE);
 		} return TRUE;
 
@@ -407,12 +405,10 @@
 			_help_msg = str;
 			DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(101), NULL, HelpDialogFunc);
 		} else {
-#if defined(UNICODE)
 			/* We need to put the text in a separate buffer because the default
-			 * buffer in MB_TO_WIDE might not be large enough (512 chars) */
-			wchar_t help_msgW[8192];
-#endif
-			MessageBox(GetActiveWindow(), MB_TO_WIDE_BUFFER(str, help_msgW, lengthof(help_msgW)), _T("OpenTTD"), MB_ICONINFORMATION | MB_OK);
+			 * buffer in OTTD2FS might not be large enough (512 chars). */
+			TCHAR help_msg_buf[8192];
+			MessageBox(GetActiveWindow(), convert_to_fs(str, help_msg_buf, lengthof(help_msg_buf)), _T("OpenTTD"), MB_ICONINFORMATION | MB_OK);
 		}
 		MyShowCursor(old);
 	}
@@ -426,24 +422,18 @@
 {
 	int argc;
 	char *argv[64]; // max 64 command line arguments
-	char *cmdline;
 
 	CrashLog::InitialiseCrashLog();
 
-#if defined(UNICODE)
-
-#if !defined(WINCE)
+#if defined(UNICODE) && !defined(WINCE)
 	/* Check if a win9x user started the win32 version */
 	if (HasBit(GetVersion(), 31)) usererror("This version of OpenTTD doesn't run on windows 95/98/ME.\nPlease download the win9x binary and try again.");
 #endif
 
-	/* For UNICODE we need to convert the commandline to char* _AND_
-	 * save it because argv[] points into this buffer and thus needs to
-	 * be available between subsequent calls to FS2OTTD() */
-	char cmdlinebuf[MAX_PATH];
-#endif /* UNICODE */
-
-	cmdline = WIDE_TO_MB_BUFFER(GetCommandLine(), cmdlinebuf, lengthof(cmdlinebuf));
+	/* Convert the command line to UTF-8. We need a dedicated buffer
+	 * for this because argv[] points into this buffer and this needs to
+	 * be available between subsequent calls to FS2OTTD(). */
+	char *cmdline = strdup(FS2OTTD(GetCommandLine()));
 
 #if defined(_DEBUG)
 	CreateConsole();
@@ -459,6 +449,7 @@
 	argc = ParseCommandLine(cmdline, argv, lengthof(argv));
 
 	openttd_main(argc, argv);
+	free(cmdline);
 	return 0;
 }
 
@@ -486,12 +477,10 @@
 	/* GetModuleFileName returns dir with file, so remove everything behind latest '\\' */
 	char *p = strrchr(buf, '\\');
 	if (p != NULL) *p = '\0';
-#elif defined(UNICODE)
+#else
 	TCHAR path[MAX_PATH];
 	GetCurrentDirectory(MAX_PATH - 1, path);
 	convert_from_fs(path, buf, size);
-#else
-	GetCurrentDirectory(size, buf);
 #endif
 	return buf;
 }
@@ -503,7 +492,7 @@
 	TCHAR path[MAX_PATH];
 #ifdef WITH_PERSONAL_DIR
 	if (SUCCEEDED(OTTDSHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, path))) {
-		strecpy(tmp, WIDE_TO_MB_BUFFER(path, tmp, lengthof(tmp)), lastof(tmp));
+		strecpy(tmp, FS2OTTD(path), lastof(tmp));
 		AppendPathSeparator(tmp, MAX_PATH);
 		ttd_strlcat(tmp, PERSONAL_DIR, MAX_PATH);
 		AppendPathSeparator(tmp, MAX_PATH);
@@ -513,7 +502,7 @@
 	}
 
 	if (SUCCEEDED(OTTDSHGetFolderPath(NULL, CSIDL_COMMON_DOCUMENTS, NULL, SHGFP_TYPE_CURRENT, path))) {
-		strecpy(tmp, WIDE_TO_MB_BUFFER(path, tmp, lengthof(tmp)), lastof(tmp));
+		strecpy(tmp, FS2OTTD(path), lastof(tmp));
 		AppendPathSeparator(tmp, MAX_PATH);
 		ttd_strlcat(tmp, PERSONAL_DIR, MAX_PATH);
 		AppendPathSeparator(tmp, MAX_PATH);
@@ -536,12 +525,12 @@
 		_searchpaths[SP_BINARY_DIR] = NULL;
 	} else {
 		TCHAR exec_dir[MAX_PATH];
-		_tcsncpy(path, MB_TO_WIDE_BUFFER(exe, path, lengthof(path)), lengthof(path));
+		_tcsncpy(path, convert_to_fs(exe, path, lengthof(path)), lengthof(path));
 		if (!GetFullPathName(path, lengthof(exec_dir), exec_dir, NULL)) {
 			DEBUG(misc, 0, "GetFullPathName failed (%lu)\n", GetLastError());
 			_searchpaths[SP_BINARY_DIR] = NULL;
 		} else {
-			strecpy(tmp, WIDE_TO_MB_BUFFER(exec_dir, tmp, lengthof(tmp)), lastof(tmp));
+			strecpy(tmp, convert_from_fs(exec_dir, tmp, lengthof(tmp)), lastof(tmp));
 			char *s = strrchr(tmp, PATHSEPCHAR);
 			*(s + 1) = '\0';
 			_searchpaths[SP_BINARY_DIR] = strdup(tmp);
--- a/src/os/windows/win32.h
+++ b/src/os/windows/win32.h
@@ -23,21 +23,14 @@
 
 /* Function shortcuts for UTF-8 <> UNICODE conversion. When unicode is not
  * defined these macros return the string passed to them, with UNICODE
- * they return a pointer to the converted string. The only difference between
- * XX_TO_YY and XX_TO_YY_BUFFER is that with the buffer variant you can
- * specify where to put the converted string (and how long it can be). Without
- * the buffer and internal buffer is used, of max 512 characters */
+ * they return a pointer to the converted string. These functions use an
+ * internal buffer of max 512 characters. */
 #if defined(UNICODE)
 # define MB_TO_WIDE(str) OTTD2FS(str)
-# define MB_TO_WIDE_BUFFER(str, buffer, buflen) convert_to_fs(str, buffer, buflen)
 # define WIDE_TO_MB(str) FS2OTTD(str)
-# define WIDE_TO_MB_BUFFER(str, buffer, buflen) convert_from_fs(str, buffer, buflen)
 #else
-extern uint _codepage; // local code-page in the system @see win32_v.cpp:WM_INPUTLANGCHANGE
 # define MB_TO_WIDE(str) (str)
-# define MB_TO_WIDE_BUFFER(str, buffer, buflen) (str)
 # define WIDE_TO_MB(str) (str)
-# define WIDE_TO_MB_BUFFER(str, buffer, buflen) (str)
 #endif
 
 HRESULT OTTDSHGetFolderPath(HWND, int, HANDLE, DWORD, LPTSTR);