From 36ad6cd20a07aecf69e92e9fa724beef14be536a Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Mon, 22 Mar 2021 17:28:05 +0200 Subject: Basic language string mechanism Added a set of English strings. Lang can load a language. LabelWidget can replace IDs in the label. IssueID #192 --- src/app.c | 2 +- src/lang.c | 11 ++++++----- src/ui/labelwidget.c | 36 +++++++++++++++++++++++++++++++++++- src/ui/window.c | 4 ++-- 4 files changed, 44 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/app.c b/src/app.c index 4789c62b..95345bda 100644 --- a/src/app.c +++ b/src/app.c @@ -507,7 +507,6 @@ static void communicateWithRunningInstance_App_(iApp *d, iProcessId instance, static void init_App_(iApp *d, int argc, char **argv) { init_CommandLine(&d->args, argc, argv); - init_Lang(); /* Where was the app started from? We ask SDL first because the command line alone is not a reliable source of this information, particularly when it comes to different operating systems. */ { @@ -533,6 +532,7 @@ static void init_App_(iApp *d, int argc, char **argv) { } } #endif + init_Lang(); /* Configure the valid command line options. */ { defineValues_CommandLine(&d->args, "close-tab", 0); defineValues_CommandLine(&d->args, "echo;E", 0); diff --git a/src/lang.c b/src/lang.c index 3e99c09c..d0120798 100644 --- a/src/lang.c +++ b/src/lang.c @@ -31,15 +31,16 @@ static void clear_Lang_(iLang *d) { static void load_Lang_(iLang *d, const char *id) { /* Load compiled language strings from an embedded blob. */ - const iBlock *data = NULL; // &blobLangEn_Embedded; + iUnused(id); + const iBlock *data = &blobEn_Embedded; iMsgStr msg; for (const char *ptr = constBegin_Block(data); ptr != constEnd_Block(data); ptr++) { msg.id = ptr; while (*++ptr) {} msg.str = ++ptr; while (*++ptr) {} - /* Allocate the string. */ - insert_SortedArray(d->messages, &msg); + /* Allocate the string. The data has already been sorted. */ + pushBack_Array(&d->messages->values, &msg); } } @@ -68,8 +69,8 @@ const char *cstr_Lang(const char *msgId) { if (locate_SortedArray(d->messages, &key, &pos)) { return ((const iMsgStr *) at_SortedArray(d->messages, pos))->str; } - //iAssert(iFalse); - fprintf(stderr, "[Lang] missing: %s\n", msgId); + fprintf(stderr, "[Lang] missing: %s\n", msgId); fflush(stderr); + iAssert(iFalse); return msgId; } diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c index ea70977c..c3bc4392 100644 --- a/src/ui/labelwidget.c +++ b/src/ui/labelwidget.c @@ -40,6 +40,7 @@ iLocalDef iInt2 padding_(int64_t flags) { struct Impl_LabelWidget { iWidget widget; + iString srcLabel; iString label; int font; int key; @@ -357,12 +358,40 @@ void updateSize_LabelWidget(iLabelWidget *d) { } } +static void replaceVariables_LabelWidget_(iLabelWidget *d) { + for (const char *label = cstr_String(&d->label); *label; ) { + iRangecc id; + id.start = strstr(label, "${"); + if (!id.start) { + break; + } + id.start += 2; + id.end = strchr(id.start, '}'); + iAssert(id.end != NULL); + /* TODO: Add a lookup that doesn't allocate anything; Lang can handle it. */ + const size_t len = size_Range(&id); + char *key = malloc(len + 1); + memcpy(key, id.start, len); + key[len] = 0; + const char *text = cstr_Lang(key); + const size_t textLen = strlen(text); + free(key); + /* Replace it. */ + size_t startPos = id.start - cstr_String(&d->label) - 2; + remove_Block(&d->label.chars, startPos, len + 3); + insertData_Block(&d->label.chars, startPos, text, textLen); + label = cstr_String(&d->label) + startPos + textLen; + } +} + void init_LabelWidget(iLabelWidget *d, const char *label, const char *cmd) { init_Widget(&d->widget); d->font = uiLabel_FontId; d->forceFg = none_ColorId; d->icon = 0; - initCStr_String(&d->label, label); + initCStr_String(&d->srcLabel, label); + initCopy_String(&d->label, &d->srcLabel); + replaceVariables_LabelWidget_(d); if (cmd) { initCStr_String(&d->command, cmd); } @@ -381,6 +410,7 @@ void init_LabelWidget(iLabelWidget *d, const char *label, const char *cmd) { void deinit_LabelWidget(iLabelWidget *d) { deinit_String(&d->label); + deinit_String(&d->srcLabel); deinit_String(&d->command); } @@ -407,11 +437,15 @@ void setAlignVisually_LabelWidget(iLabelWidget *d, iBool alignVisual) { void updateText_LabelWidget(iLabelWidget *d, const iString *text) { set_String(&d->label, text); + set_String(&d->srcLabel, text); + replaceVariables_LabelWidget_(d); refresh_Widget(&d->widget); } void updateTextCStr_LabelWidget(iLabelWidget *d, const char *text) { setCStr_String(&d->label, text); + set_String(&d->srcLabel, &d->label); + replaceVariables_LabelWidget_(d); refresh_Widget(&d->widget); } diff --git a/src/ui/window.c b/src/ui/window.c index b8b2853e..2d1deb72 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -188,8 +188,8 @@ static iBool handleRootCommands_(iWidget *root, const char *cmd) { #if !defined (iPlatformAppleMobile) /* TODO: Submenus wouldn't hurt here. */ static const iMenuItem navMenuItems_[] = { - { add_Icon " ${menu.nav.newtab}", 't', KMOD_PRIMARY, "tabs.new" }, - { "${menu.nav.openlocation}", SDLK_l, KMOD_PRIMARY, "navigate.focus" }, + { add_Icon " ${menu.newtab}", 't', KMOD_PRIMARY, "tabs.new" }, + { "${menu.openlocation}", SDLK_l, KMOD_PRIMARY, "navigate.focus" }, { "---", 0, 0, NULL }, { download_Icon " " saveToDownloads_Label, SDLK_s, KMOD_PRIMARY, "document.save" }, { "${menu.copy.source}", SDLK_c, KMOD_PRIMARY, "copy" }, -- cgit v1.2.3