Refactor/Improve String and Path Handling

This commit is contained in:
LRFLEW 2016-09-25 21:24:29 -05:00
parent 211a0d7863
commit e5ff7412e4
94 changed files with 1038 additions and 989 deletions

View File

@ -344,7 +344,7 @@ static exitcode_t HandleCommandSetRCT2(CommandLineArgEnumerator * enumerator)
// Check user path that will contain the config
utf8 userPath[MAX_PATH];
platform_resolve_user_data_path();
platform_get_user_directory(userPath, NULL);
platform_get_user_directory(userPath, NULL, sizeof(userPath));
if (!platform_ensure_directory_exists(userPath)) {
Console::Error::WriteLine("Unable to access or create directory '%s'.", userPath);
return EXITCODE_FAIL;

View File

@ -547,7 +547,7 @@ int cmdline_for_sprite(const char **argv, int argc)
for (int x = 0; x < numbers; x++){
outputPath[pathLen + x] = '0';
}
safe_strcpy(outputPath + pathLen + numbers, ".png", MAX_PATH);
safe_strcpy(outputPath + pathLen + numbers, ".png", MAX_PATH - pathLen - numbers);
for (int spriteIndex = 0; spriteIndex < maxIndex; spriteIndex++){
@ -651,7 +651,9 @@ int cmdline_for_sprite(const char **argv, int argc)
safe_strcpy(imagePath, resourcePath, MAX_PATH);
if (resourcePath[resourceLength - 1] == '/' || resourcePath[resourceLength - 1] == '\\')
imagePath[resourceLength - 1] = 0;
sprintf(imagePath, "%s%c%d.png", imagePath, platform_get_path_separator(), i);
char filename[16];
snprintf(filename, 16, "%d.png", i);
safe_strcat_path(imagePath, filename, MAX_PATH);
file = SDL_RWFromFile(imagePath, "r");
if (file != NULL) {

View File

@ -371,7 +371,7 @@ static void rwopsprintf(SDL_RWops *file, const char *format, ...)
va_start(args, format);
char buffer[64];
vsprintf(buffer, format, args);
vsnprintf(buffer, 64, format, args);
SDL_RWwrite(file, buffer, strlen(buffer), 1);
@ -380,7 +380,7 @@ static void rwopsprintf(SDL_RWops *file, const char *format, ...)
static void rwopswritenewline(SDL_RWops *file)
{
rwopswritestr(file, platform_get_new_line());
rwopswritestr(file, PLATFORM_NEWLINE);
}
static void rwopswritestresc(SDL_RWops *file, const char *str) {
@ -468,17 +468,17 @@ void config_release()
}
}
void config_get_default_path(utf8 *outPath)
void config_get_default_path(utf8 *outPath, size_t size)
{
platform_get_user_directory(outPath, NULL);
strcat(outPath, "config.ini");
platform_get_user_directory(outPath, NULL, size);
safe_strcat_path(outPath, "config.ini", size);
}
bool config_open_default()
{
utf8 path[MAX_PATH];
config_get_default_path(path);
config_get_default_path(path, sizeof(path));
if (config_open(path)) {
currency_load_custom_currency_config();
return true;
@ -491,7 +491,7 @@ bool config_save_default()
{
utf8 path[MAX_PATH];
config_get_default_path(path);
config_get_default_path(path, sizeof(path));
if (config_save(path)) {
return true;
}
@ -950,9 +950,8 @@ bool config_find_or_browse_install_directory()
if (platform_original_game_data_exists(installPath))
return true;
utf8 message[MAX_PATH] = { 0 };
char separator = platform_get_path_separator();
sprintf(message, "Could not find %s%cData%cg1.dat at this path", installPath, separator, separator);
utf8 message[MAX_PATH];
snprintf(message, MAX_PATH, "Could not find %s" PATH_SEPARATOR "Data" PATH_SEPARATOR "g1.dat at this path", installPath);
platform_show_messagebox(message);
}
}
@ -1043,10 +1042,10 @@ void config_reset_shortcut_keys()
memcpy(gShortcutKeys, _defaultShortcutKeys, sizeof(gShortcutKeys));
}
static void config_shortcut_keys_get_path(utf8 *outPath)
static void config_shortcut_keys_get_path(utf8 *outPath, size_t size)
{
platform_get_user_directory(outPath, NULL);
strcat(outPath, "hotkeys.cfg");
platform_get_user_directory(outPath, NULL, size);
safe_strcat_path(outPath, "hotkeys.cfg", size);
}
bool config_shortcut_keys_load()
@ -1056,7 +1055,7 @@ bool config_shortcut_keys_load()
bool result;
uint16 version;
config_shortcut_keys_get_path(path);
config_shortcut_keys_get_path(path, sizeof(path));
file = SDL_RWFromFile(path, "rb");
if (file != NULL) {
@ -1086,7 +1085,7 @@ bool config_shortcut_keys_save()
SDL_RWops *file;
bool result;
config_shortcut_keys_get_path(path);
config_shortcut_keys_get_path(path, sizeof(path));
file = SDL_RWFromFile(path, "wb");
if (file != NULL) {
@ -1112,34 +1111,39 @@ void title_sequences_set_default()
{
char path[MAX_PATH];
char dataPath[MAX_PATH];
char sep = platform_get_path_separator();
platform_get_user_directory(path, "title sequences");
platform_get_user_directory(path, "title sequences", sizeof(path));
platform_ensure_directory_exists(path);
gConfigTitleSequences.presets = malloc(0);
gConfigTitleSequences.num_presets = 0;
platform_get_openrct_data_path(dataPath);
platform_get_openrct_data_path(dataPath, sizeof(dataPath));
safe_strcat_path(dataPath, "title", MAX_PATH);
// RCT1 title sequence
sprintf(path, "%s%c%s%c%s%c", dataPath, sep, "title", sep, "rct1", sep);
safe_strcpy(path, dataPath, MAX_PATH);
safe_strcat_path(path, "rct1", MAX_PATH);
title_sequence_open(path, language_get_string(STR_TITLE_SEQUENCE_RCT1));
// RCT1 (AA) title sequence
sprintf(path, "%s%c%s%c%s%c", dataPath, sep, "title", sep, "rct1aa", sep);
safe_strcpy(path, dataPath, MAX_PATH);
safe_strcat_path(path, "rct1aa", MAX_PATH);
title_sequence_open(path, language_get_string(STR_TITLE_SEQUENCE_RCT1_AA));
// RCT1 (AA + LL) title sequence
sprintf(path, "%s%c%s%c%s%c", dataPath, sep, "title", sep, "rct1aall", sep);
safe_strcpy(path, dataPath, MAX_PATH);
safe_strcat_path(path, "rct1aall", MAX_PATH);
title_sequence_open(path, language_get_string(STR_TITLE_SEQUENCE_RCT1_AA_LL));
// RCT2 title sequence
sprintf(path, "%s%c%s%c%s%c", dataPath, sep, "title", sep, "rct2", sep);
safe_strcpy(path, dataPath, MAX_PATH);
safe_strcat_path(path, "rct2", MAX_PATH);
title_sequence_open(path, language_get_string(STR_TITLE_SEQUENCE_RCT2));
// OpenRCT2 title sequence
sprintf(path, "%s%c%s%c%s%c", dataPath, sep, "title", sep, "openrct2", sep);
safe_strcpy(path, dataPath, MAX_PATH);
safe_strcat_path(path, "openrct2", MAX_PATH);
title_sequence_open(path, language_get_string(STR_TITLE_SEQUENCE_OPENRCT2));
}
@ -1149,11 +1153,11 @@ void title_sequences_load_presets()
int dirEnumHandle, i;
// Find all directories in the title sequences folder
platform_get_user_directory(path, "title sequences");
platform_get_user_directory(path, "title sequences", sizeof(path));
dirEnumHandle = platform_enumerate_directories_begin(path);
while (platform_enumerate_directories_next(dirEnumHandle, titleDir)) {
platform_get_user_directory(path, "title sequences");
strcat(path, titleDir);
platform_get_user_directory(path, "title sequences", sizeof(path));
safe_strcat(path, titleDir, sizeof(path));
title_sequence_open(path, NULL);
}
platform_enumerate_directories_end(dirEnumHandle);
@ -1197,8 +1201,8 @@ static void title_sequence_open(const char *path, const char *customName)
char parts[3 * 128], *token, *part1, *part2;
// Check for the script file
safe_strcpy(scriptPath, path, MAX_PATH);
strcat(scriptPath, "script.txt");
safe_strcpy(scriptPath, path, sizeof(scriptPath));
safe_strcat_path(scriptPath, "script.txt", sizeof(scriptPath));
if (!platform_file_exists(scriptPath)) {
// No script file, title sequence is invalid
return;
@ -1221,9 +1225,9 @@ static void title_sequence_open(const char *path, const char *customName)
safe_strcpy(nameBuffer, path, MAX_PATH);
// Get folder name
// First strip off the last folder separator
*strrchr(nameBuffer, platform_get_path_separator()) = '\0';
*strrchr(nameBuffer, *PATH_SEPARATOR) = '\0';
// Then find the name of the folder
char *name = strrchr(nameBuffer, platform_get_path_separator()) + 1;
char *name = strrchr(nameBuffer, *PATH_SEPARATOR) + 1;
safe_strcpy(gConfigTitleSequences.presets[preset].name, name, TITLE_SEQUENCE_NAME_SIZE);
gConfigTitleSequences.presets[preset].path[0] = 0;
}
@ -1239,8 +1243,8 @@ static void title_sequence_open(const char *path, const char *customName)
}
// Get the save file list
safe_strcpy(titlePath, path, MAX_PATH);
strcat(titlePath, "*.sv6");
safe_strcpy(titlePath, path, sizeof(titlePath));
safe_strcat_path(titlePath, "*.sv6", sizeof(titlePath));
fileEnumHandle = platform_enumerate_files_begin(titlePath);
while (platform_enumerate_files_next(fileEnumHandle, &fileInfo)) {
gConfigTitleSequences.presets[preset].num_saves++;
@ -1249,8 +1253,8 @@ static void title_sequence_open(const char *path, const char *customName)
gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1][TITLE_SEQUENCE_MAX_SAVE_LENGTH - 1] = '\0';
}
platform_enumerate_files_end(fileEnumHandle);
safe_strcpy(titlePath, path, MAX_PATH);
strcat(titlePath, "*.sc6");
safe_strcpy(titlePath, path, sizeof(titlePath));
safe_strcat_path(titlePath, "*.sc6", sizeof(titlePath));
fileEnumHandle = platform_enumerate_files_begin(titlePath);
while (platform_enumerate_files_next(fileEnumHandle, &fileInfo)) {
gConfigTitleSequences.presets[preset].num_saves++;
@ -1321,13 +1325,11 @@ void title_sequence_save_preset_script(int preset)
utf8 path[MAX_PATH];
SDL_RWops *file;
int i;
char separator = platform_get_path_separator();
platform_get_user_directory(path, "title sequences");
strcat(path, gConfigTitleSequences.presets[preset].name);
strncat(path, &separator, 1);
strcat(path, "script.txt");
platform_get_user_directory(path, "title sequences", sizeof(path));
safe_strcat_path(path, gConfigTitleSequences.presets[preset].name, MAX_PATH);
safe_strcat_path(path, "script.txt", MAX_PATH);
file = SDL_RWFromFile(path, "wb");
if (file == NULL) {

View File

@ -345,7 +345,7 @@ extern title_sequences_configuration gConfigTitleSequences;
extern uint16 gShortcutKeys[SHORTCUT_COUNT];
void config_get_default_path(utf8 *outPath);
void config_get_default_path(utf8 *outPath, size_t size);
void config_set_defaults();
void config_release();
bool config_open_default();

View File

@ -88,7 +88,7 @@ namespace Console
void WriteLine()
{
fputs(platform_get_new_line(), stderr);
fputs(PLATFORM_NEWLINE, stderr);
}
void WriteLine(const utf8 * format, ...)
@ -105,4 +105,4 @@ namespace Console
puts("");
}
}
}
}

View File

@ -75,7 +75,8 @@ namespace Guard
if (message != nullptr)
{
strcat(buffer, "\r\n");
vsprintf((char *)strchr(buffer, 0), message, args);
char *bufend = (char *)strchr(buffer, 0);
vsnprintf(bufend, sizeof(buffer) - (bufend - buffer), message, args);
}
int result = MessageBox(nullptr, buffer, OPENRCT2_NAME, MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION);
if (result == IDABORT)

View File

