// // Remove the current selection // BOOL TextView::OnClear() { BOOL success = FALSE; if(m_nEditMode == MODE_READONLY) return FALSE; if(SelectionSize() > 0) { ForwardDelete(); success = TRUE; } return success; }
// // Remove current selection and copy to the clipboard // BOOL TextView::OnCut() { BOOL success = FALSE; if(m_nEditMode == MODE_READONLY) return FALSE; if(SelectionSize() > 0) { // copy selected text to clipboard then erase current selection success = OnCopy(); success = success && ForwardDelete(); } return success; }
// // Process keyboard-navigation keys // LONG TextViewBase::OnKeyDown(UINT nKeyCode, UINT nFlags) { bool fCtrlDown = IsKeyPressed(VK_CONTROL); bool fShiftDown = IsKeyPressed(VK_SHIFT); BOOL fAdvancing = FALSE; long oldCursorOffset = m_nSelectionEnd; // // Process the key-press. Cursor movement is different depending // on if <ctrl> is held down or not, so act accordingly // switch(nKeyCode) { case VK_SHIFT: case VK_CONTROL: return 0; case 'a': case 'A': { if(fCtrlDown) SelectAll(); } return 0; // CTRL+Z undo case 'z': case 'Z': if(fCtrlDown && Undo()) /*NotifyParent(TVN_CHANGED);*/ return 0; // CTRL+Y redo case 'y': case 'Y': if(fCtrlDown && Redo()) //NotifyParent(TVN_CHANGED); return 0; // CTRL+C copy case 'c': case 'C': { //if(fCtrlDown && Redo()) // NotifyParent(TVN_CHANGED); if(fCtrlDown) return OnCopy(); else break; } case 'x': case 'X': { if(fCtrlDown) return OnCut(); else break; } case 'v': case 'V': { if(fCtrlDown) return OnPaste(); else break; } // Change insert mode / clipboard copy&paste case VK_INSERT: if(fCtrlDown) { OnCopy(); NotifyParent(TVN_CHANGED); } else if(fShiftDown) { OnPaste(); NotifyParent(TVN_CHANGED); } else { if(m_nEditMode == MODE_INSERT) m_nEditMode = MODE_OVERWRITE; else if(m_nEditMode == MODE_OVERWRITE) m_nEditMode = MODE_INSERT; NotifyParent(TVN_EDITMODE_CHANGE); } return 0; case VK_DELETE: if(m_nEditMode != MODE_READONLY) { if(fShiftDown) OnCut(); else ForwardDelete(); NotifyParent(TVN_CHANGED); } return 0; case VK_BACK: if(m_nEditMode != MODE_READONLY) { BackDelete(); fAdvancing = FALSE; NotifyParent(TVN_CHANGED); } return 0; case VK_LEFT: if(fCtrlDown) MoveWordPrev(); else MoveCharPrev(); fAdvancing = FALSE; break; case VK_RIGHT: if(fCtrlDown) MoveWordNext(); else MoveCharNext(); fAdvancing = TRUE; break; case VK_UP: if(fCtrlDown) Scroll(0, -1); else MoveLineUp(1); break; case VK_DOWN: if(fCtrlDown) Scroll(0, 1); else MoveLineDown(1); break; case VK_PRIOR: if(!fCtrlDown) MovePageUp(); break; case VK_NEXT: if(!fCtrlDown) MovePageDown(); break; case VK_HOME: if(fCtrlDown) MoveFileStart(); else MoveLineStart(m_nCurrentLine); break; case VK_END: if(fCtrlDown) MoveFileEnd(); else MoveLineEnd(m_nCurrentLine); break; default: return 0; } // Extend selection if <shift> is down if(fShiftDown) { InvalidateRange(m_nSelectionEnd, oldCursorOffset); //m_nSelectionEnd = m_nCursorOffset; } // Otherwise clear the selection else { if(m_nSelectionStart != m_nSelectionEnd) InvalidateRange(m_nSelectionStart, m_nSelectionEnd); //m_nSelectionEnd = m_nCursorOffset; m_nSelectionStart = m_nSelectionEnd; } // update caret-location (xpos, line#) from the offset //UpdateCaretOffset(m_nCursorOffset, fAdvancing, &m_nCaretPosX, &m_nCurrentLine); CHAR_POS cp; FilePosToCharPos(m_nSelectionEnd, &cp); m_nCurrentLine_D = cp.logLine; // maintain the caret 'anchor' position *except* for up/down actions if(nKeyCode != VK_UP && nKeyCode != VK_DOWN) { //m_nAnchorPosX = m_nCaretPosX; // scroll as necessary to keep caret within viewport //ScrollToPosition(m_nCaretPosX, m_nCurrentLine); } else { // scroll as necessary to keep caret within viewport if(!fCtrlDown); //ScrollToPosition(m_nCaretPosX, m_nCurrentLine); } NotifyParent(TVN_CURSOR_CHANGE); return 0; }
JBoolean JVIKeyHandler::HandleKeyPress ( const JCharacter key, const JBoolean selectText, const JTextEditor::CaretMotion motion, const JBoolean deleteToTabStop ) { JBoolean result; if (PrehandleKeyPress(key, &result)) { return result; } if (key == kJLeftArrow || key == kJRightArrow || key == kJUpArrow || key == kJDownArrow) { ClearKeyBuffers(); return kJFalse; } JTextEditor* te = GetTE(); JBoolean clearKeyBuffer = kJTrue; JArray<JIndexRange> matchList; JCharacter prevChar; if (key == 'i') { SetMode(kTextEntryMode); } else if (key == 'I') { SetMode(kTextEntryMode); const JBoolean save = te->WillMoveToFrontOfText(); te->ShouldMoveToFrontOfText(kJTrue); te->GoToEndOfLine(); te->GoToBeginningOfLine(); te->ShouldMoveToFrontOfText(save); } else if (key == 'a') { SetMode(kTextEntryMode); const JIndex i = te->GetInsertionIndex(); if (te->IndexValid(i) && (te->GetText()).GetCharacter(i) != '\n') { te->SetCaretLocation(te->GetInsertionIndex()+1); } } else if (key == 'A') { SetMode(kTextEntryMode); te->GoToEndOfLine(); } else if (key == 'O') { SetMode(kTextEntryMode); te->GoToBeginningOfLine(); const JIndex i = te->GetInsertionIndex(); te->SetCaretLocation(i-1); InsertKeyPress('\n'); if (i == 1) { te->SetCaretLocation(1); } } else if (key == 'o') { SetMode(kTextEntryMode); te->GoToEndOfLine(); InsertKeyPress('\n'); } else if ((key == '0' || key == '^') && itsKeyBuffer.IsEmpty()) { te->GoToBeginningOfLine(); } else if (key == '\n') { MoveCaretVert(1); const JBoolean save = te->WillMoveToFrontOfText(); te->ShouldMoveToFrontOfText(kJTrue); te->GoToEndOfLine(); te->GoToBeginningOfLine(); te->ShouldMoveToFrontOfText(save); } else if (key == 'G') { te->SetCaretLocation(te->GetTextLength()+1); } else if (isdigit(key)) // after 0 => beginning of line { if (!numberPattern.Match(itsKeyBuffer)) { ClearKeyBuffers(); } itsKeyBuffer.AppendCharacter(key); clearKeyBuffer = kJFalse; } else if (key == '"') { itsMode = kBufferNameMode; // don't use SetMode() itsKeyBuffer.AppendCharacter(key); clearKeyBuffer = kJFalse; } else if (key == 'X' || key == 'x') { CutBuffer* buf = GetCutBuffer(cutbufPattern); buf->Set("", kJFalse); const JSize count = GetOperationCount(); JString s; for (JIndex i=1; i<=count; i++) { if (key == 'X') { if (te->GetInsertionIndex() == 1) { break; } BackwardDelete(deleteToTabStop, &s); } else { if (te->GetInsertionIndex() >= te->GetTextLength()) { break; } ForwardDelete(deleteToTabStop, &s); } buf->buf->Append(s); } } else if (key == 'C' || key == 'D' || (key == '$' && GetPrevCharacter(&prevChar) && (prevChar == 'd' || prevChar == 'y'))) { const JBoolean del = JNegate(GetPrevCharacter(&prevChar) && prevChar == 'y' && key == '$'); YankToEndOfLine(del, JI2B(key == 'C')); } else if ((key == 'Y' || key == 'y' || key == 'd') && yankDeletePattern.Match(itsKeyBuffer, &matchList)) { if (key == 'Y' || (GetPrevCharacter(&prevChar) && prevChar == key)) { YankLines(matchList, JI2B(key == 'd')); } else { itsKeyBuffer.AppendCharacter(key); clearKeyBuffer = kJFalse; } } else if (key == 'P' || key == 'p') { CutBuffer* buf = GetCutBuffer(cutbufPattern); if (buf->buf != NULL) { const JIndex i = te->GetInsertionIndex(); if (buf->line) { te->GoToBeginningOfLine(); if (key == 'p') { MoveCaretVert(1); } } else if (key == 'p' && (te->IndexValid(i) && (te->GetText()).GetCharacter(i) != '\n')) { te->SetCaretLocation(te->GetInsertionIndex()+1); } const JSize count = GetOperationCount(); for (JIndex i=1; i<=count; i++) { te->Paste(*(buf->buf)); } } } else if (key == 'u') { te->Undo(); } else if (key == '$') // after d$ and y$ { te->GoToEndOfLine(); const JIndex i = te->GetInsertionIndex(); if (i > 1 && te->IndexValid(i) && (te->GetText()).GetCharacter(i) == '\n') { te->SetCaretLocation(i-1); } } if (clearKeyBuffer) { ClearKeyBuffers(); } return kJTrue; }
LRESULT HexView::OnKeyDown(UINT nVirtualKey, UINT nRepeatCount, UINT nFlags) { BOOL fForceUpdate = FALSE; bool fCtrlDown = IsKeyDown(VK_CONTROL); bool fShiftDown = IsKeyDown(VK_SHIFT); size_w oldoffset = m_nCursorOffset; fForceUpdate = !IsKeyDown(VK_SHIFT); if(nVirtualKey == VK_CONTROL || nVirtualKey == VK_SHIFT || nVirtualKey == VK_MENU) return 0; switch(nVirtualKey) { case VK_ESCAPE: fForceUpdate = TRUE; break; case VK_INSERT: if(fCtrlDown) { OnCopy(); } else if(fShiftDown) { OnPaste(); } else { if(m_nEditMode == HVMODE_INSERT) m_nEditMode = HVMODE_OVERWRITE; else if(m_nEditMode == HVMODE_OVERWRITE) m_nEditMode = HVMODE_INSERT; NotifyParent(HVN_EDITMODE_CHANGE); } return 0; case 'z': case 'Z': m_nSubItem = 0; if(fCtrlDown) Undo(); return 0; // CTRL+Y redo case 'y': case 'Y': m_nSubItem = 0; if(fCtrlDown) Redo(); return 0; case VK_DELETE: // can only erase when in Insert mode if(m_nEditMode == HVMODE_INSERT || CheckStyle(HVS_ALWAYSDELETE) && (m_nEditMode == HVMODE_INSERT || m_nEditMode == HVMODE_OVERWRITE) && SelectionSize() == 0) { ForwardDelete(); } else if(m_nEditMode != HVMODE_READONLY) { BYTE b[] = { 0 }; FillData(b, 1, SelectionSize()); } return 0; case VK_BACK: // can only erase when in Insert mode if(m_nEditMode == HVMODE_INSERT || CheckStyle(HVS_ALWAYSDELETE) && (m_nEditMode == HVMODE_INSERT || m_nEditMode == HVMODE_OVERWRITE)) { BackDelete(); } else { //PostMessage(m_hWnd, WM_KEYDOWN, INPUT inp = { INPUT_KEYBOARD }; inp.ki.wVk = VK_LEFT; SendInput(1, &inp, sizeof(inp)); } return 0; case VK_LEFT: //if ctrl held down, then scroll the viewport around! if(IsKeyDown(VK_CONTROL)) { PostMessage(m_hWnd, WM_HSCROLL, SB_LINEUP, 0L); return 0; } if(m_nCursorOffset > 0) m_nCursorOffset--; m_fCursorAdjustment = FALSE; break; case VK_RIGHT: //if ctrl held down, then scroll the viewport around! if(IsKeyDown(VK_CONTROL)) { PostMessage(m_hWnd, WM_HSCROLL, SB_LINEDOWN, 0L); return 0; } if(m_nCursorOffset < m_pDataSeq->size()) { m_nCursorOffset++; if(m_nCursorOffset == m_pDataSeq->size() && m_pDataSeq->size() % m_nBytesPerLine == 0) m_fCursorAdjustment = TRUE; else m_fCursorAdjustment = FALSE; } break; case VK_UP: //if ctrl held down, then scroll the viewport around! if(IsKeyDown(VK_CONTROL)) { PostMessage(m_hWnd, WM_VSCROLL, SB_LINEUP, 0L); return 0; } if(m_nCursorOffset > (unsigned)m_nBytesPerLine) m_nCursorOffset -= m_nBytesPerLine; break; case VK_DOWN: //if ctrl held down, then scroll the viewport around! if(IsKeyDown(VK_CONTROL)) { PostMessage(m_hWnd, WM_VSCROLL, SB_LINEDOWN, 0L); return 0; } m_nCursorOffset += min((size_w)m_nBytesPerLine, m_pDataSeq->size() - m_nCursorOffset); // if in the last partial line, don't go to end of file, rather // stay at "bottom" of file/window if(m_nCursorOffset >= m_pDataSeq->size() && !m_fCursorAdjustment) { // test if in a partial line if( oldoffset % m_nBytesPerLine < m_pDataSeq->size() % m_nBytesPerLine || m_pDataSeq->size() % m_nBytesPerLine == 0) { m_nCursorOffset = oldoffset; fForceUpdate = TRUE; } } break; case VK_HOME: //if ctrl held down, then scroll the viewport around! if(fCtrlDown) { m_nCursorOffset = 0; PostMessage(m_hWnd, WM_VSCROLL, SB_TOP, 0L); } else { if(m_fCursorAdjustment && m_nCursorOffset > 0) m_nCursorOffset--; m_nCursorOffset -= m_nCursorOffset % m_nBytesPerLine; } m_fCursorAdjustment = FALSE; break; case VK_END: if(IsKeyDown(VK_CONTROL)) { m_nCursorOffset = m_pDataSeq->size(); if(m_nCursorOffset % m_nBytesPerLine == 0) m_fCursorAdjustment = TRUE; PostMessage(m_hWnd, WM_VSCROLL, SB_BOTTOM, 0L); } else { // if not already at very end of line if(m_fCursorAdjustment == FALSE) { if(m_pDataSeq->size() - m_nBytesPerLine >= m_nCursorOffset && m_pDataSeq->size() >= m_nBytesPerLine) { m_nCursorOffset += m_nBytesPerLine - (m_nCursorOffset % m_nBytesPerLine); m_fCursorAdjustment = TRUE; } else { m_nCursorOffset += m_pDataSeq->size()-m_nCursorOffset; } } if(m_nCursorOffset >= m_pDataSeq->size() && m_pDataSeq->size() % m_nBytesPerLine == 0) m_fCursorAdjustment = TRUE; } break; case VK_PRIOR: // pageup m_nCursorOffset -= min(m_nCursorOffset, (size_w)m_nBytesPerLine * m_nWindowLines); break; case VK_NEXT: // pagedown m_nCursorOffset += min(m_pDataSeq->size() - m_nCursorOffset, (size_w)m_nBytesPerLine * m_nWindowLines); if(m_nCursorOffset >= m_pDataSeq->size() && m_pDataSeq->size() % m_nBytesPerLine == 0) { m_fCursorAdjustment = TRUE; } break; case VK_TAB: m_nWhichPane ^= 1; fForceUpdate = TRUE; if(m_ColourList[HVC_SELECTION] != m_ColourList[HVC_SELECTION2]) { InvalidateRange(m_nSelectionStart, m_nSelectionEnd); } break; default: // don't know what this key is, so exit return 0; } m_nSubItem = 0; if(m_nCursorOffset != oldoffset || fForceUpdate) { // SHIFT key being held down? if(IsKeyDown(VK_SHIFT)) { // extend the selection m_nSelectionEnd = m_nCursorOffset; InvalidateRange(oldoffset, m_nSelectionEnd); } else if(nVirtualKey != VK_TAB) { // clear any selection if(m_nSelectionEnd != m_nSelectionStart) InvalidateRange(m_nSelectionEnd, m_nSelectionStart); m_nSelectionEnd = m_nCursorOffset; m_nSelectionStart = m_nCursorOffset; } ScrollToCaret(); NotifyParent(HVN_CURSOR_CHANGE); if(nVirtualKey == VK_NEXT || nVirtualKey == VK_PRIOR) { RefreshWindow(); } } return 0; }