summaryrefslogtreecommitdiff
path: root/editeng/source/editeng/impedit4.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'editeng/source/editeng/impedit4.cxx')
-rw-r--r--editeng/source/editeng/impedit4.cxx2958
1 files changed, 2958 insertions, 0 deletions
diff --git a/editeng/source/editeng/impedit4.cxx b/editeng/source/editeng/impedit4.cxx
new file mode 100644
index 0000000000..1280fecdfd
--- /dev/null
+++ b/editeng/source/editeng/impedit4.cxx
@@ -0,0 +1,2958 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: impedit4.cxx,v $
+ * $Revision: 1.78.54.1 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_editeng.hxx"
+
+#include <vcl/wrkwin.hxx>
+#include <vcl/dialog.hxx>
+#include <vcl/msgbox.hxx>
+#include <vcl/svapp.hxx>
+
+#include <svl/srchitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/tstpitem.hxx>
+
+#include <eertfpar.hxx>
+#include <editeng/editeng.hxx>
+#include <impedit.hxx>
+#include <editeng/editview.hxx>
+#include <eehtml.hxx>
+#include <editobj2.hxx>
+#include <i18npool/lang.h>
+
+#include "editxml.hxx"
+
+#include <editeng/akrnitem.hxx>
+#include <editeng/cntritem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/crsditem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/charreliefitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/emphitem.hxx>
+#include <textconv.hxx>
+#include <rtl/tencinfo.h>
+#include <svtools/rtfout.hxx>
+#include <edtspell.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include <editeng/unolingu.hxx>
+#include <linguistic/lngprops.hxx>
+#include <com/sun/star/linguistic2/XThesaurus.hpp>
+#include <com/sun/star/linguistic2/XMeaning.hpp>
+#include <com/sun/star/i18n/ScriptType.hpp>
+#include <unotools/transliterationwrapper.hxx>
+#include <unotools/textsearch.hxx>
+#include <comphelper/processfactory.hxx>
+#include <vcl/help.hxx>
+#include <svtools/rtfkeywd.hxx>
+#include <editeng/edtdlg.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::linguistic2;
+
+void SwapUSHORTs( sal_uInt16& rX, sal_uInt16& rY )
+{
+ sal_uInt16 n = rX;
+ rX = rY;
+ rY = n;
+}
+
+EditPaM ImpEditEngine::Read( SvStream& rInput, const String& rBaseURL, EETextFormat eFormat, EditSelection aSel, SvKeyValueIterator* pHTTPHeaderAttrs )
+{
+ sal_Bool _bUpdate = GetUpdateMode();
+ SetUpdateMode( sal_False );
+ EditPaM aPaM;
+ if ( eFormat == EE_FORMAT_TEXT )
+ aPaM = ReadText( rInput, aSel );
+ else if ( eFormat == EE_FORMAT_RTF )
+ aPaM = ReadRTF( rInput, aSel );
+ else if ( eFormat == EE_FORMAT_XML )
+ aPaM = ReadXML( rInput, aSel );
+ else if ( eFormat == EE_FORMAT_HTML )
+ aPaM = ReadHTML( rInput, rBaseURL, aSel, pHTTPHeaderAttrs );
+ else if ( eFormat == EE_FORMAT_BIN)
+ aPaM = ReadBin( rInput, aSel );
+ else
+ {
+ DBG_ERROR( "Read: Unbekanntes Format" );
+ }
+
+ FormatFullDoc(); // reicht vielleicht auch ein einfaches Format?
+ SetUpdateMode( _bUpdate );
+
+ return aPaM;
+}
+
+EditPaM ImpEditEngine::ReadText( SvStream& rInput, EditSelection aSel )
+{
+ if ( aSel.HasRange() )
+ aSel = ImpDeleteSelection( aSel );
+ EditPaM aPaM = aSel.Max();
+
+ XubString aTmpStr, aStr;
+ sal_Bool bDone = rInput.ReadByteStringLine( aTmpStr );
+ while ( bDone )
+ {
+ aTmpStr.Erase( MAXCHARSINPARA );
+ aPaM = ImpInsertText( EditSelection( aPaM, aPaM ), aTmpStr );
+ aPaM = ImpInsertParaBreak( aPaM );
+ bDone = rInput.ReadByteStringLine( aTmpStr );
+ }
+ return aPaM;
+}
+
+EditPaM ImpEditEngine::ReadXML( SvStream& rInput, EditSelection aSel )
+{
+#ifndef SVX_LIGHT
+ if ( aSel.HasRange() )
+ aSel = ImpDeleteSelection( aSel );
+
+ ESelection aESel = CreateESel( aSel );
+
+ ::SvxReadXML( *GetEditEnginePtr(), rInput, aESel );
+
+ return aSel.Max();
+#else
+ return EditPaM();
+#endif
+}
+
+EditPaM ImpEditEngine::ReadRTF( SvStream& rInput, EditSelection aSel )
+{
+#ifndef SVX_LIGHT
+
+#if defined (EDITDEBUG) && !defined( UNX )
+ SvFileStream aRTFOut( String( RTL_CONSTASCII_USTRINGPARAM ( "d:\\rtf_in.rtf" ) ), STREAM_WRITE );
+ aRTFOut << rInput;
+ aRTFOut.Close();
+ rInput.Seek( 0 );
+#endif
+ if ( aSel.HasRange() )
+ aSel = ImpDeleteSelection( aSel );
+
+// sal_Bool bCharsBeforeInsertPos = ( aSel.Min().GetIndex() ) ? sal_True : sal_False;
+// sal_Bool bCharsBehindInsertPos = ( aSel.Min().GetIndex() < aSel.Min().GetNode()->Len() ) ? sal_True : sal_False;
+
+ // Der SvRTF-Parser erwartet, dass das Which-Mapping am uebergebenen Pool,
+ // nicht an einem Secondary haengt.
+ SfxItemPool* pPool = &aEditDoc.GetItemPool();
+ while ( pPool->GetSecondaryPool() && !pPool->GetName().EqualsAscii( "EditEngineItemPool" ) )
+ {
+ pPool = pPool->GetSecondaryPool();
+
+ }
+ DBG_ASSERT( pPool && pPool->GetName().EqualsAscii( "EditEngineItemPool" ), "ReadRTF: Kein EditEnginePool!" );
+
+ EditRTFParserRef xPrsr = new EditRTFParser( rInput, aSel, *pPool, this );
+ SvParserState eState = xPrsr->CallParser();
+ if ( ( eState != SVPAR_ACCEPTED ) && ( !rInput.GetError() ) )
+ {
+ rInput.SetError( EE_READWRITE_WRONGFORMAT );
+ return aSel.Min();
+ }
+ return xPrsr->GetCurPaM();
+#else
+ return EditPaM();
+#endif
+}
+
+EditPaM ImpEditEngine::ReadHTML( SvStream& rInput, const String& rBaseURL, EditSelection aSel, SvKeyValueIterator* pHTTPHeaderAttrs )
+{
+#ifndef SVX_LIGHT
+
+ if ( aSel.HasRange() )
+ aSel = ImpDeleteSelection( aSel );
+
+// sal_Bool bCharsBeforeInsertPos = ( aSel.Min().GetIndex() ) ? sal_True : sal_False;
+// sal_Bool bCharsBehindInsertPos = ( aSel.Min().GetIndex() < aSel.Min().GetNode()->Len() ) ? sal_True : sal_False;
+
+ EditHTMLParserRef xPrsr = new EditHTMLParser( rInput, rBaseURL, pHTTPHeaderAttrs );
+ SvParserState eState = xPrsr->CallParser( this, aSel.Max() );
+ if ( ( eState != SVPAR_ACCEPTED ) && ( !rInput.GetError() ) )
+ {
+ rInput.SetError( EE_READWRITE_WRONGFORMAT );
+ return aSel.Min();
+ }
+ return xPrsr->GetCurSelection().Max();
+#else
+ return EditPaM();
+#endif
+}
+
+EditPaM ImpEditEngine::ReadBin( SvStream& rInput, EditSelection aSel )
+{
+ // Einfach ein temporaeres TextObject missbrauchen...
+ EditTextObject* pObj = EditTextObject::Create( rInput, NULL );
+
+ EditPaM aLastPaM = aSel.Max();
+ if ( pObj )
+ aLastPaM = InsertText( *pObj, aSel ).Max();
+
+ delete pObj;
+ return aLastPaM;
+}
+
+#ifndef SVX_LIGHT
+void ImpEditEngine::Write( SvStream& rOutput, EETextFormat eFormat, EditSelection aSel )
+{
+ if ( !rOutput.IsWritable() )
+ rOutput.SetError( SVSTREAM_WRITE_ERROR );
+
+ if ( !rOutput.GetError() )
+ {
+ if ( eFormat == EE_FORMAT_TEXT )
+ WriteText( rOutput, aSel );
+ else if ( eFormat == EE_FORMAT_RTF )
+ WriteRTF( rOutput, aSel );
+ else if ( eFormat == EE_FORMAT_XML )
+ WriteXML( rOutput, aSel );
+ else if ( eFormat == EE_FORMAT_HTML )
+ WriteHTML( rOutput, aSel );
+ else if ( eFormat == EE_FORMAT_BIN)
+ WriteBin( rOutput, aSel );
+ else
+ {
+ DBG_ERROR( "Write: Unbekanntes Format" );
+ }
+ }
+}
+#endif
+
+sal_uInt32 ImpEditEngine::WriteText( SvStream& rOutput, EditSelection aSel )
+{
+ sal_uInt16 nStartNode, nEndNode;
+ sal_Bool bRange = aSel.HasRange();
+ if ( bRange )
+ {
+ aSel.Adjust( aEditDoc );
+ nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
+ nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
+ }
+ else
+ {
+ nStartNode = 0;
+ nEndNode = aEditDoc.Count()-1;
+ }
+
+ // ueber die Absaetze iterieren...
+ for ( sal_uInt16 nNode = nStartNode; nNode <= nEndNode; nNode++ )
+ {
+ ContentNode* pNode = aEditDoc.GetObject( nNode );
+ DBG_ASSERT( pNode, "Node nicht gefunden: Search&Replace" );
+
+ sal_uInt16 nStartPos = 0;
+ sal_uInt16 nEndPos = pNode->Len();
+ if ( bRange )
+ {
+ if ( nNode == nStartNode )
+ nStartPos = aSel.Min().GetIndex();
+ if ( nNode == nEndNode ) // kann auch == nStart sein!
+ nEndPos = aSel.Max().GetIndex();
+ }
+ XubString aTmpStr = aEditDoc.GetParaAsString( pNode, nStartPos, nEndPos );
+ rOutput.WriteByteStringLine( aTmpStr );
+ }
+
+ return rOutput.GetError();
+}
+
+sal_Bool ImpEditEngine::WriteItemListAsRTF( ItemList& rLst, SvStream& rOutput, sal_uInt16 nPara, sal_uInt16 nPos,
+ SvxFontTable& rFontTable, SvxColorList& rColorList )
+{
+ const SfxPoolItem* pAttrItem = rLst.First();
+ while ( pAttrItem )
+ {
+ WriteItemAsRTF( *pAttrItem, rOutput, nPara, nPos,rFontTable, rColorList );
+ pAttrItem = rLst.Next();
+ }
+ return ( rLst.Count() ? sal_True : sal_False );
+}
+
+void lcl_FindValidAttribs( ItemList& rLst, ContentNode* pNode, sal_uInt16 nIndex, USHORT nScriptType )
+{
+ sal_uInt16 nAttr = 0;
+ EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
+ while ( pAttr && ( pAttr->GetStart() <= nIndex ) )
+ {
+ // Start wird in While ueberprueft...
+ if ( pAttr->GetEnd() > nIndex )
+ {
+ if ( IsScriptItemValid( pAttr->GetItem()->Which(), nScriptType ) )
+ rLst.Insert( pAttr->GetItem(), LIST_APPEND );
+ }
+ nAttr++;
+ pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
+ }
+}
+
+sal_uInt32 ImpEditEngine::WriteBin( SvStream& rOutput, EditSelection aSel, BOOL bStoreUnicodeStrings ) const
+{
+ BinTextObject* pObj = (BinTextObject*)CreateBinTextObject( aSel, NULL );
+ pObj->StoreUnicodeStrings( bStoreUnicodeStrings );
+ pObj->Store( rOutput );
+ delete pObj;
+ return 0;
+}
+
+#ifndef SVX_LIGHT
+sal_uInt32 ImpEditEngine::WriteXML( SvStream& rOutput, EditSelection aSel )
+{
+ ESelection aESel = CreateESel( aSel );
+
+ SvxWriteXML( *GetEditEnginePtr(), rOutput, aESel );
+
+ return 0;
+}
+#endif
+
+static sal_uInt16 getStylePos( const SfxStyles& rStyles, SfxStyleSheet* pSheet )
+{
+ sal_uInt16 nNumber = 0;
+ SfxStyles::const_iterator iter( rStyles.begin() );
+ while( iter != rStyles.end() )
+ {
+ if( (*iter++).get() == pSheet )
+ return nNumber;
+ ++nNumber;
+ }
+ return 0;
+}
+
+sal_uInt32 ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel )
+{
+#ifndef SVX_LIGHT
+ DBG_ASSERT( GetUpdateMode(), "WriteRTF bei UpdateMode = sal_False!" );
+ CheckIdleFormatter();
+ if ( !IsFormatted() )
+ FormatDoc();
+
+ sal_uInt16 nStartNode, nEndNode;
+ aSel.Adjust( aEditDoc );
+
+ nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
+ nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
+
+ // RTF-Vorspann...
+ rOutput << '{' ;
+
+ rOutput << OOO_STRING_SVTOOLS_RTF_RTF;
+
+ rOutput << OOO_STRING_SVTOOLS_RTF_ANSI;
+ rtl_TextEncoding eDestEnc = RTL_TEXTENCODING_MS_1252;
+
+ // Fonttabelle erzeugen und rausschreiben...
+ SvxFontTable aFontTable;
+ // DefaultFont muss ganz vorne stehen, damit DEF-Font im RTF
+ aFontTable.Insert( 0, new SvxFontItem( (const SvxFontItem&)aEditDoc.GetItemPool().GetDefaultItem( EE_CHAR_FONTINFO ) ) );
+ aFontTable.Insert( 1, new SvxFontItem( (const SvxFontItem&)aEditDoc.GetItemPool().GetDefaultItem( EE_CHAR_FONTINFO_CJK ) ) );
+ aFontTable.Insert( 2, new SvxFontItem( (const SvxFontItem&)aEditDoc.GetItemPool().GetDefaultItem( EE_CHAR_FONTINFO_CTL ) ) );
+ for ( USHORT nScriptType = 0; nScriptType < 3; nScriptType++ )
+ {
+ USHORT nWhich = EE_CHAR_FONTINFO;
+ if ( nScriptType == 1 )
+ nWhich = EE_CHAR_FONTINFO_CJK;
+ else if ( nScriptType == 2 )
+ nWhich = EE_CHAR_FONTINFO_CTL;
+
+ sal_uInt16 i = 0;
+ SvxFontItem* pFontItem = (SvxFontItem*)aEditDoc.GetItemPool().GetItem( nWhich, i );
+ while ( pFontItem )
+ {
+ bool bAlreadyExist = false;
+ ULONG nTestMax = nScriptType ? aFontTable.Count() : 1;
+ for ( ULONG nTest = 0; !bAlreadyExist && ( nTest < nTestMax ); nTest++ )
+ {
+ bAlreadyExist = *aFontTable.Get( nTest ) == *pFontItem;
+ }
+
+ if ( !bAlreadyExist )
+ aFontTable.Insert( aFontTable.Count(), new SvxFontItem( *pFontItem ) );
+
+ pFontItem = (SvxFontItem*)aEditDoc.GetItemPool().GetItem( nWhich, ++i );
+ }
+ }
+
+ rOutput << endl << '{' << OOO_STRING_SVTOOLS_RTF_FONTTBL;
+ sal_uInt16 j;
+ for ( j = 0; j < aFontTable.Count(); j++ )
+ {
+ SvxFontItem* pFontItem = aFontTable.Get( j );
+ rOutput << '{';
+ rOutput << OOO_STRING_SVTOOLS_RTF_F;
+ rOutput.WriteNumber( j );
+ switch ( pFontItem->GetFamily() )
+ {
+ case FAMILY_DONTKNOW: rOutput << OOO_STRING_SVTOOLS_RTF_FNIL;
+ break;
+ case FAMILY_DECORATIVE: rOutput << OOO_STRING_SVTOOLS_RTF_FDECOR;
+ break;
+ case FAMILY_MODERN: rOutput << OOO_STRING_SVTOOLS_RTF_FMODERN;
+ break;
+ case FAMILY_ROMAN: rOutput << OOO_STRING_SVTOOLS_RTF_FROMAN;
+ break;
+ case FAMILY_SCRIPT: rOutput << OOO_STRING_SVTOOLS_RTF_FSCRIPT;
+ break;
+ case FAMILY_SWISS: rOutput << OOO_STRING_SVTOOLS_RTF_FSWISS;
+ break;
+ default:
+ break;
+ }
+ rOutput << OOO_STRING_SVTOOLS_RTF_FPRQ;
+ sal_uInt16 nVal = 0;
+ switch( pFontItem->GetPitch() )
+ {
+ case PITCH_FIXED: nVal = 1; break;
+ case PITCH_VARIABLE: nVal = 2; break;
+ default:
+ break;
+ }
+ rOutput.WriteNumber( nVal );
+
+ CharSet eChrSet = pFontItem->GetCharSet();
+ DBG_ASSERT( eChrSet != 9, "SystemCharSet?!" );
+ if( RTL_TEXTENCODING_DONTKNOW == eChrSet )
+ eChrSet = gsl_getSystemTextEncoding();
+ rOutput << OOO_STRING_SVTOOLS_RTF_FCHARSET;
+ rOutput.WriteNumber( rtl_getBestWindowsCharsetFromTextEncoding( eChrSet ) );
+
+ rOutput << ' ';
+ RTFOutFuncs::Out_String( rOutput, pFontItem->GetFamilyName(), eDestEnc );
+ rOutput << ";}";
+ }
+ rOutput << '}';
+ rOutput << endl;
+
+ // ColorList rausschreiben...
+ SvxColorList aColorList;
+ sal_uInt16 i = 0;
+ SvxColorItem* pColorItem = (SvxColorItem*)aEditDoc.GetItemPool().GetItem( EE_CHAR_COLOR, i );
+ while ( pColorItem )
+ {
+ USHORT nPos = i;
+ if ( pColorItem->GetValue() == COL_AUTO )
+ nPos = 0;
+ aColorList.Insert( new SvxColorItem( *pColorItem ), nPos );
+ pColorItem = (SvxColorItem*)aEditDoc.GetItemPool().GetItem( EE_CHAR_COLOR, ++i );
+ }
+ aColorList.Insert( new SvxColorItem( (const SvxColorItem&)aEditDoc.GetItemPool().GetDefaultItem( EE_CHAR_COLOR) ), (sal_uInt32)i );
+
+ rOutput << '{' << OOO_STRING_SVTOOLS_RTF_COLORTBL;
+ for ( j = 0; j < aColorList.Count(); j++ )
+ {
+ pColorItem = aColorList.GetObject( j );
+ if ( !j || ( pColorItem->GetValue() != COL_AUTO ) )
+ {
+ rOutput << OOO_STRING_SVTOOLS_RTF_RED;
+ rOutput.WriteNumber( pColorItem->GetValue().GetRed() );
+ rOutput << OOO_STRING_SVTOOLS_RTF_GREEN;
+ rOutput.WriteNumber( pColorItem->GetValue().GetGreen() );
+ rOutput << OOO_STRING_SVTOOLS_RTF_BLUE;
+ rOutput.WriteNumber( pColorItem->GetValue().GetBlue() );
+ }
+ rOutput << ';';
+ }
+ rOutput << '}';
+ rOutput << endl;
+
+ // StyleSheets...
+ if ( GetStyleSheetPool() )
+ {
+ sal_uInt16 nStyles = (sal_uInt16)GetStyleSheetPool()->GetStyles().size();
+ if ( nStyles )
+ {
+ rOutput << '{' << OOO_STRING_SVTOOLS_RTF_STYLESHEET;
+
+ for ( sal_uInt16 nStyle = 0; nStyle < nStyles; nStyle++ )
+ {
+
+ SfxStyleSheet* pStyle = (SfxStyleSheet*)GetStyleSheetPool()->GetStyles()[ nStyle ].get();
+
+ rOutput << endl << '{' << OOO_STRING_SVTOOLS_RTF_S;
+ sal_uInt16 nNumber = (sal_uInt16) (nStyle + 1);
+ rOutput.WriteNumber( nNumber );
+
+ // Attribute, auch aus Parent!
+ for ( sal_uInt16 nParAttr = EE_PARA_START; nParAttr <= EE_CHAR_END; nParAttr++ )
+ {
+ if ( pStyle->GetItemSet().GetItemState( nParAttr ) == SFX_ITEM_ON )
+ {
+ const SfxPoolItem& rItem = pStyle->GetItemSet().Get( nParAttr );
+ WriteItemAsRTF( rItem, rOutput, 0, 0, aFontTable, aColorList );
+ }
+ }
+
+ // Parent...(nur wenn noetig)
+ if ( pStyle->GetParent().Len() && ( pStyle->GetParent() != pStyle->GetName() ) )
+ {
+ SfxStyleSheet* pParent = (SfxStyleSheet*)GetStyleSheetPool()->Find( pStyle->GetParent(), pStyle->GetFamily() );
+ DBG_ASSERT( pParent, "Parent nicht gefunden!" );
+ rOutput << OOO_STRING_SVTOOLS_RTF_SBASEDON;
+ nNumber = (sal_uInt16) getStylePos( GetStyleSheetPool()->GetStyles(), pParent ) + 1;
+ rOutput.WriteNumber( nNumber );
+ }
+
+ // Folgevorlage...(immer)
+ SfxStyleSheet* pNext = pStyle;
+ if ( pStyle->GetFollow().Len() && ( pStyle->GetFollow() != pStyle->GetName() ) )
+ pNext = (SfxStyleSheet*)GetStyleSheetPool()->Find( pStyle->GetFollow(), pStyle->GetFamily() );
+
+ DBG_ASSERT( pNext, "Naechsten nicht gefunden!" );
+ rOutput << OOO_STRING_SVTOOLS_RTF_SNEXT;
+ nNumber = (sal_uInt16) getStylePos( GetStyleSheetPool()->GetStyles(), pNext ) + 1;
+ rOutput.WriteNumber( nNumber );
+
+ // Namen der Vorlage...
+ rOutput << " " << ByteString( pStyle->GetName(), eDestEnc ).GetBuffer();
+ rOutput << ";}";
+ }
+ rOutput << '}';
+ rOutput << endl;
+ }
+ }
+
+ // Die Pool-Defaults vorweg schreiben...
+ rOutput << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << "\\EditEnginePoolDefaults";
+ for ( sal_uInt16 nPoolDefItem = EE_PARA_START; nPoolDefItem <= EE_CHAR_END; nPoolDefItem++)
+ {
+ const SfxPoolItem& rItem = aEditDoc.GetItemPool().GetDefaultItem( nPoolDefItem );
+ WriteItemAsRTF( rItem, rOutput, 0, 0, aFontTable, aColorList );
+ }
+ rOutput << '}' << endl;
+
+ // Def-Hoehe vorweg, da sonst 12Pt
+ // Doch nicht, onst in jedem Absatz hart!
+ // SfxItemSet aTmpSet( GetEmptyItemSet() );
+ // const SvxFontHeightItem& rDefFontHeight = (const SvxFontHeightItem&)aTmpSet.Get( EE_CHAR_FONTHEIGHT );
+ // WriteItemAsRTF( rDefFontHeight, rOutput, aFontTable, aColorList );
+ // rOutput << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << "\\EditEnginePoolDefaultHeight}" << endl;
+
+ // DefTab:
+ MapMode aTwpMode( MAP_TWIP );
+ sal_uInt16 nDefTabTwps = (sal_uInt16) GetRefDevice()->LogicToLogic(
+ Point( aEditDoc.GetDefTab(), 0 ),
+ &GetRefMapMode(), &aTwpMode ).X();
+ rOutput << OOO_STRING_SVTOOLS_RTF_DEFTAB;
+ rOutput.WriteNumber( nDefTabTwps );
+ rOutput << endl;
+
+ // ueber die Absaetze iterieren...
+ rOutput << '{' << endl;
+ for ( sal_uInt16 nNode = nStartNode; nNode <= nEndNode; nNode++ )
+ {
+ ContentNode* pNode = aEditDoc.SaveGetObject( nNode );
+ DBG_ASSERT( pNode, "Node nicht gefunden: Search&Replace" );
+
+ // Die Absatzattribute vorweg...
+ sal_Bool bAttr = sal_False;
+
+ // Vorlage ?
+ if ( pNode->GetStyleSheet() )
+ {
+ // Nummer der Vorlage
+ rOutput << OOO_STRING_SVTOOLS_RTF_S;
+ sal_uInt16 nNumber = (sal_uInt16) getStylePos( GetStyleSheetPool()->GetStyles(), pNode->GetStyleSheet() ) + 1;
+ rOutput.WriteNumber( nNumber );
+
+ // Alle Attribute
+ // Attribute, auch aus Parent!
+ for ( sal_uInt16 nParAttr = EE_PARA_START; nParAttr <= EE_CHAR_END; nParAttr++ )
+ {
+ if ( pNode->GetStyleSheet()->GetItemSet().GetItemState( nParAttr ) == SFX_ITEM_ON )
+ {
+ const SfxPoolItem& rItem = pNode->GetStyleSheet()->GetItemSet().Get( nParAttr );
+ WriteItemAsRTF( rItem, rOutput, nNode, 0, aFontTable, aColorList );
+ bAttr = sal_True;
+ }
+ }
+ }
+
+ for ( sal_uInt16 nParAttr = EE_PARA_START; nParAttr <= EE_CHAR_END; nParAttr++ )
+ {
+// const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItem( nParAttr );
+ // Jetzt, wo StyleSheet-Verarbeitung, nur noch harte Absatzattribute!
+ if ( pNode->GetContentAttribs().GetItems().GetItemState( nParAttr ) == SFX_ITEM_ON )
+ {
+ const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItems().Get( nParAttr );
+ WriteItemAsRTF( rItem, rOutput, nNode, 0, aFontTable, aColorList );
+ bAttr = sal_True;
+ }
+ }
+ if ( bAttr )
+ rOutput << ' '; // Separator
+
+ ItemList aAttribItems;
+ ParaPortion* pParaPortion = FindParaPortion( pNode );
+ DBG_ASSERT( pParaPortion, "Portion nicht gefunden: WriteRTF" );
+
+ sal_uInt16 nIndex = 0;
+ sal_uInt16 nStartPos = 0;
+ sal_uInt16 nEndPos = pNode->Len();
+ sal_uInt16 nStartPortion = 0;
+ sal_uInt16 nEndPortion = (sal_uInt16)pParaPortion->GetTextPortions().Count() - 1;
+ sal_Bool bFinishPortion = sal_False;
+ sal_uInt16 nPortionStart;
+
+ if ( nNode == nStartNode )
+ {
+ nStartPos = aSel.Min().GetIndex();
+ nStartPortion = pParaPortion->GetTextPortions().FindPortion( nStartPos, nPortionStart );
+ if ( nStartPos != 0 )
+ {
+ aAttribItems.Clear();
+ lcl_FindValidAttribs( aAttribItems, pNode, nStartPos, GetScriptType( EditPaM( pNode, 0 ) ) );
+ if ( aAttribItems.Count() )
+ {
+ // Diese Attribute duerfen nicht fuer den gesamten
+ // Absatz gelten:
+ rOutput << '{';
+ WriteItemListAsRTF( aAttribItems, rOutput, nNode, nStartPos, aFontTable, aColorList );
+ bFinishPortion = sal_True;
+ }
+ aAttribItems.Clear();
+ }
+ }
+ if ( nNode == nEndNode ) // kann auch == nStart sein!
+ {
+ nEndPos = aSel.Max().GetIndex();
+ nEndPortion = pParaPortion->GetTextPortions().FindPortion( nEndPos, nPortionStart );
+ }
+
+ EditCharAttrib* pNextFeature = pNode->GetCharAttribs().FindFeature( nIndex );
+ // Bei 0 anfangen, damit der Index richtig ist...
+
+ for ( sal_uInt16 n = 0; n <= nEndPortion; n++ )
+ {
+ TextPortion* pTextPortion = pParaPortion->GetTextPortions().GetObject(n);
+ if ( n < nStartPortion )
+ {
+ nIndex = nIndex + pTextPortion->GetLen();
+ continue;
+ }
+
+ if ( pNextFeature && ( pNextFeature->GetStart() == nIndex ) && ( pNextFeature->GetItem()->Which() != EE_FEATURE_FIELD ) )
+ {
+ WriteItemAsRTF( *pNextFeature->GetItem(), rOutput, nNode, nIndex, aFontTable, aColorList );
+ pNextFeature = pNode->GetCharAttribs().FindFeature( pNextFeature->GetStart() + 1 );
+ }
+ else
+ {
+ aAttribItems.Clear();
+ USHORT nScriptType = GetScriptType( EditPaM( pNode, nIndex+1 ) );
+ if ( !n || IsScriptChange( EditPaM( pNode, nIndex ) ) )
+ {
+ SfxItemSet aAttribs = GetAttribs( nNode, nIndex+1, nIndex+1 );
+ aAttribItems.Insert( &aAttribs.Get( GetScriptItemId( EE_CHAR_FONTINFO, nScriptType ) ), LIST_APPEND );
+ aAttribItems.Insert( &aAttribs.Get( GetScriptItemId( EE_CHAR_FONTHEIGHT, nScriptType ) ), LIST_APPEND );
+ aAttribItems.Insert( &aAttribs.Get( GetScriptItemId( EE_CHAR_WEIGHT, nScriptType ) ), LIST_APPEND );
+ aAttribItems.Insert( &aAttribs.Get( GetScriptItemId( EE_CHAR_ITALIC, nScriptType ) ), LIST_APPEND );
+ aAttribItems.Insert( &aAttribs.Get( GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType ) ), LIST_APPEND );
+ }
+ // #96298# Insert hard attribs AFTER CJK attribs...
+ lcl_FindValidAttribs( aAttribItems, pNode, nIndex, nScriptType );
+
+ rOutput << '{';
+ if ( WriteItemListAsRTF( aAttribItems, rOutput, nNode, nIndex, aFontTable, aColorList ) )
+ rOutput << ' ';
+
+ USHORT nS = nIndex;
+ USHORT nE = nIndex + pTextPortion->GetLen();
+ if ( n == nStartPortion )
+ nS = nStartPos;
+ if ( n == nEndPortion )
+ nE = nEndPos;
+
+ XubString aRTFStr = aEditDoc.GetParaAsString( pNode, nS, nE);
+ RTFOutFuncs::Out_String( rOutput, aRTFStr, eDestEnc );
+ rOutput << '}';
+ }
+ if ( bFinishPortion )
+ {
+ rOutput << '}';
+ bFinishPortion = sal_False;
+ }
+
+ nIndex = nIndex + pTextPortion->GetLen();
+ }
+
+ rOutput << OOO_STRING_SVTOOLS_RTF_PAR << OOO_STRING_SVTOOLS_RTF_PARD << OOO_STRING_SVTOOLS_RTF_PLAIN;;
+ rOutput << endl;
+ }
+ // RTF-Nachspann...
+ rOutput << "}}"; // 1xKlammerung Absaetze, 1x Klammerung RTF-Dokument
+ rOutput.Flush();
+
+#if defined (EDITDEBUG) && !defined( UNX )
+ {
+ SvFileStream aStream( String( RTL_CONSTASCII_USTRINGPARAM ( "d:\\rtf_out.rtf" ) ), STREAM_WRITE|STREAM_TRUNC );
+ ULONG nP = rOutput.Tell();
+ rOutput.Seek( 0 );
+ aStream << rOutput;
+ rOutput.Seek( nP );
+ }
+#endif
+
+ return rOutput.GetError();
+#else
+ return 0;
+#endif
+}
+
+
+void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, sal_uInt16 nPara, sal_uInt16 nPos,
+ SvxFontTable& rFontTable, SvxColorList& rColorList )
+{
+ sal_uInt16 nWhich = rItem.Which();
+ switch ( nWhich )
+ {
+ case EE_PARA_WRITINGDIR:
+ {
+ const SvxFrameDirectionItem& rWritingMode = (const SvxFrameDirectionItem&)rItem;
+ if ( rWritingMode.GetValue() == FRMDIR_HORI_RIGHT_TOP )
+ rOutput << "\\rtlpar";
+ else
+ rOutput << "\\ltrpar";
+ }
+ break;
+ case EE_PARA_OUTLLEVEL:
+ {
+ sal_Int16 nLevel = ((const SfxInt16Item&)rItem).GetValue();
+ if( nLevel >= 0 )
+ {
+ rOutput << "\\level";
+ rOutput.WriteNumber( nLevel );
+ }
+ }
+ break;
+ case EE_PARA_OUTLLRSPACE:
+ case EE_PARA_LRSPACE:
+ {
+// const ContentNode *pNode = aEditDoc.GetObject( nPara );
+
+ rOutput << OOO_STRING_SVTOOLS_RTF_FI;
+ short nTxtFirst = ((const SvxLRSpaceItem&)rItem).GetTxtFirstLineOfst();
+ nTxtFirst = (short)LogicToTwips( nTxtFirst );
+ rOutput.WriteNumber( nTxtFirst );
+ rOutput << OOO_STRING_SVTOOLS_RTF_LI;
+ sal_uInt16 nTxtLeft = static_cast< sal_uInt16 >(((const SvxLRSpaceItem&)rItem).GetTxtLeft());
+ nTxtLeft = (sal_uInt16)LogicToTwips( nTxtLeft );
+ rOutput.WriteNumber( nTxtLeft );
+ rOutput << OOO_STRING_SVTOOLS_RTF_RI;
+ sal_uInt32 nTxtRight = ((const SvxLRSpaceItem&)rItem).GetRight();
+ nTxtRight = LogicToTwips( nTxtRight);
+ rOutput.WriteNumber( nTxtRight );
+ }
+ break;
+ case EE_PARA_ULSPACE:
+ {
+ rOutput << OOO_STRING_SVTOOLS_RTF_SB;
+ sal_uInt16 nUpper = ((const SvxULSpaceItem&)rItem).GetUpper();
+ nUpper = (sal_uInt16)LogicToTwips( nUpper );
+ rOutput.WriteNumber( nUpper );
+ rOutput << OOO_STRING_SVTOOLS_RTF_SA;
+ sal_uInt16 nLower = ((const SvxULSpaceItem&)rItem).GetLower();
+ nLower = (sal_uInt16)LogicToTwips( nLower );
+ rOutput.WriteNumber( nLower );
+ }
+ break;
+ case EE_PARA_SBL:
+ {
+ rOutput << OOO_STRING_SVTOOLS_RTF_SL;
+ long nVal = ((const SvxLineSpacingItem&)rItem).GetLineHeight();
+ char cMult = '0';
+ if ( ((const SvxLineSpacingItem&)rItem).GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP )
+ {
+ // Woher kriege ich jetzt den Wert?
+ // Der SwRTF-Parser geht von einem 240er Font aus!
+ nVal = ((const SvxLineSpacingItem&)rItem).GetPropLineSpace();
+ nVal *= 240;
+ nVal /= 100;
+ cMult = '1';
+ }
+ rOutput.WriteNumber( nVal );
+ rOutput << OOO_STRING_SVTOOLS_RTF_SLMULT << cMult;
+ }
+ break;
+ case EE_PARA_JUST:
+ {
+ SvxAdjust eJustification = ((const SvxAdjustItem&)rItem).GetAdjust();
+ switch ( eJustification )
+ {
+ case SVX_ADJUST_CENTER: rOutput << OOO_STRING_SVTOOLS_RTF_QC;
+ break;
+ case SVX_ADJUST_RIGHT: rOutput << OOO_STRING_SVTOOLS_RTF_QR;
+ break;
+ default: rOutput << OOO_STRING_SVTOOLS_RTF_QL;
+ break;
+ }
+ }
+ break;
+ case EE_PARA_TABS:
+ {
+ const SvxTabStopItem& rTabs = (const SvxTabStopItem&) rItem;
+ for ( sal_uInt16 i = 0; i < rTabs.Count(); i++ )
+ {
+ const SvxTabStop& rTab = rTabs[i];
+ rOutput << OOO_STRING_SVTOOLS_RTF_TX;
+ rOutput.WriteNumber( LogicToTwips( rTab.GetTabPos() ) );
+ }
+ }
+ break;
+ case EE_CHAR_COLOR:
+ {
+ sal_uInt32 n = rColorList.GetId( (const SvxColorItem&)rItem );
+ rOutput << OOO_STRING_SVTOOLS_RTF_CF;
+ rOutput.WriteNumber( n );
+ }
+ break;
+ case EE_CHAR_FONTINFO:
+ case EE_CHAR_FONTINFO_CJK:
+ case EE_CHAR_FONTINFO_CTL:
+ {
+ sal_uInt32 n = rFontTable.GetId( (const SvxFontItem&)rItem );
+ rOutput << OOO_STRING_SVTOOLS_RTF_F;
+ rOutput.WriteNumber( n );
+ }
+ break;
+ case EE_CHAR_FONTHEIGHT:
+ case EE_CHAR_FONTHEIGHT_CJK:
+ case EE_CHAR_FONTHEIGHT_CTL:
+ {
+ rOutput << OOO_STRING_SVTOOLS_RTF_FS;
+ long nHeight = ((const SvxFontHeightItem&)rItem).GetHeight();
+ nHeight = LogicToTwips( nHeight );
+ // Twips => HalfPoints
+ nHeight /= 10;
+ rOutput.WriteNumber( nHeight );
+ }
+ break;
+ case EE_CHAR_WEIGHT:
+ case EE_CHAR_WEIGHT_CJK:
+ case EE_CHAR_WEIGHT_CTL:
+ {
+ FontWeight e = ((const SvxWeightItem&)rItem).GetWeight();
+ switch ( e )
+ {
+ case WEIGHT_BOLD: rOutput << OOO_STRING_SVTOOLS_RTF_B; break;
+ default: rOutput << OOO_STRING_SVTOOLS_RTF_B << '0'; break;
+ }
+ }
+ break;
+ case EE_CHAR_UNDERLINE:
+ {
+ // muesste bei WordLineMode ggf. ulw werden,
+ // aber die Information fehlt hier
+ FontUnderline e = ((const SvxUnderlineItem&)rItem).GetLineStyle();
+ switch ( e )
+ {
+ case UNDERLINE_NONE: rOutput << OOO_STRING_SVTOOLS_RTF_ULNONE; break;
+ case UNDERLINE_SINGLE: rOutput << OOO_STRING_SVTOOLS_RTF_UL; break;
+ case UNDERLINE_DOUBLE: rOutput << OOO_STRING_SVTOOLS_RTF_ULDB; break;
+ case UNDERLINE_DOTTED: rOutput << OOO_STRING_SVTOOLS_RTF_ULD; break;
+ default:
+ break;
+ }
+ }
+ break;
+ case EE_CHAR_OVERLINE:
+ {
+ FontUnderline e = ((const SvxOverlineItem&)rItem).GetLineStyle();
+ switch ( e )
+ {
+ case UNDERLINE_NONE: rOutput << OOO_STRING_SVTOOLS_RTF_OLNONE; break;
+ case UNDERLINE_SINGLE: rOutput << OOO_STRING_SVTOOLS_RTF_OL; break;
+ case UNDERLINE_DOUBLE: rOutput << OOO_STRING_SVTOOLS_RTF_OLDB; break;
+ case UNDERLINE_DOTTED: rOutput << OOO_STRING_SVTOOLS_RTF_OLD; break;
+ default:
+ break;
+ }
+ }
+ break;
+ case EE_CHAR_STRIKEOUT:
+ {
+ FontStrikeout e = ((const SvxCrossedOutItem&)rItem).GetStrikeout();
+ switch ( e )
+ {
+ case STRIKEOUT_SINGLE:
+ case STRIKEOUT_DOUBLE: rOutput << OOO_STRING_SVTOOLS_RTF_STRIKE; break;
+ case STRIKEOUT_NONE: rOutput << OOO_STRING_SVTOOLS_RTF_STRIKE << '0'; break;
+ default:
+ break;
+ }
+ }
+ break;
+ case EE_CHAR_ITALIC:
+ case EE_CHAR_ITALIC_CJK:
+ case EE_CHAR_ITALIC_CTL:
+ {
+ FontItalic e = ((const SvxPostureItem&)rItem).GetPosture();
+ switch ( e )
+ {
+ case ITALIC_OBLIQUE:
+ case ITALIC_NORMAL: rOutput << OOO_STRING_SVTOOLS_RTF_I; break;
+ case ITALIC_NONE: rOutput << OOO_STRING_SVTOOLS_RTF_I << '0'; break;
+ default:
+ break;
+ }
+ }
+ break;
+ case EE_CHAR_OUTLINE:
+ {
+ rOutput << OOO_STRING_SVTOOLS_RTF_OUTL;
+ if ( ((const SvxContourItem&)rItem).GetValue() == 0 )
+ rOutput << '0';
+ }
+ break;
+ case EE_CHAR_RELIEF:
+ {
+ USHORT nRelief = ((const SvxCharReliefItem&)rItem).GetValue();
+ if ( nRelief == RELIEF_EMBOSSED )
+ rOutput << OOO_STRING_SVTOOLS_RTF_EMBO;
+ if ( nRelief == RELIEF_ENGRAVED )
+ rOutput << OOO_STRING_SVTOOLS_RTF_IMPR;
+ }
+ break;
+ case EE_CHAR_EMPHASISMARK:
+ {
+ USHORT nMark = ((const SvxEmphasisMarkItem&)rItem).GetValue();
+ if ( nMark == EMPHASISMARK_NONE )
+ rOutput << OOO_STRING_SVTOOLS_RTF_ACCNONE;
+ else if ( nMark == EMPHASISMARK_SIDE_DOTS )
+ rOutput << OOO_STRING_SVTOOLS_RTF_ACCCOMMA;
+ else
+ rOutput << OOO_STRING_SVTOOLS_RTF_ACCDOT;
+ }
+ break;
+ case EE_CHAR_SHADOW:
+ {
+ rOutput << OOO_STRING_SVTOOLS_RTF_SHAD;
+ if ( ((const SvxShadowedItem&)rItem).GetValue() == 0 )
+ rOutput << '0';
+ }
+ break;
+ case EE_FEATURE_TAB:
+ {
+ rOutput << OOO_STRING_SVTOOLS_RTF_TAB;
+ }
+ break;
+ case EE_FEATURE_LINEBR:
+ {
+ rOutput << OOO_STRING_SVTOOLS_RTF_SL;
+ }
+ break;
+ case EE_CHAR_KERNING:
+ {
+ rOutput << OOO_STRING_SVTOOLS_RTF_EXPNDTW;
+ rOutput.WriteNumber( LogicToTwips(
+ ((const SvxKerningItem&)rItem).GetValue() ) );
+ }
+ break;
+ case EE_CHAR_PAIRKERNING:
+ {
+ rOutput << OOO_STRING_SVTOOLS_RTF_KERNING;
+ rOutput.WriteNumber( ((const SvxAutoKernItem&)rItem).GetValue() ? 1 : 0 );
+ }
+ break;
+ case EE_CHAR_ESCAPEMENT:
+ {
+ SvxFont aFont;
+ ContentNode* pNode = aEditDoc.GetObject( nPara );
+ SeekCursor( pNode, nPos, aFont );
+ MapMode aPntMode( MAP_POINT );
+ long nFontHeight = GetRefDevice()->LogicToLogic(
+ aFont.GetSize(), &GetRefMapMode(), &aPntMode ).Height();
+ nFontHeight *=2; // HalfPoints
+ sal_uInt16 nProp = ((const SvxEscapementItem&)rItem).GetProp();
+ sal_uInt16 nProp100 = nProp*100; // Fuer SWG-Token Prop in 100tel Prozent.
+ short nEsc = ((const SvxEscapementItem&)rItem).GetEsc();
+ if ( nEsc == DFLT_ESC_AUTO_SUPER )
+ {
+ nEsc = 100 - nProp;
+ nProp100++; // Eine 1 hinten bedeutet 'automatisch'.
+ }
+ else if ( nEsc == DFLT_ESC_AUTO_SUB )
+ {
+ nEsc = sal::static_int_cast< short >( -( 100 - nProp ) );
+ nProp100++;
+ }
+ // SWG:
+ if ( nEsc )
+ rOutput << "{\\*\\updnprop" << ByteString::CreateFromInt32( nProp100 ).GetBuffer() << '}';
+ long nUpDown = nFontHeight * Abs( nEsc ) / 100;
+ ByteString aUpDown = ByteString::CreateFromInt32( nUpDown );
+ if ( nEsc < 0 )
+ rOutput << OOO_STRING_SVTOOLS_RTF_DN << aUpDown.GetBuffer();
+ else if ( nEsc > 0 )
+ rOutput << OOO_STRING_SVTOOLS_RTF_UP << aUpDown.GetBuffer();
+ }
+ break;
+ }
+}
+
+sal_uInt32 ImpEditEngine::WriteHTML( SvStream&, EditSelection )
+{
+ return 0;
+}
+
+
+EditTextObject* ImpEditEngine::CreateTextObject()
+{
+ EditSelection aCompleteSelection;
+ aCompleteSelection.Min() = aEditDoc.GetStartPaM();
+ aCompleteSelection.Max() = aEditDoc.GetEndPaM();
+
+ return CreateTextObject( aCompleteSelection );
+}
+
+EditTextObject* ImpEditEngine::CreateTextObject( EditSelection aSel )
+{
+ return CreateBinTextObject( aSel, GetEditTextObjectPool(), aStatus.AllowBigObjects(), nBigTextObjectStart );
+}
+
+EditTextObject* ImpEditEngine::CreateBinTextObject( EditSelection aSel, SfxItemPool* pPool, sal_Bool bAllowBigObjects, sal_uInt16 nBigObjectStart ) const
+{
+ BinTextObject* pTxtObj = new BinTextObject( pPool );
+ pTxtObj->SetVertical( IsVertical() );
+ MapUnit eMapUnit = (MapUnit)aEditDoc.GetItemPool().GetMetric( DEF_METRIC );
+ pTxtObj->SetMetric( (sal_uInt16) eMapUnit );
+ if ( pTxtObj->IsOwnerOfPool() )
+ pTxtObj->GetPool()->SetDefaultMetric( (SfxMapUnit) eMapUnit );
+
+ sal_uInt16 nStartNode, nEndNode;
+ sal_uInt32 nTextPortions = 0;
+
+ aSel.Adjust( aEditDoc );
+ nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
+ nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
+
+ sal_Bool bOnlyFullParagraphs = ( aSel.Min().GetIndex() ||
+ ( aSel.Max().GetIndex() < aSel.Max().GetNode()->Len() ) ) ?
+ sal_False : sal_True;
+
+ // Vorlagen werden nicht gespeichert!
+ // ( Nur Name und Familie, Vorlage selbst muss in App stehen! )
+
+ pTxtObj->SetScriptType( GetScriptType( aSel ) );
+
+ // ueber die Absaetze iterieren...
+ sal_uInt16 nNode;
+ for ( nNode = nStartNode; nNode <= nEndNode; nNode++ )
+ {
+ ContentNode* pNode = aEditDoc.SaveGetObject( nNode );
+ DBG_ASSERT( pNode, "Node nicht gefunden: Search&Replace" );
+
+ if ( bOnlyFullParagraphs )
+ {
+ ParaPortion* pParaPortion = GetParaPortions()[nNode];
+ nTextPortions += pParaPortion->GetTextPortions().Count();
+ }
+
+ sal_uInt16 nStartPos = 0;
+ sal_uInt16 nEndPos = pNode->Len();
+
+ sal_Bool bEmptyPara = nEndPos ? sal_False : sal_True;
+
+ if ( ( nNode == nStartNode ) && !bOnlyFullParagraphs )
+ nStartPos = aSel.Min().GetIndex();
+ if ( ( nNode == nEndNode ) && !bOnlyFullParagraphs )
+ nEndPos = aSel.Max().GetIndex();
+
+
+ ContentInfo* pC = pTxtObj->CreateAndInsertContent();
+
+ // Die Absatzattribute...
+ pC->GetParaAttribs().Set( pNode->GetContentAttribs().GetItems() );
+
+ // Das StyleSheet...
+ if ( pNode->GetStyleSheet() )
+ {
+ pC->GetStyle() = pNode->GetStyleSheet()->GetName();
+ pC->GetFamily() = pNode->GetStyleSheet()->GetFamily();
+ }
+
+ // Der Text...
+ pC->GetText() = pNode->Copy( nStartPos, nEndPos-nStartPos );
+
+ // und die Attribute...
+ sal_uInt16 nAttr = 0;
+ EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
+ while ( pAttr )
+ {
+ // In einem leeren Absatz die Attribute behalten!
+ if ( bEmptyPara ||
+ ( ( pAttr->GetEnd() > nStartPos ) && ( pAttr->GetStart() < nEndPos ) ) )
+ {
+ XEditAttribute* pX = pTxtObj->CreateAttrib( *pAttr->GetItem(), pAttr->GetStart(), pAttr->GetEnd() );
+ // Evtl. korrigieren...
+ if ( ( nNode == nStartNode ) && ( nStartPos != 0 ) )
+ {
+ pX->GetStart() = ( pX->GetStart() > nStartPos ) ? pX->GetStart()-nStartPos : 0;
+ pX->GetEnd() = pX->GetEnd() - nStartPos;
+
+ }
+ if ( nNode == nEndNode )
+ {
+ if ( pX->GetEnd() > (nEndPos-nStartPos) )
+ pX->GetEnd() = nEndPos-nStartPos;
+ }
+ DBG_ASSERT( pX->GetEnd() <= (nEndPos-nStartPos), "CreateBinTextObject: Attribut zu lang!" );
+ if ( !pX->GetLen() && !bEmptyPara )
+ pTxtObj->DestroyAttrib( pX );
+ else
+ pC->GetAttribs().Insert( pX, pC->GetAttribs().Count() );
+ }
+ nAttr++;
+ pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
+ }
+
+#ifndef SVX_LIGHT
+ // ggf. Online-Spelling
+ if ( bAllowBigObjects && bOnlyFullParagraphs && pNode->GetWrongList() )
+ pC->SetWrongList( pNode->GetWrongList()->Clone() );
+#endif // !SVX_LIGHT
+
+ }
+
+ // Bei grossen Textobjekten die PortionInfos merken:
+ // Schwelle rauf setzen, wenn Olli die Absaetze nicht mehr zerhackt!
+ if ( bAllowBigObjects && bOnlyFullParagraphs && IsFormatted() && GetUpdateMode() && ( nTextPortions >= nBigObjectStart ) )
+ {
+ XParaPortionList* pXList = new XParaPortionList( GetRefDevice(), aPaperSize.Width() );
+ pTxtObj->SetPortionInfo( pXList );
+ for ( nNode = nStartNode; nNode <= nEndNode; nNode++ )
+ {
+ ParaPortion* pParaPortion = GetParaPortions()[nNode];
+ XParaPortion* pX = new XParaPortion;
+ pXList->Insert( pX, pXList->Count() );
+
+ pX->nHeight = pParaPortion->GetHeight();
+ pX->nFirstLineOffset = pParaPortion->GetFirstLineOffset();
+
+ // Die TextPortions
+ sal_uInt16 nCount = pParaPortion->GetTextPortions().Count();
+ sal_uInt16 n;
+ for ( n = 0; n < nCount; n++ )
+ {
+ TextPortion* pTextPortion = pParaPortion->GetTextPortions()[n];
+ TextPortion* pNew = new TextPortion( *pTextPortion );
+ pX->aTextPortions.Insert( pNew, pX->aTextPortions.Count() );
+ }
+
+ // Die Zeilen
+ nCount = pParaPortion->GetLines().Count();
+ for ( n = 0; n < nCount; n++ )
+ {
+ EditLine* pLine = pParaPortion->GetLines()[n];
+ EditLine* pNew = pLine->Clone();
+ pX->aLines.Insert( pNew, pX->aLines.Count() );
+ }
+#ifdef DBG_UTIL
+ USHORT nTest;
+ int nTPLen = 0, nTxtLen = 0;
+ for ( nTest = pParaPortion->GetTextPortions().Count(); nTest; )
+ nTPLen += pParaPortion->GetTextPortions().GetObject( --nTest )->GetLen();
+ for ( nTest = pParaPortion->GetLines().Count(); nTest; )
+ nTxtLen += pParaPortion->GetLines().GetObject( --nTest )->GetLen();
+ DBG_ASSERT( ( nTPLen == pParaPortion->GetNode()->Len() ) && ( nTxtLen == pParaPortion->GetNode()->Len() ), "CreateBinTextObject: ParaPortion not completely formatted!" );
+#endif
+ }
+ }
+ return pTxtObj;
+}
+
+void ImpEditEngine::SetText( const EditTextObject& rTextObject )
+{
+ // Da Setzen eines TextObject ist nicht Undo-faehig!
+ ResetUndoManager();
+ sal_Bool _bUpdate = GetUpdateMode();
+ sal_Bool _bUndo = IsUndoEnabled();
+
+ SetText( XubString() );
+ EditPaM aPaM = aEditDoc.GetStartPaM();
+
+ SetUpdateMode( sal_False );
+ EnableUndo( sal_False );
+
+ InsertText( rTextObject, EditSelection( aPaM, aPaM ) );
+ SetVertical( rTextObject.IsVertical() );
+
+#ifndef SVX_LIGHT
+ DBG_ASSERT( !HasUndoManager() || !GetUndoManager().GetUndoActionCount(), "Woher kommt das Undo in SetText ?!" );
+#endif
+ SetUpdateMode( _bUpdate );
+ EnableUndo( _bUndo );
+}
+
+EditSelection ImpEditEngine::InsertText( const EditTextObject& rTextObject, EditSelection aSel )
+{
+ EnterBlockNotifications();
+ aSel.Adjust( aEditDoc );
+ if ( aSel.HasRange() )
+ aSel = ImpDeleteSelection( aSel );
+ EditSelection aNewSel = InsertBinTextObject( (BinTextObject&)rTextObject, aSel.Max() );
+ LeaveBlockNotifications();
+ return aNewSel;
+
+ // MT 05/00: InsertBinTextObject direkt hier machen...
+}
+
+EditSelection ImpEditEngine::InsertBinTextObject( BinTextObject& rTextObject, EditPaM aPaM )
+{
+ // Optimieren:
+ // Kein GetPos undFindParaportion, sondern Index berechnen!
+ EditSelection aSel( aPaM, aPaM );
+ DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "InsertBibTextObject: Selektion kaput!(1)" );
+
+ sal_Bool bUsePortionInfo = sal_False;
+// sal_Bool bFields = sal_False;
+ XParaPortionList* pPortionInfo = rTextObject.GetPortionInfo();
+
+ if ( pPortionInfo && ( (long)pPortionInfo->GetPaperWidth() == aPaperSize.Width() )
+ && ( pPortionInfo->GetRefMapMode() == GetRefDevice()->GetMapMode() ) )
+ {
+ if ( ( pPortionInfo->GetRefDevPtr() == (sal_uIntPtr)GetRefDevice() ) ||
+ ( ( pPortionInfo->GetRefDevType() == OUTDEV_VIRDEV ) &&
+ ( GetRefDevice()->GetOutDevType() == OUTDEV_VIRDEV ) ) )
+ bUsePortionInfo = sal_True;
+ }
+
+ sal_Bool bConvertItems = sal_False;
+ MapUnit eSourceUnit = MapUnit(), eDestUnit = MapUnit();
+ if ( rTextObject.HasMetric() )
+ {
+ eSourceUnit = (MapUnit)rTextObject.GetMetric();
+ eDestUnit = (MapUnit)aEditDoc.GetItemPool().GetMetric( DEF_METRIC );
+ if ( eSourceUnit != eDestUnit )
+ bConvertItems = sal_True;
+ }
+
+ sal_uInt16 nContents = rTextObject.GetContents().Count();
+ sal_uInt16 nPara = aEditDoc.GetPos( aPaM.GetNode() );
+
+ for ( sal_uInt16 n = 0; n < nContents; n++, nPara++ )
+ {
+ ContentInfo* pC = rTextObject.GetContents().GetObject( n );
+ sal_Bool bNewContent = aPaM.GetNode()->Len() ? sal_False: sal_True;
+ sal_uInt16 nStartPos = aPaM.GetIndex();
+
+ aPaM = ImpFastInsertText( aPaM, pC->GetText() );
+
+ ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() );
+ DBG_ASSERT( pPortion, "Blinde Portion in FastInsertText" );
+ pPortion->MarkInvalid( nStartPos, pC->GetText().Len() );
+
+ // Zeicheattribute...
+ sal_Bool bAllreadyHasAttribs = aPaM.GetNode()->GetCharAttribs().Count() ? sal_True : sal_False;
+ sal_uInt16 nNewAttribs = pC->GetAttribs().Count();
+ if ( nNewAttribs )
+ {
+ BOOL bUpdateFields = FALSE;
+ for ( sal_uInt16 nAttr = 0; nAttr < nNewAttribs; nAttr++ )
+ {
+ XEditAttribute* pX = pC->GetAttribs().GetObject( nAttr );
+ // Kann passieren wenn Absaetze >16K entstehen, dann wird einfach umgebrochen.
+ if ( pX->GetEnd() <= aPaM.GetNode()->Len() )
+ {
+ if ( !bAllreadyHasAttribs || pX->IsFeature() )
+ {
+ // Normale Attribute gehen dann schneller...
+ // Features duerfen nicht ueber EditDoc::InsertAttrib
+ // eingefuegt werden, sie sind bei FastInsertText schon im TextFluss
+ DBG_ASSERT( pX->GetEnd() <= aPaM.GetNode()->Len(), "InsertBinTextObject: Attribut zu gross!" );
+ EditCharAttrib* pAttr;
+ if ( !bConvertItems )
+ pAttr = MakeCharAttrib( aEditDoc.GetItemPool(), *(pX->GetItem()), pX->GetStart()+nStartPos, pX->GetEnd()+nStartPos );
+ else
+ {
+ SfxPoolItem* pNew = pX->GetItem()->Clone();
+ ConvertItem( *pNew, eSourceUnit, eDestUnit );
+ pAttr = MakeCharAttrib( aEditDoc.GetItemPool(), *pNew, pX->GetStart()+nStartPos, pX->GetEnd()+nStartPos );
+ delete pNew;
+ }
+ DBG_ASSERT( pAttr->GetEnd() <= aPaM.GetNode()->Len(), "InsertBinTextObject: Attribut passt nicht! (1)" );
+ aPaM.GetNode()->GetCharAttribs().InsertAttrib( pAttr );
+ if ( pAttr->Which() == EE_FEATURE_FIELD )
+ bUpdateFields = TRUE;
+ }
+ else
+ {
+ DBG_ASSERT( pX->GetEnd()+nStartPos <= aPaM.GetNode()->Len(), "InsertBinTextObject: Attribut passt nicht! (2)" );
+ // Tabs und andere Features koennen nicht ueber InsertAttrib eingefuegt werden:
+ aEditDoc.InsertAttrib( aPaM.GetNode(), pX->GetStart()+nStartPos, pX->GetEnd()+nStartPos, *pX->GetItem() );
+ }
+ }
+ }
+ if ( bUpdateFields )
+ UpdateFields();
+
+ // Sonst QuickFormat => Keine Attribute!
+ pPortion->MarkSelectionInvalid( nStartPos, pC->GetText().Len() );
+ }
+
+ DBG_ASSERT( CheckOrderedList( aPaM.GetNode()->GetCharAttribs().GetAttribs(), sal_True ), "InsertBinTextObject: Start-Liste verdreht" );
+
+ sal_Bool bParaAttribs = sal_False;
+ if ( bNewContent || ( ( n > 0 ) && ( n < (nContents-1) ) ) )
+ {
+ bParaAttribs = sal_False;
+ // #101512# Don't overwrite level/style from existing paragraph in OutlineView
+ // MT 10/2002: Removed because of #103874#, handled in Outliner::EndPasteOrDropHdl now.
+// if ( !aStatus.IsOutliner() || n )
+ {
+ // nur dann Style und ParaAttribs, wenn neuer Absatz, oder
+ // komplett inneliegender...
+ bParaAttribs = pC->GetParaAttribs().Count() ? sal_True : sal_False;
+ if ( GetStyleSheetPool() && pC->GetStyle().Len() )
+ {
+ SfxStyleSheet* pStyle = (SfxStyleSheet*)GetStyleSheetPool()->Find( pC->GetStyle(), pC->GetFamily() );
+ DBG_ASSERT( pStyle, "InsertBinTextObject - Style not found!" );
+ SetStyleSheet( nPara, pStyle );
+ }
+ if ( !bConvertItems )
+ SetParaAttribs( aEditDoc.GetPos( aPaM.GetNode() ), pC->GetParaAttribs() );
+ else
+ {
+ SfxItemSet aAttribs( GetEmptyItemSet() );
+ ConvertAndPutItems( aAttribs, pC->GetParaAttribs(), &eSourceUnit, &eDestUnit );
+ SetParaAttribs( aEditDoc.GetPos( aPaM.GetNode() ), aAttribs );
+ }
+ }
+ if ( bNewContent && bUsePortionInfo )
+ {
+ XParaPortion* pXP = pPortionInfo->GetObject( n );
+ DBG_ASSERT( pXP, "InsertBinTextObject: PortionInfo?" );
+ ParaPortion* pParaPortion = GetParaPortions()[ nPara ];
+ DBG_ASSERT( pParaPortion, "InsertBinTextObject: ParaPortion?" );
+ pParaPortion->nHeight = pXP->nHeight;
+ pParaPortion->nFirstLineOffset = pXP->nFirstLineOffset;
+ pParaPortion->bForceRepaint = sal_True;
+ pParaPortion->SetValid(); // Nicht formatieren
+
+ // Die TextPortions
+ pParaPortion->GetTextPortions().Reset();
+ sal_uInt16 nCount = pXP->aTextPortions.Count();
+ for ( sal_uInt16 _n = 0; _n < nCount; _n++ )
+ {
+ TextPortion* pTextPortion = pXP->aTextPortions[_n];
+ TextPortion* pNew = new TextPortion( *pTextPortion );
+ pParaPortion->GetTextPortions().Insert( pNew, _n );
+ }
+
+ // Die Zeilen
+ pParaPortion->GetLines().Reset();
+ nCount = pXP->aLines.Count();
+ for ( sal_uInt16 m = 0; m < nCount; m++ )
+ {
+ EditLine* pLine = pXP->aLines[m];
+ EditLine* pNew = pLine->Clone();
+ pNew->SetInvalid(); // neu Painten!
+ pParaPortion->GetLines().Insert( pNew, m );
+ }
+#ifdef DBG_UTIL
+ USHORT nTest;
+ int nTPLen = 0, nTxtLen = 0;
+ for ( nTest = pParaPortion->GetTextPortions().Count(); nTest; )
+ nTPLen += pParaPortion->GetTextPortions().GetObject( --nTest )->GetLen();
+ for ( nTest = pParaPortion->GetLines().Count(); nTest; )
+ nTxtLen += pParaPortion->GetLines().GetObject( --nTest )->GetLen();
+ DBG_ASSERT( ( nTPLen == pParaPortion->GetNode()->Len() ) && ( nTxtLen == pParaPortion->GetNode()->Len() ), "InsertBinTextObject: ParaPortion not completely formatted!" );
+#endif
+ }
+ }
+ if ( !bParaAttribs ) // DefFont wird bei FastInsertParagraph nicht berechnet
+ {
+ aPaM.GetNode()->GetCharAttribs().GetDefFont() = aEditDoc.GetDefFont();
+ if ( aStatus.UseCharAttribs() )
+ aPaM.GetNode()->CreateDefFont();
+ }
+
+#ifndef SVX_LIGHT
+ if ( bNewContent && GetStatus().DoOnlineSpelling() && pC->GetWrongList() )
+ {
+ aPaM.GetNode()->DestroyWrongList(); // otherwise MLK, if list exists...
+ aPaM.GetNode()->SetWrongList( pC->GetWrongList()->Clone() );
+ }
+#endif // !SVX_LIGHT
+
+ // Zeilenumbruch, wenn weitere folgen...
+ if ( n < ( nContents-1) )
+ {
+ if ( bNewContent )
+ aPaM = ImpFastInsertParagraph( nPara+1 );
+ else
+ aPaM = ImpInsertParaBreak( aPaM, sal_False );
+ }
+ }
+
+ aSel.Max() = aPaM;
+ DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "InsertBibTextObject: Selektion kaput!(1)" );
+ return aSel;
+}
+
+LanguageType ImpEditEngine::GetLanguage( const EditPaM& rPaM, USHORT* pEndPos ) const
+{
+ short nScriptType = GetScriptType( rPaM, pEndPos ); // pEndPos will be valid now, pointing to ScriptChange or NodeLen
+ USHORT nLangId = GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType );
+ const SvxLanguageItem* pLangItem = &(const SvxLanguageItem&)rPaM.GetNode()->GetContentAttribs().GetItem( nLangId );
+ EditCharAttrib* pAttr = rPaM.GetNode()->GetCharAttribs().FindAttrib( nLangId, rPaM.GetIndex() );
+ if ( pAttr )
+ pLangItem = (const SvxLanguageItem*)pAttr->GetItem();
+
+ if ( pEndPos && pAttr && ( pAttr->GetEnd() < *pEndPos ) )
+ *pEndPos = pAttr->GetEnd();
+
+ return pLangItem->GetLanguage();
+}
+
+::com::sun::star::lang::Locale ImpEditEngine::GetLocale( const EditPaM& rPaM ) const
+{
+ return SvxCreateLocale( GetLanguage( rPaM ) );
+}
+
+Reference< XSpellChecker1 > ImpEditEngine::GetSpeller()
+{
+#ifndef SVX_LIGHT
+ if ( !xSpeller.is() )
+ xSpeller = SvxGetSpellChecker();
+#endif
+ return xSpeller;
+}
+
+EESpellState ImpEditEngine::Spell( EditView* pEditView, sal_Bool bMultipleDoc )
+{
+#ifdef SVX_LIGHT
+ return EE_SPELL_NOSPELLER;
+#else
+
+ DBG_ASSERTWARNING( xSpeller.is(), "Kein Speller gesetzt!" );
+
+ if ( !xSpeller.is() )
+ return EE_SPELL_NOSPELLER;
+
+ aOnlineSpellTimer.Stop();
+
+ // Bei MultipleDoc immer von vorne/hinten...
+ if ( bMultipleDoc )
+ {
+ pEditView->pImpEditView->SetEditSelection( aEditDoc.GetStartPaM() );
+ }
+
+ EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() );
+ pSpellInfo = new SpellInfo;
+ pSpellInfo->bMultipleDoc = bMultipleDoc;
+ pSpellInfo->aSpellStart = CreateEPaM( SelectWord( aCurSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD ).Min() );
+
+ sal_Bool bIsStart = sal_False;
+ if ( bMultipleDoc )
+ bIsStart = sal_True; // Immer von Vorne bzw. von hinten...
+ else if ( ( CreateEPaM( aEditDoc.GetStartPaM() ) == pSpellInfo->aSpellStart ) )
+ bIsStart = sal_True;
+
+ EditSpellWrapper* pWrp = new EditSpellWrapper( Application::GetDefDialogParent(),
+ xSpeller, bIsStart, sal_False, pEditView );
+ pWrp->SpellDocument();
+ delete pWrp;
+
+ if ( !bMultipleDoc )
+ {
+ pEditView->pImpEditView->DrawSelection();
+ if ( aCurSel.Max().GetIndex() > aCurSel.Max().GetNode()->Len() )
+ aCurSel.Max().GetIndex() = aCurSel.Max().GetNode()->Len();
+ aCurSel.Min() = aCurSel.Max();
+ pEditView->pImpEditView->SetEditSelection( aCurSel );
+ pEditView->pImpEditView->DrawSelection();
+ pEditView->ShowCursor( sal_True, sal_False );
+ }
+ EESpellState eState = pSpellInfo->eState;
+ delete pSpellInfo;
+ pSpellInfo = 0;
+ return eState;
+#endif
+}
+
+
+sal_Bool ImpEditEngine::HasConvertibleTextPortion( LanguageType nSrcLang )
+{
+#ifdef SVX_LIGHT
+ return sal_False;
+#else
+ sal_Bool bHasConvTxt = sal_False;
+
+ USHORT nParas = pEditEngine->GetParagraphCount();
+ for (USHORT k = 0; k < nParas; ++k)
+ {
+ SvUShorts aPortions;
+ pEditEngine->GetPortions( k, aPortions );
+ for ( USHORT nPos = 0; nPos < aPortions.Count(); ++nPos )
+ {
+ USHORT nEnd = aPortions.GetObject( nPos );
+ USHORT nStart = nPos > 0 ? aPortions.GetObject( nPos - 1 ) : 0;
+
+ // if the paragraph is not empty we need to increase the index
+ // by one since the attribute of the character left to the
+ // specified position is evaluated.
+ if (nEnd > nStart) // empty para?
+ ++nStart;
+ LanguageType nLangFound = pEditEngine->GetLanguage( k, nStart );
+#ifdef DEBUG
+ lang::Locale aLocale( SvxCreateLocale( nLangFound ) );
+#endif
+ bHasConvTxt = (nSrcLang == nLangFound) ||
+ (editeng::HangulHanjaConversion::IsChinese( nLangFound ) &&
+ editeng::HangulHanjaConversion::IsChinese( nSrcLang ));
+ if (bHasConvTxt)
+ return bHasConvTxt;
+ }
+ }
+
+#endif
+ return bHasConvTxt;
+}
+
+
+void ImpEditEngine::Convert( EditView* pEditView,
+ LanguageType nSrcLang, LanguageType nDestLang, const Font *pDestFont,
+ INT32 nOptions, sal_Bool bIsInteractive, sal_Bool bMultipleDoc )
+{
+ // modified version of ImpEditEngine::Spell
+
+#ifdef SVX_LIGHT
+#else
+
+ // Bei MultipleDoc immer von vorne/hinten...
+ if ( bMultipleDoc )
+ pEditView->pImpEditView->SetEditSelection( aEditDoc.GetStartPaM() );
+
+ //
+ // initialize pConvInfo
+ //
+ EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() );
+ aCurSel.Adjust( aEditDoc );
+ pConvInfo = new ConvInfo;
+ pConvInfo->bMultipleDoc = bMultipleDoc;
+ pConvInfo->aConvStart = CreateEPaM( aCurSel.Min() );
+ //
+ // if it is not just a selection and we are about to begin
+ // with the current conversion for the very first time
+ // we need to find the start of the current (initial)
+ // convertible unit in order for the text conversion to give
+ // the correct result for that. Since it is easier to obtain
+ // the start of the word we use that though.
+ if (!aCurSel.HasRange() && ImplGetBreakIterator().is())
+ {
+ EditPaM aWordStartPaM( SelectWord( aCurSel, i18n::WordType::DICTIONARY_WORD ).Min() );
+
+ // since #118246 / #117803 still occurs if the cursor is placed
+ // between the two chinese characters to be converted (because both
+ // of them are words on their own!) using the word boundary here does
+ // not work. Thus since chinese conversion is not interactive we start
+ // at the begin of the paragraph to solve the problem, i.e. have the
+ // TextConversion service get those characters together in the same call.
+ USHORT nStartIdx = ( editeng::HangulHanjaConversion::IsChinese( nSrcLang ) ) ?
+ 0 : aWordStartPaM.GetIndex();
+ pConvInfo->aConvStart.nIndex = nStartIdx;
+ }
+ //
+ pConvInfo->aConvContinue = pConvInfo->aConvStart;
+
+ sal_Bool bIsStart = sal_False;
+ if ( bMultipleDoc )
+ bIsStart = sal_True; // Immer von Vorne bzw. von hinten...
+ else if ( CreateEPaM( aEditDoc.GetStartPaM() ) == pConvInfo->aConvStart )
+ bIsStart = sal_True;
+
+ bImpConvertFirstCall = sal_True; // next ImpConvert call is the very first in this conversion turn
+
+ Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory();
+ TextConvWrapper aWrp( Application::GetDefDialogParent(), xMSF,
+ SvxCreateLocale( nSrcLang ), SvxCreateLocale( nDestLang ),
+ pDestFont,
+ nOptions, bIsInteractive,
+ bIsStart, pEditView );
+
+ //
+ //!! optimization does not work since when update mode is false
+ //!! the object is 'lying' about it portions, paragraphs,
+ //!! EndPaM... later on.
+ //!! Should not be a great problem since text boxes or cells in
+ //!! Calc usually have only a rather short text.
+ //
+ // disallow formatting, updating the view, ... while
+ // non-interactively converting the document. (saves time)
+ //if (!bIsInteractive)
+ // SetUpdateMode( FALSE );
+
+ aWrp.Convert();
+
+ //if (!bIsInteractive)
+ //SetUpdateMode( TRUE, 0, TRUE );
+
+ if ( !bMultipleDoc )
+ {
+ pEditView->pImpEditView->DrawSelection();
+ if ( aCurSel.Max().GetIndex() > aCurSel.Max().GetNode()->Len() )
+ aCurSel.Max().GetIndex() = aCurSel.Max().GetNode()->Len();
+ aCurSel.Min() = aCurSel.Max();
+ pEditView->pImpEditView->SetEditSelection( aCurSel );
+ pEditView->pImpEditView->DrawSelection();
+ pEditView->ShowCursor( sal_True, sal_False );
+ }
+ delete pConvInfo;
+ pConvInfo = 0;
+#endif
+}
+
+
+void ImpEditEngine::SetLanguageAndFont(
+ const ESelection &rESel,
+ LanguageType nLang, USHORT nLangWhichId,
+ const Font *pFont, USHORT nFontWhichId )
+{
+ ESelection aOldSel = pActiveView->GetSelection();
+ pActiveView->SetSelection( rESel );
+
+ // set new language attribute
+ SfxItemSet aNewSet( pActiveView->GetEmptyItemSet() );
+ aNewSet.Put( SvxLanguageItem( nLang, nLangWhichId ) );
+
+ // new font to be set?
+ DBG_ASSERT( pFont, "target font missing?" );
+ if (pFont)
+ {
+ // set new font attribute
+ SvxFontItem aFontItem = (SvxFontItem&) aNewSet.Get( nFontWhichId );
+ aFontItem.GetFamilyName() = pFont->GetName();
+ aFontItem.GetFamily() = pFont->GetFamily();
+ aFontItem.GetStyleName() = pFont->GetStyleName();
+ aFontItem.GetPitch() = pFont->GetPitch();
+ aFontItem.GetCharSet() = pFont->GetCharSet();
+ aNewSet.Put( aFontItem );
+ }
+
+ // apply new attributes
+ pActiveView->SetAttribs( aNewSet );
+
+ pActiveView->SetSelection( aOldSel );
+}
+
+
+void ImpEditEngine::ImpConvert( rtl::OUString &rConvTxt, LanguageType &rConvTxtLang,
+ EditView* pEditView, LanguageType nSrcLang, const ESelection &rConvRange,
+ sal_Bool bAllowImplicitChangesForNotConvertibleText,
+ LanguageType nTargetLang, const Font *pTargetFont )
+{
+ // modified version of ImpEditEngine::ImpSpell
+
+ // looks for next convertible text portion to be passed on to the wrapper
+
+ String aRes;
+ LanguageType nResLang = LANGUAGE_NONE;
+
+#ifdef SVX_LIGHT
+ rConvTxt = rtl::OUString();
+ rConvTxtLang = LANGUAGE_NONE;
+#else
+
+ /* ContentNode* pLastNode = */ aEditDoc.SaveGetObject( aEditDoc.Count()-1 );
+
+ EditPaM aPos( CreateEditPaM( pConvInfo->aConvContinue ) );
+ EditSelection aCurSel = EditSelection( aPos, aPos );
+
+ String aWord;
+
+ while (!aRes.Len())
+ {
+ // empty paragraph found that needs to have language and font set?
+ if (bAllowImplicitChangesForNotConvertibleText &&
+ !pEditEngine->GetText( pConvInfo->aConvContinue.nPara ).Len())
+ {
+ USHORT nPara = pConvInfo->aConvContinue.nPara;
+ ESelection aESel( nPara, 0, nPara, 0 );
+ // see comment for below same function call
+ SetLanguageAndFont( aESel,
+ nTargetLang, EE_CHAR_LANGUAGE_CJK,
+ pTargetFont, EE_CHAR_FONTINFO_CJK );
+ }
+
+
+ if (pConvInfo->aConvContinue.nPara == pConvInfo->aConvTo.nPara &&
+ pConvInfo->aConvContinue.nIndex >= pConvInfo->aConvTo.nIndex)
+ break;
+
+/*
+ // Bekannter (wahrscheinlicher) Bug: Wenn SpellToCurrent, muss
+ // Current bei jeder Ersetzung korrigiert werden, sonst passt
+ // das Ende evtl. nicht mehr genau...
+ if ( pConvInfo->bConvToEnd || pConvInfo->bMultipleDoc )
+ {
+ if ( aCurSel.Max().GetNode() == pLastNode &&
+ aCurSel.Max().GetIndex() >= pLastNode->Len() )
+ break;
+ }
+*/
+
+ USHORT nAttribStart = USHRT_MAX;
+ USHORT nAttribEnd = USHRT_MAX;
+ USHORT nCurPos = USHRT_MAX;
+ EPaM aCurStart = CreateEPaM( aCurSel.Min() );
+ SvUShorts aPortions;
+ pEditEngine->GetPortions( (USHORT)aCurStart.nPara, aPortions );
+ for ( USHORT nPos = 0; nPos < aPortions.Count(); ++nPos )
+ {
+ USHORT nEnd = aPortions.GetObject( nPos );
+ USHORT nStart = nPos > 0 ? aPortions.GetObject( nPos - 1 ) : 0;
+
+ // the language attribute is obtained from the left character
+ // (like usually all other attributes)
+ // thus we usually have to add 1 in order to get the language
+ // of the text right to the cursor position
+ USHORT nLangIdx = nEnd > nStart ? nStart + 1 : nStart;
+ LanguageType nLangFound = pEditEngine->GetLanguage( aCurStart.nPara, nLangIdx );
+#ifdef DEBUG
+ lang::Locale aLocale( SvxCreateLocale( nLangFound ) );
+#endif
+ sal_Bool bLangOk = (nLangFound == nSrcLang) ||
+ (editeng::HangulHanjaConversion::IsChinese( nLangFound ) &&
+ editeng::HangulHanjaConversion::IsChinese( nSrcLang ));
+
+ if (nAttribEnd != USHRT_MAX) // start already found?
+ {
+ DBG_ASSERT(nEnd >= aCurStart.nIndex, "error while scanning attributes (a)" );
+ DBG_ASSERT(nEnd >= nAttribEnd, "error while scanning attributes (b)" );
+ if (/*nEnd >= aCurStart.nIndex &&*/ nLangFound == nResLang)
+ nAttribEnd = nEnd;
+ else // language attrib has changed
+ break;
+ }
+ if (nAttribStart == USHRT_MAX && // start not yet found?
+ nEnd > aCurStart.nIndex && bLangOk)
+ {
+ nAttribStart = nStart;
+ nAttribEnd = nEnd;
+ nResLang = nLangFound;
+ }
+ //! the list of portions may have changed compared to the previous
+ //! call to this function (because of possibly changed language
+ //! attribute!)
+ //! But since we don't want to start in the already processed part
+ //! we clip the start accordingly.
+ if (nAttribStart < aCurStart.nIndex)
+ {
+ nAttribStart = aCurStart.nIndex;
+ }
+
+ // check script type to the right of the start of the current portion
+ EditPaM aPaM( CreateEditPaM( EPaM(aCurStart.nPara, nLangIdx) ) );
+ sal_Bool bIsAsianScript = (i18n::ScriptType::ASIAN == GetScriptType( aPaM ));
+ // not yet processed text part with for conversion
+ // not suitable language found that needs to be changed?
+ if (bAllowImplicitChangesForNotConvertibleText &&
+ !bLangOk && !bIsAsianScript && nEnd > aCurStart.nIndex)
+ {
+ ESelection aESel( aCurStart.nPara, nStart, aCurStart.nPara, nEnd );
+ // set language and font to target language and font of conversion
+ //! Now this especially includes all non convertible text e.g.
+ //! spaces, empty paragraphs and western text.
+ // This is in order for every *new* text entered at *any* position to
+ // have the correct language and font attributes set.
+ SetLanguageAndFont( aESel,
+ nTargetLang, EE_CHAR_LANGUAGE_CJK,
+ pTargetFont, EE_CHAR_FONTINFO_CJK );
+ }
+
+ nCurPos = nEnd;
+ }
+
+ if (nAttribStart != USHRT_MAX && nAttribEnd != USHRT_MAX)
+ {
+ aCurSel.Min().SetIndex( nAttribStart );
+ aCurSel.Max().SetIndex( nAttribEnd );
+ }
+ else if (nCurPos != USHRT_MAX)
+ {
+ // set selection to end of scanned text
+ // (used to set the position where to continue from later on)
+ aCurSel.Min().SetIndex( nCurPos );
+ aCurSel.Max().SetIndex( nCurPos );
+ }
+
+ if ( !pConvInfo->bConvToEnd )
+ {
+ EPaM aEPaM( CreateEPaM( aCurSel.Min() ) );
+ if ( !( aEPaM < pConvInfo->aConvTo ) )
+ break;
+ }
+
+ // clip selected word to the converted area
+ // (main use when conversion starts/ends **within** a word)
+ EditPaM aPaM( CreateEditPaM( pConvInfo->aConvStart ) );
+ if (pConvInfo->bConvToEnd &&
+ aCurSel.Min().GetNode() == aPaM.GetNode() &&
+ aCurSel.Min().GetIndex() < aPaM.GetIndex())
+ aCurSel.Min().SetIndex( aPaM.GetIndex() );
+ aPaM = CreateEditPaM( pConvInfo->aConvContinue );
+ if (aCurSel.Min().GetNode() == aPaM.GetNode() &&
+ aCurSel.Min().GetIndex() < aPaM.GetIndex())
+ aCurSel.Min().SetIndex( aPaM.GetIndex() );
+ aPaM = CreateEditPaM( pConvInfo->aConvTo );
+ if ((!pConvInfo->bConvToEnd || rConvRange.HasRange())&&
+ aCurSel.Max().GetNode() == aPaM.GetNode() &&
+ aCurSel.Max().GetIndex() > aPaM.GetIndex())
+ aCurSel.Max().SetIndex( aPaM.GetIndex() );
+
+ aWord = GetSelected( aCurSel );
+
+ if ( aWord.Len() > 0 /* && bLangOk */)
+ aRes = aWord;
+
+ // move to next word/paragraph if necessary
+ if ( !aRes.Len() )
+ aCurSel = WordRight( aCurSel.Min(), ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
+
+ pConvInfo->aConvContinue = CreateEPaM( aCurSel.Max() );
+ }
+
+ pEditView->pImpEditView->DrawSelection();
+ pEditView->pImpEditView->SetEditSelection( aCurSel );
+ pEditView->pImpEditView->DrawSelection();
+ pEditView->ShowCursor( sal_True, sal_False );
+
+ rConvTxt = aRes;
+ if (rConvTxt.getLength())
+ rConvTxtLang = nResLang;
+#endif
+}
+
+
+Reference< XSpellAlternatives > ImpEditEngine::ImpSpell( EditView* pEditView )
+{
+#ifdef SVX_LIGHT
+ return Reference< XSpellAlternatives >();
+#else
+
+ DBG_ASSERT( xSpeller.is(), "Kein Speller gesetzt!" );
+
+ ContentNode* pLastNode = aEditDoc.SaveGetObject( (aEditDoc.Count()-1) );
+ EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() );
+ aCurSel.Min() = aCurSel.Max();
+
+ String aWord;
+ Reference< XSpellAlternatives > xSpellAlt;
+ Sequence< PropertyValue > aEmptySeq;
+ while (!xSpellAlt.is())
+ {
+
+ // Bekannter (wahrscheinlicher) Bug: Wenn SpellToCurrent, muss
+ // Current bei jeder Ersetzung korrigiert werden, sonst passt
+ // das Ende evtl. nicht mehr genau...
+ if ( pSpellInfo->bSpellToEnd || pSpellInfo->bMultipleDoc )
+ {
+ if ( aCurSel.Max().GetNode() == pLastNode )
+ {
+ if ( ( aCurSel.Max().GetIndex() >= pLastNode->Len() ) )
+ break;
+ }
+ }
+ else if ( !pSpellInfo->bSpellToEnd )
+ {
+ EPaM aEPaM( CreateEPaM( aCurSel.Max() ) );
+ if ( !( aEPaM < pSpellInfo->aSpellTo ) )
+ break;
+ }
+
+ aCurSel = SelectWord( aCurSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
+ aWord = GetSelected( aCurSel );
+
+ // Wenn Punkt dahinter, muss dieser mit uebergeben werden !
+ // Falls Abkuerzung...
+ if ( aWord.Len() && ( aCurSel.Max().GetIndex() < aCurSel.Max().GetNode()->Len() ) )
+ {
+ sal_Unicode cNext = aCurSel.Max().GetNode()->GetChar( aCurSel.Max().GetIndex() );
+ if ( cNext == '.' )
+ {
+ aCurSel.Max().GetIndex()++;
+ aWord += cNext;
+ }
+ }
+
+ if ( aWord.Len() > 0 )
+ {
+ LanguageType eLang = GetLanguage( aCurSel.Max() );
+ SvxSpellWrapper::CheckSpellLang( xSpeller, eLang );
+ xSpellAlt = xSpeller->spell( aWord, eLang, aEmptySeq );
+ }
+
+ if ( !xSpellAlt.is() )
+ aCurSel = WordRight( aCurSel.Min(), ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
+ else
+ pSpellInfo->eState = EE_SPELL_ERRORFOUND;
+ }
+
+ pEditView->pImpEditView->DrawSelection();
+ pEditView->pImpEditView->SetEditSelection( aCurSel );
+ pEditView->pImpEditView->DrawSelection();
+ pEditView->ShowCursor( sal_True, sal_False );
+ return xSpellAlt;
+#endif
+}
+/*-- 13.10.2003 16:43:27---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+void ImpEditEngine::EndSpelling()
+{
+ DELETEZ(pSpellInfo);
+}
+/*-- 13.10.2003 16:43:27---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+void ImpEditEngine::StartSpelling(EditView& rEditView, sal_Bool bMultipleDoc)
+{
+ DBG_ASSERT(!pSpellInfo, "pSpellInfo already set?");
+ pSpellInfo = new SpellInfo;
+ pSpellInfo->bMultipleDoc = bMultipleDoc;
+ rEditView.pImpEditView->SetEditSelection( aEditDoc.GetStartPaM() );
+ EditSelection aCurSel( rEditView.pImpEditView->GetEditSelection() );
+ pSpellInfo->aSpellStart = CreateEPaM( SelectWord( aCurSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD ).Min() );
+}
+/*-- 13.10.2003 16:43:27---------------------------------------------------
+ Search for the next wrong word within the given selection
+ -----------------------------------------------------------------------*/
+Reference< XSpellAlternatives > ImpEditEngine::ImpFindNextError(EditSelection& rSelection)
+{
+ /* ContentNode* pLastNode = */ aEditDoc.SaveGetObject( (aEditDoc.Count()-1) );
+ EditSelection aCurSel( rSelection.Min() );
+
+ String aWord;
+ Reference< XSpellAlternatives > xSpellAlt;
+ Sequence< PropertyValue > aEmptySeq;
+ while (!xSpellAlt.is())
+ {
+ //check if the end of the selection has been reached
+ {
+ EPaM aEPaM( CreateEPaM( aCurSel.Max() ) );
+ if ( !( aEPaM < CreateEPaM( rSelection.Max()) ) )
+ break;
+ }
+
+ aCurSel = SelectWord( aCurSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
+ aWord = GetSelected( aCurSel );
+
+ // Wenn Punkt dahinter, muss dieser mit uebergeben werden !
+ // Falls Abkuerzung...
+ if ( aWord.Len() && ( aCurSel.Max().GetIndex() < aCurSel.Max().GetNode()->Len() ) )
+ {
+ sal_Unicode cNext = aCurSel.Max().GetNode()->GetChar( aCurSel.Max().GetIndex() );
+ if ( cNext == '.' )
+ {
+ aCurSel.Max().GetIndex()++;
+ aWord += cNext;
+ }
+ }
+
+ if ( aWord.Len() > 0 )
+ xSpellAlt = xSpeller->spell( aWord, GetLanguage( aCurSel.Max() ), aEmptySeq );
+
+ if ( !xSpellAlt.is() )
+ aCurSel = WordRight( aCurSel.Min(), ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
+ else
+ {
+ pSpellInfo->eState = EE_SPELL_ERRORFOUND;
+ rSelection = aCurSel;
+ }
+ }
+ return xSpellAlt;
+}
+/*-- 13.10.2003 16:43:27---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+bool ImpEditEngine::SpellSentence(EditView& rEditView, ::svx::SpellPortions& rToFill, bool /*bIsGrammarChecking*/ )
+{
+#ifdef SVX_LIGHT
+#else
+ bool bRet = false;
+ //the pSpellInfo has to be created on demand
+ if(!pSpellInfo)
+ {
+ pSpellInfo = new SpellInfo;
+ pSpellInfo->bMultipleDoc = sal_True;
+ rEditView.pImpEditView->SetEditSelection( aEditDoc.GetStartPaM() );
+ EditSelection aCurSel( rEditView.pImpEditView->GetEditSelection() );
+ pSpellInfo->aSpellStart = CreateEPaM( SelectWord( aCurSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD ).Min() );
+ }
+ DBG_ASSERT( xSpeller.is(), "Kein Speller gesetzt!" );
+ pSpellInfo->aLastSpellPortions.clear();
+ pSpellInfo->aLastSpellContentSelections.clear();
+ rToFill.clear();
+ EditSelection aCurSel( rEditView.pImpEditView->GetEditSelection() );
+ //if no selection previously exists the range is extended to the end of the object
+ if(aCurSel.Min() == aCurSel.Max())
+ {
+ ContentNode* pLastNode = aEditDoc.SaveGetObject( aEditDoc.Count()-1);
+ aCurSel.Max() = EditPaM(pLastNode, pLastNode->Len());
+ }
+ Reference< XSpellAlternatives > xAlt = ImpFindNextError(aCurSel);
+ if(xAlt.is())
+ {
+ bRet = true;
+ //find the sentence boundaries
+ EditSelection aSentencePaM = SelectSentence(aCurSel);
+ //make sure that the sentence is never smaller than the error range!
+ if(aSentencePaM.Max().GetIndex() < aCurSel.Max().GetIndex())
+ aSentencePaM.Max() = aCurSel.Max();
+ //add the portion preceeding the error
+ EditSelection aStartSelection(aSentencePaM.Min(), aCurSel.Min());
+ if(aStartSelection.HasRange())
+ AddPortionIterated(rEditView, aStartSelection, 0, rToFill);
+ //add the error portion
+ AddPortionIterated(rEditView, aCurSel, xAlt, rToFill);
+ //find the end of the sentence
+ //search for all errors in the rest of the sentence and add all the portions
+ do
+ {
+ EditSelection aNextSel = EditSelection(aCurSel.Max(), aSentencePaM.Max());
+ xAlt = ImpFindNextError(aNextSel);
+ if(xAlt.is())
+ {
+ //add the part between the previous and the current error
+ AddPortionIterated(rEditView, EditSelection(aCurSel.Max(), aNextSel.Min()), 0, rToFill);
+ //add the current error
+ AddPortionIterated(rEditView, aNextSel, xAlt, rToFill);
+ }
+ else
+ AddPortionIterated(rEditView, EditSelection(aCurSel.Max(), aSentencePaM.Max()), xAlt, rToFill);
+ aCurSel = aNextSel;
+ }
+ while( xAlt.is() );
+ //set the selection to the end of the current sentence
+ rEditView.pImpEditView->SetEditSelection(aSentencePaM.Max());
+ }
+#endif
+ return bRet;
+}
+
+/*-- 15.10.2003 16:09:12---------------------------------------------------
+ adds one portion to the SpellPortions
+ -----------------------------------------------------------------------*/
+void ImpEditEngine::AddPortion(
+ const EditSelection rSel,
+ uno::Reference< XSpellAlternatives > xAlt,
+ ::svx::SpellPortions& rToFill,
+ bool bIsField)
+{
+#ifdef SVX_LIGHT
+#else
+ if(rSel.HasRange())
+ {
+ svx::SpellPortion aPortion;
+ aPortion.sText = GetSelected( rSel );
+ aPortion.eLanguage = GetLanguage( rSel.Min() );
+ aPortion.xAlternatives = xAlt;
+ aPortion.bIsField = bIsField;
+ rToFill.push_back(aPortion);
+
+ //save the spelled portions for later use
+ pSpellInfo->aLastSpellPortions.push_back(aPortion);
+ pSpellInfo->aLastSpellContentSelections.push_back(rSel);
+
+ }
+#endif
+}
+
+/*-- 15.10.2003 16:07:47---------------------------------------------------
+ adds one or more portions of text to the SpellPortions depending on language changes
+ -----------------------------------------------------------------------*/
+void ImpEditEngine::AddPortionIterated(
+ EditView& rEditView,
+ const EditSelection rSel,
+ Reference< XSpellAlternatives > xAlt,
+ ::svx::SpellPortions& rToFill)
+{
+#ifdef SVX_LIGHT
+#else
+ if(rSel.Min() != rSel.Max())
+ {
+ if(xAlt.is())
+ {
+ AddPortion(rSel, xAlt, rToFill, false);
+ }
+ else
+ {
+ //iterate and search for language attribute changes
+ //save the start and end positions
+ bool bTest = rSel.Min().GetIndex() <= rSel.Max().GetIndex();
+ EditPaM aStart(bTest ? rSel.Min() : rSel.Max());
+ EditPaM aEnd(bTest ? rSel.Max() : rSel.Min());
+ //iterate over the text to find changes in language
+ //set the mark equal to the point
+ EditPaM aCursor(aStart);
+ rEditView.pImpEditView->SetEditSelection( aCursor );
+ LanguageType eStartLanguage = GetLanguage( aCursor );
+ //search for a field attribute at the beginning - only the end position
+ //of this field is kept to end a portion at that position
+ const EditCharAttrib* pFieldAttr = aCursor.GetNode()->GetCharAttribs().
+ FindFeature( aCursor.GetIndex() );
+ bool bIsField = pFieldAttr &&
+ pFieldAttr->GetStart() == aCursor.GetIndex() &&
+ pFieldAttr->GetStart() != pFieldAttr->GetEnd() &&
+ pFieldAttr->Which() == EE_FEATURE_FIELD;
+ USHORT nEndField = bIsField ? pFieldAttr->GetEnd() : USHRT_MAX;
+ bool bIsEndField = false;
+ do
+ {
+ aCursor = CursorRight( aCursor);
+ //determine whether a field and has been reached
+ bIsEndField = nEndField == aCursor.GetIndex();
+ //search for a new field attribute
+ EditCharAttrib* _pFieldAttr = aCursor.GetNode()->GetCharAttribs().
+ FindFeature( aCursor.GetIndex() );
+ bIsField = _pFieldAttr &&
+ _pFieldAttr->GetStart() == aCursor.GetIndex() &&
+ _pFieldAttr->GetStart() != _pFieldAttr->GetEnd() &&
+ _pFieldAttr->Which() == EE_FEATURE_FIELD;
+ //on every new field move the end position
+ if(bIsField)
+ nEndField = bIsField ? _pFieldAttr->GetEnd() : USHRT_MAX;
+
+ LanguageType eCurLanguage = GetLanguage( aCursor );
+ if(eCurLanguage != eStartLanguage || bIsField || bIsEndField)
+ {
+ eStartLanguage = eCurLanguage;
+ //go one step back - the cursor currently selects the first character
+ //with a different language
+ //create a selection from start to the current Cursor
+ EditSelection aSelection(aStart, aCursor);
+ AddPortion(aSelection, xAlt, rToFill, bIsEndField);
+ aStart = aCursor;
+ }
+ }
+ while(aCursor.GetIndex() < aEnd.GetIndex());
+ EditSelection aSelection(aStart, aCursor);
+ AddPortion(aSelection, xAlt, rToFill, bIsField);
+ }
+ }
+#endif
+}
+
+/*-- 13.10.2003 16:43:33---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+void ImpEditEngine::ApplyChangedSentence(EditView& rEditView, const ::svx::SpellPortions& rNewPortions, bool /*bIsGrammarChecking*/ )
+{
+#ifdef SVX_LIGHT
+#else
+ DBG_ASSERT(pSpellInfo, "pSpellInfo not initialized");
+ if(pSpellInfo)
+ {
+ UndoActionStart( EDITUNDO_INSERT );
+ if(pSpellInfo->aLastSpellPortions.size() == rNewPortions.size())
+ {
+ //the simple case: the same number of elements on both sides
+ //each changed element has to be applied to the corresponding source element
+ svx::SpellPortions::const_iterator aCurrentNewPortion = rNewPortions.end();
+ svx::SpellPortions::const_iterator aCurrentOldPortion = pSpellInfo->aLastSpellPortions.end();
+ SpellContentSelections::const_iterator aCurrentOldPosition = pSpellInfo->aLastSpellContentSelections.end();
+ bool bSetToEnd = false;
+ do
+ {
+ --aCurrentNewPortion;
+ --aCurrentOldPortion;
+ --aCurrentOldPosition;
+ //set the cursor to the end of the sentence - necessary to
+ //resume there at the next step
+ if(!bSetToEnd)
+ {
+ bSetToEnd = true;
+ rEditView.pImpEditView->SetEditSelection( aCurrentOldPosition->Max() );
+ }
+
+ USHORT nScriptType = GetI18NScriptTypeOfLanguage( aCurrentNewPortion->eLanguage );
+// LanguageType eTextLanguage = GetLanguage( aCurrentOldPosition->Min() );
+
+ USHORT nLangWhichId = EE_CHAR_LANGUAGE;
+ switch(nScriptType)
+ {
+ case SCRIPTTYPE_ASIAN : nLangWhichId = EE_CHAR_LANGUAGE_CJK; break;
+ case SCRIPTTYPE_COMPLEX : nLangWhichId = EE_CHAR_LANGUAGE_CTL; break;
+ }
+ if(aCurrentNewPortion->sText != aCurrentOldPortion->sText)
+ {
+ //change text and apply language
+ SfxItemSet aSet( aEditDoc.GetItemPool(), nLangWhichId, nLangWhichId);
+ aSet.Put(SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId));
+ SetAttribs( *aCurrentOldPosition, aSet );
+ ImpInsertText( *aCurrentOldPosition, aCurrentNewPortion->sText );
+ }
+ else if(aCurrentNewPortion->eLanguage != aCurrentOldPortion->eLanguage)
+ {
+ //apply language
+ SfxItemSet aSet( aEditDoc.GetItemPool(), nLangWhichId, nLangWhichId);
+ aSet.Put(SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId));
+ SetAttribs( *aCurrentOldPosition, aSet );
+ }
+ if(aCurrentNewPortion == rNewPortions.begin())
+ break;
+ }
+ while(aCurrentNewPortion != rNewPortions.begin());
+ }
+ else
+ {
+ //select the complete sentence
+ SpellContentSelections::const_iterator aCurrentEndPosition = pSpellInfo->aLastSpellContentSelections.end();
+ --aCurrentEndPosition;
+ SpellContentSelections::const_iterator aCurrentStartPosition = pSpellInfo->aLastSpellContentSelections.begin();
+ EditSelection aAllSentence(aCurrentStartPosition->Min(), aCurrentEndPosition->Max());
+
+ //delete the sentence completely
+ ImpDeleteSelection( aAllSentence );
+ svx::SpellPortions::const_iterator aCurrentNewPortion = rNewPortions.begin();
+ EditPaM aCurrentPaM = aAllSentence.Min();
+ while(aCurrentNewPortion != rNewPortions.end())
+ {
+ //set the language attribute
+ LanguageType eCurLanguage = GetLanguage( aCurrentPaM );
+ if(eCurLanguage != aCurrentNewPortion->eLanguage)
+ {
+ USHORT nScriptType = GetI18NScriptTypeOfLanguage( aCurrentNewPortion->eLanguage );
+ USHORT nLangWhichId = EE_CHAR_LANGUAGE;
+ switch(nScriptType)
+ {
+ case SCRIPTTYPE_ASIAN : nLangWhichId = EE_CHAR_LANGUAGE_CJK; break;
+ case SCRIPTTYPE_COMPLEX : nLangWhichId = EE_CHAR_LANGUAGE_CTL; break;
+ }
+ SfxItemSet aSet( aEditDoc.GetItemPool(), nLangWhichId, nLangWhichId);
+ aSet.Put(SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId));
+ SetAttribs( aCurrentPaM, aSet );
+ }
+ //insert the new string and set the cursor to the end of the inserted string
+ aCurrentPaM = ImpInsertText( aCurrentPaM , aCurrentNewPortion->sText );
+ ++aCurrentNewPortion;
+ }
+ }
+ UndoActionEnd( EDITUNDO_INSERT );
+ }
+ FormatAndUpdate();
+ aEditDoc.SetModified(TRUE);
+#endif
+}
+/*-- 08.09.2008 11:33:02---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+void ImpEditEngine::PutSpellingToSentenceStart( EditView& rEditView )
+{
+#ifdef SVX_LIGHT
+#else
+ if( pSpellInfo && pSpellInfo->aLastSpellContentSelections.size() )
+ {
+ rEditView.pImpEditView->SetEditSelection( pSpellInfo->aLastSpellContentSelections.begin()->Min() );
+ }
+
+#endif
+}
+
+
+void ImpEditEngine::DoOnlineSpelling( ContentNode* pThisNodeOnly, sal_Bool bSpellAtCursorPos, sal_Bool bInteruptable )
+{
+#ifndef SVX_LIGHT
+ /*
+ Er wird ueber alle Absaetze iteriert, nur Absaetze mit invalidierter
+ WrongList werden geprueft...
+
+ Es werden alle Woerter im invalidierten Bereich geprueft.
+ Ist ein Wort falsch, aber noch nicht in der WrongList, oder umgekehrt,
+ wird der Bereich des Wortes invalidiert
+ ( kein Invalidate, sondern wenn nur Uebergaenge von richtig=>falsch,
+ einfaches Paint, bei Uebergaengen von falsch=>richtig mit VDev
+ ueberplaetten )
+ */
+
+ if ( !xSpeller.is() )
+ return;
+
+ EditPaM aCursorPos;
+ if( pActiveView && !bSpellAtCursorPos )
+ {
+ DBG_CHKOBJ( pActiveView, EditView, 0 );
+ aCursorPos = pActiveView->pImpEditView->GetEditSelection().Max();
+ }
+ sal_Bool bRestartTimer = sal_False;
+
+ ContentNode* pLastNode = aEditDoc.SaveGetObject( aEditDoc.Count() - 1 );
+ sal_uInt16 nNodes = GetEditDoc().Count();
+ sal_uInt16 nInvalids = 0;
+ Sequence< PropertyValue > aEmptySeq;
+ for ( sal_uInt16 n = 0; n < nNodes; n++ )
+ {
+ ContentNode* pNode = GetEditDoc().GetObject( n );
+ if ( pThisNodeOnly )
+ pNode = pThisNodeOnly;
+
+ if ( pNode->GetWrongList()->IsInvalid() )
+ {
+ WrongList* pWrongList = pNode->GetWrongList();
+ sal_uInt16 nInvStart = pWrongList->GetInvalidStart();
+ sal_uInt16 nInvEnd = pWrongList->GetInvalidEnd();
+
+ sal_uInt16 nWrongs = 0; // Auch im Absatz mal die Kontrolle abgeben...
+// sal_Bool bStop = sal_False;
+
+ sal_uInt16 nPaintFrom = 0xFFFF, nPaintTo = 0;
+ sal_Bool bSimpleRepaint = sal_True;
+
+ pWrongList->SetValid();
+
+ EditPaM aPaM( pNode, nInvStart );
+ EditSelection aSel( aPaM, aPaM );
+ while ( ( aSel.Max().GetNode() == pNode ) /* && !bStop */ )
+ {
+ if ( ( aSel.Min().GetIndex() > nInvEnd )
+ || ( ( aSel.Max().GetNode() == pLastNode ) && ( aSel.Max().GetIndex() >= pLastNode->Len() ) ) )
+ break; // Dokument- oder Ungueltigkeitsbereich-Ende
+
+ aSel = SelectWord( aSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
+ String aWord( GetSelected( aSel ) );
+ // Wenn Punkt dahinter, muss dieser mit uebergeben werden !
+ // Falls Abkuerzung...
+ sal_Bool bDottAdded = sal_False;
+ if ( aSel.Max().GetIndex() < aSel.Max().GetNode()->Len() )
+ {
+ sal_Unicode cNext = aSel.Max().GetNode()->GetChar( aSel.Max().GetIndex() );
+ if ( cNext == '.' )
+ {
+ aSel.Max().GetIndex()++;
+ aWord += cNext;
+ bDottAdded = sal_True;
+ }
+ }
+
+
+ sal_Bool bChanged = sal_False;
+ if ( aWord.Len() > 0 )
+ {
+ sal_uInt16 nWStart = aSel.Min().GetIndex();
+ sal_uInt16 nWEnd= aSel.Max().GetIndex();
+ if ( !xSpeller->isValid( aWord, GetLanguage( EditPaM( aSel.Min().GetNode(), nWStart+1 ) ), aEmptySeq ) )
+ {
+ // Pruefen, ob schon richtig markiert...
+ nWrongs++;
+ // Nur bei SimpleRepaint stoppen, sonst zu oft VDev
+ // if ( ( nWrongs > 8 ) && bSimpleRepaint )
+ // {
+ // bStop = sal_True;
+ // pWrongList->MarkInvalid( aSel.Max().GetIndex(), nInvEnd );
+ // }
+ sal_uInt16 nXEnd = bDottAdded ? nWEnd -1 : nWEnd;
+ if ( !pWrongList->HasWrong( nWStart, nXEnd ) )
+ {
+ // Wort als falsch markieren...
+ // Aber nur, wenn nicht an Cursor-Position...
+ sal_Bool bCursorPos = sal_False;
+ if ( aCursorPos.GetNode() == pNode )
+ {
+ if ( ( nWStart <= aCursorPos.GetIndex() ) && nWEnd >= aCursorPos.GetIndex() )
+ bCursorPos = sal_True;
+ }
+ if ( bCursorPos )
+ {
+ // Dann weiter als ungueltig markieren...
+ pWrongList->GetInvalidStart() = nWStart;
+ pWrongList->GetInvalidEnd() = nWEnd;
+ bRestartTimer = sal_True;
+ }
+ else
+ {
+ // Es kann sein, dass die Wrongs in der Liste nicht
+ // genau ueber Woerter aufgespannt sind, weil die
+ // WordDelimiters beim Expandieren nicht ausgewrtet werden.
+ pWrongList->InsertWrong( nWStart, nXEnd, sal_True );
+ bChanged = sal_True;
+ }
+ }
+ }
+ else
+ {
+ // Pruefen, ob nicht als als falsch markiert....
+ if ( pWrongList->HasAnyWrong( nWStart, nWEnd ) )
+ {
+ pWrongList->ClearWrongs( nWStart, nWEnd, pNode );
+ bSimpleRepaint = sal_False;
+ bChanged = sal_True;
+ }
+ }
+ if ( bChanged )
+ {
+ if ( nPaintFrom == 0xFFFF )
+ nPaintFrom = nWStart;
+ nPaintTo = nWEnd;
+ }
+ }
+
+ EditPaM aLastEnd( aSel.Max() );
+ aSel = WordRight( aSel.Max(), ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
+ if ( bChanged && ( aSel.Min().GetNode() == pNode ) &&
+ ( ( aSel.Min().GetIndex()-aLastEnd.GetIndex() > 1 ) ) )
+ {
+ // Wenn zwei Worte durch mehr Zeichen als ein Blank getrennt
+ // sind, kann es passieren, dass beim Aufsplitten eines Wrongs
+ // der Start den zweiten Wortes vor dem tatsaechlich Wort liegt
+ pWrongList->ClearWrongs( aLastEnd.GetIndex(), aSel.Min().GetIndex(), pNode );
+ }
+ }
+
+ // Invalidieren?
+ if ( ( nPaintFrom != 0xFFFF ) )
+ {
+ aStatus.GetStatusWord() |= EE_STAT_WRONGWORDCHANGED;
+ CallStatusHdl();
+
+ if ( aEditViews.Count() )
+ {
+ // Bei SimpleRepaint wuerde ein uebermalen ohne VDev reichen,
+ // aber dann muesste ich ueber alle Views, Intersecten,
+ // Clippen, ...
+ // Lohnt wahrscheinlich nicht.
+ EditPaM aStartPaM( pNode, nPaintFrom );
+ EditPaM aEndPaM( pNode, nPaintTo );
+ Rectangle aStartCursor( PaMtoEditCursor( aStartPaM ) );
+ Rectangle aEndCursor( PaMtoEditCursor( aEndPaM ) );
+ DBG_ASSERT( aInvalidRec.IsEmpty(), "InvalidRect gesetzt!" );
+ aInvalidRec.Left() = 0;
+ aInvalidRec.Right() = GetPaperSize().Width();
+ aInvalidRec.Top() = aStartCursor.Top();
+ aInvalidRec.Bottom() = aEndCursor.Bottom();
+ if ( pActiveView && pActiveView->HasSelection() )
+ {
+ // Dann darf nicht ueber VDev ausgegeben werden
+ UpdateViews( NULL );
+ }
+ else if ( bSimpleRepaint )
+ {
+ for ( sal_uInt16 nView = 0; nView < aEditViews.Count(); nView++ )
+ {
+ EditView* pView = aEditViews[nView];
+ Rectangle aClipRec( aInvalidRec );
+ aClipRec.Intersection( pView->GetVisArea() );
+ if ( !aClipRec.IsEmpty() )
+ {
+ // in Fensterkoordinaten umwandeln....
+ aClipRec.SetPos( pView->pImpEditView->GetWindowPos( aClipRec.TopLeft() ) );
+ // Wenn Selektion, dann VDev...
+ Paint( pView->pImpEditView, aClipRec, pView->HasSelection() );
+ }
+ }
+ }
+ else
+ {
+ UpdateViews( pActiveView );
+ }
+ aInvalidRec = Rectangle();
+ }
+ }
+ // Nach zwei korrigierten Nodes die Kontrolle abgeben...
+ nInvalids++;
+ if ( bInteruptable && ( nInvalids >= 2 ) )
+ {
+ bRestartTimer = sal_True;
+ break;
+ }
+ }
+
+ if ( pThisNodeOnly )
+ break;
+ }
+ if ( bRestartTimer )
+ aOnlineSpellTimer.Start();
+#endif // !SVX_LIGHT
+}
+
+
+EESpellState ImpEditEngine::HasSpellErrors()
+{
+ DBG_ASSERT( xSpeller.is(), "Kein Speller gesetzt!" );
+
+#ifndef SVX_LIGHT
+ ContentNode* pLastNode = aEditDoc.SaveGetObject( aEditDoc.Count() - 1 );
+ EditSelection aCurSel( aEditDoc.GetStartPaM() );
+
+ String aWord;
+ Reference< XSpellAlternatives > xSpellAlt;
+ Sequence< PropertyValue > aEmptySeq;
+ while ( !xSpellAlt.is() )
+ {
+ if ( ( aCurSel.Max().GetNode() == pLastNode ) &&
+ ( aCurSel.Max().GetIndex() >= pLastNode->Len() ) )
+ {
+ return EE_SPELL_OK;
+ }
+
+ aCurSel = SelectWord( aCurSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
+ aWord = GetSelected( aCurSel );
+ if ( aWord.Len() > 0 )
+ {
+ LanguageType eLang = GetLanguage( aCurSel.Max() );
+ SvxSpellWrapper::CheckSpellLang( xSpeller, eLang );
+ xSpellAlt = xSpeller->spell( aWord, eLang, aEmptySeq );
+ }
+ aCurSel = WordRight( aCurSel.Max(), ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
+ }
+#endif
+
+ return EE_SPELL_ERRORFOUND;
+}
+
+EESpellState ImpEditEngine::StartThesaurus( EditView* pEditView )
+{
+#ifndef SVX_LIGHT
+ EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() );
+ if ( !aCurSel.HasRange() )
+ aCurSel = SelectWord( aCurSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
+ String aWord( GetSelected( aCurSel ) );
+
+ Reference< XThesaurus > xThes( SvxGetThesaurus() );
+ if (!xThes.is())
+ return EE_SPELL_ERRORFOUND;
+
+ EditAbstractDialogFactory* pFact = EditAbstractDialogFactory::Create();
+ AbstractThesaurusDialog* pDlg = pFact->CreateThesaurusDialog( pEditView->GetWindow(), xThes, aWord, GetLanguage( aCurSel.Max() ) );
+ if ( pDlg->Execute() == RET_OK )
+ {
+ // Wort ersetzen...
+ pEditView->pImpEditView->DrawSelection();
+ pEditView->pImpEditView->SetEditSelection( aCurSel );
+ pEditView->pImpEditView->DrawSelection();
+ pEditView->InsertText( pDlg->GetWord() );
+ pEditView->ShowCursor( sal_True, sal_False );
+ }
+
+ delete pDlg;
+ return EE_SPELL_OK;
+#else
+ return EE_SPELL_NOSPELLER;
+#endif
+}
+
+sal_uInt16 ImpEditEngine::StartSearchAndReplace( EditView* pEditView, const SvxSearchItem& rSearchItem )
+{
+ sal_uInt16 nFound = 0;
+
+#ifndef SVX_LIGHT
+ EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() );
+
+ // FIND_ALL ohne Mehrfachselektion nicht moeglich.
+ if ( ( rSearchItem.GetCommand() == SVX_SEARCHCMD_FIND ) ||
+ ( rSearchItem.GetCommand() == SVX_SEARCHCMD_FIND_ALL ) )
+ {
+ if ( Search( rSearchItem, pEditView ) )
+ nFound++;
+ }
+ else if ( rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE )
+ {
+ // Das Wort ist selektiert, wenn der Anwender die Selektion
+ // nicht zwischendurch manipuliert:
+ if ( aCurSel.HasRange() )
+ {
+ pEditView->InsertText( rSearchItem.GetReplaceString() );
+ nFound = 1;
+ }
+ else
+ if( Search( rSearchItem, pEditView ) )
+ nFound = 1;
+ }
+ else if ( rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE_ALL )
+ {
+ // Der Writer ersetzt alle, vorn Anfang bis Ende...
+ SvxSearchItem aTmpItem( rSearchItem );
+ aTmpItem.SetBackward( sal_False );
+
+ pEditView->pImpEditView->DrawSelection();
+
+ aCurSel.Adjust( aEditDoc );
+ EditPaM aStartPaM = aTmpItem.GetSelection() ? aCurSel.Min() : aEditDoc.GetStartPaM();
+ EditSelection aFoundSel( aCurSel.Max() );
+ sal_Bool bFound = ImpSearch( aTmpItem, aCurSel, aStartPaM, aFoundSel );
+ if ( bFound )
+ UndoActionStart( EDITUNDO_REPLACEALL );
+ while ( bFound )
+ {
+ nFound++;
+ aStartPaM = ImpInsertText( aFoundSel, rSearchItem.GetReplaceString() );
+ bFound = ImpSearch( aTmpItem, aCurSel, aStartPaM, aFoundSel );
+ }
+ if ( nFound )
+ {
+ EditPaM aNewPaM( aFoundSel.Max() );
+ if ( aNewPaM.GetIndex() > aNewPaM.GetNode()->Len() )
+ aNewPaM.GetIndex() = aNewPaM.GetNode()->Len();
+ pEditView->pImpEditView->SetEditSelection( aNewPaM );
+ FormatAndUpdate( pEditView );
+ UndoActionEnd( EDITUNDO_REPLACEALL );
+ }
+ else
+ {
+ pEditView->pImpEditView->DrawSelection();
+ pEditView->ShowCursor( sal_True, sal_False );
+ }
+ }
+#endif // !SVX_LIGHT
+ return nFound;
+}
+
+BOOL ImpEditEngine::Search( const SvxSearchItem& rSearchItem, EditView* pEditView )
+{
+ EditSelection aSel( pEditView->pImpEditView->GetEditSelection() );
+ aSel.Adjust( aEditDoc );
+ EditPaM aStartPaM( aSel.Max() );
+ if ( rSearchItem.GetSelection() && !rSearchItem.GetBackward() )
+ aStartPaM = aSel.Min();
+
+ EditSelection aFoundSel;
+ BOOL bFound = ImpSearch( rSearchItem, aSel, aStartPaM, aFoundSel );
+ if ( bFound && ( aFoundSel == aSel ) ) // Bei Rueckwaetssuche
+ {
+ aStartPaM = aSel.Min();
+ bFound = ImpSearch( rSearchItem, aSel, aStartPaM, aFoundSel );
+ }
+
+ pEditView->pImpEditView->DrawSelection();
+ if ( bFound )
+ {
+ // Erstmal das Min einstellen, damit das ganze Wort in den sichtbaren Bereich kommt.
+ pEditView->pImpEditView->SetEditSelection( aFoundSel.Min() );
+ pEditView->ShowCursor( TRUE, FALSE );
+ pEditView->pImpEditView->SetEditSelection( aFoundSel );
+ }
+ else
+ pEditView->pImpEditView->SetEditSelection( aSel.Max() );
+
+ pEditView->pImpEditView->DrawSelection();
+ pEditView->ShowCursor( TRUE, FALSE );
+ return bFound;
+}
+
+sal_Bool ImpEditEngine::ImpSearch( const SvxSearchItem& rSearchItem,
+ const EditSelection& rSearchSelection, const EditPaM& rStartPos, EditSelection& rFoundSel )
+{
+#ifndef SVX_LIGHT
+ util::SearchOptions aSearchOptions( rSearchItem.GetSearchOptions() );
+ aSearchOptions.Locale = GetLocale( rStartPos );
+
+ sal_Bool bBack = rSearchItem.GetBackward();
+ sal_Bool bSearchInSelection = rSearchItem.GetSelection();
+ sal_uInt16 nStartNode = aEditDoc.GetPos( rStartPos.GetNode() );
+ sal_uInt16 nEndNode;
+ if ( bSearchInSelection )
+ {
+ nEndNode = aEditDoc.GetPos( bBack ? rSearchSelection.Min().GetNode() : rSearchSelection.Max().GetNode() );
+ }
+ else
+ {
+ nEndNode = bBack ? 0 : aEditDoc.Count()-1;
+ }
+
+ utl::TextSearch aSearcher( aSearchOptions );
+
+ // ueber die Absaetze iterieren...
+ for ( sal_uInt16 nNode = nStartNode;
+ bBack ? ( nNode >= nEndNode ) : ( nNode <= nEndNode) ;
+ bBack ? nNode-- : nNode++ )
+ {
+ // Bei rueckwaertsuche, wenn nEndNode = 0:
+ if ( nNode >= 0xFFFF )
+ return sal_False;
+
+ ContentNode* pNode = aEditDoc.GetObject( nNode );
+
+ sal_uInt16 nStartPos = 0;
+ sal_uInt16 nEndPos = pNode->Len();
+ if ( nNode == nStartNode )
+ {
+ if ( bBack )
+ nEndPos = rStartPos.GetIndex();
+ else
+ nStartPos = rStartPos.GetIndex();
+ }
+ if ( ( nNode == nEndNode ) && bSearchInSelection )
+ {
+ if ( bBack )
+ nStartPos = rSearchSelection.Min().GetIndex();
+ else
+ nEndPos = rSearchSelection.Max().GetIndex();
+ }
+
+ // Suchen...
+ XubString aParaStr( GetEditDoc().GetParaAsString( pNode ) );
+ bool bFound = false;
+ if ( bBack )
+ {
+ SwapUSHORTs( nStartPos, nEndPos );
+ bFound = aSearcher.SearchBkwrd( aParaStr, &nStartPos, &nEndPos);
+ }
+ else
+ bFound = aSearcher.SearchFrwrd( aParaStr, &nStartPos, &nEndPos);
+
+ if ( bFound )
+ {
+ rFoundSel.Min().SetNode( pNode );
+ rFoundSel.Min().SetIndex( nStartPos );
+ rFoundSel.Max().SetNode( pNode );
+ rFoundSel.Max().SetIndex( nEndPos );
+ return sal_True;
+ }
+ }
+#endif // !SVX_LIGHT
+ return sal_False;
+}
+
+sal_Bool ImpEditEngine::HasText( const SvxSearchItem& rSearchItem )
+{
+#ifndef SVX_LIGHT
+ SvxSearchItem aTmpItem( rSearchItem );
+ aTmpItem.SetBackward( sal_False );
+ aTmpItem.SetSelection( sal_False );
+
+ EditPaM aStartPaM( aEditDoc.GetStartPaM() );
+ EditSelection aDummySel( aStartPaM );
+ EditSelection aFoundSel;
+ return ImpSearch( aTmpItem, aDummySel, aStartPaM, aFoundSel );
+#else
+ return sal_False;
+#endif
+}
+
+void ImpEditEngine::SetAutoCompleteText( const String& rStr, sal_Bool bClearTipWindow )
+{
+#ifndef SVX_LIGHT
+ aAutoCompleteText = rStr;
+ if ( bClearTipWindow && pActiveView )
+ Help::ShowQuickHelp( pActiveView->GetWindow(), Rectangle(), String(), 0 );
+#endif // !SVX_LIGHT
+}
+
+EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, sal_Int32 nTransliterationMode )
+{
+ EditSelection aSel( rSelection );
+ aSel.Adjust( aEditDoc );
+
+ if ( !aSel.HasRange() )
+ aSel = SelectWord( aSel );
+
+ EditSelection aNewSel( aSel );
+
+ USHORT nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
+ USHORT nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
+
+ BOOL bChanges = FALSE;
+ BOOL bLenChanged = FALSE;
+ EditUndoTransliteration* pUndo = NULL;
+
+ utl::TransliterationWrapper aTranslitarationWrapper( ::comphelper::getProcessServiceFactory(), nTransliterationMode );
+ BOOL bConsiderLanguage = aTranslitarationWrapper.needLanguageForTheMode();
+
+ for ( USHORT nNode = nStartNode; nNode <= nEndNode; nNode++ )
+ {
+ ContentNode* pNode = aEditDoc.GetObject( nNode );
+ xub_StrLen nStartPos = 0;
+ xub_StrLen nEndPos = pNode->Len();
+ if ( nNode == nStartNode )
+ nStartPos = aSel.Min().GetIndex();
+ if ( nNode == nEndNode ) // kann auch == nStart sein!
+ nEndPos = aSel.Max().GetIndex();
+
+ USHORT nCurrentStart = nStartPos;
+ USHORT nCurrentEnd = nEndPos;
+ sal_uInt16 nLanguage = LANGUAGE_SYSTEM;
+
+ do
+ {
+ if ( bConsiderLanguage )
+ {
+ nLanguage = GetLanguage( EditPaM( pNode, nCurrentStart+1 ), &nCurrentEnd );
+ if ( nCurrentEnd > nEndPos )
+ nCurrentEnd = nEndPos;
+ }
+
+ xub_StrLen nLen = nCurrentEnd - nCurrentStart;
+
+ Sequence <sal_Int32> aOffsets;
+ String aNewText( aTranslitarationWrapper.transliterate( *pNode, nLanguage, nCurrentStart, nLen, &aOffsets ) );
+
+ if( ( nLen != aNewText.Len() ) || !pNode->Equals( aNewText, nCurrentStart, nLen ) )
+ {
+ bChanges = TRUE;
+ if ( nLen != aNewText.Len() )
+ bLenChanged = TRUE;
+
+#ifndef SVX_LIGHT
+ // Create UndoAction on Demand....
+ if ( !pUndo && IsUndoEnabled() && !IsInUndo() )
+ {
+ ESelection aESel( CreateESel( aSel ) );
+ pUndo = new EditUndoTransliteration( this, aESel, nTransliterationMode );
+
+ if ( ( nStartNode == nEndNode ) && !aSel.Min().GetNode()->GetCharAttribs().HasAttrib( aSel.Min().GetIndex(), aSel.Max().GetIndex() ) )
+ pUndo->SetText( aSel.Min().GetNode()->Copy( aSel.Min().GetIndex(), aSel.Max().GetIndex()-aSel.Min().GetIndex() ) );
+ else
+ pUndo->SetText( CreateBinTextObject( aSel, NULL ) );
+ }
+#endif
+
+ // Change text without loosing the attributes
+ USHORT nCharsAfterTransliteration =
+ sal::static_int_cast< USHORT >(aOffsets.getLength());
+ const sal_Int32* pOffsets = aOffsets.getConstArray();
+ short nDiffs = 0;
+ for ( USHORT n = 0; n < nCharsAfterTransliteration; n++ )
+ {
+ USHORT nCurrentPos = nCurrentStart+n;
+ sal_Int32 nDiff = (nCurrentPos-nDiffs) - pOffsets[n];
+
+ if ( !nDiff )
+ {
+ DBG_ASSERT( nCurrentPos < pNode->Len(), "TransliterateText - String smaller than expected!" );
+ pNode->SetChar( nCurrentPos, aNewText.GetChar(n) );
+ }
+ else if ( nDiff < 0 )
+ {
+ // Replace first char, delete the rest...
+ DBG_ASSERT( nCurrentPos < pNode->Len(), "TransliterateText - String smaller than expected!" );
+ pNode->SetChar( nCurrentPos, aNewText.GetChar(n) );
+
+ DBG_ASSERT( (nCurrentPos+1) < pNode->Len(), "TransliterateText - String smaller than expected!" );
+ GetEditDoc().RemoveChars( EditPaM( pNode, nCurrentPos+1 ), sal::static_int_cast< USHORT >(-nDiff) );
+ }
+ else
+ {
+ DBG_ASSERT( nDiff == 1, "TransliterateText - Diff other than expected! But should work..." );
+ GetEditDoc().InsertText( EditPaM( pNode, nCurrentPos ), aNewText.GetChar(n) );
+
+ }
+ nDiffs = sal::static_int_cast< short >(nDiffs + nDiff);
+ }
+
+ if ( nNode == nEndNode )
+ aNewSel.Max().GetIndex() =
+ aNewSel.Max().GetIndex() + nDiffs;
+
+ ParaPortion* pParaPortion = GetParaPortions()[nNode];
+ pParaPortion->MarkSelectionInvalid( nCurrentStart, std::max< USHORT >( nCurrentStart+nLen, nCurrentStart+aNewText.Len() ) );
+
+ }
+ nCurrentStart = nCurrentEnd;
+ } while( nCurrentEnd < nEndPos );
+ }
+
+#ifndef SVX_LIGHT
+ if ( pUndo )
+ {
+ ESelection aESel( CreateESel( aNewSel ) );
+ pUndo->SetNewSelection( aESel );
+ InsertUndo( pUndo );
+ }
+#endif
+
+ if ( bChanges )
+ {
+ TextModified();
+ SetModifyFlag( sal_True );
+ if ( bLenChanged )
+ UpdateSelections();
+ FormatAndUpdate();
+ }
+
+ return aNewSel;
+}
+
+void ImpEditEngine::SetAsianCompressionMode( USHORT n )
+{
+ if ( n != nAsianCompressionMode )
+ {
+ nAsianCompressionMode = n;
+ if ( ImplHasText() )
+ {
+ FormatFullDoc();
+ UpdateViews();
+ }
+ }
+}
+
+void ImpEditEngine::SetKernAsianPunctuation( BOOL b )
+{
+ if ( b != bKernAsianPunctuation )
+ {
+ bKernAsianPunctuation = b;
+ if ( ImplHasText() )
+ {
+ FormatFullDoc();
+ UpdateViews();
+ }
+ }
+}
+
+void ImpEditEngine::SetAddExtLeading( BOOL bExtLeading )
+{
+ if ( IsAddExtLeading() != bExtLeading )
+ {
+ bAddExtLeading = bExtLeading;
+ if ( ImplHasText() )
+ {
+ FormatFullDoc();
+ UpdateViews();
+ }
+ }
+};
+
+
+
+BOOL ImpEditEngine::ImplHasText() const
+{
+ return ( ( GetEditDoc().Count() > 1 ) || GetEditDoc().GetObject(0)->Len() );
+}
+
+long ImpEditEngine::LogicToTwips( long n )
+{
+ Size aSz( n, 0 );
+ MapMode aTwipsMode( MAP_TWIP );
+ aSz = pRefDev->LogicToLogic( aSz, NULL, &aTwipsMode );
+ return aSz.Width();
+}
+
+