1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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>
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>
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>
82 #include <edtspell.hxx>
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>
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
)
113 EditPaM
ImpEditEngine::Read( SvStream
& rInput
, const String
& rBaseURL
, EETextFormat eFormat
, EditSelection aSel
, SvKeyValueIterator
* pHTTPHeaderAttrs
)
115 sal_Bool _bUpdate
= GetUpdateMode();
116 SetUpdateMode( sal_False
);
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
);
130 DBG_ERROR( "Read: Unbekanntes Format" );
133 FormatFullDoc(); // reicht vielleicht auch ein einfaches Format?
134 SetUpdateMode( _bUpdate
);
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
);
149 aTmpStr
.Erase( MAXCHARSINPARA
);
150 aPaM
= ImpInsertText( EditSelection( aPaM
, aPaM
), aTmpStr
);
151 aPaM
= ImpInsertParaBreak( aPaM
);
152 bDone
= rInput
.ReadByteStringLine( aTmpStr
);
157 EditPaM
ImpEditEngine::ReadXML( SvStream
& rInput
, EditSelection aSel
)
160 if ( aSel
.HasRange() )
161 aSel
= ImpDeleteSelection( aSel
);
163 ESelection aESel
= CreateESel( aSel
);
165 ::SvxReadXML( *GetEditEnginePtr(), rInput
, aESel
);
173 EditPaM
ImpEditEngine::ReadRTF( SvStream
& rInput
, EditSelection aSel
)
177 #if defined (EDITDEBUG) && !defined( UNX )
178 SvFileStream
aRTFOut( String( RTL_CONSTASCII_USTRINGPARAM ( "d:\\rtf_in.rtf" ) ), STREAM_WRITE
);
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
);
206 return xPrsr
->GetCurPaM();
212 EditPaM
ImpEditEngine::ReadHTML( SvStream
& rInput
, const String
& rBaseURL
, EditSelection aSel
, SvKeyValueIterator
* pHTTPHeaderAttrs
)
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
);
229 return xPrsr
->GetCurSelection().Max();
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();
242 aLastPaM
= InsertText( *pObj
, aSel
).Max();
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
);
268 DBG_ERROR( "Write: Unbekanntes Format" );
274 sal_uInt32
ImpEditEngine::WriteText( SvStream
& rOutput
, EditSelection aSel
)
276 sal_uInt16 nStartNode
, nEndNode
;
277 sal_Bool bRange
= aSel
.HasRange();
280 aSel
.Adjust( aEditDoc
);
281 nStartNode
= aEditDoc
.GetPos( aSel
.Min().GetNode() );
282 nEndNode
= aEditDoc
.GetPos( aSel
.Max().GetNode() );
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();
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();
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
);
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
);
351 sal_uInt32
ImpEditEngine::WriteXML( SvStream
& rOutput
, EditSelection aSel
)
353 ESelection aESel
= CreateESel( aSel
);
355 SvxWriteXML( *GetEditEnginePtr(), rOutput
, aESel
);
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
)
374 sal_uInt32
ImpEditEngine::WriteRTF( SvStream
& rOutput
, EditSelection aSel
)
377 DBG_ASSERT( GetUpdateMode(), "WriteRTF bei UpdateMode = sal_False!" );
378 CheckIdleFormatter();
379 if ( !IsFormatted() )
382 sal_uInt16 nStartNode
, nEndNode
;
383 aSel
.Adjust( aEditDoc
);
385 nStartNode
= aEditDoc
.GetPos( aSel
.Min().GetNode() );
386 nEndNode
= aEditDoc
.GetPos( aSel
.Max().GetNode() );
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
;
411 SvxFontItem
* pFontItem
= (SvxFontItem
*)aEditDoc
.GetItemPool().GetItem( nWhich
, i
);
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
;
430 for ( j
= 0; j
< aFontTable
.Count(); j
++ )
432 SvxFontItem
* pFontItem
= aFontTable
.Get( j
);
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
;
440 case FAMILY_DECORATIVE
: rOutput
<< OOO_STRING_SVTOOLS_RTF_FDECOR
;
442 case FAMILY_MODERN
: rOutput
<< OOO_STRING_SVTOOLS_RTF_FMODERN
;
444 case FAMILY_ROMAN
: rOutput
<< OOO_STRING_SVTOOLS_RTF_FROMAN
;
446 case FAMILY_SCRIPT
: rOutput
<< OOO_STRING_SVTOOLS_RTF_FSCRIPT
;
448 case FAMILY_SWISS
: rOutput
<< OOO_STRING_SVTOOLS_RTF_FSWISS
;
453 rOutput
<< OOO_STRING_SVTOOLS_RTF_FPRQ
;
455 switch( pFontItem
->GetPitch() )
457 case PITCH_FIXED
: nVal
= 1; break;
458 case PITCH_VARIABLE
: nVal
= 2; 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
) );
472 RTFOutFuncs::Out_String( rOutput
, pFontItem
->GetFamilyName(), eDestEnc
);
478 // ColorList rausschreiben...
479 SvxColorList aColorList
;
481 SvxColorItem
* pColorItem
= (SvxColorItem
*)aEditDoc
.GetItemPool().GetItem( EE_CHAR_COLOR
, i
);
485 if ( pColorItem
->GetValue() == COL_AUTO
)
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() );
511 if ( GetStyleSheetPool() )
513 sal_uInt16 nStyles
= (sal_uInt16
)GetStyleSheetPool()->GetStyles().size();
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();
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;
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
);
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
;
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
);
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
);
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
);
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
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();
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 );
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
);
707 if ( WriteItemListAsRTF( aAttribItems
, rOutput
, nNode
, nIndex
, aFontTable
, aColorList
) )
711 USHORT nE
= nIndex
+ pTextPortion
->GetLen();
712 if ( n
== nStartPortion
)
714 if ( n
== nEndPortion
)
717 XubString aRTFStr
= aEditDoc
.GetParaAsString( pNode
, nS
, nE
);
718 RTFOutFuncs::Out_String( rOutput
, aRTFStr
, eDestEnc
);
721 if ( bFinishPortion
)
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
;;
734 rOutput
<< "}}"; // 1xKlammerung Absaetze, 1x Klammerung RTF-Dokument
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();
747 return rOutput
.GetError();
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();
760 case EE_PARA_WRITINGDIR
:
762 const SvxFrameDirectionItem
& rWritingMode
= (const SvxFrameDirectionItem
&)rItem
;
763 if ( rWritingMode
.GetValue() == FRMDIR_HORI_RIGHT_TOP
)
764 rOutput
<< "\\rtlpar";
766 rOutput
<< "\\ltrpar";
769 case EE_PARA_OUTLLEVEL
:
771 sal_Int16 nLevel
= ((const SfxInt16Item
&)rItem
).GetValue();
774 rOutput
<< "\\level";
775 rOutput
.WriteNumber( nLevel
);
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
);
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
);
812 rOutput
<< OOO_STRING_SVTOOLS_RTF_SL
;
813 long nVal
= ((const SvxLineSpacingItem
&)rItem
).GetLineHeight();
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();
824 rOutput
.WriteNumber( nVal
);
825 rOutput
<< OOO_STRING_SVTOOLS_RTF_SLMULT
<< cMult
;
830 SvxAdjust eJustification
= ((const SvxAdjustItem
&)rItem
).GetAdjust();
831 switch ( eJustification
)
833 case SVX_ADJUST_CENTER
: rOutput
<< OOO_STRING_SVTOOLS_RTF_QC
;
835 case SVX_ADJUST_RIGHT
: rOutput
<< OOO_STRING_SVTOOLS_RTF_QR
;
837 default: rOutput
<< OOO_STRING_SVTOOLS_RTF_QL
;
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() ) );
855 sal_uInt32 n
= rColorList
.GetId( (const SvxColorItem
&)rItem
);
856 rOutput
<< OOO_STRING_SVTOOLS_RTF_CF
;
857 rOutput
.WriteNumber( n
);
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
);
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
878 rOutput
.WriteNumber( nHeight
);
882 case EE_CHAR_WEIGHT_CJK
:
883 case EE_CHAR_WEIGHT_CTL
:
885 FontWeight e
= ((const SvxWeightItem
&)rItem
).GetWeight();
888 case WEIGHT_BOLD
: rOutput
<< OOO_STRING_SVTOOLS_RTF_B
; break;
889 default: rOutput
<< OOO_STRING_SVTOOLS_RTF_B
<< '0'; 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();
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;
909 case EE_CHAR_OVERLINE
:
911 FontUnderline e
= ((const SvxOverlineItem
&)rItem
).GetLineStyle();
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;
923 case EE_CHAR_STRIKEOUT
:
925 FontStrikeout e
= ((const SvxCrossedOutItem
&)rItem
).GetStrikeout();
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;
937 case EE_CHAR_ITALIC_CJK
:
938 case EE_CHAR_ITALIC_CTL
:
940 FontItalic e
= ((const SvxPostureItem
&)rItem
).GetPosture();
944 case ITALIC_NORMAL
: rOutput
<< OOO_STRING_SVTOOLS_RTF_I
; break;
945 case ITALIC_NONE
: rOutput
<< OOO_STRING_SVTOOLS_RTF_I
<< '0'; break;
951 case EE_CHAR_OUTLINE
:
953 rOutput
<< OOO_STRING_SVTOOLS_RTF_OUTL
;
954 if ( ((const SvxContourItem
&)rItem
).GetValue() == 0 )
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
;
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
;
975 rOutput
<< OOO_STRING_SVTOOLS_RTF_ACCDOT
;
980 rOutput
<< OOO_STRING_SVTOOLS_RTF_SHAD
;
981 if ( ((const SvxShadowedItem
&)rItem
).GetValue() == 0 )
987 rOutput
<< OOO_STRING_SVTOOLS_RTF_TAB
;
990 case EE_FEATURE_LINEBR
:
992 rOutput
<< OOO_STRING_SVTOOLS_RTF_SL
;
995 case EE_CHAR_KERNING
:
997 rOutput
<< OOO_STRING_SVTOOLS_RTF_EXPNDTW
;
998 rOutput
.WriteNumber( LogicToTwips(
999 ((const SvxKerningItem
&)rItem
).GetValue() ) );
1002 case EE_CHAR_PAIRKERNING
:
1004 rOutput
<< OOO_STRING_SVTOOLS_RTF_KERNING
;
1005 rOutput
.WriteNumber( ((const SvxAutoKernItem
&)rItem
).GetValue() ? 1 : 0 );
1008 case EE_CHAR_ESCAPEMENT
:
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
)
1023 nProp100
++; // Eine 1 hinten bedeutet 'automatisch'.
1025 else if ( nEsc
== DFLT_ESC_AUTO_SUB
)
1027 nEsc
= sal::static_int_cast
< short >( -( 100 - nProp
) );
1032 rOutput
<< "{\\*\\updnprop" << ByteString::CreateFromInt32( nProp100
).GetBuffer() << '}';
1033 long nUpDown
= nFontHeight
* Abs( nEsc
) / 100;
1034 ByteString aUpDown
= ByteString::CreateFromInt32( nUpDown
);
1036 rOutput
<< OOO_STRING_SVTOOLS_RTF_DN
<< aUpDown
.GetBuffer();
1037 else if ( nEsc
> 0 )
1038 rOutput
<< OOO_STRING_SVTOOLS_RTF_UP
<< aUpDown
.GetBuffer();
1044 sal_uInt32
ImpEditEngine::WriteHTML( SvStream
&, EditSelection
)
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...
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();
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
);
1133 // In einem leeren Absatz die Attribute behalten!
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
);
1154 pC
->GetAttribs().Insert( pX
, pC
->GetAttribs().Count() );
1157 pAttr
= GetAttrib( pNode
->GetCharAttribs().GetAttribs(), nAttr
);
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();
1184 sal_uInt16 nCount
= pParaPortion
->GetTextPortions().Count();
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() );
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() );
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!" );
1215 void ImpEditEngine::SetText( const EditTextObject
& rTextObject
)
1217 // Da Setzen eines TextObject ist nicht Undo-faehig!
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() );
1232 DBG_ASSERT( !HasUndoManager() || !GetUndoManager().GetUndoActionCount(), "Woher kommt das Undo in SetText ?!" );
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();
1248 // MT 05/00: InsertBinTextObject direkt hier machen...
1251 EditSelection
ImpEditEngine::InsertBinTextObject( BinTextObject
& rTextObject
, EditPaM aPaM
)
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();
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
);
1321 SfxPoolItem
* pNew
= pX
->GetItem()->Clone();
1322 ConvertItem( *pNew
, eSourceUnit
, eDestUnit
);
1323 pAttr
= MakeCharAttrib( aEditDoc
.GetItemPool(), *pNew
, pX
->GetStart()+nStartPos
, pX
->GetEnd()+nStartPos
);
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
;
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
)
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() );
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
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
);
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
);
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!" );
1416 if ( !bParaAttribs
) // DefFont wird bei FastInsertParagraph nicht berechnet
1418 aPaM
.GetNode()->GetCharAttribs().GetDefFont() = aEditDoc
.GetDefFont();
1419 if ( aStatus
.UseCharAttribs() )
1420 aPaM
.GetNode()->CreateDefFont();
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) )
1435 aPaM
= ImpFastInsertParagraph( nPara
+1 );
1437 aPaM
= ImpInsertParaBreak( aPaM
, sal_False
);
1442 DBG_ASSERT( !aSel
.DbgIsBuggy( aEditDoc
), "InsertBibTextObject: Selektion kaput!(1)" );
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() );
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()
1469 if ( !xSpeller
.is() )
1470 xSpeller
= SvxGetSpellChecker();
1475 EESpellState
ImpEditEngine::Spell( EditView
* pEditView
, sal_Bool bMultipleDoc
)
1478 return EE_SPELL_NOSPELLER
;
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...
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
;
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();
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
;
1528 sal_Bool
ImpEditEngine::HasConvertibleTextPortion( LanguageType nSrcLang
)
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?
1550 LanguageType nLangFound
= pEditEngine
->GetLanguage( k
, nStart
);
1552 lang::Locale
aLocale( SvxCreateLocale( nLangFound
) );
1554 bHasConvTxt
= (nSrcLang
== nLangFound
) ||
1555 (svx::HangulHanjaConversion::IsChinese( nLangFound
) &&
1556 svx::HangulHanjaConversion::IsChinese( nSrcLang
));
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
1576 // Bei MultipleDoc immer von vorne/hinten...
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
;
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
),
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 );
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
);
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?" );
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
1703 LanguageType nResLang
= LANGUAGE_NONE
;
1706 rConvTxt
= rtl::OUString();
1707 rConvTxtLang
= LANGUAGE_NONE
;
1710 /* ContentNode* pLastNode = */ aEditDoc
.SaveGetObject( aEditDoc
.Count()-1 );
1712 EditPaM
aPos( CreateEditPaM( pConvInfo
->aConvContinue
) );
1713 EditSelection aCurSel
= EditSelection( aPos
, aPos
);
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
)
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() )
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
);
1766 lang::Locale
aLocale( SvxCreateLocale( nLangFound
) );
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
)
1778 else // language attrib has changed
1781 if (nAttribStart
== USHRT_MAX
&& // start not yet found?
1782 nEnd
> aCurStart
.nIndex
&& bLangOk
)
1784 nAttribStart
= nStart
;
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
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
);
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
) )
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 */)
1862 // move to next word/paragraph if necessary
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
);
1875 if (rConvTxt
.getLength())
1876 rConvTxtLang
= nResLang
;
1881 Reference
< XSpellAlternatives
> ImpEditEngine::ImpSpell( EditView
* pEditView
)
1884 return Reference
< XSpellAlternatives
>();
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();
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() ) )
1910 else if ( !pSpellInfo
->bSpellToEnd
)
1912 EPaM
aEPaM( CreateEPaM( aCurSel
.Max() ) );
1913 if ( !( aEPaM
< pSpellInfo
->aSpellTo
) )
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() );
1927 aCurSel
.Max().GetIndex()++;
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
);
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
);
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() );
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()) ) )
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() );
2001 aCurSel
.Max().GetIndex()++;
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
);
2013 pSpellInfo
->eState
= EE_SPELL_ERRORFOUND
;
2014 rSelection
= aCurSel
;
2019 /*-- 13.10.2003 16:43:27---------------------------------------------------
2021 -----------------------------------------------------------------------*/
2022 bool ImpEditEngine::SpellSentence(EditView
& rEditView
, ::svx::SpellPortions
& rToFill
, bool /*bIsGrammarChecking*/ )
2027 //the pSpellInfo has to be created on demand
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();
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
);
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
);
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
);
2076 AddPortionIterated(rEditView
, EditSelection(aCurSel
.Max(), aSentencePaM
.Max()), xAlt
, rToFill
);
2080 //set the selection to the end of the current sentence
2081 rEditView
.pImpEditView
->SetEditSelection(aSentencePaM
.Max());
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
,
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
);
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
)
2126 if(rSel
.Min() != rSel
.Max())
2130 AddPortion(rSel
, xAlt
, rToFill
, false);
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
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
);
2182 while(aCursor
.GetIndex() < aEnd
.GetIndex());
2183 EditSelection
aSelection(aStart
, aCursor
);
2184 AddPortion(aSelection
, xAlt
, rToFill
, bIsField
);
2190 /*-- 13.10.2003 16:43:33---------------------------------------------------
2192 -----------------------------------------------------------------------*/
2193 void ImpEditEngine::ApplyChangedSentence(EditView
& rEditView
, const ::svx::SpellPortions
& rNewPortions
, bool /*bIsGrammarChecking*/ )
2197 DBG_ASSERT(pSpellInfo
, "pSpellInfo not initialized");
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
2219 rEditView
.pImpEditView
->SetEditSelection( aCurrentOldPosition
->Max() );
2222 USHORT nScriptType
= GetI18NScriptTypeOfLanguage( aCurrentNewPortion
->eLanguage
);
2223 // LanguageType eTextLanguage = GetLanguage( aCurrentOldPosition->Min() );
2225 USHORT nLangWhichId
= EE_CHAR_LANGUAGE
;
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
)
2242 SfxItemSet
aSet( aEditDoc
.GetItemPool(), nLangWhichId
, nLangWhichId
);
2243 aSet
.Put(SvxLanguageItem(aCurrentNewPortion
->eLanguage
, nLangWhichId
));
2244 SetAttribs( *aCurrentOldPosition
, aSet
);
2246 if(aCurrentNewPortion
== rNewPortions
.begin())
2249 while(aCurrentNewPortion
!= rNewPortions
.begin());
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
;
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
);
2288 aEditDoc
.SetModified(TRUE
);
2291 /*-- 08.09.2008 11:33:02---------------------------------------------------
2293 -----------------------------------------------------------------------*/
2294 void ImpEditEngine::PutSpellingToSentenceStart( EditView
& rEditView
)
2298 if( pSpellInfo
&& pSpellInfo
->aLastSpellContentSelections
.size() )
2300 rEditView
.pImpEditView
->SetEditSelection( pSpellInfo
->aLastSpellContentSelections
.begin()->Min() );
2307 void ImpEditEngine::DoOnlineSpelling( ContentNode
* pThisNodeOnly
, sal_Bool bSpellAtCursorPos
, sal_Bool bInteruptable
)
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
2322 if ( !xSpeller
.is() )
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() );
2375 aSel
.Max().GetIndex()++;
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...
2391 // Nur bei SimpleRepaint stoppen, sonst zu oft VDev
2392 // if ( ( nWrongs > 8 ) && bSimpleRepaint )
2394 // bStop = sal_True;
2395 // pWrongList->MarkInvalid( aSel.Max().GetIndex(), nInvEnd );
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
;
2410 // Dann weiter als ungueltig markieren...
2411 pWrongList
->GetInvalidStart() = nWStart
;
2412 pWrongList
->GetInvalidEnd() = nWEnd
;
2413 bRestartTimer
= sal_True
;
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
;
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
;
2437 if ( nPaintFrom
== 0xFFFF )
2438 nPaintFrom
= nWStart
;
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
);
2456 if ( ( nPaintFrom
!= 0xFFFF ) )
2458 aStatus
.GetStatusWord() |= EE_STAT_WRONGWORDCHANGED
;
2461 if ( aEditViews
.Count() )
2463 // Bei SimpleRepaint wuerde ein uebermalen ohne VDev reichen,
2464 // aber dann muesste ich ueber alle Views, Intersecten,
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() );
2499 UpdateViews( pActiveView
);
2501 aInvalidRec
= Rectangle();
2504 // Nach zwei korrigierten Nodes die Kontrolle abgeben...
2506 if ( bInteruptable
&& ( nInvalids
>= 2 ) )
2508 bRestartTimer
= sal_True
;
2513 if ( pThisNodeOnly
)
2516 if ( bRestartTimer
)
2517 aOnlineSpellTimer
.Start();
2518 #endif // !SVX_LIGHT
2522 EESpellState
ImpEditEngine::HasSpellErrors()
2524 DBG_ASSERT( xSpeller
.is(), "Kein Speller gesetzt!" );
2527 ContentNode
* pLastNode
= aEditDoc
.SaveGetObject( aEditDoc
.Count() - 1 );
2528 EditSelection
aCurSel( aEditDoc
.GetStartPaM() );
2531 Reference
< XSpellAlternatives
> xSpellAlt
;
2532 Sequence
< PropertyValue
> aEmptySeq
;
2533 while ( !xSpellAlt
.is() )
2535 if ( ( aCurSel
.Max().GetNode() == pLastNode
) &&
2536 ( aCurSel
.Max().GetIndex() >= pLastNode
->Len() ) )
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
);
2553 return EE_SPELL_ERRORFOUND
;
2556 EESpellState
ImpEditEngine::StartThesaurus( EditView
* pEditView
)
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() );
2566 return EE_SPELL_ERRORFOUND
;
2568 SvxThesaurusDialog
aDialog( pEditView
->GetWindow(), xThes
, aWord
, GetLanguage( aCurSel
.Max() ) );
2570 if ( aDialog
.Execute() == RET_OK
)
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
);
2582 return EE_SPELL_NOSPELLER
;
2586 sal_uInt16
ImpEditEngine::StartSearchAndReplace( EditView
* pEditView
, const SvxSearchItem
& rSearchItem
)
2588 sal_uInt16 nFound
= 0;
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
) )
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() );
2610 if( Search( rSearchItem
, pEditView
) )
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
);
2626 UndoActionStart( EDITUNDO_REPLACEALL
);
2630 aStartPaM
= ImpInsertText( aFoundSel
, rSearchItem
.GetReplaceString() );
2631 bFound
= ImpSearch( aTmpItem
, aCurSel
, aStartPaM
, aFoundSel
);
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
);
2644 pEditView
->pImpEditView
->DrawSelection();
2645 pEditView
->ShowCursor( sal_True
, sal_False
);
2648 #endif // !SVX_LIGHT
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();
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
);
2677 pEditView
->pImpEditView
->SetEditSelection( aSel
.Max() );
2679 pEditView
->pImpEditView
->DrawSelection();
2680 pEditView
->ShowCursor( TRUE
, FALSE
);
2684 sal_Bool
ImpEditEngine::ImpSearch( const SvxSearchItem
& rSearchItem
,
2685 const EditSelection
& rSearchSelection
, const EditPaM
& rStartPos
, EditSelection
& rFoundSel
)
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() );
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 )
2715 ContentNode
* pNode
= aEditDoc
.GetObject( nNode
);
2717 sal_uInt16 nStartPos
= 0;
2718 sal_uInt16 nEndPos
= pNode
->Len();
2719 if ( nNode
== nStartNode
)
2722 nEndPos
= rStartPos
.GetIndex();
2724 nStartPos
= rStartPos
.GetIndex();
2726 if ( ( nNode
== nEndNode
) && bSearchInSelection
)
2729 nStartPos
= rSearchSelection
.Min().GetIndex();
2731 nEndPos
= rSearchSelection
.Max().GetIndex();
2735 XubString
aParaStr( GetEditDoc().GetParaAsString( pNode
) );
2736 bool bFound
= false;
2739 SwapUSHORTs( nStartPos
, nEndPos
);
2740 bFound
= aSearcher
.SearchBkwrd( aParaStr
, &nStartPos
, &nEndPos
);
2743 bFound
= aSearcher
.SearchFrwrd( aParaStr
, &nStartPos
, &nEndPos
);
2747 rFoundSel
.Min().SetNode( pNode
);
2748 rFoundSel
.Min().SetIndex( nStartPos
);
2749 rFoundSel
.Max().SetNode( pNode
);
2750 rFoundSel
.Max().SetIndex( nEndPos
);
2754 #endif // !SVX_LIGHT
2758 sal_Bool
ImpEditEngine::HasText( const SvxSearchItem
& rSearchItem
)
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
);
2774 void ImpEditEngine::SetAutoCompleteText( const String
& rStr
, sal_Bool bClearTipWindow
)
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
) )
2834 if ( nLen
!= aNewText
.Len() )
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() ) );
2847 pUndo
->SetText( CreateBinTextObject( aSel
, NULL
) );
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();
2856 for ( USHORT n
= 0; n
< nCharsAfterTransliteration
; n
++ )
2858 USHORT nCurrentPos
= nCurrentStart
+n
;
2859 sal_Int32 nDiff
= (nCurrentPos
-nDiffs
) - pOffsets
[n
];
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
) );
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
);
2899 ESelection
aESel( CreateESel( aNewSel
) );
2900 pUndo
->SetNewSelection( aESel
);
2901 InsertUndo( pUndo
);
2908 SetModifyFlag( sal_True
);
2917 void ImpEditEngine::SetAsianCompressionMode( USHORT n
)
2919 if ( n
!= nAsianCompressionMode
)
2921 nAsianCompressionMode
= n
;
2922 if ( ImplHasText() )
2930 void ImpEditEngine::SetKernAsianPunctuation( BOOL b
)
2932 if ( b
!= bKernAsianPunctuation
)
2934 bKernAsianPunctuation
= b
;
2935 if ( ImplHasText() )
2943 void ImpEditEngine::SetAddExtLeading( BOOL bExtLeading
)
2945 if ( IsAddExtLeading() != bExtLeading
)
2947 bAddExtLeading
= bExtLeading
;
2948 if ( ImplHasText() )
2958 BOOL
ImpEditEngine::ImplHasText() const
2960 return ( ( GetEditDoc().Count() > 1 ) || GetEditDoc().GetObject(0)->Len() );
2963 long ImpEditEngine::LogicToTwips( long n
)
2966 MapMode
aTwipsMode( MAP_TWIP
);
2967 aSz
= pRefDev
->LogicToLogic( aSz
, NULL
, &aTwipsMode
);