diff --git a/amxmodx/CLang.cpp b/amxmodx/CLang.cpp index 168df98b..832706b2 100755 --- a/amxmodx/CLang.cpp +++ b/amxmodx/CLang.cpp @@ -47,10 +47,10 @@ #define INSERT_STRING 3 #define INSERT_NEWLINE 4 -// dictionary format is Fast-Format-Hash-Lookup, v5 +// dictionary format is Fast-Format-Hash-Lookup, v6 #define MAGIC_HDR 0x4646484C -#define FFHL_VERSION 5 -#define FFHL_MIN_VERSION 4 +#define FFHL_VERSION 6 +#define FFHL_MIN_VERSION 6 /*version history: * 1 (BAILOPAN) - Simplest form possible, no reverse @@ -58,6 +58,7 @@ * 3 (PM OnoTo) - 2^32 languages per file with full reverse * 4 (BAILOPAN) - Optimized by separating and relocating tables (normalization) * 5 (BAILOPAN) - Removed hash storage + * 6 (BAILOPAN) - Arbitrary bump to force reparse. FORMAT: Magic 4bytes Version 1byte @@ -403,192 +404,10 @@ const char *CLangMngr::Format(const char *fmt, ...) #define ZEROTERM(buf) buf[(sizeof(buf)/sizeof(buf[0]))-1]=0; #define NEXT_PARAM() +//this is not implemented.... char *CLangMngr::FormatString(const char *fmt, va_list &ap) { - // the output buffer - static char outbuf[4096]; - char *outptr = outbuf; - const char *src = fmt; - int status; - - while (*src) - { - if (*src == '%') - { - ++src; - if (*src == 'L') - { - NEXT_PARAM(); - const char *pAmxLangName = va_arg(ap, const char*); - const char *cpLangName=NULL; - // Handle player ids (1-32) and server language - - if (pAmxLangName == (const char *)LANG_PLAYER) // LANG_PLAYER - { - if ((int)CVAR_GET_FLOAT("amx_client_languages")) - { - cpLangName = g_vault.get("server_language"); - } else { - cpLangName = ENTITY_KEYVALUE(GET_PLAYER_POINTER_I(m_CurGlobId)->pEdict, "lang"); - } - } - else if (pAmxLangName == (const char *)LANG_SERVER) // LANG_SERVER - { - cpLangName = g_vault.get("server_language"); - } - else if (pAmxLangName >= (const char *)1 && pAmxLangName <= (const char *)32) // Direct Client Id - { - if ((int)CVAR_GET_FLOAT("amx_client_languages")) - { - cpLangName = g_vault.get("server_language"); - } else { - cpLangName = ENTITY_KEYVALUE(GET_PLAYER_POINTER_I((int)pAmxLangName)->pEdict, "lang"); - } - } else { // Language Name - int tmplen = 0; - cpLangName = pAmxLangName; - } - - if (!cpLangName || strlen(cpLangName) < 1) - cpLangName = "en"; - - int tmplen = 0; - const char *key = va_arg(ap, const char *); - const char *def = GetDef(cpLangName, key, status); - - if (def == NULL) - { - if (pAmxLangName != LANG_SERVER) - { - def = GetDef(g_vault.get("server_language"), key, status); - } - - if (strcmp(cpLangName, "en") != 0 && strcmp(g_vault.get("server_language"), "en") != 0) - { - def = GetDef("en", key, status); - } - - if (!def) - { - static char buf[512]; - CHECK_PTR((char*)(buf + 17 + strlen(key)), buf, sizeof(buf)); - sprintf(buf, "ML_LNOTFOUND: %s", key); - def = buf; - } - } - - while (*def) - { - if (*def == '%') - { - ++def; - static char format[32]; - format[0] = '%'; - char *ptr = format + 1; - while (ptr-format &tmpVec) @@ -712,6 +531,7 @@ int CLangMngr::MergeDefinitionFile(const char *file) tmpEntry.definition = new String; tmpEntry.definition->assign(def.c_str()); tmpEntry.definition->trim(); + tmpEntry.definition->reparse_newlines(); Defq.push(tmpEntry); tmpEntry.key = -1; tmpEntry.definition = NULL; @@ -738,6 +558,7 @@ int CLangMngr::MergeDefinitionFile(const char *file) } else { if (buf[0] == ':') { + tmpEntry.definition->reparse_newlines(); Defq.push(tmpEntry); tmpEntry.key = -1; tmpEntry.definition = NULL; diff --git a/amxmodx/CString.h b/amxmodx/CString.h index 14b86509..3f9d6531 100755 --- a/amxmodx/CString.h +++ b/amxmodx/CString.h @@ -178,6 +178,30 @@ public: return false; } + + void reparse_newlines() + { + size_t len = size(); + int offs = 0; + char c; + if (!len) + return; + for (size_t i=0; i(params[2]); + cell *fmt = get_amxaddr(amx, params[3]); + int param = 4; + size_t total = atcprintf(buf, maxlen, fmt, amx, params, ¶m); + return static_cast(total); +} + static cell AMX_NATIVE_CALL format(AMX *amx, cell *params) /* 3 param */ { - //int len; - //return set_amxstring(amx, params[1], format_amxstring(amx, params, 3, len), params[2]); cell *buf = get_amxaddr(amx, params[1]); cell *fmt = get_amxaddr(amx, params[3]); size_t maxlen = params[2]; + /** + * SPECIAL CASE - check if the buffers overlap. + * some users, for whatever reason, do things like: + * format(buf, 255, buf.... + * this is considered "deprecated" but we have to support it. + * we do this by checking to see if reading from buf will overlap + */ + cell addr_start = params[1]; + cell addr_end = params[1] + maxlen * sizeof(cell); + cell max = params[0] / sizeof(cell); + bool copy = false; + for (cell i = 3; i <= max; i++) + { + //does this clip the bounds?!?!? WELL, DOES IT!?!?! i am a loud dog + if (params[i] >= addr_start && params[i] <= addr_end) + { + copy = true; + break; + } + } + if (copy) + buf = g_cpbuf; int param = 4; size_t total = atcprintf(buf, maxlen, fmt, amx, params, ¶m); + if (copy) + { + /* copy back */ + cell *old = get_amxaddr(amx, params[1]); + memcpy(old, g_cpbuf, total * sizeof(cell)); + } return total; } @@ -906,6 +944,7 @@ AMX_NATIVE_INFO string_Natives[] = {"equal", equal}, {"equali", equali}, {"format", format}, + {"formatex", formatex}, {"format_args", format_args}, {"isdigit", is_digit}, {"isalnum", is_alnum},