[Freeciv-Dev] (PR#9722) fix charset problems in 1.14
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://rt.freeciv.org/Ticket/Display.html?id=9722 >
This patch is an update of the PR#1824 patch, but for the 1.14 branch.
The main purpose is to get some more people to test it out. I believe
it should work just like the 1824 patch, but it's possible I made an
error in removing the "old" charset fixes.
To test: put the fciconv.[ch] files in common/, apply the patch, and
rerun autogen.sh.
jason
? fciconv-1.14.diff
? common/fciconv.c
? common/fciconv.h
Index: client/civclient.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/civclient.c,v
retrieving revision 1.149
diff -u -r1.149 civclient.c
--- client/civclient.c 9 Oct 2002 13:39:47 -0000 1.149
+++ client/civclient.c 17 Aug 2004 19:24:23 -0000
@@ -32,6 +32,8 @@
#endif
#include "capstr.h"
+#include "dataio.h"
+#include "fciconv.h"
#include "fcintl.h"
#include "game.h"
#include "idex.h"
@@ -105,6 +107,62 @@
static void client_remove_all_cli_conn(void);
/**************************************************************************
+ Convert a text string from the internal to the data encoding, when it
+ is written to the network.
+**************************************************************************/
+static unsigned char *put_conv(const char *src, size_t *length)
+{
+ char *out = internal_to_data_string_malloc(src);
+
+ if (out) {
+ *length = strlen(out);
+ return out;
+ } else {
+ *length = 0;
+ return NULL;
+ }
+}
+
+/**************************************************************************
+ Convert a text string from the data to the internal encoding when it is
+ first read from the network. Returns FALSE if the destination isn't
+ large enough or the source was bad.
+**************************************************************************/
+static bool get_conv(char *dst, size_t ndst,
+ const unsigned char *src, size_t nsrc)
+{
+ char *out = data_to_internal_string_malloc(src);
+ bool ret = TRUE;
+ size_t len;
+
+ if (!out) {
+ dst[0] = '\0';
+ return FALSE;
+ }
+
+ len = strlen(out);
+ if (ndst > 0 && len >= ndst) {
+ ret = FALSE;
+ len = ndst - 1;
+ }
+
+ memcpy(dst, out, len);
+ dst[len] = '\0';
+ free(out);
+
+ return ret;
+}
+
+/**************************************************************************
+ Set up charsets for the client.
+**************************************************************************/
+static void charsets_init(void)
+{
+ dio_set_put_conv_callback(put_conv);
+ dio_set_get_conv_callback(get_conv);
+}
+
+/**************************************************************************
...
**************************************************************************/
int main(int argc, char *argv[])
@@ -192,6 +250,7 @@
/* initialization */
ui_init();
+ charsets_init();
my_init_network();
init_messages_where();
init_city_report_data();
Index: client/gui-gtk/gui_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/gui_main.c,v
retrieving revision 1.115.2.1
diff -u -r1.115.2.1 gui_main.c
--- client/gui-gtk/gui_main.c 15 Oct 2002 21:57:37 -0000 1.115.2.1
+++ client/gui-gtk/gui_main.c 17 Aug 2004 19:24:23 -0000
@@ -31,6 +31,7 @@
#include <gtk/gtkinvisible.h>
#include <gdk/gdkkeysyms.h>
+#include "fciconv.h"
#include "fcintl.h"
#include "game.h"
#include "government.h"
@@ -727,6 +728,7 @@
**************************************************************************/
void ui_init(void)
{
+ init_character_encodings(NULL);
}
/**************************************************************************
Index: client/gui-gtk-2.0/connectdlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/connectdlg.c,v
retrieving revision 1.15.2.6
diff -u -r1.15.2.6 connectdlg.c
--- client/gui-gtk-2.0/connectdlg.c 18 May 2003 16:20:41 -0000 1.15.2.6
+++ client/gui-gtk-2.0/connectdlg.c 17 Aug 2004 19:24:23 -0000
@@ -319,12 +319,12 @@
GtkTreeIter it;
int i;
- row[0] = ntoh_str(pserver->name);
- row[1] = ntoh_str(pserver->port);
- row[2] = ntoh_str(pserver->version);
+ row[0] = pserver->name;
+ row[1] = pserver->port;
+ row[2] = pserver->version;
row[3] = _(pserver->status);
- row[4] = ntoh_str(pserver->players);
- row[5] = ntoh_str(pserver->metastring);
+ row[4] = pserver->players;
+ row[5] = pserver->metastring;
gtk_list_store_append(store, &it);
gtk_list_store_set(store, &it,
Index: client/gui-gtk-2.0/gui_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/gui_main.c,v
retrieving revision 1.27.2.10
diff -u -r1.27.2.10 gui_main.c
--- client/gui-gtk-2.0/gui_main.c 26 Mar 2004 19:44:08 -0000
1.27.2.10
+++ client/gui-gtk-2.0/gui_main.c 17 Aug 2004 19:24:24 -0000
@@ -32,6 +32,7 @@
#include <gdk/gdkkeysyms.h>
#include "dataio.h"
+#include "fciconv.h"
#include "fcintl.h"
#include "game.h"
#include "government.h"
@@ -157,107 +158,13 @@
gpointer data);
static gint timer_callback(gpointer data);
-static char *network_charset = NULL;
-
-
-/**************************************************************************
-Network string charset conversion functions.
-**************************************************************************/
-gchar *ntoh_str(const gchar *netstr)
-{
- return g_convert(netstr, -1, "UTF-8", network_charset, NULL, NULL, NULL);
-}
-
-/**************************************************************************
-...
-**************************************************************************/
-static unsigned char *put_conv(const char *src, size_t *length)
-{
- gsize len;
- gchar *out =
- g_convert(src, -1, network_charset, "UTF-8", NULL, &len, NULL);
-
- if (out) {
- unsigned char *dst = fc_malloc(len + 1);
-
- memcpy(dst, out, len);
- g_free(out);
- dst[len] = '\0';
-
- *length = len;
- return dst;
- } else {
- *length = 0;
- return NULL;
- }
-}
-
-/**************************************************************************
- Returns FALSE if the destination isn't large enough or the source was
- bad.
-**************************************************************************/
-static bool get_conv(char *dst, size_t ndst, const unsigned char *src,
- size_t nsrc)
-{
- gsize len; /* length to copy, not including null */
- gchar *out = g_convert(src, nsrc, "UTF-8", network_charset, NULL, &len,
NULL);
- bool ret = TRUE;
-
- if (!out) {
- dst[0] = '\0';
- return FALSE;
- }
-
- if (ndst > 0 && len >= ndst) {
- ret = FALSE;
- len = ndst - 1;
- }
-
- memcpy(dst, out, len);
- dst[len] = '\0';
- g_free(out);
-
- return ret;
-}
-
-/**************************************************************************
-Local log callback functions.
-**************************************************************************/
-static void fprintf_utf8(FILE *stream, const char *format, ...)
-{
- va_list ap;
- const gchar *charset;
- gchar *s;
-
- va_start(ap, format);
- s = g_strdup_vprintf(format, ap);
- va_end(ap);
-
- if (!g_get_charset(&charset)) {
- GError *error = NULL;
- gchar *s2;
-
- s2 = g_convert(s, -1, charset, "UTF-8", NULL, NULL, &error);
-
- if (error) {
- fprintf(stream, "fprintf_utf8: %s\n", error->message);
- g_error_free(error);
- } else {
- g_free(s);
- s = s2;
- }
- }
- fputs(s, stream);
- fflush(stream);
- g_free(s);
-}
/**************************************************************************
...
**************************************************************************/
static void log_callback_utf8(int level, const char *message)
{
- fprintf_utf8(stderr, "%d: %s\n", level, message);
+ fc_fprintf(stderr, "%d: %s\n", level, message);
}
/**************************************************************************
@@ -267,7 +174,7 @@
static void print_usage(const char *argv0)
{
/* add client-specific usage information here */
- fprintf_utf8(stderr, _("Report bugs to <%s>.\n"), BUG_EMAIL_ADDRESS);
+ fc_fprintf(stderr, _("Report bugs to <%s>.\n"), BUG_EMAIL_ADDRESS);
}
/**************************************************************************
@@ -880,33 +787,11 @@
void ui_init(void)
{
gchar *s;
- char *net_charset;
-#ifdef ENABLE_NLS
- bind_textdomain_codeset(PACKAGE, "UTF-8");
-#endif
+ init_character_encodings("UTF-8");
log_set_callback(log_callback_utf8);
- /* set networking string conversion callbacks */
- if ((net_charset = getenv("FREECIV_NETWORK_ENCODING"))) {
- network_charset = mystrdup(net_charset);
- } else {
- const gchar *charset;
-
- g_get_charset(&charset);
-
- if (!strcmp(charset, "ANSI_X3.4-1968")
- || !strcmp(charset, "ASCII")) {
- charset = "ISO-8859-1";
- }
-
- network_charset = mystrdup(charset);
- }
-
- dio_set_put_conv_callback(put_conv);
- dio_set_get_conv_callback(get_conv);
-
/* convert inputs */
s = g_locale_to_utf8(player_name, -1, NULL, NULL, NULL);
sz_strlcpy(player_name, s);
Index: client/gui-win32/gui_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-win32/gui_main.c,v
retrieving revision 1.16.2.1
diff -u -r1.16.2.1 gui_main.c
--- client/gui-win32/gui_main.c 15 Oct 2002 16:56:19 -0000 1.16.2.1
+++ client/gui-win32/gui_main.c 17 Aug 2004 19:24:24 -0000
@@ -19,6 +19,7 @@
#include <commctrl.h>
#include <richedit.h>
+#include "fciconv.h"
#include "fcintl.h"
#include "game.h"
#include "log.h"
@@ -512,6 +513,7 @@
**************************************************************************/
void ui_init(void)
{
+ init_character_encodings(NULL);
}
/**************************************************************************
Index: client/gui-xaw/gui_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-xaw/gui_main.c,v
retrieving revision 1.71
diff -u -r1.71 gui_main.c
--- client/gui-xaw/gui_main.c 24 Aug 2002 14:37:48 -0000 1.71
+++ client/gui-xaw/gui_main.c 17 Aug 2004 19:24:24 -0000
@@ -36,6 +36,7 @@
#include "canvas.h"
#include "pixcomm.h"
+#include "fciconv.h"
#include "fcintl.h"
#include "game.h"
#include "government.h"
@@ -264,6 +265,7 @@
**************************************************************************/
void ui_init(void)
{
+ init_character_encodings(NULL);
}
/**************************************************************************
Index: common/Makefile.am
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/Makefile.am,v
retrieving revision 1.41
diff -u -r1.41 Makefile.am
--- common/Makefile.am 9 Oct 2002 20:54:20 -0000 1.41
+++ common/Makefile.am 17 Aug 2004 19:24:24 -0000
@@ -25,6 +25,8 @@
diptreaty.c \
diptreaty.h \
events.h \
+ fciconv.c \
+ fciconv.h \
fcintl.c \
fcintl.h \
game.c \
Index: common/log.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/Attic/log.c,v
retrieving revision 1.39.2.1
diff -u -r1.39.2.1 log.c
--- common/log.c 13 Nov 2002 18:47:21 -0000 1.39.2.1
+++ common/log.c 17 Aug 2004 19:24:24 -0000
@@ -18,6 +18,7 @@
#include <stdarg.h>
#include <string.h>
+#include "fciconv.h"
#include "fcintl.h"
#include "mem.h"
#include "shared.h"
@@ -79,16 +80,16 @@
}
if (n == 0) {
if (sscanf(level_str, "%d", &level) != 1) {
- fprintf(stderr, _("Bad log level \"%s\".\n"), level_str);
+ fc_fprintf(stderr, _("Bad log level \"%s\".\n"), level_str);
return -1;
}
if (level >= LOG_FATAL && level <= max_level) {
return level;
} else {
- fprintf(stderr, _("Bad log level %d in \"%s\".\n"), level, level_str);
+ fc_fprintf(stderr, _("Bad log level %d in \"%s\".\n"), level, level_str);
if (level == LOG_DEBUG && max_level < LOG_DEBUG) {
- fprintf(stderr, _("Freeciv must be compiled with the DEBUG flag"
- " to use debug level %d.\n"), LOG_DEBUG);
+ fc_fprintf(stderr, _("Freeciv must be compiled with the DEBUG flag"
+ " to use debug level %d.\n"), LOG_DEBUG);
}
return -1;
}
@@ -98,12 +99,13 @@
if (c[0] == ('0' + LOG_DEBUG) && c[1] == ':') {
level = LOG_DEBUG;
if (max_level < LOG_DEBUG) {
- fprintf(stderr, _("Freeciv must be compiled with the DEBUG flag"
- " to use debug level %d.\n"), LOG_DEBUG);
+ fc_fprintf(stderr, _("Freeciv must be compiled with the DEBUG flag"
+ " to use debug level %d.\n"), LOG_DEBUG);
return -1;
}
} else {
- fprintf(stderr, _("Badly formed log level argument \"%s\".\n"), level_str);
+ fc_fprintf(stderr, _("Badly formed log level argument \"%s\".\n"),
+ level_str);
return -1;
}
logd_num_files = n;
@@ -114,7 +116,8 @@
tok = strtok(dup, ":");
if (!tok) {
- fprintf(stderr, _("Badly formed log level argument \"%s\".\n"), level_str);
+ fc_fprintf(stderr, _("Badly formed log level argument \"%s\".\n"),
+ level_str);
level = -1;
goto out;
}
@@ -131,20 +134,20 @@
if (d && *pc != '\0' && d[1] != '\0') {
d[0] = '\0';
if (sscanf(pc, "%d", &logd_files[i].min) != 1) {
- fprintf(stderr, _("Not an integer: '%s'\n"), pc);
+ fc_fprintf(stderr, _("Not an integer: '%s'\n"), pc);
level = -1;
goto out;
}
if (sscanf(d + 1, "%d", &logd_files[i].max) != 1) {
- fprintf(stderr, _("Not an integer: '%s'\n"), d + 1);
+ fc_fprintf(stderr, _("Not an integer: '%s'\n"), d + 1);
level = -1;
goto out;
}
}
}
if(strlen(tok)==0) {
- fprintf(stderr, _("Empty filename in log level argument \"%s\".\n"),
- level_str);
+ fc_fprintf(stderr, _("Empty filename in log level argument \"%s\".\n"),
+ level_str);
level = -1;
goto out;
}
@@ -154,7 +157,8 @@
} while(tok);
if (i!=logd_num_files) {
- fprintf(stderr, _("Badly formed log level argument \"%s\".\n"), level_str);
+ fc_fprintf(stderr, _("Badly formed log level argument \"%s\".\n"),
+ level_str);
level = -1;
goto out;
}
@@ -259,7 +263,7 @@
if(log_filename) {
if(!(fs=fopen(log_filename, "a"))) {
- fprintf(stderr, _("Couldn't open logfile: %s for appending.\n"),
+ fc_fprintf(stderr, _("Couldn't open logfile: %s for appending.\n"),
log_filename);
exit(EXIT_FAILURE);
}
Index: common/shared.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/Attic/shared.c,v
retrieving revision 1.92.2.8
diff -u -r1.92.2.8 shared.c
--- common/shared.c 6 Jan 2004 07:14:46 -0000 1.92.2.8
+++ common/shared.c 17 Aug 2004 19:24:24 -0000
@@ -28,16 +28,6 @@
#include <sys/types.h>
#include <sys/stat.h>
-#ifdef HAVE_ICONV
-#include <iconv.h>
-#ifdef HAVE_LIBCHARSET
-#include <libcharset.h>
-#else
-#ifdef HAVE_LANGINFO_CODESET
-#include <langinfo.h>
-#endif
-#endif
-#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -1235,136 +1225,3 @@
}
return FALSE;
}
-
-#ifdef HAVE_ICONV
-/***************************************************************************
- Convert the text. This assumes 'from' is an 8-bit charset.
-***************************************************************************/
-static char *convert_string_malloc(const char *text,
- const char *from, const char *to)
-{
- iconv_t cd;
- size_t from_len = strlen(text) + 1, to_len = from_len;
- char *result;
-
- cd = iconv_open(to, from);
- if (cd == (iconv_t) (-1)) {
- freelog(LOG_ERROR,
- _("String conversion from %s not possible. You may\n"
- "want to set your local encoding manually by setting\n"
- "the environment variable $FREECIV_LOCAL_ENCODING."
- "Proceeding anyway..."),
- from);
- return mystrdup(text); /* The best we can do? */
- }
-
- do {
- size_t flen = from_len, tlen = to_len, res;
- const char *mytext = text;
- char *myresult;
-
- if (to_len > 1000000) {
- /* Avoid unterminated loop. */
- /* NOTE: same as error message above. */
- freelog(LOG_ERROR,
- _("String conversion from %s not possible. You may\n"
- "want to set your local encoding manually by setting\n"
- "the environment variable $FREECIV_LOCAL_ENCODING."
- "Proceeding anyway..."),
- from);
- iconv_close(cd);
- return mystrdup(text);
- }
-
- result = fc_malloc(to_len);
-
- myresult = result;
-
- /* Since we may do multiple translations, we may need to reset iconv
- * in between. */
- iconv(cd, NULL, NULL, NULL, NULL);
-
- res = iconv(cd, (ICONV_CONST char **)&mytext, &flen, &myresult, &tlen);
- if (res == (size_t) (-1)) {
- if (errno != E2BIG) {
- /* Invalid input. */
- freelog(LOG_ERROR,
- _("The string '%s' is not valid: %s. Ruleset files must\n"
- "be encoded as %s; you can change this by setting\n"
- "$FREECIV_DATA_ENCODING."),
- text, strerror(errno), from);
- free(result);
- iconv_close(cd);
- return mystrdup(text); /* The best we can do? */
- }
- } else {
- /* Success. */
- iconv_close(cd);
-
- /* There may be wasted space here. But we don't want to call
- * mystrdup on result since it might not be in an 8-bit charset. */
- return result;
- }
-
- /* Not enough space; try again. */
- free(result);
- to_len *= 2;
- } while (TRUE);
-}
-#endif
-
-/***************************************************************************
- We convert from the charset used by the rulesets into the local encoding.
-***************************************************************************/
-char *convert_data_string_malloc(const char *text)
-{
-#ifdef HAVE_ICONV
- char *local_encoding, *data_encoding;
- char target[128];
-
- data_encoding = getenv("FREECIV_DATA_ENCODING");
- if (!data_encoding) {
- /* Currently the rulesets are in latin1 (ISO-8859-1). */
- data_encoding = "ISO-8859-1";
- }
-
- local_encoding = getenv("FREECIV_LOCAL_ENCODING");
- if (!local_encoding) {
-#ifdef HAVE_LIBCHARSET
- local_encoding = locale_charset();
-#else
-#ifdef HAVE_LANGINFO_CODESET
- local_encoding = nl_langinfo(CODESET);
-#else
- local_encoding = "";
-#endif
-#endif
- if (strcasecmp(local_encoding, "ANSI_X3.4-1968") == 0
- || strcasecmp(local_encoding, "ASCII") == 0) {
- /* HACK: Use latin1 instead of ascii. */
- local_encoding = "ISO-8859-1";
- }
- my_snprintf(target, sizeof(target), "%s//TRANSLIT", local_encoding);
- local_encoding = target;
- }
-
- return convert_string_malloc(text, data_encoding, local_encoding);
-#else
-/* Don't expect that win32 users install iconv on their own, especially
- * not from http://gnu.org/ in source form... */
-#ifndef WIN32_NATIVE
- static bool only_give_this_damn_warning_once = FALSE;
-
- if (!only_give_this_damn_warning_once) {
- only_give_this_damn_warning_once = TRUE;
-
- freelog(LOG_ERROR,
- _("You are running Freeciv without using iconv. Unless\n"
- "you are using the latin1 character set, some characters\n"
- "may not be displayed properly. You can download iconv\n"
- "at http://gnu.org/."));
- }
-#endif
- return mystrdup(text);
-#endif
-}
Index: common/shared.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/Attic/shared.h,v
retrieving revision 1.104.2.1
diff -u -r1.104.2.1 shared.h
--- common/shared.h 4 Feb 2003 18:15:48 -0000 1.104.2.1
+++ common/shared.h 17 Aug 2004 19:24:24 -0000
@@ -178,6 +178,4 @@
const char *freeciv_motto(void);
-char *convert_data_string_malloc(const char *text);
-
#endif /* FC__SHARED_H */
Index: server/ruleset.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/ruleset.c,v
retrieving revision 1.120.2.3
diff -u -r1.120.2.3 ruleset.c
--- server/ruleset.c 14 Jul 2004 18:53:13 -0000 1.120.2.3
+++ server/ruleset.c 17 Aug 2004 19:24:25 -0000
@@ -1951,7 +1951,7 @@
} /* if (!next) */
} /* if (name) */
remove_leading_trailing_spaces(cities[j]);
- city_names[j].name = convert_data_string_malloc(cities[j]);
+ city_names[j].name = mystrdup(cities[j]);
if (check_name(city_names[j].name)) {
/* The ruleset contains a name that is too long. This shouldn't
happen - if it does, the author should get immediate feedback */
@@ -2003,7 +2003,7 @@
}
pl->leader_count = dim;
for(j = 0; j < dim; j++) {
- pl->leader_name[j] = convert_data_string_malloc(leaders[j]);
+ pl->leader_name[j] = mystrdup(leaders[j]);
if (check_name(leaders[j])) {
pl->leader_name[j][MAX_LEN_NAME - 1] = 0;
}
Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.97.2.2
diff -u -r1.97.2.2 srv_main.c
--- server/srv_main.c 12 Oct 2003 11:04:55 -0000 1.97.2.2
+++ server/srv_main.c 17 Aug 2004 19:24:26 -0000
@@ -47,6 +47,7 @@
#include "capstr.h"
#include "city.h"
#include "events.h"
+#include "fciconv.h"
#include "fcintl.h"
#include "game.h"
#include "log.h"
@@ -182,6 +183,9 @@
/* mark as initialized */
has_been_srv_init = TRUE;
+ /* init character encodings. */
+ init_character_encodings(DEFAULT_DATA_ENCODING);
+
/* done */
return;
}
/**********************************************************************
Freeciv - Copyright (C) 2003-2004 - The Freeciv Project
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
***********************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_ICONV
#include <iconv.h>
#endif
#ifdef HAVE_LANGINFO_CODESET
#include <langinfo.h>
#endif
#include "fciconv.h"
#include "fcintl.h"
#include "log.h"
#include "mem.h"
#include "support.h"
static bool is_init = FALSE;
static char convert_buffer[4096];
#ifdef HAVE_ICONV
static char *local_encoding, *data_encoding, *internal_encoding;
#endif
/***************************************************************************
Must be called during the initialization phase of server and client to
initialize the character encodings to be used.
***************************************************************************/
void init_character_encodings(char *my_internal_encoding)
{
#ifdef HAVE_ICONV
/* Set the data encoding - first check $FREECIV_DATA_ENCODING,
* then fall back to the default. */
data_encoding = getenv("FREECIV_DATA_ENCODING");
if (!data_encoding) {
/* Currently the rulesets are in latin1 (ISO-8859-1). */
data_encoding = DEFAULT_DATA_ENCODING;
}
/* Set the local encoding - first check $FREECIV_LOCAL_ENCODING,
* then ask the system. */
local_encoding = getenv("FREECIV_LOCAL_ENCODING");
if (!local_encoding) {
#ifdef HAVE_LIBCHARSET
local_encoding = locale_charset();
#else
#ifdef HAVE_LANGINFO_CODESET
local_encoding = nl_langinfo(CODESET);
#else
local_encoding = "";
#endif
#endif
if (strcasecmp(local_encoding, "ANSI_X3.4-1968") == 0
|| strcasecmp(local_encoding, "ASCII") == 0) {
/* HACK: use latin1 instead of ascii in typical cases when the
* encoding is unconfigured. */
local_encoding = "ISO-8859-1";
}
}
/* Set the internal encoding - first check $FREECIV_INTERNAL_ENCODING,
* then check the passed-in default value, then fall back to the local
* encoding. */
internal_encoding = getenv("FREECIV_INTERNAL_ENCODING");
if (!internal_encoding) {
internal_encoding = my_internal_encoding;
if (!internal_encoding) {
internal_encoding = local_encoding;
}
}
#ifdef ENABLE_NLS
bind_textdomain_codeset(PACKAGE, internal_encoding);
#endif
fprintf(stderr, "Data=%s, Local=%s, Internal=%s\n",
data_encoding, local_encoding, internal_encoding);
#else
/* freelog may not work at this point. */
fprintf(stderr,
_("You are running Freeciv without using iconv. Unless\n"
"you are using the latin1 character set, some characters\n"
"may not be displayed properly. You can download iconv\n"
"at http://gnu.org/.\n"));
#endif
is_init = TRUE;
}
const char *get_data_encoding(void)
{
assert(is_init);
return data_encoding;
}
const char *get_local_encoding(void)
{
assert(is_init);
return local_encoding;
}
const char *get_internal_encoding(void)
{
assert(is_init);
return internal_encoding;
}
/***************************************************************************
Convert the text. Both 'from' and 'to' must be 8-bit charsets. The
result will be put into the buf buffer unless it is NULL, in which case it
will be allocated on demand.
***************************************************************************/
static char *convert_string(const char *text,
const char *from,
const char *to,
char *buf, size_t bufsz)
{
#ifdef HAVE_ICONV
iconv_t cd = iconv_open(to, from);
size_t from_len = strlen(text) + 1, to_len;
bool alloc = (buf == NULL);
assert(is_init && from != NULL && to != NULL);
assert(text != NULL);
if (cd == (iconv_t) (-1)) {
freelog(LOG_ERROR,
_("Could not convert text from %s to %s: %s"),
from, to, strerror(errno));
/* The best we can do? */
if (alloc) {
return mystrdup(text);
} else {
my_snprintf(buf, bufsz, "%s", text);
return buf;
}
}
if (alloc) {
to_len = from_len;
} else {
to_len = bufsz;
}
do {
size_t flen = from_len, tlen = to_len, res;
const char *mytext = text;
char *myresult;
if (alloc) {
buf = fc_malloc(to_len);
}
myresult = buf;
/* Since we may do multiple translations, we may need to reset iconv
* in between. */
iconv(cd, NULL, NULL, NULL, NULL);
res = iconv(cd, (char**)&mytext, &flen, &myresult, &tlen);
if (res == (size_t) (-1)) {
if (errno != E2BIG) {
/* Invalid input. */
freelog(LOG_ERROR, "Invalid string conversion from %s to %s.",
from, to);
iconv_close(cd);
if (alloc) {
free(buf);
return mystrdup(text); /* The best we can do? */
} else {
my_snprintf(buf, bufsz, "%s", text);
return buf;
}
}
} else {
/* Success. */
iconv_close(cd);
/* There may be wasted space here, but there's nothing we can do
* about it. */
return buf;
}
if (alloc) {
/* Not enough space; try again. */
buf[to_len - 1] = 0;
freelog(LOG_VERBOSE, " Result was '%s'.", buf);
free(buf);
to_len *= 2;
}
} while (alloc);
return buf;
#else /* HAVE_ICONV */
if (buf) {
strncpy(buf, text, bufsz);
buf[bufsz - 1] = '\0';
} else {
return mystrdup(text);
}
#endif /* HAVE_ICONV */
}
#define CONV_FUNC_MALLOC(src, dst) \
char *src ## _to_ ## dst ## _string_malloc(const char *text) \
{ \
return convert_string(text, (src ## _encoding), \
(dst ## _encoding), NULL, 0); \
}
#define CONV_FUNC_BUFFER(src, dst) \
char *src ## _to_ ## dst ## _string_buffer(const char *text, \
char *buf, size_t bufsz) \
{ \
return convert_string(text, (src ## _encoding), \
(dst ## _encoding), buf, bufsz); \
}
#define CONV_FUNC_STATIC(src, dst) \
char *src ## _to_ ## dst ## _string_static(const char *text) \
{ \
(src ## _to_ ## dst ## _string_buffer)(text, \
convert_buffer, \
sizeof(convert_buffer)); \
return convert_buffer; \
}
CONV_FUNC_MALLOC(data, internal)
CONV_FUNC_MALLOC(internal, data)
static CONV_FUNC_BUFFER(internal, local)
static CONV_FUNC_STATIC(internal, local)
/***************************************************************************
Do a printf in the currently bound codeset.
***************************************************************************/
void fc_fprintf(FILE *stream, const char *format, ...)
{
va_list ap;
char string[4096];
const char *output;
va_start(ap, format);
my_vsnprintf(string, sizeof(string), format, ap);
va_end(ap);
output = internal_to_local_string_static(string);
fputs(output, stream);
fflush(stream);
}
/**********************************************************************
Freeciv - Copyright (C) 2003-2004 - The Freeciv Project
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
***********************************************************************/
#ifndef FC__FCICONV_H
#define FC__FCICONV_H
#include "shared.h"
#define DEFAULT_DATA_ENCODING "ISO-8859-1"
void init_character_encodings(char *internal_encoding);
const char *get_data_encoding(void);
const char *get_local_encoding(void);
const char *get_internal_encoding(void);
char *data_to_internal_string_malloc(const char *text);
char *internal_to_data_string_malloc(const char *text);
void fc_fprintf(FILE *stream, const char *format, ...)
fc__attribute((format (printf, 2, 3)));
#endif /* FC__FCICONV_H */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Freeciv-Dev] (PR#9722) fix charset problems in 1.14,
Jason Short <=
|
|