/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 * 
 *************************************************************/



#include "precompiled_sdext.hxx"

#include "PresenterTextView.hxx"
#include "PresenterCanvasHelper.hxx"
#include "PresenterGeometryHelper.hxx"
#include "PresenterTimer.hxx"

#include <cmath>

#include <com/sun/star/accessibility/AccessibleTextType.hpp>
#include <com/sun/star/container/XEnumerationAccess.hpp>
#include <com/sun/star/i18n/CharType.hpp>
#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
#include <com/sun/star/i18n/CTLScriptType.hpp>
#include <com/sun/star/i18n/ScriptDirection.hpp>
#include <com/sun/star/i18n/WordType.hpp>
#include <com/sun/star/rendering/CompositeOperation.hpp>
#include <com/sun/star/rendering/TextDirection.hpp>
#include <com/sun/star/text/WritingMode2.hpp>
#include <boost/bind.hpp>

using namespace ::com::sun::star;
using namespace ::com::sun::star::accessibility;
using namespace ::com::sun::star::uno;

#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))

const static sal_Int64 CaretBlinkIntervall = 500 * 1000 * 1000;

//#define SHOW_CHARACTER_BOXES

namespace {
    sal_Int32 Signum (const sal_Int32 nValue)
    {
        if (nValue < 0)
            return -1;
        else if (nValue > 0)
            return +1;
        else
            return 0;
    }
}

