LCOV - code coverage report
Current view: top level - sw/source/core/access - accportions.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 85 232 36.6 %
Date: 2012-08-25 Functions: 13 31 41.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 75 223 33.6 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include "accportions.hxx"
      30                 :            : #include <rtl/ustring.hxx>
      31                 :            : #include <com/sun/star/i18n/Boundary.hpp>
      32                 :            : #include <txttypes.hxx>
      33                 :            : 
      34                 :            : // for portion replacement in Special()
      35                 :            : #include "access.hrc"
      36                 :            : #include <tools/resid.hxx>
      37                 :            : #include "viewopt.hxx"
      38                 :            : 
      39                 :            : // for GetWordBoundary(...), GetSentenceBoundary(...):
      40                 :            : #include <breakit.hxx>
      41                 :            : #include <com/sun/star/i18n/WordType.hpp>
      42                 :            : #include <com/sun/star/i18n/XBreakIterator.hpp>
      43                 :            : #include <ndtxt.hxx>
      44                 :            : 
      45                 :            : // for FillSpecialPos(...)
      46                 :            : #include "crstate.hxx"
      47                 :            : 
      48                 :            : // for SwAccessibleContext::GetResource()
      49                 :            : #include "acccontext.hxx"
      50                 :            : 
      51                 :            : // for Post-It replacement text:
      52                 :            : #include "txatbase.hxx"
      53                 :            : #include "fmtfld.hxx"
      54                 :            : #include "fldbas.hxx"
      55                 :            : #include "docufld.hxx"
      56                 :            : 
      57                 :            : // for in-line graphics replacement:
      58                 :            : #include "ndindex.hxx"
      59                 :            : #include "ndnotxt.hxx"
      60                 :            : #include "fmtflcnt.hxx"
      61                 :            : #include "frmfmt.hxx"
      62                 :            : #include "fmtcntnt.hxx"
      63                 :            : 
      64                 :            : 
      65                 :            : using namespace ::com::sun::star;
      66                 :            : 
      67                 :            : using rtl::OUString;
      68                 :            : using rtl::OUStringBuffer;
      69                 :            : using i18n::Boundary;
      70                 :            : 
      71                 :            : 
      72                 :            : // 'portion type' for terminating portions
      73                 :            : #define POR_TERMINATE 0
      74                 :            : 
      75                 :            : 
      76                 :            : // portion attributes
      77                 :            : #define PORATTR_SPECIAL     1
      78                 :            : #define PORATTR_READONLY    2
      79                 :            : #define PORATTR_GRAY        4
      80                 :            : #define PORATTR_TERM        128
      81                 :            : 
      82                 :         55 : SwAccessiblePortionData::SwAccessiblePortionData(
      83                 :            :     const SwTxtNode* pTxtNd,
      84                 :            :     const SwViewOption* pViewOpt ) :
      85                 :            :     SwPortionHandler(),
      86                 :            :     pTxtNode( pTxtNd ),
      87                 :            :     aBuffer(),
      88                 :            :     nModelPosition( 0 ),
      89                 :            :     bFinished( sal_False ),
      90                 :            :     pViewOptions( pViewOpt ),
      91                 :            :     sAccessibleString(),
      92                 :            :     aLineBreaks(),
      93                 :            :     aModelPositions(),
      94                 :            :     aAccessiblePositions(),
      95                 :            :     pSentences( 0 ),
      96                 :            :     nBeforePortions( 0 ),
      97 [ +  - ][ +  - ]:         55 :     bLastIsSpecial( sal_False )
         [ +  - ][ +  - ]
      98                 :            : {
      99                 :            :     OSL_ENSURE( pTxtNode != NULL, "Text node is needed!" );
     100                 :            : 
     101                 :            :     // reserve some space to reduce memory allocations
     102         [ +  - ]:         55 :     aLineBreaks.reserve( 5 );
     103         [ +  - ]:         55 :     aModelPositions.reserve( 10 );
     104         [ +  - ]:         55 :     aAccessiblePositions.reserve( 10 );
     105                 :            : 
     106                 :            :     // always include 'first' line-break position
     107         [ +  - ]:         55 :     aLineBreaks.push_back( 0 );
     108                 :         55 : }
     109                 :            : 
     110                 :         55 : SwAccessiblePortionData::~SwAccessiblePortionData()
     111                 :            : {
     112         [ -  + ]:         55 :     delete pSentences;
     113         [ -  + ]:        110 : }
     114                 :            : 
     115                 :         24 : void SwAccessiblePortionData::Text(sal_uInt16 nLength, sal_uInt16 nType, sal_Int32 /*nHeight*/, sal_Int32 /*nWidth*/)
     116                 :            : {
     117                 :            :     OSL_ENSURE( (nModelPosition + nLength) <= pTxtNode->GetTxt().Len(),
     118                 :            :                 "portion exceeds model string!" );
     119                 :            : 
     120                 :            :     OSL_ENSURE( !bFinished, "We are already done!" );
     121                 :            : 
     122                 :            :     // ignore zero-length portions
     123         [ +  + ]:         24 :     if( nLength == 0 )
     124                 :         24 :         return;
     125                 :            : 
     126                 :            :     // store 'old' positions
     127         [ +  - ]:          8 :     aModelPositions.push_back( nModelPosition );
     128         [ +  - ]:          8 :     aAccessiblePositions.push_back( aBuffer.getLength() );
     129                 :            : 
     130                 :            :     // store portion attributes
     131 [ +  - ][ -  + ]:          8 :     sal_uInt8 nAttr = IsGrayPortionType(nType) ? PORATTR_GRAY : 0;
     132         [ +  - ]:          8 :     aPortionAttrs.push_back( nAttr );
     133                 :            : 
     134                 :            :     // update buffer + nModelPosition
     135                 :            :     aBuffer.append( OUString(
     136                 :          8 :         pTxtNode->GetTxt().Copy(
     137                 :            :             static_cast<sal_uInt16>( nModelPosition ),
     138 [ +  - ][ +  - ]:          8 :             nLength ) ) );
         [ +  - ][ +  - ]
     139                 :          8 :     nModelPosition += nLength;
     140                 :            : 
     141                 :         24 :     bLastIsSpecial = sal_False;
     142                 :            : }
     143                 :            : 
     144                 :        134 : void SwAccessiblePortionData::Special(
     145                 :            :     sal_uInt16 nLength, const String& rText, sal_uInt16 nType, sal_Int32 /*nHeight*/, sal_Int32 /*nWidth*/)
     146                 :            : {
     147                 :            :     OSL_ENSURE( nModelPosition >= 0, "illegal position" );
     148                 :            :     OSL_ENSURE( (nModelPosition + nLength) <= pTxtNode->GetTxt().Len(),
     149                 :            :                 "portion exceeds model string!" );
     150                 :            : 
     151                 :            :     OSL_ENSURE( !bFinished, "We are already done!" );
     152                 :            : 
     153                 :            :     // construct string with representation; either directly from
     154                 :            :     // rText, or use resources for special case portions
     155         [ +  - ]:        134 :     String sDisplay;
     156   [ -  -  -  + ]:        134 :     switch( nType )
     157                 :            :     {
     158                 :            :         case POR_POSTITS:
     159                 :            :         case POR_FLYCNT:
     160                 :            :         case POR_GRFNUM:
     161         [ #  # ]:          0 :             sDisplay = rtl::OUString(sal_Unicode(0xfffc));
     162                 :            : 
     163                 :          0 :             break;
     164                 :            :         case POR_NUMBER:
     165                 :            :         {
     166                 :          0 :             OUStringBuffer aTmpBuffer( rText.Len() + 1 );
     167 [ #  # ][ #  # ]:          0 :             aTmpBuffer.append( rText );
     168         [ #  # ]:          0 :             aTmpBuffer.append( sal_Unicode(' ') );
     169 [ #  # ][ #  # ]:          0 :             sDisplay = aTmpBuffer.makeStringAndClear();
     170                 :          0 :             break;
     171                 :            :         }
     172                 :            :         // #i111768# - apply patch from kstribley:
     173                 :            :         // Include the control characters.
     174                 :            :         case POR_CONTROLCHAR:
     175                 :            :         {
     176                 :          0 :             OUStringBuffer aTmpBuffer( rText.Len() + 1 );
     177 [ #  # ][ #  # ]:          0 :             aTmpBuffer.append( rText );
     178         [ #  # ]:          0 :             aTmpBuffer.append( pTxtNode->GetTxt().GetChar(nModelPosition) );
     179 [ #  # ][ #  # ]:          0 :             sDisplay = aTmpBuffer.makeStringAndClear();
     180                 :          0 :             break;
     181                 :            :         }
     182                 :            :         default:
     183         [ +  - ]:        134 :             sDisplay = rText;
     184                 :        134 :             break;
     185                 :            :     }
     186                 :            : 
     187                 :            :     // ignore zero/zero portions (except for terminators)
     188 [ +  + ][ +  + ]:        134 :     if( (nLength == 0) && (sDisplay.Len() == 0) && (nType != POR_TERMINATE) )
         [ +  + ][ +  + ]
     189                 :        134 :         return;
     190                 :            : 
     191                 :            :     // special treatment for zero length portion at the beginning:
     192                 :            :     // count as 'before' portion
     193 [ +  + ][ +  + ]:        130 :     if( ( nLength == 0 ) && ( nModelPosition == 0 ) )
     194                 :         60 :         nBeforePortions++;
     195                 :            : 
     196                 :            :     // store the 'old' positions
     197         [ +  - ]:        130 :     aModelPositions.push_back( nModelPosition );
     198         [ +  - ]:        130 :     aAccessiblePositions.push_back( aBuffer.getLength() );
     199                 :            : 
     200                 :            :     // store portion attributes
     201                 :        130 :     sal_uInt8 nAttr = PORATTR_SPECIAL;
     202 [ +  - ][ +  + ]:        130 :     if( IsGrayPortionType(nType) )      nAttr |= PORATTR_GRAY;
     203         [ +  + ]:        130 :     if( nLength == 0 )                  nAttr |= PORATTR_READONLY;
     204         [ +  + ]:        130 :     if( nType == POR_TERMINATE )        nAttr |= PORATTR_TERM;
     205         [ +  - ]:        130 :     aPortionAttrs.push_back( nAttr );
     206                 :            : 
     207                 :            :     // update buffer + nModelPosition
     208 [ +  - ][ +  - ]:        130 :     aBuffer.append( OUString(sDisplay) );
     209                 :        130 :     nModelPosition += nLength;
     210                 :            : 
     211                 :            :     // remember 'last' special portion (unless it's our own 'closing'
     212                 :            :     // portions from 'Finish()'
     213         [ +  + ]:        130 :     if( nType != POR_TERMINATE )
     214 [ +  - ][ +  + ]:        134 :         bLastIsSpecial = sal_True;
     215                 :            : }
     216                 :            : 
     217                 :        154 : void SwAccessiblePortionData::LineBreak()
     218                 :            : {
     219                 :            :     OSL_ENSURE( !bFinished, "We are already done!" );
     220                 :            : 
     221         [ +  - ]:        154 :     aLineBreaks.push_back( aBuffer.getLength() );
     222                 :        154 : }
     223                 :            : 
     224                 :          0 : void SwAccessiblePortionData::Skip(sal_uInt16 nLength)
     225                 :            : {
     226                 :            :     OSL_ENSURE( !bFinished, "We are already done!" );
     227                 :            :     OSL_ENSURE( aModelPositions.empty(), "Never Skip() after portions" );
     228                 :            :     OSL_ENSURE( nLength <= pTxtNode->GetTxt().Len(), "skip exceeds model string!" );
     229                 :            : 
     230                 :          0 :     nModelPosition += nLength;
     231                 :          0 : }
     232                 :            : 
     233                 :         55 : void SwAccessiblePortionData::Finish()
     234                 :            : {
     235                 :            :     OSL_ENSURE( !bFinished, "We are already done!" );
     236                 :            : 
     237                 :            :     // include terminator values: always include two 'last character'
     238                 :            :     // markers in the position arrays to make sure we always find one
     239                 :            :     // position before the end
     240         [ +  - ]:         55 :     Special( 0, String(), POR_TERMINATE );
     241         [ +  - ]:         55 :     Special( 0, String(), POR_TERMINATE );
     242                 :         55 :     LineBreak();
     243                 :         55 :     LineBreak();
     244                 :            : 
     245                 :         55 :     sAccessibleString = aBuffer.makeStringAndClear();
     246                 :         55 :     bFinished = sal_True;
     247                 :         55 : }
     248                 :            : 
     249                 :            : 
     250                 :          0 : sal_Bool SwAccessiblePortionData::IsPortionAttrSet(
     251                 :            :     size_t nPortionNo, sal_uInt8 nAttr ) const
     252                 :            : {
     253                 :            :     OSL_ENSURE( nPortionNo < aPortionAttrs.size(),
     254                 :            :                 "Illegal portion number" );
     255                 :          0 :     return (aPortionAttrs[nPortionNo] & nAttr) != 0;
     256                 :            : }
     257                 :            : 
     258                 :          0 : sal_Bool SwAccessiblePortionData::IsSpecialPortion( size_t nPortionNo ) const
     259                 :            : {
     260                 :          0 :     return IsPortionAttrSet(nPortionNo, PORATTR_SPECIAL);
     261                 :            : }
     262                 :            : 
     263                 :          0 : sal_Bool SwAccessiblePortionData::IsReadOnlyPortion( size_t nPortionNo ) const
     264                 :            : {
     265                 :          0 :     return IsPortionAttrSet(nPortionNo, PORATTR_READONLY);
     266                 :            : }
     267                 :            : 
     268                 :        138 : sal_Bool SwAccessiblePortionData::IsGrayPortionType( sal_uInt16 nType ) const
     269                 :            : {
     270                 :            :     // gray portions?
     271                 :            :     // Compare with: inftxt.cxx, SwTxtPaintInfo::DrawViewOpt(...)
     272                 :        138 :     sal_Bool bGray = sal_False;
     273   [ +  -  -  -  :        138 :     switch( nType )
                      + ]
     274                 :            :     {
     275                 :            :         case POR_FTN:
     276                 :            :         case POR_ISOREF:
     277                 :            :         case POR_REF:
     278                 :            :         case POR_QUOVADIS:
     279                 :            :         case POR_NUMBER:
     280                 :            :         case POR_FLD:
     281                 :            :         case POR_URL:
     282                 :            :         case POR_ISOTOX:
     283                 :            :         case POR_TOX:
     284                 :            :         case POR_HIDDEN:
     285                 :         18 :             bGray = !pViewOptions->IsPagePreview() &&
     286 [ +  - ][ +  - ]:         18 :                 !pViewOptions->IsReadonly() && SwViewOption::IsFieldShadings();
                 [ +  - ]
     287                 :         18 :         break;
     288                 :          0 :         case POR_TAB:       bGray = pViewOptions->IsTab();          break;
     289                 :          0 :         case POR_SOFTHYPH:  bGray = pViewOptions->IsSoftHyph();     break;
     290                 :          0 :         case POR_BLANK:     bGray = pViewOptions->IsHardBlank();    break;
     291                 :            :         default:
     292                 :        120 :             break; // bGray is false
     293                 :            :     }
     294                 :        138 :     return bGray;
     295                 :            : }
     296                 :            : 
     297                 :            : 
     298                 :         68 : const OUString& SwAccessiblePortionData::GetAccessibleString() const
     299                 :            : {
     300                 :            :     OSL_ENSURE( bFinished, "Shouldn't call this before we are done!" );
     301                 :            : 
     302                 :         68 :     return sAccessibleString;
     303                 :            : }
     304                 :            : 
     305                 :            : 
     306                 :          0 : void SwAccessiblePortionData::GetLineBoundary(
     307                 :            :     Boundary& rBound,
     308                 :            :     sal_Int32 nPos ) const
     309                 :            : {
     310                 :            :     FillBoundary( rBound, aLineBreaks,
     311                 :          0 :                   FindBreak( aLineBreaks, nPos ) );
     312                 :          0 : }
     313                 :            : 
     314                 :            : // #i89175#
     315                 :          0 : sal_Int32 SwAccessiblePortionData::GetLineCount() const
     316                 :            : {
     317                 :          0 :     size_t nBreaks = aLineBreaks.size();
     318                 :            :     // A non-empty paragraph has at least 4 breaks: one for each line3 and
     319                 :            :     // 3 additional ones.
     320                 :            :     // An empty paragraph has 3 breaks.
     321                 :            :     // Less than 3 breaks is an error case.
     322                 :            :     sal_Int32 nLineCount = ( nBreaks > 3 )
     323                 :            :                            ? nBreaks - 3
     324 [ #  # ][ #  # ]:          0 :                            : ( ( nBreaks == 3 ) ? 1 : 0 );
     325                 :          0 :     return nLineCount;
     326                 :            : }
     327                 :            : 
     328                 :          0 : sal_Int32 SwAccessiblePortionData::GetLineNo( const sal_Int32 nPos ) const
     329                 :            : {
     330                 :          0 :     sal_Int32 nLineNo = FindBreak( aLineBreaks, nPos );
     331                 :            : 
     332                 :            :     // handling of position after last character
     333                 :          0 :     const sal_Int32 nLineCount( GetLineCount() );
     334         [ #  # ]:          0 :     if ( nLineNo >= nLineCount )
     335                 :            :     {
     336                 :          0 :         nLineNo = nLineCount - 1;
     337                 :            :     }
     338                 :            : 
     339                 :          0 :     return nLineNo;
     340                 :            : }
     341                 :            : 
     342                 :          0 : void SwAccessiblePortionData::GetBoundaryOfLine( const sal_Int32 nLineNo,
     343                 :            :                                                  i18n::Boundary& rLineBound )
     344                 :            : {
     345                 :          0 :     FillBoundary( rLineBound, aLineBreaks, nLineNo );
     346                 :          0 : }
     347                 :            : 
     348                 :          0 : void SwAccessiblePortionData::GetLastLineBoundary(
     349                 :            :     Boundary& rBound ) const
     350                 :            : {
     351                 :            :     OSL_ENSURE( aLineBreaks.size() >= 2, "need min + max value" );
     352                 :            : 
     353                 :            :     // The last two positions except the two deleimiters are the ones
     354                 :            :     // we are looking for, except for empty paragraphs (nBreaks==3)
     355                 :          0 :     size_t nBreaks = aLineBreaks.size();
     356         [ #  # ]:          0 :     FillBoundary( rBound, aLineBreaks, nBreaks <= 3 ? 0 : nBreaks-4 );
     357                 :          0 : }
     358                 :            : 
     359                 :          0 : sal_uInt16 SwAccessiblePortionData::GetModelPosition( sal_Int32 nPos ) const
     360                 :            : {
     361                 :            :     OSL_ENSURE( nPos >= 0, "illegal position" );
     362                 :            :     OSL_ENSURE( nPos <= sAccessibleString.getLength(), "illegal position" );
     363                 :            : 
     364                 :            :     // find the portion number
     365                 :          0 :     size_t nPortionNo = FindBreak( aAccessiblePositions, nPos );
     366                 :            : 
     367                 :            :     // get model portion size
     368                 :          0 :     sal_Int32 nStartPos = aModelPositions[nPortionNo];
     369                 :            : 
     370                 :            :     // if it's a non-special portion, move into the portion, else
     371                 :            :     // return the portion start
     372         [ #  # ]:          0 :     if( ! IsSpecialPortion( nPortionNo ) )
     373                 :            :     {
     374                 :            :         // 'wide' portions have to be of the same width
     375                 :            :         OSL_ENSURE( ( aModelPositions[nPortionNo+1] - nStartPos ) ==
     376                 :            :                     ( aAccessiblePositions[nPortionNo+1] -
     377                 :            :                       aAccessiblePositions[nPortionNo] ),
     378                 :            :                     "accesability portion disagrees with text model" );
     379                 :            : 
     380                 :          0 :         sal_Int32 nWithinPortion = nPos - aAccessiblePositions[nPortionNo];
     381                 :          0 :         nStartPos += nWithinPortion;
     382                 :            :     }
     383                 :            :     // else: return nStartPos unmodified
     384                 :            : 
     385                 :            :     OSL_ENSURE( (nStartPos >= 0) && (nStartPos < USHRT_MAX),
     386                 :            :                 "How can the SwTxtNode have so many characters?" );
     387                 :          0 :     return static_cast<sal_uInt16>(nStartPos);
     388                 :            : }
     389                 :            : 
     390                 :          0 : void SwAccessiblePortionData::FillBoundary(
     391                 :            :     Boundary& rBound,
     392                 :            :     const Positions_t& rPositions,
     393                 :            :     size_t nPos ) const
     394                 :            : {
     395                 :          0 :     rBound.startPos = rPositions[nPos];
     396                 :          0 :     rBound.endPos = rPositions[nPos+1];
     397                 :          0 : }
     398                 :            : 
     399                 :            : 
     400                 :        119 : size_t SwAccessiblePortionData::FindBreak(
     401                 :            :     const Positions_t& rPositions,
     402                 :            :     sal_Int32 nValue ) const
     403                 :            : {
     404                 :            :     OSL_ENSURE( rPositions.size() >= 2, "need min + max value" );
     405                 :            :     OSL_ENSURE( rPositions[0] <= nValue, "need min value" );
     406                 :            :     OSL_ENSURE( rPositions[rPositions.size()-1] >= nValue,
     407                 :            :                 "need first terminator value" );
     408                 :            :     OSL_ENSURE( rPositions[rPositions.size()-2] >= nValue,
     409                 :            :                 "need second terminator value" );
     410                 :            : 
     411                 :        119 :     size_t nMin = 0;
     412                 :        119 :     size_t nMax = rPositions.size()-2;
     413                 :            : 
     414                 :            :     // loop until no more than two candidates are left
     415         [ -  + ]:        119 :     while( nMin+1 < nMax )
     416                 :            :     {
     417                 :            :         // check loop invariants
     418                 :            :         OSL_ENSURE( ( (nMin == 0) && (rPositions[nMin] <= nValue) ) ||
     419                 :            :                     ( (nMin != 0) && (rPositions[nMin] < nValue) ),
     420                 :            :                     "minvalue not minimal" );
     421                 :            :         OSL_ENSURE( nValue <= rPositions[nMax], "max value not maximal" );
     422                 :            : 
     423                 :            :         // get middle (and ensure progress)
     424                 :          0 :         size_t nMiddle = (nMin + nMax)/2;
     425                 :            :         OSL_ENSURE( nMin < nMiddle, "progress?" );
     426                 :            :         OSL_ENSURE( nMiddle < nMax, "progress?" );
     427                 :            : 
     428                 :            :         // check array
     429                 :            :         OSL_ENSURE( rPositions[nMin] <= rPositions[nMiddle],
     430                 :            :                     "garbled positions array" );
     431                 :            :         OSL_ENSURE( rPositions[nMiddle] <= rPositions[nMax],
     432                 :            :                     "garbled positions array" );
     433                 :            : 
     434         [ #  # ]:          0 :         if( nValue > rPositions[nMiddle] )
     435                 :          0 :             nMin = nMiddle;
     436                 :            :         else
     437                 :          0 :             nMax = nMiddle;
     438                 :            :     }
     439                 :            : 
     440                 :            :     // only two are left; we only need to check which one is the winner
     441                 :            :     OSL_ENSURE( (nMax == nMin) || (nMax == nMin+1), "only two left" );
     442 [ +  + ][ +  - ]:        119 :     if( (rPositions[nMin] < nValue) && (rPositions[nMin+1] <= nValue) )
                 [ +  + ]
     443                 :         42 :         nMin = nMin+1;
     444                 :            : 
     445                 :            :     // finally, check to see whether the returned value is the 'right' position
     446                 :            :     OSL_ENSURE( rPositions[nMin] <= nValue, "not smaller or equal" );
     447                 :            :     OSL_ENSURE( nValue <= rPositions[nMin+1], "not equal or larger" );
     448                 :            :     OSL_ENSURE( (nMin == 0) || (rPositions[nMin-1] <= nValue),
     449                 :            :                 "earlier value should have been returned" );
     450                 :            : 
     451                 :            :     OSL_ENSURE( nMin < rPositions.size()-1,
     452                 :            :                 "shouldn't return last position (due to termintator values)" );
     453                 :            : 
     454                 :        119 :     return nMin;
     455                 :            : }
     456                 :            : 
     457                 :        119 : size_t SwAccessiblePortionData::FindLastBreak(
     458                 :            :     const Positions_t& rPositions,
     459                 :            :     sal_Int32 nValue ) const
     460                 :            : {
     461                 :        119 :     size_t nResult = FindBreak( rPositions, nValue );
     462                 :            : 
     463                 :            :     // skip 'zero-length' portions
     464                 :            :     // #i70538# consider size of <rPosition> and ignore last entry
     465   [ +  +  +  - ]:        131 :     while ( nResult < rPositions.size() - 2 &&
                 [ +  + ]
     466                 :          6 :             rPositions[nResult+1] <= nValue )
     467                 :            :     {
     468                 :          6 :         nResult++;
     469                 :            :     }
     470                 :            : 
     471                 :        119 :     return nResult;
     472                 :            : }
     473                 :            : 
     474                 :            : 
     475                 :          0 : void SwAccessiblePortionData::GetSentenceBoundary(
     476                 :            :     Boundary& rBound,
     477                 :            :     sal_Int32 nPos )
     478                 :            : {
     479                 :            :     OSL_ENSURE( nPos >= 0, "illegal position; check before" );
     480                 :            :     OSL_ENSURE( nPos < sAccessibleString.getLength(), "illegal position" );
     481                 :            : 
     482         [ #  # ]:          0 :     if( pSentences == NULL )
     483                 :            :     {
     484                 :            :          OSL_ENSURE( pBreakIt != NULL, "We always need a break." );
     485                 :            :          OSL_ENSURE( pBreakIt->GetBreakIter().is(), "No break-iterator." );
     486         [ #  # ]:          0 :          if( pBreakIt->GetBreakIter().is() )
     487                 :            :          {
     488 [ #  # ][ #  # ]:          0 :              pSentences = new Positions_t();
     489         [ #  # ]:          0 :              pSentences->reserve(10);
     490                 :            : 
     491                 :            :              // use xBreak->endOfSentence to iterate over all words; store
     492                 :            :              // positions in pSentences
     493                 :          0 :              sal_Int32 nCurrent = 0;
     494                 :          0 :              sal_Int32 nLength = sAccessibleString.getLength();
     495         [ #  # ]:          0 :              do
     496                 :            :              {
     497         [ #  # ]:          0 :                  pSentences->push_back( nCurrent );
     498                 :            : 
     499         [ #  # ]:          0 :                  sal_uInt16 nModelPos = GetModelPosition( nCurrent );
     500                 :            : 
     501 [ #  # ][ #  # ]:          0 :                  sal_Int32 nNew = pBreakIt->GetBreakIter()->endOfSentence(
     502                 :            :                      sAccessibleString, nCurrent,
     503 [ #  # ][ #  # ]:          0 :                      pBreakIt->GetLocale(pTxtNode->GetLang(nModelPos)) ) + 1;
                 [ #  # ]
     504                 :            : 
     505 [ #  # ][ #  # ]:          0 :                  if( (nNew < 0) && (nNew > nLength) )
     506                 :          0 :                      nNew = nLength;
     507         [ #  # ]:          0 :                  else if (nNew <= nCurrent)
     508                 :          0 :                      nNew = nCurrent + 1;   // ensure forward progress
     509                 :            : 
     510                 :          0 :                  nCurrent = nNew;
     511                 :            :              }
     512                 :            :              while (nCurrent < nLength);
     513                 :            : 
     514                 :            :              // finish with two terminators
     515         [ #  # ]:          0 :              pSentences->push_back( nLength );
     516         [ #  # ]:          0 :              pSentences->push_back( nLength );
     517                 :            :          }
     518                 :            :          else
     519                 :            :          {
     520                 :            :              // no break iterator -> empty word
     521                 :          0 :              rBound.startPos = 0;
     522                 :          0 :              rBound.endPos = 0;
     523                 :          0 :              return;
     524                 :            :          }
     525                 :            :     }
     526                 :            : 
     527                 :          0 :     FillBoundary( rBound, *pSentences, FindBreak( *pSentences, nPos ) );
     528                 :            : }
     529                 :            : 
     530                 :          0 : void SwAccessiblePortionData::GetAttributeBoundary(
     531                 :            :     Boundary& rBound,
     532                 :            :     sal_Int32 nPos) const
     533                 :            : {
     534                 :            :     OSL_ENSURE( pTxtNode != NULL, "Need SwTxtNode!" );
     535                 :            : 
     536                 :            :     // attribute boundaries can only occur on portion boundaries
     537                 :            :     FillBoundary( rBound, aAccessiblePositions,
     538                 :          0 :                   FindBreak( aAccessiblePositions, nPos ) );
     539                 :          0 : }
     540                 :            : 
     541                 :            : 
     542                 :        119 : sal_Int32 SwAccessiblePortionData::GetAccessiblePosition( sal_uInt16 nPos ) const
     543                 :            : {
     544                 :            :     OSL_ENSURE( nPos <= pTxtNode->GetTxt().Len(), "illegal position" );
     545                 :            : 
     546                 :            :     // find the portion number
     547                 :            :     // #i70538# - consider "empty" model portions - e.g. number portion
     548                 :            :     size_t nPortionNo = FindLastBreak( aModelPositions,
     549                 :        119 :                                        static_cast<sal_Int32>(nPos) );
     550                 :            : 
     551                 :        119 :     sal_Int32 nRet = aAccessiblePositions[nPortionNo];
     552                 :            : 
     553                 :            :     // if the model portion has more than one position, go into it;
     554                 :            :     // else return that position
     555                 :        119 :     sal_Int32 nStartPos = aModelPositions[nPortionNo];
     556                 :        119 :     sal_Int32 nEndPos = aModelPositions[nPortionNo+1];
     557         [ -  + ]:        119 :     if( (nEndPos - nStartPos) > 1 )
     558                 :            :     {
     559                 :            :         // 'wide' portions have to be of the same width
     560                 :            :         OSL_ENSURE( ( nEndPos - nStartPos ) ==
     561                 :            :                     ( aAccessiblePositions[nPortionNo+1] -
     562                 :            :                       aAccessiblePositions[nPortionNo] ),
     563                 :            :                     "accesability portion disagrees with text model" );
     564                 :            : 
     565                 :          0 :         sal_Int32 nWithinPortion = nPos - aModelPositions[nPortionNo];
     566                 :          0 :         nRet += nWithinPortion;
     567                 :            :     }
     568                 :            :     // else: return nRet unmodified
     569                 :            : 
     570                 :            :     OSL_ENSURE( (nRet >= 0) && (nRet <= sAccessibleString.getLength()),
     571                 :            :                 "too long!" );
     572                 :        119 :     return nRet;
     573                 :            : }
     574                 :            : 
     575                 :          0 : sal_uInt16 SwAccessiblePortionData::FillSpecialPos(
     576                 :            :     sal_Int32 nPos,
     577                 :            :     SwSpecialPos& rPos,
     578                 :            :     SwSpecialPos*& rpPos ) const
     579                 :            : {
     580                 :          0 :     size_t nPortionNo = FindLastBreak( aAccessiblePositions, nPos );
     581                 :            : 
     582                 :          0 :     sal_uInt8 nExtend(SP_EXTEND_RANGE_NONE);
     583                 :          0 :     sal_Int32 nRefPos(0);
     584                 :          0 :     sal_Int32 nModelPos(0);
     585                 :            : 
     586         [ #  # ]:          0 :     if( nPortionNo < nBeforePortions )
     587                 :            :     {
     588                 :          0 :         nExtend = SP_EXTEND_RANGE_BEFORE;
     589                 :          0 :         rpPos = &rPos;
     590                 :            :     }
     591                 :            :     else
     592                 :            :     {
     593                 :          0 :         sal_Int32 nModelEndPos = aModelPositions[nPortionNo+1];
     594                 :          0 :         nModelPos = aModelPositions[nPortionNo];
     595                 :            : 
     596                 :            :         // skip backwards over zero-length portions, since GetCharRect()
     597                 :            :         // counts all model-zero-length portions as belonging to the
     598                 :            :         // previus portion
     599                 :          0 :         size_t nCorePortionNo = nPortionNo;
     600         [ #  # ]:          0 :         while( nModelPos == nModelEndPos )
     601                 :            :         {
     602                 :          0 :             nCorePortionNo--;
     603                 :          0 :             nModelEndPos = nModelPos;
     604                 :          0 :             nModelPos = aModelPositions[nCorePortionNo];
     605                 :            : 
     606                 :            :             OSL_ENSURE( nModelPos >= 0, "Can't happen." );
     607                 :            :             OSL_ENSURE( nCorePortionNo >= nBeforePortions, "Can't happen." );
     608                 :            :         }
     609                 :            :         OSL_ENSURE( nModelPos != nModelEndPos,
     610                 :            :                     "portion with core-representation expected" );
     611                 :            : 
     612                 :            :         // if we have anything except plain text, compute nExtend + nRefPos
     613   [ #  #  #  # ]:          0 :         if( (nModelEndPos - nModelPos == 1) &&
                 [ #  # ]
     614                 :          0 :             (pTxtNode->GetTxt().GetChar(static_cast<sal_uInt16>(nModelPos)) !=
     615                 :          0 :              sAccessibleString.getStr()[nPos]) )
     616                 :            :         {
     617                 :            :             // case 1: a one-character, non-text portion
     618                 :            :             // reference position is the first accessibilty for our
     619                 :            :             // core portion
     620                 :          0 :             nRefPos = aAccessiblePositions[ nCorePortionNo ];
     621                 :          0 :             nExtend = SP_EXTEND_RANGE_NONE;
     622                 :          0 :             rpPos = &rPos;
     623                 :            :         }
     624         [ #  # ]:          0 :         else if(nPortionNo != nCorePortionNo)
     625                 :            :         {
     626                 :            :             // case 2: a multi-character (text!) portion, followed by
     627                 :            :             // zero-length portions
     628                 :            :             // reference position is the first character of the next
     629                 :            :             // portion, and we are 'behind'
     630                 :          0 :             nRefPos = aAccessiblePositions[ nCorePortionNo+1 ];
     631                 :          0 :             nExtend = SP_EXTEND_RANGE_BEHIND;
     632                 :          0 :             rpPos = &rPos;
     633                 :            :         }
     634                 :            :         else
     635                 :            :         {
     636                 :            :             // case 3: regular text portion
     637                 :            :             OSL_ENSURE( ( nModelEndPos - nModelPos ) ==
     638                 :            :                         ( aAccessiblePositions[nPortionNo+1] -
     639                 :            :                           aAccessiblePositions[nPortionNo] ),
     640                 :            :                         "text portion expected" );
     641                 :            : 
     642                 :          0 :             nModelPos += nPos - aAccessiblePositions[ nPortionNo ];
     643                 :          0 :             rpPos = NULL;
     644                 :            :         }
     645                 :            :     }
     646         [ #  # ]:          0 :     if( rpPos != NULL )
     647                 :            :     {
     648                 :            :         OSL_ENSURE( rpPos == &rPos, "Yes!" );
     649                 :            :         OSL_ENSURE( nRefPos <= nPos, "wrong reference" );
     650                 :            :         OSL_ENSURE( (nExtend == SP_EXTEND_RANGE_NONE) ||
     651                 :            :                     (nExtend == SP_EXTEND_RANGE_BEFORE) ||
     652                 :            :                     (nExtend == SP_EXTEND_RANGE_BEHIND), "need extend" );
     653                 :            : 
     654                 :            :         // get the line number, and adjust nRefPos for the line
     655                 :            :         // (if necessary)
     656                 :          0 :         size_t nRefLine = FindBreak( aLineBreaks, nRefPos );
     657                 :          0 :         size_t nMyLine  = FindBreak( aLineBreaks, nPos );
     658                 :          0 :         sal_uInt16 nLineOffset = static_cast<sal_uInt16>( nMyLine - nRefLine );
     659         [ #  # ]:          0 :         if( nLineOffset != 0 )
     660                 :          0 :             nRefPos = aLineBreaks[ nMyLine ];
     661                 :            : 
     662                 :            :         // fill char offset and 'special position'
     663                 :          0 :         rPos.nCharOfst = static_cast<sal_uInt16>( nPos - nRefPos );
     664                 :          0 :         rPos.nExtendRange = nExtend;
     665                 :          0 :         rPos.nLineOfst = nLineOffset;
     666                 :            :     }
     667                 :            : 
     668                 :          0 :     return static_cast<sal_uInt16>( nModelPos );
     669                 :            : }
     670                 :            : 
     671                 :          0 : void SwAccessiblePortionData::AdjustAndCheck(
     672                 :            :     sal_Int32 nPos,
     673                 :            :     size_t& nPortionNo,
     674                 :            :     sal_uInt16& nCorePos,
     675                 :            :     sal_Bool& bEdit) const
     676                 :            : {
     677                 :            :     // find portion and get mode position
     678                 :          0 :     nPortionNo = FindBreak( aAccessiblePositions, nPos );
     679                 :          0 :     nCorePos = static_cast<sal_uInt16>( aModelPositions[ nPortionNo ] );
     680                 :            : 
     681                 :            :     // for special portions, make sure we're on a portion boundary
     682                 :            :     // for text portions, add the in-portion offset
     683         [ #  # ]:          0 :     if( IsSpecialPortion( nPortionNo ) )
     684                 :          0 :         bEdit &= nPos == aAccessiblePositions[nPortionNo];
     685                 :            :     else
     686                 :            :         nCorePos = static_cast<sal_uInt16>( nCorePos +
     687                 :          0 :             nPos - aAccessiblePositions[nPortionNo] );
     688                 :          0 : }
     689                 :            : 
     690                 :          0 : sal_Bool SwAccessiblePortionData::GetEditableRange(
     691                 :            :     sal_Int32 nStart, sal_Int32 nEnd,
     692                 :            :     sal_uInt16& nCoreStart, sal_uInt16& nCoreEnd ) const
     693                 :            : {
     694                 :          0 :     sal_Bool bIsEditable = sal_True;
     695                 :            : 
     696                 :            :     // get start and end portions
     697                 :            :     size_t nStartPortion, nEndPortion;
     698         [ #  # ]:          0 :     AdjustAndCheck( nStart, nStartPortion, nCoreStart, bIsEditable );
     699         [ #  # ]:          0 :     AdjustAndCheck( nEnd,   nEndPortion,   nCoreEnd,   bIsEditable );
     700                 :            : 
     701                 :            :     // iterate over portions, and make sure there is no read-only portion
     702                 :            :     // in-between
     703                 :          0 :     size_t nLastPortion = nEndPortion;
     704                 :            : 
     705                 :            :     // don't count last portion if we're in front of a special portion
     706 [ #  # ][ #  # ]:          0 :     if( IsSpecialPortion(nLastPortion) )
     707                 :            :     {
     708         [ #  # ]:          0 :         if (nLastPortion > 0)
     709                 :          0 :             nLastPortion--;
     710                 :            :         else
     711                 :            :             // special case: because size_t is usually unsigned, we can't just
     712                 :            :             // decrease nLastPortion to -1 (which would normally do the job, so
     713                 :            :             // this whole if wouldn't be needed). Instead, we'll do this
     714                 :            :             // special case and just increae the start portion beyond the last
     715                 :            :             // portion to make sure the loop below will have zero iteration.
     716                 :          0 :             nStartPortion = nLastPortion + 1;
     717                 :            :     }
     718                 :            : 
     719         [ #  # ]:          0 :     for( size_t nPor = nStartPortion; nPor <= nLastPortion; nPor ++ )
     720                 :            :     {
     721         [ #  # ]:          0 :         bIsEditable &= ! IsReadOnlyPortion( nPor );
     722                 :            :     }
     723                 :            : 
     724                 :          0 :     return bIsEditable;
     725                 :            : }
     726                 :            : 
     727                 :        119 : sal_Bool SwAccessiblePortionData::IsValidCorePosition( sal_uInt16 nPos ) const
     728                 :            : {
     729                 :            :     // a position is valid its within the model positions that we know
     730                 :        119 :     return ( aModelPositions[0] <= nPos ) &&
     731 [ +  - ][ +  - ]:        119 :            ( nPos <= aModelPositions[ aModelPositions.size()-1 ] );
     732                 :            : }
     733                 :            : 
     734                 :          0 : sal_uInt16 SwAccessiblePortionData::GetFirstValidCorePosition() const
     735                 :            : {
     736                 :          0 :     return static_cast<sal_uInt16>( aModelPositions[0] );
     737                 :            : }
     738                 :            : 
     739                 :          0 : sal_uInt16 SwAccessiblePortionData::GetLastValidCorePosition() const
     740                 :            : {
     741                 :          0 :     return static_cast<sal_uInt16>( aModelPositions[ aModelPositions.size()-1 ] );
     742                 :            : }
     743                 :            : 
     744                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10