OSDN Git Service

compiler-calculated maximum value for `m_SourceDefs` (#966)
[winmerge-jp/winmerge-jp.git] / Src / Plugins.h
1 /////////////////////////////////////////////////////////////////////////////
2 //    WinMerge:  an interactive diff/merge utility
3 //    Copyright (C) 1997-2000  Thingamahoochie Software
4 //    Author: Dean Grimm
5 //    SPDX-License-Identifier: GPL-2.0-or-later
6 /////////////////////////////////////////////////////////////////////////////
7 /**
8  *  @file Plugins.h
9  *
10  *  @brief Declaration file for VBS Scriptlets, VB ActiveX DLL, VC++ COM DLL
11  */ 
12 #pragma once
13
14 #include <Poco/Foundation.h>
15 #include <string>
16 #include <vector>
17 #include <optional>
18 #include <windows.h>
19 #include <oleauto.h>
20 #include <memory>
21 #include "UnicodeString.h"
22
23 struct FileFilterElement;
24 typedef std::shared_ptr<FileFilterElement> FileFilterElementPtr;
25
26 /**
27  * @brief List of transformation categories (events)
28  *
29  * @note If you add some event, you have to complete this array in FileTransform.cpp
30  */
31 extern const wchar_t *TransformationCategories[];
32
33 /** 
34  * @brief Information structure for a plugin
35  */
36 class PluginInfo
37 {
38 public:
39         PluginInfo()
40                 : m_lpDispatch(nullptr)
41                 , m_filters(NULL)
42                 , m_bAutomatic(false)
43                 , m_nFreeFunctions(0)
44                 , m_disabled(false)
45                 , m_hasArgumentsProperty(false)
46         {       
47         }
48
49         ~PluginInfo()
50         {
51                 if (m_lpDispatch!=nullptr)
52                         m_lpDispatch->Release();
53         }
54
55         int LoadPlugin(const String & scriptletFilepath);
56         int MakeInfo(const String & scriptletFilepath, IDispatch *pDispatch);
57
58         /// Parse the filter string (only for files), and create the filters
59         void LoadFilterString();
60         /**
61          * @brief Does the plugin handles this(ese) filename(s) ?
62          *
63          * @param szTest String of filenames, delimited with '|'
64          */
65         bool TestAgainstRegList(const String& szTest) const;
66
67         std::optional<StringView> GetExtendedPropertyValue(const String& name) const;
68
69 public:
70         String      m_filepath;
71         LPDISPATCH  m_lpDispatch;
72         String      m_name; // usually filename, except for special cases (like auto or no)
73         String      m_ext;
74         String      m_extendedProperties;
75         String      m_arguments;
76         String      m_argumentsDefault;
77         String      m_filtersText;
78         String      m_filtersTextDefault;
79         String      m_description;
80         String      m_event;
81         bool        m_bAutomatic;
82         bool        m_bAutomaticDefault;
83         bool        m_disabled;
84         bool        m_hasArgumentsProperty;
85         bool        m_hasVariablesProperty;
86         std::vector<FileFilterElementPtr> m_filters;
87         /// only for plugins with free function names (EDITOR_SCRIPT)
88         int         m_nFreeFunctions;
89
90 private:
91         PluginInfo( const PluginInfo& other ); // non construction-copyable
92         PluginInfo& operator=( const PluginInfo& ); // non copyable
93 };
94
95 typedef std::shared_ptr<PluginInfo> PluginInfoPtr;
96
97 typedef std::vector<PluginInfoPtr> PluginArray;
98 typedef std::shared_ptr<PluginArray> PluginArrayPtr;
99
100 /**
101  * @brief Cache for the scriptlets' interfaces during the life of a thread. 
102  * One instance and only one for each thread (necessary for VB)
103  *
104  * @note Never create CScriptsOfThread directly : use the class CAssureScriptsForThread
105  * to guarantee unicity
106  */
107 class CScriptsOfThread
108 {
109 friend class CAssureScriptsForThread;
110 friend class CAllThreadsScripts;
111 public:
112         PluginArray * GetAvailableScripts(const wchar_t *transformationEvent);
113         PluginInfo * GetUnpackerPluginByFilter(const String& filteredText);
114         PluginInfo * GetAutomaticPluginByFilter(const wchar_t *transformationEvent, const String& filteredText);
115         PluginInfo * GetPluginByName(const wchar_t *transformationEvent, const String& name);
116         PluginInfo * GetPluginInfo(LPDISPATCH piScript);
117         void SaveSettings();
118
119         void FreeAllScripts();
120         void FreeScriptsForEvent(const wchar_t *transformationEvent);
121
122 protected:
123         CScriptsOfThread();
124         ~CScriptsOfThread();
125         void Lock()       { m_nLocks ++; };
126         bool Unlock()   { m_nLocks --; return (m_nLocks == 0); };
127         /// Tell if this scripts is the one for main thread (by convention, the first in the repository)
128         bool bInMainThread();
129
130 private:
131         unsigned m_nLocks;
132         unsigned long m_nThreadId;
133         /// Result of CoInitialize
134         HRESULT hrInitialize;
135         int nTransformationEvents;
136         std::map<String, PluginArrayPtr> m_aPluginsByEvent;
137 };
138
139
140 /**
141  * @brief Repository of CScriptsOfThread
142  */
143 class CAllThreadsScripts
144 {
145 friend class CAssureScriptsForThread;
146 protected:
147         static void Add(CScriptsOfThread * scripts);
148         static void Remove(CScriptsOfThread * scripts);
149         static CScriptsOfThread * GetActiveSetNoAssert();
150 public:
151         /// main public function : get the plugins array for the current thread
152         static CScriptsOfThread * GetActiveSet();
153         /// by convention, the scripts for main thread must be created before all others
154         static bool bInMainThread(CScriptsOfThread * scripts);
155         using InternalPluginLoaderFuncPtr = bool (*)(std::map<String, PluginArrayPtr>& aPluginsByEvent, String& errmsg);
156         static InternalPluginLoaderFuncPtr GetInternalPluginsLoader() { return m_funcInternalPluginsLoader; }
157         static void RegisterInternalPluginsLoader(InternalPluginLoaderFuncPtr func) { m_funcInternalPluginsLoader = func; }
158         static void ReloadCustomSettings();
159 private:
160         // fixed size array, advantage : no mutex to allocate/free
161         static std::vector<CScriptsOfThread *> m_aAvailableThreads;
162         static inline InternalPluginLoaderFuncPtr m_funcInternalPluginsLoader = nullptr;
163 };
164
165 /**
166  * @brief Simple control to add/remove a CScriptsOfThread in the repository. 
167  * Create at least one CAssumeScriptsForThread for each thread, including the main one.
168  * It's OK to create several CAssumeScriptsForThread for the same thread (if you need scripts in one function 
169  * and do not know what happened before the function).
170  */
171 class CAssureScriptsForThread
172 {
173 public:
174         CAssureScriptsForThread();
175         ~CAssureScriptsForThread();
176 };
177
178 namespace plugin
179 {
180
181 /**
182  * @brief Check for the presence of Windows Script
183  *
184  * .sct plugins require this optional component
185  */
186 bool IsWindowsScriptThere();
187 /**
188  * @brief Get a list of the function IDs and names in a script or activeX/COM DLL
189  *
190  * @return Returns the number of functions
191  *
192  */
193 int GetMethodsFromScript(LPDISPATCH piDispatch, std::vector<String>& namesArray, std::vector<int>& IdArray);
194
195 /**
196 /**
197  * @brief Get the ID of the a free function
198  * @param methodOrdinal : index of the free function (0,1,2...)
199  */
200 int GetMethodIDInScript(LPDISPATCH piDispatch, int methodIndex);
201
202
203
204 // Wrappers to call plugins methods
205
206 /**
207  * @brief Call the plugin "PrediffBufferW" method, events PREDIFFING
208  *
209  * @param bstrBuf Overwrite/realloc this buffer
210  */
211 bool InvokePrediffBuffer(BSTR & bstrBuf, int & nChanged, LPDISPATCH piScript);
212
213 /** 
214  * @brief Call custom plugin functions : text transformation
215  */
216 bool InvokeTransformText(String & text, int & changed, LPDISPATCH piScript, int fncId);
217
218 /**
219  * @brief Call the plugin "UnpackBufferA" method, event BUFFER_PACK_UNPACK
220  *
221  * @param pszBuf has unknown format, so a simple char*
222  * never owervrites this source buffer
223  */
224 bool InvokeUnpackBuffer(VARIANT & array, int & nChanged, LPDISPATCH piScript, int & subcode);
225 /**
226  * @brief Call the plugin "PackBufferA" method, event BUFFER_PACK_UNPACK
227  *
228  * @param pszBuf has unknown format, so a simple char*
229  * never owervrites this source buffer
230  */
231 bool InvokePackBuffer(VARIANT & array, int & nChanged, LPDISPATCH piScript, int subcode);
232 /**
233  * @brief Call the plugin "UnpackFile" method, event FILE_PACK_UNPACK
234  */
235 bool InvokeUnpackFile(const String& fileSource, const String& fileDest, int & nChanged, LPDISPATCH piScript, int & subCode);
236 /**
237  * @brief Call the plugin "PackFile" method, event FILE_PACK_UNPACK
238  */
239 bool InvokePackFile(const String& fileSource, const String& fileDest, int & nChanged, LPDISPATCH piScript, int subCode);
240 /**
241  * @brief Call the plugin "IsFolder" method, event FILE_FOLDER_PACK_UNPACK
242  */
243 bool InvokeIsFolder(const String& file, IDispatch *piScript);
244 /**
245  * @brief Call the plugin "UnpackFolder" method, event FILE_FOLDER_PACK_UNPACK
246  */
247 bool InvokeUnpackFolder(const String& fileSource, const String& folderDest, int & nChanged, IDispatch *piScript, int & subCode);
248 /**
249  * @brief Call the plugin "PackFolder" method, event FILE_FOLDER_PACK_UNPACK
250  */
251 bool InvokePackFolder(const String& folderSource, const String& fileDest, int & nChanged, IDispatch *piScript, int subCode);
252 /**
253  * @brief Call the plugin "PrediffFile" method, event FILE_PREDIFF
254  */
255 bool InvokePrediffFile(const String& fileSource, const String& fileDest, int & nChanged, LPDISPATCH piScript);
256 /**
257  * @brief Call the plugin "ShowSettingsDialog" method
258  */
259 bool InvokeShowSettingsDialog(LPDISPATCH piScript);
260
261 /**
262  * @brief Set value to the plugin "PluginArguments" property 
263  */
264 bool InvokePutPluginArguments(const String& args, LPDISPATCH piScript);
265
266 /**
267  * @brief Set value to the plugin "PluginVariables" property 
268  */
269 bool InvokePutPluginVariables(const String& args, LPDISPATCH piScript);
270 }