1 ///////////////////////////////////////////////////////////////////////////
2 // File: ccrystaleditview.cpp
4 // Created: 29-Dec-1998
6 // Copyright: Stcherbatchenko Andrei
7 // E-mail: windfall@gmx.de
9 // Implementation of the CCrystalEditView class, a part of the Crystal Edit -
10 // syntax coloring text editor.
12 // You are free to use or modify this code to the following restrictions:
13 // - Acknowledge me somewhere in your about box, simple "Parts of code by.."
14 // will be enough. If you can't (or don't want to), contact me personally.
15 // - LEAVE THIS HEADER INTACT
16 ////////////////////////////////////////////////////////////////////////////
18 ////////////////////////////////////////////////////////////////////////////
20 // Paul Selormey, James R. Twine:
21 // + FEATURE: description for Undo/Redo actions
22 // + FEATURE: multiple MSVC-like bookmarks
23 // + FEATURE: 'Disable backspace at beginning of line' option
24 // + FEATURE: 'Disable drag-n-drop editing' option
26 // + FEATURE: Auto indent
27 // + FIX: ResetView() was overriden to provide cleanup
28 ////////////////////////////////////////////////////////////////////////////
30 ////////////////////////////////////////////////////////////////////////////
33 // + FEATURE: support for autoindenting brackets and parentheses
34 // + FEATURE: menu options, view and window
35 // + FEATURE: SDI+MDI versions with help
36 // + FEATURE: extended registry support for saving settings
37 // + FEATURE: some other things I've forgotten ...
39 // + FIX: treating groups in regular expressions corrected
40 // + FIX: autocomplete corrected
42 // ... it's being edited very rapidly so sorry for non-commented
43 // and maybe "ugly" code ...
44 ////////////////////////////////////////////////////////////////////////////
46 ////////////////////////////////////////////////////////////////////////////
48 // Sven Wiegand (search for "//BEGIN SW" to find my changes):
49 // + FEATURE: "Go to last change" (sets the cursor on the position where
50 // the user did his last edit actions
51 // + FEATURE: Support for incremental search in CCrystalTextView
52 ////////////////////////////////////////////////////////////////////////////
54 ////////////////////////////////////////////////////////////////////////////
57 // + FEATURE: Supporting [Return] to exit incremental-search-mode
59 ////////////////////////////////////////////////////////////////////////////
62 * @file ccrystaleditview.cpp
64 * @brief Implementation of the CCrystalEditView class
70 #include "ccrystaleditview.h"
71 #include "ccrystaltextbuffer.h"
72 #include "dialogs/ceditreplacedlg.h"
73 #include "dialogs/chcondlg.h"
74 #include "utils/registry.h"
75 #include "utils/cs2cs.h"
76 #include "utils/string_util.h"
77 #include "utils/icu.hpp"
80 #pragma message("Include <afxpriv.h> in your stdafx.h to avoid this message")
84 #pragma message("Include <afxole.h> in your stdafx.h to avoid this message")
92 static const unsigned int MAX_TAB_LEN = 64; // Same as in CrystalViewText.cpp
94 #define DRAG_BORDER_X 5
95 #define DRAG_BORDER_Y 5
97 /////////////////////////////////////////////////////////////////////////////
98 // CEditDropTargetImpl class declaration
100 class CEditDropTargetImpl : public COleDropTarget
103 CCrystalEditView * m_pOwner;
105 explicit CEditDropTargetImpl (CCrystalEditView * pOwner)
106 : m_pOwner(pOwner), m_pAlternateDropTarget(nullptr)
110 virtual DROPEFFECT OnDragEnter (CWnd * pWnd, COleDataObject * pDataObject, DWORD dwKeyState, CPoint point);
111 virtual void OnDragLeave (CWnd * pWnd);
112 virtual DROPEFFECT OnDragOver (CWnd * pWnd, COleDataObject * pDataObject, DWORD dwKeyState, CPoint point);
113 virtual BOOL OnDrop (CWnd * pWnd, COleDataObject * pDataObject, DROPEFFECT dropEffect, CPoint point);
114 virtual DROPEFFECT OnDragScroll (CWnd * pWnd, DWORD dwKeyState, CPoint point);
116 IDropTarget * m_pAlternateDropTarget;
120 /////////////////////////////////////////////////////////////////////////////
123 IMPLEMENT_DYNCREATE (CCrystalEditView, CCrystalTextView)
125 CCrystalEditView::CCrystalEditView ()
126 : m_nLastReplaceLen(0)
127 , m_mapExpand(new CMap<CString, LPCTSTR, CString, LPCTSTR> (10))
128 , m_bLastReplace(false)
129 , m_dwLastReplaceFlags(0)
130 , m_pEditReplaceDlg(nullptr)
131 , m_bDropPosVisible(false)
132 , m_bSelectionPushed(false)
133 , m_bAutoIndent(true)
134 , m_bDisableBSAtSOL(false)
135 , m_pDropTarget(nullptr)
136 , m_bMergeUndo(false)
140 CCrystalEditView:: ~CCrystalEditView ()
143 delete m_pEditReplaceDlg;
146 bool CCrystalEditView::
147 DoSetTextType (CrystalLineParser::TextDefinition *def)
149 m_CurSourceDef = def;
150 SetAutoIndent ((def->flags & SRCOPT_AUTOINDENT) != 0);
151 SetDisableBSAtSOL ((def->flags & SRCOPT_BSATBOL) == 0);
152 m_mapExpand->RemoveAll ();
154 CString sKey = AfxGetApp ()->m_pszRegistryKey;
155 sKey += _T("\\") EDITPAD_SECTION _T("\\");
157 sKey += _T ("\\Expand");
158 if (reg.Open (HKEY_CURRENT_USER, sKey, KEY_READ))
162 if (reg.FindFirstValue (pszValue, ®Val))
166 if (RegValGetString (®Val, sData))
167 m_mapExpand->SetAt (pszValue, sData);
168 while (reg.FindNextValue (pszValue, ®Val));
172 return CCrystalTextView::DoSetTextType (def);
175 BEGIN_MESSAGE_MAP (CCrystalEditView, CCrystalTextView)
176 //{{AFX_MSG_MAP(CCrystalEditView)
177 ON_COMMAND (ID_EDIT_PASTE, OnEditPaste)
178 ON_UPDATE_COMMAND_UI (ID_EDIT_CUT, OnUpdateEditCut)
179 ON_COMMAND (ID_EDIT_CUT, OnEditCut)
180 ON_UPDATE_COMMAND_UI (ID_EDIT_PASTE, OnUpdateEditPaste)
181 ON_COMMAND (ID_EDIT_DELETE, OnEditDelete)
183 ON_COMMAND (ID_EDIT_DELETE_BACK, OnEditDeleteBack)
184 ON_COMMAND (ID_EDIT_UNTAB, OnEditUntab)
185 ON_COMMAND (ID_EDIT_TAB, OnEditTab)
186 ON_COMMAND (ID_EDIT_SWITCH_OVRMODE, OnEditSwitchOvrmode)
187 ON_UPDATE_COMMAND_UI (ID_EDIT_SWITCH_OVRMODE, OnUpdateEditSwitchOvrmode)
190 ON_COMMAND (ID_EDIT_REPLACE, OnEditReplace)
191 ON_UPDATE_COMMAND_UI (ID_EDIT_UNDO, OnUpdateEditUndo)
192 ON_COMMAND (ID_EDIT_UNDO, OnEditUndo)
193 ON_UPDATE_COMMAND_UI (ID_EDIT_REDO, OnUpdateEditRedo)
194 ON_COMMAND (ID_EDIT_REDO, OnEditRedo)
195 ON_UPDATE_COMMAND_UI (ID_EDIT_AUTOCOMPLETE, OnUpdateEditAutoComplete)
196 ON_COMMAND (ID_EDIT_AUTOCOMPLETE, OnEditAutoComplete)
197 ON_UPDATE_COMMAND_UI (ID_EDIT_AUTOEXPAND, OnUpdateEditAutoExpand)
198 ON_COMMAND (ID_EDIT_AUTOEXPAND, OnEditAutoExpand)
199 ON_UPDATE_COMMAND_UI (ID_EDIT_LOWERCASE, OnUpdateEditLowerCase)
200 ON_COMMAND (ID_EDIT_LOWERCASE, OnEditLowerCase)
201 ON_UPDATE_COMMAND_UI (ID_EDIT_UPPERCASE, OnUpdateEditUpperCase)
202 ON_COMMAND (ID_EDIT_UPPERCASE, OnEditUpperCase)
203 ON_UPDATE_COMMAND_UI (ID_EDIT_SWAPCASE, OnUpdateEditSwapCase)
204 ON_COMMAND (ID_EDIT_SWAPCASE, OnEditSwapCase)
205 ON_UPDATE_COMMAND_UI (ID_EDIT_SWAPCASE, OnUpdateEditSwapCase)
206 ON_COMMAND (ID_EDIT_SWAPCASE, OnEditSwapCase)
207 ON_UPDATE_COMMAND_UI (ID_EDIT_CAPITALIZE, OnUpdateEditCapitalize)
208 ON_COMMAND (ID_EDIT_CAPITALIZE, OnEditCapitalize)
209 ON_UPDATE_COMMAND_UI (ID_EDIT_SENTENCE, OnUpdateEditSentence)
210 ON_COMMAND (ID_EDIT_SENTENCE, OnEditSentence)
211 ON_UPDATE_COMMAND_UI(ID_EDIT_GOTO_LAST_CHANGE, OnUpdateEditGotoLastChange)
212 ON_COMMAND(ID_EDIT_GOTO_LAST_CHANGE, OnEditGotoLastChange)
213 ON_COMMAND(ID_EDIT_DELETE_WORD, OnEditDeleteWord)
214 ON_COMMAND(ID_EDIT_DELETE_WORD_BACK, OnEditDeleteWordBack)
217 ON_UPDATE_COMMAND_UI (ID_EDIT_INDICATOR_READ, OnUpdateIndicatorRead)
218 ON_UPDATE_COMMAND_UI (ID_INDICATOR_OVR, OnUpdateIndicatorOvr)
219 ON_UPDATE_COMMAND_UI (ID_EDIT_INDICATOR_POSITION, OnUpdateIndicatorPosition)
220 ON_UPDATE_COMMAND_UI (ID_TOOLS_SPELLING, OnUpdateToolsSpelling)
221 ON_COMMAND (ID_TOOLS_SPELLING, OnToolsSpelling)
222 ON_UPDATE_COMMAND_UI (ID_TOOLS_CHARCODING, OnUpdateToolsCharCoding)
223 ON_COMMAND (ID_TOOLS_CHARCODING, OnToolsCharCoding)
224 // cursor movement commands
225 ON_COMMAND (ID_EDIT_CHAR_LEFT, OnCharLeft)
226 ON_COMMAND (ID_EDIT_EXT_CHAR_LEFT, OnExtCharLeft)
227 ON_COMMAND (ID_EDIT_CHAR_RIGHT, OnCharRight)
228 ON_COMMAND (ID_EDIT_EXT_CHAR_RIGHT, OnExtCharRight)
229 ON_COMMAND (ID_EDIT_WORD_LEFT, OnWordLeft)
230 ON_COMMAND (ID_EDIT_EXT_WORD_LEFT, OnExtWordLeft)
231 ON_COMMAND (ID_EDIT_WORD_RIGHT, OnWordRight)
232 ON_COMMAND (ID_EDIT_EXT_WORD_RIGHT, OnExtWordRight)
233 ON_COMMAND (ID_EDIT_LINE_UP, OnLineUp)
234 ON_COMMAND (ID_EDIT_EXT_LINE_UP, OnExtLineUp)
235 ON_COMMAND (ID_EDIT_LINE_DOWN, OnLineDown)
236 ON_COMMAND (ID_EDIT_EXT_LINE_DOWN, OnExtLineDown)
237 ON_COMMAND (ID_EDIT_SCROLL_UP, ScrollUp)
238 ON_COMMAND (ID_EDIT_SCROLL_DOWN, ScrollDown)
239 ON_COMMAND (ID_EDIT_PAGE_UP, OnPageUp)
240 ON_COMMAND (ID_EDIT_EXT_PAGE_UP, OnExtPageUp)
241 ON_COMMAND (ID_EDIT_PAGE_DOWN, OnPageDown)
242 ON_COMMAND (ID_EDIT_EXT_PAGE_DOWN, OnExtPageDown)
243 ON_COMMAND (ID_EDIT_LINE_END, OnLineEnd)
244 ON_COMMAND (ID_EDIT_EXT_LINE_END, OnExtLineEnd)
245 ON_COMMAND (ID_EDIT_HOME, OnHome)
246 ON_COMMAND (ID_EDIT_EXT_HOME, OnExtHome)
247 ON_COMMAND (ID_EDIT_TEXT_BEGIN, OnTextBegin)
248 ON_COMMAND (ID_EDIT_EXT_TEXT_BEGIN, OnExtTextBegin)
249 ON_COMMAND (ID_EDIT_TEXT_END, OnTextEnd)
250 ON_COMMAND (ID_EDIT_EXT_TEXT_END, OnExtTextEnd)
256 /////////////////////////////////////////////////////////////////////////////
257 // CCrystalEditView message handlers
259 void CCrystalEditView::ResetView ()
261 // m_bAutoIndent = true;
263 m_bLastReplace = false;
264 CCrystalTextView::ResetView ();
267 bool CCrystalEditView::
270 if (m_pTextBuffer == nullptr)
272 return !m_pTextBuffer->GetReadOnly ();
275 void CCrystalEditView::
281 void CCrystalEditView::
282 OnUpdateEditPaste (CCmdUI * pCmdUI)
284 pCmdUI->Enable (TextInClipboard ());
287 void CCrystalEditView::
288 OnUpdateEditCut (CCmdUI * pCmdUI)
290 pCmdUI->Enable (IsSelection ());
293 void CCrystalEditView::
299 bool CCrystalEditView::
300 DeleteCurrentSelection ()
304 auto [ptSelStart, ptSelEnd] = GetSelection ();
306 CPoint ptCursorPos = ptSelStart;
307 ASSERT_VALIDTEXTPOS (ptCursorPos);
308 SetAnchor (ptCursorPos);
309 SetSelection (ptCursorPos, ptCursorPos);
310 SetCursorPos (ptCursorPos);
311 EnsureVisible (ptCursorPos);
314 m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_DELSEL);
320 bool CCrystalEditView::
321 DeleteCurrentColumnSelection (int nAction, bool bFlushUndoGroup /*= true*/, bool bUpdateCursorPosition /*= true*/)
326 m_pTextBuffer->BeginUndoGroup ();
328 auto [ptSelStart, ptSelEnd] = GetSelection ();
330 int nSelLeft, nSelRight;
331 GetColumnSelection (m_ptDrawSelStart.y, nSelLeft, nSelRight);
332 CPoint ptCursorPos(nSelLeft, m_ptDrawSelStart.y);
333 int nStartLine = m_ptDrawSelStart.y;
334 int nEndLine = m_ptDrawSelEnd.y;
336 if (GetEnableHideLines ())
338 for (int nLineIndex = nEndLine; nLineIndex >= nStartLine; nLineIndex--)
340 if (!(GetLineFlags (nLineIndex) & LF_INVISIBLE))
342 int nEndLine2 = nLineIndex;
344 for (nStartLine2 = nLineIndex - 1; nStartLine2 >= nStartLine; nStartLine2--)
346 if (GetLineFlags (nStartLine2) & LF_INVISIBLE)
350 nLineIndex = nStartLine2;
351 DeleteCurrentColumnSelection2 (nStartLine2, nEndLine2, nAction);
357 DeleteCurrentColumnSelection2 (ptSelStart.y, ptSelEnd.y, nAction);
361 m_pTextBuffer->FlushUndoGroup (this);
363 if (bUpdateCursorPosition)
365 ASSERT_VALIDTEXTPOS (ptCursorPos);
366 SetAnchor (ptCursorPos);
367 SetSelection (ptCursorPos, ptCursorPos);
368 SetCursorPos (ptCursorPos);
369 EnsureVisible (ptCursorPos);
376 bool CCrystalEditView::
377 DeleteCurrentColumnSelection2 (int nStartLine, int nEndLine, int nAction)
380 for (int L = nStartLine; L <= nEndLine; L++)
381 nBufSize += GetFullLineLength (L);
384 LPTSTR p, pszBuf = text.GetBuffer (nBufSize);
387 for (int I = nStartLine; I <= nEndLine; I++)
389 LPCTSTR pszChars = GetLineChars (I);
390 int nSelLeft, nSelRight;
391 GetColumnSelection (I, nSelLeft, nSelRight);
394 memcpy (p, pszChars, sizeof (TCHAR) * nSelLeft);
397 int nLineLength = GetFullLineLength (I);
398 if (nSelRight < nLineLength)
400 memcpy (p, pszChars + nSelRight, sizeof (TCHAR) * (nLineLength - nSelRight));
401 p += nLineLength - nSelRight;
406 text.ReleaseBuffer (static_cast<int>(p - pszBuf));
409 if (nEndLine + 1 < GetLineCount())
410 m_pTextBuffer->DeleteText (this, nStartLine, 0, nEndLine + 1, 0, nAction);
412 m_pTextBuffer->DeleteText (this, nStartLine, 0, nEndLine, GetLineLength (nEndLine), nAction);
414 m_pTextBuffer->InsertText (this, nStartLine, 0, text, text.GetLength(), y, x, nAction);
419 bool CCrystalEditView::
420 InsertColumnText (int nLine, int nPos, LPCTSTR pszText, int cchText, int nAction, bool bFlushUndoGroup)
422 if (pszText == nullptr || cchText == 0)
425 CTypedPtrArray<CPtrArray, LPTSTR> aLines;
426 CDWordArray aLineLengths;
428 for (int nTextPos = 0; nTextPos < cchText; )
431 aLines.Add ((LPTSTR)&pszText[nTextPos]);
433 for (; nTextPos < cchText; nTextPos++)
435 ch = pszText[nTextPos];
436 if (ch=='\r' || ch=='\n'/*iseol(pszText[nTextPos]*/)
440 aLineLengths.Add (nTextPos - nLineBegin);
442 // advance after EOL of line
443 if (ch=='\r' && pszText[nTextPos + 1]=='\n'/*isdoseol(&pszText[nTextPos])*/)
445 else if (ch=='\r' || ch=='\n'/*iseol(pszText[nTextPos])*/)
447 nLineBegin = nTextPos;
452 int nLineCount = GetLineCount ();
453 ASSERT(aLineLengths.GetSize() < INT_MAX);
454 int nPasteTextLineCount = static_cast<int>(aLineLengths.GetSize ());
455 for (L = 0; L < nPasteTextLineCount; L++)
457 if (nLine + L < nLineCount)
458 nBufSize += GetFullLineLength (nLine + L) + aLineLengths[L] + 2;
460 nBufSize += aLineLengths[L] + 2;
463 LPTSTR pszBuf = new TCHAR[nBufSize];
465 int nTopBeginCharPos = CalculateActualOffset (nLine, nPos, true);
466 for (L = 0; L < nPasteTextLineCount; L++)
468 if (nLine + L < nLineCount)
470 int nLineLength = GetFullLineLength (nLine + L);
471 LPCTSTR pszChars = GetLineChars (nLine + L);
472 int nOffset = ApproxActualOffset (nLine + L, nTopBeginCharPos);
473 memcpy(p, pszChars, nOffset * sizeof(TCHAR));
475 memcpy(p, aLines[L], aLineLengths[L] * sizeof(TCHAR));
476 p += aLineLengths[L];
477 memcpy(p, pszChars + nOffset, (nLineLength - nOffset) * sizeof(TCHAR));
478 p += nLineLength - nOffset;
482 CString sEol = m_pTextBuffer->GetDefaultEol ();
483 if (p > pszBuf && p[-1] != '\r' && p[-1] != '\n')
485 memcpy(p, sEol, sEol.GetLength () * sizeof(TCHAR));
486 p += sEol.GetLength ();
488 memcpy(p, aLines[L], aLineLengths[L] * sizeof(TCHAR));
489 p += aLineLengths[L];
490 memcpy(p, sEol, sEol.GetLength () * sizeof(TCHAR));
491 p += sEol.GetLength ();
497 m_pTextBuffer->BeginUndoGroup ();
499 if (nLine + nPasteTextLineCount + 1 < nLineCount)
500 m_pTextBuffer->DeleteText (this, nLine, 0, nLine + nPasteTextLineCount, 0, nAction);
501 else if (nLine != nLineCount - 1 || GetLineLength (nLineCount - 1) != 0)
502 m_pTextBuffer->DeleteText (this, nLine, 0, nLineCount - 1, GetLineLength (nLineCount - 1), nAction);
504 m_pTextBuffer->InsertText (this, nLine, 0, pszBuf, static_cast<int>(p - pszBuf), x, y, nAction);
507 m_pTextBuffer->FlushUndoGroup (this);
514 void CCrystalEditView::
517 if (!QueryEditable ())
519 if (m_pTextBuffer == nullptr)
523 bool bColumnSelection;
524 if (GetFromClipboard (text, bColumnSelection))
526 m_pTextBuffer->BeginUndoGroup ();
531 auto [ptSelStart, ptSelEnd] = GetSelection ();
533 ptCursorPos = ptSelStart;
534 /*SetAnchor (ptCursorPos);
535 SetSelection (ptCursorPos, ptCursorPos);
536 SetCursorPos (ptCursorPos);
537 EnsureVisible (ptCursorPos);*/
540 if (!m_bRectangularSelection)
541 m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_PASTE);
543 DeleteCurrentColumnSelection (CE_ACTION_PASTE, false, false);
547 ptCursorPos = GetCursorPos ();
549 ASSERT_VALIDTEXTPOS (ptCursorPos);
551 if (!bColumnSelection)
554 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, text, text.GetLength(), y, x, CE_ACTION_PASTE); // [JRT]
559 InsertColumnText (ptCursorPos.y, ptCursorPos.x, text, text.GetLength(), CE_ACTION_PASTE, false);
561 ASSERT_VALIDTEXTPOS (ptCursorPos);
562 SetAnchor (ptCursorPos);
563 SetSelection (ptCursorPos, ptCursorPos);
564 SetCursorPos (ptCursorPos);
565 EnsureVisible (ptCursorPos);
567 m_pTextBuffer->FlushUndoGroup (this);
571 void CCrystalEditView::
574 if (!QueryEditable ())
576 if (m_pTextBuffer == nullptr)
581 auto [ptSelStart, ptSelEnd] = GetSelection ();
583 if (!m_bRectangularSelection)
584 GetText (ptSelStart, ptSelEnd, text);
586 GetTextInColumnSelection (text);
587 PutToClipboard (text, text.GetLength());
589 if (!m_bRectangularSelection)
591 CPoint ptCursorPos = ptSelStart;
592 ASSERT_VALIDTEXTPOS (ptCursorPos);
593 SetAnchor (ptCursorPos);
594 SetSelection (ptCursorPos, ptCursorPos);
595 SetCursorPos (ptCursorPos);
596 EnsureVisible (ptCursorPos);
598 m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_CUT); // [JRT]
601 DeleteCurrentColumnSelection (CE_ACTION_CUT);
604 void CCrystalEditView::
607 if (!QueryEditable () || m_pTextBuffer == nullptr)
610 auto [ptSelStart, ptSelEnd] = GetSelection ();
611 if (ptSelStart == ptSelEnd)
613 if (ptSelEnd.x == GetLineLength (ptSelEnd.y))
615 if (ptSelEnd.y == GetLineCount () - 1)
622 auto pIterChar = ICUBreakIterator::getCharacterBreakIterator(GetLineChars(ptSelEnd.y), GetLineLength(ptSelEnd.y));
623 ptSelEnd.x = pIterChar->following(ptSelEnd.x);
627 if (!m_bRectangularSelection)
629 CPoint ptCursorPos = ptSelStart;
630 ASSERT_VALIDTEXTPOS (ptCursorPos);
631 SetAnchor (ptCursorPos);
632 SetSelection (ptCursorPos, ptCursorPos);
633 SetCursorPos (ptCursorPos);
634 EnsureVisible (ptCursorPos);
636 m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_DELETE); // [JRT]
639 DeleteCurrentColumnSelection (CE_ACTION_DELETE);
642 void CCrystalEditView::
643 OnChar (UINT nChar, UINT nRepCnt, UINT nFlags)
646 // check if incremental search is active before call to CCrystalTextView::OnChar()
647 bool bIncrementalSearch = m_bIncrementalSearchForward || m_bIncrementalSearchBackward;
649 CCrystalTextView::OnChar (static_cast<wchar_t>(nChar), nRepCnt, nFlags);
651 // if we are in incremental search mode ignore the character
652 if( m_bIncrementalSearchForward || m_bIncrementalSearchBackward )
656 // if we *were* in incremental search mode and CCrystalTextView::OnChar()
657 // exited it the ignore the character (VK_RETURN)
658 if( bIncrementalSearch && !m_bIncrementalSearchForward && !m_bIncrementalSearchBackward )
662 if ((::GetAsyncKeyState (VK_LBUTTON) & 0x8000) != 0 ||
663 (::GetAsyncKeyState (VK_RBUTTON) & 0x8000) != 0)
666 if (nChar == VK_RETURN)
670 CPoint ptCursorPos = GetCursorPos ();
671 ASSERT_VALIDTEXTPOS (ptCursorPos);
672 if (ptCursorPos.y < GetLineCount () - 1)
677 ASSERT_VALIDTEXTPOS (ptCursorPos);
678 SetSelection (ptCursorPos, ptCursorPos);
679 SetAnchor (ptCursorPos);
680 SetCursorPos (ptCursorPos);
681 EnsureVisible (ptCursorPos);
686 m_pTextBuffer->BeginUndoGroup(m_bMergeUndo);
687 m_bMergeUndo = false;
689 if (QueryEditable () && m_pTextBuffer != nullptr)
694 auto [ptSelStart, ptSelEnd] = GetSelection ();
696 ptCursorPos = ptSelStart;
697 /*SetAnchor (ptCursorPos);
698 SetSelection (ptCursorPos, ptCursorPos);
699 SetCursorPos (ptCursorPos);
700 EnsureVisible (ptCursorPos);*/
703 m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_TYPING);
706 ptCursorPos = GetCursorPos ();
707 ASSERT_VALIDTEXTPOS (ptCursorPos);
708 LPCTSTR pszText = m_pTextBuffer->GetDefaultEol();
709 int cchText = (int) _tcslen(pszText);
712 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszText, cchText, y, x, CE_ACTION_TYPING); // [JRT]
716 ASSERT_VALIDTEXTPOS (ptCursorPos);
717 SetSelection (ptCursorPos, ptCursorPos);
718 SetAnchor (ptCursorPos);
719 SetCursorPos (ptCursorPos);
720 EnsureVisible (ptCursorPos);
723 m_pTextBuffer->FlushUndoGroup (this);
726 // Accept control characters other than [\t\n\r] through Alt-Numpad
728 || GetKeyState(VK_CONTROL) >= 0 &&
729 (nChar != 27 || GetKeyState(VK_ESCAPE) >= 0) &&
730 nChar != 9 && nChar != 10 && nChar != 13)
732 if (QueryEditable () && m_pTextBuffer != nullptr)
734 m_pTextBuffer->BeginUndoGroup (m_bMergeUndo);
737 auto [ptSelStart, ptSelEnd] = GetSelection ();
739 if (ptSelStart != ptSelEnd)
741 ptCursorPos = ptSelStart;
744 auto [ptSelStart1, ptSelEnd1] = GetSelection ();
746 /*SetAnchor (ptCursorPos);
747 SetSelection (ptCursorPos, ptCursorPos);
748 SetCursorPos (ptCursorPos);
749 EnsureVisible (ptCursorPos);*/
752 m_pTextBuffer->DeleteText (this, ptSelStart1.y, ptSelStart1.x, ptSelEnd1.y, ptSelEnd1.x, CE_ACTION_TYPING);
757 ptCursorPos = GetCursorPos ();
758 if (m_bOvrMode && ptCursorPos.x < GetLineLength (ptCursorPos.y))
759 m_pTextBuffer->DeleteText (this, ptCursorPos.y, ptCursorPos.x, ptCursorPos.y, ptCursorPos.x + 1, CE_ACTION_TYPING); // [JRT]
763 ASSERT_VALIDTEXTPOS (ptCursorPos);
766 pszText[0] = (TCHAR) nChar;
770 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszText, 1, y, x, CE_ACTION_TYPING); // [JRT]
774 ASSERT_VALIDTEXTPOS (ptCursorPos);
775 SetSelection (ptCursorPos, ptCursorPos);
776 SetAnchor (ptCursorPos);
777 SetCursorPos (ptCursorPos);
778 EnsureVisible (ptCursorPos);
780 m_pTextBuffer->FlushUndoGroup (this);
787 // [JRT]: Added Support For "Disable Backspace At Start Of Line"
789 void CCrystalEditView::
793 // if we are in incremental search mode ignore backspace
794 CCrystalTextView::OnEditDeleteBack();
795 if( m_bIncrementalSearchForward || m_bIncrementalSearchBackward )
805 if (!QueryEditable () || m_pTextBuffer == nullptr)
808 CPoint ptCursorPos = GetCursorPos ();
809 CPoint ptCurrentCursorPos = ptCursorPos;
810 bool bDeleted = false;
812 if (!(ptCursorPos.x)) // If At Start Of Line
815 if (!m_bDisableBSAtSOL) // If DBSASOL Is Disabled
818 if (ptCursorPos.y > 0) // If Previous Lines Available
821 ptCursorPos.y--; // Decrement To Previous Line
823 ptCursorPos.x = GetLineLength (
824 ptCursorPos.y); // Set Cursor To End Of Previous Line
826 bDeleted = true; // Set Deleted Flag
831 else // If Caret Not At SOL
834 auto pIterChar = ICUBreakIterator::getCharacterBreakIterator(GetLineChars(ptCursorPos.y), GetLineLength(ptCursorPos.y));
835 ptCursorPos.x = pIterChar->preceding(ptCursorPos.x);
836 bDeleted = true; // Set Deleted Flag
839 if (ptCursorPos.x == 0)
841 if (ptCursorPos.y == 0)
844 ptCursorPos.x = GetLineLength(ptCursorPos.y);
849 ASSERT_VALIDTEXTPOS (ptCursorPos);
850 SetAnchor (ptCursorPos);
851 SetSelection (ptCursorPos, ptCursorPos);
852 SetCursorPos (ptCursorPos);
853 EnsureVisible (ptCursorPos);
857 m_pTextBuffer->DeleteText (this, ptCursorPos.y, ptCursorPos.x, ptCurrentCursorPos.y, ptCurrentCursorPos.x, CE_ACTION_BACKSPACE); // [JRT]
863 void CCrystalEditView::
866 if (!QueryEditable () || m_pTextBuffer == nullptr)
869 bool bTabify = false;
870 CPoint ptSelStart, ptSelEnd;
873 GetSelection (ptSelStart, ptSelEnd);
875 // If we have more than one line selected, tabify sel lines
876 if ( ptSelStart.y != ptSelEnd.y )
882 CPoint ptCursorPos = GetCursorPos ();
883 ASSERT_VALIDTEXTPOS (ptCursorPos);
885 TCHAR pszText[MAX_TAB_LEN + 1] = {0};
886 // If inserting tabs, then initialize the text to a tab.
887 if (m_pTextBuffer->GetInsertTabs())
892 else //...otherwise, built whitespace depending on the location and tab stops
894 int nTabSize = GetTabSize ();
895 int nChars = nTabSize - ptCursorPos.x % nTabSize;
896 for (int i = 0; i < nChars; i++)
898 pszText[nChars] = '\0';
901 // Indent selected lines (multiple lines selected)
904 m_pTextBuffer->BeginUndoGroup ();
906 int nStartLine = ptSelStart.y;
907 int nEndLine = ptSelEnd.y;
911 if (ptSelEnd.y == GetLineCount () - 1)
913 ptSelEnd.x = GetLineLength (ptSelEnd.y);
921 else //...otherwise, do not indent the empty line.
923 SetSelection (ptSelStart, ptSelEnd);
924 SetCursorPos (ptSelEnd);
925 EnsureVisible (ptSelEnd);
927 // Shift selection to right
928 m_bHorzScrollBarLocked = true;
929 for (int L = nStartLine; L <= nEndLine; L++)
932 if (m_pTextBuffer->IsIndentableLine (L))
933 m_pTextBuffer->InsertText (this, L, 0, pszText, (int) _tcslen(pszText), y, x, CE_ACTION_INDENT); // [JRT]
935 m_bHorzScrollBarLocked = false;
936 RecalcHorzScrollBar ();
938 m_pTextBuffer->FlushUndoGroup (this);
942 // Overwrite mode, replace next char with tab/spaces
945 CPoint ptCursorPos1 = GetCursorPos ();
946 ASSERT_VALIDTEXTPOS (ptCursorPos1);
948 int nLineLength = GetLineLength (ptCursorPos1.y);
949 LPCTSTR pszLineChars = GetLineChars (ptCursorPos1.y);
952 if (ptCursorPos1.x < nLineLength)
954 int nTabSize = GetTabSize ();
955 int nChars = nTabSize - CalculateActualOffset(
956 ptCursorPos1.y, ptCursorPos1.x ) % nTabSize;
957 ASSERT (nChars > 0 && nChars <= nTabSize);
961 if (ptCursorPos1.x == nLineLength)
963 if (pszLineChars[ptCursorPos1.x] == _T ('\t'))
971 ASSERT (ptCursorPos1.x <= nLineLength);
972 ASSERT_VALIDTEXTPOS (ptCursorPos1);
974 SetSelection (ptCursorPos1, ptCursorPos1);
975 SetAnchor (ptCursorPos1);
976 SetCursorPos (ptCursorPos1);
977 EnsureVisible (ptCursorPos1);
982 m_pTextBuffer->BeginUndoGroup ();
984 int x, y; // For cursor position
986 // Text selected, no overwrite mode, replace sel with tab
989 auto [ptSelStart1, ptSelEnd1] = GetSelection ();
991 /*SetAnchor (ptCursorPos);
992 SetSelection (ptCursorPos, ptCursorPos);
993 SetCursorPos (ptCursorPos);
994 EnsureVisible (ptCursorPos);*/
997 m_pTextBuffer->DeleteText (this, ptSelStart1.y, ptSelStart1.x, ptSelEnd1.y, ptSelEnd1.x, CE_ACTION_TYPING);
998 m_pTextBuffer->InsertText( this, ptSelStart1.y, ptSelStart1.x, pszText, (int) _tcslen(pszText), y, x, CE_ACTION_TYPING );
1000 // No selection, add tab
1003 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszText, (int) _tcslen(pszText), y, x, CE_ACTION_TYPING); // [JRT]
1008 ASSERT_VALIDTEXTPOS (ptCursorPos);
1009 SetSelection (ptCursorPos, ptCursorPos);
1010 SetAnchor (ptCursorPos);
1011 SetCursorPos (ptCursorPos);
1012 EnsureVisible (ptCursorPos);
1014 m_pTextBuffer->FlushUndoGroup (this);
1017 void CCrystalEditView::
1020 if (!QueryEditable () || m_pTextBuffer == nullptr)
1023 bool bTabify = false;
1026 auto [ptSelStart, ptSelEnd] = GetSelection ();
1027 bTabify = ptSelStart.y != ptSelEnd.y;
1032 m_pTextBuffer->BeginUndoGroup ();
1034 auto [ptSelStart, ptSelEnd] = GetSelection ();
1035 int nStartLine = ptSelStart.y;
1036 int nEndLine = ptSelEnd.y;
1040 if (ptSelEnd.y == GetLineCount () - 1)
1042 ptSelEnd.x = GetLineLength (ptSelEnd.y);
1052 SetSelection (ptSelStart, ptSelEnd);
1053 SetCursorPos (ptSelEnd);
1054 EnsureVisible (ptSelEnd);
1056 // Shift selection to left
1057 m_bHorzScrollBarLocked = true;
1058 for (int L = nStartLine; L <= nEndLine; L++)
1060 int nLength = GetLineLength (L);
1063 LPCTSTR pszChars = GetLineChars (L);
1064 int nPos = 0, nOffset = 0;
1065 while (nPos < nLength)
1067 if (pszChars[nPos] == _T (' '))
1070 if (++nOffset >= GetTabSize ())
1075 if (pszChars[nPos] == _T ('\t'))
1082 m_pTextBuffer->DeleteText (this, L, 0, L, nPos, CE_ACTION_INDENT); // [JRT]
1086 m_bHorzScrollBarLocked = false;
1087 RecalcHorzScrollBar ();
1089 m_pTextBuffer->FlushUndoGroup (this);
1093 CPoint ptCursorPos = GetCursorPos ();
1094 ASSERT_VALIDTEXTPOS (ptCursorPos);
1095 if (ptCursorPos.x > 0)
1097 int nTabSize = GetTabSize ();
1098 int nOffset = CalculateActualOffset (ptCursorPos.y, ptCursorPos.x);
1099 int nNewOffset = nOffset / nTabSize * nTabSize;
1100 if (nOffset == nNewOffset && nNewOffset > 0)
1101 nNewOffset -= nTabSize;
1102 ASSERT (nNewOffset >= 0);
1104 LPCTSTR pszChars = GetLineChars (ptCursorPos.y);
1105 int nCurrentOffset = 0;
1107 while (nCurrentOffset < nNewOffset)
1109 if (pszChars[I] == _T ('\t'))
1110 nCurrentOffset = nCurrentOffset / nTabSize * nTabSize + nTabSize;
1116 ASSERT (nCurrentOffset == nNewOffset);
1119 ASSERT_VALIDTEXTPOS (ptCursorPos);
1120 SetSelection (ptCursorPos, ptCursorPos);
1121 SetAnchor (ptCursorPos);
1122 SetCursorPos (ptCursorPos);
1123 EnsureVisible (ptCursorPos);
1128 void CCrystalEditView::
1129 OnUpdateIndicatorCol (CCmdUI * pCmdUI)
1131 pCmdUI->Enable (false);
1134 void CCrystalEditView::
1135 OnUpdateIndicatorOvr (CCmdUI * pCmdUI)
1137 pCmdUI->Enable (m_bOvrMode);
1140 void CCrystalEditView::
1141 OnUpdateIndicatorRead (CCmdUI * pCmdUI)
1143 if (m_pTextBuffer == nullptr)
1144 pCmdUI->Enable (false);
1146 pCmdUI->Enable (m_pTextBuffer->GetReadOnly ());
1149 void CCrystalEditView::
1150 OnEditSwitchOvrmode ()
1152 m_bOvrMode = !m_bOvrMode;
1156 void CCrystalEditView::
1157 OnUpdateEditSwitchOvrmode (CCmdUI * pCmdUI)
1159 pCmdUI->SetCheck (m_bOvrMode ? 1 : 0);
1162 DROPEFFECT CEditDropTargetImpl::
1163 OnDragEnter (CWnd * pWnd, COleDataObject * pDataObject, DWORD dwKeyState, CPoint point)
1165 CLIPFORMAT fmt = CCrystalTextView::GetClipTcharTextFormat();
1166 if (!pDataObject->IsDataAvailable (fmt))
1168 if (m_pAlternateDropTarget != nullptr)
1170 DROPEFFECT dwEffect = DROPEFFECT_NONE;
1171 m_pAlternateDropTarget->DragEnter(pDataObject->m_lpDataObject, dwKeyState, { point.x, point.y }, &dwEffect);
1174 m_pOwner->HideDropIndicator ();
1175 return DROPEFFECT_NONE;
1177 m_pOwner->ShowDropIndicator (point);
1178 if (dwKeyState & MK_CONTROL)
1179 return DROPEFFECT_COPY;
1180 return DROPEFFECT_MOVE;
1183 void CEditDropTargetImpl::
1184 OnDragLeave (CWnd * pWnd)
1186 m_pOwner->HideDropIndicator ();
1189 DROPEFFECT CEditDropTargetImpl::
1190 OnDragOver (CWnd * pWnd, COleDataObject * pDataObject, DWORD dwKeyState, CPoint point)
1195 bool bDataSupported = false;
1197 if ((m_pOwner == nullptr) || // If No Owner
1198 (!(m_pOwner->QueryEditable ())) || // Or Not Editable
1199 (m_pOwner->GetDisableDragAndDrop ())) // Or Drag And Drop Disabled
1202 if (m_pAlternateDropTarget != nullptr)
1204 DROPEFFECT dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_LINK;
1205 m_pAlternateDropTarget->DragOver(dwKeyState, { point.x, point.y }, &dwEffect);
1208 m_pOwner->HideDropIndicator (); // Hide Drop Caret
1210 return DROPEFFECT_NONE; // Return DE_NONE
1213 // if ((pDataObject->IsDataAvailable( CF_TEXT ) ) || // If Text Available
1214 // ( pDataObject -> IsDataAvailable( xxx ) ) || // Or xxx Available
1215 // ( pDataObject -> IsDataAvailable( yyy ) ) ) // Or yyy Available
1216 CLIPFORMAT fmt = CCrystalTextView::GetClipTcharTextFormat(); // CF_TEXT or CF_UNICODETEXT
1217 if (pDataObject->IsDataAvailable (fmt)) // If Text Available
1220 bDataSupported = true; // Set Flag
1223 if (!bDataSupported) // If No Supported Formats Available
1226 if (m_pAlternateDropTarget != nullptr)
1228 DROPEFFECT dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_LINK;
1229 m_pAlternateDropTarget->DragOver(dwKeyState, { point.x, point.y }, &dwEffect);
1232 m_pOwner->HideDropIndicator (); // Hide Drop Caret
1234 return DROPEFFECT_NONE; // Return DE_NONE
1237 m_pOwner->ShowDropIndicator (point);
1238 if (dwKeyState & MK_CONTROL)
1239 return DROPEFFECT_COPY;
1240 return DROPEFFECT_MOVE;
1243 BOOL CEditDropTargetImpl::
1244 OnDrop (CWnd * pWnd, COleDataObject * pDataObject, DROPEFFECT dropEffect, CPoint point)
1247 // [JRT] ( m_pOwner -> GetDisableDragAndDrop() ) ) // Or Drag And Drop Disabled
1249 bool bDataSupported = false;
1251 m_pOwner->HideDropIndicator (); // Hide Drop Caret
1253 if ((m_pOwner == nullptr) || // If No Owner
1254 (!(m_pOwner->QueryEditable ())) || // Or Not Editable
1255 (m_pOwner->GetDisableDragAndDrop ())) // Or Drag And Drop Disabled
1258 if (m_pAlternateDropTarget != nullptr)
1260 DROPEFFECT dwEffect = DROPEFFECT_NONE;
1261 m_pAlternateDropTarget->Drop(pDataObject->m_lpDataObject, 0, { point.x, point.y }, &dwEffect);
1264 return DROPEFFECT_NONE; // Return DE_NONE
1267 // if( ( pDataObject -> IsDataAvailable( CF_TEXT ) ) || // If Text Available
1268 // ( pDataObject -> IsDataAvailable( xxx ) ) || // Or xxx Available
1269 // ( pDataObject -> IsDataAvailable( yyy ) ) ) // Or yyy Available
1270 CLIPFORMAT fmt = CCrystalTextView::GetClipTcharTextFormat(); // CF_TEXT or CF_UNICODETEXT
1271 if (pDataObject->IsDataAvailable (fmt)) // If Text Available
1274 bDataSupported = true; // Set Flag
1277 if (!bDataSupported) // If No Supported Formats Available
1280 if (m_pAlternateDropTarget != nullptr)
1282 DROPEFFECT dwEffect = DROPEFFECT_NONE;
1283 m_pAlternateDropTarget->Drop(pDataObject->m_lpDataObject, 0, { point.x, point.y }, &dwEffect);
1286 return DROPEFFECT_NONE; // Return DE_NONE
1289 return (m_pOwner->DoDropText (pDataObject, point)); // Return Result Of Drop
1293 DROPEFFECT CEditDropTargetImpl::
1294 OnDragScroll (CWnd * pWnd, DWORD dwKeyState, CPoint point)
1296 ASSERT (m_pOwner == pWnd);
1297 m_pOwner->DoDragScroll (point);
1299 if (dwKeyState & MK_CONTROL)
1300 return DROPEFFECT_COPY;
1301 return DROPEFFECT_MOVE;
1304 void CCrystalEditView::
1305 DoDragScroll (const CPoint & point)
1308 GetClientRect (rcClientRect);
1309 if (point.y < rcClientRect.top + DRAG_BORDER_Y)
1311 HideDropIndicator ();
1314 ShowDropIndicator (point);
1315 //UpdateSiblingScrollPos(false);
1318 if (point.y >= rcClientRect.bottom - DRAG_BORDER_Y)
1320 HideDropIndicator ();
1323 ShowDropIndicator (point);
1324 //UpdateSiblingScrollPos(false);
1327 if (point.x < rcClientRect.left + GetMarginWidth () + DRAG_BORDER_X)
1329 HideDropIndicator ();
1332 ShowDropIndicator (point);
1333 //UpdateSiblingScrollPos(true);
1336 if (point.x >= rcClientRect.right - DRAG_BORDER_X)
1338 HideDropIndicator ();
1341 ShowDropIndicator (point);
1342 //UpdateSiblingScrollPos(true);
1347 void CCrystalEditView::
1348 SetAlternateDropTarget (IDropTarget *pDropTarget)
1350 ASSERT(m_pDropTarget->m_pAlternateDropTarget == nullptr);
1351 m_pDropTarget->m_pAlternateDropTarget = pDropTarget;
1352 m_pDropTarget->m_pAlternateDropTarget->AddRef();
1355 bool CCrystalEditView::
1356 DoDropText (COleDataObject * pDataObject, const CPoint & ptClient)
1358 CLIPFORMAT fmt = GetClipTcharTextFormat(); // CF_TEXT or CF_UNICODETEXT
1359 HGLOBAL hData = pDataObject->GetGlobalData (fmt);
1360 if (hData == nullptr)
1363 CPoint ptDropPos = ClientToText (ptClient);
1364 if (IsDraggingText () && IsInsideSelection (ptDropPos))
1366 SetAnchor (ptDropPos);
1367 SetSelection (ptDropPos, ptDropPos);
1368 SetCursorPos (ptDropPos);
1369 EnsureVisible (ptDropPos);
1373 UINT cbData = (UINT) ::GlobalSize (hData);
1374 UINT cchText = cbData / sizeof(TCHAR) - 1;
1375 LPTSTR pszText = (LPTSTR)::GlobalLock (hData);
1376 if (pszText == nullptr)
1379 // Open the undo group
1380 // When we drag from the same panel, it is already open, so do nothing
1381 // (we could test m_pTextBuffer->m_bUndoGroup if it were not a protected member)
1382 bool bGroupFlag = false;
1383 if (! IsDraggingText())
1385 m_pTextBuffer->BeginUndoGroup ();
1390 m_pTextBuffer->InsertText (this, ptDropPos.y, ptDropPos.x, pszText, cchText, y, x, CE_ACTION_DRAGDROP); // [JRT]
1392 CPoint ptCurPos (x, y);
1393 ASSERT_VALIDTEXTPOS (ptCurPos);
1394 SetAnchor (ptDropPos);
1395 SetSelection (ptDropPos, ptCurPos);
1396 SetCursorPos (ptCurPos);
1397 EnsureVisible (ptCurPos);
1400 m_pTextBuffer->FlushUndoGroup (this);
1402 ::GlobalUnlock (hData);
1406 int CCrystalEditView::
1407 OnCreate (LPCREATESTRUCT lpCreateStruct)
1409 if (CCrystalTextView::OnCreate (lpCreateStruct) == -1)
1412 ASSERT (m_pDropTarget == nullptr);
1413 m_pDropTarget = new CEditDropTargetImpl (this);
1414 if (!m_pDropTarget->Register (this))
1416 TRACE0 ("Warning: Unable to register drop target for ccrystaleditview.\n");
1417 delete m_pDropTarget;
1418 m_pDropTarget = nullptr;
1424 void CCrystalEditView::
1427 if (m_pDropTarget != nullptr)
1429 m_pDropTarget->Revoke ();
1430 if (m_pDropTarget->m_pAlternateDropTarget)
1431 m_pDropTarget->m_pAlternateDropTarget->Release();
1432 delete m_pDropTarget;
1433 m_pDropTarget = nullptr;
1436 CCrystalTextView::OnDestroy ();
1439 void CCrystalEditView::
1440 ShowDropIndicator (const CPoint & point)
1442 if (!m_bDropPosVisible)
1445 m_ptSavedCaretPos = GetCursorPos ();
1446 m_bDropPosVisible = true;
1447 ::CreateCaret (m_hWnd, (HBITMAP) 1, 2, GetLineHeight ());
1449 m_ptDropPos = ClientToText (point);
1450 // NB: m_ptDropPos.x is index into char array, which is uncomparable to m_nOffsetChar.
1451 CPoint ptCaretPos = TextToClient (m_ptDropPos);
1452 if (ptCaretPos.x >= GetMarginWidth())
1454 SetCaretPos (ptCaretPos);
1463 void CCrystalEditView::
1464 HideDropIndicator ()
1466 if (m_bDropPosVisible)
1468 SetCursorPos (m_ptSavedCaretPos);
1470 m_bDropPosVisible = false;
1474 DROPEFFECT CCrystalEditView::
1477 return DROPEFFECT_COPY | DROPEFFECT_MOVE;
1480 void CCrystalEditView::
1481 OnDropSource (DROPEFFECT de)
1483 if (!IsDraggingText ())
1486 ASSERT_VALIDTEXTPOS (m_ptDraggedTextBegin);
1487 ASSERT_VALIDTEXTPOS (m_ptDraggedTextEnd);
1489 if (de == DROPEFFECT_MOVE)
1491 m_pTextBuffer->DeleteText (this, m_ptDraggedTextBegin.y, m_ptDraggedTextBegin.x, m_ptDraggedTextEnd.y,
1492 m_ptDraggedTextEnd.x, CE_ACTION_DRAGDROP); // [JRT]
1497 void CCrystalEditView::
1498 UpdateView (CCrystalTextView * pSource, CUpdateContext * pContext, DWORD dwFlags, int nLineIndex /*= -1*/ )
1500 CCrystalTextView::UpdateView (pSource, pContext, dwFlags, nLineIndex);
1502 if (m_bSelectionPushed && pContext != nullptr)
1504 pContext->RecalcPoint (m_ptSavedSelStart);
1505 pContext->RecalcPoint (m_ptSavedSelEnd);
1506 ASSERT_VALIDTEXTPOS (m_ptSavedSelStart);
1507 ASSERT_VALIDTEXTPOS (m_ptSavedSelEnd);
1509 if (m_bDropPosVisible )
1511 pContext->RecalcPoint (m_ptSavedCaretPos);
1512 ASSERT_VALIDTEXTPOS (m_ptSavedCaretPos);
1516 void CCrystalEditView::
1519 if (!QueryEditable ())
1522 CWinApp *pApp = AfxGetApp ();
1523 ASSERT (pApp != nullptr);
1525 delete m_pEditReplaceDlg;
1526 m_pEditReplaceDlg = new CEditReplaceDlg(this);
1527 LastSearchInfos * lastSearch = m_pEditReplaceDlg->GetLastSearchInfos();
1531 // Get the latest Replace parameters
1532 lastSearch->m_bMatchCase = (m_dwLastReplaceFlags & FIND_MATCH_CASE) != 0;
1533 lastSearch->m_bWholeWord = (m_dwLastReplaceFlags & FIND_WHOLE_WORD) != 0;
1534 lastSearch->m_bRegExp = (m_dwLastReplaceFlags & FIND_REGEXP) != 0;
1535 lastSearch->m_bNoWrap = (m_dwLastReplaceFlags & FIND_NO_WRAP) != 0;
1536 if (m_pszLastFindWhat != nullptr)
1537 lastSearch->m_sText = m_pszLastFindWhat;
1541 DWORD dwFlags = pApp->GetProfileInt (EDITPAD_SECTION, _T("ReplaceFlags"), 0);
1542 lastSearch->m_bMatchCase = (dwFlags & FIND_MATCH_CASE) != 0;
1543 lastSearch->m_bWholeWord = (dwFlags & FIND_WHOLE_WORD) != 0;
1544 lastSearch->m_bRegExp = (dwFlags & FIND_REGEXP) != 0;
1545 lastSearch->m_bNoWrap = (dwFlags & FIND_NO_WRAP) != 0;
1547 lastSearch->m_nDirection = 1;
1548 m_pEditReplaceDlg->UseLastSearch ();
1553 GetSelection (m_ptSavedSelStart, m_ptSavedSelEnd);
1554 m_bSelectionPushed = true;
1556 m_pEditReplaceDlg->SetScope(true); // Replace in current selection
1557 m_pEditReplaceDlg->m_ptCurrentPos = m_ptSavedSelStart;
1558 m_pEditReplaceDlg->m_bEnableScopeSelection = true;
1559 m_pEditReplaceDlg->m_ptBlockBegin = m_ptSavedSelStart;
1560 m_pEditReplaceDlg->m_ptBlockEnd = m_ptSavedSelEnd;
1562 // If the selection is in one line, copy text to dialog
1563 if (m_ptSavedSelStart.y == m_ptSavedSelEnd.y)
1564 GetText(m_ptSavedSelStart, m_ptSavedSelEnd, m_pEditReplaceDlg->m_sText);
1568 m_pEditReplaceDlg->SetScope(false); // Set scope when no selection
1569 m_pEditReplaceDlg->m_ptCurrentPos = GetCursorPos ();
1570 m_pEditReplaceDlg->m_bEnableScopeSelection = false;
1572 CPoint ptCursorPos = GetCursorPos ();
1573 CPoint ptStart = WordToLeft (ptCursorPos);
1574 CPoint ptEnd = WordToRight (ptCursorPos);
1575 if (IsValidTextPos (ptStart) && IsValidTextPos (ptEnd) && ptStart != ptEnd)
1576 GetText (ptStart, ptEnd, m_pEditReplaceDlg->m_sText);
1579 // Execute Replace dialog
1580 m_pEditReplaceDlg->Create(CEditReplaceDlg::IDD, this);
1581 m_pEditReplaceDlg->ShowWindow(SW_SHOW);
1584 void CCrystalEditView::
1585 SaveLastSearch(LastSearchInfos *lastSearch)
1587 // Save Replace parameters for 'F3' command
1588 m_bLastReplace = true;
1589 if (m_pszLastFindWhat != nullptr)
1590 free (m_pszLastFindWhat);
1591 m_pszLastFindWhat = _tcsdup (lastSearch->m_sText);
1592 m_dwLastReplaceFlags = 0;
1593 if (lastSearch->m_bMatchCase)
1594 m_dwLastReplaceFlags |= FIND_MATCH_CASE;
1595 if (lastSearch->m_bWholeWord)
1596 m_dwLastReplaceFlags |= FIND_WHOLE_WORD;
1597 if (lastSearch->m_bRegExp)
1598 m_dwLastReplaceFlags |= FIND_REGEXP;
1599 if (lastSearch->m_bNoWrap)
1600 m_dwLastReplaceFlags |= FIND_NO_WRAP;
1602 // Restore selection
1603 if (m_bSelectionPushed)
1605 SetSelection (m_ptSavedSelStart, m_ptSavedSelEnd);
1606 m_bSelectionPushed = false;
1609 // Save search parameters to registry
1610 VERIFY (AfxGetApp()->WriteProfileInt (EDITPAD_SECTION, _T ("ReplaceFlags"), m_dwLastReplaceFlags));
1614 * @brief Replace selected text.
1615 * This function replaces selected text in the editor pane with given text.
1616 * @param [in] pszNewText The text replacing selected text.
1617 * @param [in] cchNewText Length of the replacing text.
1618 * @param [in] dwFlags Additional modifier flags:
1619 * - FIND_REGEXP: use the regular expression.
1620 * @return true if succeeded.
1622 bool CCrystalEditView::
1623 ReplaceSelection (LPCTSTR pszNewText, size_t cchNewText, DWORD dwFlags, bool bGroupWithPrevious)
1626 return DeleteCurrentSelection();
1627 ASSERT (pszNewText != nullptr);
1629 m_pTextBuffer->BeginUndoGroup(bGroupWithPrevious);
1634 auto [ptSelStart, ptSelEnd] = GetSelection ();
1636 ptCursorPos = ptSelStart;
1638 m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_REPLACE);
1641 ptCursorPos = GetCursorPos ();
1642 ASSERT_VALIDTEXTPOS (ptCursorPos);
1646 if (dwFlags & FIND_REGEXP)
1648 LPTSTR lpszNewStr = nullptr;
1649 if (m_pszMatched && !RxReplace(pszNewText, m_pszMatched, m_nLastFindWhatLen, m_rxmatch, &lpszNewStr, &m_nLastReplaceLen))
1652 if (lpszNewStr != nullptr && m_nLastReplaceLen > 0)
1654 LPTSTR buf = text.GetBuffer (m_nLastReplaceLen + 1);
1655 _tcsncpy_s (buf, m_nLastReplaceLen+1, lpszNewStr, m_nLastReplaceLen);
1656 text.ReleaseBuffer (m_nLastReplaceLen);
1660 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, text, text.GetLength(), y, x, CE_ACTION_REPLACE); // [JRT+FRD]
1661 if (lpszNewStr != nullptr)
1667 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszNewText, cchNewText, y, x, CE_ACTION_REPLACE); // [JRT]
1668 ASSERT(cchNewText < INT_MAX);
1669 m_nLastReplaceLen = static_cast<int>(cchNewText);
1672 CPoint ptEndOfBlock = CPoint (x, y);
1673 if (ptEndOfBlock.x == m_pTextBuffer->GetLineLength (ptEndOfBlock.y))
1675 if (ptEndOfBlock.y < m_pTextBuffer->GetLineCount() - 1)
1681 ASSERT_VALIDTEXTPOS (ptCursorPos);
1682 ASSERT_VALIDTEXTPOS (ptEndOfBlock);
1683 SetAnchor (ptEndOfBlock);
1684 SetSelection (ptCursorPos, ptEndOfBlock);
1685 SetCursorPos (ptEndOfBlock);
1687 m_pTextBuffer->FlushUndoGroup(this);
1692 void CCrystalEditView::
1693 OnUpdateEditUndo (CCmdUI * pCmdUI)
1695 bool bCanUndo = m_pTextBuffer != nullptr && m_pTextBuffer->CanUndo ();
1696 pCmdUI->Enable (bCanUndo);
1698 // Since we need text only for menus...
1699 if (pCmdUI->m_pMenu != nullptr)
1701 // Tune up 'resource handle'
1702 HINSTANCE hOldResHandle = AfxGetResourceHandle ();
1703 AfxSetResourceHandle (GetResourceHandle ());
1708 // Format menu item text using the provided item description
1710 m_pTextBuffer->GetUndoDescription (desc);
1711 menu.Format (IDS_MENU_UNDO_FORMAT, (LPCTSTR)desc);
1715 // Just load default menu item text
1716 menu.LoadString (IDS_MENU_UNDO_DEFAULT);
1719 // Restore original handle
1720 AfxSetResourceHandle (hOldResHandle);
1722 // Set menu item text
1723 pCmdUI->SetText (menu);
1727 void CCrystalEditView::
1733 bool CCrystalEditView::
1736 if (m_pTextBuffer != nullptr && m_pTextBuffer->CanUndo ())
1739 if (m_pTextBuffer->Undo (this, ptCursorPos))
1741 ASSERT_VALIDTEXTPOS (ptCursorPos);
1742 SetAnchor (ptCursorPos);
1743 SetSelection (ptCursorPos, ptCursorPos);
1744 SetCursorPos (ptCursorPos);
1745 EnsureVisible (ptCursorPos);
1753 void CCrystalEditView::
1754 SetDisableBSAtSOL (bool bDisableBSAtSOL)
1756 m_bDisableBSAtSOL = bDisableBSAtSOL;
1759 void CCrystalEditView::
1760 CopyProperties (CCrystalTextView* pSource)
1762 CCrystalTextView::CopyProperties(pSource);
1763 auto pSourceEditView = dynamic_cast<decltype(this)>(pSource);
1764 if (!pSourceEditView)
1766 m_bDisableBSAtSOL = pSourceEditView->m_bDisableBSAtSOL;
1767 m_bOvrMode = pSourceEditView->m_bOvrMode;
1768 m_bAutoIndent = pSourceEditView->m_bAutoIndent;
1771 void CCrystalEditView::
1777 bool CCrystalEditView::
1780 if (m_pTextBuffer != nullptr && m_pTextBuffer->CanRedo ())
1783 if (m_pTextBuffer->Redo (this, ptCursorPos))
1785 ASSERT_VALIDTEXTPOS (ptCursorPos);
1786 SetAnchor (ptCursorPos);
1787 SetSelection (ptCursorPos, ptCursorPos);
1788 SetCursorPos (ptCursorPos);
1789 EnsureVisible (ptCursorPos);
1796 void CCrystalEditView::
1797 OnUpdateEditRedo (CCmdUI * pCmdUI)
1799 bool bCanRedo = m_pTextBuffer != nullptr && m_pTextBuffer->CanRedo ();
1800 pCmdUI->Enable (bCanRedo);
1802 // Since we need text only for menus...
1803 if (pCmdUI->m_pMenu != nullptr)
1805 // Tune up 'resource handle'
1806 HINSTANCE hOldResHandle = AfxGetResourceHandle ();
1807 AfxSetResourceHandle (GetResourceHandle ());
1812 // Format menu item text using the provided item description
1814 m_pTextBuffer->GetRedoDescription (desc);
1815 menu.Format (IDS_MENU_REDO_FORMAT, (LPCTSTR)desc);
1819 // Just load default menu item text
1820 menu.LoadString (IDS_MENU_REDO_DEFAULT);
1823 // Restore original handle
1824 AfxSetResourceHandle (hOldResHandle);
1826 // Set menu item text
1827 pCmdUI->SetText (menu);
1832 isopenbrace (TCHAR c)
1834 return c == _T ('{') || c == _T ('(') || c == _T ('[') || c == _T ('<');
1838 isclosebrace (TCHAR c)
1840 return c == _T ('}') || c == _T (')') || c == _T (']') || c == _T ('>');
1844 isopenbrace (LPCTSTR s)
1846 return s[1] == _T ('\0') && isopenbrace (*s);
1850 isclosebrace (LPCTSTR s)
1852 return s[1] == _T ('\0') && isclosebrace (*s);
1855 int bracetype (TCHAR c);
1856 int bracetype (LPCTSTR s);
1858 void CCrystalEditView::
1859 OnEditOperation (int nAction, LPCTSTR pszText, size_t cchText)
1863 // Analyse last action...
1864 if (nAction == CE_ACTION_TYPING && (
1865 _tcsncmp (pszText, _T ("\r\n"), cchText) == 0 ||
1866 (cchText == 1 && (*pszText == '\r' || *pszText == '\n')))
1867 && !m_bOvrMode && !m_pTextBuffer->GetTableEditing())
1870 CPoint ptCursorPos = GetCursorPos ();
1871 ASSERT (ptCursorPos.y > 0);
1873 // Take indentation from the previous line
1874 int nLength = m_pTextBuffer->GetLineLength (ptCursorPos.y - 1);
1875 LPCTSTR pszLineChars = m_pTextBuffer->GetLineChars (ptCursorPos.y - 1);
1877 while (nPos < nLength && xisspace (pszLineChars[nPos]))
1882 if ((GetFlags () & SRCOPT_BRACEGNU) && isclosebrace (pszLineChars[nLength - 1]) && ptCursorPos.y > 0 && nPos && nPos == nLength - 1)
1884 if (pszLineChars[nPos - 1] == _T ('\t'))
1890 int nTabSize = GetTabSize (),
1891 nDelta = nTabSize - nPos % nTabSize;
1903 // Insert part of the previous line
1904 TCHAR *pszInsertStr;
1905 if ((GetFlags () & (SRCOPT_BRACEGNU|SRCOPT_BRACEANSI)) && isopenbrace (pszLineChars[nLength - 1]))
1907 if (m_pTextBuffer->GetInsertTabs())
1909 const size_t InsertSiz = (nPos + 2);
1910 pszInsertStr = static_cast<TCHAR *> (_alloca (sizeof(TCHAR) * InsertSiz));
1911 _tcsncpy_s (pszInsertStr, InsertSiz, pszLineChars, nPos);
1912 pszInsertStr[nPos++] = _T ('\t');
1916 int nTabSize = GetTabSize ();
1917 int nChars = nTabSize - nPos % nTabSize;
1918 const size_t InsertSiz = (nPos + nChars + 1);
1919 pszInsertStr = static_cast<TCHAR *> (_alloca (sizeof (TCHAR) * InsertSiz));
1920 _tcsncpy_s (pszInsertStr, InsertSiz, pszLineChars, nPos);
1923 pszInsertStr[nPos++] = _T (' ');
1929 const size_t InsertSiz = (nPos + 1);
1930 pszInsertStr = static_cast<TCHAR *> (_alloca (sizeof (TCHAR) * InsertSiz));
1931 _tcsncpy_s (pszInsertStr, InsertSiz, pszLineChars, nPos);
1933 pszInsertStr[nPos] = 0;
1935 // m_pTextBuffer->BeginUndoGroup ();
1937 m_pTextBuffer->InsertText (nullptr, ptCursorPos.y, ptCursorPos.x,
1938 pszInsertStr, nPos, y, x, CE_ACTION_AUTOINDENT);
1940 SetSelection (pt, pt);
1944 // m_pTextBuffer->FlushUndoGroup (this);
1948 // Insert part of the previous line
1949 if ((GetFlags () & (SRCOPT_BRACEGNU|SRCOPT_BRACEANSI)) && isopenbrace (pszLineChars[nLength - 1]))
1951 TCHAR *pszInsertStr;
1952 if (m_pTextBuffer->GetInsertTabs())
1954 pszInsertStr = (TCHAR *) _alloca (sizeof (TCHAR) * 2);
1955 pszInsertStr[nPos++] = _T ('\t');
1959 int nTabSize = GetTabSize ();
1960 int nChars = nTabSize - nPos % nTabSize;
1961 pszInsertStr = (TCHAR *) _alloca (sizeof (TCHAR) * (nChars + 1));
1964 pszInsertStr[nPos++] = _T (' ');
1967 pszInsertStr[nPos] = 0;
1969 // m_pTextBuffer->BeginUndoGroup ();
1971 m_pTextBuffer->InsertText (nullptr, ptCursorPos.y, ptCursorPos.x,
1972 pszInsertStr, nPos, y, x, CE_ACTION_AUTOINDENT);
1974 SetSelection (pt, pt);
1978 // m_pTextBuffer->FlushUndoGroup (this);
1982 else if (nAction == CE_ACTION_TYPING && (GetFlags () & SRCOPT_FNBRACE) && bracetype (pszText) == 3)
1985 CPoint ptCursorPos = GetCursorPos ();
1986 LPCTSTR pszChars = m_pTextBuffer->GetLineChars (ptCursorPos.y);
1987 if (ptCursorPos.x > 1 && xisalnum (pszChars[ptCursorPos.x - 2]))
1989 LPTSTR pszInsertStr = (TCHAR *) _alloca (sizeof (TCHAR) * 2);
1990 *pszInsertStr = _T (' ');
1991 pszInsertStr[1] = _T ('\0');
1992 // m_pTextBuffer->BeginUndoGroup ();
1994 m_pTextBuffer->InsertText (nullptr, ptCursorPos.y, ptCursorPos.x - 1,
1995 pszInsertStr, 1, y, x, CE_ACTION_AUTOINDENT);
1996 ptCursorPos.x = x + 1;
1998 SetSelection (ptCursorPos, ptCursorPos);
1999 SetAnchor (ptCursorPos);
2000 SetCursorPos (ptCursorPos);
2001 EnsureVisible (ptCursorPos);
2002 // m_pTextBuffer->FlushUndoGroup (this);
2005 else if (nAction == CE_ACTION_TYPING && (GetFlags () & SRCOPT_BRACEGNU) && isopenbrace (pszText))
2008 CPoint ptCursorPos = GetCursorPos ();
2010 // Take indentation from the previous line
2011 int nLength = m_pTextBuffer->GetLineLength (ptCursorPos.y);
2012 LPCTSTR pszLineChars = m_pTextBuffer->GetLineChars (ptCursorPos.y );
2014 while (nPos < nLength && xisspace (pszLineChars[nPos]))
2016 if (nPos == nLength - 1)
2018 TCHAR *pszInsertStr;
2019 if (m_pTextBuffer->GetInsertTabs())
2021 pszInsertStr = (TCHAR *) _alloca (sizeof (TCHAR) * 2);
2022 *pszInsertStr = _T ('\t');
2027 int nTabSize = GetTabSize ();
2028 int nChars = nTabSize - nPos % nTabSize;
2029 pszInsertStr = (TCHAR *) _alloca (sizeof (TCHAR) * (nChars + 1));
2033 pszInsertStr[nPos++] = _T (' ');
2036 pszInsertStr[nPos] = 0;
2038 // m_pTextBuffer->BeginUndoGroup ();
2040 m_pTextBuffer->InsertText (nullptr, ptCursorPos.y, ptCursorPos.x - 1,
2041 pszInsertStr, nPos, y, x, CE_ACTION_AUTOINDENT);
2042 CPoint pt (x + 1, y);
2043 SetSelection (pt, pt);
2047 // m_pTextBuffer->FlushUndoGroup (this);
2050 else if (nAction == CE_ACTION_TYPING && (GetFlags () & (SRCOPT_BRACEGNU|SRCOPT_BRACEANSI)) && isclosebrace (pszText))
2053 CPoint ptCursorPos = GetCursorPos ();
2055 // Take indentation from the previous line
2056 int nLength = m_pTextBuffer->GetLineLength (ptCursorPos.y);
2057 LPCTSTR pszLineChars = m_pTextBuffer->GetLineChars (ptCursorPos.y );
2059 while (nPos < nLength && xisspace (pszLineChars[nPos]))
2061 if (ptCursorPos.y > 0 && nPos && nPos == nLength - 1)
2063 if (pszLineChars[nPos - 1] == _T ('\t'))
2069 int nTabSize = GetTabSize ();
2070 nPos = nTabSize - (ptCursorPos.x - 1) % nTabSize;
2075 if (nPos > nLength - 1)
2080 // m_pTextBuffer->BeginUndoGroup ();
2081 m_pTextBuffer->DeleteText (nullptr, ptCursorPos.y, ptCursorPos.x - nPos - 1,
2082 ptCursorPos.y, ptCursorPos.x - 1, CE_ACTION_AUTOINDENT);
2083 ptCursorPos.x -= nPos;
2084 SetCursorPos (ptCursorPos);
2085 SetSelection (ptCursorPos, ptCursorPos);
2086 SetAnchor (ptCursorPos);
2087 EnsureVisible (ptCursorPos);
2088 // m_pTextBuffer->FlushUndoGroup (this);
2094 void CCrystalEditView::
2095 OnEditAutoComplete ()
2097 CPoint ptCursorPos = GetCursorPos ();
2098 int nLength = m_pTextBuffer->GetLineLength (ptCursorPos.y);
2099 LPCTSTR pszText = m_pTextBuffer->GetLineChars (ptCursorPos.y), pszEnd = pszText + ptCursorPos.x;
2100 if (ptCursorPos.x > 0 && ptCursorPos.y > 0 && (nLength == ptCursorPos.x || !xisalnum (*pszEnd)) && xisalnum (pszEnd[-1]))
2102 LPCTSTR pszBegin = pszEnd - 1;
2103 while (pszBegin > pszText && xisalnum (*pszBegin))
2105 if (!xisalnum (*pszBegin))
2107 nLength = static_cast<int>(pszEnd - pszBegin);
2109 LPTSTR pszBuffer = sText.GetBuffer (nLength + 2);
2110 *pszBuffer = _T('<');
2111 _tcsncpy_s (pszBuffer + 1, nLength + 1, pszBegin, nLength);
2112 sText.ReleaseBuffer (nLength + 1);
2114 ptCursorPos.x -= nLength;
2115 bool bFound = FindText (sText, ptCursorPos, FIND_MATCH_CASE|FIND_REGEXP|FIND_DIRECTION_UP, true, &ptTextPos);
2118 ptCursorPos.x += nLength;
2119 bFound = FindText (sText, ptCursorPos, FIND_MATCH_CASE|FIND_REGEXP, true, &ptTextPos);
2120 ptCursorPos.x -= nLength;
2124 const int nLineLength = m_pTextBuffer->GetLineLength (ptTextPos.y);
2125 int nFound = nLineLength;
2126 pszText = m_pTextBuffer->GetLineChars (ptTextPos.y) + ptTextPos.x + m_nLastFindWhatLen;
2127 nFound -= ptTextPos.x + m_nLastFindWhatLen;
2128 pszBuffer = sText.GetBuffer (nFound + 1);
2129 while (nFound-- && xisalnum (*pszText))
2130 *pszBuffer++ = *pszText++;
2131 sText.ReleaseBuffer (nLineLength - (ptTextPos.x + m_nLastFindWhatLen) - nFound - 1);
2132 if (!sText.IsEmpty ())
2134 m_pTextBuffer->BeginUndoGroup ();
2136 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x + nLength, sText, sText.GetLength(), y, x, CE_ACTION_AUTOCOMPLETE);
2139 SetCursorPos (ptCursorPos);
2140 SetSelection (ptCursorPos, ptCursorPos);
2141 SetAnchor (ptCursorPos);
2142 EnsureVisible (ptCursorPos);
2143 m_pTextBuffer->FlushUndoGroup (this);
2149 void CCrystalEditView::
2150 OnUpdateEditAutoComplete (CCmdUI * pCmdUI)
2152 CPoint ptCursorPos = GetCursorPos ();
2153 int nLength = m_pTextBuffer->GetLineLength (ptCursorPos.y);
2154 LPCTSTR pszText = m_pTextBuffer->GetLineChars (ptCursorPos.y) + ptCursorPos.x;
2155 pCmdUI->Enable (ptCursorPos.x > 0 && ptCursorPos.y > 0 && (nLength == ptCursorPos.x || !xisalnum (*pszText)) && xisalnum (pszText[-1]));
2158 void CCrystalEditView::
2161 CPoint ptCursorPos = GetCursorPos ();
2162 int nLength = m_pTextBuffer->GetLineLength (ptCursorPos.y);
2163 LPCTSTR pszText = m_pTextBuffer->GetLineChars (ptCursorPos.y), pszEnd = pszText + ptCursorPos.x;
2164 if (ptCursorPos.x > 0 && ptCursorPos.y > 0 && (nLength == ptCursorPos.x || !xisalnum (*pszEnd)) && xisalnum (pszEnd[-1]))
2166 LPCTSTR pszBegin = pszEnd - 1;
2167 while (pszBegin > pszText && xisalnum (*pszBegin))
2169 if (!xisalnum (*pszBegin))
2171 nLength = static_cast<int>(pszEnd - pszBegin);
2172 CString sText, sExpand;
2173 LPTSTR pszBuffer = sText.GetBuffer (nLength + 1);
2174 _tcsncpy_s (pszBuffer, nLength + 1, pszBegin, nLength);
2175 sText.ReleaseBuffer (nLength);
2177 ptCursorPos.x -= nLength;
2178 bool bFound = !!m_mapExpand->Lookup (sText, sExpand);
2179 if (bFound && !sExpand.IsEmpty ())
2181 m_pTextBuffer->BeginUndoGroup ();
2183 m_pTextBuffer->DeleteText (this, ptCursorPos.y, ptCursorPos.x, ptCursorPos.y, ptCursorPos.x + nLength, CE_ACTION_AUTOEXPAND);
2184 LPTSTR pszExpand = sExpand.GetBuffer (sExpand.GetLength () + 1);
2185 LPTSTR pszSlash = _tcschr (pszExpand, _T ('\\'));
2186 if (pszSlash == nullptr)
2188 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszExpand, _tcslen(pszExpand), y, x, CE_ACTION_AUTOEXPAND);
2191 ASSERT_VALIDTEXTPOS (ptCursorPos);
2192 SetCursorPos (ptCursorPos);
2193 SetSelection (ptCursorPos, ptCursorPos);
2194 SetAnchor (ptCursorPos);
2198 *pszSlash++ = _T ('\0');
2201 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszExpand, _tcslen(pszExpand), y, x, CE_ACTION_AUTOEXPAND);
2204 ASSERT_VALIDTEXTPOS (ptCursorPos);
2205 SetSelection (ptCursorPos, ptCursorPos);
2206 SetAnchor (ptCursorPos);
2207 SetCursorPos (ptCursorPos);
2208 OnEditOperation (CE_ACTION_TYPING, pszExpand, _tcslen(pszExpand));
2209 ptCursorPos = GetCursorPos ();
2210 if (pszSlash == nullptr)
2216 const static TCHAR szText[3] = _T ("\r\n");
2217 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, szText, _tcslen(szText), y, x, CE_ACTION_AUTOEXPAND); // [JRT]
2220 ASSERT_VALIDTEXTPOS (ptCursorPos);
2221 SetSelection (ptCursorPos, ptCursorPos);
2222 SetAnchor (ptCursorPos);
2223 SetCursorPos (ptCursorPos);
2224 OnEditOperation (CE_ACTION_TYPING, szText, _tcslen(pszExpand));
2247 CPoint ptSelStart = ptCursorPos;
2248 bool bDeleted = false;
2249 if (!(ptCursorPos.x)) // If At Start Of Line
2252 if (!m_bDisableBSAtSOL) // If DBSASOL Is Disabled
2255 if (ptCursorPos.y > 0) // If Previous Lines Available
2258 ptCursorPos.y--; // Decrement To Previous Line
2260 ptCursorPos.x = GetLineLength (
2261 ptCursorPos.y); // Set Cursor To End Of Previous Line
2263 bDeleted = true; // Set Deleted Flag
2268 else // If Caret Not At SOL
2271 ptCursorPos.x--; // Decrement Position
2273 bDeleted = true; // Set Deleted Flag
2276 ASSERT_VALIDTEXTPOS (ptCursorPos);
2277 SetAnchor (ptCursorPos);
2278 SetSelection (ptCursorPos, ptCursorPos);
2279 SetCursorPos (ptCursorPos);
2282 m_pTextBuffer->DeleteText (this, ptCursorPos.y, ptCursorPos.x, ptSelStart.y, ptSelStart.x, CE_ACTION_AUTOEXPAND); // [JRT]
2287 CPoint ptSelEnd = ptCursorPos;
2288 if (ptSelEnd.x == GetLineLength (ptSelEnd.y))
2290 if (ptSelEnd.y == GetLineCount () - 1)
2297 m_pTextBuffer->DeleteText (this, ptCursorPos.y, ptCursorPos.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_AUTOEXPAND); // [JRT]
2302 static TCHAR szText[32];
2303 if (m_pTextBuffer->GetInsertTabs())
2310 int nTabSize = GetTabSize ();
2311 int nChars = nTabSize - ptCursorPos.x % nTabSize;
2312 for (int i = 0; i < nChars; i++)
2314 szText[nChars] = '\0';
2316 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, szText, _tcslen(szText), y, x, CE_ACTION_AUTOEXPAND); // [JRT]
2319 ASSERT_VALIDTEXTPOS (ptCursorPos);
2320 SetSelection (ptCursorPos, ptCursorPos);
2321 SetAnchor (ptCursorPos);
2322 SetCursorPos (ptCursorPos);
2325 ptCursorPos = GetCursorPos ();
2326 pszExpand = pszSlash + 1;
2327 pszSlash = _tcschr (pszExpand, '\\');
2328 if (pszSlash != nullptr)
2332 sExpand.ReleaseBuffer ();
2333 EnsureVisible (ptCursorPos);
2334 m_pTextBuffer->FlushUndoGroup (this);
2339 void CCrystalEditView::
2340 OnUpdateEditAutoExpand (CCmdUI * pCmdUI)
2342 if (m_mapExpand->IsEmpty ())
2343 pCmdUI->Enable (false);
2345 OnUpdateEditAutoComplete (pCmdUI);
2348 void CCrystalEditView::
2349 OnUpdateEditLowerCase (CCmdUI * pCmdUI)
2351 pCmdUI->Enable (IsSelection ());
2354 void CCrystalEditView::
2359 CPoint ptCursorPos = GetCursorPos ();
2360 auto [ptSelStart, ptSelEnd] = GetSelection ();
2362 GetText (ptSelStart, ptSelEnd, text);
2365 m_pTextBuffer->BeginUndoGroup ();
2369 auto [ptSelStart1, ptSelEnd1] = GetSelection ();
2371 ptCursorPos = ptSelStart1;
2372 /*SetAnchor (ptCursorPos);
2373 SetSelection (ptCursorPos, ptCursorPos);
2374 SetCursorPos (ptCursorPos);
2375 EnsureVisible (ptCursorPos);*/
2378 m_pTextBuffer->DeleteText (this, ptSelStart1.y, ptSelStart1.x, ptSelEnd1.y, ptSelEnd1.x, CE_ACTION_LOWERCASE);
2382 m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, text.GetLength(), y, x, CE_ACTION_LOWERCASE);
2384 ASSERT_VALIDTEXTPOS (ptCursorPos);
2385 SetAnchor (ptCursorPos);
2386 SetSelection (ptSelStart, ptSelEnd);
2387 SetCursorPos (ptCursorPos);
2388 EnsureVisible (ptCursorPos);
2390 m_pTextBuffer->FlushUndoGroup (this);
2394 void CCrystalEditView::
2395 OnUpdateEditUpperCase (CCmdUI * pCmdUI)
2397 pCmdUI->Enable (IsSelection ());
2400 void CCrystalEditView::
2405 CPoint ptCursorPos = GetCursorPos ();
2406 auto [ptSelStart, ptSelEnd] = GetSelection ();
2408 GetText (ptSelStart, ptSelEnd, text);
2411 m_pTextBuffer->BeginUndoGroup ();
2415 auto [ptSelStart1, ptSelEnd1] = GetSelection ();
2417 ptCursorPos = ptSelStart1;
2418 /*SetAnchor (ptCursorPos);
2419 SetSelection (ptCursorPos, ptCursorPos);
2420 SetCursorPos (ptCursorPos);
2421 EnsureVisible (ptCursorPos);*/
2424 m_pTextBuffer->DeleteText (this, ptSelStart1.y, ptSelStart1.x, ptSelEnd1.y, ptSelEnd1.x, CE_ACTION_UPPERCASE);
2428 m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, text.GetLength(), y, x, CE_ACTION_UPPERCASE);
2430 ASSERT_VALIDTEXTPOS (ptCursorPos);
2431 SetAnchor (ptCursorPos);
2432 SetSelection (ptSelStart, ptSelEnd);
2433 SetCursorPos (ptCursorPos);
2434 EnsureVisible (ptCursorPos);
2436 m_pTextBuffer->FlushUndoGroup (this);
2440 void CCrystalEditView::
2441 OnUpdateEditSwapCase (CCmdUI * pCmdUI)
2443 pCmdUI->Enable (IsSelection ());
2446 void CCrystalEditView::
2451 CPoint ptCursorPos = GetCursorPos ();
2452 auto [ptSelStart, ptSelEnd] = GetSelection ();
2454 GetText (ptSelStart, ptSelEnd, text);
2455 int nLen = text.GetLength ();
2456 LPTSTR pszText = text.GetBuffer (nLen + 1);
2458 *pszText++ = (TCHAR)(_istlower (*pszText) ? _totupper (*pszText) : _totlower (*pszText));
2459 text.ReleaseBuffer (nLen);
2461 m_pTextBuffer->BeginUndoGroup ();
2465 auto [ptSelStart1, ptSelEnd1] = GetSelection ();
2467 ptCursorPos = ptSelStart1;
2468 /*SetAnchor (ptCursorPos);
2469 SetSelection (ptCursorPos, ptCursorPos);
2470 SetCursorPos (ptCursorPos);
2471 EnsureVisible (ptCursorPos);*/
2474 m_pTextBuffer->DeleteText (this, ptSelStart1.y, ptSelStart1.x, ptSelEnd1.y, ptSelEnd1.x, CE_ACTION_SWAPCASE);
2478 m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, text.GetLength(), y, x, CE_ACTION_SWAPCASE);
2480 ASSERT_VALIDTEXTPOS (ptCursorPos);
2481 SetAnchor (ptCursorPos);
2482 SetSelection (ptSelStart, ptSelEnd);
2483 SetCursorPos (ptCursorPos);
2484 EnsureVisible (ptCursorPos);
2486 m_pTextBuffer->FlushUndoGroup (this);
2490 void CCrystalEditView::
2491 OnUpdateEditCapitalize (CCmdUI * pCmdUI)
2493 pCmdUI->Enable (IsSelection ());
2496 void CCrystalEditView::
2501 CPoint ptCursorPos = GetCursorPos ();
2502 auto [ptSelStart, ptSelEnd] = GetSelection ();
2504 GetText (ptSelStart, ptSelEnd, text);
2505 int nLen = text.GetLength ();
2506 LPTSTR pszText = text.GetBuffer (nLen + 1);
2507 bool bCapitalize = true;
2510 if (xisspace (*pszText))
2512 else if (_istalpha (*pszText))
2515 *pszText = (TCHAR)_totupper (*pszText);
2516 bCapitalize = false;
2519 *pszText = (TCHAR)_totlower (*pszText);
2522 text.ReleaseBuffer (nLen);
2524 m_pTextBuffer->BeginUndoGroup ();
2528 auto [ptSelStart1, ptSelEnd1] = GetSelection ();
2530 ptCursorPos = ptSelStart1;
2531 /*SetAnchor (ptCursorPos);
2532 SetSelection (ptCursorPos, ptCursorPos);
2533 SetCursorPos (ptCursorPos);
2534 EnsureVisible (ptCursorPos);*/
2537 m_pTextBuffer->DeleteText (this, ptSelStart1.y, ptSelStart1.x, ptSelEnd1.y, ptSelEnd1.x, CE_ACTION_CAPITALIZE);
2541 m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, text.GetLength(), y, x, CE_ACTION_CAPITALIZE);
2543 ASSERT_VALIDTEXTPOS (ptCursorPos);
2544 SetAnchor (ptCursorPos);
2545 SetSelection (ptSelStart, ptSelEnd);
2546 SetCursorPos (ptCursorPos);
2547 EnsureVisible (ptCursorPos);
2549 m_pTextBuffer->FlushUndoGroup (this);
2553 void CCrystalEditView::
2554 OnUpdateEditSentence (CCmdUI * pCmdUI)
2556 pCmdUI->Enable (IsSelection ());
2559 void CCrystalEditView::
2564 CPoint ptCursorPos = GetCursorPos ();
2565 auto [ptSelStart, ptSelEnd] = GetSelection ();
2567 GetText (ptSelStart, ptSelEnd, text);
2568 int nLen = text.GetLength ();
2569 LPTSTR pszText = text.GetBuffer (nLen + 1);
2570 bool bCapitalize = true;
2573 if (!xisspace (*pszText))
2574 if (*pszText == _T ('.'))
2576 if (pszText[1] && !_istdigit (pszText[1]))
2579 else if (_istalpha (*pszText))
2582 *pszText = (TCHAR)_totupper (*pszText);
2583 bCapitalize = false;
2586 *pszText = (TCHAR)_totlower (*pszText);
2589 text.ReleaseBuffer (nLen);
2591 m_pTextBuffer->BeginUndoGroup ();
2595 auto [ptSelStart1, ptSelEnd1] = GetSelection ();
2597 ptCursorPos = ptSelStart1;
2598 /*SetAnchor (ptCursorPos);
2599 SetSelection (ptCursorPos, ptCursorPos);
2600 SetCursorPos (ptCursorPos);
2601 EnsureVisible (ptCursorPos);*/
2604 m_pTextBuffer->DeleteText (this, ptSelStart1.y, ptSelStart1.x, ptSelEnd1.y, ptSelEnd1.x, CE_ACTION_SENTENCIZE);
2608 m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, text.GetLength(), y, x, CE_ACTION_SENTENCIZE);
2610 ASSERT_VALIDTEXTPOS (ptCursorPos);
2611 SetAnchor (ptCursorPos);
2612 SetSelection (ptSelStart, ptSelEnd);
2613 SetCursorPos (ptCursorPos);
2614 EnsureVisible (ptCursorPos);
2616 m_pTextBuffer->FlushUndoGroup (this);
2621 void CCrystalEditView::OnUpdateEditGotoLastChange( CCmdUI *pCmdUI )
2623 CPoint ptLastChange = m_pTextBuffer->GetLastChangePos();
2624 pCmdUI->Enable( ptLastChange.x > 0 && ptLastChange.y > -1 );
2627 void CCrystalEditView::OnEditGotoLastChange()
2629 CPoint ptLastChange = m_pTextBuffer->GetLastChangePos();
2630 if( ptLastChange.x < 0 || ptLastChange.y < 0 )
2634 SetSelection( ptLastChange, ptLastChange );
2635 SetCursorPos( ptLastChange );
2636 EnsureVisible( ptLastChange );
2640 int CCrystalEditView::SpellGetLine (struct SpellData_t *pdata)
2642 CCrystalEditView *pView = static_cast<CCrystalEditView*>(pdata->pUserData);
2643 static TCHAR szBuffer[4096];
2645 if (pdata->nRow < pView->GetLineCount ())
2647 int nCount = pView->GetLineLength (pdata->nRow) + 1;
2648 /*if (pdata->pszBuffer)
2649 free (pdata->pszBuffer);
2650 pdata->pszBuffer = (LPTSTR) malloc (nCount + 2);*/
2651 pdata->pszBuffer = szBuffer;
2652 *pdata->pszBuffer = _T ('^');
2654 _tcscpy_s (pdata->pszBuffer + 1, sizeof(szBuffer)-1, pView->GetLineChars (pdata->nRow));
2656 pdata->pszBuffer[nCount++] = _T (' ');
2657 pdata->pszBuffer[nCount++] = _T ('\n');
2658 pdata->pszBuffer[nCount] = _T ('\0');
2662 pdata->pszBuffer = szBuffer;
2663 *pdata->pszBuffer = _T ('\0');
2667 int CCrystalEditView::SpellNotify (int nEvent, struct SpellData_t *pdata)
2669 CCrystalEditView *pView = static_cast<CCrystalEditView*>(pdata->pUserData);
2670 CPoint ptStartPos, ptEndPos;
2675 ptStartPos.x = pdata->nColumn - 1;
2676 ptStartPos.y = pdata->nRow - 1;
2677 ptEndPos.x = pdata->nColumn - 1 + static_cast<LONG>(_tcslen (pdata->pszWord));
2678 ptEndPos.y = pdata->nRow - 1;
2679 if (!pView->IsValidTextPos (ptStartPos))
2680 if (ptStartPos.x > 0)
2684 if (!pView->IsValidTextPos (ptEndPos))
2689 pView->SetAnchor (ptStartPos);
2690 pView->SetSelection (ptStartPos, ptEndPos);
2691 pView->SetCursorPos (ptStartPos);
2692 pView->EnsureVisible (ptStartPos);
2695 if (pView->IsSelection ())
2698 pView->GetSelection (ptStartPos, ptEndPos);
2699 pView->m_pTextBuffer->DeleteText (pView, ptStartPos.y, ptStartPos.x, ptEndPos.y, ptEndPos.x, CE_ACTION_SPELL);
2700 pView->m_pTextBuffer->InsertText (pView, ptStartPos.y, ptStartPos.x, pdata->pszWord, _tcslen(pdata->pszWord), y, x, CE_ACTION_SPELL);
2703 pView->SetAnchor (ptEndPos);
2704 pView->SetSelection (ptEndPos, ptEndPos);
2705 pView->SetCursorPos (ptEndPos);
2709 ptStartPos = pView->GetCursorPos ();
2710 pView->SetAnchor (ptStartPos);
2711 pView->SetSelection (ptStartPos, ptStartPos);
2712 pView->SetCursorPos (ptStartPos);
2713 pView->EnsureVisible (ptStartPos);
2714 ::MessageBox (pdata->hParent, _T ("Spellchecking finished."), _T ("WIspell"), MB_OK|MB_ICONINFORMATION);
2719 HMODULE CCrystalEditView::hSpellDll = nullptr;
2720 TCHAR CCrystalEditView::szWIspellPath[_MAX_PATH];
2721 SpellData CCrystalEditView::spellData;
2722 int (*CCrystalEditView::SpellInit) (SpellData*);
2723 int (*CCrystalEditView::SpellCheck) (SpellData*);
2724 int (*CCrystalEditView::SpellConfig) (SpellData*);
2726 bool CCrystalEditView::LoadSpellDll (bool bAlert /*= true*/)
2728 if (hSpellDll != nullptr)
2730 CString sPath = szWIspellPath;
2731 if (!sPath.IsEmpty () && sPath[sPath.GetLength () - 1] != _T('\\'))
2733 sPath += _T ("wispell.dll");
2734 hSpellDll = LoadLibrary (sPath);
2735 if (hSpellDll != nullptr)
2737 SpellInit = (int (*) (SpellData*)) GetProcAddress (hSpellDll, "SpellInit");
2738 SpellCheck = (int (*) (SpellData*)) GetProcAddress (hSpellDll, "SpellCheck");
2739 SpellConfig = (int (*) (SpellData*)) GetProcAddress (hSpellDll, "SpellConfig");
2741 SpellInit (&spellData);
2742 _tcscpy_s (spellData.szIspell, szWIspellPath);
2743 spellData.GetLine = SpellGetLine;
2744 spellData.Notify = SpellNotify;
2748 SpellInit = SpellCheck = SpellConfig = nullptr;
2750 ::MessageBox (AfxGetMainWnd ()->GetSafeHwnd (), _T ("Error loading \"wispell.dll\"."), _T ("Error"), MB_OK|MB_ICONEXCLAMATION);
2752 return hSpellDll != nullptr;
2755 void CCrystalEditView::
2756 OnUpdateToolsSpelling (CCmdUI * pCmdUI)
2758 CPoint ptCursorPos = GetCursorPos ();
2759 int nLines = GetLineCount () - 1;
2760 pCmdUI->Enable (LoadSpellDll (false) && ptCursorPos.y < nLines);
2763 void CCrystalEditView::
2766 CPoint ptCursorPos = GetCursorPos ();
2767 if (LoadSpellDll () && ptCursorPos.y < GetLineCount ())
2769 spellData.hParent = GetSafeHwnd ();
2770 spellData.nRow = ptCursorPos.y;
2771 spellData.pUserData = (LPVOID) (LPCVOID) this;
2772 spellData.pszBuffer = nullptr;
2773 m_pTextBuffer->BeginUndoGroup ();
2774 if (SpellCheck (&spellData) == IDCANCEL)
2776 m_pTextBuffer->FlushUndoGroup (this);
2780 m_pTextBuffer->FlushUndoGroup (this);
2781 /*if (spellData.pszBuffer)
2782 free (spellData.pszBuffer);*/
2786 void CCrystalEditView::
2787 OnUpdateToolsCharCoding (CCmdUI * pCmdUI)
2789 pCmdUI->Enable (IsSelection ());
2792 void CCrystalEditView::
2793 OnToolsCharCoding ()
2798 CPoint ptCursorPos = GetCursorPos ();
2799 auto [ptSelStart, ptSelEnd] = GetSelection ();
2801 GetText (ptSelStart, ptSelEnd, sText);
2803 dlg.m_sOriginal = sText;
2804 LPTSTR pszEnd = dlg.m_sOriginal.GetBuffer (dlg.m_sOriginal.GetLength () + 1);
2805 for (int i = 0; i < 13; i++)
2807 pszEnd = _tcschr (pszEnd, _T ('\n'));
2808 if (pszEnd != nullptr)
2813 if (pszEnd != nullptr)
2814 *pszEnd = _T ('\0');
2815 dlg.m_sOriginal.ReleaseBuffer ();
2816 if (dlg.DoModal () != IDOK)
2818 LPTSTR pszNew = nullptr;
2819 if (!iconvert_new (sText, &pszNew, dlg.m_nSource, dlg.m_nDest, dlg.m_bAlpha))
2821 ASSERT (pszNew != nullptr);
2822 m_pTextBuffer->BeginUndoGroup ();
2824 m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_RECODE);
2827 m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, pszNew, _tcslen(pszNew), y, x, CE_ACTION_RECODE);
2829 if (IsValidTextPos (ptCursorPos))
2831 ASSERT_VALIDTEXTPOS (ptCursorPos);
2832 SetAnchor (ptCursorPos);
2833 SetSelection (ptSelStart, ptSelEnd);
2834 SetCursorPos (ptCursorPos);
2835 EnsureVisible (ptCursorPos);
2837 m_pTextBuffer->FlushUndoGroup (this);
2839 if (pszNew != nullptr)
2844 void CCrystalEditView::
2847 if (!IsSelection ())
2848 MoveWordRight (true);
2851 auto [ptSelStart, ptSelEnd] = GetSelection ();
2853 m_pTextBuffer->BeginUndoGroup ();
2855 m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_DELETE);
2857 ASSERT_VALIDTEXTPOS (ptSelStart);
2858 SetAnchor (ptSelStart);
2859 SetSelection (ptSelStart, ptSelStart);
2860 SetCursorPos (ptSelStart);
2861 EnsureVisible (ptSelStart);
2863 m_pTextBuffer->FlushUndoGroup (this);
2867 void CCrystalEditView::
2868 OnEditDeleteWordBack ()
2870 if (!IsSelection ())
2871 MoveWordLeft (true);
2874 auto [ptSelStart, ptSelEnd] = GetSelection ();
2876 m_pTextBuffer->BeginUndoGroup ();
2878 m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_DELETE);
2880 ASSERT_VALIDTEXTPOS (ptSelStart);
2881 SetAnchor (ptSelStart);
2882 SetSelection (ptSelStart, ptSelStart);
2883 SetCursorPos (ptSelStart);
2884 EnsureVisible (ptSelStart);
2886 m_pTextBuffer->FlushUndoGroup (this);
2890 void CCrystalEditView::
2891 OnKillFocus (CWnd * pNewWnd)
2893 m_bMergeUndo = false;
2894 CCrystalTextView::OnKillFocus (pNewWnd);
2897 void CCrystalEditView::OnCharLeft()
2899 m_bMergeUndo = false;
2900 CCrystalTextView::OnCharLeft();
2903 void CCrystalEditView::OnExtCharLeft()
2905 m_bMergeUndo = false;
2906 CCrystalTextView::OnExtCharLeft();
2909 void CCrystalEditView::OnCharRight()
2911 m_bMergeUndo = false;
2912 CCrystalTextView::OnCharRight();
2915 void CCrystalEditView::OnExtCharRight()
2917 m_bMergeUndo = false;
2918 CCrystalTextView::OnExtCharRight();
2921 void CCrystalEditView::OnWordLeft()
2923 m_bMergeUndo = false;
2924 CCrystalTextView::OnWordLeft();
2927 void CCrystalEditView::OnExtWordLeft()
2929 m_bMergeUndo = false;
2930 CCrystalTextView::OnExtWordLeft();
2933 void CCrystalEditView::OnWordRight()
2935 m_bMergeUndo = false;
2936 CCrystalTextView::OnWordRight();
2939 void CCrystalEditView::OnExtWordRight()
2941 m_bMergeUndo = false;
2942 CCrystalTextView::OnExtWordRight();
2945 void CCrystalEditView::OnLineUp()
2947 m_bMergeUndo = false;
2948 CCrystalTextView::OnLineUp();
2951 void CCrystalEditView::OnExtLineUp()
2953 m_bMergeUndo = false;
2954 CCrystalTextView::OnExtLineUp();
2957 void CCrystalEditView::OnLineDown()
2959 m_bMergeUndo = false;
2960 CCrystalTextView::OnLineDown();
2963 void CCrystalEditView::OnExtLineDown()
2965 m_bMergeUndo = false;
2966 CCrystalTextView::OnExtLineDown();
2969 void CCrystalEditView::OnPageUp()
2971 m_bMergeUndo = false;
2972 CCrystalTextView::OnPageUp();
2975 void CCrystalEditView::OnExtPageUp()
2977 m_bMergeUndo = false;
2978 CCrystalTextView::OnExtPageUp();
2981 void CCrystalEditView::OnPageDown()
2983 m_bMergeUndo = false;
2984 CCrystalTextView::OnPageDown();
2987 void CCrystalEditView::OnExtPageDown()
2989 m_bMergeUndo = false;
2990 CCrystalTextView::OnExtPageDown();
2993 void CCrystalEditView::OnLineEnd()
2995 m_bMergeUndo = false;
2996 CCrystalTextView::OnLineEnd();
2999 void CCrystalEditView::OnExtLineEnd()
3001 m_bMergeUndo = false;
3002 CCrystalTextView::OnExtLineEnd();
3005 void CCrystalEditView::OnHome()
3007 m_bMergeUndo = false;
3008 CCrystalTextView::OnHome();
3011 void CCrystalEditView::OnExtHome()
3013 m_bMergeUndo = false;
3014 CCrystalTextView::OnExtHome();
3017 void CCrystalEditView::OnTextBegin()
3019 m_bMergeUndo = false;
3020 CCrystalTextView::OnTextBegin();
3023 void CCrystalEditView::OnExtTextBegin()
3025 m_bMergeUndo = false;
3026 CCrystalTextView::OnExtTextBegin();
3029 void CCrystalEditView::OnTextEnd()
3031 m_bMergeUndo = false;
3032 CCrystalTextView::OnTextEnd();
3035 void CCrystalEditView::OnExtTextEnd()
3037 m_bMergeUndo = false;
3038 CCrystalTextView::OnExtTextEnd();
3041 void CCrystalEditView::OnLButtonDown(UINT nFlags, CPoint point)
3043 m_bMergeUndo = false;
3044 CCrystalTextView::OnLButtonDown(nFlags, point);
3047 void CCrystalEditView::OnRButtonDown(UINT nFlags, CPoint point)
3049 m_bMergeUndo = false;
3050 CCrystalTextView::OnRButtonDown(nFlags, point);
3053 ////////////////////////////////////////////////////////////////////////////