summaryrefslogtreecommitdiff
path: root/src/lang.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-03-22 19:27:44 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-03-22 19:29:09 +0200
commitde34940c4dd709fa7103c6961cbe8b410638ffdd (patch)
tree03afd79839273638bc25efbed0d8e70e2ce0896d /src/lang.c
parent0bd8465b33c6e3f6dacf79785a47cbd6abea6f25 (diff)
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
Diffstat (limited to 'src/lang.c')
-rw-r--r--src/lang.c53
1 files changed, 44 insertions, 9 deletions
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)
8iDeclareType(MsgStr) 8iDeclareType(MsgStr)
9 9
10struct Impl_MsgStr { 10struct Impl_MsgStr {
11 const char *id; /* these point to null-terminated strings in embedded data */ 11 iRangecc id; /* these point to null-terminated strings in embedded data */
12 const char *str; 12 iRangecc str;
13}; 13};
14 14
15int cmp_MsgStr_(const void *e1, const void *e2) { 15int cmp_MsgStr_(const void *e1, const void *e2) {
16 const iMsgStr *a = e1, *b = e2; 16 const iMsgStr *a = e1, *b = e2;
17 return iCmpStr(a->id, b->id); 17 return cmpCStrNSc_Rangecc(a->id, b->id.start, size_Range(&b->id), &iCaseSensitive);
18} 18}
19 19
20/*----------------------------------------------------------------------------------------------*/ 20/*----------------------------------------------------------------------------------------------*/
@@ -35,10 +35,12 @@ static void load_Lang_(iLang *d, const char *id) {
35 const iBlock *data = &blobEn_Embedded; 35 const iBlock *data = &blobEn_Embedded;
36 iMsgStr msg; 36 iMsgStr msg;
37 for (const char *ptr = constBegin_Block(data); ptr != constEnd_Block(data); ptr++) { 37 for (const char *ptr = constBegin_Block(data); ptr != constEnd_Block(data); ptr++) {
38 msg.id = ptr; 38 msg.id.start = ptr;
39 while (*++ptr) {} 39 while (*++ptr) {}
40 msg.str = ++ptr; 40 msg.id.end = ptr;
41 msg.str.start = ++ptr;
41 while (*++ptr) {} 42 while (*++ptr) {}
43 msg.str.end = ptr;
42 /* Allocate the string. The data has already been sorted. */ 44 /* Allocate the string. The data has already been sorted. */
43 pushBack_Array(&d->messages->values, &msg); 45 pushBack_Array(&d->messages->values, &msg);
44 } 46 }
@@ -62,18 +64,51 @@ void setCurrent_Lang(const char *language) {
62 load_Lang_(d, language); 64 load_Lang_(d, language);
63} 65}
64 66
65const char *cstr_Lang(const char *msgId) { 67iRangecc range_Lang(iRangecc msgId) {
66 const iLang *d = &lang_; 68 const iLang *d = &lang_;
67 size_t pos; 69 size_t pos;
68 const iMsgStr key = { .id = iConstCast(char *, msgId) }; 70 const iMsgStr key = { .id = msgId };
69 if (locate_SortedArray(d->messages, &key, &pos)) { 71 if (locate_SortedArray(d->messages, &key, &pos)) {
70 return ((const iMsgStr *) at_SortedArray(d->messages, pos))->str; 72 return ((const iMsgStr *) at_SortedArray(d->messages, pos))->str;
71 } 73 }
72 fprintf(stderr, "[Lang] missing: %s\n", msgId); fflush(stderr); 74 fprintf(stderr, "[Lang] missing: %s\n", cstr_Rangecc(msgId)); fflush(stderr);
73 iAssert(iFalse); 75 iAssert(iFalse);
74 return msgId; 76 return msgId;
75} 77}
76 78
79const char *cstr_Lang(const char *msgId) {
80 return range_Lang(range_CStr(msgId)).start; /* guaranteed to be NULL-terminated */
81}
82
77const iString *string_Lang(const char *msgId) { 83const iString *string_Lang(const char *msgId) {
78 return collectNewCStr_String(cstr_Lang(msgId)); 84 return collectNewRange_String(range_Lang(range_CStr(msgId)));
85}
86
87void translate_Lang(iString *textWithIds) {
88 for (const char *pos = cstr_String(textWithIds); *pos; ) {
89 iRangecc id;
90 id.start = strstr(pos, "${");
91 if (!id.start) {
92 break;
93 }
94 id.start += 2;
95 id.end = strchr(id.start, '}');
96 iAssert(id.end != NULL);
97 const size_t idLen = size_Range(&id);
98 const iRangecc replacement = range_Lang(id);
99 const size_t startPos = id.start - cstr_String(textWithIds) - 2;
100 /* Replace it. */
101 remove_Block(&textWithIds->chars, startPos, idLen + 3);
102 insertData_Block(&textWithIds->chars, startPos, replacement.start, size_Range(&replacement));
103 pos = cstr_String(textWithIds) + startPos + size_Range(&replacement);
104 }
105}
106
107const char *translateCStr_Lang(const char *textWithIds) {
108 if (strstr(textWithIds, "${") == NULL) {
109 return textWithIds; /* nothing to replace */
110 }
111 iString *text = collectNewCStr_String(textWithIds);
112 translate_Lang(text);
113 return cstr_String(text);
79} 114}