     0 0 <NSRange> :> effective-range
     text -> string CF>string :> str
     str utf16n encode :> byte-16n
-    0 :> cp-loc!    
+    0 :> cp-loc!
     "NSMarkedClauseSegment" <NSString> :> segment-attr
     [ effective-range [ location>> ] [ length>> ] bi + text-length < ] [
         text


    ! Text input
    METHOD: void insertText: id text replacementRange: NSRange replacementRange [
            self window :> window
            window [
                "" clone :> str!
                text NSString -> class -> isKindOfClass: 0 = not [
                    text CF>string str!               
                ] [
                    text -> string CF>string str!               
                ] if
                window world-focus :> gadget
                gadget [
                    gadget support-input-methods? [                        
                        replacementRange location>> NSNotFound = [                        
                            gadget editor-caret first
                            dup gadget editor-line
                            [ 
                                replacementRange location>> >codepoint-index
                                2array gadget set-caret
                            ] [
                                replacementRange [ location>> ] [ length>> ] bi + 
                                >codepoint-index
                                2array gadget set-mark
                            ] 2bi                        
                        ] unless
                        gadget preedit? [
                            gadget [ remove-preedit-text ] [ remove-preedit-info ] bi
                            str gadget user-input* drop
                            f gadget preedit-selection-mode?<<
                        ] [
                            str window user-input                           
                        ] if
                    ] [ 
                        str window user-input
                    ] if
                ] when
            ] when
        ] ;

    METHOD: char hasMarkedText [
            self window :> window
            window [
                window world-focus :> gadget
                gadget [
                    gadget preedit? [ 1 ] [ 0 ] if
                ] [ 0 ] if
            ] [ 0 ] if
        ] ;

    METHOD: NSRange markedRange [ 
            self window :> window
            window [
                window world-focus :> gadget
                gadget [
                    gadget preedit? [
                        gadget [ preedit-start>> second ] [ preedit-end>> second ] bi >= [ 
                            NSNotFound 0 
                        ] [
                            gadget preedit-start>> first gadget editor-line :> str
                            gadget
                            [ preedit-start>> second ]                 ! location
                            [ preedit-end>> second ]
                            bi [ str swap >utf16-index ] bi@ over -    ! length
                        ] if
                    ] [  NSNotFound 0 ] if
                ] [  NSNotFound 0 ] if
            ] [ NSNotFound 0 ] if
            <NSRange>
        ] ;

    METHOD: NSRange selectedRange [
            self window :> window
            window [
                window world-focus :> gadget
                gadget [
                    gadget support-input-methods? [
                        gadget editor-caret first gadget editor-line :> str
                        gadget preedit? [
                            str
                            gadget
                            [ preedit-selected-start>> second ]
                            [ preedit-start>> second ] 
                            bi - >utf16-index                        ! location
                            gadget
                            [ preedit-selected-end>> second ]
                            [ preedit-selected-start>> second ]
                            bi [ str swap >utf16-index ] bi@ -       ! length
                        ] [                            
                            str gadget editor-caret second >utf16-index 0
                        ] if
                    ] [ 0 0 ] if
                ] [ 0 0 ] if
            ] [ 0 0 ] if 
            <NSRange>
        ] ;
   
    METHOD: void setMarkedText: id text selectedRange: NSRange selectedRange
                                     replacementRange: NSRange replacementRange [           
            self window :> window
            window [
                window world-focus :> gadget
                gadget [
                    { } clone :> underlines!
                    "" clone :> str!
                    text NSString -> class -> isKindOfClass: 0 = not [
                        text CF>string str!               
                    ] [
                        text -> string CF>string str!               
                        gadget support-input-methods? [
                            gadget text selectedRange make-preedit-underlines underlines!
                        ] when
                    ] if
                    gadget support-input-methods? [
                        gadget str selectedRange replacementRange update-marked-text
                        underlines gadget preedit-underlines<<
                    ] when
                ] when
            ] when            
        ] ;
             
    METHOD: void unmarkText [ 
            self window :> window
            window [
                window world-focus :> gadget
                gadget [
                    gadget support-input-methods? [
                        gadget preedit? [
                            gadget {
                                [ preedit-start>> second ]
                                [ preedit-end>> second ]
                                [ preedit-start>> first ] [ editor-line ]
                            } cleave subseq
                            gadget [ remove-preedit-text ] [ remove-preedit-info ] bi
                            gadget user-input* drop
                        ] when
                        f gadget preedit-selection-mode?<<
                    ] when
                ] when
            ] when
        ] ;
    
    METHOD: id validAttributesForMarkedText [             
            NSArray "NSMarkedClauseSegment" <NSString> -> arrayWithObject:
        ] ;

    METHOD: id attributedSubstringForProposedRange: NSRange aRange
                                       actualRange: id actualRange [ f ] ;
    
    METHOD: NSUInteger characterIndexForPoint: NSPoint point [ 0 ] ;

    METHOD: NSRect firstRectForCharacterRange: NSRange aRange
                                  actualRange: NSRange actualRange [
            self window :> window
            window [
                window world-focus :> gadget
                gadget [
                    gadget support-input-methods? [
                        gadget editor-caret first gadget editor-line :> str                
                        str aRange location>> >codepoint-index :> start-pos
                        gadget editor-caret first start-pos 2array gadget loc>x
                        gadget caret-loc second gadget caret-dim second + 
                        2array                     ! character pos
                        gadget screen-loc v+       ! + gadget pos 
                        { 1 -1 } v*
                        window handle>> window>> dup -> frame -> contentRectForFrameRect:
                        CGRect-top-left 2array v+  ! + window pos
                        first2 [ >fixnum ] bi@ 0 gadget line-height >fixnum
                    ] [ 0 0 0 0 ] if
                ] [ 0 0 0 0 ] if
            ] [ 0 0 0 0 ] if
            <CGRect>
        ] ;

    METHOD: void doCommandBySelector: SEL selector [ ] ;
    
    ! Initialization
    METHOD: void updateFactorGadgetSize: id notification
    [


:: >codepoint-index ( str utf16-index -- codepoint-index )
    0 utf16-index 2 * str utf16n encode subseq utf16n decode length ;

:: >utf16-index ( str codepoint-index -- utf16-index )
    0 codepoint-index str subseq utf16n encode length 2 / >integer ;

