Added clause and selection support for Input Methods. Fixes bug #8639, #8459, #6989, #7824

git-svn-id: svn://10.0.0.236/trunk@37435 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
tague%netscape.com 1999-06-29 20:31:22 +00:00
parent db23dd7d5c
commit ea708a16a8
54 changed files with 2716 additions and 563 deletions

View File

@ -31,6 +31,7 @@ CPPSRCS = \
nsEventStateManager.cpp \
nsDOMEvent.cpp \
nsDOMEventsIIDs.cpp \
nsDOMTextRange.cpp \
$(NULL)
MODULE=layout
@ -40,6 +41,7 @@ EXPORTS = \
nsEventStateManager.h \
nsDOMEvent.h \
nsDOMEventsIIDs.h \
nsDOMTextRange.h \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))

View File

@ -30,16 +30,18 @@ CPPSRCS= nsEventListenerManager.cpp \
nsEventStateManager.cpp \
nsDOMEvent.cpp \
nsDOMEventsIIDs.cpp \
nsDOMTextRange.cpp \
$(NULL)
CPP_OBJS= .\$(OBJDIR)\nsEventListenerManager.obj \
.\$(OBJDIR)\nsEventStateManager.obj \
.\$(OBJDIR)\nsDOMEvent.obj \
.\$(OBJDIR)\nsDOMEventsIIDs.obj \
.\$(OBJDIR)\nsDOMTextRange.obj \
$(NULL)
EXPORTS= nsEventListenerManager.h nsEventStateManager.h nsDOMEvent.h nsDOMEventsIIDs.h
EXPORTS= nsEventListenerManager.h nsEventStateManager.h nsDOMEvent.h nsDOMEventsIIDs.h nsDOMTextRange.h
LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor \
-I$(PUBLIC)\dom -I$(PUBLIC)\js -I..\..\html\base\src -I$(PUBLIC)\netlib

View File

@ -26,6 +26,7 @@
#include "nsIWidget.h"
#include "nsIWebShell.h"
#include "nsIPresShell.h"
#include "nsDOMTextRange.h"
static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID);
static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID);
@ -50,10 +51,28 @@ nsDOMEvent::nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent) {
mEvent = aEvent;
mTarget = nsnull;
mText = nsnull;
mTextRange = nsnull;
if (aEvent->eventStructType ==NS_TEXT_EVENT) {
//
// extract the IME composition string
//
mText = new nsString(((nsTextEvent*)aEvent)->theText);
mCommitText = ((nsTextEvent*)aEvent)->commitText;
//
// build the range list -- ranges need to be DOM-ified since the IME transaction
// will hold a ref, the widget representation isn't persistent
//
nsIDOMTextRange** tempTextRangeList = new nsIDOMTextRange*[((nsTextEvent*)aEvent)->rangeCount];
for(PRUint16 i=0;i<((nsTextEvent*)aEvent)->rangeCount;i++) {
nsDOMTextRange* tempDOMTextRange = new nsDOMTextRange((((nsTextEvent*)aEvent)->rangeArray[i]).mStartOffset,
(((nsTextEvent*)aEvent)->rangeArray[i]).mEndOffset,
(((nsTextEvent*)aEvent)->rangeArray[i]).mRangeType);
tempDOMTextRange->AddRef();
tempTextRangeList[i] = (nsIDOMTextRange*)tempDOMTextRange;
}
mTextRange = (nsIDOMTextRangeList*) new nsDOMTextRangeList(((nsTextEvent*)aEvent)->rangeCount,tempTextRangeList);
mTextRange->AddRef();
}
NS_INIT_REFCNT();
@ -62,8 +81,10 @@ nsDOMEvent::nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent) {
nsDOMEvent::~nsDOMEvent() {
NS_RELEASE(mPresContext);
NS_IF_RELEASE(mTarget);
NS_IF_RELEASE(mTextRange);
delete mText;
if (mText!=nsnull)
delete mText;
}
NS_IMPL_ADDREF(nsDOMEvent)
@ -182,18 +203,18 @@ NS_METHOD nsDOMEvent::GetText(nsString& aText)
return NS_ERROR_FAILURE;
}
NS_METHOD nsDOMEvent::GetCommitText(PRBool* aCommitText)
NS_METHOD nsDOMEvent::GetInputRange(nsIDOMTextRangeList** aInputRange)
{
if (mEvent->message == NS_TEXT_EVENT) {
*aCommitText = mCommitText;
*aInputRange = mTextRange;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_METHOD nsDOMEvent::SetCommitText(PRBool aCommitText)
{
NS_METHOD nsDOMEvent::SetInputRange(nsIDOMTextRangeList* aInputRange)
{
return NS_ERROR_FAILURE;
}

View File

@ -81,10 +81,11 @@ public:
NS_IMETHOD PreventDefault();
NS_IMETHOD GetText(nsString& aText);
NS_IMETHOD GetText(nsString& aText);
NS_IMETHOD GetCommitText(PRBool* aCommitText);
NS_IMETHOD SetCommitText(PRBool aCommitText);
NS_IMETHOD GetInputRange(nsIDOMTextRangeList** aInputRange);
NS_IMETHOD SetInputRange(nsIDOMTextRangeList* aInputRange);
NS_IMETHOD GetScreenX(PRInt32* aScreenX);
@ -135,7 +136,7 @@ protected:
nsIPresContext* mPresContext;
nsIDOMNode* mTarget;
nsString* mText;
PRBool mCommitText;
nsIDOMTextRangeList* mTextRange;
const char* GetEventName(PRUint32 aEventType);
};

View File

@ -43,6 +43,8 @@ EXPORTS = \
nsIDOMEventTarget.h \
nsIDOMTextListener.h \
nsIDOMCompositionListener.h \
nsIDOMTextRange.h \
nsIDOMTextRangeList.h \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))

View File

@ -38,6 +38,8 @@ EXPORTS = \
nsIDOMEventTarget.h \
nsIDOMTextListener.h \
nsIDOMCompositionListener.h \
nsIDOMTextRange.h \
nsIDOMTextRangeList.h \
$(NULL)
MODULE=dom

View File

@ -0,0 +1,76 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* AUTO-GENERATED. DO NOT EDIT!!! */
#ifndef nsIDOMTextRange_h__
#define nsIDOMTextRange_h__
#include "nsISupports.h"
#include "nsString.h"
#include "nsIScriptContext.h"
#define NS_IDOMTEXTRANGE_IID \
{0xb471ab41, 0x2a79, 0x11d3, \
{ 0x9e, 0xa4, 0x0, 0x60, 0x8, 0x9f, 0xe5, 0x9b } }
class nsIDOMTextRange : public nsISupports {
public:
static const nsIID& GetIID() { static nsIID iid = NS_IDOMTEXTRANGE_IID; return iid; }
enum {
TEXTRANGE_RAWINPUT = 1,
TEXTRANGE_SELECTEDRAWTEXT = 2,
TEXTRANGE_CONVERTEDTEXT = 3,
TEXTRANGE_SELECTEDCONVERTEDTEXT = 4
};
NS_IMETHOD GetRangeStart(PRUint16* aRangeStart)=0;
NS_IMETHOD SetRangeStart(PRUint16 aRangeStart)=0;
NS_IMETHOD GetRangeEnd(PRUint16* aRangeEnd)=0;
NS_IMETHOD SetRangeEnd(PRUint16 aRangeEnd)=0;
NS_IMETHOD GetRangeType(PRUint16* aRangeType)=0;
NS_IMETHOD SetRangeType(PRUint16 aRangeType)=0;
};
#define NS_DECL_IDOMTEXTRANGE \
NS_IMETHOD GetRangeStart(PRUint16* aRangeStart); \
NS_IMETHOD SetRangeStart(PRUint16 aRangeStart); \
NS_IMETHOD GetRangeEnd(PRUint16* aRangeEnd); \
NS_IMETHOD SetRangeEnd(PRUint16 aRangeEnd); \
NS_IMETHOD GetRangeType(PRUint16* aRangeType); \
NS_IMETHOD SetRangeType(PRUint16 aRangeType); \
#define NS_FORWARD_IDOMTEXTRANGE(_to) \
NS_IMETHOD GetRangeStart(PRUint16* aRangeStart) { return _to GetRangeStart(aRangeStart); } \
NS_IMETHOD SetRangeStart(PRUint16 aRangeStart) { return _to SetRangeStart(aRangeStart); } \
NS_IMETHOD GetRangeEnd(PRUint16* aRangeEnd) { return _to GetRangeEnd(aRangeEnd); } \
NS_IMETHOD SetRangeEnd(PRUint16 aRangeEnd) { return _to SetRangeEnd(aRangeEnd); } \
NS_IMETHOD GetRangeType(PRUint16* aRangeType) { return _to GetRangeType(aRangeType); } \
NS_IMETHOD SetRangeType(PRUint16 aRangeType) { return _to SetRangeType(aRangeType); } \
extern "C" NS_DOM nsresult NS_InitTextRangeClass(nsIScriptContext *aContext, void **aPrototype);
extern "C" NS_DOM nsresult NS_NewScriptTextRange(nsIScriptContext *aContext, nsISupports *aSupports, nsISupports *aParent, void **aReturn);
#endif // nsIDOMTextRange_h__

View File

@ -0,0 +1,54 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* AUTO-GENERATED. DO NOT EDIT!!! */
#ifndef nsIDOMTextRangeList_h__
#define nsIDOMTextRangeList_h__
#include "nsISupports.h"
#include "nsString.h"
#include "nsIScriptContext.h"
class nsIDOMTextRange;
#define NS_IDOMTEXTRANGELIST_IID \
{ 0x1ee9d531, 0x2a79, 0x11d3, \
{ 0x9e, 0xa4, 0x0, 0x60, 0x8, 0x9f, 0xe5, 0x9b} }
class nsIDOMTextRangeList : public nsISupports {
public:
static const nsIID& GetIID() { static nsIID iid = NS_IDOMTEXTRANGELIST_IID; return iid; }
NS_IMETHOD GetLength(PRUint16* aLength)=0;
NS_IMETHOD Item(PRUint16 aIndex, nsIDOMTextRange** aReturn)=0;
};
#define NS_DECL_IDOMTEXTRANGELIST \
NS_IMETHOD GetLength(PRUint16* aLength); \
NS_IMETHOD Item(PRUint16 aIndex, nsIDOMTextRange** aReturn); \
#define NS_FORWARD_IDOMTEXTRANGELIST(_to) \
NS_IMETHOD GetLength(PRUint16* aLength) { return _to GetLength(aLength); } \
NS_IMETHOD Item(PRUint16 aIndex, nsIDOMTextRange** aReturn) { return _to Item(aIndex, aReturn); } \
#endif // nsIDOMTextRangeList_h__

View File

