OSDN Git Service

Use std::vector for undo records. Optimize allocation of vector items. Should help...
[winmerge-jp/winmerge-jp.git] / Src / GhostTextBuffer.h
1 /**
2  * @file  GhostTextBuffer.h
3  *
4  * @brief Declaration of CGhostTextBuffer (subclasses CCrystalTextBuffer to handle ghost lines)
5  */
6 // ID line follows -- this is updated by SVN
7 // $Id$
8
9 #ifndef __GHOSTTEXTBUFFER_H__
10 #define __GHOSTTEXTBUFFER_H__
11
12 #include <vector>
13 #include "ccrystaltextbuffer.h"
14
15
16 /////////////////////////////////////////////////////////////////////////////
17
18 /**
19  * We use the current ccrystalEditor flags 
20  *
21  * This flag must be cleared and set in GhostTextBuffer.cpp 
22  * and MergeDoc.cpp (Rescan) only.
23  *
24  * GetLineColors (in MergeEditView) reads it to choose the line color.
25  */
26 enum GHOST_LINEFLAGS
27 {
28         LF_GHOST = 0x00400000L, /**< Ghost line. */
29 };
30
31 /////////////////////////////////////////////////////////////////////////////
32 // CCrystalTextBuffer command target
33
34 /**
35  * @brief A class handling ghost lines.
36  * Features offered with this class : 
37  * <ul>
38  *  <li> apparent/real line conversion 
39  *  <li> insertText/deleteText working with ghost lines 
40  *  <li> AddUndoRecord/Undo/Redo working with ghost lines 
41  *  <li> insertGhostLine function 
42  * </ul>
43  */
44 class EDITPADC_CLASS CGhostTextBuffer : public CCrystalTextBuffer
45 {
46 public:
47         DECLARE_DYNCREATE (CGhostTextBuffer)
48
49 protected :
50 #pragma pack(push, 1)
51         //  Nested class declarations
52         struct SLineInfo
53         {
54                 TCHAR *m_pcLine;
55                 int m_nLength, m_nMax;
56                 int m_nEolChars; // # of eolchars
57                 DWORD m_dwFlags;
58                 DWORD m_dwRevisionNumber;
59
60                 int FullLength() const { return m_nLength + m_nEolChars; }
61                 int Length() const { return m_nLength; }
62
63                 SLineInfo ()
64                 {
65                         memset (this, 0, sizeof (SLineInfo));
66                 };
67         };
68
69         enum
70         {
71                 UNDO_INSERT = 0x0001,
72                 UNDO_BEGINGROUP = 0x0100
73         };
74
75         /** 
76         Support For Descriptions On Undo/Redo Actions
77
78         We need a structure to remember richer information position
79         and the number of real lines inserted/deleted (to set ghost lines during undo)
80
81         This flags are parameters of AddUndoRecord ; so AddUndoRecord
82         is not the virtual version of CCrystalTextBuffer::AddUndoRecord
83
84         The text is duplicated (already in CCrystalTextBuffer::SUndoRecord),
85         and it is not useful. If someone finds a clean way to correct this...
86         */
87         struct SUndoRecord
88         {
89                 DWORD m_dwFlags;
90
91                 // Undo records store file line numbers, not screen line numbers
92                 // File line numbers do not count ghost lines
93                 // (ghost lines are lines with no text and no EOL chars, which are
94                 // used by WinMerge as left-only or right-only placeholders)
95                 // All the stored line number needed are real !
96
97                 CPoint m_ptStartPos, m_ptEndPos;  // Block of text participating
98                 int m_ptStartPos_nGhost, m_ptEndPos_nGhost;
99
100                 // Redo records store file line numbers, not screen line numbers
101                 // they store the file number of the previous real line
102                 // and (apparentLine - ComputeApparentLine(previousRealLine))
103
104                 CPoint m_redo_ptStartPos, m_redo_ptEndPos;  // Block of text participating
105                 int m_redo_ptStartPos_nGhost, m_redo_ptEndPos_nGhost;
106
107                 int m_nRealLinesCreated;         //  number of lines created during insertion 
108                                                  //  (= total of real lines after - total before)
109                 int m_nRealLinesInDeletedBlock;  //  number of real lines in the deleted block 
110                                                  // (<> total of real lines after - total before  
111                                                  //  as first/end line may be just truncated, not removed)
112                 int m_nAction;                   //  For information only: action type
113                 CDWordArray *m_paSavedRevisonNumbers;
114
115 private :
116                 // TCHAR   *m_pcText;
117                 // Since in most cases we have 1 character here,
118                 // we should invent a better way. Note: 2 * sizeof(WORD) <= sizeof(TCHAR*)
119                 //
120                 // Here we will use the following trick: on Win32 platforms high-order word
121                 // of any pointer will be != 0. So we can store 1 character strings without
122                 // allocating memory.
123                 //
124                 struct TextBuffer
125                 {
126                         int size;
127                         TCHAR data[1];
128                 };
129                 union
130                 {
131                         TextBuffer *m_pszText; // For cases when we have > 1 character strings
132                         TCHAR m_szText[2];     // For single-character strings
133
134                 };
135
136 public :
137                 SUndoRecord () // default constructor
138                 {
139                         memset (this, 0, sizeof (SUndoRecord));
140                 }
141                 SUndoRecord (const SUndoRecord & src) // copy constructor
142                 {
143                         memset (this, 0, sizeof (SUndoRecord));
144                         (*this)=src;
145                 }
146                 SUndoRecord & operator=(const SUndoRecord & src) // copy assignment
147                 {
148                         m_dwFlags = src.m_dwFlags;
149                         m_ptStartPos = src.m_ptStartPos;
150                         m_ptStartPos_nGhost = src.m_ptStartPos_nGhost;
151                         m_ptEndPos = src.m_ptEndPos;
152                         m_ptEndPos_nGhost = src.m_ptEndPos_nGhost;
153                         m_nAction = src.m_nAction;
154                         m_redo_ptStartPos = src.m_redo_ptStartPos;
155                         m_redo_ptStartPos_nGhost = src.m_redo_ptStartPos_nGhost;
156                         m_redo_ptEndPos = src.m_redo_ptEndPos;
157                         m_redo_ptEndPos_nGhost = src.m_redo_ptEndPos_nGhost;
158                         m_nRealLinesCreated = src.m_nRealLinesCreated;
159                         m_nRealLinesInDeletedBlock = src.m_nRealLinesInDeletedBlock;
160                         SetText(src.GetText(), src.GetTextLength());
161                         INT_PTR size = src.m_paSavedRevisonNumbers->GetSize();
162                         if (!m_paSavedRevisonNumbers)
163                                 m_paSavedRevisonNumbers = new CDWordArray();
164                         m_paSavedRevisonNumbers->SetSize(size);
165                         INT_PTR i;
166                         for (i = 0; i < size; i++)
167                                 (*m_paSavedRevisonNumbers)[i] = (*src.m_paSavedRevisonNumbers)[i];
168                         return *this;
169                 }
170                 ~SUndoRecord () // destructor
171                 {
172                         FreeText();
173                         if (m_paSavedRevisonNumbers)
174                                 delete m_paSavedRevisonNumbers;
175                 }
176
177                 void SetText (LPCTSTR pszText, int cchText);
178                 void FreeText ();
179
180                 LPCTSTR GetText () const
181                 {
182                         // See the m_szText/m_pszText definition
183                         // Check if m_pszText is a pointer by removing bits having
184                         // possible char value
185                         if (((INT_PTR)m_pszText >> 16) != 0)
186                                 return m_pszText->data;
187                         return m_szText;
188                 }
189                 int GetTextLength () const
190                 {
191                         if (((INT_PTR)m_pszText >> 16) != 0)
192                                 return m_pszText->size;
193                         return 1;
194                 }
195         };
196
197 #pragma pack(pop)
198
199 protected:
200         /** 
201         We need another array with our richer structure.
202
203         We share the positions with the CCrystalTextBuffer object. 
204         We share m_bUndoGroup, its utility is to check we opened the UndoBeginGroup.
205         We share m_nUndoBufSize which is the max buffer size.
206         */
207         std::vector<SUndoRecord> m_aUndoBuf;
208         /** 
209         This one must be duplicated because the flag UNDO_BEGINGROUP needs to be set in both 
210         CGhostTextBuffer::m_aUndoBuf and CCrystalTextBuffer::m_aUndoBuf CArrays 
211         */
212         BOOL m_bUndoBeginGroup;
213
214         // [JRT] Support For Descriptions On Undo/Redo Actions
215         virtual void AddUndoRecord (BOOL bInsert, const CPoint & ptStartPos, const CPoint & ptEndPos,
216                               LPCTSTR pszText, int cchText, int nRealLinesChanged, int nActionType = CE_ACTION_UNKNOWN, CDWordArray *paSavedRevisonNumbers = NULL);
217
218 private:
219         /**
220          * @brief A struct mapping real lines and apparent (screen) lines.
221          * This struct maps lines between real lines and apparent (screen) lines.
222          * The mapping records for each text block an apparent line and matching
223          * real line.
224          */
225         struct RealityBlock
226         {
227                 int nStartReal; /**< Start line of real block. */
228                 int nStartApparent; /**< Start line of apparent block. */
229                 int nCount; /**< Lines in the block. */
230         };
231         std::vector<RealityBlock> m_RealityBlocks; /**< Mapping of real and apparent lines. */
232
233         // Operations
234 private:
235         BOOL InternalInsertGhostLine (CCrystalTextView * pSource, int nLine);
236         BOOL InternalDeleteGhostLine (CCrystalTextView * pSource, int nLine, int nCount);
237 public :
238         // Construction/destruction code
239         CGhostTextBuffer ();
240         virtual BOOL InitNew (CRLFSTYLE nCrlfStyle = CRLF_STYLE_DOS);
241
242         /** 
243         This should work in base code as ghost lines are real empty lines
244         but maybe it doesn't (if there is an assert to check there is an EOL,
245         or if it adds the default EOL)
246         */
247         virtual void GetTextWithoutEmptys (int nStartLine, int nStartChar,
248                         int nEndLine, int nEndChar, CString &text,
249                         CRLFSTYLE nCrlfStyle =CRLF_STYLE_AUTOMATIC);
250
251
252         // Text modification functions
253         virtual BOOL InsertText (CCrystalTextView * pSource, int nLine, int nPos,
254                 LPCTSTR pszText, int cchText, int &nEndLine, int &nEndChar,
255                 int nAction = CE_ACTION_UNKNOWN, BOOL bHistory = TRUE);
256         virtual BOOL DeleteText (CCrystalTextView * pSource, int nStartLine,
257                 int nStartPos, int nEndLine, int nEndPos,
258                 int nAction = CE_ACTION_UNKNOWN, BOOL bHistory = TRUE);
259         BOOL InsertGhostLine (CCrystalTextView * pSource, int nLine);
260
261         // Undo/Redo
262         virtual BOOL Undo (CCrystalTextView * pSource, CPoint & ptCursorPos);
263         virtual BOOL Redo (CCrystalTextView * pSource, CPoint & ptCursorPos);
264
265         // Undo grouping
266         virtual void BeginUndoGroup (BOOL bMergeWithPrevious = FALSE);
267         virtual void FlushUndoGroup (CCrystalTextView * pSource);
268
269 public:
270         //@{
271         /**
272          * @name Real/apparent line number conversion functions.
273          * These functions convert line numbers between file line numbers
274          * (real line numbers) and screen line numbers (apparent line numbers).
275          *
276          * This mapping is needed to handle ghost lines (ones with no text or
277          * EOL chars) which WinMerge uses for left-only or right-only lines.
278         */
279         int ApparentLastRealLine() const;
280         int ComputeRealLine(int nApparentLine) const;
281         int ComputeApparentLine(int nRealLine) const;
282         /** richer position information   yApparent = apparent(yReal) - yGhost */
283         int ComputeRealLineAndGhostAdjustment(int nApparentLine, int& decToReal) const;
284         /** richer position information   yApparent = apparent(yReal) - yGhost */
285         int ComputeApparentLine(int nRealLine, int decToReal) const;
286         //@}
287
288         /** for loading file */
289         void FinishLoading();
290         /** for saving file */ 
291         void RemoveAllGhostLines();
292
293
294 private:
295         void RecomputeRealityMapping();
296         /** 
297         Code to set EOL, if the status ghost/real of the line changes 
298
299         We should call a CCrystalTextBuffer function to add the correct EOL
300         (if CCrystalTextBuffer keeps the default EOL for the file)
301         */
302         void RecomputeEOL(CCrystalTextView * pSource, int nStartLine, int nEndLine);
303         /** For debugging purpose */
304         void checkFlagsFromReality(BOOL bFlag) const;
305
306 protected:
307         virtual void OnNotifyLineHasBeenEdited(int nLine);
308
309
310 protected:
311         // Overrides
312         // ClassWizard generated virtual function overrides
313         //{{AFX_VIRTUAL(CCrystalTextBuffer)
314         //}}AFX_VIRTUAL
315
316         // Generated message map functions
317         //{{AFX_MSG(CCrystalTextBuffer)
318         //}}AFX_MSG
319
320         DECLARE_MESSAGE_MAP ()
321 };
322
323 /////////////////////////////////////////////////////////////////////////////
324
325 //{{AFX_INSERT_LOCATION}}
326 // Microsoft Developer Studio will insert additional declarations immediately before the previous line.
327
328
329 #endif //__GHOSTTEXTBUFFER_H__