Skip to content

Commit 572990d

Browse files
committedJun 13, 2015
Add utf-8 conversion utilities and re-add intlGUIEditBox
1 parent aa13baa commit 572990d

10 files changed

+1966
-4
lines changed
 

‎build/android/Makefile

+67-2
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,13 @@ FREETYPE_TIMESTAMP = $(FREETYPE_DIR)timestamp
131131
FREETYPE_TIMESTAMP_INT = $(ROOT)/deps/freetype_timestamp
132132
FREETYPE_URL_GIT = https://github.com/cdave1/freetype2-android
133133

134+
ICONV_VERSION = 1.14
135+
ICONV_DIR = $(ROOT)/deps/libiconv/
136+
ICONV_LIB = $(ICONV_DIR)/iconv.so
137+
ICONV_TIMESTAMP = $(ICONV_DIR)timestamp
138+
ICONV_TIMESTAMP_INT = $(ROOT)/deps/iconv_timestamp
139+
ICONV_URL_HTTP = http://ftp.gnu.org/pub/gnu/libiconv/libiconv-$(ICONV_VERSION).tar.gz
140+
134141
SQLITE3_FOLDER = sqlite-amalgamation-3080704
135142
SQLITE3_URL = http://www.sqlite.org/2014/$(SQLITE3_FOLDER).zip
136143

@@ -431,6 +438,64 @@ $(FREETYPE_LIB) : $(FREETYPE_TIMESTAMP)
431438
clean_freetype :
432439
$(RM) -rf ${FREETYPE_DIR}
433440

