diff --git a/editor/base/IMETextTxn.cpp b/editor/base/IMETextTxn.cpp index 4b4cc63e4e10..9a97e3a4af44 100644 --- a/editor/base/IMETextTxn.cpp +++ b/editor/base/IMETextTxn.cpp @@ -224,12 +224,14 @@ NS_IMETHODIMP IMETextTxn::GetData(nsString& aResult,nsIDOMTextRangeList** aTextR NS_IMETHODIMP IMETextTxn::CollapseTextSelection(void) { nsresult result; - PRBool haveSelectedRange; + PRBool haveSelectedRange, haveCaretPosition; PRUint16 textRangeListLength,selectionStart,selectionEnd, - textRangeType, i; + textRangeType, caretPosition, i; nsIDOMTextRange* textRange; haveSelectedRange = PR_FALSE; + haveCaretPosition = PR_FALSE; + #ifdef DEBUG_tague PRUint16 listlen,start,stop,type; @@ -266,6 +268,11 @@ NS_IMETHODIMP IMETextTxn::CollapseTextSelection(void) textRange->GetRangeStart(&selectionStart); textRange->GetRangeEnd(&selectionEnd); } + if (textRangeType==nsIDOMTextRange::TEXTRANGE_CARETPOSITION) + { + haveCaretPosition = PR_TRUE; + textRange->GetRangeStart(&caretPosition); + } } } } @@ -275,9 +282,12 @@ NS_IMETHODIMP IMETextTxn::CollapseTextSelection(void) if (NS_SUCCEEDED(result) && selection){ if (haveSelectedRange) { result = selection->Collapse(mElement,mOffset+selectionStart); - result = selection->Extend(mElement,mOffset+selectionEnd+1); + result = selection->Extend(mElement,mOffset+selectionEnd); } else { - result = selection->Collapse(mElement,mOffset+mStringToInsert.Length()); + if (haveCaretPosition) + result = selection->Collapse(mElement,mOffset+caretPosition); + else + result = selection->Collapse(mElement,mOffset+mStringToInsert.Length()); } } diff --git a/editor/libeditor/base/IMETextTxn.cpp b/editor/libeditor/base/IMETextTxn.cpp index 4b4cc63e4e10..9a97e3a4af44 100644 --- a/editor/libeditor/base/IMETextTxn.cpp +++ b/editor/libeditor/base/IMETextTxn.cpp @@ -224,12 +224,14 @@ NS_IMETHODIMP IMETextTxn::GetData(nsString& aResult,nsIDOMTextRangeList** aTextR NS_IMETHODIMP IMETextTxn::CollapseTextSelection(void) { nsresult result; - PRBool haveSelectedRange; + PRBool haveSelectedRange, haveCaretPosition; PRUint16 textRangeListLength,selectionStart,selectionEnd, - textRangeType, i; + textRangeType, caretPosition, i; nsIDOMTextRange* textRange; haveSelectedRange = PR_FALSE; + haveCaretPosition = PR_FALSE; + #ifdef DEBUG_tague PRUint16 listlen,start,stop,type; @@ -266,6 +268,11 @@ NS_IMETHODIMP IMETextTxn::CollapseTextSelection(void) textRange->GetRangeStart(&selectionStart); textRange->GetRangeEnd(&selectionEnd); } + if (textRangeType==nsIDOMTextRange::TEXTRANGE_CARETPOSITION) + { + haveCaretPosition = PR_TRUE; + textRange->GetRangeStart(&caretPosition); + } } } } @@ -275,9 +282,12 @@ NS_IMETHODIMP IMETextTxn::CollapseTextSelection(void) if (NS_SUCCEEDED(result) && selection){ if (haveSelectedRange) { result = selection->Collapse(mElement,mOffset+selectionStart); - result = selection->Extend(mElement,mOffset+selectionEnd+1); + result = selection->Extend(mElement,mOffset+selectionEnd); } else { - result = selection->Collapse(mElement,mOffset+mStringToInsert.Length()); + if (haveCaretPosition) + result = selection->Collapse(mElement,mOffset+caretPosition); + else + result = selection->Collapse(mElement,mOffset+mStringToInsert.Length()); } } diff --git a/widget/src/mac/nsMacEventHandler.cpp b/widget/src/mac/nsMacEventHandler.cpp index 09ddbb3e8a1e..cdf1fcbc1722 100644 --- a/widget/src/mac/nsMacEventHandler.cpp +++ b/widget/src/mac/nsMacEventHandler.cpp @@ -1108,16 +1108,18 @@ PRBool nsMacEventHandler::HandleOffsetToPosition(long offset,Point* thePoint) // HandleUpdate Event // //------------------------------------------------------------------------- - nsMacEventHandler::HandleUpdate(Handle textHandle,ScriptCode script,long fixedLength) + nsMacEventHandler::HandleUpdateInputArea(char* text,Size text_size, ScriptCode textScript,long fixedLength,TextRangeArray* textRangeList) { TextToUnicodeInfo textToUnicodeInfo; TextEncoding textEncodingFromScript; - ByteCount text_size, source_read; + ByteCount source_read; + ByteOffset sourceOffset[2], destinationOffset[2]; + ItemCount destinationLength; + nsTextRangeArray xpTextRangeArray; PRBool rv; + int i; OSErr err; - HLock(textHandle); - // // if we aren't in composition mode alredy, signal the backing store w/ the mode change // @@ -1129,47 +1131,89 @@ PRBool nsMacEventHandler::HandleOffsetToPosition(long offset,Point* thePoint) // // convert our script code (smKeyScript) to a TextEncoding // - err = ::UpgradeScriptInfoToTextEncoding(script,kTextLanguageDontCare,kTextRegionDontCare,nsnull, + err = ::UpgradeScriptInfoToTextEncoding(textScript,kTextLanguageDontCare,kTextRegionDontCare,nsnull, &textEncodingFromScript); - NS_ASSERTION(err==noErr,"nsMacEventHandler::HandleUpdate: UpgradeScriptInfoToTextEncoding failed."); - if (err!=noErr) { ::HUnlock(textHandle); return PR_FALSE; } + NS_ASSERTION(err==noErr,"nsMacEventHandler::UpdateInputArea: UpgradeScriptInfoToTextEncoding failed."); + if (err!=noErr) { return PR_FALSE; } err = ::CreateTextToUnicodeInfoByEncoding(textEncodingFromScript,&textToUnicodeInfo); - NS_ASSERTION(err==noErr,"nsMacEventHandler::HandleUpdate: CreateUnicodeToTextInfoByEncoding failed."); - if (err!=noErr) { ::HUnlock(textHandle); return PR_FALSE; } + NS_ASSERTION(err==noErr,"nsMacEventHandler::UpdateInputArea: CreateUnicodeToTextInfoByEncoding failed."); + if (err!=noErr) { return PR_FALSE; } - text_size = ::GetHandleSize(textHandle); - if (mIMECompositionStringSize < (text_size+1)*3) { - mIMECompositionStringSize = (text_size+1)*3; + if (mIMECompositionStringSize < text_size+32) { + mIMECompositionStringSize = text_size+32; if (mIMECompositionString!=nsnull) delete [] mIMECompositionString; - mIMECompositionString = new PRUnichar[(text_size+1)*3]; + mIMECompositionString = new PRUnichar[mIMECompositionStringSize]; } // - // convert the text from the Update event into Unicode + // build up the nsGUIEvent text range array and convert the destination string to Unicode // - err = ::ConvertFromTextToUnicode(textToUnicodeInfo, - text_size,*textHandle, - kUnicodeLooseMappingsMask, - 0,NULL,NULL,NULL, - mIMECompositionStringSize*sizeof(PRUnichar),&source_read, - &mIMECompositionStringLength,mIMECompositionString); - - NS_ASSERTION(err==noErr,"nsMacEventHandler::HandleUpdate: ConverFromTextToUnicode failed."); - if (err!=noErr) { ::HUnlock(textHandle); ::DisposeTextToUnicodeInfo(&textToUnicodeInfo); return PR_FALSE; } + if (textRangeList!=NULL) { + + xpTextRangeArray = new nsTextRange[textRangeList->fNumOfRanges]; + NS_ASSERTION(xpTextRangeArray!=NULL,"nsMacEventHandler::UpdateInputArea: xpTextRangeArray memory allocation failed."); + if (xpTextRangeArray==NULL) { ::DisposeTextToUnicodeInfo(&textToUnicodeInfo); return PR_FALSE; } + + // + // the TEC offset mapping capabilities won't work here because you need to have unique, ordered offsets + // so instead we iterate over the range list and map each range individually. it's probably faster than + // trying to do collapse all the ranges into a single offset list + // + for(i=0;ifNumOfRanges;i++) { + + sourceOffset[0] = textRangeList->fRange[i].fStart; + sourceOffset[1] = textRangeList->fRange[i].fEnd; + + err = ::ConvertFromTextToUnicode(textToUnicodeInfo,text_size,text,kUnicodeLooseMappingsMask, + 2,sourceOffset,&destinationLength,destinationOffset, + mIMECompositionStringSize*sizeof(PRUnichar), + &source_read,&mIMECompositionStringLength,mIMECompositionString); + NS_ASSERTION(err==noErr,"nsMacEventHandler::UpdateInputArea: ConvertFromTextToUnicode failed.\n"); + if (err!=noErr) { ::DisposeTextToUnicodeInfo(&textToUnicodeInfo); return PR_FALSE; } + + if (destinationLength==2) { + xpTextRangeArray[i].mStartOffset = destinationOffset[0]/sizeof(PRUnichar); + xpTextRangeArray[i].mEndOffset = destinationOffset[1]/sizeof(PRUnichar); + xpTextRangeArray[i].mRangeType = textRangeList->fRange[i].fHiliteStyle; + } else { + xpTextRangeArray[i].mStartOffset = destinationOffset[0]/sizeof(PRUnichar); + xpTextRangeArray[i].mEndOffset = destinationOffset[0]/sizeof(PRUnichar); + xpTextRangeArray[i].mRangeType = textRangeList->fRange[i].fHiliteStyle; + } + } + } else { + + err = ::ConvertFromTextToUnicode(textToUnicodeInfo,text_size,text,kUnicodeLooseMappingsMask, + 0,NULL,NULL,NULL, + mIMECompositionStringSize*sizeof(PRUnichar), + &source_read,&mIMECompositionStringLength,mIMECompositionString); + NS_ASSERTION(err==noErr,"nsMacEventHandler::UpdateInputArea: ConvertFromTextToUnicode failed.\n"); + if (err!=noErr) { ::DisposeTextToUnicodeInfo(&textToUnicodeInfo); return PR_FALSE; } + + xpTextRangeArray = new nsTextRange[1]; + xpTextRangeArray[0].mStartOffset = 0; + xpTextRangeArray[0].mEndOffset = (mIMECompositionStringLength/sizeof(PRUnichar)); + xpTextRangeArray[0].mRangeType = NS_TEXTRANGE_RAWINPUT; + } // // null terminate the string for the XP-stuff // mIMECompositionString[mIMECompositionStringLength/sizeof(PRUnichar)] = (PRUnichar)0; - - rv = HandleTextEvent(); - - ::HUnlock(textHandle); - ::DisposeTextToUnicodeInfo(&textToUnicodeInfo); - if (fixedLength==-1 || fixedLength==text_size) { + if (textRangeList==NULL) + rv = HandleTextEvent(1,xpTextRangeArray); + else + rv = HandleTextEvent(textRangeList->fNumOfRanges,xpTextRangeArray); + + ::DisposeTextToUnicodeInfo(&textToUnicodeInfo); + + // + // text_size incldues the null-terminator which isn't included in the fixedLength + // + if (fixedLength==-1 || fixedLength==text_size-1) { HandleEndComposition(); mIMEIsComposing = PR_FALSE; } @@ -1264,7 +1308,7 @@ PRBool nsMacEventHandler::HandleEndComposition(void) // HandleTextEvent // //------------------------------------------------------------------------- -PRBool nsMacEventHandler::HandleTextEvent(void) +PRBool nsMacEventHandler::HandleTextEvent(PRUint32 textRangeCount, nsTextRangeArray textRangeArray) { // // get the focused widget [tague: may need to rethink this later] @@ -1291,11 +1335,8 @@ PRBool nsMacEventHandler::HandleTextEvent(void) textEvent.point.y = 0; textEvent.time = PR_IntervalNow(); textEvent.theText = mIMECompositionString; - textEvent.rangeCount = 1; - textEvent.rangeArray = new nsTextRange[1]; - textEvent.rangeArray[0].mStartOffset = 0; - textEvent.rangeArray[0].mEndOffset = 1; - textEvent.rangeArray[0].mRangeType = 0x01; + textEvent.rangeCount = textRangeCount; + textEvent.rangeArray = textRangeArray; // // nsGUIEvent parts diff --git a/widget/src/mac/nsMacEventHandler.h b/widget/src/mac/nsMacEventHandler.h index 69c2ad111b9a..bacebcdb953f 100644 --- a/widget/src/mac/nsMacEventHandler.h +++ b/widget/src/mac/nsMacEventHandler.h @@ -48,7 +48,7 @@ public: // virtual long HandlePositionToOffset(Point aPoint,short* regionClass); virtual PRBool HandleOffsetToPosition(long offset,Point* position); - virtual PRBool HandleUpdate(Handle textHandle,ScriptCode script,long fixedLength); + virtual PRBool HandleUpdateInputArea(char* text,Size text_size, ScriptCode textScript,long fixedLength,TextRangeArray* textRangeArray); protected: #if 1 @@ -70,7 +70,7 @@ protected: PRUint32 aMessage); virtual PRBool HandleStartComposition(void); virtual PRBool HandleEndComposition(void); - virtual PRBool HandleTextEvent(void); + virtual PRBool HandleTextEvent(PRUint32 textRangeCount, nsTextRangeArray textRangeArray); public: virtual void NotifyDelete(void* aDeletedObject); diff --git a/widget/src/mac/nsMacTSMMessagePump.cpp b/widget/src/mac/nsMacTSMMessagePump.cpp index 54e48353d701..63e75c1c1ab1 100644 --- a/widget/src/mac/nsMacTSMMessagePump.cpp +++ b/widget/src/mac/nsMacTSMMessagePump.cpp @@ -187,11 +187,12 @@ pascal OSErr nsMacTSMMessagePump::UpdateHandler(const AppleEvent *theAppleEvent, DescType returnedType; nsMacEventHandler* eventHandler; Size actualSize; - AEDesc text; + AEDesc text, hiliteRangeArray; ScriptCode textScript; long fixLength; PRBool rv; - + TextRangeArray* hiliteRangePtr; + // // refcon stores the nsMacEventHandler // @@ -218,21 +219,47 @@ pascal OSErr nsMacTSMMessagePump::UpdateHandler(const AppleEvent *theAppleEvent, &fixLength,sizeof(fixLength),&actualSize); NS_ASSERTION(err==noErr,"nsMacTSMMessagePump::UpdateHandler: AEGetParamPtr[fixlen] failed."); if (err!=noErr) return err; + + // + // extract the hilite ranges (optional param) + // + err = AEGetParamDesc(theAppleEvent,keyAEHiliteRange,typeTextRangeArray,&hiliteRangeArray); + NS_ASSERTION(err==noErr||err==errAEDescNotFound,"nsMacTSMMessagePump::UpdateHandler: AEGetParamPtr[fixlen] failed."); + if (err==errAEDescNotFound) hiliteRangePtr=NULL; + else if (err==noErr) { ::HLock(hiliteRangeArray.dataHandle); hiliteRangePtr=(TextRangeArray*)*(hiliteRangeArray.dataHandle);} + else return err; + #if TARGET_CARBON - void* textPtr; - err = AEGetDescData(&text,(unsigned long)typeChar,textPtr,fixLength); - if (err!=noErr) return err; - rv = eventHandler->HandleUpdate((char**)&textPtr,textScript,fixLength); -#else - rv = eventHandler->HandleUpdate(text.dataHandle,textScript,fixLength); + // еее Fix Me !!!!! + rv = eventHandler->HandleUpdateInputArea((char*)textPtr,textScript,fixLength,hiliteRangePtr); +#else + ::HLock(text.dataHandle); + Size text_size = GetHandleSize(text.dataHandle); + char* mbcsText = new char[text_size+1]; + strncpy(mbcsText,*(text.dataHandle),text_size); + mbcsText[text_size]=0; + + // + // must pass HandleUpdateInputArea a null-terminated multibyte string, the text size must include the terminator + // + rv = eventHandler->HandleUpdateInputArea(mbcsText,text_size+1,textScript,fixLength,hiliteRangePtr); + #endif - NS_ASSERTION(rv==PR_TRUE,"nsMAcMessagePump::UpdateHandler: HandleUpdated failed."); + NS_ASSERTION(rv==PR_TRUE,"nsMacMessagePump::UpdateHandler: HandleUpdated failed."); if (rv!=PR_TRUE) return paramErr; // // clean up // +#if !TARGET_CARBON + ::HUnlock(text.dataHandle); + ::HUnlock(hiliteRangeArray.dataHandle); + delete [] mbcsText; + +#endif + (void)AEDisposeDesc(&text); + (void)AEDisposeDesc(&hiliteRangeArray); return noErr; }