namespace sdext { namespace presenter {


//===== PresenterTextView =====================================================

PresenterTextView::PresenterTextView (
    const Reference<XComponentContext>& rxContext,
    const Reference<rendering::XCanvas>& rxCanvas,
    const ::boost::function<void(const ::css::awt::Rectangle&)>& rInvalidator)
    : mxCanvas(rxCanvas),
      mbDoOuput(true),
      mxBreakIterator(),
      mxScriptTypeDetector(),
      maLocation(0,0),
      maSize(0,0),
      mpFont(),
      maParagraphs(),
      mpCaret(new PresenterTextCaret(
          ::boost::bind(&PresenterTextView::GetCaretBounds, this, _1, _2),
          rInvalidator)),
      mnLeftOffset(0),
      mnTopOffset(0),
      maInvalidator(rInvalidator),
      mbIsFormatPending(false),
      mnCharacterCount(-1),
      maTextChangeBroadcaster()
{
    Reference<lang::XMultiComponentFactory> xFactory (
        rxContext->getServiceManager(), UNO_QUERY);
    if ( ! xFactory.is())
        return;

    // Create the break iterator that we use to break text into lines.
    mxBreakIterator = Reference<i18n::XBreakIterator>(
        xFactory->createInstanceWithContext(
            A2S("com.sun.star.i18n.BreakIterator"),
            rxContext),
        UNO_QUERY_THROW);

    // Create the script type detector that is used to split paragraphs into
    // portions of the same text direction.
    mxScriptTypeDetector = Reference<i18n::XScriptTypeDetector>(
        xFactory->createInstanceWithContext(
            A2S("com.sun.star.i18n.ScriptTypeDetector"),
            rxContext),
        UNO_QUERY_THROW);
}




PresenterTextView::PresenterTextView (
    const Reference<XComponentContext>& rxContext,
    const Reference<rendering::XCanvas>& rxCanvas)
    : mxCanvas(rxCanvas),
      mbDoOuput(false),
      mxBreakIterator(),
      mxScriptTypeDetector(),
      maLocation(0,0),
      maSize(0,0),
      mpFont(),
      maParagraphs(),
      mpCaret(new PresenterTextCaret(
          ::boost::bind(&PresenterTextView::GetCaretBounds, this, _1, _2),
          ::boost::function<void(const css::awt::Rectangle&)>())),
      mnLeftOffset(0),
      mnTopOffset(0),
      maInvalidator(),
      mbIsFormatPending(false),
      mnCharacterCount(-1),
      maTextChangeBroadcaster()
{
    Reference<lang::XMultiComponentFactory> xFactory (
        rxContext->getServiceManager(), UNO_QUERY);
    if ( ! xFactory.is())
        return;

    // Create the break iterator that we use to break text into lines.
    mxBreakIterator = Reference<i18n::XBreakIterator>(
        xFactory->createInstanceWithContext(
            A2S("com.sun.star.i18n.BreakIterator"),
            rxContext),
        UNO_QUERY_THROW);

    // Create the script type detector that is used to split paragraphs into
    // portions of the same text direction.
    mxScriptTypeDetector = Reference<i18n::XScriptTypeDetector>(
        xFactory->createInstanceWithContext(
            A2S("com.sun.star.i18n.ScriptTypeDetector"),
            rxContext),
        UNO_QUERY_THROW);
}




void PresenterTextView::SetText (const Reference<text::XText>& rxText)
{
    maParagraphs.clear();
    mnCharacterCount = -1;

    Reference<container::XEnumerationAccess> xParagraphAccess (rxText, UNO_QUERY);
    if ( ! xParagraphAccess.is())
        return;
    
    Reference<container::XEnumeration> xParagraphs (
        xParagraphAccess->createEnumeration() , UNO_QUERY);
    if ( ! xParagraphs.is())
        return;

    if ( ! mpFont || ! mpFont->PrepareFont(mxCanvas))
        return;

    sal_Int32 nCharacterCount (0);
    while (xParagraphs->hasMoreElements())
    {
        SharedPresenterTextParagraph pParagraph (new PresenterTextParagraph(
            maParagraphs.size(),
            mxBreakIterator,
            mxScriptTypeDetector,
            Reference<text::XTextRange>(xParagraphs->nextElement(), UNO_QUERY),
            mpCaret));
        pParagraph->SetupCellArray(mpFont);
        pParagraph->SetCharacterOffset(nCharacterCount);
        nCharacterCount += pParagraph->GetCharacterCount();
        maParagraphs.push_back(pParagraph);
    }

    if (mpCaret)
        mpCaret->HideCaret();

    RequestFormat();
}




void PresenterTextView::SetText (const ::rtl::OUString& rsText)
{
    maParagraphs.clear();
    mnCharacterCount = -1;

    if ( ! mpFont || ! mpFont->PrepareFont(mxCanvas))
        return;

    sal_Int32 nCharacterCount (0);

    SharedPresenterTextParagraph pParagraph (new PresenterTextParagraph(
        0,
        mxBreakIterator,
        mxScriptTypeDetector,
        rsText,
        mpCaret));
    pParagraph->SetupCellArray(mpFont);
    pParagraph->SetCharacterOffset(nCharacterCount);
    nCharacterCount += pParagraph->GetCharacterCount();
    maParagraphs.push_back(pParagraph);

    if (mpCaret)
        mpCaret->HideCaret();

    RequestFormat();
}




void PresenterTextView::SetTextChangeBroadcaster (
    const ::boost::function<void(void)>& rBroadcaster)
{
    maTextChangeBroadcaster = rBroadcaster;
}




void PresenterTextView::SetLocation (const css::geometry::RealPoint2D& rLocation)
{
    maLocation = rLocation;
    
    for (::std::vector<SharedPresenterTextParagraph>::iterator
             iParagraph(maParagraphs.begin()),
             iEnd(maParagraphs.end());
         iParagraph!=iEnd;
         ++iParagraph)
    {
        (*iParagraph)->SetOrigin(
            maLocation.X - mnLeftOffset,
            maLocation.Y - mnTopOffset);
    }
}




void PresenterTextView::SetSize (const css::geometry::RealSize2D& rSize)
{
    maSize = rSize;
    RequestFormat();
}




double PresenterTextView::GetTotalTextHeight (void)
{
    double nTotalHeight (0);

    if (mbIsFormatPending)
    {
        if ( ! mpFont->PrepareFont(mxCanvas))
            return 0;
        Format();
    }

    for (::std::vector<SharedPresenterTextParagraph>::iterator
             iParagraph(maParagraphs.begin()),
             iEnd(maParagraphs.end());
         iParagraph!=iEnd;
         ++iParagraph)
    {
        nTotalHeight += (*iParagraph)->GetTotalTextHeight();
    }

    return nTotalHeight;
}




void PresenterTextView::SetFont (const PresenterTheme::SharedFontDescriptor& rpFont)
{
    mpFont = rpFont;
    RequestFormat();
}




void PresenterTextView::SetOffset(
    const double nLeft,
    const double nTop)
{
    mnLeftOffset = nLeft;
    mnTopOffset = nTop;

    // Trigger an update of the text origin stored at the individual paragraphs.
    SetLocation(maLocation);
}



void PresenterTextView::MoveCaret (
    const sal_Int32 nDistance,
    const sal_Int16 nTextType)
{
    if ( ! mpCaret)
        return;

    // When the caret has not been visible yet then move it to the beginning
    // of the text.
    if (mpCaret->GetParagraphIndex() < 0)
    {
        mpCaret->SetPosition(0,0);
        return;
    }

    sal_Int32 nParagraphIndex (mpCaret->GetParagraphIndex());
    sal_Int32 nCharacterIndex (mpCaret->GetCharacterIndex());
    switch (nTextType)
    {
        default:
        case AccessibleTextType::CHARACTER:
            nCharacterIndex += nDistance;
            break;
                    
        case AccessibleTextType::WORD:
        {
            sal_Int32 nRemainingDistance (nDistance);
            while (nRemainingDistance != 0)
            {
                SharedPresenterTextParagraph pParagraph (GetParagraph(nParagraphIndex));
                if (pParagraph)
                {
                    const sal_Int32 nDelta (Signum(nDistance));
                    nCharacterIndex = pParagraph->GetWordBoundary(nCharacterIndex, nDelta);
                    if (nCharacterIndex < 0)
                    {
                        // Go to previous or next paragraph.
                        nParagraphIndex += nDelta;
                        if (nParagraphIndex < 0)
                        {
                            nParagraphIndex = 0;
                            nCharacterIndex = 0;
                            nRemainingDistance = 0;
                        }
                        else if (sal_uInt32(nParagraphIndex) >= maParagraphs.size())
                        {
                            nParagraphIndex = maParagraphs.size()-1;
                            pParagraph = GetParagraph(nParagraphIndex);
                            if (pParagraph)
                                nCharacterIndex = pParagraph->GetCharacterCount();
                            nRemainingDistance = 0;
                        }
                        else
                        {
                            nRemainingDistance -= nDelta;
                            
                            // Move caret one character to the end of
                            // the previous or the start of the next paragraph.
                            pParagraph = GetParagraph(nParagraphIndex);
                            if (pParagraph)
                            {
                                if (nDistance<0)
                                    nCharacterIndex = pParagraph->GetCharacterCount();
                                else
                                    nCharacterIndex = 0;
                            }
                        }
                    }
                    else
                        nRemainingDistance -= nDelta;
                }
                else
                    break;
            }
            break;
        }
    }

    // Move the caret to the new position.
    mpCaret->SetPosition(nParagraphIndex, nCharacterIndex);
}




void PresenterTextView::Paint (
    const css::awt::Rectangle& rUpdateBox)
{
    if ( ! mbDoOuput)
        return;
    if ( ! mxCanvas.is())
        return;
    if ( ! mpFont->PrepareFont(mxCanvas))
        return;

    if (mbIsFormatPending)
        Format();

    // Setup the clipping rectangle.  Horizontally we make it a little
    // larger to allow characters (and the caret) to stick out of their
    // bounding boxes.  This can happen on some characters (like the
    // uppercase J) for typographical reasons.
    const sal_Int32 nAdditionalLeftBorder (10);
    const sal_Int32 nAdditionalRightBorder (5);
    double nX (maLocation.X - mnLeftOffset);
    double nY (maLocation.Y - mnTopOffset);
    const sal_Int32 nClipLeft (::std::max(
        PresenterGeometryHelper::Round(maLocation.X)-nAdditionalLeftBorder, rUpdateBox.X));
    const sal_Int32 nClipTop (::std::max(
        PresenterGeometryHelper::Round(maLocation.Y), rUpdateBox.Y));
    const sal_Int32 nClipRight (::std::min(
        PresenterGeometryHelper::Round(maLocation.X+maSize.Width)+nAdditionalRightBorder, rUpdateBox.X+rUpdateBox.Width));
    const sal_Int32 nClipBottom (::std::min(
        PresenterGeometryHelper::Round(maLocation.Y+maSize.Height), rUpdateBox.Y+rUpdateBox.Height));
    if (nClipLeft>=nClipRight || nClipTop>=nClipBottom)
        return;

    const awt::Rectangle aClipBox(
        nClipLeft,
        nClipTop,
        nClipRight - nClipLeft,
        nClipBottom - nClipTop);
    Reference<rendering::XPolyPolygon2D> xClipPolygon (
        PresenterGeometryHelper::CreatePolygon(aClipBox, mxCanvas->getDevice()));

    const rendering::ViewState aViewState(
        geometry::AffineMatrix2D(1,0,0, 0,1,0),
        xClipPolygon);

    rendering::RenderState aRenderState (
        geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
        NULL,
        Sequence<double>(4),
        rendering::CompositeOperation::SOURCE);
    PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor);

    for (::std::vector<SharedPresenterTextParagraph>::const_iterator
             iParagraph(maParagraphs.begin()),
             iEnd(maParagraphs.end());
         iParagraph!=iEnd;
         ++iParagraph)
    {
        (*iParagraph)->Paint(
            mxCanvas,
            maSize,
            mpFont,
            aViewState,
            aRenderState,
            mnTopOffset,
            nClipTop,
            nClipBottom);
    }

    aRenderState.AffineTransform.m02 = 0;
    aRenderState.AffineTransform.m12 = 0;

#ifdef SHOW_CHARACTER_BOXES
    PresenterCanvasHelper::SetDeviceColor(aRenderState, 0x00808080);
    for (sal_Int32 nParagraphIndex(0), nParagraphCount(GetParagraphCount());
         nParagraphIndex<nParagraphCount;
         ++nParagraphIndex)
    {
        const SharedPresenterTextParagraph pParagraph (GetParagraph(nParagraphIndex));
        if ( ! pParagraph)
            continue;
        for (sal_Int32 nCharacterIndex(0),nCharacterCount(pParagraph->GetCharacterCount());
             nCharacterIndex<nCharacterCount; ++nCharacterIndex)
        {
            const awt::Rectangle aBox (pParagraph->GetCharacterBounds(nCharacterIndex, false));
            mxCanvas->drawPolyPolygon (
                PresenterGeometryHelper::CreatePolygon(
                    aBox,
                    mxCanvas->getDevice()),
                aViewState,
                aRenderState);
        }
    }
    PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor);
#endif

    if (mpCaret && mpCaret->IsVisible())
    {
        mxCanvas->fillPolyPolygon (
            PresenterGeometryHelper::CreatePolygon(
                mpCaret->GetBounds(),
                mxCanvas->getDevice()),
            aViewState,
            aRenderState);
    }
}




SharedPresenterTextCaret PresenterTextView::GetCaret (void) const
{
    return mpCaret;
}




sal_Int32 PresenterTextView::GetCharacterOffset (const sal_Int32 nParagraphIndex) const
{
    sal_Int32 nCharacterOffset (0);
    for (sal_Int32 nIndex=0; nIndex<nParagraphIndex; ++nIndex)
        nCharacterOffset += maParagraphs[nIndex]->GetCharacterCount();
    return nCharacterOffset;
}




awt::Rectangle PresenterTextView::GetCaretBounds (
    sal_Int32 nParagraphIndex,
    const sal_Int32 nCharacterIndex) const
{
    SharedPresenterTextParagraph pParagraph (GetParagraph(nParagraphIndex));

    if (pParagraph)
        return pParagraph->GetCharacterBounds(nCharacterIndex, true);
    else
        return awt::Rectangle(0,0,0,0);
}




//----- private ---------------------------------------------------------------

void PresenterTextView::RequestFormat (void)
{
    mbIsFormatPending = true;
}




void PresenterTextView::Format (void)
{
    mbIsFormatPending = false;

    double nY (0);
    for (::std::vector<SharedPresenterTextParagraph>::const_iterator
             iParagraph(maParagraphs.begin()),
             iEnd(maParagraphs.end());
         iParagraph!=iEnd;
         ++iParagraph)
    {
        (*iParagraph)->Format(nY, maSize.Width, mpFont);
        nY += (*iParagraph)->GetTotalTextHeight();
    }

    if (maTextChangeBroadcaster)
        maTextChangeBroadcaster();
}




sal_Int32 PresenterTextView::GetParagraphCount (void) const
{
    return maParagraphs.size();
}




SharedPresenterTextParagraph PresenterTextView::GetParagraph (
    const sal_Int32 nParagraphIndex) const
{
    if (nParagraphIndex < 0)
        return SharedPresenterTextParagraph();
    else if (nParagraphIndex>=sal_Int32(maParagraphs.size()))
        return SharedPresenterTextParagraph();
    else
        return maParagraphs[nParagraphIndex];
}




//===== PresenterTextParagraph ================================================

