t- New config variable "Encoding" added to override the locale's codeset - New … | |
git clone git://src.adamsgaard.dk/vaccinewars | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 203e30e33f384b52c4b4d60050b9722c6d876d90 | |
parent 693a111612284494085ee70284eb8cc05155e689 | |
Author: Ben Webb <[email protected]> | |
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.)</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_P… | |
+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>, <… | |
<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> | |
diff --git a/src/Makefile.am b/src/Makefile.am | |
t@@ -26,7 +26,7 @@ dopewars_DEPENDENCIES = @GUILIB@ @CURSESLIB@ @GTKPORTLIB@ @C… | |
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 <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, … | |
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 m… | |
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 <glib.h> | |
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: [email protected] * | |
+ * 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); | |
+} | |
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: [email protected] * | |
+ * 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__ */ | |
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… | |
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 <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 Retu… | |
* 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++) { |