@ -25,6 +25,7 @@
#include "nsIScriptContext.h"
#include "nsIDOMEvent.h"
class nsIDOMTextRangeList;
#define NS_IDOMUIEVENT_IID \
{ 0xa6cf90c3, 0x15b3, 0x11d2, \
@ -150,8 +151,8 @@ public:
NS_IMETHOD GetText(nsString& aText)=0;
NS_IMETHOD GetCommitText(PRBool* aCommitText)=0;
NS_IMETHOD SetCommitText(PRBool aCommitText)=0;
NS_IMETHOD GetInputRange(nsIDOMTextRangeList** aInputRange)=0;
NS_IMETHOD SetInputRange(nsIDOMTextRangeList* aInputRange)=0;
NS_IMETHOD GetScreenX(PRInt32* aScreenX)=0;
@ -179,8 +180,8 @@ public:
#define NS_DECL_IDOMUIEVENT \
NS_IMETHOD GetText(nsString& aText); \
NS_IMETHOD GetCommitText(PRBool* aCommitText); \
NS_IMETHOD SetCommitText(PRBool aCommitText); \
NS_IMETHOD GetInputRange(nsIDOMTextRangeList** aInputRange); \
NS_IMETHOD SetInputRange(nsIDOMTextRangeList* aInputRange); \
NS_IMETHOD GetScreenX(PRInt32* aScreenX); \
NS_IMETHOD GetScreenY(PRInt32* aScreenY); \
NS_IMETHOD GetClientX(PRInt32* aClientX); \
@ -197,8 +198,8 @@ public:
#define NS_FORWARD_IDOMUIEVENT(_to) \
NS_IMETHOD GetText(nsString& aText) { return _to GetText(aText); } \
NS_IMETHOD GetCommitText(PRBool* aCommitText) { return _to GetCommitText(aCommitText); } \
NS_IMETHOD SetCommitText(PRBool aCommitText) { return _to SetCommitText(aCommitText); } \
NS_IMETHOD GetInputRange(nsIDOMTextRangeList** aInputRange) { return _to GetInputRange(aInputRange); } \
NS_IMETHOD SetInputRange(nsIDOMTextRangeList* aInputRange) { return _to SetInputRange(aInputRange); } \
NS_IMETHOD GetScreenX(PRInt32* aScreenX) { return _to GetScreenX(aScreenX); } \
NS_IMETHOD GetScreenY(PRInt32* aScreenY) { return _to GetScreenY(aScreenY); } \
NS_IMETHOD GetClientX(PRInt32* aClientX) { return _to GetClientX(aClientX); } \

View File

@ -0,0 +1,19 @@
interface TextRange {
/* IID: {0xb471ab41, 0x2a79, 0x11d3, \
{ 0x9e, 0xa4, 0x0, 0x60, 0x8, 0x9f, 0xe5, 0x9b } } */
const int TEXTRANGE_RAWINPUT = 1;
const int TEXTRANGE_SELECTEDRAWTEXT = 2;
const int TEXTRANGE_CONVERTEDTEXT = 3;
const int TEXTRANGE_SELECTEDCONVERTEDTEXT = 4;
attribute unsigned short rangeStart;
attribute unsigned short rangeEnd;
attribute unsigned short rangeType;
};
interface TextRangeList {
/* IID: { 0x1ee9d531, 0x2a79, 0x11d3, \
{ 0x9e, 0xa4, 0x0, 0x60, 0x8, 0x9f, 0xe5, 0x9b} } */
readonly attribute unsigned short length;
TextRange Item(in unsigned short index);
};

View File

@ -124,7 +124,7 @@
const int VK_QUOTE = 0xDE;
readonly attribute wstring text;
attribute boolean commitText;
attribute TextRangeList inputRange;
readonly attribute int screenX;
readonly attribute int screenY;

View File

@ -23,6 +23,7 @@ MODULE=raptor
IDLSRCS = \
Event.idl \
UIEvent.idl \
TextRange.idl
XPCOM_DESTDIR=$(DEPTH)\dom\public\coreEvents
JSSTUB_DESTDIR=$(DEPTH)\dom\src\events

View File

@ -31,6 +31,7 @@ CPPSRCS = \
nsJSDOMEventListener.cpp \
nsJSEvent.cpp \
nsJSUIEvent.cpp \
nsJSTextRange.cpp \
$(NULL)
MODULE=dom

View File

@ -29,6 +29,7 @@ CPPSRCS = \
nsJSDOMEventListener.cpp \
nsJSEvent.cpp \
nsJSUIEvent.cpp \
nsJSTextRange.cpp \
$(NULL)
CPP_OBJS= \

View File

@ -0,0 +1,512 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* AUTO-GENERATED. DO NOT EDIT!!! */
#include "jsapi.h"
#include "nsJSUtils.h"
#include "nscore.h"
#include "nsIScriptContext.h"
#include "nsIScriptSecurityManager.h"
#include "nsIJSScriptObject.h"
#include "nsIScriptObjectOwner.h"
#include "nsIScriptGlobalObject.h"
#include "nsIPtr.h"
#include "nsString.h"
#include "nsIDOMTextRange.h"
#include "nsIDOMTextRangeList.h"
static NS_DEFINE_IID(kIScriptObjectOwnerIID, NS_ISCRIPTOBJECTOWNER_IID);
static NS_DEFINE_IID(kIJSScriptObjectIID, NS_IJSSCRIPTOBJECT_IID);
static NS_DEFINE_IID(kIScriptGlobalObjectIID, NS_ISCRIPTGLOBALOBJECT_IID);
static NS_DEFINE_IID(kITextRangeIID, NS_IDOMTEXTRANGE_IID);
static NS_DEFINE_IID(kITextRangeListIID, NS_IDOMTEXTRANGELIST_IID);
NS_DEF_PTR(nsIDOMTextRange);
NS_DEF_PTR(nsIDOMTextRangeList);
//
// TextRange property ids
//
enum TextRange_slots {
TEXTRANGE_RANGESTART = -1,
TEXTRANGE_RANGEEND = -2,
TEXTRANGE_RANGETYPE = -3,
TEXTRANGELIST_LENGTH = -4
};
/***********************************************************************/
//
// TextRange Properties Getter
//
PR_STATIC_CALLBACK(JSBool)
GetTextRangeProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
nsIDOMTextRange *a = (nsIDOMTextRange*)nsJSUtils::nsGetNativeThis(cx, obj);
// If there's no private data, this must be the prototype, so ignore
if (nsnull == a) {
return JS_TRUE;
}
if (JSVAL_IS_INT(id)) {
nsIScriptContext *scriptCX = (nsIScriptContext *)JS_GetContextPrivate(cx);
nsIScriptSecurityManager *secMan;
PRBool ok = PR_FALSE;
if (NS_OK != scriptCX->GetSecurityManager(&secMan)) {
return JS_FALSE;
}
switch(JSVAL_TO_INT(id)) {
case TEXTRANGE_RANGESTART:
{
secMan->CheckScriptAccess(scriptCX, obj, "textrange.rangestart", &ok);
if (!ok) {
//Need to throw error here
return JS_FALSE;
}
PRUint16 prop;
if (NS_OK == a->GetRangeStart(&prop)) {
*vp = INT_TO_JSVAL(prop);
}
else {
return JS_FALSE;
}
break;
}
case TEXTRANGE_RANGEEND:
{
secMan->CheckScriptAccess(scriptCX, obj, "textrange.rangeend", &ok);
if (!ok) {
//Need to throw error here
return JS_FALSE;
}
PRUint16 prop;
if (NS_OK == a->GetRangeEnd(&prop)) {
*vp = INT_TO_JSVAL(prop);
}
else {
return JS_FALSE;
}
break;
}
case TEXTRANGE_RANGETYPE:
{
secMan->CheckScriptAccess(scriptCX, obj, "textrange.rangetype", &ok);
if (!ok) {
//Need to throw error here
return JS_FALSE;
}
PRUint16 prop;
if (NS_OK == a->GetRangeType(&prop)) {
*vp = INT_TO_JSVAL(prop);
}
else {
return JS_FALSE;
}
break;
}
case TEXTRANGELIST_LENGTH:
{
secMan->CheckScriptAccess(scriptCX, obj, "textrangelist.length", &ok);
if (!ok) {
//Need to throw error here
return JS_FALSE;
}
PRUint16 prop;
nsIDOMTextRangeList* b;
if (NS_OK == a->QueryInterface(kITextRangeListIID, (void **)&b)) {
if(NS_OK == b->GetLength(&prop)) {
*vp = INT_TO_JSVAL(prop);
NS_RELEASE(b);
}
else {
NS_RELEASE(b);
return JS_FALSE;
}
}
else {
JS_ReportError(cx, "Object must be of type TextRangeList");
return JS_FALSE;
}
break;
}
default:
return nsJSUtils::nsCallJSScriptObjectGetProperty(a, cx, id, vp);
}
NS_RELEASE(secMan);
}
else {
return nsJSUtils::nsCallJSScriptObjectGetProperty(a, cx, id, vp);
}
return PR_TRUE;
}
/***********************************************************************/
//
// TextRange Properties Setter
//
PR_STATIC_CALLBACK(JSBool)
SetTextRangeProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
nsIDOMTextRange *a = (nsIDOMTextRange*)nsJSUtils::nsGetNativeThis(cx, obj);
// If there's no private data, this must be the prototype, so ignore
if (nsnull == a) {
return JS_TRUE;
}
if (JSVAL_IS_INT(id)) {
nsIScriptContext *scriptCX = (nsIScriptContext *)JS_GetContextPrivate(cx);
nsIScriptSecurityManager *secMan;
PRBool ok = PR_FALSE;
if (NS_OK != scriptCX->GetSecurityManager(&secMan)) {
return JS_FALSE;
}
switch(JSVAL_TO_INT(id)) {
case TEXTRANGE_RANGESTART:
{
secMan->CheckScriptAccess(scriptCX, obj, "textrange.rangestart", &ok);
if (!ok) {
//Need to throw error here
return JS_FALSE;
}
PRUint16 prop;
int32 temp;
if (JSVAL_IS_NUMBER(*vp) && JS_ValueToInt32(cx, *vp, &temp)) {
prop = (PRUint16)temp;
}
else {
JS_ReportError(cx, "Parameter must be a number");
return JS_FALSE;
}
a->SetRangeStart(prop);
break;
}
case TEXTRANGE_RANGEEND:
{
secMan->CheckScriptAccess(scriptCX, obj, "textrange.rangeend", &ok);
if (!ok) {
//Need to throw error here
return JS_FALSE;
}
PRUint16 prop;
int32 temp;
if (JSVAL_IS_NUMBER(*vp) && JS_ValueToInt32(cx, *vp, &temp)) {
prop = (PRUint16)temp;
}
else {
JS_ReportError(cx, "Parameter must be a number");
return JS_FALSE;
}
a->SetRangeEnd(prop);
break;
}
case TEXTRANGE_RANGETYPE:
{
secMan->CheckScriptAccess(scriptCX, obj, "textrange.rangetype", &ok);
if (!ok) {
//Need to throw error here
return JS_FALSE;
}
PRUint16 prop;
int32 temp;
if (JSVAL_IS_NUMBER(*vp) && JS_ValueToInt32(cx, *vp, &temp)) {
prop = (PRUint16)temp;
}
else {
JS_ReportError(cx, "Parameter must be a number");
return JS_FALSE;
}
a->SetRangeType(prop);
break;
}
default:
return nsJSUtils::nsCallJSScriptObjectSetProperty(a, cx, id, vp);
}
NS_RELEASE(secMan);
}
else {
return nsJSUtils::nsCallJSScriptObjectSetProperty(a, cx, id, vp);
}
return PR_TRUE;
}
//
// TextRange finalizer
//
PR_STATIC_CALLBACK(void)
FinalizeTextRange(JSContext *cx, JSObject *obj)
{
nsJSUtils::nsGenericFinalize(cx, obj);
}
//
// TextRange enumerate
//
PR_STATIC_CALLBACK(JSBool)
EnumerateTextRange(JSContext *cx, JSObject *obj)
{
return nsJSUtils::nsGenericEnumerate(cx, obj);
}
//
// TextRange resolve
//
PR_STATIC_CALLBACK(JSBool)
ResolveTextRange(JSContext *cx, JSObject *obj, jsval id)
{
return nsJSUtils::nsGenericResolve(cx, obj, id);
}
//
// Native method Item
//
PR_STATIC_CALLBACK(JSBool)
TextRangeListItem(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
nsIDOMTextRange *privateThis = (nsIDOMTextRange*)nsJSUtils::nsGetNativeThis(cx, obj);
nsIDOMTextRangeList *nativeThis = nsnull;
if (NS_OK != privateThis->QueryInterface(kITextRangeListIID, (void **)&nativeThis)) {
JS_ReportError(cx, "Object must be of type TextRangeList");
return JS_FALSE;
}
JSBool rBool = JS_FALSE;
nsIDOMTextRange* nativeRet;
PRUint32 b0;
*rval = JSVAL_NULL;
nsIScriptContext *scriptCX = (nsIScriptContext *)JS_GetContextPrivate(cx);
nsIScriptSecurityManager *secMan;
if (NS_OK == scriptCX->GetSecurityManager(&secMan)) {
PRBool ok;
secMan->CheckScriptAccess(scriptCX, obj, "textrangelist.item", &ok);
if (!ok) {
//Need to throw error here
return JS_FALSE;
}
NS_RELEASE(secMan);
}
else {
return JS_FALSE;
}
// If there's no private data, this must be the prototype, so ignore
if (nsnull == nativeThis) {
return JS_TRUE;
}
if (argc >= 1) {
if (!JS_ValueToInt32(cx, argv[0], (int32 *)&b0)) {
JS_ReportError(cx, "Parameter must be a number");
return JS_FALSE;
}
if (NS_OK != nativeThis->Item(b0, &nativeRet)) {
return JS_FALSE;
}
nsJSUtils::nsConvertObjectToJSVal(nativeRet, cx, rval);
}
else {
JS_ReportError(cx, "Function Item requires 1 parameters");
return JS_FALSE;
}
return JS_TRUE;
}
/***********************************************************************/
//
// class for TextRange
//
JSClass TextRangeClass = {
"TextRange",
JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS,
JS_PropertyStub,
JS_PropertyStub,
GetTextRangeProperty,
SetTextRangeProperty,
EnumerateTextRange,
ResolveTextRange,
JS_ConvertStub,
FinalizeTextRange
};
//
// TextRange class properties
//
static JSPropertySpec TextRangeProperties[] =
{
{"rangeStart", TEXTRANGE_RANGESTART, JSPROP_ENUMERATE},
{"rangeEnd", TEXTRANGE_RANGEEND, JSPROP_ENUMERATE},
{"rangeType", TEXTRANGE_RANGETYPE, JSPROP_ENUMERATE},
{"length", TEXTRANGELIST_LENGTH, JSPROP_ENUMERATE | JSPROP_READONLY},
{0}
};
//
// TextRange class methods
//
static JSFunctionSpec TextRangeMethods[] =
{
{"Item", TextRangeListItem, 1},
{0}
};
//
// TextRange constructor
//
PR_STATIC_CALLBACK(JSBool)
TextRange(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
return JS_FALSE;
}
//
// TextRange class initialization
//
extern "C" NS_DOM nsresult NS_InitTextRangeClass(nsIScriptContext *aContext, void **aPrototype)
{
JSContext *jscontext = (JSContext *)aContext->GetNativeContext();
JSObject *proto = nsnull;
JSObject *constructor = nsnull;
JSObject *parent_proto = nsnull;
JSObject *global = JS_GetGlobalObject(jscontext);
jsval vp;
if ((PR_TRUE != JS_LookupProperty(jscontext, global, "TextRange", &vp)) ||
!JSVAL_IS_OBJECT(vp) ||
((constructor = JSVAL_TO_OBJECT(vp)) == nsnull) ||
(PR_TRUE != JS_LookupProperty(jscontext, JSVAL_TO_OBJECT(vp), "prototype", &vp)) ||
!JSVAL_IS_OBJECT(vp)) {
proto = JS_InitClass(jscontext, // context
global, // global object
parent_proto, // parent proto
&TextRangeClass, // JSClass
TextRange, // JSNative ctor
0, // ctor args
TextRangeProperties, // proto props
TextRangeMethods, // proto funcs
nsnull, // ctor props (static)
nsnull); // ctor funcs (static)
if (nsnull == proto) {
return NS_ERROR_FAILURE;
}
if ((PR_TRUE == JS_LookupProperty(jscontext, global, "TextRange", &vp)) &&
JSVAL_IS_OBJECT(vp) &&
((constructor = JSVAL_TO_OBJECT(vp)) != nsnull)) {
vp = INT_TO_JSVAL(nsIDOMTextRange::TEXTRANGE_RAWINPUT);
JS_SetProperty(jscontext, constructor, "TEXTRANGE_RAWINPUT", &vp);
vp = INT_TO_JSVAL(nsIDOMTextRange::TEXTRANGE_SELECTEDRAWTEXT);
JS_SetProperty(jscontext, constructor, "TEXTRANGE_SELECTEDRAWTEXT", &vp);
vp = INT_TO_JSVAL(nsIDOMTextRange::TEXTRANGE_CONVERTEDTEXT);
JS_SetProperty(jscontext, constructor, "TEXTRANGE_CONVERTEDTEXT", &vp);
vp = INT_TO_JSVAL(nsIDOMTextRange::TEXTRANGE_SELECTEDCONVERTEDTEXT);
JS_SetProperty(jscontext, constructor, "TEXTRANGE_SELECTEDCONVERTEDTEXT", &vp);
}
}
else if ((nsnull != constructor) && JSVAL_IS_OBJECT(vp)) {
proto = JSVAL_TO_OBJECT(vp);
}
else {
return NS_ERROR_FAILURE;
}
if (aPrototype) {
*aPrototype = proto;
}
return NS_OK;
}
//
// Method for creating a new TextRange JavaScript object
//
extern "C" NS_DOM nsresult NS_NewScriptTextRange(nsIScriptContext *aContext, nsISupports *aSupports, nsISupports *aParent, void **aReturn)
{
NS_PRECONDITION(nsnull != aContext && nsnull != aSupports && nsnull != aReturn, "null argument to NS_NewScriptTextRange");
JSObject *proto;
JSObject *parent;
nsIScriptObjectOwner *owner;
JSContext *jscontext = (JSContext *)aContext->GetNativeContext();
nsresult result = NS_OK;
nsIDOMTextRange *aTextRange;
if (nsnull == aParent) {
parent = nsnull;
}
else if (NS_OK == aParent->QueryInterface(kIScriptObjectOwnerIID, (void**)&owner)) {
if (NS_OK != owner->GetScriptObject(aContext, (void **)&parent)) {
NS_RELEASE(owner);
return NS_ERROR_FAILURE;
}
NS_RELEASE(owner);
}
else {
return NS_ERROR_FAILURE;
}
if (NS_OK != NS_InitTextRangeClass(aContext, (void **)&proto)) {
return NS_ERROR_FAILURE;
}
result = aSupports->QueryInterface(kITextRangeIID, (void **)&aTextRange);
if (NS_OK != result) {
return result;
}
// create a js object for this class
*aReturn = JS_NewObject(jscontext, &TextRangeClass, proto, parent);
if (nsnull != *aReturn) {
// connect the native object to the js object
JS_SetPrivate(jscontext, (JSObject *)*aReturn, aTextRange);
}
else {
NS_RELEASE(aTextRange);
return NS_ERROR_FAILURE;
}
return NS_OK;
}

View File

