From de34940c4dd709fa7103c6961cbe8b410638ffdd Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Mon, 22 Mar 2021 19:27:44 +0200 Subject: Lang: Improvements; macOS menu items Use char pointer ranges for the array of IDs and strings to avoid allocations. Translate macOS menu items. IssueID #192 --- src/lang.c | 53 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 9 deletions(-) (limited to 'src/lang.c') diff --git a/src/lang.c b/src/lang.c index d0120798..81afb0d2 100644 --- a/src/lang.c +++ b/src/lang.c @@ -8,13 +8,13 @@ iDeclareType(Lang) iDeclareType(MsgStr) struct Impl_MsgStr { - const char *id; /* these point to null-terminated strings in embedded data */ - const char *str; + iRangecc id; /* these point to null-terminated strings in embedded data */ + iRangecc str; }; int cmp_MsgStr_(const void *e1, const void *e2) { const iMsgStr *a = e1, *b = e2; - return iCmpStr(a->id, b->id); + return cmpCStrNSc_Rangecc(a->id, b->id.start, size_Range(&b->id), &iCaseSensitive); } /*----------------------------------------------------------------------------------------------*/ @@ -35,10 +35,12 @@ static void load_Lang_(iLang *d, const char *id) { const iBlock *data = &blobEn_Embedded; iMsgStr msg; for (const char *ptr = constBegin_Block(data); ptr != constEnd_Block(data); ptr++) { - msg.id = ptr; + msg.id.start = ptr; while (*++ptr) {} - msg.str = ++ptr; + msg.id.end = ptr; + msg.str.start = ++ptr; while (*++ptr) {} + msg.str.end = ptr; /* Allocate the string. The data has already been sorted. */ pushBack_Array(&d->messages->values, &msg); } @@ -62,18 +64,51 @@ void setCurrent_Lang(const char *language) { load_Lang_(d, language); } -const char *cstr_Lang(const char *msgId) { +iRangecc range_Lang(iRangecc msgId) { const iLang *d = &lang_; size_t pos; - const iMsgStr key = { .id = iConstCast(char *, msgId) }; + const iMsgStr key = { .id = msgId }; if (locate_SortedArray(d->messages, &key, &pos)) { return ((const iMsgStr *) at_SortedArray(d->messages, pos))->str; } - fprintf(stderr, "[Lang] missing: %s\n", msgId); fflush(stderr); + fprintf(stderr, "[Lang] missing: %s\n", cstr_Rangecc(msgId)); fflush(stderr); iAssert(iFalse); return msgId; } +const char *cstr_Lang(const char *msgId) { + return range_Lang(range_CStr(msgId)).start; /* guaranteed to be NULL-terminated */ +} + const iString *string_Lang(const char *msgId) { - return collectNewCStr_String(cstr_Lang(msgId)); + return collectNewRange_String(range_Lang(range_CStr(msgId))); +} + +void translate_Lang(iString *textWithIds) { + for (const char *pos = cstr_String(textWithIds); *pos; ) { + iRangecc id; + id.start = strstr(pos, "${"); + if (!id.start) { + break; + } + id.start += 2; + id.end = strchr(id.start, '}'); + iAssert(id.end != NULL); + const size_t idLen = size_Range(&id); + const iRangecc replacement = range_Lang(id); + const size_t startPos = id.start - cstr_String(textWithIds) - 2; + /* Replace it. */ + remove_Block(&textWithIds->chars, startPos, idLen + 3); + insertData_Block(&textWithIds->chars, startPos, replacement.start, size_Range(&replacement)); + pos = cstr_String(textWithIds) + startPos + size_Range(&replacement); + } +} + +const char *translateCStr_Lang(const char *textWithIds) { + if (strstr(textWithIds, "${") == NULL) { + return textWithIds; /* nothing to replace */ + } + iString *text = collectNewCStr_String(textWithIds); + translate_Lang(text); + return cstr_String(text); } -- cgit v1.2.3