diff --git a/src/LineRef.h b/src/LineRef.h
index 38586b0..ac6a000 100644
--- a/src/LineRef.h
+++ b/src/LineRef.h
@@ -1,59 +1,60 @@
/**
*
* Copyright (C) 2018 Michael Reeves
*
* This file is part of Kdiff3.
*
* Kdiff3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* Kdiff3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kdiff3. If not, see .
*
*/
#ifndef LINEREF_H
#define LINEREF_H
#include
#include
+#include
class LineRef
{
public:
- typedef int LineType;
-
- static_assert(sizeof(LineType) <= sizeof(size_t), "Unsupport configuration.");
-
+ typedef qint32 LineType;
LineRef() = default;
LineRef(const LineType i) { mLineNumber = i; }
operator LineType() const { return mLineNumber; }
inline void operator= (const LineType lineIn) { mLineNumber = lineIn; }
inline LineRef& operator+=(const LineType& inLine)
{
mLineNumber += inLine;
return *this;
};
+ void invalidate() { mLineNumber = -1; }
+ bool isValid() const { return mLineNumber != -1; }
+
private:
LineType mLineNumber = -1;
};
static_assert(std::is_copy_constructible::value, "");
static_assert(std::is_copy_assignable::value, "");
static_assert(std::is_move_constructible::value, "");
static_assert(std::is_move_assignable::value, "");
static_assert(std::is_convertible::value, "");
static_assert(std::is_convertible::value, "");
typedef LineRef::LineType LineCount;
typedef size_t PtrDiffRef;
typedef LineRef::LineType LineIndex;
#endif
diff --git a/src/Overview.cpp b/src/Overview.cpp
index ee1d73f..0421b1c 100644
--- a/src/Overview.cpp
+++ b/src/Overview.cpp
@@ -1,316 +1,316 @@
/***************************************************************************
* Copyright (C) 2003-2007 by Joachim Eibl *
* Copyright (C) 2018 Michael Reeves reeves.87@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "Overview.h"
#include "mergeresultwindow.h"
#include "options.h"
#include "diff.h"
#include
#include
#include
#include
#include
Overview::Overview(Options* pOptions)
//: QWidget( pParent, 0, Qt::WNoAutoErase )
{
m_pDiff3LineList = nullptr;
m_pOptions = pOptions;
m_bTripleDiff = false;
m_eOverviewMode = eOMNormal;
m_nofLines = 1;
setUpdatesEnabled(false);
m_firstLine = 0;
m_pageHeight = 0;
setFixedWidth(20);
}
void Overview::init(Diff3LineList* pDiff3LineList, bool bTripleDiff)
{
m_pDiff3LineList = pDiff3LineList;
m_bTripleDiff = bTripleDiff;
m_pixmap = QPixmap(QSize(0, 0)); // make sure that a redraw happens
update();
}
void Overview::reset()
{
m_pDiff3LineList = nullptr;
}
void Overview::slotRedraw()
{
m_pixmap = QPixmap(QSize(0, 0)); // make sure that a redraw happens
update();
}
void Overview::setRange(int firstLine, int pageHeight)
{
m_firstLine = firstLine;
m_pageHeight = pageHeight;
update();
}
void Overview::setFirstLine(int firstLine)
{
m_firstLine = firstLine;
update();
}
void Overview::setOverviewMode(e_OverviewMode eOverviewMode)
{
m_eOverviewMode = eOverviewMode;
slotRedraw();
}
Overview::e_OverviewMode Overview::getOverviewMode()
{
return m_eOverviewMode;
}
void Overview::mousePressEvent(QMouseEvent* e)
{
int h = height() - 1;
int h1 = h * m_pageHeight / std::max(1, m_nofLines) + 3;
if(h > 0)
emit setLine((e->y() - h1 / 2) * m_nofLines / h);
}
void Overview::mouseMoveEvent(QMouseEvent* e)
{
mousePressEvent(e);
}
void Overview::setPaintingAllowed(bool bAllowPainting)
{
if(updatesEnabled() != bAllowPainting)
{
setUpdatesEnabled(bAllowPainting);
if(bAllowPainting)
update();
else
reset();
}
}
void Overview::drawColumn(QPainter& p, e_OverviewMode eOverviewMode, int x, int w, int h, int nofLines)
{
p.setPen(Qt::black);
p.drawLine(x, 0, x, h);
if(nofLines == 0) return;
int line = 0;
int oldY = 0;
int oldConflictY = -1;
int wrapLineIdx = 0;
Diff3LineList::const_iterator i;
for(i = m_pDiff3LineList->begin(); i != m_pDiff3LineList->end();)
{
const Diff3Line& d3l = *i;
int y = h * (line + 1) / nofLines;
e_MergeDetails md;
bool bConflict;
bool bLineRemoved;
e_SrcSelector src;
d3l.mergeOneLine(md, bConflict, bLineRemoved, src, !m_bTripleDiff);
QColor c = m_pOptions->m_bgColor;
bool bWhiteSpaceChange = false;
//if( bConflict ) c=m_pOptions->m_colorForConflict;
//else
if(eOverviewMode == eOMNormal)
{
switch(md)
{
case eDefault:
case eNoChange:
c = m_pOptions->m_bgColor;
break;
case eBAdded:
case eBDeleted:
case eBChanged:
c = bConflict ? m_pOptions->m_colorForConflict : m_pOptions->m_colorB;
bWhiteSpaceChange = d3l.isEqualAB() || (d3l.bWhiteLineA && d3l.bWhiteLineB);
break;
case eCAdded:
case eCDeleted:
case eCChanged:
bWhiteSpaceChange = d3l.isEqualAC() || (d3l.bWhiteLineA && d3l.bWhiteLineC);
c = bConflict ? m_pOptions->m_colorForConflict : m_pOptions->m_colorC;
break;
case eBCChanged: // conflict
case eBCChangedAndEqual: // possible conflict
case eBCDeleted: // possible conflict
case eBChanged_CDeleted: // conflict
case eCChanged_BDeleted: // conflict
case eBCAdded: // conflict
case eBCAddedAndEqual: // possible conflict
c = m_pOptions->m_colorForConflict;
break;
default:
Q_ASSERT(true);
break;
}
}
else if(eOverviewMode == eOMAvsB)
{
switch(md)
{
case eDefault:
case eNoChange:
case eCAdded:
case eCDeleted:
case eCChanged:
break;
default:
c = m_pOptions->m_colorForConflict;
bWhiteSpaceChange = d3l.isEqualAB() || (d3l.bWhiteLineA && d3l.bWhiteLineB);
break;
}
}
else if(eOverviewMode == eOMAvsC)
{
switch(md)
{
case eDefault:
case eNoChange:
case eBAdded:
case eBDeleted:
case eBChanged:
break;
default:
c = m_pOptions->m_colorForConflict;
bWhiteSpaceChange = d3l.isEqualAC() || (d3l.bWhiteLineA && d3l.bWhiteLineC);
break;
}
}
else if(eOverviewMode == eOMBvsC)
{
switch(md)
{
case eDefault:
case eNoChange:
case eBCChangedAndEqual:
case eBCDeleted:
case eBCAddedAndEqual:
break;
default:
c = m_pOptions->m_colorForConflict;
bWhiteSpaceChange = d3l.isEqualBC() || (d3l.bWhiteLineB && d3l.bWhiteLineC);
break;
}
}
int x2 = x;
int w2 = w;
if(!m_bTripleDiff)
{
- if(d3l.getLineA() == -1 && d3l.getLineB() >= 0)
+ if(!d3l.getLineA().isValid() && d3l.getLineB().isValid())
{
c = m_pOptions->m_colorA;
x2 = w / 2;
w2 = x2;
}
- if(d3l.getLineA() >= 0 && d3l.getLineB() == -1)
+ if(d3l.getLineA().isValid() && !d3l.getLineB().isValid())
{
c = m_pOptions->m_colorB;
w2 = w / 2;
}
}
if(!bWhiteSpaceChange || m_pOptions->m_bShowWhiteSpace)
{
// Make sure that lines with conflict are not overwritten.
if(c == m_pOptions->m_colorForConflict)
{
p.fillRect(x2 + 1, oldY, w2, std::max(1, y - oldY), bWhiteSpaceChange ? QBrush(c, Qt::Dense4Pattern) : QBrush(c));
oldConflictY = oldY;
}
else if(c != m_pOptions->m_bgColor && oldY > oldConflictY)
{
p.fillRect(x2 + 1, oldY, w2, std::max(1, y - oldY), bWhiteSpaceChange ? QBrush(c, Qt::Dense4Pattern) : QBrush(c));
}
}
oldY = y;
++line;
if(m_pOptions->m_bWordWrap)
{
++wrapLineIdx;
if(wrapLineIdx >= d3l.linesNeededForDisplay)
{
wrapLineIdx = 0;
++i;
}
}
else
{
++i;
}
}
}
void Overview::paintEvent(QPaintEvent*)
{
if(m_pDiff3LineList == nullptr) return;
int h = height() - 1;
int w = width();
if(m_pixmap.size() != size())
{
if(m_pOptions->m_bWordWrap)
{
m_nofLines = 0;
Diff3LineList::const_iterator i;
for(i = m_pDiff3LineList->begin(); i != m_pDiff3LineList->end(); ++i)
{
m_nofLines += i->linesNeededForDisplay;
}
}
else
{
m_nofLines = m_pDiff3LineList->size();
}
m_pixmap = QPixmap(size());
QPainter p(&m_pixmap);
p.fillRect(rect(), m_pOptions->m_bgColor);
if(!m_bTripleDiff || m_eOverviewMode == eOMNormal)
{
drawColumn(p, eOMNormal, 0, w, h, m_nofLines);
}
else
{
drawColumn(p, eOMNormal, 0, w / 2, h, m_nofLines);
drawColumn(p, m_eOverviewMode, w / 2, w / 2, h, m_nofLines);
}
}
QPainter painter(this);
painter.drawPixmap(0, 0, m_pixmap);
int y1=0, h1=0;
if(m_nofLines > 0)
{
y1 = h * m_firstLine / m_nofLines - 1;
h1 = h * m_pageHeight / m_nofLines + 3;
}
painter.setPen(Qt::black);
painter.drawRect(1, y1, w - 1, h1);
}
diff --git a/src/cvsignorelist.cpp b/src/cvsignorelist.cpp
index fdc56d1..22d0141 100644
--- a/src/cvsignorelist.cpp
+++ b/src/cvsignorelist.cpp
@@ -1,204 +1,204 @@
/***************************************************************************
* class CvsIgnoreList from Cervisia cvsdir.cpp *
* Copyright (C) 1999-2002 Bernd Gehrmann *
* with elements from class StringMatcher *
* Copyright (c) 2003 Andre Woebbeking *
* Modifications for KDiff3 by Joachim Eibl *
* *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#include "cvsignorelist.h"
#include
#include
void CvsIgnoreList::init(FileAccess& dir, const t_DirectoryList* pDirList)
{
static const char* ignorestr = ". .. core RCSLOG tags TAGS RCS SCCS .make.state "
".nse_depinfo #* .#* cvslog.* ,* CVS CVS.adm .del-* *.a *.olb *.o *.obj "
"*.so *.Z *~ *.old *.elc *.ln *.bak *.BAK *.orig *.rej *.exe _$* *$";
static const char* varname = "CVSIGNORE";
addEntriesFromString(QString::fromLatin1(ignorestr));
addEntriesFromFile(QDir::homePath() + "/.cvsignore");
if(qEnvironmentVariableIsSet(varname) && !qEnvironmentVariableIsEmpty(varname))
{
addEntriesFromString(QString::fromLocal8Bit(qgetenv(varname)));
}
const bool bUseLocalCvsIgnore = cvsIgnoreExists(pDirList);
if(bUseLocalCvsIgnore)
{
FileAccess file(dir);
file.addPath(".cvsignore");
qint64 size = file.exists() ? file.sizeForReading() : 0;
if(size > 0)
{
char* buf = new char[size];
if(buf != nullptr)
{
file.readFile(buf, size);
int pos1 = 0;
for(int pos = 0; pos <= size; ++pos)
{
if(pos == size || buf[pos] == ' ' || buf[pos] == '\t' || buf[pos] == '\n' || buf[pos] == '\r')
{
if(pos > pos1)
{
addEntry(QString::fromLatin1(&buf[pos1], pos - pos1));
}
++pos1;
}
}
delete[] buf;
}
}
}
}
void CvsIgnoreList::addEntriesFromString(const QString& str)
{
int posLast(0);
int pos;
while((pos = str.indexOf(' ', posLast)) >= 0)
{
if(pos > posLast)
addEntry(str.mid(posLast, pos - posLast));
posLast = pos + 1;
}
if(posLast < static_cast(str.length()))
addEntry(str.mid(posLast));
}
void CvsIgnoreList::addEntriesFromFile(const QString& name)
{
QFile file(name);
if(file.open(QIODevice::ReadOnly))
{
QTextStream stream(&file);
while(!stream.atEnd())
{
addEntriesFromString(stream.readLine());
}
}
}
void CvsIgnoreList::addEntry(const QString& pattern)
{
if(pattern != QString("!"))
{
if(pattern.isEmpty()) return;
// The general match is general but slow.
// Special tests for '*' and '?' at the beginning or end of a pattern
// allow fast checks.
// Count number of '*' and '?'
unsigned int nofMetaCharacters = 0;
const QChar* pos;
pos = pattern.unicode();
const QChar* posEnd;
posEnd = pos + pattern.length();
while(pos < posEnd)
{
if(*pos == QChar('*') || *pos == QChar('?')) ++nofMetaCharacters;
++pos;
}
if(nofMetaCharacters == 0)
{
m_exactPatterns.append(pattern);
}
else if(nofMetaCharacters == 1)
{
if(pattern.at(0) == QChar('*'))
{
m_endPatterns.append(pattern.right(pattern.length() - 1));
}
else if(pattern.at(pattern.length() - 1) == QChar('*'))
{
m_startPatterns.append(pattern.left(pattern.length() - 1));
}
else
{
m_generalPatterns.append(pattern);
}
}
else
{
m_generalPatterns.append(pattern);
}
}
else
{
m_exactPatterns.clear();
m_startPatterns.clear();
m_endPatterns.clear();
m_generalPatterns.clear();
}
}
bool CvsIgnoreList::matches(const QString& text, bool bCaseSensitive) const
{
if(m_exactPatterns.indexOf(text) >= 0)
{
return true;
}
QStringList::ConstIterator it;
QStringList::ConstIterator itEnd;
for(it = m_startPatterns.begin(), itEnd = m_startPatterns.end(); it != itEnd; ++it)
{
if(text.startsWith(*it))
{
return true;
}
}
for(it = m_endPatterns.begin(), itEnd = m_endPatterns.end(); it != itEnd; ++it)
{
- if(text.mid(text.length() - (*it).length()) == *it) //(text.endsWith(*it))
+ if(text.mid(text.length() - it->length()) == *it) //(text.endsWith(*it))
{
return true;
}
}
/*
for (QValueList::const_iterator it(m_generalPatterns.begin()),
itEnd(m_generalPatterns.end());
it != itEnd; ++it)
{
if (::fnmatch(*it, text.local8Bit(), FNM_PATHNAME) == 0)
{
return true;
}
}
*/
for(it = m_generalPatterns.begin(); it != m_generalPatterns.end(); ++it)
{
QRegExp pattern(*it, bCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::Wildcard);
if(pattern.exactMatch(text))
return true;
}
return false;
}
bool CvsIgnoreList::cvsIgnoreExists(const t_DirectoryList* pDirList)
{
t_DirectoryList::const_iterator i;
for(i = pDirList->begin(); i != pDirList->end(); ++i)
{
if(i->fileName() == ".cvsignore")
return true;
}
return false;
}
diff --git a/src/diff.cpp b/src/diff.cpp
index 0481a0a..a353d23 100644
--- a/src/diff.cpp
+++ b/src/diff.cpp
@@ -1,1461 +1,1461 @@
/***************************************************************************
* Copyright (C) 2003-2007 by Joachim Eibl *
* Copyright (C) 2018 Michael Reeves reeves.87@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "diff.h"
#include "Utils.h"
#include "fileaccess.h"
#include "gnudiff_diff.h"
#include "options.h"
#include "progress.h"
#include
#include
#include