// Test for distance between caret and text that will be deleted nsresult nsTextEditRules::CheckBidiLevelForDeletion(nsISelection *aSelection, nsIDOMNode *aSelNode, PRInt32 aSelOffset, nsIEditor::EDirection aAction, bool *aCancel) { NS_ENSURE_ARG_POINTER(aCancel); *aCancel = false; nsCOMPtr<nsIPresShell> shell = mEditor->GetPresShell(); NS_ENSURE_TRUE(shell, NS_ERROR_NOT_INITIALIZED); nsPresContext *context = shell->GetPresContext(); NS_ENSURE_TRUE(context, NS_ERROR_NULL_POINTER); if (!context->BidiEnabled()) return NS_OK; nsCOMPtr<nsIContent> content = do_QueryInterface(aSelNode); NS_ENSURE_TRUE(content, NS_ERROR_NULL_POINTER); PRUint8 levelBefore; PRUint8 levelAfter; nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(aSelection)); NS_ENSURE_TRUE(privateSelection, NS_ERROR_NULL_POINTER); nsRefPtr<nsFrameSelection> frameSelection; privateSelection->GetFrameSelection(getter_AddRefs(frameSelection)); NS_ENSURE_TRUE(frameSelection, NS_ERROR_NULL_POINTER); nsPrevNextBidiLevels levels = frameSelection-> GetPrevNextBidiLevels(content, aSelOffset, true); levelBefore = levels.mLevelBefore; levelAfter = levels.mLevelAfter; PRUint8 currentCaretLevel = frameSelection->GetCaretBidiLevel(); PRUint8 levelOfDeletion; levelOfDeletion = (nsIEditor::eNext==aAction || nsIEditor::eNextWord==aAction) ? levelAfter : levelBefore; if (currentCaretLevel == levelOfDeletion) ; // perform the deletion else { if (mDeleteBidiImmediately || levelBefore == levelAfter) ; // perform the deletion else *aCancel = true; // Set the bidi level of the caret to that of the // character that will be (or would have been) deleted frameSelection->SetCaretBidiLevel(levelOfDeletion); } return NS_OK; }
//----------------------------------------------------------------------------- already_AddRefed<nsFrameSelection> nsCaret::GetFrameSelection() { nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryReferent(mDomSelectionWeak)); if (!privateSelection) return nsnull; nsFrameSelection* frameSelection = nsnull; privateSelection->GetFrameSelection(&frameSelection); return frameSelection; }
NS_IMETHODIMP nsTextEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection) { if (mLockRulesSniffing) return NS_OK; nsAutoLockRulesSniffing lockIt(this); NS_PRECONDITION(mActionNesting>0, "bad action nesting!"); nsresult res = NS_OK; if (!--mActionNesting) { nsCOMPtr<nsISelection>selection; res = mEditor->GetSelection(getter_AddRefs(selection)); NS_ENSURE_SUCCESS(res, res); res = mEditor->HandleInlineSpellCheck(action, selection, mCachedSelectionNode, mCachedSelectionOffset, nsnull, 0, nsnull, 0); NS_ENSURE_SUCCESS(res, res); // detect empty doc res = CreateBogusNodeIfNeeded(selection); NS_ENSURE_SUCCESS(res, res); // insure trailing br node res = CreateTrailingBRIfNeeded(); NS_ENSURE_SUCCESS(res, res); // collapse the selection to the trailing BR if it's at the end of our text node CollapseSelectionToTrailingBRIfNeeded(selection); /* After inserting text the cursor Bidi level must be set to the level of the inserted text. * This is difficult, because we cannot know what the level is until after the Bidi algorithm * is applied to the whole paragraph. * * So we set the cursor Bidi level to UNDEFINED here, and the caret code will set it correctly later */ if (action == nsEditor::kOpInsertText || action == nsEditor::kOpInsertIMEText) { nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(selection)); nsCOMPtr<nsFrameSelection> frameSelection; privateSelection->GetFrameSelection(getter_AddRefs(frameSelection)); if (frameSelection) { frameSelection->UndefineCaretBidiLevel(); } } } return res; }
//----------------------------------------------------------------------------- void nsCaret::Terminate() { // this doesn't erase the caret if it's drawn. Should it? We might not have // a good drawing environment during teardown. KillTimer(); mBlinkTimer = nsnull; // unregiser ourselves as a selection listener nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak); nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection)); if (privateSelection) privateSelection->RemoveSelectionListener(this); mDomSelectionWeak = nsnull; mPresShell = nsnull; mLastContent = nsnull; }
void nsCaret::DrawCaret(PRBool aInvalidate) { // Do we need to draw the caret at all? if (!MustDrawCaret(PR_FALSE)) return; // Can we draw the caret now? nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell); NS_ENSURE_TRUE(presShell, /**/); { PRBool isPaintingSuppressed; presShell->IsPaintingSuppressed(&isPaintingSuppressed); if (isPaintingSuppressed) { if (!mDrawn) mPendingDraw = PR_TRUE; // PresShell::UnsuppressAndInvalidate() will call CheckCaretDrawingState() // to get us drawn. return; } } nsCOMPtr<nsIDOMNode> node; PRInt32 offset; nsFrameSelection::HINT hint; PRUint8 bidiLevel; if (!mDrawn) { nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak); nsCOMPtr<nsISelectionPrivate> privateSelection(do_QueryInterface(domSelection)); if (!privateSelection) return; PRBool isCollapsed = PR_FALSE; domSelection->GetIsCollapsed(&isCollapsed); if (!mShowDuringSelection && !isCollapsed) return; PRBool hintRight; privateSelection->GetInterlinePosition(&hintRight);//translate hint. hint = hintRight ? nsFrameSelection::HINTRIGHT : nsFrameSelection::HINTLEFT; // get the node and offset, which is where we want the caret to draw domSelection->GetFocusNode(getter_AddRefs(node)); if (!node) return; if (NS_FAILED(domSelection->GetFocusOffset(&offset))) return; nsCOMPtr<nsFrameSelection> frameSelection = GetFrameSelection(); if (!frameSelection) return; bidiLevel = frameSelection->GetCaretBidiLevel(); mPendingDraw = PR_FALSE; } else { if (!mLastContent) { mDrawn = PR_FALSE; return; } if (!mLastContent->IsInDoc()) { mLastContent = nsnull; mDrawn = PR_FALSE; return; } node = do_QueryInterface(mLastContent); offset = mLastContentOffset; hint = mLastHint; bidiLevel = mLastBidiLevel; } DrawAtPositionWithHint(node, offset, hint, bidiLevel, aInvalidate); ToggleDrawnStatus(); }