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