/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is the Mozilla browser. * * The Initial Developer of the Original Code is * Netscape Communications, Inc. * Portions created by the Initial Developer are Copyright (C) 1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Frank Yung-Fong Tang * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ /* * The embedding application could choose to install either Carbon Event Handler * or Apple Event to implement Asian Input Method and/or Unicode keyboard mapping. * * This file is a sample implementation of how ot use Carbon Text Input event handler * that. Example of Apple event handler could be found at nsMacTSMMessagePump.{h,cpp} */ #include "CTextInputEventHandler.h" #include "nsCRT.h" #include "nsAutoBuffer.h" #pragma mark - #pragma mark - //************************************************************************************* // GetGeckoTarget //************************************************************************************* CBrowserShell* CTextInputEventHandler::GetGeckoTarget() { return dynamic_cast (LCommander::GetTarget()); } #pragma mark - //************************************************************************************* // GetScriptLang //************************************************************************************* OSStatus CTextInputEventHandler::GetScriptLang(EventRef inEvent, ScriptLanguageRecord& outSlr ) { OSStatus err = ::GetEventParameter(inEvent, kEventParamTextInputSendSLRec, typeIntlWritingCode, NULL, sizeof(outSlr), NULL, &outSlr); return err; } //************************************************************************************* // GetText //************************************************************************************* OSStatus CTextInputEventHandler::GetText(EventRef inEvent, nsString& outString) { UInt32 neededSize; outString.Truncate(0); OSStatus err = ::GetEventParameter(inEvent, kEventParamTextInputSendText, typeUnicodeText, NULL, 0, &neededSize, NULL); if (noErr != err) return err; if (neededSize > 0) { nsAutoBuffer buf; if (! buf.EnsureElemCapacity(neededSize/sizeof(PRUnichar))) return eventParameterNotFoundErr; err = ::GetEventParameter(inEvent, kEventParamTextInputSendText, typeUnicodeText, NULL, neededSize, &neededSize, buf.get()); if (noErr == err) outString.Assign(buf.get(), neededSize/sizeof(PRUnichar)); } return err; } #pragma mark - //************************************************************************************* // HandleUnicodeForKeyEvent //************************************************************************************* OSStatus CTextInputEventHandler::HandleUnicodeForKeyEvent( CBrowserShell* aBrowserShell, EventHandlerCallRef inHandlerCallRef, EventRef inEvent) { NS_ENSURE_TRUE(aBrowserShell, eventNotHandledErr); EventRef keyboardEvent; OSStatus err = ::GetEventParameter(inEvent, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(keyboardEvent), NULL, &keyboardEvent); if (noErr != err) return eventParameterNotFoundErr; // Check first to see if the key event is a cmd-key or control-key. // If so, return eventNotHandledErr, and the keydown event will end // up being handled by LEventDispatcher::EventKeyDown() which is the // standard PowerPlant handling. UInt32 keyModifiers; err = ::GetEventParameter(keyboardEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers); if ((noErr == err) && (keyModifiers & (cmdKey | controlKey))) return eventNotHandledErr; EventRecord eventRecord; if (! ::ConvertEventRefToEventRecord(keyboardEvent, &eventRecord)) return eventParameterNotFoundErr; // printf("uk1- %d %d %d %d %d\n", eventRecord.what, eventRecord.message, eventRecord.when, eventRecord.where, eventRecord.modifiers); ScriptLanguageRecord slr; err = GetScriptLang(inEvent, slr); if (noErr != err) return eventParameterNotFoundErr; nsAutoString text; err = GetText(inEvent, text); if (noErr != err) return eventParameterNotFoundErr; // printf("call HandleUnicodeForKeyEvent textlength = %d script=%d language=%d\n", text.Length(), slr.fScript, slr.fLanguage); err = aBrowserShell->HandleUnicodeForKeyEvent(text, slr.fScript, slr.fLanguage, &eventRecord); // printf("err = %d\n", err); return err; } //************************************************************************************* // HandleUpdateActiveInputArea //************************************************************************************* OSStatus CTextInputEventHandler::HandleUpdateActiveInputArea( CBrowserShell* aBrowserShell, EventHandlerCallRef inHandlerCallRef, EventRef inEvent) { NS_ENSURE_TRUE(aBrowserShell, eventNotHandledErr); PRUint32 fixLength; OSStatus err = ::GetEventParameter(inEvent, kEventParamTextInputSendFixLen, typeLongInteger, NULL, sizeof(fixLength), NULL, &fixLength); if (noErr != err) return eventParameterNotFoundErr; ScriptLanguageRecord slr; err = GetScriptLang(inEvent, slr); if (noErr != err) return eventParameterNotFoundErr; nsAutoString text; err = GetText(inEvent, text); if (noErr != err) return eventParameterNotFoundErr; // kEventParamTextInputSendHiliteRng is optional parameter, don't return if we cannot get it. TextRangeArray* hiliteRng = nsnull; UInt32 rngSize=0; err = ::GetEventParameter(inEvent, kEventParamTextInputSendHiliteRng, typeTextRangeArray, NULL, 0, NULL, &rngSize); if (noErr == err) { TextRangeArray* pt = (TextRangeArray*)::malloc(rngSize); NS_WARN_IF_FALSE( (pt), "Cannot malloc for hiliteRng") ; if (pt) { hiliteRng = pt; err = ::GetEventParameter(inEvent, kEventParamTextInputSendHiliteRng, typeTextRangeArray, NULL, rngSize, &rngSize, hiliteRng); NS_WARN_IF_FALSE( (noErr == err), "Cannot get hiliteRng") ; } } // printf("call HandleUpdateActiveInputArea textlength = %d ",text.Length()); // printf("script=%d language=%d fixlen=%d\n", slr.fScript, slr.fLanguage, fixLength / 2); err = aBrowserShell->HandleUpdateActiveInputArea(text, slr.fScript, slr.fLanguage, fixLength / sizeof(PRUnichar), hiliteRng); if (hiliteRng) ::free(hiliteRng); return err; } //************************************************************************************* // HandleUpdateActiveInputArea //************************************************************************************* OSStatus CTextInputEventHandler::HandleGetSelectedText( CBrowserShell* aBrowserShell, EventHandlerCallRef inHandlerCallRef, EventRef inEvent) { NS_ENSURE_TRUE(aBrowserShell, eventNotHandledErr); nsAutoString outString; OSStatus err = aBrowserShell->HandleGetSelectedText(outString); if (noErr != err) return eventParameterNotFoundErr; err = ::SetEventParameter(inEvent, kEventParamTextInputReplyText, typeUnicodeText, outString.Length()*sizeof(PRUnichar), outString.get()); return err; } //************************************************************************************* // HandleOffsetToPos //************************************************************************************* OSStatus CTextInputEventHandler::HandleOffsetToPos( CBrowserShell* aBrowserShell, EventHandlerCallRef inHandlerCallRef, EventRef inEvent) { NS_ENSURE_TRUE(aBrowserShell, eventNotHandledErr); PRUint32 offset; OSStatus err = ::GetEventParameter(inEvent, kEventParamTextInputSendTextOffset, typeLongInteger, NULL, sizeof(offset), NULL, &offset); if (noErr != err) return eventParameterNotFoundErr; Point thePoint; // printf("call HandleOffsetToPos offset = %d\n", offset); err = aBrowserShell->HandleOffsetToPos(offset, &thePoint.h, &thePoint.v); // printf("return %d, %d\n", thePoint.v, thePoint.h); if (noErr != err) return eventParameterNotFoundErr; err = ::SetEventParameter(inEvent, kEventParamTextInputReplyPoint, typeQDPoint, sizeof(thePoint), &thePoint); return err; } //************************************************************************************* // HandlePosToOffset //************************************************************************************* OSStatus CTextInputEventHandler::HandlePosToOffset( CBrowserShell* aBrowserShell, EventHandlerCallRef inHandlerCallRef, EventRef inEvent) { NS_ENSURE_TRUE(aBrowserShell, eventNotHandledErr); PRInt32 offset; Point thePoint; short regionClass; OSStatus err = ::GetEventParameter(inEvent, kEventParamTextInputSendCurrentPoint, typeQDPoint, NULL, sizeof(thePoint), NULL, &thePoint); if (noErr != err) return eventParameterNotFoundErr; // printf("call HandlePosToOffset Point = %d, %d\n", thePoint.h, thePoint.v); err = aBrowserShell->HandlePosToOffset(thePoint.h, thePoint.v, &offset, ®ionClass); // printf("return offset = %d, region = %d\n", offset, regionClass); if (noErr != err) return eventParameterNotFoundErr; err = ::SetEventParameter(inEvent, kEventParamTextInputReplyRegionClass, typeShortInteger, sizeof(regionClass), ®ionClass); if (noErr != err) return eventParameterNotFoundErr; err = ::SetEventParameter(inEvent, kEventParamTextInputReplyTextOffset, typeLongInteger, sizeof(offset), &offset); return err; } //************************************************************************************* // HandleAll //************************************************************************************* OSStatus CTextInputEventHandler::HandleAll(EventHandlerCallRef inHandlerCallRef, EventRef inEvent) { CBrowserShell* aBrowserShell = GetGeckoTarget(); // if this is not an event for Gecko, just return eventNotHandledErr and let // OS to fallback to class event handling if (!aBrowserShell) return eventNotHandledErr; UInt32 eventClass = ::GetEventClass(inEvent); if (eventClass != kEventClassTextInput) return eventNotHandledErr; UInt32 eventKind = ::GetEventKind(inEvent); if ((kEventTextInputUpdateActiveInputArea != eventKind) && (kEventTextInputUnicodeForKeyEvent!= eventKind) && (kEventTextInputOffsetToPos != eventKind) && (kEventTextInputPosToOffset != eventKind) && (kEventTextInputGetSelectedText != eventKind)) return eventNotHandledErr; switch(eventKind) { case kEventTextInputUpdateActiveInputArea: return HandleUpdateActiveInputArea(aBrowserShell, inHandlerCallRef, inEvent); case kEventTextInputUnicodeForKeyEvent: return HandleUnicodeForKeyEvent(aBrowserShell, inHandlerCallRef, inEvent); case kEventTextInputOffsetToPos: return HandleOffsetToPos(aBrowserShell, inHandlerCallRef, inEvent); case kEventTextInputPosToOffset: return HandlePosToOffset(aBrowserShell, inHandlerCallRef, inEvent); case kEventTextInputGetSelectedText: return HandleGetSelectedText(aBrowserShell, inHandlerCallRef, inEvent); } return eventNotHandledErr; } #pragma mark - //************************************************************************************* // TextInputHandler //************************************************************************************* static pascal OSStatus TextInputHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) { CTextInputEventHandler* realHandler = (CTextInputEventHandler*)inUserData; return realHandler->HandleAll(inHandlerCallRef, inEvent); } //************************************************************************************* // InitializeTextInputEventHandling //************************************************************************************* void InitializeTextInputEventHandling() { static CTextInputEventHandler Singleton; EventTypeSpec eventTypes[5] = { {kEventClassTextInput, kEventTextInputUpdateActiveInputArea }, {kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }, {kEventClassTextInput, kEventTextInputOffsetToPos }, {kEventClassTextInput, kEventTextInputPosToOffset }, {kEventClassTextInput, kEventTextInputGetSelectedText } }; EventHandlerUPP textInputUPP = NewEventHandlerUPP(TextInputHandler); OSStatus err = InstallApplicationEventHandler( textInputUPP, 5, eventTypes, &Singleton, NULL); NS_ASSERTION(err==noErr, "Cannot install carbon event"); }