summaryrefslogtreecommitdiff
path: root/src
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
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')
-rw-r--r--src/lang.c53
-rw-r--r--src/lang.h7
-rw-r--r--src/macos.m4
-rw-r--r--src/ui/labelwidget.c24
-rw-r--r--src/ui/window.c12
5 files changed, 60 insertions, 40 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}
diff --git a/src/lang.h b/src/lang.h
index 3e9291f2..ea71e531 100644
--- a/src/lang.h
+++ b/src/lang.h
@@ -6,5 +6,10 @@ void init_Lang (void);
6void deinit_Lang (void); 6void deinit_Lang (void);
7 7
8void setCurrent_Lang (const char *language); 8void setCurrent_Lang (const char *language);
9const iString * string_Lang (const char *msgId); 9iRangecc range_Lang (iRangecc msgId);
10
10const char * cstr_Lang (const char *msgId); 11const char * cstr_Lang (const char *msgId);
12const iString * string_Lang (const char *msgId);
13
14void translate_Lang (iString *textWithIds);
15const char * translateCStr_Lang (const char *textWithIds);
diff --git a/src/macos.m b/src/macos.m
index c6c30fa5..12575dd5 100644
--- a/src/macos.m
+++ b/src/macos.m
@@ -22,6 +22,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
22 22
23#include "macos.h" 23#include "macos.h"
24#include "app.h" 24#include "app.h"
25#include "lang.h"
25#include "ui/color.h" 26#include "ui/color.h"
26#include "ui/command.h" 27#include "ui/command.h"
27#include "ui/keys.h" 28#include "ui/keys.h"
@@ -462,6 +463,7 @@ void insertMenuItems_MacOS(const char *menuLabel, int atIndex, const iMenuItem *
462 NSApplication *app = [NSApplication sharedApplication]; 463 NSApplication *app = [NSApplication sharedApplication];
463 MyDelegate *myDel = (MyDelegate *) app.delegate; 464 MyDelegate *myDel = (MyDelegate *) app.delegate;
464 NSMenu *appMenu = [app mainMenu]; 465 NSMenu *appMenu = [app mainMenu];
466 menuLabel = translateCStr_Lang(menuLabel);
465 NSMenuItem *mainItem = [appMenu insertItemWithTitle:[NSString stringWithUTF8String:menuLabel] 467 NSMenuItem *mainItem = [appMenu insertItemWithTitle:[NSString stringWithUTF8String:menuLabel]
466 action:nil 468 action:nil
467 keyEquivalent:@"" 469 keyEquivalent:@""
@@ -469,7 +471,7 @@ void insertMenuItems_MacOS(const char *menuLabel, int atIndex, const iMenuItem *
469 NSMenu *menu = [[NSMenu alloc] initWithTitle:[NSString stringWithUTF8String:menuLabel]]; 471 NSMenu *menu = [[NSMenu alloc] initWithTitle:[NSString stringWithUTF8String:menuLabel]];
470 [menu setAutoenablesItems:NO]; 472 [menu setAutoenablesItems:NO];
471 for (size_t i = 0; i < count; ++i) { 473 for (size_t i = 0; i < count; ++i) {
472 const char *label = items[i].label; 474 const char *label = translateCStr_Lang(items[i].label);
473 if (label[0] == '\r') { 475 if (label[0] == '\r') {
474 /* Skip the formatting escape. */ 476 /* Skip the formatting escape. */
475 label += 2; 477 label += 2;
diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c
index c3bc4392..0becd419 100644
--- a/src/ui/labelwidget.c
+++ b/src/ui/labelwidget.c
@@ -359,29 +359,7 @@ void updateSize_LabelWidget(iLabelWidget *d) {
359} 359}
360 360
361static void replaceVariables_LabelWidget_(iLabelWidget *d) { 361static void replaceVariables_LabelWidget_(iLabelWidget *d) {
362 for (const char *label = cstr_String(&d->label); *label; ) { 362 translate_Lang(&d->label);
363 iRangecc id;
364 id.start = strstr(label, "${");
365 if (!id.start) {
366 break;
367 }
368 id.start += 2;
369 id.end = strchr(id.start, '}');
370 iAssert(id.end != NULL);
371 /* TODO: Add a lookup that doesn't allocate anything; Lang can handle it. */
372 const size_t len = size_Range(&id);
373 char *key = malloc(len + 1);
374 memcpy(key, id.start, len);
375 key[len] = 0;
376 const char *text = cstr_Lang(key);
377 const size_t textLen = strlen(text);
378 free(key);
379 /* Replace it. */
380 size_t startPos = id.start - cstr_String(&d->label) - 2;
381 remove_Block(&d->label.chars, startPos, len + 3);
382 insertData_Block(&d->label.chars, startPos, text, textLen);
383 label = cstr_String(&d->label) + startPos + textLen;
384 }
385} 363}
386 364
387void init_LabelWidget(iLabelWidget *d, const char *label, const char *cmd) { 365void init_LabelWidget(iLabelWidget *d, const char *label, const char *cmd) {
diff --git a/src/ui/window.c b/src/ui/window.c
index 2d1deb72..d27d252b 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -1055,12 +1055,12 @@ static void setupUserInterface_Window(iWindow *d) {
1055 setAlignVisually_LabelWidget(navMenu, iTrue); 1055 setAlignVisually_LabelWidget(navMenu, iTrue);
1056 setId_Widget(addChildFlags_Widget(navBar, iClob(navMenu), collapse_WidgetFlag), "navbar.menu"); 1056 setId_Widget(addChildFlags_Widget(navBar, iClob(navMenu), collapse_WidgetFlag), "navbar.menu");
1057#else 1057#else
1058 insertMenuItems_MacOS("File", 1, fileMenuItems_, iElemCount(fileMenuItems_)); 1058 insertMenuItems_MacOS("${menu.title.file}", 1, fileMenuItems_, iElemCount(fileMenuItems_));
1059 insertMenuItems_MacOS("Edit", 2, editMenuItems_, iElemCount(editMenuItems_)); 1059 insertMenuItems_MacOS("${menu.title.edit}", 2, editMenuItems_, iElemCount(editMenuItems_));
1060 insertMenuItems_MacOS("View", 3, viewMenuItems_, iElemCount(viewMenuItems_)); 1060 insertMenuItems_MacOS("${menu.title.view}", 3, viewMenuItems_, iElemCount(viewMenuItems_));
1061 insertMenuItems_MacOS("Bookmarks", 4, bookmarksMenuItems_, iElemCount(bookmarksMenuItems_)); 1061 insertMenuItems_MacOS("${menu.title.bookmarks}", 4, bookmarksMenuItems_, iElemCount(bookmarksMenuItems_));
1062 insertMenuItems_MacOS("Identity", 5, identityMenuItems_, iElemCount(identityMenuItems_)); 1062 insertMenuItems_MacOS("${menu.title.identity}", 5, identityMenuItems_, iElemCount(identityMenuItems_));
1063 insertMenuItems_MacOS("Help", 7, helpMenuItems_, iElemCount(helpMenuItems_)); 1063 insertMenuItems_MacOS("${menu.title.help}", 7, helpMenuItems_, iElemCount(helpMenuItems_));
1064#endif 1064#endif
1065 } 1065 }
1066 /* Tab bar. */ { 1066 /* Tab bar. */ {