BOOL CCrystalTextBuffer::InsertText(CCrystalTextView *pSource, int nLine, int nPos, LPCTSTR pszText, int &nEndLine, int &nEndChar, LPCTSTR cpDesc ) { if (! InternalInsertText(pSource, nLine, nPos, pszText, nEndLine, nEndChar)) return FALSE; BOOL bGroupFlag = FALSE; if (! m_bUndoGroup) { BeginUndoGroup(); bGroupFlag = TRUE; } AddUndoRecord(TRUE, CPoint(nPos, nLine), CPoint(nEndChar, nEndLine), pszText, cpDesc ); if (bGroupFlag) FlushUndoGroup(); return TRUE; }
BOOL CCrystalTextBuffer::DeleteText(CCrystalTextView *pSource, int nStartLine, int nStartChar, int nEndLine, int nEndChar, LPCTSTR cpDesc ) { CString sTextToDelete; GetText(nStartLine, nStartChar, nEndLine, nEndChar, sTextToDelete); if (! InternalDeleteText(pSource, nStartLine, nStartChar, nEndLine, nEndChar)) return FALSE; BOOL bGroupFlag = FALSE; if (! m_bUndoGroup) { BeginUndoGroup(); bGroupFlag = TRUE; } AddUndoRecord(FALSE, CPoint(nStartChar, nStartLine), CPoint(nEndChar, nEndLine), sTextToDelete, cpDesc ); if (bGroupFlag) FlushUndoGroup(); return TRUE; }
// insert separator feature void CSpacerView::MouseDown(BPoint where) { static const char *bigsep = "\n/*\nvoid c------------------------------() {}\n*/\n"; static const char *smallsep = "// ---------------------------------------\n"; EditView *ev = editor.curev; uint32 buttons; if (!ev) return; LockWindow(); int y = ev->scroll.y + ((int)where.y / editor.font_height); if (y < 0) y = 0; if (y >= ev->nlines) y = (ev->nlines - 1); clLine *line = ev->GetLineHandle(y); if (!line) { UnlockWindow(); return; } GetMouse(&where, &buttons); const char *sep = (buttons & B_SECONDARY_MOUSE_BUTTON) ? smallsep : bigsep; BeginUndoGroup(ev); ev->action_insert_string(0, y, sep, NULL, NULL); EndUndoGroup(ev); ev->RedrawView(); if (sep == bigsep) FunctionList->ScanIfNeeded(); UnlockWindow(); }
// deletes a selection and it's contents void EditView::SelDel() { EditView *ev = this; int old_cy; if (ev->selection.present) { int x1, y1, x2, y2; BeginUndoGroup(ev); GetSelectionExtents(ev, &x1, &y1, &x2, &y2); lstat2(" ** SelDel from [%d,%d] - [%d,%d]", x1, y1, x2, y2); // remember current screen position of cursor old_cy = ev->cursor.screen_y; // when undoing a seldel always move cursor to the end of the deleted text DocPoint endpt(ev, x2, y2); endpt.Increment(); // delete selection and it's contents selection_drop(ev); ev->action_delete_range(x1, y1, x2, y2); // move to start of selection ev->cursor.move(x1, y1); // ensure cursor is still visible, and try to keep it at the // same screen Y position it was at before (when deleting a large portion of text) ev->BringLineIntoView(ev->cursor.y, BV_SPECIFIC_Y, old_cy); XScrollToCursor(); EndUndoGroupSetCursor(ev, endpt.x, endpt.y); } }
// process the key void ProcessKey(EditView *ev, int key) { uint flags = GetKeyAttr(key); char MergeToPrior; // free xseek mode if (ev->cursor.xseekmode != CM_FREE) { switch(key) { // these need to maintain the state of the CM_WANT_SCREEN_COORD coordinate case B_UP_ARROW: case B_DOWN_ARROW: case B_PAGE_UP: case B_PAGE_DOWN: break; default: ev->cursor.set_mode(CM_FREE); } } // commands which delete selection & contents if a selection is present if (flags & KF_SELDEL) { if (ev->selection.present) { ev->SelDel(); if (flags & KF_SELDEL_ONLY) return; } } // create new undo group before executing keys which modify the document if (flags & KF_UNDOABLE) { if (flags & KF_UNDO_MERGEABLE) { MergeToPrior = undo_can_merge(ev, ev->cursor.x, ev->cursor.y, key); if (!MergeToPrior) BeginUndoGroup(ev); } else { MergeToPrior = 0; BeginUndoGroup(ev); } } if (flags & KF_AFFECTS_SELECTION) // key can create/remove selection { if (IsShiftDown() && !ev->selection.present) selection_create(ev); } switch(key) { case B_ESCAPE: if (editor.settings.esc_quits_immediately) // a testmode { MainWindow->fDoingInstantQuit = true; be_app->PostMessage(B_QUIT_REQUESTED); } break; case B_LEFT_ARROW: ev->cursor.left(); break; case B_RIGHT_ARROW: ev->cursor.right(); break; case B_UP_ARROW: ev->cursor.up(); break; case B_DOWN_ARROW: ev->cursor.down(); break; case B_PAGE_DOWN: ev->cursor.pgdn(); break; case B_PAGE_UP: ev->cursor.pgup(); break; case B_HOME: DoHome(ev); break; case B_END: DoEnd(ev); break; case KEY_MOUSEWHEEL_DOWN: ev->scroll_down(3); break; case KEY_MOUSEWHEEL_UP: ev->scroll_up(3); break; case B_ENTER: DoEnter(ev); editor.stats.CRs_typed++; editor.stats.keystrokes_typed++; break; case B_TAB: { if (IsShiftDown()) { DoShiftTab(ev); break; } if (DoTabIndent(ev)) break; ev->SelDel(); ev->action_insert_char(ev->cursor.x, ev->cursor.y, TAB); ev->cursor.x++; editor.stats.keystrokes_typed++; } break; // BKSP is equivalent to left followed by del case B_BACKSPACE: if (!ev->cursor.y && !ev->cursor.x) break; ev->cursor.left(); undo_SetMergeMode(ev, MERGE_BKSP, MergeToPrior); ev->action_delete_right(ev->cursor.x, ev->cursor.y, 1); editor.stats.keystrokes_typed++; break; case B_DELETE: undo_SetMergeMode(ev, MERGE_DEL, MergeToPrior); ev->action_delete_right(ev->cursor.x, ev->cursor.y, 1); editor.stats.keystrokes_typed++; break; // typing default: { // ignore non-printable keystrokes if (key > 127 || key < 9) break; if (editor.InOverwriteMode && \ ev->cursor.x < ev->curline->GetLength()) { // less than ideal: i wasn't planning on Overwrite Mode when writing // the undo feature, so it can't merge undo records that contain both a // delete and a insertion. OVR mode isn't used much and undo still works, // just one char at a time, so I think it's ok for now but eventually should // be looked at. if (MergeToPrior) { MergeToPrior = false; BeginUndoGroup(ev); } ev->action_delete_right(ev->cursor.x, ev->cursor.y, 1); } else { undo_SetMergeMode(ev, MERGE_TYPING, MergeToPrior); } ev->action_insert_char(ev->cursor.x, ev->cursor.y, key); ev->cursor.x++; editor.stats.keystrokes_typed++; } break; } // smart indent (for close quotes) if (key == '}' && editor.settings.smart_indent_on_close) CloseSmartIndent(ev); if (flags & KF_AFFECTS_SELECTION) ev->ExtendOrDropSel(key); if (flags & KF_UNDOABLE) { if (MergeToPrior) UpdateMergedUndoGroup(ev); else EndUndoGroup(ev); } if (!(flags & KF_NO_VIEW_TO_CURSOR)) { ev->MakeCursorVisible(); } }