OSDN Git Service

Merge from rev.7205
[winmerge-jp/winmerge-jp.git] / Src / GhostTextView.cpp
1 ////////////////////////////////////////////////////////////////////////////
2 //  File:       GhostTextView.h
3 //  Version:    1.0.0.0
4 //  Created:    31-Jul-2003
5 //
6 /////////////////////////////////////////////////////////////////////////////
7 //    WinMerge:  an interactive diff/merge utility
8 //    Copyright (C) 1997-2000  Thingamahoochie Software
9 //    Author: Dean Grimm
10 //
11 //    This program is free software; you can redistribute it and/or modify
12 //    it under the terms of the GNU General Public License as published by
13 //    the Free Software Foundation; either version 2 of the License, or
14 //    (at your option) any later version.
15 //
16 //    This program is distributed in the hope that it will be useful,
17 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
18 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 //    GNU General Public License for more details.
20 //
21 //    You should have received a copy of the GNU General Public License
22 //    along with this program; if not, write to the Free Software
23 //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 //
25 /////////////////////////////////////////////////////////////////////////////
26
27
28 #include "stdafx.h"
29 #include "GhostTextView.h"
30 #include "GhostTextBuffer.h"
31
32 #ifdef _DEBUG
33 #define new DEBUG_NEW
34 #undef THIS_FILE
35 static char THIS_FILE[] = __FILE__;
36 #endif
37
38
39 IMPLEMENT_DYNCREATE (CGhostTextView, CCrystalEditViewEx)
40
41 /** 
42  * @brief Constructor, initializes members.
43  */
44 CGhostTextView::CGhostTextView()
45 : m_pGhostTextBuffer(NULL)
46 {
47 }
48
49 void CGhostTextView::
50 ReAttachToBuffer (CCrystalTextBuffer * pBuf /*= NULL*/ )
51 {
52         if (pBuf == NULL)
53         {
54                 pBuf = LocateTextBuffer ();
55                 // ...
56         }
57         m_pGhostTextBuffer = dynamic_cast<CGhostTextBuffer*> (pBuf);
58         CCrystalEditViewEx::ReAttachToBuffer(pBuf);
59 }
60
61 void CGhostTextView::
62 AttachToBuffer (CCrystalTextBuffer * pBuf /*= NULL*/ )
63 {
64         if (pBuf == NULL)
65         {
66                 pBuf = LocateTextBuffer ();
67                 // ...
68         }
69         m_pGhostTextBuffer = dynamic_cast<CGhostTextBuffer*> (pBuf);
70         CCrystalEditViewEx::AttachToBuffer(pBuf);
71 }
72
73 void CGhostTextView::
74 DetachFromBuffer ()
75 {
76         if (m_pGhostTextBuffer != NULL)
77                 m_pGhostTextBuffer = NULL;
78         CCrystalEditViewEx::DetachFromBuffer();
79 }
80
81 void CGhostTextView::popPosition(SCursorPushed Ssrc, CPoint & pt)
82 {
83         pt.x = Ssrc.x;
84         pt.y = m_pGhostTextBuffer->ComputeApparentLine(Ssrc.y, Ssrc.nToFirstReal);
85         // if the cursor was in a trailing ghost line, and this disappeared,
86         // got at the end of the last line
87         if (pt.y >= GetLineCount())
88         {
89                 pt.y = GetLineCount()-1;
90                 pt.x = GetLineLength(pt.y);
91         }
92 }
93
94 void CGhostTextView::pushPosition(SCursorPushed & Sdest, CPoint pt)
95 {
96         Sdest.x = pt.x;
97         Sdest.y = m_pGhostTextBuffer->ComputeRealLineAndGhostAdjustment(pt.y, Sdest.nToFirstReal);
98 }
99
100 void CGhostTextView::PopCursors ()
101 {
102         CPoint ptCursorLast = m_ptCursorLast;
103         popPosition(m_ptCursorPosPushed, ptCursorLast);
104
105         ASSERT_VALIDTEXTPOS (ptCursorLast);
106         SetCursorPos (ptCursorLast);
107
108         popPosition(m_ptSelStartPushed, m_ptSelStart);
109         ASSERT_VALIDTEXTPOS (m_ptSelStart);
110         popPosition(m_ptSelEndPushed, m_ptSelEnd);
111         ASSERT_VALIDTEXTPOS (m_ptSelEnd);
112         popPosition(m_ptAnchorPushed, m_ptAnchor);
113         ASSERT_VALIDTEXTPOS (m_ptAnchor);
114         // laoran 2003/09/03
115         // here is what we did before, maybe we have to do it, but test with pushed positions
116         // SetSelection (ptCursorLast, ptCursorLast);
117         // SetAnchor (ptCursorLast);
118
119         if (m_bDraggingText == TRUE)
120         {
121                 popPosition(m_ptDraggedTextBeginPushed, m_ptDraggedTextBegin);
122                 ASSERT_VALIDTEXTPOS(m_ptDraggedTextBegin);
123                 popPosition(m_ptDraggedTextEndPushed, m_ptDraggedTextEnd);
124                 ASSERT_VALIDTEXTPOS(m_ptDraggedTextEnd);
125         }
126         if (m_bDropPosVisible == TRUE)
127         {
128                 popPosition(m_ptSavedCaretPosPushed, m_ptSavedCaretPos);
129                 ASSERT_VALIDTEXTPOS(m_ptSavedCaretPos);
130         }
131         if (m_bSelectionPushed == TRUE)
132         {
133                 popPosition(m_ptSavedSelStartPushed, m_ptSavedSelStart);
134                 ASSERT_VALIDTEXTPOS(m_ptSavedSelStart);
135                 popPosition(m_ptSavedSelEndPushed, m_ptSavedSelEnd);
136                 ASSERT_VALIDTEXTPOS(m_ptSavedSelEnd);
137         }
138
139         CPoint ptLastChange;
140         if (m_ptLastChangePushed.y == 0 && m_ptLastChangePushed.nToFirstReal > 0)
141                 ptLastChange = CPoint(-1,-1);
142         else 
143         {
144                 popPosition(m_ptLastChangePushed, ptLastChange);
145                 ASSERT_VALIDTEXTPOS(ptLastChange);
146         }
147         m_pGhostTextBuffer->RestoreLastChangePos(ptLastChange);
148
149         // restore the scrolling position
150         m_nTopSubLine = m_nTopSubLinePushed;
151         if (m_nTopSubLine >= GetSubLineCount())
152                 m_nTopSubLine = GetSubLineCount() - 1;
153         if (m_nTopSubLine < 0)
154                 m_nTopSubLine = 0;
155         int nDummy;
156         GetLineBySubLine( m_nTopSubLine, m_nTopLine, nDummy );
157     RecalcVertScrollBar(TRUE);
158 }
159
160 void CGhostTextView::PushCursors ()
161 {
162         pushPosition(m_ptCursorPosPushed, m_ptCursorPos);
163         pushPosition(m_ptSelStartPushed, m_ptSelStart);
164         pushPosition(m_ptSelEndPushed, m_ptSelEnd);
165         pushPosition(m_ptAnchorPushed, m_ptAnchor);
166         if (m_bDraggingText == TRUE)
167         {
168                 pushPosition(m_ptDraggedTextBeginPushed, m_ptDraggedTextBegin);
169                 pushPosition(m_ptDraggedTextEndPushed, m_ptDraggedTextEnd);
170         }
171         if (m_bDropPosVisible == TRUE)
172         {
173                 pushPosition(m_ptSavedCaretPosPushed, m_ptSavedCaretPos);
174         }
175         if (m_bSelectionPushed == TRUE)
176         {
177                 pushPosition(m_ptSavedSelStartPushed, m_ptSavedSelStart);
178                 pushPosition(m_ptSavedSelEndPushed, m_ptSavedSelEnd);
179         }
180
181         pushPosition(m_ptLastChangePushed, m_pGhostTextBuffer->GetLastChangePos());
182
183         // and top line positions
184         m_nTopSubLinePushed = m_nTopSubLine;
185 }
186
187
188
189
190 int CGhostTextView::ComputeRealLine (int nApparentLine) const
191 {
192         if (!m_pGhostTextBuffer)
193                 return 0;
194         return m_pGhostTextBuffer->ComputeRealLine(nApparentLine);
195 }
196
197 int CGhostTextView::ComputeApparentLine (int nRealLine) const
198 {
199         return m_pGhostTextBuffer->ComputeApparentLine(nRealLine);
200 }
201
202 void CGhostTextView::GetTextWithoutEmptys (int nStartLine, int nStartChar,
203                 int nEndLine, int nEndChar, CString &text,
204                 CRLFSTYLE nCrlfStyle /*=CRLF_STYLE_AUTOMATIC*/,
205                 BOOL bExcludeInvisibleLines/*=FALSE*/)
206 {
207   if (m_pGhostTextBuffer != NULL)
208     m_pGhostTextBuffer->GetTextWithoutEmptys (nStartLine, nStartChar, nEndLine, nEndChar, text, nCrlfStyle, bExcludeInvisibleLines);
209   else
210     text = _T ("");
211 }
212
213 void CGhostTextView::GetTextWithoutEmptysInColumnSelection (CString & text, BOOL bExcludeInvisibleLines/*=TRUE*/)
214 {
215         if (m_pGhostTextBuffer == NULL)
216         {
217                 text = _T ("");
218                 return;
219         }
220
221         PrepareSelBounds ();
222
223         CString sEol = m_pGhostTextBuffer->GetStringEol (CRLF_STYLE_DOS);
224
225         int nBufSize = 1;
226         for (int L = m_ptDrawSelStart.y; L <= m_ptDrawSelEnd.y; L++)
227                 nBufSize += GetLineLength (L) + sEol.GetLength ();
228         LPTSTR pszBuf = text.GetBuffer (nBufSize);
229
230         for (int I = m_ptDrawSelStart.y; I <= m_ptDrawSelEnd.y; I++)
231         {
232                 // exclude ghost lines
233                 if ((GetLineFlags(I) & LF_GHOST) || (bExcludeInvisibleLines && (GetLineFlags(I) & LF_INVISIBLE)))
234                         continue;
235
236                 int nSelLeft, nSelRight;
237                 GetColumnSelection (I, nSelLeft, nSelRight);
238                 memcpy (pszBuf, GetLineChars (I) + nSelLeft, sizeof (TCHAR) * (nSelRight - nSelLeft));
239                 pszBuf += (nSelRight - nSelLeft);
240                 memcpy (pszBuf, sEol, sizeof (TCHAR) * sEol.GetLength ());
241                 pszBuf += sEol.GetLength ();
242         }
243         pszBuf[0] = 0;
244         text.ReleaseBuffer ();
245         text.FreeExtra ();
246 }
247
248 HGLOBAL CGhostTextView::PrepareDragData ()
249 {
250         PrepareSelBounds ();
251         if (m_ptDrawSelStart == m_ptDrawSelEnd)
252                 return NULL;
253
254         CString text;
255         GetTextWithoutEmptys (m_ptDrawSelStart.y, m_ptDrawSelStart.x, m_ptDrawSelEnd.y, m_ptDrawSelEnd.x, text);
256         int cchText = text.GetLength();
257         SIZE_T cbData = (cchText + 1) * sizeof(TCHAR);
258         HGLOBAL hData =::GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, cbData);
259         if (hData == NULL)
260                 return NULL;
261         ::GlobalReAlloc(hData, cbData, 0);
262         ASSERT(::GlobalSize(hData) == cbData);
263
264         LPTSTR pszData = (LPTSTR)::GlobalLock (hData);
265         memcpy (pszData, text, cbData);
266         ::GlobalUnlock (hData);
267
268         m_ptDraggedTextBegin = m_ptDrawSelStart;
269         m_ptDraggedTextEnd = m_ptDrawSelEnd;
270         return hData;
271 }
272
273 /**
274  * @brief Draw selection margin. 
275  * @param [in] pdc         Pointer to draw context.
276  * @param [in] rect        The rectangle to draw.
277  * @param [in] nLineIndex  Index of line in view.
278  * @param [in] nLineNumber Line number to display. if -1, it's not displayed.
279  */
280 void CGhostTextView::DrawMargin (CDC * pdc, const CRect & rect, int nLineIndex, int nLineNumber)
281 {
282         int nRealLineNumber;
283         if (nLineIndex < 0 || GetLineFlags(nLineIndex) & LF_GHOST)
284                 nRealLineNumber = -1;
285         else
286                 nRealLineNumber = ComputeRealLine(nLineIndex) + 1;
287         CCrystalTextView::DrawMargin(pdc, rect, nLineIndex, nRealLineNumber);
288 }