mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Added "string_format" script function
Some code refactoring.
This commit is contained in:
+7
-7
@@ -707,29 +707,29 @@ CreditsAtBottom=0
|
|||||||
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||||
|
|
||||||
;To change the path and filename of the critical table file, uncomment the next line
|
;To change the path and filename of the critical table file, uncomment the next line
|
||||||
;OverrideCriticalFile=CriticalOverrides.ini
|
;OverrideCriticalFile=sfall\CriticalOverrides.ini
|
||||||
|
|
||||||
;To change the relationship between SPECIAL stats and derived stats, uncomment the next line
|
;To change the relationship between SPECIAL stats and derived stats, uncomment the next line
|
||||||
;See the Stats.ini in the modders pack for an example file
|
;See the Stats.ini in the modders pack for an example file
|
||||||
;DerivedStats=Stats.ini
|
;DerivedStats=sfall\Stats.ini
|
||||||
|
|
||||||
;Allows you to edit the skill tables
|
;Allows you to edit the skill tables
|
||||||
;Point the next line to an ini file containing the replacement skill data
|
;Point the next line to an ini file containing the replacement skill data
|
||||||
;SkillsFile=Skills.ini
|
;SkillsFile=sfall\Skills.ini
|
||||||
|
|
||||||
;To add additional perks to the game, uncomment the next line and set it to point to a file containing perk information
|
;To add additional perks to the game, uncomment the next line and set it to point to a file containing perk information
|
||||||
;PerksFile=Perks.ini
|
;PerksFile=sfall\Perks.ini
|
||||||
|
|
||||||
;To add additional books to the game, uncomment the next line and point to a file containing book information
|
;To add additional books to the game, uncomment the next line and point to a file containing book information
|
||||||
;See the Books.ini in the modders pack for an example file
|
;See the Books.ini in the modders pack for an example file
|
||||||
;BooksFile=Books.ini
|
;BooksFile=sfall\Books.ini
|
||||||
|
|
||||||
;Allows you to change some parameters for drugs and their addictions
|
;Allows you to change some parameters for drugs and their addictions
|
||||||
;See the Drugs.ini in the modders pack for an example file
|
;See the Drugs.ini in the modders pack for an example file
|
||||||
;DrugsFile=Drugs.ini
|
;DrugsFile=sfall\Drugs.ini
|
||||||
|
|
||||||
;Point to an ini file containing elevator data
|
;Point to an ini file containing elevator data
|
||||||
;ElevatorsFile=Elevators.ini
|
;ElevatorsFile=sfall\Elevators.ini
|
||||||
|
|
||||||
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||||
[Scripts]
|
[Scripts]
|
||||||
|
|||||||
@@ -320,6 +320,7 @@
|
|||||||
#define spatial_radius(obj) sfall_func1("spatial_radius", obj)
|
#define spatial_radius(obj) sfall_func1("spatial_radius", obj)
|
||||||
#define string_compare(str1, str2) sfall_func2("string_compare", str1, str2)
|
#define string_compare(str1, str2) sfall_func2("string_compare", str1, str2)
|
||||||
#define string_compare_locale(str1, str2, codePage) sfall_func3("string_compare", str1, str2, codePage)
|
#define string_compare_locale(str1, str2, codePage) sfall_func3("string_compare", str1, str2, codePage)
|
||||||
|
#define string_format(format, a1, a2) sfall_func3("string_format", format, a1, a2)
|
||||||
#define tile_refresh_display sfall_func0("tile_refresh_display")
|
#define tile_refresh_display sfall_func0("tile_refresh_display")
|
||||||
#define unjam_lock(obj) sfall_func1("unjam_lock", obj)
|
#define unjam_lock(obj) sfall_func1("unjam_lock", obj)
|
||||||
#define unset_unique_id(obj) sfall_func2("set_unique_id", obj, -1)
|
#define unset_unique_id(obj) sfall_func2("set_unique_id", obj, -1)
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ Some utility/math functions are available:
|
|||||||
- you can use this to search for a substring in a string like this: strlen(get_array(string_split(haystack, needle), 0))
|
- you can use this to search for a substring in a string like this: strlen(get_array(string_split(haystack, needle), 0))
|
||||||
|
|
||||||
> string substr(string, start, length)
|
> string substr(string, start, length)
|
||||||
- cuts a substring from a string starting at "start" up to "length" characters. The first character position starts with 0 (zero).
|
- cuts a substring from a string starting at "start" up to "length" characters. The first character position is 0 (zero).
|
||||||
- If start is negative - it indicates starting position from the end of the string (for example substr("test", -2, 2) will return last 2 charactes: "st").
|
- If start is negative - it indicates starting position from the end of the string (for example substr("test", -2, 2) will return last 2 charactes: "st").
|
||||||
- If length is negative - it means so many characters will be omitted from the end of string (example: substr("test", 0, -2) will return string without last 2 characters: "te").
|
- If length is negative - it means so many characters will be omitted from the end of string (example: substr("test", 0, -2) will return string without last 2 characters: "te").
|
||||||
- If length is zero - it will return a string from the starting position to the end of the string **New behavior** for sfall 4.2.2/3.8.22
|
- If length is zero - it will return a string from the starting position to the end of the string **New behavior** for sfall 4.2.2/3.8.22
|
||||||
@@ -682,6 +682,10 @@ optional argument:
|
|||||||
- codePage: code page number to properly compare national characters in the range 128-255 of the ASCII code table
|
- codePage: code page number to properly compare national characters in the range 128-255 of the ASCII code table
|
||||||
available encodings: 1250-1252, 866
|
available encodings: 1250-1252, 866
|
||||||
|
|
||||||
|
> string sfall_func3("string_format", string format, any val1, any val2, ...)
|
||||||
|
- formats given value using standard syntax of C printf function (google "printf" for format details). However it is limited to formatting up to 4 values
|
||||||
|
- formatting is only supported for %s and %d. The format string is limited to 1024 characters
|
||||||
|
|
||||||
------------------------
|
------------------------
|
||||||
------ MORE INFO -------
|
------ MORE INFO -------
|
||||||
------------------------
|
------------------------
|
||||||
|
|||||||
@@ -310,19 +310,18 @@ hide:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* artDbgMsg = "\nError: file not found: %s\n";
|
static char* artDbgMsg = "\nERROR: File not found: %s\n";
|
||||||
static void __declspec(naked) art_data_size_hook() {
|
static void __declspec(naked) art_data_size_hook() {
|
||||||
__asm {
|
__asm {
|
||||||
test edi, edi;
|
test edi, edi;
|
||||||
jz artNotExist;
|
jz artNotExist;
|
||||||
retn;
|
retn;
|
||||||
artNotExist:
|
artNotExist:
|
||||||
mov eax, [esp + 0x124 - 0x1C + 4]; // filename
|
mov edx, [esp + 0x124 - 0x1C + 4]; // filename
|
||||||
push eax;
|
push edx;
|
||||||
push artDbgMsg;
|
push artDbgMsg;
|
||||||
call fo::funcoffs::debug_printf_;
|
call fo::funcoffs::debug_printf_;
|
||||||
mov eax, [esp + 0x124 - 0x1C + 12]; // filename
|
push edx; // filename
|
||||||
push eax;
|
|
||||||
push artDbgMsg;
|
push artDbgMsg;
|
||||||
lea eax, [esp + 0x124 - 0x124 + 20]; // buf
|
lea eax, [esp + 0x124 - 0x124 + 20]; // buf
|
||||||
push eax;
|
push eax;
|
||||||
@@ -368,7 +367,7 @@ static void DebugModePatch() {
|
|||||||
if (iniGetInt("Debugging", "HideObjIsNullMsg", 0, ::sfall::ddrawIni)) {
|
if (iniGetInt("Debugging", "HideObjIsNullMsg", 0, ::sfall::ddrawIni)) {
|
||||||
MakeJump(0x453FD2, dbg_error_hack);
|
MakeJump(0x453FD2, dbg_error_hack);
|
||||||
}
|
}
|
||||||
// prints a debug message about missing art file for critters to debug.log and the message window
|
// prints a debug message about missing art file for critters to both debug.log and the message window
|
||||||
HookCall(0x419B65, art_data_size_hook);
|
HookCall(0x419B65, art_data_size_hook);
|
||||||
|
|
||||||
dlogr(" Done", DL_INIT);
|
dlogr(" Done", DL_INIT);
|
||||||
|
|||||||
@@ -523,7 +523,7 @@ end:
|
|||||||
|
|
||||||
static void __declspec(naked) DialogHook() {
|
static void __declspec(naked) DialogHook() {
|
||||||
__asm {
|
__asm {
|
||||||
test inLoop, DIALOG; // check bit flag
|
test inLoop, DIALOG; // check byte flag
|
||||||
jz changeMode;
|
jz changeMode;
|
||||||
jmp fo::funcoffs::gdProcess_;
|
jmp fo::funcoffs::gdProcess_;
|
||||||
changeMode:
|
changeMode:
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ static DWORD _stdcall HandleMapUpdateForScripts(const DWORD procId);
|
|||||||
|
|
||||||
static int idle;
|
static int idle;
|
||||||
|
|
||||||
|
char ScriptExtender::gTextBuffer[5120]; // used as global temp text buffer for script functions
|
||||||
|
|
||||||
std::string ScriptExtender::iniConfigFolder;
|
std::string ScriptExtender::iniConfigFolder;
|
||||||
|
|
||||||
struct GlobalScript {
|
struct GlobalScript {
|
||||||
|
|||||||
@@ -40,6 +40,11 @@ public:
|
|||||||
|
|
||||||
static std::string iniConfigFolder;
|
static std::string iniConfigFolder;
|
||||||
|
|
||||||
|
static char gTextBuffer[5120];
|
||||||
|
|
||||||
|
// returns the size of the global text buffer
|
||||||
|
inline static const long TextBufferSize() { return sizeof(gTextBuffer); }
|
||||||
|
|
||||||
static long GetScriptReturnValue();
|
static long GetScriptReturnValue();
|
||||||
static long GetResetScriptReturnValue();
|
static long GetResetScriptReturnValue();
|
||||||
|
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ static const SfallMetarule metarules[] = {
|
|||||||
{"show_window", sf_show_window, 0, 1, -1, {ARG_STRING}},
|
{"show_window", sf_show_window, 0, 1, -1, {ARG_STRING}},
|
||||||
{"spatial_radius", sf_spatial_radius, 1, 1, 0, {ARG_OBJECT}},
|
{"spatial_radius", sf_spatial_radius, 1, 1, 0, {ARG_OBJECT}},
|
||||||
{"string_compare", sf_string_compare, 2, 3, 0, {ARG_STRING, ARG_STRING, ARG_INT}},
|
{"string_compare", sf_string_compare, 2, 3, 0, {ARG_STRING, ARG_STRING, ARG_INT}},
|
||||||
|
{"string_format", sf_string_format, 2, 5, 0, {ARG_STRING, ARG_ANY, ARG_ANY, ARG_ANY, ARG_ANY}},
|
||||||
{"tile_refresh_display", sf_tile_refresh_display, 0, 0},
|
{"tile_refresh_display", sf_tile_refresh_display, 0, 0},
|
||||||
{"unjam_lock", sf_unjam_lock, 1, 1, -1, {ARG_OBJECT}},
|
{"unjam_lock", sf_unjam_lock, 1, 1, -1, {ARG_OBJECT}},
|
||||||
{"unwield_slot", sf_unwield_slot, 2, 2, -1, {ARG_OBJECT, ARG_INT}},
|
{"unwield_slot", sf_unwield_slot, 2, 2, -1, {ARG_OBJECT, ARG_INT}},
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ namespace sfall
|
|||||||
namespace script
|
namespace script
|
||||||
{
|
{
|
||||||
|
|
||||||
const char* stringTooLong = "%s() - the string length exceeds maximum of 64 characters.";
|
const char* stringTooLong = "%s() - the string exceeds maximum length of 64 characters.";
|
||||||
|
|
||||||
void sf_set_dm_model(OpcodeContext& ctx) {
|
void sf_set_dm_model(OpcodeContext& ctx) {
|
||||||
auto model = ctx.arg(0).strValue();
|
auto model = ctx.arg(0).strValue();
|
||||||
@@ -453,7 +453,6 @@ specialIni:
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char IniStrBuffer[256];
|
|
||||||
static DWORD GetIniSetting(const char* str, bool isString) {
|
static DWORD GetIniSetting(const char* str, bool isString) {
|
||||||
const char* key;
|
const char* key;
|
||||||
char section[33], file[128];
|
char section[33], file[128];
|
||||||
@@ -462,9 +461,9 @@ static DWORD GetIniSetting(const char* str, bool isString) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (isString) {
|
if (isString) {
|
||||||
IniStrBuffer[0] = 0;
|
ScriptExtender::gTextBuffer[0] = 0;
|
||||||
iniGetString(section, key, "", IniStrBuffer, 256, file);
|
iniGetString(section, key, "", ScriptExtender::gTextBuffer, 256, file);
|
||||||
return (DWORD)&IniStrBuffer[0];
|
return (DWORD)&ScriptExtender::gTextBuffer[0];
|
||||||
} else {
|
} else {
|
||||||
return iniGetInt(section, key, -1, file);
|
return iniGetInt(section, key, -1, file);
|
||||||
}
|
}
|
||||||
@@ -1037,8 +1036,8 @@ void sf_set_ini_setting(OpcodeContext& ctx) {
|
|||||||
|
|
||||||
const char* saveValue;
|
const char* saveValue;
|
||||||
if (argVal.isInt()) {
|
if (argVal.isInt()) {
|
||||||
_itoa_s(argVal.rawValue(), IniStrBuffer, 10);
|
_itoa_s(argVal.rawValue(), ScriptExtender::gTextBuffer, 10);
|
||||||
saveValue = IniStrBuffer;
|
saveValue = ScriptExtender::gTextBuffer;
|
||||||
} else {
|
} else {
|
||||||
saveValue = argVal.strValue();
|
saveValue = argVal.strValue();
|
||||||
}
|
}
|
||||||
@@ -1075,12 +1074,10 @@ static std::string GetIniFilePath(const ScriptValue& arg) {
|
|||||||
return fileName;
|
return fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
char getIniSectionBuf[5120];
|
|
||||||
|
|
||||||
void sf_get_ini_sections(OpcodeContext& ctx) {
|
void sf_get_ini_sections(OpcodeContext& ctx) {
|
||||||
GetPrivateProfileSectionNamesA(getIniSectionBuf, 5120, GetIniFilePath(ctx.arg(0)).data());
|
GetPrivateProfileSectionNamesA(ScriptExtender::gTextBuffer, ScriptExtender::TextBufferSize(), GetIniFilePath(ctx.arg(0)).data());
|
||||||
std::vector<char*> sections;
|
std::vector<char*> sections;
|
||||||
char* section = getIniSectionBuf;
|
char* section = ScriptExtender::gTextBuffer;
|
||||||
while (*section != 0) {
|
while (*section != 0) {
|
||||||
sections.push_back(section); // position
|
sections.push_back(section); // position
|
||||||
section += std::strlen(section) + 1;
|
section += std::strlen(section) + 1;
|
||||||
@@ -1099,10 +1096,10 @@ void sf_get_ini_sections(OpcodeContext& ctx) {
|
|||||||
|
|
||||||
void sf_get_ini_section(OpcodeContext& ctx) {
|
void sf_get_ini_section(OpcodeContext& ctx) {
|
||||||
auto section = ctx.arg(1).strValue();
|
auto section = ctx.arg(1).strValue();
|
||||||
GetPrivateProfileSectionA(section, getIniSectionBuf, 5120, GetIniFilePath(ctx.arg(0)).data());
|
GetPrivateProfileSectionA(section, ScriptExtender::gTextBuffer, ScriptExtender::TextBufferSize(), GetIniFilePath(ctx.arg(0)).data());
|
||||||
int arrayId = TempArray(-1, 0); // associative
|
int arrayId = TempArray(-1, 0); // associative
|
||||||
auto& arr = arrays[arrayId];
|
auto& arr = arrays[arrayId];
|
||||||
char *key = getIniSectionBuf, *val = nullptr;
|
char *key = ScriptExtender::gTextBuffer, *val = nullptr;
|
||||||
while (*key != 0) {
|
while (*key != 0) {
|
||||||
char* val = std::strpbrk(key, "=");
|
char* val = std::strpbrk(key, "=");
|
||||||
if (val != nullptr) {
|
if (val != nullptr) {
|
||||||
|
|||||||
@@ -190,8 +190,6 @@ void sf_string_split(OpcodeContext& ctx) {
|
|||||||
ctx.setReturn(StringSplit(ctx.arg(0).strValue(), ctx.arg(1).strValue()));
|
ctx.setReturn(StringSplit(ctx.arg(0).strValue(), ctx.arg(1).strValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* tempTextBuf = nullptr;
|
|
||||||
|
|
||||||
char* Substring(const char* str, int startPos, int length) {
|
char* Substring(const char* str, int startPos, int length) {
|
||||||
int len = strlen(str);
|
int len = strlen(str);
|
||||||
|
|
||||||
@@ -201,11 +199,8 @@ char* Substring(const char* str, int startPos, int length) {
|
|||||||
}
|
}
|
||||||
if (length < 0) {
|
if (length < 0) {
|
||||||
length += len - startPos; // cutoff at end
|
length += len - startPos; // cutoff at end
|
||||||
if (length == 0) {
|
if (length == 0) return "";
|
||||||
return "";
|
abs(length); // length can't be negative
|
||||||
} else if (length < 0) {
|
|
||||||
length = -length; // length can't be negative
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// check position
|
// check position
|
||||||
if (startPos >= len) return ""; // start position is out of string length, return empty string
|
if (startPos >= len) return ""; // start position is out of string length, return empty string
|
||||||
@@ -213,11 +208,12 @@ char* Substring(const char* str, int startPos, int length) {
|
|||||||
length = len - startPos; // set the correct length, the length of characters goes beyond the end of the string
|
length = len - startPos; // set the correct length, the length of characters goes beyond the end of the string
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tempTextBuf) delete[] tempTextBuf;
|
const int bufMax = ScriptExtender::TextBufferSize() - 1;
|
||||||
tempTextBuf = new char[length + 1];
|
if (length > bufMax) length = bufMax;
|
||||||
memcpy(tempTextBuf, &str[startPos], length);
|
|
||||||
tempTextBuf[length] = '\0';
|
memcpy(ScriptExtender::gTextBuffer, &str[startPos], length);
|
||||||
return tempTextBuf;
|
ScriptExtender::gTextBuffer[length] = '\0';
|
||||||
|
return ScriptExtender::gTextBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sf_substr(OpcodeContext& ctx) {
|
void sf_substr(OpcodeContext& ctx) {
|
||||||
@@ -241,8 +237,7 @@ static char* _stdcall sprintf_lite(const char* format, ScriptValue value) {
|
|||||||
int fmtlen = strlen(format);
|
int fmtlen = strlen(format);
|
||||||
int buflen = fmtlen + 1;
|
int buflen = fmtlen + 1;
|
||||||
for (int i = 0; i < fmtlen; i++) {
|
for (int i = 0; i < fmtlen; i++) {
|
||||||
if (format[i] == '%')
|
if (format[i] == '%') buflen++; // will possibly be escaped, need space for that
|
||||||
buflen++; // will possibly be escaped, need space for that
|
|
||||||
}
|
}
|
||||||
// parse format to make it safe
|
// parse format to make it safe
|
||||||
char* newfmt = new char[buflen];
|
char* newfmt = new char[buflen];
|
||||||
@@ -290,7 +285,8 @@ static char* _stdcall sprintf_lite(const char* format, ScriptValue value) {
|
|||||||
newfmt[j++] = c;
|
newfmt[j++] = c;
|
||||||
}
|
}
|
||||||
newfmt[j] = '\0';
|
newfmt[j] = '\0';
|
||||||
// calculate required memory
|
|
||||||
|
// calculate required length
|
||||||
if (hasDigits) {
|
if (hasDigits) {
|
||||||
buflen = 254;
|
buflen = 254;
|
||||||
} else if (specifier == 'c') {
|
} else if (specifier == 'c') {
|
||||||
@@ -300,18 +296,18 @@ static char* _stdcall sprintf_lite(const char* format, ScriptValue value) {
|
|||||||
} else {
|
} else {
|
||||||
buflen = j + 30; // numbers
|
buflen = j + 30; // numbers
|
||||||
}
|
}
|
||||||
if (tempTextBuf) {
|
|
||||||
delete[] tempTextBuf;
|
const long bufMaxLen = ScriptExtender::TextBufferSize() - 1;
|
||||||
}
|
if (buflen > bufMaxLen - 1) buflen = bufMaxLen - 1;
|
||||||
tempTextBuf = new char[buflen + 1];
|
ScriptExtender::gTextBuffer[bufMaxLen] = '\0';
|
||||||
|
|
||||||
if (value.isFloat()) {
|
if (value.isFloat()) {
|
||||||
_snprintf(tempTextBuf, buflen, newfmt, value.floatValue());
|
_snprintf(ScriptExtender::gTextBuffer, buflen, newfmt, value.floatValue());
|
||||||
} else {
|
} else {
|
||||||
_snprintf(tempTextBuf, buflen, newfmt, value.rawValue());
|
_snprintf(ScriptExtender::gTextBuffer, buflen, newfmt, value.rawValue());
|
||||||
}
|
}
|
||||||
tempTextBuf[buflen] = '\0'; // just in case
|
|
||||||
delete[] newfmt;
|
delete[] newfmt;
|
||||||
return tempTextBuf;
|
return ScriptExtender::gTextBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sf_sprintf(OpcodeContext& ctx) {
|
void sf_sprintf(OpcodeContext& ctx) {
|
||||||
@@ -320,6 +316,53 @@ void sf_sprintf(OpcodeContext& ctx) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sf_string_format(OpcodeContext& ctx) {
|
||||||
|
const char* format = ctx.arg(0).strValue();
|
||||||
|
|
||||||
|
int fmtLen = strlen(format);
|
||||||
|
if (fmtLen == 0) {
|
||||||
|
ctx.setReturn(format);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fmtLen > 1024) {
|
||||||
|
ctx.printOpcodeError("%s() - the format string exceeds maximum length of 1024 characters.", ctx.getMetaruleName());
|
||||||
|
ctx.setReturn("Error");
|
||||||
|
} else {
|
||||||
|
char* newFmt = new char[fmtLen + 1];
|
||||||
|
newFmt[fmtLen] = '\0';
|
||||||
|
// parse format to make it safe
|
||||||
|
int i = 0;
|
||||||
|
do {
|
||||||
|
char c = format[i];
|
||||||
|
if (c == '%') {
|
||||||
|
char cf = format[i + 1];
|
||||||
|
if (cf != 's' && cf != 'd' && cf != '%') c = ' '; // unsupported format
|
||||||
|
}
|
||||||
|
newFmt[i] = c;
|
||||||
|
} while (++i < fmtLen);
|
||||||
|
|
||||||
|
const long bufMaxLen = ScriptExtender::TextBufferSize() - 1;
|
||||||
|
|
||||||
|
switch (ctx.numArgs()) {
|
||||||
|
case 2 :
|
||||||
|
_snprintf(ScriptExtender::gTextBuffer, bufMaxLen, newFmt, ctx.arg(1).rawValue());
|
||||||
|
break;
|
||||||
|
case 3 :
|
||||||
|
_snprintf(ScriptExtender::gTextBuffer, bufMaxLen, newFmt, ctx.arg(1).rawValue(), ctx.arg(2).rawValue());
|
||||||
|
break;
|
||||||
|
case 4 :
|
||||||
|
_snprintf(ScriptExtender::gTextBuffer, bufMaxLen, newFmt, ctx.arg(1).rawValue(), ctx.arg(2).rawValue(), ctx.arg(3).rawValue());
|
||||||
|
break;
|
||||||
|
case 5 :
|
||||||
|
_snprintf(ScriptExtender::gTextBuffer, bufMaxLen, newFmt, ctx.arg(1).rawValue(), ctx.arg(2).rawValue(), ctx.arg(3).rawValue(), ctx.arg(4).rawValue());
|
||||||
|
}
|
||||||
|
ScriptExtender::gTextBuffer[bufMaxLen] = '\0'; // just in case
|
||||||
|
|
||||||
|
delete[] newFmt;
|
||||||
|
ctx.setReturn(ScriptExtender::gTextBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void sf_power(OpcodeContext& ctx) {
|
void sf_power(OpcodeContext& ctx) {
|
||||||
const ScriptValue &base = ctx.arg(0),
|
const ScriptValue &base = ctx.arg(0),
|
||||||
&power = ctx.arg(1);
|
&power = ctx.arg(1);
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ void sf_string_compare(OpcodeContext&);
|
|||||||
|
|
||||||
void sf_sprintf(OpcodeContext&);
|
void sf_sprintf(OpcodeContext&);
|
||||||
|
|
||||||
|
void sf_string_format(OpcodeContext&);
|
||||||
|
|
||||||
void sf_ord(OpcodeContext&);
|
void sf_ord(OpcodeContext&);
|
||||||
|
|
||||||
void sf_typeof(OpcodeContext&);
|
void sf_typeof(OpcodeContext&);
|
||||||
|
|||||||
Reference in New Issue
Block a user