annotate kdiff3/src/difftextwindow.cpp @ 68:d7cafcda8c99

KDiff3 0.9.87
author joachim99
date Mon, 31 Jan 2005 22:30:47 +0000
parents efe33e938730
children 8febbfb1148c
rev   line source
joachim99@8 1 /***************************************************************************
joachim99@8 2 difftextwindow.cpp - description
joachim99@8 3 -------------------
joachim99@8 4 begin : Mon Apr 8 2002
joachim99@58 5 copyright : (C) 2002-2004 by Joachim Eibl
joachim99@8 6 email : joachim.eibl@gmx.de
joachim99@8 7 ***************************************************************************/
joachim99@8 8
joachim99@8 9 /***************************************************************************
joachim99@8 10 * *
joachim99@8 11 * This program is free software; you can redistribute it and/or modify *
joachim99@8 12 * it under the terms of the GNU General Public License as published by *
joachim99@8 13 * the Free Software Foundation; either version 2 of the License, or *
joachim99@8 14 * (at your option) any later version. *
joachim99@8 15 * *
joachim99@8 16 ***************************************************************************/
joachim99@8 17
joachim99@8 18 #include <iostream>
joachim99@8 19 #include "diff.h"
joachim99@8 20 #include "merger.h"
joachim99@8 21 #include <qpainter.h>
joachim99@8 22 #include <assert.h>
joachim99@8 23 #include <qpixmap.h>
joachim99@8 24 #include <qstatusbar.h>
joachim99@8 25 #include <qapplication.h>
joachim99@8 26 #include <qtooltip.h>
joachim99@8 27 #include <qfont.h>
joachim99@66 28 #include <qstringlist.h>
joachim99@8 29 #include <optiondialog.h>
joachim99@8 30 #include <math.h>
joachim99@8 31 #include <qdragobject.h>
joachim99@51 32 #include <klocale.h>
joachim99@8 33
joachim99@53 34 #undef leftInfoWidth
joachim99@8 35 #define leftInfoWidth (4+m_lineNumberWidth) // Nr of information columns on left side
joachim99@8 36
joachim99@8 37
joachim99@8 38 DiffTextWindow::DiffTextWindow(
joachim99@8 39 QWidget* pParent,
joachim99@8 40 QStatusBar* pStatusBar,
joachim99@8 41 OptionDialog* pOptionDialog
joachim99@8 42 )
joachim99@8 43 : QWidget(pParent, 0, WRepaintNoErase)
joachim99@8 44 {
joachim99@8 45 setFocusPolicy( QWidget::ClickFocus );
joachim99@8 46 setAcceptDrops( true );
joachim99@8 47
joachim99@8 48 m_pOptionDialog = pOptionDialog;
joachim99@8 49 init( 0, 0, 0, 0, 0, false );
joachim99@8 50
joachim99@8 51 setBackgroundMode( PaletteBase );
joachim99@8 52 setMinimumSize(QSize(20,20));
joachim99@8 53
joachim99@8 54 m_pStatusBar = pStatusBar;
joachim99@8 55 m_bPaintingAllowed = true;
joachim99@66 56 m_bWordWrap = false;
joachim99@27 57
joachim99@27 58 setFont(m_pOptionDialog->m_font);
joachim99@8 59 }
joachim99@8 60
joachim99@8 61
joachim99@8 62 void DiffTextWindow::init(
joachim99@8 63 const QString& filename,
joachim99@58 64 const LineData* pLineData,
joachim99@8 65 int size,
joachim99@8 66 const Diff3LineVector* pDiff3LineVector,
joachim99@8 67 int winIdx,
joachim99@8 68 bool bTriple
joachim99@8 69 )
joachim99@8 70 {
joachim99@8 71 m_filename = filename;
joachim99@8 72 m_pLineData = pLineData;
joachim99@8 73 m_size = size;
joachim99@8 74 m_pDiff3LineVector = pDiff3LineVector;
joachim99@66 75 m_diff3WrapLineVector.clear();
joachim99@8 76 m_winIdx = winIdx;
joachim99@8 77
joachim99@8 78 m_firstLine = 0;
joachim99@8 79 m_oldFirstLine = -1;
joachim99@8 80 m_firstColumn = 0;
joachim99@8 81 m_oldFirstColumn = -1;
joachim99@8 82 m_bTriple = bTriple;
joachim99@8 83 m_scrollDeltaX=0;
joachim99@8 84 m_scrollDeltaY=0;
joachim99@8 85 m_bMyUpdate = false;
joachim99@8 86 m_fastSelectorLine1 = 0;
joachim99@8 87 m_fastSelectorNofLines = 0;
joachim99@8 88 m_lineNumberWidth = 0;
joachim99@8 89 selection.reset();
joachim99@8 90 selection.oldFirstLine = -1; // reset is not enough here.
joachim99@8 91 selection.oldLastLine = -1;
joachim99@8 92 selection.lastLine = -1;
joachim99@8 93
joachim99@8 94 QToolTip::remove(this);
joachim99@8 95 QToolTip::add( this, QRect( 0,0, 1024, fontMetrics().height() ), m_filename );
joachim99@8 96 update();
joachim99@8 97 }
joachim99@8 98
joachim99@8 99 void DiffTextWindow::setPaintingAllowed( bool bAllowPainting )
joachim99@8 100 {
joachim99@8 101 if (m_bPaintingAllowed != bAllowPainting)
joachim99@8 102 {
joachim99@8 103 m_bPaintingAllowed = bAllowPainting;
joachim99@8 104 if ( m_bPaintingAllowed ) update();
joachim99@8 105 }
joachim99@8 106 }
joachim99@8 107
joachim99@8 108 void DiffTextWindow::dragEnterEvent( QDragEnterEvent* e )
joachim99@8 109 {
joachim99@8 110 e->accept( QUriDrag::canDecode(e) || QTextDrag::canDecode(e) );
joachim99@8 111 // Note that the corresponding drop is handled in KDiff3App::eventFilter().
joachim99@8 112 }
joachim99@8 113
joachim99@8 114 void DiffTextWindow::setFirstLine(int firstLine)
joachim99@8 115 {
joachim99@66 116 int fontHeight = fontMetrics().height();
joachim99@66 117 int topLineYOffset = fontHeight + 3;
joachim99@66 118
joachim99@66 119 int newFirstLine = max2(0,firstLine);
joachim99@66 120
joachim99@66 121 int deltaY = fontHeight * ( m_firstLine - newFirstLine );
joachim99@66 122
joachim99@66 123 m_firstLine = newFirstLine;
joachim99@66 124
joachim99@66 125 if ( m_scrollDeltaY > 0 )
joachim99@66 126 {
joachim99@66 127 update( 0, height()-fontHeight*3, width(), fontHeight*3 );
joachim99@66 128 }
joachim99@66 129 else if ( m_scrollDeltaY<0 )
joachim99@66 130 {
joachim99@66 131 update( 0, 0, width(), topLineYOffset+fontHeight*2 );
joachim99@66 132 }
joachim99@66 133 else
joachim99@66 134 {
joachim99@66 135 update( 0, 0, width(), topLineYOffset );
joachim99@66 136 }
joachim99@66 137
joachim99@66 138 QRect r( 0, topLineYOffset, width(), height()-topLineYOffset );
joachim99@66 139 QWidget::scroll( 0, deltaY, r );
joachim99@8 140 }
joachim99@8 141
joachim99@8 142 void DiffTextWindow::setFirstColumn(int firstCol)
joachim99@8 143 {
joachim99@66 144 int fontHeight = fontMetrics().height();
joachim99@66 145 int fontWidth = fontMetrics().width('W');
joachim99@66 146 int topLineYOffset = fontHeight + 3;
joachim99@66 147 int xOffset = leftInfoWidth * fontWidth;
joachim99@66 148
joachim99@66 149 int newFirstColumn = max2(0,firstCol);
joachim99@66 150
joachim99@66 151 int deltaX = fontWidth * ( m_firstColumn - newFirstColumn );
joachim99@66 152
joachim99@66 153 m_firstColumn = newFirstColumn;
joachim99@66 154
joachim99@68 155 QRect r( xOffset, topLineYOffset, width()-xOffset, height()-topLineYOffset );
joachim99@68 156
joachim99@68 157 if ( m_pOptionDialog->m_bRightToLeftLanguage )
joachim99@68 158 {
joachim99@68 159 deltaX = -deltaX;
joachim99@68 160 r = QRect( width()-1-xOffset, topLineYOffset, -(width()-xOffset), height()-topLineYOffset ).normalize();
joachim99@68 161 }
joachim99@68 162
joachim99@66 163 QWidget::scroll( deltaX, 0, r );
joachim99@8 164 }
joachim99@8 165
joachim99@8 166 int DiffTextWindow::getNofColumns()
joachim99@8 167 {
joachim99@66 168 if (m_bWordWrap)
joachim99@8 169 {
joachim99@66 170 return getNofVisibleColumns();
joachim99@8 171 }
joachim99@66 172 else
joachim99@66 173 {
joachim99@66 174 int nofColumns = 0;
joachim99@66 175 for( int i = 0; i< m_size; ++i )
joachim99@66 176 {
joachim99@66 177 if ( m_pLineData[i].width() > nofColumns )
joachim99@66 178 nofColumns = m_pLineData[i].width();
joachim99@66 179 }
joachim99@66 180 return nofColumns;
joachim99@66 181 }
joachim99@8 182 }
joachim99@8 183
joachim99@8 184 int DiffTextWindow::getNofLines()
joachim99@8 185 {
joachim99@66 186 return m_bWordWrap ? m_diff3WrapLineVector.size() :
joachim99@66 187 m_pDiff3LineVector->size();
joachim99@66 188 }
joachim99@66 189
joachim99@66 190
joachim99@66 191 int DiffTextWindow::convertLineToDiff3LineIdx( int line )
joachim99@66 192 {
joachim99@66 193 if ( m_bWordWrap && m_diff3WrapLineVector.size()>0 )
joachim99@66 194 return m_diff3WrapLineVector[ min2( line, (int)m_diff3WrapLineVector.size()-1 ) ].diff3LineIndex;
joachim99@66 195 else
joachim99@66 196 return line;
joachim99@66 197 }
joachim99@66 198
joachim99@66 199 int DiffTextWindow::convertDiff3LineIdxToLine( int d3lIdx )
joachim99@66 200 {
joachim99@66 201 if ( m_bWordWrap && m_pDiff3LineVector!=0 && m_pDiff3LineVector->size()>0 )
joachim99@66 202 return (*m_pDiff3LineVector)[ min2( d3lIdx, (int)m_pDiff3LineVector->size()-1 ) ]->sumLinesNeededForDisplay;
joachim99@66 203 else
joachim99@66 204 return d3lIdx;
joachim99@8 205 }
joachim99@8 206
joachim99@8 207 /** Returns a line number where the linerange [line, line+nofLines] can
joachim99@8 208 be displayed best. If it fits into the currently visible range then
joachim99@8 209 the returned value is the current firstLine.
joachim99@8 210 */
joachim99@8 211 int getBestFirstLine( int line, int nofLines, int firstLine, int visibleLines )
joachim99@8 212 {
joachim99@8 213 int newFirstLine = firstLine;
joachim99@8 214 if ( line < firstLine || line + nofLines + 2 > firstLine + visibleLines )
joachim99@8 215 {
joachim99@8 216 if ( nofLines > visibleLines || nofLines <= ( 2*visibleLines / 3 - 1) )
joachim99@8 217 newFirstLine = line - visibleLines/3;
joachim99@8 218 else
joachim99@8 219 newFirstLine = line - (visibleLines - nofLines);
joachim99@8 220 }
joachim99@8 221
joachim99@8 222 return newFirstLine;
joachim99@8 223 }
joachim99@8 224
joachim99@8 225
joachim99@8 226 void DiffTextWindow::setFastSelectorRange( int line1, int nofLines )
joachim99@66 227 {
joachim99@8 228 m_fastSelectorLine1 = line1;
joachim99@8 229 m_fastSelectorNofLines = nofLines;
joachim99@8 230 if ( isVisible() )
joachim99@8 231 {
joachim99@66 232 int newFirstLine = getBestFirstLine(
joachim99@66 233 convertDiff3LineIdxToLine(m_fastSelectorLine1),
joachim99@66 234 convertDiff3LineIdxToLine(m_fastSelectorLine1+m_fastSelectorNofLines)-convertDiff3LineIdxToLine(m_fastSelectorLine1),
joachim99@66 235 m_firstLine,
joachim99@66 236 getNofVisibleLines()
joachim99@66 237 );
joachim99@8 238 if ( newFirstLine != m_firstLine )
joachim99@8 239 {
joachim99@8 240 scroll( 0, newFirstLine - m_firstLine );
joachim99@8 241 }
joachim99@8 242
joachim99@8 243 update();
joachim99@8 244 }
joachim99@8 245 }
joachim99@8 246
joachim99@8 247
joachim99@66 248 void DiffTextWindow::showStatusLine(int line )
joachim99@8 249 {
joachim99@66 250 int d3lIdx = convertLineToDiff3LineIdx( line );
joachim99@8 251 int l=0;
joachim99@66 252 const Diff3Line* pD3l = (*m_pDiff3LineVector)[d3lIdx];
joachim99@66 253 if(d3lIdx >= 0 && d3lIdx<(int)m_pDiff3LineVector->size() && pD3l != 0 )
joachim99@8 254 {
joachim99@66 255 if ( m_winIdx==1 ) l = pD3l->lineA;
joachim99@66 256 else if ( m_winIdx==2 ) l = pD3l->lineB;
joachim99@66 257 else if ( m_winIdx==3 ) l = pD3l->lineC;
joachim99@8 258 else assert(false);
joachim99@8 259
joachim99@8 260 QString s;
joachim99@8 261 if ( l!=-1 )
joachim99@66 262 s.sprintf("File %s: Line %d", m_filename.ascii(), l+1 );
joachim99@8 263 else
joachim99@66 264 s.sprintf("File %s: Line not available", m_filename.ascii() );
joachim99@66 265 if (m_pStatusBar!=0) m_pStatusBar->message(s);
joachim99@8 266 }
joachim99@8 267 }
joachim99@8 268
joachim99@66 269 void DiffTextWindow::focusInEvent(QFocusEvent* e)
joachim99@66 270 {
joachim99@66 271 emit gotFocus();
joachim99@66 272 QWidget::focusInEvent(e);
joachim99@66 273 }
joachim99@8 274
joachim99@8 275 void DiffTextWindow::mousePressEvent ( QMouseEvent* e )
joachim99@8 276 {
joachim99@8 277 if ( e->button() == LeftButton )
joachim99@8 278 {
joachim99@8 279 int line;
joachim99@8 280 int pos;
joachim99@8 281 convertToLinePos( e->x(), e->y(), line, pos );
joachim99@8 282 if ( pos < m_firstColumn )
joachim99@8 283 {
joachim99@66 284 emit setFastSelectorLine( convertLineToDiff3LineIdx(line) );
joachim99@8 285 selection.firstLine = -1; // Disable current selection
joachim99@8 286 }
joachim99@8 287 else
joachim99@8 288 { // Selection
joachim99@8 289 resetSelection();
joachim99@8 290 selection.start( line, pos );
joachim99@8 291 selection.end( line, pos );
joachim99@8 292
joachim99@66 293 showStatusLine( line );
joachim99@8 294 }
joachim99@8 295 }
joachim99@8 296 }
joachim99@8 297
joachim99@68 298 bool isCTokenChar( QChar c )
joachim99@8 299 {
joachim99@8 300 return (c=='_') ||
joachim99@8 301 ( c>='A' && c<='Z' ) || ( c>='a' && c<='z' ) ||
joachim99@8 302 (c>='0' && c<='9');
joachim99@8 303 }
joachim99@8 304
joachim99@8 305 /// Calculate where a token starts and ends, given the x-position on screen.
joachim99@68 306 void calcTokenPos( const QString& s, int posOnScreen, int& pos1, int& pos2 )
joachim99@8 307 {
joachim99@8 308 // Cursor conversions that consider g_tabSize
joachim99@68 309 int pos = convertToPosInText( s, max2( 0, posOnScreen ) );
joachim99@68 310 if ( pos>=(int)s.length() )
joachim99@8 311 {
joachim99@68 312 pos1=s.length();
joachim99@68 313 pos2=s.length();
joachim99@8 314 return;
joachim99@8 315 }
joachim99@8 316
joachim99@8 317 pos1 = pos;
joachim99@8 318 pos2 = pos+1;
joachim99@8 319
joachim99@68 320 if( isCTokenChar( s[pos1] ) )
joachim99@8 321 {
joachim99@68 322 while( pos1>=0 && isCTokenChar( s[pos1] ) )
joachim99@8 323 --pos1;
joachim99@8 324 ++pos1;
joachim99@8 325
joachim99@68 326 while( pos2<(int)s.length() && isCTokenChar( s[pos2] ) )
joachim99@8 327 ++pos2;
joachim99@8 328 }
joachim99@8 329 }
joachim99@8 330
joachim99@8 331 void DiffTextWindow::mouseDoubleClickEvent( QMouseEvent* e )
joachim99@8 332 {
joachim99@8 333 if ( e->button() == LeftButton )
joachim99@8 334 {
joachim99@8 335 int line;
joachim99@8 336 int pos;
joachim99@8 337 convertToLinePos( e->x(), e->y(), line, pos );
joachim99@8 338
joachim99@8 339 // Get the string data of the current line
joachim99@68 340 QString s;
joachim99@66 341 if ( m_bWordWrap )
joachim99@66 342 {
joachim99@66 343 const Diff3WrapLine& d = m_diff3WrapLineVector[line];
joachim99@66 344 s = getString( d.diff3LineIndex ).mid( d.wrapLineOffset, d.wrapLineLength );
joachim99@66 345 }
joachim99@66 346 else
joachim99@66 347 {
joachim99@66 348 s = getString( line );
joachim99@66 349 }
joachim99@66 350
joachim99@8 351 if ( ! s.isEmpty() )
joachim99@8 352 {
joachim99@8 353 int pos1, pos2;
joachim99@68 354 calcTokenPos( s, pos, pos1, pos2 );
joachim99@8 355
joachim99@8 356 resetSelection();
joachim99@8 357 selection.start( line, convertToPosOnScreen( s, pos1 ) );
joachim99@8 358 selection.end( line, convertToPosOnScreen( s, pos2 ) );
joachim99@8 359 update();
joachim99@8 360 // emit selectionEnd() happens in the mouseReleaseEvent.
joachim99@66 361 showStatusLine( line );
joachim99@8 362 }
joachim99@8 363 }
joachim99@8 364 }
joachim99@8 365
joachim99@8 366 void DiffTextWindow::mouseReleaseEvent ( QMouseEvent * /*e*/ )
joachim99@8 367 {
joachim99@8 368 //if ( e->button() == LeftButton )
joachim99@8 369 {
joachim99@8 370 killTimers();
joachim99@8 371 if (selection.firstLine != -1 )
joachim99@8 372 {
joachim99@8 373 emit selectionEnd();
joachim99@8 374 }
joachim99@8 375 }
joachim99@8 376 m_scrollDeltaX=0;
joachim99@8 377 m_scrollDeltaY=0;
joachim99@8 378 }
joachim99@8 379
joachim99@8 380 void DiffTextWindow::mouseMoveEvent ( QMouseEvent * e )
joachim99@8 381 {
joachim99@8 382 int line;
joachim99@8 383 int pos;
joachim99@8 384 convertToLinePos( e->x(), e->y(), line, pos );
joachim99@8 385 if (selection.firstLine != -1 )
joachim99@8 386 {
joachim99@8 387 selection.end( line, pos );
joachim99@8 388
joachim99@66 389 showStatusLine( line );
joachim99@8 390
joachim99@8 391 // Scroll because mouse moved out of the window
joachim99@8 392 const QFontMetrics& fm = fontMetrics();
joachim99@8 393 int fontHeight = fm.height();
joachim99@8 394 int fontWidth = fm.width('W');
joachim99@8 395 int topLineYOffset = fontHeight + 3;
joachim99@8 396 int deltaX=0;
joachim99@8 397 int deltaY=0;
joachim99@68 398 if ( ! m_pOptionDialog->m_bRightToLeftLanguage )
joachim99@68 399 {
joachim99@68 400 if ( e->x() < leftInfoWidth*fontWidth ) deltaX=-1;
joachim99@68 401 if ( e->x() > width() ) deltaX=+1;
joachim99@68 402 }
joachim99@68 403 else
joachim99@68 404 {
joachim99@68 405 if ( e->x() > width()-1-leftInfoWidth*fontWidth ) deltaX=-1;
joachim99@68 406 if ( e->x() < fontWidth ) deltaX=+1;
joachim99@68 407 }
joachim99@8 408 if ( e->y() < topLineYOffset ) deltaY=-1;
joachim99@8 409 if ( e->y() > height() ) deltaY=+1;
joachim99@66 410 if ( deltaX != 0 && m_scrollDeltaX!=deltaX || deltaY!= 0 && m_scrollDeltaY!=deltaY )
joachim99@8 411 {
joachim99@66 412 m_scrollDeltaX = deltaX;
joachim99@66 413 m_scrollDeltaY = deltaY;
joachim99@8 414 emit scroll( deltaX, deltaY );
joachim99@66 415 startTimer(50);
joachim99@66 416 }
joachim99@66 417 else
joachim99@66 418 {
joachim99@66 419 m_scrollDeltaX = deltaX;
joachim99@66 420 m_scrollDeltaY = deltaY;
joachim99@66 421 myUpdate(0);
joachim99@8 422 }
joachim99@8 423 }
joachim99@8 424 }
joachim99@8 425
joachim99@8 426
joachim99@8 427 void DiffTextWindow::myUpdate(int afterMilliSecs)
joachim99@8 428 {
joachim99@8 429 killTimers();
joachim99@8 430 m_bMyUpdate = true;
joachim99@8 431 startTimer( afterMilliSecs );
joachim99@8 432 }
joachim99@8 433
joachim99@8 434 void DiffTextWindow::timerEvent(QTimerEvent*)
joachim99@8 435 {
joachim99@8 436 killTimers();
joachim99@8 437
joachim99@8 438 if ( m_bMyUpdate )
joachim99@8 439 {
joachim99@8 440 paintEvent( 0 );
joachim99@8 441 m_bMyUpdate = false;
joachim99@8 442 }
joachim99@8 443
joachim99@8 444 if ( m_scrollDeltaX != 0 || m_scrollDeltaY != 0 )
joachim99@8 445 {
joachim99@8 446 selection.end( selection.lastLine + m_scrollDeltaY, selection.lastPos + m_scrollDeltaX );
joachim99@8 447 emit scroll( m_scrollDeltaX, m_scrollDeltaY );
joachim99@8 448 killTimers();
joachim99@8 449 startTimer(50);
joachim99@8 450 }
joachim99@8 451 }
joachim99@8 452
joachim99@8 453 void DiffTextWindow::resetSelection()
joachim99@8 454 {
joachim99@8 455 selection.reset();
joachim99@8 456 update();
joachim99@8 457 }
joachim99@8 458
joachim99@8 459 void DiffTextWindow::convertToLinePos( int x, int y, int& line, int& pos )
joachim99@8 460 {
joachim99@8 461 const QFontMetrics& fm = fontMetrics();
joachim99@8 462 int fontHeight = fm.height();
joachim99@8 463 int fontWidth = fm.width('W');
joachim99@8 464 int xOffset = (leftInfoWidth-m_firstColumn)*fontWidth;
joachim99@8 465
joachim99@8 466 int topLineYOffset = fontHeight + 3;
joachim99@8 467
joachim99@8 468 int yOffset = topLineYOffset - m_firstLine * fontHeight;
joachim99@8 469
joachim99@8 470 line = ( y - yOffset ) / fontHeight;
joachim99@68 471 if ( ! m_pOptionDialog->m_bRightToLeftLanguage )
joachim99@68 472 pos = ( x - xOffset ) / fontWidth;
joachim99@68 473 else
joachim99@68 474 pos = ( (width() - 1 - x) - xOffset ) / fontWidth;
joachim99@8 475 }
joachim99@8 476
joachim99@8 477 int Selection::firstPosInLine(int l)
joachim99@8 478 {
joachim99@8 479 assert( firstLine != -1 );
joachim99@8 480
joachim99@8 481 int l1 = firstLine;
joachim99@8 482 int l2 = lastLine;
joachim99@8 483 int p1 = firstPos;
joachim99@8 484 int p2 = lastPos;
joachim99@8 485 if ( l1>l2 ){ std::swap(l1,l2); std::swap(p1,p2); }
joachim99@8 486 if ( l1==l2 && p1>p2 ){ std::swap(p1,p2); }
joachim99@8 487
joachim99@8 488 if ( l==l1 )
joachim99@8 489 return p1;
joachim99@8 490 return 0;
joachim99@8 491 }
joachim99@8 492
joachim99@8 493 int Selection::lastPosInLine(int l)
joachim99@8 494 {
joachim99@8 495 assert( firstLine != -1 );
joachim99@8 496
joachim99@8 497 int l1 = firstLine;
joachim99@8 498 int l2 = lastLine;
joachim99@8 499 int p1 = firstPos;
joachim99@8 500 int p2 = lastPos;
joachim99@8 501
joachim99@8 502 if ( l1>l2 ){ std::swap(l1,l2); std::swap(p1,p2); }
joachim99@8 503 if ( l1==l2 && p1>p2 ){ std::swap(p1,p2); }
joachim99@8 504
joachim99@8 505 if ( l==l2 )
joachim99@8 506 return p2;
joachim99@8 507 return INT_MAX;
joachim99@8 508 }
joachim99@8 509
joachim99@8 510 bool Selection::within( int l, int p )
joachim99@8 511 {
joachim99@8 512 if ( firstLine == -1 ) return false;
joachim99@8 513 int l1 = firstLine;
joachim99@8 514 int l2 = lastLine;
joachim99@8 515 int p1 = firstPos;
joachim99@8 516 int p2 = lastPos;
joachim99@8 517 if ( l1>l2 ){ std::swap(l1,l2); std::swap(p1,p2); }
joachim99@8 518 if ( l1==l2 && p1>p2 ){ std::swap(p1,p2); }
joachim99@8 519 if( l1 <= l && l <= l2 )
joachim99@8 520 {
joachim99@8 521 if ( l1==l2 )
joachim99@8 522 return p>=p1 && p<p2;
joachim99@8 523 if ( l==l1 )
joachim99@8 524 return p>=p1;
joachim99@8 525 if ( l==l2 )
joachim99@8 526 return p<p2;
joachim99@8 527 return true;
joachim99@8 528 }
joachim99@8 529 return false;
joachim99@8 530 }
joachim99@8 531
joachim99@8 532 bool Selection::lineWithin( int l )
joachim99@8 533 {
joachim99@8 534 if ( firstLine == -1 ) return false;
joachim99@8 535 int l1 = firstLine;
joachim99@8 536 int l2 = lastLine;
joachim99@8 537
joachim99@8 538 if ( l1>l2 ){ std::swap(l1,l2); }
joachim99@8 539
joachim99@8 540 return ( l1 <= l && l <= l2 );
joachim99@8 541 }
joachim99@8 542
joachim99@68 543
joachim99@8 544 void DiffTextWindow::writeLine(
joachim99@68 545 MyPainter& p,
joachim99@8 546 const LineData* pld,
joachim99@8 547 const DiffList* pLineDiff1,
joachim99@8 548 const DiffList* pLineDiff2,
joachim99@8 549 int line,
joachim99@8 550 int whatChanged,
joachim99@8 551 int whatChanged2,
joachim99@66 552 int srcLineNr,
joachim99@66 553 int wrapLineOffset,
joachim99@66 554 int wrapLineLength,
joachim99@66 555 bool bWrapLine
joachim99@8 556 )
joachim99@8 557 {
joachim99@8 558 QFont normalFont = font();
joachim99@8 559 QFont diffFont = normalFont;
joachim99@8 560 diffFont.setItalic( m_pOptionDialog->m_bItalicForDeltas );
joachim99@8 561 const QFontMetrics& fm = fontMetrics();
joachim99@8 562 int fontHeight = fm.height();
joachim99@8 563 int fontAscent = fm.ascent();
joachim99@8 564 int fontDescent = fm.descent();
joachim99@8 565 int fontWidth = fm.width('W');
joachim99@8 566 int topLineYOffset = fontHeight + 3;
joachim99@8 567
joachim99@8 568 int xOffset = (leftInfoWidth - m_firstColumn)*fontWidth;
joachim99@8 569 int yOffset = (line-m_firstLine) * fontHeight + topLineYOffset;
joachim99@8 570
joachim99@8 571 QRect lineRect( 0, yOffset, width(), fontHeight );
joachim99@8 572 if ( ! m_invalidRect.intersects( lineRect ) )
joachim99@8 573 return;
joachim99@8 574
joachim99@66 575 int fastSelectorLine1 = convertDiff3LineIdxToLine(m_fastSelectorLine1);
joachim99@66 576 int fastSelectorLine2 = convertDiff3LineIdxToLine(m_fastSelectorLine1+m_fastSelectorNofLines)-1;
joachim99@66 577
joachim99@66 578 bool bFastSelectionRange = (line>=fastSelectorLine1 && line<= fastSelectorLine2 );
joachim99@8 579 QColor bgColor = m_pOptionDialog->m_bgColor;
joachim99@8 580 QColor diffBgColor = m_pOptionDialog->m_diffBgColor;
joachim99@8 581
joachim99@8 582 if ( bFastSelectionRange )
joachim99@8 583 {
joachim99@8 584 bgColor = m_pOptionDialog->m_currentRangeBgColor;
joachim99@8 585 diffBgColor = m_pOptionDialog->m_currentRangeDiffBgColor;
joachim99@8 586 }
joachim99@8 587
joachim99@8 588 // QRect winRect = rect(); //p.window();
joachim99@8 589 if ( yOffset+fontHeight<0 || height() + fontHeight < yOffset )
joachim99@8 590 return;
joachim99@8 591
joachim99@8 592 int changed = whatChanged;
joachim99@8 593 if ( pLineDiff1 != 0 ) changed |= 1;
joachim99@8 594 if ( pLineDiff2 != 0 ) changed |= 2;
joachim99@8 595
joachim99@8 596 QColor c = m_pOptionDialog->m_fgColor;
joachim99@8 597 if ( changed == 2 ) {
joachim99@8 598 c = m_cDiff2;
joachim99@8 599 } else if ( changed == 1 ) {
joachim99@8 600 c = m_cDiff1;
joachim99@8 601 } else if ( changed == 3 ) {
joachim99@8 602 c = m_cDiffBoth;
joachim99@8 603 }
joachim99@8 604
joachim99@8 605 p.fillRect( leftInfoWidth*fontWidth, yOffset, width(), fontHeight, bgColor );
joachim99@51 606
joachim99@8 607 if (pld!=0)
joachim99@8 608 {
joachim99@8 609 // First calculate the "changed" information for each character.
joachim99@8 610 int i=0;
joachim99@8 611 std::vector<UINT8> charChanged( pld->size );
joachim99@8 612 if ( pLineDiff1!=0 || pLineDiff2 != 0 )
joachim99@8 613 {
joachim99@8 614 Merger merger( pLineDiff1, pLineDiff2 );
joachim99@8 615 while( ! merger.isEndReached() && i<pld->size )
joachim99@8 616 {
joachim99@8 617 if ( i < pld->size )
joachim99@8 618 {
joachim99@8 619 charChanged[i] = merger.whatChanged();
joachim99@8 620 ++i;
joachim99@8 621 }
joachim99@8 622 merger.next();
joachim99@8 623 }
joachim99@8 624 }
joachim99@8 625
joachim99@68 626 QString s=" ";
joachim99@8 627 // Convert tabs
joachim99@8 628 int outPos = 0;
joachim99@68 629
joachim99@68 630 QString lineString( pld->pLine, pld->size );
joachim99@68 631 int lineLength = m_bWordWrap ? wrapLineOffset+wrapLineLength : lineString.length();
joachim99@66 632
joachim99@66 633 for( i=wrapLineOffset; i<lineLength; ++i )
joachim99@8 634 {
joachim99@8 635 int spaces = 1;
joachim99@8 636
joachim99@68 637 if ( lineString[i]=='\t' )
joachim99@8 638 {
joachim99@8 639 spaces = tabber( outPos, g_tabSize );
joachim99@8 640 s[0] = ' ';
joachim99@8 641 }
joachim99@8 642 else
joachim99@8 643 {
joachim99@68 644 s[0] = lineString[i];
joachim99@8 645 }
joachim99@8 646
joachim99@8 647 QColor c = m_pOptionDialog->m_fgColor;
joachim99@8 648 int cchanged = charChanged[i] | whatChanged;
joachim99@8 649
joachim99@8 650 if ( cchanged == 2 ) {
joachim99@8 651 c = m_cDiff2;
joachim99@8 652 } else if ( cchanged == 1 ) {
joachim99@8 653 c = m_cDiff1;
joachim99@8 654 } else if ( cchanged == 3 ) {
joachim99@8 655 c = m_cDiffBoth;
joachim99@8 656 }
joachim99@8 657
joachim99@51 658 if ( c!=m_pOptionDialog->m_fgColor && whatChanged2==0 && !m_pOptionDialog->m_bShowWhiteSpace )
joachim99@51 659 {
joachim99@51 660 // The user doesn't want to see highlighted white space.
joachim99@51 661 c = m_pOptionDialog->m_fgColor;
joachim99@51 662 }
joachim99@51 663
joachim99@8 664 QRect outRect( xOffset + fontWidth*outPos, yOffset, fontWidth*spaces, fontHeight );
joachim99@68 665 if ( m_pOptionDialog->m_bRightToLeftLanguage )
joachim99@68 666 outRect = QRect( width()-1-(xOffset + fontWidth*outPos), yOffset, -fontWidth*spaces, fontHeight ).normalize();
joachim99@8 667 if ( m_invalidRect.intersects( outRect ) )
joachim99@8 668 {
joachim99@8 669 if( !selection.within( line, outPos ) )
joachim99@8 670 {
joachim99@51 671
joachim99@8 672 if( c!=m_pOptionDialog->m_fgColor )
joachim99@8 673 {
joachim99@8 674 QColor lightc = diffBgColor;
joachim99@8 675 p.fillRect( xOffset + fontWidth*outPos, yOffset,
joachim99@8 676 fontWidth*spaces, fontHeight, lightc );
joachim99@8 677 p.setFont(diffFont);
joachim99@8 678 }
joachim99@8 679
joachim99@8 680 p.setPen( c );
joachim99@8 681 if ( s[0]==' ' && c!=m_pOptionDialog->m_fgColor && charChanged[i]!=0 )
joachim99@8 682 {
joachim99@51 683 if ( m_pOptionDialog->m_bShowWhiteSpaceCharacters && m_pOptionDialog->m_bShowWhiteSpace)
joachim99@8 684 {
joachim99@8 685 p.fillRect( xOffset + fontWidth*outPos, yOffset+fontAscent,
joachim99@8 686 fontWidth*spaces-1, fontDescent+1, c );
joachim99@8 687 }
joachim99@8 688 }
joachim99@8 689 else
joachim99@8 690 {
joachim99@68 691 p.drawText( xOffset + fontWidth*outPos, yOffset + fontAscent, s );
joachim99@8 692 }
joachim99@8 693 p.setFont(normalFont);
joachim99@8 694 }
joachim99@8 695 else
joachim99@8 696 {
joachim99@8 697 p.fillRect( xOffset + fontWidth*outPos, yOffset,
joachim99@8 698 fontWidth*(spaces), fontHeight, colorGroup().highlight() );
joachim99@8 699
joachim99@8 700 p.setPen( colorGroup().highlightedText() );
joachim99@68 701 p.drawText( xOffset + fontWidth*outPos, yOffset + fontAscent, s );
joachim99@8 702
joachim99@8 703 selection.bSelectionContainsData = true;
joachim99@8 704 }
joachim99@8 705 }
joachim99@8 706
joachim99@8 707 outPos += spaces;
joachim99@8 708 }
joachim99@8 709
joachim99@8 710 if( selection.lineWithin( line ) && selection.lineWithin( line+1 ) )
joachim99@8 711 {
joachim99@8 712 p.fillRect( xOffset + fontWidth*outPos, yOffset,
joachim99@8 713 width(), fontHeight, colorGroup().highlight() );
joachim99@8 714 }
joachim99@8 715 }
joachim99@8 716
joachim99@8 717 p.fillRect( 0, yOffset, leftInfoWidth*fontWidth, fontHeight, m_pOptionDialog->m_bgColor );
joachim99@8 718
joachim99@8 719 xOffset = (m_lineNumberWidth+2)*fontWidth;
joachim99@8 720 int xLeft = m_lineNumberWidth*fontWidth;
joachim99@8 721 p.setPen( m_pOptionDialog->m_fgColor );
joachim99@8 722 if ( pld!=0 )
joachim99@8 723 {
joachim99@66 724 if ( m_pOptionDialog->m_bShowLineNumbers && !bWrapLine )
joachim99@8 725 {
joachim99@8 726 QString num;
joachim99@8 727 num.sprintf( "%0*d", m_lineNumberWidth, srcLineNr);
joachim99@8 728 p.drawText( 0, yOffset + fontAscent, num );
joachim99@8 729 //p.drawLine( xLeft -1, yOffset, xLeft -1, yOffset+fontHeight-1 );
joachim99@8 730 }
joachim99@66 731 if ( !bWrapLine || wrapLineLength>0 )
joachim99@66 732 {
joachim99@66 733 p.setPen( QPen( m_pOptionDialog->m_fgColor, 0, bWrapLine ? DotLine : SolidLine) );
joachim99@66 734 p.drawLine( xOffset +1, yOffset, xOffset +1, yOffset+fontHeight-1 );
joachim99@66 735 p.setPen( QPen( m_pOptionDialog->m_fgColor, 0, SolidLine) );
joachim99@66 736 }
joachim99@8 737 }
joachim99@8 738 if ( c!=m_pOptionDialog->m_fgColor && whatChanged2==0 )//&& whatChanged==0 )
joachim99@8 739 {
joachim99@51 740 if ( m_pOptionDialog->m_bShowWhiteSpace )
joachim99@51 741 {
joachim99@51 742 p.setBrushOrigin(0,0);
joachim99@51 743 p.fillRect( xLeft, yOffset, fontWidth*2-1, fontHeight, QBrush(c,Dense5Pattern) );
joachim99@51 744 }
joachim99@8 745 }
joachim99@8 746 else
joachim99@8 747 {
joachim99@8 748 p.fillRect( xLeft, yOffset, fontWidth*2-1, fontHeight, c==m_pOptionDialog->m_fgColor ? bgColor : c );
joachim99@8 749 }
joachim99@8 750
joachim99@8 751 if ( bFastSelectionRange )
joachim99@8 752 {
joachim99@8 753 p.fillRect( xOffset + fontWidth-1, yOffset, 3, fontHeight, m_pOptionDialog->m_fgColor );
joachim99@8 754 }
joachim99@8 755 }
joachim99@8 756
joachim99@8 757 void DiffTextWindow::paintEvent( QPaintEvent* e )
joachim99@8 758 {
joachim99@66 759 if ( m_pDiff3LineVector==0 || ! m_bPaintingAllowed ||
joachim99@66 760 ( m_diff3WrapLineVector.empty() && m_bWordWrap ) )
joachim99@66 761 return;
joachim99@8 762
joachim99@8 763 m_lineNumberWidth = m_pOptionDialog->m_bShowLineNumbers ? (int)log10((double)m_size)+1 : 0;
joachim99@8 764
joachim99@8 765 if (e!=0)
joachim99@8 766 {
joachim99@8 767 m_invalidRect |= e->rect();
joachim99@8 768 }
joachim99@8 769
joachim99@8 770 if ( m_winIdx==1 )
joachim99@8 771 {
joachim99@8 772 m_cThis = m_pOptionDialog->m_colorA;
joachim99@8 773 m_cDiff1 = m_pOptionDialog->m_colorB;
joachim99@8 774 m_cDiff2 = m_pOptionDialog->m_colorC;
joachim99@8 775 }
joachim99@8 776 if ( m_winIdx==2 )
joachim99@8 777 {
joachim99@8 778 m_cThis = m_pOptionDialog->m_colorB;
joachim99@8 779 m_cDiff1 = m_pOptionDialog->m_colorC;
joachim99@8 780 m_cDiff2 = m_pOptionDialog->m_colorA;
joachim99@8 781 }
joachim99@8 782 if ( m_winIdx==3 )
joachim99@8 783 {
joachim99@8 784 m_cThis = m_pOptionDialog->m_colorC;
joachim99@8 785 m_cDiff1 = m_pOptionDialog->m_colorA;
joachim99@8 786 m_cDiff2 = m_pOptionDialog->m_colorB;
joachim99@8 787 }
joachim99@8 788 m_cDiffBoth = m_pOptionDialog->m_colorForConflict; // Conflict color
joachim99@8 789
joachim99@8 790 bool bOldSelectionContainsData = selection.bSelectionContainsData;
joachim99@8 791 selection.bSelectionContainsData = false;
joachim99@8 792
joachim99@8 793 int fontHeight = fontMetrics().height();
joachim99@8 794 int fontAscent = fontMetrics().ascent();
joachim99@8 795 // int fontDescent = fontMetrics().descent();
joachim99@8 796
joachim99@8 797 int topLineYOffset = fontHeight + 3;
joachim99@8 798
joachim99@8 799 if ( selection.oldLastLine != -1 )
joachim99@8 800 {
joachim99@8 801 int lastLine;
joachim99@8 802 int firstLine;
joachim99@8 803 if ( selection.oldFirstLine != -1 )
joachim99@8 804 {
joachim99@8 805 firstLine = min3( selection.oldFirstLine, selection.lastLine, selection.oldLastLine );
joachim99@8 806 lastLine = max3( selection.oldFirstLine, selection.lastLine, selection.oldLastLine );
joachim99@8 807 }
joachim99@8 808 else
joachim99@8 809 {
joachim99@8 810 firstLine = min2( selection.lastLine, selection.oldLastLine );
joachim99@8 811 lastLine = max2( selection.lastLine, selection.oldLastLine );
joachim99@8 812 }
joachim99@66 813 int y1 = topLineYOffset + ( firstLine - m_firstLine ) * fontHeight;
joachim99@8 814 int y2 = min2( height(),
joachim99@66 815 topLineYOffset + ( lastLine - m_firstLine + 1 ) * fontHeight );
joachim99@8 816
joachim99@8 817 if ( y1<height() && y2>topLineYOffset )
joachim99@8 818 {
joachim99@8 819 m_invalidRect |= QRect( 0, y1, width(), y2-y1 );
joachim99@8 820 }
joachim99@8 821 }
joachim99@8 822
joachim99@8 823 if ( m_invalidRect.isEmpty() )
joachim99@8 824 return;
joachim99@8 825
joachim99@8 826 QPainter painter(this);
joachim99@8 827 //QPainter& p=painter;
joachim99@8 828 QPixmap pixmap( m_invalidRect.size() );
joachim99@68 829 MyPainter p( &pixmap, m_pOptionDialog->m_bRightToLeftLanguage, width(), fontMetrics().width('W') );
joachim99@68 830
joachim99@8 831 p.translate( -m_invalidRect.x(), -m_invalidRect.y() );
joachim99@8 832
joachim99@68 833 p.QPainter::fillRect( m_invalidRect, m_pOptionDialog->m_bgColor );
joachim99@8 834
joachim99@8 835 p.setFont( font() );
joachim99@8 836
joachim99@8 837 p.setPen( m_cThis );
joachim99@8 838 if( m_invalidRect.intersects( QRect(0,0,width(), topLineYOffset ) )
joachim99@8 839 || m_firstLine != m_oldFirstLine )
joachim99@8 840 {
joachim99@8 841 int l=-1;
joachim99@66 842 for ( int i = convertLineToDiff3LineIdx(m_firstLine); i<(int)m_pDiff3LineVector->size(); ++i )
joachim99@8 843 {
joachim99@8 844 const Diff3Line* d3l = (*m_pDiff3LineVector)[i];
joachim99@8 845 if ( m_winIdx==1 ) l=d3l->lineA;
joachim99@8 846 else if ( m_winIdx==2 ) l=d3l->lineB;
joachim99@8 847 else if ( m_winIdx==3 ) l=d3l->lineC;
joachim99@8 848 else assert(false);
joachim99@8 849 if (l!=-1) break;
joachim99@8 850 }
joachim99@8 851
joachim99@8 852 const char* winId = ( m_winIdx==1 ? (m_bTriple?"A (Base)":"A") :
joachim99@8 853 ( m_winIdx==2 ? "B" : "C" ) );
joachim99@8 854
joachim99@51 855 QString s = QString(" ")+ winId + " : " + m_filename + " : ";
joachim99@8 856 if ( l!=-1 )
joachim99@66 857 s += i18n("Top line %1").arg( l+1 );
joachim99@8 858 else
joachim99@51 859 s += i18n("End");
joachim99@8 860
joachim99@8 861 if (hasFocus())
joachim99@8 862 {
joachim99@8 863 painter.fillRect( 0, 0, width(), topLineYOffset, m_cThis );
joachim99@8 864 painter.setPen( m_pOptionDialog->m_bgColor );
joachim99@8 865 painter.drawText( 0, fontAscent+1, s );
joachim99@8 866 }
joachim99@8 867 else
joachim99@8 868 {
joachim99@8 869 painter.fillRect( 0, 0, width(), topLineYOffset, m_pOptionDialog->m_bgColor );
joachim99@8 870 painter.setPen( m_cThis );
joachim99@8 871 painter.drawLine( 0, fontHeight + 2, width(), fontHeight + 2 );
joachim99@8 872 painter.drawText( 0, fontAscent+1, s );
joachim99@8 873 }
joachim99@8 874 }
joachim99@8 875
joachim99@66 876 int lastVisibleLine = min2( m_firstLine + getNofVisibleLines()+2,
joachim99@66 877 (int)(m_bWordWrap ? m_diff3WrapLineVector.size() : m_pDiff3LineVector->size()) );
joachim99@8 878
joachim99@8 879 for ( int line = m_firstLine; line<lastVisibleLine; ++line )
joachim99@8 880 {
joachim99@66 881 int wrapLineOffset=0;
joachim99@66 882 int wrapLineLength=0;
joachim99@66 883 const Diff3Line* d3l =0;
joachim99@66 884 bool bWrapLine = false;
joachim99@66 885 if (m_bWordWrap)
joachim99@66 886 {
joachim99@66 887 Diff3WrapLine& d3wl = m_diff3WrapLineVector[line];
joachim99@66 888 wrapLineOffset = d3wl.wrapLineOffset;
joachim99@66 889 wrapLineLength = d3wl.wrapLineLength;
joachim99@66 890 d3l = d3wl.pD3L;
joachim99@66 891 bWrapLine = line > 0 && m_diff3WrapLineVector[line-1].pD3L == d3l;
joachim99@66 892 }
joachim99@66 893 else
joachim99@66 894 {
joachim99@66 895 d3l = (*m_pDiff3LineVector)[line];
joachim99@66 896 }
joachim99@8 897 DiffList* pFineDiff1;
joachim99@8 898 DiffList* pFineDiff2;
joachim99@8 899 int changed=0;
joachim99@8 900 int changed2=0;
joachim99@8 901 int lineIdx;
joachim99@8 902
joachim99@8 903 getLineInfo( *d3l, lineIdx, pFineDiff1, pFineDiff2, changed, changed2 );
joachim99@8 904
joachim99@8 905 writeLine(
joachim99@8 906 p, // QPainter
joachim99@8 907 lineIdx == -1 ? 0 : &m_pLineData[lineIdx], // Text in this line
joachim99@8 908 pFineDiff1,
joachim99@8 909 pFineDiff2,
joachim99@8 910 line, // Line on the screen
joachim99@8 911 changed,
joachim99@8 912 changed2,
joachim99@66 913 lineIdx+1,
joachim99@66 914 wrapLineOffset,
joachim99@66 915 wrapLineLength,
joachim99@66 916 bWrapLine
joachim99@8 917 );
joachim99@8 918 }
joachim99@8 919
joachim99@8 920 // p.drawLine( m_invalidRect.x(), m_invalidRect.y(), m_invalidRect.right(), m_invalidRect.bottom() );
joachim99@8 921 p.end();
joachim99@8 922
joachim99@8 923 painter.setClipRect ( 0, topLineYOffset, width(), height()-topLineYOffset );
joachim99@8 924
joachim99@8 925 painter.drawPixmap( m_invalidRect.x(), m_invalidRect.y(), pixmap );
joachim99@8 926
joachim99@8 927 m_oldFirstLine = m_firstLine;
joachim99@8 928 m_oldFirstColumn = m_firstColumn;
joachim99@8 929 m_invalidRect = QRect(0,0,0,0);
joachim99@8 930 selection.oldLastLine = -1;
joachim99@8 931 if ( selection.oldFirstLine !=-1 )
joachim99@8 932 selection.oldFirstLine = -1;
joachim99@8 933 if( !bOldSelectionContainsData && selection.bSelectionContainsData )
joachim99@8 934 emit newSelection();
joachim99@8 935
joachim99@8 936 }
joachim99@8 937
joachim99@68 938 QString DiffTextWindow::getString( int d3lIdx )
joachim99@8 939 {
joachim99@66 940 const Diff3Line* d3l = (*m_pDiff3LineVector)[d3lIdx];
joachim99@8 941 DiffList* pFineDiff1;
joachim99@8 942 DiffList* pFineDiff2;
joachim99@8 943 int changed=0;
joachim99@8 944 int changed2=0;
joachim99@8 945 int lineIdx;
joachim99@8 946 getLineInfo( *d3l, lineIdx, pFineDiff1, pFineDiff2, changed, changed2 );
joachim99@8 947
joachim99@68 948 if (lineIdx==-1) return QString();
joachim99@8 949 else
joachim99@8 950 {
joachim99@58 951 const LineData* ld = &m_pLineData[lineIdx];
joachim99@68 952 return QString( ld->pLine, ld->size );
joachim99@8 953 }
joachim99@68 954 return QString();
joachim99@8 955 }
joachim99@8 956
joachim99@68 957 QString DiffTextWindow::getLineString( int line )
joachim99@66 958 {
joachim99@66 959 if ( m_bWordWrap )
joachim99@66 960 {
joachim99@66 961 int d3LIdx = convertLineToDiff3LineIdx(line);
joachim99@66 962 return getString( d3LIdx ).mid( m_diff3WrapLineVector[line].wrapLineOffset, m_diff3WrapLineVector[line].wrapLineLength );
joachim99@66 963 }
joachim99@66 964 else
joachim99@66 965 {
joachim99@66 966 return getString( line );
joachim99@66 967 }
joachim99@66 968 }
joachim99@8 969
joachim99@8 970 void DiffTextWindow::getLineInfo(
joachim99@8 971 const Diff3Line& d,
joachim99@8 972 int& lineIdx,
joachim99@8 973 DiffList*& pFineDiff1, DiffList*& pFineDiff2, // return values
joachim99@8 974 int& changed, int& changed2
joachim99@8 975 )
joachim99@8 976 {
joachim99@8 977 changed=0;
joachim99@8 978 changed2=0;
joachim99@8 979 bool bAEqB = d.bAEqB || ( d.bWhiteLineA && d.bWhiteLineB );
joachim99@8 980 bool bAEqC = d.bAEqC || ( d.bWhiteLineA && d.bWhiteLineC );
joachim99@8 981 bool bBEqC = d.bBEqC || ( d.bWhiteLineB && d.bWhiteLineC );
joachim99@8 982 if ( m_winIdx == 1 ) {
joachim99@8 983 lineIdx=d.lineA;
joachim99@8 984 pFineDiff1=d.pFineAB;
joachim99@8 985 pFineDiff2=d.pFineCA;
joachim99@8 986 changed |= ((d.lineB==-1)!=(lineIdx==-1) ? 1 : 0) +
joachim99@8 987 ((d.lineC==-1)!=(lineIdx==-1) && m_bTriple ? 2 : 0);
joachim99@8 988 changed2 |= ( bAEqB ? 0 : 1 ) + (bAEqC || !m_bTriple ? 0 : 2);
joachim99@8 989 }
joachim99@8 990 else if ( m_winIdx == 2 ) {
joachim99@8 991 lineIdx=d.lineB;
joachim99@8 992 pFineDiff1=d.pFineBC;
joachim99@8 993 pFineDiff2=d.pFineAB;
joachim99@8 994 changed |= ((d.lineC==-1)!=(lineIdx==-1) && m_bTriple ? 1 : 0) +
joachim99@8 995 ((d.lineA==-1)!=(lineIdx==-1) ? 2 : 0);
joachim99@8 996 changed2 |= ( bBEqC || !m_bTriple ? 0 : 1 ) + (bAEqB ? 0 : 2);
joachim99@8 997 }
joachim99@8 998 else if ( m_winIdx == 3 ) {
joachim99@8 999 lineIdx=d.lineC;
joachim99@8 1000 pFineDiff1=d.pFineCA;
joachim99@8 1001 pFineDiff2=d.pFineBC;
joachim99@8 1002 changed |= ((d.lineA==-1)!=(lineIdx==-1) ? 1 : 0) +
joachim99@8 1003 ((d.lineB==-1)!=(lineIdx==-1) ? 2 : 0);
joachim99@8 1004 changed2 |= ( bAEqC ? 0 : 1 ) + (bBEqC ? 0 : 2);
joachim99@8 1005 }
joachim99@8 1006 else assert(false);
joachim99@8 1007 }
joachim99@8 1008
joachim99@8 1009
joachim99@8 1010
joachim99@8 1011 void DiffTextWindow::resizeEvent( QResizeEvent* e )
joachim99@8 1012 {
joachim99@8 1013 QSize s = e->size();
joachim99@8 1014 QFontMetrics fm = fontMetrics();
joachim99@8 1015 int visibleLines = s.height()/fm.height()-2;
joachim99@8 1016 int visibleColumns = s.width()/fm.width('W')-leftInfoWidth;
joachim99@8 1017 emit resizeSignal( visibleColumns, visibleLines );
joachim99@8 1018 QWidget::resizeEvent(e);
joachim99@8 1019 }
joachim99@8 1020
joachim99@8 1021 int DiffTextWindow::getNofVisibleLines()
joachim99@8 1022 {
joachim99@8 1023 QFontMetrics fm = fontMetrics();
joachim99@8 1024 int fmh = fm.height();
joachim99@8 1025 int h = height();
joachim99@8 1026 return h/fmh -2;//height()/fm.height()-2;
joachim99@8 1027 }
joachim99@8 1028
joachim99@8 1029 int DiffTextWindow::getNofVisibleColumns()
joachim99@8 1030 {
joachim99@8 1031 QFontMetrics fm = fontMetrics();
joachim99@8 1032 return width()/fm.width('W')-leftInfoWidth;
joachim99@8 1033 }
joachim99@8 1034
joachim99@8 1035 QString DiffTextWindow::getSelection()
joachim99@8 1036 {
joachim99@8 1037 QString selectionString;
joachim99@8 1038
joachim99@8 1039 int line=0;
joachim99@8 1040 int lineIdx=0;
joachim99@8 1041
joachim99@8 1042 int it;
joachim99@66 1043 int vectorSize = m_bWordWrap ? m_diff3WrapLineVector.size() : m_pDiff3LineVector->size();
joachim99@66 1044 for( it=0; it<vectorSize; ++it )
joachim99@8 1045 {
joachim99@66 1046 const Diff3Line* d = m_bWordWrap ? m_diff3WrapLineVector[it].pD3L : (*m_pDiff3LineVector)[it];
joachim99@8 1047 if ( m_winIdx == 1 ) { lineIdx=d->lineA; }
joachim99@8 1048 else if ( m_winIdx == 2 ) { lineIdx=d->lineB; }
joachim99@8 1049 else if ( m_winIdx == 3 ) { lineIdx=d->lineC; }
joachim99@8 1050 else assert(false);
joachim99@8 1051
joachim99@8 1052 if( lineIdx != -1 )
joachim99@68 1053 {
joachim99@68 1054 const QChar* pLine = m_pLineData[lineIdx].pLine;
joachim99@8 1055 int size = m_pLineData[lineIdx].size;
joachim99@68 1056 QString lineString = QString( pLine, size );
joachim99@66 1057
joachim99@66 1058 if ( m_bWordWrap )
joachim99@66 1059 {
joachim99@66 1060 size = m_diff3WrapLineVector[it].wrapLineLength;
joachim99@68 1061 lineString = lineString.mid( m_diff3WrapLineVector[it].wrapLineOffset, size );
joachim99@66 1062 }
joachim99@8 1063
joachim99@8 1064 // Consider tabs
joachim99@8 1065 int outPos = 0;
joachim99@8 1066 for( int i=0; i<size; ++i )
joachim99@8 1067 {
joachim99@8 1068 int spaces = 1;
joachim99@68 1069 if ( lineString[i]=='\t' )
joachim99@8 1070 {
joachim99@8 1071 spaces = tabber( outPos, g_tabSize );
joachim99@8 1072 }
joachim99@8 1073
joachim99@8 1074 if( selection.within( line, outPos ) )
joachim99@8 1075 {
joachim99@68 1076 selectionString += lineString[i];
joachim99@8 1077 }
joachim99@8 1078
joachim99@8 1079 outPos += spaces;
joachim99@68 1080 }
joachim99@66 1081
joachim99@66 1082 if( selection.within( line, outPos ) &&
joachim99@66 1083 !( m_bWordWrap && it+1<vectorSize && d == m_diff3WrapLineVector[it+1].pD3L )
joachim99@66 1084 )
joachim99@8 1085 {
joachim99@8 1086 #ifdef _WIN32
joachim99@8 1087 selectionString += '\r';
joachim99@8 1088 #endif
joachim99@8 1089 selectionString += '\n';
joachim99@8 1090 }
joachim99@8 1091 }
joachim99@8 1092
joachim99@8 1093 ++line;
joachim99@8 1094 }
joachim99@8 1095
joachim99@8 1096 return selectionString;
joachim99@8 1097 }
joachim99@8 1098
joachim99@68 1099 bool DiffTextWindow::findString( const QString& s, int& d3vLine, int& posInLine, bool bDirDown, bool bCaseSensitive )
joachim99@8 1100 {
joachim99@8 1101 int it = d3vLine;
joachim99@8 1102 int endIt = bDirDown ? (int)m_pDiff3LineVector->size() : -1;
joachim99@8 1103 int step = bDirDown ? 1 : -1;
joachim99@8 1104 int startPos = posInLine;
joachim99@8 1105
joachim99@8 1106 for( ; it!=endIt; it+=step )
joachim99@8 1107 {
joachim99@68 1108 QString line = getString( it );
joachim99@8 1109 if ( !line.isEmpty() )
joachim99@8 1110 {
joachim99@8 1111 int pos = line.find( s, startPos, bCaseSensitive );
joachim99@8 1112 if ( pos != -1 )
joachim99@8 1113 {
joachim99@8 1114 d3vLine = it;
joachim99@8 1115 posInLine = pos;
joachim99@8 1116 return true;
joachim99@8 1117 }
joachim99@8 1118
joachim99@8 1119 startPos = 0;
joachim99@8 1120 }
joachim99@8 1121 }
joachim99@8 1122 return false;
joachim99@8 1123 }
joachim99@8 1124
joachim99@66 1125 void DiffTextWindow::convertD3LCoordsToLineCoords( int d3LIdx, int d3LPos, int& line, int& pos )
joachim99@66 1126 {
joachim99@66 1127 if( m_bWordWrap )
joachim99@66 1128 {
joachim99@66 1129 int wrapPos = d3LPos;
joachim99@66 1130 int wrapLine = convertDiff3LineIdxToLine(d3LIdx);
joachim99@66 1131 while ( wrapPos > m_diff3WrapLineVector[wrapLine].wrapLineLength )
joachim99@66 1132 {
joachim99@66 1133 wrapPos -= m_diff3WrapLineVector[wrapLine].wrapLineLength;
joachim99@66 1134 ++wrapLine;
joachim99@66 1135 }
joachim99@66 1136 pos = wrapPos;
joachim99@66 1137 line = wrapLine;
joachim99@66 1138 }
joachim99@66 1139 else
joachim99@66 1140 {
joachim99@66 1141 pos = d3LPos;
joachim99@66 1142 line = d3LIdx;
joachim99@66 1143 }
joachim99@66 1144 }
joachim99@66 1145
joachim99@66 1146 void DiffTextWindow::convertLineCoordsToD3LCoords( int line, int pos, int& d3LIdx, int& d3LPos )
joachim99@66 1147 {
joachim99@66 1148 if( m_bWordWrap )
joachim99@66 1149 {
joachim99@66 1150 d3LPos = pos;
joachim99@66 1151 d3LIdx = convertLineToDiff3LineIdx( line );
joachim99@66 1152 int wrapLine = convertDiff3LineIdxToLine(d3LIdx); // First wrap line belonging to this d3LIdx
joachim99@66 1153 while ( wrapLine < line )
joachim99@66 1154 {
joachim99@66 1155 d3LPos += m_diff3WrapLineVector[wrapLine].wrapLineLength;
joachim99@66 1156 ++wrapLine;
joachim99@66 1157 }
joachim99@66 1158 }
joachim99@66 1159 else
joachim99@66 1160 {
joachim99@66 1161 d3LPos = pos;
joachim99@66 1162 d3LIdx = line;
joachim99@66 1163 }
joachim99@66 1164 }
joachim99@66 1165
joachim99@66 1166
joachim99@66 1167 void DiffTextWindow::setSelection( int firstLine, int startPos, int lastLine, int endPos, int& l, int& p )
joachim99@8 1168 {
joachim99@8 1169 selection.reset();
joachim99@66 1170 if ( m_bWordWrap && m_pDiff3LineVector!=0 )
joachim99@66 1171 {
joachim99@66 1172 QString s1 = getString(firstLine);
joachim99@66 1173 int firstWrapLine = convertDiff3LineIdxToLine(firstLine);
joachim99@66 1174 int wrapStartPos = startPos;
joachim99@66 1175 while ( wrapStartPos > m_diff3WrapLineVector[firstWrapLine].wrapLineLength )
joachim99@66 1176 {
joachim99@66 1177 wrapStartPos -= m_diff3WrapLineVector[firstWrapLine].wrapLineLength;
joachim99@66 1178 s1 = s1.mid(m_diff3WrapLineVector[firstWrapLine].wrapLineLength);
joachim99@66 1179 ++firstWrapLine;
joachim99@66 1180 }
joachim99@66 1181
joachim99@66 1182 QString s2 = getString(lastLine);
joachim99@66 1183 int lastWrapLine = convertDiff3LineIdxToLine(lastLine);
joachim99@66 1184 int wrapEndPos = endPos;
joachim99@66 1185 while ( wrapEndPos > m_diff3WrapLineVector[lastWrapLine].wrapLineLength )
joachim99@66 1186 {
joachim99@66 1187 wrapEndPos -= m_diff3WrapLineVector[lastWrapLine].wrapLineLength;
joachim99@66 1188 s2 = s2.mid(m_diff3WrapLineVector[lastWrapLine].wrapLineLength);
joachim99@66 1189 ++lastWrapLine;
joachim99@66 1190 }
joachim99@66 1191
joachim99@66 1192 selection.start( firstWrapLine, convertToPosOnScreen( s1, wrapStartPos ) );
joachim99@66 1193 selection.end( lastWrapLine, convertToPosOnScreen( s2, wrapEndPos ) );
joachim99@66 1194 l=firstWrapLine;
joachim99@66 1195 p=wrapStartPos;
joachim99@66 1196 }
joachim99@66 1197 else
joachim99@66 1198 {
joachim99@66 1199 selection.start( firstLine, convertToPosOnScreen( getString(firstLine), startPos ) );
joachim99@66 1200 selection.end( lastLine, convertToPosOnScreen( getString(lastLine), endPos ) );
joachim99@66 1201 l=firstLine;
joachim99@66 1202 p=startPos;
joachim99@66 1203 }
joachim99@8 1204 update();
joachim99@8 1205 }
joachim99@51 1206
joachim99@51 1207
joachim99@66 1208 // Returns the number of wrapped lines
joachim99@66 1209 // if pWrappedLines != 0 then the stringlist will contain the wrapped lines.
joachim99@66 1210 int wordWrap( const QString& origLine, int nofColumns, Diff3WrapLine* pDiff3WrapLine )
joachim99@66 1211 {
joachim99@66 1212 if (nofColumns<=0)
joachim99@66 1213 nofColumns = 1;
joachim99@66 1214
joachim99@66 1215 int nofNeededLines = 0;
joachim99@66 1216 int length = origLine.length();
joachim99@66 1217
joachim99@66 1218 if (length==0)
joachim99@66 1219 {
joachim99@66 1220 nofNeededLines = 1;
joachim99@66 1221 if( pDiff3WrapLine )
joachim99@66 1222 {
joachim99@66 1223 pDiff3WrapLine->wrapLineOffset=0;
joachim99@66 1224 pDiff3WrapLine->wrapLineLength=0;
joachim99@66 1225 }
joachim99@66 1226 }
joachim99@66 1227 else
joachim99@66 1228 {
joachim99@66 1229 int pos = 0;
joachim99@66 1230
joachim99@66 1231 while ( pos < length )
joachim99@66 1232 {
joachim99@66 1233 int wrapPos = pos + nofColumns;
joachim99@66 1234
joachim99@66 1235 if ( length-pos <= nofColumns )
joachim99@66 1236 {
joachim99@66 1237 wrapPos = length;
joachim99@66 1238 }
joachim99@66 1239 else
joachim99@66 1240 {
joachim99@66 1241 int wsPos = max2( origLine.findRev( ' ', wrapPos ), origLine.findRev( '\t', wrapPos ) );
joachim99@66 1242
joachim99@66 1243 if ( wsPos > pos )
joachim99@66 1244 {
joachim99@66 1245 // Wrap line at wsPos
joachim99@66 1246 wrapPos = wsPos;
joachim99@66 1247 }
joachim99@66 1248 }
joachim99@66 1249
joachim99@66 1250 if ( pDiff3WrapLine )
joachim99@66 1251 {
joachim99@66 1252 pDiff3WrapLine->wrapLineOffset = pos;
joachim99@66 1253 pDiff3WrapLine->wrapLineLength = wrapPos-pos;
joachim99@66 1254 ++pDiff3WrapLine;
joachim99@66 1255 }
joachim99@66 1256
joachim99@66 1257 pos = wrapPos;
joachim99@66 1258
joachim99@66 1259 ++nofNeededLines;
joachim99@66 1260 }
joachim99@66 1261 }
joachim99@66 1262 return nofNeededLines;
joachim99@66 1263 }
joachim99@66 1264
joachim99@66 1265 void DiffTextWindow::convertSelectionToD3LCoords()
joachim99@66 1266 {
joachim99@66 1267 if ( m_pDiff3LineVector==0 || ! m_bPaintingAllowed || !isVisible() || selection.isEmpty() )
joachim99@66 1268 {
joachim99@66 1269 return;
joachim99@66 1270 }
joachim99@66 1271
joachim99@66 1272 // convert the selection to unwrapped coordinates: Later restore to new coords
joachim99@66 1273 int firstD3LIdx, firstD3LPos;
joachim99@68 1274 QString s = getLineString( selection.beginLine() );
joachim99@68 1275 int firstPosInText = convertToPosInText( s, selection.beginPos() );
joachim99@66 1276 convertLineCoordsToD3LCoords( selection.beginLine(), firstPosInText, firstD3LIdx, firstD3LPos );
joachim99@66 1277
joachim99@66 1278 int lastD3LIdx, lastD3LPos;
joachim99@66 1279 s = getLineString( selection.endLine() );
joachim99@68 1280 int lastPosInText = convertToPosInText( s, selection.endPos() );
joachim99@66 1281 convertLineCoordsToD3LCoords( selection.endLine(), lastPosInText, lastD3LIdx, lastD3LPos );
joachim99@66 1282
joachim99@66 1283 //selection.reset();
joachim99@66 1284 selection.start( firstD3LIdx, firstD3LPos );
joachim99@66 1285 selection.end( lastD3LIdx, lastD3LPos );
joachim99@66 1286 }
joachim99@66 1287
joachim99@66 1288 void DiffTextWindow::recalcWordWrap( bool bWordWrap, int wrapLineVectorSize )
joachim99@66 1289 {
joachim99@66 1290 if ( m_pDiff3LineVector==0 || ! m_bPaintingAllowed || !isVisible() )
joachim99@66 1291 {
joachim99@66 1292 m_bWordWrap = bWordWrap;
joachim99@66 1293 if (!bWordWrap) m_diff3WrapLineVector.resize( 0 );
joachim99@66 1294 return;
joachim99@66 1295 }
joachim99@66 1296
joachim99@66 1297 m_bWordWrap = bWordWrap;
joachim99@66 1298
joachim99@66 1299 if ( bWordWrap )
joachim99@66 1300 {
joachim99@66 1301 m_diff3WrapLineVector.resize( wrapLineVectorSize );
joachim99@66 1302
joachim99@66 1303 int nofVisibleColumns = getNofVisibleColumns();
joachim99@66 1304 int i;
joachim99@66 1305 int wrapLineIdx = 0;
joachim99@66 1306 int size = m_pDiff3LineVector->size();
joachim99@66 1307 for( i=0; i<size; ++i )
joachim99@66 1308 {
joachim99@66 1309 QString s = getString( i );
joachim99@66 1310 int linesNeeded = wordWrap( s, nofVisibleColumns, wrapLineVectorSize==0 ? 0 : &m_diff3WrapLineVector[wrapLineIdx] );
joachim99@66 1311 Diff3Line& d3l = *(*m_pDiff3LineVector)[i];
joachim99@66 1312 if ( d3l.linesNeededForDisplay<linesNeeded )
joachim99@66 1313 {
joachim99@66 1314 d3l.linesNeededForDisplay = linesNeeded;
joachim99@66 1315 }
joachim99@66 1316
joachim99@66 1317 if ( wrapLineVectorSize>0 )
joachim99@66 1318 {
joachim99@66 1319 int j;
joachim99@66 1320 for( j=0; j<d3l.linesNeededForDisplay; ++j, ++wrapLineIdx )
joachim99@66 1321 {
joachim99@66 1322 Diff3WrapLine& d3wl = m_diff3WrapLineVector[wrapLineIdx];
joachim99@66 1323 d3wl.diff3LineIndex = i;
joachim99@66 1324 d3wl.pD3L = (*m_pDiff3LineVector)[i];
joachim99@66 1325 if ( j>=linesNeeded )
joachim99@66 1326 {
joachim99@66 1327 d3wl.wrapLineOffset=0;
joachim99@66 1328 d3wl.wrapLineLength=0;
joachim99@66 1329 }
joachim99@66 1330 }
joachim99@66 1331 }
joachim99@66 1332 }
joachim99@66 1333
joachim99@66 1334 if ( wrapLineVectorSize>0 )
joachim99@66 1335 {
joachim99@66 1336 m_firstLine = min2( m_firstLine, wrapLineVectorSize-1 );
joachim99@66 1337 m_firstColumn = 0;
joachim99@66 1338 }
joachim99@66 1339 }
joachim99@66 1340 else
joachim99@66 1341 {
joachim99@66 1342 m_diff3WrapLineVector.resize( 0 );
joachim99@66 1343 }
joachim99@66 1344
joachim99@66 1345 if ( !selection.isEmpty() && ( !m_bWordWrap || wrapLineVectorSize>0 ) )
joachim99@66 1346 {
joachim99@66 1347 // Assume unwrapped coordinates
joachim99@66 1348 //( Why? ->Conversion to unwrapped coords happened a few lines above in this method.
joachim99@66 1349 // Also see KDiff3App::recalcWordWrap() on the role of wrapLineVectorSize)
joachim99@66 1350
joachim99@66 1351 // Wrap them now.
joachim99@66 1352
joachim99@66 1353 // convert the selection to unwrapped coordinates.
joachim99@66 1354 int firstLine, firstPos;
joachim99@66 1355 convertD3LCoordsToLineCoords( selection.beginLine(), selection.beginPos(), firstLine, firstPos );
joachim99@66 1356
joachim99@66 1357 int lastLine, lastPos;
joachim99@66 1358 convertD3LCoordsToLineCoords( selection.endLine(), selection.endPos(), lastLine, lastPos );
joachim99@66 1359
joachim99@66 1360 //selection.reset();
joachim99@66 1361 selection.start( firstLine, convertToPosOnScreen( getLineString( firstLine ), firstPos ) );
joachim99@66 1362 selection.end( lastLine, convertToPosOnScreen( getLineString( lastLine ),lastPos ) );
joachim99@66 1363 }
joachim99@66 1364 }
joachim99@66 1365
joachim99@66 1366
joachim99@66 1367
joachim99@66 1368
joachim99@51 1369 #include <qtextcodec.h>
joachim99@51 1370
joachim99@68 1371
joachim99@68 1372 QCString encodeString( const QString& s )
joachim99@51 1373 {
joachim99@68 1374 QTextCodec* c = QTextCodec::codecForLocale();
joachim99@68 1375 if (c!=0)
joachim99@68 1376 return c->fromUnicode( s );
joachim99@51 1377 else
joachim99@68 1378 return QCString( s.latin1() );
joachim99@51 1379 }