OSDN Git Service

Update version number to 1.2.1.0
[tortoisegit/TortoiseGitJp.git] / src / TortoiseMerge / DiffData.cpp
1 // TortoiseMerge - a Diff/Patch program\r
2 \r
3 // Copyright (C) 2006-2009 - TortoiseSVN\r
4 \r
5 // This program is free software; you can redistribute it and/or\r
6 // modify it under the terms of the GNU General Public License\r
7 // as published by the Free Software Foundation; either version 2\r
8 // of the License, or (at your option) any later version.\r
9 \r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 \r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, write to the Free Software Foundation,\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
18 //\r
19 #include "StdAfx.h"\r
20 #include "svn_version.h"\r
21 #include "svn_io.h"\r
22 #include "diff.h"\r
23 #include "TempFiles.h"\r
24 #include "registry.h"\r
25 #include "Resource.h"\r
26 #include "Diffdata.h"\r
27 #include "UnicodeUtils.h"\r
28 #include "GitAdminDir.h"\r
29 #include "svn_dso.h"\r
30 \r
31 #pragma warning(push)\r
32 #pragma warning(disable: 4702) // unreachable code\r
33 int CDiffData::abort_on_pool_failure (int /*retcode*/)\r
34 {\r
35         abort ();\r
36         return -1;\r
37 }\r
38 #pragma warning(pop)\r
39 \r
40 CDiffData::CDiffData(void)\r
41 {\r
42         apr_initialize();\r
43         svn_dso_initialize2();\r
44         g_GitAdminDir.Init();\r
45 \r
46         m_bBlame = false;\r
47 \r
48         m_sPatchOriginal = _T(": original");\r
49         m_sPatchPatched = _T(": patched");\r
50 }\r
51 \r
52 CDiffData::~CDiffData(void)\r
53 {\r
54         g_GitAdminDir.Close();\r
55         apr_terminate();\r
56 }\r
57 \r
58 int CDiffData::GetLineCount()\r
59 {\r
60         int count = 0;\r
61         count = (int)m_arBaseFile.GetCount();\r
62         count = (int)(count > m_arTheirFile.GetCount() ? count : m_arTheirFile.GetCount());\r
63         count = (int)(count > m_arYourFile.GetCount() ? count : m_arYourFile.GetCount());\r
64         return count;\r
65 }\r
66 \r
67 int CDiffData::GetLineActualLength(int index)\r
68 {\r
69         int count = 0;\r
70         if (index < m_arBaseFile.GetCount())\r
71                 count = (count > m_arBaseFile.GetAt(index).GetLength() ? count : m_arBaseFile.GetAt(index).GetLength());\r
72         if (index < m_arTheirFile.GetCount())\r
73                 count = (count > m_arTheirFile.GetAt(index).GetLength() ? count : m_arTheirFile.GetAt(index).GetLength());\r
74         if (index < m_arYourFile.GetCount())\r
75                 count = (count > m_arYourFile.GetAt(index).GetLength() ? count : m_arYourFile.GetAt(index).GetLength());\r
76         return count;\r
77 }\r
78 \r
79 LPCTSTR CDiffData::GetLineChars(int index)\r
80 {\r
81         if (index < m_arBaseFile.GetCount())\r
82                 return m_arBaseFile.GetAt(index);\r
83         if (index < m_arTheirFile.GetCount())\r
84                 return m_arTheirFile.GetAt(index);\r
85         if (index < m_arYourFile.GetCount())\r
86                 return m_arYourFile.GetAt(index);\r
87         return NULL;\r
88 }\r
89 \r
90 BOOL CDiffData::Load()\r
91 {\r
92         CString sConvertedBaseFilename, sConvertedTheirFilename, sConvertedYourFilename;\r
93         apr_pool_t * pool;\r
94 \r
95         apr_pool_create_ex (&pool, NULL, abort_on_pool_failure, NULL);\r
96 \r
97         m_arBaseFile.RemoveAll();\r
98         m_arYourFile.RemoveAll();\r
99         m_arTheirFile.RemoveAll();\r
100 \r
101         m_YourBaseBoth.Clear();\r
102         m_YourBaseLeft.Clear();\r
103         m_YourBaseRight.Clear();\r
104 \r
105         m_TheirBaseBoth.Clear();\r
106         m_TheirBaseLeft.Clear();\r
107         m_TheirBaseRight.Clear();\r
108 \r
109         m_Diff3.Clear();\r
110 \r
111         m_arDiff3LinesBase.RemoveAll();\r
112         m_arDiff3LinesYour.RemoveAll();\r
113         m_arDiff3LinesTheir.RemoveAll();\r
114 \r
115         CTempFiles tempfiles;\r
116         CRegDWORD regIgnoreWS = CRegDWORD(_T("Software\\TortoiseMerge\\IgnoreWS"));\r
117         CRegDWORD regIgnoreEOL = CRegDWORD(_T("Software\\TortoiseMerge\\IgnoreEOL"), TRUE);\r
118         CRegDWORD regIgnoreCase = CRegDWORD(_T("Software\\TortoiseMerge\\CaseInsensitive"), FALSE);\r
119         DWORD dwIgnoreWS = regIgnoreWS;\r
120         bool bIgnoreEOL = ((DWORD)regIgnoreEOL)!=0;\r
121         BOOL bIgnoreCase = ((DWORD)regIgnoreCase)!=0;\r
122 \r
123         // The Subversion diff API only can ignore whitespaces and eol styles.\r
124         // It also can only handle one-byte charsets.\r
125         // To ignore case changes or to handle UTF-16 files, we have to\r
126         // save the original file in UTF-8 and/or the letters changed to lowercase\r
127         // so the Subversion diff can handle those.\r
128         sConvertedBaseFilename = m_baseFile.GetFilename();\r
129         sConvertedYourFilename = m_yourFile.GetFilename();\r
130         sConvertedTheirFilename = m_theirFile.GetFilename();\r
131         if (IsBaseFileInUse())\r
132         {\r
133                 if (!m_arBaseFile.Load(m_baseFile.GetFilename()))\r
134                 {\r
135                         m_sError = m_arBaseFile.GetErrorString();\r
136                         return FALSE;\r
137                 }\r
138                 if ((bIgnoreCase)||(m_arBaseFile.GetUnicodeType() == CFileTextLines::UNICODE_LE))\r
139                 {\r
140                         CFileTextLines converted(m_arBaseFile);\r
141                         sConvertedBaseFilename = tempfiles.GetTempFilePath();\r
142                         converted.Save(sConvertedBaseFilename, m_arBaseFile.GetUnicodeType() == CFileTextLines::UNICODE_LE, dwIgnoreWS, bIgnoreCase, m_bBlame);\r
143                 }\r
144         }\r
145 \r
146         if (IsTheirFileInUse())\r
147         {\r
148                 // m_arBaseFile.GetCount() is passed as a hint for the number of lines in this file\r
149                 // It's a fair guess that the files will be roughly the same size\r
150                 if (!m_arTheirFile.Load(m_theirFile.GetFilename(),m_arBaseFile.GetCount()))\r
151                 {\r
152                         m_sError = m_arTheirFile.GetErrorString();\r
153                         return FALSE;\r
154                 }\r
155                 if ((bIgnoreCase)||(m_arTheirFile.GetUnicodeType() == CFileTextLines::UNICODE_LE))\r
156                 {\r
157                         CFileTextLines converted(m_arTheirFile);\r
158                         sConvertedTheirFilename = tempfiles.GetTempFilePath();\r
159                         converted.Save(sConvertedTheirFilename, m_arTheirFile.GetUnicodeType() == CFileTextLines::UNICODE_LE, dwIgnoreWS, bIgnoreCase, m_bBlame);\r
160                 }\r
161         }\r
162 \r
163         if (IsYourFileInUse())\r
164         {\r
165                 // m_arBaseFile.GetCount() is passed as a hint for the number of lines in this file\r
166                 // It's a fair guess that the files will be roughly the same size\r
167                 if (!m_arYourFile.Load(m_yourFile.GetFilename(),m_arBaseFile.GetCount()))\r
168                 {\r
169                         m_sError = m_arYourFile.GetErrorString();\r
170                         return FALSE;\r
171                 }\r
172                 if ((bIgnoreCase)||(m_arYourFile.GetUnicodeType() == CFileTextLines::UNICODE_LE))\r
173                 {\r
174                         CFileTextLines converted(m_arYourFile);\r
175                         sConvertedYourFilename = tempfiles.GetTempFilePath();\r
176                         converted.Save(sConvertedYourFilename, m_arYourFile.GetUnicodeType() == CFileTextLines::UNICODE_LE, dwIgnoreWS, bIgnoreCase, m_bBlame);\r
177                 }\r
178         }\r
179 \r
180         // Calculate the number of lines in the largest of the three files\r
181         int lengthHint = max(m_arBaseFile.GetCount(), m_arTheirFile.GetCount());\r
182         lengthHint = max(lengthHint, m_arYourFile.GetCount());\r
183 \r
184         try\r
185         {\r
186                 m_YourBaseBoth.Reserve(lengthHint);\r
187                 m_YourBaseLeft.Reserve(lengthHint);\r
188                 m_YourBaseRight.Reserve(lengthHint);\r
189 \r
190                 m_TheirBaseBoth.Reserve(lengthHint);\r
191                 m_TheirBaseLeft.Reserve(lengthHint);\r
192                 m_TheirBaseRight.Reserve(lengthHint);\r
193 \r
194                 m_arDiff3LinesBase.Reserve(lengthHint);\r
195                 m_arDiff3LinesYour.Reserve(lengthHint);\r
196                 m_arDiff3LinesTheir.Reserve(lengthHint);\r
197         }\r
198         catch (CMemoryException* e)\r
199         {\r
200                 e->GetErrorMessage(m_sError.GetBuffer(255), 255);\r
201                 m_sError.ReleaseBuffer();\r
202                 return FALSE;\r
203         }\r
204 \r
205         // Is this a two-way diff?\r
206         if (IsBaseFileInUse() && IsYourFileInUse() && !IsTheirFileInUse())\r
207         {\r
208                 if (!DoTwoWayDiff(sConvertedBaseFilename, sConvertedYourFilename, dwIgnoreWS, bIgnoreEOL, pool))\r
209                 {\r
210                         apr_pool_destroy (pool);                                        // free the allocated memory\r
211                         return FALSE;\r
212                 }\r
213         }\r
214 \r
215         if (IsBaseFileInUse() && IsTheirFileInUse() && !IsYourFileInUse())\r
216         {\r
217                 ASSERT(FALSE);\r
218         }\r
219 \r
220         if (IsBaseFileInUse() && IsTheirFileInUse() && IsYourFileInUse())\r
221         {\r
222                 m_Diff3.Reserve(lengthHint);\r
223 \r
224                 if (!DoThreeWayDiff(sConvertedBaseFilename, sConvertedYourFilename, sConvertedTheirFilename, dwIgnoreWS, bIgnoreEOL, !!bIgnoreCase, pool))\r
225                 {\r
226                         apr_pool_destroy (pool);                                        // free the allocated memory\r
227                         return FALSE;\r
228                 }\r
229         }\r
230 \r
231         apr_pool_destroy (pool);                                        // free the allocated memory\r
232         return TRUE;\r
233 }\r
234 \r
235 \r
236 bool\r
237 CDiffData::DoTwoWayDiff(const CString& sBaseFilename, const CString& sYourFilename, DWORD dwIgnoreWS, bool bIgnoreEOL, apr_pool_t * pool)\r
238 {\r
239         // convert CString filenames (UTF-16 or ANSI) to UTF-8\r
240         CStringA sBaseFilenameUtf8 = CUnicodeUtils::GetUTF8(sBaseFilename);\r
241         CStringA sYourFilenameUtf8 = CUnicodeUtils::GetUTF8(sYourFilename);\r
242 \r
243         svn_diff_t * diffYourBase = NULL;\r
244         svn_error_t * svnerr = NULL;\r
245         svn_diff_file_options_t * options = svn_diff_file_options_create(pool);\r
246         options->ignore_eol_style = bIgnoreEOL;\r
247         options->ignore_space = svn_diff_file_ignore_space_none;\r
248         switch (dwIgnoreWS)\r
249         {\r
250         case 0:\r
251                 options->ignore_space = svn_diff_file_ignore_space_none;\r
252                 break;\r
253         case 1:\r
254                 options->ignore_space = svn_diff_file_ignore_space_all;\r
255                 break;\r
256         case 2:\r
257                 options->ignore_space = svn_diff_file_ignore_space_change;\r
258                 break;\r
259         }\r
260 \r
261         svnerr = svn_diff_file_diff_2(&diffYourBase, sBaseFilenameUtf8, sYourFilenameUtf8, options, pool);\r
262         if (svnerr)\r
263         {\r
264                 TRACE(_T("diff-error in CDiffData::Load()\n"));\r
265                 CString sMsg = CString(svnerr->message);\r
266                 while (svnerr->child)\r
267                 {\r
268                         svnerr = svnerr->child;\r
269                         sMsg += _T("\n");\r
270                         sMsg += CString(svnerr->message);\r
271                 }\r
272                 m_sError.Format(IDS_ERR_DIFF_DIFF, (LPCTSTR)sMsg);\r
273                 svn_error_clear(svnerr);\r
274                 return false;\r
275         }\r
276         svn_diff_t * tempdiff = diffYourBase;\r
277         LONG baseline = 0;\r
278         LONG yourline = 0;\r
279 \r
280         while (tempdiff)\r
281         {\r
282                 for (int i=0; i<tempdiff->original_length; i++)\r
283                 {\r
284                         if (baseline >= m_arBaseFile.GetCount())\r
285                         {\r
286                                 m_sError.LoadString(IDS_ERR_DIFF_NEWLINES);\r
287                                 return false;\r
288                         }\r
289                         const CString& sCurrentBaseLine = m_arBaseFile.GetAt(baseline);\r
290                         EOL endingBase = m_arBaseFile.GetLineEnding(baseline);\r
291                         if (tempdiff->type == svn_diff__type_common)\r
292                         {\r
293                                 if (yourline >= m_arYourFile.GetCount())\r
294                                 {\r
295                                         m_sError.LoadString(IDS_ERR_DIFF_NEWLINES);\r
296                                         return false;\r
297                                 }\r
298                                 const CString& sCurrentYourLine = m_arYourFile.GetAt(yourline);\r
299                                 EOL endingYours = m_arYourFile.GetLineEnding(yourline);\r
300                                 if (sCurrentBaseLine != sCurrentYourLine)\r
301                                 {\r
302                                         if (dwIgnoreWS == 2 || dwIgnoreWS == 3)\r
303                                         {\r
304                                                 CString s1 = m_arBaseFile.GetAt(baseline);\r
305                                                 CString s2 = sCurrentYourLine;\r
306                                                 \r
307                                                 if ( dwIgnoreWS == 2 )\r
308                                                 {\r
309                                                         s1.TrimLeft(_T(" \t"));\r
310                                                         s2.TrimLeft(_T(" \t"));\r
311                                                 }\r
312                                                 else\r
313                                                 {\r
314                                                         s1.TrimRight(_T(" \t"));\r
315                                                         s2.TrimRight(_T(" \t"));\r
316                                                 }\r
317 \r
318                                                 if (s1 != s2)\r
319                                                 {\r
320                                                         // one-pane view: two lines, one 'removed' and one 'added'\r
321                                                         m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_REMOVEDWHITESPACE, yourline, endingBase);\r
322                                                         m_YourBaseBoth.AddData(sCurrentYourLine, DIFFSTATE_ADDEDWHITESPACE, yourline, endingYours);\r
323                                                 }\r
324                                                 else\r
325                                                 {\r
326                                                         m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, yourline, endingBase);\r
327                                                 }\r
328                                         }\r
329                                         else if (dwIgnoreWS == 0)\r
330                                         {\r
331                                                 m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_REMOVEDWHITESPACE, yourline, endingBase);\r
332                                                 m_YourBaseBoth.AddData(sCurrentYourLine, DIFFSTATE_ADDEDWHITESPACE, yourline, endingYours);\r
333                                         }\r
334                                         else\r
335                                         {\r
336                                                 m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, yourline, endingBase);\r
337                                         }\r
338                                 }\r
339                                 else\r
340                                 {\r
341                                         m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, yourline, endingBase);\r
342                                 }\r
343                                 yourline++;             //in both files\r
344                         }\r
345                         else\r
346                         {\r
347                                 m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_REMOVED, yourline, endingBase);\r
348                         }\r
349                         baseline++;\r
350                 }\r
351                 if (tempdiff->type == svn_diff__type_diff_modified)\r
352                 {\r
353                         for (int i=0; i<tempdiff->modified_length; i++)\r
354                         {\r
355                                 if (m_arYourFile.GetCount() > yourline)\r
356                                 {\r
357                                         m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_ADDED, yourline, m_arYourFile.GetLineEnding(yourline));\r
358                                 }\r
359                                 yourline++;\r
360                         }\r
361                 }\r
362                 tempdiff = tempdiff->next;\r
363         }\r
364 \r
365         tempdiff = diffYourBase;\r
366         baseline = 0;\r
367         yourline = 0;\r
368         while (tempdiff)\r
369         {\r
370                 if (tempdiff->type == svn_diff__type_common)\r
371                 {\r
372                         for (int i=0; i<tempdiff->original_length; i++)\r
373                         {\r
374                                 const CString& sCurrentYourLine = m_arYourFile.GetAt(yourline);\r
375                                 EOL endingYours = m_arYourFile.GetLineEnding(yourline);\r
376                                 const CString& sCurrentBaseLine = m_arBaseFile.GetAt(baseline);\r
377                                 EOL endingBase = m_arBaseFile.GetLineEnding(baseline);\r
378                                 if (sCurrentBaseLine != sCurrentYourLine)\r
379                                 {\r
380                                         if (dwIgnoreWS == 2 || dwIgnoreWS == 3)\r
381                                         {\r
382                                                 CString s1 = sCurrentBaseLine;\r
383                                                 CString s2 = sCurrentYourLine;\r
384                                                 if ( dwIgnoreWS == 2 )\r
385                                                 {\r
386                                                         s1 = s1.TrimLeft(_T(" \t"));\r
387                                                         s2 = s2.TrimLeft(_T(" \t"));\r
388                                                 }\r
389                                                 else\r
390                                                 {\r
391                                                         s1 = s1.TrimRight(_T(" \t"));\r
392                                                         s2 = s2.TrimRight(_T(" \t"));\r
393                                                 }\r
394                                                 \r
395                                                 if (s1 != s2)\r
396                                                 {\r
397                                                         m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_WHITESPACE, baseline, endingBase);\r
398                                                         m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_WHITESPACE, yourline, endingYours);\r
399                                                 }\r
400                                                 else\r
401                                                 {\r
402                                                         m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, baseline, endingBase);\r
403                                                         m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_NORMAL, yourline, endingYours);\r
404                                                 }\r
405                                         }\r
406                                         else if (dwIgnoreWS == 0)\r
407                                         {\r
408                                                 m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_WHITESPACE, baseline, endingBase);\r
409                                                 m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_WHITESPACE, yourline, endingYours);\r
410                                         }\r
411                                         else\r
412                                         {\r
413                                                 m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, baseline, endingBase);\r
414                                                 m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_NORMAL, yourline, endingYours);\r
415                                         }\r
416                                 }\r
417                                 else\r
418                                 {\r
419                                         m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, baseline, endingBase);\r
420                                         m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_NORMAL, yourline, endingYours);\r
421                                 }\r
422                                 baseline++;\r
423                                 yourline++;\r
424                         }\r
425                 }\r
426                 if (tempdiff->type == svn_diff__type_diff_modified)\r
427                 {\r
428                         apr_off_t original_length = tempdiff->original_length;\r
429                         for (int i=0; i<tempdiff->modified_length; i++)\r
430                         {\r
431                                 if (m_arYourFile.GetCount() > yourline)\r
432                                 {\r
433                                         EOL endingYours = m_arYourFile.GetLineEnding(yourline);\r
434                                         if (original_length-- <= 0)\r
435                                         {\r
436                                                 m_YourBaseLeft.AddData(_T(""), DIFFSTATE_EMPTY, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
437                                                 m_YourBaseRight.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_ADDED, yourline, endingYours);\r
438                                         }\r
439                                         else\r
440                                         {\r
441                                                 EOL endingBase = m_arBaseFile.GetLineEnding(baseline);\r
442                                                 m_YourBaseLeft.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_REMOVED, baseline, endingBase);\r
443                                                 m_YourBaseRight.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_ADDED, yourline, endingYours);\r
444                                                 baseline++;\r
445                                         }\r
446                                         yourline++;\r
447                                 }\r
448                         }\r
449                         apr_off_t modified_length = tempdiff->modified_length;\r
450                         for (int i=0; i<tempdiff->original_length; i++)\r
451                         {\r
452                                 if (modified_length-- <= 0)\r
453                                 {\r
454                                         if (m_arBaseFile.GetCount() > baseline)\r
455                                         {\r
456                                                 EOL endingBase = m_arBaseFile.GetLineEnding(baseline);\r
457                                                 m_YourBaseLeft.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_REMOVED, baseline, endingBase);\r
458                                                 m_YourBaseRight.AddData(_T(""), DIFFSTATE_EMPTY, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
459                                                 baseline++;\r
460                                         }\r
461                                 }\r
462                         }\r
463                 }\r
464                 tempdiff = tempdiff->next;\r
465         }\r
466         TRACE(_T("done with 2-way diff\n"));\r
467 \r
468         return true;\r
469 }\r
470 \r
471 bool\r
472 CDiffData::DoThreeWayDiff(const CString& sBaseFilename, const CString& sYourFilename, const CString& sTheirFilename, DWORD dwIgnoreWS, bool bIgnoreEOL, bool bIgnoreCase, apr_pool_t * pool)\r
473 {\r
474         // convert CString filenames (UTF-16 or ANSI) to UTF-8\r
475         CStringA sBaseFilenameUtf8  = CUnicodeUtils::GetUTF8(sBaseFilename);\r
476         CStringA sYourFilenameUtf8  = CUnicodeUtils::GetUTF8(sYourFilename);\r
477         CStringA sTheirFilenameUtf8 = CUnicodeUtils::GetUTF8(sTheirFilename);\r
478         svn_diff_t * diffTheirYourBase = NULL;\r
479         svn_diff_file_options_t * options = svn_diff_file_options_create(pool);\r
480         options->ignore_eol_style = bIgnoreEOL;\r
481         options->ignore_space = svn_diff_file_ignore_space_none;\r
482         switch (dwIgnoreWS)\r
483         {\r
484         case 0:\r
485                 options->ignore_space = svn_diff_file_ignore_space_none;\r
486                 break;\r
487         case 1:\r
488                 options->ignore_space = svn_diff_file_ignore_space_all;\r
489                 break;\r
490         case 2:\r
491                 options->ignore_space = svn_diff_file_ignore_space_change;\r
492                 break;\r
493         }\r
494         svn_error_t * svnerr = svn_diff_file_diff3_2(&diffTheirYourBase, sBaseFilenameUtf8, sTheirFilenameUtf8, sYourFilenameUtf8, options, pool);\r
495         if (svnerr)\r
496         {\r
497                 TRACE(_T("diff-error in CDiffData::Load()\n"));\r
498                 CString sMsg = CString(svnerr->message);\r
499                 while (svnerr->child)\r
500                 {\r
501                         svnerr = svnerr->child;\r
502                         sMsg += _T("\n");\r
503                         sMsg += CString(svnerr->message);\r
504                 }\r
505                 m_sError.Format(IDS_ERR_DIFF_DIFF, (LPCTSTR)sMsg);\r
506                 svn_error_clear(svnerr);\r
507                 return false;\r
508         }\r
509 \r
510         svn_diff_t * tempdiff = diffTheirYourBase;\r
511         LONG baseline = 0;\r
512         LONG yourline = 0;\r
513         LONG theirline = 0;\r
514         LONG resline = 0;\r
515         while (tempdiff)\r
516         {\r
517                 if (tempdiff->type == svn_diff__type_common)\r
518                 {\r
519                         ASSERT((tempdiff->latest_length == tempdiff->modified_length) && (tempdiff->modified_length == tempdiff->original_length));\r
520                         for (int i=0; i<tempdiff->original_length; i++)\r
521                         {\r
522                                 if ((m_arYourFile.GetCount() > yourline)&&(m_arTheirFile.GetCount() > theirline))\r
523                                 {\r
524                                         m_Diff3.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_NORMAL, resline, m_arYourFile.GetLineEnding(yourline));\r
525 \r
526                                         m_arDiff3LinesBase.Add(baseline);\r
527                                         m_arDiff3LinesYour.Add(yourline);\r
528                                         m_arDiff3LinesTheir.Add(theirline);\r
529 \r
530                                         m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_NORMAL, yourline, m_arYourFile.GetLineEnding(yourline));\r
531                                         m_TheirBaseBoth.AddData(m_arTheirFile.GetAt(theirline), DIFFSTATE_NORMAL, theirline, m_arTheirFile.GetLineEnding(theirline));\r
532 \r
533                                         baseline++;\r
534                                         yourline++;\r
535                                         theirline++;\r
536                                         resline++;\r
537                                 }\r
538                         }\r
539                 }\r
540                 else if (tempdiff->type == svn_diff__type_diff_common)\r
541                 {\r
542                         ASSERT(tempdiff->latest_length == tempdiff->modified_length);\r
543                         //both theirs and yours have lines replaced\r
544                         for (int i=0; i<tempdiff->original_length; i++)\r
545                         {\r
546                                 if (m_arBaseFile.GetCount() > baseline)\r
547                                 {\r
548                                         m_Diff3.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));\r
549 \r
550                                         m_arDiff3LinesBase.Add(baseline);\r
551                                         m_arDiff3LinesYour.Add(yourline);\r
552                                         m_arDiff3LinesTheir.Add(theirline);\r
553 \r
554                                         m_YourBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
555                                         m_TheirBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
556 \r
557                                         baseline++;\r
558                                 }\r
559                         }\r
560                         for (int i=0; i<tempdiff->modified_length; i++)\r
561                         {\r
562                                 if ((m_arYourFile.GetCount() > yourline)&&(m_arTheirFile.GetCount() > theirline))\r
563                                 {\r
564                                         m_Diff3.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_IDENTICALADDED, resline, m_arYourFile.GetLineEnding(yourline));\r
565 \r
566                                         m_arDiff3LinesBase.Add(baseline);\r
567                                         m_arDiff3LinesYour.Add(yourline);\r
568                                         m_arDiff3LinesTheir.Add(theirline);\r
569 \r
570                                         m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_IDENTICALADDED, yourline, m_arYourFile.GetLineEnding(yourline));\r
571                                         m_TheirBaseBoth.AddData(m_arTheirFile.GetAt(theirline), DIFFSTATE_IDENTICALADDED, resline, m_arTheirFile.GetLineEnding(theirline));\r
572 \r
573                                         yourline++;\r
574                                         theirline++;\r
575                                         resline++;\r
576                                 }\r
577                         }\r
578                 }\r
579                 else if (tempdiff->type == svn_diff__type_conflict)\r
580                 {\r
581                         apr_off_t length = max(tempdiff->original_length, tempdiff->modified_length);\r
582                         length = max(tempdiff->latest_length, length);\r
583                         apr_off_t original = tempdiff->original_length;\r
584                         apr_off_t modified = tempdiff->modified_length;\r
585                         apr_off_t latest = tempdiff->latest_length;\r
586 \r
587                         apr_off_t originalresolved = 0;\r
588                         apr_off_t modifiedresolved = 0;\r
589                         apr_off_t latestresolved = 0;\r
590 \r
591                         LONG base = baseline;\r
592                         LONG your = yourline;\r
593                         LONG their = theirline;\r
594                         if (tempdiff->resolved_diff)\r
595                         {\r
596                                 originalresolved = tempdiff->resolved_diff->original_length;\r
597                                 modifiedresolved = tempdiff->resolved_diff->modified_length;\r
598                                 latestresolved = tempdiff->resolved_diff->latest_length;\r
599                         }\r
600                         for (int i=0; i<length; i++)\r
601                         {\r
602                                 if (original)\r
603                                 {\r
604                                         if (m_arBaseFile.GetCount() > baseline)\r
605                                         {\r
606                                                 m_Diff3.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));\r
607 \r
608                                                 m_arDiff3LinesBase.Add(baseline);\r
609                                                 m_arDiff3LinesYour.Add(yourline);\r
610                                                 m_arDiff3LinesTheir.Add(theirline);\r
611                                         }\r
612                                 }\r
613                                 else if ((originalresolved)||((modifiedresolved)&&(latestresolved)))\r
614                                 {\r
615                                         m_Diff3.AddData(_T(""), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
616 \r
617                                         m_arDiff3LinesBase.Add(baseline);\r
618                                         m_arDiff3LinesYour.Add(yourline);\r
619                                         m_arDiff3LinesTheir.Add(theirline);\r
620 \r
621                                 }\r
622                                 if ((latest)&&(original))\r
623                                 {\r
624                                         if (m_arBaseFile.GetCount() > baseline)\r
625                                         {\r
626                                                 m_YourBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));\r
627                                         }\r
628                                 }\r
629                                 else\r
630                                 {\r
631                                         if (original)\r
632                                         {\r
633                                                 if (m_arBaseFile.GetCount() > baseline)\r
634                                                 {\r
635                                                         m_YourBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));\r
636                                                 }\r
637                                         }\r
638                                         else if ((latestresolved)&&(modifiedresolved))\r
639                                         {\r
640                                                 m_YourBaseBoth.AddData(_T(""), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
641                                         }\r
642                                 }\r
643                                 if ((modified)&&(original))\r
644                                 {\r
645                                         if (m_arBaseFile.GetCount() > baseline)\r
646                                         {\r
647                                                 m_TheirBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));\r
648                                         }\r
649                                 }\r
650                                 else\r
651                                 {\r
652                                         if (original)\r
653                                         {\r
654                                                 if (m_arBaseFile.GetCount() > baseline)\r
655                                                 {\r
656                                                         m_TheirBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));\r
657                                                 }\r
658                                         }\r
659                                         else if ((modifiedresolved)&&(latestresolved))\r
660                                         {\r
661                                                 m_TheirBaseBoth.AddData(_T(""), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
662                                         }\r
663                                 }\r
664                                 if (original)\r
665                                 {\r
666                                         original--;\r
667                                         baseline++;\r
668                                 }\r
669                                 if (originalresolved)\r
670                                         originalresolved--;\r
671 \r
672                                 if (modified)\r
673                                 {\r
674                                         modified--;\r
675                                         theirline++;\r
676                                 }\r
677                                 if (modifiedresolved)\r
678                                         modifiedresolved--;\r
679                                 if (latest)\r
680                                 {\r
681                                         latest--;\r
682                                         yourline++;\r
683                                 }\r
684                                 if (latestresolved)\r
685                                         latestresolved--;\r
686                         }\r
687                         original = tempdiff->original_length;\r
688                         modified = tempdiff->modified_length;\r
689                         latest = tempdiff->latest_length;\r
690                         baseline = base;\r
691                         yourline = your;\r
692                         theirline = their;\r
693                         if (tempdiff->resolved_diff)\r
694                         {\r
695                                 originalresolved = tempdiff->resolved_diff->original_length;\r
696                                 modifiedresolved = tempdiff->resolved_diff->modified_length;\r
697                                 latestresolved = tempdiff->resolved_diff->latest_length;\r
698                         }\r
699                         for (int i=0; i<length; i++)\r
700                         {\r
701                                 if ((latest)||(modified))\r
702                                 {\r
703                                         m_Diff3.AddData(_T(""), DIFFSTATE_CONFLICTED, resline, EOL_NOENDING);\r
704 \r
705                                         m_arDiff3LinesBase.Add(baseline);\r
706                                         m_arDiff3LinesYour.Add(yourline);\r
707                                         m_arDiff3LinesTheir.Add(theirline);\r
708 \r
709                                         resline++;\r
710                                 }\r
711 \r
712                                 if (latest)\r
713                                 {\r
714                                         if (m_arYourFile.GetCount() > yourline)\r
715                                         {\r
716                                                 m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_CONFLICTADDED, yourline, m_arYourFile.GetLineEnding(yourline));\r
717                                         }\r
718                                 }\r
719                                 else if ((latestresolved)||(modified)||(modifiedresolved))\r
720                                 {\r
721                                         m_YourBaseBoth.AddData(_T(""), DIFFSTATE_CONFLICTEMPTY, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
722                                 }\r
723                                 if (modified)\r
724                                 {\r
725                                         if (m_arTheirFile.GetCount() > theirline)\r
726                                         {\r
727                                                 m_TheirBaseBoth.AddData(m_arTheirFile.GetAt(theirline), DIFFSTATE_CONFLICTADDED, theirline, m_arTheirFile.GetLineEnding(theirline));\r
728                                         }\r
729                                 }\r
730                                 else if ((modifiedresolved)||(latest)||(latestresolved))\r
731                                 {\r
732                                         m_TheirBaseBoth.AddData(_T(""), DIFFSTATE_CONFLICTEMPTY, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
733                                 }\r
734                                 if (original)\r
735                                 {\r
736                                         original--;\r
737                                         baseline++;\r
738                                 }\r
739                                 if (originalresolved)\r
740                                         originalresolved--;\r
741                                 if (modified)\r
742                                 {\r
743                                         modified--;\r
744                                         theirline++;\r
745                                 }\r
746                                 if (modifiedresolved)\r
747                                         modifiedresolved--;\r
748                                 if (latest)\r
749                                 {\r
750                                         latest--;\r
751                                         yourline++;\r
752                                 }\r
753                                 if (latestresolved)\r
754                                         latestresolved--;\r
755                         }\r
756                 }\r
757                 else if (tempdiff->type == svn_diff__type_diff_modified)\r
758                 {\r
759                         //deleted!\r
760                         for (int i=0; i<tempdiff->original_length; i++)\r
761                         {\r
762                                 if ((m_arBaseFile.GetCount() > baseline)&&(m_arYourFile.GetCount() > yourline))\r
763                                 {\r
764                                         m_Diff3.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_THEIRSREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));\r
765 \r
766                                         m_arDiff3LinesBase.Add(baseline);\r
767                                         m_arDiff3LinesYour.Add(yourline);\r
768                                         m_arDiff3LinesTheir.Add(theirline);\r
769 \r
770                                         m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_NORMAL, yourline, m_arYourFile.GetLineEnding(yourline));\r
771                                         m_TheirBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_THEIRSREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
772                                         baseline++;\r
773                                         yourline++;\r
774                                 }\r
775                         }\r
776                         //added\r
777                         for (int i=0; i<tempdiff->modified_length; i++)\r
778                         {\r
779                                 if (m_arTheirFile.GetCount() > theirline)\r
780                                 {\r
781                                         m_Diff3.AddData(m_arTheirFile.GetAt(theirline), DIFFSTATE_THEIRSADDED, resline, m_arTheirFile.GetLineEnding(theirline));\r
782 \r
783                                         m_arDiff3LinesBase.Add(baseline);\r
784                                         m_arDiff3LinesYour.Add(yourline);\r
785                                         m_arDiff3LinesTheir.Add(theirline);\r
786 \r
787                                         m_YourBaseBoth.AddData(_T(""), DIFFSTATE_EMPTY, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
788                                         m_TheirBaseBoth.AddData(m_arTheirFile.GetAt(theirline), DIFFSTATE_THEIRSADDED, theirline, m_arTheirFile.GetLineEnding(theirline));\r
789 \r
790                                         theirline++;\r
791                                         resline++;\r
792                                 }\r
793                         }\r
794                 }\r
795                 else if (tempdiff->type == svn_diff__type_diff_latest)\r
796                 {\r
797                         //YOURS differs from base\r
798 \r
799                         for (int i=0; i<tempdiff->original_length; i++)\r
800                         {\r
801                                 if ((m_arBaseFile.GetCount() > baseline)&&(m_arTheirFile.GetCount() > theirline))\r
802                                 {\r
803                                         m_Diff3.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_YOURSREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));\r
804 \r
805                                         m_arDiff3LinesBase.Add(baseline);\r
806                                         m_arDiff3LinesYour.Add(yourline);\r
807                                         m_arDiff3LinesTheir.Add(theirline);\r
808 \r
809                                         m_YourBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_YOURSREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));\r
810                                         m_TheirBaseBoth.AddData(m_arTheirFile.GetAt(theirline), DIFFSTATE_NORMAL, theirline, m_arTheirFile.GetLineEnding(theirline));\r
811 \r
812                                         baseline++;\r
813                                         theirline++;\r
814                                 }\r
815                         }\r
816                         for (int i=0; i<tempdiff->latest_length; i++)\r
817                         {\r
818                                 if (m_arYourFile.GetCount() > yourline)\r
819                                 {\r
820                                         m_Diff3.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_YOURSADDED, resline, m_arYourFile.GetLineEnding(yourline));\r
821 \r
822                                         m_arDiff3LinesBase.Add(baseline);\r
823                                         m_arDiff3LinesYour.Add(yourline);\r
824                                         m_arDiff3LinesTheir.Add(theirline);\r
825 \r
826                                         m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_IDENTICALADDED, yourline, m_arYourFile.GetLineEnding(yourline));\r
827                                         m_TheirBaseBoth.AddData(_T(""), DIFFSTATE_EMPTY, DIFF_EMPTYLINENUMBER, EOL_NOENDING);\r
828 \r
829                                         yourline++;\r
830                                         resline++;\r
831                                 }\r
832                         }\r
833                 }\r
834                 else\r
835                 {\r
836                         TRACE(_T("something bad happened during diff!\n"));\r
837                 }\r
838                 tempdiff = tempdiff->next;\r
839 \r
840         } // while (tempdiff)\r
841 \r
842         if ((options->ignore_space != svn_diff_file_ignore_space_none)||(bIgnoreCase)||(bIgnoreEOL))\r
843         {\r
844                 // If whitespaces are ignored, a conflict could have been missed\r
845                 // We now go through all lines again and check if they're identical.\r
846                 // If they're not, then that means it is a conflict, and we\r
847                 // mark the conflict with the proper colors.\r
848                 for (long i=0; i<m_Diff3.GetCount(); ++i)\r
849                 {\r
850                         DiffStates state1 = m_YourBaseBoth.GetState(i);\r
851                         DiffStates state2 = m_TheirBaseBoth.GetState(i);\r
852 \r
853                         if (((state1 == DIFFSTATE_IDENTICALADDED)||(state1 == DIFFSTATE_NORMAL))&&\r
854                                 ((state2 == DIFFSTATE_IDENTICALADDED)||(state2 == DIFFSTATE_NORMAL)))\r
855                         {\r
856                                 LONG lineyour = m_arDiff3LinesYour.GetAt(i);\r
857                                 LONG linetheir = m_arDiff3LinesTheir.GetAt(i);\r
858                                 LONG linebase = m_arDiff3LinesBase.GetAt(i);\r
859                                 if ((lineyour < m_arYourFile.GetCount()) &&\r
860                                         (linetheir < m_arTheirFile.GetCount()) &&\r
861                                         (linebase < m_arBaseFile.GetCount()))\r
862                                 {\r
863                                         if (((m_arYourFile.GetLineEnding(lineyour)!=m_arBaseFile.GetLineEnding(linebase))&&\r
864                                                 (m_arTheirFile.GetLineEnding(linetheir)!=m_arBaseFile.GetLineEnding(linebase))&&\r
865                                                 (m_arYourFile.GetLineEnding(lineyour)!=m_arTheirFile.GetLineEnding(linetheir))) ||\r
866                                                 ((m_arYourFile.GetAt(lineyour).Compare(m_arBaseFile.GetAt(linebase))!=0)&&\r
867                                                 (m_arTheirFile.GetAt(linetheir).Compare(m_arBaseFile.GetAt(linebase))!=0)&&\r
868                                                 (m_arYourFile.GetAt(lineyour).Compare(m_arTheirFile.GetAt(linetheir))!=0)))\r
869                                         {\r
870                                                 m_Diff3.SetState(i, DIFFSTATE_CONFLICTED_IGNORED);\r
871                                                 m_YourBaseBoth.SetState(i, DIFFSTATE_CONFLICTADDED);\r
872                                                 m_TheirBaseBoth.SetState(i, DIFFSTATE_CONFLICTADDED);\r
873                                         }\r
874                                 }\r
875                         }\r
876                 }\r
877         }\r
878         ASSERT(m_Diff3.GetCount() == m_YourBaseBoth.GetCount());\r
879         ASSERT(m_TheirBaseBoth.GetCount() == m_YourBaseBoth.GetCount());\r
880 \r
881         TRACE(_T("done with 3-way diff\n"));\r
882         return true;\r
883 }\r