From 9d733b29cc4c995f5f68303684775f09f13b7579 Mon Sep 17 00:00:00 2001
From: Don Ho <don.h@free.fr>
Date: Sun, 7 Nov 2010 03:00:27 +0000
Subject: [PATCH] [NEW_FEATURE] Add a new capacity in context menu: the menu
 item and folder item can be renamed in any language.

git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository/trunk@697 f5eea248-9336-0410-98b8-ebc06183d4e3
---
 PowerEditor/src/MISC/Common/Common.cpp | 12 ++++
 PowerEditor/src/Parameters.cpp         | 97 +++++++++++++++++---------
 PowerEditor/src/Parameters.h           |  4 +-
 PowerEditor/src/contextMenu.xml        |  3 +-
 4 files changed, 79 insertions(+), 37 deletions(-)

diff --git a/PowerEditor/src/MISC/Common/Common.cpp b/PowerEditor/src/MISC/Common/Common.cpp
index 79ed12ad4..1bc04ab02 100644
--- a/PowerEditor/src/MISC/Common/Common.cpp
+++ b/PowerEditor/src/MISC/Common/Common.cpp
@@ -220,6 +220,9 @@ generic_string purgeMenuItemString(const TCHAR * menuItemStr, bool keepAmpersand
 
 const wchar_t * WcharMbcsConvertor::char2wchar(const char * mbcs2Convert, UINT codepage, int lenMbcs, int *pLenWc, int *pBytesNotProcessed)
 {
+	// Do not process NULL pointer
+	if (!mbcs2Convert) return NULL;
+
 	// Do not process empty strings
 	if (lenMbcs == 0 || lenMbcs == -1 && mbcs2Convert[0] == 0) { _wideCharStr.empty(); return _wideCharStr;	}
 
@@ -279,6 +282,9 @@ const wchar_t * WcharMbcsConvertor::char2wchar(const char * mbcs2Convert, UINT c
 // which are converted to the corresponding indexes in the returned wchar_t string.
 const wchar_t * WcharMbcsConvertor::char2wchar(const char * mbcs2Convert, UINT codepage, int *mstart, int *mend)
 {
+	// Do not process NULL pointer
+	if (!mbcs2Convert) return NULL;
+
 	int len = MultiByteToWideChar(codepage, 0, mbcs2Convert, -1, NULL, 0);
 	if (len > 0)
 	{
@@ -307,6 +313,9 @@ const wchar_t * WcharMbcsConvertor::char2wchar(const char * mbcs2Convert, UINT c
 
 const char * WcharMbcsConvertor::wchar2char(const wchar_t * wcharStr2Convert, UINT codepage, int lenWc, int *pLenMbcs) 
 {
+	// Do not process NULL pointer
+	if (!wcharStr2Convert) return NULL;
+
 	int lenMbcs = WideCharToMultiByte(codepage, 0, wcharStr2Convert, lenWc, NULL, 0, NULL, NULL);
 	if (lenMbcs > 0)
 	{
@@ -322,6 +331,9 @@ const char * WcharMbcsConvertor::wchar2char(const wchar_t * wcharStr2Convert, UI
 
 const char * WcharMbcsConvertor::wchar2char(const wchar_t * wcharStr2Convert, UINT codepage, long *mstart, long *mend) 
 {
+	// Do not process NULL pointer
+	if (!wcharStr2Convert) return NULL;
+
 	int len = WideCharToMultiByte(codepage, 0, wcharStr2Convert, -1, NULL, 0, NULL, NULL);
 	if (len > 0)
 	{
diff --git a/PowerEditor/src/Parameters.cpp b/PowerEditor/src/Parameters.cpp
index 9ae4273da..fbe88c323 100644
--- a/PowerEditor/src/Parameters.cpp
+++ b/PowerEditor/src/Parameters.cpp
@@ -599,7 +599,7 @@ int FileDialog::_dialogFileBoxId = (NppParameters::getInstance())->getWinVersion
 NppParameters::NppParameters() : _pXmlDoc(NULL),_pXmlUserDoc(NULL), _pXmlUserStylerDoc(NULL),\
 								_pXmlUserLangDoc(NULL), _pXmlNativeLangDocA(NULL),\
 								_nbLang(0), _nbFile(0), _nbMaxFile(10), _pXmlToolIconsDoc(NULL),\
-								_pXmlShortcutDoc(NULL), _pXmlContextMenuDoc(NULL), _pXmlSessionDoc(NULL), _pXmlBlacklistDoc(NULL),\
+								_pXmlShortcutDoc(NULL), _pXmlContextMenuDocA(NULL), _pXmlSessionDoc(NULL), _pXmlBlacklistDoc(NULL),\
 								_nbUserLang(0), _nbExternalLang(0), _hUser32(NULL), _hUXTheme(NULL),\
 								_transparentFuncAddr(NULL), _enableThemeDialogTextureFuncAddr(NULL),\
 								_isTaskListRBUTTONUP_Active(false), _fileSaveDlgFilterIndex(-1), _asNotepadStyle(false), _isFindReplacing(false)
@@ -772,8 +772,6 @@ bool NppParameters::load()
             TCHAR nppDirLocation[MAX_PATH];
             lstrcpy(nppDirLocation, _nppPath.c_str());
             ::PathRemoveFileSpec(nppDirLocation);
-		    //printStr(progPath);
-            //printStr(nppDirLocation);
             	
             if  (lstrcmp(progPath, nppDirLocation) == 0)
                 isLocal = false;
@@ -1038,12 +1036,12 @@ bool NppParameters::load()
 		::CopyFile(srcContextMenuPath.c_str(), _contextMenuPath.c_str(), TRUE);
 	}
 
-	_pXmlContextMenuDoc = new TiXmlDocument(_contextMenuPath);
-	loadOkay = _pXmlContextMenuDoc->LoadFile();
+	_pXmlContextMenuDocA = new TiXmlDocumentA();
+	loadOkay = _pXmlContextMenuDocA->LoadUnicodeFilePath(_contextMenuPath.c_str());
 	if (!loadOkay)
 	{
-		delete _pXmlContextMenuDoc;
-		_pXmlContextMenuDoc = NULL;
+		delete _pXmlContextMenuDocA;
+		_pXmlContextMenuDocA = NULL;
 		isAllLaoded = false;
 	}
 
@@ -1128,8 +1126,8 @@ void NppParameters::destroyInstance()
 	if (_pXmlShortcutDoc)
 		delete _pXmlShortcutDoc;
 
-	if (_pXmlContextMenuDoc)
-		delete _pXmlContextMenuDoc;
+	if (_pXmlContextMenuDocA)
+		delete _pXmlContextMenuDocA;
 
 	if (_pXmlSessionDoc)
 		delete _pXmlSessionDoc;
@@ -1362,39 +1360,61 @@ bool NppParameters::reloadContextMenuFromXmlTree(HMENU mainMenuHadle, HMENU plug
 
 bool NppParameters::getContextMenuFromXmlTree(HMENU mainMenuHadle, HMENU pluginsMenu)
 {
-	if (!_pXmlContextMenuDoc)
+	if (!_pXmlContextMenuDocA)
 		return false;
-	TiXmlNode *root = _pXmlContextMenuDoc->FirstChild(TEXT("NotepadPlus"));
+	TiXmlNodeA *root = _pXmlContextMenuDocA->FirstChild("NotepadPlus");
 	if (!root) 
 		return false;
-	TiXmlNode *contextMenuRoot = root->FirstChildElement(TEXT("ScintillaContextMenu"));
-	if (contextMenuRoot)
-	{
-		for (TiXmlNode *childNode = contextMenuRoot->FirstChildElement(TEXT("Item"));
-			childNode ;
-			childNode = childNode->NextSibling(TEXT("Item")) )
-		{
-			const TCHAR *folderName = (childNode->ToElement())->Attribute(TEXT("FolderName"));
-			const TCHAR *displayAs = (childNode->ToElement())->Attribute(TEXT("ItemNameAs"));
 
+	WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance();
+				
+	TiXmlNodeA *contextMenuRoot = root->FirstChildElement("ScintillaContextMenu");
+	if (contextMenuRoot)
+	{//printInt(int(mainMenuHadle));printInt(int(pluginsMenu));
+		for (TiXmlNodeA *childNode = contextMenuRoot->FirstChildElement("Item");
+			childNode ;
+			childNode = childNode->NextSibling("Item") )
+		{
+			const char *folderNameA = (childNode->ToElement())->Attribute("FolderName");
+			const char *displayAsA = (childNode->ToElement())->Attribute("ItemNameAs");
+
+			generic_string folderName;
+			generic_string displayAs;
+#ifdef UNICODE
+			folderName = folderNameA?wmc->char2wchar(folderNameA, SC_CP_UTF8):TEXT("");
+			displayAs = displayAsA?wmc->char2wchar(displayAsA, SC_CP_UTF8):TEXT("");
+#else
+			folderName = folderNameA?folderNameA:"";
+			displayAs = displayAsA?displayAsA:"";
+#endif
 			int id;
-			const TCHAR *idStr = (childNode->ToElement())->Attribute(TEXT("id"), &id);
+			const char *idStr = (childNode->ToElement())->Attribute("id", &id);
 			if (idStr)
 			{
-				_contextMenuItems.push_back(MenuItemUnit(id, displayAs?displayAs:TEXT(""), folderName));
+				_contextMenuItems.push_back(MenuItemUnit(id, displayAs.c_str(), folderName.c_str()));
 			}
 			else
 			{
-				const TCHAR *menuEntryName = (childNode->ToElement())->Attribute(TEXT("MenuEntryName"));
-				const TCHAR *menuItemName = (childNode->ToElement())->Attribute(TEXT("MenuItemName"));
-				if (menuEntryName && menuItemName)
+				const char *menuEntryNameA = (childNode->ToElement())->Attribute("MenuEntryName");
+				const char *menuItemNameA = (childNode->ToElement())->Attribute("MenuItemName");
+
+				generic_string menuEntryName;
+				generic_string menuItemName;
+#ifdef UNICODE
+				menuEntryName = menuEntryNameA?wmc->char2wchar(menuEntryNameA, SC_CP_UTF8):TEXT("");
+				menuItemName = menuItemNameA?wmc->char2wchar(menuItemNameA, SC_CP_UTF8):TEXT("");
+#else
+				menuEntryName = menuEntryNameA?menuEntryNameA:"";
+				menuItemName = menuItemNameA?menuItemNameA:"";
+#endif
+				if (menuEntryName != TEXT("") && menuItemName != TEXT(""))
 				{
 					int nbMenuEntry = ::GetMenuItemCount(mainMenuHadle);
 					for (int i = 0 ; i < nbMenuEntry ; i++)
 					{
 						TCHAR menuEntryString[64];
 						::GetMenuString(mainMenuHadle, i, menuEntryString, 64, MF_BYPOSITION);
-						if (generic_stricmp(menuEntryName, purgeMenuItemString(menuEntryString).c_str()) == 0)
+						if (generic_stricmp(menuEntryName.c_str(), purgeMenuItemString(menuEntryString).c_str()) == 0)
 						{
 							vector< pair<HMENU, int> > parentMenuPos;
 							HMENU topMenu = ::GetSubMenu(mainMenuHadle, i);
@@ -1417,10 +1437,10 @@ bool NppParameters::getContextMenuFromXmlTree(HMENU mainMenuHadle, HMENU plugins
 									//  Check current menu position.
 									TCHAR cmdStr[256];
 									::GetMenuString(currMenu, currMenuPos, cmdStr, 256, MF_BYPOSITION);
-									if (generic_stricmp(menuItemName, purgeMenuItemString(cmdStr).c_str()) == 0)
+									if (generic_stricmp(menuItemName.c_str(), purgeMenuItemString(cmdStr).c_str()) == 0)
 									{
 										int cmdId = ::GetMenuItemID(currMenu, currMenuPos);
-										_contextMenuItems.push_back(MenuItemUnit(cmdId, displayAs?displayAs:TEXT(""), folderName));
+										_contextMenuItems.push_back(MenuItemUnit(cmdId, displayAs.c_str(), folderName.c_str()));
 										break;
 									}
 									
@@ -1445,18 +1465,27 @@ bool NppParameters::getContextMenuFromXmlTree(HMENU mainMenuHadle, HMENU plugins
 				}
 				else
 				{
-					const TCHAR *pluginName = (childNode->ToElement())->Attribute(TEXT("PluginEntryName"));
-					const TCHAR *pluginCmdName = (childNode->ToElement())->Attribute(TEXT("PluginCommandItemName"));
+					const char *pluginNameA = (childNode->ToElement())->Attribute("PluginEntryName");
+					const char *pluginCmdNameA = (childNode->ToElement())->Attribute("PluginCommandItemName");
 
+					generic_string pluginName;
+					generic_string pluginCmdName;
+#ifdef UNICODE
+					pluginName = pluginNameA?wmc->char2wchar(pluginNameA, SC_CP_UTF8):TEXT("");
+					pluginCmdName = pluginCmdNameA?wmc->char2wchar(pluginCmdNameA, SC_CP_UTF8):TEXT("");
+#else
+					pluginName = pluginNameA?pluginNameA:"";
+					pluginCmdName = pluginCmdNameA?pluginCmdNameA:"";
+#endif
 					// if plugin menu existing plls the value of PluginEntryName and PluginCommandItemName are valid
-					if (pluginsMenu && pluginName && pluginCmdName)
+					if (pluginsMenu && pluginName != TEXT("") && pluginCmdName != TEXT(""))
 					{
 						int nbPlugins = ::GetMenuItemCount(pluginsMenu);
 						for (int i = 0 ; i < nbPlugins ; i++)
 						{
 							TCHAR menuItemString[256];
 							::GetMenuString(pluginsMenu, i, menuItemString, 256, MF_BYPOSITION);
-							if (generic_stricmp(pluginName, purgeMenuItemString(menuItemString).c_str()) == 0)
+							if (generic_stricmp(pluginName.c_str(), purgeMenuItemString(menuItemString).c_str()) == 0)
 							{
 								HMENU pluginMenu = ::GetSubMenu(pluginsMenu, i);
 								int nbPluginCmd = ::GetMenuItemCount(pluginMenu);
@@ -1464,10 +1493,10 @@ bool NppParameters::getContextMenuFromXmlTree(HMENU mainMenuHadle, HMENU plugins
 								{
 									TCHAR pluginCmdStr[256];
 									::GetMenuString(pluginMenu, j, pluginCmdStr, 256, MF_BYPOSITION);
-									if (generic_stricmp(pluginCmdName, purgeMenuItemString(pluginCmdStr).c_str()) == 0)
+									if (generic_stricmp(pluginCmdName.c_str(), purgeMenuItemString(pluginCmdStr).c_str()) == 0)
 									{
 										int pluginCmdId = ::GetMenuItemID(pluginMenu, j);
-										_contextMenuItems.push_back(MenuItemUnit(pluginCmdId, displayAs?displayAs:TEXT(""), folderName));
+										_contextMenuItems.push_back(MenuItemUnit(pluginCmdId, displayAs.c_str(), folderName.c_str()));
 										break;
 									}
 								}
diff --git a/PowerEditor/src/Parameters.h b/PowerEditor/src/Parameters.h
index 8c4384250..348b9879d 100644
--- a/PowerEditor/src/Parameters.h
+++ b/PowerEditor/src/Parameters.h
@@ -1434,13 +1434,13 @@ private:
     static NppParameters *_pSelf;
 
 	TiXmlDocument *_pXmlDoc, *_pXmlUserDoc, *_pXmlUserStylerDoc, *_pXmlUserLangDoc,\
-		*_pXmlToolIconsDoc, *_pXmlShortcutDoc, *_pXmlContextMenuDoc, *_pXmlSessionDoc,\
+		*_pXmlToolIconsDoc, *_pXmlShortcutDoc, *_pXmlSessionDoc,\
         *_pXmlBlacklistDoc;
 
 	TiXmlDocument *_importedULD[NB_MAX_IMPORTED_UDL];
 	int _nbImportedULD;
 	
-	TiXmlDocumentA *_pXmlNativeLangDocA;
+	TiXmlDocumentA *_pXmlNativeLangDocA, *_pXmlContextMenuDocA;
 
 	vector<TiXmlDocument *> _pXmlExternalLexerDoc;
 
diff --git a/PowerEditor/src/contextMenu.xml b/PowerEditor/src/contextMenu.xml
index e1698a9de..eb4565d38 100644
--- a/PowerEditor/src/contextMenu.xml
+++ b/PowerEditor/src/contextMenu.xml
@@ -27,6 +27,7 @@ http://sourceforge.net/apps/mediawiki/notepad-plus/index.php?title=Context_Menu
 		http://notepad-plus.svn.sourceforge.net/viewvc/notepad-plus/trunk/PowerEditor/installer/nativeLang/english.xml
 		
 		Use FolderName (optional) to create sub-menu. FolderName can be used in any type of item.
+		FolderName value can be in any language.
 		-->
         <Item FolderName="Style token" id="43022"/>
         <Item FolderName="Style token" id="43024"/>
@@ -50,7 +51,7 @@ http://sourceforge.net/apps/mediawiki/notepad-plus/index.php?title=Context_Menu
 		
 		<!--
 		Use ItemNameAs (optional) to rename the menu item name in the context menu 
-		ItemNameAs can be used in any type of item.
+		ItemNameAs can be used in any type of item. ItemNameAs value can be in any language.
 		-->
         <Item FolderName="Plugin commands" PluginEntryName="NppExport" PluginCommandItemName="Copy all formats to clipboard" ItemNameAs="Copy Text with Syntax Highlighting" />