@ -36,8 +36,7 @@ namespace Path
utf8 * GetDirectory(utf8 * buffer, size_t bufferSize, const utf8 * path)
{
const char pathSeperator = platform_get_path_separator();
size_t lastPathSepIndex = String::LastIndexOf(path, pathSeperator);
size_t lastPathSepIndex = String::LastIndexOf(path, *PATH_SEPARATOR);
if (lastPathSepIndex == SIZE_MAX)
{
return String::Set(buffer, bufferSize, String::Empty);
@ -54,7 +53,7 @@ namespace Path
const utf8 * lastPathSeperator = nullptr;
for (const utf8 * ch = path; *ch != '\0'; ch++)
{
if (*ch == platform_get_path_separator())
if (*ch == *PATH_SEPARATOR)
{
lastPathSeperator = ch;
}

View File

@ -277,7 +277,7 @@ public:
if (_context == nullptr)
{
char szRequiredVersion[32];
sprintf(szRequiredVersion, "OpenGL %d.%d", requiredVersion.Major, requiredVersion.Minor);
snprintf(szRequiredVersion, 32, "OpenGL %d.%d", requiredVersion.Major, requiredVersion.Minor);
throw Exception(std::string(szRequiredVersion) + std::string(" not available."));
}
SDL_GL_MakeCurrent(_window, _context);

View File

@ -70,7 +70,7 @@ GLuint OpenGLShader::GetShaderId()
void OpenGLShader::GetPath(char * buffer, size_t bufferSize, const char * name)
{
platform_get_openrct_data_path(buffer);
platform_get_openrct_data_path(buffer, bufferSize);
Path::Append(buffer, bufferSize, "shaders");
Path::Append(buffer, bufferSize, name);
if (_type == GL_VERTEX_SHADER)

View File

@ -133,12 +133,12 @@ static uint8 scrolling_text_get_colour(uint32 character)
}
}
static void scrolling_text_format(utf8 *dst, rct_draw_scroll_text *scrollText)
static void scrolling_text_format(utf8 *dst, size_t size, rct_draw_scroll_text *scrollText)
{
if (gConfigGeneral.upper_case_banners) {
format_string_to_upper(dst, scrollText->string_id, &scrollText->string_args_0);
format_string_to_upper(dst, size, scrollText->string_id, &scrollText->string_args_0);
} else {
format_string(dst, scrollText->string_id, &scrollText->string_args_0);
format_string(dst, size, scrollText->string_id, &scrollText->string_args_0);
}
}
@ -1442,7 +1442,7 @@ int scrolling_text_setup(rct_string_id stringId, uint16 scroll, uint16 scrolling
// Create the string to draw
utf8 scrollString[256];
scrolling_text_format(scrollString, scrollText);
scrolling_text_format(scrollString, 256, scrollText);
const sint16* scrollingModePositions = _scrollPositions[scrollingMode];

View File

@ -19,6 +19,7 @@
#include "../openrct2.h"
#include "../platform/platform.h"
#include "../sprites.h"
#include "../util/util.h"
#include "drawing.h"
void *_g1Buffer = NULL;
@ -152,10 +153,9 @@ bool gfx_load_g2()
unsigned int i;
char path[MAX_PATH];
char dataPath[MAX_PATH];
platform_get_openrct_data_path(dataPath);
sprintf(path, "%s%cg2.dat", dataPath, platform_get_path_separator());
platform_get_openrct_data_path(path, sizeof(path));
safe_strcat_path(path, "g2.dat", MAX_PATH);
file = SDL_RWFromFile(path, "rb");
if (file != NULL) {
if (SDL_RWread(file, &g2.header, 8, 1) == 1) {

View File

@ -247,7 +247,7 @@ int gfx_wrap_string(utf8 *text, int width, int *outNumLines, int *outFontHeight)
void gfx_draw_string_left_clipped(rct_drawpixelinfo* dpi, rct_string_id format, void* args, int colour, int x, int y, int width)
{
char* buffer = gCommonStringFormatBuffer;
format_string(buffer, format, args);
format_string(buffer, 256, format, args);
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
@ -272,7 +272,7 @@ void gfx_draw_string_left_clipped(rct_drawpixelinfo* dpi, rct_string_id format,
void gfx_draw_string_centred_clipped(rct_drawpixelinfo *dpi, rct_string_id format, void *args, int colour, int x, int y, int width)
{
char* buffer = gCommonStringFormatBuffer;
format_string(buffer, format, args);
format_string(buffer, 256, format, args);
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
@ -301,7 +301,7 @@ void gfx_draw_string_centred_clipped(rct_drawpixelinfo *dpi, rct_string_id forma
void gfx_draw_string_right(rct_drawpixelinfo* dpi, rct_string_id format, void* args, int colour, int x, int y)
{
char* buffer = gCommonStringFormatBuffer;
format_string(buffer, format, args);
format_string(buffer, 256, format, args);
// Measure text width
short text_width = gfx_get_string_width(buffer);
@ -347,7 +347,7 @@ int gfx_draw_string_centred_wrapped(rct_drawpixelinfo *dpi, void *args, int x, i
char *buffer = gCommonStringFormatBuffer;
gfx_draw_string(dpi, "", colour, dpi->x, dpi->y);
format_string(buffer, format, args);
format_string(buffer, 256, format, args);
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
@ -394,7 +394,7 @@ int gfx_draw_string_left_wrapped(rct_drawpixelinfo *dpi, void *args, int x, int
char *buffer = gCommonStringFormatBuffer;
gfx_draw_string(dpi, "", colour, dpi->x, dpi->y);
format_string(buffer, format, args);
format_string(buffer, 256, format, args);
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
gfx_wrap_string(buffer, width, &numLines, &fontSpriteBase);
@ -423,7 +423,7 @@ int gfx_draw_string_left_wrapped(rct_drawpixelinfo *dpi, void *args, int x, int
void gfx_draw_string_left(rct_drawpixelinfo *dpi, rct_string_id format, void *args, int colour, int x, int y)
{
char* buffer = gCommonStringFormatBuffer;
format_string(buffer, format, args);
format_string(buffer, 256, format, args);
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
gfx_draw_string(dpi, buffer, colour, x, y);
}
@ -435,7 +435,7 @@ void gfx_draw_string_left_centred(rct_drawpixelinfo *dpi, rct_string_id format,
{
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
char *buffer = gCommonStringFormatBuffer;
format_string(buffer, format, args);
format_string(buffer, 256, format, args);
int height = string_get_height_raw(buffer);
gfx_draw_string(dpi, buffer, colour, x, y - (height / 2));
}
@ -500,7 +500,7 @@ void draw_string_left_underline(rct_drawpixelinfo *dpi, rct_string_id format, vo
char buffer[128];
int width;
format_string(buffer, format, args);
format_string(buffer, 128, format, args);
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
width = gfx_get_string_width(buffer);
gfx_draw_string(dpi, buffer, colour, x, y);
@ -514,7 +514,7 @@ void draw_string_right_underline(rct_drawpixelinfo *dpi, rct_string_id format, v
char buffer[128];
int width;
format_string(buffer, format, args);
format_string(buffer, 128, format, args);
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
width = gfx_get_string_width(buffer);
x -= width;
@ -529,7 +529,7 @@ void draw_string_centred_underline(rct_drawpixelinfo *dpi, rct_string_id format,
char buffer[128];
int width;
format_string(buffer, format, args);
format_string(buffer, 128, format, args);
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
width = gfx_get_string_width(buffer);
x -= width / 2;
@ -655,7 +655,7 @@ void gfx_draw_string_centred_wrapped_partial(rct_drawpixelinfo *dpi, int x, int
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
gfx_draw_string(dpi, "", colour, dpi->x, dpi->y);
format_string(buffer, format, args);
format_string(buffer, 256, format, args);
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
@ -844,7 +844,7 @@ bool ttf_initialise()
TTFFontDescriptor *fontDesc = &(gCurrentTTFFontSet->size[i]);
utf8 fontPath[MAX_PATH];
if (!platform_get_font_path(fontDesc, fontPath)) {
if (!platform_get_font_path(fontDesc, fontPath, sizeof(fontPath))) {
log_error("Unable to load font '%s'", fontDesc->font_name);
return false;
}
@ -1345,7 +1345,7 @@ void shorten_path(utf8 *buffer, size_t bufferSize, const utf8 *path, int availab
// Count path separators
int path_separators = 0;
for (size_t x = 0; x < length; x++) {
if (path[x] == platform_get_path_separator()) {
if (path[x] == *PATH_SEPARATOR) {
path_separators++;
}
}
@ -1358,7 +1358,7 @@ void shorten_path(utf8 *buffer, size_t bufferSize, const utf8 *path, int availab
for (int x = 0; x < path_separators; x++){
do {
begin++;
} while (path[begin] != platform_get_path_separator());
} while (path[begin] != *PATH_SEPARATOR);
safe_strcpy(buffer + 3, path + begin, bufferSize - 3);
if (gfx_get_string_width(buffer) <= availableWidth) {

View File

@ -675,8 +675,7 @@ static void rct2_to_utf8_self(char *buffer, size_t length)
char tempBuffer[512];
if (length > 0) {
rct2_to_utf8(tempBuffer, buffer);
strncpy(buffer, tempBuffer, length - 1);
buffer[length - 1] = '\0';
safe_strcpy(buffer, tempBuffer, length);
}
}
@ -954,8 +953,8 @@ static void limit_autosave_count(const size_t numberOfFilesToKeep)
size_t i=0;
platform_get_user_directory(filter, "save");
strncat(filter, "autosave_*.sv6", sizeof(filter) - strnlen(filter, MAX_PATH) - 1);
platform_get_user_directory(filter, "save", sizeof(filter));
safe_strcat_path(filter, "autosave_*.sv6", sizeof(filter));
// At first, count how many autosaves there are
fileEnumHandle = platform_enumerate_files_begin(filter);
@ -977,8 +976,8 @@ static void limit_autosave_count(const size_t numberOfFilesToKeep)
memset(autosaveFiles[i], 0, sizeof(utf8) * MAX_PATH);
if(platform_enumerate_files_next(fileEnumHandle, &fileInfo)) {
platform_get_user_directory(autosaveFiles[i], "save");
strcat(autosaveFiles[i], fileInfo.path);
platform_get_user_directory(autosaveFiles[i], "save", sizeof(utf8) * MAX_PATH);
safe_strcat_path(autosaveFiles[i], fileInfo.path, sizeof(utf8) * MAX_PATH);
}
}
platform_enumerate_files_end(fileEnumHandle);
@ -1008,7 +1007,7 @@ void game_autosave()
{
utf8 path[MAX_PATH];
utf8 backupPath[MAX_PATH];
utf8 timeString[21]="";
utf8 timeName[34];
// retrieve current time
rct2_date currentDate;
@ -1016,18 +1015,15 @@ void game_autosave()
rct2_time currentTime;
platform_get_time_local(&currentTime);
sprintf(timeString, "%d-%02d-%02d_%02d-%02d-%02d", currentDate.year, currentDate.month, currentDate.day, currentTime.hour, currentTime.minute,currentTime.second);
snprintf(timeName, 34, "autosave_%d-%02d-%02d_%02d-%02d-%02d.sv6", currentDate.year, currentDate.month, currentDate.day, currentTime.hour, currentTime.minute,currentTime.second);
limit_autosave_count(NUMBER_OF_AUTOSAVES_TO_KEEP);
platform_get_user_directory(path, "save");
safe_strcpy(backupPath, path, MAX_PATH);
platform_get_user_directory(path, "save", sizeof(path));
safe_strcpy(backupPath, path, sizeof(backupPath));
strcat(path, "autosave_");
strcat(path, timeString);
strcat(path, ".sv6");
strcat(backupPath, "autosave.sv6.bak");
safe_strcat_path(path, timeName, sizeof(path));
safe_strcat_path(backupPath, "autosave.sv6.bak", sizeof(backupPath));
if (platform_file_exists(path)) {
platform_file_copy(path, backupPath, true);
@ -1048,10 +1044,10 @@ void rct2_exit_reason(rct_string_id title, rct_string_id body){
// Before this would set a quit message
char exit_title[255];
format_string(exit_title, title, 0);
format_string(exit_title, 256, title, 0);
char exit_body[255];
format_string(exit_body, body, 0);
format_string(exit_body, 256, body, 0);
log_error(exit_title);
log_error(exit_body);

View File

@ -644,7 +644,7 @@ namespace ThemeManager
void GetThemePath(utf8 * buffer, size_t bufferSize)
{
platform_get_user_directory(buffer, "themes");
platform_get_user_directory(buffer, "themes", bufferSize);
}
}

View File

@ -102,7 +102,7 @@ void chat_draw(rct_drawpixelinfo * dpi)
continue;
}
safe_strcpy(lineBuffer, chat_history_get(i), CHAT_INPUT_SIZE + 10);
safe_strcpy(lineBuffer, chat_history_get(i), sizeof(lineBuffer));
int lineHeight = chat_string_wrapped_get_height((void*)&lineCh, _chatWidth - 10);
_chatTop -= (lineHeight + 5);
@ -134,7 +134,7 @@ void chat_draw(rct_drawpixelinfo * dpi)
break;
}
safe_strcpy(lineBuffer, chat_history_get(i), CHAT_INPUT_SIZE + 10);
safe_strcpy(lineBuffer, chat_history_get(i), sizeof(lineBuffer));
stringHeight = chat_history_draw_string(dpi, (void*) &lineCh, x, y, _chatWidth - 10) + 5;
gfx_set_dirty_blocks(x, y - stringHeight, x + _chatWidth, y + 20);
@ -220,7 +220,7 @@ int chat_history_draw_string(rct_drawpixelinfo *dpi, void *args, int x, int y, i
gfx_draw_string(dpi, "", 255, dpi->x, dpi->y);
char *buffer = gCommonStringFormatBuffer;
format_string(buffer, STR_STRING, args);
format_string(buffer, 256, STR_STRING, args);
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
gfx_wrap_string(buffer, width, &numLines, &fontSpriteBase);
@ -251,7 +251,7 @@ int chat_string_wrapped_get_height(void *args, int width)
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
char *buffer = gCommonStringFormatBuffer;
format_string(buffer, STR_STRING, args);
format_string(buffer, 256, STR_STRING, args);
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
gfx_wrap_string(buffer, width, &numLines, &fontSpriteBase);

View File

@ -205,7 +205,7 @@ void console_draw(rct_drawpixelinfo *dpi)
size_t lineLength = min(sizeof(lineBuffer) - (size_t)utf8_get_codepoint_length(FORMAT_WHITE), (size_t)(nextLine - ch));
lineCh = lineBuffer;
lineCh = utf8_write_codepoint(lineCh, FORMAT_WHITE);
strncpy(lineCh, ch, lineLength);
memcpy(lineCh, ch, lineLength);
lineCh[lineLength] = 0;
gfx_draw_string(dpi, lineBuffer, 100, x, y); //Value 100 outlines the letters
@ -226,7 +226,7 @@ void console_draw(rct_drawpixelinfo *dpi)
// Draw current line
lineCh = lineBuffer;
lineCh = utf8_write_codepoint(lineCh, FORMAT_WHITE);
strcpy(lineCh, _consoleCurrentLine);
safe_strcpy(lineCh, _consoleCurrentLine, sizeof(lineBuffer) - (lineCh - lineBuffer));
gfx_draw_string(dpi, lineBuffer, 255, x, y);
// Draw caret
@ -301,8 +301,9 @@ void console_write(const utf8 *src)
if (charactersToWrite > charactersRemainingInBuffer) {
memmove(_consoleBuffer, _consoleBuffer + bufferShift, CONSOLE_BUFFER_SIZE - bufferShift);
_consoleBufferPointer -= bufferShift;
charactersRemainingInBuffer = CONSOLE_BUFFER_SIZE - (_consoleBufferPointer - _consoleBuffer) - 1;
}
strcpy(_consoleBufferPointer, src);
safe_strcpy(_consoleBufferPointer, src, charactersRemainingInBuffer);
_consoleBufferPointer += charactersToWrite;
console_update_scroll();
}
@ -315,14 +316,14 @@ void console_writeline(const utf8 *src)
void console_writeline_error(const utf8 *src)
{
strcpy(_consoleErrorBuffer + 1, src);
safe_strcpy(_consoleErrorBuffer + 1, src, CONSOLE_BUFFER_2_SIZE - 1);
_consoleErrorBuffer[0] = FORMAT_RED;
console_writeline(_consoleErrorBuffer);
}
void console_writeline_warning(const utf8 *src)
{
strcpy(_consoleErrorBuffer + 1, src);
safe_strcpy(_consoleErrorBuffer + 1, src, CONSOLE_BUFFER_2_SIZE - 1);
_consoleErrorBuffer[0] = FORMAT_YELLOW;
console_writeline(_consoleErrorBuffer);
}
@ -331,7 +332,7 @@ void console_printf(const utf8 *format, ...)
{
va_list list;
va_start(list, format);
vsprintf(_consolePrintfBuffer, format, list);
vsnprintf(_consolePrintfBuffer, sizeof(_consolePrintfBuffer), format, list);
va_end(list);
console_writeline(_consolePrintfBuffer);
}
@ -449,7 +450,7 @@ static int cc_rides(const utf8 **argv, int argc)
int i;
FOR_ALL_RIDES(i, ride) {
char name[128];
format_string(name, ride->name, &ride->name_arguments);
format_string(name, 128, ride->name, &ride->name_arguments);
console_printf("rides %03d type: %02u subtype %03u name %s", i, ride->type, ride->subtype, name);
}
} else if (strcmp(argv[0], "set") == 0) {
@ -515,7 +516,7 @@ static int cc_staff(const utf8 **argv, int argc)
int i;
FOR_ALL_STAFF(i, peep) {
char name[128];
format_string(name, peep->name_string_idx, &peep->id);
format_string(name, 128, peep->name_string_idx, &peep->id);
console_printf("staff id %03d type: %02u energy %03u name %s", i, peep->staff_type, peep->energy, name);
}
} else if (strcmp(argv[0], "set") == 0) {
@ -1178,7 +1179,7 @@ void console_execute_silent(const utf8 *src)
utf8 output[128];
utf8 *dst = output;
dst = utf8_write_codepoint(dst, FORMAT_TOPAZ);
strcpy(dst, "Unknown command. Type help to list available commands.");
safe_strcpy(dst, "Unknown command. Type help to list available commands.", sizeof(output) - (dst - output));
console_writeline(output);
}
}

View File

@ -26,6 +26,7 @@
#include "../platform/platform.h"
#include "../ride/track_paint.h"
#include "../title.h"
#include "../util/util.h"
#include "keyboard_shortcut.h"
#include "viewport.h"
#include "widget.h"
@ -92,33 +93,34 @@ void keyboard_shortcut_handle_command(int shortcutIndex)
}
}
void keyboard_shortcut_format_string(char *buffer, uint16 shortcutKey)
void keyboard_shortcut_format_string(char *buffer, size_t size, uint16 shortcutKey)
{
char formatBuffer[256];
if (size == 0) return;
*buffer = 0;
if (shortcutKey == SHORTCUT_UNDEFINED) return;
if (shortcutKey & 0x100) {
format_string(formatBuffer, STR_SHIFT_PLUS, NULL);
strcat(buffer, formatBuffer);
format_string(formatBuffer, 256, STR_SHIFT_PLUS, NULL);
safe_strcat(buffer, formatBuffer, size);
}
if (shortcutKey & 0x200) {
format_string(formatBuffer, STR_CTRL_PLUS, NULL);
strcat(buffer, formatBuffer);
format_string(formatBuffer, 256, STR_CTRL_PLUS, NULL);
safe_strcat(buffer, formatBuffer, size);
}
if (shortcutKey & 0x400) {
#ifdef __MACOSX__
format_string(formatBuffer, STR_OPTION_PLUS, NULL);
format_string(formatBuffer, 256, STR_OPTION_PLUS, NULL);
#else
format_string(formatBuffer, STR_ALT_PLUS, NULL);
format_string(formatBuffer, 256, STR_ALT_PLUS, NULL);
#endif
strcat(buffer, formatBuffer);
safe_strcat(buffer, formatBuffer, size);
}
if (shortcutKey & 0x800) {
format_string(formatBuffer, STR_CMD_PLUS, NULL);
strcat(buffer, formatBuffer);
format_string(formatBuffer, 256, STR_CMD_PLUS, NULL);
safe_strcat(buffer, formatBuffer, size);
}
strcat(buffer, SDL_GetScancodeName(shortcutKey & 0xFF));
safe_strcat(buffer, SDL_GetScancodeName(shortcutKey & 0xFF), size);
}
#pragma region Shortcut Commands

View File

@ -25,6 +25,6 @@ extern uint8 gKeyboardShortcutChangeId;
void keyboard_shortcut_set(int key);
void keyboard_shortcut_handle(int key);
void keyboard_shortcut_handle_command(int shortcutIndex);
void keyboard_shortcut_format_string(char *buffer, uint16 shortcutKey);
void keyboard_shortcut_format_string(char *buffer, size_t size, uint16 shortcutKey);
#endif

View File

@ -67,18 +67,18 @@ static void screenshot_get_rendered_palette(rct_palette* palette) {
}
}
static int screenshot_get_next_path(char *path)
static int screenshot_get_next_path(char *path, size_t size)
{
char screenshotPath[MAX_PATH];
platform_get_user_directory(screenshotPath, "screenshot");
platform_get_user_directory(screenshotPath, "screenshot", sizeof(screenshotPath));
if (!platform_ensure_directory_exists(screenshotPath)) {
log_error("Unable to save screenshots in OpenRCT2 screenshot directory.\n");
return -1;
}
char park_name[128] = { 0 };
format_string(park_name, gParkName, &gParkNameArgs);
char park_name[128];
format_string(park_name, 128, gParkName, &gParkNameArgs);
// retrieve current time
rct2_date currentDate;
@ -87,7 +87,7 @@ static int screenshot_get_next_path(char *path)
platform_get_time_local(&currentTime);
// Glue together path and filename
sprintf(path, "%s%s %d-%02d-%02d %02d-%02d-%02d.png", screenshotPath, park_name, currentDate.year, currentDate.month, currentDate.day, currentTime.hour, currentTime.minute, currentTime.second);
snprintf(path, size, "%s%s %d-%02d-%02d %02d-%02d-%02d.png", screenshotPath, park_name, currentDate.year, currentDate.month, currentDate.day, currentTime.hour, currentTime.minute, currentTime.second);
if (!platform_file_exists(path)) {
return 0; // path ok
@ -102,7 +102,7 @@ static int screenshot_get_next_path(char *path)
int i;
for (i = 1; i < 1000; i++) {
// Glue together path and filename
sprintf(path, "%s%s %d-%02d-%02d %02d-%02d-%02d (%d).png", screenshotPath, park_name, currentDate.year, currentDate.month, currentDate.day, currentTime.hour, currentTime.minute, currentTime.second, i);
snprintf(path, size, "%s%s %d-%02d-%02d %02d-%02d-%02d (%d).png", screenshotPath, park_name, currentDate.year, currentDate.month, currentDate.day, currentTime.hour, currentTime.minute, currentTime.second, i);
if (!platform_file_exists(path)) {
return i;
@ -118,7 +118,7 @@ int screenshot_dump_png(rct_drawpixelinfo *dpi)
// Get a free screenshot path
int index;
char path[MAX_PATH] = "";
if ((index = screenshot_get_next_path(path)) == -1) {
if ((index = screenshot_get_next_path(path, MAX_PATH)) == -1) {
return -1;
}
@ -137,7 +137,7 @@ int screenshot_dump_png_32bpp(sint32 width, sint32 height, const void *pixels)
// Get a free screenshot path
int index;
char path[MAX_PATH] = "";
if ((index = screenshot_get_next_path(path)) == -1) {
if ((index = screenshot_get_next_path(path, MAX_PATH)) == -1) {
return -1;
}
@ -222,7 +222,7 @@ void screenshot_giant()
// Get a free screenshot path
char path[MAX_PATH];
int index;
if ((index = screenshot_get_next_path(path)) == -1) {
if ((index = screenshot_get_next_path(path, MAX_PATH)) == -1) {
log_error("Giant screenshot failed, unable to find a suitable destination path.");
window_error_open(STR_SCREENSHOT_FAILED, STR_NONE);
return;
@ -236,9 +236,8 @@ void screenshot_giant()
free(dpi.bits);
// Show user that screenshot saved successfully
rct_string_id stringId = STR_PLACEHOLDER;
strcpy((char*)language_get_string(stringId), path_get_filename(path));
set_format_arg(0, rct_string_id, stringId);
set_format_arg(0, rct_string_id, STR_STRING);
set_format_arg(2, char *, path_get_filename(path));
window_error_open(STR_SCREENSHOT_SAVED_AS, STR_NONE);
}

View File

@ -42,10 +42,10 @@ bool title_sequence_name_exists(const char *name)
bool title_sequence_save_exists(int preset, const char *name)
{
utf8 newName[MAX_PATH];
char *extension = (char*)path_get_extension(name);
const char *extension = path_get_extension(name);
safe_strcpy(newName, name, MAX_PATH);
if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0)
strcat(newName, ".sv6");
path_append_extension(newName, ".sv6", MAX_PATH);
for (int i = 0; i < gConfigTitleSequences.presets[preset].num_saves; i++) {
if (_stricmp(gConfigTitleSequences.presets[preset].saves[i], newName) == 0)
return true;
@ -102,8 +102,8 @@ void title_sequence_create_preset(const char *name)
// Create the folder
utf8 path[MAX_PATH];
platform_get_user_directory(path, "title sequences");
strcat(path, gConfigTitleSequences.presets[preset].name);
platform_get_user_directory(path, "title sequences", sizeof(path));
safe_strcat_path(path, gConfigTitleSequences.presets[preset].name, MAX_PATH);
platform_file_delete(path);
platform_ensure_directory_exists(path);
@ -141,28 +141,25 @@ void title_sequence_duplicate_preset(int duplicate, const char *name)
// Create the folder
utf8 path[MAX_PATH], srcPath[MAX_PATH];
platform_get_user_directory(path, "title sequences");
strcat(path, gConfigTitleSequences.presets[preset].name);
platform_get_user_directory(path, "title sequences", sizeof(path));
safe_strcat_path(path, gConfigTitleSequences.presets[preset].name, MAX_PATH);
platform_file_delete(path);
platform_ensure_directory_exists(path);
// Copy the saves
char separator = platform_get_path_separator();
for (int i = 0; i < gConfigTitleSequences.presets[preset].num_saves; i++) {
if (gConfigTitleSequences.presets[duplicate].path[0]) {
safe_strcpy(srcPath, gConfigTitleSequences.presets[duplicate].path, MAX_PATH);
strcat(srcPath, gConfigTitleSequences.presets[duplicate].saves[i]);
safe_strcat_path(srcPath, gConfigTitleSequences.presets[duplicate].saves[i], MAX_PATH);
}
else {
platform_get_user_directory(srcPath, "title sequences");
strcat(srcPath, gConfigTitleSequences.presets[duplicate].name);
strncat(srcPath, &separator, 1);
strcat(srcPath, gConfigTitleSequences.presets[duplicate].saves[i]);
platform_get_user_directory(srcPath, "title sequences", sizeof(srcPath));
safe_strcat_path(srcPath, gConfigTitleSequences.presets[duplicate].name, MAX_PATH);
safe_strcat_path(srcPath, gConfigTitleSequences.presets[duplicate].saves[i], MAX_PATH);
}
platform_get_user_directory(path, "title sequences");
strcat(path, gConfigTitleSequences.presets[preset].name);
strncat(path, &separator, 1);
strcat(path, gConfigTitleSequences.presets[preset].saves[i]);
platform_get_user_directory(path, "title sequences", sizeof(path));
safe_strcat_path(path, gConfigTitleSequences.presets[preset].name, MAX_PATH);
safe_strcat_path(path, gConfigTitleSequences.presets[preset].saves[i], MAX_PATH);
platform_file_copy(srcPath, path, false);
}
@ -181,8 +178,8 @@ void title_sequence_delete_preset(int preset)
if (preset >= TITLE_SEQUENCE_DEFAULT_PRESETS && preset < gConfigTitleSequences.num_presets) {
// Delete the folder
utf8 path[MAX_PATH];
platform_get_user_directory(path, "title sequences");
strcat(path, gConfigTitleSequences.presets[preset].name);
platform_get_user_directory(path, "title sequences", sizeof(path));
safe_strcat_path(path, gConfigTitleSequences.presets[preset].name, MAX_PATH);
if (!platform_directory_delete(path)) {
log_error("Failed to delete directory: \"%s\"", path);
}
@ -209,10 +206,10 @@ void title_sequence_rename_preset(int preset, const char *newName)
if (preset >= TITLE_SEQUENCE_DEFAULT_PRESETS && preset < gConfigTitleSequences.num_presets && filename_valid_characters(newName) && !title_sequence_name_exists(newName)) {
// Rename the folder
utf8 src[MAX_PATH], dest[MAX_PATH];
platform_get_user_directory(src, "title sequences");
platform_get_user_directory(dest, "title sequences");
strcat(src, gConfigTitleSequences.presets[preset].name);
strcat(dest, newName);
platform_get_user_directory(src, "title sequences", sizeof(src));
platform_get_user_directory(dest, "title sequences", sizeof(dest));
safe_strcat_path(src, gConfigTitleSequences.presets[preset].name, sizeof(src));
safe_strcat_path(dest, newName, sizeof(dest));
platform_file_move(src, dest);
safe_strcpy(gConfigTitleSequences.presets[preset].name, newName, TITLE_SEQUENCE_NAME_SIZE);
@ -228,20 +225,18 @@ void title_sequence_rename_preset(int preset, const char *newName)
void title_sequence_add_save(int preset, const char *path, const char *newName)
{
utf8 newPath[MAX_PATH];
char *extension = (char*)path_get_extension(newName);
const char *extension = path_get_extension(newName);
safe_strcpy(newPath, newName, MAX_PATH);
if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0)
strcat(newPath, ".sv6");
path_append_extension(newPath, ".sv6", MAX_PATH);
if (preset >= TITLE_SEQUENCE_DEFAULT_PRESETS && preset < gConfigTitleSequences.num_presets && filename_valid_characters(newPath) && !title_sequence_save_exists(preset, newPath) && platform_file_exists(path)) {
// Copy the save file
char separator = platform_get_path_separator();
platform_get_user_directory(newPath, "title sequences");
strcat(newPath, gConfigTitleSequences.presets[preset].name);
strncat(newPath, &separator, 1);
strcat(newPath, newName);
platform_get_user_directory(newPath, "title sequences", sizeof(newPath));
safe_strcat_path(newPath, gConfigTitleSequences.presets[preset].name, sizeof(newPath));
safe_strcat_path(newPath, newName, sizeof(newPath));
// Add the appropriate extension if needed
if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0)
strcat(newPath, ".sv6");
path_append_extension(newPath, ".sv6", sizeof(newPath));
platform_file_copy(path, newPath, false);
gConfigTitleSequences.presets[preset].num_saves++;
@ -250,7 +245,7 @@ void title_sequence_add_save(int preset, const char *path, const char *newName)
safe_strcpy(gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1], newName, TITLE_SEQUENCE_MAX_SAVE_LENGTH);
// Add the appropriate extension if needed
if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0)
strcat(gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1], ".sv6");
path_append_extension(gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1], ".sv6", TITLE_SEQUENCE_MAX_SAVE_LENGTH);
}
}
@ -258,12 +253,10 @@ void title_sequence_remove_save(int preset, int index)
{
if (preset >= TITLE_SEQUENCE_DEFAULT_PRESETS && preset < gConfigTitleSequences.num_presets && index >= 0 && index < gConfigTitleSequences.presets[preset].num_saves) {
// Delete the save file
char separator = platform_get_path_separator();
utf8 path[MAX_PATH];
platform_get_user_directory(path, "title sequences");
strcat(path, gConfigTitleSequences.presets[preset].name);
strncat(path, &separator, 1);
strcat(path, gConfigTitleSequences.presets[preset].saves[index]);
platform_get_user_directory(path, "title sequences", sizeof(path));
safe_strcat_path(path, gConfigTitleSequences.presets[preset].name, sizeof(path));
safe_strcat_path(path, gConfigTitleSequences.presets[preset].saves[index], sizeof(path));
platform_file_delete(path);
// Remove all references to this save in the commands and decrement save indices
@ -291,26 +284,23 @@ void title_sequence_rename_save(int preset, int index, const char *newName)
filename_valid_characters(newName) && !title_sequence_save_exists(preset, newName)) {
// Rename the save file
char separator = platform_get_path_separator();
utf8 src[MAX_PATH], dest[MAX_PATH];
platform_get_user_directory(src, "title sequences");
platform_get_user_directory(dest, "title sequences");
strcat(src, gConfigTitleSequences.presets[preset].name);
strcat(dest, gConfigTitleSequences.presets[preset].name);
strncat(src, &separator, 1);
strncat(dest, &separator, 1);
strcat(src, gConfigTitleSequences.presets[preset].saves[index]);
strcat(dest, newName);
platform_get_user_directory(src, "title sequences", sizeof(src));
platform_get_user_directory(dest, "title sequences", sizeof(dest));
safe_strcat_path(src, gConfigTitleSequences.presets[preset].name, sizeof(src));
safe_strcat_path(dest, gConfigTitleSequences.presets[preset].name, sizeof(dest));
safe_strcat_path(src, gConfigTitleSequences.presets[preset].saves[index], sizeof(src));
safe_strcat_path(dest, newName, sizeof(dest));
// Add the appropriate extension if needed
char *extension = (char*)path_get_extension(newName);
const char *extension = path_get_extension(newName);
if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0)
strcat(dest, ".sv6");
path_append_extension(dest, ".sv6", sizeof(dest));
platform_file_move(src, dest);
safe_strcpy(gConfigTitleSequences.presets[preset].saves[index], newName, TITLE_SEQUENCE_MAX_SAVE_LENGTH);
// Add the appropriate extension if needed
if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0)
strcat(gConfigTitleSequences.presets[preset].saves[index], ".sv6");
path_append_extension(gConfigTitleSequences.presets[preset].saves[index], ".sv6", TITLE_SEQUENCE_MAX_SAVE_LENGTH);
title_sequence_save_preset_script(preset);
}
}

View File

@ -2470,7 +2470,7 @@ void window_start_textbox(rct_window *call_w, int call_widget, rct_string_id exi
// Enter in the the text input buffer any existing
// text.
if (existing_text != STR_NONE)
format_string(gTextBoxInput, existing_text, &existing_args);
format_string(gTextBoxInput, 512, existing_text, &existing_args);
// In order to prevent strings that exceed the maxLength
// from crashing the game.

View File

@ -15,6 +15,7 @@
#pragma endregion
#include "../config.h"
#include "../util/util.h"
#include "currency.h"
#include "string_ids.h"
@ -42,5 +43,5 @@ void currency_load_custom_currency_config()
{
CurrencyDescriptors[CURRENCY_CUSTOM].rate = gConfigGeneral.custom_currency_rate;
CurrencyDescriptors[CURRENCY_CUSTOM].affix_unicode = gConfigGeneral.custom_currency_affix;
strncpy(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

@ -148,7 +148,6 @@ const char *language_get_string(rct_string_id id)
bool language_open(int id)
{
static const char *languagePath = "%s/language/%s.txt";
char filename[MAX_PATH];
char dataPath[MAX_PATH];
@ -156,13 +155,19 @@ bool language_open(int id)
if (id == LANGUAGE_UNDEFINED)
return false;
platform_get_openrct_data_path(dataPath);
platform_get_openrct_data_path(dataPath, sizeof(dataPath));
if (id != LANGUAGE_ENGLISH_UK) {
sprintf(filename, languagePath, dataPath, LanguagesDescriptors[LANGUAGE_ENGLISH_UK].locale);
safe_strcpy(filename, dataPath, MAX_PATH);
safe_strcat_path(filename, "language", MAX_PATH);
safe_strcat_path(filename, LanguagesDescriptors[LANGUAGE_ENGLISH_UK].locale, MAX_PATH);
path_append_extension(filename, ".txt", MAX_PATH);
_languageFallback = LanguagePackFactory::FromFile(LANGUAGE_ENGLISH_UK, filename);
}
sprintf(filename, languagePath, dataPath, LanguagesDescriptors[id].locale);
safe_strcpy(filename, dataPath, MAX_PATH);
safe_strcat_path(filename, "language", MAX_PATH);
safe_strcat_path(filename, LanguagesDescriptors[id].locale, MAX_PATH);
path_append_extension(filename, ".txt", MAX_PATH);
_languageCurrent = LanguagePackFactory::FromFile(id, filename);
if (_languageCurrent != nullptr) {
gCurrentLanguage = id;

View File

@ -488,254 +488,391 @@ void utf8_remove_formatting(utf8* string, bool allowColours) {
#pragma endregion
void format_string_part_from_raw(char **dest, const char *src, char **args);
void format_string_part(char **dest, rct_string_id format, char **args);
#define 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); }
static void format_integer(char **dest, long long value)
#define format_push_wrap(C) { *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(char **dest, size_t *size, rct_string_id format, char **args);
static void format_append_string(char **dest, size_t *size, const utf8 *string) {
if ((*size) == 0) return;
size_t length = strlen(string);
if (length < (*size)) {
memcpy((*dest), string, length);
(*dest) += length;
} else {
memcpy((*dest), string, (*size) - 1);
(*dest) += (*size) - 1;
*(*dest)++ = '\0';
(*size) = 0;
}
}
static void format_append_string_n(char **dest, size_t *size, const utf8 *string, size_t maxlen) {
if ((*size) == 0) return;
size_t length = min(maxlen, strlen(string));
if (length < (*size)) {
memcpy((*dest), string, length);
(*dest) += length;
} else {
memcpy((*dest), string, (*size) - 1);
(*dest) += (*size) - 1;
*(*dest)++ = '\0';
(*size) = 0;
}
}
static void format_integer(char **dest, size_t *size, long long value)
{
int digit;
char *dst = *dest;
char *finish;
char *nbegin, *nend, *ncur;
char tmp;
if ((*size) == 0) return;
// Negative sign
if (value < 0) {
*dst++ = '-';
format_push_char('-');
value = -value;
}
*dest = dst;
if (value == 0) {
*dst++ = '0';
} else {
// Right to left
format_push_char('0');
return;
}
nbegin = (*dest);
// Right to left
while (value > 0 && (*size) > 1) {
digit = value % 10;
value /= 10;
format_push_char_safe('0' + digit);
}
if (value > 0) {
ncur = nbegin;
while (value > 0) {
digit = value % 10;
value /= 10;
*dst++ = '0' + digit;
format_push_wrap('0' + digit);
}
// Reverse first half of string
nend = ncur - 1;
reverse_string();
// Reverse second half of string
nbegin = ncur;
nend = (*dest) - 1;
reverse_string();
format_push_char_safe('\0'); // truncate overflowed string
} else {
// Reverse string
nend = (*dest) - 1;
reverse_string();
}
finish = dst;
// Reverse string
dst--;
while (*dest < dst) {
tmp = **dest;
**dest = *dst;
*dst = tmp;
(*dest)++;
dst--;
}
*dest = finish;
}
static void format_comma_separated_integer(char **dest, long long value)
static void format_comma_separated_integer(char **dest, size_t *size, long long value)
{
int digit, groupIndex;
char *dst = *dest;
char *finish;
char *nbegin, *nend, *ncur;
char tmp;
const char *commaMark = language_get_string(STR_LOCALE_THOUSANDS_SEPARATOR);
const char *ch;
const char *ch = NULL;
if ((*size) == 0) return;
// Negative sign
if (value < 0) {
*dst++ = '-';
format_push_char('-');
value = -value;
}
*dest = dst;
if (value == 0) {
*dst++ = '0';
} else {
// Groups of three digits, right to left
groupIndex = 0;
format_push_char('0');
return;
}
nbegin = *dest;
// Groups of three digits, right to left
groupIndex = 0;
while (value > 0 && (*size) > 1) {
// Append group separator
if (groupIndex == 3) {
groupIndex = 0;
ch = commaMark;
}
if (ch != NULL ) {
format_push_char_safe(*ch++);
if (*ch == '\0') ch = NULL;
} else {
digit = value % 10;
value /= 10;
format_push_char_safe('0' + digit);
groupIndex++;
}
}
if (value > 0) {
ncur = nbegin;
while (value > 0) {
// Append group separator
if (groupIndex == 3) {
groupIndex = 0;
ch = commaMark;
while (*ch != 0) {
*dst++ = *ch++;
}
}
digit = value % 10;
value /= 10;
*dst++ = '0' + digit;
groupIndex++;
if (ch != NULL ) {
format_push_wrap(*ch++);
if (*ch == '\0') ch = NULL;
} else {
digit = value % 10;
value /= 10;
format_push_wrap('0' + digit);
groupIndex++;
}
}
// Reverse first half of string
nend = ncur - 1;
reverse_string();
// Reverse second half of string
nbegin = ncur;
nend = (*dest) - 1;
reverse_string();
format_push_char_safe('\0'); // truncate overflowed string
} else {
// Reverse string
nend = *dest - 1;
reverse_string();
}
finish = dst;
// Reverse string
dst--;
while (*dest < dst) {
tmp = **dest;
**dest = *dst;
*dst = tmp;
(*dest)++;
dst--;
}
*dest = finish;
}
static void format_comma_separated_fixed_1dp(char **dest, long long value)
static void format_comma_separated_fixed_1dp(char **dest, size_t *size, long long value)
{
int digit, groupIndex;
char *dst = *dest;
char *finish;
char *nbegin, *nend, *ncur;
char tmp;
const char *commaMark = language_get_string(STR_LOCALE_THOUSANDS_SEPARATOR);
const char *decimalMark = language_get_string(STR_LOCALE_DECIMAL_POINT);
const char *ch;
int zeroNeeded = 1;
if ((*size) == 0) return;
// Negative sign
if (value < 0) {
*dst++ = '-';
format_push_char('-');
value = -value;
}
nbegin = (*dest);
*dest = dst;
// One decimal place
digit = value % 10;
value /= 10;
*dst++ = '0' + digit;
ch = decimalMark;
while (*ch != 0) {
*dst++ = *ch++;
// In the case of buffers this small,
// all of this would be truncated anyways.
format_handle_overflow(1);
if ((*size) > 2) {
// One decimal place
digit = value % 10;
format_push_char_safe('0' + digit);
ch = decimalMark;
}
value /= 10;
if (value == 0) {
*dst++ = '0';
} else {
// Groups of three digits, right to left
groupIndex = 0;
while (value > 0) {
// Append group separator
if (groupIndex == 3) {
groupIndex = 0;
ch = commaMark;
while (*ch != 0) {
*dst++ = *ch++;
}
}
groupIndex = 0;
while ((zeroNeeded || value > 0) && (*size) > 1) {
// Append group separator
if (groupIndex == 3) {
groupIndex = 0;
ch = commaMark;
}
if (ch != NULL ) {
format_push_char_safe(*ch++);
if (*ch == '\0') ch = NULL;
} else {
zeroNeeded = 0;
digit = value % 10;
value /= 10;
*dst++ = '0' + digit;
format_push_char_safe('0' + digit);
groupIndex++;
}
}
finish = dst;
// Reverse string
dst--;
while (*dest < dst) {
tmp = **dest;
**dest = *dst;
*dst = tmp;
(*dest)++;
dst--;
if (zeroNeeded || value > 0) {
ncur = nbegin;
while (zeroNeeded || value > 0) {
// Append group separator
if (groupIndex == 3) {
groupIndex = 0;
ch = commaMark;
}
if (ch != NULL ) {
format_push_wrap(*ch++);
if (*ch == '\0') ch = NULL;
} else {
zeroNeeded = 0;
digit = value % 10;
value /= 10;
format_push_wrap('0' + digit);
groupIndex++;
}
}
// Reverse first half of string
nend = ncur - 1;
reverse_string();
// Reverse second half of string
nbegin = ncur;
nend = (*dest) - 1;
reverse_string();
format_push_char_safe('\0'); // truncate overflowed string
} else {
// Reverse string
nend = *dest - 1;
reverse_string();
}
*dest = finish;
}
static void format_comma_separated_fixed_2dp(char **dest, long long value)
static void format_comma_separated_fixed_2dp(char **dest, size_t *size, long long value)
{
int digit, groupIndex;
char *dst = *dest;
char *finish;
char *nbegin, *nend, *ncur;
char tmp;
const char *commaMark = language_get_string(STR_LOCALE_THOUSANDS_SEPARATOR);
const char *decimalMark = language_get_string(STR_LOCALE_DECIMAL_POINT);
const char *ch;
const char *ch = NULL;
int zeroNeeded = 1;
if ((*size) == 0) return;
// Negative sign
if (value < 0) {
*dst++ = '-';
format_push_char('-');
value = -value;
}
*dest = dst;
nbegin = (*dest);
// Two decimal places
digit = value % 10;
value /= 10;
*dst++ = '0' + digit;
digit = value % 10;
value /= 10;
*dst++ = '0' + digit;
ch = decimalMark;
while (*ch != 0) {
*dst++ = *ch++;
// In the case of buffers this small,
// all of this would be truncated anyways.
format_handle_overflow(1);
if ((*size) < 3) {
value /= 100;
} else {
// Two decimal places
digit = value % 10;
value /= 10;
format_push_char_safe('0' + digit);
digit = value % 10;
value /= 10;
format_push_char_safe('0' + digit);
ch = decimalMark;
}
if (value == 0) {
*dst++ = '0';
} else {
// Groups of three digits, right to left
groupIndex = 0;
while (value > 0) {
// Append group separator
if (groupIndex == 3) {
groupIndex = 0;
ch = commaMark;
while (*ch != 0) {
*dst++ = *ch++;
}
}
groupIndex = 0;
while ((zeroNeeded || value > 0) && (*size) > 1) {
// Append group separator
if (groupIndex == 3) {
groupIndex = 0;
ch = commaMark;
}
if (ch != NULL ) {
format_push_char_safe(*ch++);
if (*ch == '\0') ch = NULL;
} else {
zeroNeeded = 0;
digit = value % 10;
value /= 10;
*dst++ = '0' + digit;
format_push_char_safe('0' + digit);
groupIndex++;
}
}
finish = dst;
// Reverse string
dst--;
while (*dest < dst) {
tmp = **dest;
**dest = *dst;
*dst = tmp;
(*dest)++;
dst--;
if (zeroNeeded || value > 0) {
ncur = nbegin;
while (zeroNeeded || value > 0) {
// Append group separator
if (groupIndex == 3) {
groupIndex = 0;
ch = commaMark;
}
if (ch != NULL ) {
format_push_wrap(*ch++);
if (*ch == '\0') ch = NULL;
} else {
zeroNeeded = 0;
digit = value % 10;
value /= 10;
format_push_wrap('0' + digit);
groupIndex++;
}
}
// Reverse first half of string
nend = ncur - 1;
reverse_string();
// Reverse second half of string
nbegin = ncur;
nend = (*dest) - 1;
reverse_string();
format_push_char_safe('\0'); // truncate overflowed string
} else {
// Reverse string
nend = *dest - 1;
reverse_string();
}
*dest = finish;
}
static void format_currency(char **dest, long long value)
static void format_currency(char **dest, size_t *size, long long value)
{
if ((*size) == 0) return;
const currency_descriptor *currencyDesc = &CurrencyDescriptors[gConfigGeneral.currency_format];
int rate = currencyDesc->rate;
value *= rate;
value *= currencyDesc->rate;
// Negative sign
if (value < 0) {
// Round the value away from zero
value = (value - 99) / 100;
*(*dest)++ = '-';
format_push_char('-');
value = -value;
}
else{
//Round the value away from zero
value = (value + 99) / 100;
}
//Round the value away from zero
value = (value + 99) / 100;
// Currency symbol
const utf8 *symbol = currencyDesc->symbol_unicode;
@ -746,22 +883,22 @@ static void format_currency(char **dest, long long value)
}
// Prefix
if (affix == CURRENCY_PREFIX) {
safe_strcpy(*dest, symbol, CURRENCY_SYMBOL_MAX_SIZE);
*dest += strlen(*dest);
}
if (affix == CURRENCY_PREFIX)
format_append_string(dest, size, symbol);
if ((*size) == 0) return;
format_comma_separated_integer(dest, value);
format_comma_separated_integer(dest, size, value);
if ((*size) == 0) return;
// Currency symbol suffix
if (affix == CURRENCY_SUFFIX) {
safe_strcpy(*dest, symbol, CURRENCY_SYMBOL_MAX_SIZE);
*dest += strlen(*dest);
}
if (affix == CURRENCY_SUFFIX)
format_append_string(dest, size, symbol);
}
static void format_currency_2dp(char **dest, long long value)
static void format_currency_2dp(char **dest, size_t *size, long long value)
{
if ((*size) == 0) return;
const currency_descriptor *currencyDesc = &CurrencyDescriptors[gConfigGeneral.currency_format];
int rate = currencyDesc->rate;
@ -769,7 +906,7 @@ static void format_currency_2dp(char **dest, long long value)
// Negative sign
if (value < 0) {
*(*dest)++ = '-';
format_push_char('-');
value = -value;
}
@ -782,34 +919,31 @@ static void format_currency_2dp(char **dest, long long value)
}
// Prefix
if (affix == CURRENCY_PREFIX) {
safe_strcpy(*dest, symbol, CURRENCY_SYMBOL_MAX_SIZE);
*dest += strlen(*dest);
}
if (affix == CURRENCY_PREFIX)
format_append_string(dest, size, symbol);
if ((*size) == 0) return;
// Drop the pennies for "large" currencies
if (rate >= 100) {
format_comma_separated_integer(dest, value / 100);
format_comma_separated_integer(dest, size, value / 100);
} else {
format_comma_separated_fixed_2dp(dest, value);
format_comma_separated_fixed_2dp(dest, size, value);
}
if ((*size) == 0) return;
// Currency symbol suffix
if (affix == CURRENCY_SUFFIX) {
safe_strcpy(*dest, symbol, CURRENCY_SYMBOL_MAX_SIZE);
*dest += strlen(*dest);
}
if (affix == CURRENCY_SUFFIX)
format_append_string(dest, size, symbol);
}
static void format_date(char **dest, uint16 value)
static void format_date(char **dest, size_t *size, uint16 value)
{
uint16 args[] = { date_get_month(value), date_get_year(value) + 1 };
uint16 *argsRef = args;
format_string_part(dest, STR_DATE_FORMAT_MY, (char**)&argsRef);
(*dest)--;
format_string_part(dest, size, STR_DATE_FORMAT_MY, (char**)&argsRef);
}
static void format_length(char **dest, sint16 value)
static void format_length(char **dest, size_t *size, sint16 value)
{
rct_string_id stringId = STR_UNIT_SUFFIX_METRES;
@ -819,11 +953,10 @@ static void format_length(char **dest, sint16 value)
}
sint16 *argRef = &value;
format_string_part(dest, stringId, (char**)&argRef);
(*dest)--;
format_string_part(dest, size, stringId, (char**)&argRef);
}
static void format_velocity(char **dest, uint16 value)
static void format_velocity(char **dest, size_t *size, uint16 value)
{
rct_string_id stringId;
@ -842,8 +975,7 @@ static void format_velocity(char **dest, uint16 value)
}
uint16 *argRef = &value;
format_string_part(dest, stringId, (char**)&argRef);
(*dest)--;
format_string_part(dest, size, stringId, (char**)&argRef);
}
static const rct_string_id DurationFormats[][2] = {
@ -852,7 +984,7 @@ static const rct_string_id DurationFormats[][2] = {
{STR_DURATION_MINS_SEC, STR_DURATION_MINS_SECS},
};
static void format_duration(char **dest, uint16 value)
static void format_duration(char **dest, size_t *size, uint16 value)
{
uint16 minutes = value / 60;
uint16 seconds = value % 60;
@ -876,8 +1008,7 @@ static void format_duration(char **dest, uint16 value)
rct_string_id stringId = DurationFormats[minuteIndex][secondsIndex];
format_string_part(dest, stringId, (char**)&argsRef);
(*dest)--;
format_string_part(dest, size, stringId, (char**)&argsRef);
}
static const rct_string_id RealtimeFormats[][2] = {
@ -886,7 +1017,7 @@ static const rct_string_id RealtimeFormats[][2] = {
{STR_REALTIME_HOURS_MIN, STR_REALTIME_HOURS_MINS},
};
static void format_realtime(char ** dest, uint16 value)
static void format_realtime(char **dest, size_t *size, uint16 value)
{
uint16 hours = value / 60;
uint16 minutes = value % 60;
@ -910,13 +1041,14 @@ static void format_realtime(char ** dest, uint16 value)
rct_string_id stringId = RealtimeFormats[hourIndex][minuteIndex];
format_string_part(dest, stringId, (char**)&argsRef);
(*dest)--;
format_string_part(dest, size, stringId, (char**)&argsRef);
}
static void format_string_code(unsigned int format_code, char **dest, char **args)
static void format_string_code(unsigned int format_code, char **dest, size_t *size, char **args)
{
intptr_t value;
if ((*size) == 0) return;
switch (format_code) {
case FORMAT_COMMA32:
@ -924,56 +1056,56 @@ static void format_string_code(unsigned int format_code, char **dest, char **arg
value = *((sint32*)*args);
*args += 4;
format_comma_separated_integer(dest, value);
format_comma_separated_integer(dest, size, value);
break;
case FORMAT_INT32:
// Pop argument
value = *((sint32*)*args);
*args += 4;
format_integer(dest, value);
format_integer(dest, size, value);
break;
case FORMAT_COMMA2DP32:
// Pop argument
value = *((sint32*)*args);
*args += 4;
format_comma_separated_fixed_2dp(dest, value);
format_comma_separated_fixed_2dp(dest, size, value);
break;
case FORMAT_COMMA1DP16:
case FORMAT_COMMA1DP16:
// Pop argument
value = *((sint16*)*args);
*args += 2;
format_comma_separated_fixed_1dp(dest, value);
format_comma_separated_fixed_1dp(dest, size, value);
break;
case FORMAT_COMMA16:
// Pop argument
value = *((sint16*)*args);
*args += 2;
format_comma_separated_integer(dest, value);
format_comma_separated_integer(dest, size, value);
break;
case FORMAT_UINT16:
// Pop argument
value = *((uint16*)*args);
*args += 2;
format_integer(dest, value);
format_integer(dest, size, value);
break;
case FORMAT_CURRENCY2DP:
// Pop argument
value = *((sint32*)*args);
*args += 4;
format_currency_2dp(dest, value);
format_currency_2dp(dest, size, value);
break;
case FORMAT_CURRENCY:
// Pop argument
value = *((sint32*)*args);
*args += 4;
format_currency(dest, value);
format_currency(dest, size, value);
break;
case FORMAT_STRINGID:
case FORMAT_STRINGID2:
@ -981,40 +1113,36 @@ static void format_string_code(unsigned int format_code, char **dest, char **arg
value = *((uint16*)*args);
*args += 2;
format_string_part(dest, (rct_string_id)value, args);
(*dest)--;
format_string_part(dest, size, (rct_string_id)value, args);
break;
case FORMAT_STRING:
// Pop argument
value = *((uintptr_t*)*args);
*args += sizeof(uintptr_t);
if (value != 0) {
strcpy(*dest, (char*)value);
*dest += strlen(*dest);
}
if (value != 0)
format_append_string(dest, size, (char*)value);
break;
case FORMAT_MONTHYEAR:
// Pop argument
value = *((uint16*)*args);
*args += 2;
format_date(dest, (uint16)value);
format_date(dest, size, (uint16)value);
break;
case FORMAT_MONTH:
// Pop argument
value = *((uint16*)*args);
*args += 2;
strcpy(*dest, language_get_string(DateGameMonthNames[date_get_month((int)value)]));
*dest += strlen(*dest);
format_append_string(dest, size, language_get_string(DateGameMonthNames[date_get_month((int)value)]));
break;
case FORMAT_VELOCITY:
// Pop argument
value = *((sint16*)*args);
*args += 2;
format_velocity(dest, (uint16)value);
format_velocity(dest, size, (uint16)value);
break;
case FORMAT_POP16:
*args += 2;
@ -1027,76 +1155,84 @@ static void format_string_code(unsigned int format_code, char **dest, char **arg
value = *((uint16*)*args);
*args += 2;
format_duration(dest, (uint16)value);
format_duration(dest, size, (uint16)value);
break;
case FORMAT_REALTIME:
// Pop argument
value = *((uint16*)*args);
*args += 2;
format_realtime(dest, (uint16)value);
format_realtime(dest, size, (uint16)value);
break;
case FORMAT_LENGTH:
// Pop argument
value = *((sint16*)*args);
*args += 2;
format_length(dest, (sint16)value);
format_length(dest, size, (sint16)value);
break;
case FORMAT_SPRITE:
// Pop argument
value = *((uint32*)*args);
*args += 4;
*(*dest)++ = 23;
format_handle_overflow(1 + sizeof(intptr_t));
format_push_char_safe('\x17');
*((intptr_t*)(*dest)) = value;
*dest += 4;
(*dest) += sizeof(intptr_t);
(*size) -= sizeof(intptr_t);
break;
}
}
void format_string_part_from_raw(utf8 **dest, const utf8 *src, char **args)
static void format_string_part_from_raw(utf8 **dest, size_t *size, const utf8 *src, char **args)
{
unsigned int code;
while (1) {
while (*size > 1) {
code = utf8_get_next(src, &src);
if (code < ' ') {
if (code == 0) {
*(*dest)++ = code;
break;
} else if (code <= 4) {
*(*dest)++ = code;
*(*dest)++ = *src++;
format_handle_overflow(2);
format_push_char_safe(code);
format_push_char_safe(*src++);
} else if (code <= 16) {
*(*dest)++ = code;
format_handle_overflow(1);
format_push_char_safe(code);
} else if (code <= 22) {
*(*dest)++ = code;
*(*dest)++ = *src++;
*(*dest)++ = *src++;
format_handle_overflow(3);
format_push_char_safe(code);
format_push_char_safe(*src++);
format_push_char_safe(*src++);
} else {
*(*dest)++ = code;
*(*dest)++ = *src++;
*(*dest)++ = *src++;
*(*dest)++ = *src++;
*(*dest)++ = *src++;
format_handle_overflow(5);
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 if (code <= 'z') {
*(*dest)++ = code;
format_push_char(code);
} else if (code < FORMAT_COLOUR_CODE_START || code == FORMAT_COMMA1DP16) {
format_string_code(code, dest, args);
format_string_code(code, dest, size, args);
} else {
format_handle_overflow((size_t) utf8_get_codepoint_length(code));
*dest = utf8_write_codepoint(*dest, code);
}
}
*(*dest) = '\0';
}
void format_string_part(utf8 **dest, 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) {
**dest = 0;
*(*dest) = '\0';
} else if (format < 0x8000) {
// Language string
format_string_part_from_raw(dest, language_get_string(format), args);
format_string_part_from_raw(dest, size, language_get_string(format), args);
} else if (format < 0x9000) {
// Custom string
format -= 0x8000;
@ -1105,16 +1241,18 @@ void format_string_part(utf8 **dest, rct_string_id format, char **args)
*args += (format & 0xC00) >> 9;
format &= ~0xC00;
safe_strcpy(*dest, &gUserStrings[format * 32], 32);
*dest = strchr(*dest, 0) + 1;
format_append_string_n(dest, size, &gUserStrings[format * 32], 32);
if ((*size) > 0) *(*dest) = '\0';
} else if (format < 0xE000) {
// Real name
format -= -0xA000;
sprintf(*dest, "%s %c.",
real_names[format % countof(real_names)],
real_name_initials[(format >> 10) % countof(real_name_initials)]
);
*dest = strchr(*dest, 0) + 1;
format_append_string(dest, size, real_names[format % countof(real_names)]);
if ((*size) == 0) return;
format_push_char(' ');
format_push_char(real_name_initials[(format >> 10) % countof(real_name_initials)]);
format_push_char('.');
*(*dest) = '\0';
*args += 4;
} else {
@ -1131,14 +1269,22 @@ void format_string_part(utf8 **dest, rct_string_id format, char **args)
* format (ax)
* args (ecx)
*/
void format_string(utf8 *dest, rct_string_id format, void *args)
void format_string(utf8 *dest, size_t size, rct_string_id format, void *args)
{
format_string_part(&dest, format, (char**)&args);
utf8 *end = dest;
size_t left = size;
format_string_part(&end, &left, format, (char**)&args);
if (left == 0)
log_warning("Truncating formatted string \"%s\" to %d bytes.", dest, size);
}
void format_string_raw(utf8 *dest, utf8 *src, void *args)
void format_string_raw(utf8 *dest, size_t size, utf8 *src, void *args)
{
format_string_part_from_raw(&dest, src, (char**)&args);
utf8 *end = dest;
size_t left = size;
format_string_part_from_raw(&end, &left, src, (char**)&args);
if (left == 0)
log_warning("Truncating formatted string \"%s\" to %d bytes.", dest, size);
}
/**
@ -1148,12 +1294,16 @@ void format_string_raw(utf8 *dest, utf8 *src, void *args)
* format (ax)
* args (ecx)
*/
void format_string_to_upper(utf8 *dest, rct_string_id format, void *args)
void format_string_to_upper(utf8 *dest, size_t size, rct_string_id format, void *args)
{
format_string(dest, format, args);
utf8 *end;
size_t left;
format_string_part(&end, &left, format, args);
if (left == 0)
log_warning("Truncating formatted string \"%s\" to %d bytes.", dest, size);
char *ch = dest;
while (*ch != 0) {
while (ch < end) {
*ch = toupper(*ch);
ch++;
}

View File

@ -31,9 +31,9 @@ int font_sprite_get_codepoint_offset(int codepoint);
int utf8_get_format_code_arg_length(int codepoint);
void utf8_remove_formatting(utf8* string, bool allowColours);
void format_string(char *dest, rct_string_id format, void *args);
void format_string_raw(char *dest, char *src, void *args);
void format_string_to_upper(char *dest, rct_string_id format, void *args);
void format_string(char *dest, size_t size, rct_string_id format, void *args);
void format_string_raw(char *dest, size_t size, char *src, void *args);
void format_string_to_upper(char *dest, size_t size, rct_string_id format, void *args);
void generate_string_file();
utf8 *get_string_end(const utf8 *text);
size_t get_string_size(const utf8 *text);

View File

@ -2563,7 +2563,7 @@ enum {
STR_ERR_REASON_NOT_ENOUGH_MEMORY = 3162,
// STR_3163 :Installing new data:
STR_OBJECT_SELECTION_SELECTION_SIZE = 3164,
STR_PLACEHOLDER = 3165,
// STR_PLACEHOLDER = 3165, <placeholder strings are unsafe>
// STR_3166 :{BLACK}(ID:
// STR_3167 :{WINDOW_COLOUR_2}Includes: {BLACK}{COMMA16} objects
STR_OBJECT_SELECTION_DESCRIPTION_SCENARIO_TEXT = 3168,

View File

@ -20,6 +20,7 @@
#include "../localisation/localisation.h"
#include "../peep/peep.h"
#include "../ride/ride.h"
#include "../util/util.h"
#include "../world/park.h"
#include "../world/sprite.h"
#include "finance.h"
@ -202,7 +203,7 @@ void finance_init() {
gScenarioCompletedCompanyValue = MONEY32_UNDEFINED;
gTotalAdmissions = 0;
gTotalIncomeFromAdmissions = 0;
strcpy(gScenarioCompletedBy, "?");
safe_strcpy(gScenarioCompletedBy, "?", sizeof(gScenarioCompletedBy));
}
/**

View File

@ -282,7 +282,7 @@ void news_item_add_to_queue(uint8 type, rct_string_id string_id, uint32 assoc)
utf8 buffer[256];
void *args = gCommonFormatArgs;
format_string(buffer, string_id, args); // overflows possible?
format_string(buffer, 256, string_id, args); // overflows possible?
news_item_add_to_queue_raw(type, buffer, assoc);
}

View File

@ -191,7 +191,7 @@ void NetworkConnection::SetLastDisconnectReason(const utf8 * src)
void NetworkConnection::SetLastDisconnectReason(const rct_string_id string_id, void *args)
{
char buffer[NETWORK_DISCONNECT_REASON_BUFFER_SIZE];
format_string(buffer, string_id, args);
format_string(buffer, NETWORK_DISCONNECT_REASON_BUFFER_SIZE, string_id, args);
SetLastDisconnectReason(buffer);
}

View File

@ -337,7 +337,7 @@ std::string NetworkKey::PublicKeyHash()
for (unsigned int i = 0; i < digest_size; i++)
{
char buf[3];
sprintf(buf, "%02x", digest[i]);
snprintf(buf, 3, "%02x", digest[i]);
digest_out.append(buf);
}
return digest_out;

View File

@ -248,7 +248,7 @@ NetworkUser * NetworkUserManager::GetOrAddUser(const std::string &hash)
void NetworkUserManager::GetStorePath(utf8 * buffer, size_t bufferSize)
{
platform_get_user_directory(buffer, nullptr);
platform_get_user_directory(buffer, nullptr, bufferSize);
Path::Append(buffer, bufferSize, USER_STORE_FILENAME);
}

View File

@ -62,7 +62,7 @@ void http_init()
#ifdef __WINDOWS__
// Find SSL certificate bundle
platform_get_exe_path(_caBundlePath);
platform_get_exe_path(_caBundlePath, sizeof(_caBundlePath));
Path::Append(_caBundlePath, sizeof(_caBundlePath), DEFAULT_CA_BUNDLE_PATH);
if (!platform_file_exists(_caBundlePath)) {
String::Set(_caBundlePath, sizeof(_caBundlePath), DEFAULT_CA_BUNDLE_PATH);

View File

@ -405,7 +405,7 @@ void Network::UpdateClient()
{
_lastConnectStatus = SOCKET_STATUS_RESOLVING;
char str_resolving[256];
format_string(str_resolving, STR_MULTIPLAYER_RESOLVING, NULL);
format_string(str_resolving, 256, STR_MULTIPLAYER_RESOLVING, NULL);
window_network_status_open(str_resolving, []() -> void {
gNetwork.Close();
});
@ -418,7 +418,7 @@ void Network::UpdateClient()
{
_lastConnectStatus = SOCKET_STATUS_CONNECTING;
char str_connecting[256];
format_string(str_connecting, STR_MULTIPLAYER_CONNECTING, NULL);
format_string(str_connecting, 256, STR_MULTIPLAYER_CONNECTING, NULL);
window_network_status_open(str_connecting, []() -> void {
gNetwork.Close();
});
@ -432,7 +432,7 @@ void Network::UpdateClient()
server_connection.ResetLastPacketTime();
Client_Send_TOKEN();
char str_authenticating[256];
format_string(str_authenticating, STR_MULTIPLAYER_AUTHENTICATING, NULL);
format_string(str_authenticating, 256, STR_MULTIPLAYER_AUTHENTICATING, NULL);
window_network_status_open(str_authenticating, []() -> void {
gNetwork.Close();
});
@ -464,9 +464,9 @@ void Network::UpdateClient()
if (server_connection.GetLastDisconnectReason()) {
const char * disconnect_reason = server_connection.GetLastDisconnectReason();
format_string(str_disconnected, STR_MULTIPLAYER_DISCONNECTED_WITH_REASON, &disconnect_reason);
format_string(str_disconnected, 256, STR_MULTIPLAYER_DISCONNECTED_WITH_REASON, &disconnect_reason);
} else {
format_string(str_disconnected, STR_MULTIPLAYER_DISCONNECTED_NO_REASON, NULL);
format_string(str_disconnected, 256, STR_MULTIPLAYER_DISCONNECTED_NO_REASON, NULL);
}
window_network_status_open(str_disconnected, NULL);
@ -479,7 +479,7 @@ void Network::UpdateClient()
if (!_desynchronised && !CheckSRAND(gCurrentTicks, gScenarioSrand0)) {
_desynchronised = true;
char str_desync[256];
format_string(str_desync, STR_MULTIPLAYER_DESYNC, NULL);
format_string(str_desync, 256, STR_MULTIPLAYER_DESYNC, NULL);
window_network_status_open(str_desync, NULL);
if (!gConfigNetwork.stay_connected) {
Close();
@ -534,8 +534,8 @@ const char* Network::FormatChat(NetworkPlayer* fromplayer, const char* text)
if (fromplayer) {
lineCh = utf8_write_codepoint(lineCh, FORMAT_OUTLINE);
lineCh = utf8_write_codepoint(lineCh, FORMAT_BABYBLUE);
safe_strcpy(lineCh, (const char*)fromplayer->name.c_str(), fromplayer->name.size() + 1);
strcat(lineCh, ": ");
safe_strcpy(lineCh, (const char *) fromplayer->name.c_str(), sizeof(formatted) - (lineCh - formatted));
safe_strcat(lineCh, ": ", sizeof(formatted) - (lineCh - formatted));
lineCh = strchr(lineCh, '\0');
}
lineCh = utf8_write_codepoint(lineCh, FORMAT_OUTLINE);
@ -582,7 +582,7 @@ void Network::KickPlayer(int playerId)
// Disconnect the client gracefully
(*it)->SetLastDisconnectReason(STR_MULTIPLAYER_KICKED);
char str_disconnect_msg[256];
format_string(str_disconnect_msg, STR_MULTIPLAYER_KICKED_REASON, NULL);
format_string(str_disconnect_msg, 256, STR_MULTIPLAYER_KICKED_REASON, NULL);
Server_Send_SETDISCONNECTMSG(*(*it), str_disconnect_msg);
(*it)->Socket->Disconnect();
break;
@ -695,8 +695,8 @@ void Network::SaveGroups()
if (GetMode() == NETWORK_MODE_SERVER) {
utf8 path[MAX_PATH];
platform_get_user_directory(path, NULL);
strcat(path, "groups.json");
platform_get_user_directory(path, NULL, sizeof(path));
safe_strcat_path(path, "groups.json", sizeof(path));
json_t * jsonGroupsCfg = json_object();
json_t * jsonGroups = json_array();
@ -748,8 +748,8 @@ void Network::LoadGroups()
utf8 path[MAX_PATH];
platform_get_user_directory(path, NULL);
strcat(path, "groups.json");
platform_get_user_directory(path, NULL, sizeof(path));
safe_strcat_path(path, "groups.json", sizeof(path));
json_t * json = nullptr;
if (platform_file_exists(path)) {
@ -790,7 +790,7 @@ void Network::BeginChatLog()
strftime(filename, sizeof(filename), "%Y%m%d-%H%M%S.txt", tmInfo);
utf8 path[MAX_PATH];
platform_get_user_directory(path, "chatlogs");
platform_get_user_directory(path, "chatlogs", sizeof(path));
Path::Append(path, sizeof(path), filename);
_chatLogPath = std::string(path);
@ -819,7 +819,7 @@ void Network::AppendChatLog(const utf8 *text)
String::Append(buffer, sizeof(buffer), text);
utf8_remove_formatting(buffer, false);
String::Append(buffer, sizeof(buffer), platform_get_new_line());
String::Append(buffer, sizeof(buffer), PLATFORM_NEWLINE);
SDL_RWwrite(_chatLogStream, buffer, strlen(buffer), 1);
SDL_RWclose(_chatLogStream);
@ -1216,9 +1216,9 @@ void Network::RemoveClient(std::unique_ptr<NetworkConnection>& connection)
connection->GetLastDisconnectReason()
};
if (has_disconnected_args[1]) {
format_string(text, STR_MULTIPLAYER_PLAYER_HAS_DISCONNECTED_WITH_REASON, has_disconnected_args);
format_string(text, 256, STR_MULTIPLAYER_PLAYER_HAS_DISCONNECTED_WITH_REASON, has_disconnected_args);
} else {
format_string(text, STR_MULTIPLAYER_PLAYER_HAS_DISCONNECTED_NO_REASON, &(has_disconnected_args[0]));
format_string(text, 256, STR_MULTIPLAYER_PLAYER_HAS_DISCONNECTED_NO_REASON, &(has_disconnected_args[0]));
}
chat_history_add(text);
@ -1408,7 +1408,7 @@ void Network::Server_Client_Joined(const char* name, const std::string &keyhash,
if (player) {
char text[256];
const char * player_name = (const char *) player->name.c_str();
format_string(text, STR_MULTIPLAYER_PLAYER_HAS_JOINED_THE_GAME, &player_name);
format_string(text, 256, STR_MULTIPLAYER_PLAYER_HAS_JOINED_THE_GAME, &player_name);
chat_history_add(text);
Server_Send_MAP(&connection);
gNetwork.Server_Send_EVENT_PLAYER_JOINED(player_name);
@ -1511,7 +1511,7 @@ void Network::Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& pa
}
char str_downloading_map[256];
unsigned int downloading_map_args[2] = {(offset + chunksize) / 1024, size / 1024};
format_string(str_downloading_map, STR_MULTIPLAYER_DOWNLOADING_MAP, downloading_map_args);
format_string(str_downloading_map, 256, STR_MULTIPLAYER_DOWNLOADING_MAP, downloading_map_args);
window_network_status_open(str_downloading_map, []() -> void {
gNetwork.Close();
});
@ -1779,27 +1779,26 @@ void Network::Client_Handle_GROUPLIST(NetworkConnection& connection, NetworkPack
void Network::Client_Handle_EVENT(NetworkConnection& connection, NetworkPacket& packet)
{
char text[256];
uint16 eventType;
packet >> eventType;
switch (eventType) {
case SERVER_EVENT_PLAYER_JOINED:
{
char text[256];
const char *playerName = packet.ReadString();
format_string(text, STR_MULTIPLAYER_PLAYER_HAS_JOINED_THE_GAME, &playerName);
format_string(text, 256, STR_MULTIPLAYER_PLAYER_HAS_JOINED_THE_GAME, &playerName);
chat_history_add(text);
break;
}
case SERVER_EVENT_PLAYER_DISCONNECTED:
{
char text[256];
const char *playerName = packet.ReadString();
const char *reason = packet.ReadString();
const char *args[] = { playerName, reason };
if (str_is_null_or_empty(reason)) {
format_string(text, STR_MULTIPLAYER_PLAYER_HAS_DISCONNECTED_NO_REASON, args);
format_string(text, 256, STR_MULTIPLAYER_PLAYER_HAS_DISCONNECTED_NO_REASON, args);
} else {
format_string(text, STR_MULTIPLAYER_PLAYER_HAS_DISCONNECTED_WITH_REASON, args);
format_string(text, 256, STR_MULTIPLAYER_PLAYER_HAS_DISCONNECTED_WITH_REASON, args);
}
chat_history_add(text);
break;
@ -2022,13 +2021,13 @@ const char* network_get_group_name(unsigned int index)
void network_chat_show_connected_message()
{
// TODO: How does this work? 2525 is '???'
char *templateString = (char*)language_get_string(STR_SHORTCUT_KEY_UNKNOWN);
keyboard_shortcut_format_string(templateString, gShortcutKeys[SHORTCUT_OPEN_CHAT_WINDOW]);
char templateBuffer[128];
char *templateString = templateBuffer;
keyboard_shortcut_format_string(templateBuffer, 128, gShortcutKeys[SHORTCUT_OPEN_CHAT_WINDOW]);
utf8 buffer[256];
NetworkPlayer server;
server.name = "Server";
format_string(buffer, STR_MULTIPLAYER_CONNECTED_CHAT_HINT, &templateString);
format_string(buffer, 256, STR_MULTIPLAYER_CONNECTED_CHAT_HINT, &templateString);
const char *formatted = Network::FormatChat(&server, buffer);
chat_history_add(formatted);
}
@ -2349,7 +2348,7 @@ void network_append_chat_log(const utf8 *text)
static void network_get_keys_directory(utf8 *buffer, size_t bufferSize)
{
platform_get_user_directory(buffer, "keys");
platform_get_user_directory(buffer, "keys", bufferSize);
}
static void network_get_private_key_path(utf8 *buffer, size_t bufferSize, const utf8 * playerName)
@ -2370,7 +2369,7 @@ static void network_get_public_key_path(utf8 *buffer, size_t bufferSize, const u
static void network_get_keymap_path(utf8 *buffer, size_t bufferSize)
{
platform_get_user_directory(buffer, NULL);
platform_get_user_directory(buffer, NULL, bufferSize);
Path::Append(buffer, bufferSize, "keymappings.json");
}

View File

@ -415,7 +415,7 @@ namespace Twitch
if (is_user_string_id(peep->name_string_idx))
{
utf8 buffer[256];
format_string(buffer, peep->name_string_idx, NULL);
format_string(buffer, 256, peep->name_string_idx, NULL);
AudienceMember * member = nullptr;
for (AudienceMember &m : members)
@ -505,27 +505,6 @@ namespace Twitch
}
}
/**
* Like strchr but allows searching for one of many characters.
*/
static char * strchrm(const char * str, const char * find)
{
do
{
const char * fch = find;
while (*fch != '\0')
{
if (*str == *fch)
{
return (char *)str;
}
fch++;
}
}
while (*str++ != '\0');
return nullptr;
}
static char * strskipwhitespace(const char * str)
{
while (*str == ' ' || *str == '\t')
@ -546,17 +525,16 @@ namespace Twitch
// Skip '!'
message++;
// Set buffer to the next word / token and skip
char buffer[32];
const char * ch = strchrm(message, " \t");
safe_strcpy(buffer, message, Math::Min(sizeof(buffer), (size_t)(ch - message + 1)));
ch = strskipwhitespace(ch);
// Check what the word / token is
if (String::Equals(buffer, "news", true))
{
DoChatMessageNews(ch);
// Check that command is "news"
const char *ch, *cmd;
for (ch = message, cmd = "news"; *cmd != '\0'; ++ch, ++cmd) {
if (*ch != *cmd) return;
}
if (!isspace(*ch)) return;
ch = strskipwhitespace(ch);
DoChatMessageNews(ch);
}
static void DoChatMessageNews(const char * message)

View File

@ -116,7 +116,7 @@ bool object_entry_is_empty(const rct_object_entry *entry);
bool object_entry_compare(const rct_object_entry *a, const rct_object_entry *b);
int object_calculate_checksum(const rct_object_entry * entry, const void * data, size_t dataLength);
int find_object_in_entry_group(const rct_object_entry* entry, uint8* entry_type, uint8* entry_index);
void object_create_identifier_name(char* string_buffer, const rct_object_entry* object);
void object_create_identifier_name(char* string_buffer, size_t size, const rct_object_entry* object);
rct_object_entry *object_list_find_by_name(const char *name);
rct_object_entry *object_list_find(rct_object_entry *entry);

View File

@ -46,6 +46,7 @@ extern "C"
#include "../platform/platform.h"
#include "../scenario.h"
#include "../util/sawyercoding.h"
#include "../util/util.h"
}
constexpr uint16 OBJECT_REPOSITORY_VERSION = 10;
@ -634,8 +635,8 @@ private:
static void GetRepositoryPath(utf8 * buffer, size_t bufferSize)
{
platform_get_user_directory(buffer, nullptr);
strcat(buffer, "objects.idx");
platform_get_user_directory(buffer, nullptr, bufferSize);
safe_strcat_path(buffer, "objects.idx", bufferSize);
}
static void GetRCT2ObjectPath(utf8 * buffer, size_t bufferSize)
@ -645,7 +646,7 @@ private:
static void GetUserObjectPath(utf8 * buffer, size_t bufferSize)
{
platform_get_user_directory(buffer, "object");
platform_get_user_directory(buffer, "object", bufferSize);
}
static uint32 GetPathChecksum(const utf8 * path)

View File

@ -122,9 +122,9 @@ bool object_entry_is_empty(const rct_object_entry *entry)
*
* rct2: 0x006AB344
*/
void object_create_identifier_name(char* string_buffer, const rct_object_entry* object)
void object_create_identifier_name(char* string_buffer, size_t size, const rct_object_entry* object)
{
sprintf(string_buffer, "%.8s/%4X%4X", object->name, object->flags, object->checksum);
snprintf(string_buffer, size, "%.8s/%4X%4X", object->name, object->flags, object->checksum);
}
/**

View File

@ -90,23 +90,25 @@ void openrct2_write_full_version_info(utf8 *buffer, size_t bufferSize)
utf8 *ch = buffer;
// Name and version
strcpy(ch, OPENRCT2_NAME);
strcat(buffer, ", v");
strcat(buffer, OPENRCT2_VERSION);
safe_strcpy(ch, OPENRCT2_NAME ", v" OPENRCT2_VERSION, bufferSize - (ch - buffer));
ch = strchr(ch, '\0');
// Build information
if (!str_is_null_or_empty(gGitBranch)) {
sprintf(strchr(buffer, 0), "-%s", gGitBranch);
snprintf(ch, bufferSize - (ch - buffer), "-%s", gGitBranch);
ch = strchr(ch, '\0');
}
if (!str_is_null_or_empty(gCommitSha1Short)) {
sprintf(strchr(buffer, 0), " build %s", gCommitSha1Short);
snprintf(ch, bufferSize - (ch - buffer), " build %s", gCommitSha1Short);
ch = strchr(ch, '\0');
}
if (!str_is_null_or_empty(gBuildServer)) {
sprintf(strchr(buffer, 0), " provided by %s", gBuildServer);
snprintf(ch, bufferSize - (ch - buffer), " provided by %s", gBuildServer);
ch = strchr(ch, '\0');
}
#if DEBUG
sprintf(strchr(buffer, 0), " (DEBUG)");
snprintf(ch, bufferSize - (ch - buffer), " (DEBUG)");
#endif
}
@ -122,23 +124,23 @@ static void openrct2_copy_files_over(const utf8 *originalDirectory, const utf8 *
}
// Create filter path
safe_strcpy(filter, originalDirectory, MAX_PATH);
safe_strcpy(filter, originalDirectory, sizeof(filter));
ch = strchr(filter, '*');
if (ch != NULL)
*ch = 0;
strcat(filter, "*");
strcat(filter, extension);
safe_strcat_path(filter, "*", sizeof(filter));
path_append_extension(filter, extension, sizeof(filter));
fileEnumHandle = platform_enumerate_files_begin(filter);
while (platform_enumerate_files_next(fileEnumHandle, &fileInfo)) {
safe_strcpy(newPath, newDirectory, MAX_PATH);
strcat(newPath, fileInfo.path);
safe_strcpy(newPath, newDirectory, sizeof(newPath));
safe_strcat_path(newPath, fileInfo.path, sizeof(newPath));
safe_strcpy(oldPath, originalDirectory, MAX_PATH);
safe_strcpy(oldPath, originalDirectory, sizeof(oldPath));
ch = strchr(oldPath, '*');
if (ch != NULL)
*ch = 0;
strcat(oldPath, fileInfo.path);
safe_strcat_path(oldPath, fileInfo.path, sizeof(oldPath));
if (!platform_file_exists(newPath))
platform_file_copy(oldPath, newPath, false);
@ -147,14 +149,14 @@ static void openrct2_copy_files_over(const utf8 *originalDirectory, const utf8 *
fileEnumHandle = platform_enumerate_directories_begin(originalDirectory);
while (platform_enumerate_directories_next(fileEnumHandle, filter)) {
safe_strcpy(newPath, newDirectory, MAX_PATH);
strcat(newPath, filter);
safe_strcpy(newPath, newDirectory, sizeof(newPath));
safe_strcat_path(newPath, filter, sizeof(newPath));
safe_strcpy(oldPath, originalDirectory, MAX_PATH);
ch = strchr(oldPath, '*');
if (ch != NULL)
*ch = 0;
strcat(oldPath, filter);
safe_strcat_path(oldPath, filter, sizeof(oldPath));
if (!platform_ensure_directory_exists(newPath)) {
log_error("Could not create directory %s.", newPath);
@ -167,7 +169,7 @@ static void openrct2_copy_files_over(const utf8 *originalDirectory, const utf8 *
static void openrct2_set_exe_path()
{
platform_get_exe_path(gExePath);
platform_get_exe_path(gExePath, sizeof(gExePath));
log_verbose("Setting exe path to %s", gExePath);
}
@ -178,10 +180,10 @@ static void openrct2_copy_original_user_files_over()
{
utf8 path[MAX_PATH];
platform_get_user_directory(path, "save");
platform_get_user_directory(path, "save", sizeof(path));
openrct2_copy_files_over((utf8*)gRCT2AddressSavedGamesPath, path, ".sv6");
platform_get_user_directory(path, "landscape");
platform_get_user_directory(path, "landscape", sizeof(path));
openrct2_copy_files_over((utf8*)gRCT2AddressLandscapesPath, path, ".sc6");
}
@ -196,7 +198,7 @@ bool openrct2_initialise()
platform_resolve_openrct_data_path();
platform_resolve_user_data_path();
platform_get_user_directory(userPath, NULL);
platform_get_user_directory(userPath, NULL, sizeof(userPath));
if (!platform_ensure_directory_exists(userPath)) {
log_fatal("Could not create user directory (do you have write access to your documents folder?)");
return false;
@ -217,7 +219,7 @@ bool openrct2_initialise()
gConfigGeneral.last_run_version = strndup(OPENRCT2_VERSION, strlen(OPENRCT2_VERSION));
config_save_default();
utf8 path[MAX_PATH];
config_get_default_path(path);
config_get_default_path(path, sizeof(path));
log_fatal("An RCT2 install directory must be specified! Please edit \"game_path\" in %s.", path);
return false;
}
@ -493,7 +495,7 @@ void openrct2_reset_object_tween_locations()
static void openrct2_get_segment_data_path(char * buffer, size_t bufferSize)
{
platform_get_exe_path(buffer);
platform_get_exe_path(buffer, bufferSize);
safe_strcat_path(buffer, "openrct2_data", bufferSize);
}

View File

@ -99,9 +99,9 @@ void banner_paint(uint8 direction, int height, rct_map_element* map_element)
string_id = STR_BANNER_TEXT_FORMAT;
}
if (gConfigGeneral.upper_case_banners) {
format_string_to_upper(gCommonStringFormatBuffer, string_id, gCommonFormatArgs);
format_string_to_upper(gCommonStringFormatBuffer, 256, string_id, gCommonFormatArgs);
} else {
format_string(gCommonStringFormatBuffer, string_id, gCommonFormatArgs);
format_string(gCommonStringFormatBuffer, 256, string_id, gCommonFormatArgs);
}
gCurrentFontSpriteBase = FONT_SPRITE_BASE_TINY;

View File

@ -131,9 +131,9 @@ static void ride_entrance_exit_paint(uint8 direction, int height, rct_map_elemen
utf8 entrance_string[MAX_PATH];
if (gConfigGeneral.upper_case_banners) {
format_string_to_upper(entrance_string, string_id, gCommonFormatArgs);
format_string_to_upper(entrance_string, MAX_PATH, string_id, gCommonFormatArgs);
} else {
format_string(entrance_string, string_id, gCommonFormatArgs);
format_string(entrance_string, MAX_PATH, string_id, gCommonFormatArgs);
}
gCurrentFontSpriteBase = FONT_SPRITE_BASE_TINY;
@ -208,9 +208,9 @@ static void park_entrance_paint(uint8 direction, int height, rct_map_element* ma
utf8 park_name[MAX_PATH];
if (gConfigGeneral.upper_case_banners) {
format_string_to_upper(park_name, park_text_id, gCommonFormatArgs);
format_string_to_upper(park_name, MAX_PATH, park_text_id, gCommonFormatArgs);
} else {
format_string(park_name, park_text_id, gCommonFormatArgs);
format_string(park_name, MAX_PATH, park_text_id, gCommonFormatArgs);
}
gCurrentFontSpriteBase = FONT_SPRITE_BASE_TINY;

View File

@ -367,9 +367,9 @@ void fence_paint(uint8 direction, int height, rct_map_element * map_element)
utf8 signString[MAX_PATH];
rct_string_id stringId = STR_SCROLLING_SIGN_TEXT;
if (gConfigGeneral.upper_case_banners) {
format_string_to_upper(signString, stringId, gCommonFormatArgs);
format_string_to_upper(signString, MAX_PATH, stringId, gCommonFormatArgs);
} else {
format_string(signString, stringId, gCommonFormatArgs);
format_string(signString, MAX_PATH, stringId, gCommonFormatArgs);
}
gCurrentFontSpriteBase = FONT_SPRITE_BASE_TINY;

View File

@ -396,9 +396,9 @@ static void sub_6A4101(rct_map_element * map_element, uint16 height, uint32 ebp,
string_id = STR_RIDE_ENTRANCE_NAME;
}
if (gConfigGeneral.upper_case_banners) {
format_string_to_upper(gCommonStringFormatBuffer, string_id, gCommonFormatArgs);
format_string_to_upper(gCommonStringFormatBuffer, 256, string_id, gCommonFormatArgs);
} else {
format_string(gCommonStringFormatBuffer, string_id, gCommonFormatArgs);
format_string(gCommonStringFormatBuffer, 256, string_id, gCommonFormatArgs);
}
gCurrentFontSpriteBase = FONT_SPRITE_BASE_TINY;

View File

@ -21,6 +21,7 @@
#include "../../game.h"
#include "../../interface/viewport.h"
#include "../../localisation/localisation.h"
#include "../../util/util.h"
#include "../../world/map.h"
#include "../../world/scenery.h"
@ -88,9 +89,9 @@ static int scenery_multiple_sign_text_height(const utf8 *str, rct_large_scenery_
static const utf8 *scenery_multiple_sign_fit_text(const utf8 *str, rct_large_scenery_text *text, bool height)
{
static utf8 fitStr[32] = {0};
static utf8 fitStr[32];
utf8 *fitStrEnd = fitStr;
strncpy(fitStr, str, sizeof(fitStr) - 1);
safe_strcpy(fitStr, str, sizeof(fitStr));
int w = 0;
uint32 codepoint;
while (w <= text->max_width && (codepoint = utf8_get_next(fitStrEnd, (const utf8**)&fitStrEnd)) != 0) {
@ -262,16 +263,16 @@ void scenery_multiple_paint(uint8 direction, uint16 height, rct_map_element *map
stringId = ride->name;
set_format_arg(0, uint32, ride->name_arguments);
}
utf8 signString[MAX_PATH] = {0};
format_string(signString, stringId, gCommonFormatArgs);
utf8 signString[MAX_PATH];
format_string(signString, MAX_PATH, stringId, gCommonFormatArgs);
rct_large_scenery_text *text = entry->large_scenery.text;
int y_offset = (text->offset[(direction & 1)].y * 2);
if (text->var_C & 0x1) {
// Draw vertical sign:
y_offset += 1;
utf8 fitStr[32] = {0};
utf8 fitStr[32];
const utf8 *fitStrPtr = fitStr;
strncpy(fitStr, scenery_multiple_sign_fit_text(signString, text, true), sizeof(fitStr) - 1);
safe_strcpy(fitStr, scenery_multiple_sign_fit_text(signString, text, true), sizeof(fitStr));
int height = scenery_multiple_sign_text_height(fitStr, text);
uint32 codepoint;
while ((codepoint = utf8_get_next(fitStrPtr, &fitStrPtr)) != 0) {
@ -355,9 +356,9 @@ void scenery_multiple_paint(uint8 direction, uint16 height, rct_map_element *map
utf8 signString[MAX_PATH];
rct_string_id stringId = STR_SCROLLING_SIGN_TEXT;
if (gConfigGeneral.upper_case_banners) {
format_string_to_upper(signString, stringId, gCommonFormatArgs);
format_string_to_upper(signString, MAX_PATH, stringId, gCommonFormatArgs);
} else {
format_string(signString, stringId, gCommonFormatArgs);
format_string(signString, MAX_PATH, stringId, gCommonFormatArgs);
}
gCurrentFontSpriteBase = FONT_SPRITE_BASE_TINY;

View File

@ -1094,7 +1094,7 @@ void viewport_draw_money_effects()
draw_pixel_info_crop_by_zoom(&dpi);
do {
format_string(buffer, ps->string_id, &ps->args);
format_string(buffer, 256, ps->string_id, &ps->args);
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
bool forceSpriteFont = false;

View File

@ -7364,7 +7364,7 @@ int peep_check_easteregg_name(int index, rct_peep *peep)
{
char buffer[256];
format_string(buffer, peep->name_string_idx, &peep->id);
format_string(buffer, 256, peep->name_string_idx, &peep->id);
return _stricmp(buffer, gPeepEasterEggNames[index]) == 0;
}
@ -7373,7 +7373,7 @@ int peep_get_easteregg_name_id(rct_peep *peep)
char buffer[256];
int i;
format_string(buffer, peep->name_string_idx, &peep->id);
format_string(buffer, 256, peep->name_string_idx, &peep->id);
for (i = 0; i < countof(gPeepEasterEggNames); i++)
if (_stricmp(buffer, gPeepEasterEggNames[i]) == 0)
@ -9889,7 +9889,7 @@ static int guest_path_finding(rct_peep* peep)
/* For guests, use the existing PEEP_FLAGS_TRACKING flag to
* determine for which guest(s) the pathfinding debugging will
* be output for. */
format_string(gPathFindDebugPeepName, peep->name_string_idx, &(peep->id));
format_string(gPathFindDebugPeepName, sizeof(gPathFindDebugPeepName), peep->name_string_idx, &(peep->id));
gPathFindDebug = peep->peep_flags & PEEP_FLAGS_TRACKING;
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
@ -11888,9 +11888,9 @@ static int peep_compare(const void *sprite_index_a, const void *sprite_index_b)
utf8 name_a[256];
utf8 name_b[256];
uint32 peepIndex = peep_a->id;
format_string(name_a, peep_a->name_string_idx, &peepIndex);
format_string(name_a, 256, peep_a->name_string_idx, &peepIndex);
peepIndex = peep_b->id;
format_string(name_b, peep_b->name_string_idx, &peepIndex);
format_string(name_b, 256, peep_b->name_string_idx, &peepIndex);
return strlogicalcmp(name_a, name_b);
}
@ -12059,7 +12059,7 @@ money32 set_peep_name(int flags, int state, uint16 sprite_index, uint8* text_1,
set_format_arg(0, uint32, peep->id);
utf8* curName = gCommonStringFormatBuffer;
rct_string_id curId = peep->name_string_idx;
format_string(curName, curId, gCommonFormatArgs);
format_string(curName, 256, curId, gCommonFormatArgs);
if (strcmp(curName, newName) == 0)
return 0;

View File

@ -1100,7 +1100,7 @@ static uint8 staff_mechanic_direction_path(rct_peep* peep, uint8 validDirections
/* For staff, there is no tracking button (any other similar
* suitable existing mechanism?), so fall back to a crude
* string comparison with a compile time hardcoded name. */
format_string(gPathFindDebugPeepName, peep->name_string_idx, &(peep->id));
format_string(gPathFindDebugPeepName, sizeof(gPathFindDebugPeepName), peep->name_string_idx, &(peep->id));
gPathFindDebug = strcmp(gPathFindDebugPeepName, "Mechanic Debug") == 0;
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1

View File

@ -24,9 +24,6 @@
#include <breakpad/client/windows/handler/exception_handler.h>
#include <string>
#include <ShlObj.h>
#elif defined(__LINUX__)
#include <breakpad/client/linux/handler/exception_handler.h>
#define BREAKPAD_PATH "/tmp"
#else
#error Breakpad support not implemented yet for this platform
#endif
@ -68,12 +65,12 @@ static bool OnCrash(const wchar_t * dumpPath,
// Get filenames
wchar_t dumpFilePath[MAX_PATH];
wchar_t saveFilePath[MAX_PATH];
wsprintfW(dumpFilePath, L"%s%s.dmp", dumpPath, miniDumpId);
wsprintfW(saveFilePath, L"%s%s.sv6", dumpPath, miniDumpId);
swprintf_s(dumpFilePath, sizeof(dumpFilePath), L"%s%s.dmp", dumpPath, miniDumpId);
swprintf_s(saveFilePath, sizeof(saveFilePath), L"%s%s.sv6", dumpPath, miniDumpId);
// Try to rename the files
wchar_t dumpFilePathNew[MAX_PATH];
wsprintfW(dumpFilePathNew, L"%s%s(%s).dmp", dumpPath, miniDumpId, _wszCommitSha1Short);
swprintf_s(dumpFilePathNew, sizeof(dumpFilePathNew), L"%s%s(%s).dmp", dumpPath, miniDumpId, _wszCommitSha1Short);
if (_wrename(dumpFilePath, dumpFilePathNew) == 0)
{
std::wcscpy(dumpFilePath, dumpFilePathNew);
@ -141,7 +138,7 @@ static bool OnCrash(const wchar_t * dumpPath,
static std::wstring GetDumpDirectory()
{
char userDirectory[MAX_PATH];
platform_get_user_directory(userDirectory, NULL);
platform_get_user_directory(userDirectory, NULL, sizeof(userDirectory));
wchar_t * userDirectoryW = utf8_to_widechar(userDirectory);
auto result = std::wstring(userDirectoryW);

View File

@ -46,7 +46,7 @@ struct dummy {
typedef enum { DT_NONE, DT_KDIALOG, DT_ZENITY } dialog_type;
void platform_get_exe_path(utf8 *outPath)
void platform_get_exe_path(utf8 *outPath, size_t outSize)
{
char exePath[MAX_PATH];
ssize_t bytesRead;
@ -55,17 +55,16 @@ void platform_get_exe_path(utf8 *outPath)
log_fatal("failed to read /proc/self/exe");
}
exePath[bytesRead - 1] = '\0';
char *exeDelimiter = strrchr(exePath, platform_get_path_separator());
char *exeDelimiter = strrchr(exePath, *PATH_SEPARATOR);
if (exeDelimiter == NULL)
{
log_error("should never happen here");
outPath[0] = '\0';
return;
}
int exeDelimiterIndex = (int)(exeDelimiter - exePath);
*exeDelimiter = '\0';
exePath[exeDelimiterIndex] = '\0';
safe_strcpy(outPath, exePath, exeDelimiterIndex + 1);
safe_strcpy(outPath, exePath, outSize);
}
bool platform_check_steam_overlay_attached() {
@ -94,7 +93,7 @@ bool platform_check_steam_overlay_attached() {
* - $XDG_CONFIG_HOME/OpenRCT2
* - /home/[uid]/.config/OpenRCT2
*/
void platform_posix_sub_user_data_path(char *buffer, const char *homedir, const char *separator) {
void platform_posix_sub_user_data_path(char *buffer, size_t size, const char *homedir) {
const char *configdir = getenv("XDG_CONFIG_HOME");
log_verbose("configdir = '%s'", configdir);
if (configdir == NULL)
@ -107,17 +106,15 @@ void platform_posix_sub_user_data_path(char *buffer, const char *homedir, const
return;
}
strncat(buffer, homedir, MAX_PATH - 1);
strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
strncat(buffer, ".config", MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
safe_strcpy(buffer, homedir, size);
safe_strcat_path(buffer, ".config", size);
}
else
{
strncat(buffer, configdir, MAX_PATH - 1);
safe_strcpy(buffer, configdir, size);
}
strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
strncat(buffer, "OpenRCT2", MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
safe_strcat_path(buffer, "OpenRCT2", size);
path_end_with_separator(buffer, size);
}
/**
@ -128,7 +125,7 @@ void platform_posix_sub_user_data_path(char *buffer, const char *homedir, const
* - /var/lib/openrct2
* - /usr/share/openrct2
*/
void platform_posix_sub_resolve_openrct_data_path(utf8 *out) {
void platform_posix_sub_resolve_openrct_data_path(utf8 *out, size_t size) {
static const utf8 *searchLocations[] = {
"../share/openrct2",
#ifdef ORCT2_RESOURCE_DIR
@ -144,8 +141,7 @@ void platform_posix_sub_resolve_openrct_data_path(utf8 *out) {
log_verbose("Looking for OpenRCT2 data in %s", searchLocations[i]);
if (platform_directory_exists(searchLocations[i]))
{
out[0] = '\0';
safe_strcpy(out, searchLocations[i], MAX_PATH);
safe_strcpy(out, searchLocations[i], size);
return;
}
}
@ -169,7 +165,7 @@ uint16 platform_get_locale_language(){
}
}
} //end strip
strncpy(pattern,langString, length); //copy all until first '.' or '@'
memcpy(pattern, langString, length); //copy all until first '.' or '@'
pattern[length] = '\0';
//find _ if present
const char *strip = strchr(pattern, '_');
@ -304,7 +300,7 @@ static dialog_type get_dialog_app(char *cmd, size_t *cmd_size) {
return dtype;
}
bool platform_open_common_file_dialog(utf8 *outFilename, file_dialog_desc *desc) {
bool platform_open_common_file_dialog(utf8 *outFilename, file_dialog_desc *desc, size_t outSize) {
int exit_value;
char executable[MAX_PATH];
char cmd[MAX_PATH];
@ -428,7 +424,7 @@ bool platform_open_common_file_dialog(utf8 *outFilename, file_dialog_desc *desc)
snprintf(msg, MAX_PATH, "\"%s\" not found: %s, please choose another file\n", result, strerror(errno));
platform_show_messagebox(msg);
return platform_open_common_file_dialog(outFilename, desc);
return platform_open_common_file_dialog(outFilename, desc, outSize);
} else
if (desc->type == FD_SAVE && access(result, F_OK) != -1 && dtype == DT_KDIALOG) {
snprintf(cmd, MAX_PATH, "%s --yesno \"Overwrite %s?\"", executable, result);
@ -441,7 +437,7 @@ bool platform_open_common_file_dialog(utf8 *outFilename, file_dialog_desc *desc)
}
}
strncpy(outFilename, result, MAX_PATH);
safe_strcpy(outFilename, result, outSize);
return 1;
}
@ -477,8 +473,7 @@ utf8 *platform_open_directory_browser(utf8 *title) {
result[size-1] = '\0';
return_value = (char*) malloc(strlen(result)+1);
strcpy(return_value, result);
return_value = _strdup(result);
return return_value;
}
@ -510,7 +505,7 @@ void platform_show_messagebox(char *message) {
execute_cmd(cmd, 0, 0, 0);
}
bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer)
bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer, size_t size)
{
assert(buffer != NULL);
assert(font != NULL);
@ -538,7 +533,7 @@ bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer)
if (FcPatternGetString(match, FC_FILE, 0, &filename) == FcResultMatch)
{
found = true;
safe_strcpy(buffer, (utf8*) filename, MAX_PATH);
safe_strcpy(buffer, (utf8*) filename, size);
log_verbose("FontConfig provided font %s", filename);
}
FcPatternDestroy(match);

View File

@ -29,8 +29,9 @@ bool platform_check_steam_overlay_attached() {
return false;
}
void platform_get_exe_path(utf8 *outPath)
void platform_get_exe_path(utf8 *outPath, size_t outSize)
{
if (outSize == 0) return;
char exePath[MAX_PATH];
uint32_t size = MAX_PATH;
int result = _NSGetExecutablePath(exePath, &size);
@ -38,17 +39,16 @@ void platform_get_exe_path(utf8 *outPath)
log_fatal("failed to get path");
}
exePath[MAX_PATH - 1] = '\0';
char *exeDelimiter = strrchr(exePath, platform_get_path_separator());
char *exeDelimiter = strrchr(exePath, *PATH_SEPARATOR);
if (exeDelimiter == NULL)
{
log_error("should never happen here");
outPath[0] = '\0';
return;
}
int exeDelimiterIndex = (int)(exeDelimiter - exePath);
*exeDelimiter = '\0';
safe_strcpy(outPath, exePath, exeDelimiterIndex + 1);
outPath[exeDelimiterIndex] = '\0';
safe_strcpy(outPath, exePath, outSize);
}
/**
@ -56,7 +56,7 @@ void platform_get_exe_path(utf8 *outPath)
* - (command line argument)
* - ~/Library/Application Support/OpenRCT2
*/
void platform_posix_sub_user_data_path(char *buffer, const char *homedir, const char *separator) {
void platform_posix_sub_user_data_path(char *buffer, size_t size, const char *homedir) {
if (homedir == NULL)
{
log_fatal("Couldn't find user data directory");
@ -64,14 +64,11 @@ void platform_posix_sub_user_data_path(char *buffer, const char *homedir, const
return;
}
strncat(buffer, homedir, MAX_PATH - 1);
strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
strncat(buffer, "Library", MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
strncat(buffer, "Application Support", MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
strncat(buffer, "OpenRCT2", MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
safe_strcpy(buffer, homedir, size);
safe_strcat_path(buffer, "Library", size);
safe_strcat_path(buffer, "Application Support", size);
safe_strcat_path(buffer, "OpenRCT2", size);
path_end_with_separator(buffer, size);
}
/**
@ -80,7 +77,7 @@ void platform_posix_sub_user_data_path(char *buffer, const char *homedir, const
* - <exePath>/data
* - <Resources Folder>
*/
void platform_posix_sub_resolve_openrct_data_path(utf8 *out) {
void platform_posix_sub_resolve_openrct_data_path(utf8 *out, size_t size) {
@autoreleasepool
{
NSBundle *bundle = [NSBundle mainBundle];
@ -90,7 +87,7 @@ void platform_posix_sub_resolve_openrct_data_path(utf8 *out) {
if (platform_directory_exists(resources))
{
out[0] = '\0';
safe_strcpy(out, resources, MAX_PATH);
safe_strcpy(out, resources, size);
return;
}
}
@ -121,14 +118,13 @@ utf8 *platform_open_directory_browser(utf8 *title)
{
NSString *selectedPath = panel.URL.path;
const char *path = selectedPath.UTF8String;
url = (utf8*)malloc(strlen(path) + 1);
strcpy(url,path);
url = _strdup(path);
}
return url;
}
}
bool platform_open_common_file_dialog(utf8 *outFilename, file_dialog_desc *desc) {
bool platform_open_common_file_dialog(utf8 *outFilename, file_dialog_desc *desc, size_t outSize) {
@autoreleasepool
{
NSMutableArray *extensions = [NSMutableArray new];
@ -169,14 +165,14 @@ bool platform_open_common_file_dialog(utf8 *outFilename, file_dialog_desc *desc)
SDL_RaiseWindow(gWindow);
return false;
} else {
strcpy(outFilename, panel.URL.path.UTF8String);
safe_strcpy(outFilename, panel.URL.path.UTF8String, outSize);
SDL_RaiseWindow(gWindow);
return true;
}
}
}
bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer)
bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer, size_t size)
{
@autoreleasepool
{
@ -184,7 +180,7 @@ bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer)
CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(fontRef, kCTFontURLAttribute);
if (url) {
NSString *fontPath = [NSString stringWithString:[(NSURL *)CFBridgingRelease(url) path]];
strcpy(buffer, fontPath.UTF8String);
safe_strcpy(buffer, fontPath.UTF8String, size);
return true;
} else {
return false;

View File

@ -46,8 +46,10 @@
#ifdef __WINDOWS__
#define PATH_SEPARATOR "\\"
#define PLATFORM_NEWLINE "\r\n"
#else
#define PATH_SEPARATOR "/"
#define PLATFORM_NEWLINE "\n"
#endif
typedef struct resolution {
@ -145,9 +147,7 @@ void platform_get_date_local(rct2_date *out_date);
void platform_get_time_local(rct2_time *out_time);
// Platform specific definitions
void platform_get_exe_path(utf8 *outPath);
const char *platform_get_new_line();
char platform_get_path_separator();
void platform_get_exe_path(utf8 *outPath, size_t outSize);
bool platform_file_exists(const utf8 *path);
bool platform_directory_exists(const utf8 *path);
bool platform_original_game_data_exists(const utf8 *path);
@ -177,18 +177,18 @@ void platform_set_cursor_position(int x, int y);
unsigned int platform_get_ticks();
void platform_resolve_user_data_path();
void platform_resolve_openrct_data_path();
void platform_get_openrct_data_path(utf8 *outPath);
void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory);
void platform_get_openrct_data_path(utf8 *outPath, size_t outSize);
void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory, size_t outSize);
utf8* platform_get_username();
void platform_show_messagebox(utf8 *message);
bool platform_open_common_file_dialog(utf8 *outFilename, file_dialog_desc *desc);
bool platform_open_common_file_dialog(utf8 *outFilename, file_dialog_desc *desc, size_t outSize);
utf8 *platform_open_directory_browser(utf8 *title);
uint8 platform_get_locale_currency();
uint8 platform_get_currency_value(const char *currencyCode);
uint16 platform_get_locale_language();
uint8 platform_get_locale_measurement_format();
uint8 platform_get_locale_temperature_format();
bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer);
bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer, size_t size);
bool platform_check_steam_overlay_attached();
@ -212,8 +212,8 @@ datetime64 platform_get_datetime_now_utc();
#endif // __WINDOWS__
#if defined(__LINUX__) || defined(__MACOSX__)
void platform_posix_sub_user_data_path(char *buffer, const char *homedir, const char *separator);
void platform_posix_sub_resolve_openrct_data_path(utf8 *out);
void platform_posix_sub_user_data_path(char *buffer, size_t size, const char *homedir);
void platform_posix_sub_resolve_openrct_data_path(utf8 *out, size_t size);
#endif
#endif

View File

@ -111,16 +111,6 @@ void platform_get_time_local(rct2_time *out_time)
out_time->hour = timeinfo->tm_hour;
}
char platform_get_path_separator()
{
return '/';
}
const char *platform_get_new_line()
{
return "\n";
}
bool platform_file_exists(const utf8 *path)
{
wchar_t *wPath = utf8_to_widechar(path);
@ -160,9 +150,10 @@ bool platform_original_game_data_exists(const utf8 *path)
wcstombs(buffer, wPath, len);
buffer[len] = '\0';
free(wPath);
char separator = platform_get_path_separator();
char checkPath[MAX_PATH];
sprintf(checkPath, "%s%c%s%c%s", buffer, separator, "Data", separator, "g1.dat");
safe_strcpy(checkPath, buffer, MAX_PATH);
safe_strcat_path(checkPath, "Data", MAX_PATH);
safe_strcat_path(checkPath, "g1.dat", MAX_PATH);
return platform_file_exists(checkPath);
}
@ -198,8 +189,7 @@ bool platform_directory_delete(const utf8 *path)
FTSENT *p, *chp;
// fts_open only accepts non const paths, so we have to take a copy
char* ourPath = (char*)malloc(strlen(path) + 1);
strcpy(ourPath, path);
char* ourPath = _strdup(path);
utf8* const patharray[2] = {ourPath, NULL};
if ((ftsp = fts_open(patharray, FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOCHDIR, NULL)) == NULL) {
@ -321,7 +311,7 @@ int platform_enumerate_files_begin(const utf8 *pattern)
}
log_verbose("begin file search, pattern: %s", npattern);
char *file_name = strrchr(npattern, platform_get_path_separator());
char *file_name = strrchr(npattern, *PATH_SEPARATOR);
char *dir_name;
if (file_name != NULL)
{
@ -356,7 +346,6 @@ int platform_enumerate_files_begin(const utf8 *pattern)
char **paths = enumFileInfo->paths;
// 256 is size of dirent.d_name
const int dir_name_len = strnlen(dir_name, MAX_PATH);
char separator[] = {platform_get_path_separator(), 0};
for (int idx = 0; idx < cnt; idx++)
{
struct dirent *d = enumFileInfo->fileListTemp[idx];
@ -364,11 +353,9 @@ int platform_enumerate_files_begin(const utf8 *pattern)
// 1 for separator, 1 for trailing null
size_t path_len = sizeof(char) * min(MAX_PATH, entry_len + dir_name_len + 2);
paths[idx] = malloc(path_len);
paths[idx][0] = '\0';
log_verbose("dir_name: %s", dir_name);
strncat(paths[idx], dir_name, path_len - 2);
strncat(paths[idx], separator, path_len - strnlen(paths[idx], path_len) - 1);
strncat(paths[idx], d->d_name, path_len - strnlen(paths[idx], path_len) - 1);
safe_strcpy(paths[idx], dir_name, path_len);
safe_strcat_path(paths[idx], d->d_name, path_len);
log_verbose("paths[%d] = %s", idx, paths[idx]);
}
enumFileInfo->handle = 0;
@ -495,7 +482,6 @@ int platform_enumerate_directories_begin(const utf8 *directory)
char **paths = enumFileInfo->paths;
// 256 is size of dirent.d_name
const int dir_name_len = strnlen(npattern, MAX_PATH);
char separator[] = {platform_get_path_separator(), 0};
for (int idx = 0; idx < cnt; idx++)
{
struct dirent *d = enumFileInfo->fileListTemp[idx];
@ -503,11 +489,9 @@ int platform_enumerate_directories_begin(const utf8 *directory)
// 1 for separator, 1 for trailing null
size_t path_len = sizeof(char) * min(MAX_PATH, entry_len + dir_name_len + 2);
paths[idx] = malloc(path_len);
paths[idx][0] = '\0';
log_verbose("dir_name: %s", npattern);
strncat(paths[idx], npattern, path_len - 2);
strncat(paths[idx], separator, path_len - strnlen(paths[idx], path_len) - 1);
strncat(paths[idx], d->d_name, path_len - strnlen(paths[idx], path_len) - 1);
safe_strcpy(paths[idx], npattern, path_len);
safe_strcat_path(paths[idx], d->d_name, path_len);
log_verbose("paths[%d] = %s", idx, paths[idx]);
}
enumFileInfo->handle = 0;
@ -552,7 +536,7 @@ bool platform_enumerate_directories_next(int handle, utf8 *path)
}
// so very, very wrong
safe_strcpy(path, basename(fileName), MAX_PATH);
strncat(path, "/", MAX_PATH - strlen(path) - 1);
path_end_with_separator(path, MAX_PATH);
return true;
} else {
return false;
@ -679,7 +663,6 @@ static wchar_t *regular_to_wchar(const char* src)
*/
void platform_resolve_user_data_path()
{
const char separator[2] = { platform_get_path_separator(), 0 };
if (gCustomUserDataPath[0] != 0) {
if (!platform_ensure_directory_exists(gCustomUserDataPath)) {
@ -696,10 +679,7 @@ void platform_resolve_user_data_path()
free(path);
// Ensure path ends with separator
int len = strlen(_userDataDirectoryPath);
if (_userDataDirectoryPath[len - 1] != separator[0]) {
strncat(_userDataDirectoryPath, separator, MAX_PATH - 1);
}
path_end_with_separator(_userDataDirectoryPath, MAX_PATH);
log_verbose("User data path resolved to: %s", _userDataDirectoryPath);
if (!platform_directory_exists(_userDataDirectoryPath)) {
log_error("Custom user data directory %s does not exist", _userDataDirectoryPath);
@ -708,11 +688,10 @@ void platform_resolve_user_data_path()
}
char buffer[MAX_PATH];
buffer[0] = '\0';
log_verbose("buffer = '%s'", buffer);
const char *homedir = getpwuid(getuid())->pw_dir;
platform_posix_sub_user_data_path(buffer, homedir, separator);
platform_posix_sub_user_data_path(buffer, MAX_PATH, homedir);
log_verbose("OpenRCT2 user data directory = '%s'", buffer);
int len = strnlen(buffer, MAX_PATH);
@ -725,9 +704,9 @@ void platform_resolve_user_data_path()
log_verbose("User data path resolved to: %s", _userDataDirectoryPath);
}
void platform_get_openrct_data_path(utf8 *outPath)
void platform_get_openrct_data_path(utf8 *outPath, size_t outSize)
{
safe_strcpy(outPath, _openrctDataDirectoryPath, sizeof(_openrctDataDirectoryPath));
safe_strcpy(outPath, _openrctDataDirectoryPath, outSize);
}
/**
@ -738,27 +717,20 @@ void platform_get_openrct_data_path(utf8 *outPath)
*/
void platform_resolve_openrct_data_path()
{
const char separator[2] = { platform_get_path_separator(), 0 };
if (gCustomOpenrctDataPath[0] != 0) {
if (realpath(gCustomOpenrctDataPath, _openrctDataDirectoryPath)) {
log_error("Could not resolve path \"%s\"", gCustomOpenrctDataPath);
return;
}
// Ensure path ends with separator
int len = strlen(_openrctDataDirectoryPath);
if (_openrctDataDirectoryPath[len - 1] != separator[0]) {
strncat(_openrctDataDirectoryPath, separator, MAX_PATH - 1);
}
path_end_with_separator(_openrctDataDirectoryPath, MAX_PATH);
return;
}
char buffer[MAX_PATH] = { 0 };
platform_get_exe_path(buffer);
char buffer[MAX_PATH];
platform_get_exe_path(buffer, sizeof(buffer));
strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
strncat(buffer, "data", MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
safe_strcat_path(buffer, "data", MAX_PATH);
log_verbose("Looking for OpenRCT2 data in %s", buffer);
if (platform_directory_exists(buffer))
{
@ -768,26 +740,25 @@ void platform_resolve_openrct_data_path()
return;
}
platform_posix_sub_resolve_openrct_data_path(_openrctDataDirectoryPath);
platform_posix_sub_resolve_openrct_data_path(_openrctDataDirectoryPath, sizeof(_openrctDataDirectoryPath));
log_verbose("Trying to use OpenRCT2 data in %s", _openrctDataDirectoryPath);
}
void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory)
void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory, size_t outSize)
{
const char separator[2] = { platform_get_path_separator(), 0 };
char buffer[MAX_PATH];
safe_strcpy(buffer, _userDataDirectoryPath, sizeof(buffer));
if (subDirectory != NULL && subDirectory[0] != 0) {
log_verbose("adding subDirectory '%s'", subDirectory);
strncat(buffer, subDirectory, MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
safe_strcat_path(buffer, subDirectory, sizeof(buffer));
path_end_with_separator(buffer, sizeof(buffer));
}
int len = strnlen(buffer, MAX_PATH);
wchar_t *w_buffer = regular_to_wchar(buffer);
w_buffer[len] = '\0';
utf8 *path = widechar_to_utf8(w_buffer);
free(w_buffer);
safe_strcpy(outPath, path, MAX_PATH);
safe_strcpy(outPath, path, outSize);
free(path);
log_verbose("outPath + subDirectory = '%s'", buffer);
}

View File

@ -517,7 +517,7 @@ void platform_process_messages()
break;
case SDL_TEXTEDITING:
// When inputting Korean characters, `e.edit.length` is always Zero.
safe_strcpy(gTextInputComposition, e.edit.text, min((e.edit.length == 0) ? (strlen(e.edit.text)+1) : e.edit.length, 32));
safe_strcpy(gTextInputComposition, e.edit.text, sizeof(gTextInputComposition));
gTextInputCompositionStart = e.edit.start;
gTextInputCompositionLength = e.edit.length;
gTextInputCompositionActive = ((e.edit.length != 0 || strlen(e.edit.text) != 0) && gTextInputComposition[0] != 0);

View File

@ -178,16 +178,6 @@ void platform_get_time_local(rct2_time *out_time)
out_time->second = systime.wSecond;
}
char platform_get_path_separator()
{
return '\\';
}
const char *platform_get_new_line()
{
return "\r\n";
}
bool platform_file_exists(const utf8 *path)
{
wchar_t *wPath = utf8_to_widechar(path);
@ -208,7 +198,9 @@ bool platform_directory_exists(const utf8 *path)
bool platform_original_game_data_exists(const utf8 *path)
{
utf8 checkPath[MAX_PATH];
sprintf(checkPath, "%s%c%s%c%s", path, platform_get_path_separator(), "Data", platform_get_path_separator(), "g1.dat");
safe_strcpy(checkPath, path, MAX_PATH);
safe_strcat_path(checkPath, "Data", MAX_PATH);
safe_strcat_path(checkPath, "g1.dat", MAX_PATH);
return platform_file_exists(checkPath);
}
@ -465,8 +457,8 @@ bool platform_enumerate_directories_next(int handle, utf8 *path)
}
utf8 *filename = widechar_to_utf8(enumFileInfo->data.cFileName);
strncpy(path, filename, MAX_PATH);
strncat(path, "\\", MAX_PATH);
safe_strcpy(path, filename, MAX_PATH);
path_end_with_separator(path, MAX_PATH);
free(filename);
return true;
}
@ -519,7 +511,6 @@ bool platform_file_delete(const utf8 *path)
void platform_resolve_openrct_data_path()
{
wchar_t wOutPath[MAX_PATH];
const char separator[2] = { platform_get_path_separator(), 0 };
if (gCustomOpenrctDataPath[0] != 0) {
wchar_t *customUserDataPathW = utf8_to_widechar(gCustomOpenrctDataPath);
@ -532,18 +523,13 @@ void platform_resolve_openrct_data_path()
free(outPathTemp);
free(customUserDataPathW);
// Ensure path ends with separator
size_t len = strlen(_userDataDirectoryPath);
if (_userDataDirectoryPath[len - 1] != separator[0]) {
strcat(_userDataDirectoryPath, separator);
}
path_end_with_separator(_userDataDirectoryPath, sizeof(_userDataDirectoryPath));
return;
}
char buffer[MAX_PATH] = { 0 };
platform_get_exe_path(buffer);
char buffer[MAX_PATH];
platform_get_exe_path(buffer, sizeof(buffer));
strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
strncat(buffer, "data", MAX_PATH - strnlen(buffer, MAX_PATH) - 1);
safe_strcat_path(buffer, "data", MAX_PATH);
if (platform_directory_exists(buffer))
{
@ -556,9 +542,9 @@ void platform_resolve_openrct_data_path()
}
}
void platform_get_openrct_data_path(utf8 *outPath)
void platform_get_openrct_data_path(utf8 *outPath, size_t outSize)
{
safe_strcpy(outPath, _openrctDataDirectoryPath, sizeof(_openrctDataDirectoryPath));
safe_strcpy(outPath, _openrctDataDirectoryPath, outSize);
}
/**
@ -569,7 +555,6 @@ void platform_get_openrct_data_path(utf8 *outPath)
void platform_resolve_user_data_path()
{
wchar_t wOutPath[MAX_PATH];
const char separator[2] = { platform_get_path_separator(), 0 };
if (gCustomUserDataPath[0] != 0) {
wchar_t *customUserDataPathW = utf8_to_widechar(gCustomUserDataPath);
@ -582,11 +567,7 @@ void platform_resolve_user_data_path()
free(outPathTemp);
free(customUserDataPathW);
// Ensure path ends with separator
size_t len = strlen(_userDataDirectoryPath);
if (_userDataDirectoryPath[len - 1] != separator[0]) {
strcat(_userDataDirectoryPath, separator);
}
path_end_with_separator(_userDataDirectoryPath, sizeof(_userDataDirectoryPath));
return;
}
@ -595,23 +576,20 @@ void platform_resolve_user_data_path()
safe_strcpy(_userDataDirectoryPath, outPathTemp, sizeof(_userDataDirectoryPath));
free(outPathTemp);
strcat(_userDataDirectoryPath, separator);
strcat(_userDataDirectoryPath, "OpenRCT2");
strcat(_userDataDirectoryPath, separator);
safe_strcat_path(_userDataDirectoryPath, "OpenRCT2", sizeof(_userDataDirectoryPath));
path_end_with_separator(_userDataDirectoryPath, sizeof(_userDataDirectoryPath));
} else {
log_fatal("Unable to resolve user data path.");
exit(-1);
}
}
void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory)
void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory, size_t outSize)
{
const char separator[2] = { platform_get_path_separator(), 0 };
strcpy(outPath, _userDataDirectoryPath);
safe_strcpy(outPath, _userDataDirectoryPath, outSize);
if (subDirectory != NULL && subDirectory[0] != 0) {
strcat(outPath, subDirectory);
strcat(outPath, separator);
safe_strcat_path(outPath, subDirectory, outSize);
path_end_with_separator(outPath, outSize);
}
}
@ -624,7 +602,7 @@ void platform_show_messagebox(utf8 *message)
*
* rct2: 0x004080EA
*/
bool platform_open_common_file_dialog(utf8 *outFilename, file_dialog_desc *desc)
bool platform_open_common_file_dialog(utf8 *outFilename, file_dialog_desc *desc, size_t outSize)
{
OPENFILENAMEW openFileName;
wchar_t wcFilename[MAX_PATH];
@ -651,9 +629,9 @@ bool platform_open_common_file_dialog(utf8 *outFilename, file_dialog_desc *desc)
utf8 *ch = filters;
for (int i = 0; i < countof(desc->filters); i++) {
if (desc->filters[i].name != NULL) {
strcpy(ch, desc->filters[i].name);
safe_strcpy(ch, desc->filters[i].name, sizeof(filters) - (ch - filters));
ch = strchr(ch, 0) + 1;
strcpy(ch, desc->filters[i].pattern);
safe_strcpy(ch, desc->filters[i].pattern, sizeof(filters) - (ch - filters));
ch = strchr(ch, 0) + 1;
}
}
@ -695,7 +673,7 @@ bool platform_open_common_file_dialog(utf8 *outFilename, file_dialog_desc *desc)
if (result) {
utf8 *resultFilename = widechar_to_utf8(openFileName.lpstrFile);
strcpy(outFilename, resultFilename);
safe_strcpy(outFilename, resultFilename, outSize);
free(resultFilename);
// If there is no extension, append the pattern
@ -709,7 +687,7 @@ bool platform_open_common_file_dialog(utf8 *outFilename, file_dialog_desc *desc)
const utf8 *pattern = desc->filters[filterIndex].pattern;
const utf8 *patternExtension = path_get_extension(pattern);
if (!str_is_null_or_empty(patternExtension)) {
strcat(outFilename, patternExtension);
safe_strcat_path(outFilename, patternExtension, outSize);
}
}
}
@ -775,10 +753,10 @@ int windows_get_registry_install_info(rct2_install_info *installInfo, char *sour
HKEY hKey;
DWORD type, size;
strcpy(subkeyInfogrames, "Software\\Infogrames\\");
strcat(subkeyInfogrames, source);
strcpy(subkeyFishTechGroup, "Software\\Fish Technology Group\\");
strcat(subkeyFishTechGroup, source);
safe_strcpy(subkeyInfogrames, "Software\\Infogrames\\", sizeof(subkeyInfogrames));
safe_strcat(subkeyInfogrames, source, sizeof(subkeyInfogrames));
safe_strcpy(subkeyFishTechGroup, "Software\\Fish Technology Group\\", sizeof(subkeyFishTechGroup));
safe_strcat(subkeyFishTechGroup, source, sizeof(subkeyFishTechGroup));
if (RegOpenKeyA(HKEY_LOCAL_MACHINE, subkeyInfogrames, &hKey) != ERROR_SUCCESS)
return 0;
@ -798,7 +776,7 @@ int windows_get_registry_install_info(rct2_install_info *installInfo, char *sour
size = 4;
RegQueryValueExA(hKey, "InstallLevel", 0, &type, (LPBYTE)&installInfo->installLevel, &size);
for (int i = 0; i <= 15; i++) {
sprintf(keyName, "AddonPack%d", i);
snprintf(keyName, 100, "AddonPack%d", i);
size = sizeof(installInfo->expansionPackNames[i]);
if (RegQueryValueExA(hKey, keyName, 0, &type, installInfo->expansionPackNames[i], &size) == ERROR_SUCCESS)
installInfo->activeExpansionPacks |= (1 << i);
@ -992,23 +970,21 @@ char *strndup(const char *src, size_t size)
return (char *)dst;
}
void platform_get_exe_path(utf8 *outPath)
void platform_get_exe_path(utf8 *outPath, size_t outSize)
{
wchar_t exePath[MAX_PATH];
wchar_t tempPath[MAX_PATH];
wchar_t *exeDelimiter;
int exeDelimiterIndex;
GetModuleFileNameW(NULL, exePath, MAX_PATH);
exeDelimiter = wcsrchr(exePath, platform_get_path_separator());
exeDelimiterIndex = (int)(exeDelimiter - exePath);
lstrcpynW(tempPath, exePath, exeDelimiterIndex + 1);
tempPath[exeDelimiterIndex] = L'\0';
exeDelimiter = wcsrchr(exePath, *PATH_SEPARATOR);
*exeDelimiter = L'\0';
wcscpy_s(tempPath, MAX_PATH, exePath);
_wfullpath(exePath, tempPath, MAX_PATH);
WideCharToMultiByte(CP_UTF8, 0, exePath, countof(exePath), outPath, MAX_PATH, NULL, NULL);
WideCharToMultiByte(CP_UTF8, 0, exePath, MAX_PATH, outPath, (int) outSize, NULL, NULL);
}
bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer)
bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer, size_t size)
{
#if !defined(__MINGW32__) && ((NTDDI_VERSION >= NTDDI_VISTA) && !defined(_USING_V110_SDK71_) && !defined(_ATL_XP_TARGETING))
wchar_t *fontFolder;
@ -1016,15 +992,13 @@ bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer)
{
// Convert wchar to utf8, then copy the font folder path to the buffer.
utf8 *outPathTemp = widechar_to_utf8(fontFolder);
strcpy(buffer, outPathTemp);
safe_strcpy(buffer, outPathTemp, size);
free(outPathTemp);
CoTaskMemFree(fontFolder);
// Append the requested font's file name.
const char separator[2] = { platform_get_path_separator(), 0 };
strcat(buffer, separator);
strcat(buffer, font->filename);
safe_strcat_path(buffer, font->filename, size);
return true;
}
else
@ -1033,8 +1007,8 @@ bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer)
}
#else
log_warning("Compatibility hack: falling back to C:\\Windows\\Fonts");
strcpy(buffer, "C:\\Windows\\Fonts\\");
strcat(buffer, font->filename);
safe_strcpy(buffer, "C:\\Windows\\Fonts\\", size);
safe_strcat_path(buffer, font->filename, size);
return true;
#endif
}
@ -1090,6 +1064,8 @@ static bool windows_setup_file_association(
) {
wchar_t exePathW[MAX_PATH];
wchar_t dllPathW[MAX_PATH];
int printResult;
GetModuleFileNameW(NULL, exePathW, sizeof(exePathW));
GetModuleFileNameW(_dllModule, dllPathW, sizeof(dllPathW));
@ -1126,7 +1102,8 @@ static bool windows_setup_file_association(
}
// [hRootKey\OpenRCT2.ext\DefaultIcon]
wchar_t szIconW[MAX_PATH];
wsprintfW(szIconW, L"\"%s\",%d", dllPathW, iconIndex);
printResult = swprintf_s(szIconW, MAX_PATH, L"\"%s\",%d", dllPathW, iconIndex);
assert(printResult >= 0);
if (RegSetValueW(hKey, L"DefaultIcon", REG_SZ, szIconW, 0) != ERROR_SUCCESS) {
goto fail;
}
@ -1143,7 +1120,8 @@ static bool windows_setup_file_association(
// [hRootKey\OpenRCT2.sv6\shell\open\command]
wchar_t szCommandW[MAX_PATH];
wsprintfW(szCommandW, L"\"%s\" %s", exePathW, commandArgsW);
printResult = swprintf_s(szCommandW, MAX_PATH, L"\"%s\" %s", exePathW, commandArgsW);
assert(printResult >= 0);
if (RegSetValueW(hKey, L"shell\\open\\command", REG_SZ, szCommandW, 0) != ERROR_SUCCESS) {
goto fail;
}

View File

@ -204,59 +204,55 @@ int rct2_init_directories()
{
// windows_get_registry_install_info((rct2_install_info*)0x009AA10C, "RollerCoaster Tycoon 2 Setup", "MS Sans Serif", 0);
char separator[] = {platform_get_path_separator(), 0};
if (str_is_null_or_empty(gCustomRCT2DataPath)) {
// check install directory
if (!platform_original_game_data_exists(gConfigGeneral.game_path)) {
log_verbose("install directory does not exist or invalid directory selected, %s", gConfigGeneral.game_path);
if (!config_find_or_browse_install_directory()) {
utf8 path[MAX_PATH];
config_get_default_path(path);
config_get_default_path(path, sizeof(path));
log_fatal("Invalid RCT2 installation path. Please correct \"game_path\" in %s.", path);
return 0;
}
}
strcpy(gRCT2AddressAppPath, gConfigGeneral.game_path);
safe_strcpy(gRCT2AddressAppPath, gConfigGeneral.game_path, sizeof(gRCT2AddressAppPath));
} else {
strcpy(gRCT2AddressAppPath, gCustomRCT2DataPath);
safe_strcpy(gRCT2AddressAppPath, gCustomRCT2DataPath, sizeof(gRCT2AddressAppPath));
}
strcat(gRCT2AddressAppPath, separator);
path_end_with_separator(gRCT2AddressAppPath, sizeof(gRCT2AddressAppPath));
strcpy(gRCT2AddressSavedGamesPath, gRCT2AddressAppPath);
strcat(gRCT2AddressSavedGamesPath, "Saved Games");
strcat(gRCT2AddressSavedGamesPath, separator);
safe_strcpy(gRCT2AddressSavedGamesPath, gRCT2AddressAppPath, sizeof(gRCT2AddressSavedGamesPath));
safe_strcat_path(gRCT2AddressSavedGamesPath, "Saved Games", sizeof(gRCT2AddressSavedGamesPath));
path_end_with_separator(gRCT2AddressSavedGamesPath, sizeof(gRCT2AddressSavedGamesPath));
strcpy(gRCT2AddressScenariosPath, gRCT2AddressAppPath);
strcat(gRCT2AddressScenariosPath, "Scenarios");
strcat(gRCT2AddressScenariosPath, separator);
strcat(gRCT2AddressScenariosPath, "*.SC6");
safe_strcpy(gRCT2AddressScenariosPath, gRCT2AddressAppPath, sizeof(gRCT2AddressScenariosPath));
safe_strcat_path(gRCT2AddressScenariosPath, "Scenarios", sizeof(gRCT2AddressScenariosPath));
safe_strcat_path(gRCT2AddressScenariosPath, "*.SC6", sizeof(gRCT2AddressScenariosPath));
strcpy(gRCT2AddressLandscapesPath, gRCT2AddressAppPath);
strcat(gRCT2AddressLandscapesPath, "Landscapes");
strcat(gRCT2AddressLandscapesPath, separator);
strcat(gRCT2AddressLandscapesPath, "*.SC6");
safe_strcpy(gRCT2AddressLandscapesPath, gRCT2AddressAppPath, sizeof(gRCT2AddressLandscapesPath));
safe_strcat_path(gRCT2AddressLandscapesPath, "Landscapes", sizeof(gRCT2AddressLandscapesPath));
safe_strcat_path(gRCT2AddressLandscapesPath, "*.SC6", sizeof(gRCT2AddressLandscapesPath));
strcpy(gRCT2AddressObjectDataPath, gRCT2AddressAppPath);
strcat(gRCT2AddressObjectDataPath, "ObjData");
strcat(gRCT2AddressObjectDataPath, separator);
strcat(gRCT2AddressObjectDataPath, "*.DAT");
safe_strcpy(gRCT2AddressObjectDataPath, gRCT2AddressAppPath, sizeof(gRCT2AddressObjectDataPath));
safe_strcat_path(gRCT2AddressObjectDataPath, "ObjData", sizeof(gRCT2AddressObjectDataPath));
safe_strcat_path(gRCT2AddressObjectDataPath, "*.DAT", sizeof(gRCT2AddressObjectDataPath));
strcpy(gRCT2AddressTracksPath, gRCT2AddressAppPath);
strcat(gRCT2AddressTracksPath, "Tracks");
strcat(gRCT2AddressTracksPath, separator);
strcat(gRCT2AddressTracksPath, "*.TD?");
safe_strcpy(gRCT2AddressTracksPath, gRCT2AddressAppPath, sizeof(gRCT2AddressTracksPath));
safe_strcat_path(gRCT2AddressTracksPath, "Tracks", sizeof(gRCT2AddressTracksPath));
safe_strcat_path(gRCT2AddressTracksPath, "*.TD?", sizeof(gRCT2AddressTracksPath));
strcpy(gRCT2AddressSavedGamesPath2, gRCT2AddressSavedGamesPath);
safe_strcpy(gRCT2AddressSavedGamesPath2, gRCT2AddressSavedGamesPath, sizeof(gRCT2AddressSavedGamesPath2));
return 1;
}
void substitute_path(char *dest, const char *path, const char *filename)
void substitute_path(char *dest, size_t size, const char *path, const char *filename)
{
while (*path != '*') {
size_t written = 0;
while (*path != '*' && *path != '\0' && written < size) {
*dest++ = *path++;
++written;
}
strcpy(dest, filename);
safe_strcpy(dest, filename, size - written);
}
/**
@ -331,7 +327,7 @@ static void rct2_draw_fps(rct_drawpixelinfo *dpi)
ch = utf8_write_codepoint(ch, FORMAT_OUTLINE);
ch = utf8_write_codepoint(ch, FORMAT_WHITE);
sprintf(ch, "%d", _currentFPS);
snprintf(ch, 64 - (ch - buffer), "%d", _currentFPS);
// Draw Text
int stringWidth = gfx_get_string_width(buffer);
@ -351,7 +347,7 @@ bool rct2_open_file(const char *path)
extension++;
if (_stricmp(extension, "sv6") == 0) {
strcpy((char*)gRCT2AddressSavedGamesPath2, path);
safe_strcpy((char*)gRCT2AddressSavedGamesPath2, path, sizeof(gRCT2AddressSavedGamesPath2));
if (game_load_save(path)) {
gFirstTimeSave = 0;
return true;
@ -359,7 +355,7 @@ bool rct2_open_file(const char *path)
} else if (_stricmp(extension, "sc6") == 0) {
// TODO scenario install
rct_scenario_basic scenarioBasic;
strcpy(scenarioBasic.path, path);
safe_strcpy(scenarioBasic.path, path, sizeof(scenarioBasic.path));
if (scenario_load_and_play_from_path(scenarioBasic.path)) {
return true;
}
@ -471,7 +467,7 @@ void rct2_update()
const utf8 *get_file_path(int pathId)
{
static utf8 path[MAX_PATH];
strcpy(path, gRCT2AddressAppPath);
safe_strcpy(path, gRCT2AddressAppPath, sizeof(path));
safe_strcat_path(path, RCT2FilePaths[pathId], sizeof(path));
return path;
}

View File

@ -292,7 +292,7 @@ int rct2_init_directories();
int rct2_startup_checks();
void rct2_dispose();
void rct2_update();
void substitute_path(char *dest, const char *path, const char *filename);
void substitute_path(char *dest, size_t size, const char *path, const char *filename);
int check_mutex();
int check_file_paths();
int check_file_path(int pathId);

View File

@ -38,6 +38,7 @@ extern "C"
#include "../ride/ride_ratings.h"
#include "../scenario.h"
#include "../util/sawyercoding.h"
#include "../util/util.h"
#include "../world/climate.h"
#include "../world/map_animation.h"
#include "../world/park.h"
@ -381,7 +382,7 @@ void S6Exporter::Export()
memcpy(_s6.park_entrance_y, gParkEntranceY, sizeof(_s6.park_entrance_y));
memcpy(_s6.park_entrance_z, gParkEntranceZ, sizeof(_s6.park_entrance_z));
memcpy(_s6.park_entrance_direction, gParkEntranceDirection, sizeof(_s6.park_entrance_direction));
strncpy(_s6.scenario_filename, _scenarioFileName, sizeof(_s6.scenario_filename) - 1);
safe_strcpy(_s6.scenario_filename, _scenarioFileName, sizeof(_s6.scenario_filename));
memcpy(_s6.saved_expansion_pack_names, gScenarioExpansionPacks, sizeof(_s6.saved_expansion_pack_names));
memcpy(_s6.banners, gBanners, sizeof(_s6.banners));
memcpy(_s6.custom_strings, gUserStrings, sizeof(_s6.custom_strings));

View File

@ -263,7 +263,7 @@ rct_ride_entry *get_ride_entry_by_ride(rct_ride *ride)
if (type == NULL)
{
char oldname[128];
format_string(oldname, ride->name, &ride->name_arguments);
format_string(oldname, 128, ride->name, &ride->name_arguments);
log_error("Invalid ride subtype for ride %s", oldname);
}
return type;
@ -5607,7 +5607,7 @@ void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi
*ebx = MONEY32_UNDEFINED;
return;
}
format_string(oldName, ride->name, &ride->name_arguments);
format_string(oldName, 128, ride->name, &ride->name_arguments);
if (strcmp(oldName, newName) == 0) {
*ebx = 0;
return;
@ -5811,7 +5811,7 @@ static bool ride_name_exists(char *name)
int i;
FOR_ALL_RIDES(i, ride) {
format_string(buffer, ride->name, &ride->name_arguments);
format_string(buffer, 256, ride->name, &ride->name_arguments);
if (strcmp(buffer, name) == 0) {
return true;
}
@ -6015,7 +6015,7 @@ foundRideEntry:
name_args.number = 0;
do {
name_args.number++;
format_string(rideNameBuffer, 1, &name_args);
format_string(rideNameBuffer, 256, 1, &name_args);
} while (ride_name_exists(rideNameBuffer));
ride->name = 1;
ride->name_arguments_type_name = name_args.type_name;
@ -6031,7 +6031,7 @@ foundRideEntry:
rct_string_id rideNameStringId = 0;
for (int i = 0; i < 100; i++) {
ride->name_arguments_number++;
format_string(rideNameBuffer, ride->name, &ride->name_arguments);
format_string(rideNameBuffer, 256, ride->name, &ride->name_arguments);
rideNameStringId = user_string_allocate(4, rideNameBuffer);
if (rideNameStringId != 0) {
@ -8589,7 +8589,7 @@ void ride_reset_all_names()
name_args.number = 0;
do {
name_args.number++;
format_string(rideNameBuffer, 1, &name_args);
format_string(rideNameBuffer, 256, 1, &name_args);
} while (ride_name_exists(rideNameBuffer));
ride->name = 1;

View File

@ -180,15 +180,15 @@ bool track_design_index_rename(const utf8 *path, const utf8 *newName)
}
utf8 newPath[MAX_PATH];
const char *lastPathSep = strrchr(path, platform_get_path_separator());
const char *lastPathSep = strrchr(path, *PATH_SEPARATOR);
if (lastPathSep == NULL) {
gGameCommandErrorText = STR_CANT_RENAME_TRACK_DESIGN;
return false;
}
size_t directoryLength = (size_t)(lastPathSep - path + 1);
memcpy(newPath, path, directoryLength);
strcpy(newPath + directoryLength, newName);
strcat(newPath, ".td6");
safe_strcpy(newPath + directoryLength, newName, sizeof(newPath) - directoryLength);
path_append_extension(newPath, ".td6", sizeof(newPath));
if (!platform_file_move(path, newPath)) {
gGameCommandErrorText = STR_ANOTHER_FILE_EXISTS_WITH_NAME_OR_FILE_IS_WRITE_PROTECTED;
@ -271,7 +271,7 @@ static void track_design_index_scan()
track_design_index_include(directory);
// Get track directory from user directory
platform_get_user_directory(directory, "track");
platform_get_user_directory(directory, "track", sizeof(directory));
track_design_index_include(directory);
// Sort items by ride type then by filename
@ -360,6 +360,6 @@ static void track_design_index_dispose()
static void track_design_index_get_path(utf8 * buffer, size_t bufferLength)
{
platform_get_user_directory(buffer, NULL);
safe_strcat(buffer, "tracks.idx", bufferLength);
platform_get_user_directory(buffer, NULL, bufferLength);
safe_strcat_path(buffer, "tracks.idx", bufferLength);
}

View File

@ -172,7 +172,7 @@ bool track_design_save(uint8 rideIndex)
}
utf8 track_name[MAX_PATH];
format_string(track_name, ride->name, &ride->name_arguments);
format_string(track_name, MAX_PATH, ride->name, &ride->name_arguments);
window_loadsave_open(LOADSAVETYPE_TRACK | LOADSAVETYPE_SAVE, track_name);
gLoadSaveCallback = track_design_save_callback;

View File

@ -237,15 +237,15 @@ void scenario_begin()
char *buffer = gCommonStringFormatBuffer;
// Set localised park name
format_string(buffer, stex->park_name, 0);
format_string(buffer, 256, stex->park_name, 0);
park_set_name(buffer);
// Set localised scenario name
format_string(buffer, stex->scenario_name, 0);
format_string(buffer, 256, stex->scenario_name, 0);
safe_strcpy(gScenarioName, buffer, 64);
// Set localised scenario details
format_string(buffer, stex->details, 0);
format_string(buffer, 256, stex->details, 0);
safe_strcpy(gScenarioDetails, buffer, 256);
}
}
@ -253,15 +253,15 @@ void scenario_begin()
// Set the last saved game path
char parkName[128];
format_string(parkName, gParkName, &gParkNameArgs);
format_string(parkName, 128, gParkName, &gParkNameArgs);
platform_get_user_directory(gScenarioSavePath, "save");
strncat(gScenarioSavePath, parkName, sizeof(gScenarioSavePath) - strlen(gScenarioSavePath) - 1);
strncat(gScenarioSavePath, ".sv6", sizeof(gScenarioSavePath) - strlen(gScenarioSavePath) - 1);
platform_get_user_directory(gScenarioSavePath, "save", sizeof(gScenarioSavePath));
safe_strcat_path(gScenarioSavePath, parkName, sizeof(gScenarioSavePath));
path_append_extension(gScenarioSavePath, ".sv6", sizeof(gScenarioSavePath));
strcpy(gRCT2AddressSavedGamesPath2, gRCT2AddressSavedGamesPath);
strcpy(gRCT2AddressSavedGamesPath2 + strlen(gRCT2AddressSavedGamesPath2), gScenarioSavePath);
strcat(gRCT2AddressSavedGamesPath2, ".SV6");
safe_strcpy(gRCT2AddressSavedGamesPath2, gRCT2AddressSavedGamesPath, MAX_PATH);
safe_strcat_path(gRCT2AddressSavedGamesPath2, gScenarioSavePath, MAX_PATH);
path_append_extension(gRCT2AddressSavedGamesPath2, ".SV6", MAX_PATH);
gCurrentExpenditure = 0;
gCurrentProfit = 0;
@ -270,7 +270,7 @@ void scenario_begin()
gScenarioCompletedCompanyValue = MONEY32_UNDEFINED;
gTotalAdmissions = 0;
gTotalIncomeFromAdmissions = 0;
strcpy(gScenarioCompletedBy, "?");
safe_strcpy(gScenarioCompletedBy, "?", sizeof(gScenarioCompletedBy));
park_reset_history();
finance_reset_history();
award_reset();
@ -312,7 +312,7 @@ static void scenario_end()
void scenario_set_filename(const char *value)
{
substitute_path(_scenarioPath, gRCT2AddressScenariosPath, value);
substitute_path(_scenarioPath, sizeof(_scenarioPath), gRCT2AddressScenariosPath, value);
_scenarioFileName = path_get_filename(_scenarioPath);
}
@ -679,14 +679,14 @@ int scenario_prepare_for_save()
rct_stex_entry* stex = g_stexEntries[0];
if ((intptr_t)stex != -1) {
char buffer[256];
format_string(buffer, stex->scenario_name, NULL);
format_string(buffer, 256, stex->scenario_name, NULL);
safe_strcpy(gS6Info.name, buffer, sizeof(gS6Info.name));
memcpy(&gS6Info.entry, &object_entry_groups[OBJECT_TYPE_SCENARIO_TEXT].entries[0], sizeof(rct_object_entry));
}
if (gS6Info.name[0] == 0)
format_string(gS6Info.name, gParkName, &gParkNameArgs);
format_string(gS6Info.name, 64, gParkName, &gParkNameArgs);
gS6Info.objective_type = gScenarioObjectiveType;
gS6Info.objective_arg_1 = gScenarioObjectiveYear;

View File

@ -38,7 +38,7 @@ static int scenario_list_sort_by_category(const void *a, const void *b);
static int scenario_list_sort_by_index(const void *a, const void *b);
static bool scenario_scores_load();
static void scenario_scores_legacy_get_path(utf8 *outPath);
static void scenario_scores_legacy_get_path(utf8 *outPath, size_t size);
static bool scenario_scores_legacy_load(const utf8 *path);
static void scenario_highscore_remove(scenario_highscore_entry *higscore);
static void scenario_highscore_list_dispose();
@ -61,14 +61,14 @@ void scenario_load_list()
scenario_list_include(directory);
// Get scenario directory from user directory
platform_get_user_directory(directory, "scenario");
platform_get_user_directory(directory, "scenario", sizeof(directory));
scenario_list_include(directory);
scenario_list_sort();
scenario_scores_load();
utf8 scoresPath[MAX_PATH];
scenario_scores_legacy_get_path(scoresPath);
scenario_scores_legacy_get_path(scoresPath, sizeof(scoresPath));
scenario_scores_legacy_load(scoresPath);
scenario_scores_legacy_load(get_file_path(PATH_ID_SCORES));
}
@ -289,19 +289,19 @@ scenario_index_entry *scenario_list_find_by_path(const utf8 *path)
/**
* Gets the path for the scenario scores path.
*/
static void scenario_scores_get_path(utf8 *outPath)
static void scenario_scores_get_path(utf8 *outPath, size_t size)
{
platform_get_user_directory(outPath, NULL);
strcat(outPath, "highscores.dat");
platform_get_user_directory(outPath, NULL, size);
safe_strcat_path(outPath, "highscores.dat", size);
}
/**
* Gets the path for the scenario scores path.
*/
static void scenario_scores_legacy_get_path(utf8 *outPath)
static void scenario_scores_legacy_get_path(utf8 *outPath, size_t size)
{
platform_get_user_directory(outPath, NULL);
strcat(outPath, "scores.dat");
platform_get_user_directory(outPath, NULL, size);
safe_strcat_path(outPath, "scores.dat", size);
}
/**
@ -380,7 +380,7 @@ static bool scenario_scores_legacy_load(const utf8 *path)
static bool scenario_scores_load()
{
utf8 scoresPath[MAX_PATH];
scenario_scores_get_path(scoresPath);
scenario_scores_get_path(scoresPath, sizeof(scoresPath));
// Load scores file
SDL_RWops *file = SDL_RWFromFile(scoresPath, "rb");
@ -431,7 +431,7 @@ static bool scenario_scores_load()
bool scenario_scores_save()
{
utf8 scoresPath[MAX_PATH];
scenario_scores_get_path(scoresPath);
scenario_scores_get_path(scoresPath, sizeof(scoresPath));
SDL_RWops *file = SDL_RWFromFile(scoresPath, "wb");
if (file == NULL) {

View File

@ -366,7 +366,6 @@ static void title_do_next_script_opcode()
case TITLE_SCRIPT_LOAD:
{
char *ch, filename[32], path[MAX_PATH];
char separator = platform_get_path_separator();
// Get filename
ch = filename;
@ -379,12 +378,11 @@ static void title_do_next_script_opcode()
safe_strcpy(path, gConfigTitleSequences.presets[_scriptCurrentPreset].path, MAX_PATH);
}
else {
platform_get_user_directory(path, "title sequences");
strcat(path, gConfigTitleSequences.presets[_scriptCurrentPreset].name);
strncat(path, &separator, 1);
platform_get_user_directory(path, "title sequences", sizeof(path));
safe_strcat_path(path, gConfigTitleSequences.presets[_scriptCurrentPreset].name, sizeof(path));
}
strcat(path, filename);
safe_strcat_path(path, filename, sizeof(path));
if (title_load_park(path)) {
_scriptNoLoadsSinceRestart = 0;
gTitleScriptSave = gConfigTitleSequences.presets[gCurrentPreviewTitleSequence].commands[gTitleScriptCommand].saveIndex;
@ -504,7 +502,7 @@ void DrawOpenRCT2(rct_drawpixelinfo *dpi, int x, int y)
gfx_draw_string(dpi, buffer, 0, x + 5, y + 5 - 13);
// Write platform information
sprintf(ch, "%s (%s)", OPENRCT2_PLATFORM, OPENRCT2_ARCHITECTURE);
snprintf(ch, 256 - (ch - buffer), "%s (%s)", OPENRCT2_PLATFORM, OPENRCT2_ARCHITECTURE);
gfx_draw_string(dpi, buffer, 0, x + 5, y + 5);
}
@ -624,11 +622,10 @@ static uint8 *title_script_load()
char parts[3 * 128], *token, *part1, *part2, *src;
utf8 path[MAX_PATH];
utf8 dataPath[MAX_PATH];
utf8 filePath[] = "title/script.txt";
platform_get_openrct_data_path(dataPath);
sprintf(path, "%s%c%s", dataPath, platform_get_path_separator(), filePath);
platform_get_openrct_data_path(path, sizeof(path));
safe_strcat_path(path, "title", MAX_PATH);
safe_strcat_path(path, "script.txt", MAX_PATH);
log_verbose("loading title script, %s", path);
file = SDL_RWFromFile(path, "r");
if (file == NULL) {

View File

@ -65,7 +65,7 @@ bool filename_valid_characters(const utf8 *filename)
utf8 *path_get_directory(const utf8 *path)
{
// Find the last slash or backslash in the path
char *filename = strrchr(path, platform_get_path_separator());
char *filename = strrchr(path, *PATH_SEPARATOR);
// If the path is invalid (e.g. just a file name), return NULL
if (filename == NULL)
@ -80,7 +80,7 @@ utf8 *path_get_directory(const utf8 *path)
const char *path_get_filename(const utf8 *path)
{
// Find last slash or backslash in the path
char *filename = strrchr(path, platform_get_path_separator());
char *filename = strrchr(path, *PATH_SEPARATOR);
// Checks if the path is valid (e.g. not just a file name)
if (filename == NULL)
@ -112,24 +112,23 @@ const char *path_get_extension(const utf8 *path)
return extension;
}
void path_set_extension(utf8 *path, const utf8 *newExtension)
void path_set_extension(utf8 *path, const utf8 *newExtension, size_t size)
{
// Remove existing extension (check first if there is one)
if (path_get_extension(path) < strrchr(path, '\0'))
path_remove_extension(path);
// Append new extension
path_append_extension(path, newExtension);
path_append_extension(path, newExtension, size);
}
void path_append_extension(utf8 *path, const utf8 *newExtension)
void path_append_extension(utf8 *path, const utf8 *newExtension, size_t size)
{
// Append a dot to the filename if the new extension doesn't start with it
char *endOfString = strrchr(path, '\0');
if (newExtension[0] != '.')
*endOfString++ = '.';
safe_strcat(path, ".", size);
// Append the extension to the path
safe_strcpy(endOfString, newExtension, MAX_PATH - (endOfString - path) - 1);
safe_strcat(path, newExtension, size);
}
void path_remove_extension(utf8 *path)
@ -142,6 +141,14 @@ void path_remove_extension(utf8 *path)
log_warning("No extension found. (path = %s)", path);
}
void path_end_with_separator(utf8 *path, size_t size) {
size_t length = strnlen(path, size);
if (length >= size - 1) return;
if (path[length - 1] != *PATH_SEPARATOR)
safe_strcat(path, PATH_SEPARATOR, size);
}
bool readentirefile(const utf8 *path, void **outBuffer, size_t *outLength)
{
SDL_RWops *fp;
@ -338,18 +345,7 @@ char *safe_strcat(char *destination, const char *source, size_t size)
char *safe_strcat_path(char *destination, const char *source, size_t size)
{
const char pathSeparator = platform_get_path_separator();
size_t length = strnlen(destination, size);
if (length >= size - 1) {
return destination;
}
if (destination[length - 1] != pathSeparator) {
destination[length] = pathSeparator;
destination[length + 1] = '\0';
}
path_end_with_separator(destination, size);
return safe_strcat(destination, source, size);
}

View File

@ -31,9 +31,10 @@ bool filename_valid_characters(const utf8 *filename);
char *path_get_directory(const utf8 *path);
const char *path_get_filename(const utf8 *path);
const char *path_get_extension(const utf8 *path);
void path_set_extension(utf8 *path, const utf8 *newExtension);
void path_append_extension(utf8 *path, const utf8 *newExtension);
void path_set_extension(utf8 *path, const utf8 *newExtension, size_t size);
void path_append_extension(utf8 *path, const utf8 *newExtension, size_t size);
void path_remove_extension(utf8 *path);
void path_end_with_separator(utf8 *path, size_t size);
bool readentirefile(const utf8 *path, void **outBuffer, size_t *outLength);
int bitscanforward(int source);

View File

@ -205,7 +205,8 @@ static bool window_changelog_read_file()
{
window_changelog_dispose_file();
utf8 path[MAX_PATH];
sprintf(path, "%s%cchangelog.txt", gExePath, platform_get_path_separator());
safe_strcpy(path, gExePath, MAX_PATH);
safe_strcat_path(path, "changelog.txt", MAX_PATH);
if (!readentirefile(path, (void**)&_changelogText, &_changelogTextSize)) {
log_error("Unable to read changelog.txt");
return false;

View File

@ -22,6 +22,7 @@
#include "../localisation/localisation.h"
#include "../interface/widget.h"
#include "../interface/window.h"
#include "../util/util.h"
#include "dropdown.h"
enum WINDOW_CUSTOM_CURRENCY_WIDGET_IDX {
@ -238,13 +239,13 @@ static void custom_currency_window_text_input(struct rct_window *w, int widgetIn
char* end;
switch(widgetIndex){
case WIDX_SYMBOL_TEXT:
strncpy(
safe_strcpy(
CurrencyDescriptors[CURRENCY_CUSTOM].symbol_unicode,
text,
CURRENCY_SYMBOL_MAX_SIZE
);
strncpy(
safe_strcpy(
gConfigGeneral.custom_currency_symbol,
CurrencyDescriptors[CURRENCY_CUSTOM].symbol_unicode,
CURRENCY_SYMBOL_MAX_SIZE

View File

@ -133,7 +133,7 @@ void window_dropdown_show_text(int x, int y, int extray, uint8 colour, uint8 fla
// Calculate the longest string width
max_string_width = 0;
for (i = 0; i < num_items; i++) {
format_string(buffer, gDropdownItemsFormat[i], (void*)(&gDropdownItemsArgs[i]));
format_string(buffer, 256, gDropdownItemsFormat[i], (void*)(&gDropdownItemsArgs[i]));
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
string_width = gfx_get_string_width(buffer);
max_string_width = max(string_width, max_string_width);

View File

@ -895,7 +895,7 @@ static void window_editor_inventions_list_scrollpaint(rct_window *w, rct_drawpix
ptr = utf8_write_codepoint(ptr, colour & 0xFF);
}
format_string(ptr, stringId, NULL);
format_string(ptr, 256, stringId, NULL);
if (disableItemMovement) {
gCurrentFontSpriteBase = -1;
@ -931,7 +931,7 @@ static void window_editor_inventions_list_drag_open(rct_research_item *researchI
_editorInventionsListDraggedItem = researchItem;
stringId = research_item_get_name(researchItem->entryIndex & 0xFFFFFF);
format_string(buffer, stringId, NULL);
format_string(buffer, 256, stringId, NULL);
stringWidth = gfx_get_string_width(buffer);
window_editor_inventions_list_drag_widgets[0].right = stringWidth;

View File

@ -1446,13 +1446,13 @@ static void window_editor_object_selection_scrollpaint(rct_window *w, rct_drawpi
if (ridePage) {
// Draw ride type
rct_string_id rideTypeStringId = get_ride_type_string_id(listItem->repositoryItem);
strcpy(buffer, language_get_string(rideTypeStringId));
safe_strcpy(buffer, language_get_string(rideTypeStringId), 256 - (buffer - bufferWithColour));
gfx_draw_string(dpi, bufferWithColour, colour, x, y);
x = w->widgets[WIDX_LIST_SORT_RIDE].left - w->widgets[WIDX_LIST].left;
}
// Draw text
strcpy(buffer, listItem->repositoryItem->Name);
safe_strcpy(buffer, listItem->repositoryItem->Name, 256 - (buffer - bufferWithColour));
if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) {
while (*buffer != 0 && *buffer != 9)
buffer++;
@ -1629,7 +1629,7 @@ static int window_editor_object_selection_select_object(uint8 bh, int flags, con
if (bh != 0 && !(flags & (1 << 1))) {
char objectName[64];
object_create_identifier_name(objectName, &item->ObjectEntry);
object_create_identifier_name(objectName, 64, &item->ObjectEntry);
set_format_arg(0, const char *, objectName);
set_object_selection_error(bh, STR_OBJECT_SELECTION_ERR_SHOULD_SELECT_X_FIRST);
return 0;

View File

@ -794,10 +794,10 @@ static void window_editor_objective_options_main_textinput(rct_window *w, int wi
park_set_name(text);
if (gS6Info.name[0] == 0)
format_string(gS6Info.name, gParkName, &gParkNameArgs);
format_string(gS6Info.name, 64, gParkName, &gParkNameArgs);
break;
case WIDX_SCENARIO_NAME:
strncpy(gS6Info.name, text, 64);
safe_strcpy(gS6Info.name, text, 64);
if (strnlen(gS6Info.name, 64) == 64)
{
gS6Info.name[64 - 1] = '\0';
@ -806,7 +806,7 @@ static void window_editor_objective_options_main_textinput(rct_window *w, int wi
window_invalidate(w);
break;
case WIDX_DETAILS:
strncpy(gS6Info.details, text, 256);
safe_strcpy(gS6Info.details, text, 256);
if (strnlen(gS6Info.details, 256) == 256)
{
gS6Info.details[256 - 1] = '\0';

View File

@ -87,14 +87,14 @@ void window_error_open(rct_string_id title, rct_string_id message)
// Format the title
dst = utf8_write_codepoint(dst, FORMAT_BLACK);
if (title != STR_NONE) {
format_string(dst, title, gCommonFormatArgs);
format_string(dst, 512 - (dst - _window_error_text), title, gCommonFormatArgs);
dst = get_string_end(dst);
}
// Format the message
if (message != STR_NONE) {
dst = utf8_write_codepoint(dst, FORMAT_NEWLINE);
format_string(dst, message, gCommonFormatArgs);
format_string(dst, 512 - (dst - _window_error_text), message, gCommonFormatArgs);
dst = get_string_end(dst);
}

View File

@ -378,15 +378,15 @@ static void window_install_track_design(rct_window *w)
{
utf8 destPath[MAX_PATH];
platform_get_user_directory(destPath, "track");
platform_get_user_directory(destPath, "track", sizeof(destPath));
if (!platform_ensure_directory_exists(destPath)) {
log_error("Unable to create directory '%s'", destPath);
window_error_open(STR_CANT_SAVE_TRACK_DESIGN, STR_NONE);
return;
}
strcat(destPath, _trackName);
strcat(destPath, ".td6");
safe_strcat_path(destPath, _trackName, sizeof(destPath));
path_append_extension(destPath, ".td6", sizeof(destPath));
if (platform_file_exists(destPath)) {
log_info("%s already exists, prompting user for a different track design name", destPath);

View File

@ -139,12 +139,12 @@ static void window_loadsave_sort_list(int index, int endIndex);
static rct_window *window_overwrite_prompt_open(const char *name, const char *path);
static int window_loadsave_get_dir(utf8 *last_save, char *path, const char *subdir)
static int window_loadsave_get_dir(utf8 *last_save, char *path, const char *subdir, size_t pathSize)
{
if (last_save && platform_ensure_directory_exists(last_save))
safe_strcpy(path, last_save, MAX_PATH);
safe_strcpy(path, last_save, pathSize);
else
platform_get_user_directory(path, subdir);
platform_get_user_directory(path, subdir, pathSize);
if (!platform_ensure_directory_exists(path)) {
log_error("Unable to create save directory.");
@ -183,28 +183,28 @@ rct_window *window_loadsave_open(int type, char *defaultName)
switch (type & 0x0E) {
case LOADSAVETYPE_GAME:
w->widgets[WIDX_TITLE].text = isSave ? STR_FILE_DIALOG_TITLE_SAVE_GAME : STR_FILE_DIALOG_TITLE_LOAD_GAME;
if (window_loadsave_get_dir(gConfigGeneral.last_save_game_directory, path, "save")) {
if (window_loadsave_get_dir(gConfigGeneral.last_save_game_directory, path, "save", sizeof(path))) {
window_loadsave_populate_list(w, isSave, path, ".sv6");
success = true;
}
break;
case LOADSAVETYPE_LANDSCAPE:
w->widgets[WIDX_TITLE].text = isSave ? STR_FILE_DIALOG_TITLE_SAVE_LANDSCAPE : STR_FILE_DIALOG_TITLE_LOAD_LANDSCAPE;
if (window_loadsave_get_dir(gConfigGeneral.last_save_landscape_directory, path, "landscape")) {
if (window_loadsave_get_dir(gConfigGeneral.last_save_landscape_directory, path, "landscape", sizeof(path))) {
window_loadsave_populate_list(w, isSave, path, ".sc6");
success = true;
}
break;
case LOADSAVETYPE_SCENARIO:
w->widgets[WIDX_TITLE].text = STR_FILE_DIALOG_TITLE_SAVE_SCENARIO;
if (window_loadsave_get_dir(gConfigGeneral.last_save_scenario_directory, path, "scenario")) {
if (window_loadsave_get_dir(gConfigGeneral.last_save_scenario_directory, path, "scenario", sizeof(path))) {
window_loadsave_populate_list(w, isSave, path, ".sc6");
success = true;
}
break;
case LOADSAVETYPE_TRACK:
w->widgets[WIDX_TITLE].text = isSave ? STR_FILE_DIALOG_TITLE_SAVE_TRACK : STR_FILE_DIALOG_TITLE_INSTALL_NEW_TRACK_DESIGN;
if (window_loadsave_get_dir(gConfigGeneral.last_save_track_directory, path, "track")) {
if (window_loadsave_get_dir(gConfigGeneral.last_save_track_directory, path, "track", sizeof(path))) {
window_loadsave_populate_list(w, isSave, path, ".td?");
success = true;
}
@ -233,11 +233,11 @@ static void window_loadsave_close(rct_window *w)
window_close_by_class(WC_LOADSAVE_OVERWRITE_PROMPT);
}
static bool browse(bool isSave, char *path)
static bool browse(bool isSave, char *path, size_t pathSize)
{
safe_strcpy(path, _directory, MAX_PATH);
safe_strcpy(path, _directory, pathSize);
if (isSave)
strcat(path, _defaultName);
safe_strcat_path(path, _defaultName, pathSize);
file_dialog_desc desc = { 0 };
desc.initial_directory = _directory;
@ -269,7 +269,7 @@ static bool browse(bool isSave, char *path)
}
desc.title = language_get_string(title);
return platform_open_common_file_dialog(path, &desc);
return platform_open_common_file_dialog(path, &desc, pathSize);
}
static void window_loadsave_mouseup(rct_window *w, int widgetIndex)
@ -291,7 +291,7 @@ static void window_loadsave_mouseup(rct_window *w, int widgetIndex)
window_text_input_open(w, WIDX_NEW, STR_NONE, STR_FILEBROWSER_NAME_PROMPT, STR_STRING, (uintptr_t)&_defaultName, 64);
break;
case WIDX_BROWSE:
if (browse(isSave, path))
if (browse(isSave, path, sizeof(path)))
window_loadsave_select(w, path);
break;
case WIDX_SORT_NAME:
@ -317,16 +317,16 @@ static void window_loadsave_mouseup(rct_window *w, int widgetIndex)
case WIDX_DEFAULT:
switch (_type & 0x0E) {
case LOADSAVETYPE_GAME:
platform_get_user_directory(path, "save");
platform_get_user_directory(path, "save", sizeof(path));
break;
case LOADSAVETYPE_LANDSCAPE:
platform_get_user_directory(path, "landscape");
platform_get_user_directory(path, "landscape", sizeof(path));
break;
case LOADSAVETYPE_SCENARIO:
platform_get_user_directory(path, "scenario");
platform_get_user_directory(path, "scenario", sizeof(path));
break;
case LOADSAVETYPE_TRACK:
platform_get_user_directory(path, "track");
platform_get_user_directory(path, "track", sizeof(path));
break;
}
@ -411,8 +411,8 @@ static void window_loadsave_textinput(rct_window *w, int widgetIndex, char *text
}
safe_strcpy(path, _directory, sizeof(path));
strncat(path, text, sizeof(path) - strnlen(path, MAX_PATH) - 1);
strncat(path, _extension, sizeof(path) - strnlen(path, MAX_PATH) - 1);
safe_strcat_path(path, text, sizeof(path));
path_append_extension(path, _extension, sizeof(path));
overwrite = 0;
for (i = 0; i < _listItemsCount; i++) {
@ -563,7 +563,7 @@ static void window_loadsave_populate_list(rct_window *w, int includeNewItem, con
// If the drive exists, list it
loadsave_list_item *listItem = &_listItems[_listItemsCount];
sprintf(listItem->path, "%c:%c", 'A' + x, platform_get_path_separator());
snprintf(listItem->path, sizeof(listItem->path), "%c:" PATH_SEPARATOR, 'A' + x);
safe_strcpy(listItem->name, listItem->path, sizeof(listItem->name));
listItem->type = TYPE_DIRECTORY;
@ -572,15 +572,14 @@ static void window_loadsave_populate_list(rct_window *w, int includeNewItem, con
}
}
else {
char separator = platform_get_path_separator();
// Remove the separator at the end of the path, if present
safe_strcpy(_parentDirectory, directory, sizeof(_parentDirectory));
if (_parentDirectory[strlen(_parentDirectory) - 1] == separator)
if (_parentDirectory[strlen(_parentDirectory) - 1] == *PATH_SEPARATOR)
_parentDirectory[strlen(_parentDirectory) - 1] = '\0';
// Remove everything past the now last separator
char *ch = strrchr(_parentDirectory, separator);
char *ch = strrchr(_parentDirectory, *PATH_SEPARATOR);
if (ch != NULL) {
*(ch + 1) = '\0';
} else if (drives) {
@ -588,7 +587,7 @@ static void window_loadsave_populate_list(rct_window *w, int includeNewItem, con
_parentDirectory[0] = '\0';
} else {
// Else, go to the root directory
sprintf(_parentDirectory, "%c", separator);
snprintf(_parentDirectory, MAX_PATH, "%c", *PATH_SEPARATOR);
}
// Disable the Up button if the current directory is the root directory
@ -623,7 +622,7 @@ static void window_loadsave_populate_list(rct_window *w, int includeNewItem, con
char filter[MAX_PATH];
safe_strcpy(filter, directory, sizeof(filter));
safe_strcat_path(filter, "*", sizeof(filter));
safe_strcat(filter, extension, sizeof(filter));
path_append_extension(filter, extension, sizeof(filter));
file_info fileInfo;
fileEnumHandle = platform_enumerate_files_begin(filter);
@ -675,10 +674,10 @@ static void window_loadsave_select(rct_window *w, const char *path)
save_path(&gConfigGeneral.last_save_game_directory, path);
if (gLoadSaveTitleSequenceSave) {
utf8 newName[MAX_PATH];
char *extension = (char*)path_get_extension(path);
const char *extension = path_get_extension(path);
safe_strcpy(newName, path_get_filename(path), MAX_PATH);
if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0)
strcat(newName, ".sv6");
path_append_extension(newName, ".sv6", sizeof(newName));
if (title_sequence_save_exists(gCurrentTitleSequence, newName)) {
set_format_arg(0, intptr_t, (intptr_t)&_listItems[w->selected_list_item].name);
window_text_input_open(w, WIDX_SCROLL, STR_FILEBROWSER_RENAME_SAVE_TITLE, STR_ERROR_EXISTING_NAME, STR_STRING, (uintptr_t)_listItems[w->selected_list_item].name, TITLE_SEQUENCE_MAX_SAVE_LENGTH - 1);
@ -789,10 +788,10 @@ static void window_loadsave_select(rct_window *w, const char *path)
break;
case (LOADSAVETYPE_SAVE | LOADSAVETYPE_TRACK) :
{
char *p = _strdup(path);
path_set_extension(p, "td6");
char p[MAX_PATH];
safe_strcpy(p, path, sizeof(p));
path_set_extension(p, "td6", sizeof(p));
int success = track_design_save_to_file(p);
free(p);
if (success) {
window_close_by_class(WC_LOADSAVE);
@ -913,16 +912,13 @@ static void window_overwrite_prompt_invalidate(rct_window *w)
static void window_overwrite_prompt_paint(rct_window *w, rct_drawpixelinfo *dpi)
{
window_draw_widgets(w, dpi);
rct_string_id templateStringId = STR_PLACEHOLDER;
char *templateString;
templateString = (char*)language_get_string(templateStringId);
strcpy(templateString, _window_overwrite_prompt_name);
set_format_arg(0, rct_string_id, STR_STRING);
set_format_arg(2, char *, _window_overwrite_prompt_name);
int x = w->x + w->width / 2;
int y = w->y + (w->height / 2) - 3;
gfx_draw_string_centred_wrapped(dpi, &templateStringId, x, y, w->width - 4, STR_FILEBROWSER_OVERWRITE_PROMPT, 0);
gfx_draw_string_centred_wrapped(dpi, gCommonFormatArgs, x, y, w->width - 4, STR_FILEBROWSER_OVERWRITE_PROMPT, 0);
}

View File

@ -610,7 +610,7 @@ static void window_multiplayer_players_scrollpaint(rct_window *w, rct_drawpixeli
int colour = 0;
if (i == w->selected_list_item) {
gfx_fill_rect(dpi, 0, y, 800, y + 9, 0x02000031);
safe_strcpy(&buffer[0], network_get_player_name(i), sizeof(buffer));
safe_strcpy(buffer, network_get_player_name(i), sizeof(buffer));
colour = w->colours[2];
} else {
if (network_get_player_flags(i) & NETWORK_PLAYER_FLAG_ISSERVER) {
@ -652,7 +652,7 @@ static void window_multiplayer_players_scrollpaint(rct_window *w, rct_drawpixeli
} else {
lineCh = utf8_write_codepoint(lineCh, FORMAT_RED);
}
sprintf(lineCh, "%d ms", ping);
snprintf(lineCh, sizeof(buffer) - (lineCh - buffer), "%d ms", ping);
gfx_draw_string(dpi, buffer, colour, 356, y - 1);
}
y += 10;
@ -819,11 +819,11 @@ static void window_multiplayer_groups_paint(rct_window *w, rct_drawpixelinfo *dp
rct_widget* widget = &window_multiplayer_groups_widgets[WIDX_DEFAULT_GROUP];
int group = network_get_group_index(network_get_default_group());
if (group != -1) {
char buffer[300] = {0};
char buffer[300];
char* lineCh;
lineCh = buffer;
lineCh = utf8_write_codepoint(lineCh, FORMAT_WINDOW_COLOUR_2);
strcpy(lineCh, network_get_group_name(group));
safe_strcpy(lineCh, network_get_group_name(group), sizeof(buffer) - (lineCh - buffer));
set_format_arg(0, const char *, buffer);
gfx_draw_string_centred_clipped(
dpi,
@ -848,11 +848,11 @@ static void window_multiplayer_groups_paint(rct_window *w, rct_drawpixelinfo *dp
widget = &window_multiplayer_groups_widgets[WIDX_SELECTED_GROUP];
group = network_get_group_index(_selectedGroup);
if (group != -1) {
char buffer[300] = {0};
char buffer[300];
char* lineCh;
lineCh = buffer;
lineCh = utf8_write_codepoint(lineCh, FORMAT_WINDOW_COLOUR_2);
strcpy(lineCh, network_get_group_name(group));
safe_strcpy(lineCh, network_get_group_name(group), sizeof(buffer) - (lineCh - buffer));
set_format_arg(0, const char *, buffer);
gfx_draw_string_centred_clipped(
dpi,

View File

@ -145,7 +145,7 @@ static void window_network_status_update(rct_window *w)
static void window_network_status_textinput(rct_window *w, int widgetIndex, char *text)
{
strcpy(_password, "");
_password[0] = '\0';
switch (widgetIndex) {
case WIDX_PASSWORD:
if (text != NULL)
@ -177,7 +177,7 @@ static void window_network_status_paint(rct_window *w, rct_drawpixelinfo *dpi)
char buffer[sizeof(window_network_status_text) + 10];
char* lineCh = buffer;
lineCh = utf8_write_codepoint(lineCh, FORMAT_BLACK);
strcpy(lineCh, window_network_status_text);
safe_strcpy(lineCh, window_network_status_text, sizeof(buffer) - (lineCh - buffer));
gfx_clip_string(buffer, w->widgets[WIDX_BACKGROUND].right - 50);
int x = w->x + (w->width / 2);
int y = w->y + (w->height / 2);

View File

@ -114,8 +114,8 @@ static int ride_name_compare(const void *a, const void *b)
rideA = get_ride(*((uint8*)a));
rideB = get_ride(*((uint8*)b));
format_string(rideAName, rideA->name, &rideA->name_arguments);
format_string(rideBName, rideB->name, &rideB->name_arguments);
format_string(rideAName, 256, rideA->name, &rideA->name_arguments);
format_string(rideBName, 256, rideB->name, &rideB->name_arguments);
return _strcmpi(rideAName, rideBName);
}

View File

@ -33,6 +33,7 @@
#include "../ride/ride_data.h"
#include "../sprites.h"
#include "../ride/track_data.h"
#include "../util/util.h"
static uint8 _windowNewRideCurrentTab;
static ride_list_item _windowNewRideHighlightedItem[6];
@ -311,7 +312,7 @@ static void window_new_ride_populate_list()
}
char preferredVehicleName[9];
strcpy(preferredVehicleName," ");
safe_strcpy(preferredVehicleName, " ", sizeof(preferredVehicleName));
if (ride_type_is_invented(rideType)) {
int dh = 0;
@ -338,11 +339,11 @@ static void window_new_ride_populate_list()
// Skip if the vehicle isn't the preferred vehicle for this generic track type
if (gConfigInterface.select_by_track_type && (!(rideEntry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE) || rideTypeShouldLoseSeparateFlag(rideEntry))) {
if (strcmp(preferredVehicleName, " \0") == 0) {
strcpy(preferredVehicleName, rideEntryName);
safe_strcpy(preferredVehicleName, rideEntryName, sizeof(preferredVehicleName));
preferredVehicleName[8] = 0;
} else {
if (vehicle_preference_compare(rideType, preferredVehicleName, rideEntryName) == 1) {
strcpy(preferredVehicleName, rideEntryName);
safe_strcpy(preferredVehicleName, rideEntryName, sizeof(preferredVehicleName));
preferredVehicleName[8] = 0;
} else {
continue;

View File

@ -360,11 +360,11 @@ void window_player_overview_paint(rct_window *w, rct_drawpixelinfo *dpi)
int groupindex = network_get_group_index(network_get_player_group(player));
if (groupindex != -1) {
rct_widget* widget = &window_player_overview_widgets[WIDX_GROUP];
char buffer[300] = {0};
char buffer[300];
char* lineCh;
lineCh = buffer;
lineCh = utf8_write_codepoint(lineCh, FORMAT_WINDOW_COLOUR_2);
strcpy(lineCh, network_get_group_name(groupindex));
safe_strcpy(lineCh, network_get_group_name(groupindex), sizeof(buffer) - (lineCh - buffer));
set_format_arg(0, const char *, buffer);
gfx_draw_string_centred_clipped(
@ -385,7 +385,7 @@ void window_player_overview_paint(rct_window *w, rct_drawpixelinfo *dpi)
set_format_arg(0, rct_string_id, STR_PING);
gfx_draw_string_left(dpi, STR_WINDOW_COLOUR_2_STRINGID, gCommonFormatArgs, 0, x, y);
char ping[64];
sprintf(ping, "%d ms", network_get_player_ping(player));
snprintf(ping, 64, "%d ms", network_get_player_ping(player));
gfx_draw_string(dpi, ping, w->colours[2], x + 30, y);
// Draw last action

View File

@ -729,10 +729,10 @@ static void window_ride_list_refresh_list(rct_window *w)
int current_list_position = list_index;
switch (w->list_information_type) {
case INFORMATION_TYPE_STATUS:
format_string_to_upper(bufferA, ride->name, &ride->name_arguments);
format_string_to_upper(bufferA, 128, ride->name, &ride->name_arguments);
while (--current_list_position >= 0) {
otherRide = get_ride(w->list_item_positions[current_list_position]);
format_string_to_upper(bufferB, otherRide->name, &otherRide->name_arguments);
format_string_to_upper(bufferB, 128, otherRide->name, &otherRide->name_arguments);
if (strcmp(bufferA, bufferB) >= 0)
break;

View File

@ -480,7 +480,7 @@ static void window_server_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi
char players[32];
players[0] = 0;
if (serverDetails->maxplayers > 0) {
sprintf(players, "%d/%d", serverDetails->players, serverDetails->maxplayers);
snprintf(players, 32, "%d/%d", serverDetails->players, serverDetails->maxplayers);
}
int numPlayersStringWidth = gfx_get_string_width(players);
gfx_draw_string(dpi, players, w->colours[1], right - numPlayersStringWidth, y + 3);
@ -525,8 +525,8 @@ static void server_list_load_server_entries()
utf8 path[MAX_PATH];
SDL_RWops *file;
platform_get_user_directory(path, NULL);
strcat(path, "servers.cfg");
platform_get_user_directory(path, NULL, sizeof(path));
safe_strcat_path(path, "servers.cfg", sizeof(path));
file = SDL_RWFromFile(path, "rb");
if (file == NULL) {
@ -564,8 +564,8 @@ static void server_list_save_server_entries()
utf8 path[MAX_PATH];
SDL_RWops *file;
platform_get_user_directory(path, NULL);
strcat(path, "servers.cfg");
platform_get_user_directory(path, NULL, sizeof(path));
safe_strcat_path(path, "servers.cfg", sizeof(path));
file = SDL_RWFromFile(path, "wb");
if (file == NULL) {

View File

@ -140,7 +140,7 @@ void window_server_start_open()
window->page = 0;
window->list_information_type = 0;
sprintf(_port, "%u", gConfigNetwork.default_port);
snprintf(_port, 7, "%u", gConfigNetwork.default_port);
safe_strcpy(_name, gConfigNetwork.server_name, sizeof(_name));
}

View File

@ -256,14 +256,13 @@ static void window_shortcut_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, i
gfx_fill_rect(dpi, 0, y, 800, y + 9, 0x2000031);
}
// TODO: How does this work? 2525 is '???'
rct_string_id templateStringId = STR_SHORTCUT_KEY_UNKNOWN;
char *templateString = (char*)language_get_string(templateStringId);
keyboard_shortcut_format_string(templateString, gShortcutKeys[i]);
char templateString[128];
keyboard_shortcut_format_string(templateString, 128, gShortcutKeys[i]);
set_format_arg(0, rct_string_id, STR_SHORTCUT_ENTRY_FORMAT);
set_format_arg(2, rct_string_id, ShortcutStringIds[i]);
set_format_arg(4, rct_string_id, templateStringId);
set_format_arg(4, rct_string_id, STR_STRING);
set_format_arg(6, char *, templateString);
gfx_draw_string_left(dpi, format, gCommonFormatArgs, 0, 0, y - 1);
}
}

View File

@ -107,11 +107,7 @@ void window_text_input_open(rct_window* call_w, int call_widget, rct_string_id t
// Enter in the the text input buffer any existing
// text.
if (existing_text != STR_NONE)
format_string(text_input, existing_text, &existing_args);
// In order to prevent strings that exceed the maxLength
// from crashing the game.
text_input[maxLength - 1] = '\0';
format_string(text_input, maxLength, existing_text, &existing_args);
utf8_remove_format_codes(text_input, false);

View File

@ -573,8 +573,8 @@ static void window_tile_inspector_paint(rct_window *w, rct_drawpixelinfo *dpi)
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_CHOOSE_MSG, NULL, 12, x, y);
} else {
char buffer[256];
sprintf(
buffer,
snprintf(
buffer, 256,
"X: %d, Y: %d",
window_tile_inspector_tile_x,
window_tile_inspector_tile_y
@ -614,8 +614,8 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo *
switch (type) {
case MAP_ELEMENT_TYPE_SURFACE:
sprintf(
buffer,
snprintf(
buffer, 256,
"Surface (%s, %s)",
language_get_string(TerrainTypes[map_element_get_terrain(element)]),
language_get_string(TerrainEdgeTypes[map_element_get_terrain_edge(element)])
@ -628,16 +628,16 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo *
const uint8 pathHasScenery = footpath_element_has_path_scenery(element);
const uint8 pathAdditionType = footpath_element_get_path_scenery_index(element);
if (footpath_element_is_queue(element)) {
sprintf(
buffer, "Queue (%s)%s%s for (%d)",
snprintf(
buffer, 256, "Queue (%s)%s%s for (%d)",
language_get_string(get_footpath_entry(pathType)->string_idx), // Path name
pathHasScenery ? " with " : "", // Adds " with " when there is something on the path
pathHasScenery ? language_get_string(get_footpath_item_entry(pathAdditionType)->name) : "", // Path addition name
element->properties.path.ride_index // Ride index for queue
);
} else {
sprintf(
buffer, "Path (%s)%s%s",
snprintf(
buffer, 256, "Path (%s)%s%s",
language_get_string(get_footpath_entry(pathType)->string_idx), // Path name
pathHasScenery ? " with " : "", // Adds " with " when there is something on the path
pathHasScenery ? language_get_string(get_footpath_item_entry(pathAdditionType)->name) : "" // Path addition name
@ -647,32 +647,32 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo *
type_name = buffer;
break;
case MAP_ELEMENT_TYPE_TRACK:
sprintf(
buffer,
snprintf(
buffer, 256,
"Track (%s)",
language_get_string(RideNaming[get_ride(element->properties.track.ride_index)->type].name)
);
type_name = buffer;
break;
case MAP_ELEMENT_TYPE_SCENERY:
sprintf(
buffer,
snprintf(
buffer, 256,
"Scenery (%s)",
language_get_string(get_small_scenery_entry(element->properties.scenery.type)->name)
);
type_name = buffer;
break;
case MAP_ELEMENT_TYPE_ENTRANCE:
sprintf(
buffer,
snprintf(
buffer, 256,
"Entrance (%s)",
language_get_string(EntranceTypes[element->properties.entrance.type])
);
type_name = buffer;
break;
case MAP_ELEMENT_TYPE_FENCE:
sprintf(
buffer,
snprintf(
buffer, 256,
"Fence (%s)",
language_get_string(get_wall_entry(element->properties.scenery.type)->name)
);
@ -682,8 +682,8 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo *
type_name = "Scenery multiple";
break;
case MAP_ELEMENT_TYPE_BANNER:
sprintf(
buffer,
snprintf(
buffer, 256,
"Banner (%d)",
element->properties.banner.index
);
@ -692,7 +692,7 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo *
case MAP_ELEMENT_TYPE_CORRUPT:
// fall-through
default:
sprintf(buffer, "Unknown (type %d)", type);
snprintf(buffer, 256, "Unknown (type %d)", type);
type_name = buffer;
}

View File

@ -25,6 +25,7 @@
#include "../interface/themes.h"
#include "../interface/title_sequences.h"
#include "../title.h"
#include "../util/util.h"
#include "dropdown.h"
typedef struct TITLE_COMMAND_ORDER {
@ -448,7 +449,7 @@ static void window_title_command_editor_textinput(rct_window *w, int widgetIndex
window_invalidate(w);
}
else {
strcpy(textbox1Buffer, text);
safe_strcpy(textbox1Buffer, text, sizeof(textbox1Buffer));
}
break;
case WIDX_TEXTBOX_X:
@ -459,7 +460,7 @@ static void window_title_command_editor_textinput(rct_window *w, int widgetIndex
window_invalidate(w);
}
else {
strcpy(textbox1Buffer, text);
safe_strcpy(textbox1Buffer, text, sizeof(textbox1Buffer));
}
break;
case WIDX_TEXTBOX_Y:
@ -470,7 +471,7 @@ static void window_title_command_editor_textinput(rct_window *w, int widgetIndex
window_invalidate(w);
}
else {
strcpy(textbox2Buffer, text);
safe_strcpy(textbox2Buffer, text, sizeof(textbox2Buffer));
}
break;
}

View File

@ -295,7 +295,6 @@ void window_title_editor_close(rct_window *w)
static void window_title_editor_mouseup(rct_window *w, int widgetIndex)
{
char path[MAX_PATH];
char separator = platform_get_path_separator();
int defaultPreset, playing, inTitle, i, commandEditorOpen;
defaultPreset = (gCurrentTitleSequence < TITLE_SEQUENCE_DEFAULT_PRESETS);
@ -360,12 +359,11 @@ static void window_title_editor_mouseup(rct_window *w, int widgetIndex)
}
else {
// TODO: This should probably use a constant
platform_get_user_directory(path, "title sequences");
strcat(path, gConfigTitleSequences.presets[gCurrentTitleSequence].name);
strncat(path, &separator, 1);
platform_get_user_directory(path, "title sequences", sizeof(path));
safe_strcat_path(path, gConfigTitleSequences.presets[gCurrentTitleSequence].name, sizeof(path));
}
strcat(path, gConfigTitleSequences.presets[gCurrentTitleSequence].saves[w->selected_list_item]);
safe_strcat_path(path, gConfigTitleSequences.presets[gCurrentTitleSequence].saves[w->selected_list_item], sizeof(path));
game_load_save(path);
window_title_editor_open(1);
}
@ -905,10 +903,10 @@ void window_title_editor_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int
set_format_arg(0, uintptr_t, &title->saves[i]);
if (selected || hover) {
format_string(buffer, STR_STRING, gCommonFormatArgs);
format_string(buffer, 256, STR_STRING, gCommonFormatArgs);
}
else {
format_string(buffer + 1, STR_STRING, gCommonFormatArgs);
format_string(buffer + 1, 255, STR_STRING, gCommonFormatArgs);
buffer[0] = FORMAT_BLACK;
}
set_format_arg(0, uintptr_t, &buffer);
@ -980,10 +978,10 @@ void window_title_editor_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int
}
if ((selected || hover) && !error) {
format_string(buffer, commandName, gCommonFormatArgs);
format_string(buffer, 256, commandName, gCommonFormatArgs);
}
else {
format_string(buffer + 1, commandName, gCommonFormatArgs);
format_string(buffer + 1, 255, commandName, gCommonFormatArgs);
buffer[0] = (error ? ((selected || hover) ? FORMAT_LIGHTPINK : FORMAT_RED) : FORMAT_BLACK);
}
set_format_arg(0, uintptr_t, &buffer);

View File

@ -484,14 +484,16 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo *
bool isDisabled = listItem->scenario.is_locked;
// Draw scenario name
rct_string_id placeholderStringId = STR_PLACEHOLDER;
safe_strcpy((char*)language_get_string(placeholderStringId), scenario->name, 64);
char buffer[64];
safe_strcpy(buffer, scenario->name, sizeof(buffer));
rct_string_id format = isDisabled ? STR_STRINGID : (isHighlighted ? highlighted_format : unhighlighted_format);
set_format_arg(0, rct_string_id, STR_STRING);
set_format_arg(2, char *, buffer);
colour = isDisabled ? w->colours[1] | 0x40 : COLOUR_BLACK;
if (isDisabled) {
gCurrentFontSpriteBase = -1;
}
gfx_draw_string_centred(dpi, format, wide ? 270 : 210, y + 1, colour, &placeholderStringId);
gfx_draw_string_centred(dpi, format, wide ? 270 : 210, y + 1, colour, gCommonFormatArgs);
// Check if scenario is completed
if (isCompleted) {
@ -503,9 +505,10 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo *
if (!str_is_null_or_empty(scenario->highscore->name)) {
completedByName = scenario->highscore->name;
}
safe_strcpy((char*)language_get_string(placeholderStringId), completedByName, 64);
safe_strcpy(buffer, completedByName, 64);
set_format_arg(0, rct_string_id, STR_COMPLETED_BY);
set_format_arg(2, rct_string_id, placeholderStringId);
set_format_arg(2, rct_string_id, STR_STRING);
set_format_arg(4, char *, buffer);
gfx_draw_string_centred(dpi, format, wide ? 270 : 210, y + 11, 0, gCommonFormatArgs);
}
@ -527,7 +530,7 @@ static void draw_category_heading(rct_window *w, rct_drawpixelinfo *dpi, int lef
// Get string dimensions
utf8 *buffer = gCommonStringFormatBuffer;
format_string(buffer, stringId, NULL);
format_string(buffer, 256, stringId, NULL);
int categoryStringHalfWidth = (gfx_get_string_width(buffer) / 2) + 4;
int strLeft = centreX - categoryStringHalfWidth;
int strRight = centreX + categoryStringHalfWidth;

View File

@ -88,7 +88,7 @@ void window_tooltip_show(rct_string_id id, int x, int y)
char* buffer = gCommonStringFormatBuffer;
format_string(buffer, id, gCommonFormatArgs);
format_string(buffer, 256, id, gCommonFormatArgs);
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
int tooltip_text_width;

View File

@ -39,7 +39,7 @@ enum {
static rct_widget window_track_manage_widgets[] = {
{ WWT_FRAME, 0, 0, 249, 0, 43, STR_NONE, STR_NONE },
{ WWT_CAPTION, 0, 1, 248, 1, 14, 3155, STR_WINDOW_TITLE_TIP },
{ WWT_CAPTION, 0, 1, 248, 1, 14, STR_STRING, STR_WINDOW_TITLE_TIP },
{ WWT_CLOSEBOX, 0, 237, 247, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP },
{ WWT_DROPDOWN_BUTTON, 0, 10, 119, 24, 35, STR_TRACK_MANAGE_RENAME, STR_NONE },
{ WWT_DROPDOWN_BUTTON, 0, 130, 239, 24, 35, STR_TRACK_MANAGE_DELETE, STR_NONE },
@ -166,10 +166,6 @@ void window_track_manage_open(track_design_file_ref *tdFileRef)
trackDesignListWindow->track_list.var_484 |= 1;
}
// TODO: 3155 appears to be empty. What is this supposed to do?
utf8 *title = (utf8*)language_get_string(3155);
format_string(title, STR_TRACK_LIST_NAME_FORMAT, &tdFileRef->name);
_trackDesignFileReference = tdFileRef;
}
@ -240,6 +236,7 @@ static void window_track_manage_invalidate(rct_window *w)
*/
static void window_track_manage_paint(rct_window *w, rct_drawpixelinfo *dpi)
{
set_format_arg(0, char *, _trackDesignFileReference->name);
window_draw_widgets(w, dpi);
}

View File

@ -45,7 +45,7 @@ enum {
static rct_widget window_track_place_widgets[] = {
{ WWT_FRAME, 0, 0, 199, 0, 123, 0xFFFFFFFF, STR_NONE },
{ WWT_CAPTION, 0, 1, 198, 1, 14, 3155, STR_WINDOW_TITLE_TIP },
{ WWT_CAPTION, 0, 1, 198, 1, 14, STR_STRING, STR_WINDOW_TITLE_TIP },
{ WWT_CLOSEBOX, 0, 187, 197, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP },
{ WWT_FLATBTN, 0, 173, 196, 83, 106, SPR_ROTATE_ARROW, STR_ROTATE_90_TIP },
{ WWT_FLATBTN, 0, 173, 196, 59, 82, SPR_MIRROR_ARROW, STR_MIRROR_IMAGE_TIP },
@ -167,10 +167,6 @@ void window_track_place_open(const track_design_file_ref *tdFileRef)
_window_track_place_last_x = 0xFFFF;
_currentTrackPieceDirection = (2 - get_current_rotation()) & 3;
window_track_place_draw_mini_preview(td6);
// TODO: 3155 appears to be empty. What is this supposed to do?
char *title = (char*)language_get_string(3155);
format_string(title, STR_TRACK_LIST_NAME_FORMAT, &td6->name);
_trackDesign = td6;
}
@ -445,6 +441,7 @@ static void window_track_place_attempt_placement(rct_track_td6 *td6, int x, int
*/
static void window_track_place_paint(rct_window *w, rct_drawpixelinfo *dpi)
{
set_format_arg(0, char *, _trackDesign->name);
window_draw_widgets(w, dpi);
// Draw mini tile preview

View File

@ -30,6 +30,7 @@
#include "../ride/track.h"
#include "../ride/track_data.h"
#include "../scenario.h"
#include "../util/util.h"
#include "banner.h"
#include "climate.h"
#include "footpath.h"
@ -5249,7 +5250,7 @@ void game_command_set_banner_name(int* eax, int* ebx, int* ecx, int* edx, int* e
utf8 *buffer = gCommonStringFormatBuffer;
utf8 *dst = buffer;
dst = utf8_write_codepoint(dst, FORMAT_COLOUR_CODE_START + banner->text_colour);
strncpy(dst, newName, 32);
safe_strcpy(dst, newName, 32);
rct_string_id stringId = user_string_allocate(128, buffer);
if (stringId) {
@ -5388,7 +5389,7 @@ void game_command_set_banner_style(int* eax, int* ebx, int* ecx, int* edx, int*
int colourCodepoint = FORMAT_COLOUR_CODE_START + banner->text_colour;
utf8 buffer[256];
format_string(buffer, banner->string_idx, 0);
format_string(buffer, 256, banner->string_idx, 0);
int firstCodepoint = utf8_get_next(buffer, NULL);
if (firstCodepoint >= FORMAT_COLOUR_CODE_START && firstCodepoint <= FORMAT_COLOUR_CODE_END) {
utf8_write_codepoint(buffer, colourCodepoint);

View File

@ -55,7 +55,7 @@ static void money_effect_create_at(money32 value, int x, int y, int z)
value *= -1;
stringId = 1399;
}
format_string(buffer, stringId, &value);
format_string(buffer, 128, stringId, &value);
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
moneyEffect->offset_x = -(gfx_get_string_width(buffer) / 2);
moneyEffect->wiggle = 0;

View File

@ -147,7 +147,7 @@ void park_init()
award_reset();
gS6Info.name[0] = '\0';
format_string(gS6Info.details, STR_NO_DETAILS_YET, NULL);
format_string(gS6Info.details, 256, STR_NO_DETAILS_YET, NULL);
}
/**
@ -915,7 +915,7 @@ void game_command_set_park_name(int *eax, int *ebx, int *ecx, int *edx, int *esi
return;
}
format_string(oldName, gParkName, &gParkNameArgs);
format_string(oldName, 128, gParkName, &gParkNameArgs);
if (strcmp(oldName, newName) == 0) {
*ebx = 0;
return;

View File

@ -207,7 +207,7 @@ const char * sprite_checksum()
char *x = (char *)_spriteChecksum;
for (unsigned int i = 0; i < size; i++)
{
sprintf(x, "%02x", localhash[i]);
snprintf(x, EVP_MAX_MD_SIZE + 1, "%02x", localhash[i]);
x += 2;
}
*x = '\0';