t- New config variable "Encoding" added to override the locale's codeset - New "convert" module added to translate strings between codesets; all old code in gtk_client.c and configfile.c changed to use this API - UTF8 ability added to network code; as yet, it is non-functional, but will be used to translate network messages to and from UTF8 if necessary - vaccinewars - be a doctor and try to vaccinate the world
git clone git://src.adamsgaard.dk/vaccinewars
Log
Files
Refs
README
LICENSE
---
commit 203e30e33f384b52c4b4d60050b9722c6d876d90
parent 693a111612284494085ee70284eb8cc05155e689
Author: Ben Webb 
Date:   Mon,  5 Aug 2002 11:35:44 +0000

- New config variable "Encoding" added to override the locale's codeset
- New "convert" module added to translate strings between codesets; all
  old code in gtk_client.c and configfile.c changed to use this API
- UTF8 ability added to network code; as yet, it is non-functional, but
  will be used to translate network messages to and from UTF8 if necessary


Diffstat:
  M doc/configfile.html                 |      11 ++++++++++-
  M src/Makefile.am                     |       2 +-
  M src/configfile.c                    |      82 ++++++++++++++++++++-----------
  M src/configfile.h                    |       1 +
  A src/convert.c                       |     136 +++++++++++++++++++++++++++++++
  A src/convert.h                       |      45 +++++++++++++++++++++++++++++++
  M src/dopewars.c                      |       8 ++++++++
  M src/dopewars.h                      |       4 +++-
  M src/gui_client/gtk_client.c         |      63 ++-----------------------------
  M src/message.c                       |       1 +

10 files changed, 262 insertions(+), 91 deletions(-)
---
diff --git a/doc/configfile.html b/doc/configfile.html
t@@ -638,6 +638,15 @@ feature.)
 