@ -30,6 +30,7 @@
#include "nsIDOMNSUIEvent.h"
#include "nsIDOMNode.h"
#include "nsIDOMUIEvent.h"
#include "nsIDOMTextRangeList.h"
#include "nsIDOMRenderingContext.h"
@ -39,11 +40,13 @@ static NS_DEFINE_IID(kIScriptGlobalObjectIID, NS_ISCRIPTGLOBALOBJECT_IID);
static NS_DEFINE_IID(kINSUIEventIID, NS_IDOMNSUIEVENT_IID);
static NS_DEFINE_IID(kINodeIID, NS_IDOMNODE_IID);
static NS_DEFINE_IID(kIUIEventIID, NS_IDOMUIEVENT_IID);
static NS_DEFINE_IID(kITextRangeListIID, NS_IDOMTEXTRANGELIST_IID);
static NS_DEFINE_IID(kIRenderingContextIID, NS_IDOMRENDERINGCONTEXT_IID);
NS_DEF_PTR(nsIDOMNSUIEvent);
NS_DEF_PTR(nsIDOMNode);
NS_DEF_PTR(nsIDOMUIEvent);
NS_DEF_PTR(nsIDOMTextRangeList);
NS_DEF_PTR(nsIDOMRenderingContext);
//
@ -51,7 +54,7 @@ NS_DEF_PTR(nsIDOMRenderingContext);
//
enum UIEvent_slots {
UIEVENT_TEXT = -1,
UIEVENT_COMMITTEXT = -2,
UIEVENT_INPUTRANGE = -2,
UIEVENT_SCREENX = -3,
UIEVENT_SCREENY = -4,
UIEVENT_CLIENTX = -5,
@ -111,16 +114,17 @@ GetUIEventProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
}
break;
}
case UIEVENT_COMMITTEXT:
case UIEVENT_INPUTRANGE:
{
secMan->CheckScriptAccess(scriptCX, obj, "uievent.committext", &ok);
secMan->CheckScriptAccess(scriptCX, obj, "uievent.inputrange", &ok);
if (!ok) {
//Need to throw error here
return JS_FALSE;
}
PRBool prop;
if (NS_OK == a->GetCommitText(&prop)) {
*vp = BOOLEAN_TO_JSVAL(prop);
nsIDOMTextRangeList* prop;
if (NS_OK == a->GetInputRange(&prop)) {
// get the js object
nsJSUtils::nsConvertObjectToJSVal((nsISupports *)prop, cx, vp);
}
else {
return JS_FALSE;
@ -539,20 +543,22 @@ SetUIEventProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
return JS_FALSE;
}
switch(JSVAL_TO_INT(id)) {
case UIEVENT_COMMITTEXT:
case UIEVENT_INPUTRANGE:
{
secMan->CheckScriptAccess(scriptCX, obj, "uievent.committext", &ok);
secMan->CheckScriptAccess(scriptCX, obj, "uievent.inputrange", &ok);
if (!ok) {
//Need to throw error here
return JS_FALSE;
}
PRBool prop;
if (PR_FALSE == nsJSUtils::nsConvertJSValToBool(&prop, cx, *vp)) {
nsIDOMTextRangeList* prop;
if (PR_FALSE == nsJSUtils::nsConvertJSValToObject((nsISupports **)&prop,
kITextRangeListIID, "TextRangeList",
cx, *vp)) {
return JS_FALSE;
}
a->SetCommitText(prop);
a->SetInputRange(prop);
NS_IF_RELEASE(prop);
break;
}
default:
@ -622,7 +628,7 @@ JSClass UIEventClass = {
static JSPropertySpec UIEventProperties[] =
{
{"text", UIEVENT_TEXT, JSPROP_ENUMERATE | JSPROP_READONLY},
{"commitText", UIEVENT_COMMITTEXT, JSPROP_ENUMERATE},
{"inputRange", UIEVENT_INPUTRANGE, JSPROP_ENUMERATE},
{"screenX", UIEVENT_SCREENX, JSPROP_ENUMERATE | JSPROP_READONLY},
{"screenY", UIEVENT_SCREENY, JSPROP_ENUMERATE | JSPROP_READONLY},
{"clientX", UIEVENT_CLIENTX, JSPROP_ENUMERATE | JSPROP_READONLY},

View File

@ -0,0 +1,114 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "IMECommitTxn.h"
#include "nsEditor.h"
static NS_DEFINE_IID(kIMECommitTxnIID, IME_COMMIT_TXN_IID);
nsIAtom *IMECommitTxn::gIMECommitTxnName = nsnull;
nsresult IMECommitTxn::ClassInit()
{
if (nsnull==gIMECommitTxnName)
gIMECommitTxnName = NS_NewAtom("NS_IMECommitTxn");
return NS_OK;
}
IMECommitTxn::IMECommitTxn()
: EditTxn()
{
}
IMECommitTxn::~IMECommitTxn()
{
}
NS_IMETHODIMP IMECommitTxn::Init(void)
{
return NS_OK;
}
NS_IMETHODIMP IMECommitTxn::Do(void)
{
#ifdef DEBUG_TAGUE
printf("Do IME Commit); }
#endif
return NS_OK;
}
NS_IMETHODIMP IMECommitTxn::Undo(void)
{
#ifdef DEBUG_TAGUE
printf("Undo IME Commit");
#endif
return NS_OK;
}
NS_IMETHODIMP IMECommitTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
#ifdef DEBUG_TAGUE
printf("Merge IME Commit");
#endif
*aDidMerge=PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP IMECommitTxn::Write(nsIOutputStream *aOutputStream)
{
return NS_OK;
}
NS_IMETHODIMP IMECommitTxn::GetUndoString(nsString *aString)
{
if (nsnull!=aString)
{
*aString="Remove IMECommit: ";
}
return NS_OK;
}
NS_IMETHODIMP IMECommitTxn::GetRedoString(nsString *aString)
{
if (nsnull!=aString)
{
*aString="Insert IMECommit: ";
}
return NS_OK;
}
/* ============= nsISupports implementation ====================== */
NS_IMETHODIMP
IMECommitTxn::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (nsnull == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(kIMECommitTxnIID)) {
*aInstancePtr = (void*)(IMECommitTxn*)this;
NS_ADDREF_THIS();
return NS_OK;
}
return (EditTxn::QueryInterface(aIID, aInstancePtr));
}

View File

@ -0,0 +1,82 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef IMECommitTxn_h__
#define IMECommitTxn_h__
#include "EditTxn.h"
#include "nsIDOMCharacterData.h"
#include "nsCOMPtr.h"
// {9C4994A1-281C-11d3-9EA3-0060089FE59B}
#define IME_COMMIT_TXN_IID \
{ 0x9c4994a1, 0x281c, 0x11d3, \
{ 0x9e, 0xa3, 0x0, 0x60, 0x8, 0x9f, 0xe5, 0x9b }}
/**
* A transaction representing an IME commit operation
*/
class IMECommitTxn : public EditTxn
{
public:
virtual ~IMECommitTxn();
static nsIAtom *gIMECommitTxnName;
/** initialize the transaction
*/
NS_IMETHOD Init(void);
private:
IMECommitTxn();
public:
NS_IMETHOD Do(void);
NS_IMETHOD Undo(void);
NS_IMETHOD Merge(PRBool *aDidMerge, nsITransaction *aTransaction);
NS_IMETHOD Write(nsIOutputStream *aOutputStream);
NS_IMETHOD GetUndoString(nsString *aString);
NS_IMETHOD GetRedoString(nsString *aString);
// nsISupports declarations
// override QueryInterface to handle IMECommitTxn request
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
static const nsIID& GetIID() { static nsIID iid = IME_COMMIT_TXN_IID; return iid; }
/** must be called before any IMECommitTxn is instantiated */
static nsresult ClassInit();
protected:
friend class TransactionFactory;
friend class nsDerivedSafe<IMECommitTxn>; // work around for a compiler bug
};
#endif

View File

@ -0,0 +1,296 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "IMETextTxn.h"
#include "IMECommitTxn.h"
#include "nsEditor.h"
#include "nsIDOMCharacterData.h"
#include "nsIDOMTextRange.h"
#include "nsIDOMTextRangeList.h"
#include "nsIDOMSelection.h"
#include "nsIPresShell.h"
#include "EditAggregateTxn.h"
static NS_DEFINE_IID(kIMETextTxnIID, IME_TEXT_TXN_IID);
static NS_DEFINE_IID(kIDOMSelectionIID, NS_IDOMSELECTION_IID);
nsIAtom *IMETextTxn::gIMETextTxnName = nsnull;
nsresult IMETextTxn::ClassInit()
{
if (nsnull==gIMETextTxnName)
gIMETextTxnName = NS_NewAtom("NS_IMETextTxn");
return NS_OK;
}
IMETextTxn::IMETextTxn()
: EditTxn()
{
}
IMETextTxn::~IMETextTxn()
{
mRangeList = do_QueryInterface(nsnull);
}
NS_IMETHODIMP IMETextTxn::Init(nsIDOMCharacterData *aElement,
PRUint32 aOffset,
PRUint32 aReplaceLength,
nsIDOMTextRangeList* aTextRangeList,
const nsString &aStringToInsert,
nsIPresShell *aPresShell)
{
mElement = do_QueryInterface(aElement);
mOffset = aOffset;
mReplaceLength = aReplaceLength;
mStringToInsert = aStringToInsert;
mPresShell = aPresShell;
mRangeList = do_QueryInterface(aTextRangeList);
mFixed = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP IMETextTxn::Do(void)
{
#ifdef DEBUG_TAGUE
printf("Do IME Text element = %p\n", mElement.get());
#endif
// advance caret: This requires the presentation shell to get the selection.
nsCOMPtr<nsIDOMSelection> selection;
nsresult result = mPresShell->GetSelection(getter_AddRefs(selection));
NS_ASSERTION(selection,"Could not get selection in IMEtextTxn::Do\n");
if (NS_SUCCEEDED(result) && selection) {
if (mReplaceLength==0) {
result = mElement->InsertData(mOffset,mStringToInsert);
} else {
result = mElement->ReplaceData(mOffset,mReplaceLength,mStringToInsert);
}
if (NS_SUCCEEDED(result)) {
result = CollapseTextSelection();
}
}
return result;
}
NS_IMETHODIMP IMETextTxn::Undo(void)
{
#ifdef DEBUG_TAGUE
printf("Undo IME Text element = %p\n", mElement.get());
#endif
nsresult result;
PRUint32 length = mStringToInsert.Length();
result = mElement->DeleteData(mOffset, length);
if (NS_SUCCEEDED(result))
{ // set the selection to the insertion point where the string was removed
nsCOMPtr<nsIDOMSelection> selection;
result = mPresShell->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(result) && selection) {
result = selection->Collapse(mElement, mOffset);
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of IME insert.");
}
}
return result;
}
NS_IMETHODIMP IMETextTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
#ifdef DEBUG_TAGUE
printf("Merge IME Text element = %p\n", mElement.get());
#endif
//
// check to make sure we have valid return pointers
//
if ((nsnull==aDidMerge) && (nsnull==aTransaction))
{
return NS_OK;
}
//
// check to make sure we aren't fixed, if we are then nothing get's absorbed
//
if (mFixed) {
*aDidMerge = PR_FALSE;
return NS_OK;
}
//
// if aTransaction is another IMETextTxn then absorbe it
//
nsCOMPtr<IMETextTxn> otherTxn(do_QueryInterface(aTransaction));
if (otherTxn)
{
//
// we absorbe the next IME transaction by adopting it's insert string as our own
//
nsIDOMTextRangeList* newTextRangeList;
otherTxn->GetData(mStringToInsert,&newTextRangeList);
mRangeList = do_QueryInterface(newTextRangeList);
*aDidMerge = PR_TRUE;
#ifdef DEBUG_TAGUE
printf("IMETextTxn assimilated IMETextTxn:%p\n", aTransaction);
#endif
return NS_OK;
}
//
// second possible case is that we have a commit transaction
//
nsCOMPtr<IMECommitTxn> commitTxn(do_QueryInterface(aTransaction));
if (commitTxn)
{
(void)CollapseTextSelectionOnCommit();
mFixed = PR_TRUE;
*aDidMerge = PR_TRUE; // absorbe the commit transaction
#ifdef DEBUG_TAGUE
printf("IMETextTxn assimilated IMECommitTxn%p\n", aTransaction);
#endif
return NS_OK;
}
*aDidMerge = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP IMETextTxn::Write(nsIOutputStream *aOutputStream)
{
return NS_OK;
}
NS_IMETHODIMP IMETextTxn::GetUndoString(nsString *aString)
{
if (nsnull!=aString)
{
*aString="Remove Text: ";
*aString += mStringToInsert;
}
return NS_OK;
}
NS_IMETHODIMP IMETextTxn::GetRedoString(nsString *aString)
{
if (nsnull!=aString)
{
*aString="Insert Text: ";
*aString += mStringToInsert;
}
return NS_OK;
}
/* ============= nsISupports implementation ====================== */
NS_IMETHODIMP
IMETextTxn::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (nsnull == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(kIMETextTxnIID)) {
*aInstancePtr = (void*)(IMETextTxn*)this;
NS_ADDREF_THIS();
return NS_OK;
}
return (EditTxn::QueryInterface(aIID, aInstancePtr));
}
/* ============ protected methods ================== */
NS_IMETHODIMP IMETextTxn::GetData(nsString& aResult,nsIDOMTextRangeList** aTextRangeList)
{
aResult = mStringToInsert;
*aTextRangeList = mRangeList;
return NS_OK;
}
NS_IMETHODIMP IMETextTxn::CollapseTextSelection(void)
{
nsresult result;
PRBool haveSelectedRange;
PRUint16 textRangeListLength,selectionStart,selectionEnd,
textRangeType, i;
nsIDOMTextRange* textRange;
haveSelectedRange = PR_FALSE;
#ifdef DEBUG_tague
PRUint16 listlen,start,stop,type;
nsIDOMTextRange* rangePtr;
result = mRangeList->GetLength(&listlen);
printf("nsIDOMTextRangeList[%p]\n",mRangeList);
for (i=0;i<listlen;i++) {
(void)mRangeList->Item(i,&rangePtr);
rangePtr->GetRangeStart(&start);
rangePtr->GetRangeEnd(&stop);
rangePtr->GetRangeType(&type);
printf("range[%d] start=%d end=%d type=",i,start,stop,type);
if (type==nsIDOMTextRange::TEXTRANGE_RAWINPUT) printf("TEXTRANGE_RAWINPUT\n");
if (type==nsIDOMTextRange::TEXTRANGE_SELECTEDRAWTEXT) printf("TEXTRANGE_SELECTEDRAWTEXT\n");
if (type==nsIDOMTextRange::TEXTRANGE_CONVERTEDTEXT) printf("TEXTRANGE_CONVERTEDTEXT\n");
if (type==nsIDOMTextRange::TEXTRANGE_SELECTEDCONVERTEDTEXT) printf("TEXTRANGE_SELECTEDCONVERTEDTEXT\n");
}
#endif
//
// run through the text range list
//
result = mRangeList->GetLength(&textRangeListLength);
if (NS_SUCCEEDED(result))
{
for(i=0;i<textRangeListLength;i++) {
result = mRangeList->Item(i,&textRange);
if (NS_SUCCEEDED(result))
{
result = textRange->GetRangeType(&textRangeType);
if (textRangeType==nsIDOMTextRange::TEXTRANGE_SELECTEDCONVERTEDTEXT)
{
haveSelectedRange = PR_TRUE;
textRange->GetRangeStart(&selectionStart);
textRange->GetRangeEnd(&selectionEnd);
}
}
}
}
nsCOMPtr<nsIDOMSelection> selection;
result = mPresShell->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(result) && selection){
if (haveSelectedRange) {
result = selection->Collapse(mElement,mOffset+selectionStart);
result = selection->Extend(mElement,mOffset+selectionEnd+1);
} else {
result = selection->Collapse(mElement,mOffset+mStringToInsert.Length());
}
}
return result;
}
NS_IMETHODIMP IMETextTxn::CollapseTextSelectionOnCommit(void)
{
nsCOMPtr<nsIDOMSelection> selection;
nsresult result = mPresShell->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(result) && selection){
result = selection->Collapse(mElement,mOffset+mStringToInsert.Length());
}
return result;
}

View File

@ -0,0 +1,126 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef IMETextTxn_h__
#define IMETextTxn_h__
#include "EditTxn.h"
#include "nsIDOMCharacterData.h"
#include "nsIDOMTextRangeList.h"
#include "nsCOMPtr.h"
// {D4D25721-2813-11d3-9EA3-0060089FE59B}
#define IME_TEXT_TXN_IID \
{0xd4d25721, 0x2813, 0x11d3, \
{0x9e, 0xa3, 0x0, 0x60, 0x8, 0x9f, 0xe5, 0x9b }}
class nsIPresShell;
/**
* A transaction that inserts text into a content node.
*/
class IMETextTxn : public EditTxn
{
public:
virtual ~IMETextTxn();
/** used to name aggregate transactions that consist only of a single IMETextTxn,
* or a DeleteSelection followed by an IMETextTxn.
*/
static nsIAtom *gIMETextTxnName;
/** initialize the transaction
* @param aElement the text content node
* @param aOffset the location in aElement to do the insertion
* @param aReplaceLength the length of text to replace (0= no replacement)
* @param aString the new text to insert
* @param aPresShell used to get and set the selection
*/
NS_IMETHOD Init(nsIDOMCharacterData *aElement,
PRUint32 aOffset,
PRUint32 aReplaceLength,
nsIDOMTextRangeList* aTextRangeList,
const nsString& aString,
nsIPresShell* aPresShell);
private:
IMETextTxn();
public:
NS_IMETHOD Do(void);
NS_IMETHOD Undo(void);
NS_IMETHOD Merge(PRBool *aDidMerge, nsITransaction *aTransaction);
NS_IMETHOD Write(nsIOutputStream *aOutputStream);
NS_IMETHOD GetUndoString(nsString *aString);
NS_IMETHOD GetRedoString(nsString *aString);
// nsISupports declarations
// override QueryInterface to handle IMETextTxn request
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
static const nsIID& GetIID() { static nsIID iid = IME_TEXT_TXN_IID; return iid; }
/** return the string data associated with this transaction */
NS_IMETHOD GetData(nsString& aResult, nsIDOMTextRangeList** aTextRangeList);
/** must be called before any IMETextTxn is instantiated */
static nsresult ClassInit();
protected:
NS_IMETHOD CollapseTextSelection(void);
NS_IMETHOD CollapseTextSelectionOnCommit(void);
/** the text element to operate upon */
nsCOMPtr<nsIDOMCharacterData> mElement;
/** the offsets into mElement where the insertion should be placed*/
PRUint32 mOffset;
PRUint32 mReplaceLength;
/** the text to insert into mElement at mOffset */
nsString mStringToInsert;
/** the range list **/
nsCOMPtr<nsIDOMTextRangeList> mRangeList;
/** the presentation shell, which we'll need to get the selection */
nsIPresShell* mPresShell;
PRBool mFixed;
friend class TransactionFactory;
friend class nsDerivedSafe<IMETextTxn>; // work around for a compiler bug
};
#endif

View File

@ -25,6 +25,7 @@
static NS_DEFINE_IID(kInsertTextTxnIID, INSERT_TEXT_TXN_IID);
static NS_DEFINE_IID(kIDOMSelectionIID, NS_IDOMSELECTION_IID);
static NS_DEFINE_IID(kEditAggregateTxnIID, EDIT_AGGREGATE_TXN_IID);
#ifdef NS_DEBUG
static PRBool gNoisy = PR_FALSE;

View File

@ -67,6 +67,8 @@ CPPSRCS = \
nsEditorShellFactory.cpp \
nsJSEditorLog.cpp \
nsJSTxnLog.cpp \
IMETextTxn.cpp \
IMECommitTxn.cpp \
$(NULL)
MODULE = editor

View File

@ -39,7 +39,9 @@
#include "DeleteTableColumnTxn.h"
#include "DeleteTableRowTxn.h"
#include "JoinTableCellsTxn.h"
#include "IMETextTxn.h"
#include "IMECommitTxn.h"
static NS_DEFINE_IID(kEditAggregateTxnIID, EDIT_AGGREGATE_TXN_IID);
static NS_DEFINE_IID(kPlaceholderTxnIID, PLACEHOLDER_TXN_IID);
static NS_DEFINE_IID(kInsertTextTxnIID, INSERT_TEXT_TXN_IID);
@ -61,6 +63,8 @@ static NS_DEFINE_IID(kDeleteTableCellTxnIID, DELETE_CELL_TXN_IID);
static NS_DEFINE_IID(kDeleteTableColumnTxnIID, DELETE_COLUMN_TXN_IID);
static NS_DEFINE_IID(kDeleteTableRowTxnIID, DELETE_ROW_TXN_IID);
static NS_DEFINE_IID(kJoinTableCellsTxnIID, JOIN_CELLS_TXN_IID);
static NS_DEFINE_IID(kIMETextTxnIID, IME_TEXT_TXN_IID);
static NS_DEFINE_IID(kIMECommitTxnIID, IME_COMMIT_TXN_IID);
TransactionFactory::TransactionFactory()
{
@ -97,6 +101,10 @@ TransactionFactory::GetNewTransaction(REFNSIID aTxnType, EditTxn **aResult)
*aResult = new JoinElementTxn();
else if (aTxnType.Equals(kEditAggregateTxnIID))
*aResult = new EditAggregateTxn();
else if (aTxnType.Equals(kIMETextTxnIID))
*aResult = new IMETextTxn();
else if (aTxnType.Equals(kIMECommitTxnIID))
*aResult = new IMECommitTxn();
else if (aTxnType.Equals(kPlaceholderTxnIID))
*aResult = new PlaceholderTxn();
else

View File

@ -62,6 +62,8 @@ CPPSRCS = \
nsEditorShellFactory.cpp \
nsJSEditorLog.cpp \
nsJSTxnLog.cpp \
IMETextTxn.cpp \
IMECommitTxn.cpp \
$(NULL)
CPP_OBJS = \
@ -106,6 +108,8 @@ CPP_OBJS = \
.\$(OBJDIR)\nsEditorShellFactory.obj \
.\$(OBJDIR)\nsJSEditorLog.obj \
.\$(OBJDIR)\nsJSTxnLog.obj \
.\$(OBJDIR)\IMETextTxn.obj \
.\$(OBJDIR)\IMECommitTxn.obj \
$(NULL)
MODULE=editor

View File

@ -84,6 +84,8 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "SplitElementTxn.h"
#include "JoinElementTxn.h"
#include "nsIStringStream.h"
#include "IMETextTxn.h"
#include "IMECommitTxn.h"
// #define HACK_FORCE_REDRAW 1
@ -128,6 +130,8 @@ static NS_DEFINE_IID(kDeleteRangeTxnIID, DELETE_RANGE_TXN_IID);
static NS_DEFINE_IID(kChangeAttributeTxnIID,CHANGE_ATTRIBUTE_TXN_IID);
static NS_DEFINE_IID(kSplitElementTxnIID, SPLIT_ELEMENT_TXN_IID);
static NS_DEFINE_IID(kJoinElementTxnIID, JOIN_ELEMENT_TXN_IID);
static NS_DEFINE_IID(kIMETextTxnIID, IME_TEXT_TXN_IID);
static NS_DEFINE_IID(kIMECommitTxnIID, IME_COMMIT_TXN_IID);
static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
static NS_DEFINE_CID(kCDOMRangeCID, NS_RANGE_CID);
@ -334,7 +338,6 @@ nsEditor::nsEditor()
{
//initialize member variables here
NS_INIT_REFCNT();
mIMEFirstTransaction=PR_FALSE;
PR_EnterMonitor(GetEditorMonitor());
gInstanceCount++;
mActionListeners = 0;
@ -519,6 +522,13 @@ nsEditor::Init(nsIDOMDocument *aDoc, nsIPresShell* aPresShell)
mUpdateCount=0;
InsertTextTxn::ClassInit();
/* initalize IME stuff */
IMETextTxn::ClassInit();
IMECommitTxn::ClassInit();
mIMETextNode = do_QueryInterface(nsnull);
mIMETextOffset = 0;
mIMEBufferLength = 0;
/* Show the caret */
nsCOMPtr<nsICaret> caret;
if (NS_SUCCEEDED(mPresShell->GetCaret(getter_AddRefs(caret))))
@ -3188,93 +3198,102 @@ NS_IMETHODIMP nsEditor::GetLayoutObject(nsIDOMNode *aNode, nsISupports **aLayout
return result;
}
//
// The BeingComposition method is called from the Editor Composition event listeners.
// It caches the current text node and offset which is subsequently used for the
// created of IMETextTxn's.
//
NS_IMETHODIMP
nsEditor::BeginComposition(void)
{
if ((nsITransactionManager *)nsnull!=mTxnMgr.get())
{
#ifdef DEBUG_tague
printf("nsEditor::StartComposition -- begin batch.\n");
printf("nsEditor::StartComposition\n");
#endif
mTxnMgr->BeginBatch();
}
if (!mIMESelectionRange)
{
nsresult result = nsComponentManager::CreateInstance(kCDOMRangeCID, nsnull,
nsIDOMRange::GetIID(),
getter_AddRefs(mIMESelectionRange));
if (NS_FAILED(result))
nsresult result;
PRInt32 offset;
nsCOMPtr<nsIDOMSelection> selection;
nsCOMPtr<nsIDOMCharacterData> nodeAsText;
result = mPresShell->GetSelection(getter_AddRefs(selection));
if ((NS_SUCCEEDED(result)) && selection)
{
mTxnMgr->EndBatch();
return result;
result = NS_ERROR_UNEXPECTED;
nsCOMPtr<nsIEnumerator> enumerator;
enumerator = do_QueryInterface(selection);
if (enumerator)
{
enumerator->First();
nsISupports *currentItem;
result = enumerator->CurrentItem(&currentItem);
if ((NS_SUCCEEDED(result)) && (nsnull!=currentItem))
{
result = NS_ERROR_UNEXPECTED;
nsCOMPtr<nsIDOMRange> range(do_QueryInterface(currentItem));
if (range)
{
nsCOMPtr<nsIDOMNode> node;
result = range->GetStartParent(getter_AddRefs(node));
if ((NS_SUCCEEDED(result)) && (node))
{
nodeAsText = do_QueryInterface(node);
range->GetStartOffset(&offset);
if (!nodeAsText) {
result = NS_ERROR_EDITOR_NO_TEXTNODE;
}
}
}
}
else
{
result = NS_ERROR_EDITOR_NO_SELECTION;
}
}
}
}
mIMEFirstTransaction=PR_TRUE;
return NS_OK;
if (NS_SUCCEEDED(result) && nodeAsText)
{
//
// store the information needed to construct IME transactions for this composition
//
mIMETextNode = nodeAsText;
mIMETextOffset = offset;
mIMEBufferLength = 0;
}
return result;
}
NS_IMETHODIMP
nsEditor::EndComposition(void)
{
if ((nsITransactionManager *)nsnull!=mTxnMgr.get())
{
#ifdef DEBUG_tague
printf("nsEditor::EndComposition -- end batch.\n");
#endif
mTxnMgr->EndBatch();
mIMEFirstTransaction=PR_TRUE;
return NS_OK;
}
nsresult result;
IMECommitTxn *commitTxn;
//
// create the commit transaction..we can do it directly from the transaction mgr
//
result = TransactionFactory::GetNewTransaction(kIMECommitTxnIID,(EditTxn**)&commitTxn);
if (NS_SUCCEEDED(result) && commitTxn!=nsnull)
{
commitTxn->Init();
result = Do(commitTxn);
}
// mIMESelectionRange = nsCOMPtr<nsIDOMRange>();
/* reset the data we need to construct a transaction */
mIMETextNode = do_QueryInterface(nsnull);
mIMETextOffset = 0;
mIMEBufferLength = 0;
return NS_OK;
return result;
}
NS_IMETHODIMP
nsEditor::SetCompositionString(const nsString& aCompositionString)
nsEditor::SetCompositionString(const nsString& aCompositionString, nsIDOMTextRangeList* aTextRangeList)
{
nsresult result = SetInputMethodText(aCompositionString,aTextRangeList);
mIMEBufferLength = aCompositionString.Length();
if (mIMEFirstTransaction==PR_TRUE) {
mIMEFirstTransaction = PR_FALSE;
} else {
// printf("Undo!\n");
// mTxnMgr->Undo();
nsCOMPtr<nsIDOMSelection> selection;
nsresult result;
result = mPresShell->GetSelection(getter_AddRefs(selection));
if (NS_FAILED(result))
{
EndTransaction();
return result;
}
nsCOMPtr<nsIDOMNode> node;
PRInt32 offset;
result = mIMESelectionRange->GetStartParent(getter_AddRefs(node));
result = mIMESelectionRange->GetStartOffset(&offset);
result = selection->Collapse(node, offset);
result = mIMESelectionRange->GetEndParent(getter_AddRefs(node));
result = mIMESelectionRange->GetEndOffset(&offset);
result = selection->Extend(node, offset);
}
#ifdef DEBUG_tague
printf("nsEditor::SetCompositionString: string=%s\n",aCompositionString);
#endif
return SetPreeditText(aCompositionString);
return result;
}
NS_IMETHODIMP
@ -3450,176 +3469,130 @@ nsEditor::GetFirstTextNode(nsIDOMNode *aNode, nsIDOMNode **aRetNode)
//END nsEditor Private methods
NS_IMETHODIMP nsEditor::DoInitialPreeeditInsert(const nsString& aStringToInsert)
NS_IMETHODIMP
nsEditor::SetInputMethodText(const nsString& aStringToInsert,nsIDOMTextRangeList *aTextRangeList)
{
if (!mDoc) {
return NS_ERROR_NOT_INITIALIZED;
}
nsCOMPtr<nsIDOMNodeList>nodeList;
nsAutoString bodyTag = "body";
nsresult result = mDoc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList));
if ((NS_SUCCEEDED(result)) && nodeList)
{
PRUint32 count;
nodeList->GetLength(&count);
NS_ASSERTION(1==count, "there is not exactly 1 body in the document!");
nsCOMPtr<nsIDOMNode>node;
result = nodeList->Item(0, getter_AddRefs(node));
if ((NS_SUCCEEDED(result)) && node)
{ // now we've got the body tag.
// create transaction to insert the text node,
// and create a transaction to insert the text
CreateElementTxn *txn;
result = CreateTxnForCreateElement(GetTextNodeTag(), node, 0, &txn);
if ((NS_SUCCEEDED(result)) && txn)
{
result = Do(txn);
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMNode>newNode;
txn->GetNewNode(getter_AddRefs(newNode));
if ((NS_SUCCEEDED(result)) && newNode)
{
nsCOMPtr<nsIDOMCharacterData>newTextNode;
newTextNode = do_QueryInterface(newNode);
if (newTextNode)
{
InsertTextTxn *insertTxn;
result = CreateTxnForInsertText(aStringToInsert, newTextNode, &insertTxn);
if (NS_SUCCEEDED(result)) {
result = Do(insertTxn);
}
}
else {
result = NS_ERROR_UNEXPECTED;
}
}
}
}
}
}
return result;
IMETextTxn *txn;
nsresult result;
result = CreateTxnForIMEText(aStringToInsert,aTextRangeList,&txn); // insert at the current selection
if ((NS_SUCCEEDED(result)) && txn) {
BeginUpdateViewBatch();
result = Do(txn);
EndUpdateViewBatch();
}
else if (NS_ERROR_EDITOR_NO_SELECTION==result) {
result = DoInitialInputMethodInsert(aStringToInsert,aTextRangeList);
}
else if (NS_ERROR_EDITOR_NO_TEXTNODE==result)
{
BeginTransaction();
nsCOMPtr<nsIDOMSelection> selection;
result = GetSelection(getter_AddRefs(selection));
if ((NS_SUCCEEDED(result)) && selection)
{
nsCOMPtr<nsIDOMNode> selectedNode;
PRInt32 offset;
result = selection->GetAnchorNode(getter_AddRefs(selectedNode));
if (NS_SUCCEEDED(result) && NS_SUCCEEDED(selection->GetAnchorOffset(&offset)) && selectedNode)
{
nsCOMPtr<nsIDOMNode> newNode;
result = CreateNode(GetTextNodeTag(), selectedNode, offset+1,getter_AddRefs(newNode));
if (NS_SUCCEEDED(result) && newNode)
{
nsCOMPtr<nsIDOMCharacterData>newTextNode;
newTextNode = do_QueryInterface(newNode);
if (newTextNode)
{
nsAutoString placeholderText(" ");
newTextNode->SetData(placeholderText);
selection->Collapse(newNode, 0);
selection->Extend(newNode, 1);
result = SetInputMethodText(aStringToInsert,aTextRangeList);
}
}
}
}
EndTransaction();
}
return result;
}
NS_IMETHODIMP
nsEditor::SetPreeditText(const nsString& aStringToInsert)
nsEditor::CreateTxnForIMEText(const nsString & aStringToInsert,
nsIDOMTextRangeList* aTextRangeList,
IMETextTxn ** aTxn)
{
nsresult result;
nsresult result;
//EditAggregateTxn *aggTxn = nsnull;
// Create the "delete current selection" txn
nsCOMPtr<nsIDOMSelection> selection;
BeginTransaction();
result = mPresShell->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(result) && selection)
{
PRBool collapsed;
result = selection->GetIsCollapsed(&collapsed);
if (NS_SUCCEEDED(result) && !collapsed) {
EditAggregateTxn *delSelTxn;
// XXX should this be eDoNothing instead of eDeleteRight?
result = CreateTxnForDeleteSelection(nsIEditor::eDeleteRight,
&delSelTxn);
if (NS_SUCCEEDED(result) && delSelTxn) {
result = Do(delSelTxn);
if (NS_FAILED(result)) {
EndTransaction();
return result;
}
}
}
}
result = mPresShell->GetSelection(getter_AddRefs(selection));
if (NS_FAILED(result))
{
EndTransaction();
return result;
}
nsCOMPtr<nsIDOMRange> startRange;
nsCOMPtr<nsIDOMRange> endRange;
result = selection->GetRangeAt(0, getter_AddRefs(startRange));
if (NS_FAILED(result))
{
EndTransaction();
return result;
}
InsertTextTxn *txn;
result = CreateTxnForInsertText(aStringToInsert, nsnull, &txn); // insert at the current selection
if ((NS_SUCCEEDED(result)) && txn) {
result = Do(txn);
}
else if (NS_ERROR_EDITOR_NO_SELECTION==result) {
result = DoInitialInsert(aStringToInsert);
}
else if (NS_ERROR_EDITOR_NO_TEXTNODE==result)
{
result = GetSelection(getter_AddRefs(selection));
if ((NS_SUCCEEDED(result)) && selection)
{
nsCOMPtr<nsIDOMNode> selectedNode;
PRInt32 offset;
result = selection->GetAnchorNode(getter_AddRefs(selectedNode));
if (NS_SUCCEEDED(result) && NS_SUCCEEDED(selection->GetAnchorOffset(&offset)) && selectedNode)
{
nsCOMPtr<nsIDOMNode> newNode;
result = CreateNode(GetTextNodeTag(), selectedNode, offset+1,
getter_AddRefs(newNode));
if (NS_SUCCEEDED(result) && newNode)
{
nsCOMPtr<nsIDOMCharacterData>newTextNode;
newTextNode = do_QueryInterface(newNode);
if (newTextNode)
{
nsAutoString placeholderText(" ");
newTextNode->SetData(placeholderText);
selection->Collapse(newNode, 0);
selection->Extend(newNode, 1);
result = SetPreeditText(aStringToInsert);
}
}
}
}
}
result = mPresShell->GetSelection(getter_AddRefs(selection));
if (NS_FAILED(result))
{
EndTransaction();
return result;
}
result = selection->GetRangeAt(0, getter_AddRefs(endRange));
nsCOMPtr<nsIDOMNode> node;
PRInt32 offset;
startRange->GetStartParent(getter_AddRefs(node));
startRange->GetStartOffset(&offset);
mIMESelectionRange->SetStart(node, offset);
endRange->GetStartParent(getter_AddRefs(node));
endRange->GetStartOffset(&offset);
mIMESelectionRange->SetEnd(node, offset);
EndTransaction();
// HACKForceRedraw();
return result;
result = TransactionFactory::GetNewTransaction(kIMETextTxnIID, (EditTxn **)aTxn);
if (nsnull!=*aTxn) {
result = (*aTxn)->Init(mIMETextNode,mIMETextOffset,mIMEBufferLength,aTextRangeList,aStringToInsert,mPresShell);
}
else {
result = NS_ERROR_OUT_OF_MEMORY;
}
return result;
}
NS_IMETHODIMP nsEditor::DoInitialInputMethodInsert(const nsString & aStringToInsert,nsIDOMTextRangeList* aTextRangeList)
{
if (!mDoc) {
return NS_ERROR_NOT_INITIALIZED;
}
nsCOMPtr<nsIDOMNodeList>nodeList;
nsAutoString bodyTag = "body";
nsresult result = mDoc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList));
if ((NS_SUCCEEDED(result)) && nodeList)
{
PRUint32 count;
nodeList->GetLength(&count);
NS_ASSERTION(1==count, "there is not exactly 1 body in the document!");
nsCOMPtr<nsIDOMNode>node;
result = nodeList->Item(0, getter_AddRefs(node));
if ((NS_SUCCEEDED(result)) && node)
{ // now we've got the body tag.
// create transaction to insert the text node,
// and create a transaction to insert the text
CreateElementTxn *txn;
result = CreateTxnForCreateElement(GetTextNodeTag(), node, 0, &txn);
if ((NS_SUCCEEDED(result)) && txn)
{
result = Do(txn);
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMNode>newNode;
txn->GetNewNode(getter_AddRefs(newNode));
if ((NS_SUCCEEDED(result)) && newNode)
{
nsCOMPtr<nsIDOMCharacterData>newTextNode;
newTextNode = do_QueryInterface(newNode);
if (newTextNode)
{
mIMETextNode = newTextNode;
mIMETextOffset = 0;
mIMEBufferLength = 0;
IMETextTxn *IMETxn;
result = CreateTxnForIMEText(aStringToInsert,aTextRangeList,&IMETxn);
if (NS_SUCCEEDED(result)) {
result = Do(IMETxn);
}
}
else {
result = NS_ERROR_UNEXPECTED;
}
}
}
}
}
}
return result;
}
///////////////////////////////////////////////////////////////////////////
// GetTag: digs out the atom for the tag of this node
//

