OSDN Git Service

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