LayoutTests:
authordarin <darin@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 9 Oct 2005 02:57:21 +0000 (02:57 +0000)
committerdarin <darin@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 9 Oct 2005 02:57:21 +0000 (02:57 +0000)
        Reviewed by Darin.

        - Added a test for http://bugzilla.opendarwin.org/show_bug.cgi?id=4707
          Need a way to automatically test for regressions in NSTextInput implementation

        * editing/input/text-input-controller-expected.txt: Added.
        * editing/input/text-input-controller.html: Added.

WebKitTools:

        Reviewed, rearranged and landed by Darin.

        - fixed http://bugzilla.opendarwin.org/show_bug.cgi?id=4707
          Need a way to automatically test for regressions in NSTextInput implementation

        * DumpRenderTree/DumpRenderTree.m:
        (-[WaitUntilDoneDelegate webView:windowScriptObjectAvailable:]):
        Create a text input controller and put it in a property of the window object.

        * DumpRenderTree/TextInputController.h: Added.
        * DumpRenderTree/TextInputController.m: Added.
        * DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj: Added files.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@10793 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/editing/input/text-input-controller-expected.txt [new file with mode: 0644]
LayoutTests/editing/input/text-input-controller.html [new file with mode: 0644]
WebKitTools/ChangeLog
WebKitTools/DumpRenderTree/DumpRenderTree.m
WebKitTools/DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj
WebKitTools/DumpRenderTree/TextInputController.h [new file with mode: 0644]
WebKitTools/DumpRenderTree/TextInputController.m [new file with mode: 0644]

index 26d3e0424620181415ccc0bf908a42a78d2098c3..1df0f1998786b0b8149e4c5f739f39027767fbb8 100644 (file)
@@ -1,3 +1,13 @@
+2005-10-08  Alexey Proskuryakov  <ap@nypop.com>
+
+        Reviewed by Darin.
+
+        - Added a test for http://bugzilla.opendarwin.org/show_bug.cgi?id=4707
+          Need a way to automatically test for regressions in NSTextInput implementation
+
+        * editing/input/text-input-controller-expected.txt: Added.
+        * editing/input/text-input-controller.html: Added.
+
 2005-10-08  Darin Adler  <darin@apple.com>
 
         - Updated test results for fixed http://bugzilla.opendarwin.org/show_bug.cgi?id=3245