441+
$(ICONV_TIMESTAMP) : iconv_download
442+
@LAST_MODIF=$$(find ${ICONV_DIR} -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "); \
443+
if [ $$(basename $$LAST_MODIF) != "timestamp" ] ; then \
444+
touch ${ICONV_TIMESTAMP}; \
445+
fi
446+
447+
iconv_download :
448+
@if [ ! -d ${ICONV_DIR} ] ; then \
449+
echo "iconv sources missing, downloading..."; \
450+
mkdir -p ${ROOT}/deps; \
451+
cd ${ROOT}/deps; \
452+
wget ${ICONV_URL_HTTP} || exit 1; \
453+
tar -xzf libiconv-${ICONV_VERSION}.tar.gz || exit 1; \
454+
rm libiconv-${ICONV_VERSION}.tar.gz; \
455+
ln -s libiconv-${ICONV_VERSION} libiconv; \
456+
cd ${ICONV_DIR}; \
457+
patch -p1 < ${ROOT}/libiconv_android.patch; \
458+
patch -p1 < ${ROOT}/libiconv_android_mk.patch; \
459+
patch -p1 < ${ROOT}/libiconv_stdio.patch; \
460+
cd jni; \
461+
ln -s .. src; \
462+
fi
463+
464+
iconv : $(ICONV_LIB)
465+
466+
$(ICONV_LIB) : $(ICONV_TIMESTAMP)
467+
@REFRESH=0; \
468+
if [ ! -e ${ICONV_TIMESTAMP_INT} ] ; then \
469+
REFRESH=1; \
470+
fi; \
471+
if [ ! -e ${ICONV_LIB} ] ; then \
472+
REFRESH=1; \
473+
fi; \
474+
if [ ${ICONV_TIMESTAMP} -nt ${ICONV_TIMESTAMP_INT} ] ; then \
475+
REFRESH=1; \
476+
fi; \
477+
if [ $$REFRESH -ne 0 ] ; then \
478+
mkdir -p ${ICONV_DIR}; \
479+
export PATH=$$PATH:${SDKFOLDER}/platform-tools:${ANDROID_NDK}; \
480+
echo "changed timestamp for iconv detected building..."; \
481+
cd ${ICONV_DIR}; \
482+
./configure; \
483+
make; \
484+
export NDK_PROJECT_PATH=${ICONV_DIR}; \
485+
ndk-build NDEBUG=${NDEBUG} NDK_MODULE_PATH=${NDK_MODULE_PATH} \
486+
APP_PLATFORM=${APP_PLATFORM} APP_ABI=${TARGET_ABI} \
487+
TARGET_CFLAGS+="${TARGET_CFLAGS_ADDON}" \
488+
TARGET_LDFLAGS+="${TARGET_LDFLAGS_ADDON}" \
489+
TARGET_CXXFLAGS+="${TARGET_CXXFLAGS_ADDON}" || exit 1; \
490+
touch ${ICONV_TIMESTAMP}; \
491+
touch ${ICONV_TIMESTAMP_INT}; \
492+
else \
493+
echo "nothing to be done for iconv"; \
494+
fi
495+
496+
clean_iconv :
497+
$(RM) -rf ${ICONV_DIR}
498+
434499
#Note: Texturehack patch is required for gpu's not supporting color format
435500
# correctly. Known bad GPU:
436501
# -geforce on emulator
@@ -736,7 +801,7 @@ assets : $(ASSETS_TIMESTAMP)
736801
clean_assets :
737802
@$(RM) -r assets
738803

739-
apk: $(PATHCFGFILE) assets $(IRRLICHT_LIB) $(CURL_LIB) $(GMP_LIB) $(LEVELDB_TARGET) \
804+
apk: $(PATHCFGFILE) assets $(ICONV_LIB) $(IRRLICHT_LIB) $(CURL_LIB) $(GMP_LIB) $(LEVELDB_TARGET) \
740805
$(OPENAL_LIB) $(OGG_LIB) prep_srcdir $(ROOT)/jni/src/android_version.h \
741806
sqlite3_download
742807
@export NDEBUG=$$NDEBUG; $(MAKE) manifest; \
@@ -778,7 +843,7 @@ envpaths :
778843

779844
clean_all :
780845
@$(MAKE) clean_apk; \
781-
$(MAKE) clean_assets clean_irrlicht clean_leveldb clean_curl clean_openssl \
846+
$(MAKE) clean_assets clean_iconv clean_irrlicht clean_leveldb clean_curl clean_openssl \
782847
clean_openal clean_ogg clean_gmp clean_manifest; \
783848
sleep 1; \
784849
$(RM) -r gen libs obj deps bin Debug and_env

‎build/android/jni/Android.mk

+8-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ LOCAL_MODULE := freetype
2424
LOCAL_SRC_FILES := deps/freetype2-android/Android/obj/local/$(TARGET_ARCH_ABI)/libfreetype2-static.a
2525
include $(PREBUILT_STATIC_LIBRARY)
2626

27+
include $(CLEAR_VARS)
28+
LOCAL_MODULE := iconv
29+
LOCAL_SRC_FILES := deps/libiconv/obj/local/$(TARGET_ARCH_ABI)/libiconv.a
30+
include $(PREBUILT_STATIC_LIBRARY)
31+
2732
include $(CLEAR_VARS)
2833
LOCAL_MODULE := openal
2934
LOCAL_SRC_FILES := deps/openal-soft/libs/$(TARGET_LIBDIR)/libopenal.so
@@ -97,6 +102,7 @@ LOCAL_C_INCLUDES := \
97102
jni/src/json \
98103
jni/src/cguittfont \
99104
deps/irrlicht/include \
105+
deps/libiconv/include \
100106
deps/freetype2-android/include \
101107
deps/curl/include \
102108
deps/openal-soft/jni/OpenAL/include \
@@ -153,6 +159,7 @@ LOCAL_SRC_FILES := \
153159
jni/src/httpfetch.cpp \
154160
jni/src/hud.cpp \
155161
jni/src/imagefilters.cpp \
162+
jni/src/intlGUIEditBox.cpp \
156163
jni/src/inventory.cpp \
157164
jni/src/inventorymanager.cpp \
158165
jni/src/itemdef.cpp \
@@ -346,7 +353,7 @@ LOCAL_SRC_FILES += \
346353
LOCAL_SRC_FILES += jni/src/json/jsoncpp.cpp
347354

348355
LOCAL_SHARED_LIBRARIES := openal ogg vorbis gmp
349-
LOCAL_STATIC_LIBRARIES := Irrlicht freetype curl ssl crypto android_native_app_glue $(PROFILER_LIBS)
356+
LOCAL_STATIC_LIBRARIES := Irrlicht iconv freetype curl ssl crypto android_native_app_glue $(PROFILER_LIBS)
350357

351358
ifeq ($(HAVE_LEVELDB), 1)
352359
LOCAL_STATIC_LIBRARIES += LevelDB

‎build/android/libiconv_android.patch

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
--- a/libcharset/lib/localcharset.c 2015-06-10 11:55:25.933870724 +0200
2+
+++ b/libcharset/lib/localcharset.c 2015-06-10 11:55:39.578063493 +0200
3+
@@ -47,7 +47,7 @@
4+
5+
#if !defined WIN32_NATIVE
6+
# include <unistd.h>
7+
-# if HAVE_LANGINFO_CODESET
8+
+# if HAVE_LANGINFO_CODESET && !(defined __ANDROID__)
9+
# include <langinfo.h>
10+
# else
11+
# if 0 /* see comment below */
12+
@@ -124,7 +124,7 @@ get_charset_aliases (void)
13+
cp = charset_aliases;
14+
if (cp == NULL)
15+
{
16+
-#if !(defined DARWIN7 || defined VMS || defined WIN32_NATIVE || defined __CYGWIN__)
17+
+#if !(defined DARWIN7 || defined VMS || defined WIN32_NATIVE || defined __CYGWIN__ || defined __ANDROID__)
18+
const char *dir;
19+
const char *base = "charset.alias";
20+
char *file_name;
21+
@@ -338,6 +338,9 @@ get_charset_aliases (void)
22+
"CP54936" "\0" "GB18030" "\0"
23+
"CP65001" "\0" "UTF-8" "\0";
24+
# endif
25+
+# if defined __ANDROID__
26+
+ cp = "*" "\0" "UTF-8" "\0";
27+
+# endif
28+
#endif
29+
30+
charset_aliases = cp;
31+
@@ -361,7 +364,7 @@ locale_charset (void)
32+
const char *codeset;
33+
const char *aliases;
34+
35+
-#if !(defined WIN32_NATIVE || defined OS2)
36+
+#if !(defined WIN32_NATIVE || defined OS2 || defined __ANDROID__)
37+
38+
# if HAVE_LANGINFO_CODESET
39+
+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
From fe27aae178d65b06d5f4104158343b0d2d33e3f0 Mon Sep 17 00:00:00 2001
2+
From: Pierre Zurek <pierrezurek@gmail.com>
3+
Date: Sat, 2 Apr 2011 23:11:57 +0200
4+
Subject: [PATCH] Added Android.mk.
5+
6+
This makefile first executes the configure script, that will
7+
generate the config.h files necessary to build iconv.
8+
---
9+
Android.mk | 29 +++++++++++++++++++++++++++++
10+
1 file changed, 29 insertions(+)
11+
create mode 100644 Android.mk
12+
13+
diff --git a/jni/Android.mk b/jni/Android.mk
14+
new file mode 100644
15+
index 0000000..799b22d
16+
--- /dev/null
17+
+++ b/jni/Android.mk
18+
@@ -0,0 +1,32 @@
19+
+LOCAL_PATH := $(call my-dir)
20+
+include $(CLEAR_VARS)
21+
+
22+
+LOCAL_ARM_MODE := arm
23+
+
24+
+LOCAL_SRC_FILES := src/lib/iconv.c \
25+
+ src/libcharset/lib/localcharset.c \
26+
+ src/lib/relocatable.c
27+
+
28+
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/include \
29+
+ $(LOCAL_PATH)/src/libcharset \
30+
+ $(LOCAL_PATH)/src/libcharset/include
31+
+
32+
+LOCAL_CFLAGS := \
33+
+ -DLIBDIR="\"c\"" \
34+
+ -D_ANDROID \
35+
+ -DBUILDING_LIBCHARSET \
36+
+ -DBUILDING_LIBICONV \
37+
+ -DBUILDING_LIBICONV \
38+
+ -DIN_LIBRARY
39+
+
40+
+LOCAL_MODULE:= iconv
41+
+
42+
+$(info Configuring iconv...)
43+
+COMMAND := $(shell \
44+
+ export PATH=$(TOOLCHAIN_INSTALL_DIR)/bin:$$PATH; \
45+
+ cd $(LOCAL_PATH); \
46+
+ make distclean; \
47+
+ ./configure --host="arm-linux-androideabi")
48+
+$(info iconv configured.)
49+
+
50+
+include $(BUILD_STATIC_LIBRARY)
51+
+

‎build/android/libiconv_stdio.patch

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--- a/srclib/stdio.in.h 2011-08-07 15:42:06.000000000 +0200
2+
+++ b/srclib/stdio.in.h 2015-06-10 09:27:58.129056262 +0200
3+
@@ -695,7 +696,8 @@ _GL_CXXALIASWARN (gets);
4+
/* It is very rare that the developer ever has full control of stdin,
5+
so any use of gets warrants an unconditional warning. Assume it is
6+
always declared, since it is required by C89. */
7+
-_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
8+
+/*_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");*/
9+
+#define gets(a) fgets( a, sizeof(*(a)), stdin)
10+
#endif

‎src/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ set(client_SRCS
417417
guiVolumeChange.cpp
418418
hud.cpp
419419
imagefilters.cpp
420+
intlGUIEditBox.cpp
420421
keycode.cpp
421422
localplayer.cpp
422423
main.cpp

‎src/intlGUIEditBox.cpp

+1,509
Large diffs are not rendered by default.

‎src/intlGUIEditBox.h

+178
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
// Copyright (C) 2002-2013 Nikolaus Gebhardt
2+
// This file is part of the "Irrlicht Engine".
3+
// For conditions of distribution and use, see copyright notice in irrlicht.h
4+
5+
#ifndef __C_INTL_GUI_EDIT_BOX_H_INCLUDED__
6+
#define __C_INTL_GUI_EDIT_BOX_H_INCLUDED__
7+
8+
#include "IrrCompileConfig.h"
9+
//#ifdef _IRR_COMPILE_WITH_GUI_
10+
11+
#include "IGUIEditBox.h"
12+
#include "irrArray.h"
13+
#include "IOSOperator.h"
14+
15+
namespace irr
16+
{
17+
namespace gui
18+
{
19+
class intlGUIEditBox : public IGUIEditBox
20+
{
21+
public:
22+
23+
//! constructor
24+
intlGUIEditBox(const wchar_t* text, bool border, IGUIEnvironment* environment,
25+
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle);
26+
27+
//! destructor
28+
virtual ~intlGUIEditBox();
29+
30+
//! Sets another skin independent font.
31+
virtual void setOverrideFont(IGUIFont* font=0);
32+
33+
//! Gets the override font (if any)
34+
/** \return The override font (may be 0) */
35+
virtual IGUIFont* getOverrideFont() const;
36+
37+
//! Get the font which is used right now for drawing
38+
/** Currently this is the override font when one is set and the
39+
font of the active skin otherwise */
40+
virtual IGUIFont* getActiveFont() const;
41+
42+
//! Sets another color for the text.
43+
virtual void setOverrideColor(video::SColor color);
44+
45+
//! Gets the override color
46+
virtual video::SColor getOverrideColor() const;
47+
48+
//! Sets if the text should use the overide color or the
49+
//! color in the gui skin.
50+
virtual void enableOverrideColor(bool enable);
51+
52+
//! Checks if an override color is enabled
53+
/** \return true if the override color is enabled, false otherwise */
54+
virtual bool isOverrideColorEnabled(void) const;
55+
56+
//! Sets whether to draw the background
57+
virtual void setDrawBackground(bool draw);
58+
59+
//! Turns the border on or off
60+
virtual void setDrawBorder(bool border);
61+
62+
//! Enables or disables word wrap for using the edit box as multiline text editor.
63+
virtual void setWordWrap(bool enable);
64+
65+
//! Checks if word wrap is enabled
66+
//! \return true if word wrap is enabled, false otherwise
67+
virtual bool isWordWrapEnabled() const;
68+
69+
//! Enables or disables newlines.
70+
/** \param enable: If set to true, the EGET_EDITBOX_ENTER event will not be fired,
71+
instead a newline character will be inserted. */
72+
virtual void setMultiLine(bool enable);
73+
74+
//! Checks if multi line editing is enabled
75+
//! \return true if mult-line is enabled, false otherwise
76+
virtual bool isMultiLineEnabled() const;
77+
78+
//! Enables or disables automatic scrolling with cursor position
79+
//! \param enable: If set to true, the text will move around with the cursor position
80+
virtual void setAutoScroll(bool enable);
81+
82+
//! Checks to see if automatic scrolling is enabled
83+
//! \return true if automatic scrolling is enabled, false if not
84+
virtual bool isAutoScrollEnabled() const;
85+
86+
//! Gets the size area of the text in the edit box
87+
//! \return Returns the size in pixels of the text
88+
virtual core::dimension2du getTextDimension();
89+
90+
//! Sets text justification
91+
virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical);
92+
93+
//! called if an event happened.
94+
virtual bool OnEvent(const SEvent& event);
95+
96+
//! draws the element and its children
97+
virtual void draw();
98+
99+
//! Sets the new caption of this element.
100+
virtual void setText(const wchar_t* text);
101+
102+
//! Sets the maximum amount of characters which may be entered in the box.
103+
//! \param max: Maximum amount of characters. If 0, the character amount is
104+
//! infinity.
105+
virtual void setMax(u32 max);
106+
107+
//! Returns maximum amount of characters, previously set by setMax();
108+
virtual u32 getMax() const;
109+
110+
//! Sets whether the edit box is a password box. Setting this to true will
111+
/** disable MultiLine, WordWrap and the ability to copy with ctrl+c or ctrl+x
112+
\param passwordBox: true to enable password, false to disable
113+
\param passwordChar: the character that is displayed instead of letters */
114+
virtual void setPasswordBox(bool passwordBox, wchar_t passwordChar = L'*');
115+
116+
//! Returns true if the edit box is currently a password box.
117+
virtual bool isPasswordBox() const;
118+
119+
//! Updates the absolute position, splits text if required
120+
virtual void updateAbsolutePosition();
121+
122+
//! Writes attributes of the element.
123+
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
124+
125+
//! Reads attributes of the element
126+
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
127+
128+
protected:
129+
//! Breaks the single text line.
130+
void breakText();
131+
//! sets the area of the given line
132+
void setTextRect(s32 line);
133+
//! returns the line number that the cursor is on
134+
s32 getLineFromPos(s32 pos);
135+
//! adds a letter to the edit box
136+
void inputChar(wchar_t c);
137+
//! calculates the current scroll position
138+
void calculateScrollPos();
139+
//! send some gui event to parent
140+
void sendGuiEvent(EGUI_EVENT_TYPE type);
141+
//! set text markers
142+
void setTextMarkers(s32 begin, s32 end);
143+
144+
bool processKey(const SEvent& event);
145+
bool processMouse(const SEvent& event);
146+
s32 getCursorPos(s32 x, s32 y);
147+
148+
bool MouseMarking;
149+
bool Border;
150+
bool OverrideColorEnabled;
151+
s32 MarkBegin;
152+
s32 MarkEnd;
153+
154+
video::SColor OverrideColor;
155+
gui::IGUIFont *OverrideFont, *LastBreakFont;
156+
IOSOperator* Operator;
157+
158+
u32 BlinkStartTime;
159+
s32 CursorPos;
160+
s32 HScrollPos, VScrollPos; // scroll position in characters
161+
u32 Max;
162+
163+
bool WordWrap, MultiLine, AutoScroll, PasswordBox;
164+
wchar_t PasswordChar;
165+
EGUI_ALIGNMENT HAlign, VAlign;
166+
167+
core::array< core::stringw > BrokenText;
168+
core::array< s32 > BrokenTextPositions;
169+
170+
core::rect<s32> CurrentTextRect, FrameRect; // temporary values
171+
};
172+
173+
174+
} // end namespace gui
175+
} // end namespace irr
176+
177+
//#endif // _IRR_COMPILE_WITH_GUI_
178+
#endif // __C_GUI_EDIT_BOX_H_INCLUDED__

‎src/util/string.cpp

+94
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,103 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2929
#include <iomanip>
3030
#include <map>
3131

32+
#ifndef _WIN32
33+
#include <iconv.h>
34+
#else
35+
#define _WIN32_WINNT 0x0501
36+
#include <windows.h>
37+
#endif
38+
3239
static bool parseHexColorString(const std::string &value, video::SColor &color);
3340
static bool parseNamedColorString(const std::string &value, video::SColor &color);
3441

42+
#ifndef _WIN32
43+
size_t convert(const char *to, const char *from, char *outbuf,
44+
size_t outbuf_size, char *inbuf, size_t inbuf_size)
45+
{
46+
iconv_t cd = iconv_open(to, from);
47+
48+
#if defined(__FreeBSD__) || defined(__FreeBSD)
49+
const char *inbuf_ptr = inbuf;
50+
#else
51+
char *inbuf_ptr = inbuf;
52+
#endif
53+
54+
char *outbuf_ptr = outbuf;
55+
56+
size_t *inbuf_left_ptr = &inbuf_size;
57+
size_t *outbuf_left_ptr = &outbuf_size;
58+
59+
while (inbuf_size > 0)
60+
iconv(cd, &inbuf_ptr, inbuf_left_ptr, &outbuf_ptr, outbuf_left_ptr);
61+
62+
iconv_close(cd);
63+
return 0;
64+
}
65+
66+
std::wstring utf8_to_wide(const std::string &input)
67+
{
68+
size_t inbuf_size = input.length() + 1;
69+
// maximum possible size, every character is sizeof(wchar_t) bytes
70+
size_t outbuf_size = (input.length() + 1) * sizeof(wchar_t);
71+
72+
char *inbuf = new char[inbuf_size];
73+
memcpy(inbuf, input.c_str(), inbuf_size);
74+
char *outbuf = new char[outbuf_size];
75+
memset(outbuf, 0, outbuf_size);
76+
77+
convert("WCHAR_T", "UTF-8", outbuf, outbuf_size, inbuf, inbuf_size);
78+
std::wstring out((wchar_t*)outbuf);
79+
80+
delete[] inbuf;
81+
delete[] outbuf;
82+
83+
return out;
84+
}
85+
86+
std::string wide_to_utf8(const std::wstring &input)
87+
{
88+
size_t inbuf_size = (input.length() + 1) * sizeof(wchar_t);
89+
// maximum possible size: utf-8 encodes codepoints using 1 up to 6 bytes
90+
size_t outbuf_size = (input.length() + 1) * 6;
91+
92+
char *inbuf = new char[inbuf_size];
93+
memcpy(inbuf, input.c_str(), inbuf_size);
94+
char *outbuf = new char[outbuf_size];
95+
memset(outbuf, 0, outbuf_size);
96+
97+
convert("UTF-8", "WCHAR_T", outbuf, outbuf_size, inbuf, inbuf_size);
98+
std::string out(outbuf);
99+
100+
delete[] inbuf;
101+
delete[] outbuf;
102+
103+
return out;
104+
}
105+
#else
106+
std::wstring utf8_to_wide(const std::string &input)
107+
{
108+
size_t outbuf_size = input.size() + 1;
109+
wchar_t *outbuf = new wchar_t[outbuf_size];
110+
memset(outbuf, 0, outbuf_size * sizeof(wchar_t));
111+
MultiByteToWideChar(CP_UTF8, 0, input.c_str(), input.size(), outbuf, outbuf_size);
112+
std::wstring out(outbuf);
113+
delete[] outbuf;
114+
return out;
115+
}
116+
117+
std::string wide_to_utf8(const std::wstring &input)
118+
{
119+
size_t outbuf_size = (input.size() + 1) * 6;
120+
char *outbuf = new char[outbuf_size];
121+
memset(outbuf, 0, outbuf_size);
122+
WideCharToMultiByte(CP_UTF8, 0, input.c_str(), input.size(), outbuf, outbuf_size, NULL, NULL);
123+
std::string out(outbuf);
124+
delete[] outbuf;
125+
return out;
126+
}
127+
#endif
128+
35129

36130
// You must free the returned string!
37131
// The returned string is allocated using new

‎src/util/string.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,18 @@ struct FlagDesc {
3939
u32 flag;
4040
};
4141

42+
// try not to convert between wide/utf8 encodings; this can result in data loss
43+
// try to only convert between them when you need to input/output stuff via Irrlicht
44+
std::wstring utf8_to_wide(const std::string &input);
45+
std::string wide_to_utf8(const std::wstring &input);
46+
47+
// NEVER use those two functions unless you have a VERY GOOD reason to
48+
// they just convert between wide and multibyte encoding
49+
// multibyte encoding depends on current locale, this is no good, especially on Windows
50+
4251
// You must free the returned string!
4352
// The returned string is allocated using new
4453
wchar_t *narrow_to_wide_c(const char *str);
45-
4654
std::wstring narrow_to_wide(const std::string &mbs);
4755
std::string wide_to_narrow(const std::wstring &wcs);
4856

0 commit comments

Comments
 (0)
Please sign in to comment.