PresenterTextParagraph::PresenterTextParagraph (
    const sal_Int32 nParagraphIndex,
    const Reference<i18n::XBreakIterator>& rxBreakIterator,
    const Reference<i18n::XScriptTypeDetector>& rxScriptTypeDetector,
    const Reference<text::XTextRange>& rxTextRange,
    const SharedPresenterTextCaret& rpCaret)
    : msParagraphText(),
      mnParagraphIndex(nParagraphIndex),
      mpCaret(rpCaret),
      mxBreakIterator(rxBreakIterator),
      mxScriptTypeDetector(rxScriptTypeDetector),
      maLines(),
      mnVerticalOffset(0),
      mnXOrigin(0),
      mnYOrigin(0),
      mnWidth(0),
      mnAscent(0),
      mnDescent(0),
      mnLineHeight(-1),
      meAdjust(style::ParagraphAdjust_LEFT),
      mnWritingMode (text::WritingMode2::LR_TB),
      mnCharacterOffset(0),
      maCells()
{
    if (rxTextRange.is())
    {
        Reference<beans::XPropertySet> xProperties (rxTextRange, UNO_QUERY);
        lang::Locale aLocale;
        try
        {
            xProperties->getPropertyValue(A2S("CharLocale")) >>= aLocale;
        }
        catch(beans::UnknownPropertyException&)
        {
            // Ignore the exception.  Use the default value.
        }
        try
        {
            xProperties->getPropertyValue(A2S("ParaAdjust")) >>= meAdjust;
        }
        catch(beans::UnknownPropertyException&)
        {
            // Ignore the exception.  Use the default value.
        }
        try
        {
            xProperties->getPropertyValue(A2S("WritingMode")) >>= mnWritingMode;
        }
        catch(beans::UnknownPropertyException&)
        {
            // Ignore the exception.  Use the default value.
        }

        msParagraphText = rxTextRange->getString();
    }
}




PresenterTextParagraph::PresenterTextParagraph (
    const sal_Int32 nParagraphIndex,
    const Reference<i18n::XBreakIterator>& rxBreakIterator,
    const Reference<i18n::XScriptTypeDetector>& rxScriptTypeDetector,
    const ::rtl::OUString& rsText,
    const SharedPresenterTextCaret& rpCaret)
    : msParagraphText(rsText),
      mnParagraphIndex(nParagraphIndex),
      mpCaret(rpCaret),
      mxBreakIterator(rxBreakIterator),
      mxScriptTypeDetector(rxScriptTypeDetector),
      maLines(),
      mnVerticalOffset(0),
      mnXOrigin(0),
      mnYOrigin(0),
      mnWidth(0),
      mnAscent(0),
      mnDescent(0),
      mnLineHeight(-1),
      meAdjust(style::ParagraphAdjust_LEFT),
      mnWritingMode (text::WritingMode2::LR_TB),
      mnCharacterOffset(0),
      maCells()
{
}




void PresenterTextParagraph::Paint (
    const Reference<rendering::XCanvas>& rxCanvas,
    const geometry::RealSize2D& rSize,
    const PresenterTheme::SharedFontDescriptor& rpFont,
    const rendering::ViewState& rViewState,
    rendering::RenderState& rRenderState,
    const double nTopOffset,
    const double nClipTop,
    const double nClipBottom)
{
    if (mnLineHeight <= 0)
        return;

    sal_Int8 nTextDirection (GetTextDirection());

    const double nSavedM12 (rRenderState.AffineTransform.m12);

    if ( ! IsTextReferencePointLeft())
        rRenderState.AffineTransform.m02 += rSize.Width;


#ifdef SHOW_CHARACTER_BOXES
    for (sal_Int32 nIndex=0,nCount=maLines.size();
         nIndex<nCount;
         ++nIndex)
    {
        Line& rLine (maLines[nIndex]);
        rLine.ProvideLayoutedLine(msParagraphText, rpFont, nTextDirection);
    }
#endif

    for (sal_Int32 nIndex=0,nCount=maLines.size();
         nIndex<nCount;
         ++nIndex, rRenderState.AffineTransform.m12 += mnLineHeight)
    {
        Line& rLine (maLines[nIndex]);

        // Paint only visible lines.
        const double nLineTop = rLine.mnBaseLine - mnAscent - nTopOffset;
        if (nLineTop + mnLineHeight< nClipTop)
            continue;
        else if (nLineTop > nClipBottom)
            break;
        rLine.ProvideLayoutedLine(msParagraphText, rpFont, nTextDirection);

        rRenderState.AffineTransform.m12 = nSavedM12 + rLine.mnBaseLine;

        rxCanvas->drawTextLayout (
            rLine.mxLayoutedLine,
            rViewState,
            rRenderState);
    }
    rRenderState.AffineTransform.m12 = nSavedM12;

    if ( ! IsTextReferencePointLeft())
        rRenderState.AffineTransform.m02 -= rSize.Width;
}




void PresenterTextParagraph::Format (
    const double nY,
    const double nWidth,
    const PresenterTheme::SharedFontDescriptor& rpFont)
{
    // Make sure that the text view is in a valid and sane state.
    if ( ! mxBreakIterator.is() || ! mxScriptTypeDetector.is())
        return;
    if (nWidth<=0)
        return;
    if ( ! rpFont || ! rpFont->mxFont.is())
        return;

    sal_Int32 nPosition (0);

    mnWidth = nWidth;
    maLines.clear();
    mnLineHeight = 0;
    mnAscent = 0;
    mnDescent = 0;
    mnVerticalOffset = nY;
    maWordBoundaries.clear();
    maWordBoundaries.push_back(0);
    
    const rendering::FontMetrics aMetrics (rpFont->mxFont->getFontMetrics());
    mnAscent = aMetrics.Ascent;
    mnDescent = aMetrics.Descent;
    mnLineHeight = aMetrics.Ascent + aMetrics.Descent + aMetrics.ExternalLeading;
    nPosition = 0;
    i18n::Boundary aCurrentLine(0,0);
    while (true)
    {
        const i18n::Boundary aWordBoundary = mxBreakIterator->nextWord(
            msParagraphText,
            nPosition,
            lang::Locale(),
            i18n::WordType::ANYWORD_IGNOREWHITESPACES);
        AddWord(nWidth, aCurrentLine, aWordBoundary.startPos, rpFont);

        // Remember the new word boundary for caret travelling by words.
        // Prevent duplicates.
        if (aWordBoundary.startPos > maWordBoundaries.back())
            maWordBoundaries.push_back(aWordBoundary.startPos);

        if (aWordBoundary.endPos>aWordBoundary.startPos)
            AddWord(nWidth, aCurrentLine, aWordBoundary.endPos, rpFont);
            
        if (aWordBoundary.startPos<0 || aWordBoundary.endPos<0)
            break;
        if (nPosition >= aWordBoundary.endPos)
            break;
        nPosition = aWordBoundary.endPos;
    }

    if (aCurrentLine.endPos>aCurrentLine.startPos)
        AddLine(aCurrentLine);

}




