Complete.Org: Mailing Lists: Archives: freeciv-dev: April 2004:
[Freeciv-Dev] Re: (PR#1824) ruleset data is in incompatible charsets
Home

[Freeciv-Dev] Re: (PR#1824) ruleset data is in incompatible charsets

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: Kenn.Munro@xxxxxxxxxxxxxx, jdwheeler42@xxxxxxxxx, jrg45@xxxxxxxxxxxxxxxxx, pawel@xxxxxxxxxxxxxxx, per@xxxxxxxxxxx
Cc: mrproper@xxxxxxxxxx, jlangley@xxxxxxx
Subject: [Freeciv-Dev] Re: (PR#1824) ruleset data is in incompatible charsets
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 26 Apr 2004 13:21:50 -0700
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=1824 >

Jason Short wrote:

> Note that this is different from what Vasco does now in the conversion 
> step for gui-gtk-2.0.  He automatically converts strings to and from 
> (basically) the "network" charset and UTF-8 when the strings are 
> received from the network.  This works well with the gtk2 client because 
> UTF-8 can then basically be used everywhere.  It also works because 
> ascii strings can safely be converted into utf-8 and still used.  It 
> won't work well for other GUIs with less convenient charsets (like 
> gui-sdl with a UTF-16 charset).

OK, this patch does it the way the gtk2 client did it.  This is much 
easier, leading to a relatively small patch (only 50k :-).

- The server keeps all text strings in the data encoding.
- The client keeps all text strings in the display encoding.
- Text strings are converted by the client's network code.

- Gettext translates into the internal encoding: the data encoding at 
the server, the display encoding at the client.
- fprintf must therefore generally convert from this encoding to the 
local encoding.  So I write a new function fc_fprintf to do this.  Of 
course this replaces gui-gtk-2.0's fprintf_utf8.  I didn't replace all 
fprintf's with this new function, however.

It's still pretty unpolished, but I believe this design is workable.

Please test.

jason

Index: configure.ac
===================================================================
RCS file: /home/freeciv/CVS/freeciv/configure.ac,v
retrieving revision 1.61
diff -u -r1.61 configure.ac
--- configure.ac        19 Apr 2004 17:24:16 -0000      1.61
+++ configure.ac        26 Apr 2004 20:14:26 -0000
@@ -305,6 +305,11 @@
   AC_MSG_ERROR([zlib found but not zlib.h.  
 You may need to install a zlib \"development\" package.]))
 
+dnl Check for libiconv (which is usually included in glibc, but may be
+dnl distributed separately).
+AM_ICONV
+LIBS="$LIBS $LIBICONV"
+
 dnl Check and choose clients
 if test x$client != xno; then
 
Index: configure.in
===================================================================
RCS file: /home/freeciv/CVS/freeciv/configure.in,v
retrieving revision 1.237
diff -u -r1.237 configure.in
--- configure.in        20 Apr 2004 17:26:13 -0000      1.237
+++ configure.in        26 Apr 2004 20:14:26 -0000
@@ -298,6 +298,11 @@
   AC_MSG_ERROR([zlib found but not zlib.h.  
 You may need to install a zlib \"development\" package.]))
 
+dnl Check for libiconv (which is usually included in glibc, but may be
+dnl distributed separately).
+AM_ICONV
+LIBS="$LIBS $LIBICONV"
+
 dnl Check and choose clients
 if test x$client != xno; then
 
Index: client/civclient.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/civclient.c,v
retrieving revision 1.187
diff -u -r1.187 civclient.c
--- client/civclient.c  21 Apr 2004 19:46:37 -0000      1.187
+++ client/civclient.c  26 Apr 2004 20:14:26 -0000
@@ -32,7 +32,9 @@
 #endif
 
 #include "capstr.h"
+#include "dataio.h"
 #include "diptreaty.h"
+#include "fciconv.h"
 #include "fcintl.h"
 #include "game.h"
 #include "idex.h"
@@ -102,6 +104,64 @@
  */
 bool turn_done_sent = FALSE;
 
+/**************************************************************************
+  Convert a text string from the data to the display encoding, when it
+  is read from the network.
+**************************************************************************/
+static unsigned char *put_conv(const char *src, size_t *length)
+{
+  char *out = display_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 display 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_display_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)
+{
+#ifdef ENABLE_NLS
+  bind_textdomain_codeset(PACKAGE, get_display_encoding());
+#endif
+  dio_set_put_conv_callback(put_conv);
+  dio_set_get_conv_callback(get_conv);
+}
 
 /**************************************************************************
 ...
@@ -214,6 +274,7 @@
   conn_list_init(&game.game_connections);
 
   ui_init();
+  charsets_init();
   my_init_network();
   init_messages_where();
   init_city_report_data();
Index: client/clinet.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/clinet.c,v
retrieving revision 1.96
diff -u -r1.96 clinet.c
--- client/clinet.c     13 Apr 2004 16:40:00 -0000      1.96
+++ client/clinet.c     26 Apr 2004 20:14:26 -0000
@@ -812,12 +812,12 @@
     if (type != SERVER_LAN_VERSION) {
       return lan_servers;
     }
-    dio_get_string(&din, servername, sizeof(servername));
-    dio_get_string(&din, port, sizeof(port));
-    dio_get_string(&din, version, sizeof(version));
-    dio_get_string(&din, status, sizeof(status));
-    dio_get_string(&din, players, sizeof(players));
-    dio_get_string(&din, metastring, sizeof(metastring));
+    dio_get_ascii_string(&din, servername, sizeof(servername));
+    dio_get_ascii_string(&din, port, sizeof(port));
+    dio_get_ascii_string(&din, version, sizeof(version));
+    dio_get_ascii_string(&din, status, sizeof(status));
+    dio_get_ascii_string(&din, players, sizeof(players));
+    dio_get_ascii_string(&din, metastring, sizeof(metastring));
 
     if (!mystrcasecmp("none", servername)) {
       from = gethostbyaddr((char *) &fromend.sockaddr_in.sin_addr,
Index: client/gui-gtk/gui_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/gui_main.c,v
retrieving revision 1.148
diff -u -r1.148 gui_main.c
--- client/gui-gtk/gui_main.c   15 Apr 2004 19:36:01 -0000      1.148
+++ client/gui-gtk/gui_main.c   26 Apr 2004 20:14:26 -0000
@@ -31,6 +31,7 @@
 #include <unistd.h>
 #endif
 
+#include "fciconv.h"
 #include "fcintl.h"
 #include "game.h"
 #include "government.h"
@@ -798,6 +799,7 @@
 **************************************************************************/
 void ui_init(void)
 {
+  init_character_encodings(NULL, 1);
 }
 
 /**************************************************************************
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.32
diff -u -r1.32 connectdlg.c
--- client/gui-gtk-2.0/connectdlg.c     23 Apr 2004 23:13:55 -0000      1.32
+++ client/gui-gtk-2.0/connectdlg.c     26 Apr 2004 20:14:27 -0000
@@ -260,12 +260,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(storelan, &it);
       gtk_list_store_set(storelan, &it,
@@ -1135,12 +1135,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(storemeta, &it);
     gtk_list_store_set(storemeta, &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.71
diff -u -r1.71 gui_main.c
--- client/gui-gtk-2.0/gui_main.c       15 Apr 2004 19:36:01 -0000      1.71
+++ client/gui-gtk-2.0/gui_main.c       26 Apr 2004 20:14:27 -0000
@@ -33,6 +33,7 @@
 #include <gdk/gdkkeysyms.h>
 
 #include "dataio.h"
+#include "fciconv.h"
 #include "fcintl.h"
 #include "game.h"
 #include "government.h"
@@ -170,107 +171,13 @@
 static gint timer_callback(gpointer data);
 static gboolean show_conn_popup(GtkWidget *view, GdkEventButton *ev,
                                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);
 }
 
 /**************************************************************************
@@ -280,7 +187,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);
 }
 
 /**************************************************************************
@@ -1012,32 +919,10 @@
 void ui_init(void)
 {
   gchar *s;
-  char *net_charset;
 
-#ifdef ENABLE_NLS
-  bind_textdomain_codeset(PACKAGE, "UTF-8");
-#endif
+  init_character_encodings("UTF-8", 1);
 
   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(user_name, -1, NULL, NULL, NULL);
Index: client/gui-xaw/gui_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-xaw/gui_main.c,v
retrieving revision 1.91
diff -u -r1.91 gui_main.c
--- client/gui-xaw/gui_main.c   15 Apr 2004 19:36:01 -0000      1.91
+++ client/gui-xaw/gui_main.c   26 Apr 2004 20:14:27 -0000
@@ -37,6 +37,7 @@
 #include "canvas.h"
 #include "pixcomm.h"
 
+#include "fciconv.h"
 #include "fcintl.h"
 #include "game.h"
 #include "government.h"
@@ -261,6 +262,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.49
diff -u -r1.49 Makefile.am
--- common/Makefile.am  13 Feb 2004 07:57:58 -0000      1.49
+++ common/Makefile.am  26 Apr 2004 20:14:27 -0000
@@ -28,6 +28,8 @@
                effects.c       \
                effects.h       \
                events.h        \
+               fciconv.c       \
+               fciconv.h       \
                fcintl.c        \
                fcintl.h        \
                game.c          \
Index: common/dataio.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/dataio.c,v
retrieving revision 1.10
diff -u -r1.10 dataio.c
--- common/dataio.c     14 Feb 2004 02:21:25 -0000      1.10
+++ common/dataio.c     26 Apr 2004 20:14:27 -0000
@@ -317,7 +317,15 @@
 /**************************************************************************
 ...
 **************************************************************************/
-void dio_put_string(struct data_out *dout, const char *value)
+void dio_put_ascii_string(struct data_out *dout, const char *value)
+{
+  dio_put_memory(dout, value, strlen(value) + 1);
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+void dio_put_text_string(struct data_out *dout, const char *value)
 {
   if (put_conv_callback) {
     size_t length;
@@ -546,7 +554,53 @@
 /**************************************************************************
 ...
 **************************************************************************/
-void dio_get_string(struct data_in *din, char *dest, size_t max_dest_size)
+void dio_get_ascii_string(struct data_in *din,
+                         char *dest, size_t max_dest_size)
+{
+  unsigned char *c;
+  size_t ps_len;               /* length in packet, not including null */
+  size_t offset, remaining;
+
+  assert(max_dest_size > 0 || dest == NULL);
+
+  if (!enough_data(din, 1)) {
+    dest[0] = '\0';
+    return;
+  }
+
+  remaining = dio_input_remaining(din);
+  c = ADD_TO_POINTER(din->src, din->current);
+
+  /* avoid using strlen (or strcpy) on an (unsigned char*)  --dwp */
+  for (offset = 0; c[offset] != '\0' && offset < remaining; offset++) {
+    /* nothing */
+  }
+
+  if (offset >= remaining) {
+    ps_len = remaining;
+    din->too_short = TRUE;
+    din->bad_string = TRUE;
+  } else {
+    ps_len = offset;
+  }
+
+  {
+    size_t copy_len = MIN(ps_len + 1, max_dest_size);
+
+    mystrlcpy(dest, c, copy_len);
+    dest[copy_len - 1] = '\0';
+  }
+
+  if (!din->too_short) {
+    din->current += (ps_len + 1);      /* past terminator */
+  }
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+void dio_get_text_string(struct data_in *din,
+                        char *dest, size_t max_dest_size)
 {
   unsigned char *c;
   size_t ps_len;               /* length in packet, not including null */
Index: common/dataio.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/dataio.h,v
retrieving revision 1.5
diff -u -r1.5 dataio.h
--- common/dataio.h     10 Apr 2004 03:47:49 -0000      1.5
+++ common/dataio.h     26 Apr 2004 20:14:27 -0000
@@ -65,7 +65,10 @@
 void dio_get_bool8(struct data_in *din, bool *dest);
 void dio_get_bool32(struct data_in *din, bool *dest);
 void dio_get_memory(struct data_in *din, void *dest, size_t dest_size);
-void dio_get_string(struct data_in *din, char *dest, size_t max_dest_size);
+void dio_get_ascii_string(struct data_in *din,
+                         char *dest, size_t max_dest_size);
+void dio_get_text_string(struct data_in *din,
+                        char *dest, size_t max_dest_size);
 void dio_get_bit_string(struct data_in *din, char *dest,
                        size_t max_dest_size);
 void dio_get_city_map(struct data_in *din, char *dest, size_t max_dest_size);
@@ -94,7 +97,8 @@
 void dio_put_bool32(struct data_out *dout, bool value);
 
 void dio_put_memory(struct data_out *dout, const void *value, size_t size);
-void dio_put_string(struct data_out *dout, const char *value);
+void dio_put_ascii_string(struct data_out *dout, const char *value);
+void dio_put_text_string(struct data_out *dout, const char *value);
 void dio_put_bit_string(struct data_out *dout, const char *value);
 void dio_put_city_map(struct data_out *dout, const char *value);
 void dio_put_tech_list(struct data_out *dout, const int *value);
Index: common/fciconv.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/fciconv.c,v
retrieving revision 1.1
diff -u -r1.1 fciconv.c
--- common/fciconv.c    26 Apr 2004 02:13:30 -0000      1.1
+++ common/fciconv.c    26 Apr 2004 20:14:27 -0000
@@ -0,0 +1,310 @@
+/********************************************************************** 
+ Freeciv - Copyright (C) 2003 - 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 "mem.h"
+#include "support.h"
+
+#ifdef HAVE_ICONV
+#include "log.h"
+#endif
+
+#define DEFAULT_DATA_ENCODING "ISO-8859-1"
+
+static bool is_init = FALSE;
+static char convert_buffer[4096];
+
+#ifdef HAVE_ICONV
+static char *local_encoding, *data_encoding, *display_encoding;
+static const size_t local_encoding_size = 1, data_encoding_size = 1;
+static size_t display_encoding_size = 1;
+#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_display_encoding,
+                             size_t encoding_size)
+{
+#ifdef HAVE_ICONV
+  static char local[128];
+
+  /* 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";
+    }
+
+
+    my_snprintf(local, sizeof(local), "%s//TRANSLIT", local_encoding);
+    local_encoding = local;
+  }
+
+  /* Set the display encoding - first check $FREECIV_DISPLAY_ENCODING,
+   * then check the passed-in default value, then fall back to the local
+   * encoding. */
+  display_encoding = getenv("FREECIV_DISPLAY_ENCODING");
+  if (!display_encoding) {
+    display_encoding = my_display_encoding;
+
+    if (!display_encoding) {
+      display_encoding = local_encoding;
+    }
+  }
+  display_encoding_size = encoding_size;
+
+  fprintf(stderr, "Data=%s, Local=%s, Display=%s\n",
+        data_encoding, local_encoding, display_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";));
+   assert(encoding_size == 1);
+#endif
+
+   is_init = TRUE;
+}
+
+const char *get_data_encoding(void)
+{
+  return data_encoding;
+}
+
+const char *get_local_encoding(void)
+{
+  return local_encoding;
+}
+
+const char *get_display_encoding(void)
+{
+  return display_encoding;
+}
+
+#ifdef HAVE_ICONV
+/***************************************************************************
+  Return the number of characters in the string.  from_sz is the character
+  encoding size (currently 1 or 2).
+***************************************************************************/
+static size_t char_strlen(const char *text, size_t from_sz)
+{
+  size_t length = 0;
+
+  do {
+    size_t i;
+
+    for (i = 0; i < from_sz; i++) {
+      if (text[length * from_sz + i] != 0) {
+       break;
+      }
+    }
+
+    if (i == from_sz) {
+      return length;
+    }
+
+    length++;
+  } while (TRUE);
+}
+
+/***************************************************************************
+  Convert the text.  This assumes 'from' is an 8-bit charset.  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, size_t from_sz,
+                           const char *to,
+                           char *buf, size_t bufsz)
+{
+  iconv_t cd = iconv_open(to, from);
+  size_t from_len = char_strlen(text, from_sz) + from_sz, 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;
+}
+
+#endif
+
+#ifdef HAVE_ICONV
+
+#define CONV_FUNC_MALLOC(src, dst)                                          \
+char *src ## _to_ ## dst ## _string_malloc(const char *text)                \
+{                                                                           \
+  return convert_string(text, (src ## _encoding), (src ## _encoding_size),  \
+                       (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), (src ## _encoding_size),  \
+                        (dst ## _encoding), buf, bufsz);                    \
+}
+
+#else /* HAVE_ICONV */
+
+#define CONV_FUNC_MALLOC(src, dst)                                          \
+char *src ## _to_ ## dst ## _string_malloc(const char *text)                \
+{                                                                           \
+  return mystrdup(text);                                                    \
+}
+
+#define CONV_FUNC_BUFFER(src, dst)                                          \
+char *src ## _to_ ## dst ## _string_buffer(const char *text,                \
+                                          char *buf, size_t bufsz)         \
+{                                                                           \
+  my_snprintf(buf, bufsz, "%s", text);                                      \
+  return buf;                                                               \
+}
+
+#endif /* HAVE_ICONV */
+
+#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, display)
+CONV_FUNC_MALLOC(display, data)
+
+CONV_FUNC_STATIC(data, display)
+CONV_FUNC_STATIC(display, data)
+
+CONV_FUNC_BUFFER(data, display)
+CONV_FUNC_BUFFER(display, data)
+
+static CONV_FUNC_BUFFER(display, local)
+CONV_FUNC_STATIC(display, local)
+
+static CONV_FUNC_BUFFER(data, local)
+CONV_FUNC_STATIC(data, local)
Index: common/fciconv.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/fciconv.h,v
retrieving revision 1.1
diff -u -r1.1 fciconv.h
--- common/fciconv.h    26 Apr 2004 02:13:30 -0000      1.1
+++ common/fciconv.h    26 Apr 2004 20:14:27 -0000
@@ -0,0 +1,36 @@
+/********************************************************************** 
+ Freeciv - Copyright (C) 2003 - 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
+
+void init_character_encodings(char *my_display_encoding,
+                             size_t encoding_size);
+
+const char *get_data_encoding(void);
+const char *get_local_encoding(void);
+const char *get_display_encoding(void);
+
+char *data_to_display_string_malloc(const char *text);
+char *data_to_display_string_static(const char *text);
+char *data_to_display_string_buffer(const char *text,
+                                   char *buf, size_t bufsz);
+
+char *display_to_data_string_malloc(const char *text);
+char *display_to_data_string_static(const char *text);
+char *display_to_data_string_buffer(const char *text,
+                                   char *buf, size_t bufsz);
+
+char *display_to_local_string_static(const char *text);
+char *data_to_local_string_static(const char *text);
+
+#endif /* FC__FCICONV_H */
Index: common/generate_packets.py
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/generate_packets.py,v
retrieving revision 1.10
diff -u -r1.10 generate_packets.py
--- common/generate_packets.py  7 Apr 2004 21:12:43 -0000       1.10
+++ common/generate_packets.py  26 Apr 2004 20:14:28 -0000
@@ -218,7 +218,7 @@
         return result
 
     def get_handle_type(self,const=0):
-        if self.dataio_type=="string":
+        if self.dataio_type in ["ascii_string","text_string"]:
             if const: return "const char *"
             else:     return "char *"
             
@@ -245,7 +245,7 @@
             return "  copy_worklist(&real_packet->%(name)s, 
%(name)s);"%self.__dict__
         if self.is_array==0:
             return "  real_packet->%(name)s = %(name)s;"%self.__dict__
-        if self.dataio_type=="string":
+        if self.dataio_type in ["ascii_string", "text_string"]:
             return "  sz_strlcpy(real_packet->%(name)s, 
%(name)s);"%self.__dict__
         if self.is_array==1:
             tmp="real_packet->%(name)s[i] = %(name)s[i]"%self.__dict__
@@ -266,14 +266,14 @@
             return "  differ = (memcmp(old->%(name)s, real_packet->%(name)s, 
%(array_size_d)s) != 0);"%self.__dict__
         if self.dataio_type=="bitvector":
             return "  differ = !BV_ARE_EQUAL(old->%(name)s, 
real_packet->%(name)s);"%self.__dict__
-        if self.dataio_type in ["string","bit_string"] and self.is_array==1:
+        if self.dataio_type in ["ascii_string","text_string","bit_string"] and 
self.is_array==1:
             return "  differ = (strcmp(old->%(name)s, real_packet->%(name)s) 
!= 0);"%self.__dict__
         if self.is_struct and self.is_array==0:
             return "  differ = !are_%(dataio_type)ss_equal(&old->%(name)s, 
&real_packet->%(name)s);"%self.__dict__
         if not self.is_array:
             return "  differ = (old->%(name)s != 
real_packet->%(name)s);"%self.__dict__
         
-        if self.dataio_type=="string":
+        if self.dataio_type in ["ascii_string","text_string"]:
             c="strcmp(old->%(name)s[i], real_packet->%(name)s[i]) != 
0"%self.__dict__
             array_size_u=self.array_size1_u
             array_size_o=self.array_size1_o
@@ -349,13 +349,13 @@
         if self.dataio_type in ["memory"]:
             return "  dio_put_%(dataio_type)s(&dout, &real_packet->%(name)s, 
%(array_size_u)s);"%self.__dict__
         
-        arr_types=["string","bit_string","city_map","tech_list"]
+        
arr_types=["ascii_string","text_string","bit_string","city_map","tech_list"]
         if (self.dataio_type in arr_types and self.is_array==1) or \
            (self.dataio_type not in arr_types and self.is_array==0):
             return "  dio_put_%(dataio_type)s(&dout, 
real_packet->%(name)s);"%self.__dict__
         if self.is_struct:
             c="dio_put_%(dataio_type)s(&dout, 
