Update ooo320-m1
[ooovba.git] / svx / source / editeng / impedit4.cxx
blob9138cd1d5641d68c0d844c4b28efcc5aa8f252ac
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: impedit4.cxx,v $
10 * $Revision: 1.78.54.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 #include <eeng_pch.hxx>
36 #ifndef _MSGBOX_HXX //autogen
37 #include <vcl/msgbox.hxx>
38 #endif
39 #include <vcl/svapp.hxx>
41 #include <sfx2/srchitem.hxx>
42 #include <svx/lspcitem.hxx>
43 #include <svx/adjitem.hxx>
44 #include <svx/tstpitem.hxx>
46 #include <eertfpar.hxx>
47 #include <svx/editeng.hxx>
48 #include <impedit.hxx>
49 #include <svx/editview.hxx>
50 #include <eehtml.hxx>
51 #include <editobj2.hxx>
52 #include <i18npool/lang.h>
54 #include <editxml.hxx>
57 #include <svx/akrnitem.hxx>
58 #include <svx/cntritem.hxx>
59 #include <svx/colritem.hxx>
60 #include <svx/crsditem.hxx>
61 #include <svx/escpitem.hxx>
62 #include <svx/fhgtitem.hxx>
63 #include "fontitem.hxx"
64 #include <svx/kernitem.hxx>
65 #include <svx/lrspitem.hxx>
66 #include <svx/postitem.hxx>
67 #include <svx/shdditem.hxx>
68 #include <svx/udlnitem.hxx>
69 #include <svx/ulspitem.hxx>
70 #include <svx/wghtitem.hxx>
71 #include <svx/langitem.hxx>
72 #include <svx/charreliefitem.hxx>
73 #include <svx/frmdiritem.hxx>
74 #include <svx/emphitem.hxx>
75 #include <textconv.hxx>
77 #include <rtl/tencinfo.h>
79 #include <svtools/rtfout.hxx>
81 #ifndef SVX_LIGHT
82 #include <edtspell.hxx>
83 #endif
84 #include <svx/scripttypeitem.hxx>
85 #include <unolingu.hxx>
86 #include <sfx2/sfxuno.hxx>
87 #include <linguistic/lngprops.hxx>
88 #include <com/sun/star/linguistic2/XThesaurus.hpp>
89 #include <com/sun/star/linguistic2/XMeaning.hpp>
90 #include <com/sun/star/i18n/ScriptType.hpp>
91 #include <unotools/transliterationwrapper.hxx>
93 #ifndef _TXTCMP_HXX //autogen
94 #include <unotools/textsearch.hxx>
95 #endif
96 #include <comphelper/processfactory.hxx>
97 #include <vcl/help.hxx>
99 #include <svtools/rtfkeywd.hxx>
101 using namespace ::com::sun::star;
102 using namespace ::com::sun::star::uno;
103 using namespace ::com::sun::star::beans;
104 using namespace ::com::sun::star::linguistic2;
106 void SwapUSHORTs( sal_uInt16& rX, sal_uInt16& rY )
108 sal_uInt16 n = rX;
109 rX = rY;
110 rY = n;
113 EditPaM ImpEditEngine::Read( SvStream& rInput, const String& rBaseURL, EETextFormat eFormat, EditSelection aSel, SvKeyValueIterator* pHTTPHeaderAttrs )
115 sal_Bool _bUpdate = GetUpdateMode();
116 SetUpdateMode( sal_False );
117 EditPaM aPaM;
118 if ( eFormat == EE_FORMAT_TEXT )
119 aPaM = ReadText( rInput, aSel );
120 else if ( eFormat == EE_FORMAT_RTF )
121 aPaM = ReadRTF( rInput, aSel );
122 else if ( eFormat == EE_FORMAT_XML )
123 aPaM = ReadXML( rInput, aSel );
124 else if ( eFormat == EE_FORMAT_HTML )
125 aPaM = ReadHTML( rInput, rBaseURL, aSel, pHTTPHeaderAttrs );
126 else if ( eFormat == EE_FORMAT_BIN)
127 aPaM = ReadBin( rInput, aSel );
128 else
130 DBG_ERROR( "Read: Unbekanntes Format" );
133 FormatFullDoc(); // reicht vielleicht auch ein einfaches Format?
134 SetUpdateMode( _bUpdate );
136 return aPaM;
139 EditPaM ImpEditEngine::ReadText( SvStream& rInput, EditSelection aSel )
141 if ( aSel.HasRange() )
142 aSel = ImpDeleteSelection( aSel );
143 EditPaM aPaM = aSel.Max();
145 XubString aTmpStr, aStr;
146 sal_Bool bDone = rInput.ReadByteStringLine( aTmpStr );
147 while ( bDone )
149 aTmpStr.Erase( MAXCHARSINPARA );
150 aPaM = ImpInsertText( EditSelection( aPaM, aPaM ), aTmpStr );
151 aPaM = ImpInsertParaBreak( aPaM );
152 bDone = rInput.ReadByteStringLine( aTmpStr );
154 return aPaM;
157 EditPaM ImpEditEngine::ReadXML( SvStream& rInput, EditSelection aSel )
159 #ifndef SVX_LIGHT
160 if ( aSel.HasRange() )
161 aSel = ImpDeleteSelection( aSel );
163 ESelection aESel = CreateESel( aSel );
165 ::SvxReadXML( *GetEditEnginePtr(), rInput, aESel );
167 return aSel.Max();
168 #else
169 return EditPaM();
170 #endif
173 EditPaM ImpEditEngine::ReadRTF( SvStream& rInput, EditSelection aSel )
175 #ifndef SVX_LIGHT
177 #if defined (EDITDEBUG) && !defined( UNX )
178 SvFileStream aRTFOut( String( RTL_CONSTASCII_USTRINGPARAM ( "d:\\rtf_in.rtf" ) ), STREAM_WRITE );
179 aRTFOut << rInput;
180 aRTFOut.Close();
181 rInput.Seek( 0 );
182 #endif
183 if ( aSel.HasRange() )
184 aSel = ImpDeleteSelection( aSel );
186 // sal_Bool bCharsBeforeInsertPos = ( aSel.Min().GetIndex() ) ? sal_True : sal_False;
187 // sal_Bool bCharsBehindInsertPos = ( aSel.Min().GetIndex() < aSel.Min().GetNode()->Len() ) ? sal_True : sal_False;
189 // Der SvRTF-Parser erwartet, dass das Which-Mapping am uebergebenen Pool,
190 // nicht an einem Secondary haengt.
191 SfxItemPool* pPool = &aEditDoc.GetItemPool();
192 while ( pPool->GetSecondaryPool() && !pPool->GetName().EqualsAscii( "EditEngineItemPool" ) )
194 pPool = pPool->GetSecondaryPool();
197 DBG_ASSERT( pPool && pPool->GetName().EqualsAscii( "EditEngineItemPool" ), "ReadRTF: Kein EditEnginePool!" );
199 EditRTFParserRef xPrsr = new EditRTFParser( rInput, aSel, *pPool, this );
200 SvParserState eState = xPrsr->CallParser();
201 if ( ( eState != SVPAR_ACCEPTED ) && ( !rInput.GetError() ) )
203 rInput.SetError( EE_READWRITE_WRONGFORMAT );
204 return aSel.Min();
206 return xPrsr->GetCurPaM();
207 #else
208 return EditPaM();
209 #endif
212 EditPaM ImpEditEngine::ReadHTML( SvStream& rInput, const String& rBaseURL, EditSelection aSel, SvKeyValueIterator* pHTTPHeaderAttrs )
214 #ifndef SVX_LIGHT
216 if ( aSel.HasRange() )
217 aSel = ImpDeleteSelection( aSel );
219 // sal_Bool bCharsBeforeInsertPos = ( aSel.Min().GetIndex() ) ? sal_True : sal_False;
220 // sal_Bool bCharsBehindInsertPos = ( aSel.Min().GetIndex() < aSel.Min().GetNode()->Len() ) ? sal_True : sal_False;
222 EditHTMLParserRef xPrsr = new EditHTMLParser( rInput, rBaseURL, pHTTPHeaderAttrs );
223 SvParserState eState = xPrsr->CallParser( this, aSel.Max() );
224 if ( ( eState != SVPAR_ACCEPTED ) && ( !rInput.GetError() ) )
226 rInput.SetError( EE_READWRITE_WRONGFORMAT );
227 return aSel.Min();
229 return xPrsr->GetCurSelection().Max();
230 #else
231 return EditPaM();
232 #endif
235 EditPaM ImpEditEngine::ReadBin( SvStream& rInput, EditSelection aSel )
237 // Einfach ein temporaeres TextObject missbrauchen...
238 EditTextObject* pObj = EditTextObject::Create( rInput, NULL );
240 EditPaM aLastPaM = aSel.Max();
241 if ( pObj )
242 aLastPaM = InsertText( *pObj, aSel ).Max();
244 delete pObj;
245 return aLastPaM;
248 #ifndef SVX_LIGHT
249 void ImpEditEngine::Write( SvStream& rOutput, EETextFormat eFormat, EditSelection aSel )
251 if ( !rOutput.IsWritable() )
252 rOutput.SetError( SVSTREAM_WRITE_ERROR );
254 if ( !rOutput.GetError() )
256 if ( eFormat == EE_FORMAT_TEXT )
257 WriteText( rOutput, aSel );
258 else if ( eFormat == EE_FORMAT_RTF )
259 WriteRTF( rOutput, aSel );
260 else if ( eFormat == EE_FORMAT_XML )
261 WriteXML( rOutput, aSel );
262 else if ( eFormat == EE_FORMAT_HTML )
263 WriteHTML( rOutput, aSel );
264 else if ( eFormat == EE_FORMAT_BIN)
265 WriteBin( rOutput, aSel );
266 else
268 DBG_ERROR( "Write: Unbekanntes Format" );
272 #endif
274 sal_uInt32 ImpEditEngine::WriteText( SvStream& rOutput, EditSelection aSel )
276 sal_uInt16 nStartNode, nEndNode;
277 sal_Bool bRange = aSel.HasRange();
278 if ( bRange )
280 aSel.Adjust( aEditDoc );
281 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
282 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
284 else
286 nStartNode = 0;
287 nEndNode = aEditDoc.Count()-1;
290 // ueber die Absaetze iterieren...
291 for ( sal_uInt16 nNode = nStartNode; nNode <= nEndNode; nNode++ )
293 ContentNode* pNode = aEditDoc.GetObject( nNode );
294 DBG_ASSERT( pNode, "Node nicht gefunden: Search&Replace" );
296 sal_uInt16 nStartPos = 0;
297 sal_uInt16 nEndPos = pNode->Len();
298 if ( bRange )
300 if ( nNode == nStartNode )
301 nStartPos = aSel.Min().GetIndex();
302 if ( nNode == nEndNode ) // kann auch == nStart sein!
303 nEndPos = aSel.Max().GetIndex();
305 XubString aTmpStr = aEditDoc.GetParaAsString( pNode, nStartPos, nEndPos );
306 rOutput.WriteByteStringLine( aTmpStr );
309 return rOutput.GetError();
312 sal_Bool ImpEditEngine::WriteItemListAsRTF( ItemList& rLst, SvStream& rOutput, sal_uInt16 nPara, sal_uInt16 nPos,
313 SvxFontTable& rFontTable, SvxColorList& rColorList )
315 const SfxPoolItem* pAttrItem = rLst.First();
316 while ( pAttrItem )
318 WriteItemAsRTF( *pAttrItem, rOutput, nPara, nPos,rFontTable, rColorList );
319 pAttrItem = rLst.Next();
321 return ( rLst.Count() ? sal_True : sal_False );
324 void lcl_FindValidAttribs( ItemList& rLst, ContentNode* pNode, sal_uInt16 nIndex, USHORT nScriptType )
326 sal_uInt16 nAttr = 0;
327 EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
328 while ( pAttr && ( pAttr->GetStart() <= nIndex ) )
330 // Start wird in While ueberprueft...
331 if ( pAttr->GetEnd() > nIndex )
333 if ( IsScriptItemValid( pAttr->GetItem()->Which(), nScriptType ) )
334 rLst.Insert( pAttr->GetItem(), LIST_APPEND );
336 nAttr++;
337 pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
341 sal_uInt32 ImpEditEngine::WriteBin( SvStream& rOutput, EditSelection aSel, BOOL bStoreUnicodeStrings ) const
343 BinTextObject* pObj = (BinTextObject*)CreateBinTextObject( aSel, NULL );
344 pObj->StoreUnicodeStrings( bStoreUnicodeStrings );
345 pObj->Store( rOutput );
346 delete pObj;
347 return 0;
350 #ifndef SVX_LIGHT
351 sal_uInt32 ImpEditEngine::WriteXML( SvStream& rOutput, EditSelection aSel )
353 ESelection aESel = CreateESel( aSel );
355 SvxWriteXML( *GetEditEnginePtr(), rOutput, aESel );
357 return 0;
359 #endif
361 static sal_uInt16 getStylePos( const SfxStyles& rStyles, SfxStyleSheet* pSheet )
363 sal_uInt16 nNumber = 0;
364 SfxStyles::const_iterator iter( rStyles.begin() );
365 while( iter != rStyles.end() )
367 if( (*iter++).get() == pSheet )
368 return nNumber;
369 ++nNumber;
371 return 0;
374 sal_uInt32 ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel )
376 #ifndef SVX_LIGHT
377 DBG_ASSERT( GetUpdateMode(), "WriteRTF bei UpdateMode = sal_False!" );
378 CheckIdleFormatter();
379 if ( !IsFormatted() )
380 FormatDoc();
382 sal_uInt16 nStartNode, nEndNode;
383 aSel.Adjust( aEditDoc );
385 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
386 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
388 // RTF-Vorspann...
389 rOutput << '{' ;
391 rOutput << OOO_STRING_SVTOOLS_RTF_RTF;
393 rOutput << OOO_STRING_SVTOOLS_RTF_ANSI;
394 rtl_TextEncoding eDestEnc = RTL_TEXTENCODING_MS_1252;
396 // Fonttabelle erzeugen und rausschreiben...
397 SvxFontTable aFontTable;
398 // DefaultFont muss ganz vorne stehen, damit DEF-Font im RTF
399 aFontTable.Insert( 0, new SvxFontItem( (const SvxFontItem&)aEditDoc.GetItemPool().GetDefaultItem( EE_CHAR_FONTINFO ) ) );
400 aFontTable.Insert( 1, new SvxFontItem( (const SvxFontItem&)aEditDoc.GetItemPool().GetDefaultItem( EE_CHAR_FONTINFO_CJK ) ) );
401 aFontTable.Insert( 2, new SvxFontItem( (const SvxFontItem&)aEditDoc.GetItemPool().GetDefaultItem( EE_CHAR_FONTINFO_CTL ) ) );
402 for ( USHORT nScriptType = 0; nScriptType < 3; nScriptType++ )
404 USHORT nWhich = EE_CHAR_FONTINFO;
405 if ( nScriptType == 1 )
406 nWhich = EE_CHAR_FONTINFO_CJK;
407 else if ( nScriptType == 2 )
408 nWhich = EE_CHAR_FONTINFO_CTL;
410 sal_uInt16 i = 0;
411 SvxFontItem* pFontItem = (SvxFontItem*)aEditDoc.GetItemPool().GetItem( nWhich, i );
412 while ( pFontItem )
414 bool bAlreadyExist = false;
415 ULONG nTestMax = nScriptType ? aFontTable.Count() : 1;
416 for ( ULONG nTest = 0; !bAlreadyExist && ( nTest < nTestMax ); nTest++ )
418 bAlreadyExist = *aFontTable.Get( nTest ) == *pFontItem;
421 if ( !bAlreadyExist )
422 aFontTable.Insert( aFontTable.Count(), new SvxFontItem( *pFontItem ) );
424 pFontItem = (SvxFontItem*)aEditDoc.GetItemPool().GetItem( nWhich, ++i );
428 rOutput << endl << '{' << OOO_STRING_SVTOOLS_RTF_FONTTBL;
429 sal_uInt16 j;
430 for ( j = 0; j < aFontTable.Count(); j++ )
432 SvxFontItem* pFontItem = aFontTable.Get( j );
433 rOutput << '{';
434 rOutput << OOO_STRING_SVTOOLS_RTF_F;
435 rOutput.WriteNumber( j );
436 switch ( pFontItem->GetFamily() )
438 case FAMILY_DONTKNOW: rOutput << OOO_STRING_SVTOOLS_RTF_FNIL;
439 break;
440 case FAMILY_DECORATIVE: rOutput << OOO_STRING_SVTOOLS_RTF_FDECOR;
441 break;
442 case FAMILY_MODERN: rOutput << OOO_STRING_SVTOOLS_RTF_FMODERN;
443 break;
444 case FAMILY_ROMAN: rOutput << OOO_STRING_SVTOOLS_RTF_FROMAN;
445 break;
446 case FAMILY_SCRIPT: rOutput << OOO_STRING_SVTOOLS_RTF_FSCRIPT;
447 break;
448 case FAMILY_SWISS: rOutput << OOO_STRING_SVTOOLS_RTF_FSWISS;
449 break;
450 default:
451 break;
453 rOutput << OOO_STRING_SVTOOLS_RTF_FPRQ;
454 sal_uInt16 nVal = 0;
455 switch( pFontItem->GetPitch() )
457 case PITCH_FIXED: nVal = 1; break;
458 case PITCH_VARIABLE: nVal = 2; break;
459 default:
460 break;
462 rOutput.WriteNumber( nVal );
464 CharSet eChrSet = pFontItem->GetCharSet();
465 DBG_ASSERT( eChrSet != 9, "SystemCharSet?!" );
466 if( RTL_TEXTENCODING_DONTKNOW == eChrSet )
467 eChrSet = gsl_getSystemTextEncoding();
468 rOutput << OOO_STRING_SVTOOLS_RTF_FCHARSET;
469 rOutput.WriteNumber( rtl_getBestWindowsCharsetFromTextEncoding( eChrSet ) );
471 rOutput << ' ';
472 RTFOutFuncs::Out_String( rOutput, pFontItem->GetFamilyName(), eDestEnc );
473 rOutput << ";}";
475 rOutput << '}';
476 rOutput << endl;
478 // ColorList rausschreiben...
479 SvxColorList aColorList;
480 sal_uInt16 i = 0;
481 SvxColorItem* pColorItem = (SvxColorItem*)aEditDoc.GetItemPool().GetItem( EE_CHAR_COLOR, i );
482 while ( pColorItem )
484 USHORT nPos = i;
485 if ( pColorItem->GetValue() == COL_AUTO )
486 nPos = 0;
487 aColorList.Insert( new SvxColorItem( *pColorItem ), nPos );
488 pColorItem = (SvxColorItem*)aEditDoc.GetItemPool().GetItem( EE_CHAR_COLOR, ++i );
490 aColorList.Insert( new SvxColorItem( (const SvxColorItem&)aEditDoc.GetItemPool().GetDefaultItem( EE_CHAR_COLOR) ), (sal_uInt32)i );
492 rOutput << '{' << OOO_STRING_SVTOOLS_RTF_COLORTBL;
493 for ( j = 0; j < aColorList.Count(); j++ )
495 pColorItem = aColorList.GetObject( j );
496 if ( !j || ( pColorItem->GetValue() != COL_AUTO ) )
498 rOutput << OOO_STRING_SVTOOLS_RTF_RED;
499 rOutput.WriteNumber( pColorItem->GetValue().GetRed() );
500 rOutput << OOO_STRING_SVTOOLS_RTF_GREEN;
501 rOutput.WriteNumber( pColorItem->GetValue().GetGreen() );
502 rOutput << OOO_STRING_SVTOOLS_RTF_BLUE;
503 rOutput.WriteNumber( pColorItem->GetValue().GetBlue() );
505 rOutput << ';';
507 rOutput << '}';
508 rOutput << endl;
510 // StyleSheets...
511 if ( GetStyleSheetPool() )
513 sal_uInt16 nStyles = (sal_uInt16)GetStyleSheetPool()->GetStyles().size();
514 if ( nStyles )
516 rOutput << '{' << OOO_STRING_SVTOOLS_RTF_STYLESHEET;
518 for ( sal_uInt16 nStyle = 0; nStyle < nStyles; nStyle++ )
521 SfxStyleSheet* pStyle = (SfxStyleSheet*)GetStyleSheetPool()->GetStyles()[ nStyle ].get();
523 rOutput << endl << '{' << OOO_STRING_SVTOOLS_RTF_S;
524 sal_uInt16 nNumber = (sal_uInt16) (nStyle + 1);
525 rOutput.WriteNumber( nNumber );
527 // Attribute, auch aus Parent!
528 for ( sal_uInt16 nParAttr = EE_PARA_START; nParAttr <= EE_CHAR_END; nParAttr++ )
530 if ( pStyle->GetItemSet().GetItemState( nParAttr ) == SFX_ITEM_ON )
532 const SfxPoolItem& rItem = pStyle->GetItemSet().Get( nParAttr );
533 WriteItemAsRTF( rItem, rOutput, 0, 0, aFontTable, aColorList );
537 // Parent...(nur wenn noetig)
538 if ( pStyle->GetParent().Len() && ( pStyle->GetParent() != pStyle->GetName() ) )
540 SfxStyleSheet* pParent = (SfxStyleSheet*)GetStyleSheetPool()->Find( pStyle->GetParent(), pStyle->GetFamily() );
541 DBG_ASSERT( pParent, "Parent nicht gefunden!" );
542 rOutput << OOO_STRING_SVTOOLS_RTF_SBASEDON;
543 nNumber = (sal_uInt16) getStylePos( GetStyleSheetPool()->GetStyles(), pParent ) + 1;
544 rOutput.WriteNumber( nNumber );
547 // Folgevorlage...(immer)
548 SfxStyleSheet* pNext = pStyle;
549 if ( pStyle->GetFollow().Len() && ( pStyle->GetFollow() != pStyle->GetName() ) )
550 pNext = (SfxStyleSheet*)GetStyleSheetPool()->Find( pStyle->GetFollow(), pStyle->GetFamily() );
552 DBG_ASSERT( pNext, "Naechsten nicht gefunden!" );
553 rOutput << OOO_STRING_SVTOOLS_RTF_SNEXT;
554 nNumber = (sal_uInt16) getStylePos( GetStyleSheetPool()->GetStyles(), pNext ) + 1;
555 rOutput.WriteNumber( nNumber );
557 // Namen der Vorlage...
558 rOutput << " " << ByteString( pStyle->GetName(), eDestEnc ).GetBuffer();
559 rOutput << ";}";
561 rOutput << '}';
562 rOutput << endl;
566 // Die Pool-Defaults vorweg schreiben...
567 rOutput << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << "\\EditEnginePoolDefaults";
568 for ( sal_uInt16 nPoolDefItem = EE_PARA_START; nPoolDefItem <= EE_CHAR_END; nPoolDefItem++)
570 const SfxPoolItem& rItem = aEditDoc.GetItemPool().GetDefaultItem( nPoolDefItem );
571 WriteItemAsRTF( rItem, rOutput, 0, 0, aFontTable, aColorList );
573 rOutput << '}' << endl;
575 // Def-Hoehe vorweg, da sonst 12Pt
576 // Doch nicht, onst in jedem Absatz hart!
577 // SfxItemSet aTmpSet( GetEmptyItemSet() );
578 // const SvxFontHeightItem& rDefFontHeight = (const SvxFontHeightItem&)aTmpSet.Get( EE_CHAR_FONTHEIGHT );
579 // WriteItemAsRTF( rDefFontHeight, rOutput, aFontTable, aColorList );
580 // rOutput << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << "\\EditEnginePoolDefaultHeight}" << endl;
582 // DefTab:
583 MapMode aTwpMode( MAP_TWIP );
584 sal_uInt16 nDefTabTwps = (sal_uInt16) GetRefDevice()->LogicToLogic(
585 Point( aEditDoc.GetDefTab(), 0 ),
586 &GetRefMapMode(), &aTwpMode ).X();
587 rOutput << OOO_STRING_SVTOOLS_RTF_DEFTAB;
588 rOutput.WriteNumber( nDefTabTwps );
589 rOutput << endl;
591 // ueber die Absaetze iterieren...
592 rOutput << '{' << endl;
593 for ( sal_uInt16 nNode = nStartNode; nNode <= nEndNode; nNode++ )
595 ContentNode* pNode = aEditDoc.SaveGetObject( nNode );
596 DBG_ASSERT( pNode, "Node nicht gefunden: Search&Replace" );
598 // Die Absatzattribute vorweg...
599 sal_Bool bAttr = sal_False;
601 // Vorlage ?
602 if ( pNode->GetStyleSheet() )
604 // Nummer der Vorlage
605 rOutput << OOO_STRING_SVTOOLS_RTF_S;
606 sal_uInt16 nNumber = (sal_uInt16) getStylePos( GetStyleSheetPool()->GetStyles(), pNode->GetStyleSheet() ) + 1;
607 rOutput.WriteNumber( nNumber );
609 // Alle Attribute
610 // Attribute, auch aus Parent!
611 for ( sal_uInt16 nParAttr = EE_PARA_START; nParAttr <= EE_CHAR_END; nParAttr++ )
613 if ( pNode->GetStyleSheet()->GetItemSet().GetItemState( nParAttr ) == SFX_ITEM_ON )
615 const SfxPoolItem& rItem = pNode->GetStyleSheet()->GetItemSet().Get( nParAttr );
616 WriteItemAsRTF( rItem, rOutput, nNode, 0, aFontTable, aColorList );
617 bAttr = sal_True;
622 for ( sal_uInt16 nParAttr = EE_PARA_START; nParAttr <= EE_CHAR_END; nParAttr++ )
624 // const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItem( nParAttr );
625 // Jetzt, wo StyleSheet-Verarbeitung, nur noch harte Absatzattribute!
626 if ( pNode->GetContentAttribs().GetItems().GetItemState( nParAttr ) == SFX_ITEM_ON )
628 const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItems().Get( nParAttr );
629 WriteItemAsRTF( rItem, rOutput, nNode, 0, aFontTable, aColorList );
630 bAttr = sal_True;
633 if ( bAttr )
634 rOutput << ' '; // Separator
636 ItemList aAttribItems;
637 ParaPortion* pParaPortion = FindParaPortion( pNode );
638 DBG_ASSERT( pParaPortion, "Portion nicht gefunden: WriteRTF" );
640 sal_uInt16 nIndex = 0;
641 sal_uInt16 nStartPos = 0;
642 sal_uInt16 nEndPos = pNode->Len();
643 sal_uInt16 nStartPortion = 0;
644 sal_uInt16 nEndPortion = (sal_uInt16)pParaPortion->GetTextPortions().Count() - 1;
645 sal_Bool bFinishPortion = sal_False;
646 sal_uInt16 nPortionStart;
648 if ( nNode == nStartNode )
650 nStartPos = aSel.Min().GetIndex();
651 nStartPortion = pParaPortion->GetTextPortions().FindPortion( nStartPos, nPortionStart );
652 if ( nStartPos != 0 )
654 aAttribItems.Clear();
655 lcl_FindValidAttribs( aAttribItems, pNode, nStartPos, GetScriptType( EditPaM( pNode, 0 ) ) );
656 if ( aAttribItems.Count() )
658 // Diese Attribute duerfen nicht fuer den gesamten
659 // Absatz gelten:
660 rOutput << '{';
661 WriteItemListAsRTF( aAttribItems, rOutput, nNode, nStartPos, aFontTable, aColorList );
662 bFinishPortion = sal_True;
664 aAttribItems.Clear();
667 if ( nNode == nEndNode ) // kann auch == nStart sein!
669 nEndPos = aSel.Max().GetIndex();
670 nEndPortion = pParaPortion->GetTextPortions().FindPortion( nEndPos, nPortionStart );
673 EditCharAttrib* pNextFeature = pNode->GetCharAttribs().FindFeature( nIndex );
674 // Bei 0 anfangen, damit der Index richtig ist...
676 for ( sal_uInt16 n = 0; n <= nEndPortion; n++ )
678 TextPortion* pTextPortion = pParaPortion->GetTextPortions().GetObject(n);
679 if ( n < nStartPortion )
681 nIndex = nIndex + pTextPortion->GetLen();
682 continue;
685 if ( pNextFeature && ( pNextFeature->GetStart() == nIndex ) && ( pNextFeature->GetItem()->Which() != EE_FEATURE_FIELD ) )
687 WriteItemAsRTF( *pNextFeature->GetItem(), rOutput, nNode, nIndex, aFontTable, aColorList );
688 pNextFeature = pNode->GetCharAttribs().FindFeature( pNextFeature->GetStart() + 1 );
690 else
692 aAttribItems.Clear();
693 USHORT nScriptType = GetScriptType( EditPaM( pNode, nIndex+1 ) );
694 if ( !n || IsScriptChange( EditPaM( pNode, nIndex ) ) )
696 SfxItemSet aAttribs = GetAttribs( nNode, nIndex+1, nIndex+1 );
697 aAttribItems.Insert( &aAttribs.Get( GetScriptItemId( EE_CHAR_FONTINFO, nScriptType ) ), LIST_APPEND );
698 aAttribItems.Insert( &aAttribs.Get( GetScriptItemId( EE_CHAR_FONTHEIGHT, nScriptType ) ), LIST_APPEND );
699 aAttribItems.Insert( &aAttribs.Get( GetScriptItemId( EE_CHAR_WEIGHT, nScriptType ) ), LIST_APPEND );
700 aAttribItems.Insert( &aAttribs.Get( GetScriptItemId( EE_CHAR_ITALIC, nScriptType ) ), LIST_APPEND );
701 aAttribItems.Insert( &aAttribs.Get( GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType ) ), LIST_APPEND );
703 // #96298# Insert hard attribs AFTER CJK attribs...
704 lcl_FindValidAttribs( aAttribItems, pNode, nIndex, nScriptType );
706 rOutput << '{';
707 if ( WriteItemListAsRTF( aAttribItems, rOutput, nNode, nIndex, aFontTable, aColorList ) )
708 rOutput << ' ';
710 USHORT nS = nIndex;
711 USHORT nE = nIndex + pTextPortion->GetLen();
712 if ( n == nStartPortion )
713 nS = nStartPos;
714 if ( n == nEndPortion )
715 nE = nEndPos;
717 XubString aRTFStr = aEditDoc.GetParaAsString( pNode, nS, nE);
718 RTFOutFuncs::Out_String( rOutput, aRTFStr, eDestEnc );
719 rOutput << '}';
721 if ( bFinishPortion )
723 rOutput << '}';
724 bFinishPortion = sal_False;
727 nIndex = nIndex + pTextPortion->GetLen();
730 rOutput << OOO_STRING_SVTOOLS_RTF_PAR << OOO_STRING_SVTOOLS_RTF_PARD << OOO_STRING_SVTOOLS_RTF_PLAIN;;
731 rOutput << endl;
733 // RTF-Nachspann...
734 rOutput << "}}"; // 1xKlammerung Absaetze, 1x Klammerung RTF-Dokument
735 rOutput.Flush();
737 #if defined (EDITDEBUG) && !defined( UNX )
739 SvFileStream aStream( String( RTL_CONSTASCII_USTRINGPARAM ( "d:\\rtf_out.rtf" ) ), STREAM_WRITE|STREAM_TRUNC );
740 ULONG nP = rOutput.Tell();
741 rOutput.Seek( 0 );
742 aStream << rOutput;
743 rOutput.Seek( nP );
745 #endif
747 return rOutput.GetError();
748 #else
749 return 0;
750 #endif
754 void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, sal_uInt16 nPara, sal_uInt16 nPos,
755 SvxFontTable& rFontTable, SvxColorList& rColorList )
757 sal_uInt16 nWhich = rItem.Which();
758 switch ( nWhich )
760 case EE_PARA_WRITINGDIR:
762 const SvxFrameDirectionItem& rWritingMode = (const SvxFrameDirectionItem&)rItem;
763 if ( rWritingMode.GetValue() == FRMDIR_HORI_RIGHT_TOP )
764 rOutput << "\\rtlpar";
765 else
766 rOutput << "\\ltrpar";
768 break;
769 case EE_PARA_OUTLLEVEL:
771 sal_Int16 nLevel = ((const SfxInt16Item&)rItem).GetValue();
772 if( nLevel >= 0 )
774 rOutput << "\\level";
775 rOutput.WriteNumber( nLevel );
778 break;
779 case EE_PARA_OUTLLRSPACE:
780 case EE_PARA_LRSPACE:
782 // const ContentNode *pNode = aEditDoc.GetObject( nPara );
784 rOutput << OOO_STRING_SVTOOLS_RTF_FI;
785 short nTxtFirst = ((const SvxLRSpaceItem&)rItem).GetTxtFirstLineOfst();
786 nTxtFirst = (short)LogicToTwips( nTxtFirst );
787 rOutput.WriteNumber( nTxtFirst );
788 rOutput << OOO_STRING_SVTOOLS_RTF_LI;
789 sal_uInt16 nTxtLeft = static_cast< sal_uInt16 >(((const SvxLRSpaceItem&)rItem).GetTxtLeft());
790 nTxtLeft = (sal_uInt16)LogicToTwips( nTxtLeft );
791 rOutput.WriteNumber( nTxtLeft );
792 rOutput << OOO_STRING_SVTOOLS_RTF_RI;
793 sal_uInt32 nTxtRight = ((const SvxLRSpaceItem&)rItem).GetRight();
794 nTxtRight = LogicToTwips( nTxtRight);
795 rOutput.WriteNumber( nTxtRight );
797 break;
798 case EE_PARA_ULSPACE:
800 rOutput << OOO_STRING_SVTOOLS_RTF_SB;
801 sal_uInt16 nUpper = ((const SvxULSpaceItem&)rItem).GetUpper();
802 nUpper = (sal_uInt16)LogicToTwips( nUpper );
803 rOutput.WriteNumber( nUpper );
804 rOutput << OOO_STRING_SVTOOLS_RTF_SA;
805 sal_uInt16 nLower = ((const SvxULSpaceItem&)rItem).GetLower();
806 nLower = (sal_uInt16)LogicToTwips( nLower );
807 rOutput.WriteNumber( nLower );
809 break;
810 case EE_PARA_SBL:
812 rOutput << OOO_STRING_SVTOOLS_RTF_SL;
813 long nVal = ((const SvxLineSpacingItem&)rItem).GetLineHeight();
814 char cMult = '0';
815 if ( ((const SvxLineSpacingItem&)rItem).GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP )
817 // Woher kriege ich jetzt den Wert?
818 // Der SwRTF-Parser geht von einem 240er Font aus!
819 nVal = ((const SvxLineSpacingItem&)rItem).GetPropLineSpace();
820 nVal *= 240;
821 nVal /= 100;
822 cMult = '1';
824 rOutput.WriteNumber( nVal );
825 rOutput << OOO_STRING_SVTOOLS_RTF_SLMULT << cMult;
827 break;
828 case EE_PARA_JUST:
830 SvxAdjust eJustification = ((const SvxAdjustItem&)rItem).GetAdjust();
831 switch ( eJustification )
833 case SVX_ADJUST_CENTER: rOutput << OOO_STRING_SVTOOLS_RTF_QC;
834 break;
835 case SVX_ADJUST_RIGHT: rOutput << OOO_STRING_SVTOOLS_RTF_QR;
836 break;
837 default: rOutput << OOO_STRING_SVTOOLS_RTF_QL;
838 break;
841 break;
842 case EE_PARA_TABS:
844 const SvxTabStopItem& rTabs = (const SvxTabStopItem&) rItem;
845 for ( sal_uInt16 i = 0; i < rTabs.Count(); i++ )
847 const SvxTabStop& rTab = rTabs[i];
848 rOutput << OOO_STRING_SVTOOLS_RTF_TX;
849 rOutput.WriteNumber( LogicToTwips( rTab.GetTabPos() ) );
852 break;
853 case EE_CHAR_COLOR:
855 sal_uInt32 n = rColorList.GetId( (const SvxColorItem&)rItem );
856 rOutput << OOO_STRING_SVTOOLS_RTF_CF;
857 rOutput.WriteNumber( n );
859 break;
860 case EE_CHAR_FONTINFO:
861 case EE_CHAR_FONTINFO_CJK:
862 case EE_CHAR_FONTINFO_CTL:
864 sal_uInt32 n = rFontTable.GetId( (const SvxFontItem&)rItem );
865 rOutput << OOO_STRING_SVTOOLS_RTF_F;
866 rOutput.WriteNumber( n );
868 break;
869 case EE_CHAR_FONTHEIGHT:
870 case EE_CHAR_FONTHEIGHT_CJK:
871 case EE_CHAR_FONTHEIGHT_CTL:
873 rOutput << OOO_STRING_SVTOOLS_RTF_FS;
874 long nHeight = ((const SvxFontHeightItem&)rItem).GetHeight();
875 nHeight = LogicToTwips( nHeight );
876 // Twips => HalfPoints
877 nHeight /= 10;
878 rOutput.WriteNumber( nHeight );
880 break;
881 case EE_CHAR_WEIGHT:
882 case EE_CHAR_WEIGHT_CJK:
883 case EE_CHAR_WEIGHT_CTL:
885 FontWeight e = ((const SvxWeightItem&)rItem).GetWeight();
886 switch ( e )
888 case WEIGHT_BOLD: rOutput << OOO_STRING_SVTOOLS_RTF_B; break;
889 default: rOutput << OOO_STRING_SVTOOLS_RTF_B << '0'; break;
892 break;
893 case EE_CHAR_UNDERLINE:
895 // muesste bei WordLineMode ggf. ulw werden,
896 // aber die Information fehlt hier
897 FontUnderline e = ((const SvxUnderlineItem&)rItem).GetLineStyle();
898 switch ( e )
900 case UNDERLINE_NONE: rOutput << OOO_STRING_SVTOOLS_RTF_ULNONE; break;
901 case UNDERLINE_SINGLE: rOutput << OOO_STRING_SVTOOLS_RTF_UL; break;
902 case UNDERLINE_DOUBLE: rOutput << OOO_STRING_SVTOOLS_RTF_ULDB; break;
903 case UNDERLINE_DOTTED: rOutput << OOO_STRING_SVTOOLS_RTF_ULD; break;
904 default:
905 break;
908 break;
909 case EE_CHAR_OVERLINE:
911 FontUnderline e = ((const SvxOverlineItem&)rItem).GetLineStyle();
912 switch ( e )
914 case UNDERLINE_NONE: rOutput << OOO_STRING_SVTOOLS_RTF_OLNONE; break;
915 case UNDERLINE_SINGLE: rOutput << OOO_STRING_SVTOOLS_RTF_OL; break;
916 case UNDERLINE_DOUBLE: rOutput << OOO_STRING_SVTOOLS_RTF_OLDB; break;
917 case UNDERLINE_DOTTED: rOutput << OOO_STRING_SVTOOLS_RTF_OLD; break;
918 default:
919 break;
922 break;
923 case EE_CHAR_STRIKEOUT:
925 FontStrikeout e = ((const SvxCrossedOutItem&)rItem).GetStrikeout();
926 switch ( e )
928 case STRIKEOUT_SINGLE:
929 case STRIKEOUT_DOUBLE: rOutput << OOO_STRING_SVTOOLS_RTF_STRIKE; break;
930 case STRIKEOUT_NONE: rOutput << OOO_STRING_SVTOOLS_RTF_STRIKE << '0'; break;
931 default:
932 break;
935 break;
936 case EE_CHAR_ITALIC:
937 case EE_CHAR_ITALIC_CJK:
938 case EE_CHAR_ITALIC_CTL:
940 FontItalic e = ((const SvxPostureItem&)rItem).GetPosture();
941 switch ( e )
943 case ITALIC_OBLIQUE:
944 case ITALIC_NORMAL: rOutput << OOO_STRING_SVTOOLS_RTF_I; break;
945 case ITALIC_NONE: rOutput << OOO_STRING_SVTOOLS_RTF_I << '0'; break;
946 default:
947 break;
950 break;
951 case EE_CHAR_OUTLINE:
953 rOutput << OOO_STRING_SVTOOLS_RTF_OUTL;
954 if ( ((const SvxContourItem&)rItem).GetValue() == 0 )
955 rOutput << '0';
957 break;
958 case EE_CHAR_RELIEF:
960 USHORT nRelief = ((const SvxCharReliefItem&)rItem).GetValue();
961 if ( nRelief == RELIEF_EMBOSSED )
962 rOutput << OOO_STRING_SVTOOLS_RTF_EMBO;
963 if ( nRelief == RELIEF_ENGRAVED )
964 rOutput << OOO_STRING_SVTOOLS_RTF_IMPR;
966 break;
967 case EE_CHAR_EMPHASISMARK:
969 USHORT nMark = ((const SvxEmphasisMarkItem&)rItem).GetValue();
970 if ( nMark == EMPHASISMARK_NONE )
971 rOutput << OOO_STRING_SVTOOLS_RTF_ACCNONE;
972 else if ( nMark == EMPHASISMARK_SIDE_DOTS )
973 rOutput << OOO_STRING_SVTOOLS_RTF_ACCCOMMA;
974 else
975 rOutput << OOO_STRING_SVTOOLS_RTF_ACCDOT;
977 break;
978 case EE_CHAR_SHADOW:
980 rOutput << OOO_STRING_SVTOOLS_RTF_SHAD;
981 if ( ((const SvxShadowedItem&)rItem).GetValue() == 0 )
982 rOutput << '0';
984 break;
985 case EE_FEATURE_TAB:
987 rOutput << OOO_STRING_SVTOOLS_RTF_TAB;
989 break;
990 case EE_FEATURE_LINEBR:
992 rOutput << OOO_STRING_SVTOOLS_RTF_SL;
994 break;
995 case EE_CHAR_KERNING:
997 rOutput << OOO_STRING_SVTOOLS_RTF_EXPNDTW;
998 rOutput.WriteNumber( LogicToTwips(
999 ((const SvxKerningItem&)rItem).GetValue() ) );
1001 break;
1002 case EE_CHAR_PAIRKERNING:
1004 rOutput << OOO_STRING_SVTOOLS_RTF_KERNING;
1005 rOutput.WriteNumber( ((const SvxAutoKernItem&)rItem).GetValue() ? 1 : 0 );
1007 break;
1008 case EE_CHAR_ESCAPEMENT:
1010 SvxFont aFont;
1011 ContentNode* pNode = aEditDoc.GetObject( nPara );
1012 SeekCursor( pNode, nPos, aFont );
1013 MapMode aPntMode( MAP_POINT );
1014 long nFontHeight = GetRefDevice()->LogicToLogic(
1015 aFont.GetSize(), &GetRefMapMode(), &aPntMode ).Height();
1016 nFontHeight *=2; // HalfPoints
1017 sal_uInt16 nProp = ((const SvxEscapementItem&)rItem).GetProp();
1018 sal_uInt16 nProp100 = nProp*100; // Fuer SWG-Token Prop in 100tel Prozent.
1019 short nEsc = ((const SvxEscapementItem&)rItem).GetEsc();
1020 if ( nEsc == DFLT_ESC_AUTO_SUPER )
1022 nEsc = 100 - nProp;
1023 nProp100++; // Eine 1 hinten bedeutet 'automatisch'.
1025 else if ( nEsc == DFLT_ESC_AUTO_SUB )
1027 nEsc = sal::static_int_cast< short >( -( 100 - nProp ) );
1028 nProp100++;
1030 // SWG:
1031 if ( nEsc )
1032 rOutput << "{\\*\\updnprop" << ByteString::CreateFromInt32( nProp100 ).GetBuffer() << '}';
1033 long nUpDown = nFontHeight * Abs( nEsc ) / 100;
1034 ByteString aUpDown = ByteString::CreateFromInt32( nUpDown );
1035 if ( nEsc < 0 )
1036 rOutput << OOO_STRING_SVTOOLS_RTF_DN << aUpDown.GetBuffer();
1037 else if ( nEsc > 0 )
1038 rOutput << OOO_STRING_SVTOOLS_RTF_UP << aUpDown.GetBuffer();
1040 break;
1044 sal_uInt32 ImpEditEngine::WriteHTML( SvStream&, EditSelection )
1046 return 0;
1050 EditTextObject* ImpEditEngine::CreateTextObject()
1052 EditSelection aCompleteSelection;
1053 aCompleteSelection.Min() = aEditDoc.GetStartPaM();
1054 aCompleteSelection.Max() = aEditDoc.GetEndPaM();
1056 return CreateTextObject( aCompleteSelection );
1059 EditTextObject* ImpEditEngine::CreateTextObject( EditSelection aSel )
1061 return CreateBinTextObject( aSel, GetEditTextObjectPool(), aStatus.AllowBigObjects(), nBigTextObjectStart );
1064 EditTextObject* ImpEditEngine::CreateBinTextObject( EditSelection aSel, SfxItemPool* pPool, sal_Bool bAllowBigObjects, sal_uInt16 nBigObjectStart ) const
1066 BinTextObject* pTxtObj = new BinTextObject( pPool );
1067 pTxtObj->SetVertical( IsVertical() );
1068 MapUnit eMapUnit = (MapUnit)aEditDoc.GetItemPool().GetMetric( DEF_METRIC );
1069 pTxtObj->SetMetric( (sal_uInt16) eMapUnit );
1070 if ( pTxtObj->IsOwnerOfPool() )
1071 pTxtObj->GetPool()->SetDefaultMetric( (SfxMapUnit) eMapUnit );
1073 sal_uInt16 nStartNode, nEndNode;
1074 sal_uInt32 nTextPortions = 0;
1076 aSel.Adjust( aEditDoc );
1077 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
1078 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
1080 sal_Bool bOnlyFullParagraphs = ( aSel.Min().GetIndex() ||
1081 ( aSel.Max().GetIndex() < aSel.Max().GetNode()->Len() ) ) ?
1082 sal_False : sal_True;
1084 // Vorlagen werden nicht gespeichert!
1085 // ( Nur Name und Familie, Vorlage selbst muss in App stehen! )
1087 pTxtObj->SetScriptType( GetScriptType( aSel ) );
1089 // ueber die Absaetze iterieren...
1090 sal_uInt16 nNode;
1091 for ( nNode = nStartNode; nNode <= nEndNode; nNode++ )
1093 ContentNode* pNode = aEditDoc.SaveGetObject( nNode );
1094 DBG_ASSERT( pNode, "Node nicht gefunden: Search&Replace" );
1096 if ( bOnlyFullParagraphs )
1098 ParaPortion* pParaPortion = GetParaPortions()[nNode];
1099 nTextPortions += pParaPortion->GetTextPortions().Count();
1102 sal_uInt16 nStartPos = 0;
1103 sal_uInt16 nEndPos = pNode->Len();
1105 sal_Bool bEmptyPara = nEndPos ? sal_False : sal_True;
1107 if ( ( nNode == nStartNode ) && !bOnlyFullParagraphs )
1108 nStartPos = aSel.Min().GetIndex();
1109 if ( ( nNode == nEndNode ) && !bOnlyFullParagraphs )
1110 nEndPos = aSel.Max().GetIndex();
1113 ContentInfo* pC = pTxtObj->CreateAndInsertContent();
1115 // Die Absatzattribute...
1116 pC->GetParaAttribs().Set( pNode->GetContentAttribs().GetItems() );
1118 // Das StyleSheet...
1119 if ( pNode->GetStyleSheet() )
1121 pC->GetStyle() = pNode->GetStyleSheet()->GetName();
1122 pC->GetFamily() = pNode->GetStyleSheet()->GetFamily();
1125 // Der Text...
1126 pC->GetText() = pNode->Copy( nStartPos, nEndPos-nStartPos );
1128 // und die Attribute...
1129 sal_uInt16 nAttr = 0;
1130 EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
1131 while ( pAttr )
1133 // In einem leeren Absatz die Attribute behalten!
1134 if ( bEmptyPara ||
1135 ( ( pAttr->GetEnd() > nStartPos ) && ( pAttr->GetStart() < nEndPos ) ) )
1137 XEditAttribute* pX = pTxtObj->CreateAttrib( *pAttr->GetItem(), pAttr->GetStart(), pAttr->GetEnd() );
1138 // Evtl. korrigieren...
1139 if ( ( nNode == nStartNode ) && ( nStartPos != 0 ) )
1141 pX->GetStart() = ( pX->GetStart() > nStartPos ) ? pX->GetStart()-nStartPos : 0;
1142 pX->GetEnd() = pX->GetEnd() - nStartPos;
1145 if ( nNode == nEndNode )
1147 if ( pX->GetEnd() > (nEndPos-nStartPos) )
1148 pX->GetEnd() = nEndPos-nStartPos;
1150 DBG_ASSERT( pX->GetEnd() <= (nEndPos-nStartPos), "CreateBinTextObject: Attribut zu lang!" );
1151 if ( !pX->GetLen() && !bEmptyPara )
1152 pTxtObj->DestroyAttrib( pX );
1153 else
1154 pC->GetAttribs().Insert( pX, pC->GetAttribs().Count() );
1156 nAttr++;
1157 pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
1160 #ifndef SVX_LIGHT
1161 // ggf. Online-Spelling
1162 if ( bAllowBigObjects && bOnlyFullParagraphs && pNode->GetWrongList() )
1163 pC->SetWrongList( pNode->GetWrongList()->Clone() );
1164 #endif // !SVX_LIGHT
1168 // Bei grossen Textobjekten die PortionInfos merken:
1169 // Schwelle rauf setzen, wenn Olli die Absaetze nicht mehr zerhackt!
1170 if ( bAllowBigObjects && bOnlyFullParagraphs && IsFormatted() && GetUpdateMode() && ( nTextPortions >= nBigObjectStart ) )
1172 XParaPortionList* pXList = new XParaPortionList( GetRefDevice(), aPaperSize.Width(), nStretchX, nStretchY );
1173 pTxtObj->SetPortionInfo( pXList );
1174 for ( nNode = nStartNode; nNode <= nEndNode; nNode++ )
1176 ParaPortion* pParaPortion = GetParaPortions()[nNode];
1177 XParaPortion* pX = new XParaPortion;
1178 pXList->Insert( pX, pXList->Count() );
1180 pX->nHeight = pParaPortion->GetHeight();
1181 pX->nFirstLineOffset = pParaPortion->GetFirstLineOffset();
1183 // Die TextPortions
1184 sal_uInt16 nCount = pParaPortion->GetTextPortions().Count();
1185 sal_uInt16 n;
1186 for ( n = 0; n < nCount; n++ )
1188 TextPortion* pTextPortion = pParaPortion->GetTextPortions()[n];
1189 TextPortion* pNew = new TextPortion( *pTextPortion );
1190 pX->aTextPortions.Insert( pNew, pX->aTextPortions.Count() );
1193 // Die Zeilen
1194 nCount = pParaPortion->GetLines().Count();
1195 for ( n = 0; n < nCount; n++ )
1197 EditLine* pLine = pParaPortion->GetLines()[n];
1198 EditLine* pNew = pLine->Clone();
1199 pX->aLines.Insert( pNew, pX->aLines.Count() );
1201 #ifdef DBG_UTIL
1202 USHORT nTest;
1203 int nTPLen = 0, nTxtLen = 0;
1204 for ( nTest = pParaPortion->GetTextPortions().Count(); nTest; )
1205 nTPLen += pParaPortion->GetTextPortions().GetObject( --nTest )->GetLen();
1206 for ( nTest = pParaPortion->GetLines().Count(); nTest; )
1207 nTxtLen += pParaPortion->GetLines().GetObject( --nTest )->GetLen();
1208 DBG_ASSERT( ( nTPLen == pParaPortion->GetNode()->Len() ) && ( nTxtLen == pParaPortion->GetNode()->Len() ), "CreateBinTextObject: ParaPortion not completely formatted!" );
1209 #endif
1212 return pTxtObj;
1215 void ImpEditEngine::SetText( const EditTextObject& rTextObject )
1217 // Da Setzen eines TextObject ist nicht Undo-faehig!
1218 ResetUndoManager();
1219 sal_Bool _bUpdate = GetUpdateMode();
1220 sal_Bool _bUndo = IsUndoEnabled();
1222 SetText( XubString() );
1223 EditPaM aPaM = aEditDoc.GetStartPaM();
1225 SetUpdateMode( sal_False );
1226 EnableUndo( sal_False );
1228 InsertText( rTextObject, EditSelection( aPaM, aPaM ) );
1229 SetVertical( rTextObject.IsVertical() );
1231 #ifndef SVX_LIGHT
1232 DBG_ASSERT( !HasUndoManager() || !GetUndoManager().GetUndoActionCount(), "Woher kommt das Undo in SetText ?!" );
1233 #endif
1234 SetUpdateMode( _bUpdate );
1235 EnableUndo( _bUndo );
1238 EditSelection ImpEditEngine::InsertText( const EditTextObject& rTextObject, EditSelection aSel )
1240 EnterBlockNotifications();
1241 aSel.Adjust( aEditDoc );
1242 if ( aSel.HasRange() )
1243 aSel = ImpDeleteSelection( aSel );
1244 EditSelection aNewSel = InsertBinTextObject( (BinTextObject&)rTextObject, aSel.Max() );
1245 LeaveBlockNotifications();
1246 return aNewSel;
1248 // MT 05/00: InsertBinTextObject direkt hier machen...
1251 EditSelection ImpEditEngine::InsertBinTextObject( BinTextObject& rTextObject, EditPaM aPaM )
1253 // Optimieren:
1254 // Kein GetPos undFindParaportion, sondern Index berechnen!
1255 EditSelection aSel( aPaM, aPaM );
1256 DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "InsertBibTextObject: Selektion kaput!(1)" );
1258 sal_Bool bUsePortionInfo = sal_False;
1259 // sal_Bool bFields = sal_False;
1260 XParaPortionList* pPortionInfo = rTextObject.GetPortionInfo();
1262 if ( pPortionInfo && ( (long)pPortionInfo->GetPaperWidth() == aPaperSize.Width() )
1263 && ( pPortionInfo->GetRefMapMode() == GetRefDevice()->GetMapMode() )
1264 && ( pPortionInfo->GetStretchX() == nStretchX )
1265 && ( pPortionInfo->GetStretchY() == nStretchY ) )
1267 if ( ( pPortionInfo->GetRefDevPtr() == (sal_uIntPtr)GetRefDevice() ) ||
1268 ( ( pPortionInfo->GetRefDevType() == OUTDEV_VIRDEV ) &&
1269 ( GetRefDevice()->GetOutDevType() == OUTDEV_VIRDEV ) ) )
1270 bUsePortionInfo = sal_True;
1273 sal_Bool bConvertItems = sal_False;
1274 MapUnit eSourceUnit = MapUnit(), eDestUnit = MapUnit();
1275 if ( rTextObject.HasMetric() )
1277 eSourceUnit = (MapUnit)rTextObject.GetMetric();
1278 eDestUnit = (MapUnit)aEditDoc.GetItemPool().GetMetric( DEF_METRIC );
1279 if ( eSourceUnit != eDestUnit )
1280 bConvertItems = sal_True;
1283 sal_uInt16 nContents = rTextObject.GetContents().Count();
1284 sal_uInt16 nPara = aEditDoc.GetPos( aPaM.GetNode() );
1286 for ( sal_uInt16 n = 0; n < nContents; n++, nPara++ )
1288 ContentInfo* pC = rTextObject.GetContents().GetObject( n );
1289 sal_Bool bNewContent = aPaM.GetNode()->Len() ? sal_False: sal_True;
1290 sal_uInt16 nStartPos = aPaM.GetIndex();
1292 aPaM = ImpFastInsertText( aPaM, pC->GetText() );
1294 ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() );
1295 DBG_ASSERT( pPortion, "Blinde Portion in FastInsertText" );
1296 pPortion->MarkInvalid( nStartPos, pC->GetText().Len() );
1298 // Zeicheattribute...
1299 sal_Bool bAllreadyHasAttribs = aPaM.GetNode()->GetCharAttribs().Count() ? sal_True : sal_False;
1300 sal_uInt16 nNewAttribs = pC->GetAttribs().Count();
1301 if ( nNewAttribs )
1303 BOOL bUpdateFields = FALSE;
1304 for ( sal_uInt16 nAttr = 0; nAttr < nNewAttribs; nAttr++ )
1306 XEditAttribute* pX = pC->GetAttribs().GetObject( nAttr );
1307 // Kann passieren wenn Absaetze >16K entstehen, dann wird einfach umgebrochen.
1308 if ( pX->GetEnd() <= aPaM.GetNode()->Len() )
1310 if ( !bAllreadyHasAttribs || pX->IsFeature() )
1312 // Normale Attribute gehen dann schneller...
1313 // Features duerfen nicht ueber EditDoc::InsertAttrib
1314 // eingefuegt werden, sie sind bei FastInsertText schon im TextFluss
1315 DBG_ASSERT( pX->GetEnd() <= aPaM.GetNode()->Len(), "InsertBinTextObject: Attribut zu gross!" );
1316 EditCharAttrib* pAttr;
1317 if ( !bConvertItems )
1318 pAttr = MakeCharAttrib( aEditDoc.GetItemPool(), *(pX->GetItem()), pX->GetStart()+nStartPos, pX->GetEnd()+nStartPos );
1319 else
1321 SfxPoolItem* pNew = pX->GetItem()->Clone();
1322 ConvertItem( *pNew, eSourceUnit, eDestUnit );
1323 pAttr = MakeCharAttrib( aEditDoc.GetItemPool(), *pNew, pX->GetStart()+nStartPos, pX->GetEnd()+nStartPos );
1324 delete pNew;
1326 DBG_ASSERT( pAttr->GetEnd() <= aPaM.GetNode()->Len(), "InsertBinTextObject: Attribut passt nicht! (1)" );
1327 aPaM.GetNode()->GetCharAttribs().InsertAttrib( pAttr );
1328 if ( pAttr->Which() == EE_FEATURE_FIELD )
1329 bUpdateFields = TRUE;
1331 else
1333 DBG_ASSERT( pX->GetEnd()+nStartPos <= aPaM.GetNode()->Len(), "InsertBinTextObject: Attribut passt nicht! (2)" );
1334 // Tabs und andere Features koennen nicht ueber InsertAttrib eingefuegt werden:
1335 aEditDoc.InsertAttrib( aPaM.GetNode(), pX->GetStart()+nStartPos, pX->GetEnd()+nStartPos, *pX->GetItem() );
1339 if ( bUpdateFields )
1340 UpdateFields();
1342 // Sonst QuickFormat => Keine Attribute!
1343 pPortion->MarkSelectionInvalid( nStartPos, pC->GetText().Len() );
1346 DBG_ASSERT( CheckOrderedList( aPaM.GetNode()->GetCharAttribs().GetAttribs(), sal_True ), "InsertBinTextObject: Start-Liste verdreht" );
1348 sal_Bool bParaAttribs = sal_False;
1349 if ( bNewContent || ( ( n > 0 ) && ( n < (nContents-1) ) ) )
1351 bParaAttribs = sal_False;
1352 // #101512# Don't overwrite level/style from existing paragraph in OutlineView
1353 // MT 10/2002: Removed because of #103874#, handled in Outliner::EndPasteOrDropHdl now.
1354 // if ( !aStatus.IsOutliner() || n )
1356 // nur dann Style und ParaAttribs, wenn neuer Absatz, oder
1357 // komplett inneliegender...
1358 bParaAttribs = pC->GetParaAttribs().Count() ? sal_True : sal_False;
1359 if ( GetStyleSheetPool() && pC->GetStyle().Len() )
1361 SfxStyleSheet* pStyle = (SfxStyleSheet*)GetStyleSheetPool()->Find( pC->GetStyle(), pC->GetFamily() );
1362 DBG_ASSERT( pStyle, "InsertBinTextObject - Style not found!" );
1363 SetStyleSheet( nPara, pStyle );
1365 if ( !bConvertItems )
1366 SetParaAttribs( aEditDoc.GetPos( aPaM.GetNode() ), pC->GetParaAttribs() );
1367 else
1369 SfxItemSet aAttribs( GetEmptyItemSet() );
1370 ConvertAndPutItems( aAttribs, pC->GetParaAttribs(), &eSourceUnit, &eDestUnit );
1371 SetParaAttribs( aEditDoc.GetPos( aPaM.GetNode() ), aAttribs );
1374 if ( bNewContent && bUsePortionInfo )
1376 XParaPortion* pXP = pPortionInfo->GetObject( n );
1377 DBG_ASSERT( pXP, "InsertBinTextObject: PortionInfo?" );
1378 ParaPortion* pParaPortion = GetParaPortions()[ nPara ];
1379 DBG_ASSERT( pParaPortion, "InsertBinTextObject: ParaPortion?" );
1380 pParaPortion->nHeight = pXP->nHeight;
1381 pParaPortion->nFirstLineOffset = pXP->nFirstLineOffset;
1382 pParaPortion->bForceRepaint = sal_True;
1383 pParaPortion->SetValid(); // Nicht formatieren
1385 // Die TextPortions
1386 pParaPortion->GetTextPortions().Reset();
1387 sal_uInt16 nCount = pXP->aTextPortions.Count();
1388 for ( sal_uInt16 _n = 0; _n < nCount; _n++ )
1390 TextPortion* pTextPortion = pXP->aTextPortions[_n];
1391 TextPortion* pNew = new TextPortion( *pTextPortion );
1392 pParaPortion->GetTextPortions().Insert( pNew, _n );
1395 // Die Zeilen
1396 pParaPortion->GetLines().Reset();
1397 nCount = pXP->aLines.Count();
1398 for ( sal_uInt16 m = 0; m < nCount; m++ )
1400 EditLine* pLine = pXP->aLines[m];
1401 EditLine* pNew = pLine->Clone();
1402 pNew->SetInvalid(); // neu Painten!
1403 pParaPortion->GetLines().Insert( pNew, m );
1405 #ifdef DBG_UTIL
1406 USHORT nTest;
1407 int nTPLen = 0, nTxtLen = 0;
1408 for ( nTest = pParaPortion->GetTextPortions().Count(); nTest; )
1409 nTPLen += pParaPortion->GetTextPortions().GetObject( --nTest )->GetLen();
1410 for ( nTest = pParaPortion->GetLines().Count(); nTest; )
1411 nTxtLen += pParaPortion->GetLines().GetObject( --nTest )->GetLen();
1412 DBG_ASSERT( ( nTPLen == pParaPortion->GetNode()->Len() ) && ( nTxtLen == pParaPortion->GetNode()->Len() ), "InsertBinTextObject: ParaPortion not completely formatted!" );
1413 #endif
1416 if ( !bParaAttribs ) // DefFont wird bei FastInsertParagraph nicht berechnet
1418 aPaM.GetNode()->GetCharAttribs().GetDefFont() = aEditDoc.GetDefFont();
1419 if ( aStatus.UseCharAttribs() )
1420 aPaM.GetNode()->CreateDefFont();
1423 #ifndef SVX_LIGHT
1424 if ( bNewContent && GetStatus().DoOnlineSpelling() && pC->GetWrongList() )
1426 aPaM.GetNode()->DestroyWrongList(); // otherwise MLK, if list exists...
1427 aPaM.GetNode()->SetWrongList( pC->GetWrongList()->Clone() );
1429 #endif // !SVX_LIGHT
1431 // Zeilenumbruch, wenn weitere folgen...
1432 if ( n < ( nContents-1) )
1434 if ( bNewContent )
1435 aPaM = ImpFastInsertParagraph( nPara+1 );
1436 else
1437 aPaM = ImpInsertParaBreak( aPaM, sal_False );
1441 aSel.Max() = aPaM;
1442 DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "InsertBibTextObject: Selektion kaput!(1)" );
1443 return aSel;
1446 LanguageType ImpEditEngine::GetLanguage( const EditPaM& rPaM, USHORT* pEndPos ) const
1448 short nScriptType = GetScriptType( rPaM, pEndPos ); // pEndPos will be valid now, pointing to ScriptChange or NodeLen
1449 USHORT nLangId = GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType );
1450 const SvxLanguageItem* pLangItem = &(const SvxLanguageItem&)rPaM.GetNode()->GetContentAttribs().GetItem( nLangId );
1451 EditCharAttrib* pAttr = rPaM.GetNode()->GetCharAttribs().FindAttrib( nLangId, rPaM.GetIndex() );
1452 if ( pAttr )
1453 pLangItem = (const SvxLanguageItem*)pAttr->GetItem();
1455 if ( pEndPos && pAttr && ( pAttr->GetEnd() < *pEndPos ) )
1456 *pEndPos = pAttr->GetEnd();
1458 return pLangItem->GetLanguage();
1461 ::com::sun::star::lang::Locale ImpEditEngine::GetLocale( const EditPaM& rPaM ) const
1463 return SvxCreateLocale( GetLanguage( rPaM ) );
1466 Reference< XSpellChecker1 > ImpEditEngine::GetSpeller()
1468 #ifndef SVX_LIGHT
1469 if ( !xSpeller.is() )
1470 xSpeller = SvxGetSpellChecker();
1471 #endif
1472 return xSpeller;
1475 EESpellState ImpEditEngine::Spell( EditView* pEditView, sal_Bool bMultipleDoc )
1477 #ifdef SVX_LIGHT
1478 return EE_SPELL_NOSPELLER;
1479 #else
1481 DBG_ASSERTWARNING( xSpeller.is(), "Kein Speller gesetzt!" );
1483 if ( !xSpeller.is() )
1484 return EE_SPELL_NOSPELLER;
1486 aOnlineSpellTimer.Stop();
1488 // Bei MultipleDoc immer von vorne/hinten...
1489 if ( bMultipleDoc )
1491 pEditView->pImpEditView->SetEditSelection( aEditDoc.GetStartPaM() );
1494 EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() );
1495 pSpellInfo = new SpellInfo;
1496 pSpellInfo->bMultipleDoc = bMultipleDoc;
1497 pSpellInfo->aSpellStart = CreateEPaM( SelectWord( aCurSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD ).Min() );
1499 sal_Bool bIsStart = sal_False;
1500 if ( bMultipleDoc )
1501 bIsStart = sal_True; // Immer von Vorne bzw. von hinten...
1502 else if ( ( CreateEPaM( aEditDoc.GetStartPaM() ) == pSpellInfo->aSpellStart ) )
1503 bIsStart = sal_True;
1505 EditSpellWrapper* pWrp = new EditSpellWrapper( Application::GetDefDialogParent(),
1506 xSpeller, bIsStart, sal_False, pEditView );
1507 pWrp->SpellDocument();
1508 delete pWrp;
1510 if ( !bMultipleDoc )
1512 pEditView->pImpEditView->DrawSelection();
1513 if ( aCurSel.Max().GetIndex() > aCurSel.Max().GetNode()->Len() )
1514 aCurSel.Max().GetIndex() = aCurSel.Max().GetNode()->Len();
1515 aCurSel.Min() = aCurSel.Max();
1516 pEditView->pImpEditView->SetEditSelection( aCurSel );
1517 pEditView->pImpEditView->DrawSelection();
1518 pEditView->ShowCursor( sal_True, sal_False );
1520 EESpellState eState = pSpellInfo->eState;
1521 delete pSpellInfo;
1522 pSpellInfo = 0;
1523 return eState;
1524 #endif
1528 sal_Bool ImpEditEngine::HasConvertibleTextPortion( LanguageType nSrcLang )
1530 #ifdef SVX_LIGHT
1531 return sal_False;
1532 #else
1533 sal_Bool bHasConvTxt = sal_False;
1535 USHORT nParas = pEditEngine->GetParagraphCount();
1536 for (USHORT k = 0; k < nParas; ++k)
1538 SvUShorts aPortions;
1539 pEditEngine->GetPortions( k, aPortions );
1540 for ( USHORT nPos = 0; nPos < aPortions.Count(); ++nPos )
1542 USHORT nEnd = aPortions.GetObject( nPos );
1543 USHORT nStart = nPos > 0 ? aPortions.GetObject( nPos - 1 ) : 0;
1545 // if the paragraph is not empty we need to increase the index
1546 // by one since the attribute of the character left to the
1547 // specified position is evaluated.
1548 if (nEnd > nStart) // empty para?
1549 ++nStart;
1550 LanguageType nLangFound = pEditEngine->GetLanguage( k, nStart );
1551 #ifdef DEBUG
1552 lang::Locale aLocale( SvxCreateLocale( nLangFound ) );
1553 #endif
1554 bHasConvTxt = (nSrcLang == nLangFound) ||
1555 (svx::HangulHanjaConversion::IsChinese( nLangFound ) &&
1556 svx::HangulHanjaConversion::IsChinese( nSrcLang ));
1557 if (bHasConvTxt)
1558 return bHasConvTxt;
1562 #endif
1563 return bHasConvTxt;
1567 void ImpEditEngine::Convert( EditView* pEditView,
1568 LanguageType nSrcLang, LanguageType nDestLang, const Font *pDestFont,
1569 INT32 nOptions, sal_Bool bIsInteractive, sal_Bool bMultipleDoc )
1571 // modified version of ImpEditEngine::Spell
1573 #ifdef SVX_LIGHT
1574 #else
1576 // Bei MultipleDoc immer von vorne/hinten...
1577 if ( bMultipleDoc )
1578 pEditView->pImpEditView->SetEditSelection( aEditDoc.GetStartPaM() );
1581 // initialize pConvInfo
1583 EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() );
1584 aCurSel.Adjust( aEditDoc );
1585 pConvInfo = new ConvInfo;
1586 pConvInfo->bMultipleDoc = bMultipleDoc;
1587 pConvInfo->aConvStart = CreateEPaM( aCurSel.Min() );
1589 // if it is not just a selection and we are about to begin
1590 // with the current conversion for the very first time
1591 // we need to find the start of the current (initial)
1592 // convertible unit in order for the text conversion to give
1593 // the correct result for that. Since it is easier to obtain
1594 // the start of the word we use that though.
1595 if (!aCurSel.HasRange() && ImplGetBreakIterator().is())
1597 EditPaM aWordStartPaM( SelectWord( aCurSel, i18n::WordType::DICTIONARY_WORD ).Min() );
1599 // since #118246 / #117803 still occurs if the cursor is placed
1600 // between the two chinese characters to be converted (because both
1601 // of them are words on their own!) using the word boundary here does
1602 // not work. Thus since chinese conversion is not interactive we start
1603 // at the begin of the paragraph to solve the problem, i.e. have the
1604 // TextConversion service get those characters together in the same call.
1605 USHORT nStartIdx = ( svx::HangulHanjaConversion::IsChinese( nSrcLang ) ) ?
1606 0 : aWordStartPaM.GetIndex();
1607 pConvInfo->aConvStart.nIndex = nStartIdx;
1610 pConvInfo->aConvContinue = pConvInfo->aConvStart;
1612 sal_Bool bIsStart = sal_False;
1613 if ( bMultipleDoc )
1614 bIsStart = sal_True; // Immer von Vorne bzw. von hinten...
1615 else if ( CreateEPaM( aEditDoc.GetStartPaM() ) == pConvInfo->aConvStart )
1616 bIsStart = sal_True;
1618 bImpConvertFirstCall = sal_True; // next ImpConvert call is the very first in this conversion turn
1620 Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory();
1621 TextConvWrapper aWrp( Application::GetDefDialogParent(), xMSF,
1622 SvxCreateLocale( nSrcLang ), SvxCreateLocale( nDestLang ),
1623 pDestFont,
1624 nOptions, bIsInteractive,
1625 bIsStart, pEditView );
1628 //!! optimization does not work since when update mode is false
1629 //!! the object is 'lying' about it portions, paragraphs,
1630 //!! EndPaM... later on.
1631 //!! Should not be a great problem since text boxes or cells in
1632 //!! Calc usually have only a rather short text.
1634 // disallow formatting, updating the view, ... while
1635 // non-interactively converting the document. (saves time)
1636 //if (!bIsInteractive)
1637 // SetUpdateMode( FALSE );
1639 aWrp.Convert();
1641 //if (!bIsInteractive)
1642 //SetUpdateMode( TRUE, 0, TRUE );
1644 if ( !bMultipleDoc )
1646 pEditView->pImpEditView->DrawSelection();
1647 if ( aCurSel.Max().GetIndex() > aCurSel.Max().GetNode()->Len() )
1648 aCurSel.Max().GetIndex() = aCurSel.Max().GetNode()->Len();
1649 aCurSel.Min() = aCurSel.Max();
1650 pEditView->pImpEditView->SetEditSelection( aCurSel );
1651 pEditView->pImpEditView->DrawSelection();
1652 pEditView->ShowCursor( sal_True, sal_False );
1654 delete pConvInfo;
1655 pConvInfo = 0;
1656 #endif
1660 void ImpEditEngine::SetLanguageAndFont(
1661 const ESelection &rESel,
1662 LanguageType nLang, USHORT nLangWhichId,
1663 const Font *pFont, USHORT nFontWhichId )
1665 ESelection aOldSel = pActiveView->GetSelection();
1666 pActiveView->SetSelection( rESel );
1668 // set new language attribute
1669 SfxItemSet aNewSet( pActiveView->GetEmptyItemSet() );
1670 aNewSet.Put( SvxLanguageItem( nLang, nLangWhichId ) );
1672 // new font to be set?
1673 DBG_ASSERT( pFont, "target font missing?" );
1674 if (pFont)
1676 // set new font attribute
1677 SvxFontItem aFontItem = (SvxFontItem&) aNewSet.Get( nFontWhichId );
1678 aFontItem.GetFamilyName() = pFont->GetName();
1679 aFontItem.GetFamily() = pFont->GetFamily();
1680 aFontItem.GetStyleName() = pFont->GetStyleName();
1681 aFontItem.GetPitch() = pFont->GetPitch();
1682 aFontItem.GetCharSet() = pFont->GetCharSet();
1683 aNewSet.Put( aFontItem );
1686 // apply new attributes
1687 pActiveView->SetAttribs( aNewSet );
1689 pActiveView->SetSelection( aOldSel );
1693 void ImpEditEngine::ImpConvert( rtl::OUString &rConvTxt, LanguageType &rConvTxtLang,
1694 EditView* pEditView, LanguageType nSrcLang, const ESelection &rConvRange,
1695 sal_Bool bAllowImplicitChangesForNotConvertibleText,
1696 LanguageType nTargetLang, const Font *pTargetFont )
1698 // modified version of ImpEditEngine::ImpSpell
1700 // looks for next convertible text portion to be passed on to the wrapper
1702 String aRes;
1703 LanguageType nResLang = LANGUAGE_NONE;
1705 #ifdef SVX_LIGHT
1706 rConvTxt = rtl::OUString();
1707 rConvTxtLang = LANGUAGE_NONE;
1708 #else
1710 /* ContentNode* pLastNode = */ aEditDoc.SaveGetObject( aEditDoc.Count()-1 );
1712 EditPaM aPos( CreateEditPaM( pConvInfo->aConvContinue ) );
1713 EditSelection aCurSel = EditSelection( aPos, aPos );
1715 String aWord;
1717 while (!aRes.Len())
1719 // empty paragraph found that needs to have language and font set?
1720 if (bAllowImplicitChangesForNotConvertibleText &&
1721 !pEditEngine->GetText( pConvInfo->aConvContinue.nPara ).Len())
1723 USHORT nPara = pConvInfo->aConvContinue.nPara;
1724 ESelection aESel( nPara, 0, nPara, 0 );
1725 // see comment for below same function call
1726 SetLanguageAndFont( aESel,
1727 nTargetLang, EE_CHAR_LANGUAGE_CJK,
1728 pTargetFont, EE_CHAR_FONTINFO_CJK );
1732 if (pConvInfo->aConvContinue.nPara == pConvInfo->aConvTo.nPara &&
1733 pConvInfo->aConvContinue.nIndex >= pConvInfo->aConvTo.nIndex)
1734 break;
1737 // Bekannter (wahrscheinlicher) Bug: Wenn SpellToCurrent, muss
1738 // Current bei jeder Ersetzung korrigiert werden, sonst passt
1739 // das Ende evtl. nicht mehr genau...
1740 if ( pConvInfo->bConvToEnd || pConvInfo->bMultipleDoc )
1742 if ( aCurSel.Max().GetNode() == pLastNode &&
1743 aCurSel.Max().GetIndex() >= pLastNode->Len() )
1744 break;
1748 USHORT nAttribStart = USHRT_MAX;
1749 USHORT nAttribEnd = USHRT_MAX;
1750 USHORT nCurPos = USHRT_MAX;
1751 EPaM aCurStart = CreateEPaM( aCurSel.Min() );
1752 SvUShorts aPortions;
1753 pEditEngine->GetPortions( (USHORT)aCurStart.nPara, aPortions );
1754 for ( USHORT nPos = 0; nPos < aPortions.Count(); ++nPos )
1756 USHORT nEnd = aPortions.GetObject( nPos );
1757 USHORT nStart = nPos > 0 ? aPortions.GetObject( nPos - 1 ) : 0;
1759 // the language attribute is obtained from the left character
1760 // (like usually all other attributes)
1761 // thus we usually have to add 1 in order to get the language
1762 // of the text right to the cursor position
1763 USHORT nLangIdx = nEnd > nStart ? nStart + 1 : nStart;
1764 LanguageType nLangFound = pEditEngine->GetLanguage( aCurStart.nPara, nLangIdx );
1765 #ifdef DEBUG
1766 lang::Locale aLocale( SvxCreateLocale( nLangFound ) );
1767 #endif
1768 sal_Bool bLangOk = (nLangFound == nSrcLang) ||
1769 (svx::HangulHanjaConversion::IsChinese( nLangFound ) &&
1770 svx::HangulHanjaConversion::IsChinese( nSrcLang ));
1772 if (nAttribEnd != USHRT_MAX) // start already found?
1774 DBG_ASSERT(nEnd >= aCurStart.nIndex, "error while scanning attributes (a)" );
1775 DBG_ASSERT(nEnd >= nAttribEnd, "error while scanning attributes (b)" );
1776 if (/*nEnd >= aCurStart.nIndex &&*/ nLangFound == nResLang)
1777 nAttribEnd = nEnd;
1778 else // language attrib has changed
1779 break;
1781 if (nAttribStart == USHRT_MAX && // start not yet found?
1782 nEnd > aCurStart.nIndex && bLangOk)
1784 nAttribStart = nStart;
1785 nAttribEnd = nEnd;
1786 nResLang = nLangFound;
1788 //! the list of portions may have changed compared to the previous
1789 //! call to this function (because of possibly changed language
1790 //! attribute!)
1791 //! But since we don't want to start in the already processed part
1792 //! we clip the start accordingly.
1793 if (nAttribStart < aCurStart.nIndex)
1795 nAttribStart = aCurStart.nIndex;
1798 // check script type to the right of the start of the current portion
1799 EditPaM aPaM( CreateEditPaM( EPaM(aCurStart.nPara, nLangIdx) ) );
1800 sal_Bool bIsAsianScript = (i18n::ScriptType::ASIAN == GetScriptType( aPaM ));
1801 // not yet processed text part with for conversion
1802 // not suitable language found that needs to be changed?
1803 if (bAllowImplicitChangesForNotConvertibleText &&
1804 !bLangOk && !bIsAsianScript && nEnd > aCurStart.nIndex)
1806 ESelection aESel( aCurStart.nPara, nStart, aCurStart.nPara, nEnd );
1807 // set language and font to target language and font of conversion
1808 //! Now this especially includes all non convertible text e.g.
1809 //! spaces, empty paragraphs and western text.
1810 // This is in order for every *new* text entered at *any* position to
1811 // have the correct language and font attributes set.
1812 SetLanguageAndFont( aESel,
1813 nTargetLang, EE_CHAR_LANGUAGE_CJK,
1814 pTargetFont, EE_CHAR_FONTINFO_CJK );
1817 nCurPos = nEnd;
1820 if (nAttribStart != USHRT_MAX && nAttribEnd != USHRT_MAX)
1822 aCurSel.Min().SetIndex( nAttribStart );
1823 aCurSel.Max().SetIndex( nAttribEnd );
1825 else if (nCurPos != USHRT_MAX)
1827 // set selection to end of scanned text
1828 // (used to set the position where to continue from later on)
1829 aCurSel.Min().SetIndex( nCurPos );
1830 aCurSel.Max().SetIndex( nCurPos );
1833 if ( !pConvInfo->bConvToEnd )
1835 EPaM aEPaM( CreateEPaM( aCurSel.Min() ) );
1836 if ( !( aEPaM < pConvInfo->aConvTo ) )
1837 break;
1840 // clip selected word to the converted area
1841 // (main use when conversion starts/ends **within** a word)
1842 EditPaM aPaM( CreateEditPaM( pConvInfo->aConvStart ) );
1843 if (pConvInfo->bConvToEnd &&
1844 aCurSel.Min().GetNode() == aPaM.GetNode() &&
1845 aCurSel.Min().GetIndex() < aPaM.GetIndex())
1846 aCurSel.Min().SetIndex( aPaM.GetIndex() );
1847 aPaM = CreateEditPaM( pConvInfo->aConvContinue );
1848 if (aCurSel.Min().GetNode() == aPaM.GetNode() &&
1849 aCurSel.Min().GetIndex() < aPaM.GetIndex())
1850 aCurSel.Min().SetIndex( aPaM.GetIndex() );
1851 aPaM = CreateEditPaM( pConvInfo->aConvTo );
1852 if ((!pConvInfo->bConvToEnd || rConvRange.HasRange())&&
1853 aCurSel.Max().GetNode() == aPaM.GetNode() &&
1854 aCurSel.Max().GetIndex() > aPaM.GetIndex())
1855 aCurSel.Max().SetIndex( aPaM.GetIndex() );
1857 aWord = GetSelected( aCurSel );
1859 if ( aWord.Len() > 0 /* && bLangOk */)
1860 aRes = aWord;
1862 // move to next word/paragraph if necessary
1863 if ( !aRes.Len() )
1864 aCurSel = WordRight( aCurSel.Min(), ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
1866 pConvInfo->aConvContinue = CreateEPaM( aCurSel.Max() );
1869 pEditView->pImpEditView->DrawSelection();
1870 pEditView->pImpEditView->SetEditSelection( aCurSel );
1871 pEditView->pImpEditView->DrawSelection();
1872 pEditView->ShowCursor( sal_True, sal_False );
1874 rConvTxt = aRes;
1875 if (rConvTxt.getLength())
1876 rConvTxtLang = nResLang;
1877 #endif
1881 Reference< XSpellAlternatives > ImpEditEngine::ImpSpell( EditView* pEditView )
1883 #ifdef SVX_LIGHT
1884 return Reference< XSpellAlternatives >();
1885 #else
1887 DBG_ASSERT( xSpeller.is(), "Kein Speller gesetzt!" );
1889 ContentNode* pLastNode = aEditDoc.SaveGetObject( (aEditDoc.Count()-1) );
1890 EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() );
1891 aCurSel.Min() = aCurSel.Max();
1893 String aWord;
1894 Reference< XSpellAlternatives > xSpellAlt;
1895 Sequence< PropertyValue > aEmptySeq;
1896 while (!xSpellAlt.is())
1899 // Bekannter (wahrscheinlicher) Bug: Wenn SpellToCurrent, muss
1900 // Current bei jeder Ersetzung korrigiert werden, sonst passt
1901 // das Ende evtl. nicht mehr genau...
1902 if ( pSpellInfo->bSpellToEnd || pSpellInfo->bMultipleDoc )
1904 if ( aCurSel.Max().GetNode() == pLastNode )
1906 if ( ( aCurSel.Max().GetIndex() >= pLastNode->Len() ) )
1907 break;
1910 else if ( !pSpellInfo->bSpellToEnd )
1912 EPaM aEPaM( CreateEPaM( aCurSel.Max() ) );
1913 if ( !( aEPaM < pSpellInfo->aSpellTo ) )
1914 break;
1917 aCurSel = SelectWord( aCurSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
1918 aWord = GetSelected( aCurSel );
1920 // Wenn Punkt dahinter, muss dieser mit uebergeben werden !
1921 // Falls Abkuerzung...
1922 if ( aWord.Len() && ( aCurSel.Max().GetIndex() < aCurSel.Max().GetNode()->Len() ) )
1924 sal_Unicode cNext = aCurSel.Max().GetNode()->GetChar( aCurSel.Max().GetIndex() );
1925 if ( cNext == '.' )
1927 aCurSel.Max().GetIndex()++;
1928 aWord += cNext;
1932 if ( aWord.Len() > 0 )
1934 LanguageType eLang = GetLanguage( aCurSel.Max() );
1935 SvxSpellWrapper::CheckSpellLang( xSpeller, eLang );
1936 xSpellAlt = xSpeller->spell( aWord, eLang, aEmptySeq );
1939 if ( !xSpellAlt.is() )
1940 aCurSel = WordRight( aCurSel.Min(), ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
1941 else
1942 pSpellInfo->eState = EE_SPELL_ERRORFOUND;
1945 pEditView->pImpEditView->DrawSelection();
1946 pEditView->pImpEditView->SetEditSelection( aCurSel );
1947 pEditView->pImpEditView->DrawSelection();
1948 pEditView->ShowCursor( sal_True, sal_False );
1949 return xSpellAlt;
1950 #endif
1952 /*-- 13.10.2003 16:43:27---------------------------------------------------
1954 -----------------------------------------------------------------------*/
1955 void ImpEditEngine::EndSpelling()
1957 DELETEZ(pSpellInfo);
1959 /*-- 13.10.2003 16:43:27---------------------------------------------------
1961 -----------------------------------------------------------------------*/
1962 void ImpEditEngine::StartSpelling(EditView& rEditView, sal_Bool bMultipleDoc)
1964 DBG_ASSERT(!pSpellInfo, "pSpellInfo already set?");
1965 pSpellInfo = new SpellInfo;
1966 pSpellInfo->bMultipleDoc = bMultipleDoc;
1967 rEditView.pImpEditView->SetEditSelection( aEditDoc.GetStartPaM() );
1968 EditSelection aCurSel( rEditView.pImpEditView->GetEditSelection() );
1969 pSpellInfo->aSpellStart = CreateEPaM( SelectWord( aCurSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD ).Min() );
1971 /*-- 13.10.2003 16:43:27---------------------------------------------------
1972 Search for the next wrong word within the given selection
1973 -----------------------------------------------------------------------*/
1974 Reference< XSpellAlternatives > ImpEditEngine::ImpFindNextError(EditSelection& rSelection)
1976 /* ContentNode* pLastNode = */ aEditDoc.SaveGetObject( (aEditDoc.Count()-1) );
1977 EditSelection aCurSel( rSelection.Min() );
1979 String aWord;
1980 Reference< XSpellAlternatives > xSpellAlt;
1981 Sequence< PropertyValue > aEmptySeq;
1982 while (!xSpellAlt.is())
1984 //check if the end of the selection has been reached
1986 EPaM aEPaM( CreateEPaM( aCurSel.Max() ) );
1987 if ( !( aEPaM < CreateEPaM( rSelection.Max()) ) )
1988 break;
1991 aCurSel = SelectWord( aCurSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
1992 aWord = GetSelected( aCurSel );
1994 // Wenn Punkt dahinter, muss dieser mit uebergeben werden !
1995 // Falls Abkuerzung...
1996 if ( aWord.Len() && ( aCurSel.Max().GetIndex() < aCurSel.Max().GetNode()->Len() ) )
1998 sal_Unicode cNext = aCurSel.Max().GetNode()->GetChar( aCurSel.Max().GetIndex() );
1999 if ( cNext == '.' )
2001 aCurSel.Max().GetIndex()++;
2002 aWord += cNext;
2006 if ( aWord.Len() > 0 )
2007 xSpellAlt = xSpeller->spell( aWord, GetLanguage( aCurSel.Max() ), aEmptySeq );
2009 if ( !xSpellAlt.is() )
2010 aCurSel = WordRight( aCurSel.Min(), ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
2011 else
2013 pSpellInfo->eState = EE_SPELL_ERRORFOUND;
2014 rSelection = aCurSel;
2017 return xSpellAlt;
2019 /*-- 13.10.2003 16:43:27---------------------------------------------------
2021 -----------------------------------------------------------------------*/
2022 bool ImpEditEngine::SpellSentence(EditView& rEditView, ::svx::SpellPortions& rToFill, bool /*bIsGrammarChecking*/ )
2024 #ifdef SVX_LIGHT
2025 #else
2026 bool bRet = false;
2027 //the pSpellInfo has to be created on demand
2028 if(!pSpellInfo)
2030 pSpellInfo = new SpellInfo;
2031 pSpellInfo->bMultipleDoc = sal_True;
2032 rEditView.pImpEditView->SetEditSelection( aEditDoc.GetStartPaM() );
2033 EditSelection aCurSel( rEditView.pImpEditView->GetEditSelection() );
2034 pSpellInfo->aSpellStart = CreateEPaM( SelectWord( aCurSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD ).Min() );
2036 DBG_ASSERT( xSpeller.is(), "Kein Speller gesetzt!" );
2037 pSpellInfo->aLastSpellPortions.clear();
2038 pSpellInfo->aLastSpellContentSelections.clear();
2039 rToFill.clear();
2040 EditSelection aCurSel( rEditView.pImpEditView->GetEditSelection() );
2041 //if no selection previously exists the range is extended to the end of the object
2042 if(aCurSel.Min() == aCurSel.Max())
2044 ContentNode* pLastNode = aEditDoc.SaveGetObject( aEditDoc.Count()-1);
2045 aCurSel.Max() = EditPaM(pLastNode, pLastNode->Len());
2047 Reference< XSpellAlternatives > xAlt = ImpFindNextError(aCurSel);
2048 if(xAlt.is())
2050 bRet = true;
2051 //find the sentence boundaries
2052 EditSelection aSentencePaM = SelectSentence(aCurSel);
2053 //make sure that the sentence is never smaller than the error range!
2054 if(aSentencePaM.Max().GetIndex() < aCurSel.Max().GetIndex())
2055 aSentencePaM.Max() = aCurSel.Max();
2056 //add the portion preceeding the error
2057 EditSelection aStartSelection(aSentencePaM.Min(), aCurSel.Min());
2058 if(aStartSelection.HasRange())
2059 AddPortionIterated(rEditView, aStartSelection, 0, rToFill);
2060 //add the error portion
2061 AddPortionIterated(rEditView, aCurSel, xAlt, rToFill);
2062 //find the end of the sentence
2063 //search for all errors in the rest of the sentence and add all the portions
2066 EditSelection aNextSel = EditSelection(aCurSel.Max(), aSentencePaM.Max());
2067 xAlt = ImpFindNextError(aNextSel);
2068 if(xAlt.is())
2070 //add the part between the previous and the current error
2071 AddPortionIterated(rEditView, EditSelection(aCurSel.Max(), aNextSel.Min()), 0, rToFill);
2072 //add the current error
2073 AddPortionIterated(rEditView, aNextSel, xAlt, rToFill);
2075 else
2076 AddPortionIterated(rEditView, EditSelection(aCurSel.Max(), aSentencePaM.Max()), xAlt, rToFill);
2077 aCurSel = aNextSel;
2079 while( xAlt.is() );
2080 //set the selection to the end of the current sentence
2081 rEditView.pImpEditView->SetEditSelection(aSentencePaM.Max());
2083 #endif
2084 return bRet;
2087 /*-- 15.10.2003 16:09:12---------------------------------------------------
2088 adds one portion to the SpellPortions
2089 -----------------------------------------------------------------------*/
2090 void ImpEditEngine::AddPortion(
2091 const EditSelection rSel,
2092 uno::Reference< XSpellAlternatives > xAlt,
2093 ::svx::SpellPortions& rToFill,
2094 bool bIsField)
2096 #ifdef SVX_LIGHT
2097 #else
2098 if(rSel.HasRange())
2100 svx::SpellPortion aPortion;
2101 aPortion.sText = GetSelected( rSel );
2102 aPortion.eLanguage = GetLanguage( rSel.Min() );
2103 aPortion.xAlternatives = xAlt;
2104 aPortion.bIsField = bIsField;
2105 rToFill.push_back(aPortion);
2107 //save the spelled portions for later use
2108 pSpellInfo->aLastSpellPortions.push_back(aPortion);
2109 pSpellInfo->aLastSpellContentSelections.push_back(rSel);
2112 #endif
2115 /*-- 15.10.2003 16:07:47---------------------------------------------------
2116 adds one or more portions of text to the SpellPortions depending on language changes
2117 -----------------------------------------------------------------------*/
2118 void ImpEditEngine::AddPortionIterated(
2119 EditView& rEditView,
2120 const EditSelection rSel,
2121 Reference< XSpellAlternatives > xAlt,
2122 ::svx::SpellPortions& rToFill)
2124 #ifdef SVX_LIGHT
2125 #else
2126 if(rSel.Min() != rSel.Max())
2128 if(xAlt.is())
2130 AddPortion(rSel, xAlt, rToFill, false);
2132 else
2134 //iterate and search for language attribute changes
2135 //save the start and end positions
2136 bool bTest = rSel.Min().GetIndex() <= rSel.Max().GetIndex();
2137 EditPaM aStart(bTest ? rSel.Min() : rSel.Max());
2138 EditPaM aEnd(bTest ? rSel.Max() : rSel.Min());
2139 //iterate over the text to find changes in language
2140 //set the mark equal to the point
2141 EditPaM aCursor(aStart);
2142 rEditView.pImpEditView->SetEditSelection( aCursor );
2143 LanguageType eStartLanguage = GetLanguage( aCursor );
2144 //search for a field attribute at the beginning - only the end position
2145 //of this field is kept to end a portion at that position
2146 const EditCharAttrib* pFieldAttr = aCursor.GetNode()->GetCharAttribs().
2147 FindFeature( aCursor.GetIndex() );
2148 bool bIsField = pFieldAttr &&
2149 pFieldAttr->GetStart() == aCursor.GetIndex() &&
2150 pFieldAttr->GetStart() != pFieldAttr->GetEnd() &&
2151 pFieldAttr->Which() == EE_FEATURE_FIELD;
2152 USHORT nEndField = bIsField ? pFieldAttr->GetEnd() : USHRT_MAX;
2153 bool bIsEndField = false;
2156 aCursor = CursorRight( aCursor);
2157 //determine whether a field and has been reached
2158 bIsEndField = nEndField == aCursor.GetIndex();
2159 //search for a new field attribute
2160 EditCharAttrib* _pFieldAttr = aCursor.GetNode()->GetCharAttribs().
2161 FindFeature( aCursor.GetIndex() );
2162 bIsField = _pFieldAttr &&
2163 _pFieldAttr->GetStart() == aCursor.GetIndex() &&
2164 _pFieldAttr->GetStart() != _pFieldAttr->GetEnd() &&
2165 _pFieldAttr->Which() == EE_FEATURE_FIELD;
2166 //on every new field move the end position
2167 if(bIsField)
2168 nEndField = bIsField ? _pFieldAttr->GetEnd() : USHRT_MAX;
2170 LanguageType eCurLanguage = GetLanguage( aCursor );
2171 if(eCurLanguage != eStartLanguage || bIsField || bIsEndField)
2173 eStartLanguage = eCurLanguage;
2174 //go one step back - the cursor currently selects the first character
2175 //with a different language
2176 //create a selection from start to the current Cursor
2177 EditSelection aSelection(aStart, aCursor);
2178 AddPortion(aSelection, xAlt, rToFill, bIsEndField);
2179 aStart = aCursor;
2182 while(aCursor.GetIndex() < aEnd.GetIndex());
2183 EditSelection aSelection(aStart, aCursor);
2184 AddPortion(aSelection, xAlt, rToFill, bIsField);
2187 #endif
2190 /*-- 13.10.2003 16:43:33---------------------------------------------------
2192 -----------------------------------------------------------------------*/
2193 void ImpEditEngine::ApplyChangedSentence(EditView& rEditView, const ::svx::SpellPortions& rNewPortions, bool /*bIsGrammarChecking*/ )
2195 #ifdef SVX_LIGHT
2196 #else
2197 DBG_ASSERT(pSpellInfo, "pSpellInfo not initialized");
2198 if(pSpellInfo)
2200 UndoActionStart( EDITUNDO_INSERT );
2201 if(pSpellInfo->aLastSpellPortions.size() == rNewPortions.size())
2203 //the simple case: the same number of elements on both sides
2204 //each changed element has to be applied to the corresponding source element
2205 svx::SpellPortions::const_iterator aCurrentNewPortion = rNewPortions.end();
2206 svx::SpellPortions::const_iterator aCurrentOldPortion = pSpellInfo->aLastSpellPortions.end();
2207 SpellContentSelections::const_iterator aCurrentOldPosition = pSpellInfo->aLastSpellContentSelections.end();
2208 bool bSetToEnd = false;
2211 --aCurrentNewPortion;
2212 --aCurrentOldPortion;
2213 --aCurrentOldPosition;
2214 //set the cursor to the end of the sentence - necessary to
2215 //resume there at the next step
2216 if(!bSetToEnd)
2218 bSetToEnd = true;
2219 rEditView.pImpEditView->SetEditSelection( aCurrentOldPosition->Max() );
2222 USHORT nScriptType = GetI18NScriptTypeOfLanguage( aCurrentNewPortion->eLanguage );
2223 // LanguageType eTextLanguage = GetLanguage( aCurrentOldPosition->Min() );
2225 USHORT nLangWhichId = EE_CHAR_LANGUAGE;
2226 switch(nScriptType)
2228 case SCRIPTTYPE_ASIAN : nLangWhichId = EE_CHAR_LANGUAGE_CJK; break;
2229 case SCRIPTTYPE_COMPLEX : nLangWhichId = EE_CHAR_LANGUAGE_CTL; break;
2231 if(aCurrentNewPortion->sText != aCurrentOldPortion->sText)
2233 //change text and apply language
2234 SfxItemSet aSet( aEditDoc.GetItemPool(), nLangWhichId, nLangWhichId);
2235 aSet.Put(SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId));
2236 SetAttribs( *aCurrentOldPosition, aSet );
2237 ImpInsertText( *aCurrentOldPosition, aCurrentNewPortion->sText );
2239 else if(aCurrentNewPortion->eLanguage != aCurrentOldPortion->eLanguage)
2241 //apply language
2242 SfxItemSet aSet( aEditDoc.GetItemPool(), nLangWhichId, nLangWhichId);
2243 aSet.Put(SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId));
2244 SetAttribs( *aCurrentOldPosition, aSet );
2246 if(aCurrentNewPortion == rNewPortions.begin())
2247 break;
2249 while(aCurrentNewPortion != rNewPortions.begin());
2251 else
2253 //select the complete sentence
2254 SpellContentSelections::const_iterator aCurrentEndPosition = pSpellInfo->aLastSpellContentSelections.end();
2255 --aCurrentEndPosition;
2256 SpellContentSelections::const_iterator aCurrentStartPosition = pSpellInfo->aLastSpellContentSelections.begin();
2257 EditSelection aAllSentence(aCurrentStartPosition->Min(), aCurrentEndPosition->Max());
2259 //delete the sentence completely
2260 ImpDeleteSelection( aAllSentence );
2261 svx::SpellPortions::const_iterator aCurrentNewPortion = rNewPortions.begin();
2262 EditPaM aCurrentPaM = aAllSentence.Min();
2263 while(aCurrentNewPortion != rNewPortions.end())
2265 //set the language attribute
2266 LanguageType eCurLanguage = GetLanguage( aCurrentPaM );
2267 if(eCurLanguage != aCurrentNewPortion->eLanguage)
2269 USHORT nScriptType = GetI18NScriptTypeOfLanguage( aCurrentNewPortion->eLanguage );
2270 USHORT nLangWhichId = EE_CHAR_LANGUAGE;
2271 switch(nScriptType)
2273 case SCRIPTTYPE_ASIAN : nLangWhichId = EE_CHAR_LANGUAGE_CJK; break;
2274 case SCRIPTTYPE_COMPLEX : nLangWhichId = EE_CHAR_LANGUAGE_CTL; break;
2276 SfxItemSet aSet( aEditDoc.GetItemPool(), nLangWhichId, nLangWhichId);
2277 aSet.Put(SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId));
2278 SetAttribs( aCurrentPaM, aSet );
2280 //insert the new string and set the cursor to the end of the inserted string
2281 aCurrentPaM = ImpInsertText( aCurrentPaM , aCurrentNewPortion->sText );
2282 ++aCurrentNewPortion;
2285 UndoActionEnd( EDITUNDO_INSERT );
2287 FormatAndUpdate();
2288 aEditDoc.SetModified(TRUE);
2289 #endif
2291 /*-- 08.09.2008 11:33:02---------------------------------------------------
2293 -----------------------------------------------------------------------*/
2294 void ImpEditEngine::PutSpellingToSentenceStart( EditView& rEditView )
2296 #ifdef SVX_LIGHT
2297 #else
2298 if( pSpellInfo && pSpellInfo->aLastSpellContentSelections.size() )
2300 rEditView.pImpEditView->SetEditSelection( pSpellInfo->aLastSpellContentSelections.begin()->Min() );
2303 #endif
2307 void ImpEditEngine::DoOnlineSpelling( ContentNode* pThisNodeOnly, sal_Bool bSpellAtCursorPos, sal_Bool bInteruptable )
2309 #ifndef SVX_LIGHT
2311 Er wird ueber alle Absaetze iteriert, nur Absaetze mit invalidierter
2312 WrongList werden geprueft...
2314 Es werden alle Woerter im invalidierten Bereich geprueft.
2315 Ist ein Wort falsch, aber noch nicht in der WrongList, oder umgekehrt,
2316 wird der Bereich des Wortes invalidiert
2317 ( kein Invalidate, sondern wenn nur Uebergaenge von richtig=>falsch,
2318 einfaches Paint, bei Uebergaengen von falsch=>richtig mit VDev
2319 ueberplaetten )
2322 if ( !xSpeller.is() )
2323 return;
2325 EditPaM aCursorPos;
2326 if( pActiveView && !bSpellAtCursorPos )
2328 DBG_CHKOBJ( pActiveView, EditView, 0 );
2329 aCursorPos = pActiveView->pImpEditView->GetEditSelection().Max();
2331 sal_Bool bRestartTimer = sal_False;
2333 ContentNode* pLastNode = aEditDoc.SaveGetObject( aEditDoc.Count() - 1 );
2334 sal_uInt16 nNodes = GetEditDoc().Count();
2335 sal_uInt16 nInvalids = 0;
2336 Sequence< PropertyValue > aEmptySeq;
2337 for ( sal_uInt16 n = 0; n < nNodes; n++ )
2339 ContentNode* pNode = GetEditDoc().GetObject( n );
2340 if ( pThisNodeOnly )
2341 pNode = pThisNodeOnly;
2343 if ( pNode->GetWrongList()->IsInvalid() )
2345 WrongList* pWrongList = pNode->GetWrongList();
2346 sal_uInt16 nInvStart = pWrongList->GetInvalidStart();
2347 sal_uInt16 nInvEnd = pWrongList->GetInvalidEnd();
2349 sal_uInt16 nWrongs = 0; // Auch im Absatz mal die Kontrolle abgeben...
2350 // sal_Bool bStop = sal_False;
2352 sal_uInt16 nPaintFrom = 0xFFFF, nPaintTo = 0;
2353 sal_Bool bSimpleRepaint = sal_True;
2355 pWrongList->SetValid();
2357 EditPaM aPaM( pNode, nInvStart );
2358 EditSelection aSel( aPaM, aPaM );
2359 while ( ( aSel.Max().GetNode() == pNode ) /* && !bStop */ )
2361 if ( ( aSel.Min().GetIndex() > nInvEnd )
2362 || ( ( aSel.Max().GetNode() == pLastNode ) && ( aSel.Max().GetIndex() >= pLastNode->Len() ) ) )
2363 break; // Dokument- oder Ungueltigkeitsbereich-Ende
2365 aSel = SelectWord( aSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
2366 String aWord( GetSelected( aSel ) );
2367 // Wenn Punkt dahinter, muss dieser mit uebergeben werden !
2368 // Falls Abkuerzung...
2369 sal_Bool bDottAdded = sal_False;
2370 if ( aSel.Max().GetIndex() < aSel.Max().GetNode()->Len() )
2372 sal_Unicode cNext = aSel.Max().GetNode()->GetChar( aSel.Max().GetIndex() );
2373 if ( cNext == '.' )
2375 aSel.Max().GetIndex()++;
2376 aWord += cNext;
2377 bDottAdded = sal_True;
2382 sal_Bool bChanged = sal_False;
2383 if ( aWord.Len() > 0 )
2385 sal_uInt16 nWStart = aSel.Min().GetIndex();
2386 sal_uInt16 nWEnd= aSel.Max().GetIndex();
2387 if ( !xSpeller->isValid( aWord, GetLanguage( EditPaM( aSel.Min().GetNode(), nWStart+1 ) ), aEmptySeq ) )
2389 // Pruefen, ob schon richtig markiert...
2390 nWrongs++;
2391 // Nur bei SimpleRepaint stoppen, sonst zu oft VDev
2392 // if ( ( nWrongs > 8 ) && bSimpleRepaint )
2393 // {
2394 // bStop = sal_True;
2395 // pWrongList->MarkInvalid( aSel.Max().GetIndex(), nInvEnd );
2396 // }
2397 sal_uInt16 nXEnd = bDottAdded ? nWEnd -1 : nWEnd;
2398 if ( !pWrongList->HasWrong( nWStart, nXEnd ) )
2400 // Wort als falsch markieren...
2401 // Aber nur, wenn nicht an Cursor-Position...
2402 sal_Bool bCursorPos = sal_False;
2403 if ( aCursorPos.GetNode() == pNode )
2405 if ( ( nWStart <= aCursorPos.GetIndex() ) && nWEnd >= aCursorPos.GetIndex() )
2406 bCursorPos = sal_True;
2408 if ( bCursorPos )
2410 // Dann weiter als ungueltig markieren...
2411 pWrongList->GetInvalidStart() = nWStart;
2412 pWrongList->GetInvalidEnd() = nWEnd;
2413 bRestartTimer = sal_True;
2415 else
2417 // Es kann sein, dass die Wrongs in der Liste nicht
2418 // genau ueber Woerter aufgespannt sind, weil die
2419 // WordDelimiters beim Expandieren nicht ausgewrtet werden.
2420 pWrongList->InsertWrong( nWStart, nXEnd, sal_True );
2421 bChanged = sal_True;
2425 else
2427 // Pruefen, ob nicht als als falsch markiert....
2428 if ( pWrongList->HasAnyWrong( nWStart, nWEnd ) )
2430 pWrongList->ClearWrongs( nWStart, nWEnd, pNode );
2431 bSimpleRepaint = sal_False;
2432 bChanged = sal_True;
2435 if ( bChanged )
2437 if ( nPaintFrom == 0xFFFF )
2438 nPaintFrom = nWStart;
2439 nPaintTo = nWEnd;
2443 EditPaM aLastEnd( aSel.Max() );
2444 aSel = WordRight( aSel.Max(), ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
2445 if ( bChanged && ( aSel.Min().GetNode() == pNode ) &&
2446 ( ( aSel.Min().GetIndex()-aLastEnd.GetIndex() > 1 ) ) )
2448 // Wenn zwei Worte durch mehr Zeichen als ein Blank getrennt
2449 // sind, kann es passieren, dass beim Aufsplitten eines Wrongs
2450 // der Start den zweiten Wortes vor dem tatsaechlich Wort liegt
2451 pWrongList->ClearWrongs( aLastEnd.GetIndex(), aSel.Min().GetIndex(), pNode );
2455 // Invalidieren?
2456 if ( ( nPaintFrom != 0xFFFF ) )
2458 aStatus.GetStatusWord() |= EE_STAT_WRONGWORDCHANGED;
2459 CallStatusHdl();
2461 if ( aEditViews.Count() )
2463 // Bei SimpleRepaint wuerde ein uebermalen ohne VDev reichen,
2464 // aber dann muesste ich ueber alle Views, Intersecten,
2465 // Clippen, ...
2466 // Lohnt wahrscheinlich nicht.
2467 EditPaM aStartPaM( pNode, nPaintFrom );
2468 EditPaM aEndPaM( pNode, nPaintTo );
2469 Rectangle aStartCursor( PaMtoEditCursor( aStartPaM ) );
2470 Rectangle aEndCursor( PaMtoEditCursor( aEndPaM ) );
2471 DBG_ASSERT( aInvalidRec.IsEmpty(), "InvalidRect gesetzt!" );
2472 aInvalidRec.Left() = 0;
2473 aInvalidRec.Right() = GetPaperSize().Width();
2474 aInvalidRec.Top() = aStartCursor.Top();
2475 aInvalidRec.Bottom() = aEndCursor.Bottom();
2476 if ( pActiveView && pActiveView->HasSelection() )
2478 // Dann darf nicht ueber VDev ausgegeben werden
2479 UpdateViews( NULL );
2481 else if ( bSimpleRepaint )
2483 for ( sal_uInt16 nView = 0; nView < aEditViews.Count(); nView++ )
2485 EditView* pView = aEditViews[nView];
2486 Rectangle aClipRec( aInvalidRec );
2487 aClipRec.Intersection( pView->GetVisArea() );
2488 if ( !aClipRec.IsEmpty() )
2490 // in Fensterkoordinaten umwandeln....
2491 aClipRec.SetPos( pView->pImpEditView->GetWindowPos( aClipRec.TopLeft() ) );
2492 // Wenn Selektion, dann VDev...
2493 Paint( pView->pImpEditView, aClipRec, pView->HasSelection() );
2497 else
2499 UpdateViews( pActiveView );
2501 aInvalidRec = Rectangle();
2504 // Nach zwei korrigierten Nodes die Kontrolle abgeben...
2505 nInvalids++;
2506 if ( bInteruptable && ( nInvalids >= 2 ) )
2508 bRestartTimer = sal_True;
2509 break;
2513 if ( pThisNodeOnly )
2514 break;
2516 if ( bRestartTimer )
2517 aOnlineSpellTimer.Start();
2518 #endif // !SVX_LIGHT
2522 EESpellState ImpEditEngine::HasSpellErrors()
2524 DBG_ASSERT( xSpeller.is(), "Kein Speller gesetzt!" );
2526 #ifndef SVX_LIGHT
2527 ContentNode* pLastNode = aEditDoc.SaveGetObject( aEditDoc.Count() - 1 );
2528 EditSelection aCurSel( aEditDoc.GetStartPaM() );
2530 String aWord;
2531 Reference< XSpellAlternatives > xSpellAlt;
2532 Sequence< PropertyValue > aEmptySeq;
2533 while ( !xSpellAlt.is() )
2535 if ( ( aCurSel.Max().GetNode() == pLastNode ) &&
2536 ( aCurSel.Max().GetIndex() >= pLastNode->Len() ) )
2538 return EE_SPELL_OK;
2541 aCurSel = SelectWord( aCurSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
2542 aWord = GetSelected( aCurSel );
2543 if ( aWord.Len() > 0 )
2545 LanguageType eLang = GetLanguage( aCurSel.Max() );
2546 SvxSpellWrapper::CheckSpellLang( xSpeller, eLang );
2547 xSpellAlt = xSpeller->spell( aWord, eLang, aEmptySeq );
2549 aCurSel = WordRight( aCurSel.Max(), ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
2551 #endif
2553 return EE_SPELL_ERRORFOUND;
2556 EESpellState ImpEditEngine::StartThesaurus( EditView* pEditView )
2558 #ifndef SVX_LIGHT
2559 EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() );
2560 if ( !aCurSel.HasRange() )
2561 aCurSel = SelectWord( aCurSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
2562 String aWord( GetSelected( aCurSel ) );
2564 Reference< XThesaurus > xThes( SvxGetThesaurus() );
2565 if (!xThes.is())
2566 return EE_SPELL_ERRORFOUND;
2568 SvxThesaurusDialog aDialog( pEditView->GetWindow(), xThes, aWord, GetLanguage( aCurSel.Max() ) );
2570 if ( aDialog.Execute() == RET_OK )
2572 // Wort ersetzen...
2573 pEditView->pImpEditView->DrawSelection();
2574 pEditView->pImpEditView->SetEditSelection( aCurSel );
2575 pEditView->pImpEditView->DrawSelection();
2576 pEditView->InsertText( aDialog.GetWord() );
2577 pEditView->ShowCursor( sal_True, sal_False );
2580 return EE_SPELL_OK;
2581 #else
2582 return EE_SPELL_NOSPELLER;
2583 #endif
2586 sal_uInt16 ImpEditEngine::StartSearchAndReplace( EditView* pEditView, const SvxSearchItem& rSearchItem )
2588 sal_uInt16 nFound = 0;
2590 #ifndef SVX_LIGHT
2591 EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() );
2593 // FIND_ALL ohne Mehrfachselektion nicht moeglich.
2594 if ( ( rSearchItem.GetCommand() == SVX_SEARCHCMD_FIND ) ||
2595 ( rSearchItem.GetCommand() == SVX_SEARCHCMD_FIND_ALL ) )
2597 if ( Search( rSearchItem, pEditView ) )
2598 nFound++;
2600 else if ( rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE )
2602 // Das Wort ist selektiert, wenn der Anwender die Selektion
2603 // nicht zwischendurch manipuliert:
2604 if ( aCurSel.HasRange() )
2606 pEditView->InsertText( rSearchItem.GetReplaceString() );
2607 nFound = 1;
2609 else
2610 if( Search( rSearchItem, pEditView ) )
2611 nFound = 1;
2613 else if ( rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE_ALL )
2615 // Der Writer ersetzt alle, vorn Anfang bis Ende...
2616 SvxSearchItem aTmpItem( rSearchItem );
2617 aTmpItem.SetBackward( sal_False );
2619 pEditView->pImpEditView->DrawSelection();
2621 aCurSel.Adjust( aEditDoc );
2622 EditPaM aStartPaM = aTmpItem.GetSelection() ? aCurSel.Min() : aEditDoc.GetStartPaM();
2623 EditSelection aFoundSel( aCurSel.Max() );
2624 sal_Bool bFound = ImpSearch( aTmpItem, aCurSel, aStartPaM, aFoundSel );
2625 if ( bFound )
2626 UndoActionStart( EDITUNDO_REPLACEALL );
2627 while ( bFound )
2629 nFound++;
2630 aStartPaM = ImpInsertText( aFoundSel, rSearchItem.GetReplaceString() );
2631 bFound = ImpSearch( aTmpItem, aCurSel, aStartPaM, aFoundSel );
2633 if ( nFound )
2635 EditPaM aNewPaM( aFoundSel.Max() );
2636 if ( aNewPaM.GetIndex() > aNewPaM.GetNode()->Len() )
2637 aNewPaM.GetIndex() = aNewPaM.GetNode()->Len();
2638 pEditView->pImpEditView->SetEditSelection( aNewPaM );
2639 FormatAndUpdate( pEditView );
2640 UndoActionEnd( EDITUNDO_REPLACEALL );
2642 else
2644 pEditView->pImpEditView->DrawSelection();
2645 pEditView->ShowCursor( sal_True, sal_False );
2648 #endif // !SVX_LIGHT
2649 return nFound;
2652 BOOL ImpEditEngine::Search( const SvxSearchItem& rSearchItem, EditView* pEditView )
2654 EditSelection aSel( pEditView->pImpEditView->GetEditSelection() );
2655 aSel.Adjust( aEditDoc );
2656 EditPaM aStartPaM( aSel.Max() );
2657 if ( rSearchItem.GetSelection() && !rSearchItem.GetBackward() )
2658 aStartPaM = aSel.Min();
2660 EditSelection aFoundSel;
2661 BOOL bFound = ImpSearch( rSearchItem, aSel, aStartPaM, aFoundSel );
2662 if ( bFound && ( aFoundSel == aSel ) ) // Bei Rueckwaetssuche
2664 aStartPaM = aSel.Min();
2665 bFound = ImpSearch( rSearchItem, aSel, aStartPaM, aFoundSel );
2668 pEditView->pImpEditView->DrawSelection();
2669 if ( bFound )
2671 // Erstmal das Min einstellen, damit das ganze Wort in den sichtbaren Bereich kommt.
2672 pEditView->pImpEditView->SetEditSelection( aFoundSel.Min() );
2673 pEditView->ShowCursor( TRUE, FALSE );
2674 pEditView->pImpEditView->SetEditSelection( aFoundSel );
2676 else
2677 pEditView->pImpEditView->SetEditSelection( aSel.Max() );
2679 pEditView->pImpEditView->DrawSelection();
2680 pEditView->ShowCursor( TRUE, FALSE );
2681 return bFound;
2684 sal_Bool ImpEditEngine::ImpSearch( const SvxSearchItem& rSearchItem,
2685 const EditSelection& rSearchSelection, const EditPaM& rStartPos, EditSelection& rFoundSel )
2687 #ifndef SVX_LIGHT
2688 util::SearchOptions aSearchOptions( rSearchItem.GetSearchOptions() );
2689 aSearchOptions.Locale = GetLocale( rStartPos );
2691 sal_Bool bBack = rSearchItem.GetBackward();
2692 sal_Bool bSearchInSelection = rSearchItem.GetSelection();
2693 sal_uInt16 nStartNode = aEditDoc.GetPos( rStartPos.GetNode() );
2694 sal_uInt16 nEndNode;
2695 if ( bSearchInSelection )
2697 nEndNode = aEditDoc.GetPos( bBack ? rSearchSelection.Min().GetNode() : rSearchSelection.Max().GetNode() );
2699 else
2701 nEndNode = bBack ? 0 : aEditDoc.Count()-1;
2704 utl::TextSearch aSearcher( aSearchOptions );
2706 // ueber die Absaetze iterieren...
2707 for ( sal_uInt16 nNode = nStartNode;
2708 bBack ? ( nNode >= nEndNode ) : ( nNode <= nEndNode) ;
2709 bBack ? nNode-- : nNode++ )
2711 // Bei rueckwaertsuche, wenn nEndNode = 0:
2712 if ( nNode >= 0xFFFF )
2713 return sal_False;
2715 ContentNode* pNode = aEditDoc.GetObject( nNode );
2717 sal_uInt16 nStartPos = 0;
2718 sal_uInt16 nEndPos = pNode->Len();
2719 if ( nNode == nStartNode )
2721 if ( bBack )
2722 nEndPos = rStartPos.GetIndex();
2723 else
2724 nStartPos = rStartPos.GetIndex();
2726 if ( ( nNode == nEndNode ) && bSearchInSelection )
2728 if ( bBack )
2729 nStartPos = rSearchSelection.Min().GetIndex();
2730 else
2731 nEndPos = rSearchSelection.Max().GetIndex();
2734 // Suchen...
2735 XubString aParaStr( GetEditDoc().GetParaAsString( pNode ) );
2736 bool bFound = false;
2737 if ( bBack )
2739 SwapUSHORTs( nStartPos, nEndPos );
2740 bFound = aSearcher.SearchBkwrd( aParaStr, &nStartPos, &nEndPos);
2742 else
2743 bFound = aSearcher.SearchFrwrd( aParaStr, &nStartPos, &nEndPos);
2745 if ( bFound )
2747 rFoundSel.Min().SetNode( pNode );
2748 rFoundSel.Min().SetIndex( nStartPos );
2749 rFoundSel.Max().SetNode( pNode );
2750 rFoundSel.Max().SetIndex( nEndPos );
2751 return sal_True;
2754 #endif // !SVX_LIGHT
2755 return sal_False;
2758 sal_Bool ImpEditEngine::HasText( const SvxSearchItem& rSearchItem )
2760 #ifndef SVX_LIGHT
2761 SvxSearchItem aTmpItem( rSearchItem );
2762 aTmpItem.SetBackward( sal_False );
2763 aTmpItem.SetSelection( sal_False );
2765 EditPaM aStartPaM( aEditDoc.GetStartPaM() );
2766 EditSelection aDummySel( aStartPaM );
2767 EditSelection aFoundSel;
2768 return ImpSearch( aTmpItem, aDummySel, aStartPaM, aFoundSel );
2769 #else
2770 return sal_False;
2771 #endif
2774 void ImpEditEngine::SetAutoCompleteText( const String& rStr, sal_Bool bClearTipWindow )
2776 #ifndef SVX_LIGHT
2777 aAutoCompleteText = rStr;
2778 if ( bClearTipWindow && pActiveView )
2779 Help::ShowQuickHelp( pActiveView->GetWindow(), Rectangle(), String(), 0 );
2780 #endif // !SVX_LIGHT
2783 EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, sal_Int32 nTransliterationMode )
2785 EditSelection aSel( rSelection );
2786 aSel.Adjust( aEditDoc );
2788 if ( !aSel.HasRange() )
2789 aSel = SelectWord( aSel );
2791 EditSelection aNewSel( aSel );
2793 USHORT nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
2794 USHORT nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
2796 BOOL bChanges = FALSE;
2797 BOOL bLenChanged = FALSE;
2798 EditUndoTransliteration* pUndo = NULL;
2800 utl::TransliterationWrapper aTranslitarationWrapper( ::comphelper::getProcessServiceFactory(), nTransliterationMode );
2801 BOOL bConsiderLanguage = aTranslitarationWrapper.needLanguageForTheMode();
2803 for ( USHORT nNode = nStartNode; nNode <= nEndNode; nNode++ )
2805 ContentNode* pNode = aEditDoc.GetObject( nNode );
2806 xub_StrLen nStartPos = 0;
2807 xub_StrLen nEndPos = pNode->Len();
2808 if ( nNode == nStartNode )
2809 nStartPos = aSel.Min().GetIndex();
2810 if ( nNode == nEndNode ) // kann auch == nStart sein!
2811 nEndPos = aSel.Max().GetIndex();
2813 USHORT nCurrentStart = nStartPos;
2814 USHORT nCurrentEnd = nEndPos;
2815 sal_uInt16 nLanguage = LANGUAGE_SYSTEM;
2819 if ( bConsiderLanguage )
2821 nLanguage = GetLanguage( EditPaM( pNode, nCurrentStart+1 ), &nCurrentEnd );
2822 if ( nCurrentEnd > nEndPos )
2823 nCurrentEnd = nEndPos;
2826 xub_StrLen nLen = nCurrentEnd - nCurrentStart;
2828 Sequence <sal_Int32> aOffsets;
2829 String aNewText( aTranslitarationWrapper.transliterate( *pNode, nLanguage, nCurrentStart, nLen, &aOffsets ) );
2831 if( ( nLen != aNewText.Len() ) || !pNode->Equals( aNewText, nCurrentStart, nLen ) )
2833 bChanges = TRUE;
2834 if ( nLen != aNewText.Len() )
2835 bLenChanged = TRUE;
2837 #ifndef SVX_LIGHT
2838 // Create UndoAction on Demand....
2839 if ( !pUndo && IsUndoEnabled() && !IsInUndo() )
2841 ESelection aESel( CreateESel( aSel ) );
2842 pUndo = new EditUndoTransliteration( this, aESel, nTransliterationMode );
2844 if ( ( nStartNode == nEndNode ) && !aSel.Min().GetNode()->GetCharAttribs().HasAttrib( aSel.Min().GetIndex(), aSel.Max().GetIndex() ) )
2845 pUndo->SetText( aSel.Min().GetNode()->Copy( aSel.Min().GetIndex(), aSel.Max().GetIndex()-aSel.Min().GetIndex() ) );
2846 else
2847 pUndo->SetText( CreateBinTextObject( aSel, NULL ) );
2849 #endif
2851 // Change text without loosing the attributes
2852 USHORT nCharsAfterTransliteration =
2853 sal::static_int_cast< USHORT >(aOffsets.getLength());
2854 const sal_Int32* pOffsets = aOffsets.getConstArray();
2855 short nDiffs = 0;
2856 for ( USHORT n = 0; n < nCharsAfterTransliteration; n++ )
2858 USHORT nCurrentPos = nCurrentStart+n;
2859 sal_Int32 nDiff = (nCurrentPos-nDiffs) - pOffsets[n];
2861 if ( !nDiff )
2863 DBG_ASSERT( nCurrentPos < pNode->Len(), "TransliterateText - String smaller than expected!" );
2864 pNode->SetChar( nCurrentPos, aNewText.GetChar(n) );
2866 else if ( nDiff < 0 )
2868 // Replace first char, delete the rest...
2869 DBG_ASSERT( nCurrentPos < pNode->Len(), "TransliterateText - String smaller than expected!" );
2870 pNode->SetChar( nCurrentPos, aNewText.GetChar(n) );
2872 DBG_ASSERT( (nCurrentPos+1) < pNode->Len(), "TransliterateText - String smaller than expected!" );
2873 GetEditDoc().RemoveChars( EditPaM( pNode, nCurrentPos+1 ), sal::static_int_cast< USHORT >(-nDiff) );
2875 else
2877 DBG_ASSERT( nDiff == 1, "TransliterateText - Diff other than expected! But should work..." );
2878 GetEditDoc().InsertText( EditPaM( pNode, nCurrentPos ), aNewText.GetChar(n) );
2881 nDiffs = sal::static_int_cast< short >(nDiffs + nDiff);
2884 if ( nNode == nEndNode )
2885 aNewSel.Max().GetIndex() =
2886 aNewSel.Max().GetIndex() + nDiffs;
2888 ParaPortion* pParaPortion = GetParaPortions()[nNode];
2889 pParaPortion->MarkSelectionInvalid( nCurrentStart, std::max< USHORT >( nCurrentStart+nLen, nCurrentStart+aNewText.Len() ) );
2892 nCurrentStart = nCurrentEnd;
2893 } while( nCurrentEnd < nEndPos );
2896 #ifndef SVX_LIGHT
2897 if ( pUndo )
2899 ESelection aESel( CreateESel( aNewSel ) );
2900 pUndo->SetNewSelection( aESel );
2901 InsertUndo( pUndo );
2903 #endif
2905 if ( bChanges )
2907 TextModified();
2908 SetModifyFlag( sal_True );
2909 if ( bLenChanged )
2910 UpdateSelections();
2911 FormatAndUpdate();
2914 return aNewSel;
2917 void ImpEditEngine::SetAsianCompressionMode( USHORT n )
2919 if ( n != nAsianCompressionMode )
2921 nAsianCompressionMode = n;
2922 if ( ImplHasText() )
2924 FormatFullDoc();
2925 UpdateViews();
2930 void ImpEditEngine::SetKernAsianPunctuation( BOOL b )
2932 if ( b != bKernAsianPunctuation )
2934 bKernAsianPunctuation = b;
2935 if ( ImplHasText() )
2937 FormatFullDoc();
2938 UpdateViews();
2943 void ImpEditEngine::SetAddExtLeading( BOOL bExtLeading )
2945 if ( IsAddExtLeading() != bExtLeading )
2947 bAddExtLeading = bExtLeading;
2948 if ( ImplHasText() )
2950 FormatFullDoc();
2951 UpdateViews();
2958 BOOL ImpEditEngine::ImplHasText() const
2960 return ( ( GetEditDoc().Count() > 1 ) || GetEditDoc().GetObject(0)->Len() );
2963 long ImpEditEngine::LogicToTwips( long n )
2965 Size aSz( n, 0 );
2966 MapMode aTwipsMode( MAP_TWIP );
2967 aSz = pRefDev->LogicToLogic( aSz, NULL, &aTwipsMode );
2968 return aSz.Width();