diff -rup /cygdrive/c/Users/Henner/Downloads/OOSource/OOH680_m12/sw/source/core/inc/scriptinfo.hxx core/inc/scriptinfo.hxx --- /cygdrive/c/Users/Henner/Downloads/OOSource/OOH680_m12/sw/source/core/inc/scriptinfo.hxx 2007-09-27 08:58:02.000000000 +0000 +++ core/inc/scriptinfo.hxx 2008-04-26 11:51:17.084000000 +0000 @@ -107,6 +107,7 @@ private: SvXub_StrLens aDirChg; SvBytes aDirType; SvXub_StrLens aKashida; + SvXub_StrLens aKashidaInvalid; SvXub_StrLens aCompChg; SvXub_StrLens aCompLen; SvXub_StrLens aHiddenChg; @@ -116,6 +117,10 @@ private: void UpdateBidiInfo( const String& rTxt ); + sal_Bool IsKashidaValid ( xub_StrLen nKashPos ) const; + void MarkKashidaInvalid ( xub_StrLen nKashPos ); + void ClearKashidaInvalid ( xub_StrLen nKashPos ); + public: enum CompType { KANA, SPECIAL_LEFT, SPECIAL_RIGHT, NONE }; @@ -263,9 +268,24 @@ public: The value which has to be added to a kashida opportunity. @return The number of kashida opportunities in the given range */ - USHORT KashidaJustify( sal_Int32* pKernArray ,sal_Int32* pScrArray, - xub_StrLen nIdx, xub_StrLen nLen, - long nSpaceAdd = 0 ) const; + USHORT KashidaJustify( sal_Int32* pKernArray, sal_Int32* pScrArray, + xub_StrLen nStt, xub_StrLen nLen, + long nSpaceAdd = 0) const; + +/** Marks a kashida as invalid for the given text range. + returns true if a kashida was marked invalid +*/ + bool MarkKashidaInvalid ( xub_StrLen nStt, xub_StrLen nLen ); + +/** Clears array of kashidas marked as invalid +*/ + void ClearKashidaInvalid ( xub_StrLen nStt, xub_StrLen nLen ); + +/** Count kashida in text range +*/ + + USHORT CountKashidaInRange ( xub_StrLen nStt, xub_StrLen nLen ); + /** Checks if language is one of the 16 Arabic languages @@ -303,6 +323,7 @@ public: sal_Bool bAllowInvalid = sal_False ); static BYTE WhichFont( xub_StrLen nIdx, const String* pTxt, const SwScriptInfo* pSI ); + }; inline void SwScriptInfo::SetInvalidity( const xub_StrLen nPos ) diff -rup /cygdrive/c/Users/Henner/Downloads/OOSource/OOH680_m12/sw/source/core/text/itradj.cxx core/text/itradj.cxx --- /cygdrive/c/Users/Henner/Downloads/OOSource/OOH680_m12/sw/source/core/text/itradj.cxx 2007-09-27 09:13:31.000000000 +0000 +++ core/text/itradj.cxx 2008-04-25 20:53:23.367000000 +0000 @@ -54,6 +54,8 @@ #include #endif +#include + #define MIN_TAB_WIDTH 60 /************************************************************************* @@ -154,6 +156,18 @@ void SwTxtAdjuster::CalcNewBlock( SwLine xub_StrLen nCharCnt = 0; MSHORT nSpaceIdx = 0; + SwScriptInfo& rSI = GetInfo().GetParaPortion()->GetScriptInfo(); + SwTxtSizeInfo aInf ( GetTxtFrm() ); + SwTxtIter aItr ( GetTxtFrm(), &aInf ); + + if ( rSI.CountKashida() ) + { + while (aItr.GetCurr() != pCurrent && aItr.GetNext()) + aItr.Next(); + ASSERT ( aItr.GetCurr() == pCurrent, "CalcNewBlock: kashida iterator at wrong line"); + rSI.ClearKashidaInvalid ( aItr.GetStart(), aItr.GetLength() ); + } + // Nicht vergessen: // CalcRightMargin() setzt pCurrent->Width() auf die Zeilenbreite ! CalcRightMargin( pCurrent, nReal ); @@ -210,7 +224,52 @@ void SwTxtAdjuster::CalcNewBlock( SwLine if( nGluePortion ) { - const long nSpaceAdd = nGluePortionWidth / nGluePortion; + long nSpaceAdd = nGluePortionWidth / nGluePortion; + + // validate or recalculate for Kashida justification + if ( rSI.CountKashida() ) + { + xub_StrLen nIdx = aItr.GetStart(); + xub_StrLen nEnd = aItr.GetEnd(); + + xub_StrLen nKashidas = rSI.CountKashidaInRange ( aItr.GetStart(), aItr.GetLength() ); + + bool bAddSpaceChanged; + while ( nKashidas ) + { + bAddSpaceChanged = false; + nIdx = aItr.GetStart(); + aItr.SeekAndChgAttrIter( nIdx, aInf.GetOut() ); + + while ( nIdx < nEnd ) + { + long nFontMinKashida = aInf.GetOut()->GetMinKashida(); + if ( nFontMinKashida ) + { + while ( nKashidas && nGluePortion > 1 && + nSpaceAdd / SPACING_PRECISION_FACTOR < nFontMinKashida ) + { + if ( rSI.MarkKashidaInvalid(aItr.GetStart(), aItr.GetLength()) ) + { + --nGluePortion; + --nKashidas; + nSpaceAdd = nGluePortionWidth / nGluePortion; + bAddSpaceChanged = true; + } + } + } + if ( bAddSpaceChanged ) + break; // start all over again + nIdx = aItr.GetNextAttr(); + if ( nIdx != STRING_LEN ) + aItr.SeekAndChgAttrIter( nIdx, aInf.GetOut() ); + } + + if ( !bAddSpaceChanged ) + break; + } + } + pCurrent->SetLLSpaceAdd( nSpaceAdd , nSpaceIdx ); pPos->Width( ( (SwGluePortion*)pPos )->GetFixWidth() ); } diff -rup /cygdrive/c/Users/Henner/Downloads/OOSource/OOH680_m12/sw/source/core/text/porlay.cxx core/text/porlay.cxx --- /cygdrive/c/Users/Henner/Downloads/OOSource/OOH680_m12/sw/source/core/text/porlay.cxx 2007-09-27 09:17:13.000000000 +0000 +++ core/text/porlay.cxx 2008-04-25 20:17:07.137979500 +0000 @@ -113,6 +113,104 @@ using namespace i18n::ScriptType; //#ifdef BIDI #include +sal_Bool isAlefChar ( xub_Unicode cCh ) +{ + return ( cCh == 0x622 || cCh == 0x623 || cCh == 0x625 || cCh == 0x627 || + cCh == 0x622 || cCh == 0x671 || cCh == 0x672 || cCh == 0x673 || cCh == 0x675 ); +} + +sal_Bool isWawChar ( xub_Unicode cCh ) +{ + return ( cCh == 0x624 || cCh == 0x648 || cCh == 0x676 || cCh == 0x677 || + ( cCh >= 0x6C4 && cCh <= 0x6CB ) || cCh == 0x6CF ); +} + +sal_Bool isDalChar ( xub_Unicode cCh ) +{ + return ( cCh == 0x62F || cCh == 0x630 || cCh == 0x688 || cCh == 0x689 || cCh == 0x690 ); +} + +sal_Bool isRehChar ( xub_Unicode cCh ) +{ + return ( cCh == 0x631 || cCh == 0x632 || ( cCh >= 0x691 && cCh <= 0x699 )); +} + +sal_Bool isTehMarbutaChar ( xub_Unicode cCh ) +{ + return ( cCh == 0x629 || cCh == 0x6C0 ); +} + +sal_Bool isBaaChar ( xub_Unicode cCh ) +{ + return ( cCh == 0x628 || cCh == 0x62A || cCh == 0x62B || cCh == 0x679 || cCh == 0x680 ); +} + +sal_Bool isYehChar ( xub_Unicode cCh ) +{ + return ( cCh == 0x626 || cCh == 0x649 || cCh == 0x64A || cCh == 0x678 || cCh == 0x6CC || + cCh == 0x6CE || cCh == 0x6D0 || cCh == 0x6D1 ); +} + +sal_Bool isSeenOrSadChar ( xub_Unicode cCh ) +{ + return ( ( cCh >= 0x633 && cCh <= 0x636 ) || ( cCh >= 0x69A && cCh <= 0x69E ) + || cCh == 0x6FA || cCh == 0x6FB ); +} + +sal_Bool isHahChar ( xub_Unicode cCh ) +{ + return ( ( cCh >= 0x62C && cCh <= 0x62E ) || ( cCh >= 0x681 && cCh <= 0x687 ) + || cCh == 0x6BF ); +} + +sal_Bool isTahChar ( xub_Unicode cCh ) +{ + return ( cCh == 0x637 || cCh == 0x638 || cCh == 0x69F ); +} + +sal_Bool isAinChar ( xub_Unicode cCh ) +{ + return ( cCh == 0x639 || cCh == 0x63A || cCh == 0x6A0 || cCh == 0x6FC ); +} + +sal_Bool isKafChar ( xub_Unicode cCh ) +{ + return ( cCh == 0x643 || ( cCh >= 0x6AC && cCh <= 0x6AE ) ); +} + +sal_Bool isLamChar ( xub_Unicode cCh ) +{ + return ( cCh == 0x644 || ( cCh >= 0x6B5 && cCh <= 0x6B8 ) ); +} + +sal_Bool isGafChar ( xub_Unicode cCh ) +{ + return ( cCh == 0x6A9 || cCh == 0x6AB ||( cCh >= 0x6AF && cCh <= 0x6B4 ) ); +} + +sal_Bool isQafChar ( xub_Unicode cCh ) +{ + return ( cCh == 0x642 || cCh == 0x6A7 || cCh == 0x6A8 ); +} + +sal_Bool isFeChar ( xub_Unicode cCh ) +{ + return ( cCh == 0x641 || ( cCh >= 0x6A1 && cCh <= 0x6A6 ) ); +} + +sal_Bool isTransparentChar ( xub_Unicode cCh ) +{ + return ( ( cCh >= 0x610 && cCh <= 0x61A ) || + ( cCh >= 0x64B && cCh <= 0x65E ) || + ( cCh == 0x670 ) || + ( cCh >= 0x6D6 && cCh <= 0x6DC ) || + ( cCh >= 0x6DF && cCh <= 0x6E4 ) || + ( cCh >= 0x6E7 && cCh <= 0x6E8 ) || + ( cCh >= 0x6EA && cCh <= 0x6ED )); + + +} + /************************************************************************* * lcl_IsLigature * @@ -127,6 +225,8 @@ sal_Bool lcl_IsLigature( xub_Unicode cCh ( 0x628 == cCh && 0x631 == cNextCh ); } + + /************************************************************************* * lcl_ConnectToPrev * @@ -142,13 +242,16 @@ sal_Bool lcl_ConnectToPrev( xub_Unicode sal_Bool bRet = 0x628 == cPrevCh || ( 0x62A <= cPrevCh && cPrevCh <= 0x62E ) || ( 0x633 <= cPrevCh && cPrevCh <= 0x643 ) || + 0x644 == cPrevCh || // Lam does connect !!! ( 0x645 <= cPrevCh && cPrevCh <= 0x647 ) || + 0x649 == cPrevCh || // Alef Maksura does connect !!! 0x64A == cPrevCh || ( 0x678 <= cPrevCh && cPrevCh <= 0x687 ) || ( 0x69A <= cPrevCh && cPrevCh <= 0x6B4 ) || ( 0x6B9 <= cPrevCh && cPrevCh <= 0x6C0 ) || ( 0x6C3 <= cPrevCh && cPrevCh <= 0x6D3 ); + // check for ligatures cPrevChar + cChar if ( bRet ) bRet = ! lcl_IsLigature( cPrevCh, cCh ); @@ -713,6 +816,7 @@ BYTE SwScriptInfo::WhichFont( xub_StrLen return SW_LATIN; } + /************************************************************************* * SwScriptInfo::InitScriptInfo() * @@ -882,6 +986,9 @@ void SwScriptInfo::InitScriptInfo( const // remove invalid entries from kashida array aKashida.Remove( nCntKash, aKashida.Count() - nCntKash ); + // todo: remove only invalid range ? + aKashidaInvalid.Remove (0, aKashidaInvalid.Count () ); + // // TAKE CARE OF WEAK CHARACTERS: WE MUST FIND AN APPROPRIATE // SCRIPT FOR WEAK CHARACTERS AT THE BEGINNING OF A PARAGRAPH @@ -1025,93 +1132,145 @@ void SwScriptInfo::InitScriptInfo( const xub_StrLen nKashidaPos = STRING_LEN; xub_Unicode cCh; xub_Unicode cPrevCh = 0; - - while ( nIdx < rWord.Len() ) - { - cCh = rWord.GetChar( nIdx ); - - // 1. Priority: - // after user inserted kashida + USHORT nPriorityLevel = 7; // 0..6 = level found + // 7 not found + while (nIdx < rWord.Len()) + { + cCh = rWord.GetChar( nIdx ); + // 1. Priority: + // after user inserted kashida if ( 0x640 == cCh ) - { - nKashidaPos = aScanner.GetBegin() + nIdx; - break; - } - - // 2. Priority: - // after a Seen or Sad - if ( nIdx + 1 < rWord.Len() && - ( 0x633 == cCh || 0x635 == cCh ) ) - { - nKashidaPos = aScanner.GetBegin() + nIdx; - break; - } - - // 3. Priority: - // before final form of Teh Marbuta, Hah, Dal - // 4. Priority: - // before final form of Alef, Lam or Kaf - if ( nIdx && nIdx + 1 == rWord.Len() && - ( 0x629 == cCh || 0x62D == cCh || 0x62F == cCh || - 0x627 == cCh || 0x644 == cCh || 0x643 == cCh ) ) - { - ASSERT( 0 != cPrevCh, "No previous character" ) - - // check if character is connectable to previous character, - if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) - { - nKashidaPos = aScanner.GetBegin() + nIdx - 1; - break; - } - } - - // 5. Priority: - // before media Bah - if ( nIdx && nIdx + 1 < rWord.Len() && 0x628 == cCh ) - { - ASSERT( 0 != cPrevCh, "No previous character" ) - - // check if next character is Reh, Yeh or Alef Maksura - xub_Unicode cNextCh = rWord.GetChar( nIdx + 1 ); + { + nKashidaPos = aScanner.GetBegin() + nIdx; + nPriorityLevel = 0; + } + + // 2. Priority: + // after a Seen or Sad + if (nPriorityLevel >= 1 && nIdx < rWord.Len() - 1) + { + if ( isSeenOrSadChar ( cCh ) ) + { + nKashidaPos = aScanner.GetBegin() + nIdx; + nPriorityLevel = 1; + } + } + // 3. Priority: + // before final form of Teh Marbuta, Hah, Dal + if ( nPriorityLevel >= 2 && nIdx > 0 ) + { + if ( isTehMarbutaChar ( cCh ) || // Teh Marbuta (right joining) + isDalChar ( cCh ) || // Dal (right joining) final form may appear in the middle of word + ( isHahChar ( cCh ) && nIdx == rWord.Len() - 1)) // Hah (dual joining) only at end of word + { + + ASSERT( 0 != cPrevCh, "No previous character" ) + // check if character is connectable to previous character, + if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) + { + nKashidaPos = aScanner.GetBegin() + nIdx - 1; + nPriorityLevel = 2; + } + } + } - if ( 0x631 == cNextCh || 0x64A == cNextCh || - 0x649 == cNextCh ) - { - // check if character is connectable to previous character, - if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) - nKashidaPos = aScanner.GetBegin() + nIdx - 1; - } + // 4. Priority: + // before final form of Alef, Lam or Kaf + if ( nPriorityLevel >= 3 && nIdx > 0 ) + { + if ( isAlefChar ( cCh ) || // Alef (right joining) final form may appear in the middle of word + (( isLamChar ( cCh ) || // Lam + isKafChar ( cCh ) || // Kaf (both dual joining) + isGafChar ( cCh ) ) + && nIdx == rWord.Len() - 1)) // only at end of word + { + ASSERT( 0 != cPrevCh, "No previous character" ) + // check if character is connectable to previous character, + if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) + { + nKashidaPos = aScanner.GetBegin() + nIdx - 1; + nPriorityLevel = 3; + } + } + } + + // 5. Priority: + // before media Bah + + if ( nPriorityLevel >= 4 && nIdx > 0 && nIdx < rWord.Len() - 1 ) + { + if ( isBaaChar ( cCh )) // Bah + { + // check if next character is Reh, Yeh or Alef Maksura + xub_Unicode cNextCh = rWord.GetChar( nIdx + 1 ); + if ( isRehChar ( cNextCh ) || isYehChar ( cNextCh )) + { + ASSERT( 0 != cPrevCh, "No previous character" ) + // check if character is connectable to previous character, + if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) + { + nKashidaPos = aScanner.GetBegin() + nIdx - 1; + nPriorityLevel = 4; + } + } + } } - // 6. Priority: - // other connecting possibilities - if ( nIdx && nIdx + 1 == rWord.Len() && - 0x60C <= cCh && 0x6FE >= cCh ) - { - ASSERT( 0 != cPrevCh, "No previous character" ) - - // check if character is connectable to previous character, - if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) - { - // only choose this position if we did not find - // a better one: - if ( STRING_LEN == nKashidaPos ) - nKashidaPos = aScanner.GetBegin() + nIdx - 1; - break; - } - } + // 6. Priority: + // before the final form of Waw, Ain, Qaf and Fa + + if ( nPriorityLevel >= 5 && nIdx > 0 ) + { + if ( isWawChar ( cCh ) || // Wav (right joining) + // final form may appear in the middle of word + (( isAinChar ( cCh ) || // Ain (dual joining) + isQafChar ( cCh ) || // Qaf (dual joining) + isFeChar ( cCh ) ) // Feh (dual joining) + && nIdx == rWord.Len() - 1)) // only at end of word + { + ASSERT( 0 != cPrevCh, "No previous character" ) + // check if character is connectable to previous character, + if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) + { + nKashidaPos = aScanner.GetBegin() + nIdx - 1; + nPriorityLevel = 5; + } + } + } + + // other connecting possibilities + if ( nPriorityLevel >= 6 && nIdx > 0 ) + { + // remaining right joiners + // Reh, Zain, Thal, + if ( isRehChar ( cCh ) || // Reh Zain (right joining) + // final form may appear in the middle of word + ( 0x60C <= cCh && 0x6FE >= cCh // all others + && nIdx == rWord.Len() - 1)) // only at end of word + { + ASSERT( 0 != cPrevCh, "No previous character" ) + // check if character is connectable to previous character, + if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) + { + nKashidaPos = aScanner.GetBegin() + nIdx - 1; + nPriorityLevel = 6; + } + } + } - // Do not consider Fathatan, Dammatan, Kasratan, Fatha, + // Do not consider Fathatan, Dammatan, Kasratan, Fatha, // Damma, Kasra, Shadda and Sukun when checking if // a character can be connected to previous character. - if ( cCh < 0x64B || cCh > 0x652 ) + if ( !isTransparentChar ( cCh) ) cPrevCh = cCh; - ++nIdx; - } // end of current word + ++nIdx; + } // end of current word if ( STRING_LEN != nKashidaPos ) - aKashida.Insert( nKashidaPos, nCntKash++ ); + { + aKashida.Insert( nKashidaPos, nCntKash++ ); + } } // end of kashida search } @@ -1702,13 +1861,15 @@ long SwScriptInfo::Compress( sal_Int32* * SwScriptInfo::KashidaJustify() *************************************************************************/ -USHORT SwScriptInfo::KashidaJustify( sal_Int32* pKernArray, sal_Int32* pScrArray, - xub_StrLen nStt, xub_StrLen nLen, - long nSpaceAdd ) const +USHORT SwScriptInfo::KashidaJustify( sal_Int32* pKernArray, + sal_Int32* pScrArray, + xub_StrLen nStt, + xub_StrLen nLen, + long nSpaceAdd ) const { ASSERT( nLen, "Kashida justification without text?!" ) - // evaluate kashida informatin in collected in SwScriptInfo + // evaluate kashida information in collected in SwScriptInfo USHORT nCntKash = 0; while( nCntKash < CountKashida() ) @@ -1721,50 +1882,60 @@ USHORT SwScriptInfo::KashidaJustify( sal const xub_StrLen nEnd = nStt + nLen; - if ( ! pKernArray ) + + USHORT nCntKashEnd = nCntKash; + while ( nCntKashEnd < CountKashida() ) { - USHORT nCntKashEnd = nCntKash; - while ( nCntKashEnd < CountKashida() ) - { - if ( nEnd <= GetKashida( nCntKashEnd ) ) - break; - else - nCntKashEnd++; - } - - return nCntKashEnd - nCntKash; + if ( nEnd <= GetKashida( nCntKashEnd ) ) + break; + else + nCntKashEnd++; } + + USHORT nActualKashCount = nCntKashEnd - nCntKash; + for ( USHORT i = nCntKash; i < nCntKashEnd; ++i ) + { + if ( nActualKashCount && !IsKashidaValid ( i ) ) + --nActualKashCount; + + } - // do nothing if there is no more kashida - if ( nCntKash < CountKashida() ) - { - xub_StrLen nKashidaPos = GetKashida( nCntKash ); - xub_StrLen nIdx = nKashidaPos; - long nKashAdd = nSpaceAdd; - - while ( nIdx < nEnd ) - { - USHORT nArrayPos = nIdx - nStt; - - // next kashida position - nIdx = ++nCntKash < CountKashida() ? GetKashida( nCntKash ) : nEnd; - if ( nIdx > nEnd ) - nIdx = nEnd; + if ( !pKernArray ) + return nActualKashCount; - const USHORT nArrayEnd = nIdx - nStt; + // do nothing if there is no more kashida + if ( nCntKash < CountKashida() ) + { + while ( ! IsKashidaValid ( nCntKash ) && nCntKash < nCntKashEnd ) + ++nCntKash; + xub_StrLen nKashidaPos = GetKashida( nCntKash ); + xub_StrLen nIdx = nKashidaPos; + long nKashAdd = nSpaceAdd; + + while ( nIdx < nEnd ) + { + USHORT nArrayPos = nIdx - nStt; - while ( nArrayPos < nArrayEnd ) - { - pKernArray[ nArrayPos ] += nKashAdd; - if ( pScrArray ) - pScrArray[ nArrayPos ] += nKashAdd; - ++nArrayPos; - } + // next kashida position + ++nCntKash; + while ( ! IsKashidaValid ( nCntKash ) && nCntKash < nCntKashEnd ) + ++nCntKash; + nIdx = nCntKash < CountKashida() && IsKashidaValid ( nCntKash ) ? GetKashida( nCntKash ) : nEnd; + if ( nIdx > nEnd ) + nIdx = nEnd; - nKashAdd += nSpaceAdd; - } - } + const USHORT nArrayEnd = nIdx - nStt; + while ( nArrayPos < nArrayEnd ) + { + pKernArray[ nArrayPos ] += nKashAdd; + if ( pScrArray ) + pScrArray[ nArrayPos ] += nKashAdd; + ++nArrayPos; + } + nKashAdd += nSpaceAdd; + } + } return 0; } @@ -1786,6 +1957,128 @@ sal_Bool SwScriptInfo::IsArabicLanguage( } /************************************************************************* + * SwScriptInfo::IsKashidaValid() + *************************************************************************/ + +sal_Bool SwScriptInfo::IsKashidaValid ( xub_StrLen nKashPos ) const +{ + for ( xub_StrLen i = 0; i < aKashidaInvalid.Count(); ++i ) + { + if ( aKashidaInvalid [ i ] == nKashPos ) + return false; + } + return true; +} + +/************************************************************************* + * SwScriptInfo::ClearKashidaInvalid() + *************************************************************************/ + +void SwScriptInfo::ClearKashidaInvalid ( xub_StrLen nStt, xub_StrLen nLen ) +{ + if ( !aKashidaInvalid.Count() ) + return; + USHORT nCntKash = 0; + while( nCntKash < CountKashida() ) + { + if ( nStt <= GetKashida( nCntKash ) ) + break; + else + nCntKash++; + } + + const xub_StrLen nEnd = nStt + nLen; + + while ( nCntKash < CountKashida() ) + { + if ( nEnd <= GetKashida( nCntKash ) ) + break; + else + { + ClearKashidaInvalid ( nCntKash ); + nCntKash++; + } + } +} + + +void SwScriptInfo::ClearKashidaInvalid ( xub_StrLen nKashPos ) +{ + for ( xub_StrLen i = 0; i < aKashidaInvalid.Count(); ++i ) + { + if ( aKashidaInvalid [ i ] == nKashPos ) + { + aKashidaInvalid.Remove (i, 1); + return; + } + } +} + +/************************************************************************* + * SwScriptInfo::MarkKashidaInvalid() + * + *************************************************************************/ + +bool SwScriptInfo::MarkKashidaInvalid ( xub_StrLen nStt, xub_StrLen nLen ) +{ + USHORT nCntKash = 0; + while( nCntKash < CountKashida() ) + { + if ( nStt <= GetKashida( nCntKash ) ) + break; + else + nCntKash++; + } + + const xub_StrLen nEnd = nStt + nLen; + + while ( nCntKash < CountKashida() ) + { + if ( nEnd <= GetKashida( nCntKash ) ) + break; + else + { + if ( IsKashidaValid ( nCntKash ) ) + { + MarkKashidaInvalid ( nCntKash ); + return true; + } + nCntKash++; + } + } + return false; +} + +void SwScriptInfo::MarkKashidaInvalid ( xub_StrLen nKashPos ) +{ + aKashidaInvalid.Insert( nKashPos, aKashidaInvalid.Count() ); +} + +USHORT SwScriptInfo::CountKashidaInRange ( xub_StrLen nStt, xub_StrLen nLen ) +{ + USHORT nCntKash = 0; + while( nCntKash < CountKashida() ) + { + if ( nStt <= GetKashida( nCntKash ) ) + break; + else + nCntKash++; + } + + const xub_StrLen nEnd = nStt + nLen; + + USHORT nCntKashEnd = nCntKash; + while ( nCntKashEnd < CountKashida() ) + { + if ( nEnd <= GetKashida( nCntKashEnd ) ) + break; + else + nCntKashEnd++; + } + return nCntKashEnd - nCntKash; +} + +/************************************************************************* * SwScriptInfo::ThaiJustify() *************************************************************************/ diff -rup /cygdrive/c/Users/Henner/Downloads/OOSource/OOH680_m12/sw/source/core/txtnode/fntcache.cxx core/txtnode/fntcache.cxx --- /cygdrive/c/Users/Henner/Downloads/OOSource/OOH680_m12/sw/source/core/txtnode/fntcache.cxx 2008-01-15 07:51:39.000000000 +0000 +++ core/txtnode/fntcache.cxx 2008-04-11 07:03:00.451000000 +0000 @@ -887,6 +887,11 @@ static sal_Bool lcl_IsMonoSpaceFont( con return nWidth1 == nWidth2; } +sal_Bool isCharArabic ( xub_Unicode cChar ) +{ + return ( cChar >= 0x0600 && cChar <= 0x06FF ); +} + // ER 09.07.95 20:34 // mit -Ox Optimierung stuerzt's unter win95 ab // JP 12.07.95: unter WNT auch (i386); Alpha ?? @@ -1267,12 +1272,13 @@ void SwFntObj::DrawText( SwDrawTextInfo if ( SwScriptInfo::IsArabicLanguage( rInf.GetFont()-> GetLanguage( SW_CTL ) ) ) { - if ( pSI && pSI->CountKashida() ) - pSI->KashidaJustify( pKernArray, 0, rInf.GetIdx(), + if ( pSI && pSI->CountKashida() ) + { + pSI->KashidaJustify( pKernArray, 0, rInf.GetIdx(), rInf.GetLen(), nSpaceAdd ); - - bSpecialJust = sal_True; - nSpaceAdd = 0; + bSpecialJust = sal_True; + nSpaceAdd = 0; + } } } } @@ -1426,6 +1432,15 @@ void SwFntObj::DrawText( SwDrawTextInfo // Modify Printer and ScreenArrays for special justifications // long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR; + bool bNoHalfSpace = false; + + if ( nSpaceAdd ) + for ( xub_StrLen i = 0; i < rInf.GetLen(); ++i ) + { + bNoHalfSpace = isCharArabic ( rInf.GetText().GetChar ( i )); + if ( bNoHalfSpace ) + break; + } if ( rInf.GetFont() && rInf.GetLen() ) { @@ -1489,10 +1504,12 @@ void SwFntObj::DrawText( SwDrawTextInfo if ( SwScriptInfo::IsArabicLanguage( rInf.GetFont()-> GetLanguage( SW_CTL ) ) ) { - if ( pSI && pSI->CountKashida() ) - pSI->KashidaJustify( pKernArray, pScrArray, rInf.GetIdx(), + if ( pSI && pSI->CountKashida() ) + { + pSI->KashidaJustify( pKernArray, pScrArray, rInf.GetIdx(), rInf.GetLen(), nSpaceAdd ); - nSpaceAdd = 0; + nSpaceAdd = 0; + } } } } @@ -1571,7 +1588,7 @@ void SwFntObj::DrawText( SwDrawTextInfo // vor bzw. hinter den kompletten Zwischenraum gesetzt werden, // sonst wuerde das Durch-/Unterstreichen Luecken aufweisen. long nSpaceSum = 0; - long nHalfSpace = pPrtFont->IsWordLineMode() ? 0 : nSpaceAdd / 2; + long nHalfSpace = pPrtFont->IsWordLineMode() || bNoHalfSpace ? 0 : nSpaceAdd / 2; long nOtherHalf = nSpaceAdd - nHalfSpace; if ( nSpaceAdd && ( cChPrev == CH_BLANK ) ) nSpaceSum = nHalfSpace; @@ -2139,11 +2156,13 @@ xub_StrLen SwFntObj::GetCrsrOfst( SwDraw if ( SwScriptInfo::IsArabicLanguage( rInf.GetFont()-> GetLanguage( SW_CTL ) ) ) { - if ( pSI && pSI->CountKashida() ) - pSI->KashidaJustify( pKernArray, 0, rInf.GetIdx(), rInf.GetLen(), + if ( pSI && pSI->CountKashida() ) + { + pSI->KashidaJustify( pKernArray, 0, rInf.GetIdx(), rInf.GetLen(), nSpaceAdd ); - nSpaceAdd = 0; + nSpaceAdd = 0; + } } } }