Attempt at using iconv. Fails miserably for me atm because gettext will only return latin-1 and not UTF-8 like I ask it
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@4412 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
6d779f9356
commit
11d864ae7c
@ -593,7 +593,16 @@ void IrrDriver::removeCameraSceneNode(scene::ICameraSceneNode *camera)
|
||||
*/
|
||||
video::ITexture *IrrDriver::getTexture(const std::string &filename)
|
||||
{
|
||||
return m_scene_manager->getVideoDriver()->getTexture(filename.c_str());
|
||||
video::ITexture* out = m_scene_manager->getVideoDriver()->getTexture(filename.c_str());
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (out == NULL)
|
||||
{
|
||||
printf("Put a breakpoint at line %s:%i to debug!\n", __FILE__, __LINE__ );
|
||||
}
|
||||
#endif
|
||||
|
||||
return out;
|
||||
} // getTexture
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -4,5 +4,5 @@ HEADER_SEARCH_PATHS = /usr/local/include /usr/include /usr/local/include/irrlich
|
||||
|
||||
OTHER_CFLAGS = -Wall -DHAVE_OGGVORBIS=1 -DHAS_SOCKLEN_T -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAS_POLL=1 -DHAS_FCNTL=1 -DHAS_INET_PTON=1 -DHAS_INET_NTOP=1 -DHAS_MSGHDR_FLAGS=1 -DENABLE_NLS=1 -DHAVE_GETTEXT=1 -DHAVE_GLUT=1 -DHAVE_IRRLICHT=1 -DPACKAGE="\"supertuxkart\"" -D__MACOSX__=1 -DHAVE_RTT=1
|
||||
|
||||
OTHER_LDFLAGS = -lirrlicht
|
||||
OTHER_LDFLAGS = -lirrlicht -liconv
|
||||
LIBRARY_SEARCH_PATHS = /usr/local/lib /usr/lib
|
||||
|
@ -26,14 +26,267 @@
|
||||
#include "irrlicht.h"
|
||||
|
||||
#include "utils/translation.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
|
||||
#include <locale.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <iconv.h>
|
||||
#include <stdlib.h>
|
||||
#include <iostream>
|
||||
|
||||
enum CONVERT_TO
|
||||
{
|
||||
UTF_16 = 0,
|
||||
UTF_32 = 1
|
||||
};
|
||||
const char* CODE_NAMES[] =
|
||||
{
|
||||
"UTF-16",
|
||||
"UTF-32"
|
||||
};
|
||||
|
||||
/*
|
||||
The code below is based on Solaris' man pages code. No license was specified, but I assume that
|
||||
they wrote man pages for people to use them...
|
||||
*/
|
||||
|
||||
/*
|
||||
* For state-dependent encodings, changes the state of the conversion
|
||||
* descriptor to initial shift state. Also, outputs the byte sequence
|
||||
* to change the state to initial state.
|
||||
* This code is assuming the iconv call for initializing the state
|
||||
* won't fail due to lack of space in the output buffer.
|
||||
*/
|
||||
#define INIT_SHIFT_STATE(cd, fptr, ileft, tptr, oleft) \
|
||||
{ \
|
||||
fptr = NULL; \
|
||||
ileft = 0; \
|
||||
tptr = to; \
|
||||
oleft = BUFSIZ; \
|
||||
(void) iconv(cd, (&fptr), &ileft, &tptr, &oleft); \
|
||||
}
|
||||
|
||||
bool convertToEncoding(const char* from, char* to, const int BUF_SIZE, const char* from_code, CONVERT_TO to_code)
|
||||
{
|
||||
iconv_t cd;
|
||||
char *tptr;
|
||||
const char *fptr;
|
||||
size_t ileft, oleft, ret;
|
||||
|
||||
cd = iconv_open(CODE_NAMES[to_code], from_code);
|
||||
if (cd == (iconv_t)-1)
|
||||
{
|
||||
// failed
|
||||
fprintf(stderr, "iconv_open(%s, %s) failed\n", CODE_NAMES[to_code], from_code);
|
||||
return false;
|
||||
}
|
||||
|
||||
ileft = strlen(from);
|
||||
|
||||
|
||||
fptr = from;
|
||||
for (;;)
|
||||
{
|
||||
tptr = to;
|
||||
oleft = BUFSIZ;
|
||||
|
||||
ret = iconv(cd, (&fptr), &ileft, &tptr, &oleft);
|
||||
if (ret != (size_t)-1)
|
||||
{
|
||||
// iconv succeeded
|
||||
|
||||
// Manually add ending '\0'
|
||||
const int curr_offset = BUFSIZ - oleft;
|
||||
|
||||
to[curr_offset] = '\0';
|
||||
|
||||
if (curr_offset+1 >= BUFSIZ)
|
||||
{
|
||||
fprintf(stderr, "iconv failed : error while adding '\\0' character (Output buffer not big enough) \n");
|
||||
return false;
|
||||
}
|
||||
to[curr_offset+1] = '\0';
|
||||
|
||||
// UTF-32 needs 2 more bytes at 0
|
||||
if (to_code == UTF_32)
|
||||
{
|
||||
to[curr_offset+2] = '\0';
|
||||
|
||||
if (curr_offset+3 >= BUFSIZ)
|
||||
{
|
||||
fprintf(stderr, "iconv failed : error while adding '\\0' character (Output buffer not big enough) \n");
|
||||
return false;
|
||||
}
|
||||
to[curr_offset+3] = '\0';
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// iconv failed
|
||||
if (errno == EINVAL)
|
||||
{
|
||||
fprintf(stderr, "iconv failed : EINVAL error (Incomplete character or shift sequence) \n");
|
||||
break;
|
||||
}
|
||||
else if (errno == E2BIG)
|
||||
{
|
||||
// Lack of space in output buffer
|
||||
fprintf(stderr, "iconv failed : E2BIG error (Output buffer not big enough) \n");
|
||||
|
||||
std::cout << "So far, I have :\n";
|
||||
for (int i=0; i<BUF_SIZE; i++)
|
||||
{
|
||||
std::cout << " " << to[i] << " (" << (unsigned int)to[i] << ")\n";
|
||||
}
|
||||
|
||||
//Outputs converted characters
|
||||
//fwrite(to, 1, BUFSIZ - oleft, stdout);
|
||||
|
||||
// Tries to convert remaining characters in
|
||||
// input buffer with emptied output buffer
|
||||
return false;
|
||||
}
|
||||
else if (errno == EILSEQ)
|
||||
{
|
||||
|
||||
fprintf(stderr, "iconv failed : EILSEQ error (Illegal character or shift sequence) \n");
|
||||
|
||||
std::cout << "Original :\n";
|
||||
for (int i=0; ; i++)
|
||||
{
|
||||
std::cout << " " << from[i] << " (" << std::hex << (unsigned int)from[i] << ")\n";
|
||||
if (from[i] == 0) break;
|
||||
}
|
||||
|
||||
// Outputs converted characters
|
||||
//fwrite(to, 1, BUFSIZ - oleft, stdout);
|
||||
|
||||
// Initializes the conversion descriptor and
|
||||
// outputs the sequence to change the state to
|
||||
// initial state.
|
||||
INIT_SHIFT_STATE(cd, fptr, ileft, tptr, oleft);
|
||||
iconv_close(cd);
|
||||
|
||||
return false;
|
||||
}
|
||||
else if (errno == EBADF)
|
||||
{
|
||||
fprintf(stderr, "iconv failed : EBADF error (invalid conversion description) \n");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "iconv failed : other error\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes the conversion descriptor and outputs
|
||||
* the sequence to change the state to initial state.
|
||||
*/
|
||||
INIT_SHIFT_STATE(cd, fptr, ileft, tptr, oleft);
|
||||
|
||||
iconv_close(cd);
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: use a type that works on all platforms
|
||||
typedef unsigned int uint32;
|
||||
|
||||
/**
|
||||
* \param input_text Some UTF-8 text
|
||||
* \return The appropriate representation of this text in the platform's native wchar_t type, or
|
||||
* NULL if conversion failed (in this case a message will be printed to the console)
|
||||
*/
|
||||
wchar_t* utf8_to_wchar_t(const char* input_text)
|
||||
{
|
||||
const int buffer_size = 2048; // let's arbitrarly support 2048 chars
|
||||
const int byte_size = buffer_size*sizeof(wchar_t); // we need more space if the system uses UTF-32
|
||||
|
||||
static char output_buffer[byte_size];
|
||||
static wchar_t wide_form[buffer_size*2]; // Allow for some surrogate pairs
|
||||
|
||||
|
||||
if (sizeof(wchar_t) == 2)
|
||||
{
|
||||
// UTF-16
|
||||
if (!convertToEncoding(input_text, output_buffer, byte_size, "UTF-8", UTF_16)) return NULL;
|
||||
|
||||
return ((wchar_t*)output_buffer)+1; // Skip initial Unicode header
|
||||
|
||||
|
||||
for (int n=0; true; n+=2)
|
||||
{
|
||||
wide_form[n/2] = (uint32(output_buffer[n ]) << 8) |
|
||||
uint32(output_buffer[n+1] );
|
||||
|
||||
//std::cout << "char : <" << to[n] << ", " << to[n+1] << ">; wide char = " << std::hex << (uint32)wide_form[n/2] << "\n";
|
||||
|
||||
if (wide_form[n/2] == 0) break;
|
||||
}
|
||||
|
||||
return &wide_form[1];
|
||||
|
||||
}
|
||||
else if (sizeof(wchar_t) == 4)
|
||||
{
|
||||
// UTF-32
|
||||
if (!convertToEncoding(input_text, output_buffer, byte_size, "UTF-8", UTF_32)) return NULL;
|
||||
|
||||
//return ((wchar_t*)output_buffer)+1; // Skip initial Unicode header
|
||||
|
||||
|
||||
for (int n=0; true; n+=4)
|
||||
{
|
||||
wide_form[n/4] = (uint32(output_buffer[ n ]) << 24) |
|
||||
(uint32(output_buffer[n+1]) << 16) |
|
||||
(uint32(output_buffer[n+2]) << 8 ) |
|
||||
uint32(output_buffer[n+3]) ;
|
||||
|
||||
//std::cout << "char : <" << to[n] << ", " << to[n+1] << ", " << to[n+2] << ", " << to[n+3]
|
||||
// << ">; wide char = " << std::hex << (uint32)wide_form[n/4] << "\n";
|
||||
|
||||
if (wide_form[n/4] == 0) break;
|
||||
}
|
||||
return &wide_form[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "ERROR : Unknown wchar_t size!\n";
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
int main()
|
||||
{
|
||||
const char* from = "Some text in plain ASCII. z";
|
||||
|
||||
|
||||
wchar_t* out_ptr = utf8_to_wchar_t(from);
|
||||
|
||||
if (out_ptr == NULL)
|
||||
{
|
||||
std::cout << "ERROR!\n";
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::wcout << L"Converted text : <" << out_ptr << L">\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
#include "io/file_manager.hpp"
|
||||
|
||||
Translations* translations=NULL;
|
||||
|
||||
Translations::Translations() {
|
||||
Translations::Translations()
|
||||
{
|
||||
#ifdef HAVE_GETTEXT
|
||||
// LC_ALL does not work, sscanf will then not always be able
|
||||
// to scan for example: s=-1.1,-2.3,-3.3 correctly, which is
|
||||
@ -45,24 +298,41 @@ Translations::Translations() {
|
||||
setlocale(LC_MESSAGES, "");
|
||||
#endif
|
||||
bindtextdomain (PACKAGE, file_manager->getTranslationDir().c_str());
|
||||
//bind_textdomain_codeset(PACKAGE, "UTF-8");
|
||||
bind_textdomain_codeset(PACKAGE, "iso-8859-1");
|
||||
bind_textdomain_codeset(PACKAGE, "UTF-8");
|
||||
//bind_textdomain_codeset(PACKAGE, "iso-8859-1");
|
||||
textdomain (PACKAGE);
|
||||
#endif
|
||||
|
||||
} // Translations
|
||||
|
||||
const int BUFFER_SIZE = 512;
|
||||
wchar_t out_buffer[BUFFER_SIZE];
|
||||
//const int BUFFER_SIZE = 512;
|
||||
//wchar_t out_buffer[BUFFER_SIZE];
|
||||
|
||||
wchar_t* w_gettext(const char* original)
|
||||
{
|
||||
if (original[0] == '\0') return L"";
|
||||
|
||||
std::cout << "Translating " << original << "\n";
|
||||
|
||||
#if ENABLE_NLS
|
||||
const char* original_t = gettext(original);
|
||||
#else
|
||||
const char* original_t = original;
|
||||
#endif
|
||||
|
||||
wchar_t* out_ptr = utf8_to_wchar_t(original_t);
|
||||
|
||||
if (out_ptr == NULL)
|
||||
{
|
||||
std::cerr << " ERROR in w_gettext! could not be converted to wchar_t.\n";
|
||||
}
|
||||
|
||||
std::wcout << L" translation : " << out_ptr << std::endl;
|
||||
|
||||
return out_ptr;
|
||||
|
||||
|
||||
/*
|
||||
int index = 0;
|
||||
for (const char* c=original_t; *c != 0; c++)
|
||||
{
|
||||
@ -74,4 +344,5 @@ wchar_t* w_gettext(const char* original)
|
||||
//mbstowcs(out_buffer, original_t, BUFFER_SIZE);
|
||||
|
||||
return out_buffer;
|
||||
*/
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user