diff --git a/LayoutTests/editing/input/text-input-controller-expected.txt b/LayoutTests/editing/input/text-input-controller-expected.txt
new file mode 100644 (file)
index 0000000..c5fbc7d
--- /dev/null
@@ -0,0 +1,29 @@
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldInsertText:to be deleted replacingDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > BODY > HTML > #document givenAction:WebViewInsertActionTyped
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 13 of #text > DIV > BODY > HTML > #document to 13 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 13 of #text > DIV > BODY > HTML > #document to 13 of #text > DIV > BODY > HTML > #document toDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 13 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldDeleteDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 13 of #text > DIV > BODY > HTML > #document
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > BODY > HTML > #document toDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+Success
+
diff --git a/LayoutTests/editing/input/text-input-controller.html b/LayoutTests/editing/input/text-input-controller.html
new file mode 100644 (file)
index 0000000..2126704
--- /dev/null
@@ -0,0 +1,61 @@
+<html>
+<head>
+<style>
+body { margin: 0; padding: 0 }
+</style>
+</head>
+<body>
+<div contenteditable>FAILURE</div>
+<script type="text/javascript">
+
+    if (window.layoutTestController) {
+        
+        try {
+        
+            layoutTestController.dumpAsText();
+            document.execCommand("SelectAll");
+        
+            textInputController.insertText("to be deleted");
+            textInputController.doCommand("selectAll:");
+            textInputController.doCommand("delete:");
+    
+            textInputController.setMarkedText("Failure", 0, 7);
+            if (textInputController.hasMarkedText() && textInputController.markedRange().toString() == "0,7")
+                textInputController.setMarkedText("Success", 0, 7);
+            
+            var textAttributes = textInputController.validAttributesForMarkedText();
+            textInputController.unmarkText();
+    
+            textInputController.doCommand("selectAll:");
+            if (textInputController.hasMarkedText() || textInputController.selectedRange().toString() != "0,7") {
+                textInputController.doCommand("delete:");
+                textInputController.insertText("Failure");
+            }
+    
+            var charRect = textInputController.firstRectForCharacterRange(0, 1);
+            textInputController.characterIndexForPoint(0, 0); // currently unimplemented
+            textInputController.substringFromRange(1, 1); // currently unimplemented
+            textInputController.conversationIdentifier(); // just an identifier...
+            
+            textAttributes = textAttributes.toString();
+            if (-1 == textAttributes.indexOf("NSUnderline"))
+                textInputController.insertText("Attribute NSUnderline is missing");
+
+            if (-1 == textAttributes.indexOf("NSUnderlineColor"))
+                textInputController.insertText("Attribute NSUnderlineColor is missing");
+
+            if (-1 == textAttributes.indexOf("NSMarkedClauseSegment"))
+                textInputController.insertText("Attribute NSMarkedClauseSegment is missing");
+
+            if (-1 == textAttributes.indexOf("NSTextInputReplacementRangeAttributeName"))
+                textInputController.insertText("Attribute NSTextInputReplacementRangeAttributeName is missing");
+
+        } catch (ex) {
+            document.write("Exception: " + ex.description);
+        }
+    } else {
+        document.write("(cannot run interactively)");
+    }
+</script>
+</body>
+</html>
index 7bda61fbdb6257b2b6bc0ce4f654e7cd194ba30d..14a18ffe82e402a3257f5da36658ed593344b3cc 100644 (file)
@@ -1,3 +1,18 @@
+2005-10-08  Alexey Proskuryakov  <ap@nypop.com>
+
+        Reviewed, rearranged and landed by Darin.
+
+        - fixed http://bugzilla.opendarwin.org/show_bug.cgi?id=4707
+          Need a way to automatically test for regressions in NSTextInput implementation
+
+        * DumpRenderTree/DumpRenderTree.m:
+        (-[WaitUntilDoneDelegate webView:windowScriptObjectAvailable:]):
+        Create a text input controller and put it in a property of the window object.
+
+        * DumpRenderTree/TextInputController.h: Added.
+        * DumpRenderTree/TextInputController.m: Added.
+        * DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj: Added files.
+
 2005-10-06  Darin Adler  <darin@apple.com>
 
         * Scripts/cvs-apply: Fixed merge option to work better when not all directories
index ca182fb27e9ca03d5ae4a631edb7bcf2fdcd0a8b..853f96451b46582184aaafa21dc4b1aee367e4bb 100644 (file)
@@ -46,6 +46,8 @@
 #import <CommonCrypto/CommonDigest.h>
 #import <getopt.h>
 
+#import "TextInputController.h"
+
 @interface WaitUntilDoneDelegate : NSObject
 @end
 
@@ -273,12 +275,14 @@ static void dump(void)
 - (void)webView:(WebView *)sender windowScriptObjectAvailable:(WebScriptObject *)obj 
 { 
     LayoutTestController *ltc = [[LayoutTestController alloc] init];
-    [(id)obj setValue:ltc forKey:@"layoutTestController"];
+    [obj setValue:ltc forKey:@"layoutTestController"];
     [ltc release];
     EventSendingController *esc = [[EventSendingController alloc] init];
-    [(id)obj setValue:esc forKey:@"eventSender"];
+    [obj setValue:esc forKey:@"eventSender"];
     [esc release];
-
+    TextInputController *tic = [[TextInputController alloc] initWithWebView:sender];
+    [obj setValue:tic forKey:@"textInputController"];
+    [tic release];
 }
 
 - (void)webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message
index c0b67cb5b941f8a9f398aa447ddeda1b6d13c974..c28bc08c0950f0d5232fd44fbd1e9e91eaacfd74 100644 (file)
@@ -38,6 +38,8 @@
                9340994C08540CAE007F3BC8 /* DumpRenderTreePrefix.h in Headers */ = {isa = PBXBuildFile; fileRef = 32A70AAB03705E1F00C91783 /* DumpRenderTreePrefix.h */; };
                9340994E08540CAE007F3BC8 /* DumpRenderTree.m in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* DumpRenderTree.m */; settings = {ATTRIBUTES = (); }; };
                9340995108540CAE007F3BC8 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9335435F03D75502008635CE /* WebKit.framework */; };
+               93442CF608F8BA4900BFE8CA /* TextInputController.h in Headers */ = {isa = PBXBuildFile; fileRef = 93442CF408F8BA4900BFE8CA /* TextInputController.h */; };
+               93442CF708F8BA4900BFE8CA /* TextInputController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93442CF508F8BA4900BFE8CA /* TextInputController.m */; };
                A817090008B163EF00CCB9FB /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A84F608908B136DA00E9745F /* Cocoa.framework */; };
                A817090208B1643800CCB9FB /* WebCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A817090108B1643800CCB9FB /* WebCore.framework */; };
                A817090408B164D300CCB9FB /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A817090308B164D300CCB9FB /* JavaScriptCore.framework */; };
