Further refactoring of text-controller-impl
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-controller-impl.cpp
index 2c1b772..6554a2c 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <dali-toolkit/internal/text/text-controller-impl.h>
 
 // EXTERNAL INCLUDES
 #include <dali-toolkit/internal/text/text-controller-impl.h>
 
 // EXTERNAL INCLUDES
-#include <dali/public-api/adaptor-framework/key.h>
+#include <dali/public-api/rendering/renderer.h>
 #include <dali/integration-api/debug.h>
 #include <dali/integration-api/debug.h>
-#include <limits>
 
 // INTERNAL INCLUDES
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
 #include <dali-toolkit/internal/text/bidirectional-support.h>
 #include <dali-toolkit/internal/text/character-set-conversion.h>
 #include <dali-toolkit/internal/text/color-segmentation.h>
 #include <dali-toolkit/internal/text/bidirectional-support.h>
 #include <dali-toolkit/internal/text/character-set-conversion.h>
 #include <dali-toolkit/internal/text/color-segmentation.h>
 #include <dali-toolkit/internal/text/segmentation.h>
 #include <dali-toolkit/internal/text/shaper.h>
 #include <dali-toolkit/internal/text/text-control-interface.h>
 #include <dali-toolkit/internal/text/segmentation.h>
 #include <dali-toolkit/internal/text/shaper.h>
 #include <dali-toolkit/internal/text/text-control-interface.h>
+#include <dali-toolkit/internal/text/text-controller-impl-event-handler.h>
 #include <dali-toolkit/internal/text/text-run-container.h>
 #include <dali-toolkit/internal/text/text-run-container.h>
+#include <dali-toolkit/internal/text/text-selection-handle-controller.h>
+
+using namespace Dali;
 
 namespace
 {
 
 
 namespace
 {
 
-/**
- * @brief Struct used to calculate the selection box.
- */
-struct SelectionBoxInfo
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
+#endif
+
+#define MAKE_SHADER(A)#A
+
+const char* VERTEX_SHADER_BACKGROUND = MAKE_SHADER(
+attribute mediump vec2    aPosition;
+attribute mediump vec4    aColor;
+varying   mediump vec4    vColor;
+uniform   highp mat4      uMvpMatrix;
+
+void main()
+{
+  mediump vec4 position = vec4( aPosition, 0.0, 1.0 );
+  gl_Position = uMvpMatrix * position;
+  vColor = aColor;
+}
+);
+
+const char* FRAGMENT_SHADER_BACKGROUND = MAKE_SHADER(
+varying mediump vec4      vColor;
+uniform lowp    vec4      uColor;
+
+void main()
+{
+  gl_FragColor = vColor * uColor;
+}
+);
+
+struct BackgroundVertex
 {
 {
-  float lineOffset;
-  float lineHeight;
-  float minX;
-  float maxX;
+  Vector2 mPosition;        ///< Vertex posiiton
+  Vector4 mColor;           ///< Vertex color
 };
 
 };
 
-#if defined(DEBUG_ENABLED)
-  Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
-#endif
+struct BackgroundMesh
+{
+  Vector< BackgroundVertex > mVertices;    ///< container of vertices
+  Vector< unsigned short > mIndices;       ///< container of indices
+};
 
 
-const float MAX_FLOAT = std::numeric_limits<float>::max();
-const float MIN_FLOAT = std::numeric_limits<float>::min();
-const Dali::Toolkit::Text::CharacterDirection LTR = false; ///< Left To Right direction
-const uint32_t STAR = 0x2A;
+const Dali::Vector4 LIGHT_BLUE( 0.75f, 0.96f, 1.f, 1.f );
+const Dali::Vector4 BACKGROUND_SUB4( 0.58f, 0.87f, 0.96f, 1.f );
+const Dali::Vector4 BACKGROUND_SUB5( 0.83f, 0.94f, 0.98f, 1.f );
+const Dali::Vector4 BACKGROUND_SUB6( 1.f, 0.5f, 0.5f, 1.f );
+const Dali::Vector4 BACKGROUND_SUB7( 1.f, 0.8f, 0.8f, 1.f );
 
 } // namespace
 
 
 } // namespace
 
@@ -68,12 +100,13 @@ namespace Toolkit
 namespace Text
 {
 
 namespace Text
 {
 
-EventData::EventData( DecoratorPtr decorator )
+EventData::EventData( DecoratorPtr decorator, InputMethodContext& inputMethodContext )
 : mDecorator( decorator ),
 : mDecorator( decorator ),
-  mImfManager(),
+  mInputMethodContext( inputMethodContext ),
+  mPlaceholderFont( NULL ),
   mPlaceholderTextActive(),
   mPlaceholderTextInactive(),
   mPlaceholderTextActive(),
   mPlaceholderTextInactive(),
-  mPlaceholderTextColor( 0.8f, 0.8f, 0.8f, 0.8f ),
+  mPlaceholderTextColor( 0.8f, 0.8f, 0.8f, 0.8f ), // This color has been published in the Public API (placeholder-properties.h).
   mEventQueue(),
   mInputStyleChangedQueue(),
   mPreviousState( INACTIVE ),
   mEventQueue(),
   mInputStyleChangedQueue(),
   mPreviousState( INACTIVE ),
@@ -84,6 +117,8 @@ EventData::EventData( DecoratorPtr decorator )
   mPreEditStartPosition( 0u ),
   mPreEditLength( 0u ),
   mCursorHookPositionX( 0.f ),
   mPreEditStartPosition( 0u ),
   mPreEditLength( 0u ),
   mCursorHookPositionX( 0.f ),
+  mDoubleTapAction( Controller::NoTextTap::NO_ACTION ),
+  mLongPressAction( Controller::NoTextTap::SHOW_SELECTION_POPUP ),
   mIsShowingPlaceholderText( false ),
   mPreEditFlag( false ),
   mDecoratorUpdated( false ),
   mIsShowingPlaceholderText( false ),
   mPreEditFlag( false ),
   mDecoratorUpdated( false ),
@@ -97,216 +132,31 @@ EventData::EventData( DecoratorPtr decorator )
   mUpdateLeftSelectionPosition( false ),
   mUpdateRightSelectionPosition( false ),
   mIsLeftHandleSelected( false ),
   mUpdateLeftSelectionPosition( false ),
   mUpdateRightSelectionPosition( false ),
   mIsLeftHandleSelected( false ),
+  mIsRightHandleSelected( false ),
   mUpdateHighlightBox( false ),
   mScrollAfterUpdatePosition( false ),
   mScrollAfterDelete( false ),
   mAllTextSelected( false ),
   mUpdateInputStyle( false ),
   mUpdateHighlightBox( false ),
   mScrollAfterUpdatePosition( false ),
   mScrollAfterDelete( false ),
   mAllTextSelected( false ),
   mUpdateInputStyle( false ),
-  mPasswordInput( false )
+  mPasswordInput( false ),
+  mCheckScrollAmount( false ),
+  mIsPlaceholderPixelSize( false ),
+  mIsPlaceholderElideEnabled( false ),
+  mPlaceholderEllipsisFlag( false ),
+  mShiftSelectionFlag( true ),
+  mUpdateAlignment( false ),
+  mEditingEnabled( true )
 {
 {
-  mImfManager = ImfManager::Get();
 }
 
 }
 
-EventData::~EventData()
-{}
-
 bool Controller::Impl::ProcessInputEvents()
 {
 bool Controller::Impl::ProcessInputEvents()
 {
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::ProcessInputEvents\n" );
-  if( NULL == mEventData )
-  {
-    // Nothing to do if there is no text input.
-    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::ProcessInputEvents no event data\n" );
-    return false;
-  }
-
-  if( mEventData->mDecorator )
-  {
-    for( std::vector<Event>::iterator iter = mEventData->mEventQueue.begin();
-         iter != mEventData->mEventQueue.end();
-         ++iter )
-    {
-      switch( iter->type )
-      {
-        case Event::CURSOR_KEY_EVENT:
-        {
-          OnCursorKeyEvent( *iter );
-          break;
-        }
-        case Event::TAP_EVENT:
-        {
-          OnTapEvent( *iter );
-          break;
-        }
-        case Event::LONG_PRESS_EVENT:
-        {
-          OnLongPressEvent( *iter );
-          break;
-        }
-        case Event::PAN_EVENT:
-        {
-          OnPanEvent( *iter );
-          break;
-        }
-        case Event::GRAB_HANDLE_EVENT:
-        case Event::LEFT_SELECTION_HANDLE_EVENT:
-        case Event::RIGHT_SELECTION_HANDLE_EVENT: // Fall through
-        {
-          OnHandleEvent( *iter );
-          break;
-        }
-        case Event::SELECT:
-        {
-          OnSelectEvent( *iter );
-          break;
-        }
-        case Event::SELECT_ALL:
-        {
-          OnSelectAllEvent();
-          break;
-        }
-      }
-    }
-  }
-
-  if( mEventData->mUpdateCursorPosition ||
-      mEventData->mUpdateHighlightBox )
-  {
-    NotifyImfManager();
-  }
-
-  // The cursor must also be repositioned after inserts into the model
-  if( mEventData->mUpdateCursorPosition )
-  {
-    // Updates the cursor position and scrolls the text to make it visible.
-    CursorInfo cursorInfo;
-    // Calculate the cursor position from the new cursor index.
-    GetCursorPosition( mEventData->mPrimaryCursorPosition,
-                       cursorInfo );
-
-    if( mEventData->mUpdateCursorHookPosition )
-    {
-      // Update the cursor hook position. Used to move the cursor with the keys 'up' and 'down'.
-      mEventData->mCursorHookPositionX = cursorInfo.primaryPosition.x;
-      mEventData->mUpdateCursorHookPosition = false;
-    }
-
-    // Scroll first the text after delete ...
-    if( mEventData->mScrollAfterDelete )
-    {
-      ScrollTextToMatchCursor( cursorInfo );
-    }
-
-    // ... then, text can be scrolled to make the cursor visible.
-    if( mEventData->mScrollAfterUpdatePosition )
-    {
-      const Vector2 currentCursorPosition( cursorInfo.primaryPosition.x, cursorInfo.lineOffset );
-      ScrollToMakePositionVisible( currentCursorPosition, cursorInfo.lineHeight );
-    }
-    mEventData->mScrollAfterUpdatePosition = false;
-    mEventData->mScrollAfterDelete = false;
-
-    UpdateCursorPosition( cursorInfo );
-
-    mEventData->mDecoratorUpdated = true;
-    mEventData->mUpdateCursorPosition = false;
-    mEventData->mUpdateGrabHandlePosition = false;
-  }
-  else
-  {
-    CursorInfo leftHandleInfo;
-    CursorInfo rightHandleInfo;
-
-    if( mEventData->mUpdateHighlightBox )
-    {
-      GetCursorPosition( mEventData->mLeftSelectionPosition,
-                         leftHandleInfo );
-
-      GetCursorPosition( mEventData->mRightSelectionPosition,
-                         rightHandleInfo );
-
-      if( mEventData->mScrollAfterUpdatePosition && ( mEventData->mIsLeftHandleSelected ? mEventData->mUpdateLeftSelectionPosition : mEventData->mUpdateRightSelectionPosition ) )
-      {
-        CursorInfo& info = mEventData->mIsLeftHandleSelected ? leftHandleInfo : rightHandleInfo;
-
-        const Vector2 currentCursorPosition( info.primaryPosition.x, info.lineOffset );
-        ScrollToMakePositionVisible( currentCursorPosition, info.lineHeight );
-      }
-    }
-
-    if( mEventData->mUpdateLeftSelectionPosition )
-    {
-      UpdateSelectionHandle( LEFT_SELECTION_HANDLE,
-                             leftHandleInfo );
-
-      SetPopupButtons();
-      mEventData->mDecoratorUpdated = true;
-      mEventData->mUpdateLeftSelectionPosition = false;
-    }
-
-    if( mEventData->mUpdateRightSelectionPosition )
-    {
-      UpdateSelectionHandle( RIGHT_SELECTION_HANDLE,
-                             rightHandleInfo );
-
-      SetPopupButtons();
-      mEventData->mDecoratorUpdated = true;
-      mEventData->mUpdateRightSelectionPosition = false;
-    }
-
-    if( mEventData->mUpdateHighlightBox )
-    {
-      RepositionSelectionHandles();
-
-      mEventData->mUpdateLeftSelectionPosition = false;
-      mEventData->mUpdateRightSelectionPosition = false;
-      mEventData->mUpdateHighlightBox = false;
-    }
-
-    mEventData->mScrollAfterUpdatePosition = false;
-  }
-
-  if( mEventData->mUpdateInputStyle )
-  {
-    // Keep a copy of the current input style.
-    InputStyle currentInputStyle;
-    currentInputStyle.Copy( mEventData->mInputStyle );
-
-    // Set the default style first.
-    RetrieveDefaultInputStyle( mEventData->mInputStyle );
-
-    // Get the character index from the cursor index.
-    const CharacterIndex styleIndex = ( mEventData->mPrimaryCursorPosition > 0u ) ? mEventData->mPrimaryCursorPosition - 1u : 0u;
-
-    // Retrieve the style from the style runs stored in the logical model.
-    mModel->mLogicalModel->RetrieveStyle( styleIndex, mEventData->mInputStyle );
-
-    // Compare if the input style has changed.
-    const bool hasInputStyleChanged = !currentInputStyle.Equal( mEventData->mInputStyle );
-
-    if( hasInputStyleChanged )
-    {
-      const InputStyle::Mask styleChangedMask = currentInputStyle.GetInputStyleChangeMask( mEventData->mInputStyle );
-      // Queue the input style changed signal.
-      mEventData->mInputStyleChangedQueue.PushBack( styleChangedMask );
-    }
-
-    mEventData->mUpdateInputStyle = false;
-  }
-
-  mEventData->mEventQueue.clear();
-
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::ProcessInputEvents\n" );
-
-  const bool decoratorUpdated = mEventData->mDecoratorUpdated;
-  mEventData->mDecoratorUpdated = false;
-
-  return decoratorUpdated;
+  return ControllerImplEventHandler::ProcessInputEvents(*this);
 }
 
 }
 
-void Controller::Impl::NotifyImfManager()
+void Controller::Impl::NotifyInputMethodContext()
 {
 {
-  if( mEventData && mEventData->mImfManager )
+  if( mEventData && mEventData->mInputMethodContext )
   {
     CharacterIndex cursorPosition = GetLogicalCursorPosition();
 
   {
     CharacterIndex cursorPosition = GetLogicalCursorPosition();
 
@@ -322,17 +172,17 @@ void Controller::Impl::NotifyImfManager()
       cursorPosition -= numberOfWhiteSpaces;
     }
 
       cursorPosition -= numberOfWhiteSpaces;
     }
 
-    mEventData->mImfManager.SetCursorPosition( cursorPosition );
-    mEventData->mImfManager.NotifyCursorPosition();
+    mEventData->mInputMethodContext.SetCursorPosition( cursorPosition );
+    mEventData->mInputMethodContext.NotifyCursorPosition();
   }
 }
 
   }
 }
 
