You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1617 lines
48 KiB
1617 lines
48 KiB
// This file is part of Notepad++ project |
|
// Copyright (C)2021 Don HO <don.h@free.fr> |
|
|
|
// This program is free software: you can redistribute it and/or modify |
|
// it under the terms of the GNU General Public License as published by |
|
// the Free Software Foundation, either version 3 of the License, or |
|
// at your option any later version. |
|
// |
|
// This program is distributed in the hope that it will be useful, |
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
// GNU General Public License for more details. |
|
// |
|
// You should have received a copy of the GNU General Public License |
|
// along with this program. If not, see <https://www.gnu.org/licenses/>. |
|
|
|
|
|
#include "Notepad_plus.h" |
|
#include "ShortcutMapper.h" |
|
#include "EncodingMapper.h" |
|
#include "localization.h" |
|
#include "fileBrowser.h" |
|
#include "NppDarkMode.h" |
|
|
|
using namespace std; |
|
|
|
|
|
|
|
MenuPosition g_menuFolderPositions[] = { |
|
//============================================== |
|
// {L0, L1, L2, id}, |
|
//============================================== |
|
{ 0, -1, -1, "file" }, |
|
{ 1, -1, -1, "edit" }, |
|
{ 2, -1, -1, "search" }, |
|
{ 3, -1, -1, "view" }, |
|
{ 4, -1, -1, "encoding" }, |
|
{ 5, -1, -1, "language" }, |
|
{ 6, -1, -1, "settings" }, |
|
{ 7, -1, -1, "tools" }, |
|
{ 8, -1, -1, "macro" }, |
|
{ 9, -1, -1, "run" }, |
|
{ 10, -1, -1, "Plugins" }, |
|
{ 11, -1, -1, "Window" }, |
|
|
|
{ 0, 2, -1, "file-openFolder" }, |
|
{ 0, 13, -1, "file-closeMore" }, |
|
{ 0, 22, -1, "file-recentFiles" }, |
|
|
|
{ 1, 11, -1, "edit-insert" }, |
|
{ 1, 12, -1, "edit-copyToClipboard" }, |
|
{ 1, 13, -1, "edit-indent" }, |
|
{ 1, 14, -1, "edit-convertCaseTo" }, |
|
{ 1, 15, -1, "edit-lineOperations" }, |
|
{ 1, 16, -1, "edit-comment" }, |
|
{ 1, 17, -1, "edit-autoCompletion" }, |
|
{ 1, 18, -1, "edit-eolConversion" }, |
|
{ 1, 19, -1, "edit-blankOperations" }, |
|
{ 1, 20, -1, "edit-pasteSpecial" }, |
|
{ 1, 21, -1, "edit-onSelection" }, |
|
{ 1, 23, -1, "edit-multiSelectALL" }, |
|
{ 1, 24, -1, "edit-multiSelectNext" }, |
|
|
|
{ 2, 18, -1, "search-changeHistory" }, |
|
{ 2, 20, -1, "search-markAll" }, |
|
{ 2, 21, -1, "search-markOne" }, |
|
{ 2, 22, -1, "search-unmarkAll" }, |
|
{ 2, 23, -1, "search-jumpUp" }, |
|
{ 2, 24, -1, "search-jumpDown" }, |
|
{ 2, 25, -1, "search-copyStyledText" }, |
|
{ 2, 27, -1, "search-bookmark" }, |
|
|
|
{ 3, 5, -1, "view-currentFileIn" }, |
|
{ 3, 7, -1, "view-showSymbol" }, |
|
{ 3, 8, -1, "view-zoom" }, |
|
{ 3, 9, -1, "view-moveCloneDocument" }, |
|
{ 3, 10, -1, "view-tab" }, |
|
{ 3, 19, -1, "view-collapseLevel" }, |
|
{ 3, 20, -1, "view-uncollapseLevel" }, |
|
{ 3, 24, -1, "view-project" }, |
|
|
|
{ 4, 5, -1, "encoding-characterSets" }, |
|
{ 4, 5, 0, "encoding-arabic" }, |
|
{ 4, 5, 1, "encoding-baltic" }, |
|
{ 4, 5, 2, "encoding-celtic" }, |
|
{ 4, 5, 3, "encoding-cyrillic" }, |
|
{ 4, 5, 4, "encoding-centralEuropean" }, |
|
{ 4, 5, 5, "encoding-chinese" }, |
|
{ 4, 5, 6, "encoding-easternEuropean" }, |
|
{ 4, 5, 7, "encoding-greek" }, |
|
{ 4, 5, 8, "encoding-hebrew" }, |
|
{ 4, 5, 9, "encoding-japanese" }, |
|
{ 4, 5, 10, "encoding-korean" }, |
|
{ 4, 5, 11, "encoding-northEuropean" }, |
|
{ 4, 5, 12, "encoding-thai" }, |
|
{ 4, 5, 13, "encoding-turkish" }, |
|
{ 4, 5, 14, "encoding-westernEuropean" }, |
|
{ 4, 5, 15, "encoding-vietnamese" }, |
|
|
|
{ 5, 25, -1, "language-userDefinedLanguage" }, |
|
|
|
{ 6, 4, -1, "settings-import" }, |
|
|
|
{ 7, 0, -1, "tools-md5" }, |
|
{ 7, 1, -1, "tools-sha1" }, |
|
{ 7, 2, -1, "tools-sha256" }, |
|
{ 7, 3, -1, "tools-sha512" }, |
|
|
|
{ 11, 0, -1, "window-sortby"}, |
|
|
|
{ -1, -1, -1, "" } // End of array |
|
}; |
|
|
|
MenuPosition& getMenuPosition(const char* id) |
|
{ |
|
int nbSubMenuPos = sizeof(g_menuFolderPositions) / sizeof(MenuPosition); |
|
|
|
for (int i = 0; i < nbSubMenuPos; ++i) |
|
{ |
|
if (strcmp(g_menuFolderPositions[i]._id, id) == 0) |
|
return g_menuFolderPositions[i]; |
|
} |
|
return g_menuFolderPositions[nbSubMenuPos - 1]; |
|
} |
|
|
|
void NativeLangSpeaker::init(TiXmlDocumentA *nativeLangDocRootA, bool loadIfEnglish) |
|
{ |
|
if (nativeLangDocRootA) |
|
{ |
|
_nativeLangA = nativeLangDocRootA->FirstChild("NotepadPlus"); |
|
if (_nativeLangA) |
|
{ |
|
_nativeLangA = _nativeLangA->FirstChild("Native-Langue"); |
|
if (_nativeLangA) |
|
{ |
|
TiXmlElementA *element = _nativeLangA->ToElement(); |
|
const char *rtl = element->Attribute("RTL"); |
|
|
|
if (rtl) |
|
{ |
|
_isRTL = (strcmp(rtl, "yes") == 0); |
|
|
|
if (_isRTL) |
|
{ |
|
const char* editZoneRtl = element->Attribute("editZoneRTL"); |
|
if (editZoneRtl) |
|
_isEditZoneRTL = !(strcmp(editZoneRtl, "no") == 0); |
|
else |
|
_isEditZoneRTL = true; |
|
} |
|
else |
|
_isEditZoneRTL = false; |
|
} |
|
else |
|
{ |
|
_isRTL = false; |
|
_isEditZoneRTL = false; |
|
} |
|
|
|
|
|
// get original file name (defined by Notpad++) from the attribute |
|
_fileName = element->Attribute("filename"); |
|
|
|
if (!loadIfEnglish && _fileName && stricmp("english.xml", _fileName) == 0) |
|
{ |
|
_nativeLangA = NULL; |
|
return; |
|
} |
|
// get encoding |
|
TiXmlDeclarationA *declaration = _nativeLangA->GetDocument()->FirstChild()->ToDeclaration(); |
|
if (declaration) |
|
{ |
|
const char * encodingStr = declaration->Encoding(); |
|
const EncodingMapper& em = EncodingMapper::getInstance(); |
|
int enc = em.getEncodingFromString(encodingStr); |
|
_nativeLangEncoding = (enc != -1)?enc:CP_ACP; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
wstring NativeLangSpeaker::getSubMenuEntryName(const char *nodeName) const |
|
{ |
|
if (!_nativeLangA) return L""; |
|
TiXmlNodeA *mainMenu = _nativeLangA->FirstChild("Menu"); |
|
if (!mainMenu) return L""; |
|
mainMenu = mainMenu->FirstChild("Main"); |
|
if (!mainMenu) return L""; |
|
TiXmlNodeA *entriesRoot = mainMenu->FirstChild("SubEntries"); |
|
if (!entriesRoot) return L""; |
|
|
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
|
|
for (TiXmlNodeA *childNode = entriesRoot->FirstChildElement("Item"); |
|
childNode ; |
|
childNode = childNode->NextSibling("Item") ) |
|
{ |
|
TiXmlElementA *element = childNode->ToElement(); |
|
|
|
const char *idName = element->Attribute("subMenuId"); |
|
if (idName) |
|
{ |
|
const char *name = element->Attribute("name"); |
|
if (!strcmp(idName, nodeName)) |
|
{ |
|
return wmc.char2wchar(name, _nativeLangEncoding); |
|
} |
|
} |
|
} |
|
return L""; |
|
} |
|
|
|
void purifyMenuString(string& s) |
|
{ |
|
// Remove & for CJK localization |
|
size_t posAndCJK = s.find("(&", 0); |
|
if (posAndCJK != string::npos) |
|
{ |
|
if (posAndCJK + 3 < s.length()) |
|
{ |
|
if (s[posAndCJK + 3] == ')') |
|
s.erase(posAndCJK, 4); |
|
} |
|
} |
|
|
|
// Remove & and transform && to & for all localizations |
|
for (int i = static_cast<int>(s.length()) - 1; i >= 0; --i) |
|
{ |
|
if (s[i] == '&') |
|
{ |
|
if (i-1 >= 0 && s[i-1] == '&') |
|
{ |
|
s.erase(i, 1); |
|
i -= 1; |
|
} |
|
else |
|
{ |
|
s.erase(i, 1); |
|
} |
|
} |
|
} |
|
|
|
// Remove ellipsis... |
|
size_t len = s.length(); |
|
if (len <= 3) |
|
return; |
|
size_t posEllipsis = len - 3; |
|
if (s.substr(posEllipsis) == "...") |
|
s.erase(posEllipsis, 3); |
|
|
|
} |
|
|
|
wstring NativeLangSpeaker::getNativeLangMenuString(int itemID, wstring inCaseOfFailureStr, bool removeMarkAnd) const |
|
{ |
|
if (!_nativeLangA) |
|
return inCaseOfFailureStr; |
|
|
|
TiXmlNodeA *node = _nativeLangA->FirstChild("Menu"); |
|
if (!node) return inCaseOfFailureStr; |
|
|
|
node = node->FirstChild("Main"); |
|
if (!node) return inCaseOfFailureStr; |
|
|
|
node = node->FirstChild("Commands"); |
|
if (!node) return inCaseOfFailureStr; |
|
|
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
|
|
for (TiXmlNodeA *childNode = node->FirstChildElement("Item"); |
|
childNode ; |
|
childNode = childNode->NextSibling("Item") ) |
|
{ |
|
TiXmlElementA *element = childNode->ToElement(); |
|
int id; |
|
if (element->Attribute("id", &id) && (id == itemID)) |
|
{ |
|
const char *name = element->Attribute("name"); |
|
if (name) |
|
{ |
|
string nameStr = name; |
|
|
|
if (removeMarkAnd) |
|
{ |
|
purifyMenuString(nameStr); |
|
} |
|
return wmc.char2wchar(nameStr.c_str(), _nativeLangEncoding); |
|
} |
|
} |
|
} |
|
return inCaseOfFailureStr; |
|
} |
|
|
|
wstring NativeLangSpeaker::getShortcutNameString(int itemID) const |
|
{ |
|
if (!_nativeLangA) |
|
return L""; |
|
|
|
TiXmlNodeA *node = _nativeLangA->FirstChild("Dialog"); |
|
if (!node) return L""; |
|
|
|
node = node->FirstChild("ShortcutMapper"); |
|
if (!node) return L""; |
|
|
|
node = node->FirstChild("MainCommandNames"); |
|
if (!node) return L""; |
|
|
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
|
|
for (TiXmlNodeA *childNode = node->FirstChildElement("Item"); |
|
childNode ; |
|
childNode = childNode->NextSibling("Item") ) |
|
{ |
|
TiXmlElementA *element = childNode->ToElement(); |
|
int id; |
|
if (element->Attribute("id", &id) && (id == itemID)) |
|
{ |
|
const char *name = element->Attribute("name"); |
|
if (name) |
|
{ |
|
return wmc.char2wchar(name, _nativeLangEncoding); |
|
} |
|
} |
|
} |
|
return L""; |
|
} |
|
|
|
wstring NativeLangSpeaker::getLocalizedStrFromID(const char *strID, const wstring& defaultString) const |
|
{ |
|
if (!_nativeLangA) |
|
return defaultString; |
|
|
|
if (!strID) |
|
return defaultString; |
|
|
|
TiXmlNodeA *node = _nativeLangA->FirstChild("MiscStrings"); |
|
if (!node) return defaultString; |
|
|
|
node = node->FirstChild(strID); |
|
if (!node) return defaultString; |
|
|
|
TiXmlElementA *element = node->ToElement(); |
|
|
|
const char *value = element->Attribute("value"); |
|
if (!value) return defaultString; |
|
|
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
return wmc.char2wchar(value, _nativeLangEncoding); |
|
} |
|
|
|
|
|
// Get string from map. |
|
// If string not found, get string from menu, then put it into map for the next use. |
|
void NativeLangSpeaker::getMainMenuEntryName(std::wstring& dest, HMENU hMenu, const char* menuId, const wchar_t* defaultDest) |
|
{ |
|
const auto iter = _shortcutMenuEntryNameMap.find(menuId); |
|
if (iter == _shortcutMenuEntryNameMap.end()) |
|
{ |
|
MenuPosition& menuPos = getMenuPosition(menuId); |
|
if (menuPos._x != -1 && menuPos._y == -1 && menuPos._z == -1) |
|
{ |
|
wchar_t str[MAX_PATH]; |
|
GetMenuString(hMenu, menuPos._x, str, MAX_PATH, MF_BYPOSITION); |
|
dest = str; |
|
dest.erase(std::remove(dest.begin(), dest.end(), '&'), dest.end()); |
|
_shortcutMenuEntryNameMap[menuId] = dest; |
|
|
|
} |
|
else |
|
{ |
|
if (strcmp(menuId, "about") == 0) |
|
{ |
|
dest = getShortcutMapperLangStr("AboutCategory", defaultDest); |
|
} |
|
else |
|
{ |
|
_shortcutMenuEntryNameMap[menuId] = defaultDest; |
|
dest = defaultDest; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
dest = iter->second; |
|
} |
|
} |
|
|
|
|
|
void NativeLangSpeaker::changeMenuLang(HMENU menuHandle) |
|
{ |
|
if (nullptr == _nativeLangA) |
|
return; |
|
|
|
TiXmlNodeA *mainMenu = _nativeLangA->FirstChild("Menu"); |
|
if (nullptr == mainMenu) |
|
return; |
|
|
|
mainMenu = mainMenu->FirstChild("Main"); |
|
if (nullptr == mainMenu) |
|
return; |
|
|
|
TiXmlNodeA *entriesRoot = mainMenu->FirstChild("Entries"); |
|
if (nullptr == entriesRoot) |
|
return; |
|
|
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
|
|
for (TiXmlNodeA *childNode = entriesRoot->FirstChildElement("Item"); |
|
childNode ; |
|
childNode = childNode->NextSibling("Item") ) |
|
{ |
|
TiXmlElementA *element = childNode->ToElement(); |
|
const char *menuIdStr = element->Attribute("menuId"); |
|
if (menuIdStr) |
|
{ |
|
MenuPosition & menuPos = getMenuPosition(menuIdStr); |
|
if (menuPos._x != -1) |
|
{ |
|
const char *name = element->Attribute("name"); |
|
const wchar_t *nameW = wmc.char2wchar(name, _nativeLangEncoding); |
|
::ModifyMenu(menuHandle, menuPos._x, MF_BYPOSITION, 0, nameW); |
|
} |
|
} |
|
} |
|
|
|
TiXmlNodeA *menuCommandsRoot = mainMenu->FirstChild("Commands"); |
|
for (TiXmlNodeA *childNode = menuCommandsRoot->FirstChildElement("Item"); |
|
childNode ; |
|
childNode = childNode->NextSibling("Item") ) |
|
{ |
|
TiXmlElementA *element = childNode->ToElement(); |
|
int id; |
|
element->Attribute("id", &id); |
|
const char *name = element->Attribute("name"); |
|
|
|
const wchar_t *nameW = wmc.char2wchar(name, _nativeLangEncoding); |
|
::ModifyMenu(menuHandle, id, MF_BYCOMMAND, id, nameW); |
|
} |
|
|
|
TiXmlNodeA *subEntriesRoot = mainMenu->FirstChild("SubEntries"); |
|
|
|
for (TiXmlNodeA *childNode = subEntriesRoot->FirstChildElement("Item"); |
|
childNode ; |
|
childNode = childNode->NextSibling("Item") ) |
|
{ |
|
TiXmlElementA* element = childNode->ToElement(); |
|
const char* subMenuIdStr = element->Attribute("subMenuId"); |
|
const char* name = element->Attribute("name"); |
|
|
|
if (nullptr == subMenuIdStr or nullptr == name) |
|
continue; |
|
|
|
MenuPosition& menuPos = getMenuPosition(subMenuIdStr); |
|
int x = menuPos._x; |
|
int y = menuPos._y; |
|
int z = menuPos._z; |
|
|
|
HMENU hSubMenu = ::GetSubMenu(menuHandle, x); |
|
if (!hSubMenu) |
|
continue; |
|
|
|
HMENU hSubMenu2 = ::GetSubMenu(hSubMenu, y); |
|
if (!hSubMenu2) |
|
continue; |
|
|
|
HMENU hMenu = hSubMenu; |
|
int pos = y; |
|
|
|
//const char *zStr = element->Attribute("posZ", &z); |
|
if (z != -1) |
|
{ |
|
HMENU hSubMenu3 = ::GetSubMenu(hSubMenu2, z); |
|
if (!hSubMenu3) |
|
continue; |
|
hMenu = hSubMenu2; |
|
pos = z; |
|
} |
|
|
|
const wchar_t *nameW = wmc.char2wchar(name, _nativeLangEncoding); |
|
::ModifyMenu(hMenu, pos, MF_BYPOSITION, 0, nameW); |
|
} |
|
} |
|
|
|
|
|
static const int tabCmSubMenuEntryPos[] = |
|
{ |
|
// +-------------- The submenu entry item position on the top level of tab context menu |
|
// | |
|
// | +------- Index order (CMDID: Context Menu submenu entry ID): in <TabBar> of english.xml - the number and the order of this array should be synchronized with <TabBar> |
|
// | | |
|
// | | |
|
// | | |
|
1, // 0 Close Multiple Tabs |
|
4, // 1 Open into |
|
13, // 2 Copy to Clipboard |
|
14, // 3 Move Document |
|
15, // 4 Apply Color to Tab |
|
}; |
|
|
|
|
|
void NativeLangSpeaker::changeLangTabContextMenu(HMENU hCM) |
|
{ |
|
if (_nativeLangA != nullptr) |
|
{ |
|
TiXmlNodeA *tabBarMenu = _nativeLangA->FirstChild("Menu"); |
|
if (tabBarMenu) |
|
{ |
|
tabBarMenu = tabBarMenu->FirstChild("TabBar"); |
|
if (tabBarMenu) |
|
{ |
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
int nbSubEntry = sizeof(tabCmSubMenuEntryPos)/sizeof(int); |
|
|
|
for (TiXmlNodeA *childNode = tabBarMenu->FirstChildElement("Item"); |
|
childNode ; |
|
childNode = childNode->NextSibling("Item") ) |
|
{ |
|
TiXmlElementA *element = childNode->ToElement(); |
|
int cmd; |
|
const char *cmdStr = element->Attribute("CMDID", &cmd); |
|
if (!cmdStr || (cmd < 0)) |
|
continue; |
|
|
|
const char* pName = element->Attribute("name"); |
|
const wchar_t* pNameW = wmc.char2wchar(pName, _nativeLangEncoding); |
|
|
|
if (cmd > nbSubEntry) // menu item CMD |
|
{ |
|
::ModifyMenu(hCM, cmd, MF_BYCOMMAND, cmd, pNameW); |
|
|
|
// Here CMDID are default Tab Context Menu commands. |
|
// User can always add any command beyond the default commands in tabContextMenu.xml file. |
|
// But such command won't be translated. |
|
} |
|
else // sub-menu entry id. |
|
{ |
|
if (!NppParameters::getInstance().hasCustomTabContextMenu()) // The customized sub-menu entry cannot be translated. |
|
// User can use his/her native language as value of attribute "FolderName" in tabContextMenu.xml file. |
|
{ |
|
int subEntryIndex = cmd; |
|
int subEntrypos = tabCmSubMenuEntryPos[subEntryIndex]; |
|
::ModifyMenu(hCM, subEntrypos, MF_BYPOSITION, cmd, pNameW); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
void NativeLangSpeaker::changeLangTabDropContextMenu(HMENU hCM) |
|
{ |
|
const int POS_GO2VIEW = 0; |
|
const int POS_CLONE2VIEW = 1; |
|
|
|
if (_nativeLangA) |
|
{ |
|
const char *goToViewA = nullptr; |
|
const char *cloneToViewA = nullptr; |
|
|
|
TiXmlNodeA *tabBarMenu = _nativeLangA->FirstChild("Menu"); |
|
if (tabBarMenu) |
|
tabBarMenu = tabBarMenu->FirstChild("TabBar"); |
|
|
|
if (tabBarMenu) |
|
{ |
|
for (TiXmlNodeA *childNode = tabBarMenu->FirstChildElement("Item"); |
|
childNode ; |
|
childNode = childNode->NextSibling("Item") ) |
|
{ |
|
TiXmlElementA *element = childNode->ToElement(); |
|
int ordre; |
|
element->Attribute("CMDID", &ordre); |
|
if (ordre == IDM_VIEW_GOTO_ANOTHER_VIEW) |
|
goToViewA = element->Attribute("name"); |
|
else if (ordre == IDM_VIEW_CLONE_TO_ANOTHER_VIEW) |
|
cloneToViewA = element->Attribute("name"); |
|
} |
|
} |
|
|
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
if (goToViewA && goToViewA[0]) |
|
{ |
|
const wchar_t *goToViewG = wmc.char2wchar(goToViewA, _nativeLangEncoding); |
|
int cmdID = ::GetMenuItemID(hCM, POS_GO2VIEW); |
|
::ModifyMenu(hCM, POS_GO2VIEW, MF_BYPOSITION|MF_STRING, cmdID, goToViewG); |
|
} |
|
if (cloneToViewA && cloneToViewA[0]) |
|
{ |
|
const wchar_t *cloneToViewG = wmc.char2wchar(cloneToViewA, _nativeLangEncoding); |
|
int cmdID = ::GetMenuItemID(hCM, POS_CLONE2VIEW); |
|
::ModifyMenu(hCM, POS_CLONE2VIEW, MF_BYPOSITION|MF_STRING, cmdID, cloneToViewG); |
|
} |
|
} |
|
} |
|
|
|
void NativeLangSpeaker::changeLangTrayIconContexMenu(HMENU hCM) |
|
{ |
|
if (!_nativeLangA) return; |
|
|
|
TiXmlNodeA *tryIconMenu = _nativeLangA->FirstChild("Menu"); |
|
if (!tryIconMenu) return; |
|
|
|
tryIconMenu = tryIconMenu->FirstChild("TrayIcon"); |
|
if (!tryIconMenu) return; |
|
|
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
|
|
for (TiXmlNodeA *childNode = tryIconMenu->FirstChildElement("Item"); |
|
childNode ; |
|
childNode = childNode->NextSibling("Item") ) |
|
{ |
|
TiXmlElementA *element = childNode->ToElement(); |
|
int id; |
|
const char *sentinel = element->Attribute("id", &id); |
|
const char *name = element->Attribute("name"); |
|
if (sentinel && (name && name[0])) |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(name, _nativeLangEncoding); |
|
::ModifyMenu(hCM, id, MF_BYCOMMAND, id, nameW); |
|
} |
|
} |
|
} |
|
|
|
void NativeLangSpeaker::changeConfigLang(HWND hDlg) |
|
{ |
|
if (nullptr == _nativeLangA) |
|
return; |
|
|
|
TiXmlNodeA *styleConfDlgNode = _nativeLangA->FirstChild("Dialog"); |
|
if (!styleConfDlgNode) |
|
return; |
|
|
|
styleConfDlgNode = styleConfDlgNode->FirstChild("StyleConfig"); |
|
if (!styleConfDlgNode) return; |
|
|
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
|
|
// Set Title |
|
const char *titre = (styleConfDlgNode->ToElement())->Attribute("title"); |
|
|
|
if ((titre && titre[0]) && hDlg) |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
::SetWindowText(hDlg, nameW); |
|
} |
|
for (TiXmlNodeA *childNode = styleConfDlgNode->FirstChildElement("Item"); |
|
childNode ; |
|
childNode = childNode->NextSibling("Item") ) |
|
{ |
|
TiXmlElementA *element = childNode->ToElement(); |
|
int id; |
|
const char *sentinel = element->Attribute("id", &id); |
|
const char *name = element->Attribute("name"); |
|
if (sentinel && (name && name[0])) |
|
{ |
|
HWND hItem = ::GetDlgItem(hDlg, id); |
|
if (hItem) |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(name, _nativeLangEncoding); |
|
::SetWindowText(hItem, nameW); |
|
} |
|
} |
|
} |
|
styleConfDlgNode = styleConfDlgNode->FirstChild("SubDialog"); |
|
|
|
for (TiXmlNodeA *childNode = styleConfDlgNode->FirstChildElement("Item"); |
|
childNode ; |
|
childNode = childNode->NextSibling("Item") ) |
|
{ |
|
TiXmlElementA *element = childNode->ToElement(); |
|
int id; |
|
const char *sentinel = element->Attribute("id", &id); |
|
const char *name = element->Attribute("name"); |
|
if (sentinel && (name && name[0])) |
|
{ |
|
HWND hItem = ::GetDlgItem(hDlg, id); |
|
if (hItem) |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(name, _nativeLangEncoding); |
|
::SetWindowText(hItem, nameW); |
|
resizeCheckboxRadioBtn(hItem); |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
void NativeLangSpeaker::changeStyleCtrlsLang(HWND hDlg, int *idArray, const char **translatedText) |
|
{ |
|
const int iColorStyle = 0; |
|
const int iUnderline = 8; |
|
|
|
HWND hItem; |
|
for (int i = iColorStyle ; i < (iUnderline + 1) ; ++i) |
|
{ |
|
if (translatedText[i] && translatedText[i][0]) |
|
{ |
|
hItem = ::GetDlgItem(hDlg, idArray[i]); |
|
if (hItem) |
|
{ |
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
const wchar_t *nameW = wmc.char2wchar(translatedText[i], _nativeLangEncoding); |
|
::SetWindowText(hItem, nameW); |
|
} |
|
} |
|
} |
|
} |
|
|
|
void NativeLangSpeaker::changeUserDefineLangPopupDlg(HWND hDlg) |
|
{ |
|
if (!_nativeLangA) return; |
|
|
|
TiXmlNodeA *userDefineDlgNode = _nativeLangA->FirstChild("Dialog"); |
|
if (!userDefineDlgNode) return; |
|
|
|
userDefineDlgNode = userDefineDlgNode->FirstChild("UserDefine"); |
|
if (!userDefineDlgNode) return; |
|
|
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
|
|
TiXmlNodeA *stylerDialogNode = userDefineDlgNode->FirstChild("StylerDialog"); |
|
if (!stylerDialogNode) return; |
|
|
|
const char *titre = (stylerDialogNode->ToElement())->Attribute("title"); |
|
if (titre &&titre[0]) |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
::SetWindowText(hDlg, nameW); |
|
} |
|
for (TiXmlNodeA *childNode = stylerDialogNode->FirstChildElement("Item"); |
|
childNode ; |
|
childNode = childNode->NextSibling("Item") ) |
|
{ |
|
TiXmlElementA *element = childNode->ToElement(); |
|
int id; |
|
const char *sentinel = element->Attribute("id", &id); |
|
const char *name = element->Attribute("name"); |
|
if (sentinel && (name && name[0])) |
|
{ |
|
HWND hItem = ::GetDlgItem(hDlg, id); |
|
if (hItem) |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(name, _nativeLangEncoding); |
|
::SetWindowText(hItem, nameW); |
|
resizeCheckboxRadioBtn(hItem); |
|
} |
|
} |
|
} |
|
} |
|
|
|
void NativeLangSpeaker::changeUserDefineLang(UserDefineDialog *userDefineDlg) |
|
{ |
|
if (!_nativeLangA) return; |
|
|
|
TiXmlNodeA *userDefineDlgNode = _nativeLangA->FirstChild("Dialog"); |
|
if (!userDefineDlgNode) return; |
|
|
|
userDefineDlgNode = userDefineDlgNode->FirstChild("UserDefine"); |
|
if (!userDefineDlgNode) return; |
|
|
|
HWND hDlg = userDefineDlg->getHSelf(); |
|
|
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
|
|
// Set Title |
|
const char *titre = (userDefineDlgNode->ToElement())->Attribute("title"); |
|
if (titre && titre[0]) |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
::SetWindowText(hDlg, nameW); |
|
} |
|
|
|
for (TiXmlNodeA *childNode = userDefineDlgNode->FirstChildElement("Item"); |
|
childNode ; |
|
childNode = childNode->NextSibling("Item") ) |
|
{ |
|
TiXmlElementA *element = childNode->ToElement(); |
|
int id; |
|
const char *sentinel = element->Attribute("id", &id); |
|
const char *name = element->Attribute("name"); |
|
|
|
if (sentinel && (name && name[0])) |
|
{ |
|
if (id > 30) |
|
{ |
|
HWND hItem = ::GetDlgItem(hDlg, id); |
|
if (hItem) |
|
{ |
|
if (id == IDC_DOCK_BUTTON && userDefineDlg->isDocked()) |
|
{ |
|
wstring undockStr = getAttrNameByIdStr(L"Undock", userDefineDlgNode, std::to_string(IDC_UNDOCK_BUTTON).c_str()); |
|
::SetWindowText(hItem, undockStr.c_str()); |
|
} |
|
else |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(name, _nativeLangEncoding); |
|
::SetWindowText(hItem, nameW); |
|
resizeCheckboxRadioBtn(hItem); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
const int nbDlg = 4; |
|
HWND hDlgArrary[nbDlg]{}; |
|
hDlgArrary[0] = userDefineDlg->getFolderHandle(); |
|
hDlgArrary[1] = userDefineDlg->getKeywordsHandle(); |
|
hDlgArrary[2] = userDefineDlg->getCommentHandle(); |
|
hDlgArrary[3] = userDefineDlg->getSymbolHandle(); |
|
|
|
const char nodeNameArray[nbDlg][16] = {"Folder", "Keywords", "Comment", "Operator"}; |
|
|
|
for (int i = 0 ; i < nbDlg ; ++i) |
|
{ |
|
TiXmlNodeA *node = userDefineDlgNode->FirstChild(nodeNameArray[i]); |
|
|
|
if (node) |
|
{ |
|
// Set Title |
|
titre = (node->ToElement())->Attribute("title"); |
|
if (titre &&titre[0]) |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
userDefineDlg->setTabName(i, nameW); |
|
} |
|
for (TiXmlNodeA *childNode = node->FirstChildElement("Item"); |
|
childNode ; |
|
childNode = childNode->NextSibling("Item") ) |
|
{ |
|
TiXmlElementA *element = childNode->ToElement(); |
|
int id; |
|
const char *sentinel = element->Attribute("id", &id); |
|
const char *name = element->Attribute("name"); |
|
if (sentinel && (name && name[0])) |
|
{ |
|
HWND hItem = ::GetDlgItem(hDlgArrary[i], id); |
|
if (hItem) |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(name, _nativeLangEncoding); |
|
::SetWindowText(hItem, nameW); |
|
resizeCheckboxRadioBtn(hItem); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
userDefineDlg->redraw(); |
|
} |
|
|
|
void NativeLangSpeaker::changeFindReplaceDlgLang(FindReplaceDlg & findReplaceDlg) |
|
{ |
|
if (_nativeLangA) |
|
{ |
|
TiXmlNodeA *dlgNode = _nativeLangA->FirstChild("Dialog"); |
|
if (dlgNode) |
|
{ |
|
NppParameters& nppParam = NppParameters::getInstance(); |
|
dlgNode = searchDlgNode(dlgNode, "Find"); |
|
if (dlgNode) |
|
{ |
|
const char *titre1 = (dlgNode->ToElement())->Attribute("titleFind"); |
|
const char *titre2 = (dlgNode->ToElement())->Attribute("titleReplace"); |
|
const char *titre3 = (dlgNode->ToElement())->Attribute("titleFindInFiles"); |
|
const char *titre4 = (dlgNode->ToElement())->Attribute("titleFindInProjects"); |
|
const char *titre5 = (dlgNode->ToElement())->Attribute("titleMark"); |
|
|
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
|
|
if (titre1 && titre1[0]) |
|
{ |
|
basic_string<wchar_t> nameW = wmc.char2wchar(titre1, _nativeLangEncoding); |
|
nppParam.getFindDlgTabTitiles()._find = nameW; |
|
findReplaceDlg.changeTabName(FIND_DLG, nppParam.getFindDlgTabTitiles()._find.c_str()); |
|
} |
|
if (titre2 && titre2[0]) |
|
{ |
|
basic_string<wchar_t> nameW = wmc.char2wchar(titre2, _nativeLangEncoding); |
|
nppParam.getFindDlgTabTitiles()._replace = nameW; |
|
findReplaceDlg.changeTabName(REPLACE_DLG, nppParam.getFindDlgTabTitiles()._replace.c_str()); |
|
} |
|
if (titre3 && titre3[0]) |
|
{ |
|
basic_string<wchar_t> nameW = wmc.char2wchar(titre3, _nativeLangEncoding); |
|
nppParam.getFindDlgTabTitiles()._findInFiles = nameW; |
|
findReplaceDlg.changeTabName(FINDINFILES_DLG, nppParam.getFindDlgTabTitiles()._findInFiles.c_str()); |
|
} |
|
if (titre4 && titre4[0]) |
|
{ |
|
basic_string<wchar_t> nameW = wmc.char2wchar(titre4, _nativeLangEncoding); |
|
nppParam.getFindDlgTabTitiles()._findInProjects = nameW; |
|
findReplaceDlg.changeTabName(FINDINPROJECTS_DLG, nppParam.getFindDlgTabTitiles()._findInProjects.c_str()); |
|
} |
|
if (titre5 && titre5[0]) |
|
{ |
|
basic_string<wchar_t> nameW = wmc.char2wchar(titre5, _nativeLangEncoding); |
|
nppParam.getFindDlgTabTitiles()._mark = nameW; |
|
findReplaceDlg.changeTabName(MARK_DLG, nppParam.getFindDlgTabTitiles()._mark.c_str()); |
|
} |
|
} |
|
} |
|
} |
|
changeDlgLang(findReplaceDlg.getHSelf(), "Find"); |
|
} |
|
|
|
void NativeLangSpeaker::changePluginsAdminDlgLang(PluginsAdminDlg & pluginsAdminDlg) |
|
{ |
|
if (_nativeLangA) |
|
{ |
|
TiXmlNodeA *dlgNode = _nativeLangA->FirstChild("Dialog"); |
|
if (dlgNode) |
|
{ |
|
dlgNode = searchDlgNode(dlgNode, "PluginsAdminDlg"); |
|
if (dlgNode) |
|
{ |
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
|
|
TiXmlNodeA *ColumnPluginNode = dlgNode->FirstChild("ColumnPlugin"); |
|
if (ColumnPluginNode) |
|
{ |
|
const char *name = (ColumnPluginNode->ToElement())->Attribute("name"); |
|
if (name && name[0]) |
|
{ |
|
basic_string<wchar_t> nameW = wmc.char2wchar(name, _nativeLangEncoding); |
|
pluginsAdminDlg.changeColumnName(COLUMN_PLUGIN, nameW.c_str()); |
|
} |
|
} |
|
|
|
TiXmlNodeA *ColumnVersionNode = dlgNode->FirstChild("ColumnVersion"); |
|
if (ColumnVersionNode) |
|
{ |
|
const char *name = (ColumnVersionNode->ToElement())->Attribute("name"); |
|
if (name && name[0]) |
|
{ |
|
basic_string<wchar_t> nameW = wmc.char2wchar(name, _nativeLangEncoding); |
|
pluginsAdminDlg.changeColumnName(COLUMN_VERSION, nameW.c_str()); |
|
} |
|
} |
|
|
|
const char *titre1 = (dlgNode->ToElement())->Attribute("titleAvailable"); |
|
const char *titre2 = (dlgNode->ToElement())->Attribute("titleUpdates"); |
|
const char *titre3 = (dlgNode->ToElement())->Attribute("titleInstalled"); |
|
const char *titre4 = (dlgNode->ToElement())->Attribute("titleIncompatible"); |
|
|
|
if (titre1 && titre1[0]) |
|
{ |
|
basic_string<wchar_t> nameW = wmc.char2wchar(titre1, _nativeLangEncoding); |
|
pluginsAdminDlg.changeTabName(AVAILABLE_LIST, nameW.c_str()); |
|
} |
|
if (titre2 && titre2[0]) |
|
{ |
|
basic_string<wchar_t> nameW = wmc.char2wchar(titre2, _nativeLangEncoding); |
|
pluginsAdminDlg.changeTabName(UPDATES_LIST, nameW.c_str()); |
|
} |
|
if (titre3 && titre3[0]) |
|
{ |
|
basic_string<wchar_t> nameW = wmc.char2wchar(titre3, _nativeLangEncoding); |
|
pluginsAdminDlg.changeTabName(INSTALLED_LIST, nameW.c_str()); |
|
} |
|
if (titre4 && titre4[0]) |
|
{ |
|
basic_string<wchar_t> nameW = wmc.char2wchar(titre4, _nativeLangEncoding); |
|
pluginsAdminDlg.changeTabName(INCOMPATIBLE_LIST, nameW.c_str()); |
|
} |
|
} |
|
|
|
changeDlgLang(pluginsAdminDlg.getHSelf(), "PluginsAdminDlg"); |
|
} |
|
} |
|
} |
|
|
|
void NativeLangSpeaker::changePrefereceDlgLang(PreferenceDlg & preference) |
|
{ |
|
auto currentSel = preference.getListSelectedIndex(); |
|
changeDlgLang(preference.getHSelf(), "Preference"); |
|
|
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
const size_t titreMaxSize = 128; |
|
char titre[titreMaxSize]; |
|
changeDlgLang(preference._generalSubDlg.getHSelf(), "Global", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"Global", nameW); |
|
} |
|
|
|
changeDlgLang(preference._editingSubDlg.getHSelf(), "Scintillas", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"Scintillas", nameW); |
|
} |
|
|
|
changeDlgLang(preference._editing2SubDlg.getHSelf(), "Scintillas2", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"Scintillas2", nameW); |
|
} |
|
|
|
changeDlgLang(preference._darkModeSubDlg.getHSelf(), "DarkMode", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t* nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"DarkMode", nameW); |
|
} |
|
|
|
changeDlgLang(preference._marginsBorderEdgeSubDlg.getHSelf(), "MarginsBorderEdge", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"MarginsBorderEdge", nameW); |
|
} |
|
|
|
changeDlgLang(preference._newDocumentSubDlg.getHSelf(), "NewDoc", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"NewDoc", nameW); |
|
} |
|
|
|
changeDlgLang(preference._defaultDirectorySubDlg.getHSelf(), "DefaultDir", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"DefaultDir", nameW); |
|
} |
|
|
|
changeDlgLang(preference._recentFilesHistorySubDlg.getHSelf(), "RecentFilesHistory", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"RecentFilesHistory", nameW); |
|
} |
|
|
|
changeDlgLang(preference._fileAssocDlg.getHSelf(), "FileAssoc", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"FileAssoc", nameW); |
|
} |
|
|
|
changeDlgLang(preference._languageSubDlg.getHSelf(), "Language", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"Language", nameW); |
|
} |
|
|
|
changeDlgLang(preference._indentationSubDlg.getHSelf(), "Indentation", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"Indentation", nameW); |
|
} |
|
|
|
changeDlgLang(preference._highlightingSubDlg.getHSelf(), "Highlighting", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"Highlighting", nameW); |
|
} |
|
|
|
changeDlgLang(preference._printSubDlg.getHSelf(), "Print", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"Print", nameW); |
|
} |
|
|
|
changeDlgLang(preference._searchingSubDlg.getHSelf(), "Searching", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t* nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"Searching", nameW); |
|
} |
|
|
|
changeDlgLang(preference._miscSubDlg.getHSelf(), "MISC", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"MISC", nameW); |
|
} |
|
changeDlgLang(preference._backupSubDlg.getHSelf(), "Backup", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"Backup", nameW); |
|
} |
|
|
|
changeDlgLang(preference._autoCompletionSubDlg.getHSelf(), "AutoCompletion", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"AutoCompletion", nameW); |
|
} |
|
|
|
changeDlgLang(preference._multiInstanceSubDlg.getHSelf(), "MultiInstance", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"MultiInstance", nameW); |
|
} |
|
|
|
changeDlgLang(preference._delimiterSubDlg.getHSelf(), "Delimiter", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"Delimiter", nameW); |
|
} |
|
|
|
changeDlgLang(preference._performanceSubDlg.getHSelf(), "Performance", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"Performance", nameW); |
|
} |
|
|
|
changeDlgLang(preference._cloudAndLinkSubDlg.getHSelf(), "Cloud", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"Cloud", nameW); |
|
} |
|
|
|
changeDlgLang(preference._searchEngineSubDlg.getHSelf(), "SearchEngine", titre, titreMaxSize); |
|
if (titre[0] != '\0') |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(titre, _nativeLangEncoding); |
|
preference.renameDialogTitle(L"SearchEngine", nameW); |
|
} |
|
|
|
preference._darkModeSubDlg.destroyResetMenu(); |
|
|
|
preference.setListSelection(currentSel); |
|
} |
|
|
|
void NativeLangSpeaker::changeShortcutLang() |
|
{ |
|
if (!_nativeLangA) return; |
|
|
|
NppParameters& nppParam = NppParameters::getInstance(); |
|
vector<CommandShortcut> & mainshortcuts = nppParam.getUserShortcuts(); |
|
vector<ScintillaKeyMap> & scinshortcuts = nppParam.getScintillaKeyList(); |
|
|
|
TiXmlNodeA *shortcuts = _nativeLangA->FirstChild("Shortcuts"); |
|
if (!shortcuts) return; |
|
|
|
shortcuts = shortcuts->FirstChild("Main"); |
|
if (!shortcuts) return; |
|
|
|
TiXmlNodeA *entriesRoot = shortcuts->FirstChild("Entries"); |
|
if (!entriesRoot) return; |
|
|
|
for (TiXmlNodeA *childNode = entriesRoot->FirstChildElement("Item"); |
|
childNode ; |
|
childNode = childNode->NextSibling("Item") ) |
|
{ |
|
TiXmlElementA *element = childNode->ToElement(); |
|
int index, id; |
|
if (element->Attribute("index", &index) && element->Attribute("id", &id)) |
|
{ |
|
if (index > -1 && static_cast<size_t>(index) < mainshortcuts.size()) //valid index only |
|
{ |
|
const char *name = element->Attribute("name"); |
|
CommandShortcut & csc = mainshortcuts[index]; |
|
if (csc.getID() == (unsigned long)id) |
|
{ |
|
csc.setName(name); |
|
} |
|
} |
|
} |
|
} |
|
|
|
//Scintilla |
|
shortcuts = _nativeLangA->FirstChild("Shortcuts"); |
|
if (!shortcuts) return; |
|
|
|
shortcuts = shortcuts->FirstChild("Scintilla"); |
|
if (!shortcuts) return; |
|
|
|
entriesRoot = shortcuts->FirstChild("Entries"); |
|
if (!entriesRoot) return; |
|
|
|
for (TiXmlNodeA *childNode = entriesRoot->FirstChildElement("Item"); |
|
childNode ; |
|
childNode = childNode->NextSibling("Item") ) |
|
{ |
|
TiXmlElementA *element = childNode->ToElement(); |
|
int index; |
|
if (element->Attribute("index", &index)) |
|
{ |
|
if (index > -1 && static_cast<size_t>(index) < scinshortcuts.size()) //valid index only |
|
{ |
|
const char *name = element->Attribute("name"); |
|
ScintillaKeyMap & skm = scinshortcuts[index]; |
|
skm.setName(name); |
|
} |
|
} |
|
} |
|
|
|
} |
|
|
|
wstring NativeLangSpeaker::getShortcutMapperLangStr(const char *nodeName, const wchar_t *defaultStr) const |
|
{ |
|
if (!_nativeLangA) return defaultStr; |
|
|
|
TiXmlNodeA *targetNode = _nativeLangA->FirstChild("Dialog"); |
|
if (!targetNode) return defaultStr; |
|
|
|
targetNode = targetNode->FirstChild("ShortcutMapper"); |
|
if (!targetNode) return defaultStr; |
|
|
|
targetNode = targetNode->FirstChild(nodeName); |
|
if (!targetNode) return defaultStr; |
|
|
|
const char *name = (targetNode->ToElement())->Attribute("name"); |
|
if (name && name[0]) |
|
{ |
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
return wmc.char2wchar(name, _nativeLangEncoding); |
|
} |
|
|
|
return defaultStr; |
|
} |
|
|
|
|
|
TiXmlNodeA * NativeLangSpeaker::searchDlgNode(TiXmlNodeA *node, const char *dlgTagName) |
|
{ |
|
TiXmlNodeA *dlgNode = node->FirstChild(dlgTagName); |
|
if (dlgNode) return dlgNode; |
|
for (TiXmlNodeA *childNode = node->FirstChildElement(); |
|
childNode ; |
|
childNode = childNode->NextSibling() ) |
|
{ |
|
dlgNode = searchDlgNode(childNode, dlgTagName); |
|
if (dlgNode) return dlgNode; |
|
} |
|
return NULL; |
|
} |
|
|
|
bool NativeLangSpeaker::getDoSaveOrNotStrings(wstring& title, wstring& msg) |
|
{ |
|
if (!_nativeLangA) return false; |
|
|
|
TiXmlNodeA *dlgNode = _nativeLangA->FirstChild("Dialog"); |
|
if (!dlgNode) return false; |
|
|
|
dlgNode = searchDlgNode(dlgNode, "DoSaveOrNot"); |
|
if (!dlgNode) return false; |
|
|
|
const char *title2set = (dlgNode->ToElement())->Attribute("title"); |
|
if (!title2set || !title2set[0]) return false; |
|
|
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
const wchar_t *titleW = wmc.char2wchar(title2set, _nativeLangEncoding); |
|
title = titleW; |
|
|
|
for (TiXmlNodeA *childNode = dlgNode->FirstChildElement("Item"); |
|
childNode; |
|
childNode = childNode->NextSibling("Item")) |
|
{ |
|
TiXmlElementA *element = childNode->ToElement(); |
|
int id; |
|
const char *sentinel = element->Attribute("id", &id); |
|
const char *name = element->Attribute("name"); |
|
if (sentinel && (name && name[0])) |
|
{ |
|
if (id == 1761) |
|
{ |
|
const wchar_t *msgW = wmc.char2wchar(name, _nativeLangEncoding); |
|
msg = msgW; |
|
|
|
return true; |
|
} |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
bool NativeLangSpeaker::changeDlgLang(HWND hDlg, const char *dlgTagName, char *title, size_t titleMaxSize) |
|
{ |
|
if (title) |
|
title[0] = '\0'; |
|
|
|
if (!_nativeLangA) return false; |
|
|
|
TiXmlNodeA *dlgNode = _nativeLangA->FirstChild("Dialog"); |
|
if (!dlgNode) return false; |
|
|
|
dlgNode = searchDlgNode(dlgNode, dlgTagName); |
|
if (!dlgNode) return false; |
|
|
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
|
|
// Set Title |
|
const char *title2set = (dlgNode->ToElement())->Attribute("title"); |
|
if ((title2set && title2set[0]) && hDlg) |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(title2set, _nativeLangEncoding); |
|
::SetWindowText(hDlg, nameW); |
|
|
|
if (title && titleMaxSize) |
|
strncpy(title, title2set, titleMaxSize - 1); |
|
} |
|
|
|
// Set the text of child control |
|
for (TiXmlNodeA *childNode = dlgNode->FirstChildElement("Item"); |
|
childNode ; |
|
childNode = childNode->NextSibling("Item") ) |
|
{ |
|
TiXmlElementA *element = childNode->ToElement(); |
|
int id; |
|
const char *sentinel = element->Attribute("id", &id); |
|
const char *name = element->Attribute("name"); |
|
if (sentinel && (name && name[0])) |
|
{ |
|
HWND hItem = ::GetDlgItem(hDlg, id); |
|
if (hItem) |
|
{ |
|
const wchar_t *nameW = wmc.char2wchar(name, _nativeLangEncoding); |
|
::SetWindowText(hItem, nameW); |
|
resizeCheckboxRadioBtn(hItem); |
|
} |
|
} |
|
} |
|
|
|
// Set the text of child control |
|
for (TiXmlNodeA *childNode = dlgNode->FirstChildElement("ComboBox"); |
|
childNode; |
|
childNode = childNode->NextSibling("ComboBox")) |
|
{ |
|
std::vector<wstring> comboElms; |
|
TiXmlElementA *element = childNode->ToElement(); |
|
int id; |
|
element->Attribute("id", &id); |
|
HWND hCombo = ::GetDlgItem(hDlg, id); |
|
if (!hCombo) return false; |
|
|
|
for (TiXmlNodeA *gChildNode = childNode->FirstChildElement("Element"); |
|
gChildNode; |
|
gChildNode = gChildNode->NextSibling("Element")) |
|
{ |
|
TiXmlElementA *comBoelement = gChildNode->ToElement(); |
|
const char *name = comBoelement->Attribute("name"); |
|
const wchar_t *nameW = wmc.char2wchar(name, _nativeLangEncoding); |
|
comboElms.push_back(nameW); |
|
} |
|
|
|
size_t count = ::SendMessage(hCombo, CB_GETCOUNT, 0, 0); |
|
if (count == comboElms.size()) |
|
{ |
|
// get selected index |
|
auto selIndex = ::SendMessage(hCombo, CB_GETCURSEL, 0, 0); |
|
|
|
// remove all old items |
|
::SendMessage(hCombo, CB_RESETCONTENT, 0, 0); |
|
|
|
// add translated entries |
|
for (const auto& i : comboElms) |
|
{ |
|
::SendMessage(hCombo, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(i.c_str())); |
|
} |
|
|
|
// restore selected index |
|
::SendMessage(hCombo, CB_SETCURSEL, selIndex, 0); |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
bool NativeLangSpeaker::getMsgBoxLang(const char *msgBoxTagName, wstring & title, wstring & message) |
|
{ |
|
title = L""; |
|
message = L""; |
|
|
|
if (!_nativeLangA) return false; |
|
|
|
TiXmlNodeA *msgBoxNode = _nativeLangA->FirstChild("MessageBox"); |
|
if (!msgBoxNode) return false; |
|
|
|
msgBoxNode = searchDlgNode(msgBoxNode, msgBoxTagName); |
|
if (!msgBoxNode) return false; |
|
|
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
|
|
// Set Title |
|
const char *titre = (msgBoxNode->ToElement())->Attribute("title"); |
|
const char *msg = (msgBoxNode->ToElement())->Attribute("message"); |
|
if ((titre && titre[0]) && (msg && msg[0])) |
|
{ |
|
title = wmc.char2wchar(titre, _nativeLangEncoding); |
|
message = wmc.char2wchar(msg, _nativeLangEncoding); |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
wstring NativeLangSpeaker::getDlgLangMenuStr(const char* firstLevelNodeName, const char* secondLevelNodeName, int cmdID, const wchar_t* defaultStr) const |
|
{ |
|
if (!_nativeLangA) return defaultStr; |
|
|
|
TiXmlNodeA *targetNode = _nativeLangA->FirstChild(firstLevelNodeName); |
|
if (!targetNode) return defaultStr; |
|
|
|
if (secondLevelNodeName && secondLevelNodeName[0]) |
|
{ |
|
targetNode = targetNode->FirstChild(secondLevelNodeName); |
|
if (!targetNode) return defaultStr; |
|
} |
|
|
|
targetNode = targetNode->FirstChild("Menu"); |
|
if (!targetNode) return defaultStr; |
|
|
|
const char *name = NULL; |
|
for (TiXmlNodeA *childNode = targetNode->FirstChildElement("Item"); |
|
childNode; |
|
childNode = childNode->NextSibling("Item")) |
|
{ |
|
TiXmlElementA *element = childNode->ToElement(); |
|
int id; |
|
const char *idStr = element->Attribute("id", &id); |
|
|
|
if (idStr && id == cmdID) |
|
{ |
|
name = element->Attribute("name"); |
|
break; |
|
} |
|
} |
|
|
|
if (name && name[0]) |
|
{ |
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
return wmc.char2wchar(name, _nativeLangEncoding); |
|
} |
|
return defaultStr; |
|
} |
|
|
|
std::wstring NativeLangSpeaker::getCmdLangStr(std::vector<const char*> nodeNames, int cmdID, const wchar_t* defaultStr) const |
|
{ |
|
if (!_nativeLangA) return defaultStr; |
|
TiXmlNodeA* targetNode = _nativeLangA->FirstChild(nodeNames.at(0)); |
|
if (targetNode == nullptr) |
|
return defaultStr; |
|
|
|
auto it = nodeNames.begin(); |
|
++it; |
|
|
|
for (auto end = nodeNames.end(); it != end; ++it) |
|
{ |
|
targetNode = targetNode->FirstChild(*it); |
|
if (targetNode == nullptr) |
|
return defaultStr; |
|
} |
|
|
|
if (targetNode == nullptr) |
|
return defaultStr; |
|
|
|
const char* name = nullptr; |
|
for (TiXmlNodeA* childNode = targetNode->FirstChildElement("Item"); |
|
childNode; |
|
childNode = childNode->NextSibling("Item")) |
|
{ |
|
TiXmlElementA* element = childNode->ToElement(); |
|
int id = 0; |
|
const char* idStr = element->Attribute("id", &id); |
|
|
|
if (idStr && id == cmdID) |
|
{ |
|
name = element->Attribute("name"); |
|
break; |
|
} |
|
} |
|
|
|
if (name && name[0]) |
|
{ |
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
return wmc.char2wchar(name, _nativeLangEncoding); |
|
} |
|
return defaultStr; |
|
} |
|
|
|
std::wstring NativeLangSpeaker::getProjectPanelLangMenuStr(const char * nodeName, int cmdID, const wchar_t *defaultStr) const |
|
{ |
|
if (!_nativeLangA) return defaultStr; |
|
|
|
TiXmlNodeA *targetNode = _nativeLangA->FirstChild("ProjectManager"); |
|
if (!targetNode) return defaultStr; |
|
|
|
targetNode = targetNode->FirstChild("Menus"); |
|
if (!targetNode) return defaultStr; |
|
|
|
targetNode = targetNode->FirstChild(nodeName); |
|
if (!targetNode) return defaultStr; |
|
|
|
const char *name = NULL; |
|
for (TiXmlNodeA *childNode = targetNode->FirstChildElement("Item"); |
|
childNode ; |
|
childNode = childNode->NextSibling("Item") ) |
|
{ |
|
TiXmlElementA *element = childNode->ToElement(); |
|
int id; |
|
const char *idStr = element->Attribute("id", &id); |
|
|
|
if (idStr && id == cmdID) |
|
{ |
|
name = element->Attribute("name"); |
|
break; |
|
} |
|
} |
|
|
|
if (name && name[0]) |
|
{ |
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
return wmc.char2wchar(name, _nativeLangEncoding); |
|
} |
|
return defaultStr; |
|
} |
|
|
|
wstring NativeLangSpeaker::getAttrNameStr(const wchar_t *defaultStr, const char *nodeL1Name, const char *nodeL2Name, const char *nodeL3Name) const |
|
{ |
|
if (!_nativeLangA) return defaultStr; |
|
|
|
TiXmlNodeA *targetNode = _nativeLangA->FirstChild(nodeL1Name); |
|
if (!targetNode) return defaultStr; |
|
if (nodeL2Name) |
|
targetNode = targetNode->FirstChild(nodeL2Name); |
|
|
|
if (!targetNode) return defaultStr; |
|
|
|
const char *name = (targetNode->ToElement())->Attribute(nodeL3Name); |
|
if (name && name[0]) |
|
{ |
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
return wmc.char2wchar(name, _nativeLangEncoding); |
|
} |
|
return defaultStr; |
|
} |
|
|
|
wstring NativeLangSpeaker::getAttrNameByIdStr(const wchar_t *defaultStr, TiXmlNodeA *targetNode, const char *nodeL1Value, const char *nodeL1Name, const char *nodeL2Name) const |
|
{ |
|
if (!targetNode) return defaultStr; |
|
|
|
for (TiXmlNodeA *childNode = targetNode->FirstChildElement("Item"); |
|
childNode; |
|
childNode = childNode->NextSibling("Item")) |
|
{ |
|
TiXmlElementA *element = childNode->ToElement(); |
|
const char *id = element->Attribute(nodeL1Name); |
|
if (id && id[0] && !strcmp(id, nodeL1Value)) |
|
{ |
|
const char *name = element->Attribute(nodeL2Name); |
|
if (name && name[0]) |
|
{ |
|
WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); |
|
return wmc.char2wchar(name, _nativeLangEncoding); |
|
} |
|
} |
|
} |
|
return defaultStr; |
|
} |
|
|
|
int NativeLangSpeaker::messageBox(const char *msgBoxTagName, HWND hWnd, const wchar_t *defaultMessage, const wchar_t *defaultTitle, int msgBoxType, int intInfo, const wchar_t *strInfo) |
|
{ |
|
if ((NppParameters::getInstance()).isEndSessionCritical()) |
|
return IDCANCEL; // simulate Esc-key or Cancel-button as there should not be any big delay / code-flow block |
|
|
|
wstring msg, title; |
|
if (!getMsgBoxLang(msgBoxTagName, title, msg)) |
|
{ |
|
title = defaultTitle; |
|
msg = defaultMessage; |
|
} |
|
title = stringReplace(title, L"$INT_REPLACE$", std::to_wstring(intInfo)); |
|
msg = stringReplace(msg, L"$INT_REPLACE$", std::to_wstring(intInfo)); |
|
if (strInfo) |
|
{ |
|
title = stringReplace(title, L"$STR_REPLACE$", strInfo); |
|
msg = stringReplace(msg, L"$STR_REPLACE$", strInfo); |
|
} |
|
if (_isRTL) |
|
{ |
|
msgBoxType |= MB_RTLREADING | MB_RIGHT; |
|
} |
|
return ::MessageBox(hWnd, msg.c_str(), (title.empty() || wcscmp(title.c_str(), L"0") == 0) ? nullptr : title.c_str(), msgBoxType); |
|
} |
|
|
|
// Default English localization during Notepad++ launch |
|
// is handled in NppDarkMode::subclassButtonControl. |
|
void NativeLangSpeaker::resizeCheckboxRadioBtn(HWND hWnd) |
|
{ |
|
constexpr size_t classNameLen = 32; |
|
wchar_t className[classNameLen]{}; |
|
::GetClassNameW(hWnd, className, classNameLen); |
|
if (wcscmp(className, WC_BUTTON) == 0) |
|
{ |
|
const auto nBtnStyle = ::GetWindowLongPtrW(hWnd, GWL_STYLE); |
|
switch (nBtnStyle & BS_TYPEMASK) |
|
{ |
|
case BS_CHECKBOX: |
|
case BS_AUTOCHECKBOX: |
|
case BS_RADIOBUTTON: |
|
case BS_AUTORADIOBUTTON: |
|
{ |
|
if ((nBtnStyle & BS_MULTILINE) != BS_MULTILINE) |
|
{ |
|
::SendMessageW(hWnd, NppDarkMode::WM_SETBUTTONIDEALSIZE, 0, 0); |
|
} |
|
break; |
|
} |
|
|
|
default: |
|
break; |
|
} |
|
} |
|
}
|
|
|