@@ -87,6 +89,8 @@
                32A70AAB03705E1F00C91783 /* DumpRenderTreePrefix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DumpRenderTreePrefix.h; sourceTree = "<group>"; };
                9335435F03D75502008635CE /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = WebKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
                9340995408540CAF007F3BC8 /* DumpRenderTree */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = DumpRenderTree; sourceTree = BUILT_PRODUCTS_DIR; };
+               93442CF408F8BA4900BFE8CA /* TextInputController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextInputController.h; sourceTree = "<group>"; };
+               93442CF508F8BA4900BFE8CA /* TextInputController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TextInputController.m; sourceTree = "<group>"; };
                A817090108B1643800CCB9FB /* WebCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = WebCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
                A817090308B164D300CCB9FB /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = JavaScriptCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
                A84F608908B136DA00E9745F /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
                08FB7794FE84155DC02AAC07 /* DumpRenderTree */ = {
                        isa = PBXGroup;
                        children = (
-                               B5A7525808AF4A3600138E45 /* ImageDiff.m */,
                                08FB7796FE84155DC02AAC07 /* DumpRenderTree.m */,
                                32A70AAB03705E1F00C91783 /* DumpRenderTreePrefix.h */,
+                               93442CF408F8BA4900BFE8CA /* TextInputController.h */,
+                               93442CF508F8BA4900BFE8CA /* TextInputController.m */,
+                               B5A7525808AF4A3600138E45 /* ImageDiff.m */,
                                9335435F03D75502008635CE /* WebKit.framework */,
                                A817090308B164D300CCB9FB /* JavaScriptCore.framework */,
                                A817090108B1643800CCB9FB /* WebCore.framework */,
                        buildActionMask = 2147483647;
                        files = (
                                9340994C08540CAE007F3BC8 /* DumpRenderTreePrefix.h in Headers */,
+                               93442CF608F8BA4900BFE8CA /* TextInputController.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        buildActionMask = 2147483647;
                        files = (
                                9340994E08540CAE007F3BC8 /* DumpRenderTree.m in Sources */,
+                               93442CF708F8BA4900BFE8CA /* TextInputController.m in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
diff --git a/WebKitTools/DumpRenderTree/TextInputController.h b/WebKitTools/DumpRenderTree/TextInputController.h
new file mode 100644 (file)
index 0000000..92644cd
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2005 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Foundation/Foundation.h>
+
+@class WebView;
+
+@interface TextInputController : NSObject
+{
+    WebView *webView;
+}
+- (id)initWithWebView:(WebView *)view;
+@end
diff --git a/WebKitTools/DumpRenderTree/TextInputController.m b/WebKitTools/DumpRenderTree/TextInputController.m
new file mode 100644 (file)
index 0000000..b0ef4b7
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2005 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "TextInputController.h"
+
+#import <AppKit/NSInputManager.h>
+#import <WebKit/WebDocument.h>
+#import <WebKit/WebFrame.h>
+#import <WebKit/WebFrameView.h>
+#import <WebKit/WebView.h>
+
+@implementation TextInputController
+
+// FIXME: need to support attributed strings
+
++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
+{
+    if (aSelector == @selector(insertText:)
+            || aSelector == @selector(doCommand:)
+            || aSelector == @selector(setMarkedText:selectedFrom:length:)
+            || aSelector == @selector(unmarkText)
+            || aSelector == @selector(hasMarkedText)
+            || aSelector == @selector(conversationIdentifier)
+            || aSelector == @selector(substringFrom:length:)
+            || aSelector == @selector(markedRange)
+            || aSelector == @selector(selectedRange)
+            || aSelector == @selector(firstRectForCharactersFrom:length:)
+            || aSelector == @selector(characterIndexForPointX:Y:)
+            || aSelector == @selector(validAttributesForMarkedText))
+        return NO;
+    return YES;
+}
+
++ (NSString *)webScriptNameForSelector:(SEL)aSelector
+{
+    if (aSelector == @selector(insertText:))
+        return @"insertText";
+    else if (aSelector == @selector(doCommand:))
+        return @"doCommand";
+    else if (aSelector == @selector(setMarkedText:selectedFrom:length:))
+        return @"setMarkedText";
+    else if (aSelector == @selector(substringFrom:length:))
+        return @"substringFromRange";
+    else if (aSelector == @selector(firstRectForCharactersFrom:length:))
+        return @"firstRectForCharacterRange";
+    else if (aSelector == @selector(characterIndexForPointX:Y:))
+        return @"characterIndexForPoint";
+
+    return nil;
+}
+
+- (id)initWithWebView:(WebView *)wv
+{
+    self = [super init];
+    webView = wv;
+    return self;
+}
+
+- (NSObject <NSTextInput> *)textInput
+{
+    NSView <WebDocumentView> *view = [[[webView mainFrame] frameView] documentView];
+    return [view conformsToProtocol:@protocol(NSTextInput)] ? view : nil;
+}
+
+- (void)insertText:(NSString *)aString
+{
+    NSObject <NSTextInput> *textInput = [self textInput];
+
+    if (textInput)
+        [textInput insertText:aString];
+}
+
+- (void)doCommand:(NSString *)aCommand
+{
+    NSObject <NSTextInput> *textInput = [self textInput];
+
+    if (textInput)
+        [textInput doCommandBySelector:NSSelectorFromString(aCommand)];
+}
+
+- (void)setMarkedText:(NSString *)aString selectedFrom:(int)from length:(int)length
+{
+    NSObject <NSTextInput> *textInput = [self textInput];
+    if (textInput)
+        [textInput setMarkedText:aString selectedRange:NSMakeRange(from, length)];
+}
+
+- (void)unmarkText
+{
+    NSObject <NSTextInput> *textInput = [self textInput];
+
+    if (textInput)
+        [textInput unmarkText];
+}
+
+- (BOOL)hasMarkedText
+{
+    NSObject <NSTextInput> *textInput = [self textInput];
+
+    if (textInput)
+        return [textInput hasMarkedText];
+
+    return FALSE;
+}
+
+- (long)conversationIdentifier
+{
+    NSObject <NSTextInput> *textInput = [self textInput];
+
+    if (textInput)
+        return [textInput conversationIdentifier];
+
+    return 0;
+}
+
+- (NSString *)substringFrom:(int)from length:(int)length
+{
+    NSObject <NSTextInput> *textInput = [self textInput];
+
+    if (textInput)
+        return [[textInput attributedSubstringFromRange:NSMakeRange(from, length)] string];
+    
+    return @"";
+}
+
+- (NSArray *)markedRange
+{
+    NSObject <NSTextInput> *textInput = [self textInput];
+
+    if (textInput) {
+        NSRange range = [textInput markedRange];
+        return [NSArray arrayWithObjects:[NSNumber numberWithUnsignedInt:range.location], [NSNumber numberWithUnsignedInt:range.length], nil];
+    }
+
+    return nil;
+}
+
+- (NSArray *)selectedRange
+{
+    NSObject <NSTextInput> *textInput = [self textInput];
+
+    if (textInput) {
+        NSRange range = [textInput selectedRange];
+        return [NSArray arrayWithObjects:[NSNumber numberWithUnsignedInt:range.location], [NSNumber numberWithUnsignedInt:range.length], nil];
+    }
+
+    return nil;
+}
+  
+
+- (NSArray *)firstRectForCharactersFrom:(int)from length:(int)length
+{
+    NSObject <NSTextInput> *textInput = [self textInput];
+
+    if (textInput) {
+        NSRect rect = [textInput firstRectForCharacterRange:NSMakeRange(from, length)];
+        return [NSArray arrayWithObjects:
+                    [NSNumber numberWithFloat:rect.origin.x],
+                    [NSNumber numberWithFloat:rect.origin.y],
+                    [NSNumber numberWithFloat:rect.size.width],
+                    [NSNumber numberWithFloat:rect.size.height],
+                    nil];
+    }
+
+    return nil;
+}
+
+- (int)characterIndexForPointX:(float)x Y:(float)y
+{
+    NSObject <NSTextInput> *textInput = [self textInput];
+
+    if (textInput)
+        return [textInput characterIndexForPoint:NSMakePoint(x, y)];
+
+    return 0;
+}
+
+- (NSArray *)validAttributesForMarkedText
+{
+    NSObject <NSTextInput> *textInput = [self textInput];
+
+    if (textInput)
+        return [textInput validAttributesForMarkedText];
+
+    return nil;
+}
+
+@end