changeset 6139:3c76c0f47447 draft

(svn r8881) -Feature: Allow built-in newgrf error messages to be translated, and load custom error messages properly.
author maedhros <maedhros@openttd.org>
date Sat, 24 Feb 2007 16:34:37 +0000
parents 994f395e0ad0
children 577a7c5a9ae7
files src/lang/english.txt src/newgrf.cpp src/newgrf_config.cpp src/newgrf_config.h src/newgrf_gui.cpp
diffstat 5 files changed, 106 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -2896,12 +2896,22 @@
 STR_NEWGRF_SET_PARAMETERS                                       :{BLACK}Set parameters
 STR_NEWGRF_TIP                                                  :{BLACK}A list of all the Newgrf sets that you have installed. Click a set to change the settings
 STR_NEWGRF_NO_FILES_INSTALLED                                   :{BLACK}There are currently no newgrf files installed! Please refer to the manual for instructions on installing new graphics
-STR_NEWGRF_ERROR_MSG                                            :{RED}{STRING}
 STR_NEWGRF_FILENAME                                             :{BLACK}Filename: {SILVER}{STRING}
 STR_NEWGRF_GRF_ID                                               :{BLACK}GRF ID: {SILVER}{STRING}
 STR_NEWGRF_MD5SUM                                               :{BLACK}MD5sum: {SILVER}{STRING}
 STR_NEWGRF_CONFIRMATION_TEXT                                    :{YELLOW}You are about to make changes to a running game; this can crash OpenTTD.{}Are you absolutely sure about this?
 
+STR_NEWGRF_ERROR_MSG_INFO                                       :{SILVER}{STRING}
+STR_NEWGRF_ERROR_MSG_WARNING                                    :{RED}Warning: {SILVER}{STRING}
+STR_NEWGRF_ERROR_MSG_ERROR                                      :{RED}Error: {SILVER}{STRING}
+STR_NEWGRF_ERROR_MSG_FATAL                                      :{RED}Fatal: {SILVER}{STRING}
+STR_NEWGRF_ERROR_VERSION_NUMBER                                 :{STRING} will not work with the TTDPatch version reported by OpenTTD.
+STR_NEWGRF_ERROR_DOS_OR_WINDOWS                                 :{STRING} is for the {STRING} version of TTD.
+STR_NEWGRF_ERROR_UNSET_SWITCH                                   :{STRING} is designed to be used with {STRING}
+STR_NEWGRF_ERROR_INVALID_PARAMETER                              :Invalid parameter for {STRING}: parameter {STRING} ({NUM})
+STR_NEWGRF_ERROR_LOAD_BEFORE                                    :{STRING} must be loaded before {STRING}.
+STR_NEWGRF_ERROR_LOAD_AFTER                                     :{STRING} must be loaded after {STRING}.
+
 STR_NEWGRF_ADD                                                  :{BLACK}Add
 STR_NEWGRF_ADD_TIP                                              :{BLACK}Add a NewGRF file to the list
 STR_NEWGRF_REMOVE                                               :{BLACK}Remove
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -2644,7 +2644,7 @@
 }
 
 /* Action 0x0B */
