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
(HTM) git clone git://src.adamsgaard.dk/vaccinewars
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
(DIR) commit 203e30e33f384b52c4b4d60050b9722c6d876d90
(DIR) parent 693a111612284494085ee70284eb8cc05155e689
(HTM) Author: Ben Webb <ben@salilab.org>
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(-)
---
(DIR) diff --git a/doc/configfile.html b/doc/configfile.html
t@@ -638,6 +638,15 @@ feature.)</dd>
<dd>If TRUE, then the server will keep track of the price you paid for
any drugs, and clients will display this information if available.</dd>
+<dt><b>Encoding=<i>"UTF-8"</i></b></dt>
+<dd>Specifies that any text in the configuration files is in <i>"UTF-8"</i>
+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.</dd>
+
<dt><b>Sounds.FightHit=<i>"hit.wav"</i></b></dt>
<dd>Plays the sound file <i>"hit.wav"</i> 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: <b>FightMiss</b>, <b>FightReload</b>,
<li><a href="index.html">Main index</a></li>
</ul>
<p>
- Last update: <b>16-07-2002</b><br />
+ Last update: <b>04-08-2002</b><br />
Valid <a href="http://validator.w3.org/check/referer">XHTML 1.1</a>
</p>
</body>
(DIR) 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 \
(DIR) diff --git a/src/configfile.c b/src/configfile.c
t@@ -31,6 +31,7 @@
#include <ctype.h> /* For isprint */
#include <glib.h>
+#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);
+}
(DIR) diff --git a/src/configfile.h b/src/configfile.h
t@@ -26,5 +26,6 @@
#include <glib.h>
gboolean UpdateConfigFile(const gchar *cfgfile);
+void ConvertConfigFile(void);
#endif /* __DP_CONFIGFILE_H__ */
(DIR) 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 <config.h>
+#endif
+
+#include <string.h>
+#include <glib.h>
+
+#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);
+}
(DIR) 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 <config.h>
+#endif
+
+#include <glib.h>
+
+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__ */
(DIR) 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");
(DIR) 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
(DIR) diff --git a/src/gui_client/gtk_client.c b/src/gui_client/gtk_client.c
t@@ -28,6 +28,8 @@
#include <ctype.h>
#include <string.h>
+#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
(DIR) 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++) {