OSDN Git Service

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