aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/api/locales/localesmgr.cpp
diff options
context:
space:
mode:
authorJean-Francois Mauguit <jfmauguit@mac.com>2024-09-24 09:03:25 -0400
committerGitHub <noreply@github.com>2024-09-24 09:03:25 -0400
commitbab614c421ed7ae329d26bf028c4a3b1d2450f5a (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Wasabi/api/locales/localesmgr.cpp
parent4bde6044fddf053f31795b9eaccdd2a5a527d21f (diff)
parent20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (diff)
downloadwinamp-bab614c421ed7ae329d26bf028c4a3b1d2450f5a.tar.gz
Merge pull request #5 from WinampDesktop/community
Merge to main
Diffstat (limited to 'Src/Wasabi/api/locales/localesmgr.cpp')
-rw-r--r--Src/Wasabi/api/locales/localesmgr.cpp462
1 files changed, 462 insertions, 0 deletions
diff --git a/Src/Wasabi/api/locales/localesmgr.cpp b/Src/Wasabi/api/locales/localesmgr.cpp
new file mode 100644
index 00000000..610a0432
--- /dev/null
+++ b/Src/Wasabi/api/locales/localesmgr.cpp
@@ -0,0 +1,462 @@
+#include <precomp.h>
+#include <wasabicfg.h>
+#include "localesmgr.h"
+#include <bfc/parse/pathparse.h>
+#include <api/config/items/cfgitem.h>
+#include <bfc/file/readdir.h>
+#include <api/xml/XMLAutoInclude.h>
+#include "../nu/regexp.h"
+#include "../Agave/language/api_language.h"
+#include <bfc/ptrlist.h>
+
+struct StringEntry
+{
+ uint32_t id;
+ wchar_t *string;
+};
+
+typedef PtrList<StringEntry> StringTable;
+struct StringTableData
+{
+ wchar_t *id;
+ StringTable entries;
+};
+
+typedef PtrList<StringTableData> StringTables;
+
+StringTables stringTables;
+
+void LocalesAcceleratorSectionXmlCallback::xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
+{
+ const wchar_t *section = params->getItemValue(L"section");
+ if (!section)
+ LocalesManager::setAcceleratorSection(L"general");
+ else
+ LocalesManager::setAcceleratorSection(section);
+}
+
+void LocalesAcceleratorSectionXmlCallback::xmlReaderOnEndElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag)
+{
+ LocalesManager::setAcceleratorSection(L"");
+}
+
+void StringTableXmlCallback::xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
+{
+ const wchar_t *section = params->getItemValue(L"id");
+ if (!section)
+ LocalesManager::SetStringTable(L"nullsoft.wasabi");
+ else
+ LocalesManager::SetStringTable(section);
+}
+
+void StringTableXmlCallback::xmlReaderOnEndElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag)
+{
+ LocalesManager::SetStringTable(L"");
+}
+
+void StringTableEntryXmlCallback::xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
+{
+ const wchar_t *b = params->getItemValue(L"id");
+ const wchar_t *a = params->getItemValue(L"string");
+ if (b && a)
+ LocalesManager::AddString(WTOI(b), a);
+}
+
+/* ------------------------------------------------------------ */
+void LocalesAcceleratorXmlCallback::xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
+{
+ const wchar_t *b = params->getItemValue(L"bind");
+ const wchar_t *a = params->getItemValue(L"action");
+ if (b && a)
+ LocalesManager::addAccelerator(b, a);
+}
+
+/* ------------------------------------------------------------ */
+void LocalesTranslationXmlCallback::xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
+{
+ const wchar_t *f = params->getItemValue(L"from");
+ const wchar_t *t = params->getItemValue(L"to");
+ if (f && t)
+ LocalesManager::addTranslation(f, t);
+}
+
+int LocalesSkinCallback::skincb_onUnloading()
+{
+ LocalesManager::ResetStrings();
+ LocalesManager::resetAll();
+ return 0;
+}
+
+int LocalesSkinCallback::skincb_onReset()
+{
+ //
+ return 0;
+}
+
+int LocalesSkinCallback::skincb_onReload()
+{
+ //LocalesManager::load();
+ return 0;
+}
+
+int LocalesSkinCallback::skincb_onBeforeLoadingElements()
+{
+ LocalesManager::load();
+ return 0;
+}
+
+int LocalesSkinCallback::skincb_onGuiLoaded()
+{
+ LocalesManager::LoadStringTables();
+ return 0;
+}
+
+int LocalesSkinCallback::skincb_onLoaded()
+{
+ // TODO: load string table?
+ return 0;
+}
+
+/* ------------------------------------------------------------ */
+void LocalesManager::init()
+{
+ WASABI_API_SYSCB->syscb_registerCallback(&localesSkinCallback);
+ //load();
+}
+
+void LocalesManager::load()
+{
+#ifdef LOCALES_CUSTOM_LOAD
+
+ LOCALES_CUSTOM_LOAD(localePath);
+ // TODO: benski> don't load this here. we should set up a syscallback for skin load (maybe skincb_onBeforeLoadingElements?)
+ // and also we should call deinit() on skin unload (skincb_onReload, skincb_onReset, skincb_onUnloading?)
+ StringPathCombine filetoload(localePath, L"Wasabi.xml");
+ /*
+ PathParserW pp(localeName);
+ localeName = pp.getLastString();
+ int p = localeName.lFindChar('.');
+ if (p > 0) localeName.trunc(p);
+ */
+#else
+ wchar_t tmpbuf[WA_MAX_PATH] = L"english";
+
+ WASABI_API_CONFIG->getStringPrivate(L"LocaleFile", tmpbuf, WA_MAX_PATH, L"english");
+
+ // FG> ok I have no idea why it doesn't work when i read from cfg instead of stringprivate and frankly i don't have time for this
+ // so for now it'll work with both a cfgitem and a stringprivate, i couldn't desync them so it should be ok in the meantime.
+ /* const GUID options_guid =
+ { 0x280876cf, 0x48c0, 0x40bc, { 0x8e, 0x86, 0x73, 0xce, 0x6b, 0xb4, 0x62, 0xe5 } };
+ CfgItem *item = WASABI_API_CONFIG->config_getCfgItemByGuid(options_guid);
+ if (item != NULL)
+ item->getData("Language", tmpbuf, WA_MAX_PATH-1);*/
+
+ localeName = tmpbuf;
+ englishLocale = !WCSICMP(localeName, L"english");
+ loadFile(L"english");
+ StringW filetoload = localeName;
+ if (englishLocale)
+ filetoload.trunc(0);
+#endif
+
+ if (!filetoload.isempty())
+ loadFile(filetoload);
+
+#ifdef WASABI_API_WNDMGR
+ if (WASABI_API_WNDMGR)
+ WASABI_API_WNDMGR->wndTrackInvalidateAll();
+#endif
+}
+
+void LocalesManager::deinit()
+{
+ resetAll();
+ WASABI_API_SYSCB->syscb_deregisterCallback(&localesSkinCallback);
+}
+
+void LoadXmlFile(obj_xml *parser, const wchar_t *filename);
+
+void LocalesManager::LoadStringTables()
+{
+ StringPathCombine genericStringTable(localePath, L"stringtable.xml");
+ LoadStringTable(genericStringTable);
+
+ StringPathCombine skinStringTable(localePath, WASABI_API_SKIN->getSkinName());
+ skinStringTable.AppendPath(L"stringtable.xml");
+ LoadStringTable(skinStringTable);
+}
+
+void LocalesManager::LoadStringTable(const wchar_t *name)
+{
+ waServiceFactory *parserFactory = WASABI_API_SVC->service_getServiceByGuid(obj_xmlGUID);
+ if (parserFactory)
+ {
+ obj_xml *parser = (obj_xml *)parserFactory->getInterface();
+
+ if (parser)
+ {
+ {
+ const wchar_t *file = Wasabi::Std::filename(name);
+ int fnlen = wcslen(file);
+ StringW path = name;
+ path.trunc( -fnlen);
+ XMLAutoInclude include(parser, path);
+ parser->xmlreader_registerCallback(L"WinampLocaleDefinition\fStringTable", &stringTableXmlCallback);
+ parser->xmlreader_registerCallback(L"WinampLocaleDefinition\fStringTable\fStringEntry", &stringTableXmlEntryCallback);
+ parser->xmlreader_open();
+#ifdef LOCALES_CUSTOM_LOAD
+ LoadXmlFile(parser, name);
+#else
+ LoadXmlFile(parser, StringPrintfW(L"Locales/%s.xml", name));
+#endif
+ parser->xmlreader_unregisterCallback(&stringTableXmlCallback);
+ parser->xmlreader_unregisterCallback(&stringTableXmlEntryCallback);
+ }
+ parser->xmlreader_close();
+ parserFactory->releaseInterface(parser);
+ parser = 0;
+ }
+ }
+}
+
+void LocalesManager::loadFile(const wchar_t *name)
+{
+ waServiceFactory *parserFactory = WASABI_API_SVC->service_getServiceByGuid(obj_xmlGUID);
+ if (parserFactory)
+ {
+ obj_xml *parser = (obj_xml *)parserFactory->getInterface();
+
+ if (parser)
+ {
+ {
+ const wchar_t *file = Wasabi::Std::filename(name);
+ int fnlen = wcslen(file);
+ StringW path = name;
+ path.trunc( -fnlen);
+ XMLAutoInclude include(parser, path);
+ parser->xmlreader_registerCallback(L"WinampLocaleDefinition\faccelerators", &accelSectionXmlCallback);
+ parser->xmlreader_registerCallback(L"WinampLocaleDefinition\faccelerators\faccelerator", &accelXmlCallback);
+ parser->xmlreader_registerCallback(L"WinampLocaleDefinition\ftranslations\ftranslation", &transXmlCallback);
+ parser->xmlreader_open();
+#ifdef LOCALES_CUSTOM_LOAD
+ LoadXmlFile(parser, name);
+#else
+ LoadXmlFile(parser, StringPrintfW(L"Locales/%s.xml", name));
+#endif
+ parser->xmlreader_unregisterCallback(&accelSectionXmlCallback);
+ parser->xmlreader_unregisterCallback(&accelXmlCallback);
+ parser->xmlreader_unregisterCallback(&transXmlCallback);
+ }
+ parser->xmlreader_close();
+ parserFactory->releaseInterface(parser);
+ parser = 0;
+ }
+ }
+}
+
+void LocalesManager::addTranslation(const wchar_t *from, const wchar_t *to)
+{
+ LocTrans *t = translationsList.findItem(from);
+ if (t)
+ translationsList.removeItem(t);
+ translationsList.addItem(new LocTrans(from, to));
+}
+
+
+const wchar_t *LocalesManager::lookupString(const wchar_t *from)
+{
+ if (from == NULL)
+ return NULL;
+
+ if (*from == L'@')
+ {
+
+ const wchar_t *findPound = wcschr(from, L'#');
+ if (findPound && (findPound-from) < 128)
+ {
+ wchar_t table[128] = {0};
+ memcpy(table, from+1, sizeof(wchar_t)*(findPound-from-1));
+ table[findPound-from-1]=0;
+ const wchar_t *string = GetString(table, WTOI(findPound+1));
+ if (string)
+ return string;
+ }
+ }
+ return from;
+}
+
+const wchar_t *LocalesManager::getTranslation(const wchar_t *from)
+{
+ if (!from)
+ return NULL;
+
+ LocTrans *t = translationsList.findItem(from);
+ if (t == NULL)
+ {
+ return from;
+ }
+ return t->getTo();
+}
+
+void LocalesManager::addAccelerator(const wchar_t *bind, const wchar_t *action)
+{
+ LocAccel *a = acceleratorsList.findItem(bind);
+ if (a) // Martin> shouldn't we also check here if it is the same section?
+ // Hm, now that i look closer, we search our list for a wchar_t but we store LocAccels in the list - does this work?
+ acceleratorsList.removeItem(a);
+ acceleratorsList.addItem(new LocAccel(curSection, bind, action));
+}
+
+void LocalesManager::addAcceleratorFromSkin(const wchar_t *bind, const wchar_t *action)
+{
+ //TODO> use binary search
+ int l = acceleratorsList.getNumItems();
+ for (int i = 0;i < l;i++)
+ {
+ if (0 == WCSICMP(acceleratorsList[i]->getSection(), curSection) &&
+ 0 == WCSICMP(acceleratorsList[i]->getKey(), bind))
+ return;
+ }
+ acceleratorsList.addItem(new LocAccel(curSection, bind, action));
+}
+
+const wchar_t *LocalesManager::getBindFromAction(int action)
+{
+ //TODO> use binary search
+ int l = acceleratorsList.getNumItems();
+ for (int i = 0;i < l;i++)
+ {
+ if (acceleratorsList[i]->getActionNum() == action && action != ACTION_NONE)
+ return acceleratorsList[i]->getRealKey();
+ }
+ return NULL;
+}
+
+const wchar_t *LocalesManager::translateAccelerator(const wchar_t *section, const wchar_t *key)
+{
+ //TODO> use binary search
+ int l = acceleratorsList.getNumItems();
+ for (int i = 0;i < l;i++)
+ {
+ if (!WCSICMP(acceleratorsList[i]->getSection(), section))
+ if (!WCSICMP(acceleratorsList[i]->getKey(), key))
+ return acceleratorsList[i]->getAction();
+ }
+ return NULL;
+}
+
+#if 0
+void LocalesManager::setNewLocaleFile(const wchar_t *name)
+{
+ //WASABI_API_CONFIG->setStringPrivate(L"LocaleFile", name);
+ resetAll();
+ init();
+}
+#endif
+
+void LocalesManager::resetAll()
+{
+ translationsList.deleteAll();
+ acceleratorsList.deleteAll();
+}
+
+void LocalesManager::SetStringTable(const wchar_t *table)
+{
+ curTable = table;
+}
+
+void LocalesManager::setAcceleratorSection(const wchar_t *section)
+{
+ curSection = section;
+}
+
+const wchar_t *LocalesManager::getLocaleRoot()
+{
+ return localePath;
+}
+
+void LocalesManager::ResetStrings()
+{
+ for (int i=0;i!=stringTables.getNumItems();i++)
+ {
+ FREE(stringTables[i]->id);
+ for (int j=0;j!=stringTables[i]->entries.getNumItems();j++)
+ {
+ FREE(stringTables[i]->entries[j]->string);
+ }
+ }
+ stringTables.removeAll();
+}
+
+const wchar_t *LocalesManager::GetString(const wchar_t *table, uint32_t id)
+{
+ if (!table)
+ return 0;
+
+ if (!_wcsicmp(table, L"gen_ff"))
+ return WASABI_API_LNGSTRINGW(id);
+
+ for (int i=0;i!=stringTables.getNumItems();i++)
+ {
+ if (!wcscmp(table, stringTables[i]->id))
+ {
+ for (int j=0;j!=stringTables[i]->entries.getNumItems();j++)
+ {
+ if (id == stringTables[i]->entries[j]->id)
+ return stringTables[i]->entries[j]->string;
+ }
+ }
+ }
+ return 0;
+}
+
+void LocalesManager::AddString(const wchar_t *table, uint32_t id, const wchar_t *string)
+{
+ for (int i=0;i!=stringTables.getNumItems();i++)
+ {
+ if (!wcscmp(table, stringTables[i]->id))
+ {
+ for (int j=0;j!=stringTables[i]->entries.getNumItems();j++)
+ {
+ if (id == stringTables[i]->entries[j]->id)
+ {
+ FREE(stringTables[i]->entries[j]->string);
+ stringTables[i]->entries[j]->string=WCSDUP(string);
+ return;
+ }
+ }
+ StringEntry *newEntry = new StringEntry;
+ newEntry->id = id;
+ newEntry->string = WCSDUP(string);
+ stringTables[i]->entries.addItem(newEntry);
+ return;
+ }
+ }
+ StringTableData *newTable = new StringTableData;
+ newTable->id = WCSDUP(table);
+
+ StringEntry *newEntry = new StringEntry;
+ newEntry->id = id;
+ newEntry->string = WCSDUP(string);
+ stringTables.addItem(newTable);
+ newTable->entries.addItem(newEntry);
+}
+
+void LocalesManager::AddString(uint32_t id, const wchar_t *string)
+{
+ AddString(curTable, id, string);
+}
+
+LocalesAcceleratorXmlCallback LocalesManager::accelXmlCallback;
+LocalesAcceleratorSectionXmlCallback LocalesManager::accelSectionXmlCallback;
+LocalesTranslationXmlCallback LocalesManager::transXmlCallback;
+PtrListSorted<LocTrans, PLS_LocTrans, QuickSorted<LocTrans, PLS_LocTrans> > LocalesManager::translationsList;
+PtrListSorted<LocAccel, PLS_LocAccel, QuickSorted<LocAccel, PLS_LocAccel> > LocalesManager::acceleratorsList;
+StringW LocalesManager::localePath;
+//int LocalesManager::localeListLoaded = 0, LocalesManager::curLocaleNum = -1, LocalesManager::englishLocale;
+//PtrList<LocaleItem> LocalesManager::loadableLocalesList;
+StringW LocalesManager::curSection;
+LocalesSkinCallback LocalesManager::localesSkinCallback;
+StringW LocalesManager::curTable;
+StringTableXmlCallback LocalesManager::stringTableXmlCallback;
+StringTableEntryXmlCallback LocalesManager::stringTableXmlEntryCallback; \ No newline at end of file