[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-controller-impl.cpp
diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp
deleted file mode 100644 (file)
index e97535c..0000000
+++ /dev/null
@@ -1,1888 +0,0 @@
-/*
- * Copyright (c) 2022 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// CLASS HEADER
-#include <dali-toolkit/internal/text/text-controller-impl.h>
-
-// EXTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/window-devel.h>
-#include <dali/integration-api/debug.h>
-#include <dali/public-api/actors/layer.h>
-#include <dali/public-api/rendering/renderer.h>
-#include <cmath>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/character-set-conversion.h>
-#include <dali-toolkit/internal/text/cursor-helper-functions.h>
-#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
-#include <dali-toolkit/internal/text/text-control-interface.h>
-#include <dali-toolkit/internal/text/text-controller-impl-data-clearer.h>
-#include <dali-toolkit/internal/text/text-controller-impl-event-handler.h>
-#include <dali-toolkit/internal/text/text-controller-impl-model-updater.h>
-#include <dali-toolkit/internal/text/text-controller-placeholder-handler.h>
-#include <dali-toolkit/internal/text/text-controller-relayouter.h>
-#include <dali-toolkit/internal/text/text-editable-control-interface.h>
-#include <dali-toolkit/internal/text/text-enumerations-impl.h>
-#include <dali-toolkit/internal/text/text-run-container.h>
-#include <dali-toolkit/internal/text/text-selection-handle-controller.h>
-#include <dali-toolkit/internal/text/underlined-glyph-run.h>
-
-using namespace Dali;
-
-namespace
-{
-#if defined(DEBUG_ENABLED)
-Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
-#endif
-
-constexpr float MAX_FLOAT = std::numeric_limits<float>::max();
-
-const std::string EMPTY_STRING("");
-
-} // namespace
-
-namespace Dali::Toolkit::Text
-{
-namespace
-{
-void SetDefaultInputStyle(InputStyle& inputStyle, const FontDefaults* const fontDefaults, const Vector4& textColor)
-{
-  // Sets the default text's color.
-  inputStyle.textColor      = textColor;
-  inputStyle.isDefaultColor = true;
-
-  inputStyle.familyName.clear();
-  inputStyle.weight = TextAbstraction::FontWeight::NORMAL;
-  inputStyle.width  = TextAbstraction::FontWidth::NORMAL;
-  inputStyle.slant  = TextAbstraction::FontSlant::NORMAL;
-  inputStyle.size   = 0.f;
-
-  inputStyle.lineSpacing = 0.f;
-
-  inputStyle.underlineProperties.clear();
-  inputStyle.shadowProperties.clear();
-  inputStyle.embossProperties.clear();
-  inputStyle.outlineProperties.clear();
-
-  inputStyle.isFamilyDefined = false;
-  inputStyle.isWeightDefined = false;
-  inputStyle.isWidthDefined  = false;
-  inputStyle.isSlantDefined  = false;
-  inputStyle.isSizeDefined   = false;
-
-  inputStyle.isLineSpacingDefined = false;
-
-  inputStyle.isUnderlineDefined = false;
-  inputStyle.isShadowDefined    = false;
-  inputStyle.isEmbossDefined    = false;
-  inputStyle.isOutlineDefined   = false;
-
-  // Sets the default font's family name, weight, width, slant and size.
-  if(fontDefaults)
-  {
-    if(fontDefaults->familyDefined)
-    {
-      inputStyle.familyName      = fontDefaults->mFontDescription.family;
-      inputStyle.isFamilyDefined = true;
-    }
-
-    if(fontDefaults->weightDefined)
-    {
-      inputStyle.weight          = fontDefaults->mFontDescription.weight;
-      inputStyle.isWeightDefined = true;
-    }
-
-    if(fontDefaults->widthDefined)
-    {
-      inputStyle.width          = fontDefaults->mFontDescription.width;
-      inputStyle.isWidthDefined = true;
-    }
-
-    if(fontDefaults->slantDefined)
-    {
-      inputStyle.slant          = fontDefaults->mFontDescription.slant;
-      inputStyle.isSlantDefined = true;
-    }
-
-    if(fontDefaults->sizeDefined)
-    {
-      inputStyle.size          = fontDefaults->mDefaultPointSize;
-      inputStyle.isSizeDefined = true;
-    }
-  }
-}
-
-void ChangeTextControllerState(Controller::Impl& impl, EventData::State newState)
-{
-  EventData* eventData = impl.mEventData;
-
-  if(nullptr == eventData)
-  {
-    // Nothing to do if there is no text input.
-    return;
-  }
-
-  DecoratorPtr& decorator = eventData->mDecorator;
-  if(!decorator)
-  {
-    // Nothing to do if there is no decorator.
-    return;
-  }
-
-  DALI_LOG_INFO(gLogFilter, Debug::General, "ChangeState state:%d  newstate:%d\n", eventData->mState, newState);
-
-  if(eventData->mState != newState)
-  {
-    eventData->mPreviousState = eventData->mState;
-    eventData->mState         = newState;
-
-    switch(eventData->mState)
-    {
-      case EventData::INACTIVE:
-      {
-        decorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
-        decorator->StopCursorBlink();
-        decorator->SetHandleActive(GRAB_HANDLE, false);
-        decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
-        decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
-        decorator->SetHighlightActive(false);
-        decorator->SetPopupActive(false);
-        eventData->mDecoratorUpdated = true;
-        break;
-      }
-
-      case EventData::INTERRUPTED:
-      {
-        decorator->SetHandleActive(GRAB_HANDLE, false);
-        decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
-        decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
-        decorator->SetHighlightActive(false);
-        decorator->SetPopupActive(false);
-        eventData->mDecoratorUpdated = true;
-        break;
-      }
-
-      case EventData::SELECTING:
-      {
-        decorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
-        decorator->StopCursorBlink();
-        decorator->SetHandleActive(GRAB_HANDLE, false);
-        if(eventData->mGrabHandleEnabled)
-        {
-          decorator->SetHandleActive(LEFT_SELECTION_HANDLE, true);
-          decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, true);
-        }
-        decorator->SetHighlightActive(true);
-        if(eventData->mGrabHandlePopupEnabled)
-        {
-          impl.SetPopupButtons();
-          decorator->SetPopupActive(true);
-        }
-        eventData->mDecoratorUpdated = true;
-        break;
-      }
-
-      case EventData::EDITING:
-      {
-        decorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
-        if(eventData->mCursorBlinkEnabled)
-        {
-          decorator->StartCursorBlink();
-        }
-        // Grab handle is not shown until a tap is received whilst EDITING
-        decorator->SetHandleActive(GRAB_HANDLE, false);
-        decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
-        decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
-        decorator->SetHighlightActive(false);
-        if(eventData->mGrabHandlePopupEnabled)
-        {
-          decorator->SetPopupActive(false);
-        }
-        eventData->mDecoratorUpdated = true;
-        break;
-      }
-      case EventData::EDITING_WITH_POPUP:
-      {
-        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_POPUP \n", newState);
-
-        decorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
-        if(eventData->mCursorBlinkEnabled)
-        {
-          decorator->StartCursorBlink();
-        }
-        if(eventData->mSelectionEnabled)
-        {
-          decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
-          decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
-          decorator->SetHighlightActive(false);
-        }
-        else if(eventData->mGrabHandleEnabled)
-        {
-          decorator->SetHandleActive(GRAB_HANDLE, true);
-        }
-        if(eventData->mGrabHandlePopupEnabled)
-        {
-          impl.SetPopupButtons();
-          decorator->SetPopupActive(true);
-        }
-        eventData->mDecoratorUpdated = true;
-        break;
-      }
-      case EventData::EDITING_WITH_GRAB_HANDLE:
-      {
-        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_GRAB_HANDLE \n", newState);
-
-        decorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
-        if(eventData->mCursorBlinkEnabled)
-        {
-          decorator->StartCursorBlink();
-        }
-        // Grab handle is not shown until a tap is received whilst EDITING
-        if(eventData->mGrabHandleEnabled)
-        {
-          decorator->SetHandleActive(GRAB_HANDLE, true);
-        }
-        decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
-        decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
-        decorator->SetHighlightActive(false);
-        if(eventData->mGrabHandlePopupEnabled)
-        {
-          decorator->SetPopupActive(false);
-        }
-        eventData->mDecoratorUpdated = true;
-        break;
-      }
-
-      case EventData::SELECTION_HANDLE_PANNING:
-      {
-        decorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
-        decorator->StopCursorBlink();
-        decorator->SetHandleActive(GRAB_HANDLE, false);
-        if(eventData->mGrabHandleEnabled)
-        {
-          decorator->SetHandleActive(LEFT_SELECTION_HANDLE, true);
-          decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, true);
-        }
-        decorator->SetHighlightActive(true);
-        if(eventData->mGrabHandlePopupEnabled)
-        {
-          decorator->SetPopupActive(false);
-        }
-        eventData->mDecoratorUpdated = true;
-        break;
-      }
-
-      case EventData::GRAB_HANDLE_PANNING:
-      {
-        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "GRAB_HANDLE_PANNING \n", newState);
-
-        decorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
-        if(eventData->mCursorBlinkEnabled)
-        {
-          decorator->StartCursorBlink();
-        }
-        if(eventData->mGrabHandleEnabled)
-        {
-          decorator->SetHandleActive(GRAB_HANDLE, true);
-        }
-        decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
-        decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
-        decorator->SetHighlightActive(false);
-        if(eventData->mGrabHandlePopupEnabled)
-        {
-          decorator->SetPopupActive(false);
-        }
-        eventData->mDecoratorUpdated = true;
-        break;
-      }
-
-      case EventData::EDITING_WITH_PASTE_POPUP:
-      {
-        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_PASTE_POPUP \n", newState);
-
-        decorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
-        if(eventData->mCursorBlinkEnabled)
-        {
-          decorator->StartCursorBlink();
-        }
-
-        if(eventData->mGrabHandleEnabled)
-        {
-          decorator->SetHandleActive(GRAB_HANDLE, true);
-        }
-        decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
-        decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
-        decorator->SetHighlightActive(false);
-
-        if(eventData->mGrabHandlePopupEnabled)
-        {
-          impl.SetPopupButtons();
-          decorator->SetPopupActive(true);
-        }
-        eventData->mDecoratorUpdated = true;
-        break;
-      }
-
-      case EventData::TEXT_PANNING:
-      {
-        decorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
-        decorator->StopCursorBlink();
-        decorator->SetHandleActive(GRAB_HANDLE, false);
-        if(eventData->mDecorator->IsHandleActive(LEFT_SELECTION_HANDLE) ||
-           decorator->IsHandleActive(RIGHT_SELECTION_HANDLE))
-        {
-          decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
-          decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
-          decorator->SetHighlightActive(true);
-        }
-
-        if(eventData->mGrabHandlePopupEnabled)
-        {
-          decorator->SetPopupActive(false);
-        }
-
-        eventData->mDecoratorUpdated = true;
-        break;
-      }
-    }
-  }
-}
-
-} // unnamed Namespace
-
-EventData::EventData(DecoratorPtr decorator, InputMethodContext& inputMethodContext)
-: mDecorator(decorator),
-  mInputMethodContext(inputMethodContext),
-  mPlaceholderFont(nullptr),
-  mPlaceholderTextActive(),
-  mPlaceholderTextInactive(),
-  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),
-  mState(INACTIVE),
-  mPrimaryCursorPosition(0u),
-  mLeftSelectionPosition(0u),
-  mRightSelectionPosition(0u),
-  mPreEditStartPosition(0u),
-  mPreEditLength(0u),
-  mCursorHookPositionX(0.f),
-  mDoubleTapAction(Controller::NoTextTap::NO_ACTION),
-  mLongPressAction(Controller::NoTextTap::SHOW_SELECTION_POPUP),
-  mIsShowingPlaceholderText(false),
-  mPreEditFlag(false),
-  mDecoratorUpdated(false),
-  mCursorBlinkEnabled(true),
-  mGrabHandleEnabled(true),
-  mGrabHandlePopupEnabled(true),
-  mSelectionEnabled(true),
-  mUpdateCursorHookPosition(false),
-  mUpdateCursorPosition(false),
-  mUpdateGrabHandlePosition(false),
-  mUpdateLeftSelectionPosition(false),
-  mUpdateRightSelectionPosition(false),
-  mIsLeftHandleSelected(false),
-  mIsRightHandleSelected(false),
-  mUpdateHighlightBox(false),
-  mScrollAfterUpdatePosition(false),
-  mScrollAfterDelete(false),
-  mAllTextSelected(false),
-  mUpdateInputStyle(false),
-  mPasswordInput(false),
-  mCheckScrollAmount(false),
-  mIsPlaceholderPixelSize(false),
-  mIsPlaceholderElideEnabled(false),
-  mPlaceholderEllipsisFlag(false),
-  mShiftSelectionFlag(true),
-  mUpdateAlignment(false),
-  mEditingEnabled(true)
-{
-}
-
-bool Controller::Impl::ProcessInputEvents()
-{
-  return ControllerImplEventHandler::ProcessInputEvents(*this);
-}
-
-void Controller::Impl::NotifyInputMethodContext()
-{
-  if(mEventData && mEventData->mInputMethodContext)
-  {
-    CharacterIndex cursorPosition = GetLogicalCursorPosition();
-
-    const Length numberOfWhiteSpaces = GetNumberOfWhiteSpaces(0u);
-
-    // Update the cursor position by removing the initial white spaces.
-    if(cursorPosition < numberOfWhiteSpaces)
-    {
-      cursorPosition = 0u;
-    }
-    else
-    {
-      cursorPosition -= numberOfWhiteSpaces;
-    }
-
-    mEventData->mInputMethodContext.SetCursorPosition(cursorPosition);
-    mEventData->mInputMethodContext.NotifyCursorPosition();
-  }
-}
-
-void Controller::Impl::NotifyInputMethodContextMultiLineStatus()
-{
-  if(mEventData && mEventData->mInputMethodContext)
-  {
-    Text::Layout::Engine::Type layout = mLayoutEngine.GetLayout();
-    mEventData->mInputMethodContext.NotifyTextInputMultiLine(layout == Text::Layout::Engine::MULTI_LINE_BOX);
-  }
-}
-
-CharacterIndex Controller::Impl::GetLogicalCursorPosition() const
-{
-  CharacterIndex cursorPosition = 0u;
-
-  if(mEventData)
-  {
-    if((EventData::SELECTING == mEventData->mState) ||
-       (EventData::SELECTION_HANDLE_PANNING == mEventData->mState))
-    {
-      cursorPosition = std::min(mEventData->mRightSelectionPosition, mEventData->mLeftSelectionPosition);
-    }
-    else
-    {
-      cursorPosition = mEventData->mPrimaryCursorPosition;
-    }
-  }
-
-  return cursorPosition;
-}
-
-Length Controller::Impl::GetNumberOfWhiteSpaces(CharacterIndex index) const
-{
-  Length numberOfWhiteSpaces = 0u;
-
-  // Get the buffer to the text.
-  Character* utf32CharacterBuffer = mModel->mLogicalModel->mText.Begin();
-
-  const Length totalNumberOfCharacters = mModel->mLogicalModel->mText.Count();
-  for(; index < totalNumberOfCharacters; ++index, ++numberOfWhiteSpaces)
-  {
-    if(!TextAbstraction::IsWhiteSpace(*(utf32CharacterBuffer + index)))
-    {
-      break;
-    }
-  }
-
-  return numberOfWhiteSpaces;
-}
-
-void Controller::Impl::GetText(std::string& text) const
-{
-  if(!IsShowingPlaceholderText())
-  {
-    // Retrieves the text string.
-    GetText(0u, text);
-  }
-  else
-  {
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::GetText %p empty (but showing placeholder)\n", this);
-  }
-}
-
-void Controller::Impl::GetText(CharacterIndex index, std::string& text) const
-{
-  // Get the total number of characters.
-  Length numberOfCharacters = mModel->mLogicalModel->mText.Count();
-
-  // Retrieve the text.
-  if(0u != numberOfCharacters)
-  {
-    Utf32ToUtf8(mModel->mLogicalModel->mText.Begin() + index, numberOfCharacters - index, text);
-  }
-}
-
-Dali::LayoutDirection::Type Controller::Impl::GetLayoutDirection(Dali::Actor& actor) const
-{
-  if(mModel->mMatchLayoutDirection == DevelText::MatchLayoutDirection::LOCALE ||
-     (mModel->mMatchLayoutDirection == DevelText::MatchLayoutDirection::INHERIT && !mIsLayoutDirectionChanged))
-  {
-    return static_cast<Dali::LayoutDirection::Type>(DevelWindow::Get(actor).GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
-  }
-  else
-  {
-    return static_cast<Dali::LayoutDirection::Type>(actor.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
-  }
-}
-
-Toolkit::DevelText::TextDirection::Type Controller::Impl::GetTextDirection()
-{
-  if(mUpdateTextDirection)
-  {
-    // Operations that can be done only once until the text changes.
-    const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
-                                                                          GET_SCRIPTS |
-                                                                          VALIDATE_FONTS |
-                                                                          GET_LINE_BREAKS |
-                                                                          BIDI_INFO |
-                                                                          SHAPE_TEXT |
-                                                                          GET_GLYPH_METRICS);
-
-    // Set the update info to relayout the whole text.
-    mTextUpdateInfo.mParagraphCharacterIndex     = 0u;
-    mTextUpdateInfo.mRequestedNumberOfCharacters = mModel->mLogicalModel->mText.Count();
-
-    // Make sure the model is up-to-date before layouting
-    UpdateModel(onlyOnceOperations);
-
-    Vector3 naturalSize;
-    Relayouter::DoRelayout(*this,
-                           Size(MAX_FLOAT, MAX_FLOAT),
-                           static_cast<OperationsMask>(onlyOnceOperations |
-                                                       LAYOUT | REORDER | UPDATE_DIRECTION),
-                           naturalSize.GetVectorXY());
-
-    // Do not do again the only once operations.
-    mOperationsPending = static_cast<OperationsMask>(mOperationsPending & ~onlyOnceOperations);
-
-    // Clear the update info. This info will be set the next time the text is updated.
-    mTextUpdateInfo.Clear();
-
-    // FullRelayoutNeeded should be true because DoRelayout is MAX_FLOAT, MAX_FLOAT.
-    mTextUpdateInfo.mFullRelayoutNeeded = true;
-
-    mUpdateTextDirection = false;
-  }
-
-  return mIsTextDirectionRTL ? Toolkit::DevelText::TextDirection::RIGHT_TO_LEFT : Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT;
-}
-
-void Controller::Impl::CalculateTextUpdateIndices(Length& numberOfCharacters)
-{
-  mTextUpdateInfo.mParagraphCharacterIndex = 0u;
-  mTextUpdateInfo.mStartGlyphIndex         = 0u;
-  mTextUpdateInfo.mStartLineIndex          = 0u;
-  numberOfCharacters                       = 0u;
-
-  const Length numberOfParagraphs = mModel->mLogicalModel->mParagraphInfo.Count();
-  if(0u == numberOfParagraphs)
-  {
-    mTextUpdateInfo.mParagraphCharacterIndex = 0u;
-    numberOfCharacters                       = 0u;
-
-    mTextUpdateInfo.mRequestedNumberOfCharacters = mTextUpdateInfo.mNumberOfCharactersToAdd - mTextUpdateInfo.mNumberOfCharactersToRemove;
-
-    // Nothing else to do if there are no paragraphs.
-    return;
-  }
-
-  // Find the paragraphs to be updated.
-  Vector<ParagraphRunIndex> paragraphsToBeUpdated;
-  if(mTextUpdateInfo.mCharacterIndex >= mTextUpdateInfo.mPreviousNumberOfCharacters)
-  {
-    // Text is being added at the end of the current text.
-    if(mTextUpdateInfo.mIsLastCharacterNewParagraph)
-    {
-      // Text is being added in a new paragraph after the last character of the text.
-      mTextUpdateInfo.mParagraphCharacterIndex     = mTextUpdateInfo.mPreviousNumberOfCharacters;
-      numberOfCharacters                           = 0u;
-      mTextUpdateInfo.mRequestedNumberOfCharacters = mTextUpdateInfo.mNumberOfCharactersToAdd - mTextUpdateInfo.mNumberOfCharactersToRemove;
-
-      mTextUpdateInfo.mStartGlyphIndex = mModel->mVisualModel->mGlyphs.Count();
-      mTextUpdateInfo.mStartLineIndex  = mModel->mVisualModel->mLines.Count() - 1u;
-
-      // Nothing else to do;
-      return;
-    }
-
-    paragraphsToBeUpdated.PushBack(numberOfParagraphs - 1u);
-  }
-  else
-  {
-    Length numberOfCharactersToUpdate = 0u;
-    if(mTextUpdateInfo.mFullRelayoutNeeded)
-    {
-      numberOfCharactersToUpdate = mTextUpdateInfo.mPreviousNumberOfCharacters;
-    }
-    else
-    {
-      numberOfCharactersToUpdate = (mTextUpdateInfo.mNumberOfCharactersToRemove > 0u) ? mTextUpdateInfo.mNumberOfCharactersToRemove : 1u;
-    }
-    mModel->mLogicalModel->FindParagraphs(mTextUpdateInfo.mCharacterIndex,
-                                          numberOfCharactersToUpdate,
-                                          paragraphsToBeUpdated);
-  }
-
-  if(0u != paragraphsToBeUpdated.Count())
-  {
-    const ParagraphRunIndex firstParagraphIndex = *(paragraphsToBeUpdated.Begin());
-    const ParagraphRun&     firstParagraph      = *(mModel->mLogicalModel->mParagraphInfo.Begin() + firstParagraphIndex);
-    mTextUpdateInfo.mParagraphCharacterIndex    = firstParagraph.characterRun.characterIndex;
-
-    ParagraphRunIndex   lastParagraphIndex = *(paragraphsToBeUpdated.End() - 1u);
-    const ParagraphRun& lastParagraph      = *(mModel->mLogicalModel->mParagraphInfo.Begin() + lastParagraphIndex);
-
-    if((mTextUpdateInfo.mNumberOfCharactersToRemove > 0u) &&                                           // Some character are removed.
-       (lastParagraphIndex < numberOfParagraphs - 1u) &&                                               // There is a next paragraph.
-       ((lastParagraph.characterRun.characterIndex + lastParagraph.characterRun.numberOfCharacters) == // The last removed character is the new paragraph character.
-        (mTextUpdateInfo.mCharacterIndex + mTextUpdateInfo.mNumberOfCharactersToRemove)))
-    {
-      // The new paragraph character of the last updated paragraph has been removed so is going to be merged with the next one.
-      const ParagraphRun& lastParagraph = *(mModel->mLogicalModel->mParagraphInfo.Begin() + lastParagraphIndex + 1u);
-
-      numberOfCharacters = lastParagraph.characterRun.characterIndex + lastParagraph.characterRun.numberOfCharacters - mTextUpdateInfo.mParagraphCharacterIndex;
-    }
-    else
-    {
-      numberOfCharacters = lastParagraph.characterRun.characterIndex + lastParagraph.characterRun.numberOfCharacters - mTextUpdateInfo.mParagraphCharacterIndex;
-    }
-  }
-
-  mTextUpdateInfo.mRequestedNumberOfCharacters = numberOfCharacters + mTextUpdateInfo.mNumberOfCharactersToAdd - mTextUpdateInfo.mNumberOfCharactersToRemove;
-  mTextUpdateInfo.mStartGlyphIndex             = *(mModel->mVisualModel->mCharactersToGlyph.Begin() + mTextUpdateInfo.mParagraphCharacterIndex);
-}
-
-void Controller::Impl::ClearModelData(CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations)
-{
-  ControllerImplDataClearer::ClearModelData(*this, startIndex, endIndex, operations);
-}
-
-bool Controller::Impl::UpdateModel(OperationsMask operationsRequired)
-{
-  return ControllerImplModelUpdater::Update(*this, operationsRequired);
-}
-
-void Controller::Impl::RetrieveDefaultInputStyle(InputStyle& inputStyle)
-{
-  SetDefaultInputStyle(inputStyle, mFontDefaults, mTextColor);
-}
-
-float Controller::Impl::GetDefaultFontLineHeight()
-{
-  FontId defaultFontId = 0u;
-  if(nullptr == mFontDefaults)
-  {
-    TextAbstraction::FontDescription fontDescription;
-    defaultFontId = mFontClient.GetFontId(fontDescription, TextAbstraction::FontClient::DEFAULT_POINT_SIZE * GetFontSizeScale());
-  }
-  else
-  {
-    defaultFontId = mFontDefaults->GetFontId(mFontClient, mFontDefaults->mDefaultPointSize * GetFontSizeScale());
-  }
-
-  Text::FontMetrics fontMetrics;
-  mMetrics->GetFontMetrics(defaultFontId, fontMetrics);
-
-  return (fontMetrics.ascender - fontMetrics.descender);
-}
-
-bool Controller::Impl::SetDefaultLineSpacing(float lineSpacing)
-{
-  if(std::fabs(lineSpacing - mLayoutEngine.GetDefaultLineSpacing()) > Math::MACHINE_EPSILON_1000)
-  {
-    mLayoutEngine.SetDefaultLineSpacing(lineSpacing);
-
-    RelayoutAllCharacters();
-    return true;
-  }
-  return false;
-}
-
-bool Controller::Impl::SetDefaultLineSize(float lineSize)
-{
-  if(std::fabs(lineSize - mLayoutEngine.GetDefaultLineSize()) > Math::MACHINE_EPSILON_1000)
-  {
-    mLayoutEngine.SetDefaultLineSize(lineSize);
-
-    RelayoutAllCharacters();
-    return true;
-  }
-  return false;
-}
-
-bool Controller::Impl::SetRelativeLineSize(float relativeLineSize)
-{
-  if(std::fabs(relativeLineSize - GetRelativeLineSize()) > Math::MACHINE_EPSILON_1000)
-  {
-    mLayoutEngine.SetRelativeLineSize(relativeLineSize);
-
-    RelayoutAllCharacters();
-    return true;
-  }
-  return false;
-}
-
-float Controller::Impl::GetRelativeLineSize()
-{
-  return mLayoutEngine.GetRelativeLineSize();
-}
-
-string Controller::Impl::GetSelectedText()
-{
-  string text;
-  if(EventData::SELECTING == mEventData->mState)
-  {
-    RetrieveSelection(text, false);
-  }
-  return text;
-}
-
-string Controller::Impl::CopyText()
-{
-  string text;
-  RetrieveSelection(text, false);
-  SendSelectionToClipboard(false); // Text not modified
-
-  mEventData->mUpdateCursorPosition = true;
-
-  RequestRelayout(); // Cursor, Handles, Selection Highlight, Popup
-
-  return text;
-}
-
-string Controller::Impl::CutText()
-{
-  string text;
-  RetrieveSelection(text, false);
-
-  if(!IsEditable())
-  {
-    return EMPTY_STRING;
-  }
-
-  SendSelectionToClipboard(true); // Synchronous call to modify text
-  mOperationsPending = ALL_OPERATIONS;
-
-  if((0u != mModel->mLogicalModel->mText.Count()) ||
-     !IsPlaceholderAvailable())
-  {
-    QueueModifyEvent(ModifyEvent::TEXT_DELETED);
-  }
-  else
-  {
-    PlaceholderHandler::ShowPlaceholderText(*this);
-  }
-
-  mEventData->mUpdateCursorPosition = true;
-  mEventData->mScrollAfterDelete    = true;
-
-  RequestRelayout();
-
-  if(nullptr != mEditableControlInterface)
-  {
-    mEditableControlInterface->TextChanged(true);
-  }
-  return text;
-}
-
-void Controller::Impl::SetTextSelectionRange(const uint32_t* pStart, const uint32_t* pEnd)
-{
-  if(nullptr == mEventData)
-  {
-    // Nothing to do if there is no text.
-    return;
-  }
-
-  if(mEventData->mSelectionEnabled && (pStart || pEnd))
-  {
-    uint32_t length   = static_cast<uint32_t>(mModel->mLogicalModel->mText.Count());
-    uint32_t oldStart = mEventData->mLeftSelectionPosition;
-    uint32_t oldEnd   = mEventData->mRightSelectionPosition;
-
-    if(pStart)
-    {
-      mEventData->mLeftSelectionPosition = std::min(*pStart, length);
-    }
-    if(pEnd)
-    {
-      mEventData->mRightSelectionPosition = std::min(*pEnd, length);
-    }
-
-    if(mEventData->mLeftSelectionPosition == mEventData->mRightSelectionPosition)
-    {
-      ChangeState(EventData::EDITING);
-      mEventData->mPrimaryCursorPosition = mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition;
-      mEventData->mUpdateCursorPosition                                       = true;
-    }
-    else
-    {
-      ChangeState(EventData::SELECTING);
-      mEventData->mUpdateHighlightBox           = true;
-      mEventData->mUpdateLeftSelectionPosition  = true;
-      mEventData->mUpdateRightSelectionPosition = true;
-    }
-
-    if(mSelectableControlInterface != nullptr)
-    {
-      mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition);
-    }
-  }
-}
-
-CharacterIndex Controller::Impl::GetPrimaryCursorPosition() const
-{
-  if(nullptr == mEventData)
-  {
-    return 0;
-  }
-  return mEventData->mPrimaryCursorPosition;
-}
-
-bool Controller::Impl::SetPrimaryCursorPosition(CharacterIndex index, bool focused)
-{
-  if(nullptr == mEventData)
-  {
-    // Nothing to do if there is no text.
-    return false;
-  }
-
-  if(mEventData->mPrimaryCursorPosition == index && mEventData->mState != EventData::SELECTING)
-  {
-    // Nothing for same cursor position.
-    return false;
-  }
-
-  uint32_t length                    = static_cast<uint32_t>(mModel->mLogicalModel->mText.Count());
-  uint32_t oldCursorPos              = mEventData->mPrimaryCursorPosition;
-  mEventData->mPrimaryCursorPosition = std::min(index, length);
-  // If there is no focus, only the value is updated.
-  if(focused)
-  {
-    bool     wasInSelectingState = mEventData->mState == EventData::SELECTING;
-    uint32_t oldStart            = mEventData->mLeftSelectionPosition;
-    uint32_t oldEnd              = mEventData->mRightSelectionPosition;
-    ChangeState(EventData::EDITING);
-    mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition = mEventData->mPrimaryCursorPosition;
-    mEventData->mUpdateCursorPosition                                        = true;
-
-    if(mSelectableControlInterface != nullptr && wasInSelectingState)
-    {
-      mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition);
-    }
-
-    ScrollTextToMatchCursor();
-  }
-
-  if(nullptr != mEditableControlInterface)
-  {
-    mEditableControlInterface->CursorPositionChanged(oldCursorPos, mEventData->mPrimaryCursorPosition);
-  }
-
-  return true;
-}
-
-Uint32Pair Controller::Impl::GetTextSelectionRange() const
-{
-  Uint32Pair range;
-
-  if(mEventData)
-  {
-    range.first  = mEventData->mLeftSelectionPosition;
-    range.second = mEventData->mRightSelectionPosition;
-  }
-
-  return range;
-}
-
-bool Controller::Impl::IsEditable() const
-{
-  return mEventData && mEventData->mEditingEnabled;
-}
-
-void Controller::Impl::SetEditable(bool editable)
-{
-  if(mEventData)
-  {
-    mEventData->mEditingEnabled = editable;
-
-    if(mEventData->mDecorator)
-    {
-      mEventData->mDecorator->SetEditable(editable);
-    }
-  }
-}
-
-void Controller::Impl::UpdateAfterFontChange(const std::string& newDefaultFont)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::UpdateAfterFontChange\n");
-
-  if(!mFontDefaults->familyDefined) // If user defined font then should not update when system font changes
-  {
-    DALI_LOG_INFO(gLogFilter, Debug::Concise, "Controller::UpdateAfterFontChange newDefaultFont(%s)\n", newDefaultFont.c_str());
-    mFontDefaults->mFontDescription.family = newDefaultFont;
-
-    ClearFontData();
-
-    RequestRelayout();
-  }
-}
-
-void Controller::Impl::RetrieveSelection(std::string& selectedText, bool deleteAfterRetrieval)
-{
-  if(mEventData->mLeftSelectionPosition == mEventData->mRightSelectionPosition)
-  {
-    // Nothing to select if handles are in the same place.
-    selectedText.clear();
-    return;
-  }
-
-  const bool handlesCrossed = mEventData->mLeftSelectionPosition > mEventData->mRightSelectionPosition;
-
-  //Get start and end position of selection
-  const CharacterIndex startOfSelectedText  = handlesCrossed ? mEventData->mRightSelectionPosition : mEventData->mLeftSelectionPosition;
-  const Length         lengthOfSelectedText = (handlesCrossed ? mEventData->mLeftSelectionPosition : mEventData->mRightSelectionPosition) - startOfSelectedText;
-
-  Vector<Character>& utf32Characters    = mModel->mLogicalModel->mText;
-  const Length       numberOfCharacters = utf32Characters.Count();
-
-  // Validate the start and end selection points
-  if((startOfSelectedText + lengthOfSelectedText) <= numberOfCharacters)
-  {
-    //Get text as a UTF8 string
-    Utf32ToUtf8(&utf32Characters[startOfSelectedText], lengthOfSelectedText, selectedText);
-
-    if(deleteAfterRetrieval) // Only delete text if copied successfully
-    {
-      // Keep a copy of the current input style.
-      InputStyle currentInputStyle;
-      currentInputStyle.Copy(mEventData->mInputStyle);
-
-      // Set as input style the style of the first deleted character.
-      mModel->mLogicalModel->RetrieveStyle(startOfSelectedText, 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);
-      }
-
-      mModel->mLogicalModel->UpdateTextStyleRuns(startOfSelectedText, -static_cast<int>(lengthOfSelectedText));
-
-      // Mark the paragraphs to be updated.
-      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;
-      Vector<Character>::Iterator last  = first + lengthOfSelectedText;
-      utf32Characters.Erase(first, last);
-
-      // Will show the cursor at the first character of the selection.
-      mEventData->mPrimaryCursorPosition = handlesCrossed ? mEventData->mRightSelectionPosition : mEventData->mLeftSelectionPosition;
-    }
-    else
-    {
-      // Will show the cursor at the last character of the selection.
-      mEventData->mPrimaryCursorPosition = handlesCrossed ? mEventData->mLeftSelectionPosition : mEventData->mRightSelectionPosition;
-    }
-
-    mEventData->mDecoratorUpdated = true;
-  }
-}
-
-void Controller::Impl::SetSelection(int start, int end)
-{
-  uint32_t oldStart = mEventData->mLeftSelectionPosition;
-  uint32_t oldEnd   = mEventData->mRightSelectionPosition;
-
-  mEventData->mLeftSelectionPosition  = start;
-  mEventData->mRightSelectionPosition = end;
-  mEventData->mUpdateCursorPosition   = true;
-
-  if(mSelectableControlInterface != nullptr)
-  {
-    mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, start, end);
-  }
-}
-
-std::pair<int, int> Controller::Impl::GetSelectionIndexes() const
-{
-  return {mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition};
-}
-
-void Controller::Impl::ShowClipboard()
-{
-  if(mClipboard)
-  {
-    mClipboard.ShowClipboard();
-  }
-}
-
-void Controller::Impl::HideClipboard()
-{
-  if(mClipboard && mClipboardHideEnabled)
-  {
-    mClipboard.HideClipboard();
-  }
-}
-
-void Controller::Impl::SetClipboardHideEnable(bool enable)
-{
-  mClipboardHideEnabled = enable;
-}
-
-bool Controller::Impl::CopyStringToClipboard(const std::string& source)
-{
-  //Send string to clipboard
-  return (mClipboard && mClipboard.SetItem(source));
-}
-
-void Controller::Impl::SendSelectionToClipboard(bool deleteAfterSending)
-{
-  std::string selectedText;
-  RetrieveSelection(selectedText, deleteAfterSending);
-  CopyStringToClipboard(selectedText);
-  ChangeState(EventData::EDITING);
-}
-
-void Controller::Impl::RequestGetTextFromClipboard()
-{
-  if(mClipboard)
-  {
-    mClipboard.RequestItem();
-  }
-}
-
-void Controller::Impl::RepositionSelectionHandles()
-{
-  SelectionHandleController::Reposition(*this);
-}
-void Controller::Impl::RepositionSelectionHandles(float visualX, float visualY, Controller::NoTextTap::Action action)
-{
-  SelectionHandleController::Reposition(*this, visualX, visualY, action);
-}
-
-void Controller::Impl::SetPopupButtons()
-{
-  /**
-   *  Sets the Popup buttons to be shown depending on State.
-   *
-   *  If SELECTING :  CUT & COPY + ( PASTE & CLIPBOARD if content available to paste )
-   *
-   *  If EDITING_WITH_POPUP : SELECT & SELECT_ALL
-   */
-
-  bool                        isEditable    = IsEditable();
-  TextSelectionPopup::Buttons buttonsToShow = TextSelectionPopup::NONE;
-
-  if(EventData::SELECTING == mEventData->mState)
-  {
-    buttonsToShow = TextSelectionPopup::Buttons(TextSelectionPopup::COPY);
-    if(isEditable)
-    {
-      buttonsToShow = TextSelectionPopup::Buttons(buttonsToShow | TextSelectionPopup::CUT);
-    }
-
-    if(!IsClipboardEmpty())
-    {
-      if(isEditable)
-      {
-        buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::PASTE));
-      }
-      buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::CLIPBOARD));
-    }
-
-    if(!mEventData->mAllTextSelected)
-    {
-      buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::SELECT_ALL));
-    }
-  }
-  else if(EventData::EDITING_WITH_POPUP == mEventData->mState)
-  {
-    if(mModel->mLogicalModel->mText.Count() && !IsShowingPlaceholderText())
-    {
-      buttonsToShow = TextSelectionPopup::Buttons(TextSelectionPopup::SELECT | TextSelectionPopup::SELECT_ALL);
-    }
-
-    if(!IsClipboardEmpty())
-    {
-      if(isEditable)
-      {
-        buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::PASTE));
-      }
-      buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::CLIPBOARD));
-    }
-  }
-  else if(EventData::EDITING_WITH_PASTE_POPUP == mEventData->mState)
-  {
-    if(!IsClipboardEmpty())
-    {
-      if(isEditable)
-      {
-        buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::PASTE));
-      }
-      buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::CLIPBOARD));
-    }
-  }
-
-  mEventData->mDecorator->SetEnabledPopupButtons(buttonsToShow);
-}
-
-void Controller::Impl::ChangeState(EventData::State newState)
-{
-  ChangeTextControllerState(*this, newState);
-}
-
-void Controller::Impl::GetCursorPosition(CharacterIndex logical,
-                                         CursorInfo&    cursorInfo)
-{
-  if(!IsShowingRealText())
-  {
-    // Do not want to use the place-holder text to set the cursor position.
-
-    // Use the line's height of the font's family set to set the cursor's size.
-    // If there is no font's family set, use the default font.
-    // Use the current alignment to place the cursor at the beginning, center or end of the box.
-
-    cursorInfo.lineOffset          = 0.f;
-    cursorInfo.lineHeight          = GetDefaultFontLineHeight();
-    cursorInfo.primaryCursorHeight = cursorInfo.lineHeight;
-
-    bool isRTL = false;
-    if(mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS)
-    {
-      isRTL = mLayoutDirection == LayoutDirection::RIGHT_TO_LEFT;
-    }
-
-    switch(mModel->mHorizontalAlignment)
-    {
-      case Text::HorizontalAlignment::BEGIN:
-      {
-        if(isRTL)
-        {
-          cursorInfo.primaryPosition.x = mModel->mVisualModel->mControlSize.width - mEventData->mDecorator->GetCursorWidth();
-        }
-        else
-        {
-          cursorInfo.primaryPosition.x = 0.f;
-        }
-        break;
-      }
-      case Text::HorizontalAlignment::CENTER:
-      {
-        cursorInfo.primaryPosition.x = floorf(0.5f * mModel->mVisualModel->mControlSize.width);
-        break;
-      }
-      case Text::HorizontalAlignment::END:
-      {
-        if(isRTL)
-        {
-          cursorInfo.primaryPosition.x = 0.f;
-        }
-        else
-        {
-          cursorInfo.primaryPosition.x = mModel->mVisualModel->mControlSize.width - mEventData->mDecorator->GetCursorWidth();
-        }
-        break;
-      }
-    }
-
-    // Nothing else to do.
-    return;
-  }
-
-  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;
-
-  float defaultFontLineHeight = GetDefaultFontLineHeight();
-
-  Text::GetCursorPosition(parameters,
-                          defaultFontLineHeight,
-                          cursorInfo);
-
-  // 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.
-
-    // Note the white spaces laid-out at the end of the line might exceed the boundaries of the control.
-    // The reason is a wrapped line must not start with a white space so they are laid-out at the end of the line.
-
-    if(0.f > cursorInfo.primaryPosition.x)
-    {
-      cursorInfo.primaryPosition.x = 0.f;
-    }
-
-    const float edgeWidth = mModel->mVisualModel->mControlSize.width - static_cast<float>(mEventData->mDecorator->GetCursorWidth());
-    if(cursorInfo.primaryPosition.x > edgeWidth)
-    {
-      cursorInfo.primaryPosition.x = edgeWidth;
-    }
-  }
-}
-
-CharacterIndex Controller::Impl::CalculateNewCursorIndex(CharacterIndex index) const
-{
-  if(nullptr == mEventData)
-  {
-    // Nothing to do if there is no text input.
-    return 0u;
-  }
-
-  CharacterIndex cursorIndex = mEventData->mPrimaryCursorPosition;
-
-  const GlyphIndex* const charactersToGlyphBuffer  = mModel->mVisualModel->mCharactersToGlyph.Begin();
-  const Length* const     charactersPerGlyphBuffer = mModel->mVisualModel->mCharactersPerGlyph.Begin();
-
-  GlyphIndex glyphIndex         = *(charactersToGlyphBuffer + index);
-  Length     numberOfCharacters = *(charactersPerGlyphBuffer + glyphIndex);
-
-  if(numberOfCharacters > 1u)
-  {
-    const Script script = mModel->mLogicalModel->GetScript(index);
-    if(HasLigatureMustBreak(script))
-    {
-      // Prevents to jump the whole Latin ligatures like fi, ff, or Arabic ﻻ, ...
-      numberOfCharacters = 1u;
-    }
-  }
-  else
-  {
-    while(0u == numberOfCharacters)
-    {
-      ++glyphIndex;
-      numberOfCharacters = *(charactersPerGlyphBuffer + glyphIndex);
-    }
-  }
-
-  if(index < mEventData->mPrimaryCursorPosition)
-  {
-    cursorIndex -= numberOfCharacters;
-  }
-  else
-  {
-    cursorIndex += numberOfCharacters;
-  }
-
-  // Will update the cursor hook position.
-  mEventData->mUpdateCursorHookPosition = true;
-
-  return cursorIndex;
-}
-
-void Controller::Impl::UpdateCursorPosition(const CursorInfo& cursorInfo)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::UpdateCursorPosition %p\n", this);
-  if(nullptr == mEventData)
-  {
-    // Nothing to do if there is no text input.
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::UpdateCursorPosition no event data\n");
-    return;
-  }
-
-  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,
-                                      cursorPosition.y,
-                                      cursorInfo.primaryCursorHeight,
-                                      cursorInfo.lineHeight);
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Primary cursor position: %f,%f\n", cursorPosition.x, cursorPosition.y);
-
-  if(mEventData->mUpdateGrabHandlePosition)
-  {
-    // Sets the grab handle position.
-    mEventData->mDecorator->SetPosition(GRAB_HANDLE,
-                                        cursorPosition.x,
-                                        cursorInfo.lineOffset + mModel->mScrollPosition.y,
-                                        cursorInfo.lineHeight);
-  }
-
-  if(cursorInfo.isSecondaryCursor)
-  {
-    mEventData->mDecorator->SetPosition(SECONDARY_CURSOR,
-                                        cursorInfo.secondaryPosition.x + mModel->mScrollPosition.x,
-                                        cursorInfo.secondaryPosition.y + mModel->mScrollPosition.y,
-                                        cursorInfo.secondaryCursorHeight,
-                                        cursorInfo.lineHeight);
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Secondary cursor position: %f,%f\n", cursorInfo.secondaryPosition.x + mModel->mScrollPosition.x, cursorInfo.secondaryPosition.y + mModel->mScrollPosition.y);
-  }
-
-  // Set which cursors are active according the state.
-  if(EventData::IsEditingState(mEventData->mState) || (EventData::GRAB_HANDLE_PANNING == mEventData->mState))
-  {
-    if(cursorInfo.isSecondaryCursor)
-    {
-      mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_BOTH);
-    }
-    else
-    {
-      mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
-    }
-  }
-  else
-  {
-    mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
-  }
-
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::UpdateCursorPosition\n");
-}
-
-void Controller::Impl::UpdateSelectionHandle(HandleType        handleType,
-                                             const CursorInfo& cursorInfo)
-{
-  SelectionHandleController::Update(*this, handleType, cursorInfo);
-}
-
-void Controller::Impl::ClampHorizontalScroll(const Vector2& layoutSize)
-{
-  // Clamp between -space & -alignment offset.
-
-  if(layoutSize.width > mModel->mVisualModel->mControlSize.width)
-  {
-    const float space         = (layoutSize.width - mModel->mVisualModel->mControlSize.width) + mModel->mAlignmentOffset;
-    mModel->mScrollPosition.x = (mModel->mScrollPosition.x < -space) ? -space : mModel->mScrollPosition.x;
-    mModel->mScrollPosition.x = (mModel->mScrollPosition.x > -mModel->mAlignmentOffset) ? -mModel->mAlignmentOffset : mModel->mScrollPosition.x;
-
-    mEventData->mDecoratorUpdated = true;
-  }
-  else
-  {
-    mModel->mScrollPosition.x = 0.f;
-  }
-}
-
-void Controller::Impl::ClampVerticalScroll(const Vector2& layoutSize)
-{
-  if(Layout::Engine::SINGLE_LINE_BOX == mLayoutEngine.GetLayout())
-  {
-    // Nothing to do if the text is single line.
-    return;
-  }
-
-  // Clamp between -space & 0.
-  if(layoutSize.height > mModel->mVisualModel->mControlSize.height)
-  {
-    const float space         = (layoutSize.height - mModel->mVisualModel->mControlSize.height);
-    mModel->mScrollPosition.y = (mModel->mScrollPosition.y < -space) ? -space : mModel->mScrollPosition.y;
-    mModel->mScrollPosition.y = (mModel->mScrollPosition.y > 0.f) ? 0.f : mModel->mScrollPosition.y;
-
-    mEventData->mDecoratorUpdated = true;
-  }
-  else
-  {
-    mModel->mScrollPosition.y = 0.f;
-  }
-}
-
-void Controller::Impl::ScrollToMakePositionVisible(const Vector2& position, float lineHeight)
-{
-  const float cursorWidth = mEventData->mDecorator ? static_cast<float>(mEventData->mDecorator->GetCursorWidth()) : 0.f;
-
-  // position is in actor's coords.
-  const float positionEndX = position.x + cursorWidth;
-  const float positionEndY = position.y + lineHeight;
-
-  // Transform the position to decorator coords.
-  const float decoratorPositionBeginX = position.x + mModel->mScrollPosition.x;
-  const float decoratorPositionEndX   = positionEndX + mModel->mScrollPosition.x;
-
-  const float decoratorPositionBeginY = position.y + mModel->mScrollPosition.y;
-  const float decoratorPositionEndY   = positionEndY + mModel->mScrollPosition.y;
-
-  if(decoratorPositionBeginX < 0.f)
-  {
-    mModel->mScrollPosition.x = -position.x;
-  }
-  else if(decoratorPositionEndX > mModel->mVisualModel->mControlSize.width)
-  {
-    mModel->mScrollPosition.x = mModel->mVisualModel->mControlSize.width - positionEndX;
-  }
-
-  if(Layout::Engine::MULTI_LINE_BOX == mLayoutEngine.GetLayout())
-  {
-    if(decoratorPositionBeginY < 0.f)
-    {
-      mModel->mScrollPosition.y = -position.y;
-    }
-    else if(decoratorPositionEndY > mModel->mVisualModel->mControlSize.height)
-    {
-      mModel->mScrollPosition.y = mModel->mVisualModel->mControlSize.height - positionEndY;
-    }
-  }
-}
-
-void Controller::Impl::ScrollTextToMatchCursor(const CursorInfo& cursorInfo)
-{
-  // 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;
-
-  //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());
-
-  // Makes the new cursor position visible if needed.
-  ScrollToMakePositionVisible(cursorInfo.primaryPosition, cursorInfo.lineHeight);
-}
-
-void Controller::Impl::ScrollTextToMatchCursor()
-{
-  CursorInfo cursorInfo;
-  GetCursorPosition(mEventData->mPrimaryCursorPosition, cursorInfo);
-  ScrollTextToMatchCursor(cursorInfo);
-}
-
-void Controller::Impl::RequestRelayout()
-{
-  if(nullptr != mControlInterface)
-  {
-    mControlInterface->RequestTextRelayout();
-  }
-}
-
-void Controller::Impl::RelayoutAllCharacters()
-{
-  // relayout all characters
-  mTextUpdateInfo.mCharacterIndex             = 0;
-  mTextUpdateInfo.mNumberOfCharactersToRemove = mTextUpdateInfo.mPreviousNumberOfCharacters;
-  mTextUpdateInfo.mNumberOfCharactersToAdd    = mModel->mLogicalModel->mText.Count();
-  mOperationsPending                          = static_cast<OperationsMask>(mOperationsPending | LAYOUT);
-
-  mTextUpdateInfo.mFullRelayoutNeeded = true;
-
-  // Need to recalculate natural size
-  mRecalculateNaturalSize = true;
-
-  //remove selection
-  if((mEventData != nullptr) && (mEventData->mState == EventData::SELECTING))
-  {
-    ChangeState(EventData::EDITING);
-  }
-
-  RequestRelayout();
-}
-
-bool Controller::Impl::IsInputStyleChangedSignalsQueueEmpty()
-{
-  return (NULL == mEventData) || (0u == mEventData->mInputStyleChangedQueue.Count());
-}
-
-void Controller::Impl::ProcessInputStyleChangedSignals()
-{
-  if(mEventData)
-  {
-    if(mEditableControlInterface)
-    {
-      // Emit the input style changed signal for each mask
-      std::for_each(mEventData->mInputStyleChangedQueue.begin(),
-                    mEventData->mInputStyleChangedQueue.end(),
-                    [&](const auto mask) { mEditableControlInterface->InputStyleChanged(mask); });
-    }
-
-    mEventData->mInputStyleChangedQueue.Clear();
-  }
-}
-
-void Controller::Impl::ScrollBy(Vector2 scroll)
-{
-  if(mEventData && (fabs(scroll.x) > Math::MACHINE_EPSILON_0 || fabs(scroll.y) > Math::MACHINE_EPSILON_0))
-  {
-    const Vector2& layoutSize    = mModel->mVisualModel->GetLayoutSize();
-    const Vector2  currentScroll = mModel->mScrollPosition;
-
-    scroll.x = -scroll.x;
-    scroll.y = -scroll.y;
-
-    if(fabs(scroll.x) > Math::MACHINE_EPSILON_0)
-    {
-      mModel->mScrollPosition.x += scroll.x;
-      ClampHorizontalScroll(layoutSize);
-    }
-
-    if(fabs(scroll.y) > Math::MACHINE_EPSILON_0)
-    {
-      mModel->mScrollPosition.y += scroll.y;
-      ClampVerticalScroll(layoutSize);
-    }
-
-    if(mModel->mScrollPosition != currentScroll)
-    {
-      mEventData->mDecorator->UpdatePositions(mModel->mScrollPosition - currentScroll);
-      RequestRelayout();
-    }
-  }
-}
-
-float Controller::Impl::GetHorizontalScrollPosition()
-{
-  // Scroll values are negative internally so we convert them to positive numbers
-  return mEventData ? -mModel->mScrollPosition.x : 0.0f;
-}
-
-float Controller::Impl::GetVerticalScrollPosition()
-{
-  // Scroll values are negative internally so we convert them to positive numbers
-  return mEventData ? -mModel->mScrollPosition.y : 0.0f;
-}
-
-Vector3 Controller::Impl::GetAnchorPosition(Anchor anchor) const
-{
-  //TODO
-  return Vector3(10.f, 10.f, 10.f);
-}
-
-Vector2 Controller::Impl::GetAnchorSize(Anchor anchor) const
-{
-  //TODO
-  return Vector2(10.f, 10.f);
-}
-
-Toolkit::TextAnchor Controller::Impl::CreateAnchorActor(Anchor anchor)
-{
-  auto actor = Toolkit::TextAnchor::New();
-  actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
-  actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
-  const Vector3 anchorPosition = GetAnchorPosition(anchor);
-  actor.SetProperty(Actor::Property::POSITION, anchorPosition);
-  const Vector2 anchorSize = GetAnchorSize(anchor);
-  actor.SetProperty(Actor::Property::SIZE, anchorSize);
-  std::string anchorText(mModel->mLogicalModel->mText.Begin() + anchor.startIndex, mModel->mLogicalModel->mText.Begin() + anchor.endIndex);
-  actor.SetProperty(Actor::Property::NAME, anchorText);
-  actor.SetProperty(Toolkit::TextAnchor::Property::URI, std::string(anchor.href));
-  actor.SetProperty(Toolkit::TextAnchor::Property::START_CHARACTER_INDEX, static_cast<int>(anchor.startIndex));
-  actor.SetProperty(Toolkit::TextAnchor::Property::END_CHARACTER_INDEX, static_cast<int>(anchor.endIndex));
-  return actor;
-}
-
-void Controller::Impl::GetAnchorActors(std::vector<Toolkit::TextAnchor>& anchorActors)
-{
-  /* TODO: Now actors are created/destroyed in every "RenderText" function call. Even when we add just 1 character,
-           we need to create and destroy potentially many actors. Some optimization can be considered here.
-           Maybe a "dirty" flag in mLogicalModel? */
-  anchorActors.clear();
-  for(auto& anchor : mModel->mLogicalModel->mAnchors)
-  {
-    auto actor = CreateAnchorActor(anchor);
-    anchorActors.push_back(actor);
-  }
-}
-
-int32_t Controller::Impl::GetAnchorIndex(size_t characterOffset) const
-{
-  Vector<Anchor>::Iterator it = mModel->mLogicalModel->mAnchors.Begin();
-
-  while(it != mModel->mLogicalModel->mAnchors.End() && (it->startIndex > characterOffset || it->endIndex <= characterOffset))
-  {
-    it++;
-  }
-
-  return it == mModel->mLogicalModel->mAnchors.End() ? -1 : it - mModel->mLogicalModel->mAnchors.Begin();
-}
-
-void Controller::Impl::CopyUnderlinedFromLogicalToVisualModels(bool shouldClearPreUnderlineRuns)
-{
-  //Underlined character runs for markup-processor
-  const Vector<UnderlinedCharacterRun>& underlinedCharacterRuns = mModel->mLogicalModel->mUnderlinedCharacterRuns;
-  const Vector<GlyphIndex>&             charactersToGlyph       = mModel->mVisualModel->mCharactersToGlyph;
-  const Vector<Length>&                 glyphsPerCharacter      = mModel->mVisualModel->mGlyphsPerCharacter;
-
-  if(shouldClearPreUnderlineRuns)
-  {
-    mModel->mVisualModel->mUnderlineRuns.Clear();
-  }
-
-  for(Vector<UnderlinedCharacterRun>::ConstIterator it = underlinedCharacterRuns.Begin(), endIt = underlinedCharacterRuns.End(); it != endIt; ++it)
-  {
-    CharacterIndex characterIndex     = it->characterRun.characterIndex;
-    Length         numberOfCharacters = it->characterRun.numberOfCharacters;
-
-    if(numberOfCharacters == 0)
-    {
-      continue;
-    }
-
-    // Create one run for all glyphs of all run's characters that has same properties
-    // This enhance performance and reduce the needed memory to store glyphs-runs
-    UnderlinedGlyphRun underlineGlyphRun;
-    underlineGlyphRun.glyphRun.glyphIndex     = charactersToGlyph[characterIndex];
-    underlineGlyphRun.glyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex];
-    //Copy properties (attributes)
-    underlineGlyphRun.properties = it->properties;
-
-    for(Length index = 1u; index < numberOfCharacters; index++)
-    {
-      underlineGlyphRun.glyphRun.numberOfGlyphs += glyphsPerCharacter[characterIndex + index];
-    }
-
-    mModel->mVisualModel->mUnderlineRuns.PushBack(underlineGlyphRun);
-  }
-}
-
-void Controller::Impl::CopyStrikethroughFromLogicalToVisualModels()
-{
-  //Strikethrough character runs from markup-processor
-  const Vector<StrikethroughCharacterRun>& strikethroughCharacterRuns = mModel->mLogicalModel->mStrikethroughCharacterRuns;
-  const Vector<GlyphIndex>&                charactersToGlyph          = mModel->mVisualModel->mCharactersToGlyph;
-  const Vector<Length>&                    glyphsPerCharacter         = mModel->mVisualModel->mGlyphsPerCharacter;
-
-  mModel->mVisualModel->mStrikethroughRuns.Clear();
-
-  for(Vector<StrikethroughCharacterRun>::ConstIterator it = strikethroughCharacterRuns.Begin(), endIt = strikethroughCharacterRuns.End(); it != endIt; ++it)
-  {
-    CharacterIndex characterIndex     = it->characterRun.characterIndex;
-    Length         numberOfCharacters = it->characterRun.numberOfCharacters;
-
-    if(numberOfCharacters == 0)
-    {
-      continue;
-    }
-
-    StrikethroughGlyphRun strikethroughGlyphRun;
-    strikethroughGlyphRun.properties              = it->properties;
-    strikethroughGlyphRun.glyphRun.glyphIndex     = charactersToGlyph[characterIndex];
-    strikethroughGlyphRun.glyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex];
-
-    for(Length index = 1u; index < numberOfCharacters; index++)
-    {
-      strikethroughGlyphRun.glyphRun.numberOfGlyphs += glyphsPerCharacter[characterIndex + index];
-    }
-
-    mModel->mVisualModel->mStrikethroughRuns.PushBack(strikethroughGlyphRun);
-  }
-}
-
-void Controller::Impl::SetAutoScrollEnabled(bool enable)
-{
-  if(mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX)
-  {
-    mOperationsPending = static_cast<OperationsMask>(mOperationsPending |
-                                                     LAYOUT |
-                                                     ALIGN |
-                                                     UPDATE_LAYOUT_SIZE |
-                                                     REORDER);
-
-    if(enable)
-    {
-      DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled for SINGLE_LINE_BOX\n");
-      mOperationsPending = static_cast<OperationsMask>(mOperationsPending | UPDATE_DIRECTION);
-    }
-    else
-    {
-      DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled Disabling autoscroll\n");
-    }
-
-    mIsAutoScrollEnabled = enable;
-    RequestRelayout();
-  }
-  else
-  {
-    DALI_LOG_WARNING("Attempted AutoScrolling on a non SINGLE_LINE_BOX, request ignored\n");
-    mIsAutoScrollEnabled = false;
-  }
-}
-
-void Controller::Impl::SetEnableCursorBlink(bool enable)
-{
-  DALI_ASSERT_DEBUG(NULL != mEventData && "TextInput disabled");
-
-  if(mEventData)
-  {
-    mEventData->mCursorBlinkEnabled = enable;
-
-    if(!enable && mEventData->mDecorator)
-    {
-      mEventData->mDecorator->StopCursorBlink();
-    }
-  }
-}
-
-void Controller::Impl::SetMultiLineEnabled(bool enable)
-{
-  const Layout::Engine::Type layout = enable ? Layout::Engine::MULTI_LINE_BOX : Layout::Engine::SINGLE_LINE_BOX;
-
-  if(layout != mLayoutEngine.GetLayout())
-  {
-    // Set the layout type.
-    mLayoutEngine.SetLayout(layout);
-
-    // Set the flags to redo the layout operations
-    const OperationsMask layoutOperations = static_cast<OperationsMask>(LAYOUT |
-                                                                        UPDATE_LAYOUT_SIZE |
-                                                                        ALIGN |
-                                                                        REORDER);
-
-    mTextUpdateInfo.mFullRelayoutNeeded = true;
-    mOperationsPending                  = static_cast<OperationsMask>(mOperationsPending | layoutOperations);
-
-    // Need to recalculate natural size
-    mRecalculateNaturalSize = true;
-
-    RequestRelayout();
-  }
-}
-
-void Controller::Impl::SetHorizontalAlignment(Text::HorizontalAlignment::Type alignment)
-{
-  if(alignment != mModel->mHorizontalAlignment)
-  {
-    // Set the alignment.
-    mModel->mHorizontalAlignment = alignment;
-
-    // Set the flag to redo the alignment operation.
-    mOperationsPending = static_cast<OperationsMask>(mOperationsPending | ALIGN);
-
-    if(mEventData)
-    {
-      mEventData->mUpdateAlignment = true;
-
-      // Update the cursor if it's in editing mode
-      if(EventData::IsEditingState(mEventData->mState))
-      {
-        ChangeState(EventData::EDITING);
-        mEventData->mUpdateCursorPosition = true;
-      }
-    }
-
-    RequestRelayout();
-  }
-}
-
-void Controller::Impl::SetVerticalAlignment(VerticalAlignment::Type alignment)
-{
-  if(alignment != mModel->mVerticalAlignment)
-  {
-    // Set the alignment.
-    mModel->mVerticalAlignment = alignment;
-    mOperationsPending         = static_cast<OperationsMask>(mOperationsPending | ALIGN);
-    RequestRelayout();
-  }
-}
-
-void Controller::Impl::SetLineWrapMode(Text::LineWrap::Mode lineWrapMode)
-{
-  if(lineWrapMode != mModel->mLineWrapMode)
-  {
-    // Update Text layout for applying wrap mode
-    mOperationsPending = static_cast<OperationsMask>(mOperationsPending |
-                                                     ALIGN |
-                                                     LAYOUT |
-                                                     UPDATE_LAYOUT_SIZE |
-                                                     REORDER);
-
-    if((mModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) || (lineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) ||
-       (mModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::MIXED) || (lineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::MIXED)) // hyphen is treated as line break
-    {
-      mOperationsPending = static_cast<OperationsMask>(mOperationsPending | GET_LINE_BREAKS);
-    }
-
-    // Set the text wrap mode.
-    mModel->mLineWrapMode = lineWrapMode;
-
-    mTextUpdateInfo.mCharacterIndex             = 0u;
-    mTextUpdateInfo.mNumberOfCharactersToRemove = mTextUpdateInfo.mPreviousNumberOfCharacters;
-    mTextUpdateInfo.mNumberOfCharactersToAdd    = mModel->mLogicalModel->mText.Count();
-
-    // Request relayout
-    RequestRelayout();
-  }
-}
-
-void Controller::Impl::SetDefaultColor(const Vector4& color)
-{
-  mTextColor = color;
-
-  if(!IsShowingPlaceholderText())
-  {
-    mModel->mVisualModel->SetTextColor(color);
-    mModel->mLogicalModel->mColorRuns.Clear();
-    mOperationsPending = static_cast<OperationsMask>(mOperationsPending | COLOR);
-    RequestRelayout();
-  }
-}
-
-void Controller::Impl::ClearFontData()
-{
-  if(mFontDefaults)
-  {
-    mFontDefaults->mFontId = 0u; // Remove old font ID
-  }
-
-  // Set flags to update the model.
-  mTextUpdateInfo.mCharacterIndex             = 0u;
-  mTextUpdateInfo.mNumberOfCharactersToRemove = mTextUpdateInfo.mPreviousNumberOfCharacters;
-  mTextUpdateInfo.mNumberOfCharactersToAdd    = mModel->mLogicalModel->mText.Count();
-
-  mTextUpdateInfo.mClearAll           = true;
-  mTextUpdateInfo.mFullRelayoutNeeded = true;
-  mRecalculateNaturalSize             = true;
-
-  mOperationsPending = static_cast<OperationsMask>(mOperationsPending |
-                                                   VALIDATE_FONTS |
-                                                   SHAPE_TEXT |
-                                                   BIDI_INFO |
-                                                   GET_GLYPH_METRICS |
-                                                   LAYOUT |
-                                                   UPDATE_LAYOUT_SIZE |
-                                                   REORDER |
-                                                   ALIGN);
-}
-
-void Controller::Impl::ClearStyleData()
-{
-  mModel->mLogicalModel->mColorRuns.Clear();
-  mModel->mLogicalModel->ClearFontDescriptionRuns();
-  mModel->mLogicalModel->ClearStrikethroughRuns();
-}
-
-void Controller::Impl::ResetScrollPosition()
-{
-  if(mEventData)
-  {
-    // Reset the scroll position.
-    mModel->mScrollPosition                = Vector2::ZERO;
-    mEventData->mScrollAfterUpdatePosition = true;
-  }
-}
-
-} // namespace Dali::Toolkit::Text