diff options
author | Daniel Vogelheim <dvo@openoffice.org> | 2002-02-27 16:28:54 +0000 |
---|---|---|
committer | Daniel Vogelheim <dvo@openoffice.org> | 2002-02-27 16:28:54 +0000 |
commit | bbb08df9767e0d6599929e72283caf731280c54c (patch) | |
tree | fbe841267982d37410c55c4e1f6bf5603954d3d2 /sw/source/core/access/accportions.cxx | |
parent | c605b04940e72f0ca43b10bd8f40301e479ad816 (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.cxx | 220 |
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 ); +} |