View File

@ -26,6 +26,7 @@
#include "nsIDOMSelection.h"
#include "nsIDOMEventListener.h"
#include "nsIDOMRange.h"
#include "nsIDOMTextRangeList.h"
#include "nsCOMPtr.h"
#include "nsIStringBundle.h"
#include "nsITransactionManager.h"
@ -54,6 +55,7 @@ class nsIPref;
class nsIStringBundleService;
class nsIStringBundle;
class nsILocale;
class IMETextTxn;
#ifdef ENABLE_JS_EDITOR_LOG
class nsJSEditorLog;
@ -78,7 +80,12 @@ private:
nsCOMPtr<nsITransactionManager> mTxnMgr;
nsCOMPtr<nsIEditProperty> mEditProperty;
nsCOMPtr<nsIDOMRange> mIMESelectionRange;
//
// data necessary to build IME transactions
//
nsCOMPtr<nsIDOMCharacterData> mIMETextNode;
PRUint32 mIMETextOffset;
PRUint32 mIMEBufferLength;
friend PRBool NSCanUnload(nsISupports* serviceMgr);
static PRInt32 gInstanceCount;
@ -163,7 +170,7 @@ public:
NS_IMETHOD BeginComposition(void);
NS_IMETHOD SetCompositionString(const nsString& aCompositionString);
NS_IMETHOD SetCompositionString(const nsString& aCompositionString, nsIDOMTextRangeList* aTextRangeList);
NS_IMETHOD EndComposition(void);
@ -273,10 +280,16 @@ protected:
nsIDOMCharacterData *aTextNode,
InsertTextTxn ** aTxn);
NS_IMETHOD CreateTxnForIMEText(const nsString & aStringToInsert,
nsIDOMTextRangeList* aTextRangeList,
IMETextTxn ** aTxn);
/** insert aStringToInsert as the first text in the document
*/
NS_IMETHOD DoInitialInsert(const nsString & aStringToInsert);
NS_IMETHOD DoInitialInputMethodInsert(const nsString& aStringToInsert,nsIDOMTextRangeList* aTextRangeList);
NS_IMETHOD DeleteText(nsIDOMCharacterData *aElement,
PRUint32 aOffset,
@ -314,10 +327,7 @@ protected:
NS_IMETHOD DebugDumpContent() const;
// should these me methodimp?
NS_IMETHODIMP SetPreeditText(const nsString& aStringToInsert);
NS_IMETHODIMP DoInitialPreeeditInsert(const nsString& aStringToInsert);
NS_IMETHOD SetInputMethodText(const nsString& aStringToInsert, nsIDOMTextRangeList* aTextRangeList);
// called each time we modify the document. Increments the mod
// count of the doc.
@ -344,8 +354,6 @@ protected:
// document after a change via the DOM - gpk 2/13/99
void HACKForceRedraw(void);
PRBool mIMEFirstTransaction;
NS_IMETHOD DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNode> &parentSelectedNode, PRInt32& offsetOfNewNode);
public:

