joachim99@8: /*************************************************************************** joachim99@8: difftextwindow.cpp - description joachim99@8: ------------------- joachim99@8: begin : Mon Apr 8 2002 joachim99@58: copyright : (C) 2002-2004 by Joachim Eibl joachim99@8: email : joachim.eibl@gmx.de joachim99@8: ***************************************************************************/ joachim99@8: joachim99@8: /*************************************************************************** joachim99@8: * * joachim99@8: * This program is free software; you can redistribute it and/or modify * joachim99@8: * it under the terms of the GNU General Public License as published by * joachim99@8: * the Free Software Foundation; either version 2 of the License, or * joachim99@8: * (at your option) any later version. * joachim99@8: * * joachim99@8: ***************************************************************************/ joachim99@8: joachim99@8: #include joachim99@8: #include "diff.h" joachim99@8: #include "merger.h" joachim99@8: #include joachim99@8: #include joachim99@8: #include joachim99@8: #include joachim99@8: #include joachim99@8: #include joachim99@8: #include joachim99@8: #include joachim99@8: #include joachim99@8: #include joachim99@51: #include joachim99@8: joachim99@53: #undef leftInfoWidth joachim99@8: #define leftInfoWidth (4+m_lineNumberWidth) // Nr of information columns on left side joachim99@8: joachim99@8: joachim99@8: DiffTextWindow::DiffTextWindow( joachim99@8: QWidget* pParent, joachim99@8: QStatusBar* pStatusBar, joachim99@8: OptionDialog* pOptionDialog joachim99@8: ) joachim99@8: : QWidget(pParent, 0, WRepaintNoErase) joachim99@8: { joachim99@8: setFocusPolicy( QWidget::ClickFocus ); joachim99@8: setAcceptDrops( true ); joachim99@8: joachim99@8: m_pOptionDialog = pOptionDialog; joachim99@8: init( 0, 0, 0, 0, 0, false ); joachim99@8: joachim99@8: setBackgroundMode( PaletteBase ); joachim99@8: setMinimumSize(QSize(20,20)); joachim99@8: joachim99@8: m_pStatusBar = pStatusBar; joachim99@8: m_bPaintingAllowed = true; joachim99@27: joachim99@27: setFont(m_pOptionDialog->m_font); joachim99@8: } joachim99@8: joachim99@8: joachim99@8: void DiffTextWindow::init( joachim99@8: const QString& filename, joachim99@58: const LineData* pLineData, joachim99@8: int size, joachim99@8: const Diff3LineVector* pDiff3LineVector, joachim99@8: int winIdx, joachim99@8: bool bTriple joachim99@8: ) joachim99@8: { joachim99@8: m_filename = filename; joachim99@8: m_pLineData = pLineData; joachim99@8: m_size = size; joachim99@8: m_pDiff3LineVector = pDiff3LineVector; joachim99@8: m_winIdx = winIdx; joachim99@8: joachim99@8: m_firstLine = 0; joachim99@8: m_oldFirstLine = -1; joachim99@8: m_firstColumn = 0; joachim99@8: m_oldFirstColumn = -1; joachim99@8: m_bTriple = bTriple; joachim99@8: m_scrollDeltaX=0; joachim99@8: m_scrollDeltaY=0; joachim99@8: m_bMyUpdate = false; joachim99@8: m_fastSelectorLine1 = 0; joachim99@8: m_fastSelectorNofLines = 0; joachim99@8: m_lineNumberWidth = 0; joachim99@8: selection.reset(); joachim99@8: selection.oldFirstLine = -1; // reset is not enough here. joachim99@8: selection.oldLastLine = -1; joachim99@8: selection.lastLine = -1; joachim99@8: joachim99@8: QToolTip::remove(this); joachim99@8: QToolTip::add( this, QRect( 0,0, 1024, fontMetrics().height() ), m_filename ); joachim99@8: update(); joachim99@8: } joachim99@8: joachim99@8: void DiffTextWindow::setPaintingAllowed( bool bAllowPainting ) joachim99@8: { joachim99@8: if (m_bPaintingAllowed != bAllowPainting) joachim99@8: { joachim99@8: m_bPaintingAllowed = bAllowPainting; joachim99@8: if ( m_bPaintingAllowed ) update(); joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: void DiffTextWindow::dragEnterEvent( QDragEnterEvent* e ) joachim99@8: { joachim99@8: e->accept( QUriDrag::canDecode(e) || QTextDrag::canDecode(e) ); joachim99@8: // Note that the corresponding drop is handled in KDiff3App::eventFilter(). joachim99@8: } joachim99@8: joachim99@8: void DiffTextWindow::setFirstLine(int firstLine) joachim99@8: { joachim99@8: m_firstLine = max2(0,firstLine); joachim99@8: myUpdate(0); // Immediately joachim99@8: } joachim99@8: joachim99@8: void DiffTextWindow::setFirstColumn(int firstCol) joachim99@8: { joachim99@8: m_firstColumn = max2(0,firstCol); joachim99@8: myUpdate(0); // Immediately joachim99@8: } joachim99@8: joachim99@8: int DiffTextWindow::getNofColumns() joachim99@8: { joachim99@8: int nofColumns = 0; joachim99@8: for( int i = 0; i< m_size; ++i ) joachim99@8: { joachim99@8: if ( m_pLineData[i].width() > nofColumns ) joachim99@8: nofColumns = m_pLineData[i].width(); joachim99@8: } joachim99@8: return nofColumns; joachim99@8: } joachim99@8: joachim99@8: int DiffTextWindow::getNofLines() joachim99@8: { joachim99@8: return m_pDiff3LineVector->size(); joachim99@8: } joachim99@8: joachim99@8: /** Returns a line number where the linerange [line, line+nofLines] can joachim99@8: be displayed best. If it fits into the currently visible range then joachim99@8: the returned value is the current firstLine. joachim99@8: */ joachim99@8: int getBestFirstLine( int line, int nofLines, int firstLine, int visibleLines ) joachim99@8: { joachim99@8: int newFirstLine = firstLine; joachim99@8: if ( line < firstLine || line + nofLines + 2 > firstLine + visibleLines ) joachim99@8: { joachim99@8: if ( nofLines > visibleLines || nofLines <= ( 2*visibleLines / 3 - 1) ) joachim99@8: newFirstLine = line - visibleLines/3; joachim99@8: else joachim99@8: newFirstLine = line - (visibleLines - nofLines); joachim99@8: } joachim99@8: joachim99@8: return newFirstLine; joachim99@8: } joachim99@8: joachim99@8: joachim99@8: void DiffTextWindow::setFastSelectorRange( int line1, int nofLines ) joachim99@8: { joachim99@8: m_fastSelectorLine1 = line1; joachim99@8: m_fastSelectorNofLines = nofLines; joachim99@8: joachim99@8: if ( isVisible() ) joachim99@8: { joachim99@8: int newFirstLine = getBestFirstLine( line1, nofLines, m_firstLine, getNofVisibleLines() ); joachim99@8: if ( newFirstLine != m_firstLine ) joachim99@8: { joachim99@8: scroll( 0, newFirstLine - m_firstLine ); joachim99@8: } joachim99@8: joachim99@8: update(); joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: joachim99@8: static void showStatusLine(int line, int winIdx, const QString& filename, const Diff3LineVector& d3lv, QStatusBar* sb) joachim99@8: { joachim99@8: int l=0; joachim99@8: const Diff3Line* pD3l = d3lv[line]; joachim99@8: if(line >= 0 && line<(int)d3lv.size() && pD3l != 0 ) joachim99@8: { joachim99@8: if ( winIdx==1 ) l = pD3l->lineA; joachim99@8: else if ( winIdx==2 ) l = pD3l->lineB; joachim99@8: else if ( winIdx==3 ) l = pD3l->lineC; joachim99@8: else assert(false); joachim99@8: joachim99@8: QString s; joachim99@8: if ( l!=-1 ) joachim99@8: s.sprintf("File %s: Line %d", filename.ascii(), l+1 ); joachim99@8: else joachim99@8: s.sprintf("File %s: Line not available", filename.ascii() ); joachim99@8: if (sb!=0) sb->message(s); joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: joachim99@8: void DiffTextWindow::mousePressEvent ( QMouseEvent* e ) joachim99@8: { joachim99@8: if ( e->button() == LeftButton ) joachim99@8: { joachim99@8: int line; joachim99@8: int pos; joachim99@8: convertToLinePos( e->x(), e->y(), line, pos ); joachim99@8: if ( pos < m_firstColumn ) joachim99@8: { joachim99@8: emit setFastSelectorLine( line ); joachim99@8: selection.firstLine = -1; // Disable current selection joachim99@8: } joachim99@8: else joachim99@8: { // Selection joachim99@8: resetSelection(); joachim99@8: selection.start( line, pos ); joachim99@8: selection.end( line, pos ); joachim99@8: joachim99@8: showStatusLine( line, m_winIdx, m_filename, *m_pDiff3LineVector, m_pStatusBar ); joachim99@8: } joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: bool isCTokenChar( char c ) joachim99@8: { joachim99@8: return (c=='_') || joachim99@8: ( c>='A' && c<='Z' ) || ( c>='a' && c<='z' ) || joachim99@8: (c>='0' && c<='9'); joachim99@8: } joachim99@8: joachim99@8: /// Calculate where a token starts and ends, given the x-position on screen. joachim99@8: void calcTokenPos( const char* p, int size, int posOnScreen, int& pos1, int& pos2 ) joachim99@8: { joachim99@8: // Cursor conversions that consider g_tabSize joachim99@8: int pos = convertToPosInText( p, size, max2( 0, posOnScreen ) ); joachim99@8: if ( pos>=size ) joachim99@8: { joachim99@8: pos1=size; joachim99@8: pos2=size; joachim99@8: return; joachim99@8: } joachim99@8: joachim99@8: pos1 = pos; joachim99@8: pos2 = pos+1; joachim99@8: joachim99@8: if( isCTokenChar( p[pos1] ) ) joachim99@8: { joachim99@8: while( pos1>=0 && isCTokenChar( p[pos1] ) ) joachim99@8: --pos1; joachim99@8: ++pos1; joachim99@8: joachim99@8: while( pos2button() == LeftButton ) joachim99@8: { joachim99@8: int line; joachim99@8: int pos; joachim99@8: convertToLinePos( e->x(), e->y(), line, pos ); joachim99@8: joachim99@8: // Get the string data of the current line joachim99@8: QCString s = getString( line ); joachim99@8: joachim99@8: if ( ! s.isEmpty() ) joachim99@8: { joachim99@8: int pos1, pos2; joachim99@8: calcTokenPos( s, s.length(), pos, pos1, pos2 ); joachim99@8: joachim99@8: resetSelection(); joachim99@8: selection.start( line, convertToPosOnScreen( s, pos1 ) ); joachim99@8: selection.end( line, convertToPosOnScreen( s, pos2 ) ); joachim99@8: update(); joachim99@8: // emit selectionEnd() happens in the mouseReleaseEvent. joachim99@8: showStatusLine( line, m_winIdx, m_filename, *m_pDiff3LineVector, m_pStatusBar ); joachim99@8: } joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: void DiffTextWindow::mouseReleaseEvent ( QMouseEvent * /*e*/ ) joachim99@8: { joachim99@8: //if ( e->button() == LeftButton ) joachim99@8: { joachim99@8: killTimers(); joachim99@8: if (selection.firstLine != -1 ) joachim99@8: { joachim99@8: emit selectionEnd(); joachim99@8: } joachim99@8: } joachim99@8: m_scrollDeltaX=0; joachim99@8: m_scrollDeltaY=0; joachim99@8: } joachim99@8: joachim99@8: void DiffTextWindow::mouseMoveEvent ( QMouseEvent * e ) joachim99@8: { joachim99@8: int line; joachim99@8: int pos; joachim99@8: convertToLinePos( e->x(), e->y(), line, pos ); joachim99@8: if (selection.firstLine != -1 ) joachim99@8: { joachim99@8: selection.end( line, pos ); joachim99@8: myUpdate(0); joachim99@8: joachim99@8: showStatusLine( line, m_winIdx, m_filename, *m_pDiff3LineVector, m_pStatusBar ); joachim99@8: joachim99@8: // Scroll because mouse moved out of the window joachim99@8: const QFontMetrics& fm = fontMetrics(); joachim99@8: int fontHeight = fm.height(); joachim99@8: int fontWidth = fm.width('W'); joachim99@8: int topLineYOffset = fontHeight + 3; joachim99@8: int deltaX=0; joachim99@8: int deltaY=0; joachim99@8: if ( e->x() < leftInfoWidth*fontWidth ) deltaX=-1; joachim99@8: if ( e->x() > width() ) deltaX=+1; joachim99@8: if ( e->y() < topLineYOffset ) deltaY=-1; joachim99@8: if ( e->y() > height() ) deltaY=+1; joachim99@8: m_scrollDeltaX = deltaX; joachim99@8: m_scrollDeltaY = deltaY; joachim99@8: if ( deltaX != 0 || deltaY!= 0) joachim99@8: { joachim99@8: emit scroll( deltaX, deltaY ); joachim99@8: } joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: joachim99@8: void DiffTextWindow::myUpdate(int afterMilliSecs) joachim99@8: { joachim99@8: killTimers(); joachim99@8: m_bMyUpdate = true; joachim99@8: startTimer( afterMilliSecs ); joachim99@8: } joachim99@8: joachim99@8: void DiffTextWindow::timerEvent(QTimerEvent*) joachim99@8: { joachim99@8: killTimers(); joachim99@8: joachim99@8: if ( m_bMyUpdate ) joachim99@8: { joachim99@8: paintEvent( 0 ); joachim99@8: m_bMyUpdate = false; joachim99@8: } joachim99@8: joachim99@8: if ( m_scrollDeltaX != 0 || m_scrollDeltaY != 0 ) joachim99@8: { joachim99@8: selection.end( selection.lastLine + m_scrollDeltaY, selection.lastPos + m_scrollDeltaX ); joachim99@8: emit scroll( m_scrollDeltaX, m_scrollDeltaY ); joachim99@8: killTimers(); joachim99@8: startTimer(50); joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: void DiffTextWindow::resetSelection() joachim99@8: { joachim99@8: selection.reset(); joachim99@8: update(); joachim99@8: } joachim99@8: joachim99@8: void DiffTextWindow::convertToLinePos( int x, int y, int& line, int& pos ) joachim99@8: { joachim99@8: const QFontMetrics& fm = fontMetrics(); joachim99@8: int fontHeight = fm.height(); joachim99@8: int fontWidth = fm.width('W'); joachim99@8: int xOffset = (leftInfoWidth-m_firstColumn)*fontWidth; joachim99@8: joachim99@8: int topLineYOffset = fontHeight + 3; joachim99@8: joachim99@8: int yOffset = topLineYOffset - m_firstLine * fontHeight; joachim99@8: joachim99@8: line = ( y - yOffset ) / fontHeight; joachim99@8: pos = ( x - xOffset ) / fontWidth; joachim99@8: } joachim99@8: joachim99@8: int Selection::firstPosInLine(int l) joachim99@8: { joachim99@8: assert( firstLine != -1 ); joachim99@8: joachim99@8: int l1 = firstLine; joachim99@8: int l2 = lastLine; joachim99@8: int p1 = firstPos; joachim99@8: int p2 = lastPos; joachim99@8: if ( l1>l2 ){ std::swap(l1,l2); std::swap(p1,p2); } joachim99@8: if ( l1==l2 && p1>p2 ){ std::swap(p1,p2); } joachim99@8: joachim99@8: if ( l==l1 ) joachim99@8: return p1; joachim99@8: return 0; joachim99@8: } joachim99@8: joachim99@8: int Selection::lastPosInLine(int l) joachim99@8: { joachim99@8: assert( firstLine != -1 ); joachim99@8: joachim99@8: int l1 = firstLine; joachim99@8: int l2 = lastLine; joachim99@8: int p1 = firstPos; joachim99@8: int p2 = lastPos; joachim99@8: joachim99@8: if ( l1>l2 ){ std::swap(l1,l2); std::swap(p1,p2); } joachim99@8: if ( l1==l2 && p1>p2 ){ std::swap(p1,p2); } joachim99@8: joachim99@8: if ( l==l2 ) joachim99@8: return p2; joachim99@8: return INT_MAX; joachim99@8: } joachim99@8: joachim99@8: bool Selection::within( int l, int p ) joachim99@8: { joachim99@8: if ( firstLine == -1 ) return false; joachim99@8: int l1 = firstLine; joachim99@8: int l2 = lastLine; joachim99@8: int p1 = firstPos; joachim99@8: int p2 = lastPos; joachim99@8: if ( l1>l2 ){ std::swap(l1,l2); std::swap(p1,p2); } joachim99@8: if ( l1==l2 && p1>p2 ){ std::swap(p1,p2); } joachim99@8: if( l1 <= l && l <= l2 ) joachim99@8: { joachim99@8: if ( l1==l2 ) joachim99@8: return p>=p1 && p=p1; joachim99@8: if ( l==l2 ) joachim99@8: return pl2 ){ std::swap(l1,l2); } joachim99@8: joachim99@8: return ( l1 <= l && l <= l2 ); joachim99@8: } joachim99@8: joachim99@8: void DiffTextWindow::writeLine( joachim99@8: QPainter& p, joachim99@8: const LineData* pld, joachim99@8: const DiffList* pLineDiff1, joachim99@8: const DiffList* pLineDiff2, joachim99@8: int line, joachim99@8: int whatChanged, joachim99@8: int whatChanged2, joachim99@8: int srcLineNr joachim99@8: ) joachim99@8: { joachim99@8: QFont normalFont = font(); joachim99@8: QFont diffFont = normalFont; joachim99@8: diffFont.setItalic( m_pOptionDialog->m_bItalicForDeltas ); joachim99@8: const QFontMetrics& fm = fontMetrics(); joachim99@8: int fontHeight = fm.height(); joachim99@8: int fontAscent = fm.ascent(); joachim99@8: int fontDescent = fm.descent(); joachim99@8: int fontWidth = fm.width('W'); joachim99@8: int topLineYOffset = fontHeight + 3; joachim99@8: joachim99@8: int xOffset = (leftInfoWidth - m_firstColumn)*fontWidth; joachim99@8: int yOffset = (line-m_firstLine) * fontHeight + topLineYOffset; joachim99@8: joachim99@8: QRect lineRect( 0, yOffset, width(), fontHeight ); joachim99@8: if ( ! m_invalidRect.intersects( lineRect ) ) joachim99@8: return; joachim99@8: joachim99@8: int fastSelectorLine2 = m_fastSelectorLine1+m_fastSelectorNofLines - 1; joachim99@8: bool bFastSelectionRange = (line>=m_fastSelectorLine1 && line<= fastSelectorLine2 ); joachim99@8: QColor bgColor = m_pOptionDialog->m_bgColor; joachim99@8: QColor diffBgColor = m_pOptionDialog->m_diffBgColor; joachim99@8: joachim99@8: if ( bFastSelectionRange ) joachim99@8: { joachim99@8: bgColor = m_pOptionDialog->m_currentRangeBgColor; joachim99@8: diffBgColor = m_pOptionDialog->m_currentRangeDiffBgColor; joachim99@8: } joachim99@8: joachim99@8: // QRect winRect = rect(); //p.window(); joachim99@8: if ( yOffset+fontHeight<0 || height() + fontHeight < yOffset ) joachim99@8: return; joachim99@8: joachim99@8: int changed = whatChanged; joachim99@8: if ( pLineDiff1 != 0 ) changed |= 1; joachim99@8: if ( pLineDiff2 != 0 ) changed |= 2; joachim99@8: joachim99@8: QColor c = m_pOptionDialog->m_fgColor; joachim99@8: if ( changed == 2 ) { joachim99@8: c = m_cDiff2; joachim99@8: } else if ( changed == 1 ) { joachim99@8: c = m_cDiff1; joachim99@8: } else if ( changed == 3 ) { joachim99@8: c = m_cDiffBoth; joachim99@8: } joachim99@8: joachim99@8: p.fillRect( leftInfoWidth*fontWidth, yOffset, width(), fontHeight, bgColor ); joachim99@51: joachim99@8: if (pld!=0) joachim99@8: { joachim99@8: // First calculate the "changed" information for each character. joachim99@8: int i=0; joachim99@8: std::vector charChanged( pld->size ); joachim99@8: if ( pLineDiff1!=0 || pLineDiff2 != 0 ) joachim99@8: { joachim99@8: Merger merger( pLineDiff1, pLineDiff2 ); joachim99@8: while( ! merger.isEndReached() && isize ) joachim99@8: { joachim99@8: if ( i < pld->size ) joachim99@8: { joachim99@8: charChanged[i] = merger.whatChanged(); joachim99@8: ++i; joachim99@8: } joachim99@8: merger.next(); joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: QCString s=" "; joachim99@8: // Convert tabs joachim99@8: int outPos = 0; joachim99@8: for( i=0; isize; ++i ) joachim99@8: { joachim99@8: int spaces = 1; joachim99@8: joachim99@8: if ( pld->pLine[i]=='\t' ) joachim99@8: { joachim99@8: spaces = tabber( outPos, g_tabSize ); joachim99@8: s[0] = ' '; joachim99@8: } joachim99@8: else joachim99@8: { joachim99@8: s[0] = pld->pLine[i]; joachim99@8: } joachim99@8: joachim99@8: QColor c = m_pOptionDialog->m_fgColor; joachim99@8: int cchanged = charChanged[i] | whatChanged; joachim99@8: joachim99@8: if ( cchanged == 2 ) { joachim99@8: c = m_cDiff2; joachim99@8: } else if ( cchanged == 1 ) { joachim99@8: c = m_cDiff1; joachim99@8: } else if ( cchanged == 3 ) { joachim99@8: c = m_cDiffBoth; joachim99@8: } joachim99@8: joachim99@51: if ( c!=m_pOptionDialog->m_fgColor && whatChanged2==0 && !m_pOptionDialog->m_bShowWhiteSpace ) joachim99@51: { joachim99@51: // The user doesn't want to see highlighted white space. joachim99@51: c = m_pOptionDialog->m_fgColor; joachim99@51: } joachim99@51: joachim99@8: QRect outRect( xOffset + fontWidth*outPos, yOffset, fontWidth*spaces, fontHeight ); joachim99@8: if ( m_invalidRect.intersects( outRect ) ) joachim99@8: { joachim99@8: if( !selection.within( line, outPos ) ) joachim99@8: { joachim99@51: joachim99@8: if( c!=m_pOptionDialog->m_fgColor ) joachim99@8: { joachim99@8: QColor lightc = diffBgColor; joachim99@8: p.fillRect( xOffset + fontWidth*outPos, yOffset, joachim99@8: fontWidth*spaces, fontHeight, lightc ); joachim99@8: p.setFont(diffFont); joachim99@8: } joachim99@8: joachim99@8: p.setPen( c ); joachim99@8: if ( s[0]==' ' && c!=m_pOptionDialog->m_fgColor && charChanged[i]!=0 ) joachim99@8: { joachim99@51: if ( m_pOptionDialog->m_bShowWhiteSpaceCharacters && m_pOptionDialog->m_bShowWhiteSpace) joachim99@8: { joachim99@8: p.fillRect( xOffset + fontWidth*outPos, yOffset+fontAscent, joachim99@8: fontWidth*spaces-1, fontDescent+1, c ); joachim99@8: } joachim99@8: } joachim99@8: else joachim99@8: { joachim99@51: p.drawText( xOffset + fontWidth*outPos, yOffset + fontAscent, decodeString(s,m_pOptionDialog) ); joachim99@8: } joachim99@8: p.setFont(normalFont); joachim99@8: } joachim99@8: else joachim99@8: { joachim99@8: joachim99@8: p.fillRect( xOffset + fontWidth*outPos, yOffset, joachim99@8: fontWidth*(spaces), fontHeight, colorGroup().highlight() ); joachim99@8: joachim99@8: p.setPen( colorGroup().highlightedText() ); joachim99@51: p.drawText( xOffset + fontWidth*outPos, yOffset + fontAscent, decodeString(s,m_pOptionDialog) ); joachim99@8: joachim99@8: selection.bSelectionContainsData = true; joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: outPos += spaces; joachim99@8: } joachim99@8: joachim99@8: if( selection.lineWithin( line ) && selection.lineWithin( line+1 ) ) joachim99@8: { joachim99@8: p.fillRect( xOffset + fontWidth*outPos, yOffset, joachim99@8: width(), fontHeight, colorGroup().highlight() ); joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: p.fillRect( 0, yOffset, leftInfoWidth*fontWidth, fontHeight, m_pOptionDialog->m_bgColor ); joachim99@8: joachim99@8: xOffset = (m_lineNumberWidth+2)*fontWidth; joachim99@8: int xLeft = m_lineNumberWidth*fontWidth; joachim99@8: p.setPen( m_pOptionDialog->m_fgColor ); joachim99@8: if ( pld!=0 ) joachim99@8: { joachim99@8: if ( m_pOptionDialog->m_bShowLineNumbers ) joachim99@8: { joachim99@8: QString num; joachim99@8: num.sprintf( "%0*d", m_lineNumberWidth, srcLineNr); joachim99@8: p.drawText( 0, yOffset + fontAscent, num ); joachim99@8: //p.drawLine( xLeft -1, yOffset, xLeft -1, yOffset+fontHeight-1 ); joachim99@8: } joachim99@8: p.drawLine( xOffset +1, yOffset, xOffset +1, yOffset+fontHeight-1 ); joachim99@8: } joachim99@8: if ( c!=m_pOptionDialog->m_fgColor && whatChanged2==0 )//&& whatChanged==0 ) joachim99@8: { joachim99@51: if ( m_pOptionDialog->m_bShowWhiteSpace ) joachim99@51: { joachim99@51: p.setBrushOrigin(0,0); joachim99@51: p.fillRect( xLeft, yOffset, fontWidth*2-1, fontHeight, QBrush(c,Dense5Pattern) ); joachim99@51: } joachim99@8: } joachim99@8: else joachim99@8: { joachim99@8: p.fillRect( xLeft, yOffset, fontWidth*2-1, fontHeight, c==m_pOptionDialog->m_fgColor ? bgColor : c ); joachim99@8: } joachim99@8: joachim99@8: if ( bFastSelectionRange ) joachim99@8: { joachim99@8: p.fillRect( xOffset + fontWidth-1, yOffset, 3, fontHeight, m_pOptionDialog->m_fgColor ); joachim99@8: /* p.drawLine( xOffset + fontWidth-1, yOffset, xOffset + fontWidth-1, yOffset+fontHeight-1 ); joachim99@8: if ( line == m_fastSelectorLine1 ) joachim99@8: { joachim99@8: p.drawLine( xOffset + fontWidth-1, yOffset, xOffset + fontWidth+2, yOffset ); joachim99@8: } joachim99@8: if ( line == fastSelectorLine2 ) joachim99@8: { joachim99@8: p.drawLine( xOffset + fontWidth-1, yOffset+fontHeight-1, xOffset + fontWidth+2, yOffset+fontHeight-1 ); joachim99@8: }*/ joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: void DiffTextWindow::paintEvent( QPaintEvent* e ) joachim99@8: { joachim99@8: if ( m_pDiff3LineVector==0 || ! m_bPaintingAllowed ) return; joachim99@8: joachim99@8: m_lineNumberWidth = m_pOptionDialog->m_bShowLineNumbers ? (int)log10((double)m_size)+1 : 0; joachim99@8: joachim99@8: if (e!=0) joachim99@8: { joachim99@8: m_invalidRect |= e->rect(); joachim99@8: } joachim99@8: joachim99@8: if ( m_winIdx==1 ) joachim99@8: { joachim99@8: m_cThis = m_pOptionDialog->m_colorA; joachim99@8: m_cDiff1 = m_pOptionDialog->m_colorB; joachim99@8: m_cDiff2 = m_pOptionDialog->m_colorC; joachim99@8: } joachim99@8: if ( m_winIdx==2 ) joachim99@8: { joachim99@8: m_cThis = m_pOptionDialog->m_colorB; joachim99@8: m_cDiff1 = m_pOptionDialog->m_colorC; joachim99@8: m_cDiff2 = m_pOptionDialog->m_colorA; joachim99@8: } joachim99@8: if ( m_winIdx==3 ) joachim99@8: { joachim99@8: m_cThis = m_pOptionDialog->m_colorC; joachim99@8: m_cDiff1 = m_pOptionDialog->m_colorA; joachim99@8: m_cDiff2 = m_pOptionDialog->m_colorB; joachim99@8: } joachim99@8: m_cDiffBoth = m_pOptionDialog->m_colorForConflict; // Conflict color joachim99@8: joachim99@8: bool bOldSelectionContainsData = selection.bSelectionContainsData; joachim99@8: selection.bSelectionContainsData = false; joachim99@8: joachim99@8: int fontHeight = fontMetrics().height(); joachim99@8: int fontAscent = fontMetrics().ascent(); joachim99@8: // int fontDescent = fontMetrics().descent(); joachim99@8: int fontWidth = fontMetrics().width('W'); joachim99@8: joachim99@8: int topLineYOffset = fontHeight + 3; joachim99@8: int xOffset = leftInfoWidth * fontWidth; joachim99@8: joachim99@8: int firstLineToDraw = 0; joachim99@8: int lastLineToDraw = (height() - topLineYOffset ) / fontHeight; joachim99@8: if ( abs(m_oldFirstLine - m_firstLine)>=lastLineToDraw ) joachim99@8: { joachim99@8: m_oldFirstLine = -1; joachim99@8: m_invalidRect |= QRect( 0, topLineYOffset, width(), height() ); joachim99@8: } joachim99@8: joachim99@8: if ( m_oldFirstLine != -1 && m_oldFirstLine != m_firstLine ) joachim99@8: { joachim99@8: int deltaY = fontHeight * ( m_oldFirstLine - m_firstLine ); joachim99@8: if ( deltaY > 0 ) joachim99@8: { // Move down joachim99@8: bitBlt( this, 0, deltaY + topLineYOffset /*dy*/, this, 0, topLineYOffset /*sy*/, width(), height()- (deltaY + topLineYOffset), CopyROP, true); joachim99@8: lastLineToDraw = firstLineToDraw + ( m_oldFirstLine - m_firstLine); joachim99@8: m_invalidRect |= QRect( 0, topLineYOffset, width(), deltaY ); joachim99@8: } joachim99@8: else joachim99@8: { // Move up joachim99@8: bitBlt( this, 0, topLineYOffset /*dy*/, this, 0, -deltaY+topLineYOffset /*sy*/, width(), height()-(-deltaY+topLineYOffset), CopyROP, true); joachim99@8: firstLineToDraw = lastLineToDraw + ( m_oldFirstLine - m_firstLine); joachim99@8: m_invalidRect |= QRect( 0, height()+deltaY, width(), -deltaY ); joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: if ( m_oldFirstColumn != -1 && m_oldFirstColumn != m_firstColumn ) joachim99@8: { joachim99@8: int deltaX = fontWidth * ( m_oldFirstColumn - m_firstColumn ); joachim99@8: if ( deltaX > 0 ) joachim99@8: { // Move right, scroll left joachim99@8: bitBlt( this, deltaX+xOffset, topLineYOffset, this, xOffset, topLineYOffset, width(), height(), CopyROP, true); joachim99@8: m_invalidRect |= joachim99@8: QRect( xOffset, topLineYOffset, deltaX, height() - topLineYOffset ); joachim99@8: } joachim99@8: else joachim99@8: { // Move left, scroll right joachim99@8: bitBlt( this, xOffset, topLineYOffset, this, xOffset-deltaX, topLineYOffset, width()-(xOffset-deltaX), height()-topLineYOffset, CopyROP, true); joachim99@8: m_invalidRect |= joachim99@8: QRect( width() + deltaX, topLineYOffset, -deltaX, height() - topLineYOffset ); joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: if ( selection.oldLastLine != -1 ) joachim99@8: { joachim99@8: int lastLine; joachim99@8: int firstLine; joachim99@8: if ( selection.oldFirstLine != -1 ) joachim99@8: { joachim99@8: firstLine = min3( selection.oldFirstLine, selection.lastLine, selection.oldLastLine ); joachim99@8: lastLine = max3( selection.oldFirstLine, selection.lastLine, selection.oldLastLine ); joachim99@8: } joachim99@8: else joachim99@8: { joachim99@8: firstLine = min2( selection.lastLine, selection.oldLastLine ); joachim99@8: lastLine = max2( selection.lastLine, selection.oldLastLine ); joachim99@8: } joachim99@8: int y1 = topLineYOffset + ( firstLine - m_firstLine ) * fontHeight; joachim99@8: int y2 = min2( height(), joachim99@8: topLineYOffset + ( lastLine - m_firstLine +1 ) * fontHeight ); joachim99@8: joachim99@8: if ( y1topLineYOffset ) joachim99@8: { joachim99@8: m_invalidRect |= QRect( 0, y1, width(), y2-y1 ); joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: if ( m_invalidRect.isEmpty() ) joachim99@8: return; joachim99@8: joachim99@8: QPainter painter(this); joachim99@8: //QPainter& p=painter; joachim99@8: QPixmap pixmap( m_invalidRect.size() ); joachim99@8: QPainter p( &pixmap ); joachim99@8: p.translate( -m_invalidRect.x(), -m_invalidRect.y() ); joachim99@8: joachim99@8: p.fillRect( m_invalidRect, m_pOptionDialog->m_bgColor ); joachim99@8: joachim99@8: firstLineToDraw += m_firstLine; joachim99@8: lastLineToDraw += m_firstLine; joachim99@8: joachim99@8: p.setFont( font() ); joachim99@8: joachim99@8: p.setPen( m_cThis ); joachim99@8: if( m_invalidRect.intersects( QRect(0,0,width(), topLineYOffset ) ) joachim99@8: || m_firstLine != m_oldFirstLine ) joachim99@8: { joachim99@8: int l=-1; joachim99@8: for ( int i = m_firstLine; i<(int)m_pDiff3LineVector->size(); ++i ) joachim99@8: { joachim99@8: const Diff3Line* d3l = (*m_pDiff3LineVector)[i]; joachim99@8: if ( m_winIdx==1 ) l=d3l->lineA; joachim99@8: else if ( m_winIdx==2 ) l=d3l->lineB; joachim99@8: else if ( m_winIdx==3 ) l=d3l->lineC; joachim99@8: else assert(false); joachim99@8: if (l!=-1) break; joachim99@8: } joachim99@8: joachim99@8: const char* winId = ( m_winIdx==1 ? (m_bTriple?"A (Base)":"A") : joachim99@8: ( m_winIdx==2 ? "B" : "C" ) ); joachim99@8: joachim99@51: QString s = QString(" ")+ winId + " : " + m_filename + " : "; joachim99@8: if ( l!=-1 ) joachim99@51: s += i18n("Topline %1").arg( l+1 ); joachim99@8: else joachim99@51: s += i18n("End"); joachim99@8: joachim99@8: if (hasFocus()) joachim99@8: { joachim99@8: painter.fillRect( 0, 0, width(), topLineYOffset, m_cThis ); joachim99@8: painter.setPen( m_pOptionDialog->m_bgColor ); joachim99@8: painter.drawText( 0, fontAscent+1, s ); joachim99@8: } joachim99@8: else joachim99@8: { joachim99@8: painter.fillRect( 0, 0, width(), topLineYOffset, m_pOptionDialog->m_bgColor ); joachim99@8: painter.setPen( m_cThis ); joachim99@8: painter.drawLine( 0, fontHeight + 2, width(), fontHeight + 2 ); joachim99@8: painter.drawText( 0, fontAscent+1, s ); joachim99@8: } joachim99@8: } joachim99@8: joachim99@8: int lastVisibleLine = min2( m_firstLine + getNofVisibleLines()+2, (int)m_pDiff3LineVector->size() ); joachim99@8: joachim99@8: for ( int line = m_firstLine; linepLine, ld->size + 1 ); joachim99@8: } joachim99@8: return QCString(); joachim99@8: } joachim99@8: joachim99@8: joachim99@8: void DiffTextWindow::getLineInfo( joachim99@8: const Diff3Line& d, joachim99@8: int& lineIdx, joachim99@8: DiffList*& pFineDiff1, DiffList*& pFineDiff2, // return values joachim99@8: int& changed, int& changed2 joachim99@8: ) joachim99@8: { joachim99@8: changed=0; joachim99@8: changed2=0; joachim99@8: bool bAEqB = d.bAEqB || ( d.bWhiteLineA && d.bWhiteLineB ); joachim99@8: bool bAEqC = d.bAEqC || ( d.bWhiteLineA && d.bWhiteLineC ); joachim99@8: bool bBEqC = d.bBEqC || ( d.bWhiteLineB && d.bWhiteLineC ); joachim99@8: if ( m_winIdx == 1 ) { joachim99@8: lineIdx=d.lineA; joachim99@8: pFineDiff1=d.pFineAB; joachim99@8: pFineDiff2=d.pFineCA; joachim99@8: changed |= ((d.lineB==-1)!=(lineIdx==-1) ? 1 : 0) + joachim99@8: ((d.lineC==-1)!=(lineIdx==-1) && m_bTriple ? 2 : 0); joachim99@8: changed2 |= ( bAEqB ? 0 : 1 ) + (bAEqC || !m_bTriple ? 0 : 2); joachim99@8: } joachim99@8: else if ( m_winIdx == 2 ) { joachim99@8: lineIdx=d.lineB; joachim99@8: pFineDiff1=d.pFineBC; joachim99@8: pFineDiff2=d.pFineAB; joachim99@8: changed |= ((d.lineC==-1)!=(lineIdx==-1) && m_bTriple ? 1 : 0) + joachim99@8: ((d.lineA==-1)!=(lineIdx==-1) ? 2 : 0); joachim99@8: changed2 |= ( bBEqC || !m_bTriple ? 0 : 1 ) + (bAEqB ? 0 : 2); joachim99@8: } joachim99@8: else if ( m_winIdx == 3 ) { joachim99@8: lineIdx=d.lineC; joachim99@8: pFineDiff1=d.pFineCA; joachim99@8: pFineDiff2=d.pFineBC; joachim99@8: changed |= ((d.lineA==-1)!=(lineIdx==-1) ? 1 : 0) + joachim99@8: ((d.lineB==-1)!=(lineIdx==-1) ? 2 : 0); joachim99@8: changed2 |= ( bAEqC ? 0 : 1 ) + (bBEqC ? 0 : 2); joachim99@8: } joachim99@8: else assert(false); joachim99@8: } joachim99@8: joachim99@8: joachim99@8: joachim99@8: void DiffTextWindow::resizeEvent( QResizeEvent* e ) joachim99@8: { joachim99@8: QSize s = e->size(); joachim99@8: QFontMetrics fm = fontMetrics(); joachim99@8: int visibleLines = s.height()/fm.height()-2; joachim99@8: int visibleColumns = s.width()/fm.width('W')-leftInfoWidth; joachim99@8: emit resizeSignal( visibleColumns, visibleLines ); joachim99@8: QWidget::resizeEvent(e); joachim99@8: } joachim99@8: joachim99@8: int DiffTextWindow::getNofVisibleLines() joachim99@8: { joachim99@8: QFontMetrics fm = fontMetrics(); joachim99@8: int fmh = fm.height(); joachim99@8: int h = height(); joachim99@8: return h/fmh -2;//height()/fm.height()-2; joachim99@8: } joachim99@8: joachim99@8: int DiffTextWindow::getNofVisibleColumns() joachim99@8: { joachim99@8: QFontMetrics fm = fontMetrics(); joachim99@8: return width()/fm.width('W')-leftInfoWidth; joachim99@8: } joachim99@8: joachim99@8: QString DiffTextWindow::getSelection() joachim99@8: { joachim99@8: QString selectionString; joachim99@8: joachim99@8: int line=0; joachim99@8: int lineIdx=0; joachim99@8: joachim99@8: int it; joachim99@8: for( it=0; it<(int)m_pDiff3LineVector->size(); ++it ) joachim99@8: { joachim99@8: const Diff3Line* d = (*m_pDiff3LineVector)[it]; joachim99@8: if ( m_winIdx == 1 ) { lineIdx=d->lineA; } joachim99@8: else if ( m_winIdx == 2 ) { lineIdx=d->lineB; } joachim99@8: else if ( m_winIdx == 3 ) { lineIdx=d->lineC; } joachim99@8: else assert(false); joachim99@8: joachim99@8: if( lineIdx != -1 ) joachim99@8: { joachim99@8: const char* pLine = m_pLineData[lineIdx].pLine; joachim99@8: int size = m_pLineData[lineIdx].size; joachim99@8: joachim99@8: // Consider tabs joachim99@8: int outPos = 0; joachim99@8: for( int i=0; isize() : -1; joachim99@8: int step = bDirDown ? 1 : -1; joachim99@8: int startPos = posInLine; joachim99@8: joachim99@8: for( ; it!=endIt; it+=step ) joachim99@8: { joachim99@8: QCString line = getString( it ); joachim99@8: if ( !line.isEmpty() ) joachim99@8: { joachim99@8: int pos = line.find( s, startPos, bCaseSensitive ); joachim99@8: if ( pos != -1 ) joachim99@8: { joachim99@8: d3vLine = it; joachim99@8: posInLine = pos; joachim99@8: return true; joachim99@8: } joachim99@8: joachim99@8: startPos = 0; joachim99@8: } joachim99@8: } joachim99@8: return false; joachim99@8: } joachim99@8: joachim99@8: void DiffTextWindow::setSelection( int firstLine, int startPos, int lastLine, int endPos ) joachim99@8: { joachim99@8: selection.reset(); joachim99@8: selection.start( firstLine, convertToPosOnScreen( getString(firstLine), startPos ) ); joachim99@8: selection.end( lastLine, convertToPosOnScreen( getString(lastLine), endPos ) ); joachim99@8: update(); joachim99@8: } joachim99@51: joachim99@51: joachim99@51: #include joachim99@51: joachim99@51: QString decodeString( const char*s , OptionDialog* pOptions ) joachim99@51: { joachim99@51: if ( pOptions->m_bStringEncoding ) joachim99@51: { joachim99@51: QTextCodec* c = QTextCodec::codecForLocale(); joachim99@51: if (c!=0) joachim99@51: return c->toUnicode( s ); joachim99@51: else joachim99@51: return QString(s); joachim99@51: } joachim99@51: else joachim99@51: return QString(s); joachim99@51: } joachim99@58: joachim99@58: QCString encodeString( const QString& s , OptionDialog* pOptions ) joachim99@58: { joachim99@58: if ( pOptions->m_bStringEncoding ) joachim99@58: { joachim99@58: QTextCodec* c = QTextCodec::codecForLocale(); joachim99@58: if (c!=0) joachim99@58: return c->fromUnicode( s ); joachim99@58: else joachim99@58: return QCString( s.ascii() ); joachim99@58: } joachim99@58: else joachim99@58: return QCString( s.ascii() ); joachim99@58: }