changeset 17147:5ffc4ae6944d draft

(svn r21885) -Fix [FS#4422]: NewGRF string codes 0x80 and 0x81 were broken since the typechecking of string parameters
author yexo <yexo@openttd.org>
date Fri, 21 Jan 2011 23:10:02 +0000
parents 64e9ac7856b0
children 848eb1ffb17d
files src/newgrf_text.cpp src/strings.cpp src/table/control_codes.h
diffstat 3 files changed, 32 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/newgrf_text.cpp
+++ b/src/newgrf_text.cpp
@@ -447,7 +447,7 @@
 				StringID string;
 				string  = ((uint8)*str++);
 				string |= ((uint8)*str++) << 8;
-				d += Utf8Encode(d, SCC_STRING_ID);
+				d += Utf8Encode(d, SCC_NEWGRF_STRINL);
 				d += Utf8Encode(d, MapGRFStringID(grfid, string));
 				break;
 			}
@@ -1059,7 +1059,7 @@
 			return SCC_CURRENCY;
 
 		case SCC_NEWGRF_PRINT_STRING_ID:
-			return SCC_STRING1;
+			return SCC_NEWGRF_PRINT_STRING_ID;
 
 		case SCC_NEWGRF_PRINT_DATE:
 			return SCC_DATE_LONG;
--- a/src/strings.cpp
+++ b/src/strings.cpp
@@ -37,6 +37,7 @@
 #include "smallmap_gui.h"
 #include "window_func.h"
 #include "debug.h"
+#include <stack>
 
 #include "table/strings.h"
 #include "table/control_codes.h"
@@ -121,6 +122,8 @@
 const char *GetStringPtr(StringID string)
 {
 	switch (GB(string, 11, 5)) {
+		/* GetGRFStringPtr doesn't handle 0xD4xx ids, we need to convert those to 0xD0xx. */
+		case 26: return GetStringPtr(GetGRFStringID(0, 0xD000 + GB(string, 0, 10)));
 		case 28: return GetGRFStringPtr(GB(string, 0, 11));
 		case 29: return GetGRFStringPtr(GB(string, 0, 11) + 0x0800);
 		case 30: return GetGRFStringPtr(GB(string, 0, 11) + 0x1000);
@@ -622,7 +625,7 @@
  * @param argt  Pointer to an array with the string codes used to parse the argv array.
  * @param dry_run True when the argt array is not yet initialized.
  */
-static char *FormatString(char *buff, const char *str, int64 *argv, const int64 *argve, uint casei, const char *last, WChar *argt, bool dry_run)
+static char *FormatString(char *buff, const char *str_arg, int64 *argv, const int64 *argve, uint casei, const char *last, WChar *argt, bool dry_run)
 {
 	/* When there is no array with types there is no need to do a dry run. */
 	if (argt == NULL) dry_run = true;
@@ -634,18 +637,26 @@
 		 * pass makes sure the argv array is correctly filled and the second
 		 * pass can reference later values without problems. */
 		struct TextRefStack *backup = CreateTextRefStackBackup();
-		FormatString(buff, str, argv, argve, casei, last, argt, true);
+		FormatString(buff, str_arg, argv, argve, casei, last, argt, true);
 		RestoreTextRefStackBackup(backup);
 	} else if (!dry_run) {
-		FormatString(buff, str, argv, argve, casei, last, argt, true);
+		FormatString(buff, str_arg, argv, argve, casei, last, argt, true);
 	}
 	WChar b;
 	int64 *argv_orig = argv;
 	WChar *argt_orig = argt;
 	uint modifier = 0;
 	char *buf_start = buff;
+	std::stack<const char *> str_stack;
+	str_stack.push(str_arg);
 
-	while ((b = Utf8Consume(&str)) != '\0') {
+	while (true) {
+		while (!str_stack.empty() && (b = Utf8Consume(&str_stack.top())) == '\0') {
+			str_stack.pop();
+		}
+		if (str_stack.empty()) break;
+		const char *&str = str_stack.top();
+
 		if (SCC_NEWGRF_FIRST <= b && b <= SCC_NEWGRF_LAST) {
 			/* We need to pass some stuff as it might be modified; oh boy. */
 			//todo: should argve be passed here too?
@@ -654,6 +665,19 @@
 		}
 
 		switch (b) {
+			case SCC_NEWGRF_STRINL: {
+				StringID substr = Utf8Consume(&str);
+				str_stack.push(GetStringPtr(substr));
+				break;
+			}
+
+			case SCC_NEWGRF_PRINT_STRING_ID: {
+				StringID substr = GetInt32(&argv, argve, &argt, SCC_NEWGRF_PRINT_STRING_ID);
+				str_stack.push(GetStringPtr(substr));
+				break;
+			}
+
+
 			case SCC_SETX: // {SETX}
 				if (buff + Utf8CharLen(SCC_SETX) + 1 < last) {
 					buff += Utf8Encode(buff, SCC_SETX);
--- a/src/table/control_codes.h
+++ b/src/table/control_codes.h
@@ -134,6 +134,8 @@
 	SCC_NEWGRF_ROTATE_TOP_4_WORDS,             ///< Rotate the top 4 words of the stack (W4 W1 W2 W3)
 	SCC_NEWGRF_LAST = SCC_NEWGRF_ROTATE_TOP_4_WORDS,
 
+	SCC_NEWGRF_STRINL,                         ///< Inline another string at the current position, StringID is encoded in the string
+
 	/* Special printable symbols.
 	 * These are mapped to the original glyphs */
 	SCC_LESSTHAN       = SCC_SPRITE_START + 0x3C,