diff options
author | Frank Meies <fme@openoffice.org> | 2002-02-27 16:06:16 +0000 |
---|---|---|
committer | Frank Meies <fme@openoffice.org> | 2002-02-27 16:06:16 +0000 |
commit | 0af4d64e5842f168f4b806feec806c510118bfb4 (patch) | |
tree | 33ca6561e68e52330bd750308d6adfa6bbc45c24 | |
parent | e08c3172aae4fec8ce9bb562f47f9bc403201274 (diff) |
#95586# Accessibility - Get coordinates for a position inside a paragraph
-rw-r--r-- | sw/inc/crstate.hxx | 49 | ||||
-rw-r--r-- | sw/source/core/text/itrcrsr.cxx | 145 |
2 files changed, 185 insertions, 9 deletions
diff --git a/sw/inc/crstate.hxx b/sw/inc/crstate.hxx index 5af0da7445d2..540bf8e1a5e6 100644 --- a/sw/inc/crstate.hxx +++ b/sw/inc/crstate.hxx @@ -2,9 +2,9 @@ * * $RCSfile: crstate.hxx,v $ * - * $Revision: 1.7 $ + * $Revision: 1.8 $ * - * last change: $Author: ama $ $Date: 2002-02-15 14:33:06 $ + * last change: $Author: fme $ $Date: 2002-02-27 17:06:16 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -110,6 +110,48 @@ struct Sw2LinesPos BYTE nMultiType; // Multiportion type }; +/** + * SwSpecialPos. This structure is used to pass some additional information + * during the call of SwTxtFrm::GetCharRect(). An SwSpecialPos defines a position + * inside a portion which does not have a representation in the core string or + * which is only represented by one position, e.g., field portions, + * number portions, ergo sum and quo vadis portions. + * + * nCharOfst - The offset inside the special portion. Fields and its + * follow fields are treated as one long special portion. + * nLineOfst - The number of lines between the beginning of the special + * portion and nCharOfst. A line offset required to be + * nCharOfst relative to the beginning of the line. + * nExtendRange - Setting this identifies portions which are in front or + * behind the core string (number portion, quo vadis) + * + * Examples 1) + * + * Get the position of the second character inside a number portion: + * nCharOfst = 2; nLineOfst = 0; nExtendRange = SP_EXTEND_RANGE_BEFORE; + * Call SwTxtFrm:::GetCharRect with core string position 0. + * + * Example 2) + * + * Field A - Length = 5 + * Follow field B - Length = 9 + * Get the position of the third character in follow field B, core position + * of field A is 33. + * nCharOfst = 7; nLineOfst = 0; nExtendRange = SP_EXTEND_RANGE_NONE; + * Call SwTxtFrm:::GetCharRect with core string position 33. + */ + +#define SP_EXTEND_RANGE_NONE 0 +#define SP_EXTEND_RANGE_BEFORE 1 +#define SP_EXTEND_RANGE_BEHIND 2 + +struct SwSpecialPos +{ + xub_StrLen nCharOfst; + USHORT nLineOfst; + BYTE nExtendRange; +}; + // CrsrTravelling-Staties (fuer GetCrsrOfst) enum CrsrMoveState { @@ -126,6 +168,7 @@ struct SwCrsrMoveState { SwFillCrsrPos *pFill; // fuer das automatische Auffuellen mit Tabs etc. Sw2LinesPos *p2Lines; // for selections inside/around 2line portions + SwSpecialPos* pSpecialPos; // for positions inside fields Point aRealHeight; // enthaelt dann die Position/Hoehe des Cursors CrsrMoveState eState; BOOL bStop :1; @@ -145,6 +188,7 @@ struct SwCrsrMoveState SwCrsrMoveState( CrsrMoveState eSt = MV_NONE ) : pFill( NULL ), p2Lines( NULL ), + pSpecialPos( NULL ), eState( eSt ), bStop( FALSE ), bRealHeight( FALSE ), @@ -159,6 +203,7 @@ struct SwCrsrMoveState {} SwCrsrMoveState( SwFillCrsrPos *pInitFill ) : pFill( pInitFill ), + pSpecialPos( NULL ), eState( MV_SETONLYTEXT ), bStop( FALSE ), bRealHeight( FALSE ), diff --git a/sw/source/core/text/itrcrsr.cxx b/sw/source/core/text/itrcrsr.cxx index f6aeb0c9312a..eb379fecb794 100644 --- a/sw/source/core/text/itrcrsr.cxx +++ b/sw/source/core/text/itrcrsr.cxx @@ -2,9 +2,9 @@ * * $RCSfile: itrcrsr.cxx,v $ * - * $Revision: 1.41 $ + * $Revision: 1.42 $ * - * last change: $Author: ama $ $Date: 2002-02-15 14:46:19 $ + * last change: $Author: fme $ $Date: 2002-02-27 17:05:19 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -115,10 +115,85 @@ #include <pormulti.hxx> // SwMultiPortion #endif +extern BYTE WhichFont( xub_StrLen nIdx, const String* pTxt, + const SwScriptInfo* pSI ); + // Nicht reentrant !!! // wird in GetCharRect gesetzt und im UnitUp/Down ausgewertet. sal_Bool SwTxtCursor::bRightMargin = sal_False; + +/************************************************************************* + * lcl_GetPositionInsideField + * + * After calculating the position of a character during GetCharRect + * this function allows to find the coordinates of a position (defined + * in pCMS->pSpecialPos) inside a special portion (e.g., a field) + *************************************************************************/ +void lcl_GetPositionInsideField( SwTxtSizeInfo& rInf, SwRect& rOrig, + const SwCrsrMoveState& rCMS, + const SwLinePortion& rPor ) +{ + ASSERT( rCMS.pSpecialPos, "Information about special pos missing" ) + + const USHORT nCharOfst = rCMS.pSpecialPos->nCharOfst; + USHORT nFldIdx = 0; + USHORT nFldLen = 0; + + const XubString* pString = 0; + const SwLinePortion* pPor = &rPor; + do + { + if ( pPor->InFldGrp() ) + { + pString = &((SwFldPortion*)pPor)->GetExp(); + nFldLen = pString->Len(); + } + else + { + pString = 0; + nFldLen = 0; + } + + if ( ! pPor->GetPortion() || nFldIdx + nFldLen > nCharOfst ) + break; + + nFldIdx += nFldLen; + rOrig.Pos().X() += pPor->Width(); + pPor = pPor->GetPortion(); + + } while ( TRUE ); + + ASSERT( nCharOfst >= nFldIdx, "Request of position inside field failed" ) + USHORT nLen = nCharOfst - nFldIdx + 1; + + if ( pString ) + { + // get script for field portion + rInf.GetFont()->SetActual( WhichFont( 0, pString, 0 ) ); + + xub_StrLen nOldLen = pPor->GetLen(); + ((SwLinePortion*)pPor)->SetLen( nLen - 1 ); + const SwTwips nX1 = pPor->GetLen() ? + pPor->GetTxtSize( rInf ).Width() : + 0; + + SwTwips nX2 = 0; + if ( rCMS.bRealWidth ) + { + ((SwLinePortion*)pPor)->SetLen( nLen ); + nX2 = pPor->GetTxtSize( rInf ).Width(); + } + + ((SwLinePortion*)pPor)->SetLen( nOldLen ); + + rOrig.Pos().X() += nX1; + rOrig.Width( ( nX2 > nX1 ) ? + ( nX2 - nX1 ) : + 1 ); + } +} + /************************************************************************* * SwTxtMargin::CtorInit() *************************************************************************/ @@ -366,6 +441,15 @@ void SwTxtCursor::_GetCharRect( SwRect* pOrig, const xub_StrLen nOfst, const Point aCharPos; pOrig->Pos( aCharPos ); pOrig->SSize( aCharSize ); + + // If we are looking for a position inside a field which covers + // more than one line we may not skip any "empty portions" at the + // beginning of a line + const sal_Bool bInsideFirstField = pCMS && pCMS->pSpecialPos && + ( pCMS->pSpecialPos->nLineOfst || + SP_EXTEND_RANGE_BEFORE == + pCMS->pSpecialPos->nExtendRange ); + sal_Bool bWidth = pCMS && pCMS->bRealWidth; if( !pCurr->GetLen() && !pCurr->Width() ) { @@ -396,7 +480,7 @@ void SwTxtCursor::_GetCharRect( SwRect* pOrig, const xub_StrLen nOfst, // 8477: aber auch die einzige Textportion einer leeren Zeile mit // Right/Center-Adjustment! Also nicht nur pPor->GetExpandPortion() ... - while( pPor && !pPor->GetLen() ) + while( pPor && !pPor->GetLen() && ! bInsideFirstField ) { nX += pPor->Width(); if ( pPor->InSpaceGrp() && nSpaceAdd ) @@ -538,6 +622,10 @@ void SwTxtCursor::_GetCharRect( SwRect* pOrig, const xub_StrLen nOfst, } else if( ((SwMultiPortion*)pPor)->IsDouble() ) pCMS->p2Lines->nMultiType = MT_TWOLINE; +#ifdef BIDI + else if( ((SwMultiPortion*)pPor)->IsBidi() ) + pCMS->p2Lines->nMultiType = MT_BIDI; +#endif else pCMS->p2Lines->nMultiType = MT_RUBY; SwTwips nTmpWidth = pPor->Width(); @@ -693,7 +781,15 @@ void SwTxtCursor::_GetCharRect( SwRect* pOrig, const xub_StrLen nOfst, else { pOrig->Pos().Y() += aOldPos.Y(); +#ifdef BIDI + if ( ((SwMultiPortion*)pPor)->IsBidi() ) + pOrig->Pos().X() = nX + pPor->Width() - + pOrig->Pos().X(); + else + pOrig->Pos().X() += nX; +#else pOrig->Pos().X() += nX; +#endif if( ((SwMultiPortion*)pPor)->HasBrackets() ) pOrig->Pos().X() += ((SwDoubleLinePortion*)pPor)->PreWidth(); @@ -771,9 +867,9 @@ void SwTxtCursor::_GetCharRect( SwRect* pOrig, const xub_StrLen nOfst, } } // 8513: Felder im Blocksatz, ueberspringen - while( pPor && !pPor->GetLen() && ( pPor->IsFlyPortion() || - pPor->IsKernPortion() || - ( !bEmptyFld && pPor->InFldGrp() ) ) ) + while( pPor && !pPor->GetLen() && ! bInsideFirstField && + ( pPor->IsFlyPortion() || pPor->IsKernPortion() || + ( !bEmptyFld && pPor->InFldGrp() ) ) ) { if ( pPor->InSpaceGrp() && nSpaceAdd ) nX += pPor->PrtWidth() + @@ -892,6 +988,14 @@ void SwTxtCursor::_GetCharRect( SwRect* pOrig, const xub_StrLen nOfst, } pOrig->Width( nTmp ); } + + // travel inside field portion? + if ( pCMS->pSpecialPos ) + { + // apply attributes to font + Seek( nOfst ); + lcl_GetPositionInsideField( aInf, *pOrig, *pCMS, *pPor ); + } } } pOrig->Pos().X() += nX; @@ -925,13 +1029,35 @@ sal_Bool SwTxtCursor::GetCharRect( SwRect* pOrig, const xub_StrLen nOfst, { CharCrsrToLine(nOfst); + // Indicates that a position inside a special portion (field, number portion) + // is requested. + const sal_Bool bSpecialPos = pCMS && pCMS->pSpecialPos; + xub_StrLen nFindOfst = nOfst; + + if ( bSpecialPos ) + { + xub_StrLen nLineOfst = pCMS->pSpecialPos->nLineOfst; + BYTE nExtendRange = pCMS->pSpecialPos->nExtendRange; + + ASSERT( ! nLineOfst || SP_EXTEND_RANGE_BEFORE != nExtendRange, + "LineOffset AND Number Portion?" ) + + // portions which are behind the string + if ( SP_EXTEND_RANGE_BEHIND == nExtendRange ) + ++nFindOfst; + + // skip lines for fields which cover more than one line + for ( USHORT i = 0; i < pCMS->pSpecialPos->nLineOfst; i++ ) + Next(); + } + // Adjustierung ggf. nachholen GetAdjusted(); const Point aCharPos( GetTopLeft() ); sal_Bool bRet = sal_True; - _GetCharRect( pOrig, nOfst, pCMS ); + _GetCharRect( pOrig, nFindOfst, pCMS ); const SwTwips nRight = Right() - 12; @@ -1276,6 +1402,11 @@ xub_StrLen SwTxtCursor::GetCrsrOfst( SwPosition *pPos, const Point &rPoint, nTmpY = 0; nX = (KSHORT)nTmpY; } +#ifdef BIDI + else if( ((SwMultiPortion*)pPor)->IsBidi() ) + nX = pPor->Width() - nX; +#endif + if( ((SwMultiPortion*)pPor)->HasBrackets() ) { USHORT nPreWidth = ((SwDoubleLinePortion*)pPor)->PreWidth(); |