joachim99@75
|
1 /*
|
joachim99@75
|
2 * Copyright (c) 2003-2006, Sergey Zorin. All rights reserved.
|
joachim99@75
|
3 *
|
joachim99@75
|
4 * This software is distributable under the BSD license. See the terms
|
joachim99@75
|
5 * of the BSD license in the LICENSE file provided with this software.
|
joachim99@75
|
6 *
|
joachim99@75
|
7 */
|
joachim99@75
|
8 #define _CRT_SECURE_NO_DEPRECATE
|
joachim99@75
|
9
|
joachim99@75
|
10 #include <assert.h>
|
joachim99@75
|
11 #include <stdio.h>
|
joachim99@75
|
12 #include <tchar.h>
|
joachim99@75
|
13
|
joachim99@75
|
14 #include "diff_ext.h"
|
joachim99@75
|
15 #include <map>
|
joachim99@75
|
16 #include <vector>
|
joachim99@75
|
17
|
joachim99@75
|
18
|
joachim99@75
|
19 #ifdef UNICODE
|
joachim99@75
|
20
|
joachim99@75
|
21 static void parseString( const std::wstring& s, size_t& i /*pos*/, std::wstring& r /*result*/ )
|
joachim99@75
|
22 {
|
joachim99@75
|
23 size_t size = s.size();
|
joachim99@75
|
24 ++i; // Skip initial '"'
|
joachim99@75
|
25 for( ; i<size; ++i )
|
joachim99@75
|
26 {
|
joachim99@75
|
27 if ( s[i]=='"' )
|
joachim99@75
|
28 {
|
joachim99@75
|
29 ++i;
|
joachim99@75
|
30 break;
|
joachim99@75
|
31 }
|
joachim99@75
|
32 else if ( s[i]==L'\\' && i+1<size )
|
joachim99@75
|
33 {
|
joachim99@75
|
34 ++i;
|
joachim99@75
|
35 switch( s[i] ) {
|
joachim99@75
|
36 case L'n': r+=L'\n'; break;
|
joachim99@75
|
37 case L'r': r+=L'\r'; break;
|
joachim99@75
|
38 case L'\\': r+=L'\\'; break;
|
joachim99@75
|
39 case L'"': r+=L'"'; break;
|
joachim99@75
|
40 case L't': r+=L'\t'; break;
|
joachim99@75
|
41 default: r+=L'\\'; r+=s[i]; break;
|
joachim99@75
|
42 }
|
joachim99@75
|
43 }
|
joachim99@75
|
44 else
|
joachim99@75
|
45 r+=s[i];
|
joachim99@75
|
46 }
|
joachim99@75
|
47 }
|
joachim99@75
|
48
|
joachim99@75
|
49 static std::map< std::wstring, std::wstring > s_translationMap;
|
joachim99@75
|
50 static tstring s_translationFileName;
|
joachim99@75
|
51
|
joachim99@75
|
52 void readTranslationFile()
|
joachim99@75
|
53 {
|
joachim99@75
|
54 s_translationMap.clear();
|
joachim99@75
|
55 FILE* pFile = _tfopen( s_translationFileName.c_str(), TEXT("rb") );
|
joachim99@75
|
56 if ( pFile )
|
joachim99@75
|
57 {
|
joachim99@75
|
58 MESSAGELOG( TEXT( "Reading translations: " ) + s_translationFileName );
|
joachim99@75
|
59 std::vector<char> buffer;
|
joachim99@75
|
60 try {
|
joachim99@75
|
61 if ( fseek(pFile, 0, SEEK_END)==0 )
|
joachim99@75
|
62 {
|
joachim99@75
|
63 size_t length = ftell(pFile); // Get the file length
|
joachim99@75
|
64 buffer.resize(length);
|
joachim99@75
|
65 fseek(pFile, 0, SEEK_SET );
|
joachim99@75
|
66 fread(&buffer[0], 1, length, pFile );
|
joachim99@75
|
67 }
|
joachim99@75
|
68 }
|
joachim99@75
|
69 catch(...)
|
joachim99@75
|
70 {
|
joachim99@75
|
71 }
|
joachim99@75
|
72 fclose(pFile);
|
joachim99@75
|
73
|
joachim99@75
|
74 if (buffer.size()>0)
|
joachim99@75
|
75 {
|
joachim99@75
|
76 size_t bufferSize = buffer.size();
|
joachim99@75
|
77 int offset = 0;
|
joachim99@75
|
78 if ( buffer[0]=='\xEF' && buffer[1]=='\xBB' && buffer[2]=='\xBF' )
|
joachim99@75
|
79 {
|
joachim99@75
|
80 offset += 3;
|
joachim99@75
|
81 bufferSize -= 3;
|
joachim99@75
|
82 }
|
joachim99@75
|
83
|
joachim99@75
|
84 size_t sLength = MultiByteToWideChar(CP_UTF8,0,&buffer[offset], (int)bufferSize, 0, 0 );
|
joachim99@75
|
85 std::wstring s( sLength, L' ' );
|
joachim99@75
|
86 MultiByteToWideChar(CP_UTF8,0,&buffer[offset], (int)bufferSize, &s[0], (int)s.size() );
|
joachim99@75
|
87
|
joachim99@75
|
88 // Now analyse the file and extract translation strings
|
joachim99@75
|
89 std::wstring msgid;
|
joachim99@75
|
90 std::wstring msgstr;
|
joachim99@75
|
91 msgid.reserve( 1000 );
|
joachim99@75
|
92 msgstr.reserve( 1000 );
|
joachim99@75
|
93 bool bExpectingId = true;
|
joachim99@75
|
94 for( size_t i=0; i<sLength; ++i )
|
joachim99@75
|
95 {
|
joachim99@75
|
96 wchar_t c = s[i];
|
joachim99@75
|
97 if( c == L'\n' || c == L'\r' || c==L' ' || c==L'\t' )
|
joachim99@75
|
98 continue;
|
joachim99@75
|
99 else if ( s[i]==L'#' ) // Comment
|
joachim99@75
|
100 while( s[i]!='\n' && s[i]!=L'\r' && i<sLength )
|
joachim99@75
|
101 ++i;
|
joachim99@75
|
102 else if ( s[i]==L'"' )
|
joachim99@75
|
103 {
|
joachim99@75
|
104 if ( bExpectingId ) parseString(s,i,msgid);
|
joachim99@75
|
105 else parseString(s,i,msgstr);
|
joachim99@75
|
106 }
|
joachim99@75
|
107 else if ( sLength-i>5 && wcsncmp( &s[i], L"msgid", 5 )==0 )
|
joachim99@75
|
108 {
|
joachim99@75
|
109 if ( !msgid.empty() && !msgstr.empty() )
|
joachim99@75
|
110 {
|
joachim99@75
|
111 s_translationMap[msgid] = msgstr;
|
joachim99@75
|
112 }
|
joachim99@75
|
113 bExpectingId = true;
|
joachim99@75
|
114 msgid.clear();
|
joachim99@75
|
115 i+=4;
|
joachim99@75
|
116 }
|
joachim99@75
|
117 else if ( sLength-i>6 && wcsncmp( &s[i], L"msgstr", 6 )==0 )
|
joachim99@75
|
118 {
|
joachim99@75
|
119 bExpectingId = false;
|
joachim99@75
|
120 msgstr.clear();
|
joachim99@75
|
121 i+=5;
|
joachim99@75
|
122 }
|
joachim99@75
|
123 else
|
joachim99@75
|
124 {
|
joachim99@75
|
125 // Unexpected ?
|
joachim99@75
|
126 }
|
joachim99@75
|
127 }
|
joachim99@75
|
128 }
|
joachim99@75
|
129 }
|
joachim99@75
|
130 else
|
joachim99@75
|
131 {
|
joachim99@75
|
132 ERRORLOG( TEXT( "Reading translations failed: " ) + s_translationFileName );
|
joachim99@75
|
133 }
|
joachim99@75
|
134 }
|
joachim99@75
|
135
|
joachim99@75
|
136 static tstring getTranslation( const tstring& fallback )
|
joachim99@75
|
137 {
|
joachim99@75
|
138 std::map< std::wstring, std::wstring >::iterator i = s_translationMap.find( fallback );
|
joachim99@75
|
139 if (i!=s_translationMap.end())
|
joachim99@75
|
140 return i->second;
|
joachim99@75
|
141 return fallback;
|
joachim99@75
|
142 }
|
joachim99@75
|
143 #else
|
joachim99@75
|
144
|
joachim99@75
|
145 static tstring getTranslation( const tstring& fallback )
|
joachim99@75
|
146 {
|
joachim99@75
|
147 return fallback;
|
joachim99@75
|
148 }
|
joachim99@75
|
149
|
joachim99@75
|
150 #endif
|
joachim99@75
|
151
|
joachim99@75
|
152
|
joachim99@75
|
153 static void replaceArgs( tstring& s, const tstring& r1, const tstring& r2=TEXT(""), const tstring& r3=TEXT("") )
|
joachim99@75
|
154 {
|
joachim99@75
|
155 tstring arg1 = TEXT("%1");
|
joachim99@75
|
156 size_t pos1 = s.find( arg1 );
|
joachim99@75
|
157 tstring arg2 = TEXT("%2");
|
joachim99@75
|
158 size_t pos2 = s.find( arg2 );
|
joachim99@75
|
159 tstring arg3 = TEXT("%3");
|
joachim99@75
|
160 size_t pos3 = s.find( arg3 );
|
joachim99@75
|
161 if ( pos1 != size_t(-1) )
|
joachim99@75
|
162 {
|
joachim99@75
|
163 s.replace( pos1, arg1.length(), r1 );
|
joachim99@75
|
164 if ( pos2 != size_t(-1) && pos1<pos2 )
|
joachim99@75
|
165 pos2 += r1.length() - arg1.length();
|
joachim99@75
|
166 if ( pos3 != size_t(-1) && pos1<pos3 )
|
joachim99@75
|
167 pos3 += r1.length() - arg1.length();
|
joachim99@75
|
168 }
|
joachim99@75
|
169 if ( pos2 != size_t(-1) )
|
joachim99@75
|
170 {
|
joachim99@75
|
171 s.replace( pos2, arg2.length(), r2 );
|
joachim99@75
|
172 if ( pos3 != size_t(-1) && pos2<pos3 )
|
joachim99@75
|
173 pos3 += r2.length() - arg2.length();
|
joachim99@75
|
174 }
|
joachim99@75
|
175 if ( pos3 != size_t(-1) )
|
joachim99@75
|
176 {
|
joachim99@75
|
177 s.replace( pos3, arg3.length(), r3 );
|
joachim99@75
|
178 }
|
joachim99@75
|
179 }
|
joachim99@75
|
180
|
joachim99@75
|
181 DIFF_EXT::DIFF_EXT()
|
joachim99@75
|
182 : m_nrOfSelectedFiles(0), _ref_count(0L),
|
joachim99@75
|
183 m_recentFiles( SERVER::instance()->recent_files() )
|
joachim99@75
|
184 {
|
joachim99@75
|
185 LOG();
|
joachim99@75
|
186 _resource = SERVER::instance()->handle();
|
joachim99@75
|
187
|
joachim99@75
|
188 SERVER::instance()->lock();
|
joachim99@75
|
189 }
|
joachim99@75
|
190
|
joachim99@75
|
191 DIFF_EXT::~DIFF_EXT()
|
joachim99@75
|
192 {
|
joachim99@75
|
193 LOG();
|
joachim99@77
|
194 if(_resource != SERVER::instance()->handle()) {
|
joachim99@77
|
195 FreeLibrary(_resource);
|
joachim99@77
|
196 }
|
joachim99@75
|
197
|
joachim99@77
|
198 SERVER::instance()->release();
|
joachim99@75
|
199 }
|
joachim99@75
|
200
|
joachim99@75
|
201 STDMETHODIMP
|
joachim99@75
|
202 DIFF_EXT::QueryInterface(REFIID refiid, void** ppv)
|
joachim99@75
|
203 {
|
joachim99@75
|
204 HRESULT ret = E_NOINTERFACE;
|
joachim99@75
|
205 *ppv = 0;
|
joachim99@75
|
206
|
joachim99@75
|
207 if(IsEqualIID(refiid, IID_IShellExtInit) || IsEqualIID(refiid, IID_IUnknown)) {
|
joachim99@75
|
208 *ppv = static_cast<IShellExtInit*>(this);
|
joachim99@75
|
209 } else if (IsEqualIID(refiid, IID_IContextMenu)) {
|
joachim99@75
|
210 *ppv = static_cast<IContextMenu*>(this);
|
joachim99@75
|
211 }
|
joachim99@75
|
212
|
joachim99@75
|
213 if(*ppv != 0) {
|
joachim99@75
|
214 AddRef();
|
joachim99@75
|
215
|
joachim99@75
|
216 ret = NOERROR;
|
joachim99@75
|
217 }
|
joachim99@75
|
218
|
joachim99@75
|
219 return ret;
|
joachim99@75
|
220 }
|
joachim99@75
|
221
|
joachim99@75
|
222 STDMETHODIMP_(ULONG)
|
joachim99@75
|
223 DIFF_EXT::AddRef()
|
joachim99@75
|
224 {
|
joachim99@75
|
225 return InterlockedIncrement((LPLONG)&_ref_count);
|
joachim99@75
|
226 }
|
joachim99@75
|
227
|
joachim99@75
|
228 STDMETHODIMP_(ULONG)
|
joachim99@75
|
229 DIFF_EXT::Release()
|
joachim99@75
|
230 {
|
joachim99@75
|
231 ULONG ret = 0L;
|
joachim99@75
|
232
|
joachim99@75
|
233 if(InterlockedDecrement((LPLONG)&_ref_count) != 0) {
|
joachim99@75
|
234 ret = _ref_count;
|
joachim99@75
|
235 } else {
|
joachim99@75
|
236 delete this;
|
joachim99@75
|
237 }
|
joachim99@75
|
238
|
joachim99@75
|
239 return ret;
|
joachim99@75
|
240 }
|
joachim99@75
|
241
|
joachim99@75
|
242
|
joachim99@75
|
243
|
joachim99@75
|
244 STDMETHODIMP
|
joachim99@75
|
245 DIFF_EXT::Initialize(LPCITEMIDLIST /*folder not used*/, IDataObject* data, HKEY /*key not used*/)
|
joachim99@75
|
246 {
|
joachim99@75
|
247 LOG();
|
joachim99@75
|
248
|
joachim99@75
|
249 #ifdef UNICODE
|
joachim99@75
|
250 tstring installDir = SERVER::instance()->getRegistryKeyString( TEXT(""), TEXT("InstallDir") );
|
joachim99@75
|
251 tstring language = SERVER::instance()->getRegistryKeyString( TEXT(""), TEXT("Language") );
|
joachim99@75
|
252 tstring translationFileName = installDir + TEXT("\\translations\\diff_ext_") + language + TEXT(".po");
|
joachim99@75
|
253 if ( s_translationFileName != translationFileName )
|
joachim99@75
|
254 {
|
joachim99@75
|
255 s_translationFileName = translationFileName;
|
joachim99@75
|
256 readTranslationFile();
|
joachim99@75
|
257 }
|
joachim99@75
|
258 #endif
|
joachim99@75
|
259
|
joachim99@75
|
260 FORMATETC format = {CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
|
joachim99@75
|
261 STGMEDIUM medium;
|
joachim99@75
|
262 medium.tymed = TYMED_HGLOBAL;
|
joachim99@75
|
263 HRESULT ret = E_INVALIDARG;
|
joachim99@75
|
264
|
joachim99@75
|
265 if(data->GetData(&format, &medium) == S_OK)
|
joachim99@75
|
266 {
|
joachim99@75
|
267 HDROP drop = (HDROP)medium.hGlobal;
|
joachim99@75
|
268 m_nrOfSelectedFiles = DragQueryFile(drop, 0xFFFFFFFF, 0, 0);
|
joachim99@75
|
269
|
joachim99@75
|
270 TCHAR tmp[MAX_PATH];
|
joachim99@75
|
271
|
joachim99@75
|
272 //initialize_language();
|
joachim99@75
|
273
|
joachim99@75
|
274 if (m_nrOfSelectedFiles >= 1 && m_nrOfSelectedFiles <= 3)
|
joachim99@75
|
275 {
|
joachim99@75
|
276 DragQueryFile(drop, 0, tmp, MAX_PATH);
|
joachim99@75
|
277 _file_name1 = tmp;
|
joachim99@75
|
278
|
joachim99@75
|
279 if(m_nrOfSelectedFiles >= 2)
|
joachim99@75
|
280 {
|
joachim99@75
|
281 DragQueryFile(drop, 1, tmp, MAX_PATH);
|
joachim99@75
|
282 _file_name2 = tmp;
|
joachim99@75
|
283 }
|
joachim99@75
|
284
|
joachim99@75
|
285 if( m_nrOfSelectedFiles == 3)
|
joachim99@75
|
286 {
|
joachim99@75
|
287 DragQueryFile(drop, 2, tmp, MAX_PATH);
|
joachim99@75
|
288 _file_name3 = tmp;
|
joachim99@75
|
289 }
|
joachim99@75
|
290
|
joachim99@75
|
291 ret = S_OK;
|
joachim99@75
|
292 }
|
joachim99@75
|
293 }
|
joachim99@75
|
294 else
|
joachim99@75
|
295 {
|
joachim99@75
|
296 SYSERRORLOG(TEXT("GetData"));
|
joachim99@75
|
297 }
|
joachim99@75
|
298
|
joachim99@75
|
299 return ret;
|
joachim99@75
|
300 }
|
joachim99@75
|
301
|
joachim99@75
|
302 static int insertMenuItemHelper( HMENU menu, UINT id, UINT position, const tstring& text,
|
joachim99@75
|
303 UINT fState = MFS_ENABLED, HMENU hSubMenu=0 )
|
joachim99@75
|
304 {
|
joachim99@75
|
305 MENUITEMINFO item_info;
|
joachim99@75
|
306 ZeroMemory(&item_info, sizeof(item_info));
|
joachim99@75
|
307 item_info.cbSize = sizeof(MENUITEMINFO);
|
joachim99@75
|
308 item_info.wID = id;
|
joachim99@75
|
309 if (text.empty())
|
joachim99@75
|
310 { // Separator
|
joachim99@75
|
311 item_info.fMask = MIIM_TYPE;
|
joachim99@75
|
312 item_info.fType = MFT_SEPARATOR;
|
joachim99@75
|
313 item_info.dwTypeData = 0;
|
joachim99@75
|
314 }
|
joachim99@75
|
315 else
|
joachim99@75
|
316 {
|
joachim99@75
|
317 item_info.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | (hSubMenu!=0 ? MIIM_SUBMENU : 0);
|
joachim99@75
|
318 item_info.fType = MFT_STRING;
|
joachim99@75
|
319 item_info.fState = fState;
|
joachim99@75
|
320 item_info.dwTypeData = (LPTSTR)text.c_str();
|
joachim99@75
|
321 item_info.hSubMenu = hSubMenu;
|
joachim99@75
|
322 }
|
joachim99@75
|
323 if ( 0 == InsertMenuItem(menu, position, TRUE, &item_info) )
|
joachim99@75
|
324 SYSERRORLOG(TEXT("InsertMenuItem"));
|
joachim99@75
|
325 return id;
|
joachim99@75
|
326 }
|
joachim99@75
|
327
|
joachim99@75
|
328
|
joachim99@75
|
329 STDMETHODIMP
|
joachim99@75
|
330 DIFF_EXT::QueryContextMenu(HMENU menu, UINT position, UINT first_cmd, UINT /*last_cmd not used*/, UINT flags)
|
joachim99@75
|
331 {
|
joachim99@75
|
332 LOG();
|
joachim99@75
|
333 m_id_Diff = UINT(-1);
|
joachim99@75
|
334 m_id_DiffWith = UINT(-1);
|
joachim99@75
|
335 m_id_DiffLater = UINT(-1);
|
joachim99@75
|
336 m_id_MergeWith = UINT(-1);
|
joachim99@75
|
337 m_id_Merge3 = UINT(-1);
|
joachim99@75
|
338 m_id_Diff3 = UINT(-1);
|
joachim99@75
|
339 m_id_DiffWith_Base = UINT(-1);
|
joachim99@77
|
340 m_id_ClearList = UINT(-1);
|
joachim99@75
|
341 m_id_About = UINT(-1);
|
joachim99@75
|
342
|
joachim99@75
|
343 HRESULT ret = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
|
joachim99@75
|
344
|
joachim99@75
|
345 if(!(flags & CMF_DEFAULTONLY))
|
joachim99@75
|
346 {
|
joachim99@75
|
347 /* Menu structure:
|
joachim99@75
|
348 KDiff3 -> (1 File selected): Save 'selection' for later comparison (push onto history stack)
|
joachim99@75
|
349 Compare 'selection' with first file on history stack.
|
joachim99@75
|
350 Compare 'selection' with -> choice from history stack
|
joachim99@75
|
351 Merge 'selection' with first file on history stack.
|
joachim99@75
|
352 Merge 'selection' with last two files on history stack.
|
joachim99@75
|
353 (2 Files selected): Compare 's1' with 's2'
|
joachim99@75
|
354 Merge 's1' with 's2'
|
joachim99@75
|
355 (3 Files selected): Compare 's1', 's2' and 's3'
|
joachim99@75
|
356 */
|
joachim99@75
|
357 HMENU subMenu = CreateMenu();
|
joachim99@75
|
358
|
joachim99@75
|
359 UINT id = first_cmd;
|
joachim99@75
|
360 m_id_FirstCmd = first_cmd;
|
joachim99@75
|
361
|
joachim99@75
|
362 insertMenuItemHelper( menu, id++, position++, TEXT("") ); // begin separator
|
joachim99@75
|
363
|
joachim99@75
|
364 tstring menuString;
|
joachim99@75
|
365 UINT pos2=0;
|
joachim99@75
|
366 if(m_nrOfSelectedFiles == 1)
|
joachim99@75
|
367 {
|
joachim99@75
|
368 size_t nrOfRecentFiles = m_recentFiles.size();
|
joachim99@77
|
369 tstring menuStringCompare = i18n("Compare with %1");
|
joachim99@77
|
370 tstring menuStringMerge = i18n("Merge with %1");
|
joachim99@77
|
371 tstring firstFileName;
|
joachim99@75
|
372 if( nrOfRecentFiles>=1 )
|
joachim99@75
|
373 {
|
joachim99@80
|
374 firstFileName = TEXT("'") + cut_to_length( m_recentFiles.front() ) + TEXT("'");
|
joachim99@75
|
375 }
|
joachim99@77
|
376 replaceArgs( menuStringCompare, firstFileName );
|
joachim99@77
|
377 replaceArgs( menuStringMerge, firstFileName );
|
joachim99@75
|
378 m_id_DiffWith = insertMenuItemHelper( subMenu, id++, pos2++, menuStringCompare, nrOfRecentFiles >=1 ? MFS_ENABLED : MFS_DISABLED );
|
joachim99@75
|
379 m_id_MergeWith = insertMenuItemHelper( subMenu, id++, pos2++, menuStringMerge, nrOfRecentFiles >=1 ? MFS_ENABLED : MFS_DISABLED );
|
joachim99@75
|
380
|
joachim99@75
|
381 //if( nrOfRecentFiles>=2 )
|
joachim99@75
|
382 //{
|
joachim99@75
|
383 // tstring firstFileName = cut_to_length( m_recentFiles.front() );
|
joachim99@75
|
384 // tstring secondFileName = cut_to_length( *(++m_recentFiles.begin()) );
|
joachim99@75
|
385 //}
|
joachim99@75
|
386 m_id_Merge3 = insertMenuItemHelper( subMenu, id++, pos2++, i18n("3-way merge with base"),
|
joachim99@75
|
387 nrOfRecentFiles >=2 ? MFS_ENABLED : MFS_DISABLED );
|
joachim99@75
|
388
|
joachim99@77
|
389 menuString = i18n("Save '%1' for later");
|
joachim99@75
|
390 replaceArgs( menuString, _file_name1 );
|
joachim99@75
|
391 m_id_DiffLater = insertMenuItemHelper( subMenu, id++, pos2++, menuString );
|
joachim99@75
|
392
|
joachim99@75
|
393 HMENU file_list = CreateMenu();
|
joachim99@75
|
394 std::list<tstring>::iterator i;
|
joachim99@75
|
395 m_id_DiffWith_Base = id;
|
joachim99@75
|
396 int n = 0;
|
joachim99@75
|
397 for( i = m_recentFiles.begin(); i!=m_recentFiles.end(); ++i )
|
joachim99@75
|
398 {
|
joachim99@75
|
399 tstring s = cut_to_length( *i );
|
joachim99@75
|
400 insertMenuItemHelper( file_list, id++, n, s );
|
joachim99@75
|
401 ++n;
|
joachim99@75
|
402 }
|
joachim99@75
|
403
|
joachim99@77
|
404 insertMenuItemHelper( subMenu, id++, pos2++, i18n("Compare with ..."),
|
joachim99@75
|
405 nrOfRecentFiles > 0 ? MFS_ENABLED : MFS_DISABLED, file_list );
|
joachim99@77
|
406
|
joachim99@77
|
407 m_id_ClearList = insertMenuItemHelper( subMenu, id++, pos2++, i18n("Clear list"), nrOfRecentFiles >=1 ? MFS_ENABLED : MFS_DISABLED );
|
joachim99@75
|
408 }
|
joachim99@75
|
409 else if(m_nrOfSelectedFiles == 2)
|
joachim99@75
|
410 {
|
joachim99@75
|
411 //= "Diff " + cut_to_length(_file_name1, 20)+" and "+cut_to_length(_file_name2, 20);
|
joachim99@75
|
412 m_id_Diff = insertMenuItemHelper( subMenu, id++, pos2++, i18n("Compare") );
|
joachim99@75
|
413 }
|
joachim99@75
|
414 else if ( m_nrOfSelectedFiles == 3 )
|
joachim99@75
|
415 {
|
joachim99@75
|
416 m_id_Diff3 = insertMenuItemHelper( subMenu, id++, pos2++, i18n("3 way comparison") );
|
joachim99@75
|
417 }
|
joachim99@75
|
418 else
|
joachim99@75
|
419 {
|
joachim99@75
|
420 // More than 3 files selected?
|
joachim99@75
|
421 }
|
joachim99@75
|
422 m_id_About = insertMenuItemHelper( subMenu, id++, pos2++, i18n("About Diff-Ext ...") );
|
joachim99@75
|
423
|
joachim99@75
|
424 insertMenuItemHelper( menu, id++, position++, TEXT("KDiff3"), MFS_ENABLED, subMenu );
|
joachim99@75
|
425
|
joachim99@75
|
426 insertMenuItemHelper( menu, id++, position++, TEXT("") ); // final separator
|
joachim99@75
|
427
|
joachim99@75
|
428 ret = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, id-first_cmd);
|
joachim99@75
|
429 }
|
joachim99@75
|
430
|
joachim99@75
|
431 return ret;
|
joachim99@75
|
432 }
|
joachim99@75
|
433
|
joachim99@75
|
434 STDMETHODIMP
|
joachim99@75
|
435 DIFF_EXT::InvokeCommand(LPCMINVOKECOMMANDINFO ici)
|
joachim99@75
|
436 {
|
joachim99@75
|
437 HRESULT ret = NOERROR;
|
joachim99@75
|
438
|
joachim99@75
|
439 _hwnd = ici->hwnd;
|
joachim99@75
|
440
|
joachim99@75
|
441 if(HIWORD(ici->lpVerb) == 0)
|
joachim99@75
|
442 {
|
joachim99@75
|
443 UINT id = m_id_FirstCmd + LOWORD(ici->lpVerb);
|
joachim99@75
|
444 if(id == m_id_Diff)
|
joachim99@75
|
445 {
|
joachim99@75
|
446 LOG();
|
joachim99@75
|
447 diff( TEXT("\"") + _file_name1 + TEXT("\" \"") + _file_name2 + TEXT("\"") );
|
joachim99@75
|
448 }
|
joachim99@75
|
449 else if(id == m_id_Diff3)
|
joachim99@75
|
450 {
|
joachim99@75
|
451 LOG();
|
joachim99@75
|
452 diff( TEXT("\"") + _file_name1 + TEXT("\" \"") + _file_name2 + TEXT("\" \"") + _file_name3 + TEXT("\"") );
|
joachim99@75
|
453 }
|
joachim99@75
|
454 else if(id == m_id_Merge3)
|
joachim99@75
|
455 {
|
joachim99@75
|
456 LOG();
|
joachim99@75
|
457 std::list< tstring >::iterator iFrom = m_recentFiles.begin();
|
joachim99@75
|
458 std::list< tstring >::iterator iBase = iFrom;
|
joachim99@75
|
459 ++iBase;
|
joachim99@75
|
460 diff( TEXT("-m \"") + *iBase + TEXT("\" \"") + *iFrom + TEXT("\" \"") + _file_name1 + TEXT("\"") );
|
joachim99@75
|
461 }
|
joachim99@75
|
462 else if(id == m_id_DiffWith)
|
joachim99@75
|
463 {
|
joachim99@75
|
464 LOG();
|
joachim99@75
|
465 diff_with(0, false);
|
joachim99@75
|
466 }
|
joachim99@75
|
467 else if(id == m_id_MergeWith)
|
joachim99@75
|
468 {
|
joachim99@75
|
469 LOG();
|
joachim99@75
|
470 diff_with(0, true);
|
joachim99@75
|
471 }
|
joachim99@77
|
472 else if(id == m_id_ClearList)
|
joachim99@77
|
473 {
|
joachim99@77
|
474 LOG();
|
joachim99@77
|
475 m_recentFiles.clear();
|
joachim99@77
|
476 }
|
joachim99@75
|
477 else if(id == m_id_DiffLater)
|
joachim99@75
|
478 {
|
joachim99@75
|
479 MESSAGELOG(TEXT("Diff Later: ")+_file_name1);
|
joachim99@75
|
480 m_recentFiles.remove( _file_name1 );
|
joachim99@75
|
481 m_recentFiles.push_front( _file_name1 );
|
joachim99@75
|
482 }
|
joachim99@75
|
483 else if(id >= m_id_DiffWith_Base && id < m_id_DiffWith_Base+m_recentFiles.size())
|
joachim99@75
|
484 {
|
joachim99@75
|
485 LOG();
|
joachim99@75
|
486 diff_with(id-m_id_DiffWith_Base, false);
|
joachim99@75
|
487 }
|
joachim99@75
|
488 else if(id == m_id_About)
|
joachim99@75
|
489 {
|
joachim99@75
|
490 LOG();
|
joachim99@75
|
491 MessageBox( _hwnd, (i18n("Diff-Ext Copyright (c) 2003-2006, Sergey Zorin. All rights reserved.\n")
|
joachim99@75
|
492 + i18n("This software is distributable under the BSD license.\n")
|
joachim99@75
|
493 + i18n("Some extensions for KDiff3 by Joachim Eibl.\n")
|
joachim99@75
|
494 + i18n("Homepage for Diff-Ext: http://diff-ext.sourceforge.net\n")
|
joachim99@75
|
495 + i18n("Homepage for KDiff3: http://kdiff3.sourceforge.net")).c_str()
|
joachim99@75
|
496 , i18n("About Diff-Ext for KDiff3").c_str(), MB_OK );
|
joachim99@75
|
497 }
|
joachim99@75
|
498 else
|
joachim99@75
|
499 {
|
joachim99@75
|
500 ret = E_INVALIDARG;
|
joachim99@75
|
501 TCHAR verb[80];
|
joachim99@75
|
502 _sntprintf(verb, 79, TEXT("Command id: %d"), LOWORD(ici->lpVerb));
|
joachim99@75
|
503 verb[79]=0;
|
joachim99@75
|
504 ERRORLOG(verb);
|
joachim99@75
|
505 }
|
joachim99@75
|
506 }
|
joachim99@80
|
507 else
|
joachim99@80
|
508 {
|
joachim99@80
|
509 ret = E_INVALIDARG;
|
joachim99@80
|
510 }
|
joachim99@75
|
511
|
joachim99@75
|
512 return ret;
|
joachim99@75
|
513 }
|
joachim99@75
|
514
|
joachim99@75
|
515 STDMETHODIMP
|
joachim99@75
|
516 DIFF_EXT::GetCommandString(UINT idCmd, UINT uFlags, UINT*, LPSTR pszName, UINT cchMax)
|
joachim99@75
|
517 {
|
joachim99@75
|
518 // LOG(); // Gets called very often
|
joachim99@75
|
519 HRESULT ret = NOERROR;
|
joachim99@75
|
520
|
joachim99@75
|
521 if(uFlags == GCS_HELPTEXT) {
|
joachim99@75
|
522 tstring helpString;
|
joachim99@75
|
523 if( idCmd == m_id_Diff )
|
joachim99@75
|
524 {
|
joachim99@75
|
525 helpString = i18n("Compare selected files");
|
joachim99@75
|
526 }
|
joachim99@75
|
527 else if( idCmd == m_id_DiffWith )
|
joachim99@75
|
528 {
|
joachim99@75
|
529 if(!m_recentFiles.empty())
|
joachim99@75
|
530 {
|
joachim99@75
|
531 helpString = i18n("Compare '%1' with '%2'");
|
joachim99@75
|
532 replaceArgs( helpString, _file_name1, m_recentFiles.front() );
|
joachim99@75
|
533 }
|
joachim99@75
|
534 }
|
joachim99@75
|
535 else if(idCmd == m_id_DiffLater)
|
joachim99@75
|
536 {
|
joachim99@75
|
537 helpString = i18n("Save '%1' for later operation");
|
joachim99@75
|
538 replaceArgs( helpString, _file_name1 );
|
joachim99@75
|
539 }
|
joachim99@75
|
540 else if((idCmd >= m_id_DiffWith_Base) && (idCmd < m_id_DiffWith_Base+m_recentFiles.size()))
|
joachim99@75
|
541 {
|
joachim99@75
|
542 if( !m_recentFiles.empty() )
|
joachim99@75
|
543 {
|
joachim99@75
|
544 unsigned int num = idCmd - m_id_DiffWith_Base;
|
joachim99@75
|
545 std::list<tstring>::iterator i = m_recentFiles.begin();
|
joachim99@75
|
546 for(unsigned int j = 0; j < num && i != m_recentFiles.end(); j++)
|
joachim99@75
|
547 i++;
|
joachim99@75
|
548
|
joachim99@75
|
549 if ( i!=m_recentFiles.end() )
|
joachim99@75
|
550 {
|
joachim99@75
|
551 helpString = i18n("Compare '%1' with '%2'");
|
joachim99@75
|
552 replaceArgs( helpString, _file_name1, *i );
|
joachim99@75
|
553 }
|
joachim99@75
|
554 }
|
joachim99@75
|
555 }
|
joachim99@75
|
556 lstrcpyn( (LPTSTR)pszName, helpString.c_str(), cchMax );
|
joachim99@75
|
557 }
|
joachim99@75
|
558
|
joachim99@75
|
559 return ret;
|
joachim99@75
|
560 }
|
joachim99@75
|
561
|
joachim99@75
|
562 void
|
joachim99@75
|
563 DIFF_EXT::diff( const tstring& arguments )
|
joachim99@75
|
564 {
|
joachim99@75
|
565 LOG();
|
joachim99@75
|
566 STARTUPINFO si;
|
joachim99@75
|
567 PROCESS_INFORMATION pi;
|
joachim99@75
|
568 bool bError = true;
|
joachim99@75
|
569 tstring command = SERVER::instance()->getRegistryKeyString( TEXT(""), TEXT("diffcommand") );
|
joachim99@75
|
570 tstring commandLine = TEXT("\"") + command + TEXT("\" ") + arguments;
|
joachim99@75
|
571 if ( ! command.empty() )
|
joachim99@75
|
572 {
|
joachim99@75
|
573 ZeroMemory(&si, sizeof(si));
|
joachim99@75
|
574 si.cb = sizeof(si);
|
joachim99@75
|
575 if (CreateProcess(command.c_str(), (LPTSTR)commandLine.c_str(), 0, 0, FALSE, 0, 0, 0, &si, &pi) == 0)
|
joachim99@75
|
576 {
|
joachim99@75
|
577 SYSERRORLOG(TEXT("CreateProcess") + command);
|
joachim99@75
|
578 }
|
joachim99@75
|
579 else
|
joachim99@75
|
580 {
|
joachim99@75
|
581 bError = false;
|
joachim99@75
|
582 CloseHandle( pi.hProcess );
|
joachim99@75
|
583 CloseHandle( pi.hThread );
|
joachim99@75
|
584 }
|
joachim99@75
|
585 }
|
joachim99@75
|
586
|
joachim99@75
|
587 if (bError)
|
joachim99@75
|
588 {
|
joachim99@75
|
589 tstring message = i18n("Could not start KDiff3. Please rerun KDiff3 installation.");
|
joachim99@75
|
590 message += TEXT("\n") + i18n("Command") + TEXT(": ") + command;
|
joachim99@75
|
591 message += TEXT("\n") + i18n("CommandLine") + TEXT(": ") + commandLine;
|
joachim99@75
|
592 MessageBox(_hwnd, message.c_str(), i18n("Diff-Ext For KDiff3").c_str(), MB_OK);
|
joachim99@75
|
593 }
|
joachim99@75
|
594 }
|
joachim99@75
|
595
|
joachim99@75
|
596 void
|
joachim99@75
|
597 DIFF_EXT::diff_with(unsigned int num, bool bMerge)
|
joachim99@75
|
598 {
|
joachim99@75
|
599 LOG();
|
joachim99@75
|
600 std::list<tstring>::iterator i = m_recentFiles.begin();
|
joachim99@75
|
601 for(unsigned int j = 0; j < num && i!=m_recentFiles.end(); j++) {
|
joachim99@75
|
602 i++;
|
joachim99@75
|
603 }
|
joachim99@75
|
604
|
joachim99@75
|
605 if ( i!=m_recentFiles.end() )
|
joachim99@75
|
606 _file_name2 = *i;
|
joachim99@75
|
607
|
joachim99@77
|
608 diff( (bMerge ? TEXT("-m \"") : TEXT("\"") ) + _file_name2 + TEXT("\" \"") + _file_name1 + TEXT("\"") );
|
joachim99@75
|
609 }
|
joachim99@75
|
610
|
joachim99@75
|
611
|
joachim99@75
|
612 tstring
|
joachim99@75
|
613 DIFF_EXT::cut_to_length(const tstring& in, size_t max_len)
|
joachim99@75
|
614 {
|
joachim99@75
|
615 tstring ret;
|
joachim99@75
|
616 if( in.length() > max_len)
|
joachim99@75
|
617 {
|
joachim99@75
|
618 ret = in.substr(0, (max_len-3)/2);
|
joachim99@75
|
619 ret += TEXT("...");
|
joachim99@75
|
620 ret += in.substr( in.length()-(max_len-3)/2 );
|
joachim99@75
|
621 }
|
joachim99@75
|
622 else
|
joachim99@75
|
623 {
|
joachim99@75
|
624 ret = in;
|
joachim99@75
|
625 }
|
joachim99@75
|
626
|
joachim99@75
|
627 return ret;
|
joachim99@75
|
628 }
|