localesmgr.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. #include <precomp.h>
  2. #include <wasabicfg.h>
  3. #include "localesmgr.h"
  4. #include <bfc/parse/pathparse.h>
  5. #include <api/config/items/cfgitem.h>
  6. #include <bfc/file/readdir.h>
  7. #include <api/xml/XMLAutoInclude.h>
  8. #include "../nu/regexp.h"
  9. #include "../Agave/language/api_language.h"
  10. #include <bfc/ptrlist.h>
  11. struct StringEntry
  12. {
  13. uint32_t id;
  14. wchar_t *string;
  15. };
  16. typedef PtrList<StringEntry> StringTable;
  17. struct StringTableData
  18. {
  19. wchar_t *id;
  20. StringTable entries;
  21. };
  22. typedef PtrList<StringTableData> StringTables;
  23. StringTables stringTables;
  24. void LocalesAcceleratorSectionXmlCallback::xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
  25. {
  26. const wchar_t *section = params->getItemValue(L"section");
  27. if (!section)
  28. LocalesManager::setAcceleratorSection(L"general");
  29. else
  30. LocalesManager::setAcceleratorSection(section);
  31. }
  32. void LocalesAcceleratorSectionXmlCallback::xmlReaderOnEndElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag)
  33. {
  34. LocalesManager::setAcceleratorSection(L"");
  35. }
  36. void StringTableXmlCallback::xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
  37. {
  38. const wchar_t *section = params->getItemValue(L"id");
  39. if (!section)
  40. LocalesManager::SetStringTable(L"nullsoft.wasabi");
  41. else
  42. LocalesManager::SetStringTable(section);
  43. }
  44. void StringTableXmlCallback::xmlReaderOnEndElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag)
  45. {
  46. LocalesManager::SetStringTable(L"");
  47. }
  48. void StringTableEntryXmlCallback::xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
  49. {
  50. const wchar_t *b = params->getItemValue(L"id");
  51. const wchar_t *a = params->getItemValue(L"string");
  52. if (b && a)
  53. LocalesManager::AddString(WTOI(b), a);
  54. }
  55. /* ------------------------------------------------------------ */
  56. void LocalesAcceleratorXmlCallback::xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
  57. {
  58. const wchar_t *b = params->getItemValue(L"bind");
  59. const wchar_t *a = params->getItemValue(L"action");
  60. if (b && a)
  61. LocalesManager::addAccelerator(b, a);
  62. }
  63. /* ------------------------------------------------------------ */
  64. void LocalesTranslationXmlCallback::xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
  65. {
  66. const wchar_t *f = params->getItemValue(L"from");
  67. const wchar_t *t = params->getItemValue(L"to");
  68. if (f && t)
  69. LocalesManager::addTranslation(f, t);
  70. }
  71. int LocalesSkinCallback::skincb_onUnloading()
  72. {
  73. LocalesManager::ResetStrings();
  74. LocalesManager::resetAll();
  75. return 0;
  76. }
  77. int LocalesSkinCallback::skincb_onReset()
  78. {
  79. //
  80. return 0;
  81. }
  82. int LocalesSkinCallback::skincb_onReload()
  83. {
  84. //LocalesManager::load();
  85. return 0;
  86. }
  87. int LocalesSkinCallback::skincb_onBeforeLoadingElements()
  88. {
  89. LocalesManager::load();
  90. return 0;
  91. }
  92. int LocalesSkinCallback::skincb_onGuiLoaded()
  93. {
  94. LocalesManager::LoadStringTables();
  95. return 0;
  96. }
  97. int LocalesSkinCallback::skincb_onLoaded()
  98. {
  99. // TODO: load string table?
  100. return 0;
  101. }
  102. /* ------------------------------------------------------------ */
  103. void LocalesManager::init()
  104. {
  105. WASABI_API_SYSCB->syscb_registerCallback(&localesSkinCallback);
  106. //load();
  107. }
  108. void LocalesManager::load()
  109. {
  110. #ifdef LOCALES_CUSTOM_LOAD
  111. LOCALES_CUSTOM_LOAD(localePath);
  112. // TODO: benski> don't load this here. we should set up a syscallback for skin load (maybe skincb_onBeforeLoadingElements?)
  113. // and also we should call deinit() on skin unload (skincb_onReload, skincb_onReset, skincb_onUnloading?)
  114. StringPathCombine filetoload(localePath, L"Wasabi.xml");
  115. /*
  116. PathParserW pp(localeName);
  117. localeName = pp.getLastString();
  118. int p = localeName.lFindChar('.');
  119. if (p > 0) localeName.trunc(p);
  120. */
  121. #else
  122. wchar_t tmpbuf[WA_MAX_PATH] = L"english";
  123. WASABI_API_CONFIG->getStringPrivate(L"LocaleFile", tmpbuf, WA_MAX_PATH, L"english");
  124. // 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
  125. // 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.
  126. /* const GUID options_guid =
  127. { 0x280876cf, 0x48c0, 0x40bc, { 0x8e, 0x86, 0x73, 0xce, 0x6b, 0xb4, 0x62, 0xe5 } };
  128. CfgItem *item = WASABI_API_CONFIG->config_getCfgItemByGuid(options_guid);
  129. if (item != NULL)
  130. item->getData("Language", tmpbuf, WA_MAX_PATH-1);*/
  131. localeName = tmpbuf;
  132. englishLocale = !WCSICMP(localeName, L"english");
  133. loadFile(L"english");
  134. StringW filetoload = localeName;
  135. if (englishLocale)
  136. filetoload.trunc(0);
  137. #endif
  138. if (!filetoload.isempty())
  139. loadFile(filetoload);
  140. #ifdef WASABI_API_WNDMGR
  141. if (WASABI_API_WNDMGR)
  142. WASABI_API_WNDMGR->wndTrackInvalidateAll();
  143. #endif
  144. }
  145. void LocalesManager::deinit()
  146. {
  147. resetAll();
  148. WASABI_API_SYSCB->syscb_deregisterCallback(&localesSkinCallback);
  149. }
  150. void LoadXmlFile(obj_xml *parser, const wchar_t *filename);
  151. void LocalesManager::LoadStringTables()
  152. {
  153. StringPathCombine genericStringTable(localePath, L"stringtable.xml");
  154. LoadStringTable(genericStringTable);
  155. StringPathCombine skinStringTable(localePath, WASABI_API_SKIN->getSkinName());
  156. skinStringTable.AppendPath(L"stringtable.xml");
  157. LoadStringTable(skinStringTable);
  158. }
  159. void LocalesManager::LoadStringTable(const wchar_t *name)
  160. {
  161. waServiceFactory *parserFactory = WASABI_API_SVC->service_getServiceByGuid(obj_xmlGUID);
  162. if (parserFactory)
  163. {
  164. obj_xml *parser = (obj_xml *)parserFactory->getInterface();
  165. if (parser)
  166. {
  167. {
  168. const wchar_t *file = Wasabi::Std::filename(name);
  169. int fnlen = wcslen(file);
  170. StringW path = name;
  171. path.trunc( -fnlen);
  172. XMLAutoInclude include(parser, path);
  173. parser->xmlreader_registerCallback(L"WinampLocaleDefinition\fStringTable", &stringTableXmlCallback);
  174. parser->xmlreader_registerCallback(L"WinampLocaleDefinition\fStringTable\fStringEntry", &stringTableXmlEntryCallback);
  175. parser->xmlreader_open();
  176. #ifdef LOCALES_CUSTOM_LOAD
  177. LoadXmlFile(parser, name);
  178. #else
  179. LoadXmlFile(parser, StringPrintfW(L"Locales/%s.xml", name));
  180. #endif
  181. parser->xmlreader_unregisterCallback(&stringTableXmlCallback);
  182. parser->xmlreader_unregisterCallback(&stringTableXmlEntryCallback);
  183. }
  184. parser->xmlreader_close();
  185. parserFactory->releaseInterface(parser);
  186. parser = 0;
  187. }
  188. }
  189. }
  190. void LocalesManager::loadFile(const wchar_t *name)
  191. {
  192. waServiceFactory *parserFactory = WASABI_API_SVC->service_getServiceByGuid(obj_xmlGUID);
  193. if (parserFactory)
  194. {
  195. obj_xml *parser = (obj_xml *)parserFactory->getInterface();
  196. if (parser)
  197. {
  198. {
  199. const wchar_t *file = Wasabi::Std::filename(name);
  200. int fnlen = wcslen(file);
  201. StringW path = name;
  202. path.trunc( -fnlen);
  203. XMLAutoInclude include(parser, path);
  204. parser->xmlreader_registerCallback(L"WinampLocaleDefinition\faccelerators", &accelSectionXmlCallback);
  205. parser->xmlreader_registerCallback(L"WinampLocaleDefinition\faccelerators\faccelerator", &accelXmlCallback);
  206. parser->xmlreader_registerCallback(L"WinampLocaleDefinition\ftranslations\ftranslation", &transXmlCallback);
  207. parser->xmlreader_open();
  208. #ifdef LOCALES_CUSTOM_LOAD
  209. LoadXmlFile(parser, name);
  210. #else
  211. LoadXmlFile(parser, StringPrintfW(L"Locales/%s.xml", name));
  212. #endif
  213. parser->xmlreader_unregisterCallback(&accelSectionXmlCallback);
  214. parser->xmlreader_unregisterCallback(&accelXmlCallback);
  215. parser->xmlreader_unregisterCallback(&transXmlCallback);
  216. }
  217. parser->xmlreader_close();
  218. parserFactory->releaseInterface(parser);
  219. parser = 0;
  220. }
  221. }
  222. }
  223. void LocalesManager::addTranslation(const wchar_t *from, const wchar_t *to)
  224. {
  225. LocTrans *t = translationsList.findItem(from);
  226. if (t)
  227. translationsList.removeItem(t);
  228. translationsList.addItem(new LocTrans(from, to));
  229. }
  230. const wchar_t *LocalesManager::lookupString(const wchar_t *from)
  231. {
  232. if (from == NULL)
  233. return NULL;
  234. if (*from == L'@')
  235. {
  236. const wchar_t *findPound = wcschr(from, L'#');
  237. if (findPound && (findPound-from) < 128)
  238. {
  239. wchar_t table[128] = {0};
  240. memcpy(table, from+1, sizeof(wchar_t)*(findPound-from-1));
  241. table[findPound-from-1]=0;
  242. const wchar_t *string = GetString(table, WTOI(findPound+1));
  243. if (string)
  244. return string;
  245. }
  246. }
  247. return from;
  248. }
  249. const wchar_t *LocalesManager::getTranslation(const wchar_t *from)
  250. {
  251. if (!from)
  252. return NULL;
  253. LocTrans *t = translationsList.findItem(from);
  254. if (t == NULL)
  255. {
  256. return from;
  257. }
  258. return t->getTo();
  259. }
  260. void LocalesManager::addAccelerator(const wchar_t *bind, const wchar_t *action)
  261. {
  262. LocAccel *a = acceleratorsList.findItem(bind);
  263. if (a) // Martin> shouldn't we also check here if it is the same section?
  264. // Hm, now that i look closer, we search our list for a wchar_t but we store LocAccels in the list - does this work?
  265. acceleratorsList.removeItem(a);
  266. acceleratorsList.addItem(new LocAccel(curSection, bind, action));
  267. }
  268. void LocalesManager::addAcceleratorFromSkin(const wchar_t *bind, const wchar_t *action)
  269. {
  270. //TODO> use binary search
  271. int l = acceleratorsList.getNumItems();
  272. for (int i = 0;i < l;i++)
  273. {
  274. if (0 == WCSICMP(acceleratorsList[i]->getSection(), curSection) &&
  275. 0 == WCSICMP(acceleratorsList[i]->getKey(), bind))
  276. return;
  277. }
  278. acceleratorsList.addItem(new LocAccel(curSection, bind, action));
  279. }
  280. const wchar_t *LocalesManager::getBindFromAction(int action)
  281. {
  282. //TODO> use binary search
  283. int l = acceleratorsList.getNumItems();
  284. for (int i = 0;i < l;i++)
  285. {
  286. if (acceleratorsList[i]->getActionNum() == action && action != ACTION_NONE)
  287. return acceleratorsList[i]->getRealKey();
  288. }
  289. return NULL;
  290. }
  291. const wchar_t *LocalesManager::translateAccelerator(const wchar_t *section, const wchar_t *key)
  292. {
  293. //TODO> use binary search
  294. int l = acceleratorsList.getNumItems();
  295. for (int i = 0;i < l;i++)
  296. {
  297. if (!WCSICMP(acceleratorsList[i]->getSection(), section))
  298. if (!WCSICMP(acceleratorsList[i]->getKey(), key))
  299. return acceleratorsList[i]->getAction();
  300. }
  301. return NULL;
  302. }
  303. #if 0
  304. void LocalesManager::setNewLocaleFile(const wchar_t *name)
  305. {
  306. //WASABI_API_CONFIG->setStringPrivate(L"LocaleFile", name);
  307. resetAll();
  308. init();
  309. }
  310. #endif
  311. void LocalesManager::resetAll()
  312. {
  313. translationsList.deleteAll();
  314. acceleratorsList.deleteAll();
  315. }
  316. void LocalesManager::SetStringTable(const wchar_t *table)
  317. {
  318. curTable = table;
  319. }
  320. void LocalesManager::setAcceleratorSection(const wchar_t *section)
  321. {
  322. curSection = section;
  323. }
  324. const wchar_t *LocalesManager::getLocaleRoot()
  325. {
  326. return localePath;
  327. }
  328. void LocalesManager::ResetStrings()
  329. {
  330. for (int i=0;i!=stringTables.getNumItems();i++)
  331. {
  332. FREE(stringTables[i]->id);
  333. for (int j=0;j!=stringTables[i]->entries.getNumItems();j++)
  334. {
  335. FREE(stringTables[i]->entries[j]->string);
  336. }
  337. }
  338. stringTables.removeAll();
  339. }
  340. const wchar_t *LocalesManager::GetString(const wchar_t *table, uint32_t id)
  341. {
  342. if (!table)
  343. return 0;
  344. if (!_wcsicmp(table, L"gen_ff"))
  345. return WASABI_API_LNGSTRINGW(id);
  346. for (int i=0;i!=stringTables.getNumItems();i++)
  347. {
  348. if (!wcscmp(table, stringTables[i]->id))
  349. {
  350. for (int j=0;j!=stringTables[i]->entries.getNumItems();j++)
  351. {
  352. if (id == stringTables[i]->entries[j]->id)
  353. return stringTables[i]->entries[j]->string;
  354. }
  355. }
  356. }
  357. return 0;
  358. }
  359. void LocalesManager::AddString(const wchar_t *table, uint32_t id, const wchar_t *string)
  360. {
  361. for (int i=0;i!=stringTables.getNumItems();i++)
  362. {
  363. if (!wcscmp(table, stringTables[i]->id))
  364. {
  365. for (int j=0;j!=stringTables[i]->entries.getNumItems();j++)
  366. {
  367. if (id == stringTables[i]->entries[j]->id)
  368. {
  369. FREE(stringTables[i]->entries[j]->string);
  370. stringTables[i]->entries[j]->string=WCSDUP(string);
  371. return;
  372. }
  373. }
  374. StringEntry *newEntry = new StringEntry;
  375. newEntry->id = id;
  376. newEntry->string = WCSDUP(string);
  377. stringTables[i]->entries.addItem(newEntry);
  378. return;
  379. }
  380. }
  381. StringTableData *newTable = new StringTableData;
  382. newTable->id = WCSDUP(table);
  383. StringEntry *newEntry = new StringEntry;
  384. newEntry->id = id;
  385. newEntry->string = WCSDUP(string);
  386. stringTables.addItem(newTable);
  387. newTable->entries.addItem(newEntry);
  388. }
  389. void LocalesManager::AddString(uint32_t id, const wchar_t *string)
  390. {
  391. AddString(curTable, id, string);
  392. }
  393. LocalesAcceleratorXmlCallback LocalesManager::accelXmlCallback;
  394. LocalesAcceleratorSectionXmlCallback LocalesManager::accelSectionXmlCallback;
  395. LocalesTranslationXmlCallback LocalesManager::transXmlCallback;
  396. PtrListSorted<LocTrans, PLS_LocTrans, QuickSorted<LocTrans, PLS_LocTrans> > LocalesManager::translationsList;
  397. PtrListSorted<LocAccel, PLS_LocAccel, QuickSorted<LocAccel, PLS_LocAccel> > LocalesManager::acceleratorsList;
  398. StringW LocalesManager::localePath;
  399. //int LocalesManager::localeListLoaded = 0, LocalesManager::curLocaleNum = -1, LocalesManager::englishLocale;
  400. //PtrList<LocaleItem> LocalesManager::loadableLocalesList;
  401. StringW LocalesManager::curSection;
  402. LocalesSkinCallback LocalesManager::localesSkinCallback;
  403. StringW LocalesManager::curTable;
  404. StringTableXmlCallback LocalesManager::stringTableXmlCallback;
  405. StringTableEntryXmlCallback LocalesManager::stringTableXmlEntryCallback;