-static void GRFError(byte *buf, int len)
+static void GRFLoadError(byte *buf, int len)
 {
 	/* <0B> <severity> <language-id> <message-id> [<message...> 00] [<data...>] 00 [<parnum>]
 	 *
@@ -2659,44 +2659,54 @@
 	 * S message       for custom messages (message-id FF), text of the message
 	 *                 not present for built-in messages.
 	 * V data          additional data for built-in (or custom) messages
-	 * B parnum        see action 6, only used with built-in message 03 */
-	/* TODO: For now we just show the message, sometimes incomplete and never translated. */
-
-	static const char *const msgstr[] = {
-		"%sRequires at least pseudo-TTDPatch version %s.",
-		"%sThis file is for %s version of TTD.",
-		"%sDesigned to be used with %s",
-		"%sInvalid parameter %s.",
-		"%sMust be loaded before %s.",
-		"%sMust be loaded after %s.",
-		"%s%s"
+	 * B parnum        parameter numbers to be shown in the message (maximum of 2) */
+
+	static const StringID msgstr[] = {
+		STR_NEWGRF_ERROR_VERSION_NUMBER,
+		STR_NEWGRF_ERROR_DOS_OR_WINDOWS,
+		STR_NEWGRF_ERROR_UNSET_SWITCH,
+		STR_NEWGRF_ERROR_INVALID_PARAMETER,
+		STR_NEWGRF_ERROR_LOAD_BEFORE,
+		STR_NEWGRF_ERROR_LOAD_AFTER
 	};
 
-	static const char *const sevstr[] = {
-		"",
-		"Warning: ",
-		"Error: ",
-		"Fatal: ",
+	static const StringID sevstr[] = {
+		STR_NEWGRF_ERROR_MSG_INFO,
+		STR_NEWGRF_ERROR_MSG_WARNING,
+		STR_NEWGRF_ERROR_MSG_ERROR,
+		STR_NEWGRF_ERROR_MSG_FATAL
 	};
 
-	if (!check_length(len, 6, "GRFError")) return;
+	/* AddGRFString expects the string to be referred to by an id in the newgrf
+	 * file. Errors messages are never referred to however, so invent ids that
+	 * are unlikely to be reached in a newgrf file so they don't overwrite
+	 * anything else. */
+	enum {
+		MESSAGE_STRING_ID = MAX_UVALUE(StringID) - 1,
+		MESSAGE_DATA_ID   = MAX_UVALUE(StringID)
+	};
+
+	if (!check_length(len, 6, "GRFLoadError")) return;
+
+	/* For now we can only show one message per newgrf file. */
+	if (_cur_grfconfig->error != NULL) return;
 
 	buf++; /* Skip the action byte. */
 	byte severity   = grf_load_byte(&buf);
-	buf++; /* TODO: Language id. */
+	byte lang       = grf_load_byte(&buf);
 	byte message_id = grf_load_byte(&buf);
 	len -= 4;
 
 	/* Skip the error until the activation stage unless bit 7 of the severity
 	 * is set. */
 	if (!HASBIT(severity, 7) && _cur_stage < GLS_ACTIVATION) {
-		grfmsg(7, "Skipping non-fatal GRFError in stage 1");
+		grfmsg(7, "Skipping non-fatal GRFLoadError in stage 1");
 		return;
 	}
 	CLRBIT(severity, 7);
 
 	if (severity >= lengthof(sevstr)) {
-		grfmsg(7, "GRFError: Invalid severity id %d. Setting to 2 (non-fatal error).", severity);
+		grfmsg(7, "GRFLoadError: Invalid severity id %d. Setting to 2 (non-fatal error).", severity);
 		severity = 2;
 	} else if (severity == 3) {
 		/* This is a fatal error, so make sure the GRF is deactivated and no
@@ -2708,23 +2718,46 @@
 	}
 
 	if (message_id >= lengthof(msgstr) && message_id != 0xFF) {
-		grfmsg(7, "GRFError: Invalid message id.");
+		grfmsg(7, "GRFLoadError: Invalid message id.");
 		return;
 	}
 
 	if (len <= 1) {
-		grfmsg(7, "GRFError: No message data supplied.");
+		grfmsg(7, "GRFLoadError: No message data supplied.");
 		return;
 	}
 
-	char message[512];
-	snprintf(message, lengthof(message), msgstr[(message_id == 0xFF) ? lengthof(msgstr) - 1 : message_id], sevstr[severity], grf_load_string(&buf, len));
-
-	if (_cur_grfconfig->error == NULL) {
-		_cur_grfconfig->error = strdup(message);
+	bool new_scheme = _cur_grffile->grf_version >= 7;
+	GRFError *error = CallocT<GRFError>(1);
+
+	error->severity = sevstr[severity];
+
+	if (message_id == 0xFF) {
+		/* This is a custom error message. */
+		const char *message = grf_load_string(&buf, len);
+		len -= (strlen(message) + 1);
+
+		error->message = AddGRFString(_cur_grffile->grfid, MESSAGE_STRING_ID, lang, new_scheme, message, STR_UNDEFINED);
+	} else {
+		error->message = msgstr[message_id];
 	}
 
-	grfmsg(0, message);
+	if (len > 0) {
+		const char *data = grf_load_string(&buf, len);
+		len -= (strlen(data) + 1);
+
+		error->data = AddGRFString(_cur_grffile->grfid, MESSAGE_DATA_ID, lang, new_scheme, data, STR_UNDEFINED);
+	}
+
+	/* Only two parameter numbers can be used in the string. */
+	uint i = 0;
+	for (; i < 2 && len > 0; i++) {
+		error->param_number[i] = grf_load_byte(&buf);
+		len--;
+	}
+	error->num_params = i;
+
+	_cur_grfconfig->error = error;
 }
 
 /* Action 0x0C */
@@ -3715,7 +3748,7 @@
 		/* 0x08 */ { ScanInfo, NULL,      NULL,            GRFInfo,    GRFInfo, },
 		/* 0x09 */ { NULL,     NULL,      NULL,            SkipIf,     SkipIf, },
 		/* 0x0A */ { NULL,     NULL,      NULL,            NULL,       SpriteReplace, },
-		/* 0x0B */ { NULL,     NULL,      NULL,            GRFError,   GRFError, },
+		/* 0x0B */ { NULL,     NULL,      NULL,            GRFLoadError, GRFLoadError, },
 		/* 0x0C */ { NULL,     NULL,      NULL,            GRFComment, GRFComment, },
 		/* 0x0D */ { NULL,     SafeParamSet, NULL,         ParamSet,   ParamSet, },
 		/* 0x0E */ { NULL,     SafeGRFInhibit, NULL,       GRFInhibit, GRFInhibit, },
--- a/src/newgrf_config.cpp
+++ b/src/newgrf_config.cpp
@@ -124,7 +124,10 @@
 		if (src->filename != NULL) c->filename = strdup(src->filename);
 		if (src->name     != NULL) c->name     = strdup(src->name);
 		if (src->info     != NULL) c->info     = strdup(src->info);
-		if (src->error    != NULL) c->error    = strdup(src->error);
+		if (src->error    != NULL) {
+			c->error = CallocT<GRFError>(1);
+			memcpy(c->error, src->error, sizeof(GRFError));
+		}
 
 		*dst = c;
 		dst = &c->next;
--- a/src/newgrf_config.h
+++ b/src/newgrf_config.h
@@ -3,6 +3,8 @@
 #ifndef NEWGRF_CONFIG_H
 #define NEWGRF_CONFIG_H
 
+#include "openttd.h"
+
 /* GRF config bit flags */
 typedef enum {
 	GCF_DISABLED,  ///< GRF file is disabled
@@ -20,11 +22,19 @@
 	uint8 md5sum[16];
 } GRF;
 
+typedef struct GRFError {
+	StringID message;
+	StringID data;
+	StringID severity;
+	uint8 num_params;
+	uint8 param_number[2];
+} GRFError;
+
 typedef struct GRFConfig : public GRFIdentifier {
 	char *filename;
 	char *name;
 	char *info;
-	char *error;
+	GRFError *error;
 
 	uint8 flags;
 	uint32 param[0x80];
--- a/src/newgrf_gui.cpp
+++ b/src/newgrf_gui.cpp
@@ -11,6 +11,7 @@
 #include "table/sprites.h"
 #include "newgrf.h"
 #include "newgrf_config.h"
+#include "strings.h"
 #include "helpers.hpp"
 
 
@@ -44,8 +45,22 @@
 	char buff[256];
 
 	if (c->error != NULL) {
-		SetDParamStr(0, c->error);
-		y += DrawStringMultiLine(x, y, STR_NEWGRF_ERROR_MSG, w);
+		SetDParamStr(0, c->filename);
+		SetDParam(1, c->error->data);
+		for (uint i = 0; i < c->error->num_params; i++) {
+			uint32 param = 0;
+			byte param_number = c->error->param_number[i];
+
+			if (param_number < c->num_params) param = c->param[param_number];
+
+			SetDParam(2 + i, param);
+		}
+
+		char message[512];
+		GetString(message, c->error->message, lastof(message));
+
+		SetDParamStr(0, message);
+		y += DrawStringMultiLine(x, y, c->error->severity, w);
 	}
 
 	/* Draw filename or not if it is not known (GRF sent over internet) */