sal_Int32 PresenterTextParagraph::GetWordBoundary(
    const sal_Int32 nLocalCharacterIndex,
    const sal_Int32 nDistance)
{
    OSL_ASSERT(nDistance==-1 || nDistance==+1);

    if (nLocalCharacterIndex < 0)
    {
        // The caller asked for the start or end position of the paragraph.
        if (nDistance < 0)
            return 0;
        else
            return GetCharacterCount();
    }
    
    sal_Int32 nIndex (0);
    for (sal_Int32 nCount (maWordBoundaries.size()); nIndex<nCount; ++nIndex)
    {
        if (maWordBoundaries[nIndex] >= nLocalCharacterIndex)
        {
            // When inside the word (not at its start or end) then
            // first move to the start or end before going the previous or
            // next word.
            if (maWordBoundaries[nIndex] > nLocalCharacterIndex)
                if (nDistance > 0)
                    --nIndex;
            break;
        }
    }

    nIndex += nDistance;

    if (nIndex < 0)
        return -1;
    else if (sal_uInt32(nIndex)>=maWordBoundaries.size())
        return -1;
    else
        return maWordBoundaries[nIndex];
}




sal_Int32 PresenterTextParagraph::GetCaretPosition (void) const
{
    if (mpCaret && mpCaret->GetParagraphIndex()==mnParagraphIndex)
        return mpCaret->GetCharacterIndex();
    else
        return -1;
}




void PresenterTextParagraph::SetCaretPosition (const sal_Int32 nPosition) const
{
    if (mpCaret && mpCaret->GetParagraphIndex()==mnParagraphIndex)
        return mpCaret->SetPosition(mnParagraphIndex, nPosition);
}




void PresenterTextParagraph::SetOrigin (const double nXOrigin, const double nYOrigin)
{
    mnXOrigin = nXOrigin;
    mnYOrigin = nYOrigin;
}




awt::Point PresenterTextParagraph::GetRelativeLocation (void) const
{
    return awt::Point(
        sal_Int32(mnXOrigin),
        sal_Int32(mnYOrigin + mnVerticalOffset));
}




awt::Size PresenterTextParagraph::GetSize (void)
{
    return awt::Size(
        sal_Int32(mnWidth),
        sal_Int32(GetTotalTextHeight()));
}




void PresenterTextParagraph::AddWord (
    const double nWidth,
    i18n::Boundary& rCurrentLine,
    const sal_Int32 nWordBoundary,
    const PresenterTheme::SharedFontDescriptor& rpFont)
{
    sal_Int32 nLineStart (0);
    sal_Int32 nLineEnd (0);
    if ( ! maLines.empty())
    {
        nLineStart = rCurrentLine.startPos;
        nLineEnd = rCurrentLine.endPos;
    }
    
    const ::rtl::OUString sLineCandidate (
        msParagraphText.copy(nLineStart, nWordBoundary-nLineStart));

    css::geometry::RealRectangle2D aLineBox (
        PresenterCanvasHelper::GetTextBoundingBox (
            rpFont->mxFont,
            sLineCandidate,
            mnWritingMode));
    const double nLineWidth (aLineBox.X2 - aLineBox.X1);

    if (nLineWidth >= nWidth)
    {
        // Add new line with a single word (so far).
        AddLine(rCurrentLine);
    }
    rCurrentLine.endPos = nWordBoundary;
}




void PresenterTextParagraph::AddLine (
    i18n::Boundary& rCurrentLine)
{
    Line aLine (rCurrentLine.startPos, rCurrentLine.endPos);

    // Find the start and end of the line with respect to cells.
    if (maLines.size() > 0)
    {
        aLine.mnLineStartCellIndex = maLines.back().mnLineEndCellIndex;
        aLine.mnBaseLine = maLines.back().mnBaseLine + mnLineHeight;
    }
    else
    {
        aLine.mnLineStartCellIndex = 0;
        aLine.mnBaseLine = mnVerticalOffset + mnAscent;
    }
    sal_Int32 nCellIndex (aLine.mnLineStartCellIndex);
    double nWidth (0);
    for ( ; nCellIndex<sal_Int32(maCells.size()); ++nCellIndex)
    {
        const Cell& rCell (maCells[nCellIndex]);
        if (rCell.mnCharacterIndex+rCell.mnCharacterCount > aLine.mnLineEndCharacterIndex)
            break;
        nWidth += rCell.mnCellWidth;
    }
    aLine.mnLineEndCellIndex = nCellIndex;
    aLine.mnWidth = nWidth;

    maLines.push_back(aLine);

    rCurrentLine.startPos = rCurrentLine.endPos;
}




sal_Int32 PresenterTextParagraph::GetParagraphIndex (void) const
{
    return mnParagraphIndex;
}




double PresenterTextParagraph::GetTotalTextHeight (void)
{
    return maLines.size() * mnLineHeight;
}




