1 // TortoiseMerge - a Diff/Patch program
\r
3 // Copyright (C) 2006-2008 - TortoiseSVN
\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
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
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
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 "GitAdminDir.h"
\r
29 #pragma warning(push)
\r
30 #pragma warning(disable: 4702) // unreachable code
\r
31 int CDiffData::abort_on_pool_failure (int /*retcode*/)
\r
36 #pragma warning(pop)
\r
38 CDiffData::CDiffData(void)
\r
40 // apr_initialize();
\r
41 // svn_dso_initialize();
\r
42 // g_SVNAdminDir.Init();
\r
46 m_sPatchOriginal = _T(": original");
\r
47 m_sPatchPatched = _T(": patched");
\r
50 CDiffData::~CDiffData(void)
\r
52 //// g_SVNAdminDir.Close();
\r
56 int CDiffData::GetLineCount()
\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
65 int CDiffData::GetLineActualLength(int index)
\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
77 LPCTSTR CDiffData::GetLineChars(int index)
\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
88 BOOL CDiffData::Load()
\r
91 CString sConvertedBaseFilename, sConvertedTheirFilename, sConvertedYourFilename;
\r
94 apr_pool_create_ex (&pool, NULL, abort_on_pool_failure, NULL);
\r
96 m_arBaseFile.RemoveAll();
\r
97 m_arYourFile.RemoveAll();
\r
98 m_arTheirFile.RemoveAll();
\r
100 m_YourBaseBoth.Clear();
\r
101 m_YourBaseLeft.Clear();
\r
102 m_YourBaseRight.Clear();
\r
104 m_TheirBaseBoth.Clear();
\r
105 m_TheirBaseLeft.Clear();
\r
106 m_TheirBaseRight.Clear();
\r
110 m_arDiff3LinesBase.RemoveAll();
\r
111 m_arDiff3LinesYour.RemoveAll();
\r
112 m_arDiff3LinesTheir.RemoveAll();
\r
114 CTempFiles tempfiles;
\r
115 CRegDWORD regIgnoreWS = CRegDWORD(_T("Software\\TortoiseMerge\\IgnoreWS"));
\r
116 CRegDWORD regIgnoreEOL = CRegDWORD(_T("Software\\TortoiseMerge\\IgnoreEOL"), TRUE);
\r
117 CRegDWORD regIgnoreCase = CRegDWORD(_T("Software\\TortoiseMerge\\CaseInsensitive"), FALSE);
\r
118 DWORD dwIgnoreWS = regIgnoreWS;
\r
119 bool bIgnoreEOL = ((DWORD)regIgnoreEOL)!=0;
\r
120 BOOL bIgnoreCase = ((DWORD)regIgnoreCase)!=0;
\r
122 // The Subversion diff API only can ignore whitespaces and eol styles.
\r
123 // It also can only handle one-byte charsets.
\r
124 // To ignore case changes or to handle UTF-16 files, we have to
\r
125 // save the original file in UTF-8 and/or the letters changed to lowercase
\r
126 // so the Subversion diff can handle those.
\r
127 sConvertedBaseFilename = m_baseFile.GetFilename();
\r
128 sConvertedYourFilename = m_yourFile.GetFilename();
\r
129 sConvertedTheirFilename = m_theirFile.GetFilename();
\r
130 if (IsBaseFileInUse())
\r
132 if (!m_arBaseFile.Load(m_baseFile.GetFilename()))
\r
134 m_sError = m_arBaseFile.GetErrorString();
\r
137 if ((bIgnoreCase)||(m_arBaseFile.GetUnicodeType() == CFileTextLines::UNICODE_LE))
\r
139 CFileTextLines converted(m_arBaseFile);
\r
140 sConvertedBaseFilename = tempfiles.GetTempFilePath();
\r
141 converted.Save(sConvertedBaseFilename, m_arBaseFile.GetUnicodeType() == CFileTextLines::UNICODE_LE, dwIgnoreWS, bIgnoreCase, m_bBlame);
\r
145 if (IsTheirFileInUse())
\r
147 // m_arBaseFile.GetCount() is passed as a hint for the number of lines in this file
\r
148 // It's a fair guess that the files will be roughly the same size
\r
149 if (!m_arTheirFile.Load(m_theirFile.GetFilename(),m_arBaseFile.GetCount()))
\r
151 m_sError = m_arTheirFile.GetErrorString();
\r
154 if ((bIgnoreCase)||(m_arTheirFile.GetUnicodeType() == CFileTextLines::UNICODE_LE))
\r
156 CFileTextLines converted(m_arTheirFile);
\r
157 sConvertedTheirFilename = tempfiles.GetTempFilePath();
\r
158 converted.Save(sConvertedTheirFilename, m_arTheirFile.GetUnicodeType() == CFileTextLines::UNICODE_LE, dwIgnoreWS, bIgnoreCase, m_bBlame);
\r
162 if (IsYourFileInUse())
\r
164 // m_arBaseFile.GetCount() is passed as a hint for the number of lines in this file
\r
165 // It's a fair guess that the files will be roughly the same size
\r
166 if (!m_arYourFile.Load(m_yourFile.GetFilename(),m_arBaseFile.GetCount()))
\r
168 m_sError = m_arYourFile.GetErrorString();
\r
171 if ((bIgnoreCase)||(m_arYourFile.GetUnicodeType() == CFileTextLines::UNICODE_LE))
\r
173 CFileTextLines converted(m_arYourFile);
\r
174 sConvertedYourFilename = tempfiles.GetTempFilePath();
\r
175 converted.Save(sConvertedYourFilename, m_arYourFile.GetUnicodeType() == CFileTextLines::UNICODE_LE, dwIgnoreWS, bIgnoreCase, m_bBlame);
\r
179 // Calculate the number of lines in the largest of the three files
\r
180 int lengthHint = max(m_arBaseFile.GetCount(), m_arTheirFile.GetCount());
\r
181 lengthHint = max(lengthHint, m_arYourFile.GetCount());
\r
183 m_YourBaseBoth.Reserve(lengthHint);
\r
184 m_YourBaseLeft.Reserve(lengthHint);
\r
185 m_YourBaseRight.Reserve(lengthHint);
\r
187 m_TheirBaseBoth.Reserve(lengthHint);
\r
188 m_TheirBaseLeft.Reserve(lengthHint);
\r
189 m_TheirBaseRight.Reserve(lengthHint);
\r
191 m_arDiff3LinesBase.Reserve(lengthHint);
\r
192 m_arDiff3LinesYour.Reserve(lengthHint);
\r
193 m_arDiff3LinesTheir.Reserve(lengthHint);
\r
195 // Is this a two-way diff?
\r
196 if (IsBaseFileInUse() && IsYourFileInUse() && !IsTheirFileInUse())
\r
198 if (!DoTwoWayDiff(sConvertedBaseFilename, sConvertedYourFilename, dwIgnoreWS, bIgnoreEOL, pool))
\r
200 apr_pool_destroy (pool); // free the allocated memory
\r
205 if (IsBaseFileInUse() && IsTheirFileInUse() && !IsYourFileInUse())
\r
210 if (IsBaseFileInUse() && IsTheirFileInUse() && IsYourFileInUse())
\r
212 m_Diff3.Reserve(lengthHint);
\r
214 if (!DoThreeWayDiff(sConvertedBaseFilename, sConvertedYourFilename, sConvertedTheirFilename, dwIgnoreWS, bIgnoreEOL, !!bIgnoreCase, pool))
\r
216 apr_pool_destroy (pool); // free the allocated memory
\r
221 apr_pool_destroy (pool); // free the allocated memory
\r
229 CDiffData::DoTwoWayDiff(const CString& sBaseFilename, const CString& sYourFilename, DWORD dwIgnoreWS, bool bIgnoreEOL)
\r
231 // convert CString filenames (UTF-16 or ANSI) to UTF-8
\r
232 CStringA sBaseFilenameUtf8 = CUnicodeUtils::GetUTF8(sBaseFilename);
\r
233 CStringA sYourFilenameUtf8 = CUnicodeUtils::GetUTF8(sYourFilename);
\r
236 svn_diff_t * diffYourBase = NULL;
\r
237 svn_error_t * svnerr = NULL;
\r
238 svn_diff_file_options_t * options = svn_diff_file_options_create(pool);
\r
239 options->ignore_eol_style = bIgnoreEOL;
\r
240 options->ignore_space = svn_diff_file_ignore_space_none;
\r
241 switch (dwIgnoreWS)
\r
244 options->ignore_space = svn_diff_file_ignore_space_none;
\r
247 options->ignore_space = svn_diff_file_ignore_space_all;
\r
250 options->ignore_space = svn_diff_file_ignore_space_change;
\r
254 svnerr = svn_diff_file_diff_2(&diffYourBase, sBaseFilenameUtf8, sYourFilenameUtf8, options, pool);
\r
257 TRACE(_T("diff-error in CDiffData::Load()\n"));
\r
258 CString sMsg = CString(svnerr->message);
\r
259 while (svnerr->child)
\r
261 svnerr = svnerr->child;
\r
263 sMsg += CString(svnerr->message);
\r
265 m_sError.Format(IDS_ERR_DIFF_DIFF, (LPCTSTR)sMsg);
\r
266 svn_error_clear(svnerr);
\r
269 svn_diff_t * tempdiff = diffYourBase;
\r
275 for (int i=0; i<tempdiff->original_length; i++)
\r
277 if (baseline >= m_arBaseFile.GetCount())
\r
279 m_sError.LoadString(IDS_ERR_DIFF_NEWLINES);
\r
282 const CString& sCurrentBaseLine = m_arBaseFile.GetAt(baseline);
\r
283 EOL endingBase = m_arBaseFile.GetLineEnding(baseline);
\r
284 if (tempdiff->type == svn_diff__type_common)
\r
286 if (yourline >= m_arYourFile.GetCount())
\r
288 m_sError.LoadString(IDS_ERR_DIFF_NEWLINES);
\r
291 const CString& sCurrentYourLine = m_arYourFile.GetAt(yourline);
\r
292 EOL endingYours = m_arYourFile.GetLineEnding(yourline);
\r
293 if (sCurrentBaseLine != sCurrentYourLine)
\r
295 if (dwIgnoreWS == 2 || dwIgnoreWS == 3)
\r
297 CString s1 = m_arBaseFile.GetAt(baseline);
\r
298 CString s2 = sCurrentYourLine;
\r
300 if ( dwIgnoreWS == 2 )
\r
302 s1.TrimLeft(_T(" \t"));
\r
303 s2.TrimLeft(_T(" \t"));
\r
307 s1.TrimRight(_T(" \t"));
\r
308 s2.TrimRight(_T(" \t"));
\r
313 // one-pane view: two lines, one 'removed' and one 'added'
\r
314 m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_REMOVEDWHITESPACE, yourline, endingBase);
\r
315 m_YourBaseBoth.AddData(sCurrentYourLine, DIFFSTATE_ADDEDWHITESPACE, yourline, endingYours);
\r
319 m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, yourline, endingBase);
\r
322 else if (dwIgnoreWS == 0)
\r
324 m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_REMOVEDWHITESPACE, yourline, endingBase);
\r
325 m_YourBaseBoth.AddData(sCurrentYourLine, DIFFSTATE_ADDEDWHITESPACE, yourline, endingYours);
\r
329 m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, yourline, endingBase);
\r
334 m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, yourline, endingBase);
\r
336 yourline++; //in both files
\r
340 m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_REMOVED, yourline, endingBase);
\r
344 if (tempdiff->type == svn_diff__type_diff_modified)
\r
346 for (int i=0; i<tempdiff->modified_length; i++)
\r
348 if (m_arYourFile.GetCount() > yourline)
\r
350 m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_ADDED, yourline, m_arYourFile.GetLineEnding(yourline));
\r
355 tempdiff = tempdiff->next;
\r
358 tempdiff = diffYourBase;
\r
363 if (tempdiff->type == svn_diff__type_common)
\r
365 for (int i=0; i<tempdiff->original_length; i++)
\r
367 const CString& sCurrentYourLine = m_arYourFile.GetAt(yourline);
\r
368 EOL endingYours = m_arYourFile.GetLineEnding(yourline);
\r
369 const CString& sCurrentBaseLine = m_arBaseFile.GetAt(baseline);
\r
370 EOL endingBase = m_arBaseFile.GetLineEnding(baseline);
\r
371 if (sCurrentBaseLine != sCurrentYourLine)
\r
373 if (dwIgnoreWS == 2 || dwIgnoreWS == 3)
\r
375 CString s1 = sCurrentBaseLine;
\r
376 CString s2 = sCurrentYourLine;
\r
377 if ( dwIgnoreWS == 2 )
\r
379 s1 = s1.TrimLeft(_T(" \t"));
\r
380 s2 = s2.TrimLeft(_T(" \t"));
\r
384 s1 = s1.TrimRight(_T(" \t"));
\r
385 s2 = s2.TrimRight(_T(" \t"));
\r
390 m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_WHITESPACE, baseline, endingBase);
\r
391 m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_WHITESPACE, yourline, endingYours);
\r
395 m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, baseline, endingBase);
\r
396 m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_NORMAL, yourline, endingYours);
\r
399 else if (dwIgnoreWS == 0)
\r
401 m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_WHITESPACE, baseline, endingBase);
\r
402 m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_WHITESPACE, yourline, endingYours);
\r
406 m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, baseline, endingBase);
\r
407 m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_NORMAL, yourline, endingYours);
\r
412 m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, baseline, endingBase);
\r
413 m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_NORMAL, yourline, endingYours);
\r
419 if (tempdiff->type == svn_diff__type_diff_modified)
\r
421 apr_off_t original_length = tempdiff->original_length;
\r
422 for (int i=0; i<tempdiff->modified_length; i++)
\r
424 if (m_arYourFile.GetCount() > yourline)
\r
426 EOL endingYours = m_arYourFile.GetLineEnding(yourline);
\r
427 if (original_length-- <= 0)
\r
429 m_YourBaseLeft.AddData(_T(""), DIFFSTATE_EMPTY, DIFF_EMPTYLINENUMBER, EOL_NOENDING);
\r
430 m_YourBaseRight.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_ADDED, yourline, endingYours);
\r
434 EOL endingBase = m_arBaseFile.GetLineEnding(baseline);
\r
435 m_YourBaseLeft.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_REMOVED, baseline, endingBase);
\r
436 m_YourBaseRight.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_ADDED, yourline, endingYours);
\r
442 apr_off_t modified_length = tempdiff->modified_length;
\r
443 for (int i=0; i<tempdiff->original_length; i++)
\r
445 if (modified_length-- <= 0)
\r
447 if (m_arBaseFile.GetCount() > baseline)
\r
449 EOL endingBase = m_arBaseFile.GetLineEnding(baseline);
\r
450 m_YourBaseLeft.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_REMOVED, baseline, endingBase);
\r
451 m_YourBaseRight.AddData(_T(""), DIFFSTATE_EMPTY, DIFF_EMPTYLINENUMBER, EOL_NOENDING);
\r
457 tempdiff = tempdiff->next;
\r
459 TRACE(_T("done with 2-way diff\n"));
\r
465 CDiffData::DoThreeWayDiff(const CString& sBaseFilename, const CString& sYourFilename, const CString& sTheirFilename, DWORD dwIgnoreWS, bool bIgnoreEOL, bool bIgnoreCase)
\r
467 // convert CString filenames (UTF-16 or ANSI) to UTF-8
\r
468 CStringA sBaseFilenameUtf8 = CUnicodeUtils::GetUTF8(sBaseFilename);
\r
469 CStringA sYourFilenameUtf8 = CUnicodeUtils::GetUTF8(sYourFilename);
\r
470 CStringA sTheirFilenameUtf8 = CUnicodeUtils::GetUTF8(sTheirFilename);
\r
472 svn_diff_t * diffTheirYourBase = NULL;
\r
473 svn_diff_file_options_t * options = svn_diff_file_options_create(pool);
\r
474 options->ignore_eol_style = bIgnoreEOL;
\r
475 options->ignore_space = svn_diff_file_ignore_space_none;
\r
476 switch (dwIgnoreWS)
\r
479 options->ignore_space = svn_diff_file_ignore_space_none;
\r
482 options->ignore_space = svn_diff_file_ignore_space_all;
\r
485 options->ignore_space = svn_diff_file_ignore_space_change;
\r
488 svn_error_t * svnerr = svn_diff_file_diff3_2(&diffTheirYourBase, sBaseFilenameUtf8, sTheirFilenameUtf8, sYourFilenameUtf8, options, pool);
\r
491 TRACE(_T("diff-error in CDiffData::Load()\n"));
\r
492 CString sMsg = CString(svnerr->message);
\r
493 while (svnerr->child)
\r
495 svnerr = svnerr->child;
\r
497 sMsg += CString(svnerr->message);
\r
499 m_sError.Format(IDS_ERR_DIFF_DIFF, (LPCTSTR)sMsg);
\r
500 svn_error_clear(svnerr);
\r
504 svn_diff_t * tempdiff = diffTheirYourBase;
\r
507 LONG theirline = 0;
\r
511 if (tempdiff->type == svn_diff__type_common)
\r
513 ASSERT((tempdiff->latest_length == tempdiff->modified_length) && (tempdiff->modified_length == tempdiff->original_length));
\r
514 for (int i=0; i<tempdiff->original_length; i++)
\r
516 if ((m_arYourFile.GetCount() > yourline)&&(m_arTheirFile.GetCount() > theirline))
\r
518 m_Diff3.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_NORMAL, resline, m_arYourFile.GetLineEnding(yourline));
\r
520 m_arDiff3LinesBase.Add(baseline);
\r
521 m_arDiff3LinesYour.Add(yourline);
\r
522 m_arDiff3LinesTheir.Add(theirline);
\r
524 m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_NORMAL, yourline, m_arYourFile.GetLineEnding(yourline));
\r
525 m_TheirBaseBoth.AddData(m_arTheirFile.GetAt(theirline), DIFFSTATE_NORMAL, theirline, m_arTheirFile.GetLineEnding(theirline));
\r
534 else if (tempdiff->type == svn_diff__type_diff_common)
\r
536 ASSERT(tempdiff->latest_length == tempdiff->modified_length);
\r
537 //both theirs and yours have lines replaced
\r
538 for (int i=0; i<tempdiff->original_length; i++)
\r
540 if (m_arBaseFile.GetCount() > baseline)
\r
542 m_Diff3.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));
\r
544 m_arDiff3LinesBase.Add(baseline);
\r
545 m_arDiff3LinesYour.Add(yourline);
\r
546 m_arDiff3LinesTheir.Add(theirline);
\r
548 m_YourBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);
\r
549 m_TheirBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);
\r
554 for (int i=0; i<tempdiff->modified_length; i++)
\r
556 if ((m_arYourFile.GetCount() > yourline)&&(m_arTheirFile.GetCount() > theirline))
\r
558 m_Diff3.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_IDENTICALADDED, resline, m_arYourFile.GetLineEnding(yourline));
\r
560 m_arDiff3LinesBase.Add(baseline);
\r
561 m_arDiff3LinesYour.Add(yourline);
\r
562 m_arDiff3LinesTheir.Add(theirline);
\r
564 m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_IDENTICALADDED, yourline, m_arYourFile.GetLineEnding(yourline));
\r
565 m_TheirBaseBoth.AddData(m_arTheirFile.GetAt(theirline), DIFFSTATE_IDENTICALADDED, resline, m_arTheirFile.GetLineEnding(theirline));
\r
573 else if (tempdiff->type == svn_diff__type_conflict)
\r
575 apr_off_t length = max(tempdiff->original_length, tempdiff->modified_length);
\r
576 length = max(tempdiff->latest_length, length);
\r
577 apr_off_t original = tempdiff->original_length;
\r
578 apr_off_t modified = tempdiff->modified_length;
\r
579 apr_off_t latest = tempdiff->latest_length;
\r
581 apr_off_t originalresolved = 0;
\r
582 apr_off_t modifiedresolved = 0;
\r
583 apr_off_t latestresolved = 0;
\r
585 LONG base = baseline;
\r
586 LONG your = yourline;
\r
587 LONG their = theirline;
\r
588 if (tempdiff->resolved_diff)
\r
590 originalresolved = tempdiff->resolved_diff->original_length;
\r
591 modifiedresolved = tempdiff->resolved_diff->modified_length;
\r
592 latestresolved = tempdiff->resolved_diff->latest_length;
\r
594 for (int i=0; i<length; i++)
\r
598 if (m_arBaseFile.GetCount() > baseline)
\r
600 m_Diff3.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));
\r
602 m_arDiff3LinesBase.Add(baseline);
\r
603 m_arDiff3LinesYour.Add(yourline);
\r
604 m_arDiff3LinesTheir.Add(theirline);
\r
607 else if ((originalresolved)||((modifiedresolved)&&(latestresolved)))
\r
609 m_Diff3.AddData(_T(""), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);
\r
611 m_arDiff3LinesBase.Add(baseline);
\r
612 m_arDiff3LinesYour.Add(yourline);
\r
613 m_arDiff3LinesTheir.Add(theirline);
\r
616 if ((latest)&&(original))
\r
618 if (m_arBaseFile.GetCount() > baseline)
\r
620 m_YourBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));
\r
627 if (m_arBaseFile.GetCount() > baseline)
\r
629 m_YourBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));
\r
632 else if ((latestresolved)&&(modifiedresolved))
\r
634 m_YourBaseBoth.AddData(_T(""), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);
\r
637 if ((modified)&&(original))
\r
639 if (m_arBaseFile.GetCount() > baseline)
\r
641 m_TheirBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));
\r
648 if (m_arBaseFile.GetCount() > baseline)
\r
650 m_TheirBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));
\r
653 else if ((modifiedresolved)&&(latestresolved))
\r
655 m_TheirBaseBoth.AddData(_T(""), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);
\r
663 if (originalresolved)
\r
664 originalresolved--;
\r
671 if (modifiedresolved)
\r
672 modifiedresolved--;
\r
678 if (latestresolved)
\r
681 original = tempdiff->original_length;
\r
682 modified = tempdiff->modified_length;
\r
683 latest = tempdiff->latest_length;
\r
687 if (tempdiff->resolved_diff)
\r
689 originalresolved = tempdiff->resolved_diff->original_length;
\r
690 modifiedresolved = tempdiff->resolved_diff->modified_length;
\r
691 latestresolved = tempdiff->resolved_diff->latest_length;
\r
693 for (int i=0; i<length; i++)
\r
695 if ((latest)||(modified))
\r
697 m_Diff3.AddData(_T(""), DIFFSTATE_CONFLICTED, resline, EOL_NOENDING);
\r
699 m_arDiff3LinesBase.Add(baseline);
\r
700 m_arDiff3LinesYour.Add(yourline);
\r
701 m_arDiff3LinesTheir.Add(theirline);
\r
708 if (m_arYourFile.GetCount() > yourline)
\r
710 m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_CONFLICTADDED, yourline, m_arYourFile.GetLineEnding(yourline));
\r
713 else if ((latestresolved)||(modified)||(modifiedresolved))
\r
715 m_YourBaseBoth.AddData(_T(""), DIFFSTATE_CONFLICTEMPTY, DIFF_EMPTYLINENUMBER, EOL_NOENDING);
\r
719 if (m_arTheirFile.GetCount() > theirline)
\r
721 m_TheirBaseBoth.AddData(m_arTheirFile.GetAt(theirline), DIFFSTATE_CONFLICTADDED, theirline, m_arTheirFile.GetLineEnding(theirline));
\r
724 else if ((modifiedresolved)||(latest)||(latestresolved))
\r
726 m_TheirBaseBoth.AddData(_T(""), DIFFSTATE_CONFLICTEMPTY, DIFF_EMPTYLINENUMBER, EOL_NOENDING);
\r
733 if (originalresolved)
\r
734 originalresolved--;
\r
740 if (modifiedresolved)
\r
741 modifiedresolved--;
\r
747 if (latestresolved)
\r
751 else if (tempdiff->type == svn_diff__type_diff_modified)
\r
754 for (int i=0; i<tempdiff->original_length; i++)
\r
756 if ((m_arBaseFile.GetCount() > baseline)&&(m_arYourFile.GetCount() > yourline))
\r
758 m_Diff3.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_THEIRSREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));
\r
760 m_arDiff3LinesBase.Add(baseline);
\r
761 m_arDiff3LinesYour.Add(yourline);
\r
762 m_arDiff3LinesTheir.Add(theirline);
\r
764 m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_NORMAL, yourline, m_arYourFile.GetLineEnding(yourline));
\r
765 m_TheirBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_THEIRSREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);
\r
771 for (int i=0; i<tempdiff->modified_length; i++)
\r
773 if (m_arTheirFile.GetCount() > theirline)
\r
775 m_Diff3.AddData(m_arTheirFile.GetAt(theirline), DIFFSTATE_THEIRSADDED, resline, m_arTheirFile.GetLineEnding(theirline));
\r
777 m_arDiff3LinesBase.Add(baseline);
\r
778 m_arDiff3LinesYour.Add(yourline);
\r
779 m_arDiff3LinesTheir.Add(theirline);
\r
781 m_YourBaseBoth.AddData(_T(""), DIFFSTATE_EMPTY, DIFF_EMPTYLINENUMBER, EOL_NOENDING);
\r
782 m_TheirBaseBoth.AddData(m_arTheirFile.GetAt(theirline), DIFFSTATE_THEIRSADDED, theirline, m_arTheirFile.GetLineEnding(theirline));
\r
789 else if (tempdiff->type == svn_diff__type_diff_latest)
\r
791 //YOURS differs from base
\r
793 for (int i=0; i<tempdiff->original_length; i++)
\r
795 if ((m_arBaseFile.GetCount() > baseline)&&(m_arTheirFile.GetCount() > theirline))
\r
797 m_Diff3.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_YOURSREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));
\r
799 m_arDiff3LinesBase.Add(baseline);
\r
800 m_arDiff3LinesYour.Add(yourline);
\r
801 m_arDiff3LinesTheir.Add(theirline);
\r
803 m_YourBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_YOURSREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));
\r
804 m_TheirBaseBoth.AddData(m_arTheirFile.GetAt(theirline), DIFFSTATE_NORMAL, theirline, m_arTheirFile.GetLineEnding(theirline));
\r
810 for (int i=0; i<tempdiff->latest_length; i++)
\r
812 if (m_arYourFile.GetCount() > yourline)
\r
814 m_Diff3.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_YOURSADDED, resline, m_arYourFile.GetLineEnding(yourline));
\r
816 m_arDiff3LinesBase.Add(baseline);
\r
817 m_arDiff3LinesYour.Add(yourline);
\r
818 m_arDiff3LinesTheir.Add(theirline);
\r
820 m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_IDENTICALADDED, yourline, m_arYourFile.GetLineEnding(yourline));
\r
821 m_TheirBaseBoth.AddData(_T(""), DIFFSTATE_EMPTY, DIFF_EMPTYLINENUMBER, EOL_NOENDING);
\r
830 TRACE(_T("something bad happened during diff!\n"));
\r
832 tempdiff = tempdiff->next;
\r
834 } // while (tempdiff)
\r
836 if ((options->ignore_space != svn_diff_file_ignore_space_none)||(bIgnoreCase)||(bIgnoreEOL))
\r
838 // If whitespaces are ignored, a conflict could have been missed
\r
839 // We now go through all lines again and check if they're identical.
\r
840 // If they're not, then that means it is a conflict, and we
\r
841 // mark the conflict with the proper colors.
\r
842 for (long i=0; i<m_Diff3.GetCount(); ++i)
\r
844 DiffStates state1 = m_YourBaseBoth.GetState(i);
\r
845 DiffStates state2 = m_TheirBaseBoth.GetState(i);
\r
847 if (((state1 == DIFFSTATE_IDENTICALADDED)||(state1 == DIFFSTATE_NORMAL))&&
\r
848 ((state2 == DIFFSTATE_IDENTICALADDED)||(state2 == DIFFSTATE_NORMAL)))
\r
850 LONG lineyour = m_arDiff3LinesYour.GetAt(i);
\r
851 LONG linetheir = m_arDiff3LinesTheir.GetAt(i);
\r
852 LONG linebase = m_arDiff3LinesBase.GetAt(i);
\r
853 if ((lineyour < m_arYourFile.GetCount()) &&
\r
854 (linetheir < m_arTheirFile.GetCount()) &&
\r
855 (linebase < m_arBaseFile.GetCount()))
\r
857 if (((m_arYourFile.GetLineEnding(lineyour)!=m_arBaseFile.GetLineEnding(linebase))&&
\r
858 (m_arTheirFile.GetLineEnding(linetheir)!=m_arBaseFile.GetLineEnding(linebase))&&
\r
859 (m_arYourFile.GetLineEnding(lineyour)!=m_arTheirFile.GetLineEnding(linetheir))) ||
\r
860 ((m_arYourFile.GetAt(lineyour).Compare(m_arBaseFile.GetAt(linebase))!=0)&&
\r
861 (m_arTheirFile.GetAt(linetheir).Compare(m_arBaseFile.GetAt(linebase))!=0)&&
\r
862 (m_arYourFile.GetAt(lineyour).Compare(m_arTheirFile.GetAt(linetheir))!=0)))
\r
864 m_Diff3.SetState(i, DIFFSTATE_CONFLICTED_IGNORED);
\r
865 m_YourBaseBoth.SetState(i, DIFFSTATE_CONFLICTADDED);
\r
866 m_TheirBaseBoth.SetState(i, DIFFSTATE_CONFLICTADDED);
\r
872 ASSERT(m_Diff3.GetCount() == m_YourBaseBoth.GetCount());
\r
873 ASSERT(m_TheirBaseBoth.GetCount() == m_YourBaseBoth.GetCount());
\r
875 TRACE(_T("done with 3-way diff\n"));
\r