joachim99@8: /*************************************************************************** joachim99@8: diff.h - description joachim99@8: ------------------- joachim99@8: begin : Mon Mar 18 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: #ifndef DIFF_H joachim99@8: #define DIFF_H joachim99@8: joachim99@8: #include joachim99@8: #include joachim99@8: #include joachim99@8: #include joachim99@8: #include joachim99@8: #include joachim99@8: #include joachim99@8: #include "common.h" joachim99@8: #include "fileaccess.h" joachim99@8: joachim99@58: class OptionDialog; joachim99@8: joachim99@8: // Each range with matching elements is followed by a range with differences on either side. joachim99@8: // Then again range of matching elements should follow. joachim99@8: struct Diff joachim99@8: { joachim99@8: int nofEquals; joachim99@8: joachim99@8: int diff1; joachim99@8: int diff2; joachim99@8: joachim99@8: Diff(int eq, int d1, int d2){nofEquals=eq; diff1=d1; diff2=d2; } joachim99@8: }; joachim99@8: joachim99@8: typedef std::list DiffList; joachim99@8: joachim99@8: struct Diff3Line joachim99@8: { joachim99@8: int lineA; joachim99@8: int lineB; joachim99@8: int lineC; joachim99@8: joachim99@8: bool bAEqC; // These are true if equal or only white-space changes exist. joachim99@8: bool bBEqC; joachim99@8: bool bAEqB; joachim99@8: joachim99@8: DiffList* pFineAB; // These are 0 only if completely equal. joachim99@8: DiffList* pFineBC; joachim99@8: DiffList* pFineCA; joachim99@8: joachim99@8: bool bWhiteLineA; joachim99@8: bool bWhiteLineB; joachim99@8: bool bWhiteLineC; joachim99@8: joachim99@8: Diff3Line() joachim99@8: { joachim99@8: lineA=-1; lineB=-1; lineC=-1; joachim99@8: bAEqC=false; bAEqB=false; bBEqC=false; joachim99@8: pFineAB=0; pFineBC=0; pFineCA=0; joachim99@8: } joachim99@8: joachim99@8: ~Diff3Line() joachim99@8: { joachim99@8: if (pFineAB!=0) delete pFineAB; joachim99@8: if (pFineBC!=0) delete pFineBC; joachim99@8: if (pFineCA!=0) delete pFineCA; joachim99@8: pFineAB=0; pFineBC=0; pFineCA=0; joachim99@8: } joachim99@8: joachim99@8: bool operator==( const Diff3Line& d3l ) joachim99@8: { joachim99@8: return lineA == d3l.lineA && lineB == d3l.lineB && lineC == d3l.lineC joachim99@8: && bAEqB == d3l.bAEqB && bAEqC == d3l.bAEqC && bBEqC == d3l.bBEqC; joachim99@8: } joachim99@8: }; joachim99@8: joachim99@8: typedef std::list Diff3LineList; joachim99@8: typedef std::vector Diff3LineVector; joachim99@8: joachim99@8: class TotalDiffStatus joachim99@8: { joachim99@8: public: joachim99@8: void reset() {bBinaryAEqC=false; bBinaryBEqC=false; bBinaryAEqB=false; joachim99@8: bTextAEqC=false; bTextBEqC=false; bTextAEqB=false;} joachim99@8: bool bBinaryAEqC; joachim99@8: bool bBinaryBEqC; joachim99@8: bool bBinaryAEqB; joachim99@8: joachim99@8: bool bTextAEqC; joachim99@8: bool bTextBEqC; joachim99@8: bool bTextAEqB; joachim99@8: }; joachim99@8: joachim99@51: void calcDiff3LineListUsingAB( joachim99@8: const DiffList* pDiffListAB, joachim99@8: Diff3LineList& d3ll joachim99@8: ); joachim99@8: joachim99@8: void calcDiff3LineListUsingAC( joachim99@8: const DiffList* pDiffListBC, joachim99@8: Diff3LineList& d3ll joachim99@8: ); joachim99@8: joachim99@8: void calcDiff3LineListUsingBC( joachim99@8: const DiffList* pDiffListBC, joachim99@8: Diff3LineList& d3ll joachim99@8: ); joachim99@8: joachim99@8: struct LineData joachim99@8: { joachim99@8: const char* pLine; joachim99@8: const char* pFirstNonWhiteChar; joachim99@8: int size; joachim99@8: joachim99@51: LineData(){ pLine=0; size=0; occurances=0; bContainsPureComment=false; } joachim99@58: int width() const; // Calcs width considering tabs. joachim99@8: int occurances; joachim99@58: bool whiteLine() const { return pFirstNonWhiteChar-pLine == size; } joachim99@51: bool bContainsPureComment; joachim99@8: }; joachim99@8: joachim99@8: joachim99@8: class SourceData joachim99@8: { joachim99@8: public: joachim99@58: SourceData(); joachim99@58: ~SourceData(); joachim99@58: joachim99@58: void setOptionDialog( OptionDialog* pOptionDialog ); joachim99@58: joachim99@58: int getSizeLines() const; joachim99@58: int getSizeBytes() const; joachim99@58: const char* getBuf() const; joachim99@58: const LineData* getLineDataForDisplay() const; joachim99@58: const LineData* getLineDataForDiff() const; joachim99@58: joachim99@8: void setFilename(const QString& filename); joachim99@8: void setFileAccess( const FileAccess& fa ); joachim99@8: FileAccess& getFileAccess(); joachim99@8: QString getFilename(); joachim99@8: void setAliasName(const QString& a); joachim99@8: QString getAliasName(); joachim99@58: bool isEmpty(); // File was set joachim99@58: bool hasData(); // Data was readable joachim99@58: bool isText(); // is it pure text (vs. binary data) joachim99@58: bool isFromBuffer(); // was it set via setData() (vs. setFileAccess() or setFilename()) joachim99@58: void setData( const QString& data ); joachim99@58: joachim99@58: void readAndPreprocess(); joachim99@58: bool saveNormalDataAs( const QString& fileName ); joachim99@58: joachim99@58: bool isBinaryEqualWith( const SourceData& other ) const; joachim99@58: joachim99@58: void reset(); joachim99@58: joachim99@58: private: joachim99@8: QString m_aliasName; joachim99@8: FileAccess m_fileAccess; joachim99@58: OptionDialog* m_pOptionDialog; joachim99@58: QString m_tempInputFileName; joachim99@58: joachim99@58: struct FileData joachim99@58: { joachim99@58: FileData(){ m_pBuf=0; m_size=0; } joachim99@58: ~FileData(){ reset(); } joachim99@58: const char* m_pBuf; joachim99@58: int m_size; joachim99@58: int m_vSize; // Nr of lines in m_pBuf1 and size of m_v1, m_dv12 and m_dv13 joachim99@58: std::vector m_v; joachim99@58: bool m_bIsText; joachim99@58: bool readFile( const QString& filename ); joachim99@58: bool writeFile( const QString& filename ); joachim99@58: void preprocess(bool bPreserveCR ); joachim99@58: void reset(); joachim99@58: void removeComments(); joachim99@58: void copyBufFrom( const FileData& src ); joachim99@58: }; joachim99@58: FileData m_normalData; joachim99@58: FileData m_lmppData; joachim99@8: }; joachim99@8: joachim99@58: void calcDiff3LineListTrim( Diff3LineList& d3ll, const LineData* pldA, const LineData* pldB, const LineData* pldC ); joachim99@58: void calcWhiteDiff3Lines( Diff3LineList& d3ll, const LineData* pldA, const LineData* pldB, const LineData* pldC ); joachim99@8: joachim99@8: void calcDiff3LineVector( const Diff3LineList& d3ll, Diff3LineVector& d3lv ); joachim99@8: joachim99@8: void debugLineCheck( Diff3LineList& d3ll, int size, int idx ); joachim99@8: joachim99@8: class QStatusBar; joachim99@8: joachim99@8: joachim99@8: joachim99@8: class Selection joachim99@8: { joachim99@8: public: joachim99@8: Selection(){ reset(); oldLastLine=-1; lastLine=-1; oldFirstLine=-1; } joachim99@8: int firstLine; joachim99@8: int firstPos; joachim99@8: int lastLine; joachim99@8: int lastPos; joachim99@8: int oldLastLine; joachim99@8: int oldFirstLine; joachim99@8: bool bSelectionContainsData; joachim99@8: bool isEmpty() { return firstLine==-1 || (firstLine==lastLine && firstPos==lastPos) || bSelectionContainsData==false;} joachim99@8: void reset(){ joachim99@8: oldFirstLine=firstLine; joachim99@8: oldLastLine =lastLine; joachim99@8: firstLine=-1; joachim99@8: bSelectionContainsData = false; joachim99@8: } joachim99@8: void start( int l, int p ) { firstLine = l; firstPos = p; } joachim99@8: void end( int l, int p ) { joachim99@8: if ( oldLastLine == -1 ) joachim99@8: oldLastLine = lastLine; joachim99@8: lastLine = l; joachim99@8: lastPos = p; joachim99@8: } joachim99@8: bool within( int l, int p ); joachim99@8: joachim99@8: bool lineWithin( int l ); joachim99@8: int firstPosInLine(int l); joachim99@8: int lastPosInLine(int l); joachim99@8: int beginLine(){ return min2(firstLine,lastLine); } joachim99@8: int endLine(){ return max2(firstLine,lastLine); } joachim99@8: int beginPos() { return firstLine==lastLine ? min2(firstPos,lastPos) : joachim99@8: firstLine joachim99@8: { // I want to know the size immediately! joachim99@8: private: joachim99@8: typedef std::list BASE; joachim99@8: int m_size; joachim99@58: int* m_pTotalSize; joachim99@8: public: joachim99@8: typedef std::list::iterator iterator; joachim99@8: typedef std::list::const_iterator const_iterator; joachim99@58: MergeEditLineList(){m_size=0; m_pTotalSize=0; } joachim99@58: void clear() { ds(-m_size); BASE::clear(); } joachim99@58: void push_back( const MergeEditLine& m) { ds(+1); BASE::push_back(m); } joachim99@58: void push_front( const MergeEditLine& m) { ds(+1); BASE::push_front(m); } joachim99@58: iterator erase( iterator i ) { ds(-1); return BASE::erase(i); } joachim99@58: iterator insert( iterator i, const MergeEditLine& m ) { ds(+1); return BASE::insert(i,m); } joachim99@8: int size(){ /*assert(int(BASE::size())==m_size);*/ return m_size;} joachim99@8: iterator begin(){return BASE::begin();} joachim99@8: iterator end(){return BASE::end();} joachim99@8: bool empty() { return m_size==0; } joachim99@58: joachim99@58: void setTotalSizePtr(int* pTotalSize) joachim99@58: { joachim99@58: m_pTotalSize = pTotalSize; joachim99@58: *m_pTotalSize += m_size; joachim99@58: } joachim99@58: joachim99@58: private: joachim99@58: void ds(int deltaSize) joachim99@58: { joachim99@58: m_size+=deltaSize; joachim99@58: if (m_pTotalSize!=0) *m_pTotalSize+=deltaSize; joachim99@58: } joachim99@8: }; joachim99@8: joachim99@8: friend class MergeEditLine; joachim99@8: joachim99@8: struct MergeLine joachim99@8: { joachim99@8: MergeLine() joachim99@51: { joachim99@51: srcSelect=0; mergeDetails=eDefault; d3lLineIdx = -1; srcRangeLength=0; joachim99@51: bConflict=false; bDelta=false; bWhiteSpaceConflict=false; joachim99@51: } joachim99@8: Diff3LineList::const_iterator id3l; joachim99@8: e_MergeDetails mergeDetails; joachim99@8: int d3lLineIdx; // Needed to show the correct window pos. joachim99@8: int srcRangeLength; // how many src-lines have this properties joachim99@8: bool bConflict; joachim99@51: bool bWhiteSpaceConflict; joachim99@8: bool bDelta; joachim99@8: int srcSelect; joachim99@8: MergeEditLineList mergeEditLineList; joachim99@8: }; joachim99@8: joachim99@8: private: joachim99@8: static bool sameKindCheck( const MergeLine& ml1, const MergeLine& ml2 ); joachim99@8: joachim99@8: typedef std::list MergeLineList; joachim99@8: MergeLineList m_mergeLineList; joachim99@8: MergeLineList::iterator m_currentMergeLineIt; joachim99@8: int m_currentPos; joachim99@8: joachim99@8: enum e_Direction { eUp, eDown }; joachim99@8: enum e_EndPoint { eDelta, eConflict, eUnsolvedConflict, eLine, eEnd }; joachim99@8: void go( e_Direction eDir, e_EndPoint eEndPoint ); joachim99@8: void calcIteratorFromLineNr( joachim99@8: int line, joachim99@8: MergeLineList::iterator& mlIt, joachim99@8: MergeEditLineList::iterator& melIt joachim99@8: ); joachim99@8: joachim99@8: virtual void paintEvent( QPaintEvent* e ); joachim99@8: joachim99@8: joachim99@8: void myUpdate(int afterMilliSecs); joachim99@8: virtual void timerEvent(QTimerEvent*); joachim99@8: void writeLine( joachim99@8: QPainter& p, int line, const char* pStr, int size, joachim99@8: int srcSelect, e_MergeDetails mergeDetails, int rangeMark, bool bUserModified, bool bLineRemoved joachim99@8: ); joachim99@8: void setFastSelector(MergeLineList::iterator i); joachim99@8: void convertToLinePos( int x, int y, int& line, int& pos ); joachim99@8: virtual void mousePressEvent ( QMouseEvent* e ); joachim99@8: virtual void mouseDoubleClickEvent ( QMouseEvent* e ); joachim99@8: virtual void mouseReleaseEvent ( QMouseEvent * ); joachim99@8: virtual void mouseMoveEvent ( QMouseEvent * ); joachim99@8: joachim99@8: QPixmap m_pixmap; joachim99@8: int m_firstLine; joachim99@8: int m_firstColumn; joachim99@8: int m_nofColumns; joachim99@8: int m_nofLines; joachim99@58: int m_totalSize; //Same as m_nofLines, but calculated differently joachim99@8: bool m_bMyUpdate; joachim99@8: bool m_bInsertMode; joachim99@8: QString m_fileName; joachim99@8: bool m_bModified; joachim99@8: void setModified(); joachim99@8: joachim99@8: int m_scrollDeltaX; joachim99@8: int m_scrollDeltaY; joachim99@8: int m_cursorXPos; joachim99@8: int m_cursorYPos; joachim99@8: int m_cursorOldXPos; joachim99@8: bool m_bCursorOn; // blinking on and off each second joachim99@8: QTimer m_cursorTimer; joachim99@8: joachim99@8: Selection m_selection; joachim99@8: joachim99@8: bool deleteSelection2( const char*& ps, int& stringLength, int& x, int& y, joachim99@8: MergeLineList::iterator& mlIt, MergeEditLineList::iterator& melIt ); joachim99@8: public slots: joachim99@8: void deleteSelection(); joachim99@8: void pasteClipboard(); joachim99@8: private slots: joachim99@8: void slotCursorUpdate(); joachim99@8: }; joachim99@8: joachim99@8: void fineDiff( joachim99@8: Diff3LineList& diff3LineList, joachim99@8: int selector, joachim99@58: const LineData* v1, joachim99@58: const LineData* v2, joachim99@8: bool& bTextsTotalEqual joachim99@8: ); joachim99@8: joachim99@8: joachim99@8: bool equal( const LineData& l1, const LineData& l2, bool bStrict ); joachim99@8: joachim99@8: joachim99@8: joachim99@8: joachim99@8: inline bool isWhite( char c ) joachim99@8: { joachim99@8: return c==' ' || c=='\t' || c=='\r'; joachim99@8: } joachim99@8: joachim99@8: /** Returns the number of equivalent spaces at position outPos. joachim99@8: */ joachim99@8: inline int tabber( int outPos, int tabSize ) joachim99@8: { joachim99@8: return tabSize - ( outPos % tabSize ); 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: extern int g_tabSize; joachim99@8: extern bool g_bIgnoreWhiteSpace; joachim99@8: extern bool g_bIgnoreTrivialMatches; joachim99@8: extern int g_bAutoSolve; joachim99@8: joachim99@8: // Cursor conversions that consider g_tabSize. joachim99@8: int convertToPosInText( const char* p, int size, int posOnScreen ); joachim99@8: int convertToPosOnScreen( const char* p, int posInText ); joachim99@8: void calcTokenPos( const char* p, int size, int posOnScreen, int& pos1, int& pos2 ); joachim99@8: #endif joachim99@8: