--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -113,17 +113,17 @@
#include "jsapi.h"
#include "nsNodeInfoManager.h"
#include "nsICategoryManager.h"
#include "nsIDOMNSFeatureFactory.h"
#include "nsIDOMDocumentType.h"
#include "nsIDOMUserDataHandler.h"
-#include "nsGenericHTMLElement.h"
+#include "nsIDOMNSEditableElement.h"
#include "nsIEditor.h"
#include "nsIEditorDocShell.h"
#include "nsEventDispatcher.h"
#include "nsContentCreatorFunctions.h"
#include "nsIFocusController.h"
#include "nsIControllers.h"
#include "nsLayoutUtils.h"
#include "nsIView.h"
@@ -338,25 +338,23 @@ static nsIContent* GetEditorRootContent(
}
nsIContent*
nsINode::GetTextEditorRootContent(nsIEditor** aEditor)
{
if (aEditor)
*aEditor = nsnull;
for (nsINode* node = this; node; node = node->GetNodeParent()) {
- if (!node->IsNodeOfType(eHTML))
+ nsCOMPtr<nsIDOMNSEditableElement> editableElement(do_QueryInterface(node));
+ if (!editableElement)
continue;
nsCOMPtr<nsIEditor> editor;
- static_cast<nsGenericHTMLElement*>(node)->
- GetEditorInternal(getter_AddRefs(editor));
- if (!editor)
- continue;
-
+ editableElement->GetEditor(getter_AddRefs(editor));
+ NS_ENSURE_TRUE(editor, nsnull);
nsIContent* rootContent = GetEditorRootContent(editor);
if (aEditor)
editor.swap(*aEditor);
return rootContent;
}
return nsnull;
}
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -57,19 +57,17 @@
#undef small
#endif
//---------------------------------------------------------------------------
// Generic atoms
//---------------------------------------------------------------------------
GK_ATOM(_empty, "")
-GK_ATOM(moz, "_moz")
GK_ATOM(mozdirty, "_moz_dirty")
-GK_ATOM(mozeditorbogusnode, "_moz_editor_bogus_node")
GK_ATOM(mozgeneratedcontentbefore, "_moz_generated_content_before")
GK_ATOM(mozgeneratedcontentafter, "_moz_generated_content_after")
GK_ATOM(mozgeneratedcontentimage, "_moz_generated_content_image")
GK_ATOM(_moz_target, "_moz_target")
GK_ATOM(menuactive, "_moz-menuactive")
GK_ATOM(_poundDefault, "#default")
GK_ATOM(_asterix, "*")
GK_ATOM(a, "a")
--- a/content/events/src/Makefile.in
+++ b/content/events/src/Makefile.in
@@ -86,17 +86,17 @@ CPPSRCS = \
nsDOMMessageEvent.cpp \
nsPrivateTextRange.cpp \
nsDOMEventGroup.cpp \
nsXMLEventsManager.cpp \
nsXMLEventsElement.cpp \
nsPLDOMEvent.cpp \
nsEventDispatcher.cpp \
nsIMEStateManager.cpp \
- nsContentEventHandler.cpp \
+ nsQueryContentEventHandler.cpp \
nsDOMProgressEvent.cpp \
nsDOMDataTransfer.cpp \
nsDOMNotifyPaintEvent.cpp \
nsDOMSimpleGestureEvent.cpp \
$(NULL)
# we don't want the shared lib, but we want to force the creation of a static lib.
FORCE_STATIC_LIB = 1
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -23,17 +23,16 @@
* Contributor(s):
* Makoto Kato <m_kato@ga2.so-net.ne.jp>
* Dean Tessman <dean_tessman@hotmail.com>
* Mats Palmgren <mats.palmgren@bredband.net>
* Masayuki Nakano <masayuki@d-toybox.com>
* Ginn Chen <ginn.chen@sun.com>
* Simon Bünzli <zeniko@gmail.com>
* Ehsan Akhgari <ehsan.akhgari@gmail.com>
- * Ningjie Chen <chenn@email.uc.edu>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
@@ -43,17 +42,17 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h"
#include "nsEventStateManager.h"
#include "nsEventListenerManager.h"
#include "nsIMEStateManager.h"
-#include "nsContentEventHandler.h"
+#include "nsQueryContentEventHandler.h"
#include "nsIContent.h"
#include "nsINodeInfo.h"
#include "nsIDocument.h"
#include "nsIFrame.h"
#include "nsIWidget.h"
#include "nsPresContext.h"
#include "nsIPresShell.h"
#include "nsDOMEvent.h"
@@ -1055,18 +1054,16 @@ nsEventStateManager::PreHandleEvent(nsPr
// If the document didn't change, then the only thing that could have
// changed is the focused content node. That's handled elsewhere
// (SetContentState and SendFocusBlur).
if (gLastFocusedDocument == mDocument)
break;
if (mDocument) {
- nsIMEStateManager::OnTextStateBlur(mPresContext, mCurrentFocus);
-
if (gLastFocusedDocument && gLastFocusedPresContextWeak) {
nsCOMPtr<nsPIDOMWindow> ourWindow =
gLastFocusedDocument->GetWindow();
// If the focus controller is already suppressed, it means that we
// are in the middle of an activate sequence. In this case, we do
// _not_ want to fire a blur on the previously focused content, since
// we will be focusing it again later when we receive the NS_ACTIVATE
@@ -1174,18 +1171,16 @@ nsEventStateManager::PreHandleEvent(nsPr
focusevent.target = nsnull;
nsEventDispatcher::Dispatch(window, aPresContext, &focusevent,
nsnull, &status);
SetFocusedContent(currentFocus); // we kept this reference above
NS_IF_RELEASE(gLastFocusedContent);
gLastFocusedContent = mCurrentFocus;
NS_IF_ADDREF(gLastFocusedContent);
-
- nsIMEStateManager::OnTextStateFocus(mPresContext, mCurrentFocus);
}
// Try to keep the focus controllers and the globals in synch
if (gLastFocusedDocument && gLastFocusedDocument != mDocument) {
nsIFocusController *lastController = nsnull;
nsPIDOMWindow* lastWindow = gLastFocusedDocument->GetWindow();
if (lastWindow)
@@ -1247,18 +1242,16 @@ nsEventStateManager::PreHandleEvent(nsPr
// immediately.
EnsureDocument(aPresContext);
if (gLastFocusedContent && !gLastFocusedContent->IsInDoc()) {
NS_RELEASE(gLastFocusedContent);
}
- nsIMEStateManager::OnTextStateBlur(nsnull, nsnull);
-
// Now fire blurs. We fire a blur on the focused document, element,
// and window.
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event(PR_TRUE, NS_BLUR_CONTENT);
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
if (gLastFocusedDocument && gLastFocusedPresContextWeak) {
@@ -1422,18 +1415,16 @@ nsEventStateManager::PreHandleEvent(nsPr
// window.
nsCOMPtr<nsIFocusController> focusController =
GetFocusControllerForDocument(mDocument);
if (focusController)
focusController->SetSuppressFocus(PR_TRUE, "Deactivate Suppression");
- nsIMEStateManager::OnTextStateBlur(nsnull, nsnull);
-
// Now fire blurs. Blur the content, then the document, then the window.
if (gLastFocusedDocument && gLastFocusedDocument == mDocument &&
gLastFocusedDocument != mFirstDocumentBlurEvent) {
PRBool clearFirstDocumentBlurEvent = PR_FALSE;
if (!mFirstDocumentBlurEvent) {
mFirstDocumentBlurEvent = gLastFocusedDocument;
@@ -1598,50 +1589,38 @@ nsEventStateManager::PreHandleEvent(nsPr
if ((msEvent->scrollFlags & nsMouseScrollEvent::kIsHorizontal) ?
mLastLineScrollConsumedX : mLastLineScrollConsumedY) {
*aStatus = nsEventStatus_eConsumeNoDefault;
}
}
break;
case NS_QUERY_SELECTED_TEXT:
{
- nsContentEventHandler handler(mPresContext);
+ nsQueryContentEventHandler handler(mPresContext);
handler.OnQuerySelectedText((nsQueryContentEvent*)aEvent);
}
break;
case NS_QUERY_TEXT_CONTENT:
{
- nsContentEventHandler handler(mPresContext);
+ nsQueryContentEventHandler handler(mPresContext);
handler.OnQueryTextContent((nsQueryContentEvent*)aEvent);
}
break;
+ case NS_QUERY_CHARACTER_RECT:
+ {
+ nsQueryContentEventHandler handler(mPresContext);
+ handler.OnQueryCharacterRect((nsQueryContentEvent*)aEvent);
+ }
+ break;
case NS_QUERY_CARET_RECT:
{
- nsContentEventHandler handler(mPresContext);
+ nsQueryContentEventHandler handler(mPresContext);
handler.OnQueryCaretRect((nsQueryContentEvent*)aEvent);
}
break;
- case NS_QUERY_TEXT_RECT:
- {
- nsContentEventHandler handler(mPresContext);
- handler.OnQueryTextRect((nsQueryContentEvent*)aEvent);
- }
- break;
- case NS_QUERY_EDITOR_RECT:
- {
- nsContentEventHandler handler(mPresContext);
- handler.OnQueryEditorRect((nsQueryContentEvent*)aEvent);
- }
- break;
- case NS_SELECTION_SET:
- {
- nsContentEventHandler handler(mPresContext);
- handler.OnSelectionEvent((nsSelectionEvent*)aEvent);
- }
- break;
}
return NS_OK;
}
static PRInt32
GetAccessModifierMask(nsISupports* aDocShell)
{
nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(aDocShell));
@@ -5144,18 +5123,16 @@ nsEventStateManager::SendFocusBlur(nsPre
// send it a blur.
if (previousFocus && !previousFocus->GetDocument())
previousFocus = nsnull;
// Track the old focus controller if any focus suppressions is used on it.
nsFocusSuppressor oldFocusSuppressor;
- nsIMEStateManager::OnTextStateBlur(aPresContext, aContent);
-
if (nsnull != gLastFocusedPresContextWeak) {
nsCOMPtr<nsIContent> focusAfterBlur;
if (gLastFocusedContent && gLastFocusedContent != mFirstBlurEvent) {
//Store the first blur event we fire and don't refire blur
//to that element while the first blur is still ongoing.
@@ -5376,18 +5353,16 @@ nsEventStateManager::SendFocusBlur(nsPre
PRInt32 ec, val = tabIndex.ToInteger(&ec);
if (NS_SUCCEEDED (ec)) {
mCurrentTabIndex = val;
}
if (clearFirstFocusEvent) {
mFirstFocusEvent = nsnull;
}
-
- nsIMEStateManager::OnTextStateFocus(mPresContext, mCurrentFocus);
} else if (!aContent) {
//fire focus on document even if the content isn't focusable (ie. text)
//see bugzilla bug 93521
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event(PR_TRUE, NS_FOCUS_CONTENT);
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
if (nsnull != mPresContext && mDocument) {
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -17,17 +17,16 @@
*
* The Initial Developer of the Original Code is
* Mozilla Japan.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Masayuki Nakano <masayuki@d-toybox.com>
- * Ningjie Chen <chenn@email.uc.edu>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
@@ -49,47 +48,34 @@
#include "nsIInterfaceRequestorUtils.h"
#include "nsIEditorDocShell.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsPresContext.h"
#include "nsIFocusController.h"
#include "nsIDOMWindow.h"
#include "nsContentUtils.h"
-#include "nsINode.h"
-#include "nsIFrame.h"
-#include "nsRange.h"
-#include "nsIDOMRange.h"
-#include "nsISelection.h"
-#include "nsISelectionPrivate.h"
-#include "nsISelectionListener.h"
-#include "nsISelectionController.h"
-#include "nsIMutationObserver.h"
-#include "nsContentEventHandler.h"
/******************************************************************/
/* nsIMEStateManager */
/******************************************************************/
nsIContent* nsIMEStateManager::sContent = nsnull;
nsPresContext* nsIMEStateManager::sPresContext = nsnull;
nsPIDOMWindow* nsIMEStateManager::sActiveWindow = nsnull;
PRBool nsIMEStateManager::sInstalledMenuKeyboardListener = PR_FALSE;
-nsTextStateManager* nsIMEStateManager::sTextStateObserver = nsnull;
-
nsresult
nsIMEStateManager::OnDestroyPresContext(nsPresContext* aPresContext)
{
NS_ENSURE_ARG_POINTER(aPresContext);
if (aPresContext != sPresContext)
return NS_OK;
sContent = nsnull;
sPresContext = nsnull;
- OnTextStateBlur(nsnull, nsnull);
return NS_OK;
}
nsresult
nsIMEStateManager::OnRemoveContent(nsPresContext* aPresContext,
nsIContent* aContent)
{
NS_ENSURE_ARG_POINTER(aPresContext);
@@ -278,306 +264,8 @@ nsIMEStateManager::GetWidget(nsPresConte
if (!vm)
return nsnull;
nsCOMPtr<nsIWidget> widget = nsnull;
nsresult rv = vm->GetWidget(getter_AddRefs(widget));
NS_ENSURE_SUCCESS(rv, nsnull);
return widget;
}
-
-// nsTextStateManager notifies widget of any text and selection changes
-// in the currently focused editor
-// sTextStateObserver points to the currently active nsTextStateManager
-// sTextStateObserver is null if there is no focused editor
-
-class nsTextStateManager : public nsISelectionListener,
- public nsStubMutationObserver
-{
-public:
- nsTextStateManager();
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSISELECTIONLISTENER
- NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
- NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
- NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
- NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
-
- nsresult Init(nsIWidget* aWidget,
- nsPresContext* aPresContext,
- nsINode* aNode);
- void Destroy(void);
-
- nsCOMPtr<nsIWidget> mWidget;
- nsCOMPtr<nsISelection> mSel;
- nsCOMPtr<nsIContent> mRootContent;
- nsCOMPtr<nsINode> mEditableNode;
- PRBool mDestroying;
-
-private:
- void NotifyContentAdded(nsINode* aContainer, PRInt32 aStart, PRInt32 aEnd);
-};
-
-nsTextStateManager::nsTextStateManager()
-{
- mDestroying = PR_FALSE;
-}
-
-nsresult
-nsTextStateManager::Init(nsIWidget* aWidget,
- nsPresContext* aPresContext,
- nsINode* aNode)
-{
- mWidget = aWidget;
-
- nsIPresShell* presShell = aPresContext->PresShell();
-
- // get selection and root content
- nsCOMPtr<nsISelectionController> selCon;
- if (aNode->IsNodeOfType(nsINode::eCONTENT)) {
- nsIFrame* frame = presShell->GetPrimaryFrameFor(
- static_cast<nsIContent*>(aNode));
- NS_ENSURE_TRUE(frame, NS_ERROR_UNEXPECTED);
-
- frame->GetSelectionController(aPresContext,
- getter_AddRefs(selCon));
- } else {
- // aNode is a document
- selCon = do_QueryInterface(presShell);
- }
- NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
-
- nsCOMPtr<nsISelection> sel;
- nsresult rv = selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
- getter_AddRefs(sel));
- NS_ENSURE_TRUE(sel, NS_ERROR_UNEXPECTED);
-
- nsCOMPtr<nsIDOMRange> selDomRange;
- rv = sel->GetRangeAt(0, getter_AddRefs(selDomRange));
- NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<nsIRange> selRange(do_QueryInterface(selDomRange));
- NS_ENSURE_TRUE(selRange && selRange->GetStartParent(), NS_ERROR_UNEXPECTED);
-
- mRootContent = selRange->GetStartParent()->
- GetSelectionRootContent(presShell);
-
- // add text change observer
- mRootContent->AddMutationObserver(this);
-
- // add selection change listener
- nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(sel));
- NS_ENSURE_TRUE(selPrivate, NS_ERROR_UNEXPECTED);
- rv = selPrivate->AddSelectionListener(this);
- NS_ENSURE_SUCCESS(rv, rv);
- mSel = sel;
-
- mEditableNode = aNode;
- return NS_OK;
-}
-
-void
-nsTextStateManager::Destroy(void)
-{
- if (mSel) {
- nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(mSel));
- if (selPrivate)
- selPrivate->RemoveSelectionListener(this);
- mSel = nsnull;
- }
- if (mRootContent) {
- mRootContent->RemoveMutationObserver(this);
- mRootContent = nsnull;
- }
- mEditableNode = nsnull;
- mWidget = nsnull;
-}
-
-NS_IMPL_ISUPPORTS2(nsTextStateManager,
- nsIMutationObserver,
- nsISelectionListener)
-
-nsresult
-nsTextStateManager::NotifySelectionChanged(nsIDOMDocument* aDoc,
- nsISelection* aSel,
- PRInt16 aReason)
-{
- PRInt32 count = 0;
- nsresult rv = aSel->GetRangeCount(&count);
- NS_ENSURE_SUCCESS(rv, rv);
- if (count > 0) {
- mWidget->OnIMESelectionChange();
- }
- return NS_OK;
-}
-
-void
-nsTextStateManager::CharacterDataChanged(nsIDocument* aDocument,
- nsIContent* aContent,
- CharacterDataChangeInfo* aInfo)
-{
- NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
- "character data changed for non-text node");
-
- PRUint32 offset = 0;
- // get offsets of change and fire notification
- if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(
- mRootContent, aContent, aInfo->mChangeStart, &offset)))
- return;
-
- PRUint32 oldEnd = offset + aInfo->mChangeEnd - aInfo->mChangeStart;
- PRUint32 newEnd = offset + aInfo->mReplaceLength;
- mWidget->OnIMETextChange(offset, oldEnd, newEnd);
-}
-
-void
-nsTextStateManager::NotifyContentAdded(nsINode* aContainer,
- PRInt32 aStartIndex,
- PRInt32 aEndIndex)
-{
- PRUint32 offset = 0, newOffset = 0;
- if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(
- mRootContent, aContainer, aStartIndex, &offset)))
- return;
-
- // get offset at the end of the last added node
- if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(
- aContainer->GetChildAt(aStartIndex),
- aContainer, aEndIndex, &newOffset)))
- return;
-
- // fire notification
- if (newOffset)
- mWidget->OnIMETextChange(offset, offset, offset + newOffset);
-}
-
-void
-nsTextStateManager::ContentAppended(nsIDocument* aDocument,
- nsIContent* aContainer,
- PRInt32 aNewIndexInContainer)
-{
- NotifyContentAdded(aContainer, aNewIndexInContainer,
- aContainer->GetChildCount());
-}
-
-void
-nsTextStateManager::ContentInserted(nsIDocument* aDocument,
- nsIContent* aContainer,
- nsIContent* aChild,
- PRInt32 aIndexInContainer)
-{
- NotifyContentAdded(NODE_FROM(aContainer, aDocument),
- aIndexInContainer, aIndexInContainer + 1);
-}
-
-void
-nsTextStateManager::ContentRemoved(nsIDocument* aDocument,
- nsIContent* aContainer,
- nsIContent* aChild,
- PRInt32 aIndexInContainer)
-{
- PRUint32 offset = 0, childOffset = 1;
- if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(
- mRootContent, NODE_FROM(aContainer, aDocument),
- aIndexInContainer, &offset)))
- return;
-
- // get offset at the end of the deleted node
- if (aChild->IsNodeOfType(nsINode::eTEXT))
- childOffset = aChild->TextLength();
- else if (0 < aChild->GetChildCount())
- childOffset = aChild->GetChildCount();
-
- if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(
- aChild, aChild, childOffset, &childOffset)))
- return;
-
- // fire notification
- if (childOffset)
- mWidget->OnIMETextChange(offset, offset + childOffset, offset);
-}
-
-static nsINode* GetRootEditableNode(nsPresContext* aPresContext,
- nsIContent* aContent)
-{
- if (aContent) {
- nsINode* root = nsnull;
- nsINode* node = aContent;
- while (node && node->IsEditable()) {
- root = node;
- node = node->GetParent();
- }
- return root;
- }
- if (aPresContext) {
- nsIDocument* document = aPresContext->Document();
- if (document && document->IsEditable())
- return document;
- }
- return nsnull;
-}
-
-nsresult
-nsIMEStateManager::OnTextStateBlur(nsPresContext* aPresContext,
- nsIContent* aContent)
-{
- if (!sTextStateObserver || sTextStateObserver->mDestroying ||
- sTextStateObserver->mEditableNode ==
- GetRootEditableNode(aPresContext, aContent))
- return NS_OK;
-
- sTextStateObserver->mDestroying = PR_TRUE;
- sTextStateObserver->mWidget->OnIMEFocusChange(PR_FALSE);
- sTextStateObserver->Destroy();
- NS_RELEASE(sTextStateObserver);
- return NS_OK;
-}
-
-nsresult
-nsIMEStateManager::OnTextStateFocus(nsPresContext* aPresContext,
- nsIContent* aContent)
-{
- if (sTextStateObserver) return NS_OK;
-
- nsINode *editableNode = GetRootEditableNode(aPresContext, aContent);
- if (!editableNode) return NS_OK;
-
- nsIViewManager* vm = aPresContext->GetViewManager();
- NS_ENSURE_TRUE(vm, NS_ERROR_NOT_AVAILABLE);
-
- nsCOMPtr<nsIWidget> widget;
- nsresult rv = vm->GetWidget(getter_AddRefs(widget));
- NS_ENSURE_SUCCESS(rv, NS_ERROR_NOT_AVAILABLE);
-
- rv = widget->OnIMEFocusChange(PR_TRUE);
- NS_ENSURE_SUCCESS(rv, NS_OK);
-
- // OnIMEFocusChange may cause focus and sTextStateObserver to change
- // In that case return and keep the current sTextStateObserver
- NS_ENSURE_TRUE(!sTextStateObserver, NS_OK);
-
- sTextStateObserver = new nsTextStateManager();
- NS_ENSURE_TRUE(sTextStateObserver, NS_ERROR_OUT_OF_MEMORY);
- NS_ADDREF(sTextStateObserver);
- rv = sTextStateObserver->Init(widget, aPresContext, editableNode);
- if (NS_FAILED(rv)) {
- sTextStateObserver->mDestroying = PR_TRUE;
- sTextStateObserver->Destroy();
- NS_RELEASE(sTextStateObserver);
- widget->OnIMEFocusChange(PR_FALSE);
- return rv;
- }
- return NS_OK;
-}
-
-nsresult
-nsIMEStateManager::GetFocusSelectionAndRoot(nsISelection** aSel,
- nsIContent** aRoot)
-{
- if (!sTextStateObserver || !sTextStateObserver->mEditableNode)
- return NS_ERROR_NOT_AVAILABLE;
-
- NS_ASSERTION(sTextStateObserver->mSel && sTextStateObserver->mRootContent,
- "uninitialized text state observer");
- NS_ADDREF(*aSel = sTextStateObserver->mSel);
- NS_ADDREF(*aRoot = sTextStateObserver->mRootContent);
- return NS_OK;
-}
--- a/content/events/src/nsIMEStateManager.h
+++ b/content/events/src/nsIMEStateManager.h
@@ -35,73 +35,49 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsIMEStateManager_h__
#define nsIMEStateManager_h__
#include "nscore.h"
-#include "nsGUIEvent.h"
class nsIContent;
class nsPIDOMWindow;
class nsPresContext;
class nsIWidget;
class nsIFocusController;
-class nsTextStateManager;
-class nsISelection;
/*
* IME state manager
*/
class nsIMEStateManager
{
public:
static nsresult OnDestroyPresContext(nsPresContext* aPresContext);
static nsresult OnRemoveContent(nsPresContext* aPresContext,
nsIContent* aContent);
static nsresult OnChangeFocus(nsPresContext* aPresContext,
nsIContent* aContent);
static nsresult OnActivate(nsPresContext* aPresContext);
static nsresult OnDeactivate(nsPresContext* aPresContext);
static void OnInstalledMenuKeyboardListener(PRBool aInstalling);
-
- // These two methods manage focus and selection/text observers.
- // They are separate from OnChangeFocus above because this offers finer
- // control compared to having the two methods incorporated into OnChangeFocus
-
- // OnTextStateBlur should be called *before* NS_BLUR_CONTENT fires
- // aPresContext is the nsPresContext receiving focus (not lost focus)
- // aContent is the nsIContent receiving focus (not lost focus)
- // aPresContext and/or aContent may be null
- static nsresult OnTextStateBlur(nsPresContext* aPresContext,
- nsIContent* aContent);
- // OnTextStateFocus should be called *after* NS_FOCUS_CONTENT fires
- // aPresContext is the nsPresContext receiving focus
- // aContent is the nsIContent receiving focus
- static nsresult OnTextStateFocus(nsPresContext* aPresContext,
- nsIContent* aContent);
- // Get the focused editor's selection and root
- static nsresult GetFocusSelectionAndRoot(nsISelection** aSel,
- nsIContent** aRoot);
protected:
static void SetIMEState(nsPresContext* aPresContext,
PRUint32 aState,
nsIWidget* aKB);
static PRUint32 GetNewIMEState(nsPresContext* aPresContext,
nsIContent* aContent);
static PRBool IsActive(nsPresContext* aPresContext);
static nsIFocusController* GetFocusController(nsPresContext* aPresContext);
static nsIWidget* GetWidget(nsPresContext* aPresContext);
static nsIContent* sContent;
static nsPresContext* sPresContext;
static nsPIDOMWindow* sActiveWindow;
static PRBool sInstalledMenuKeyboardListener;
-
- static nsTextStateManager* sTextStateObserver;
};
#endif // nsIMEStateManager_h__
rename from content/events/src/nsContentEventHandler.cpp
rename to content/events/src/nsQueryContentEventHandler.cpp
--- a/content/events/src/nsContentEventHandler.cpp
+++ b/content/events/src/nsQueryContentEventHandler.cpp
@@ -17,70 +17,64 @@
*
* The Initial Developer of the Original Code is
* Mozilla Japan.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Masayuki Nakano <masayuki@d-toybox.com>
- * Ningjie Chen <chenn@email.uc.edu>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-#include "nsContentEventHandler.h"
+#include "nsQueryContentEventHandler.h"
#include "nsCOMPtr.h"
#include "nsPresContext.h"
#include "nsIPresShell.h"
#include "nsISelection.h"
#include "nsIDOMText.h"
#include "nsIDOMRange.h"
#include "nsRange.h"
#include "nsGUIEvent.h"
#include "nsCaret.h"
#include "nsFrameSelection.h"
#include "nsIFrame.h"
#include "nsIView.h"
#include "nsIContentIterator.h"
#include "nsTextFragment.h"
#include "nsTextFrame.h"
-#include "nsISelectionController.h"
-#include "nsISelectionPrivate.h"
-#include "nsContentUtils.h"
-#include "nsISelection2.h"
-#include "nsIMEStateManager.h"
nsresult NS_NewContentIterator(nsIContentIterator** aInstancePtrResult);
/******************************************************************/
-/* nsContentEventHandler */
+/* nsQueryContentEventHandler */
/******************************************************************/
-nsContentEventHandler::nsContentEventHandler(
+nsQueryContentEventHandler::nsQueryContentEventHandler(
nsPresContext* aPresContext) :
mPresContext(aPresContext),
mPresShell(aPresContext->GetPresShell()), mSelection(nsnull),
mFirstSelectedRange(nsnull), mRootContent(nsnull)
{
}
nsresult
-nsContentEventHandler::Init(nsQueryContentEvent* aEvent)
+nsQueryContentEventHandler::Init(nsQueryContentEvent* aEvent)
{
NS_ASSERTION(aEvent, "aEvent must not be null");
if (mSelection)
return NS_OK;
aEvent->mSucceeded = PR_FALSE;
@@ -118,34 +112,16 @@ nsContentEventHandler::Init(nsQueryConte
mSelection, &r, &isCollapsed, &view);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(view, NS_ERROR_FAILURE);
aEvent->mReply.mFocusedWidget = view->GetWidget();
return NS_OK;
}
-// Editor places a bogus BR node under its root content if the editor doesn't
-// have any text. This happens even for single line editors.
-// When we get text content and when we change the selection,
-// we don't want to include the bogus BRs at the end.
-static PRBool IsContentBR(nsIContent* aContent)
-{
- return aContent->IsNodeOfType(nsINode::eHTML) &&
- aContent->Tag() == nsGkAtoms::br &&
- !aContent->AttrValueIs(kNameSpaceID_None,
- nsGkAtoms::type,
- nsGkAtoms::moz,
- eIgnoreCase) &&
- !aContent->AttrValueIs(kNameSpaceID_None,
- nsGkAtoms::mozeditorbogusnode,
- nsGkAtoms::_true,
- eIgnoreCase);
-}
-
static void ConvertToNativeNewlines(nsAFlatString& aString)
{
#if defined(XP_MACOSX)
aString.ReplaceSubstring(NS_LITERAL_STRING("\n"), NS_LITERAL_STRING("\r"));
#elif defined(XP_WIN)
aString.ReplaceSubstring(NS_LITERAL_STRING("\n"), NS_LITERAL_STRING("\r\n"));
#endif
}
@@ -180,17 +156,18 @@ static void AppendSubString(nsAString& a
text->AppendTo(aString, PRInt32(aXPOffset), PRInt32(aXPLength));
}
static PRUint32 GetNativeTextLength(nsIContent* aContent)
{
nsAutoString str;
if (aContent->IsNodeOfType(nsINode::eTEXT))
AppendString(str, aContent);
- else if (IsContentBR(aContent))
+ else if (aContent->IsNodeOfType(nsINode::eHTML) &&
+ aContent->Tag() == nsGkAtoms::br)
str.Assign(PRUnichar('\n'));
ConvertToNativeNewlines(str);
return str.Length();
}
static PRUint32 ConvertToXPOffset(nsIContent* aContent, PRUint32 aNativeOffset)
{
@@ -199,18 +176,19 @@ static PRUint32 ConvertToXPOffset(nsICon
ConvertToNativeNewlines(str);
NS_ASSERTION(aNativeOffset <= str.Length(),
"aOffsetForNativeLF is too large!");
str.Truncate(aNativeOffset);
ConvertToXPNewlines(str);
return str.Length();
}
-static nsresult GenerateFlatTextContent(nsIRange* aRange,
- nsAFlatString& aString)
+nsresult
+nsQueryContentEventHandler::GenerateFlatTextContent(nsIRange* aRange,
+ nsAFlatString& aString)
{
nsCOMPtr<nsIContentIterator> iter;
nsresult rv = NS_NewContentIterator(getter_AddRefs(iter));
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(iter, "NS_NewContentIterator succeeded, but the result is null");
nsCOMPtr<nsIDOMRange> domRange(do_QueryInterface(aRange));
NS_ASSERTION(domRange, "aRange doesn't have nsIDOMRange!");
iter->Init(domRange);
@@ -238,37 +216,37 @@ static nsresult GenerateFlatTextContent(
if (content->IsNodeOfType(nsINode::eTEXT)) {
if (content == startNode)
AppendSubString(aString, content, aRange->StartOffset(),
content->TextLength() - aRange->StartOffset());
else if (content == endNode)
AppendSubString(aString, content, 0, aRange->EndOffset());
else
AppendString(aString, content);
- } else if (IsContentBR(content))
+ } else if (content->IsNodeOfType(nsINode::eHTML) &&
+ content->Tag() == nsGkAtoms::br)
aString.Append(PRUnichar('\n'));
}
ConvertToNativeNewlines(aString);
return NS_OK;
}
nsresult
-nsContentEventHandler::ExpandToClusterBoundary(nsIContent* aContent,
+nsQueryContentEventHandler::ExpandToClusterBoundary(nsIContent* aContent,
PRBool aForward,
PRUint32* aXPOffset)
{
+ NS_ASSERTION(*aXPOffset >= 0 && *aXPOffset <= aContent->TextLength(),
+ "offset is out of range.");
+
// XXX This method assumes that the frame boundaries must be cluster
// boundaries. It's false, but no problem now, maybe.
if (!aContent->IsNodeOfType(nsINode::eTEXT) ||
*aXPOffset == 0 || *aXPOffset == aContent->TextLength())
return NS_OK;
-
- NS_ASSERTION(*aXPOffset >= 0 && *aXPOffset <= aContent->TextLength(),
- "offset is out of range.");
-
nsCOMPtr<nsFrameSelection> fs = mPresShell->FrameSelection();
PRInt32 offsetInFrame;
nsFrameSelection::HINT hint =
aForward ? nsFrameSelection::HINTLEFT : nsFrameSelection::HINTRIGHT;
nsIFrame* frame = fs->GetFrameForNodeOffset(aContent, PRInt32(*aXPOffset),
hint, &offsetInFrame);
if (!frame) {
// This content doesn't have any frames, we only can check surrogate pair...
@@ -282,25 +260,25 @@ nsContentEventHandler::ExpandToClusterBo
PRInt32 startOffset, endOffset;
nsresult rv = frame->GetOffsets(startOffset, endOffset);
NS_ENSURE_SUCCESS(rv, rv);
if (*aXPOffset == PRUint32(startOffset) || *aXPOffset == PRUint32(endOffset))
return NS_OK;
if (frame->GetType() != nsGkAtoms::textFrame)
return NS_ERROR_FAILURE;
nsTextFrame* textFrame = static_cast<nsTextFrame*>(frame);
- PRInt32 newOffsetInFrame = *aXPOffset - startOffset;
+ PRInt32 newOffsetInFrame = offsetInFrame;
newOffsetInFrame += aForward ? -1 : 1;
textFrame->PeekOffsetCharacter(aForward, &newOffsetInFrame);
*aXPOffset = startOffset + newOffsetInFrame;
return NS_OK;
}
nsresult
-nsContentEventHandler::SetRangeFromFlatTextOffset(
+nsQueryContentEventHandler::SetRangeFromFlatTextOffset(
nsIRange* aRange,
PRUint32 aNativeOffset,
PRUint32 aNativeLength,
PRBool aExpandToClusterBoundaries)
{
nsCOMPtr<nsIContentIterator> iter;
nsresult rv = NS_NewContentIterator(getter_AddRefs(iter));
NS_ENSURE_SUCCESS(rv, rv);
@@ -386,61 +364,50 @@ nsContentEventHandler::SetRangeFromFlatT
NS_ENSURE_SUCCESS(rv, rv);
}
rv = domRange->SetEnd(domNode, PRInt32(mRootContent->GetChildCount()));
NS_ASSERTION(NS_SUCCEEDED(rv), "nsIDOMRange::SetEnd failed");
return rv;
}
nsresult
-nsContentEventHandler::OnQuerySelectedText(nsQueryContentEvent* aEvent)
+nsQueryContentEventHandler::OnQuerySelectedText(nsQueryContentEvent* aEvent)
{
nsresult rv = Init(aEvent);
if (NS_FAILED(rv))
return rv;
NS_ASSERTION(aEvent->mReply.mString.IsEmpty(),
"The reply string must be empty");
- rv = GetFlatTextOffsetOfRange(mRootContent,
- mFirstSelectedRange, &aEvent->mReply.mOffset);
+ rv = GetFlatTextOffsetOfRange(mFirstSelectedRange, &aEvent->mReply.mOffset);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ PRBool isCollapsed;
+ rv = mSelection->GetIsCollapsed(&isCollapsed);
NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<nsIDOMNode> anchorDomNode, focusDomNode;
- rv = mSelection->GetAnchorNode(getter_AddRefs(anchorDomNode));
- NS_ENSURE_TRUE(anchorDomNode, NS_ERROR_FAILURE);
- rv = mSelection->GetFocusNode(getter_AddRefs(focusDomNode));
- NS_ENSURE_TRUE(focusDomNode, NS_ERROR_FAILURE);
+ if (!isCollapsed) {
+ nsCOMPtr<nsIDOMRange> domRange;
+ rv = mSelection->GetRangeAt(0, getter_AddRefs(domRange));
+ NS_ENSURE_SUCCESS(rv, rv);
+ NS_ASSERTION(domRange, "GetRangeAt succeeded, but the result is null");
- PRInt32 anchorOffset, focusOffset;
- rv = mSelection->GetAnchorOffset(&anchorOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = mSelection->GetFocusOffset(&focusOffset);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsINode> anchorNode(do_QueryInterface(anchorDomNode));
- nsCOMPtr<nsINode> focusNode(do_QueryInterface(focusDomNode));
- NS_ENSURE_TRUE(anchorNode && focusNode, NS_ERROR_UNEXPECTED);
-
- PRInt16 compare = nsContentUtils::ComparePoints(anchorNode, anchorOffset,
- focusNode, focusOffset);
- aEvent->mReply.mReversed = compare > 0;
-
- if (compare) {
- nsCOMPtr<nsIRange> range = mFirstSelectedRange;
+ nsCOMPtr<nsIRange> range(do_QueryInterface(domRange));
+ NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
rv = GenerateFlatTextContent(range, aEvent->mReply.mString);
NS_ENSURE_SUCCESS(rv, rv);
}
aEvent->mSucceeded = PR_TRUE;
return NS_OK;
}
nsresult
-nsContentEventHandler::OnQueryTextContent(nsQueryContentEvent* aEvent)
+nsQueryContentEventHandler::OnQueryTextContent(nsQueryContentEvent* aEvent)
{
nsresult rv = Init(aEvent);
if (NS_FAILED(rv))
return rv;
NS_ASSERTION(aEvent->mReply.mString.IsEmpty(),
"The reply string must be empty");
@@ -453,178 +420,75 @@ nsContentEventHandler::OnQueryTextConten
rv = GenerateFlatTextContent(range, aEvent->mReply.mString);
NS_ENSURE_SUCCESS(rv, rv);
aEvent->mSucceeded = PR_TRUE;
return NS_OK;
}
-// Adjust to use a child node if possible
-// to make the returned rect more accurate
-static nsINode* AdjustTextRectNode(nsINode* aNode,
- PRInt32& aOffset)
+nsresult
+nsQueryContentEventHandler::QueryRectFor(nsQueryContentEvent* aEvent,
+ nsIRange* aRange,
+ nsCaret* aCaret)
{
- PRInt32 childCount = PRInt32(aNode->GetChildCount());
- nsINode* node = aNode;
- if (childCount) {
- if (aOffset < childCount) {
- node = aNode->GetChildAt(aOffset);
- aOffset = 0;
- } else if (aOffset == childCount) {
- node = aNode->GetChildAt(childCount - 1);
- aOffset = node->IsNodeOfType(nsINode::eTEXT) ?
- static_cast<nsIContent*>(node)->TextLength() : 1;
- }
+ PRInt32 offsetInFrame;
+ nsIFrame* frame;
+ nsresult rv = GetStartFrameAndOffset(aRange, &frame, &offsetInFrame);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsPoint posInFrame;
+ rv = frame->GetPointFromOffset(aRange->StartOffset(), &posInFrame);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsRect rect;
+ rect.y = posInFrame.y;
+ rect.height = frame->GetSize().height;
+
+ if (aEvent->message == NS_QUERY_CHARACTER_RECT) {
+ nsPoint nextPos;
+ rv = frame->GetPointFromOffset(aRange->EndOffset(), &nextPos);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rect.x = PR_MIN(posInFrame.x, nextPos.x);
+ rect.width = PR_ABS(posInFrame.x - nextPos.x);
+ } else {
+ rect.x = posInFrame.x;
+ rect.width = aCaret->GetCaretRect().width;
}
- return node;
-}
+
+ rv = ConvertToRootViewRelativeOffset(frame, rect);
+ NS_ENSURE_SUCCESS(rv, rv);
-// Similar to nsFrameSelection::GetFrameForNodeOffset,
-// but this is more flexible for OnQueryTextRect to use
-static nsresult GetFrameForTextRect(nsIPresShell* aPresShell,
- nsINode* aNode,
- PRInt32 aOffset,
- PRBool aHint,
- nsIFrame** aReturnFrame)
-{
- NS_ENSURE_TRUE(aNode && aNode->IsNodeOfType(nsINode::eCONTENT),
- NS_ERROR_UNEXPECTED);
- nsIContent* content = static_cast<nsIContent*>(aNode);
- nsIFrame* frame = aPresShell->GetPrimaryFrameFor(content);
- NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
- PRInt32 childOffset = 0;
- return frame->GetChildFrameContainingOffset(aOffset, aHint, &childOffset,
- aReturnFrame);
+ aEvent->mReply.mRect = nsRect::ToOutsidePixels(rect, mPresContext->AppUnitsPerDevPixel());
+ aEvent->mSucceeded = PR_TRUE;
+ return NS_OK;
}
nsresult
-nsContentEventHandler::OnQueryTextRect(nsQueryContentEvent* aEvent)
+nsQueryContentEventHandler::OnQueryCharacterRect(nsQueryContentEvent* aEvent)
{
nsresult rv = Init(aEvent);
if (NS_FAILED(rv))
return rv;
- nsRefPtr<nsRange> range = new nsRange();
- if (!range) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset,
- aEvent->mInput.mLength, PR_TRUE);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // used to iterate over all contents and their frames
- nsCOMPtr<nsIContentIterator> iter;
- rv = NS_NewContentIterator(getter_AddRefs(iter));
- NS_ENSURE_SUCCESS(rv, rv);
- iter->Init(range);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // get the starting frame
- PRInt32 offset = range->StartOffset();
- nsINode* node = iter->GetCurrentNode();
- if (!node) {
- node = AdjustTextRectNode(range->GetStartParent(), offset);
- }
- nsIFrame* firstFrame = nsnull;
- rv = GetFrameForTextRect(mPresShell, node, offset,
- PR_TRUE, &firstFrame);
+ nsCOMPtr<nsIRange> range = new nsRange();
+ NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY);
+ rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset, 1, PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
- // get the starting frame rect
- nsRect rect(nsPoint(0, 0), firstFrame->GetRect().Size());
- rv = ConvertToRootViewRelativeOffset(firstFrame, rect);
- NS_ENSURE_SUCCESS(rv, rv);
- nsRect frameRect = rect;
- nsPoint ptOffset;
- firstFrame->GetPointFromOffset(offset, &ptOffset);
- // minus 1 to avoid creating an empty rect
- rect.x += ptOffset.x - 1;
- rect.width -= ptOffset.x - 1;
-
- // get the ending frame
- offset = range->EndOffset();
- node = AdjustTextRectNode(range->GetEndParent(), offset);
- nsIFrame* lastFrame = nsnull;
- rv = GetFrameForTextRect(mPresShell, node, offset,
- range->Collapsed(), &lastFrame);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // iterate over all covered frames
- for (nsIFrame* frame = firstFrame; frame != lastFrame;) {
- frame = frame->GetNextContinuation();
- if (!frame) {
- do {
- iter->Next();
- node = iter->GetCurrentNode();
- if (!node || !node->IsNodeOfType(nsINode::eCONTENT))
- continue;
- frame = mPresShell->GetPrimaryFrameFor(static_cast<nsIContent*>(node));
- } while (!frame && !iter->IsDone());
- if (!frame) {
- // this can happen when the end offset of the range is 0.
- frame = lastFrame;
- }
- }
- frameRect.SetRect(nsPoint(0, 0), frame->GetRect().Size());
- rv = ConvertToRootViewRelativeOffset(frame, frameRect);
- NS_ENSURE_SUCCESS(rv, rv);
- if (frame != lastFrame) {
- // not last frame, so just add rect to previous result
- rect.UnionRect(rect, frameRect);
- }
+ if (range->Collapsed()) {
+ // There is no character at the offset.
+ return NS_OK;
}
- // get the ending frame rect
- lastFrame->GetPointFromOffset(offset, &ptOffset);
- // minus 1 to avoid creating an empty rect
- frameRect.width -= lastFrame->GetRect().width - ptOffset.x - 1;
-
- if (firstFrame == lastFrame) {
- rect.IntersectRect(rect, frameRect);
- } else {
- rect.UnionRect(rect, frameRect);
- }
- aEvent->mReply.mRect =
- nsRect::ToOutsidePixels(rect, mPresContext->AppUnitsPerDevPixel());
- aEvent->mSucceeded = PR_TRUE;
- return NS_OK;
+ return QueryRectFor(aEvent, range, nsnull);
}
nsresult
-nsContentEventHandler::OnQueryEditorRect(nsQueryContentEvent* aEvent)
-{
- nsresult rv = Init(aEvent);
- if (NS_FAILED(rv))
- return rv;
-
- nsIFrame* frame = mPresShell->GetPrimaryFrameFor(mRootContent);
- NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
-
- // get rect for first frame
- nsRect resultRect(nsPoint(0, 0), frame->GetRect().Size());
- rv = ConvertToRootViewRelativeOffset(frame, resultRect);
- NS_ENSURE_SUCCESS(rv, rv);
-
- // account for any additional frames
- while ((frame = frame->GetNextContinuation()) != nsnull) {
- nsRect frameRect(nsPoint(0, 0), frame->GetRect().Size());
- rv = ConvertToRootViewRelativeOffset(frame, frameRect);
- NS_ENSURE_SUCCESS(rv, rv);
- resultRect.UnionRect(resultRect, frameRect);
- }
-
- aEvent->mReply.mRect =
- nsRect::ToOutsidePixels(resultRect, mPresContext->AppUnitsPerDevPixel());
- aEvent->mSucceeded = PR_TRUE;
- return NS_OK;
-}
-
-nsresult
-nsContentEventHandler::OnQueryCaretRect(nsQueryContentEvent* aEvent)
+nsQueryContentEventHandler::OnQueryCaretRect(nsQueryContentEvent* aEvent)
{
nsresult rv = Init(aEvent);
if (NS_FAILED(rv))
return rv;
nsRefPtr<nsCaret> caret;
rv = mPresShell->GetCaret(getter_AddRefs(caret));
NS_ENSURE_SUCCESS(rv, rv);
@@ -633,104 +497,72 @@ nsContentEventHandler::OnQueryCaretRect(
// When the selection is collapsed and the queried offset is current caret
// position, we should return the "real" caret rect.
PRBool selectionIsCollapsed;
rv = mSelection->GetIsCollapsed(&selectionIsCollapsed);
NS_ENSURE_SUCCESS(rv, rv);
if (selectionIsCollapsed) {
PRUint32 offset;
- rv = GetFlatTextOffsetOfRange(mRootContent, mFirstSelectedRange, &offset);
+ rv = GetFlatTextOffsetOfRange(mFirstSelectedRange, &offset);
NS_ENSURE_SUCCESS(rv, rv);
if (offset == aEvent->mInput.mOffset) {
PRBool isCollapsed;
nsRect rect;
rv = caret->GetCaretCoordinates(nsCaret::eTopLevelWindowCoordinates,
mSelection, &rect,
&isCollapsed, nsnull);
- aEvent->mReply.mRect =
- nsRect::ToOutsidePixels(rect, mPresContext->AppUnitsPerDevPixel());
+ aEvent->mReply.mRect = nsRect::ToOutsidePixels(rect, mPresContext->AppUnitsPerDevPixel());
NS_ENSURE_SUCCESS(rv, rv);
aEvent->mSucceeded = PR_TRUE;
return NS_OK;
}
}
// Otherwise, we should set the guessed caret rect.
nsCOMPtr<nsIRange> range = new nsRange();
NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY);
rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset, 0, PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
- PRInt32 offsetInFrame;
- nsIFrame* frame;
- rv = GetStartFrameAndOffset(range, &frame, &offsetInFrame);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsPoint posInFrame;
- rv = frame->GetPointFromOffset(range->StartOffset(), &posInFrame);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsRect rect;
- rect.x = posInFrame.x;
- rect.y = posInFrame.y;
- rect.width = caret->GetCaretRect().width;
- rect.height = frame->GetSize().height;
-
- rv = ConvertToRootViewRelativeOffset(frame, rect);
- NS_ENSURE_SUCCESS(rv, rv);
-
- aEvent->mReply.mRect =
- nsRect::ToOutsidePixels(rect, mPresContext->AppUnitsPerDevPixel());
- aEvent->mSucceeded = PR_TRUE;
- return NS_OK;
+ return QueryRectFor(aEvent, range, caret);
}
nsresult
-nsContentEventHandler::GetFlatTextOffsetOfRange(nsIContent* aRootContent,
- nsINode* aNode,
- PRInt32 aNodeOffset,
- PRUint32* aNativeOffset)
+nsQueryContentEventHandler::GetFlatTextOffsetOfRange(nsIRange* aRange,
+ PRUint32* aNativeOffset)
{
NS_ASSERTION(aNativeOffset, "param is invalid");
nsCOMPtr<nsIRange> prev = new nsRange();
NS_ENSURE_TRUE(prev, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsIDOMRange> domPrev(do_QueryInterface(prev));
NS_ASSERTION(domPrev, "nsRange doesn't have nsIDOMRange??");
- nsCOMPtr<nsIDOMNode> rootDOMNode(do_QueryInterface(aRootContent));
+ nsCOMPtr<nsIDOMNode> rootDOMNode(do_QueryInterface(mRootContent));
domPrev->SetStart(rootDOMNode, 0);
- nsCOMPtr<nsIDOMNode> startDOMNode(do_QueryInterface(aNode));
+ nsINode* startNode = aRange->GetStartParent();
+ NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
+
+ PRInt32 startOffset = aRange->StartOffset();
+ nsCOMPtr<nsIDOMNode> startDOMNode(do_QueryInterface(startNode));
NS_ASSERTION(startDOMNode, "startNode doesn't have nsIDOMNode");
- domPrev->SetEnd(startDOMNode, aNodeOffset);
+ domPrev->SetEnd(startDOMNode, startOffset);
nsAutoString prevStr;
nsresult rv = GenerateFlatTextContent(prev, prevStr);
NS_ENSURE_SUCCESS(rv, rv);
*aNativeOffset = prevStr.Length();
return NS_OK;
}
nsresult
-nsContentEventHandler::GetFlatTextOffsetOfRange(nsIContent* aRootContent,
- nsIRange* aRange,
- PRUint32* aNativeOffset)
-{
- nsINode* startNode = aRange->GetStartParent();
- NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
- PRInt32 startOffset = aRange->StartOffset();
- return GetFlatTextOffsetOfRange(aRootContent, startNode, startOffset,
- aNativeOffset);
-}
-
-nsresult
-nsContentEventHandler::GetStartFrameAndOffset(nsIRange* aRange,
- nsIFrame** aFrame,
- PRInt32* aOffsetInFrame)
+nsQueryContentEventHandler::GetStartFrameAndOffset(nsIRange* aRange,
+ nsIFrame** aFrame,
+ PRInt32* aOffsetInFrame)
{
NS_ASSERTION(aRange && aFrame && aOffsetInFrame, "params are invalid");
nsIContent* content = nsnull;
nsINode* node = aRange->GetStartParent();
if (node && node->IsNodeOfType(nsINode::eCONTENT))
content = static_cast<nsIContent*>(node);
NS_ASSERTION(content, "the start node doesn't have nsIContent!");
@@ -740,104 +572,21 @@ nsContentEventHandler::GetStartFrameAndO
fs->GetHint(), aOffsetInFrame);
NS_ENSURE_TRUE((*aFrame), NS_ERROR_FAILURE);
NS_ASSERTION((*aFrame)->GetType() == nsGkAtoms::textFrame,
"The frame is not textframe");
return NS_OK;
}
nsresult
-nsContentEventHandler::ConvertToRootViewRelativeOffset(nsIFrame* aFrame,
- nsRect& aRect)
+nsQueryContentEventHandler::ConvertToRootViewRelativeOffset(nsIFrame* aFrame,
+ nsRect& aRect)
{
NS_ASSERTION(aFrame, "aFrame must not be null");
nsIView* view = nsnull;
nsPoint posInView;
aFrame->GetOffsetFromView(posInView, &view);
if (!view)
return NS_ERROR_FAILURE;
aRect += posInView + view->GetOffsetTo(nsnull);
return NS_OK;
}
-
-static void AdjustRangeForSelection(nsIContent* aRoot,
- nsINode** aNode,
- PRInt32* aOffset)
-{
- nsINode* node = *aNode;
- PRInt32 offset = *aOffset;
- if (aRoot != node && node->GetParent() &&
- !node->IsNodeOfType(nsINode::eTEXT)) {
- node = node->GetParent();
- offset = node->IndexOf(*aNode) + (offset ? 1 : 0);
- }
- nsINode* brNode = node->GetChildAt(offset - 1);
- while (brNode && brNode->IsNodeOfType(nsINode::eHTML)) {
- nsIContent* brContent = static_cast<nsIContent*>(brNode);
- if (brContent->Tag() != nsGkAtoms::br || IsContentBR(brContent))
- break;
- brNode = node->GetChildAt(--offset - 1);
- }
- *aNode = node;
- *aOffset = PR_MAX(offset, 0);
-}
-
-nsresult
-nsContentEventHandler::OnSelectionEvent(nsSelectionEvent* aEvent)
-{
- aEvent->mSucceeded = PR_FALSE;
-
- // Get selection to manipulate
- nsCOMPtr<nsISelection> sel;
- nsresult rv = nsIMEStateManager::
- GetFocusSelectionAndRoot(getter_AddRefs(sel),
- getter_AddRefs(mRootContent));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // Get range from offset and length
- nsRefPtr<nsRange> range = new nsRange();
- NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY);
- rv = SetRangeFromFlatTextOffset(range, aEvent->mOffset,
- aEvent->mLength, PR_TRUE);
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsINode* startNode = range->GetStartParent();
- nsINode* endNode = range->GetEndParent();
- PRInt32 startOffset = range->StartOffset();
- PRInt32 endOffset = range->EndOffset();
- AdjustRangeForSelection(mRootContent, &startNode, &startOffset);
- AdjustRangeForSelection(mRootContent, &endNode, &endOffset);
-
- nsCOMPtr<nsIDOMNode> startDomNode(do_QueryInterface(startNode));
- nsCOMPtr<nsIDOMNode> endDomNode(do_QueryInterface(endNode));
- NS_ENSURE_TRUE(startDomNode && endDomNode, NS_ERROR_UNEXPECTED);
-
- nsCOMPtr<nsISelectionPrivate> selPrivate = do_QueryInterface(sel);
- NS_ENSURE_TRUE(selPrivate, NS_ERROR_UNEXPECTED);
- selPrivate->StartBatchChanges();
-
- // Clear selection first before setting
- rv = sel->RemoveAllRanges();
- // Need to call EndBatchChanges at the end even if call failed
- if (NS_SUCCEEDED(rv)) {
- if (aEvent->mReversed) {
- rv = sel->Collapse(endDomNode, endOffset);
- } else {
- rv = sel->Collapse(startDomNode, startOffset);
- }
- if (NS_SUCCEEDED(rv) &&
- (startDomNode != endDomNode || startOffset != endOffset)) {
- if (aEvent->mReversed) {
- rv = sel->Extend(startDomNode, startOffset);
- } else {
- rv = sel->Extend(endDomNode, endOffset);
- }
- }
- }
- selPrivate->EndBatchChanges();
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsISelection2>(do_QueryInterface(sel))->ScrollIntoView(
- nsISelectionController::SELECTION_FOCUS_REGION, PR_FALSE, -1, -1);
- aEvent->mSucceeded = PR_TRUE;
- return NS_OK;
-}
rename from content/events/src/nsContentEventHandler.h
rename to content/events/src/nsQueryContentEventHandler.h
--- a/content/events/src/nsContentEventHandler.h
+++ b/content/events/src/nsQueryContentEventHandler.h
@@ -16,112 +16,100 @@
*
* The Initial Developer of the Original Code is
* Mozilla Japan.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Masayuki Nakano <masayuki@d-toybox.com>
- * Ningjie Chen <chenn@email.uc.edu>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-#ifndef nsContentEventHandler_h__
-#define nsContentEventHandler_h__
+#ifndef nsQueryContentEventHandler_h__
+#define nsQueryContentEventHandler_h__
#include "nscore.h"
#include "nsCOMPtr.h"
#include "nsISelection.h"
#include "nsIRange.h"
#include "nsIContent.h"
#include "nsIDOMTreeWalker.h"
class nsPresContext;
class nsIPresShell;
class nsQueryContentEvent;
-class nsSelectionEvent;
class nsCaret;
struct nsRect;
/*
* Query Content Event Handler
- * nsContentEventHandler is a helper class for nsEventStateManager.
+ * nsQueryContentEventHandler is a helper class for nsEventStateManager.
* The platforms request some content informations, e.g., the selected text,
* the offset of the selected text and the text for specified range.
* This class answers to NS_QUERY_* events from actual contents.
*/
-class NS_STACK_CLASS nsContentEventHandler {
+class NS_STACK_CLASS nsQueryContentEventHandler {
public:
- nsContentEventHandler(nsPresContext *aPresContext);
+ nsQueryContentEventHandler(nsPresContext *aPresContext);
// NS_QUERY_SELECTED_TEXT event handler
nsresult OnQuerySelectedText(nsQueryContentEvent* aEvent);
// NS_QUERY_TEXT_CONTENT event handler
nsresult OnQueryTextContent(nsQueryContentEvent* aEvent);
+ // NS_QUERY_CHARACTER_RECT event handler
+ nsresult OnQueryCharacterRect(nsQueryContentEvent* aEvent);
// NS_QUERY_CARET_RECT event handler
nsresult OnQueryCaretRect(nsQueryContentEvent* aEvent);
- // NS_QUERY_TEXT_RECT event handler
- nsresult OnQueryTextRect(nsQueryContentEvent* aEvent);
- // NS_QUERY_EDITOR_RECT event handler
- nsresult OnQueryEditorRect(nsQueryContentEvent* aEvent);
-
- // NS_SELECTION_* event
- nsresult OnSelectionEvent(nsSelectionEvent* aEvent);
-
protected:
nsPresContext* mPresContext;
nsIPresShell* mPresShell;
nsCOMPtr<nsISelection> mSelection;
nsCOMPtr<nsIRange> mFirstSelectedRange;
nsCOMPtr<nsIContent> mRootContent;
nsresult Init(nsQueryContentEvent* aEvent);
-public:
// FlatText means the text that is generated from DOM tree. The BR elements
// are replaced to native linefeeds. Other elements are ignored.
- // Get the offset in FlatText of the range. (also used by nsIMEStateManager)
- static nsresult GetFlatTextOffsetOfRange(nsIContent* aRootContent,
- nsINode* aNode,
- PRInt32 aNodeOffset,
- PRUint32* aOffset);
- static nsresult GetFlatTextOffsetOfRange(nsIContent* aRootContent,
- nsIRange* aRange,
- PRUint32* aOffset);
-protected:
+ // Generate the FlatText from DOM range.
+ nsresult GenerateFlatTextContent(nsIRange* aRange, nsAFlatString& aString);
// Make the DOM range from the offset of FlatText and the text length.
// If aExpandToClusterBoundaries is true, the start offset and the end one are
// expanded to nearest cluster boundaries.
nsresult SetRangeFromFlatTextOffset(nsIRange* aRange,
PRUint32 aNativeOffset,
PRUint32 aNativeLength,
PRBool aExpandToClusterBoundaries);
+ // Get the offset in FlatText of the range.
+ nsresult GetFlatTextOffsetOfRange(nsIRange* aRange, PRUint32* aOffset);
// Find the first textframe for the range, and get the start offset in
// the frame.
nsresult GetStartFrameAndOffset(nsIRange* aRange,
- nsIFrame** aFrame,
- PRInt32* aOffsetInFrame);
+ nsIFrame** aFrame, PRInt32* aOffsetInFrame);
// Convert the frame relative offset to the root view relative offset.
- nsresult ConvertToRootViewRelativeOffset(nsIFrame* aFrame,
- nsRect& aRect);
+ nsresult ConvertToRootViewRelativeOffset(nsIFrame* aFrame, nsRect& aRect);
+ // The helper for OnQueryCharacterRect/OnQueryCaretRect.
+ // Don't call for another event.
+ nsresult QueryRectFor(nsQueryContentEvent* aEvent, nsIRange* aRange,
+ nsCaret* aCaret);
// Expand aXPOffset to the nearest offset in cluster boundary. aForward is
// true, it is expanded to forward.
nsresult ExpandToClusterBoundary(nsIContent* aContent, PRBool aForward,
PRUint32* aXPOffset);
};
-#endif // nsContentEventHandler_h__
+#endif // nsQueryContentEventHandler_h__
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -564,23 +564,16 @@ public:
static nsresult GetSearchFromHrefString(const nsAString &aHref,
nsAString& aSearch);
static nsresult GetPortFromHrefString(const nsAString &aHref,
nsAString& aPort);
static nsresult GetHashFromHrefString(const nsAString &aHref,
nsAString& aHash);
-
- /**
- * Locate an nsIEditor rooted at this content node, if there is one.
- */
- NS_HIDDEN_(nsresult) GetEditor(nsIEditor** aEditor);
- NS_HIDDEN_(nsresult) GetEditorInternal(nsIEditor** aEditor);
-
protected:
/**
* Focus or blur the element. This is what you should call if you want to
* *cause* a focus or blur on your element. SetFocus / SetBlur are the
* methods where you want to catch what occurs on your element.
* @param aDoFocus true to focus, false to blur
*/
void SetElementFocus(PRBool aDoFocus);
@@ -731,16 +724,22 @@ protected:
* attributes in null namespace.
*
* @param aAttr name of attribute.
* @param aResult result value [out]
*/
NS_HIDDEN_(nsresult) GetURIListAttr(nsIAtom* aAttr, nsAString& aResult);
/**
+ * Locate an nsIEditor rooted at this content node, if there is one.
+ */
+ NS_HIDDEN_(nsresult) GetEditor(nsIEditor** aEditor);
+ NS_HIDDEN_(nsresult) GetEditorInternal(nsIEditor** aEditor);
+
+ /**
* Locates the nsIEditor associated with this node. In general this is
* equivalent to GetEditorInternal(), but for designmode or contenteditable,
* this may need to get an editor that's not actually on this element's
* associated TextControlFrame. This is used by the spellchecking routines
* to get the editor affected by changing the spellcheck attribute on this
* node.
*/
virtual already_AddRefed<nsIEditor> GetAssociatedEditor();
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -1538,19 +1538,16 @@ pref("network.autodial-helper.enabled",
pref("advanced.system.supportDDEExec", true);
// Use CP932 compatible map for JIS X 0208
pref("intl.jis0208.map", "CP932");
// Switch the keyboard layout per window
pref("intl.keyboard.per_window_layout", false);
-// Enable/Disable TSF support
-pref("intl.enable_tsf_support", false);
-
// See bug 448927, on topmost panel, some IMEs are not usable on Windows.
pref("ui.panel.default_level_parent", false);
# WINNT
#endif
#ifdef XP_MACOSX
// Mac specific preference defaults
--- a/view/src/nsViewManager.cpp
+++ b/view/src/nsViewManager.cpp
@@ -1244,17 +1244,16 @@ NS_IMETHODIMP nsViewManager::DispatchEve
//Find the view whose coordinates system we're in.
nsView* baseView = nsView::GetViewFor(aEvent->widget);
nsView* view = baseView;
PRBool capturedEvent = PR_FALSE;
if (!NS_IS_KEY_EVENT(aEvent) && !NS_IS_IME_EVENT(aEvent) &&
!NS_IS_CONTEXT_MENU_KEY(aEvent) && !NS_IS_FOCUS_EVENT(aEvent) &&
!NS_IS_QUERY_CONTENT_EVENT(aEvent) && !NS_IS_PLUGIN_EVENT(aEvent) &&
- !NS_IS_SELECTION_EVENT(aEvent) &&
aEvent->eventStructType != NS_ACCESSIBLE_EVENT) {
// will dispatch using coordinates. Pretty bogus but it's consistent
// with what presshell does.
view = GetDisplayRootFor(baseView);
}
//Find the view to which we're initially going to send the event
//for hittesting.
--- a/widget/Makefile.in
+++ b/widget/Makefile.in
@@ -40,13 +40,13 @@ topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src
ifdef ENABLE_TESTS
-TOOL_DIRS += tests
+DIRS += tests
endif
include $(topsrcdir)/config/rules.mk
--- a/widget/public/nsGUIEvent.h
+++ b/widget/public/nsGUIEvent.h
@@ -100,17 +100,16 @@ class nsHashKey;
#define NS_XUL_COMMAND_EVENT 32
#define NS_QUERY_CONTENT_EVENT 33
#ifdef MOZ_MEDIA
#define NS_MEDIA_EVENT 34
#endif // MOZ_MEDIA
#define NS_DRAG_EVENT 35
#define NS_NOTIFYPAINT_EVENT 36
#define NS_SIMPLE_GESTURE_EVENT 37
-#define NS_SELECTION_EVENT 38
// These flags are sort of a mess. They're sort of shared between event
// listener flags and event flags, but only some of them. You've been
// warned!
#define NS_EVENT_FLAG_NONE 0x0000
#define NS_EVENT_FLAG_TRUSTED 0x0001
#define NS_EVENT_FLAG_BUBBLE 0x0002
#define NS_EVENT_FLAG_CAPTURE 0x0004
@@ -345,28 +344,24 @@ class nsHashKey;
// Query the content information
#define NS_QUERY_CONTENT_EVENT_START 3200
// Query for the selected text information, it return the selection offset,
// selection length and selected text.
#define NS_QUERY_SELECTED_TEXT (NS_QUERY_CONTENT_EVENT_START)
// Query for the text content of specified range, it returns actual lengh (if
// the specified range is too long) and the text of the specified range.
-// Returns the entire text if requested length > actual length.
#define NS_QUERY_TEXT_CONTENT (NS_QUERY_CONTENT_EVENT_START + 1)
+// Query for the character rect of nth character. If there is no character at
+// the offset, the query will be failed. The offset of the result is relative
+// position from the top level widget.
+#define NS_QUERY_CHARACTER_RECT (NS_QUERY_CONTENT_EVENT_START + 2)
// Query for the caret rect of nth insertion point. The offset of the result is
// relative position from the top level widget.
#define NS_QUERY_CARET_RECT (NS_QUERY_CONTENT_EVENT_START + 3)
-// Query for the bounding rect of a range of characters. This works on any
-// valid character range given offset and length. Result is relative to top
-// level widget coordinates
-#define NS_QUERY_TEXT_RECT (NS_QUERY_CONTENT_EVENT_START + 4)
-// Query for the bounding rect of the current focused frame. Result is relative
-// to top level widget coordinates
-#define NS_QUERY_EDITOR_RECT (NS_QUERY_CONTENT_EVENT_START + 5)
// Video events
#ifdef MOZ_MEDIA
#define NS_MEDIA_EVENT_START 3300
#define NS_LOADSTART (NS_MEDIA_EVENT_START)
#define NS_PROGRESS (NS_MEDIA_EVENT_START+1)
#define NS_LOADEDMETADATA (NS_MEDIA_EVENT_START+2)
#define NS_LOADEDDATA (NS_MEDIA_EVENT_START+3)
@@ -402,21 +397,16 @@ class nsHashKey;
#define NS_SIMPLE_GESTURE_ROTATE_UPDATE (NS_SIMPLE_GESTURE_EVENT_START+5)
#define NS_SIMPLE_GESTURE_ROTATE (NS_SIMPLE_GESTURE_EVENT_START+6)
// Plug-in event. This is used when a plug-in has focus and when the native
// event needs to be passed to the focused plug-in directly.
#define NS_PLUGIN_EVENT_START 3600
#define NS_PLUGIN_EVENT (NS_PLUGIN_EVENT_START)
-// Events to manipulate selection (nsSelectionEvent)
-#define NS_SELECTION_EVENT_START 3700
-// Clear any previous selection and set the given range as the selection
-#define NS_SELECTION_SET (NS_SELECTION_EVENT_START)
-
/**
* Return status for event processors, nsEventStatus, is defined in
* nsEvent.h.
*/
/**
* sizemode is an adjunct to widget size
*/
@@ -868,21 +858,21 @@ struct nsTextEventReply
typedef struct nsTextEventReply nsTextEventReply;
class nsTextEvent : public nsInputEvent
{
public:
nsTextEvent(PRBool isTrusted, PRUint32 msg, nsIWidget *w)
: nsInputEvent(isTrusted, msg, w, NS_TEXT_EVENT),
- rangeCount(0), rangeArray(nsnull), isChar(PR_FALSE)
+ theText(nsnull), rangeCount(0), rangeArray(nsnull), isChar(PR_FALSE)
{
}
- nsString theText;
+ const PRUnichar* theText;
nsTextEventReply theReply;
PRUint32 rangeCount;
// Note that the range array may not specify a caret position; in that
// case there will be no range of type NS_TEXTRANGE_CARETPOSITION in the
// array.
nsTextRangeArray rangeArray;
PRBool isChar;
};
@@ -975,62 +965,45 @@ public:
void InitForQueryTextContent(PRUint32 aOffset, PRUint32 aLength)
{
NS_ASSERTION(message == NS_QUERY_TEXT_CONTENT,
"wrong initializer is called");
mInput.mOffset = aOffset;
mInput.mLength = aLength;
}
+ void InitForQueryCharacterRect(PRUint32 aOffset)
+ {
+ NS_ASSERTION(message == NS_QUERY_CHARACTER_RECT,
+ "wrong initializer is called");
+ mInput.mOffset = aOffset;
+ }
+
void InitForQueryCaretRect(PRUint32 aOffset)
{
NS_ASSERTION(message == NS_QUERY_CARET_RECT,
"wrong initializer is called");
mInput.mOffset = aOffset;
}
- void InitForQueryTextRect(PRUint32 aOffset, PRUint32 aLength)
- {
- NS_ASSERTION(message == NS_QUERY_TEXT_RECT,
- "wrong initializer is called");
- mInput.mOffset = aOffset;
- mInput.mLength = aLength;
- }
-
PRBool mSucceeded;
struct {
PRUint32 mOffset;
PRUint32 mLength;
} mInput;
struct {
void* mContentsRoot;
PRUint32 mOffset;
nsString mString;
nsIntRect mRect; // Finally, the coordinates is system coordinates.
// The return widget has the caret. This is set at all query events.
nsIWidget* mFocusedWidget;
- PRPackedBool mReversed; // true if selection is reversed (end < start)
} mReply;
};
-class nsSelectionEvent : public nsGUIEvent
-{
-public:
- nsSelectionEvent(PRBool aIsTrusted, PRUint32 aMsg, nsIWidget *aWidget) :
- nsGUIEvent(aIsTrusted, aMsg, aWidget, NS_SELECTION_EVENT),
- mSucceeded(PR_FALSE)
- {
- }
-
- PRUint32 mOffset; // start offset of selection
- PRUint32 mLength; // length of selection
- PRPackedBool mReversed; // selection "anchor" should be in front
- PRPackedBool mSucceeded;
-};
-
/**
* MenuItem event
*
* When this event occurs the widget field in nsGUIEvent holds the "target"
* for the event
*/
class nsMenuEvent : public nsGUIEvent
@@ -1259,22 +1232,18 @@ enum nsDragDropEventStatus {
((evnt)->message == NS_LOSTFOCUS) || \
((evnt)->message == NS_ACTIVATE) || \
((evnt)->message == NS_DEACTIVATE) || \
((evnt)->message == NS_PLUGIN_ACTIVATE))
#define NS_IS_QUERY_CONTENT_EVENT(evnt) \
(((evnt)->message == NS_QUERY_SELECTED_TEXT) || \
((evnt)->message == NS_QUERY_TEXT_CONTENT) || \
- ((evnt)->message == NS_QUERY_CARET_RECT) || \
- ((evnt)->message == NS_QUERY_TEXT_RECT) || \
- ((evnt)->message == NS_QUERY_EDITOR_RECT))
-
-#define NS_IS_SELECTION_EVENT(evnt) \
- (((evnt)->message == NS_SELECTION_SET))
+ ((evnt)->message == NS_QUERY_CHARACTER_RECT) || \
+ ((evnt)->message == NS_QUERY_CARET_RECT))
#define NS_IS_PLUGIN_EVENT(evnt) \
(((evnt)->message == NS_PLUGIN_EVENT))
#define NS_IS_TRUSTED_EVENT(event) \
(((event)->flags & NS_EVENT_FLAG_TRUSTED) != 0)
// Mark an event as being dispatching.
--- a/widget/public/nsIWidget.h
+++ b/widget/public/nsIWidget.h
@@ -88,24 +88,21 @@ typedef nsEventStatus (* EVENT_CALLBACK)
#define NS_NATIVE_OFFSETY 7
#define NS_NATIVE_PLUGIN_PORT 8
#define NS_NATIVE_SCREEN 9
#define NS_NATIVE_SHELLWIDGET 10 // Get the shell GtkWidget
#ifdef XP_MACOSX
#define NS_NATIVE_PLUGIN_PORT_QD 100
#define NS_NATIVE_PLUGIN_PORT_CG 101
#endif
-#ifdef XP_WIN
-#define NS_NATIVE_TSF_POINTER 100
-#endif
-// 075a7792-6ba9-454e-b431-25a43fdbd3f6
+// a85944af-7fce-4e45-bf04-ac12c823394b
#define NS_IWIDGET_IID \
-{ 0x075a7792, 0x6ba9, 0x454e, \
- { 0xb4, 0x31, 0x25, 0xa4, 0x3f, 0xdb, 0xd3, 0xf6 } }
+{ 0xa85944af, 0x7fce, 0x4e45, \
+ { 0xbf, 0x04, 0xac, 0x12, 0xc8, 0x23, 0x39, 0x4b } }
// Hide the native window systems real window type so as to avoid
// including native window system types and APIs. This is necessary
// to ensure cross-platform code.
typedef void* nsNativeWidget;
/*
* Window shadow styles
@@ -1240,39 +1237,16 @@ class nsIWidget : public nsISupports {
* NS_VK_SCROLL_LOCK.
* aLEDState is the result for current LED state of the key.
* If the LED is 'ON', it returns TRUE, otherwise, FALSE.
* If the platform doesn't support the LED state (or we cannot get the
* state), this method returns NS_ERROR_NOT_IMPLEMENTED.
*/
NS_IMETHOD GetToggledKeyState(PRUint32 aKeyCode, PRBool* aLEDState) = 0;
- /*
- * An editable node (i.e. input/textarea/design mode document)
- * is receiving or giving up focus
- * aFocus is true if node is receiving focus
- * aFocus is false if node is giving up focus (blur)
- */
- NS_IMETHOD OnIMEFocusChange(PRBool aFocus) = 0;
-
- /*
- * Text content of the focused node has changed
- * aStart is the starting offset of the change
- * aOldEnd is the ending offset of the change
- * aNewEnd is the caret offset after the change
- */
- NS_IMETHOD OnIMETextChange(PRUint32 aStart,
- PRUint32 aOldEnd,
- PRUint32 aNewEnd) = 0;
-
- /*
- * Selection has changed in the focused node
- */
- NS_IMETHOD OnIMESelectionChange(void) = 0;
-
protected:
// keep the list of children. We also keep track of our siblings.
// The ownership model is as follows: parent holds a strong ref to
// the first element of the list, and each element holds a strong
// ref to the next element in the list. The prevsibling and
// lastchild pointers are weak, which is fine as long as they are
// maintained properly.
nsCOMPtr<nsIWidget> mFirstChild;
--- a/widget/src/cocoa/nsChildView.mm
+++ b/widget/src/cocoa/nsChildView.mm
@@ -5485,18 +5485,18 @@ GetUSLayoutCharFromKeyTranslate(UInt32 a
NSRect rect;
if (!mGeckoChild || theRange.location == NSNotFound)
return rect;
nsIntRect r;
PRBool useCaretRect = theRange.length == 0;
if (!useCaretRect) {
- nsQueryContentEvent charRect(PR_TRUE, NS_QUERY_TEXT_RECT, mGeckoChild);
- charRect.InitForQueryTextRect(theRange.location, 1);
+ nsQueryContentEvent charRect(PR_TRUE, NS_QUERY_CHARACTER_RECT, mGeckoChild);
+ charRect.InitForQueryCharacterRect(theRange.location);
mGeckoChild->DispatchWindowEvent(charRect);
if (charRect.mSucceeded)
r = charRect.mReply.mRect;
else
useCaretRect = PR_TRUE;
}
if (useCaretRect) {
--- a/widget/src/windows/Makefile.in
+++ b/widget/src/windows/Makefile.in
@@ -102,17 +102,16 @@ CPPSRCS += \
nsNativeDragTarget.cpp \
nsNativeDragSource.cpp \
nsDragService.cpp \
nsClipboard.cpp \
nsImageClipboard.cpp \
nsBidiKeyboard.cpp \
nsSound.cpp \
nsIdleServiceWin.cpp \
- nsTextStore.cpp \
$(NULL)
endif
DEFINES += -D_IMPL_NS_WIDGET -DMOZ_UNICODE
ifdef BUILD_STATIC_LIBS
DEFINES += -DMOZ_STATIC_COMPONENT_LIBS
deleted file mode 100644
--- a/widget/src/windows/nsTextStore.cpp
+++ /dev/null
@@ -1,1274 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Ningjie Chen <chenn@email.uc.edu>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include <olectl.h>
-
-#include "nscore.h"
-#include "nsTextStore.h"
-#include "nsWindow.h"
-#include "nsIPrefBranch.h"
-#include "nsIPrefService.h"
-#include "prlog.h"
-
-/******************************************************************/
-/* nsTextStore */
-/******************************************************************/
-
-ITfThreadMgr* nsTextStore::sTsfThreadMgr = NULL;
-DWORD nsTextStore::sTsfClientId = 0;
-nsTextStore* nsTextStore::sTsfTextStore = NULL;
-
-UINT nsTextStore::sFlushTIPInputMessage = 0;
-
-#ifdef PR_LOGGING
-PRLogModuleInfo* sTextStoreLog = nsnull;
-#endif
-
-nsTextStore::nsTextStore()
-{
- mRefCnt = 1;
- mEditCookie = 0;
- mSinkMask = 0;
- mWindow = nsnull;
- mLock = 0;
- mLockQueued = 0;
- mTextChange.acpStart = PR_INT32_MAX;
- mTextChange.acpOldEnd = mTextChange.acpNewEnd = 0;
-}
-
-nsTextStore::~nsTextStore()
-{
-}
-
-PRBool
-nsTextStore::Create(nsWindow* aWindow,
- PRUint32 aIMEState)
-{
- if (!mDocumentMgr) {
- // Create document manager
- HRESULT hr = sTsfThreadMgr->CreateDocumentMgr(
- getter_AddRefs(mDocumentMgr));
- NS_ENSURE_TRUE(SUCCEEDED(hr), PR_FALSE);
- mWindow = aWindow;
- // Create context and add it to document manager
- hr = mDocumentMgr->CreateContext(sTsfClientId, 0,
- static_cast<ITextStoreACP*>(this),
- getter_AddRefs(mContext), &mEditCookie);
- if (SUCCEEDED(hr)) {
- SetIMEEnabledInternal(aIMEState);
- hr = mDocumentMgr->Push(mContext);
- }
- if (SUCCEEDED(hr)) {
- PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
- ("TSF: Created, window=%08x\n", aWindow));
- return PR_TRUE;
- }
- mContext = NULL;
- mDocumentMgr = NULL;
- }
- return PR_FALSE;
-}
-
-PRBool
-nsTextStore::Destroy(void)
-{
- Blur();
- if (mWindow) {
- // When blurred, Tablet Input Panel posts "blur" messages
- // and try to insert text when the message is retrieved later.
- // But by that time the text store is already destroyed,
- // so try to get the message early
- MSG msg;
- if (::PeekMessageW(&msg, mWindow->GetWindowHandle(),
- sFlushTIPInputMessage, sFlushTIPInputMessage,
- PM_REMOVE)) {
- ::DispatchMessageW(&msg);
- }
- }
- mContext = NULL;
- if (mDocumentMgr) {
- mDocumentMgr->Pop(TF_POPF_ALL);
- mDocumentMgr = NULL;
- }
- mSink = NULL;
- PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
- ("TSF: Destroyed, window=%08x\n", mWindow));
- mWindow = NULL;
- return PR_TRUE;
-}
-
-PRBool
-nsTextStore::Focus(void)
-{
- HRESULT hr = sTsfThreadMgr->SetFocus(mDocumentMgr);
- NS_ENSURE_TRUE(SUCCEEDED(hr), PR_FALSE);
- PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
- ("TSF: Focused\n"));
- return PR_TRUE;
-}
-
-PRBool
-nsTextStore::Blur(void)
-{
- sTsfThreadMgr->SetFocus(NULL);
- PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
- ("TSF: Blurred\n"));
- return PR_TRUE;
-}
-
-STDMETHODIMP
-nsTextStore::QueryInterface(REFIID riid,
- void** ppv)
-{
- *ppv=NULL;
- if ( (IID_IUnknown == riid) || (IID_ITextStoreACP == riid) ) {
- *ppv = static_cast<ITextStoreACP*>(this);
- } else if (IID_ITfContextOwnerCompositionSink == riid) {
- *ppv = static_cast<ITfContextOwnerCompositionSink*>(this);
- }
- if (*ppv) {
- AddRef();
- return S_OK;
- }
- return E_NOINTERFACE;
-}
-
-STDMETHODIMP_(ULONG) nsTextStore::AddRef()
-{
- return ++mRefCnt;
-}
-
-STDMETHODIMP_(ULONG) nsTextStore::Release()
-{
- --mRefCnt;
- if (0 != mRefCnt)
- return mRefCnt;
- delete this;
- return 0;
-}
-
-STDMETHODIMP
-nsTextStore::AdviseSink(REFIID riid,
- IUnknown *punk,
- DWORD dwMask)
-{
- NS_ENSURE_TRUE(punk && IID_ITextStoreACPSink == riid, E_INVALIDARG);
- if (!mSink) {
- // Install sink
- punk->QueryInterface(IID_ITextStoreACPSink, getter_AddRefs(mSink));
- NS_ENSURE_TRUE(mSink, E_UNEXPECTED);
- } else {
- // If sink is already installed we check to see if they are the same
- // Get IUnknown from both sides for comparison
- nsRefPtr<IUnknown> comparison1, comparison2;
- punk->QueryInterface(IID_IUnknown, getter_AddRefs(comparison1));
- mSink->QueryInterface(IID_IUnknown, getter_AddRefs(comparison2));
- if (comparison1 != comparison2)
- return CONNECT_E_ADVISELIMIT;
- }
- // Update mask either for a new sink or an existing sink
- mSinkMask = dwMask;
- PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
- ("TSF: Sink installed, punk=%08x\n", punk));
- return S_OK;
-}
-
-STDMETHODIMP
-nsTextStore::UnadviseSink(IUnknown *punk)
-{
- NS_ENSURE_TRUE(punk, E_INVALIDARG);
- NS_ENSURE_TRUE(mSink, CONNECT_E_NOCONNECTION);
- // Get IUnknown from both sides for comparison
- nsRefPtr<IUnknown> comparison1, comparison2;
- punk->QueryInterface(IID_IUnknown, getter_AddRefs(comparison1));
- mSink->QueryInterface(IID_IUnknown, getter_AddRefs(comparison2));
- // Unadvise only if sinks are the same
- NS_ENSURE_TRUE(comparison1 == comparison2, CONNECT_E_NOCONNECTION);
- mSink = NULL;
- mSinkMask = 0;
- PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
- ("TSF: Sink removed, punk=%08x\n", punk));
- return S_OK;
-}
-
-STDMETHODIMP
-nsTextStore::RequestLock(DWORD dwLockFlags,
- HRESULT *phrSession)
-{
- NS_ENSURE_TRUE(mSink, E_FAIL);
- NS_ENSURE_TRUE(phrSession, E_INVALIDARG);
- if (mLock) {
- // only time when reentrant lock is allowed is when caller holds a
- // read-only lock and is requesting an async write lock
- if (TS_LF_READ == (mLock & TS_LF_READWRITE) &&
- TS_LF_READWRITE == (dwLockFlags & TS_LF_READWRITE) &&
- !(dwLockFlags & TS_LF_SYNC)) {
- *phrSession = TS_S_ASYNC;
- mLockQueued = dwLockFlags & (~TS_LF_SYNC);
- } else {
- // no more locks allowed
- *phrSession = TS_E_SYNCHRONOUS;
- return E_FAIL;
- }
- } else {
- // put on lock
- mLock = dwLockFlags & (~TS_LF_SYNC);
- *phrSession = mSink->OnLockGranted(mLock);
- while (mLockQueued) {
- mLock = mLockQueued;
- mLockQueued = 0;
- mSink->OnLockGranted(mLock);
- }
- mLock = 0;
- }
- return S_OK;
-}
-
-STDMETHODIMP
-nsTextStore::GetStatus(TS_STATUS *pdcs)
-{
- NS_ENSURE_TRUE(pdcs, E_INVALIDARG);
- pdcs->dwDynamicFlags = 0;
- // we use a "flat" text model for TSF support so no hidden text
- pdcs->dwStaticFlags = TS_SS_NOHIDDENTEXT;
- return S_OK;
-}
-
-STDMETHODIMP
-nsTextStore::QueryInsert(LONG acpTestStart,
- LONG acpTestEnd,
- ULONG cch,
- LONG *pacpResultStart,
- LONG *pacpResultEnd)
-{
- PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
- ("TSF: QueryInsert, start=%ld end=%ld cch=%lu\n",
- acpTestStart, acpTestEnd, cch));
- // We don't test to see if these positions are
- // after the end of document for performance reasons
- NS_ENSURE_TRUE(0 <= acpTestStart && acpTestStart <= acpTestEnd &&
- pacpResultStart && pacpResultEnd, E_INVALIDARG);
-
- // XXX need to adjust to cluster boundary
- // Assume we are given good offsets for now
- *pacpResultStart = acpTestStart;
- *pacpResultEnd = acpTestStart + cch;
-
- PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
- ("TSF: QueryInsert SUCCEEDED\n"));
- return S_OK;
-}
-
-STDMETHODIMP
-nsTextStore::GetSelection(ULONG ulIndex,
- ULONG ulCount,
- TS_SELECTION_ACP *pSelection,
- ULONG *pcFetched)
-{
- NS_ENSURE_TRUE(TS_LF_READ == (mLock & TS_LF_READ), TS_E_NOLOCK);
- NS_ENSURE_TRUE(ulCount && pSelection && pcFetched, E_INVALIDARG);
-
- *pcFetched = 0;
- NS_ENSURE_TRUE(TS_DEFAULT_SELECTION == ulIndex || 0 == ulIndex,
- TS_E_NOSELECTION);
- if (mCompositionView) {
- // Emulate selection during compositions
- *pSelection = mCompositionSelection;
- } else {
- // Construct and initialize an event to get selection info
- nsQueryContentEvent event(PR_TRUE, NS_QUERY_SELECTED_TEXT, mWindow);
- mWindow->InitEvent(event);
- mWindow->DispatchWindowEvent(&event);
- NS_ENSURE_TRUE(event.mSucceeded, E_FAIL);
- // Usually the selection anchor (beginning) position corresponds to the
- // TSF start and the selection focus (ending) position corresponds to
- // the TSF end, but if selection is reversed the focus now corresponds
- // to the TSF start and the anchor now corresponds to the TSF end
- pSelection->acpStart = event.mReply.mOffset;
- pSelection->acpEnd = pSelection->acpStart + event.mReply.mString.Length();
- pSelection->style.ase = event.mReply.mString.Length() &&
- event.mReply.mReversed ? TS_AE_START : TS_AE_END;
- // No support for interim character
- pSelection->style.fInterimChar = 0;
- }
- *pcFetched = 1;
- return S_OK;
-}
-
-HRESULT
-nsTextStore::SetSelectionInternal(const TS_SELECTION_ACP* pSelection)
-{
- PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
- ("TSF: SetSelection, sel=%ld-%ld\n",
- pSelection->acpStart, pSelection->acpEnd));
- if (mCompositionView) {
- // Emulate selection during compositions
- NS_ENSURE_TRUE(pSelection->acpStart >= mCompositionStart &&
- pSelection->acpEnd <= mCompositionStart +
- LONG(mCompositionString.Length()), TS_E_INVALIDPOS);
- mCompositionSelection = *pSelection;
- } else {
- nsSelectionEvent event(PR_TRUE, NS_SELECTION_SET, mWindow);
- event.mOffset = pSelection->acpStart;
- event.mLength = PRUint32(pSelection->acpEnd - pSelection->acpStart);
- event.mReversed = pSelection->style.ase == TS_AE_START;
- mWindow->InitEvent(event);
- mWindow->DispatchWindowEvent(&event);
- NS_ENSURE_TRUE(event.mSucceeded, E_FAIL);
- }
- PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
- ("TSF: SetSelection SUCCEEDED\n"));
- return S_OK;
-}
-
-STDMETHODIMP
-nsTextStore::SetSelection(ULONG ulCount,
- const TS_SELECTION_ACP *pSelection)
-{
- NS_ENSURE_TRUE(TS_LF_READWRITE == (mLock & TS_LF_READWRITE), TS_E_NOLOCK);
- NS_ENSURE_TRUE(1 == ulCount && pSelection, E_INVALIDARG);
-
- return SetSelectionInternal(pSelection);
-}
-
-STDMETHODIMP
-nsTextStore::GetText(LONG acpStart,
- LONG acpEnd,
- WCHAR *pchPlain,
- ULONG cchPlainReq,
- ULONG *pcchPlainOut,
- TS_RUNINFO *prgRunInfo,
- ULONG ulRunInfoReq,
- ULONG *pulRunInfoOut,
- LONG *pacpNext)
-{
- NS_ENSURE_TRUE(TS_LF_READ == (mLock & TS_LF_READ), TS_E_NOLOCK);
- NS_ENSURE_TRUE(pcchPlainOut && (pchPlain || prgRunInfo) &&
- (!cchPlainReq == !pchPlain) &&
- (!ulRunInfoReq == !prgRunInfo), E_INVALIDARG);
- NS_ENSURE_TRUE(0 <= acpStart && -1 <= acpEnd &&
- (-1 == acpEnd || acpStart <= acpEnd), TS_E_INVALIDPOS);
-
- // Making sure to NULL-terminate string just to be on the safe side
- *pcchPlainOut = 0;
- if (pchPlain && cchPlainReq) *pchPlain = NULL;
- if (pulRunInfoOut) *pulRunInfoOut = 0;
- if (pacpNext) *pacpNext = acpStart;
- if (prgRunInfo && ulRunInfoReq) {
- prgRunInfo->uCount = 0;
- prgRunInfo->type = TS_RT_PLAIN;
- }
- PRUint32 length = -1 == acpEnd ? PR_UINT32_MAX : PRUint32(acpEnd - acpStart);
- if (cchPlainReq && cchPlainReq - 1 < length) {
- length = cchPlainReq - 1;
- }
- if (length) {
- LONG compNewStart = 0, compOldEnd = 0, compNewEnd = 0;
- if (mCompositionView) {
- // Sometimes GetText gets called between InsertTextAtSelection and
- // OnUpdateComposition. In this case the returned text would
- // be out of sync because we haven't sent NS_TEXT_TEXT in
- // OnUpdateComposition yet. Manually resync here.
- compOldEnd = PR_MIN(LONG(length) + acpStart,
- mCompositionLength + mCompositionStart);
- compNewEnd = PR_MIN(LONG(length) + acpStart,
- LONG(mCompositionString.Length()) + mCompositionStart);
- compNewStart = PR_MAX(acpStart, mCompositionStart);
- // Check if the range is affected
- if (compOldEnd > compNewStart || compNewEnd > compNewStart) {
- NS_ASSERTION(compOldEnd >= mCompositionStart &&
- compNewEnd >= mCompositionStart, "Range end is less than start\n");
- length = PRUint32(LONG(length) + compOldEnd - compNewEnd);
- }
- }
- // Send NS_QUERY_TEXT_CONTENT to get text content
- nsQueryContentEvent event(PR_TRUE, NS_QUERY_TEXT_CONTENT, mWindow);
- mWindow->InitEvent(event);
- event.InitForQueryTextContent(PRUint32(acpStart), length);
- mWindow->DispatchWindowEvent(&event);
- NS_ENSURE_TRUE(event.mSucceeded, E_FAIL);
-
- if (compOldEnd > compNewStart || compNewEnd > compNewStart) {
- // Resync composition string
- const PRUnichar* compStrStart = mCompositionString.BeginReading() +
- PR_MAX(compNewStart - mCompositionStart, 0);
- event.mReply.mString.Replace(compNewStart - acpStart,
- compOldEnd - mCompositionStart, compStrStart,
- compNewEnd - mCompositionStart);
- length = PRUint32(LONG(length) - compOldEnd + compNewEnd);
- }
- NS_ENSURE_TRUE(-1 == acpEnd || event.mReply.mString.Length() == length,
- TS_E_INVALIDPOS);
- length = PR_MIN(length, event.mReply.mString.Length());
-
- if (pchPlain && cchPlainReq) {
- memcpy(pchPlain, event.mReply.mString.BeginReading(),
- length * sizeof(*pchPlain));
- pchPlain[length] = NULL;
- *pcchPlainOut = length;
- }
- if (prgRunInfo && ulRunInfoReq) {
- prgRunInfo->uCount = length;
- prgRunInfo->type = TS_RT_PLAIN;
- if (pulRunInfoOut) *pulRunInfoOut = 1;
- }
- if (pacpNext) *pacpNext = acpStart + length;
- }
- return S_OK;
-}
-
-STDMETHODIMP
-nsTextStore::SetText(DWORD dwFlags,
- LONG acpStart,
- LONG acpEnd,
- const WCHAR *pchText,
- ULONG cch,
- TS_TEXTCHANGE *pChange)
-{
- // Per SDK documentation, and since we don't have better
- // ways to do this, this method acts as a helper to
- // call SetSelection followed by InsertTextAtSelection
- NS_ENSURE_TRUE(TS_LF_READWRITE == (mLock & TS_LF_READWRITE), TS_E_NOLOCK);
- TS_SELECTION_ACP selection;
- selection.acpStart = acpStart;
- selection.acpEnd = acpEnd;
- selection.style.ase = TS_AE_END;
- selection.style.fInterimChar = 0;
- // Set selection to desired range
- NS_ENSURE_TRUE(SUCCEEDED(SetSelectionInternal(&selection)), E_FAIL);
- // Replace just selected text
- return InsertTextAtSelection(TS_IAS_NOQUERY, pchText, cch,
- NULL, NULL, pChange);
-}
-
-STDMETHODIMP
-nsTextStore::GetFormattedText(LONG acpStart,
- LONG acpEnd,
- IDataObject **ppDataObject)
-{
- // no support for formatted text
- return E_NOTIMPL;
-}
-
-STDMETHODIMP
-nsTextStore::GetEmbedded(LONG acpPos,
- REFGUID rguidService,
- REFIID riid,
- IUnknown **ppunk)
-{
- // embedded objects are not supported
- return E_NOTIMPL;
-}
-
-STDMETHODIMP
-nsTextStore::QueryInsertEmbedded(const GUID *pguidService,
- const FORMATETC *pFormatEtc,
- BOOL *pfInsertable)
-{
- // embedded objects are not supported
- *pfInsertable = FALSE;
- return S_OK;
-}
-
-STDMETHODIMP
-nsTextStore::InsertEmbedded(DWORD dwFlags,
- LONG acpStart,
- LONG acpEnd,
- IDataObject *pDataObject,
- TS_TEXTCHANGE *pChange)
-{
- // embedded objects are not supported
- return E_NOTIMPL;
-}
-
-STDMETHODIMP
-nsTextStore::RequestSupportedAttrs(DWORD dwFlags,
- ULONG cFilterAttrs,
- const TS_ATTRID *paFilterAttrs)
-{
- // no attributes defined
- return S_OK;
-}
-
-STDMETHODIMP
-nsTextStore::RequestAttrsAtPosition(LONG acpPos,
- ULONG cFilterAttrs,
- const TS_ATTRID *paFilterAttrs,
- DWORD dwFlags)
-{
- // no per character attributes defined
- return S_OK;
-}
-
-STDMETHODIMP
-nsTextStore::RequestAttrsTransitioningAtPosition(LONG acpPos,
- ULONG cFilterAttrs,
- const TS_ATTRID *paFilterAttr,
- DWORD dwFlags)
-{
- // no per character attributes defined
- return S_OK;
-}
-
-STDMETHODIMP
-nsTextStore::FindNextAttrTransition(LONG acpStart,
- LONG acpHalt,
- ULONG cFilterAttrs,
- const TS_ATTRID *paFilterAttrs,
- DWORD dwFlags,
- LONG *pacpNext,
- BOOL *pfFound,
- LONG *plFoundOffset)
-{
- NS_ENSURE_TRUE(pacpNext && pfFound && plFoundOffset, E_INVALIDARG);
- // no per character attributes defined
- *pacpNext = *plFoundOffset = acpHalt;
- *pfFound = FALSE;
- return S_OK;
-}
-
-STDMETHODIMP
-nsTextStore::RetrieveRequestedAttrs(ULONG ulCount,
- TS_ATTRVAL *paAttrVals,
- ULONG *pcFetched)
-{
- NS_ENSURE_TRUE(pcFetched && ulCount && paAttrVals, E_INVALIDARG);
- // no attributes defined
- *pcFetched = 0;
- return S_OK;
-}
-
-STDMETHODIMP
-nsTextStore::GetEndACP(LONG *pacp)
-{
- NS_ENSURE_TRUE(TS_LF_READ == (mLock & TS_LF_READ), TS_E_NOLOCK);
- NS_ENSURE_TRUE(pacp, E_INVALIDARG);
- // Flattened text is retrieved and its length returned
- nsQueryContentEvent event(PR_TRUE, NS_QUERY_TEXT_CONTENT, mWindow);
- mWindow->InitEvent(event);
- // Return entire text
- event.InitForQueryTextContent(0, PR_INT32_MAX);
- mWindow->DispatchWindowEvent(&event);
- NS_ENSURE_TRUE(event.mSucceeded, E_FAIL);
- *pacp = LONG(event.mReply.mString.Length());
- return S_OK;
-}
-
-#define TEXTSTORE_DEFAULT_VIEW (1)
-
-STDMETHODIMP
-nsTextStore::GetActiveView(TsViewCookie *pvcView)
-{
- NS_ENSURE_TRUE(pvcView, E_INVALIDARG);
- *pvcView = TEXTSTORE_DEFAULT_VIEW;
- return S_OK;
-}
-
-STDMETHODIMP
-nsTextStore::GetACPFromPoint(TsViewCookie vcView,
- const POINT *pt,
- DWORD dwFlags,
- LONG *pacp)
-{
- NS_ENSURE_TRUE(TS_LF_READ == (mLock & TS_LF_READ), TS_E_NOLOCK);
- NS_ENSURE_TRUE(TEXTSTORE_DEFAULT_VIEW == vcView, E_INVALIDARG);
- // not supported for now
- return E_NOTIMPL;
-}
-
-STDMETHODIMP
-nsTextStore::GetTextExt(TsViewCookie vcView,
- LONG acpStart,
- LONG acpEnd,
- RECT *prc,
- BOOL *pfClipped)
-{
- NS_ENSURE_TRUE(TS_LF_READ == (mLock & TS_LF_READ), TS_E_NOLOCK);
- NS_ENSURE_TRUE(TEXTSTORE_DEFAULT_VIEW == vcView && prc && pfClipped,
- E_INVALIDARG);
- NS_ENSURE_TRUE(acpStart >= 0 && acpEnd >= acpStart, TS_E_INVALIDPOS);
-
- // use NS_QUERY_TEXT_RECT to get rect in system, screen coordinates
- nsQueryContentEvent event(PR_TRUE, NS_QUERY_TEXT_RECT, mWindow);
- mWindow->InitEvent(event);
- event.InitForQueryTextRect(acpStart, acpEnd - acpStart);
- mWindow->DispatchWindowEvent(&event);
- NS_ENSURE_TRUE(event.mSucceeded, TS_E_INVALIDPOS);
- // IMEs don't like empty rects, fix here
- if (event.mReply.mRect.width <= 0)
- event.mReply.mRect.width = 1;
- if (event.mReply.mRect.height <= 0)
- event.mReply.mRect.height = 1;
-
- // convert to unclipped screen rect
- nsWindow* refWindow = static_cast<nsWindow*>(
- event.mReply.mFocusedWidget ? event.mReply.mFocusedWidget : mWindow);
- // Result rect is in top level widget coordinates
- refWindow = refWindow->GetTopLevelWindow(PR_FALSE);
- NS_ENSURE_TRUE(refWindow, E_FAIL);
-
- nsresult rv = refWindow->WidgetToScreen(event.mReply.mRect,
- event.mReply.mRect);
- NS_ENSURE_SUCCESS(rv, E_FAIL);
-
- // get bounding screen rect to test for clipping
- HRESULT hr = GetScreenExt(vcView, prc);
- NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
-
- // clip text rect to bounding rect
- RECT textRect;
- ::SetRect(&textRect, event.mReply.mRect.x, event.mReply.mRect.y,
- event.mReply.mRect.XMost(), event.mReply.mRect.YMost());
- if (!::IntersectRect(prc, prc, &textRect))
- // Text is not visible
- ::SetRectEmpty(prc);
-
- // not equal if text rect was clipped
- *pfClipped = !::EqualRect(prc, &textRect);
- return S_OK;
-}
-
-STDMETHODIMP
-nsTextStore::GetScreenExt(TsViewCookie vcView,
- RECT *prc)
-{
- NS_ENSURE_TRUE(TEXTSTORE_DEFAULT_VIEW == vcView && prc, E_INVALIDARG);
- // use NS_QUERY_EDITOR_RECT to get rect in system, screen coordinates
- nsQueryContentEvent event(PR_TRUE, NS_QUERY_EDITOR_RECT, mWindow);
- mWindow->InitEvent(event);
- mWindow->DispatchWindowEvent(&event);
- NS_ENSURE_TRUE(event.mSucceeded, E_FAIL);
-
- nsWindow* refWindow = static_cast<nsWindow*>(
- event.mReply.mFocusedWidget ? event.mReply.mFocusedWidget : mWindow);
- // Result rect is in top level widget coordinates
- refWindow = refWindow->GetTopLevelWindow(PR_FALSE);
- NS_ENSURE_TRUE(refWindow, E_FAIL);
-
- nsIntRect boundRect;
- nsresult rv = refWindow->GetClientBounds(boundRect);
- NS_ENSURE_SUCCESS(rv, E_FAIL);
-
- // Clip frame rect to window rect
- boundRect.IntersectRect(event.mReply.mRect, boundRect);
- rv = refWindow->WidgetToScreen(boundRect, boundRect);
- NS_ENSURE_SUCCESS(rv, E_FAIL);
-
- if (!boundRect.IsEmpty()) {
- ::SetRect(prc, boundRect.x, boundRect.y,
- boundRect.XMost(), boundRect.YMost());
- } else {
- ::SetRectEmpty(prc);
- }
- return S_OK;
-}
-
-STDMETHODIMP
-nsTextStore::GetWnd(TsViewCookie vcView,
- HWND *phwnd)
-{
- NS_ENSURE_TRUE(TEXTSTORE_DEFAULT_VIEW == vcView && phwnd, E_INVALIDARG);
- *phwnd = mWindow->GetWindowHandle();
- return S_OK;
-}
-
-STDMETHODIMP
-nsTextStore::InsertTextAtSelection(DWORD dwFlags,
- const WCHAR *pchText,
- ULONG cch,
- LONG *pacpStart,
- LONG *pacpEnd,
- TS_TEXTCHANGE *pChange)
-{
- PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
- ("TSF: InsertTextAtSelection, cch=%lu\n", cch));
- NS_ENSURE_TRUE(TS_LF_READWRITE == (mLock & TS_LF_READWRITE), TS_E_NOLOCK);
- NS_ENSURE_TRUE(!cch || pchText, E_INVALIDARG);
-
- // Get selection first
- TS_SELECTION_ACP sel;
- ULONG selFetched;
- NS_ENSURE_TRUE(SUCCEEDED(GetSelection(
- TS_DEFAULT_SELECTION, 1, &sel, &selFetched)) && selFetched, E_FAIL);
- if (TS_IAS_QUERYONLY == dwFlags) {
- NS_ENSURE_TRUE(pacpStart && pacpEnd, E_INVALIDARG);
- // Simulate text insertion
- *pacpStart = sel.acpStart;
- *pacpEnd = sel.acpEnd;
- if (pChange) {
- pChange->acpStart = sel.acpStart;
- pChange->acpOldEnd = sel.acpEnd;
- pChange->acpNewEnd = sel.acpStart + cch;
- }
- } else {
- NS_ENSURE_TRUE(pChange, E_INVALIDARG);
- NS_ENSURE_TRUE(TS_IAS_NOQUERY == dwFlags || (pacpStart && pacpEnd),
- E_INVALIDARG);
- if (mCompositionView) {
- // Emulate text insertion during compositions, because during a
- // composition, editor expects the whole composition string to
- // be sent in NS_TEXT_TEXT, not just the inserted part.
- // The actual NS_TEXT_TEXT is sent in OnUpdateComposition, which
- // should get called by TSF after this returns
- mCompositionString.Replace(PRUint32(sel.acpStart - mCompositionStart),
- sel.acpEnd - sel.acpStart, pchText, cch);
-
- mCompositionSelection.acpStart += cch;
- mCompositionSelection.acpEnd = mCompositionSelection.acpStart;
- mCompositionSelection.style.ase = TS_AE_END;
- // OnUpdateComposition is not called here because it will
- // result in fun visual artifacts
- PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
- ("TSF: InsertTextAtSelection, replaced=%lu-%lu\n",
- sel.acpStart - mCompositionStart,
- sel.acpEnd - mCompositionStart));
- } else {
- // Use a temporary composition to contain the text
- nsCompositionEvent compEvent(PR_TRUE, NS_COMPOSITION_START, mWindow);
- mWindow->InitEvent(compEvent);
- mWindow->DispatchWindowEvent(&compEvent);
- nsTextEvent event(PR_TRUE, NS_TEXT_TEXT, mWindow);
- mWindow->InitEvent(event);
- if (!cch) {
- // XXX See OnEndComposition comment on inserting empty strings
- event.theText = NS_LITERAL_STRING(" ");
- mWindow->DispatchWindowEvent(&event);
- }
- event.theText.Assign(pchText, cch);
- event.theText.ReplaceSubstring(NS_LITERAL_STRING("\r\n"),
- NS_LITERAL_STRING("\n"));
- mWindow->DispatchWindowEvent(&event);
- compEvent.message = NS_COMPOSITION_END;
- mWindow->DispatchWindowEvent(&compEvent);
- }
- pChange->acpStart = sel.acpStart;
- pChange->acpOldEnd = sel.acpEnd;
- // Get new selection
- NS_ENSURE_TRUE(SUCCEEDED(GetSelection(
- TS_DEFAULT_SELECTION, 1, &sel, &selFetched)) && selFetched, E_FAIL);
- pChange->acpNewEnd = sel.acpEnd;
- if (TS_IAS_NOQUERY != dwFlags) {
- *pacpStart = pChange->acpStart;
- *pacpEnd = pChange->acpNewEnd;
- }
- }
- PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
- ("TSF: InsertTextAtSelection SUCCEEDED\n"));
- return S_OK;
-}
-
-STDMETHODIMP
-nsTextStore::InsertEmbeddedAtSelection(DWORD dwFlags,
- IDataObject *pDataObject,
- LONG *pacpStart,
- LONG *pacpEnd,
- TS_TEXTCHANGE *pChange)
-{
- // embedded objects are not supported
- return E_NOTIMPL;
-}
-
-static HRESULT
-GetRangeExtent(ITfRange* aRange, LONG* aStart, LONG* aLength)
-{
- nsRefPtr<ITfRangeACP> rangeACP;
- aRange->QueryInterface(IID_ITfRangeACP, getter_AddRefs(rangeACP));
- NS_ENSURE_TRUE(rangeACP, E_FAIL);
- return rangeACP->GetExtent(aStart, aLength);
-}
-
-HRESULT
-nsTextStore::OnStartCompositionInternal(ITfCompositionView* pComposition,
- ITfRange* aRange,
- PRBool aPreserveSelection)
-{
- mCompositionView = pComposition;
- HRESULT hr = GetRangeExtent(aRange, &mCompositionStart, &mCompositionLength);
- NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
-
- PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
- ("TSF: OnStartComposition, range=%ld-%ld\n", mCompositionStart,
- mCompositionStart + mCompositionLength));
-
- // Select composition range so the new composition replaces the range
- nsSelectionEvent selEvent(PR_TRUE, NS_SELECTION_SET, mWindow);
- mWindow->InitEvent(selEvent);
- selEvent.mOffset = PRUint32(mCompositionStart);
- selEvent.mLength = PRUint32(mCompositionLength);
- selEvent.mReversed = PR_FALSE;
- mWindow->DispatchWindowEvent(&selEvent);
- NS_ENSURE_TRUE(selEvent.mSucceeded, E_FAIL);
-
- // Set up composition
- nsQueryContentEvent queryEvent(PR_TRUE, NS_QUERY_SELECTED_TEXT, mWindow);
- mWindow->InitEvent(queryEvent);
- mWindow->DispatchWindowEvent(&queryEvent);
- NS_ENSURE_TRUE(queryEvent.mSucceeded, E_FAIL);
- mCompositionString = queryEvent.mReply.mString;
- if (!aPreserveSelection) {
- mCompositionSelection.acpStart = mCompositionStart;
- mCompositionSelection.acpEnd = mCompositionStart + mCompositionLength;
- mCompositionSelection.style.ase = TS_AE_END;
- mCompositionSelection.style.fInterimChar = FALSE;
- }
- nsCompositionEvent event(PR_TRUE, NS_COMPOSITION_START, mWindow);
- mWindow->InitEvent(event);
- mWindow->DispatchWindowEvent(&event);
- return S_OK;
-}
-
-STDMETHODIMP
-nsTextStore::OnStartComposition(ITfCompositionView* pComposition,
- BOOL* pfOk)
-{
- *pfOk = FALSE;
-
- // Only one composition at a time
- if (mCompositionView)
- return S_OK;
-
- nsRefPtr<ITfRange> range;
- HRESULT hr = pComposition->GetRange(getter_AddRefs(range));
- NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
- hr = OnStartCompositionInternal(pComposition, range, PR_FALSE);
- if (SUCCEEDED(hr))
- *pfOk = TRUE;
- return hr;
-}
-
-STDMETHODIMP
-nsTextStore::OnUpdateComposition(ITfCompositionView* pComposition,
- ITfRange* pRangeNew)
-{
- NS_ENSURE_TRUE(mCompositionView &&
- mCompositionView == pComposition &&
- mDocumentMgr && mContext, E_UNEXPECTED);
-
- // Getting display attributes is *really* complicated!
- // We first get the context and the property objects to query for
- // attributes, but since a big range can have a variety of values for
- // the attribute, we have to find out all the ranges that have distinct
- // attribute values. Then we query for what the value represents through
- // the display attribute manager and translate that to nsTextRange to be
- // sent in NS_TEXT_TEXT
- if (!pRangeNew) // pRangeNew is null when the update is not complete
- return S_OK;
-
- // Get starting offset of the composition
- LONG compStart = 0, compLength = 0;
- HRESULT hr = GetRangeExtent(pRangeNew, &compStart, &compLength);
- NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
- if (mCompositionStart != compStart ||
- mCompositionString.Length() != compLength) {
- // If the queried composition length is different from the length
- // of our composition string, OnUpdateComposition is being called
- // because a part of the original composition was committed.
- // Reflect that by committing existing composition and starting
- // a new one. OnEndComposition followed by OnStartComposition
- // will accomplish this automagically.
- OnEndComposition(pComposition);
- OnStartCompositionInternal(pComposition, pRangeNew, PR_TRUE);
- PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
- ("TSF: OnUpdateComposition, (reset) range=%ld-%ld\n",
- compStart, compStart + compLength));
- } else {
- mCompositionLength = compLength;
- PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
- ("TSF: OnUpdateComposition, range=%ld-%ld\n",
- compStart, compStart + compLength));
- }
-
- nsRefPtr<ITfProperty> prop;
- hr = mContext->GetProperty(GUID_PROP_ATTRIBUTE, getter_AddRefs(prop));
- NS_ENSURE_TRUE(SUCCEEDED(hr) && prop, hr);
- hr = LoadManagers();
- NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
-
- // Use NS_TEXT_TEXT to set composition string
- nsTextEvent event(PR_TRUE, NS_TEXT_TEXT, mWindow);
- mWindow->InitEvent(event);
-
- VARIANT propValue;
- ::VariantInit(&propValue);
- nsRefPtr<ITfRange> range;
- nsRefPtr<IEnumTfRanges> enumRanges;
- hr = prop->EnumRanges(TfEditCookie(mEditCookie),
- getter_AddRefs(enumRanges), pRangeNew);
- NS_ENSURE_TRUE(SUCCEEDED(hr) && enumRanges, hr);
-
- nsAutoTArray<nsTextRange, 4> textRanges;
- nsTextRange newRange;
- newRange.mStartOffset = PRUint32(mCompositionSelection.acpStart - compStart);
- newRange.mEndOffset = PRUint32(mCompositionSelection.acpEnd - compStart);
- newRange.mRangeType = NS_TEXTRANGE_CARETPOSITION;
- textRanges.AppendElement(newRange);
- // No matter if we have display attribute info or not,
- // we always pass in at least one range to NS_TEXT_TEXT
- newRange.mStartOffset = 0;
- newRange.mEndOffset = mCompositionString.Length();
- newRange.mRangeType = NS_TEXTRANGE_RAWINPUT;
- textRanges.AppendElement(newRange);
-
- while (S_OK == enumRanges->Next(1, getter_AddRefs(range), NULL) && range) {
-
- LONG start = 0, length = 0;
- if (FAILED(GetRangeExtent(range, &start, &length))) continue;
-
- newRange.mStartOffset = PRUint32(start - compStart);
- // The end of the last range in the array is
- // always kept at the end of composition
- newRange.mEndOffset = mCompositionString.Length();
-
- // Who came up with this convoluted way that we have to follow?
- ::VariantClear(&propValue);
- hr = prop->GetValue(TfEditCookie(mEditCookie), range, &propValue);
- if (FAILED(hr) || VT_I4 != propValue.vt) continue;
-
- GUID guid;
- hr = mCatMgr->GetGUID(DWORD(propValue.lVal), &guid);
- if (FAILED(hr)) continue;
-
- nsRefPtr<ITfDisplayAttributeInfo> info;
- hr = mDAMgr->GetDisplayAttributeInfo(
- guid, getter_AddRefs(info), NULL);
- if (FAILED(hr) || !info) continue;
-
- TF_DISPLAYATTRIBUTE attr;
- hr = info->GetAttributeInfo(&attr);
- if (FAILED(hr)) continue;
-
- switch (attr.bAttr) {
- case TF_ATTR_TARGET_CONVERTED:
- newRange.mRangeType = NS_TEXTRANGE_SELECTEDCONVERTEDTEXT;
- break;
- case TF_ATTR_CONVERTED:
- newRange.mRangeType = NS_TEXTRANGE_CONVERTEDTEXT;
- break;
- case TF_ATTR_TARGET_NOTCONVERTED:
- newRange.mRangeType = NS_TEXTRANGE_SELECTEDRAWTEXT;
- break;
- default:
- newRange.mRangeType = NS_TEXTRANGE_RAWINPUT;
- break;
- }
-
- nsTextRange& lastRange = textRanges[textRanges.Length() - 1];
- if (lastRange.mStartOffset == newRange.mStartOffset) {
- // Replace range if last range is the same as this one
- // So that ranges don't overlap and confuse the editor
- lastRange = newRange;
- } else {
- lastRange.mEndOffset = newRange.mStartOffset;
- textRanges.AppendElement(newRange);
- }
- }
-
- event.theText = mCompositionString;
- event.rangeArray = textRanges.Elements();
- event.rangeCount = textRanges.Length();
- mWindow->DispatchWindowEvent(&event);
- ::VariantClear(&propValue);
- return S_OK;
-}
-
-STDMETHODIMP
-nsTextStore::OnEndComposition(ITfCompositionView* pComposition)
-{
- NS_ENSURE_TRUE(mCompositionView &&
- mCompositionView == pComposition, E_UNEXPECTED);
- PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
- ("TSF: OnEndComposition\n"));
-
- // Use NS_TEXT_TEXT to commit composition string
- nsTextEvent textEvent(PR_TRUE, NS_TEXT_TEXT, mWindow);
- mWindow->InitEvent(textEvent);
- if (!mCompositionString.Length()) {
- // XXX HACK! HACK! NS_TEXT_TEXT handler specifically rejects
- // first-time empty strings as workaround for another IME bug
- // and our request will be rejected if this is the first time
- // we are sending NS_TEXT_TEXT. The workaround is to send it a
- // non-empty dummy string first.
- textEvent.theText = NS_LITERAL_STRING(" ");
- mWindow->DispatchWindowEvent(&textEvent);
- }
- textEvent.theText = mCompositionString;
- textEvent.theText.ReplaceSubstring(NS_LITERAL_STRING("\r\n"),
- NS_LITERAL_STRING("\n"));
- mWindow->DispatchWindowEvent(&textEvent);
-
- nsCompositionEvent event(PR_TRUE, NS_COMPOSITION_END, mWindow);
- mWindow->InitEvent(event);
- mWindow->DispatchWindowEvent(&event);
-
- mCompositionView = NULL;
- mCompositionString.Truncate(0);
- // Maintain selection
- SetSelectionInternal(&mCompositionSelection);
- return S_OK;
-}
-
-nsresult
-nsTextStore::OnFocusChange(PRBool aFocus,
- nsWindow* aWindow,
- PRUint32 aIMEEnabled)
-{
- // no change notifications if TSF is disabled
- if (!sTsfThreadMgr || !sTsfTextStore)
- return NS_ERROR_NOT_AVAILABLE;
-
- if (aFocus) {
- if (sTsfTextStore->Create(aWindow, aIMEEnabled))
- sTsfTextStore->Focus();
- } else {
- sTsfTextStore->Destroy();
- }
- return NS_OK;
-}
-
-nsresult
-nsTextStore::OnTextChangeInternal(PRUint32 aStart,
- PRUint32 aOldEnd,
- PRUint32 aNewEnd)
-{
- if (!mLock && mSink && 0 != (mSinkMask & TS_AS_TEXT_CHANGE)) {
- mTextChange.acpStart = PR_MIN(mTextChange.acpStart, LONG(aStart));
- mTextChange.acpOldEnd = PR_MAX(mTextChange.acpOldEnd, LONG(aOldEnd));
- mTextChange.acpNewEnd = PR_MAX(mTextChange.acpNewEnd, LONG(aNewEnd));
- ::PostMessageW(mWindow->GetWindowHandle(),
- WM_USER_TSF_TEXTCHANGE, 0, NULL);
- }
- return NS_OK;
-}
-
-void
-nsTextStore::OnTextChangeMsgInternal(void)
-{
- if (!mLock && mSink && 0 != (mSinkMask & TS_AS_TEXT_CHANGE) &&
- PR_INT32_MAX > mTextChange.acpStart) {
- mSink->OnTextChange(0, &mTextChange);
- mTextChange.acpStart = PR_INT32_MAX;
- mTextChange.acpOldEnd = mTextChange.acpNewEnd = 0;
- }
-}
-
-nsresult
-nsTextStore::OnSelectionChangeInternal(void)
-{
- if (!mLock && mSink && 0 != (mSinkMask & TS_AS_SEL_CHANGE)) {
- mSink->OnSelectionChange();
- }
- return NS_OK;
-}
-
-void
-nsTextStore::CommitCompositionInternal(PRBool aDiscard)
-{
- if (mCompositionView && aDiscard) {
- mCompositionString.Truncate(0);
- if (mSink && !mLock) {
- TS_TEXTCHANGE textChange;
- textChange.acpStart = mCompositionStart;
- textChange.acpOldEnd = mCompositionStart + mCompositionLength;
- textChange.acpNewEnd = mCompositionStart;
- mSink->OnTextChange(0, &textChange);
- }
- }
- // Terminate two contexts, the base context (mContext) and the top
- // if the top context is not the same as the base context
- nsRefPtr<ITfContext> context = mContext;
- do {
- if (context) {
- nsRefPtr<ITfContextOwnerCompositionServices> services;
- context->QueryInterface(IID_ITfContextOwnerCompositionServices,
- getter_AddRefs(services));
- if (services)
- services->TerminateComposition(NULL);
- }
- if (context != mContext)
- break;
- if (mDocumentMgr)
- mDocumentMgr->GetTop(getter_AddRefs(context));
- } while (context != mContext);
-}
-
-static
-PRBool
-GetCompartment(IUnknown* pUnk,
- const GUID& aID,
- ITfCompartment** aCompartment)
-{
- if (!pUnk) return PR_FALSE;
-
- nsRefPtr<ITfCompartmentMgr> compMgr;
- pUnk->QueryInterface(IID_ITfCompartmentMgr, getter_AddRefs(compMgr));
- if (!compMgr) return PR_FALSE;
-
- return SUCCEEDED(compMgr->GetCompartment(aID, aCompartment)) &&
- (*aCompartment) != NULL;
-}
-
-void
-nsTextStore::SetIMEOpenState(PRBool aState)
-{
- PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
- ("TSF: SetIMEOpenState, state=%lu\n", aState));
-
- nsRefPtr<ITfCompartment> comp;
- if (!GetCompartment(sTsfThreadMgr,
- GUID_COMPARTMENT_KEYBOARD_OPENCLOSE,
- getter_AddRefs(comp)))
- return;
-
- VARIANT variant;
- variant.vt = VT_I4;
- variant.lVal = aState;
- comp->SetValue(sTsfClientId, &variant);
-}
-
-PRBool
-nsTextStore::GetIMEOpenState(void)
-{
- nsRefPtr<ITfCompartment> comp;
- if (!GetCompartment(sTsfThreadMgr,
- GUID_COMPARTMENT_KEYBOARD_OPENCLOSE,
- getter_AddRefs(comp)))
- return PR_FALSE;
-
- VARIANT variant;
- ::VariantInit(&variant);
- if (SUCCEEDED(comp->GetValue(&variant)) && variant.vt == VT_I4)
- return variant.lVal != 0;
-
- ::VariantClear(&variant); // clear up in case variant.vt != VT_I4
- return PR_FALSE;
-}
-
-void
-nsTextStore::SetIMEEnabledInternal(PRUint32 aState)
-{
- PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
- ("TSF: SetIMEEnabled, state=%lu\n", aState));
-
- VARIANT variant;
- variant.vt = VT_I4;
- variant.lVal = aState != nsIWidget::IME_STATUS_ENABLED;
-
- // Set two contexts, the base context (mContext) and the top
- // if the top context is not the same as the base context
- nsRefPtr<ITfContext> context = mContext;
- nsRefPtr<ITfCompartment> comp;
- do {
- if (GetCompartment(context, GUID_COMPARTMENT_KEYBOARD_DISABLED,
- getter_AddRefs(comp)))
- comp->SetValue(sTsfClientId, &variant);
-
- if (context != mContext)
- break;
- if (mDocumentMgr)
- mDocumentMgr->GetTop(getter_AddRefs(context));
- } while (context != mContext);
-}
-
-HRESULT
-nsTextStore::LoadManagers(void)
-{
- HRESULT hr;
- if (!mDAMgr) {
- hr = ::CoCreateInstance(CLSID_TF_DisplayAttributeMgr, NULL,
- CLSCTX_INPROC_SERVER, IID_ITfDisplayAttributeMgr,
- getter_AddRefs(mDAMgr));
- NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
- }
- if (!mCatMgr) {
- hr = ::CoCreateInstance(CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER,
- IID_ITfCategoryMgr, getter_AddRefs(mCatMgr));
- NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
- }
- return S_OK;
-}
-
-void
-nsTextStore::Initialize(void)
-{
-#ifdef PR_LOGGING
- if (!sTextStoreLog)
- sTextStoreLog = PR_NewLogModule("nsTextStoreWidgets");
-#endif
- if (!sTsfThreadMgr) {
- PRBool enableTsf = PR_TRUE;
- nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
- if (prefs) {
- nsCOMPtr<nsIPrefBranch> prefBranch;
- prefs->GetBranch(nsnull, getter_AddRefs(prefBranch));
- if (prefBranch && NS_FAILED(prefBranch->GetBoolPref(
- "intl.enable_tsf_support", &enableTsf)))
- enableTsf = PR_TRUE;
- }
- if (enableTsf) {
- if (SUCCEEDED(CoCreateInstance(CLSID_TF_ThreadMgr, NULL,
- CLSCTX_INPROC_SERVER, IID_ITfThreadMgr,
- reinterpret_cast<void**>(&sTsfThreadMgr)))) {
- if (FAILED(sTsfThreadMgr->Activate(&sTsfClientId))) {
- NS_RELEASE(sTsfThreadMgr);
- NS_WARNING("failed to activate TSF\n");
- }
- } else
- // TSF not installed?
- NS_WARNING("failed to create TSF manager\n");
- }
- }
- if (sTsfThreadMgr && !sTsfTextStore) {
- sTsfTextStore = new nsTextStore();
- if (!sTsfTextStore)
- NS_ERROR("failed to create text store\n");
- }
- if (sTsfThreadMgr && !sFlushTIPInputMessage) {
- sFlushTIPInputMessage = ::RegisterWindowMessageW(
- NS_LITERAL_STRING("Flush TIP Input Message").get());
- }
-}
-
-void
-nsTextStore::Terminate(void)
-{
- NS_IF_RELEASE(sTsfTextStore);
- if (sTsfThreadMgr) {
- sTsfThreadMgr->Deactivate();
- NS_RELEASE(sTsfThreadMgr);
- }
-}
deleted file mode 100644
--- a/widget/src/windows/nsTextStore.h
+++ /dev/null
@@ -1,233 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Ningjie Chen <chenn@email.uc.edu>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef NSTEXTSTORE_H_
-#define NSTEXTSTORE_H_
-
-#include "nsAutoPtr.h"
-#include "nsString.h"
-
-#include <msctf.h>
-#include <textstor.h>
-
-struct ITfThreadMgr;
-struct ITfDocumentMgr;
-class nsWindow;
-
-// It doesn't work well when we notify TSF of text change
-// during a mutation observer call because things get broken.
-// So we post a message and notify TSF when we get it later.
-#define WM_USER_TSF_TEXTCHANGE (WM_USER + 0x100)
-
-/*
- * Text Services Framework text store
- */
-
-class nsTextStore : public ITextStoreACP,
- public ITfContextOwnerCompositionSink
-{
-public: /*IUnknown*/
- STDMETHODIMP_(ULONG) AddRef(void);
- STDMETHODIMP QueryInterface(REFIID, void**);
- STDMETHODIMP_(ULONG) Release(void);
-
-public: /*ITextStoreACP*/
- STDMETHODIMP AdviseSink(REFIID, IUnknown*, DWORD);
- STDMETHODIMP UnadviseSink(IUnknown*);
- STDMETHODIMP RequestLock(DWORD, HRESULT*);
- STDMETHODIMP GetStatus(TS_STATUS*);
- STDMETHODIMP QueryInsert(LONG, LONG, ULONG, LONG*, LONG*);
- STDMETHODIMP GetSelection(ULONG, ULONG, TS_SELECTION_ACP*, ULONG*);
- STDMETHODIMP SetSelection(ULONG, const TS_SELECTION_ACP*);
- STDMETHODIMP GetText(LONG, LONG, WCHAR*, ULONG, ULONG*, TS_RUNINFO*, ULONG,
- ULONG*, LONG*);
- STDMETHODIMP SetText(DWORD, LONG, LONG, const WCHAR*, ULONG, TS_TEXTCHANGE*);
- STDMETHODIMP GetFormattedText(LONG, LONG, IDataObject**);
- STDMETHODIMP GetEmbedded(LONG, REFGUID, REFIID, IUnknown**);
- STDMETHODIMP QueryInsertEmbedded(const GUID*, const FORMATETC*, BOOL*);
- STDMETHODIMP InsertEmbedded(DWORD, LONG, LONG, IDataObject*, TS_TEXTCHANGE*);
- STDMETHODIMP RequestSupportedAttrs(DWORD, ULONG, const TS_ATTRID*);
- STDMETHODIMP RequestAttrsAtPosition(LONG, ULONG, const TS_ATTRID*, DWORD);
- STDMETHODIMP RequestAttrsTransitioningAtPosition(LONG, ULONG,
- const TS_ATTRID*, DWORD);
- STDMETHODIMP FindNextAttrTransition(LONG, LONG, ULONG, const TS_ATTRID*,
- DWORD, LONG*, BOOL*, LONG*);
- STDMETHODIMP RetrieveRequestedAttrs(ULONG, TS_ATTRVAL*, ULONG*);
- STDMETHODIMP GetEndACP(LONG*);
- STDMETHODIMP GetActiveView(TsViewCookie*);
- STDMETHODIMP GetACPFromPoint(TsViewCookie, const POINT*, DWORD, LONG*);
- STDMETHODIMP GetTextExt(TsViewCookie, LONG, LONG, RECT*, BOOL*);
- STDMETHODIMP GetScreenExt(TsViewCookie, RECT*);
- STDMETHODIMP GetWnd(TsViewCookie, HWND*);
- STDMETHODIMP InsertTextAtSelection(DWORD, const WCHAR*, ULONG, LONG*, LONG*,
- TS_TEXTCHANGE*);
- STDMETHODIMP InsertEmbeddedAtSelection(DWORD, IDataObject*, LONG*, LONG*,
- TS_TEXTCHANGE*);
-
-public: /*ITfContextOwnerCompositionSink*/
- STDMETHODIMP OnStartComposition(ITfCompositionView*, BOOL*);
- STDMETHODIMP OnUpdateComposition(ITfCompositionView*, ITfRange*);
- STDMETHODIMP OnEndComposition(ITfCompositionView*);
-
-public:
- static void Initialize(void);
- static void Terminate(void);
- static void SetIMEOpenState(PRBool);
- static PRBool GetIMEOpenState(void);
-
- static void CommitComposition(PRBool aDiscard)
- {
- if (!sTsfTextStore) return;
- sTsfTextStore->CommitCompositionInternal(aDiscard);
- }
-
- static void SetIMEEnabled(PRUint32 aState)
- {
- if (!sTsfTextStore) return;
- sTsfTextStore->SetIMEEnabledInternal(aState);
- }
-
- static nsresult OnFocusChange(PRBool, nsWindow*, PRUint32);
-
- static nsresult OnTextChange(PRUint32 aStart,
- PRUint32 aOldEnd,
- PRUint32 aNewEnd)
- {
- if (!sTsfTextStore) return NS_OK;
- return sTsfTextStore->OnTextChangeInternal(aStart, aOldEnd, aNewEnd);
- }
-
- static void OnTextChangeMsg(void)
- {
- if (!sTsfTextStore) return;
- // Notify TSF text change
- // (see comments on WM_USER_TSF_TEXTCHANGE in nsTextStore.h)
- sTsfTextStore->OnTextChangeMsgInternal();
- }
-
- static nsresult OnSelectionChange(void)
- {
- if (!sTsfTextStore) return NS_OK;
- return sTsfTextStore->OnSelectionChangeInternal();
- }
-
- static void* GetNativeData(void)
- {
- // Returns the address of the pointer so that the TSF automatic test can
- // replace the system object with a custom implementation for testing.
- Initialize(); // Apply any previous changes
- return (void*) & sTsfThreadMgr;
- }
-
-protected:
- nsTextStore();
- ~nsTextStore();
-
- PRBool Create(nsWindow*, PRUint32);
- PRBool Destroy(void);
- PRBool Focus(void);
- PRBool Blur(void);
-
- HRESULT LoadManagers(void);
- HRESULT SetSelectionInternal(const TS_SELECTION_ACP*);
- HRESULT OnStartCompositionInternal(ITfCompositionView*, ITfRange*, PRBool);
- void CommitCompositionInternal(PRBool);
- void SetIMEEnabledInternal(PRUint32 aState);
- nsresult OnTextChangeInternal(PRUint32, PRUint32, PRUint32);
- void OnTextChangeMsgInternal(void);
- nsresult OnSelectionChangeInternal(void);
-
- // TSF display attribute manager, loaded by LoadManagers
- nsRefPtr<ITfDisplayAttributeMgr> mDAMgr;
- // TSF category manager, loaded by LoadManagers
- nsRefPtr<ITfCategoryMgr> mCatMgr;
-
- // Document manager for the currently focused editor
- nsRefPtr<ITfDocumentMgr> mDocumentMgr;
- // Edit cookie associated with the current editing context
- DWORD mEditCookie;
- // Editing context at the bottom of mDocumentMgr's context stack
- nsRefPtr<ITfContext> mContext;
- // Currently installed notification sink
- nsRefPtr<ITextStoreACPSink> mSink;
- // TS_AS_* mask of what events to notify
- DWORD mSinkMask;
- // Window containing the focused editor
- nsWindow* mWindow;
- // 0 if not locked, otherwise TS_LF_* indicating the current lock
- DWORD mLock;
- // 0 if no lock is queued, otherwise TS_LF_* indicating the queue lock
- DWORD mLockQueued;
- // Cumulative text change offsets since the last notification
- TS_TEXTCHANGE mTextChange;
- // NULL if no composition is active, otherwise the current composition
- nsRefPtr<ITfCompositionView> mCompositionView;
- // Current copy of the active composition string. Only mCompositionString is
- // changed during a InsertTextAtSelection call if we have a composition.
- // mCompositionString acts as a buffer until OnUpdateComposition is called
- // and mCompositionString is flushed to editor through NS_TEXT_TEXT. This
- // way all changes are updated in batches to avoid inconsistencies/artifacts.
- nsString mCompositionString;
- // "Current selection" during a composition, in ACP offsets.
- // We use a fake selection during a composition because editor code doesn't
- // like us accessing the actual selection during a composition. So we leave
- // the actual selection alone and get/set mCompositionSelection instead
- // during GetSelection/SetSelection calls.
- TS_SELECTION_ACP mCompositionSelection;
- // The start and length of the current active composition, in ACP offsets
- LONG mCompositionStart;
- LONG mCompositionLength;
-
- // TSF thread manager object for the current application
- static ITfThreadMgr* sTsfThreadMgr;
- // TSF client ID for the current application
- static DWORD sTsfClientId;
- // Current text store. Currently only ONE nsTextStore instance is ever used,
- // although Create is called when an editor is focused and Destroy called
- // when the focused editor is blurred.
- static nsTextStore* sTsfTextStore;
-
- // Message the Tablet Input Panel uses to flush text during blurring.
- // See comments in Destroy
- static UINT sFlushTIPInputMessage;
-
-private:
- ULONG mRefCnt;
-};
-
-#endif /*NSTEXTSTORE_H_*/
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -29,17 +29,16 @@
* Pierre Phaneuf <pp@ludusdesign.com>
* Robert O'Callahan <roc+moz@cs.cmu.edu>
* Roy Yokoyama <yokoyama@netscape.com>
* Makoto Kato <m_kato@ga2.so-net.ne.jp>
* Masayuki Nakano <masayuki@d-toybox.com>
* Dainis Jonitis <Dainis_Jonitis@swh-t.lv>
* Christian Biesinger <cbiesinger@web.de>
* Mats Palmgren <mats.palmgren@bredband.net>
- * Ningjie Chen <chenn@email.uc.edu>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
@@ -146,19 +145,16 @@
#include "nsAppDirectoryServiceDefs.h"
#include "nsXPIDLString.h"
#include "nsIFile.h"
#include "prprf.h"
#include "prmem.h"
-#ifdef NS_ENABLE_TSF
-#include "nsTextStore.h"
-#endif //NS_ENABLE_TSF
#ifdef WINCE
static PRBool gSoftKeyMenuBar = PR_FALSE;
static void CreateSoftKeyMenuBar(HWND wnd)
{
if (!wnd)
@@ -745,29 +741,24 @@ nsWindow::nsWindow() : nsBaseWidget()
// Heap dump
nsWindow::uWM_HEAP_DUMP = ::RegisterWindowMessageW(kMozHeapDumpMessageString);
}
mNativeDragTarget = nsnull;
mIsTopWidgetWindow = PR_FALSE;
mLastKeyboardLayout = 0;
-#ifdef NS_ENABLE_TSF
- if (!sInstanceCount)
- nsTextStore::Initialize();
-#endif //NS_ENABLE_TSF
-
#ifndef WINCE
if (!sInstanceCount && SUCCEEDED(::OleInitialize(NULL))) {
sIsOleInitialized = TRUE;
}
NS_ASSERTION(sIsOleInitialized, "***** OLE is not initialized!\n");
-#endif
sInstanceCount++;
+#endif
}
//-------------------------------------------------------------------------
//
// nsWindow destructor
//
//-------------------------------------------------------------------------
nsWindow::~nsWindow()
@@ -792,27 +783,21 @@ nsWindow::~nsWindow()
Destroy();
}
if (mCursor == -1) {
// A successfull SetCursor call will destroy the custom cursor, if it's ours
SetCursor(eCursor_standard);
}
- sInstanceCount--;
-
-#ifdef NS_ENABLE_TSF
- if (!sInstanceCount)
- nsTextStore::Terminate();
-#endif //NS_ENABLE_TSF
-
#ifndef WINCE
//
// delete any of the IME structures that we allocated
//
+ sInstanceCount--;
if (sInstanceCount == 0) {
if (sIMECompUnicode)
delete sIMECompUnicode;
if (sIMEAttributeArray)
delete [] sIMEAttributeArray;
if (sIMECompClauseArray)
delete [] sIMECompClauseArray;
@@ -2836,22 +2821,16 @@ void* nsWindow::GetNativeData(PRUint32 a
case NS_NATIVE_GRAPHIC:
// XXX: This is sleezy!! Remember to Release the DC after using it!
#ifdef MOZ_XUL
return (void*)(eTransparencyTransparent == mTransparencyMode) ?
mMemoryDC : ::GetDC(mWnd);
#else
return (void*)::GetDC(mWnd);
#endif
-
-#ifdef NS_ENABLE_TSF
- case NS_NATIVE_TSF_POINTER:
- return nsTextStore::GetNativeData();
-#endif //NS_ENABLE_TSF
-
case NS_NATIVE_COLORMAP:
default:
break;
}
return NULL;
}
@@ -5319,22 +5298,16 @@ PRBool nsWindow::ProcessMessage(UINT msg
else if (msg == nsWindow::uWM_HEAP_DUMP) {
// XXX for now we use c:\heapdump.txt until we figure out how to
// XXX pass in message parameters.
HeapDump("c:\\heapdump.txt", "whatever");
result = PR_TRUE;
}
#endif // WINCE
-#ifdef NS_ENABLE_TSF
- else if (msg == WM_USER_TSF_TEXTCHANGE) {
- nsTextStore::OnTextChangeMsg();
- }
-#endif //NS_ENABLE_TSF
-
}
break;
#ifndef WINCE
case WM_DWMCOMPOSITIONCHANGED:
BroadcastMsg(mWnd, WM_DWMCOMPOSITIONCHANGED);
DispatchStandardEvent(NS_THEMECHANGED);
if (nsUXThemeData::CheckForCompositor() && mTransparencyMode == eTransparencyGlass) {
MARGINS margins = { -1, -1, -1, -1 };
@@ -7449,18 +7422,18 @@ PRBool nsWindow::OnIMEQueryCharPosition(
if (!selection.mSucceeded)
return PR_FALSE;
PRUint32 offset = selection.mReply.mOffset + pCharPosition->dwCharPos;
PRBool useCaretRect = selection.mReply.mString.IsEmpty();
nsIntRect r;
if (!useCaretRect) {
- nsQueryContentEvent charRect(PR_TRUE, NS_QUERY_TEXT_RECT, this);
- charRect.InitForQueryTextRect(offset, 1);
+ nsQueryContentEvent charRect(PR_TRUE, NS_QUERY_CHARACTER_RECT, this);
+ charRect.InitForQueryCharacterRect(offset);
InitEvent(charRect, &point);
DispatchWindowEvent(&charRect);
if (charRect.mSucceeded)
r = charRect.mReply.mRect;
else
useCaretRect = PR_TRUE;
}
@@ -7558,21 +7531,16 @@ BOOL nsWindow::OnIMEStartComposition()
}
//==========================================================================
NS_IMETHODIMP nsWindow::ResetInputState()
{
#ifdef DEBUG_KBSTATE
printf("ResetInputState\n");
#endif
-
-#ifdef NS_ENABLE_TSF
- nsTextStore::CommitComposition(PR_FALSE);
-#endif //NS_ENABLE_TSF
-
HIMC hIMC = ::ImmGetContext(mWnd);
if (hIMC) {
BOOL ret = FALSE;
ret = ::ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, NULL);
ret = ::ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, NULL);
//NS_ASSERTION(ret, "ImmNotify failed");
::ImmReleaseContext(mWnd, hIMC);
}
@@ -7580,21 +7548,16 @@ NS_IMETHODIMP nsWindow::ResetInputState(
}
//==========================================================================
NS_IMETHODIMP nsWindow::SetIMEOpenState(PRBool aState)
{
#ifdef DEBUG_KBSTATE
printf("SetIMEOpenState %s\n", (aState ? "Open" : "Close"));
#endif
-
-#ifdef NS_ENABLE_TSF
- nsTextStore::SetIMEOpenState(aState);
-#endif //NS_ENABLE_TSF
-
HIMC hIMC = ::ImmGetContext(mWnd);
if (hIMC) {
::ImmSetOpenStatus(hIMC, aState ? TRUE : FALSE);
::ImmReleaseContext(mWnd, hIMC);
}
return NS_OK;
}
@@ -7603,31 +7566,22 @@ NS_IMETHODIMP nsWindow::GetIMEOpenState(
{
HIMC hIMC = ::ImmGetContext(mWnd);
if (hIMC) {
BOOL isOpen = ::ImmGetOpenStatus(hIMC);
*aState = isOpen ? PR_TRUE : PR_FALSE;
::ImmReleaseContext(mWnd, hIMC);
} else
*aState = PR_FALSE;
-
-#ifdef NS_ENABLE_TSF
- *aState |= nsTextStore::GetIMEOpenState();
-#endif //NS_ENABLE_TSF
-
return NS_OK;
}
//==========================================================================
NS_IMETHODIMP nsWindow::SetIMEEnabled(PRUint32 aState)
{
-#ifdef NS_ENABLE_TSF
- nsTextStore::SetIMEEnabled(aState);
-#endif //NS_ENABLE_TSF
-
if (sIMEIsComposing)
ResetInputState();
mIMEEnabled = aState;
PRBool enable = (aState == nsIWidget::IME_STATUS_ENABLED ||
aState == nsIWidget::IME_STATUS_PLUGIN);
if (!enable != !mOldIMC)
return NS_OK;
mOldIMC = ::ImmAssociateContext(mWnd, enable ? mOldIMC : NULL);
@@ -7644,21 +7598,16 @@ NS_IMETHODIMP nsWindow::GetIMEEnabled(PR
}
//==========================================================================
NS_IMETHODIMP nsWindow::CancelIMEComposition()
{
#ifdef DEBUG_KBSTATE
printf("CancelIMEComposition\n");
#endif
-
-#ifdef NS_ENABLE_TSF
- nsTextStore::CommitComposition(PR_TRUE);
-#endif //NS_ENABLE_TSF
-
HIMC hIMC = ::ImmGetContext(mWnd);
if (hIMC) {
BOOL ret = FALSE;
ret = ::ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, NULL);
::ImmReleaseContext(mWnd, hIMC);
}
return NS_OK;
}
@@ -7854,40 +7803,16 @@ static VOID CALLBACK nsGetAttentionTimer
}
gAttentionTimerMonitor->SetFlashed(hwnd);
}
else
gAttentionTimerMonitor->KillTimer(hwnd);
}
-
-#ifdef NS_ENABLE_TSF
-NS_IMETHODIMP
-nsWindow::OnIMEFocusChange(PRBool aFocus)
-{
- return nsTextStore::OnFocusChange(aFocus, this, mIMEEnabled);
-}
-
-NS_IMETHODIMP
-nsWindow::OnIMETextChange(PRUint32 aStart,
- PRUint32 aOldEnd,
- PRUint32 aNewEnd)
-{
- return nsTextStore::OnTextChange(aStart, aOldEnd, aNewEnd);
-}
-
-NS_IMETHODIMP
-nsWindow::OnIMESelectionChange(void)
-{
- return nsTextStore::OnSelectionChange();
-}
-#endif //NS_ENABLE_TSF
-
-
// Draw user's attention to this window until it comes to foreground.
NS_IMETHODIMP
nsWindow::GetAttention(PRInt32 aCycleCount)
{
// Got window?
if (!mWnd)
return NS_ERROR_NOT_INITIALIZED;
--- a/widget/src/windows/nsWindow.h
+++ b/widget/src/windows/nsWindow.h
@@ -20,17 +20,16 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert O'Callahan <roc+moz@cs.cmu.edu>
* Dean Tessman <dean_tessman@hotmail.com>
* Makoto Kato <m_kato@ga2.so-net.ne.jp>
* Dainis Jonitis <Dainis_Jonitis@swh-t.lv>
* Masayuki Nakano <masayuki@d-toybox.com>
- * Ningjie Chen <chenn@email.uc.edu>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
@@ -69,21 +68,16 @@ struct nsFakeCharMessage;
#ifdef ACCESSIBILITY
#include "OLEACC.H"
#include "nsIAccessible.h"
#endif
#include "gfxWindowsSurface.h"
-// Text Services Framework support
-#ifndef WINCE
-#define NS_ENABLE_TSF
-#endif //WINCE
-
#define IME_MAX_CHAR_POS 64
#define NSRGB_2_COLOREF(color) \
RGB(NS_GET_R(color),NS_GET_G(color),NS_GET_B(color))
#define COLOREF_2_NSRGB(color) \
NS_RGB(GetRValue(color), GetGValue(color), GetBValue(color))
#define WIN2K_VERSION 0x500
@@ -236,39 +230,31 @@ public:
NS_IMETHOD ResetInputState();
NS_IMETHOD SetIMEOpenState(PRBool aState);
NS_IMETHOD GetIMEOpenState(PRBool* aState);
NS_IMETHOD SetIMEEnabled(PRUint32 aState);
NS_IMETHOD GetIMEEnabled(PRUint32* aState);
NS_IMETHOD CancelIMEComposition();
NS_IMETHOD GetToggledKeyState(PRUint32 aKeyCode, PRBool* aLEDState);
-#ifdef NS_ENABLE_TSF
- NS_IMETHOD OnIMEFocusChange(PRBool aFocus);
- NS_IMETHOD OnIMETextChange(PRUint32 aStart, PRUint32 aOldEnd, PRUint32 aNewEnd);
- NS_IMETHOD OnIMESelectionChange(void);
-#endif //NS_ENABLE_TSF
-
PRBool IMEMouseHandling(PRInt32 aAction, LPARAM lParam);
PRBool IMECompositionHitTest(POINT * ptPos);
PRBool HandleMouseActionOfIME(PRInt32 aAction, POINT* ptPos);
void GetCompositionWindowPos(HIMC hIMC, PRUint32 aEventType, COMPOSITIONFORM *cpForm);
// nsSwitchToUIThread interface
virtual BOOL CallMethod(MethodInfo *info);
HWND GetWindowHandle() { return mWnd; }
WNDPROC GetPrevWindowProc() { return mPrevWndProc; }
virtual PRBool DispatchMouseEvent(PRUint32 aEventType, WPARAM wParam,
LPARAM lParam,
PRBool aIsContextMenuKey = PR_FALSE,
PRInt16 aButton = nsMouseEvent::eLeftButton);
- virtual PRBool DispatchWindowEvent(nsGUIEvent* event);
- virtual PRBool DispatchWindowEvent(nsGUIEvent*event, nsEventStatus &aStatus);
#ifdef ACCESSIBILITY
virtual PRBool DispatchAccessibleEvent(PRUint32 aEventType, nsIAccessible** aAccessible, nsIntPoint* aPoint = nsnull);
already_AddRefed<nsIAccessible> GetRootAccessible();
#endif
virtual PRBool AutoErase();
nsIntPoint* GetLastPoint() { return &mLastPoint; }
PRInt32 GetNewCmdMenuId() { mMenuCmdId++; return mMenuCmdId; }
@@ -312,16 +298,18 @@ protected:
LRESULT ProcessCharMessage(const MSG &aMsg,
PRBool *aEventDispatched);
LRESULT ProcessKeyUpMessage(const MSG &aMsg,
PRBool *aEventDispatched);
LRESULT ProcessKeyDownMessage(const MSG &aMsg,
PRBool *aEventDispatched);
+ virtual PRBool DispatchWindowEvent(nsGUIEvent* event);
+ virtual PRBool DispatchWindowEvent(nsGUIEvent*event, nsEventStatus &aStatus);
// Allow Derived classes to modify the height that is passed
// when the window is created or resized.
virtual PRInt32 GetHeight(PRInt32 aProposedHeight);
virtual LPCWSTR WindowClass();
virtual LPCWSTR WindowPopupClass();
virtual DWORD WindowStyle();
virtual DWORD WindowExStyle();
--- a/widget/src/xpwidgets/nsBaseWidget.h
+++ b/widget/src/xpwidgets/nsBaseWidget.h
@@ -134,26 +134,23 @@ public:
NS_IMETHOD EndSecureKeyboardInput();
NS_IMETHOD SetWindowTitlebarColor(nscolor aColor, PRBool aActive);
virtual PRBool ShowsResizeIndicator(nsIntRect* aResizerRect);
virtual void ConvertToDeviceCoordinates(nscoord &aX,nscoord &aY) {}
virtual void FreeNativeData(void * data, PRUint32 aDataType) {}
NS_IMETHOD BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical);
virtual nsresult ActivateNativeMenuItemAt(const nsAString& indexString) { return NS_ERROR_NOT_IMPLEMENTED; }
virtual nsresult ForceUpdateNativeMenuAt(const nsAString& indexString) { return NS_ERROR_NOT_IMPLEMENTED; }
- NS_IMETHOD ResetInputState() { return NS_OK; }
+ NS_IMETHOD ResetInputState() { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD SetIMEOpenState(PRBool aState) { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD GetIMEOpenState(PRBool* aState) { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD SetIMEEnabled(PRUint32 aState) { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD GetIMEEnabled(PRUint32* aState) { return NS_ERROR_NOT_IMPLEMENTED; }
- NS_IMETHOD CancelIMEComposition() { return NS_OK; }
+ NS_IMETHOD CancelIMEComposition() { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD GetToggledKeyState(PRUint32 aKeyCode, PRBool* aLEDState) { return NS_ERROR_NOT_IMPLEMENTED; }
- NS_IMETHOD OnIMEFocusChange(PRBool aFocus) { return NS_ERROR_NOT_IMPLEMENTED; }
- NS_IMETHOD OnIMETextChange(PRUint32 aStart, PRUint32 aOldEnd, PRUint32 aNewEnd) { return NS_ERROR_NOT_IMPLEMENTED; }
- NS_IMETHOD OnIMESelectionChange(void) { return NS_ERROR_NOT_IMPLEMENTED; }
protected:
virtual void ResolveIconName(const nsAString &aIconName,
const nsAString &aIconSuffix,
nsILocalFile **aResult);
virtual void OnDestroy();
virtual void BaseCreate(nsIWidget *aParent,
--- a/widget/tests/Makefile.in
+++ b/widget/tests/Makefile.in
@@ -34,32 +34,19 @@
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
-relativesrcdir = widget/tests
+relativesrcdir = widget/test
include $(DEPTH)/config/autoconf.mk
-
-ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
-ifneq ($(OS_ARCH), WINCE)
-CPP_UNIT_TESTS += TestWinTSF.cpp \
- $(NULL)
-REQUIRES += appshell content docshell \
- dom embed_base gfx layout locale \
- necko string thebes uriloader view \
- webbrwsr widget xpcom \
- $(NULL)
-endif
-endif
-
include $(topsrcdir)/config/rules.mk
_TEST_FILES = test_bug343416.xul \
test_bug444800.xul \
test_bug462106.xul \
test_keycodes.xul \
test_wheeltransaction.xul \
window_wheeltransaction.xul \
deleted file mode 100644
--- a/widget/tests/TestWinTSF.cpp
+++ /dev/null
@@ -1,1830 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Ningjie Chen <chenn@email.uc.edu>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-
-/* This tests Mozilla's Text Services Framework implementation (bug #88831)
- *
- * The Mozilla implementation interacts with the TSF system through a
- * system-provided COM interface, ITfThreadMgr. This tests works by swapping
- * the system version of the interface with a custom version implemented in
- * here. This way the Mozilla implementation thinks it's interacting with the
- * system but in fact is interacting with this test program. This allows the
- * test program to access and test every aspect of the Mozilla implementation.
- */
-
-#include <msctf.h>
-#include <textstor.h>
-
-#include "TestHarness.h"
-
-#define WM_USER_TSF_TEXTCHANGE (WM_USER + 0x100)
-
-#ifndef MOZILLA_INTERNAL_API
-// some of the includes make use of internal string types
-#define nsAString_h___
-#define nsString_h___
-class nsAFlatString;
-class nsAFlatCString;
-#endif
-
-#include "nsWeakReference.h"
-#include "nsIAppShell.h"
-#include "nsWidgetsCID.h"
-#include "nsIAppShellService.h"
-#include "nsAppShellCID.h"
-#include "nsNetUtil.h"
-#include "nsIWebBrowserChrome.h"
-#include "nsIXULWindow.h"
-#include "nsIBaseWindow.h"
-#include "nsIDOMWindowInternal.h"
-#include "nsIDocShell.h"
-#include "nsIWidget.h"
-#include "nsIPresShell.h"
-#include "nsPresContext.h"
-#include "nsIFrame.h"
-#include "nsIWebProgress.h"
-#include "nsIWebProgressListener.h"
-#include "nsIInterfaceRequestorUtils.h"
-#include "nsIDOMHTMLDocument.h"
-#include "nsIDOMHTMLBodyElement.h"
-#include "nsIDOMHTMLElement.h"
-#include "nsIDOMHTMLInputElement.h"
-#include "nsIDOMHTMLTextAreaElement.h"
-#include "nsISelectionController.h"
-#include "nsIViewManager.h"
-
-#ifndef MOZILLA_INTERNAL_API
-#undef nsString_h___
-#undef nsAString_h___
-#endif
-
-static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
-
-class TSFImpl;
-
-class TestApp : public nsIWebProgressListener, public nsSupportsWeakReference
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIWEBPROGRESSLISTENER
-
- TestApp() : mFailed(PR_FALSE) {}
- ~TestApp() {}
-
- nsresult Run(void);
- PRBool CheckFailed(void);
-
- typedef PRBool (TestApp::*test_type)(void);
-
-protected:
- nsresult Init(void);
- nsresult Term(void);
- PRBool RunTest(test_type aTest, PRBool aLock = PR_TRUE);
-
- PRBool TestFocus(void);
- PRBool TestClustering(void);
- PRBool TestSelection(void);
- PRBool TestText(void);
- PRBool TestExtents(void);
- PRBool TestComposition(void);
- PRBool TestNotification(void);
-
- PRBool TestApp::TestSelectionInternal(char* aTestName,
- LONG aStart,
- LONG aEnd,
- TsActiveSelEnd aSelEnd);
- PRBool TestCompositionSelectionAndText(char* aTestName,
- LONG aExpectedSelStart,
- LONG aExpectedSelEnd,
- nsString& aReferenceString);
- PRBool TestNotificationTextChange(nsIWidget* aWidget,
- PRUint32 aCode,
- const nsAString& aCharacter,
- LONG aStart,
- LONG aOldEnd,
- LONG aNewEnd);
- nsresult GetSelCon(nsISelectionController** aSelCon);
-
- PRBool mFailed;
- nsString mTestString;
- nsRefPtr<TSFImpl> mImpl;
- nsCOMPtr<nsIAppShell> mAppShell;
- nsCOMPtr<nsIXULWindow> mWindow;
- nsCOMPtr<nsIDOMNode> mCurrentNode;
- nsCOMPtr<nsIDOMHTMLInputElement> mInput;
- nsCOMPtr<nsIDOMHTMLTextAreaElement> mTextArea;
- nsCOMPtr<nsIDOMHTMLInputElement> mButton;
-};
-
-NS_IMETHODIMP
-TestApp::OnProgressChange(nsIWebProgress *aWebProgress,
- nsIRequest *aRequest,
- PRInt32 aCurSelfProgress,
- PRInt32 aMaxSelfProgress,
- PRInt32 aCurTotalProgress,
- PRInt32 aMaxTotalProgress)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-TestApp::OnLocationChange(nsIWebProgress *aWebProgress,
- nsIRequest *aRequest,
- nsIURI *aLocation)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-TestApp::OnStatusChange(nsIWebProgress *aWebProgress,
- nsIRequest *aRequest,
- nsresult aStatus,
- const PRUnichar *aMessage)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-TestApp::OnSecurityChange(nsIWebProgress *aWebProgress,
- nsIRequest *aRequest,
- PRUint32 aState)
-{
- return NS_OK;
-}
-
-// Simple TSF manager implementation for testing
-// Most methods are not implemented, but the ones used by Mozilla are
-//
-// XXX Implement appropriate methods here as the Mozilla TSF code changes
-//
-class TSFImpl : public ITfThreadMgr, public ITfDocumentMgr, public ITfContext,
- public ITfRangeACP, public ITfCompositionView,
- public ITextStoreACPSink
-{
-private:
- ULONG mRefCnt;
- nsRefPtr<TestApp> mTestApp;
-
-public:
- TestApp::test_type mTest;
- TestApp::test_type mOnFocus;
- TestApp::test_type mOnBlur;
- nsRefPtr<ITextStoreACP> mStore;
- PRBool mFocused;
- PRBool mContextPushed;
- PRBool mDeactivated;
- PRUint32 mFocusCount;
- PRUint32 mBlurCount;
- PRUint32 mRangeStart;
- PRUint32 mRangeLength;
- PRBool mTextChanged;
- PRBool mSelChanged;
- TS_TEXTCHANGE mTextChangeData;
-
-public:
- TSFImpl(TestApp* test) : mTestApp(test), mTest(nsnull),
- mRefCnt(0), mFocused(PR_FALSE), mDeactivated(PR_FALSE),
- mFocusCount(0), mBlurCount(0), mRangeStart(0), mRangeLength(0),
- mContextPushed(PR_FALSE), mOnFocus(nsnull), mOnBlur(nsnull),
- mTextChanged(PR_FALSE), mSelChanged(PR_FALSE)
- {
- }
-
- ~TSFImpl()
- {
- }
-
-public: // IUnknown
-
- STDMETHODIMP QueryInterface(REFIID riid, void** ppUnk)
- {
- *ppUnk = NULL;
- if (IID_IUnknown == riid || IID_ITfThreadMgr == riid)
- *ppUnk = static_cast<ITfThreadMgr*>(this);
- else if (IID_ITfDocumentMgr == riid)
- *ppUnk = static_cast<ITfDocumentMgr*>(this);
- else if (IID_ITfContext == riid)
- *ppUnk = static_cast<ITfContext*>(this);
- else if (IID_ITfRange == riid || IID_ITfRangeACP == riid)
- *ppUnk = static_cast<ITfRangeACP*>(this);
- else if (IID_ITextStoreACPSink == riid)
- *ppUnk = static_cast<ITextStoreACPSink*>(this);
- if (*ppUnk)
- AddRef();
- return *ppUnk ? S_OK : E_NOINTERFACE;
- }
-
- STDMETHODIMP_(ULONG) AddRef(void)
- {
- return ++mRefCnt;
- }
-
- STDMETHODIMP_(ULONG) Release(void)
- {
- if (--mRefCnt) return mRefCnt;
- delete this;
- return 0;
- }
-
-public: // ITfThreadMgr
-
- STDMETHODIMP Activate(TfClientId *ptid)
- {
- *ptid = 1;
- return S_OK;
- }
-
- STDMETHODIMP Deactivate(void)
- {
- SetFocus(NULL);
- mDeactivated = PR_TRUE;
- return S_OK;
- }
-
- STDMETHODIMP CreateDocumentMgr(ITfDocumentMgr **ppdim)
- {
- (*ppdim) = this;
- (*ppdim)->AddRef();
- return S_OK;
- }
-
- STDMETHODIMP EnumDocumentMgrs(IEnumTfDocumentMgrs **ppEnum)
- {
- NS_NOTREACHED("ITfThreadMgr::EnumDocumentMgrs");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP GetFocus(ITfDocumentMgr **ppdimFocus)
- {
- (*ppdimFocus) = mFocused ? this : NULL;
- if (*ppdimFocus) (*ppdimFocus)->AddRef();
- return S_OK;
- }
-
- STDMETHODIMP SetFocus(ITfDocumentMgr *pdimFocus)
- {
- mFocused = pdimFocus != NULL;
- if (mFocused) {
- ++mFocusCount;
- if (mOnFocus) (mTestApp->*mOnFocus)();
- } else {
- ++mBlurCount;
- if (mOnBlur) (mTestApp->*mOnBlur)();
- }
- return S_OK;
- }
-
- STDMETHODIMP AssociateFocus(HWND hwnd, ITfDocumentMgr *pdimNew,
- ITfDocumentMgr **ppdimPrev)
- {
- NS_NOTREACHED("ITfThreadMgr::AssociateFocus");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP IsThreadFocus(BOOL *pfThreadFocus)
- {
- *pfThreadFocus = TRUE;
- return S_OK;
- }
-
- STDMETHODIMP GetFunctionProvider(REFCLSID clsid,
- ITfFunctionProvider **ppFuncProv)
- {
- NS_NOTREACHED("ITfThreadMgr::GetFunctionProvider");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP EnumFunctionProviders(IEnumTfFunctionProviders **ppEnum)
- {
- NS_NOTREACHED("ITfThreadMgr::EnumFunctionProviders");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP GetGlobalCompartment(ITfCompartmentMgr **ppCompMgr)
- {
- NS_NOTREACHED("ITfThreadMgr::GetGlobalCompartment");
- return E_NOTIMPL;
- }
-
-public: // ITfDocumentMgr
-
- STDMETHODIMP CreateContext(TfClientId tidOwner, DWORD dwFlags,
- IUnknown *punk, ITfContext **ppic,
- TfEditCookie *pecTextStore)
- {
- punk->QueryInterface(IID_ITextStoreACP, getter_AddRefs(mStore));
- NS_ENSURE_TRUE(mStore, E_FAIL);
- HRESULT hr = mStore->AdviseSink(IID_ITextStoreACPSink,
- static_cast<ITextStoreACPSink*>(this),
- TS_AS_ALL_SINKS);
- if (FAILED(hr)) mStore = NULL;
- NS_ENSURE_TRUE(SUCCEEDED(hr), E_FAIL);
- (*ppic) = this;
- (*ppic)->AddRef();
- *pecTextStore = 1;
- return S_OK;
- }
-
- STDMETHODIMP Push(ITfContext *pic)
- {
- mContextPushed = PR_TRUE;
- return S_OK;
- }
-
- STDMETHODIMP Pop(DWORD dwFlags)
- {
- if (!mStore || dwFlags != TF_POPF_ALL) return E_FAIL;
- mStore->UnadviseSink(static_cast<ITextStoreACPSink*>(this));
- mStore = NULL;
- mContextPushed = PR_FALSE;
- return S_OK;
- }
-
- STDMETHODIMP GetTop(ITfContext **ppic)
- {
- (*ppic) = mContextPushed ? this : NULL;
- if (*ppic) (*ppic)->AddRef();
- return S_OK;
- }
-
- STDMETHODIMP GetBase(ITfContext **ppic)
- {
- (*ppic) = mContextPushed ? this : NULL;
- if (*ppic) (*ppic)->AddRef();
- return S_OK;
- }
-
- STDMETHODIMP EnumContexts(IEnumTfContexts **ppEnum)
- {
- NS_NOTREACHED("ITfDocumentMgr::EnumContexts");
- return E_NOTIMPL;
- }
-
-public: // ITfContext
-
- STDMETHODIMP RequestEditSession(TfClientId tid, ITfEditSession *pes,
- DWORD dwFlags, HRESULT *phrSession)
- {
- NS_NOTREACHED("ITfContext::RequestEditSession");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP InWriteSession(TfClientId tid, BOOL *pfWriteSession)
- {
- NS_NOTREACHED("ITfContext::InWriteSession");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP GetSelection(TfEditCookie ec, ULONG ulIndex, ULONG ulCount,
- TF_SELECTION *pSelection, ULONG *pcFetched)
- {
- NS_NOTREACHED("ITfContext::GetSelection");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP SetSelection(TfEditCookie ec, ULONG ulCount,
- const TF_SELECTION *pSelection)
- {
- NS_NOTREACHED("ITfContext::SetSelection");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP GetStart(TfEditCookie ec, ITfRange **ppStart)
- {
- NS_NOTREACHED("ITfContext::GetStart");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP GetEnd(TfEditCookie ec, ITfRange **ppEnd)
- {
- NS_NOTREACHED("ITfContext::GetEnd");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP GetActiveView(ITfContextView **ppView)
- {
- NS_NOTREACHED("ITfContext::GetActiveView");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP EnumViews(IEnumTfContextViews **ppEnum)
- {
- NS_NOTREACHED("ITfContext::EnumViews");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP GetStatus(TF_STATUS *pdcs)
- {
- NS_NOTREACHED("ITfContext::GetStatus");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP GetProperty(REFGUID guidProp, ITfProperty **ppProp)
- {
- NS_NOTREACHED("ITfContext::GetProperty");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP GetAppProperty(REFGUID guidProp, ITfReadOnlyProperty **ppProp)
- {
- NS_NOTREACHED("ITfContext::GetAppProperty");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP TrackProperties(const GUID **prgProp, ULONG cProp,
- const GUID **prgAppProp, ULONG cAppProp,
- ITfReadOnlyProperty **ppProperty)
- {
- NS_NOTREACHED("ITfContext::TrackProperties");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP EnumProperties(IEnumTfProperties **ppEnum)
- {
- NS_NOTREACHED("ITfContext::EnumProperties");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP GetDocumentMgr(ITfDocumentMgr **ppDm)
- {
- NS_NOTREACHED("ITfContext::GetDocumentMgr");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP CreateRangeBackup(TfEditCookie ec, ITfRange *pRange,
- ITfRangeBackup **ppBackup)
- {
- NS_NOTREACHED("ITfContext::CreateRangeBackup");
- return E_NOTIMPL;
- }
-
-public: // ITfRangeACP
-
- STDMETHODIMP GetText(TfEditCookie ec, DWORD dwFlags, WCHAR *pchText,
- ULONG cchMax, ULONG *pcch)
- {
- NS_NOTREACHED("ITfRangeACP::GetText");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP SetText(TfEditCookie ec, DWORD dwFlags, const WCHAR *pchText,
- LONG cch)
- {
- NS_NOTREACHED("ITfRangeACP::SetText");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP GetFormattedText(TfEditCookie ec, IDataObject **ppDataObject)
- {
- NS_NOTREACHED("ITfRangeACP::GetFormattedText");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP GetEmbedded(TfEditCookie ec, REFGUID rguidService, REFIID riid,
- IUnknown **ppunk)
- {
- NS_NOTREACHED("ITfRangeACP::GetEmbedded");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP InsertEmbedded(TfEditCookie ec, DWORD dwFlags,
- IDataObject *pDataObject)
- {
- NS_NOTREACHED("ITfRangeACP::InsertEmbedded");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP ShiftStart(TfEditCookie ec, LONG cchReq, LONG *pcch,
- const TF_HALTCOND *pHalt)
- {
- NS_NOTREACHED("ITfRangeACP::ShiftStart");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP ShiftEnd(TfEditCookie ec, LONG cchReq, LONG *pcch,
- const TF_HALTCOND *pHalt)
- {
- NS_NOTREACHED("ITfRangeACP::ShiftEnd");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP ShiftStartToRange(TfEditCookie ec, ITfRange *pRange,
- TfAnchor aPos)
- {
- NS_NOTREACHED("ITfRangeACP::ShiftStartToRange");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP ShiftEndToRange(TfEditCookie ec, ITfRange *pRange,
- TfAnchor aPos)
- {
- NS_NOTREACHED("ITfRangeACP::ShiftEndToRange");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP ShiftStartRegion(TfEditCookie ec, TfShiftDir dir,
- BOOL *pfNoRegion)
- {
- NS_NOTREACHED("ITfRangeACP::ShiftStartRegion");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP ShiftEndRegion(TfEditCookie ec, TfShiftDir dir,
- BOOL *pfNoRegion)
- {
- NS_NOTREACHED("ITfRangeACP::ShiftEndRegion");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP IsEmpty(TfEditCookie ec, BOOL *pfEmpty)
- {
- NS_NOTREACHED("ITfRangeACP::IsEmpty");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP Collapse(TfEditCookie ec, TfAnchor aPos)
- {
- NS_NOTREACHED("ITfRangeACP::Collapse");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP IsEqualStart(TfEditCookie ec, ITfRange *pWith,
- TfAnchor aPos, BOOL *pfEqual)
- {
- NS_NOTREACHED("ITfRangeACP::IsEqualStart");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP IsEqualEnd(TfEditCookie ec, ITfRange *pWith,
- TfAnchor aPos, BOOL *pfEqual)
- {
- NS_NOTREACHED("ITfRangeACP::IsEqualEnd");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP CompareStart(TfEditCookie ec, ITfRange *pWith,
- TfAnchor aPos, LONG *plResult)
- {
- NS_NOTREACHED("ITfRangeACP::CompareStart");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP CompareEnd(TfEditCookie ec, ITfRange *pWith,
- TfAnchor aPos, LONG *plResult)
- {
- NS_NOTREACHED("ITfRangeACP::CompareEnd");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP AdjustForInsert(TfEditCookie ec, ULONG cchInsert,
- BOOL *pfInsertOk)
- {
- NS_NOTREACHED("ITfRangeACP::AdjustForInsert");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP GetGravity(TfGravity *pgStart, TfGravity *pgEnd)
- {
- NS_NOTREACHED("ITfRangeACP::GetGravity");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP SetGravity(TfEditCookie ec, TfGravity gStart, TfGravity gEnd)
- {
- NS_NOTREACHED("ITfRangeACP::SetGravity");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP Clone(ITfRange **ppClone)
- {
- NS_NOTREACHED("ITfRangeACP::Clone");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP GetContext(ITfContext **ppContext)
- {
- NS_NOTREACHED("ITfRangeACP::GetContext");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP GetExtent(LONG *pacpAnchor, LONG *pcch)
- {
- *pacpAnchor = LONG(mRangeStart);
- *pcch = LONG(mRangeLength);
- return S_OK;
- }
-
- STDMETHODIMP SetExtent(LONG acpAnchor, LONG cch)
- {
- mRangeStart = PRUint32(acpAnchor);
- mRangeLength = PRUint32(cch);
- return S_OK;
- }
-
-public: // ITfCompositionView
-
- STDMETHODIMP GetOwnerClsid(CLSID* pclsid)
- {
- NS_NOTREACHED("ITfCompositionView::GetOwnerClsid");
- return E_NOTIMPL;
- }
-
- STDMETHODIMP GetRange(ITfRange** ppRange)
- {
- (*ppRange) = this;
- (*ppRange)->AddRef();
- return S_OK;
- }
-
-public: // ITextStoreACPSink
-
- STDMETHODIMP OnTextChange(DWORD dwFlags, const TS_TEXTCHANGE *pChange)
- {
- mTextChanged = PR_TRUE;
- mTextChangeData = *pChange;
- return S_OK;
- }
-
- STDMETHODIMP OnSelectionChange(void)
- {
- mSelChanged = PR_TRUE;
- return S_OK;
- }
-
- STDMETHODIMP OnLayoutChange(TsLayoutCode lcode, TsViewCookie vcView)
- {
- return S_OK;
- }
-
- STDMETHODIMP OnStatusChange(DWORD dwFlags)
- {
- return S_OK;
- }
-
- STDMETHODIMP OnAttrsChange(LONG acpStart, LONG acpEnd, ULONG cAttrs,
- const TS_ATTRID *paAttrs)
- {
- return S_OK;
- }
-
- STDMETHODIMP OnLockGranted(DWORD dwLockFlags)
- {
- // If we have a test, run it
- if (mTest && !(mTestApp->*mTest)())
- return S_FALSE;
- return S_OK;
- }
-
- STDMETHODIMP OnStartEditTransaction(void)
- {
- return S_OK;
- }
-
- STDMETHODIMP OnEndEditTransaction(void)
- {
- return S_OK;
- }
-};
-
-NS_IMPL_ISUPPORTS2(TestApp, nsIWebProgressListener,
- nsISupportsWeakReference)
-
-nsresult
-TestApp::Run(void)
-{
- // Create a test window
- // We need a full-fledged window to test for TSF functionality
- nsresult rv;
- mAppShell = do_GetService(kAppShellCID);
- NS_ENSURE_TRUE(mAppShell, NS_ERROR_UNEXPECTED);
-
- nsCOMPtr<nsIAppShellService> appShellService(
- do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
- NS_ENSURE_TRUE(appShellService, NS_ERROR_UNEXPECTED);
-
- nsCOMPtr<nsIURI> uri;
- rv = NS_NewURI(getter_AddRefs(uri), "about:blank", nsnull);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = appShellService->CreateTopLevelWindow(nsnull, uri,
- nsIWebBrowserChrome::CHROME_DEFAULT,
- 800 /*nsIAppShellService::SIZE_TO_CONTENT*/,
- 600 /*nsIAppShellService::SIZE_TO_CONTENT*/,
- mAppShell, getter_AddRefs(mWindow));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<nsIDocShell> docShell;
- rv = mWindow->GetDocShell(getter_AddRefs(docShell));
- NS_ENSURE_TRUE(docShell, NS_ERROR_UNEXPECTED);
- nsCOMPtr<nsIWebProgress> progress(do_GetInterface(docShell));
- NS_ENSURE_TRUE(progress, NS_ERROR_UNEXPECTED);
- rv = progress->AddProgressListener(this,
- nsIWebProgress::NOTIFY_STATE_WINDOW |
- nsIWebProgress::NOTIFY_STATUS);
- NS_ENSURE_SUCCESS(rv, rv);
-
- mAppShell->Run();
- return NS_OK;
-}
-
-PRBool
-TestApp::CheckFailed(void)
-{
- // All windows should be closed by now
- if (mImpl && !mImpl->mDeactivated) {
- fail("TSF not terminated properly");
- mFailed = PR_TRUE;
- }
- mImpl = nsnull;
- return mFailed;
-}
-
-nsresult
-TestApp::Init(void)
-{
- // Replace TSF manager pointer
- nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(mWindow));
- NS_ENSURE_TRUE(baseWindow, NS_ERROR_UNEXPECTED);
- nsCOMPtr<nsIWidget> widget;
- nsresult rv = baseWindow->GetMainWidget(getter_AddRefs(widget));
- NS_ENSURE_TRUE(widget, NS_ERROR_UNEXPECTED);
-
- ITfThreadMgr **mgr = reinterpret_cast<ITfThreadMgr**>(
- widget->GetNativeData(NS_NATIVE_TSF_POINTER));
- if (!mgr) {
- fail("nsIWidget::GetNativeData(NS_NATIVE_TSF_POINTER) not supported");
- return NS_ERROR_FAILURE;
- }
- if (*mgr) {
- (*mgr)->Deactivate();
- (*mgr)->Release();
- (*mgr) = NULL;
- } else {
- // This is only for information. The test does not need TSF to run.
- printf("TSF not initialized properly (TSF is not enabled/installed?)\n");
- }
-
- mImpl = new TSFImpl(this);
- if (!mImpl) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- (*mgr) = mImpl;
- (*mgr)->AddRef();
-
- // Apply the change
- reinterpret_cast<ITfThreadMgr**>(
- widget->GetNativeData(NS_NATIVE_TSF_POINTER));
-
- // Create a couple of text boxes for testing
- nsCOMPtr<nsIDOMWindowInternal> win(do_GetInterface(mWindow));
- NS_ENSURE_TRUE(win, NS_ERROR_UNEXPECTED);
- nsCOMPtr<nsIDOMDocument> document;
- rv = win->GetDocument(getter_AddRefs(document));
- NS_ENSURE_TRUE(document, NS_ERROR_UNEXPECTED);
- nsCOMPtr<nsIDOMHTMLDocument> htmlDoc(do_QueryInterface(document));
- NS_ENSURE_TRUE(htmlDoc, NS_ERROR_UNEXPECTED);
- nsCOMPtr<nsIDOMHTMLElement> htmlBody;
- rv = htmlDoc->GetBody(getter_AddRefs(htmlBody));
- NS_ENSURE_TRUE(htmlBody, NS_ERROR_UNEXPECTED);
-
- nsCOMPtr<nsIDOMElement> form;
- rv = htmlDoc->CreateElementNS(
- NS_LITERAL_STRING("http://www.w3.org/1999/xhtml"),
- NS_LITERAL_STRING("form"),
- getter_AddRefs(form));
- nsCOMPtr<nsIDOMElement> elem;
- rv = htmlDoc->CreateElementNS(
- NS_LITERAL_STRING("http://www.w3.org/1999/xhtml"),
- NS_LITERAL_STRING("input"),
- getter_AddRefs(elem));
- NS_ENSURE_SUCCESS(rv, rv);
- elem->SetAttribute(NS_LITERAL_STRING("type"),
- NS_LITERAL_STRING("text"));
- mInput = do_QueryInterface(elem);
- NS_ENSURE_TRUE(mInput, NS_ERROR_UNEXPECTED);
- rv = htmlDoc->CreateElementNS(
- NS_LITERAL_STRING("http://www.w3.org/1999/xhtml"),
- NS_LITERAL_STRING("textarea"),
- getter_AddRefs(elem));
- NS_ENSURE_SUCCESS(rv, rv);
- mTextArea = do_QueryInterface(elem);
- NS_ENSURE_TRUE(mTextArea, NS_ERROR_UNEXPECTED);
- rv = htmlDoc->CreateElementNS(
- NS_LITERAL_STRING("http://www.w3.org/1999/xhtml"),
- NS_LITERAL_STRING("input"),
- getter_AddRefs(elem));
- NS_ENSURE_SUCCESS(rv, rv);
- elem->SetAttribute(NS_LITERAL_STRING("type"),
- NS_LITERAL_STRING("button"));
- mButton = do_QueryInterface(elem);
- NS_ENSURE_TRUE(mButton, NS_ERROR_UNEXPECTED);
-
- nsCOMPtr<nsIDOMNode> node;
- rv = form->AppendChild(mInput, getter_AddRefs(node));
- NS_ENSURE_SUCCESS(rv, rv);
- rv = form->AppendChild(mTextArea, getter_AddRefs(node));
- NS_ENSURE_SUCCESS(rv, rv);
- rv = form->AppendChild(mButton, getter_AddRefs(node));
- NS_ENSURE_SUCCESS(rv, rv);
- rv = htmlBody->AppendChild(form, getter_AddRefs(node));
- NS_ENSURE_SUCCESS(rv, rv);
-
- // set a background color manually,
- // otherwise the window might be transparent
- nsCOMPtr<nsIDOMHTMLBodyElement>(do_QueryInterface(htmlBody))->
- SetBgColor(NS_LITERAL_STRING("white"));
-
- widget->Show(PR_TRUE);
- widget->SetFocus();
- return NS_OK;
-}
-
-nsresult
-TestApp::Term(void)
-{
- mCurrentNode = nsnull;
- mInput = nsnull;
- mTextArea = nsnull;
- mButton = nsnull;
-
- nsCOMPtr<nsIDOMWindowInternal> win(do_GetInterface(mWindow));
- if (win)
- win->Close();
- win = nsnull;
- mWindow = nsnull;
-
- if (mAppShell)
- mAppShell->Exit();
- mAppShell = nsnull;
- return NS_OK;
-}
-
-PRBool
-TestApp::RunTest(test_type aTest, PRBool aLock)
-{
- PRBool succeeded;
- if (aLock && mImpl->mStore) {
- mImpl->mTest = aTest;
- HRESULT hr = E_FAIL;
- mImpl->mStore->RequestLock(TS_LF_READWRITE | TS_LF_SYNC, &hr);
- succeeded = hr == S_OK;
- } else {
- succeeded = (this->*aTest)();
- }
- mFailed |= !succeeded;
- return succeeded;
-}
-
-NS_IMETHODIMP
-TestApp::OnStateChange(nsIWebProgress *aWebProgress,
- nsIRequest *aRequest,
- PRUint32 aStateFlags,
- nsresult aStatus)
-{
- NS_ASSERTION(aStateFlags & nsIWebProgressListener::STATE_IS_WINDOW &&
- aStateFlags & nsIWebProgressListener::STATE_STOP, "wrong state");
- if (NS_SUCCEEDED(Init())) {
- if (RunTest(&TestApp::TestFocus, PR_FALSE))
- passed("TestFocus");
-
- mCurrentNode = mInput;
- mInput->Focus();
- if (mImpl->mStore) {
- if (RunTest(&TestApp::TestClustering))
- passed("TestClustering");
- } else {
- fail("no text store (clustering)");
- mFailed = PR_TRUE;
- }
-
- printf("Testing TSF support in text input element...\n");
- mCurrentNode = mInput;
- mTestString = NS_LITERAL_STRING(
- "This is a test of the Text Services Framework implementation.");
- mInput->SetValue(mTestString);
- mInput->Focus();
- if (mImpl->mStore) {
- if (RunTest(&TestApp::TestSelection))
- passed("TestSelection (input)");
- if (RunTest(&TestApp::TestText))
- passed("TestText (input)");
- if (RunTest(&TestApp::TestExtents))
- passed("TestExtents (input)");
- if (RunTest(&TestApp::TestComposition))
- passed("TestComposition (input)");
- if (RunTest(&TestApp::TestNotification, PR_FALSE))
- passed("TestNotification (input)");
- } else {
- fail("no text store (input)");
- mFailed = PR_TRUE;
- }
-
- printf("Testing TSF support in textarea element...\n");
- mCurrentNode = mTextArea;
- mTestString = NS_LITERAL_STRING(
- "This is a test of the\r\nText Services Framework\r\nimplementation.");
- mTextArea->SetValue(mTestString);
- mTextArea->Focus();
- if (mImpl->mStore) {
- if (RunTest(&TestApp::TestSelection))
- passed("TestSelection (textarea)");
- if (RunTest(&TestApp::TestText))
- passed("TestText (textarea)");
- if (RunTest(&TestApp::TestExtents))
- passed("TestExtents (textarea)");
- if (RunTest(&TestApp::TestComposition))
- passed("TestComposition (textarea)");
- if (RunTest(&TestApp::TestNotification, PR_FALSE))
- passed("TestNotification (textarea)");
- } else {
- fail("no text store (textarea)");
- mFailed = PR_TRUE;
- }
- } else {
- fail("initialization");
- mFailed = PR_TRUE;
- }
- Term();
- return NS_OK;
-}
-
-PRBool
-TestApp::TestFocus(void)
-{
- PRUint32 focus = mImpl->mFocusCount, blur = mImpl->mBlurCount;
- nsresult rv;
-
- /* If these fail the cause is probably one or more of:
- * - nsIMEStateManager::OnTextStateFocus not called by nsEventStateManager
- * - nsIMEStateManager::OnTextStateBlur not called by nsEventStateManager
- * - nsWindow::OnIMEFocusChange (nsIWidget) not called by nsIMEStateManager
- * - nsTextStore::Create/Focus/Destroy not called by nsWindow
- * - ITfThreadMgr::CreateDocumentMgr/SetFocus not called by nsTextStore
- * - ITfDocumentMgr::CreateContext/Push not called by nsTextStore
- */
-
- rv = mInput->Focus();
- if (!(NS_SUCCEEDED(rv) &&
- mImpl->mFocused &&
- mImpl->mStore &&
- mImpl->mFocusCount - focus == 1 &&
- mImpl->mBlurCount - blur == 0 &&
- mImpl->mStore)) {
- fail("TestFocus: document focus was not set");
- return PR_FALSE;
- }
-
- rv = mTextArea->Focus();
- if (!(NS_SUCCEEDED(rv) &&
- mImpl->mFocused &&
- mImpl->mStore &&
- mImpl->mFocusCount - focus == 2 &&
- mImpl->mBlurCount - blur == 1 &&
- mImpl->mStore)) {
- fail("TestFocus: document focus was not changed");
- return PR_FALSE;
- }
-
- rv = mButton->Focus();
- if (!(NS_SUCCEEDED(rv) &&
- !mImpl->mFocused &&
- !mImpl->mStore &&
- mImpl->mFocusCount - focus == 2 &&
- mImpl->mBlurCount - blur == 2 &&
- !mImpl->mStore)) {
- fail("TestFocus: document was not blurred");
- return PR_FALSE;
- }
- return PR_TRUE;
-}
-
-PRBool
-TestApp::TestClustering(void)
-{
- // Text for testing
- const PRUint32 STRING_LENGTH = 2;
- PRUnichar string[3];
- string[0] = 'e';
- string[1] = 0x0301; // U+0301 'acute accent'
- string[2] = nsnull;
-
- // Replace entire string with our string
- TS_TEXTCHANGE textChange;
- HRESULT hr = mImpl->mStore->SetText(0, 0, -1, string, STRING_LENGTH,
- &textChange);
- if (!(SUCCEEDED(hr) &&
- 0 == textChange.acpStart &&
- STRING_LENGTH == textChange.acpNewEnd)) {
- fail("TestClustering: SetText");
- return PR_FALSE;
- }
-
- TsViewCookie view;
- RECT rectLetter, rectAccent, rectWhole, rectCombined;
- BOOL clipped, nonEmpty;
-
- hr = mImpl->mStore->GetActiveView(&view);
- if (!(SUCCEEDED(hr))) {
- fail("TestClustering: GetActiveView");
- return PR_FALSE;
- }
-
- // Get rect of first char (the letter)
- hr = mImpl->mStore->GetTextExt(view, 0, STRING_LENGTH / 2,
- &rectLetter, &clipped);
- if (!(SUCCEEDED(hr))) {
- fail("TestClustering: GetTextExt (letter)");
- return PR_FALSE;
- }
-
- // Get rect of second char (the accent)
- hr = mImpl->mStore->GetTextExt(view, STRING_LENGTH / 2, STRING_LENGTH,
- &rectAccent, &clipped);
- if (!(SUCCEEDED(hr))) {
- fail("TestClustering: GetTextExt (accent)");
- return PR_FALSE;
- }
-
- // Get rect of combined char
- hr = mImpl->mStore->GetTextExt(view, 0, STRING_LENGTH,
- &rectWhole, &clipped);
- if (!(SUCCEEDED(hr))) {
- fail("TestClustering: GetTextExt (whole)");
- return PR_FALSE;
- }
-
- nonEmpty = ::UnionRect(&rectCombined, &rectLetter, &rectAccent);
- if (!(nonEmpty &&
- ::EqualRect(&rectCombined, &rectWhole))) {
- fail("TestClustering: unexpected combined rect");
- return PR_FALSE;
- }
- return PR_TRUE;
-}
-
-PRBool
-TestApp::TestSelectionInternal(char* aTestName,
- LONG aStart,
- LONG aEnd,
- TsActiveSelEnd aSelEnd)
-{
- PRBool succeeded = PR_TRUE, continueTest = PR_TRUE;
- TS_SELECTION_ACP sel, testSel;
- ULONG selFetched;
-
- sel.acpStart = aStart;
- sel.acpEnd = aEnd;
- sel.style.ase = aSelEnd;
- sel.style.fInterimChar = FALSE;
- HRESULT hr = mImpl->mStore->SetSelection(1, &sel);
- if (!(SUCCEEDED(hr))) {
- fail("TestSelection: SetSelection (%s)", aTestName);
- continueTest = succeeded = PR_FALSE;
- }
-
- if (continueTest) {
- hr = mImpl->mStore->GetSelection(TS_DEFAULT_SELECTION, 1,
- &testSel, &selFetched);
- if (!(SUCCEEDED(hr) &&
- selFetched == 1 &&
- !memcmp(&sel, &testSel, sizeof(sel)))) {
- fail("TestSelection: unexpected GetSelection result (%s)", aTestName);
- succeeded = PR_FALSE;
- }
- }
- return succeeded;
-}
-
-PRBool
-TestApp::TestSelection(void)
-{
- PRBool succeeded = PR_TRUE;
-
- /* If these fail the cause is probably one or more of:
- * nsTextStore::GetSelection not sending NS_QUERY_SELECTED_TEXT
- * NS_QUERY_SELECTED_TEXT not handled by nsContentEventHandler
- * Bug in NS_QUERY_SELECTED_TEXT handler
- * nsTextStore::SetSelection not sending NS_SELECTION_SET
- * NS_SELECTION_SET not handled by nsContentEventHandler
- * Bug in NS_SELECTION_SET handler
- */
-
- TS_SELECTION_ACP testSel;
- ULONG selFetched;
-
- HRESULT hr = mImpl->mStore->GetSelection(0, 1, &testSel, &selFetched);
- if (!(SUCCEEDED(hr) &&
- selFetched == 1)) {
- fail("TestSelection: GetSelection");
- succeeded = PR_FALSE;
- }
-
- const LONG SELECTION1_START = 0;
- const LONG SELECTION1_END = mTestString.Length();
- const TsActiveSelEnd SELECTION1_SELEND = TS_AE_END;
-
- if (!TestSelectionInternal("normal",
- SELECTION1_START,
- SELECTION1_END,
- SELECTION1_SELEND)) {
- succeeded = PR_FALSE;
- }
-
- const LONG SELECTION2_START = mTestString.Length() / 2;
- const LONG SELECTION2_END = SELECTION2_START;
- const TsActiveSelEnd SELECTION2_SELEND = TS_AE_END;
-
- if (!TestSelectionInternal("collapsed",
- SELECTION2_START,
- SELECTION2_END,
- SELECTION2_SELEND)) {
- succeeded = PR_FALSE;
- }
-
- const LONG SELECTION3_START = 12;
- const LONG SELECTION3_END = mTestString.Length() - 20;
- const TsActiveSelEnd SELECTION3_SELEND = TS_AE_START;
-
- if (!TestSelectionInternal("reversed",
- SELECTION3_START,
- SELECTION3_END,
- SELECTION3_SELEND)) {
- succeeded = PR_FALSE;
- }
- return succeeded;
-}
-
-PRBool
-TestApp::TestText(void)
-{
- const PRUint32 BUFFER_SIZE = (0x100);
- const PRUint32 RUNINFO_SIZE = (0x10);
-
- PRBool succeeded = PR_TRUE, continueTest;
- PRUnichar buffer[BUFFER_SIZE];
- TS_RUNINFO runInfo[RUNINFO_SIZE];
- ULONG bufferRet, runInfoRet;
- LONG acpRet, acpCurrent;
- TS_TEXTCHANGE textChange;
- HRESULT hr;
-
- /* If these fail the cause is probably one or more of:
- * nsTextStore::GetText not sending NS_QUERY_TEXT_CONTENT
- * NS_QUERY_TEXT_CONTENT not handled by nsContentEventHandler
- * Bug in NS_QUERY_TEXT_CONTENT handler
- * nsTextStore::SetText not calling SetSelection or InsertTextAtSelection
- * Bug in SetSelection or InsertTextAtSelection
- * NS_SELECTION_SET bug or NS_COMPOSITION_* / NS_TEXT_TEXT bug
- */
-
- // Get all text
- hr = mImpl->mStore->GetText(0, -1, buffer, BUFFER_SIZE, &bufferRet,
- runInfo, RUNINFO_SIZE, &runInfoRet, &acpRet);
- if (!(SUCCEEDED(hr) &&
- bufferRet <= mTestString.Length() &&
- !wcsncmp(mTestString.get(), buffer, bufferRet) &&
- acpRet == LONG(bufferRet) &&
- runInfoRet > 0)) {
- fail("TestText: GetText 1");
- succeeded = PR_FALSE;
- }
-
-
- // Get text from GETTEXT2_START to GETTEXT2_END
- const PRUint32 GETTEXT2_START = (18);
- const PRUint32 GETTEXT2_END = (mTestString.Length() - 16);
- const PRUint32 GETTEXT2_BUFFER_SIZE = (0x10);
-
- hr = mImpl->mStore->GetText(GETTEXT2_START, GETTEXT2_END,
- buffer, GETTEXT2_BUFFER_SIZE, &bufferRet,
- runInfo, RUNINFO_SIZE, &runInfoRet, &acpRet);
- if (!(SUCCEEDED(hr) &&
- bufferRet <= GETTEXT2_BUFFER_SIZE &&
- !wcsncmp(mTestString.get() + GETTEXT2_START, buffer, bufferRet) &&
- acpRet == LONG(bufferRet) + GETTEXT2_START &&
- runInfoRet > 0)) {
- fail("TestText: GetText 2");
- succeeded = PR_FALSE;
- }
-
-
- // Replace text from SETTEXT1_START to SETTEXT1_END with insertString
- const PRUint32 SETTEXT1_START = (8);
- const PRUint32 SETTEXT1_TAIL_LENGTH = (40);
- const PRUint32 SETTEXT1_END = (mTestString.Length() -
- SETTEXT1_TAIL_LENGTH);
- NS_NAMED_LITERAL_STRING(insertString, "(Inserted string)");
-
- continueTest = PR_TRUE;
- hr = mImpl->mStore->SetText(0, SETTEXT1_START, SETTEXT1_END,
- insertString.get(), insertString.Length(), &textChange);
- if (!(SUCCEEDED(hr) &&
- textChange.acpStart == SETTEXT1_START &&
- textChange.acpOldEnd == LONG(SETTEXT1_END) &&
- textChange.acpNewEnd == LONG(SETTEXT1_START +
- insertString.Length()))) {
- fail("TestText: SetText 1");
- continueTest = succeeded = PR_FALSE;
- }
-
- const PRUint32 SETTEXT1_FINAL_LENGTH = (SETTEXT1_START +
- SETTEXT1_TAIL_LENGTH +
- insertString.Length());
-
- if (continueTest) {
- acpCurrent = 0;
- while (acpCurrent < LONG(SETTEXT1_FINAL_LENGTH)) {
- hr = mImpl->mStore->GetText(acpCurrent, -1, &buffer[acpCurrent],
- BUFFER_SIZE, &bufferRet, runInfo,
- RUNINFO_SIZE, &runInfoRet, &acpRet);
- if (!(SUCCEEDED(hr) &&
- acpRet > acpCurrent &&
- bufferRet <= SETTEXT1_FINAL_LENGTH &&
- runInfoRet > 0)) {
- fail("TestText: GetText failed after SetTest 1");
- continueTest = succeeded = PR_FALSE;
- break;
- }
- acpCurrent = acpRet;
- }
- }
-
- if (continueTest) {
- if (!(acpCurrent == LONG(SETTEXT1_FINAL_LENGTH) &&
- !wcsncmp(buffer, mTestString.get(), SETTEXT1_START) &&
- !wcsncmp(&buffer[SETTEXT1_START], insertString.get(),
- insertString.Length()) &&
- !wcsncmp(&buffer[SETTEXT1_START + insertString.Length()],
- mTestString.get() + SETTEXT1_END, SETTEXT1_TAIL_LENGTH))) {
- fail("TestText: unexpected GetText result after SetText 1");
- succeeded = PR_FALSE;
- }
- }
-
-
- // Restore entire text to original text (mTestString)
- continueTest = PR_TRUE;
- hr = mImpl->mStore->SetText(0, 0, -1, mTestString.get(),
- mTestString.Length(), &textChange);
- if (!(SUCCEEDED(hr) &&
- textChange.acpStart == 0 &&
- textChange.acpOldEnd == LONG(SETTEXT1_FINAL_LENGTH) &&
- textChange.acpNewEnd == LONG(mTestString.Length()))) {
- fail("TestText: SetText 2");
- continueTest = succeeded = PR_FALSE;
- }
-
- if (continueTest) {
- acpCurrent = 0;
- while (acpCurrent < LONG(mTestString.Length())) {
- hr = mImpl->mStore->GetText(acpCurrent, -1, &buffer[acpCurrent],
- BUFFER_SIZE, &bufferRet, runInfo, RUNINFO_SIZE, &runInfoRet, &acpRet);
- if (!(SUCCEEDED(hr) &&
- acpRet > acpCurrent &&
- bufferRet <= mTestString.Length() &&
- runInfoRet > 0)) {
- fail("TestText: GetText failed after SetText 2");
- continueTest = succeeded = PR_FALSE;
- break;
- }
- acpCurrent = acpRet;
- }
- }
-
- if (continueTest) {
- if (!(acpCurrent == LONG(mTestString.Length()) &&
- !wcsncmp(buffer, mTestString.get(), mTestString.Length()))) {
- fail("TestText: unexpected GetText result after SetText 2");
- succeeded = PR_FALSE;
- }
- }
- return succeeded;
-}
-
-PRBool
-TestApp::TestExtents(void)
-{
- TS_SELECTION_ACP sel;
- sel.acpStart = 0;
- sel.acpEnd = 0;
- sel.style.ase = TS_AE_END;
- sel.style.fInterimChar = FALSE;
- mImpl->mStore->SetSelection(1, &sel);
-
- nsCOMPtr<nsISelectionController> selCon;
- if (!(NS_SUCCEEDED(GetSelCon(getter_AddRefs(selCon))) && selCon)) {
- fail("TestExtents: get nsISelectionController");
- return PR_FALSE;
- }
- selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
- nsISelectionController::SELECTION_FOCUS_REGION, PR_TRUE);
-
- nsCOMPtr<nsIDOMWindowInternal> window(do_GetInterface(mWindow));
- if (!window) {
- fail("TestExtents: get nsIDOMWindowInternal");
- return PR_FALSE;
- }
- RECT windowRect, screenRect, textRect1, textRect2;
- BOOL clipped;
- PRInt32 val;
- TsViewCookie view;
- HRESULT hr;
-
- nsresult nsr = window->GetScreenX(&val);
- windowRect.left = val;
- nsr |= window->GetScreenY(&val);
- windowRect.top = val;
- nsr |= window->GetOuterWidth(&val);
- windowRect.right = windowRect.left + val;
- nsr |= window->GetOuterHeight(&val);
- windowRect.bottom = windowRect.top + val;
- if (!(NS_SUCCEEDED(nsr))) {
- fail("TestExtents: get window rect failed");
- return PR_FALSE;
- }
-
- hr = mImpl->mStore->GetActiveView(&view);
- if (!(SUCCEEDED(hr))) {
- fail("TestExtents: GetActiveView");
- return PR_FALSE;
- }
-
- PRBool succeeded = PR_TRUE;
- HWND hwnd;
- hr = mImpl->mStore->GetWnd(view, &hwnd);
- if (!(SUCCEEDED(hr) &&
- ::IsWindow(hwnd))) {
- fail("TestExtents: GetWnd");
- succeeded = PR_FALSE;
- }
-
- ::SetRectEmpty(&screenRect);
- hr = mImpl->mStore->GetScreenExt(view, &screenRect);
- if (!(SUCCEEDED(hr) &&
- screenRect.left > windowRect.left &&
- screenRect.top > windowRect.top &&
- screenRect.right > screenRect.left &&
- screenRect.bottom > screenRect.top &&
- screenRect.right < windowRect.right &&
- screenRect.bottom < windowRect.bottom)) {
- fail("TestExtents: GetScreenExt");
- succeeded = PR_FALSE;
- }
-
- const LONG GETTEXTEXT1_START = 0;
- const LONG GETTEXTEXT1_END = 0;
-
- ::SetRectEmpty(&textRect1);
- hr = mImpl->mStore->GetTextExt(view, GETTEXTEXT1_START, GETTEXTEXT1_END,
- &textRect1, &clipped);
- if (!(SUCCEEDED(hr) &&
- textRect1.left >= screenRect.left &&
- textRect1.top >= screenRect.top &&
- textRect1.right < screenRect.right &&
- textRect1.bottom <= screenRect.bottom &&
- textRect1.right >= textRect1.left &&
- textRect1.bottom > textRect1.top)) {
- fail("TestExtents: GetTextExt (offset %ld to %ld)",
- GETTEXTEXT1_START, GETTEXTEXT1_END);
- succeeded = PR_FALSE;
- }
-
- const LONG GETTEXTEXT2_START = 10;
- const LONG GETTEXTEXT2_END = 25;
-
- ::SetRectEmpty(&textRect2);
- hr = mImpl->mStore->GetTextExt(view, GETTEXTEXT2_START, GETTEXTEXT2_END,
- &textRect2, &clipped);
- if (!(SUCCEEDED(hr) &&
- textRect2.left >= screenRect.left &&
- textRect2.top >= screenRect.top &&
- textRect2.right <= screenRect.right &&
- textRect2.bottom <= screenRect.bottom &&
- textRect2.right > textRect2.left &&
- textRect2.bottom > textRect2.top)) {
- fail("TestExtents: GetTextExt (offset %ld to %ld)",
- GETTEXTEXT2_START, GETTEXTEXT2_END);
- succeeded = PR_FALSE;
- }
-
- // Offsets must be between GETTEXTEXT2_START and GETTEXTEXT2_END
- const LONG GETTEXTEXT3_START = 23;
- const LONG GETTEXTEXT3_END = 23;
-
- ::SetRectEmpty(&textRect1);
- hr = mImpl->mStore->GetTextExt(view, GETTEXTEXT3_START, GETTEXTEXT3_END,
- &textRect1, &clipped);
- // Rectangle must be entirely inside the previous rectangle,
- // since GETTEXTEXT3_START and GETTEXTEXT3_END are between
- // GETTEXTEXT2_START and GETTEXTEXT2_START
- if (!(SUCCEEDED(hr) && ::IsRectEmpty(&textRect1) ||
- (textRect1.left >= textRect2.left &&
- textRect1.top >= textRect2.top &&
- textRect1.right <= textRect2.right &&
- textRect1.bottom <= textRect2.bottom &&
- textRect1.right >= textRect1.left &&
- textRect1.bottom > textRect1.top))) {
- fail("TestExtents: GetTextExt (offset %ld to %ld)",
- GETTEXTEXT3_START, GETTEXTEXT3_END);
- succeeded = PR_FALSE;
- }
- return succeeded;
-}
-
-PRBool
-TestApp::TestCompositionSelectionAndText(char* aTestName,
- LONG aExpectedSelStart,
- LONG aExpectedSelEnd,
- nsString& aReferenceString)
-{
- TS_SELECTION_ACP currentSel;
- ULONG selFetched = 0;
- HRESULT hr = mImpl->mStore->GetSelection(TF_DEFAULT_SELECTION, 1,
- ¤tSel, &selFetched);
- if (!(SUCCEEDED(hr) &&
- 1 == selFetched &&
- currentSel.acpStart == aExpectedSelStart &&
- currentSel.acpEnd == aExpectedSelEnd)) {
- fail("TestComposition: GetSelection (%s)", aTestName);
- return PR_FALSE;
- }
-
- const PRUint32 bufferSize = 0x100, runInfoSize = 0x10;
- PRUnichar buffer[bufferSize];
- TS_RUNINFO runInfo[runInfoSize];
- ULONG bufferRet, runInfoRet;
- LONG acpRet, acpCurrent = 0;
- while (acpCurrent < LONG(aReferenceString.Length())) {
- hr = mImpl->mStore->GetText(acpCurrent, aReferenceString.Length(),
- &buffer[acpCurrent], bufferSize, &bufferRet, runInfo, runInfoSize,
- &runInfoRet, &acpRet);
- if (!(SUCCEEDED(hr) &&
- acpRet > acpCurrent &&
- bufferRet <= aReferenceString.Length() &&
- runInfoRet > 0)) {
- fail("TestComposition: GetText (%s)", aTestName);
- return PR_FALSE;
- }
- acpCurrent = acpRet;
- }
- if (!(acpCurrent == aReferenceString.Length() &&
- !wcsncmp(buffer, aReferenceString.get(), aReferenceString.Length()))) {
- fail("TestComposition: unexpected GetText result (%s)", aTestName);
- return PR_FALSE;
- }
- return PR_TRUE;
-}
-
-PRBool
-TestApp::TestComposition(void)
-{
- nsRefPtr<ITfContextOwnerCompositionSink> sink;
- HRESULT hr = mImpl->mStore->QueryInterface(
- IID_ITfContextOwnerCompositionSink,
- getter_AddRefs(sink));
- if (!(SUCCEEDED(hr))) {
- fail("TestComposition: QueryInterface");
- return PR_FALSE;
- }
-
- const LONG PRECOMPOSITION_SEL_START = 2;
- const LONG PRECOMPOSITION_SEL_END = PRECOMPOSITION_SEL_START;
- const TsActiveSelEnd PRECOMPOSITION_SEL_SELEND = TS_AE_END;
-
- TS_SELECTION_ACP sel;
- sel.acpStart = PRECOMPOSITION_SEL_START;
- sel.acpEnd = PRECOMPOSITION_SEL_END;
- sel.style.ase = PRECOMPOSITION_SEL_SELEND;
- sel.style.fInterimChar = FALSE;
- hr = mImpl->mStore->SetSelection(1, &sel);
- if (!(SUCCEEDED(hr))) {
- fail("TestComposition: SetSelection (pre-composition)");
- return PR_FALSE;
- }
-
-
- TS_TEXTCHANGE textChange;
- NS_NAMED_LITERAL_STRING(insertString1, "Compo1");
- hr = mImpl->mStore->InsertTextAtSelection(TF_IAS_NOQUERY,
- insertString1.get(),
- insertString1.Length(),
- NULL, NULL, &textChange);
- if (!(SUCCEEDED(hr) &&
- sel.acpEnd == textChange.acpStart &&
- sel.acpEnd == textChange.acpOldEnd &&
- sel.acpEnd + insertString1.Length() == textChange.acpNewEnd)) {
- fail("TestComposition: InsertTextAtSelection");
- return PR_FALSE;
- }
- sel.acpEnd = textChange.acpNewEnd;
-
- mImpl->mRangeStart = textChange.acpStart;
- mImpl->mRangeLength = textChange.acpNewEnd - textChange.acpOldEnd;
- BOOL okay = FALSE;
- hr = sink->OnStartComposition(mImpl, &okay);
- if (!(SUCCEEDED(hr) &&
- okay)) {
- fail("TestComposition: OnStartComposition");
- return PR_FALSE;
- }
-
-
- NS_NAMED_LITERAL_STRING(insertString2, "Composition2");
- hr = mImpl->mStore->SetText(0, mImpl->mRangeStart + mImpl->mRangeLength,
- mImpl->mRangeStart + mImpl->mRangeLength,
- insertString2.get(), insertString2.Length(),
- &textChange);
- if (!(SUCCEEDED(hr) &&
- sel.acpEnd == textChange.acpStart &&
- sel.acpEnd == textChange.acpOldEnd &&
- sel.acpEnd + insertString2.Length() == textChange.acpNewEnd)) {
- fail("TestComposition: SetText 1");
- return PR_FALSE;
- }
- sel.acpEnd = textChange.acpNewEnd;
- mImpl->mRangeLength += textChange.acpNewEnd - textChange.acpOldEnd;
-
-
- const LONG COMPOSITION3_TEXT_START_OFFSET = -8; // offset 8 from the end
- const LONG COMPOSITION3_TEXT_END_OFFSET = 4;
-
- const LONG COMPOSITION3_TEXT_START = mImpl->mRangeStart +
- mImpl->mRangeLength +
- COMPOSITION3_TEXT_START_OFFSET;
- const LONG COMPOSITION3_TEXT_END = COMPOSITION3_TEXT_START +
- COMPOSITION3_TEXT_END_OFFSET;
-
- NS_NAMED_LITERAL_STRING(insertString3, "Compo3");
- hr = mImpl->mStore->SetText(0, COMPOSITION3_TEXT_START,
- COMPOSITION3_TEXT_END,
- insertString3.get(), insertString3.Length(),
- &textChange);
- if (!(SUCCEEDED(hr) &&
- sel.acpEnd + COMPOSITION3_TEXT_START_OFFSET == textChange.acpStart &&
- sel.acpEnd + COMPOSITION3_TEXT_START_OFFSET +
- COMPOSITION3_TEXT_END_OFFSET == textChange.acpOldEnd &&
- sel.acpEnd + insertString3.Length() + COMPOSITION3_TEXT_START_OFFSET ==
- textChange.acpNewEnd)) {
- fail("TestComposition: SetText 2");
- return PR_FALSE;
- }
- sel.acpEnd = textChange.acpNewEnd;
- mImpl->mRangeLength += textChange.acpNewEnd - textChange.acpOldEnd;
-
-
- nsString referenceString;
- referenceString.Append(mTestString.get(), sel.acpStart);
- referenceString.Append(insertString1);
- referenceString.Append(insertString2.get(),
- insertString2.Length() + COMPOSITION3_TEXT_START_OFFSET);
- referenceString.Append(insertString3);
- referenceString.Append(insertString2.get() + insertString2.Length() -
- COMPOSITION3_TEXT_END_OFFSET, COMPOSITION3_TEXT_END_OFFSET);
- referenceString.Append(mTestString.get() + sel.acpStart,
- COMPOSITION3_TEXT_END_OFFSET);
-
- if (!TestCompositionSelectionAndText("composition",
- sel.acpEnd, sel.acpEnd,
- referenceString))
- return PR_FALSE;
-
-
- const LONG POSTCOMPOSITION_SEL_START = sel.acpEnd - 8;
- const LONG POSTCOMPOSITION_SEL_END = POSTCOMPOSITION_SEL_START + 2;
-
- sel.acpStart = POSTCOMPOSITION_SEL_START;
- sel.acpEnd = POSTCOMPOSITION_SEL_END;
- hr = mImpl->mStore->SetSelection(1, &sel);
- if (!(SUCCEEDED(hr))) {
- fail("TestComposition: SetSelection (composition)");
- return PR_FALSE;
- }
-
- hr = sink->OnEndComposition(mImpl);
- if (!(SUCCEEDED(hr))) {
- fail("TestComposition: OnEndComposition");
- return PR_FALSE;
- }
-
- if (!TestCompositionSelectionAndText("post-composition",
- sel.acpStart, sel.acpEnd,
- referenceString))
- return PR_FALSE;
-
-
- const LONG EMPTYCOMPOSITION_START = mImpl->mRangeStart + 2;
- const LONG EMPTYCOMPOSITION_LENGTH = mImpl->mRangeLength - 4;
-
- mImpl->mRangeStart = EMPTYCOMPOSITION_START;
- mImpl->mRangeLength = EMPTYCOMPOSITION_LENGTH;
- okay = FALSE;
- hr = sink->OnStartComposition(mImpl, &okay);
- if (!(SUCCEEDED(hr) &&
- okay)) {
- fail("TestComposition: OnStartComposition (empty composition)");
- return PR_FALSE;
- }
-
- hr = sink->OnEndComposition(mImpl);
- if (!(SUCCEEDED(hr))) {
- fail("TestComposition: OnEndComposition (empty composition)");
- return PR_FALSE;
- }
-
- if (!TestCompositionSelectionAndText("empty composition",
- mImpl->mRangeStart,
- mImpl->mRangeStart + mImpl->mRangeLength,
- referenceString))
- return PR_FALSE;
-
- return PR_TRUE;
-}
-
-PRBool
-TestApp::TestNotificationTextChange(nsIWidget* aWidget,
- PRUint32 aCode,
- const nsAString& aCharacter,
- LONG aStart,
- LONG aOldEnd,
- LONG aNewEnd)
-{
- MSG msg;
- if (::PeekMessageW(&msg, NULL, WM_USER_TSF_TEXTCHANGE,
- WM_USER_TSF_TEXTCHANGE, PM_REMOVE))
- ::DispatchMessageW(&msg);
- mImpl->mTextChanged = PR_FALSE;
- nsresult nsr = aWidget->SynthesizeNativeKeyEvent(0, aCode, 0,
- aCharacter, aCharacter);
- if (::PeekMessageW(&msg, NULL, WM_USER_TSF_TEXTCHANGE,
- WM_USER_TSF_TEXTCHANGE, PM_REMOVE))
- ::DispatchMessageW(&msg);
- return NS_SUCCEEDED(nsr) &&
- mImpl->mTextChanged &&
- aStart == mImpl->mTextChangeData.acpStart &&
- aOldEnd == mImpl->mTextChangeData.acpOldEnd &&
- aNewEnd == mImpl->mTextChangeData.acpNewEnd;
-}
-
-PRBool
-TestApp::TestNotification(void)
-{
- nsresult nsr;
- // get selection to test notification support
- nsCOMPtr<nsISelectionController> selCon;
- if (!(NS_SUCCEEDED(GetSelCon(getter_AddRefs(selCon))) && selCon)) {
- fail("TestNotification: get nsISelectionController");
- return PR_FALSE;
- }
-
- nsr = selCon->CompleteMove(PR_FALSE, PR_FALSE);
- if (!(NS_SUCCEEDED(nsr))) {
- fail("TestNotification: CompleteMove");
- return PR_FALSE;
- }
-
- mImpl->mSelChanged = PR_FALSE;
- nsr = selCon->CharacterMove(PR_TRUE, PR_FALSE);
- if (!(NS_SUCCEEDED(nsr) &&
- mImpl->mSelChanged)) {
- fail("TestNotification: CharacterMove");
- return PR_FALSE;
- }
-
- mImpl->mSelChanged = PR_FALSE;
- nsr = selCon->CharacterMove(PR_TRUE, PR_TRUE);
- if (!(NS_SUCCEEDED(nsr) &&
- mImpl->mSelChanged)) {
- fail("TestNotification: CharacterMove (extend)");
- return PR_FALSE;
- }
-
- nsCOMPtr<nsIWidget> widget;
- nsCOMPtr<nsIDocShell> docShell;
- nsr = mWindow->GetDocShell(getter_AddRefs(docShell));
- if (NS_SUCCEEDED(nsr) && docShell) {
- nsCOMPtr<nsIPresShell> presShell;
- nsr = docShell->GetPresShell(getter_AddRefs(presShell));
- if (NS_SUCCEEDED(nsr) && presShell) {
- nsCOMPtr<nsIViewManager> viewManager = presShell->GetViewManager();
- if (viewManager) {
- nsr = viewManager->GetWidget(getter_AddRefs(widget));
- }
- }
- }
- if (!(NS_SUCCEEDED(nsr) && widget)) {
- fail("TestNotification: get nsIWidget");
- return PR_FALSE;
- }
-
- NS_NAMED_LITERAL_STRING(character, "");
- NS_NAMED_LITERAL_STRING(characterA, "A");
-
- // The selection test code above placed the selection at offset 1 to 2
- const LONG TEXTCHANGE1_START = 1;
- const LONG TEXTCHANGE1_OLDEND = 2;
- const LONG TEXTCHANGE1_NEWEND = 2;
-
- // replace single selected character with 'A'
- if (!TestNotificationTextChange(widget, 'A', characterA,
- TEXTCHANGE1_START, TEXTCHANGE1_OLDEND, TEXTCHANGE1_NEWEND)) {
- fail("TestNotification: text change 1");
- return PR_FALSE;
- }
-
- const LONG TEXTCHANGE2_START = TEXTCHANGE1_NEWEND;
- const LONG TEXTCHANGE2_OLDEND = TEXTCHANGE1_NEWEND;
- const LONG TEXTCHANGE2_NEWEND = TEXTCHANGE1_NEWEND + 1;
-
- // insert 'A'
- if (!TestNotificationTextChange(widget, 'A', characterA,
- TEXTCHANGE2_START, TEXTCHANGE2_OLDEND, TEXTCHANGE2_NEWEND)) {
- fail("TestNotification: text change 2");
- return PR_FALSE;
- }
-
- const LONG TEXTCHANGE3_START = TEXTCHANGE2_NEWEND - 1;
- const LONG TEXTCHANGE3_OLDEND = TEXTCHANGE2_NEWEND;
- const LONG TEXTCHANGE3_NEWEND = TEXTCHANGE2_NEWEND - 1;
-
- // backspace
- if (!TestNotificationTextChange(widget, '\b', character,
- TEXTCHANGE3_START, TEXTCHANGE3_OLDEND, TEXTCHANGE3_NEWEND)) {
- fail("TestNotification: text change 3");
- return PR_FALSE;
- }
- return PR_TRUE;
-}
-
-nsresult
-TestApp::GetSelCon(nsISelectionController** aSelCon)
-{
- nsCOMPtr<nsIDocShell> docShell;
- nsresult nsr = mWindow->GetDocShell(getter_AddRefs(docShell));
- if (NS_SUCCEEDED(nsr) && docShell) {
- nsCOMPtr<nsIPresShell> presShell;
- nsr = docShell->GetPresShell(getter_AddRefs(presShell));
- if (NS_SUCCEEDED(nsr) && presShell) {
- nsIFrame* frame = presShell->GetPrimaryFrameFor(
- nsCOMPtr<nsIContent>(do_QueryInterface(mCurrentNode)));
- if (frame) {
- nsPresContext* presContext = presShell->GetPresContext();
- if (presContext) {
- nsr = frame->GetSelectionController(presContext, aSelCon);
- }
- }
- }
- }
- return nsr;
-}
-
-int main(int argc, char** argv)
-{
- ScopedXPCOM xpcom("TestWinTSF (bug #88831)");
- if (xpcom.failed())
- return 1;
-
- nsRefPtr<TestApp> tests = new TestApp();
- if (!tests)
- return 1;
-
- if (NS_FAILED(tests->Run())) {
- fail("run failed");
- return 1;
- }
- return int(tests->CheckFailed());
-}