|
|
|
/***************************************************************************
|
|
|
|
difftextwindow.cpp - description
|
|
|
|
-------------------
|
|
|
|
begin : Mon Apr 8 2002
|
|
|
|
copyright : (C) 2002-2007 by Joachim Eibl
|
|
|
|
email : joachim.eibl at gmx.de
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* *
|
|
|
|
* 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 "difftextwindow.h"
|
|
|
|
#include "merger.h"
|
|
|
|
#include <tqpainter.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <tqpixmap.h>
|
|
|
|
#include <tqstatusbar.h>
|
|
|
|
#include <tqapplication.h>
|
|
|
|
#include <tqtooltip.h>
|
|
|
|
#include <tqfont.h>
|
|
|
|
#include <tqstringlist.h>
|
|
|
|
#include <tqlineedit.h>
|
|
|
|
#include <tqlabel.h>
|
|
|
|
#include <tqpushbutton.h>
|
|
|
|
#include <tqlayout.h>
|
|
|
|
#include <tqtextcodec.h>
|
|
|
|
#include <optiondialog.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <tqdragobject.h>
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <tdefiledialog.h>
|
|
|
|
|
|
|
|
class DiffTextWindowData
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DiffTextWindowData( DiffTextWindow* p )
|
|
|
|
{
|
|
|
|
m_pDiffTextWindow = p;
|
|
|
|
m_bPaintingAllowed = false;
|
|
|
|
m_pLineData = 0;
|
|
|
|
m_size = 0;
|
|
|
|
m_bWordWrap = false;
|
|
|
|
m_delayedDrawTimer = 0;
|
|
|
|
m_pDiff3LineVector = 0;
|
|
|
|
m_pManualDiffHelpList = 0;
|
|
|
|
m_pOptionDialog = 0;
|
|
|
|
m_fastSelectorLine1 = 0;
|
|
|
|
m_fastSelectorNofLines = 0;
|
|
|
|
m_bTriple = 0;
|
|
|
|
m_winIdx = 0;
|
|
|
|
m_firstLine = 0;
|
|
|
|
m_oldFirstLine = 0;
|
|
|
|
m_oldFirstColumn = 0;
|
|
|
|
m_firstColumn = 0;
|
|
|
|
m_lineNumberWidth = 0;
|
|
|
|
m_pStatusBar = 0;
|
|
|
|
m_scrollDeltaX = 0;
|
|
|
|
m_scrollDeltaY = 0;
|
|
|
|
m_bMyUpdate = false;
|
|
|
|
m_bSelectionInProgress = false;
|
|
|
|
}
|
|
|
|
DiffTextWindow* m_pDiffTextWindow;
|
|
|
|
DiffTextWindowFrame* m_pDiffTextWindowFrame;
|
|
|
|
|
|
|
|
bool m_bPaintingAllowed;
|
|
|
|
const LineData* m_pLineData;
|
|
|
|
int m_size;
|
|
|
|
TQString m_filename;
|
|
|
|
bool m_bWordWrap;
|
|
|
|
int m_delayedDrawTimer;
|
|
|
|
|
|
|
|
const Diff3LineVector* m_pDiff3LineVector;
|
|
|
|
Diff3WrapLineVector m_diff3WrapLineVector;
|
|
|
|
const ManualDiffHelpList* m_pManualDiffHelpList;
|
|
|
|
|
|
|
|
OptionDialog* m_pOptionDialog;
|
|
|
|
TQColor m_cThis;
|
|
|
|
TQColor m_cDiff1;
|
|
|
|
TQColor m_cDiff2;
|
|
|
|
TQColor m_cDiffBoth;
|
|
|
|
|
|
|
|
int m_fastSelectorLine1;
|
|
|
|
int m_fastSelectorNofLines;
|
|
|
|
|
|
|
|
bool m_bTriple;
|
|
|
|
int m_winIdx;
|
|
|
|
int m_firstLine;
|
|
|
|
int m_oldFirstLine;
|
|
|
|
int m_oldFirstColumn;
|
|
|
|
int m_firstColumn;
|
|
|
|
int m_lineNumberWidth;
|
|
|
|
|
|
|
|
void getLineInfo(
|
|
|
|
const Diff3Line& d,
|
|
|
|
int& lineIdx,
|
|
|
|
DiffList*& pFineDiff1, DiffList*& pFineDiff2, // return values
|
|
|
|
int& changed, int& changed2 );
|
|
|
|
|
|
|
|
TQString getString( int d3lIdx );
|
|
|
|
TQString getLineString( int line );
|
|
|
|
|
|
|
|
void writeLine(
|
|
|
|
MyPainter& p, const LineData* pld,
|
|
|
|
const DiffList* pLineDiff1, const DiffList* pLineDiff2, int line,
|
|
|
|
int whatChanged, int whatChanged2, int srcLineIdx,
|
|
|
|
int wrapLineOffset, int wrapLineLength, bool bWrapLine, const TQRect& invalidRect, int deviceWidth
|
|
|
|
);
|
|
|
|
|
|
|
|
void draw( MyPainter& p, const TQRect& invalidRect, int deviceWidth, int beginLine, int endLine );
|
|
|
|
|
|
|
|
TQStatusBar* m_pStatusBar;
|
|
|
|
|
|
|
|
Selection m_selection;
|
|
|
|
|
|
|
|
int m_scrollDeltaX;
|
|
|
|
int m_scrollDeltaY;
|
|
|
|
|
|
|
|
bool m_bMyUpdate;
|
|
|
|
void myUpdate(int afterMilliSecs );
|
|
|
|
|
|
|
|
int leftInfoWidth() { return 4+m_lineNumberWidth; } // Nr of information columns on left side
|
|
|
|
int convertLineOnScreenToLineInSource( int lineOnScreen, e_CoordType coordType, bool bFirstLine );
|
|
|
|
|
|
|
|
bool m_bSelectionInProgress;
|
|
|
|
TQPoint m_lastKnownMousePos;
|
|
|
|
};
|
|
|
|
|
|
|
|
DiffTextWindow::DiffTextWindow(
|
|
|
|
DiffTextWindowFrame* pParent,
|
|
|
|
TQStatusBar* pStatusBar,
|
|
|
|
OptionDialog* pOptionDialog,
|
|
|
|
int winIdx
|
|
|
|
)
|
|
|
|
: TQWidget(pParent, 0, TQt::WResizeNoErase | TQt::WRepaintNoErase)
|
|
|
|
{
|
|
|
|
d = new DiffTextWindowData(this);
|
|
|
|
d->m_pDiffTextWindowFrame = pParent;
|
|
|
|
setFocusPolicy( TQWidget::ClickFocus );
|
|
|
|
setAcceptDrops( true );
|
|
|
|
|
|
|
|
d->m_pOptionDialog = pOptionDialog;
|
|
|
|
init( 0, 0, 0, 0, 0, false );
|
|
|
|
|
|
|
|
setMinimumSize(TQSize(20,20));
|
|
|
|
|
|
|
|
d->m_pStatusBar = pStatusBar;
|
|
|
|
d->m_bPaintingAllowed = true;
|
|
|
|
d->m_bWordWrap = false;
|
|
|
|
d->m_winIdx = winIdx;
|
|
|
|
|
|
|
|
setFont(d->m_pOptionDialog->m_font);
|
|
|
|
}
|
|
|
|
|
|
|
|
DiffTextWindow::~DiffTextWindow()
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindow::init(
|
|
|
|
const TQString& filename,
|
|
|
|
const LineData* pLineData,
|
|
|
|
int size,
|
|
|
|
const Diff3LineVector* pDiff3LineVector,
|
|
|
|
const ManualDiffHelpList* pManualDiffHelpList,
|
|
|
|
bool bTriple
|
|
|
|
)
|
|
|
|
{
|
|
|
|
d->m_filename = filename;
|
|
|
|
d->m_pLineData = pLineData;
|
|
|
|
d->m_size = size;
|
|
|
|
d->m_pDiff3LineVector = pDiff3LineVector;
|
|
|
|
d->m_diff3WrapLineVector.clear();
|
|
|
|
d->m_pManualDiffHelpList = pManualDiffHelpList;
|
|
|
|
|
|
|
|
d->m_firstLine = 0;
|
|
|
|
d->m_oldFirstLine = -1;
|
|
|
|
d->m_firstColumn = 0;
|
|
|
|
d->m_oldFirstColumn = -1;
|
|
|
|
d->m_bTriple = bTriple;
|
|
|
|
d->m_scrollDeltaX=0;
|
|
|
|
d->m_scrollDeltaY=0;
|
|
|
|
d->m_bMyUpdate = false;
|
|
|
|
d->m_fastSelectorLine1 = 0;
|
|
|
|
d->m_fastSelectorNofLines = 0;
|
|
|
|
d->m_lineNumberWidth = 0;
|
|
|
|
d->m_selection.reset();
|
|
|
|
d->m_selection.oldFirstLine = -1; // reset is not enough here.
|
|
|
|
d->m_selection.oldLastLine = -1;
|
|
|
|
d->m_selection.lastLine = -1;
|
|
|
|
|
|
|
|
update();
|
|
|
|
d->m_pDiffTextWindowFrame->init();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindow::reset()
|
|
|
|
{
|
|
|
|
d->m_pLineData=0;
|
|
|
|
d->m_size=0;
|
|
|
|
d->m_pDiff3LineVector=0;
|
|
|
|
d->m_filename="";
|
|
|
|
d->m_diff3WrapLineVector.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindow::setPaintingAllowed( bool bAllowPainting )
|
|
|
|
{
|
|
|
|
if (d->m_bPaintingAllowed != bAllowPainting)
|
|
|
|
{
|
|
|
|
d->m_bPaintingAllowed = bAllowPainting;
|
|
|
|
if ( d->m_bPaintingAllowed ) update();
|
|
|
|
else reset();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindow::dragEnterEvent( TQDragEnterEvent* e )
|
|
|
|
{
|
|
|
|
e->accept( TQUriDrag::canDecode(e) || TQTextDrag::canDecode(e) );
|
|
|
|
// Note that the corresponding drop is handled in KDiff3App::eventFilter().
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DiffTextWindow::setFirstLine(int firstLine)
|
|
|
|
{
|
|
|
|
int fontHeight = fontMetrics().height();
|
|
|
|
|
|
|
|
int newFirstLine = max2(0,firstLine);
|
|
|
|
|
|
|
|
int deltaY = fontHeight * ( d->m_firstLine - newFirstLine );
|
|
|
|
|
|
|
|
d->m_firstLine = newFirstLine;
|
|
|
|
|
|
|
|
if ( d->m_bSelectionInProgress && d->m_selection.firstLine != -1 )
|
|
|
|
{
|
|
|
|
int line, pos;
|
|
|
|
convertToLinePos( d->m_lastKnownMousePos.x(), d->m_lastKnownMousePos.y(), line, pos );
|
|
|
|
d->m_selection.end( line, pos );
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TQWidget::scroll( 0, deltaY );
|
|
|
|
}
|
|
|
|
d->m_pDiffTextWindowFrame->setFirstLine( d->m_firstLine );
|
|
|
|
}
|
|
|
|
|
|
|
|
int DiffTextWindow::getFirstLine()
|
|
|
|
{
|
|
|
|
return d->m_firstLine;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindow::setFirstColumn(int firstCol)
|
|
|
|
{
|
|
|
|
int fontWidth = fontMetrics().width('W');
|
|
|
|
int xOffset = d->leftInfoWidth() * fontWidth;
|
|
|
|
|
|
|
|
int newFirstColumn = max2(0,firstCol);
|
|
|
|
|
|
|
|
int deltaX = fontWidth * ( d->m_firstColumn - newFirstColumn );
|
|
|
|
|
|
|
|
d->m_firstColumn = newFirstColumn;
|
|
|
|
|
|
|
|
TQRect r( xOffset, 0, width()-xOffset, height() );
|
|
|
|
|
|
|
|
if ( d->m_pOptionDialog->m_bRightToLeftLanguage )
|
|
|
|
{
|
|
|
|
deltaX = -deltaX;
|
|
|
|
r = TQRect( width()-1-xOffset, 0, -(width()-xOffset), height() ).normalize();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( d->m_bSelectionInProgress && d->m_selection.firstLine != -1 )
|
|
|
|
{
|
|
|
|
int line, pos;
|
|
|
|
convertToLinePos( d->m_lastKnownMousePos.x(), d->m_lastKnownMousePos.y(), line, pos );
|
|
|
|
d->m_selection.end( line, pos );
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TQWidget::scroll( deltaX, 0, r );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int DiffTextWindow::getNofColumns()
|
|
|
|
{
|
|
|
|
if (d->m_bWordWrap)
|
|
|
|
{
|
|
|
|
return getNofVisibleColumns();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int nofColumns = 0;
|
|
|
|
for( int i = 0; i< d->m_size; ++i )
|
|
|
|
{
|
|
|
|
if ( d->m_pLineData[i].width( d->m_pOptionDialog->m_tabSize ) > nofColumns )
|
|
|
|
nofColumns = d->m_pLineData[i].width( d->m_pOptionDialog->m_tabSize );
|
|
|
|
}
|
|
|
|
return nofColumns;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int DiffTextWindow::getNofLines()
|
|
|
|
{
|
|
|
|
return d->m_bWordWrap ? d->m_diff3WrapLineVector.size() :
|
|
|
|
d->m_pDiff3LineVector->size();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int DiffTextWindow::convertLineToDiff3LineIdx( int line )
|
|
|
|
{
|
|
|
|
if ( d->m_bWordWrap && d->m_diff3WrapLineVector.size()>0 )
|
|
|
|
return d->m_diff3WrapLineVector[ min2( line, (int)d->m_diff3WrapLineVector.size()-1 ) ].diff3LineIndex;
|
|
|
|
else
|
|
|
|
return line;
|
|
|
|
}
|
|
|
|
|
|
|
|
int DiffTextWindow::convertDiff3LineIdxToLine( int d3lIdx )
|
|
|
|
{
|
|
|
|
if ( d->m_bWordWrap && d->m_pDiff3LineVector!=0 && d->m_pDiff3LineVector->size()>0 )
|
|
|
|
return (*d->m_pDiff3LineVector)[ min2( d3lIdx, (int)d->m_pDiff3LineVector->size()-1 ) ]->sumLinesNeededForDisplay;
|
|
|
|
else
|
|
|
|
return d3lIdx;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns a line number where the linerange [line, line+nofLines] can
|
|
|
|
be displayed best. If it fits into the currently visible range then
|
|
|
|
the returned value is the current firstLine.
|
|
|
|
*/
|
|
|
|
int getBestFirstLine( int line, int nofLines, int firstLine, int visibleLines )
|
|
|
|
{
|
|
|
|
int newFirstLine = firstLine;
|
|
|
|
if ( line < firstLine || line + nofLines + 2 > firstLine + visibleLines )
|
|
|
|
{
|
|
|
|
if ( nofLines > visibleLines || nofLines <= ( 2*visibleLines / 3 - 1) )
|
|
|
|
newFirstLine = line - visibleLines/3;
|
|
|
|
else
|
|
|
|
newFirstLine = line - (visibleLines - nofLines);
|
|
|
|
}
|
|
|
|
|
|
|
|
return newFirstLine;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DiffTextWindow::setFastSelectorRange( int line1, int nofLines )
|
|
|
|
{
|
|
|
|
d->m_fastSelectorLine1 = line1;
|
|
|
|
d->m_fastSelectorNofLines = nofLines;
|
|
|
|
if ( isVisible() )
|
|
|
|
{
|
|
|
|
int newFirstLine = getBestFirstLine(
|
|
|
|
convertDiff3LineIdxToLine(d->m_fastSelectorLine1),
|
|
|
|
convertDiff3LineIdxToLine(d->m_fastSelectorLine1+d->m_fastSelectorNofLines)-convertDiff3LineIdxToLine(d->m_fastSelectorLine1),
|
|
|
|
d->m_firstLine,
|
|
|
|
getNofVisibleLines()
|
|
|
|
);
|
|
|
|
if ( newFirstLine != d->m_firstLine )
|
|
|
|
{
|
|
|
|
scroll( 0, newFirstLine - d->m_firstLine );
|
|
|
|
}
|
|
|
|
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DiffTextWindow::showStatusLine(int line )
|
|
|
|
{
|
|
|
|
int d3lIdx = convertLineToDiff3LineIdx( line );
|
|
|
|
if(d3lIdx >= 0 && d3lIdx<(int)d->m_pDiff3LineVector->size() )
|
|
|
|
{
|
|
|
|
const Diff3Line* pD3l = (*d->m_pDiff3LineVector)[d3lIdx];
|
|
|
|
if ( pD3l != 0 )
|
|
|
|
{
|
|
|
|
int l = pD3l->getLineInFile( d->m_winIdx );
|
|
|
|
|
|
|
|
TQString s;
|
|
|
|
if ( l!=-1 )
|
|
|
|
s.sprintf("File %s: Line %d", d->m_filename.ascii(), l+1 );
|
|
|
|
else
|
|
|
|
s.sprintf("File %s: Line not available", d->m_filename.ascii() );
|
|
|
|
if (d->m_pStatusBar!=0) d->m_pStatusBar->message(s);
|
|
|
|
|
|
|
|
emit lineClicked( d->m_winIdx, l );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindow::focusInEvent(TQFocusEvent* e)
|
|
|
|
{
|
|
|
|
emit gotFocus();
|
|
|
|
TQWidget::focusInEvent(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindow::mousePressEvent ( TQMouseEvent* e )
|
|
|
|
{
|
|
|
|
if ( e->button() == TQt::LeftButton )
|
|
|
|
{
|
|
|
|
int line;
|
|
|
|
int pos;
|
|
|
|
convertToLinePos( e->x(), e->y(), line, pos );
|
|
|
|
if ( pos < d->m_firstColumn )
|
|
|
|
{
|
|
|
|
emit setFastSelectorLine( convertLineToDiff3LineIdx(line) );
|
|
|
|
d->m_selection.firstLine = -1; // Disable current d->m_selection
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // Selection
|
|
|
|
resetSelection();
|
|
|
|
d->m_selection.start( line, pos );
|
|
|
|
d->m_selection.end( line, pos );
|
|
|
|
d->m_bSelectionInProgress = true;
|
|
|
|
d->m_lastKnownMousePos = e->pos();
|
|
|
|
|
|
|
|
showStatusLine( line );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isCTokenChar( TQChar c )
|
|
|
|
{
|
|
|
|
return (c=='_') ||
|
|
|
|
( c.unicode()>='A' && c.unicode()<='Z' ) || ( c.unicode()>='a' && c.unicode()<='z' ) ||
|
|
|
|
(c.unicode()>='0' && c.unicode()<='9');
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Calculate where a token starts and ends, given the x-position on screen.
|
|
|
|
void calcTokenPos( const TQString& s, int posOnScreen, int& pos1, int& pos2, int tabSize )
|
|
|
|
{
|
|
|
|
// Cursor conversions that consider g_tabSize
|
|
|
|
int pos = convertToPosInText( s, max2( 0, posOnScreen ), tabSize );
|
|
|
|
if ( pos>=(int)s.length() )
|
|
|
|
{
|
|
|
|
pos1=s.length();
|
|
|
|
pos2=s.length();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pos1 = pos;
|
|
|
|
pos2 = pos+1;
|
|
|
|
|
|
|
|
if( isCTokenChar( s[pos1] ) )
|
|
|
|
{
|
|
|
|
while( pos1>=0 && isCTokenChar( s[pos1] ) )
|
|
|
|
--pos1;
|
|
|
|
++pos1;
|
|
|
|
|
|
|
|
while( pos2<(int)s.length() && isCTokenChar( s[pos2] ) )
|
|
|
|
++pos2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindow::mouseDoubleClickEvent( TQMouseEvent* e )
|
|
|
|
{
|
|
|
|
d->m_bSelectionInProgress = false;
|
|
|
|
d->m_lastKnownMousePos = e->pos();
|
|
|
|
if ( e->button() == TQt::LeftButton )
|
|
|
|
{
|
|
|
|
int line;
|
|
|
|
int pos;
|
|
|
|
convertToLinePos( e->x(), e->y(), line, pos );
|
|
|
|
|
|
|
|
// Get the string data of the current line
|
|
|
|
TQString s;
|
|
|
|
if ( d->m_bWordWrap )
|
|
|
|
{
|
|
|
|
if ( line<0 || line >= (int)d->m_diff3WrapLineVector.size() )
|
|
|
|
return;
|
|
|
|
const Diff3WrapLine& d3wl = d->m_diff3WrapLineVector[line];
|
|
|
|
s = d->getString( d3wl.diff3LineIndex ).mid( d3wl.wrapLineOffset, d3wl.wrapLineLength );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( line<0 || line >= (int)d->m_pDiff3LineVector->size() )
|
|
|
|
return;
|
|
|
|
s = d->getString( line );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ! s.isEmpty() )
|
|
|
|
{
|
|
|
|
int pos1, pos2;
|
|
|
|
calcTokenPos( s, pos, pos1, pos2, d->m_pOptionDialog->m_tabSize );
|
|
|
|
|
|
|
|
resetSelection();
|
|
|
|
d->m_selection.start( line, convertToPosOnScreen( s, pos1, d->m_pOptionDialog->m_tabSize ) );
|
|
|
|
d->m_selection.end( line, convertToPosOnScreen( s, pos2, d->m_pOptionDialog->m_tabSize ) );
|
|
|
|
update();
|
|
|
|
// emit d->m_selectionEnd() happens in the mouseReleaseEvent.
|
|
|
|
showStatusLine( line );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindow::mouseReleaseEvent ( TQMouseEvent* e )
|
|
|
|
{
|
|
|
|
d->m_bSelectionInProgress = false;
|
|
|
|
d->m_lastKnownMousePos = e->pos();
|
|
|
|
//if ( e->button() == LeftButton )
|
|
|
|
{
|
|
|
|
killTimer(d->m_delayedDrawTimer);
|
|
|
|
d->m_delayedDrawTimer = 0;
|
|
|
|
if (d->m_selection.firstLine != -1 )
|
|
|
|
{
|
|
|
|
emit selectionEnd();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
d->m_scrollDeltaX=0;
|
|
|
|
d->m_scrollDeltaY=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline int sqr(int x){return x*x;}
|
|
|
|
|
|
|
|
void DiffTextWindow::mouseMoveEvent ( TQMouseEvent * e )
|
|
|
|
{
|
|
|
|
int line;
|
|
|
|
int pos;
|
|
|
|
convertToLinePos( e->x(), e->y(), line, pos );
|
|
|
|
d->m_lastKnownMousePos = e->pos();
|
|
|
|
|
|
|
|
if (d->m_selection.firstLine != -1 )
|
|
|
|
{
|
|
|
|
d->m_selection.end( line, pos );
|
|
|
|
|
|
|
|
showStatusLine( line );
|
|
|
|
|
|
|
|
// Scroll because mouse moved out of the window
|
|
|
|
const TQFontMetrics& fm = fontMetrics();
|
|
|
|
int fontWidth = fm.width('W');
|
|
|
|
int deltaX=0;
|
|
|
|
int deltaY=0;
|
|
|
|
if ( ! d->m_pOptionDialog->m_bRightToLeftLanguage )
|
|
|
|
{
|
|
|
|
if ( e->x() < d->leftInfoWidth()*fontWidth ) deltaX = -1 - abs(e->x()-d->leftInfoWidth()*fontWidth)/fontWidth;
|
|
|
|
if ( e->x() > width() ) deltaX = +1 + abs(e->x()-width())/fontWidth;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( e->x() > width()-1-d->leftInfoWidth()*fontWidth ) deltaX=+1+ abs(e->x() - (width()-1-d->leftInfoWidth()*fontWidth)) / fontWidth;
|
|
|
|
if ( e->x() < fontWidth ) deltaX=-1- abs(e->x()-fontWidth)/fontWidth;
|
|
|
|
}
|
|
|
|
if ( e->y() < 0 ) deltaY = -1 - sqr( e->y() ) / sqr(fm.height());
|
|
|
|
if ( e->y() > height() ) deltaY = +1 + sqr( e->y() - height() ) / sqr(fm.height());
|
|
|
|
if ( deltaX != 0 && d->m_scrollDeltaX!=deltaX || deltaY!= 0 && d->m_scrollDeltaY!=deltaY )
|
|
|
|
{
|
|
|
|
d->m_scrollDeltaX = deltaX;
|
|
|
|
d->m_scrollDeltaY = deltaY;
|
|
|
|
emit scroll( deltaX, deltaY );
|
|
|
|
killTimer( d->m_delayedDrawTimer );
|
|
|
|
d->m_delayedDrawTimer = startTimer(50);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d->m_scrollDeltaX = deltaX;
|
|
|
|
d->m_scrollDeltaY = deltaY;
|
|
|
|
d->myUpdate(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DiffTextWindowData::myUpdate(int afterMilliSecs)
|
|
|
|
{
|
|
|
|
m_pDiffTextWindow->killTimer( m_delayedDrawTimer );
|
|
|
|
m_bMyUpdate = true;
|
|
|
|
m_delayedDrawTimer = m_pDiffTextWindow->startTimer( afterMilliSecs );
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindow::timerEvent(TQTimerEvent*)
|
|
|
|
{
|
|
|
|
killTimer(d->m_delayedDrawTimer);
|
|
|
|
d->m_delayedDrawTimer = 0;
|
|
|
|
|
|
|
|
if ( d->m_bMyUpdate )
|
|
|
|
{
|
|
|
|
int fontHeight = fontMetrics().height();
|
|
|
|
|
|
|
|
if ( d->m_selection.oldLastLine != -1 )
|
|
|
|
{
|
|
|
|
int lastLine;
|
|
|
|
int firstLine;
|
|
|
|
if ( d->m_selection.oldFirstLine != -1 )
|
|
|
|
{
|
|
|
|
firstLine = min3( d->m_selection.oldFirstLine, d->m_selection.lastLine, d->m_selection.oldLastLine );
|
|
|
|
lastLine = max3( d->m_selection.oldFirstLine, d->m_selection.lastLine, d->m_selection.oldLastLine );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
firstLine = min2( d->m_selection.lastLine, d->m_selection.oldLastLine );
|
|
|
|
lastLine = max2( d->m_selection.lastLine, d->m_selection.oldLastLine );
|
|
|
|
}
|
|
|
|
int y1 = ( firstLine - d->m_firstLine ) * fontHeight;
|
|
|
|
int y2 = min2( height(), ( lastLine - d->m_firstLine + 1 ) * fontHeight );
|
|
|
|
|
|
|
|
if ( y1<height() && y2>0 )
|
|
|
|
{
|
|
|
|
TQRect invalidRect = TQRect( 0, y1, width(), y2-y1 );
|
|
|
|
update( invalidRect );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
d->m_bMyUpdate = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( d->m_scrollDeltaX != 0 || d->m_scrollDeltaY != 0 )
|
|
|
|
{
|
|
|
|
d->m_selection.end( d->m_selection.lastLine + d->m_scrollDeltaY, d->m_selection.lastPos + d->m_scrollDeltaX );
|
|
|
|
emit scroll( d->m_scrollDeltaX, d->m_scrollDeltaY );
|
|
|
|
killTimer(d->m_delayedDrawTimer);
|
|
|
|
d->m_delayedDrawTimer = startTimer(50);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindow::resetSelection()
|
|
|
|
{
|
|
|
|
d->m_selection.reset();
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindow::convertToLinePos( int x, int y, int& line, int& pos )
|
|
|
|
{
|
|
|
|
const TQFontMetrics& fm = fontMetrics();
|
|
|
|
int fontHeight = fm.height();
|
|
|
|
int fontWidth = fm.width('W');
|
|
|
|
int xOffset = ( d->leftInfoWidth() - d->m_firstColumn ) * fontWidth;
|
|
|
|
|
|
|
|
int yOffset = - d->m_firstLine * fontHeight;
|
|
|
|
|
|
|
|
line = ( y - yOffset ) / fontHeight;
|
|
|
|
if ( ! d->m_pOptionDialog->m_bRightToLeftLanguage )
|
|
|
|
pos = ( x - xOffset ) / fontWidth;
|
|
|
|
else
|
|
|
|
pos = ( (width() - 1 - x) - xOffset ) / fontWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Selection::firstPosInLine(int l)
|
|
|
|
{
|
|
|
|
assert( firstLine != -1 );
|
|
|
|
|
|
|
|
int l1 = firstLine;
|
|
|
|
int l2 = lastLine;
|
|
|
|
int p1 = firstPos;
|
|
|
|
int p2 = lastPos;
|
|
|
|
if ( l1>l2 ){ std::swap(l1,l2); std::swap(p1,p2); }
|
|
|
|
if ( l1==l2 && p1>p2 ){ std::swap(p1,p2); }
|
|
|
|
|
|
|
|
if ( l==l1 )
|
|
|
|
return p1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Selection::lastPosInLine(int l)
|
|
|
|
{
|
|
|
|
assert( firstLine != -1 );
|
|
|
|
|
|
|
|
int l1 = firstLine;
|
|
|
|
int l2 = lastLine;
|
|
|
|
int p1 = firstPos;
|
|
|
|
int p2 = lastPos;
|
|
|
|
|
|
|
|
if ( l1>l2 ){ std::swap(l1,l2); std::swap(p1,p2); }
|
|
|
|
if ( l1==l2 && p1>p2 ){ std::swap(p1,p2); }
|
|
|
|
|
|
|
|
if ( l==l2 )
|
|
|
|
return p2;
|
|
|
|
return INT_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Selection::within( int l, int p )
|
|
|
|
{
|
|
|
|
if ( firstLine == -1 ) return false;
|
|
|
|
int l1 = firstLine;
|
|
|
|
int l2 = lastLine;
|
|
|
|
int p1 = firstPos;
|
|
|
|
int p2 = lastPos;
|
|
|
|
if ( l1>l2 ){ std::swap(l1,l2); std::swap(p1,p2); }
|
|
|
|
if ( l1==l2 && p1>p2 ){ std::swap(p1,p2); }
|
|
|
|
if( l1 <= l && l <= l2 )
|
|
|
|
{
|
|
|
|
if ( l1==l2 )
|
|
|
|
return p>=p1 && p<p2;
|
|
|
|
if ( l==l1 )
|
|
|
|
return p>=p1;
|
|
|
|
if ( l==l2 )
|
|
|
|
return p<p2;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Selection::lineWithin( int l )
|
|
|
|
{
|
|
|
|
if ( firstLine == -1 ) return false;
|
|
|
|
int l1 = firstLine;
|
|
|
|
int l2 = lastLine;
|
|
|
|
|
|
|
|
if ( l1>l2 ){ std::swap(l1,l2); }
|
|
|
|
|
|
|
|
return ( l1 <= l && l <= l2 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DiffTextWindowData::writeLine(
|
|
|
|
MyPainter& p,
|
|
|
|
const LineData* pld,
|
|
|
|
const DiffList* pLineDiff1,
|
|
|
|
const DiffList* pLineDiff2,
|
|
|
|
int line,
|
|
|
|
int whatChanged,
|
|
|
|
int whatChanged2,
|
|
|
|
int srcLineIdx,
|
|
|
|
int wrapLineOffset,
|
|
|
|
int wrapLineLength,
|
|
|
|
bool bWrapLine,
|
|
|
|
const TQRect& invalidRect,
|
|
|
|
int deviceWidth
|
|
|
|
)
|
|
|
|
{
|
|
|
|
TQFont normalFont = p.font();
|
|
|
|
TQFont diffFont = normalFont;
|
|
|
|
diffFont.setItalic( m_pOptionDialog->m_bItalicForDeltas );
|
|
|
|
const TQFontMetrics& fm = p.fontMetrics();
|
|
|
|
int fontHeight = fm.height();
|
|
|
|
int fontAscent = fm.ascent();
|
|
|
|
int fontDescent = fm.descent();
|
|
|
|
int fontWidth = fm.width('W');
|
|
|
|
|
|
|
|
int xOffset = (leftInfoWidth() - m_firstColumn)*fontWidth;
|
|
|
|
int yOffset = (line-m_firstLine) * fontHeight;
|
|
|
|
|
|
|
|
TQRect lineRect( 0, yOffset, deviceWidth, fontHeight );
|
|
|
|
if ( ! invalidRect.intersects( lineRect ) )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int fastSelectorLine1 = m_pDiffTextWindow->convertDiff3LineIdxToLine(m_fastSelectorLine1);
|
|
|
|
int fastSelectorLine2 = m_pDiffTextWindow->convertDiff3LineIdxToLine(m_fastSelectorLine1+m_fastSelectorNofLines)-1;
|
|
|
|
|
|
|
|
bool bFastSelectionRange = (line>=fastSelectorLine1 && line<= fastSelectorLine2 );
|
|
|
|
TQColor bgColor = m_pOptionDialog->m_bgColor;
|
|
|
|
TQColor diffBgColor = m_pOptionDialog->m_diffBgColor;
|
|
|
|
|
|
|
|
if ( bFastSelectionRange )
|
|
|
|
{
|
|
|
|
bgColor = m_pOptionDialog->m_currentRangeBgColor;
|
|
|
|
diffBgColor = m_pOptionDialog->m_currentRangeDiffBgColor;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( yOffset+fontHeight<invalidRect.top() || invalidRect.bottom() < yOffset-fontHeight )
|
|
|
|
return;
|
|
|
|
|
|
|
|
int changed = whatChanged;
|
|
|
|
if ( pLineDiff1 != 0 ) changed |= 1;
|
|
|
|
if ( pLineDiff2 != 0 ) changed |= 2;
|
|
|
|
|
|
|
|
TQColor c = m_pOptionDialog->m_fgColor;
|
|
|
|
if ( changed == 2 ) {
|
|
|
|
c = m_cDiff2;
|
|
|
|
} else if ( changed == 1 ) {
|
|
|
|
c = m_cDiff1;
|
|
|
|
} else if ( changed == 3 ) {
|
|
|
|
c = m_cDiffBoth;
|
|
|
|
}
|
|
|
|
|
|
|
|
p.fillRect( leftInfoWidth()*fontWidth, yOffset, deviceWidth, fontHeight, bgColor );
|
|
|
|
|
|
|
|
if (pld!=0)
|
|
|
|
{
|
|
|
|
// First calculate the "changed" information for each character.
|
|
|
|
int i=0;
|
|
|
|
std::vector<UINT8> charChanged( pld->size );
|
|
|
|
if ( pLineDiff1!=0 || pLineDiff2 != 0 )
|
|
|
|
{
|
|
|
|
Merger merger( pLineDiff1, pLineDiff2 );
|
|
|
|
while( ! merger.isEndReached() && i<pld->size )
|
|
|
|
{
|
|
|
|
if ( i < pld->size )
|
|
|
|
{
|
|
|
|
charChanged[i] = merger.whatChanged();
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
merger.next();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString s=" ";
|
|
|
|
// Convert tabs
|
|
|
|
int outPos = 0;
|
|
|
|
|
|
|
|
TQString lineString( pld->pLine, pld->size );
|
|
|
|
int lineLength = m_bWordWrap ? wrapLineOffset+wrapLineLength : lineString.length();
|
|
|
|
|
|
|
|
for( i=wrapLineOffset; i<lineLength; ++i )
|
|
|
|
{
|
|
|
|
int spaces = 1;
|
|
|
|
|
|
|
|
if ( lineString[i]=='\t' )
|
|
|
|
{
|
|
|
|
spaces = tabber( outPos, m_pOptionDialog->m_tabSize );
|
|
|
|
s[0] = ' ';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
s[0] = lineString[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
TQColor c = m_pOptionDialog->m_fgColor;
|
|
|
|
int cchanged = charChanged[i] | whatChanged;
|
|
|
|
|
|
|
|
if ( cchanged == 2 ) {
|
|
|
|
c = m_cDiff2;
|
|
|
|
} else if ( cchanged == 1 ) {
|
|
|
|
c = m_cDiff1;
|
|
|
|
} else if ( cchanged == 3 ) {
|
|
|
|
c = m_cDiffBoth;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( c!=m_pOptionDialog->m_fgColor && whatChanged2==0 && !m_pOptionDialog->m_bShowWhiteSpace )
|
|
|
|
{
|
|
|
|
// The user doesn't want to see highlighted white space.
|
|
|
|
c = m_pOptionDialog->m_fgColor;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQRect outRect( xOffset + fontWidth*outPos, yOffset, fontWidth*spaces, fontHeight );
|
|
|
|
if ( m_pOptionDialog->m_bRightToLeftLanguage )
|
|
|
|
outRect = TQRect( deviceWidth-1-(xOffset + fontWidth*outPos), yOffset, -fontWidth*spaces, fontHeight ).normalize();
|
|
|
|
if ( invalidRect.intersects( outRect ) )
|
|
|
|
{
|
|
|
|
if( !m_selection.within( line, outPos ) )
|
|
|
|
{
|
|
|
|
|
|
|
|
if( c!=m_pOptionDialog->m_fgColor )
|
|
|
|
{
|
|
|
|
TQColor lightc = diffBgColor;
|
|
|
|
p.fillRect( xOffset + fontWidth*outPos, yOffset,
|
|
|
|
fontWidth*spaces, fontHeight, lightc );
|
|
|
|
p.setFont(diffFont);
|
|
|
|
}
|
|
|
|
|
|
|
|
p.setPen( c );
|
|
|
|
if ( s[0]==' ' && c!=m_pOptionDialog->m_fgColor && charChanged[i]!=0 )
|
|
|
|
{
|
|
|
|
if ( m_pOptionDialog->m_bShowWhiteSpaceCharacters && m_pOptionDialog->m_bShowWhiteSpace)
|
|
|
|
{
|
|
|
|
p.fillRect( xOffset + fontWidth*outPos, yOffset+fontAscent,
|
|
|
|
fontWidth*spaces-1, fontDescent, c );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p.drawText( xOffset + fontWidth*outPos, yOffset + fontAscent, s );
|
|
|
|
}
|
|
|
|
p.setFont(normalFont);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p.fillRect( xOffset + fontWidth*outPos, yOffset,
|
|
|
|
fontWidth*(spaces), fontHeight, m_pDiffTextWindow->colorGroup().highlight() );
|
|
|
|
|
|
|
|
p.setPen( m_pDiffTextWindow->colorGroup().highlightedText() );
|
|
|
|
p.drawText( xOffset + fontWidth*outPos, yOffset + fontAscent, s );
|
|
|
|
|
|
|
|
m_selection.bSelectionContainsData = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
outPos += spaces;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( m_selection.lineWithin( line ) && m_selection.lineWithin( line+1 ) )
|
|
|
|
{
|
|
|
|
p.fillRect( xOffset + fontWidth*outPos, yOffset,
|
|
|
|
deviceWidth, fontHeight, m_pDiffTextWindow->colorGroup().highlight() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
p.fillRect( 0, yOffset, leftInfoWidth()*fontWidth, fontHeight, m_pOptionDialog->m_bgColor );
|
|
|
|
|
|
|
|
xOffset = (m_lineNumberWidth+2)*fontWidth;
|
|
|
|
int xLeft = m_lineNumberWidth*fontWidth;
|
|
|
|
p.setPen( m_pOptionDialog->m_fgColor );
|
|
|
|
if ( pld!=0 )
|
|
|
|
{
|
|
|
|
if ( m_pOptionDialog->m_bShowLineNumbers && !bWrapLine )
|
|
|
|
{
|
|
|
|
TQString num;
|
|
|
|
num.sprintf( "%0*d", m_lineNumberWidth, srcLineIdx+1);
|
|
|
|
p.drawText( 0, yOffset + fontAscent, num );
|
|
|
|
//p.drawLine( xLeft -1, yOffset, xLeft -1, yOffset+fontHeight-1 );
|
|
|
|
}
|
|
|
|
if ( !bWrapLine || wrapLineLength>0 )
|
|
|
|
{
|
|
|
|
p.setPen( TQPen( m_pOptionDialog->m_fgColor, 0, bWrapLine ? TQt::DotLine : TQt::SolidLine) );
|
|
|
|
p.drawLine( xOffset +1, yOffset, xOffset +1, yOffset+fontHeight-1 );
|
|
|
|
p.setPen( TQPen( m_pOptionDialog->m_fgColor, 0, TQt::SolidLine) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( c!=m_pOptionDialog->m_fgColor && whatChanged2==0 )//&& whatChanged==0 )
|
|
|
|
{
|
|
|
|
if ( m_pOptionDialog->m_bShowWhiteSpace )
|
|
|
|
{
|
|
|
|
p.setBrushOrigin(0,0);
|
|
|
|
p.fillRect( xLeft, yOffset, fontWidth*2-1, fontHeight, TQBrush(c,TQt::Dense5Pattern) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p.fillRect( xLeft, yOffset, fontWidth*2-1, fontHeight, c==m_pOptionDialog->m_fgColor ? bgColor : c );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( bFastSelectionRange )
|
|
|
|
{
|
|
|
|
p.fillRect( xOffset + fontWidth-1, yOffset, 3, fontHeight, m_pOptionDialog->m_fgColor );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if line needs a manual diff help mark
|
|
|
|
ManualDiffHelpList::const_iterator ci;
|
|
|
|
for( ci = m_pManualDiffHelpList->begin(); ci!=m_pManualDiffHelpList->end(); ++ci)
|
|
|
|
{
|
|
|
|
const ManualDiffHelpEntry& mdhe=*ci;
|
|
|
|
int rangeLine1 = -1;
|
|
|
|
int rangeLine2 = -1;
|
|
|
|
if (m_winIdx==1 ) { rangeLine1 = mdhe.lineA1; rangeLine2= mdhe.lineA2; }
|
|
|
|
if (m_winIdx==2 ) { rangeLine1 = mdhe.lineB1; rangeLine2= mdhe.lineB2; }
|
|
|
|
if (m_winIdx==3 ) { rangeLine1 = mdhe.lineC1; rangeLine2= mdhe.lineC2; }
|
|
|
|
if ( rangeLine1>=0 && rangeLine2>=0 && srcLineIdx >= rangeLine1 && srcLineIdx <= rangeLine2 )
|
|
|
|
{
|
|
|
|
p.fillRect( xOffset - fontWidth, yOffset, fontWidth-1, fontHeight, m_pOptionDialog->m_manualHelpRangeColor );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindow::paintEvent( TQPaintEvent* e )
|
|
|
|
{
|
|
|
|
if ( d->m_pDiff3LineVector==0 || ! d->m_bPaintingAllowed ||
|
|
|
|
( d->m_diff3WrapLineVector.empty() && d->m_bWordWrap ) )
|
|
|
|
return;
|
|
|
|
|
|
|
|
TQRect invalidRect = e->rect();
|
|
|
|
if ( invalidRect.isEmpty() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
bool bOldSelectionContainsData = d->m_selection.bSelectionContainsData;
|
|
|
|
d->m_selection.bSelectionContainsData = false;
|
|
|
|
|
|
|
|
int endLine = min2( d->m_firstLine + getNofVisibleLines()+2, getNofLines() );
|
|
|
|
|
|
|
|
//if ( invalidRect.size()==size() )
|
|
|
|
{
|
|
|
|
TQPainter painter(this);
|
|
|
|
TQPixmap pixmap( invalidRect.size() );
|
|
|
|
|
|
|
|
MyPainter p( &pixmap, d->m_pOptionDialog->m_bRightToLeftLanguage, width(), fontMetrics().width('W') );
|
|
|
|
|
|
|
|
p.translate( -invalidRect.x(), -invalidRect.y() );
|
|
|
|
|
|
|
|
p.setFont( font() );
|
|
|
|
p.TQPainter::fillRect( invalidRect, d->m_pOptionDialog->m_bgColor );
|
|
|
|
|
|
|
|
d->draw( p, invalidRect, width(), d->m_firstLine, endLine );
|
|
|
|
// p.drawLine( m_invalidRect.x(), m_invalidRect.y(), m_invalidRect.right(), m_invalidRect.bottom() ); // For test only
|
|
|
|
p.end();
|
|
|
|
|
|
|
|
painter.drawPixmap( invalidRect.x(), invalidRect.y(), pixmap );
|
|
|
|
}
|
|
|
|
// else
|
|
|
|
// { // no double buffering
|
|
|
|
// MyPainter p( this, d->m_pOptionDialog->m_bRightToLeftLanguage, width(), fontMetrics().width('W') );
|
|
|
|
// p.setFont( font() );
|
|
|
|
// p.TQPainter::fillRect( invalidRect, d->m_pOptionDialog->m_bgColor );
|
|
|
|
// d->draw( p, invalidRect, width(), d->m_firstLine, endLine );
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
d->m_oldFirstLine = d->m_firstLine;
|
|
|
|
d->m_oldFirstColumn = d->m_firstColumn;
|
|
|
|
d->m_selection.oldLastLine = -1;
|
|
|
|
if ( d->m_selection.oldFirstLine !=-1 )
|
|
|
|
d->m_selection.oldFirstLine = -1;
|
|
|
|
|
|
|
|
if( !bOldSelectionContainsData && d->m_selection.bSelectionContainsData )
|
|
|
|
emit newSelection();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindow::print( MyPainter& p, const TQRect&, int firstLine, int nofLinesPerPage )
|
|
|
|
{
|
|
|
|
if ( d->m_pDiff3LineVector==0 || ! d->m_bPaintingAllowed ||
|
|
|
|
( d->m_diff3WrapLineVector.empty() && d->m_bWordWrap ) )
|
|
|
|
return;
|
|
|
|
resetSelection();
|
|
|
|
// MyPainter p( this, d->m_pOptionDialog->m_bRightToLeftLanguage, width(), fontMetrics().width('W') );
|
|
|
|
int oldFirstLine = d->m_firstLine;
|
|
|
|
d->m_firstLine = firstLine;
|
|
|
|
TQRect invalidRect = TQRect(0,0,TQCOORD_MAX,TQCOORD_MAX);
|
|
|
|
TQColor bgColor = d->m_pOptionDialog->m_bgColor;
|
|
|
|
d->m_pOptionDialog->m_bgColor = TQt::white;
|
|
|
|
d->draw( p, invalidRect, p.window().width(), firstLine, min2(firstLine+nofLinesPerPage,getNofLines()) );
|
|
|
|
d->m_pOptionDialog->m_bgColor = bgColor;
|
|
|
|
d->m_firstLine = oldFirstLine;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindowData::draw( MyPainter& p, const TQRect& invalidRect, int deviceWidth, int beginLine, int endLine )
|
|
|
|
{
|
|
|
|
m_lineNumberWidth = m_pOptionDialog->m_bShowLineNumbers ? (int)log10((double)m_size)+1 : 0;
|
|
|
|
|
|
|
|
if ( m_winIdx==1 )
|
|
|
|
{
|
|
|
|
m_cThis = m_pOptionDialog->m_colorA;
|
|
|
|
m_cDiff1 = m_pOptionDialog->m_colorB;
|
|
|
|
m_cDiff2 = m_pOptionDialog->m_colorC;
|
|
|
|
}
|
|
|
|
if ( m_winIdx==2 )
|
|
|
|
{
|
|
|
|
m_cThis = m_pOptionDialog->m_colorB;
|
|
|
|
m_cDiff1 = m_pOptionDialog->m_colorC;
|
|
|
|
m_cDiff2 = m_pOptionDialog->m_colorA;
|
|
|
|
}
|
|
|
|
if ( m_winIdx==3 )
|
|
|
|
{
|
|
|
|
m_cThis = m_pOptionDialog->m_colorC;
|
|
|
|
m_cDiff1 = m_pOptionDialog->m_colorA;
|
|
|
|
m_cDiff2 = m_pOptionDialog->m_colorB;
|
|
|
|
}
|
|
|
|
m_cDiffBoth = m_pOptionDialog->m_colorForConflict; // Conflict color
|
|
|
|
|
|
|
|
p.setPen( m_cThis );
|
|
|
|
|
|
|
|
for ( int line = beginLine; line<endLine; ++line )
|
|
|
|
{
|
|
|
|
int wrapLineOffset=0;
|
|
|
|
int wrapLineLength=0;
|
|
|
|
const Diff3Line* d3l =0;
|
|
|
|
bool bWrapLine = false;
|
|
|
|
if (m_bWordWrap)
|
|
|
|
{
|
|
|
|
Diff3WrapLine& d3wl = m_diff3WrapLineVector[line];
|
|
|
|
wrapLineOffset = d3wl.wrapLineOffset;
|
|
|
|
wrapLineLength = d3wl.wrapLineLength;
|
|
|
|
d3l = d3wl.pD3L;
|
|
|
|
bWrapLine = line > 0 && m_diff3WrapLineVector[line-1].pD3L == d3l;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d3l = (*m_pDiff3LineVector)[line];
|
|
|
|
}
|
|
|
|
DiffList* pFineDiff1;
|
|
|
|
DiffList* pFineDiff2;
|
|
|
|
int changed=0;
|
|
|
|
int changed2=0;
|
|
|
|
|
|
|
|
int srcLineIdx=-1;
|
|
|
|
getLineInfo( *d3l, srcLineIdx, pFineDiff1, pFineDiff2, changed, changed2 );
|
|
|
|
|
|
|
|
writeLine(
|
|
|
|
p, // TQPainter
|
|
|
|
srcLineIdx == -1 ? 0 : &m_pLineData[srcLineIdx], // Text in this line
|
|
|
|
pFineDiff1,
|
|
|
|
pFineDiff2,
|
|
|
|
line, // Line on the screen
|
|
|
|
changed,
|
|
|
|
changed2,
|
|
|
|
srcLineIdx,
|
|
|
|
wrapLineOffset,
|
|
|
|
wrapLineLength,
|
|
|
|
bWrapLine,
|
|
|
|
invalidRect,
|
|
|
|
deviceWidth
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString DiffTextWindowData::getString( int d3lIdx )
|
|
|
|
{
|
|
|
|
if ( d3lIdx<0 || d3lIdx>=(int)m_pDiff3LineVector->size() )
|
|
|
|
return TQString();
|
|
|
|
const Diff3Line* d3l = (*m_pDiff3LineVector)[d3lIdx];
|
|
|
|
DiffList* pFineDiff1;
|
|
|
|
DiffList* pFineDiff2;
|
|
|
|
int changed=0;
|
|
|
|
int changed2=0;
|
|
|
|
int lineIdx;
|
|
|
|
getLineInfo( *d3l, lineIdx, pFineDiff1, pFineDiff2, changed, changed2 );
|
|
|
|
|
|
|
|
if (lineIdx==-1) return TQString();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const LineData* ld = &m_pLineData[lineIdx];
|
|
|
|
return TQString( ld->pLine, ld->size );
|
|
|
|
}
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString DiffTextWindowData::getLineString( int line )
|
|
|
|
{
|
|
|
|
if ( m_bWordWrap )
|
|
|
|
{
|
|
|
|
int d3LIdx = m_pDiffTextWindow->convertLineToDiff3LineIdx(line);
|
|
|
|
return getString( d3LIdx ).mid( m_diff3WrapLineVector[line].wrapLineOffset, m_diff3WrapLineVector[line].wrapLineLength );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return getString( line );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindowData::getLineInfo(
|
|
|
|
const Diff3Line& d3l,
|
|
|
|
int& lineIdx,
|
|
|
|
DiffList*& pFineDiff1, DiffList*& pFineDiff2, // return values
|
|
|
|
int& changed, int& changed2
|
|
|
|
)
|
|
|
|
{
|
|
|
|
changed=0;
|
|
|
|
changed2=0;
|
|
|
|
bool bAEqB = d3l.bAEqB || ( d3l.bWhiteLineA && d3l.bWhiteLineB );
|
|
|
|
bool bAEqC = d3l.bAEqC || ( d3l.bWhiteLineA && d3l.bWhiteLineC );
|
|
|
|
bool bBEqC = d3l.bBEqC || ( d3l.bWhiteLineB && d3l.bWhiteLineC );
|
|
|
|
if ( m_winIdx == 1 ) {
|
|
|
|
lineIdx=d3l.lineA;
|
|
|
|
pFineDiff1=d3l.pFineAB;
|
|
|
|
pFineDiff2=d3l.pFineCA;
|
|
|
|
changed |= ((d3l.lineB==-1)!=(lineIdx==-1) ? 1 : 0) +
|
|
|
|
((d3l.lineC==-1)!=(lineIdx==-1) && m_bTriple ? 2 : 0);
|
|
|
|
changed2 |= ( bAEqB ? 0 : 1 ) + (bAEqC || !m_bTriple ? 0 : 2);
|
|
|
|
}
|
|
|
|
else if ( m_winIdx == 2 ) {
|
|
|
|
lineIdx=d3l.lineB;
|
|
|
|
pFineDiff1=d3l.pFineBC;
|
|
|
|
pFineDiff2=d3l.pFineAB;
|
|
|
|
changed |= ((d3l.lineC==-1)!=(lineIdx==-1) && m_bTriple ? 1 : 0) +
|
|
|
|
((d3l.lineA==-1)!=(lineIdx==-1) ? 2 : 0);
|
|
|
|
changed2 |= ( bBEqC || !m_bTriple ? 0 : 1 ) + (bAEqB ? 0 : 2);
|
|
|
|
}
|
|
|
|
else if ( m_winIdx == 3 ) {
|
|
|
|
lineIdx=d3l.lineC;
|
|
|
|
pFineDiff1=d3l.pFineCA;
|
|
|
|
pFineDiff2=d3l.pFineBC;
|
|
|
|
changed |= ((d3l.lineA==-1)!=(lineIdx==-1) ? 1 : 0) +
|
|
|
|
((d3l.lineB==-1)!=(lineIdx==-1) ? 2 : 0);
|
|
|
|
changed2 |= ( bAEqC ? 0 : 1 ) + (bBEqC ? 0 : 2);
|
|
|
|
}
|
|
|
|
else assert(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DiffTextWindow::resizeEvent( TQResizeEvent* e )
|
|
|
|
{
|
|
|
|
TQSize s = e->size();
|
|
|
|
TQFontMetrics fm = fontMetrics();
|
|
|
|
int visibleLines = s.height()/fm.height()-2;
|
|
|
|
int visibleColumns = s.width()/fm.width('W') - d->leftInfoWidth();
|
|
|
|
emit resizeSignal( visibleColumns, visibleLines );
|
|
|
|
TQWidget::resizeEvent(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
int DiffTextWindow::getNofVisibleLines()
|
|
|
|
{
|
|
|
|
TQFontMetrics fm = fontMetrics();
|
|
|
|
int fmh = fm.height();
|
|
|
|
int h = height();
|
|
|
|
return h/fmh -1;//height()/fm.height()-2;
|
|
|
|
}
|
|
|
|
|
|
|
|
int DiffTextWindow::getNofVisibleColumns()
|
|
|
|
{
|
|
|
|
TQFontMetrics fm = fontMetrics();
|
|
|
|
return width()/fm.width('W') - d->leftInfoWidth();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString DiffTextWindow::getSelection()
|
|
|
|
{
|
|
|
|
TQString selectionString;
|
|
|
|
|
|
|
|
int line=0;
|
|
|
|
int lineIdx=0;
|
|
|
|
|
|
|
|
int it;
|
|
|
|
int vectorSize = d->m_bWordWrap ? d->m_diff3WrapLineVector.size() : d->m_pDiff3LineVector->size();
|
|
|
|
for( it=0; it<vectorSize; ++it )
|
|
|
|
{
|
|
|
|
const Diff3Line* d3l = d->m_bWordWrap ? d->m_diff3WrapLineVector[it].pD3L : (*d->m_pDiff3LineVector)[it];
|
|
|
|
if ( d->m_winIdx == 1 ) { lineIdx=d3l->lineA; }
|
|
|
|
else if ( d->m_winIdx == 2 ) { lineIdx=d3l->lineB; }
|
|
|
|
else if ( d->m_winIdx == 3 ) { lineIdx=d3l->lineC; }
|
|
|
|
else assert(false);
|
|
|
|
|
|
|
|
if( lineIdx != -1 )
|
|
|
|
{
|
|
|
|
const TQChar* pLine = d->m_pLineData[lineIdx].pLine;
|
|
|
|
int size = d->m_pLineData[lineIdx].size;
|
|
|
|
TQString lineString = TQString( pLine, size );
|
|
|
|
|
|
|
|
if ( d->m_bWordWrap )
|
|
|
|
{
|
|
|
|
size = d->m_diff3WrapLineVector[it].wrapLineLength;
|
|
|
|
lineString = lineString.mid( d->m_diff3WrapLineVector[it].wrapLineOffset, size );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Consider tabs
|
|
|
|
int outPos = 0;
|
|
|
|
for( int i=0; i<size; ++i )
|
|
|
|
{
|
|
|
|
int spaces = 1;
|
|
|
|
if ( lineString[i]=='\t' )
|
|
|
|
{
|
|
|
|
spaces = tabber( outPos, d->m_pOptionDialog->m_tabSize );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( d->m_selection.within( line, outPos ) )
|
|
|
|
{
|
|
|
|
selectionString += lineString[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
outPos += spaces;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( d->m_selection.within( line, outPos ) &&
|
|
|
|
!( d->m_bWordWrap && it+1<vectorSize && d3l == d->m_diff3WrapLineVector[it+1].pD3L )
|
|
|
|
)
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
selectionString += '\r';
|
|
|
|
#endif
|
|
|
|
selectionString += '\n';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
++line;
|
|
|
|
}
|
|
|
|
|
|
|
|
return selectionString;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DiffTextWindow::findString( const TQString& s, int& d3vLine, int& posInLine, bool bDirDown, bool bCaseSensitive )
|
|
|
|
{
|
|
|
|
int it = d3vLine;
|
|
|
|
int endIt = bDirDown ? (int)d->m_pDiff3LineVector->size() : -1;
|
|
|
|
int step = bDirDown ? 1 : -1;
|
|
|
|
int startPos = posInLine;
|
|
|
|
|
|
|
|
for( ; it!=endIt; it+=step )
|
|
|
|
{
|
|
|
|
TQString line = d->getString( it );
|
|
|
|
if ( !line.isEmpty() )
|
|
|
|
{
|
|
|
|
int pos = line.find( s, startPos, bCaseSensitive );
|
|
|
|
if ( pos != -1 )
|
|
|
|
{
|
|
|
|
d3vLine = it;
|
|
|
|
posInLine = pos;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
startPos = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindow::convertD3LCoordsToLineCoords( int d3LIdx, int d3LPos, int& line, int& pos )
|
|
|
|
{
|
|
|
|
if( d->m_bWordWrap )
|
|
|
|
{
|
|
|
|
int wrapPos = d3LPos;
|
|
|
|
int wrapLine = convertDiff3LineIdxToLine(d3LIdx);
|
|
|
|
while ( wrapPos > d->m_diff3WrapLineVector[wrapLine].wrapLineLength )
|
|
|
|
{
|
|
|
|
wrapPos -= d->m_diff3WrapLineVector[wrapLine].wrapLineLength;
|
|
|
|
++wrapLine;
|
|
|
|
}
|
|
|
|
pos = wrapPos;
|
|
|
|
line = wrapLine;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pos = d3LPos;
|
|
|
|
line = d3LIdx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindow::convertLineCoordsToD3LCoords( int line, int pos, int& d3LIdx, int& d3LPos )
|
|
|
|
{
|
|
|
|
if( d->m_bWordWrap )
|
|
|
|
{
|
|
|
|
d3LPos = pos;
|
|
|
|
d3LIdx = convertLineToDiff3LineIdx( line );
|
|
|
|
int wrapLine = convertDiff3LineIdxToLine(d3LIdx); // First wrap line belonging to this d3LIdx
|
|
|
|
while ( wrapLine < line )
|
|
|
|
{
|
|
|
|
d3LPos += d->m_diff3WrapLineVector[wrapLine].wrapLineLength;
|
|
|
|
++wrapLine;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d3LPos = pos;
|
|
|
|
d3LIdx = line;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DiffTextWindow::setSelection( int firstLine, int startPos, int lastLine, int endPos, int& l, int& p )
|
|
|
|
{
|
|
|
|
d->m_selection.reset();
|
|
|
|
if ( lastLine >= getNofLines() )
|
|
|
|
{
|
|
|
|
lastLine = getNofLines()-1;
|
|
|
|
|
|
|
|
const Diff3Line* d3l = (*d->m_pDiff3LineVector)[convertLineToDiff3LineIdx(lastLine)];
|
|
|
|
int line = -1;
|
|
|
|
if ( d->m_winIdx==1 ) line = d3l->lineA;
|
|
|
|
if ( d->m_winIdx==2 ) line = d3l->lineB;
|
|
|
|
if ( d->m_winIdx==3 ) line = d3l->lineC;
|
|
|
|
if (line>=0)
|
|
|
|
endPos = d->m_pLineData[line].width( d->m_pOptionDialog->m_tabSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( d->m_bWordWrap && d->m_pDiff3LineVector!=0 )
|
|
|
|
{
|
|
|
|
TQString s1 = d->getString(firstLine);
|
|
|
|
int firstWrapLine = convertDiff3LineIdxToLine(firstLine);
|
|
|
|
int wrapStartPos = startPos;
|
|
|
|
while ( wrapStartPos > d->m_diff3WrapLineVector[firstWrapLine].wrapLineLength )
|
|
|
|
{
|
|
|
|
wrapStartPos -= d->m_diff3WrapLineVector[firstWrapLine].wrapLineLength;
|
|
|
|
s1 = s1.mid(d->m_diff3WrapLineVector[firstWrapLine].wrapLineLength);
|
|
|
|
++firstWrapLine;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString s2 = d->getString(lastLine);
|
|
|
|
int lastWrapLine = convertDiff3LineIdxToLine(lastLine);
|
|
|
|
int wrapEndPos = endPos;
|
|
|
|
while ( wrapEndPos > d->m_diff3WrapLineVector[lastWrapLine].wrapLineLength )
|
|
|
|
{
|
|
|
|
wrapEndPos -= d->m_diff3WrapLineVector[lastWrapLine].wrapLineLength;
|
|
|
|
s2 = s2.mid(d->m_diff3WrapLineVector[lastWrapLine].wrapLineLength);
|
|
|
|
++lastWrapLine;
|
|
|
|
}
|
|
|
|
|
|
|
|
d->m_selection.start( firstWrapLine, convertToPosOnScreen( s1, wrapStartPos, d->m_pOptionDialog->m_tabSize ) );
|
|
|
|
d->m_selection.end( lastWrapLine, convertToPosOnScreen( s2, wrapEndPos, d->m_pOptionDialog->m_tabSize ) );
|
|
|
|
l=firstWrapLine;
|
|
|
|
p=wrapStartPos;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d->m_selection.start( firstLine, convertToPosOnScreen( d->getString(firstLine), startPos, d->m_pOptionDialog->m_tabSize ) );
|
|
|
|
d->m_selection.end( lastLine, convertToPosOnScreen( d->getString(lastLine), endPos, d->m_pOptionDialog->m_tabSize ) );
|
|
|
|
l=firstLine;
|
|
|
|
p=startPos;
|
|
|
|
}
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
int DiffTextWindowData::convertLineOnScreenToLineInSource( int lineOnScreen, e_CoordType coordType, bool bFirstLine )
|
|
|
|
{
|
|
|
|
int line=-1;
|
|
|
|
if (lineOnScreen>=0)
|
|
|
|
{
|
|
|
|
if (coordType==eWrapCoords) return lineOnScreen;
|
|
|
|
int d3lIdx = m_pDiffTextWindow->convertLineToDiff3LineIdx( lineOnScreen );
|
|
|
|
if ( !bFirstLine && d3lIdx >= (int)m_pDiff3LineVector->size() )
|
|
|
|
d3lIdx = m_pDiff3LineVector->size()-1;
|
|
|
|
if (coordType==eD3LLineCoords) return d3lIdx;
|
|
|
|
while ( line<0 && d3lIdx<(int)m_pDiff3LineVector->size() && d3lIdx>=0 )
|
|
|
|
{
|
|
|
|
const Diff3Line* d3l = (*m_pDiff3LineVector)[d3lIdx];
|
|
|
|
if ( m_winIdx==1 ) line = d3l->lineA;
|
|
|
|
if ( m_winIdx==2 ) line = d3l->lineB;
|
|
|
|
if ( m_winIdx==3 ) line = d3l->lineC;
|
|
|
|
if ( bFirstLine )
|
|
|
|
++d3lIdx;
|
|
|
|
else
|
|
|
|
--d3lIdx;
|
|
|
|
}
|
|
|
|
if (coordType==eFileCoords) return line;
|
|
|
|
}
|
|
|
|
return line;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DiffTextWindow::getSelectionRange( int* pFirstLine, int* pLastLine, e_CoordType coordType )
|
|
|
|
{
|
|
|
|
if (pFirstLine)
|
|
|
|
*pFirstLine = d->convertLineOnScreenToLineInSource( d->m_selection.beginLine(), coordType, true );
|
|
|
|
if (pLastLine)
|
|
|
|
*pLastLine = d->convertLineOnScreenToLineInSource( d->m_selection.endLine(), coordType, false );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the number of wrapped lines
|
|
|
|
// if pWrappedLines != 0 then the stringlist will contain the wrapped lines.
|
|
|
|
int wordWrap( const TQString& origLine, int nofColumns, Diff3WrapLine* pDiff3WrapLine )
|
|
|
|
{
|
|
|
|
if (nofColumns<=0)
|
|
|
|
nofColumns = 1;
|
|
|
|
|
|
|
|
int nofNeededLines = 0;
|
|
|
|
int length = origLine.length();
|
|
|
|
|
|
|
|
if (length==0)
|
|
|
|
{
|
|
|
|
nofNeededLines = 1;
|
|
|
|
if( pDiff3WrapLine )
|
|
|
|
{
|
|
|
|
pDiff3WrapLine->wrapLineOffset=0;
|
|
|
|
pDiff3WrapLine->wrapLineLength=0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int pos = 0;
|
|
|
|
|
|
|
|
while ( pos < length )
|
|
|
|
{
|
|
|
|
int wrapPos = pos + nofColumns;
|
|
|
|
|
|
|
|
if ( length-pos <= nofColumns )
|
|
|
|
{
|
|
|
|
wrapPos = length;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int wsPos = max2( origLine.findRev( ' ', wrapPos ), origLine.findRev( '\t', wrapPos ) );
|
|
|
|
|
|
|
|
if ( wsPos > pos )
|
|
|
|
{
|
|
|
|
// Wrap line at wsPos
|
|
|
|
wrapPos = wsPos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( pDiff3WrapLine )
|
|
|
|
{
|
|
|
|
pDiff3WrapLine->wrapLineOffset = pos;
|
|
|
|
pDiff3WrapLine->wrapLineLength = wrapPos-pos;
|
|
|
|
++pDiff3WrapLine;
|
|
|
|
}
|
|
|
|
|
|
|
|
pos = wrapPos;
|
|
|
|
|
|
|
|
++nofNeededLines;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nofNeededLines;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindow::convertSelectionToD3LCoords()
|
|
|
|
{
|
|
|
|
if ( d->m_pDiff3LineVector==0 || ! d->m_bPaintingAllowed || !isVisible() || d->m_selection.isEmpty() )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// convert the d->m_selection to unwrapped coordinates: Later restore to new coords
|
|
|
|
int firstD3LIdx, firstD3LPos;
|
|
|
|
TQString s = d->getLineString( d->m_selection.beginLine() );
|
|
|
|
int firstPosInText = convertToPosInText( s, d->m_selection.beginPos(), d->m_pOptionDialog->m_tabSize );
|
|
|
|
convertLineCoordsToD3LCoords( d->m_selection.beginLine(), firstPosInText, firstD3LIdx, firstD3LPos );
|
|
|
|
|
|
|
|
int lastD3LIdx, lastD3LPos;
|
|
|
|
s = d->getLineString( d->m_selection.endLine() );
|
|
|
|
int lastPosInText = convertToPosInText( s, d->m_selection.endPos(), d->m_pOptionDialog->m_tabSize );
|
|
|
|
convertLineCoordsToD3LCoords( d->m_selection.endLine(), lastPosInText, lastD3LIdx, lastD3LPos );
|
|
|
|
|
|
|
|
//d->m_selection.reset();
|
|
|
|
d->m_selection.start( firstD3LIdx, firstD3LPos );
|
|
|
|
d->m_selection.end( lastD3LIdx, lastD3LPos );
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindow::recalcWordWrap( bool bWordWrap, int wrapLineVectorSize, int nofVisibleColumns )
|
|
|
|
{
|
|
|
|
if ( d->m_pDiff3LineVector==0 || ! d->m_bPaintingAllowed || !isVisible() )
|
|
|
|
{
|
|
|
|
d->m_bWordWrap = bWordWrap;
|
|
|
|
if (!bWordWrap) d->m_diff3WrapLineVector.resize( 0 );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
d->m_bWordWrap = bWordWrap;
|
|
|
|
|
|
|
|
if ( bWordWrap )
|
|
|
|
{
|
|
|
|
d->m_diff3WrapLineVector.resize( wrapLineVectorSize );
|
|
|
|
|
|
|
|
if (nofVisibleColumns<0)
|
|
|
|
nofVisibleColumns = getNofVisibleColumns();
|
|
|
|
else
|
|
|
|
nofVisibleColumns-= d->leftInfoWidth();
|
|
|
|
int i;
|
|
|
|
int wrapLineIdx = 0;
|
|
|
|
int size = d->m_pDiff3LineVector->size();
|
|
|
|
for( i=0; i<size; ++i )
|
|
|
|
{
|
|
|
|
TQString s = d->getString( i );
|
|
|
|
int linesNeeded = wordWrap( s, nofVisibleColumns, wrapLineVectorSize==0 ? 0 : &d->m_diff3WrapLineVector[wrapLineIdx] );
|
|
|
|
Diff3Line& d3l = *(*d->m_pDiff3LineVector)[i];
|
|
|
|
if ( d3l.linesNeededForDisplay<linesNeeded )
|
|
|
|
{
|
|
|
|
d3l.linesNeededForDisplay = linesNeeded;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( wrapLineVectorSize>0 )
|
|
|
|
{
|
|
|
|
int j;
|
|
|
|
for( j=0; j<d3l.linesNeededForDisplay; ++j, ++wrapLineIdx )
|
|
|
|
{
|
|
|
|
Diff3WrapLine& d3wl = d->m_diff3WrapLineVector[wrapLineIdx];
|
|
|
|
d3wl.diff3LineIndex = i;
|
|
|
|
d3wl.pD3L = (*d->m_pDiff3LineVector)[i];
|
|
|
|
if ( j>=linesNeeded )
|
|
|
|
{
|
|
|
|
d3wl.wrapLineOffset=0;
|
|
|
|
d3wl.wrapLineLength=0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( wrapLineVectorSize>0 )
|
|
|
|
{
|
|
|
|
d->m_firstLine = min2( d->m_firstLine, wrapLineVectorSize-1 );
|
|
|
|
d->m_firstColumn = 0;
|
|
|
|
d->m_pDiffTextWindowFrame->setFirstLine( d->m_firstLine );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d->m_diff3WrapLineVector.resize( 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !d->m_selection.isEmpty() && ( !d->m_bWordWrap || wrapLineVectorSize>0 ) )
|
|
|
|
{
|
|
|
|
// Assume unwrapped coordinates
|
|
|
|
//( Why? ->Conversion to unwrapped coords happened a few lines above in this method.
|
|
|
|
// Also see KDiff3App::recalcWordWrap() on the role of wrapLineVectorSize)
|
|
|
|
|
|
|
|
// Wrap them now.
|
|
|
|
|
|
|
|
// convert the d->m_selection to unwrapped coordinates.
|
|
|
|
int firstLine, firstPos;
|
|
|
|
convertD3LCoordsToLineCoords( d->m_selection.beginLine(), d->m_selection.beginPos(), firstLine, firstPos );
|
|
|
|
|
|
|
|
int lastLine, lastPos;
|
|
|
|
convertD3LCoordsToLineCoords( d->m_selection.endLine(), d->m_selection.endPos(), lastLine, lastPos );
|
|
|
|
|
|
|
|
//d->m_selection.reset();
|
|
|
|
d->m_selection.start( firstLine, convertToPosOnScreen( d->getLineString( firstLine ), firstPos, d->m_pOptionDialog->m_tabSize ) );
|
|
|
|
d->m_selection.end( lastLine, convertToPosOnScreen( d->getLineString( lastLine ),lastPos, d->m_pOptionDialog->m_tabSize ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class DiffTextWindowFrameData
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DiffTextWindow* m_pDiffTextWindow;
|
|
|
|
TQLineEdit* m_pFileSelection;
|
|
|
|
TQPushButton* m_pBrowseButton;
|
|
|
|
OptionDialog* m_pOptionDialog;
|
|
|
|
TQLabel* m_pLabel;
|
|
|
|
TQLabel* m_pTopLine;
|
|
|
|
TQWidget* m_pTopLineWidget;
|
|
|
|
};
|
|
|
|
|
|
|
|
DiffTextWindowFrame::DiffTextWindowFrame( TQWidget* pParent, TQStatusBar* pStatusBar, OptionDialog* pOptionDialog, int winIdx )
|
|
|
|
: TQWidget( pParent )
|
|
|
|
{
|
|
|
|
d = new DiffTextWindowFrameData;
|
|
|
|
d->m_pOptionDialog = pOptionDialog;
|
|
|
|
d->m_pTopLineWidget = new TQWidget(this);
|
|
|
|
d->m_pFileSelection = new TQLineEdit(d->m_pTopLineWidget);
|
|
|
|
d->m_pBrowseButton = new TQPushButton( "...",d->m_pTopLineWidget );
|
|
|
|
d->m_pBrowseButton->setFixedWidth( 30 );
|
|
|
|
connect(d->m_pBrowseButton,TQT_SIGNAL(clicked()), this, TQT_SLOT(slotBrowseButtonClicked()));
|
|
|
|
connect(d->m_pFileSelection,TQT_SIGNAL(returnPressed()), this, TQT_SLOT(slotReturnPressed()));
|
|
|
|
|
|
|
|
d->m_pLabel = new TQLabel("A:",d->m_pTopLineWidget);
|
|
|
|
d->m_pTopLine = new TQLabel(d->m_pTopLineWidget);
|
|
|
|
d->m_pDiffTextWindow = 0;
|
|
|
|
d->m_pDiffTextWindow = new DiffTextWindow( this, pStatusBar, pOptionDialog, winIdx );
|
|
|
|
TQHBoxLayout* pHL = new TQHBoxLayout(d->m_pTopLineWidget);
|
|
|
|
pHL->setMargin(2);
|
|
|
|
pHL->setSpacing(2);
|
|
|
|
|
|
|
|
pHL->addWidget( d->m_pLabel, 0 );
|
|
|
|
pHL->addWidget( d->m_pFileSelection, 1 );
|
|
|
|
pHL->addWidget( d->m_pBrowseButton, 0 );
|
|
|
|
pHL->addWidget( d->m_pTopLine, 0 );
|
|
|
|
|
|
|
|
TQVBoxLayout* pVL = new TQVBoxLayout( this, 0, 0 );
|
|
|
|
pVL->addWidget( d->m_pTopLineWidget, 0 );
|
|
|
|
pVL->addWidget( d->m_pDiffTextWindow, 1 );
|
|
|
|
|
|
|
|
d->m_pDiffTextWindow->installEventFilter( this );
|
|
|
|
d->m_pFileSelection->installEventFilter( this );
|
|
|
|
d->m_pBrowseButton->installEventFilter( this );
|
|
|
|
init();
|
|
|
|
}
|
|
|
|
|
|
|
|
DiffTextWindowFrame::~DiffTextWindowFrame()
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindowFrame::init()
|
|
|
|
{
|
|
|
|
DiffTextWindow* pDTW = d->m_pDiffTextWindow;
|
|
|
|
if ( pDTW )
|
|
|
|
{
|
|
|
|
TQString s = pDTW->d->m_filename ;
|
|
|
|
d->m_pFileSelection->setText( TQDir::convertSeparators(s) );
|
|
|
|
TQString winId = pDTW->d->m_winIdx==1 ?
|
|
|
|
( pDTW->d->m_bTriple?"A (Base)":"A") :
|
|
|
|
( pDTW->d->m_winIdx==2 ? "B" : "C" );
|
|
|
|
d->m_pLabel->setText( winId + ":" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Search for the first visible line (search loop needed when no line exist for this file.)
|
|
|
|
int DiffTextWindow::calcTopLineInFile( int firstLine )
|
|
|
|
{
|
|
|
|
int l=-1;
|
|
|
|
for ( int i = convertLineToDiff3LineIdx(firstLine); i<(int)d->m_pDiff3LineVector->size(); ++i )
|
|
|
|
{
|
|
|
|
const Diff3Line* d3l = (*d->m_pDiff3LineVector)[i];
|
|
|
|
l = d3l->getLineInFile(d->m_winIdx);
|
|
|
|
if (l!=-1) break;
|
|
|
|
}
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindowFrame::setFirstLine( int firstLine )
|
|
|
|
{
|
|
|
|
DiffTextWindow* pDTW = d->m_pDiffTextWindow;
|
|
|
|
if ( pDTW && pDTW->d->m_pDiff3LineVector )
|
|
|
|
{
|
|
|
|
TQString s= i18n("Top line");
|
|
|
|
int lineNumberWidth = (int)log10((double)pDTW->d->m_size)+1;
|
|
|
|
|
|
|
|
int l=pDTW->calcTopLineInFile(firstLine);
|
|
|
|
|
|
|
|
int w = d->m_pTopLine->fontMetrics().width(
|
|
|
|
s+" "+TQString().fill('0',lineNumberWidth));
|
|
|
|
d->m_pTopLine->setMinimumWidth( w );
|
|
|
|
|
|
|
|
if (l==-1)
|
|
|
|
s = i18n("End");
|
|
|
|
else
|
|
|
|
s += " " + TQString::number( l+1 );
|
|
|
|
|
|
|
|
d->m_pTopLine->setText( s );
|
|
|
|
d->m_pTopLine->repaint();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DiffTextWindow* DiffTextWindowFrame::getDiffTextWindow()
|
|
|
|
{
|
|
|
|
return d->m_pDiffTextWindow;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DiffTextWindowFrame::eventFilter( TQObject* o, TQEvent* e )
|
|
|
|
{
|
|
|
|
DiffTextWindow* pDTW = d->m_pDiffTextWindow;
|
|
|
|
if ( e->type()==TQEvent::FocusIn || e->type()==TQEvent::FocusOut )
|
|
|
|
{
|
|
|
|
TQColor c1 = d->m_pOptionDialog->m_bgColor;
|
|
|
|
TQColor c2 = pDTW->d->m_cThis;
|
|
|
|
TQPalette p = d->m_pTopLineWidget->palette();
|
|
|
|
if ( e->type()==TQEvent::FocusOut )
|
|
|
|
std::swap(c1,c2);
|
|
|
|
|
|
|
|
p.setColor(TQColorGroup::Background, c2);
|
|
|
|
d->m_pTopLineWidget->setPalette( p );
|
|
|
|
d->m_pBrowseButton->setPalette( p );
|
|
|
|
d->m_pFileSelection->setPalette( p );
|
|
|
|
|
|
|
|
p.setColor(TQColorGroup::Foreground, c1);
|
|
|
|
d->m_pLabel->setPalette( p );
|
|
|
|
d->m_pTopLine->setPalette( p );
|
|
|
|
}
|
|
|
|
if (o == d->m_pFileSelection && e->type()==TQEvent::Drop)
|
|
|
|
{
|
|
|
|
TQDropEvent* d = static_cast<TQDropEvent*>(e);
|
|
|
|
|
|
|
|
if ( TQUriDrag::canDecode( d ) )
|
|
|
|
{
|
|
|
|
TQStringList lst;
|
|
|
|
TQUriDrag::decodeLocalFiles( d, lst );
|
|
|
|
|
|
|
|
if ( lst.count() > 0 )
|
|
|
|
{
|
|
|
|
static_cast<TQLineEdit*>(TQT_TQWIDGET(o))->setText( lst[0] );
|
|
|
|
static_cast<TQLineEdit*>(TQT_TQWIDGET(o))->setFocus();
|
|
|
|
emit fileNameChanged( lst[0], pDTW->d->m_winIdx );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* The following lines work for TQt>4.1 but not for 4.0.x*/
|
|
|
|
/*if ( d->mimeData()->hasUrls() )
|
|
|
|
{
|
|
|
|
TQPtrList<TQUrl> lst = d->mimeData()->urls();
|
|
|
|
if ( !lst.empty() )
|
|
|
|
{
|
|
|
|
static_cast<TQLineEdit*>(o)->setText( lst[0].toLocalFile() );
|
|
|
|
static_cast<TQLineEdit*>(o)->setFocus();
|
|
|
|
emit fileNameChanged( lst[0], pDTW->d->m_winIdx );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindowFrame::slotReturnPressed()
|
|
|
|
{
|
|
|
|
DiffTextWindow* pDTW = d->m_pDiffTextWindow;
|
|
|
|
if ( pDTW->d->m_filename != d->m_pFileSelection->text() )
|
|
|
|
{
|
|
|
|
emit fileNameChanged( d->m_pFileSelection->text(), pDTW->d->m_winIdx );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DiffTextWindowFrame::slotBrowseButtonClicked()
|
|
|
|
{
|
|
|
|
TQString current = d->m_pFileSelection->text();
|
|
|
|
|
|
|
|
KURL newURL = KFileDialog::getOpenURL( current, 0, this);
|
|
|
|
if ( !newURL.isEmpty() )
|
|
|
|
{
|
|
|
|
DiffTextWindow* pDTW = d->m_pDiffTextWindow;
|
|
|
|
emit fileNameChanged( newURL.url(), pDTW->d->m_winIdx );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQCString encodeString( const TQString& s )
|
|
|
|
{
|
|
|
|
TQTextCodec* c = TQTextCodec::codecForLocale();
|
|
|
|
if (c!=0)
|
|
|
|
return c->fromUnicode( s );
|
|
|
|
else
|
|
|
|
return TQCString( s.latin1() );
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "difftextwindow.moc"
|