OSDN Git Service

Add WinMergePluginBase.h
authorTakashi Sawanaka <sdottaka@users.sourceforge.net>
Mon, 10 May 2021 00:24:32 +0000 (09:24 +0900)
committerTakashi Sawanaka <sdottaka@users.sourceforge.net>
Mon, 10 May 2021 00:24:32 +0000 (09:24 +0900)
Src/Merge.vcxproj
Src/Merge.vcxproj.filters
Src/Plugins.cpp
Src/Plugins.h
Src/WinMergePluginBase.h [new file with mode: 0644]

index 022e644..6187a37 100644 (file)
     <ClInclude Include="Common\VersionInfo.h" />\r
     <ClInclude Include="WildcardDropList.h" />\r
     <ClInclude Include="WindowsManagerDialog.h" />\r
+    <ClInclude Include="WinMergePluginBase.h" />\r
     <ClInclude Include="Win_VersionHelper.h" />\r
     <ClInclude Include="WMGotoDlg.h" />\r
     <ClInclude Include="xdiff_gnudiff_compat.h" />\r
index 215c17e..08e7556 100644 (file)
     <ClInclude Include="Common\IniOptionsMgr.h">\r
       <Filter>Common\Header Files</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="WinMergePluginBase.h">\r
+      <Filter>Header Files</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <None Include="res\binarydiff.ico">\r
index 940a156..90c617f 100644 (file)
@@ -39,6 +39,7 @@
 #include "OptionsDef.h"
 #include "codepage_detect.h"
 #include "UniFile.h"
+#include "WinMergePluginBase.h"
 
 using std::vector;
 using Poco::RegularExpression;
@@ -375,50 +376,21 @@ static String GetCustomFilters(const String& name, const String& filtersTextDefa
                return filtersTextDefault;
 }
 
-class UnpackerGeneratedFromEditorScript: public IDispatch
+class UnpackerGeneratedFromEditorScript: public WinMergePluginBase
 {
 public:
-       UnpackerGeneratedFromEditorScript(IDispatch *pDispatch, int id) : m_pDispatch(pDispatch), m_funcid(id), m_nRef(0)
+       UnpackerGeneratedFromEditorScript(IDispatch *pDispatch, const std::wstring funcname, int id) : m_pDispatch(pDispatch), m_funcid(id)
        {
+               m_sDescription =
+                       strutils::format_string1(_T("Unpacker to execute %1 script (automatically generated)") , funcname);
+               m_sFileFilters = _T(".");
+               m_bIsAutomatic = true;
+               m_sEvent = L"FILE_PACK_UNPACK";
                m_pDispatch->AddRef();
        }
 
-       HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override
+       virtual ~UnpackerGeneratedFromEditorScript()
        {
-               return E_NOTIMPL;
-       }
-
-       ULONG STDMETHODCALLTYPE AddRef(void) override
-       {
-               return ++m_nRef;
-       }
-
-       ULONG STDMETHODCALLTYPE Release(void) override
-       {
-               if (--m_nRef == 0)
-               {
-                       m_pDispatch->Release();
-                       delete this;
-                       return 0;
-               }
-               return m_nRef;
-       }
-
-       HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* pctinfo) override
-       {
-               return E_NOTIMPL;
-       }
-
-       HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) override
-       {
-               return E_NOTIMPL;
-       }
-
-       HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) override
-       {
-               for (unsigned i = 0; i < cNames; ++i)
-                       rgDispId[i] = (wcscmp(L"UnpackFile", rgszNames[i]) == 0) ? 1 : -1;
-               return S_OK;
        }
 
        static HRESULT ReadFile(const String& path, String& text)
@@ -454,53 +426,27 @@ public:
                return S_OK;
        }
 
