1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski *
3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file
5*b1cdbd2cSJim Jagielski * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file
7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski *
11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski *
13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the
17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski * under the License.
19*b1cdbd2cSJim Jagielski *
20*b1cdbd2cSJim Jagielski *************************************************************/
21*b1cdbd2cSJim Jagielski
22*b1cdbd2cSJim Jagielski
23*b1cdbd2cSJim Jagielski
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_sw.hxx"
26*b1cdbd2cSJim Jagielski
27*b1cdbd2cSJim Jagielski
28*b1cdbd2cSJim Jagielski #include "errhdl.hxx" // ASSERT
29*b1cdbd2cSJim Jagielski
30*b1cdbd2cSJim Jagielski #include "txtcfg.hxx"
31*b1cdbd2cSJim Jagielski #include "porlay.hxx"
32*b1cdbd2cSJim Jagielski #include "itrform2.hxx"
33*b1cdbd2cSJim Jagielski #include "porglue.hxx"
34*b1cdbd2cSJim Jagielski #include "porexp.hxx" // SwQuoVadisPortion
35*b1cdbd2cSJim Jagielski #include "blink.hxx" // pBlink
36*b1cdbd2cSJim Jagielski #include "redlnitr.hxx" // SwRedlineItr
37*b1cdbd2cSJim Jagielski #include "porfly.hxx" // SwFlyCntPortion
38*b1cdbd2cSJim Jagielski #include <porrst.hxx> // SwHangingPortion
39*b1cdbd2cSJim Jagielski #include <pormulti.hxx> // SwMultiPortion
40*b1cdbd2cSJim Jagielski #include <breakit.hxx>
41*b1cdbd2cSJim Jagielski #include <unicode/uchar.h>
42*b1cdbd2cSJim Jagielski #include <com/sun/star/i18n/ScriptType.hdl>
43*b1cdbd2cSJim Jagielski #include <com/sun/star/i18n/CTLScriptType.hdl>
44*b1cdbd2cSJim Jagielski #include <com/sun/star/i18n/WordType.hdl>
45*b1cdbd2cSJim Jagielski #include <paratr.hxx>
46*b1cdbd2cSJim Jagielski #include <editeng/adjitem.hxx>
47*b1cdbd2cSJim Jagielski #include <editeng/scripttypeitem.hxx>
48*b1cdbd2cSJim Jagielski #include <editeng/charhiddenitem.hxx>
49*b1cdbd2cSJim Jagielski #include <vcl/outdev.hxx>
50*b1cdbd2cSJim Jagielski #include <editeng/blnkitem.hxx>
51*b1cdbd2cSJim Jagielski #include <tools/multisel.hxx>
52*b1cdbd2cSJim Jagielski #include <unotools/charclass.hxx>
53*b1cdbd2cSJim Jagielski #include <i18npool/mslangid.hxx>
54*b1cdbd2cSJim Jagielski #include <charfmt.hxx>
55*b1cdbd2cSJim Jagielski #include <fchrfmt.hxx>
56*b1cdbd2cSJim Jagielski #include <docary.hxx> // SwRedlineTbl
57*b1cdbd2cSJim Jagielski #include <redline.hxx> // SwRedline
58*b1cdbd2cSJim Jagielski #include <section.hxx>
59*b1cdbd2cSJim Jagielski #include <switerator.hxx>
60*b1cdbd2cSJim Jagielski #include <IDocumentRedlineAccess.hxx>
61*b1cdbd2cSJim Jagielski #include <IDocumentSettingAccess.hxx>
62*b1cdbd2cSJim Jagielski #include <IDocumentContentOperations.hxx>
63*b1cdbd2cSJim Jagielski
64*b1cdbd2cSJim Jagielski using namespace ::com::sun::star;
65*b1cdbd2cSJim Jagielski using namespace i18n::ScriptType;
66*b1cdbd2cSJim Jagielski
67*b1cdbd2cSJim Jagielski //#ifdef BIDI
68*b1cdbd2cSJim Jagielski #include <unicode/ubidi.h>
69*b1cdbd2cSJim Jagielski #include <i18nutil/unicode.hxx> //unicode::getUnicodeScriptType
70*b1cdbd2cSJim Jagielski
isAlefChar(xub_Unicode cCh)71*b1cdbd2cSJim Jagielski sal_Bool isAlefChar ( xub_Unicode cCh )
72*b1cdbd2cSJim Jagielski {
73*b1cdbd2cSJim Jagielski return ( cCh == 0x622 || cCh == 0x623 || cCh == 0x625 || cCh == 0x627 ||
74*b1cdbd2cSJim Jagielski cCh == 0x622 || cCh == 0x671 || cCh == 0x672 || cCh == 0x673 || cCh == 0x675 );
75*b1cdbd2cSJim Jagielski }
76*b1cdbd2cSJim Jagielski
isWawChar(xub_Unicode cCh)77*b1cdbd2cSJim Jagielski sal_Bool isWawChar ( xub_Unicode cCh )
78*b1cdbd2cSJim Jagielski {
79*b1cdbd2cSJim Jagielski return ( cCh == 0x624 || cCh == 0x648 || cCh == 0x676 || cCh == 0x677 ||
80*b1cdbd2cSJim Jagielski ( cCh >= 0x6C4 && cCh <= 0x6CB ) || cCh == 0x6CF );
81*b1cdbd2cSJim Jagielski }
82*b1cdbd2cSJim Jagielski
isDalChar(xub_Unicode cCh)83*b1cdbd2cSJim Jagielski sal_Bool isDalChar ( xub_Unicode cCh )
84*b1cdbd2cSJim Jagielski {
85*b1cdbd2cSJim Jagielski return ( cCh == 0x62F || cCh == 0x630 || cCh == 0x688 || cCh == 0x689 || cCh == 0x690 );
86*b1cdbd2cSJim Jagielski }
87*b1cdbd2cSJim Jagielski
isRehChar(xub_Unicode cCh)88*b1cdbd2cSJim Jagielski sal_Bool isRehChar ( xub_Unicode cCh )
89*b1cdbd2cSJim Jagielski {
90*b1cdbd2cSJim Jagielski return ( cCh == 0x631 || cCh == 0x632 || ( cCh >= 0x691 && cCh <= 0x699 ));
91*b1cdbd2cSJim Jagielski }
92*b1cdbd2cSJim Jagielski
isTehMarbutaChar(xub_Unicode cCh)93*b1cdbd2cSJim Jagielski sal_Bool isTehMarbutaChar ( xub_Unicode cCh )
94*b1cdbd2cSJim Jagielski {
95*b1cdbd2cSJim Jagielski return ( cCh == 0x629 || cCh == 0x6C0 );
96*b1cdbd2cSJim Jagielski }
97*b1cdbd2cSJim Jagielski
isBaaChar(xub_Unicode cCh)98*b1cdbd2cSJim Jagielski sal_Bool isBaaChar ( xub_Unicode cCh )
99*b1cdbd2cSJim Jagielski {
100*b1cdbd2cSJim Jagielski return ( cCh == 0x628 || cCh == 0x62A || cCh == 0x62B || cCh == 0x679 || cCh == 0x680 );
101*b1cdbd2cSJim Jagielski }
102*b1cdbd2cSJim Jagielski
isYehChar(xub_Unicode cCh)103*b1cdbd2cSJim Jagielski sal_Bool isYehChar ( xub_Unicode cCh )
104*b1cdbd2cSJim Jagielski {
105*b1cdbd2cSJim Jagielski return ( cCh == 0x626 || cCh == 0x649 || cCh == 0x64A || cCh == 0x678 || cCh == 0x6CC ||
106*b1cdbd2cSJim Jagielski cCh == 0x6CE || cCh == 0x6D0 || cCh == 0x6D1 );
107*b1cdbd2cSJim Jagielski }
108*b1cdbd2cSJim Jagielski
isSeenOrSadChar(xub_Unicode cCh)109*b1cdbd2cSJim Jagielski sal_Bool isSeenOrSadChar ( xub_Unicode cCh )
110*b1cdbd2cSJim Jagielski {
111*b1cdbd2cSJim Jagielski return ( ( cCh >= 0x633 && cCh <= 0x636 ) || ( cCh >= 0x69A && cCh <= 0x69E )
112*b1cdbd2cSJim Jagielski || cCh == 0x6FA || cCh == 0x6FB );
113*b1cdbd2cSJim Jagielski }
114*b1cdbd2cSJim Jagielski
isHahChar(xub_Unicode cCh)115*b1cdbd2cSJim Jagielski sal_Bool isHahChar ( xub_Unicode cCh )
116*b1cdbd2cSJim Jagielski {
117*b1cdbd2cSJim Jagielski return ( ( cCh >= 0x62C && cCh <= 0x62E ) || ( cCh >= 0x681 && cCh <= 0x687 )
118*b1cdbd2cSJim Jagielski || cCh == 0x6BF );
119*b1cdbd2cSJim Jagielski }
120*b1cdbd2cSJim Jagielski
isAinChar(xub_Unicode cCh)121*b1cdbd2cSJim Jagielski sal_Bool isAinChar ( xub_Unicode cCh )
122*b1cdbd2cSJim Jagielski {
123*b1cdbd2cSJim Jagielski return ( cCh == 0x639 || cCh == 0x63A || cCh == 0x6A0 || cCh == 0x6FC );
124*b1cdbd2cSJim Jagielski }
125*b1cdbd2cSJim Jagielski
isKafChar(xub_Unicode cCh)126*b1cdbd2cSJim Jagielski sal_Bool isKafChar ( xub_Unicode cCh )
127*b1cdbd2cSJim Jagielski {
128*b1cdbd2cSJim Jagielski return ( cCh == 0x643 || ( cCh >= 0x6AC && cCh <= 0x6AE ) );
129*b1cdbd2cSJim Jagielski }
130*b1cdbd2cSJim Jagielski
isLamChar(xub_Unicode cCh)131*b1cdbd2cSJim Jagielski sal_Bool isLamChar ( xub_Unicode cCh )
132*b1cdbd2cSJim Jagielski {
133*b1cdbd2cSJim Jagielski return ( cCh == 0x644 || ( cCh >= 0x6B5 && cCh <= 0x6B8 ) );
134*b1cdbd2cSJim Jagielski }
135*b1cdbd2cSJim Jagielski
isGafChar(xub_Unicode cCh)136*b1cdbd2cSJim Jagielski sal_Bool isGafChar ( xub_Unicode cCh )
137*b1cdbd2cSJim Jagielski {
138*b1cdbd2cSJim Jagielski return ( cCh == 0x6A9 || cCh == 0x6AB ||( cCh >= 0x6AF && cCh <= 0x6B4 ) );
139*b1cdbd2cSJim Jagielski }
140*b1cdbd2cSJim Jagielski
isQafChar(xub_Unicode cCh)141*b1cdbd2cSJim Jagielski sal_Bool isQafChar ( xub_Unicode cCh )
142*b1cdbd2cSJim Jagielski {
143*b1cdbd2cSJim Jagielski return ( cCh == 0x642 || cCh == 0x6A7 || cCh == 0x6A8 );
144*b1cdbd2cSJim Jagielski }
145*b1cdbd2cSJim Jagielski
isFeChar(xub_Unicode cCh)146*b1cdbd2cSJim Jagielski sal_Bool isFeChar ( xub_Unicode cCh )
147*b1cdbd2cSJim Jagielski {
148*b1cdbd2cSJim Jagielski return ( cCh == 0x641 || ( cCh >= 0x6A1 && cCh <= 0x6A6 ) );
149*b1cdbd2cSJim Jagielski }
isTransparentChar(xub_Unicode cCh)150*b1cdbd2cSJim Jagielski sal_Bool isTransparentChar ( xub_Unicode cCh )
151*b1cdbd2cSJim Jagielski {
152*b1cdbd2cSJim Jagielski return ( ( cCh >= 0x610 && cCh <= 0x61A ) ||
153*b1cdbd2cSJim Jagielski ( cCh >= 0x64B && cCh <= 0x65E ) ||
154*b1cdbd2cSJim Jagielski ( cCh == 0x670 ) ||
155*b1cdbd2cSJim Jagielski ( cCh >= 0x6D6 && cCh <= 0x6DC ) ||
156*b1cdbd2cSJim Jagielski ( cCh >= 0x6DF && cCh <= 0x6E4 ) ||
157*b1cdbd2cSJim Jagielski ( cCh >= 0x6E7 && cCh <= 0x6E8 ) ||
158*b1cdbd2cSJim Jagielski ( cCh >= 0x6EA && cCh <= 0x6ED ));
159*b1cdbd2cSJim Jagielski }
160*b1cdbd2cSJim Jagielski
161*b1cdbd2cSJim Jagielski /*************************************************************************
162*b1cdbd2cSJim Jagielski * lcl_IsLigature
163*b1cdbd2cSJim Jagielski *
164*b1cdbd2cSJim Jagielski * Checks if cCh + cNectCh builds a ligature (used for Kashidas)
165*b1cdbd2cSJim Jagielski *************************************************************************/
166*b1cdbd2cSJim Jagielski
lcl_IsLigature(xub_Unicode cCh,xub_Unicode cNextCh)167*b1cdbd2cSJim Jagielski sal_Bool lcl_IsLigature( xub_Unicode cCh, xub_Unicode cNextCh )
168*b1cdbd2cSJim Jagielski {
169*b1cdbd2cSJim Jagielski // Lam + Alef
170*b1cdbd2cSJim Jagielski return ( isLamChar ( cCh ) && isAlefChar ( cNextCh ));
171*b1cdbd2cSJim Jagielski }
172*b1cdbd2cSJim Jagielski
173*b1cdbd2cSJim Jagielski /*************************************************************************
174*b1cdbd2cSJim Jagielski * lcl_ConnectToPrev
175*b1cdbd2cSJim Jagielski *
176*b1cdbd2cSJim Jagielski * Checks if cCh is connectable to cPrevCh (used for Kashidas)
177*b1cdbd2cSJim Jagielski *************************************************************************/
178*b1cdbd2cSJim Jagielski
lcl_ConnectToPrev(xub_Unicode cCh,xub_Unicode cPrevCh)179*b1cdbd2cSJim Jagielski sal_Bool lcl_ConnectToPrev( xub_Unicode cCh, xub_Unicode cPrevCh )
180*b1cdbd2cSJim Jagielski {
181*b1cdbd2cSJim Jagielski // Alef, Dal, Thal, Reh, Zain, and Waw do not connect to the left
182*b1cdbd2cSJim Jagielski // Uh, there seem to be some more characters that are not connectable
183*b1cdbd2cSJim Jagielski // to the left. So we look for the characters that are actually connectable
184*b1cdbd2cSJim Jagielski // to the left. Here is the complete list of WH:
185*b1cdbd2cSJim Jagielski
186*b1cdbd2cSJim Jagielski // (hennerdrewes):
187*b1cdbd2cSJim Jagielski // added lam forms 0x06B5..0x06B8
188*b1cdbd2cSJim Jagielski // added 0x6FA..0x6FC, according to unicode documentation, although not present in my fonts
189*b1cdbd2cSJim Jagielski // added heh goal 0x6C1
190*b1cdbd2cSJim Jagielski sal_Bool bRet = 0x628 == cPrevCh ||
191*b1cdbd2cSJim Jagielski ( 0x62A <= cPrevCh && cPrevCh <= 0x62E ) ||
192*b1cdbd2cSJim Jagielski ( 0x633 <= cPrevCh && cPrevCh <= 0x647 ) ||
193*b1cdbd2cSJim Jagielski 0x649 == cPrevCh || // Alef Maksura does connect !!!
194*b1cdbd2cSJim Jagielski 0x64A == cPrevCh ||
195*b1cdbd2cSJim Jagielski ( 0x678 <= cPrevCh && cPrevCh <= 0x687 ) ||
196*b1cdbd2cSJim Jagielski ( 0x69A <= cPrevCh && cPrevCh <= 0x6C1 ) ||
197*b1cdbd2cSJim Jagielski ( 0x6C3 <= cPrevCh && cPrevCh <= 0x6D3 ) ||
198*b1cdbd2cSJim Jagielski ( 0x6FA <= cPrevCh && cPrevCh <= 0x6FC ) ;
199*b1cdbd2cSJim Jagielski
200*b1cdbd2cSJim Jagielski // check for ligatures cPrevChar + cChar
201*b1cdbd2cSJim Jagielski if( bRet )
202*b1cdbd2cSJim Jagielski bRet = !lcl_IsLigature( cPrevCh, cCh );
203*b1cdbd2cSJim Jagielski return bRet;
204*b1cdbd2cSJim Jagielski }
205*b1cdbd2cSJim Jagielski
206*b1cdbd2cSJim Jagielski /*************************************************************************
207*b1cdbd2cSJim Jagielski * lcl_HasStrongLTR
208*b1cdbd2cSJim Jagielski *************************************************************************/
lcl_HasStrongLTR(const String & rTxt,xub_StrLen nStart,xub_StrLen nEnd)209*b1cdbd2cSJim Jagielski bool lcl_HasStrongLTR ( const String& rTxt, xub_StrLen nStart, xub_StrLen nEnd )
210*b1cdbd2cSJim Jagielski {
211*b1cdbd2cSJim Jagielski for ( xub_StrLen nCharIdx = nStart; nCharIdx < nEnd; ++nCharIdx )
212*b1cdbd2cSJim Jagielski {
213*b1cdbd2cSJim Jagielski const UCharDirection nCharDir = u_charDirection ( rTxt.GetChar ( nCharIdx ));
214*b1cdbd2cSJim Jagielski if ( nCharDir == U_LEFT_TO_RIGHT ||
215*b1cdbd2cSJim Jagielski nCharDir == U_LEFT_TO_RIGHT_EMBEDDING ||
216*b1cdbd2cSJim Jagielski nCharDir == U_LEFT_TO_RIGHT_OVERRIDE )
217*b1cdbd2cSJim Jagielski return true;
218*b1cdbd2cSJim Jagielski }
219*b1cdbd2cSJim Jagielski return false;
220*b1cdbd2cSJim Jagielski }
221*b1cdbd2cSJim Jagielski
222*b1cdbd2cSJim Jagielski /*************************************************************************
223*b1cdbd2cSJim Jagielski * SwLineLayout::~SwLineLayout()
224*b1cdbd2cSJim Jagielski *
225*b1cdbd2cSJim Jagielski * class SwLineLayout: Das Layout einer einzelnen Zeile. Dazu
226*b1cdbd2cSJim Jagielski * gehoeren vor allen Dingen die Dimension, die Anzahl der
227*b1cdbd2cSJim Jagielski * Character und der Wortzwischenraeume in der Zeile.
228*b1cdbd2cSJim Jagielski * Zeilenobjekte werden in einem eigenen Pool verwaltet, um zu
229*b1cdbd2cSJim Jagielski * erreichen, dass sie im Speicher moeglichst beeinander liegen
230*b1cdbd2cSJim Jagielski * (d.h. zusammen gepaged werden und den Speicher nicht
231*b1cdbd2cSJim Jagielski * fragmentieren).
232*b1cdbd2cSJim Jagielski *************************************************************************/
233*b1cdbd2cSJim Jagielski
~SwLineLayout()234*b1cdbd2cSJim Jagielski SwLineLayout::~SwLineLayout()
235*b1cdbd2cSJim Jagielski {
236*b1cdbd2cSJim Jagielski Truncate();
237*b1cdbd2cSJim Jagielski if( GetNext() )
238*b1cdbd2cSJim Jagielski delete GetNext();
239*b1cdbd2cSJim Jagielski if( pBlink )
240*b1cdbd2cSJim Jagielski pBlink->Delete( this );
241*b1cdbd2cSJim Jagielski delete pLLSpaceAdd;
242*b1cdbd2cSJim Jagielski if ( pKanaComp )
243*b1cdbd2cSJim Jagielski delete pKanaComp;
244*b1cdbd2cSJim Jagielski }
245*b1cdbd2cSJim Jagielski
246*b1cdbd2cSJim Jagielski /*************************************************************************
247*b1cdbd2cSJim Jagielski * virtual SwLineLayout::Insert()
248*b1cdbd2cSJim Jagielski *************************************************************************/
249*b1cdbd2cSJim Jagielski
Insert(SwLinePortion * pIns)250*b1cdbd2cSJim Jagielski SwLinePortion *SwLineLayout::Insert( SwLinePortion *pIns )
251*b1cdbd2cSJim Jagielski {
252*b1cdbd2cSJim Jagielski // Erster Attributwechsel, Masse und Laengen
253*b1cdbd2cSJim Jagielski // aus *pCurr in die erste Textportion kopieren.
254*b1cdbd2cSJim Jagielski if( !pPortion )
255*b1cdbd2cSJim Jagielski {
256*b1cdbd2cSJim Jagielski if( GetLen() )
257*b1cdbd2cSJim Jagielski {
258*b1cdbd2cSJim Jagielski pPortion = new SwTxtPortion( *(SwLinePortion*)this );
259*b1cdbd2cSJim Jagielski if( IsBlinking() && pBlink )
260*b1cdbd2cSJim Jagielski {
261*b1cdbd2cSJim Jagielski SetBlinking( sal_False );
262*b1cdbd2cSJim Jagielski pBlink->Replace( this, pPortion );
263*b1cdbd2cSJim Jagielski }
264*b1cdbd2cSJim Jagielski }
265*b1cdbd2cSJim Jagielski else
266*b1cdbd2cSJim Jagielski {
267*b1cdbd2cSJim Jagielski SetPortion( pIns );
268*b1cdbd2cSJim Jagielski return pIns;
269*b1cdbd2cSJim Jagielski }
270*b1cdbd2cSJim Jagielski }
271*b1cdbd2cSJim Jagielski // mit Skope aufrufen, sonst Rekursion !
272*b1cdbd2cSJim Jagielski return pPortion->SwLinePortion::Insert( pIns );
273*b1cdbd2cSJim Jagielski }
274*b1cdbd2cSJim Jagielski
275*b1cdbd2cSJim Jagielski /*************************************************************************
276*b1cdbd2cSJim Jagielski * virtual SwLineLayout::Append()
277*b1cdbd2cSJim Jagielski *************************************************************************/
278*b1cdbd2cSJim Jagielski
Append(SwLinePortion * pIns)279*b1cdbd2cSJim Jagielski SwLinePortion *SwLineLayout::Append( SwLinePortion *pIns )
280*b1cdbd2cSJim Jagielski {
281*b1cdbd2cSJim Jagielski // Erster Attributwechsel, Masse und Laengen
282*b1cdbd2cSJim Jagielski // aus *pCurr in die erste Textportion kopieren.
283*b1cdbd2cSJim Jagielski if( !pPortion )
284*b1cdbd2cSJim Jagielski pPortion = new SwTxtPortion( *(SwLinePortion*)this );
285*b1cdbd2cSJim Jagielski // mit Skope aufrufen, sonst Rekursion !
286*b1cdbd2cSJim Jagielski return pPortion->SwLinePortion::Append( pIns );
287*b1cdbd2cSJim Jagielski }
288*b1cdbd2cSJim Jagielski
289*b1cdbd2cSJim Jagielski /*************************************************************************
290*b1cdbd2cSJim Jagielski * virtual SwLineLayout::Format()
291*b1cdbd2cSJim Jagielski *************************************************************************/
292*b1cdbd2cSJim Jagielski
293*b1cdbd2cSJim Jagielski // fuer die Sonderbehandlung bei leeren Zeilen
294*b1cdbd2cSJim Jagielski
Format(SwTxtFormatInfo & rInf)295*b1cdbd2cSJim Jagielski sal_Bool SwLineLayout::Format( SwTxtFormatInfo &rInf )
296*b1cdbd2cSJim Jagielski {
297*b1cdbd2cSJim Jagielski if( GetLen() )
298*b1cdbd2cSJim Jagielski return SwTxtPortion::Format( rInf );
299*b1cdbd2cSJim Jagielski else
300*b1cdbd2cSJim Jagielski {
301*b1cdbd2cSJim Jagielski Height( rInf.GetTxtHeight() );
302*b1cdbd2cSJim Jagielski return sal_True;
303*b1cdbd2cSJim Jagielski }
304*b1cdbd2cSJim Jagielski }
305*b1cdbd2cSJim Jagielski
306*b1cdbd2cSJim Jagielski /*************************************************************************
307*b1cdbd2cSJim Jagielski * SwLineLayout::CalcLeftMargin()
308*b1cdbd2cSJim Jagielski *
309*b1cdbd2cSJim Jagielski * Wir sammeln alle FlyPortions am Anfang der Zeile zu einer MarginPortion.
310*b1cdbd2cSJim Jagielski *************************************************************************/
311*b1cdbd2cSJim Jagielski
CalcLeftMargin()312*b1cdbd2cSJim Jagielski SwMarginPortion *SwLineLayout::CalcLeftMargin()
313*b1cdbd2cSJim Jagielski {
314*b1cdbd2cSJim Jagielski SwMarginPortion *pLeft = (GetPortion() && GetPortion()->IsMarginPortion()) ?
315*b1cdbd2cSJim Jagielski (SwMarginPortion *)GetPortion() : 0;
316*b1cdbd2cSJim Jagielski if( !GetPortion() )
317*b1cdbd2cSJim Jagielski SetPortion( new SwTxtPortion( *(SwLinePortion*)this ) );
318*b1cdbd2cSJim Jagielski if( !pLeft )
319*b1cdbd2cSJim Jagielski {
320*b1cdbd2cSJim Jagielski pLeft = new SwMarginPortion( 0 );
321*b1cdbd2cSJim Jagielski pLeft->SetPortion( GetPortion() );
322*b1cdbd2cSJim Jagielski SetPortion( pLeft );
323*b1cdbd2cSJim Jagielski }
324*b1cdbd2cSJim Jagielski else
325*b1cdbd2cSJim Jagielski {
326*b1cdbd2cSJim Jagielski pLeft->Height( 0 );
327*b1cdbd2cSJim Jagielski pLeft->Width( 0 );
328*b1cdbd2cSJim Jagielski pLeft->SetLen( 0 );
329*b1cdbd2cSJim Jagielski pLeft->SetAscent( 0 );
330*b1cdbd2cSJim Jagielski pLeft->SetPortion( NULL );
331*b1cdbd2cSJim Jagielski pLeft->SetFixWidth(0);
332*b1cdbd2cSJim Jagielski }
333*b1cdbd2cSJim Jagielski
334*b1cdbd2cSJim Jagielski SwLinePortion *pPos = pLeft->GetPortion();
335*b1cdbd2cSJim Jagielski while( pPos )
336*b1cdbd2cSJim Jagielski {
337*b1cdbd2cSJim Jagielski DBG_LOOP;
338*b1cdbd2cSJim Jagielski if( pPos->IsFlyPortion() )
339*b1cdbd2cSJim Jagielski {
340*b1cdbd2cSJim Jagielski // Die FlyPortion wird ausgesogen ...
341*b1cdbd2cSJim Jagielski pLeft->Join( (SwGluePortion*)pPos );
342*b1cdbd2cSJim Jagielski pPos = pLeft->GetPortion();
343*b1cdbd2cSJim Jagielski if( GetpKanaComp() )
344*b1cdbd2cSJim Jagielski GetKanaComp().Remove( 0, 1 );
345*b1cdbd2cSJim Jagielski }
346*b1cdbd2cSJim Jagielski else
347*b1cdbd2cSJim Jagielski pPos = 0;
348*b1cdbd2cSJim Jagielski }
349*b1cdbd2cSJim Jagielski return pLeft;
350*b1cdbd2cSJim Jagielski }
351*b1cdbd2cSJim Jagielski
352*b1cdbd2cSJim Jagielski /*************************************************************************
353*b1cdbd2cSJim Jagielski * SwLineLayout::InitSpaceAdd()
354*b1cdbd2cSJim Jagielski *************************************************************************/
355*b1cdbd2cSJim Jagielski
InitSpaceAdd()356*b1cdbd2cSJim Jagielski void SwLineLayout::InitSpaceAdd()
357*b1cdbd2cSJim Jagielski {
358*b1cdbd2cSJim Jagielski if ( !pLLSpaceAdd )
359*b1cdbd2cSJim Jagielski CreateSpaceAdd();
360*b1cdbd2cSJim Jagielski else
361*b1cdbd2cSJim Jagielski SetLLSpaceAdd( 0, 0 );
362*b1cdbd2cSJim Jagielski }
363*b1cdbd2cSJim Jagielski
364*b1cdbd2cSJim Jagielski /*************************************************************************
365*b1cdbd2cSJim Jagielski * SwLineLayout::CreateSpaceAdd()
366*b1cdbd2cSJim Jagielski *************************************************************************/
367*b1cdbd2cSJim Jagielski
CreateSpaceAdd(const long nInit)368*b1cdbd2cSJim Jagielski void SwLineLayout::CreateSpaceAdd( const long nInit )
369*b1cdbd2cSJim Jagielski {
370*b1cdbd2cSJim Jagielski pLLSpaceAdd = new std::vector<long>;
371*b1cdbd2cSJim Jagielski SetLLSpaceAdd( nInit, 0 );
372*b1cdbd2cSJim Jagielski }
373*b1cdbd2cSJim Jagielski
374*b1cdbd2cSJim Jagielski /*************************************************************************
375*b1cdbd2cSJim Jagielski * Local helper function. Returns true if there are only blanks
376*b1cdbd2cSJim Jagielski * in [nStt, nEnd[
377*b1cdbd2cSJim Jagielski *************************************************************************/
378*b1cdbd2cSJim Jagielski
lcl_HasOnlyBlanks(const XubString & rTxt,xub_StrLen nStt,xub_StrLen nEnd)379*b1cdbd2cSJim Jagielski bool lcl_HasOnlyBlanks( const XubString& rTxt, xub_StrLen nStt, xub_StrLen nEnd )
380*b1cdbd2cSJim Jagielski {
381*b1cdbd2cSJim Jagielski bool bBlankOnly = true;
382*b1cdbd2cSJim Jagielski while ( nStt < nEnd )
383*b1cdbd2cSJim Jagielski {
384*b1cdbd2cSJim Jagielski const xub_Unicode cChar = rTxt.GetChar( nStt++ );
385*b1cdbd2cSJim Jagielski if ( ' ' != cChar && 0x3000 != cChar )
386*b1cdbd2cSJim Jagielski {
387*b1cdbd2cSJim Jagielski bBlankOnly = false;
388*b1cdbd2cSJim Jagielski break;
389*b1cdbd2cSJim Jagielski }
390*b1cdbd2cSJim Jagielski }
391*b1cdbd2cSJim Jagielski return bBlankOnly;
392*b1cdbd2cSJim Jagielski }
393*b1cdbd2cSJim Jagielski
394*b1cdbd2cSJim Jagielski /*************************************************************************
395*b1cdbd2cSJim Jagielski * SwLineLayout::CalcLine()
396*b1cdbd2cSJim Jagielski *
397*b1cdbd2cSJim Jagielski * Aus FormatLine() ausgelagert.
398*b1cdbd2cSJim Jagielski *************************************************************************/
399*b1cdbd2cSJim Jagielski
CalcLine(SwTxtFormatter & rLine,SwTxtFormatInfo & rInf)400*b1cdbd2cSJim Jagielski void SwLineLayout::CalcLine( SwTxtFormatter &rLine, SwTxtFormatInfo &rInf )
401*b1cdbd2cSJim Jagielski {
402*b1cdbd2cSJim Jagielski const KSHORT nLineWidth = rInf.RealWidth();
403*b1cdbd2cSJim Jagielski
404*b1cdbd2cSJim Jagielski KSHORT nFlyAscent = 0;
405*b1cdbd2cSJim Jagielski KSHORT nFlyHeight = 0;
406*b1cdbd2cSJim Jagielski KSHORT nFlyDescent = 0;
407*b1cdbd2cSJim Jagielski sal_Bool bOnlyPostIts = sal_True;
408*b1cdbd2cSJim Jagielski SetHanging( sal_False );
409*b1cdbd2cSJim Jagielski
410*b1cdbd2cSJim Jagielski sal_Bool bTmpDummy = ( 0 == GetLen() );
411*b1cdbd2cSJim Jagielski SwFlyCntPortion* pFlyCnt = 0;
412*b1cdbd2cSJim Jagielski if( bTmpDummy )
413*b1cdbd2cSJim Jagielski {
414*b1cdbd2cSJim Jagielski nFlyAscent = 0;
415*b1cdbd2cSJim Jagielski nFlyHeight = 0;
416*b1cdbd2cSJim Jagielski nFlyDescent = 0;
417*b1cdbd2cSJim Jagielski }
418*b1cdbd2cSJim Jagielski
419*b1cdbd2cSJim Jagielski // --> FME 2006-03-01 #i3952#
420*b1cdbd2cSJim Jagielski const bool bIgnoreBlanksAndTabsForLineHeightCalculation =
421*b1cdbd2cSJim Jagielski rInf.GetTxtFrm()->GetNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION);
422*b1cdbd2cSJim Jagielski
423*b1cdbd2cSJim Jagielski bool bHasBlankPortion = false;
424*b1cdbd2cSJim Jagielski bool bHasOnlyBlankPortions = true;
425*b1cdbd2cSJim Jagielski // <--
426*b1cdbd2cSJim Jagielski
427*b1cdbd2cSJim Jagielski if( pPortion )
428*b1cdbd2cSJim Jagielski {
429*b1cdbd2cSJim Jagielski SetCntnt( sal_False );
430*b1cdbd2cSJim Jagielski if( pPortion->IsBreakPortion() )
431*b1cdbd2cSJim Jagielski {
432*b1cdbd2cSJim Jagielski SetLen( pPortion->GetLen() );
433*b1cdbd2cSJim Jagielski if( GetLen() )
434*b1cdbd2cSJim Jagielski bTmpDummy = sal_False;
435*b1cdbd2cSJim Jagielski }
436*b1cdbd2cSJim Jagielski else
437*b1cdbd2cSJim Jagielski {
438*b1cdbd2cSJim Jagielski Init( GetPortion() );
439*b1cdbd2cSJim Jagielski SwLinePortion *pPos = pPortion;
440*b1cdbd2cSJim Jagielski SwLinePortion *pLast = this;
441*b1cdbd2cSJim Jagielski KSHORT nMaxDescent = 0;
442*b1cdbd2cSJim Jagielski
443*b1cdbd2cSJim Jagielski // Eine Gruppe ist ein Abschnitt in der Portion-Kette von
444*b1cdbd2cSJim Jagielski // pCurr oder einer Fix-Portion bis zum Ende bzw. zur naechsten
445*b1cdbd2cSJim Jagielski // Fix-Portion.
446*b1cdbd2cSJim Jagielski while( pPos )
447*b1cdbd2cSJim Jagielski {
448*b1cdbd2cSJim Jagielski DBG_LOOP;
449*b1cdbd2cSJim Jagielski ASSERT( POR_LIN != pPos->GetWhichPor(),
450*b1cdbd2cSJim Jagielski "SwLineLayout::CalcLine: don't use SwLinePortions !" );
451*b1cdbd2cSJim Jagielski
452*b1cdbd2cSJim Jagielski // Null-Portions werden eliminiert. Sie koennen entstehen,
453*b1cdbd2cSJim Jagielski // wenn zwei FlyFrms ueberlappen.
454*b1cdbd2cSJim Jagielski if( !pPos->Compress() )
455*b1cdbd2cSJim Jagielski {
456*b1cdbd2cSJim Jagielski // 8110: Hoehe und Ascent nur uebernehmen, wenn sonst in der
457*b1cdbd2cSJim Jagielski // Zeile nichts mehr los ist.
458*b1cdbd2cSJim Jagielski if( !pPos->GetPortion() )
459*b1cdbd2cSJim Jagielski {
460*b1cdbd2cSJim Jagielski if( !Height() )
461*b1cdbd2cSJim Jagielski Height( pPos->Height() );
462*b1cdbd2cSJim Jagielski if( !GetAscent() )
463*b1cdbd2cSJim Jagielski SetAscent( pPos->GetAscent() );
464*b1cdbd2cSJim Jagielski }
465*b1cdbd2cSJim Jagielski delete pLast->Cut( pPos );
466*b1cdbd2cSJim Jagielski pPos = pLast->GetPortion();
467*b1cdbd2cSJim Jagielski continue;
468*b1cdbd2cSJim Jagielski }
469*b1cdbd2cSJim Jagielski
470*b1cdbd2cSJim Jagielski const xub_StrLen nPorSttIdx = rInf.GetLineStart() + nLineLength;
471*b1cdbd2cSJim Jagielski nLineLength = nLineLength + pPos->GetLen();
472*b1cdbd2cSJim Jagielski AddPrtWidth( pPos->Width() );
473*b1cdbd2cSJim Jagielski
474*b1cdbd2cSJim Jagielski // --> FME 2006-03-01 #i3952#
475*b1cdbd2cSJim Jagielski if ( bIgnoreBlanksAndTabsForLineHeightCalculation )
476*b1cdbd2cSJim Jagielski {
477*b1cdbd2cSJim Jagielski if ( pPos->InTabGrp() || pPos->IsHolePortion() ||
478*b1cdbd2cSJim Jagielski ( pPos->IsTextPortion() &&
479*b1cdbd2cSJim Jagielski lcl_HasOnlyBlanks( rInf.GetTxt(), nPorSttIdx, nPorSttIdx + pPos->GetLen() ) ) )
480*b1cdbd2cSJim Jagielski {
481*b1cdbd2cSJim Jagielski pLast = pPos;
482*b1cdbd2cSJim Jagielski pPos = pPos->GetPortion();
483*b1cdbd2cSJim Jagielski bHasBlankPortion = true;
484*b1cdbd2cSJim Jagielski continue;
485*b1cdbd2cSJim Jagielski }
486*b1cdbd2cSJim Jagielski }
487*b1cdbd2cSJim Jagielski // <--
488*b1cdbd2cSJim Jagielski
489*b1cdbd2cSJim Jagielski bHasOnlyBlankPortions = false;
490*b1cdbd2cSJim Jagielski
491*b1cdbd2cSJim Jagielski // Es gab Attributwechsel: Laengen und Masse aufaddieren;
492*b1cdbd2cSJim Jagielski // bzw.Maxima bilden.
493*b1cdbd2cSJim Jagielski
494*b1cdbd2cSJim Jagielski KSHORT nPosHeight = pPos->Height();
495*b1cdbd2cSJim Jagielski KSHORT nPosAscent = pPos->GetAscent();
496*b1cdbd2cSJim Jagielski
497*b1cdbd2cSJim Jagielski ASSERT( nPosHeight >= nPosAscent,
498*b1cdbd2cSJim Jagielski "SwLineLayout::CalcLine: bad ascent or height" );
499*b1cdbd2cSJim Jagielski
500*b1cdbd2cSJim Jagielski if( pPos->IsHangingPortion() )
501*b1cdbd2cSJim Jagielski {
502*b1cdbd2cSJim Jagielski SetHanging( sal_True );
503*b1cdbd2cSJim Jagielski rInf.GetParaPortion()->SetMargin( sal_True );
504*b1cdbd2cSJim Jagielski }
505*b1cdbd2cSJim Jagielski
506*b1cdbd2cSJim Jagielski // Damit ein Paragraphende-Zeichen nicht durch ein Descent zu einer
507*b1cdbd2cSJim Jagielski // geaenderten Zeilenhoehe und zum Umformatieren fuehrt.
508*b1cdbd2cSJim Jagielski if ( !pPos->IsBreakPortion() || !Height() )
509*b1cdbd2cSJim Jagielski {
510*b1cdbd2cSJim Jagielski bOnlyPostIts &= pPos->IsPostItsPortion();
511*b1cdbd2cSJim Jagielski
512*b1cdbd2cSJim Jagielski if( bTmpDummy && !nLineLength )
513*b1cdbd2cSJim Jagielski {
514*b1cdbd2cSJim Jagielski if( pPos->IsFlyPortion() )
515*b1cdbd2cSJim Jagielski {
516*b1cdbd2cSJim Jagielski if( nFlyHeight < nPosHeight )
517*b1cdbd2cSJim Jagielski nFlyHeight = nPosHeight;
518*b1cdbd2cSJim Jagielski if( nFlyAscent < nPosAscent )
519*b1cdbd2cSJim Jagielski nFlyAscent = nPosAscent;
520*b1cdbd2cSJim Jagielski if( nFlyDescent < nPosHeight - nPosAscent )
521*b1cdbd2cSJim Jagielski nFlyDescent = nPosHeight - nPosAscent;
522*b1cdbd2cSJim Jagielski }
523*b1cdbd2cSJim Jagielski else
524*b1cdbd2cSJim Jagielski {
525*b1cdbd2cSJim Jagielski if( pPos->InNumberGrp() )
526*b1cdbd2cSJim Jagielski {
527*b1cdbd2cSJim Jagielski KSHORT nTmp = rInf.GetFont()->GetAscent(
528*b1cdbd2cSJim Jagielski rInf.GetVsh(), *rInf.GetOut() );
529*b1cdbd2cSJim Jagielski if( nTmp > nPosAscent )
530*b1cdbd2cSJim Jagielski {
531*b1cdbd2cSJim Jagielski nPosHeight += nTmp - nPosAscent;
532*b1cdbd2cSJim Jagielski nPosAscent = nTmp;
533*b1cdbd2cSJim Jagielski }
534*b1cdbd2cSJim Jagielski nTmp = rInf.GetFont()->GetHeight( rInf.GetVsh(),
535*b1cdbd2cSJim Jagielski *rInf.GetOut() );
536*b1cdbd2cSJim Jagielski if( nTmp > nPosHeight )
537*b1cdbd2cSJim Jagielski nPosHeight = nTmp;
538*b1cdbd2cSJim Jagielski }
539*b1cdbd2cSJim Jagielski Height( nPosHeight );
540*b1cdbd2cSJim Jagielski nAscent = nPosAscent;
541*b1cdbd2cSJim Jagielski nMaxDescent = nPosHeight - nPosAscent;
542*b1cdbd2cSJim Jagielski }
543*b1cdbd2cSJim Jagielski }
544*b1cdbd2cSJim Jagielski else if( !pPos->IsFlyPortion() )
545*b1cdbd2cSJim Jagielski {
546*b1cdbd2cSJim Jagielski if( Height() < nPosHeight )
547*b1cdbd2cSJim Jagielski Height( nPosHeight );
548*b1cdbd2cSJim Jagielski if( pPos->IsFlyCntPortion() || ( pPos->IsMultiPortion()
549*b1cdbd2cSJim Jagielski && ((SwMultiPortion*)pPos)->HasFlyInCntnt() ) )
550*b1cdbd2cSJim Jagielski rLine.SetFlyInCntBase();
551*b1cdbd2cSJim Jagielski if( pPos->IsFlyCntPortion() &&
552*b1cdbd2cSJim Jagielski ((SwFlyCntPortion*)pPos)->GetAlign() )
553*b1cdbd2cSJim Jagielski {
554*b1cdbd2cSJim Jagielski ((SwFlyCntPortion*)pPos)->SetMax( sal_False );
555*b1cdbd2cSJim Jagielski if( !pFlyCnt || pPos->Height() > pFlyCnt->Height() )
556*b1cdbd2cSJim Jagielski pFlyCnt = (SwFlyCntPortion*)pPos;
557*b1cdbd2cSJim Jagielski }
558*b1cdbd2cSJim Jagielski else
559*b1cdbd2cSJim Jagielski {
560*b1cdbd2cSJim Jagielski if( nAscent < nPosAscent )
561*b1cdbd2cSJim Jagielski nAscent = nPosAscent;
562*b1cdbd2cSJim Jagielski if( nMaxDescent < nPosHeight - nPosAscent )
563*b1cdbd2cSJim Jagielski nMaxDescent = nPosHeight - nPosAscent;
564*b1cdbd2cSJim Jagielski }
565*b1cdbd2cSJim Jagielski }
566*b1cdbd2cSJim Jagielski }
567*b1cdbd2cSJim Jagielski else if( pPos->GetLen() )
568*b1cdbd2cSJim Jagielski bTmpDummy = sal_False;
569*b1cdbd2cSJim Jagielski
570*b1cdbd2cSJim Jagielski if( !HasCntnt() && !pPos->InNumberGrp() )
571*b1cdbd2cSJim Jagielski {
572*b1cdbd2cSJim Jagielski if ( pPos->InExpGrp() )
573*b1cdbd2cSJim Jagielski {
574*b1cdbd2cSJim Jagielski XubString aTxt;
575*b1cdbd2cSJim Jagielski if( pPos->GetExpTxt( rInf, aTxt ) && aTxt.Len() )
576*b1cdbd2cSJim Jagielski SetCntnt( sal_True );
577*b1cdbd2cSJim Jagielski }
578*b1cdbd2cSJim Jagielski else if( ( pPos->InTxtGrp() || pPos->IsMultiPortion() ) &&
579*b1cdbd2cSJim Jagielski pPos->GetLen() )
580*b1cdbd2cSJim Jagielski SetCntnt( sal_True );
581*b1cdbd2cSJim Jagielski }
582*b1cdbd2cSJim Jagielski
583*b1cdbd2cSJim Jagielski bTmpDummy = bTmpDummy && !HasCntnt() &&
584*b1cdbd2cSJim Jagielski ( !pPos->Width() || pPos->IsFlyPortion() );
585*b1cdbd2cSJim Jagielski
586*b1cdbd2cSJim Jagielski pLast = pPos;
587*b1cdbd2cSJim Jagielski pPos = pPos->GetPortion();
588*b1cdbd2cSJim Jagielski }
589*b1cdbd2cSJim Jagielski
590*b1cdbd2cSJim Jagielski if( pFlyCnt )
591*b1cdbd2cSJim Jagielski {
592*b1cdbd2cSJim Jagielski if( pFlyCnt->Height() == Height() )
593*b1cdbd2cSJim Jagielski {
594*b1cdbd2cSJim Jagielski pFlyCnt->SetMax( sal_True );
595*b1cdbd2cSJim Jagielski if( Height() > nMaxDescent + nAscent )
596*b1cdbd2cSJim Jagielski {
597*b1cdbd2cSJim Jagielski if( 3 == pFlyCnt->GetAlign() ) // Bottom
598*b1cdbd2cSJim Jagielski nAscent = Height() - nMaxDescent;
599*b1cdbd2cSJim Jagielski else if( 2 == pFlyCnt->GetAlign() ) // Center
600*b1cdbd2cSJim Jagielski nAscent = ( Height() + nAscent - nMaxDescent ) / 2;
601*b1cdbd2cSJim Jagielski }
602*b1cdbd2cSJim Jagielski pFlyCnt->SetAscent( nAscent );
603*b1cdbd2cSJim Jagielski }
604*b1cdbd2cSJim Jagielski }
605*b1cdbd2cSJim Jagielski
606*b1cdbd2cSJim Jagielski if( bTmpDummy && nFlyHeight )
607*b1cdbd2cSJim Jagielski {
608*b1cdbd2cSJim Jagielski nAscent = nFlyAscent;
609*b1cdbd2cSJim Jagielski if( nFlyDescent > nFlyHeight - nFlyAscent )
610*b1cdbd2cSJim Jagielski Height( nFlyHeight + nFlyDescent );
611*b1cdbd2cSJim Jagielski else
612*b1cdbd2cSJim Jagielski Height( nFlyHeight );
613*b1cdbd2cSJim Jagielski }
614*b1cdbd2cSJim Jagielski else if( nMaxDescent > Height() - nAscent )
615*b1cdbd2cSJim Jagielski Height( nMaxDescent + nAscent );
616*b1cdbd2cSJim Jagielski
617*b1cdbd2cSJim Jagielski if( bOnlyPostIts && !( bHasBlankPortion && bHasOnlyBlankPortions ) )
618*b1cdbd2cSJim Jagielski {
619*b1cdbd2cSJim Jagielski Height( rInf.GetFont()->GetHeight( rInf.GetVsh(), *rInf.GetOut() ) );
620*b1cdbd2cSJim Jagielski nAscent = rInf.GetFont()->GetAscent( rInf.GetVsh(), *rInf.GetOut() );
621*b1cdbd2cSJim Jagielski }
622*b1cdbd2cSJim Jagielski }
623*b1cdbd2cSJim Jagielski }
624*b1cdbd2cSJim Jagielski else
625*b1cdbd2cSJim Jagielski {
626*b1cdbd2cSJim Jagielski SetCntnt( !bTmpDummy );
627*b1cdbd2cSJim Jagielski
628*b1cdbd2cSJim Jagielski // --> FME 2006-03-01 #i3952#
629*b1cdbd2cSJim Jagielski if ( bIgnoreBlanksAndTabsForLineHeightCalculation &&
630*b1cdbd2cSJim Jagielski lcl_HasOnlyBlanks( rInf.GetTxt(), rInf.GetLineStart(), rInf.GetLineStart() + GetLen() ) )
631*b1cdbd2cSJim Jagielski {
632*b1cdbd2cSJim Jagielski bHasBlankPortion = true;
633*b1cdbd2cSJim Jagielski }
634*b1cdbd2cSJim Jagielski // <--
635*b1cdbd2cSJim Jagielski }
636*b1cdbd2cSJim Jagielski
637*b1cdbd2cSJim Jagielski // --> FME 2006-03-01 #i3952#
638*b1cdbd2cSJim Jagielski if ( bHasBlankPortion && bHasOnlyBlankPortions )
639*b1cdbd2cSJim Jagielski {
640*b1cdbd2cSJim Jagielski sal_uInt16 nTmpAscent = GetAscent();
641*b1cdbd2cSJim Jagielski sal_uInt16 nTmpHeight = Height();
642*b1cdbd2cSJim Jagielski rLine.GetAttrHandler().GetDefaultAscentAndHeight( rInf.GetVsh(), *rInf.GetOut(), nTmpAscent, nTmpHeight );
643*b1cdbd2cSJim Jagielski SetAscent( nTmpAscent );
644*b1cdbd2cSJim Jagielski Height( nTmpHeight );
645*b1cdbd2cSJim Jagielski }
646*b1cdbd2cSJim Jagielski // <--
647*b1cdbd2cSJim Jagielski
648*b1cdbd2cSJim Jagielski // Robust:
649*b1cdbd2cSJim Jagielski if( nLineWidth < Width() )
650*b1cdbd2cSJim Jagielski Width( nLineWidth );
651*b1cdbd2cSJim Jagielski ASSERT( nLineWidth >= Width(), "SwLineLayout::CalcLine: line is bursting" );
652*b1cdbd2cSJim Jagielski SetDummy( bTmpDummy );
653*b1cdbd2cSJim Jagielski SetRedline( rLine.GetRedln() &&
654*b1cdbd2cSJim Jagielski rLine.GetRedln()->CheckLine( rLine.GetStart(), rLine.GetEnd() ) );
655*b1cdbd2cSJim Jagielski }
656*b1cdbd2cSJim Jagielski
657*b1cdbd2cSJim Jagielski // --> OD 2005-05-20 #i47162# - add optional parameter <_bNoFlyCntPorAndLinePor>
658*b1cdbd2cSJim Jagielski // to control, if the fly content portions and line portion are considered.
MaxAscentDescent(SwTwips & _orAscent,SwTwips & _orDescent,SwTwips & _orObjAscent,SwTwips & _orObjDescent,const SwLinePortion * _pDontConsiderPortion,const bool _bNoFlyCntPorAndLinePor) const659*b1cdbd2cSJim Jagielski void SwLineLayout::MaxAscentDescent( SwTwips& _orAscent,
660*b1cdbd2cSJim Jagielski SwTwips& _orDescent,
661*b1cdbd2cSJim Jagielski SwTwips& _orObjAscent,
662*b1cdbd2cSJim Jagielski SwTwips& _orObjDescent,
663*b1cdbd2cSJim Jagielski const SwLinePortion* _pDontConsiderPortion,
664*b1cdbd2cSJim Jagielski const bool _bNoFlyCntPorAndLinePor ) const
665*b1cdbd2cSJim Jagielski {
666*b1cdbd2cSJim Jagielski _orAscent = 0;
667*b1cdbd2cSJim Jagielski _orDescent = 0;
668*b1cdbd2cSJim Jagielski _orObjAscent = 0;
669*b1cdbd2cSJim Jagielski _orObjDescent = 0;
670*b1cdbd2cSJim Jagielski
671*b1cdbd2cSJim Jagielski const SwLinePortion* pTmpPortion = this;
672*b1cdbd2cSJim Jagielski if ( !pTmpPortion->GetLen() && pTmpPortion->GetPortion() )
673*b1cdbd2cSJim Jagielski {
674*b1cdbd2cSJim Jagielski pTmpPortion = pTmpPortion->GetPortion();
675*b1cdbd2cSJim Jagielski }
676*b1cdbd2cSJim Jagielski
677*b1cdbd2cSJim Jagielski while ( pTmpPortion )
678*b1cdbd2cSJim Jagielski {
679*b1cdbd2cSJim Jagielski if ( !pTmpPortion->IsBreakPortion() && !pTmpPortion->IsFlyPortion() &&
680*b1cdbd2cSJim Jagielski ( !_bNoFlyCntPorAndLinePor ||
681*b1cdbd2cSJim Jagielski ( !pTmpPortion->IsFlyCntPortion() &&
682*b1cdbd2cSJim Jagielski !(pTmpPortion == this && pTmpPortion->GetPortion() ) ) ) )
683*b1cdbd2cSJim Jagielski {
684*b1cdbd2cSJim Jagielski SwTwips nPortionAsc = static_cast<SwTwips>(pTmpPortion->GetAscent());
685*b1cdbd2cSJim Jagielski SwTwips nPortionDesc = static_cast<SwTwips>(pTmpPortion->Height()) -
686*b1cdbd2cSJim Jagielski nPortionAsc;
687*b1cdbd2cSJim Jagielski
688*b1cdbd2cSJim Jagielski const sal_Bool bFlyCmp = pTmpPortion->IsFlyCntPortion() ?
689*b1cdbd2cSJim Jagielski static_cast<const SwFlyCntPortion*>(pTmpPortion)->IsMax() :
690*b1cdbd2cSJim Jagielski !( pTmpPortion == _pDontConsiderPortion );
691*b1cdbd2cSJim Jagielski
692*b1cdbd2cSJim Jagielski if ( bFlyCmp )
693*b1cdbd2cSJim Jagielski {
694*b1cdbd2cSJim Jagielski _orObjAscent = Max( _orObjAscent, nPortionAsc );
695*b1cdbd2cSJim Jagielski _orObjDescent = Max( _orObjDescent, nPortionDesc );
696*b1cdbd2cSJim Jagielski }
697*b1cdbd2cSJim Jagielski
698*b1cdbd2cSJim Jagielski if ( !pTmpPortion->IsFlyCntPortion() && !pTmpPortion->IsGrfNumPortion() )
699*b1cdbd2cSJim Jagielski {
700*b1cdbd2cSJim Jagielski _orAscent = Max( _orAscent, nPortionAsc );
701*b1cdbd2cSJim Jagielski _orDescent = Max( _orDescent, nPortionDesc );
702*b1cdbd2cSJim Jagielski }
703*b1cdbd2cSJim Jagielski }
704*b1cdbd2cSJim Jagielski pTmpPortion = pTmpPortion->GetPortion();
705*b1cdbd2cSJim Jagielski }
706*b1cdbd2cSJim Jagielski }
707*b1cdbd2cSJim Jagielski
708*b1cdbd2cSJim Jagielski /*************************************************************************
709*b1cdbd2cSJim Jagielski * class SwCharRange
710*b1cdbd2cSJim Jagielski *************************************************************************/
711*b1cdbd2cSJim Jagielski
operator +=(const SwCharRange & rRange)712*b1cdbd2cSJim Jagielski SwCharRange &SwCharRange::operator+=(const SwCharRange &rRange)
713*b1cdbd2cSJim Jagielski {
714*b1cdbd2cSJim Jagielski if(0 != rRange.nLen ) {
715*b1cdbd2cSJim Jagielski if(0 == nLen) {
716*b1cdbd2cSJim Jagielski nStart = rRange.nStart;
717*b1cdbd2cSJim Jagielski nLen = rRange.nLen ;
718*b1cdbd2cSJim Jagielski }
719*b1cdbd2cSJim Jagielski else {
720*b1cdbd2cSJim Jagielski if(rRange.nStart + rRange.nLen > nStart + nLen) {
721*b1cdbd2cSJim Jagielski nLen = rRange.nStart + rRange.nLen - nStart;
722*b1cdbd2cSJim Jagielski }
723*b1cdbd2cSJim Jagielski if(rRange.nStart < nStart) {
724*b1cdbd2cSJim Jagielski nLen += nStart - rRange.nStart;
725*b1cdbd2cSJim Jagielski nStart = rRange.nStart;
726*b1cdbd2cSJim Jagielski }
727*b1cdbd2cSJim Jagielski }
728*b1cdbd2cSJim Jagielski }
729*b1cdbd2cSJim Jagielski return *this;
730*b1cdbd2cSJim Jagielski }
731*b1cdbd2cSJim Jagielski
732*b1cdbd2cSJim Jagielski /*************************************************************************
733*b1cdbd2cSJim Jagielski * SwScriptInfo::SwScriptInfo()
734*b1cdbd2cSJim Jagielski *************************************************************************/
SwScriptInfo()735*b1cdbd2cSJim Jagielski SwScriptInfo::SwScriptInfo() :
736*b1cdbd2cSJim Jagielski nInvalidityPos( 0 ),
737*b1cdbd2cSJim Jagielski nDefaultDir( 0 )
738*b1cdbd2cSJim Jagielski {
739*b1cdbd2cSJim Jagielski };
740*b1cdbd2cSJim Jagielski
741*b1cdbd2cSJim Jagielski /*************************************************************************
742*b1cdbd2cSJim Jagielski * SwScriptInfo::~SwScriptInfo()
743*b1cdbd2cSJim Jagielski *************************************************************************/
~SwScriptInfo()744*b1cdbd2cSJim Jagielski SwScriptInfo::~SwScriptInfo()
745*b1cdbd2cSJim Jagielski {
746*b1cdbd2cSJim Jagielski }
747*b1cdbd2cSJim Jagielski
748*b1cdbd2cSJim Jagielski /*************************************************************************
749*b1cdbd2cSJim Jagielski * SwScriptInfo::WhichFont()
750*b1cdbd2cSJim Jagielski *
751*b1cdbd2cSJim Jagielski * Converts i18n Script Type (LATIN, ASIAN, COMPLEX, WEAK) to
752*b1cdbd2cSJim Jagielski * Sw Script Types (SW_LATIN, SW_CJK, SW_CTL), used to identify the font
753*b1cdbd2cSJim Jagielski *************************************************************************/
WhichFont(xub_StrLen nIdx,const String * pTxt,const SwScriptInfo * pSI)754*b1cdbd2cSJim Jagielski sal_uInt8 SwScriptInfo::WhichFont( xub_StrLen nIdx, const String* pTxt, const SwScriptInfo* pSI )
755*b1cdbd2cSJim Jagielski {
756*b1cdbd2cSJim Jagielski ASSERT( pTxt || pSI,"How should I determine the script type?" );
757*b1cdbd2cSJim Jagielski sal_uInt16 nScript;
758*b1cdbd2cSJim Jagielski
759*b1cdbd2cSJim Jagielski // First we try to use our SwScriptInfo
760*b1cdbd2cSJim Jagielski if ( pSI )
761*b1cdbd2cSJim Jagielski nScript = pSI->ScriptType( nIdx );
762*b1cdbd2cSJim Jagielski else
763*b1cdbd2cSJim Jagielski // Ok, we have to ask the break iterator
764*b1cdbd2cSJim Jagielski nScript = pBreakIt->GetRealScriptOfText( *pTxt, nIdx );
765*b1cdbd2cSJim Jagielski
766*b1cdbd2cSJim Jagielski switch ( nScript ) {
767*b1cdbd2cSJim Jagielski case i18n::ScriptType::LATIN : return SW_LATIN;
768*b1cdbd2cSJim Jagielski case i18n::ScriptType::ASIAN : return SW_CJK;
769*b1cdbd2cSJim Jagielski case i18n::ScriptType::COMPLEX : return SW_CTL;
770*b1cdbd2cSJim Jagielski }
771*b1cdbd2cSJim Jagielski
772*b1cdbd2cSJim Jagielski ASSERT( sal_False, "Somebody tells lies about the script type!" );
773*b1cdbd2cSJim Jagielski return SW_LATIN;
774*b1cdbd2cSJim Jagielski }
775*b1cdbd2cSJim Jagielski
776*b1cdbd2cSJim Jagielski /*************************************************************************
777*b1cdbd2cSJim Jagielski * SwScriptInfo::InitScriptInfo()
778*b1cdbd2cSJim Jagielski *
779*b1cdbd2cSJim Jagielski * searches for script changes in rTxt and stores them
780*b1cdbd2cSJim Jagielski *************************************************************************/
781*b1cdbd2cSJim Jagielski
InitScriptInfo(const SwTxtNode & rNode)782*b1cdbd2cSJim Jagielski void SwScriptInfo::InitScriptInfo( const SwTxtNode& rNode )
783*b1cdbd2cSJim Jagielski {
784*b1cdbd2cSJim Jagielski InitScriptInfo( rNode, nDefaultDir == UBIDI_RTL );
785*b1cdbd2cSJim Jagielski }
786*b1cdbd2cSJim Jagielski
InitScriptInfo(const SwTxtNode & rNode,sal_Bool bRTL)787*b1cdbd2cSJim Jagielski void SwScriptInfo::InitScriptInfo( const SwTxtNode& rNode, sal_Bool bRTL )
788*b1cdbd2cSJim Jagielski {
789*b1cdbd2cSJim Jagielski if( !pBreakIt->GetBreakIter().is() )
790*b1cdbd2cSJim Jagielski return;
791*b1cdbd2cSJim Jagielski
792*b1cdbd2cSJim Jagielski const String& rTxt = rNode.GetTxt();
793*b1cdbd2cSJim Jagielski
794*b1cdbd2cSJim Jagielski //
795*b1cdbd2cSJim Jagielski // HIDDEN TEXT INFORMATION
796*b1cdbd2cSJim Jagielski //
797*b1cdbd2cSJim Jagielski Range aRange( 0, rTxt.Len() ? rTxt.Len() - 1 : 0 );
798*b1cdbd2cSJim Jagielski MultiSelection aHiddenMulti( aRange );
799*b1cdbd2cSJim Jagielski CalcHiddenRanges( rNode, aHiddenMulti );
800*b1cdbd2cSJim Jagielski
801*b1cdbd2cSJim Jagielski aHiddenChg.clear();
802*b1cdbd2cSJim Jagielski sal_uInt16 i = 0;
803*b1cdbd2cSJim Jagielski for( i = 0; i < aHiddenMulti.GetRangeCount(); ++i )
804*b1cdbd2cSJim Jagielski {
805*b1cdbd2cSJim Jagielski const Range& rRange = aHiddenMulti.GetRange( i );
806*b1cdbd2cSJim Jagielski const xub_StrLen nStart = (xub_StrLen)rRange.Min();
807*b1cdbd2cSJim Jagielski const xub_StrLen nEnd = (xub_StrLen)rRange.Max() + 1;
808*b1cdbd2cSJim Jagielski
809*b1cdbd2cSJim Jagielski aHiddenChg.push_back( nStart );
810*b1cdbd2cSJim Jagielski aHiddenChg.push_back( nEnd );
811*b1cdbd2cSJim Jagielski }
812*b1cdbd2cSJim Jagielski
813*b1cdbd2cSJim Jagielski //
814*b1cdbd2cSJim Jagielski // SCRIPT AND SCRIPT RELATED INFORMATION
815*b1cdbd2cSJim Jagielski //
816*b1cdbd2cSJim Jagielski
817*b1cdbd2cSJim Jagielski xub_StrLen nChg = nInvalidityPos;
818*b1cdbd2cSJim Jagielski
819*b1cdbd2cSJim Jagielski // STRING_LEN means the data structure is up to date
820*b1cdbd2cSJim Jagielski nInvalidityPos = STRING_LEN;
821*b1cdbd2cSJim Jagielski
822*b1cdbd2cSJim Jagielski // this is the default direction
823*b1cdbd2cSJim Jagielski nDefaultDir = static_cast<sal_uInt8>(bRTL ? UBIDI_RTL : UBIDI_LTR);
824*b1cdbd2cSJim Jagielski
825*b1cdbd2cSJim Jagielski // counter for script info arrays
826*b1cdbd2cSJim Jagielski sal_uInt16 nCnt = 0;
827*b1cdbd2cSJim Jagielski // counter for compression information arrays
828*b1cdbd2cSJim Jagielski sal_uInt16 nCntComp = 0;
829*b1cdbd2cSJim Jagielski // counter for kashida array
830*b1cdbd2cSJim Jagielski sal_uInt16 nCntKash = 0;
831*b1cdbd2cSJim Jagielski
832*b1cdbd2cSJim Jagielski sal_uInt8 nScript = i18n::ScriptType::LATIN;
833*b1cdbd2cSJim Jagielski
834*b1cdbd2cSJim Jagielski // compression type
835*b1cdbd2cSJim Jagielski const SwCharCompressType aCompEnum = rNode.getIDocumentSettingAccess()->getCharacterCompressionType();
836*b1cdbd2cSJim Jagielski
837*b1cdbd2cSJim Jagielski // justification type
838*b1cdbd2cSJim Jagielski const sal_Bool bAdjustBlock = SVX_ADJUST_BLOCK ==
839*b1cdbd2cSJim Jagielski rNode.GetSwAttrSet().GetAdjust().GetAdjust();
840*b1cdbd2cSJim Jagielski
841*b1cdbd2cSJim Jagielski //
842*b1cdbd2cSJim Jagielski // FIND INVALID RANGES IN SCRIPT INFO ARRAYS:
843*b1cdbd2cSJim Jagielski //
844*b1cdbd2cSJim Jagielski
845*b1cdbd2cSJim Jagielski if( nChg )
846*b1cdbd2cSJim Jagielski {
847*b1cdbd2cSJim Jagielski // if change position = 0 we do not use any data from the arrays
848*b1cdbd2cSJim Jagielski // because by deleting all characters of the first group at the beginning
849*b1cdbd2cSJim Jagielski // of a paragraph nScript is set to a wrong value
850*b1cdbd2cSJim Jagielski ASSERT( CountScriptChg(), "Where're my changes of script?" );
851*b1cdbd2cSJim Jagielski while( nCnt < CountScriptChg() )
852*b1cdbd2cSJim Jagielski {
853*b1cdbd2cSJim Jagielski if ( nChg > GetScriptChg( nCnt ) )
854*b1cdbd2cSJim Jagielski nCnt++;
855*b1cdbd2cSJim Jagielski else
856*b1cdbd2cSJim Jagielski {
857*b1cdbd2cSJim Jagielski nScript = GetScriptType( nCnt );
858*b1cdbd2cSJim Jagielski break;
859*b1cdbd2cSJim Jagielski }
860*b1cdbd2cSJim Jagielski }
861*b1cdbd2cSJim Jagielski if( CHARCOMPRESS_NONE != aCompEnum )
862*b1cdbd2cSJim Jagielski {
863*b1cdbd2cSJim Jagielski while( nCntComp < CountCompChg() )
864*b1cdbd2cSJim Jagielski {
865*b1cdbd2cSJim Jagielski if ( nChg > GetCompStart( nCntComp ) )
866*b1cdbd2cSJim Jagielski nCntComp++;
867*b1cdbd2cSJim Jagielski else
868*b1cdbd2cSJim Jagielski break;
869*b1cdbd2cSJim Jagielski }
870*b1cdbd2cSJim Jagielski }
871*b1cdbd2cSJim Jagielski if ( bAdjustBlock )
872*b1cdbd2cSJim Jagielski {
873*b1cdbd2cSJim Jagielski while( nCntKash < CountKashida() )
874*b1cdbd2cSJim Jagielski {
875*b1cdbd2cSJim Jagielski if ( nChg > GetKashida( nCntKash ) )
876*b1cdbd2cSJim Jagielski nCntKash++;
877*b1cdbd2cSJim Jagielski else
878*b1cdbd2cSJim Jagielski break;
879*b1cdbd2cSJim Jagielski }
880*b1cdbd2cSJim Jagielski }
881*b1cdbd2cSJim Jagielski }
882*b1cdbd2cSJim Jagielski
883*b1cdbd2cSJim Jagielski //
884*b1cdbd2cSJim Jagielski // ADJUST nChg VALUE:
885*b1cdbd2cSJim Jagielski //
886*b1cdbd2cSJim Jagielski
887*b1cdbd2cSJim Jagielski // by stepping back one position we know that we are inside a group
888*b1cdbd2cSJim Jagielski // declared as an nScript group
889*b1cdbd2cSJim Jagielski if ( nChg )
890*b1cdbd2cSJim Jagielski --nChg;
891*b1cdbd2cSJim Jagielski
892*b1cdbd2cSJim Jagielski const xub_StrLen nGrpStart = nCnt ? GetScriptChg( nCnt - 1 ) : 0;
893*b1cdbd2cSJim Jagielski
894*b1cdbd2cSJim Jagielski // we go back in our group until we reach the first character of
895*b1cdbd2cSJim Jagielski // type nScript
896*b1cdbd2cSJim Jagielski while ( nChg > nGrpStart &&
897*b1cdbd2cSJim Jagielski nScript != pBreakIt->GetBreakIter()->getScriptType( rTxt, nChg ) )
898*b1cdbd2cSJim Jagielski --nChg;
899*b1cdbd2cSJim Jagielski
900*b1cdbd2cSJim Jagielski // If we are at the start of a group, we do not trust nScript,
901*b1cdbd2cSJim Jagielski // we better get nScript from the breakiterator:
902*b1cdbd2cSJim Jagielski if ( nChg == nGrpStart )
903*b1cdbd2cSJim Jagielski nScript = (sal_uInt8)pBreakIt->GetBreakIter()->getScriptType( rTxt, nChg );
904*b1cdbd2cSJim Jagielski
905*b1cdbd2cSJim Jagielski //
906*b1cdbd2cSJim Jagielski // INVALID DATA FROM THE SCRIPT INFO ARRAYS HAS TO BE DELETED:
907*b1cdbd2cSJim Jagielski //
908*b1cdbd2cSJim Jagielski
909*b1cdbd2cSJim Jagielski // remove invalid entries from script information arrays
910*b1cdbd2cSJim Jagielski const size_t nScriptRemove = aScriptChg.size() - nCnt;
911*b1cdbd2cSJim Jagielski aScriptChg.erase( aScriptChg.begin() + nCnt, aScriptChg.end() );
912*b1cdbd2cSJim Jagielski aScriptType.erase( aScriptType.begin() + nCnt, aScriptType.begin() + (nCnt + nScriptRemove) );
913*b1cdbd2cSJim Jagielski
914*b1cdbd2cSJim Jagielski // get the start of the last compression group
915*b1cdbd2cSJim Jagielski sal_uInt16 nLastCompression = nChg;
916*b1cdbd2cSJim Jagielski if( nCntComp )
917*b1cdbd2cSJim Jagielski {
918*b1cdbd2cSJim Jagielski --nCntComp;
919*b1cdbd2cSJim Jagielski nLastCompression = GetCompStart( nCntComp );
920*b1cdbd2cSJim Jagielski if( nChg >= nLastCompression + GetCompLen( nCntComp ) )
921*b1cdbd2cSJim Jagielski {
922*b1cdbd2cSJim Jagielski nLastCompression = nChg;
923*b1cdbd2cSJim Jagielski ++nCntComp;
924*b1cdbd2cSJim Jagielski }
925*b1cdbd2cSJim Jagielski }
926*b1cdbd2cSJim Jagielski
927*b1cdbd2cSJim Jagielski // remove invalid entries from compression information arrays
928*b1cdbd2cSJim Jagielski const size_t nCompRemove = aCompChg.size() - nCntComp;
929*b1cdbd2cSJim Jagielski aCompChg.erase( aCompChg.begin() + nCntComp, aCompChg.end() );
930*b1cdbd2cSJim Jagielski aCompLen.erase( aCompLen.begin() + nCntComp, aCompLen.begin() + (nCntComp + nCompRemove) );
931*b1cdbd2cSJim Jagielski aCompType.erase( aCompType.begin() + nCntComp, aCompType.end() );
932*b1cdbd2cSJim Jagielski
933*b1cdbd2cSJim Jagielski // get the start of the last kashida group
934*b1cdbd2cSJim Jagielski sal_uInt16 nLastKashida = nChg;
935*b1cdbd2cSJim Jagielski if( nCntKash && i18n::ScriptType::COMPLEX == nScript )
936*b1cdbd2cSJim Jagielski {
937*b1cdbd2cSJim Jagielski --nCntKash;
938*b1cdbd2cSJim Jagielski nLastKashida = GetKashida( nCntKash );
939*b1cdbd2cSJim Jagielski }
940*b1cdbd2cSJim Jagielski
941*b1cdbd2cSJim Jagielski // remove invalid entries from kashida array
942*b1cdbd2cSJim Jagielski aKashida.erase( aKashida.begin() + nCntKash, aKashida.end() );
943*b1cdbd2cSJim Jagielski
944*b1cdbd2cSJim Jagielski //
945*b1cdbd2cSJim Jagielski // TAKE CARE OF WEAK CHARACTERS: WE MUST FIND AN APPROPRIATE
946*b1cdbd2cSJim Jagielski // SCRIPT FOR WEAK CHARACTERS AT THE BEGINNING OF A PARAGRAPH
947*b1cdbd2cSJim Jagielski //
948*b1cdbd2cSJim Jagielski
949*b1cdbd2cSJim Jagielski if( WEAK == pBreakIt->GetBreakIter()->getScriptType( rTxt, nChg ) )
950*b1cdbd2cSJim Jagielski {
951*b1cdbd2cSJim Jagielski // If the beginning of the current group is weak, this means that
952*b1cdbd2cSJim Jagielski // all of the characters in this grounp are weak. We have to assign
953*b1cdbd2cSJim Jagielski // the scripts to these characters depending on the fonts which are
954*b1cdbd2cSJim Jagielski // set for these characters to display them.
955*b1cdbd2cSJim Jagielski xub_StrLen nEnd =
956*b1cdbd2cSJim Jagielski (xub_StrLen)pBreakIt->GetBreakIter()->endOfScript( rTxt, nChg, WEAK );
957*b1cdbd2cSJim Jagielski
958*b1cdbd2cSJim Jagielski if( nEnd > rTxt.Len() )
959*b1cdbd2cSJim Jagielski nEnd = rTxt.Len();
960*b1cdbd2cSJim Jagielski
961*b1cdbd2cSJim Jagielski nScript = (sal_uInt8)GetI18NScriptTypeOfLanguage( (sal_uInt16)GetAppLanguage() );
962*b1cdbd2cSJim Jagielski
963*b1cdbd2cSJim Jagielski ASSERT( i18n::ScriptType::LATIN == nScript ||
964*b1cdbd2cSJim Jagielski i18n::ScriptType::ASIAN == nScript ||
965*b1cdbd2cSJim Jagielski i18n::ScriptType::COMPLEX == nScript, "Wrong default language" );
966*b1cdbd2cSJim Jagielski
967*b1cdbd2cSJim Jagielski nChg = nEnd;
968*b1cdbd2cSJim Jagielski
969*b1cdbd2cSJim Jagielski // Get next script type or set to weak in order to exit
970*b1cdbd2cSJim Jagielski sal_uInt8 nNextScript = ( nEnd < rTxt.Len() ) ?
971*b1cdbd2cSJim Jagielski (sal_uInt8)pBreakIt->GetBreakIter()->getScriptType( rTxt, nEnd ) :
972*b1cdbd2cSJim Jagielski (sal_uInt8)WEAK;
973*b1cdbd2cSJim Jagielski
974*b1cdbd2cSJim Jagielski if ( nScript != nNextScript )
975*b1cdbd2cSJim Jagielski {
976*b1cdbd2cSJim Jagielski aScriptChg.insert( aScriptChg.begin() + nCnt, nEnd );
977*b1cdbd2cSJim Jagielski aScriptType.insert( aScriptType.begin() + nCnt, nScript );
978*b1cdbd2cSJim Jagielski nCnt++;
979*b1cdbd2cSJim Jagielski nScript = nNextScript;
980*b1cdbd2cSJim Jagielski }
981*b1cdbd2cSJim Jagielski }
982*b1cdbd2cSJim Jagielski
983*b1cdbd2cSJim Jagielski //
984*b1cdbd2cSJim Jagielski // UPDATE THE SCRIPT INFO ARRAYS:
985*b1cdbd2cSJim Jagielski //
986*b1cdbd2cSJim Jagielski
987*b1cdbd2cSJim Jagielski while ( nChg < rTxt.Len() || ( aScriptChg.empty() && !rTxt.Len() ) )
988*b1cdbd2cSJim Jagielski {
989*b1cdbd2cSJim Jagielski ASSERT( i18n::ScriptType::WEAK != nScript,
990*b1cdbd2cSJim Jagielski "Inserting WEAK into SwScriptInfo structure" );
991*b1cdbd2cSJim Jagielski ASSERT( STRING_LEN != nChg, "65K? Strange length of script section" );
992*b1cdbd2cSJim Jagielski
993*b1cdbd2cSJim Jagielski xub_StrLen nSearchStt = nChg;
994*b1cdbd2cSJim Jagielski nChg = (xub_StrLen)pBreakIt->GetBreakIter()->endOfScript( rTxt, nSearchStt, nScript );
995*b1cdbd2cSJim Jagielski
996*b1cdbd2cSJim Jagielski if ( nChg > rTxt.Len() )
997*b1cdbd2cSJim Jagielski nChg = rTxt.Len();
998*b1cdbd2cSJim Jagielski
999*b1cdbd2cSJim Jagielski // --> FME 2008-09-17 #i28203#
1000*b1cdbd2cSJim Jagielski // for 'complex' portions, we make sure that a portion does not contain more
1001*b1cdbd2cSJim Jagielski // than one script:
1002*b1cdbd2cSJim Jagielski if( i18n::ScriptType::COMPLEX == nScript && pBreakIt->GetScriptTypeDetector().is() )
1003*b1cdbd2cSJim Jagielski {
1004*b1cdbd2cSJim Jagielski const short nScriptType = pBreakIt->GetScriptTypeDetector()->getCTLScriptType( rTxt, nSearchStt );
1005*b1cdbd2cSJim Jagielski xub_StrLen nNextCTLScriptStart = nSearchStt;
1006*b1cdbd2cSJim Jagielski short nCurrentScriptType = nScriptType;
1007*b1cdbd2cSJim Jagielski while( com::sun::star::i18n::CTLScriptType::CTL_UNKNOWN == nCurrentScriptType || nScriptType == nCurrentScriptType )
1008*b1cdbd2cSJim Jagielski {
1009*b1cdbd2cSJim Jagielski nNextCTLScriptStart = (xub_StrLen)pBreakIt->GetScriptTypeDetector()->endOfCTLScriptType( rTxt, nNextCTLScriptStart );
1010*b1cdbd2cSJim Jagielski if( nNextCTLScriptStart < rTxt.Len() && nNextCTLScriptStart < nChg )
1011*b1cdbd2cSJim Jagielski nCurrentScriptType = pBreakIt->GetScriptTypeDetector()->getCTLScriptType( rTxt, nNextCTLScriptStart );
1012*b1cdbd2cSJim Jagielski else
1013*b1cdbd2cSJim Jagielski break;
1014*b1cdbd2cSJim Jagielski }
1015*b1cdbd2cSJim Jagielski nChg = Min( nChg, nNextCTLScriptStart );
1016*b1cdbd2cSJim Jagielski }
1017*b1cdbd2cSJim Jagielski // <--
1018*b1cdbd2cSJim Jagielski
1019*b1cdbd2cSJim Jagielski // special case for dotted circle since it can be used with complex
1020*b1cdbd2cSJim Jagielski // before a mark, so we want it associated with the mark's script
1021*b1cdbd2cSJim Jagielski if (nChg < rTxt.Len() && nChg > 0 && (i18n::ScriptType::WEAK ==
1022*b1cdbd2cSJim Jagielski pBreakIt->GetBreakIter()->getScriptType(rTxt,nChg - 1)))
1023*b1cdbd2cSJim Jagielski {
1024*b1cdbd2cSJim Jagielski int8_t nType = u_charType(rTxt.GetChar(nChg) );
1025*b1cdbd2cSJim Jagielski if (nType == U_NON_SPACING_MARK || nType == U_ENCLOSING_MARK ||
1026*b1cdbd2cSJim Jagielski nType == U_COMBINING_SPACING_MARK )
1027*b1cdbd2cSJim Jagielski {
1028*b1cdbd2cSJim Jagielski aScriptChg.insert( aScriptChg.begin() + nCnt, nChg - 1 );
1029*b1cdbd2cSJim Jagielski }
1030*b1cdbd2cSJim Jagielski else
1031*b1cdbd2cSJim Jagielski {
1032*b1cdbd2cSJim Jagielski aScriptChg.insert( aScriptChg.begin() + nCnt, nChg );
1033*b1cdbd2cSJim Jagielski }
1034*b1cdbd2cSJim Jagielski }
1035*b1cdbd2cSJim Jagielski else
1036*b1cdbd2cSJim Jagielski {
1037*b1cdbd2cSJim Jagielski aScriptChg.insert( aScriptChg.begin() + nCnt, nChg );
1038*b1cdbd2cSJim Jagielski }
1039*b1cdbd2cSJim Jagielski aScriptType.insert( aScriptType.begin() + nCnt, nScript );
1040*b1cdbd2cSJim Jagielski nCnt++;
1041*b1cdbd2cSJim Jagielski
1042*b1cdbd2cSJim Jagielski // if current script is asian, we search for compressable characters
1043*b1cdbd2cSJim Jagielski // in this range
1044*b1cdbd2cSJim Jagielski if ( CHARCOMPRESS_NONE != aCompEnum &&
1045*b1cdbd2cSJim Jagielski i18n::ScriptType::ASIAN == nScript )
1046*b1cdbd2cSJim Jagielski {
1047*b1cdbd2cSJim Jagielski sal_uInt8 ePrevState = NONE;
1048*b1cdbd2cSJim Jagielski sal_uInt8 eState;
1049*b1cdbd2cSJim Jagielski sal_uInt16 nPrevChg = nLastCompression;
1050*b1cdbd2cSJim Jagielski
1051*b1cdbd2cSJim Jagielski while ( nLastCompression < nChg )
1052*b1cdbd2cSJim Jagielski {
1053*b1cdbd2cSJim Jagielski xub_Unicode cChar = rTxt.GetChar( nLastCompression );
1054*b1cdbd2cSJim Jagielski
1055*b1cdbd2cSJim Jagielski // examine current character
1056*b1cdbd2cSJim Jagielski switch ( cChar )
1057*b1cdbd2cSJim Jagielski {
1058*b1cdbd2cSJim Jagielski // Left punctuation found
1059*b1cdbd2cSJim Jagielski case 0x3008: case 0x300A: case 0x300C: case 0x300E:
1060*b1cdbd2cSJim Jagielski case 0x3010: case 0x3014: case 0x3016: case 0x3018:
1061*b1cdbd2cSJim Jagielski case 0x301A: case 0x301D:
1062*b1cdbd2cSJim Jagielski eState = SPECIAL_LEFT;
1063*b1cdbd2cSJim Jagielski break;
1064*b1cdbd2cSJim Jagielski // Right punctuation found
1065*b1cdbd2cSJim Jagielski case 0x3001: case 0x3002: case 0x3009: case 0x300B:
1066*b1cdbd2cSJim Jagielski case 0x300D: case 0x300F: case 0x3011: case 0x3015:
1067*b1cdbd2cSJim Jagielski case 0x3017: case 0x3019: case 0x301B: case 0x301E:
1068*b1cdbd2cSJim Jagielski case 0x301F:
1069*b1cdbd2cSJim Jagielski eState = SPECIAL_RIGHT;
1070*b1cdbd2cSJim Jagielski break;
1071*b1cdbd2cSJim Jagielski default:
1072*b1cdbd2cSJim Jagielski eState = static_cast<sal_uInt8>( ( 0x3040 <= cChar && 0x3100 > cChar ) ? KANA : NONE );
1073*b1cdbd2cSJim Jagielski }
1074*b1cdbd2cSJim Jagielski
1075*b1cdbd2cSJim Jagielski // insert range of compressable characters
1076*b1cdbd2cSJim Jagielski if( ePrevState != eState )
1077*b1cdbd2cSJim Jagielski {
1078*b1cdbd2cSJim Jagielski if ( ePrevState != NONE )
1079*b1cdbd2cSJim Jagielski {
1080*b1cdbd2cSJim Jagielski // insert start and type
1081*b1cdbd2cSJim Jagielski if ( CHARCOMPRESS_PUNCTUATION_KANA == aCompEnum ||
1082*b1cdbd2cSJim Jagielski ePrevState != KANA )
1083*b1cdbd2cSJim Jagielski {
1084*b1cdbd2cSJim Jagielski aCompChg.insert( aCompChg.begin() + nCntComp, nPrevChg );
1085*b1cdbd2cSJim Jagielski sal_uInt8 nTmpType = ePrevState;
1086*b1cdbd2cSJim Jagielski aCompType.insert( aCompType.begin() + nCntComp, nTmpType );
1087*b1cdbd2cSJim Jagielski aCompLen.insert( aCompLen.begin() + nCntComp, nLastCompression - nPrevChg );
1088*b1cdbd2cSJim Jagielski nCntComp++;
1089*b1cdbd2cSJim Jagielski }
1090*b1cdbd2cSJim Jagielski }
1091*b1cdbd2cSJim Jagielski
1092*b1cdbd2cSJim Jagielski ePrevState = eState;
1093*b1cdbd2cSJim Jagielski nPrevChg = nLastCompression;
1094*b1cdbd2cSJim Jagielski }
1095*b1cdbd2cSJim Jagielski
1096*b1cdbd2cSJim Jagielski nLastCompression++;
1097*b1cdbd2cSJim Jagielski }
1098*b1cdbd2cSJim Jagielski
1099*b1cdbd2cSJim Jagielski // we still have to examine last entry
1100*b1cdbd2cSJim Jagielski if ( ePrevState != NONE )
1101*b1cdbd2cSJim Jagielski {
1102*b1cdbd2cSJim Jagielski // insert start and type
1103*b1cdbd2cSJim Jagielski if ( CHARCOMPRESS_PUNCTUATION_KANA == aCompEnum ||
1104*b1cdbd2cSJim Jagielski ePrevState != KANA )
1105*b1cdbd2cSJim Jagielski {
1106*b1cdbd2cSJim Jagielski aCompChg.insert( aCompChg.begin() + nCntComp, nPrevChg );
1107*b1cdbd2cSJim Jagielski sal_uInt8 nTmpType = ePrevState;
1108*b1cdbd2cSJim Jagielski aCompType.insert( aCompType.begin() + nCntComp, nTmpType );
1109*b1cdbd2cSJim Jagielski aCompLen.insert( aCompLen.begin() + nCntComp, nLastCompression - nPrevChg );
1110*b1cdbd2cSJim Jagielski nCntComp++;
1111*b1cdbd2cSJim Jagielski }
1112*b1cdbd2cSJim Jagielski }
1113*b1cdbd2cSJim Jagielski }
1114*b1cdbd2cSJim Jagielski
1115*b1cdbd2cSJim Jagielski // we search for connecting opportunities (kashida)
1116*b1cdbd2cSJim Jagielski else if ( bAdjustBlock && i18n::ScriptType::COMPLEX == nScript )
1117*b1cdbd2cSJim Jagielski {
1118*b1cdbd2cSJim Jagielski SwScanner aScanner( rNode, rNode.GetTxt(), 0, 0,
1119*b1cdbd2cSJim Jagielski i18n::WordType::DICTIONARY_WORD,
1120*b1cdbd2cSJim Jagielski nLastKashida, nChg );
1121*b1cdbd2cSJim Jagielski
1122*b1cdbd2cSJim Jagielski // the search has to be performed on a per word base
1123*b1cdbd2cSJim Jagielski while ( aScanner.NextWord() )
1124*b1cdbd2cSJim Jagielski {
1125*b1cdbd2cSJim Jagielski const XubString& rWord = aScanner.GetWord();
1126*b1cdbd2cSJim Jagielski
1127*b1cdbd2cSJim Jagielski xub_StrLen nIdx = 0;
1128*b1cdbd2cSJim Jagielski xub_StrLen nKashidaPos = STRING_LEN;
1129*b1cdbd2cSJim Jagielski xub_Unicode cCh;
1130*b1cdbd2cSJim Jagielski xub_Unicode cPrevCh = 0;
1131*b1cdbd2cSJim Jagielski
1132*b1cdbd2cSJim Jagielski sal_uInt16 nPriorityLevel = 7; // 0..6 = level found
1133*b1cdbd2cSJim Jagielski // 7 not found
1134*b1cdbd2cSJim Jagielski
1135*b1cdbd2cSJim Jagielski xub_StrLen nWordLen = rWord.Len();
1136*b1cdbd2cSJim Jagielski
1137*b1cdbd2cSJim Jagielski // ignore trailing vowel chars
1138*b1cdbd2cSJim Jagielski while( nWordLen && isTransparentChar( rWord.GetChar( nWordLen - 1 )))
1139*b1cdbd2cSJim Jagielski --nWordLen;
1140*b1cdbd2cSJim Jagielski
1141*b1cdbd2cSJim Jagielski while (nIdx < nWordLen)
1142*b1cdbd2cSJim Jagielski {
1143*b1cdbd2cSJim Jagielski cCh = rWord.GetChar( nIdx );
1144*b1cdbd2cSJim Jagielski
1145*b1cdbd2cSJim Jagielski // 1. Priority:
1146*b1cdbd2cSJim Jagielski // after user inserted kashida
1147*b1cdbd2cSJim Jagielski if ( 0x640 == cCh )
1148*b1cdbd2cSJim Jagielski {
1149*b1cdbd2cSJim Jagielski nKashidaPos = aScanner.GetBegin() + nIdx;
1150*b1cdbd2cSJim Jagielski nPriorityLevel = 0;
1151*b1cdbd2cSJim Jagielski }
1152*b1cdbd2cSJim Jagielski
1153*b1cdbd2cSJim Jagielski // 2. Priority:
1154*b1cdbd2cSJim Jagielski // after a Seen or Sad
1155*b1cdbd2cSJim Jagielski if (nPriorityLevel >= 1 && nIdx < nWordLen - 1)
1156*b1cdbd2cSJim Jagielski {
1157*b1cdbd2cSJim Jagielski if( isSeenOrSadChar( cCh )
1158*b1cdbd2cSJim Jagielski && (rWord.GetChar( nIdx+1 ) != 0x200C) ) // #i98410#: prevent ZWNJ expansion
1159*b1cdbd2cSJim Jagielski {
1160*b1cdbd2cSJim Jagielski nKashidaPos = aScanner.GetBegin() + nIdx;
1161*b1cdbd2cSJim Jagielski nPriorityLevel = 1;
1162*b1cdbd2cSJim Jagielski }
1163*b1cdbd2cSJim Jagielski }
1164*b1cdbd2cSJim Jagielski
1165*b1cdbd2cSJim Jagielski // 3. Priority:
1166*b1cdbd2cSJim Jagielski // before final form of Teh Marbuta, Hah, Dal
1167*b1cdbd2cSJim Jagielski if ( nPriorityLevel >= 2 && nIdx > 0 )
1168*b1cdbd2cSJim Jagielski {
1169*b1cdbd2cSJim Jagielski if ( isTehMarbutaChar ( cCh ) || // Teh Marbuta (right joining)
1170*b1cdbd2cSJim Jagielski isDalChar ( cCh ) || // Dal (right joining) final form may appear in the middle of word
1171*b1cdbd2cSJim Jagielski ( isHahChar ( cCh ) && nIdx == nWordLen - 1)) // Hah (dual joining) only at end of word
1172*b1cdbd2cSJim Jagielski {
1173*b1cdbd2cSJim Jagielski
1174*b1cdbd2cSJim Jagielski ASSERT( 0 != cPrevCh, "No previous character" )
1175*b1cdbd2cSJim Jagielski // check if character is connectable to previous character,
1176*b1cdbd2cSJim Jagielski if ( lcl_ConnectToPrev( cCh, cPrevCh ) )
1177*b1cdbd2cSJim Jagielski {
1178*b1cdbd2cSJim Jagielski nKashidaPos = aScanner.GetBegin() + nIdx - 1;
1179*b1cdbd2cSJim Jagielski nPriorityLevel = 2;
1180*b1cdbd2cSJim Jagielski }
1181*b1cdbd2cSJim Jagielski }
1182*b1cdbd2cSJim Jagielski }
1183*b1cdbd2cSJim Jagielski
1184*b1cdbd2cSJim Jagielski // 4. Priority:
1185*b1cdbd2cSJim Jagielski // before final form of Alef, Lam or Kaf
1186*b1cdbd2cSJim Jagielski if ( nPriorityLevel >= 3 && nIdx > 0 )
1187*b1cdbd2cSJim Jagielski {
1188*b1cdbd2cSJim Jagielski if ( isAlefChar ( cCh ) || // Alef (right joining) final form may appear in the middle of word
1189*b1cdbd2cSJim Jagielski (( isLamChar ( cCh ) || // Lam
1190*b1cdbd2cSJim Jagielski isKafChar ( cCh ) || // Kaf (both dual joining)
1191*b1cdbd2cSJim Jagielski isGafChar ( cCh ) )
1192*b1cdbd2cSJim Jagielski && nIdx == nWordLen - 1)) // only at end of word
1193*b1cdbd2cSJim Jagielski {
1194*b1cdbd2cSJim Jagielski ASSERT( 0 != cPrevCh, "No previous character" )
1195*b1cdbd2cSJim Jagielski // check if character is connectable to previous character,
1196*b1cdbd2cSJim Jagielski if ( lcl_ConnectToPrev( cCh, cPrevCh ) )
1197*b1cdbd2cSJim Jagielski {
1198*b1cdbd2cSJim Jagielski nKashidaPos = aScanner.GetBegin() + nIdx - 1;
1199*b1cdbd2cSJim Jagielski nPriorityLevel = 3;
1200*b1cdbd2cSJim Jagielski }
1201*b1cdbd2cSJim Jagielski }
1202*b1cdbd2cSJim Jagielski }
1203*b1cdbd2cSJim Jagielski
1204*b1cdbd2cSJim Jagielski // 5. Priority:
1205*b1cdbd2cSJim Jagielski // before media Bah
1206*b1cdbd2cSJim Jagielski if ( nPriorityLevel >= 4 && nIdx > 0 && nIdx < nWordLen - 1 )
1207*b1cdbd2cSJim Jagielski {
1208*b1cdbd2cSJim Jagielski if ( isBaaChar ( cCh )) // Bah
1209*b1cdbd2cSJim Jagielski {
1210*b1cdbd2cSJim Jagielski // check if next character is Reh, Yeh or Alef Maksura
1211*b1cdbd2cSJim Jagielski xub_Unicode cNextCh = rWord.GetChar( nIdx + 1 );
1212*b1cdbd2cSJim Jagielski if ( isRehChar ( cNextCh ) || isYehChar ( cNextCh ))
1213*b1cdbd2cSJim Jagielski {
1214*b1cdbd2cSJim Jagielski ASSERT( 0 != cPrevCh, "No previous character" )
1215*b1cdbd2cSJim Jagielski // check if character is connectable to previous character,
1216*b1cdbd2cSJim Jagielski if ( lcl_ConnectToPrev( cCh, cPrevCh ) )
1217*b1cdbd2cSJim Jagielski {
1218*b1cdbd2cSJim Jagielski nKashidaPos = aScanner.GetBegin() + nIdx - 1;
1219*b1cdbd2cSJim Jagielski nPriorityLevel = 4;
1220*b1cdbd2cSJim Jagielski }
1221*b1cdbd2cSJim Jagielski }
1222*b1cdbd2cSJim Jagielski }
1223*b1cdbd2cSJim Jagielski }
1224*b1cdbd2cSJim Jagielski
1225*b1cdbd2cSJim Jagielski // 6. Priority:
1226*b1cdbd2cSJim Jagielski // before the final form of Waw, Ain, Qaf and Fa
1227*b1cdbd2cSJim Jagielski if ( nPriorityLevel >= 5 && nIdx > 0 )
1228*b1cdbd2cSJim Jagielski {
1229*b1cdbd2cSJim Jagielski if ( isWawChar ( cCh ) || // Wav (right joining)
1230*b1cdbd2cSJim Jagielski // final form may appear in the middle of word
1231*b1cdbd2cSJim Jagielski (( isAinChar ( cCh ) || // Ain (dual joining)
1232*b1cdbd2cSJim Jagielski isQafChar ( cCh ) || // Qaf (dual joining)
1233*b1cdbd2cSJim Jagielski isFeChar ( cCh ) ) // Feh (dual joining)
1234*b1cdbd2cSJim Jagielski && nIdx == nWordLen - 1)) // only at end of word
1235*b1cdbd2cSJim Jagielski {
1236*b1cdbd2cSJim Jagielski ASSERT( 0 != cPrevCh, "No previous character" )
1237*b1cdbd2cSJim Jagielski // check if character is connectable to previous character,
1238*b1cdbd2cSJim Jagielski if ( lcl_ConnectToPrev( cCh, cPrevCh ) )
1239*b1cdbd2cSJim Jagielski {
1240*b1cdbd2cSJim Jagielski nKashidaPos = aScanner.GetBegin() + nIdx - 1;
1241*b1cdbd2cSJim Jagielski nPriorityLevel = 5;
1242*b1cdbd2cSJim Jagielski }
1243*b1cdbd2cSJim Jagielski }
1244*b1cdbd2cSJim Jagielski }
1245*b1cdbd2cSJim Jagielski
1246*b1cdbd2cSJim Jagielski // other connecting possibilities
1247*b1cdbd2cSJim Jagielski if ( nPriorityLevel >= 6 && nIdx > 0 )
1248*b1cdbd2cSJim Jagielski {
1249*b1cdbd2cSJim Jagielski // remaining right joiners
1250*b1cdbd2cSJim Jagielski // Reh, Zain, Thal,
1251*b1cdbd2cSJim Jagielski if ( isRehChar ( cCh ) || // Reh Zain (right joining)
1252*b1cdbd2cSJim Jagielski // final form may appear in the middle of word
1253*b1cdbd2cSJim Jagielski ( 0x60C <= cCh && 0x6FE >= cCh // all others
1254*b1cdbd2cSJim Jagielski && nIdx == nWordLen - 1)) // only at end of word
1255*b1cdbd2cSJim Jagielski {
1256*b1cdbd2cSJim Jagielski ASSERT( 0 != cPrevCh, "No previous character" )
1257*b1cdbd2cSJim Jagielski // check if character is connectable to previous character,
1258*b1cdbd2cSJim Jagielski if ( lcl_ConnectToPrev( cCh, cPrevCh ) )
1259*b1cdbd2cSJim Jagielski {
1260*b1cdbd2cSJim Jagielski nKashidaPos = aScanner.GetBegin() + nIdx - 1;
1261*b1cdbd2cSJim Jagielski nPriorityLevel = 6;
1262*b1cdbd2cSJim Jagielski }
1263*b1cdbd2cSJim Jagielski }
1264*b1cdbd2cSJim Jagielski }
1265*b1cdbd2cSJim Jagielski
1266*b1cdbd2cSJim Jagielski // Do not consider Fathatan, Dammatan, Kasratan, Fatha,
1267*b1cdbd2cSJim Jagielski // Damma, Kasra, Shadda and Sukun when checking if
1268*b1cdbd2cSJim Jagielski // a character can be connected to previous character.
1269*b1cdbd2cSJim Jagielski if ( !isTransparentChar ( cCh) )
1270*b1cdbd2cSJim Jagielski cPrevCh = cCh;
1271*b1cdbd2cSJim Jagielski
1272*b1cdbd2cSJim Jagielski ++nIdx;
1273*b1cdbd2cSJim Jagielski } // end of current word
1274*b1cdbd2cSJim Jagielski
1275*b1cdbd2cSJim Jagielski if ( STRING_LEN != nKashidaPos )
1276*b1cdbd2cSJim Jagielski {
1277*b1cdbd2cSJim Jagielski aKashida.insert( aKashida.begin() + nCntKash, nKashidaPos);
1278*b1cdbd2cSJim Jagielski nCntKash++;
1279*b1cdbd2cSJim Jagielski }
1280*b1cdbd2cSJim Jagielski } // end of kashida search
1281*b1cdbd2cSJim Jagielski }
1282*b1cdbd2cSJim Jagielski
1283*b1cdbd2cSJim Jagielski if ( nChg < rTxt.Len() )
1284*b1cdbd2cSJim Jagielski nScript = (sal_uInt8)pBreakIt->GetBreakIter()->getScriptType( rTxt, nChg );
1285*b1cdbd2cSJim Jagielski
1286*b1cdbd2cSJim Jagielski nLastCompression = nChg;
1287*b1cdbd2cSJim Jagielski nLastKashida = nChg;
1288*b1cdbd2cSJim Jagielski };
1289*b1cdbd2cSJim Jagielski
1290*b1cdbd2cSJim Jagielski #ifdef DBG_UTIL
1291*b1cdbd2cSJim Jagielski // check kashida data
1292*b1cdbd2cSJim Jagielski long nTmpKashidaPos = -1;
1293*b1cdbd2cSJim Jagielski sal_Bool bWrongKash = sal_False;
1294*b1cdbd2cSJim Jagielski for (i = 0; i < aKashida.size(); ++i )
1295*b1cdbd2cSJim Jagielski {
1296*b1cdbd2cSJim Jagielski long nCurrKashidaPos = GetKashida( i );
1297*b1cdbd2cSJim Jagielski if ( nCurrKashidaPos <= nTmpKashidaPos )
1298*b1cdbd2cSJim Jagielski {
1299*b1cdbd2cSJim Jagielski bWrongKash = sal_True;
1300*b1cdbd2cSJim Jagielski break;
1301*b1cdbd2cSJim Jagielski }
1302*b1cdbd2cSJim Jagielski nTmpKashidaPos = nCurrKashidaPos;
1303*b1cdbd2cSJim Jagielski }
1304*b1cdbd2cSJim Jagielski ASSERT( ! bWrongKash, "Kashida array contains wrong data" )
1305*b1cdbd2cSJim Jagielski #endif
1306*b1cdbd2cSJim Jagielski
1307*b1cdbd2cSJim Jagielski // remove invalid entries from direction information arrays
1308*b1cdbd2cSJim Jagielski aDirChg.clear();
1309*b1cdbd2cSJim Jagielski aDirType.clear();
1310*b1cdbd2cSJim Jagielski
1311*b1cdbd2cSJim Jagielski // Perform Unicode Bidi Algorithm for text direction information
1312*b1cdbd2cSJim Jagielski bool bPerformUBA = UBIDI_LTR != nDefaultDir;
1313*b1cdbd2cSJim Jagielski nCnt = 0;
1314*b1cdbd2cSJim Jagielski while( !bPerformUBA && nCnt < CountScriptChg() )
1315*b1cdbd2cSJim Jagielski {
1316*b1cdbd2cSJim Jagielski if ( i18n::ScriptType::COMPLEX == GetScriptType( nCnt++ ) )
1317*b1cdbd2cSJim Jagielski bPerformUBA = true;
1318*b1cdbd2cSJim Jagielski }
1319*b1cdbd2cSJim Jagielski
1320*b1cdbd2cSJim Jagielski // do not call the unicode bidi algorithm if not required
1321*b1cdbd2cSJim Jagielski if ( bPerformUBA )
1322*b1cdbd2cSJim Jagielski {
1323*b1cdbd2cSJim Jagielski UpdateBidiInfo( rTxt );
1324*b1cdbd2cSJim Jagielski
1325*b1cdbd2cSJim Jagielski // #i16354# Change script type for RTL text to CTL:
1326*b1cdbd2cSJim Jagielski // 1. All text in RTL runs will use the CTL font
1327*b1cdbd2cSJim Jagielski // #i89825# change the script type also to CTL (hennerdrewes)
1328*b1cdbd2cSJim Jagielski // 2. Text in embedded LTR runs that does not have any strong LTR characters (numbers!)
1329*b1cdbd2cSJim Jagielski for ( size_t nDirIdx = 0; nDirIdx < aDirChg.size(); ++nDirIdx )
1330*b1cdbd2cSJim Jagielski {
1331*b1cdbd2cSJim Jagielski const sal_uInt8 nCurrDirType = GetDirType( nDirIdx );
1332*b1cdbd2cSJim Jagielski // nStart ist start of RTL run:
1333*b1cdbd2cSJim Jagielski const xub_StrLen nStart = nDirIdx > 0 ? GetDirChg( nDirIdx - 1 ) : 0;
1334*b1cdbd2cSJim Jagielski // nEnd is end of RTL run:
1335*b1cdbd2cSJim Jagielski const xub_StrLen nEnd = GetDirChg( nDirIdx );
1336*b1cdbd2cSJim Jagielski
1337*b1cdbd2cSJim Jagielski if ( nCurrDirType % 2 == UBIDI_RTL || // text in RTL run
1338*b1cdbd2cSJim Jagielski ( nCurrDirType > UBIDI_LTR && !lcl_HasStrongLTR( rTxt, nStart, nEnd ) ) ) // non-strong text in embedded LTR run
1339*b1cdbd2cSJim Jagielski {
1340*b1cdbd2cSJim Jagielski // nScriptIdx points into the ScriptArrays:
1341*b1cdbd2cSJim Jagielski size_t nScriptIdx = 0;
1342*b1cdbd2cSJim Jagielski
1343*b1cdbd2cSJim Jagielski // Skip entries in ScriptArray which are not inside the RTL run:
1344*b1cdbd2cSJim Jagielski // Make nScriptIdx become the index of the script group with
1345*b1cdbd2cSJim Jagielski // 1. nStartPosOfGroup <= nStart and
1346*b1cdbd2cSJim Jagielski // 2. nEndPosOfGroup > nStart
1347*b1cdbd2cSJim Jagielski while ( GetScriptChg( nScriptIdx ) <= nStart )
1348*b1cdbd2cSJim Jagielski ++nScriptIdx;
1349*b1cdbd2cSJim Jagielski
1350*b1cdbd2cSJim Jagielski const xub_StrLen nStartPosOfGroup = nScriptIdx ? GetScriptChg( nScriptIdx - 1 ) : 0;
1351*b1cdbd2cSJim Jagielski const sal_uInt8 nScriptTypeOfGroup = GetScriptType( nScriptIdx );
1352*b1cdbd2cSJim Jagielski
1353*b1cdbd2cSJim Jagielski ASSERT( nStartPosOfGroup <= nStart && GetScriptChg( nScriptIdx ) > nStart,
1354*b1cdbd2cSJim Jagielski "Script override with CTL font trouble" )
1355*b1cdbd2cSJim Jagielski
1356*b1cdbd2cSJim Jagielski // Check if we have to insert a new script change at
1357*b1cdbd2cSJim Jagielski // position nStart. If nStartPosOfGroup < nStart,
1358*b1cdbd2cSJim Jagielski // we have to insert a new script change:
1359*b1cdbd2cSJim Jagielski if ( nStart > 0 && nStartPosOfGroup < nStart )
1360*b1cdbd2cSJim Jagielski {
1361*b1cdbd2cSJim Jagielski aScriptChg.insert( aScriptChg.begin() + nScriptIdx, nStart );
1362*b1cdbd2cSJim Jagielski aScriptType.insert( aScriptType.begin() + nScriptIdx, nScriptTypeOfGroup );
1363*b1cdbd2cSJim Jagielski ++nScriptIdx;
1364*b1cdbd2cSJim Jagielski }
1365*b1cdbd2cSJim Jagielski
1366*b1cdbd2cSJim Jagielski // Remove entries in ScriptArray which end inside the RTL run:
1367*b1cdbd2cSJim Jagielski while ( nScriptIdx < aScriptChg.size() && GetScriptChg( nScriptIdx ) <= nEnd )
1368*b1cdbd2cSJim Jagielski {
1369*b1cdbd2cSJim Jagielski aScriptChg.erase( aScriptChg.begin() + nScriptIdx );
1370*b1cdbd2cSJim Jagielski aScriptType.erase( aScriptType.begin() + nScriptIdx );
1371*b1cdbd2cSJim Jagielski }
1372*b1cdbd2cSJim Jagielski
1373*b1cdbd2cSJim Jagielski // Insert a new entry in ScriptArray for the end of the RTL run:
1374*b1cdbd2cSJim Jagielski aScriptChg.insert( aScriptChg.begin() + nScriptIdx, nEnd );
1375*b1cdbd2cSJim Jagielski aScriptType.insert( aScriptType.begin() + nScriptIdx, i18n::ScriptType::COMPLEX );
1376*b1cdbd2cSJim Jagielski
1377*b1cdbd2cSJim Jagielski #if OSL_DEBUG_LEVEL > 1
1378*b1cdbd2cSJim Jagielski sal_uInt8 nScriptType;
1379*b1cdbd2cSJim Jagielski sal_uInt8 nLastScriptType = i18n::ScriptType::WEAK;
1380*b1cdbd2cSJim Jagielski xub_StrLen nScriptChg;
1381*b1cdbd2cSJim Jagielski xub_StrLen nLastScriptChg = 0;
1382*b1cdbd2cSJim Jagielski (void) nLastScriptChg;
1383*b1cdbd2cSJim Jagielski (void) nLastScriptType;
1384*b1cdbd2cSJim Jagielski
1385*b1cdbd2cSJim Jagielski for ( size_t i2 = 0; i2 < aScriptChg.size(); ++i2 )
1386*b1cdbd2cSJim Jagielski {
1387*b1cdbd2cSJim Jagielski nScriptChg = GetScriptChg( i2 );
1388*b1cdbd2cSJim Jagielski nScriptType = GetScriptType( i2 );
1389*b1cdbd2cSJim Jagielski ASSERT( nLastScriptType != nScriptType &&
1390*b1cdbd2cSJim Jagielski nLastScriptChg < nScriptChg,
1391*b1cdbd2cSJim Jagielski "Heavy InitScriptType() confusion" )
1392*b1cdbd2cSJim Jagielski }
1393*b1cdbd2cSJim Jagielski #endif
1394*b1cdbd2cSJim Jagielski }
1395*b1cdbd2cSJim Jagielski }
1396*b1cdbd2cSJim Jagielski }
1397*b1cdbd2cSJim Jagielski }
1398*b1cdbd2cSJim Jagielski
UpdateBidiInfo(const String & rTxt)1399*b1cdbd2cSJim Jagielski void SwScriptInfo::UpdateBidiInfo( const String& rTxt )
1400*b1cdbd2cSJim Jagielski {
1401*b1cdbd2cSJim Jagielski // remove invalid entries from direction information arrays
1402*b1cdbd2cSJim Jagielski aDirChg.clear();
1403*b1cdbd2cSJim Jagielski aDirType.clear();
1404*b1cdbd2cSJim Jagielski
1405*b1cdbd2cSJim Jagielski //
1406*b1cdbd2cSJim Jagielski // Bidi functions from icu 2.0
1407*b1cdbd2cSJim Jagielski //
1408*b1cdbd2cSJim Jagielski UErrorCode nError = U_ZERO_ERROR;
1409*b1cdbd2cSJim Jagielski UBiDi* pBidi = ubidi_openSized( rTxt.Len(), 0, &nError );
1410*b1cdbd2cSJim Jagielski nError = U_ZERO_ERROR;
1411*b1cdbd2cSJim Jagielski
1412*b1cdbd2cSJim Jagielski ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(rTxt.GetBuffer()), rTxt.Len(), // UChar != sal_Unicode in MinGW
1413*b1cdbd2cSJim Jagielski nDefaultDir, NULL, &nError );
1414*b1cdbd2cSJim Jagielski nError = U_ZERO_ERROR;
1415*b1cdbd2cSJim Jagielski long nCount = ubidi_countRuns( pBidi, &nError );
1416*b1cdbd2cSJim Jagielski int32_t nStart = 0;
1417*b1cdbd2cSJim Jagielski int32_t nEnd;
1418*b1cdbd2cSJim Jagielski UBiDiLevel nCurrDir;
1419*b1cdbd2cSJim Jagielski // counter for direction information arrays
1420*b1cdbd2cSJim Jagielski
1421*b1cdbd2cSJim Jagielski for ( sal_uInt16 nIdx = 0; nIdx < nCount; ++nIdx )
1422*b1cdbd2cSJim Jagielski {
1423*b1cdbd2cSJim Jagielski ubidi_getLogicalRun( pBidi, nStart, &nEnd, &nCurrDir );
1424*b1cdbd2cSJim Jagielski aDirChg.push_back( (sal_uInt16)nEnd );
1425*b1cdbd2cSJim Jagielski aDirType.push_back( (sal_uInt8)nCurrDir );
1426*b1cdbd2cSJim Jagielski nStart = nEnd;
1427*b1cdbd2cSJim Jagielski }
1428*b1cdbd2cSJim Jagielski
1429*b1cdbd2cSJim Jagielski ubidi_close( pBidi );
1430*b1cdbd2cSJim Jagielski }
1431*b1cdbd2cSJim Jagielski
1432*b1cdbd2cSJim Jagielski
1433*b1cdbd2cSJim Jagielski /*************************************************************************
1434*b1cdbd2cSJim Jagielski * SwScriptInfo::NextScriptChg(..)
1435*b1cdbd2cSJim Jagielski * returns the position of the next character which belongs to another script
1436*b1cdbd2cSJim Jagielski * than the character of the actual (input) position.
1437*b1cdbd2cSJim Jagielski * If there's no script change until the end of the paragraph, it will return
1438*b1cdbd2cSJim Jagielski * STRING_LEN.
1439*b1cdbd2cSJim Jagielski * Scripts are Asian (Chinese, Japanese, Korean),
1440*b1cdbd2cSJim Jagielski * Latin ( English etc.)
1441*b1cdbd2cSJim Jagielski * and Complex ( Hebrew, Arabian )
1442*b1cdbd2cSJim Jagielski *************************************************************************/
1443*b1cdbd2cSJim Jagielski
NextScriptChg(const xub_StrLen nPos) const1444*b1cdbd2cSJim Jagielski xub_StrLen SwScriptInfo::NextScriptChg( const xub_StrLen nPos ) const
1445*b1cdbd2cSJim Jagielski {
1446*b1cdbd2cSJim Jagielski sal_uInt16 nEnd = CountScriptChg();
1447*b1cdbd2cSJim Jagielski for( sal_uInt16 nX = 0; nX < nEnd; ++nX )
1448*b1cdbd2cSJim Jagielski {
1449*b1cdbd2cSJim Jagielski if( nPos < GetScriptChg( nX ) )
1450*b1cdbd2cSJim Jagielski return GetScriptChg( nX );
1451*b1cdbd2cSJim Jagielski }
1452*b1cdbd2cSJim Jagielski
1453*b1cdbd2cSJim Jagielski return STRING_LEN;
1454*b1cdbd2cSJim Jagielski }
1455*b1cdbd2cSJim Jagielski
1456*b1cdbd2cSJim Jagielski /*************************************************************************
1457*b1cdbd2cSJim Jagielski * SwScriptInfo::ScriptType(..)
1458*b1cdbd2cSJim Jagielski * returns the script of the character at the input position
1459*b1cdbd2cSJim Jagielski *************************************************************************/
1460*b1cdbd2cSJim Jagielski
ScriptType(const xub_StrLen nPos) const1461*b1cdbd2cSJim Jagielski sal_uInt8 SwScriptInfo::ScriptType( const xub_StrLen nPos ) const
1462*b1cdbd2cSJim Jagielski {
1463*b1cdbd2cSJim Jagielski sal_uInt16 nEnd = CountScriptChg();
1464*b1cdbd2cSJim Jagielski for( sal_uInt16 nX = 0; nX < nEnd; ++nX )
1465*b1cdbd2cSJim Jagielski {
1466*b1cdbd2cSJim Jagielski if( nPos < GetScriptChg( nX ) )
1467*b1cdbd2cSJim Jagielski return GetScriptType( nX );
1468*b1cdbd2cSJim Jagielski }
1469*b1cdbd2cSJim Jagielski
1470*b1cdbd2cSJim Jagielski // the default is the application language script
1471*b1cdbd2cSJim Jagielski return (sal_uInt8)GetI18NScriptTypeOfLanguage( (sal_uInt16)GetAppLanguage() );
1472*b1cdbd2cSJim Jagielski }
1473*b1cdbd2cSJim Jagielski
NextDirChg(const xub_StrLen nPos,const sal_uInt8 * pLevel) const1474*b1cdbd2cSJim Jagielski xub_StrLen SwScriptInfo::NextDirChg( const xub_StrLen nPos,
1475*b1cdbd2cSJim Jagielski const sal_uInt8* pLevel ) const
1476*b1cdbd2cSJim Jagielski {
1477*b1cdbd2cSJim Jagielski sal_uInt8 nCurrDir = pLevel ? *pLevel : 62;
1478*b1cdbd2cSJim Jagielski sal_uInt16 nEnd = CountDirChg();
1479*b1cdbd2cSJim Jagielski for( sal_uInt16 nX = 0; nX < nEnd; ++nX )
1480*b1cdbd2cSJim Jagielski {
1481*b1cdbd2cSJim Jagielski if( nPos < GetDirChg( nX ) &&
1482*b1cdbd2cSJim Jagielski ( nX + 1 == nEnd || GetDirType( nX + 1 ) <= nCurrDir ) )
1483*b1cdbd2cSJim Jagielski return GetDirChg( nX );
1484*b1cdbd2cSJim Jagielski }
1485*b1cdbd2cSJim Jagielski
1486*b1cdbd2cSJim Jagielski return STRING_LEN;
1487*b1cdbd2cSJim Jagielski }
1488*b1cdbd2cSJim Jagielski
DirType(const xub_StrLen nPos) const1489*b1cdbd2cSJim Jagielski sal_uInt8 SwScriptInfo::DirType( const xub_StrLen nPos ) const
1490*b1cdbd2cSJim Jagielski {
1491*b1cdbd2cSJim Jagielski sal_uInt16 nEnd = CountDirChg();
1492*b1cdbd2cSJim Jagielski for( sal_uInt16 nX = 0; nX < nEnd; ++nX )
1493*b1cdbd2cSJim Jagielski {
1494*b1cdbd2cSJim Jagielski if( nPos < GetDirChg( nX ) )
1495*b1cdbd2cSJim Jagielski return GetDirType( nX );
1496*b1cdbd2cSJim Jagielski }
1497*b1cdbd2cSJim Jagielski
1498*b1cdbd2cSJim Jagielski return 0;
1499*b1cdbd2cSJim Jagielski }
1500*b1cdbd2cSJim Jagielski
1501*b1cdbd2cSJim Jagielski /*************************************************************************
1502*b1cdbd2cSJim Jagielski * SwScriptInfo::MaskHiddenRanges(..)
1503*b1cdbd2cSJim Jagielski * Takes a string and replaced the hidden ranges with cChar.
1504*b1cdbd2cSJim Jagielski **************************************************************************/
1505*b1cdbd2cSJim Jagielski
MaskHiddenRanges(const SwTxtNode & rNode,XubString & rText,const xub_StrLen nStt,const xub_StrLen nEnd,const xub_Unicode cChar)1506*b1cdbd2cSJim Jagielski sal_uInt16 SwScriptInfo::MaskHiddenRanges( const SwTxtNode& rNode, XubString& rText,
1507*b1cdbd2cSJim Jagielski const xub_StrLen nStt, const xub_StrLen nEnd,
1508*b1cdbd2cSJim Jagielski const xub_Unicode cChar )
1509*b1cdbd2cSJim Jagielski {
1510*b1cdbd2cSJim Jagielski ASSERT( rNode.GetTxt().Len() == rText.Len(), "MaskHiddenRanges, string len mismatch" )
1511*b1cdbd2cSJim Jagielski
1512*b1cdbd2cSJim Jagielski PositionList aList;
1513*b1cdbd2cSJim Jagielski xub_StrLen nHiddenStart;
1514*b1cdbd2cSJim Jagielski xub_StrLen nHiddenEnd;
1515*b1cdbd2cSJim Jagielski sal_uInt16 nNumOfHiddenChars = 0;
1516*b1cdbd2cSJim Jagielski GetBoundsOfHiddenRange( rNode, 0, nHiddenStart, nHiddenEnd, &aList );
1517*b1cdbd2cSJim Jagielski PositionList::const_reverse_iterator rFirst( aList.end() );
1518*b1cdbd2cSJim Jagielski PositionList::const_reverse_iterator rLast( aList.begin() );
1519*b1cdbd2cSJim Jagielski while ( rFirst != rLast )
1520*b1cdbd2cSJim Jagielski {
1521*b1cdbd2cSJim Jagielski nHiddenEnd = *(rFirst++);
1522*b1cdbd2cSJim Jagielski nHiddenStart = *(rFirst++);
1523*b1cdbd2cSJim Jagielski
1524*b1cdbd2cSJim Jagielski if ( nHiddenEnd < nStt || nHiddenStart > nEnd )
1525*b1cdbd2cSJim Jagielski continue;
1526*b1cdbd2cSJim Jagielski
1527*b1cdbd2cSJim Jagielski while ( nHiddenStart < nHiddenEnd && nHiddenStart < nEnd )
1528*b1cdbd2cSJim Jagielski {
1529*b1cdbd2cSJim Jagielski if ( nHiddenStart >= nStt && nHiddenStart < nEnd )
1530*b1cdbd2cSJim Jagielski {
1531*b1cdbd2cSJim Jagielski rText.SetChar( nHiddenStart, cChar );
1532*b1cdbd2cSJim Jagielski ++nNumOfHiddenChars;
1533*b1cdbd2cSJim Jagielski }
1534*b1cdbd2cSJim Jagielski ++nHiddenStart;
1535*b1cdbd2cSJim Jagielski }
1536*b1cdbd2cSJim Jagielski }
1537*b1cdbd2cSJim Jagielski
1538*b1cdbd2cSJim Jagielski return nNumOfHiddenChars;
1539*b1cdbd2cSJim Jagielski }
1540*b1cdbd2cSJim Jagielski
1541*b1cdbd2cSJim Jagielski /*************************************************************************
1542*b1cdbd2cSJim Jagielski * SwScriptInfo::DeleteHiddenRanges(..)
1543*b1cdbd2cSJim Jagielski * Takes a SwTxtNode and deletes the hidden ranges from the node.
1544*b1cdbd2cSJim Jagielski **************************************************************************/
1545*b1cdbd2cSJim Jagielski
DeleteHiddenRanges(SwTxtNode & rNode)1546*b1cdbd2cSJim Jagielski void SwScriptInfo::DeleteHiddenRanges( SwTxtNode& rNode )
1547*b1cdbd2cSJim Jagielski {
1548*b1cdbd2cSJim Jagielski PositionList aList;
1549*b1cdbd2cSJim Jagielski xub_StrLen nHiddenStart;
1550*b1cdbd2cSJim Jagielski xub_StrLen nHiddenEnd;
1551*b1cdbd2cSJim Jagielski GetBoundsOfHiddenRange( rNode, 0, nHiddenStart, nHiddenEnd, &aList );
1552*b1cdbd2cSJim Jagielski PositionList::const_reverse_iterator rFirst( aList.end() );
1553*b1cdbd2cSJim Jagielski PositionList::const_reverse_iterator rLast( aList.begin() );
1554*b1cdbd2cSJim Jagielski while ( rFirst != rLast )
1555*b1cdbd2cSJim Jagielski {
1556*b1cdbd2cSJim Jagielski nHiddenEnd = *(rFirst++);
1557*b1cdbd2cSJim Jagielski nHiddenStart = *(rFirst++);
1558*b1cdbd2cSJim Jagielski
1559*b1cdbd2cSJim Jagielski SwPaM aPam( rNode, nHiddenStart, rNode, nHiddenEnd );
1560*b1cdbd2cSJim Jagielski rNode.getIDocumentContentOperations()->DeleteRange( aPam );
1561*b1cdbd2cSJim Jagielski }
1562*b1cdbd2cSJim Jagielski }
1563*b1cdbd2cSJim Jagielski
1564*b1cdbd2cSJim Jagielski /*************************************************************************
1565*b1cdbd2cSJim Jagielski * SwScriptInfo::GetBoundsOfHiddenRange(..)
1566*b1cdbd2cSJim Jagielski * static version
1567*b1cdbd2cSJim Jagielski **************************************************************************/
1568*b1cdbd2cSJim Jagielski
GetBoundsOfHiddenRange(const SwTxtNode & rNode,xub_StrLen nPos,xub_StrLen & rnStartPos,xub_StrLen & rnEndPos,PositionList * pList)1569*b1cdbd2cSJim Jagielski bool SwScriptInfo::GetBoundsOfHiddenRange( const SwTxtNode& rNode, xub_StrLen nPos,
1570*b1cdbd2cSJim Jagielski xub_StrLen& rnStartPos, xub_StrLen& rnEndPos,
1571*b1cdbd2cSJim Jagielski PositionList* pList )
1572*b1cdbd2cSJim Jagielski {
1573*b1cdbd2cSJim Jagielski rnStartPos = STRING_LEN;
1574*b1cdbd2cSJim Jagielski rnEndPos = 0;
1575*b1cdbd2cSJim Jagielski
1576*b1cdbd2cSJim Jagielski bool bNewContainsHiddenChars = false;
1577*b1cdbd2cSJim Jagielski
1578*b1cdbd2cSJim Jagielski //
1579*b1cdbd2cSJim Jagielski // Optimization: First examine the flags at the text node:
1580*b1cdbd2cSJim Jagielski //
1581*b1cdbd2cSJim Jagielski if ( !rNode.IsCalcHiddenCharFlags() )
1582*b1cdbd2cSJim Jagielski {
1583*b1cdbd2cSJim Jagielski bool bWholePara = rNode.HasHiddenCharAttribute( true );
1584*b1cdbd2cSJim Jagielski bool bContainsHiddenChars = rNode.HasHiddenCharAttribute( false );
1585*b1cdbd2cSJim Jagielski if ( !bContainsHiddenChars )
1586*b1cdbd2cSJim Jagielski return false;
1587*b1cdbd2cSJim Jagielski
1588*b1cdbd2cSJim Jagielski if ( bWholePara )
1589*b1cdbd2cSJim Jagielski {
1590*b1cdbd2cSJim Jagielski if ( pList )
1591*b1cdbd2cSJim Jagielski {
1592*b1cdbd2cSJim Jagielski pList->push_back( 0 );
1593*b1cdbd2cSJim Jagielski pList->push_back( rNode.GetTxt().Len() );
1594*b1cdbd2cSJim Jagielski }
1595*b1cdbd2cSJim Jagielski
1596*b1cdbd2cSJim Jagielski rnStartPos = 0;
1597*b1cdbd2cSJim Jagielski rnEndPos = rNode.GetTxt().Len();
1598*b1cdbd2cSJim Jagielski return true;
1599*b1cdbd2cSJim Jagielski }
1600*b1cdbd2cSJim Jagielski }
1601*b1cdbd2cSJim Jagielski
1602*b1cdbd2cSJim Jagielski const SwScriptInfo* pSI = SwScriptInfo::GetScriptInfo( rNode );
1603*b1cdbd2cSJim Jagielski if ( pSI )
1604*b1cdbd2cSJim Jagielski {
1605*b1cdbd2cSJim Jagielski //
1606*b1cdbd2cSJim Jagielski // Check first, if we have a valid SwScriptInfo object for this text node:
1607*b1cdbd2cSJim Jagielski //
1608*b1cdbd2cSJim Jagielski bNewContainsHiddenChars = pSI->GetBoundsOfHiddenRange( nPos, rnStartPos, rnEndPos, pList );
1609*b1cdbd2cSJim Jagielski const bool bNewHiddenCharsHidePara = ( rnStartPos == 0 && rnEndPos >= rNode.GetTxt().Len() );
1610*b1cdbd2cSJim Jagielski rNode.SetHiddenCharAttribute( bNewHiddenCharsHidePara, bNewContainsHiddenChars );
1611*b1cdbd2cSJim Jagielski }
1612*b1cdbd2cSJim Jagielski else
1613*b1cdbd2cSJim Jagielski {
1614*b1cdbd2cSJim Jagielski //
1615*b1cdbd2cSJim Jagielski // No valid SwScriptInfo Object, we have to do it the hard way:
1616*b1cdbd2cSJim Jagielski //
1617*b1cdbd2cSJim Jagielski Range aRange( 0, rNode.GetTxt().Len() ? rNode.GetTxt().Len() - 1 : 0 );
1618*b1cdbd2cSJim Jagielski MultiSelection aHiddenMulti( aRange );
1619*b1cdbd2cSJim Jagielski SwScriptInfo::CalcHiddenRanges( rNode, aHiddenMulti );
1620*b1cdbd2cSJim Jagielski for( sal_uInt16 i = 0; i < aHiddenMulti.GetRangeCount(); ++i )
1621*b1cdbd2cSJim Jagielski {
1622*b1cdbd2cSJim Jagielski const Range& rRange = aHiddenMulti.GetRange( i );
1623*b1cdbd2cSJim Jagielski const xub_StrLen nHiddenStart = (xub_StrLen)rRange.Min();
1624*b1cdbd2cSJim Jagielski const xub_StrLen nHiddenEnd = (xub_StrLen)rRange.Max() + 1;
1625*b1cdbd2cSJim Jagielski
1626*b1cdbd2cSJim Jagielski if ( nHiddenStart > nPos )
1627*b1cdbd2cSJim Jagielski break;
1628*b1cdbd2cSJim Jagielski else if ( nHiddenStart <= nPos && nPos < nHiddenEnd )
1629*b1cdbd2cSJim Jagielski {
1630*b1cdbd2cSJim Jagielski rnStartPos = nHiddenStart;
1631*b1cdbd2cSJim Jagielski rnEndPos = Min( nHiddenEnd, rNode.GetTxt().Len() );
1632*b1cdbd2cSJim Jagielski break;
1633*b1cdbd2cSJim Jagielski }
1634*b1cdbd2cSJim Jagielski }
1635*b1cdbd2cSJim Jagielski
1636*b1cdbd2cSJim Jagielski if ( pList )
1637*b1cdbd2cSJim Jagielski {
1638*b1cdbd2cSJim Jagielski for( sal_uInt16 i = 0; i < aHiddenMulti.GetRangeCount(); ++i )
1639*b1cdbd2cSJim Jagielski {
1640*b1cdbd2cSJim Jagielski const Range& rRange = aHiddenMulti.GetRange( i );
1641*b1cdbd2cSJim Jagielski pList->push_back( (xub_StrLen)rRange.Min() );
1642*b1cdbd2cSJim Jagielski pList->push_back( (xub_StrLen)rRange.Max() + 1 );
1643*b1cdbd2cSJim Jagielski }
1644*b1cdbd2cSJim Jagielski }
1645*b1cdbd2cSJim Jagielski
1646*b1cdbd2cSJim Jagielski bNewContainsHiddenChars = aHiddenMulti.GetRangeCount() > 0;
1647*b1cdbd2cSJim Jagielski }
1648*b1cdbd2cSJim Jagielski
1649*b1cdbd2cSJim Jagielski return bNewContainsHiddenChars;
1650*b1cdbd2cSJim Jagielski }
1651*b1cdbd2cSJim Jagielski
1652*b1cdbd2cSJim Jagielski /*************************************************************************
1653*b1cdbd2cSJim Jagielski * SwScriptInfo::GetBoundsOfHiddenRange(..)
1654*b1cdbd2cSJim Jagielski * non-static version
1655*b1cdbd2cSJim Jagielski **************************************************************************/
1656*b1cdbd2cSJim Jagielski
GetBoundsOfHiddenRange(xub_StrLen nPos,xub_StrLen & rnStartPos,xub_StrLen & rnEndPos,PositionList * pList) const1657*b1cdbd2cSJim Jagielski bool SwScriptInfo::GetBoundsOfHiddenRange( xub_StrLen nPos, xub_StrLen& rnStartPos,
1658*b1cdbd2cSJim Jagielski xub_StrLen& rnEndPos, PositionList* pList ) const
1659*b1cdbd2cSJim Jagielski {
1660*b1cdbd2cSJim Jagielski rnStartPos = STRING_LEN;
1661*b1cdbd2cSJim Jagielski rnEndPos = 0;
1662*b1cdbd2cSJim Jagielski
1663*b1cdbd2cSJim Jagielski sal_uInt16 nEnd = CountHiddenChg();
1664*b1cdbd2cSJim Jagielski for( sal_uInt16 nX = 0; nX < nEnd; ++nX )
1665*b1cdbd2cSJim Jagielski {
1666*b1cdbd2cSJim Jagielski const xub_StrLen nHiddenStart = GetHiddenChg( nX++ );
1667*b1cdbd2cSJim Jagielski const xub_StrLen nHiddenEnd = GetHiddenChg( nX );
1668*b1cdbd2cSJim Jagielski
1669*b1cdbd2cSJim Jagielski if ( nHiddenStart > nPos )
1670*b1cdbd2cSJim Jagielski break;
1671*b1cdbd2cSJim Jagielski else if ( nHiddenStart <= nPos && nPos < nHiddenEnd )
1672*b1cdbd2cSJim Jagielski {
1673*b1cdbd2cSJim Jagielski rnStartPos = nHiddenStart;
1674*b1cdbd2cSJim Jagielski rnEndPos = nHiddenEnd;
1675*b1cdbd2cSJim Jagielski break;
1676*b1cdbd2cSJim Jagielski }
1677*b1cdbd2cSJim Jagielski }
1678*b1cdbd2cSJim Jagielski
1679*b1cdbd2cSJim Jagielski if ( pList )
1680*b1cdbd2cSJim Jagielski {
1681*b1cdbd2cSJim Jagielski for( sal_uInt16 nX = 0; nX < nEnd; ++nX )
1682*b1cdbd2cSJim Jagielski {
1683*b1cdbd2cSJim Jagielski pList->push_back( GetHiddenChg( nX++ ) );
1684*b1cdbd2cSJim Jagielski pList->push_back( GetHiddenChg( nX ) );
1685*b1cdbd2cSJim Jagielski }
1686*b1cdbd2cSJim Jagielski }
1687*b1cdbd2cSJim Jagielski
1688*b1cdbd2cSJim Jagielski return CountHiddenChg() > 0;
1689*b1cdbd2cSJim Jagielski }
1690*b1cdbd2cSJim Jagielski
1691*b1cdbd2cSJim Jagielski /*************************************************************************
1692*b1cdbd2cSJim Jagielski * SwScriptInfo::IsInHiddenRange()
1693*b1cdbd2cSJim Jagielski **************************************************************************/
1694*b1cdbd2cSJim Jagielski
IsInHiddenRange(const SwTxtNode & rNode,xub_StrLen nPos)1695*b1cdbd2cSJim Jagielski bool SwScriptInfo::IsInHiddenRange( const SwTxtNode& rNode, xub_StrLen nPos )
1696*b1cdbd2cSJim Jagielski {
1697*b1cdbd2cSJim Jagielski xub_StrLen nStartPos;
1698*b1cdbd2cSJim Jagielski xub_StrLen nEndPos;
1699*b1cdbd2cSJim Jagielski SwScriptInfo::GetBoundsOfHiddenRange( rNode, nPos, nStartPos, nEndPos );
1700*b1cdbd2cSJim Jagielski return nStartPos != STRING_LEN;
1701*b1cdbd2cSJim Jagielski }
1702*b1cdbd2cSJim Jagielski
1703*b1cdbd2cSJim Jagielski
1704*b1cdbd2cSJim Jagielski #if OSL_DEBUG_LEVEL > 1
1705*b1cdbd2cSJim Jagielski /*************************************************************************
1706*b1cdbd2cSJim Jagielski * SwScriptInfo::CompType(..)
1707*b1cdbd2cSJim Jagielski * returns the type of the compressed character
1708*b1cdbd2cSJim Jagielski *************************************************************************/
1709*b1cdbd2cSJim Jagielski
CompType(const xub_StrLen nPos) const1710*b1cdbd2cSJim Jagielski sal_uInt8 SwScriptInfo::CompType( const xub_StrLen nPos ) const
1711*b1cdbd2cSJim Jagielski {
1712*b1cdbd2cSJim Jagielski sal_uInt16 nEnd = CountCompChg();
1713*b1cdbd2cSJim Jagielski for( sal_uInt16 nX = 0; nX < nEnd; ++nX )
1714*b1cdbd2cSJim Jagielski {
1715*b1cdbd2cSJim Jagielski xub_StrLen nChg = GetCompStart( nX );
1716*b1cdbd2cSJim Jagielski
1717*b1cdbd2cSJim Jagielski if ( nPos < nChg )
1718*b1cdbd2cSJim Jagielski return NONE;
1719*b1cdbd2cSJim Jagielski
1720*b1cdbd2cSJim Jagielski if( nPos < nChg + GetCompLen( nX ) )
1721*b1cdbd2cSJim Jagielski return GetCompType( nX );
1722*b1cdbd2cSJim Jagielski }
1723*b1cdbd2cSJim Jagielski return NONE;
1724*b1cdbd2cSJim Jagielski }
1725*b1cdbd2cSJim Jagielski #endif
1726*b1cdbd2cSJim Jagielski
1727*b1cdbd2cSJim Jagielski /*************************************************************************
1728*b1cdbd2cSJim Jagielski * SwScriptInfo::HasKana()
1729*b1cdbd2cSJim Jagielski * returns, if there are compressable kanas or specials
1730*b1cdbd2cSJim Jagielski * betwenn nStart and nEnd
1731*b1cdbd2cSJim Jagielski *************************************************************************/
1732*b1cdbd2cSJim Jagielski
HasKana(xub_StrLen nStart,const xub_StrLen nLen) const1733*b1cdbd2cSJim Jagielski sal_uInt16 SwScriptInfo::HasKana( xub_StrLen nStart, const xub_StrLen nLen ) const
1734*b1cdbd2cSJim Jagielski {
1735*b1cdbd2cSJim Jagielski sal_uInt16 nCnt = CountCompChg();
1736*b1cdbd2cSJim Jagielski xub_StrLen nEnd = nStart + nLen;
1737*b1cdbd2cSJim Jagielski
1738*b1cdbd2cSJim Jagielski for( sal_uInt16 nX = 0; nX < nCnt; ++nX )
1739*b1cdbd2cSJim Jagielski {
1740*b1cdbd2cSJim Jagielski xub_StrLen nKanaStart = GetCompStart( nX );
1741*b1cdbd2cSJim Jagielski xub_StrLen nKanaEnd = nKanaStart + GetCompLen( nX );
1742*b1cdbd2cSJim Jagielski
1743*b1cdbd2cSJim Jagielski if ( nKanaStart >= nEnd )
1744*b1cdbd2cSJim Jagielski return USHRT_MAX;
1745*b1cdbd2cSJim Jagielski
1746*b1cdbd2cSJim Jagielski if ( nStart < nKanaEnd )
1747*b1cdbd2cSJim Jagielski return nX;
1748*b1cdbd2cSJim Jagielski }
1749*b1cdbd2cSJim Jagielski
1750*b1cdbd2cSJim Jagielski return USHRT_MAX;
1751*b1cdbd2cSJim Jagielski }
1752*b1cdbd2cSJim Jagielski
1753*b1cdbd2cSJim Jagielski /*************************************************************************
1754*b1cdbd2cSJim Jagielski * SwScriptInfo::Compress()
1755*b1cdbd2cSJim Jagielski *************************************************************************/
1756*b1cdbd2cSJim Jagielski
Compress(sal_Int32 * pKernArray,xub_StrLen nIdx,xub_StrLen nLen,const sal_uInt16 nCompress,const sal_uInt16 nFontHeight,Point * pPoint) const1757*b1cdbd2cSJim Jagielski long SwScriptInfo::Compress( sal_Int32* pKernArray, xub_StrLen nIdx, xub_StrLen nLen,
1758*b1cdbd2cSJim Jagielski const sal_uInt16 nCompress, const sal_uInt16 nFontHeight,
1759*b1cdbd2cSJim Jagielski Point* pPoint ) const
1760*b1cdbd2cSJim Jagielski {
1761*b1cdbd2cSJim Jagielski ASSERT( nCompress, "Compression without compression?!" );
1762*b1cdbd2cSJim Jagielski ASSERT( nLen, "Compression without text?!" );
1763*b1cdbd2cSJim Jagielski sal_uInt16 nCompCount = CountCompChg();
1764*b1cdbd2cSJim Jagielski
1765*b1cdbd2cSJim Jagielski // In asian typography, there are full width and half width characters.
1766*b1cdbd2cSJim Jagielski // Full width punctuation characters can be compressed by 50 %
1767*b1cdbd2cSJim Jagielski // to determine this, we compare the font width with 75 % of its height
1768*b1cdbd2cSJim Jagielski sal_uInt16 nMinWidth = ( 3 * nFontHeight ) / 4;
1769*b1cdbd2cSJim Jagielski
1770*b1cdbd2cSJim Jagielski sal_uInt16 nCompIdx = HasKana( nIdx, nLen );
1771*b1cdbd2cSJim Jagielski
1772*b1cdbd2cSJim Jagielski if ( USHRT_MAX == nCompIdx )
1773*b1cdbd2cSJim Jagielski return 0;
1774*b1cdbd2cSJim Jagielski
1775*b1cdbd2cSJim Jagielski xub_StrLen nChg = GetCompStart( nCompIdx );
1776*b1cdbd2cSJim Jagielski xub_StrLen nCompLen = GetCompLen( nCompIdx );
1777*b1cdbd2cSJim Jagielski sal_uInt16 nI = 0;
1778*b1cdbd2cSJim Jagielski nLen = nLen + nIdx;
1779*b1cdbd2cSJim Jagielski
1780*b1cdbd2cSJim Jagielski if( nChg > nIdx )
1781*b1cdbd2cSJim Jagielski {
1782*b1cdbd2cSJim Jagielski nI = nChg - nIdx;
1783*b1cdbd2cSJim Jagielski nIdx = nChg;
1784*b1cdbd2cSJim Jagielski }
1785*b1cdbd2cSJim Jagielski else if( nIdx < nChg + nCompLen )
1786*b1cdbd2cSJim Jagielski nCompLen -= nIdx - nChg;
1787*b1cdbd2cSJim Jagielski
1788*b1cdbd2cSJim Jagielski if( nIdx > nLen || nCompIdx >= nCompCount )
1789*b1cdbd2cSJim Jagielski return 0;
1790*b1cdbd2cSJim Jagielski
1791*b1cdbd2cSJim Jagielski long nSub = 0;
1792*b1cdbd2cSJim Jagielski long nLast = nI ? pKernArray[ nI - 1 ] : 0;
1793*b1cdbd2cSJim Jagielski do
1794*b1cdbd2cSJim Jagielski {
1795*b1cdbd2cSJim Jagielski sal_uInt16 nType = GetCompType( nCompIdx );
1796*b1cdbd2cSJim Jagielski #if OSL_DEBUG_LEVEL > 1
1797*b1cdbd2cSJim Jagielski ASSERT( nType == CompType( nIdx ), "Gimme the right type!" );
1798*b1cdbd2cSJim Jagielski #endif
1799*b1cdbd2cSJim Jagielski nCompLen = nCompLen + nIdx;
1800*b1cdbd2cSJim Jagielski if( nCompLen > nLen )
1801*b1cdbd2cSJim Jagielski nCompLen = nLen;
1802*b1cdbd2cSJim Jagielski
1803*b1cdbd2cSJim Jagielski // are we allowed to compress the character?
1804*b1cdbd2cSJim Jagielski if ( pKernArray[ nI ] - nLast < nMinWidth )
1805*b1cdbd2cSJim Jagielski {
1806*b1cdbd2cSJim Jagielski nIdx++; nI++;
1807*b1cdbd2cSJim Jagielski }
1808*b1cdbd2cSJim Jagielski else
1809*b1cdbd2cSJim Jagielski {
1810*b1cdbd2cSJim Jagielski while( nIdx < nCompLen )
1811*b1cdbd2cSJim Jagielski {
1812*b1cdbd2cSJim Jagielski ASSERT( SwScriptInfo::NONE != nType, "None compression?!" );
1813*b1cdbd2cSJim Jagielski
1814*b1cdbd2cSJim Jagielski // nLast is width of current character
1815*b1cdbd2cSJim Jagielski nLast -= pKernArray[ nI ];
1816*b1cdbd2cSJim Jagielski
1817*b1cdbd2cSJim Jagielski nLast *= nCompress;
1818*b1cdbd2cSJim Jagielski long nMove = 0;
1819*b1cdbd2cSJim Jagielski if( SwScriptInfo::KANA != nType )
1820*b1cdbd2cSJim Jagielski {
1821*b1cdbd2cSJim Jagielski nLast /= 20000;
1822*b1cdbd2cSJim Jagielski if( pPoint && SwScriptInfo::SPECIAL_LEFT == nType )
1823*b1cdbd2cSJim Jagielski {
1824*b1cdbd2cSJim Jagielski if( nI )
1825*b1cdbd2cSJim Jagielski nMove = nLast;
1826*b1cdbd2cSJim Jagielski else
1827*b1cdbd2cSJim Jagielski {
1828*b1cdbd2cSJim Jagielski pPoint->X() += nLast;
1829*b1cdbd2cSJim Jagielski nLast = 0;
1830*b1cdbd2cSJim Jagielski }
1831*b1cdbd2cSJim Jagielski }
1832*b1cdbd2cSJim Jagielski }
1833*b1cdbd2cSJim Jagielski else
1834*b1cdbd2cSJim Jagielski nLast /= 100000;
1835*b1cdbd2cSJim Jagielski nSub -= nLast;
1836*b1cdbd2cSJim Jagielski nLast = pKernArray[ nI ];
1837*b1cdbd2cSJim Jagielski if( nMove )
1838*b1cdbd2cSJim Jagielski pKernArray[ nI - 1 ] += nMove;
1839*b1cdbd2cSJim Jagielski pKernArray[ nI++ ] -= nSub;
1840*b1cdbd2cSJim Jagielski ++nIdx;
1841*b1cdbd2cSJim Jagielski }
1842*b1cdbd2cSJim Jagielski }
1843*b1cdbd2cSJim Jagielski
1844*b1cdbd2cSJim Jagielski if( nIdx < nLen )
1845*b1cdbd2cSJim Jagielski {
1846*b1cdbd2cSJim Jagielski xub_StrLen nTmpChg;
1847*b1cdbd2cSJim Jagielski if( ++nCompIdx < nCompCount )
1848*b1cdbd2cSJim Jagielski {
1849*b1cdbd2cSJim Jagielski nTmpChg = GetCompStart( nCompIdx );
1850*b1cdbd2cSJim Jagielski if( nTmpChg > nLen )
1851*b1cdbd2cSJim Jagielski nTmpChg = nLen;
1852*b1cdbd2cSJim Jagielski nCompLen = GetCompLen( nCompIdx );
1853*b1cdbd2cSJim Jagielski }
1854*b1cdbd2cSJim Jagielski else
1855*b1cdbd2cSJim Jagielski nTmpChg = nLen;
1856*b1cdbd2cSJim Jagielski while( nIdx < nTmpChg )
1857*b1cdbd2cSJim Jagielski {
1858*b1cdbd2cSJim Jagielski nLast = pKernArray[ nI ];
1859*b1cdbd2cSJim Jagielski pKernArray[ nI++ ] -= nSub;
1860*b1cdbd2cSJim Jagielski ++nIdx;
1861*b1cdbd2cSJim Jagielski }
1862*b1cdbd2cSJim Jagielski }
1863*b1cdbd2cSJim Jagielski else
1864*b1cdbd2cSJim Jagielski break;
1865*b1cdbd2cSJim Jagielski } while( nIdx < nLen );
1866*b1cdbd2cSJim Jagielski return nSub;
1867*b1cdbd2cSJim Jagielski }
1868*b1cdbd2cSJim Jagielski
1869*b1cdbd2cSJim Jagielski /*************************************************************************
1870*b1cdbd2cSJim Jagielski * SwScriptInfo::KashidaJustify()
1871*b1cdbd2cSJim Jagielski *************************************************************************/
1872*b1cdbd2cSJim Jagielski
1873*b1cdbd2cSJim Jagielski // Note on calling KashidaJustify():
1874*b1cdbd2cSJim Jagielski // Kashida positions may be marked as invalid. Therefore KashidaJustify may return the clean
1875*b1cdbd2cSJim Jagielski // total number of kashida positions, or the number of kashida positions after some positions
1876*b1cdbd2cSJim Jagielski // have been dropped, depending on the state of the aKashidaInvalid array.
1877*b1cdbd2cSJim Jagielski
KashidaJustify(sal_Int32 * pKernArray,sal_Int32 * pScrArray,xub_StrLen nStt,xub_StrLen nLen,long nSpaceAdd) const1878*b1cdbd2cSJim Jagielski sal_uInt16 SwScriptInfo::KashidaJustify( sal_Int32* pKernArray,
1879*b1cdbd2cSJim Jagielski sal_Int32* pScrArray,
1880*b1cdbd2cSJim Jagielski xub_StrLen nStt,
1881*b1cdbd2cSJim Jagielski xub_StrLen nLen,
1882*b1cdbd2cSJim Jagielski long nSpaceAdd ) const
1883*b1cdbd2cSJim Jagielski {
1884*b1cdbd2cSJim Jagielski ASSERT( nLen, "Kashida justification without text?!" )
1885*b1cdbd2cSJim Jagielski
1886*b1cdbd2cSJim Jagielski if( !IsKashidaLine(nStt))
1887*b1cdbd2cSJim Jagielski return STRING_LEN;
1888*b1cdbd2cSJim Jagielski
1889*b1cdbd2cSJim Jagielski // evaluate kashida informatin in collected in SwScriptInfo
1890*b1cdbd2cSJim Jagielski
1891*b1cdbd2cSJim Jagielski sal_uInt16 nCntKash = 0;
1892*b1cdbd2cSJim Jagielski while( nCntKash < CountKashida() )
1893*b1cdbd2cSJim Jagielski {
1894*b1cdbd2cSJim Jagielski if ( nStt <= GetKashida( nCntKash ) )
1895*b1cdbd2cSJim Jagielski break;
1896*b1cdbd2cSJim Jagielski else
1897*b1cdbd2cSJim Jagielski nCntKash++;
1898*b1cdbd2cSJim Jagielski }
1899*b1cdbd2cSJim Jagielski
1900*b1cdbd2cSJim Jagielski const xub_StrLen nEnd = nStt + nLen;
1901*b1cdbd2cSJim Jagielski
1902*b1cdbd2cSJim Jagielski sal_uInt16 nCntKashEnd = nCntKash;
1903*b1cdbd2cSJim Jagielski while ( nCntKashEnd < CountKashida() )
1904*b1cdbd2cSJim Jagielski {
1905*b1cdbd2cSJim Jagielski if ( nEnd <= GetKashida( nCntKashEnd ) )
1906*b1cdbd2cSJim Jagielski break;
1907*b1cdbd2cSJim Jagielski else
1908*b1cdbd2cSJim Jagielski nCntKashEnd++;
1909*b1cdbd2cSJim Jagielski }
1910*b1cdbd2cSJim Jagielski
1911*b1cdbd2cSJim Jagielski sal_uInt16 nActualKashCount = nCntKashEnd - nCntKash;
1912*b1cdbd2cSJim Jagielski for ( sal_uInt16 i = nCntKash; i < nCntKashEnd; ++i )
1913*b1cdbd2cSJim Jagielski {
1914*b1cdbd2cSJim Jagielski if ( nActualKashCount && !IsKashidaValid ( i ) )
1915*b1cdbd2cSJim Jagielski --nActualKashCount;
1916*b1cdbd2cSJim Jagielski }
1917*b1cdbd2cSJim Jagielski
1918*b1cdbd2cSJim Jagielski if ( !pKernArray )
1919*b1cdbd2cSJim Jagielski return nActualKashCount;
1920*b1cdbd2cSJim Jagielski
1921*b1cdbd2cSJim Jagielski // do nothing if there is no more kashida
1922*b1cdbd2cSJim Jagielski if ( nCntKash < CountKashida() )
1923*b1cdbd2cSJim Jagielski {
1924*b1cdbd2cSJim Jagielski // skip any invalid kashidas
1925*b1cdbd2cSJim Jagielski while ( ! IsKashidaValid ( nCntKash ) && nCntKash < nCntKashEnd )
1926*b1cdbd2cSJim Jagielski ++nCntKash;
1927*b1cdbd2cSJim Jagielski
1928*b1cdbd2cSJim Jagielski xub_StrLen nKashidaPos = GetKashida( nCntKash );
1929*b1cdbd2cSJim Jagielski xub_StrLen nIdx = nKashidaPos;
1930*b1cdbd2cSJim Jagielski long nKashAdd = nSpaceAdd;
1931*b1cdbd2cSJim Jagielski
1932*b1cdbd2cSJim Jagielski while ( nIdx < nEnd )
1933*b1cdbd2cSJim Jagielski {
1934*b1cdbd2cSJim Jagielski sal_uInt16 nArrayPos = nIdx - nStt;
1935*b1cdbd2cSJim Jagielski
1936*b1cdbd2cSJim Jagielski // next kashida position
1937*b1cdbd2cSJim Jagielski ++nCntKash;
1938*b1cdbd2cSJim Jagielski while ( ! IsKashidaValid ( nCntKash ) && nCntKash < nCntKashEnd )
1939*b1cdbd2cSJim Jagielski ++nCntKash;
1940*b1cdbd2cSJim Jagielski
1941*b1cdbd2cSJim Jagielski nIdx = nCntKash < CountKashida() && IsKashidaValid ( nCntKash ) ? GetKashida( nCntKash ) : nEnd;
1942*b1cdbd2cSJim Jagielski if ( nIdx > nEnd )
1943*b1cdbd2cSJim Jagielski nIdx = nEnd;
1944*b1cdbd2cSJim Jagielski
1945*b1cdbd2cSJim Jagielski const sal_uInt16 nArrayEnd = nIdx - nStt;
1946*b1cdbd2cSJim Jagielski
1947*b1cdbd2cSJim Jagielski while ( nArrayPos < nArrayEnd )
1948*b1cdbd2cSJim Jagielski {
1949*b1cdbd2cSJim Jagielski pKernArray[ nArrayPos ] += nKashAdd;
1950*b1cdbd2cSJim Jagielski if ( pScrArray )
1951*b1cdbd2cSJim Jagielski pScrArray[ nArrayPos ] += nKashAdd;
1952*b1cdbd2cSJim Jagielski ++nArrayPos;
1953*b1cdbd2cSJim Jagielski }
1954*b1cdbd2cSJim Jagielski nKashAdd += nSpaceAdd;
1955*b1cdbd2cSJim Jagielski }
1956*b1cdbd2cSJim Jagielski }
1957*b1cdbd2cSJim Jagielski
1958*b1cdbd2cSJim Jagielski return 0;
1959*b1cdbd2cSJim Jagielski }
1960*b1cdbd2cSJim Jagielski
1961*b1cdbd2cSJim Jagielski /*************************************************************************
1962*b1cdbd2cSJim Jagielski * SwScriptInfo::IsArabicText()
1963*b1cdbd2cSJim Jagielski *
1964*b1cdbd2cSJim Jagielski * Checks if the current text is 'Arabic' text. Note that only the first
1965*b1cdbd2cSJim Jagielski * character has to be checked because a ctl portion only contains one
1966*b1cdbd2cSJim Jagielski * script, see NewTxtPortion
1967*b1cdbd2cSJim Jagielski *************************************************************************/
IsArabicText(const XubString & rTxt,xub_StrLen nStt,xub_StrLen nLen)1968*b1cdbd2cSJim Jagielski sal_Bool SwScriptInfo::IsArabicText( const XubString& rTxt, xub_StrLen nStt, xub_StrLen nLen )
1969*b1cdbd2cSJim Jagielski {
1970*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::i18n;
1971*b1cdbd2cSJim Jagielski static ScriptTypeList typeList[] = {
1972*b1cdbd2cSJim Jagielski { UnicodeScript_kArabic, UnicodeScript_kArabic, UnicodeScript_kArabic }, // 11,
1973*b1cdbd2cSJim Jagielski { UnicodeScript_kScriptCount, UnicodeScript_kScriptCount, UnicodeScript_kScriptCount } // 88
1974*b1cdbd2cSJim Jagielski };
1975*b1cdbd2cSJim Jagielski
1976*b1cdbd2cSJim Jagielski // go forward if current position does not hold a regular character:
1977*b1cdbd2cSJim Jagielski const CharClass& rCC = GetAppCharClass();
1978*b1cdbd2cSJim Jagielski sal_Int32 nIdx = nStt;
1979*b1cdbd2cSJim Jagielski const xub_StrLen nEnd = nStt + nLen;
1980*b1cdbd2cSJim Jagielski while ( nIdx < nEnd && !rCC.isLetterNumeric( rTxt, (xub_StrLen)nIdx ) )
1981*b1cdbd2cSJim Jagielski {
1982*b1cdbd2cSJim Jagielski ++nIdx;
1983*b1cdbd2cSJim Jagielski }
1984*b1cdbd2cSJim Jagielski
1985*b1cdbd2cSJim Jagielski if( nIdx == nEnd )
1986*b1cdbd2cSJim Jagielski {
1987*b1cdbd2cSJim Jagielski // no regular character found in this portion. Go backward:
1988*b1cdbd2cSJim Jagielski --nIdx;
1989*b1cdbd2cSJim Jagielski while ( nIdx >= 0 && !rCC.isLetterNumeric( rTxt, (xub_StrLen)nIdx ) )
1990*b1cdbd2cSJim Jagielski {
1991*b1cdbd2cSJim Jagielski --nIdx;
1992*b1cdbd2cSJim Jagielski }
1993*b1cdbd2cSJim Jagielski }
1994*b1cdbd2cSJim Jagielski
1995*b1cdbd2cSJim Jagielski if( nIdx >= 0 )
1996*b1cdbd2cSJim Jagielski {
1997*b1cdbd2cSJim Jagielski const xub_Unicode cCh = rTxt.GetChar( (xub_StrLen)nIdx );
1998*b1cdbd2cSJim Jagielski const sal_Int16 type = unicode::getUnicodeScriptType( cCh, typeList, UnicodeScript_kScriptCount );
1999*b1cdbd2cSJim Jagielski return type == UnicodeScript_kArabic;
2000*b1cdbd2cSJim Jagielski }
2001*b1cdbd2cSJim Jagielski return sal_False;
2002*b1cdbd2cSJim Jagielski }
2003*b1cdbd2cSJim Jagielski
2004*b1cdbd2cSJim Jagielski /*************************************************************************
2005*b1cdbd2cSJim Jagielski * SwScriptInfo::IsKashidaValid()
2006*b1cdbd2cSJim Jagielski *************************************************************************/
2007*b1cdbd2cSJim Jagielski
IsKashidaValid(xub_StrLen nKashPos) const2008*b1cdbd2cSJim Jagielski sal_Bool SwScriptInfo::IsKashidaValid ( xub_StrLen nKashPos ) const
2009*b1cdbd2cSJim Jagielski {
2010*b1cdbd2cSJim Jagielski for ( size_t i = 0; i < aKashidaInvalid.size(); ++i )
2011*b1cdbd2cSJim Jagielski {
2012*b1cdbd2cSJim Jagielski if ( aKashidaInvalid [ i ] == nKashPos )
2013*b1cdbd2cSJim Jagielski return false;
2014*b1cdbd2cSJim Jagielski }
2015*b1cdbd2cSJim Jagielski return true;
2016*b1cdbd2cSJim Jagielski }
2017*b1cdbd2cSJim Jagielski
2018*b1cdbd2cSJim Jagielski /*************************************************************************
2019*b1cdbd2cSJim Jagielski * SwScriptInfo::ClearKashidaInvalid()
2020*b1cdbd2cSJim Jagielski *************************************************************************/
2021*b1cdbd2cSJim Jagielski
ClearKashidaInvalid(xub_StrLen nKashPos)2022*b1cdbd2cSJim Jagielski void SwScriptInfo::ClearKashidaInvalid ( xub_StrLen nKashPos )
2023*b1cdbd2cSJim Jagielski {
2024*b1cdbd2cSJim Jagielski for ( size_t i = 0; i < aKashidaInvalid.size(); ++i )
2025*b1cdbd2cSJim Jagielski {
2026*b1cdbd2cSJim Jagielski if ( aKashidaInvalid [ i ] == nKashPos )
2027*b1cdbd2cSJim Jagielski {
2028*b1cdbd2cSJim Jagielski aKashidaInvalid.erase ( aKashidaInvalid.begin() + i );
2029*b1cdbd2cSJim Jagielski return;
2030*b1cdbd2cSJim Jagielski }
2031*b1cdbd2cSJim Jagielski }
2032*b1cdbd2cSJim Jagielski }
2033*b1cdbd2cSJim Jagielski
2034*b1cdbd2cSJim Jagielski /*************************************************************************
2035*b1cdbd2cSJim Jagielski * SwScriptInfo::MarkOrClearKashidaInvalid()
2036*b1cdbd2cSJim Jagielski *************************************************************************/
2037*b1cdbd2cSJim Jagielski // bMark == true:
2038*b1cdbd2cSJim Jagielski // marks the first valid kashida in the given text range as invalid
2039*b1cdbd2cSJim Jagielski
2040*b1cdbd2cSJim Jagielski // bMark == false:
2041*b1cdbd2cSJim Jagielski // clears all kashida invalid flags in the given text range
2042*b1cdbd2cSJim Jagielski
MarkOrClearKashidaInvalid(xub_StrLen nStt,xub_StrLen nLen,bool bMark,xub_StrLen nMarkCount)2043*b1cdbd2cSJim Jagielski bool SwScriptInfo::MarkOrClearKashidaInvalid ( xub_StrLen nStt, xub_StrLen nLen, bool bMark, xub_StrLen nMarkCount )
2044*b1cdbd2cSJim Jagielski {
2045*b1cdbd2cSJim Jagielski sal_uInt16 nCntKash = 0;
2046*b1cdbd2cSJim Jagielski while( nCntKash < CountKashida() )
2047*b1cdbd2cSJim Jagielski {
2048*b1cdbd2cSJim Jagielski if ( nStt <= GetKashida( nCntKash ) )
2049*b1cdbd2cSJim Jagielski break;
2050*b1cdbd2cSJim Jagielski else
2051*b1cdbd2cSJim Jagielski nCntKash++;
2052*b1cdbd2cSJim Jagielski }
2053*b1cdbd2cSJim Jagielski
2054*b1cdbd2cSJim Jagielski const xub_StrLen nEnd = nStt + nLen;
2055*b1cdbd2cSJim Jagielski
2056*b1cdbd2cSJim Jagielski while ( nCntKash < CountKashida() )
2057*b1cdbd2cSJim Jagielski {
2058*b1cdbd2cSJim Jagielski if ( nEnd <= GetKashida( nCntKash ) )
2059*b1cdbd2cSJim Jagielski break;
2060*b1cdbd2cSJim Jagielski else
2061*b1cdbd2cSJim Jagielski {
2062*b1cdbd2cSJim Jagielski if(bMark)
2063*b1cdbd2cSJim Jagielski {
2064*b1cdbd2cSJim Jagielski if ( IsKashidaValid ( nCntKash ) )
2065*b1cdbd2cSJim Jagielski {
2066*b1cdbd2cSJim Jagielski MarkKashidaInvalid ( nCntKash );
2067*b1cdbd2cSJim Jagielski --nMarkCount;
2068*b1cdbd2cSJim Jagielski if(!nMarkCount)
2069*b1cdbd2cSJim Jagielski return true;
2070*b1cdbd2cSJim Jagielski }
2071*b1cdbd2cSJim Jagielski }
2072*b1cdbd2cSJim Jagielski else
2073*b1cdbd2cSJim Jagielski {
2074*b1cdbd2cSJim Jagielski ClearKashidaInvalid ( nCntKash );
2075*b1cdbd2cSJim Jagielski }
2076*b1cdbd2cSJim Jagielski nCntKash++;
2077*b1cdbd2cSJim Jagielski }
2078*b1cdbd2cSJim Jagielski }
2079*b1cdbd2cSJim Jagielski return false;
2080*b1cdbd2cSJim Jagielski }
2081*b1cdbd2cSJim Jagielski
MarkKashidaInvalid(xub_StrLen nKashPos)2082*b1cdbd2cSJim Jagielski void SwScriptInfo::MarkKashidaInvalid ( xub_StrLen nKashPos )
2083*b1cdbd2cSJim Jagielski {
2084*b1cdbd2cSJim Jagielski aKashidaInvalid.push_back( nKashPos );
2085*b1cdbd2cSJim Jagielski }
2086*b1cdbd2cSJim Jagielski
2087*b1cdbd2cSJim Jagielski /*************************************************************************
2088*b1cdbd2cSJim Jagielski * SwScriptInfo::GetKashidaPositions()
2089*b1cdbd2cSJim Jagielski *************************************************************************/
2090*b1cdbd2cSJim Jagielski // retrieve the kashida positions in the given text range
GetKashidaPositions(xub_StrLen nStt,xub_StrLen nLen,xub_StrLen * pKashidaPosition)2091*b1cdbd2cSJim Jagielski sal_uInt16 SwScriptInfo::GetKashidaPositions ( xub_StrLen nStt, xub_StrLen nLen,
2092*b1cdbd2cSJim Jagielski xub_StrLen* pKashidaPosition )
2093*b1cdbd2cSJim Jagielski {
2094*b1cdbd2cSJim Jagielski sal_uInt16 nCntKash = 0;
2095*b1cdbd2cSJim Jagielski while( nCntKash < CountKashida() )
2096*b1cdbd2cSJim Jagielski {
2097*b1cdbd2cSJim Jagielski if ( nStt <= GetKashida( nCntKash ) )
2098*b1cdbd2cSJim Jagielski break;
2099*b1cdbd2cSJim Jagielski else
2100*b1cdbd2cSJim Jagielski nCntKash++;
2101*b1cdbd2cSJim Jagielski }
2102*b1cdbd2cSJim Jagielski
2103*b1cdbd2cSJim Jagielski const xub_StrLen nEnd = nStt + nLen;
2104*b1cdbd2cSJim Jagielski
2105*b1cdbd2cSJim Jagielski sal_uInt16 nCntKashEnd = nCntKash;
2106*b1cdbd2cSJim Jagielski while ( nCntKashEnd < CountKashida() )
2107*b1cdbd2cSJim Jagielski {
2108*b1cdbd2cSJim Jagielski if ( nEnd <= GetKashida( nCntKashEnd ) )
2109*b1cdbd2cSJim Jagielski break;
2110*b1cdbd2cSJim Jagielski else
2111*b1cdbd2cSJim Jagielski {
2112*b1cdbd2cSJim Jagielski pKashidaPosition [ nCntKashEnd - nCntKash ] = GetKashida ( nCntKashEnd );
2113*b1cdbd2cSJim Jagielski nCntKashEnd++;
2114*b1cdbd2cSJim Jagielski }
2115*b1cdbd2cSJim Jagielski }
2116*b1cdbd2cSJim Jagielski return nCntKashEnd - nCntKash;
2117*b1cdbd2cSJim Jagielski }
2118*b1cdbd2cSJim Jagielski
SetNoKashidaLine(xub_StrLen nStt,xub_StrLen nLen)2119*b1cdbd2cSJim Jagielski void SwScriptInfo::SetNoKashidaLine ( xub_StrLen nStt, xub_StrLen nLen )
2120*b1cdbd2cSJim Jagielski {
2121*b1cdbd2cSJim Jagielski aNoKashidaLine.push_back( nStt );
2122*b1cdbd2cSJim Jagielski aNoKashidaLineEnd.push_back( nStt+nLen );
2123*b1cdbd2cSJim Jagielski }
2124*b1cdbd2cSJim Jagielski
2125*b1cdbd2cSJim Jagielski /*************************************************************************
2126*b1cdbd2cSJim Jagielski * SwScriptInfo::IsKashidaLine()
2127*b1cdbd2cSJim Jagielski *************************************************************************/
2128*b1cdbd2cSJim Jagielski // determines if the line uses kashida justification
2129*b1cdbd2cSJim Jagielski
IsKashidaLine(xub_StrLen nCharIdx) const2130*b1cdbd2cSJim Jagielski bool SwScriptInfo::IsKashidaLine ( xub_StrLen nCharIdx ) const
2131*b1cdbd2cSJim Jagielski {
2132*b1cdbd2cSJim Jagielski for( size_t i = 0; i < aNoKashidaLine.size(); ++i )
2133*b1cdbd2cSJim Jagielski {
2134*b1cdbd2cSJim Jagielski if( nCharIdx >= aNoKashidaLine[ i ] && nCharIdx < aNoKashidaLineEnd[ i ])
2135*b1cdbd2cSJim Jagielski return false;
2136*b1cdbd2cSJim Jagielski }
2137*b1cdbd2cSJim Jagielski return true;
2138*b1cdbd2cSJim Jagielski }
2139*b1cdbd2cSJim Jagielski /*************************************************************************
2140*b1cdbd2cSJim Jagielski * SwScriptInfo::ClearKashidaLine()
2141*b1cdbd2cSJim Jagielski *************************************************************************/
2142*b1cdbd2cSJim Jagielski
ClearNoKashidaLine(xub_StrLen nStt,xub_StrLen nLen)2143*b1cdbd2cSJim Jagielski void SwScriptInfo::ClearNoKashidaLine ( xub_StrLen nStt, xub_StrLen nLen )
2144*b1cdbd2cSJim Jagielski {
2145*b1cdbd2cSJim Jagielski size_t i = 0;
2146*b1cdbd2cSJim Jagielski while( i < aNoKashidaLine.size())
2147*b1cdbd2cSJim Jagielski {
2148*b1cdbd2cSJim Jagielski if( nStt + nLen >= aNoKashidaLine[ i ] && nStt < aNoKashidaLineEnd [ i ] )
2149*b1cdbd2cSJim Jagielski {
2150*b1cdbd2cSJim Jagielski aNoKashidaLine.erase(aNoKashidaLine.begin() + i);
2151*b1cdbd2cSJim Jagielski aNoKashidaLineEnd.erase(aNoKashidaLineEnd.begin() + i);
2152*b1cdbd2cSJim Jagielski }
2153*b1cdbd2cSJim Jagielski else
2154*b1cdbd2cSJim Jagielski ++i;
2155*b1cdbd2cSJim Jagielski }
2156*b1cdbd2cSJim Jagielski }
2157*b1cdbd2cSJim Jagielski
2158*b1cdbd2cSJim Jagielski /*************************************************************************
2159*b1cdbd2cSJim Jagielski * SwScriptInfo::MarkKashidasInvalid()
2160*b1cdbd2cSJim Jagielski *************************************************************************/
2161*b1cdbd2cSJim Jagielski // mark the given character indices as invalid kashida positions
MarkKashidasInvalid(xub_StrLen nCnt,xub_StrLen * pKashidaPositions)2162*b1cdbd2cSJim Jagielski bool SwScriptInfo::MarkKashidasInvalid ( xub_StrLen nCnt, xub_StrLen* pKashidaPositions )
2163*b1cdbd2cSJim Jagielski {
2164*b1cdbd2cSJim Jagielski ASSERT( pKashidaPositions && nCnt > 0, "Where are kashidas?" )
2165*b1cdbd2cSJim Jagielski
2166*b1cdbd2cSJim Jagielski sal_uInt16 nCntKash = 0;
2167*b1cdbd2cSJim Jagielski xub_StrLen nKashidaPosIdx = 0;
2168*b1cdbd2cSJim Jagielski
2169*b1cdbd2cSJim Jagielski while ( nCntKash < CountKashida() && nKashidaPosIdx < nCnt )
2170*b1cdbd2cSJim Jagielski {
2171*b1cdbd2cSJim Jagielski if ( pKashidaPositions [nKashidaPosIdx] > GetKashida( nCntKash ) )
2172*b1cdbd2cSJim Jagielski {
2173*b1cdbd2cSJim Jagielski nCntKash++;
2174*b1cdbd2cSJim Jagielski continue;
2175*b1cdbd2cSJim Jagielski }
2176*b1cdbd2cSJim Jagielski
2177*b1cdbd2cSJim Jagielski if ( pKashidaPositions [nKashidaPosIdx] == GetKashida( nCntKash ) && IsKashidaValid ( nCntKash ) )
2178*b1cdbd2cSJim Jagielski {
2179*b1cdbd2cSJim Jagielski MarkKashidaInvalid ( nCntKash );
2180*b1cdbd2cSJim Jagielski }
2181*b1cdbd2cSJim Jagielski else
2182*b1cdbd2cSJim Jagielski return false; // something is wrong
2183*b1cdbd2cSJim Jagielski nKashidaPosIdx++;
2184*b1cdbd2cSJim Jagielski }
2185*b1cdbd2cSJim Jagielski return true;
2186*b1cdbd2cSJim Jagielski }
2187*b1cdbd2cSJim Jagielski
2188*b1cdbd2cSJim Jagielski /*************************************************************************
2189*b1cdbd2cSJim Jagielski * SwScriptInfo::ThaiJustify()
2190*b1cdbd2cSJim Jagielski *************************************************************************/
2191*b1cdbd2cSJim Jagielski
ThaiJustify(const XubString & rTxt,sal_Int32 * pKernArray,sal_Int32 * pScrArray,xub_StrLen nStt,xub_StrLen nLen,xub_StrLen nNumberOfBlanks,long nSpaceAdd)2192*b1cdbd2cSJim Jagielski sal_uInt16 SwScriptInfo::ThaiJustify( const XubString& rTxt, sal_Int32* pKernArray,
2193*b1cdbd2cSJim Jagielski sal_Int32* pScrArray, xub_StrLen nStt,
2194*b1cdbd2cSJim Jagielski xub_StrLen nLen, xub_StrLen nNumberOfBlanks,
2195*b1cdbd2cSJim Jagielski long nSpaceAdd )
2196*b1cdbd2cSJim Jagielski {
2197*b1cdbd2cSJim Jagielski ASSERT( nStt + nLen <= rTxt.Len(), "String in ThaiJustify too small" )
2198*b1cdbd2cSJim Jagielski
2199*b1cdbd2cSJim Jagielski SwTwips nNumOfTwipsToDistribute = nSpaceAdd * nNumberOfBlanks /
2200*b1cdbd2cSJim Jagielski SPACING_PRECISION_FACTOR;
2201*b1cdbd2cSJim Jagielski
2202*b1cdbd2cSJim Jagielski long nSpaceSum = 0;
2203*b1cdbd2cSJim Jagielski sal_uInt16 nCnt = 0;
2204*b1cdbd2cSJim Jagielski
2205*b1cdbd2cSJim Jagielski for ( sal_uInt16 nI = 0; nI < nLen; ++nI )
2206*b1cdbd2cSJim Jagielski {
2207*b1cdbd2cSJim Jagielski const xub_Unicode cCh = rTxt.GetChar( nStt + nI );
2208*b1cdbd2cSJim Jagielski
2209*b1cdbd2cSJim Jagielski // check if character is not above or below base
2210*b1cdbd2cSJim Jagielski if ( ( 0xE34 > cCh || cCh > 0xE3A ) &&
2211*b1cdbd2cSJim Jagielski ( 0xE47 > cCh || cCh > 0xE4E ) && cCh != 0xE31 )
2212*b1cdbd2cSJim Jagielski {
2213*b1cdbd2cSJim Jagielski if ( nNumberOfBlanks > 0 )
2214*b1cdbd2cSJim Jagielski {
2215*b1cdbd2cSJim Jagielski nSpaceAdd = nNumOfTwipsToDistribute / nNumberOfBlanks;
2216*b1cdbd2cSJim Jagielski --nNumberOfBlanks;
2217*b1cdbd2cSJim Jagielski nNumOfTwipsToDistribute -= nSpaceAdd;
2218*b1cdbd2cSJim Jagielski }
2219*b1cdbd2cSJim Jagielski nSpaceSum += nSpaceAdd;
2220*b1cdbd2cSJim Jagielski ++nCnt;
2221*b1cdbd2cSJim Jagielski }
2222*b1cdbd2cSJim Jagielski
2223*b1cdbd2cSJim Jagielski if ( pKernArray ) pKernArray[ nI ] += nSpaceSum;
2224*b1cdbd2cSJim Jagielski if ( pScrArray ) pScrArray[ nI ] += nSpaceSum;
2225*b1cdbd2cSJim Jagielski }
2226*b1cdbd2cSJim Jagielski
2227*b1cdbd2cSJim Jagielski return nCnt;
2228*b1cdbd2cSJim Jagielski }
2229*b1cdbd2cSJim Jagielski
2230*b1cdbd2cSJim Jagielski /*************************************************************************
2231*b1cdbd2cSJim Jagielski * SwScriptInfo::GetScriptInfo()
2232*b1cdbd2cSJim Jagielski *************************************************************************/
2233*b1cdbd2cSJim Jagielski
GetScriptInfo(const SwTxtNode & rTNd,sal_Bool bAllowInvalid)2234*b1cdbd2cSJim Jagielski SwScriptInfo* SwScriptInfo::GetScriptInfo( const SwTxtNode& rTNd,
2235*b1cdbd2cSJim Jagielski sal_Bool bAllowInvalid )
2236*b1cdbd2cSJim Jagielski {
2237*b1cdbd2cSJim Jagielski SwIterator<SwTxtFrm,SwTxtNode> aIter( rTNd );
2238*b1cdbd2cSJim Jagielski SwScriptInfo* pScriptInfo = 0;
2239*b1cdbd2cSJim Jagielski
2240*b1cdbd2cSJim Jagielski for( SwTxtFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() )
2241*b1cdbd2cSJim Jagielski {
2242*b1cdbd2cSJim Jagielski pScriptInfo = (SwScriptInfo*)pLast->GetScriptInfo();
2243*b1cdbd2cSJim Jagielski if ( pScriptInfo )
2244*b1cdbd2cSJim Jagielski {
2245*b1cdbd2cSJim Jagielski if ( !bAllowInvalid && STRING_LEN != pScriptInfo->GetInvalidity() )
2246*b1cdbd2cSJim Jagielski pScriptInfo = 0;
2247*b1cdbd2cSJim Jagielski else break;
2248*b1cdbd2cSJim Jagielski }
2249*b1cdbd2cSJim Jagielski }
2250*b1cdbd2cSJim Jagielski
2251*b1cdbd2cSJim Jagielski return pScriptInfo;
2252*b1cdbd2cSJim Jagielski }
2253*b1cdbd2cSJim Jagielski
2254*b1cdbd2cSJim Jagielski /*************************************************************************
2255*b1cdbd2cSJim Jagielski * SwParaPortion::SwParaPortion()
2256*b1cdbd2cSJim Jagielski *************************************************************************/
SwParaPortion()2257*b1cdbd2cSJim Jagielski SwParaPortion::SwParaPortion()
2258*b1cdbd2cSJim Jagielski {
2259*b1cdbd2cSJim Jagielski FormatReset();
2260*b1cdbd2cSJim Jagielski bFlys = bFtnNum = bMargin = sal_False;
2261*b1cdbd2cSJim Jagielski SetWhichPor( POR_PARA );
2262*b1cdbd2cSJim Jagielski }
2263*b1cdbd2cSJim Jagielski
2264*b1cdbd2cSJim Jagielski /*************************************************************************
2265*b1cdbd2cSJim Jagielski * SwParaPortion::~SwParaPortion()
2266*b1cdbd2cSJim Jagielski *************************************************************************/
~SwParaPortion()2267*b1cdbd2cSJim Jagielski SwParaPortion::~SwParaPortion()
2268*b1cdbd2cSJim Jagielski {
2269*b1cdbd2cSJim Jagielski }
2270*b1cdbd2cSJim Jagielski
2271*b1cdbd2cSJim Jagielski /*************************************************************************
2272*b1cdbd2cSJim Jagielski * SwParaPortion::GetParLen()
2273*b1cdbd2cSJim Jagielski *************************************************************************/
GetParLen() const2274*b1cdbd2cSJim Jagielski xub_StrLen SwParaPortion::GetParLen() const
2275*b1cdbd2cSJim Jagielski {
2276*b1cdbd2cSJim Jagielski xub_StrLen nLen = 0;
2277*b1cdbd2cSJim Jagielski const SwLineLayout *pLay = this;
2278*b1cdbd2cSJim Jagielski while( pLay )
2279*b1cdbd2cSJim Jagielski {
2280*b1cdbd2cSJim Jagielski DBG_LOOP;
2281*b1cdbd2cSJim Jagielski nLen = nLen + pLay->GetLen();
2282*b1cdbd2cSJim Jagielski pLay = pLay->GetNext();
2283*b1cdbd2cSJim Jagielski }
2284*b1cdbd2cSJim Jagielski return nLen;
2285*b1cdbd2cSJim Jagielski }
2286*b1cdbd2cSJim Jagielski
2287*b1cdbd2cSJim Jagielski /*************************************************************************
2288*b1cdbd2cSJim Jagielski * SwParaPortion::FindDropPortion()
2289*b1cdbd2cSJim Jagielski *************************************************************************/
2290*b1cdbd2cSJim Jagielski
FindDropPortion() const2291*b1cdbd2cSJim Jagielski const SwDropPortion *SwParaPortion::FindDropPortion() const
2292*b1cdbd2cSJim Jagielski {
2293*b1cdbd2cSJim Jagielski const SwLineLayout *pLay = this;
2294*b1cdbd2cSJim Jagielski while( pLay && pLay->IsDummy() )
2295*b1cdbd2cSJim Jagielski pLay = pLay->GetNext();
2296*b1cdbd2cSJim Jagielski while( pLay )
2297*b1cdbd2cSJim Jagielski {
2298*b1cdbd2cSJim Jagielski const SwLinePortion *pPos = pLay->GetPortion();
2299*b1cdbd2cSJim Jagielski while ( pPos && !pPos->GetLen() )
2300*b1cdbd2cSJim Jagielski pPos = pPos->GetPortion();
2301*b1cdbd2cSJim Jagielski if( pPos && pPos->IsDropPortion() )
2302*b1cdbd2cSJim Jagielski return (SwDropPortion *)pPos;
2303*b1cdbd2cSJim Jagielski pLay = pLay->GetLen() ? NULL : pLay->GetNext();
2304*b1cdbd2cSJim Jagielski }
2305*b1cdbd2cSJim Jagielski return NULL;
2306*b1cdbd2cSJim Jagielski }
2307*b1cdbd2cSJim Jagielski
2308*b1cdbd2cSJim Jagielski /*************************************************************************
2309*b1cdbd2cSJim Jagielski * SwLineLayout::Init()
2310*b1cdbd2cSJim Jagielski *************************************************************************/
2311*b1cdbd2cSJim Jagielski
Init(SwLinePortion * pNextPortion)2312*b1cdbd2cSJim Jagielski void SwLineLayout::Init( SwLinePortion* pNextPortion )
2313*b1cdbd2cSJim Jagielski {
2314*b1cdbd2cSJim Jagielski Height( 0 );
2315*b1cdbd2cSJim Jagielski Width( 0 );
2316*b1cdbd2cSJim Jagielski SetLen( 0 );
2317*b1cdbd2cSJim Jagielski SetAscent( 0 );
2318*b1cdbd2cSJim Jagielski SetRealHeight( 0 );
2319*b1cdbd2cSJim Jagielski SetPortion( pNextPortion );
2320*b1cdbd2cSJim Jagielski }
2321*b1cdbd2cSJim Jagielski
2322*b1cdbd2cSJim Jagielski /*-----------------16.11.00 11:04-------------------
2323*b1cdbd2cSJim Jagielski * HangingMargin()
2324*b1cdbd2cSJim Jagielski * looks for hanging punctuation portions in the paragraph
2325*b1cdbd2cSJim Jagielski * and return the maximum right offset of them.
2326*b1cdbd2cSJim Jagielski * If no such portion is found, the Margin/Hanging-flags will be atualized.
2327*b1cdbd2cSJim Jagielski * --------------------------------------------------*/
2328*b1cdbd2cSJim Jagielski
_GetHangingMargin() const2329*b1cdbd2cSJim Jagielski SwTwips SwLineLayout::_GetHangingMargin() const
2330*b1cdbd2cSJim Jagielski {
2331*b1cdbd2cSJim Jagielski SwLinePortion* pPor = GetPortion();
2332*b1cdbd2cSJim Jagielski sal_Bool bFound = sal_False;
2333*b1cdbd2cSJim Jagielski SwTwips nDiff = 0;
2334*b1cdbd2cSJim Jagielski while( pPor)
2335*b1cdbd2cSJim Jagielski {
2336*b1cdbd2cSJim Jagielski if( pPor->IsHangingPortion() )
2337*b1cdbd2cSJim Jagielski {
2338*b1cdbd2cSJim Jagielski nDiff = ((SwHangingPortion*)pPor)->GetInnerWidth() - pPor->Width();
2339*b1cdbd2cSJim Jagielski if( nDiff )
2340*b1cdbd2cSJim Jagielski bFound = sal_True;
2341*b1cdbd2cSJim Jagielski }
2342*b1cdbd2cSJim Jagielski // the last post its portion
2343*b1cdbd2cSJim Jagielski else if ( pPor->IsPostItsPortion() && ! pPor->GetPortion() )
2344*b1cdbd2cSJim Jagielski nDiff = nAscent;
2345*b1cdbd2cSJim Jagielski
2346*b1cdbd2cSJim Jagielski pPor = pPor->GetPortion();
2347*b1cdbd2cSJim Jagielski }
2348*b1cdbd2cSJim Jagielski if( !bFound ) // actualize the hanging-flag
2349*b1cdbd2cSJim Jagielski ((SwLineLayout*)this)->SetHanging( sal_False );
2350*b1cdbd2cSJim Jagielski return nDiff;
2351*b1cdbd2cSJim Jagielski }
2352*b1cdbd2cSJim Jagielski
HangingMargin() const2353*b1cdbd2cSJim Jagielski SwTwips SwTxtFrm::HangingMargin() const
2354*b1cdbd2cSJim Jagielski {
2355*b1cdbd2cSJim Jagielski ASSERT( HasPara(), "Don't call me without a paraportion" );
2356*b1cdbd2cSJim Jagielski if( !GetPara()->IsMargin() )
2357*b1cdbd2cSJim Jagielski return 0;
2358*b1cdbd2cSJim Jagielski const SwLineLayout* pLine = GetPara();
2359*b1cdbd2cSJim Jagielski SwTwips nRet = 0;
2360*b1cdbd2cSJim Jagielski do
2361*b1cdbd2cSJim Jagielski {
2362*b1cdbd2cSJim Jagielski SwTwips nDiff = pLine->GetHangingMargin();
2363*b1cdbd2cSJim Jagielski if( nDiff > nRet )
2364*b1cdbd2cSJim Jagielski nRet = nDiff;
2365*b1cdbd2cSJim Jagielski pLine = pLine->GetNext();
2366*b1cdbd2cSJim Jagielski } while ( pLine );
2367*b1cdbd2cSJim Jagielski if( !nRet ) // actualize the margin-flag
2368*b1cdbd2cSJim Jagielski ((SwParaPortion*)GetPara())->SetMargin( sal_False );
2369*b1cdbd2cSJim Jagielski return nRet;
2370*b1cdbd2cSJim Jagielski }
2371*b1cdbd2cSJim Jagielski
2372*b1cdbd2cSJim Jagielski
2373*b1cdbd2cSJim Jagielski /*************************************************************************
2374*b1cdbd2cSJim Jagielski * SwScriptInfo::CalcHiddenRanges()
2375*b1cdbd2cSJim Jagielski *
2376*b1cdbd2cSJim Jagielski * Returns a MultiSection indicating the hidden ranges.
2377*b1cdbd2cSJim Jagielski *************************************************************************/
2378*b1cdbd2cSJim Jagielski
CalcHiddenRanges(const SwTxtNode & rNode,MultiSelection & rHiddenMulti)2379*b1cdbd2cSJim Jagielski void SwScriptInfo::CalcHiddenRanges( const SwTxtNode& rNode, MultiSelection& rHiddenMulti )
2380*b1cdbd2cSJim Jagielski {
2381*b1cdbd2cSJim Jagielski const SfxPoolItem* pItem = 0;
2382*b1cdbd2cSJim Jagielski if( SFX_ITEM_SET == rNode.GetSwAttrSet().GetItemState( RES_CHRATR_HIDDEN, sal_True, &pItem ) &&
2383*b1cdbd2cSJim Jagielski ((SvxCharHiddenItem*)pItem)->GetValue() )
2384*b1cdbd2cSJim Jagielski {
2385*b1cdbd2cSJim Jagielski rHiddenMulti.SelectAll();
2386*b1cdbd2cSJim Jagielski }
2387*b1cdbd2cSJim Jagielski
2388*b1cdbd2cSJim Jagielski const SwpHints* pHints = rNode.GetpSwpHints();
2389*b1cdbd2cSJim Jagielski const SwTxtAttr* pTxtAttr = 0;
2390*b1cdbd2cSJim Jagielski
2391*b1cdbd2cSJim Jagielski if( pHints )
2392*b1cdbd2cSJim Jagielski {
2393*b1cdbd2cSJim Jagielski MSHORT nTmp = 0;
2394*b1cdbd2cSJim Jagielski
2395*b1cdbd2cSJim Jagielski while( nTmp < pHints->GetStartCount() )
2396*b1cdbd2cSJim Jagielski {
2397*b1cdbd2cSJim Jagielski pTxtAttr = pHints->GetStart( nTmp++ );
2398*b1cdbd2cSJim Jagielski const SvxCharHiddenItem* pHiddenItem = static_cast<const SvxCharHiddenItem*>( CharFmt::GetItem( *pTxtAttr, RES_CHRATR_HIDDEN ) );
2399*b1cdbd2cSJim Jagielski if( pHiddenItem )
2400*b1cdbd2cSJim Jagielski {
2401*b1cdbd2cSJim Jagielski const xub_StrLen nSt = *pTxtAttr->GetStart();
2402*b1cdbd2cSJim Jagielski const xub_StrLen nEnd = *pTxtAttr->End();
2403*b1cdbd2cSJim Jagielski if( nEnd > nSt )
2404*b1cdbd2cSJim Jagielski {
2405*b1cdbd2cSJim Jagielski Range aTmp( nSt, nEnd - 1 );
2406*b1cdbd2cSJim Jagielski rHiddenMulti.Select( aTmp, pHiddenItem->GetValue() );
2407*b1cdbd2cSJim Jagielski }
2408*b1cdbd2cSJim Jagielski }
2409*b1cdbd2cSJim Jagielski }
2410*b1cdbd2cSJim Jagielski }
2411*b1cdbd2cSJim Jagielski
2412*b1cdbd2cSJim Jagielski // If there are any hidden ranges in the current text node, we have
2413*b1cdbd2cSJim Jagielski // to unhide the redlining ranges:
2414*b1cdbd2cSJim Jagielski const IDocumentRedlineAccess& rIDRA = *rNode.getIDocumentRedlineAccess();
2415*b1cdbd2cSJim Jagielski if ( rHiddenMulti.GetRangeCount() && IDocumentRedlineAccess::IsShowChanges( rIDRA.GetRedlineMode() ) )
2416*b1cdbd2cSJim Jagielski {
2417*b1cdbd2cSJim Jagielski sal_uInt16 nAct = rIDRA.GetRedlinePos( rNode, USHRT_MAX );
2418*b1cdbd2cSJim Jagielski
2419*b1cdbd2cSJim Jagielski for ( ; nAct < rIDRA.GetRedlineTbl().Count(); nAct++ )
2420*b1cdbd2cSJim Jagielski {
2421*b1cdbd2cSJim Jagielski const SwRedline* pRed = rIDRA.GetRedlineTbl()[ nAct ];
2422*b1cdbd2cSJim Jagielski
2423*b1cdbd2cSJim Jagielski if ( pRed->Start()->nNode > rNode.GetIndex() )
2424*b1cdbd2cSJim Jagielski break;
2425*b1cdbd2cSJim Jagielski
2426*b1cdbd2cSJim Jagielski xub_StrLen nRedlStart;
2427*b1cdbd2cSJim Jagielski xub_StrLen nRedlnEnd;
2428*b1cdbd2cSJim Jagielski pRed->CalcStartEnd( rNode.GetIndex(), nRedlStart, nRedlnEnd );
2429*b1cdbd2cSJim Jagielski if ( nRedlnEnd > nRedlStart )
2430*b1cdbd2cSJim Jagielski {
2431*b1cdbd2cSJim Jagielski Range aTmp( nRedlStart, nRedlnEnd - 1 );
2432*b1cdbd2cSJim Jagielski rHiddenMulti.Select( aTmp, false );
2433*b1cdbd2cSJim Jagielski }
2434*b1cdbd2cSJim Jagielski }
2435*b1cdbd2cSJim Jagielski }
2436*b1cdbd2cSJim Jagielski
2437*b1cdbd2cSJim Jagielski //
2438*b1cdbd2cSJim Jagielski // We calculated a lot of stuff. Finally we can update the flags at the text node.
2439*b1cdbd2cSJim Jagielski //
2440*b1cdbd2cSJim Jagielski const bool bNewContainsHiddenChars = rHiddenMulti.GetRangeCount() > 0;
2441*b1cdbd2cSJim Jagielski bool bNewHiddenCharsHidePara = false;
2442*b1cdbd2cSJim Jagielski if ( bNewContainsHiddenChars )
2443*b1cdbd2cSJim Jagielski {
2444*b1cdbd2cSJim Jagielski const Range& rRange = rHiddenMulti.GetRange( 0 );
2445*b1cdbd2cSJim Jagielski const xub_StrLen nHiddenStart = (xub_StrLen)rRange.Min();
2446*b1cdbd2cSJim Jagielski const xub_StrLen nHiddenEnd = (xub_StrLen)rRange.Max() + 1;
2447*b1cdbd2cSJim Jagielski bNewHiddenCharsHidePara = ( nHiddenStart == 0 && nHiddenEnd >= rNode.GetTxt().Len() );
2448*b1cdbd2cSJim Jagielski }
2449*b1cdbd2cSJim Jagielski rNode.SetHiddenCharAttribute( bNewHiddenCharsHidePara, bNewContainsHiddenChars );
2450*b1cdbd2cSJim Jagielski }
2451*b1cdbd2cSJim Jagielski
2452