sal_Int32 PresenterTextParagraph::GetCharacterOffset (void) const
{
    return mnCharacterOffset;
}




void PresenterTextParagraph::SetCharacterOffset (const sal_Int32 nCharacterOffset)
{
    mnCharacterOffset = nCharacterOffset;
}




sal_Int32 PresenterTextParagraph::GetCharacterCount (void) const
{
    return msParagraphText.getLength();
}




sal_Unicode PresenterTextParagraph::GetCharacter (
    const sal_Int32 nGlobalCharacterIndex) const
{
    if (nGlobalCharacterIndex<mnCharacterOffset
        || nGlobalCharacterIndex>=mnCharacterOffset+msParagraphText.getLength())
    {
        return sal_Unicode();
    }
    else
    {
        return msParagraphText.getStr()[nGlobalCharacterIndex - mnCharacterOffset];
    }
}




::rtl::OUString PresenterTextParagraph::GetText (void) const
{
    return msParagraphText;
}




TextSegment PresenterTextParagraph::GetTextSegment (
    const sal_Int32 nOffset,
    const sal_Int32 nIndex,
    const sal_Int16 nTextType) const
{
    switch(nTextType)
    {
        case AccessibleTextType::PARAGRAPH:
            return TextSegment(
                msParagraphText,
                mnCharacterOffset,
                mnCharacterOffset+msParagraphText.getLength());

        case AccessibleTextType::SENTENCE:
            if (mxBreakIterator.is())
            {
                const sal_Int32 nStart (mxBreakIterator->beginOfSentence(
                    msParagraphText, nIndex-mnCharacterOffset, lang::Locale()));
                const sal_Int32 nEnd (mxBreakIterator->endOfSentence(
                    msParagraphText, nIndex-mnCharacterOffset, lang::Locale()));
                if (nStart < nEnd)
                    return TextSegment(
                        msParagraphText.copy(nStart, nEnd-nStart),
                        nStart+mnCharacterOffset,
                        nEnd+mnCharacterOffset);
            }
            break;

        case AccessibleTextType::WORD:
            if (mxBreakIterator.is())
                return GetWordTextSegment(nOffset, nIndex);
            break;
                
        case AccessibleTextType::LINE:
        {
            for (::std::vector<Line>::const_iterator
                     iLine(maLines.begin()),
                     iEnd(maLines.end());
                 iLine!=iEnd;
                 ++iLine)
            {
                if (nIndex < iLine->mnLineEndCharacterIndex)
                {
                    return TextSegment(
                        msParagraphText.copy(
                            iLine->mnLineStartCharacterIndex,
                            iLine->mnLineEndCharacterIndex - iLine->mnLineStartCharacterIndex),
                        iLine->mnLineStartCharacterIndex,
                        iLine->mnLineEndCharacterIndex);
                }
            }
        }
        break;

        // Handle GLYPH and ATTRIBUTE_RUN like CHARACTER because we can not
        // do better at the moment.
        case AccessibleTextType::CHARACTER:
        case AccessibleTextType::GLYPH:
        case AccessibleTextType::ATTRIBUTE_RUN:
            return CreateTextSegment(nIndex+nOffset, nIndex+nOffset+1);
    }

    return TextSegment(::rtl::OUString(), 0,0);
}




TextSegment PresenterTextParagraph::GetWordTextSegment (
    const sal_Int32 nOffset,
    const sal_Int32 nIndex) const
{
    sal_Int32 nCurrentOffset (nOffset);
    sal_Int32 nCurrentIndex (nIndex);

    i18n::Boundary aWordBoundary;
    if (nCurrentOffset == 0)
        aWordBoundary = mxBreakIterator->getWordBoundary(
            msParagraphText,
            nIndex,
            lang::Locale(),
            i18n::WordType::ANYWORD_IGNOREWHITESPACES,
            sal_True);
    else if (nCurrentOffset < 0)
    {
        while (nCurrentOffset<0 && nCurrentIndex>0)
        {
            aWordBoundary = mxBreakIterator->previousWord(
                msParagraphText,
                nCurrentIndex,
                lang::Locale(),
                i18n::WordType::ANYWORD_IGNOREWHITESPACES);
            nCurrentIndex = aWordBoundary.startPos;
            ++nCurrentOffset;
        }
    }
    else
    {
        while (nCurrentOffset>0 && nCurrentIndex<=GetCharacterCount())
        {
            aWordBoundary = mxBreakIterator->nextWord(
                msParagraphText,
                nCurrentIndex,
                lang::Locale(),
                i18n::WordType::ANYWORD_IGNOREWHITESPACES);
            nCurrentIndex = aWordBoundary.endPos;
            --nCurrentOffset;
        }
    }

    return CreateTextSegment(aWordBoundary.startPos, aWordBoundary.endPos);
}




TextSegment PresenterTextParagraph::CreateTextSegment (
    sal_Int32 nStartIndex,
    sal_Int32 nEndIndex) const
{
    if (nEndIndex <= nStartIndex)
        return TextSegment(
            ::rtl::OUString(),
            nStartIndex,
            nEndIndex);
    else
        return TextSegment(
            msParagraphText.copy(nStartIndex, nEndIndex-nStartIndex),
            nStartIndex,
            nEndIndex);
}




