@@ -17,6 +17,8 @@ int MenuManager::s_startCommandID;
1717int MenuManager::s_endCommandID;
1818int MenuManager::s_startFixedID;
1919int MenuManager::s_endFixedID;
20+ int MenuManager::s_startDynamicEntryID;
21+ int MenuManager::s_endDynamicEntryID;
2022bool MenuManager::s_menuItemClicked;
2123
2224void (*MenuManager::s_runScript)(int );
@@ -55,7 +57,11 @@ MenuManager::MenuManager(HWND hNotepad, HINSTANCE hInst, void(*runScript)(const
5557 m_hNotepad (hNotepad),
5658 m_runScript (runScript),
5759 m_pythonPluginMenu (NULL )
60+
5861{
62+ s_startDynamicEntryID = 1 ;
63+ s_endDynamicEntryID = 0 ;
64+
5965 m_runScriptFuncs[0 ] = runScript0;
6066 m_runScriptFuncs[1 ] = runScript1;
6167 m_runScriptFuncs[2 ] = runScript2;
@@ -114,24 +120,26 @@ MenuManager::MenuManager(HWND hNotepad, HINSTANCE hInst, void(*runScript)(const
114120/* This code was shamefully robbed from NppExec from Dovgan Vitaliy*/
115121HMENU MenuManager::getOurMenu ()
116122{
117-
118- HMENU hPluginMenu = (HMENU )::SendMessage (m_hNotepad, NPPM_GETMENUHANDLE , 0 , 0 );
119- HMENU hPythonMenu = NULL ;
120- int iMenuItems = GetMenuItemCount (hPluginMenu);
121- for ( int i = 0 ; i < iMenuItems; i++ )
123+ if (NULL == m_pythonPluginMenu)
122124 {
123- HMENU hSubMenu = ::GetSubMenu (hPluginMenu, i);
124- // does our About menu command exist here?
125- if ( ::GetMenuState (hSubMenu, m_funcItems[0 ]._cmdID , MF_BYCOMMAND ) != -1 )
125+ HMENU hPluginMenu = (HMENU )::SendMessage (m_hNotepad, NPPM_GETMENUHANDLE , 0 , 0 );
126+ HMENU hPythonMenu = NULL ;
127+ int iMenuItems = GetMenuItemCount (hPluginMenu);
128+ for ( int i = 0 ; i < iMenuItems; i++ )
126129 {
127- // this is our "Python Script" sub-menu
128- hPythonMenu = hSubMenu;
129- break ;
130+ HMENU hSubMenu = ::GetSubMenu (hPluginMenu, i);
131+ // does our About menu command exist here?
132+ if ( ::GetMenuState (hSubMenu, m_funcItems[0 ]._cmdID , MF_BYCOMMAND ) != -1 )
133+ {
134+ // this is our "Python Script" sub-menu
135+ m_pythonPluginMenu = hSubMenu;
136+ break ;
137+ }
130138 }
139+
131140 }
132141
133-
134- return hPythonMenu;
142+ return m_pythonPluginMenu;
135143}
136144
137145void MenuManager::stopScriptEnabled (bool enabled)
@@ -155,32 +163,35 @@ bool MenuManager::populateScriptsMenu()
155163 else
156164 {
157165
158- HMENU hScriptsMenu = CreateMenu ();
166+ m_hScriptsMenu = CreateMenu ();
159167 // funcItem[g_aboutFuncIndex]._cmdID + 1000
160168 s_startCommandID = m_funcItems[0 ]._cmdID + ADD_CMD_ID ;
161169
162- InsertMenu (m_pythonPluginMenu, m_scriptsMenuIndex, MF_BYPOSITION | MF_POPUP , reinterpret_cast <UINT_PTR >(hScriptsMenu ), _T (" Scripts" ));
163- m_submenus.insert (pair<string, HMENU >(" \\ " , hScriptsMenu ));
170+ InsertMenu (m_pythonPluginMenu, m_scriptsMenuIndex, MF_BYPOSITION | MF_POPUP , reinterpret_cast <UINT_PTR >(m_hScriptsMenu ), _T (" Scripts" ));
171+ m_submenus.insert (pair<string, HMENU >(" \\ " , m_hScriptsMenu ));
164172
165173 TCHAR pluginDir[MAX_PATH ];
166174 TCHAR configDir[MAX_PATH ];
167175 ::SendMessage (m_hNotepad, NPPM_GETNPPDIRECTORY , MAX_PATH , reinterpret_cast <LPARAM >(pluginDir));
168176 ::SendMessage (m_hNotepad, NPPM_GETPLUGINSCONFIGDIR , MAX_PATH , reinterpret_cast <LPARAM >(configDir));
169177 shared_ptr<char > path = WcharMbcsConverter::tchar2char (pluginDir);
170- string machineScriptsPath ( path.get () );
171- machineScriptsPath .append (" \\ plugins\\ PythonScript\\ scripts" );
178+ m_machineScriptsPath = path.get ();
179+ m_machineScriptsPath .append (" \\ plugins\\ PythonScript\\ scripts" );
172180
173181 path = WcharMbcsConverter::tchar2char (configDir);
174- string userScriptsPath (path.get ());
175- userScriptsPath.append (" \\ PythonScript\\ scripts" );
176-
177- int nextID = findScripts (hScriptsMenu, machineScriptsPath.size (), s_startCommandID, machineScriptsPath);
178-
179- s_endCommandID = findScripts (hScriptsMenu, userScriptsPath.size (), nextID, userScriptsPath);
182+ m_userScriptsPath = path.get ();
183+ m_userScriptsPath.append (" \\ PythonScript\\ scripts" );
180184
185+
181186 // Assume here that the func items are assigned from start to finish
182187 s_startFixedID = m_funcItems[m_dynamicStartIndex]._cmdID ;
183- s_endFixedID = m_funcItems[m_funcItemCount - 1 ]._cmdID ;
188+ s_endFixedID = m_funcItems[m_funcItemCount - 1 ]._cmdID ;
189+
190+ // Fill the actual menu
191+ refreshScriptsMenu ();
192+
193+ // Dynamic scripts will start at one lower index now we've inserted the Scripts submenu
194+ ++m_dynamicStartIndex;
184195
185196 subclassNotepadPlusPlus ();
186197
@@ -189,6 +200,35 @@ bool MenuManager::populateScriptsMenu()
189200 return true ;
190201}
191202
203+ // Fills the Scripts menu
204+ void MenuManager::refreshScriptsMenu ()
205+ {
206+ // This will try to delete all scripts menu items
207+ // - scripts in sub directories will be unsuccessful,
208+ // but less trouble (read: CPU) than trying to work out which ones we should delete (ie. root dir)
209+ for (ScriptCommandsTD::iterator it = m_scriptCommands.begin (); it != m_scriptCommands.end (); ++it)
210+ {
211+ DeleteMenu (m_hScriptsMenu, it->first , MF_BYCOMMAND );
212+ }
213+
214+ m_scriptCommands.erase (m_scriptCommands.begin (), m_scriptCommands.end ());
215+ m_machineScriptNames.erase (m_machineScriptNames.begin (), m_machineScriptNames.end ());
216+ for (SubmenusTD::iterator it = m_submenus.begin (); it != m_submenus.end (); ++it)
217+ {
218+ if (it->first != " \\ " )
219+ {
220+ DestroyMenu (it->second );
221+ }
222+ }
223+
224+ int nextID = findScripts (m_hScriptsMenu, m_machineScriptsPath.size (), s_startCommandID, m_machineScriptsPath);
225+
226+ s_endCommandID = findScripts (m_hScriptsMenu, m_userScriptsPath.size (), nextID, m_userScriptsPath);
227+
228+
229+ }
230+
231+
192232int MenuManager::findScripts (HMENU hBaseMenu, int basePathLength, int startID, string& path)
193233{
194234 WIN32_FIND_DATAA findData;
@@ -315,6 +355,12 @@ LRESULT CALLBACK notepadWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM l
315355 {
316356 MenuManager::s_menuItemClicked = true ;
317357 }
358+ else if (LOWORD (wParam) >= MenuManager::s_startDynamicEntryID && LOWORD (wParam) < MenuManager::s_endDynamicEntryID && HIWORD (wParam) == 0 )
359+ {
360+ MenuManager::s_menuItemClicked = true ;
361+ MenuManager::getInstance ()->menuCommand (LOWORD (wParam));
362+ return TRUE ;
363+ }
318364
319365 }
320366
@@ -396,9 +442,88 @@ FuncItem* MenuManager::getFuncItemArray(int *nbF, ItemVectorTD items, void (*run
396442
397443 m_dynamicStartIndex = dynamicStartIndex;
398444 m_dynamicCount = menuItems.size ();
445+ m_originalDynamicCount = m_dynamicCount;
399446 m_scriptsMenuIndex = scriptsMenuIndex;
400447 m_stopScriptIndex = stopScriptIndex;
401448
402449 return m_funcItems;
403450
451+ }
452+
453+
454+ // Reconfigure the dynamic menus from the config
455+ void MenuManager::reconfigure ()
456+ {
457+ ConfigFile *configFile = ConfigFile::getInstance ();
458+ ConfigFile::MenuItemsTD menuItems = configFile->getMenuItems ();
459+
460+
461+ TCHAR buffer[MAX_PATH ];
462+ TCHAR *filename;
463+
464+ // Remove the current list of script commands
465+ m_scriptCommands.clear ();
466+
467+ HMENU hPluginMenu = getOurMenu ();
468+ int dynamicEntryID = m_funcItems[0 ]._cmdID + DYNAMIC_ADD_ID ;
469+ s_startDynamicEntryID = dynamicEntryID;
470+ // Remove the current "extra" entries - ie. entries after the original list in funcItems
471+ for (int position = m_originalDynamicCount; position < m_dynamicCount; ++position)
472+ {
473+ ::DeleteMenu (hPluginMenu, m_dynamicStartIndex + position, MF_BYPOSITION );
474+ }
475+
476+ int position = 0 ;
477+
478+ for (ConfigFile::MenuItemsTD::iterator it = menuItems.begin (); it != menuItems.end (); ++it)
479+ {
480+ _tcscpy_s<MAX_PATH >(buffer, (*it).c_str ());
481+
482+ filename = PathFindFileName (buffer);
483+ PathRemoveExtension (filename);
484+
485+ // If it's less than the original funcItem count given
486+ // back from getFuncItems
487+ if (position < m_originalDynamicCount)
488+ {
489+ // If we're currently passed the number of CURRENT
490+ // dynamic entries, then we need to create the HMENU item again
491+ if (position >= m_dynamicCount)
492+ {
493+ // put a menu item back with the same ID
494+ // (N++ will believe this to be genuine :)
495+
496+ // scripts sub menu didn't exist when dynamicStartIndex was set, hence the -1
497+ ::InsertMenu (hPluginMenu, position + m_dynamicStartIndex, MF_BYPOSITION , m_funcItems[m_dynamicStartIndex + position - 1 ]._cmdID, filename);
498+ }
499+ else
500+ {
501+ // Update the existing menu
502+ // scripts sub menu didn't exist when dynamicStartIndex was set, hence the -1
503+ ::ModifyMenu (hPluginMenu, position + m_dynamicStartIndex, MF_BYPOSITION , m_funcItems[m_dynamicStartIndex + position - 1 ]._cmdID, filename);
504+ }
505+
506+ m_scriptCommands.insert (pair<int , string>(m_funcItems[position]._cmdID , string (WcharMbcsConverter::tchar2char (it->c_str ()).get ())));
507+ }
508+ else // position >= m_funcItemCount, so just add a new one
509+ {
510+ ::InsertMenu (hPluginMenu, position + m_dynamicStartIndex, MF_BYPOSITION , dynamicEntryID, filename);
511+ m_scriptCommands.insert (pair<int , string>(dynamicEntryID, string (WcharMbcsConverter::tchar2char (it->c_str ()).get ())));
512+ ++dynamicEntryID;
513+ }
514+
515+ ++position;
516+ }
517+
518+ // Delete the extra menus
519+ if (menuItems.size () < static_cast <size_t >(m_dynamicCount))
520+ {
521+ for (int currentCount = position; currentCount < m_dynamicCount; ++currentCount)
522+ {
523+ ::DeleteMenu (hPluginMenu, position + m_dynamicStartIndex, MF_BYPOSITION );
524+ }
525+ }
526+
527+ m_dynamicCount = menuItems.size ();
528+ s_endDynamicEntryID = dynamicEntryID;
404529}
0 commit comments