-       HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) override
+       HRESULT STDMETHODCALLTYPE UnpackFile(BSTR fileSrc, BSTR fileDst, VARIANT_BOOL* pbChanged, INT* pSubcode, VARIANT_BOOL* pbSuccess) override
        {
-               if (!pDispParams)
-                       return DISP_E_BADVARTYPE;
-               if (dispIdMember != 1)
-                       return E_NOTIMPL;
-
-               BSTR dstPath = pDispParams->rgvarg[2].bstrVal;
-               BSTR srcPath = pDispParams->rgvarg[3].bstrVal;
-
-               int changed = 0;
                String text;
-               HRESULT hr = ReadFile(srcPath, text);
+               HRESULT hr = ReadFile(fileSrc, text);
                if (FAILED(hr))
                        return hr;
+               int changed = 0;
                if (!plugin::InvokeTransformText(text, changed, m_pDispatch, m_funcid))
                        return E_FAIL;
-               hr = WriteFile(dstPath, text);
+               hr = WriteFile(fileDst, text);
                if (FAILED(hr))
                        return hr;
-
-               *pDispParams->rgvarg[1].pboolVal = VARIANT_TRUE;
-               pVarResult->boolVal = VARIANT_TRUE;
+               *pSubcode = 0;
+               *pbChanged = VARIANT_TRUE;
+               *pbSuccess = VARIANT_TRUE;
                return S_OK;
        }
 
-       static PluginInfoPtr MakePluginInfo(PluginInfo *pPluginBase, const String& funcname, int fncid)
-       {
-               PluginInfoPtr plugin(new PluginInfo);
-               plugin->m_lpDispatch = new UnpackerGeneratedFromEditorScript(pPluginBase->m_lpDispatch, fncid);
-               plugin->m_lpDispatch->AddRef();
-               plugin->m_name = pPluginBase->m_name + _T(":") + funcname;
-               plugin->m_description =
-                       strutils::format_string2(_T("Unpacker to execute %1 script (automatically generated from %2)")
-                               , funcname, pPluginBase->m_name);
-               plugin->m_disabled = false;
-               plugin->m_filtersTextDefault = _T(".");
-               plugin->m_filtersText = GetCustomFilters(plugin->m_name, plugin->m_filtersTextDefault);
-               plugin->m_bAutomatic = true;
-               plugin->m_event = L"FILE_PACK_UNPACK";
-               return plugin;
-       }
-
 private:
        IDispatch *m_pDispatch;
        int m_funcid;
-       int m_nRef;
 };
 
 /**
@@ -524,19 +470,11 @@ struct ScriptInfo
  *
  * @return 1 if loaded plugin successfully, negatives for errors
  */
-int PluginInfo::LoadPlugin(const String & scriptletFilepath)
+int PluginInfo::MakeInfo(const String & scriptletFilepath, IDispatch *lpDispatch)
 {
        // set up object in case we need to log info
        ScriptInfo scinfo(scriptletFilepath);
 
-       // Search for the class "WinMergeScript"
-       LPDISPATCH lpDispatch = CreateDispatchBySource(scriptletFilepath.c_str(), L"WinMergeScript");
-       if (lpDispatch == nullptr)
-       {
-               scinfo.Log(_T("WinMergeScript entry point not found"));
-               return -10; // error
-       }
-
        // Ensure that interface is released if any bad exit or exception
        AutoReleaser<IDispatch> drv(lpDispatch);
 
@@ -702,6 +640,27 @@ int PluginInfo::LoadPlugin(const String & scriptletFilepath)
        return 1;
 }
 
+/**
+ * @brief Try to load a plugin
+ *
+ * @return 1 if loaded plugin successfully, negatives for errors
+ */
+int PluginInfo::LoadPlugin(const String & scriptletFilepath)
+{
+       // set up object in case we need to log info
+       ScriptInfo scinfo(scriptletFilepath);
+
+       // Search for the class "WinMergeScript"
+       LPDISPATCH lpDispatch = CreateDispatchBySource(scriptletFilepath.c_str(), L"WinMergeScript");
+       if (lpDispatch == nullptr)
+       {
+               scinfo.Log(_T("WinMergeScript entry point not found"));
+               return -10; // error
+       }
+
+       return MakeInfo(scriptletFilepath, lpDispatch);
+}
+
 static void ReportPluginLoadFailure(const String & scriptletFilepath)
 {
        AppErrorMessageBox(strutils::format(_T("Exception loading plugin\r\n%s"), scriptletFilepath));
@@ -862,8 +821,10 @@ static std::map<String, PluginArrayPtr> GetAvailableScripts()
                        {
                                if (plugins.find(L"FILE_PACK_UNPACK") == plugins.end())
                                        plugins[L"FILE_PACK_UNPACK"].reset(new PluginArray);
-                               PluginInfoPtr pluginNew = UnpackerGeneratedFromEditorScript::MakePluginInfo(plugin.get(), namesArray[i], idArray[i]);
-                               pluginNew->m_disabled = (disabled_plugin_list.find(pluginNew->m_name) != disabled_plugin_list.end());
+                               PluginInfoPtr pluginNew(new PluginInfo());
+                               IDispatch *pDispatch = new UnpackerGeneratedFromEditorScript(plugin->m_lpDispatch, namesArray[i], idArray[i]);
+                               pDispatch->AddRef();
+                               pluginNew->MakeInfo(plugin->m_filepath + _T(":") + namesArray[i], pDispatch);
                                plugins[L"FILE_PACK_UNPACK"]->push_back(pluginNew);
                        }
                }
