Fix Android text bug (no text displaying)

This commit is contained in:
Craig Robbins 2015-03-07 15:09:27 +10:00
parent ffdf8dedb7
commit 5698e2baf8
4 changed files with 82 additions and 83 deletions

@ -4175,7 +4175,9 @@ inline void Game::limitFps(FpsControl *fps_timings, f32 *dtime)
fps_timings->last_time = time; fps_timings->last_time = time;
} }
// Note: This will free (using delete[])! \p msg. If you want to use it later,
// pass a copy of it to this function
// Note: \p msg must be allocated using new (not malloc())
void Game::showOverlayMessage(const wchar_t *msg, float dtime, void Game::showOverlayMessage(const wchar_t *msg, float dtime,
int percent, bool draw_clouds) int percent, bool draw_clouds)
{ {

@ -29,25 +29,25 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#endif #endif
#define _(String) gettext(String) #define _(String) gettext(String)
#define gettext_noop(String) String #define gettext_noop(String) (String)
#define N_(String) gettext_noop (String) #define N_(String) gettext_noop((String))
#ifdef _MSC_VER #ifdef _MSC_VER
void init_gettext(const char *path, const std::string &configured_language, int argc, char** argv); void init_gettext(const char *path, const std::string &configured_language,
int argc, char** argv);
#else #else
void init_gettext(const char *path, const std::string &configured_language); void init_gettext(const char *path, const std::string &configured_language);
#endif #endif
extern const wchar_t *narrow_to_wide_c(const char *mbs); extern wchar_t *narrow_to_wide_c(const char *str);
extern std::wstring narrow_to_wide(const std::string &mbs);
// You must free the returned string! // You must free the returned string!
// The returned string is allocated using new
inline const wchar_t *wgettext(const char *str) inline const wchar_t *wgettext(const char *str)
{ {
return narrow_to_wide_c(gettext(str)); return narrow_to_wide_c(gettext(str));
} }
// Gettext under MSVC needs this strange way. Just don't ask...
inline std::wstring wstrgettext(const std::string &text) inline std::wstring wstrgettext(const std::string &text)
{ {
const wchar_t *tmp = wgettext(text.c_str()); const wchar_t *tmp = wgettext(text.c_str());

@ -22,9 +22,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "numeric.h" #include "numeric.h"
#include "log.h" #include "log.h"
#include "sha1.h"
#include "base64.h" #include "base64.h"
#include "hex.h" #include "hex.h"
#include "sha1.h"
#include "../porting.h" #include "../porting.h"
#include <algorithm> #include <algorithm>
@ -32,13 +32,36 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <iomanip> #include <iomanip>
#include <map> #include <map>
#if defined(_WIN32)
#include <windows.h> // MultiByteToWideChar
#endif
static bool parseHexColorString(const std::string &value, video::SColor &color); static bool parseHexColorString(const std::string &value, video::SColor &color);
static bool parseNamedColorString(const std::string &value, video::SColor &color); static bool parseNamedColorString(const std::string &value, video::SColor &color);
// You must free the returned string!
// The returned string is allocated using new
wchar_t *narrow_to_wide_c(const char *str)
{
wchar_t* nstr = 0;
#if defined(_WIN32)
int nResult = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) str, -1, 0, 0);
if (nResult == 0) {
errorstream<<"gettext: MultiByteToWideChar returned null"<<std::endl;
} else {
nstr = new wchar_t[nResult];
MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) str, -1, (WCHAR *) nstr, nResult);
}
#else
size_t len = strlen(str);
nstr = new wchar_t[len+1];
std::wstring intermediate = narrow_to_wide(str);
memset(nstr, 0, (len + 1) * sizeof(wchar_t));
memcpy(nstr, intermediate.c_str(), len * sizeof(wchar_t));
#endif
return nstr;
}
#ifdef __ANDROID__ #ifdef __ANDROID__
const wchar_t* wide_chars = const wchar_t* wide_chars =
@ -63,83 +86,54 @@ int wctomb(char *s, wchar_t wc)
int mbtowc(wchar_t *pwc, const char *s, size_t n) int mbtowc(wchar_t *pwc, const char *s, size_t n)
{ {
if (s == NULL || *s == '\0') std::wstring intermediate = narrow_to_wide(s);
if (intermediate.length() > 0) {
*pwc = intermediate[0];
return 1;
}
else {
return -1; return -1;
}
const wchar_t *tmp = narrow_to_wide_c(s);
bool success = tmp[0] != '\0';
if (success)
*pwc = tmp[0];
delete tmp;
return success ? 1 : -1;
} }
// You must free the returned string! std::wstring narrow_to_wide(const std::string &mbs) {
const wchar_t *narrow_to_wide_c(const char *mbs) size_t wcl = mbs.size();
{
size_t mbl = strlen(mbs);
wchar_t *wcs = new wchar_t[mbl + 1];
size_t i, dest_i = 0; std::wstring retval = L"";
for (i = 0; i < mbl; i++) {
for (unsigned int i = 0; i < wcl; i++) {
if (((unsigned char) mbs[i] >31) && if (((unsigned char) mbs[i] >31) &&
((unsigned char) mbs[i] < 127)) { ((unsigned char) mbs[i] < 127)) {
wcs[dest_i++] = wide_chars[(unsigned char) mbs[i] - 32];
retval += wide_chars[(unsigned char) mbs[i] -32];
} }
//handle newline //handle newline
else if (mbs[i] == '\n') { else if (mbs[i] == '\n') {
wcs[dest_i++] = L'\n'; retval += L'\n';
} }
} }
wcs[dest_i] = '\0';
return wcs; return retval;
} }
#else #else // not Android
// You must free the returned string!
const wchar_t *narrow_to_wide_c(const char *mbs)
{
wchar_t *wcs = NULL;
#if defined(_WIN32)
int nResult = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) mbs, -1, 0, 0);
if (nResult == 0) {
errorstream << "gettext: MultiByteToWideChar returned null" << std::endl;
} else {
wcs = new wchar_t[nResult];
MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) mbs, -1, (WCHAR *) wcs, nResult);
}
#else
size_t wcl = mbstowcs(NULL, mbs, 0);
if (wcl == (size_t) -1)
return NULL;
wcs = new wchar_t[wcl + 1];
size_t l = mbstowcs(wcs, mbs, wcl);
assert(l != (size_t) -1); // Should never happen if the last call worked
wcs[l] = '\0';
#endif
return wcs;
}
#endif
std::wstring narrow_to_wide(const std::string &mbs) std::wstring narrow_to_wide(const std::string &mbs)
{ {
size_t wcl = mbs.size(); size_t wcl = mbs.size();
Buffer<wchar_t> wcs(wcl + 1); Buffer<wchar_t> wcs(wcl + 1);
size_t l = mbstowcs(*wcs, mbs.c_str(), wcl); size_t len = mbstowcs(*wcs, mbs.c_str(), wcl);
if (l == (size_t)(-1)) if (len == (size_t)(-1))
return L"<invalid multibyte string>"; return L"<invalid multibyte string>";
wcs[l] = 0; wcs[len] = 0;
return *wcs; return *wcs;
} }
#endif
#ifdef __ANDROID__ #ifdef __ANDROID__
std::string wide_to_narrow(const std::wstring &wcs) { std::string wide_to_narrow(const std::wstring &wcs) {
size_t mbl = wcs.size()*4; size_t mbl = wcs.size()*4;
@ -165,17 +159,18 @@ std::string wide_to_narrow(const std::wstring& wcs) {
return retval; return retval;
} }
#else
#else // not Android
std::string wide_to_narrow(const std::wstring &wcs) std::string wide_to_narrow(const std::wstring &wcs)
{ {
size_t mbl = wcs.size() * 4; size_t mbl = wcs.size() * 4;
SharedBuffer<char> mbs(mbl+1); SharedBuffer<char> mbs(mbl+1);
size_t l = wcstombs(*mbs, wcs.c_str(), mbl); size_t len = wcstombs(*mbs, wcs.c_str(), mbl);
if(l == (size_t)(-1)) { if (len == (size_t)(-1))
return "Character conversion failed!"; return "Character conversion failed!";
}
else else
mbs[l] = 0; mbs[len] = 0;
return *mbs; return *mbs;
} }

@ -36,8 +36,10 @@ struct FlagDesc {
u32 flag; u32 flag;
}; };
// You must free the returned string! // You must free the returned string!
const wchar_t *narrow_to_wide_c(const char *mbs); // The returned string is allocated using new
wchar_t *narrow_to_wide_c(const char *str);
std::wstring narrow_to_wide(const std::string &mbs); std::wstring narrow_to_wide(const std::string &mbs);
std::string wide_to_narrow(const std::wstring &wcs); std::string wide_to_narrow(const std::wstring &wcs);