View File

@ -1090,16 +1090,19 @@ nsTextEditorTextListener::HandleText(nsIDOMEvent* aTextEvent)
{
nsString composedText;
nsresult result;
nsCOMPtr<nsIDOMUIEvent>uiEvent;
nsIDOMTextRangeList *textRangeList;
nsCOMPtr<nsIDOMUIEvent>uiEvent;
uiEvent = do_QueryInterface(aTextEvent);
if (!uiEvent) {
//non-ui event passed in. bad things.
return NS_OK;
}
uiEvent = do_QueryInterface(aTextEvent);
if (!uiEvent) {
//non-ui event passed in. bad things.
return NS_OK;
}
uiEvent->GetText(composedText);
result = mEditor->SetCompositionString(composedText);
uiEvent->GetInputRange(&textRangeList);
textRangeList->AddRef();
result = mEditor->SetCompositionString(composedText,textRangeList);
return result;
}

View File

@ -2488,9 +2488,9 @@ NS_IMETHODIMP nsHTMLEditor::EndComposition(void)
return nsTextEditor::EndComposition();
}
NS_IMETHODIMP nsHTMLEditor::SetCompositionString(const nsString& aCompositionString)
NS_IMETHODIMP nsHTMLEditor::SetCompositionString(const nsString& aCompositionString, nsIDOMTextRangeList* aTextRangeList)
{
return nsTextEditor::SetCompositionString(aCompositionString);
return nsTextEditor::SetCompositionString(aCompositionString,aTextRangeList);
}
NS_IMETHODIMP

View File

@ -106,7 +106,7 @@ public:
NS_IMETHOD InsertHTML(const nsString& aInputString);
NS_IMETHOD BeginComposition(void);
NS_IMETHOD SetCompositionString(const nsString& aCompositionString);
NS_IMETHOD SetCompositionString(const nsString& aCompositionString, nsIDOMTextRangeList* aTextRange);
NS_IMETHOD EndComposition(void);
NS_IMETHOD OutputTextToString(nsString& aOutputString, PRBool aSelectionOnly);
NS_IMETHOD OutputHTMLToString(nsString& aOutputString, PRBool aSelectionOnly);

View File

@ -828,7 +828,7 @@ nsJSEditorLog::BeginComposition(void)
}
NS_IMETHODIMP
nsJSEditorLog::SetCompositionString(const nsString& aCompositionString)
nsJSEditorLog::SetCompositionString(const nsString& aCompositionString,nsIDOMTextRangeList* aTextRangeList)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@ -138,7 +138,7 @@ public:
NS_IMETHOD DeleteTableRow(PRInt32 aNumber);
NS_IMETHOD JoinTableCells(PRBool aCellToRight);
NS_IMETHOD BeginComposition(void);
NS_IMETHOD SetCompositionString(const nsString& aCompositionString);
NS_IMETHOD SetCompositionString(const nsString& aCompositionString, nsIDOMTextRangeList* aTextRangeList);
NS_IMETHOD EndComposition(void);
NS_IMETHOD StartLogging(nsIFileSpec *aLogFile);
NS_IMETHOD StopLogging();

View File

@ -2804,9 +2804,9 @@ nsTextEditor::BeginComposition(void)
}
NS_IMETHODIMP
nsTextEditor::SetCompositionString(const nsString& aCompositionString)
nsTextEditor::SetCompositionString(const nsString& aCompositionString,nsIDOMTextRangeList* aTextRangeList)
{
return nsEditor::SetCompositionString(aCompositionString);
return nsEditor::SetCompositionString(aCompositionString,aTextRangeList);
}
NS_IMETHODIMP

View File

@ -110,7 +110,7 @@ public:
// Input/Output
NS_IMETHOD BeginComposition(void);
NS_IMETHOD SetCompositionString(const nsString& aCompositionString);
NS_IMETHOD SetCompositionString(const nsString& aCompositionString, nsIDOMTextRangeList* aRangeList);
NS_IMETHOD EndComposition(void);
NS_IMETHOD OutputTextToString(nsString& aOutputString, PRBool aSelectionOnly);
NS_IMETHOD OutputHTMLToString(nsString& aOutputString, PRBool aSelectionOnly);

View File

@ -0,0 +1,296 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "IMETextTxn.h"
#include "IMECommitTxn.h"
#include "nsEditor.h"
#include "nsIDOMCharacterData.h"
#include "nsIDOMTextRange.h"
#include "nsIDOMTextRangeList.h"
#include "nsIDOMSelection.h"
#include "nsIPresShell.h"
#include "EditAggregateTxn.h"
static NS_DEFINE_IID(kIMETextTxnIID, IME_TEXT_TXN_IID);
static NS_DEFINE_IID(kIDOMSelectionIID, NS_IDOMSELECTION_IID);
nsIAtom *IMETextTxn::gIMETextTxnName = nsnull;
nsresult IMETextTxn::ClassInit()
{
if (nsnull==gIMETextTxnName)
gIMETextTxnName = NS_NewAtom("NS_IMETextTxn");
return NS_OK;
}
IMETextTxn::IMETextTxn()
: EditTxn()
{
}
IMETextTxn::~IMETextTxn()
{
mRangeList = do_QueryInterface(nsnull);
}
NS_IMETHODIMP IMETextTxn::Init(nsIDOMCharacterData *aElement,
PRUint32 aOffset,
PRUint32 aReplaceLength,
nsIDOMTextRangeList* aTextRangeList,
const nsString &aStringToInsert,
nsIPresShell *aPresShell)
{
mElement = do_QueryInterface(aElement);
mOffset = aOffset;
mReplaceLength = aReplaceLength;
mStringToInsert = aStringToInsert;
mPresShell = aPresShell;
mRangeList = do_QueryInterface(aTextRangeList);
mFixed = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP IMETextTxn::Do(void)
{
#ifdef DEBUG_TAGUE
printf("Do IME Text element = %p\n", mElement.get());
#endif
// advance caret: This requires the presentation shell to get the selection.
nsCOMPtr<nsIDOMSelection> selection;
nsresult result = mPresShell->GetSelection(getter_AddRefs(selection));
NS_ASSERTION(selection,"Could not get selection in IMEtextTxn::Do\n");
if (NS_SUCCEEDED(result) && selection) {
if (mReplaceLength==0) {
result = mElement->InsertData(mOffset,mStringToInsert);
} else {
result = mElement->ReplaceData(mOffset,mReplaceLength,mStringToInsert);
}
if (NS_SUCCEEDED(result)) {
result = CollapseTextSelection();
}
}
return result;
}
NS_IMETHODIMP IMETextTxn::Undo(void)
{
#ifdef DEBUG_TAGUE
printf("Undo IME Text element = %p\n", mElement.get());
#endif
nsresult result;
PRUint32 length = mStringToInsert.Length();
result = mElement->DeleteData(mOffset, length);
if (NS_SUCCEEDED(result))
{ // set the selection to the insertion point where the string was removed
nsCOMPtr<nsIDOMSelection> selection;
result = mPresShell->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(result) && selection) {
result = selection->Collapse(mElement, mOffset);
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of IME insert.");
}
}
return result;
}
NS_IMETHODIMP IMETextTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
#ifdef DEBUG_TAGUE
printf("Merge IME Text element = %p\n", mElement.get());
#endif
//
// check to make sure we have valid return pointers
//
if ((nsnull==aDidMerge) && (nsnull==aTransaction))
{
return NS_OK;
}
//
// check to make sure we aren't fixed, if we are then nothing get's absorbed
//
if (mFixed) {
*aDidMerge = PR_FALSE;
return NS_OK;
}
//
// if aTransaction is another IMETextTxn then absorbe it
//
nsCOMPtr<IMETextTxn> otherTxn(do_QueryInterface(aTransaction));
if (otherTxn)
{
//
// we absorbe the next IME transaction by adopting it's insert string as our own
//
nsIDOMTextRangeList* newTextRangeList;
otherTxn->GetData(mStringToInsert,&newTextRangeList);
mRangeList = do_QueryInterface(newTextRangeList);
*aDidMerge = PR_TRUE;
#ifdef DEBUG_TAGUE
printf("IMETextTxn assimilated IMETextTxn:%p\n", aTransaction);
#endif
return NS_OK;
}
//
// second possible case is that we have a commit transaction
//
nsCOMPtr<IMECommitTxn> commitTxn(do_QueryInterface(aTransaction));
if (commitTxn)
{
(void)CollapseTextSelectionOnCommit();
mFixed = PR_TRUE;
*aDidMerge = PR_TRUE; // absorbe the commit transaction
#ifdef DEBUG_TAGUE
printf("IMETextTxn assimilated IMECommitTxn%p\n", aTransaction);
#endif
return NS_OK;
}
*aDidMerge = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP IMETextTxn::Write(nsIOutputStream *aOutputStream)
{
return NS_OK;
}
NS_IMETHODIMP IMETextTxn::GetUndoString(nsString *aString)
{
if (nsnull!=aString)
{
*aString="Remove Text: ";
*aString += mStringToInsert;
}
return NS_OK;
}
NS_IMETHODIMP IMETextTxn::GetRedoString(nsString *aString)
{
if (nsnull!=aString)
{
*aString="Insert Text: ";
*aString += mStringToInsert;
}
return NS_OK;
}
/* ============= nsISupports implementation ====================== */
NS_IMETHODIMP
IMETextTxn::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (nsnull == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(kIMETextTxnIID)) {
*aInstancePtr = (void*)(IMETextTxn*)this;
NS_ADDREF_THIS();
return NS_OK;
}
return (EditTxn::QueryInterface(aIID, aInstancePtr));
}
/* ============ protected methods ================== */
NS_IMETHODIMP IMETextTxn::GetData(nsString& aResult,nsIDOMTextRangeList** aTextRangeList)
{
aResult = mStringToInsert;
*aTextRangeList = mRangeList;
return NS_OK;
}
NS_IMETHODIMP IMETextTxn::CollapseTextSelection(void)
{
nsresult result;
PRBool haveSelectedRange;
PRUint16 textRangeListLength,selectionStart,selectionEnd,
textRangeType, i;
nsIDOMTextRange* textRange;
haveSelectedRange = PR_FALSE;
#ifdef DEBUG_tague
PRUint16 listlen,start,stop,type;
nsIDOMTextRange* rangePtr;
result = mRangeList->GetLength(&listlen);
printf("nsIDOMTextRangeList[%p]\n",mRangeList);
for (i=0;i<listlen;i++) {
(void)mRangeList->Item(i,&rangePtr);
rangePtr->GetRangeStart(&start);
rangePtr->GetRangeEnd(&stop);
rangePtr->GetRangeType(&type);
printf("range[%d] start=%d end=%d type=",i,start,stop,type);
if (type==nsIDOMTextRange::TEXTRANGE_RAWINPUT) printf("TEXTRANGE_RAWINPUT\n");
if (type==nsIDOMTextRange::TEXTRANGE_SELECTEDRAWTEXT) printf("TEXTRANGE_SELECTEDRAWTEXT\n");
if (type==nsIDOMTextRange::TEXTRANGE_CONVERTEDTEXT) printf("TEXTRANGE_CONVERTEDTEXT\n");
if (type==nsIDOMTextRange::TEXTRANGE_SELECTEDCONVERTEDTEXT) printf("TEXTRANGE_SELECTEDCONVERTEDTEXT\n");
}
#endif
//
// run through the text range list
//
result = mRangeList->GetLength(&textRangeListLength);
if (NS_SUCCEEDED(result))
{
for(i=0;i<textRangeListLength;i++) {
result = mRangeList->Item(i,&textRange);
if (NS_SUCCEEDED(result))
{
result = textRange->GetRangeType(&textRangeType);
if (textRangeType==nsIDOMTextRange::TEXTRANGE_SELECTEDCONVERTEDTEXT)
{
haveSelectedRange = PR_TRUE;
textRange->GetRangeStart(&selectionStart);
textRange->GetRangeEnd(&selectionEnd);
}
}
}
}
nsCOMPtr<nsIDOMSelection> selection;
result = mPresShell->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(result) && selection){
if (haveSelectedRange) {
result = selection->Collapse(mElement,mOffset+selectionStart);
result = selection->Extend(mElement,mOffset+selectionEnd+1);
} else {
result = selection->Collapse(mElement,mOffset+mStringToInsert.Length());
}
}
return result;
}
NS_IMETHODIMP IMETextTxn::CollapseTextSelectionOnCommit(void)
{
nsCOMPtr<nsIDOMSelection> selection;
nsresult result = mPresShell->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(result) && selection){
result = selection->Collapse(mElement,mOffset+mStringToInsert.Length());
}
return result;
}

View File