-void Controller::Impl::NotifyImfMultiLineStatus()
+void Controller::Impl::NotifyInputMethodContextMultiLineStatus()
 {
 {
-  if ( mEventData )
+  if ( mEventData && mEventData->mInputMethodContext )
   {
     Text::Layout::Engine::Type layout = mLayoutEngine.GetLayout();
   {
     Text::Layout::Engine::Type layout = mLayoutEngine.GetLayout();
-    mEventData->mImfManager.NotifyTextInputMultiLine( layout == Text::Layout::Engine::MULTI_LINE_BOX );
+    mEventData->mInputMethodContext.NotifyTextInputMultiLine( layout == Text::Layout::Engine::MULTI_LINE_BOX );
   }
 }
 
   }
 }
 
@@ -480,11 +330,6 @@ void Controller::Impl::ClearFullModelData( OperationsMask operations )
     mModel->mLogicalModel->mParagraphInfo.Clear();
   }
 
     mModel->mLogicalModel->mParagraphInfo.Clear();
   }
 
-  if( NO_OPERATION != ( GET_WORD_BREAKS & operations ) )
-  {
-    mModel->mLogicalModel->mLineBreakInfo.Clear();
-  }
-
   if( NO_OPERATION != ( GET_SCRIPTS & operations ) )
   {
     mModel->mLogicalModel->mScriptRuns.Clear();
   if( NO_OPERATION != ( GET_SCRIPTS & operations ) )
   {
     mModel->mLogicalModel->mScriptRuns.Clear();
@@ -538,6 +383,7 @@ void Controller::Impl::ClearFullModelData( OperationsMask operations )
   if( NO_OPERATION != ( COLOR & operations ) )
   {
     mModel->mVisualModel->mColorIndices.Clear();
   if( NO_OPERATION != ( COLOR & operations ) )
   {
     mModel->mVisualModel->mColorIndices.Clear();
+    mModel->mVisualModel->mBackgroundColorIndices.Clear();
   }
 }
 
   }
 }
 
@@ -559,15 +405,6 @@ void Controller::Impl::ClearCharacterModelData( CharacterIndex startIndex, Chara
                         mModel->mLogicalModel->mParagraphInfo );
   }
 
                         mModel->mLogicalModel->mParagraphInfo );
   }
 
-  if( NO_OPERATION != ( GET_WORD_BREAKS & operations ) )
-  {
-    // Clear the word break info.
-    WordBreakInfo* wordBreakInfoBuffer = mModel->mLogicalModel->mWordBreakInfo.Begin();
-
-    mModel->mLogicalModel->mWordBreakInfo.Erase( wordBreakInfoBuffer + startIndex,
-                                         wordBreakInfoBuffer + endIndexPlusOne );
-  }
-
   if( NO_OPERATION != ( GET_SCRIPTS & operations ) )
   {
     // Clear the scripts.
   if( NO_OPERATION != ( GET_SCRIPTS & operations ) )
   {
     // Clear the scripts.
@@ -730,6 +567,13 @@ void Controller::Impl::ClearGlyphModelData( CharacterIndex startIndex, Character
       mModel->mVisualModel->mColorIndices.Erase( colorIndexBuffer + mTextUpdateInfo.mStartGlyphIndex,
                                                  colorIndexBuffer + endGlyphIndexPlusOne );
     }
       mModel->mVisualModel->mColorIndices.Erase( colorIndexBuffer + mTextUpdateInfo.mStartGlyphIndex,
                                                  colorIndexBuffer + endGlyphIndexPlusOne );
     }
+
+    if( 0u != mModel->mVisualModel->mBackgroundColorIndices.Count() )
+    {
+      ColorIndex* backgroundColorIndexBuffer = mModel->mVisualModel->mBackgroundColorIndices.Begin();
+      mModel->mVisualModel->mBackgroundColorIndices.Erase( backgroundColorIndexBuffer + mTextUpdateInfo.mStartGlyphIndex,
+                                                           backgroundColorIndexBuffer + endGlyphIndexPlusOne );
+    }
   }
 }
 
   }
 }
 
@@ -769,24 +613,16 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired )
     return false;
   }
 
     return false;
   }
 
-  Vector<Character> utf32CharactersStar;
-  const Length characterCount = mModel->mLogicalModel->mText.Count();
-  const bool isPasswordInput = ( mEventData != NULL && mEventData->mPasswordInput &&
-        !mEventData->mIsShowingPlaceholderText && characterCount > 0 );
-
-  if (isPasswordInput)
+  Vector<Character>& srcCharacters = mModel->mLogicalModel->mText;
+  Vector<Character> displayCharacters;
+  bool useHiddenText = false;
+  if ( mHiddenInput && mEventData != NULL && !mEventData->mIsShowingPlaceholderText)
   {
   {
-    utf32CharactersStar.Resize( characterCount );
-
-    uint32_t* begin = utf32CharactersStar.Begin();
-    uint32_t* end = begin + characterCount;
-    while ( begin < end )
-    {
-      *begin++ = STAR;
-    }
+    mHiddenInput->Substitute( srcCharacters,displayCharacters );
+    useHiddenText = true;
   }
 
   }
 
-  Vector<Character>& utf32Characters = isPasswordInput ? utf32CharactersStar : mModel->mLogicalModel->mText;
+  Vector<Character>& utf32Characters = useHiddenText ? displayCharacters : srcCharacters;
   const Length numberOfCharacters = utf32Characters.Count();
 
   // Index to the first character of the first paragraph to be updated.
   const Length numberOfCharacters = utf32Characters.Count();
 
   // Index to the first character of the first paragraph to be updated.
@@ -795,6 +631,36 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired )
   Length paragraphCharacters = 0u;
 
   CalculateTextUpdateIndices( paragraphCharacters );
   Length paragraphCharacters = 0u;
 
   CalculateTextUpdateIndices( paragraphCharacters );
+
+  // Check whether the indices for updating the text is valid
+  if ( numberOfCharacters > 0u &&
+       ( mTextUpdateInfo.mParagraphCharacterIndex > numberOfCharacters ||
+         mTextUpdateInfo.mRequestedNumberOfCharacters > numberOfCharacters ) )
+  {
+    std::string currentText;
+    Utf32ToUtf8( mModel->mLogicalModel->mText.Begin(), numberOfCharacters, currentText );
+
+    DALI_LOG_ERROR( "Controller::Impl::UpdateModel: mTextUpdateInfo has invalid indices\n" );
+    DALI_LOG_ERROR( "Number of characters: %d, current text is: %s\n", numberOfCharacters, currentText.c_str() );
+
+    // Dump mTextUpdateInfo
+    DALI_LOG_ERROR( "Dump mTextUpdateInfo:\n" );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mCharacterIndex = %u\n", mTextUpdateInfo.mCharacterIndex );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mNumberOfCharactersToRemove = %u\n", mTextUpdateInfo.mNumberOfCharactersToRemove );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mNumberOfCharactersToAdd = %u\n", mTextUpdateInfo.mNumberOfCharactersToAdd );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mPreviousNumberOfCharacters = %u\n", mTextUpdateInfo.mPreviousNumberOfCharacters );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mParagraphCharacterIndex = %u\n", mTextUpdateInfo.mParagraphCharacterIndex );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mRequestedNumberOfCharacters = %u\n", mTextUpdateInfo.mRequestedNumberOfCharacters );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mStartGlyphIndex = %u\n", mTextUpdateInfo.mStartGlyphIndex );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mStartLineIndex = %u\n", mTextUpdateInfo.mStartLineIndex );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mEstimatedNumberOfLines = %u\n", mTextUpdateInfo.mEstimatedNumberOfLines );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mClearAll = %d\n", mTextUpdateInfo.mClearAll );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mFullRelayoutNeeded = %d\n", mTextUpdateInfo.mFullRelayoutNeeded );
+    DALI_LOG_ERROR( "     mTextUpdateInfo.mIsLastCharacterNewParagraph = %d\n", mTextUpdateInfo.mIsLastCharacterNewParagraph );
+
+    return false;
+  }
+
   startIndex = mTextUpdateInfo.mParagraphCharacterIndex;
 
   if( mTextUpdateInfo.mClearAll ||
   startIndex = mTextUpdateInfo.mParagraphCharacterIndex;
 
   if( mTextUpdateInfo.mClearAll ||
@@ -830,19 +696,6 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired )
     updated = true;
   }
 
     updated = true;
   }
 
-  Vector<WordBreakInfo>& wordBreakInfo = mModel->mLogicalModel->mWordBreakInfo;
-  if( NO_OPERATION != ( GET_WORD_BREAKS & operations ) )
-  {
-    // Retrieves the word break info. The word break info is used to layout the text (where to wrap the text in lines).
-    wordBreakInfo.Resize( numberOfCharacters, TextAbstraction::WORD_NO_BREAK );
-
-    SetWordBreakInfo( utf32Characters,
-                      startIndex,
-                      requestedNumberOfCharacters,
-                      wordBreakInfo );
-    updated = true;
-  }
-
   const bool getScripts = NO_OPERATION != ( GET_SCRIPTS & operations );
   const bool validateFonts = NO_OPERATION != ( VALIDATE_FONTS & operations );
 
   const bool getScripts = NO_OPERATION != ( GET_SCRIPTS & operations );
   const bool validateFonts = NO_OPERATION != ( VALIDATE_FONTS & operations );
 
@@ -871,11 +724,30 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired )
 
       // Get the default font's description.
       TextAbstraction::FontDescription defaultFontDescription;
 
       // Get the default font's description.
       TextAbstraction::FontDescription defaultFontDescription;
-      TextAbstraction::PointSize26Dot6 defaultPointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
-      if( NULL != mFontDefaults )
+      TextAbstraction::PointSize26Dot6 defaultPointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE * mFontSizeScale;
+
+      if( IsShowingPlaceholderText() && mEventData && ( NULL != mEventData->mPlaceholderFont ) )
+      {
+        // If the placeholder font is set specifically, only placeholder font is changed.
+        defaultFontDescription = mEventData->mPlaceholderFont->mFontDescription;
+        if( mEventData->mPlaceholderFont->sizeDefined )
+        {
+          defaultPointSize = mEventData->mPlaceholderFont->mDefaultPointSize * mFontSizeScale * 64u;
+        }
+      }
+      else if( NULL != mFontDefaults )
       {
       {
+        // Set the normal font and the placeholder font.
         defaultFontDescription = mFontDefaults->mFontDescription;
         defaultFontDescription = mFontDefaults->mFontDescription;
-        defaultPointSize = mFontDefaults->mDefaultPointSize * 64u;
+
+        if( mTextFitEnabled )
+        {
+          defaultPointSize = mFontDefaults->mFitPointSize * 64u;
+        }
+        else
+        {
+          defaultPointSize = mFontDefaults->mDefaultPointSize * mFontSizeScale * 64u;
+        }
       }
 
       // Validates the fonts. If there is a character with no assigned font it sets a default one.
       }
 
       // Validates the fonts. If there is a character with no assigned font it sets a default one.
@@ -906,7 +778,9 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired )
                           lineBreakInfo,
                           startIndex,
                           requestedNumberOfCharacters,
                           lineBreakInfo,
                           startIndex,
                           requestedNumberOfCharacters,
-                          bidirectionalInfo );
+                          bidirectionalInfo,
+                          mModel->mMatchSystemLanguageDirection,
+                          mLayoutDirection );
 
     if( 0u != bidirectionalInfo.Count() )
     {
 
     if( 0u != bidirectionalInfo.Count() )
     {
@@ -985,6 +859,136 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired )
     updated = true;
   }
 
     updated = true;
   }
 
