Fix bidi behavior of ctrl+backspace and ctrl+del. bug=344226 r=smontagu sr=roc

This commit is contained in:
uriber%gmail.com 2006-07-18 07:28:38 +00:00
parent de394c31ae
commit 3bef115769
6 changed files with 57 additions and 24 deletions

View File

@ -164,6 +164,12 @@ interface nsISelectionController : nsISelectionDisplay
void wordMove(in boolean forward, in boolean extend);
/** wordExtendForDelete will extend the selection one word forward/backward in the document.
* this method is used internally for handling ctrl[option]-backspace and ctrl[option]-del.
* @param aForward forward or backward if PR_FALSE
*/
[noscript] void wordExtendForDelete(in boolean forward);
/** LineMove will move the selection one line forward/backward in the document.
* this will also have the effect of collapsing the selection if the aExtend = PR_FALSE
* the "point" of selection that is extended is considered the "focus" point.

View File

@ -637,34 +637,20 @@ NS_IMETHODIMP nsPlaintextEditor::DeleteSelection(nsIEditor::EDirection aAction)
if (aAction == eNextWord || aAction == ePreviousWord
|| aAction == eToBeginningOfLine || aAction == eToEndOfLine)
{
if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps) return NS_ERROR_NOT_INITIALIZED;
PRUint8 caretBidiLevel;
result = ps->GetCaretBidiLevel(&caretBidiLevel);
if (NS_FAILED(result)) return result;
nsCOMPtr<nsISelectionController> selCont (do_QueryReferent(mSelConWeak));
if (!selCont)
return NS_ERROR_NO_INTERFACE;
switch (aAction)
{
// if caret has odd Bidi level, i.e. text is right-to-left,
// reverse the effect of ePreviousWord and eNextWord
case eNextWord:
result = (caretBidiLevel & 1) ?
selCont->WordMove(PR_FALSE, PR_TRUE) :
selCont->WordMove(PR_TRUE, PR_TRUE);
result = selCont->WordExtendForDelete(PR_TRUE);
// DeleteSelectionImpl doesn't handle these actions
// because it's inside batching, so don't confuse it:
aAction = eNone;
break;
case ePreviousWord:
result = (caretBidiLevel & 1) ?
selCont->WordMove(PR_TRUE, PR_TRUE) :
selCont->WordMove(PR_FALSE, PR_TRUE);
result = selCont->WordExtendForDelete(PR_FALSE);
aAction = eNone;
break;
case eToBeginningOfLine:

View File

@ -1205,6 +1205,7 @@ public:
NS_IMETHOD CharacterMove(PRBool aForward, PRBool aExtend);
NS_IMETHOD WordMove(PRBool aForward, PRBool aExtend);
NS_IMETHOD WordExtendForDelete(PRBool aForward);
NS_IMETHOD LineMove(PRBool aForward, PRBool aExtend);
NS_IMETHOD IntraLineMove(PRBool aForward, PRBool aExtend);
NS_IMETHOD PageMove(PRBool aForward, PRBool aExtend);
@ -3293,6 +3294,12 @@ PresShell::WordMove(PRBool aForward, PRBool aExtend)
return mSelection->WordMove(aForward, aExtend);
}
NS_IMETHODIMP
PresShell::WordExtendForDelete(PRBool aForward)
{
return mSelection->WordExtendForDelete(aForward);
}
NS_IMETHODIMP
PresShell::LineMove(PRBool aForward, PRBool aExtend)
{

View File

@ -610,6 +610,7 @@ public:
NS_IMETHOD SetCaretVisibilityDuringSelection(PRBool aVisibility);
NS_IMETHOD CharacterMove(PRBool aForward, PRBool aExtend);
NS_IMETHOD WordMove(PRBool aForward, PRBool aExtend);
NS_IMETHOD WordExtendForDelete(PRBool aForward);
NS_IMETHOD LineMove(PRBool aForward, PRBool aExtend);
NS_IMETHOD IntraLineMove(PRBool aForward, PRBool aExtend);
NS_IMETHOD PageMove(PRBool aForward, PRBool aExtend);
@ -830,6 +831,13 @@ nsTextInputSelectionImpl::WordMove(PRBool aForward, PRBool aExtend)
return NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP
nsTextInputSelectionImpl::WordExtendForDelete(PRBool aForward)
{
if (mFrameSelection)
return mFrameSelection->WordExtendForDelete(aForward);
return NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP
nsTextInputSelectionImpl::LineMove(PRBool aForward, PRBool aExtend)

View File

@ -367,6 +367,12 @@ public:
*/
nsresult WordMove(PRBool aForward, PRBool aExtend);
/** WordExtendForDelete extends the selection backward or forward (logically) to the
* next word boundary, so that the selected word can be deleted.
* @param aForward select forward in document.
*/
nsresult WordExtendForDelete(PRBool aForward);
/** LineMove will generally be called from the nsiselectioncontroller implementations.
* the effect being the selection will move one line up or down.
* @param aForward move forward in document.

View File

@ -1203,9 +1203,12 @@ nsFrameSelection::MoveCaret(PRUint32 aKeycode,
nsCOMPtr<nsIDOMNode> parentNode;
nsPeekOffsetStruct pos;
PRBool visualMovement = mCaretMovementStyle == 1 ||
(mCaretMovementStyle == 2 && !aContinueSelection);
PRBool visualMovement =
(aKeycode == nsIDOMKeyEvent::DOM_VK_BACK_SPACE ||
aKeycode == nsIDOMKeyEvent::DOM_VK_DELETE) ?
PR_FALSE : // Delete operations are always logical
mCaretMovementStyle == 1 || (mCaretMovementStyle == 2 && !aContinueSelection);
//set data using mLimiter to stop on scroll views. If we have a limiter then we stop peeking
//when we hit scrollable views. If no limiter then just let it go ahead
pos.SetData(aAmount, eDirPrevious, offsetused, desiredX,
@ -1219,16 +1222,25 @@ nsFrameSelection::MoveCaret(PRUint32 aKeycode,
InvalidateDesiredX();
pos.mDirection = (baseLevel & 1) ? eDirPrevious : eDirNext;
break;
case nsIDOMKeyEvent::DOM_VK_LEFT : //no break
case nsIDOMKeyEvent::DOM_VK_LEFT :
InvalidateDesiredX();
pos.mDirection = (baseLevel & 1) ? eDirNext : eDirPrevious;
break;
case nsIDOMKeyEvent::DOM_VK_DELETE :
InvalidateDesiredX();
pos.mDirection = eDirNext;
break;
case nsIDOMKeyEvent::DOM_VK_BACK_SPACE :
InvalidateDesiredX();
pos.mDirection = eDirPrevious;
break;
case nsIDOMKeyEvent::DOM_VK_DOWN :
pos.mAmount = eSelectLine;
pos.mDirection = eDirNext;//no break here
pos.mDirection = eDirNext;
break;
case nsIDOMKeyEvent::DOM_VK_UP :
pos.mAmount = eSelectLine;
pos.mDirection = eDirPrevious;
break;
case nsIDOMKeyEvent::DOM_VK_HOME :
InvalidateDesiredX();
@ -1237,7 +1249,7 @@ nsFrameSelection::MoveCaret(PRUint32 aKeycode,
case nsIDOMKeyEvent::DOM_VK_END :
InvalidateDesiredX();
pos.mAmount = eSelectEndLine;
break;
break;
default :return NS_ERROR_FAILURE;
}
PostReason(nsISelectionListener::KEYPRESS_REASON);
@ -1246,8 +1258,7 @@ nsFrameSelection::MoveCaret(PRUint32 aKeycode,
nsIFrame *theFrame;
PRInt32 currentOffset, frameStart, frameEnd;
if (aKeycode == nsIDOMKeyEvent::DOM_VK_RIGHT ||
aKeycode == nsIDOMKeyEvent::DOM_VK_LEFT)
if (aAmount == eSelectCharacter || aAmount == eSelectWord)
{
// For left/right, PeekOffset() sets pos.mResultFrame correctly, but does not set pos.mAttachForward,
// so determine the hint here based on the result frame and offset:
@ -2760,6 +2771,15 @@ nsFrameSelection::WordMove(PRBool aForward, PRBool aExtend)
return MoveCaret(nsIDOMKeyEvent::DOM_VK_LEFT,aExtend,eSelectWord);
}
nsresult
nsFrameSelection::WordExtendForDelete(PRBool aForward)
{
if (aForward)
return MoveCaret(nsIDOMKeyEvent::DOM_VK_DELETE, PR_TRUE, eSelectWord);
else
return MoveCaret(nsIDOMKeyEvent::DOM_VK_BACK_SPACE, PR_TRUE, eSelectWord);
}
nsresult
nsFrameSelection::LineMove(PRBool aForward, PRBool aExtend)
{