This folders holds the WinMerge runtime plugins, source code and binaries both.
These filters are distributed in the MergePlugins
subdirectory beneath the WinMerge executables.
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 (VBScript, JScript)
- 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).
In editor view, apply a function to the current selection.
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.
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.
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.
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
isfalse
, the plugin is never used in automatic mode. - When
PluginIsAutomatic
istrue
,PluginFileFilters
is compared to the filename of both files. If one file matches the filter, the plugin is applied.
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.
Language | Syntax |
---|---|
C++ | STDMETHODIMP CWinMergeScript::get_PluginEvent(BSTR * pVal) |
VB | Public Property Get PluginEvent() As String |
VBScript | Function get_PluginEvent() |
JScript | function get_PluginEvent() |
Language | Syntax |
---|---|
C++ | STDMETHODIMP CWinMergeScript::get_PluginDescription(BSTR * pVal) |
VB | Public Property Get PluginDescription() As String |
VBScript | `Function get_PluginDescription() |
JScript | function get_PluginDescription() |
String formed of fileFilters, separated with ;
Language | Syntax |
---|---|
C++ | STDMETHODIMP CWinMergeScript::get_PluginFileFilters(BSTR * pVal) |
VB | Public Property Get PluginFileFilters() As String |
VBScript | `Function get_PluginFileFilters() |
JScript | function get_PluginFileFilters() |
Language | Syntax |
---|---|
C++ | STDMETHODIMP CWinMergeScript::get_PluginIsAutomatic(VARIANT_BOOL * pVal) |
VB | Public Property Get PluginIsAutomatic() As Boolean |
VBScript | Function get_PluginIsAutomatic() |
JScript | function get_PluginIsAutomatic() |
Language | Functions parameters (function names are free) |
---|---|
C++ | STDMETHOD(MakeUpper)([in] BSTR inputText, [out, retval] BSTR * outputText); |
VB | Public Function MakeUpper(text As String) |
VBScript | Function MakeUpper(Text) |
JScript | function MakeUpper(Text) |
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 |
VBScript | Function PrediffFile |
(fileSrc, fileDst, bChanged, subcode) |
JScript | function PrediffFile |
(fileSrc, fileDst, bChanged, subcode) { ...; var r = new ActiveXObject("Scripting.Dictionary"); r.Add(0, retval); r.Add(1, bChanged); r.Add(2, subcode); return r.Items(); } |
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 |
VBScript | Function PrediffBufferW |
(text, size, bChanged) |
JScript | function PrediffBufferW |
(text, size, bChanged) { ...; var r = new ActiveXObject("Scripting.Dictionary"); r.Add(0, retval); r.Add(1, text); r.Add(2, size); r.Add(3, bChanged); return r.Items(); } |
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 |
VBScript | Function UnpackFile |
(fileSrc, fileDst, bChanged, subcode) |
VBScript | Function PackFile |
(fileSrc, fileDst, bChanged, subcode) |
JScript | function UnpackFile |
(fileSrc, fileDst, bChanged, subcode) { ...; var r = new ActiveXObject("Scripting.Dictionary"); r.Add(0, retval); r.Add(1, bChanged); r.Add(2, subcode); return r.Items(); } |
JScript | function PackFile |
(fileSrc, fileDst, bChanged, subcode) { ...; var r = new ActiveXObject("Scripting.Dictionary"); r.Add(0, retval); r.Add(1, bChanged); return r.Items(); } |
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 |
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.
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.
- Select a C++ plugin with the same API
- Rename the files
cpp,def,dsp,idl,rc
: replace [name of old plugin] with [name of your plugin] - In all the files, replace all instances of [name of old plugin] with [name of your plugin]
- Write your custom code :
WinMergeScript.cpp
holds all the important functions. - Generate new GUIDs and add to the
.idl
file.
- 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 inWinMergeScript.h
(see commented lines) SAFEARRAY
: replace the interface in.idl
:SAFEARRAY *
SAFEARRAY(unsigned char)
SAFEARRAY **
SAFEARRAY(unsigned char) *
Easy with Visual Studio after you installed WinMerge source.
- Set a breakpoint at the beginning of
safeInvokeA
inPlugins.cpp
. - Run WinMerge
- Do all you need (open file, menu...) to call the plugin.
- 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. - Set a breakpoint in this file at the beginning of your function.
F5
. The breakpoint in your function is triggered.
Same steps, point #1 only differs:
-
Set a breakpoint at the beginning of
safeInvokeW
inPlugins.cpp
.Note:
safeInvokeW
instead ofsafeInvokeA
.