awt::Rectangle PresenterTextParagraph::GetCharacterBounds (
    sal_Int32 nGlobalCharacterIndex,
    const bool bCaretBox)
{
    // Find the line that contains the requested character and accumulate
    // the previous line heights.
    sal_Int32 nFirstCharacterIndex (0);
    sal_Int32 nEndCharacterIndex (0);
    double nX (mnXOrigin);
    double nY (mnYOrigin + mnVerticalOffset + mnAscent);
    const sal_Int8 nTextDirection (GetTextDirection());
    for (sal_Int32 nLineIndex=0,nLineCount=maLines.size();
         nLineIndex<nLineCount;
         ++nLineIndex, nFirstCharacterIndex=nEndCharacterIndex, nY+=mnLineHeight)
    {
        Line& rLine (maLines[nLineIndex]);
        // Skip lines before the indexed character.
        if (nGlobalCharacterIndex >= rLine.mnLineEndCharacterIndex)
            // When in the last line then allow the index past the last char.
            if (nLineIndex<nLineCount-1)
                continue;

        rLine.ProvideCellBoxes();

        const sal_Int32 nCellIndex (nGlobalCharacterIndex - rLine.mnLineStartCharacterIndex);

        // The cell bounding box is defined relative to the origin of
        // the current line.  Therefore we have to add the absolute
        // position of the line.
        geometry::RealRectangle2D rCellBox (rLine.maCellBoxes[
            ::std::min(nCellIndex, rLine.maCellBoxes.getLength()-1)]);

        double nLeft = nX + rCellBox.X1;
        double nRight = nX + rCellBox.X2;
        if (nTextDirection == rendering::TextDirection::WEAK_RIGHT_TO_LEFT)
        {
            const double nOldRight (nRight);
            nRight = rLine.mnWidth - nLeft;
            nLeft = rLine.mnWidth - nOldRight;
        }
        double nTop (nY + rCellBox.Y1);
        double nBottom (nY + rCellBox.Y2);
        if (bCaretBox)
        {
            nTop = nTop - rCellBox.Y1 - mnAscent;
            nBottom = nTop + mnLineHeight;
            if (nCellIndex >= rLine.maCellBoxes.getLength())
                nLeft = nRight-2;
            if (nLeft < nX)
                nLeft = nX;
            nRight = nLeft+2;
        }
        else
        {
            nTop = nTop - rCellBox.Y1 - mnAscent;
            nBottom = nTop + mnAscent + mnDescent;
        }
        const sal_Int32 nX1 = sal_Int32(floor(nLeft));
        const sal_Int32 nY1 = sal_Int32(floor(nTop));
        const sal_Int32 nX2 = sal_Int32(ceil(nRight));
        const sal_Int32 nY2 = sal_Int32(ceil(nBottom));

        return awt::Rectangle(nX1,nY1,nX2-nX1+1,nY2-nY1+1);
    }

    // We are still here.  That means that the given index lies past the
    // last character in the paragraph.
    // Return an empty box that lies past the last character.  Better than nothing.
    return awt::Rectangle(sal_Int32(nX+0.5), sal_Int32(nY+0.5), 0, 0);
}




sal_Int32 PresenterTextParagraph::GetIndexAtPoint (const awt::Point& rPoint) const
{
    (void)rPoint;
    return -1;
}




sal_Int8 PresenterTextParagraph::GetTextDirection (void) const
{
    // Find first portion that has a non-neutral text direction.
    sal_Int32 nPosition (0);
    sal_Int32 nTextLength (msParagraphText.getLength());
    while (nPosition < nTextLength)
    {
        const sal_Int16 nScriptDirection (
            mxScriptTypeDetector->getScriptDirection(
                msParagraphText, nPosition, i18n::ScriptDirection::NEUTRAL));
        switch (nScriptDirection)
        {
            case i18n::ScriptDirection::NEUTRAL:
                // continue looping.
                break;
            case i18n::ScriptDirection::LEFT_TO_RIGHT:
                return rendering::TextDirection::WEAK_LEFT_TO_RIGHT;

            case i18n::ScriptDirection::RIGHT_TO_LEFT:
                return rendering::TextDirection::WEAK_RIGHT_TO_LEFT;
        }

        nPosition = mxScriptTypeDetector->endOfScriptDirection(
            msParagraphText, nPosition, nScriptDirection);
    }

    // All text in paragraph is neutral.  Fall back on writing mode taken
    // from the XText (which may not be properly initialized.)
    sal_Int8 nTextDirection(rendering::TextDirection::WEAK_LEFT_TO_RIGHT);
    switch(mnWritingMode)
    {
        case text::WritingMode2::LR_TB:
            nTextDirection = rendering::TextDirection::WEAK_LEFT_TO_RIGHT;
            break;

        case text::WritingMode2::RL_TB:
            nTextDirection = rendering::TextDirection::WEAK_RIGHT_TO_LEFT;
            break;

        default:
        case text::WritingMode2::TB_RL:
        case text::WritingMode2::TB_LR:
            // Can not handle this.  Use default and hope for the best.
            break;
    }
    return nTextDirection;
}




bool PresenterTextParagraph::IsTextReferencePointLeft (void) const
{
    return mnWritingMode != text::WritingMode2::RL_TB;
}




void PresenterTextParagraph::SetupCellArray (
    const PresenterTheme::SharedFontDescriptor& rpFont)
{
    maCells.clear();

    if ( ! rpFont || ! rpFont->mxFont.is())
        return;

    sal_Int32 nPosition (0);
    sal_Int32 nIndex (0);
    const sal_Int32 nTextLength (msParagraphText.getLength());
    const sal_Int8 nTextDirection (GetTextDirection());
    while (nPosition < nTextLength)
    {
        const sal_Int32 nNewPosition (mxBreakIterator->nextCharacters(
            msParagraphText,
            nPosition,
            lang::Locale(),
            i18n::CharacterIteratorMode::SKIPCELL,
            1,
            nIndex));

        rendering::StringContext aContext (msParagraphText, nPosition, nNewPosition-nPosition);
        Reference<rendering::XTextLayout> xLayout (
            rpFont->mxFont->createTextLayout(aContext, nTextDirection, 0));
        css::geometry::RealRectangle2D aCharacterBox (xLayout->queryTextBounds());

        maCells.push_back(Cell(
            nPosition,
            nNewPosition-nPosition,
            aCharacterBox.X2-aCharacterBox.X1));

        nPosition = nNewPosition;
    }
}