+  if( ( NULL != mEventData ) &&
+      mEventData->mPreEditFlag &&
+      ( 0u != mModel->mVisualModel->mCharactersToGlyph.Count() ) )
+  {
+    Dali::InputMethodContext::PreEditAttributeDataContainer attrs;
+    mEventData->mInputMethodContext.GetPreeditStyle( attrs );
+    Dali::InputMethodContext::PreeditStyle type = Dali::InputMethodContext::PreeditStyle::NONE;
+
+    // Check the type of preedit and run it.
+    for( Dali::InputMethodContext::PreEditAttributeDataContainer::Iterator it = attrs.Begin(), endIt = attrs.End(); it != endIt; it++ )
+    {
+      Dali::InputMethodContext::PreeditAttributeData attrData = *it;
+      DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::UpdateModel PreeditStyle type : %d  start %d end %d \n", attrData.preeditType, attrData.startIndex, attrData.endIndex  );
+      type = attrData.preeditType;
+
+      // Check the number of commit characters for the start position.
+      unsigned int numberOfCommit = mEventData->mPrimaryCursorPosition - mEventData->mPreEditLength;
+      Length numberOfIndices = attrData.endIndex - attrData.startIndex;
+
+      switch( type )
+      {
+        case Dali::InputMethodContext::PreeditStyle::UNDERLINE:
+        {
+          // Add the underline for the pre-edit text.
+          GlyphRun underlineRun;
+          underlineRun.glyphIndex = attrData.startIndex + numberOfCommit;
+          underlineRun.numberOfGlyphs = numberOfIndices;
+          mModel->mVisualModel->mUnderlineRuns.PushBack( underlineRun );
+          break;
+        }
+        case Dali::InputMethodContext::PreeditStyle::REVERSE:
+        {
+          Vector4 textColor = mModel->mVisualModel->GetTextColor();
+          ColorRun backgroundColorRun;
+          backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
+          backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
+          backgroundColorRun.color = textColor;
+          mModel->mLogicalModel->mBackgroundColorRuns.PushBack( backgroundColorRun );
+
+          Vector4 backgroundColor = mModel->mVisualModel->GetBackgroundColor();
+          Vector<ColorRun>  colorRuns;
+          colorRuns.Resize( 1u );
+          ColorRun& colorRun = *( colorRuns.Begin() );
+          colorRun.color = backgroundColor;
+          colorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
+          colorRun.characterRun.numberOfCharacters = numberOfIndices;
+
+          mModel->mLogicalModel->mColorRuns.PushBack( colorRun );
+          break;
+        }
+        case Dali::InputMethodContext::PreeditStyle::HIGHLIGHT:
+        {
+          ColorRun backgroundColorRun;
+          backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
+          backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
+          backgroundColorRun.color = LIGHT_BLUE;
+          mModel->mLogicalModel->mBackgroundColorRuns.PushBack( backgroundColorRun );
+          break;
+        }
+        case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1:
+        {
+          // CUSTOM_PLATFORM_STYLE_1 should be drawn with background and underline together.
+          ColorRun backgroundColorRun;
+          backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
+          backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
+          backgroundColorRun.color = BACKGROUND_SUB4;
+          mModel->mLogicalModel->mBackgroundColorRuns.PushBack( backgroundColorRun );
+
+          GlyphRun underlineRun;
+          underlineRun.glyphIndex = attrData.startIndex + numberOfCommit;
+          underlineRun.numberOfGlyphs = numberOfIndices;
+          mModel->mVisualModel->mUnderlineRuns.PushBack( underlineRun );
+          break;
+        }
+        case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2:
+        {
+          // CUSTOM_PLATFORM_STYLE_2 should be drawn with background and underline together.
+          ColorRun backgroundColorRun;
+          backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
+          backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
+          backgroundColorRun.color = BACKGROUND_SUB5;
+          mModel->mLogicalModel->mBackgroundColorRuns.PushBack( backgroundColorRun );
+
+          GlyphRun underlineRun;
+          underlineRun.glyphIndex = attrData.startIndex + numberOfCommit;
+          underlineRun.numberOfGlyphs = numberOfIndices;
+          mModel->mVisualModel->mUnderlineRuns.PushBack( underlineRun );
+          break;
+        }
+        case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3:
+        {
+          // CUSTOM_PLATFORM_STYLE_3 should be drawn with background and underline together.
+          ColorRun backgroundColorRun;
+          backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
+          backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
+          backgroundColorRun.color = BACKGROUND_SUB6;
+          mModel->mLogicalModel->mBackgroundColorRuns.PushBack( backgroundColorRun );
+
+          GlyphRun underlineRun;
+          underlineRun.glyphIndex = attrData.startIndex + numberOfCommit;
+          underlineRun.numberOfGlyphs = numberOfIndices;
+          mModel->mVisualModel->mUnderlineRuns.PushBack( underlineRun );
+          break;
+        }
+        case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4:
+        {
+          // CUSTOM_PLATFORM_STYLE_4 should be drawn with background and underline together.
+          ColorRun backgroundColorRun;
+          backgroundColorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
+          backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
+          backgroundColorRun.color = BACKGROUND_SUB7;
+          mModel->mLogicalModel->mBackgroundColorRuns.PushBack( backgroundColorRun );
+
+          GlyphRun underlineRun;
+          underlineRun.glyphIndex = attrData.startIndex + numberOfCommit;
+          underlineRun.numberOfGlyphs = numberOfIndices;
+          mModel->mVisualModel->mUnderlineRuns.PushBack( underlineRun );
+          break;
+        }
+        case Dali::InputMethodContext::PreeditStyle::NONE:
+        default:
+        {
+          break;
+        }
+      }
+    }
+    attrs.Clear();
+    updated = true;
+  }
+
   if( NO_OPERATION != ( COLOR & operations ) )
   {
     // Set the color runs in glyphs.
   if( NO_OPERATION != ( COLOR & operations ) )
   {
     // Set the color runs in glyphs.
@@ -997,29 +1001,19 @@ bool Controller::Impl::UpdateModel( OperationsMask operationsRequired )
                               mModel->mVisualModel->mColors,
                               mModel->mVisualModel->mColorIndices );
 
                               mModel->mVisualModel->mColors,
                               mModel->mVisualModel->mColorIndices );
 
+    // Set the background color runs in glyphs.
+    SetColorSegmentationInfo( mModel->mLogicalModel->mBackgroundColorRuns,
+                              mModel->mVisualModel->mCharactersToGlyph,
+                              mModel->mVisualModel->mGlyphsPerCharacter,
+                              startIndex,
+                              mTextUpdateInfo.mStartGlyphIndex,
+                              requestedNumberOfCharacters,
+                              mModel->mVisualModel->mBackgroundColors,
+                              mModel->mVisualModel->mBackgroundColorIndices );
+
     updated = true;
   }
 
     updated = true;
   }
 
-  if( ( NULL != mEventData ) &&
-      mEventData->mPreEditFlag &&
-      ( 0u != mModel->mVisualModel->mCharactersToGlyph.Count() ) )
-  {
-    // Add the underline for the pre-edit text.
-    const GlyphIndex* const charactersToGlyphBuffer = mModel->mVisualModel->mCharactersToGlyph.Begin();
-    const Length* const glyphsPerCharacterBuffer = mModel->mVisualModel->mGlyphsPerCharacter.Begin();
-
-    const GlyphIndex glyphStart = *( charactersToGlyphBuffer + mEventData->mPreEditStartPosition );
-    const CharacterIndex lastPreEditCharacter = mEventData->mPreEditStartPosition + ( ( mEventData->mPreEditLength > 0u ) ? mEventData->mPreEditLength - 1u : 0u );
-    const Length numberOfGlyphsLastCharacter = *( glyphsPerCharacterBuffer + lastPreEditCharacter );
-    const GlyphIndex glyphEnd = *( charactersToGlyphBuffer + lastPreEditCharacter ) + ( numberOfGlyphsLastCharacter > 1u ? numberOfGlyphsLastCharacter - 1u : 0u );
-
-    GlyphRun underlineRun;
-    underlineRun.glyphIndex = glyphStart;
-    underlineRun.numberOfGlyphs = 1u + glyphEnd - glyphStart;
-
-    // TODO: At the moment the underline runs are only for pre-edit.
-    mModel->mVisualModel->mUnderlineRuns.PushBack( underlineRun );
-  }
 
   // The estimated number of lines. Used to avoid reallocations when layouting.
   mTextUpdateInfo.mEstimatedNumberOfLines = std::max( mModel->mVisualModel->mLines.Count(), mModel->mLogicalModel->mParagraphInfo.Count() );
 
   // The estimated number of lines. Used to avoid reallocations when layouting.
   mTextUpdateInfo.mEstimatedNumberOfLines = std::max( mModel->mVisualModel->mLines.Count(), mModel->mLogicalModel->mParagraphInfo.Count() );
@@ -1103,11 +1097,11 @@ float Controller::Impl::GetDefaultFontLineHeight()
   if( NULL == mFontDefaults )
   {
     TextAbstraction::FontDescription fontDescription;
   if( NULL == mFontDefaults )
   {
     TextAbstraction::FontDescription fontDescription;
-    defaultFontId = mFontClient.GetFontId( fontDescription );
+    defaultFontId = mFontClient.GetFontId( fontDescription, TextAbstraction::FontClient::DEFAULT_POINT_SIZE * mFontSizeScale );
   }
   else
   {
   }
   else
   {
-    defaultFontId = mFontDefaults->GetFontId( mFontClient );
+    defaultFontId = mFontDefaults->GetFontId( mFontClient, mFontDefaults->mDefaultPointSize * mFontSizeScale );
   }
 
   Text::FontMetrics fontMetrics;
   }
 
   Text::FontMetrics fontMetrics;
@@ -1116,554 +1110,98 @@ float Controller::Impl::GetDefaultFontLineHeight()
   return( fontMetrics.ascender - fontMetrics.descender );
 }
 
   return( fontMetrics.ascender - fontMetrics.descender );
 }
 
-void Controller::Impl::OnCursorKeyEvent( const Event& event )
+void Controller::Impl::SetTextSelectionRange(const uint32_t *pStart, const uint32_t *pEnd)
 {
 {
-  if( NULL == mEventData )
+  if( nullptr == mEventData )
   {
   {
-    // Nothing to do if there is no text input.
+    // Nothing to do if there is no text.
     return;
   }
 
     return;
   }
 
-  int keyCode = event.p1.mInt;
-
-  if( Dali::DALI_KEY_CURSOR_LEFT == keyCode )
-  {
-    if( mEventData->mPrimaryCursorPosition > 0u )
-    {
-      mEventData->mPrimaryCursorPosition = CalculateNewCursorIndex( mEventData->mPrimaryCursorPosition - 1u );
-    }
-  }
-  else if( Dali::DALI_KEY_CURSOR_RIGHT == keyCode )
-  {
-    if( mModel->mLogicalModel->mText.Count() > mEventData->mPrimaryCursorPosition )
-    {
-      mEventData->mPrimaryCursorPosition = CalculateNewCursorIndex( mEventData->mPrimaryCursorPosition );
-    }
-  }
-  else if( Dali::DALI_KEY_CURSOR_UP == keyCode )
+  if( mEventData->mSelectionEnabled && (pStart || pEnd))
   {
   {
-    // Get first the line index of the current cursor position index.
-    CharacterIndex characterIndex = 0u;
+    uint32_t length = static_cast<uint32_t>(mModel->mLogicalModel->mText.Count());
 
 
-    if( mEventData->mPrimaryCursorPosition > 0u )
+    if (pStart)
     {
     {
-      characterIndex = mEventData->mPrimaryCursorPosition - 1u;
+      mEventData->mLeftSelectionPosition = std::min(*pStart, length);
     }
     }
-
-    const LineIndex lineIndex = mModel->mVisualModel->GetLineOfCharacter( characterIndex );
-
-    if( lineIndex > 0u )
+    if (pEnd)
     {
     {
-      // Retrieve the cursor position info.
-      CursorInfo cursorInfo;
-      GetCursorPosition( mEventData->mPrimaryCursorPosition,
-                         cursorInfo );
-
-      // Get the line above.
-      const LineRun& line = *( mModel->mVisualModel->mLines.Begin() + ( lineIndex - 1u ) );
-
-      // Get the next hit 'y' point.
-      const float hitPointY = cursorInfo.lineOffset - 0.5f * ( line.ascender - line.descender );
-
-      // Use the cursor hook position 'x' and the next hit 'y' position to calculate the new cursor index.
-      mEventData->mPrimaryCursorPosition = Text::GetClosestCursorIndex( mModel->mVisualModel,
-                                                                        mModel->mLogicalModel,
-                                                                        mMetrics,
-                                                                        mEventData->mCursorHookPositionX,
-                                                                        hitPointY );
+      mEventData->mRightSelectionPosition = std::min(*pEnd, length);
     }
     }
-  }
-  else if(   Dali::DALI_KEY_CURSOR_DOWN == keyCode )
-  {
-    // Get first the line index of the current cursor position index.
-    CharacterIndex characterIndex = 0u;
 
 
-    if( mEventData->mPrimaryCursorPosition > 0u )
+    if (mEventData->mLeftSelectionPosition == mEventData->mRightSelectionPosition)
     {
     {
-      characterIndex = mEventData->mPrimaryCursorPosition - 1u;
+      ChangeState( EventData::EDITING );
+      mEventData->mPrimaryCursorPosition = mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition;
+      mEventData->mUpdateCursorPosition = true;
     }
     }
-
-    const LineIndex lineIndex = mModel->mVisualModel->GetLineOfCharacter( characterIndex );
-
-    if( lineIndex + 1u < mModel->mVisualModel->mLines.Count() )
+    else
     {
     {
-      // Retrieve the cursor position info.
-      CursorInfo cursorInfo;
-      GetCursorPosition( mEventData->mPrimaryCursorPosition,
-                         cursorInfo );
-
-      // Get the line below.
-      const LineRun& line = *( mModel->mVisualModel->mLines.Begin() + lineIndex + 1u );
-
-      // Get the next hit 'y' point.
-      const float hitPointY = cursorInfo.lineOffset + cursorInfo.lineHeight + 0.5f * ( line.ascender - line.descender );
-
-      // Use the cursor hook position 'x' and the next hit 'y' position to calculate the new cursor index.
-      mEventData->mPrimaryCursorPosition = Text::GetClosestCursorIndex( mModel->mVisualModel,
-                                                                        mModel->mLogicalModel,
-                                                                        mMetrics,
-                                                                        mEventData->mCursorHookPositionX,
-                                                                        hitPointY );
+      ChangeState( EventData::SELECTING );
+      mEventData->mUpdateHighlightBox = true;
+      mEventData->mUpdateLeftSelectionPosition = true;
+      mEventData->mUpdateRightSelectionPosition = true;
     }
   }
     }
   }
-
-  mEventData->mUpdateCursorPosition = true;
-  mEventData->mUpdateInputStyle = true;
-  mEventData->mScrollAfterUpdatePosition = true;
 }
 
 }
 
-void Controller::Impl::OnTapEvent( const Event& event )
+CharacterIndex Controller::Impl::GetPrimaryCursorPosition() const
 {
 {
-  if( NULL != mEventData )
+  if( nullptr == mEventData )
   {
   {
-    const unsigned int tapCount = event.p1.mUint;
-
-    if( 1u == tapCount )
-    {
-      if( IsShowingRealText() )
-      {
-        // Convert from control's coords to text's coords.
-        const float xPosition = event.p2.mFloat - mModel->mScrollPosition.x;
-        const float yPosition = event.p3.mFloat - mModel->mScrollPosition.y;
-
-        // Keep the tap 'x' position. Used to move the cursor.
-        mEventData->mCursorHookPositionX = xPosition;
-
-        mEventData->mPrimaryCursorPosition = Text::GetClosestCursorIndex( mModel->mVisualModel,
-                                                                          mModel->mLogicalModel,
-                                                                          mMetrics,
-                                                                          xPosition,
-                                                                          yPosition );
-
-        // When the cursor position is changing, delay cursor blinking
-        mEventData->mDecorator->DelayCursorBlink();
-      }
-      else
-      {
-        mEventData->mPrimaryCursorPosition = 0u;
-      }
-
-      mEventData->mUpdateCursorPosition = true;
-      mEventData->mUpdateGrabHandlePosition = true;
-      mEventData->mScrollAfterUpdatePosition = true;
-      mEventData->mUpdateInputStyle = true;
-
-      // Notify the cursor position to the imf manager.
-      if( mEventData->mImfManager )
-      {
-        mEventData->mImfManager.SetCursorPosition( mEventData->mPrimaryCursorPosition );
-        mEventData->mImfManager.NotifyCursorPosition();
-      }
-    }
+    return 0;
   }
   }
+  return mEventData->mPrimaryCursorPosition;
 }
 
 }
 
-void Controller::Impl::OnPanEvent( const Event& event )
+bool Controller::Impl::SetPrimaryCursorPosition( CharacterIndex index )
 {
 {
-  if( NULL == mEventData )
+  if( nullptr == mEventData )
   {
   {
-    // Nothing to do if there is no text input.
-    return;
+    // Nothing to do if there is no text.
+    return false;
   }
 
   }
 
-  const bool isHorizontalScrollEnabled = mEventData->mDecorator->IsHorizontalScrollEnabled();
-  const bool isVerticalScrollEnabled = mEventData->mDecorator->IsVerticalScrollEnabled();
-
-  if( !isHorizontalScrollEnabled && !isVerticalScrollEnabled )
+  if( mEventData->mPrimaryCursorPosition == index )
   {
   {
-    // Nothing to do if scrolling is not enabled.
-    return;
+    // Nothing for same cursor position.
+    return false;
   }
 
   }
 
-  const int state = event.p1.mInt;
+  uint32_t length = static_cast<uint32_t>(mModel->mLogicalModel->mText.Count());
+  mEventData->mPrimaryCursorPosition = std::min(index, length);
+  ChangeState( EventData::EDITING );
+  mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition = mEventData->mPrimaryCursorPosition;
+  mEventData->mUpdateCursorPosition = true;
+  ScrollTextToMatchCursor();
+  return true;
+}
+
+Uint32Pair Controller::Impl::GetTextSelectionRange() const
+{
+  Uint32Pair range;
 
 
-  switch( state )
+  if( mEventData )
   {
   {
-    case Gesture::Started:
-    {
-      // Will remove the cursor, handles or text's popup, ...
-      ChangeState( EventData::TEXT_PANNING );
-      break;
-    }
-    case Gesture::Continuing:
-    {
-      const Vector2& layoutSize = mModel->mVisualModel->GetLayoutSize();
-      const Vector2 currentScroll = mModel->mScrollPosition;
-
-      if( isHorizontalScrollEnabled )
-      {
-        const float displacementX = event.p2.mFloat;
-        mModel->mScrollPosition.x += displacementX;
-
-        ClampHorizontalScroll( layoutSize );
-      }
-
-      if( isVerticalScrollEnabled )
-      {
-        const float displacementY = event.p3.mFloat;
-        mModel->mScrollPosition.y += displacementY;
-
-        ClampVerticalScroll( layoutSize );
-      }
-
-      mEventData->mDecorator->UpdatePositions( mModel->mScrollPosition - currentScroll );
-      break;
-    }
-    case Gesture::Finished:
-    case Gesture::Cancelled: // FALLTHROUGH
-    {
-      // Will go back to the previous state to show the cursor, handles, the text's popup, ...
-      ChangeState( mEventData->mPreviousState );
-      break;
-    }
-    default:
-      break;
+    range.first = mEventData->mLeftSelectionPosition;
+    range.second = mEventData->mRightSelectionPosition;
   }
   }
-}
-
-void Controller::Impl::OnLongPressEvent( const Event& event )
-{
-  DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::OnLongPressEvent\n" );
 
 
-  if( EventData::EDITING == mEventData->mState )
-  {
-    ChangeState ( EventData::EDITING_WITH_POPUP );
-    mEventData->mDecoratorUpdated = true;
-    mEventData->mUpdateInputStyle = true;
-  }
+  return range;
 }
 
 }
 
-void Controller::Impl::OnHandleEvent( const Event& event )
+bool Controller::Impl::IsEditable() const
 {
 {
-  if( NULL == mEventData )
-  {
-    // Nothing to do if there is no text input.
-    return;
-  }
-
-  const unsigned int state = event.p1.mUint;
-  const bool handleStopScrolling = ( HANDLE_STOP_SCROLLING == state );
-  const bool isSmoothHandlePanEnabled = mEventData->mDecorator->IsSmoothHandlePanEnabled();
-
-  if( HANDLE_PRESSED == state )
-  {
-    // Convert from decorator's coords to text's coords.
-    const float xPosition = event.p2.mFloat - mModel->mScrollPosition.x;
-    const float yPosition = event.p3.mFloat - mModel->mScrollPosition.y;
-
-    // Need to calculate the handle's new position.
-    const CharacterIndex handleNewPosition = Text::GetClosestCursorIndex( mModel->mVisualModel,
-                                                                          mModel->mLogicalModel,
-                                                                          mMetrics,
-                                                                          xPosition,
-                                                                          yPosition );
-
-    if( Event::GRAB_HANDLE_EVENT == event.type )
-    {
-      ChangeState ( EventData::GRAB_HANDLE_PANNING );
-
-      if( handleNewPosition != mEventData->mPrimaryCursorPosition )
-      {
-        // Updates the cursor position if the handle's new position is different than the current one.
-        mEventData->mUpdateCursorPosition = true;
-        // Does not update the grab handle position if the smooth panning is enabled. (The decorator does it smooth).
-        mEventData->mUpdateGrabHandlePosition = !isSmoothHandlePanEnabled;
-        mEventData->mPrimaryCursorPosition = handleNewPosition;
-      }
-
-      // Updates the decorator if the soft handle panning is enabled. It triggers a relayout in the decorator and the new position of the handle is set.
-      mEventData->mDecoratorUpdated = isSmoothHandlePanEnabled;
-    }
-    else if( Event::LEFT_SELECTION_HANDLE_EVENT == event.type )
-    {
-      ChangeState ( EventData::SELECTION_HANDLE_PANNING );
-
-      if( ( handleNewPosition != mEventData->mLeftSelectionPosition ) &&
-          ( handleNewPosition != mEventData->mRightSelectionPosition ) )
-      {
-        // Updates the highlight box if the handle's new position is different than the current one.
-        mEventData->mUpdateHighlightBox = true;
-        // Does not update the selection handle position if the smooth panning is enabled. (The decorator does it smooth).
-        mEventData->mUpdateLeftSelectionPosition = !isSmoothHandlePanEnabled;
-        mEventData->mLeftSelectionPosition = handleNewPosition;
-      }
-
-      // Updates the decorator if the soft handle panning is enabled. It triggers a relayout in the decorator and the new position of the handle is set.
-      mEventData->mDecoratorUpdated = isSmoothHandlePanEnabled;
-
-      // Will define the order to scroll the text to match the handle position.
-      mEventData->mIsLeftHandleSelected = true;
-    }
-    else if( Event::RIGHT_SELECTION_HANDLE_EVENT == event.type )
-    {
-      ChangeState ( EventData::SELECTION_HANDLE_PANNING );
-
-      if( ( handleNewPosition != mEventData->mRightSelectionPosition ) &&
-          ( handleNewPosition != mEventData->mLeftSelectionPosition ) )
-      {
-        // Updates the highlight box if the handle's new position is different than the current one.
-        mEventData->mUpdateHighlightBox = true;
-        // Does not update the selection handle position if the smooth panning is enabled. (The decorator does it smooth).
-        mEventData->mUpdateRightSelectionPosition = !isSmoothHandlePanEnabled;
-        mEventData->mRightSelectionPosition = handleNewPosition;
-      }
-
-      // Updates the decorator if the soft handle panning is enabled. It triggers a relayout in the decorator and the new position of the handle is set.
-      mEventData->mDecoratorUpdated = isSmoothHandlePanEnabled;
-
-      // Will define the order to scroll the text to match the handle position.
-      mEventData->mIsLeftHandleSelected = false;
-    }
-  } // end ( HANDLE_PRESSED == state )
-  else if( ( HANDLE_RELEASED == state ) ||
-           handleStopScrolling )
-  {
-    CharacterIndex handlePosition = 0u;
-    if( handleStopScrolling || isSmoothHandlePanEnabled )
-    {
-      // Convert from decorator's coords to text's coords.
-      const float xPosition = event.p2.mFloat - mModel->mScrollPosition.x;
-      const float yPosition = event.p3.mFloat - mModel->mScrollPosition.y;
-
-      handlePosition = Text::GetClosestCursorIndex( mModel->mVisualModel,
-                                                    mModel->mLogicalModel,
-                                                    mMetrics,
-                                                    xPosition,
-                                                    yPosition );
-    }
-
-    if( Event::GRAB_HANDLE_EVENT == event.type )
-    {
-      mEventData->mUpdateCursorPosition = true;
-      mEventData->mUpdateGrabHandlePosition = true;
-      mEventData->mUpdateInputStyle = true;
-
-      if( !IsClipboardEmpty() )
-      {
-        ChangeState( EventData::EDITING_WITH_PASTE_POPUP ); // Moving grabhandle will show Paste Popup
-      }
-
-      if( handleStopScrolling || isSmoothHandlePanEnabled )
-      {
-        mEventData->mScrollAfterUpdatePosition = true;
-        mEventData->mPrimaryCursorPosition = handlePosition;
-      }
-    }
-    else if( Event::LEFT_SELECTION_HANDLE_EVENT == event.type )
-    {
-      ChangeState( EventData::SELECTING );
-
-      mEventData->mUpdateHighlightBox = true;
-      mEventData->mUpdateLeftSelectionPosition = true;
-      mEventData->mUpdateRightSelectionPosition = true;
-
-      if( handleStopScrolling || isSmoothHandlePanEnabled )
-      {
-        mEventData->mScrollAfterUpdatePosition = true;
-
-        if( ( handlePosition != mEventData->mRightSelectionPosition ) &&
-            ( handlePosition != mEventData->mLeftSelectionPosition ) )
-        {
-          mEventData->mLeftSelectionPosition = handlePosition;
-        }
-      }
-    }
-    else if( Event::RIGHT_SELECTION_HANDLE_EVENT == event.type )
-    {
-      ChangeState( EventData::SELECTING );
-
-      mEventData->mUpdateHighlightBox = true;
-      mEventData->mUpdateRightSelectionPosition = true;
-      mEventData->mUpdateLeftSelectionPosition = true;
-
-      if( handleStopScrolling || isSmoothHandlePanEnabled )
-      {
-        mEventData->mScrollAfterUpdatePosition = true;
-        if( ( handlePosition != mEventData->mRightSelectionPosition ) &&
-            ( handlePosition != mEventData->mLeftSelectionPosition ) )
-        {
-          mEventData->mRightSelectionPosition = handlePosition;
-        }
-      }
-    }
-
-    mEventData->mDecoratorUpdated = true;
-  } // end ( ( HANDLE_RELEASED == state ) || ( HANDLE_STOP_SCROLLING == state ) )
-  else if( HANDLE_SCROLLING == state )
-  {
-    const float xSpeed = event.p2.mFloat;
-    const float ySpeed = event.p3.mFloat;
-    const Vector2& layoutSize = mModel->mVisualModel->GetLayoutSize();
-    const Vector2 currentScrollPosition = mModel->mScrollPosition;
-
-    mModel->mScrollPosition.x += xSpeed;
-    mModel->mScrollPosition.y += ySpeed;
-
-    ClampHorizontalScroll( layoutSize );
-    ClampVerticalScroll( layoutSize );
-
-    bool endOfScroll = false;
-    if( Vector2::ZERO == ( currentScrollPosition - mModel->mScrollPosition ) )
-    {
-      // Notify the decorator there is no more text to scroll.
-      // The decorator won't send more scroll events.
-      mEventData->mDecorator->NotifyEndOfScroll();
-      // Still need to set the position of the handle.
-      endOfScroll = true;
-    }
-
-    // Set the position of the handle.
-    const bool scrollRightDirection = xSpeed > 0.f;
-    const bool scrollBottomDirection = ySpeed > 0.f;
-    const bool leftSelectionHandleEvent = Event::LEFT_SELECTION_HANDLE_EVENT == event.type;
-    const bool rightSelectionHandleEvent = Event::RIGHT_SELECTION_HANDLE_EVENT == event.type;
-
-    if( Event::GRAB_HANDLE_EVENT == event.type )
-    {
-      ChangeState( EventData::GRAB_HANDLE_PANNING );
-
-      // Get the grab handle position in decorator coords.
-      Vector2 position = mEventData->mDecorator->GetPosition( GRAB_HANDLE );
-
-      if( mEventData->mDecorator->IsHorizontalScrollEnabled() )
-      {
-        // Position the grag handle close to either the left or right edge.
-        position.x = scrollRightDirection ? 0.f : mModel->mVisualModel->mControlSize.width;
-      }
-
-      if( mEventData->mDecorator->IsVerticalScrollEnabled() )
-      {
-        position.x = mEventData->mCursorHookPositionX;
-
-        // Position the grag handle close to either the top or bottom edge.
-        position.y = scrollBottomDirection ? 0.f : mModel->mVisualModel->mControlSize.height;
-      }
-
-      // Get the new handle position.
-      // The grab handle's position is in decorator's coords. Need to transforms to text's coords.
-      const CharacterIndex handlePosition = Text::GetClosestCursorIndex( mModel->mVisualModel,
-                                                                         mModel->mLogicalModel,
-                                                                         mMetrics,
-                                                                         position.x - mModel->mScrollPosition.x,
-                                                                         position.y - mModel->mScrollPosition.y );
-
-      if( mEventData->mPrimaryCursorPosition != handlePosition )
-      {
-        mEventData->mUpdateCursorPosition = true;
-        mEventData->mUpdateGrabHandlePosition = !isSmoothHandlePanEnabled;
-        mEventData->mScrollAfterUpdatePosition = true;
-        mEventData->mPrimaryCursorPosition = handlePosition;
-      }
-      mEventData->mUpdateInputStyle = mEventData->mUpdateCursorPosition;
-
-      // Updates the decorator if the soft handle panning is enabled.
-      mEventData->mDecoratorUpdated = isSmoothHandlePanEnabled;
-    }
-    else if( leftSelectionHandleEvent || rightSelectionHandleEvent )
-    {
-      ChangeState( EventData::SELECTION_HANDLE_PANNING );
-
-      // Get the selection handle position in decorator coords.
-      Vector2 position = mEventData->mDecorator->GetPosition( leftSelectionHandleEvent ? Text::LEFT_SELECTION_HANDLE : Text::RIGHT_SELECTION_HANDLE );
-
-      if( mEventData->mDecorator->IsHorizontalScrollEnabled() )
-      {
-        // Position the selection handle close to either the left or right edge.
-        position.x = scrollRightDirection ? 0.f : mModel->mVisualModel->mControlSize.width;
-      }
-
-      if( mEventData->mDecorator->IsVerticalScrollEnabled() )
-      {
-        position.x = mEventData->mCursorHookPositionX;
-
-        // Position the grag handle close to either the top or bottom edge.
-        position.y = scrollBottomDirection ? 0.f : mModel->mVisualModel->mControlSize.height;
-      }
-
-      // Get the new handle position.
-      // The selection handle's position is in decorator's coords. Need to transform to text's coords.
-      const CharacterIndex handlePosition = Text::GetClosestCursorIndex( mModel->mVisualModel,
-                                                                         mModel->mLogicalModel,
-                                                                         mMetrics,
-                                                                         position.x - mModel->mScrollPosition.x,
-                                                                         position.y - mModel->mScrollPosition.y );
-
-      if( leftSelectionHandleEvent )
-      {
-        const bool differentHandles = ( mEventData->mLeftSelectionPosition != handlePosition ) && ( mEventData->mRightSelectionPosition != handlePosition );
-
-        if( differentHandles || endOfScroll )
-        {
-          mEventData->mUpdateHighlightBox = true;
-          mEventData->mUpdateLeftSelectionPosition = !isSmoothHandlePanEnabled;
-          mEventData->mUpdateRightSelectionPosition = isSmoothHandlePanEnabled;
-          mEventData->mLeftSelectionPosition = handlePosition;
-        }
-      }
-      else
-      {
-        const bool differentHandles = ( mEventData->mRightSelectionPosition != handlePosition ) && ( mEventData->mLeftSelectionPosition != handlePosition );
-        if( differentHandles || endOfScroll )
-        {
-          mEventData->mUpdateHighlightBox = true;
-          mEventData->mUpdateRightSelectionPosition = !isSmoothHandlePanEnabled;
-          mEventData->mUpdateLeftSelectionPosition = isSmoothHandlePanEnabled;
-          mEventData->mRightSelectionPosition = handlePosition;
-        }
-      }
-
-      if( mEventData->mUpdateLeftSelectionPosition || mEventData->mUpdateRightSelectionPosition )
-      {
-        RepositionSelectionHandles();
-
-        mEventData->mScrollAfterUpdatePosition = !isSmoothHandlePanEnabled;
-      }
-    }
-    mEventData->mDecoratorUpdated = true;
-  } // end ( HANDLE_SCROLLING == state )
+  return mEventData && mEventData->mEditingEnabled;
 }
 
 }
 
-void Controller::Impl::OnSelectEvent( const Event& event )
+void Controller::Impl::SetEditable( bool editable )
 {
 {
-  if( NULL == mEventData )
-  {
-    // Nothing to do if there is no text.
-    return;
-  }
-
-  if( mEventData->mSelectionEnabled )
-  {
-    // Convert from control's coords to text's coords.
-    const float xPosition = event.p2.mFloat - mModel->mScrollPosition.x;
-    const float yPosition = event.p3.mFloat - mModel->mScrollPosition.y;
-
-    // Calculates the logical position from the x,y coords.
-    RepositionSelectionHandles( xPosition,
-                                yPosition );
-  }
-}
-
-void Controller::Impl::OnSelectAllEvent()
-{
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "OnSelectAllEvent mEventData->mSelectionEnabled%s \n", mEventData->mSelectionEnabled?"true":"false");
-
-  if( NULL == mEventData )
-  {
-    // Nothing to do if there is no text.
-    return;
-  }
-
-  if( mEventData->mSelectionEnabled )
+  if( mEventData)
   {
   {
-    ChangeState( EventData::SELECTING );
-
-    mEventData->mLeftSelectionPosition = 0u;
-    mEventData->mRightSelectionPosition = mModel->mLogicalModel->mText.Count();
-
-    mEventData->mScrollAfterUpdatePosition = true;
-    mEventData->mUpdateLeftSelectionPosition = true;
-    mEventData->mUpdateRightSelectionPosition = true;
-    mEventData->mUpdateHighlightBox = true;
+    mEventData->mEditingEnabled = editable;
   }
 }
 
   }
 }
 
@@ -1713,8 +1251,18 @@ void Controller::Impl::RetrieveSelection( std::string& selectedText, bool delete
       mModel->mLogicalModel->UpdateTextStyleRuns( startOfSelectedText, -static_cast<int>( lengthOfSelectedText ) );
 
       // Mark the paragraphs to be updated.
       mModel->mLogicalModel->UpdateTextStyleRuns( startOfSelectedText, -static_cast<int>( lengthOfSelectedText ) );
 
       // Mark the paragraphs to be updated.
-      mTextUpdateInfo.mCharacterIndex = startOfSelectedText;
-      mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
+      if( Layout::Engine::SINGLE_LINE_BOX == mLayoutEngine.GetLayout() )
+      {
+        mTextUpdateInfo.mCharacterIndex = 0;
+        mTextUpdateInfo.mNumberOfCharactersToRemove = mTextUpdateInfo.mPreviousNumberOfCharacters;
+        mTextUpdateInfo.mNumberOfCharactersToAdd = mTextUpdateInfo.mPreviousNumberOfCharacters - lengthOfSelectedText;
+        mTextUpdateInfo.mClearAll = true;
+      }
+      else
+      {
+        mTextUpdateInfo.mCharacterIndex = startOfSelectedText;
+        mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
+      }
 
       // Delete text between handles
       Vector<Character>::Iterator first = utf32Characters.Begin() + startOfSelectedText;
 
       // Delete text between handles
       Vector<Character>::Iterator first = utf32Characters.Begin() + startOfSelectedText;
@@ -1734,6 +1282,18 @@ void Controller::Impl::RetrieveSelection( std::string& selectedText, bool delete
   }
 }
 
   }
 }
 
+void Controller::Impl::SetSelection( int start, int end )
+{
+  mEventData->mLeftSelectionPosition = start;
+  mEventData->mRightSelectionPosition = end;
+  mEventData->mUpdateCursorPosition = true;
+}
+
+std::pair< int, int > Controller::Impl::GetSelectionIndexes() const
+{
+  return { mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition };
+}
+
 void Controller::Impl::ShowClipboard()
 {
   if( mClipboard )
 void Controller::Impl::ShowClipboard()
 {
   if( mClipboard )
@@ -1755,7 +1315,7 @@ void Controller::Impl::SetClipboardHideEnable(bool enable)
   mClipboardHideEnabled = enable;
 }
 
   mClipboardHideEnabled = enable;
 }
 
-bool Controller::Impl::CopyStringToClipboard( std::string& source )
+bool Controller::Impl::CopyStringToClipboard( const std::string& source )
 {
   //Send string to clipboard
   return ( mClipboard && mClipboard.SetItem( source ) );
 {
   //Send string to clipboard
   return ( mClipboard && mClipboard.SetItem( source ) );
@@ -1779,463 +1339,11 @@ void Controller::Impl::RequestGetTextFromClipboard()
 
 void Controller::Impl::RepositionSelectionHandles()
 {
 
 void Controller::Impl::RepositionSelectionHandles()
 {
-  CharacterIndex selectionStart = mEventData->mLeftSelectionPosition;
-  CharacterIndex selectionEnd = mEventData->mRightSelectionPosition;
-
-  if( selectionStart == selectionEnd )
-  {
-    // Nothing to select if handles are in the same place.
-    return;
-  }
-
-  mEventData->mDecorator->ClearHighlights();
-
-  const GlyphIndex* const charactersToGlyphBuffer = mModel->mVisualModel->mCharactersToGlyph.Begin();
-  const Length* const glyphsPerCharacterBuffer = mModel->mVisualModel->mGlyphsPerCharacter.Begin();
-  const GlyphInfo* const glyphsBuffer = mModel->mVisualModel->mGlyphs.Begin();
-  const Vector2* const positionsBuffer = mModel->mVisualModel->mGlyphPositions.Begin();
-  const Length* const charactersPerGlyphBuffer = mModel->mVisualModel->mCharactersPerGlyph.Begin();
-  const CharacterIndex* const glyphToCharacterBuffer = mModel->mVisualModel->mGlyphsToCharacters.Begin();
-  const CharacterDirection* const modelCharacterDirectionsBuffer = ( 0u != mModel->mLogicalModel->mCharacterDirections.Count() ) ? mModel->mLogicalModel->mCharacterDirections.Begin() : NULL;
-
-  const bool isLastCharacter = selectionEnd >= mModel->mLogicalModel->mText.Count();
-  const CharacterDirection startDirection = ( ( NULL == modelCharacterDirectionsBuffer ) ? false : *( modelCharacterDirectionsBuffer + selectionStart ) );
-  const CharacterDirection endDirection = ( ( NULL == modelCharacterDirectionsBuffer ) ? false : *( modelCharacterDirectionsBuffer + ( selectionEnd - ( isLastCharacter ? 1u : 0u ) ) ) );
-
-  // Swap the indices if the start is greater than the end.
-  const bool indicesSwapped = selectionStart > selectionEnd;
-
-  // Tell the decorator to flip the selection handles if needed.
-  mEventData->mDecorator->SetSelectionHandleFlipState( indicesSwapped, startDirection, endDirection );
-
-  if( indicesSwapped )
-  {
-    std::swap( selectionStart, selectionEnd );
-  }
-
-  // Get the indices to the first and last selected glyphs.
-  const CharacterIndex selectionEndMinusOne = selectionEnd - 1u;
-  const GlyphIndex glyphStart = *( charactersToGlyphBuffer + selectionStart );
-  const Length numberOfGlyphs = *( glyphsPerCharacterBuffer + selectionEndMinusOne );
-  const GlyphIndex glyphEnd = *( charactersToGlyphBuffer + selectionEndMinusOne ) + ( ( numberOfGlyphs > 0 ) ? numberOfGlyphs - 1u : 0u );
-
-  // Get the lines where the glyphs are laid-out.
-  const LineRun* lineRun = mModel->mVisualModel->mLines.Begin();
-
-  LineIndex lineIndex = 0u;
-  Length numberOfLines = 0u;
-  mModel->mVisualModel->GetNumberOfLines( glyphStart,
-                                          1u + glyphEnd - glyphStart,
-                                          lineIndex,
-                                          numberOfLines );
-  const LineIndex firstLineIndex = lineIndex;
-
-  // Create the structure to store some selection box info.
-  Vector<SelectionBoxInfo> selectionBoxLinesInfo;
-  selectionBoxLinesInfo.Resize( numberOfLines );
-
-  SelectionBoxInfo* selectionBoxInfo = selectionBoxLinesInfo.Begin();
-  selectionBoxInfo->minX = MAX_FLOAT;
-  selectionBoxInfo->maxX = MIN_FLOAT;
-
-  // Keep the min and max 'x' position to calculate the size and position of the highlighed text.
-  float minHighlightX = std::numeric_limits<float>::max();
-  float maxHighlightX = std::numeric_limits<float>::min();
-  Size highLightSize;
-  Vector2 highLightPosition; // The highlight position in decorator's coords.
-
-  // Retrieve the first line and get the line's vertical offset, the line's height and the index to the last glyph.
-
-  // The line's vertical offset of all the lines before the line where the first glyph is laid-out.
-  selectionBoxInfo->lineOffset = CalculateLineOffset( mModel->mVisualModel->mLines,
-                                                      firstLineIndex );
-
-  // Transform to decorator's (control) coords.
-  selectionBoxInfo->lineOffset += mModel->mScrollPosition.y;
-
-  lineRun += firstLineIndex;
-
-  // The line height is the addition of the line ascender and the line descender.
-  // However, the line descender has a negative value, hence the subtraction.
-  selectionBoxInfo->lineHeight = lineRun->ascender - lineRun->descender;
-
-  GlyphIndex lastGlyphOfLine = lineRun->glyphRun.glyphIndex + lineRun->glyphRun.numberOfGlyphs - 1u;
-
-  // Check if the first glyph is a ligature that must be broken like Latin ff, fi, or Arabic ï»», etc which needs special code.
-  const Length numberOfCharactersStart = *( charactersPerGlyphBuffer + glyphStart );
-  bool splitStartGlyph = ( numberOfCharactersStart > 1u ) && HasLigatureMustBreak( mModel->mLogicalModel->GetScript( selectionStart ) );
-
-  // Check if the last glyph is a ligature that must be broken like Latin ff, fi, or Arabic ï»», etc which needs special code.
-  const Length numberOfCharactersEnd = *( charactersPerGlyphBuffer + glyphEnd );
-  bool splitEndGlyph = ( glyphStart != glyphEnd ) && ( numberOfCharactersEnd > 1u ) && HasLigatureMustBreak( mModel->mLogicalModel->GetScript( selectionEndMinusOne ) );
-
-  // The number of quads of the selection box.
-  const unsigned int numberOfQuads = 1u + ( glyphEnd - glyphStart ) + ( ( numberOfLines > 1u ) ? 2u * numberOfLines : 0u );
-  mEventData->mDecorator->ResizeHighlightQuads( numberOfQuads );
-
-  // Count the actual number of quads.
-  unsigned int actualNumberOfQuads = 0u;
-  Vector4 quad;
-
-  // Traverse the glyphs.
-  for( GlyphIndex index = glyphStart; index <= glyphEnd; ++index )
-  {
-    const GlyphInfo& glyph = *( glyphsBuffer + index );
-    const Vector2& position = *( positionsBuffer + index );
-
-    if( splitStartGlyph )
-    {
-      // If the first glyph is a ligature that must be broken it may be needed to add only part of the glyph to the highlight box.
-
-      const float glyphAdvance = glyph.advance / static_cast<float>( numberOfCharactersStart );
-      const CharacterIndex interGlyphIndex = selectionStart - *( glyphToCharacterBuffer + glyphStart );
-      // Get the direction of the character.
-      CharacterDirection isCurrentRightToLeft = false;
-      if( NULL != modelCharacterDirectionsBuffer ) // If modelCharacterDirectionsBuffer is NULL, it means the whole text is left to right.
-      {
-        isCurrentRightToLeft = *( modelCharacterDirectionsBuffer + selectionStart );
-      }
-
-      // The end point could be in the middle of the ligature.
-      // Calculate the number of characters selected.
-      const Length numberOfCharacters = ( glyphStart == glyphEnd ) ? ( selectionEnd - selectionStart ) : ( numberOfCharactersStart - interGlyphIndex );
-
-      quad.x = lineRun->alignmentOffset + position.x - glyph.xBearing + mModel->mScrollPosition.x + glyphAdvance * static_cast<float>( isCurrentRightToLeft ? ( numberOfCharactersStart - interGlyphIndex - numberOfCharacters ) : interGlyphIndex );
-      quad.y = selectionBoxInfo->lineOffset;
-      quad.z = quad.x + static_cast<float>( numberOfCharacters ) * glyphAdvance;
-      quad.w = selectionBoxInfo->lineOffset + selectionBoxInfo->lineHeight;
-
-      // Store the min and max 'x' for each line.
-      selectionBoxInfo->minX = std::min( selectionBoxInfo->minX, quad.x );
-      selectionBoxInfo->maxX = std::max( selectionBoxInfo->maxX, quad.z );
-
-      mEventData->mDecorator->AddHighlight( actualNumberOfQuads, quad );
-      ++actualNumberOfQuads;
-
-      splitStartGlyph = false;
-      continue;
-    }
-
-    if( splitEndGlyph && ( index == glyphEnd ) )
-    {
-      // Equally, if the last glyph is a ligature that must be broken it may be needed to add only part of the glyph to the highlight box.
-
-      const float glyphAdvance = glyph.advance / static_cast<float>( numberOfCharactersEnd );
-      const CharacterIndex interGlyphIndex = selectionEnd - *( glyphToCharacterBuffer + glyphEnd );
-      // Get the direction of the character.
-      CharacterDirection isCurrentRightToLeft = false;
-      if( NULL != modelCharacterDirectionsBuffer ) // If modelCharacterDirectionsBuffer is NULL, it means the whole text is left to right.
-      {
-        isCurrentRightToLeft = *( modelCharacterDirectionsBuffer + selectionEnd );
-      }
-
-      const Length numberOfCharacters = numberOfCharactersEnd - interGlyphIndex;
-
-      quad.x = lineRun->alignmentOffset + position.x - glyph.xBearing + mModel->mScrollPosition.x + ( isCurrentRightToLeft ? ( glyphAdvance * static_cast<float>( numberOfCharacters ) ) : 0.f );
-      quad.y = selectionBoxInfo->lineOffset;
-      quad.z = quad.x + static_cast<float>( interGlyphIndex ) * glyphAdvance;
-      quad.w = quad.y + selectionBoxInfo->lineHeight;
-
-      // Store the min and max 'x' for each line.
-      selectionBoxInfo->minX = std::min( selectionBoxInfo->minX, quad.x );
-      selectionBoxInfo->maxX = std::max( selectionBoxInfo->maxX, quad.z );
-
-      mEventData->mDecorator->AddHighlight( actualNumberOfQuads,
-                                            quad );
-      ++actualNumberOfQuads;
-
-      splitEndGlyph = false;
-      continue;
-    }
-
-    quad.x = lineRun->alignmentOffset + position.x - glyph.xBearing + mModel->mScrollPosition.x;
-    quad.y = selectionBoxInfo->lineOffset;
-    quad.z = quad.x + glyph.advance;
-    quad.w = quad.y + selectionBoxInfo->lineHeight;
-
-    // Store the min and max 'x' for each line.
-    selectionBoxInfo->minX = std::min( selectionBoxInfo->minX, quad.x );
-    selectionBoxInfo->maxX = std::max( selectionBoxInfo->maxX, quad.z );
-
-    mEventData->mDecorator->AddHighlight( actualNumberOfQuads,
-                                          quad );
-    ++actualNumberOfQuads;
-
-    // Whether to retrieve the next line.
-    if( index == lastGlyphOfLine )
-    {
-      // Retrieve the next line.
-      ++lineRun;
-
-      // Get the last glyph of the new line.
-      lastGlyphOfLine = lineRun->glyphRun.glyphIndex + lineRun->glyphRun.numberOfGlyphs - 1u;
-
-      ++lineIndex;
-      if( lineIndex < firstLineIndex + numberOfLines )
-      {
-        // Keep the offset and height of the current selection box.
-        const float currentLineOffset = selectionBoxInfo->lineOffset;
-        const float currentLineHeight = selectionBoxInfo->lineHeight;
-
-        // Get the selection box info for the next line.
-        ++selectionBoxInfo;
-
-        selectionBoxInfo->minX = MAX_FLOAT;
-        selectionBoxInfo->maxX = MIN_FLOAT;
-
-        // Update the line's vertical offset.
-        selectionBoxInfo->lineOffset = currentLineOffset + currentLineHeight;
-
-        // The line height is the addition of the line ascender and the line descender.
-        // However, the line descender has a negative value, hence the subtraction.
-        selectionBoxInfo->lineHeight = lineRun->ascender - lineRun->descender;
-      }
-    }
-  }
-
-  // Traverses all the lines and updates the min and max 'x' positions and the total height.
-  // The final width is calculated after 'boxifying' the selection.
-  for( Vector<SelectionBoxInfo>::ConstIterator it = selectionBoxLinesInfo.Begin(),
-         endIt = selectionBoxLinesInfo.End();
-       it != endIt;
-       ++it )
-  {
-    const SelectionBoxInfo& info = *it;
-
-    // Update the size of the highlighted text.
-    highLightSize.height += info.lineHeight;
-    minHighlightX = std::min( minHighlightX, info.minX );
-    maxHighlightX = std::max( maxHighlightX, info.maxX );
-  }
-
-  // Add extra geometry to 'boxify' the selection.
-
-  if( 1u < numberOfLines )
-  {
-    // Boxify the first line.
-    lineRun = mModel->mVisualModel->mLines.Begin() + firstLineIndex;
-    const SelectionBoxInfo& firstSelectionBoxLineInfo = *( selectionBoxLinesInfo.Begin() );
-
-    bool boxifyBegin = ( LTR != lineRun->direction ) && ( LTR != startDirection );
-    bool boxifyEnd = ( LTR == lineRun->direction ) && ( LTR == startDirection );
-
-    if( boxifyBegin )
-    {
-      quad.x = 0.f;
-      quad.y = firstSelectionBoxLineInfo.lineOffset;
-      quad.z = firstSelectionBoxLineInfo.minX;
-      quad.w = firstSelectionBoxLineInfo.lineOffset + firstSelectionBoxLineInfo.lineHeight;
-
-      // Boxify at the beginning of the line.
-      mEventData->mDecorator->AddHighlight( actualNumberOfQuads,
-                                            quad );
-      ++actualNumberOfQuads;
-
-      // Update the size of the highlighted text.
-      minHighlightX = 0.f;
-    }
-
-    if( boxifyEnd )
-    {
-      quad.x = firstSelectionBoxLineInfo.maxX;
-      quad.y = firstSelectionBoxLineInfo.lineOffset;
-      quad.z = mModel->mVisualModel->mControlSize.width;
-      quad.w = firstSelectionBoxLineInfo.lineOffset + firstSelectionBoxLineInfo.lineHeight;
-
-      // Boxify at the end of the line.
-      mEventData->mDecorator->AddHighlight( actualNumberOfQuads,
-                                            quad );
-      ++actualNumberOfQuads;
-
-      // Update the size of the highlighted text.
-      maxHighlightX = mModel->mVisualModel->mControlSize.width;
-    }
-
-    // Boxify the central lines.
-    if( 2u < numberOfLines )
-    {
-      for( Vector<SelectionBoxInfo>::ConstIterator it = selectionBoxLinesInfo.Begin() + 1u,
-             endIt = selectionBoxLinesInfo.End() - 1u;
-           it != endIt;
-           ++it )
-      {
-        const SelectionBoxInfo& info = *it;
-
-        quad.x = 0.f;
-        quad.y = info.lineOffset;
-        quad.z = info.minX;
-        quad.w = info.lineOffset + info.lineHeight;
-
-        mEventData->mDecorator->AddHighlight( actualNumberOfQuads,
-                                              quad );
-        ++actualNumberOfQuads;
-
-        quad.x = info.maxX;
-        quad.y = info.lineOffset;
-        quad.z = mModel->mVisualModel->mControlSize.width;
-        quad.w = info.lineOffset + info.lineHeight;
-
-        mEventData->mDecorator->AddHighlight( actualNumberOfQuads,
-                                              quad );
-        ++actualNumberOfQuads;
-      }
-
-      // Update the size of the highlighted text.
-      minHighlightX = 0.f;
-      maxHighlightX = mModel->mVisualModel->mControlSize.width;
-    }
-
-    // Boxify the last line.
-    lineRun = mModel->mVisualModel->mLines.Begin() + firstLineIndex + numberOfLines - 1u;
-    const SelectionBoxInfo& lastSelectionBoxLineInfo = *( selectionBoxLinesInfo.End() - 1u );
-
-    boxifyBegin = ( LTR == lineRun->direction ) && ( LTR == endDirection );
-    boxifyEnd = ( LTR != lineRun->direction ) && ( LTR != endDirection );
-
-    if( boxifyBegin )
-    {
-      quad.x = 0.f;
-      quad.y = lastSelectionBoxLineInfo.lineOffset;
-      quad.z = lastSelectionBoxLineInfo.minX;
-      quad.w = lastSelectionBoxLineInfo.lineOffset + lastSelectionBoxLineInfo.lineHeight;
-
-      // Boxify at the beginning of the line.
-      mEventData->mDecorator->AddHighlight( actualNumberOfQuads,
-                                            quad );
-      ++actualNumberOfQuads;
-
-      // Update the size of the highlighted text.
-      minHighlightX = 0.f;
-    }
-
-    if( boxifyEnd )
-    {
-      quad.x = lastSelectionBoxLineInfo.maxX;
-      quad.y = lastSelectionBoxLineInfo.lineOffset;
-      quad.z = mModel->mVisualModel->mControlSize.width;
-      quad.w = lastSelectionBoxLineInfo.lineOffset + lastSelectionBoxLineInfo.lineHeight;
-
-      // Boxify at the end of the line.
-      mEventData->mDecorator->AddHighlight( actualNumberOfQuads,
-                                            quad );
-      ++actualNumberOfQuads;
-
-      // Update the size of the highlighted text.
-      maxHighlightX = mModel->mVisualModel->mControlSize.width;
-    }
-  }
-
-  // Set the actual number of quads.
-  mEventData->mDecorator->ResizeHighlightQuads( actualNumberOfQuads );
-
-  // Sets the highlight's size and position. In decorator's coords.
-  // The highlight's height has been calculated above (before 'boxifying' the highlight).
-  highLightSize.width = maxHighlightX - minHighlightX;
-
-  highLightPosition.x = minHighlightX;
-  const SelectionBoxInfo& firstSelectionBoxLineInfo = *( selectionBoxLinesInfo.Begin() );
-  highLightPosition.y = firstSelectionBoxLineInfo.lineOffset;
-
-  mEventData->mDecorator->SetHighLightBox( highLightPosition, highLightSize );
-
-  if( !mEventData->mDecorator->IsSmoothHandlePanEnabled() )
-  {
-    CursorInfo primaryCursorInfo;
-    GetCursorPosition( mEventData->mLeftSelectionPosition,
-                       primaryCursorInfo );
-
-    const Vector2 primaryPosition = primaryCursorInfo.primaryPosition + mModel->mScrollPosition;
-
-    mEventData->mDecorator->SetPosition( LEFT_SELECTION_HANDLE,
-                                         primaryPosition.x,
-                                         primaryCursorInfo.lineOffset + mModel->mScrollPosition.y,
-                                         primaryCursorInfo.lineHeight );
-
-    CursorInfo secondaryCursorInfo;
-    GetCursorPosition( mEventData->mRightSelectionPosition,
-                       secondaryCursorInfo );
-
-    const Vector2 secondaryPosition = secondaryCursorInfo.primaryPosition + mModel->mScrollPosition;
-
-    mEventData->mDecorator->SetPosition( RIGHT_SELECTION_HANDLE,
-                                         secondaryPosition.x,
-                                         secondaryCursorInfo.lineOffset + mModel->mScrollPosition.y,
-                                         secondaryCursorInfo.lineHeight );
-  }
-
-  // Cursor to be positioned at end of selection so if selection interrupted and edit mode restarted the cursor will be at end of selection
-  mEventData->mPrimaryCursorPosition = ( indicesSwapped ) ? mEventData->mLeftSelectionPosition : mEventData->mRightSelectionPosition;
-
-  // Set the flag to update the decorator.
-  mEventData->mDecoratorUpdated = true;
+  SelectionHandleController::Reposition(*this);
 }
 }
-
-void Controller::Impl::RepositionSelectionHandles( float visualX, float visualY )
+void Controller::Impl::RepositionSelectionHandles( float visualX, float visualY, Controller::NoTextTap::Action action )
 {
 {
-  if( NULL == mEventData )
-  {
-    // Nothing to do if there is no text input.
-    return;
-  }
-
-  if( IsShowingPlaceholderText() )
-  {
-    // Nothing to do if there is the place-holder text.
-    return;
-  }
-
-  const Length numberOfGlyphs = mModel->mVisualModel->mGlyphs.Count();
-  const Length numberOfLines  = mModel->mVisualModel->mLines.Count();
-  if( ( 0 == numberOfGlyphs ) ||
-      ( 0 == numberOfLines ) )
-  {
-    // Nothing to do if there is no text.
-    return;
-  }
-
-  // Find which word was selected
-  CharacterIndex selectionStart( 0 );
-  CharacterIndex selectionEnd( 0 );
-  const bool indicesFound = FindSelectionIndices( mModel->mVisualModel,
-                                                  mModel->mLogicalModel,
-                                                  mMetrics,
-                                                  visualX,
-                                                  visualY,
-                                                  selectionStart,
-                                                  selectionEnd );
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "%p selectionStart %d selectionEnd %d\n", this, selectionStart, selectionEnd );
-
-  if( indicesFound )
-  {
-    ChangeState( EventData::SELECTING );
-
-    mEventData->mLeftSelectionPosition = selectionStart;
-    mEventData->mRightSelectionPosition = selectionEnd;
-
-    mEventData->mUpdateLeftSelectionPosition = true;
-    mEventData->mUpdateRightSelectionPosition = true;
-    mEventData->mUpdateHighlightBox = true;
-
-    // It may happen an IMF commit event arrives before the selection event
-    // if the IMF manager is in pre-edit state. The commit event will set the
-    // mEventData->mUpdateCursorPosition flag to true. If it's not set back
-    // to false, the highlight box won't be updated.
-    mEventData->mUpdateCursorPosition = false;
-
-    mEventData->mScrollAfterUpdatePosition = ( mEventData->mLeftSelectionPosition != mEventData->mRightSelectionPosition );
-  }
-  else
-  {
-    // Nothing to select. i.e. a white space, out of bounds
-    ChangeState( EventData::EDITING );
-
-    mEventData->mPrimaryCursorPosition = selectionEnd;
-
-    mEventData->mUpdateCursorPosition = true;
-    mEventData->mUpdateGrabHandlePosition = true;
-    mEventData->mScrollAfterUpdatePosition = true;
-    mEventData->mUpdateInputStyle = true;
-  }
+  SelectionHandleController::Reposition(*this, visualX, visualY, action);
 }
 
 void Controller::Impl::SetPopupButtons()
 }
 
 void Controller::Impl::SetPopupButtons()
@@ -2248,15 +1356,23 @@ void Controller::Impl::SetPopupButtons()
    *  If EDITING_WITH_POPUP : SELECT & SELECT_ALL
    */
 
    *  If EDITING_WITH_POPUP : SELECT & SELECT_ALL
    */
 
+  bool isEditable = IsEditable();
   TextSelectionPopup::Buttons buttonsToShow = TextSelectionPopup::NONE;
 
   if( EventData::SELECTING == mEventData->mState )
   {
   TextSelectionPopup::Buttons buttonsToShow = TextSelectionPopup::NONE;
 
   if( EventData::SELECTING == mEventData->mState )
   {
-    buttonsToShow = TextSelectionPopup::Buttons(  TextSelectionPopup::CUT | TextSelectionPopup::COPY );
+    buttonsToShow = TextSelectionPopup::Buttons( TextSelectionPopup::COPY );
+    if(isEditable)
+    {
+      buttonsToShow = TextSelectionPopup::Buttons( buttonsToShow | TextSelectionPopup::CUT );
+    }
 
     if( !IsClipboardEmpty() )
     {
 
     if( !IsClipboardEmpty() )
     {
-      buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::PASTE ) );
+      if(isEditable)
+      {
+        buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::PASTE ) );
+      }
       buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::CLIPBOARD ) );
     }
 
       buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::CLIPBOARD ) );
     }
 
@@ -2274,7 +1390,10 @@ void Controller::Impl::SetPopupButtons()
 
     if( !IsClipboardEmpty() )
     {
 
     if( !IsClipboardEmpty() )
     {
-      buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::PASTE ) );
+      if(isEditable)
+      {
+        buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::PASTE ) );
+      }
       buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::CLIPBOARD ) );
     }
   }
       buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::CLIPBOARD ) );
     }
   }
@@ -2282,7 +1401,10 @@ void Controller::Impl::SetPopupButtons()
   {
     if ( !IsClipboardEmpty() )
     {
   {
     if ( !IsClipboardEmpty() )
     {
-      buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::PASTE ) );
+      if(isEditable)
+      {
+        buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::PASTE ) );
+      }
       buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::CLIPBOARD ) );
     }
   }
       buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::CLIPBOARD ) );
     }
   }
@@ -2334,8 +1456,11 @@ void Controller::Impl::ChangeState( EventData::State newState )
         mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE );
         mEventData->mDecorator->StopCursorBlink();
         mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false );
         mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE );
         mEventData->mDecorator->StopCursorBlink();
         mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false );
-        mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, true );
-        mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true );
+        if ( mEventData->mGrabHandleEnabled )
+        {
+          mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, true );
+          mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true );
+        }
         mEventData->mDecorator->SetHighlightActive( true );
         if( mEventData->mGrabHandlePopupEnabled )
         {
         mEventData->mDecorator->SetHighlightActive( true );
         if( mEventData->mGrabHandlePopupEnabled )
         {
@@ -2379,7 +1504,7 @@ void Controller::Impl::ChangeState( EventData::State newState )
           mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
           mEventData->mDecorator->SetHighlightActive( false );
         }
           mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
           mEventData->mDecorator->SetHighlightActive( false );
         }
-        else
+        else if ( mEventData->mGrabHandleEnabled )
         {
           mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
         }
         {
           mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
         }
@@ -2401,7 +1526,10 @@ void Controller::Impl::ChangeState( EventData::State newState )
           mEventData->mDecorator->StartCursorBlink();
         }
         // Grab handle is not shown until a tap is received whilst EDITING
           mEventData->mDecorator->StartCursorBlink();
         }
         // Grab handle is not shown until a tap is received whilst EDITING
-        mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
+        if ( mEventData->mGrabHandleEnabled )
+        {
+          mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
+        }
         mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
         mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
         mEventData->mDecorator->SetHighlightActive( false );
         mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
         mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
         mEventData->mDecorator->SetHighlightActive( false );
@@ -2417,8 +1545,11 @@ void Controller::Impl::ChangeState( EventData::State newState )
         mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE );
         mEventData->mDecorator->StopCursorBlink();
         mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false );
         mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE );
         mEventData->mDecorator->StopCursorBlink();
         mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false );
-        mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, true );
-        mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true );
+        if ( mEventData->mGrabHandleEnabled )
+        {
+          mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, true );
+          mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true );
+        }
         mEventData->mDecorator->SetHighlightActive( true );
         if( mEventData->mGrabHandlePopupEnabled )
         {
         mEventData->mDecorator->SetHighlightActive( true );
         if( mEventData->mGrabHandlePopupEnabled )
         {
@@ -2436,7 +1567,10 @@ void Controller::Impl::ChangeState( EventData::State newState )
         {
           mEventData->mDecorator->StartCursorBlink();
         }
         {
           mEventData->mDecorator->StartCursorBlink();
         }
-        mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
+        if ( mEventData->mGrabHandleEnabled )
+        {
+          mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
+        }
         mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
         mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
         mEventData->mDecorator->SetHighlightActive( false );
         mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
         mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
         mEventData->mDecorator->SetHighlightActive( false );
@@ -2457,7 +1591,10 @@ void Controller::Impl::ChangeState( EventData::State newState )
           mEventData->mDecorator->StartCursorBlink();
         }
 
           mEventData->mDecorator->StartCursorBlink();
         }
 
-        mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
+        if ( mEventData->mGrabHandleEnabled )
+        {
+          mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
+        }
         mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
         mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
         mEventData->mDecorator->SetHighlightActive( false );
         mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
         mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
         mEventData->mDecorator->SetHighlightActive( false );
@@ -2510,21 +1647,41 @@ void Controller::Impl::GetCursorPosition( CharacterIndex logical,
     cursorInfo.lineHeight = GetDefaultFontLineHeight();
     cursorInfo.primaryCursorHeight = cursorInfo.lineHeight;
 
     cursorInfo.lineHeight = GetDefaultFontLineHeight();
     cursorInfo.primaryCursorHeight = cursorInfo.lineHeight;
 
+    bool isRTL = false;
+    if( mModel->mMatchSystemLanguageDirection )
+    {
+      isRTL = mLayoutDirection == LayoutDirection::RIGHT_TO_LEFT;
+    }
+
     switch( mModel->mHorizontalAlignment )
     {
     switch( mModel->mHorizontalAlignment )
     {
-      case Layout::HORIZONTAL_ALIGN_BEGIN:
+      case Text::HorizontalAlignment::BEGIN :
       {
       {
-        cursorInfo.primaryPosition.x = 0.f;
+        if( isRTL )
+        {
+          cursorInfo.primaryPosition.x = mModel->mVisualModel->mControlSize.width - mEventData->mDecorator->GetCursorWidth();
+        }
+        else
+        {
+          cursorInfo.primaryPosition.x = 0.f;
+        }
         break;
       }
         break;
       }
-      case Layout::HORIZONTAL_ALIGN_CENTER:
+      case Text::HorizontalAlignment::CENTER:
       {
         cursorInfo.primaryPosition.x = floorf( 0.5f * mModel->mVisualModel->mControlSize.width );
         break;
       }
       {
         cursorInfo.primaryPosition.x = floorf( 0.5f * mModel->mVisualModel->mControlSize.width );
         break;
       }
-      case Layout::HORIZONTAL_ALIGN_END:
+      case Text::HorizontalAlignment::END:
       {
       {
-        cursorInfo.primaryPosition.x = mModel->mVisualModel->mControlSize.width - mEventData->mDecorator->GetCursorWidth();
+        if( isRTL )
+        {
+          cursorInfo.primaryPosition.x = 0.f;
+        }
+        else
+        {
+          cursorInfo.primaryPosition.x = mModel->mVisualModel->mControlSize.width - mEventData->mDecorator->GetCursorWidth();
+        }
         break;
       }
     }
         break;
       }
     }
@@ -2533,13 +1690,25 @@ void Controller::Impl::GetCursorPosition( CharacterIndex logical,
     return;
   }
 
     return;
   }
 
-  Text::GetCursorPosition( mModel->mVisualModel,
-                           mModel->mLogicalModel,
-                           mMetrics,
-                           logical,
+  const bool isMultiLine = ( Layout::Engine::MULTI_LINE_BOX == mLayoutEngine.GetLayout() );
+  GetCursorPositionParameters parameters;
+  parameters.visualModel = mModel->mVisualModel;
+  parameters.logicalModel = mModel->mLogicalModel;
+  parameters.metrics = mMetrics;
+  parameters.logical = logical;
+  parameters.isMultiline = isMultiLine;
+
+  Text::GetCursorPosition( parameters,
                            cursorInfo );
 
                            cursorInfo );
 
