atcprintf() is now fully re-entrant, meaning translations can be used from inside translations

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401626
This commit is contained in:
David Anderson 2007-10-21 17:58:35 +00:00
parent c3149f22cf
commit 744dbdc4c7

View File

@ -87,23 +87,43 @@ inline bool TryTranslation(CPlugin *pl, const char *key, unsigned int langid, un
return (err == Trans_Okay) ? true : false; return (err == Trans_Okay) ? true : false;
} }
size_t Translate(char *buffer, size_t maxlen, IPluginContext *pCtx, const char *key, cell_t target, const cell_t *params, int *arg, bool *error) inline void ReorderTranslationParams(const Translation *pTrans, cell_t *params)
{
cell_t new_params[MAX_TRANSLATE_PARAMS];
for (unsigned int i = 0; i < pTrans->fmt_count; i++)
{
new_params[i] = params[pTrans->fmt_order[i]];
}
memcpy(params, new_params, pTrans->fmt_count * sizeof(cell_t));
}
size_t Translate(char *buffer,
size_t maxlen,
IPluginContext *pCtx,
const char *key,
cell_t target,
const cell_t *params,
int *arg,
bool *error)
{ {
unsigned int langid; unsigned int langid;
*error = false; *error = false;
Translation pTrans; Translation pTrans;
CPlugin *pl = (CPlugin *)g_PluginSys.FindPluginByContext(pCtx->GetContext()); CPlugin *pl = (CPlugin *)g_PluginSys.FindPluginByContext(pCtx->GetContext());
size_t langcount = pl->GetLangFileCount(); size_t langcount = pl->GetLangFileCount();
void *new_params[MAX_TRANSLATE_PARAMS];
unsigned int max_params = 0; unsigned int max_params = 0;
try_serverlang: try_serverlang:
if (target == LANG_SERVER) if (target == LANG_SERVER)
{ {
langid = g_Translator.GetServerLanguage(); langid = g_Translator.GetServerLanguage();
} else if ((target >= 1) && (target <= g_Players.GetMaxClients())) { }
else if ((target >= 1) && (target <= g_Players.GetMaxClients()))
{
langid = g_Translator.GetClientLanguage(target); langid = g_Translator.GetClientLanguage(target);
} else { }
else
{
pCtx->ThrowNativeErrorEx(SP_ERROR_PARAM, "Translation failed: invalid client index %d", target); pCtx->ThrowNativeErrorEx(SP_ERROR_PARAM, "Translation failed: invalid client index %d", target);
goto error_out; goto error_out;
} }
@ -114,13 +134,17 @@ try_serverlang:
{ {
target = LANG_SERVER; target = LANG_SERVER;
goto try_serverlang; goto try_serverlang;
} else if (langid != LANGUAGE_ENGLISH) { }
else if (langid != LANGUAGE_ENGLISH)
{
if (!TryTranslation(pl, key, LANGUAGE_ENGLISH, langcount, &pTrans)) if (!TryTranslation(pl, key, LANGUAGE_ENGLISH, langcount, &pTrans))
{ {
pCtx->ThrowNativeErrorEx(SP_ERROR_PARAM, "Language phrase \"%s\" not found", key); pCtx->ThrowNativeErrorEx(SP_ERROR_PARAM, "Language phrase \"%s\" not found", key);
goto error_out; goto error_out;
} }
} else { }
else
{
pCtx->ThrowNativeErrorEx(SP_ERROR_PARAM, "Language phrase \"%s\" not found", key); pCtx->ThrowNativeErrorEx(SP_ERROR_PARAM, "Language phrase \"%s\" not found", key);
goto error_out; goto error_out;
} }
@ -140,22 +164,18 @@ try_serverlang:
goto error_out; goto error_out;
} }
/* Translate the parameters to raw pointers */ /* Re-order the parameters that this translation requires */
for (size_t i=0; i<max_params; i++) ReorderTranslationParams(&pTrans, const_cast<cell_t *>(&params[*arg]));
{
pCtx->LocalToPhysAddr(params[*arg], reinterpret_cast<cell_t **>(&new_params[i]));
(*arg)++;
}
} }
return g_Translator.Translate(buffer, maxlen, new_params, &pTrans); /* Now, call back into atcprintf() which is re-entrant */
return atcprintf(buffer, maxlen, pTrans.szPhrase, pCtx, params, arg);
error_out: error_out:
*error = true; *error = true;
return 0; return 0;
} }
//:TODO: review this code before we choose a license
void AddString(char **buf_p, size_t &maxlen, const char *string, int width, int prec) void AddString(char **buf_p, size_t &maxlen, const char *string, int width, int prec)
{ {
int size = 0; int size = 0;