mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-10 18:00:15 +01:00
358 lines
14 KiB
C++
358 lines
14 KiB
C++
|
/* -*- 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 <ftang@netscape.com>
|
||
|
*
|
||
|
* 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<CBrowserShell*> (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<PRUnichar, 256> 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");
|
||
|
}
|