//===== PresenterTextCaret ================================================----

PresenterTextCaret::PresenterTextCaret (
    const ::boost::function<css::awt::Rectangle(const sal_Int32,const sal_Int32)>& rCharacterBoundsAccess,
    const ::boost::function<void(const css::awt::Rectangle&)>& rInvalidator)
    : mnParagraphIndex(-1),
      mnCharacterIndex(-1),
      mnCaretBlinkTaskId(0),
      mbIsCaretVisible(false),
      maCharacterBoundsAccess(rCharacterBoundsAccess),
      maInvalidator(rInvalidator),
      maBroadcaster(),
      maCaretBounds()
{
}




PresenterTextCaret::~PresenterTextCaret (void)
{
    HideCaret();
}




void PresenterTextCaret::ShowCaret (void)
{
    if (mnCaretBlinkTaskId == 0)
    {
        mnCaretBlinkTaskId = PresenterTimer::ScheduleRepeatedTask (
            ::boost::bind(&PresenterTextCaret::InvertCaret, this),
            CaretBlinkIntervall,
            CaretBlinkIntervall);
    }
    mbIsCaretVisible = true;
}




void PresenterTextCaret::HideCaret (void)
{
    if (mnCaretBlinkTaskId != 0)
    {
        PresenterTimer::CancelTask(mnCaretBlinkTaskId);
        mnCaretBlinkTaskId = 0;
    }
    mbIsCaretVisible = false;
    // Reset the caret position.
    mnParagraphIndex = -1;
    mnCharacterIndex = -1;
}




sal_Int32 PresenterTextCaret::GetParagraphIndex (void) const
{
    return mnParagraphIndex;
}




sal_Int32 PresenterTextCaret::GetCharacterIndex (void) const
{
    return mnCharacterIndex;
}




void PresenterTextCaret::SetPosition (
    const sal_Int32 nParagraphIndex,
    const sal_Int32 nCharacterIndex)
{
    if (mnParagraphIndex != nParagraphIndex
        || mnCharacterIndex != nCharacterIndex)
    {
        if (mnParagraphIndex >= 0)
            maInvalidator(maCaretBounds);

        const sal_Int32 nOldParagraphIndex (mnParagraphIndex);
        const sal_Int32 nOldCharacterIndex (mnCharacterIndex);
        mnParagraphIndex = nParagraphIndex;
        mnCharacterIndex = nCharacterIndex;
        maCaretBounds = maCharacterBoundsAccess(mnParagraphIndex, mnCharacterIndex);
        if (mnParagraphIndex >= 0)
            ShowCaret();
        else
            HideCaret();

        if (mnParagraphIndex >= 0)
            maInvalidator(maCaretBounds);

        if (maBroadcaster)
            maBroadcaster(
                nOldParagraphIndex,
                nOldCharacterIndex,
                mnParagraphIndex,
                mnCharacterIndex);

    }
}




bool PresenterTextCaret::IsVisible (void) const
{
    return mbIsCaretVisible;
}




void PresenterTextCaret::SetCaretMotionBroadcaster (
    const ::boost::function<void(sal_Int32,sal_Int32,sal_Int32,sal_Int32)>& rBroadcaster)
{
    maBroadcaster = rBroadcaster;
}




css::awt::Rectangle PresenterTextCaret::GetBounds (void) const
{
    return maCaretBounds;
}




void PresenterTextCaret::InvertCaret (void)
{
    mbIsCaretVisible = !mbIsCaretVisible;
    if (mnParagraphIndex >= 0)
        maInvalidator(maCaretBounds);
}







//===== PresenterTextParagraph::Cell ==========================================

PresenterTextParagraph::Cell::Cell (
    const sal_Int32 nCharacterIndex,
    const sal_Int32 nCharacterCount,
    const double nCellWidth)
    : mnCharacterIndex(nCharacterIndex),
      mnCharacterCount(nCharacterCount),
      mnCellWidth(nCellWidth)
{
}




//===== PresenterTextParagraph::Line ==========================================

PresenterTextParagraph::Line::Line (
    const sal_Int32 nLineStartCharacterIndex,
    const sal_Int32 nLineEndCharacterIndex)
    : mnLineStartCharacterIndex(nLineStartCharacterIndex),
      mnLineEndCharacterIndex(nLineEndCharacterIndex),
      mnLineStartCellIndex(-1), mnLineEndCellIndex(-1),
      mxLayoutedLine(),
      mnBaseLine(0), mnWidth(0),
      maCellBoxes()
{
}




sal_Int32 PresenterTextParagraph::Line::GetLength (void) const
{
    return mnLineEndCharacterIndex-mnLineStartCharacterIndex;
}




void PresenterTextParagraph::Line::ProvideCellBoxes (void)
{
    if ( ! IsEmpty() && maCellBoxes.getLength()==0)
    {
        if (mxLayoutedLine.is())
            maCellBoxes = mxLayoutedLine->queryInkMeasures();
        else
        {
            OSL_ASSERT(mxLayoutedLine.is());
        }
    }
}




void PresenterTextParagraph::Line::ProvideLayoutedLine (
    const ::rtl::OUString& rsParagraphText,
    const PresenterTheme::SharedFontDescriptor& rpFont,
    const sal_Int8 nTextDirection)
{
    if ( ! mxLayoutedLine.is())
    {
        const rendering::StringContext aContext (
            rsParagraphText,
            mnLineStartCharacterIndex,
            mnLineEndCharacterIndex - mnLineStartCharacterIndex);

        mxLayoutedLine = rpFont->mxFont->createTextLayout(
            aContext,
            nTextDirection,
            0);
    }
}




bool PresenterTextParagraph::Line::IsEmpty (void) const
{
    return mnLineStartCharacterIndex >= mnLineEndCharacterIndex;
}




} } // end of namespace ::sdext::presenter