index fbe3ee0..eb3fd74 100644 (file)
@@ -47,6 +47,7 @@ public:
        }
 
        int LoadPlugin(const String & scriptletFilepath);
+       int MakeInfo(const String & scriptletFilepath, IDispatch *pDispatch);
 
        /// Parse the filter string (only for files), and create the filters
        void LoadFilterString();
diff --git a/Src/WinMergePluginBase.h b/Src/WinMergePluginBase.h
new file mode 100644 (file)
index 0000000..6f03b1b
--- /dev/null
@@ -0,0 +1,304 @@
+#include <oleauto.h>
+#include <string>
+#include <map>
+
+class WinMergePluginBase : public IDispatch, public ITypeInfo
+{
+public:
+       enum
+       {
+               DISPID_UnpackFile,
+               DISPID_PackFile,
+               DISPID_ShowSettingsDialog,
+               DISPID_PluginFileFilters,
+               DISPID_PluginIsAutomatic,
+               DISPID_PluginDescription,
+               DISPID_PluginEvent,
+       };
+       struct MemberInfo { std::wstring name; DISPID id; int flags; };
+
+       WinMergePluginBase() : m_nRef(0)
+       {
+               static const MemberInfo memberInfo[] =
+               {
+                       { L"UnpackFile",         DISPID_UnpackFile,         DISPATCH_METHOD },
+                       { L"PackFile",           DISPID_PackFile ,          DISPATCH_METHOD },
+                       { L"ShowSettingsDialog", DISPID_ShowSettingsDialog, DISPATCH_METHOD },
+                       { L"PluginFileFilters",  DISPID_PluginFileFilters,  DISPATCH_PROPERTYGET },
+                       { L"PluginIsAutomatic",  DISPID_PluginIsAutomatic,  DISPATCH_PROPERTYGET },
+                       { L"PluginDescription",  DISPID_PluginDescription,  DISPATCH_PROPERTYGET },
+                       { L"PluginEvent",        DISPID_PluginEvent,        DISPATCH_PROPERTYGET },
+               };
+               for (auto item : memberInfo)
+               {
+                       m_memberInfo.push_back(item);
+                       m_mapNameToIndex.emplace(item.name, item.id);
+               }
+       }
+
+       virtual ~WinMergePluginBase() {}
+
+       HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override
+       {
+               return E_NOTIMPL;
+       }
+
+       ULONG STDMETHODCALLTYPE AddRef(void) override
+       {
+               return ++m_nRef;
+       }
+
+       ULONG STDMETHODCALLTYPE Release(void) override
+       {
+               if (--m_nRef == 0)
+               {
+                       delete this;
+                       return 0;
+               }
+               return m_nRef;
+       }
+
+       HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* pctinfo) override
+       {
+               *pctinfo = static_cast<UINT>(m_memberInfo.size());
+               return S_OK;
+       }
+
+       HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) override
+       {
+               *ppTInfo = this;
+               (*ppTInfo)->AddRef();
+               return S_OK;
+       }
+
+       HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) override
+       {
+               for (unsigned i = 0; i < cNames; ++i)
+               {
+                       auto it = m_mapNameToIndex.find(rgszNames[i]);
+                       if (it == m_mapNameToIndex.end())
+                               return DISP_E_UNKNOWNNAME;
+                       rgDispId[i] = it->second;
+               }
+               return S_OK;
+       }
+
+       HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) override
+       {
+               if (!pDispParams)
+                       return DISP_E_BADVARTYPE;
+               HRESULT hr = E_NOTIMPL;
+               if (wFlags == DISPATCH_METHOD)
+               {
+                       switch (dispIdMember)
+                       {
+                       case DISPID_UnpackFile:
+                       {
+                               BSTR fileSrc = pDispParams->rgvarg[3].bstrVal;
+                               BSTR fileDst = pDispParams->rgvarg[2].bstrVal;
+                               VARIANT_BOOL* pbChanged = pDispParams->rgvarg[1].pboolVal;
+                               INT* pSubcode = &pDispParams->rgvarg[0].intVal;
+                               VARIANT_BOOL* pbSuccess = &pVarResult->boolVal;
+                               hr = UnpackFile(fileSrc, fileDst, pbChanged, pSubcode, pbSuccess);
+                               break;
+                       }
+                       case DISPID_PackFile:
+                       {
+                               BSTR fileSrc = pDispParams->rgvarg[3].bstrVal;
+                               BSTR fileDst = pDispParams->rgvarg[2].bstrVal;
+                               VARIANT_BOOL* pbChanged = pDispParams->rgvarg[1].pboolVal;
+                               INT subcode = pDispParams->rgvarg[0].intVal;
+                               VARIANT_BOOL* pbSuccess = &pVarResult->boolVal;
+                               hr = PackFile(fileSrc, fileDst, pbChanged, subcode, pbSuccess);
+                               break;
+                       }
+                       case DISPID_ShowSettingsDialog:
+                               hr = ShowSettingsDialog(&pVarResult->boolVal);
+                               break;
+                       }
+               }
+               else if (wFlags == DISPATCH_PROPERTYGET)
+               {
+                       switch (dispIdMember)
+                       {
+                       case DISPID_PluginFileFilters:
+                               pVarResult->vt = VT_BSTR;
+                               hr = get_PluginFileFilters(&pVarResult->bstrVal);
+                               break;
+                       case DISPID_PluginIsAutomatic:
+                               pVarResult->vt = VT_BOOL;
+                               hr = get_PluginIsAutomatic(&pVarResult->boolVal);
+                               break;
+                       case DISPID_PluginDescription:
+                               pVarResult->vt = VT_BSTR;
+                               hr = get_PluginDescription(&pVarResult->bstrVal);
+                               break;
+                       case DISPID_PluginEvent:
+                               pVarResult->vt = VT_BSTR;
+                               hr = get_PluginEvent(&pVarResult->bstrVal);
+                               break;
+                       }
+               }
+               return hr;
+       }
+
+       HRESULT STDMETHODCALLTYPE GetTypeAttr(TYPEATTR** ppTypeAttr) override
+       {
+               auto* pTypeAttr = new TYPEATTR();
+               pTypeAttr->cFuncs = static_cast<WORD>(m_memberInfo.size());
+               *ppTypeAttr = pTypeAttr;
+               return S_OK;
+       }
+       
+       HRESULT STDMETHODCALLTYPE GetTypeComp(ITypeComp** ppTComp) override
+       {
+               return E_NOTIMPL;
+       }
+       
+       HRESULT STDMETHODCALLTYPE GetFuncDesc(UINT index, FUNCDESC** ppFuncDesc) override
+       {
+               if (index >= m_memberInfo.size())
+                       return E_INVALIDARG;
+               auto* pFuncDesc = new FUNCDESC();
+               pFuncDesc->invkind = static_cast<INVOKEKIND>(m_memberInfo[index].flags);
+               pFuncDesc->wFuncFlags = 0;
+               pFuncDesc->memid = index;
+               *ppFuncDesc = pFuncDesc;
+               return S_OK;
+       }
+       
+       HRESULT STDMETHODCALLTYPE GetVarDesc(UINT index, VARDESC** ppVarDesc) override
+       {
+               return E_NOTIMPL;
+       }
+       
+       HRESULT STDMETHODCALLTYPE GetNames(MEMBERID memid, BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames) override
+       {
+               if (memid >= m_memberInfo.size())
+                       return E_INVALIDARG;
+               *rgBstrNames = SysAllocString(m_memberInfo[memid].name.c_str());
+               *pcNames = 1;
+               return S_OK;
+       }
+       
+       HRESULT STDMETHODCALLTYPE GetRefTypeOfImplType(UINT index, HREFTYPE *pRefType) override
+       {
+               return E_NOTIMPL;
+       }
+
+       HRESULT STDMETHODCALLTYPE GetImplTypeFlags(UINT index, INT *pImplTypeFlags) override
+       {
+               return E_NOTIMPL;
+       }
+       
+       HRESULT STDMETHODCALLTYPE GetIDsOfNames(LPOLESTR* rgszNames, UINT cNames, MEMBERID* pMemId) override
+       {
+               return GetIDsOfNames(IID_NULL, rgszNames, cNames, 0, pMemId);
+       }
+       
+       HRESULT STDMETHODCALLTYPE Invoke(PVOID pvInstance, MEMBERID memid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) override
+       {
+               return reinterpret_cast<IDispatch*>(pvInstance)->Invoke(memid, IID_NULL, 0, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+       }
+       
+       HRESULT STDMETHODCALLTYPE GetDocumentation(MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString, DWORD *pdwHelpContext, BSTR *pBstrHelpFile) override
+       {
+               return E_NOTIMPL;
+       }
+       
+       HRESULT STDMETHODCALLTYPE GetDllEntry(MEMBERID memid, INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName, WORD *pwOrdinal)
+       {
+               return E_NOTIMPL;
+       }
+       
+       HRESULT STDMETHODCALLTYPE GetRefTypeInfo(HREFTYPE hRefType, ITypeInfo **ppTInfo) override
+       {
+               return E_NOTIMPL;
+       }
+       
+       HRESULT STDMETHODCALLTYPE AddressOfMember(MEMBERID memid, INVOKEKIND invKind, PVOID *ppv) override
+       {
+               return E_NOTIMPL;
+       }
+       
+       HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown *pUnkOuter, REFIID riid, PVOID *ppvObj) override
+       {
+               return E_NOTIMPL;
+       }
+       
+       HRESULT STDMETHODCALLTYPE GetMops(MEMBERID memid, BSTR *pBstrMops) override
+       {
+               return E_NOTIMPL;
+       }
+       
+       HRESULT STDMETHODCALLTYPE GetContainingTypeLib(ITypeLib **ppTLib, UINT *pIndex) override
+       {
+               return E_NOTIMPL;
+       }
+       
+       void STDMETHODCALLTYPE ReleaseTypeAttr(TYPEATTR *pTypeAttr) override
+       {
+               delete pTypeAttr;
+       }
+       
+       void STDMETHODCALLTYPE ReleaseFuncDesc(FUNCDESC *pFuncDesc) override
+       {
+               delete pFuncDesc;
+       }
+       
+       void STDMETHODCALLTYPE ReleaseVarDesc(VARDESC *pVarDesc) override
+       {
+       }
+       
+       virtual HRESULT STDMETHODCALLTYPE PackFile(BSTR fileSrc, BSTR fileDst, VARIANT_BOOL* pbChanged, INT subcode, VARIANT_BOOL* pbSuccess)
+       {
+               *pbSuccess = VARIANT_FALSE;
+               return E_NOTIMPL;
+       }
+
+       virtual HRESULT STDMETHODCALLTYPE UnpackFile(BSTR fileSrc, BSTR fileDst, VARIANT_BOOL* pbChanged, INT* pSubcode, VARIANT_BOOL* pbSuccess)
+       {
+               *pbSuccess = VARIANT_FALSE;
+               return E_NOTIMPL;
+       }
+
+       virtual HRESULT STDMETHODCALLTYPE ShowSettingsDialog(VARIANT_BOOL* pbHandled)
+       {
+               *pbHandled = VARIANT_FALSE;
+               return E_NOTIMPL;
+       }
+
+       virtual HRESULT STDMETHODCALLTYPE get_PluginIsAutomatic(VARIANT_BOOL* pVal)
+       {
+               *pVal = m_bIsAutomatic ? -1 : 0;
+               return S_OK;
+       }
+
+       virtual HRESULT STDMETHODCALLTYPE get_PluginFileFilters(BSTR* pVal)
+       {
+               *pVal = SysAllocString(m_sFileFilters.c_str());
+               return S_OK;
+       }
+
+       virtual HRESULT STDMETHODCALLTYPE get_PluginDescription(BSTR* pVal)
+       {
+               *pVal = SysAllocString(m_sDescription.c_str());
+               return S_OK;
+       }
+
+       virtual HRESULT STDMETHODCALLTYPE get_PluginEvent(BSTR* pVal)
+       {
+               *pVal = SysAllocString(m_sEvent.c_str());
+               return S_OK;
+       }
+
+protected:
+       int m_nRef;
+       std::map<std::wstring, int> m_mapNameToIndex;
+       std::vector<MemberInfo> m_memberInfo;
+       std::wstring m_sEvent;
+       std::wstring m_sDescription;
+       std::wstring m_sFileFilters;
+       bool m_bIsAutomatic;
+};
+