OSDN Git Service

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