OSDN Git Service

949015fb5c763ccfe92b43e337f86fd5376caf2a
[winmerge-jp/winmerge-jp.git] / Docs / Developers / Plugins.html
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
2   "http://www.w3.org/TR/html4/loose.dtd">
3 <html>
4 <head>
5   <title>Plugins</title>
6   <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
7   <style type="text/css">
8   <!--
9     body {
10       font-family: Verdana,Helvetica,Arial,sans-serif;
11       font-size: small;
12     }
13     code,pre {
14       font-family: "Courier New",Courier,monospace;
15       font-size: 1em;
16     }
17     h3 {
18       padding: 2px;
19       border-left: 4px solid #FFCC00;
20       border-bottom: 1px solid #FFCC00;
21     }
22     h4 {
23       padding: 2px;
24       border-left: 8px solid #FF9933;
25       border-bottom: 1px solid #FF9933;
26     }
27     table {
28       border-collapse: collapse;
29       border: 1px solid black;
30     }
31     th {
32       text-align: left;
33       padding: 3px;
34       background-color: #EEEEEE;
35       border: 1px solid black;
36     }
37     td {
38       padding: 3px;
39       border: 1px solid black;
40     }
41     dt {
42       font-weight: bold;
43     }
44   -->
45   </style>
46 </head>
47 <body>
48 <h2>Plugins</h2>
49
50 <h3>Table of Contents</h3>
51 <ul>
52   <li><a href="#description">Quick description</a></li>
53   <li><a href="#events">Events</a></li>
54   <li><a href="#api">API</a></li>
55   <li><a href="#properties">Properties</a></li>
56   <li><a href="#methods">Methods</a></li>
57   <li><a href="#syntax">Syntax</a>
58     <ul>
59       <li><a href="#syntax_properties">Properties syntax</a></li>
60       <li><a href="#syntax_methods">Methods syntax</a></li>
61     </ul>
62   </li>
63   <li><a href="#write">How to write plugins quickly ?</a></li>
64   <li><a href="#debug">How to debug VC++ plugins ?</a></li>
65 </ul>
66
67 <h3><a name="description">Quick description</a></h3>
68 <p>Plugins use an ActiveX interface. Plugins may be written in any format that supports this interface.</p>
69 <p>Examples are available in :</p>
70 <ul>
71   <li>C++ COM component</li>
72   <li>VB ActiveX dll</li>
73   <li>Scriptlets (VBS, JS)</li>
74   <li>Delphi</li>
75 </ul>
76 <p>Limitation : Scriptlets only work for <code>EDITOR_SCRIPT</code> plugins.</p>
77 <p><a href="#properties">Properties</a> are used to present information concerning the plugin.<br />
78 <a href="#methods">Methods</a> are used to process the data. Method names and syntax depends on events and <a href="#api">API</a> (see below).</p>
79
80 <h3><a name="events">Events</a></h3>
81 <dl>
82   <dt><code>EDITOR_SCRIPT</code></dt>
83   <dd><p>In editor view, apply a function to the current selection.</p></dd>
84
85   <dt><code>PREDIFF</code></dt>
86   <dd>
87     <p>Preprocess file before diffing : the plugin is not apply to the text displayed in the editor. It is applied only to a copy of the left and right texts, and this copy are then scanned to create the difference list. As now :</p>
88     <ul>
89       <li>you may delete one column, change the names of variables...</li>
90       <li>you may not add/delete/move lines.</li>
91     </ul>
92   </dd>
93
94   <dt><code>PACK_UNPACK</code></dt>
95   <dd>
96     <p>Transform a file in a viewable format (for example, decompress a file...)</p>
97     <ul>
98       <li>The editor displays the unpacked data.</li>
99       <li>Sometimes files may be packed again (zipped files...). An additional function is of course necessary.</li>
100       <li>If the author of the plugin created this function, file may be saved again in the compressed format.</li>
101       <li>Else the file can only be saved in a text format. To avoid problems, you are proposed to change the filename when saving a changed file.</li>
102     </ul>
103   </dd>
104 </dl>
105
106 <h3><a name="api">API</a></h3>
107 <p>Some events have two API. One to exchange the data through a <code>BSTR</code> (memory) and one through input/ouput files.</p>
108
109 <table border="1">
110   <tr>
111     <td><code>FILE_PREDIFF</code></td>
112     <td>data are exchanged through an input and an output file</td>
113   </tr>
114   <tr>
115     <td><code>BUFFER_PREDIFF</code></td>
116     <td>data are exchanged through a <code>BSTR</code></td>
117   </tr>
118   <tr>
119     <td><code>FILE_PACK_UNPACK</code></td>
120     <td>data are exchanged through an input and an output file</td>
121   </tr>
122   <tr>
123     <td><code>BUFFER_PACK_UNPACK</code></td>
124     <td>data are exchanged through a <code>SafeArray</code> (<code>BSTR</code> not available as the packed data are possibly not text)</td>
125   </tr>
126   <tr>
127     <td><code>EDITOR_SCRIPT</code></td>
128     <td>data are exchanged through a <code>BSTR</code></td>
129   </tr>
130 </table>
131 <p>You need to define only one API to handle an event. Define the one you prefer.</p>
132
133 <h3><a name="properties">Properties</a></h3>
134 <table border="1">
135   <tr>
136     <th>Name</th>
137     <th>Mandatory</th>
138     <th>Events</th>
139   </tr>
140   <tr>
141     <td><code>PluginEvent</code></td>
142     <td>yes</td>
143     <td>all</td>
144   </tr>
145   <tr>
146     <td><code>PluginDescription</code></td>
147     <td>no</td>
148     <td>all</td>
149   </tr>
150   <tr>
151     <td><code>PluginFileFilters</code></td>
152     <td>no</td>
153     <td><code>PACK_UNPACK</code>, <code>PREDIFF</code></td>
154   </tr>
155   <tr>
156     <td><code>PluginIsAutomatic</code></td>
157     <td>if <code>PluginFileFilters</code> is defined</td>
158     <td><code>PACK_UNPACK</code>, <code>PREDIFF</code></td>
159   </tr>
160 </table>
161
162 <p><code>PluginIsAutomatic</code> and <code>PluginFileFilters</code> are for automatic mode :</p>
163 <ul>
164   <li>When <code>PluginIsAutomatic</code> is <code>false</code>, the plugin is never used in automatic mode.</li>
165   <li>When <code>PluginIsAutomatic</code> is <code>true</code>, <code>PluginFileFilters</code> is compared to the filename of both files. If one file
166       matches the filter, the plugin is applied.</li>
167 </ul>
168
169 <h3><a name="methods">Methods</a></h3>
170 <table border="1">
171   <tr>
172     <th>API</th>
173     <th>Method name</th>
174   </tr>
175   <tr>
176     <td><code>EDITOR_SCRIPT</code></td>
177     <td>function name is free<br /><br /><b>Note</b> : several functions may be defined in one <code>EDITOR_SCRIPT</code> plugin</td>
178   </tr>
179   <tr>
180     <td><code>BUFFER_PREDIFF</code></td>
181     <td><code>PrediffBufferW</code></td>
182   </tr>
183   <tr>
184     <td><code>FILE_PREDIFF</code></td>
185     <td><code>PrediffFile</code></td>
186   </tr>
187   <tr>
188     <td><code>BUFFER_PACK_UNPACK</code></td>
189     <td><code>UnpackBufferA</code><br /><code>PackBufferA</code></td>
190   </tr>
191   <tr>
192     <td><code>FILE_PACK_UNPACK</code></td>
193     <td><code>UnpackFile</code><br /><code>PackFile</code></td>
194   </tr>
195 </table>
196
197 <p><b>Note</b> : <code>PACK_UNPACK</code> functions use an additional parameter. The value may be set during <code>UnpackBuffer</code>.
198 When file is changed, the value is forwarded to <code>PackBuffer</code>.
199 The goal is to pass a parameter from <code>UnpackBuffer</code> to <code>PackBuffer</code>.<br />
200 For example, the plugin may handle several compressed formats, and use this value to recompress a file in
201 the format of the original.
202 This parameter is mandatory for the function's syntax. But you don't have to set its value when you don't use it.</p>
203
204 <h3><a name="syntax">Syntax</a></h3>
205
206 <h3><a name="syntax_properties">Properties syntax</a></h3>
207
208 <h4><code>PluginEvent</code></h4>
209 <table border="1">
210   <tr>
211     <th>C++</th>
212     <td><code>STDMETHODIMP CWinMergeScript::get_PluginEvent(BSTR * pVal)</code></td>
213   </tr>
214   <tr>
215     <th>VB</th>
216     <td><code>Public Property Get PluginEvent() As String</code></td>
217   </tr>
218   <tr>
219     <th>VBS</th>
220     <td><code>Function get_PluginEvent()</code></td>
221   </tr>
222 </table>
223
224 <h4><code>PluginDescription</code></h4>
225 <table border="1">
226   <tr>
227     <th>C++</th>
228     <td><code>STDMETHODIMP CWinMergeScript::get_PluginDescription(BSTR * pVal)</code></td>
229   </tr>
230   <tr>
231     <th>VB</th>
232     <td><code>Public Property Get PluginDescription() As String</code></td>
233   </tr>
234   <tr>
235     <th>VBS</th>
236     <td><code>Function get_PluginDescription()</code></td>
237   </tr>
238 </table>
239
240 <h4><code>PluginFileFilters</code></h4>
241 <p>String formed of fileFilters, separated with "<code>;</code>"</p>
242 <table border="1">
243   <tr>
244     <th>C++</th>
245     <td><code>STDMETHODIMP CWinMergeScript::get_PluginFileFilters(BSTR * pVal)</code></td>
246   </tr>
247   <tr>
248     <th>VB</th>
249     <td><code>Public Property Get PluginFileFilters() As String</code></td>
250   </tr>
251 </table>
252
253 <h4><code>PluginIsAutomatic</code></h4>
254 <table border="1">
255   <tr>
256     <th>C++</th>
257     <td><code>STDMETHODIMP CWinMergeScript::get_PluginIsAutomatic(VARIANT_BOOL * pVal)</code></td>
258   </tr>
259   <tr>
260     <th>VB</th>
261     <td><code>Public Property Get PluginIsAutomatic() As Boolean</code></td>
262   </tr>
263 </table>
264
265 <h3><a name="syntax_methods">Methods syntax</a></h3>
266
267 <h4><code>EDITOR_SCRIPT</code></h4>
268 <table border="1">
269   <tr>
270     <th></th>
271     <th>Functions parameters (function names are free)</th>
272   </tr>
273   <tr>
274     <th>C++</th>
275     <td><code>STDMETHOD(MakeUpperVB)([in] BSTR inputText, [out, retval] BSTR * outputText);</code></td>
276   </tr>
277   <tr>
278     <th>VB</th>
279     <td><code>Public Function MakeUpperVB(text As String)</code></td>
280   </tr>
281   <tr>
282     <th>VBS</th>
283     <td><code>Function MakeUpperVBS(Text)</code></td>
284   </tr>
285 </table>
286
287 <h4><code>FILE_PREDIFF</code></h4>
288 <table border="1">
289   <tr>
290     <th></th>
291     <th>Functions names</th>
292     <th>Functions parameters</th>
293   </tr>
294   <tr>
295     <th>VC++</th>
296     <td><code>STDMETHOD(PrediffFile)</code></td>
297     <td><code>([in] BSTR fileSrc, [in] BSTR fileDst, VARIANT_BOOL * pbChanged, INT * pSubcode, [out, retval] VARIANT_BOOL * pbSuccess)</code></td>
298   </tr>
299   <tr>
300     <th>VB</th>
301     <td><code>Public Function PrediffFile</code></td>
302     <td><code>(BSTR fileSrc, BSTR fileDst, ByRef bChanged As Boolean, ByRef subcode As Long) As Boolean</code></td>
303   </tr>
304 </table>
305
306 <h4><code>BUFFER_PREDIFF</code></h4>
307 <table border="1">
308   <tr>
309     <th></th>
310     <th>Functions names</th>
311     <th>Functions parameters</th>
312   </tr>
313   <tr>
314     <th>C++</th>
315     <td><code>STDMETHOD(PrediffBufferW)</code></td>
316     <td><code>([in] BSTR * pText, [in] INT * pSize, [in] VARIANT_BOOL * pbChanged, [out, retval] VARIANT_BOOL * pbHandled);</code></td>
317   </tr>
318   <tr>
319     <th>VB</th>
320     <td><code>Public Function PrediffBufferW</code></td>
321     <td><code>(ByRef text As String, ByRef size As Long, ByRef bChanged As Boolean) As Boolean</code></td>
322   </tr>
323 </table>
324
325 <h4><code>FILE_PACK_UNPACK</code></h4>
326 <table border="1">
327   <tr>
328     <th></th>
329     <th>Functions names</th>
330     <th>Functions parameters</th>
331   </tr>
332   <tr>
333     <th rowspan="2">VC++</th>
334     <td><code>STDMETHOD(UnpackFile)</code></td>
335     <td><code>([in] BSTR fileSrc, [in] BSTR fileDst, VARIANT_BOOL * pbChanged, INT * pSubcode, [out, retval] VARIANT_BOOL * pbSuccess)</code></td>
336   </tr>
337   <tr>
338     <td><code>STDMETHOD(PackFile)</code></td>
339     <td><code>([in] BSTR fileSrc, [in] BSTR fileDst, VARIANT_BOOL * pbChanged, INT pSubcode, [out, retval] VARIANT_BOOL * pbSuccess)</code></td>
340   </tr>
341   <tr>
342     <th rowspan="2">VB</th>
343     <td><code>Public Function UnpackFile</code></td>
344     <td><code>(BSTR fileSrc, BSTR fileDst, ByRef bChanged As Boolean, ByRef subcode As Long) As Boolean</code></td>
345   </tr>
346   <tr>
347     <td><code>Public Function PackFile</code></td>
348     <td><code>(BSTR fileSrc, BSTR fileDst, ByRef bChanged As Boolean, subcode As Long) As Boolean</code></td>
349   </tr>
350 </table>
351
352 <h4><code>BUFFER_PACK_UNPACK</code></h4>
353 <table border="1">
354   <tr>
355     <th></th>
356     <th>Functions names</th>
357     <th>Functions parameters</th>
358   </tr>
359   <tr>
360     <th rowspan="2">VC++</th>
361     <td><code>STDMETHOD(UnpackBufferA)</code></td>
362     <td><code>([in] SAFEARRAY ** pBuffer, [in] INT * pSize, [in] VARIANT_BOOL * pbChanged, [in] INT * pSubcode, [out, retval] VARIANT_BOOL * pbSuccess)</code></td>
363   </tr>
364   <tr>
365     <td><code>STDMETHOD(PackBufferA)</code></td>
366     <td><code>([in] SAFEARRAY ** pBuffer, [in] INT * pSize, [in] VARIANT_BOOL * pbChanged, [in] INT subcode, [out, retval] VARIANT_BOOL * pbSuccess)</code></td>
367   </tr>
368   <tr>
369     <th rowspan="2">VB</th>
370     <td><code>Public Function UnpackBufferA</code></td>
371     <td><code>(ByRef buffer() As Byte, ByRef size As Long, ByRef bChanged As Boolean, ByRef subcode As Long) As Boolean</code></td>
372   </tr>
373   <tr>
374     <td><code>Public Function PackBufferA</code></td>
375     <td><code>(ByRef buffer() As Byte, ByRef size As Long, ByRef bChanged As Boolean, subcode As Long) As Boolean</code></td>
376   </tr>
377 </table>
378
379 <h3><a name="write">How to write plugins quickly ?</a></h3>
380 <p>Easiest plugins are scriptlets.</p>
381 <p>Just VBscript (or JavaScript probably) with an additional section <code>&lt;implement&gt;</code>. See examples.<br />
382 But they are difficult to debug. And valid only for <code>EDITOR_SCRIPT</code> events.</p>
383
384 <h4>VC++ plugins :</h4>
385 <p>The most difficult to write when you do it from scratch. See in <code>Plugins/syntax.txt</code>, there are three additional steps from normal COM dll.</p>
386 <p>But easy to write from an existing plugin.</p>
387 <ol>
388   <li>Select a C++ plugin with the same API</li>
389   <li>Rename the files <code>cpp,def,dsp,idl,rc</code> : replace [<em>name of old plugin</em>] with [<em>name of your plugin</em>]</li>
390   <li>In all the files, replace all instances of [<em>name of old plugin</em>] with [<em>name of your plugin</em>]</li>
391   <li>Write your custom code : <code>WinMergeScript.cpp</code> holds all the important functions.</li>
392   <li>Generate new GUIDs and add to the <code>.idl</code> file.</li>
393 </ol>
394
395 <h4>Additional steps to write a plugin in C++</h4>
396 <ul>
397   <li>do not register the dll : delete everything in 'settings'->'custom build'</li>
398   <li>do not register the dll : delete the file <code>.rgs</code>, and the registry section in the file <code>.rc</code></li>
399   <li>do not register the dll : add <code>typeinfoex.h</code> + and make 3 changes in <code>WinMergeScript.h</code> (see commented lines)</li>
400   <li><code>SAFEARRAY</code> : replace the interface in <code>.idl</code> :
401     <ul>
402       <li><code>SAFEARRAY *</code>              <code>SAFEARRAY(unsigned char)</code></li>
403       <li><code>SAFEARRAY **</code>             <code>SAFEARRAY(unsigned char) *</code></li>
404     </ul>
405   </li>
406 </ul>
407
408 <h3><a name="debug">How to debug VC++ plugins ?</a></h3>
409 <p>Easy with Visual Studio after you installed WinMerge source.</p>
410
411 <h4><code>EDITOR_SCRIPT</code> :</h4>
412 <ol>
413   <li>Set a breakpoint at the beginning of <code>safeInvokeA</code> in <code>Plugins.cpp</code>.</li>
414   <li>Run WinMerge</li>
415   <li>Do all you need (open file, menu...) to call the plugin.</li>
416   <li>The breakpoint is triggered. The plugin interface is loaded at this moment.
417       Open the file <code>WinMergeScript.cpp</code> source of your plugin in the debugging session.</li>
418   <li>Set a breakpoint in this file at the beginning of your function.</li>
419   <li><code>F5</code>. The breakpoint in your function is triggered.</li>
420 </ol>
421
422 <h4><code>PREDIFF</code>, <code>PACK_UNPACK</code> :</h4>
423 <p>Same steps, point #1 only differs:</p>
424 <ol>
425   <li>Set a breakpoint at the beginning of <code>safeInvokeW</code> in <code>Plugins.cpp</code>.<br /><br />
426       <b>Note</b> : <code>safeInvokeW</code> instead of <code>safeInvokeA</code>.</li>
427 </ol>
428 </body>
429 </html>