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_pEditReplaceDlg(nullptr)
128 memset((static_cast<CCrystalTextView*>(this))+1, 0, sizeof(*this) - sizeof(class CCrystalTextView)); // AFX_ZERO_INIT_OBJECT (CCrystalTextView)
129 m_bAutoIndent = true;
130 m_mapExpand = new CMap<CString, LPCTSTR, CString, LPCTSTR> (10);
131 m_bMergeUndo = false;
132 m_bDisableBSAtSOL = false;
135 CCrystalEditView:: ~CCrystalEditView ()
138 delete m_pEditReplaceDlg;
141 bool CCrystalEditView::
142 DoSetTextType (CrystalLineParser::TextDefinition *def)
144 m_CurSourceDef = def;
145 SetAutoIndent ((def->flags & SRCOPT_AUTOINDENT) != 0);
146 SetDisableBSAtSOL ((def->flags & SRCOPT_BSATBOL) == 0);
147 m_mapExpand->RemoveAll ();
149 CString sKey = AfxGetApp ()->m_pszRegistryKey;
150 sKey += _T("\\") EDITPAD_SECTION _T("\\");
152 sKey += _T ("\\Expand");
153 if (reg.Open (HKEY_CURRENT_USER, sKey, KEY_READ))
157 if (reg.FindFirstValue (pszValue, ®Val))
161 if (RegValGetString (®Val, sData))
162 m_mapExpand->SetAt (pszValue, sData);
163 while (reg.FindNextValue (pszValue, ®Val));
167 return CCrystalTextView::DoSetTextType (def);
170 BEGIN_MESSAGE_MAP (CCrystalEditView, CCrystalTextView)
171 //{{AFX_MSG_MAP(CCrystalEditView)
172 ON_COMMAND (ID_EDIT_PASTE, OnEditPaste)
173 ON_UPDATE_COMMAND_UI (ID_EDIT_CUT, OnUpdateEditCut)
174 ON_COMMAND (ID_EDIT_CUT, OnEditCut)
175 ON_UPDATE_COMMAND_UI (ID_EDIT_PASTE, OnUpdateEditPaste)
176 ON_COMMAND (ID_EDIT_DELETE, OnEditDelete)
178 ON_COMMAND (ID_EDIT_DELETE_BACK, OnEditDeleteBack)
179 ON_COMMAND (ID_EDIT_UNTAB, OnEditUntab)
180 ON_COMMAND (ID_EDIT_TAB, OnEditTab)
181 ON_COMMAND (ID_EDIT_SWITCH_OVRMODE, OnEditSwitchOvrmode)
182 ON_UPDATE_COMMAND_UI (ID_EDIT_SWITCH_OVRMODE, OnUpdateEditSwitchOvrmode)
185 ON_COMMAND (ID_EDIT_REPLACE, OnEditReplace)
186 ON_UPDATE_COMMAND_UI (ID_EDIT_UNDO, OnUpdateEditUndo)
187 ON_COMMAND (ID_EDIT_UNDO, OnEditUndo)
188 ON_UPDATE_COMMAND_UI (ID_EDIT_REDO, OnUpdateEditRedo)
189 ON_COMMAND (ID_EDIT_REDO, OnEditRedo)
190 ON_UPDATE_COMMAND_UI (ID_EDIT_AUTOCOMPLETE, OnUpdateEditAutoComplete)
191 ON_COMMAND (ID_EDIT_AUTOCOMPLETE, OnEditAutoComplete)
192 ON_UPDATE_COMMAND_UI (ID_EDIT_AUTOEXPAND, OnUpdateEditAutoExpand)
193 ON_COMMAND (ID_EDIT_AUTOEXPAND, OnEditAutoExpand)
194 ON_UPDATE_COMMAND_UI (ID_EDIT_LOWERCASE, OnUpdateEditLowerCase)
195 ON_COMMAND (ID_EDIT_LOWERCASE, OnEditLowerCase)
196 ON_UPDATE_COMMAND_UI (ID_EDIT_UPPERCASE, OnUpdateEditUpperCase)
197 ON_COMMAND (ID_EDIT_UPPERCASE, OnEditUpperCase)
198 ON_UPDATE_COMMAND_UI (ID_EDIT_SWAPCASE, OnUpdateEditSwapCase)
199 ON_COMMAND (ID_EDIT_SWAPCASE, OnEditSwapCase)
200 ON_UPDATE_COMMAND_UI (ID_EDIT_SWAPCASE, OnUpdateEditSwapCase)
201 ON_COMMAND (ID_EDIT_SWAPCASE, OnEditSwapCase)
202 ON_UPDATE_COMMAND_UI (ID_EDIT_CAPITALIZE, OnUpdateEditCapitalize)
203 ON_COMMAND (ID_EDIT_CAPITALIZE, OnEditCapitalize)
204 ON_UPDATE_COMMAND_UI (ID_EDIT_SENTENCE, OnUpdateEditSentence)
205 ON_COMMAND (ID_EDIT_SENTENCE, OnEditSentence)
206 ON_UPDATE_COMMAND_UI(ID_EDIT_GOTO_LAST_CHANGE, OnUpdateEditGotoLastChange)
207 ON_COMMAND(ID_EDIT_GOTO_LAST_CHANGE, OnEditGotoLastChange)
208 ON_COMMAND(ID_EDIT_DELETE_WORD, OnEditDeleteWord)
209 ON_COMMAND(ID_EDIT_DELETE_WORD_BACK, OnEditDeleteWordBack)
212 ON_UPDATE_COMMAND_UI (ID_EDIT_INDICATOR_READ, OnUpdateIndicatorRead)
213 ON_UPDATE_COMMAND_UI (ID_INDICATOR_OVR, OnUpdateIndicatorOvr)
214 ON_UPDATE_COMMAND_UI (ID_EDIT_INDICATOR_POSITION, OnUpdateIndicatorPosition)
215 ON_UPDATE_COMMAND_UI (ID_TOOLS_SPELLING, OnUpdateToolsSpelling)
216 ON_COMMAND (ID_TOOLS_SPELLING, OnToolsSpelling)
217 ON_UPDATE_COMMAND_UI (ID_TOOLS_CHARCODING, OnUpdateToolsCharCoding)
218 ON_COMMAND (ID_TOOLS_CHARCODING, OnToolsCharCoding)
219 // cursor movement commands
220 ON_COMMAND (ID_EDIT_CHAR_LEFT, OnCharLeft)
221 ON_COMMAND (ID_EDIT_EXT_CHAR_LEFT, OnExtCharLeft)
222 ON_COMMAND (ID_EDIT_CHAR_RIGHT, OnCharRight)
223 ON_COMMAND (ID_EDIT_EXT_CHAR_RIGHT, OnExtCharRight)
224 ON_COMMAND (ID_EDIT_WORD_LEFT, OnWordLeft)
225 ON_COMMAND (ID_EDIT_EXT_WORD_LEFT, OnExtWordLeft)
226 ON_COMMAND (ID_EDIT_WORD_RIGHT, OnWordRight)
227 ON_COMMAND (ID_EDIT_EXT_WORD_RIGHT, OnExtWordRight)
228 ON_COMMAND (ID_EDIT_LINE_UP, OnLineUp)
229 ON_COMMAND (ID_EDIT_EXT_LINE_UP, OnExtLineUp)
230 ON_COMMAND (ID_EDIT_LINE_DOWN, OnLineDown)
231 ON_COMMAND (ID_EDIT_EXT_LINE_DOWN, OnExtLineDown)
232 ON_COMMAND (ID_EDIT_SCROLL_UP, ScrollUp)
233 ON_COMMAND (ID_EDIT_SCROLL_DOWN, ScrollDown)
234 ON_COMMAND (ID_EDIT_PAGE_UP, OnPageUp)
235 ON_COMMAND (ID_EDIT_EXT_PAGE_UP, OnExtPageUp)
236 ON_COMMAND (ID_EDIT_PAGE_DOWN, OnPageDown)
237 ON_COMMAND (ID_EDIT_EXT_PAGE_DOWN, OnExtPageDown)
238 ON_COMMAND (ID_EDIT_LINE_END, OnLineEnd)
239 ON_COMMAND (ID_EDIT_EXT_LINE_END, OnExtLineEnd)
240 ON_COMMAND (ID_EDIT_HOME, OnHome)
241 ON_COMMAND (ID_EDIT_EXT_HOME, OnExtHome)
242 ON_COMMAND (ID_EDIT_TEXT_BEGIN, OnTextBegin)
243 ON_COMMAND (ID_EDIT_EXT_TEXT_BEGIN, OnExtTextBegin)
244 ON_COMMAND (ID_EDIT_TEXT_END, OnTextEnd)
245 ON_COMMAND (ID_EDIT_EXT_TEXT_END, OnExtTextEnd)
251 /////////////////////////////////////////////////////////////////////////////
252 // CCrystalEditView message handlers
254 void CCrystalEditView::ResetView ()
256 // m_bAutoIndent = true;
258 m_bLastReplace = false;
259 CCrystalTextView::ResetView ();
262 bool CCrystalEditView::
265 if (m_pTextBuffer == nullptr)
267 return !m_pTextBuffer->GetReadOnly ();
270 void CCrystalEditView::
276 void CCrystalEditView::
277 OnUpdateEditPaste (CCmdUI * pCmdUI)
279 pCmdUI->Enable (TextInClipboard ());
282 void CCrystalEditView::
283 OnUpdateEditCut (CCmdUI * pCmdUI)
285 pCmdUI->Enable (IsSelection ());
288 void CCrystalEditView::
294 bool CCrystalEditView::
295 DeleteCurrentSelection ()
299 auto [ptSelStart, ptSelEnd] = GetSelection ();
301 CPoint ptCursorPos = ptSelStart;
302 ASSERT_VALIDTEXTPOS (ptCursorPos);
303 SetAnchor (ptCursorPos);
304 SetSelection (ptCursorPos, ptCursorPos);
305 SetCursorPos (ptCursorPos);
306 EnsureVisible (ptCursorPos);
309 m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_DELSEL);
315 bool CCrystalEditView::
316 DeleteCurrentColumnSelection (int nAction, bool bFlushUndoGroup /*= true*/, bool bUpdateCursorPosition /*= true*/)
321 m_pTextBuffer->BeginUndoGroup ();
323 auto [ptSelStart, ptSelEnd] = GetSelection ();
325 int nSelLeft, nSelRight;
326 GetColumnSelection (m_ptDrawSelStart.y, nSelLeft, nSelRight);
327 CPoint ptCursorPos(nSelLeft, m_ptDrawSelStart.y);
328 int nStartLine = m_ptDrawSelStart.y;
329 int nEndLine = m_ptDrawSelEnd.y;
331 if (GetEnableHideLines ())
333 for (int nLineIndex = nEndLine; nLineIndex >= nStartLine; nLineIndex--)
335 if (!(GetLineFlags (nLineIndex) & LF_INVISIBLE))
337 int nEndLine2 = nLineIndex;
339 for (nStartLine2 = nLineIndex - 1; nStartLine2 >= nStartLine; nStartLine2--)
341 if (GetLineFlags (nStartLine2) & LF_INVISIBLE)
345 nLineIndex = nStartLine2;
346 DeleteCurrentColumnSelection2 (nStartLine2, nEndLine2, nAction);
352 DeleteCurrentColumnSelection2 (ptSelStart.y, ptSelEnd.y, nAction);
356 m_pTextBuffer->FlushUndoGroup (this);
358 if (bUpdateCursorPosition)
360 ASSERT_VALIDTEXTPOS (ptCursorPos);
361 SetAnchor (ptCursorPos);
362 SetSelection (ptCursorPos, ptCursorPos);
363 SetCursorPos (ptCursorPos);
364 EnsureVisible (ptCursorPos);
371 bool CCrystalEditView::
372 DeleteCurrentColumnSelection2 (int nStartLine, int nEndLine, int nAction)
375 for (int L = nStartLine; L <= nEndLine; L++)
376 nBufSize += GetFullLineLength (L);
379 LPTSTR p, pszBuf = text.GetBuffer (nBufSize);
382 for (int I = nStartLine; I <= nEndLine; I++)
384 LPCTSTR pszChars = GetLineChars (I);
385 int nSelLeft, nSelRight;
386 GetColumnSelection (I, nSelLeft, nSelRight);
389 memcpy (p, pszChars, sizeof (TCHAR) * nSelLeft);
392 int nLineLength = GetFullLineLength (I);
393 if (nSelRight < nLineLength)
395 memcpy (p, pszChars + nSelRight, sizeof (TCHAR) * (nLineLength - nSelRight));
396 p += nLineLength - nSelRight;
401 text.ReleaseBuffer (static_cast<int>(p - pszBuf));
404 if (nEndLine + 1 < GetLineCount())
405 m_pTextBuffer->DeleteText (this, nStartLine, 0, nEndLine + 1, 0, nAction);
407 m_pTextBuffer->DeleteText (this, nStartLine, 0, nEndLine, GetLineLength (nEndLine), nAction);
409 m_pTextBuffer->InsertText (this, nStartLine, 0, text, text.GetLength(), y, x, nAction);
414 bool CCrystalEditView::
415 InsertColumnText (int nLine, int nPos, LPCTSTR pszText, int cchText, int nAction, bool bFlushUndoGroup)
417 if (pszText == nullptr || cchText == 0)
420 CTypedPtrArray<CPtrArray, LPTSTR> aLines;
421 CDWordArray aLineLengths;
423 for (int nTextPos = 0; nTextPos < cchText; )
426 aLines.Add ((LPTSTR)&pszText[nTextPos]);
428 for (; nTextPos < cchText; nTextPos++)
430 ch = pszText[nTextPos];
431 if (ch=='\r' || ch=='\n'/*iseol(pszText[nTextPos]*/)
435 aLineLengths.Add (nTextPos - nLineBegin);
437 // advance after EOL of line
438 if (ch=='\r' && pszText[nTextPos + 1]=='\n'/*isdoseol(&pszText[nTextPos])*/)
440 else if (ch=='\r' || ch=='\n'/*iseol(pszText[nTextPos])*/)
442 nLineBegin = nTextPos;
447 int nLineCount = GetLineCount ();
448 ASSERT(aLineLengths.GetSize() < INT_MAX);
449 int nPasteTextLineCount = static_cast<int>(aLineLengths.GetSize ());
450 for (L = 0; L < nPasteTextLineCount; L++)
452 if (nLine + L < nLineCount)
453 nBufSize += GetFullLineLength (nLine + L) + aLineLengths[L] + 2;
455 nBufSize += aLineLengths[L] + 2;
458 LPTSTR pszBuf = new TCHAR[nBufSize];
460 int nTopBeginCharPos = CalculateActualOffset (nLine, nPos, true);
461 for (L = 0; L < nPasteTextLineCount; L++)
463 if (nLine + L < nLineCount)
465 int nLineLength = GetFullLineLength (nLine + L);
466 LPCTSTR pszChars = GetLineChars (nLine + L);
467 int nOffset = ApproxActualOffset (nLine + L, nTopBeginCharPos);
468 memcpy(p, pszChars, nOffset * sizeof(TCHAR));
470 memcpy(p, aLines[L], aLineLengths[L] * sizeof(TCHAR));
471 p += aLineLengths[L];
472 memcpy(p, pszChars + nOffset, (nLineLength - nOffset) * sizeof(TCHAR));
473 p += nLineLength - nOffset;
477 CString sEol = m_pTextBuffer->GetDefaultEol ();
478 if (p > pszBuf && p[-1] != '\r' && p[-1] != '\n')
480 memcpy(p, sEol, sEol.GetLength () * sizeof(TCHAR));
481 p += sEol.GetLength ();
483 memcpy(p, aLines[L], aLineLengths[L] * sizeof(TCHAR));
484 p += aLineLengths[L];
485 memcpy(p, sEol, sEol.GetLength () * sizeof(TCHAR));
486 p += sEol.GetLength ();
492 m_pTextBuffer->BeginUndoGroup ();
494 if (nLine + nPasteTextLineCount + 1 < nLineCount)
495 m_pTextBuffer->DeleteText (this, nLine, 0, nLine + nPasteTextLineCount, 0, nAction);
496 else if (nLine != nLineCount - 1 || GetLineLength (nLineCount - 1) != 0)
497 m_pTextBuffer->DeleteText (this, nLine, 0, nLineCount - 1, GetLineLength (nLineCount - 1), nAction);
499 m_pTextBuffer->InsertText (this, nLine, 0, pszBuf, static_cast<int>(p - pszBuf), x, y, nAction);
502 m_pTextBuffer->FlushUndoGroup (this);
509 void CCrystalEditView::
512 if (!QueryEditable ())
514 if (m_pTextBuffer == nullptr)
518 bool bColumnSelection;
519 if (GetFromClipboard (text, bColumnSelection))
521 m_pTextBuffer->BeginUndoGroup ();
526 auto [ptSelStart, ptSelEnd] = GetSelection ();
528 ptCursorPos = ptSelStart;
529 /*SetAnchor (ptCursorPos);
530 SetSelection (ptCursorPos, ptCursorPos);
531 SetCursorPos (ptCursorPos);
532 EnsureVisible (ptCursorPos);*/
535 if (!m_bRectangularSelection)
536 m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_PASTE);
538 DeleteCurrentColumnSelection (CE_ACTION_PASTE, false, false);
542 ptCursorPos = GetCursorPos ();
544 ASSERT_VALIDTEXTPOS (ptCursorPos);
546 if (!bColumnSelection)
549 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, text, text.GetLength(), y, x, CE_ACTION_PASTE); // [JRT]
554 InsertColumnText (ptCursorPos.y, ptCursorPos.x, text, text.GetLength(), CE_ACTION_PASTE, false);
556 ASSERT_VALIDTEXTPOS (ptCursorPos);
557 SetAnchor (ptCursorPos);
558 SetSelection (ptCursorPos, ptCursorPos);
559 SetCursorPos (ptCursorPos);
560 EnsureVisible (ptCursorPos);
562 m_pTextBuffer->FlushUndoGroup (this);
566 void CCrystalEditView::
569 if (!QueryEditable ())
571 if (m_pTextBuffer == nullptr)
576 auto [ptSelStart, ptSelEnd] = GetSelection ();
578 if (!m_bRectangularSelection)
579 GetText (ptSelStart, ptSelEnd, text);
581 GetTextInColumnSelection (text);
582 PutToClipboard (text, text.GetLength());
584 if (!m_bRectangularSelection)
586 CPoint ptCursorPos = ptSelStart;
587 ASSERT_VALIDTEXTPOS (ptCursorPos);
588 SetAnchor (ptCursorPos);
589 SetSelection (ptCursorPos, ptCursorPos);
590 SetCursorPos (ptCursorPos);
591 EnsureVisible (ptCursorPos);
593 m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_CUT); // [JRT]
596 DeleteCurrentColumnSelection (CE_ACTION_CUT);
599 void CCrystalEditView::
602 if (!QueryEditable () || m_pTextBuffer == nullptr)
605 auto [ptSelStart, ptSelEnd] = GetSelection ();
606 if (ptSelStart == ptSelEnd)
608 if (ptSelEnd.x == GetLineLength (ptSelEnd.y))
610 if (ptSelEnd.y == GetLineCount () - 1)
617 auto pIterChar = ICUBreakIterator::getCharacterBreakIterator(GetLineChars(ptSelEnd.y), GetLineLength(ptSelEnd.y));
618 ptSelEnd.x = pIterChar->following(ptSelEnd.x);
622 if (!m_bRectangularSelection)
624 CPoint ptCursorPos = ptSelStart;
625 ASSERT_VALIDTEXTPOS (ptCursorPos);
626 SetAnchor (ptCursorPos);
627 SetSelection (ptCursorPos, ptCursorPos);
628 SetCursorPos (ptCursorPos);
629 EnsureVisible (ptCursorPos);
631 m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_DELETE); // [JRT]
634 DeleteCurrentColumnSelection (CE_ACTION_DELETE);
637 void CCrystalEditView::
638 OnChar (UINT nChar, UINT nRepCnt, UINT nFlags)
641 // check if incremental search is active before call to CCrystalTextView::OnChar()
642 bool bIncrementalSearch = m_bIncrementalSearchForward || m_bIncrementalSearchBackward;
644 CCrystalTextView::OnChar (static_cast<wchar_t>(nChar), nRepCnt, nFlags);
646 // if we are in incremental search mode ignore the character
647 if( m_bIncrementalSearchForward || m_bIncrementalSearchBackward )
651 // if we *were* in incremental search mode and CCrystalTextView::OnChar()
652 // exited it the ignore the character (VK_RETURN)
653 if( bIncrementalSearch && !m_bIncrementalSearchForward && !m_bIncrementalSearchBackward )
657 if ((::GetAsyncKeyState (VK_LBUTTON) & 0x8000) != 0 ||
658 (::GetAsyncKeyState (VK_RBUTTON) & 0x8000) != 0)
661 if (nChar == VK_RETURN)
665 CPoint ptCursorPos = GetCursorPos ();
666 ASSERT_VALIDTEXTPOS (ptCursorPos);
667 if (ptCursorPos.y < GetLineCount () - 1)
672 ASSERT_VALIDTEXTPOS (ptCursorPos);
673 SetSelection (ptCursorPos, ptCursorPos);
674 SetAnchor (ptCursorPos);
675 SetCursorPos (ptCursorPos);
676 EnsureVisible (ptCursorPos);
681 m_pTextBuffer->BeginUndoGroup(m_bMergeUndo);
682 m_bMergeUndo = false;
684 if (QueryEditable () && m_pTextBuffer != nullptr)
689 auto [ptSelStart, ptSelEnd] = GetSelection ();
691 ptCursorPos = ptSelStart;
692 /*SetAnchor (ptCursorPos);
693 SetSelection (ptCursorPos, ptCursorPos);
694 SetCursorPos (ptCursorPos);
695 EnsureVisible (ptCursorPos);*/
698 m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_TYPING);
701 ptCursorPos = GetCursorPos ();
702 ASSERT_VALIDTEXTPOS (ptCursorPos);
703 LPCTSTR pszText = m_pTextBuffer->GetDefaultEol();
704 int cchText = (int) _tcslen(pszText);
707 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszText, cchText, y, x, CE_ACTION_TYPING); // [JRT]
711 ASSERT_VALIDTEXTPOS (ptCursorPos);
712 SetSelection (ptCursorPos, ptCursorPos);
713 SetAnchor (ptCursorPos);
714 SetCursorPos (ptCursorPos);
715 EnsureVisible (ptCursorPos);
718 m_pTextBuffer->FlushUndoGroup (this);
721 // Accept control characters other than [\t\n\r] through Alt-Numpad
723 || GetKeyState(VK_CONTROL) >= 0 &&
724 (nChar != 27 || GetKeyState(VK_ESCAPE) >= 0) &&
725 nChar != 9 && nChar != 10 && nChar != 13)
727 if (QueryEditable () && m_pTextBuffer != nullptr)
729 m_pTextBuffer->BeginUndoGroup (m_bMergeUndo);
732 auto [ptSelStart, ptSelEnd] = GetSelection ();
734 if (ptSelStart != ptSelEnd)
736 ptCursorPos = ptSelStart;
739 auto [ptSelStart1, ptSelEnd1] = GetSelection ();
741 /*SetAnchor (ptCursorPos);
742 SetSelection (ptCursorPos, ptCursorPos);
743 SetCursorPos (ptCursorPos);
744 EnsureVisible (ptCursorPos);*/
747 m_pTextBuffer->DeleteText (this, ptSelStart1.y, ptSelStart1.x, ptSelEnd1.y, ptSelEnd1.x, CE_ACTION_TYPING);
752 ptCursorPos = GetCursorPos ();
753 if (m_bOvrMode && ptCursorPos.x < GetLineLength (ptCursorPos.y))
754 m_pTextBuffer->DeleteText (this, ptCursorPos.y, ptCursorPos.x, ptCursorPos.y, ptCursorPos.x + 1, CE_ACTION_TYPING); // [JRT]
758 ASSERT_VALIDTEXTPOS (ptCursorPos);
761 pszText[0] = (TCHAR) nChar;
765 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszText, 1, y, x, CE_ACTION_TYPING); // [JRT]
769 ASSERT_VALIDTEXTPOS (ptCursorPos);
770 SetSelection (ptCursorPos, ptCursorPos);
771 SetAnchor (ptCursorPos);
772 SetCursorPos (ptCursorPos);
773 EnsureVisible (ptCursorPos);
775 m_pTextBuffer->FlushUndoGroup (this);
782 // [JRT]: Added Support For "Disable Backspace At Start Of Line"
784 void CCrystalEditView::
788 // if we are in incremental search mode ignore backspace
789 CCrystalTextView::OnEditDeleteBack();
790 if( m_bIncrementalSearchForward || m_bIncrementalSearchBackward )
800 if (!QueryEditable () || m_pTextBuffer == nullptr)
803 CPoint ptCursorPos = GetCursorPos ();
804 CPoint ptCurrentCursorPos = ptCursorPos;
805 bool bDeleted = false;
807 if (!(ptCursorPos.x)) // If At Start Of Line
810 if (!m_bDisableBSAtSOL) // If DBSASOL Is Disabled
813 if (ptCursorPos.y > 0) // If Previous Lines Available
816 ptCursorPos.y--; // Decrement To Previous Line
818 ptCursorPos.x = GetLineLength (
819 ptCursorPos.y); // Set Cursor To End Of Previous Line
821 bDeleted = true; // Set Deleted Flag
826 else // If Caret Not At SOL
829 auto pIterChar = ICUBreakIterator::getCharacterBreakIterator(GetLineChars(ptCursorPos.y), GetLineLength(ptCursorPos.y));
830 ptCursorPos.x = pIterChar->preceding(ptCursorPos.x);
831 bDeleted = true; // Set Deleted Flag
834 if (ptCursorPos.x == 0)
836 if (ptCursorPos.y == 0)
839 ptCursorPos.x = GetLineLength(ptCursorPos.y);
844 ASSERT_VALIDTEXTPOS (ptCursorPos);
845 SetAnchor (ptCursorPos);
846 SetSelection (ptCursorPos, ptCursorPos);
847 SetCursorPos (ptCursorPos);
848 EnsureVisible (ptCursorPos);
852 m_pTextBuffer->DeleteText (this, ptCursorPos.y, ptCursorPos.x, ptCurrentCursorPos.y, ptCurrentCursorPos.x, CE_ACTION_BACKSPACE); // [JRT]
858 void CCrystalEditView::
861 if (!QueryEditable () || m_pTextBuffer == nullptr)
864 bool bTabify = false;
865 CPoint ptSelStart, ptSelEnd;
868 GetSelection (ptSelStart, ptSelEnd);
870 // If we have more than one line selected, tabify sel lines
871 if ( ptSelStart.y != ptSelEnd.y )
877 CPoint ptCursorPos = GetCursorPos ();
878 ASSERT_VALIDTEXTPOS (ptCursorPos);
880 TCHAR pszText[MAX_TAB_LEN + 1] = {0};
881 // If inserting tabs, then initialize the text to a tab.
882 if (m_pTextBuffer->GetInsertTabs())
887 else //...otherwise, built whitespace depending on the location and tab stops
889 int nTabSize = GetTabSize ();
890 int nChars = nTabSize - ptCursorPos.x % nTabSize;
891 for (int i = 0; i < nChars; i++)
893 pszText[nChars] = '\0';
896 // Indent selected lines (multiple lines selected)
899 m_pTextBuffer->BeginUndoGroup ();
901 int nStartLine = ptSelStart.y;
902 int nEndLine = ptSelEnd.y;
906 if (ptSelEnd.y == GetLineCount () - 1)
908 ptSelEnd.x = GetLineLength (ptSelEnd.y);
916 else //...otherwise, do not indent the empty line.
918 SetSelection (ptSelStart, ptSelEnd);
919 SetCursorPos (ptSelEnd);
920 EnsureVisible (ptSelEnd);
922 // Shift selection to right
923 m_bHorzScrollBarLocked = true;
924 for (int L = nStartLine; L <= nEndLine; L++)
927 if (m_pTextBuffer->IsIndentableLine (L))
928 m_pTextBuffer->InsertText (this, L, 0, pszText, (int) _tcslen(pszText), y, x, CE_ACTION_INDENT); // [JRT]
930 m_bHorzScrollBarLocked = false;
931 RecalcHorzScrollBar ();
933 m_pTextBuffer->FlushUndoGroup (this);
937 // Overwrite mode, replace next char with tab/spaces
940 CPoint ptCursorPos1 = GetCursorPos ();
941 ASSERT_VALIDTEXTPOS (ptCursorPos1);
943 int nLineLength = GetLineLength (ptCursorPos1.y);
944 LPCTSTR pszLineChars = GetLineChars (ptCursorPos1.y);
947 if (ptCursorPos1.x < nLineLength)
949 int nTabSize = GetTabSize ();
950 int nChars = nTabSize - CalculateActualOffset(
951 ptCursorPos1.y, ptCursorPos1.x ) % nTabSize;
952 ASSERT (nChars > 0 && nChars <= nTabSize);
956 if (ptCursorPos1.x == nLineLength)
958 if (pszLineChars[ptCursorPos1.x] == _T ('\t'))
966 ASSERT (ptCursorPos1.x <= nLineLength);
967 ASSERT_VALIDTEXTPOS (ptCursorPos1);
969 SetSelection (ptCursorPos1, ptCursorPos1);
970 SetAnchor (ptCursorPos1);
971 SetCursorPos (ptCursorPos1);
972 EnsureVisible (ptCursorPos1);
977 m_pTextBuffer->BeginUndoGroup ();
979 int x, y; // For cursor position
981 // Text selected, no overwrite mode, replace sel with tab
984 auto [ptSelStart1, ptSelEnd1] = GetSelection ();
986 /*SetAnchor (ptCursorPos);
987 SetSelection (ptCursorPos, ptCursorPos);
988 SetCursorPos (ptCursorPos);
989 EnsureVisible (ptCursorPos);*/
992 m_pTextBuffer->DeleteText (this, ptSelStart1.y, ptSelStart1.x, ptSelEnd1.y, ptSelEnd1.x, CE_ACTION_TYPING);
993 m_pTextBuffer->InsertText( this, ptSelStart1.y, ptSelStart1.x, pszText, (int) _tcslen(pszText), y, x, CE_ACTION_TYPING );
995 // No selection, add tab
998 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszText, (int) _tcslen(pszText), y, x, CE_ACTION_TYPING); // [JRT]
1003 ASSERT_VALIDTEXTPOS (ptCursorPos);
1004 SetSelection (ptCursorPos, ptCursorPos);
1005 SetAnchor (ptCursorPos);
1006 SetCursorPos (ptCursorPos);
1007 EnsureVisible (ptCursorPos);
1009 m_pTextBuffer->FlushUndoGroup (this);
1012 void CCrystalEditView::
1015 if (!QueryEditable () || m_pTextBuffer == nullptr)
1018 bool bTabify = false;
1021 auto [ptSelStart, ptSelEnd] = GetSelection ();
1022 bTabify = ptSelStart.y != ptSelEnd.y;
1027 m_pTextBuffer->BeginUndoGroup ();
1029 auto [ptSelStart, ptSelEnd] = GetSelection ();
1030 int nStartLine = ptSelStart.y;
1031 int nEndLine = ptSelEnd.y;
1035 if (ptSelEnd.y == GetLineCount () - 1)
1037 ptSelEnd.x = GetLineLength (ptSelEnd.y);
1047 SetSelection (ptSelStart, ptSelEnd);
1048 SetCursorPos (ptSelEnd);
1049 EnsureVisible (ptSelEnd);
1051 // Shift selection to left
1052 m_bHorzScrollBarLocked = true;
1053 for (int L = nStartLine; L <= nEndLine; L++)
1055 int nLength = GetLineLength (L);
1058 LPCTSTR pszChars = GetLineChars (L);
1059 int nPos = 0, nOffset = 0;
1060 while (nPos < nLength)
1062 if (pszChars[nPos] == _T (' '))
1065 if (++nOffset >= GetTabSize ())
1070 if (pszChars[nPos] == _T ('\t'))
1077 m_pTextBuffer->DeleteText (this, L, 0, L, nPos, CE_ACTION_INDENT); // [JRT]
1081 m_bHorzScrollBarLocked = false;
1082 RecalcHorzScrollBar ();
1084 m_pTextBuffer->FlushUndoGroup (this);
1088 CPoint ptCursorPos = GetCursorPos ();
1089 ASSERT_VALIDTEXTPOS (ptCursorPos);
1090 if (ptCursorPos.x > 0)
1092 int nTabSize = GetTabSize ();
1093 int nOffset = CalculateActualOffset (ptCursorPos.y, ptCursorPos.x);
1094 int nNewOffset = nOffset / nTabSize * nTabSize;
1095 if (nOffset == nNewOffset && nNewOffset > 0)
1096 nNewOffset -= nTabSize;
1097 ASSERT (nNewOffset >= 0);
1099 LPCTSTR pszChars = GetLineChars (ptCursorPos.y);
1100 int nCurrentOffset = 0;
1102 while (nCurrentOffset < nNewOffset)
1104 if (pszChars[I] == _T ('\t'))
1105 nCurrentOffset = nCurrentOffset / nTabSize * nTabSize + nTabSize;
1111 ASSERT (nCurrentOffset == nNewOffset);
1114 ASSERT_VALIDTEXTPOS (ptCursorPos);
1115 SetSelection (ptCursorPos, ptCursorPos);
1116 SetAnchor (ptCursorPos);
1117 SetCursorPos (ptCursorPos);
1118 EnsureVisible (ptCursorPos);
1123 void CCrystalEditView::
1124 OnUpdateIndicatorCol (CCmdUI * pCmdUI)
1126 pCmdUI->Enable (false);
1129 void CCrystalEditView::
1130 OnUpdateIndicatorOvr (CCmdUI * pCmdUI)
1132 pCmdUI->Enable (m_bOvrMode);
1135 void CCrystalEditView::
1136 OnUpdateIndicatorRead (CCmdUI * pCmdUI)
1138 if (m_pTextBuffer == nullptr)
1139 pCmdUI->Enable (false);
1141 pCmdUI->Enable (m_pTextBuffer->GetReadOnly ());
1144 void CCrystalEditView::
1145 OnEditSwitchOvrmode ()
1147 m_bOvrMode = !m_bOvrMode;
1151 void CCrystalEditView::
1152 OnUpdateEditSwitchOvrmode (CCmdUI * pCmdUI)
1154 pCmdUI->SetCheck (m_bOvrMode ? 1 : 0);
1157 DROPEFFECT CEditDropTargetImpl::
1158 OnDragEnter (CWnd * pWnd, COleDataObject * pDataObject, DWORD dwKeyState, CPoint point)
1160 CLIPFORMAT fmt = CCrystalTextView::GetClipTcharTextFormat();
1161 if (!pDataObject->IsDataAvailable (fmt))
1163 if (m_pAlternateDropTarget != nullptr)
1165 DROPEFFECT dwEffect = DROPEFFECT_NONE;
1166 m_pAlternateDropTarget->DragEnter(pDataObject->m_lpDataObject, dwKeyState, { point.x, point.y }, &dwEffect);
1169 m_pOwner->HideDropIndicator ();
1170 return DROPEFFECT_NONE;
1172 m_pOwner->ShowDropIndicator (point);
1173 if (dwKeyState & MK_CONTROL)
1174 return DROPEFFECT_COPY;
1175 return DROPEFFECT_MOVE;
1178 void CEditDropTargetImpl::
1179 OnDragLeave (CWnd * pWnd)
1181 m_pOwner->HideDropIndicator ();
1184 DROPEFFECT CEditDropTargetImpl::
1185 OnDragOver (CWnd * pWnd, COleDataObject * pDataObject, DWORD dwKeyState, CPoint point)
1190 bool bDataSupported = false;
1192 if ((m_pOwner == nullptr) || // If No Owner
1193 (!(m_pOwner->QueryEditable ())) || // Or Not Editable
1194 (m_pOwner->GetDisableDragAndDrop ())) // Or Drag And Drop Disabled
1197 if (m_pAlternateDropTarget != nullptr)
1199 DROPEFFECT dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_LINK;
1200 m_pAlternateDropTarget->DragOver(dwKeyState, { point.x, point.y }, &dwEffect);
1203 m_pOwner->HideDropIndicator (); // Hide Drop Caret
1205 return DROPEFFECT_NONE; // Return DE_NONE
1208 // if ((pDataObject->IsDataAvailable( CF_TEXT ) ) || // If Text Available
1209 // ( pDataObject -> IsDataAvailable( xxx ) ) || // Or xxx Available
1210 // ( pDataObject -> IsDataAvailable( yyy ) ) ) // Or yyy Available
1211 CLIPFORMAT fmt = CCrystalTextView::GetClipTcharTextFormat(); // CF_TEXT or CF_UNICODETEXT
1212 if (pDataObject->IsDataAvailable (fmt)) // If Text Available
1215 bDataSupported = true; // Set Flag
1218 if (!bDataSupported) // If No Supported Formats Available
1221 if (m_pAlternateDropTarget != nullptr)
1223 DROPEFFECT dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_LINK;
1224 m_pAlternateDropTarget->DragOver(dwKeyState, { point.x, point.y }, &dwEffect);
1227 m_pOwner->HideDropIndicator (); // Hide Drop Caret
1229 return DROPEFFECT_NONE; // Return DE_NONE
1232 m_pOwner->ShowDropIndicator (point);
1233 if (dwKeyState & MK_CONTROL)
1234 return DROPEFFECT_COPY;
1235 return DROPEFFECT_MOVE;
1238 BOOL CEditDropTargetImpl::
1239 OnDrop (CWnd * pWnd, COleDataObject * pDataObject, DROPEFFECT dropEffect, CPoint point)
1242 // [JRT] ( m_pOwner -> GetDisableDragAndDrop() ) ) // Or Drag And Drop Disabled
1244 bool bDataSupported = false;
1246 m_pOwner->HideDropIndicator (); // Hide Drop Caret
1248 if ((m_pOwner == nullptr) || // If No Owner
1249 (!(m_pOwner->QueryEditable ())) || // Or Not Editable
1250 (m_pOwner->GetDisableDragAndDrop ())) // Or Drag And Drop Disabled
1253 if (m_pAlternateDropTarget != nullptr)
1255 DROPEFFECT dwEffect = DROPEFFECT_NONE;
1256 m_pAlternateDropTarget->Drop(pDataObject->m_lpDataObject, 0, { point.x, point.y }, &dwEffect);
1259 return DROPEFFECT_NONE; // Return DE_NONE
1262 // if( ( pDataObject -> IsDataAvailable( CF_TEXT ) ) || // If Text Available
1263 // ( pDataObject -> IsDataAvailable( xxx ) ) || // Or xxx Available
1264 // ( pDataObject -> IsDataAvailable( yyy ) ) ) // Or yyy Available
1265 CLIPFORMAT fmt = CCrystalTextView::GetClipTcharTextFormat(); // CF_TEXT or CF_UNICODETEXT
1266 if (pDataObject->IsDataAvailable (fmt)) // If Text Available
1269 bDataSupported = true; // Set Flag
1272 if (!bDataSupported) // If No Supported Formats Available
1275 if (m_pAlternateDropTarget != nullptr)
1277 DROPEFFECT dwEffect = DROPEFFECT_NONE;
1278 m_pAlternateDropTarget->Drop(pDataObject->m_lpDataObject, 0, { point.x, point.y }, &dwEffect);
1281 return DROPEFFECT_NONE; // Return DE_NONE
1284 return (m_pOwner->DoDropText (pDataObject, point)); // Return Result Of Drop
1288 DROPEFFECT CEditDropTargetImpl::
1289 OnDragScroll (CWnd * pWnd, DWORD dwKeyState, CPoint point)
1291 ASSERT (m_pOwner == pWnd);
1292 m_pOwner->DoDragScroll (point);
1294 if (dwKeyState & MK_CONTROL)
1295 return DROPEFFECT_COPY;
1296 return DROPEFFECT_MOVE;
1299 void CCrystalEditView::
1300 DoDragScroll (const CPoint & point)
1303 GetClientRect (rcClientRect);
1304 if (point.y < rcClientRect.top + DRAG_BORDER_Y)
1306 HideDropIndicator ();
1309 ShowDropIndicator (point);
1310 //UpdateSiblingScrollPos(false);
1313 if (point.y >= rcClientRect.bottom - DRAG_BORDER_Y)
1315 HideDropIndicator ();
1318 ShowDropIndicator (point);
1319 //UpdateSiblingScrollPos(false);
1322 if (point.x < rcClientRect.left + GetMarginWidth () + DRAG_BORDER_X)
1324 HideDropIndicator ();
1327 ShowDropIndicator (point);
1328 //UpdateSiblingScrollPos(true);
1331 if (point.x >= rcClientRect.right - DRAG_BORDER_X)
1333 HideDropIndicator ();
1336 ShowDropIndicator (point);
1337 //UpdateSiblingScrollPos(true);
1342 void CCrystalEditView::
1343 SetAlternateDropTarget (IDropTarget *pDropTarget)
1345 ASSERT(m_pDropTarget->m_pAlternateDropTarget == nullptr);
1346 m_pDropTarget->m_pAlternateDropTarget = pDropTarget;
1347 m_pDropTarget->m_pAlternateDropTarget->AddRef();
1350 bool CCrystalEditView::
1351 DoDropText (COleDataObject * pDataObject, const CPoint & ptClient)
1353 CLIPFORMAT fmt = GetClipTcharTextFormat(); // CF_TEXT or CF_UNICODETEXT
1354 HGLOBAL hData = pDataObject->GetGlobalData (fmt);
1355 if (hData == nullptr)
1358 CPoint ptDropPos = ClientToText (ptClient);
1359 if (IsDraggingText () && IsInsideSelection (ptDropPos))
1361 SetAnchor (ptDropPos);
1362 SetSelection (ptDropPos, ptDropPos);
1363 SetCursorPos (ptDropPos);
1364 EnsureVisible (ptDropPos);
1368 UINT cbData = (UINT) ::GlobalSize (hData);
1369 UINT cchText = cbData / sizeof(TCHAR) - 1;
1370 LPTSTR pszText = (LPTSTR)::GlobalLock (hData);
1371 if (pszText == nullptr)
1374 // Open the undo group
1375 // When we drag from the same panel, it is already open, so do nothing
1376 // (we could test m_pTextBuffer->m_bUndoGroup if it were not a protected member)
1377 bool bGroupFlag = false;
1378 if (! IsDraggingText())
1380 m_pTextBuffer->BeginUndoGroup ();
1385 m_pTextBuffer->InsertText (this, ptDropPos.y, ptDropPos.x, pszText, cchText, y, x, CE_ACTION_DRAGDROP); // [JRT]
1387 CPoint ptCurPos (x, y);
1388 ASSERT_VALIDTEXTPOS (ptCurPos);
1389 SetAnchor (ptDropPos);
1390 SetSelection (ptDropPos, ptCurPos);
1391 SetCursorPos (ptCurPos);
1392 EnsureVisible (ptCurPos);
1395 m_pTextBuffer->FlushUndoGroup (this);
1397 ::GlobalUnlock (hData);
1401 int CCrystalEditView::
1402 OnCreate (LPCREATESTRUCT lpCreateStruct)
1404 if (CCrystalTextView::OnCreate (lpCreateStruct) == -1)
1407 ASSERT (m_pDropTarget == nullptr);
1408 m_pDropTarget = new CEditDropTargetImpl (this);
1409 if (!m_pDropTarget->Register (this))
1411 TRACE0 ("Warning: Unable to register drop target for ccrystaleditview.\n");
1412 delete m_pDropTarget;
1413 m_pDropTarget = nullptr;
1419 void CCrystalEditView::
1422 if (m_pDropTarget != nullptr)
1424 m_pDropTarget->Revoke ();
1425 if (m_pDropTarget->m_pAlternateDropTarget)
1426 m_pDropTarget->m_pAlternateDropTarget->Release();
1427 delete m_pDropTarget;
1428 m_pDropTarget = nullptr;
1431 CCrystalTextView::OnDestroy ();
1434 void CCrystalEditView::
1435 ShowDropIndicator (const CPoint & point)
1437 if (!m_bDropPosVisible)
1440 m_ptSavedCaretPos = GetCursorPos ();
1441 m_bDropPosVisible = true;
1442 ::CreateCaret (m_hWnd, (HBITMAP) 1, 2, GetLineHeight ());
1444 m_ptDropPos = ClientToText (point);
1445 // NB: m_ptDropPos.x is index into char array, which is uncomparable to m_nOffsetChar.
1446 CPoint ptCaretPos = TextToClient (m_ptDropPos);
1447 if (ptCaretPos.x >= GetMarginWidth())
1449 SetCaretPos (ptCaretPos);
1458 void CCrystalEditView::
1459 HideDropIndicator ()
1461 if (m_bDropPosVisible)
1463 SetCursorPos (m_ptSavedCaretPos);
1465 m_bDropPosVisible = false;
1469 DROPEFFECT CCrystalEditView::
1472 return DROPEFFECT_COPY | DROPEFFECT_MOVE;
1475 void CCrystalEditView::
1476 OnDropSource (DROPEFFECT de)
1478 if (!IsDraggingText ())
1481 ASSERT_VALIDTEXTPOS (m_ptDraggedTextBegin);
1482 ASSERT_VALIDTEXTPOS (m_ptDraggedTextEnd);
1484 if (de == DROPEFFECT_MOVE)
1486 m_pTextBuffer->DeleteText (this, m_ptDraggedTextBegin.y, m_ptDraggedTextBegin.x, m_ptDraggedTextEnd.y,
1487 m_ptDraggedTextEnd.x, CE_ACTION_DRAGDROP); // [JRT]
1492 void CCrystalEditView::
1493 UpdateView (CCrystalTextView * pSource, CUpdateContext * pContext, DWORD dwFlags, int nLineIndex /*= -1*/ )
1495 CCrystalTextView::UpdateView (pSource, pContext, dwFlags, nLineIndex);
1497 if (m_bSelectionPushed && pContext != nullptr)
1499 pContext->RecalcPoint (m_ptSavedSelStart);
1500 pContext->RecalcPoint (m_ptSavedSelEnd);
1501 ASSERT_VALIDTEXTPOS (m_ptSavedSelStart);
1502 ASSERT_VALIDTEXTPOS (m_ptSavedSelEnd);
1504 if (m_bDropPosVisible )
1506 pContext->RecalcPoint (m_ptSavedCaretPos);
1507 ASSERT_VALIDTEXTPOS (m_ptSavedCaretPos);
1511 void CCrystalEditView::
1514 if (!QueryEditable ())
1517 CWinApp *pApp = AfxGetApp ();
1518 ASSERT (pApp != nullptr);
1520 delete m_pEditReplaceDlg;
1521 m_pEditReplaceDlg = new CEditReplaceDlg(this);
1522 LastSearchInfos * lastSearch = m_pEditReplaceDlg->GetLastSearchInfos();
1526 // Get the latest Replace parameters
1527 lastSearch->m_bMatchCase = (m_dwLastReplaceFlags & FIND_MATCH_CASE) != 0;
1528 lastSearch->m_bWholeWord = (m_dwLastReplaceFlags & FIND_WHOLE_WORD) != 0;
1529 lastSearch->m_bRegExp = (m_dwLastReplaceFlags & FIND_REGEXP) != 0;
1530 lastSearch->m_bNoWrap = (m_dwLastReplaceFlags & FIND_NO_WRAP) != 0;
1531 if (m_pszLastFindWhat != nullptr)
1532 lastSearch->m_sText = m_pszLastFindWhat;
1536 DWORD dwFlags = pApp->GetProfileInt (EDITPAD_SECTION, _T("ReplaceFlags"), 0);
1537 lastSearch->m_bMatchCase = (dwFlags & FIND_MATCH_CASE) != 0;
1538 lastSearch->m_bWholeWord = (dwFlags & FIND_WHOLE_WORD) != 0;
1539 lastSearch->m_bRegExp = (dwFlags & FIND_REGEXP) != 0;
1540 lastSearch->m_bNoWrap = (dwFlags & FIND_NO_WRAP) != 0;
1542 lastSearch->m_nDirection = 1;
1543 m_pEditReplaceDlg->UseLastSearch ();
1548 GetSelection (m_ptSavedSelStart, m_ptSavedSelEnd);
1549 m_bSelectionPushed = true;
1551 m_pEditReplaceDlg->SetScope(true); // Replace in current selection
1552 m_pEditReplaceDlg->m_ptCurrentPos = m_ptSavedSelStart;
1553 m_pEditReplaceDlg->m_bEnableScopeSelection = true;
1554 m_pEditReplaceDlg->m_ptBlockBegin = m_ptSavedSelStart;
1555 m_pEditReplaceDlg->m_ptBlockEnd = m_ptSavedSelEnd;
1557 // If the selection is in one line, copy text to dialog
1558 if (m_ptSavedSelStart.y == m_ptSavedSelEnd.y)
1559 GetText(m_ptSavedSelStart, m_ptSavedSelEnd, m_pEditReplaceDlg->m_sText);
1563 m_pEditReplaceDlg->SetScope(false); // Set scope when no selection
1564 m_pEditReplaceDlg->m_ptCurrentPos = GetCursorPos ();
1565 m_pEditReplaceDlg->m_bEnableScopeSelection = false;
1567 CPoint ptCursorPos = GetCursorPos ();
1568 CPoint ptStart = WordToLeft (ptCursorPos);
1569 CPoint ptEnd = WordToRight (ptCursorPos);
1570 if (IsValidTextPos (ptStart) && IsValidTextPos (ptEnd) && ptStart != ptEnd)
1571 GetText (ptStart, ptEnd, m_pEditReplaceDlg->m_sText);
1574 // Execute Replace dialog
1575 m_pEditReplaceDlg->Create(CEditReplaceDlg::IDD, this);
1576 m_pEditReplaceDlg->ShowWindow(SW_SHOW);
1579 void CCrystalEditView::
1580 SaveLastSearch(LastSearchInfos *lastSearch)
1582 // Save Replace parameters for 'F3' command
1583 m_bLastReplace = true;
1584 if (m_pszLastFindWhat != nullptr)
1585 free (m_pszLastFindWhat);
1586 m_pszLastFindWhat = _tcsdup (lastSearch->m_sText);
1587 m_dwLastReplaceFlags = 0;
1588 if (lastSearch->m_bMatchCase)
1589 m_dwLastReplaceFlags |= FIND_MATCH_CASE;
1590 if (lastSearch->m_bWholeWord)
1591 m_dwLastReplaceFlags |= FIND_WHOLE_WORD;
1592 if (lastSearch->m_bRegExp)
1593 m_dwLastReplaceFlags |= FIND_REGEXP;
1594 if (lastSearch->m_bNoWrap)
1595 m_dwLastReplaceFlags |= FIND_NO_WRAP;
1597 // Restore selection
1598 if (m_bSelectionPushed)
1600 SetSelection (m_ptSavedSelStart, m_ptSavedSelEnd);
1601 m_bSelectionPushed = false;
1604 // Save search parameters to registry
1605 VERIFY (AfxGetApp()->WriteProfileInt (EDITPAD_SECTION, _T ("ReplaceFlags"), m_dwLastReplaceFlags));
1609 * @brief Replace selected text.
1610 * This function replaces selected text in the editor pane with given text.
1611 * @param [in] pszNewText The text replacing selected text.
1612 * @param [in] cchNewText Length of the replacing text.
1613 * @param [in] dwFlags Additional modifier flags:
1614 * - FIND_REGEXP: use the regular expression.
1615 * @return true if succeeded.
1617 bool CCrystalEditView::
1618 ReplaceSelection (LPCTSTR pszNewText, size_t cchNewText, DWORD dwFlags, bool bGroupWithPrevious)
1621 return DeleteCurrentSelection();
1622 ASSERT (pszNewText != nullptr);
1624 m_pTextBuffer->BeginUndoGroup(bGroupWithPrevious);
1629 auto [ptSelStart, ptSelEnd] = GetSelection ();
1631 ptCursorPos = ptSelStart;
1633 m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_REPLACE);
1636 ptCursorPos = GetCursorPos ();
1637 ASSERT_VALIDTEXTPOS (ptCursorPos);
1641 if (dwFlags & FIND_REGEXP)
1643 LPTSTR lpszNewStr = nullptr;
1644 if (m_pszMatched && !RxReplace(pszNewText, m_pszMatched, m_nLastFindWhatLen, m_rxmatch, &lpszNewStr, &m_nLastReplaceLen))
1647 if (lpszNewStr != nullptr && m_nLastReplaceLen > 0)
1649 LPTSTR buf = text.GetBuffer (m_nLastReplaceLen + 1);
1650 _tcsncpy_s (buf, m_nLastReplaceLen+1, lpszNewStr, m_nLastReplaceLen);
1651 text.ReleaseBuffer (m_nLastReplaceLen);
1655 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, text, text.GetLength(), y, x, CE_ACTION_REPLACE); // [JRT+FRD]
1656 if (lpszNewStr != nullptr)
1662 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszNewText, cchNewText, y, x, CE_ACTION_REPLACE); // [JRT]
1663 ASSERT(cchNewText < INT_MAX);
1664 m_nLastReplaceLen = static_cast<int>(cchNewText);
1667 CPoint ptEndOfBlock = CPoint (x, y);
1668 if (ptEndOfBlock.x == m_pTextBuffer->GetLineLength (ptEndOfBlock.y))
1670 if (ptEndOfBlock.y < m_pTextBuffer->GetLineCount() - 1)
1676 ASSERT_VALIDTEXTPOS (ptCursorPos);
1677 ASSERT_VALIDTEXTPOS (ptEndOfBlock);
1678 SetAnchor (ptEndOfBlock);
1679 SetSelection (ptCursorPos, ptEndOfBlock);
1680 SetCursorPos (ptEndOfBlock);
1682 m_pTextBuffer->FlushUndoGroup(this);
1687 void CCrystalEditView::
1688 OnUpdateEditUndo (CCmdUI * pCmdUI)
1690 bool bCanUndo = m_pTextBuffer != nullptr && m_pTextBuffer->CanUndo ();
1691 pCmdUI->Enable (bCanUndo);
1693 // Since we need text only for menus...
1694 if (pCmdUI->m_pMenu != nullptr)
1696 // Tune up 'resource handle'
1697 HINSTANCE hOldResHandle = AfxGetResourceHandle ();
1698 AfxSetResourceHandle (GetResourceHandle ());
1703 // Format menu item text using the provided item description
1705 m_pTextBuffer->GetUndoDescription (desc);
1706 menu.Format (IDS_MENU_UNDO_FORMAT, (LPCTSTR)desc);
1710 // Just load default menu item text
1711 menu.LoadString (IDS_MENU_UNDO_DEFAULT);
1714 // Restore original handle
1715 AfxSetResourceHandle (hOldResHandle);
1717 // Set menu item text
1718 pCmdUI->SetText (menu);
1722 void CCrystalEditView::
1728 bool CCrystalEditView::
1731 if (m_pTextBuffer != nullptr && m_pTextBuffer->CanUndo ())
1734 if (m_pTextBuffer->Undo (this, ptCursorPos))
1736 ASSERT_VALIDTEXTPOS (ptCursorPos);
1737 SetAnchor (ptCursorPos);
1738 SetSelection (ptCursorPos, ptCursorPos);
1739 SetCursorPos (ptCursorPos);
1740 EnsureVisible (ptCursorPos);
1748 void CCrystalEditView::
1749 SetDisableBSAtSOL (bool bDisableBSAtSOL)
1751 m_bDisableBSAtSOL = bDisableBSAtSOL;
1754 void CCrystalEditView::
1760 bool CCrystalEditView::
1763 if (m_pTextBuffer != nullptr && m_pTextBuffer->CanRedo ())
1766 if (m_pTextBuffer->Redo (this, ptCursorPos))
1768 ASSERT_VALIDTEXTPOS (ptCursorPos);
1769 SetAnchor (ptCursorPos);
1770 SetSelection (ptCursorPos, ptCursorPos);
1771 SetCursorPos (ptCursorPos);
1772 EnsureVisible (ptCursorPos);
1779 void CCrystalEditView::
1780 OnUpdateEditRedo (CCmdUI * pCmdUI)
1782 bool bCanRedo = m_pTextBuffer != nullptr && m_pTextBuffer->CanRedo ();
1783 pCmdUI->Enable (bCanRedo);
1785 // Since we need text only for menus...
1786 if (pCmdUI->m_pMenu != nullptr)
1788 // Tune up 'resource handle'
1789 HINSTANCE hOldResHandle = AfxGetResourceHandle ();
1790 AfxSetResourceHandle (GetResourceHandle ());
1795 // Format menu item text using the provided item description
1797 m_pTextBuffer->GetRedoDescription (desc);
1798 menu.Format (IDS_MENU_REDO_FORMAT, (LPCTSTR)desc);
1802 // Just load default menu item text
1803 menu.LoadString (IDS_MENU_REDO_DEFAULT);
1806 // Restore original handle
1807 AfxSetResourceHandle (hOldResHandle);
1809 // Set menu item text
1810 pCmdUI->SetText (menu);
1815 isopenbrace (TCHAR c)
1817 return c == _T ('{') || c == _T ('(') || c == _T ('[') || c == _T ('<');
1821 isclosebrace (TCHAR c)
1823 return c == _T ('}') || c == _T (')') || c == _T (']') || c == _T ('>');
1827 isopenbrace (LPCTSTR s)
1829 return s[1] == _T ('\0') && isopenbrace (*s);
1833 isclosebrace (LPCTSTR s)
1835 return s[1] == _T ('\0') && isclosebrace (*s);
1838 int bracetype (TCHAR c);
1839 int bracetype (LPCTSTR s);
1841 void CCrystalEditView::
1842 OnEditOperation (int nAction, LPCTSTR pszText, size_t cchText)
1846 // Analyse last action...
1847 if (nAction == CE_ACTION_TYPING && (
1848 _tcsncmp (pszText, _T ("\r\n"), cchText) == 0 ||
1849 (cchText == 1 && (*pszText == '\r' || *pszText == '\n')))
1850 && !m_bOvrMode && !m_pTextBuffer->GetTableEditing())
1853 CPoint ptCursorPos = GetCursorPos ();
1854 ASSERT (ptCursorPos.y > 0);
1856 // Take indentation from the previous line
1857 int nLength = m_pTextBuffer->GetLineLength (ptCursorPos.y - 1);
1858 LPCTSTR pszLineChars = m_pTextBuffer->GetLineChars (ptCursorPos.y - 1);
1860 while (nPos < nLength && xisspace (pszLineChars[nPos]))
1865 if ((GetFlags () & SRCOPT_BRACEGNU) && isclosebrace (pszLineChars[nLength - 1]) && ptCursorPos.y > 0 && nPos && nPos == nLength - 1)
1867 if (pszLineChars[nPos - 1] == _T ('\t'))
1873 int nTabSize = GetTabSize (),
1874 nDelta = nTabSize - nPos % nTabSize;
1886 // Insert part of the previous line
1887 TCHAR *pszInsertStr;
1888 if ((GetFlags () & (SRCOPT_BRACEGNU|SRCOPT_BRACEANSI)) && isopenbrace (pszLineChars[nLength - 1]))
1890 if (m_pTextBuffer->GetInsertTabs())
1892 const size_t InsertSiz = (nPos + 2);
1893 pszInsertStr = static_cast<TCHAR *> (_alloca (sizeof(TCHAR) * InsertSiz));
1894 _tcsncpy_s (pszInsertStr, InsertSiz, pszLineChars, nPos);
1895 pszInsertStr[nPos++] = _T ('\t');
1899 int nTabSize = GetTabSize ();
1900 int nChars = nTabSize - nPos % nTabSize;
1901 const size_t InsertSiz = (nPos + nChars + 1);
1902 pszInsertStr = static_cast<TCHAR *> (_alloca (sizeof (TCHAR) * InsertSiz));
1903 _tcsncpy_s (pszInsertStr, InsertSiz, pszLineChars, nPos);
1906 pszInsertStr[nPos++] = _T (' ');
1912 const size_t InsertSiz = (nPos + 1);
1913 pszInsertStr = static_cast<TCHAR *> (_alloca (sizeof (TCHAR) * InsertSiz));
1914 _tcsncpy_s (pszInsertStr, InsertSiz, pszLineChars, nPos);
1916 pszInsertStr[nPos] = 0;
1918 // m_pTextBuffer->BeginUndoGroup ();
1920 m_pTextBuffer->InsertText (nullptr, ptCursorPos.y, ptCursorPos.x,
1921 pszInsertStr, nPos, y, x, CE_ACTION_AUTOINDENT);
1923 SetSelection (pt, pt);
1927 // m_pTextBuffer->FlushUndoGroup (this);
1931 // Insert part of the previous line
1932 if ((GetFlags () & (SRCOPT_BRACEGNU|SRCOPT_BRACEANSI)) && isopenbrace (pszLineChars[nLength - 1]))
1934 TCHAR *pszInsertStr;
1935 if (m_pTextBuffer->GetInsertTabs())
1937 pszInsertStr = (TCHAR *) _alloca (sizeof (TCHAR) * 2);
1938 pszInsertStr[nPos++] = _T ('\t');
1942 int nTabSize = GetTabSize ();
1943 int nChars = nTabSize - nPos % nTabSize;
1944 pszInsertStr = (TCHAR *) _alloca (sizeof (TCHAR) * (nChars + 1));
1947 pszInsertStr[nPos++] = _T (' ');
1950 pszInsertStr[nPos] = 0;
1952 // m_pTextBuffer->BeginUndoGroup ();
1954 m_pTextBuffer->InsertText (nullptr, ptCursorPos.y, ptCursorPos.x,
1955 pszInsertStr, nPos, y, x, CE_ACTION_AUTOINDENT);
1957 SetSelection (pt, pt);
1961 // m_pTextBuffer->FlushUndoGroup (this);
1965 else if (nAction == CE_ACTION_TYPING && (GetFlags () & SRCOPT_FNBRACE) && bracetype (pszText) == 3)
1968 CPoint ptCursorPos = GetCursorPos ();
1969 LPCTSTR pszChars = m_pTextBuffer->GetLineChars (ptCursorPos.y);
1970 if (ptCursorPos.x > 1 && xisalnum (pszChars[ptCursorPos.x - 2]))
1972 LPTSTR pszInsertStr = (TCHAR *) _alloca (sizeof (TCHAR) * 2);
1973 *pszInsertStr = _T (' ');
1974 pszInsertStr[1] = _T ('\0');
1975 // m_pTextBuffer->BeginUndoGroup ();
1977 m_pTextBuffer->InsertText (nullptr, ptCursorPos.y, ptCursorPos.x - 1,
1978 pszInsertStr, 1, y, x, CE_ACTION_AUTOINDENT);
1979 ptCursorPos.x = x + 1;
1981 SetSelection (ptCursorPos, ptCursorPos);
1982 SetAnchor (ptCursorPos);
1983 SetCursorPos (ptCursorPos);
1984 EnsureVisible (ptCursorPos);
1985 // m_pTextBuffer->FlushUndoGroup (this);
1988 else if (nAction == CE_ACTION_TYPING && (GetFlags () & SRCOPT_BRACEGNU) && isopenbrace (pszText))
1991 CPoint ptCursorPos = GetCursorPos ();
1993 // Take indentation from the previous line
1994 int nLength = m_pTextBuffer->GetLineLength (ptCursorPos.y);
1995 LPCTSTR pszLineChars = m_pTextBuffer->GetLineChars (ptCursorPos.y );
1997 while (nPos < nLength && xisspace (pszLineChars[nPos]))
1999 if (nPos == nLength - 1)
2001 TCHAR *pszInsertStr;
2002 if (m_pTextBuffer->GetInsertTabs())
2004 pszInsertStr = (TCHAR *) _alloca (sizeof (TCHAR) * 2);
2005 *pszInsertStr = _T ('\t');
2010 int nTabSize = GetTabSize ();
2011 int nChars = nTabSize - nPos % nTabSize;
2012 pszInsertStr = (TCHAR *) _alloca (sizeof (TCHAR) * (nChars + 1));
2016 pszInsertStr[nPos++] = _T (' ');
2019 pszInsertStr[nPos] = 0;
2021 // m_pTextBuffer->BeginUndoGroup ();
2023 m_pTextBuffer->InsertText (nullptr, ptCursorPos.y, ptCursorPos.x - 1,
2024 pszInsertStr, nPos, y, x, CE_ACTION_AUTOINDENT);
2025 CPoint pt (x + 1, y);
2026 SetSelection (pt, pt);
2030 // m_pTextBuffer->FlushUndoGroup (this);
2033 else if (nAction == CE_ACTION_TYPING && (GetFlags () & (SRCOPT_BRACEGNU|SRCOPT_BRACEANSI)) && isclosebrace (pszText))
2036 CPoint ptCursorPos = GetCursorPos ();
2038 // Take indentation from the previous line
2039 int nLength = m_pTextBuffer->GetLineLength (ptCursorPos.y);
2040 LPCTSTR pszLineChars = m_pTextBuffer->GetLineChars (ptCursorPos.y );
2042 while (nPos < nLength && xisspace (pszLineChars[nPos]))
2044 if (ptCursorPos.y > 0 && nPos && nPos == nLength - 1)
2046 if (pszLineChars[nPos - 1] == _T ('\t'))
2052 int nTabSize = GetTabSize ();
2053 nPos = nTabSize - (ptCursorPos.x - 1) % nTabSize;
2058 if (nPos > nLength - 1)
2063 // m_pTextBuffer->BeginUndoGroup ();
2064 m_pTextBuffer->DeleteText (nullptr, ptCursorPos.y, ptCursorPos.x - nPos - 1,
2065 ptCursorPos.y, ptCursorPos.x - 1, CE_ACTION_AUTOINDENT);
2066 ptCursorPos.x -= nPos;
2067 SetCursorPos (ptCursorPos);
2068 SetSelection (ptCursorPos, ptCursorPos);
2069 SetAnchor (ptCursorPos);
2070 EnsureVisible (ptCursorPos);
2071 // m_pTextBuffer->FlushUndoGroup (this);
2077 void CCrystalEditView::
2078 OnEditAutoComplete ()
2080 CPoint ptCursorPos = GetCursorPos ();
2081 int nLength = m_pTextBuffer->GetLineLength (ptCursorPos.y);
2082 LPCTSTR pszText = m_pTextBuffer->GetLineChars (ptCursorPos.y), pszEnd = pszText + ptCursorPos.x;
2083 if (ptCursorPos.x > 0 && ptCursorPos.y > 0 && (nLength == ptCursorPos.x || !xisalnum (*pszEnd)) && xisalnum (pszEnd[-1]))
2085 LPCTSTR pszBegin = pszEnd - 1;
2086 while (pszBegin > pszText && xisalnum (*pszBegin))
2088 if (!xisalnum (*pszBegin))
2090 nLength = static_cast<int>(pszEnd - pszBegin);
2092 LPTSTR pszBuffer = sText.GetBuffer (nLength + 2);
2093 *pszBuffer = _T('<');
2094 _tcsncpy_s (pszBuffer + 1, nLength + 1, pszBegin, nLength);
2095 sText.ReleaseBuffer (nLength + 1);
2097 ptCursorPos.x -= nLength;
2098 bool bFound = FindText (sText, ptCursorPos, FIND_MATCH_CASE|FIND_REGEXP|FIND_DIRECTION_UP, true, &ptTextPos);
2101 ptCursorPos.x += nLength;
2102 bFound = FindText (sText, ptCursorPos, FIND_MATCH_CASE|FIND_REGEXP, true, &ptTextPos);
2103 ptCursorPos.x -= nLength;
2107 const int nLineLength = m_pTextBuffer->GetLineLength (ptTextPos.y);
2108 int nFound = nLineLength;
2109 pszText = m_pTextBuffer->GetLineChars (ptTextPos.y) + ptTextPos.x + m_nLastFindWhatLen;
2110 nFound -= ptTextPos.x + m_nLastFindWhatLen;
2111 pszBuffer = sText.GetBuffer (nFound + 1);
2112 while (nFound-- && xisalnum (*pszText))
2113 *pszBuffer++ = *pszText++;
2114 sText.ReleaseBuffer (nLineLength - (ptTextPos.x + m_nLastFindWhatLen) - nFound - 1);
2115 if (!sText.IsEmpty ())
2117 m_pTextBuffer->BeginUndoGroup ();
2119 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x + nLength, sText, sText.GetLength(), y, x, CE_ACTION_AUTOCOMPLETE);
2122 SetCursorPos (ptCursorPos);
2123 SetSelection (ptCursorPos, ptCursorPos);
2124 SetAnchor (ptCursorPos);
2125 EnsureVisible (ptCursorPos);
2126 m_pTextBuffer->FlushUndoGroup (this);
2132 void CCrystalEditView::
2133 OnUpdateEditAutoComplete (CCmdUI * pCmdUI)
2135 CPoint ptCursorPos = GetCursorPos ();
2136 int nLength = m_pTextBuffer->GetLineLength (ptCursorPos.y);
2137 LPCTSTR pszText = m_pTextBuffer->GetLineChars (ptCursorPos.y) + ptCursorPos.x;
2138 pCmdUI->Enable (ptCursorPos.x > 0 && ptCursorPos.y > 0 && (nLength == ptCursorPos.x || !xisalnum (*pszText)) && xisalnum (pszText[-1]));
2141 void CCrystalEditView::
2144 CPoint ptCursorPos = GetCursorPos ();
2145 int nLength = m_pTextBuffer->GetLineLength (ptCursorPos.y);
2146 LPCTSTR pszText = m_pTextBuffer->GetLineChars (ptCursorPos.y), pszEnd = pszText + ptCursorPos.x;
2147 if (ptCursorPos.x > 0 && ptCursorPos.y > 0 && (nLength == ptCursorPos.x || !xisalnum (*pszEnd)) && xisalnum (pszEnd[-1]))
2149 LPCTSTR pszBegin = pszEnd - 1;
2150 while (pszBegin > pszText && xisalnum (*pszBegin))
2152 if (!xisalnum (*pszBegin))
2154 nLength = static_cast<int>(pszEnd - pszBegin);
2155 CString sText, sExpand;
2156 LPTSTR pszBuffer = sText.GetBuffer (nLength + 1);
2157 _tcsncpy_s (pszBuffer, nLength + 1, pszBegin, nLength);
2158 sText.ReleaseBuffer (nLength);
2160 ptCursorPos.x -= nLength;
2161 bool bFound = !!m_mapExpand->Lookup (sText, sExpand);
2162 if (bFound && !sExpand.IsEmpty ())
2164 m_pTextBuffer->BeginUndoGroup ();
2166 m_pTextBuffer->DeleteText (this, ptCursorPos.y, ptCursorPos.x, ptCursorPos.y, ptCursorPos.x + nLength, CE_ACTION_AUTOEXPAND);
2167 LPTSTR pszExpand = sExpand.GetBuffer (sExpand.GetLength () + 1);
2168 LPTSTR pszSlash = _tcschr (pszExpand, _T ('\\'));
2169 if (pszSlash == nullptr)
2171 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszExpand, _tcslen(pszExpand), y, x, CE_ACTION_AUTOEXPAND);
2174 ASSERT_VALIDTEXTPOS (ptCursorPos);
2175 SetCursorPos (ptCursorPos);
2176 SetSelection (ptCursorPos, ptCursorPos);
2177 SetAnchor (ptCursorPos);
2181 *pszSlash++ = _T ('\0');
2184 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, pszExpand, _tcslen(pszExpand), y, x, CE_ACTION_AUTOEXPAND);
2187 ASSERT_VALIDTEXTPOS (ptCursorPos);
2188 SetSelection (ptCursorPos, ptCursorPos);
2189 SetAnchor (ptCursorPos);
2190 SetCursorPos (ptCursorPos);
2191 OnEditOperation (CE_ACTION_TYPING, pszExpand, _tcslen(pszExpand));
2192 ptCursorPos = GetCursorPos ();
2193 if (pszSlash == nullptr)
2199 const static TCHAR szText[3] = _T ("\r\n");
2200 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, szText, _tcslen(szText), y, x, CE_ACTION_AUTOEXPAND); // [JRT]
2203 ASSERT_VALIDTEXTPOS (ptCursorPos);
2204 SetSelection (ptCursorPos, ptCursorPos);
2205 SetAnchor (ptCursorPos);
2206 SetCursorPos (ptCursorPos);
2207 OnEditOperation (CE_ACTION_TYPING, szText, _tcslen(pszExpand));
2230 CPoint ptSelStart = ptCursorPos;
2231 bool bDeleted = false;
2232 if (!(ptCursorPos.x)) // If At Start Of Line
2235 if (!m_bDisableBSAtSOL) // If DBSASOL Is Disabled
2238 if (ptCursorPos.y > 0) // If Previous Lines Available
2241 ptCursorPos.y--; // Decrement To Previous Line
2243 ptCursorPos.x = GetLineLength (
2244 ptCursorPos.y); // Set Cursor To End Of Previous Line
2246 bDeleted = true; // Set Deleted Flag
2251 else // If Caret Not At SOL
2254 ptCursorPos.x--; // Decrement Position
2256 bDeleted = true; // Set Deleted Flag
2259 ASSERT_VALIDTEXTPOS (ptCursorPos);
2260 SetAnchor (ptCursorPos);
2261 SetSelection (ptCursorPos, ptCursorPos);
2262 SetCursorPos (ptCursorPos);
2265 m_pTextBuffer->DeleteText (this, ptCursorPos.y, ptCursorPos.x, ptSelStart.y, ptSelStart.x, CE_ACTION_AUTOEXPAND); // [JRT]
2270 CPoint ptSelEnd = ptCursorPos;
2271 if (ptSelEnd.x == GetLineLength (ptSelEnd.y))
2273 if (ptSelEnd.y == GetLineCount () - 1)
2280 m_pTextBuffer->DeleteText (this, ptCursorPos.y, ptCursorPos.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_AUTOEXPAND); // [JRT]
2285 static TCHAR szText[32];
2286 if (m_pTextBuffer->GetInsertTabs())
2293 int nTabSize = GetTabSize ();
2294 int nChars = nTabSize - ptCursorPos.x % nTabSize;
2295 for (int i = 0; i < nChars; i++)
2297 szText[nChars] = '\0';
2299 m_pTextBuffer->InsertText (this, ptCursorPos.y, ptCursorPos.x, szText, _tcslen(szText), y, x, CE_ACTION_AUTOEXPAND); // [JRT]
2302 ASSERT_VALIDTEXTPOS (ptCursorPos);
2303 SetSelection (ptCursorPos, ptCursorPos);
2304 SetAnchor (ptCursorPos);
2305 SetCursorPos (ptCursorPos);
2308 ptCursorPos = GetCursorPos ();
2309 pszExpand = pszSlash + 1;
2310 pszSlash = _tcschr (pszExpand, '\\');
2311 if (pszSlash != nullptr)
2315 sExpand.ReleaseBuffer ();
2316 EnsureVisible (ptCursorPos);
2317 m_pTextBuffer->FlushUndoGroup (this);
2322 void CCrystalEditView::
2323 OnUpdateEditAutoExpand (CCmdUI * pCmdUI)
2325 if (m_mapExpand->IsEmpty ())
2326 pCmdUI->Enable (false);
2328 OnUpdateEditAutoComplete (pCmdUI);
2331 void CCrystalEditView::
2332 OnUpdateEditLowerCase (CCmdUI * pCmdUI)
2334 pCmdUI->Enable (IsSelection ());
2337 void CCrystalEditView::
2342 CPoint ptCursorPos = GetCursorPos ();
2343 auto [ptSelStart, ptSelEnd] = GetSelection ();
2345 GetText (ptSelStart, ptSelEnd, text);
2348 m_pTextBuffer->BeginUndoGroup ();
2352 auto [ptSelStart1, ptSelEnd1] = GetSelection ();
2354 ptCursorPos = ptSelStart1;
2355 /*SetAnchor (ptCursorPos);
2356 SetSelection (ptCursorPos, ptCursorPos);
2357 SetCursorPos (ptCursorPos);
2358 EnsureVisible (ptCursorPos);*/
2361 m_pTextBuffer->DeleteText (this, ptSelStart1.y, ptSelStart1.x, ptSelEnd1.y, ptSelEnd1.x, CE_ACTION_LOWERCASE);
2365 m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, text.GetLength(), y, x, CE_ACTION_LOWERCASE);
2367 ASSERT_VALIDTEXTPOS (ptCursorPos);
2368 SetAnchor (ptCursorPos);
2369 SetSelection (ptSelStart, ptSelEnd);
2370 SetCursorPos (ptCursorPos);
2371 EnsureVisible (ptCursorPos);
2373 m_pTextBuffer->FlushUndoGroup (this);
2377 void CCrystalEditView::
2378 OnUpdateEditUpperCase (CCmdUI * pCmdUI)
2380 pCmdUI->Enable (IsSelection ());
2383 void CCrystalEditView::
2388 CPoint ptCursorPos = GetCursorPos ();
2389 auto [ptSelStart, ptSelEnd] = GetSelection ();
2391 GetText (ptSelStart, ptSelEnd, text);
2394 m_pTextBuffer->BeginUndoGroup ();
2398 auto [ptSelStart1, ptSelEnd1] = GetSelection ();
2400 ptCursorPos = ptSelStart1;
2401 /*SetAnchor (ptCursorPos);
2402 SetSelection (ptCursorPos, ptCursorPos);
2403 SetCursorPos (ptCursorPos);
2404 EnsureVisible (ptCursorPos);*/
2407 m_pTextBuffer->DeleteText (this, ptSelStart1.y, ptSelStart1.x, ptSelEnd1.y, ptSelEnd1.x, CE_ACTION_UPPERCASE);
2411 m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, text.GetLength(), y, x, CE_ACTION_UPPERCASE);
2413 ASSERT_VALIDTEXTPOS (ptCursorPos);
2414 SetAnchor (ptCursorPos);
2415 SetSelection (ptSelStart, ptSelEnd);
2416 SetCursorPos (ptCursorPos);
2417 EnsureVisible (ptCursorPos);
2419 m_pTextBuffer->FlushUndoGroup (this);
2423 void CCrystalEditView::
2424 OnUpdateEditSwapCase (CCmdUI * pCmdUI)
2426 pCmdUI->Enable (IsSelection ());
2429 void CCrystalEditView::
2434 CPoint ptCursorPos = GetCursorPos ();
2435 auto [ptSelStart, ptSelEnd] = GetSelection ();
2437 GetText (ptSelStart, ptSelEnd, text);
2438 int nLen = text.GetLength ();
2439 LPTSTR pszText = text.GetBuffer (nLen + 1);
2441 *pszText++ = (TCHAR)(_istlower (*pszText) ? _totupper (*pszText) : _totlower (*pszText));
2442 text.ReleaseBuffer (nLen);
2444 m_pTextBuffer->BeginUndoGroup ();
2448 auto [ptSelStart1, ptSelEnd1] = GetSelection ();
2450 ptCursorPos = ptSelStart1;
2451 /*SetAnchor (ptCursorPos);
2452 SetSelection (ptCursorPos, ptCursorPos);
2453 SetCursorPos (ptCursorPos);
2454 EnsureVisible (ptCursorPos);*/
2457 m_pTextBuffer->DeleteText (this, ptSelStart1.y, ptSelStart1.x, ptSelEnd1.y, ptSelEnd1.x, CE_ACTION_SWAPCASE);
2461 m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, text.GetLength(), y, x, CE_ACTION_SWAPCASE);
2463 ASSERT_VALIDTEXTPOS (ptCursorPos);
2464 SetAnchor (ptCursorPos);
2465 SetSelection (ptSelStart, ptSelEnd);
2466 SetCursorPos (ptCursorPos);
2467 EnsureVisible (ptCursorPos);
2469 m_pTextBuffer->FlushUndoGroup (this);
2473 void CCrystalEditView::
2474 OnUpdateEditCapitalize (CCmdUI * pCmdUI)
2476 pCmdUI->Enable (IsSelection ());
2479 void CCrystalEditView::
2484 CPoint ptCursorPos = GetCursorPos ();
2485 auto [ptSelStart, ptSelEnd] = GetSelection ();
2487 GetText (ptSelStart, ptSelEnd, text);
2488 int nLen = text.GetLength ();
2489 LPTSTR pszText = text.GetBuffer (nLen + 1);
2490 bool bCapitalize = true;
2493 if (xisspace (*pszText))
2495 else if (_istalpha (*pszText))
2498 *pszText = (TCHAR)_totupper (*pszText);
2499 bCapitalize = false;
2502 *pszText = (TCHAR)_totlower (*pszText);
2505 text.ReleaseBuffer (nLen);
2507 m_pTextBuffer->BeginUndoGroup ();
2511 auto [ptSelStart1, ptSelEnd1] = GetSelection ();
2513 ptCursorPos = ptSelStart1;
2514 /*SetAnchor (ptCursorPos);
2515 SetSelection (ptCursorPos, ptCursorPos);
2516 SetCursorPos (ptCursorPos);
2517 EnsureVisible (ptCursorPos);*/
2520 m_pTextBuffer->DeleteText (this, ptSelStart1.y, ptSelStart1.x, ptSelEnd1.y, ptSelEnd1.x, CE_ACTION_CAPITALIZE);
2524 m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, text.GetLength(), y, x, CE_ACTION_CAPITALIZE);
2526 ASSERT_VALIDTEXTPOS (ptCursorPos);
2527 SetAnchor (ptCursorPos);
2528 SetSelection (ptSelStart, ptSelEnd);
2529 SetCursorPos (ptCursorPos);
2530 EnsureVisible (ptCursorPos);
2532 m_pTextBuffer->FlushUndoGroup (this);
2536 void CCrystalEditView::
2537 OnUpdateEditSentence (CCmdUI * pCmdUI)
2539 pCmdUI->Enable (IsSelection ());
2542 void CCrystalEditView::
2547 CPoint ptCursorPos = GetCursorPos ();
2548 auto [ptSelStart, ptSelEnd] = GetSelection ();
2550 GetText (ptSelStart, ptSelEnd, text);
2551 int nLen = text.GetLength ();
2552 LPTSTR pszText = text.GetBuffer (nLen + 1);
2553 bool bCapitalize = true;
2556 if (!xisspace (*pszText))
2557 if (*pszText == _T ('.'))
2559 if (pszText[1] && !_istdigit (pszText[1]))
2562 else if (_istalpha (*pszText))
2565 *pszText = (TCHAR)_totupper (*pszText);
2566 bCapitalize = false;
2569 *pszText = (TCHAR)_totlower (*pszText);
2572 text.ReleaseBuffer (nLen);
2574 m_pTextBuffer->BeginUndoGroup ();
2578 auto [ptSelStart1, ptSelEnd1] = GetSelection ();
2580 ptCursorPos = ptSelStart1;
2581 /*SetAnchor (ptCursorPos);
2582 SetSelection (ptCursorPos, ptCursorPos);
2583 SetCursorPos (ptCursorPos);
2584 EnsureVisible (ptCursorPos);*/
2587 m_pTextBuffer->DeleteText (this, ptSelStart1.y, ptSelStart1.x, ptSelEnd1.y, ptSelEnd1.x, CE_ACTION_SENTENCIZE);
2591 m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, text, text.GetLength(), y, x, CE_ACTION_SENTENCIZE);
2593 ASSERT_VALIDTEXTPOS (ptCursorPos);
2594 SetAnchor (ptCursorPos);
2595 SetSelection (ptSelStart, ptSelEnd);
2596 SetCursorPos (ptCursorPos);
2597 EnsureVisible (ptCursorPos);
2599 m_pTextBuffer->FlushUndoGroup (this);
2604 void CCrystalEditView::OnUpdateEditGotoLastChange( CCmdUI *pCmdUI )
2606 CPoint ptLastChange = m_pTextBuffer->GetLastChangePos();
2607 pCmdUI->Enable( ptLastChange.x > 0 && ptLastChange.y > -1 );
2610 void CCrystalEditView::OnEditGotoLastChange()
2612 CPoint ptLastChange = m_pTextBuffer->GetLastChangePos();
2613 if( ptLastChange.x < 0 || ptLastChange.y < 0 )
2617 SetSelection( ptLastChange, ptLastChange );
2618 SetCursorPos( ptLastChange );
2619 EnsureVisible( ptLastChange );
2623 int CCrystalEditView::SpellGetLine (struct SpellData_t *pdata)
2625 CCrystalEditView *pView = static_cast<CCrystalEditView*>(pdata->pUserData);
2626 static TCHAR szBuffer[4096];
2628 if (pdata->nRow < pView->GetLineCount ())
2630 int nCount = pView->GetLineLength (pdata->nRow) + 1;
2631 /*if (pdata->pszBuffer)
2632 free (pdata->pszBuffer);
2633 pdata->pszBuffer = (LPTSTR) malloc (nCount + 2);*/
2634 pdata->pszBuffer = szBuffer;
2635 *pdata->pszBuffer = _T ('^');
2637 _tcscpy_s (pdata->pszBuffer + 1, sizeof(szBuffer)-1, pView->GetLineChars (pdata->nRow));
2639 pdata->pszBuffer[nCount++] = _T (' ');
2640 pdata->pszBuffer[nCount++] = _T ('\n');
2641 pdata->pszBuffer[nCount] = _T ('\0');
2645 pdata->pszBuffer = szBuffer;
2646 *pdata->pszBuffer = _T ('\0');
2650 int CCrystalEditView::SpellNotify (int nEvent, struct SpellData_t *pdata)
2652 CCrystalEditView *pView = static_cast<CCrystalEditView*>(pdata->pUserData);
2653 CPoint ptStartPos, ptEndPos;
2658 ptStartPos.x = pdata->nColumn - 1;
2659 ptStartPos.y = pdata->nRow - 1;
2660 ptEndPos.x = pdata->nColumn - 1 + static_cast<LONG>(_tcslen (pdata->pszWord));
2661 ptEndPos.y = pdata->nRow - 1;
2662 if (!pView->IsValidTextPos (ptStartPos))
2663 if (ptStartPos.x > 0)
2667 if (!pView->IsValidTextPos (ptEndPos))
2672 pView->SetAnchor (ptStartPos);
2673 pView->SetSelection (ptStartPos, ptEndPos);
2674 pView->SetCursorPos (ptStartPos);
2675 pView->EnsureVisible (ptStartPos);
2678 if (pView->IsSelection ())
2681 pView->GetSelection (ptStartPos, ptEndPos);
2682 pView->m_pTextBuffer->DeleteText (pView, ptStartPos.y, ptStartPos.x, ptEndPos.y, ptEndPos.x, CE_ACTION_SPELL);
2683 pView->m_pTextBuffer->InsertText (pView, ptStartPos.y, ptStartPos.x, pdata->pszWord, _tcslen(pdata->pszWord), y, x, CE_ACTION_SPELL);
2686 pView->SetAnchor (ptEndPos);
2687 pView->SetSelection (ptEndPos, ptEndPos);
2688 pView->SetCursorPos (ptEndPos);
2692 ptStartPos = pView->GetCursorPos ();
2693 pView->SetAnchor (ptStartPos);
2694 pView->SetSelection (ptStartPos, ptStartPos);
2695 pView->SetCursorPos (ptStartPos);
2696 pView->EnsureVisible (ptStartPos);
2697 ::MessageBox (pdata->hParent, _T ("Spellchecking finished."), _T ("WIspell"), MB_OK|MB_ICONINFORMATION);
2702 HMODULE CCrystalEditView::hSpellDll = nullptr;
2703 TCHAR CCrystalEditView::szWIspellPath[_MAX_PATH];
2704 SpellData CCrystalEditView::spellData;
2705 int (*CCrystalEditView::SpellInit) (SpellData*);
2706 int (*CCrystalEditView::SpellCheck) (SpellData*);
2707 int (*CCrystalEditView::SpellConfig) (SpellData*);
2709 bool CCrystalEditView::LoadSpellDll (bool bAlert /*= true*/)
2711 if (hSpellDll != nullptr)
2713 CString sPath = szWIspellPath;
2714 if (!sPath.IsEmpty () && sPath[sPath.GetLength () - 1] != _T('\\'))
2716 sPath += _T ("wispell.dll");
2717 hSpellDll = LoadLibrary (sPath);
2718 if (hSpellDll != nullptr)
2720 SpellInit = (int (*) (SpellData*)) GetProcAddress (hSpellDll, "SpellInit");
2721 SpellCheck = (int (*) (SpellData*)) GetProcAddress (hSpellDll, "SpellCheck");
2722 SpellConfig = (int (*) (SpellData*)) GetProcAddress (hSpellDll, "SpellConfig");
2724 SpellInit (&spellData);
2725 _tcscpy_s (spellData.szIspell, szWIspellPath);
2726 spellData.GetLine = SpellGetLine;
2727 spellData.Notify = SpellNotify;
2731 SpellInit = SpellCheck = SpellConfig = nullptr;
2733 ::MessageBox (AfxGetMainWnd ()->GetSafeHwnd (), _T ("Error loading \"wispell.dll\"."), _T ("Error"), MB_OK|MB_ICONEXCLAMATION);
2735 return hSpellDll != nullptr;
2738 void CCrystalEditView::
2739 OnUpdateToolsSpelling (CCmdUI * pCmdUI)
2741 CPoint ptCursorPos = GetCursorPos ();
2742 int nLines = GetLineCount () - 1;
2743 pCmdUI->Enable (LoadSpellDll (false) && ptCursorPos.y < nLines);
2746 void CCrystalEditView::
2749 CPoint ptCursorPos = GetCursorPos ();
2750 if (LoadSpellDll () && ptCursorPos.y < GetLineCount ())
2752 spellData.hParent = GetSafeHwnd ();
2753 spellData.nRow = ptCursorPos.y;
2754 spellData.pUserData = (LPVOID) (LPCVOID) this;
2755 spellData.pszBuffer = nullptr;
2756 m_pTextBuffer->BeginUndoGroup ();
2757 if (SpellCheck (&spellData) == IDCANCEL)
2759 m_pTextBuffer->FlushUndoGroup (this);
2763 m_pTextBuffer->FlushUndoGroup (this);
2764 /*if (spellData.pszBuffer)
2765 free (spellData.pszBuffer);*/
2769 void CCrystalEditView::
2770 OnUpdateToolsCharCoding (CCmdUI * pCmdUI)
2772 pCmdUI->Enable (IsSelection ());
2775 void CCrystalEditView::
2776 OnToolsCharCoding ()
2781 CPoint ptCursorPos = GetCursorPos ();
2782 auto [ptSelStart, ptSelEnd] = GetSelection ();
2784 GetText (ptSelStart, ptSelEnd, sText);
2786 dlg.m_sOriginal = sText;
2787 LPTSTR pszEnd = dlg.m_sOriginal.GetBuffer (dlg.m_sOriginal.GetLength () + 1);
2788 for (int i = 0; i < 13; i++)
2790 pszEnd = _tcschr (pszEnd, _T ('\n'));
2791 if (pszEnd != nullptr)
2796 if (pszEnd != nullptr)
2797 *pszEnd = _T ('\0');
2798 dlg.m_sOriginal.ReleaseBuffer ();
2799 if (dlg.DoModal () != IDOK)
2801 LPTSTR pszNew = nullptr;
2802 if (!iconvert_new (sText, &pszNew, dlg.m_nSource, dlg.m_nDest, dlg.m_bAlpha))
2804 ASSERT (pszNew != nullptr);
2805 m_pTextBuffer->BeginUndoGroup ();
2807 m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_RECODE);
2810 m_pTextBuffer->InsertText (this, ptSelStart.y, ptSelStart.x, pszNew, _tcslen(pszNew), y, x, CE_ACTION_RECODE);
2812 if (IsValidTextPos (ptCursorPos))
2814 ASSERT_VALIDTEXTPOS (ptCursorPos);
2815 SetAnchor (ptCursorPos);
2816 SetSelection (ptSelStart, ptSelEnd);
2817 SetCursorPos (ptCursorPos);
2818 EnsureVisible (ptCursorPos);
2820 m_pTextBuffer->FlushUndoGroup (this);
2822 if (pszNew != nullptr)
2827 void CCrystalEditView::
2830 if (!IsSelection ())
2831 MoveWordRight (true);
2834 auto [ptSelStart, ptSelEnd] = GetSelection ();
2836 m_pTextBuffer->BeginUndoGroup ();
2838 m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_DELETE);
2840 ASSERT_VALIDTEXTPOS (ptSelStart);
2841 SetAnchor (ptSelStart);
2842 SetSelection (ptSelStart, ptSelStart);
2843 SetCursorPos (ptSelStart);
2844 EnsureVisible (ptSelStart);
2846 m_pTextBuffer->FlushUndoGroup (this);
2850 void CCrystalEditView::
2851 OnEditDeleteWordBack ()
2853 if (!IsSelection ())
2854 MoveWordLeft (true);
2857 auto [ptSelStart, ptSelEnd] = GetSelection ();
2859 m_pTextBuffer->BeginUndoGroup ();
2861 m_pTextBuffer->DeleteText (this, ptSelStart.y, ptSelStart.x, ptSelEnd.y, ptSelEnd.x, CE_ACTION_DELETE);
2863 ASSERT_VALIDTEXTPOS (ptSelStart);
2864 SetAnchor (ptSelStart);
2865 SetSelection (ptSelStart, ptSelStart);
2866 SetCursorPos (ptSelStart);
2867 EnsureVisible (ptSelStart);
2869 m_pTextBuffer->FlushUndoGroup (this);
2873 void CCrystalEditView::
2874 OnKillFocus (CWnd * pNewWnd)
2876 m_bMergeUndo = false;
2877 CCrystalTextView::OnKillFocus (pNewWnd);
2880 void CCrystalEditView::OnCharLeft()
2882 m_bMergeUndo = false;
2883 CCrystalTextView::OnCharLeft();
2886 void CCrystalEditView::OnExtCharLeft()
2888 m_bMergeUndo = false;
2889 CCrystalTextView::OnExtCharLeft();
2892 void CCrystalEditView::OnCharRight()
2894 m_bMergeUndo = false;
2895 CCrystalTextView::OnCharRight();
2898 void CCrystalEditView::OnExtCharRight()
2900 m_bMergeUndo = false;
2901 CCrystalTextView::OnExtCharRight();
2904 void CCrystalEditView::OnWordLeft()
2906 m_bMergeUndo = false;
2907 CCrystalTextView::OnWordLeft();
2910 void CCrystalEditView::OnExtWordLeft()
2912 m_bMergeUndo = false;
2913 CCrystalTextView::OnExtWordLeft();
2916 void CCrystalEditView::OnWordRight()
2918 m_bMergeUndo = false;
2919 CCrystalTextView::OnWordRight();
2922 void CCrystalEditView::OnExtWordRight()
2924 m_bMergeUndo = false;
2925 CCrystalTextView::OnExtWordRight();
2928 void CCrystalEditView::OnLineUp()
2930 m_bMergeUndo = false;
2931 CCrystalTextView::OnLineUp();
2934 void CCrystalEditView::OnExtLineUp()
2936 m_bMergeUndo = false;
2937 CCrystalTextView::OnExtLineUp();
2940 void CCrystalEditView::OnLineDown()
2942 m_bMergeUndo = false;
2943 CCrystalTextView::OnLineDown();
2946 void CCrystalEditView::OnExtLineDown()
2948 m_bMergeUndo = false;
2949 CCrystalTextView::OnExtLineDown();
2952 void CCrystalEditView::OnPageUp()
2954 m_bMergeUndo = false;
2955 CCrystalTextView::OnPageUp();
2958 void CCrystalEditView::OnExtPageUp()
2960 m_bMergeUndo = false;
2961 CCrystalTextView::OnExtPageUp();
2964 void CCrystalEditView::OnPageDown()
2966 m_bMergeUndo = false;
2967 CCrystalTextView::OnPageDown();
2970 void CCrystalEditView::OnExtPageDown()
2972 m_bMergeUndo = false;
2973 CCrystalTextView::OnExtPageDown();
2976 void CCrystalEditView::OnLineEnd()
2978 m_bMergeUndo = false;
2979 CCrystalTextView::OnLineEnd();
2982 void CCrystalEditView::OnExtLineEnd()
2984 m_bMergeUndo = false;
2985 CCrystalTextView::OnExtLineEnd();
2988 void CCrystalEditView::OnHome()
2990 m_bMergeUndo = false;
2991 CCrystalTextView::OnHome();
2994 void CCrystalEditView::OnExtHome()
2996 m_bMergeUndo = false;
2997 CCrystalTextView::OnExtHome();
3000 void CCrystalEditView::OnTextBegin()
3002 m_bMergeUndo = false;
3003 CCrystalTextView::OnTextBegin();
3006 void CCrystalEditView::OnExtTextBegin()
3008 m_bMergeUndo = false;
3009 CCrystalTextView::OnExtTextBegin();
3012 void CCrystalEditView::OnTextEnd()
3014 m_bMergeUndo = false;
3015 CCrystalTextView::OnTextEnd();
3018 void CCrystalEditView::OnExtTextEnd()
3020 m_bMergeUndo = false;
3021 CCrystalTextView::OnExtTextEnd();
3024 void CCrystalEditView::OnLButtonDown(UINT nFlags, CPoint point)
3026 m_bMergeUndo = false;
3027 CCrystalTextView::OnLButtonDown(nFlags, point);
3030 void CCrystalEditView::OnRButtonDown(UINT nFlags, CPoint point)
3032 m_bMergeUndo = false;
3033 CCrystalTextView::OnRButtonDown(nFlags, point);
3036 ////////////////////////////////////////////////////////////////////////////