joachim99@8
|
1 /***************************************************************************
|
joachim99@8
|
2 diff.h - description
|
joachim99@8
|
3 -------------------
|
joachim99@8
|
4 begin : Mon Mar 18 2002
|
joachim99@8
|
5 copyright : (C) 2002 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 /***************************************************************************
|
joachim99@8
|
19 * $Log$
|
joachim99@8
|
20 * Revision 1.1 2003/10/06 18:38:48 joachim99
|
joachim99@8
|
21 * KDiff3 version 0.9.70
|
joachim99@8
|
22 * *
|
joachim99@8
|
23 ***************************************************************************/
|
joachim99@8
|
24
|
joachim99@8
|
25 #ifndef DIFF_H
|
joachim99@8
|
26 #define DIFF_H
|
joachim99@8
|
27
|
joachim99@8
|
28 #include <qwidget.h>
|
joachim99@8
|
29 #include <qpixmap.h>
|
joachim99@8
|
30 #include <qtimer.h>
|
joachim99@8
|
31 #include <qframe.h>
|
joachim99@8
|
32 #include <list>
|
joachim99@8
|
33 #include <vector>
|
joachim99@8
|
34 #include <assert.h>
|
joachim99@8
|
35 #include "common.h"
|
joachim99@8
|
36 #include "fileaccess.h"
|
joachim99@8
|
37
|
joachim99@8
|
38
|
joachim99@8
|
39
|
joachim99@8
|
40 // Each range with matching elements is followed by a range with differences on either side.
|
joachim99@8
|
41 // Then again range of matching elements should follow.
|
joachim99@8
|
42 struct Diff
|
joachim99@8
|
43 {
|
joachim99@8
|
44 int nofEquals;
|
joachim99@8
|
45
|
joachim99@8
|
46 int diff1;
|
joachim99@8
|
47 int diff2;
|
joachim99@8
|
48
|
joachim99@8
|
49 Diff(int eq, int d1, int d2){nofEquals=eq; diff1=d1; diff2=d2; }
|
joachim99@8
|
50 };
|
joachim99@8
|
51
|
joachim99@8
|
52 typedef std::list<Diff> DiffList;
|
joachim99@8
|
53
|
joachim99@8
|
54 struct Diff3Line
|
joachim99@8
|
55 {
|
joachim99@8
|
56 int lineA;
|
joachim99@8
|
57 int lineB;
|
joachim99@8
|
58 int lineC;
|
joachim99@8
|
59
|
joachim99@8
|
60 bool bAEqC; // These are true if equal or only white-space changes exist.
|
joachim99@8
|
61 bool bBEqC;
|
joachim99@8
|
62 bool bAEqB;
|
joachim99@8
|
63
|
joachim99@8
|
64 DiffList* pFineAB; // These are 0 only if completely equal.
|
joachim99@8
|
65 DiffList* pFineBC;
|
joachim99@8
|
66 DiffList* pFineCA;
|
joachim99@8
|
67
|
joachim99@8
|
68 bool bWhiteLineA;
|
joachim99@8
|
69 bool bWhiteLineB;
|
joachim99@8
|
70 bool bWhiteLineC;
|
joachim99@8
|
71
|
joachim99@8
|
72 Diff3Line()
|
joachim99@8
|
73 {
|
joachim99@8
|
74 lineA=-1; lineB=-1; lineC=-1;
|
joachim99@8
|
75 bAEqC=false; bAEqB=false; bBEqC=false;
|
joachim99@8
|
76 pFineAB=0; pFineBC=0; pFineCA=0;
|
joachim99@8
|
77 }
|
joachim99@8
|
78
|
joachim99@8
|
79 ~Diff3Line()
|
joachim99@8
|
80 {
|
joachim99@8
|
81 if (pFineAB!=0) delete pFineAB;
|
joachim99@8
|
82 if (pFineBC!=0) delete pFineBC;
|
joachim99@8
|
83 if (pFineCA!=0) delete pFineCA;
|
joachim99@8
|
84 pFineAB=0; pFineBC=0; pFineCA=0;
|
joachim99@8
|
85 }
|
joachim99@8
|
86
|
joachim99@8
|
87 bool operator==( const Diff3Line& d3l )
|
joachim99@8
|
88 {
|
joachim99@8
|
89 return lineA == d3l.lineA && lineB == d3l.lineB && lineC == d3l.lineC
|
joachim99@8
|
90 && bAEqB == d3l.bAEqB && bAEqC == d3l.bAEqC && bBEqC == d3l.bBEqC;
|
joachim99@8
|
91 }
|
joachim99@8
|
92 };
|
joachim99@8
|
93
|
joachim99@8
|
94 typedef std::list<Diff3Line> Diff3LineList;
|
joachim99@8
|
95 typedef std::vector<const Diff3Line*> Diff3LineVector;
|
joachim99@8
|
96
|
joachim99@8
|
97 class TotalDiffStatus
|
joachim99@8
|
98 {
|
joachim99@8
|
99 public:
|
joachim99@8
|
100 void reset() {bBinaryAEqC=false; bBinaryBEqC=false; bBinaryAEqB=false;
|
joachim99@8
|
101 bTextAEqC=false; bTextBEqC=false; bTextAEqB=false;}
|
joachim99@8
|
102 bool bBinaryAEqC;
|
joachim99@8
|
103 bool bBinaryBEqC;
|
joachim99@8
|
104 bool bBinaryAEqB;
|
joachim99@8
|
105
|
joachim99@8
|
106 bool bTextAEqC;
|
joachim99@8
|
107 bool bTextBEqC;
|
joachim99@8
|
108 bool bTextAEqB;
|
joachim99@8
|
109 };
|
joachim99@8
|
110
|
joachim99@8
|
111 void calcDiff3LineListUsingAB(
|
joachim99@8
|
112 const DiffList* pDiffListAB,
|
joachim99@8
|
113 Diff3LineList& d3ll
|
joachim99@8
|
114 );
|
joachim99@8
|
115
|
joachim99@8
|
116 void calcDiff3LineListUsingAC(
|
joachim99@8
|
117 const DiffList* pDiffListBC,
|
joachim99@8
|
118 Diff3LineList& d3ll
|
joachim99@8
|
119 );
|
joachim99@8
|
120
|
joachim99@8
|
121 void calcDiff3LineListUsingBC(
|
joachim99@8
|
122 const DiffList* pDiffListBC,
|
joachim99@8
|
123 Diff3LineList& d3ll
|
joachim99@8
|
124 );
|
joachim99@8
|
125
|
joachim99@8
|
126 struct LineData
|
joachim99@8
|
127 {
|
joachim99@8
|
128 const char* pLine;
|
joachim99@8
|
129 const char* pFirstNonWhiteChar;
|
joachim99@8
|
130 int size;
|
joachim99@8
|
131
|
joachim99@8
|
132 LineData(){ pLine=0; size=0; occurances=0; }
|
joachim99@8
|
133 int width(); // Calcs width considering tabs.
|
joachim99@8
|
134 int occurances;
|
joachim99@8
|
135 bool whiteLine(){ return pFirstNonWhiteChar-pLine == size; }
|
joachim99@8
|
136 };
|
joachim99@8
|
137
|
joachim99@8
|
138 void prepareOccurances( LineData* p, int size );
|
joachim99@8
|
139
|
joachim99@8
|
140
|
joachim99@8
|
141 class SourceData
|
joachim99@8
|
142 {
|
joachim99@8
|
143 public:
|
joachim99@8
|
144 SourceData(){ m_pBuf=0;m_size=0;m_vSize=0;m_bIsText=false;m_bPreserve=false; }
|
joachim99@8
|
145 const char* m_pBuf;
|
joachim99@8
|
146 int m_size;
|
joachim99@8
|
147 int m_vSize; // Nr of lines in m_pBuf1 and size of m_v1, m_dv12 and m_dv13
|
joachim99@8
|
148 std::vector<LineData> m_v;
|
joachim99@8
|
149 bool m_bIsText;
|
joachim99@8
|
150 bool m_bPreserve;
|
joachim99@8
|
151 void reset();
|
joachim99@8
|
152 void readPPFile( bool bPreserveCR, const QString& ppCmd, bool bUpCase );
|
joachim99@8
|
153 void readLMPPFile( SourceData* pOrigSource, const QString& ppCmd, bool bUpCase );
|
joachim99@8
|
154 void readFile(const QString& filename, bool bFollowLinks, bool bUpCase );
|
joachim99@8
|
155 void preprocess(bool bPreserveCR );
|
joachim99@8
|
156 void setData( const QString& data, bool bUpCase );
|
joachim99@8
|
157 void setFilename(const QString& filename);
|
joachim99@8
|
158 void setFileAccess( const FileAccess& fa );
|
joachim99@8
|
159 FileAccess& getFileAccess();
|
joachim99@8
|
160 QString getFilename();
|
joachim99@8
|
161 void setAliasName(const QString& a);
|
joachim99@8
|
162 QString getAliasName();
|
joachim99@8
|
163 bool isEmpty() { return getFilename().isEmpty(); }
|
joachim99@8
|
164 private:
|
joachim99@8
|
165 QString m_fileName;
|
joachim99@8
|
166 QString m_aliasName;
|
joachim99@8
|
167 FileAccess m_fileAccess;
|
joachim99@8
|
168 };
|
joachim99@8
|
169
|
joachim99@8
|
170 void calcDiff3LineListTrim( Diff3LineList& d3ll, LineData* pldA, LineData* pldB, LineData* pldC );
|
joachim99@8
|
171 void calcWhiteDiff3Lines( Diff3LineList& d3ll, LineData* pldA, LineData* pldB, LineData* pldC );
|
joachim99@8
|
172
|
joachim99@8
|
173 void calcDiff3LineVector( const Diff3LineList& d3ll, Diff3LineVector& d3lv );
|
joachim99@8
|
174
|
joachim99@8
|
175 void debugLineCheck( Diff3LineList& d3ll, int size, int idx );
|
joachim99@8
|
176
|
joachim99@8
|
177 class QStatusBar;
|
joachim99@8
|
178
|
joachim99@8
|
179
|
joachim99@8
|
180
|
joachim99@8
|
181 class Selection
|
joachim99@8
|
182 {
|
joachim99@8
|
183 public:
|
joachim99@8
|
184 Selection(){ reset(); oldLastLine=-1; lastLine=-1; oldFirstLine=-1; }
|
joachim99@8
|
185 int firstLine;
|
joachim99@8
|
186 int firstPos;
|
joachim99@8
|
187 int lastLine;
|
joachim99@8
|
188 int lastPos;
|
joachim99@8
|
189 int oldLastLine;
|
joachim99@8
|
190 int oldFirstLine;
|
joachim99@8
|
191 bool bSelectionContainsData;
|
joachim99@8
|
192 bool isEmpty() { return firstLine==-1 || (firstLine==lastLine && firstPos==lastPos) || bSelectionContainsData==false;}
|
joachim99@8
|
193 void reset(){
|
joachim99@8
|
194 oldFirstLine=firstLine;
|
joachim99@8
|
195 oldLastLine =lastLine;
|
joachim99@8
|
196 firstLine=-1;
|
joachim99@8
|
197 bSelectionContainsData = false;
|
joachim99@8
|
198 }
|
joachim99@8
|
199 void start( int l, int p ) { firstLine = l; firstPos = p; }
|
joachim99@8
|
200 void end( int l, int p ) {
|
joachim99@8
|
201 if ( oldLastLine == -1 )
|
joachim99@8
|
202 oldLastLine = lastLine;
|
joachim99@8
|
203 lastLine = l;
|
joachim99@8
|
204 lastPos = p;
|
joachim99@8
|
205 }
|
joachim99@8
|
206 bool within( int l, int p );
|
joachim99@8
|
207
|
joachim99@8
|
208 bool lineWithin( int l );
|
joachim99@8
|
209 int firstPosInLine(int l);
|
joachim99@8
|
210 int lastPosInLine(int l);
|
joachim99@8
|
211 int beginLine(){ return min2(firstLine,lastLine); }
|
joachim99@8
|
212 int endLine(){ return max2(firstLine,lastLine); }
|
joachim99@8
|
213 int beginPos() { return firstLine==lastLine ? min2(firstPos,lastPos) :
|
joachim99@8
|
214 firstLine<lastLine ? firstPos : lastPos; }
|
joachim99@8
|
215 int endPos() { return firstLine==lastLine ? max2(firstPos,lastPos) :
|
joachim99@8
|
216 firstLine<lastLine ? lastPos : firstPos; }
|
joachim99@8
|
217 };
|
joachim99@8
|
218
|
joachim99@8
|
219 class OptionDialog;
|
joachim99@8
|
220
|
joachim99@8
|
221 class DiffTextWindow : public QWidget
|
joachim99@8
|
222 {
|
joachim99@8
|
223 Q_OBJECT
|
joachim99@8
|
224 public:
|
joachim99@8
|
225 DiffTextWindow(
|
joachim99@8
|
226 QWidget* pParent,
|
joachim99@8
|
227 QStatusBar* pStatusBar,
|
joachim99@8
|
228 OptionDialog* pOptionDialog
|
joachim99@8
|
229 );
|
joachim99@8
|
230 void init(
|
joachim99@8
|
231 const QString& fileName,
|
joachim99@8
|
232 LineData* pLineData,
|
joachim99@8
|
233 int size,
|
joachim99@8
|
234 const Diff3LineVector* pDiff3LineVector,
|
joachim99@8
|
235 int winIdx,
|
joachim99@8
|
236 bool bTriple
|
joachim99@8
|
237 );
|
joachim99@8
|
238 virtual void mousePressEvent ( QMouseEvent * );
|
joachim99@8
|
239 virtual void mouseReleaseEvent ( QMouseEvent * );
|
joachim99@8
|
240 virtual void mouseMoveEvent ( QMouseEvent * );
|
joachim99@8
|
241 virtual void mouseDoubleClickEvent ( QMouseEvent * e );
|
joachim99@8
|
242 void convertToLinePos( int x, int y, int& line, int& pos );
|
joachim99@8
|
243
|
joachim99@8
|
244 virtual void paintEvent( QPaintEvent* );
|
joachim99@8
|
245 virtual void dragEnterEvent( QDragEnterEvent* e );
|
joachim99@8
|
246 //void setData( const char* pText);
|
joachim99@8
|
247
|
joachim99@8
|
248 virtual void resizeEvent( QResizeEvent* );
|
joachim99@8
|
249
|
joachim99@8
|
250 QString getSelection();
|
joachim99@8
|
251 int getFirstLine() { return m_firstLine; }
|
joachim99@8
|
252
|
joachim99@8
|
253 int getNofColumns();
|
joachim99@8
|
254 int getNofLines();
|
joachim99@8
|
255 int getNofVisibleLines();
|
joachim99@8
|
256 int getNofVisibleColumns();
|
joachim99@8
|
257
|
joachim99@8
|
258 bool findString( const QCString& s, int& d3vLine, int& posInLine, bool bDirDown, bool bCaseSensitive );
|
joachim99@8
|
259 void setSelection( int firstLine, int startPos, int lastLine, int endPos );
|
joachim99@8
|
260
|
joachim99@8
|
261 void setPaintingAllowed( bool bAllowPainting );
|
joachim99@8
|
262 signals:
|
joachim99@8
|
263 void resizeSignal( int nofVisibleColumns, int nofVisibleLines );
|
joachim99@8
|
264 void scroll( int deltaX, int deltaY );
|
joachim99@8
|
265 void newSelection();
|
joachim99@8
|
266 void selectionEnd();
|
joachim99@8
|
267 void setFastSelectorLine( int line );
|
joachim99@8
|
268
|
joachim99@8
|
269 public slots:
|
joachim99@8
|
270 void setFirstLine( int line );
|
joachim99@8
|
271 void setFirstColumn( int col );
|
joachim99@8
|
272 void resetSelection();
|
joachim99@8
|
273 void setFastSelectorRange( int line1, int nofLines );
|
joachim99@8
|
274
|
joachim99@8
|
275 private:
|
joachim99@8
|
276 bool m_bPaintingAllowed;
|
joachim99@8
|
277 LineData* m_pLineData;
|
joachim99@8
|
278 int m_size;
|
joachim99@8
|
279 QString m_filename;
|
joachim99@8
|
280
|
joachim99@8
|
281 const Diff3LineVector* m_pDiff3LineVector;
|
joachim99@8
|
282
|
joachim99@8
|
283 OptionDialog* m_pOptionDialog;
|
joachim99@8
|
284 QColor m_cThis;
|
joachim99@8
|
285 QColor m_cDiff1;
|
joachim99@8
|
286 QColor m_cDiff2;
|
joachim99@8
|
287 QColor m_cDiffBoth;
|
joachim99@8
|
288
|
joachim99@8
|
289 int m_fastSelectorLine1;
|
joachim99@8
|
290 int m_fastSelectorNofLines;
|
joachim99@8
|
291
|
joachim99@8
|
292 bool m_bTriple;
|
joachim99@8
|
293 int m_winIdx;
|
joachim99@8
|
294 int m_firstLine;
|
joachim99@8
|
295 int m_oldFirstLine;
|
joachim99@8
|
296 int m_oldFirstColumn;
|
joachim99@8
|
297 int m_firstColumn;
|
joachim99@8
|
298 int m_lineNumberWidth;
|
joachim99@8
|
299
|
joachim99@8
|
300 void getLineInfo(
|
joachim99@8
|
301 const Diff3Line& d,
|
joachim99@8
|
302 int& lineIdx,
|
joachim99@8
|
303 DiffList*& pFineDiff1, DiffList*& pFineDiff2, // return values
|
joachim99@8
|
304 int& changed, int& changed2 );
|
joachim99@8
|
305
|
joachim99@8
|
306 QCString getString( int line );
|
joachim99@8
|
307
|
joachim99@8
|
308 void writeLine(
|
joachim99@8
|
309 QPainter& p, const LineData* pld,
|
joachim99@8
|
310 const DiffList* pLineDiff1, const DiffList* pLineDiff2, int line,
|
joachim99@8
|
311 int whatChanged, int whatChanged2, int srcLineNr );
|
joachim99@8
|
312
|
joachim99@8
|
313 QStatusBar* m_pStatusBar;
|
joachim99@8
|
314
|
joachim99@8
|
315 Selection selection;
|
joachim99@8
|
316
|
joachim99@8
|
317 int m_scrollDeltaX;
|
joachim99@8
|
318 int m_scrollDeltaY;
|
joachim99@8
|
319 virtual void timerEvent(QTimerEvent*);
|
joachim99@8
|
320 bool m_bMyUpdate;
|
joachim99@8
|
321 void myUpdate(int afterMilliSecs );
|
joachim99@8
|
322
|
joachim99@8
|
323 QRect m_invalidRect;
|
joachim99@8
|
324 };
|
joachim99@8
|
325
|
joachim99@8
|
326
|
joachim99@8
|
327
|
joachim99@8
|
328 class Overview : public QWidget
|
joachim99@8
|
329 {
|
joachim99@8
|
330 Q_OBJECT
|
joachim99@8
|
331 public:
|
joachim99@8
|
332 Overview( QWidget* pParent, OptionDialog* pOptions );
|
joachim99@8
|
333
|
joachim99@8
|
334 void init( Diff3LineList* pDiff3LineList, bool bTripleDiff );
|
joachim99@8
|
335 void setRange( int firstLine, int pageHeight );
|
joachim99@8
|
336 void setPaintingAllowed( bool bAllowPainting );
|
joachim99@8
|
337
|
joachim99@8
|
338 public slots:
|
joachim99@8
|
339 void setFirstLine(int firstLine);
|
joachim99@8
|
340 signals:
|
joachim99@8
|
341 void setLine(int);
|
joachim99@8
|
342 private:
|
joachim99@8
|
343 const Diff3LineList* m_pDiff3LineList;
|
joachim99@8
|
344 OptionDialog* m_pOptions;
|
joachim99@8
|
345 bool m_bTripleDiff;
|
joachim99@8
|
346 int m_firstLine;
|
joachim99@8
|
347 int m_pageHeight;
|
joachim99@8
|
348 QPixmap m_pixmap;
|
joachim99@8
|
349 bool m_bPaintingAllowed;
|
joachim99@8
|
350
|
joachim99@8
|
351 virtual void paintEvent( QPaintEvent* e );
|
joachim99@8
|
352 virtual void mousePressEvent( QMouseEvent* e );
|
joachim99@8
|
353 virtual void mouseMoveEvent( QMouseEvent* e );
|
joachim99@8
|
354 };
|
joachim99@8
|
355
|
joachim99@8
|
356
|
joachim99@8
|
357 enum e_MergeDetails
|
joachim99@8
|
358 {
|
joachim99@8
|
359 eDefault,
|
joachim99@8
|
360 eNoChange,
|
joachim99@8
|
361 eBChanged,
|
joachim99@8
|
362 eCChanged,
|
joachim99@8
|
363 eBCChanged, // conflict
|
joachim99@8
|
364 eBCChangedAndEqual, // possible conflict
|
joachim99@8
|
365 eBDeleted,
|
joachim99@8
|
366 eCDeleted,
|
joachim99@8
|
367 eBCDeleted, // possible conflict
|
joachim99@8
|
368
|
joachim99@8
|
369 eBChanged_CDeleted, // conflict
|
joachim99@8
|
370 eCChanged_BDeleted, // conflict
|
joachim99@8
|
371 eBAdded,
|
joachim99@8
|
372 eCAdded,
|
joachim99@8
|
373 eBCAdded, // conflict
|
joachim99@8
|
374 eBCAddedAndEqual // possible conflict
|
joachim99@8
|
375 };
|
joachim99@8
|
376
|
joachim99@8
|
377 void mergeOneLine( const Diff3Line& d, e_MergeDetails& mergeDetails, bool& bConflict, bool& bLineRemoved, int& src, bool bTwoInputs );
|
joachim99@8
|
378
|
joachim99@8
|
379
|
joachim99@8
|
380 class MergeResultWindow : public QWidget
|
joachim99@8
|
381 {
|
joachim99@8
|
382 Q_OBJECT
|
joachim99@8
|
383 public:
|
joachim99@8
|
384 MergeResultWindow(
|
joachim99@8
|
385 QWidget* pParent,
|
joachim99@8
|
386 OptionDialog* pOptionDialog
|
joachim99@8
|
387 );
|
joachim99@8
|
388
|
joachim99@8
|
389 void init(
|
joachim99@8
|
390 const LineData* pLineDataA,
|
joachim99@8
|
391 const LineData* pLineDataB,
|
joachim99@8
|
392 const LineData* pLineDataC,
|
joachim99@8
|
393 const Diff3LineList* pDiff3LineList,
|
joachim99@8
|
394 const TotalDiffStatus* pTotalDiffStatus,
|
joachim99@8
|
395 QString fileName
|
joachim99@8
|
396 );
|
joachim99@8
|
397
|
joachim99@8
|
398 bool saveDocument( const QString& fileName );
|
joachim99@8
|
399 int getNrOfUnsolvedConflicts();
|
joachim99@8
|
400 void choose(int selector);
|
joachim99@8
|
401
|
joachim99@8
|
402 int getNofColumns();
|
joachim99@8
|
403 int getNofLines();
|
joachim99@8
|
404 int getNofVisibleColumns();
|
joachim99@8
|
405 int getNofVisibleLines();
|
joachim99@8
|
406 virtual void resizeEvent( QResizeEvent* e );
|
joachim99@8
|
407 virtual void keyPressEvent( QKeyEvent* e );
|
joachim99@8
|
408 virtual void wheelEvent( QWheelEvent* e );
|
joachim99@8
|
409 QString getSelection();
|
joachim99@8
|
410 void resetSelection();
|
joachim99@8
|
411 void showNrOfConflicts();
|
joachim99@8
|
412 bool isDeltaAboveCurrent();
|
joachim99@8
|
413 bool isDeltaBelowCurrent();
|
joachim99@8
|
414 bool isConflictAboveCurrent();
|
joachim99@8
|
415 bool isConflictBelowCurrent();
|
joachim99@8
|
416 bool isUnsolvedConflictAboveCurrent();
|
joachim99@8
|
417 bool isUnsolvedConflictBelowCurrent();
|
joachim99@8
|
418 bool findString( const QCString& s, int& d3vLine, int& posInLine, bool bDirDown, bool bCaseSensitive );
|
joachim99@8
|
419 void setSelection( int firstLine, int startPos, int lastLine, int endPos );
|
joachim99@8
|
420 public slots:
|
joachim99@8
|
421 void setFirstLine(int firstLine);
|
joachim99@8
|
422 void setFirstColumn(int firstCol);
|
joachim99@8
|
423
|
joachim99@8
|
424 void slotGoCurrent();
|
joachim99@8
|
425 void slotGoTop();
|
joachim99@8
|
426 void slotGoBottom();
|
joachim99@8
|
427 void slotGoPrevDelta();
|
joachim99@8
|
428 void slotGoNextDelta();
|
joachim99@8
|
429 void slotGoPrevUnsolvedConflict();
|
joachim99@8
|
430 void slotGoNextUnsolvedConflict();
|
joachim99@8
|
431 void slotGoPrevConflict();
|
joachim99@8
|
432 void slotGoNextConflict();
|
joachim99@8
|
433 void slotChooseA();
|
joachim99@8
|
434 void slotChooseB();
|
joachim99@8
|
435 void slotChooseC();
|
joachim99@8
|
436 void slotChooseAEverywhere();
|
joachim99@8
|
437 void slotChooseBEverywhere();
|
joachim99@8
|
438 void slotChooseCEverywhere();
|
joachim99@8
|
439 void slotAutoSolve();
|
joachim99@8
|
440 void slotUnsolve();
|
joachim99@8
|
441 void slotSetFastSelectorLine(int);
|
joachim99@8
|
442
|
joachim99@8
|
443 signals:
|
joachim99@8
|
444 void scroll( int deltaX, int deltaY );
|
joachim99@8
|
445 void modified();
|
joachim99@8
|
446 void setFastSelectorRange( int line1, int nofLines );
|
joachim99@8
|
447 void sourceMask( int srcMask, int enabledMask );
|
joachim99@8
|
448 void resizeSignal();
|
joachim99@8
|
449 void selectionEnd();
|
joachim99@8
|
450 void newSelection();
|
joachim99@8
|
451 void updateAvailabilities();
|
joachim99@8
|
452 void showPopupMenu( const QPoint& point );
|
joachim99@8
|
453
|
joachim99@8
|
454 private:
|
joachim99@8
|
455 void merge(bool bAutoSolve, int defaultSelector);
|
joachim99@8
|
456 QCString getString( int lineIdx );
|
joachim99@8
|
457
|
joachim99@8
|
458 OptionDialog* m_pOptionDialog;
|
joachim99@8
|
459
|
joachim99@8
|
460 const LineData* m_pldA;
|
joachim99@8
|
461 const LineData* m_pldB;
|
joachim99@8
|
462 const LineData* m_pldC;
|
joachim99@8
|
463
|
joachim99@8
|
464 const Diff3LineList* m_pDiff3LineList;
|
joachim99@8
|
465 const TotalDiffStatus* m_pTotalDiffStatus;
|
joachim99@8
|
466
|
joachim99@8
|
467 private:
|
joachim99@8
|
468 class MergeEditLine
|
joachim99@8
|
469 {
|
joachim99@8
|
470 public:
|
joachim99@8
|
471 MergeEditLine(){ m_src=0; m_bLineRemoved=false; }
|
joachim99@8
|
472 void setConflict() { m_src=0; m_bLineRemoved=false; m_str=QCString(); }
|
joachim99@8
|
473 bool isConflict() { return m_src==0 && !m_bLineRemoved && m_str.isNull(); }
|
joachim99@8
|
474 void setRemoved(int src=0) { m_src=src; m_bLineRemoved=true; m_str=QCString(); }
|
joachim99@8
|
475 bool isRemoved() { return m_bLineRemoved; }
|
joachim99@8
|
476 bool isEditableText() { return !isConflict() && !isRemoved(); }
|
joachim99@8
|
477 void setString( const QCString& s ){ m_str=s; m_bLineRemoved=false; m_src=0; }
|
joachim99@8
|
478 const char* getString( const MergeResultWindow*, int& size );
|
joachim99@8
|
479 bool isModified() { return ! m_str.isNull() || (m_bLineRemoved && m_src==0); }
|
joachim99@8
|
480
|
joachim99@8
|
481 void setSource( int src, Diff3LineList::const_iterator i, bool bLineRemoved )
|
joachim99@8
|
482 {
|
joachim99@8
|
483 m_src=src; m_id3l=i; m_bLineRemoved =bLineRemoved;
|
joachim99@8
|
484 }
|
joachim99@8
|
485 int src() { return m_src; }
|
joachim99@8
|
486 Diff3LineList::const_iterator id3l(){return m_id3l;}
|
joachim99@8
|
487 // getString() is implemented as MergeResultWindow::getString()
|
joachim99@8
|
488 private:
|
joachim99@8
|
489 Diff3LineList::const_iterator m_id3l;
|
joachim99@8
|
490 int m_src; // 1, 2 or 3 for A, B or C respectively, or 0 when line is from neither source.
|
joachim99@8
|
491 QCString m_str; // String when modified by user or null-string when orig data is used.
|
joachim99@8
|
492 bool m_bLineRemoved;
|
joachim99@8
|
493 };
|
joachim99@8
|
494
|
joachim99@8
|
495 class MergeEditLineList : private std::list<MergeEditLine>
|
joachim99@8
|
496 { // I want to know the size immediately!
|
joachim99@8
|
497 private:
|
joachim99@8
|
498 typedef std::list<MergeEditLine> BASE;
|
joachim99@8
|
499 int m_size;
|
joachim99@8
|
500 public:
|
joachim99@8
|
501 typedef std::list<MergeEditLine>::iterator iterator;
|
joachim99@8
|
502 typedef std::list<MergeEditLine>::const_iterator const_iterator;
|
joachim99@8
|
503 MergeEditLineList(){m_size=0;}
|
joachim99@8
|
504 void clear() { m_size=0; BASE::clear(); }
|
joachim99@8
|
505 void push_back( const MergeEditLine& m) { ++m_size; BASE::push_back(m); }
|
joachim99@8
|
506 void push_front( const MergeEditLine& m) { ++m_size; BASE::push_front(m); }
|
joachim99@8
|
507 iterator erase( iterator i ) { --m_size; return BASE::erase(i); }
|
joachim99@8
|
508 iterator insert( iterator i, const MergeEditLine& m ) { ++m_size; return BASE::insert(i,m); }
|
joachim99@8
|
509 int size(){ /*assert(int(BASE::size())==m_size);*/ return m_size;}
|
joachim99@8
|
510 iterator begin(){return BASE::begin();}
|
joachim99@8
|
511 iterator end(){return BASE::end();}
|
joachim99@8
|
512 bool empty() { return m_size==0; }
|
joachim99@8
|
513 };
|
joachim99@8
|
514
|
joachim99@8
|
515 friend class MergeEditLine;
|
joachim99@8
|
516
|
joachim99@8
|
517 struct MergeLine
|
joachim99@8
|
518 {
|
joachim99@8
|
519 MergeLine()
|
joachim99@8
|
520 { srcSelect=0; mergeDetails=eDefault; d3lLineIdx = -1; srcRangeLength=0; bConflict=false; bDelta=false;}
|
joachim99@8
|
521 Diff3LineList::const_iterator id3l;
|
joachim99@8
|
522 e_MergeDetails mergeDetails;
|
joachim99@8
|
523 int d3lLineIdx; // Needed to show the correct window pos.
|
joachim99@8
|
524 int srcRangeLength; // how many src-lines have this properties
|
joachim99@8
|
525 bool bConflict;
|
joachim99@8
|
526 bool bDelta;
|
joachim99@8
|
527 int srcSelect;
|
joachim99@8
|
528 MergeEditLineList mergeEditLineList;
|
joachim99@8
|
529 };
|
joachim99@8
|
530
|
joachim99@8
|
531 private:
|
joachim99@8
|
532 static bool sameKindCheck( const MergeLine& ml1, const MergeLine& ml2 );
|
joachim99@8
|
533
|
joachim99@8
|
534 typedef std::list<MergeLine> MergeLineList;
|
joachim99@8
|
535 MergeLineList m_mergeLineList;
|
joachim99@8
|
536 MergeLineList::iterator m_currentMergeLineIt;
|
joachim99@8
|
537 int m_currentPos;
|
joachim99@8
|
538
|
joachim99@8
|
539 enum e_Direction { eUp, eDown };
|
joachim99@8
|
540 enum e_EndPoint { eDelta, eConflict, eUnsolvedConflict, eLine, eEnd };
|
joachim99@8
|
541 void go( e_Direction eDir, e_EndPoint eEndPoint );
|
joachim99@8
|
542 void calcIteratorFromLineNr(
|
joachim99@8
|
543 int line,
|
joachim99@8
|
544 MergeLineList::iterator& mlIt,
|
joachim99@8
|
545 MergeEditLineList::iterator& melIt
|
joachim99@8
|
546 );
|
joachim99@8
|
547
|
joachim99@8
|
548 virtual void paintEvent( QPaintEvent* e );
|
joachim99@8
|
549
|
joachim99@8
|
550
|
joachim99@8
|
551 void myUpdate(int afterMilliSecs);
|
joachim99@8
|
552 virtual void timerEvent(QTimerEvent*);
|
joachim99@8
|
553 void writeLine(
|
joachim99@8
|
554 QPainter& p, int line, const char* pStr, int size,
|
joachim99@8
|
555 int srcSelect, e_MergeDetails mergeDetails, int rangeMark, bool bUserModified, bool bLineRemoved
|
joachim99@8
|
556 );
|
joachim99@8
|
557 void setFastSelector(MergeLineList::iterator i);
|
joachim99@8
|
558 void convertToLinePos( int x, int y, int& line, int& pos );
|
joachim99@8
|
559 virtual void mousePressEvent ( QMouseEvent* e );
|
joachim99@8
|
560 virtual void mouseDoubleClickEvent ( QMouseEvent* e );
|
joachim99@8
|
561 virtual void mouseReleaseEvent ( QMouseEvent * );
|
joachim99@8
|
562 virtual void mouseMoveEvent ( QMouseEvent * );
|
joachim99@8
|
563
|
joachim99@8
|
564 QPixmap m_pixmap;
|
joachim99@8
|
565 int m_firstLine;
|
joachim99@8
|
566 int m_firstColumn;
|
joachim99@8
|
567 int m_nofColumns;
|
joachim99@8
|
568 int m_nofLines;
|
joachim99@8
|
569 bool m_bMyUpdate;
|
joachim99@8
|
570 bool m_bInsertMode;
|
joachim99@8
|
571 QString m_fileName;
|
joachim99@8
|
572 bool m_bModified;
|
joachim99@8
|
573 void setModified();
|
joachim99@8
|
574
|
joachim99@8
|
575 int m_scrollDeltaX;
|
joachim99@8
|
576 int m_scrollDeltaY;
|
joachim99@8
|
577 int m_cursorXPos;
|
joachim99@8
|
578 int m_cursorYPos;
|
joachim99@8
|
579 int m_cursorOldXPos;
|
joachim99@8
|
580 bool m_bCursorOn; // blinking on and off each second
|
joachim99@8
|
581 QTimer m_cursorTimer;
|
joachim99@8
|
582
|
joachim99@8
|
583 Selection m_selection;
|
joachim99@8
|
584
|
joachim99@8
|
585 bool deleteSelection2( const char*& ps, int& stringLength, int& x, int& y,
|
joachim99@8
|
586 MergeLineList::iterator& mlIt, MergeEditLineList::iterator& melIt );
|
joachim99@8
|
587 public slots:
|
joachim99@8
|
588 void deleteSelection();
|
joachim99@8
|
589 void pasteClipboard();
|
joachim99@8
|
590 private slots:
|
joachim99@8
|
591 void slotCursorUpdate();
|
joachim99@8
|
592 };
|
joachim99@8
|
593
|
joachim99@8
|
594 void fineDiff(
|
joachim99@8
|
595 Diff3LineList& diff3LineList,
|
joachim99@8
|
596 int selector,
|
joachim99@8
|
597 LineData* v1,
|
joachim99@8
|
598 LineData* v2,
|
joachim99@8
|
599 int maxSearchLength,
|
joachim99@8
|
600 bool& bTextsTotalEqual
|
joachim99@8
|
601 );
|
joachim99@8
|
602
|
joachim99@8
|
603
|
joachim99@8
|
604 bool equal( const LineData& l1, const LineData& l2, bool bStrict );
|
joachim99@8
|
605
|
joachim99@8
|
606 inline bool equal( char c1, char c2, bool /*bStrict*/ )
|
joachim99@8
|
607 {
|
joachim99@8
|
608 // If bStrict then white space doesn't match
|
joachim99@8
|
609
|
joachim99@8
|
610 //if ( bStrict && ( c1==' ' || c1=='\t' ) )
|
joachim99@8
|
611 // return false;
|
joachim99@8
|
612
|
joachim99@8
|
613 return c1==c2;
|
joachim99@8
|
614 }
|
joachim99@8
|
615
|
joachim99@8
|
616
|
joachim99@8
|
617 // My own diff-invention:
|
joachim99@8
|
618 template <class T>
|
joachim99@8
|
619 void calcDiff( const T* p1, int size1, const T* p2, int size2, DiffList& diffList, int match, int maxSearchRange )
|
joachim99@8
|
620 {
|
joachim99@8
|
621 diffList.clear();
|
joachim99@8
|
622
|
joachim99@8
|
623 const T* p1start = p1;
|
joachim99@8
|
624 const T* p2start = p2;
|
joachim99@8
|
625 const T* p1end=p1+size1;
|
joachim99@8
|
626 const T* p2end=p2+size2;
|
joachim99@8
|
627 for(;;)
|
joachim99@8
|
628 {
|
joachim99@8
|
629 int nofEquals = 0;
|
joachim99@8
|
630 while( p1!=p1end && p2!=p2end && equal(*p1, *p2, false) )
|
joachim99@8
|
631 {
|
joachim99@8
|
632
|
joachim99@8
|
633
|
joachim99@8
|
634 ++p1;
|
joachim99@8
|
635 ++p2;
|
joachim99@8
|
636 ++nofEquals;
|
joachim99@8
|
637 }
|
joachim99@8
|
638
|
joachim99@8
|
639 bool bBestValid=false;
|
joachim99@8
|
640 int bestI1=0;
|
joachim99@8
|
641 int bestI2=0;
|
joachim99@8
|
642 int i1=0;
|
joachim99@8
|
643 int i2=0;
|
joachim99@8
|
644 for( i1=0; ; ++i1 )
|
joachim99@8
|
645 {
|
joachim99@8
|
646 if ( &p1[i1]==p1end || ( bBestValid && i1>= bestI1+bestI2))
|
joachim99@8
|
647 {
|
joachim99@8
|
648 break;
|
joachim99@8
|
649 }
|
joachim99@8
|
650 for(i2=0;i2<maxSearchRange;++i2)
|
joachim99@8
|
651 {
|
joachim99@8
|
652 if( &p2[i2]==p2end || ( bBestValid && i1+i2>=bestI1+bestI2) )
|
joachim99@8
|
653 {
|
joachim99@8
|
654 break;
|
joachim99@8
|
655 }
|
joachim99@8
|
656 else if( equal( p2[i2], p1[i1], true ) &&
|
joachim99@8
|
657 ( match==1 || abs(i1-i2)<3 || ( &p2[i2+1]==p2end && &p1[i1+1]==p1end ) ||
|
joachim99@8
|
658 ( &p2[i2+1]!=p2end && &p1[i1+1]!=p1end && equal( p2[i2+1], p1[i1+1], false ))
|
joachim99@8
|
659 )
|
joachim99@8
|
660 )
|
joachim99@8
|
661 {
|
joachim99@8
|
662 if ( i1+i2 < bestI1+bestI2 || bBestValid==false )
|
joachim99@8
|
663 {
|
joachim99@8
|
664 bestI1 = i1;
|
joachim99@8
|
665 bestI2 = i2;
|
joachim99@8
|
666 bBestValid = true;
|
joachim99@8
|
667 break;
|
joachim99@8
|
668 }
|
joachim99@8
|
669 }
|
joachim99@8
|
670 }
|
joachim99@8
|
671 }
|
joachim99@8
|
672
|
joachim99@8
|
673 // The match was found using the strict search. Go back if there are non-strict
|
joachim99@8
|
674 // matches.
|
joachim99@8
|
675 while( bestI1>=1 && bestI2>=1 && equal( p1[bestI1-1], p2[bestI2-1], false ) )
|
joachim99@8
|
676 {
|
joachim99@8
|
677 --bestI1;
|
joachim99@8
|
678 --bestI2;
|
joachim99@8
|
679 }
|
joachim99@8
|
680
|
joachim99@8
|
681
|
joachim99@8
|
682 bool bEndReached = false;
|
joachim99@8
|
683 if (bBestValid)
|
joachim99@8
|
684 {
|
joachim99@8
|
685 // continue somehow
|
joachim99@8
|
686 Diff d(nofEquals, bestI1, bestI2);
|
joachim99@8
|
687 diffList.push_back( d );
|
joachim99@8
|
688
|
joachim99@8
|
689 p1 += bestI1;
|
joachim99@8
|
690 p2 += bestI2;
|
joachim99@8
|
691 }
|
joachim99@8
|
692 else
|
joachim99@8
|
693 {
|
joachim99@8
|
694 // Nothing else to match.
|
joachim99@8
|
695 Diff d(nofEquals, p1end-p1, p2end-p2);
|
joachim99@8
|
696 diffList.push_back( d );
|
joachim99@8
|
697
|
joachim99@8
|
698 bEndReached = true; //break;
|
joachim99@8
|
699 }
|
joachim99@8
|
700
|
joachim99@8
|
701 // Sometimes the algorithm that chooses the first match unfortunately chooses
|
joachim99@8
|
702 // a match where later actually equal parts don't match anymore.
|
joachim99@8
|
703 // A different match could be achieved, if we start at the end.
|
joachim99@8
|
704 // Do it, if it would be a better match.
|
joachim99@8
|
705 int nofUnmatched = 0;
|
joachim99@8
|
706 const T* pu1 = p1-1;
|
joachim99@8
|
707 const T* pu2 = p2-1;
|
joachim99@8
|
708 while ( pu1>=p1start && pu2>=p2start && equal( *pu1, *pu2, false ) )
|
joachim99@8
|
709 {
|
joachim99@8
|
710 ++nofUnmatched;
|
joachim99@8
|
711 --pu1;
|
joachim99@8
|
712 --pu2;
|
joachim99@8
|
713 }
|
joachim99@8
|
714
|
joachim99@8
|
715 Diff d = diffList.back();
|
joachim99@8
|
716 if ( nofUnmatched > 0 )
|
joachim99@8
|
717 {
|
joachim99@8
|
718 // We want to go backwards the nofUnmatched elements and redo
|
joachim99@8
|
719 // the matching
|
joachim99@8
|
720 d = diffList.back();
|
joachim99@8
|
721 Diff origBack = d;
|
joachim99@8
|
722 diffList.pop_back();
|
joachim99@8
|
723
|
joachim99@8
|
724 while ( nofUnmatched > 0 )
|
joachim99@8
|
725 {
|
joachim99@8
|
726 if ( d.diff1 > 0 && d.diff2 > 0 )
|
joachim99@8
|
727 {
|
joachim99@8
|
728 --d.diff1;
|
joachim99@8
|
729 --d.diff2;
|
joachim99@8
|
730 --nofUnmatched;
|
joachim99@8
|
731 }
|
joachim99@8
|
732 else if ( d.nofEquals > 0 )
|
joachim99@8
|
733 {
|
joachim99@8
|
734 --d.nofEquals;
|
joachim99@8
|
735 --nofUnmatched;
|
joachim99@8
|
736 }
|
joachim99@8
|
737
|
joachim99@8
|
738 if ( d.nofEquals==0 && (d.diff1==0 || d.diff2==0) && nofUnmatched>0 )
|
joachim99@8
|
739 {
|
joachim99@8
|
740 if ( diffList.empty() )
|
joachim99@8
|
741 break;
|
joachim99@8
|
742 d.nofEquals += diffList.back().nofEquals;
|
joachim99@8
|
743 d.diff1 += diffList.back().diff1;
|
joachim99@8
|
744 d.diff2 += diffList.back().diff2;
|
joachim99@8
|
745 diffList.pop_back();
|
joachim99@8
|
746 bEndReached = false;
|
joachim99@8
|
747 }
|
joachim99@8
|
748 }
|
joachim99@8
|
749
|
joachim99@8
|
750 if ( bEndReached )
|
joachim99@8
|
751 diffList.push_back( origBack );
|
joachim99@8
|
752 else
|
joachim99@8
|
753 {
|
joachim99@8
|
754
|
joachim99@8
|
755 p1 = pu1 + 1 + nofUnmatched;
|
joachim99@8
|
756 p2 = pu2 + 1 + nofUnmatched;
|
joachim99@8
|
757 diffList.push_back( d );
|
joachim99@8
|
758 }
|
joachim99@8
|
759 }
|
joachim99@8
|
760 if ( bEndReached )
|
joachim99@8
|
761 break;
|
joachim99@8
|
762 }
|
joachim99@8
|
763
|
joachim99@8
|
764 #ifndef NDEBUG
|
joachim99@8
|
765 // Verify difflist
|
joachim99@8
|
766 {
|
joachim99@8
|
767 int l1=0;
|
joachim99@8
|
768 int l2=0;
|
joachim99@8
|
769 DiffList::iterator i;
|
joachim99@8
|
770 for( i = diffList.begin(); i!=diffList.end(); ++i )
|
joachim99@8
|
771 {
|
joachim99@8
|
772 l1+= i->nofEquals + i->diff1;
|
joachim99@8
|
773 l2+= i->nofEquals + i->diff2;
|
joachim99@8
|
774 }
|
joachim99@8
|
775
|
joachim99@8
|
776 //if( l1!=p1-p1start || l2!=p2-p2start )
|
joachim99@8
|
777 if( l1!=size1 || l2!=size2 )
|
joachim99@8
|
778 assert( false );
|
joachim99@8
|
779 }
|
joachim99@8
|
780 #endif
|
joachim99@8
|
781 }
|
joachim99@8
|
782
|
joachim99@8
|
783
|
joachim99@8
|
784
|
joachim99@8
|
785 inline bool isWhite( char c )
|
joachim99@8
|
786 {
|
joachim99@8
|
787 return c==' ' || c=='\t' || c=='\r';
|
joachim99@8
|
788 }
|
joachim99@8
|
789
|
joachim99@8
|
790 /** Returns the number of equivalent spaces at position outPos.
|
joachim99@8
|
791 */
|
joachim99@8
|
792 inline int tabber( int outPos, int tabSize )
|
joachim99@8
|
793 {
|
joachim99@8
|
794 return tabSize - ( outPos % tabSize );
|
joachim99@8
|
795 }
|
joachim99@8
|
796
|
joachim99@8
|
797 /** Returns a line number where the linerange [line, line+nofLines] can
|
joachim99@8
|
798 be displayed best. If it fits into the currently visible range then
|
joachim99@8
|
799 the returned value is the current firstLine.
|
joachim99@8
|
800 */
|
joachim99@8
|
801 int getBestFirstLine( int line, int nofLines, int firstLine, int visibleLines );
|
joachim99@8
|
802
|
joachim99@8
|
803 extern int g_tabSize;
|
joachim99@8
|
804 extern bool g_bIgnoreWhiteSpace;
|
joachim99@8
|
805 extern bool g_bIgnoreTrivialMatches;
|
joachim99@8
|
806 extern int g_bAutoSolve;
|
joachim99@8
|
807
|
joachim99@8
|
808 // Cursor conversions that consider g_tabSize.
|
joachim99@8
|
809 int convertToPosInText( const char* p, int size, int posOnScreen );
|
joachim99@8
|
810 int convertToPosOnScreen( const char* p, int posInText );
|
joachim99@8
|
811 void calcTokenPos( const char* p, int size, int posOnScreen, int& pos1, int& pos2 );
|
joachim99@8
|
812 #endif
|
joachim99@8
|
813
|