@ -0,0 +1,126 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef IMETextTxn_h__
#define IMETextTxn_h__
#include "EditTxn.h"
#include "nsIDOMCharacterData.h"
#include "nsIDOMTextRangeList.h"
#include "nsCOMPtr.h"
// {D4D25721-2813-11d3-9EA3-0060089FE59B}
#define IME_TEXT_TXN_IID \
{0xd4d25721, 0x2813, 0x11d3, \
{0x9e, 0xa3, 0x0, 0x60, 0x8, 0x9f, 0xe5, 0x9b }}
class nsIPresShell;
/**
* A transaction that inserts text into a content node.
*/
class IMETextTxn : public EditTxn
{
public:
virtual ~IMETextTxn();
/** used to name aggregate transactions that consist only of a single IMETextTxn,
* or a DeleteSelection followed by an IMETextTxn.
*/
static nsIAtom *gIMETextTxnName;
/** initialize the transaction
* @param aElement the text content node
* @param aOffset the location in aElement to do the insertion
* @param aReplaceLength the length of text to replace (0= no replacement)
* @param aString the new text to insert
* @param aPresShell used to get and set the selection
*/
NS_IMETHOD Init(nsIDOMCharacterData *aElement,
PRUint32 aOffset,
PRUint32 aReplaceLength,
nsIDOMTextRangeList* aTextRangeList,
const nsString& aString,
nsIPresShell* aPresShell);
private:
IMETextTxn();
public:
NS_IMETHOD Do(void);
NS_IMETHOD Undo(void);
NS_IMETHOD Merge(PRBool *aDidMerge, nsITransaction *aTransaction);
NS_IMETHOD Write(nsIOutputStream *aOutputStream);
NS_IMETHOD GetUndoString(nsString *aString);
NS_IMETHOD GetRedoString(nsString *aString);
// nsISupports declarations
// override QueryInterface to handle IMETextTxn request
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
static const nsIID& GetIID() { static nsIID iid = IME_TEXT_TXN_IID; return iid; }
/** return the string data associated with this transaction */
NS_IMETHOD GetData(nsString& aResult, nsIDOMTextRangeList** aTextRangeList);
/** must be called before any IMETextTxn is instantiated */
static nsresult ClassInit();
protected:
NS_IMETHOD CollapseTextSelection(void);
NS_IMETHOD CollapseTextSelectionOnCommit(void);
/** the text element to operate upon */
nsCOMPtr<nsIDOMCharacterData> mElement;
/** the offsets into mElement where the insertion should be placed*/
PRUint32 mOffset;
PRUint32 mReplaceLength;
/** the text to insert into mElement at mOffset */
nsString mStringToInsert;
/** the range list **/
nsCOMPtr<nsIDOMTextRangeList> mRangeList;
/** the presentation shell, which we'll need to get the selection */
nsIPresShell* mPresShell;
PRBool mFixed;
friend class TransactionFactory;
friend class nsDerivedSafe<IMETextTxn>; // work around for a compiler bug
};
#endif

View File

@ -25,6 +25,7 @@
static NS_DEFINE_IID(kInsertTextTxnIID, INSERT_TEXT_TXN_IID);
static NS_DEFINE_IID(kIDOMSelectionIID, NS_IDOMSELECTION_IID);
static NS_DEFINE_IID(kEditAggregateTxnIID, EDIT_AGGREGATE_TXN_IID);
#ifdef NS_DEBUG
static PRBool gNoisy = PR_FALSE;

View File

@ -39,7 +39,9 @@
#include "DeleteTableColumnTxn.h"
#include "DeleteTableRowTxn.h"
#include "JoinTableCellsTxn.h"
#include "IMETextTxn.h"
#include "IMECommitTxn.h"
static NS_DEFINE_IID(kEditAggregateTxnIID, EDIT_AGGREGATE_TXN_IID);
static NS_DEFINE_IID(kPlaceholderTxnIID, PLACEHOLDER_TXN_IID);
static NS_DEFINE_IID(kInsertTextTxnIID, INSERT_TEXT_TXN_IID);
@ -61,6 +63,8 @@ static NS_DEFINE_IID(kDeleteTableCellTxnIID, DELETE_CELL_TXN_IID);
static NS_DEFINE_IID(kDeleteTableColumnTxnIID, DELETE_COLUMN_TXN_IID);
static NS_DEFINE_IID(kDeleteTableRowTxnIID, DELETE_ROW_TXN_IID);
static NS_DEFINE_IID(kJoinTableCellsTxnIID, JOIN_CELLS_TXN_IID);
static NS_DEFINE_IID(kIMETextTxnIID, IME_TEXT_TXN_IID);
static NS_DEFINE_IID(kIMECommitTxnIID, IME_COMMIT_TXN_IID);
TransactionFactory::TransactionFactory()
{
@ -97,6 +101,10 @@ TransactionFactory::GetNewTransaction(REFNSIID aTxnType, EditTxn **aResult)
*aResult = new JoinElementTxn();
else if (aTxnType.Equals(kEditAggregateTxnIID))
*aResult = new EditAggregateTxn();
else if (aTxnType.Equals(kIMETextTxnIID))
*aResult = new IMETextTxn();
else if (aTxnType.Equals(kIMECommitTxnIID))
*aResult = new IMECommitTxn();
else if (aTxnType.Equals(kPlaceholderTxnIID))
*aResult = new PlaceholderTxn();
else

View File

@ -84,6 +84,8 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#include "SplitElementTxn.h"
#include "JoinElementTxn.h"
#include "nsIStringStream.h"
#include "IMETextTxn.h"
#include "IMECommitTxn.h"
// #define HACK_FORCE_REDRAW 1
@ -128,6 +130,8 @@ static NS_DEFINE_IID(kDeleteRangeTxnIID, DELETE_RANGE_TXN_IID);
static NS_DEFINE_IID(kChangeAttributeTxnIID,CHANGE_ATTRIBUTE_TXN_IID);
static NS_DEFINE_IID(kSplitElementTxnIID, SPLIT_ELEMENT_TXN_IID);
static NS_DEFINE_IID(kJoinElementTxnIID, JOIN_ELEMENT_TXN_IID);
static NS_DEFINE_IID(kIMETextTxnIID, IME_TEXT_TXN_IID);
static NS_DEFINE_IID(kIMECommitTxnIID, IME_COMMIT_TXN_IID);
static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
static NS_DEFINE_CID(kCDOMRangeCID, NS_RANGE_CID);
@ -334,7 +338,6 @@ nsEditor::nsEditor()
{
//initialize member variables here
NS_INIT_REFCNT();
mIMEFirstTransaction=PR_FALSE;
PR_EnterMonitor(GetEditorMonitor());
gInstanceCount++;
mActionListeners = 0;
@ -519,6 +522,13 @@ nsEditor::Init(nsIDOMDocument *aDoc, nsIPresShell* aPresShell)
mUpdateCount=0;
InsertTextTxn::ClassInit();
/* initalize IME stuff */
IMETextTxn::ClassInit();
IMECommitTxn::ClassInit();
mIMETextNode = do_QueryInterface(nsnull);
mIMETextOffset = 0;
mIMEBufferLength = 0;
/* Show the caret */
nsCOMPtr<nsICaret> caret;
if (NS_SUCCEEDED(mPresShell->GetCaret(getter_AddRefs(caret))))
@ -3188,93 +3198,102 @@ NS_IMETHODIMP nsEditor::GetLayoutObject(nsIDOMNode *aNode, nsISupports **aLayout
return result;
}
//
// The BeingComposition method is called from the Editor Composition event listeners.
// It caches the current text node and offset which is subsequently used for the
// created of IMETextTxn's.
//
NS_IMETHODIMP
nsEditor::BeginComposition(void)
{
if ((nsITransactionManager *)nsnull!=mTxnMgr.get())
{
#ifdef DEBUG_tague
printf("nsEditor::StartComposition -- begin batch.\n");
printf("nsEditor::StartComposition\n");
#endif
mTxnMgr->BeginBatch();
}
if (!mIMESelectionRange)
{
nsresult result = nsComponentManager::CreateInstance(kCDOMRangeCID, nsnull,
nsIDOMRange::GetIID(),
getter_AddRefs(mIMESelectionRange));
if (NS_FAILED(result))
nsresult result;
PRInt32 offset;
nsCOMPtr<nsIDOMSelection> selection;
nsCOMPtr<nsIDOMCharacterData> nodeAsText;
result = mPresShell->GetSelection(getter_AddRefs(selection));
if ((NS_SUCCEEDED(result)) && selection)
{
mTxnMgr->EndBatch();
return result;
result = NS_ERROR_UNEXPECTED;
nsCOMPtr<nsIEnumerator> enumerator;
enumerator = do_QueryInterface(selection);
if (enumerator)
{
enumerator->First();
nsISupports *currentItem;
result = enumerator->CurrentItem(&currentItem);
if ((NS_SUCCEEDED(result)) && (nsnull!=currentItem))
{
result = NS_ERROR_UNEXPECTED;
nsCOMPtr<nsIDOMRange> range(do_QueryInterface(currentItem));
if (range)
{
nsCOMPtr<nsIDOMNode> node;
result = range->GetStartParent(getter_AddRefs(node));
if ((NS_SUCCEEDED(result)) && (node))
{
nodeAsText = do_QueryInterface(node);
range->GetStartOffset(&offset);
if (!nodeAsText) {
result = NS_ERROR_EDITOR_NO_TEXTNODE;
}
}
}
}
else
{
result = NS_ERROR_EDITOR_NO_SELECTION;
}
}
}
}
mIMEFirstTransaction=PR_TRUE;
return NS_OK;
if (NS_SUCCEEDED(result) && nodeAsText)
{
//
// store the information needed to construct IME transactions for this composition
//
mIMETextNode = nodeAsText;
mIMETextOffset = offset;
mIMEBufferLength = 0;
}
return result;
}
NS_IMETHODIMP
nsEditor::EndComposition(void)
{
if ((nsITransactionManager *)nsnull!=mTxnMgr.get())
{
#ifdef DEBUG_tague
printf("nsEditor::EndComposition -- end batch.\n");
#endif
mTxnMgr->EndBatch();
mIMEFirstTransaction=PR_TRUE;
return NS_OK;
}
nsresult result;
IMECommitTxn *commitTxn;
//
// create the commit transaction..we can do it directly from the transaction mgr
//
result = TransactionFactory::GetNewTransaction(kIMECommitTxnIID,(EditTxn**)&commitTxn);
if (NS_SUCCEEDED(result) && commitTxn!=nsnull)
{
commitTxn->Init();
result = Do(commitTxn);
}
// mIMESelectionRange = nsCOMPtr<nsIDOMRange>();
/* reset the data we need to construct a transaction */
mIMETextNode = do_QueryInterface(nsnull);
mIMETextOffset = 0;
mIMEBufferLength = 0;
return NS_OK;
return result;
}
NS_IMETHODIMP
nsEditor::SetCompositionString(const nsString& aCompositionString)
nsEditor::SetCompositionString(const nsString& aCompositionString, nsIDOMTextRangeList* aTextRangeList)
{
nsresult result = SetInputMethodText(aCompositionString,aTextRangeList);
mIMEBufferLength = aCompositionString.Length();
if (mIMEFirstTransaction==PR_TRUE) {
mIMEFirstTransaction = PR_FALSE;
} else {
// printf("Undo!\n");
// mTxnMgr->Undo();
nsCOMPtr<nsIDOMSelection> selection;
nsresult result;
result = mPresShell->GetSelection(getter_AddRefs(selection));
if (NS_FAILED(result))
{
EndTransaction();
return result;
}
nsCOMPtr<nsIDOMNode> node;
PRInt32 offset;
result = mIMESelectionRange->GetStartParent(getter_AddRefs(node));
result = mIMESelectionRange->GetStartOffset(&offset);
result = selection->Collapse(node, offset);
result = mIMESelectionRange->GetEndParent(getter_AddRefs(node));
result = mIMESelectionRange->GetEndOffset(&offset);
result = selection->Extend(node, offset);
}
#ifdef DEBUG_tague
printf("nsEditor::SetCompositionString: string=%s\n",aCompositionString);
#endif
return SetPreeditText(aCompositionString);
return result;
}
NS_IMETHODIMP
@ -3450,176 +3469,130 @@ nsEditor::GetFirstTextNode(nsIDOMNode *aNode, nsIDOMNode **aRetNode)
//END nsEditor Private methods
NS_IMETHODIMP nsEditor::DoInitialPreeeditInsert(const nsString& aStringToInsert)
NS_IMETHODIMP
nsEditor::SetInputMethodText(const nsString& aStringToInsert,nsIDOMTextRangeList *aTextRangeList)
{
if (!mDoc) {
return NS_ERROR_NOT_INITIALIZED;
}
nsCOMPtr<nsIDOMNodeList>nodeList;
nsAutoString bodyTag = "body";
nsresult result = mDoc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList));
if ((NS_SUCCEEDED(result)) && nodeList)
{
PRUint32 count;
nodeList->GetLength(&count);
NS_ASSERTION(1==count, "there is not exactly 1 body in the document!");
nsCOMPtr<nsIDOMNode>node;
result = nodeList->Item(0, getter_AddRefs(node));
if ((NS_SUCCEEDED(result)) && node)
{ // now we've got the body tag.
// create transaction to insert the text node,
// and create a transaction to insert the text
CreateElementTxn *txn;
result = CreateTxnForCreateElement(GetTextNodeTag(), node, 0, &txn);
if ((NS_SUCCEEDED(result)) && txn)
{
result = Do(txn);
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMNode>newNode;
txn->GetNewNode(getter_AddRefs(newNode));
if ((NS_SUCCEEDED(result)) && newNode)
{
nsCOMPtr<nsIDOMCharacterData>newTextNode;
newTextNode = do_QueryInterface(newNode);
if (newTextNode)
{
InsertTextTxn *insertTxn;
result = CreateTxnForInsertText(aStringToInsert, newTextNode, &insertTxn);
if (NS_SUCCEEDED(result)) {
result = Do(insertTxn);
}
}
else {
result = NS_ERROR_UNEXPECTED;
}
}
}
}
}
}
return result;
IMETextTxn *txn;
nsresult result;
result = CreateTxnForIMEText(aStringToInsert,aTextRangeList,&txn); // insert at the current selection
if ((NS_SUCCEEDED(result)) && txn) {
BeginUpdateViewBatch();
result = Do(txn);
EndUpdateViewBatch();
}
else if (NS_ERROR_EDITOR_NO_SELECTION==result) {
result = DoInitialInputMethodInsert(aStringToInsert,aTextRangeList);
}
else if (NS_ERROR_EDITOR_NO_TEXTNODE==result)
{
BeginTransaction();
nsCOMPtr<nsIDOMSelection> selection;
result = GetSelection(getter_AddRefs(selection));
if ((NS_SUCCEEDED(result)) && selection)
{
nsCOMPtr<nsIDOMNode> selectedNode;
PRInt32 offset;
result = selection->GetAnchorNode(getter_AddRefs(selectedNode));
if (NS_SUCCEEDED(result) && NS_SUCCEEDED(selection->GetAnchorOffset(&offset)) && selectedNode)
{
nsCOMPtr<nsIDOMNode> newNode;
result = CreateNode(GetTextNodeTag(), selectedNode, offset+1,getter_AddRefs(newNode));
if (NS_SUCCEEDED(result) && newNode)
{
nsCOMPtr<nsIDOMCharacterData>newTextNode;
newTextNode = do_QueryInterface(newNode);
if (newTextNode)
{
nsAutoString placeholderText(" ");
newTextNode->SetData(placeholderText);
selection->Collapse(newNode, 0);
selection->Extend(newNode, 1);
result = SetInputMethodText(aStringToInsert,aTextRangeList);
}
}
}
}
EndTransaction();
}
return result;
}
NS_IMETHODIMP
nsEditor::SetPreeditText(const nsString& aStringToInsert)
nsEditor::CreateTxnForIMEText(const nsString & aStringToInsert,
nsIDOMTextRangeList* aTextRangeList,
IMETextTxn ** aTxn)
{
nsresult result;
nsresult result;
//EditAggregateTxn *aggTxn = nsnull;
// Create the "delete current selection" txn
nsCOMPtr<nsIDOMSelection> selection;
BeginTransaction();
result = mPresShell->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(result) && selection)
{
PRBool collapsed;
result = selection->GetIsCollapsed(&collapsed);
if (NS_SUCCEEDED(result) && !collapsed) {
EditAggregateTxn *delSelTxn;
// XXX should this be eDoNothing instead of eDeleteRight?
result = CreateTxnForDeleteSelection(nsIEditor::eDeleteRight,
&delSelTxn);
if (NS_SUCCEEDED(result) && delSelTxn) {
result = Do(delSelTxn);
if (NS_FAILED(result)) {
EndTransaction();
return result;
}
}
}
}
result = mPresShell->GetSelection(getter_AddRefs(selection));
if (NS_FAILED(result))
{
EndTransaction();
return result;
}
nsCOMPtr<nsIDOMRange> startRange;
nsCOMPtr<nsIDOMRange> endRange;
result = selection->GetRangeAt(0, getter_AddRefs(startRange));
if (NS_FAILED(result))
{
EndTransaction();
return result;
}
InsertTextTxn *txn;
result = CreateTxnForInsertText(aStringToInsert, nsnull, &txn); // insert at the current selection
if ((NS_SUCCEEDED(result)) && txn) {
result = Do(txn);
}
else if (NS_ERROR_EDITOR_NO_SELECTION==result) {
result = DoInitialInsert(aStringToInsert);
}
else if (NS_ERROR_EDITOR_NO_TEXTNODE==result)
{
result = GetSelection(getter_AddRefs(selection));
if ((NS_SUCCEEDED(result)) && selection)
{
nsCOMPtr<nsIDOMNode> selectedNode;
PRInt32 offset;
result = selection->GetAnchorNode(getter_AddRefs(selectedNode));
if (NS_SUCCEEDED(result) && NS_SUCCEEDED(selection->GetAnchorOffset(&offset)) && selectedNode)
{
nsCOMPtr<nsIDOMNode> newNode;
result = CreateNode(GetTextNodeTag(), selectedNode, offset+1,
getter_AddRefs(newNode));
if (NS_SUCCEEDED(result) && newNode)
{
nsCOMPtr<nsIDOMCharacterData>newTextNode;
newTextNode = do_QueryInterface(newNode);
if (newTextNode)
{
nsAutoString placeholderText(" ");
newTextNode->SetData(placeholderText);
selection->Collapse(newNode, 0);
selection->Extend(newNode, 1);
result = SetPreeditText(aStringToInsert);
}
}
}
}
}
result = mPresShell->GetSelection(getter_AddRefs(selection));
if (NS_FAILED(result))
{
EndTransaction();
return result;
}
result = selection->GetRangeAt(0, getter_AddRefs(endRange));
nsCOMPtr<nsIDOMNode> node;
PRInt32 offset;
startRange->GetStartParent(getter_AddRefs(node));
startRange->GetStartOffset(&offset);
mIMESelectionRange->SetStart(node, offset);
endRange->GetStartParent(getter_AddRefs(node));
endRange->GetStartOffset(&offset);
mIMESelectionRange->SetEnd(node, offset);
EndTransaction();
// HACKForceRedraw();
return result;
result = TransactionFactory::GetNewTransaction(kIMETextTxnIID, (EditTxn **)aTxn);
if (nsnull!=*aTxn) {
result = (*aTxn)->Init(mIMETextNode,mIMETextOffset,mIMEBufferLength,aTextRangeList,aStringToInsert,mPresShell);
}
else {
result = NS_ERROR_OUT_OF_MEMORY;
}
return result;
}
NS_IMETHODIMP nsEditor::DoInitialInputMethodInsert(const nsString & aStringToInsert,nsIDOMTextRangeList* aTextRangeList)
{
if (!mDoc) {
return NS_ERROR_NOT_INITIALIZED;
}
nsCOMPtr<nsIDOMNodeList>nodeList;
nsAutoString bodyTag = "body";
nsresult result = mDoc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList));
if ((NS_SUCCEEDED(result)) && nodeList)
{
PRUint32 count;
nodeList->GetLength(&count);
NS_ASSERTION(1==count, "there is not exactly 1 body in the document!");
nsCOMPtr<nsIDOMNode>node;
result = nodeList->Item(0, getter_AddRefs(node));
if ((NS_SUCCEEDED(result)) && node)
{ // now we've got the body tag.
// create transaction to insert the text node,
// and create a transaction to insert the text
CreateElementTxn *txn;
result = CreateTxnForCreateElement(GetTextNodeTag(), node, 0, &txn);
if ((NS_SUCCEEDED(result)) && txn)
{
result = Do(txn);
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMNode>newNode;
txn->GetNewNode(getter_AddRefs(newNode));
if ((NS_SUCCEEDED(result)) && newNode)
{
nsCOMPtr<nsIDOMCharacterData>newTextNode;
newTextNode = do_QueryInterface(newNode);
if (newTextNode)
{
mIMETextNode = newTextNode;
mIMETextOffset = 0;
mIMEBufferLength = 0;
IMETextTxn *IMETxn;
result = CreateTxnForIMEText(aStringToInsert,aTextRangeList,&IMETxn);
if (NS_SUCCEEDED(result)) {
result = Do(IMETxn);
}
}
else {
result = NS_ERROR_UNEXPECTED;
}
}
}
}
}
}
return result;
}
///////////////////////////////////////////////////////////////////////////
// GetTag: digs out the atom for the tag of this node
//