&real_packet->%(name)s[i]);"%self.__dict__
-        elif self.dataio_type=="string":
+        elif self.dataio_type in ["ascii_string","text_string"]:
             c="dio_put_%(dataio_type)s(&dout, 
real_packet->%(name)s[i]);"%self.__dict__
             array_size_u=self.array_size1_u
 
@@ -422,7 +422,7 @@
 
         if self.dataio_type=="memory":
             return "dio_get_%(dataio_type)s(&din, real_packet->%(name)s, 
%(array_size_u)s);"%self.__dict__
-        if self.dataio_type in ["string","bit_string","city_map","memory"] and 
\
+        if self.dataio_type in 
["ascii_string","text_string","bit_string","city_map","memory"] and \
            self.is_array!=2:
             return "dio_get_%(dataio_type)s(&din, real_packet->%(name)s, 
sizeof(real_packet->%(name)s));"%self.__dict__
         if self.is_struct and self.is_array==0:
@@ -436,7 +436,7 @@
 
         if self.is_struct:
             c="dio_get_%(dataio_type)s(&din, 
&real_packet->%(name)s[i]);"%self.__dict__
-        elif self.dataio_type=="string":
+        elif self.dataio_type in ["ascii_string","text_string"]:
             c="dio_get_%(dataio_type)s(&din, real_packet->%(name)s[i], 
