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 "SVNAdminDir.h"
\r
27 #include "svn_dso.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
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
90 CString sConvertedBaseFilename, sConvertedTheirFilename, sConvertedYourFilename;
\r
93 apr_pool_create_ex (&pool, NULL, abort_on_pool_failure, NULL);
\r
95 m_arBaseFile.RemoveAll();
\r
96 m_arYourFile.RemoveAll();
\r
97 m_arTheirFile.RemoveAll();
\r
99 m_YourBaseBoth.Clear();
\r
100 m_YourBaseLeft.Clear();
\r
101 m_YourBaseRight.Clear();
\r
103 m_TheirBaseBoth.Clear();
\r
104 m_TheirBaseLeft.Clear();
\r
105 m_TheirBaseRight.Clear();
\r
109 m_arDiff3LinesBase.RemoveAll();
\r
110 m_arDiff3LinesYour.RemoveAll();
\r
111 m_arDiff3LinesTheir.RemoveAll();
\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
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
131 if (!m_arBaseFile.Load(m_baseFile.GetFilename()))
\r
133 m_sError = m_arBaseFile.GetErrorString();
\r
136 if ((bIgnoreCase)||(m_arBaseFile.GetUnicodeType() == CFileTextLines::UNICODE_LE))
\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
144 if (IsTheirFileInUse())
\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
150 m_sError = m_arTheirFile.GetErrorString();
\r
153 if ((bIgnoreCase)||(m_arTheirFile.GetUnicodeType() == CFileTextLines::UNICODE_LE))
\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
161 if (IsYourFileInUse())
\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
167 m_sError = m_arYourFile.GetErrorString();
\r
170 if ((bIgnoreCase)||(m_arYourFile.GetUnicodeType() == CFileTextLines::UNICODE_LE))
\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
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
182 m_YourBaseBoth.Reserve(lengthHint);
\r
183 m_YourBaseLeft.Reserve(lengthHint);
\r
184 m_YourBaseRight.Reserve(lengthHint);
\r
186 m_TheirBaseBoth.Reserve(lengthHint);
\r
187 m_TheirBaseLeft.Reserve(lengthHint);
\r
188 m_TheirBaseRight.Reserve(lengthHint);
\r
190 m_arDiff3LinesBase.Reserve(lengthHint);
\r
191 m_arDiff3LinesYour.Reserve(lengthHint);
\r
192 m_arDiff3LinesTheir.Reserve(lengthHint);
\r
194 // Is this a two-way diff?
\r
195 if (IsBaseFileInUse() && IsYourFileInUse() && !IsTheirFileInUse())
\r
197 if (!DoTwoWayDiff(sConvertedBaseFilename, sConvertedYourFilename, dwIgnoreWS, bIgnoreEOL, pool))
\r
199 apr_pool_destroy (pool); // free the allocated memory
\r
204 if (IsBaseFileInUse() && IsTheirFileInUse() && !IsYourFileInUse())
\r
209 if (IsBaseFileInUse() && IsTheirFileInUse() && IsYourFileInUse())
\r
211 m_Diff3.Reserve(lengthHint);
\r
213 if (!DoThreeWayDiff(sConvertedBaseFilename, sConvertedYourFilename, sConvertedTheirFilename, dwIgnoreWS, bIgnoreEOL, !!bIgnoreCase, pool))
\r
215 apr_pool_destroy (pool); // free the allocated memory
\r
220 apr_pool_destroy (pool); // free the allocated memory
\r
226 CDiffData::DoTwoWayDiff(const CString& sBaseFilename, const CString& sYourFilename, DWORD dwIgnoreWS, bool bIgnoreEOL, apr_pool_t * pool)
\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
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
240 options->ignore_space = svn_diff_file_ignore_space_none;
\r
243 options->ignore_space = svn_diff_file_ignore_space_all;
\r
246 options->ignore_space = svn_diff_file_ignore_space_change;
\r
250 svnerr = svn_diff_file_diff_2(&diffYourBase, sBaseFilenameUtf8, sYourFilenameUtf8, options, pool);
\r
253 TRACE(_T("diff-error in CDiffData::Load()\n"));
\r
254 CString sMsg = CString(svnerr->message);
\r
255 while (svnerr->child)
\r
257 svnerr = svnerr->child;
\r
259 sMsg += CString(svnerr->message);
\r
261 m_sError.Format(IDS_ERR_DIFF_DIFF, (LPCTSTR)sMsg);
\r
262 svn_error_clear(svnerr);
\r
265 svn_diff_t * tempdiff = diffYourBase;
\r
271 for (int i=0; i<tempdiff->original_length; i++)
\r
273 if (baseline >= m_arBaseFile.GetCount())
\r
275 m_sError.LoadString(IDS_ERR_DIFF_NEWLINES);
\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
282 if (yourline >= m_arYourFile.GetCount())
\r
284 m_sError.LoadString(IDS_ERR_DIFF_NEWLINES);
\r
287 const CString& sCurrentYourLine = m_arYourFile.GetAt(yourline);
\r
288 EOL endingYours = m_arYourFile.GetLineEnding(yourline);
\r
289 if (sCurrentBaseLine != sCurrentYourLine)
\r
291 if (dwIgnoreWS == 2 || dwIgnoreWS == 3)
\r
293 CString s1 = m_arBaseFile.GetAt(baseline);
\r
294 CString s2 = sCurrentYourLine;
\r
296 if ( dwIgnoreWS == 2 )
\r
298 s1.TrimLeft(_T(" \t"));
\r
299 s2.TrimLeft(_T(" \t"));
\r
303 s1.TrimRight(_T(" \t"));
\r
304 s2.TrimRight(_T(" \t"));
\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
315 m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, yourline, endingBase);
\r
318 else if (dwIgnoreWS == 0)
\r
320 m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_REMOVEDWHITESPACE, yourline, endingBase);
\r
321 m_YourBaseBoth.AddData(sCurrentYourLine, DIFFSTATE_ADDEDWHITESPACE, yourline, endingYours);
\r
325 m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, yourline, endingBase);
\r
330 m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, yourline, endingBase);
\r
332 yourline++; //in both files
\r
336 m_YourBaseBoth.AddData(sCurrentBaseLine, DIFFSTATE_REMOVED, yourline, endingBase);
\r
340 if (tempdiff->type == svn_diff__type_diff_modified)
\r
342 for (int i=0; i<tempdiff->modified_length; i++)
\r
344 if (m_arYourFile.GetCount() > yourline)
\r
346 m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_ADDED, yourline, m_arYourFile.GetLineEnding(yourline));
\r
351 tempdiff = tempdiff->next;
\r
354 tempdiff = diffYourBase;
\r
359 if (tempdiff->type == svn_diff__type_common)
\r
361 for (int i=0; i<tempdiff->original_length; i++)
\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
369 if (dwIgnoreWS == 2 || dwIgnoreWS == 3)
\r
371 CString s1 = sCurrentBaseLine;
\r
372 CString s2 = sCurrentYourLine;
\r
373 if ( dwIgnoreWS == 2 )
\r
375 s1 = s1.TrimLeft(_T(" \t"));
\r
376 s2 = s2.TrimLeft(_T(" \t"));
\r
380 s1 = s1.TrimRight(_T(" \t"));
\r
381 s2 = s2.TrimRight(_T(" \t"));
\r
386 m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_WHITESPACE, baseline, endingBase);
\r
387 m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_WHITESPACE, yourline, endingYours);
\r
391 m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, baseline, endingBase);
\r
392 m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_NORMAL, yourline, endingYours);
\r
395 else if (dwIgnoreWS == 0)
\r
397 m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_WHITESPACE, baseline, endingBase);
\r
398 m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_WHITESPACE, yourline, endingYours);
\r
402 m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, baseline, endingBase);
\r
403 m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_NORMAL, yourline, endingYours);
\r
408 m_YourBaseLeft.AddData(sCurrentBaseLine, DIFFSTATE_NORMAL, baseline, endingBase);
\r
409 m_YourBaseRight.AddData(sCurrentYourLine, DIFFSTATE_NORMAL, yourline, endingYours);
\r
415 if (tempdiff->type == svn_diff__type_diff_modified)
\r
417 apr_off_t original_length = tempdiff->original_length;
\r
418 for (int i=0; i<tempdiff->modified_length; i++)
\r
420 if (m_arYourFile.GetCount() > yourline)
\r
422 EOL endingYours = m_arYourFile.GetLineEnding(yourline);
\r
423 if (original_length-- <= 0)
\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
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
438 apr_off_t modified_length = tempdiff->modified_length;
\r
439 for (int i=0; i<tempdiff->original_length; i++)
\r
441 if (modified_length-- <= 0)
\r
443 if (m_arBaseFile.GetCount() > baseline)
\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
453 tempdiff = tempdiff->next;
\r
455 TRACE(_T("done with 2-way diff\n"));
\r
461 CDiffData::DoThreeWayDiff(const CString& sBaseFilename, const CString& sYourFilename, const CString& sTheirFilename, DWORD dwIgnoreWS, bool bIgnoreEOL, bool bIgnoreCase, apr_pool_t * pool)
\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
474 options->ignore_space = svn_diff_file_ignore_space_none;
\r
477 options->ignore_space = svn_diff_file_ignore_space_all;
\r
480 options->ignore_space = svn_diff_file_ignore_space_change;
\r
483 svn_error_t * svnerr = svn_diff_file_diff3_2(&diffTheirYourBase, sBaseFilenameUtf8, sTheirFilenameUtf8, sYourFilenameUtf8, options, pool);
\r
486 TRACE(_T("diff-error in CDiffData::Load()\n"));
\r
487 CString sMsg = CString(svnerr->message);
\r
488 while (svnerr->child)
\r
490 svnerr = svnerr->child;
\r
492 sMsg += CString(svnerr->message);
\r
494 m_sError.Format(IDS_ERR_DIFF_DIFF, (LPCTSTR)sMsg);
\r
495 svn_error_clear(svnerr);
\r
499 svn_diff_t * tempdiff = diffTheirYourBase;
\r
502 LONG theirline = 0;
\r
506 if (tempdiff->type == svn_diff__type_common)
\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
511 if ((m_arYourFile.GetCount() > yourline)&&(m_arTheirFile.GetCount() > theirline))
\r
513 m_Diff3.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_NORMAL, resline, m_arYourFile.GetLineEnding(yourline));
\r
515 m_arDiff3LinesBase.Add(baseline);
\r
516 m_arDiff3LinesYour.Add(yourline);
\r
517 m_arDiff3LinesTheir.Add(theirline);
\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
529 else if (tempdiff->type == svn_diff__type_diff_common)
\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
535 if (m_arBaseFile.GetCount() > baseline)
\r
537 m_Diff3.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));
\r
539 m_arDiff3LinesBase.Add(baseline);
\r
540 m_arDiff3LinesYour.Add(yourline);
\r
541 m_arDiff3LinesTheir.Add(theirline);
\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
549 for (int i=0; i<tempdiff->modified_length; i++)
\r
551 if ((m_arYourFile.GetCount() > yourline)&&(m_arTheirFile.GetCount() > theirline))
\r
553 m_Diff3.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_IDENTICALADDED, resline, m_arYourFile.GetLineEnding(yourline));
\r
555 m_arDiff3LinesBase.Add(baseline);
\r
556 m_arDiff3LinesYour.Add(yourline);
\r
557 m_arDiff3LinesTheir.Add(theirline);
\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
568 else if (tempdiff->type == svn_diff__type_conflict)
\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
576 apr_off_t originalresolved = 0;
\r
577 apr_off_t modifiedresolved = 0;
\r
578 apr_off_t latestresolved = 0;
\r
580 LONG base = baseline;
\r
581 LONG your = yourline;
\r
582 LONG their = theirline;
\r
583 if (tempdiff->resolved_diff)
\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
589 for (int i=0; i<length; i++)
\r
593 if (m_arBaseFile.GetCount() > baseline)
\r
595 m_Diff3.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));
\r
597 m_arDiff3LinesBase.Add(baseline);
\r
598 m_arDiff3LinesYour.Add(yourline);
\r
599 m_arDiff3LinesTheir.Add(theirline);
\r
602 else if ((originalresolved)||((modifiedresolved)&&(latestresolved)))
\r
604 m_Diff3.AddData(_T(""), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);
\r
606 m_arDiff3LinesBase.Add(baseline);
\r
607 m_arDiff3LinesYour.Add(yourline);
\r
608 m_arDiff3LinesTheir.Add(theirline);
\r
611 if ((latest)&&(original))
\r
613 if (m_arBaseFile.GetCount() > baseline)
\r
615 m_YourBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));
\r
622 if (m_arBaseFile.GetCount() > baseline)
\r
624 m_YourBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));
\r
627 else if ((latestresolved)&&(modifiedresolved))
\r
629 m_YourBaseBoth.AddData(_T(""), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);
\r
632 if ((modified)&&(original))
\r
634 if (m_arBaseFile.GetCount() > baseline)
\r
636 m_TheirBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));
\r
643 if (m_arBaseFile.GetCount() > baseline)
\r
645 m_TheirBaseBoth.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));
\r
648 else if ((modifiedresolved)&&(latestresolved))
\r
650 m_TheirBaseBoth.AddData(_T(""), DIFFSTATE_IDENTICALREMOVED, DIFF_EMPTYLINENUMBER, EOL_NOENDING);
\r
658 if (originalresolved)
\r
659 originalresolved--;
\r
666 if (modifiedresolved)
\r
667 modifiedresolved--;
\r
673 if (latestresolved)
\r
676 original = tempdiff->original_length;
\r
677 modified = tempdiff->modified_length;
\r
678 latest = tempdiff->latest_length;
\r
682 if (tempdiff->resolved_diff)
\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
688 for (int i=0; i<length; i++)
\r
690 if ((latest)||(modified))
\r
692 m_Diff3.AddData(_T(""), DIFFSTATE_CONFLICTED, resline, EOL_NOENDING);
\r
694 m_arDiff3LinesBase.Add(baseline);
\r
695 m_arDiff3LinesYour.Add(yourline);
\r
696 m_arDiff3LinesTheir.Add(theirline);
\r
703 if (m_arYourFile.GetCount() > yourline)
\r
705 m_YourBaseBoth.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_CONFLICTADDED, yourline, m_arYourFile.GetLineEnding(yourline));
\r
708 else if ((latestresolved)||(modified)||(modifiedresolved))
\r
710 m_YourBaseBoth.AddData(_T(""), DIFFSTATE_CONFLICTEMPTY, DIFF_EMPTYLINENUMBER, EOL_NOENDING);
\r
714 if (m_arTheirFile.GetCount() > theirline)
\r
716 m_TheirBaseBoth.AddData(m_arTheirFile.GetAt(theirline), DIFFSTATE_CONFLICTADDED, theirline, m_arTheirFile.GetLineEnding(theirline));
\r
719 else if ((modifiedresolved)||(latest)||(latestresolved))
\r
721 m_TheirBaseBoth.AddData(_T(""), DIFFSTATE_CONFLICTEMPTY, DIFF_EMPTYLINENUMBER, EOL_NOENDING);
\r
728 if (originalresolved)
\r
729 originalresolved--;
\r
735 if (modifiedresolved)
\r
736 modifiedresolved--;
\r
742 if (latestresolved)
\r
746 else if (tempdiff->type == svn_diff__type_diff_modified)
\r
749 for (int i=0; i<tempdiff->original_length; i++)
\r
751 if ((m_arBaseFile.GetCount() > baseline)&&(m_arYourFile.GetCount() > yourline))
\r
753 m_Diff3.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_THEIRSREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));
\r
755 m_arDiff3LinesBase.Add(baseline);
\r
756 m_arDiff3LinesYour.Add(yourline);
\r
757 m_arDiff3LinesTheir.Add(theirline);
\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
766 for (int i=0; i<tempdiff->modified_length; i++)
\r
768 if (m_arTheirFile.GetCount() > theirline)
\r
770 m_Diff3.AddData(m_arTheirFile.GetAt(theirline), DIFFSTATE_THEIRSADDED, resline, m_arTheirFile.GetLineEnding(theirline));
\r
772 m_arDiff3LinesBase.Add(baseline);
\r
773 m_arDiff3LinesYour.Add(yourline);
\r
774 m_arDiff3LinesTheir.Add(theirline);
\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
784 else if (tempdiff->type == svn_diff__type_diff_latest)
\r
786 //YOURS differs from base
\r
788 for (int i=0; i<tempdiff->original_length; i++)
\r
790 if ((m_arBaseFile.GetCount() > baseline)&&(m_arTheirFile.GetCount() > theirline))
\r
792 m_Diff3.AddData(m_arBaseFile.GetAt(baseline), DIFFSTATE_YOURSREMOVED, DIFF_EMPTYLINENUMBER, m_arBaseFile.GetLineEnding(baseline));
\r
794 m_arDiff3LinesBase.Add(baseline);
\r
795 m_arDiff3LinesYour.Add(yourline);
\r
796 m_arDiff3LinesTheir.Add(theirline);
\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
805 for (int i=0; i<tempdiff->latest_length; i++)
\r
807 if (m_arYourFile.GetCount() > yourline)
\r
809 m_Diff3.AddData(m_arYourFile.GetAt(yourline), DIFFSTATE_YOURSADDED, resline, m_arYourFile.GetLineEnding(yourline));
\r
811 m_arDiff3LinesBase.Add(baseline);
\r
812 m_arDiff3LinesYour.Add(yourline);
\r
813 m_arDiff3LinesTheir.Add(theirline);
\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
825 TRACE(_T("something bad happened during diff!\n"));
\r
827 tempdiff = tempdiff->next;
\r
829 } // while (tempdiff)
\r
831 if ((options->ignore_space != svn_diff_file_ignore_space_none)||(bIgnoreCase)||(bIgnoreEOL))
\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
839 DiffStates state1 = m_YourBaseBoth.GetState(i);
\r
840 DiffStates state2 = m_TheirBaseBoth.GetState(i);
\r
842 if (((state1 == DIFFSTATE_IDENTICALADDED)||(state1 == DIFFSTATE_NORMAL))&&
\r
843 ((state2 == DIFFSTATE_IDENTICALADDED)||(state2 == DIFFSTATE_NORMAL)))
\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
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
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
867 ASSERT(m_Diff3.GetCount() == m_YourBaseBoth.GetCount());
\r
868 ASSERT(m_TheirBaseBoth.GetCount() == m_YourBaseBoth.GetCount());
\r
870 TRACE(_T("done with 3-way diff\n"));
\r