     mute: false
 
     # raw characters
-    inputBuffer: ''
-    # synchonize with the text buffer
-    outputBuffer: ''
+    rawInput: ''
     # visual marker
     textBufferMarker: null
 


    constructor: (@core) ->

        @on 'deactivate', (range) =>
            log 'IM', "deactivate #{range}"
            @deactivate()

        @on 'insert', (range, char) =>
            log 'IM', "insert '#{char}'"
            {output, further, suggestionKeys, candidateSymbols} = @translate @inputBuffer
            log 'IM', "@inputBuffer: '#{@inputBuffer}' translates to '#{output}'"
            log 'IM', "candidateSymbols: #{candidateSymbols}" if candidateSymbols.length > 1
            @updateOutputBuffer output
            if further
                @core.panelModel.setInputMethod @inputBuffer, suggestionKeys, candidateSymbols
            else
                @deactivate()

        @on 'delete', (range, textBuffer) =>
            {output, further, suggestionKeys, candidateSymbols} = @translate @inputBuffer
            log 'IM', "delete #{range} #{textBuffer} #{@inputBuffer}"
            if further
                @core.panelModel.setInputMethod @inputBuffer, suggestionKeys, candidateSymbols


    activate: ->
        if not @activated

            # initializations
            log 'IM', 'activated'
            @inputBuffer = ''
            @outputBuffer = ''
            @activated = true

            # monitors raw text buffer and figures out what happend


    dispatchEvent: (ev) =>

        unless @mute

            rangeOld = new Range ev.oldTailBufferPosition, ev.oldHeadBufferPosition
            rangeNew = new Range ev.newTailBufferPosition, ev.newHeadBufferPosition
            textBuffer = @core.editor.getBuffer().getTextInRange rangeNew
            char = textBuffer.substr -1

            # const for result of Range::compare()
            INSERT = -1
            DELETE = 1
            change = rangeNew.compare rangeOld


            if rangeNew.isEmpty()
                @deactivate()
            else if change is INSERT
                char = textBuffer.substr -1
                @rawInput += char
                log 'IM', "insert '#{char}' #{@rawInput}"
                {translation, further, suggestionKeys, candidateSymbols} = @translate @rawInput
                log 'IM', "raw input '#{@rawInput}' translates to '#{translation}'"

                # reflects current translation to the text buffer
                if translation
                    @muteEvent => @replaceString translation

                # update view
                if further
                    @core.panelModel.setInputMethod @inputBuffer, suggestionKeys, candidateSymbols
                else
                    @deactivate()

            else if change is DELETE
                @rawInput = @rawInput.substr(0, @rawInput.length - 1)
                log 'IM', "delete #{@rawInput}"


    #######################
    ###   Text Buffer   ###
    #######################

    # inserts 1 character to the text buffer (may trigger some events)
    insertChar: (char) ->
        @core.editor.getBuffer().insert @textBufferMarker.getBufferRange().end, char

    # replace content of the marker with supplied string (may trigger some events)
    replaceString: (str) ->
        @core.editor.getBuffer().setTextInRange @textBufferMarker.getBufferRange(), str

    ##################
    ###   Keymap   ###
