1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
2 "http://www.w3.org/TR/html4/loose.dtd">
6 <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
7 <style type="text/css">
10 font-family: Verdana,Helvetica,Arial,sans-serif;
14 font-family: "Courier New",Courier,monospace;
19 border-left: 4px solid #FFCC00;
20 border-bottom: 1px solid #FFCC00;
24 border-left: 8px solid #FF9933;
25 border-bottom: 1px solid #FF9933;
28 border-collapse: collapse;
29 border: 1px solid black;
34 background-color: #EEEEEE;
35 border: 1px solid black;
39 border: 1px solid black;
50 <h3>Table of Contents</h3>
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>
59 <li><a href="#syntax_properties">Properties syntax</a></li>
60 <li><a href="#syntax_methods">Methods syntax</a></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>
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>
71 <li>C++ COM component</li>
72 <li>VB ActiveX dll</li>
73 <li>Scriptlets (VBS, JS)</li>
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>
80 <h3><a name="events">Events</a></h3>
82 <dt><code>EDITOR_SCRIPT</code></dt>
83 <dd><p>In editor view, apply a function to the current selection.</p></dd>
85 <dt><code>PREDIFF</code></dt>
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>
89 <li>you may delete one column, change the names of variables...</li>
90 <li>you may not add/delete/move lines.</li>
94 <dt><code>PACK_UNPACK</code></dt>
96 <p>Transform a file in a viewable format (for example, decompress a file...)</p>
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>
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>
111 <td><code>FILE_PREDIFF</code></td>
112 <td>data are exchanged through an input and an output file</td>
115 <td><code>BUFFER_PREDIFF</code></td>
116 <td>data are exchanged through a <code>BSTR</code></td>
119 <td><code>FILE_PACK_UNPACK</code></td>
120 <td>data are exchanged through an input and an output file</td>
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>
127 <td><code>EDITOR_SCRIPT</code></td>
128 <td>data are exchanged through a <code>BSTR</code></td>
131 <p>You need to define only one API to handle an event. Define the one you prefer.</p>
133 <h3><a name="properties">Properties</a></h3>
141 <td><code>PluginEvent</code></td>
146 <td><code>PluginDescription</code></td>
151 <td><code>PluginFileFilters</code></td>
153 <td><code>PACK_UNPACK</code>, <code>PREDIFF</code></td>
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>
162 <p><code>PluginIsAutomatic</code> and <code>PluginFileFilters</code> are for automatic mode :</p>
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>
169 <h3><a name="methods">Methods</a></h3>
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>
180 <td><code>BUFFER_PREDIFF</code></td>
181 <td><code>PrediffBufferW</code></td>
184 <td><code>FILE_PREDIFF</code></td>
185 <td><code>PrediffFile</code></td>
188 <td><code>BUFFER_PACK_UNPACK</code></td>
189 <td><code>UnpackBufferA</code><br /><code>PackBufferA</code></td>
192 <td><code>FILE_PACK_UNPACK</code></td>
193 <td><code>UnpackFile</code><br /><code>PackFile</code></td>
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>
204 <h3><a name="syntax">Syntax</a></h3>
206 <h3><a name="syntax_properties">Properties syntax</a></h3>
208 <h4><code>PluginEvent</code></h4>
212 <td><code>STDMETHODIMP CWinMergeScript::get_PluginEvent(BSTR * pVal)</code></td>
216 <td><code>Public Property Get PluginEvent() As String</code></td>
220 <td><code>Function get_PluginEvent()</code></td>
224 <h4><code>PluginDescription</code></h4>
228 <td><code>STDMETHODIMP CWinMergeScript::get_PluginDescription(BSTR * pVal)</code></td>
232 <td><code>Public Property Get PluginDescription() As String</code></td>
236 <td><code>Function get_PluginDescription()</code></td>
240 <h4><code>PluginFileFilters</code></h4>
241 <p>String formed of fileFilters, separated with "<code>;</code>"</p>
245 <td><code>STDMETHODIMP CWinMergeScript::get_PluginFileFilters(BSTR * pVal)</code></td>
249 <td><code>Public Property Get PluginFileFilters() As String</code></td>
253 <h4><code>PluginIsAutomatic</code></h4>
257 <td><code>STDMETHODIMP CWinMergeScript::get_PluginIsAutomatic(VARIANT_BOOL * pVal)</code></td>
261 <td><code>Public Property Get PluginIsAutomatic() As Boolean</code></td>
265 <h3><a name="syntax_methods">Methods syntax</a></h3>
267 <h4><code>EDITOR_SCRIPT</code></h4>
271 <th>Functions parameters (function names are free)</th>
275 <td><code>STDMETHOD(MakeUpperVB)([in] BSTR inputText, [out, retval] BSTR * outputText);</code></td>
279 <td><code>Public Function MakeUpperVB(text As String)</code></td>
283 <td><code>Function MakeUpperVBS(Text)</code></td>
287 <h4><code>FILE_PREDIFF</code></h4>
291 <th>Functions names</th>
292 <th>Functions parameters</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>
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>
306 <h4><code>BUFFER_PREDIFF</code></h4>
310 <th>Functions names</th>
311 <th>Functions parameters</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>
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>
325 <h4><code>FILE_PACK_UNPACK</code></h4>
329 <th>Functions names</th>
330 <th>Functions parameters</th>
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>
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>
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>
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>
352 <h4><code>BUFFER_PACK_UNPACK</code></h4>
356 <th>Functions names</th>
357 <th>Functions parameters</th>
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>
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>
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>
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>
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><implement></code>. See examples.<br />
382 But they are difficult to debug. And valid only for <code>EDITOR_SCRIPT</code> events.</p>
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>
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>
395 <h4>Additional steps to write a plugin in C++</h4>
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> :
402 <li><code>SAFEARRAY *</code> <code>SAFEARRAY(unsigned char)</code></li>
403 <li><code>SAFEARRAY **</code> <code>SAFEARRAY(unsigned char) *</code></li>
408 <h3><a name="debug">How to debug VC++ plugins ?</a></h3>
409 <p>Easy with Visual Studio after you installed WinMerge source.</p>
411 <h4><code>EDITOR_SCRIPT</code> :</h4>
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>
422 <h4><code>PREDIFF</code>, <code>PACK_UNPACK</code> :</h4>
423 <p>Same steps, point #1 only differs:</p>
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>