summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens-Heiner Rechtien <hr@openoffice.org>2009-01-05 15:33:41 +0000
committerJens-Heiner Rechtien <hr@openoffice.org>2009-01-05 15:33:41 +0000
commit6ecc856f8cc90bd18b29523460570e9358792d34 (patch)
tree88955ffe673b18402436809d54ff975c06dc477e
parent48119ae05819132c6a4558dac23da8c70cad0814 (diff)
CWS-TOOLING: integrate CWS kashidafix
2008-12-15 15:31:40 +0100 hde r265507 : #i97098# 2008-12-15 15:30:52 +0100 hde r265506 : #i97098# 2008-12-10 14:08:07 +0100 fredrikh r265184 : i97098 2008-11-27 15:07:01 +0100 hdu r264493 : #i60594# only determine GetNextGlyphs() charpos if requested+available 2008-11-27 14:09:42 +0100 hdu r264487 : #i60594# simplify RTL-glyph-injection also for manual-cell-aligned cases 2008-11-26 13:25:08 +0100 fme r264379 : #i60594# Kashida fixes - syntax error 2008-11-26 13:16:22 +0100 hdu r264374 : #i60594# allow glyph injection even if there is not enough room if they can overlap 2008-11-25 16:40:20 +0100 hdu r264314 : #i60594# fix glyph-injection for PDF-export for usp>=1.6 2008-11-24 16:17:11 +0100 hdu r264254 : #i71804# adjust glyph-fallback usp-methods for new glyph-injection infrastructure 2008-11-24 16:15:30 +0100 hdu r264253 : #i71804# disable glyph-injection for glyph-fallback mixing 2008-11-20 08:29:15 +0100 fme r264027 : #i60594# Fix correction 2008-11-14 10:10:54 +0100 fme r263666 : CWS-TOOLING: rebase CWS kashidafix to trunk@263288 (milestone: DEV300:m35) 2008-10-30 16:35:30 +0100 fme r262834 : #i60594# migrate cws kashidafix to SVN.
-rw-r--r--sw/inc/breakit.hxx4
-rw-r--r--sw/inc/viewsh.hxx4
-rw-r--r--sw/source/core/bastyp/breakit.cxx7
-rw-r--r--sw/source/core/inc/scriptinfo.hxx72
-rw-r--r--sw/source/core/inc/txtfrm.hxx11
-rw-r--r--sw/source/core/text/ScriptInfo.cxx1366
-rw-r--r--sw/source/core/text/inftxt.cxx7
-rw-r--r--sw/source/core/text/itradj.cxx203
-rw-r--r--sw/source/core/text/itrcrsr.cxx10
-rw-r--r--sw/source/core/text/itrform2.cxx18
-rw-r--r--sw/source/core/text/itrtxt.hxx4
-rw-r--r--sw/source/core/text/porfld.cxx21
-rw-r--r--sw/source/core/text/porlay.cxx371
-rw-r--r--sw/source/core/text/pormulti.cxx54
-rw-r--r--sw/source/core/text/pormulti.hxx8
-rw-r--r--sw/source/core/text/portxt.cxx25
-rw-r--r--sw/source/core/text/txtfrm.cxx25
-rw-r--r--sw/source/core/txtnode/fntcache.cxx97
-rw-r--r--sw/source/core/txtnode/swfont.cxx10
-rw-r--r--sw/source/core/txtnode/thints.cxx20
-rw-r--r--sw/source/core/view/viewsh.cxx10
21 files changed, 803 insertions, 1544 deletions
diff --git a/sw/inc/breakit.hxx b/sw/inc/breakit.hxx
index 53940bd00e37..7855b8a68728 100644
--- a/sw/inc/breakit.hxx
+++ b/sw/inc/breakit.hxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: breakit.hxx,v $
- * $Revision: 1.12 $
+ * $Revision: 1.12.112.1 $
*
* This file is part of OpenOffice.org.
*
@@ -36,6 +36,7 @@
#include <com/sun/star/uno/Reference.h>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/i18n/XBreakIterator.hpp>
+#include <com/sun/star/i18n/XScriptTypeDetector.hpp>
#include <com/sun/star/i18n/ForbiddenCharacters.hdl>
#include <swdllapi.h>
@@ -80,6 +81,7 @@ public:
// @@@ backward compatibility @@@
com::sun::star::uno::Reference< com::sun::star::i18n::XBreakIterator > xBreak;
+ com::sun::star::uno::Reference< com::sun::star::i18n::XScriptTypeDetector > xCTLDetect;
const com::sun::star::uno::Reference< com::sun::star::i18n::XBreakIterator > & GetBreakIter()
{
diff --git a/sw/inc/viewsh.hxx b/sw/inc/viewsh.hxx
index 318490a5113e..6a7918a414b3 100644
--- a/sw/inc/viewsh.hxx
+++ b/sw/inc/viewsh.hxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: viewsh.hxx,v $
- * $Revision: 1.64.210.2 $
+ * $Revision: 1.65.40.1 $
*
* This file is part of OpenOffice.org.
*
@@ -231,7 +231,7 @@ public:
inline sal_Bool HasInvalidRect() const { return aInvalidRect.HasArea(); }
void ChgHyphenation() { Reformat(); }
- void ChgNumberDigits() { Reformat(); }
+ void ChgNumberDigits();
//Methoden fuer Paint- und Scrollrects, die auf allen Shells im
//Ring arbeiten.
diff --git a/sw/source/core/bastyp/breakit.cxx b/sw/source/core/bastyp/breakit.cxx
index 113899e5348a..f463c818c604 100644
--- a/sw/source/core/bastyp/breakit.cxx
+++ b/sw/source/core/bastyp/breakit.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: breakit.cxx,v $
- * $Revision: 1.16 $
+ * $Revision: 1.16.112.1 $
*
* This file is part of OpenOffice.org.
*
@@ -79,6 +79,11 @@ SwBreakIt::SwBreakIt(
m_xMSF->createInstance(
rtl::OUString::createFromAscii( "com.sun.star.i18n.BreakIterator" ) ),
uno::UNO_QUERY);
+
+ xCTLDetect = uno::Reference< i18n::XScriptTypeDetector >(
+ m_xMSF->createInstance(
+ rtl::OUString::createFromAscii( "com.sun.star.i18n.ScriptTypeDetector" ) ),
+ uno::UNO_QUERY);
}
}
diff --git a/sw/source/core/inc/scriptinfo.hxx b/sw/source/core/inc/scriptinfo.hxx
index 55e1d722042d..39dded3d3257 100644
--- a/sw/source/core/inc/scriptinfo.hxx
+++ b/sw/source/core/inc/scriptinfo.hxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: scriptinfo.hxx,v $
- * $Revision: 1.21 $
+ * $Revision: 1.21.112.4 $
*
* This file is part of OpenOffice.org.
*
@@ -106,6 +106,9 @@ private:
SvXub_StrLens aDirChg;
SvBytes aDirType;
SvXub_StrLens aKashida;
+ SvXub_StrLens aKashidaInvalid;
+ SvXub_StrLens aNoKashidaLine;
+ SvXub_StrLens aNoKashidaLineEnd;
SvXub_StrLens aCompChg;
SvXub_StrLens aCompLen;
SvXub_StrLens aHiddenChg;
@@ -115,6 +118,12 @@ private:
void UpdateBidiInfo( const String& rTxt );
+ sal_Bool IsKashidaValid ( xub_StrLen nKashPos ) const;
+ void MarkKashidaInvalid ( xub_StrLen nKashPos );
+ void ClearKashidaInvalid ( xub_StrLen nKashPos );
+ bool MarkOrClearKashidaInvalid( xub_StrLen nStt, xub_StrLen nLen, bool bMark, xub_StrLen nMarkCount );
+ bool IsKashidaLine ( xub_StrLen nCharIdx ) const;
+
public:
enum CompType { KANA, SPECIAL_LEFT, SPECIAL_RIGHT, NONE };
@@ -254,7 +263,7 @@ public:
The printers kerning array. Optional.
@param pScrArray
The screen kerning array. Optional.
- @param nIdx
+ @param nStt
Start referring to the paragraph.
@param nLen
The number of characters to be considered.
@@ -262,18 +271,59 @@ 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;
+
+/** Clears array of kashidas marked as invalid
+ */
+ inline void ClearKashidaInvalid ( xub_StrLen nStt, xub_StrLen nLen ) { MarkOrClearKashidaInvalid( nStt, nLen, false, 0 ); }
+
+/** Marks nCnt kashida positions as invalid
+ pKashidaPositions: array of char indices relative to the paragraph
+*/
+ bool MarkKashidasInvalid ( xub_StrLen nCnt, xub_StrLen* pKashidaPositions );
+
+/** Marks nCnt kashida positions as invalid
+ in the given text range
+ */
+ inline bool MarkKashidasInvalid ( xub_StrLen nCnt, xub_StrLen nStt, xub_StrLen nLen )
+ { return MarkOrClearKashidaInvalid( nStt, nLen, true, nCnt ); }
+
+/** retrieves kashida opportunities for a given text range.
+ returns the number of kashida positions in the given text range
+
+ pKashidaPositions: buffer to reveive the char indices of the
+ kashida opportunties relative to the paragraph
+*/
+ USHORT GetKashidaPositions ( xub_StrLen nStt, xub_StrLen nLen,
+ xub_StrLen* pKashidaPosition );
+
-/** Checks if language is one of the 16 Arabic languages
- @descr Checks if language is one of the 16 Arabic languages
- @param aLang
- The language which has to be checked.
- @return Returns if the language is an Arabic language
+
+/** Use regular blank justification instead of kashdida justification for the given line of text.
+ nStt Start char index of the line referring to the paragraph.
+ nLen Number of characters in the line
*/
- static BOOL IsArabicLanguage( LanguageType aLang );
+ void SetNoKashidaLine ( xub_StrLen nStt, xub_StrLen nLen );
+
+/** Clear forced blank justification for a given line.
+ nStt Start char index of the line referring to the paragraph.
+ nLen Number of characters in the line
+*/
+ void ClearNoKashidaLine ( xub_StrLen nStt, xub_StrLen nLen );
+
+/** Checks if text is Arabic text.
+
+ @descr Checks if text is Arabic text.
+ @param rTxt
+ The text to check
+ @param nStt
+ Start index of the text
+ @return Returns if the language is an Arabic language
+ */
+ static sal_Bool IsArabicText( const XubString& rTxt, xub_StrLen nStt, xub_StrLen nLen );
/** Performes a thai justification on the kerning array
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index 4e7293d9b6d8..b0b2b807ab43 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: txtfrm.hxx,v $
- * $Revision: 1.56.212.1 $
+ * $Revision: 1.56.110.1 $
*
* This file is part of OpenOffice.org.
*
@@ -824,4 +824,13 @@ public:
void SetAuto();
};
+class SwDigitModeModifier
+{
+ const OutputDevice& rOut;
+ LanguageType nOldLanguageType;
+public:
+ SwDigitModeModifier( const OutputDevice& rOutp, LanguageType eCurLang );
+ ~SwDigitModeModifier();
+};
+
#endif
diff --git a/sw/source/core/text/ScriptInfo.cxx b/sw/source/core/text/ScriptInfo.cxx
deleted file mode 100644
index 232789db081d..000000000000
--- a/sw/source/core/text/ScriptInfo.cxx
+++ /dev/null
@@ -1,1366 +0,0 @@
-/*************************************************************************
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * Copyright 2008 by Sun Microsystems, Inc.
- *
- * OpenOffice.org - a multi-platform office productivity suite
- *
- * $RCSfile: ScriptInfo.cxx,v $
- * $Revision: 1.6 $
- *
- * This file is part of OpenOffice.org.
- *
- * OpenOffice.org is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 3
- * only, as published by the Free Software Foundation.
- *
- * OpenOffice.org is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License version 3 for more details
- * (a copy is included in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU Lesser General Public License
- * version 3 along with OpenOffice.org. If not, see
- * <http://www.openoffice.org/license.html>
- * for a copy of the LGPLv3 License.
- *
- ************************************************************************/
-
-// MARKER(update_precomp.py): autogen include statement, do not remove
-#include "precompiled_sw.hxx"
-
-
-#include "errhdl.hxx" // ASSERT
-#include <scriptinfo.hxx>
-#ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
-#include <com/sun/star/i18n/ScriptType.hdl>
-#endif
-#ifndef _COM_SUN_STAR_I18N_WORDTYPE_HDL
-#include <com/sun/star/i18n/WordType.hdl>
-#endif
-#include <tools/multisel.hxx>
-#include <svx/scripttypeitem.hxx>
-#include <pam.hxx>
-#include <docary.hxx>
-#include <section.hxx>
-#include <redline.hxx>
-#include <ndtxt.hxx> // GetCurFld
-#include <breakit.hxx>
-#include <txatbase.hxx>
-#include <charfmt.hxx>
-#include <fchrfmt.hxx>
-#include <svx/adjitem.hxx>
-#include <svx/charhiddenitem.hxx>
-#include <swfont.hxx>
-#include <txtfrm.hxx>
-
-#include <paratr.hxx>
-#include <IDocumentRedlineAccess.hxx>
-
-using namespace ::com::sun::star;
-using namespace ::com::sun::star::i18n::ScriptType;
-
-#include <unicode/ubidi.h>
-
-/*************************************************************************
- * lcl_IsLigature
- *
- * Checks if cCh + cNectCh builds a ligature (used for Kashidas)
- *************************************************************************/
-
-sal_Bool lcl_IsLigature( xub_Unicode cCh, xub_Unicode cNextCh )
-{
- // Lam + Alef
- return ( 0x644 == cCh && 0x627 == cNextCh ) ||
- // Beh + Reh
- ( 0x628 == cCh && 0x631 == cNextCh );
-}
-
-/*************************************************************************
- * lcl_ConnectToPrev
- *
- * Checks if cCh is connectable to cPrevCh (used for Kashidas)
- *************************************************************************/
-
-sal_Bool lcl_ConnectToPrev( xub_Unicode cCh, xub_Unicode cPrevCh )
-{
- // Alef, Dal, Thal, Reh, Zain, and Waw do not connect to the left
- // Uh, there seem to be some more characters that are not connectable
- // to the left. So we look for the characters that are actually connectable
- // to the left. Here is the complete list of WH:
- sal_Bool bRet = 0x628 == cPrevCh ||
- ( 0x62A <= cPrevCh && cPrevCh <= 0x62E ) ||
- ( 0x633 <= cPrevCh && cPrevCh <= 0x643 ) ||
- ( 0x645 <= cPrevCh && cPrevCh <= 0x647 ) ||
- 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 );
-
- return bRet;
-}
-
-/*************************************************************************
- * WhichFont()
- *
- * Converts i18n Script Type (LATIN, ASIAN, COMPLEX, WEAK) to
- * Sw Script Types (SW_LATIN, SW_CJK, SW_CTL), used to identify the font
- *************************************************************************/
-
-BYTE SwScriptInfo::WhichFont( xub_StrLen nIdx, const String* pTxt, const SwScriptInfo* pSI )
-{
- ASSERT( pTxt || pSI,"How should I determine the script type?" );
- USHORT nScript;
-
- // First we try to use our SwScriptInfo
- if ( pSI )
- nScript = pSI->ScriptType( nIdx );
- else
- // Ok, we have to ask the break iterator
- nScript = pBreakIt->GetRealScriptOfText( *pTxt, nIdx );
-
- switch ( nScript ) {
- case i18n::ScriptType::LATIN : return SW_LATIN;
- case i18n::ScriptType::ASIAN : return SW_CJK;
- case i18n::ScriptType::COMPLEX : return SW_CTL;
- }
-
- ASSERT( sal_False, "Somebody tells lies about the script type!" );
- return SW_LATIN;
-}
-
-/*************************************************************************
- * SwScriptInfo::InitScriptInfo()
- *
- * searches for script changes in rTxt and stores them
- *************************************************************************/
-
-void SwScriptInfo::InitScriptInfo( const SwTxtNode& rNode )
-{
- InitScriptInfo( rNode, nDefaultDir == UBIDI_RTL );
-}
-
-void SwScriptInfo::InitScriptInfo( const SwTxtNode& rNode, sal_Bool bRTL )
-{
- if( !pBreakIt->xBreak.is() )
- return;
-
- const String& rTxt = rNode.GetTxt();
-
- //
- // HIDDEN TEXT INFORMATION
- //
- Range aRange( 0, rTxt.Len() ? rTxt.Len() - 1 : 0 );
- MultiSelection aHiddenMulti( aRange );
- CalcHiddenRanges( rNode, aHiddenMulti );
-
- aHiddenChg.Remove( 0, aHiddenChg.Count() );
- USHORT nHiddenIdx = 0;
- USHORT i = 0;
- for( i = 0; i < aHiddenMulti.GetRangeCount(); ++i )
- {
- const Range& rRange = aHiddenMulti.GetRange( i );
- const xub_StrLen nStart = (xub_StrLen)rRange.Min();
- const xub_StrLen nEnd = (xub_StrLen)rRange.Max() + 1;
-
- aHiddenChg.Insert( nStart, nHiddenIdx++ );
- aHiddenChg.Insert( nEnd, nHiddenIdx++ );
- }
-
- //
- // SCRIPT AND SCRIPT RELATED INFORMATION
- //
-
- xub_StrLen nChg = nInvalidityPos;
-
- // STRING_LEN means the data structure is up to date
- nInvalidityPos = STRING_LEN;
-
- // this is the default direction
- nDefaultDir = bRTL ? UBIDI_RTL : UBIDI_LTR;
-
- // counter for script info arrays
- USHORT nCnt = 0;
- // counter for compression information arrays
- USHORT nCntComp = 0;
- // counter for kashida array
- USHORT nCntKash = 0;
-
- BYTE nScript;
-
- // compression type
- const SwCharCompressType aCompEnum = rNode.getIDocumentSettingAccess()->getCharacterCompressionType();
-
- // justification type
- const sal_Bool bAdjustBlock = SVX_ADJUST_BLOCK ==
- rNode.GetSwAttrSet().GetAdjust().GetAdjust();
-
- //
- // FIND INVALID RANGES IN SCRIPT INFO ARRAYS:
- //
-
- if( nChg )
- {
- // if change position = 0 we do not use any data from the arrays
- // because by deleting all characters of the first group at the beginning
- // of a paragraph nScript is set to a wrong value
- ASSERT( CountScriptChg(), "Where're my changes of script?" );
- while( nCnt < CountScriptChg() )
- {
- if ( nChg > GetScriptChg( nCnt ) )
- nCnt++;
- else
- {
- nScript = GetScriptType( nCnt );
- break;
- }
- }
- if( CHARCOMPRESS_NONE != aCompEnum )
- {
- while( nCntComp < CountCompChg() )
- {
- if ( nChg > GetCompStart( nCntComp ) )
- nCntComp++;
- else
- break;
- }
- }
- if ( bAdjustBlock )
- {
- while( nCntKash < CountKashida() )
- {
- if ( nChg > GetKashida( nCntKash ) )
- nCntKash++;
- else
- break;
- }
- }
- }
-
- //
- // ADJUST nChg VALUE:
- //
-
- // by stepping back one position we know that we are inside a group
- // declared as an nScript group
- if ( nChg )
- --nChg;
-
- const xub_StrLen nGrpStart = nCnt ? GetScriptChg( nCnt - 1 ) : 0;
-
- // we go back in our group until we reach the first character of
- // type nScript
- while ( nChg > nGrpStart &&
- nScript != pBreakIt->xBreak->getScriptType( rTxt, nChg ) )
- --nChg;
-
- // If we are at the start of a group, we do not trust nScript,
- // we better get nScript from the breakiterator:
- if ( nChg == nGrpStart )
- nScript = (BYTE)pBreakIt->xBreak->getScriptType( rTxt, nChg );
-
- //
- // INVALID DATA FROM THE SCRIPT INFO ARRAYS HAS TO BE DELETED:
- //
-
- // remove invalid entries from script information arrays
- const USHORT nScriptRemove = aScriptChg.Count() - nCnt;
- aScriptChg.Remove( nCnt, nScriptRemove );
- aScriptType.Remove( nCnt, nScriptRemove );
-
- // get the start of the last compression group
- USHORT nLastCompression = nChg;
- if( nCntComp )
- {
- --nCntComp;
- nLastCompression = GetCompStart( nCntComp );
- if( nChg >= nLastCompression + GetCompLen( nCntComp ) )
- {
- nLastCompression = nChg;
- ++nCntComp;
- }
- }
-
- // remove invalid entries from compression information arrays
- const USHORT nCompRemove = aCompChg.Count() - nCntComp;
- aCompChg.Remove( nCntComp, nCompRemove );
- aCompLen.Remove( nCntComp, nCompRemove );
- aCompType.Remove( nCntComp, nCompRemove );
-
- // get the start of the last kashida group
- USHORT nLastKashida = nChg;
- if( nCntKash && i18n::ScriptType::COMPLEX == nScript )
- {
- --nCntKash;
- nLastKashida = GetKashida( nCntKash );
- }
-
- // remove invalid entries from kashida array
- aKashida.Remove( nCntKash, aKashida.Count() - nCntKash );
-
- //
- // TAKE CARE OF WEAK CHARACTERS: WE MUST FIND AN APPROPRIATE
- // SCRIPT FOR WEAK CHARACTERS AT THE BEGINNING OF A PARAGRAPH
- //
-
- if( WEAK == pBreakIt->xBreak->getScriptType( rTxt, nChg ) )
- {
- // If the beginning of the current group is weak, this means that
- // all of the characters in this grounp are weak. We have to assign
- // the scripts to these characters depending on the fonts which are
- // set for these characters to display them.
- xub_StrLen nEnd =
- (xub_StrLen)pBreakIt->xBreak->endOfScript( rTxt, nChg, WEAK );
-
- if( nEnd > rTxt.Len() )
- nEnd = rTxt.Len();
-
- nScript = (BYTE)GetI18NScriptTypeOfLanguage( (USHORT)GetAppLanguage() );
-
- ASSERT( i18n::ScriptType::LATIN == nScript ||
- i18n::ScriptType::ASIAN == nScript ||
- i18n::ScriptType::COMPLEX == nScript, "Wrong default language" );
-
- nChg = nEnd;
-
- // Get next script type or set to weak in order to exit
- BYTE nNextScript = ( nEnd < rTxt.Len() ) ?
- (BYTE)pBreakIt->xBreak->getScriptType( rTxt, nEnd ) :
- (BYTE)WEAK;
-
- if ( nScript != nNextScript )
- {
- aScriptChg.Insert( nEnd, nCnt );
- aScriptType.Insert( nScript, nCnt++ );
- nScript = nNextScript;
- }
- }
-
- //
- // UPDATE THE SCRIPT INFO ARRAYS:
- //
-
- while ( nChg < rTxt.Len() || ( !aScriptChg.Count() && !rTxt.Len() ) )
- {
- ASSERT( i18n::ScriptType::WEAK != nScript,
- "Inserting WEAK into SwScriptInfo structure" );
- ASSERT( STRING_LEN != nChg, "65K? Strange length of script section" );
-
- nChg = (xub_StrLen)pBreakIt->xBreak->endOfScript( rTxt, nChg, nScript );
-
- if ( nChg > rTxt.Len() )
- nChg = rTxt.Len();
-
- aScriptChg.Insert( nChg, nCnt );
- aScriptType.Insert( nScript, nCnt++ );
-
- // if current script is asian, we search for compressable characters
- // in this range
- if ( CHARCOMPRESS_NONE != aCompEnum &&
- i18n::ScriptType::ASIAN == nScript )
- {
- BYTE ePrevState = NONE;
- BYTE eState;
- USHORT nPrevChg = nLastCompression;
-
- while ( nLastCompression < nChg )
- {
- xub_Unicode cChar = rTxt.GetChar( nLastCompression );
-
- // examine current character
- switch ( cChar )
- {
- // Left punctuation found
- case 0x3008: case 0x300A: case 0x300C: case 0x300E:
- case 0x3010: case 0x3014: case 0x3016: case 0x3018:
- case 0x301A: case 0x301D:
- eState = SPECIAL_LEFT;
- break;
- // Right punctuation found
- case 0x3001: case 0x3002: case 0x3009: case 0x300B:
- case 0x300D: case 0x300F: case 0x3011: case 0x3015:
- case 0x3017: case 0x3019: case 0x301B: case 0x301E:
- case 0x301F:
- eState = SPECIAL_RIGHT;
- break;
- default:
- eState = ( 0x3040 <= cChar && 0x3100 > cChar ) ?
- KANA :
- NONE;
- }
-
- // insert range of compressable characters
- if( ePrevState != eState )
- {
- if ( ePrevState != NONE )
- {
- // insert start and type
- if ( CHARCOMPRESS_PUNCTUATION_KANA == aCompEnum ||
- ePrevState != KANA )
- {
- aCompChg.Insert( nPrevChg, nCntComp );
- BYTE nTmpType = ePrevState;
- aCompType.Insert( nTmpType, nCntComp );
- aCompLen.Insert( nLastCompression - nPrevChg, nCntComp++ );
- }
- }
-
- ePrevState = eState;
- nPrevChg = nLastCompression;
- }
-
- nLastCompression++;
- }
-
- // we still have to examine last entry
- if ( ePrevState != NONE )
- {
- // insert start and type
- if ( CHARCOMPRESS_PUNCTUATION_KANA == aCompEnum ||
- ePrevState != KANA )
- {
- aCompChg.Insert( nPrevChg, nCntComp );
- BYTE nTmpType = ePrevState;
- aCompType.Insert( nTmpType, nCntComp );
- aCompLen.Insert( nLastCompression - nPrevChg, nCntComp++ );
- }
- }
- }
-
- // we search for connecting opportunities (kashida)
- else if ( bAdjustBlock && i18n::ScriptType::COMPLEX == nScript )
- {
- SwScanner aScanner( rNode,
- i18n::WordType::DICTIONARY_WORD,
- nLastKashida, nChg );
-
- // the search has to be performed on a per word base
- while ( aScanner.NextWord() )
- {
- const XubString& rWord = aScanner.GetWord();
-
- xub_StrLen nIdx = 0;
- 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
- 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 );
-
- 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;
- }
- }
-
- // 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;
- }
- }
-
- // 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 )
- cPrevCh = cCh;
-
- ++nIdx;
- } // end of current word
-
- if ( STRING_LEN != nKashidaPos )
- aKashida.Insert( nKashidaPos, nCntKash++ );
- } // end of kashida search
- }
-
- if ( nChg < rTxt.Len() )
- nScript = (BYTE)pBreakIt->xBreak->getScriptType( rTxt, nChg );
-
- nLastCompression = nChg;
- nLastKashida = nChg;
- };
-
-#ifndef PRODUCT
- // check kashida data
- long nTmpKashidaPos = -1;
- sal_Bool bWrongKash = sal_False;
- for (i = 0; i < aKashida.Count(); ++i )
- {
- long nCurrKashidaPos = GetKashida( i );
- if ( nCurrKashidaPos <= nTmpKashidaPos )
- {
- bWrongKash = sal_True;
- break;
- }
- nTmpKashidaPos = nCurrKashidaPos;
- }
- ASSERT( ! bWrongKash, "Kashida array contains wrong data" )
-#endif
-
- // remove invalid entries from direction information arrays
- const USHORT nDirRemove = aDirChg.Count();
- aDirChg.Remove( 0, nDirRemove );
- aDirType.Remove( 0, nDirRemove );
-
- // Perform Unicode Bidi Algorithm for text direction information
- bool bPerformUBA = UBIDI_LTR != nDefaultDir;
- nCnt = 0;
- while( !bPerformUBA && nCnt < CountScriptChg() )
- {
- if ( i18n::ScriptType::COMPLEX == GetScriptType( nCnt++ ) )
- bPerformUBA = true;
- }
-
- // do not call the unicode bidi algorithm if not required
- if ( bPerformUBA )
- {
- UpdateBidiInfo( rTxt );
-
- // #i16354# Change script type for RTL text to CTL.
- for ( USHORT nDirIdx = 0; nDirIdx < aDirChg.Count(); ++nDirIdx )
- {
- if ( GetDirType( nDirIdx ) == UBIDI_RTL )
- {
- // nStart ist start of RTL run:
- const xub_StrLen nStart = nDirIdx > 0 ? GetDirChg( nDirIdx - 1 ) : 0;
- // nEnd is end of RTL run:
- const xub_StrLen nEnd = GetDirChg( nDirIdx );
- // nScriptIdx points into the ScriptArrays:
- USHORT nScriptIdx = 0;
-
- // Skip entries in ScriptArray which are not inside the RTL run:
- // Make nScriptIdx become the index of the script group with
- // 1. nStartPosOfGroup <= nStart and
- // 2. nEndPosOfGroup > nStart
- while ( GetScriptChg( nScriptIdx ) <= nStart )
- ++nScriptIdx;
-
- xub_StrLen nEndPosOfGroup = GetScriptChg( nScriptIdx );
- xub_StrLen nStartPosOfGroup = nScriptIdx ? GetScriptChg( nScriptIdx - 1 ) : 0;
- BYTE nScriptTypeOfGroup = GetScriptType( nScriptIdx );
-
- ASSERT( nStartPosOfGroup <= nStart && nEndPosOfGroup > nStart,
- "Script override with CTL font trouble" )
-
- // Check if we have to insert a new script change at
- // position nStart. If nStartPosOfGroup < nStart,
- // we have to insert a new script change:
- if ( nStart > 0 && nStartPosOfGroup < nStart )
- {
- aScriptChg.Insert( nStart, nScriptIdx );
- aScriptType.Insert( nScriptTypeOfGroup, nScriptIdx );
- ++nScriptIdx;
- }
-
- // Remove entries in ScriptArray which end inside the RTL run:
- while ( nScriptIdx < aScriptChg.Count() && GetScriptChg( nScriptIdx ) <= nEnd )
- {
- aScriptChg.Remove( nScriptIdx, 1 );
- aScriptType.Remove( nScriptIdx, 1 );
- }
-
- // Insert a new entry in ScriptArray for the end of the RTL run:
- aScriptChg.Insert( nEnd, nScriptIdx );
- aScriptType.Insert( i18n::ScriptType::COMPLEX, nScriptIdx );
-
-#if OSL_DEBUG_LEVEL > 1
- BYTE nScriptType;
- BYTE nLastScriptType = i18n::ScriptType::WEAK;
- xub_StrLen nScriptChg;
- xub_StrLen nLastScriptChg = 0;
-
- for ( int i = 0; i < aScriptChg.Count(); ++i )
- {
- nScriptChg = GetScriptChg( i );
- nScriptType = GetScriptType( i );
- ASSERT( nLastScriptType != nScriptType &&
- nLastScriptChg < nScriptChg,
- "Heavy InitScriptType() confusion" )
- }
-#endif
- }
- }
- }
-}
-
-void SwScriptInfo::UpdateBidiInfo( const String& rTxt )
-{
- // remove invalid entries from direction information arrays
- const USHORT nDirRemove = aDirChg.Count();
- aDirChg.Remove( 0, nDirRemove );
- aDirType.Remove( 0, nDirRemove );
-
- //
- // Bidi functions from icu 2.0
- //
- UErrorCode nError = U_ZERO_ERROR;
- UBiDi* pBidi = ubidi_openSized( rTxt.Len(), 0, &nError );
- nError = U_ZERO_ERROR;
-
- ubidi_setPara( pBidi, rTxt.GetBuffer(), rTxt.Len(),
- nDefaultDir, NULL, &nError );
- nError = U_ZERO_ERROR;
- long nCount = ubidi_countRuns( pBidi, &nError );
- int32_t nStart = 0;
- int32_t nEnd;
- UBiDiLevel nCurrDir;
- // counter for direction information arrays
- USHORT nCntDir = 0;
-
- for ( USHORT nIdx = 0; nIdx < nCount; ++nIdx )
- {
- ubidi_getLogicalRun( pBidi, nStart, &nEnd, &nCurrDir );
- aDirChg.Insert( (USHORT)nEnd, nCntDir );
- aDirType.Insert( (BYTE)nCurrDir, nCntDir++ );
- nStart = nEnd;
- }
-
- ubidi_close( pBidi );
-}
-
-
-/*************************************************************************
- * SwScriptInfo::NextScriptChg(..)
- * returns the position of the next character which belongs to another script
- * than the character of the actual (input) position.
- * If there's no script change until the end of the paragraph, it will return
- * STRING_LEN.
- * Scripts are Asian (Chinese, Japanese, Korean),
- * Latin ( English etc.)
- * and Complex ( Hebrew, Arabian )
- *************************************************************************/
-
-xub_StrLen SwScriptInfo::NextScriptChg( const xub_StrLen nPos ) const
-{
- USHORT nEnd = CountScriptChg();
- for( USHORT nX = 0; nX < nEnd; ++nX )
- {
- if( nPos < GetScriptChg( nX ) )
- return GetScriptChg( nX );
- }
-
- return STRING_LEN;
-}
-
-/*************************************************************************
- * SwScriptInfo::ScriptType(..)
- * returns the script of the character at the input position
- *************************************************************************/
-
-BYTE SwScriptInfo::ScriptType( const xub_StrLen nPos ) const
-{
- USHORT nEnd = CountScriptChg();
- for( USHORT nX = 0; nX < nEnd; ++nX )
- {
- if( nPos < GetScriptChg( nX ) )
- return GetScriptType( nX );
- }
-
- // the default is the application language script
- return (BYTE)GetI18NScriptTypeOfLanguage( (USHORT)GetAppLanguage() );
-}
-
-xub_StrLen SwScriptInfo::NextDirChg( const xub_StrLen nPos,
- const BYTE* pLevel ) const
-{
- BYTE nCurrDir = pLevel ? *pLevel : 62;
- USHORT nEnd = CountDirChg();
- for( USHORT nX = 0; nX < nEnd; ++nX )
- {
- if( nPos < GetDirChg( nX ) &&
- ( nX + 1 == nEnd || GetDirType( nX + 1 ) <= nCurrDir ) )
- return GetDirChg( nX );
- }
-
- return STRING_LEN;
-}
-
-BYTE SwScriptInfo::DirType( const xub_StrLen nPos ) const
-{
- USHORT nEnd = CountDirChg();
- for( USHORT nX = 0; nX < nEnd; ++nX )
- {
- if( nPos < GetDirChg( nX ) )
- return GetDirType( nX );
- }
-
- return 0;
-}
-
-/*************************************************************************
- * SwScriptInfo::MaskHiddenRanges(..)
- * Takes a string and replaced the hidden ranges with cChar.
- **************************************************************************/
-
-USHORT SwScriptInfo::MaskHiddenRanges( const SwTxtNode& rNode, XubString& rText,
- const xub_StrLen nStt, const xub_StrLen nEnd,
- const xub_Unicode cChar )
-{
- ASSERT( rNode.GetTxt().Len() == rText.Len(), "MaskHiddenRanges, string len mismatch" )
-
- PositionList aList;
- xub_StrLen nHiddenStart;
- xub_StrLen nHiddenEnd;
- USHORT nNumOfHiddenChars = 0;
- GetBoundsOfHiddenRange( rNode, 0, nHiddenStart, nHiddenEnd, &aList );
- PositionList::const_reverse_iterator rFirst( aList.end() );
- PositionList::const_reverse_iterator rLast( aList.begin() );
- while ( rFirst != rLast )
- {
- nHiddenEnd = *(rFirst++);
- nHiddenStart = *(rFirst++);
-
- if ( nHiddenEnd < nStt || nHiddenStart > nEnd )
- continue;
-
- while ( nHiddenStart < nHiddenEnd && nHiddenStart < nEnd )
- {
- if ( nHiddenStart >= nStt && nHiddenStart < nEnd )
- {
- rText.SetChar( nHiddenStart, cChar );
- ++nNumOfHiddenChars;
- }
- ++nHiddenStart;
- }
- }
-
- return nNumOfHiddenChars;
-}
-
-/*************************************************************************
- * SwScriptInfo::GetBoundsOfHiddenRange(..)
- * static version
- **************************************************************************/
-
-bool SwScriptInfo::GetBoundsOfHiddenRange( const SwTxtNode& rNode, xub_StrLen nPos,
- xub_StrLen& rnStartPos, xub_StrLen& rnEndPos,
- PositionList* pList )
-{
- rnStartPos = STRING_LEN;
- rnEndPos = 0;
-
- bool bNewContainsHiddenChars = false;
-
- //
- // Optimization: First examine the flags at the text node:
- //
- if ( !rNode.IsCalcHiddenCharFlags() )
- {
- bool bWholePara = rNode.HasHiddenCharAttribute( true );
- bool bContainsHiddenChars = rNode.HasHiddenCharAttribute( false );
- if ( !bContainsHiddenChars )
- return false;
-
- if ( bWholePara )
- {
- if ( pList )
- {
- pList->push_back( 0 );
- pList->push_back( rNode.GetTxt().Len() );
- }
-
- rnStartPos = 0;
- rnEndPos = rNode.GetTxt().Len();
- return true;
- }
- }
-
- const SwScriptInfo* pSI = SwScriptInfo::GetScriptInfo( rNode );
- if ( pSI )
- {
- //
- // Check first, if we have a valid SwScriptInfo object for this text node:
- //
- bNewContainsHiddenChars = pSI->GetBoundsOfHiddenRange( nPos, rnStartPos, rnEndPos, pList );
- const bool bNewHiddenCharsHidePara = ( rnStartPos == 0 && rnEndPos >= rNode.GetTxt().Len() );
- rNode.SetHiddenCharAttribute( bNewHiddenCharsHidePara, bNewContainsHiddenChars );
- }
- else
- {
- //
- // No valid SwScriptInfo Object, we have to do it the hard way:
- //
- Range aRange( 0, rNode.GetTxt().Len() ? rNode.GetTxt().Len() - 1 : 0 );
- MultiSelection aHiddenMulti( aRange );
- SwScriptInfo::CalcHiddenRanges( rNode, aHiddenMulti );
- for( USHORT i = 0; i < aHiddenMulti.GetRangeCount(); ++i )
- {
- const Range& rRange = aHiddenMulti.GetRange( i );
- const xub_StrLen nHiddenStart = (xub_StrLen)rRange.Min();
- const xub_StrLen nHiddenEnd = (xub_StrLen)rRange.Max() + 1;
-
- if ( nHiddenStart > nPos )
- break;
- else if ( nHiddenStart <= nPos && nPos < nHiddenEnd )
- {
- rnStartPos = nHiddenStart;
- rnEndPos = Min( nHiddenEnd, rNode.GetTxt().Len() );
- break;
- }
- }
-
- if ( pList )
- {
- for( USHORT i = 0; i < aHiddenMulti.GetRangeCount(); ++i )
- {
- const Range& rRange = aHiddenMulti.GetRange( i );
- pList->push_back( (xub_StrLen)rRange.Min() );
- pList->push_back( (xub_StrLen)rRange.Max() + 1 );
- }
- }
-
- bNewContainsHiddenChars = aHiddenMulti.GetRangeCount() > 0;
- }
-
- return bNewContainsHiddenChars;
-}
-
-/*************************************************************************
- * SwScriptInfo::GetBoundsOfHiddenRange(..)
- * non-static version
- **************************************************************************/
-
-bool SwScriptInfo::GetBoundsOfHiddenRange( xub_StrLen nPos, xub_StrLen& rnStartPos,
- xub_StrLen& rnEndPos, PositionList* pList ) const
-{
- rnStartPos = STRING_LEN;
- rnEndPos = 0;
-
- USHORT nEnd = CountHiddenChg();
- for( USHORT nX = 0; nX < nEnd; ++nX )
- {
- const xub_StrLen nHiddenStart = GetHiddenChg( nX++ );
- const xub_StrLen nHiddenEnd = GetHiddenChg( nX );
-
- if ( nHiddenStart > nPos )
- break;
- else if ( nHiddenStart <= nPos && nPos < nHiddenEnd )
- {
- rnStartPos = nHiddenStart;
- rnEndPos = nHiddenEnd;
- break;
- }
- }
-
- if ( pList )
- {
- for( USHORT nX = 0; nX < nEnd; ++nX )
- {
- pList->push_back( GetHiddenChg( nX++ ) );
- pList->push_back( GetHiddenChg( nX ) );
- }
- }
-
- return CountHiddenChg() > 0;
-}
-
-/*************************************************************************
- * SwScriptInfo::IsInHiddenRange()
- **************************************************************************/
-
-bool SwScriptInfo::IsInHiddenRange( const SwTxtNode& rNode, xub_StrLen nPos )
-{
- xub_StrLen nStartPos;
- xub_StrLen nEndPos;
- SwScriptInfo::GetBoundsOfHiddenRange( rNode, nPos, nStartPos, nEndPos );
- return nStartPos != STRING_LEN;
-}
-
-
-#if OSL_DEBUG_LEVEL > 1
-/*************************************************************************
- * SwScriptInfo::CompType(..)
- * returns the type of the compressed character
- *************************************************************************/
-
-BYTE SwScriptInfo::CompType( const xub_StrLen nPos ) const
-{
- USHORT nEnd = CountCompChg();
- for( USHORT nX = 0; nX < nEnd; ++nX )
- {
- xub_StrLen nChg = GetCompStart( nX );
-
- if ( nPos < nChg )
- return NONE;
-
- if( nPos < nChg + GetCompLen( nX ) )
- return GetCompType( nX );
- }
- return NONE;
-}
-#endif
-
-/*************************************************************************
- * SwScriptInfo::HasKana()
- * returns, if there are compressable kanas or specials
- * betwenn nStart and nEnd
- *************************************************************************/
-
-USHORT SwScriptInfo::HasKana( xub_StrLen nStart, const xub_StrLen nLen ) const
-{
- USHORT nCnt = CountCompChg();
- xub_StrLen nEnd = nStart + nLen;
-
- for( USHORT nX = 0; nX < nCnt; ++nX )
- {
- xub_StrLen nKanaStart = GetCompStart( nX );
- xub_StrLen nKanaEnd = nKanaStart + GetCompLen( nX );
-
- if ( nKanaStart >= nEnd )
- return USHRT_MAX;
-
- if ( nStart < nKanaEnd )
- return nX;
- }
-
- return USHRT_MAX;
-}
-
-/*************************************************************************
- * SwScriptInfo::Compress()
- *************************************************************************/
-
-long SwScriptInfo::Compress( long* pKernArray, xub_StrLen nIdx, xub_StrLen nLen,
- const USHORT nCompress, const USHORT nFontHeight,
- Point* pPoint ) const
-{
- ASSERT( nCompress, "Compression without compression?!" );
- ASSERT( nLen, "Compression without text?!" );
- USHORT nCompCount = CountCompChg();
-
- // In asian typography, there are full width and half width characters.
- // Full width punctuation characters can be compressed by 50 %
- // to determine this, we compare the font width with 75 % of its height
- USHORT nMinWidth = ( 3 * nFontHeight ) / 4;
-
- USHORT nCompIdx = HasKana( nIdx, nLen );
-
- if ( USHRT_MAX == nCompIdx )
- return 0;
-
- xub_StrLen nChg = GetCompStart( nCompIdx );
- xub_StrLen nCompLen = GetCompLen( nCompIdx );
- USHORT nI = 0;
- nLen += nIdx;
-
- if( nChg > nIdx )
- {
- nI = nChg - nIdx;
- nIdx = nChg;
- }
- else if( nIdx < nChg + nCompLen )
- nCompLen -= nIdx - nChg;
-
- if( nIdx > nLen || nCompIdx >= nCompCount )
- return 0;
-
- long nSub = 0;
- long nLast = nI ? pKernArray[ nI - 1 ] : 0;
- do
- {
- USHORT nType = GetCompType( nCompIdx );
-#if OSL_DEBUG_LEVEL > 1
- ASSERT( nType == CompType( nIdx ), "Gimme the right type!" );
-#endif
- nCompLen += nIdx;
- if( nCompLen > nLen )
- nCompLen = nLen;
-
- // are we allowed to compress the character?
- if ( pKernArray[ nI ] - nLast < nMinWidth )
- {
- nIdx++; nI++;
- }
- else
- {
- while( nIdx < nCompLen )
- {
- ASSERT( SwScriptInfo::NONE != nType, "None compression?!" );
-
- // nLast is width of current character
- nLast -= pKernArray[ nI ];
-
- nLast *= nCompress;
- long nMove = 0;
- if( SwScriptInfo::KANA != nType )
- {
- nLast /= 20000;
- if( pPoint && SwScriptInfo::SPECIAL_LEFT == nType )
- {
- if( nI )
- nMove = nLast;
- else
- {
- pPoint->X() += nLast;
- nLast = 0;
- }
- }
- }
- else
- nLast /= 100000;
- nSub -= nLast;
- nLast = pKernArray[ nI ];
- if( nMove )
- pKernArray[ nI - 1 ] += nMove;
- pKernArray[ nI++ ] -= nSub;
- ++nIdx;
- }
- }
-
- if( nIdx < nLen )
- {
- xub_StrLen nChg;
- if( ++nCompIdx < nCompCount )
- {
- nChg = GetCompStart( nCompIdx );
- if( nChg > nLen )
- nChg = nLen;
- nCompLen = GetCompLen( nCompIdx );
- }
- else
- nChg = nLen;
- while( nIdx < nChg )
- {
- nLast = pKernArray[ nI ];
- pKernArray[ nI++ ] -= nSub;
- ++nIdx;
- }
- }
- else
- break;
- } while( nIdx < nLen );
- return nSub;
-}
-
-/*************************************************************************
- * SwScriptInfo::KashidaJustify()
- *************************************************************************/
-
-USHORT SwScriptInfo::KashidaJustify( long* pKernArray, long* pScrArray,
- xub_StrLen nStt, xub_StrLen nLen,
- long nSpaceAdd ) const
-{
- ASSERT( nLen, "Kashida justification without text?!" )
-
- // evaluate kashida informatin in collected in SwScriptInfo
-
- USHORT nCntKash = 0;
- while( nCntKash < CountKashida() )
- {
- if ( nStt <= GetKashida( nCntKash ) )
- break;
- else
- nCntKash++;
- }
-
- const xub_StrLen nEnd = nStt + nLen;
-
- if ( ! pKernArray )
- {
- USHORT nCntKashEnd = nCntKash;
- while ( nCntKashEnd < CountKashida() )
- {
- if ( nEnd <= GetKashida( nCntKashEnd ) )
- break;
- else
- nCntKashEnd++;
- }
-
- return nCntKashEnd - nCntKash;
- }
-
- // 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;
-
- const USHORT nArrayEnd = nIdx - nStt;
-
- while ( nArrayPos < nArrayEnd )
- {
- pKernArray[ nArrayPos ] += nKashAdd;
- if ( pScrArray )
- pScrArray[ nArrayPos ] += nKashAdd;
- ++nArrayPos;
- }
-
- nKashAdd += nSpaceAdd;
- }
- }
-
- return 0;
-}
-
-/*************************************************************************
- * SwScriptInfo::IsArabicLanguage()
- *************************************************************************/
-
-sal_Bool SwScriptInfo::IsArabicLanguage( LanguageType aLang )
-{
- return LANGUAGE_ARABIC == aLang || LANGUAGE_ARABIC_SAUDI_ARABIA == aLang ||
- LANGUAGE_ARABIC_IRAQ == aLang || LANGUAGE_ARABIC_EGYPT == aLang ||
- LANGUAGE_ARABIC_LIBYA == aLang || LANGUAGE_ARABIC_ALGERIA == aLang ||
- LANGUAGE_ARABIC_MOROCCO == aLang || LANGUAGE_ARABIC_TUNISIA == aLang ||
- LANGUAGE_ARABIC_OMAN == aLang || LANGUAGE_ARABIC_YEMEN == aLang ||
- LANGUAGE_ARABIC_SYRIA == aLang || LANGUAGE_ARABIC_JORDAN == aLang ||
- LANGUAGE_ARABIC_LEBANON == aLang || LANGUAGE_ARABIC_KUWAIT == aLang ||
- LANGUAGE_ARABIC_UAE == aLang || LANGUAGE_ARABIC_BAHRAIN == aLang ||
- LANGUAGE_ARABIC_QATAR == aLang;
-}
-
-/*************************************************************************
- * SwScriptInfo::ThaiJustify()
- *************************************************************************/
-
-USHORT SwScriptInfo::ThaiJustify( const XubString& rTxt, long* pKernArray,
- long* pScrArray, xub_StrLen nStt,
- xub_StrLen nLen, xub_StrLen nNumberOfBlanks,
- long nSpaceAdd )
-{
- ASSERT( nStt + nLen <= rTxt.Len(), "String in ThaiJustify too small" )
-
- SwTwips nNumOfTwipsToDistribute = nSpaceAdd * nNumberOfBlanks /
- SPACING_PRECISION_FACTOR;
-
- long nSpaceSum = 0;
- USHORT nCnt = 0;
-
- for ( USHORT nI = 0; nI < nLen; ++nI )
- {
- const xub_Unicode cCh = rTxt.GetChar( nStt + nI );
-
- // check if character is not above or below base
- if ( ( 0xE34 > cCh || cCh > 0xE3A ) &&
- ( 0xE47 > cCh || cCh > 0xE4E ) && cCh != 0xE31 )
- {
- if ( nNumberOfBlanks > 0 )
- {
- nSpaceAdd = nNumOfTwipsToDistribute / nNumberOfBlanks;
- --nNumberOfBlanks;
- nNumOfTwipsToDistribute -= nSpaceAdd;
- }
- nSpaceSum += nSpaceAdd;
- ++nCnt;
- }
-
- if ( pKernArray ) pKernArray[ nI ] += nSpaceSum;
- if ( pScrArray ) pScrArray[ nI ] += nSpaceSum;
- }
-
- return nCnt;
-}
-
-/*************************************************************************
- * SwScriptInfo::GetScriptInfo()
- *************************************************************************/
-
-SwScriptInfo* SwScriptInfo::GetScriptInfo( const SwTxtNode& rTNd,
- sal_Bool bAllowInvalid )
-{
- SwClientIter aClientIter( (SwTxtNode&)rTNd );
- SwClient* pLast = aClientIter.GoStart();
- SwScriptInfo* pScriptInfo = 0;
-
- while( pLast )
- {
- if ( pLast->ISA( SwTxtFrm ) )
- {
- pScriptInfo = (SwScriptInfo*)((SwTxtFrm*)pLast)->GetScriptInfo();
- if ( pScriptInfo )
- {
- if ( !bAllowInvalid && STRING_LEN != pScriptInfo->GetInvalidity() )
- pScriptInfo = 0;
- else break;
- }
- }
- pLast = ++aClientIter;
- }
-
- return pScriptInfo;
-}
-
-/*************************************************************************
- * SwScriptInfo::CalcHiddenRanges()
- *
- * Returns a MultiSection indicating the hidden ranges.
- *************************************************************************/
-
-void SwScriptInfo::CalcHiddenRanges( const SwTxtNode& rNode, MultiSelection& rHiddenMulti )
-{
- const SfxPoolItem* pItem = 0;
- if( SFX_ITEM_SET == rNode.GetSwAttrSet().GetItemState( RES_CHRATR_HIDDEN, TRUE, &pItem ) &&
- ((SvxCharHiddenItem*)pItem)->GetValue() )
- {
- rHiddenMulti.SelectAll();
- }
-
- const SwpHints* pHints = rNode.GetpSwpHints();
- const SwTxtAttr* pTxtAttr = 0;
- bool bHidden = false;
- bool bHiddenSelect = false;
-
- if( pHints )
- {
- USHORT nTmp = 0;
-
- while( nTmp < pHints->GetStartCount() )
- {
- pTxtAttr = pHints->GetStart( nTmp++ );
- switch ( pTxtAttr->Which() )
- {
- case RES_CHRATR_HIDDEN:
- {
- bHidden = sal_True;
- bHiddenSelect = pTxtAttr->GetCharHidden().GetValue();
- }
- break;
- case RES_TXTATR_CHARFMT:
- {
- SwCharFmt* pFmt;
- const SfxPoolItem* pItem;
- pFmt = pTxtAttr->GetCharFmt().GetCharFmt();
- if ( pFmt )
- {
- if( SFX_ITEM_SET == pFmt->GetAttrSet().
- GetItemState( RES_CHRATR_HIDDEN, sal_True, &pItem ) )
- {
- bHidden = sal_True;
- bHiddenSelect = ((SvxCharHiddenItem*)pItem)->GetValue();
- }
- }
- }
- break;
- }
- if( bHidden )
- {
- xub_StrLen nSt = *pTxtAttr->GetStart();
- xub_StrLen nEnd = *pTxtAttr->GetEnd();
- if( nEnd > nSt )
- {
- Range aTmp( nSt, nEnd - 1 );
- if( bHidden )
- rHiddenMulti.Select( aTmp, bHiddenSelect );
- }
- bHidden = sal_False;
- }
- }
- }
-
- // If there are any hidden ranges in the current text node, we have
- // to unhide the redlining ranges:
- const IDocumentRedlineAccess& rIDRA = *rNode.getIDocumentRedlineAccess();
- if ( rHiddenMulti.GetRangeCount() && IDocumentRedlineAccess::IsShowChanges( rIDRA.GetRedlineMode() ) )
- {
- USHORT nAct = rIDRA.GetRedlinePos( rNode, USHRT_MAX );
-
- for ( ; nAct < rIDRA.GetRedlineTbl().Count(); nAct++ )
- {
- const SwRedline* pRed = rIDRA.GetRedlineTbl()[ nAct ];
-
- if ( pRed->Start()->nNode > rNode.GetIndex() )
- break;
-
- xub_StrLen nRedlStart;
- xub_StrLen nRedlnEnd;
- pRed->CalcStartEnd( rNode.GetIndex(), nRedlStart, nRedlnEnd );
- if ( nRedlnEnd > nRedlStart )
- {
- Range aTmp( nRedlStart, nRedlnEnd - 1 );
- rHiddenMulti.Select( aTmp, false );
- }
- }
- }
-
- //
- // We calculated a lot of stuff. Finally we can update the flags at the text node.
- //
- const bool bNewContainsHiddenChars = rHiddenMulti.GetRangeCount() > 0;
- bool bNewHiddenCharsHidePara = false;
- if ( bNewContainsHiddenChars )
- {
- const Range& rRange = rHiddenMulti.GetRange( 0 );
- const xub_StrLen nHiddenStart = (xub_StrLen)rRange.Min();
- const xub_StrLen nHiddenEnd = (xub_StrLen)rRange.Max() + 1;
- bNewHiddenCharsHidePara = ( nHiddenStart == 0 && nHiddenEnd >= rNode.GetTxt().Len() );
- }
- rNode.SetHiddenCharAttribute( bNewHiddenCharsHidePara, bNewContainsHiddenChars );
-}
-
diff --git a/sw/source/core/text/inftxt.cxx b/sw/source/core/text/inftxt.cxx
index e367f72a7fd5..268c30a802e7 100644
--- a/sw/source/core/text/inftxt.cxx
+++ b/sw/source/core/text/inftxt.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: inftxt.cxx,v $
- * $Revision: 1.123 $
+ * $Revision: 1.123.20.1 $
*
* This file is part of OpenOffice.org.
*
@@ -36,7 +36,6 @@
#include <svtools/linguprops.hxx>
#include <svtools/lingucfg.hxx>
#include <hintids.hxx>
-#include <svtools/ctloptions.hxx>
#include <sfx2/printer.hxx>
#include <svx/hyznitem.hxx>
#include <svx/escpitem.hxx>
@@ -344,7 +343,7 @@ void SwTxtSizeInfo::CtorInitTxtSizeInfo( SwTxtFrm *pFrame, SwFont *pNewFnt,
nDirection = DIR_LEFT2RIGHT;
}
- LanguageType eLang;
+/* LanguageType eLang;
const SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions();
if ( SvtCTLOptions::NUMERALS_HINDI == rCTLOptions.GetCTLTextNumerals() )
eLang = LANGUAGE_ARABIC;
@@ -354,7 +353,7 @@ void SwTxtSizeInfo::CtorInitTxtSizeInfo( SwTxtFrm *pFrame, SwFont *pNewFnt,
eLang = (LanguageType)::GetAppLanguage();
pOut->SetDigitLanguage( eLang );
- pRef->SetDigitLanguage( eLang );
+ pRef->SetDigitLanguage( eLang );*/
//
// The Options
diff --git a/sw/source/core/text/itradj.cxx b/sw/source/core/text/itradj.cxx
index e31afabf0762..b4b16d3f3ecb 100644
--- a/sw/source/core/text/itradj.cxx
+++ b/sw/source/core/text/itradj.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: itradj.cxx,v $
- * $Revision: 1.24 $
+ * $Revision: 1.24.112.4 $
*
* This file is part of OpenOffice.org.
*
@@ -30,6 +30,10 @@
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
+#ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
+#include <com/sun/star/i18n/ScriptType.hdl>
+#endif
+#include <vcl/outdev.hxx>
#include <IDocumentSettingAccess.hxx>
#include "frame.hxx" // CalcFlyAdjust()
@@ -45,6 +49,8 @@
#define MIN_TAB_WIDTH 60
+using namespace ::com::sun::star;
+
/*************************************************************************
* SwTxtAdjuster::FormatBlock()
*************************************************************************/
@@ -124,6 +130,140 @@ void SwTxtAdjuster::FormatBlock( )
}
/*************************************************************************
+ * lcl_CheckKashidaPositions()
+ *************************************************************************/
+bool lcl_CheckKashidaPositions( SwScriptInfo& rSI, SwTxtSizeInfo& rInf, SwTxtIter& rItr,
+ xub_StrLen& nKashidas, xub_StrLen& nGluePortion )
+{
+ // i60594 validate Kashida justification
+ xub_StrLen nIdx = rItr.GetStart();
+ xub_StrLen nEnd = rItr.GetEnd();
+
+ // Note on calling KashidaJustify():
+ // Kashida positions may be marked as invalid. Therefore KashidaJustify may return the clean
+ // total number of kashida positions, or the number of kashida positions after some positions
+ // have been dropped.
+ // Here we want the clean total, which is OK: We have called ClearKashidaInvalid() before.
+ nKashidas = rSI.KashidaJustify ( 0, 0, rItr.GetStart(), rItr.GetLength(), 0 );
+
+ if (!nKashidas) // nothing to do
+ return true;
+
+ // kashida positions found in SwScriptInfo are not necessarily valid in every font
+ // if two characters are replaced by a ligature glyph, there will be no place for a kashida
+ xub_StrLen* pKashidaPos = new xub_StrLen [ nKashidas ];
+ xub_StrLen* pKashidaPosDropped = new xub_StrLen [ nKashidas ];
+ rSI.GetKashidaPositions ( nIdx, rItr.GetLength(), pKashidaPos );
+ xub_StrLen nKashidaIdx = 0;
+ while ( nKashidas && nIdx < nEnd )
+ {
+ rItr.SeekAndChgAttrIter( nIdx, rInf.GetOut() );
+ xub_StrLen nNext = rItr.GetNextAttr();
+
+ // is there also a script change before?
+ // if there is, nNext should point to the script change
+ xub_StrLen nNextScript = rSI.NextScriptChg( nIdx );
+ if( nNextScript < nNext )
+ nNext = nNextScript;
+
+ if ( nNext == STRING_LEN || nNext > nEnd )
+ nNext = nEnd;
+ xub_StrLen nKashidasInAttr = rSI.KashidaJustify ( 0, 0, nIdx, nNext - nIdx );
+ if ( nKashidasInAttr )
+ {
+ xub_StrLen nKashidasDropped = 0;
+ if ( !SwScriptInfo::IsArabicText( rInf.GetTxt(), nIdx, nNext - nIdx ) )
+ {
+ nKashidasDropped = nKashidasInAttr;
+ nKashidas -= nKashidasDropped;
+ }
+ else
+ {
+ ULONG nOldLayout = rInf.GetOut()->GetLayoutMode();
+ rInf.GetOut()->SetLayoutMode ( nOldLayout | TEXT_LAYOUT_BIDI_RTL );
+ nKashidasDropped = rInf.GetOut()->ValidateKashidas ( rInf.GetTxt(), nIdx, nNext - nIdx,
+ nKashidasInAttr, pKashidaPos + nKashidaIdx,
+ pKashidaPosDropped );
+ rInf.GetOut()->SetLayoutMode ( nOldLayout );
+ if ( nKashidasDropped )
+ {
+ rSI.MarkKashidasInvalid ( nKashidasDropped, pKashidaPosDropped );
+ nKashidas -= nKashidasDropped;
+ nGluePortion -= nKashidasDropped;
+ }
+ }
+ nKashidaIdx += nKashidasInAttr;
+ }
+ nIdx = nNext;
+ }
+ delete[] pKashidaPos;
+ delete[] pKashidaPosDropped;
+
+ // return false if all kashidas have been eliminated
+ return (nKashidas > 0);
+}
+
+/*************************************************************************
+ * lcl_CheckKashidaWidth()
+ *************************************************************************/
+bool lcl_CheckKashidaWidth ( SwScriptInfo& rSI, SwTxtSizeInfo& rInf, SwTxtIter& rItr, xub_StrLen& nKashidas,
+ xub_StrLen& nGluePortion, const long nGluePortionWidth, long& nSpaceAdd )
+{
+ // check kashida width
+ // if width is smaller than minimal kashida width allowed by fonts in the current line
+ // drop one kashida after the other until kashida width is OK
+ bool bAddSpaceChanged;
+ while ( nKashidas )
+ {
+ bAddSpaceChanged = false;
+ xub_StrLen nIdx = rItr.GetStart();
+ xub_StrLen nEnd = rItr.GetEnd();
+ while ( nIdx < nEnd )
+ {
+ rItr.SeekAndChgAttrIter( nIdx, rInf.GetOut() );
+ xub_StrLen nNext = rItr.GetNextAttr();
+
+ // is there also a script change before?
+ // if there is, nNext should point to the script change
+ xub_StrLen nNextScript = rSI.NextScriptChg( nIdx );
+ if( nNextScript < nNext )
+ nNext = nNextScript;
+
+ if ( nNext == STRING_LEN || nNext > nEnd )
+ nNext = nEnd;
+ xub_StrLen nKashidasInAttr = rSI.KashidaJustify ( 0, 0, nIdx, nNext - nIdx );
+
+ long nFontMinKashida = rInf.GetOut()->GetMinKashida();
+ if ( nFontMinKashida && nKashidasInAttr && SwScriptInfo::IsArabicText( rInf.GetTxt(), nIdx, nNext - nIdx ) )
+ {
+ xub_StrLen nKashidasDropped = 0;
+ while ( nKashidas && nGluePortion && nKashidasInAttr &&
+ nSpaceAdd / SPACING_PRECISION_FACTOR < nFontMinKashida )
+ {
+ --nGluePortion;
+ --nKashidas;
+ --nKashidasInAttr;
+ ++nKashidasDropped;
+ if( !nKashidas || !nGluePortion ) // nothing left, return false to
+ return false; // do regular blank justification
+
+ nSpaceAdd = nGluePortionWidth / nGluePortion;
+ bAddSpaceChanged = true;
+ }
+ if( nKashidasDropped )
+ rSI.MarkKashidasInvalid( nKashidasDropped, nIdx, nNext - nIdx );
+ }
+ if ( bAddSpaceChanged )
+ break; // start all over again
+ nIdx = nNext;
+ }
+ if ( !bAddSpaceChanged )
+ break; // everything was OK
+ }
+ return true;
+}
+
+/*************************************************************************
* SwTxtAdjuster::CalcNewBlock()
*
* CalcNewBlock() darf erst nach CalcLine() gerufen werden !
@@ -132,7 +272,7 @@ void SwTxtAdjuster::FormatBlock( )
*************************************************************************/
void SwTxtAdjuster::CalcNewBlock( SwLineLayout *pCurrent,
- const SwLinePortion *pStopAt, SwTwips nReal )
+ const SwLinePortion *pStopAt, SwTwips nReal, bool bSkipKashida )
{
ASSERT( GetInfo().IsMulti() || SVX_ADJUST_BLOCK == GetAdjust(),
"CalcNewBlock: Why?" );
@@ -143,9 +283,31 @@ void SwTxtAdjuster::CalcNewBlock( SwLineLayout *pCurrent,
xub_StrLen nCharCnt = 0;
MSHORT nSpaceIdx = 0;
+ // i60591: hennerdrews
+ SwScriptInfo& rSI = GetInfo().GetParaPortion()->GetScriptInfo();
+ SwTxtSizeInfo aInf ( GetTxtFrm() );
+ SwTxtIter aItr ( GetTxtFrm(), &aInf );
+
+ if ( rSI.CountKashida() )
+ {
+ while (aItr.GetCurr() != pCurrent && aItr.GetNext())
+ aItr.Next();
+
+ if( bSkipKashida )
+ {
+ rSI.SetNoKashidaLine ( aItr.GetStart(), aItr.GetLength());
+ }
+ else
+ {
+ rSI.ClearKashidaInvalid ( aItr.GetStart(), aItr.GetLength() );
+ rSI.ClearNoKashidaLine( aItr.GetStart(), aItr.GetLength() );
+ }
+ }
+
// Nicht vergessen:
// CalcRightMargin() setzt pCurrent->Width() auf die Zeilenbreite !
- CalcRightMargin( pCurrent, nReal );
+ if (!bSkipKashida)
+ CalcRightMargin( pCurrent, nReal );
// --> FME 2005-06-08 #i49277#
const sal_Bool bDoNotJustifyLinesWithManualBreak =
@@ -184,7 +346,7 @@ void SwTxtAdjuster::CalcNewBlock( SwLineLayout *pCurrent,
else if( pMulti->IsDouble() )
nGluePortion = nGluePortion + ((SwDoubleLinePortion*)pMulti)->GetSpaceCnt();
else if ( pMulti->IsBidi() )
- nGluePortion = nGluePortion + ((SwBidiPortion*)pMulti)->GetSpaceCnt();
+ nGluePortion = nGluePortion + ((SwBidiPortion*)pMulti)->GetSpaceCnt( GetInfo() ); // i60594
}
if( pPos->InGlueGrp() )
@@ -197,9 +359,40 @@ void SwTxtAdjuster::CalcNewBlock( SwLineLayout *pCurrent,
const long nGluePortionWidth = static_cast<SwGluePortion*>(pPos)->GetPrtGlue() *
SPACING_PRECISION_FACTOR;
+ xub_StrLen nKashidas = 0;
+ if( nGluePortion && rSI.CountKashida() && !bSkipKashida )
+ {
+ // kashida positions found in SwScriptInfo are not necessarily valid in every font
+ // if two characters are replaced by a ligature glyph, there will be no place for a kashida
+ if ( !lcl_CheckKashidaPositions ( rSI, aInf, aItr, nKashidas, nGluePortion ))
+ {
+ // all kashida positions are invalid
+ // do regular blank justification
+ pCurrent->FinishSpaceAdd();
+ GetInfo().SetIdx( nStart );
+ CalcNewBlock( pCurrent, pStopAt, nReal, true );
+ return;
+ }
+ }
+
if( nGluePortion )
{
- const long nSpaceAdd = nGluePortionWidth / nGluePortion;
+ long nSpaceAdd = nGluePortionWidth / nGluePortion;
+
+ // i60594
+ if( rSI.CountKashida() && !bSkipKashida )
+ {
+ if( !lcl_CheckKashidaWidth( rSI, aInf, aItr, nKashidas, nGluePortion, nGluePortionWidth, nSpaceAdd ))
+ {
+ // no kashidas left
+ // do regular blank justification
+ pCurrent->FinishSpaceAdd();
+ GetInfo().SetIdx( nStart );
+ CalcNewBlock( pCurrent, pStopAt, nReal, true );
+ return;
+ }
+ }
+
pCurrent->SetLLSpaceAdd( nSpaceAdd , nSpaceIdx );
pPos->Width( ( (SwGluePortion*)pPos )->GetFixWidth() );
}
diff --git a/sw/source/core/text/itrcrsr.cxx b/sw/source/core/text/itrcrsr.cxx
index 21012c8eda7b..6436fe23fc20 100644
--- a/sw/source/core/text/itrcrsr.cxx
+++ b/sw/source/core/text/itrcrsr.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: itrcrsr.cxx,v $
- * $Revision: 1.81 $
+ * $Revision: 1.81.40.1 $
*
* This file is part of OpenOffice.org.
*
@@ -506,6 +506,7 @@ void SwTxtCursor::_GetCharRect( SwRect* pOrig, const xub_StrLen nOfst,
SwTwips nTmpFirst = 0;
SwLinePortion *pPor = pCurr->GetFirstPortion();
SwBidiPortion* pLastBidiPor = 0;
+ SwTwips nLastBidiPorWidth = 0;
SvUShorts* pKanaComp = pCurr->GetpKanaComp();
MSHORT nSpaceIdx = 0;
MSHORT nKanaIdx = 0;
@@ -649,7 +650,11 @@ void SwTxtCursor::_GetCharRect( SwRect* pOrig, const xub_StrLen nOfst,
// cursor level
if ( ((SwMultiPortion*)pPor)->IsBidi() &&
aInf.GetIdx() + pPor->GetLen() == nOfst )
+ {
pLastBidiPor = (SwBidiPortion*)pPor;
+ nLastBidiPorWidth = pLastBidiPor->Width() +
+ pLastBidiPor->CalcSpacing( nSpaceAdd, aInf );;
+ }
}
aInf.SetIdx( aInf.GetIdx() + pPor->GetLen() );
@@ -1086,8 +1091,7 @@ void SwTxtCursor::_GetCharRect( SwRect* pOrig, const xub_StrLen nOfst,
{
// we came from inside the bidi portion, we want to blink
// behind the portion
- pOrig->Pos().X() -= pLastBidiPor->Width() +
- pLastBidiPor->CalcSpacing( nSpaceAdd, aInf );
+ pOrig->Pos().X() -= nLastBidiPorWidth;
// Again, there is a special case: logically behind
// the portion can actually mean that the cursor is inside
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 0fe7b2ffe31c..00440427eaf8 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: itrform2.cxx,v $
- * $Revision: 1.107 $
+ * $Revision: 1.107.20.2 $
*
* This file is part of OpenOffice.org.
*
@@ -879,17 +879,17 @@ SwTxtPortion *SwTxtFormatter::NewTxtPortion( SwTxtFormatInfo &rInf )
Seek( rInf.GetIdx() );
SwTxtPortion *pPor = WhichTxtPor( rInf );
- // maximal bis zum naechsten Attributwchsel.
- xub_StrLen nNextAttr = GetNextAttr();
+ // until next attribute change:
+ const xub_StrLen nNextAttr = GetNextAttr();
xub_StrLen nNextChg = Min( nNextAttr, rInf.GetTxt().Len() );
- nNextAttr = pScriptInfo->NextScriptChg( rInf.GetIdx() );
+ // end of script type:
+ const xub_StrLen nNextScript = pScriptInfo->NextScriptChg( rInf.GetIdx() );
+ nNextChg = Min( nNextChg, nNextScript );
- xub_StrLen nNextDir = pScriptInfo->NextDirChg( rInf.GetIdx() );
- nNextAttr = Min( nNextAttr, nNextDir );
-
- if( nNextChg > nNextAttr )
- nNextChg = nNextAttr;
+ // end of direction:
+ const xub_StrLen nNextDir = pScriptInfo->NextDirChg( rInf.GetIdx() );
+ nNextChg = Min( nNextChg, nNextDir );
// 7515, 7516, 3470, 6441 : Turbo-Boost
// Es wird unterstellt, dass die Buchstaben eines Fonts nicht
diff --git a/sw/source/core/text/itrtxt.hxx b/sw/source/core/text/itrtxt.hxx
index 923748ee901b..58e77479f51e 100644
--- a/sw/source/core/text/itrtxt.hxx
+++ b/sw/source/core/text/itrtxt.hxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: itrtxt.hxx,v $
- * $Revision: 1.22 $
+ * $Revision: 1.21.40.3 $
*
* This file is part of OpenOffice.org.
*
@@ -230,7 +230,7 @@ protected:
inline SwTxtAdjuster(SwTxtNode* pTxtNode) : SwTxtMargin(pTxtNode) { }
// spannt beim Blocksatz die Glues auf.
void CalcNewBlock( SwLineLayout *pCurr, const SwLinePortion *pStopAt,
- SwTwips nReal = 0 );
+ SwTwips nReal = 0, bool bSkipKashida = false );
SwTwips CalcKanaAdj( SwLineLayout *pCurr );
public:
inline SwTxtAdjuster( SwTxtFrm *pTxtFrm, SwTxtSizeInfo *pTxtSizeInf ) : SwTxtMargin(pTxtFrm!=NULL?pTxtFrm->GetTxtNode():NULL)
diff --git a/sw/source/core/text/porfld.cxx b/sw/source/core/text/porfld.cxx
index ba7fd2813155..8443bf2c2e9b 100644
--- a/sw/source/core/text/porfld.cxx
+++ b/sw/source/core/text/porfld.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: porfld.cxx,v $
- * $Revision: 1.62 $
+ * $Revision: 1.62.110.1 $
*
* This file is part of OpenOffice.org.
*
@@ -262,6 +262,25 @@ void SwFldPortion::CheckScript( const SwTxtSizeInfo &rInf )
ubidi_close( pBidi );
const xub_StrLen nNextDirChg = (xub_StrLen)nEnd;
nNextScriptChg = Min( nNextScriptChg, nNextDirChg );
+
+ // #i89825# change the script type also to CTL
+ // if there is no strong LTR char in the LTR run (numbers)
+ if ( nCurrDir != UBIDI_RTL )
+ {
+ nCurrDir = UBIDI_RTL;
+ for ( xub_StrLen nCharIdx = 0; nCharIdx < nEnd; ++nCharIdx )
+ {
+ UCharDirection nCharDir = u_charDirection ( aTxt.GetChar ( nCharIdx ));
+ if ( nCharDir == U_LEFT_TO_RIGHT ||
+ nCharDir == U_LEFT_TO_RIGHT_EMBEDDING ||
+ nCharDir == U_LEFT_TO_RIGHT_OVERRIDE )
+ {
+ nCurrDir = UBIDI_LTR;
+ break;
+ }
+ }
+ }
+
if ( nCurrDir == UBIDI_RTL )
nTmp = SW_CTL;
}
diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
index 9adc64345cd0..bcd08a324b61 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: porlay.cxx,v $
- * $Revision: 1.67 $
+ * $Revision: 1.67.14.4 $
*
* This file is part of OpenOffice.org.
*
@@ -48,6 +48,9 @@
#ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
#include <com/sun/star/i18n/ScriptType.hdl>
#endif
+#ifndef _COM_SUN_STAR_I18N_CTLSCRIPTTYPE_HDL_
+#include <com/sun/star/i18n/CTLScriptType.hdl>
+#endif
#ifndef _COM_SUN_STAR_I18N_WORDTYPE_HDL
#include <com/sun/star/i18n/WordType.hdl>
#endif
@@ -58,6 +61,7 @@
#include <vcl/outdev.hxx>
#include <svx/blnkitem.hxx>
#include <tools/multisel.hxx>
+#include <unotools/charclass.hxx>
#include <charfmt.hxx>
#include <fchrfmt.hxx>
#include <docary.hxx> // SwRedlineTbl
@@ -76,6 +80,7 @@ using namespace i18n::ScriptType;
//#ifdef BIDI
#include <unicode/ubidi.h>
+#include <i18nutil/unicode.hxx> //unicode::getUnicodeScriptType
sal_Bool isAlefChar ( xub_Unicode cCh )
{
@@ -161,6 +166,16 @@ 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
@@ -171,9 +186,9 @@ sal_Bool isFeChar ( xub_Unicode cCh )
sal_Bool lcl_IsLigature( xub_Unicode cCh, xub_Unicode cNextCh )
{
// Lam + Alef
- return ( 0x644 == cCh && 0x627 == cNextCh ) ||
+ return ( isLamChar ( cCh ) && isAlefChar ( cNextCh )); // ||
// Beh + Reh
- ( 0x628 == cCh && 0x631 == cNextCh );
+ // ( 0x628 == cCh && 0x631 == cNextCh );
}
/*************************************************************************
@@ -188,6 +203,10 @@ sal_Bool lcl_ConnectToPrev( xub_Unicode cCh, xub_Unicode cPrevCh )
// Uh, there seem to be some more characters that are not connectable
// to the left. So we look for the characters that are actually connectable
// to the left. Here is the complete list of WH:
+
+ // (hennerdrewes) to do: this should be reworked
+ // use the isXXXChar functions to exclude the non-connecting character classes
+
sal_Bool bRet = 0x628 == cPrevCh ||
( 0x62A <= cPrevCh && cPrevCh <= 0x62E ) ||
( 0x633 <= cPrevCh && cPrevCh <= 0x643 ) ||
@@ -207,8 +226,21 @@ sal_Bool lcl_ConnectToPrev( xub_Unicode cCh, xub_Unicode cPrevCh )
return bRet;
}
-//#endif
-
+/*************************************************************************
+ * lcl_HasStrongLTR
+ *************************************************************************/
+ bool lcl_HasStrongLTR ( const String& rTxt, xub_StrLen nStart, xub_StrLen nEnd )
+ {
+ for ( xub_StrLen nCharIdx = nStart; nCharIdx < nEnd; ++nCharIdx )
+ {
+ const UCharDirection nCharDir = u_charDirection ( rTxt.GetChar ( nCharIdx ));
+ if ( nCharDir == U_LEFT_TO_RIGHT ||
+ nCharDir == U_LEFT_TO_RIGHT_EMBEDDING ||
+ nCharDir == U_LEFT_TO_RIGHT_OVERRIDE )
+ return true;
+ }
+ return false;
+ }
/*************************************************************************
* SwLineLayout::~SwLineLayout()
@@ -981,11 +1013,32 @@ void SwScriptInfo::InitScriptInfo( const SwTxtNode& rNode, sal_Bool bRTL )
"Inserting WEAK into SwScriptInfo structure" );
ASSERT( STRING_LEN != nChg, "65K? Strange length of script section" );
- nChg = (xub_StrLen)pBreakIt->xBreak->endOfScript( rTxt, nChg, nScript );
+ xub_StrLen nSearchStt = nChg;
+ nChg = (xub_StrLen)pBreakIt->xBreak->endOfScript( rTxt, nSearchStt, nScript );
if ( nChg > rTxt.Len() )
nChg = rTxt.Len();
+ // --> FME 2008-09-17 #i28203#
+ // for 'complex' portions, we make sure that a portion does not contain more
+ // than one script:
+ if( pBreakIt->xCTLDetect.is() && i18n::ScriptType::COMPLEX == nScript )
+ {
+ const short nScriptType = pBreakIt->xCTLDetect->getCTLScriptType( rTxt, nSearchStt );
+ xub_StrLen nNextCTLScriptStart = nSearchStt;
+ short nCurrentScriptType = nScriptType;
+ while( com::sun::star::i18n::CTLScriptType::CTL_UNKNOWN == nCurrentScriptType || nScriptType == nCurrentScriptType )
+ {
+ nNextCTLScriptStart = (xub_StrLen)pBreakIt->xCTLDetect->endOfCTLScriptType( rTxt, nNextCTLScriptStart );
+ if( nNextCTLScriptStart < rTxt.Len() && nNextCTLScriptStart < nChg )
+ nCurrentScriptType = pBreakIt->xCTLDetect->getCTLScriptType( rTxt, nNextCTLScriptStart );
+ else
+ break;
+ }
+ nChg = Min( nChg, nNextCTLScriptStart );
+ }
+ // <--
+
aScriptChg.Insert( nChg, nCnt );
aScriptType.Insert( nScript, nCnt++ );
@@ -1206,7 +1259,7 @@ void SwScriptInfo::InitScriptInfo( const SwTxtNode& rNode, sal_Bool bRTL )
// 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;
@@ -1260,15 +1313,21 @@ void SwScriptInfo::InitScriptInfo( const SwTxtNode& rNode, sal_Bool bRTL )
{
UpdateBidiInfo( rTxt );
- // #i16354# Change script type for RTL text to CTL.
+ // #i16354# Change script type for RTL text to CTL:
+ // 1. All text in RTL runs will use the CTL font
+ // #i89825# change the script type also to CTL (hennerdrewes)
+ // 2. Text in embedded LTR runs that does not have any strong LTR characters (numbers!)
for ( USHORT nDirIdx = 0; nDirIdx < aDirChg.Count(); ++nDirIdx )
{
- if ( GetDirType( nDirIdx ) == UBIDI_RTL )
- {
+ const BYTE nCurrDirType = GetDirType( nDirIdx );
// nStart ist start of RTL run:
const xub_StrLen nStart = nDirIdx > 0 ? GetDirChg( nDirIdx - 1 ) : 0;
// nEnd is end of RTL run:
const xub_StrLen nEnd = GetDirChg( nDirIdx );
+
+ if ( nCurrDirType % 2 == UBIDI_RTL || // text in RTL run
+ ( nCurrDirType > UBIDI_LTR && !lcl_HasStrongLTR( rTxt, nStart, nEnd ) ) ) // non-strong text in embedded LTR run
+ {
// nScriptIdx points into the ScriptArrays:
USHORT nScriptIdx = 0;
@@ -1279,8 +1338,8 @@ void SwScriptInfo::InitScriptInfo( const SwTxtNode& rNode, sal_Bool bRTL )
while ( GetScriptChg( nScriptIdx ) <= nStart )
++nScriptIdx;
- xub_StrLen nStartPosOfGroup = nScriptIdx ? GetScriptChg( nScriptIdx - 1 ) : 0;
- BYTE nScriptTypeOfGroup = GetScriptType( nScriptIdx );
+ const xub_StrLen nStartPosOfGroup = nScriptIdx ? GetScriptChg( nScriptIdx - 1 ) : 0;
+ const BYTE nScriptTypeOfGroup = GetScriptType( nScriptIdx );
ASSERT( nStartPosOfGroup <= nStart && GetScriptChg( nScriptIdx ) > nStart,
"Script override with CTL font trouble" )
@@ -1804,12 +1863,22 @@ long SwScriptInfo::Compress( sal_Int32* pKernArray, xub_StrLen nIdx, xub_StrLen
* SwScriptInfo::KashidaJustify()
*************************************************************************/
-USHORT SwScriptInfo::KashidaJustify( sal_Int32* pKernArray, sal_Int32* pScrArray,
- xub_StrLen nStt, xub_StrLen nLen,
- long nSpaceAdd ) const
+// Note on calling KashidaJustify():
+// Kashida positions may be marked as invalid. Therefore KashidaJustify may return the clean
+// total number of kashida positions, or the number of kashida positions after some positions
+// have been dropped, depending on the state of the aKashidaInvalid array.
+
+USHORT SwScriptInfo::KashidaJustify( sal_Int32* pKernArray,
+ sal_Int32* pScrArray,
+ xub_StrLen nStt,
+ xub_StrLen nLen,
+ long nSpaceAdd ) const
{
ASSERT( nLen, "Kashida justification without text?!" )
+ if( !IsKashidaLine(nStt))
+ return STRING_LEN;
+
// evaluate kashida informatin in collected in SwScriptInfo
USHORT nCntKash = 0;
@@ -1823,23 +1892,32 @@ USHORT SwScriptInfo::KashidaJustify( sal_Int32* pKernArray, sal_Int32* pScrArray
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++;
- }
+ if ( nEnd <= GetKashida( nCntKashEnd ) )
+ break;
+ else
+ nCntKashEnd++;
+ }
- return nCntKashEnd - nCntKash;
+ USHORT nActualKashCount = nCntKashEnd - nCntKash;
+ for ( USHORT i = nCntKash; i < nCntKashEnd; ++i )
+ {
+ if ( nActualKashCount && !IsKashidaValid ( i ) )
+ --nActualKashCount;
}
+ if ( !pKernArray )
+ return nActualKashCount;
+
// do nothing if there is no more kashida
if ( nCntKash < CountKashida() )
{
+ // skip any invalid kashidas
+ while ( ! IsKashidaValid ( nCntKash ) && nCntKash < nCntKashEnd )
+ ++nCntKash;
+
xub_StrLen nKashidaPos = GetKashida( nCntKash );
xub_StrLen nIdx = nKashidaPos;
long nKashAdd = nSpaceAdd;
@@ -1849,7 +1927,11 @@ USHORT SwScriptInfo::KashidaJustify( sal_Int32* pKernArray, sal_Int32* pScrArray
USHORT nArrayPos = nIdx - nStt;
// next kashida position
- nIdx = ++nCntKash < CountKashida() ? GetKashida( nCntKash ) : nEnd;
+ ++nCntKash;
+ while ( ! IsKashidaValid ( nCntKash ) && nCntKash < nCntKashEnd )
+ ++nCntKash;
+
+ nIdx = nCntKash < CountKashida() && IsKashidaValid ( nCntKash ) ? GetKashida( nCntKash ) : nEnd;
if ( nIdx > nEnd )
nIdx = nEnd;
@@ -1859,10 +1941,9 @@ USHORT SwScriptInfo::KashidaJustify( sal_Int32* pKernArray, sal_Int32* pScrArray
{
pKernArray[ nArrayPos ] += nKashAdd;
if ( pScrArray )
- pScrArray[ nArrayPos ] += nKashAdd;
+ pScrArray[ nArrayPos ] += nKashAdd;
++nArrayPos;
}
-
nKashAdd += nSpaceAdd;
}
}
@@ -1871,20 +1952,230 @@ USHORT SwScriptInfo::KashidaJustify( sal_Int32* pKernArray, sal_Int32* pScrArray
}
/*************************************************************************
- * SwScriptInfo::IsArabicLanguage()
+ * SwScriptInfo::IsArabicText()
+ *
+ * Checks if the current text is 'Arabic' text. Note that only the first
+ * character has to be checked because a ctl portion only contains one
+ * script, see NewTxtPortion
+ *************************************************************************/
+sal_Bool SwScriptInfo::IsArabicText( const XubString& rTxt, xub_StrLen nStt, xub_StrLen nLen )
+{
+ using namespace ::com::sun::star::i18n;
+ static ScriptTypeList typeList[] = {
+ { UnicodeScript_kArabic, UnicodeScript_kArabic, UnicodeScript_kArabic }, // 11,
+ { UnicodeScript_kScriptCount, UnicodeScript_kScriptCount, UnicodeScript_kScriptCount } // 88
+ };
+
+ // go forward if current position does not hold a regular character:
+ const CharClass& rCC = GetAppCharClass();
+ sal_Int32 nIdx = nStt;
+ const xub_StrLen nEnd = nStt + nLen;
+ while ( nIdx < nEnd && !rCC.isLetterNumeric( rTxt, (xub_StrLen)nIdx ) )
+ {
+ ++nIdx;
+ }
+
+ if( nIdx == nEnd )
+{
+ // no regular character found in this portion. Go backward:
+ --nIdx;
+ while ( nIdx >= 0 && !rCC.isLetterNumeric( rTxt, (xub_StrLen)nIdx ) )
+ {
+ --nIdx;
+ }
+ }
+
+ if( nIdx >= 0 )
+ {
+ const xub_Unicode cCh = rTxt.GetChar( (xub_StrLen)nIdx );
+ const sal_Int16 type = unicode::getUnicodeScriptType( cCh, typeList, UnicodeScript_kScriptCount );
+ return type == UnicodeScript_kArabic;
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+ * SwScriptInfo::IsKashidaValid()
*************************************************************************/
-sal_Bool SwScriptInfo::IsArabicLanguage( LanguageType aLang )
-{
- return LANGUAGE_ARABIC == aLang || LANGUAGE_ARABIC_SAUDI_ARABIA == aLang ||
- LANGUAGE_ARABIC_IRAQ == aLang || LANGUAGE_ARABIC_EGYPT == aLang ||
- LANGUAGE_ARABIC_LIBYA == aLang || LANGUAGE_ARABIC_ALGERIA == aLang ||
- LANGUAGE_ARABIC_MOROCCO == aLang || LANGUAGE_ARABIC_TUNISIA == aLang ||
- LANGUAGE_ARABIC_OMAN == aLang || LANGUAGE_ARABIC_YEMEN == aLang ||
- LANGUAGE_ARABIC_SYRIA == aLang || LANGUAGE_ARABIC_JORDAN == aLang ||
- LANGUAGE_ARABIC_LEBANON == aLang || LANGUAGE_ARABIC_KUWAIT == aLang ||
- LANGUAGE_ARABIC_UAE == aLang || LANGUAGE_ARABIC_BAHRAIN == aLang ||
- LANGUAGE_ARABIC_QATAR == aLang;
+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 nKashPos )
+{
+ for ( xub_StrLen i = 0; i < aKashidaInvalid.Count(); ++i )
+ {
+ if ( aKashidaInvalid [ i ] == nKashPos )
+ {
+ aKashidaInvalid.Remove (i, 1);
+ return;
+ }
+ }
+}
+
+/*************************************************************************
+ * SwScriptInfo::MarkOrClearKashidaInvalid()
+ *************************************************************************/
+// bMark == true:
+// marks the first valid kashida in the given text range as invalid
+
+// bMark == false:
+// clears all kashida invalid flags in the given text range
+
+bool SwScriptInfo::MarkOrClearKashidaInvalid ( xub_StrLen nStt, xub_StrLen nLen, bool bMark, xub_StrLen nMarkCount )
+{
+ 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(bMark)
+ {
+ if ( IsKashidaValid ( nCntKash ) )
+ {
+ MarkKashidaInvalid ( nCntKash );
+ --nMarkCount;
+ if(!nMarkCount)
+ return true;
+ }
+ }
+ else
+ {
+ ClearKashidaInvalid ( nCntKash );
+ }
+ nCntKash++;
+ }
+ }
+ return false;
+}
+
+void SwScriptInfo::MarkKashidaInvalid ( xub_StrLen nKashPos )
+{
+ aKashidaInvalid.Insert( nKashPos, aKashidaInvalid.Count() );
+}
+
+/*************************************************************************
+ * SwScriptInfo::GetKashidaPositions()
+ *************************************************************************/
+// retrieve the kashida positions in the given text range
+USHORT SwScriptInfo::GetKashidaPositions ( xub_StrLen nStt, xub_StrLen nLen,
+ xub_StrLen* pKashidaPosition )
+{
+ 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
+ {
+ pKashidaPosition [ nCntKashEnd - nCntKash ] = GetKashida ( nCntKashEnd );
+ nCntKashEnd++;
+ }
+ }
+ return nCntKashEnd - nCntKash;
+}
+
+void SwScriptInfo::SetNoKashidaLine ( xub_StrLen nStt, xub_StrLen nLen )
+{
+ aNoKashidaLine.Insert( nStt, aNoKashidaLine.Count());
+ aNoKashidaLineEnd.Insert( nStt+nLen, aNoKashidaLineEnd.Count());
+}
+
+/*************************************************************************
+ * SwScriptInfo::IsKashidaLine()
+ *************************************************************************/
+// determines if the line uses kashida justification
+
+bool SwScriptInfo::IsKashidaLine ( xub_StrLen nCharIdx ) const
+{
+ for( xub_StrLen i = 0; i < aNoKashidaLine.Count(); ++i )
+ {
+ if( nCharIdx >= aNoKashidaLine[ i ] && nCharIdx < aNoKashidaLineEnd[ i ])
+ return false;
+ }
+ return true;
+}
+/*************************************************************************
+ * SwScriptInfo::ClearKashidaLine()
+ *************************************************************************/
+
+void SwScriptInfo::ClearNoKashidaLine ( xub_StrLen nStt, xub_StrLen nLen )
+{
+ xub_StrLen i = 0;
+ while( i < aNoKashidaLine.Count())
+ {
+ if( nStt + nLen >= aNoKashidaLine[ i ] && nStt < aNoKashidaLineEnd [ i ] )
+ {
+ aNoKashidaLine.Remove(i, 1);
+ aNoKashidaLineEnd.Remove(i, 1);
+ }
+ else
+ ++i;
+ }
+}
+
+/*************************************************************************
+ * SwScriptInfo::MarkKashidasInvalid()
+ *************************************************************************/
+// mark the given character indices as invalid kashida positions
+bool SwScriptInfo::MarkKashidasInvalid ( xub_StrLen nCnt, xub_StrLen* pKashidaPositions )
+{
+ ASSERT( pKashidaPositions && nCnt > 0, "Where are kashidas?" )
+
+ USHORT nCntKash = 0;
+ xub_StrLen nKashidaPosIdx = 0;
+
+ while ( nCntKash < CountKashida() && nKashidaPosIdx < nCnt )
+ {
+ if ( pKashidaPositions [nKashidaPosIdx] > GetKashida( nCntKash ) )
+ {
+ nCntKash++;
+ continue;
+ }
+
+ if ( pKashidaPositions [nKashidaPosIdx] == GetKashida( nCntKash ) && IsKashidaValid ( nCntKash ) )
+ {
+ MarkKashidaInvalid ( nCntKash );
+ }
+ else
+ return false; // something is wrong
+ nKashidaPosIdx++;
+ }
+ return true;
}
/*************************************************************************
diff --git a/sw/source/core/text/pormulti.cxx b/sw/source/core/text/pormulti.cxx
index 7e3c0881109c..0776feeeb21d 100644
--- a/sw/source/core/text/pormulti.cxx
+++ b/sw/source/core/text/pormulti.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: pormulti.cxx,v $
- * $Revision: 1.89 $
+ * $Revision: 1.89.112.2 $
*
* This file is part of OpenOffice.org.
*
@@ -231,9 +231,9 @@ SwBidiPortion::SwBidiPortion( xub_StrLen nEnd, BYTE nLv )
}
-long SwBidiPortion::CalcSpacing( long nSpaceAdd, const SwTxtSizeInfo & ) const
+long SwBidiPortion::CalcSpacing( long nSpaceAdd, const SwTxtSizeInfo& rInf ) const
{
- return HasTabulator() ? 0 : GetSpaceCnt() * nSpaceAdd / SPACING_PRECISION_FACTOR;
+ return HasTabulator() ? 0 : GetSpaceCnt(rInf) * nSpaceAdd / SPACING_PRECISION_FACTOR;
}
sal_Bool SwBidiPortion::ChgSpaceAdd( SwLineLayout* pCurr, long nSpaceAdd ) const
@@ -249,6 +249,28 @@ sal_Bool SwBidiPortion::ChgSpaceAdd( SwLineLayout* pCurr, long nSpaceAdd ) const
return bRet;
}
+xub_StrLen SwBidiPortion::GetSpaceCnt( const SwTxtSizeInfo &rInf ) const
+{
+ // Calculate number of blanks for justified alignment
+ SwLinePortion* pPor = GetRoot().GetFirstPortion();
+ xub_StrLen nTmpStart = rInf.GetIdx();
+ xub_StrLen nNull = 0;
+ xub_StrLen nBlanks;
+
+ for( nBlanks = 0; pPor; pPor = pPor->GetPortion() )
+ {
+ if( pPor->InTxtGrp() )
+ nBlanks = nBlanks + ((SwTxtPortion*)pPor)->GetSpaceCnt( rInf, nNull );
+ else if ( pPor->IsMultiPortion() &&
+ ((SwMultiPortion*)pPor)->IsBidi() )
+ nBlanks = nBlanks + ((SwBidiPortion*)pPor)->GetSpaceCnt( rInf );
+
+ ((SwTxtSizeInfo &)rInf).SetIdx( rInf.GetIdx() + pPor->GetLen() );
+ }
+ ((SwTxtSizeInfo &)rInf).SetIdx( nTmpStart );
+ return nBlanks;
+}
+
/*-----------------01.11.00 14:22-------------------
* SwDoubleLinePortion::SwDoubleLinePortion(..)
* This constructor is for the continuation of a doubleline portion
@@ -2065,25 +2087,6 @@ BOOL SwTxtFormatter::BuildMultiPortion( SwTxtFormatInfo &rInf,
}
else if ( rMulti.IsBidi() )
{
- // Calculate number of blanks for justified alignment
- SwLinePortion* pPor = rMulti.GetRoot().GetFirstPortion();
- xub_StrLen nTmpStart = rInf.GetIdx();
- xub_StrLen nNull = 0;
- xub_StrLen nBlanks;
-
- for( nBlanks = 0; pPor; pPor = pPor->GetPortion() )
- {
- if( pPor->InTxtGrp() )
- nBlanks = nBlanks + ((SwTxtPortion*)pPor)->GetSpaceCnt( rInf, nNull );
- else if ( pPor->IsMultiPortion() &&
- ((SwMultiPortion*)pPor)->IsBidi() )
- nBlanks = nBlanks + ((SwBidiPortion*)pPor)->GetSpaceCnt();
-
- rInf.SetIdx( rInf.GetIdx() + pPor->GetLen() );
- }
- rInf.SetIdx( nTmpStart );
- ((SwBidiPortion&)rMulti).SetSpaceCnt( nBlanks );
-
bRet = rMulti.GetLen() < nMultiLen || pNextFirst;
}
@@ -2390,7 +2393,12 @@ SwTxtCursorSave::SwTxtCursorSave( SwTxtCursor* pTxtCursor,
nSpaceCnt = ((SwDoubleLinePortion*)pMulti)->GetSpaceCnt();
}
else
- nSpaceCnt = ((SwBidiPortion*)pMulti)->GetSpaceCnt();
+ {
+ const xub_StrLen nOldIdx = pTxtCursor->GetInfo().GetIdx();
+ pTxtCursor->GetInfo().SetIdx ( nCurrStart );
+ nSpaceCnt = ((SwBidiPortion*)pMulti)->GetSpaceCnt(pTxtCursor->GetInfo());
+ pTxtCursor->GetInfo().SetIdx ( nOldIdx );
+ }
if( nSpaceAdd > 0 && !pMulti->HasTabulator() )
pTxtCursor->pCurr->Width( static_cast<USHORT>(nWidth + nSpaceAdd * nSpaceCnt / SPACING_PRECISION_FACTOR ) );
diff --git a/sw/source/core/text/pormulti.hxx b/sw/source/core/text/pormulti.hxx
index 93d930c97035..fcb2fea9c818 100644
--- a/sw/source/core/text/pormulti.hxx
+++ b/sw/source/core/text/pormulti.hxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: pormulti.hxx,v $
- * $Revision: 1.26 $
+ * $Revision: 1.26.112.1 $
*
* This file is part of OpenOffice.org.
*
@@ -226,15 +226,13 @@ public:
class SwBidiPortion : public SwMultiPortion
{
BYTE nLevel;
- xub_StrLen nBlanks; // Number of blanks
public:
SwBidiPortion( xub_StrLen nEnd, BYTE nLv );
inline BYTE GetLevel() const { return nLevel; }
- // Set/Get number of blanks for justified alignment
- inline void SetSpaceCnt( xub_StrLen nNew ) { nBlanks = nNew; }
- inline xub_StrLen GetSpaceCnt() const { return nBlanks; }
+ // Get number of blanks for justified alignment
+ xub_StrLen GetSpaceCnt( const SwTxtSizeInfo &rInf ) const;
// Calculates extra spacing based on number of blanks
virtual long CalcSpacing( long nSpaceAdd, const SwTxtSizeInfo &rInf ) const;
// Manipulate the spacing array at pCurr
diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx
index 0e62d09744de..43d44f56fcf3 100644
--- a/sw/source/core/text/portxt.cxx
+++ b/sw/source/core/text/portxt.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: portxt.cxx,v $
- * $Revision: 1.52 $
+ * $Revision: 1.51.112.3 $
*
* This file is part of OpenOffice.org.
*
@@ -131,6 +131,19 @@ USHORT lcl_AddSpace( const SwTxtSizeInfo &rInf, const XubString* pStr,
}
}
+ // Kashida Justification: Insert Kashidas
+ if ( nEnd > nPos && pSI && COMPLEX == nScript )
+ {
+ if ( SwScriptInfo::IsArabicText( *pStr, nPos, nEnd - nPos ) )
+ {
+ const USHORT nKashRes = pSI->KashidaJustify( 0, 0, nPos, nEnd - nPos );
+ // i60591: need to check result of KashidaJustify
+ // determine if kashida justification is applicable
+ if( nKashRes != STRING_LEN )
+ return nKashRes;
+ }
+ }
+
// Thai Justification: Each character cell gets some extra space
if ( nEnd > nPos && COMPLEX == nScript )
{
@@ -154,16 +167,6 @@ USHORT lcl_AddSpace( const SwTxtSizeInfo &rInf, const XubString* pStr,
}
}
- // Kashida Justification: Insert Kashidas
- if ( nEnd > nPos && pSI && COMPLEX == nScript )
- {
- LanguageType aLang =
- rInf.GetTxtFrm()->GetTxtNode()->GetLang( rInf.GetIdx(), 1, nScript );
-
- if ( SwScriptInfo::IsArabicLanguage( aLang ) )
- return pSI->KashidaJustify( 0, 0, nPos, nEnd - nPos );
- }
-
// Here starts the good old "Look for blanks and add space to them" part.
// Note: We do not want to add space to an isolated latin blank in front
// of some complex characters in RTL environment
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index 6acf9352d785..5feee9e59045 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: txtfrm.cxx,v $
- * $Revision: 1.108 $
+ * $Revision: 1.108.30.1 $
*
* This file is part of OpenOffice.org.
*
@@ -32,6 +32,7 @@
#include "precompiled_sw.hxx"
#include <hintids.hxx>
#include <hints.hxx>
+#include <svtools/ctloptions.hxx>
#include <sfx2/printer.hxx>
#include <sfx2/sfxuno.hxx>
#include <svx/langitem.hxx>
@@ -40,6 +41,7 @@
#include <svx/ulspitem.hxx>
#include <svx/brshitem.hxx>
#include <svx/pgrditem.hxx>
+#include <swmodule.hxx>
#include <SwSmartTagMgr.hxx>
#include <doc.hxx> // GetDoc()
#include <pagefrm.hxx> // InvalidateSpelling
@@ -288,6 +290,27 @@ void SwLayoutModeModifier::SetAuto()
((OutputDevice&)rOut).SetLayoutMode( nNewLayoutMode );
}
+SwDigitModeModifier::SwDigitModeModifier( const OutputDevice& rOutp, LanguageType eCurLang ) :
+ rOut( rOutp ), nOldLanguageType( rOutp.GetDigitLanguage() )
+{
+ LanguageType eLang = eCurLang;
+ const SvtCTLOptions::TextNumerals nTextNumerals = SW_MOD()->GetCTLOptions().GetCTLTextNumerals();
+
+ if ( SvtCTLOptions::NUMERALS_HINDI == nTextNumerals )
+ eLang = LANGUAGE_ARABIC;
+ else if ( SvtCTLOptions::NUMERALS_ARABIC == nTextNumerals )
+ eLang = LANGUAGE_ENGLISH;
+ else if ( SvtCTLOptions::NUMERALS_SYSTEM == nTextNumerals )
+ eLang = (LanguageType)::GetAppLanguage();
+
+ ((OutputDevice&)rOut).SetDigitLanguage( eLang );
+}
+
+SwDigitModeModifier::~SwDigitModeModifier()
+{
+ ((OutputDevice&)rOut).SetDigitLanguage( nOldLanguageType );
+}
+
/*************************************************************************
* SwTxtFrm::Init()
*************************************************************************/
diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx
index 4eeb8f3238bf..338417c79731 100644
--- a/sw/source/core/txtnode/fntcache.cxx
+++ b/sw/source/core/txtnode/fntcache.cxx
@@ -1512,10 +1512,24 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
}
}
- // Thai Justification
+ // Kashida Justification
if ( SW_CTL == nActual && nSpaceAdd )
{
+ if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) )
+ {
+ if ( pSI && pSI->CountKashida() &&
+ pSI->KashidaJustify( pKernArray, 0, rInf.GetIdx(),
+ rInf.GetLen(), nSpaceAdd ) != STRING_LEN )
+ {
+ bSpecialJust = sal_True;
+ nSpaceAdd = 0;
+ }
+ }
+ }
+ // Thai Justification
+ if ( SW_CTL == nActual && nSpaceAdd )
+ {
LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CTL );
if ( LANGUAGE_THAI == aLang )
@@ -1532,21 +1546,6 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
nSpaceAdd = 0;
}
}
-
- // Kashida Justification
- if ( SW_CTL == nActual && nSpaceAdd )
- {
- if ( SwScriptInfo::IsArabicLanguage( rInf.GetFont()->
- GetLanguage( SW_CTL ) ) )
- {
- if ( pSI && pSI->CountKashida() )
- pSI->KashidaJustify( pKernArray, 0, rInf.GetIdx(),
- rInf.GetLen(), nSpaceAdd );
-
- bSpecialJust = sal_True;
- nSpaceAdd = 0;
- }
- }
}
long nKernSum = rInf.GetKern();
@@ -1698,6 +1697,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
// Modify Printer and ScreenArrays for special justifications
//
long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR;
+ bool bNoHalfSpace = false;
if ( rInf.GetFont() && rInf.GetLen() )
{
@@ -1737,6 +1737,20 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
}
}
+ // Kashida Justification
+ if ( SW_CTL == nActual && nSpaceAdd )
+ {
+ if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) )
+ {
+ if ( pSI && pSI->CountKashida() &&
+ pSI->KashidaJustify( pKernArray, pScrArray, rInf.GetIdx(),
+ rInf.GetLen(), nSpaceAdd ) != STRING_LEN )
+ nSpaceAdd = 0;
+ else
+ bNoHalfSpace = true;
+ }
+ }
+
// Thai Justification
if ( SW_CTL == nActual && nSpaceAdd )
{
@@ -1754,19 +1768,6 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
nSpaceAdd = 0;
}
}
-
- // Kashida Justification
- if ( SW_CTL == nActual && nSpaceAdd )
- {
- if ( SwScriptInfo::IsArabicLanguage( rInf.GetFont()->
- GetLanguage( SW_CTL ) ) )
- {
- if ( pSI && pSI->CountKashida() )
- pSI->KashidaJustify( pKernArray, pScrArray, rInf.GetIdx(),
- rInf.GetLen(), nSpaceAdd );
- nSpaceAdd = 0;
- }
- }
}
nScrPos = pScrArray[ 0 ];
@@ -1843,8 +1844,9 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
// 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 nOtherHalf = nSpaceAdd - nHalfSpace;
+ // in word line mode and for Arabic, we disable the half space trick:
+ const long nHalfSpace = pPrtFont->IsWordLineMode() || bNoHalfSpace ? 0 : nSpaceAdd / 2;
+ const long nOtherHalf = nSpaceAdd - nHalfSpace;
if ( nSpaceAdd && ( cChPrev == CH_BLANK ) )
nSpaceSum = nHalfSpace;
for ( xub_StrLen i=1; i<nCnt; ++i,nKernSum += rInf.GetKern() )
@@ -1903,6 +1905,12 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
}
cChPrev = nCh;
pKernArray[i-1] = nScrPos - nScr + nKernSum + nSpaceSum;
+ // In word line mode and for Arabic, we disabled the half space trick. If a portion
+ // ends with a blank, the full nSpaceAdd value has been added to the character in
+ // front of the blank. This leads to painting artifacts, therefore we remove the
+ // nSpaceAdd value again:
+ if ( (bNoHalfSpace || pPrtFont->IsWordLineMode()) && i+1 == nCnt && nCh == CH_BLANK )
+ pKernArray[i-1] = pKernArray[i-1] - nSpaceAdd;
}
// the layout engine requires the total width of the output
@@ -2292,6 +2300,7 @@ xub_StrLen SwFntObj::GetCrsrOfst( SwDrawTextInfo &rInf )
sal_Int32 *pKernArray = new sal_Int32[ rInf.GetLen() ];
+ // be sure to have the correct layout mode at the printer
if ( pPrinter )
{
pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() );
@@ -2337,6 +2346,18 @@ xub_StrLen SwFntObj::GetCrsrOfst( SwDrawTextInfo &rInf )
}
+ // Kashida Justification
+ if ( SW_CTL == nActual && rInf.GetSpace() )
+ {
+ if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) )
+ {
+ if ( pSI && pSI->CountKashida() &&
+ pSI->KashidaJustify( pKernArray, 0, rInf.GetIdx(), rInf.GetLen(),
+ nSpaceAdd ) != STRING_LEN )
+ nSpaceAdd = 0;
+ }
+ }
+
// Thai Justification
if ( SW_CTL == nActual && nSpaceAdd )
{
@@ -2353,20 +2374,6 @@ xub_StrLen SwFntObj::GetCrsrOfst( SwDrawTextInfo &rInf )
nSpaceAdd = 0;
}
}
-
- // Kashida Justification
- if ( SW_CTL == nActual && rInf.GetSpace() )
- {
- if ( SwScriptInfo::IsArabicLanguage( rInf.GetFont()->
- GetLanguage( SW_CTL ) ) )
- {
- if ( pSI && pSI->CountKashida() )
- pSI->KashidaJustify( pKernArray, 0, rInf.GetIdx(), rInf.GetLen(),
- nSpaceAdd );
-
- nSpaceAdd = 0;
- }
- }
}
long nLeft = 0;
diff --git a/sw/source/core/txtnode/swfont.cxx b/sw/source/core/txtnode/swfont.cxx
index 8efc0795a6b9..fc73941ad58f 100644
--- a/sw/source/core/txtnode/swfont.cxx
+++ b/sw/source/core/txtnode/swfont.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: swfont.cxx,v $
- * $Revision: 1.59 $
+ * $Revision: 1.59.24.1 $
*
* This file is part of OpenOffice.org.
*
@@ -734,6 +734,8 @@ Size SwSubFont::_GetTxtSize( SwDrawTextInfo& rInf )
!IsSameInstance( rInf.GetpOut()->GetFont() ) )
ChgFnt( rInf.GetShell(), rInf.GetOut() );
+ SwDigitModeModifier aDigitModeModifier( rInf.GetOut(), rInf.GetFont()->GetLanguage() );
+
Size aTxtSize;
xub_StrLen nLn = ( rInf.GetLen() == STRING_LEN ? rInf.GetText().Len()
: rInf.GetLen() );
@@ -849,6 +851,8 @@ void SwSubFont::_DrawText( SwDrawTextInfo &rInf, const BOOL bGrey )
if( !pLastFont || pLastFont->GetOwner()!=pMagic )
ChgFnt( rInf.GetShell(), rInf.GetOut() );
+ SwDigitModeModifier aDigitModeModifier( rInf.GetOut(), rInf.GetFont()->GetLanguage() );
+
Point aPos( rInf.GetPos() );
const Point &rOld = rInf.GetPos();
rInf.SetPos( aPos );
@@ -976,6 +980,8 @@ void SwSubFont::_DrawStretchText( SwDrawTextInfo &rInf )
if ( !pLastFont || pLastFont->GetOwner() != pMagic )
ChgFnt( rInf.GetShell(), rInf.GetOut() );
+ SwDigitModeModifier aDigitModeModifier( rInf.GetOut(), rInf.GetFont()->GetLanguage() );
+
rInf.ApplyAutoColor();
Point aPos( rInf.GetPos() );
@@ -1046,6 +1052,8 @@ xub_StrLen SwSubFont::_GetCrsrOfst( SwDrawTextInfo& rInf )
if ( !pLastFont || pLastFont->GetOwner()!=pMagic )
ChgFnt( rInf.GetShell(), rInf.GetOut() );
+ SwDigitModeModifier aDigitModeModifier( rInf.GetOut(), rInf.GetFont()->GetLanguage() );
+
xub_StrLen nLn = rInf.GetLen() == STRING_LEN ? rInf.GetText().Len()
: rInf.GetLen();
rInf.SetLen( nLn );
diff --git a/sw/source/core/txtnode/thints.cxx b/sw/source/core/txtnode/thints.cxx
index 03232f4fa655..e52bf2ba8ff0 100644
--- a/sw/source/core/txtnode/thints.cxx
+++ b/sw/source/core/txtnode/thints.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: thints.cxx,v $
- * $Revision: 1.65 $
+ * $Revision: 1.65.62.1 $
*
* This file is part of OpenOffice.org.
*
@@ -2331,21 +2331,23 @@ void SwTxtNode::ClearSwpHintsArr( bool bDelFields )
USHORT SwTxtNode::GetLang( const xub_StrLen nBegin, const xub_StrLen nLen,
USHORT nScript ) const
{
- USHORT nWhichId = RES_CHRATR_LANGUAGE;
USHORT nRet = LANGUAGE_DONTKNOW;
- if( pSwpHints )
- {
+
if ( ! nScript )
nScript = pBreakIt->GetRealScriptOfText( aText, nBegin );
- nWhichId = GetWhichOfScript( nWhichId, nScript );
+ // --> FME 2008-09-29 #i91465# hennerdrewes: Consider nScript if pSwpHints == 0
+ const USHORT nWhichId = GetWhichOfScript( RES_CHRATR_LANGUAGE, nScript );
+ // <--
- xub_StrLen nEnd = nBegin + nLen;
+ if( pSwpHints )
+ {
+ const xub_StrLen nEnd = nBegin + nLen;
for( USHORT i = 0, nSize = pSwpHints->Count(); i < nSize; ++i )
{
// ist der Attribut-Anfang schon groesser als der Idx ?
const SwTxtAttr *pHt = pSwpHints->operator[](i);
- xub_StrLen nAttrStart = *pHt->GetStart();
+ const xub_StrLen nAttrStart = *pHt->GetStart();
if( nEnd < nAttrStart )
break;
@@ -2379,10 +2381,6 @@ USHORT SwTxtNode::GetLang( const xub_StrLen nBegin, const xub_StrLen nLen,
}
if( LANGUAGE_DONTKNOW == nRet )
{
- if( !pSwpHints )
- nWhichId = GetWhichOfScript( RES_CHRATR_LANGUAGE,
- pBreakIt->GetRealScriptOfText( aText, nBegin ));
-
nRet = ((SvxLanguageItem&)GetSwAttrSet().Get( nWhichId )).GetLanguage();
if( LANGUAGE_DONTKNOW == nRet )
nRet = static_cast<USHORT>(GetAppLanguage());
diff --git a/sw/source/core/view/viewsh.cxx b/sw/source/core/view/viewsh.cxx
index 1214e7c9cda3..4b27fad5b60d 100644
--- a/sw/source/core/view/viewsh.cxx
+++ b/sw/source/core/view/viewsh.cxx
@@ -7,7 +7,7 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: viewsh.cxx,v $
- * $Revision: 1.87 $
+ * $Revision: 1.87.42.1 $
*
* This file is part of OpenOffice.org.
*
@@ -1007,6 +1007,14 @@ void ViewShell::Reformat()
}
}
+ void ViewShell::ChgNumberDigits()
+ {
+ SdrModel* pTmpDrawModel = getIDocumentDrawModelAccess()->GetDrawModel();
+ if ( pTmpDrawModel )
+ pTmpDrawModel->ReformatAllTextObjects();
+ Reformat();
+ }
+
/******************************************************************************
|*
|* ViewShell::CalcLayout()