12fc2651226baac27029e38c9d6ef883fa32084dbSteve Block/*
22fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * Copyright (C) 2011 Igalia S.L.
32fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *
42fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * Redistribution and use in source and binary forms, with or without
52fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * modification, are permitted provided that the following conditions
62fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * are met:
72fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *
82fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * 1.  Redistributions of source code must retain the above copyright
92fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *     notice, this list of conditions and the following disclaimer.
102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * 2.  Redistributions in binary form must reproduce the above copyright
112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *     notice, this list of conditions and the following disclaimer in the
122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *     documentation and/or other materials provided with the distribution.
132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *     its contributors may be used to endorse or promote products derived
152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *     from this software without specific prior written permission.
162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block *
172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block */
282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "config.h"
302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "TextInputController.h"
312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "DumpRenderTree.h"
332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "WebCoreSupport/DumpRenderTreeSupportGtk.h"
342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include <GOwnPtrGtk.h>
352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include <JavaScriptCore/JSObjectRef.h>
362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include <JavaScriptCore/JSRetainPtr.h>
372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include <JavaScriptCore/JSStringRef.h>
382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include <cstring>
392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include <webkit/webkit.h>
402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
412fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic JSValueRef setMarkedTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
422fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!view)
452fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return JSValueMakeUndefined(context);
462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (argumentCount < 3)
482fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return JSValueMakeUndefined(context);
492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    JSStringRef string = JSValueToStringCopy(context, arguments[0], exception);
512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    size_t bufferSize = JSStringGetMaximumUTF8CStringSize(string);
542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    GOwnPtr<gchar> stringBuffer(static_cast<gchar*>(g_malloc(bufferSize)));
552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    JSStringGetUTF8CString(string, stringBuffer.get(), bufferSize);
562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    JSStringRelease(string);
572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    int start = static_cast<int>(JSValueToNumber(context, arguments[1], exception));
592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    int end = static_cast<int>(JSValueToNumber(context, arguments[2], exception));
622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    DumpRenderTreeSupportGtk::setComposition(view, stringBuffer.get(), start, end);
652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return JSValueMakeUndefined(context);
672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
692fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic JSValueRef insertTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!view)
732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return JSValueMakeUndefined(context);
742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
752fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (argumentCount < 1)
762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return JSValueMakeUndefined(context);
772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    JSStringRef string = JSValueToStringCopy(context, arguments[0], exception);
792fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
812fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    size_t bufferSize = JSStringGetMaximumUTF8CStringSize(string);
822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    GOwnPtr<gchar> stringBuffer(static_cast<gchar*>(g_malloc(bufferSize)));
832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    JSStringGetUTF8CString(string, stringBuffer.get(), bufferSize);
842fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    JSStringRelease(string);
852fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
862fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    DumpRenderTreeSupportGtk::confirmComposition(view, stringBuffer.get());
872fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
882fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return JSValueMakeUndefined(context);
892fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
912fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic JSValueRef unmarkTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!view)
952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return JSValueMakeUndefined(context);
962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    DumpRenderTreeSupportGtk::confirmComposition(view, 0);
982fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return JSValueMakeUndefined(context);
992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
1002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1012fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic JSValueRef firstRectForCharacterRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
1032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
1042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!view)
1052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return JSValueMakeUndefined(context);
1062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (argumentCount < 2)
1082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return JSValueMakeUndefined(context);
1092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    int location = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
1112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
1122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    int length = static_cast<int>(JSValueToNumber(context, arguments[1], exception));
1142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
1152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    GdkRectangle rect;
1172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!DumpRenderTreeSupportGtk::firstRectForCharacterRange(view, location, length, &rect))
1182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return JSValueMakeUndefined(context);
1192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    JSValueRef arrayValues[4];
1212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    arrayValues[0] = JSValueMakeNumber(context, rect.x);
1222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    arrayValues[1] = JSValueMakeNumber(context, rect.y);
1232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    arrayValues[2] = JSValueMakeNumber(context, rect.width);
1242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    arrayValues[3] = JSValueMakeNumber(context, rect.height);
1252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    JSObjectRef arrayObject = JSObjectMakeArray(context, 4, arrayValues, exception);
1262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
1272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return arrayObject;
1292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
1302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1312fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic JSValueRef selectedRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
1322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
1332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
1342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!view)
1352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return JSValueMakeUndefined(context);
1362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    int start, end;
1382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!DumpRenderTreeSupportGtk::selectedRange(view, &start, &end))
1392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return JSValueMakeUndefined(context);
1402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    JSValueRef arrayValues[2];
1422fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    arrayValues[0] = JSValueMakeNumber(context, start);
1432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    arrayValues[1] = JSValueMakeNumber(context, end);
1442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    JSObjectRef arrayObject = JSObjectMakeArray(context, 2, arrayValues, exception);
1452fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
1462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return arrayObject;
1482fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
1492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1502fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic JSStaticFunction staticFunctions[] = {
1512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    { "setMarkedText", setMarkedTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    { "insertText", insertTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    { "unmarkText", unmarkTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    { "firstRectForCharacterRange", firstRectForCharacterRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    { "selectedRange", selectedRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
1562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    { 0, 0, 0 }
1572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block};
1582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1592fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic JSClassRef getClass(JSContextRef context)
1602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
1612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    static JSClassRef textInputControllerClass = 0;
1622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!textInputControllerClass) {
1642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        JSClassDefinition classDefinition = {
1652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                0, 0, 0, 0, 0, 0,
1662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        classDefinition.staticFunctions = staticFunctions;
1682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        textInputControllerClass = JSClassCreate(&classDefinition);
1702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
1712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return textInputControllerClass;
1732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
1742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1752fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockJSObjectRef makeTextInputController(JSContextRef context)
1762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
1772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return JSObjectMake(context, getClass(context), 0);
1782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
179