clang-format localisation

This commit is contained in:
clang-format 2018-06-22 23:01:56 +02:00 committed by Hielke Morsink
parent 17d2693422
commit 737d2c490c
19 changed files with 1232 additions and 947 deletions

View File

@ -7,12 +7,13 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include <cstdlib> #include "ConversionTables.h"
#include "../core/Util.hpp" #include "../core/Util.hpp"
#include "ConversionTables.h"
#include "FormatCodes.h" #include "FormatCodes.h"
#include <cstdlib>
// clang-format off // clang-format off
const encoding_convert_entry RCT2ToUnicodeTable[256] = const encoding_convert_entry RCT2ToUnicodeTable[256] =
{ {

View File

@ -7,14 +7,15 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include <algorithm>
#include <limits>
#include <stdexcept>
#include "../core/String.hpp" #include "../core/String.hpp"
#include "../core/Util.hpp" #include "../core/Util.hpp"
#include "ConversionTables.h" #include "ConversionTables.h"
#include "Language.h" #include "Language.h"
#include <algorithm>
#include <limits>
#include <stdexcept>
/** /**
* Decodes an RCT2 string to a wide char string still in the original code page. * Decodes an RCT2 string to a wide char string still in the original code page.
* An RCT2 string is a multi-byte string where every two-byte code point is preceeded with a byte value of 255. * An RCT2 string is a multi-byte string where every two-byte code point is preceeded with a byte value of 255.
@ -129,8 +130,7 @@ static int32_t GetCodePageForRCT2Language(RCT2LanguageId languageId)
} }
} }
template<typename TConvertFunc> template<typename TConvertFunc> static std::string DecodeConvertWithTable(const std::string_view& src, TConvertFunc func)
static std::string DecodeConvertWithTable(const std::string_view& src, TConvertFunc func)
{ {
auto decoded = DecodeToWideChar(src); auto decoded = DecodeToWideChar(src);
std::wstring u16; std::wstring u16;

View File

@ -7,9 +7,10 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include "Currency.h"
#include "../config/Config.h" #include "../config/Config.h"
#include "../util/Util.h" #include "../util/Util.h"
#include "Currency.h"
#include "StringIds.h" #include "StringIds.h"
// clang-format off // clang-format off
@ -40,6 +41,9 @@ void currency_load_custom_currency_config()
CurrencyDescriptors[CURRENCY_CUSTOM].affix_unicode = gConfigGeneral.custom_currency_affix; CurrencyDescriptors[CURRENCY_CUSTOM].affix_unicode = gConfigGeneral.custom_currency_affix;
if (gConfigGeneral.custom_currency_symbol != nullptr) if (gConfigGeneral.custom_currency_symbol != nullptr)
{ {
safe_strcpy(CurrencyDescriptors[CURRENCY_CUSTOM].symbol_unicode, gConfigGeneral.custom_currency_symbol, CURRENCY_SYMBOL_MAX_SIZE); safe_strcpy(
CurrencyDescriptors[CURRENCY_CUSTOM].symbol_unicode,
gConfigGeneral.custom_currency_symbol,
CURRENCY_SYMBOL_MAX_SIZE);
} }
} }

View File

@ -13,7 +13,8 @@
#include "../common.h" #include "../common.h"
// List of currencies // List of currencies
enum CURRENCY_TYPE { enum CURRENCY_TYPE
{
CURRENCY_POUNDS, // British Pound CURRENCY_POUNDS, // British Pound
CURRENCY_DOLLARS, // US Dollar CURRENCY_DOLLARS, // US Dollar
CURRENCY_FRANC, // French Franc CURRENCY_FRANC, // French Franc
@ -36,7 +37,8 @@ enum CURRENCY_TYPE {
CURRENCY_END // Last item CURRENCY_END // Last item
}; };
enum CURRENCY_AFFIX { enum CURRENCY_AFFIX
{
CURRENCY_PREFIX, CURRENCY_PREFIX,
CURRENCY_SUFFIX CURRENCY_SUFFIX
}; };
@ -45,7 +47,8 @@ enum CURRENCY_AFFIX {
#define CURRENCY_RATE_MAX_NUM_DIGITS 9 #define CURRENCY_RATE_MAX_NUM_DIGITS 9
// Currency format specification - inspired by OpenTTD // Currency format specification - inspired by OpenTTD
struct currency_descriptor { struct currency_descriptor
{
char isoCode[4]; char isoCode[4];
// Rate is relative to 0.10 GBP // Rate is relative to 0.10 GBP
int32_t rate; int32_t rate;

View File

@ -12,7 +12,8 @@
#include "../common.h" #include "../common.h"
enum { enum
{
MONTH_MARCH, MONTH_MARCH,
MONTH_APRIL, MONTH_APRIL,
MONTH_MAY, MONTH_MAY,
@ -25,14 +26,16 @@ enum {
MONTH_COUNT MONTH_COUNT
}; };
enum { enum
{
DATE_FORMAT_DAY_MONTH_YEAR, DATE_FORMAT_DAY_MONTH_YEAR,
DATE_FORMAT_MONTH_DAY_YEAR, DATE_FORMAT_MONTH_DAY_YEAR,
DATE_FORMAT_YEAR_MONTH_DAY, DATE_FORMAT_YEAR_MONTH_DAY,
DATE_FORMAT_YEAR_DAY_MONTH DATE_FORMAT_YEAR_DAY_MONTH
}; };
struct openrct_timeofday { struct openrct_timeofday
{
uint8_t second; uint8_t second;
uint8_t minute; uint8_t minute;
uint8_t hour; uint8_t hour;

View File

@ -7,14 +7,16 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include "FormatCodes.h"
#include "../common.h" #include "../common.h"
#include "../core/Util.hpp" #include "../core/Util.hpp"
#include "FormatCodes.h"
#include "Localisation.h" #include "Localisation.h"
#pragma region Format codes #pragma region Format codes
struct format_code_token { struct format_code_token
{
uint32_t code; uint32_t code;
const char* token; const char* token;
}; };
@ -117,7 +119,8 @@ const char *format_get_token(uint32_t code)
bool utf8_should_use_sprite_for_codepoint(int32_t codepoint) bool utf8_should_use_sprite_for_codepoint(int32_t codepoint)
{ {
switch (codepoint) { switch (codepoint)
{
case FORMAT_UP: case FORMAT_UP:
case FORMAT_DOWN: case FORMAT_DOWN:
case FORMAT_LEFTGUILLEMET: case FORMAT_LEFTGUILLEMET:

View File

@ -15,7 +15,8 @@
uint32_t format_get_code(const char* token); uint32_t format_get_code(const char* token);
const char* format_get_token(uint32_t code); const char* format_get_token(uint32_t code);
enum { enum
{
// Font format codes // Font format codes
// The next byte specifies the X coordinate // The next byte specifies the X coordinate

View File

@ -7,18 +7,19 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include <stack>
#include "../Context.h" #include "../Context.h"
#include "../core/Path.hpp" #include "../core/Path.hpp"
#include "../core/String.hpp" #include "../core/String.hpp"
#include "../interface/Fonts.h"
#include "../interface/FontFamilies.h" #include "../interface/FontFamilies.h"
#include "../interface/Fonts.h"
#include "../object/ObjectManager.h" #include "../object/ObjectManager.h"
#include "../platform/platform.h" #include "../platform/platform.h"
#include "LanguagePack.h" #include "LanguagePack.h"
#include "Localisation.h" #include "Localisation.h"
#include "LocalisationService.h" #include "LocalisationService.h"
#include <stack>
// clang-format off // clang-format off
const language_descriptor LanguagesDescriptors[LANGUAGE_COUNT] = const language_descriptor LanguagesDescriptors[LANGUAGE_COUNT] =
{ {
@ -114,10 +115,7 @@ bool language_get_localised_scenario_strings(const utf8 *scenarioFilename, rct_s
outStringIds[0] = std::get<0>(result); outStringIds[0] = std::get<0>(result);
outStringIds[1] = std::get<1>(result); outStringIds[1] = std::get<1>(result);
outStringIds[2] = std::get<2>(result); outStringIds[2] = std::get<2>(result);
return return outStringIds[0] != STR_NONE || outStringIds[1] != STR_NONE || outStringIds[2] != STR_NONE;
outStringIds[0] != STR_NONE ||
outStringIds[1] != STR_NONE ||
outStringIds[2] != STR_NONE;
} }
void language_free_object_string(rct_string_id stringId) void language_free_object_string(rct_string_id stringId)

View File

@ -10,12 +10,14 @@
#ifndef _LANGUAGE_H_ #ifndef _LANGUAGE_H_
#define _LANGUAGE_H_ #define _LANGUAGE_H_
#include <string>
#include <string_view>
#include "../common.h" #include "../common.h"
#include "../drawing/Font.h" #include "../drawing/Font.h"
enum { #include <string>
#include <string_view>
enum
{
LANGUAGE_UNDEFINED, LANGUAGE_UNDEFINED,
LANGUAGE_ARABIC, LANGUAGE_ARABIC,
LANGUAGE_CATALAN, LANGUAGE_CATALAN,
@ -66,7 +68,8 @@ enum RCT2LanguageId
#include "../interface/FontFamilies.h" #include "../interface/FontFamilies.h"
struct language_descriptor { struct language_descriptor
{
const char* locale; const char* locale;
const utf8* english_name; const utf8* english_name;
const utf8* native_name; const utf8* native_name;

View File

@ -7,20 +7,20 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include <algorithm> #include "LanguagePack.h"
#include <string>
#include <vector>
#include "../common.h" #include "../common.h"
#include "Localisation.h"
#include "../core/FileStream.hpp" #include "../core/FileStream.hpp"
#include "../core/Math.hpp" #include "../core/Math.hpp"
#include "../core/Memory.hpp" #include "../core/Memory.hpp"
#include "../core/String.hpp" #include "../core/String.hpp"
#include "../core/StringBuilder.hpp" #include "../core/StringBuilder.hpp"
#include "../core/StringReader.hpp" #include "../core/StringReader.hpp"
#include "LanguagePack.h" #include "Localisation.h"
#include <algorithm>
#include <string>
#include <vector>
// Don't try to load more than language files that exceed 64 MiB // Don't try to load more than language files that exceed 64 MiB
constexpr uint64_t MAX_LANGUAGE_SIZE = 64 * 1024 * 1024; constexpr uint64_t MAX_LANGUAGE_SIZE = 64 * 1024 * 1024;
@ -267,9 +267,9 @@ private:
// Unsure at how the original game decides which entries to write resource strings to, but this could affect adding new // Unsure at how the original game decides which entries to write resource strings to, but this could affect adding new
// strings for the time being. Further investigation is required. // strings for the time being. Further investigation is required.
// //
// When reading the language files, the STR_XXXX part is read and XXXX becomes the string id number. Everything after the colon // When reading the language files, the STR_XXXX part is read and XXXX becomes the string id number. Everything after the
// and before the new line will be saved as the string. Tokens are written with inside curly braces {TOKEN}. // colon and before the new line will be saved as the string. Tokens are written with inside curly braces {TOKEN}. Use # at
// Use # at the beginning of a line to leave a comment. // the beginning of a line to leave a comment.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static bool IsWhitespace(codepoint_t codepoint) static bool IsWhitespace(codepoint_t codepoint)
@ -317,7 +317,8 @@ private:
static void SkipToEndOfLine(IStringReader* reader) static void SkipToEndOfLine(IStringReader* reader)
{ {
codepoint_t codepoint; codepoint_t codepoint;
while (reader->TryPeek(&codepoint)) { while (reader->TryPeek(&codepoint))
{
if (codepoint != '\r' && codepoint != '\n') if (codepoint != '\r' && codepoint != '\n')
{ {
reader->Skip(); reader->Skip();
@ -336,7 +337,8 @@ private:
codepoint_t codepoint; codepoint_t codepoint;
if (reader->TryPeek(&codepoint)) if (reader->TryPeek(&codepoint))
{ {
switch (codepoint) { switch (codepoint)
{
case '#': case '#':
SkipToEndOfLine(reader); SkipToEndOfLine(reader);
break; break;
@ -370,7 +372,8 @@ private:
bool closedCorrectly = false; bool closedCorrectly = false;
while (reader->TryPeek(&codepoint)) while (reader->TryPeek(&codepoint))
{ {
if (IsNewLine(codepoint)) break; if (IsNewLine(codepoint))
break;
reader->Skip(); reader->Skip();
if (codepoint == ']') if (codepoint == ']')
@ -419,7 +422,8 @@ private:
bool closedCorrectly = false; bool closedCorrectly = false;
while (reader->TryPeek(&codepoint)) while (reader->TryPeek(&codepoint))
{ {
if (IsNewLine(codepoint)) break; if (IsNewLine(codepoint))
break;
reader->Skip(); reader->Skip();
if (codepoint == '>') if (codepoint == '>')
@ -497,14 +501,33 @@ private:
} }
else else
{ {
if (String::Equals(identifier, "STR_NAME")) { stringId = 0; } if (String::Equals(identifier, "STR_NAME"))
else if (String::Equals(identifier, "STR_DESC")) { stringId = 1; } {
else if (String::Equals(identifier, "STR_CPTY")) { stringId = 2; } stringId = 0;
}
else if (String::Equals(identifier, "STR_DESC"))
{
stringId = 1;
}
else if (String::Equals(identifier, "STR_CPTY"))
{
stringId = 2;
}
else if (String::Equals(identifier, "STR_SCNR")) { stringId = 0; } else if (String::Equals(identifier, "STR_SCNR"))
else if (String::Equals(identifier, "STR_PARK")) { stringId = 1; } {
else if (String::Equals(identifier, "STR_DTLS")) { stringId = 2; } stringId = 0;
else { }
else if (String::Equals(identifier, "STR_PARK"))
{
stringId = 1;
}
else if (String::Equals(identifier, "STR_DTLS"))
{
stringId = 2;
}
else
{
// Ignore line entirely // Ignore line entirely
return; return;
} }
@ -575,12 +598,15 @@ private:
while (reader->TryPeek(&codepoint)) while (reader->TryPeek(&codepoint))
{ {
if (IsNewLine(codepoint)) return false; if (IsNewLine(codepoint))
if (IsWhitespace(codepoint)) return false; return false;
if (IsWhitespace(codepoint))
return false;
reader->Skip(); reader->Skip();
if (codepoint == '}') break; if (codepoint == '}')
break;
sb.Append(codepoint); sb.Append(codepoint);
} }

View File

@ -9,9 +9,10 @@
#pragma once #pragma once
#include <string>
#include "../common.h" #include "../common.h"
#include <string>
interface ILanguagePack interface ILanguagePack
{ {
virtual ~ILanguagePack() = default; virtual ~ILanguagePack() = default;
@ -30,4 +31,4 @@ namespace LanguagePackFactory
{ {
ILanguagePack* FromFile(uint16_t id, const utf8* path); ILanguagePack* FromFile(uint16_t id, const utf8* path);
ILanguagePack* FromText(uint16_t id, const utf8* text); ILanguagePack* FromText(uint16_t id, const utf8* text);
} } // namespace LanguagePackFactory

View File

@ -7,12 +7,13 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include <time.h>
#include "../Game.h" #include "../Game.h"
#include "../core/Math.hpp" #include "../core/Math.hpp"
#include "Date.h" #include "Date.h"
#include "StringIds.h" #include "StringIds.h"
#include <time.h>
uint16_t gDateMonthTicks; uint16_t gDateMonthTicks;
uint16_t gDateMonthsElapsed; uint16_t gDateMonthsElapsed;

View File

@ -7,33 +7,33 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include <ctype.h>
#include <cstring> #include <cstring>
#include <ctype.h>
#include <limits.h> #include <limits.h>
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
#elif defined(__ANDROID__) #elif defined(__ANDROID__)
#include <jni.h>
#include <SDL.h> #include <SDL.h>
#include <jni.h>
#else #else
#include <iconv.h>
#include <errno.h> #include <errno.h>
#include <iconv.h>
#endif // _WIN32 #endif // _WIN32
#include "../Game.h"
#include "../common.h" #include "../common.h"
#include "../config/Config.h" #include "../config/Config.h"
#include "../core/Guard.hpp" #include "../core/Guard.hpp"
#include "../core/Math.hpp" #include "../core/Math.hpp"
#include "../core/String.hpp" #include "../core/String.hpp"
#include "../core/Util.hpp" #include "../core/Util.hpp"
#include "Date.h"
#include "../Game.h"
#include "Localisation.h"
#include "../management/Marketing.h" #include "../management/Marketing.h"
#include "../ride/Ride.h" #include "../ride/Ride.h"
#include "../util/Util.h" #include "../util/Util.h"
#include "Date.h"
#include "Localisation.h"
char gCommonStringFormatBuffer[256]; char gCommonStringFormatBuffer[256];
uint8_t gCommonFormatArgs[80]; uint8_t gCommonFormatArgs[80];
@ -330,24 +330,54 @@ const rct_string_id DateGameShortMonthNames[MONTH_COUNT] = {
}; };
// clang-format on // clang-format on
#define format_push_char_safe(C) { *(*dest)++ = (C); --(*size); } #define format_push_char_safe(C) \
#define format_handle_overflow(X) if ((*size) <= (X)) { *(*dest) = '\0'; (*size) = 0; return; } { \
#define format_push_char(C) { format_handle_overflow(1); format_push_char_safe(C); } *(*dest)++ = (C); \
--(*size); \
}
#define format_handle_overflow(X) \
if ((*size) <= (X)) \
{ \
*(*dest) = '\0'; \
(*size) = 0; \
return; \
}
#define format_push_char(C) \
{ \
format_handle_overflow(1); \
format_push_char_safe(C); \
}
#define format_push_wrap(C) { *ncur = (C); if (ncur == (*dest)) ncur = nbegin; } #define format_push_wrap(C) \
#define reverse_string() while (nbegin < nend) { tmp = *nbegin; *nbegin++ = *nend; *nend-- = tmp; } { \
*ncur = (C); \
if (ncur == (*dest)) \
ncur = nbegin; \
}
#define reverse_string() \
while (nbegin < nend) \
{ \
tmp = *nbegin; \
*nbegin++ = *nend; \
*nend-- = tmp; \
}
static void format_string_part_from_raw(char** dest, size_t* size, const char* src, char** args); static void format_string_part_from_raw(char** dest, size_t* size, const char* src, char** args);
static void format_string_part(char** dest, size_t* size, rct_string_id format, char** args); static void format_string_part(char** dest, size_t* size, rct_string_id format, char** args);
static void format_append_string(char **dest, size_t *size, const utf8 *string) { static void format_append_string(char** dest, size_t* size, const utf8* string)
if ((*size) == 0) return; {
if ((*size) == 0)
return;
size_t length = strlen(string); size_t length = strlen(string);
if (length < (*size)) { if (length < (*size))
{
memcpy((*dest), string, length); memcpy((*dest), string, length);
(*dest) += length; (*dest) += length;
(*size) -= length; (*size) -= length;
} else { }
else
{
memcpy((*dest), string, (*size) - 1); memcpy((*dest), string, (*size) - 1);
(*dest) += (*size) - 1; (*dest) += (*size) - 1;
*(*dest)++ = '\0'; *(*dest)++ = '\0';
@ -355,14 +385,19 @@ static void format_append_string(char **dest, size_t *size, const utf8 *string)
} }
} }
static void format_append_string_n(char **dest, size_t *size, const utf8 *string, size_t maxlen) { static void format_append_string_n(char** dest, size_t* size, const utf8* string, size_t maxlen)
if ((*size) == 0) return; {
if ((*size) == 0)
return;
size_t length = std::min(maxlen, strlen(string)); size_t length = std::min(maxlen, strlen(string));
if (length < (*size)) { if (length < (*size))
{
memcpy((*dest), string, length); memcpy((*dest), string, length);
(*dest) += length; (*dest) += length;
(*size) -= length; (*size) -= length;
} else { }
else
{
memcpy((*dest), string, (*size) - 1); memcpy((*dest), string, (*size) - 1);
(*dest) += (*size) - 1; (*dest) += (*size) - 1;
*(*dest)++ = '\0'; *(*dest)++ = '\0';
@ -376,15 +411,18 @@ static void format_integer(char **dest, size_t *size, int64_t value)
char *nbegin, *nend, *ncur; char *nbegin, *nend, *ncur;
char tmp; char tmp;
if ((*size) == 0) return; if ((*size) == 0)
return;
// Negative sign // Negative sign
if (value < 0) { if (value < 0)
{
format_push_char('-'); format_push_char('-');
value = -value; value = -value;
} }
if (value == 0) { if (value == 0)
{
format_push_char('0'); format_push_char('0');
return; return;
} }
@ -392,17 +430,20 @@ static void format_integer(char **dest, size_t *size, int64_t value)
nbegin = (*dest); nbegin = (*dest);
// Right to left // Right to left
while (value > 0 && (*size) > 1) { while (value > 0 && (*size) > 1)
{
digit = value % 10; digit = value % 10;
value /= 10; value /= 10;
format_push_char_safe('0' + digit); format_push_char_safe('0' + digit);
} }
if (value > 0) { if (value > 0)
{
ncur = nbegin; ncur = nbegin;
while (value > 0) { while (value > 0)
{
digit = value % 10; digit = value % 10;
value /= 10; value /= 10;
@ -419,7 +460,9 @@ static void format_integer(char **dest, size_t *size, int64_t value)
reverse_string(); reverse_string();
format_push_char_safe('\0'); // Truncate overflowed string format_push_char_safe('\0'); // Truncate overflowed string
} else { }
else
{
// Reverse string // Reverse string
nend = (*dest) - 1; nend = (*dest) - 1;
reverse_string(); reverse_string();
@ -434,15 +477,18 @@ static void format_comma_separated_integer(char **dest, size_t *size, int64_t va
const char* commaMark = language_get_string(STR_LOCALE_THOUSANDS_SEPARATOR); const char* commaMark = language_get_string(STR_LOCALE_THOUSANDS_SEPARATOR);
const char* ch = nullptr; const char* ch = nullptr;
if ((*size) == 0) return; if ((*size) == 0)
return;
// Negative sign // Negative sign
if (value < 0) { if (value < 0)
{
format_push_char('-'); format_push_char('-');
value = -value; value = -value;
} }
if (value == 0) { if (value == 0)
{
format_push_char('0'); format_push_char('0');
return; return;
} }
@ -451,17 +497,23 @@ static void format_comma_separated_integer(char **dest, size_t *size, int64_t va
// Groups of three digits, right to left // Groups of three digits, right to left
groupIndex = 0; groupIndex = 0;
while (value > 0 && (*size) > 1) { while (value > 0 && (*size) > 1)
{
// Append group separator // Append group separator
if (groupIndex == 3) { if (groupIndex == 3)
{
groupIndex = 0; groupIndex = 0;
ch = commaMark; ch = commaMark;
} }
if (ch != nullptr ) { if (ch != nullptr)
{
format_push_char_safe(*ch++); format_push_char_safe(*ch++);
if (*ch == '\0') ch = nullptr; if (*ch == '\0')
} else { ch = nullptr;
}
else
{
digit = value % 10; digit = value % 10;
value /= 10; value /= 10;
@ -470,20 +522,27 @@ static void format_comma_separated_integer(char **dest, size_t *size, int64_t va
} }
} }
if (value > 0) { if (value > 0)
{
ncur = nbegin; ncur = nbegin;
while (value > 0) { while (value > 0)
{
// Append group separator // Append group separator
if (groupIndex == 3) { if (groupIndex == 3)
{
groupIndex = 0; groupIndex = 0;
ch = commaMark; ch = commaMark;
} }
if (ch != nullptr ) { if (ch != nullptr)
{
format_push_wrap(*ch++); format_push_wrap(*ch++);
if (*ch == '\0') ch = nullptr; if (*ch == '\0')
} else { ch = nullptr;
}
else
{
digit = value % 10; digit = value % 10;
value /= 10; value /= 10;
@ -502,7 +561,9 @@ static void format_comma_separated_integer(char **dest, size_t *size, int64_t va
reverse_string(); reverse_string();
format_push_char_safe('\0'); // Truncate overflowed string format_push_char_safe('\0'); // Truncate overflowed string
} else { }
else
{
// Reverse string // Reverse string
nend = *dest - 1; nend = *dest - 1;
reverse_string(); reverse_string();
@ -519,10 +580,12 @@ static void format_comma_separated_fixed_1dp(char **dest, size_t *size, int64_t
const char* ch = nullptr; const char* ch = nullptr;
int32_t zeroNeeded = 1; int32_t zeroNeeded = 1;
if ((*size) == 0) return; if ((*size) == 0)
return;
// Negative sign // Negative sign
if (value < 0) { if (value < 0)
{
format_push_char('-'); format_push_char('-');
value = -value; value = -value;
} }
@ -532,7 +595,8 @@ static void format_comma_separated_fixed_1dp(char **dest, size_t *size, int64_t
// In the case of buffers this small, // In the case of buffers this small,
// all of this would be truncated anyways. // all of this would be truncated anyways.
format_handle_overflow(1); format_handle_overflow(1);
if ((*size) > 2) { if ((*size) > 2)
{
// One decimal place // One decimal place
digit = value % 10; digit = value % 10;
format_push_char_safe('0' + digit); format_push_char_safe('0' + digit);
@ -542,17 +606,23 @@ static void format_comma_separated_fixed_1dp(char **dest, size_t *size, int64_t
value /= 10; value /= 10;
groupIndex = 0; groupIndex = 0;
while ((zeroNeeded || value > 0) && (*size) > 1) { while ((zeroNeeded || value > 0) && (*size) > 1)
{
// Append group separator // Append group separator
if (groupIndex == 3) { if (groupIndex == 3)
{
groupIndex = 0; groupIndex = 0;
ch = commaMark; ch = commaMark;
} }
if (ch != nullptr ) { if (ch != nullptr)
{
format_push_char_safe(*ch++); format_push_char_safe(*ch++);
if (*ch == '\0') ch = nullptr; if (*ch == '\0')
} else { ch = nullptr;
}
else
{
zeroNeeded = 0; zeroNeeded = 0;
digit = value % 10; digit = value % 10;
value /= 10; value /= 10;
@ -562,20 +632,27 @@ static void format_comma_separated_fixed_1dp(char **dest, size_t *size, int64_t
} }
} }
if (zeroNeeded || value > 0) { if (zeroNeeded || value > 0)
{
ncur = nbegin; ncur = nbegin;
while (zeroNeeded || value > 0) { while (zeroNeeded || value > 0)
{
// Append group separator // Append group separator
if (groupIndex == 3) { if (groupIndex == 3)
{
groupIndex = 0; groupIndex = 0;
ch = commaMark; ch = commaMark;
} }
if (ch != nullptr ) { if (ch != nullptr)
{
format_push_wrap(*ch++); format_push_wrap(*ch++);
if (*ch == '\0') ch = nullptr; if (*ch == '\0')
} else { ch = nullptr;
}
else
{
zeroNeeded = 0; zeroNeeded = 0;
digit = value % 10; digit = value % 10;
value /= 10; value /= 10;
@ -595,7 +672,9 @@ static void format_comma_separated_fixed_1dp(char **dest, size_t *size, int64_t
reverse_string(); reverse_string();
format_push_char_safe('\0'); // Truncate overflowed string format_push_char_safe('\0'); // Truncate overflowed string
} else { }
else
{
// Reverse string // Reverse string
nend = *dest - 1; nend = *dest - 1;
reverse_string(); reverse_string();
@ -612,10 +691,12 @@ static void format_comma_separated_fixed_2dp(char **dest, size_t *size, int64_t
const char* ch = nullptr; const char* ch = nullptr;
int32_t zeroNeeded = 1; int32_t zeroNeeded = 1;
if ((*size) == 0) return; if ((*size) == 0)
return;
// Negative sign // Negative sign
if (value < 0) { if (value < 0)
{
format_push_char('-'); format_push_char('-');
value = -value; value = -value;
} }
@ -625,9 +706,12 @@ static void format_comma_separated_fixed_2dp(char **dest, size_t *size, int64_t
// In the case of buffers this small, // In the case of buffers this small,
// all of this would be truncated anyways. // all of this would be truncated anyways.
format_handle_overflow(1); format_handle_overflow(1);
if ((*size) < 3) { if ((*size) < 3)
{
value /= 100; value /= 100;
} else { }
else
{
// Two decimal places // Two decimal places
digit = value % 10; digit = value % 10;
value /= 10; value /= 10;
@ -641,17 +725,23 @@ static void format_comma_separated_fixed_2dp(char **dest, size_t *size, int64_t
} }
groupIndex = 0; groupIndex = 0;
while ((zeroNeeded || value > 0) && (*size) > 1) { while ((zeroNeeded || value > 0) && (*size) > 1)
{
// Append group separator // Append group separator
if (groupIndex == 3) { if (groupIndex == 3)
{
groupIndex = 0; groupIndex = 0;
ch = commaMark; ch = commaMark;
} }
if (ch != nullptr ) { if (ch != nullptr)
{
format_push_char_safe(*ch++); format_push_char_safe(*ch++);
if (*ch == '\0') ch = nullptr; if (*ch == '\0')
} else { ch = nullptr;
}
else
{
zeroNeeded = 0; zeroNeeded = 0;
digit = value % 10; digit = value % 10;
value /= 10; value /= 10;
@ -661,20 +751,27 @@ static void format_comma_separated_fixed_2dp(char **dest, size_t *size, int64_t
} }
} }
if (zeroNeeded || value > 0) { if (zeroNeeded || value > 0)
{
ncur = nbegin; ncur = nbegin;
while (zeroNeeded || value > 0) { while (zeroNeeded || value > 0)
{
// Append group separator // Append group separator
if (groupIndex == 3) { if (groupIndex == 3)
{
groupIndex = 0; groupIndex = 0;
ch = commaMark; ch = commaMark;
} }
if (ch != nullptr ) { if (ch != nullptr)
{
format_push_wrap(*ch++); format_push_wrap(*ch++);
if (*ch == '\0') ch = nullptr; if (*ch == '\0')
} else { ch = nullptr;
}
else
{
zeroNeeded = 0; zeroNeeded = 0;
digit = value % 10; digit = value % 10;
value /= 10; value /= 10;
@ -694,7 +791,9 @@ static void format_comma_separated_fixed_2dp(char **dest, size_t *size, int64_t
reverse_string(); reverse_string();
format_push_char_safe('\0'); // Truncate overflowed string format_push_char_safe('\0'); // Truncate overflowed string
} else { }
else
{
// Reverse string // Reverse string
nend = *dest - 1; nend = *dest - 1;
reverse_string(); reverse_string();
@ -703,14 +802,16 @@ static void format_comma_separated_fixed_2dp(char **dest, size_t *size, int64_t
static void format_currency(char** dest, size_t* size, int64_t value) static void format_currency(char** dest, size_t* size, int64_t value)
{ {
if ((*size) == 0) return; if ((*size) == 0)
return;
const currency_descriptor* currencyDesc = &CurrencyDescriptors[gConfigGeneral.currency_format]; const currency_descriptor* currencyDesc = &CurrencyDescriptors[gConfigGeneral.currency_format];
value *= currencyDesc->rate; value *= currencyDesc->rate;
// Negative sign // Negative sign
if (value < 0) { if (value < 0)
{
format_push_char('-'); format_push_char('-');
value = -value; value = -value;
} }
@ -721,7 +822,8 @@ static void format_currency(char **dest, size_t *size, int64_t value)
// Currency symbol // Currency symbol
const utf8* symbol = currencyDesc->symbol_unicode; const utf8* symbol = currencyDesc->symbol_unicode;
uint8_t affix = currencyDesc->affix_unicode; uint8_t affix = currencyDesc->affix_unicode;
if (!font_supports_string(symbol, FONT_SIZE_MEDIUM)) { if (!font_supports_string(symbol, FONT_SIZE_MEDIUM))
{
symbol = currencyDesc->symbol_ascii; symbol = currencyDesc->symbol_ascii;
affix = currencyDesc->affix_ascii; affix = currencyDesc->affix_ascii;
} }
@ -729,10 +831,12 @@ static void format_currency(char **dest, size_t *size, int64_t value)
// Prefix // Prefix
if (affix == CURRENCY_PREFIX) if (affix == CURRENCY_PREFIX)
format_append_string(dest, size, symbol); format_append_string(dest, size, symbol);
if ((*size) == 0) return; if ((*size) == 0)
return;
format_comma_separated_integer(dest, size, value); format_comma_separated_integer(dest, size, value);
if ((*size) == 0) return; if ((*size) == 0)
return;
// Currency symbol suffix // Currency symbol suffix
if (affix == CURRENCY_SUFFIX) if (affix == CURRENCY_SUFFIX)
@ -741,7 +845,8 @@ static void format_currency(char **dest, size_t *size, int64_t value)
static void format_currency_2dp(char** dest, size_t* size, int64_t value) static void format_currency_2dp(char** dest, size_t* size, int64_t value)
{ {
if ((*size) == 0) return; if ((*size) == 0)
return;
const currency_descriptor* currencyDesc = &CurrencyDescriptors[gConfigGeneral.currency_format]; const currency_descriptor* currencyDesc = &CurrencyDescriptors[gConfigGeneral.currency_format];
@ -749,7 +854,8 @@ static void format_currency_2dp(char **dest, size_t *size, int64_t value)
value *= rate; value *= rate;
// Negative sign // Negative sign
if (value < 0) { if (value < 0)
{
format_push_char('-'); format_push_char('-');
value = -value; value = -value;
} }
@ -757,7 +863,8 @@ static void format_currency_2dp(char **dest, size_t *size, int64_t value)
// Currency symbol // Currency symbol
const utf8* symbol = currencyDesc->symbol_unicode; const utf8* symbol = currencyDesc->symbol_unicode;
uint8_t affix = currencyDesc->affix_unicode; uint8_t affix = currencyDesc->affix_unicode;
if (!font_supports_string(symbol, FONT_SIZE_MEDIUM)) { if (!font_supports_string(symbol, FONT_SIZE_MEDIUM))
{
symbol = currencyDesc->symbol_ascii; symbol = currencyDesc->symbol_ascii;
affix = currencyDesc->affix_ascii; affix = currencyDesc->affix_ascii;
} }
@ -765,15 +872,20 @@ static void format_currency_2dp(char **dest, size_t *size, int64_t value)
// Prefix // Prefix
if (affix == CURRENCY_PREFIX) if (affix == CURRENCY_PREFIX)
format_append_string(dest, size, symbol); format_append_string(dest, size, symbol);
if ((*size) == 0) return; if ((*size) == 0)
return;
// Drop the pennies for "large" currencies // Drop the pennies for "large" currencies
if (rate >= 100) { if (rate >= 100)
{
format_comma_separated_integer(dest, size, value / 100); format_comma_separated_integer(dest, size, value / 100);
} else { }
else
{
format_comma_separated_fixed_2dp(dest, size, value); format_comma_separated_fixed_2dp(dest, size, value);
} }
if ((*size) == 0) return; if ((*size) == 0)
return;
// Currency symbol suffix // Currency symbol suffix
if (affix == CURRENCY_SUFFIX) if (affix == CURRENCY_SUFFIX)
@ -791,7 +903,8 @@ static void format_length(char **dest, size_t *size, int16_t value)
{ {
rct_string_id stringId = STR_UNIT_SUFFIX_METRES; rct_string_id stringId = STR_UNIT_SUFFIX_METRES;
if (gConfigGeneral.measurement_format == MEASUREMENT_FORMAT_IMPERIAL) { if (gConfigGeneral.measurement_format == MEASUREMENT_FORMAT_IMPERIAL)
{
value = metres_to_feet(value); value = metres_to_feet(value);
stringId = STR_UNIT_SUFFIX_FEET; stringId = STR_UNIT_SUFFIX_FEET;
} }
@ -804,7 +917,8 @@ static void format_velocity(char **dest, size_t *size, uint16_t value)
{ {
rct_string_id stringId; rct_string_id stringId;
switch (gConfigGeneral.measurement_format) { switch (gConfigGeneral.measurement_format)
{
default: default:
stringId = STR_UNIT_SUFFIX_MILES_PER_HOUR; stringId = STR_UNIT_SUFFIX_MILES_PER_HOUR;
break; break;
@ -836,9 +950,11 @@ static void format_duration(char **dest, size_t *size, uint16_t value)
uint16_t* argsRef = &args[1]; uint16_t* argsRef = &args[1];
int32_t minuteIndex = 0; int32_t minuteIndex = 0;
if (minutes > 0) { if (minutes > 0)
{
minuteIndex = 1; minuteIndex = 1;
if (minutes != 1) { if (minutes != 1)
{
minuteIndex = 2; minuteIndex = 2;
} }
@ -846,7 +962,8 @@ static void format_duration(char **dest, size_t *size, uint16_t value)
} }
int32_t secondsIndex = 0; int32_t secondsIndex = 0;
if (seconds != 1) { if (seconds != 1)
{
secondsIndex = 1; secondsIndex = 1;
} }
@ -869,9 +986,11 @@ static void format_realtime(char **dest, size_t *size, uint16_t value)
uint16_t* argsRef = &args[1]; uint16_t* argsRef = &args[1];
int32_t hourIndex = 0; int32_t hourIndex = 0;
if (hours > 0) { if (hours > 0)
{
hourIndex = 1; hourIndex = 1;
if (hours != 1) { if (hours != 1)
{
hourIndex = 2; hourIndex = 2;
} }
@ -879,7 +998,8 @@ static void format_realtime(char **dest, size_t *size, uint16_t value)
} }
int32_t minuteIndex = 0; int32_t minuteIndex = 0;
if (minutes != 1) { if (minutes != 1)
{
minuteIndex = 1; minuteIndex = 1;
} }
@ -892,15 +1012,18 @@ static void format_string_code(uint32_t format_code, char **dest, size_t *size,
{ {
intptr_t value; intptr_t value;
if ((*size) == 0) return; if ((*size) == 0)
return;
#ifdef DEBUG #ifdef DEBUG
if (gDebugStringFormatting) { if (gDebugStringFormatting)
{
printf("format_string_code(\"%s\")\n", format_get_token(format_code)); printf("format_string_code(\"%s\")\n", format_get_token(format_code));
} }
#endif #endif
switch (format_code) { switch (format_code)
{
case FORMAT_COMMA32: case FORMAT_COMMA32:
// Pop argument // Pop argument
value = *((int32_t*)*args); value = *((int32_t*)*args);
@ -1039,29 +1162,41 @@ static void format_string_code(uint32_t format_code, char **dest, size_t *size,
static void format_string_part_from_raw(utf8** dest, size_t* size, const utf8* src, char** args) static void format_string_part_from_raw(utf8** dest, size_t* size, const utf8* src, char** args)
{ {
#ifdef DEBUG #ifdef DEBUG
if (gDebugStringFormatting) { if (gDebugStringFormatting)
{
printf("format_string_part_from_raw(\"%s\")\n", src); printf("format_string_part_from_raw(\"%s\")\n", src);
} }
#endif #endif
while (*size > 1) { while (*size > 1)
{
uint32_t code = utf8_get_next(src, &src); uint32_t code = utf8_get_next(src, &src);
if (code < ' ') { if (code < ' ')
if (code == 0) { {
if (code == 0)
{
break; break;
} else if (code <= 4) { }
else if (code <= 4)
{
format_handle_overflow(2); format_handle_overflow(2);
format_push_char_safe(code); format_push_char_safe(code);
format_push_char_safe(*src++); format_push_char_safe(*src++);
} else if (code <= 16) { }
else if (code <= 16)
{
format_handle_overflow(1); format_handle_overflow(1);
format_push_char_safe(code); format_push_char_safe(code);
} else if (code <= 22) { }
else if (code <= 22)
{
format_handle_overflow(3); format_handle_overflow(3);
format_push_char_safe(code); format_push_char_safe(code);
format_push_char_safe(*src++); format_push_char_safe(*src++);
format_push_char_safe(*src++); format_push_char_safe(*src++);
} else { }
else
{
format_handle_overflow(5); format_handle_overflow(5);
format_push_char_safe(code); format_push_char_safe(code);
format_push_char_safe(*src++); format_push_char_safe(*src++);
@ -1069,14 +1204,21 @@ static void format_string_part_from_raw(utf8 **dest, size_t *size, const utf8 *s
format_push_char_safe(*src++); format_push_char_safe(*src++);
format_push_char_safe(*src++); format_push_char_safe(*src++);
} }
} else if (code <= 'z') { }
else if (code <= 'z')
{
format_push_char(code); format_push_char(code);
} else if (code < FORMAT_COLOUR_CODE_START || code == FORMAT_COMMA1DP16) { }
else if (code < FORMAT_COLOUR_CODE_START || code == FORMAT_COMMA1DP16)
{
format_string_code(code, dest, size, args); format_string_code(code, dest, size, args);
} else { }
else
{
size_t codepointLength = (size_t)utf8_get_codepoint_length(code); size_t codepointLength = (size_t)utf8_get_codepoint_length(code);
format_handle_overflow(codepointLength); format_handle_overflow(codepointLength);
if (*size > codepointLength) { if (*size > codepointLength)
{
*dest = utf8_write_codepoint(*dest, code); *dest = utf8_write_codepoint(*dest, code);
*size -= codepointLength; *size -= codepointLength;
} }
@ -1086,15 +1228,21 @@ static void format_string_part_from_raw(utf8 **dest, size_t *size, const utf8 *s
static void format_string_part(utf8** dest, size_t* size, rct_string_id format, char** args) static void format_string_part(utf8** dest, size_t* size, rct_string_id format, char** args)
{ {
if (format == STR_NONE) { if (format == STR_NONE)
if (*size > 0) { {
if (*size > 0)
{
*(*dest) = '\0'; *(*dest) = '\0';
} }
} else if (format < USER_STRING_START) { }
else if (format < USER_STRING_START)
{
// Language string // Language string
const utf8* rawString = language_get_string(format); const utf8* rawString = language_get_string(format);
format_string_part_from_raw(dest, size, rawString, args); format_string_part_from_raw(dest, size, rawString, args);
} else if (format <= USER_STRING_END) { }
else if (format <= USER_STRING_END)
{
// Custom string // Custom string
format -= 0x8000; format -= 0x8000;
@ -1103,20 +1251,26 @@ static void format_string_part(utf8 **dest, size_t *size, rct_string_id format,
format &= ~0xC00; format &= ~0xC00;
format_append_string_n(dest, size, gUserStrings[format], USER_STRING_MAX_LENGTH); format_append_string_n(dest, size, gUserStrings[format], USER_STRING_MAX_LENGTH);
if ((*size) > 0) *(*dest) = '\0'; if ((*size) > 0)
} else if (format <= REAL_NAME_END) { *(*dest) = '\0';
}
else if (format <= REAL_NAME_END)
{
// Real name // Real name
auto realNameIndex = format - REAL_NAME_START; auto realNameIndex = format - REAL_NAME_START;
format_append_string(dest, size, real_names[realNameIndex % Util::CountOf(real_names)]); format_append_string(dest, size, real_names[realNameIndex % Util::CountOf(real_names)]);
if ((*size) == 0) return; if ((*size) == 0)
return;
format_push_char(' '); format_push_char(' ');
format_push_char(real_name_initials[(realNameIndex >> 10) % Util::CountOf(real_name_initials)]); format_push_char(real_name_initials[(realNameIndex >> 10) % Util::CountOf(real_name_initials)]);
format_push_char('.'); format_push_char('.');
*(*dest) = '\0'; *(*dest) = '\0';
*args += 4; *args += 4;
} else { }
else
{
// ? // ?
log_error("Localisation CALLPROC reached. Please contact a dev"); log_error("Localisation CALLPROC reached. Please contact a dev");
assert(false); assert(false);
@ -1133,23 +1287,28 @@ static void format_string_part(utf8 **dest, size_t *size, rct_string_id format,
void format_string(utf8* dest, size_t size, rct_string_id format, void* args) void format_string(utf8* dest, size_t size, rct_string_id format, void* args)
{ {
#ifdef DEBUG #ifdef DEBUG
if (gDebugStringFormatting) { if (gDebugStringFormatting)
{
printf("format_string(%hu)\n", format); printf("format_string(%hu)\n", format);
} }
#endif #endif
if (size == 0) { if (size == 0)
{
return; return;
} }
utf8* end = dest; utf8* end = dest;
size_t left = size; size_t left = size;
format_string_part(&end, &left, format, (char**)&args); format_string_part(&end, &left, format, (char**)&args);
if (left == 0) { if (left == 0)
{
// Replace last character with null terminator // Replace last character with null terminator
*(end - 1) = '\0'; *(end - 1) = '\0';
log_warning("Truncating formatted string \"%s\" to %d bytes.", dest, size); log_warning("Truncating formatted string \"%s\" to %d bytes.", dest, size);
} else { }
else
{
// Null terminate // Null terminate
*end = '\0'; *end = '\0';
} }
@ -1163,23 +1322,28 @@ void format_string(utf8 *dest, size_t size, rct_string_id format, void *args)
void format_string_raw(utf8* dest, size_t size, utf8* src, void* args) void format_string_raw(utf8* dest, size_t size, utf8* src, void* args)
{ {
#ifdef DEBUG #ifdef DEBUG
if (gDebugStringFormatting) { if (gDebugStringFormatting)
{
printf("format_string_raw(\"%s\")\n", src); printf("format_string_raw(\"%s\")\n", src);
} }
#endif #endif
if (size == 0) { if (size == 0)
{
return; return;
} }
utf8* end = dest; utf8* end = dest;
size_t left = size; size_t left = size;
format_string_part_from_raw(&end, &left, src, (char**)&args); format_string_part_from_raw(&end, &left, src, (char**)&args);
if (left == 0) { if (left == 0)
{
// Replace last character with null terminator // Replace last character with null terminator
*(end - 1) = '\0'; *(end - 1) = '\0';
log_warning("Truncating formatted string \"%s\" to %d bytes.", dest, size); log_warning("Truncating formatted string \"%s\" to %d bytes.", dest, size);
} else { }
else
{
// Null terminate // Null terminate
*end = '\0'; *end = '\0';
} }
@ -1200,12 +1364,14 @@ void format_string_raw(utf8 *dest, size_t size, utf8 *src, void *args)
void format_string_to_upper(utf8* dest, size_t size, rct_string_id format, void* args) void format_string_to_upper(utf8* dest, size_t size, rct_string_id format, void* args)
{ {
#ifdef DEBUG #ifdef DEBUG
if (gDebugStringFormatting) { if (gDebugStringFormatting)
{
printf("format_string_to_upper(%hu)\n", format); printf("format_string_to_upper(%hu)\n", format);
} }
#endif #endif
if (size == 0) { if (size == 0)
{
return; return;
} }
@ -1213,7 +1379,8 @@ void format_string_to_upper(utf8 *dest, size_t size, rct_string_id format, void
std::string upperString = String::ToUpper(dest); std::string upperString = String::ToUpper(dest);
if (upperString.size() + 1 >= size) { if (upperString.size() + 1 >= size)
{
upperString.resize(size - 1); upperString.resize(size - 1);
dest[size - 1] = '\0'; dest[size - 1] = '\0';
log_warning("Truncating formatted string \"%s\" to %d bytes.", dest, size); log_warning("Truncating formatted string \"%s\" to %d bytes.", dest, size);

View File

@ -10,14 +10,14 @@
#ifndef LOCALISATION_H #ifndef LOCALISATION_H
#define LOCALISATION_H #define LOCALISATION_H
#include <cstring> #include "../management/Marketing.h"
#include "Currency.h" #include "Currency.h"
#include "Date.h" #include "Date.h"
#include "FormatCodes.h" #include "FormatCodes.h"
#include "Language.h" #include "Language.h"
#include "StringIds.h" #include "StringIds.h"
#include "../management/Marketing.h"
#include <cstring>
bool utf8_is_format_code(int32_t codepoint); bool utf8_is_format_code(int32_t codepoint);
bool utf8_is_colour_code(int32_t codepoint); bool utf8_is_colour_code(int32_t codepoint);
@ -52,7 +52,8 @@ bool is_user_string_id(rct_string_id stringId);
#define REAL_NAME_END 0xDFFF #define REAL_NAME_END 0xDFFF
// Constants used by user_string_allocate // Constants used by user_string_allocate
enum { enum
{
USER_STRING_HIGH_ID_NUMBER = 1 << 2, USER_STRING_HIGH_ID_NUMBER = 1 << 2,
USER_STRING_DUPLICATION_PERMITTED = 1 << 7 USER_STRING_DUPLICATION_PERMITTED = 1 << 7
}; };
@ -83,14 +84,19 @@ extern const rct_string_id DateGameShortMonthNames[MONTH_COUNT];
} }
#define set_format_arg(offset, type, value) \ #define set_format_arg(offset, type, value) \
do { static_assert(sizeof(type) <= sizeof(uintptr_t), "Type too large"); \ do \
set_format_arg_body(gCommonFormatArgs, offset, (uintptr_t)(value), sizeof(type)); } while (false) { \
static_assert(sizeof(type) <= sizeof(uintptr_t), "Type too large"); \
set_format_arg_body(gCommonFormatArgs, offset, (uintptr_t)(value), sizeof(type)); \
} while (false)
#define set_format_arg_on(args, offset, type, value) \ #define set_format_arg_on(args, offset, type, value) set_format_arg_body(args, offset, (uintptr_t)(value), sizeof(type))
set_format_arg_body(args, offset, (uintptr_t)(value), sizeof(type))
#define set_map_tooltip_format_arg(offset, type, value) \ #define set_map_tooltip_format_arg(offset, type, value) \
do { static_assert(sizeof(type) <= sizeof(uintptr_t), "Type too large"); \ do \
set_format_arg_body(gMapTooltipFormatArgs, offset, (uintptr_t)(value), sizeof(type)); } while (false) { \
static_assert(sizeof(type) <= sizeof(uintptr_t), "Type too large"); \
set_format_arg_body(gMapTooltipFormatArgs, offset, (uintptr_t)(value), sizeof(type)); \
} while (false)
#endif #endif

View File

@ -7,17 +7,19 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include <stdexcept> #include "LocalisationService.h"
#include "../Context.h" #include "../Context.h"
#include "../PlatformEnvironment.h"
#include "../core/Path.hpp" #include "../core/Path.hpp"
#include "../interface/Fonts.h" #include "../interface/Fonts.h"
#include "../object/ObjectManager.h" #include "../object/ObjectManager.h"
#include "../PlatformEnvironment.h"
#include "Language.h" #include "Language.h"
#include "LanguagePack.h" #include "LanguagePack.h"
#include "LocalisationService.h"
#include "StringIds.h" #include "StringIds.h"
#include <stdexcept>
using namespace OpenRCT2; using namespace OpenRCT2;
using namespace OpenRCT2::Localisation; using namespace OpenRCT2::Localisation;
@ -27,7 +29,8 @@ static constexpr uint16_t MAX_OBJECT_CACHED_STRINGS = 2048;
LocalisationService::LocalisationService(const std::shared_ptr<IPlatformEnvironment>& env) LocalisationService::LocalisationService(const std::shared_ptr<IPlatformEnvironment>& env)
: _env(env) : _env(env)
{ {
for (rct_string_id stringId = NONSTEX_BASE_STRING_ID + MAX_OBJECT_CACHED_STRINGS; stringId >= NONSTEX_BASE_STRING_ID; stringId--) for (rct_string_id stringId = NONSTEX_BASE_STRING_ID + MAX_OBJECT_CACHED_STRINGS; stringId >= NONSTEX_BASE_STRING_ID;
stringId--)
{ {
_availableObjectStringIds.push(stringId); _availableObjectStringIds.push(stringId);
} }
@ -83,7 +86,8 @@ void LocalisationService::OpenLanguage(int32_t id, IObjectManager& objectManager
if (id != LANGUAGE_ENGLISH_UK) if (id != LANGUAGE_ENGLISH_UK)
{ {
filename = GetLanguagePath(LANGUAGE_ENGLISH_UK); filename = GetLanguagePath(LANGUAGE_ENGLISH_UK);
_languageFallback = std::unique_ptr<ILanguagePack>(LanguagePackFactory::FromFile(LANGUAGE_ENGLISH_UK, filename.c_str())); _languageFallback
= std::unique_ptr<ILanguagePack>(LanguagePackFactory::FromFile(LANGUAGE_ENGLISH_UK, filename.c_str()));
} }
filename = GetLanguagePath(id); filename = GetLanguagePath(id);
@ -109,7 +113,8 @@ void LocalisationService::CloseLanguages()
_currentLanguage = LANGUAGE_UNDEFINED; _currentLanguage = LANGUAGE_UNDEFINED;
} }
std::tuple<rct_string_id, rct_string_id, rct_string_id> LocalisationService::GetLocalisedScenarioStrings(const std::string& scenarioFilename) const std::tuple<rct_string_id, rct_string_id, rct_string_id>
LocalisationService::GetLocalisedScenarioStrings(const std::string& scenarioFilename) const
{ {
auto result0 = _languageCurrent->GetScenarioOverrideStringId(scenarioFilename.c_str(), 0); auto result0 = _languageCurrent->GetScenarioOverrideStringId(scenarioFilename.c_str(), 0);
auto result1 = _languageCurrent->GetScenarioOverrideStringId(scenarioFilename.c_str(), 1); auto result1 = _languageCurrent->GetScenarioOverrideStringId(scenarioFilename.c_str(), 1);

View File

@ -9,11 +9,12 @@
#pragma once #pragma once
#include "../common.h"
#include <memory> #include <memory>
#include <stack> #include <stack>
#include <string> #include <string>
#include <tuple> #include <tuple>
#include "../common.h"
interface ILanguagePack; interface ILanguagePack;
interface IObjectManager; interface IObjectManager;
@ -36,15 +37,25 @@ namespace OpenRCT2::Localisation
std::stack<rct_string_id> _availableObjectStringIds; std::stack<rct_string_id> _availableObjectStringIds;
public: public:
int32_t GetCurrentLanguage() const { return _currentLanguage; } int32_t GetCurrentLanguage() const
bool UseTrueTypeFont() const { return _useTrueTypeFont; } {
void UseTrueTypeFont(bool value) { _useTrueTypeFont = value; } return _currentLanguage;
}
bool UseTrueTypeFont() const
{
return _useTrueTypeFont;
}
void UseTrueTypeFont(bool value)
{
_useTrueTypeFont = value;
}
LocalisationService(const std::shared_ptr<IPlatformEnvironment>& env); LocalisationService(const std::shared_ptr<IPlatformEnvironment>& env);
~LocalisationService(); ~LocalisationService();
const char* GetString(rct_string_id id) const; const char* GetString(rct_string_id id) const;
std::tuple<rct_string_id, rct_string_id, rct_string_id> GetLocalisedScenarioStrings(const std::string& scenarioFilename) const; std::tuple<rct_string_id, rct_string_id, rct_string_id>
GetLocalisedScenarioStrings(const std::string& scenarioFilename) const;
rct_string_id GetObjectOverrideStringId(const char* identifier, uint8_t index) const; rct_string_id GetObjectOverrideStringId(const char* identifier, uint8_t index) const;
std::string GetLanguagePath(uint32_t languageId) const; std::string GetLanguagePath(uint32_t languageId) const;
@ -53,7 +64,7 @@ namespace OpenRCT2::Localisation
rct_string_id AllocateObjectString(const std::string& target); rct_string_id AllocateObjectString(const std::string& target);
void FreeObjectString(rct_string_id stringId); void FreeObjectString(rct_string_id stringId);
}; };
} } // namespace OpenRCT2::Localisation
// Legacy getters // Legacy getters
// TODO Remove usages of these and instead call via shared reference // TODO Remove usages of these and instead call via shared reference

View File

@ -15,7 +15,8 @@
#define STR_NONE ((rct_string_id)-1) #define STR_NONE ((rct_string_id)-1)
#define STR_VIEWPORT ((rct_string_id)-2) #define STR_VIEWPORT ((rct_string_id)-2)
enum { enum
{
STR_EMPTY = 0, STR_EMPTY = 0,
// STR_0001 :{STRINGID} {COMMA16} // STR_0001 :{STRINGID} {COMMA16}
STR_RIDE_NAME_SPIRAL_ROLLER_COASTER = 2, STR_RIDE_NAME_SPIRAL_ROLLER_COASTER = 2,
@ -3244,7 +3245,8 @@ enum {
STR_NOTIFICATION_GUEST_DIED = 5606, STR_NOTIFICATION_GUEST_DIED = 5606,
STR_TILE_INSPECTOR_BASE_HEIGHT_SHORT = 5608, STR_TILE_INSPECTOR_BASE_HEIGHT_SHORT = 5608,
STR_TILE_INSPECTOR_CLEARANGE_HEIGHT_SHORT = 5609, STR_TILE_INSPECTOR_CLEARANGE_HEIGHT_SHORT = 5609,
// STR_5610 :{SMALLFONT}{BLACK}Remove the currently selected map element. This will forcefully remove it, so no cash will be used/gained. Use with caution. // STR_5610 :{SMALLFONT}{BLACK}Remove the currently selected map element. This will forcefully remove it, so no cash will
// be used/gained. Use with caution.
STR_REMOVE_SELECTED_ELEMENT_TIP = 5610, STR_REMOVE_SELECTED_ELEMENT_TIP = 5610,
STR_TILE_INSPECTOR_FLAG_GHOST_SHORT = 5611, STR_TILE_INSPECTOR_FLAG_GHOST_SHORT = 5611,
STR_TILE_INSPECTOR_FLAG_GHOST = 5612, STR_TILE_INSPECTOR_FLAG_GHOST = 5612,

View File

@ -8,6 +8,7 @@
*****************************************************************************/ *****************************************************************************/
#include "Localisation.h" #include "Localisation.h"
#include <wchar.h> #include <wchar.h>
uint32_t utf8_get_next(const utf8* char_ptr, const utf8** nextchar_ptr) uint32_t utf8_get_next(const utf8* char_ptr, const utf8** nextchar_ptr)
@ -15,19 +16,29 @@ uint32_t utf8_get_next(const utf8 *char_ptr, const utf8 **nextchar_ptr)
int32_t result; int32_t result;
int32_t numBytes; int32_t numBytes;
if (!(char_ptr[0] & 0x80)) { if (!(char_ptr[0] & 0x80))
{
result = char_ptr[0]; result = char_ptr[0];
numBytes = 1; numBytes = 1;
} else if ((char_ptr[0] & 0xE0) == 0xC0) { }
else if ((char_ptr[0] & 0xE0) == 0xC0)
{
result = ((char_ptr[0] & 0x1F) << 6) | (char_ptr[1] & 0x3F); result = ((char_ptr[0] & 0x1F) << 6) | (char_ptr[1] & 0x3F);
numBytes = 2; numBytes = 2;
} else if ((char_ptr[0] & 0xF0) == 0xE0) { }
else if ((char_ptr[0] & 0xF0) == 0xE0)
{
result = ((char_ptr[0] & 0x0F) << 12) | ((char_ptr[1] & 0x3F) << 6) | (char_ptr[2] & 0x3F); result = ((char_ptr[0] & 0x0F) << 12) | ((char_ptr[1] & 0x3F) << 6) | (char_ptr[2] & 0x3F);
numBytes = 3; numBytes = 3;
} else if ((char_ptr[0] & 0xF8) == 0xF0) { }
result = ((char_ptr[0] & 0x07) << 18) | ((char_ptr[1] & 0x3F) << 12) | ((char_ptr[1] & 0x3F) << 6) | (char_ptr[2] & 0x3F); else if ((char_ptr[0] & 0xF8) == 0xF0)
{
result
= ((char_ptr[0] & 0x07) << 18) | ((char_ptr[1] & 0x3F) << 12) | ((char_ptr[1] & 0x3F) << 6) | (char_ptr[2] & 0x3F);
numBytes = 4; numBytes = 4;
} else { }
else
{
// TODO 4 bytes // TODO 4 bytes
result = ' '; result = ' ';
numBytes = 1; numBytes = 1;
@ -40,19 +51,26 @@ uint32_t utf8_get_next(const utf8 *char_ptr, const utf8 **nextchar_ptr)
utf8* utf8_write_codepoint(utf8* dst, uint32_t codepoint) utf8* utf8_write_codepoint(utf8* dst, uint32_t codepoint)
{ {
if (codepoint <= 0x7F) { if (codepoint <= 0x7F)
{
dst[0] = (utf8)codepoint; dst[0] = (utf8)codepoint;
return dst + 1; return dst + 1;
} else if (codepoint <= 0x7FF) { }
else if (codepoint <= 0x7FF)
{
dst[0] = 0xC0 | ((codepoint >> 6) & 0x1F); dst[0] = 0xC0 | ((codepoint >> 6) & 0x1F);
dst[1] = 0x80 | (codepoint & 0x3F); dst[1] = 0x80 | (codepoint & 0x3F);
return dst + 2; return dst + 2;
} else if (codepoint <= 0xFFFF) { }
else if (codepoint <= 0xFFFF)
{
dst[0] = 0xE0 | ((codepoint >> 12) & 0x0F); dst[0] = 0xE0 | ((codepoint >> 12) & 0x0F);
dst[1] = 0x80 | ((codepoint >> 6) & 0x3F); dst[1] = 0x80 | ((codepoint >> 6) & 0x3F);
dst[2] = 0x80 | (codepoint & 0x3F); dst[2] = 0x80 | (codepoint & 0x3F);
return dst + 3; return dst + 3;
} else { }
else
{
dst[0] = 0xF0 | ((codepoint >> 18) & 0x07); dst[0] = 0xF0 | ((codepoint >> 18) & 0x07);
dst[1] = 0x80 | ((codepoint >> 12) & 0x3F); dst[1] = 0x80 | ((codepoint >> 12) & 0x3F);
dst[2] = 0x80 | ((codepoint >> 6) & 0x3F); dst[2] = 0x80 | ((codepoint >> 6) & 0x3F);
@ -76,20 +94,29 @@ int32_t utf8_insert_codepoint(utf8 *dst, uint32_t codepoint)
bool utf8_is_codepoint_start(const utf8* text) bool utf8_is_codepoint_start(const utf8* text)
{ {
if ((text[0] & 0x80) == 0) return true; if ((text[0] & 0x80) == 0)
if ((text[0] & 0xC0) == 0xC0) return true; return true;
if ((text[0] & 0xC0) == 0xC0)
return true;
return false; return false;
} }
int32_t utf8_get_codepoint_length(int32_t codepoint) int32_t utf8_get_codepoint_length(int32_t codepoint)
{ {
if (codepoint <= 0x7F) { if (codepoint <= 0x7F)
{
return 1; return 1;
} else if (codepoint <= 0x7FF) { }
else if (codepoint <= 0x7FF)
{
return 2; return 2;
} else if (codepoint <= 0xFFFF) { }
else if (codepoint <= 0xFFFF)
{
return 3; return 3;
} else { }
else
{
return 4; return 4;
} }
} }
@ -103,7 +130,8 @@ int32_t utf8_length(const utf8 *text)
const utf8* ch = text; const utf8* ch = text;
int32_t count = 0; int32_t count = 0;
while (utf8_get_next(ch, &ch) != 0) { while (utf8_get_next(ch, &ch) != 0)
{
count++; count++;
} }
return count; return count;
@ -116,10 +144,14 @@ wchar_t *utf8_to_widechar(const utf8 *src)
const utf8* ch = src; const utf8* ch = src;
int32_t codepoint; int32_t codepoint;
while ((codepoint = utf8_get_next(ch, &ch)) != 0) { while ((codepoint = utf8_get_next(ch, &ch)) != 0)
if ((uint32_t)codepoint > 0xFFFF) { {
if ((uint32_t)codepoint > 0xFFFF)
{
*dst++ = '?'; *dst++ = '?';
} else { }
else
{
*dst++ = codepoint; *dst++ = codepoint;
} }
} }
@ -133,7 +165,8 @@ utf8 *widechar_to_utf8(const wchar_t *src)
utf8* result = (utf8*)malloc((wcslen(src) * 4) + 1); utf8* result = (utf8*)malloc((wcslen(src) * 4) + 1);
utf8* dst = result; utf8* dst = result;
for (; *src != 0; src++) { for (; *src != 0; src++)
{
dst = utf8_write_codepoint(dst, *src); dst = utf8_write_codepoint(dst, *src);
} }
*dst++ = 0; *dst++ = 0;
@ -142,7 +175,6 @@ utf8 *widechar_to_utf8(const wchar_t *src)
return (utf8*)realloc(result, size); return (utf8*)realloc(result, size);
} }
/** /**
* Returns a pointer to the null terminator of the given UTF-8 string. * Returns a pointer to the null terminator of the given UTF-8 string.
*/ */
@ -151,7 +183,8 @@ utf8 *get_string_end(const utf8 *text)
int32_t codepoint; int32_t codepoint;
const utf8* ch = text; const utf8* ch = text;
while ((codepoint = utf8_get_next(ch, &ch)) != 0) { while ((codepoint = utf8_get_next(ch, &ch)) != 0)
{
int32_t argLength = utf8_get_format_code_arg_length(codepoint); int32_t argLength = utf8_get_format_code_arg_length(codepoint);
ch += argLength; ch += argLength;
} }
@ -175,10 +208,14 @@ int32_t get_string_length(const utf8 *text)
const utf8* ch = text; const utf8* ch = text;
int32_t count = 0; int32_t count = 0;
while ((codepoint = utf8_get_next(ch, &ch)) != 0) { while ((codepoint = utf8_get_next(ch, &ch)) != 0)
if (utf8_is_format_code(codepoint)) { {
if (utf8_is_format_code(codepoint))
{
ch += utf8_get_format_code_arg_length(codepoint); ch += utf8_get_format_code_arg_length(codepoint);
} else { }
else
{
count++; count++;
} }
} }
@ -187,7 +224,8 @@ int32_t get_string_length(const utf8 *text)
int32_t utf8_get_format_code_arg_length(int32_t codepoint) int32_t utf8_get_format_code_arg_length(int32_t codepoint)
{ {
switch (codepoint) { switch (codepoint)
{
case FORMAT_MOVE_X: case FORMAT_MOVE_X:
case FORMAT_ADJUST_PALETTE: case FORMAT_ADJUST_PALETTE:
case 3: case 3:
@ -202,17 +240,22 @@ int32_t utf8_get_format_code_arg_length(int32_t codepoint)
} }
} }
void utf8_remove_formatting(utf8* string, bool allowColours) { void utf8_remove_formatting(utf8* string, bool allowColours)
{
utf8* readPtr = string; utf8* readPtr = string;
utf8* writePtr = string; utf8* writePtr = string;
while (true) { while (true)
{
uint32_t code = utf8_get_next(readPtr, (const utf8**)&readPtr); uint32_t code = utf8_get_next(readPtr, (const utf8**)&readPtr);
if (code == 0) { if (code == 0)
{
*writePtr = 0; *writePtr = 0;
break; break;
} else if (!utf8_is_format_code(code) || (allowColours && utf8_is_colour_code(code))) { }
else if (!utf8_is_format_code(code) || (allowColours && utf8_is_colour_code(code)))
{
writePtr = utf8_write_codepoint(writePtr, code); writePtr = utf8_write_codepoint(writePtr, code);
} }
} }
@ -220,15 +263,20 @@ void utf8_remove_formatting(utf8* string, bool allowColours) {
bool utf8_is_format_code(int32_t codepoint) bool utf8_is_format_code(int32_t codepoint)
{ {
if (codepoint < 32) return true; if (codepoint < 32)
if (codepoint >= FORMAT_ARGUMENT_CODE_START && codepoint <= FORMAT_ARGUMENT_CODE_END) return true; return true;
if (codepoint >= FORMAT_COLOUR_CODE_START && codepoint <= FORMAT_COLOUR_CODE_END) return true; if (codepoint >= FORMAT_ARGUMENT_CODE_START && codepoint <= FORMAT_ARGUMENT_CODE_END)
if (codepoint == FORMAT_COMMA1DP16) return true; return true;
if (codepoint >= FORMAT_COLOUR_CODE_START && codepoint <= FORMAT_COLOUR_CODE_END)
return true;
if (codepoint == FORMAT_COMMA1DP16)
return true;
return false; return false;
} }
bool utf8_is_colour_code(int32_t codepoint) bool utf8_is_colour_code(int32_t codepoint)
{ {
if (codepoint >= FORMAT_COLOUR_CODE_START && codepoint <= FORMAT_COLOUR_CODE_END) return true; if (codepoint >= FORMAT_COLOUR_CODE_START && codepoint <= FORMAT_COLOUR_CODE_END)
return true;
return false; return false;
} }

View File

@ -7,11 +7,12 @@
* OpenRCT2 is licensed under the GNU General Public License version 3. * OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/ *****************************************************************************/
#include "User.h"
#include "../Game.h" #include "../Game.h"
#include "../ride/Ride.h" #include "../ride/Ride.h"
#include "../util/Util.h" #include "../util/Util.h"
#include "Localisation.h" #include "Localisation.h"
#include "User.h"
utf8 gUserStrings[MAX_USER_STRINGS][USER_STRING_MAX_LENGTH]; utf8 gUserStrings[MAX_USER_STRINGS][USER_STRING_MAX_LENGTH];
@ -35,7 +36,8 @@ rct_string_id user_string_allocate(int32_t base, const utf8 *text)
int32_t highBits = (base & 0x7F) << 9; int32_t highBits = (base & 0x7F) << 9;
bool allowDuplicates = base & USER_STRING_DUPLICATION_PERMITTED; bool allowDuplicates = base & USER_STRING_DUPLICATION_PERMITTED;
if (!allowDuplicates && user_string_exists(text)) { if (!allowDuplicates && user_string_exists(text))
{
gGameCommandErrorText = STR_CHOSEN_NAME_IN_USE_ALREADY; gGameCommandErrorText = STR_CHOSEN_NAME_IN_USE_ALREADY;
return 0; return 0;
} }