summaryrefslogtreecommitdiff
path: root/sw/source/core/access/accportions.cxx
diff options
context:
space:
mode:
authorDaniel Vogelheim <dvo@openoffice.org>2002-02-27 16:28:54 +0000
committerDaniel Vogelheim <dvo@openoffice.org>2002-02-27 16:28:54 +0000
commitbbb08df9767e0d6599929e72283caf731280c54c (patch)
treefbe841267982d37410c55c4e1f6bf5603954d3d2 /sw/source/core/access/accportions.cxx
parentc605b04940e72f0ca43b10bd8f40301e479ad816 (diff)
#95586# added support for selection and character bounds
Diffstat (limited to 'sw/source/core/access/accportions.cxx')
-rw-r--r--sw/source/core/access/accportions.cxx220
1 files changed, 207 insertions, 13 deletions
diff --git a/sw/source/core/access/accportions.cxx b/sw/source/core/access/accportions.cxx
index 1e6b4cf2fcca..158a5f550325 100644
--- a/sw/source/core/access/accportions.cxx
+++ b/sw/source/core/access/accportions.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: accportions.cxx,v $
*
- * $Revision: 1.3 $
+ * $Revision: 1.4 $
*
- * last change: $Author: dvo $ $Date: 2002-02-21 14:55:31 $
+ * last change: $Author: dvo $ $Date: 2002-02-27 17:28:54 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -75,7 +75,12 @@
#include <com/sun/star/i18n/Boundary.hpp>
#endif
-// for GetWordBoundary, GetSentenceBoundary:
+#ifndef _TXTTYPES_HXX
+#include <txttypes.hxx>
+#endif
+
+
+// for GetWordBoundary(...), GetSentenceBoundary(...):
#ifndef _BREAKIT_HXX
#include <breakit.hxx>
#endif
@@ -89,6 +94,10 @@
#include <ndtxt.hxx>
#endif
+// for FillSpecialPos(...)
+#ifndef _CRSTATE_HXX
+#include "crstate.hxx"
+#endif
using rtl::OUString;
@@ -109,7 +118,10 @@ SwAccessiblePortionData::SwAccessiblePortionData(
aModelPositions(),
aAccessiblePositions(),
pWords( NULL ),
- pSentences( NULL )
+ pSentences( NULL ),
+ nBeforePortions( 0 ),
+ bLastIsSpecial( sal_False )
+
{
// reserve some space to reduce memory allocations
aLineBreaks.reserve( 5 );
@@ -134,6 +146,10 @@ void SwAccessiblePortionData::Text(USHORT nLength)
DBG_ASSERT( !bFinished, "We are already done!" );
+ // ignore zero-length portions
+ if( nLength == 0 )
+ return;
+
// store 'old' positions
aModelPositions.push_back( nModelPosition );
aAccessiblePositions.push_back( aBuffer.getLength() );
@@ -141,26 +157,49 @@ void SwAccessiblePortionData::Text(USHORT nLength)
// update buffer + nModelPosition
aBuffer.append( sModelString.copy(nModelPosition, nLength) );
nModelPosition += nLength;
+
+ bLastIsSpecial = sal_False;
}
void SwAccessiblePortionData::Special(
USHORT nLength, const String& rText, USHORT nType)
{
DBG_ASSERT( nLength >= 0, "illegal length" );
+ DBG_ASSERT( nModelPosition >= 0, "illegal position" );
DBG_ASSERT( (nModelPosition + nLength) <= sModelString.getLength(),
"portion exceeds model string!" )
DBG_ASSERT( !bFinished, "We are already done!" );
- // for now, ignore the nType variable
+ // ignore zero/zero portions (except our terminators)
+ if( (nLength == 0) && (rText.Len() == 0) && (nType != 0) )
+ return;
- // store 'old' positions
+ // special case portions: (none so far)
+ // switch( nType )
+ // {
+ // default:
+ // break;
+ // }
+
+ // special treatment for zero length portion at the beginning:
+ // count as 'before' portion
+ if( ( nLength == 0 ) && ( nModelPosition == 0 ) )
+ nBeforePortions++;
+
+ // the default case: store the 'old' positions (and previous for
+ // zero-length portions)
aModelPositions.push_back( nModelPosition );
aAccessiblePositions.push_back( aBuffer.getLength() );
// update buffer + nModelPosition
aBuffer.append( OUString(rText) );
nModelPosition += nLength;
+
+ // remember 'last' special portion (unless it's our own 'closing'
+ // portions from 'Finish()'
+ if( nType != 0 )
+ bLastIsSpecial = sal_True;
}
void SwAccessiblePortionData::LineBreak()
@@ -185,8 +224,8 @@ void SwAccessiblePortionData::Finish()
// include terminator values: always include two 'last character'
// markers in the position arrays to make sure we always find one
// position before the end
- Text( 0 );
- Text( 0 );
+ Special( 0, String(), 0 );
+ Special( 0, String(), 0 );
LineBreak();
LineBreak();
@@ -226,7 +265,7 @@ USHORT SwAccessiblePortionData::GetModelPosition( sal_Int32 nPos )
// else return that position
if( (nEndPos - nStartPos) > 1 )
{
- // 'wide' portions have to be of the same with
+ // 'wide' portions have to be of the same width
DBG_ASSERT( ( nEndPos - nStartPos ) ==
( aAccessiblePositions[nPortionNo+1] -
aAccessiblePositions[nPortionNo] ),
@@ -238,7 +277,7 @@ USHORT SwAccessiblePortionData::GetModelPosition( sal_Int32 nPos )
// else: return startPos unmodified
DBG_ASSERT( (nStartPos >= 0) && (nStartPos < USHRT_MAX),
- "Why can the SwTxtNode have so many characters?" );
+ "How can the SwTxtNode have so many characters?" );
return static_cast<USHORT>(nStartPos);
}
@@ -309,6 +348,19 @@ size_t SwAccessiblePortionData::FindBreak(
return nMin;
}
+size_t SwAccessiblePortionData::FindLastBreak(
+ const Positions_t& rPositions,
+ sal_Int32 nValue )
+{
+ size_t nResult = FindBreak( rPositions, nValue );
+
+ // skip 'zero-length' portions
+ while( rPositions[nResult+1] <= nValue )
+ nResult++;
+
+ return nResult;
+}
+
void SwAccessiblePortionData::GetWordBoundary(
Boundary& rBound,
@@ -391,12 +443,16 @@ void SwAccessiblePortionData::GetSentenceBoundary(
USHORT nModelPos = GetModelPosition( nCurrent );
- nCurrent = pBreakIt->xBreak->endOfSentence(
+ sal_Int32 nNew = pBreakIt->xBreak->endOfSentence(
sAccessibleString, nCurrent,
pBreakIt->GetLocale( pNode->GetLang( nModelPos ) ) ) + 1;
- if( (nCurrent < 0) && (nCurrent > nLength) )
- nCurrent = nLength;
+ if( (nNew < 0) && (nNew > nLength) )
+ nNew = nLength;
+ else if (nNew <= nCurrent)
+ nNew = nCurrent + 1; // ensure forward progress
+
+ nCurrent = nNew;
}
while (nCurrent < nLength);
@@ -415,3 +471,141 @@ void SwAccessiblePortionData::GetSentenceBoundary(
FillBoundary( rBound, *pSentences, FindBreak( *pSentences, nPos ) );
}
+
+sal_Int32 SwAccessiblePortionData::GetAccessiblePosition( USHORT nPos )
+{
+ DBG_ASSERT( nPos <= sModelString.getLength(), "illegal position" );
+
+ // find the portion number
+ size_t nPortionNo = FindBreak( aModelPositions,
+ static_cast<sal_Int32>(nPos) );
+
+ sal_Int32 nRet = aAccessiblePositions[nPortionNo];
+
+ // if the model portion has more than one position, go into it;
+ // else return that position
+ sal_Int32 nStartPos = aModelPositions[nPortionNo];
+ sal_Int32 nEndPos = aModelPositions[nPortionNo+1];
+ if( (nEndPos - nStartPos) > 1 )
+ {
+ // 'wide' portions have to be of the same width
+ DBG_ASSERT( ( nEndPos - nStartPos ) ==
+ ( aAccessiblePositions[nPortionNo+1] -
+ aAccessiblePositions[nPortionNo] ),
+ "accesability portion disagrees with text model" );
+
+ sal_Int32 nWithinPortion = nPos - aModelPositions[nPortionNo];
+ nRet += nWithinPortion;
+ }
+ // else: return nRet unmodified
+
+ DBG_ASSERT( (nRet >= 0) && (nRet <= sAccessibleString.getLength()),
+ "too long!" );
+ return nRet;
+}
+
+sal_Int32 SwAccessiblePortionData::GetLineNumber( sal_Int32 nPos )
+{
+ size_t nPortionNo = FindBreak( aLineBreaks, nPos );
+ return nPortionNo;
+}
+
+
+
+USHORT SwAccessiblePortionData::FillSpecialPos(
+ sal_Int32 nPos,
+ SwSpecialPos& rPos,
+ SwSpecialPos*& rpPos )
+{
+ size_t nPortionNo = FindLastBreak( aAccessiblePositions, nPos );
+
+ BYTE nExtend;
+ sal_Int32 nRefPos;
+ sal_Int32 nModelPos;
+
+ if( nPortionNo < nBeforePortions )
+ {
+ nExtend = SP_EXTEND_RANGE_BEFORE;
+ nModelPos = 0;
+ nRefPos = 0;
+ rpPos = &rPos;
+ }
+ else
+ {
+ sal_Int32 nModelEndPos = aModelPositions[nPortionNo+1];
+ nModelPos = aModelPositions[nPortionNo];
+
+ // skip backwards over zero-length portions, since GetCharRect()
+ // counts all model-zero-length portions as belonging to the
+ // previus portion
+ size_t nCorePortionNo = nPortionNo;
+ while( nModelPos == nModelEndPos )
+ {
+ nCorePortionNo--;
+ nModelEndPos = nModelPos;
+ nModelPos = aModelPositions[nCorePortionNo];
+
+ DBG_ASSERT( nModelPos >= 0, "Can't happen." );
+ DBG_ASSERT( nCorePortionNo >= nBeforePortions, "Can't happen." );
+ }
+ DBG_ASSERT( nModelPos != nModelEndPos,
+ "portion with core-representation expected" );
+
+ // if we have anything except plain text, compute nExtend + nRefPos
+ if( (nModelEndPos - nModelPos == 1) &&
+ (sModelString.getStr()[nModelPos] !=
+ sAccessibleString.getStr()[nPos]) )
+ {
+ // case 1: a one-character, non-text portion
+ // reference position is the first accessibilty for our
+ // core portion
+ nRefPos = aAccessiblePositions[ nCorePortionNo ];
+ nExtend = SP_EXTEND_RANGE_NONE;
+ rpPos = &rPos;
+ }
+ else if(nPortionNo != nCorePortionNo)
+ {
+ // case 2: a multi-character (text!) portion, followed by
+ // zero-length portions
+ // reference position is the first character of the next
+ // portion, and we are 'behind'
+ nRefPos = aAccessiblePositions[ nCorePortionNo+1 ];
+ nExtend = SP_EXTEND_RANGE_BEHIND;
+ rpPos = &rPos;
+ }
+ else
+ {
+ // case 3: regular text portion
+ DBG_ASSERT( ( nModelEndPos - nModelPos ) ==
+ ( aAccessiblePositions[nPortionNo+1] -
+ aAccessiblePositions[nPortionNo] ),
+ "text portion expected" );
+
+ nModelPos += nPos - aAccessiblePositions[ nPortionNo ];
+ rpPos = NULL;
+ }
+ }
+ if( rpPos != NULL )
+ {
+ DBG_ASSERT( rpPos == &rPos, "Yes!" );
+ DBG_ASSERT( nRefPos <= nPos, "wrong reference" );
+ DBG_ASSERT( (nExtend == SP_EXTEND_RANGE_NONE) ||
+ (nExtend == SP_EXTEND_RANGE_BEFORE) ||
+ (nExtend == SP_EXTEND_RANGE_BEHIND), "need extend" );
+
+ // get the line number, and adjust nRefPos for the line
+ // (if necessary)
+ size_t nRefLine = FindBreak( aLineBreaks, nRefPos );
+ size_t nMyLine = FindBreak( aLineBreaks, nPos );
+ USHORT nLineOffset = static_cast<USHORT>( nMyLine - nRefLine );
+ if( nLineOffset != 0 )
+ nRefPos = aLineBreaks[ nMyLine ];
+
+ // fill char offset and 'special position'
+ rPos.nCharOfst = static_cast<USHORT>( nPos - nRefPos );
+ rPos.nExtendRange = nExtend;
+ rPos.nLineOfst = nLineOffset;
+ }
+
+ return static_cast<USHORT>( nModelPos );
+}