[rpcli] rpcli.cpp: Add color to the libgnuintl-8.dll and romdata-6.dll error messages.

NOTE: ConsolePrint() currently uses utf8_to_utf16() if printing to a
Windows console and ANSI isn't supported. This function is located
in libromdata (librptext), so we can't use it if romdata-6.dll is
missing. Use MultiByteToWideChar() directly instead. This might also
slightly improve performance, since an std::u16string is no longer
needed.

GDI+ init error: Localize the string. This can be localized because
libgnuintl-8.dll was already verified to be present at this point.
This commit is contained in:
David Korth 2025-04-27 19:18:20 -04:00
parent 7726fc6dfd
commit faeca807bd
2 changed files with 43 additions and 28 deletions

View File

@ -683,17 +683,23 @@ int RP_C_API _tmain(int argc, TCHAR *argv[])
setlocale(LC_CTYPE, "C");
#endif /* _WIN32 */
// Detect console information.
init_vt();
#if defined(ENABLE_NLS) && defined(_MSC_VER)
// Delay load verification: libgnuintl
// TODO: Skip this if not linked with /DELAYLOAD?
if (DelayLoad_test_libintl_textdomain() != 0) {
// Delay load failed.
_fputts(_T("*** ERROR: ") _T(LIBGNUINTL_DLL) _T(" could not be loaded.\n\n")
_T("This build of rom-properties has localization enabled,\n")
_T("which requires the use of GNU gettext.\n\n")
_T("Please redownload rom-properties ") _T(RP_VERSION_STRING) _T(" and copy the\n")
LIBGNUINTL_DLL _T(" file to the installation directory.\n"),
stderr);
ConsoleSetTextColor(&ci_stderr, 1, true); // red
ConsolePrint(&ci_stderr, "*** ERROR: " LIBGNUINTL_DLL " could not be loaded.\n\n");
ConsoleResetTextColor(&ci_stderr);
ConsolePrint(&ci_stderr,
"This build of rom-properties has localization enabled,\n"
"which requires the use of GNU gettext.\n\n"
"Please redownload rom-properties " RP_VERSION_STRING " and copy the\n"
LIBGNUINTL_DLL " file to the installation directory.\n");
fflush(stderr);
return EXIT_FAILURE;
}
#endif /* ENABLE_NLS && _MSC_VER */
@ -702,30 +708,33 @@ int RP_C_API _tmain(int argc, TCHAR *argv[])
# ifdef _MSC_VER
# define ROMDATA_PREFIX
# else
# define ROMDATA_PREFIX _T("lib")
# define ROMDATA_PREFIX "lib"
# endif
# ifndef NDEBUG
# define ROMDATA_SUFFIX _T("-") _T(LIBROMDATA_SOVERSION_STR) _T("d")
# define ROMDATA_SUFFIX "-" LIBROMDATA_SOVERSION_STR "d"
# else
# define ROMDATA_SUFFIX _T("-") _T(LIBROMDATA_SOVERSION_STR)
# define ROMDATA_SUFFIX "-" LIBROMDATA_SOVERSION_STR
# endif
# ifdef _WIN32
# define ROMDATA_EXT _T(".dll")
# define ROMDATA_EXT ".dll"
# else
// TODO: macOS
# define ROMDATA_EXT _T(".so")
# define ROMDATA_EXT ".so"
# endif
# define ROMDATA_DLL ROMDATA_PREFIX _T("romdata") ROMDATA_SUFFIX ROMDATA_EXT
# define ROMDATA_DLL ROMDATA_PREFIX "romdata" ROMDATA_SUFFIX ROMDATA_EXT
# ifdef _MSC_VER
// Delay load verification: romdata-X.dll
// TODO: Skip this if not linked with /DELAYLOAD?
if (DelayLoad_test_ImageTypesConfig_className() != 0) {
// Delay load failed.
_fputts(_T("*** ERROR: ") ROMDATA_DLL _T(" could not be loaded.\n\n")
_T("Please redownload rom-properties ") _T(RP_VERSION_STRING) _T(" and copy the\n")
ROMDATA_DLL _T(" file to the installation directory.\n"),
stderr);
ConsoleSetTextColor(&ci_stderr, 1, true); // red
ConsolePrint(&ci_stderr, "*** ERROR: " ROMDATA_DLL " could not be loaded.\n\n");
ConsoleResetTextColor(&ci_stderr);
ConsolePrint(&ci_stderr,
"Please redownload rom-properties " RP_VERSION_STRING " and copy the\n"
ROMDATA_DLL " file to the installation directory.\n");
fflush(stderr);
return EXIT_FAILURE;
}
# endif /* _MSC_VER */
@ -743,9 +752,6 @@ int RP_C_API _tmain(int argc, TCHAR *argv[])
}
#endif /* _WIN32 */
// Detect console information.
init_vt();
// Initialize i18n.
rp_i18n_init();
@ -790,7 +796,9 @@ int RP_C_API _tmain(int argc, TCHAR *argv[])
const ULONG_PTR gdipToken = GdiplusHelper::InitGDIPlus();
assert(gdipToken != 0);
if (gdipToken == 0) {
ConsolePrint(&ci_stderr, "*** ERROR: GDI+ initialization failed.", true);
ConsoleSetTextColor(&ci_stderr, 6, true); // red
ConsolePrint(&ci_stderr, C_("rpcli", "*** ERROR: GDI+ initialization failed."), true);
ConsoleResetTextColor(&ci_stderr);
fflush(stderr);
return -EIO;
}

View File

@ -11,15 +11,11 @@
#include "vt.hpp"
// librptext
#include "librptext/conversion.hpp"
using LibRpText::utf8_to_utf16;
// C++ STL classes
using std::array;
using std::ostream;
using std::string;
using std::u16string;
using std::unique_ptr;
#ifdef _WIN32
# include "libwin32common/RpWin32_sdk.h"
@ -236,9 +232,20 @@ int win32_write_to_console(const ConsoleInfo_t *ci, const char *str, int len)
// ANSI escape sequences are not supported.
// This means it's likely older than Win10 1607, so no UTF-8 support.
// Convert to UTF-16 first.
u16string wstr = utf8_to_utf16(str, len);
const wchar_t *p = reinterpret_cast<const wchar_t*>(wstr.data());
for (int size = static_cast<int>(wstr.size()); size > 0; size -= CHUNK_SIZE) {
// NOTE: Using MultiByteToWideChar() directly so we don't have a
// libromdata (librptext) dependency, since this function is used if
// libromdata can't be loaded for some reason.
const int cchWcs = MultiByteToWideChar(CP_UTF8, 0, str, len, nullptr, 0);
if (cchWcs <= 0) {
// Unable to convert the text...
return -EIO;
}
unique_ptr<wchar_t[]> wcs(new wchar_t[cchWcs]);
MultiByteToWideChar(CP_UTF8, 0, str, len, wcs.get(), cchWcs);
const wchar_t *p = wcs.get();
for (int size = cchWcs; size > 0; size -= CHUNK_SIZE) {
const DWORD chunk_len = static_cast<DWORD>((size > CHUNK_SIZE) ? CHUNK_SIZE : size);
WriteConsoleW(hConsole, p, chunk_len, nullptr, nullptr);
p += chunk_len;