sizeof(real_packet->%(name)s[i]));"%self.__dict__
         elif self.struct_type=="float":
             c='''int tmp;
Index: common/log.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/log.c,v
retrieving revision 1.45
diff -u -r1.45 log.c
--- common/log.c        10 Apr 2004 03:47:49 -0000      1.45
+++ common/log.c        26 Apr 2004 20:14:28 -0000
@@ -80,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;
     }
@@ -99,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;
@@ -115,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;
   }
@@ -132,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;
     }
@@ -155,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;
   }
@@ -236,7 +239,7 @@
     log_callback(level, message);
   }
   if (log_filename || (!log_callback)) {
-    fprintf(fs, "%d: %s\n", level, message);
+    fc_fprintf(fs, "%d: %s\n", level, message);
     fflush(fs);
   }
 }
@@ -264,7 +267,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/packets.def
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/packets.def,v
retrieving revision 1.21
diff -u -r1.21 packets.def
--- common/packets.def  24 Apr 2004 17:32:47 -0000      1.21
+++ common/packets.def  26 Apr 2004 20:14:28 -0000
@@ -149,7 +149,8 @@
 
 # typedefs for arrays/structs
 type MEMORY            = memory(unsigned char)
-type STRING            = string(char)
+type ASCII             = ascii_string(char)
+type TEXT              = text_string(char)
 type BIT_STRING                = bit_string(char)
 type CITY_MAP          = city_map(char)
 type WORKLIST          = worklist(struct worklist)
@@ -235,29 +236,29 @@
 # This packet is the first real (freeciv specific) packet send by the
 # client. The player hasn't been accepted yet.
 PACKET_SERVER_JOIN_REQ=4; cs, dsend,no-delta,no-handle
-  STRING username[MAX_LEN_NAME];
-  STRING capability[MAX_LEN_CAPSTR];
-  STRING version_label[MAX_LEN_NAME];
+  TEXT username[MAX_LEN_NAME];
+  ASCII capability[MAX_LEN_CAPSTR];
+  ASCII version_label[MAX_LEN_NAME];
   UINT32 major_version, minor_version, patch_version;
 end
 
 # ... and the server replies.
 PACKET_SERVER_JOIN_REPLY=5; sc,no-delta
   BOOL you_can_join;
-  STRING message[MAX_LEN_MSG];
-  STRING capability[MAX_LEN_CAPSTR];
-  STRING challenge_file[MAX_LEN_PATH];
+  TEXT message[MAX_LEN_MSG];
+  ASCII capability[MAX_LEN_CAPSTR];
+  ASCII challenge_file[MAX_LEN_PATH];
   # clients conn id as known in server
   CONNECTION conn_id;
 end
 
 PACKET_AUTHENTICATION_REQ=6;sc,handle-per-conn,dsend
   AUTH_TYPE type;
-  STRING message[MAX_LEN_MSG]; /* explain to the client if there's a problem */
+  TEXT message[MAX_LEN_MSG]; /* explain to the client if there's a problem */
 end
 
 PACKET_AUTHENTICATION_REPLY=7;cs,no-handle
-  STRING password[MAX_LEN_NAME];
+  TEXT password[MAX_LEN_NAME];
 end
 
 
@@ -272,7 +273,7 @@
 PACKET_NATION_SELECT_REQ=10;cs,dsend
   NATION nation_no;
   BOOL is_male;
-  STRING name[MAX_LEN_NAME];
+  TEXT name[MAX_LEN_NAME];
   UINT8 city_style;
 end
 
@@ -311,7 +312,7 @@
   SPECIAL special;
   PLAYER owner;
   CONTINENT continent;
-  STRING spec_sprite[MAX_LEN_NAME];
+  ASCII spec_sprite[MAX_LEN_NAME];
 end
 
 PACKET_GAME_INFO=15; is-info,sc
@@ -357,13 +358,13 @@
 /************** Chat/event packets **********************/
 
 PACKET_CHAT_MSG=18;sc, pre-send, post-recv,lsend
-  STRING message[MAX_LEN_MSG];
+  TEXT message[MAX_LEN_MSG];
   COORD x, y;
   EVENT event;
 end
 
 PACKET_CHAT_MSG_REQ=19;cs,handle-per-conn,dsend
-  STRING message[MAX_LEN_MSG];
+  TEXT message[MAX_LEN_MSG];
 end
 
 /************** City packets **********************/
@@ -376,7 +377,7 @@
   CITY id; key
   PLAYER owner;
   COORD x,y;
-  STRING name[MAX_LEN_NAME];
+  TEXT name[MAX_LEN_NAME];
   UINT8 size;
 
   UINT8 ppl_happy[5], ppl_content[5], ppl_unhappy[5], ppl_angry[5];
@@ -421,7 +422,7 @@
   PLAYER owner;
   COORD x;
   COORD y;
-  STRING name[MAX_LEN_NAME];
+  TEXT name[MAX_LEN_NAME];
   UINT8 size;
   BOOL happy;
   BOOL unhappy;
@@ -468,7 +469,7 @@
 
 PACKET_CITY_RENAME=30;cs,dsend
   CITY city_id;
-  STRING name[MAX_LEN_NAME];
+  TEXT name[MAX_LEN_NAME];
 end
 
 PACKET_CITY_OPTIONS_REQ=31;cs,dsend
@@ -501,7 +502,7 @@
 
 PACKET_CITY_NAME_SUGGESTION_INFO=36;sc,dsend,lsend
   UNIT unit_id;
-  STRING name[MAX_LEN_NAME];
+  TEXT name[MAX_LEN_NAME];
 end
 
 PACKET_CITY_SABOTAGE_LIST=37;sc,lsend
@@ -518,7 +519,7 @@
 
 PACKET_PLAYER_INFO=39; is-info,sc
   PLAYER playerno; key 
-  STRING name[MAX_LEN_NAME];
+  TEXT name[MAX_LEN_NAME];
   BOOL is_male;
   GOVERNMENT government;
   UINT32 embassy;
@@ -648,7 +649,7 @@
 
 PACKET_UNIT_BUILD_CITY=53;cs,dsend
   UNIT unit_id;
-  STRING name[MAX_LEN_NAME];
+  TEXT name[MAX_LEN_NAME];
 end
 
 PACKET_UNIT_DISBAND=54;cs,dsend
@@ -813,7 +814,7 @@
 /**************  Report packets **********************/
 
 PACKET_PAGE_MSG=84;sc,lsend
-  STRING message[MAX_LEN_MSG];
+  TEXT message[MAX_LEN_MSG];
   EVENT event;
 end
 
@@ -836,9 +837,9 @@
   BOOL observer;
   PLAYER player_num;
   CMDLEVEL access_level;
-  STRING username[MAX_LEN_NAME];
-  STRING addr[MAX_LEN_ADDR];
-  STRING capability[MAX_LEN_CAPSTR];
+  TEXT username[MAX_LEN_NAME];
+  ASCII addr[MAX_LEN_ADDR];
+  ASCII capability[MAX_LEN_CAPSTR];
 end
 
 # Information about the ping times of the connections.
@@ -912,13 +913,13 @@
 
 PACKET_RULESET_UNIT=96;sc,lsend
   UNIT_TYPE id;
-  STRING name[MAX_LEN_NAME];
-  STRING graphic_str[MAX_LEN_NAME];
-  STRING graphic_alt[MAX_LEN_NAME];
-  STRING sound_move[MAX_LEN_NAME];
-  STRING sound_move_alt[MAX_LEN_NAME];
-  STRING sound_fight[MAX_LEN_NAME];
-  STRING sound_fight_alt[MAX_LEN_NAME];
+  ASCII name[MAX_LEN_NAME];
+  ASCII graphic_str[MAX_LEN_NAME];
+  ASCII graphic_alt[MAX_LEN_NAME];
+  ASCII sound_move[MAX_LEN_NAME];
+  ASCII sound_move_alt[MAX_LEN_NAME];
+  ASCII sound_fight[MAX_LEN_NAME];
+  ASCII sound_fight_alt[MAX_LEN_NAME];
   UINT8 move_type;
   UINT16 build_cost;
   UINT8 pop_cost;
@@ -943,13 +944,13 @@
   UINT8 paratroopers_mr_req;
   UINT8 paratroopers_mr_sub;
 
-  STRING veteran_name[MAX_VET_LEVELS][MAX_LEN_NAME]; add-cap(veteran)
+  ASCII veteran_name[MAX_VET_LEVELS][MAX_LEN_NAME]; add-cap(veteran)
   FLOAT power_fact[MAX_VET_LEVELS]; add-cap(veteran)
   UINT8 move_bonus[MAX_VET_LEVELS]; add-cap(veteran)
 
   UINT8 bombard_rate; add-cap(bombard)
 
-  STRING helptext[MAX_LEN_PACKET];
+  ASCII helptext[MAX_LEN_PACKET];
 
   bitvector(bv_flags) flags;
   bitvector(bv_roles) roles;
@@ -982,8 +983,8 @@
   GOVERNMENT gov;
   UINT8 id;
   NATION nation;
-  STRING male_title[MAX_LEN_NAME];
-  STRING female_title[MAX_LEN_NAME];
+  ASCII male_title[MAX_LEN_NAME];
+  ASCII female_title[MAX_LEN_NAME];
 end
 
 PACKET_RULESET_TECH=99;sc,lsend
@@ -991,10 +992,10 @@
   TECH req[2];
   TECH root_req;
   UINT32 flags, preset_cost, num_reqs;
-  STRING name[MAX_LEN_NAME];
-  STRING helptext[MAX_LEN_PACKET];
-  STRING graphic_str[MAX_LEN_NAME];
-  STRING graphic_alt[MAX_LEN_NAME];
+  ASCII name[MAX_LEN_NAME];
+  ASCII helptext[MAX_LEN_PACKET];
+  ASCII graphic_str[MAX_LEN_NAME];
+  ASCII graphic_alt[MAX_LEN_NAME];
 end
 
 PACKET_RULESET_GOVERNMENT=100;sc,lsend
@@ -1054,10 +1055,10 @@
       
   UINT8 num_ruler_titles;
        
-  STRING name[MAX_LEN_NAME];
-  STRING graphic_str[MAX_LEN_NAME];
-  STRING graphic_alt[MAX_LEN_NAME];
-  STRING helptext[MAX_LEN_PACKET];
+  ASCII name[MAX_LEN_NAME];
+  ASCII graphic_str[MAX_LEN_NAME];
+  ASCII graphic_alt[MAX_LEN_NAME];
+  ASCII helptext[MAX_LEN_PACKET];
 end
 
 PACKET_RULESET_TERRAIN_CONTROL=101;sc,lsend
@@ -1073,7 +1074,7 @@
 
   UINT16 river_defense_bonus;           /* % added to defense if Civ2 river */
   UINT16 river_trade_incr;              /* added to trade if Civ2 river */
-  STRING river_help_text[MAX_LEN_PACKET]; # help for Civ2-style rivers
+  ASCII river_help_text[MAX_LEN_PACKET]; # help for Civ2-style rivers
 
   UINT16 fortress_defense_bonus;        /* % added to defense if fortress */
   UINT16 road_superhighway_trade_bonus;  # % added to trade if road/s-highway
@@ -1092,37 +1093,37 @@
 PACKET_RULESET_NATION=102;sc,lsend
   NATION id;
 
-  STRING name[MAX_LEN_NAME];
-  STRING name_plural[MAX_LEN_NAME];
-  STRING graphic_str[MAX_LEN_NAME];
-  STRING graphic_alt[MAX_LEN_NAME];
-  STRING class[MAX_LEN_NAME];
-  STRING legend[MAX_LEN_MSG];
+  TEXT name[MAX_LEN_NAME];
+  TEXT name_plural[MAX_LEN_NAME];
+  ASCII graphic_str[MAX_LEN_NAME];
+  ASCII graphic_alt[MAX_LEN_NAME];
+  ASCII class[MAX_LEN_NAME];
+  ASCII legend[MAX_LEN_MSG];
 
   UINT8 city_style;
   TECH_LIST init_techs[MAX_NUM_TECH_LIST];
 
   UINT8 leader_count;
-  STRING leader_name[MAX_NUM_LEADERS:leader_count][MAX_LEN_NAME];
+  TEXT leader_name[MAX_NUM_LEADERS:leader_count][MAX_LEN_NAME];
   BOOL leader_sex[MAX_NUM_LEADERS:leader_count];
 end
 
 PACKET_RULESET_CITY=103;sc,lsend
   UINT8 style_id; 
   UINT8 techreq;
-  STRING name[MAX_LEN_NAME];
-  STRING citizens_graphic[MAX_LEN_NAME];
-  STRING citizens_graphic_alt[MAX_LEN_NAME];
-  STRING graphic[MAX_LEN_NAME];
-  STRING graphic_alt[MAX_LEN_NAME];
+  ASCII name[MAX_LEN_NAME];
+  ASCII citizens_graphic[MAX_LEN_NAME];
+  ASCII citizens_graphic_alt[MAX_LEN_NAME];
+  ASCII graphic[MAX_LEN_NAME];
+  ASCII graphic_alt[MAX_LEN_NAME];
   SINT8 replaced_by;
 end
 
 PACKET_RULESET_BUILDING=104;sc,lsend
   IMPROVEMENT id;
-  STRING name[MAX_LEN_NAME];
-  STRING graphic_str[MAX_LEN_NAME];
-  STRING graphic_alt[MAX_LEN_NAME];
+  ASCII name[MAX_LEN_NAME];
+  ASCII graphic_str[MAX_LEN_NAME];
+  ASCII graphic_alt[MAX_LEN_NAME];
   TECH tech_req, obsolete_by;
   IMPROVEMENT bldg_req;
   BOOL is_wonder;
@@ -1130,9 +1131,9 @@
   UINT16 build_cost;
   UINT8 upkeep, sabotage;
   UINT8 variant;               /* FIXME: remove when gen-impr obsoletes */
-  STRING soundtag[MAX_LEN_NAME];
-  STRING soundtag_alt[MAX_LEN_NAME];
-  STRING helptext[MAX_LEN_PACKET];
+  ASCII soundtag[MAX_LEN_NAME];
+  ASCII soundtag_alt[MAX_LEN_NAME];
+  ASCII helptext[MAX_LEN_PACKET];
   UINT8 terr_gate_count;
   TERRAIN terr_gate[255:terr_gate_count];
   UINT8 spec_gate_count;
@@ -1150,9 +1151,9 @@
 
   bitvector(bv_terrain_flags) flags;
 
-  STRING terrain_name[MAX_LEN_NAME];
-  STRING graphic_str[MAX_LEN_NAME];
-  STRING graphic_alt[MAX_LEN_NAME];
+  ASCII terrain_name[MAX_LEN_NAME];
+  ASCII graphic_str[MAX_LEN_NAME];
+  ASCII graphic_alt[MAX_LEN_NAME];
 
   UINT8 movement_cost;
   UINT8 defense_bonus;
@@ -1161,19 +1162,19 @@
   UINT8 shield;
   UINT8 trade;
 
-  STRING special_1_name[MAX_LEN_NAME];
+  ASCII special_1_name[MAX_LEN_NAME];
   UINT8 food_special_1;
   UINT8 shield_special_1;
   UINT8 trade_special_1;
-  STRING graphic_str_special_1[MAX_LEN_NAME];
-  STRING graphic_alt_special_1[MAX_LEN_NAME];
+  ASCII graphic_str_special_1[MAX_LEN_NAME];
+  ASCII graphic_alt_special_1[MAX_LEN_NAME];
 
-  STRING special_2_name[MAX_LEN_NAME];
+  ASCII special_2_name[MAX_LEN_NAME];
   UINT8 food_special_2;
   UINT8 shield_special_2;
   UINT8 trade_special_2;
-  STRING graphic_str_special_2[MAX_LEN_NAME];
-  STRING graphic_alt_special_2[MAX_LEN_NAME];
+  ASCII graphic_str_special_2[MAX_LEN_NAME];
+  ASCII graphic_alt_special_2[MAX_LEN_NAME];
 
   UINT8 road_trade_incr;
   UINT8 road_time;
@@ -1189,7 +1190,7 @@
   TERRAIN transform_result;
   UINT8 transform_time;
   
-  STRING helptext[MAX_LEN_PACKET];
+  ASCII helptext[MAX_LEN_PACKET];
 end
 
 /*********************************************************
@@ -1222,7 +1223,7 @@
   UINT8 borders;
   BOOL slow_invasions; add-cap(slow_invasions)
 
-  STRING team_name[MAX_NUM_TEAMS][MAX_LEN_NAME];
+  TEXT team_name[MAX_NUM_TEAMS][MAX_LEN_NAME];
 end
 
 
@@ -1242,11 +1243,11 @@
 
 PACKET_SINGLE_PLAYERLIST_REPLY=111;sc
   UINT8 nplayers;
-  STRING load_filename[MAX_LEN_PACKET];
-  STRING name[MAX_NUM_PLAYERS:nplayers][MAX_LEN_NAME]; 
-  STRING username[MAX_NUM_PLAYERS:nplayers][MAX_LEN_NAME]; 
-  STRING nation_name[MAX_NUM_PLAYERS:nplayers][MAX_LEN_NAME]; 
-  STRING nation_flag[MAX_NUM_PLAYERS:nplayers][MAX_LEN_NAME]; 
+  ASCII load_filename[MAX_LEN_PACKET];
+  TEXT name[MAX_NUM_PLAYERS:nplayers][MAX_LEN_NAME]; 
+  TEXT username[MAX_NUM_PLAYERS:nplayers][MAX_LEN_NAME]; 
+  TEXT nation_name[MAX_NUM_PLAYERS:nplayers][MAX_LEN_NAME]; 
+  ASCII nation_flag[MAX_NUM_PLAYERS:nplayers][MAX_LEN_NAME]; 
   BOOL is_alive[MAX_NUM_PLAYERS:nplayers];
   BOOL is_ai[MAX_NUM_PLAYERS:nplayers];
 end
@@ -1254,14 +1255,14 @@
 PACKET_OPTIONS_SETTABLE_CONTROL=112;sc,handle-via-packet
   UINT16 nids;
   UINT8 ncategories;
-  STRING category_names[256:ncategories][MAX_LEN_NAME];
+  ASCII category_names[256:ncategories][MAX_LEN_NAME];
 end
 
 PACKET_OPTIONS_SETTABLE=113;sc
   UINT16 id;
-  STRING name[MAX_LEN_NAME];
-  STRING short_help[MAX_LEN_PACKET];
-  STRING extra_help[MAX_LEN_PACKET];
+  ASCII name[MAX_LEN_NAME];
+  ASCII short_help[MAX_LEN_PACKET];
+  ASCII extra_help[MAX_LEN_PACKET];
   SSET_TYPE type;
 
   SINT32 val;                                  /* value for bool or int */
@@ -1269,8 +1270,8 @@
   SINT32 min;                                  /* min value for int */
   SINT32 max;                                  /* max value for int */
 
-  STRING strval[MAX_LEN_PACKET];               /* space for string */
-  STRING default_strval[MAX_LEN_PACKET];       /* space for string */
+  ASCII strval[MAX_LEN_PACKET];                        /* space for string */
+  ASCII default_strval[MAX_LEN_PACKET];                /* space for string */
 
   UINT8 category;                              /* which category this is in */
 end
Index: common/shared.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/shared.c,v
retrieving revision 1.109
diff -u -r1.109 shared.c
--- common/shared.c     10 Apr 2004 01:40:17 -0000      1.109
+++ common/shared.c     26 Apr 2004 20:14:28 -0000
@@ -43,7 +43,9 @@
 #endif
 
 #include "astring.h"
+#include "fciconv.h"
 #include "fcintl.h"
+#include "game.h"
 #include "log.h"
 #include "mem.h"
 #include "support.h"
@@ -668,6 +670,29 @@
   assert(FALSE);
 
   exit(EXIT_FAILURE);
+}
+
+/***************************************************************************
+  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);
+
+  if (is_server) {
+    output = data_to_display_string_static(string);
+  } else {
+    output = display_to_local_string_static(string);
+  }
+
+  fputs(output, stream);
+  fflush(stream);
 }
 
 /***************************************************************************
Index: common/shared.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/shared.h,v
retrieving revision 1.124
diff -u -r1.124 shared.h
--- common/shared.h     10 Apr 2004 03:47:49 -0000      1.124
+++ common/shared.h     26 Apr 2004 20:14:28 -0000
@@ -13,6 +13,7 @@
 #ifndef FC__SHARED_H
 #define FC__SHARED_H
 
+#include <stdio.h>
 #include <stdlib.h>            /* size_t */
 #include <string.h>            /* memset */
 
@@ -196,6 +197,9 @@
 #define die(...) real_die(__FILE__, __LINE__, __VA_ARGS__)
 void real_die(const char *file, int line, const char *format, ...)
       fc__attribute((format (printf, 3, 4)));
+
+void fc_fprintf(FILE *stream, const char *format, ...)
+      fc__attribute((format (printf, 2, 3)));
 
 char *user_home_dir(void);
 const char *user_username(void);
Index: server/meta.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/meta.c,v
retrieving revision 1.59
diff -u -r1.59 meta.c
--- server/meta.c       25 Jan 2004 13:55:14 -0000      1.59
+++ server/meta.c       26 Apr 2004 20:14:29 -0000
@@ -140,8 +140,8 @@
 
   dio_put_uint16(&dout, 0);
   dio_put_uint8(&dout, PACKET_UDP_PCKT);
-  dio_put_string(&dout, desc);
-  dio_put_string(&dout, info);
+  dio_put_ascii_string(&dout, desc);
+  dio_put_ascii_string(&dout, info);
 
   size = dio_output_used(&dout);
 
Index: server/sernet.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/sernet.c,v
retrieving revision 1.116
diff -u -r1.116 sernet.c
--- server/sernet.c     17 Mar 2004 00:22:44 -0000      1.116
+++ server/sernet.c     26 Apr 2004 20:14:29 -0000
@@ -1076,12 +1076,12 @@
 
   dio_output_init(&dout, buffer, sizeof(buffer));
   dio_put_uint8(&dout, SERVER_LAN_VERSION);
-  dio_put_string(&dout, hostname);
-  dio_put_string(&dout, port);
-  dio_put_string(&dout, version);
-  dio_put_string(&dout, status);
-  dio_put_string(&dout, players);
-  dio_put_string(&dout, srvarg.metaserver_info_line);
+  dio_put_ascii_string(&dout, hostname);
+  dio_put_ascii_string(&dout, port);
+  dio_put_ascii_string(&dout, version);
+  dio_put_ascii_string(&dout, status);
+  dio_put_ascii_string(&dout, players);
+  dio_put_ascii_string(&dout, srvarg.metaserver_info_line);
   size = dio_output_used(&dout);
 
   /* Sending packet to client with the information gathered above. */
Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.159
diff -u -r1.159 srv_main.c
--- server/srv_main.c   25 Apr 2004 19:03:40 -0000      1.159
+++ server/srv_main.c   26 Apr 2004 20:14:29 -0000
@@ -49,6 +49,7 @@
 #include "city.h"
 #include "dataio.h"
 #include "events.h"
+#include "fciconv.h"
 #include "fcintl.h"
 #include "game.h"
 #include "log.h"
@@ -152,6 +153,9 @@
 {
   /* NLS init */
   init_nls();
+#ifdef ENABLE_NLS
+  bind_textdomain_codeset(PACKAGE, get_data_encoding());
+#endif
 
   /* init server arguments... */
 
@@ -180,6 +184,9 @@
   /* mark as initialized */
   has_been_srv_init = TRUE;
 
+  /* init character encodings. */
+  init_character_encodings(NULL, 1);
+
   /* done */
   return;
 }
@@ -751,11 +758,12 @@
     dio_put_uint8(&dout, 1);
 
     dio_put_bool32(&dout, FALSE);
-    dio_put_string(&dout, _("Your client is too old. To use this server "
-                           "please upgrade your client to a CVS version "
-                           "later than 2003-11-28 or Freeciv 1.15.0 or "
-                           "later."));
-    dio_put_string(&dout, "");
+    dio_put_text_string(&dout,
+                       _("Your client is too old. To use this server "
+                         "please upgrade your client to a CVS version "
+                         "later than 2003-11-28 or Freeciv 1.15.0 or "
+                         "later."));
+    dio_put_text_string(&dout, "");
 
     {
       size_t size = dio_output_used(&dout);

[Prev in Thread] Current Thread [Next in Thread]