xref: /trunk/main/sw/source/core/edit/edattr.cxx (revision c0286415)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 
28 #include <hintids.hxx>
29 
30 #include <editeng/tstpitem.hxx>
31 #include <editeng/lrspitem.hxx>
32 #include <editeng/scripttypeitem.hxx>
33 #include <com/sun/star/i18n/ScriptType.hdl>
34 #include <txatbase.hxx>
35 #include <txtftn.hxx>
36 #include <fmtftn.hxx>
37 #include <editsh.hxx>
38 #include <edimp.hxx>	// fuer MACROS
39 #include <doc.hxx>
40 #include <swundo.hxx>	// fuer UNDO-Ids
41 #include <ndtxt.hxx>
42 #include <ftnidx.hxx>
43 #include <expfld.hxx>
44 #include <rootfrm.hxx>
45 #include <cntfrm.hxx>
46 #include <breakit.hxx>
47 #include <txtfld.hxx>
48 #include <fmtfld.hxx>
49 #include <crsskip.hxx>
50 #include <txtfrm.hxx>		// SwTxtFrm
51 #include <scriptinfo.hxx>
52 #include <svl/ctloptions.hxx>
53 #include <charfmt.hxx>  // #i27615#
54 #include <numrule.hxx>
55 
56 
57 /*************************************
58  * harte Formatierung (Attribute)
59  *************************************/
60 
61 // wenn Selektion groesser Max Nodes oder mehr als Max Selektionen
62 // => keine Attribute
63 const sal_uInt16& getMaxLookup()
64 {
65 	static const sal_uInt16 nMaxLookup = 1000;
66 	return nMaxLookup;
67 }
68 
69 // --> OD 2008-01-16 #newlistlevelattrs#
70 sal_Bool SwEditShell::GetCurAttr( SfxItemSet& rSet,
71                               const bool bMergeIndentValuesOfNumRule ) const
72 // <--
73 {
74 	if( GetCrsrCnt() > getMaxLookup() )
75 	{
76 		rSet.InvalidateAllItems();
77 		return sal_False;
78 	}
79 
80 	SfxItemSet aSet( *rSet.GetPool(), rSet.GetRanges() );
81 	SfxItemSet *pSet = &rSet;
82 
83 	FOREACHPAM_START(this)
84 
85         // #i27615# if the cursor is in front of the numbering label
86         // the attributes to get are those from the numbering format.
87         if (PCURCRSR->IsInFrontOfLabel())
88         {
89             SwTxtNode * pTxtNd =
90                 PCURCRSR->GetPoint()->nNode.GetNode().GetTxtNode();
91 
92             if (pTxtNd)
93             {
94                 SwNumRule * pNumRule = pTxtNd->GetNumRule();
95 
96                 if (pNumRule)
97                 {
98                     const String & aCharFmtName =
99                         pNumRule->Get(static_cast<sal_uInt16>(pTxtNd->GetActualListLevel())).GetCharFmtName();
100                     SwCharFmt * pCharFmt =
101                         GetDoc()->FindCharFmtByName(aCharFmtName);
102 
103                     if (pCharFmt)
104                         rSet.Put(pCharFmt->GetAttrSet());
105                 }
106             }
107 
108             continue;
109         }
110 
111 		sal_uLong nSttNd = PCURCRSR->GetMark()->nNode.GetIndex(),
112 			  nEndNd = PCURCRSR->GetPoint()->nNode.GetIndex();
113 		xub_StrLen nSttCnt = PCURCRSR->GetMark()->nContent.GetIndex(),
114 				   nEndCnt = PCURCRSR->GetPoint()->nContent.GetIndex();
115 
116 		if( nSttNd > nEndNd || ( nSttNd == nEndNd && nSttCnt > nEndCnt ))
117 		{
118 			sal_uLong nTmp = nSttNd; nSttNd = nEndNd; nEndNd = nTmp;
119 			nTmp = nSttCnt; nSttCnt = nEndCnt; nEndCnt = (xub_StrLen)nTmp;
120 		}
121 
122 		if( nEndNd - nSttNd >= getMaxLookup() )
123 		{
124 			rSet.ClearItem();
125 			rSet.InvalidateAllItems();
126 			return sal_False;
127 		}
128 
129 		// beim 1.Node traegt der Node die Werte in den GetSet ein (Initial)
130 		// alle weiteren Nodes werden zum GetSet zu gemergt
131 		for( sal_uLong n = nSttNd; n <= nEndNd; ++n )
132 		{
133 			SwNode* pNd = GetDoc()->GetNodes()[ n ];
134 			switch( pNd->GetNodeType() )
135 			{
136 			case ND_TEXTNODE:
137 				{
138 					xub_StrLen nStt = n == nSttNd ? nSttCnt : 0,
139 						   	   nEnd = n == nEndNd ? nEndCnt
140 										: ((SwTxtNode*)pNd)->GetTxt().Len();
141                     // --> OD 2008-01-16 #newlistlevelattrs#
142                     ((SwTxtNode*)pNd)->GetAttr( *pSet, nStt, nEnd,
143                                                 sal_False, sal_True,
144                                                 bMergeIndentValuesOfNumRule );
145                     // <--
146 				}
147 				break;
148 			case ND_GRFNODE:
149 			case ND_OLENODE:
150 				((SwCntntNode*)pNd)->GetAttr( *pSet );
151 				break;
152 
153 			default:
154 				pNd = 0;
155 			}
156 
157 			if( pNd )
158 			{
159 				if( pSet != &rSet )
160 					rSet.MergeValues( aSet );
161 
162 				if( aSet.Count() )
163 					aSet.ClearItem();
164 			}
165 			pSet = &aSet;
166 		}
167 
168 	FOREACHPAM_END()
169 
170 	return sal_True;
171 }
172 
173 SwTxtFmtColl* SwEditShell::GetCurTxtFmtColl() const
174 {
175 	SwTxtFmtColl *pFmt = 0;
176 
177 	if ( GetCrsrCnt() > getMaxLookup() )
178 		return 0;
179 
180 	FOREACHPAM_START(this)
181 
182 		sal_uLong nSttNd = PCURCRSR->GetMark()->nNode.GetIndex(),
183 			  nEndNd = PCURCRSR->GetPoint()->nNode.GetIndex();
184 		xub_StrLen nSttCnt = PCURCRSR->GetMark()->nContent.GetIndex(),
185 				   nEndCnt = PCURCRSR->GetPoint()->nContent.GetIndex();
186 
187 		if( nSttNd > nEndNd || ( nSttNd == nEndNd && nSttCnt > nEndCnt ))
188 		{
189 			sal_uLong nTmp = nSttNd; nSttNd = nEndNd; nEndNd = nTmp;
190 			nTmp = nSttCnt; nSttCnt = nEndCnt; nEndCnt = (xub_StrLen)nTmp;
191 		}
192 
193 		if( nEndNd - nSttNd >= getMaxLookup() )
194 		{
195 			pFmt = 0;
196 			break;
197 		}
198 
199 		for( sal_uLong n = nSttNd; n <= nEndNd; ++n )
200 		{
201 			SwNode* pNd = GetDoc()->GetNodes()[ n ];
202 			if( pNd->IsTxtNode() )
203 			{
204 				if( !pFmt )
205 					pFmt = ((SwTxtNode*)pNd)->GetTxtColl();
206 				else if( pFmt == ((SwTxtNode*)pNd)->GetTxtColl() ) // ???
207 					break;
208 			}
209 		}
210 
211 	FOREACHPAM_END()
212 	return pFmt;
213 }
214 
215 
216 
217 sal_Bool SwEditShell::GetCurFtn( SwFmtFtn* pFillFtn )
218 {
219 	// der Cursor muss auf dem akt. Fussnoten-Anker stehen:
220 	SwPaM* pCrsr = GetCrsr();
221 	SwTxtNode* pTxtNd = pCrsr->GetNode()->GetTxtNode();
222 	if( !pTxtNd )
223 		return sal_False;
224 
225     SwTxtAttr *const pFtn = pTxtNd->GetTxtAttrForCharAt(
226         pCrsr->GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN);
227 	if( pFtn && pFillFtn )
228 	{
229 		// Daten vom Attribut uebertragen
230 		const SwFmtFtn &rFtn = ((SwTxtFtn*)pFtn)->GetFtn();
231 		pFillFtn->SetNumber( rFtn );
232 		pFillFtn->SetEndNote( rFtn.IsEndNote() );
233 	}
234 	return 0 != pFtn;
235 }
236 
237 
238 bool SwEditShell::SetCurFtn( const SwFmtFtn& rFillFtn )
239 {
240     bool bChgd = false;
241 	StartAllAction();
242 
243 	SwPaM* pCrsr = GetCrsr(), *pFirst = pCrsr;
244 	do {
245 		bChgd |=  pDoc->SetCurFtn( *pCrsr, rFillFtn.GetNumStr(),
246 											rFillFtn.GetNumber(),
247 											rFillFtn.IsEndNote() );
248 
249 	} while( pFirst != ( pCrsr = (SwPaM*)pCrsr->GetNext() ));
250 
251 	EndAllAction();
252 	return bChgd;
253 }
254 
255 
256 
257 /*sal_uInt16 SwEditShell::GetFtnCnt( sal_Bool bEndNotes = sal_False ) const
258 {
259 	const SwFtnIdxs &rIdxs = pDoc->GetFtnIdxs();
260 	sal_uInt16 nCnt = 0;
261 	for ( sal_uInt16 i = 0; i < rIdxs.Count(); ++i )
262 	{
263 		const SwFmtFtn &rFtn = rIdxs[i]->GetFtn();
264 		if ( bEndNotes == rFtn.IsEndNote() )
265 			nCnt++;
266 	}
267 	return nCnt;
268 } */
269 
270 
271 bool SwEditShell::HasFtns( bool bEndNotes ) const
272 {
273 	const SwFtnIdxs &rIdxs = pDoc->GetFtnIdxs();
274 	for ( sal_uInt16 i = 0; i < rIdxs.Count(); ++i )
275 	{
276 		const SwFmtFtn &rFtn = rIdxs[i]->GetFtn();
277 		if ( bEndNotes == rFtn.IsEndNote() )
278 			return sal_True;
279 	}
280 	return sal_False;
281 }
282 
283 
284 	// gebe Liste aller Fussnoten und deren Anfangstexte
285 sal_uInt16 SwEditShell::GetSeqFtnList( SwSeqFldList& rList, bool bEndNotes )
286 {
287 	if( rList.Count() )
288 		rList.Remove( 0, rList.Count() );
289 
290 	sal_uInt16 n, nFtnCnt = pDoc->GetFtnIdxs().Count();
291 	SwTxtFtn* pTxtFtn;
292 	for( n = 0; n < nFtnCnt; ++n )
293 	{
294 		pTxtFtn = pDoc->GetFtnIdxs()[ n ];
295 		const SwFmtFtn& rFtn = pTxtFtn->GetFtn();
296 		if ( rFtn.IsEndNote() != bEndNotes )
297 			continue;
298 
299 		SwNodeIndex* pIdx = pTxtFtn->GetStartNode();
300 		if( pIdx )
301 		{
302 			SwNodeIndex aIdx( *pIdx, 1 );
303 			SwTxtNode* pTxtNd = aIdx.GetNode().GetTxtNode();
304 			if( !pTxtNd )
305 				pTxtNd = (SwTxtNode*)pDoc->GetNodes().GoNext( &aIdx );
306 
307 			if( pTxtNd )
308 			{
309 				String sTxt( rFtn.GetViewNumStr( *pDoc ));
310 				if( sTxt.Len() )
311 					sTxt += ' ';
312                 sTxt += pTxtNd->GetExpandTxt( 0, USHRT_MAX );
313 
314 				_SeqFldLstElem* pNew = new _SeqFldLstElem( sTxt,
315 											pTxtFtn->GetSeqRefNo() );
316 				while( rList.InsertSort( pNew ) )
317 					pNew->sDlgEntry += ' ';
318 			}
319 		}
320 	}
321 
322 	return rList.Count();
323 }
324 
325 
326 // linken Rand ueber Objectleiste einstellen (aenhlich dem Stufen von
327 // Numerierungen)
328 sal_Bool SwEditShell::IsMoveLeftMargin( sal_Bool bRight, sal_Bool bModulus ) const
329 {
330 	sal_Bool bRet = sal_True;
331 
332 	const SvxTabStopItem& rTabItem = (SvxTabStopItem&)GetDoc()->
333 								GetDefault( RES_PARATR_TABSTOP );
334 	sal_uInt16 nDefDist = static_cast<sal_uInt16>(rTabItem.Count() ? rTabItem[0].GetTabPos() : 1134);
335 	if( !nDefDist )
336 		return sal_False;
337 
338 	FOREACHPAM_START(this)
339 
340 		sal_uLong nSttNd = PCURCRSR->GetMark()->nNode.GetIndex(),
341 			  nEndNd = PCURCRSR->GetPoint()->nNode.GetIndex();
342 
343 		if( nSttNd > nEndNd )
344 		{
345 			sal_uLong nTmp = nSttNd; nSttNd = nEndNd; nEndNd = nTmp;
346 		}
347 
348 		SwCntntNode* pCNd;
349 		for( sal_uLong n = nSttNd; bRet && n <= nEndNd; ++n )
350 			if( 0 != ( pCNd = GetDoc()->GetNodes()[ n ]->GetTxtNode() ))
351 			{
352 				const SvxLRSpaceItem& rLS = (SvxLRSpaceItem&)
353 											pCNd->GetAttr( RES_LR_SPACE );
354 				if( bRight )
355 				{
356 					long nNext = rLS.GetTxtLeft() + nDefDist;
357 					if( bModulus )
358 						nNext = ( nNext / nDefDist ) * nDefDist;
359 					SwFrm* pFrm = pCNd->getLayoutFrm( GetLayout() );
360                     if ( pFrm )
361                     {
362                         const sal_uInt16 nFrmWidth = static_cast<sal_uInt16>( pFrm->IsVertical() ?
363                                                  pFrm->Frm().Height() :
364                                                  pFrm->Frm().Width() );
365                         bRet = nFrmWidth > ( nNext + MM50 );
366                     }
367                     else
368                         bRet = sal_False;
369 				}
370 			}
371 
372 		if( !bRet )
373 			break;
374 
375 	FOREACHPAM_END()
376 	return bRet;
377 }
378 
379 void SwEditShell::MoveLeftMargin( sal_Bool bRight, sal_Bool bModulus )
380 {
381 	StartAllAction();
382 	StartUndo( UNDO_START );
383 
384 	SwPaM* pCrsr = GetCrsr();
385 	if( pCrsr->GetNext() != pCrsr )			// Mehrfachselektion ?
386 	{
387 		SwPamRanges aRangeArr( *pCrsr );
388 		SwPaM aPam( *pCrsr->GetPoint() );
389 		for( sal_uInt16 n = 0; n < aRangeArr.Count(); ++n )
390 			GetDoc()->MoveLeftMargin( aRangeArr.SetPam( n, aPam ),
391 										bRight, bModulus );
392 	}
393 	else
394 		GetDoc()->MoveLeftMargin( *pCrsr, bRight, bModulus );
395 
396 	EndUndo( UNDO_END );
397 	EndAllAction();
398 }
399 
400 
401 inline sal_uInt16 lcl_SetScriptFlags( sal_uInt16 nType )
402 {
403 	sal_uInt16 nRet;
404    	switch( nType )
405 	{
406 	case ::com::sun::star::i18n::ScriptType::LATIN:		nRet = SCRIPTTYPE_LATIN;	break;
407 	case ::com::sun::star::i18n::ScriptType::ASIAN:		nRet = SCRIPTTYPE_ASIAN;	break;
408 	case ::com::sun::star::i18n::ScriptType::COMPLEX:	nRet = SCRIPTTYPE_COMPLEX;	break;
409 	default: nRet = 0;
410 	}
411 	return nRet;
412 }
413 
414 sal_Bool lcl_IsNoEndTxtAttrAtPos( const SwTxtNode& rTNd, xub_StrLen nPos,
415                             sal_uInt16 &rScrpt, sal_Bool bInSelection, sal_Bool bNum )
416 {
417 	sal_Bool bRet = sal_False;
418 	const String& rTxt = rTNd.GetTxt();
419     String sExp;
420 
421     // consider numbering
422     if ( bNum )
423     {
424         bRet = sal_False;
425 
426         // --> OD 2008-03-19 #refactorlists#
427         if ( rTNd.IsInList() )
428         {
429             ASSERT( rTNd.GetNumRule(),
430                     "<lcl_IsNoEndTxtAttrAtPos(..)> - no list style found at text node. Serious defect -> please inform OD." );
431             const SwNumRule* pNumRule = rTNd.GetNumRule();
432 			//Modified for i119959,2012.6.12
433 			//Under this scenario,this pointer is null,but on win,it doesn't crash immediately
434 			//it exits with exception,and associated memory will have problem which leads to crash problem in
435 			//other place in dev env...
436 			if ( pNumRule )
437 			{
438 			//End
439             const SwNumFmt &rNumFmt = pNumRule->Get( static_cast<sal_uInt16>(rTNd.GetActualListLevel()) );
440             if( SVX_NUM_BITMAP != rNumFmt.GetNumberingType() )
441             {
442                 if ( SVX_NUM_CHAR_SPECIAL == rNumFmt.GetNumberingType() )
443                     sExp = rNumFmt.GetBulletChar();
444                 else
445                     sExp = rTNd.GetNumString();
446 				}
447 			//Modified for i119959,2012.6.12
448 			//Under this scenario,this pointer is null,but on win,it doesn't crash immediately
449 			//it exits with exception,and associated memory will have problem which leads to crash problem in
450 			//other place in dev env...
451 			}
452 			//End
453         }
454     }
455 
456     // and fields
457     if ( CH_TXTATR_BREAKWORD == rTxt.GetChar( nPos ) )
458     {
459         const SwTxtAttr* const pAttr = rTNd.GetTxtAttrForCharAt( nPos );
460         if (pAttr)
461         {
462             bRet = sal_True; // all other than fields can be
463                          // defined as weak-script ?
464             if ( RES_TXTATR_FIELD == pAttr->Which() )
465             {
466                 const SwField* const pFld = pAttr->GetFmtFld().GetField();
467                 if (pFld)
468                 {
469                     sExp += pFld->ExpandField(true);
470                 }
471             }
472         }
473     }
474 
475     xub_StrLen nEnd = sExp.Len();
476     if ( nEnd )
477     {
478         xub_StrLen n;
479         if( bInSelection )
480         {
481             sal_uInt16 nScript;
482             for( n = 0; n < nEnd; n = (xub_StrLen)
483                     pBreakIt->GetBreakIter()->endOfScript( sExp, n, nScript ))
484             {
485                 nScript = pBreakIt->GetBreakIter()->getScriptType( sExp, n );
486                 rScrpt |= lcl_SetScriptFlags( nScript );
487             }
488         }
489         else
490             rScrpt |= lcl_SetScriptFlags( pBreakIt->GetBreakIter()->
491                                         getScriptType( sExp, nEnd-1 ));
492     }
493 
494 	return bRet;
495 }
496 
497 
498 // returns the scripttpye of the selection
499 sal_uInt16 SwEditShell::GetScriptType() const
500 {
501 	sal_uInt16 nRet = 0;
502 	//if( pBreakIt->GetBreakIter().is() )
503 	{
504 		FOREACHPAM_START(this)
505 
506 			const SwPosition *pStt = PCURCRSR->Start(),
507 							 *pEnd = pStt == PCURCRSR->GetMark()
508 									? PCURCRSR->GetPoint()
509 									: PCURCRSR->GetMark();
510 			if( pStt == pEnd || *pStt == *pEnd )
511 			{
512 				const SwTxtNode* pTNd = pStt->nNode.GetNode().GetTxtNode();
513 				if( pTNd )
514 				{
515                     // try to get SwScriptInfo
516                     const SwScriptInfo* pScriptInfo = SwScriptInfo::GetScriptInfo( *pTNd );
517 
518 					xub_StrLen nPos = pStt->nContent.GetIndex();
519 					//Task 90448: we need the scripttype of the previous
520 					//				position, if no selection exist!
521 					if( nPos )
522 					{
523 						SwIndex aIdx( pStt->nContent );
524 						if( pTNd->GoPrevious( &aIdx, CRSR_SKIP_CHARS ) )
525 							nPos = aIdx.GetIndex();
526 					}
527 
528                     sal_uInt16 nScript;
529 
530                     if ( pTNd->GetTxt().Len() )
531                     {
532                         nScript = pScriptInfo ?
533                                   pScriptInfo->ScriptType( nPos ) :
534                                   pBreakIt->GetBreakIter()->getScriptType( pTNd->GetTxt(), nPos );
535                     }
536                     else
537                         nScript = GetI18NScriptTypeOfLanguage( (sal_uInt16)GetAppLanguage() );
538 
539                     if( !lcl_IsNoEndTxtAttrAtPos( *pTNd, nPos, nRet, sal_False, sal_False ))
540                         nRet |= lcl_SetScriptFlags( nScript );
541 				}
542 			}
543 			else if ( pBreakIt->GetBreakIter().is() )
544 			{
545 				sal_uLong nEndIdx = pEnd->nNode.GetIndex();
546 				SwNodeIndex aIdx( pStt->nNode );
547 				for( ; aIdx.GetIndex() <= nEndIdx; aIdx++ )
548 					if( aIdx.GetNode().IsTxtNode() )
549 					{
550 						const SwTxtNode* pTNd = aIdx.GetNode().GetTxtNode();
551 						const String& rTxt = pTNd->GetTxt();
552 
553                         // try to get SwScriptInfo
554                         const SwScriptInfo* pScriptInfo = SwScriptInfo::GetScriptInfo( *pTNd );
555 
556 						xub_StrLen nChg = aIdx == pStt->nNode
557 												? pStt->nContent.GetIndex()
558 												: 0,
559 									nEndPos = aIdx == nEndIdx
560 												? pEnd->nContent.GetIndex()
561                                                 : rTxt.Len();
562 
563 						ASSERT( nEndPos <= rTxt.Len(), "Index outside the range - endless loop!" );
564 						if( nEndPos > rTxt.Len() )
565 							nEndPos = rTxt.Len();
566 
567 						sal_uInt16 nScript;
568 						while( nChg < nEndPos )
569 						{
570                             nScript = pScriptInfo ?
571                                       pScriptInfo->ScriptType( nChg ) :
572                                       pBreakIt->GetBreakIter()->getScriptType(
573 																rTxt, nChg );
574 
575                             if( !lcl_IsNoEndTxtAttrAtPos( *pTNd, nChg, nRet, sal_True,
576                                                           0 == nChg && rTxt.Len() == nEndPos ) )
577 								nRet |= lcl_SetScriptFlags( nScript );
578 
579 							if( (SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN |
580 								SCRIPTTYPE_COMPLEX) == nRet )
581 								break;
582 
583 							xub_StrLen nFldPos = nChg+1;
584 
585                             nChg = pScriptInfo ?
586                                    pScriptInfo->NextScriptChg( nChg ) :
587                                    (xub_StrLen)pBreakIt->GetBreakIter()->endOfScript(
588 													rTxt, nChg, nScript );
589 
590                             nFldPos = rTxt.Search(
591 											CH_TXTATR_BREAKWORD, nFldPos );
592 							if( nFldPos < nChg )
593 								nChg = nFldPos;
594 						}
595 						if( (SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN |
596 								SCRIPTTYPE_COMPLEX) == nRet )
597 							break;
598 					}
599 			}
600 			if( (SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN |
601 								SCRIPTTYPE_COMPLEX) == nRet )
602 				break;
603 
604 		FOREACHPAM_END()
605 	}
606 	if( !nRet )
607         nRet = SvtLanguageOptions::GetScriptTypeOfLanguage( LANGUAGE_SYSTEM );
608 	return nRet;
609 }
610 
611 
612 sal_uInt16 SwEditShell::GetCurLang() const
613 {
614 	const SwPaM* pCrsr = GetCrsr();
615 	const SwPosition& rPos = *pCrsr->GetPoint();
616 	const SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode();
617 	sal_uInt16 nLang;
618 	if( pTNd )
619 	{
620 		//JP 24.9.2001: if exist no selection, then get the language before
621 		//				the current character!
622 		xub_StrLen nPos = rPos.nContent.GetIndex();
623 		if( nPos && !pCrsr->HasMark() )
624 			--nPos;
625 		nLang = pTNd->GetLang( nPos );
626 	}
627 	else
628 		nLang = LANGUAGE_DONTKNOW;
629 	return nLang;
630 }
631 
632 sal_uInt16 SwEditShell::GetScalingOfSelectedText() const
633 {
634 	const SwPaM* pCrsr = GetCrsr();
635 	const SwPosition* pStt = pCrsr->Start();
636 	const SwTxtNode* pTNd = pStt->nNode.GetNode().GetTxtNode();
637 	ASSERT( pTNd, "no textnode available" );
638 
639 	sal_uInt16 nScaleWidth;
640 	if( pTNd )
641 	{
642 		xub_StrLen nStt = pStt->nContent.GetIndex(), nEnd;
643 		const SwPosition* pEnd = pStt == pCrsr->GetPoint()
644 										? pCrsr->GetMark()
645 										: pCrsr->GetPoint();
646 		if( pStt->nNode == pEnd->nNode )
647 			nEnd = pEnd->nContent.GetIndex();
648 		else
649 			nEnd = pTNd->GetTxt().Len();
650 		nScaleWidth = pTNd->GetScalingOfSelectedText( nStt, nEnd );
651 	}
652 	else
653 		nScaleWidth = 100;		        // default are no scaling -> 100%
654 	return nScaleWidth;
655 }
656