+++ /dev/null
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
- <title>Plugins</title>
- <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
- <style type="text/css">
- <!--
- body {
- font-family: Verdana,Helvetica,Arial,sans-serif;
- font-size: small;
- }
- code,pre {
- font-family: "Courier New",Courier,monospace;
- font-size: 1em;
- }
- h3 {
- padding: 2px;
- border-left: 4px solid #FFCC00;
- border-bottom: 1px solid #FFCC00;
- }
- h4 {
- padding: 2px;
- border-left: 8px solid #FF9933;
- border-bottom: 1px solid #FF9933;
- }
- table {
- border-collapse: collapse;
- border: 1px solid black;
- }
- th {
- text-align: left;
- padding: 3px;
- background-color: #EEEEEE;
- border: 1px solid black;
- }
- td {
- padding: 3px;
- border: 1px solid black;
- }
- dt {
- font-weight: bold;
- }
- -->
- </style>
-</head>
-<body>
-<h2>Plugins</h2>
-
-<h3>Table of Contents</h3>
-<ul>
- <li><a href="#description">Quick description</a></li>
- <li><a href="#events">Events</a></li>
- <li><a href="#api">API</a></li>
- <li><a href="#properties">Properties</a></li>
- <li><a href="#methods">Methods</a></li>
- <li><a href="#syntax">Syntax</a>
- <ul>
- <li><a href="#syntax_properties">Properties syntax</a></li>
- <li><a href="#syntax_methods">Methods syntax</a></li>
- </ul>
- </li>
- <li><a href="#write">How to write plugins quickly ?</a></li>
- <li><a href="#debug">How to debug VC++ plugins ?</a></li>
-</ul>
-
-<h3><a name="description">Quick description</a></h3>
-<p>Plugins use an ActiveX interface. Plugins may be written in any format that supports this interface.</p>
-<p>Examples are available in :</p>
-<ul>
- <li>C++ COM component</li>
- <li>VB ActiveX dll</li>
- <li>Scriptlets (VBS, JS)</li>
- <li>Delphi</li>
-</ul>
-<p>Limitation : Scriptlets only work for <code>EDITOR_SCRIPT</code> plugins.</p>
-<p><a href="#properties">Properties</a> are used to present information concerning the plugin.<br />
-<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>
-
-<h3><a name="events">Events</a></h3>
-<dl>
- <dt><code>EDITOR_SCRIPT</code></dt>
- <dd><p>In editor view, apply a function to the current selection.</p></dd>
-
- <dt><code>PREDIFF</code></dt>
- <dd>
- <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>
- <ul>
- <li>you may delete one column, change the names of variables...</li>
- <li>you may not add/delete/move lines.</li>
- </ul>
- </dd>
-
- <dt><code>PACK_UNPACK</code></dt>
- <dd>
- <p>Transform a file in a viewable format (for example, decompress a file...)</p>
- <ul>
- <li>The editor displays the unpacked data.</li>
- <li>Sometimes files may be packed again (zipped files...). An additional function is of course necessary.</li>
- <li>If the author of the plugin created this function, file may be saved again in the compressed format.</li>
- <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>
- </ul>
- </dd>
-</dl>
-
-<h3><a name="api">API</a></h3>
-<p>Some events have two API. One to exchange the data through a <code>BSTR</code> (memory) and one through input/ouput files.</p>
-
-<table border="1">
- <tr>
- <td><code>FILE_PREDIFF</code></td>
- <td>data are exchanged through an input and an output file</td>
- </tr>
- <tr>
- <td><code>BUFFER_PREDIFF</code></td>
- <td>data are exchanged through a <code>BSTR</code></td>
- </tr>
- <tr>
- <td><code>FILE_PACK_UNPACK</code></td>
- <td>data are exchanged through an input and an output file</td>
- </tr>
- <tr>
- <td><code>BUFFER_PACK_UNPACK</code></td>
- <td>data are exchanged through a <code>SafeArray</code> (<code>BSTR</code> not available as the packed data are possibly not text)</td>
- </tr>
- <tr>
- <td><code>EDITOR_SCRIPT</code></td>
- <td>data are exchanged through a <code>BSTR</code></td>
- </tr>
-</table>
-<p>You need to define only one API to handle an event. Define the one you prefer.</p>
-
-<h3><a name="properties">Properties</a></h3>
-<table border="1">
- <tr>
- <th>Name</th>
- <th>Mandatory</th>
- <th>Events</th>
- </tr>
- <tr>
- <td><code>PluginEvent</code></td>
- <td>yes</td>
- <td>all</td>
- </tr>
- <tr>
- <td><code>PluginDescription</code></td>
- <td>no</td>
- <td>all</td>
- </tr>
- <tr>
- <td><code>PluginFileFilters</code></td>
- <td>no</td>
- <td><code>PACK_UNPACK</code>, <code>PREDIFF</code></td>
- </tr>
- <tr>
- <td><code>PluginIsAutomatic</code></td>
- <td>if <code>PluginFileFilters</code> is defined</td>
- <td><code>PACK_UNPACK</code>, <code>PREDIFF</code></td>
- </tr>
-</table>
-
-<p><code>PluginIsAutomatic</code> and <code>PluginFileFilters</code> are for automatic mode :</p>
-<ul>
- <li>When <code>PluginIsAutomatic</code> is <code>false</code>, the plugin is never used in automatic mode.</li>
- <li>When <code>PluginIsAutomatic</code> is <code>true</code>, <code>PluginFileFilters</code> is compared to the filename of both files. If one file
- matches the filter, the plugin is applied.</li>
-</ul>
-
-<h3><a name="methods">Methods</a></h3>
-<table border="1">
- <tr>
- <th>API</th>
- <th>Method name</th>
- </tr>
- <tr>
- <td><code>EDITOR_SCRIPT</code></td>
- <td>function name is free<br /><br /><b>Note</b> : several functions may be defined in one <code>EDITOR_SCRIPT</code> plugin</td>
- </tr>
- <tr>
- <td><code>BUFFER_PREDIFF</code></td>
- <td><code>PrediffBufferW</code></td>
- </tr>
- <tr>
- <td><code>FILE_PREDIFF</code></td>
- <td><code>PrediffFile</code></td>
- </tr>
- <tr>
- <td><code>BUFFER_PACK_UNPACK</code></td>
- <td><code>UnpackBufferA</code><br /><code>PackBufferA</code></td>
- </tr>
- <tr>
- <td><code>FILE_PACK_UNPACK</code></td>
- <td><code>UnpackFile</code><br /><code>PackFile</code></td>
- </tr>
-</table>
-
-<p><b>Note</b> : <code>PACK_UNPACK</code> functions use an additional parameter. The value may be set during <code>UnpackBuffer</code>.
-When file is changed, the value is forwarded to <code>PackBuffer</code>.
-The goal is to pass a parameter from <code>UnpackBuffer</code> to <code>PackBuffer</code>.<br />
-For example, the plugin may handle several compressed formats, and use this value to recompress a file in
-the format of the original.
-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>
-
-<h3><a name="syntax">Syntax</a></h3>
-
-<h3><a name="syntax_properties">Properties syntax</a></h3>
-
-<h4><code>PluginEvent</code></h4>
-<table border="1">
- <tr>
- <th>C++</th>
- <td><code>STDMETHODIMP CWinMergeScript::get_PluginEvent(BSTR * pVal)</code></td>
- </tr>
- <tr>
- <th>VB</th>
- <td><code>Public Property Get PluginEvent() As String</code></td>
- </tr>
- <tr>
- <th>VBS</th>
- <td><code>Function get_PluginEvent()</code></td>
- </tr>
-</table>
-
-<h4><code>PluginDescription</code></h4>
-<table border="1">
- <tr>
- <th>C++</th>
- <td><code>STDMETHODIMP CWinMergeScript::get_PluginDescription(BSTR * pVal)</code></td>
- </tr>
- <tr>
- <th>VB</th>
- <td><code>Public Property Get PluginDescription() As String</code></td>
- </tr>
- <tr>
- <th>VBS</th>
- <td><code>Function get_PluginDescription()</code></td>
- </tr>
-</table>
-
-<h4><code>PluginFileFilters</code></h4>
-<p>String formed of fileFilters, separated with "<code>;</code>"</p>
-<table border="1">
- <tr>
- <th>C++</th>
- <td><code>STDMETHODIMP CWinMergeScript::get_PluginFileFilters(BSTR * pVal)</code></td>
- </tr>
- <tr>
- <th>VB</th>
- <td><code>Public Property Get PluginFileFilters() As String</code></td>
- </tr>
-</table>
-
-<h4><code>PluginIsAutomatic</code></h4>
-<table border="1">
- <tr>
- <th>C++</th>
- <td><code>STDMETHODIMP CWinMergeScript::get_PluginIsAutomatic(VARIANT_BOOL * pVal)</code></td>
- </tr>
- <tr>
- <th>VB</th>
- <td><code>Public Property Get PluginIsAutomatic() As Boolean</code></td>
- </tr>
-</table>
-
-<h3><a name="syntax_methods">Methods syntax</a></h3>
-
-<h4><code>EDITOR_SCRIPT</code></h4>
-<table border="1">
- <tr>
- <th></th>
- <th>Functions parameters (function names are free)</th>
- </tr>
- <tr>
- <th>C++</th>
- <td><code>STDMETHOD(MakeUpperVB)([in] BSTR inputText, [out, retval] BSTR * outputText);</code></td>
- </tr>
- <tr>
- <th>VB</th>
- <td><code>Public Function MakeUpperVB(text As String)</code></td>
- </tr>
- <tr>
- <th>VBS</th>
- <td><code>Function MakeUpperVBS(Text)</code></td>
- </tr>
-</table>
-
-<h4><code>FILE_PREDIFF</code></h4>
-<table border="1">
- <tr>
- <th></th>
- <th>Functions names</th>
- <th>Functions parameters</th>
- </tr>
- <tr>
- <th>VC++</th>
- <td><code>STDMETHOD(PrediffFile)</code></td>
- <td><code>([in] BSTR fileSrc, [in] BSTR fileDst, VARIANT_BOOL * pbChanged, INT * pSubcode, [out, retval] VARIANT_BOOL * pbSuccess)</code></td>
- </tr>
- <tr>
- <th>VB</th>
- <td><code>Public Function PrediffFile</code></td>
- <td><code>(BSTR fileSrc, BSTR fileDst, ByRef bChanged As Boolean, ByRef subcode As Long) As Boolean</code></td>
- </tr>
-</table>
-
-<h4><code>BUFFER_PREDIFF</code></h4>
-<table border="1">
- <tr>
- <th></th>
- <th>Functions names</th>
- <th>Functions parameters</th>
- </tr>
- <tr>
- <th>C++</th>
- <td><code>STDMETHOD(PrediffBufferW)</code></td>
- <td><code>([in] BSTR * pText, [in] INT * pSize, [in] VARIANT_BOOL * pbChanged, [out, retval] VARIANT_BOOL * pbHandled);</code></td>
- </tr>
- <tr>
- <th>VB</th>
- <td><code>Public Function PrediffBufferW</code></td>
- <td><code>(ByRef text As String, ByRef size As Long, ByRef bChanged As Boolean) As Boolean</code></td>
- </tr>
-</table>
-
-<h4><code>FILE_PACK_UNPACK</code></h4>
-<table border="1">
- <tr>
- <th></th>
- <th>Functions names</th>
- <th>Functions parameters</th>
- </tr>
- <tr>
- <th rowspan="2">VC++</th>
- <td><code>STDMETHOD(UnpackFile)</code></td>
- <td><code>([in] BSTR fileSrc, [in] BSTR fileDst, VARIANT_BOOL * pbChanged, INT * pSubcode, [out, retval] VARIANT_BOOL * pbSuccess)</code></td>
- </tr>
- <tr>
- <td><code>STDMETHOD(PackFile)</code></td>
- <td><code>([in] BSTR fileSrc, [in] BSTR fileDst, VARIANT_BOOL * pbChanged, INT pSubcode, [out, retval] VARIANT_BOOL * pbSuccess)</code></td>
- </tr>
- <tr>
- <th rowspan="2">VB</th>
- <td><code>Public Function UnpackFile</code></td>
- <td><code>(BSTR fileSrc, BSTR fileDst, ByRef bChanged As Boolean, ByRef subcode As Long) As Boolean</code></td>
- </tr>
- <tr>
- <td><code>Public Function PackFile</code></td>
- <td><code>(BSTR fileSrc, BSTR fileDst, ByRef bChanged As Boolean, subcode As Long) As Boolean</code></td>
- </tr>
-</table>
-
-<h4><code>BUFFER_PACK_UNPACK</code></h4>
-<table border="1">
- <tr>
- <th></th>
- <th>Functions names</th>
- <th>Functions parameters</th>
- </tr>
- <tr>
- <th rowspan="2">VC++</th>
- <td><code>STDMETHOD(UnpackBufferA)</code></td>
- <td><code>([in] SAFEARRAY ** pBuffer, [in] INT * pSize, [in] VARIANT_BOOL * pbChanged, [in] INT * pSubcode, [out, retval] VARIANT_BOOL * pbSuccess)</code></td>
- </tr>
- <tr>
- <td><code>STDMETHOD(PackBufferA)</code></td>
- <td><code>([in] SAFEARRAY ** pBuffer, [in] INT * pSize, [in] VARIANT_BOOL * pbChanged, [in] INT subcode, [out, retval] VARIANT_BOOL * pbSuccess)</code></td>
- </tr>
- <tr>
- <th rowspan="2">VB</th>
- <td><code>Public Function UnpackBufferA</code></td>
- <td><code>(ByRef buffer() As Byte, ByRef size As Long, ByRef bChanged As Boolean, ByRef subcode As Long) As Boolean</code></td>
- </tr>
- <tr>
- <td><code>Public Function PackBufferA</code></td>
- <td><code>(ByRef buffer() As Byte, ByRef size As Long, ByRef bChanged As Boolean, subcode As Long) As Boolean</code></td>
- </tr>
-</table>
-
-<h3><a name="write">How to write plugins quickly ?</a></h3>
-<p>Easiest plugins are scriptlets.</p>
-<p>Just VBscript (or JavaScript probably) with an additional section <code><implement></code>. See examples.<br />
-But they are difficult to debug. And valid only for <code>EDITOR_SCRIPT</code> events.</p>
-
-<h4>VC++ plugins :</h4>
-<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>
-<p>But easy to write from an existing plugin.</p>
-<ol>
- <li>Select a C++ plugin with the same API</li>
- <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>
- <li>In all the files, replace all instances of [<em>name of old plugin</em>] with [<em>name of your plugin</em>]</li>
- <li>Write your custom code : <code>WinMergeScript.cpp</code> holds all the important functions.</li>
- <li>Generate new GUIDs and add to the <code>.idl</code> file.</li>
-</ol>
-
-<h4>Additional steps to write a plugin in C++</h4>
-<ul>
- <li>do not register the dll : delete everything in 'settings'->'custom build'</li>
- <li>do not register the dll : delete the file <code>.rgs</code>, and the registry section in the file <code>.rc</code></li>
- <li>do not register the dll : add <code>typeinfoex.h</code> + and make 3 changes in <code>WinMergeScript.h</code> (see commented lines)</li>
- <li><code>SAFEARRAY</code> : replace the interface in <code>.idl</code> :
- <ul>
- <li><code>SAFEARRAY *</code> <code>SAFEARRAY(unsigned char)</code></li>
- <li><code>SAFEARRAY **</code> <code>SAFEARRAY(unsigned char) *</code></li>
- </ul>
- </li>
-</ul>
-
-<h3><a name="debug">How to debug VC++ plugins ?</a></h3>
-<p>Easy with Visual Studio after you installed WinMerge source.</p>
-
-<h4><code>EDITOR_SCRIPT</code> :</h4>
-<ol>
- <li>Set a breakpoint at the beginning of <code>safeInvokeA</code> in <code>Plugins.cpp</code>.</li>
- <li>Run WinMerge</li>
- <li>Do all you need (open file, menu...) to call the plugin.</li>
- <li>The breakpoint is triggered. The plugin interface is loaded at this moment.
- Open the file <code>WinMergeScript.cpp</code> source of your plugin in the debugging session.</li>
- <li>Set a breakpoint in this file at the beginning of your function.</li>
- <li><code>F5</code>. The breakpoint in your function is triggered.</li>
-</ol>
-
-<h4><code>PREDIFF</code>, <code>PACK_UNPACK</code> :</h4>
-<p>Same steps, point #1 only differs:</p>
-<ol>
- <li>Set a breakpoint at the beginning of <code>safeInvokeW</code> in <code>Plugins.cpp</code>.<br /><br />
- <b>Note</b> : <code>safeInvokeW</code> instead of <code>safeInvokeA</code>.</li>
-</ol>
-</body>
-</html>
\ No newline at end of file
# WinMerge Plugins
-Plugins holds the WinMerge runtime plugins, source code and binaries both.
+This folders holds the WinMerge runtime plugins, source code and binaries both.
-These plugins allow transformations to files before diffing, or during
-editing. See the manual for more information.
+These filters are distributed in the `MergePlugins` subdirectory beneath the WinMerge executables.
-These filters are distributed in the MergePlugins
-subdirectory beneath the WinMerge executables.
+## Quick description
+
+Plugins use an ActiveX interface. Plugins may be written in any format that supports this interface.
+
+Examples are available in :
+
+ * C++ COM component
+ * VB ActiveX dll
+ * Scriptlets (VBS, JS)
+ * Delphi
+
+Limitation : Scriptlets only work for `EDITOR_SCRIPT` plugins.
+
+**Properties** are used to present information concerning the plugin.
+**Methods** are used to process the data. Method names and syntax depends on events and **API** (see below).
+
+## Events
+
+### `EDITOR_SCRIPT`
+
+In editor view, apply a function to the current selection.
+
+### `PREDIFF`
+
+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:
+
+ * you may delete one column, change the names of variables...
+ * you may not add/delete/move lines.
+
+### `PACK_UNPACK`
+
+Transform a file in a viewable format (for example, decompress a file...)
+
+ * The editor displays the unpacked data.
+ * Sometimes files may be packed again (zipped files...). An additional function is of course necessary.
+ * If the author of the plugin created this function, file may be saved again in the compressed format.
+ * 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.
+
+## API
+
+Some events have two API. One to exchange the data through a `BSTR` (memory) and one through input/ouput files.
+
+| Event | Data exchange |
+|:---------------------|:---------------------------------------------------------------------------------------------------------|
+| `FILE_PREDIFF` | data are exchanged through an input and an output file |
+| `BUFFER_PREDIFF` | data are exchanged through a `BSTR` |
+| `FILE_PACK_UNPACK` | data are exchanged through an input and an output file |
+| `BUFFER_PACK_UNPACK` | data are exchanged through a `SafeArray` (`BSTR` not available as the packed data are possibly not text) |
+| `EDITOR_SCRIPT` | data are exchanged through a `BSTR` |
+
+You need to define only one API to handle an event. Define the one you prefer.
+
+## Properties
+
+| Name | Mandatory | Events |
+|:--------------------|:----------------------------------|:-------------------------|
+| `PluginEvent` | yes | all |
+| `PluginDescription` | no | all |
+| `PluginFileFilters` | no | `PACK_UNPACK`, `PREDIFF` |
+| `PluginIsAutomatic` | if `PluginFileFilters` is defined | `PACK_UNPACK`, `PREDIFF` |
+
+`PluginIsAutomatic` and `PluginFileFilters` are for automatic mode :
+
+ * When `PluginIsAutomatic` is `false`, the plugin is never used in automatic mode.
+ * When `PluginIsAutomatic` is `true`, `PluginFileFilters` is compared to the filename of both files. If one file matches the filter, the plugin is applied.
+
+## Methods
+
+| API | Method name |
+|:---------------------|:-----------------------------------------------------------------------------------------------|
+| `EDITOR_SCRIPT` | function name is free **Note**: several functions may be defined in one `EDITOR_SCRIPT` plugin |
+| `BUFFER_PREDIFF` | `PrediffBufferW` |
+| `FILE_PREDIFF` | `PrediffFile` |
+| `BUFFER_PACK_UNPACK` | `UnpackBufferA`, `PackBufferA` |
+| `FILE_PACK_UNPACK` | `UnpackFile`, `PackFile` |
+
+**Note**: `PACK_UNPACK` functions use an additional parameter. The value may be set during `UnpackBuffer`.
+When file is changed, the value is forwarded to `PackBuffer`. The goal is to pass a parameter from `UnpackBuffer` to `PackBuffer`.
+
+For example, the plugin may handle several compressed formats, and use this value to recompress a file in the format of the original.
+This parameter is mandatory for the function's syntax. But you don't have to set its value when you don't use it.
+
+## Syntax
+
+### Properties syntax
+
+#### `PluginEvent`
+
+| Language | Syntax |
+|:--------:|:-------------------------------------------------------------|
+| C++ | `STDMETHODIMP CWinMergeScript::get_PluginEvent(BSTR * pVal)` |
+| VB | `Public Property Get PluginEvent() As String` |
+| VBS | `Function get_PluginEvent()` |
+
+#### `PluginDescription`
+
+| Language | Syntax |
+|:--------:|:-------------------------------------------------------------------|
+| C++ | `STDMETHODIMP CWinMergeScript::get_PluginDescription(BSTR * pVal)` |
+| VB | `Public Property Get PluginDescription() As String` |
+| VBS | `Function get_PluginDescription()` |
+
+#### `PluginFileFilters`
+
+String formed of fileFilters, separated with `;`
+
+| Language | Syntax |
+|:--------:|:-------------------------------------------------------------------|
+| C++ | `STDMETHODIMP CWinMergeScript::get_PluginFileFilters(BSTR * pVal)` |
+| VB | `Public Property Get PluginFileFilters() As String` |
+
+#### `PluginIsAutomatic`
+
+| Language | Syntax |
+|:--------:|:---------------------------------------------------------------------------|
+| C++ | `STDMETHODIMP CWinMergeScript::get_PluginIsAutomatic(VARIANT_BOOL * pVal)` |
+| VB | `Public Property Get PluginIsAutomatic() As Boolean` |
+
+### Methods syntax
+
+#### `EDITOR_SCRIPT`
+
+| Language | Functions parameters (function names are free) |
+|:--------:|:--------------------------------------------------------------------------------|
+| C++ | `STDMETHOD(MakeUpperVB)([in] BSTR inputText, [out, retval] BSTR * outputText);` |
+| VB | `Public Function MakeUpperVB(text As String)` |
+| VBS | `Function MakeUpperVBS(Text)` |
+
+#### `FILE_PREDIFF`
+
+| Language | Functions names | Functions parameters |
+|:--------:|:------------------------------|:---------------------------------------------------------------------------------------------------------------------------|
+| VC++ | `STDMETHOD(PrediffFile)` | `([in] BSTR fileSrc, [in] BSTR fileDst, VARIANT_BOOL * pbChanged, INT * pSubcode, [out, retval] VARIANT_BOOL * pbSuccess)` |
+| VB | `Public Function PrediffFile` | `(BSTR fileSrc, BSTR fileDst, ByRef bChanged As Boolean, ByRef subcode As Long) As Boolean` |
+
+#### `BUFFER_PREDIFF`
+
+| Language | Functions names | Functions parameters |
+|:--------:|:---------------------------------|:----------------------------------------------------------------------------------------------------------------|
+| C++ | `STDMETHOD(PrediffBufferW)` | `([in] BSTR * pText, [in] INT * pSize, [in] VARIANT_BOOL * pbChanged, [out, retval] VARIANT_BOOL * pbHandled);` |
+| VB | `Public Function PrediffBufferW` | `(ByRef text As String, ByRef size As Long, ByRef bChanged As Boolean) As Boolean` |
+
+#### `FILE_PACK_UNPACK`
+
+| Language | Functions names | Functions parameters |
+|:--------:|:-----------------------------|:---------------------------------------------------------------------------------------------------------------------------|
+| VC++ | `STDMETHOD(UnpackFile)` | `([in] BSTR fileSrc, [in] BSTR fileDst, VARIANT_BOOL * pbChanged, INT * pSubcode, [out, retval] VARIANT_BOOL * pbSuccess)` |
+| VC++ | `STDMETHOD(PackFile)` | `([in] BSTR fileSrc, [in] BSTR fileDst, VARIANT_BOOL * pbChanged, INT pSubcode, [out, retval] VARIANT_BOOL * pbSuccess)` |
+| VB | `Public Function UnpackFile` | `(BSTR fileSrc, BSTR fileDst, ByRef bChanged As Boolean, ByRef subcode As Long) As Boolean` |
+| VB | `Public Function PackFile` | `(BSTR fileSrc, BSTR fileDst, ByRef bChanged As Boolean, subcode As Long) As Boolean` |
+
+#### `BUFFER_PACK_UNPACK`
+
+| Language | Functions names | Functions parameters |
+|:--------:|:--------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------|
+| VC++ | `STDMETHOD(UnpackBufferA)` | `([in] SAFEARRAY ** pBuffer, [in] INT * pSize, [in] VARIANT_BOOL * pbChanged, [in] INT * pSubcode, [out, retval] VARIANT_BOOL * pbSuccess)` |
+| VC++ | `STDMETHOD(PackBufferA)` | `([in] SAFEARRAY ** pBuffer, [in] INT * pSize, [in] VARIANT_BOOL * pbChanged, [in] INT subcode, [out, retval] VARIANT_BOOL * pbSuccess)` |
+| VB | `Public Function UnpackBufferA` | `(ByRef buffer() As Byte, ByRef size As Long, ByRef bChanged As Boolean, ByRef subcode As Long) As Boolean` |
+| VB | `Public Function PackBufferA` | `(ByRef buffer() As Byte, ByRef size As Long, ByRef bChanged As Boolean, subcode As Long) As Boolean` |
+
+## How to write plugins quickly ?
+
+Easiest plugins are scriptlets.
+
+Just VBscript (or JavaScript probably) with an additional section `<implement>`. See examples.
+But they are difficult to debug. And valid only for `EDITOR_SCRIPT` events.
+
+### VC++ plugins
+
+The most difficult to write when you do it from scratch. See in `Plugins/syntax.txt`, there are three additional steps from normal COM dll.
+
+But easy to write from an existing plugin.
+
+ 1. Select a C++ plugin with the same API
+ 2. Rename the files `cpp,def,dsp,idl,rc` : replace \[_name of old plugin_\] with \[_name of your plugin_\]
+ 3. In all the files, replace all instances of \[_name of old plugin_\] with \[_name of your plugin_\]
+ 4. Write your custom code : `WinMergeScript.cpp` holds all the important functions.
+ 5. Generate new GUIDs and add to the `.idl` file.
+
+### Additional steps to write a plugin in C++
+
+ * do not register the dll : delete everything in 'settings'->'custom build'
+ * do not register the dll : delete the file `.rgs`, and the registry section in the file `.rc`
+ * do not register the dll : add `typeinfoex.h` + and make 3 changes in `WinMergeScript.h` (see commented lines)
+ * `SAFEARRAY` : replace the interface in `.idl` :
+ * `SAFEARRAY *` `SAFEARRAY(unsigned char)`
+ * `SAFEARRAY **` `SAFEARRAY(unsigned char) *`
+
+## How to debug VC++ plugins ?
+
+Easy with Visual Studio after you installed WinMerge source.
+
+### `EDITOR_SCRIPT`
+
+ 1. Set a breakpoint at the beginning of `safeInvokeA` in `Plugins.cpp`.
+ 2. Run WinMerge
+ 3. Do all you need (open file, menu...) to call the plugin.
+ 4. The breakpoint is triggered. The plugin interface is loaded at this moment. Open the file `WinMergeScript.cpp` source of your plugin in the debugging session.
+ 5. Set a breakpoint in this file at the beginning of your function.
+ 6. `F5`. The breakpoint in your function is triggered.
+
+### `PREDIFF`, `PACK_UNPACK`
+
+Same steps, point #1 only differs:
+
+ 1. Set a breakpoint at the beginning of `safeInvokeW` in `Plugins.cpp`.
+
+ **Note**: `safeInvokeW` instead of `safeInvokeA`.