OSDN Git Service

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