1: /*
     2:  ============================================================================
     3:  xoblite™ -> an advanced "extended shell" for Microsoft® Windows® 11
     4:  Copyright © 2002-2026 Karl Henrik Henriksson [qwilk/@xoblite]
     5:  Copyright © 2001-2004 The Blackbox for Windows Development Team
     6:  http://xoblite.net/ + https://github.com/xoblite/
     7:  ============================================================================
     8: 
     9:   Blackbox for Windows is free software, released under the
    10:   GNU General Public License (GPL version 2 or later), with an extension
    11:   that allows linking of proprietary modules under a controlled interface.
    12:   What this means is that plugins etc. are allowed to be released
    13:   under any license the author wishes. Please note, however, that the
    14:   original Blackbox gradient math code used in Blackbox for Windows
    15:   is available under the BSD license.
    16: 
    17:   http://www.fsf.org/licenses/gpl.html
    18:   http://www.fsf.org/licenses/gpl-faq.html#LinkingOverControlledInterface
    19:   http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5
    20: 
    21:   This program is distributed in the hope that it will be useful,
    22:   but WITHOUT ANY WARRANTY; without even the implied warranty of
    23:   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    24:   GNU General Public License for more details.
    25: 
    26:   For additional license information, please read the included license.html.
    27: 
    28:  ============================================================================
    29: */
    30: 
    31: #include "..\API\BBApi.h" 
    32: #include "..\Menu\MenuCommon.h" 
    33: #include "PluginsMenu.h" 
    34: #include "..\Menu\MenuItem.h" 
    35: #include "..\Menu\FolderItem.h" 
    36: #include "..\Settings\ConfigMenu.h" 
    37: #include "..\Dock\Dock.h" 
    38: #include "..\Settings\Settings.h" 
    39: #include "PluginManager.h" 
    40: 
    41: extern MenuCommon *pMenuCommon;
    42: extern Settings *pSettings;
    43: extern PluginManager *pPluginManager;
    44: 
    45: //===========================================================================
    46: 
    47: PluginMenu::PluginMenu(char* pszTitle) : FolderItem(NULL, pszTitle, NULL)
    48: {
    49: }
    50: 
    51: PluginMenu::~PluginMenu()
    52: {
    53:     m_pParent->RemoveChild(m_pSubMenu);
    54:     if (m_pSubMenu) delete m_pSubMenu;
    55:     m_pSubMenu = NULL;
    56: }
    57: 
    58: //====================
    59: 
    60: bool PluginMenu::Active(bool bActivate)
    61: {
    62:     if (bActivate && !m_bActive) UpdateFolder();
    63:     return FolderItem::Active(bActivate);
    64: }
    65: 
    66: void PluginMenu::Attached(Menu* pMenu)
    67: {
    68:     m_pParent = pMenu;
    69:     m_pSubMenu = new Menu(pMenuCommon->hInst);
    70:     m_pParent->AddChild(m_pSubMenu);
    71:     m_pSubMenu->SetParent(m_pParent);
    72: }
    73: 
    74: //====================
    75: 
    76: void PluginMenu::UpdateFolder()
    77: {
    78:     m_pSubMenu->DeleteMenuItems();
    79:     pMenuCommon->AddHeaderItem(m_pSubMenu, m_pszTitleANSI);
    80: 
    81:     pMenuCommon->CreateMenuItem(m_pSubMenu, MENUITEM_COMMAND, "@xoblite LoadPlugin", NULL, "Load plugin...", false);
    82: 
    83: //  UnloadPluginMenu *UPMenu = new UnloadPluginMenu("Unload/Update plugin");
    84:     UnloadPluginMenu *UPMenu = new UnloadPluginMenu("Unload plugin");
    85:     UPMenu->SetHeight(pMenuCommon->m_nSubmenuHeight);
    86:     m_pSubMenu->AddMenuItem(UPMenu);
    87: 
    88:     BroamMenu *BMenu = new BroamMenu("Bro@ms");
    89:     BMenu->SetHeight(pMenuCommon->m_nSubmenuHeight);
    90:     m_pSubMenu->AddMenuItem(BMenu);
    91: 
    92:     pMenuCommon->CreateMenuItem(m_pSubMenu, MENUITEM_SEPARATOR, NULL, NULL, NULL, false);
    93:     pMenuCommon->CreateMenuItem(m_pSubMenu, MENUITEM_COMMAND, "@xoblite Edit Plugins", NULL, "Edit plugins.rc", false);
    94:     pMenuCommon->CreateMenuItem(m_pSubMenu, MENUITEM_COMMAND, "@xoblite CheckForUpdates", NULL, "Check for updates...", false);
    95:     pMenuCommon->CreateMenuItem(m_pSubMenu, MENUITEM_COMMAND, "@xoblite About Plugins", NULL, "About loaded plugins...", false);
    96: 
    97:     pMenuCommon->CreateMenuItem(m_pSubMenu, MENUITEM_SEPARATOR, NULL, NULL, NULL, false);
    98:     pMenuCommon->CreateMenuItem(m_pSubMenu, MENUITEM_COMMAND, "[exec]", "http://xoblite.net/shell/plugins/", "Get plugins...", false);
    99: 
   100:     pMenuCommon->CreateMenuItem(m_pSubMenu, MENUITEM_SEPARATOR, NULL, NULL, NULL, false);
   101:     pMenuCommon->CreateMenuItem(m_pSubMenu, MENUITEM_BOOLEAN, "@xoblite Plugins Toggle", NULL, "Hide Plugins", pSettings->pluginsHidden);
   102: 
   103:     int numberOfPlugins = (int)pPluginManager->pluginList.size();
   104:     char gripText[255];
   105:     sprintf_s(gripText, sizeofArray(gripText), "(%d plugin", numberOfPlugins);
   106:     if (numberOfPlugins != 1) strcat_s(gripText, sizeofArray(gripText), "s");
   107:     strcat_s(gripText, sizeofArray(gripText), " loaded)");
   108: 
   109:     pMenuCommon->AddFooterItem(m_pSubMenu, gripText);
   110: 
   111:     m_pSubMenu->Invalidate();
   112:     m_pSubMenu->Validate();
   113: }
   114: 
   115: //===========================================================================
   116: 
   117: UnloadPluginMenu::UnloadPluginMenu(char* pszTitle) : FolderItem(NULL, pszTitle, NULL)
   118: {
   119: }
   120: 
   121: UnloadPluginMenu::~UnloadPluginMenu()
   122: {
   123:     m_pParent->RemoveChild(m_pSubMenu);
   124:     if (m_pSubMenu) delete m_pSubMenu;
   125:     m_pSubMenu = NULL;
   126: }
   127: 
   128: //====================
   129: 
   130: bool UnloadPluginMenu::Active(bool bActivate)
   131: {
   132:     if (bActivate && !m_bActive) UpdateFolder();
   133:     return FolderItem::Active(bActivate);
   134: }
   135: 
   136: void UnloadPluginMenu::Attached(Menu* pMenu)
   137: {
   138:     m_pParent = pMenu;
   139:     m_pSubMenu = new Menu(pMenuCommon->hInst);
   140:     m_pParent->AddChild(m_pSubMenu);
   141:     m_pSubMenu->SetParent(m_pParent);
   142: }
   143: 
   144: //====================
   145: 
   146: void UnloadPluginMenu::UpdateFolder()
   147: {
   148:     m_pSubMenu->DeleteMenuItems();
   149:     pMenuCommon->AddHeaderItem(m_pSubMenu, m_pszTitleANSI);
   150: 
   151:     if ((int)pPluginManager->pluginList.size() > 0)
   152:     {
   153:         char pluginNumber[MAX_LINE_LENGTH], pluginName[MAX_LINE_LENGTH], tempArgument[MAX_LINE_LENGTH];
   154: 
   155:         for (int i=0; i < (int)pPluginManager->pluginList.size(); i++)
   156:         {
   157:             strcpy_s(tempArgument, sizeofArray(tempArgument), "#");
   158:             strcat_s(tempArgument, sizeofArray(tempArgument), _itoa(i+1, pluginNumber, 10)); // Nb. Using more human friendly 1-N numbering for the UnloadPlugin bro@ms!
   159:             strcpy_s(pluginName, sizeofArray(pluginName), pPluginManager->GetPluginInfo(i, PLUGIN_NAME));
   160: 
   161:     //      pMenuCommon->CreateMenuItem(m_pSubMenu, MENUITEM_COMMAND, "@xoblite UnloadPlugin", tempArgument, pluginName, pPluginManager->pluginList[i].UpdateAvailable);
   162:             pMenuCommon->CreateMenuItem(m_pSubMenu, MENUITEM_COMMAND, "@xoblite UnloadPlugin", tempArgument, pluginName, false);
   163:         }
   164:     }
   165:     else pMenuCommon->CreateMenuItem(m_pSubMenu, MENUITEM_NOP, NULL, NULL, "(No plugins loaded)", false);
   166: 
   167:     pMenuCommon->AddFooterItem(m_pSubMenu, "...?");
   168: 
   169:     m_pSubMenu->Invalidate();
   170:     m_pSubMenu->Validate();
   171: }
   172: 
   173: //===========================================================================
   174: 
   175: BroamMenu::BroamMenu(char* pszTitle) : FolderItem(NULL, pszTitle, NULL)
   176: {
   177: }
   178: 
   179: BroamMenu::~BroamMenu()
   180: {
   181:     m_pParent->RemoveChild(m_pSubMenu);
   182:     if (m_pSubMenu) delete m_pSubMenu;
   183:     m_pSubMenu = NULL;
   184: }
   185: 
   186: //====================
   187: 
   188: bool BroamMenu::Active(bool bActivate)
   189: {
   190:     if (bActivate && !m_bActive) UpdateFolder();
   191:     return FolderItem::Active(bActivate);
   192: }
   193: 
   194: void BroamMenu::Attached(Menu* pMenu)
   195: {
   196:     m_pParent = pMenu;
   197:     m_pSubMenu = new Menu(pMenuCommon->hInst);
   198:     m_pParent->AddChild(m_pSubMenu);
   199:     m_pSubMenu->SetParent(m_pParent);
   200: }
   201: 
   202: //====================
   203: 
   204: void BroamMenu::UpdateFolder()
   205: {
   206:     m_pSubMenu->DeleteMenuItems();
   207:     pMenuCommon->AddHeaderItem(m_pSubMenu, m_pszTitleANSI);
   208: 
   209:     if ((int)pPluginManager->pluginList.size() > 0)
   210:     {
   211: //      char pluginName[MAX_LINE_LENGTH], pluginBroams[MAX_LINE_LENGTH], pluginCheck[MAX_LINE_LENGTH];
   212:         char pluginName[MAX_LINE_LENGTH], pluginBroams[MAX_LINE_LENGTH];
   213: 
   214:         for (int i=0; i < (int)pPluginManager->pluginList.size(); i++)
   215:         {
   216:             strcpy_s(pluginName, sizeofArray(pluginName), pPluginManager->GetPluginInfo(i, PLUGIN_NAME));
   217: 
   218:             // Check if the plugin supports the pluginInfo bro@m list parameter...
   219:             strcpy_s(pluginBroams, sizeofArray(pluginBroams), pPluginManager->GetPluginInfo(i, PLUGIN_BROAMS)); // Fetch broams list (if supported)...
   220: //          strcpy_s(pluginCheck, sizeofArray(pluginCheck), pPluginManager->getPluginInfo(i, -1)); // Fetch default fallback string...
   221: //          if (strnlen_s(pluginBroams, sizeofArray(pluginBroams)) && _stricmp(pluginBroams, pluginCheck))
   222: //          if (strnlen_s(pluginBroams, sizeofArray(pluginBroams)) && _stricmp(pluginBroams, pluginName) && (pluginBroams[0] == '@'))
   223:             if (strnlen_s(pluginBroams, sizeofArray(pluginBroams)) && _stricmp(pluginBroams, pluginName) && strchr(pluginBroams, '@'))
   224:             {
   225:                 // If it does, create a bro@m subfolder for the plugin...
   226:                 PluginBroamList *PBList = new PluginBroamList(pluginName, i);
   227:                 PBList->SetHeight(pMenuCommon->m_nSubmenuHeight);
   228:                 m_pSubMenu->AddMenuItem(PBList);
   229:             }
   230:             else
   231:             {
   232:                 // ...and if not we just create a [nop] == ghosted item...
   233:                 pMenuCommon->CreateMenuItem(m_pSubMenu, MENUITEM_NOP, NULL, NULL, pluginName, false);
   234:             }
   235:         }
   236:     }
   237:     else pMenuCommon->CreateMenuItem(m_pSubMenu, MENUITEM_NOP, NULL, NULL, "(No plugins loaded)", false);
   238: 
   239:     pMenuCommon->AddFooterItem(m_pSubMenu, "");
   240: 
   241:     m_pSubMenu->Invalidate();
   242:     m_pSubMenu->Validate();
   243: }
   244: 
   245: //===========================================================================
   246: 
   247: PluginBroamList::PluginBroamList(char* pszTitle, int pluginNumber) : FolderItem(NULL, pszTitle, NULL)
   248: {
   249:     plugNumber = pluginNumber;
   250: }
   251: 
   252: PluginBroamList::~PluginBroamList()
   253: {
   254:     m_pParent->RemoveChild(m_pSubMenu);
   255:     if (m_pSubMenu) delete m_pSubMenu;
   256:     m_pSubMenu = NULL;
   257: }
   258: 
   259: //====================
   260: 
   261: bool PluginBroamList::Active(bool bActivate)
   262: {
   263:     if (bActivate && !m_bActive) UpdateFolder();
   264:     return FolderItem::Active(bActivate);
   265: }
   266: 
   267: void PluginBroamList::Attached(Menu* pMenu)
   268: {
   269:     m_pParent = pMenu;
   270:     m_pSubMenu = new Menu(pMenuCommon->hInst);
   271:     m_pParent->AddChild(m_pSubMenu);
   272:     m_pSubMenu->SetParent(m_pParent);
   273: }
   274: 
   275: //====================
   276: 
   277: void PluginBroamList::UpdateFolder()
   278: {
   279:     m_pSubMenu->DeleteMenuItems();
   280:     pMenuCommon->AddHeaderItem(m_pSubMenu, m_pszTitleANSI);
   281: 
   282:     // Fetch bro@m list for the plugin...
   283:     char pluginBroamList[MAX_LINE_LENGTH], broam[MAX_LINE_LENGTH];
   284:     strcpy_s(pluginBroamList, sizeofArray(pluginBroamList), pPluginManager->GetPluginInfo(plugNumber, PLUGIN_BROAMS));
   285:     int nLen = strnlen_s(pluginBroamList, sizeofArray(pluginBroamList)) - 1;
   286: 
   287:     while (nLen) // Loop as long as there are characters in the buffer...
   288:     {
   289:         // Start from the end and scan backwards for the start of a bro@m -> a @ sign...
   290:         nLen = strnlen_s(pluginBroamList, sizeofArray(pluginBroamList)) - 1;
   291:         while (nLen >0 && pluginBroamList[nLen] != '@') nLen--;
   292:         // When found, we copy the bro@m to the buffer...
   293:         strcpy_s(broam, sizeofArray(broam), &pluginBroamList[nLen]);
   294:         // ...and truncate the list string...
   295:         pluginBroamList[nLen] = '\0';
   296: 
   297:         // Finally, we create a menu item for the bro@m...
   298:         if (!_stricmp(broam, "@---")) pMenuCommon->CreateMenuItem(m_pSubMenu, MENUITEM_SEPARATOR, NULL, NULL, NULL, false);
   299:         else pMenuCommon->CreateMenuItem(m_pSubMenu, MENUITEM_COMMAND, broam, NULL, broam, false);
   300:     }
   301: 
   302:     pMenuCommon->AddFooterItem(m_pSubMenu, "");
   303: 
   304:     m_pSubMenu->Invalidate();
   305:     m_pSubMenu->Validate();
   306: }
   307: 
   308: //===========================================================================
   309: