DALi signals refactor to remove V2 naming
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / internal / controls / text-input / text-input-impl.cpp
index 7cb426a..cbda7fb 100644 (file)
  *
  */
 
-#include <dali/dali.h>
-
+// CLASS HEADER
 #include <dali-toolkit/internal/controls/text-input/text-input-impl.h>
-#include <dali-toolkit/internal/controls/text-view/text-processor.h>
-#include <dali-toolkit/public-api/controls/buttons/push-button.h>
-#include <dali-toolkit/public-api/controls/alignment/alignment.h>
-#include <dali-toolkit/public-api/controls/default-controls/solid-color-actor.h>
-
-#include <dali/integration-api/debug.h>
 
+// EXTERNAL INCLUDES
 #include <math.h>
 #include <sstream>
 #include <algorithm>
+#include <dali/public-api/adaptor-framework/virtual-keyboard.h>
+#include <dali/public-api/animation/constraints.h>
+#include <dali/public-api/common/stage.h>
+#include <dali/public-api/events/key-event.h>
+#include <dali/public-api/events/touch-event.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/public-api/object/property-notification.h>
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/controls/text-view/text-processor.h>
+#include <dali-toolkit/public-api/controls/buttons/push-button.h>
+#include <dali-toolkit/public-api/controls/alignment/alignment.h>
+#include <dali-toolkit/public-api/controls/default-controls/solid-color-actor.h>
 
-using namespace std;
 using namespace Dali;
 
 // Local Data
@@ -531,24 +538,24 @@ const Vector4& TextInput::GetMaterialDiffuseColor() const
 
 // Signals
 
-Toolkit::TextInput::InputSignalV2& TextInput::InputStartedSignal()
+Toolkit::TextInput::InputSignalType& TextInput::InputStartedSignal()
 {
-  return mInputStartedSignalV2;
+  return mInputStartedSignal;
 }
 
-Toolkit::TextInput::InputSignalV2& TextInput::InputFinishedSignal()
+Toolkit::TextInput::InputSignalType& TextInput::InputFinishedSignal()
 {
-  return mInputFinishedSignalV2;
+  return mInputFinishedSignal;
 }
 
-Toolkit::TextInput::InputSignalV2& TextInput::CutAndPasteToolBarDisplayedSignal()
+Toolkit::TextInput::InputSignalType& TextInput::CutAndPasteToolBarDisplayedSignal()
 {
-  return mCutAndPasteToolBarDisplayedV2;
+  return mCutAndPasteToolBarDisplayed;
 }
 
-Toolkit::TextInput::StyleChangedSignalV2& TextInput::StyleChangedSignal()
+Toolkit::TextInput::StyleChangedSignalType& TextInput::StyleChangedSignal()
 {
-  return mStyleChangedSignalV2;
+  return mStyleChangedSignal;
 }
 
 Toolkit::TextInput::TextModifiedSignalType& TextInput::TextModifiedSignal()
@@ -556,14 +563,14 @@ Toolkit::TextInput::TextModifiedSignalType& TextInput::TextModifiedSignal()
   return mTextModifiedSignal;
 }
 
-Toolkit::TextInput::MaxInputCharactersReachedSignalV2& TextInput::MaxInputCharactersReachedSignal()
+Toolkit::TextInput::MaxInputCharactersReachedSignalType& TextInput::MaxInputCharactersReachedSignal()
 {
-  return mMaxInputCharactersReachedSignalV2;
+  return mMaxInputCharactersReachedSignal;
 }
 
-Toolkit::TextInput::InputTextExceedBoundariesSignalV2& TextInput::InputTextExceedBoundariesSignal()
+Toolkit::TextInput::InputTextExceedBoundariesSignalType& TextInput::InputTextExceedBoundariesSignal()
 {
-  return mInputTextExceedBoundariesSignalV2;
+  return mInputTextExceedBoundariesSignal;
 }
 
 bool TextInput::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
@@ -1023,7 +1030,7 @@ void TextInput::OnKeyInputFocusGained()
   StartCursorBlinkTimer();
 
   Toolkit::TextInput handle( GetOwner() );
-  mInputStartedSignalV2.Emit( handle );
+  mInputStartedSignal.Emit( handle );
 
   ImfManager imfManager = ImfManager::Get();
 
@@ -1035,7 +1042,7 @@ void TextInput::OnKeyInputFocusGained()
     imfManager.Activate();
 
     // When window gain lost focus, the imf manager is deactivated. Thus when window gain focus again, the imf manager must be activated.
-    imfManager.SetRestoreAferFocusLost( true );
+    imfManager.SetRestoreAfterFocusLost( true );
 
     imfManager.SetCursorPosition( mCursorPosition );
     imfManager.NotifyCursorPosition();
@@ -1069,7 +1076,7 @@ void TextInput::OnKeyInputFocusLost()
   if ( imfManager )
   {
     // The text editing is finished. Therefore the imf manager don't have restore activation.
-    imfManager.SetRestoreAferFocusLost( false );
+    imfManager.SetRestoreAfterFocusLost( false );
 
     // Notify that the text editing finish.
     imfManager.Deactivate();
@@ -1080,7 +1087,7 @@ void TextInput::OnKeyInputFocusLost()
   VirtualKeyboard::LanguageChangedSignal().Disconnect( this, &TextInput::SetTextDirection );
 
   Toolkit::TextInput handle( GetOwner() );
-  mInputFinishedSignalV2.Emit( handle );
+  mInputFinishedSignal.Emit( handle );
   mEditModeActive = false;
   mPreEditFlag = false;
   RemoveHighlight();
@@ -1199,7 +1206,7 @@ float TextInput::GetHeightForWidth( float width )
 
 // Private Internal methods
 
-void TextInput::OnHandlePan(Actor actor, PanGesture gesture)
+void TextInput::OnHandlePan(Actor actor, const PanGesture& gesture)
 {
   switch (gesture.state)
   {
@@ -1324,7 +1331,7 @@ bool TextInput::OnHandleTwoTouched(Dali::Actor actor, const TouchEvent& touch)
   return false;
 }
 
-void TextInput::OnDoubleTap(Dali::Actor actor, Dali::TapGesture tap)
+void TextInput::OnDoubleTap(Dali::Actor actor, const Dali::TapGesture& tap)
 {
    // If text exists then select nearest word.
    if ( !mStyledText.empty())
@@ -1389,7 +1396,7 @@ void TextInput::OnDoubleTap(Dali::Actor actor, Dali::TapGesture tap)
 }
 
 // TODO: Change the function name to be more general.
-void TextInput::OnTextTap(Dali::Actor actor, Dali::TapGesture tap)
+void TextInput::OnTextTap(Dali::Actor actor, const Dali::TapGesture& tap)
 {
   DALI_LOG_INFO( gLogFilter, Debug::General, "OnTap mPreEditFlag[%s] mEditOnTouch[%s] mEditModeActive[%s] ", (mPreEditFlag)?"true":"false"
                                                                                                            , (mEditOnTouch)?"true":"false"
@@ -1487,7 +1494,19 @@ void TextInput::OnTextTap(Dali::Actor actor, Dali::TapGesture tap)
   // otherwise the Grab handle will be shown when selecting.
   if ( createGrabHandle && IsGrabHandleEnabled() )
   {
-    const Vector3 cursorPosition = GetActualPositionFromCharacterPosition(mCursorPosition);
+    Vector3 altPosition;    // Alternate (i.e. opposite direction) cursor position.
+    bool altPositionValid;  // Alternate cursor validity flag.
+    bool directionRTL;      // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently)
+    Vector3 cursorPosition = GetActualPositionFromCharacterPosition( mCursorPosition, directionRTL, altPosition, altPositionValid );
+
+    if( altPositionValid )
+    {
+      // Check which of the positions is the closest.
+      if( fabsf( altPosition.x - tap.localPoint.x ) < fabsf( cursorPosition.x - tap.localPoint.x ) )
+      {
+        cursorPosition = altPosition;
+      }
+    }
 
     CreateGrabHandle();
 
@@ -1499,7 +1518,7 @@ void TextInput::OnTextTap(Dali::Actor actor, Dali::TapGesture tap)
   }
 }
 
-void TextInput::OnLongPress(Dali::Actor actor, Dali::LongPressGesture longPress)
+void TextInput::OnLongPress(Dali::Actor actor, const Dali::LongPressGesture& longPress)
 {
   DALI_LOG_INFO( gLogFilter, Debug::General, "OnLongPress\n" );
 
@@ -1747,7 +1766,6 @@ bool TextInput::OnKeyDownEvent(const KeyEvent& event)
     {
       // Some text is selected so erase it before adding space.
       DeleteHighlightedText( true );
-      update = true;
     }
 
     mCursorPosition = mCursorPosition + InsertAt(Text(keyString), mCursorPosition, 0);
@@ -1842,6 +1860,64 @@ bool TextInput::OnKeyUpEvent(const KeyEvent& event)
   return false;
 }
 
+void TextInput::ChooseRtlSelectionHandlePosition( const Vector3& cursorPositionOne,
+                                                  const Vector3& cursorPositionTwo,
+                                                  bool altPositionValidOne,
+                                                  bool altPositionValidTwo,
+                                                  const Vector3& altPositionOne,
+                                                  const Vector3& altPositionTwo )
+{
+  // TODO VCC Valid for one line.
+  // Try to place the selection handles. TODO think in something better. Probably need to know the direction of the paragraph.
+  if( cursorPositionOne != cursorPositionTwo )
+  {
+    if( cursorPositionOne.x < cursorPositionTwo.x )
+    {
+      mSelectionHandleOneActualPosition = cursorPositionOne;
+      mSelectionHandleTwoActualPosition = cursorPositionTwo;
+    }
+    else
+    {
+      mSelectionHandleOneActualPosition = cursorPositionTwo;
+      mSelectionHandleTwoActualPosition = cursorPositionOne;
+    }
+  }
+  else
+  {
+    mSelectionHandleOneActualPosition = cursorPositionOne;
+    if( altPositionValidOne )
+    {
+      if( altPositionOne.x < mSelectionHandleOneActualPosition.x )
+      {
+        mSelectionHandleOneActualPosition = altPositionOne;
+      }
+    }
+    if( altPositionValidTwo )
+    {
+      if(  altPositionTwo.x < mSelectionHandleOneActualPosition.x )
+      {
+        mSelectionHandleOneActualPosition = altPositionTwo;
+      }
+    }
+
+    mSelectionHandleTwoActualPosition = cursorPositionTwo;
+    if( altPositionValidTwo )
+    {
+      if(  altPositionTwo.x > mSelectionHandleTwoActualPosition.x )
+      {
+        mSelectionHandleTwoActualPosition = altPositionTwo;
+      }
+    }
+    if( altPositionValidOne )
+    {
+      if( altPositionOne.x > mSelectionHandleTwoActualPosition.x )
+      {
+        mSelectionHandleTwoActualPosition = altPositionOne;
+      }
+    }
+  }
+}
+
 void TextInput::OnTextViewScrolled( Toolkit::TextView textView, Vector2 scrollPosition )
 {
   // Updates the stored scroll position.
@@ -1854,7 +1930,20 @@ void TextInput::OnTextViewScrolled( Toolkit::TextView textView, Vector2 scrollPo
   if( mGrabHandle || mCursor )
   {
     cursorSize.height = GetRowRectFromCharacterPosition( mCursorPosition ).height;
-    const Vector3 cursorPosition = GetActualPositionFromCharacterPosition(mCursorPosition);
+
+    Vector3 altPosition;    // Alternate (i.e. opposite direction) cursor position.
+    bool altPositionValid;  // Alternate cursor validity flag.
+    bool directionRTL;      // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently)
+    Vector3 cursorPosition = GetActualPositionFromCharacterPosition( mCursorPosition, directionRTL, altPosition, altPositionValid );
+
+    if( altPositionValid )
+    {
+      // Check which of the positions is the closest.
+      if( fabsf( altPosition.x - mActualGrabHandlePosition.x ) < fabsf( cursorPosition.x - mActualGrabHandlePosition.x ) )
+      {
+        cursorPosition = altPosition;
+      }
+    }
 
     mIsCursorInScrollArea = mIsGrabHandleInScrollArea = IsPositionInsideBoundaries( cursorPosition, cursorSize, controlSize );
 
@@ -1876,16 +1965,29 @@ void TextInput::OnTextViewScrolled( Toolkit::TextView textView, Vector2 scrollPo
   // Updates the selection handles and highlighted text position and visibility.
   if( mSelectionHandleOne && mSelectionHandleTwo )
   {
-    const Vector3 cursorPositionOne = GetActualPositionFromCharacterPosition(mSelectionHandleOnePosition);
-    const Vector3 cursorPositionTwo = GetActualPositionFromCharacterPosition(mSelectionHandleTwoPosition);
+    Vector3 altPositionOne;    // Alternate (i.e. opposite direction) cursor position.
+    bool altPositionValidOne;  // Alternate cursor validity flag.
+    bool directionRTLOne;      // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently)
+    Vector3 cursorPositionOne = GetActualPositionFromCharacterPosition( mSelectionHandleOnePosition, directionRTLOne, altPositionOne, altPositionValidOne );
+
+    Vector3 altPositionTwo;    // Alternate (i.e. opposite direction) cursor position.
+    bool altPositionValidTwo;  // Alternate cursor validity flag.
+    bool directionRTLTwo;      // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently)
+    Vector3 cursorPositionTwo = GetActualPositionFromCharacterPosition( mSelectionHandleTwoPosition, directionRTLTwo, altPositionTwo, altPositionValidTwo );
+
+    // VCC TODO: This method is a hack for one line.
+    ChooseRtlSelectionHandlePosition( cursorPositionOne,
+                                      cursorPositionTwo,
+                                      altPositionValidOne,
+                                      altPositionValidTwo,
+                                      altPositionOne,
+                                      altPositionTwo );
+
     cursorSize.height = ( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + mSelectionHandleOnePosition ) ).mSize.height;
     const bool isSelectionHandleOneVisible = IsPositionInsideBoundaries( cursorPositionOne, cursorSize, controlSize );
     cursorSize.height = ( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + mSelectionHandleTwoPosition ) ).mSize.height;
     const bool isSelectionHandleTwoVisible = IsPositionInsideBoundaries( cursorPositionTwo, cursorSize, controlSize );
 
-    mSelectionHandleOneActualPosition = cursorPositionOne.GetVectorXY();
-    mSelectionHandleTwoActualPosition = cursorPositionTwo.GetVectorXY();
-
     mSelectionHandleOne.SetVisible( isSelectionHandleOneVisible );
     mSelectionHandleTwo.SetVisible( isSelectionHandleTwoVisible );
     mSelectionHandleOne.SetPosition( mSelectionHandleOneActualPosition + UI_OFFSET + mSelectionHandleOneOffset );
@@ -3226,8 +3328,23 @@ void TextInput::CreateSelectionHandles( std::size_t start, std::size_t end, Dali
   // update table as text may have changed.
   GetTextLayoutInfo();
 
-  mSelectionHandleOneActualPosition = GetActualPositionFromCharacterPosition( mSelectionHandleOnePosition );
-  mSelectionHandleTwoActualPosition = GetActualPositionFromCharacterPosition( mSelectionHandleTwoPosition );
+  Vector3 altPositionOne;    // Alternate (i.e. opposite direction) cursor position.
+  bool altPositionValidOne;  // Alternate cursor validity flag.
+  bool directionRTLOne;      // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently)
+  Vector3 cursorPositionOne = GetActualPositionFromCharacterPosition( mSelectionHandleOnePosition, directionRTLOne, altPositionOne, altPositionValidOne );
+
+  Vector3 altPositionTwo;    // Alternate (i.e. opposite direction) cursor position.
+  bool altPositionValidTwo;  // Alternate cursor validity flag.
+  bool directionRTLTwo;      // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently)
+  Vector3 cursorPositionTwo = GetActualPositionFromCharacterPosition( mSelectionHandleTwoPosition, directionRTLTwo, altPositionTwo, altPositionValidTwo );
+
+  // VCC TODO: This method is a hack for one line.
+  ChooseRtlSelectionHandlePosition( cursorPositionOne,
+                                    cursorPositionTwo,
+                                    altPositionValidOne,
+                                    altPositionValidTwo,
+                                    altPositionOne,
+                                    altPositionTwo );
 
   mSelectionHandleOne.SetPosition( mSelectionHandleOneActualPosition + UI_OFFSET + mSelectionHandleOneOffset );
   mSelectionHandleTwo.SetPosition( mSelectionHandleTwoActualPosition + UI_OFFSET + mSelectionHandleTwoOffset );
@@ -3271,7 +3388,18 @@ Vector3 TextInput::MoveSelectionHandle( SelectionHandleId handleId, const Vector
     std::size_t newHandlePosition = 0;
     ReturnClosestIndex( actualSelectionHandlePosition.GetVectorXY(), newHandlePosition );
 
-    actualHandlePosition = GetActualPositionFromCharacterPosition( newHandlePosition );
+    Vector3 altPosition;    // Alternate (i.e. opposite direction) cursor position.
+    bool altPositionValid;  // Alternate cursor validity flag.
+    bool directionRTL;      // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently)
+    actualHandlePosition = GetActualPositionFromCharacterPosition( newHandlePosition, directionRTL, altPosition, altPositionValid );
+    if( altPositionValid )
+    {
+      // Check which of the positions is the closest.
+      if( fabsf( altPosition.x - actualSelectionHandlePosition.x ) < fabsf( actualHandlePosition.x - actualSelectionHandlePosition.x ) )
+      {
+        actualHandlePosition = altPosition;
+      }
+    }
 
     bool handleVisible = true;
 
@@ -3370,41 +3498,34 @@ void TextInput::SetSelectionHandlePosition(SelectionHandleId handleId)
   }
 }
 
-void TextInput::GetVisualTextSelection(std::vector<bool>& selectedVisualText, std::size_t startSelection, std::size_t endSelection)
+void TextInput::GetVisualTextSelection( std::vector<bool>& selectedVisualText, std::size_t startSelection, std::size_t endSelection )
 {
-  std::vector<int>::iterator it = mTextLayoutInfo.mCharacterLogicalToVisualMap.begin();
-  std::vector<int>::iterator startSelectionIt = mTextLayoutInfo.mCharacterLogicalToVisualMap.begin() + std::min(startSelection, endSelection);
-  std::vector<int>::iterator endSelectionIt = mTextLayoutInfo.mCharacterLogicalToVisualMap.begin() + std::max(startSelection, endSelection);
-  std::vector<int>::iterator end = mTextLayoutInfo.mCharacterLogicalToVisualMap.end();
+  selectedVisualText.resize( mTextLayoutInfo.mCharacterLogicalToVisualMap.size(), false );
 
-  selectedVisualText.resize( mTextLayoutInfo.mCharacterLogicalToVisualMap.size() );
+  // VCC Set true/false in logical order. TODO : It needs to be checked.
 
-  // Deselect text prior to startSelectionIt
-  for(;it!=startSelectionIt;++it)
+  if( startSelection > endSelection )
   {
-    selectedVisualText[*it] = false;
+    std::swap( startSelection, endSelection );
   }
-
-  // Select text from startSelectionIt -> endSelectionIt
-  for(;it!=endSelectionIt;++it)
+  std::size_t index = 0u;
+  for( std::vector<bool>::iterator it = selectedVisualText.begin(), endIt = selectedVisualText.end(); it != endIt; ++it, ++index )
   {
-    selectedVisualText[*it] = true;
-  }
-
-  // Deselect text after endSelection
-  for(;it!=end;++it)
-  {
-    selectedVisualText[*it] = false;
+    if( ( index < startSelection ) || ( endSelection <= index ) )
+    {
+      *it = false;
+    }
+    else
+    {
+      *it = true;
+    }
   }
-
-  selectedVisualText.resize( mTextLayoutInfo.mCharacterLogicalToVisualMap.size(), false );
 }
 
 // Calculate the dimensions of the quads they will make the highlight mesh
 TextInput::HighlightInfo TextInput::CalculateHighlightInfo()
 {
   // At the moment there is no public API to modify the block alignment option.
-  const bool blockAlignEnabled = true;
 
   mNewHighlightInfo.mQuadList.clear(); // clear last quad information.
 
@@ -3415,9 +3536,9 @@ TextInput::HighlightInfo TextInput::CalculateHighlightInfo()
 
     // Get vector of flags representing characters that are selected (true) vs unselected (false).
     std::vector<bool> selectedVisualText;
-    GetVisualTextSelection(selectedVisualText, mSelectionHandleOnePosition, mSelectionHandleTwoPosition);
-    std::vector<bool>::iterator selectedIt(selectedVisualText.begin());
-    std::vector<bool>::iterator selectedEndIt(selectedVisualText.end());
+    GetVisualTextSelection( selectedVisualText, mSelectionHandleOnePosition, mSelectionHandleTwoPosition );
+    std::vector<bool>::iterator selectedIt = selectedVisualText.begin();
+    std::vector<bool>::iterator selectedEndIt = selectedVisualText.end();
 
     SelectionState selectionState = SelectionNone;          ///< Current selection status of cursor over entire text.
     float rowLeft = 0.0f;
@@ -3434,28 +3555,28 @@ TextInput::HighlightInfo TextInput::CalculateHighlightInfo()
       // selectionState: None when not in selection, Started when in selection, and Ended when reached end of selection.
 
       Toolkit::TextView::CharacterLayoutInfo& charInfo(*it);
-      bool charSelected( false );
+      bool charSelected = false;
       if( selectedIt != selectedEndIt )
       {
         charSelected = *selectedIt++;
       }
 
-      if(selectionState == SelectionNone)
+      if( selectionState == SelectionNone )
       {
-        if(charSelected)
+        if( charSelected )
         {
           selectionState = SelectionStarted;
           rowLeft = charInfo.mPosition.x - mTextLayoutInfo.mScrollOffset.x;
           rowRight = rowLeft + charInfo.mSize.width;
         }
       }
-      else if(selectionState == SelectionStarted)
+      else if( selectionState == SelectionStarted )
       {
         // break selection on:
         // 1. new line causing selection break. (\n or wordwrap)
         // 2. character not selected.
-        if(charInfo.mPosition.y - lastIt->mPosition.y > CHARACTER_THRESHOLD ||
-           !charSelected)
+        if( !charSelected ||
+            ( charInfo.mPosition.y - lastIt->mPosition.y > CHARACTER_THRESHOLD ) )
         {
           // finished selection.
           // TODO: TextView should have a table of visual rows, and each character a reference to the row
@@ -3473,7 +3594,7 @@ TextInput::HighlightInfo TextInput::CalculateHighlightInfo()
           float rowTop = rowBottom - rowSize.height;
 
           // Still selected, and block-align mode then set rowRight to max, so it can be clamped afterwards
-          if(charSelected && blockAlignEnabled)
+          if(charSelected)
           {
             rowRight = std::numeric_limits<float>::max();
           }
@@ -3485,7 +3606,7 @@ TextInput::HighlightInfo TextInput::CalculateHighlightInfo()
           if( charSelected )
           {
             // if block-align mode then set rowLeft to min, so it can be clamped afterwards
-            rowLeft = blockAlignEnabled ? 0.0f : charInfo.mPosition.x - mTextLayoutInfo.mScrollOffset.x;
+            rowLeft = 0.0f;
             rowRight = ( charInfo.mPosition.x - mTextLayoutInfo.mScrollOffset.x ) + charInfo.mSize.width;
             selectionState = SelectionStarted;
           }
@@ -3530,8 +3651,6 @@ TextInput::HighlightInfo TextInput::CalculateHighlightInfo()
     mNewHighlightInfo.Clamp2D( topLeft, bottomRight );
 
     // For block-align align Further Clamp quads to max left and right extents
-    if(blockAlignEnabled)
-    {
       // BlockAlign: Will adjust highlight to block:
       // i.e.
       //   H[ello] (top row right = max of all rows right)
@@ -3546,8 +3665,66 @@ TextInput::HighlightInfo TextInput::CalculateHighlightInfo()
       // [is some]
       // [text]
       // (common in regular text editors/web browser selection)
-
       mNewHighlightInfo.Clamp2D( Vector2(maxRowLeft, topLeft.y), Vector2(maxRowRight, bottomRight.y ) );
+
+    // Finally clamp quads again so they don't exceed the boundry of the control.
+    const Vector3& controlSize = GetControlSize();
+    mNewHighlightInfo.Clamp2D( Vector2::ZERO, Vector2(controlSize.x, controlSize.y) );
+  } // end if
+
+  return mNewHighlightInfo;
+}
+
+// VCC TODO: two methods are not needed. this one is a quick hack to fix PLMs. Should implement one which support both directions.
+// This method creates one quad per character so different selection boxes for a mix of LTR and RTL languages are created.
+TextInput::HighlightInfo TextInput::CalculateHighlightInfoRtl()
+{
+  // At the moment there is no public API to modify the block alignment option.
+
+  mNewHighlightInfo.mQuadList.clear(); // clear last quad information.
+
+  if ( !mTextLayoutInfo.mCharacterLayoutInfoTable.empty() && !mTextLayoutInfo.mCharacterLogicalToVisualMap.empty() )
+  {
+    Toolkit::TextView::CharacterLayoutInfoContainer::iterator it = mTextLayoutInfo.mCharacterLayoutInfoTable.begin();
+    Toolkit::TextView::CharacterLayoutInfoContainer::iterator end = mTextLayoutInfo.mCharacterLayoutInfoTable.end();
+
+    // Get vector of flags representing characters that are selected (true) vs unselected (false).
+    std::vector<bool> selectedVisualText;
+    GetVisualTextSelection( selectedVisualText, mSelectionHandleOnePosition, mSelectionHandleTwoPosition );
+    std::vector<bool>::iterator selectedIt = selectedVisualText.begin();
+    std::vector<bool>::iterator selectedEndIt = selectedVisualText.end();
+
+    // SelectionState selectionState = SelectionNone;          ///< Current selection status of cursor over entire text.
+    float rowLeft = 0.0f;
+    float rowRight = 0.0f;
+
+    // VCC TODO this is valid for one line.
+    Vector2 min, max;
+    const Size rowSize = GetRowRectFromCharacterPosition( 0, min, max );
+
+    // Scan through entire text.
+    while(it != end)
+    {
+      // selectionState: None when not in selection, Started when in selection, and Ended when reached end of selection.
+
+      Toolkit::TextView::CharacterLayoutInfo& charInfo(*it);
+      bool charSelected = false;
+      if( selectedIt != selectedEndIt )
+      {
+        charSelected = *selectedIt++;
+      }
+
+      if( charSelected )
+      {
+        rowLeft = charInfo.mPosition.x - mTextLayoutInfo.mScrollOffset.x;
+        rowRight = rowLeft + charInfo.mSize.width;
+
+        float rowBottom = charInfo.mPosition.y - mTextLayoutInfo.mScrollOffset.y;
+        float rowTop = rowBottom - rowSize.height;
+        mNewHighlightInfo.AddQuad( rowLeft, rowTop, rowRight, rowBottom );
+      }
+
+      ++it;
     }
 
     // Finally clamp quads again so they don't exceed the boundry of the control.
@@ -3588,7 +3765,7 @@ void TextInput::UpdateHighlight()
   if ( mHighlightMeshActor )
   {
     // vertex and triangle buffers should always be present if MeshActor is alive.
-    HighlightInfo newHighlightInfo = CalculateHighlightInfo();
+    HighlightInfo newHighlightInfo = CalculateHighlightInfoRtl();
     MeshData::VertexContainer vertices;
     Dali::MeshData::FaceIndices faceIndices;
 
@@ -3999,7 +4176,7 @@ bool TextInput::ReturnClosestIndex(const Vector2& source, std::size_t& closestIn
         ++closestIndex;
       }
     }
-    else if( closestIndex == numeric_limits<std::size_t>::max() ) // -1 RTL (after last arabic character on line)
+    else if( closestIndex == std::numeric_limits<std::size_t>::max() ) // -1 RTL (after last arabic character on line)
     {
       closestIndex = mTextLayoutInfo.mCharacterVisualToLogicalMap.size();
     }
@@ -4353,6 +4530,7 @@ Vector3 TextInput::GetActualPositionFromCharacterPosition( std::size_t character
 
   cursorPosition.x -= mTextLayoutInfo.mScrollOffset.x;
   cursorPosition.y -= mTextLayoutInfo.mScrollOffset.y;
+
   if( alternatePositionValid )
   {
     alternatePosition.x -= mTextLayoutInfo.mScrollOffset.x;
@@ -4719,6 +4897,7 @@ bool TextInput::CopySelectedTextToClipboard()
    */
   MarkupProcessor::StyledTextArray selectedText(mCurrentCopySelecton.begin(),mCurrentCopySelecton.end());
   MarkupProcessor::GetPlainString( selectedText, stringToStore );
+
   bool success = mClipboard.SetItem( stringToStore );
   return success;
 }
@@ -5328,7 +5507,7 @@ void TextInput::EmitStyleChangedSignal()
 {
   // emit signal if input style changes.
   Toolkit::TextInput handle( GetOwner() );
-  mStyleChangedSignalV2.Emit( handle, mInputStyle );
+  mStyleChangedSignal.Emit( handle, mInputStyle );
 }
 
 void TextInput::EmitTextModified()
@@ -5345,7 +5524,7 @@ void TextInput::EmitMaxInputCharactersReachedSignal()
   DALI_LOG_INFO(gLogFilter, Debug::General, "EmitMaxInputCharactersReachedSignal \n");
 
   Toolkit::TextInput handle( GetOwner() );
-  mMaxInputCharactersReachedSignalV2.Emit( handle );
+  mMaxInputCharactersReachedSignal.Emit( handle );
 }
 
 void TextInput::EmitInputTextExceedsBoundariesSignal()
@@ -5353,7 +5532,7 @@ void TextInput::EmitInputTextExceedsBoundariesSignal()
   // Emit a signal when the input text exceeds the boundaries of the text input.
 
   Toolkit::TextInput handle( GetOwner() );
-  mInputTextExceedBoundariesSignalV2.Emit( handle );
+  mInputTextExceedBoundariesSignal.Emit( handle );
 }
 
 } // namespace Internal