OSDN Git Service

Plugins: Fix a crash on Window XP
[winmerge-jp/winmerge-jp.git] / Plugins / README.md
1 # WinMerge Plugins
2
3 This folders holds the WinMerge runtime plugins, source code and binaries both.
4
5 These filters are distributed in the `MergePlugins` subdirectory beneath the WinMerge executables.
6
7 ## Quick description
8
9 Plugins use an ActiveX interface. Plugins may be written in any format that supports this interface.
10
11 Examples are available in :
12
13  * C++ COM component
14  * VB ActiveX dll
15  * Scriptlets (VBS, JS)
16  * Delphi
17
18 Limitation : Scriptlets only work for `EDITOR_SCRIPT` plugins.
19
20 **Properties** are used to present information concerning the plugin.  
21 **Methods** are used to process the data. Method names and syntax depends on events and **API** (see below).
22
23 ## Events
24
25 ### `EDITOR_SCRIPT`
26
27 In editor view, apply a function to the current selection.
28
29 ### `PREDIFF`
30
31 Preprocess file before diffing : the plugin is not apply to the text displayed in the editor.
32 It is applied only to a copy of the left and right texts, and this copy are then scanned to create the difference list.
33 As now:
34
35  * you may delete one column, change the names of variables...
36  * you may not add/delete/move lines.
37
38 ### `PACK_UNPACK`
39
40 Transform a file in a viewable format (for example, decompress a file...)
41
42  * The editor displays the unpacked data.
43  * Sometimes files may be packed again (zipped files...). An additional function is of course necessary.
44  * If the author of the plugin created this function, file may be saved again in the compressed format.
45  * 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.
46
47 ## API
48
49 Some events have two API. One to exchange the data through a `BSTR` (memory) and one through input/ouput files.
50
51 | Event                | Data exchange                                                                                            |
52 |:---------------------|:---------------------------------------------------------------------------------------------------------|
53 | `FILE_PREDIFF`       | data are exchanged through an input and an output file                                                   |
54 | `BUFFER_PREDIFF`     | data are exchanged through a `BSTR`                                                                      |
55 | `FILE_PACK_UNPACK`   | data are exchanged through an input and an output file                                                   |
56 | `BUFFER_PACK_UNPACK` | data are exchanged through a `SafeArray` (`BSTR` not available as the packed data are possibly not text) |
57 | `EDITOR_SCRIPT`      | data are exchanged through a `BSTR`                                                                      |
58
59 You need to define only one API to handle an event. Define the one you prefer.
60
61 ## Properties
62
63 | Name                | Mandatory                         | Events                   |
64 |:--------------------|:----------------------------------|:-------------------------|
65 | `PluginEvent`       | yes                               | all                      |
66 | `PluginDescription` | no                                | all                      |
67 | `PluginFileFilters` | no                                | `PACK_UNPACK`, `PREDIFF` |
68 | `PluginIsAutomatic` | if `PluginFileFilters` is defined | `PACK_UNPACK`, `PREDIFF` |
69
70 `PluginIsAutomatic` and `PluginFileFilters` are for automatic mode :
71
72  * When `PluginIsAutomatic` is `false`, the plugin is never used in automatic mode.
73  * When `PluginIsAutomatic` is `true`, `PluginFileFilters` is compared to the filename of both files. If one file matches the filter, the plugin is applied.
74
75 ## Methods
76
77 | API                  | Method name                                                                                    |
78 |:---------------------|:-----------------------------------------------------------------------------------------------|
79 | `EDITOR_SCRIPT`      | function name is free **Note**: several functions may be defined in one `EDITOR_SCRIPT` plugin |
80 | `BUFFER_PREDIFF`     | `PrediffBufferW`                                                                               |
81 | `FILE_PREDIFF`       | `PrediffFile`                                                                                  |
82 | `BUFFER_PACK_UNPACK` | `UnpackBufferA`, `PackBufferA`                                                                 |
83 | `FILE_PACK_UNPACK`   | `UnpackFile`, `PackFile`                                                                       |
84
85 **Note**: `PACK_UNPACK` functions use an additional parameter. The value may be set during `UnpackBuffer`.  
86 When file is changed, the value is forwarded to `PackBuffer`. The goal is to pass a parameter from `UnpackBuffer` to `PackBuffer`.  
87
88 For example, the plugin may handle several compressed formats, and use this value to recompress a file in the format of the original.  
89 This parameter is mandatory for the function's syntax. But you don't have to set its value when you don't use it.
90
91 ## Syntax
92
93 ### Properties syntax
94
95 #### `PluginEvent`
96
97 | Language | Syntax                                                       |
98 |:--------:|:-------------------------------------------------------------|
99 | C++      | `STDMETHODIMP CWinMergeScript::get_PluginEvent(BSTR * pVal)` |
100 | VB       | `Public Property Get PluginEvent() As String`                |
101 | VBS      | `Function get_PluginEvent()`                                 |
102
103 #### `PluginDescription`
104
105 | Language | Syntax                                                             |
106 |:--------:|:-------------------------------------------------------------------|
107 | C++      | `STDMETHODIMP CWinMergeScript::get_PluginDescription(BSTR * pVal)` |
108 | VB       | `Public Property Get PluginDescription() As String`                |
109 | VBS      | `Function get_PluginDescription()`                                 |
110
111 #### `PluginFileFilters`
112
113 String formed of fileFilters, separated with `;`
114
115 | Language | Syntax                                                             |
116 |:--------:|:-------------------------------------------------------------------|
117 | C++      | `STDMETHODIMP CWinMergeScript::get_PluginFileFilters(BSTR * pVal)` |
118 | VB       | `Public Property Get PluginFileFilters() As String`                |
119
120 #### `PluginIsAutomatic`
121
122 | Language | Syntax                                                                     |
123 |:--------:|:---------------------------------------------------------------------------|
124 | C++      | `STDMETHODIMP CWinMergeScript::get_PluginIsAutomatic(VARIANT_BOOL * pVal)` |
125 | VB       | `Public Property Get PluginIsAutomatic() As Boolean`                       |
126
127 ### Methods syntax
128
129 #### `EDITOR_SCRIPT`
130
131 | Language | Functions parameters (function names are free)                                  |
132 |:--------:|:--------------------------------------------------------------------------------|
133 | C++      | `STDMETHOD(MakeUpperVB)([in] BSTR inputText, [out, retval] BSTR * outputText);` |
134 | VB       | `Public Function MakeUpperVB(text As String)`                                   |
135 | VBS      | `Function MakeUpperVBS(Text)`                                                   |
136
137 #### `FILE_PREDIFF`
138
139 | Language | Functions names               | Functions parameters                                                                                                       |
140 |:--------:|:------------------------------|:---------------------------------------------------------------------------------------------------------------------------|
141 | VC++     | `STDMETHOD(PrediffFile)`      | `([in] BSTR fileSrc, [in] BSTR fileDst, VARIANT_BOOL * pbChanged, INT * pSubcode, [out, retval] VARIANT_BOOL * pbSuccess)` |
142 | VB       | `Public Function PrediffFile` | `(BSTR fileSrc, BSTR fileDst, ByRef bChanged As Boolean, ByRef subcode As Long) As Boolean`                                |
143
144 #### `BUFFER_PREDIFF`
145
146 | Language | Functions names                  | Functions parameters                                                                                            |
147 |:--------:|:---------------------------------|:----------------------------------------------------------------------------------------------------------------|
148 | C++      | `STDMETHOD(PrediffBufferW)`      | `([in] BSTR * pText, [in] INT * pSize, [in] VARIANT_BOOL * pbChanged, [out, retval] VARIANT_BOOL * pbHandled);` |
149 | VB       | `Public Function PrediffBufferW` | `(ByRef text As String, ByRef size As Long, ByRef bChanged As Boolean) As Boolean`                              |
150
151 #### `FILE_PACK_UNPACK`
152
153 | Language | Functions names              | Functions parameters                                                                                                       |
154 |:--------:|:-----------------------------|:---------------------------------------------------------------------------------------------------------------------------|
155 | VC++     | `STDMETHOD(UnpackFile)`      | `([in] BSTR fileSrc, [in] BSTR fileDst, VARIANT_BOOL * pbChanged, INT * pSubcode, [out, retval] VARIANT_BOOL * pbSuccess)` |
156 | VC++     | `STDMETHOD(PackFile)`        | `([in] BSTR fileSrc, [in] BSTR fileDst, VARIANT_BOOL * pbChanged, INT pSubcode, [out, retval] VARIANT_BOOL * pbSuccess)`   |
157 | VB       | `Public Function UnpackFile` | `(BSTR fileSrc, BSTR fileDst, ByRef bChanged As Boolean, ByRef subcode As Long) As Boolean`                                |
158 | VB       | `Public Function PackFile`   | `(BSTR fileSrc, BSTR fileDst, ByRef bChanged As Boolean, subcode As Long) As Boolean`                                      |
159
160 #### `BUFFER_PACK_UNPACK`
161
162 | Language | Functions names                 | Functions parameters                                                                                                                        |
163 |:--------:|:--------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------|
164 | VC++     | `STDMETHOD(UnpackBufferA)`      | `([in] SAFEARRAY ** pBuffer, [in] INT * pSize, [in] VARIANT_BOOL * pbChanged, [in] INT * pSubcode, [out, retval] VARIANT_BOOL * pbSuccess)` |
165 | VC++     | `STDMETHOD(PackBufferA)`        | `([in] SAFEARRAY ** pBuffer, [in] INT * pSize, [in] VARIANT_BOOL * pbChanged, [in] INT subcode, [out, retval] VARIANT_BOOL * pbSuccess)`    |
166 | VB       | `Public Function UnpackBufferA` | `(ByRef buffer() As Byte, ByRef size As Long, ByRef bChanged As Boolean, ByRef subcode As Long) As Boolean`                                 |
167 | VB       | `Public Function PackBufferA`   | `(ByRef buffer() As Byte, ByRef size As Long, ByRef bChanged As Boolean, subcode As Long) As Boolean`                                       |
168
169 ## How to write plugins quickly ?
170
171 Easiest plugins are scriptlets.
172
173 Just VBscript (or JavaScript probably) with an additional section `<implement>`. See examples.  
174 But they are difficult to debug. And valid only for `EDITOR_SCRIPT` events.
175
176 ### VC++ plugins
177
178 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.
179
180 But easy to write from an existing plugin.
181
182  1. Select a C++ plugin with the same API
183  2. Rename the files `cpp,def,dsp,idl,rc` : replace \[_name of old plugin_\] with \[_name of your plugin_\]
184  3. In all the files, replace all instances of \[_name of old plugin_\] with \[_name of your plugin_\]
185  4. Write your custom code : `WinMergeScript.cpp` holds all the important functions.
186  5. Generate new GUIDs and add to the `.idl` file.
187
188 ### Additional steps to write a plugin in C++
189
190  * do not register the dll : delete everything in 'settings'->'custom build'
191  * do not register the dll : delete the file `.rgs`, and the registry section in the file `.rc`
192  * do not register the dll : add `typeinfoex.h` + and make 3 changes in `WinMergeScript.h` (see commented lines)
193  * `SAFEARRAY` : replace the interface in `.idl` :
194    * `SAFEARRAY *` `SAFEARRAY(unsigned char)`
195    * `SAFEARRAY **` `SAFEARRAY(unsigned char) *`
196
197 ## How to debug VC++ plugins ?
198
199 Easy with Visual Studio after you installed WinMerge source.
200
201 ### `EDITOR_SCRIPT`
202
203  1. Set a breakpoint at the beginning of `safeInvokeA` in `Plugins.cpp`.
204  2. Run WinMerge
205  3. Do all you need (open file, menu...) to call the plugin.
206  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.
207  5. Set a breakpoint in this file at the beginning of your function.
208  6. `F5`. The breakpoint in your function is triggered.
209
210 ### `PREDIFF`, `PACK_UNPACK`
211
212 Same steps, point #1 only differs:
213
214  1. Set a breakpoint at the beginning of `safeInvokeW` in `Plugins.cpp`.  
215     
216     **Note**: `safeInvokeW` instead of `safeInvokeA`.