-  if( Layout::Engine::MULTI_LINE_BOX == mLayoutEngine.GetLayout() )
+  // Adds Outline offset.
+  const float outlineWidth = static_cast<float>( mModel->GetOutlineWidth() );
+  cursorInfo.primaryPosition.x += outlineWidth;
+  cursorInfo.primaryPosition.y += outlineWidth;
+  cursorInfo.secondaryPosition.x += outlineWidth;
+  cursorInfo.secondaryPosition.y += outlineWidth;
+
+  if( isMultiLine )
   {
     // If the text is editable and multi-line, the cursor position after a white space shouldn't exceed the boundaries of the text control.
 
   {
     // If the text is editable and multi-line, the cursor position after a white space shouldn't exceed the boundaries of the text control.
 
@@ -2620,6 +1789,8 @@ void Controller::Impl::UpdateCursorPosition( const CursorInfo& cursorInfo )
 
   const Vector2 cursorPosition = cursorInfo.primaryPosition + mModel->mScrollPosition;
 
 
   const Vector2 cursorPosition = cursorInfo.primaryPosition + mModel->mScrollPosition;
 
+  mEventData->mDecorator->SetGlyphOffset( PRIMARY_CURSOR, cursorInfo.glyphOffset );
+
   // Sets the cursor position.
   mEventData->mDecorator->SetPosition( PRIMARY_CURSOR,
                                        cursorPosition.x,
   // Sets the cursor position.
   mEventData->mDecorator->SetPosition( PRIMARY_CURSOR,
                                        cursorPosition.x,
@@ -2670,24 +1841,7 @@ void Controller::Impl::UpdateCursorPosition( const CursorInfo& cursorInfo )
 void Controller::Impl::UpdateSelectionHandle( HandleType handleType,
                                               const CursorInfo& cursorInfo )
 {
 void Controller::Impl::UpdateSelectionHandle( HandleType handleType,
                                               const CursorInfo& cursorInfo )
 {
-  if( ( LEFT_SELECTION_HANDLE != handleType ) &&
-      ( RIGHT_SELECTION_HANDLE != handleType ) )
-  {
-    return;
-  }
-
-  const Vector2 cursorPosition = cursorInfo.primaryPosition + mModel->mScrollPosition;
-
-  // Sets the handle's position.
-  mEventData->mDecorator->SetPosition( handleType,
-                                       cursorPosition.x,
-                                       cursorInfo.lineOffset + mModel->mScrollPosition.y,
-                                       cursorInfo.lineHeight );
-
-  // If selection handle at start of the text and other at end of the text then all text is selected.
-  const CharacterIndex startOfSelection = std::min( mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition );
-  const CharacterIndex endOfSelection = std::max ( mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition );
-  mEventData->mAllTextSelected = ( startOfSelection == 0 ) && ( endOfSelection == mModel->mLogicalModel->mText.Count() );
+  SelectionHandleController::Update(*this, handleType, cursorInfo);
 }
 
 void Controller::Impl::ClampHorizontalScroll( const Vector2& layoutSize )
 }
 
 void Controller::Impl::ClampHorizontalScroll( const Vector2& layoutSize )
@@ -2755,13 +1909,16 @@ void Controller::Impl::ScrollToMakePositionVisible( const Vector2& position, flo
     mModel->mScrollPosition.x = mModel->mVisualModel->mControlSize.width - positionEndX;
   }
 
     mModel->mScrollPosition.x = mModel->mVisualModel->mControlSize.width - positionEndX;
   }
 
-  if( decoratorPositionBeginY < 0.f )
-  {
-    mModel->mScrollPosition.y = -position.y;
-  }
-  else if( decoratorPositionEndY > mModel->mVisualModel->mControlSize.height )
+  if( Layout::Engine::MULTI_LINE_BOX == mLayoutEngine.GetLayout() )
   {
   {
-    mModel->mScrollPosition.y = mModel->mVisualModel->mControlSize.height - positionEndY;
+    if( decoratorPositionBeginY < 0.f )
+    {
+      mModel->mScrollPosition.y = -position.y;
+    }
+    else if( decoratorPositionEndY > mModel->mVisualModel->mControlSize.height )
+    {
+      mModel->mScrollPosition.y = mModel->mVisualModel->mControlSize.height - positionEndY;
+    }
   }
 }
 
   }
 }
 
@@ -2770,9 +1927,20 @@ void Controller::Impl::ScrollTextToMatchCursor( const CursorInfo& cursorInfo )
   // Get the current cursor position in decorator coords.
   const Vector2& currentCursorPosition = mEventData->mDecorator->GetPosition( PRIMARY_CURSOR );
 
   // Get the current cursor position in decorator coords.
   const Vector2& currentCursorPosition = mEventData->mDecorator->GetPosition( PRIMARY_CURSOR );
 
+  const LineIndex lineIndex = mModel->mVisualModel->GetLineOfCharacter( mEventData->mPrimaryCursorPosition  );
+
+
+
   // Calculate the offset to match the cursor position before the character was deleted.
   mModel->mScrollPosition.x = currentCursorPosition.x - cursorInfo.primaryPosition.x;
   // Calculate the offset to match the cursor position before the character was deleted.
   mModel->mScrollPosition.x = currentCursorPosition.x - cursorInfo.primaryPosition.x;
-  mModel->mScrollPosition.y = currentCursorPosition.y - cursorInfo.lineOffset;
+
+  //If text control has more than two lines and current line index is not last, calculate scrollpositionY
+  if( mModel->mVisualModel->mLines.Count() > 1u && lineIndex != mModel->mVisualModel->mLines.Count() -1u )
+  {
+    const float currentCursorGlyphOffset = mEventData->mDecorator->GetGlyphOffset( PRIMARY_CURSOR );
+    mModel->mScrollPosition.y = currentCursorPosition.y - cursorInfo.lineOffset - currentCursorGlyphOffset;
+  }
+
 
   ClampHorizontalScroll( mModel->mVisualModel->GetLayoutSize() );
   ClampVerticalScroll( mModel->mVisualModel->GetLayoutSize() );
 
   ClampHorizontalScroll( mModel->mVisualModel->GetLayoutSize() );
   ClampVerticalScroll( mModel->mVisualModel->GetLayoutSize() );
@@ -2781,6 +1949,13 @@ void Controller::Impl::ScrollTextToMatchCursor( const CursorInfo& cursorInfo )
   ScrollToMakePositionVisible( cursorInfo.primaryPosition, cursorInfo.lineHeight );
 }
 
   ScrollToMakePositionVisible( cursorInfo.primaryPosition, cursorInfo.lineHeight );
 }
 
+void Controller::Impl::ScrollTextToMatchCursor()
+{
+  CursorInfo cursorInfo;
+  GetCursorPosition( mEventData->mPrimaryCursorPosition, cursorInfo );
+  ScrollTextToMatchCursor(cursorInfo);
+}
+
 void Controller::Impl::RequestRelayout()
 {
   if( NULL != mControlInterface )
 void Controller::Impl::RequestRelayout()
 {
   if( NULL != mControlInterface )
@@ -2789,6 +1964,170 @@ void Controller::Impl::RequestRelayout()
   }
 }
 
   }
 }
 
+Actor Controller::Impl::CreateBackgroundActor()
+{
+  // NOTE: Currently we only support background color for one line left-to-right text,
+  //       so the following calculation is based on one line left-to-right text only!
+
+  Actor actor;
+
+  Length numberOfGlyphs = mView.GetNumberOfGlyphs();
+  if( numberOfGlyphs > 0u )
+  {
+    Vector<GlyphInfo> glyphs;
+    glyphs.Resize( numberOfGlyphs );
+
+    Vector<Vector2> positions;
+    positions.Resize( numberOfGlyphs );
+
+    // Get the line where the glyphs are laid-out.
+    const LineRun* lineRun = mModel->mVisualModel->mLines.Begin();
+    float alignmentOffset = lineRun->alignmentOffset;
+    numberOfGlyphs = mView.GetGlyphs( glyphs.Begin(),
+                                      positions.Begin(),
+                                      alignmentOffset,
+                                      0u,
+                                      numberOfGlyphs );
+
+    glyphs.Resize( numberOfGlyphs );
+    positions.Resize( numberOfGlyphs );
+
+    const GlyphInfo* const glyphsBuffer = glyphs.Begin();
+    const Vector2* const positionsBuffer = positions.Begin();
+
+    BackgroundMesh mesh;
+    mesh.mVertices.Reserve( 4u * glyphs.Size() );
+    mesh.mIndices.Reserve( 6u * glyphs.Size() );
+
+    const Vector2 textSize = mView.GetLayoutSize();
+
+    const float offsetX = textSize.width * 0.5f;
+    const float offsetY = textSize.height * 0.5f;
+
+    const Vector4* const backgroundColorsBuffer = mView.GetBackgroundColors();
+    const ColorIndex* const backgroundColorIndicesBuffer = mView.GetBackgroundColorIndices();
+    const Vector4& defaultBackgroundColor = mModel->mVisualModel->IsBackgroundEnabled() ? mModel->mVisualModel->GetBackgroundColor() : Color::TRANSPARENT;
+
+    Vector4 quad;
+    uint32_t numberOfQuads = 0u;
+
+    for( uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i )
+    {
+      const GlyphInfo& glyph = *( glyphsBuffer + i );
+
+      // Get the background color of the character.
+      // The color index zero is reserved for the default background color (i.e. Color::TRANSPARENT)
+      const ColorIndex backgroundColorIndex = ( nullptr == backgroundColorsBuffer ) ? 0u : *( backgroundColorIndicesBuffer + i );
+      const Vector4& backgroundColor = ( 0u == backgroundColorIndex ) ? defaultBackgroundColor : *( backgroundColorsBuffer + backgroundColorIndex - 1u );
+
+      // Only create quads for glyphs with a background color
+      if ( backgroundColor != Color::TRANSPARENT )
+      {
+        const Vector2 position = *( positionsBuffer + i );
+
+        if ( i == 0u && glyphSize == 1u ) // Only one glyph in the whole text
+        {
+          quad.x = position.x;
+          quad.y = 0.0f;
+          quad.z = quad.x + std::max( glyph.advance, glyph.xBearing + glyph.width );
+          quad.w = textSize.height;
+        }
+        else if ( i == 0u ) // The first glyph in the whole text
+        {
+          quad.x = position.x;
+          quad.y = 0.0f;
+          quad.z = quad.x - glyph.xBearing + glyph.advance;
+          quad.w = textSize.height;
+        }
+        else if ( i == glyphSize - 1u ) // The last glyph in the whole text
+        {
+          quad.x = position.x - glyph.xBearing;
+          quad.y = 0.0f;
+          quad.z = quad.x + std::max( glyph.advance, glyph.xBearing + glyph.width );
+          quad.w = textSize.height;
+        }
+        else // The glyph in the middle of the text
+        {
+          quad.x = position.x - glyph.xBearing;
+          quad.y = 0.0f;
+          quad.z = quad.x + glyph.advance;
+          quad.w = textSize.height;
+        }
+
+        BackgroundVertex vertex;
+
+        // Top left
+        vertex.mPosition.x = quad.x - offsetX;
+        vertex.mPosition.y = quad.y - offsetY;
+        vertex.mColor = backgroundColor;
+        mesh.mVertices.PushBack( vertex );
+
+        // Top right
+        vertex.mPosition.x = quad.z - offsetX;
+        vertex.mPosition.y = quad.y - offsetY;
+        vertex.mColor = backgroundColor;
+        mesh.mVertices.PushBack( vertex );
+
+        // Bottom left
+        vertex.mPosition.x = quad.x - offsetX;
+        vertex.mPosition.y = quad.w - offsetY;
+        vertex.mColor = backgroundColor;
+        mesh.mVertices.PushBack( vertex );
+
+        // Bottom right
+        vertex.mPosition.x = quad.z - offsetX;
+        vertex.mPosition.y = quad.w - offsetY;
+        vertex.mColor = backgroundColor;
+        mesh.mVertices.PushBack( vertex );
+
+        // Six indices in counter clockwise winding
+        mesh.mIndices.PushBack( 1u + 4 * numberOfQuads );
+        mesh.mIndices.PushBack( 0u + 4 * numberOfQuads );
+        mesh.mIndices.PushBack( 2u + 4 * numberOfQuads );
+        mesh.mIndices.PushBack( 2u + 4 * numberOfQuads );
+        mesh.mIndices.PushBack( 3u + 4 * numberOfQuads );
+        mesh.mIndices.PushBack( 1u + 4 * numberOfQuads );
+
+        numberOfQuads++;
+      }
+    }
+
+    // Only create the background actor if there are glyphs with background color
+    if ( mesh.mVertices.Count() > 0u )
+    {
+      Property::Map quadVertexFormat;
+      quadVertexFormat[ "aPosition" ] = Property::VECTOR2;
+      quadVertexFormat[ "aColor" ] = Property::VECTOR4;
+
+      VertexBuffer quadVertices = VertexBuffer::New( quadVertexFormat );
+      quadVertices.SetData( &mesh.mVertices[ 0 ], mesh.mVertices.Size() );
+
+      Geometry quadGeometry = Geometry::New();
+      quadGeometry.AddVertexBuffer( quadVertices );
+      quadGeometry.SetIndexBuffer( &mesh.mIndices[ 0 ], mesh.mIndices.Size() );
+
+      if( !mShaderBackground )
+      {
+        mShaderBackground = Shader::New( VERTEX_SHADER_BACKGROUND, FRAGMENT_SHADER_BACKGROUND );
+      }
+
+      Dali::Renderer renderer = Dali::Renderer::New( quadGeometry, mShaderBackground );
+      renderer.SetProperty( Dali::Renderer::Property::BLEND_MODE, BlendMode::ON );
+      renderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT );
+
+      actor = Actor::New();
+      actor.SetProperty( Dali::Actor::Property::NAME, "TextBackgroundColorActor" );
+      actor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
+      actor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
+      actor.SetProperty( Actor::Property::SIZE, textSize );
+      actor.SetProperty( Actor::Property::COLOR_MODE, USE_OWN_MULTIPLY_PARENT_COLOR );
+      actor.AddRenderer( renderer );
+    }
+  }
+
+  return actor;
+}
+
 } // namespace Text
 
 } // namespace Toolkit
 } // namespace Text
 
 } // namespace Toolkit