View File

@ -26,6 +26,7 @@
#include "nsIDOMSelection.h"
#include "nsIDOMEventListener.h"
#include "nsIDOMRange.h"
#include "nsIDOMTextRangeList.h"
#include "nsCOMPtr.h"
#include "nsIStringBundle.h"
#include "nsITransactionManager.h"
@ -54,6 +55,7 @@ class nsIPref;
class nsIStringBundleService;
class nsIStringBundle;
class nsILocale;
class IMETextTxn;
#ifdef ENABLE_JS_EDITOR_LOG
class nsJSEditorLog;
@ -78,7 +80,12 @@ private:
nsCOMPtr<nsITransactionManager> mTxnMgr;
nsCOMPtr<nsIEditProperty> mEditProperty;
nsCOMPtr<nsIDOMRange> mIMESelectionRange;
//
// data necessary to build IME transactions
//
nsCOMPtr<nsIDOMCharacterData> mIMETextNode;
PRUint32 mIMETextOffset;
PRUint32 mIMEBufferLength;
friend PRBool NSCanUnload(nsISupports* serviceMgr);
static PRInt32 gInstanceCount;
@ -163,7 +170,7 @@ public:
NS_IMETHOD BeginComposition(void);
NS_IMETHOD SetCompositionString(const nsString& aCompositionString);
NS_IMETHOD SetCompositionString(const nsString& aCompositionString, nsIDOMTextRangeList* aTextRangeList);
NS_IMETHOD EndComposition(void);
@ -273,10 +280,16 @@ protected:
nsIDOMCharacterData *aTextNode,
InsertTextTxn ** aTxn);
NS_IMETHOD CreateTxnForIMEText(const nsString & aStringToInsert,
nsIDOMTextRangeList* aTextRangeList,
IMETextTxn ** aTxn);
/** insert aStringToInsert as the first text in the document
*/
NS_IMETHOD DoInitialInsert(const nsString & aStringToInsert);
NS_IMETHOD DoInitialInputMethodInsert(const nsString& aStringToInsert,nsIDOMTextRangeList* aTextRangeList);
NS_IMETHOD DeleteText(nsIDOMCharacterData *aElement,
PRUint32 aOffset,
@ -314,10 +327,7 @@ protected:
NS_IMETHOD DebugDumpContent() const;
// should these me methodimp?
NS_IMETHODIMP SetPreeditText(const nsString& aStringToInsert);
NS_IMETHODIMP DoInitialPreeeditInsert(const nsString& aStringToInsert);
NS_IMETHOD SetInputMethodText(const nsString& aStringToInsert, nsIDOMTextRangeList* aTextRangeList);
// called each time we modify the document. Increments the mod
// count of the doc.
@ -344,8 +354,6 @@ protected:
// document after a change via the DOM - gpk 2/13/99
void HACKForceRedraw(void);
PRBool mIMEFirstTransaction;
NS_IMETHOD DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNode> &parentSelectedNode, PRInt32& offsetOfNewNode);
public:

View File

@ -2488,9 +2488,9 @@ NS_IMETHODIMP nsHTMLEditor::EndComposition(void)
return nsTextEditor::EndComposition();
}
NS_IMETHODIMP nsHTMLEditor::SetCompositionString(const nsString& aCompositionString)
NS_IMETHODIMP nsHTMLEditor::SetCompositionString(const nsString& aCompositionString, nsIDOMTextRangeList* aTextRangeList)
{
return nsTextEditor::SetCompositionString(aCompositionString);
return nsTextEditor::SetCompositionString(aCompositionString,aTextRangeList);
}
NS_IMETHODIMP

View File

@ -106,7 +106,7 @@ public:
NS_IMETHOD InsertHTML(const nsString& aInputString);
NS_IMETHOD BeginComposition(void);
NS_IMETHOD SetCompositionString(const nsString& aCompositionString);
NS_IMETHOD SetCompositionString(const nsString& aCompositionString, nsIDOMTextRangeList* aTextRange);
NS_IMETHOD EndComposition(void);
NS_IMETHOD OutputTextToString(nsString& aOutputString, PRBool aSelectionOnly);
NS_IMETHOD OutputHTMLToString(nsString& aOutputString, PRBool aSelectionOnly);

View File

@ -1090,16 +1090,19 @@ nsTextEditorTextListener::HandleText(nsIDOMEvent* aTextEvent)
{
nsString composedText;
nsresult result;
nsCOMPtr<nsIDOMUIEvent>uiEvent;
nsIDOMTextRangeList *textRangeList;
nsCOMPtr<nsIDOMUIEvent>uiEvent;
uiEvent = do_QueryInterface(aTextEvent);
if (!uiEvent) {
//non-ui event passed in. bad things.
return NS_OK;
}
uiEvent = do_QueryInterface(aTextEvent);
if (!uiEvent) {
//non-ui event passed in. bad things.
return NS_OK;
}
uiEvent->GetText(composedText);
result = mEditor->SetCompositionString(composedText);
uiEvent->GetInputRange(&textRangeList);
textRangeList->AddRef();
result = mEditor->SetCompositionString(composedText,textRangeList);
return result;
}

View File