If TRUE, then the server will keep track of the price you paid for any drugs, and clients will display this information if available.
+
Encoding="UTF-8"
+
Specifies that any text in the configuration files is in "UTF-8" +encoding. This variable is only supported if dopewars is built on a Unix +system and linked against GLib version 2. This influences both how the file +is read and written. If this variable is set to a blank string (the default) +then it will be assumed that your configuration files are in the locale's +default encoding - e.g. ISO-8859-1 for C or POSIX locales, ISO-8859-2 for pl_PL, +ISO-8859-15 for es_ES@euro, or UTF-8 for en_GB.UTF-8.
+
Sounds.FightHit="hit.wav"
Plays the sound file "hit.wav" when you fire a gun and hit your target. The sound must be installed on your system, and you must be using t@@ -653,7 +662,7 @@ can be configured in the same way are: FightMiss, FightReload,
  • Main index
  • - Last update: 16-07-2002
    + Last update: 04-08-2002
    Valid XHTML 1.1

    diff --git a/src/Makefile.am b/src/Makefile.am
    t@@ -26,7 +26,7 @@ dopewars_DEPENDENCIES = @GUILIB@ @CURSESLIB@ @GTKPORTLIB@ @CURSESPORTLIB@ @INTLL
     
     bin_PROGRAMS = dopewars
     dopewars_SOURCES = admin.c admin.h AIPlayer.c AIPlayer.h util.c util.h \
    -                   configfile.c configfile.h \
    +                   configfile.c configfile.h convert.c convert.h \
                        dopewars.c dopewars.h error.c error.h log.c log.h \
                        message.c message.h network.c network.h nls.h \
                        serverside.c serverside.h sound.c sound.h \
    diff --git a/src/configfile.c b/src/configfile.c
    t@@ -31,6 +31,7 @@
     #include               /* For isprint */
     #include 
     
    +#include "convert.h"            /* For Converter */
     #include "dopewars.h"           /* For struct GLOBALS etc. */
     #include "nls.h"                /* For _ function */
     #include "error.h"              /* For ErrStrFromErrno */
    t@@ -77,35 +78,12 @@ static void PrintEscaped(FILE *fp, gchar *str)
     }
     
     /*
    - * Converts the given string from UTF-8 to the locale's codeset. If the
    - * locale codeset already is UTF-8, returns a copy of the original
    - * string. The returned string is dynamically allocated, and should be
    - * later g_free'd by the caller.
    - */
    -static gchar *ToLocaleCodeset(const gchar *origstr)
    -{
    -#ifdef HAVE_GLIB2
    -  if (!g_get_charset(NULL)) {
    -    gchar *convstr = g_locale_from_utf8(origstr, -1, NULL, NULL, NULL);
    -    if (convstr) {
    -      return convstr;
    -    } else {
    -      return g_strdup("[Could not convert string from UTF8]");
    -    }
    -  } else {
    -    return g_strdup(origstr);
    -  }
    -#else
    -  return g_strdup(origstr);
    -#endif
    -}
    -
    -/*
      * Writes a single configuration file variable (identified by GlobalIndex
      * and StructIndex) to the specified file, in a format suitable for reading
      * back in (via. ParseNextConfig and friends).
      */
    -static void WriteConfigValue(FILE *fp, int GlobalIndex, int StructIndex)
    +static void WriteConfigValue(FILE *fp, Converter *conv, int GlobalIndex,
    +                             int StructIndex)
     {
       gchar *GlobalName;
     
    t@@ -133,19 +111,24 @@ static void WriteConfigValue(FILE *fp, int GlobalIndex, int StructIndex)
         gchar *convstr;
     
         fprintf(fp, "%s = \"", GlobalName);
    -    convstr = ToLocaleCodeset(*GetGlobalString(GlobalIndex, StructIndex));
    +    convstr = Conv_ToExternal(conv,
    +                              *GetGlobalString(GlobalIndex, StructIndex), -1);
         PrintEscaped(fp, convstr);
         g_free(convstr);
         fprintf(fp, "\"\n");
       } else if (Globals[GlobalIndex].StringList) {
         int i;
    +    gchar *convstr;
     
         fprintf(fp, "%s = { ", GlobalName);
         for (i = 0; i < *Globals[GlobalIndex].MaxIndex; i++) {
           if (i > 0)
             fprintf(fp, ", ");
           fputc('"', fp);
    -      PrintEscaped(fp, (*Globals[GlobalIndex].StringList)[i]);
    +      convstr = Conv_ToExternal(conv,
    +                                (*Globals[GlobalIndex].StringList)[i], -1);
    +      PrintEscaped(fp, convstr);
    +      g_free(convstr);
           fputc('"', fp);
         }
         fprintf(fp, " }\n");
    t@@ -209,18 +192,24 @@ static void ReadFileToString(FILE *fp, gchar *str, int matchlen)
     static void WriteConfigFile(FILE *fp)
     {
       int i, j;
    +  Converter *conv = Conv_New();
    +
    +  if (Encoding && Encoding[0]) {
    +    Conv_SetCodeset(conv, Encoding);
    +  }
     
       for (i = 0; i < NUMGLOB; i++) {
         if (Globals[i].Modified) {
           if (Globals[i].NameStruct[0]) {
             for (j = 1; j <= *Globals[i].MaxIndex; j++) {
    -          WriteConfigValue(fp, i, j);
    +          WriteConfigValue(fp, conv, i, j);
             }
           } else {
    -        WriteConfigValue(fp, i, 0);
    +        WriteConfigValue(fp, conv, i, 0);
           }
         }
       }
    +  Conv_Free(conv);
     }
     
     gboolean UpdateConfigFile(const gchar *cfgfile)
    t@@ -261,3 +250,38 @@ gboolean UpdateConfigFile(const gchar *cfgfile)
       g_free(defaultfile);
       return TRUE;
     }
    +
    +static void ConvertString(Converter *conv, gchar **str)
    +{
    +  AssignName(str, Conv_ToInternal(conv, *str, -1));
    +}
    +
    +void ConvertConfigFile(void)
    +{
    +  int i, j;
    +  struct GLOBALS *gvar;
    +  Converter *conv = Conv_New();
    +
    +  if (Encoding && Encoding[0]) {
    +    Conv_SetCodeset(conv, Encoding);
    +  }
    +
    +  for (i = 0; i < NUMGLOB; i++) {
    +    gvar = &Globals[i];
    +    if (gvar->StringVal) {
    +      if (gvar->StructListPt) {
    +        for (j = 1; j <= *gvar->MaxIndex; j++) {
    +          ConvertString(conv, GetGlobalString(i, j));
    +        }
    +      } else {
    +        ConvertString(conv, GetGlobalString(i, 0));
    +      }
    +    } else if (gvar->StringList) {
    +      for (j = 0; j < *gvar->MaxIndex; j++) {
    +        ConvertString(conv, (*gvar->StringList) + j);
    +      }
    +    }
    +  }
    +
    +  Conv_Free(conv);
    +}
    diff --git a/src/configfile.h b/src/configfile.h
    t@@ -26,5 +26,6 @@
     #include 
     
     gboolean UpdateConfigFile(const gchar *cfgfile);
    +void ConvertConfigFile(void);
     
     #endif /* __DP_CONFIGFILE_H__ */
    diff --git a/src/convert.c b/src/convert.c
    t@@ -0,0 +1,136 @@
    +/************************************************************************
    + * convert.c      Codeset conversion functions                          *
    + * Copyright (C)  2002  Ben Webb                                        *
    + *                Email: ben@bellatrix.pcl.ox.ac.uk                     *
    + *                WWW: http://dopewars.sourceforge.net/                 *
    + *                                                                      *
    + * 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       *
    + * of the License, 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.                         *
    + *                                                                      *
    + * You should have received a copy of the GNU General Public License    *
    + * along with this program; if not, write to the Free Software          *
    + * Foundation, Inc., 59 Temple Place - Suite 330, Boston,               *
    + *                   MA  02111-1307, USA.                               *
    + ************************************************************************/
    +
    +#ifdef HAVE_CONFIG_H
    +# include 
    +#endif
    +
    +#include 
    +#include 
    +
    +#include "convert.h"
    +
    +static gchar *int_codeset = NULL;
    +
    +static const gchar *FixedCodeset(const gchar *codeset)
    +{
    +  if (strcmp(codeset, "ANSI_X3.4-1968") == 0
    +      || strcmp(codeset, "ASCII") == 0) {
    +    return "ISO-8859-1";
    +  } else {
    +    return codeset;
    +  }
    +}
    +
    +void Conv_SetInternalCodeset(const gchar *codeset)
    +{
    +  g_free(int_codeset);
    +  int_codeset = g_strdup(FixedCodeset(codeset));
    +}
    +
    +static const gchar *GetLocaleCodeset(void)
    +{
    +#ifdef HAVE_GLIB2
    +  const gchar *codeset;
    +
    +  g_get_charset(&codeset);
    +  return FixedCodeset(codeset);
    +#else
    +  return "ISO-8859-1";
    +#endif
    +}
    +
    +Converter *Conv_New(void)
    +{
    +  Converter *conv;
    +
    +  conv = g_new(Converter, 1);
    +  conv->ext_codeset = g_strdup(GetLocaleCodeset());
    +  if (!int_codeset) {
    +    int_codeset = g_strdup(GetLocaleCodeset());
    +  }
    +  return conv;
    +}
    +
    +void Conv_Free(Converter *conv)
    +{
    +  g_free(conv->ext_codeset);
    +  g_free(conv);
    +}
    +
    +void Conv_SetCodeset(Converter *conv, const gchar *codeset)
    +{
    +  g_free(conv->ext_codeset);
    +  conv->ext_codeset = g_strdup(FixedCodeset(codeset));
    +}
    +
    +gboolean Conv_Needed(Converter *conv)
    +{
    +#ifdef HAVE_GLIB2
    +  return (strcmp(conv->ext_codeset, int_codeset) != 0
    +          || strcmp(int_codeset, "UTF-8") == 0);
    +#else
    +  return FALSE;
    +#endif
    +}
    +
    +static gchar *do_convert(const gchar *from_codeset, const gchar *to_codeset,
    +                         const gchar *from_str, size_t from_len)
    +{
    +#ifdef HAVE_GLIB2
    +  gchar *to_str;
    +
    +  if (strcmp(to_codeset, "UTF-8") == 0 && strcmp(from_codeset, "UTF-8") == 0) {
    +    const gchar *end;
    +
    +    to_str = g_strdup(from_str);
    +    if (!g_utf8_validate(to_str, -1, &end) && end) {
    +      *((gchar *)end) = '\0';
    +    }
    +    return to_str;
    +  } else {
    +    to_str = g_convert(from_str, from_len, to_codeset, from_codeset,
    +                       NULL, NULL, NULL);
    +    if (to_str) {
    +      return to_str;
    +    } else {
    +      return g_strdup("[?]");
    +    }
    +  }
    +#else
    +  if (from_len == -1) {
    +    return g_strdup(from_str);
    +  } else {
    +    return g_strndup(from_str, from_len);
    +  }
    +#endif
    +}
    +
    +gchar *Conv_ToExternal(Converter *conv, const gchar *int_str, size_t len)
    +{
    +  return do_convert(int_codeset, conv->ext_codeset, int_str, len);
    +}
    +
    +gchar *Conv_ToInternal(Converter *conv, const gchar *ext_str, size_t len)
    +{
    +  return do_convert(conv->ext_codeset, int_codeset, ext_str, len);
    +}
    diff --git a/src/convert.h b/src/convert.h
    t@@ -0,0 +1,45 @@
    +/************************************************************************
    + * convert.h      Header file for codeset conversion functions          *
    + * Copyright (C)  2002  Ben Webb                                        *
    + *                Email: ben@bellatrix.pcl.ox.ac.uk                     *
    + *                WWW: http://dopewars.sourceforge.net/                 *
    + *                                                                      *
    + * 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       *
    + * of the License, 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.                         *
    + *                                                                      *
    + * You should have received a copy of the GNU General Public License    *
    + * along with this program; if not, write to the Free Software          *
    + * Foundation, Inc., 59 Temple Place - Suite 330, Boston,               *
    + *                   MA  02111-1307, USA.                               *
    + ************************************************************************/
    +
    +#ifndef __DP_CONVERT_H__
    +#define __DP_CONVERT_H__
    +
    +#ifdef HAVE_CONFIG_H
    +# include 
    +#endif
    +
    +#include 
    +
    +typedef struct _Converter Converter;
    +struct _Converter {
    +  gchar *ext_codeset;
    +};
    +
    +void Conv_SetInternalCodeset(const gchar *codeset);
    +Converter *Conv_New(void);
    +void Conv_SetCodeset(Converter *conv, const gchar *codeset);
    +gboolean Conv_Needed(Converter *conv);
    +gchar *Conv_ToExternal(Converter *conv, const gchar *int_str, size_t len);
    +gchar *Conv_ToInternal(Converter *conv, const gchar *ext_str, size_t len);
    +void Conv_Free(Converter *conv);
    +
    +#endif /* __DP_CONVERT_H__ */
    diff --git a/src/dopewars.c b/src/dopewars.c
    t@@ -80,6 +80,7 @@ unsigned Port = 7902;
     gboolean Sanitized, ConfigVerbose, DrugValue;
     gchar *HiScoreFile = NULL, *ServerName = NULL, *ConvertFile = NULL;
     gchar *ServerMOTD = NULL, *WantedPlugin = NULL, *BindAddress = NULL;
    +gchar *Encoding = NULL;
     gboolean WantHelp, WantVersion, WantAntique, WantColour, WantNetwork;
     gboolean WantConvert, WantAdmin;
     
    t@@ -226,6 +227,11 @@ struct GLOBALS Globals[] = {
       /* The following strings are the helptexts for all the options that can
        * be set in a dopewars configuration file, or in the server. See
        * doc/configfile.html for more detailed explanations. */
    +#ifdef HAVE_GLIB2
    +  {NULL, NULL, NULL, &Encoding, NULL, "Encoding",
    +   N_("Charset encoding of the config file (e.g. UTF-8)"), NULL, NULL,
    +   0, "", NULL, NULL, FALSE, 0},
    +#endif
       {&Port, NULL, NULL, NULL, NULL, "Port", N_("Network port to connect to"),
        NULL, NULL, 0, "", NULL, NULL, FALSE, 0},
       {NULL, NULL, NULL, &HiScoreFile, NULL, "HiScoreFile",
    t@@ -2331,9 +2337,11 @@ void SetupParameters(void)
       /* Set hard-coded default values */
       g_free(ServerName);
       g_free(ServerMOTD);
    +  g_free(Encoding);
       g_free(BindAddress);
       ServerName = g_strdup("localhost");
       ServerMOTD = g_strdup("");
    +  Encoding = g_strdup("");
       BindAddress = g_strdup("");
       g_free(WebBrowser);
       WebBrowser = g_strdup("/usr/bin/mozilla");
    diff --git a/src/dopewars.h b/src/dopewars.h
    t@@ -66,6 +66,8 @@ typedef enum {
                                      * notation */
       A_DONEFIGHT,                  /* A fight is only considered over once the
                                      * client sends the server a C_DONE message */
    +  A_UTF8,                       /* All strings are sent over the network using
    +                                 * UTF-8 (Unicode) encoding */
       A_NUM                         /* N.B. Must be last */
     } AbilType;
     
    t@@ -169,7 +171,7 @@ extern int NumLocation, NumGun, NumCop, NumDrug, NumSubway, NumPlaying,
                NumStoppedTo;
     extern int DebtInterest, BankInterest;
     extern gchar *HiScoreFile, *ServerName, *ConvertFile, *ServerMOTD,
    -             *WantedPlugin, *BindAddress;
    +             *WantedPlugin, *BindAddress, *Encoding;
     extern gboolean WantHelp, WantVersion, WantAntique, WantColour,
                     WantNetwork, WantConvert, WantAdmin;
     #ifdef CYGWIN
    diff --git a/src/gui_client/gtk_client.c b/src/gui_client/gtk_client.c
    t@@ -28,6 +28,8 @@
     #include 
     #include 
     
    +#include "configfile.h"
    +#include "convert.h"
     #include "dopewars.h"
     #include "gtk_client.h"
     #include "message.h"
    t@@ -2117,64 +2119,6 @@ static void SetIcon(GtkWidget *window, gchar **xpmdata)
     #endif
     }
     
    -#ifdef HAVE_GLIB2
    -/*
    - * Converts a single string from the locale's codeset (e.g. ISO-8859-1)
    - * to UTF8. (If the locale codeset is already UTF8, and the string is
    - * invalid, truncate it at the first invalid character.)
    - */
    -static void ConvertString(gchar **str)
    -{
    -  gchar *utf8str;
    -  const gchar *end;
    -
    -  if (str && *str && **str) {
    -    if (g_get_charset(NULL)) {
    -      if (!g_utf8_validate(*str, strlen(*str), &end) && end) {
    -        *((gchar *)end) = '\0';
    -      }
    -    } else {
    -      utf8str = g_locale_to_utf8(*str, strlen(*str), NULL, NULL, NULL);
    -      if (utf8str) {
    -        AssignName(str, utf8str);
    -        g_free(utf8str);
    -      }
    -    }
    -  }
    -}
    -
    -/*
    - * Converts all configuration file strings from the locale's encoding to
    - * UTF-8. This is a bit of a hack, as ideally all strings would be in
    - * UTF-8 anyway, but we need to support old GTK+1 and curses builds,
    - * which are not Unicode-aware. (N.B. As the default location names, etc.
    - * are set before bind_text_domain_codeset is called, if the locale's
    - * encoding is not UTF-8, then these strings will not be UTF-8 either.)
    - */
    -static void ConvertToUTF8(void)
    -{
    -  int i, j;
    -  struct GLOBALS *gvar;
    -
    -  for (i = 0; i < NUMGLOB; i++) {
    -    gvar = &Globals[i];
    -    if (gvar->StringVal) {
    -      if (gvar->StructListPt) {
    -        for (j = 1; j <= *gvar->MaxIndex; j++) {
    -          ConvertString(GetGlobalString(i, j));
    -        }
    -      } else {
    -        ConvertString(GetGlobalString(i, 0));
    -      }
    -    } else if (gvar->StringList) {
    -      for (j = 0; j < *gvar->MaxIndex; j++) {
    -        ConvertString((*gvar->StringList) + j);
    -      }
    -    }
    -  }
    -}
    -#endif
    -
     static void make_tags(GtkTextView *textview)
     {
     #ifdef HAVE_GLIB2
    t@@ -2216,7 +2160,8 @@ gboolean GtkLoop(int *argc, char **argv[], gboolean ReturnOnFail)
        * all translations in this encoding here. */
       bind_textdomain_codeset(PACKAGE, "UTF-8");
     
    -  ConvertToUTF8();
    +  Conv_SetInternalCodeset("UTF-8");
    +  ConvertConfigFile();
       WantUTF8Errors(TRUE);
     #endif
     
    diff --git a/src/message.c b/src/message.c
    t@@ -247,6 +247,7 @@ void InitAbilities(Player *Play)
       Play->Abil.Local[A_DRUGVALUE] = (DrugValue ? TRUE : FALSE);
       Play->Abil.Local[A_TSTRING] = TRUE;
       Play->Abil.Local[A_DONEFIGHT] = TRUE;
    +  Play->Abil.Local[A_UTF8] = FALSE;
     
       if (!Network) {
         for (i = 0; i < A_NUM; i++) {