@ -27,6 +27,7 @@ class nsIDOMNode;
class nsITransaction;
class nsIEditActionListener;
class nsIFileSpec;
class nsIDOMTextRangeList;
/*
Editor interface to outside world
@ -194,7 +195,7 @@ public:
* BeginComposition must be called prior to this.
*/
NS_IMETHOD SetCompositionString(const nsString& aCompositionString) = 0;
NS_IMETHOD SetCompositionString(const nsString& aCompositionString, nsIDOMTextRangeList* aTextRangeList) = 0;
/**
* BeginComposition() Handles the end of inline input composition.

View File

@ -192,7 +192,7 @@ public:
// IME editing Methods
NS_IMETHOD BeginComposition(void)=0;
NS_IMETHOD SetCompositionString(const nsString& aCompositionString)=0;
NS_IMETHOD SetCompositionString(const nsString& aCompositionString, nsIDOMTextRangeList* aTextRangeList)=0;
NS_IMETHOD EndComposition(void)=0;

View File

@ -365,7 +365,7 @@ public:
// IME Editing Methods
NS_IMETHOD BeginComposition(void)=0;
NS_IMETHOD SetCompositionString(const nsString& aCompositionString)=0;
NS_IMETHOD SetCompositionString(const nsString& aCompositionString, nsIDOMTextRangeList* aTextRangeList)=0;
NS_IMETHOD EndComposition(void)=0;

View File

@ -31,6 +31,7 @@ CPPSRCS = \
nsEventStateManager.cpp \
nsDOMEvent.cpp \
nsDOMEventsIIDs.cpp \
nsDOMTextRange.cpp \
$(NULL)
MODULE=layout
@ -40,6 +41,7 @@ EXPORTS = \
nsEventStateManager.h \
nsDOMEvent.h \
nsDOMEventsIIDs.h \
nsDOMTextRange.h \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))

View File

@ -30,16 +30,18 @@ CPPSRCS= nsEventListenerManager.cpp \
nsEventStateManager.cpp \
nsDOMEvent.cpp \
nsDOMEventsIIDs.cpp \
nsDOMTextRange.cpp \
$(NULL)
CPP_OBJS= .\$(OBJDIR)\nsEventListenerManager.obj \
.\$(OBJDIR)\nsEventStateManager.obj \
.\$(OBJDIR)\nsDOMEvent.obj \
.\$(OBJDIR)\nsDOMEventsIIDs.obj \
.\$(OBJDIR)\nsDOMTextRange.obj \
$(NULL)
EXPORTS= nsEventListenerManager.h nsEventStateManager.h nsDOMEvent.h nsDOMEventsIIDs.h
EXPORTS= nsEventListenerManager.h nsEventStateManager.h nsDOMEvent.h nsDOMEventsIIDs.h nsDOMTextRange.h
LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor \
-I$(PUBLIC)\dom -I$(PUBLIC)\js -I..\..\html\base\src -I$(PUBLIC)\netlib

View File

@ -26,6 +26,7 @@
#include "nsIWidget.h"
#include "nsIWebShell.h"
#include "nsIPresShell.h"
#include "nsDOMTextRange.h"
static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID);
static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID);
@ -50,10 +51,28 @@ nsDOMEvent::nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent) {
mEvent = aEvent;
mTarget = nsnull;
mText = nsnull;
mTextRange = nsnull;
if (aEvent->eventStructType ==NS_TEXT_EVENT) {
//
// extract the IME composition string
//
mText = new nsString(((nsTextEvent*)aEvent)->theText);
mCommitText = ((nsTextEvent*)aEvent)->commitText;
//
// build the range list -- ranges need to be DOM-ified since the IME transaction
// will hold a ref, the widget representation isn't persistent
//
nsIDOMTextRange** tempTextRangeList = new nsIDOMTextRange*[((nsTextEvent*)aEvent)->rangeCount];
for(PRUint16 i=0;i<((nsTextEvent*)aEvent)->rangeCount;i++) {
nsDOMTextRange* tempDOMTextRange = new nsDOMTextRange((((nsTextEvent*)aEvent)->rangeArray[i]).mStartOffset,
(((nsTextEvent*)aEvent)->rangeArray[i]).mEndOffset,
(((nsTextEvent*)aEvent)->rangeArray[i]).mRangeType);
tempDOMTextRange->AddRef();
tempTextRangeList[i] = (nsIDOMTextRange*)tempDOMTextRange;
}
mTextRange = (nsIDOMTextRangeList*) new nsDOMTextRangeList(((nsTextEvent*)aEvent)->rangeCount,tempTextRangeList);
mTextRange->AddRef();
}
NS_INIT_REFCNT();
@ -62,8 +81,10 @@ nsDOMEvent::nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent) {
nsDOMEvent::~nsDOMEvent() {
NS_RELEASE(mPresContext);
NS_IF_RELEASE(mTarget);
NS_IF_RELEASE(mTextRange);
delete mText;
if (mText!=nsnull)
delete mText;
}
NS_IMPL_ADDREF(nsDOMEvent)
@ -182,18 +203,18 @@ NS_METHOD nsDOMEvent::GetText(nsString& aText)
return NS_ERROR_FAILURE;
}
NS_METHOD nsDOMEvent::GetCommitText(PRBool* aCommitText)
NS_METHOD nsDOMEvent::GetInputRange(nsIDOMTextRangeList** aInputRange)
{
if (mEvent->message == NS_TEXT_EVENT) {
*aCommitText = mCommitText;
*aInputRange = mTextRange;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_METHOD nsDOMEvent::SetCommitText(PRBool aCommitText)
{
NS_METHOD nsDOMEvent::SetInputRange(nsIDOMTextRangeList* aInputRange)
{
return NS_ERROR_FAILURE;
}

View File

@ -81,10 +81,11 @@ public:
NS_IMETHOD PreventDefault();
NS_IMETHOD GetText(nsString& aText);
NS_IMETHOD GetText(nsString& aText);
NS_IMETHOD GetCommitText(PRBool* aCommitText);
NS_IMETHOD SetCommitText(PRBool aCommitText);
NS_IMETHOD GetInputRange(nsIDOMTextRangeList** aInputRange);
NS_IMETHOD SetInputRange(nsIDOMTextRangeList* aInputRange);
NS_IMETHOD GetScreenX(PRInt32* aScreenX);
@ -135,7 +136,7 @@ protected:
nsIPresContext* mPresContext;
nsIDOMNode* mTarget;
nsString* mText;
PRBool mCommitText;
nsIDOMTextRangeList* mTextRange;
const char* GetEventName(PRUint32 aEventType);
};

View File

@ -0,0 +1,150 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsDOMTextRange.h"
static NS_DEFINE_IID(kIDOMTextRange, NS_IDOMTEXTRANGE_IID);
static NS_DEFINE_IID(kIDOMTextRangeList,NS_IDOMTEXTRANGELIST_IID);
nsDOMTextRange::nsDOMTextRange(PRUint16 aRangeStart, PRUint16 aRangeEnd, PRUint16 aRangeType)
: mRangeStart(aRangeStart),
mRangeEnd(aRangeEnd),
mRangeType(aRangeType)
{
NS_INIT_REFCNT();
}
nsDOMTextRange::~nsDOMTextRange(void)
{
}
NS_IMPL_ADDREF(nsDOMTextRange)
NS_IMPL_RELEASE(nsDOMTextRange)
nsresult nsDOMTextRange::QueryInterface(const nsIID& aIID,
void** aInstancePtrResult)
{
NS_PRECONDITION(nsnull != aInstancePtrResult, "null pointer");
if (nsnull == aInstancePtrResult) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(kIDOMTextRange)) {
*aInstancePtrResult = (void*) ((nsIDOMTextRange*)this);
AddRef();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_METHOD nsDOMTextRange::GetRangeStart(PRUint16* aRangeStart)
{
*aRangeStart = mRangeStart;
return NS_OK;
}
NS_METHOD nsDOMTextRange::SetRangeStart(PRUint16 aRangeStart)
{
mRangeStart = aRangeStart;
return NS_OK;
}
NS_METHOD nsDOMTextRange::GetRangeEnd(PRUint16* aRangeEnd)
{
*aRangeEnd = mRangeEnd;
return NS_OK;
}
NS_METHOD nsDOMTextRange::SetRangeEnd(PRUint16 aRangeEnd)
{
mRangeEnd = aRangeEnd;
return NS_OK;
}
NS_METHOD nsDOMTextRange::GetRangeType(PRUint16* aRangeType)
{
*aRangeType = mRangeType;
return NS_OK;
}
NS_METHOD nsDOMTextRange::SetRangeType(PRUint16 aRangeType)
{
mRangeType = aRangeType;
return NS_OK;
}
nsDOMTextRangeList::nsDOMTextRangeList(PRUint16 aLength,nsIDOMTextRange** aList)
: mLength(aLength),
mList(aList)
{
if (aList==nsnull)
aLength = 0;
NS_INIT_REFCNT();
}
nsDOMTextRangeList::~nsDOMTextRangeList(void)
{
int i;
for(i=0;i<mLength;i++)
mList[i]->Release();
}
NS_IMPL_ADDREF(nsDOMTextRangeList)
NS_IMPL_RELEASE(nsDOMTextRangeList)
nsresult nsDOMTextRangeList::QueryInterface(const nsIID& aIID,
void** aInstancePtrResult)
{
NS_PRECONDITION(nsnull != aInstancePtrResult, "null pointer");
if (nsnull == aInstancePtrResult) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(kIDOMTextRangeList)) {
*aInstancePtrResult = (void*) ((nsIDOMTextRangeList*)this);
AddRef();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_METHOD nsDOMTextRangeList::GetLength(PRUint16* aLength)
{
*aLength = mLength;
return NS_OK;
}
NS_METHOD nsDOMTextRangeList::Item(PRUint16 aIndex, nsIDOMTextRange** aReturn)
{
if (aIndex>mLength) {
*aReturn = nsnull;
return NS_ERROR_FAILURE;
}
mList[aIndex]->AddRef();
*aReturn = mList[aIndex];
return NS_OK;
}

View File

@ -0,0 +1,68 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsDOMTextRange_h__
#define nsDOMTextRange_h__
#include "nsIDOMTextRange.h"
#include "nsIDOMTextRangeList.h"
class nsDOMTextRange : public nsIDOMTextRange
{
NS_DECL_ISUPPORTS
public:
nsDOMTextRange(PRUint16 aRangeStart, PRUint16 aRangeEnd, PRUint16 aRangeType);
~nsDOMTextRange(void);
NS_IMETHOD GetRangeStart(PRUint16* aRangeStart);
NS_IMETHOD SetRangeStart(PRUint16 aRangeStart);
NS_IMETHOD GetRangeEnd(PRUint16* aRangeEnd);
NS_IMETHOD SetRangeEnd(PRUint16 aRangeEnd);
NS_IMETHOD GetRangeType(PRUint16* aRangeType);
NS_IMETHOD SetRangeType(PRUint16 aRangeType);
protected:
PRUint16 mRangeStart;
PRUint16 mRangeEnd;
PRUint16 mRangeType;
};
class nsDOMTextRangeList: public nsIDOMTextRangeList
{
NS_DECL_ISUPPORTS
public:
nsDOMTextRangeList(PRUint16 aLength,nsIDOMTextRange** aList);
~nsDOMTextRangeList(void);
NS_IMETHOD GetLength(PRUint16* aLength);
NS_IMETHOD Item(PRUint16 aIndex, nsIDOMTextRange** aReturn);
protected:
PRUint16 mLength;
nsIDOMTextRange** mList;
};
#endif

View File

@ -137,18 +137,30 @@ struct nsKeyEvent : public nsInputEvent {
};
/**
* Tooltip event
* IME Related Events
*/
struct nsTextRange {
PRUint32 mStartOffset;
PRUint32 mEndOffset;
PRUint32 mRangeType;
};
typedef struct nsTextRange nsTextRange;
typedef nsTextRange* nsTextRangeArray;
struct nsTextEvent : public nsInputEvent {
PRUnichar* theText;
PRBool commitText;
PRUint32 rangeCount;
nsTextRangeArray rangeArray;
};
struct nsCompositionEvent : public nsInputEvent {
PRUint32 compositionMessage;
};
/**
* Tooltip event
*/
struct nsTooltipEvent : public nsGUIEvent {
/// Index of tooltip area which generated the event. @see SetTooltips in nsIWidget
PRUint32 tipIndex;
@ -453,5 +465,11 @@ enum nsDragDropEventStatus {
#define NS_EVENT_FLAG_CAPTURE 0x0004
#define NS_EVENT_FLAG_POST_PROCESS 0x0008
// IME Constants -- keep in synch with nsIDOMTextRange.h
#define NS_TEXTRANGE_RAWINPUT 0X01
#define NS_TEXTRANGE_SELECTEDRAWTEXT 0x02
#define NS_TEXTRANGE_CONVERTEDTEXT 0x03
#define NS_TEXTRANGE_SELECTEDCONVERTEDTEXT 0x04
#endif // nsGUIEvent_h__

View File

@ -112,8 +112,16 @@ nsWindow::nsWindow() : nsBaseWidget()
mIMEIsComposing = PR_FALSE;
mIMECompositionString = NULL;
mIMECompositionStringSize = 0;
mIMECompositionStringSize = 0;
mIMECompositionStringLength = 0;
mIMECompositionUniString = NULL;
mIMECompositionUniStringSize = 0;
mIMEAttributeString = NULL;
mIMEAttributeStringSize = 0;
mIMEAttributeStringLength = 0;
mIMECompClauseString = NULL;
mIMECompClauseStringSize = 0;
mIMECompClauseStringLength = 0;
#if 1
mHaveDBCSLeadByte = false;
mDBCSLeadByte = '\0';
@ -152,6 +160,13 @@ nsWindow::~nsWindow()
//XXX Temporary: Should not be caching the font
delete mFont;
//
// delete any of the IME structures that we allocated
//
if (mIMECompositionString!=NULL) delete [] mIMECompositionString;
if (mIMEAttributeString!=NULL) delete [] mIMEAttributeString;
if (mIMECompositionUniString!=NULL) delete [] mIMECompositionUniString;
}
@ -2641,6 +2656,40 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
return PR_TRUE;
}
//
// This provides us with the attribute string necessary for doing hiliting
//
if (lParam & GCS_COMPATTR) {
long attrStrLen = ::ImmGetCompositionString(hIMEContext,GCS_COMPATTR,NULL,0);
if (attrStrLen+1>mIMEAttributeStringSize) {
if (mIMEAttributeString!=NULL) delete [] mIMEAttributeString;
mIMEAttributeString = new char[attrStrLen+32];
mIMEAttributeStringSize = attrStrLen+32;
}
::ImmGetCompositionString(hIMEContext,GCS_COMPATTR,mIMEAttributeString,mIMEAttributeStringSize);
mIMEAttributeStringLength = attrStrLen;
mIMEAttributeString[attrStrLen]='\0';
}
if (lParam & GCS_COMPCLAUSE) {
long compClauseLen = ::ImmGetCompositionString(hIMEContext,GCS_COMPCLAUSE,NULL,0);
if (compClauseLen+1>mIMECompClauseStringSize) {
if (mIMECompClauseString!=NULL) delete [] mIMECompClauseString;
mIMECompClauseString = new char [compClauseLen+32];
mIMECompClauseStringSize = compClauseLen+32;
}
::ImmGetCompositionString(hIMEContext,GCS_COMPCLAUSE,mIMECompClauseString,mIMECompClauseStringSize);
mIMECompClauseStringLength = compClauseLen;
mIMECompClauseString[compClauseLen]='\0';
} else {
mIMECompClauseStringLength = 0;
}
//
// This provides us with a composition string
//
if (lParam & GCS_COMPSTR) {
#ifdef DEBUG_tague
fprintf(stderr,"nsWindow::WM_IME_COMPOSITION: handling GCS_COMPSTR\n");
@ -2655,10 +2704,13 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
::ImmGetCompositionString(hIMEContext,GCS_COMPSTR,mIMECompositionString,mIMECompositionStringSize);
mIMECompositionStringLength = compStrLen;
mIMECompositionString[compStrLen]='\0';
HandleTextEvent(PR_FALSE);
HandleTextEvent();
result = PR_TRUE;
}
//
// This catches a fixed result
//
if (lParam & GCS_RESULTSTR) {
#ifdef DEBUG_tague
fprintf(stderr,"nsWindow::WM_IME_COMPOSITION: handling GCS_RESULTSTR\n");
@ -2674,7 +2726,7 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
mIMECompositionStringLength = compStrLen;
mIMECompositionString[compStrLen]='\0';
result = PR_TRUE;
HandleTextEvent(PR_TRUE);
HandleTextEvent();
HandleEndComposition();
HandleStartComposition();
}
@ -3304,31 +3356,42 @@ NS_METHOD nsWindow::SetPreferredSize(PRInt32 aWidth, PRInt32 aHeight)
}
void
nsWindow::HandleTextEvent(PRBool commit)
nsWindow::HandleTextEvent()
{
nsTextEvent event;
nsPoint point;
size_t unicharSize;
nsTextEvent event;
nsPoint point;
size_t unicharSize;
point.x = 0;
point.y = 0;
InitEvent(event, NS_TEXT_EVENT, &point);
if (mIMECompositionUniString!=NULL)
delete [] mIMECompositionUniString;
//
// convert the composition string text into unicode before it is sent to xp-land
//
unicharSize = ::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,mIMECompositionString,mIMECompositionStringLength,
mIMECompositionUniString,0);
mIMECompositionUniString = new PRUnichar[unicharSize+1];
if (mIMECompositionUniStringSize < unicharSize) {
if (mIMECompositionUniString!=NULL) delete [] mIMECompositionUniString;
mIMECompositionUniString = new PRUnichar[unicharSize+32];
mIMECompositionUniStringSize = unicharSize+32;
}
::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,mIMECompositionString,mIMECompositionStringLength,
mIMECompositionUniString,unicharSize);
mIMECompositionUniString[unicharSize] = (PRUnichar)0;
event.theText = mIMECompositionUniString;
event.commitText = commit;
event.isShift = mIsShiftDown;
//
// we need to convert the attribute array, which is alligned with the mutibyte text into an array of offsets
// mapped to the unicode text
//
MapDBCSAtrributeArrayToUnicodeOffsets(&(event.rangeCount),&(event.rangeArray));
event.theText = mIMECompositionUniString;
event.isShift = mIsShiftDown;
event.isControl = mIsControlDown;
event.isAlt = mIsAltDown;
event.isAlt = mIsAltDown;
event.eventStructType = NS_TEXT_EVENT;
(void)DispatchWindowEvent(&event);
@ -3367,3 +3430,88 @@ nsWindow::HandleEndComposition(void)
(void)DispatchWindowEvent(&event);
NS_RELEASE(event.widget);
}
//
// This function converters the composition string (CGS_COMPSTR) into Unicode while mapping the
// attribute (GCS_ATTR) string t
void
nsWindow::MapDBCSAtrributeArrayToUnicodeOffsets(PRUint32* textRangeListLengthResult,nsTextRangeArray* textRangeListResult)
{
int i,rangePointer;
size_t lastUnicodeOffset, substringLength, lastMBCSOffset;
//
// figure out the ranges from the compclause string
//
if (mIMECompClauseStringLength==0) {
*textRangeListLengthResult = 1;
*textRangeListResult = new nsTextRange[1];
(*textRangeListResult)[0].mStartOffset=0;
substringLength = ::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,mIMECompositionString,
mIMECompositionStringLength,NULL,0);
(*textRangeListResult)[0].mEndOffset = substringLength-1;
(*textRangeListResult)[0].mRangeType = mIMEAttributeString[0];
} else {
*textRangeListLengthResult = 0;
for(i=0;i<mIMECompClauseStringLength;i++) {
if (mIMECompClauseString[i]!=0x00)
(*textRangeListLengthResult)++;
}
//
// allocate the offset array
//
*textRangeListResult = new nsTextRange[*textRangeListLengthResult];
//
// iterate over the attributes and convert them into unicode
lastUnicodeOffset = 0;
lastMBCSOffset = 0;
rangePointer = 0;
for(i=0;i<mIMECompClauseStringLength;i++) {
if (mIMECompClauseString[i]!=0) {
(*textRangeListResult)[rangePointer].mStartOffset = lastUnicodeOffset;
substringLength = ::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,mIMECompositionString+lastMBCSOffset,
mIMECompClauseString[i]-lastMBCSOffset,NULL,0);
(*textRangeListResult)[rangePointer].mEndOffset = lastUnicodeOffset + substringLength -1;
(*textRangeListResult)[rangePointer].mRangeType = mIMEAttributeString[mIMECompClauseString[i]-1];
lastUnicodeOffset+= substringLength;
lastMBCSOffset = mIMECompClauseString[i];
rangePointer++;
}
}
}
#ifdef DEBUG_tague
printf("rangeCount =%d\n",*textRangeListLengthResult);
for(i=0;i<*textRangeListLengthResult;i++) {
printf("range %d: rangeStart=%d\trangeEnd=%d ",i,(*textRangeListResult)[i].mStartOffset,
(*textRangeListResult)[i].mEndOffset);
if ((*textRangeListResult)[i].mRangeType==ATTR_INPUT) printf("ATTR_INPUT\n");
if ((*textRangeListResult)[i].mRangeType==ATTR_TARGET_CONVERTED) printf("ATTR_TARGET_CONVERTED\n");
if ((*textRangeListResult)[i].mRangeType==ATTR_CONVERTED) printf("ATTR_CONVERTED\n");
if ((*textRangeListResult)[i].mRangeType==ATTR_TARGET_NOTCONVERTED) printf("ATTR_TARGET_NOTCONVERTED\n");
if ((*textRangeListResult)[i].mRangeType==ATTR_INPUT_ERROR) printf("ATTR_INPUT_ERROR\n");
if ((*textRangeListResult)[i].mRangeType==ATTR_FIXEDCONVERTED) printf("ATTR_FIXEDCONVERTED\n");
}
#endif
//
// convert from windows attributes into nsGUI/DOM attributes
//
for(i=0;i<*textRangeListLengthResult;i++) {
if ((*textRangeListResult)[i].mRangeType==ATTR_INPUT)
(*textRangeListResult)[i].mRangeType=NS_TEXTRANGE_RAWINPUT;
else
if ((*textRangeListResult)[i].mRangeType==ATTR_TARGET_CONVERTED)
(*textRangeListResult)[i].mRangeType=NS_TEXTRANGE_SELECTEDCONVERTEDTEXT;
else
if ((*textRangeListResult)[i].mRangeType==ATTR_CONVERTED)
(*textRangeListResult)[i].mRangeType=NS_TEXTRANGE_CONVERTEDTEXT;
else
if ((*textRangeListResult)[i].mRangeType==ATTR_TARGET_NOTCONVERTED)
(*textRangeListResult)[i].mRangeType=NS_TEXTRANGE_RAWINPUT;
}
}

View File

@ -196,9 +196,10 @@ protected:
void RelayMouseEvent(UINT aMsg, WPARAM wParam, LPARAM lParam);
void GetNonClientBounds(nsRect &aRect);
void HandleTextEvent(PRBool commit);
void HandleTextEvent(void);
void HandleStartComposition(void);
void HandleEndComposition(void);
void MapDBCSAtrributeArrayToUnicodeOffsets(PRUint32* textRangeListLengthResult, nsTextRangeArray* textRangeListResult);
protected:
static nsWindow* gCurrentWindow;
@ -232,8 +233,16 @@ protected:
PRBool mIMEIsComposing;
char* mIMECompositionString;
PRUnichar* mIMECompositionUniString;
PRInt32 mIMECompositionUniStringSize;
PRInt32 mIMECompositionStringLength;
PRInt32 mIMECompositionStringSize;
char* mIMEAttributeString;
PRInt32 mIMEAttributeStringLength;
PRInt32 mIMEAttributeStringSize;
char* mIMECompClauseString;
PRInt32 mIMECompClauseStringLength;
PRInt32 mIMECompClauseStringSize;
#if 1
BOOL mHaveDBCSLeadByte;
unsigned char mDBCSLeadByte;