summaryrefslogtreecommitdiff
path: root/editeng/source/editeng
diff options
context:
space:
mode:
Diffstat (limited to 'editeng/source/editeng')
-rw-r--r--editeng/source/editeng/editattr.cxx454
-rw-r--r--editeng/source/editeng/editattr.hxx426
-rw-r--r--editeng/source/editeng/editdbg.cxx586
-rw-r--r--editeng/source/editeng/editdbg.hxx57
-rw-r--r--editeng/source/editeng/editdoc.cxx2314
-rw-r--r--editeng/source/editeng/editdoc.hxx802
-rw-r--r--editeng/source/editeng/editdoc2.cxx544
-rw-r--r--editeng/source/editeng/editeng.cxx2939
-rw-r--r--editeng/source/editeng/editeng.src124
-rw-r--r--editeng/source/editeng/editobj.cxx1725
-rw-r--r--editeng/source/editeng/editobj2.hxx309
-rw-r--r--editeng/source/editeng/editsel.cxx121
-rw-r--r--editeng/source/editeng/editsel.hxx75
-rw-r--r--editeng/source/editeng/editstt2.hxx130
-rw-r--r--editeng/source/editeng/editundo.cxx750
-rw-r--r--editeng/source/editeng/editundo.hxx315
-rw-r--r--editeng/source/editeng/editview.cxx1595
-rw-r--r--editeng/source/editeng/edtspell.cxx746
-rw-r--r--editeng/source/editeng/edtspell.hxx185
-rw-r--r--editeng/source/editeng/eehtml.cxx850
-rw-r--r--editeng/source/editeng/eehtml.hxx98
-rw-r--r--editeng/source/editeng/eeng_pch.cxx30
-rw-r--r--editeng/source/editeng/eeng_pch.hxx34
-rw-r--r--editeng/source/editeng/eeobj.cxx112
-rw-r--r--editeng/source/editeng/eeobj.hxx72
-rw-r--r--editeng/source/editeng/eerdll.cxx237
-rw-r--r--editeng/source/editeng/eerdll2.hxx61
-rw-r--r--editeng/source/editeng/eertfpar.cxx632
-rw-r--r--editeng/source/editeng/eertfpar.hxx128
-rw-r--r--editeng/source/editeng/impedit.cxx2002
-rw-r--r--editeng/source/editeng/impedit.hxx1208
-rw-r--r--editeng/source/editeng/impedit2.cxx4632
-rw-r--r--editeng/source/editeng/impedit3.cxx4677
-rw-r--r--editeng/source/editeng/impedit4.cxx2955
-rw-r--r--editeng/source/editeng/impedit5.cxx911
-rw-r--r--editeng/source/editeng/makefile.mk80
-rw-r--r--editeng/source/editeng/textconv.cxx629
-rw-r--r--editeng/source/editeng/textconv.hxx122
38 files changed, 33667 insertions, 0 deletions
diff --git a/editeng/source/editeng/editattr.cxx b/editeng/source/editeng/editattr.cxx
new file mode 100644
index 000000000000..a1d4a66b8fb1
--- /dev/null
+++ b/editeng/source/editeng/editattr.cxx
@@ -0,0 +1,454 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 <eeng_pch.hxx>
+#include <vcl/wrkwin.hxx>
+#include <vcl/dialog.hxx>
+#include <vcl/msgbox.hxx>
+#include <vcl/svapp.hxx>
+
+#include <editeng/svxfont.hxx>
+#include <editeng/flditem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/cntritem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/wrlmitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/crsditem.hxx>
+#include <editeng/cscoitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/akrnitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/emphitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/charreliefitem.hxx>
+
+#include "editattr.hxx"
+
+DBG_NAME( EE_EditAttrib )
+
+// -------------------------------------------------------------------------
+// class EditAttrib
+// -------------------------------------------------------------------------
+EditAttrib::EditAttrib( const SfxPoolItem& rAttr )
+{
+ DBG_CTOR( EE_EditAttrib, 0 );
+ pItem = &rAttr;
+}
+
+EditAttrib::~EditAttrib()
+{
+ DBG_DTOR( EE_EditAttrib, 0 );
+}
+
+// -------------------------------------------------------------------------
+// class EditCharAttrib
+// -------------------------------------------------------------------------
+EditCharAttrib::EditCharAttrib( const SfxPoolItem& rAttr, USHORT nS, USHORT nE )
+ : EditAttrib( rAttr )
+{
+ nStart = nS;
+ nEnd = nE;
+ bFeature = FALSE;
+ bEdge = FALSE;
+
+ DBG_ASSERT( ( rAttr.Which() >= EE_ITEMS_START ) && ( rAttr.Which() <= EE_ITEMS_END ), "EditCharAttrib CTOR: Invalid id!" );
+ DBG_ASSERT( ( rAttr.Which() < EE_FEATURE_START ) || ( rAttr.Which() > EE_FEATURE_END ) || ( nE == (nS+1) ), "EditCharAttrib CTOR: Invalid feature!" );
+}
+
+void EditCharAttrib::SetFont( SvxFont&, OutputDevice* )
+{
+}
+
+
+// -------------------------------------------------------------------------
+// class EditCharAttribFont
+// -------------------------------------------------------------------------
+EditCharAttribFont::EditCharAttribFont( const SvxFontItem& rAttr, USHORT _nStart, USHORT _nEnd )
+ : EditCharAttrib( rAttr, _nStart, _nEnd )
+{
+ DBG_ASSERT( rAttr.Which() == EE_CHAR_FONTINFO || rAttr.Which() == EE_CHAR_FONTINFO_CJK || rAttr.Which() == EE_CHAR_FONTINFO_CTL, "Kein Fontattribut!" );
+}
+
+void EditCharAttribFont::SetFont( SvxFont& rFont, OutputDevice* )
+{
+ const SvxFontItem& rAttr = (const SvxFontItem&)(*GetItem());
+
+ rFont.SetName( rAttr.GetFamilyName() );
+ rFont.SetFamily( rAttr.GetFamily() );
+ rFont.SetPitch( rAttr.GetPitch() );
+ rFont.SetCharSet( rAttr.GetCharSet() );
+}
+
+// -------------------------------------------------------------------------
+// class EditCharAttribItalic
+// -------------------------------------------------------------------------
+EditCharAttribItalic::EditCharAttribItalic( const SvxPostureItem& rAttr, USHORT _nStart, USHORT _nEnd )
+ : EditCharAttrib( rAttr, _nStart, _nEnd )
+{
+ DBG_ASSERT( rAttr.Which() == EE_CHAR_ITALIC || rAttr.Which() == EE_CHAR_ITALIC_CJK || rAttr.Which() == EE_CHAR_ITALIC_CTL, "Kein Italicattribut!" );
+}
+
+void EditCharAttribItalic::SetFont( SvxFont& rFont, OutputDevice* )
+{
+ rFont.SetItalic( ((const SvxPostureItem*)GetItem())->GetPosture() );
+}
+
+// -------------------------------------------------------------------------
+// class EditCharAttribWeight
+// -------------------------------------------------------------------------
+EditCharAttribWeight::EditCharAttribWeight( const SvxWeightItem& rAttr, USHORT _nStart, USHORT _nEnd )
+ : EditCharAttrib( rAttr, _nStart, _nEnd )
+{
+ DBG_ASSERT( rAttr.Which() == EE_CHAR_WEIGHT || rAttr.Which() == EE_CHAR_WEIGHT_CJK || rAttr.Which() == EE_CHAR_WEIGHT_CTL, "Kein Weightttribut!" );
+}
+
+void EditCharAttribWeight::SetFont( SvxFont& rFont, OutputDevice* )
+{
+ rFont.SetWeight( (FontWeight)((const SvxWeightItem*)GetItem())->GetValue() );
+}
+
+// -------------------------------------------------------------------------
+// class EditCharAttribUnderline
+// -------------------------------------------------------------------------
+EditCharAttribUnderline::EditCharAttribUnderline( const SvxUnderlineItem& rAttr, USHORT _nStart, USHORT _nEnd )
+ : EditCharAttrib( rAttr, _nStart, _nEnd )
+{
+ DBG_ASSERT( rAttr.Which() == EE_CHAR_UNDERLINE, "Kein Underlineattribut!" );
+}
+
+void EditCharAttribUnderline::SetFont( SvxFont& rFont, OutputDevice* pOutDev )
+{
+ rFont.SetUnderline( (FontUnderline)((const SvxUnderlineItem*)GetItem())->GetValue() );
+ if ( pOutDev )
+ pOutDev->SetTextLineColor( ((const SvxUnderlineItem*)GetItem())->GetColor() );
+}
+
+// -------------------------------------------------------------------------
+// class EditCharAttribOverline
+// -------------------------------------------------------------------------
+EditCharAttribOverline::EditCharAttribOverline( const SvxOverlineItem& rAttr, USHORT _nStart, USHORT _nEnd )
+ : EditCharAttrib( rAttr, _nStart, _nEnd )
+{
+ DBG_ASSERT( rAttr.Which() == EE_CHAR_OVERLINE, "Kein Overlineattribut!" );
+}
+
+void EditCharAttribOverline::SetFont( SvxFont& rFont, OutputDevice* pOutDev )
+{
+ rFont.SetOverline( (FontUnderline)((const SvxOverlineItem*)GetItem())->GetValue() );
+ if ( pOutDev )
+ pOutDev->SetOverlineColor( ((const SvxOverlineItem*)GetItem())->GetColor() );
+}
+
+// -------------------------------------------------------------------------
+// class EditCharAttribFontHeight
+// -------------------------------------------------------------------------
+EditCharAttribFontHeight::EditCharAttribFontHeight( const SvxFontHeightItem& rAttr, USHORT _nStart, USHORT _nEnd )
+ : EditCharAttrib( rAttr, _nStart, _nEnd )
+{
+ DBG_ASSERT( rAttr.Which() == EE_CHAR_FONTHEIGHT || rAttr.Which() == EE_CHAR_FONTHEIGHT_CJK || rAttr.Which() == EE_CHAR_FONTHEIGHT_CTL, "Kein Heightattribut!" );
+}
+
+void EditCharAttribFontHeight::SetFont( SvxFont& rFont, OutputDevice* )
+{
+ // Prop wird ignoriert
+ rFont.SetSize( Size( rFont.GetSize().Width(), ((const SvxFontHeightItem*)GetItem())->GetHeight() ) );
+}
+
+// -------------------------------------------------------------------------
+// class EditCharAttribFontWidth
+// -------------------------------------------------------------------------
+EditCharAttribFontWidth::EditCharAttribFontWidth( const SvxCharScaleWidthItem& rAttr, USHORT _nStart, USHORT _nEnd )
+ : EditCharAttrib( rAttr, _nStart, _nEnd )
+{
+ DBG_ASSERT( rAttr.Which() == EE_CHAR_FONTWIDTH, "Kein Widthattribut!" );
+}
+
+void EditCharAttribFontWidth::SetFont( SvxFont& /*rFont*/, OutputDevice* )
+{
+ // must be calculated outside, because f(device)...
+}
+
+// -------------------------------------------------------------------------
+// class EditCharAttribStrikeout
+// -------------------------------------------------------------------------
+EditCharAttribStrikeout::EditCharAttribStrikeout( const SvxCrossedOutItem& rAttr, USHORT _nStart, USHORT _nEnd )
+ : EditCharAttrib( rAttr, _nStart, _nEnd )
+{
+ DBG_ASSERT( rAttr.Which() == EE_CHAR_STRIKEOUT, "Kein Sizeattribut!" );
+}
+
+void EditCharAttribStrikeout::SetFont( SvxFont& rFont, OutputDevice* )
+{
+ rFont.SetStrikeout( (FontStrikeout)((const SvxCrossedOutItem*)GetItem())->GetValue() );
+}
+
+// -------------------------------------------------------------------------
+// class EditCharAttribColor
+// -------------------------------------------------------------------------
+EditCharAttribColor::EditCharAttribColor( const SvxColorItem& rAttr, USHORT _nStart, USHORT _nEnd )
+ : EditCharAttrib( rAttr, _nStart, _nEnd )
+{
+ DBG_ASSERT( rAttr.Which() == EE_CHAR_COLOR, "Kein Colorattribut!" );
+}
+
+void EditCharAttribColor::SetFont( SvxFont& rFont, OutputDevice* )
+{
+ rFont.SetColor( ((const SvxColorItem*)GetItem())->GetValue() );
+}
+
+// -------------------------------------------------------------------------
+// class EditCharAttribLanguage
+// -------------------------------------------------------------------------
+EditCharAttribLanguage::EditCharAttribLanguage( const SvxLanguageItem& rAttr, USHORT _nStart, USHORT _nEnd )
+ : EditCharAttrib( rAttr, _nStart, _nEnd )
+{
+ DBG_ASSERT( ( rAttr.Which() == EE_CHAR_LANGUAGE ) || ( rAttr.Which() == EE_CHAR_LANGUAGE_CJK ) || ( rAttr.Which() == EE_CHAR_LANGUAGE_CTL ), "Kein Languageattribut!" );
+}
+
+void EditCharAttribLanguage::SetFont( SvxFont& rFont, OutputDevice* )
+{
+ rFont.SetLanguage( ((const SvxLanguageItem*)GetItem())->GetLanguage() );
+}
+
+// -------------------------------------------------------------------------
+// class EditCharAttribShadow
+// -------------------------------------------------------------------------
+EditCharAttribShadow::EditCharAttribShadow( const SvxShadowedItem& rAttr, USHORT _nStart, USHORT _nEnd )
+ : EditCharAttrib( rAttr, _nStart, _nEnd )
+{
+ DBG_ASSERT( rAttr.Which() == EE_CHAR_SHADOW, "Kein Shadowattribut!" );
+}
+
+void EditCharAttribShadow::SetFont( SvxFont& rFont, OutputDevice* )
+{
+ rFont.SetShadow( (BOOL)((const SvxShadowedItem*)GetItem())->GetValue() );
+}
+
+// -------------------------------------------------------------------------
+// class EditCharAttribEscapement
+// -------------------------------------------------------------------------
+EditCharAttribEscapement::EditCharAttribEscapement( const SvxEscapementItem& rAttr, USHORT _nStart, USHORT _nEnd )
+ : EditCharAttrib( rAttr, _nStart, _nEnd )
+{
+ DBG_ASSERT( rAttr.Which() == EE_CHAR_ESCAPEMENT, "Kein Escapementattribut!" );
+}
+
+#if defined( WIN ) && !defined( WNT )
+#pragma optimize ("", off)
+#endif
+
+void EditCharAttribEscapement::SetFont( SvxFont& rFont, OutputDevice* )
+{
+ USHORT nProp = ((const SvxEscapementItem*)GetItem())->GetProp();
+ rFont.SetPropr( (BYTE)nProp );
+
+ short nEsc = ((const SvxEscapementItem*)GetItem())->GetEsc();
+ if ( nEsc == DFLT_ESC_AUTO_SUPER )
+ nEsc = 100 - nProp;
+ else if ( nEsc == DFLT_ESC_AUTO_SUB )
+ nEsc = sal::static_int_cast< short >( -( 100 - nProp ) );
+ rFont.SetEscapement( nEsc );
+}
+
+#if defined( WIN ) && !defined( WNT )
+#pragma optimize ("", on)
+#endif
+
+
+// -------------------------------------------------------------------------
+// class EditCharAttribOutline
+// -------------------------------------------------------------------------
+EditCharAttribOutline::EditCharAttribOutline( const SvxContourItem& rAttr, USHORT _nStart, USHORT _nEnd )
+ : EditCharAttrib( rAttr, _nStart, _nEnd )
+{
+ DBG_ASSERT( rAttr.Which() == EE_CHAR_OUTLINE, "Kein Outlineattribut!" );
+}
+
+void EditCharAttribOutline::SetFont( SvxFont& rFont, OutputDevice* )
+{
+ rFont.SetOutline( (BOOL)((const SvxContourItem*)GetItem())->GetValue() );
+}
+
+// -------------------------------------------------------------------------
+// class EditCharAttribTab
+// -------------------------------------------------------------------------
+EditCharAttribTab::EditCharAttribTab( const SfxVoidItem& rAttr, USHORT nPos )
+ : EditCharAttrib( rAttr, nPos, nPos+1 )
+{
+ SetFeature( TRUE );
+}
+
+void EditCharAttribTab::SetFont( SvxFont&, OutputDevice* )
+{
+}
+
+// -------------------------------------------------------------------------
+// class EditCharAttribLineBreak
+// -------------------------------------------------------------------------
+EditCharAttribLineBreak::EditCharAttribLineBreak( const SfxVoidItem& rAttr, USHORT nPos )
+ : EditCharAttrib( rAttr, nPos, nPos+1 )
+{
+ SetFeature( TRUE );
+}
+
+void EditCharAttribLineBreak::SetFont( SvxFont&, OutputDevice* )
+{
+}
+
+// -------------------------------------------------------------------------
+// class EditCharAttribField
+// -------------------------------------------------------------------------
+EditCharAttribField::EditCharAttribField( const SvxFieldItem& rAttr, USHORT nPos )
+ : EditCharAttrib( rAttr, nPos, nPos+1 )
+{
+ SetFeature( TRUE ); // !!!
+ pTxtColor = 0;
+ pFldColor = 0;
+}
+
+void EditCharAttribField::SetFont( SvxFont& rFont, OutputDevice* )
+{
+ if ( pFldColor )
+ {
+ rFont.SetFillColor( *pFldColor );
+ rFont.SetTransparent( FALSE );
+ }
+ if ( pTxtColor )
+ rFont.SetColor( *pTxtColor );
+}
+
+EditCharAttribField::EditCharAttribField( const EditCharAttribField& rAttr )
+ : EditCharAttrib( *rAttr.GetItem(), rAttr.GetStart(), rAttr.GetEnd() ),
+ aFieldValue( rAttr.aFieldValue )
+{
+ // Diesen CCTOR nur fuer temporaeres Object verwenden,
+ // Item wird nicht gepoolt.
+ pTxtColor = rAttr.pTxtColor ? new Color( *rAttr.pTxtColor ) : 0;
+ pFldColor = rAttr.pFldColor ? new Color( *rAttr.pFldColor ) : 0;
+}
+
+EditCharAttribField::~EditCharAttribField()
+{
+ Reset();
+}
+
+BOOL EditCharAttribField::operator == ( const EditCharAttribField& rAttr ) const
+{
+ if ( aFieldValue != rAttr.aFieldValue )
+ return FALSE;
+
+ if ( ( pTxtColor && !rAttr.pTxtColor ) || ( !pTxtColor && rAttr.pTxtColor ) )
+ return FALSE;
+ if ( ( pTxtColor && rAttr.pTxtColor ) && ( *pTxtColor != *rAttr.pTxtColor ) )
+ return FALSE;
+
+ if ( ( pFldColor && !rAttr.pFldColor ) || ( !pFldColor && rAttr.pFldColor ) )
+ return FALSE;
+ if ( ( pFldColor && rAttr.pFldColor ) && ( *pFldColor != *rAttr.pFldColor ) )
+ return FALSE;
+
+ return TRUE;
+}
+
+// -------------------------------------------------------------------------
+// class EditCharAttribPairKerning
+// -------------------------------------------------------------------------
+EditCharAttribPairKerning::EditCharAttribPairKerning( const SvxAutoKernItem& rAttr, USHORT _nStart, USHORT _nEnd )
+: EditCharAttrib( rAttr, _nStart, _nEnd )
+{
+ DBG_ASSERT( rAttr.Which() == EE_CHAR_PAIRKERNING, "Kein PairKerning!" );
+}
+
+void EditCharAttribPairKerning::SetFont( SvxFont& rFont, OutputDevice* )
+{
+ rFont.SetKerning( ((const SvxAutoKernItem*)GetItem())->GetValue() );
+}
+
+// -------------------------------------------------------------------------
+// class EditCharAttribKerning
+// -------------------------------------------------------------------------
+EditCharAttribKerning::EditCharAttribKerning( const SvxKerningItem& rAttr, USHORT _nStart, USHORT _nEnd )
+: EditCharAttrib( rAttr, _nStart, _nEnd )
+{
+ DBG_ASSERT( rAttr.Which() == EE_CHAR_KERNING, "Kein Kerning!" );
+}
+
+void EditCharAttribKerning::SetFont( SvxFont& rFont, OutputDevice* )
+{
+ rFont.SetFixKerning( ((const SvxKerningItem*)GetItem())->GetValue() );
+}
+
+// -------------------------------------------------------------------------
+// class EditCharAttribWordLineMode
+// -------------------------------------------------------------------------
+EditCharAttribWordLineMode::EditCharAttribWordLineMode( const SvxWordLineModeItem& rAttr, USHORT _nStart, USHORT _nEnd )
+: EditCharAttrib( rAttr, _nStart, _nEnd )
+{
+ DBG_ASSERT( rAttr.Which() == EE_CHAR_WLM, "Kein Kerning!" );
+}
+
+void EditCharAttribWordLineMode::SetFont( SvxFont& rFont, OutputDevice* )
+{
+ rFont.SetWordLineMode( ((const SvxWordLineModeItem*)GetItem())->GetValue() );
+}
+
+// -------------------------------------------------------------------------
+// class EditCharAttribEmphasisMark
+// -------------------------------------------------------------------------
+EditCharAttribEmphasisMark::EditCharAttribEmphasisMark( const SvxEmphasisMarkItem& rAttr, USHORT _nStart, USHORT _nEnd )
+ : EditCharAttrib( rAttr, _nStart, _nEnd )
+{
+ DBG_ASSERT( rAttr.Which() == EE_CHAR_EMPHASISMARK, "Kein Emphasisattribut!" );
+}
+
+void EditCharAttribEmphasisMark::SetFont( SvxFont& rFont, OutputDevice* )
+{
+ rFont.SetEmphasisMark( ((const SvxEmphasisMarkItem*)GetItem())->GetEmphasisMark() );
+}
+
+// -------------------------------------------------------------------------
+// class EditCharAttribRelief
+// -------------------------------------------------------------------------
+EditCharAttribRelief::EditCharAttribRelief( const SvxCharReliefItem& rAttr, USHORT _nStart, USHORT _nEnd )
+ : EditCharAttrib( rAttr, _nStart, _nEnd )
+{
+ DBG_ASSERT( rAttr.Which() == EE_CHAR_RELIEF, "Not a relief attribute!" );
+}
+
+void EditCharAttribRelief::SetFont( SvxFont& rFont, OutputDevice* )
+{
+ rFont.SetRelief( (FontRelief)((const SvxCharReliefItem*)GetItem())->GetValue() );
+}
diff --git a/editeng/source/editeng/editattr.hxx b/editeng/source/editeng/editattr.hxx
new file mode 100644
index 000000000000..9f07969ee74d
--- /dev/null
+++ b/editeng/source/editeng/editattr.hxx
@@ -0,0 +1,426 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef _EDITATTR_HXX
+#define _EDITATTR_HXX
+
+#include <editeng/eeitem.hxx>
+
+class SvxFont;
+class SvxFontItem;
+class SvxWeightItem;
+class SvxPostureItem;
+class SvxShadowedItem;
+class SvxEscapementItem;
+class SvxContourItem;
+class SvxCrossedOutItem;
+class SvxUnderlineItem;
+class SvxOverlineItem;
+class SvxFontHeightItem;
+class SvxCharScaleWidthItem;
+class SvxColorItem;
+class SvxAutoKernItem;
+class SvxKerningItem;
+class SvxCharSetColorItem;
+class SvxWordLineModeItem;
+class SvxFieldItem;
+class SvxLanguageItem;
+class SvxEmphasisMarkItem;
+class SvxCharReliefItem;
+#include <svl/poolitem.hxx>
+
+
+class SfxVoidItem;
+
+#define CH_FEATURE_OLD (BYTE) 0xFF
+#define CH_FEATURE (sal_Unicode) 0x01
+
+// DEF_METRIC: Bei meinem Pool sollte immer die DefMetric bei
+// GetMetric( nWhich ) ankommen!
+// => Zum ermitteln der DefMetrik einfach ein GetMetric( 0 )
+#define DEF_METRIC 0
+
+ // -------------------------------------------------------------------------
+// class EditAttrib
+// -------------------------------------------------------------------------
+class EditAttrib
+{
+private:
+ EditAttrib() {;}
+ EditAttrib( const EditAttrib & ) {;}
+
+protected:
+ const SfxPoolItem* pItem;
+
+ EditAttrib( const SfxPoolItem& rAttr );
+ virtual ~EditAttrib();
+
+public:
+ // RemoveFromPool muss immer vorm DTOR Aufruf erfolgen!!
+ void RemoveFromPool( SfxItemPool& rPool );
+
+ USHORT Which() const { return pItem->Which(); }
+ const SfxPoolItem* GetItem() const { return pItem; }
+};
+
+ // -------------------------------------------------------------------------
+// class EditCharAttrib
+// -------------------------------------------------------------------------
+// bFeature: Attribut darf nicht expandieren/schrumfen, Laenge immer 1
+// bEdge: Attribut expandiert nicht, wenn genau an der Kante expandiert werden soll
+class EditCharAttrib : public EditAttrib
+{
+protected:
+
+ USHORT nStart;
+ USHORT nEnd;
+ BOOL bFeature :1;
+ BOOL bEdge :1;
+
+public:
+ EditCharAttrib( const SfxPoolItem& rAttr, USHORT nStart, USHORT nEnd );
+
+ USHORT& GetStart() { return nStart; }
+ USHORT& GetEnd() { return nEnd; }
+
+ USHORT GetStart() const { return nStart; }
+ USHORT GetEnd() const { return nEnd; }
+
+ inline USHORT GetLen() const;
+
+ inline void MoveForward( USHORT nDiff );
+ inline void MoveBackward( USHORT nDiff );
+
+ inline void Expand( USHORT nDiff );
+ inline void Collaps( USHORT nDiff );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+
+ BOOL IsIn( USHORT nIndex )
+ { return ( ( nStart <= nIndex ) && ( nEnd >= nIndex ) ); }
+ BOOL IsInside( USHORT nIndex )
+ { return ( ( nStart < nIndex ) && ( nEnd > nIndex ) ); }
+ BOOL IsEmpty()
+ { return nStart == nEnd; }
+
+ BOOL IsFeature() const { return bFeature; }
+ void SetFeature( BOOL b) { bFeature = b; }
+
+ BOOL IsEdge() const { return bEdge; }
+ void SetEdge( BOOL b ) { bEdge = b; }
+};
+
+inline USHORT EditCharAttrib::GetLen() const
+{
+ DBG_ASSERT( nEnd >= nStart, "EditCharAttrib: nEnd < nStart!" );
+ return nEnd-nStart;
+}
+
+inline void EditCharAttrib::MoveForward( USHORT nDiff )
+{
+ DBG_ASSERT( ((long)nEnd + nDiff) <= 0xFFFF, "EditCharAttrib: MoveForward?!" );
+ nStart = nStart + nDiff;
+ nEnd = nEnd + nDiff;
+}
+
+inline void EditCharAttrib::MoveBackward( USHORT nDiff )
+{
+ DBG_ASSERT( ((long)nStart - nDiff) >= 0, "EditCharAttrib: MoveBackward?!" );
+ nStart = nStart - nDiff;
+ nEnd = nEnd - nDiff;
+}
+
+inline void EditCharAttrib::Expand( USHORT nDiff )
+{
+ DBG_ASSERT( ( ((long)nEnd + nDiff) <= (long)0xFFFF ), "EditCharAttrib: Expand?!" );
+ DBG_ASSERT( !bFeature, "Bitte keine Features expandieren!" );
+ nEnd = nEnd + nDiff;
+}
+
+inline void EditCharAttrib::Collaps( USHORT nDiff )
+{
+ DBG_ASSERT( (long)nEnd - nDiff >= (long)nStart, "EditCharAttrib: Collaps?!" );
+ DBG_ASSERT( !bFeature, "Bitte keine Features schrumpfen!" );
+ nEnd = nEnd - nDiff;
+}
+
+ // -------------------------------------------------------------------------
+// class EditCharAttribFont
+// -------------------------------------------------------------------------
+class EditCharAttribFont: public EditCharAttrib
+{
+public:
+ EditCharAttribFont( const SvxFontItem& rAttr, USHORT nStart, USHORT nEnd );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+};
+
+ // -------------------------------------------------------------------------
+// class EditCharAttribWeight
+// -------------------------------------------------------------------------
+class EditCharAttribWeight : public EditCharAttrib
+{
+public:
+ EditCharAttribWeight( const SvxWeightItem& rAttr, USHORT nStart, USHORT nEnd );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+};
+ // -------------------------------------------------------------------------
+// class EditCharAttribItalic
+// -------------------------------------------------------------------------
+class EditCharAttribItalic : public EditCharAttrib
+{
+public:
+ EditCharAttribItalic( const SvxPostureItem& rAttr, USHORT nStart, USHORT nEnd );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+};
+
+ // -------------------------------------------------------------------------
+// class EditCharAttribShadow
+// -------------------------------------------------------------------------
+class EditCharAttribShadow : public EditCharAttrib
+{
+public:
+ EditCharAttribShadow( const SvxShadowedItem& rAttr, USHORT nStart, USHORT nEnd );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+};
+
+ // -------------------------------------------------------------------------
+// class EditCharAttribEscapement
+// -------------------------------------------------------------------------
+class EditCharAttribEscapement : public EditCharAttrib
+{
+public:
+ EditCharAttribEscapement( const SvxEscapementItem& rAttr, USHORT nStart, USHORT nEnd );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+};
+
+ // -------------------------------------------------------------------------
+// class EditCharAttribOutline
+// -------------------------------------------------------------------------
+class EditCharAttribOutline : public EditCharAttrib
+{
+public:
+ EditCharAttribOutline( const SvxContourItem& rAttr, USHORT nStart, USHORT nEnd );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+};
+
+ // -------------------------------------------------------------------------
+// class EditCharAttribStrikeout
+// -------------------------------------------------------------------------
+class EditCharAttribStrikeout : public EditCharAttrib
+{
+public:
+ EditCharAttribStrikeout( const SvxCrossedOutItem& rAttr, USHORT nStart, USHORT nEnd );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+};
+
+ // -------------------------------------------------------------------------
+// class EditCharAttribUnderline
+// -------------------------------------------------------------------------
+class EditCharAttribUnderline : public EditCharAttrib
+{
+public:
+ EditCharAttribUnderline( const SvxUnderlineItem& rAttr, USHORT nStart, USHORT nEnd );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+};
+
+// -------------------------------------------------------------------------
+// class EditCharAttribOverline
+// -------------------------------------------------------------------------
+class EditCharAttribOverline : public EditCharAttrib
+{
+public:
+ EditCharAttribOverline( const SvxOverlineItem& rAttr, USHORT nStart, USHORT nEnd );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+};
+
+// -------------------------------------------------------------------------
+// class EditCharAttribEmphasisMark
+// -------------------------------------------------------------------------
+class EditCharAttribEmphasisMark : public EditCharAttrib
+{
+public:
+ EditCharAttribEmphasisMark( const SvxEmphasisMarkItem& rAttr, USHORT nStart, USHORT nEnd );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+};
+
+// -------------------------------------------------------------------------
+// class EditCharAttribRelief
+// -------------------------------------------------------------------------
+class EditCharAttribRelief : public EditCharAttrib
+{
+public:
+ EditCharAttribRelief( const SvxCharReliefItem& rAttr, USHORT nStart, USHORT nEnd );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+};
+
+ // -------------------------------------------------------------------------
+// class EditCharAttribFontHeight
+// -------------------------------------------------------------------------
+class EditCharAttribFontHeight : public EditCharAttrib
+{
+public:
+ EditCharAttribFontHeight( const SvxFontHeightItem& rAttr, USHORT nStart, USHORT nEnd );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+};
+
+ // -------------------------------------------------------------------------
+// class EditCharAttribFontWidth
+// -------------------------------------------------------------------------
+class EditCharAttribFontWidth : public EditCharAttrib
+{
+public:
+ EditCharAttribFontWidth( const SvxCharScaleWidthItem& rAttr, USHORT nStart, USHORT nEnd );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+};
+
+ // -------------------------------------------------------------------------
+// class EditCharAttribColor
+// -------------------------------------------------------------------------
+class EditCharAttribColor : public EditCharAttrib
+{
+public:
+ EditCharAttribColor( const SvxColorItem& rAttr, USHORT nStart, USHORT nEnd );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+};
+
+ // -------------------------------------------------------------------------
+// class EditCharAttribLanguage
+// -------------------------------------------------------------------------
+class EditCharAttribLanguage : public EditCharAttrib
+{
+public:
+ EditCharAttribLanguage( const SvxLanguageItem& rAttr, USHORT nStart, USHORT nEnd );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+};
+
+ // -------------------------------------------------------------------------
+// class EditCharAttribTab
+// -------------------------------------------------------------------------
+class EditCharAttribTab : public EditCharAttrib
+{
+public:
+ EditCharAttribTab( const SfxVoidItem& rAttr, USHORT nPos );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+};
+
+ // -------------------------------------------------------------------------
+// class EditCharAttribLineBreak
+// -------------------------------------------------------------------------
+class EditCharAttribLineBreak : public EditCharAttrib
+{
+public:
+ EditCharAttribLineBreak( const SfxVoidItem& rAttr, USHORT nPos );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+};
+
+ // -------------------------------------------------------------------------
+// class EditCharAttribField
+// -------------------------------------------------------------------------
+class EditCharAttribField: public EditCharAttrib
+{
+ XubString aFieldValue;
+ Color* pTxtColor;
+ Color* pFldColor;
+
+ EditCharAttribField& operator = ( const EditCharAttribField& rAttr ) const;
+
+public:
+ EditCharAttribField( const SvxFieldItem& rAttr, USHORT nPos );
+ EditCharAttribField( const EditCharAttribField& rAttr );
+ ~EditCharAttribField();
+
+ BOOL operator == ( const EditCharAttribField& rAttr ) const;
+ BOOL operator != ( const EditCharAttribField& rAttr ) const
+ { return !(operator == ( rAttr ) ); }
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+ Color*& GetTxtColor() { return pTxtColor; }
+ Color*& GetFldColor() { return pFldColor; }
+
+ const XubString& GetFieldValue() const { return aFieldValue; }
+ XubString& GetFieldValue() { return aFieldValue; }
+
+ void Reset()
+ {
+ aFieldValue.Erase();
+ delete pTxtColor; pTxtColor = 0;
+ delete pFldColor; pFldColor = 0;
+ }
+};
+
+ // -------------------------------------------------------------------------
+// class EditCharAttribPairKerning
+// -------------------------------------------------------------------------
+class EditCharAttribPairKerning : public EditCharAttrib
+{
+public:
+ EditCharAttribPairKerning( const SvxAutoKernItem& rAttr, USHORT nStart, USHORT nEnd );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+};
+
+ // -------------------------------------------------------------------------
+// class EditCharAttribKerning
+// -------------------------------------------------------------------------
+class EditCharAttribKerning : public EditCharAttrib
+{
+public:
+ EditCharAttribKerning( const SvxKerningItem& rAttr, USHORT nStart, USHORT nEnd );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+};
+
+ // -------------------------------------------------------------------------
+// class EditCharAttribWordLineMode
+// -------------------------------------------------------------------------
+class EditCharAttribWordLineMode: public EditCharAttrib
+{
+public:
+ EditCharAttribWordLineMode( const SvxWordLineModeItem& rAttr, USHORT nStart, USHORT nEnd );
+
+ virtual void SetFont( SvxFont& rFont, OutputDevice* pOutDev );
+};
+
+
+#endif // _EDITATTR_HXX
diff --git a/editeng/source/editeng/editdbg.cxx b/editeng/source/editeng/editdbg.cxx
new file mode 100644
index 000000000000..01a387249f24
--- /dev/null
+++ b/editeng/source/editeng/editdbg.cxx
@@ -0,0 +1,586 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 <editeng/lspcitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/cntritem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/crsditem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/wrlmitem.hxx>
+#include <editeng/akrnitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/emphitem.hxx>
+#include <editeng/numitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/charreliefitem.hxx>
+#include <editeng/frmdiritem.hxx>
+
+#include <impedit.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/editview.hxx>
+#include <editdoc.hxx>
+#include <editdbg.hxx>
+
+#if defined( DBG_UTIL ) || ( OSL_DEBUG_LEVEL > 1 )
+
+ByteString DbgOutItem( const SfxItemPool& rPool, const SfxPoolItem& rItem )
+{
+ ByteString aDebStr;
+ switch ( rItem.Which() )
+ {
+ case EE_PARA_WRITINGDIR:
+ aDebStr += "WritingDir=";
+ aDebStr += ByteString::CreateFromInt32( ((SvxFrameDirectionItem&)rItem).GetValue() );
+ break;
+ case EE_PARA_OUTLLRSPACE:
+ case EE_PARA_LRSPACE:
+ aDebStr += "FI=";
+ aDebStr += ByteString::CreateFromInt32( ((SvxLRSpaceItem&)rItem).GetTxtFirstLineOfst() );
+ aDebStr += ", LI=";
+ aDebStr += ByteString::CreateFromInt32( ((SvxLRSpaceItem&)rItem).GetTxtLeft() );
+ aDebStr += ", RI=";
+ aDebStr += ByteString::CreateFromInt32( ((SvxLRSpaceItem&)rItem).GetRight() );
+ break;
+ case EE_PARA_NUMBULLET:
+ {
+ aDebStr += "NumItem ";
+ for ( USHORT nLevel = 0; nLevel < 3; nLevel++ )
+ {
+ aDebStr += "Level";
+ aDebStr += ByteString::CreateFromInt32( nLevel );
+ aDebStr += "=";
+ const SvxNumberFormat* pFmt = ((const SvxNumBulletItem&)rItem).GetNumRule()->Get( nLevel );
+ if ( pFmt )
+ {
+ aDebStr += "(";
+ aDebStr += ByteString::CreateFromInt32( pFmt->GetFirstLineOffset() );
+ aDebStr += ",";
+ aDebStr += ByteString::CreateFromInt32( pFmt->GetAbsLSpace() );
+ aDebStr += ",";
+ if ( pFmt->GetNumberingType() == SVX_NUM_BITMAP )
+ {
+ aDebStr += "Bitmap";
+ }
+ else if( pFmt->GetNumberingType() != SVX_NUM_CHAR_SPECIAL )
+ {
+ aDebStr += "Number";
+ }
+ else
+ {
+ aDebStr += "Char=[";
+ aDebStr += ByteString::CreateFromInt32( pFmt->GetBulletChar() );
+ aDebStr += "]";
+ }
+ aDebStr += ") ";
+ }
+ }
+ }
+ break;
+ case EE_PARA_BULLETSTATE:
+ aDebStr += "ShowBullet=";
+ aDebStr += ByteString::CreateFromInt32( ((SfxBoolItem&)rItem).GetValue() );
+ break;
+ case EE_PARA_HYPHENATE:
+ aDebStr += "Hyphenate=";
+ aDebStr += ByteString::CreateFromInt32( ((SfxBoolItem&)rItem).GetValue() );
+ break;
+ case EE_PARA_OUTLLEVEL:
+ aDebStr += "Level=";
+ aDebStr += ByteString::CreateFromInt32( ((SfxInt16Item&)rItem).GetValue() );
+ break;
+ case EE_PARA_ULSPACE:
+ aDebStr += "SB=";
+ aDebStr += ByteString::CreateFromInt32( ((SvxULSpaceItem&)rItem).GetUpper() );
+ aDebStr += ", SA=";
+ aDebStr += ByteString::CreateFromInt32( ((SvxULSpaceItem&)rItem).GetLower() );
+ break;
+ case EE_PARA_SBL:
+ aDebStr += "SBL=";
+ if ( ((SvxLineSpacingItem&)rItem).GetLineSpaceRule() == SVX_LINE_SPACE_MIN )
+ {
+ aDebStr += "Min: ";
+ aDebStr += ByteString::CreateFromInt32( ((SvxLineSpacingItem&)rItem).GetInterLineSpace() );
+ }
+ else if ( ((SvxLineSpacingItem&)rItem).GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP )
+ {
+ aDebStr += "Prop: ";
+ aDebStr += ByteString::CreateFromInt32( (ULONG)((SvxLineSpacingItem&)rItem).GetPropLineSpace() );
+ }
+ else
+ aDebStr += "Unsupported Type!";
+ break;
+ case EE_PARA_JUST:
+ aDebStr += "SvxAdust=";
+ aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxAdjustItem&)rItem).GetAdjust() );
+ break;
+ case EE_PARA_TABS:
+ {
+ aDebStr += "Tabs: ";
+ const SvxTabStopItem& rTabs = (const SvxTabStopItem&) rItem;
+ aDebStr += ByteString::CreateFromInt32( rTabs.Count() );
+ if ( rTabs.Count() )
+ {
+ aDebStr += "( ";
+ for ( USHORT i = 0; i < rTabs.Count(); i++ )
+ {
+ const SvxTabStop& rTab = rTabs[i];
+ aDebStr += ByteString::CreateFromInt32( rTab.GetTabPos() );
+ aDebStr += " ";
+ }
+ aDebStr += ")";
+ }
+ }
+ break;
+ case EE_CHAR_LANGUAGE:
+ case EE_CHAR_LANGUAGE_CJK:
+ case EE_CHAR_LANGUAGE_CTL:
+ aDebStr += "Language=";
+ aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxLanguageItem&)rItem).GetLanguage() );
+ break;
+ case EE_CHAR_COLOR:
+ {
+ aDebStr += "Color= ";
+ Color aColor( ((SvxColorItem&)rItem).GetValue() );
+ aDebStr += ByteString::CreateFromInt32( (USHORT)aColor.GetRed() );
+ aDebStr += ", ";
+ aDebStr += ByteString::CreateFromInt32( (USHORT)aColor.GetGreen() );
+ aDebStr += ", ";
+ aDebStr += ByteString::CreateFromInt32( (USHORT)aColor.GetBlue() );
+ }
+ break;
+ case EE_CHAR_FONTINFO:
+ case EE_CHAR_FONTINFO_CJK:
+ case EE_CHAR_FONTINFO_CTL:
+ {
+ aDebStr += "Font=";
+ aDebStr += ByteString( ((SvxFontItem&)rItem).GetFamilyName(), RTL_TEXTENCODING_ASCII_US );
+ aDebStr += " (CharSet: ";
+ aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxFontItem&)rItem).GetCharSet() );
+ aDebStr += ')';
+ }
+ break;
+ case EE_CHAR_FONTHEIGHT:
+ case EE_CHAR_FONTHEIGHT_CJK:
+ case EE_CHAR_FONTHEIGHT_CTL:
+ {
+ aDebStr += "Groesse=";
+ aDebStr += ByteString::CreateFromInt32( ((SvxFontHeightItem&)rItem).GetHeight() );
+ Size aSz( 0, ((SvxFontHeightItem&)rItem).GetHeight() );
+ SfxMapUnit eUnit = rPool.GetMetric( rItem.Which() );
+ MapMode aItemMapMode( (MapUnit) eUnit );
+ MapMode aPntMap( MAP_POINT );
+ aSz = OutputDevice::LogicToLogic( aSz, aItemMapMode, aPntMap );
+ aDebStr += " Points=";
+ aDebStr += ByteString::CreateFromInt32( aSz.Height() );
+ }
+ break;
+ case EE_CHAR_FONTWIDTH:
+ {
+ aDebStr += "Breite=";
+ aDebStr += ByteString::CreateFromInt32( ((SvxCharScaleWidthItem&)rItem).GetValue() );
+ aDebStr += "%";
+ }
+ break;
+ case EE_CHAR_WEIGHT:
+ case EE_CHAR_WEIGHT_CJK:
+ case EE_CHAR_WEIGHT_CTL:
+ aDebStr += "FontWeight=";
+ aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxWeightItem&)rItem).GetWeight() );
+ break;
+ case EE_CHAR_UNDERLINE:
+ aDebStr += "FontUnderline=";
+ aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxUnderlineItem&)rItem).GetLineStyle() );
+ break;
+ case EE_CHAR_OVERLINE:
+ aDebStr += "FontOverline=";
+ aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxOverlineItem&)rItem).GetLineStyle() );
+ break;
+ case EE_CHAR_EMPHASISMARK:
+ aDebStr += "FontUnderline=";
+ aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxEmphasisMarkItem&)rItem).GetEmphasisMark() );
+ break;
+ case EE_CHAR_RELIEF:
+ aDebStr += "FontRelief=";
+ aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxCharReliefItem&)rItem).GetValue() );
+ break;
+ case EE_CHAR_STRIKEOUT:
+ aDebStr += "FontStrikeout=";
+ aDebStr +=ByteString::CreateFromInt32( (USHORT)((SvxCrossedOutItem&)rItem).GetStrikeout() );
+ break;
+ case EE_CHAR_ITALIC:
+ case EE_CHAR_ITALIC_CJK:
+ case EE_CHAR_ITALIC_CTL:
+ aDebStr += "FontPosture=";
+ aDebStr +=ByteString::CreateFromInt32( (USHORT)((SvxPostureItem&)rItem).GetPosture() );
+ break;
+ case EE_CHAR_OUTLINE:
+ aDebStr += "FontOutline=";
+ aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxContourItem&)rItem).GetValue() );
+ break;
+ case EE_CHAR_SHADOW:
+ aDebStr += "FontShadowed=";
+ aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxShadowedItem&)rItem).GetValue() );
+ break;
+ case EE_CHAR_ESCAPEMENT:
+ aDebStr += "Escape=";
+ aDebStr += ByteString::CreateFromInt32( (short)((SvxEscapementItem&)rItem).GetEsc() );
+ aDebStr += ", ";
+ aDebStr += ByteString::CreateFromInt32( (short)((SvxEscapementItem&)rItem).GetProp() );
+ break;
+ case EE_CHAR_PAIRKERNING:
+ aDebStr += "PairKerning=";
+ aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxAutoKernItem&)rItem).GetValue() );
+ break;
+ case EE_CHAR_KERNING:
+ {
+ aDebStr += "Kerning=";
+ aDebStr += ByteString::CreateFromInt32( (short)((SvxKerningItem&)rItem).GetValue() );
+ Size aSz( 0, (short)((SvxKerningItem&)rItem).GetValue() );
+ SfxMapUnit eUnit = rPool.GetMetric( rItem.Which() );
+ MapMode aItemMapMode( (MapUnit) eUnit );
+ MapMode aPntMap( MAP_POINT );
+ aSz = OutputDevice::LogicToLogic( aSz, aItemMapMode, aPntMap );
+ aDebStr += " Points=";
+ aDebStr += ByteString::CreateFromInt32( aSz.Height() );
+ }
+ break;
+ case EE_CHAR_WLM:
+ aDebStr += "WordLineMode=";
+ aDebStr += ByteString::CreateFromInt32( (USHORT)((SvxWordLineModeItem&)rItem).GetValue() );
+ break;
+ case EE_CHAR_XMLATTRIBS:
+ aDebStr += "XMLAttribs=...";
+ break;
+ }
+ return aDebStr;
+}
+
+void DbgOutItemSet( FILE* fp, const SfxItemSet& rSet, BOOL bSearchInParent, BOOL bShowALL )
+{
+ for ( USHORT nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ )
+ {
+ fprintf( fp, "\nWhich: %i\t", nWhich );
+ if ( rSet.GetItemState( nWhich, bSearchInParent ) == SFX_ITEM_OFF )
+ fprintf( fp, "ITEM_OFF " );
+ else if ( rSet.GetItemState( nWhich, bSearchInParent ) == SFX_ITEM_DONTCARE )
+ fprintf( fp, "ITEM_DC " );
+ else if ( rSet.GetItemState( nWhich, bSearchInParent ) == SFX_ITEM_ON )
+ fprintf( fp, "ITEM_ON *" );
+
+ if ( !bShowALL && ( rSet.GetItemState( nWhich, bSearchInParent ) != SFX_ITEM_ON ) )
+ continue;
+
+ const SfxPoolItem& rItem = rSet.Get( nWhich, bSearchInParent );
+ ByteString aDebStr = DbgOutItem( *rSet.GetPool(), rItem );
+ fprintf( fp, "%s", aDebStr.GetBuffer() );
+ }
+}
+
+void EditDbg::ShowEditEngineData( EditEngine* pEE, BOOL bInfoBox )
+{
+#if defined UNX
+ FILE* fp = fopen( "/tmp/debug.log", "w" );
+#else
+ FILE* fp = fopen( "d:\\debug.log", "w" );
+#endif
+ if ( fp == 0 )
+ {
+ DBG_ERROR( "Log-File konnte nicht angelegt werden!" );
+ return;
+ }
+
+ const SfxItemPool& rPool = *pEE->GetEmptyItemSet().GetPool();
+
+ fprintf( fp, "================================================================================" );
+ fprintf( fp, "\n================== Dokument ================================================" );
+ fprintf( fp, "\n================================================================================" );
+ for ( USHORT nPortion = 0; nPortion < pEE->pImpEditEngine->GetParaPortions(). Count(); nPortion++)
+ {
+
+ ParaPortion* pPPortion = pEE->pImpEditEngine->GetParaPortions().GetObject(nPortion );
+ fprintf( fp, " \nAbsatz %i: Laenge = %i, Invalid = %i\nText = '%s'", nPortion, pPPortion->GetNode()->Len(), pPPortion->IsInvalid(), ByteString( *pPPortion->GetNode(), RTL_TEXTENCODING_ASCII_US ).GetBuffer() );
+ fprintf( fp, "\nVorlage:" );
+ SfxStyleSheet* pStyle = pPPortion->GetNode()->GetStyleSheet();
+ if ( pStyle )
+ fprintf( fp, " %s", ByteString( pStyle->GetName(), RTL_TEXTENCODING_ASCII_US ).GetBuffer() );
+ fprintf( fp, "\nAbsatzattribute:" );
+ DbgOutItemSet( fp, pPPortion->GetNode()->GetContentAttribs().GetItems(), FALSE, FALSE );
+
+ fprintf( fp, "\nZeichenattribute:" );
+ BOOL bZeroAttr = FALSE;
+ USHORT z;
+ for ( z = 0; z < pPPortion->GetNode()->GetCharAttribs().Count(); z++ )
+ {
+ EditCharAttrib* pAttr = pPPortion->GetNode()->GetCharAttribs().GetAttribs().GetObject( z );
+ ByteString aCharAttribs;
+ aCharAttribs += "\nA";
+ aCharAttribs += ByteString::CreateFromInt32( nPortion );
+ aCharAttribs += ": ";
+ aCharAttribs += ByteString::CreateFromInt32( pAttr->GetItem()->Which() );
+ aCharAttribs += '\t';
+ aCharAttribs += ByteString::CreateFromInt32( pAttr->GetStart() );
+ aCharAttribs += '\t';
+ aCharAttribs += ByteString::CreateFromInt32( pAttr->GetEnd() );
+ if ( pAttr->IsEmpty() )
+ bZeroAttr = TRUE;
+ fprintf( fp, "%s => ", aCharAttribs.GetBuffer() );
+
+ ByteString aDebStr = DbgOutItem( rPool, *pAttr->GetItem() );
+ fprintf( fp, "%s", aDebStr.GetBuffer() );
+ }
+ if ( bZeroAttr )
+ fprintf( fp, "\nNULL-Attribute!" );
+
+ USHORT nTextPortions = pPPortion->GetTextPortions().Count();
+ ByteString aPortionStr("\nTextportions: #");
+ aPortionStr += ByteString::CreateFromInt32( nTextPortions );
+ aPortionStr += " \nA";
+ aPortionStr += ByteString::CreateFromInt32( nPortion );
+ aPortionStr += ": Absatzlaenge = ";
+ aPortionStr += ByteString::CreateFromInt32( pPPortion->GetNode()->Len() );
+ aPortionStr += "\nA";
+ aPortionStr += ByteString::CreateFromInt32( nPortion );
+ aPortionStr += ": ";
+ ULONG n = 0;
+ for ( z = 0; z < nTextPortions; z++ )
+ {
+ TextPortion* pPortion = pPPortion->GetTextPortions().GetObject( z );
+ aPortionStr += " ";
+ aPortionStr += ByteString::CreateFromInt32( pPortion->GetLen() );
+ aPortionStr += "(";
+ aPortionStr += ByteString::CreateFromInt32( pPortion->GetSize().Width() );
+ aPortionStr += ")";
+ aPortionStr += "[";
+ aPortionStr += ByteString::CreateFromInt32( (USHORT)pPortion->GetKind() );
+ aPortionStr += "]";
+ aPortionStr += ";";
+ n += pPortion->GetLen();
+ }
+ aPortionStr += "\nA";
+ aPortionStr += ByteString::CreateFromInt32( nPortion );
+ aPortionStr += ": Gesamtlaenge: ";
+ aPortionStr += ByteString::CreateFromInt32( n );
+ if ( pPPortion->GetNode()->Len() != n )
+ aPortionStr += " => Fehler !!!";
+ fprintf( fp, "%s", aPortionStr.GetBuffer() );
+
+
+ fprintf( fp, "\n\nZeilen:" );
+ // Erstmal die Inhalte...
+ USHORT nLine;
+ for ( nLine = 0; nLine < pPPortion->GetLines().Count(); nLine++ )
+ {
+ EditLine* pLine = pPPortion->GetLines().GetObject( nLine );
+
+ ByteString aLine( *(pPPortion->GetNode()), pLine->GetStart(), pLine->GetEnd() - pLine->GetStart(), RTL_TEXTENCODING_ASCII_US );
+ fprintf( fp, "\nZeile %i\t>%s<", nLine, aLine.GetBuffer() );
+ }
+ // dann die internen Daten...
+ for ( nLine = 0; nLine < pPPortion->GetLines().Count(); nLine++ )
+ {
+ EditLine* pLine = pPPortion->GetLines().GetObject( nLine );
+ fprintf( fp, "\nZeile %i:\tStart: %i,\tEnd: %i", nLine, pLine->GetStart(), pLine->GetEnd() );
+ fprintf( fp, "\t\tPortions: %i - %i.\tHoehe: %i, Ascent=%i", pLine->GetStartPortion(), pLine->GetEndPortion(), pLine->GetHeight(), pLine->GetMaxAscent() );
+ }
+
+ fprintf( fp, "\n-----------------------------------------------------------------------------" );
+ }
+
+ if ( pEE->pImpEditEngine->GetStyleSheetPool() )
+ {
+ ULONG nStyles = pEE->pImpEditEngine->GetStyleSheetPool() ? pEE->pImpEditEngine->GetStyleSheetPool()->Count() : 0;
+ fprintf( fp, "\n\n ================================================================================" );
+ fprintf( fp, "\n================== Stylesheets =============================================" );
+ fprintf( fp, "\n================================================================================" );
+ fprintf( fp, "\n#Vorlagen: %lu\n", nStyles );
+ SfxStyleSheetIterator aIter( pEE->pImpEditEngine->GetStyleSheetPool(), SFX_STYLE_FAMILY_ALL );
+ SfxStyleSheetBase* pStyle = aIter.First();
+ while ( pStyle )
+ {
+ fprintf( fp, "\nVorlage: %s", ByteString( pStyle->GetName(), RTL_TEXTENCODING_ASCII_US ).GetBuffer() );
+ fprintf( fp, "\nParent: %s", ByteString( pStyle->GetParent(), RTL_TEXTENCODING_ASCII_US ).GetBuffer() );
+ fprintf( fp, "\nFollow: %s", ByteString( pStyle->GetFollow(), RTL_TEXTENCODING_ASCII_US ).GetBuffer() );
+ DbgOutItemSet( fp, pStyle->GetItemSet(), FALSE, FALSE );
+ fprintf( fp, "\n----------------------------------" );
+
+ pStyle = aIter.Next();
+ }
+ }
+
+ fprintf( fp, "\n\n ================================================================================" );
+ fprintf( fp, "\n================== Defaults ================================================" );
+ fprintf( fp, "\n================================================================================" );
+ DbgOutItemSet( fp, pEE->pImpEditEngine->GetEmptyItemSet(), TRUE, TRUE );
+
+ fprintf( fp, "\n\n ================================================================================" );
+ fprintf( fp, "\n================== EditEngine & Views ======================================" );
+ fprintf( fp, "\n================================================================================" );
+ fprintf( fp, "\nControl: %lx", pEE->GetControlWord() );
+ fprintf( fp, "\nRefMapMode: %i", pEE->pImpEditEngine->pRefDev->GetMapMode().GetMapUnit() );
+ fprintf( fp, "\nPaperSize: %li x %li", pEE->GetPaperSize().Width(), pEE->GetPaperSize().Height() );
+ fprintf( fp, "\nMaxAutoPaperSize: %li x %li", pEE->GetMaxAutoPaperSize().Width(), pEE->GetMaxAutoPaperSize().Height() );
+ fprintf( fp, "\nMinAutoPaperSize: %li x %li", pEE->GetMinAutoPaperSize().Width(), pEE->GetMinAutoPaperSize().Height() );
+ fprintf( fp, "\nUpdate: %i", pEE->GetUpdateMode() );
+ fprintf( fp, "\nAnzahl der Views: %i", pEE->GetViewCount() );
+ for ( USHORT nView = 0; nView < pEE->GetViewCount(); nView++ )
+ {
+ EditView* pV = pEE->GetView( nView );
+ DBG_ASSERT( pV, "View nicht gefunden!" );
+ fprintf( fp, "\nView %i: Focus=%i", nView, pV->GetWindow()->HasFocus() );
+ Rectangle aR( pV->GetOutputArea() );
+ fprintf( fp, "\n OutputArea: nX=%li, nY=%li, dX=%li, dY=%li, MapMode = %i", aR.TopLeft().X(), aR.TopLeft().Y(), aR.GetSize().Width(), aR.GetSize().Height() , pV->GetWindow()->GetMapMode().GetMapUnit() );
+ aR = pV->GetVisArea();
+ fprintf( fp, "\n VisArea: nX=%li, nY=%li, dX=%li, dY=%li", aR.TopLeft().X(), aR.TopLeft().Y(), aR.GetSize().Width(), aR.GetSize().Height() );
+ ESelection aSel = pV->GetSelection();
+ fprintf( fp, "\n Selektion: Start=%u,%u, End=%u,%u", aSel.nStartPara, aSel.nStartPos, aSel.nEndPara, aSel.nEndPos );
+ }
+ if ( pEE->GetActiveView() )
+ {
+ fprintf( fp, "\n\n ================================================================================" );
+ fprintf( fp, "\n================== Aktuelle View ===========================================" );
+ fprintf( fp, "\n================================================================================" );
+ DbgOutItemSet( fp, pEE->GetActiveView()->GetAttribs(), TRUE, FALSE );
+ }
+ fclose( fp );
+ if ( bInfoBox )
+ InfoBox(0, String( RTL_CONSTASCII_USTRINGPARAM( "D:\\DEBUG.LOG !" ) ) ).Execute();
+}
+
+ByteString EditDbg::GetPortionInfo( ParaPortion* pPPortion )
+{
+ USHORT z;
+
+ ByteString aDebStr( "Absatzlaenge = " );
+ aDebStr += ByteString::CreateFromInt32( pPPortion->GetNode()->Len() );
+
+ aDebStr += "\nZeichenattribute:";
+ for ( z = 0; z < pPPortion->GetNode()->GetCharAttribs().Count(); z++ )
+ {
+ EditCharAttrib* pAttr = pPPortion->GetNode()->GetCharAttribs().GetAttribs().GetObject( z );
+ aDebStr += "\n ";
+ aDebStr += ByteString::CreateFromInt32( pAttr->GetItem()->Which() );
+ aDebStr += '\t';
+ aDebStr += ByteString::CreateFromInt32( pAttr->GetStart() );
+ aDebStr += '\t';
+ aDebStr += ByteString::CreateFromInt32( pAttr->GetEnd() );
+ }
+
+ aDebStr += "\nTextportions:";
+ USHORT n = 0;
+ for ( z = 0; z < pPPortion->GetTextPortions().Count(); z++ )
+ {
+ TextPortion* pPortion = pPPortion->GetTextPortions().GetObject( z );
+ aDebStr += " ";
+ aDebStr += ByteString::CreateFromInt32( pPortion->GetLen() );
+ aDebStr += "(";
+ aDebStr += ByteString::CreateFromInt32( pPortion->GetSize().Width() );
+ aDebStr += ")";
+ aDebStr += ";";
+ n = n + pPortion->GetLen();
+ }
+ aDebStr += "\nGesamtlaenge: ";
+ aDebStr += ByteString::CreateFromInt32( n );
+ aDebStr += "\nSortiert nach Start:";
+ for ( USHORT x = 0; x < pPPortion->GetNode()->GetCharAttribs().Count(); x++ )
+ {
+ EditCharAttrib* pCurAttrib = pPPortion->GetNode()->GetCharAttribs().GetAttribs().GetObject( x );
+ aDebStr += "\nStart: ";
+ aDebStr += ByteString::CreateFromInt32( pCurAttrib->GetStart() );
+ aDebStr += "\tEnde: ";
+ aDebStr += ByteString::CreateFromInt32( pCurAttrib->GetEnd() );
+ }
+ return aDebStr;
+}
+
+ByteString EditDbg::GetTextPortionInfo( TextPortionList& rPortions )
+{
+ ByteString aDebStr;
+ for ( USHORT z = 0; z < rPortions.Count(); z++ )
+ {
+ TextPortion* pPortion = rPortions.GetObject( z );
+ aDebStr += " ";
+ aDebStr += ByteString::CreateFromInt32( pPortion->GetLen() );
+ aDebStr += "(";
+ aDebStr += ByteString::CreateFromInt32( pPortion->GetSize().Width() );
+ aDebStr += ")";
+ aDebStr += ";";
+ }
+ return aDebStr;
+}
+
+void EditDbg::ShowPortionData( ParaPortion* pPortion )
+{
+ ByteString aDebStr( GetPortionInfo( pPortion ) );
+ InfoBox( 0, String( aDebStr, RTL_TEXTENCODING_ASCII_US ) ).Execute();
+}
+
+
+BOOL ParaPortion::DbgCheckTextPortions()
+{
+ // pruefen, ob Portionlaenge ok:
+ USHORT nXLen = 0;
+ for ( USHORT nPortion = 0; nPortion < aTextPortionList.Count(); nPortion++ )
+ nXLen = nXLen + aTextPortionList[nPortion]->GetLen();
+ return nXLen == pNode->Len() ? TRUE : FALSE;
+}
+
+BOOL CheckOrderedList( CharAttribArray& rAttribs, BOOL bStart )
+{
+ USHORT nPrev = 0;
+ for ( USHORT nAttr = 0; nAttr < rAttribs.Count(); nAttr++ )
+ {
+ EditCharAttrib* pAttr = rAttribs[nAttr];
+ USHORT nCur = bStart ? pAttr->GetStart() : pAttr->GetEnd();
+ if ( nCur < nPrev )
+ return FALSE;
+
+ nPrev = nCur;
+ }
+ return TRUE;
+}
+
+#endif
+
diff --git a/editeng/source/editeng/editdbg.hxx b/editeng/source/editeng/editdbg.hxx
new file mode 100644
index 000000000000..efe3248e9af4
--- /dev/null
+++ b/editeng/source/editeng/editdbg.hxx
@@ -0,0 +1,57 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef _EDITDBG_HXX
+#define _EDITDBG_HXX
+
+#include <svl/solar.hrc>
+#include <tools/string.hxx>
+#include <stdio.h>
+
+class EditEngine;
+class ParaPortion;
+class EditUndoList;
+class TextPortionList;
+class SfxItemSet;
+class SfxItemPool;
+class SfxPoolItem;
+
+ByteString DbgOutItem( const SfxItemPool& rPool, const SfxPoolItem& rItem );
+void DbgOutItemSet( FILE* fp, const SfxItemSet& rSet, BOOL bSearchInParent, BOOL bShowALL );
+
+class EditDbg
+{
+public:
+ static void ShowEditEngineData( EditEngine* pEditEngine, BOOL bInfoBox = TRUE );
+ static void ShowPortionData( ParaPortion* pPortion );
+ static ByteString GetPortionInfo( ParaPortion* pPPortion );
+ static ByteString GetTextPortionInfo( TextPortionList& rPortions );
+ static ByteString GetUndoDebStr( EditUndoList* pUndoList );
+};
+
+
+#endif // _EDITDBG_HXX
diff --git a/editeng/source/editeng/editdoc.cxx b/editeng/source/editeng/editdoc.cxx
new file mode 100644
index 000000000000..9ac179a2a47f
--- /dev/null
+++ b/editeng/source/editeng/editdoc.cxx
@@ -0,0 +1,2314 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 <editeng/tstpitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/crsditem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/wrlmitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/cntritem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/akrnitem.hxx>
+#include <editeng/cscoitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/emphitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/charreliefitem.hxx>
+#include <editeng/xmlcnitm.hxx>
+#include <editeng/editids.hrc>
+
+#include <editdoc.hxx>
+#include <editdbg.hxx>
+#include <editeng/eerdll.hxx>
+#include <eerdll2.hxx>
+#include <tools/stream.hxx>
+#include <tools/debug.hxx>
+#include <tools/shl.hxx>
+#include <vcl/svapp.hxx>
+#include <com/sun/star/i18n/ScriptType.hpp>
+#include <stdlib.h> // qsort
+
+using namespace ::com::sun::star;
+
+
+// ------------------------------------------------------------
+
+USHORT GetScriptItemId( USHORT nItemId, short nScriptType )
+{
+ USHORT nId = nItemId;
+
+ if ( ( nScriptType == i18n::ScriptType::ASIAN ) ||
+ ( nScriptType == i18n::ScriptType::COMPLEX ) )
+ {
+ switch ( nItemId )
+ {
+ case EE_CHAR_LANGUAGE:
+ nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_LANGUAGE_CJK : EE_CHAR_LANGUAGE_CTL;
+ break;
+ case EE_CHAR_FONTINFO:
+ nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_FONTINFO_CJK : EE_CHAR_FONTINFO_CTL;
+ break;
+ case EE_CHAR_FONTHEIGHT:
+ nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_FONTHEIGHT_CJK : EE_CHAR_FONTHEIGHT_CTL;
+ break;
+ case EE_CHAR_WEIGHT:
+ nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_WEIGHT_CJK : EE_CHAR_WEIGHT_CTL;
+ break;
+ case EE_CHAR_ITALIC:
+ nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_ITALIC_CJK : EE_CHAR_ITALIC_CTL;
+ break;
+ }
+ }
+
+ return nId;
+}
+
+BOOL IsScriptItemValid( USHORT nItemId, short nScriptType )
+{
+ BOOL bValid = TRUE;
+
+ switch ( nItemId )
+ {
+ case EE_CHAR_LANGUAGE:
+ bValid = nScriptType == i18n::ScriptType::LATIN;
+ break;
+ case EE_CHAR_LANGUAGE_CJK:
+ bValid = nScriptType == i18n::ScriptType::ASIAN;
+ break;
+ case EE_CHAR_LANGUAGE_CTL:
+ bValid = nScriptType == i18n::ScriptType::COMPLEX;
+ break;
+ case EE_CHAR_FONTINFO:
+ bValid = nScriptType == i18n::ScriptType::LATIN;
+ break;
+ case EE_CHAR_FONTINFO_CJK:
+ bValid = nScriptType == i18n::ScriptType::ASIAN;
+ break;
+ case EE_CHAR_FONTINFO_CTL:
+ bValid = nScriptType == i18n::ScriptType::COMPLEX;
+ break;
+ case EE_CHAR_FONTHEIGHT:
+ bValid = nScriptType == i18n::ScriptType::LATIN;
+ break;
+ case EE_CHAR_FONTHEIGHT_CJK:
+ bValid = nScriptType == i18n::ScriptType::ASIAN;
+ break;
+ case EE_CHAR_FONTHEIGHT_CTL:
+ bValid = nScriptType == i18n::ScriptType::COMPLEX;
+ break;
+ case EE_CHAR_WEIGHT:
+ bValid = nScriptType == i18n::ScriptType::LATIN;
+ break;
+ case EE_CHAR_WEIGHT_CJK:
+ bValid = nScriptType == i18n::ScriptType::ASIAN;
+ break;
+ case EE_CHAR_WEIGHT_CTL:
+ bValid = nScriptType == i18n::ScriptType::COMPLEX;
+ break;
+ case EE_CHAR_ITALIC:
+ bValid = nScriptType == i18n::ScriptType::LATIN;
+ break;
+ case EE_CHAR_ITALIC_CJK:
+ bValid = nScriptType == i18n::ScriptType::ASIAN;
+ break;
+ case EE_CHAR_ITALIC_CTL:
+ bValid = nScriptType == i18n::ScriptType::COMPLEX;
+ break;
+ }
+
+ return bValid;
+}
+
+
+// ------------------------------------------------------------
+
+// Sollte spaeter zentral nach TOOLS/STRING (Aktuell: 303)
+// fuer Grep: WS_TARGET
+
+DBG_NAME( EE_TextPortion );
+DBG_NAME( EE_EditLine );
+DBG_NAME( EE_ContentNode );
+DBG_NAME( EE_CharAttribList );
+
+SfxItemInfo aItemInfos[EDITITEMCOUNT] = {
+ { SID_ATTR_FRAMEDIRECTION, SFX_ITEM_POOLABLE }, // EE_PARA_WRITINGDIR
+ { 0, SFX_ITEM_POOLABLE }, // EE_PARA_XMLATTRIBS
+ { SID_ATTR_PARA_HANGPUNCTUATION, SFX_ITEM_POOLABLE }, // EE_PARA_HANGINGPUNCTUATION
+ { SID_ATTR_PARA_FORBIDDEN_RULES, SFX_ITEM_POOLABLE },
+ { SID_ATTR_PARA_SCRIPTSPACE, SFX_ITEM_POOLABLE }, // EE_PARA_ASIANCJKSPACING
+ { SID_ATTR_NUMBERING_RULE, SFX_ITEM_POOLABLE }, // EE_PARA_NUMBULL
+ { 0, SFX_ITEM_POOLABLE }, // EE_PARA_HYPHENATE
+ { 0, SFX_ITEM_POOLABLE }, // EE_PARA_BULLETSTATE
+ { 0, SFX_ITEM_POOLABLE }, // EE_PARA_OUTLLRSPACE
+ { SID_ATTR_PARA_OUTLLEVEL, SFX_ITEM_POOLABLE },
+ { SID_ATTR_PARA_BULLET, SFX_ITEM_POOLABLE },
+ { SID_ATTR_LRSPACE, SFX_ITEM_POOLABLE },
+ { SID_ATTR_ULSPACE, SFX_ITEM_POOLABLE },
+ { SID_ATTR_PARA_LINESPACE, SFX_ITEM_POOLABLE },
+ { SID_ATTR_PARA_ADJUST, SFX_ITEM_POOLABLE },
+ { SID_ATTR_TABSTOP, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_COLOR, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_FONT, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_FONTHEIGHT, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_SCALEWIDTH, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_WEIGHT, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_UNDERLINE, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_STRIKEOUT, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_POSTURE, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_CONTOUR, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_SHADOWED, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_ESCAPEMENT, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_AUTOKERN, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_KERNING, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_WORDLINEMODE, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_LANGUAGE, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_CJK_LANGUAGE, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_CTL_LANGUAGE, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_CJK_FONT, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_CTL_FONT, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_CJK_FONTHEIGHT, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_CTL_FONTHEIGHT, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_CJK_WEIGHT, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_CTL_WEIGHT, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_CJK_POSTURE, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_CTL_POSTURE, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_EMPHASISMARK, SFX_ITEM_POOLABLE },
+ { SID_ATTR_CHAR_RELIEF, SFX_ITEM_POOLABLE },
+ { 0, SFX_ITEM_POOLABLE }, // EE_CHAR_RUBI_DUMMY
+ { 0, SFX_ITEM_POOLABLE }, // EE_CHAR_XMLATTRIBS
+ { SID_ATTR_CHAR_OVERLINE, SFX_ITEM_POOLABLE },
+ { 0, SFX_ITEM_POOLABLE }, // EE_FEATURE_TAB
+ { 0, SFX_ITEM_POOLABLE }, // EE_FEATURE_LINEBR
+ { SID_ATTR_CHAR_CHARSETCOLOR, SFX_ITEM_POOLABLE }, // EE_FEATURE_NOTCONV
+ { SID_FIELD, SFX_ITEM_POOLABLE }
+};
+
+USHORT aV1Map[] = {
+ 3999, 4001, 4002, 4003, 4004, 4005, 4006,
+ 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4017, 4018, 4019 // MI: 4019?
+};
+
+USHORT aV2Map[] = {
+ 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4009,
+ 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4018, 4019, 4020
+};
+
+USHORT aV3Map[] = {
+ 3997, 3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007,
+ 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019,
+ 4020, 4021
+};
+
+USHORT aV4Map[] = {
+ 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003,
+ 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013,
+ 4014, 4015, 4016, 4017, 4018,
+ /* CJK Items inserted here: EE_CHAR_LANGUAGE - EE_CHAR_XMLATTRIBS */
+ 4034, 4035, 4036, 4037
+};
+
+USHORT aV5Map[] = {
+ 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003,
+ 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013,
+ 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023,
+ 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033,
+ /* EE_CHAR_OVERLINE inserted here */
+ 4035, 4036, 4037, 4038
+};
+
+SV_IMPL_PTRARR( DummyContentList, ContentNode* );
+SV_IMPL_VARARR( ScriptTypePosInfos, ScriptTypePosInfo );
+SV_IMPL_VARARR( WritingDirectionInfos, WritingDirectionInfo );
+// SV_IMPL_VARARR( ExtraCharInfos, ExtraCharInfo );
+
+
+int SAL_CALL CompareStart( const void* pFirst, const void* pSecond )
+{
+ if ( (*((EditCharAttrib**)pFirst))->GetStart() < (*((EditCharAttrib**)pSecond))->GetStart() )
+ return (-1);
+ else if ( (*((EditCharAttrib**)pFirst))->GetStart() > (*((EditCharAttrib**)pSecond))->GetStart() )
+ return (1);
+ return 0;
+}
+
+EditCharAttrib* MakeCharAttrib( SfxItemPool& rPool, const SfxPoolItem& rAttr, USHORT nS, USHORT nE )
+{
+ // das neue Attribut im Pool anlegen
+ const SfxPoolItem& rNew = rPool.Put( rAttr );
+
+ EditCharAttrib* pNew = 0;
+ switch( rNew.Which() )
+ {
+ case EE_CHAR_LANGUAGE:
+ case EE_CHAR_LANGUAGE_CJK:
+ case EE_CHAR_LANGUAGE_CTL:
+ {
+ pNew = new EditCharAttribLanguage( (const SvxLanguageItem&)rNew, nS, nE );
+ }
+ break;
+ case EE_CHAR_COLOR:
+ {
+ pNew = new EditCharAttribColor( (const SvxColorItem&)rNew, nS, nE );
+ }
+ break;
+ case EE_CHAR_FONTINFO:
+ case EE_CHAR_FONTINFO_CJK:
+ case EE_CHAR_FONTINFO_CTL:
+ {
+ pNew = new EditCharAttribFont( (const SvxFontItem&)rNew, nS, nE );
+ }
+ break;
+ case EE_CHAR_FONTHEIGHT:
+ case EE_CHAR_FONTHEIGHT_CJK:
+ case EE_CHAR_FONTHEIGHT_CTL:
+ {
+ pNew = new EditCharAttribFontHeight( (const SvxFontHeightItem&)rNew, nS, nE );
+ }
+ break;
+ case EE_CHAR_FONTWIDTH:
+ {
+ pNew = new EditCharAttribFontWidth( (const SvxCharScaleWidthItem&)rNew, nS, nE );
+ }
+ break;
+ case EE_CHAR_WEIGHT:
+ case EE_CHAR_WEIGHT_CJK:
+ case EE_CHAR_WEIGHT_CTL:
+ {
+ pNew = new EditCharAttribWeight( (const SvxWeightItem&)rNew, nS, nE );
+ }
+ break;
+ case EE_CHAR_UNDERLINE:
+ {
+ pNew = new EditCharAttribUnderline( (const SvxUnderlineItem&)rNew, nS, nE );
+ }
+ break;
+ case EE_CHAR_OVERLINE:
+ {
+ pNew = new EditCharAttribOverline( (const SvxOverlineItem&)rNew, nS, nE );
+ }
+ break;
+ case EE_CHAR_EMPHASISMARK:
+ {
+ pNew = new EditCharAttribEmphasisMark( (const SvxEmphasisMarkItem&)rNew, nS, nE );
+ }
+ break;
+ case EE_CHAR_RELIEF:
+ {
+ pNew = new EditCharAttribRelief( (const SvxCharReliefItem&)rNew, nS, nE );
+ }
+ break;
+ case EE_CHAR_STRIKEOUT:
+ {
+ pNew = new EditCharAttribStrikeout( (const SvxCrossedOutItem&)rNew, nS, nE );
+ }
+ break;
+ case EE_CHAR_ITALIC:
+ case EE_CHAR_ITALIC_CJK:
+ case EE_CHAR_ITALIC_CTL:
+ {
+ pNew = new EditCharAttribItalic( (const SvxPostureItem&)rNew, nS, nE );
+ }
+ break;
+ case EE_CHAR_OUTLINE:
+ {
+ pNew = new EditCharAttribOutline( (const SvxContourItem&)rNew, nS, nE );
+ }
+ break;
+ case EE_CHAR_SHADOW:
+ {
+ pNew = new EditCharAttribShadow( (const SvxShadowedItem&)rNew, nS, nE );
+ }
+ break;
+ case EE_CHAR_ESCAPEMENT:
+ {
+ pNew = new EditCharAttribEscapement( (const SvxEscapementItem&)rNew, nS, nE );
+ }
+ break;
+ case EE_CHAR_PAIRKERNING:
+ {
+ pNew = new EditCharAttribPairKerning( (const SvxAutoKernItem&)rNew, nS, nE );
+ }
+ break;
+ case EE_CHAR_KERNING:
+ {
+ pNew = new EditCharAttribKerning( (const SvxKerningItem&)rNew, nS, nE );
+ }
+ break;
+ case EE_CHAR_WLM:
+ {
+ pNew = new EditCharAttribWordLineMode( (const SvxWordLineModeItem&)rNew, nS, nE );
+ }
+ break;
+ case EE_CHAR_XMLATTRIBS:
+ {
+ pNew = new EditCharAttrib( rNew, nS, nE ); // Attrib is only for holding XML information...
+ }
+ break;
+ case EE_FEATURE_TAB:
+ {
+ pNew = new EditCharAttribTab( (const SfxVoidItem&)rNew, nS );
+ }
+ break;
+ case EE_FEATURE_LINEBR:
+ {
+ pNew = new EditCharAttribLineBreak( (const SfxVoidItem&)rNew, nS );
+ }
+ break;
+ case EE_FEATURE_FIELD:
+ {
+ pNew = new EditCharAttribField( (const SvxFieldItem&)rNew, nS );
+ }
+ break;
+ default:
+ {
+ DBG_ERROR( "Ungueltiges Attribut!" );
+ }
+ }
+ return pNew;
+}
+
+// -------------------------------------------------------------------------
+// class EditLine
+// -------------------------------------------------------------------------
+
+EditLine::EditLine()
+{
+ DBG_CTOR( EE_EditLine, 0 );
+
+ nStart = nEnd = 0;
+ nStartPortion = 0; // damit in ungueltiger Zeile ohne Portions von einer gueltigen Zeile mit der Portion Nr0 unterscieden werden kann.
+ nEndPortion = 0;
+ nHeight = 0;
+ nStartPosX = 0;
+ nTxtHeight = 0;
+ nTxtWidth = 0;
+ nCrsrHeight = 0;
+ nMaxAscent = 0;
+ bHangingPunctuation = FALSE;
+ bInvalid = TRUE;
+}
+
+EditLine::EditLine( const EditLine& r )
+{
+ DBG_CTOR( EE_EditLine, 0 );
+
+ nEnd = r.nEnd;
+ nStart = r.nStart;
+ nStartPortion = r.nStartPortion;
+ nEndPortion = r.nEndPortion;
+ bHangingPunctuation = r.bHangingPunctuation;
+
+ nHeight = 0;
+ nStartPosX = 0;
+ nTxtHeight = 0;
+ nTxtWidth = 0;
+ nCrsrHeight = 0;
+ nMaxAscent = 0;
+ bInvalid = TRUE;
+}
+
+EditLine::~EditLine()
+{
+ DBG_DTOR( EE_EditLine, 0 );
+}
+
+EditLine* EditLine::Clone() const
+{
+ EditLine* pL = new EditLine;
+ if ( aPositions.Count() )
+ {
+ pL->aPositions.Insert (aPositions.GetData(), aPositions.Count(), 0);
+ }
+ pL->nStartPosX = nStartPosX;
+ pL->nStart = nStart;
+ pL->nEnd = nEnd;
+ pL->nStartPortion = nStartPortion;
+ pL->nEndPortion = nEndPortion;
+ pL->nHeight = nHeight;
+ pL->nTxtWidth = nTxtWidth;
+ pL->nTxtHeight = nTxtHeight;
+ pL->nCrsrHeight = nCrsrHeight;
+ pL->nMaxAscent = nMaxAscent;
+
+ return pL;
+}
+
+BOOL operator == ( const EditLine& r1, const EditLine& r2 )
+{
+ if ( r1.nStart != r2.nStart )
+ return FALSE;
+
+ if ( r1.nEnd != r2.nEnd )
+ return FALSE;
+
+ if ( r1.nStartPortion != r2.nStartPortion )
+ return FALSE;
+
+ if ( r1.nEndPortion != r2.nEndPortion )
+ return FALSE;
+
+ return TRUE;
+}
+
+EditLine& EditLine::operator = ( const EditLine& r )
+{
+ nEnd = r.nEnd;
+ nStart = r.nStart;
+ nEndPortion = r.nEndPortion;
+ nStartPortion = r.nStartPortion;
+ return *this;
+}
+
+
+BOOL operator != ( const EditLine& r1, const EditLine& r2 )
+{
+ return !( r1 == r2 );
+}
+
+Size EditLine::CalcTextSize( ParaPortion& rParaPortion )
+{
+ Size aSz;
+ Size aTmpSz;
+ TextPortion* pPortion;
+
+ USHORT nIndex = GetStart();
+
+ DBG_ASSERT( rParaPortion.GetTextPortions().Count(), "GetTextSize vor CreatePortions !" );
+
+ for ( USHORT n = nStartPortion; n <= nEndPortion; n++ )
+ {
+ pPortion = rParaPortion.GetTextPortions().GetObject(n);
+ switch ( pPortion->GetKind() )
+ {
+ case PORTIONKIND_TEXT:
+ case PORTIONKIND_FIELD:
+ case PORTIONKIND_HYPHENATOR:
+ {
+ aTmpSz = pPortion->GetSize();
+ aSz.Width() += aTmpSz.Width();
+ if ( aSz.Height() < aTmpSz.Height() )
+ aSz.Height() = aTmpSz.Height();
+ }
+ break;
+ case PORTIONKIND_TAB:
+// case PORTIONKIND_EXTRASPACE:
+ {
+ aSz.Width() += pPortion->GetSize().Width();
+ }
+ break;
+ }
+ nIndex = nIndex + pPortion->GetLen();
+ }
+
+ SetHeight( (USHORT)aSz.Height() );
+ return aSz;
+}
+
+ // -------------------------------------------------------------------------
+// class EditLineList
+// -------------------------------------------------------------------------
+EditLineList::EditLineList()
+{
+}
+
+EditLineList::~EditLineList()
+{
+ Reset();
+}
+
+void EditLineList::Reset()
+{
+ for ( USHORT nLine = 0; nLine < Count(); nLine++ )
+ delete GetObject(nLine);
+ Remove( 0, Count() );
+}
+
+void EditLineList::DeleteFromLine( USHORT nDelFrom )
+{
+ DBG_ASSERT( nDelFrom <= (Count() - 1), "DeleteFromLine: Out of range" );
+ for ( USHORT nL = nDelFrom; nL < Count(); nL++ )
+ delete GetObject(nL);
+ Remove( nDelFrom, Count()-nDelFrom );
+}
+
+USHORT EditLineList::FindLine( USHORT nChar, BOOL bInclEnd )
+{
+ for ( USHORT nLine = 0; nLine < Count(); nLine++ )
+ {
+ EditLine* pLine = GetObject( nLine );
+ if ( ( bInclEnd && ( pLine->GetEnd() >= nChar ) ) ||
+ ( pLine->GetEnd() > nChar ) )
+ {
+ return nLine;
+ }
+ }
+
+ DBG_ASSERT( !bInclEnd, "Zeile nicht gefunden: FindLine" );
+ return ( Count() - 1 );
+}
+
+ // -------------------------------------------------------------------------
+// class EditSelection
+// -------------------------------------------------------------------------
+BOOL EditPaM::DbgIsBuggy( EditDoc& rDoc )
+{
+ if ( !pNode )
+ return TRUE;
+ if ( rDoc.GetPos( pNode ) >= rDoc.Count() )
+ return TRUE;
+ if ( nIndex > pNode->Len() )
+ return TRUE;
+
+ return FALSE;
+}
+
+BOOL EditSelection::DbgIsBuggy( EditDoc& rDoc )
+{
+ if ( aStartPaM.DbgIsBuggy( rDoc ) )
+ return TRUE;
+ if ( aEndPaM.DbgIsBuggy( rDoc ) )
+ return TRUE;
+
+ return FALSE;
+}
+
+EditSelection::EditSelection()
+{
+}
+
+EditSelection::EditSelection( const EditPaM& rStartAndAnd )
+{
+ // koennte noch optimiert werden!
+ // nicht erst Def-CTOR vom PaM rufen!
+ aStartPaM = rStartAndAnd;
+ aEndPaM = rStartAndAnd;
+}
+
+EditSelection::EditSelection( const EditPaM& rStart, const EditPaM& rEnd )
+{
+ // koennte noch optimiert werden!
+ aStartPaM = rStart;
+ aEndPaM = rEnd;
+}
+
+EditSelection& EditSelection::operator = ( const EditPaM& rPaM )
+{
+ aStartPaM = rPaM;
+ aEndPaM = rPaM;
+ return *this;
+}
+
+BOOL EditSelection::IsInvalid() const
+{
+ EditPaM aEmptyPaM;
+
+ if ( aStartPaM == aEmptyPaM )
+ return TRUE;
+
+ if ( aEndPaM == aEmptyPaM )
+ return TRUE;
+
+ return FALSE;
+}
+
+BOOL EditSelection::Adjust( const ContentList& rNodes )
+{
+ DBG_ASSERT( aStartPaM.GetIndex() <= aStartPaM.GetNode()->Len(), "Index im Wald in Adjust(1)" );
+ DBG_ASSERT( aEndPaM.GetIndex() <= aEndPaM.GetNode()->Len(), "Index im Wald in Adjust(2)" );
+
+ ContentNode* pStartNode = aStartPaM.GetNode();
+ ContentNode* pEndNode = aEndPaM.GetNode();
+
+ USHORT nStartNode = rNodes.GetPos( pStartNode );
+ USHORT nEndNode = rNodes.GetPos( pEndNode );
+
+ DBG_ASSERT( nStartNode != USHRT_MAX, "Node im Wald in Adjust(1)" );
+ DBG_ASSERT( nEndNode != USHRT_MAX, "Node im Wald in Adjust(2)" );
+
+ BOOL bSwap = FALSE;
+ if ( nStartNode > nEndNode )
+ bSwap = TRUE;
+ else if ( ( nStartNode == nEndNode ) && ( aStartPaM.GetIndex() > aEndPaM.GetIndex() ) )
+ bSwap = TRUE;
+
+ if ( bSwap )
+ {
+ EditPaM aTmpPaM( aStartPaM );
+ aStartPaM = aEndPaM;
+ aEndPaM = aTmpPaM;
+ }
+
+ return bSwap;
+}
+
+
+ // -------------------------------------------------------------------------
+// class EditPaM
+// -------------------------------------------------------------------------
+BOOL operator == ( const EditPaM& r1, const EditPaM& r2 )
+{
+ if ( r1.GetNode() != r2.GetNode() )
+ return FALSE;
+
+ if ( r1.GetIndex() != r2.GetIndex() )
+ return FALSE;
+
+ return TRUE;
+}
+
+EditPaM& EditPaM::operator = ( const EditPaM& rPaM )
+{
+ nIndex = rPaM.nIndex;
+ pNode = rPaM.pNode;
+ return *this;
+}
+
+BOOL operator != ( const EditPaM& r1, const EditPaM& r2 )
+{
+ return !( r1 == r2 );
+}
+
+
+ // -------------------------------------------------------------------------
+// class ContentNode
+// -------------------------------------------------------------------------
+ContentNode::ContentNode( SfxItemPool& rPool ) : aContentAttribs( rPool )
+{
+ DBG_CTOR( EE_ContentNode, 0 );
+ pWrongList = NULL;
+}
+
+ContentNode::ContentNode( const XubString& rStr, const ContentAttribs& rContentAttribs ) :
+ XubString( rStr ), aContentAttribs( rContentAttribs )
+{
+ DBG_CTOR( EE_ContentNode, 0 );
+ pWrongList = NULL;
+}
+
+ContentNode::~ContentNode()
+{
+ DBG_DTOR( EE_ContentNode, 0 );
+#ifndef SVX_LIGHT
+ delete pWrongList;
+#endif
+}
+
+void ContentNode::ExpandAttribs( USHORT nIndex, USHORT nNew, SfxItemPool& rItemPool )
+{
+ if ( !nNew )
+ return;
+
+ // Da Features anders behandelt werden als normale Zeichenattribute,
+ // kann sich hier auch die Sortierung der Start-Liste aendern!
+ // In jedem if..., in dem weiter (n) Moeglichkeiten aufgrund von
+ // bFeature oder Spezialfall existieren,
+ // muessen (n-1) Moeglichkeiten mit bResort versehen werden.
+ // Die wahrscheinlichste Moeglichkeit erhaelt kein bResort,
+ // so dass nicht neu sortiert wird, wenn sich alle Attribute
+ // gleich verhalten.
+ BOOL bResort = FALSE;
+ BOOL bExpandedEmptyAtIndexNull = FALSE;
+
+ USHORT nAttr = 0;
+ EditCharAttrib* pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr );
+ while ( pAttrib )
+ {
+ if ( pAttrib->GetEnd() >= nIndex )
+ {
+ // Alle Attribute hinter der Einfuegeposition verschieben...
+ if ( pAttrib->GetStart() > nIndex )
+ {
+ pAttrib->MoveForward( nNew );
+ }
+ // 0: Leeres Attribut expandieren, wenn an Einfuegestelle
+ else if ( pAttrib->IsEmpty() )
+ {
+ // Index nicht pruefen, leeres durfte nur dort liegen.
+ // Wenn spaeter doch Ueberpruefung:
+ // Spezialfall: Start == 0; AbsLen == 1, nNew = 1 => Expand, weil durch Absatzumbruch!
+ // Start <= nIndex, End >= nIndex => Start=End=nIndex!
+// if ( pAttrib->GetStart() == nIndex )
+ pAttrib->Expand( nNew );
+ if ( pAttrib->GetStart() == 0 )
+ bExpandedEmptyAtIndexNull = TRUE;
+ }
+ // 1: Attribut startet davor, geht bis Index...
+ else if ( pAttrib->GetEnd() == nIndex ) // Start muss davor liegen
+ {
+ // Nur expandieren, wenn kein Feature,
+ // und wenn nicht in ExcludeListe!
+ // Sonst geht z.B. ein UL bis zum neuen ULDB, beide expandieren
+// if ( !pAttrib->IsFeature() && !rExclList.FindAttrib( pAttrib->Which() ) )
+ if ( !pAttrib->IsFeature() && !aCharAttribList.FindEmptyAttrib( pAttrib->Which(), nIndex ) )
+ {
+ if ( !pAttrib->IsEdge() )
+ pAttrib->Expand( nNew );
+ }
+ else
+ bResort = TRUE;
+ }
+ // 2: Attribut startet davor, geht hinter Index...
+ else if ( ( pAttrib->GetStart() < nIndex ) && ( pAttrib->GetEnd() > nIndex ) )
+ {
+ DBG_ASSERT( !pAttrib->IsFeature(), "Grosses Feature?!" );
+ pAttrib->Expand( nNew );
+ }
+ // 3: Attribut startet auf Index...
+ else if ( pAttrib->GetStart() == nIndex )
+ {
+ if ( pAttrib->IsFeature() )
+ {
+ pAttrib->MoveForward( nNew );
+ bResort = TRUE;
+ }
+ else
+ {
+ BOOL bExpand = FALSE;
+ if ( nIndex == 0 )
+ {
+ bExpand = TRUE;
+ if( bExpandedEmptyAtIndexNull )
+ {
+ // Check if this kind of attribut was empty and expanded here...
+ USHORT nW = pAttrib->GetItem()->Which();
+ for ( USHORT nA = 0; nA < nAttr; nA++ )
+ {
+ EditCharAttrib* pA = aCharAttribList.GetAttribs()[nA];
+ if ( ( pA->GetStart() == 0 ) && ( pA->GetItem()->Which() == nW ) )
+ {
+ bExpand = FALSE;
+ break;
+ }
+ }
+
+ }
+ }
+ if ( bExpand )
+ {
+ pAttrib->Expand( nNew );
+ bResort = TRUE;
+ }
+ else
+ {
+ pAttrib->MoveForward( nNew );
+ }
+ }
+ }
+ }
+
+ if ( pAttrib->IsEdge() )
+ pAttrib->SetEdge( FALSE );
+
+ DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" );
+
+ DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Expand: Attribut verdreht!" );
+ DBG_ASSERT( ( pAttrib->GetEnd() <= Len() ), "Expand: Attrib groesser als Absatz!" );
+ if ( pAttrib->IsEmpty() )
+ {
+ DBG_ERROR( "Leeres Attribut nach ExpandAttribs?" );
+ bResort = TRUE;
+ aCharAttribList.GetAttribs().Remove( nAttr );
+ rItemPool.Remove( *pAttrib->GetItem() );
+ delete pAttrib;
+ nAttr--;
+ }
+ nAttr++;
+ pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr );
+ }
+
+ if ( bResort )
+ aCharAttribList.ResortAttribs();
+
+#ifndef SVX_LIGHT
+ if ( pWrongList )
+ {
+ BOOL bSep = ( GetChar( nIndex ) == ' ' ) || IsFeature( nIndex );
+ pWrongList->TextInserted( nIndex, nNew, bSep );
+ }
+#endif // !SVX_LIGHT
+
+#ifdef EDITDEBUG
+ DBG_ASSERT( CheckOrderedList( aCharAttribList.GetAttribs(), TRUE ), "Expand: Start-Liste verdreht" );
+#endif
+}
+
+void ContentNode::CollapsAttribs( USHORT nIndex, USHORT nDeleted, SfxItemPool& rItemPool )
+{
+ if ( !nDeleted )
+ return;
+
+ // Da Features anders behandelt werden als normale Zeichenattribute,
+ // kann sich hier auch die Sortierung der Start-Liste aendern!
+ BOOL bResort = FALSE;
+ BOOL bDelAttr = FALSE;
+ USHORT nEndChanges = nIndex+nDeleted;
+
+ USHORT nAttr = 0;
+ EditCharAttrib* pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr );
+ while ( pAttrib )
+ {
+ bDelAttr = FALSE;
+ if ( pAttrib->GetEnd() >= nIndex )
+ {
+ // Alles Attribute hinter der Einfuegeposition verschieben...
+ if ( pAttrib->GetStart() >= nEndChanges )
+ {
+ pAttrib->MoveBackward( nDeleted );
+ }
+ // 1. Innenliegende Attribute loeschen...
+ else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() <= nEndChanges ) )
+ {
+ // Spezialfall: Attrubt deckt genau den Bereich ab
+ // => als leeres Attribut behalten.
+ if ( !pAttrib->IsFeature() && ( pAttrib->GetStart() == nIndex ) && ( pAttrib->GetEnd() == nEndChanges ) )
+ pAttrib->GetEnd() = nIndex; // leer
+ else
+ bDelAttr = TRUE;
+ }
+ // 2. Attribut beginnt davor, endet drinnen oder dahinter...
+ else if ( ( pAttrib->GetStart() <= nIndex ) && ( pAttrib->GetEnd() > nIndex ) )
+ {
+ DBG_ASSERT( !pAttrib->IsFeature(), "Collapsing Feature!" );
+ if ( pAttrib->GetEnd() <= nEndChanges ) // endet drinnen
+ pAttrib->GetEnd() = nIndex;
+ else
+ pAttrib->Collaps( nDeleted ); // endet dahinter
+ }
+ // 3. Attribut beginnt drinnen, endet dahinter...
+ else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() > nEndChanges ) )
+ {
+ // Features duerfen nicht expandieren!
+ if ( pAttrib->IsFeature() )
+ {
+ pAttrib->MoveBackward( nDeleted );
+ bResort = TRUE;
+ }
+ else
+ {
+ pAttrib->GetStart() = nEndChanges;
+ pAttrib->MoveBackward( nDeleted );
+ }
+ }
+ }
+ DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" );
+
+ DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Collaps: Attribut verdreht!" );
+ DBG_ASSERT( ( pAttrib->GetEnd() <= Len()) || bDelAttr, "Collaps: Attrib groesser als Absatz!" );
+ if ( bDelAttr /* || pAttrib->IsEmpty() */ )
+ {
+ bResort = TRUE;
+ aCharAttribList.GetAttribs().Remove( nAttr );
+ rItemPool.Remove( *pAttrib->GetItem() );
+ delete pAttrib;
+ nAttr--;
+ }
+ else if ( pAttrib->IsEmpty() )
+ aCharAttribList.HasEmptyAttribs() = TRUE;
+
+ nAttr++;
+ pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr );
+ }
+
+ if ( bResort )
+ aCharAttribList.ResortAttribs();
+
+#ifndef SVX_LIGHT
+ if ( pWrongList )
+ pWrongList->TextDeleted( nIndex, nDeleted );
+#endif // !SVX_LIGHT
+
+#ifdef EDITDEBUG
+ DBG_ASSERT( CheckOrderedList( aCharAttribList.GetAttribs(), TRUE ), "Collaps: Start-Liste verdreht" );
+#endif
+}
+
+void ContentNode::CopyAndCutAttribs( ContentNode* pPrevNode, SfxItemPool& rPool, BOOL bKeepEndingAttribs )
+{
+ DBG_ASSERT( pPrevNode, "kopieren von Attributen auf einen NULL-Pointer ?" );
+
+ xub_StrLen nCut = pPrevNode->Len();
+
+ USHORT nAttr = 0;
+ EditCharAttrib* pAttrib = GetAttrib( pPrevNode->GetCharAttribs().GetAttribs(), nAttr );
+ while ( pAttrib )
+ {
+ if ( pAttrib->GetEnd() < nCut )
+ {
+ // bleiben unveraendert....
+ ;
+ }
+ else if ( pAttrib->GetEnd() == nCut )
+ {
+ // muessen als leeres Attribut kopiert werden.
+ if ( bKeepEndingAttribs && !pAttrib->IsFeature() && !aCharAttribList.FindAttrib( pAttrib->GetItem()->Which(), 0 ) )
+ {
+ EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, 0 );
+ DBG_ASSERT( pNewAttrib, "MakeCharAttrib fehlgeschlagen!" );
+ aCharAttribList.InsertAttrib( pNewAttrib );
+ }
+ }
+ else if ( pAttrib->IsInside( nCut ) || ( !nCut && !pAttrib->GetStart() && !pAttrib->IsFeature() ) )
+ {
+ // Wenn ganz vorne gecuttet wird, muss das Attribut erhalten bleiben!
+ // muessen kopiert und geaendert werden
+ EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, pAttrib->GetEnd()-nCut );
+ DBG_ASSERT( pNewAttrib, "MakeCharAttrib fehlgeschlagen!" );
+ aCharAttribList.InsertAttrib( pNewAttrib );
+ // stutzen:
+ pAttrib->GetEnd() = nCut;
+ }
+ else
+ {
+ // alle dahinter verschieben in den neuen Node (this)
+// pPrevNode->GetCharAttribs().RemoveAttrib( pAttrib );
+ pPrevNode->GetCharAttribs().GetAttribs().Remove( nAttr );
+ aCharAttribList.InsertAttrib( pAttrib );
+ DBG_ASSERT( pAttrib->GetStart() >= nCut, "Start < nCut!" );
+ DBG_ASSERT( pAttrib->GetEnd() >= nCut, "End < nCut!" );
+ pAttrib->GetStart() = pAttrib->GetStart() - nCut;
+ pAttrib->GetEnd() = pAttrib->GetEnd() - nCut;
+ nAttr--;
+ }
+ nAttr++;
+ pAttrib = GetAttrib( pPrevNode->GetCharAttribs().GetAttribs(), nAttr );
+ }
+}
+
+void ContentNode::AppendAttribs( ContentNode* pNextNode )
+{
+ DBG_ASSERT( pNextNode, "kopieren von Attributen von einen NULL-Pointer ?" );
+
+ USHORT nNewStart = Len();
+
+#ifdef EDITDEBUG
+ DBG_ASSERT( aCharAttribList.DbgCheckAttribs(), "Attribute VOR AppendAttribs kaputt" );
+#endif
+
+ USHORT nAttr = 0;
+ EditCharAttrib* pAttrib = GetAttrib( pNextNode->GetCharAttribs().GetAttribs(), nAttr );
+ while ( pAttrib )
+ {
+ // alle Attribute verschieben in den aktuellen Node (this)
+ BOOL bMelted = FALSE;
+ if ( ( pAttrib->GetStart() == 0 ) && ( !pAttrib->IsFeature() ) )
+ {
+ // Evtl koennen Attribute zusammengefasst werden:
+ USHORT nTmpAttr = 0;
+ EditCharAttrib* pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr );
+ while ( !bMelted && pTmpAttrib )
+ {
+ if ( pTmpAttrib->GetEnd() == nNewStart )
+ {
+ if ( ( pTmpAttrib->Which() == pAttrib->Which() ) &&
+ ( *(pTmpAttrib->GetItem()) == *(pAttrib->GetItem() ) ) )
+ {
+ pTmpAttrib->GetEnd() =
+ pTmpAttrib->GetEnd() + pAttrib->GetLen();
+ pNextNode->GetCharAttribs().GetAttribs().Remove( nAttr );
+ // Vom Pool abmelden ?!
+ delete pAttrib;
+ bMelted = TRUE;
+ }
+ }
+ ++nTmpAttr;
+ pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr );
+ }
+ }
+
+ if ( !bMelted )
+ {
+ pAttrib->GetStart() = pAttrib->GetStart() + nNewStart;
+ pAttrib->GetEnd() = pAttrib->GetEnd() + nNewStart;
+ aCharAttribList.InsertAttrib( pAttrib );
+ ++nAttr;
+ }
+ pAttrib = GetAttrib( pNextNode->GetCharAttribs().GetAttribs(), nAttr );
+ }
+ // Fuer die Attribute, die nur ruebergewandert sind:
+ pNextNode->GetCharAttribs().Clear();
+
+#ifdef EDITDEBUG
+ DBG_ASSERT( aCharAttribList.DbgCheckAttribs(), "Attribute NACH AppendAttribs kaputt" );
+#endif
+}
+
+void ContentNode::CreateDefFont()
+{
+ // Erst alle Informationen aus dem Style verwenden...
+ SfxStyleSheet* pS = aContentAttribs.GetStyleSheet();
+ if ( pS )
+ CreateFont( GetCharAttribs().GetDefFont(), pS->GetItemSet() );
+
+ // ... dann die harte Absatzformatierung rueberbuegeln...
+ CreateFont( GetCharAttribs().GetDefFont(),
+ GetContentAttribs().GetItems(), pS == NULL );
+}
+
+void ContentNode::SetStyleSheet( SfxStyleSheet* pS, const SvxFont& rFontFromStyle )
+{
+ aContentAttribs.SetStyleSheet( pS );
+
+ // Erst alle Informationen aus dem Style verwenden...
+ GetCharAttribs().GetDefFont() = rFontFromStyle;
+ // ... dann die harte Absatzformatierung rueberbuegeln...
+ CreateFont( GetCharAttribs().GetDefFont(),
+ GetContentAttribs().GetItems(), pS == NULL );
+}
+
+void ContentNode::SetStyleSheet( SfxStyleSheet* pS, BOOL bRecalcFont )
+{
+ aContentAttribs.SetStyleSheet( pS );
+ if ( bRecalcFont )
+ CreateDefFont();
+}
+
+void ContentNode::DestroyWrongList()
+{
+#ifndef SVX_LIGHT
+ delete pWrongList;
+#endif
+ pWrongList = NULL;
+}
+
+void ContentNode::CreateWrongList()
+{
+ DBG_ASSERT( !pWrongList, "WrongList existiert schon!" );
+#ifndef SVX_LIGHT
+ pWrongList = new WrongList;
+#endif
+}
+
+void ContentNode::SetWrongList( WrongList* p )
+{
+ DBG_ASSERT( !pWrongList, "WrongList existiert schon!" );
+ pWrongList = p;
+}
+
+ // -------------------------------------------------------------------------
+// class ContentAttribs
+// -------------------------------------------------------------------------
+ContentAttribs::ContentAttribs( SfxItemPool& rPool ) :
+ aAttribSet( rPool, EE_PARA_START, EE_CHAR_END )
+{
+ pStyle = 0;
+}
+
+ContentAttribs::ContentAttribs( const ContentAttribs& rRef ) :
+ aAttribSet( rRef.aAttribSet )
+{
+ pStyle = rRef.pStyle;
+}
+
+ContentAttribs::~ContentAttribs()
+{
+}
+
+SvxTabStop ContentAttribs::FindTabStop( long nCurPos, USHORT nDefTab )
+{
+ const SvxTabStopItem& rTabs = (const SvxTabStopItem&) GetItem( EE_PARA_TABS );
+ for ( USHORT i = 0; i < rTabs.Count(); i++ )
+ {
+ const SvxTabStop& rTab = rTabs[i];
+ if ( rTab.GetTabPos() > nCurPos )
+ return rTab;
+ }
+
+ // DefTab ermitteln...
+ SvxTabStop aTabStop;
+ long x = nCurPos / nDefTab + 1;
+ aTabStop.GetTabPos() = nDefTab * x;
+ return aTabStop;
+}
+
+void ContentAttribs::SetStyleSheet( SfxStyleSheet* pS )
+{
+ BOOL bStyleChanged = ( pStyle != pS );
+ pStyle = pS;
+ // #104799# Only when other style sheet, not when current style sheet modified
+ if ( pStyle && bStyleChanged )
+ {
+ // Gezielt die Attribute aus der Absatzformatierung entfernen, die im Style
+ // spezifiziert sind, damit die Attribute des Styles wirken koennen.
+ const SfxItemSet& rStyleAttribs = pStyle->GetItemSet();
+ for ( USHORT nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ )
+ {
+ // #99635# Don't change bullet on/off
+ if ( ( nWhich != EE_PARA_BULLETSTATE ) && ( rStyleAttribs.GetItemState( nWhich ) == SFX_ITEM_ON ) )
+ aAttribSet.ClearItem( nWhich );
+ }
+ }
+}
+
+const SfxPoolItem& ContentAttribs::GetItem( USHORT nWhich )
+{
+ // Harte Absatzattribute haben Vorrang!
+ SfxItemSet* pTakeFrom = &aAttribSet;
+ if ( pStyle && ( aAttribSet.GetItemState( nWhich, FALSE ) != SFX_ITEM_ON ) )
+ pTakeFrom = &pStyle->GetItemSet();
+
+ return pTakeFrom->Get( nWhich );
+}
+
+BOOL ContentAttribs::HasItem( USHORT nWhich )
+{
+ BOOL bHasItem = FALSE;
+ if ( aAttribSet.GetItemState( nWhich, FALSE ) == SFX_ITEM_ON )
+ bHasItem = TRUE;
+ else if ( pStyle && pStyle->GetItemSet().GetItemState( nWhich ) == SFX_ITEM_ON )
+ bHasItem = TRUE;
+
+ return bHasItem;
+}
+
+
+
+ // ----------------------------------------------------------------------
+// class ItemList
+// ----------------------------------------------------------------------
+const SfxPoolItem* ItemList::FindAttrib( USHORT nWhich )
+{
+ const SfxPoolItem* pItem = First();
+ while ( pItem && ( pItem->Which() != nWhich ) )
+ pItem = Next();
+
+ return pItem;
+}
+
+ // -------------------------------------------------------------------------
+// class EditDoc
+// -------------------------------------------------------------------------
+EditDoc::EditDoc( SfxItemPool* pPool )
+{
+ if ( pPool )
+ {
+ pItemPool = pPool;
+ bOwnerOfPool = FALSE;
+ }
+ else
+ {
+ pItemPool = new EditEngineItemPool( FALSE );
+ bOwnerOfPool = TRUE;
+ }
+
+ nDefTab = DEFTAB;
+ bIsVertical = FALSE;
+ bIsFixedCellHeight = FALSE;
+
+ // Don't create a empty node, Clear() will be called in EditEngine-CTOR
+
+ SetModified( FALSE );
+};
+
+EditDoc::~EditDoc()
+{
+ ImplDestroyContents();
+ if ( bOwnerOfPool )
+ SfxItemPool::Free(pItemPool);
+}
+
+void EditDoc::ImplDestroyContents()
+{
+ for ( USHORT nNode = Count(); nNode; )
+ RemoveItemsFromPool( GetObject( --nNode ) );
+ DeleteAndDestroy( 0, Count() );
+}
+
+void EditDoc::RemoveItemsFromPool( ContentNode* pNode )
+{
+ for ( USHORT nAttr = 0; nAttr < pNode->GetCharAttribs().Count(); nAttr++ )
+ {
+ EditCharAttrib* pAttr = pNode->GetCharAttribs().GetAttribs()[nAttr];
+ GetItemPool().Remove( *pAttr->GetItem() );
+ }
+}
+
+void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, short nScriptType )
+{
+ Font aPrevFont( rFont );
+ rFont.SetAlign( ALIGN_BASELINE );
+ rFont.SetTransparent( TRUE );
+
+ USHORT nWhich_FontInfo = GetScriptItemId( EE_CHAR_FONTINFO, nScriptType );
+ USHORT nWhich_Language = GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType );
+ USHORT nWhich_FontHeight = GetScriptItemId( EE_CHAR_FONTHEIGHT, nScriptType );
+ USHORT nWhich_Weight = GetScriptItemId( EE_CHAR_WEIGHT, nScriptType );
+ USHORT nWhich_Italic = GetScriptItemId( EE_CHAR_ITALIC, nScriptType );
+
+ if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontInfo ) == SFX_ITEM_ON ) )
+ {
+ const SvxFontItem& rFontItem = (const SvxFontItem&)rSet.Get( nWhich_FontInfo );
+ rFont.SetName( rFontItem.GetFamilyName() );
+ rFont.SetFamily( rFontItem.GetFamily() );
+ rFont.SetPitch( rFontItem.GetPitch() );
+ rFont.SetCharSet( rFontItem.GetCharSet() );
+ }
+ if ( bSearchInParent || ( rSet.GetItemState( nWhich_Language ) == SFX_ITEM_ON ) )
+ rFont.SetLanguage( ((const SvxLanguageItem&)rSet.Get( nWhich_Language )).GetLanguage() );
+ if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_COLOR ) == SFX_ITEM_ON ) )
+ rFont.SetColor( ((const SvxColorItem&)rSet.Get( EE_CHAR_COLOR )).GetValue() );
+ if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontHeight ) == SFX_ITEM_ON ) )
+ rFont.SetSize( Size( rFont.GetSize().Width(), ((const SvxFontHeightItem&)rSet.Get( nWhich_FontHeight ) ).GetHeight() ) );
+ if ( bSearchInParent || ( rSet.GetItemState( nWhich_Weight ) == SFX_ITEM_ON ) )
+ rFont.SetWeight( ((const SvxWeightItem&)rSet.Get( nWhich_Weight )).GetWeight() );
+ if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_UNDERLINE ) == SFX_ITEM_ON ) )
+ rFont.SetUnderline( ((const SvxUnderlineItem&)rSet.Get( EE_CHAR_UNDERLINE )).GetLineStyle() );
+ if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_OVERLINE ) == SFX_ITEM_ON ) )
+ rFont.SetOverline( ((const SvxOverlineItem&)rSet.Get( EE_CHAR_OVERLINE )).GetLineStyle() );
+ if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_STRIKEOUT ) == SFX_ITEM_ON ) )
+ rFont.SetStrikeout( ((const SvxCrossedOutItem&)rSet.Get( EE_CHAR_STRIKEOUT )).GetStrikeout() );
+ if ( bSearchInParent || ( rSet.GetItemState( nWhich_Italic ) == SFX_ITEM_ON ) )
+ rFont.SetItalic( ((const SvxPostureItem&)rSet.Get( nWhich_Italic )).GetPosture() );
+ if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_OUTLINE ) == SFX_ITEM_ON ) )
+ rFont.SetOutline( ((const SvxContourItem&)rSet.Get( EE_CHAR_OUTLINE )).GetValue() );
+ if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_SHADOW ) == SFX_ITEM_ON ) )
+ rFont.SetShadow( ((const SvxShadowedItem&)rSet.Get( EE_CHAR_SHADOW )).GetValue() );
+ if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_ESCAPEMENT ) == SFX_ITEM_ON ) )
+ {
+ const SvxEscapementItem& rEsc = (const SvxEscapementItem&) rSet.Get( EE_CHAR_ESCAPEMENT );
+
+ USHORT nProp = rEsc.GetProp();
+ rFont.SetPropr( (BYTE)nProp );
+
+ short nEsc = rEsc.GetEsc();
+ if ( nEsc == DFLT_ESC_AUTO_SUPER )
+ nEsc = 100 - nProp;
+ else if ( nEsc == DFLT_ESC_AUTO_SUB )
+ nEsc = sal::static_int_cast< short >( -( 100 - nProp ) );
+ rFont.SetEscapement( nEsc );
+ }
+ if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_PAIRKERNING ) == SFX_ITEM_ON ) )
+ rFont.SetKerning( ((const SvxAutoKernItem&)rSet.Get( EE_CHAR_PAIRKERNING )).GetValue() );
+ if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_KERNING ) == SFX_ITEM_ON ) )
+ rFont.SetFixKerning( ((const SvxKerningItem&)rSet.Get( EE_CHAR_KERNING )).GetValue() );
+ if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_WLM ) == SFX_ITEM_ON ) )
+ rFont.SetWordLineMode( ((const SvxWordLineModeItem&)rSet.Get( EE_CHAR_WLM )).GetValue() );
+ if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_EMPHASISMARK ) == SFX_ITEM_ON ) )
+ rFont.SetEmphasisMark( ((const SvxEmphasisMarkItem&)rSet.Get( EE_CHAR_EMPHASISMARK )).GetValue() );
+ if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_RELIEF ) == SFX_ITEM_ON ) )
+ rFont.SetRelief( (FontRelief)((const SvxCharReliefItem&)rSet.Get( EE_CHAR_RELIEF )).GetValue() );
+
+ // Ob ich jetzt den ganzen Font vergleiche, oder vor jeder Aenderung
+ // pruefe, ob der Wert sich aendert, bleibt sich relativ gleich.
+ // So ggf ein MakeUniqFont im Font mehr, dafuer bei Aenderung schnellerer
+ // Abbruch der Abfrage, oder ich musste noch jedesmal ein bChanged pflegen.
+ if ( rFont == aPrevFont )
+ rFont = aPrevFont; // => Gleicher ImpPointer fuer IsSameInstance
+}
+
+void EditDoc::CreateDefFont( BOOL bUseStyles )
+{
+ SfxItemSet aTmpSet( GetItemPool(), EE_PARA_START, EE_CHAR_END );
+ CreateFont( aDefFont, aTmpSet );
+ aDefFont.SetVertical( IsVertical() );
+ aDefFont.SetOrientation( IsVertical() ? 2700 : 0 );
+
+ for ( USHORT nNode = 0; nNode < Count(); nNode++ )
+ {
+ ContentNode* pNode = GetObject( nNode );
+ pNode->GetCharAttribs().GetDefFont() = aDefFont;
+ if ( bUseStyles )
+ pNode->CreateDefFont();
+ }
+}
+
+static const sal_Unicode aCR[] = { 0x0d, 0x00 };
+static const sal_Unicode aLF[] = { 0x0a, 0x00 };
+static const sal_Unicode aCRLF[] = { 0x0d, 0x0a, 0x00 };
+
+XubString EditDoc::GetSepStr( LineEnd eEnd )
+{
+ XubString aSep;
+ if ( eEnd == LINEEND_CR )
+ aSep = aCR;
+ else if ( eEnd == LINEEND_LF )
+ aSep = aLF;
+ else
+ aSep = aCRLF;
+ return aSep;
+}
+
+XubString EditDoc::GetText( LineEnd eEnd ) const
+{
+ ULONG nLen = GetTextLen();
+ USHORT nNodes = Count();
+
+ String aSep = EditDoc::GetSepStr( eEnd );
+ USHORT nSepSize = aSep.Len();
+
+ if ( nSepSize )
+ nLen += nNodes * nSepSize;
+ if ( nLen > 0xFFFb / sizeof(xub_Unicode) )
+ {
+ DBG_ERROR( "Text zu gross fuer String" );
+ return XubString();
+ }
+ xub_Unicode* pStr = new xub_Unicode[nLen+1];
+ xub_Unicode* pCur = pStr;
+ USHORT nLastNode = nNodes-1;
+ for ( USHORT nNode = 0; nNode < nNodes; nNode++ )
+ {
+ XubString aTmp( GetParaAsString( GetObject(nNode) ) );
+ memcpy( pCur, aTmp.GetBuffer(), aTmp.Len()*sizeof(sal_Unicode) );
+ pCur += aTmp.Len();
+ if ( nSepSize && ( nNode != nLastNode ) )
+ {
+ memcpy( pCur, aSep.GetBuffer(), nSepSize*sizeof(sal_Unicode ) );
+ pCur += nSepSize;
+ }
+ }
+ *pCur = '\0';
+ XubString aASCIIText( pStr );
+ delete[] pStr;
+ return aASCIIText;
+}
+
+XubString EditDoc::GetParaAsString( USHORT nNode ) const
+{
+ return GetParaAsString( SaveGetObject( nNode ) );
+}
+
+XubString EditDoc::GetParaAsString( ContentNode* pNode, USHORT nStartPos, USHORT nEndPos, BOOL bResolveFields ) const
+{
+ if ( nEndPos > pNode->Len() )
+ nEndPos = pNode->Len();
+
+ DBG_ASSERT( nStartPos <= nEndPos, "Start und Ende vertauscht?" );
+
+ USHORT nIndex = nStartPos;
+ XubString aStr;
+ EditCharAttrib* pNextFeature = pNode->GetCharAttribs().FindFeature( nIndex );
+ while ( nIndex < nEndPos )
+ {
+ USHORT nEnd = nEndPos;
+ if ( pNextFeature && ( pNextFeature->GetStart() < nEnd ) )
+ nEnd = pNextFeature->GetStart();
+ else
+ pNextFeature = 0; // Feature interessiert unten nicht
+
+ DBG_ASSERT( nEnd >= nIndex, "Ende vorm Index?" );
+ //!! beware of sub string length of -1 which is also defined as STRING_LEN and
+ //!! thus would result in adding the whole sub string up to the end of the node !!
+ if (nEnd > nIndex)
+ aStr += XubString( *pNode, nIndex, nEnd - nIndex );
+
+ if ( pNextFeature )
+ {
+ switch ( pNextFeature->GetItem()->Which() )
+ {
+ case EE_FEATURE_TAB: aStr += '\t';
+ break;
+ case EE_FEATURE_LINEBR: aStr += '\x0A';
+ break;
+ case EE_FEATURE_FIELD: if ( bResolveFields )
+ aStr += ((EditCharAttribField*)pNextFeature)->GetFieldValue();
+ break;
+ default: DBG_ERROR( "Was fuer ein Feature ?" );
+ }
+ pNextFeature = pNode->GetCharAttribs().FindFeature( ++nEnd );
+ }
+ nIndex = nEnd;
+ }
+ return aStr;
+}
+
+ULONG EditDoc::GetTextLen() const
+{
+ ULONG nLen = 0;
+ for ( USHORT nNode = 0; nNode < Count(); nNode++ )
+ {
+ ContentNode* pNode = GetObject( nNode );
+ nLen += pNode->Len();
+ // Felder k”nnen laenger sein als der Platzhalter im Node.
+ const CharAttribArray& rAttrs = pNode->GetCharAttribs().GetAttribs();
+ for ( USHORT nAttr = rAttrs.Count(); nAttr; )
+ {
+ EditCharAttrib* pAttr = rAttrs[--nAttr];
+ if ( pAttr->Which() == EE_FEATURE_FIELD )
+ {
+ USHORT nFieldLen = ((EditCharAttribField*)pAttr)->GetFieldValue().Len();
+ if ( !nFieldLen )
+ nLen--;
+ else
+ nLen += nFieldLen-1;
+ }
+ }
+ }
+ return nLen;
+}
+
+EditPaM EditDoc::Clear()
+{
+ ImplDestroyContents();
+
+ ContentNode* pNode = new ContentNode( GetItemPool() );
+ Insert( pNode, 0 );
+
+ CreateDefFont( FALSE );
+
+ SetModified( FALSE );
+
+ EditPaM aPaM( pNode, 0 );
+ return aPaM;
+}
+
+void EditDoc::SetModified( BOOL b )
+{
+ bModified = b;
+ if ( bModified )
+ {
+ aModifyHdl.Call( NULL );
+ }
+}
+
+EditPaM EditDoc::RemoveText()
+{
+ // Das alte ItemSetmerken, damit z.B. im Chart Font behalten bleibt
+ ContentNode* pPrevFirstNode = GetObject(0);
+ SfxStyleSheet* pPrevStyle = pPrevFirstNode->GetStyleSheet();
+ SfxItemSet aPrevSet( pPrevFirstNode->GetContentAttribs().GetItems() );
+ Font aPrevFont( pPrevFirstNode->GetCharAttribs().GetDefFont() );
+
+ ImplDestroyContents();
+
+ ContentNode* pNode = new ContentNode( GetItemPool() );
+ Insert( pNode, 0 );
+
+ pNode->SetStyleSheet( pPrevStyle, FALSE );
+ pNode->GetContentAttribs().GetItems().Set( aPrevSet );
+ pNode->GetCharAttribs().GetDefFont() = aPrevFont;
+
+ SetModified( TRUE );
+
+ EditPaM aPaM( pNode, 0 );
+ return aPaM;
+}
+
+void EditDoc::InsertText( const EditPaM& rPaM, xub_Unicode c )
+{
+ DBG_ASSERT( c != 0x0A, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
+ DBG_ASSERT( c != 0x0D, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
+ DBG_ASSERT( c != '\t', "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
+
+ rPaM.GetNode()->Insert( c, rPaM.GetIndex() );
+ rPaM.GetNode()->ExpandAttribs( rPaM.GetIndex(), 1, GetItemPool() );
+
+ SetModified( TRUE );
+}
+
+EditPaM EditDoc::InsertText( EditPaM aPaM, const XubString& rStr )
+{
+ DBG_ASSERT( rStr.Search( 0x0A ) == STRING_NOTFOUND, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
+ DBG_ASSERT( rStr.Search( 0x0D ) == STRING_NOTFOUND, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
+ DBG_ASSERT( rStr.Search( '\t' ) == STRING_NOTFOUND, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
+ DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertText1" );
+
+ aPaM.GetNode()->Insert( rStr, aPaM.GetIndex() );
+ aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), rStr.Len(), GetItemPool() );
+ aPaM.GetIndex() = aPaM.GetIndex() + rStr.Len();
+
+ SetModified( TRUE );
+
+ return aPaM;
+}
+
+EditPaM EditDoc::InsertParaBreak( EditPaM aPaM, BOOL bKeepEndingAttribs )
+{
+ DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertParaBreak" );
+ ContentNode* pCurNode = aPaM.GetNode();
+ USHORT nPos = GetPos( pCurNode );
+ XubString aStr = aPaM.GetNode()->Copy( aPaM.GetIndex() );
+ aPaM.GetNode()->Erase( aPaM.GetIndex() );
+
+ // the paragraph attributes...
+ ContentAttribs aContentAttribs( aPaM.GetNode()->GetContentAttribs() );
+
+ // for a new paragraph we like to have the bullet/numbering visible by default
+ aContentAttribs.GetItems().Put( SfxBoolItem( EE_PARA_BULLETSTATE, TRUE), EE_PARA_BULLETSTATE );
+
+ // ContenNode-CTOR kopiert auch die Absatzattribute
+ ContentNode* pNode = new ContentNode( aStr, aContentAttribs );
+
+ // Den Default-Font kopieren
+ pNode->GetCharAttribs().GetDefFont() = aPaM.GetNode()->GetCharAttribs().GetDefFont();
+ SfxStyleSheet* pStyle = aPaM.GetNode()->GetStyleSheet();
+ if ( pStyle )
+ {
+ XubString aFollow( pStyle->GetFollow() );
+ if ( aFollow.Len() && ( aFollow != pStyle->GetName() ) )
+ {
+ SfxStyleSheetBase* pNext = pStyle->GetPool().Find( aFollow, pStyle->GetFamily() );
+ pNode->SetStyleSheet( (SfxStyleSheet*)pNext );
+ }
+ }
+
+ // Zeichenattribute muessen ggf. kopiert bzw gestutzt werden:
+ pNode->CopyAndCutAttribs( aPaM.GetNode(), GetItemPool(), bKeepEndingAttribs );
+
+ Insert( pNode, nPos+1 );
+
+ SetModified( TRUE );
+
+ aPaM.SetNode( pNode );
+ aPaM.SetIndex( 0 );
+ return aPaM;
+}
+
+EditPaM EditDoc::InsertFeature( EditPaM aPaM, const SfxPoolItem& rItem )
+{
+ DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertFeature" );
+
+ aPaM.GetNode()->Insert( CH_FEATURE, aPaM.GetIndex() );
+ aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), 1, GetItemPool() );
+
+ // Fuer das Feature ein Feature-Attribut anlegen...
+ EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rItem, aPaM.GetIndex(), aPaM.GetIndex()+1 );
+ DBG_ASSERT( pAttrib, "Warum kann ich kein Feature anlegen ?" );
+ aPaM.GetNode()->GetCharAttribs().InsertAttrib( pAttrib );
+
+ SetModified( TRUE );
+
+ aPaM.GetIndex()++;
+ return aPaM;
+}
+
+EditPaM EditDoc::ConnectParagraphs( ContentNode* pLeft, ContentNode* pRight )
+{
+ const EditPaM aPaM( pLeft, pLeft->Len() );
+
+ // Erst die Attribute, da sonst nLen nicht stimmt!
+ pLeft->AppendAttribs( pRight );
+ // Dann den Text...
+ *pLeft += *pRight;
+
+ // der rechte verschwindet.
+ RemoveItemsFromPool( pRight );
+ USHORT nRight = GetPos( pRight );
+ Remove( nRight );
+ delete pRight;
+
+ SetModified( TRUE );
+
+ return aPaM;
+}
+
+EditPaM EditDoc::RemoveChars( EditPaM aPaM, USHORT nChars )
+{
+ // Evtl. Features entfernen!
+ aPaM.GetNode()->Erase( aPaM.GetIndex(), nChars );
+ aPaM.GetNode()->CollapsAttribs( aPaM.GetIndex(), nChars, GetItemPool() );
+
+ SetModified( TRUE );
+
+ return aPaM;
+}
+
+void EditDoc::InsertAttribInSelection( ContentNode* pNode, USHORT nStart, USHORT nEnd, const SfxPoolItem& rPoolItem )
+{
+ DBG_ASSERT( pNode, "Wohin mit dem Attribut?" );
+ DBG_ASSERT( nEnd <= pNode->Len(), "InsertAttrib: Attribut zu gross!" );
+
+ // fuer Optimierung:
+ // dieses endet am Anfang der Selektion => kann erweitert werden
+ EditCharAttrib* pEndingAttrib = 0;
+ // dieses startet am Ende der Selektion => kann erweitert werden
+ EditCharAttrib* pStartingAttrib = 0;
+
+ DBG_ASSERT( nStart <= nEnd, "Kleiner Rechenfehler in InsertAttribInSelection" );
+
+ RemoveAttribs( pNode, nStart, nEnd, pStartingAttrib, pEndingAttrib, rPoolItem.Which() );
+
+ if ( pStartingAttrib && pEndingAttrib &&
+ ( *(pStartingAttrib->GetItem()) == rPoolItem ) &&
+ ( *(pEndingAttrib->GetItem()) == rPoolItem ) )
+ {
+ // wird ein groesses Attribut.
+ pEndingAttrib->GetEnd() = pStartingAttrib->GetEnd();
+ GetItemPool().Remove( *(pStartingAttrib->GetItem()) );
+ pNode->GetCharAttribs().GetAttribs().Remove( pNode->GetCharAttribs().GetAttribs().GetPos( pStartingAttrib ) );
+ delete pStartingAttrib;
+ }
+ else if ( pStartingAttrib && ( *(pStartingAttrib->GetItem()) == rPoolItem ) )
+ pStartingAttrib->GetStart() = nStart;
+ else if ( pEndingAttrib && ( *(pEndingAttrib->GetItem()) == rPoolItem ) )
+ pEndingAttrib->GetEnd() = nEnd;
+ else
+ InsertAttrib( rPoolItem, pNode, nStart, nEnd );
+
+ if ( pStartingAttrib )
+ pNode->GetCharAttribs().ResortAttribs();
+
+ SetModified( TRUE );
+}
+
+BOOL EditDoc::RemoveAttribs( ContentNode* pNode, USHORT nStart, USHORT nEnd, USHORT nWhich )
+{
+ EditCharAttrib* pStarting;
+ EditCharAttrib* pEnding;
+ return RemoveAttribs( pNode, nStart, nEnd, pStarting, pEnding, nWhich );
+}
+
+BOOL EditDoc::RemoveAttribs( ContentNode* pNode, USHORT nStart, USHORT nEnd, EditCharAttrib*& rpStarting, EditCharAttrib*& rpEnding, USHORT nWhich )
+{
+ DBG_ASSERT( pNode, "Wohin mit dem Attribut?" );
+ DBG_ASSERT( nEnd <= pNode->Len(), "InsertAttrib: Attribut zu gross!" );
+
+ // dieses endet am Anfang der Selektion => kann erweitert werden
+ rpEnding = 0;
+ // dieses startet am Ende der Selektion => kann erweitert werden
+ rpStarting = 0;
+
+ BOOL bChanged = FALSE;
+
+ DBG_ASSERT( nStart <= nEnd, "Kleiner Rechenfehler in InsertAttribInSelection" );
+
+ // ueber die Attribute iterieren...
+ USHORT nAttr = 0;
+ EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
+ while ( pAttr )
+ {
+ BOOL bRemoveAttrib = FALSE;
+ // MT 11.9.97:
+ // Ich denke dass in dieser Methode generell keine Features geloescht
+ // werden sollen.
+ // => Dann koennen die Feature-Abfragen weiter unten entfallen
+ USHORT nAttrWhich = pAttr->Which();
+ if ( ( nAttrWhich < EE_FEATURE_START ) && ( !nWhich || ( nAttrWhich == nWhich ) ) )
+ {
+ // Attribut beginnt in Selection
+ if ( ( pAttr->GetStart() >= nStart ) && ( pAttr->GetStart() <= nEnd ) )
+ {
+ bChanged = TRUE;
+ if ( pAttr->GetEnd() > nEnd )
+ {
+ pAttr->GetStart() = nEnd; // dann faengt es dahinter an
+ rpStarting = pAttr;
+ if ( nWhich )
+ break; // es kann kein weiteres Attrib hier liegen
+ }
+ else if ( !pAttr->IsFeature() || ( pAttr->GetStart() == nStart ) )
+ {
+ // Feature nur loeschen, wenn genau an der Stelle
+ bRemoveAttrib = TRUE;
+ }
+ }
+
+ // Attribut endet in Selection
+ else if ( ( pAttr->GetEnd() >= nStart ) && ( pAttr->GetEnd() <= nEnd ) )
+ {
+ bChanged = TRUE;
+ if ( ( pAttr->GetStart() < nStart ) && !pAttr->IsFeature() )
+ {
+ pAttr->GetEnd() = nStart; // dann hoert es hier auf
+ rpEnding = pAttr;
+ }
+ else if ( !pAttr->IsFeature() || ( pAttr->GetStart() == nStart ) )
+ {
+ // Feature nur loeschen, wenn genau an der Stelle
+ bRemoveAttrib = TRUE;
+ }
+ }
+ // Attribut ueberlappt die Selektion
+ else if ( ( pAttr->GetStart() <= nStart ) && ( pAttr->GetEnd() >= nEnd ) )
+ {
+ bChanged = TRUE;
+ if ( pAttr->GetStart() == nStart )
+ {
+ pAttr->GetStart() = nEnd;
+ rpStarting = pAttr;
+ if ( nWhich )
+ break; // es kann weitere Attribute geben!
+ }
+ else if ( pAttr->GetEnd() == nEnd )
+ {
+ pAttr->GetEnd() = nStart;
+ rpEnding = pAttr;
+ if ( nWhich )
+ break; // es kann weitere Attribute geben!
+ }
+ else // Attribut muss gesplittet werden...
+ {
+ USHORT nOldEnd = pAttr->GetEnd();
+ pAttr->GetEnd() = nStart;
+ rpEnding = pAttr;
+ InsertAttrib( *pAttr->GetItem(), pNode, nEnd, nOldEnd );
+ if ( nWhich )
+ break; // es kann weitere Attribute geben!
+ }
+ }
+ }
+ if ( bRemoveAttrib )
+ {
+ DBG_ASSERT( ( pAttr != rpStarting ) && ( pAttr != rpEnding ), "Loeschen und behalten des gleichen Attributs ?" );
+ DBG_ASSERT( !pAttr->IsFeature(), "RemoveAttribs: Remove a feature?!" );
+ pNode->GetCharAttribs().GetAttribs().Remove(nAttr);
+ GetItemPool().Remove( *pAttr->GetItem() );
+ delete pAttr;
+ nAttr--;
+ }
+ nAttr++;
+ pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
+ }
+
+ if ( bChanged )
+ {
+ // char attributes need to be sorted by start again
+ pNode->GetCharAttribs().ResortAttribs();
+
+ SetModified( TRUE );
+ }
+
+ return bChanged;
+}
+
+void EditDoc::InsertAttrib( const SfxPoolItem& rPoolItem, ContentNode* pNode, USHORT nStart, USHORT nEnd )
+{
+ // Diese Methode prueft nicht mehr, ob ein entspr. Attribut
+ // schon an der Stelle existiert!
+
+ EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rPoolItem, nStart, nEnd );
+ DBG_ASSERT( pAttrib, "MakeCharAttrib fehlgeschlagen!" );
+ pNode->GetCharAttribs().InsertAttrib( pAttrib );
+
+ SetModified( TRUE );
+}
+
+void EditDoc::InsertAttrib( ContentNode* pNode, USHORT nStart, USHORT nEnd, const SfxPoolItem& rPoolItem )
+{
+ if ( nStart != nEnd )
+ {
+ InsertAttribInSelection( pNode, nStart, nEnd, rPoolItem );
+ }
+ else
+ {
+ // Pruefen, ob schon ein neues Attribut mit der WhichId an der Stelle:
+ EditCharAttrib* pAttr = pNode->GetCharAttribs().FindEmptyAttrib( rPoolItem.Which(), nStart );
+ if ( pAttr )
+ {
+ // Attribut entfernen....
+ pNode->GetCharAttribs().GetAttribs().Remove(
+ pNode->GetCharAttribs().GetAttribs().GetPos( pAttr ) );
+ }
+
+ // pruefen, ob ein 'gleiches' Attribut an der Stelle liegt.
+ pAttr = pNode->GetCharAttribs().FindAttrib( rPoolItem.Which(), nStart );
+ if ( pAttr )
+ {
+ if ( pAttr->IsInside( nStart ) ) // splitten
+ {
+ // ???????????????????????????????
+ // eigentlich noch pruefen, ob wirklich splittet, oder return !
+ // ???????????????????????????????
+ USHORT nOldEnd = pAttr->GetEnd();
+ pAttr->GetEnd() = nStart;
+ pAttr = MakeCharAttrib( GetItemPool(), *(pAttr->GetItem()), nStart, nOldEnd );
+ pNode->GetCharAttribs().InsertAttrib( pAttr );
+ }
+ else if ( pAttr->GetEnd() == nStart )
+ {
+ DBG_ASSERT( !pAttr->IsEmpty(), "Doch noch ein leeres Attribut?" );
+ // pruefen, ob genau das gleiche Attribut
+ if ( *(pAttr->GetItem()) == rPoolItem )
+ return;
+ }
+ }
+ InsertAttrib( rPoolItem, pNode, nStart, nStart );
+ }
+
+ SetModified( TRUE );
+}
+
+void EditDoc::FindAttribs( ContentNode* pNode, USHORT nStartPos, USHORT nEndPos, SfxItemSet& rCurSet )
+{
+ DBG_ASSERT( pNode, "Wo soll ich suchen ?" );
+ DBG_ASSERT( nStartPos <= nEndPos, "Ungueltiger Bereich!" );
+
+ USHORT nAttr = 0;
+ EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
+ // keine Selection...
+ if ( nStartPos == nEndPos )
+ {
+ while ( pAttr && ( pAttr->GetStart() <= nEndPos) )
+ {
+ const SfxPoolItem* pItem = 0;
+ // Attribut liegt dadrueber...
+ if ( ( pAttr->GetStart() < nStartPos ) && ( pAttr->GetEnd() > nStartPos ) )
+ pItem = pAttr->GetItem();
+ // Attribut endet hier, ist nicht leer
+ else if ( ( pAttr->GetStart() < nStartPos ) && ( pAttr->GetEnd() == nStartPos ) )
+ {
+ if ( !pNode->GetCharAttribs().FindEmptyAttrib( pAttr->GetItem()->Which(), nStartPos ) )
+ pItem = pAttr->GetItem();
+ }
+ // Attribut endet hier, ist leer
+ else if ( ( pAttr->GetStart() == nStartPos ) && ( pAttr->GetEnd() == nStartPos ) )
+ {
+ pItem = pAttr->GetItem();
+ }
+ // Attribut beginnt hier
+ else if ( ( pAttr->GetStart() == nStartPos ) && ( pAttr->GetEnd() > nStartPos ) )
+ {
+ if ( nStartPos == 0 ) // Sonderfall
+ pItem = pAttr->GetItem();
+ }
+
+ if ( pItem )
+ {
+ USHORT nWhich = pItem->Which();
+ if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF )
+ {
+ rCurSet.Put( *pItem );
+ }
+ else if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_ON )
+ {
+ const SfxPoolItem& rItem = rCurSet.Get( nWhich );
+ if ( rItem != *pItem )
+ {
+ rCurSet.InvalidateItem( nWhich );
+ }
+ }
+ }
+ nAttr++;
+ pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
+ }
+ }
+ else // Selektion
+ {
+ while ( pAttr && ( pAttr->GetStart() < nEndPos) )
+ {
+ const SfxPoolItem* pItem = 0;
+ // Attribut liegt dadrueber...
+ if ( ( pAttr->GetStart() <= nStartPos ) && ( pAttr->GetEnd() >= nEndPos ) )
+ pItem = pAttr->GetItem();
+ // Attribut startet mitten drin...
+ else if ( pAttr->GetStart() >= nStartPos )
+ {
+ // !!! pItem = pAttr->GetItem();
+ // einfach nur pItem reicht nicht, da ich z.B. bei Shadow
+ // niemals ein ungleiches Item finden wuerde, da ein solche
+ // seine Anwesenheit durch Abwesenheit repraesentiert!
+ // if ( ... )
+ // Es muesste geprueft werden, on genau das gleiche Attribut
+ // an der Bruchstelle aufsetzt, was recht aufwendig ist.
+ // Da ich beim Einfuegen von Attributen aber etwas optimiere
+ // tritt der Fall nicht so schnell auf...
+ // Also aus Geschwindigkeitsgruenden:
+ rCurSet.InvalidateItem( pAttr->GetItem()->Which() );
+
+ }
+ // Attribut endet mitten drin...
+ else if ( pAttr->GetEnd() > nStartPos )
+ {
+ // pItem = pAttr->GetItem();
+ // s.o.
+ /*-----------------31.05.95 16:01-------------------
+ Ist falsch, wenn das gleiche Attribut sofort wieder
+ eingestellt wird!
+ => Sollte am besten nicht vorkommen, also gleich beim
+ Setzen von Attributen richtig machen!
+ --------------------------------------------------*/
+ rCurSet.InvalidateItem( pAttr->GetItem()->Which() );
+ }
+
+ if ( pItem )
+ {
+ USHORT nWhich = pItem->Which();
+ if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF )
+ {
+ rCurSet.Put( *pItem );
+ }
+ else if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_ON )
+ {
+ const SfxPoolItem& rItem = rCurSet.Get( nWhich );
+ if ( rItem != *pItem )
+ {
+ rCurSet.InvalidateItem( nWhich );
+ }
+ }
+ }
+ nAttr++;
+ pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
+ }
+ }
+}
+
+
+ // -------------------------------------------------------------------------
+// class EditCharAttribList
+// -------------------------------------------------------------------------
+
+CharAttribList::CharAttribList()
+{
+ DBG_CTOR( EE_CharAttribList, 0 );
+ bHasEmptyAttribs = FALSE;
+}
+
+CharAttribList::~CharAttribList()
+{
+ DBG_DTOR( EE_CharAttribList, 0 );
+
+ USHORT nAttr = 0;
+ EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr );
+ while ( pAttr )
+ {
+ delete pAttr;
+ ++nAttr;
+ pAttr = GetAttrib( aAttribs, nAttr );
+ }
+ Clear();
+}
+
+void CharAttribList::InsertAttrib( EditCharAttrib* pAttrib )
+{
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// optimieren: binaere Suche ? !
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+ // MT: 26.11.98
+ // Vielleicht aber auch einfach nur rueckwaerts iterieren:
+ // Der haeufigste und kritischste Fall: Attribute kommen bereits
+ // sortiert an (InsertBinTextObject!)
+ // Hier waere auch binaere Suche nicht optimal.
+ // => Wuerde einiges bringen!
+
+ const USHORT nCount = Count();
+ const USHORT nStart = pAttrib->GetStart(); // vielleicht besser fuer Comp.Opt.
+
+ if ( pAttrib->IsEmpty() )
+ bHasEmptyAttribs = TRUE;
+
+ BOOL bInserted = FALSE;
+ for ( USHORT x = 0; x < nCount; x++ )
+ {
+ EditCharAttribPtr pCurAttrib = aAttribs[x];
+ if ( pCurAttrib->GetStart() > nStart )
+ {
+ aAttribs.Insert( pAttrib, x );
+ bInserted = TRUE;
+ break;
+ }
+ }
+ if ( !bInserted )
+ aAttribs.Insert( pAttrib, nCount );
+}
+
+void CharAttribList::ResortAttribs()
+{
+ if ( Count() )
+ {
+#if defined __SUNPRO_CC
+#pragma disable_warn
+#endif
+ qsort( (void*)aAttribs.GetData(), aAttribs.Count(), sizeof( EditCharAttrib* ), CompareStart );
+#if defined __SUNPRO_CC
+#pragma enable_warn
+#endif
+ }
+}
+
+void CharAttribList::OptimizeRanges( SfxItemPool& rItemPool )
+{
+ for ( USHORT n = 0; n < aAttribs.Count(); n++ )
+ {
+ EditCharAttrib* pAttr = aAttribs.GetObject( n );
+ for ( USHORT nNext = n+1; nNext < aAttribs.Count(); nNext++ )
+ {
+ EditCharAttrib* p = aAttribs.GetObject( nNext );
+ if ( !pAttr->IsFeature() && ( p->GetStart() == pAttr->GetEnd() ) && ( p->Which() == pAttr->Which() ) )
+ {
+ if ( *p->GetItem() == *pAttr->GetItem() )
+ {
+ pAttr->GetEnd() = p->GetEnd();
+ aAttribs.Remove( nNext );
+ rItemPool.Remove( *p->GetItem() );
+ delete p;
+ }
+ break; // only 1 attr with same which can start here.
+ }
+ else if ( p->GetStart() > pAttr->GetEnd() )
+ {
+ break;
+ }
+ }
+ }
+}
+
+EditCharAttrib* CharAttribList::FindAttrib( USHORT nWhich, USHORT nPos )
+{
+ // Rueckwaerts, falls eins dort endet, das naechste startet.
+ // => Das startende gilt...
+ USHORT nAttr = aAttribs.Count()-1;
+ EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr );
+ while ( pAttr )
+ {
+ if ( ( pAttr->Which() == nWhich ) && pAttr->IsIn(nPos) )
+ return pAttr;
+ pAttr = GetAttrib( aAttribs, --nAttr );
+ }
+ return 0;
+}
+
+EditCharAttrib* CharAttribList::FindNextAttrib( USHORT nWhich, USHORT nFromPos ) const
+{
+ DBG_ASSERT( nWhich, "FindNextAttrib: Which?" );
+ const USHORT nAttribs = aAttribs.Count();
+ for ( USHORT nAttr = 0; nAttr < nAttribs; nAttr++ )
+ {
+ EditCharAttrib* pAttr = aAttribs[ nAttr ];
+ if ( ( pAttr->GetStart() >= nFromPos ) && ( pAttr->Which() == nWhich ) )
+ return pAttr;
+ }
+ return 0;
+}
+
+BOOL CharAttribList::HasAttrib( USHORT nWhich ) const
+{
+ for ( USHORT nAttr = aAttribs.Count(); nAttr; )
+ {
+ const EditCharAttrib* pAttr = aAttribs[--nAttr];
+ if ( pAttr->Which() == nWhich )
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL CharAttribList::HasAttrib( USHORT nStartPos, USHORT nEndPos ) const
+{
+ BOOL bAttr = FALSE;
+ for ( USHORT nAttr = aAttribs.Count(); nAttr && !bAttr; )
+ {
+ const EditCharAttrib* pAttr = aAttribs[--nAttr];
+ if ( ( pAttr->GetStart() < nEndPos ) && ( pAttr->GetEnd() > nStartPos ) )
+ return bAttr = TRUE;
+ }
+ return bAttr;
+}
+
+
+BOOL CharAttribList::HasBoundingAttrib( USHORT nBound )
+{
+ // Rueckwaerts, falls eins dort endet, das naechste startet.
+ // => Das startende gilt...
+ USHORT nAttr = aAttribs.Count()-1;
+ EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr );
+ while ( pAttr && ( pAttr->GetEnd() >= nBound ) )
+ {
+ if ( ( pAttr->GetStart() == nBound ) || ( pAttr->GetEnd() == nBound ) )
+ return TRUE;
+ pAttr = GetAttrib( aAttribs, --nAttr );
+ }
+ return FALSE;
+}
+
+EditCharAttrib* CharAttribList::FindEmptyAttrib( USHORT nWhich, USHORT nPos )
+{
+ if ( !bHasEmptyAttribs )
+ return 0;
+ USHORT nAttr = 0;
+ EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr );
+ while ( pAttr && ( pAttr->GetStart() <= nPos ) )
+ {
+ if ( ( pAttr->GetStart() == nPos ) && ( pAttr->GetEnd() == nPos ) && ( pAttr->Which() == nWhich ) )
+ return pAttr;
+ nAttr++;
+ pAttr = GetAttrib( aAttribs, nAttr );
+ }
+ return 0;
+}
+
+EditCharAttrib* CharAttribList::FindFeature( USHORT nPos ) const
+{
+
+ USHORT nAttr = 0;
+ EditCharAttrib* pNextAttrib = GetAttrib( aAttribs, nAttr );
+
+ // erstmal zur gewuenschten Position...
+ while ( pNextAttrib && ( pNextAttrib->GetStart() < nPos ) )
+ {
+ nAttr++;
+ pNextAttrib = GetAttrib( aAttribs, nAttr );
+ }
+
+ // jetzt das Feature suchen...
+ while ( pNextAttrib && !pNextAttrib->IsFeature() )
+ {
+ nAttr++;
+ pNextAttrib = GetAttrib( aAttribs, nAttr );
+ }
+
+ return pNextAttrib;
+}
+
+
+void CharAttribList::DeleteEmptyAttribs( SfxItemPool& rItemPool )
+{
+ for ( USHORT nAttr = 0; nAttr < aAttribs.Count(); nAttr++ )
+ {
+ EditCharAttrib* pAttr = aAttribs[nAttr];
+ if ( pAttr->IsEmpty() )
+ {
+ rItemPool.Remove( *pAttr->GetItem() );
+ aAttribs.Remove( nAttr );
+ delete pAttr;
+ nAttr--;
+ }
+ }
+ bHasEmptyAttribs = FALSE;
+}
+
+BOOL CharAttribList::DbgCheckAttribs()
+{
+#ifdef DBG_UTIL
+ BOOL bOK = TRUE;
+ for ( USHORT nAttr = 0; nAttr < aAttribs.Count(); nAttr++ )
+ {
+ EditCharAttrib* pAttr = aAttribs[nAttr];
+ if ( pAttr->GetStart() > pAttr->GetEnd() )
+ {
+ bOK = FALSE;
+ DBG_ERROR( "Attr verdreht" );
+ }
+ else if ( pAttr->IsFeature() && ( pAttr->GetLen() != 1 ) )
+ {
+ bOK = FALSE;
+ DBG_ERROR( "Feature, Len != 1" );
+ }
+ }
+ return bOK;
+#else
+ return TRUE;
+#endif
+}
+
+
+
+SvxFontTable::SvxFontTable()
+{
+}
+
+SvxFontTable::~SvxFontTable()
+{
+ SvxFontItem* pItem = First();
+ while( pItem )
+ {
+ delete pItem;
+ pItem = Next();
+ }
+}
+
+ULONG SvxFontTable::GetId( const SvxFontItem& rFontItem )
+{
+ SvxFontItem* pItem = First();
+ while ( pItem )
+ {
+ if ( *pItem == rFontItem )
+ return GetCurKey();
+ pItem = Next();
+ }
+ DBG_WARNING( "Font nicht gefunden: GetId()" );
+ return 0;
+}
+
+SvxColorList::SvxColorList()
+{
+}
+
+SvxColorList::~SvxColorList()
+{
+ SvxColorItem* pItem = First();
+ while( pItem )
+ {
+ delete pItem;
+ pItem = Next();
+ }
+}
+
+ULONG SvxColorList::GetId( const SvxColorItem& rColorItem )
+{
+ SvxColorItem* pItem = First();
+ while ( pItem )
+ {
+ if ( *pItem == rColorItem )
+ return GetCurPos();
+ pItem = Next();
+ }
+ DBG_WARNING( "Color nicht gefunden: GetId()" );
+ return 0;
+}
+
+EditEngineItemPool::EditEngineItemPool( BOOL bPersistenRefCounts )
+ : SfxItemPool( String( "EditEngineItemPool", RTL_TEXTENCODING_ASCII_US ), EE_ITEMS_START, EE_ITEMS_END,
+ aItemInfos, 0, bPersistenRefCounts )
+{
+ SetVersionMap( 1, 3999, 4015, aV1Map );
+ SetVersionMap( 2, 3999, 4019, aV2Map );
+ SetVersionMap( 3, 3997, 4020, aV3Map );
+ SetVersionMap( 4, 3994, 4022, aV4Map );
+ SetVersionMap( 5, 3994, 4037, aV5Map );
+
+ DBG_ASSERT( EE_DLL(), "EditDLL?!" );
+ SfxPoolItem** ppDefItems = EE_DLL()->GetGlobalData()->GetDefItems();
+ SetDefaults( ppDefItems );
+}
+
+EditEngineItemPool::~EditEngineItemPool()
+{
+}
+
+SvStream& EditEngineItemPool::Store( SvStream& rStream ) const
+{
+ // Bei einem 3.1-Export muess ein Hack eingebaut werden, da BUG im
+ // SfxItemSet::Load, aber nicht nachtraeglich in 3.1 fixbar.
+
+ // Der eingestellte Range muss nach Store erhalten bleiben, weil dann
+ // erst die ItemSets gespeichert werden...
+
+ long nVersion = rStream.GetVersion();
+ BOOL b31Format = ( nVersion && ( nVersion <= SOFFICE_FILEFORMAT_31 ) )
+ ? TRUE : FALSE;
+
+ EditEngineItemPool* pThis = (EditEngineItemPool*)this;
+ if ( b31Format )
+ pThis->SetStoringRange( 3997, 4022 );
+ else
+ pThis->SetStoringRange( EE_ITEMS_START, EE_ITEMS_END );
+
+ return SfxItemPool::Store( rStream );
+}
diff --git a/editeng/source/editeng/editdoc.hxx b/editeng/source/editeng/editdoc.hxx
new file mode 100644
index 000000000000..bf2e3d01852b
--- /dev/null
+++ b/editeng/source/editeng/editdoc.hxx
@@ -0,0 +1,802 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef _EDITDOC_HXX
+#define _EDITDOC_HXX
+
+#ifndef _COM_SUN_STAR_I18N_XEXTENDEDINPUTSEQUENCECHECKER_HDL_
+#include <com/sun/star/i18n/XExtendedInputSequenceChecker.hpp>
+#endif
+
+#include <editattr.hxx>
+#include <edtspell.hxx>
+#include <editeng/svxfont.hxx>
+#include <svl/itemset.hxx>
+#include <svl/style.hxx>
+#include <svl/itempool.hxx>
+#include <tools/table.hxx>
+
+class ImpEditEngine;
+class SvxTabStop;
+class SvtCTLOptions;
+
+DBG_NAMEEX( EE_TextPortion )
+
+#define CHARPOSGROW 16
+#define DEFTAB 720
+
+void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent = true, short nScriptType = 0 );
+USHORT GetScriptItemId( USHORT nItemId, short nScriptType );
+BOOL IsScriptItemValid( USHORT nItemId, short nScriptType );
+
+EditCharAttrib* MakeCharAttrib( SfxItemPool& rPool, const SfxPoolItem& rAttr, USHORT nS, USHORT nE );
+
+class ContentNode;
+class EditDoc;
+
+struct EPaM
+{
+ USHORT nPara;
+ USHORT nIndex;
+
+ EPaM() { nPara = 0; nIndex = 0; }
+ EPaM( USHORT nP, USHORT nI ) { nPara = nP; nIndex = nI; }
+ EPaM( const EPaM& r) { nPara = r.nPara; nIndex = r.nIndex; }
+ EPaM& operator = ( const EPaM& r ) { nPara = r.nPara; nIndex = r.nIndex; return *this; }
+ inline BOOL operator == ( const EPaM& r ) const;
+ inline BOOL operator < ( const EPaM& r ) const;
+};
+
+inline BOOL EPaM::operator < ( const EPaM& r ) const
+{
+ return ( ( nPara < r.nPara ) ||
+ ( ( nPara == r.nPara ) && nIndex < r.nIndex ) ) ? TRUE : FALSE;
+}
+
+inline BOOL EPaM::operator == ( const EPaM& r ) const
+{
+ return ( ( nPara == r.nPara ) && ( nIndex == r.nIndex ) ) ? TRUE : FALSE;
+}
+
+struct ScriptTypePosInfo
+{
+ short nScriptType;
+ USHORT nStartPos;
+ USHORT nEndPos;
+
+ ScriptTypePosInfo( short _Type, USHORT _Start, USHORT _End )
+ {
+ nScriptType = _Type;
+ nStartPos = _Start;
+ nEndPos = _End;
+ }
+};
+
+SV_DECL_VARARR( ScriptTypePosInfos, ScriptTypePosInfo, 0, 4 )
+
+struct WritingDirectionInfo
+{
+ BYTE nType;
+ USHORT nStartPos;
+ USHORT nEndPos;
+
+ WritingDirectionInfo( BYTE _Type, USHORT _Start, USHORT _End )
+ {
+ nType = _Type;
+ nStartPos = _Start;
+ nEndPos = _End;
+ }
+};
+
+SV_DECL_VARARR( WritingDirectionInfos, WritingDirectionInfo, 0, 4 )
+
+typedef EditCharAttrib* EditCharAttribPtr;
+SV_DECL_PTRARR( CharAttribArray, EditCharAttribPtr, 0, 4 )
+
+class ContentAttribsInfo
+{
+private:
+ SfxItemSet aPrevParaAttribs;
+ CharAttribArray aPrevCharAttribs;
+
+public:
+ ContentAttribsInfo( const SfxItemSet& rParaAttribs );
+
+ const SfxItemSet& GetPrevParaAttribs() const { return aPrevParaAttribs; }
+ const CharAttribArray& GetPrevCharAttribs() const { return aPrevCharAttribs; }
+
+ CharAttribArray& GetPrevCharAttribs() { return aPrevCharAttribs; }
+};
+
+typedef ContentAttribsInfo* ContentAttribsInfoPtr;
+SV_DECL_PTRARR( ContentInfoArray, ContentAttribsInfoPtr, 1, 1 )
+
+// ----------------------------------------------------------------------
+// class SvxFontTable
+// ----------------------------------------------------------------------
+DECLARE_TABLE( DummyFontTable, SvxFontItem* )
+class SvxFontTable : public DummyFontTable
+{
+public:
+ SvxFontTable();
+ ~SvxFontTable();
+
+ ULONG GetId( const SvxFontItem& rFont );
+};
+
+// ----------------------------------------------------------------------
+// class SvxColorList
+// ----------------------------------------------------------------------
+typedef ContentNode* ContentNodePtr;
+DECLARE_LIST( DummyColorList, SvxColorItem* )
+class SvxColorList : public DummyColorList
+{
+public:
+ SvxColorList();
+ ~SvxColorList();
+
+ ULONG GetId( const SvxColorItem& rColor );
+};
+
+// ----------------------------------------------------------------------
+// class ItemList
+// ----------------------------------------------------------------------
+typedef const SfxPoolItem* ConstPoolItemPtr;
+DECLARE_LIST( DummyItemList, ConstPoolItemPtr )
+class ItemList : public DummyItemList
+{
+public:
+ const SfxPoolItem* FindAttrib( USHORT nWhich );
+};
+
+// -------------------------------------------------------------------------
+// class ContentAttribs
+// -------------------------------------------------------------------------
+class ContentAttribs
+{
+private:
+ SfxStyleSheet* pStyle;
+ SfxItemSet aAttribSet;
+
+public:
+ ContentAttribs( SfxItemPool& rItemPool );
+ ContentAttribs( const ContentAttribs& );
+ ~ContentAttribs(); // erst bei umfangreicheren Tabs
+
+ SvxTabStop FindTabStop( long nCurPos, USHORT nDefTab );
+ SfxItemSet& GetItems() { return aAttribSet; }
+ SfxStyleSheet* GetStyleSheet() const { return pStyle; }
+ void SetStyleSheet( SfxStyleSheet* pS );
+
+ const SfxPoolItem& GetItem( USHORT nWhich );
+ BOOL HasItem( USHORT nWhich );
+};
+
+// -------------------------------------------------------------------------
+// class CharAttribList
+// -------------------------------------------------------------------------
+class CharAttribList
+{
+private:
+ CharAttribArray aAttribs;
+ SvxFont aDefFont; // schneller, als jedesmal vom Pool!
+ BOOL bHasEmptyAttribs;
+
+ CharAttribList( const CharAttribList& ) {;}
+
+public:
+ CharAttribList();
+ ~CharAttribList();
+
+ void DeleteEmptyAttribs( SfxItemPool& rItemPool );
+ void RemoveItemsFromPool( SfxItemPool* pItemPool );
+
+ EditCharAttrib* FindAttrib( USHORT nWhich, USHORT nPos );
+ EditCharAttrib* FindNextAttrib( USHORT nWhich, USHORT nFromPos ) const;
+ EditCharAttrib* FindEmptyAttrib( USHORT nWhich, USHORT nPos );
+ EditCharAttrib* FindFeature( USHORT nPos ) const;
+
+
+ void ResortAttribs();
+ void OptimizeRanges( SfxItemPool& rItemPool );
+
+ USHORT Count() { return aAttribs.Count(); }
+ void Clear() { aAttribs.Remove( 0, aAttribs.Count()); }
+ void InsertAttrib( EditCharAttrib* pAttrib );
+
+ SvxFont& GetDefFont() { return aDefFont; }
+
+ BOOL HasEmptyAttribs() const { return bHasEmptyAttribs; }
+ BOOL& HasEmptyAttribs() { return bHasEmptyAttribs; }
+ BOOL HasBoundingAttrib( USHORT nBound );
+ BOOL HasAttrib( USHORT nWhich ) const;
+ BOOL HasAttrib( USHORT nStartPos, USHORT nEndPos ) const;
+
+ CharAttribArray& GetAttribs() { return aAttribs; }
+ const CharAttribArray& GetAttribs() const { return aAttribs; }
+
+ // Debug:
+ BOOL DbgCheckAttribs();
+};
+
+// -------------------------------------------------------------------------
+// class ContentNode
+// -------------------------------------------------------------------------
+class ContentNode : public XubString
+{
+private:
+ ContentAttribs aContentAttribs;
+ CharAttribList aCharAttribList;
+ WrongList* pWrongList;
+
+public:
+ ContentNode( SfxItemPool& rItemPool );
+ ContentNode( const XubString& rStr, const ContentAttribs& rContentAttribs );
+ ~ContentNode();
+
+ ContentAttribs& GetContentAttribs() { return aContentAttribs; }
+ CharAttribList& GetCharAttribs() { return aCharAttribList; }
+
+ void ExpandAttribs( USHORT nIndex, USHORT nNewChars, SfxItemPool& rItemPool );
+ void CollapsAttribs( USHORT nIndex, USHORT nDelChars, SfxItemPool& rItemPool );
+ void AppendAttribs( ContentNode* pNextNode );
+ void CopyAndCutAttribs( ContentNode* pPrevNode, SfxItemPool& rPool, BOOL bKeepEndingAttribs );
+
+ void SetStyleSheet( SfxStyleSheet* pS, BOOL bRecalcFont = TRUE );
+ void SetStyleSheet( SfxStyleSheet* pS, const SvxFont& rFontFromStyle );
+ SfxStyleSheet* GetStyleSheet() { return aContentAttribs.GetStyleSheet(); }
+
+ void CreateDefFont();
+
+ WrongList* GetWrongList() { return pWrongList; }
+ void SetWrongList( WrongList* p );
+
+ void CreateWrongList();
+ void DestroyWrongList();
+
+ BOOL IsFeature( USHORT nPos ) const { return ( GetChar( nPos ) == CH_FEATURE ); }
+};
+
+typedef ContentNode* ContentNodePtr;
+SV_DECL_PTRARR( DummyContentList, ContentNodePtr, 0, 4 )
+
+class ContentList : public DummyContentList
+{
+ USHORT nLastCache;
+public:
+ ContentList() : DummyContentList( 0, 4 ), nLastCache(0) {}
+ USHORT GetPos( const ContentNodePtr &rPtr ) const;
+};
+
+// -------------------------------------------------------------------------
+// class EditPaM
+// -------------------------------------------------------------------------
+class EditPaM
+{
+private:
+ ContentNode* pNode;
+ USHORT nIndex;
+
+public:
+ EditPaM() { pNode = NULL; nIndex = 0; }
+ EditPaM( ContentNode* p, USHORT n ) { pNode = p; nIndex = n; }
+
+ ContentNode* GetNode() const { return pNode; }
+ void SetNode( ContentNode* p) { pNode = p; }
+
+ USHORT GetIndex() const { return nIndex; }
+ USHORT& GetIndex() { return nIndex; }
+ void SetIndex( USHORT n ) { nIndex = n; }
+
+ BOOL IsParaStart() const { return nIndex == 0; }
+ BOOL IsParaEnd() const { return nIndex == pNode->Len(); }
+
+ BOOL DbgIsBuggy( EditDoc& rDoc );
+
+ EditPaM& operator = ( const EditPaM& rPaM );
+ friend BOOL operator == ( const EditPaM& r1, const EditPaM& r2 );
+ friend BOOL operator != ( const EditPaM& r1, const EditPaM& r2 );
+};
+
+#define PORTIONKIND_TEXT 0
+#define PORTIONKIND_TAB 1
+#define PORTIONKIND_LINEBREAK 2
+#define PORTIONKIND_FIELD 3
+#define PORTIONKIND_HYPHENATOR 4
+// #define PORTIONKIND_EXTRASPACE 5
+
+#define DELMODE_SIMPLE 0
+#define DELMODE_RESTOFWORD 1
+#define DELMODE_RESTOFCONTENT 2
+
+#define CHAR_NORMAL 0x00
+#define CHAR_KANA 0x01
+#define CHAR_PUNCTUATIONLEFT 0x02
+#define CHAR_PUNCTUATIONRIGHT 0x04
+
+// -------------------------------------------------------------------------
+// struct ExtraPortionInfos
+// -------------------------------------------------------------------------
+struct ExtraPortionInfo
+{
+ long nOrgWidth;
+ long nWidthFullCompression;
+
+ long nPortionOffsetX;
+
+ USHORT nMaxCompression100thPercent;
+
+ BYTE nAsianCompressionTypes;
+ BOOL bFirstCharIsRightPunktuation;
+ BOOL bCompressed;
+
+ sal_Int32* pOrgDXArray;
+
+
+ ExtraPortionInfo();
+ ~ExtraPortionInfo();
+
+ void SaveOrgDXArray( const sal_Int32* pDXArray, USHORT nLen );
+ void DestroyOrgDXArray();
+};
+
+
+// -------------------------------------------------------------------------
+// class TextPortion
+// -------------------------------------------------------------------------
+class TextPortion
+{
+private:
+ ExtraPortionInfo* pExtraInfos;
+ USHORT nLen;
+ Size aOutSz;
+ BYTE nKind;
+ BYTE nRightToLeft;
+ sal_Unicode nExtraValue;
+
+
+ TextPortion() { DBG_CTOR( EE_TextPortion, 0 );
+ pExtraInfos = NULL; nLen = 0; nKind = PORTIONKIND_TEXT; nExtraValue = 0; nRightToLeft = FALSE;}
+
+public:
+ TextPortion( USHORT nL ) : aOutSz( -1, -1 )
+ { DBG_CTOR( EE_TextPortion, 0 );
+ pExtraInfos = NULL; nLen = nL; nKind = PORTIONKIND_TEXT; nExtraValue = 0; nRightToLeft = FALSE;}
+ TextPortion( const TextPortion& r ) : aOutSz( r.aOutSz )
+ { DBG_CTOR( EE_TextPortion, 0 );
+ pExtraInfos = NULL; nLen = r.nLen; nKind = r.nKind; nExtraValue = r.nExtraValue; nRightToLeft = r.nRightToLeft; }
+
+ ~TextPortion() { DBG_DTOR( EE_TextPortion, 0 ); delete pExtraInfos; }
+
+ USHORT GetLen() const { return nLen; }
+ USHORT& GetLen() { return nLen; }
+ void SetLen( USHORT nL ) { nLen = nL; }
+
+ Size& GetSize() { return aOutSz; }
+ Size GetSize() const { return aOutSz; }
+
+ BYTE& GetKind() { return nKind; }
+ BYTE GetKind() const { return nKind; }
+
+ void SetRightToLeft( BYTE b ) { nRightToLeft = b; }
+ BYTE GetRightToLeft() const { return nRightToLeft; }
+ BOOL IsRightToLeft() const { return (nRightToLeft&1); }
+
+ sal_Unicode GetExtraValue() const { return nExtraValue; }
+ void SetExtraValue( sal_Unicode n ) { nExtraValue = n; }
+
+ BOOL HasValidSize() const { return aOutSz.Width() != (-1); }
+
+ ExtraPortionInfo* GetExtraInfos() const { return pExtraInfos; }
+ void SetExtraInfos( ExtraPortionInfo* p ) { delete pExtraInfos; pExtraInfos = p; }
+};
+
+// -------------------------------------------------------------------------
+// class TextPortionList
+// -------------------------------------------------------------------------
+typedef TextPortion* TextPortionPtr;
+SV_DECL_PTRARR( TextPortionArray, TextPortionPtr, 0, 8 )
+
+class TextPortionList : public TextPortionArray
+{
+public:
+ TextPortionList();
+ ~TextPortionList();
+
+ void Reset();
+ USHORT FindPortion( USHORT nCharPos, USHORT& rPortionStart, BOOL bPreferStartingPortion = FALSE );
+ USHORT GetStartPos( USHORT nPortion );
+ void DeleteFromPortion( USHORT nDelFrom );
+};
+
+class ParaPortion;
+
+SV_DECL_VARARR( CharPosArray, sal_Int32, 0, CHARPOSGROW )
+
+// ------------------------------------------------------------------------
+// class EditLine
+// -------------------------------------------------------------------------
+class EditLine
+{
+private:
+ CharPosArray aPositions;
+ long nTxtWidth;
+ USHORT nStartPosX;
+ USHORT nStart; // koennte durch nStartPortion ersetzt werden
+ USHORT nEnd; // koennte durch nEndPortion ersetzt werden
+ USHORT nStartPortion;
+ USHORT nEndPortion;
+ USHORT nHeight; // Gesamthoehe der Zeile
+ USHORT nTxtHeight; // Reine Texthoehe
+ USHORT nCrsrHeight; // Bei Konturfluss hohe Zeilen => Cursor zu groá.
+ USHORT nMaxAscent;
+ BOOL bHangingPunctuation;
+ BOOL bInvalid; // fuer geschickte Formatierung
+
+public:
+ EditLine();
+ EditLine( const EditLine& );
+ ~EditLine();
+
+ BOOL IsIn( USHORT nIndex ) const
+ { return ( (nIndex >= nStart ) && ( nIndex < nEnd ) ); }
+
+ BOOL IsIn( USHORT nIndex, BOOL bInclEnd ) const
+ { return ( ( nIndex >= nStart ) && ( bInclEnd ? ( nIndex <= nEnd ) : ( nIndex < nEnd ) ) ); }
+
+ void SetStart( USHORT n ) { nStart = n; }
+ USHORT GetStart() const { return nStart; }
+ USHORT& GetStart() { return nStart; }
+
+ void SetEnd( USHORT n ) { nEnd = n; }
+ USHORT GetEnd() const { return nEnd; }
+ USHORT& GetEnd() { return nEnd; }
+
+ void SetStartPortion( USHORT n ) { nStartPortion = n; }
+ USHORT GetStartPortion() const { return nStartPortion; }
+ USHORT& GetStartPortion() { return nStartPortion; }
+
+ void SetEndPortion( USHORT n ) { nEndPortion = n; }
+ USHORT GetEndPortion() const { return nEndPortion; }
+ USHORT& GetEndPortion() { return nEndPortion; }
+
+ void SetHeight( USHORT nH, USHORT nTxtH = 0, USHORT nCrsrH = 0 )
+ { nHeight = nH;
+ nTxtHeight = ( nTxtH ? nTxtH : nH );
+ nCrsrHeight = ( nCrsrH ? nCrsrH : nTxtHeight );
+ }
+ USHORT GetHeight() const { return nHeight; }
+ USHORT GetTxtHeight() const { return nTxtHeight; }
+ USHORT GetCrsrHeight() const { return nCrsrHeight; }
+
+ void SetTextWidth( long n ) { nTxtWidth = n; }
+ long GetTextWidth() const { return nTxtWidth; }
+
+ void SetMaxAscent( USHORT n ) { nMaxAscent = n; }
+ USHORT GetMaxAscent() const { return nMaxAscent; }
+
+ void SetHangingPunctuation( BOOL b ) { bHangingPunctuation = b; }
+ BOOL IsHangingPunctuation() const { return bHangingPunctuation; }
+
+ USHORT GetLen() const { return nEnd - nStart; }
+
+ USHORT GetStartPosX() const { return nStartPosX; }
+ void SetStartPosX( USHORT start ) { nStartPosX = start; }
+
+ Size CalcTextSize( ParaPortion& rParaPortion );
+
+ BOOL IsInvalid() const { return bInvalid; }
+ BOOL IsValid() const { return !bInvalid; }
+ void SetInvalid() { bInvalid = TRUE; }
+ void SetValid() { bInvalid = FALSE; }
+
+ BOOL IsEmpty() const { return (nEnd > nStart) ? FALSE : TRUE; }
+
+ CharPosArray& GetCharPosArray() { return aPositions; }
+
+ EditLine* Clone() const;
+
+ EditLine& operator = ( const EditLine& rLine );
+ friend BOOL operator == ( const EditLine& r1, const EditLine& r2 );
+ friend BOOL operator != ( const EditLine& r1, const EditLine& r2 );
+};
+
+
+// -------------------------------------------------------------------------
+// class LineList
+// -------------------------------------------------------------------------
+typedef EditLine* EditLinePtr;
+SV_DECL_PTRARR( LineArray, EditLinePtr, 0, 4 )
+
+class EditLineList : public LineArray
+{
+public:
+ EditLineList();
+ ~EditLineList();
+
+ void Reset();
+ void DeleteFromLine( USHORT nDelFrom );
+ USHORT FindLine( USHORT nChar, BOOL bInclEnd );
+};
+
+// -------------------------------------------------------------------------
+// class ParaPortion
+// -------------------------------------------------------------------------
+class ParaPortion
+{
+ friend class ImpEditEngine; // zum Einstellen der Hoehe
+private:
+ EditLineList aLineList;
+ TextPortionList aTextPortionList;
+ ContentNode* pNode;
+ long nHeight;
+
+ ScriptTypePosInfos aScriptInfos;
+ WritingDirectionInfos aWritingDirectionInfos;
+
+ USHORT nInvalidPosStart;
+ USHORT nFirstLineOffset; // Fuer Writer-LineSpacing-Interpretation
+ USHORT nBulletX;
+ short nInvalidDiff;
+
+ BOOL bInvalid : 1;
+ BOOL bSimple : 1; // nur lineares Tippen
+ BOOL bVisible : 1; // MT 05/00: Gehoert an den Node!!!
+ BOOL bForceRepaint : 1;
+
+ ParaPortion( const ParaPortion& );
+
+public:
+ ParaPortion( ContentNode* pNode );
+ ~ParaPortion();
+
+ USHORT GetLineNumber( USHORT nIndex );
+
+ EditLineList& GetLines() { return aLineList; }
+
+ BOOL IsInvalid() const { return bInvalid; }
+ BOOL IsSimpleInvalid() const { return bSimple; }
+ void SetValid() { bInvalid = FALSE; bSimple = TRUE;}
+
+ BOOL MustRepaint() const { return bForceRepaint; }
+ void SetMustRepaint( BOOL bRP ) { bForceRepaint = bRP; }
+
+ USHORT GetBulletX() const { return nBulletX; }
+ void SetBulletX( USHORT n ) { nBulletX = n; }
+
+ void MarkInvalid( USHORT nStart, short nDiff);
+ void MarkSelectionInvalid( USHORT nStart, USHORT nEnd );
+
+ void SetVisible( BOOL bVisible );
+ BOOL IsVisible() { return bVisible; }
+
+ long GetHeight() const { return ( bVisible ? nHeight : 0 ); }
+ USHORT GetFirstLineOffset() const { return ( bVisible ? nFirstLineOffset : 0 ); }
+ void ResetHeight() { nHeight = 0; nFirstLineOffset = 0; }
+
+ ContentNode* GetNode() const { return pNode; }
+ TextPortionList& GetTextPortions() { return aTextPortionList; }
+
+ USHORT GetInvalidPosStart() const { return nInvalidPosStart; }
+ short GetInvalidDiff() const { return nInvalidDiff; }
+
+ void CorrectValuesBehindLastFormattedLine( USHORT nLastFormattedLine );
+
+ BOOL DbgCheckTextPortions();
+};
+
+typedef ParaPortion* ParaPortionPtr;
+SV_DECL_PTRARR( DummyParaPortionList, ParaPortionPtr, 0, 4 )
+
+// -------------------------------------------------------------------------
+// class ParaPortionList
+// -------------------------------------------------------------------------
+class ParaPortionList : public DummyParaPortionList
+{
+ USHORT nLastCache;
+public:
+ ParaPortionList();
+ ~ParaPortionList();
+
+ void Reset();
+ long GetYOffset( ParaPortion* pPPortion );
+ USHORT FindParagraph( long nYOffset );
+
+ inline ParaPortion* SaveGetObject( USHORT nPos ) const
+ { return ( nPos < Count() ) ? GetObject( nPos ) : 0; }
+
+ USHORT GetPos( const ParaPortionPtr &rPtr ) const;
+
+ // temporaer:
+ void DbgCheck( EditDoc& rDoc );
+};
+
+// -------------------------------------------------------------------------
+// class EditSelection
+// -------------------------------------------------------------------------
+class EditSelection
+{
+private:
+ EditPaM aStartPaM;
+ EditPaM aEndPaM;
+
+public:
+ EditSelection(); // kein CCTOR und DTOR, geht autom. richtig!
+ EditSelection( const EditPaM& rStartAndAnd );
+ EditSelection( const EditPaM& rStart, const EditPaM& rEnd );
+
+ EditPaM& Min() { return aStartPaM; }
+ EditPaM& Max() { return aEndPaM; }
+
+ const EditPaM& Min() const { return aStartPaM; }
+ const EditPaM& Max() const { return aEndPaM; }
+
+ BOOL HasRange() const { return aStartPaM != aEndPaM; }
+ BOOL IsInvalid() const;
+ BOOL DbgIsBuggy( EditDoc& rDoc );
+
+ BOOL Adjust( const ContentList& rNodes );
+
+ EditSelection& operator = ( const EditPaM& r );
+ BOOL operator == ( const EditSelection& r ) const
+ { return ( ( aStartPaM == r.aStartPaM ) && ( aEndPaM == r.aEndPaM ) )
+ ? TRUE : FALSE; }
+ BOOL operator != ( const EditSelection& r ) const { return !( r == *this ); }
+};
+
+// -------------------------------------------------------------------------
+// class DeletedNodeInfo
+// -------------------------------------------------------------------------
+class DeletedNodeInfo
+{
+private:
+ ULONG nInvalidAdressPtr;
+ USHORT nInvalidParagraph;
+
+public:
+ DeletedNodeInfo( ULONG nInvAdr, USHORT nPos )
+ { nInvalidAdressPtr = nInvAdr;
+ nInvalidParagraph = nPos; }
+
+ ULONG GetInvalidAdress() { return nInvalidAdressPtr; }
+ USHORT GetPosition() { return nInvalidParagraph; }
+};
+
+typedef DeletedNodeInfo* DeletedNodeInfoPtr;
+SV_DECL_PTRARR( DeletedNodesList, DeletedNodeInfoPtr, 0, 4 )
+
+// -------------------------------------------------------------------------
+// class EditDoc
+// -------------------------------------------------------------------------
+class EditDoc : public ContentList
+{
+private:
+ SfxItemPool* pItemPool;
+ Link aModifyHdl;
+
+ SvxFont aDefFont; //schneller, als jedesmal vom Pool!
+ USHORT nDefTab;
+ BOOL bIsVertical;
+ BOOL bIsFixedCellHeight;
+
+ BOOL bOwnerOfPool;
+ BOOL bModified;
+
+protected:
+ void ImplDestroyContents();
+
+public:
+ EditDoc( SfxItemPool* pItemPool );
+ ~EditDoc();
+
+ BOOL IsModified() const { return bModified; }
+ void SetModified( BOOL b );
+
+ void SetModifyHdl( const Link& rLink ) { aModifyHdl = rLink; }
+ Link GetModifyHdl() const { return aModifyHdl; }
+
+ void CreateDefFont( BOOL bUseStyles );
+ const SvxFont& GetDefFont() { return aDefFont; }
+
+ void SetDefTab( USHORT nTab ) { nDefTab = nTab ? nTab : DEFTAB; }
+ USHORT GetDefTab() const { return nDefTab; }
+
+ void SetVertical( BOOL bVertical ) { bIsVertical = bVertical; }
+ BOOL IsVertical() const { return bIsVertical; }
+
+ void SetFixedCellHeight( BOOL bUseFixedCellHeight ) { bIsFixedCellHeight = bUseFixedCellHeight; }
+ BOOL IsFixedCellHeight() const { return bIsFixedCellHeight; }
+
+ EditPaM Clear();
+ EditPaM RemoveText();
+ EditPaM RemoveChars( EditPaM aPaM, USHORT nChars );
+ void InsertText( const EditPaM& rPaM, xub_Unicode c );
+ EditPaM InsertText( EditPaM aPaM, const XubString& rStr );
+ EditPaM InsertParaBreak( EditPaM aPaM, BOOL bKeepEndingAttribs );
+ EditPaM InsertFeature( EditPaM aPaM, const SfxPoolItem& rItem );
+ EditPaM ConnectParagraphs( ContentNode* pLeft, ContentNode* pRight );
+
+ String GetText( LineEnd eEnd ) const;
+ ULONG GetTextLen() const;
+
+ XubString GetParaAsString( USHORT nNode ) const;
+ XubString GetParaAsString( ContentNode* pNode, USHORT nStartPos = 0, USHORT nEndPos = 0xFFFF, BOOL bResolveFields = TRUE ) const;
+
+ inline EditPaM GetStartPaM() const;
+ inline EditPaM GetEndPaM() const;
+
+ SfxItemPool& GetItemPool() { return *pItemPool; }
+ const SfxItemPool& GetItemPool() const { return *pItemPool; }
+
+ void RemoveItemsFromPool( ContentNode* pNode );
+
+ void InsertAttrib( const SfxPoolItem& rItem, ContentNode* pNode, USHORT nStart, USHORT nEnd );
+ void InsertAttrib( ContentNode* pNode, USHORT nStart, USHORT nEnd, const SfxPoolItem& rPoolItem );
+ void InsertAttribInSelection( ContentNode* pNode, USHORT nStart, USHORT nEnd, const SfxPoolItem& rPoolItem );
+ BOOL RemoveAttribs( ContentNode* pNode, USHORT nStart, USHORT nEnd, USHORT nWhich = 0 );
+ BOOL RemoveAttribs( ContentNode* pNode, USHORT nStart, USHORT nEnd, EditCharAttrib*& rpStarting, EditCharAttrib*& rpEnding, USHORT nWhich = 0 );
+ void FindAttribs( ContentNode* pNode, USHORT nStartPos, USHORT nEndPos, SfxItemSet& rCurSet );
+
+ USHORT GetPos( ContentNode* pNode ) const { return ContentList::GetPos(pNode); }
+ ContentNode* SaveGetObject( USHORT nPos ) const { return ( nPos < Count() ) ? GetObject( nPos ) : 0; }
+
+ static XubString GetSepStr( LineEnd eEnd );
+};
+
+inline EditPaM EditDoc::GetStartPaM() const
+{
+ return EditPaM( GetObject( 0 ), 0 );
+}
+
+inline EditPaM EditDoc::GetEndPaM() const
+{
+ ContentNode* pLastNode = GetObject( Count()-1 );
+ return EditPaM( pLastNode, pLastNode->Len() );
+}
+
+inline EditCharAttrib* GetAttrib( const CharAttribArray& rAttribs, USHORT nAttr )
+{
+ return ( nAttr < rAttribs.Count() ) ? rAttribs[nAttr] : 0;
+}
+
+BOOL CheckOrderedList( CharAttribArray& rAttribs, BOOL bStart );
+
+// -------------------------------------------------------------------------
+// class EditEngineItemPool
+// -------------------------------------------------------------------------
+class EditEngineItemPool : public SfxItemPool
+{
+public:
+ EditEngineItemPool( BOOL bPersistenRefCounts );
+protected:
+ virtual ~EditEngineItemPool();
+public:
+
+ virtual SvStream& Store( SvStream& rStream ) const;
+};
+
+#endif // _EDITDOC_HXX
diff --git a/editeng/source/editeng/editdoc2.cxx b/editeng/source/editeng/editdoc2.cxx
new file mode 100644
index 000000000000..b2a83ffd6274
--- /dev/null
+++ b/editeng/source/editeng/editdoc2.cxx
@@ -0,0 +1,544 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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/smplhint.hxx>
+
+#include <tools/rtti.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/tstpitem.hxx>
+
+#include <editdoc.hxx>
+#include <impedit.hxx>
+#include <editdbg.hxx>
+
+#include <editeng/numitem.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/wrlmitem.hxx>
+#include <editeng/charscaleitem.hxx>
+
+#include <vcl/svapp.hxx> // Fuer AppWindow...
+
+DBG_NAME( EE_ParaPortion )
+
+SV_IMPL_VARARR( CharPosArray, sal_Int32 );
+
+/*
+
+BOOL EditStyleSheet::HasStyleAsAnyParent( SfxStyleSheet& rStyle )
+{
+ if ( GetParent() == rStyle.GetName() )
+ return TRUE;
+
+ if ( GetParent().Len() && ( GetParent() != GetName() ) )
+ {
+ EditStyleSheet* pS = (EditStyleSheet*)GetPool().Find( GetParent(), rStyle.GetFamily() );
+ if ( pS )
+ return pS->HasStyleAsAnyParent( rStyle );
+ }
+ return FALSE;
+}
+
+*/
+
+// -------------------------------------------------------------------------
+// class TextPortionList
+// -------------------------------------------------------------------------
+TextPortionList::TextPortionList()
+{
+}
+
+TextPortionList::~TextPortionList()
+{
+ Reset();
+}
+
+void TextPortionList::Reset()
+{
+ for ( USHORT nPortion = 0; nPortion < Count(); nPortion++ )
+ delete GetObject( nPortion );
+ Remove( 0, Count() );
+}
+
+void TextPortionList::DeleteFromPortion( USHORT nDelFrom )
+{
+ DBG_ASSERT( ( nDelFrom < Count() ) || ( (nDelFrom == 0) && (Count() == 0) ), "DeleteFromPortion: Out of range" );
+ for ( USHORT nP = nDelFrom; nP < Count(); nP++ )
+ delete GetObject( nP );
+ Remove( nDelFrom, Count()-nDelFrom );
+}
+
+USHORT TextPortionList::FindPortion( USHORT nCharPos, USHORT& nPortionStart, BOOL bPreferStartingPortion )
+{
+ // Bei nCharPos an Portion-Grenze wird die linke Portion gefunden
+ USHORT nTmpPos = 0;
+ for ( USHORT nPortion = 0; nPortion < Count(); nPortion++ )
+ {
+ TextPortion* pPortion = GetObject( nPortion );
+ nTmpPos = nTmpPos + pPortion->GetLen();
+ if ( nTmpPos >= nCharPos )
+ {
+ // take this one if we don't prefer the starting portion, or if it's the last one
+ if ( ( nTmpPos != nCharPos ) || !bPreferStartingPortion || ( nPortion == Count() - 1 ) )
+ {
+ nPortionStart = nTmpPos - pPortion->GetLen();
+ return nPortion;
+ }
+ }
+ }
+ DBG_ERROR( "FindPortion: Nicht gefunden!" );
+ return ( Count() - 1 );
+}
+
+USHORT TextPortionList::GetStartPos( USHORT nPortion )
+{
+ USHORT nPos = 0;
+ for ( USHORT n = 0; n < nPortion; n++ )
+ {
+ TextPortion* pPortion = GetObject( n );
+ nPos = nPos + pPortion->GetLen();
+ }
+ return nPos;
+}
+
+
+// -------------------------------------------------------------------------
+// class ExtraPortionInfo
+// -------------------------------------------------------------------------
+
+ExtraPortionInfo::ExtraPortionInfo()
+{
+ nOrgWidth = 0;
+ nWidthFullCompression = 0;
+ nMaxCompression100thPercent = 0;
+ nAsianCompressionTypes = 0;
+ nPortionOffsetX = 0;
+ bFirstCharIsRightPunktuation = FALSE;
+ bCompressed = FALSE;
+ pOrgDXArray = NULL;
+}
+
+ExtraPortionInfo::~ExtraPortionInfo()
+{
+ delete[] pOrgDXArray;
+}
+
+void ExtraPortionInfo::SaveOrgDXArray( const sal_Int32* pDXArray, USHORT nLen )
+{
+ delete[] pOrgDXArray;
+ pOrgDXArray = new sal_Int32[nLen];
+ memcpy( pOrgDXArray, pDXArray, nLen*sizeof(sal_Int32) );
+}
+
+void ExtraPortionInfo::DestroyOrgDXArray()
+{
+ delete[] pOrgDXArray;
+ pOrgDXArray = NULL;
+}
+
+
+// -------------------------------------------------------------------------
+// class ParaPortion
+// -------------------------------------------------------------------------
+ParaPortion::ParaPortion( ContentNode* pN )
+{
+ DBG_CTOR( EE_ParaPortion, 0 );
+
+ pNode = pN;
+ bInvalid = TRUE;
+ bVisible = TRUE;
+ bSimple = FALSE;
+ bForceRepaint = FALSE;
+ nInvalidPosStart = 0;
+ nInvalidDiff = 0;
+ nHeight = 0;
+ nFirstLineOffset = 0;
+ nBulletX = 0;
+}
+
+ParaPortion::~ParaPortion()
+{
+ DBG_DTOR( EE_ParaPortion, 0 );
+}
+
+void ParaPortion::MarkInvalid( USHORT nStart, short nDiff )
+{
+ if ( bInvalid == FALSE )
+ {
+// nInvalidPosEnd = nStart; // ??? => CreateLines
+ nInvalidPosStart = ( nDiff >= 0 ) ? nStart : ( nStart + nDiff );
+ nInvalidDiff = nDiff;
+ }
+ else
+ {
+ // Einfaches hintereinander tippen
+ if ( ( nDiff > 0 ) && ( nInvalidDiff > 0 ) &&
+ ( ( nInvalidPosStart+nInvalidDiff ) == nStart ) )
+ {
+ nInvalidDiff = nInvalidDiff + nDiff;
+ }
+ // Einfaches hintereinander loeschen
+ else if ( ( nDiff < 0 ) && ( nInvalidDiff < 0 ) && ( nInvalidPosStart == nStart ) )
+ {
+ nInvalidPosStart = nInvalidPosStart + nDiff;
+ nInvalidDiff = nInvalidDiff + nDiff;
+ }
+ else
+ {
+// nInvalidPosEnd = pNode->Len();
+ DBG_ASSERT( ( nDiff >= 0 ) || ( (nStart+nDiff) >= 0 ), "MarkInvalid: Diff out of Range" );
+ nInvalidPosStart = Min( nInvalidPosStart, (USHORT) ( nDiff < 0 ? nStart+nDiff : nDiff ) );
+ nInvalidDiff = 0;
+ bSimple = FALSE;
+ }
+ }
+ bInvalid = TRUE;
+ aScriptInfos.Remove( 0, aScriptInfos.Count() );
+ aWritingDirectionInfos.Remove( 0, aWritingDirectionInfos.Count() );
+// aExtraCharInfos.Remove( 0, aExtraCharInfos.Count() );
+}
+
+void ParaPortion::MarkSelectionInvalid( USHORT nStart, USHORT /* nEnd */ )
+{
+ if ( bInvalid == FALSE )
+ {
+ nInvalidPosStart = nStart;
+// nInvalidPosEnd = nEnd;
+ }
+ else
+ {
+ nInvalidPosStart = Min( nInvalidPosStart, nStart );
+// nInvalidPosEnd = pNode->Len();
+ }
+ nInvalidDiff = 0;
+ bInvalid = TRUE;
+ bSimple = FALSE;
+ aScriptInfos.Remove( 0, aScriptInfos.Count() );
+ aWritingDirectionInfos.Remove( 0, aWritingDirectionInfos.Count() );
+// aExtraCharInfos.Remove( 0, aExtraCharInfos.Count() );
+}
+
+USHORT ParaPortion::GetLineNumber( USHORT nIndex )
+{
+ DBG_ASSERTWARNING( aLineList.Count(), "Leere ParaPortion in GetLine!" );
+ DBG_ASSERT( bVisible, "Wozu GetLine() bei einem unsichtbaren Absatz?" );
+
+ for ( USHORT nLine = 0; nLine < aLineList.Count(); nLine++ )
+ {
+ if ( aLineList[nLine]->IsIn( nIndex ) )
+ return nLine;
+ }
+
+ // Dann sollte es am Ende der letzten Zeile sein!
+ DBG_ASSERT( nIndex == aLineList[ aLineList.Count() - 1 ]->GetEnd(), "Index voll daneben!" );
+ return (aLineList.Count()-1);
+}
+
+void ParaPortion::SetVisible( BOOL bMakeVisible )
+{
+ bVisible = bMakeVisible;
+}
+
+void ParaPortion::CorrectValuesBehindLastFormattedLine( USHORT nLastFormattedLine )
+{
+ USHORT nLines = aLineList.Count();
+ DBG_ASSERT( nLines, "CorrectPortionNumbersFromLine: Leere Portion?" );
+ if ( nLastFormattedLine < ( nLines - 1 ) )
+ {
+ const EditLine* pLastFormatted = aLineList[ nLastFormattedLine ];
+ const EditLine* pUnformatted = aLineList[ nLastFormattedLine+1 ];
+ short nPortionDiff = pUnformatted->GetStartPortion() - pLastFormatted->GetEndPortion();
+ short nTextDiff = pUnformatted->GetStart() - pLastFormatted->GetEnd();
+ nTextDiff++; // LastFormatted->GetEnd() war incl. => 1 zuviel abgezogen!
+
+ // Die erste unformatierte muss genau eine Portion hinter der letzten der
+ // formatierten beginnen:
+ // Wenn in der geaenderten Zeile eine Portion gesplittet wurde,
+ // kann nLastEnd > nNextStart sein!
+ int nPDiff = -( nPortionDiff-1 );
+ int nTDiff = -( nTextDiff-1 );
+ if ( nPDiff || nTDiff )
+ {
+ for ( USHORT nL = nLastFormattedLine+1; nL < nLines; nL++ )
+ {
+ EditLine* pLine = aLineList[ nL ];
+
+ pLine->GetStartPortion() = sal::static_int_cast< USHORT >(
+ pLine->GetStartPortion() + nPDiff);
+ pLine->GetEndPortion() = sal::static_int_cast< USHORT >(
+ pLine->GetEndPortion() + nPDiff);
+
+ pLine->GetStart() = sal::static_int_cast< USHORT >(
+ pLine->GetStart() + nTDiff);
+ pLine->GetEnd() = sal::static_int_cast< USHORT >(
+ pLine->GetEnd() + nTDiff);
+
+ pLine->SetValid();
+ }
+ }
+ }
+ DBG_ASSERT( aLineList[ aLineList.Count()-1 ]->GetEnd() == pNode->Len(), "CorrectLines: Ende stimmt nicht!" );
+}
+
+// Shared reverse lookup acceleration pieces ...
+
+static USHORT FastGetPos( const VoidPtr *pPtrArray, USHORT nPtrArrayLen,
+ VoidPtr pPtr, USHORT &rLastPos )
+{
+ // Through certain filter code-paths we do a lot of appends, which in
+ // turn call GetPos - creating some N^2 nightmares. If we have a
+ // non-trivially large list, do a few checks from the end first.
+ if( rLastPos > 16 )
+ {
+ USHORT nEnd;
+ if (rLastPos > nPtrArrayLen - 2)
+ nEnd = nPtrArrayLen;
+ else
+ nEnd = rLastPos + 2;
+
+ for( USHORT nIdx = rLastPos - 2; nIdx < nEnd; nIdx++ )
+ {
+ if( pPtrArray[ nIdx ] == pPtr )
+ {
+ rLastPos = nIdx;
+ return nIdx;
+ }
+ }
+ }
+ // The world's lamest linear search from svarray ...
+ for( USHORT nIdx = 0; nIdx < nPtrArrayLen; nIdx++ )
+ if (pPtrArray[ nIdx ] == pPtr )
+ return rLastPos = nIdx;
+ return USHRT_MAX;
+}
+
+// -------------------------------------------------------------------------
+// class ParaPortionList
+// -------------------------------------------------------------------------
+ParaPortionList::ParaPortionList() : nLastCache( 0 )
+{
+}
+
+ParaPortionList::~ParaPortionList()
+{
+ Reset();
+}
+
+USHORT ParaPortionList::GetPos( const ParaPortionPtr &rPtr ) const
+{
+ return FastGetPos( reinterpret_cast<const VoidPtr *>( GetData() ),
+ Count(), static_cast<VoidPtr>( rPtr ),
+ ((ParaPortionList *)this)->nLastCache );
+}
+
+USHORT ContentList::GetPos( const ContentNodePtr &rPtr ) const
+{
+ return FastGetPos( reinterpret_cast<const VoidPtr *>( GetData() ),
+ Count(), static_cast<VoidPtr>( rPtr ),
+ ((ContentList *)this)->nLastCache );
+}
+
+void ParaPortionList::Reset()
+{
+ for ( USHORT nPortion = 0; nPortion < Count(); nPortion++ )
+ delete GetObject( nPortion );
+ Remove( 0, Count() );
+}
+
+long ParaPortionList::GetYOffset( ParaPortion* pPPortion )
+{
+ long nHeight = 0;
+ for ( USHORT nPortion = 0; nPortion < Count(); nPortion++ )
+ {
+ ParaPortion* pTmpPortion = GetObject(nPortion);
+ if ( pTmpPortion == pPPortion )
+ return nHeight;
+ nHeight += pTmpPortion->GetHeight();
+ }
+ DBG_ERROR( "GetYOffset: Portion nicht gefunden" );
+ return nHeight;
+}
+
+USHORT ParaPortionList::FindParagraph( long nYOffset )
+{
+ long nY = 0;
+ for ( USHORT nPortion = 0; nPortion < Count(); nPortion++ )
+ {
+ nY += GetObject(nPortion)->GetHeight(); // sollte auch bei !bVisible richtig sein!
+ if ( nY > nYOffset )
+ return nPortion;
+ }
+ return 0xFFFF; // solte mal ueber EE_PARA_NOT_FOUND erreicht werden!
+}
+
+void ParaPortionList::DbgCheck( EditDoc&
+#ifdef DBG_UTIL
+ rDoc
+#endif
+ )
+{
+#ifdef DBG_UTIL
+ DBG_ASSERT( Count() == rDoc.Count(), "ParaPortionList::DbgCheck() - Count() ungleich!" );
+ for ( USHORT i = 0; i < Count(); i++ )
+ {
+ DBG_ASSERT( SaveGetObject(i), "ParaPortionList::DbgCheck() - Null-Pointer in Liste!" );
+ DBG_ASSERT( GetObject(i)->GetNode(), "ParaPortionList::DbgCheck() - Null-Pointer in Liste(2)!" );
+ DBG_ASSERT( GetObject(i)->GetNode() == rDoc.GetObject(i), "ParaPortionList::DbgCheck() - Eintraege kreuzen sich!" );
+ }
+#endif
+}
+
+
+ContentAttribsInfo::ContentAttribsInfo( const SfxItemSet& rParaAttribs ) :
+ aPrevParaAttribs( rParaAttribs)
+{
+}
+
+
+void ConvertItem( SfxPoolItem& rPoolItem, MapUnit eSourceUnit, MapUnit eDestUnit )
+{
+ DBG_ASSERT( eSourceUnit != eDestUnit, "ConvertItem - Why?!" );
+
+ switch ( rPoolItem.Which() )
+ {
+ case EE_PARA_LRSPACE:
+ {
+ DBG_ASSERT( rPoolItem.IsA( TYPE( SvxLRSpaceItem ) ), "ConvertItem: Ungueltiges Item!" );
+ SvxLRSpaceItem& rItem = (SvxLRSpaceItem&)rPoolItem;
+ rItem.SetTxtFirstLineOfst( sal::static_int_cast< short >( OutputDevice::LogicToLogic( rItem.GetTxtFirstLineOfst(), eSourceUnit, eDestUnit ) ) );
+ rItem.SetTxtLeft( OutputDevice::LogicToLogic( rItem.GetTxtLeft(), eSourceUnit, eDestUnit ) );
+// rItem.SetLeft( OutputDevice::LogicToLogic( rItem.GetLeft(), eSourceUnit, eDestUnit ) ); // #96298# SetLeft manipulates nTxtLeft!
+ rItem.SetRight( OutputDevice::LogicToLogic( rItem.GetRight(), eSourceUnit, eDestUnit ) );
+ }
+ break;
+ case EE_PARA_ULSPACE:
+ {
+ DBG_ASSERT( rPoolItem.IsA( TYPE( SvxULSpaceItem ) ), "ConvertItem: Ungueltiges Item!" );
+ SvxULSpaceItem& rItem = (SvxULSpaceItem&)rPoolItem;
+ rItem.SetUpper( sal::static_int_cast< USHORT >( OutputDevice::LogicToLogic( rItem.GetUpper(), eSourceUnit, eDestUnit ) ) );
+ rItem.SetLower( sal::static_int_cast< USHORT >( OutputDevice::LogicToLogic( rItem.GetLower(), eSourceUnit, eDestUnit ) ) );
+ }
+ break;
+ case EE_PARA_SBL:
+ {
+ DBG_ASSERT( rPoolItem.IsA( TYPE( SvxLineSpacingItem ) ), "ConvertItem: Ungueltiges Item!" );
+ SvxLineSpacingItem& rItem = (SvxLineSpacingItem&)rPoolItem;
+ // #96298# SetLineHeight changes also eLineSpace!
+ if ( rItem.GetLineSpaceRule() == SVX_LINE_SPACE_MIN )
+ rItem.SetLineHeight( sal::static_int_cast< USHORT >( OutputDevice::LogicToLogic( rItem.GetLineHeight(), eSourceUnit, eDestUnit ) ) );
+ }
+ break;
+ case EE_PARA_TABS:
+ {
+ DBG_ASSERT( rPoolItem.IsA( TYPE( SvxTabStopItem ) ), "ConvertItem: Ungueltiges Item!" );
+ SvxTabStopItem& rItem = (SvxTabStopItem&)rPoolItem;
+ SvxTabStopItem aNewItem( EE_PARA_TABS );
+ for ( USHORT i = 0; i < rItem.Count(); i++ )
+ {
+ const SvxTabStop& rTab = rItem[i];
+ SvxTabStop aNewStop( OutputDevice::LogicToLogic( rTab.GetTabPos(), eSourceUnit, eDestUnit ), rTab.GetAdjustment(), rTab.GetDecimal(), rTab.GetFill() );
+ aNewItem.Insert( aNewStop );
+ }
+ rItem = aNewItem;
+ }
+ break;
+ case EE_CHAR_FONTHEIGHT:
+ case EE_CHAR_FONTHEIGHT_CJK:
+ case EE_CHAR_FONTHEIGHT_CTL:
+ {
+ DBG_ASSERT( rPoolItem.IsA( TYPE( SvxFontHeightItem ) ), "ConvertItem: Ungueltiges Item!" );
+ SvxFontHeightItem& rItem = (SvxFontHeightItem&)rPoolItem;
+ rItem.SetHeight( OutputDevice::LogicToLogic( rItem.GetHeight(), eSourceUnit, eDestUnit ) );
+ }
+ break;
+ }
+}
+
+void ConvertAndPutItems( SfxItemSet& rDest, const SfxItemSet& rSource, const MapUnit* pSourceUnit, const MapUnit* pDestUnit )
+{
+ const SfxItemPool* pSourcePool = rSource.GetPool();
+ const SfxItemPool* pDestPool = rDest.GetPool();
+
+ for ( USHORT nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ )
+ {
+ // Wenn moeglich ueber SlotID gehen...
+
+ USHORT nSourceWhich = nWhich;
+ USHORT nSlot = pDestPool->GetTrueSlotId( nWhich );
+ if ( nSlot )
+ {
+ USHORT nW = pSourcePool->GetTrueWhich( nSlot );
+ if ( nW )
+ nSourceWhich = nW;
+ }
+
+ if ( rSource.GetItemState( nSourceWhich, FALSE ) == SFX_ITEM_ON )
+ {
+ MapUnit eSourceUnit = pSourceUnit ? *pSourceUnit : (MapUnit)pSourcePool->GetMetric( nSourceWhich );
+ MapUnit eDestUnit = pDestUnit ? *pDestUnit : (MapUnit)pDestPool->GetMetric( nWhich );
+ if ( eSourceUnit != eDestUnit )
+ {
+ SfxPoolItem* pItem = rSource.Get( nSourceWhich ).Clone();
+// pItem->SetWhich( nWhich );
+ ConvertItem( *pItem, eSourceUnit, eDestUnit );
+ rDest.Put( *pItem, nWhich );
+ delete pItem;
+ }
+ else
+ {
+ rDest.Put( rSource.Get( nSourceWhich ), nWhich );
+ }
+ }
+ else
+ {
+ // MT 3.3.99: Waere so eigentlich richtig, aber schon seit Jahren nicht so...
+// rDest.ClearItem( nWhich );
+ }
+ }
+}
+
diff --git a/editeng/source/editeng/editeng.cxx b/editeng/source/editeng/editeng.cxx
new file mode 100644
index 000000000000..212fb8ff9446
--- /dev/null
+++ b/editeng/source/editeng/editeng.cxx
@@ -0,0 +1,2939 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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>
+
+#define USE_SVXFONT
+
+#define _SVSTDARR_USHORTS
+#include <svl/svstdarr.hxx>
+#include <svl/ctloptions.hxx>
+#include <svtools/ctrltool.hxx>
+
+#include <editeng/svxfont.hxx>
+#include <impedit.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/editview.hxx>
+#include <editeng/editstat.hxx>
+#include <editdbg.hxx>
+#include <eerdll2.hxx>
+#include <editeng/eerdll.hxx>
+#include <editeng.hrc>
+#include <editeng/flditem.hxx>
+#include <editeng/txtrange.hxx>
+#include <vcl/graph.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/wghtitem.hxx>
+#include <editeng/wrlmitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/cscoitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/emphitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/charreliefitem.hxx>
+
+#include <sot/exchange.hxx>
+#include <sot/formats.hxx>
+
+#include <editeng/numitem.hxx>
+#include <editeng/bulitem.hxx>
+#include <editeng/unolingu.hxx>
+#include <linguistic/lngprops.hxx>
+#include <i18npool/mslangid.hxx>
+#include <vcl/help.hxx>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <com/sun/star/i18n/InputSequenceCheckMode.hpp>
+
+#include <svl/srchdefs.hxx>
+
+#if OSL_DEBUG_LEVEL > 1
+#include <editeng/frmdiritem.hxx>
+#endif
+#include <basegfx/polygon/b2dpolygon.hxx>
+
+// Spaeter -> TOOLS\STRING.H (fuer Grep: WS_TARGET)
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::linguistic2;
+
+
+DBG_NAME( EditEngine )
+DBG_NAMEEX( EditView )
+
+#if (OSL_DEBUG_LEVEL > 1) || defined ( DBG_UTIL )
+static sal_Bool bDebugPaint = sal_False;
+#endif
+
+SV_IMPL_VARARR( EECharAttribArray, EECharAttrib );
+
+static SfxItemPool* pGlobalPool=0;
+
+ // ----------------------------------------------------------------------
+// EditEngine
+// ----------------------------------------------------------------------
+EditEngine::EditEngine( SfxItemPool* pItemPool )
+{
+ DBG_CTOR( EditEngine, 0 );
+ pImpEditEngine = new ImpEditEngine( this, pItemPool );
+}
+
+EditEngine::~EditEngine()
+{
+ DBG_DTOR( EditEngine, 0 );
+ delete pImpEditEngine;
+}
+
+void EditEngine::EnableUndo( sal_Bool bEnable )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->EnableUndo( bEnable );
+}
+
+sal_Bool EditEngine::IsUndoEnabled()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->IsUndoEnabled();
+}
+
+sal_Bool EditEngine::IsInUndo()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->IsInUndo();
+}
+
+SfxUndoManager& EditEngine::GetUndoManager()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetUndoManager();
+}
+
+void EditEngine::UndoActionStart( sal_uInt16 nId )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ DBG_ASSERT( !pImpEditEngine->IsInUndo(), "Aufruf von UndoActionStart im Undomodus!" );
+ if ( !pImpEditEngine->IsInUndo() )
+ pImpEditEngine->UndoActionStart( nId );
+}
+
+void EditEngine::UndoActionEnd( sal_uInt16 nId )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ DBG_ASSERT( !pImpEditEngine->IsInUndo(), "Aufruf von UndoActionEnd im Undomodus!" );
+ if ( !pImpEditEngine->IsInUndo() )
+ pImpEditEngine->UndoActionEnd( nId );
+}
+
+BOOL EditEngine::HasTriedMergeOnLastAddUndo() const
+{
+ return pImpEditEngine->mbLastTryMerge;
+}
+
+void EditEngine::SetRefDevice( OutputDevice* pRefDev )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetRefDevice( pRefDev );
+}
+
+OutputDevice* EditEngine::GetRefDevice() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetRefDevice();
+}
+
+void EditEngine::SetRefMapMode( const MapMode& rMapMode )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetRefMapMode( rMapMode );
+}
+
+MapMode EditEngine::GetRefMapMode()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetRefMapMode();
+}
+
+void EditEngine::SetBackgroundColor( const Color& rColor )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetBackgroundColor( rColor );
+}
+
+Color EditEngine::GetBackgroundColor() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetBackgroundColor();
+}
+
+Color EditEngine::GetAutoColor() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetAutoColor();
+}
+
+void EditEngine::EnableAutoColor( BOOL b )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->EnableAutoColor( b );
+}
+
+BOOL EditEngine::IsAutoColorEnabled() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->IsAutoColorEnabled();
+}
+
+void EditEngine::ForceAutoColor( BOOL b )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->ForceAutoColor( b );
+}
+
+BOOL EditEngine::IsForceAutoColor() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->IsForceAutoColor();
+}
+
+const SfxItemSet& EditEngine::GetEmptyItemSet()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetEmptyItemSet();
+}
+
+void EditEngine::Draw( OutputDevice* pOutDev, const Rectangle& rOutRect )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ Draw( pOutDev, rOutRect, Point( 0, 0 ) );
+}
+
+void EditEngine::Draw( OutputDevice* pOutDev, const Point& rStartPos, short nOrientation )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ // Mit 2 Punkten erzeugen, da bei Positivem Punkt, LONGMAX als Size
+ // Bottom und Right im Bereich > LONGMAX landen.
+ Rectangle aBigRec( -0x3FFFFFFF, -0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF );
+ if( pOutDev->GetConnectMetaFile() )
+ pOutDev->Push();
+ Point aStartPos( rStartPos );
+ if ( IsVertical() )
+ {
+ aStartPos.X() += GetPaperSize().Width();
+ aStartPos = Rotate( aStartPos, nOrientation, rStartPos );
+ }
+ pImpEditEngine->Paint( pOutDev, aBigRec, aStartPos, sal_False, nOrientation );
+ if( pOutDev->GetConnectMetaFile() )
+ pOutDev->Pop();
+}
+
+void EditEngine::Draw( OutputDevice* pOutDev, const Rectangle& rOutRect, const Point& rStartDocPos )
+{
+ Draw( pOutDev, rOutRect, rStartDocPos, sal_True );
+}
+
+void EditEngine::Draw( OutputDevice* pOutDev, const Rectangle& rOutRect, const Point& rStartDocPos, sal_Bool bClip )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+
+#if defined( DBG_UTIL ) || (OSL_DEBUG_LEVEL > 1)
+ if ( bDebugPaint )
+ EditDbg::ShowEditEngineData( this, sal_False );
+#endif
+
+ // Auf Pixelgrenze ausrichten, damit genau das gleiche
+ // wie bei Paint().
+ Rectangle aOutRect( pOutDev->LogicToPixel( rOutRect ) );
+ aOutRect = pOutDev->PixelToLogic( aOutRect );
+
+ Point aStartPos;
+ if ( !IsVertical() )
+ {
+ aStartPos.X() = aOutRect.Left() - rStartDocPos.X();
+ aStartPos.Y() = aOutRect.Top() - rStartDocPos.Y();
+ }
+ else
+ {
+ aStartPos.X() = aOutRect.Right() + rStartDocPos.Y();
+ aStartPos.Y() = aOutRect.Top() - rStartDocPos.X();
+ }
+
+ sal_Bool bClipRegion = pOutDev->IsClipRegion();
+ sal_Bool bMetafile = pOutDev->GetConnectMetaFile() ? sal_True : sal_False;
+ Region aOldRegion = pOutDev->GetClipRegion();
+
+#ifdef EDIT_PRINTER_LOG
+ if ( pOutDev->GetOutDevType() == OUTDEV_PRINTER )
+ {
+ SvFileStream aLog( "d:\\editprn.log", STREAM_WRITE );
+ aLog.Seek( STREAM_SEEK_TO_END );
+ aLog << ' ' << endl << "Printing: ";
+ aLog << GetText( "\n\r" ).GetStr();
+ aLog << endl << endl;
+ aLog << "Ref-Device: " << String( (sal_uInt32)GetRefDevice() ).GetStr() << " Type=" << String( (sal_uInt16)GetRefDevice()->GetOutDevType() ).GetStr() << ", MapX=" << String( GetRefDevice()->GetMapMode().GetScaleX().GetNumerator() ).GetStr() << "/" << String( GetRefDevice()->GetMapMode().GetScaleX().GetDenominator() ).GetStr() <<endl;
+ aLog << "Paper-Width: " << String( GetPaperSize().Width() ).GetStr() << ",\tOut-Width: " << String( rOutRect.GetWidth() ).GetStr() << ",\tCalculated: " << String( CalcTextWidth() ).GetStr() << endl;
+ aLog << "Paper-Height: " << String( GetPaperSize().Height() ).GetStr() << ",\tOut-Height: " << String( rOutRect.GetHeight() ).GetStr() << ",\tCalculated: " << String( GetTextHeight() ).GetStr() << endl;
+
+ aLog << endl;
+ }
+#endif
+
+ // Wenn es eine gab => Schnittmenge !
+ // Bei der Metafileaufzeichnung Push/Pop verwenden.
+ if ( bMetafile )
+ pOutDev->Push();
+
+ // Immer die Intersect-Methode, weil beim Metafile ein Muss!
+ if ( bClip )
+ {
+ // Clip only if neccesary...
+ if ( !rStartDocPos.X() && !rStartDocPos.Y() &&
+ ( rOutRect.GetHeight() >= (long)GetTextHeight() ) &&
+ ( rOutRect.GetWidth() >= (long)CalcTextWidth() ) )
+ {
+ bClip = FALSE;
+ }
+ else
+ {
+ // Einige Druckertreiber bereiten Probleme, wenn Buchstaben die
+ // ClipRegion streifen, deshalb lieber ein Pixel mehr...
+ Rectangle aClipRect( aOutRect );
+ if ( pOutDev->GetOutDevType() == OUTDEV_PRINTER )
+ {
+ Size aPixSz( 1, 0 );
+ aPixSz = pOutDev->PixelToLogic( aPixSz );
+ aClipRect.Right() += aPixSz.Width();
+ aClipRect.Bottom() += aPixSz.Width();
+ }
+ pOutDev->IntersectClipRegion( aClipRect );
+ }
+ }
+
+ pImpEditEngine->Paint( pOutDev, aOutRect, aStartPos );
+
+ if ( bMetafile )
+ pOutDev->Pop();
+ else if ( bClipRegion )
+ pOutDev->SetClipRegion( aOldRegion );
+ else
+ pOutDev->SetClipRegion();
+}
+
+void EditEngine::InsertView( EditView* pEditView, sal_uInt16 nIndex )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ DBG_CHKOBJ( pEditView, EditView, 0 );
+
+ if ( nIndex > pImpEditEngine->GetEditViews().Count() )
+ nIndex = pImpEditEngine->GetEditViews().Count();
+
+ pImpEditEngine->GetEditViews().Insert( pEditView, nIndex );
+ EditSelection aStartSel;
+ aStartSel = pImpEditEngine->GetEditDoc().GetStartPaM();
+ pEditView->pImpEditView->SetEditSelection( aStartSel );
+ if ( !pImpEditEngine->GetActiveView() )
+ pImpEditEngine->SetActiveView( pEditView );
+
+ pEditView->pImpEditView->AddDragAndDropListeners();
+}
+
+EditView* EditEngine::RemoveView( EditView* pView )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ DBG_CHKOBJ( pView, EditView, 0 );
+
+ pView->HideCursor();
+ EditView* pRemoved = 0;
+ sal_uInt16 nPos = pImpEditEngine->GetEditViews().GetPos( pView );
+ DBG_ASSERT( nPos != USHRT_MAX, "RemoveView mit ungueltigem Index" );
+ if ( nPos != USHRT_MAX )
+ {
+ pRemoved = pImpEditEngine->GetEditViews().GetObject( nPos );
+ pImpEditEngine->GetEditViews().Remove( nPos );
+ if ( pImpEditEngine->GetActiveView() == pView )
+ {
+ pImpEditEngine->SetActiveView( 0 );
+ pImpEditEngine->GetSelEngine().SetCurView( 0 );
+ }
+ pView->pImpEditView->RemoveDragAndDropListeners();
+
+ }
+ return pRemoved;
+}
+
+EditView* EditEngine::RemoveView( sal_uInt16 nIndex )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ EditView* pView = pImpEditEngine->GetEditViews().GetObject( nIndex );
+ if ( pView )
+ return RemoveView( pView );
+ return NULL;
+}
+
+EditView* EditEngine::GetView( sal_uInt16 nIndex ) const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetEditViews().GetObject( nIndex );
+}
+
+sal_uInt16 EditEngine::GetViewCount() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetEditViews().Count();
+}
+
+sal_Bool EditEngine::HasView( EditView* pView ) const
+{
+ return pImpEditEngine->GetEditViews().GetPos( pView ) != USHRT_MAX;
+}
+
+EditView* EditEngine::GetActiveView() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetActiveView();
+}
+
+void EditEngine::SetActiveView( EditView* pView )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ if ( pView )
+ {
+ DBG_CHKOBJ( pView, EditView, 0 );
+ }
+ pImpEditEngine->SetActiveView( pView );
+}
+
+void EditEngine::SetDefTab( sal_uInt16 nDefTab )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->GetEditDoc().SetDefTab( nDefTab );
+ if ( pImpEditEngine->IsFormatted() )
+ {
+ pImpEditEngine->FormatFullDoc();
+ pImpEditEngine->UpdateViews( (EditView*) 0 );
+ }
+}
+
+sal_uInt16 EditEngine::GetDefTab() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetEditDoc().GetDefTab();
+}
+
+void EditEngine::SetPaperSize( const Size& rNewSize )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+
+ Size aOldSize( pImpEditEngine->GetPaperSize() );
+ pImpEditEngine->SetValidPaperSize( rNewSize );
+ Size aNewSize( pImpEditEngine->GetPaperSize() );
+
+ sal_Bool bAutoPageSize = pImpEditEngine->GetStatus().AutoPageSize();
+ if ( bAutoPageSize || ( aNewSize.Width() != aOldSize.Width() ) )
+ {
+ for ( sal_uInt16 nView = 0; nView < pImpEditEngine->aEditViews.Count(); nView++ )
+ {
+ EditView* pView = pImpEditEngine->aEditViews[nView];
+ DBG_CHKOBJ( pView, EditView, 0 );
+ if ( bAutoPageSize )
+ pView->pImpEditView->RecalcOutputArea();
+ else if ( pView->pImpEditView->DoAutoSize() )
+ {
+ pView->pImpEditView->ResetOutputArea( Rectangle(
+ pView->pImpEditView->GetOutputArea().TopLeft(), aNewSize ) );
+ }
+ }
+
+ if ( bAutoPageSize || pImpEditEngine->IsFormatted() )
+ {
+ // Aendern der Breite hat bei AutoPageSize keine Wirkung, da durch
+ // Textbreite bestimmt.
+ // Optimierung erst nach Vobis-Auslieferung aktivieren...
+// if ( !bAutoPageSize )
+ pImpEditEngine->FormatFullDoc();
+// else
+// {
+// pImpEditEngine->FormatDoc(); // PageSize, falls Aenderung
+// pImpEditEngine->CheckAutoPageSize(); // Falls nichts formatiert wurde
+// }
+
+ pImpEditEngine->UpdateViews( pImpEditEngine->GetActiveView() );
+
+ if ( pImpEditEngine->GetUpdateMode() && pImpEditEngine->GetActiveView() )
+ pImpEditEngine->pActiveView->ShowCursor( sal_False, sal_False );
+ }
+ }
+}
+
+const Size& EditEngine::GetPaperSize() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetPaperSize();
+}
+
+void EditEngine::SetVertical( BOOL bVertical )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetVertical( bVertical );
+}
+
+BOOL EditEngine::IsVertical() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->IsVertical();
+}
+
+void EditEngine::SetFixedCellHeight( BOOL bUseFixedCellHeight )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetFixedCellHeight( bUseFixedCellHeight );
+}
+
+BOOL EditEngine::IsFixedCellHeight() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->IsFixedCellHeight();
+}
+
+void EditEngine::SetDefaultHorizontalTextDirection( EEHorizontalTextDirection eHTextDir )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetDefaultHorizontalTextDirection( eHTextDir );
+}
+
+EEHorizontalTextDirection EditEngine::GetDefaultHorizontalTextDirection() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetDefaultHorizontalTextDirection();
+}
+
+USHORT EditEngine::GetScriptType( const ESelection& rSelection ) const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ EditSelection aSel( pImpEditEngine->CreateSel( rSelection ) );
+ return pImpEditEngine->GetScriptType( aSel );
+}
+
+LanguageType EditEngine::GetLanguage( USHORT nPara, USHORT nPos ) const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ ContentNode* pNode = pImpEditEngine->GetEditDoc().SaveGetObject( nPara );
+ DBG_ASSERT( pNode, "GetLanguage - nPara is invalid!" );
+ return pNode ? pImpEditEngine->GetLanguage( EditPaM( pNode, nPos ) ) : LANGUAGE_DONTKNOW;
+}
+
+
+void EditEngine::TransliterateText( const ESelection& rSelection, sal_Int32 nTransliterationMode )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ pImpEditEngine->TransliterateText( pImpEditEngine->CreateSel( rSelection ), nTransliterationMode );
+}
+
+void EditEngine::SetAsianCompressionMode( USHORT n )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ pImpEditEngine->SetAsianCompressionMode( n );
+}
+
+USHORT EditEngine::GetAsianCompressionMode() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ return pImpEditEngine->GetAsianCompressionMode();
+}
+
+void EditEngine::SetKernAsianPunctuation( BOOL b )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ pImpEditEngine->SetKernAsianPunctuation( b );
+}
+
+BOOL EditEngine::IsKernAsianPunctuation() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ return pImpEditEngine->IsKernAsianPunctuation();
+}
+
+void EditEngine::SetAddExtLeading( BOOL b )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetAddExtLeading( b );
+}
+
+BOOL EditEngine::IsAddExtLeading() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->IsAddExtLeading();
+}
+
+void EditEngine::SetPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ SetPolygon( rPolyPolygon, 0L );
+}
+
+void EditEngine::SetPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::B2DPolyPolygon* pLinePolyPolygon)
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ sal_Bool bSimple(sal_False);
+
+ if(pLinePolyPolygon && 1L == rPolyPolygon.count())
+ {
+ if(rPolyPolygon.getB2DPolygon(0L).isClosed())
+ {
+ // open polygon
+ bSimple = sal_True;
+ }
+ }
+
+ TextRanger* pRanger = new TextRanger( rPolyPolygon, pLinePolyPolygon, 30, 2, 2, bSimple, sal_True );
+ pImpEditEngine->SetTextRanger( pRanger );
+ pImpEditEngine->SetPaperSize( pRanger->GetBoundRect().GetSize() );
+}
+
+void EditEngine::ClearPolygon()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetTextRanger( 0 );
+}
+
+const PolyPolygon* EditEngine::GetPolygon()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetTextRanger() ?
+ &pImpEditEngine->GetTextRanger()->GetPolyPolygon() : NULL;
+}
+
+const Size& EditEngine::GetMinAutoPaperSize() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetMinAutoPaperSize();
+}
+
+void EditEngine::SetMinAutoPaperSize( const Size& rSz )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetMinAutoPaperSize( rSz );
+}
+
+const Size& EditEngine::GetMaxAutoPaperSize() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetMaxAutoPaperSize();
+}
+
+void EditEngine::SetMaxAutoPaperSize( const Size& rSz )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetMaxAutoPaperSize( rSz );
+}
+
+XubString EditEngine::GetText( LineEnd eEnd ) const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetEditDoc().GetText( eEnd );
+}
+
+XubString EditEngine::GetText( const ESelection& rESelection, const LineEnd eEnd ) const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ EditSelection aSel( pImpEditEngine->CreateSel( rESelection ) );
+ return pImpEditEngine->GetSelected( aSel, eEnd );
+}
+
+sal_uInt32 EditEngine::GetTextLen() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetEditDoc().GetTextLen();
+}
+
+sal_uInt16 EditEngine::GetParagraphCount() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->aEditDoc.Count();
+}
+
+sal_uInt16 EditEngine::GetLineCount( sal_uInt16 nParagraph ) const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ if ( !pImpEditEngine->IsFormatted() )
+ pImpEditEngine->FormatDoc();
+ return pImpEditEngine->GetLineCount( nParagraph );
+}
+
+sal_uInt16 EditEngine::GetLineLen( sal_uInt16 nParagraph, sal_uInt16 nLine ) const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ if ( !pImpEditEngine->IsFormatted() )
+ pImpEditEngine->FormatDoc();
+ return pImpEditEngine->GetLineLen( nParagraph, nLine );
+}
+
+void EditEngine::GetLineBoundaries( /*out*/USHORT &rStart, /*out*/USHORT &rEnd, USHORT nParagraph, USHORT nLine ) const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ if ( !pImpEditEngine->IsFormatted() )
+ pImpEditEngine->FormatDoc();
+ return pImpEditEngine->GetLineBoundaries( rStart, rEnd, nParagraph, nLine );
+}
+
+USHORT EditEngine::GetLineNumberAtIndex( USHORT nPara, USHORT nIndex ) const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ if ( !pImpEditEngine->IsFormatted() )
+ pImpEditEngine->FormatDoc();
+ return pImpEditEngine->GetLineNumberAtIndex( nPara, nIndex );
+}
+
+sal_uInt32 EditEngine::GetLineHeight( sal_uInt16 nParagraph, sal_uInt16 nLine )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ // Falls jemand mit einer leeren Engine ein GetLineHeight() macht.
+ if ( !pImpEditEngine->IsFormatted() )
+ pImpEditEngine->FormatDoc();
+ return pImpEditEngine->GetLineHeight( nParagraph, nLine );
+}
+
+sal_uInt16 EditEngine::GetFirstLineOffset( sal_uInt16 nParagraph )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ if ( !pImpEditEngine->IsFormatted() )
+ pImpEditEngine->FormatDoc();
+ ParaPortion* pPortion = pImpEditEngine->GetParaPortions().SaveGetObject( nParagraph );
+ return ( pPortion ? pPortion->GetFirstLineOffset() : 0 );
+}
+
+sal_uInt32 EditEngine::GetTextHeight( sal_uInt16 nParagraph ) const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+
+ if ( !pImpEditEngine->IsFormatted() )
+ pImpEditEngine->FormatDoc();
+
+ sal_uInt32 nHeight = pImpEditEngine->GetParaHeight( nParagraph );
+ return nHeight;
+}
+
+XubString EditEngine::GetWord( sal_uInt16 nPara, sal_uInt16 nIndex )
+{
+ ESelection aESel( nPara, nIndex, nPara, nIndex );
+ EditSelection aSel( pImpEditEngine->CreateSel( aESel ) );
+ aSel = pImpEditEngine->SelectWord( aSel );
+ return pImpEditEngine->GetSelected( aSel );
+}
+
+ESelection EditEngine::GetWord( const ESelection& rSelection, USHORT nWordType ) const
+{
+ // ImpEditEngine-Iteration-Methods should be const!
+ EditEngine* pE = (EditEngine*)this;
+
+ EditSelection aSel( pE->pImpEditEngine->CreateSel( rSelection ) );
+ aSel = pE->pImpEditEngine->SelectWord( aSel, nWordType );
+ return pE->pImpEditEngine->CreateESel( aSel );
+}
+
+ESelection EditEngine::WordLeft( const ESelection& rSelection, USHORT nWordType ) const
+{
+ // ImpEditEngine-Iteration-Methods should be const!
+ EditEngine* pE = (EditEngine*)this;
+
+ EditSelection aSel( pE->pImpEditEngine->CreateSel( rSelection ) );
+ aSel = pE->pImpEditEngine->WordLeft( aSel.Min(), nWordType );
+ return pE->pImpEditEngine->CreateESel( aSel );
+}
+
+ESelection EditEngine::WordRight( const ESelection& rSelection, USHORT nWordType ) const
+{
+ // ImpEditEngine-Iteration-Methods should be const!
+ EditEngine* pE = (EditEngine*)this;
+
+ EditSelection aSel( pE->pImpEditEngine->CreateSel( rSelection ) );
+ aSel = pE->pImpEditEngine->WordRight( aSel.Max(), nWordType );
+ return pE->pImpEditEngine->CreateESel( aSel );
+}
+
+ESelection EditEngine::CursorLeft( const ESelection& rSelection, USHORT nCharacterIteratorMode ) const
+{
+ // ImpEditEngine-Iteration-Methods should be const!
+ EditEngine* pE = (EditEngine*)this;
+
+ EditSelection aSel( pE->pImpEditEngine->CreateSel( rSelection ) );
+ aSel = pE->pImpEditEngine->CursorLeft( aSel.Min(), nCharacterIteratorMode );
+ return pE->pImpEditEngine->CreateESel( aSel );
+}
+
+ESelection EditEngine::CursorRight( const ESelection& rSelection, USHORT nCharacterIteratorMode ) const
+{
+ // ImpEditEngine-Iteration-Methods should be const!
+ EditEngine* pE = (EditEngine*)this;
+
+ EditSelection aSel( pE->pImpEditEngine->CreateSel( rSelection ) );
+ aSel = pE->pImpEditEngine->CursorRight( aSel.Max(), nCharacterIteratorMode );
+ return pE->pImpEditEngine->CreateESel( aSel );
+}
+
+sal_Bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ DBG_CHKOBJ( pEditView, EditView, 0 );
+ DBG_ASSERT( pEditView, "Keine View - keine Kekse !" );
+
+ sal_Bool bDone = sal_True;
+
+ sal_Bool bModified = sal_False;
+ sal_Bool bMoved = sal_False;
+ sal_Bool bAllowIdle = sal_True;
+ sal_Bool bReadOnly = pEditView->IsReadOnly();
+
+ USHORT nNewCursorFlags = 0;
+ BOOL bSetCursorFlags = TRUE;
+
+ EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() );
+ DBG_ASSERT( !aCurSel.IsInvalid(), "Blinde Selection in EditEngine::PostKeyEvent" );
+
+ String aAutoText( pImpEditEngine->GetAutoCompleteText() );
+ if ( pImpEditEngine->GetAutoCompleteText().Len() )
+ pImpEditEngine->SetAutoCompleteText( String(), sal_True );
+
+ sal_uInt16 nCode = rKeyEvent.GetKeyCode().GetCode();
+ KeyFuncType eFunc = rKeyEvent.GetKeyCode().GetFunction();
+ if ( eFunc != KEYFUNC_DONTKNOW )
+ {
+ switch ( eFunc )
+ {
+ case KEYFUNC_UNDO:
+ {
+ if ( !bReadOnly )
+ pEditView->Undo();
+ return sal_True;
+ }
+ // break;
+ case KEYFUNC_REDO:
+ {
+ if ( !bReadOnly )
+ pEditView->Redo();
+ return sal_True;
+ }
+ // break;
+
+ default: // wird dann evtl. unten bearbeitet.
+ eFunc = KEYFUNC_DONTKNOW;
+ }
+ }
+
+ pImpEditEngine->EnterBlockNotifications();
+
+ if ( GetNotifyHdl().IsSet() )
+ {
+ EENotify aNotify( EE_NOTIFY_INPUT_START );
+ aNotify.pEditEngine = this;
+ pImpEditEngine->CallNotify( aNotify );
+ }
+
+ if ( eFunc == KEYFUNC_DONTKNOW )
+ {
+ switch ( nCode )
+ {
+ #if defined( DBG_UTIL ) || (OSL_DEBUG_LEVEL > 1)
+ case KEY_F1:
+ {
+ if ( rKeyEvent.GetKeyCode().IsMod1() && rKeyEvent.GetKeyCode().IsMod2() )
+ {
+ USHORT nParas = GetParagraphCount();
+ Point aPos;
+ Point aViewStart( pEditView->GetOutputArea().TopLeft() );
+ long n20 = 40 * pImpEditEngine->nOnePixelInRef;
+ for ( USHORT n = 0; n < nParas; n++ )
+ {
+ long nH = GetTextHeight( n );
+ Point P1( aViewStart.X() + n20 + n20*(n%2), aViewStart.Y() + aPos.Y() );
+ Point P2( P1 );
+ P2.X() += n20;
+ P2.Y() += nH;
+ pEditView->GetWindow()->SetLineColor();
+ pEditView->GetWindow()->SetFillColor( Color( (n%2) ? COL_YELLOW : COL_LIGHTGREEN ) );
+ pEditView->GetWindow()->DrawRect( Rectangle( P1, P2 ) );
+ aPos.Y() += nH;
+ }
+ }
+ bDone = FALSE;
+ }
+ break;
+ case KEY_F11:
+ {
+ if ( rKeyEvent.GetKeyCode().IsMod1() && rKeyEvent.GetKeyCode().IsMod2() )
+ {
+ bDebugPaint = !bDebugPaint;
+ ByteString aInfo( "DebugPaint: " );
+ aInfo += bDebugPaint ? "On" : "Off";
+ InfoBox( NULL, String( aInfo, RTL_TEXTENCODING_ASCII_US ) ).Execute();
+ }
+ bDone = FALSE;
+ }
+ break;
+ case KEY_F12:
+ {
+ if ( rKeyEvent.GetKeyCode().IsMod1() && rKeyEvent.GetKeyCode().IsMod2() )
+ {
+ EditDbg::ShowEditEngineData( this );
+ #ifdef EDIT_PRINTER_LOG
+ SvFileStream aLog( "d:\\editprn.log", STREAM_WRITE );
+ aLog.Seek( STREAM_SEEK_TO_END );
+ aLog << ' ' << endl << "Debug: ";
+ aLog << GetText( "\n\r" ).GetStr();
+ aLog << endl << endl;
+ aLog << "Ref-Device: " << String( (sal_uInt32)GetRefDevice() ).GetStr() << " Type=" << String( (sal_uInt16)GetRefDevice()->GetOutDevType() ).GetStr() << ", MapX=" << String( GetRefDevice()->GetMapMode().GetScaleX().GetNumerator() ).GetStr() << "/" << String( GetRefDevice()->GetMapMode().GetScaleX().GetDenominator() ).GetStr() <<endl;
+ aLog << "Paper-Width: " << String( GetPaperSize().Width() ).GetStr() << ",\tCalculated: " << String( CalcTextWidth() ).GetStr() << endl;
+ aLog << "Paper-Height: " << String( GetPaperSize().Height() ).GetStr() << ",\tCalculated: " << String( GetTextHeight() ).GetStr() << endl;
+ aLog << endl;
+ #endif
+ }
+ bDone = FALSE;
+ }
+ break;
+ #endif
+ case KEY_UP:
+ case KEY_DOWN:
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ case KEY_HOME:
+ case KEY_END:
+ case KEY_PAGEUP:
+ case KEY_PAGEDOWN:
+ case com::sun::star::awt::Key::MOVE_WORD_FORWARD:
+ case com::sun::star::awt::Key::SELECT_WORD_FORWARD:
+ case com::sun::star::awt::Key::MOVE_WORD_BACKWARD:
+ case com::sun::star::awt::Key::SELECT_WORD_BACKWARD:
+ case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE:
+ case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE:
+ case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE:
+ case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE:
+ case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
+ case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
+ case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
+ case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
+ case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
+ case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT:
+ case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
+ case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT:
+ {
+ if ( !rKeyEvent.GetKeyCode().IsMod2() || ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) )
+ {
+ if ( pImpEditEngine->DoVisualCursorTraveling( aCurSel.Max().GetNode() ) && ( ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) /* || ( nCode == KEY_HOME ) || ( nCode == KEY_END ) */ ) )
+ bSetCursorFlags = FALSE; // Will be manipulated within visual cursor move
+
+ aCurSel = pImpEditEngine->MoveCursor( rKeyEvent, pEditView );
+
+ if ( aCurSel.HasRange() ) {
+ Reference<com::sun::star::datatransfer::clipboard::XClipboard> aSelection(pEditView->GetWindow()->GetPrimarySelection());
+ pEditView->pImpEditView->CutCopy( aSelection, FALSE );
+ }
+
+ bMoved = sal_True;
+ if ( nCode == KEY_HOME )
+ nNewCursorFlags |= GETCRSR_STARTOFLINE;
+ else if ( nCode == KEY_END )
+ nNewCursorFlags |= GETCRSR_ENDOFLINE;
+
+ }
+#if OSL_DEBUG_LEVEL > 1
+ GetLanguage( pImpEditEngine->GetEditDoc().GetPos( aCurSel.Max().GetNode() ), aCurSel.Max().GetIndex() );
+#endif
+ }
+ break;
+ case KEY_BACKSPACE:
+ case KEY_DELETE:
+ case com::sun::star::awt::Key::DELETE_WORD_BACKWARD:
+ case com::sun::star::awt::Key::DELETE_WORD_FORWARD:
+ case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH:
+ case com::sun::star::awt::Key::DELETE_TO_END_OF_PARAGRAPH:
+ {
+ if ( !bReadOnly && !rKeyEvent.GetKeyCode().IsMod2() )
+ {
+ // check if we are behind a bullet and using the backspace key
+ ContentNode *pNode = aCurSel.Min().GetNode();
+ const SvxNumberFormat *pFmt = pImpEditEngine->GetNumberFormat( pNode );
+ if (pFmt && nCode == KEY_BACKSPACE &&
+ !aCurSel.HasRange() && aCurSel.Min().GetIndex() == 0)
+ {
+ // if the bullet is still visible just do not paint it from
+ // now on and that will be all. Otherwise continue as usual.
+ // ...
+
+ USHORT nPara = pImpEditEngine->GetEditDoc().GetPos( pNode );
+ SfxBoolItem aBulletState( (const SfxBoolItem&) pImpEditEngine->GetParaAttrib( nPara, EE_PARA_BULLETSTATE ) );
+ bool bBulletIsVisible = aBulletState.GetValue() ? true : false;
+
+ // just toggling EE_PARA_BULLETSTATE should be fine for both cases...
+ aBulletState.SetValue( !bBulletIsVisible );
+ SfxItemSet aSet( pImpEditEngine->GetParaAttribs( nPara ) );
+ aSet.Put( aBulletState );
+ pImpEditEngine->SetParaAttribs( nPara, aSet );
+
+ // have this and the following paragraphs formatted and repainted.
+ // (not painting a numbering in the list may cause the following
+ // numberings to have different numbers than before and thus the
+ // length may have changed as well )
+ pImpEditEngine->FormatAndUpdate( pImpEditEngine->GetActiveView() );
+
+ if (bBulletIsVisible) // bullet just turned invisible...
+ break;
+ }
+
+ BYTE nDel = 0, nMode = 0;
+ switch( nCode )
+ {
+ case com::sun::star::awt::Key::DELETE_WORD_BACKWARD:
+ nMode = DELMODE_RESTOFWORD;
+ nDel = DEL_LEFT;
+ break;
+ case com::sun::star::awt::Key::DELETE_WORD_FORWARD:
+ nMode = DELMODE_RESTOFWORD;
+ nDel = DEL_RIGHT;
+ break;
+ case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH:
+ nMode = DELMODE_RESTOFCONTENT;
+ nDel = DEL_LEFT;
+ break;
+ case com::sun::star::awt::Key::DELETE_TO_END_OF_PARAGRAPH:
+ nMode = DELMODE_RESTOFCONTENT;
+ nDel = DEL_RIGHT;
+ break;
+ default:
+ nDel = ( nCode == KEY_DELETE ) ? DEL_RIGHT : DEL_LEFT;
+ nMode = rKeyEvent.GetKeyCode().IsMod1() ? DELMODE_RESTOFWORD : DELMODE_SIMPLE;
+ if ( ( nMode == DELMODE_RESTOFWORD ) && rKeyEvent.GetKeyCode().IsShift() )
+ nMode = DELMODE_RESTOFCONTENT;
+ break;
+ }
+
+ pEditView->pImpEditView->DrawSelection();
+ pImpEditEngine->UndoActionStart( EDITUNDO_DELETE );
+ aCurSel = pImpEditEngine->DeleteLeftOrRight( aCurSel, nDel, nMode );
+ pImpEditEngine->UndoActionEnd( EDITUNDO_DELETE );
+ bModified = sal_True;
+ bAllowIdle = sal_False;
+ }
+ }
+ break;
+ case KEY_TAB:
+ {
+ if ( !bReadOnly && !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() )
+ {
+ sal_Bool bShift = rKeyEvent.GetKeyCode().IsShift();
+ if ( pImpEditEngine->GetStatus().DoTabIndenting() &&
+ ( aCurSel.Min().GetNode() != aCurSel.Max().GetNode() ) )
+ {
+ pImpEditEngine->IndentBlock( pEditView, !bShift );
+ }
+ else if ( !bShift )
+ {
+ sal_Bool bSel = pEditView->HasSelection();
+ if ( bSel )
+ pImpEditEngine->UndoActionStart( EDITUNDO_INSERT );
+ if ( pImpEditEngine->GetStatus().DoAutoCorrect() )
+ aCurSel = pImpEditEngine->AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode() );
+ aCurSel = pImpEditEngine->InsertTab( aCurSel );
+ if ( bSel )
+ pImpEditEngine->UndoActionEnd( EDITUNDO_INSERT );
+ bModified = sal_True;
+ }
+ }
+ else
+ bDone = sal_False;
+ }
+ break;
+ case KEY_RETURN:
+ {
+ if ( !bReadOnly )
+ {
+ pEditView->pImpEditView->DrawSelection();
+ if ( !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() )
+ {
+ pImpEditEngine->UndoActionStart( EDITUNDO_INSERT );
+ if ( rKeyEvent.GetKeyCode().IsShift() )
+ {
+ aCurSel = pImpEditEngine->AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode() );
+ aCurSel = pImpEditEngine->InsertLineBreak( aCurSel );
+ }
+ else
+ {
+ if ( !aAutoText.Len() )
+ {
+ if ( pImpEditEngine->GetStatus().DoAutoCorrect() )
+ aCurSel = pImpEditEngine->AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode() );
+ aCurSel = pImpEditEngine->InsertParaBreak( aCurSel );
+ }
+ else
+ {
+ DBG_ASSERT( !aCurSel.HasRange(), "Selektion bei Complete?!" );
+ EditPaM aStart( pImpEditEngine->WordLeft( aCurSel.Max() ) );
+ aCurSel = pImpEditEngine->InsertText(
+ EditSelection( aStart, aCurSel.Max() ), aAutoText );
+ pImpEditEngine->SetAutoCompleteText( String(), sal_True );
+ }
+ }
+ pImpEditEngine->UndoActionEnd( EDITUNDO_INSERT );
+ bModified = sal_True;
+ }
+ }
+ }
+ break;
+ case KEY_INSERT:
+ {
+ if ( !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() )
+ pEditView->SetInsertMode( !pEditView->IsInsertMode() );
+ }
+ break;
+ default:
+ {
+ #if (OSL_DEBUG_LEVEL > 1) && defined(DBG_UTIL)
+ if ( ( nCode == KEY_W ) && rKeyEvent.GetKeyCode().IsMod1() && rKeyEvent.GetKeyCode().IsMod2() )
+ {
+ SfxItemSet aAttribs = pEditView->GetAttribs();
+ const SvxFrameDirectionItem& rCurrentWritingMode = (const SvxFrameDirectionItem&)aAttribs.Get( EE_PARA_WRITINGDIR );
+ SvxFrameDirectionItem aNewItem( FRMDIR_HORI_LEFT_TOP, EE_PARA_WRITINGDIR );
+ if ( rCurrentWritingMode.GetValue() != FRMDIR_HORI_RIGHT_TOP )
+ aNewItem.SetValue( FRMDIR_HORI_RIGHT_TOP );
+ aAttribs.Put( aNewItem );
+ pEditView->SetAttribs( aAttribs );
+ }
+ #endif
+ if ( !bReadOnly && IsSimpleCharInput( rKeyEvent ) )
+ {
+ xub_Unicode nCharCode = rKeyEvent.GetCharCode();
+ pEditView->pImpEditView->DrawSelection();
+ // Autokorrektur ?
+ if ( ( pImpEditEngine->GetStatus().DoAutoCorrect() ) &&
+ SvxAutoCorrect::IsAutoCorrectChar( nCharCode ) )
+ {
+ aCurSel = pImpEditEngine->AutoCorrect( aCurSel, nCharCode, !pEditView->IsInsertMode() );
+ }
+ else
+ {
+ aCurSel = pImpEditEngine->InsertText( (const EditSelection&)aCurSel, nCharCode, !pEditView->IsInsertMode(), sal_True );
+ }
+ // AutoComplete ???
+ if ( pImpEditEngine->GetStatus().DoAutoComplete() && ( nCharCode != ' ' ) )
+ {
+ // Aber nur wenn Wort-Ende...
+ sal_uInt16 nIndex = aCurSel.Max().GetIndex();
+ if ( ( nIndex >= aCurSel.Max().GetNode()->Len() ) ||
+ ( pImpEditEngine->aWordDelimiters.Search( aCurSel.Max().GetNode()->GetChar( nIndex ) ) != STRING_NOTFOUND ) )
+ {
+ EditPaM aStart( pImpEditEngine->WordLeft( aCurSel.Max() ) );
+ String aWord = pImpEditEngine->GetSelected( EditSelection( aStart, aCurSel.Max() ) );
+ if ( aWord.Len() >= 3 )
+ {
+ String aComplete;
+
+ LanguageType eLang = pImpEditEngine->GetLanguage( EditPaM( aStart.GetNode(), aStart.GetIndex()+1));
+ lang::Locale aLocale( MsLangId::convertLanguageToLocale( eLang));
+
+ if (!pImpEditEngine->xLocaleDataWrapper.isInitialized())
+ pImpEditEngine->xLocaleDataWrapper.init( SvtSysLocale().GetLocaleData().getServiceFactory(), aLocale, eLang);
+ else
+ pImpEditEngine->xLocaleDataWrapper.changeLocale( aLocale, eLang);
+
+ if (!pImpEditEngine->xTransliterationWrapper.isInitialized())
+ pImpEditEngine->xTransliterationWrapper.init( SvtSysLocale().GetLocaleData().getServiceFactory(), eLang, i18n::TransliterationModules_IGNORE_CASE);
+ else
+ pImpEditEngine->xTransliterationWrapper.changeLocale( eLang);
+
+ const ::utl::TransliterationWrapper* pTransliteration = pImpEditEngine->xTransliterationWrapper.get();
+ Sequence< i18n::CalendarItem > xItem = pImpEditEngine->xLocaleDataWrapper->getDefaultCalendarDays();
+ sal_Int32 nCount = xItem.getLength();
+ const i18n::CalendarItem* pArr = xItem.getArray();
+ for( sal_Int32 n = 0; n <= nCount; ++n )
+ {
+ const ::rtl::OUString& rDay = pArr[n].FullName;
+ if( pTransliteration->isMatch( aWord, rDay) )
+ {
+ aComplete = rDay;
+ break;
+ }
+ }
+
+ if ( !aComplete.Len() )
+ {
+ xItem = pImpEditEngine->xLocaleDataWrapper->getDefaultCalendarMonths();
+ sal_Int32 nMonthCount = xItem.getLength();
+ const i18n::CalendarItem* pMonthArr = xItem.getArray();
+ for( sal_Int32 n = 0; n <= nMonthCount; ++n )
+ {
+ const ::rtl::OUString& rMon = pMonthArr[n].FullName;
+ if( pTransliteration->isMatch( aWord, rMon) )
+ {
+ aComplete = rMon;
+ break;
+ }
+ }
+ }
+
+ if( aComplete.Len() && ( ( aWord.Len() + 1 ) < aComplete.Len() ) )
+ {
+ pImpEditEngine->SetAutoCompleteText( aComplete, sal_False );
+ Point aPos = pImpEditEngine->PaMtoEditCursor( aCurSel.Max() ).TopLeft();
+ aPos = pEditView->pImpEditView->GetWindowPos( aPos );
+ aPos = pEditView->pImpEditView->GetWindow()->LogicToPixel( aPos );
+ aPos = pEditView->GetWindow()->OutputToScreenPixel( aPos );
+ aPos.Y() -= 3;
+ Help::ShowQuickHelp( pEditView->GetWindow(), Rectangle( aPos, Size( 1, 1 ) ), aComplete, QUICKHELP_BOTTOM|QUICKHELP_LEFT );
+ }
+ }
+ }
+ }
+ bModified = sal_True;
+ }
+ else
+ bDone = sal_False;
+ }
+ }
+ }
+
+ pEditView->pImpEditView->SetEditSelection( aCurSel );
+ pImpEditEngine->UpdateSelections();
+
+ if ( ( !IsVertical() && ( nCode != KEY_UP ) && ( nCode != KEY_DOWN ) ) ||
+ ( IsVertical() && ( nCode != KEY_LEFT ) && ( nCode != KEY_RIGHT ) ))
+ {
+ pEditView->pImpEditView->nTravelXPos = TRAVEL_X_DONTKNOW;
+ }
+
+ if ( /* ( nCode != KEY_HOME ) && ( nCode != KEY_END ) && */
+ ( !IsVertical() && ( nCode != KEY_LEFT ) && ( nCode != KEY_RIGHT ) ) ||
+ ( IsVertical() && ( nCode != KEY_UP ) && ( nCode != KEY_DOWN ) ))
+ {
+ pEditView->pImpEditView->SetCursorBidiLevel( 0xFFFF );
+ }
+
+ if ( bSetCursorFlags )
+ pEditView->pImpEditView->nExtraCursorFlags = nNewCursorFlags;
+
+ if ( bModified )
+ {
+ DBG_ASSERT( !bReadOnly, "ReadOnly but modified???" );
+ // Idle-Formatter nur, wenn AnyInput.
+ if ( bAllowIdle && pImpEditEngine->GetStatus().UseIdleFormatter()
+ && Application::AnyInput( INPUT_KEYBOARD) )
+ pImpEditEngine->IdleFormatAndUpdate( pEditView );
+ else
+ pImpEditEngine->FormatAndUpdate( pEditView );
+ }
+ else if ( bMoved )
+ {
+ sal_Bool bGotoCursor = pEditView->pImpEditView->DoAutoScroll();
+ pEditView->pImpEditView->ShowCursor( bGotoCursor, sal_True );
+ pImpEditEngine->CallStatusHdl();
+ }
+
+ if ( GetNotifyHdl().IsSet() )
+ {
+ EENotify aNotify( EE_NOTIFY_INPUT_END );
+ aNotify.pEditEngine = this;
+ pImpEditEngine->CallNotify( aNotify );
+ }
+
+ pImpEditEngine->LeaveBlockNotifications();
+
+ return bDone;
+}
+
+sal_uInt32 EditEngine::GetTextHeight() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+
+ if ( !pImpEditEngine->IsFormatted() )
+ pImpEditEngine->FormatDoc();
+
+ sal_uInt32 nHeight = !IsVertical() ? pImpEditEngine->GetTextHeight() : pImpEditEngine->CalcTextWidth( TRUE );
+ return nHeight;
+}
+
+sal_uInt32 EditEngine::CalcTextWidth()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+
+ if ( !pImpEditEngine->IsFormatted() )
+ pImpEditEngine->FormatDoc();
+
+ sal_uInt32 nWidth = !IsVertical() ? pImpEditEngine->CalcTextWidth( TRUE ) : pImpEditEngine->GetTextHeight();
+ return nWidth;
+}
+
+void EditEngine::SetUpdateMode( sal_Bool bUpdate )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetUpdateMode( bUpdate );
+ if ( pImpEditEngine->pActiveView )
+ pImpEditEngine->pActiveView->ShowCursor( sal_False, sal_False );
+}
+
+sal_Bool EditEngine::GetUpdateMode() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetUpdateMode();
+}
+
+void EditEngine::Clear()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->Clear();
+}
+
+void EditEngine::SetText( const XubString& rText )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetText( rText );
+ if ( rText.Len() )
+ pImpEditEngine->FormatAndUpdate();
+}
+
+ULONG EditEngine::Read( SvStream& rInput, const String& rBaseURL, EETextFormat eFormat, SvKeyValueIterator* pHTTPHeaderAttrs /* = NULL */ )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ sal_Bool bUndoEnabled = pImpEditEngine->IsUndoEnabled();
+ pImpEditEngine->EnableUndo( sal_False );
+ pImpEditEngine->SetText( XubString() );
+ EditPaM aPaM( pImpEditEngine->GetEditDoc().GetStartPaM() );
+ pImpEditEngine->Read( rInput, rBaseURL, eFormat, EditSelection( aPaM, aPaM ), pHTTPHeaderAttrs );
+ pImpEditEngine->EnableUndo( bUndoEnabled );
+ return rInput.GetError();
+}
+
+ULONG EditEngine::Write( SvStream& rOutput, EETextFormat eFormat )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ EditPaM aStartPaM( pImpEditEngine->GetEditDoc().GetStartPaM() );
+ EditPaM aEndPaM( pImpEditEngine->GetEditDoc().GetEndPaM() );
+ pImpEditEngine->Write( rOutput, eFormat, EditSelection( aStartPaM, aEndPaM ) );
+ return rOutput.GetError();
+}
+
+EditTextObject* EditEngine::CreateTextObject()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->CreateTextObject();
+}
+
+EditTextObject* EditEngine::CreateTextObject( const ESelection& rESelection )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ EditSelection aSel( pImpEditEngine->CreateSel( rESelection ) );
+ return pImpEditEngine->CreateTextObject( aSel );
+}
+
+void EditEngine::SetText( const EditTextObject& rTextObject )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->EnterBlockNotifications();
+ pImpEditEngine->SetText( rTextObject );
+ pImpEditEngine->FormatAndUpdate();
+ pImpEditEngine->LeaveBlockNotifications();
+}
+
+void EditEngine::ShowParagraph( sal_uInt16 nParagraph, sal_Bool bShow )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->ShowParagraph( nParagraph, bShow );
+}
+
+sal_Bool EditEngine::IsParagraphVisible( sal_uInt16 nParagraph )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->IsParagraphVisible( nParagraph );
+}
+
+void EditEngine::SetNotifyHdl( const Link& rLink )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetNotifyHdl( rLink );
+}
+
+Link EditEngine::GetNotifyHdl() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetNotifyHdl();
+}
+
+void EditEngine::SetStatusEventHdl( const Link& rLink )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetStatusEventHdl( rLink );
+}
+
+Link EditEngine::GetStatusEventHdl() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetStatusEventHdl();
+}
+
+void EditEngine::SetImportHdl( const Link& rLink )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->aImportHdl = rLink;
+}
+
+Link EditEngine::GetImportHdl() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->aImportHdl;
+}
+
+void EditEngine::SetBeginMovingParagraphsHdl( const Link& rLink )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->aBeginMovingParagraphsHdl = rLink;
+}
+
+void EditEngine::SetEndMovingParagraphsHdl( const Link& rLink )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->aEndMovingParagraphsHdl = rLink;
+}
+
+void EditEngine::SetBeginPasteOrDropHdl( const Link& rLink )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+
+ pImpEditEngine->aBeginPasteOrDropHdl = rLink;
+}
+
+void EditEngine::SetEndPasteOrDropHdl( const Link& rLink )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->aEndPasteOrDropHdl = rLink;
+}
+
+EditTextObject* EditEngine::CreateTextObject( sal_uInt16 nPara, sal_uInt16 nParas )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ DBG_ASSERT( nPara < pImpEditEngine->GetEditDoc().Count(), "CreateTextObject: Startpara out of Range" );
+ DBG_ASSERT( nPara+nParas-1 < pImpEditEngine->GetEditDoc().Count(), "CreateTextObject: Endpara out of Range" );
+
+ ContentNode* pStartNode = pImpEditEngine->GetEditDoc().SaveGetObject( nPara );
+ ContentNode* pEndNode = pImpEditEngine->GetEditDoc().SaveGetObject( nPara+nParas-1 );
+ DBG_ASSERT( pStartNode, "Start-Absatz existiert nicht: CreateTextObject" );
+ DBG_ASSERT( pEndNode, "End-Absatz existiert nicht: CreateTextObject" );
+
+ if ( pStartNode && pEndNode )
+ {
+ EditSelection aTmpSel;
+ aTmpSel.Min() = EditPaM( pStartNode, 0 );
+ aTmpSel.Max() = EditPaM( pEndNode, pEndNode->Len() );
+ return pImpEditEngine->CreateTextObject( aTmpSel );
+ }
+ return 0;
+}
+
+void EditEngine::RemoveParagraph( sal_uInt16 nPara )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ DBG_ASSERT( pImpEditEngine->GetEditDoc().Count() > 1, "Der erste Absatz darf nicht geloescht werden!" );
+ if( pImpEditEngine->GetEditDoc().Count() <= 1 )
+ return;
+
+ ContentNode* pNode = pImpEditEngine->GetEditDoc().SaveGetObject( nPara );
+ ParaPortion* pPortion = pImpEditEngine->GetParaPortions().SaveGetObject( nPara );
+ DBG_ASSERT( pPortion && pNode, "Absatz nicht gefunden: RemoveParagraph" );
+ if ( pNode && pPortion )
+ {
+ // Keine Undokappselung noetig.
+ pImpEditEngine->ImpRemoveParagraph( nPara );
+ pImpEditEngine->InvalidateFromParagraph( nPara );
+ pImpEditEngine->UpdateSelections();
+ pImpEditEngine->FormatAndUpdate();
+ }
+}
+
+sal_uInt16 EditEngine::GetTextLen( sal_uInt16 nPara ) const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ ContentNode* pNode = pImpEditEngine->GetEditDoc().SaveGetObject( nPara );
+ DBG_ASSERT( pNode, "Absatz nicht gefunden: GetTextLen" );
+ if ( pNode )
+ return pNode->Len();
+ return 0;
+}
+
+XubString EditEngine::GetText( sal_uInt16 nPara ) const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ XubString aStr;
+ if ( nPara < pImpEditEngine->GetEditDoc().Count() )
+ aStr = pImpEditEngine->GetEditDoc().GetParaAsString( nPara );
+ return aStr;
+}
+
+void EditEngine::SetModifyHdl( const Link& rLink )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetModifyHdl( rLink );
+}
+
+Link EditEngine::GetModifyHdl() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetModifyHdl();
+}
+
+
+void EditEngine::ClearModifyFlag()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetModifyFlag( sal_False );
+}
+
+void EditEngine::SetModified()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetModifyFlag( sal_True );
+}
+
+sal_Bool EditEngine::IsModified() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->IsModified();
+}
+
+sal_Bool EditEngine::IsInSelectionMode() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return ( pImpEditEngine->IsInSelectionMode() ||
+ pImpEditEngine->GetSelEngine().IsInSelection() );
+}
+
+void EditEngine::StopSelectionMode()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->StopSelectionMode();
+}
+
+void EditEngine::InsertParagraph( sal_uInt16 nPara, const EditTextObject& rTxtObj )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ if ( nPara > GetParagraphCount() )
+ {
+ DBG_ASSERTWARNING( nPara == USHRT_MAX, "AbsatzNr zu Gro???, aber nicht LIST_APPEND! " );
+ nPara = GetParagraphCount();
+ }
+
+ pImpEditEngine->UndoActionStart( EDITUNDO_INSERT );
+
+ // Keine Undoklammerung noetig.
+ EditPaM aPaM( pImpEditEngine->InsertParagraph( nPara ) );
+ // Bei einem InsertParagraph von aussen sollen keine Harten
+ // Attribute uebernommen werden !
+ pImpEditEngine->RemoveCharAttribs( nPara );
+ pImpEditEngine->InsertText( rTxtObj, EditSelection( aPaM, aPaM ) );
+
+ pImpEditEngine->UndoActionEnd( EDITUNDO_INSERT );
+
+ pImpEditEngine->FormatAndUpdate();
+}
+
+void EditEngine::InsertParagraph( sal_uInt16 nPara, const XubString& rTxt )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ if ( nPara > GetParagraphCount() )
+ {
+ DBG_ASSERTWARNING( nPara == USHRT_MAX, "AbsatzNr zu Gro???, aber nicht LIST_APPEND! " );
+ nPara = GetParagraphCount();
+ }
+
+ pImpEditEngine->UndoActionStart( EDITUNDO_INSERT );
+ EditPaM aPaM( pImpEditEngine->InsertParagraph( nPara ) );
+ // Bei einem InsertParagraph von aussen sollen keine Harten
+ // Attribute uebernommen werden !
+ pImpEditEngine->RemoveCharAttribs( nPara );
+ pImpEditEngine->UndoActionEnd( EDITUNDO_INSERT );
+ pImpEditEngine->ImpInsertText( EditSelection( aPaM, aPaM ), rTxt );
+ pImpEditEngine->FormatAndUpdate();
+}
+
+void EditEngine::SetText( sal_uInt16 nPara, const EditTextObject& rTxtObj )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ EditSelection* pSel = pImpEditEngine->SelectParagraph( nPara );
+ if ( pSel )
+ {
+ pImpEditEngine->UndoActionStart( EDITUNDO_INSERT );
+ pImpEditEngine->InsertText( rTxtObj, *pSel );
+ pImpEditEngine->UndoActionEnd( EDITUNDO_INSERT );
+ pImpEditEngine->FormatAndUpdate();
+ delete pSel;
+ }
+}
+
+void EditEngine::SetText( sal_uInt16 nPara, const XubString& rTxt )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ EditSelection* pSel = pImpEditEngine->SelectParagraph( nPara );
+ if ( pSel )
+ {
+ pImpEditEngine->UndoActionStart( EDITUNDO_INSERT );
+ pImpEditEngine->ImpInsertText( *pSel, rTxt );
+ pImpEditEngine->UndoActionEnd( EDITUNDO_INSERT );
+ pImpEditEngine->FormatAndUpdate();
+ delete pSel;
+ }
+}
+
+void EditEngine::SetParaAttribs( sal_uInt16 nPara, const SfxItemSet& rSet )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ // Keine Undoklammerung noetig.
+ pImpEditEngine->SetParaAttribs( nPara, rSet );
+ pImpEditEngine->FormatAndUpdate();
+}
+
+const SfxItemSet& EditEngine::GetParaAttribs( sal_uInt16 nPara ) const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetParaAttribs( nPara );
+}
+
+sal_Bool EditEngine::HasParaAttrib( sal_uInt16 nPara, sal_uInt16 nWhich ) const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->HasParaAttrib( nPara, nWhich );
+}
+
+const SfxPoolItem& EditEngine::GetParaAttrib( sal_uInt16 nPara, sal_uInt16 nWhich )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetParaAttrib( nPara, nWhich );
+}
+
+void EditEngine::GetCharAttribs( sal_uInt16 nPara, EECharAttribArray& rLst ) const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->GetCharAttribs( nPara, rLst );
+}
+
+SfxItemSet EditEngine::GetAttribs( const ESelection& rSel, BOOL bOnlyHardAttrib )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ EditSelection aSel( pImpEditEngine->
+ ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) );
+ return pImpEditEngine->GetAttribs( aSel, bOnlyHardAttrib );
+}
+
+SfxItemSet EditEngine::GetAttribs( USHORT nPara, USHORT nStart, USHORT nEnd, sal_uInt8 nFlags ) const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetAttribs( nPara, nStart, nEnd, nFlags );
+}
+
+void EditEngine::RemoveAttribs( const ESelection& rSelection, sal_Bool bRemoveParaAttribs, sal_uInt16 nWhich )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+
+ pImpEditEngine->UndoActionStart( EDITUNDO_RESETATTRIBS );
+ EditSelection aSel( pImpEditEngine->ConvertSelection( rSelection.nStartPara, rSelection.nStartPos, rSelection.nEndPara, rSelection.nEndPos ) );
+ pImpEditEngine->RemoveCharAttribs( aSel, bRemoveParaAttribs, nWhich );
+ pImpEditEngine->UndoActionEnd( EDITUNDO_RESETATTRIBS );
+ pImpEditEngine->FormatAndUpdate();
+}
+
+// MT: Can be removed after 6.x?
+Font EditEngine::GetStandardFont( sal_uInt16 nPara )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return GetStandardSvxFont( nPara );
+}
+
+SvxFont EditEngine::GetStandardSvxFont( sal_uInt16 nPara )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ ContentNode* pNode = pImpEditEngine->GetEditDoc().SaveGetObject( nPara );
+ return pNode->GetCharAttribs().GetDefFont();
+}
+
+void EditEngine::StripPortions()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ VirtualDevice aTmpDev;
+ Rectangle aBigRec( Point( 0, 0 ), Size( 0x7FFFFFFF, 0x7FFFFFFF ) );
+ if ( IsVertical() )
+ {
+ aBigRec.Right() = 0;
+ aBigRec.Left() = -0x7FFFFFFF;
+ }
+ pImpEditEngine->Paint( &aTmpDev, aBigRec, Point(), sal_True );
+}
+
+void EditEngine::GetPortions( sal_uInt16 nPara, SvUShorts& rList )
+{
+ if ( !pImpEditEngine->IsFormatted() )
+ pImpEditEngine->FormatFullDoc();
+
+ ParaPortion* pParaPortion = pImpEditEngine->GetParaPortions().SaveGetObject( nPara );
+ if ( pParaPortion )
+ {
+ sal_uInt16 nEnd = 0;
+ sal_uInt16 nTextPortions = pParaPortion->GetTextPortions().Count();
+ for ( sal_uInt16 n = 0; n < nTextPortions; n++ )
+ {
+ nEnd = nEnd + pParaPortion->GetTextPortions()[n]->GetLen();
+ rList.Insert( nEnd, rList.Count() );
+ }
+ }
+}
+
+void EditEngine::SetFlatMode( sal_Bool bFlat)
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetFlatMode( bFlat );
+}
+
+sal_Bool EditEngine::IsFlatMode() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return !( pImpEditEngine->aStatus.UseCharAttribs() );
+}
+
+void EditEngine::SetControlWord( sal_uInt32 nWord )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+
+ if ( nWord != pImpEditEngine->aStatus.GetControlWord() )
+ {
+ sal_uInt32 nPrev = pImpEditEngine->aStatus.GetControlWord();
+ pImpEditEngine->aStatus.GetControlWord() = nWord;
+
+ sal_uInt32 nChanges = nPrev ^ nWord;
+ if ( pImpEditEngine->IsFormatted() )
+ {
+ // ggf. neu formatieren:
+ if ( ( nChanges & EE_CNTRL_USECHARATTRIBS ) ||
+ ( nChanges & EE_CNTRL_USEPARAATTRIBS ) ||
+ ( nChanges & EE_CNTRL_ONECHARPERLINE ) ||
+ ( nChanges & EE_CNTRL_STRETCHING ) ||
+ ( nChanges & EE_CNTRL_OUTLINER ) ||
+ ( nChanges & EE_CNTRL_NOCOLORS ) ||
+ ( nChanges & EE_CNTRL_OUTLINER2 ) )
+ {
+ if ( ( nChanges & EE_CNTRL_USECHARATTRIBS ) ||
+ ( nChanges & EE_CNTRL_USEPARAATTRIBS ) )
+ {
+ sal_Bool bUseCharAttribs = ( nWord & EE_CNTRL_USECHARATTRIBS ) ? sal_True : sal_False;
+ pImpEditEngine->GetEditDoc().CreateDefFont( bUseCharAttribs );
+ }
+
+ pImpEditEngine->FormatFullDoc();
+ pImpEditEngine->UpdateViews( pImpEditEngine->GetActiveView() );
+ }
+ }
+
+ sal_Bool bSpellingChanged = nChanges & EE_CNTRL_ONLINESPELLING ? sal_True : sal_False;
+
+ if ( bSpellingChanged )
+ {
+ pImpEditEngine->StopOnlineSpellTimer();
+ if ( bSpellingChanged && ( nWord & EE_CNTRL_ONLINESPELLING ) )
+ {
+ // WrongListen anlegen, Timer starten...
+ sal_uInt16 nNodes = pImpEditEngine->GetEditDoc().Count();
+ for ( sal_uInt16 n = 0; n < nNodes; n++ )
+ {
+ ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( n );
+ pNode->CreateWrongList();
+ }
+ pImpEditEngine->StartOnlineSpellTimer();
+ }
+ else
+ {
+ long nY = 0;
+ sal_uInt16 nNodes = pImpEditEngine->GetEditDoc().Count();
+ for ( sal_uInt16 n = 0; n < nNodes; n++ )
+ {
+ ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( n );
+ ParaPortion* pPortion = pImpEditEngine->GetParaPortions().GetObject( n );
+ sal_Bool bWrongs = ( bSpellingChanged || ( nWord & EE_CNTRL_ONLINESPELLING ) ) ? pNode->GetWrongList()->HasWrongs() : sal_False;
+ if ( bSpellingChanged ) // Also aus
+ pNode->DestroyWrongList(); // => vorm Paint weghaun.
+ if ( bWrongs )
+ {
+ pImpEditEngine->aInvalidRec.Left() = 0;
+ pImpEditEngine->aInvalidRec.Right() = pImpEditEngine->GetPaperSize().Width();
+ pImpEditEngine->aInvalidRec.Top() = nY+1;
+ pImpEditEngine->aInvalidRec.Bottom() = nY+pPortion->GetHeight()-1;
+ pImpEditEngine->UpdateViews( pImpEditEngine->pActiveView );
+ }
+ nY += pPortion->GetHeight();
+ }
+ }
+ }
+ }
+}
+
+sal_uInt32 EditEngine::GetControlWord() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->aStatus.GetControlWord();
+}
+
+long EditEngine::GetFirstLineStartX( sal_uInt16 nParagraph )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+
+ long nX = 0;
+ ParaPortion* pPPortion = pImpEditEngine->GetParaPortions().SaveGetObject( nParagraph );
+ if ( pPPortion )
+ {
+ DBG_ASSERT( pImpEditEngine->IsFormatted() || !pImpEditEngine->IsFormatting(), "GetFirstLineStartX: Doc not formatted - unable to format!" );
+ if ( !pImpEditEngine->IsFormatted() )
+ pImpEditEngine->FormatDoc();
+ EditLine* pFirstLine = pPPortion->GetLines()[0];
+ nX = pFirstLine->GetStartPosX();
+ }
+ return nX;
+}
+
+Point EditEngine::GetDocPos( const Point& rPaperPos ) const
+{
+ Point aDocPos( rPaperPos );
+ if ( IsVertical() )
+ {
+ aDocPos.X() = rPaperPos.Y();
+ aDocPos.Y() = GetPaperSize().Width() - rPaperPos.X();
+ }
+ return aDocPos;
+}
+
+Point EditEngine::GetDocPosTopLeft( sal_uInt16 nParagraph )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ ParaPortion* pPPortion = pImpEditEngine->GetParaPortions().SaveGetObject( nParagraph );
+ DBG_ASSERT( pPPortion, "Absatz nicht gefunden: GetWindowPosTopLeft" );
+ Point aPoint;
+ if ( pPPortion )
+ {
+ // Falls jemand mit einer leeren Engine ein GetLineHeight() macht.
+ DBG_ASSERT( pImpEditEngine->IsFormatted() || !pImpEditEngine->IsFormatting(), "GetDocPosTopLeft: Doc not formatted - unable to format!" );
+ if ( !pImpEditEngine->IsFormatted() )
+ pImpEditEngine->FormatAndUpdate();
+ if ( pPPortion->GetLines().Count() )
+ {
+ // So richtiger, falls grosses Bullet.
+ EditLine* pFirstLine = pPPortion->GetLines()[0];
+ aPoint.X() = pFirstLine->GetStartPosX();
+ }
+ else
+ {
+ const SvxLRSpaceItem& rLRItem = pImpEditEngine->GetLRSpaceItem( pPPortion->GetNode() );
+// TL_NF_LR aPoint.X() = pImpEditEngine->GetXValue( (short)(rLRItem.GetTxtLeft() + rLRItem.GetTxtFirstLineOfst()) );
+ sal_Int32 nSpaceBefore = 0;
+ pImpEditEngine->GetSpaceBeforeAndMinLabelWidth( pPPortion->GetNode(), &nSpaceBefore );
+ short nX = (short)(rLRItem.GetTxtLeft()
+ + rLRItem.GetTxtFirstLineOfst()
+ + nSpaceBefore);
+ aPoint.X() = pImpEditEngine->GetXValue( nX
+ );
+ }
+ aPoint.Y() = pImpEditEngine->GetParaPortions().GetYOffset( pPPortion );
+ }
+ return aPoint;
+}
+
+const SvxNumberFormat* EditEngine::GetNumberFormat( USHORT nPara ) const
+{
+ // derived objects may overload this function to give access to
+ // bullet information (see Outliner)
+ (void) nPara;
+ return 0;
+}
+
+BOOL EditEngine::IsRightToLeft( USHORT nPara ) const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->IsRightToLeft( nPara );
+}
+
+sal_Bool EditEngine::IsTextPos( const Point& rPaperPos, sal_uInt16 nBorder )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+
+ if ( !pImpEditEngine->IsFormatted() )
+ pImpEditEngine->FormatDoc();
+
+ sal_Bool bTextPos = sal_False;
+ // #90780# take unrotated positions for calculation here
+ Point aDocPos = GetDocPos( rPaperPos );
+
+ if ( ( aDocPos.Y() > 0 ) && ( aDocPos.Y() < (long)pImpEditEngine->GetTextHeight() ) )
+ {
+ EditPaM aPaM = pImpEditEngine->GetPaM( aDocPos, sal_False );
+ if ( aPaM.GetNode() )
+ {
+ ParaPortion* pParaPortion = pImpEditEngine->FindParaPortion( aPaM.GetNode() );
+ DBG_ASSERT( pParaPortion, "ParaPortion?" );
+
+ sal_uInt16 nLine = pParaPortion->GetLineNumber( aPaM.GetIndex() );
+ EditLine* pLine = pParaPortion->GetLines().GetObject( nLine );
+ Range aLineXPosStartEnd = pImpEditEngine->GetLineXPosStartEnd( pParaPortion, pLine );
+ if ( ( aDocPos.X() >= aLineXPosStartEnd.Min() - nBorder ) &&
+ ( aDocPos.X() <= aLineXPosStartEnd.Max() + nBorder ) )
+ {
+ bTextPos = sal_True;
+ }
+ }
+ }
+ return bTextPos;
+}
+
+void EditEngine::SetEditTextObjectPool( SfxItemPool* pPool )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetEditTextObjectPool( pPool );
+}
+
+SfxItemPool* EditEngine::GetEditTextObjectPool() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetEditTextObjectPool();
+}
+
+void EditEngine::QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+
+ EditSelection aSel( pImpEditEngine->
+ ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) );
+
+ pImpEditEngine->SetAttribs( aSel, rSet );
+}
+
+void EditEngine::QuickMarkInvalid( const ESelection& rSel )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ DBG_ASSERT( rSel.nStartPara < pImpEditEngine->GetEditDoc().Count(), "MarkInvalid: Start out of Range!" );
+ DBG_ASSERT( rSel.nEndPara < pImpEditEngine->GetEditDoc().Count(), "MarkInvalid: End out of Range!" );
+ for ( sal_uInt16 nPara = rSel.nStartPara; nPara <= rSel.nEndPara; nPara++ )
+ {
+ ParaPortion* pPortion = pImpEditEngine->GetParaPortions().SaveGetObject( nPara );
+ if ( pPortion )
+ pPortion->MarkSelectionInvalid( 0, pPortion->GetNode()->Len() );
+ }
+}
+
+void EditEngine::QuickInsertText( const XubString& rText, const ESelection& rSel )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+
+ EditSelection aSel( pImpEditEngine->
+ ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) );
+
+ pImpEditEngine->ImpInsertText( aSel, rText );
+}
+
+void EditEngine::QuickDelete( const ESelection& rSel )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+
+ EditSelection aSel( pImpEditEngine->
+ ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) );
+
+ pImpEditEngine->ImpDeleteSelection( aSel );
+}
+
+void EditEngine::QuickMarkToBeRepainted( sal_uInt16 nPara )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ ParaPortion* pPortion = pImpEditEngine->GetParaPortions().SaveGetObject( nPara );
+ if ( pPortion )
+ pPortion->SetMustRepaint( sal_True );
+}
+
+void EditEngine::QuickInsertLineBreak( const ESelection& rSel )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+
+ EditSelection aSel( pImpEditEngine->
+ ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) );
+
+ pImpEditEngine->InsertLineBreak( aSel );
+}
+
+void EditEngine::QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+
+ EditSelection aSel( pImpEditEngine->
+ ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) );
+
+ pImpEditEngine->ImpInsertFeature( aSel, rFld );
+}
+
+void EditEngine::QuickFormatDoc( sal_Bool bFull )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ if ( bFull )
+ pImpEditEngine->FormatFullDoc();
+ else
+ pImpEditEngine->FormatDoc();
+
+ // #111072# Don't pass active view, maybe selection is not updated yet...
+ pImpEditEngine->UpdateViews( NULL );
+}
+
+void EditEngine::QuickRemoveCharAttribs( sal_uInt16 nPara, sal_uInt16 nWhich )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->RemoveCharAttribs( nPara, nWhich );
+}
+
+void EditEngine::SetStyleSheet( sal_uInt16 nPara, SfxStyleSheet* pStyle )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetStyleSheet( nPara, pStyle );
+}
+
+SfxStyleSheet* EditEngine::GetStyleSheet( sal_uInt16 nPara ) const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetStyleSheet( nPara );
+}
+
+void EditEngine::SetStyleSheetPool( SfxStyleSheetPool* pSPool )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetStyleSheetPool( pSPool );
+}
+
+SfxStyleSheetPool* EditEngine::GetStyleSheetPool()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetStyleSheetPool();
+}
+
+void EditEngine::SetWordDelimiters( const XubString& rDelimiters )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->aWordDelimiters = rDelimiters;
+ if ( pImpEditEngine->aWordDelimiters.Search( CH_FEATURE ) == STRING_NOTFOUND )
+ pImpEditEngine->aWordDelimiters.Insert( CH_FEATURE );
+}
+
+XubString EditEngine::GetWordDelimiters() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->aWordDelimiters;
+}
+
+void EditEngine::SetGroupChars( const XubString& rChars )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ DBG_ASSERT( ( rChars.Len() % 2 ) == 0, "SetGroupChars: Ungerade Anzahl!" );
+ pImpEditEngine->aGroupChars = rChars;
+}
+
+XubString EditEngine::GetGroupChars() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->aGroupChars;
+}
+
+void EditEngine::EnablePasteSpecial( sal_Bool bEnable )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ if ( bEnable )
+ pImpEditEngine->GetStatus().TurnOnFlags( EE_CNTRL_PASTESPECIAL );
+ else
+ pImpEditEngine->GetStatus().TurnOffFlags( EE_CNTRL_PASTESPECIAL );
+}
+
+sal_Bool EditEngine::IsPasteSpecialEnabled() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetStatus().AllowPasteSpecial();
+}
+
+void EditEngine::EnableIdleFormatter( sal_Bool bEnable )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ if ( bEnable )
+ pImpEditEngine->GetStatus().TurnOnFlags( EE_CNTRL_DOIDLEFORMAT );
+ else
+ pImpEditEngine->GetStatus().TurnOffFlags( EE_CNTRL_DOIDLEFORMAT);
+}
+
+sal_Bool EditEngine::IsIdleFormatterEnabled() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetStatus().UseIdleFormatter();
+}
+
+void EditEngine::EraseVirtualDevice()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->EraseVirtualDevice();
+}
+
+void EditEngine::SetSpeller( Reference< XSpellChecker1 > &xSpeller )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetSpeller( xSpeller );
+}
+Reference< XSpellChecker1 > EditEngine::GetSpeller()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetSpeller();
+}
+Reference< XHyphenator > EditEngine::GetHyphenator() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetHyphenator();
+}
+
+void EditEngine::SetHyphenator( Reference< XHyphenator > & xHyph )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetHyphenator( xHyph );
+}
+
+void EditEngine::SetForbiddenCharsTable( vos::ORef<SvxForbiddenCharactersTable> xForbiddenChars )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetForbiddenCharsTable( xForbiddenChars );
+}
+
+vos::ORef<SvxForbiddenCharactersTable> EditEngine::GetForbiddenCharsTable() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetForbiddenCharsTable( FALSE );
+}
+
+
+void EditEngine::SetDefaultLanguage( LanguageType eLang )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetDefaultLanguage( eLang );
+}
+
+LanguageType EditEngine::GetDefaultLanguage() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetDefaultLanguage();
+}
+
+sal_Bool __EXPORT EditEngine::SpellNextDocument()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return sal_False;
+}
+
+EESpellState EditEngine::HasSpellErrors()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ if ( !pImpEditEngine->GetSpeller().is() )
+ return EE_SPELL_NOSPELLER;
+
+ return pImpEditEngine->HasSpellErrors();
+}
+/*-- 13.10.2003 16:56:23---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+void EditEngine::StartSpelling(EditView& rEditView, sal_Bool bMultipleDoc)
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->StartSpelling(rEditView, bMultipleDoc);
+}
+/*-- 13.10.2003 16:56:23---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+void EditEngine::EndSpelling()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->EndSpelling();
+}
+
+/*-- 13.10.2003 16:43:27---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+bool EditEngine::SpellSentence(EditView& rView, ::svx::SpellPortions& rToFill, bool bIsGrammarChecking )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->SpellSentence( rView, rToFill, bIsGrammarChecking );
+}
+/*-- 08.09.2008 11:38:32---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+void EditEngine::PutSpellingToSentenceStart( EditView& rEditView )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->PutSpellingToSentenceStart( rEditView );
+}
+/*-- 13.10.2003 16:43:27---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+void EditEngine::ApplyChangedSentence(EditView& rEditView, const ::svx::SpellPortions& rNewPortions, bool bIsGrammarChecking )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->ApplyChangedSentence( rEditView, rNewPortions, bIsGrammarChecking );
+}
+
+sal_Bool EditEngine::HasConvertibleTextPortion( LanguageType nLang )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->HasConvertibleTextPortion( nLang );
+}
+
+sal_Bool __EXPORT EditEngine::ConvertNextDocument()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return sal_False;
+}
+
+sal_Bool EditEngine::HasText( const SvxSearchItem& rSearchItem )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->HasText( rSearchItem );
+}
+
+void EditEngine::SetGlobalCharStretching( sal_uInt16 nX, sal_uInt16 nY )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetCharStretching( nX, nY );
+}
+
+void EditEngine::GetGlobalCharStretching( sal_uInt16& rX, sal_uInt16& rY )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->GetCharStretching( rX, rY );
+}
+
+void EditEngine::DoStretchChars( sal_uInt16 nX, sal_uInt16 nY )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->DoStretchChars( nX, nY );
+}
+
+void EditEngine::SetBigTextObjectStart( sal_uInt16 nStartAtPortionCount )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ pImpEditEngine->SetBigTextObjectStart( nStartAtPortionCount );
+}
+
+sal_uInt16 EditEngine::GetBigTextObjectStart() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return pImpEditEngine->GetBigTextObjectStart();
+}
+
+sal_Bool EditEngine::ShouldCreateBigTextObject() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ sal_uInt16 nTextPortions = 0;
+ sal_uInt16 nParas = pImpEditEngine->GetEditDoc().Count();
+ for ( sal_uInt16 nPara = 0; nPara < nParas; nPara++ )
+ {
+ ParaPortion* pParaPortion = pImpEditEngine->GetParaPortions()[nPara];
+ nTextPortions = nTextPortions + pParaPortion->GetTextPortions().Count();
+ }
+ return ( nTextPortions >= pImpEditEngine->GetBigTextObjectStart() ) ? sal_True : sal_False;
+}
+
+USHORT EditEngine::GetFieldCount( USHORT nPara ) const
+{
+ USHORT nFields = 0;
+ ContentNode* pNode = pImpEditEngine->GetEditDoc().SaveGetObject( nPara );
+ if ( pNode )
+ {
+ const CharAttribArray& rAttrs = pNode->GetCharAttribs().GetAttribs();
+ for ( sal_uInt16 nAttr = 0; nAttr < rAttrs.Count(); nAttr++ )
+ {
+ EditCharAttrib* pAttr = rAttrs[nAttr];
+ if ( pAttr->Which() == EE_FEATURE_FIELD )
+ nFields++;
+ }
+ }
+
+ return nFields;
+}
+
+EFieldInfo EditEngine::GetFieldInfo( USHORT nPara, USHORT nField ) const
+{
+ ContentNode* pNode = pImpEditEngine->GetEditDoc().SaveGetObject( nPara );
+ if ( pNode )
+ {
+ USHORT nCurrentField = 0;
+ const CharAttribArray& rAttrs = pNode->GetCharAttribs().GetAttribs();
+ for ( sal_uInt16 nAttr = 0; nAttr < rAttrs.Count(); nAttr++ )
+ {
+ EditCharAttrib* pAttr = rAttrs[nAttr];
+ if ( pAttr->Which() == EE_FEATURE_FIELD )
+ {
+ if ( nCurrentField == nField )
+ {
+ EFieldInfo aInfo( *(const SvxFieldItem*)pAttr->GetItem(), nPara, pAttr->GetStart() );
+ aInfo.aCurrentText = ((EditCharAttribField*)pAttr)->GetFieldValue();
+ return aInfo;
+ }
+
+ nCurrentField++;
+ }
+ }
+ }
+ return EFieldInfo();
+}
+
+
+sal_Bool EditEngine::UpdateFields()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ sal_Bool bChanges = pImpEditEngine->UpdateFields();
+ if ( bChanges )
+ pImpEditEngine->FormatAndUpdate();
+ return bChanges;
+}
+
+void EditEngine::RemoveFields( sal_Bool bKeepFieldText, TypeId aType )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+
+ if ( bKeepFieldText )
+ pImpEditEngine->UpdateFields();
+
+ sal_uInt16 nParas = pImpEditEngine->GetEditDoc().Count();
+ for ( sal_uInt16 nPara = 0; nPara < nParas; nPara++ )
+ {
+ ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara );
+ const CharAttribArray& rAttrs = pNode->GetCharAttribs().GetAttribs();
+ for ( sal_uInt16 nAttr = rAttrs.Count(); nAttr; )
+ {
+ const EditCharAttrib* pAttr = rAttrs[--nAttr];
+ if ( pAttr->Which() == EE_FEATURE_FIELD )
+ {
+ const SvxFieldData* pFldData = ((const SvxFieldItem*)pAttr->GetItem())->GetField();
+ if ( pFldData && ( !aType || ( pFldData->IsA( aType ) ) ) )
+ {
+ DBG_ASSERT( pAttr->GetItem()->ISA( SvxFieldItem ), "Kein FeldItem..." );
+ EditSelection aSel( EditPaM( pNode, pAttr->GetStart() ), EditPaM( pNode, pAttr->GetEnd() ) );
+ String aFieldText = ((EditCharAttribField*)pAttr)->GetFieldValue();
+ pImpEditEngine->ImpInsertText( aSel, aFieldText );
+ }
+ }
+ }
+ }
+}
+
+sal_Bool EditEngine::HasOnlineSpellErrors() const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ sal_uInt16 nNodes = pImpEditEngine->GetEditDoc().Count();
+ for ( sal_uInt16 n = 0; n < nNodes; n++ )
+ {
+ ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( n );
+ if ( pNode->GetWrongList() && pNode->GetWrongList()->Count() )
+ return sal_True;
+ }
+ return sal_False;
+}
+
+void EditEngine::CompleteOnlineSpelling()
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ if ( pImpEditEngine->GetStatus().DoOnlineSpelling() )
+ {
+ if( !pImpEditEngine->IsFormatted() )
+ pImpEditEngine->FormatAndUpdate();
+
+ pImpEditEngine->StopOnlineSpellTimer();
+ pImpEditEngine->DoOnlineSpelling( 0, sal_True, sal_False );
+ }
+}
+
+USHORT EditEngine::FindParagraph( long nDocPosY )
+{
+ return pImpEditEngine->GetParaPortions().FindParagraph( nDocPosY );
+}
+
+EPosition EditEngine::FindDocPosition( const Point& rDocPos ) const
+{
+ EPosition aPos;
+ // From the point of the API, this is const....
+ EditPaM aPaM = ((EditEngine*)this)->pImpEditEngine->GetPaM( rDocPos, FALSE );
+ if ( aPaM.GetNode() )
+ {
+ aPos.nPara = pImpEditEngine->aEditDoc.GetPos( aPaM.GetNode() );
+ aPos.nIndex = aPaM.GetIndex();
+ }
+ return aPos;
+}
+
+Rectangle EditEngine::GetCharacterBounds( const EPosition& rPos ) const
+{
+ Rectangle aBounds;
+ ContentNode* pNode = pImpEditEngine->GetEditDoc().SaveGetObject( rPos.nPara );
+
+ // #109151# Check against index, not paragraph
+ if ( pNode && ( rPos.nIndex < pNode->Len() ) )
+ {
+ aBounds = pImpEditEngine->PaMtoEditCursor( EditPaM( pNode, rPos.nIndex ), GETCRSR_TXTONLY );
+ Rectangle aR2 = pImpEditEngine->PaMtoEditCursor( EditPaM( pNode, rPos.nIndex+1 ), GETCRSR_TXTONLY|GETCRSR_ENDOFLINE );
+ if ( aR2.Right() > aBounds.Right() )
+ aBounds.Right() = aR2.Right();
+ }
+ return aBounds;
+}
+
+ParagraphInfos EditEngine::GetParagraphInfos( sal_uInt16 nPara )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+
+ // Funktioniert nur, wenn nicht bereits in der Formatierung...
+ if ( !pImpEditEngine->IsFormatted() )
+ pImpEditEngine->FormatDoc();
+
+ ParagraphInfos aInfos;
+ aInfos.bValid = pImpEditEngine->IsFormatted();
+ if ( pImpEditEngine->IsFormatted() )
+ {
+ ParaPortion* pParaPortion = pImpEditEngine->GetParaPortions()[nPara];
+ EditLine* pLine = (pParaPortion && pParaPortion->GetLines().Count()) ?
+ pParaPortion->GetLines().GetObject( 0 ) : NULL;
+ DBG_ASSERT( pParaPortion && pLine, "GetParagraphInfos - Paragraph out of range" );
+ if ( pParaPortion && pLine )
+ {
+ aInfos.nParaHeight = (USHORT)pParaPortion->GetHeight();
+ aInfos.nLines = pParaPortion->GetLines().Count();
+ aInfos.nFirstLineStartX = pLine->GetStartPosX();
+ aInfos.nFirstLineOffset = pParaPortion->GetFirstLineOffset();
+ aInfos.nFirstLineHeight = pLine->GetHeight();
+ aInfos.nFirstLineTextHeight = pLine->GetTxtHeight();
+ aInfos.nFirstLineMaxAscent = pLine->GetMaxAscent();
+ }
+ }
+ return aInfos;
+}
+
+::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable >
+ EditEngine::CreateTransferable( const ESelection& rSelection ) const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ EditSelection aSel( pImpEditEngine->CreateSel( rSelection ) );
+ return pImpEditEngine->CreateTransferable( aSel );
+}
+
+// =====================================================================
+// ====================== Virtuelle Methoden =======================
+// =====================================================================
+void __EXPORT EditEngine::DrawingText( const Point&, const XubString&, USHORT, USHORT,
+ const sal_Int32*, const SvxFont&, sal_uInt16, sal_uInt16, BYTE,
+ const EEngineData::WrongSpellVector*, const SvxFieldData*, bool, bool, bool,
+ const ::com::sun::star::lang::Locale*, const Color&, const Color&)
+
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+}
+
+void __EXPORT EditEngine::PaintingFirstLine( sal_uInt16, const Point&, long, const Point&, short, OutputDevice* )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+}
+
+void __EXPORT EditEngine::ParagraphInserted( sal_uInt16 nPara )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+
+ if ( GetNotifyHdl().IsSet() )
+ {
+ EENotify aNotify( EE_NOTIFY_PARAGRAPHINSERTED );
+ aNotify.pEditEngine = this;
+ aNotify.nParagraph = nPara;
+ pImpEditEngine->CallNotify( aNotify );
+ }
+}
+
+void __EXPORT EditEngine::ParagraphDeleted( sal_uInt16 nPara )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+
+ if ( GetNotifyHdl().IsSet() )
+ {
+ EENotify aNotify( EE_NOTIFY_PARAGRAPHREMOVED );
+ aNotify.pEditEngine = this;
+ aNotify.nParagraph = nPara;
+ pImpEditEngine->CallNotify( aNotify );
+ }
+}
+void EditEngine::ParagraphConnected( USHORT /*nLeftParagraph*/, USHORT /*nRightParagraph*/ )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+}
+
+sal_Bool __EXPORT EditEngine::FormattingParagraph( sal_uInt16 )
+{
+ // return sal_True, wenn die Attribute geaendert wurden...
+ DBG_CHKTHIS( EditEngine, 0 );
+ return sal_False;
+}
+
+void __EXPORT EditEngine::ParaAttribsChanged( sal_uInt16 /* nParagraph */ )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+}
+
+void __EXPORT EditEngine::StyleSheetChanged( SfxStyleSheet* /* pStyle */ )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+}
+
+void __EXPORT EditEngine::ParagraphHeightChanged( sal_uInt16 nPara )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+
+ if ( GetNotifyHdl().IsSet() )
+ {
+ EENotify aNotify( EE_NOTIFY_TEXTHEIGHTCHANGED );
+ aNotify.pEditEngine = this;
+ aNotify.nParagraph = nPara;
+ pImpEditEngine->CallNotify( aNotify );
+ }
+}
+
+XubString __EXPORT EditEngine::GetUndoComment( sal_uInt16 nId ) const
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ XubString aComment;
+ switch ( nId )
+ {
+ case EDITUNDO_REMOVECHARS:
+ case EDITUNDO_CONNECTPARAS:
+ case EDITUNDO_REMOVEFEATURE:
+ case EDITUNDO_DELCONTENT:
+ case EDITUNDO_DELETE:
+ case EDITUNDO_CUT:
+ aComment = XubString( EditResId( RID_EDITUNDO_DEL ) );
+ break;
+ case EDITUNDO_MOVEPARAGRAPHS:
+ case EDITUNDO_MOVEPARAS:
+ case EDITUNDO_DRAGANDDROP:
+ aComment = XubString( EditResId( RID_EDITUNDO_MOVE ) );
+ break;
+ case EDITUNDO_INSERTFEATURE:
+ case EDITUNDO_SPLITPARA:
+ case EDITUNDO_INSERTCHARS:
+ case EDITUNDO_PASTE:
+ case EDITUNDO_INSERT:
+ case EDITUNDO_READ:
+ aComment = XubString( EditResId( RID_EDITUNDO_INSERT ) );
+ break;
+ case EDITUNDO_SRCHANDREPL:
+ case EDITUNDO_REPLACEALL:
+ aComment = XubString( EditResId( RID_EDITUNDO_REPLACE ) );
+ break;
+ case EDITUNDO_ATTRIBS:
+ case EDITUNDO_PARAATTRIBS:
+ case EDITUNDO_STRETCH:
+ aComment = XubString( EditResId( RID_EDITUNDO_SETATTRIBS ) );
+ break;
+ case EDITUNDO_RESETATTRIBS:
+ aComment = XubString( EditResId( RID_EDITUNDO_RESETATTRIBS ) );
+ break;
+ case EDITUNDO_STYLESHEET:
+ aComment = XubString( EditResId( RID_EDITUNDO_SETSTYLE ) );
+ break;
+ case EDITUNDO_TRANSLITERATE:
+ aComment = XubString( EditResId( RID_EDITUNDO_TRANSLITERATE ) );
+ break;
+ case EDITUNDO_INDENTBLOCK:
+ case EDITUNDO_UNINDENTBLOCK:
+ aComment = XubString( EditResId( RID_EDITUNDO_INDENT ) );
+ break;
+ }
+ return aComment;
+}
+
+Rectangle EditEngine::GetBulletArea( sal_uInt16 )
+{
+ return Rectangle( Point(), Point() );
+}
+
+XubString __EXPORT EditEngine::CalcFieldValue( const SvxFieldItem&, sal_uInt16, sal_uInt16, Color*&, Color*& )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+ return ' ';
+}
+
+void __EXPORT EditEngine::FieldClicked( const SvxFieldItem&, sal_uInt16, sal_uInt16 )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+}
+
+void __EXPORT EditEngine::FieldSelected( const SvxFieldItem&, sal_uInt16, sal_uInt16 )
+{
+ DBG_CHKTHIS( EditEngine, 0 );
+}
+
+ // =====================================================================
+// ====================== Statische Methoden =======================
+// =====================================================================
+SfxItemPool* EditEngine::CreatePool( sal_Bool bPersistentRefCounts )
+{
+ SfxItemPool* pPool = new EditEngineItemPool( bPersistentRefCounts );
+ return pPool;
+}
+
+SfxItemPool& EditEngine::GetGlobalItemPool()
+{
+ if ( !pGlobalPool )
+ pGlobalPool = CreatePool();
+ return *pGlobalPool;
+}
+
+sal_uInt32 EditEngine::RegisterClipboardFormatName()
+{
+ static sal_uInt32 nFormat = 0;
+ if ( !nFormat )
+ nFormat = SotExchange::RegisterFormatName( String( RTL_CONSTASCII_USTRINGPARAM( "EditEngineFormat" ) ) );
+ return nFormat;
+}
+
+sal_uInt16 EditEngine::GetAvailableSearchOptions()
+{
+ return SEARCH_OPTIONS_SEARCH | SEARCH_OPTIONS_REPLACE |
+ SEARCH_OPTIONS_REPLACE_ALL | SEARCH_OPTIONS_WHOLE_WORDS |
+ SEARCH_OPTIONS_BACKWARDS | SEARCH_OPTIONS_REG_EXP |
+ SEARCH_OPTIONS_EXACT | SEARCH_OPTIONS_SELECTION;
+}
+
+void EditEngine::SetFontInfoInItemSet( SfxItemSet& rSet, const Font& rFont )
+{
+ SvxFont aSvxFont( rFont );
+ SetFontInfoInItemSet( rSet, aSvxFont );
+
+}
+
+void EditEngine::SetFontInfoInItemSet( SfxItemSet& rSet, const SvxFont& rFont )
+{
+ rSet.Put( SvxLanguageItem( rFont.GetLanguage(), EE_CHAR_LANGUAGE ) );
+ rSet.Put( SvxFontItem( rFont.GetFamily(), rFont.GetName(), XubString(), rFont.GetPitch(), rFont.GetCharSet(), EE_CHAR_FONTINFO ) );
+ rSet.Put( SvxFontHeightItem( rFont.GetSize().Height(), 100, EE_CHAR_FONTHEIGHT ) );
+ rSet.Put( SvxCharScaleWidthItem( 100, EE_CHAR_FONTWIDTH ) );
+ rSet.Put( SvxShadowedItem( rFont.IsShadow(), EE_CHAR_SHADOW ) );
+ rSet.Put( SvxEscapementItem( rFont.GetEscapement(), rFont.GetPropr(), EE_CHAR_ESCAPEMENT ) );
+ rSet.Put( SvxWeightItem( rFont.GetWeight(), EE_CHAR_WEIGHT ) );
+ rSet.Put( SvxColorItem( rFont.GetColor(), EE_CHAR_COLOR ) );
+ rSet.Put( SvxUnderlineItem( rFont.GetUnderline(), EE_CHAR_UNDERLINE ) );
+ rSet.Put( SvxOverlineItem( rFont.GetOverline(), EE_CHAR_OVERLINE ) );
+ rSet.Put( SvxCrossedOutItem( rFont.GetStrikeout(), EE_CHAR_STRIKEOUT ) );
+ rSet.Put( SvxPostureItem( rFont.GetItalic(), EE_CHAR_ITALIC ) );
+ rSet.Put( SvxContourItem( rFont.IsOutline(), EE_CHAR_OUTLINE ) );
+ rSet.Put( SvxAutoKernItem( rFont.IsKerning(), EE_CHAR_PAIRKERNING ) );
+ rSet.Put( SvxKerningItem( rFont.GetFixKerning(), EE_CHAR_KERNING ) );
+ rSet.Put( SvxWordLineModeItem( rFont.IsWordLineMode(), EE_CHAR_WLM ) );
+ rSet.Put( SvxEmphasisMarkItem( rFont.GetEmphasisMark(), EE_CHAR_EMPHASISMARK ) );
+ rSet.Put( SvxCharReliefItem( rFont.GetRelief(), EE_CHAR_RELIEF ) );
+}
+
+Font EditEngine::CreateFontFromItemSet( const SfxItemSet& rItemSet, USHORT nScriptType )
+{
+ SvxFont aFont;
+ CreateFont( aFont, rItemSet, true, nScriptType );
+ return aFont;
+}
+
+// Maybe we can remove the next two methods, check after 6.x
+Font EditEngine::CreateFontFromItemSet( const SfxItemSet& rItemSet )
+{
+ return CreateSvxFontFromItemSet( rItemSet );
+}
+
+SvxFont EditEngine::CreateSvxFontFromItemSet( const SfxItemSet& rItemSet )
+{
+ SvxFont aFont;
+ CreateFont( aFont, rItemSet );
+ return aFont;
+}
+
+sal_Bool EditEngine::DoesKeyMoveCursor( const KeyEvent& rKeyEvent )
+{
+ sal_Bool bDoesMove = sal_False;
+
+ switch ( rKeyEvent.GetKeyCode().GetCode() )
+ {
+ case KEY_UP:
+ case KEY_DOWN:
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ case KEY_HOME:
+ case KEY_END:
+ case KEY_PAGEUP:
+ case KEY_PAGEDOWN:
+ {
+ if ( !rKeyEvent.GetKeyCode().IsMod2() )
+ bDoesMove = sal_True;
+ }
+ break;
+ }
+ return bDoesMove;
+}
+
+sal_Bool EditEngine::DoesKeyChangeText( const KeyEvent& rKeyEvent )
+{
+ sal_Bool bDoesChange = sal_False;
+
+ KeyFuncType eFunc = rKeyEvent.GetKeyCode().GetFunction();
+ if ( eFunc != KEYFUNC_DONTKNOW )
+ {
+ switch ( eFunc )
+ {
+ case KEYFUNC_UNDO:
+ case KEYFUNC_REDO:
+ case KEYFUNC_CUT:
+ case KEYFUNC_PASTE: bDoesChange = sal_True;
+ break;
+ default: // wird dann evtl. unten bearbeitet.
+ eFunc = KEYFUNC_DONTKNOW;
+ }
+ }
+ if ( eFunc == KEYFUNC_DONTKNOW )
+ {
+ switch ( rKeyEvent.GetKeyCode().GetCode() )
+ {
+ case KEY_DELETE:
+ case KEY_BACKSPACE: bDoesChange = sal_True;
+ break;
+ case KEY_RETURN:
+ case KEY_TAB:
+ {
+ if ( !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() )
+ bDoesChange = sal_True;
+ }
+ break;
+ default:
+ {
+ bDoesChange = IsSimpleCharInput( rKeyEvent );
+ }
+ }
+ }
+ return bDoesChange;
+}
+
+sal_Bool EditEngine::IsSimpleCharInput( const KeyEvent& rKeyEvent )
+{
+ if( EditEngine::IsPrintable( rKeyEvent.GetCharCode() ) &&
+ ( KEY_MOD2 != (rKeyEvent.GetKeyCode().GetModifier() & ~KEY_SHIFT ) ) &&
+ ( KEY_MOD1 != (rKeyEvent.GetKeyCode().GetModifier() & ~KEY_SHIFT ) ) )
+ {
+ return sal_True;
+ }
+ return sal_False;
+}
+
+// Mal in den Outliner schieben...
+void EditEngine::ImportBulletItem( SvxNumBulletItem& /*rNumBullet*/, sal_uInt16 /*nLevel*/,
+ const SvxBulletItem* /*pOldBullet*/, const SvxLRSpaceItem* /*pOldLRSpace*/ )
+{
+/* TL_NFLR
+ if ( pOldBullet || pOldLRSpace )
+ {
+ // Numberformat dynamisch, weil Zuweisungsoperator nicht implementiert.
+
+ // Altes NumBulletItem nur uebernehmen, wenn kein altes BulletItem
+ const SvxNumberFormat* pFmt = ( !pOldBullet && ( rNumBullet.GetNumRule()->GetLevelCount() > nLevel ) ) ?
+ rNumBullet.GetNumRule()->Get( nLevel ) : NULL;
+ SvxNumberFormat* pNumberFormat = pFmt
+ ? new SvxNumberFormat( *pFmt )
+ : new SvxNumberFormat( SVX_NUM_NUMBER_NONE );
+ if ( pOldBullet )
+ {
+ // Style
+ SvxExtNumType eNumType;
+ switch( pOldBullet->GetStyle() )
+ {
+ case BS_BMP: eNumType = SVX_NUM_BITMAP; break;
+ case BS_BULLET: eNumType = SVX_NUM_CHAR_SPECIAL; break;
+ case BS_ROMAN_BIG: eNumType = SVX_NUM_ROMAN_UPPER; break;
+ case BS_ROMAN_SMALL: eNumType = SVX_NUM_ROMAN_LOWER; break;
+ case BS_ABC_BIG: eNumType = SVX_NUM_CHARS_UPPER_LETTER; break;
+ case BS_ABC_SMALL: eNumType = SVX_NUM_CHARS_LOWER_LETTER; break;
+ case BS_123: eNumType = SVX_NUM_ARABIC; break;
+ default: eNumType = SVX_NUM_NUMBER_NONE; break;
+ }
+ pNumberFormat->SetNumberingType(
+ sal::static_int_cast< sal_Int16 >( eNumType ) );
+
+ // Justification
+ SvxAdjust eAdjust;
+ switch( pOldBullet->GetJustification() & (BJ_HRIGHT|BJ_HCENTER|BJ_HLEFT) )
+ {
+ case BJ_HRIGHT: eAdjust = SVX_ADJUST_RIGHT; break;
+ case BJ_HCENTER: eAdjust = SVX_ADJUST_CENTER; break;
+ default: eAdjust = SVX_ADJUST_LEFT; break;
+ }
+ pNumberFormat->SetNumAdjust(eAdjust);
+
+ // Prefix/Suffix
+ pNumberFormat->SetPrefix( pOldBullet->GetPrevText() );
+ pNumberFormat->SetSuffix( pOldBullet->GetFollowText() );
+
+ //Font
+ if ( eNumType != SVX_NUM_BITMAP )
+ {
+ Font aTmpFont = pOldBullet->GetFont();
+ pNumberFormat->SetBulletFont( &aTmpFont );
+ }
+
+ // Color
+ pNumberFormat->SetBulletColor( pOldBullet->GetFont().GetColor() );
+
+ // Start
+ pNumberFormat->SetStart( pOldBullet->GetStart() );
+
+ // Scale
+ pNumberFormat->SetBulletRelSize( pOldBullet->GetScale() );
+
+ // Bullet/Bitmap
+ if( eNumType == SVX_NUM_CHAR_SPECIAL )
+ {
+ pNumberFormat->SetBulletChar( pOldBullet->GetSymbol() );
+ }
+ else if( eNumType == SVX_NUM_BITMAP )
+ {
+ SvxBrushItem aBItem( Graphic( pOldBullet->GetBitmap() ), GPOS_NONE, SID_ATTR_BRUSH );
+ pNumberFormat->SetGraphicBrush( &aBItem );
+ }
+ }
+
+ // Einzug und Erstzeileneinzug
+//TL_NFLR if ( pOldLRSpace )
+//TL_NFLR {
+//TL_NFLR short nLSpace = (short)pOldLRSpace->GetTxtLeft();
+//TL_NFLR pNumberFormat->SetLSpace( nLSpace );
+//TL_NFLR pNumberFormat->SetAbsLSpace( nLSpace );
+//TL_NFLR pNumberFormat->SetFirstLineOffset( pOldLRSpace->GetTxtFirstLineOfst() );
+//TL_NFLR }
+
+ rNumBullet.GetNumRule()->SetLevel( nLevel, *pNumberFormat );
+ delete pNumberFormat;
+ }
+*/
+}
+
+BOOL EditEngine::HasValidData( const ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable >& rTransferable )
+{
+ BOOL bValidData = FALSE;
+
+ if ( rTransferable.is() )
+ {
+ // Every application that copies rtf or any other text format also copies plain text into the clipboard....
+ datatransfer::DataFlavor aFlavor;
+ SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor );
+ bValidData = rTransferable->isDataFlavorSupported( aFlavor );
+ }
+
+ return bValidData;
+}
+
+/** sets a link that is called at the beginning of a drag operation at an edit view */
+void EditEngine::SetBeginDropHdl( const Link& rLink )
+{
+ pImpEditEngine->SetBeginDropHdl( rLink );
+}
+
+Link EditEngine::GetBeginDropHdl() const
+{
+ return pImpEditEngine->GetBeginDropHdl();
+}
+
+/** sets a link that is called at the end of a drag operation at an edit view */
+void EditEngine::SetEndDropHdl( const Link& rLink )
+{
+ pImpEditEngine->SetEndDropHdl( rLink );
+}
+
+Link EditEngine::GetEndDropHdl() const
+{
+ return pImpEditEngine->GetEndDropHdl();
+}
+
+void EditEngine::SetFirstWordCapitalization( BOOL bCapitalize )
+{
+ pImpEditEngine->SetFirstWordCapitalization( bCapitalize );
+}
+
+BOOL EditEngine::IsFirstWordCapitalization() const
+{
+ return pImpEditEngine->IsFirstWordCapitalization();
+}
+
+
+// ---------------------------------------------------
+
+
+EFieldInfo::EFieldInfo()
+{
+ pFieldItem = NULL;
+}
+
+
+EFieldInfo::EFieldInfo( const SvxFieldItem& rFieldItem, USHORT nPara, USHORT nPos ) : aPosition( nPara, nPos )
+{
+ pFieldItem = new SvxFieldItem( rFieldItem );
+}
+
+EFieldInfo::~EFieldInfo()
+{
+ delete pFieldItem;
+}
+
+EFieldInfo::EFieldInfo( const EFieldInfo& rFldInfo )
+{
+ *this = rFldInfo;
+}
+
+EFieldInfo& EFieldInfo::operator= ( const EFieldInfo& rFldInfo )
+{
+ if( this == &rFldInfo )
+ return *this;
+
+ pFieldItem = rFldInfo.pFieldItem ? new SvxFieldItem( *rFldInfo.pFieldItem ) : 0;
+ aCurrentText = rFldInfo.aCurrentText;
+ aPosition = rFldInfo.aPosition;
+
+ return *this;
+}
diff --git a/editeng/source/editeng/editeng.src b/editeng/source/editeng/editeng.src
new file mode 100644
index 000000000000..b65f20c36583
--- /dev/null
+++ b/editeng/source/editeng/editeng.src
@@ -0,0 +1,124 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#include <editeng.hrc>
+#include <helpid.hrc>
+
+String RID_EDITUNDO_DEL
+{
+ Text [ en-US ] = "Delete" ;
+};
+
+String RID_EDITUNDO_MOVE
+{
+ Text [ en-US ] = "Move" ;
+};
+
+String RID_EDITUNDO_INSERT
+{
+ Text [ en-US ] = "Insert" ;
+};
+
+String RID_EDITUNDO_REPLACE
+{
+ Text [ en-US ] = "Replace" ;
+};
+
+String RID_EDITUNDO_SETATTRIBS
+{
+ Text [ en-US ] = "Apply attributes" ;
+};
+
+String RID_EDITUNDO_RESETATTRIBS
+{
+ Text [ en-US ] = "Reset attributes" ;
+};
+
+String RID_EDITUNDO_INDENT
+{
+ Text [ en-US ] = "Indent" ;
+};
+
+String RID_EDITUNDO_SETSTYLE
+{
+ Text [ en-US ] = "Apply Styles" ;
+};
+
+String RID_EDITUNDO_TRANSLITERATE
+{
+ Text [ en-US ] = "Case/Characters";
+};
+
+
+Menu RID_MENU_SPELL
+{
+ ItemList =
+ {
+ MenuItem
+ {
+ Identifier = MN_SPELLING ;
+ HelpId = HID_EDITENG_SPELLER_START;
+ Text [ en-US ] = "~Spellcheck..." ;
+ };
+ MenuItem
+ {
+ Identifier = MN_INSERT ;
+ HelpId = HID_EDITENG_SPELLER_ADDWORD;
+ SubMenu = Menu
+ {
+ };
+ Text [ en-US ] = "~Add" ;
+ };
+ MenuItem
+ {
+ Identifier = MN_IGNORE ;
+ HelpId = HID_EDITENG_SPELLER_IGNORE;
+ Text [ en-US ] = "Ignore All" ;
+ };
+ MenuItem
+ {
+ Identifier = MN_AUTOCORR ;
+ HelpId = HID_EDITENG_SPELLER_AUTOCORRECT;
+ SubMenu = Menu
+ {
+ };
+ Text [ en-US ] = "AutoCorrect" ;
+ };
+ };
+};
+
+
+String RID_STR_WORD
+{
+ Text [ en-US ] = "Word is %x";
+};
+
+String RID_STR_PARAGRAPH
+{
+ Text [ en-US ] = "Paragraph is %x";
+};
+
diff --git a/editeng/source/editeng/editobj.cxx b/editeng/source/editeng/editobj.cxx
new file mode 100644
index 000000000000..7cd009cc52be
--- /dev/null
+++ b/editeng/source/editeng/editobj.cxx
@@ -0,0 +1,1725 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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>
+
+#define ENABLE_STRING_STREAM_OPERATORS
+#include <tools/stream.hxx>
+
+#include <editobj2.hxx>
+#include <editeng/editdata.hxx>
+#include <editattr.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/cscoitem.hxx>
+#include <editeng/flditem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/bulitem.hxx>
+#include <editeng/numitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <vcl/graph.hxx>
+#include <svl/intitem.hxx>
+#include <unotools/fontcvt.hxx>
+#include <tools/tenccvt.hxx>
+
+DBG_NAME( EE_EditTextObject )
+DBG_NAME( XEditAttribute )
+
+//--------------------------------------------------------------
+
+BOOL lcl_CreateBulletItem( const SvxNumBulletItem& rNumBullet, USHORT nLevel, SvxBulletItem& rBullet )
+{
+ const SvxNumberFormat* pFmt = rNumBullet.GetNumRule()->Get( nLevel );
+ if ( pFmt )
+ {
+ rBullet.SetWidth( (-pFmt->GetFirstLineOffset()) + pFmt->GetCharTextDistance() );
+ rBullet.SetSymbol( pFmt->GetBulletChar() );
+ rBullet.SetPrevText( pFmt->GetPrefix() );
+ rBullet.SetFollowText( pFmt->GetSuffix() );
+ rBullet.SetStart( pFmt->GetStart() );
+ rBullet.SetScale( pFmt->GetBulletRelSize() );
+
+ Font aBulletFont( rBullet.GetFont() );
+ if ( pFmt->GetBulletFont() )
+ aBulletFont = *pFmt->GetBulletFont();
+ aBulletFont.SetColor( pFmt->GetBulletColor() );
+ rBullet.SetFont( aBulletFont );
+
+ if ( pFmt->GetBrush() && pFmt->GetBrush()->GetGraphic() )
+ {
+ Bitmap aBmp( pFmt->GetBrush()->GetGraphic()->GetBitmap() );
+ aBmp.SetPrefSize( pFmt->GetGraphicSize() );
+ aBmp.SetPrefMapMode( MAP_100TH_MM );
+ rBullet.SetBitmap( aBmp );
+ }
+
+ switch ( pFmt->GetNumberingType() )
+ {
+ case SVX_NUM_CHARS_UPPER_LETTER:
+ case SVX_NUM_CHARS_UPPER_LETTER_N:
+ rBullet.SetStyle( BS_ABC_BIG );
+ break;
+ case SVX_NUM_CHARS_LOWER_LETTER:
+ case SVX_NUM_CHARS_LOWER_LETTER_N:
+ rBullet.SetStyle( BS_ABC_SMALL );
+ break;
+ case SVX_NUM_ROMAN_UPPER:
+ rBullet.SetStyle( BS_ROMAN_BIG );
+ break;
+ case SVX_NUM_ROMAN_LOWER:
+ rBullet.SetStyle( BS_ROMAN_SMALL );
+ break;
+ case SVX_NUM_ARABIC:
+ rBullet.SetStyle( BS_123 );
+ break;
+ case SVX_NUM_NUMBER_NONE:
+ rBullet.SetStyle( BS_NONE );
+ break;
+ case SVX_NUM_CHAR_SPECIAL:
+ rBullet.SetStyle( BS_BULLET );
+ break;
+ case SVX_NUM_PAGEDESC:
+ DBG_ERROR( "Unknown: SVX_NUM_PAGEDESC" );
+ rBullet.SetStyle( BS_BULLET );
+ break;
+ case SVX_NUM_BITMAP:
+ rBullet.SetStyle( BS_BMP );
+ break;
+ default:
+ DBG_ERROR( "Unknown NumType" );
+ }
+
+ switch ( pFmt->GetNumAdjust() )
+ {
+ case SVX_ADJUST_LEFT:
+ rBullet.SetJustification( BJ_VCENTER|BJ_HLEFT );
+ break;
+ case SVX_ADJUST_RIGHT:
+ rBullet.SetJustification( BJ_VCENTER|BJ_HRIGHT );
+ break;
+ case SVX_ADJUST_CENTER:
+ rBullet.SetJustification( BJ_VCENTER|BJ_HCENTER );
+ break;
+ default:
+ DBG_ERROR( "Unknown or invalid NumAdjust" );
+ }
+ }
+ return pFmt ? TRUE : FALSE;
+}
+
+
+XEditAttribute* MakeXEditAttribute( SfxItemPool& rPool, const SfxPoolItem& rItem, USHORT nStart, USHORT nEnd )
+{
+ // das neue Attribut im Pool anlegen
+ const SfxPoolItem& rNew = rPool.Put( rItem );
+
+ XEditAttribute* pNew = new XEditAttribute( rNew, nStart, nEnd );
+ return pNew;
+}
+
+
+XEditAttribute::XEditAttribute( const SfxPoolItem& rAttr )
+{
+ DBG_CTOR( XEditAttribute, 0 );
+ pItem = &rAttr;
+ nStart = 0;
+ nEnd = 0;
+}
+
+XEditAttribute::XEditAttribute( const SfxPoolItem& rAttr, USHORT nS, USHORT nE )
+{
+ DBG_CTOR( XEditAttribute, 0 );
+ pItem = &rAttr;
+ nStart = nS;
+ nEnd = nE;
+}
+
+XEditAttribute::~XEditAttribute()
+{
+ DBG_DTOR( XEditAttribute, 0 );
+ pItem = 0; // Gehoert dem Pool.
+}
+
+XEditAttribute* XEditAttributeList::FindAttrib( USHORT _nWhich, USHORT nChar ) const
+{
+ for ( USHORT n = Count(); n; )
+ {
+ XEditAttribute* pAttr = GetObject( --n );
+ if( ( pAttr->GetItem()->Which() == _nWhich ) && ( pAttr->GetStart() <= nChar ) && ( pAttr->GetEnd() > nChar ) )
+ return pAttr;
+ }
+ return NULL;
+}
+
+ContentInfo::ContentInfo( SfxItemPool& rPool ) : aParaAttribs( rPool, EE_PARA_START, EE_CHAR_END )
+{
+ eFamily = SFX_STYLE_FAMILY_PARA;
+ pWrongs = NULL;
+/* cl removed because not needed anymore since binfilter
+ pTempLoadStoreInfos = NULL;
+*/
+}
+
+// Richtiger CopyCTOR unsinning, weil ich mit einem anderen Pool arbeiten muss!
+ContentInfo::ContentInfo( const ContentInfo& rCopyFrom, SfxItemPool& rPoolToUse )
+ : aParaAttribs( rPoolToUse, EE_PARA_START, EE_CHAR_END )
+{
+ pWrongs = NULL;
+/* cl removed because not needed anymore since binfilter
+ pTempLoadStoreInfos = NULL;
+*/
+ if ( rCopyFrom.GetWrongList() )
+ pWrongs = rCopyFrom.GetWrongList()->Clone();
+ // So sollten die Items im richtigen Pool landen!
+ aParaAttribs.Set( rCopyFrom.GetParaAttribs() );
+ aText = rCopyFrom.GetText();
+ aStyle = rCopyFrom.GetStyle();
+ eFamily = rCopyFrom.GetFamily();
+
+ // Attribute kopieren...
+ for ( USHORT n = 0; n < rCopyFrom.GetAttribs().Count(); n++ )
+ {
+ XEditAttribute* pAttr = rCopyFrom.GetAttribs().GetObject( n );
+ XEditAttribute* pMyAttr = MakeXEditAttribute( rPoolToUse, *pAttr->GetItem(), pAttr->GetStart(), pAttr->GetEnd() );
+ aAttribs.Insert( pMyAttr, aAttribs.Count() );
+ }
+
+ // Wrongs
+ pWrongs = NULL;
+#ifndef SVX_LIGHT
+ if ( rCopyFrom.GetWrongList() )
+ pWrongs = rCopyFrom.GetWrongList()->Clone();
+#endif // !SVX_LIGHT
+}
+
+ContentInfo::~ContentInfo()
+{
+ for ( USHORT nAttr = 0; nAttr < aAttribs.Count(); nAttr++ )
+ {
+ XEditAttribute* pAttr = aAttribs.GetObject(nAttr);
+ // Item aus Pool entfernen!
+ aParaAttribs.GetPool()->Remove( *pAttr->GetItem() );
+ delete pAttr;
+ }
+ aAttribs.Remove( 0, aAttribs.Count() );
+#ifndef SVX_LIGHT
+ delete pWrongs;
+#endif
+}
+
+/* cl removed because not needed anymore since binfilter
+void ContentInfo::CreateLoadStoreTempInfos()
+{
+ delete pTempLoadStoreInfos;
+ pTempLoadStoreInfos = new LoadStoreTempInfos;
+}
+
+void ContentInfo::DestroyLoadStoreTempInfos()
+{
+ delete pTempLoadStoreInfos;
+ pTempLoadStoreInfos = NULL;
+}
+*/
+
+// #i102062#
+bool ContentInfo::isWrongListEqual(const ContentInfo& rCompare) const
+{
+ if(GetWrongList() == rCompare.GetWrongList())
+ return true;
+
+ if(!GetWrongList() || !rCompare.GetWrongList())
+ return false;
+
+ return (*GetWrongList() == *rCompare.GetWrongList());
+}
+
+bool ContentInfo::operator==( const ContentInfo& rCompare ) const
+{
+ if( (aText == rCompare.aText) &&
+ (aStyle == rCompare.aStyle ) &&
+ (aAttribs.Count() == rCompare.aAttribs.Count() ) &&
+ (eFamily == rCompare.eFamily ) &&
+ (aParaAttribs == rCompare.aParaAttribs ) )
+ {
+ const USHORT nCount = aAttribs.Count();
+ if( nCount == rCompare.aAttribs.Count() )
+ {
+ USHORT n;
+ for( n = 0; n < nCount; n++ )
+ {
+ if( !(*aAttribs.GetObject(n) == *rCompare.aAttribs.GetObject(n)) )
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+EditTextObject::EditTextObject( USHORT n)
+{
+ DBG_CTOR( EE_EditTextObject, 0 );
+ nWhich = n;
+}
+
+EditTextObject::EditTextObject( const EditTextObject& r )
+{
+ DBG_CTOR( EE_EditTextObject, 0 );
+ nWhich = r.nWhich;
+}
+
+__EXPORT EditTextObject::~EditTextObject()
+{
+ DBG_DTOR( EE_EditTextObject, 0 );
+}
+
+USHORT EditTextObject::GetParagraphCount() const
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+ return 0;
+}
+
+XubString EditTextObject::GetText( USHORT /* nParagraph */ ) const
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+ return XubString();
+}
+
+void EditTextObject::Insert( const EditTextObject& /* rObj */, USHORT /* nPara */)
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+}
+
+EditTextObject* EditTextObject::CreateTextObject( USHORT /*nPara*/, USHORT /*nParas*/ ) const
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+ return 0;
+}
+
+void EditTextObject::RemoveParagraph( USHORT /*nPara*/ )
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+}
+
+BOOL EditTextObject::HasPortionInfo() const
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+ return FALSE;
+}
+
+void EditTextObject::ClearPortionInfo()
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+}
+
+BOOL EditTextObject::HasOnlineSpellErrors() const
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+ return FALSE;
+}
+
+BOOL EditTextObject::HasCharAttribs( USHORT ) const
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+ return FALSE;
+}
+
+void EditTextObject::GetCharAttribs( USHORT /*nPara*/, EECharAttribArray& /*rLst*/ ) const
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+}
+
+void EditTextObject::MergeParaAttribs( const SfxItemSet& /*rAttribs*/, USHORT /*nStart*/, USHORT /*nEnd*/ )
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+}
+
+BOOL EditTextObject::IsFieldObject() const
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+ return FALSE;
+}
+
+const SvxFieldItem* EditTextObject::GetField() const
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+ return 0;
+}
+
+BOOL EditTextObject::HasField( TypeId /*aType*/ ) const
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+ return FALSE;
+}
+
+SfxItemSet EditTextObject::GetParaAttribs( USHORT /*nPara*/ ) const
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+ return SfxItemSet( *(SfxItemPool*)NULL );
+}
+
+void EditTextObject::SetParaAttribs( USHORT /*nPara*/, const SfxItemSet& /*rAttribs*/ )
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+}
+
+BOOL EditTextObject::RemoveCharAttribs( USHORT /*nWhich*/ )
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+ return FALSE;
+}
+
+BOOL EditTextObject::RemoveParaAttribs( USHORT /*nWhich*/ )
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+ return FALSE;
+}
+
+BOOL EditTextObject::HasStyleSheet( const XubString& /*rName*/, SfxStyleFamily /*eFamily*/ ) const
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+ return FALSE;
+}
+
+void EditTextObject::GetStyleSheet( USHORT /*nPara*/, XubString& /*rName*/, SfxStyleFamily& /*eFamily*/ ) const
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+}
+
+void EditTextObject::SetStyleSheet( USHORT /*nPara*/, const XubString& /*rName*/, const SfxStyleFamily& /*eFamily*/ )
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+}
+
+BOOL __EXPORT EditTextObject::ChangeStyleSheets( const XubString&, SfxStyleFamily,
+ const XubString&, SfxStyleFamily )
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+ return FALSE;
+}
+
+void __EXPORT EditTextObject::ChangeStyleSheetName( SfxStyleFamily /*eFamily*/,
+ const XubString& /*rOldName*/, const XubString& /*rNewName*/ )
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+}
+
+USHORT EditTextObject::GetUserType() const
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+ return 0;
+}
+
+void EditTextObject::SetUserType( USHORT )
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+}
+
+ULONG EditTextObject::GetObjectSettings() const
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+ return 0;
+}
+
+void EditTextObject::SetObjectSettings( ULONG )
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+}
+
+BOOL EditTextObject::IsVertical() const
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+ return FALSE;
+}
+
+void EditTextObject::SetVertical( BOOL bVertical )
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+ ((BinTextObject*)this)->SetVertical( bVertical );
+}
+
+USHORT EditTextObject::GetScriptType() const
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+ return ((const BinTextObject*)this)->GetScriptType();
+}
+
+
+BOOL EditTextObject::Store( SvStream& rOStream ) const
+{
+ if ( rOStream.GetError() )
+ return FALSE;
+
+ // Vorspann:
+ sal_Size nStartPos = rOStream.Tell();
+
+ rOStream << (USHORT)Which();
+
+ sal_uInt32 nStructSz = 0;
+ rOStream << nStructSz;
+
+ // Eigene Daten:
+ StoreData( rOStream );
+
+ // Nachspann:
+ sal_Size nEndPos = rOStream.Tell();
+ nStructSz = nEndPos - nStartPos - sizeof( nWhich ) - sizeof( nStructSz );
+ rOStream.Seek( nStartPos + sizeof( nWhich ) );
+ rOStream << nStructSz;
+ rOStream.Seek( nEndPos );
+
+ return rOStream.GetError() ? FALSE : TRUE;
+}
+
+EditTextObject* EditTextObject::Create( SvStream& rIStream, SfxItemPool* pGlobalTextObjectPool )
+{
+ ULONG nStartPos = rIStream.Tell();
+
+ // Ertmal sehen, was fuer ein Object...
+ USHORT nWhich;
+ rIStream >> nWhich;
+
+ sal_uInt32 nStructSz;
+ rIStream >> nStructSz;
+
+ DBG_ASSERT( ( nWhich == 0x22 /*EE_FORMAT_BIN300*/ ) || ( nWhich == EE_FORMAT_BIN ), "CreateTextObject: Unbekanntes Objekt!" );
+
+ if ( rIStream.GetError() )
+ return NULL;
+
+ EditTextObject* pTxtObj = NULL;
+ switch ( nWhich )
+ {
+ case 0x22 /*BIN300*/: pTxtObj = new BinTextObject( 0 );
+ ((BinTextObject*)pTxtObj)->CreateData300( rIStream );
+ break;
+ case EE_FORMAT_BIN: pTxtObj = new BinTextObject( pGlobalTextObjectPool );
+ pTxtObj->CreateData( rIStream );
+ break;
+ default:
+ {
+ // Wenn ich das Format nicht kenne, ueberlese ich den Inhalt:
+ rIStream.SetError( EE_READWRITE_WRONGFORMAT );
+ }
+ }
+
+ // Sicherstellen, dass der Stream an der richtigen Stelle hinterlassen wird.
+ sal_Size nFullSz = sizeof( nWhich ) + sizeof( nStructSz ) + nStructSz;
+ rIStream.Seek( nStartPos + nFullSz );
+ return pTxtObj;
+}
+
+void EditTextObject::Skip( SvStream& rIStream )
+{
+ sal_Size nStartPos = rIStream.Tell();
+
+ USHORT _nWhich;
+ rIStream >> _nWhich;
+
+ sal_uInt32 nStructSz;
+ rIStream >> nStructSz;
+
+ sal_Size nFullSz = sizeof( _nWhich ) + sizeof( nStructSz ) + nStructSz;
+ rIStream.Seek( nStartPos + nFullSz );
+}
+
+void __EXPORT EditTextObject::StoreData( SvStream& ) const
+{
+ DBG_ERROR( "StoreData: Basisklasse!" );
+}
+
+void __EXPORT EditTextObject::CreateData( SvStream& )
+{
+ DBG_ERROR( "CreateData: Basisklasse!" );
+}
+
+USHORT EditTextObject::GetVersion() const
+{
+ DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
+ return 0;
+}
+
+bool EditTextObject::operator==( const EditTextObject& rCompare ) const
+{
+ return static_cast< const BinTextObject* >( this )->operator==( static_cast< const BinTextObject& >( rCompare ) );
+}
+
+// #i102062#
+bool EditTextObject::isWrongListEqual(const EditTextObject& rCompare) const
+{
+ return static_cast< const BinTextObject* >(this)->isWrongListEqual(static_cast< const BinTextObject& >(rCompare));
+}
+
+// from SfxItemPoolUser
+void BinTextObject::ObjectInDestruction(const SfxItemPool& rSfxItemPool)
+{
+ if(!bOwnerOfPool && pPool && pPool == &rSfxItemPool)
+ {
+ // The pool we are based on gets destructed; get owner of pool by creating own one.
+ // No need to call RemoveSfxItemPoolUser(), this is done from the pool's destructor
+ // Base new pool on EditEnginePool; it would also be possible to clone the used
+ // pool if needed, but only text attributes should be used.
+ SfxItemPool* pNewPool = EditEngine::CreatePool();
+
+ if(pPool)
+ {
+ pNewPool->SetDefaultMetric(pPool->GetMetric(DEF_METRIC));
+ }
+
+ for(sal_uInt16 n(0); n < aContents.Count(); n++)
+ {
+ // clone ContentInfos for new pool
+ ContentInfo* pOrg = aContents.GetObject(n);
+ DBG_ASSERT(pOrg, "NULL-Pointer in ContentList!");
+
+ ContentInfo* pNew = new ContentInfo(*pOrg, *pNewPool);
+ aContents.Replace(pNew, n);
+ delete pOrg;
+ }
+
+ // set local variables
+ pPool = pNewPool;
+ bOwnerOfPool = TRUE;
+ }
+}
+
+EditEngineItemPool* getEditEngineItemPool(SfxItemPool* pPool)
+{
+ EditEngineItemPool* pRetval = dynamic_cast< EditEngineItemPool* >(pPool);
+
+ while(!pRetval && pPool && pPool->GetSecondaryPool())
+ {
+ pPool = pPool->GetSecondaryPool();
+
+ if(pPool)
+ {
+ pRetval = dynamic_cast< EditEngineItemPool* >(pPool);
+ }
+ }
+
+ return pRetval;
+}
+
+BinTextObject::BinTextObject( SfxItemPool* pP ) :
+ EditTextObject( EE_FORMAT_BIN ),
+ SfxItemPoolUser()
+{
+ nVersion = 0;
+ nMetric = 0xFFFF;
+ nUserType = 0;
+ nObjSettings = 0;
+ pPortionInfo = 0;
+
+ // #i101239# ensure target is a EditEngineItemPool, else
+ // fallback to pool ownership. This is needed to ensure that at
+ // pool destruction time of an alien pool, the pool is still alive.
+ // When registering would happen at an alien pool which just uses an
+ // EditEngineItemPool as some sub-pool, that pool could already
+ // be decoupled and deleted whcih would lead to crashes.
+ pPool = getEditEngineItemPool(pP);
+
+ if ( pPool )
+ {
+ bOwnerOfPool = FALSE;
+ }
+ else
+ {
+ pPool = EditEngine::CreatePool();
+ bOwnerOfPool = TRUE;
+ }
+
+ if(!bOwnerOfPool && pPool)
+ {
+ // it is sure now that the pool is an EditEngineItemPool
+ pPool->AddSfxItemPoolUser(*this);
+ }
+
+ bVertical = FALSE;
+ bStoreUnicodeStrings = FALSE;
+ nScriptType = 0;
+}
+
+BinTextObject::BinTextObject( const BinTextObject& r ) :
+ EditTextObject( r ),
+ SfxItemPoolUser()
+{
+ nVersion = r.nVersion;
+ nMetric = r.nMetric;
+ nUserType = r.nUserType;
+ nObjSettings = r.nObjSettings;
+ bVertical = r.bVertical;
+ nScriptType = r.nScriptType;
+ pPortionInfo = NULL; // PortionInfo nicht kopieren
+ bStoreUnicodeStrings = FALSE;
+
+ if ( !r.bOwnerOfPool )
+ {
+ // reuse alien pool; this must be a EditEngineItemPool
+ // since there is no other way to construct a BinTextObject
+ // than it's regular constructor where that is ensured
+ pPool = r.pPool;
+ bOwnerOfPool = FALSE;
+ }
+ else
+ {
+ pPool = EditEngine::CreatePool();
+ bOwnerOfPool = TRUE;
+
+ }
+
+ if(!bOwnerOfPool && pPool)
+ {
+ // it is sure now that the pool is an EditEngineItemPool
+ pPool->AddSfxItemPoolUser(*this);
+ }
+
+ if ( bOwnerOfPool && pPool && r.pPool )
+ pPool->SetDefaultMetric( r.pPool->GetMetric( DEF_METRIC ) );
+
+ for ( USHORT n = 0; n < r.aContents.Count(); n++ )
+ {
+ ContentInfo* pOrg = r.aContents.GetObject( n );
+ DBG_ASSERT( pOrg, "NULL-Pointer in ContentList!" );
+ ContentInfo* pNew = new ContentInfo( *pOrg, *pPool );
+ aContents.Insert( pNew, aContents.Count() );
+ }
+}
+
+__EXPORT BinTextObject::~BinTextObject()
+{
+ if(!bOwnerOfPool && pPool)
+ {
+ pPool->RemoveSfxItemPoolUser(*this);
+ }
+
+ ClearPortionInfo();
+ DeleteContents();
+ if ( bOwnerOfPool )
+ {
+ // Nicht mehr, wegen 1xDefItems.
+ // siehe auch ~EditDoc().
+// pPool->ReleaseDefaults( TRUE /* bDelete */ );
+ SfxItemPool::Free(pPool);
+ }
+}
+
+USHORT BinTextObject::GetUserType() const
+{
+ return nUserType;
+}
+
+void BinTextObject::SetUserType( USHORT n )
+{
+ nUserType = n;
+}
+
+ULONG BinTextObject::GetObjectSettings() const
+{
+ return nObjSettings;
+}
+
+void BinTextObject::SetObjectSettings( ULONG n )
+{
+ nObjSettings = n;
+}
+
+BOOL BinTextObject::IsVertical() const
+{
+ return bVertical;
+}
+
+void BinTextObject::SetVertical( BOOL b )
+{
+ if ( b != bVertical )
+ {
+ bVertical = b;
+ ClearPortionInfo();
+ }
+}
+
+USHORT BinTextObject::GetScriptType() const
+{
+ return nScriptType;
+}
+
+void BinTextObject::SetScriptType( USHORT nType )
+{
+ nScriptType = nType;
+}
+
+
+void BinTextObject::DeleteContents()
+{
+ for ( USHORT n = 0; n < aContents.Count(); n++ )
+ {
+ ContentInfo* p = aContents.GetObject( n );
+ DBG_ASSERT( p, "NULL-Pointer in ContentList!" );
+ delete p;
+ }
+ aContents.Remove( 0, aContents.Count() );
+}
+
+EditTextObject* __EXPORT BinTextObject::Clone() const
+{
+ return new BinTextObject( *this );
+}
+
+XEditAttribute* BinTextObject::CreateAttrib( const SfxPoolItem& rItem, USHORT nStart, USHORT nEnd )
+{
+ return MakeXEditAttribute( *pPool, rItem, nStart, nEnd );
+}
+
+void BinTextObject::DestroyAttrib( XEditAttribute* pAttr )
+{
+ pPool->Remove( *pAttr->GetItem() );
+ delete pAttr;
+}
+
+ContentInfo* BinTextObject::CreateAndInsertContent()
+{
+ ContentInfo* pC = new ContentInfo( *pPool );
+ aContents.Insert( pC, aContents.Count() );
+ return pC;
+}
+
+USHORT BinTextObject::GetParagraphCount() const
+{
+ return aContents.Count();
+}
+
+XubString BinTextObject::GetText( USHORT nPara ) const
+{
+ DBG_ASSERT( nPara < aContents.Count(), "BinTextObject::GetText: Absatz existiert nicht!" );
+ if ( nPara < aContents.Count() )
+ {
+ ContentInfo* pC = aContents[ nPara ];
+ return pC->GetText();
+ }
+ return XubString();
+}
+
+void BinTextObject::Insert( const EditTextObject& rObj, USHORT nDestPara )
+{
+ DBG_ASSERT( rObj.Which() == EE_FORMAT_BIN, "UTO: Unbekanntes Textobjekt" );
+
+ const BinTextObject& rBinObj = (const BinTextObject&)rObj;
+
+ if ( nDestPara > aContents.Count() )
+ nDestPara = aContents.Count();
+
+ const USHORT nParas = rBinObj.GetContents().Count();
+ for ( USHORT nP = 0; nP < nParas; nP++ )
+ {
+ ContentInfo* pC = rBinObj.GetContents()[ nP ];
+ ContentInfo* pNew = new ContentInfo( *pC, *GetPool() );
+ aContents.Insert( pNew, nDestPara+nP );
+ }
+ ClearPortionInfo();
+}
+
+EditTextObject* BinTextObject::CreateTextObject( USHORT nPara, USHORT nParas ) const
+{
+ if ( ( nPara >= aContents.Count() ) || !nParas )
+ return NULL;
+
+ // Pool nur teilen, wenn von aussen eingestellter Pool.
+ BinTextObject* pObj = new BinTextObject( bOwnerOfPool ? 0 : pPool );
+ if ( bOwnerOfPool && pPool )
+ pObj->GetPool()->SetDefaultMetric( pPool->GetMetric( DEF_METRIC ) );
+
+ // If complete text is only one ScriptType, this is valid.
+ // If text contains different ScriptTypes, this shouldn't be a problem...
+ pObj->nScriptType = nScriptType;
+
+ const USHORT nEndPara = nPara+nParas-1;
+ for ( USHORT nP = nPara; nP <= nEndPara; nP++ )
+ {
+ ContentInfo* pC = aContents[ nP ];
+ ContentInfo* pNew = new ContentInfo( *pC, *pObj->GetPool() );
+ pObj->GetContents().Insert( pNew, pObj->GetContents().Count() );
+ }
+ return pObj;
+}
+
+void BinTextObject::RemoveParagraph( USHORT nPara )
+{
+ DBG_ASSERT( nPara < aContents.Count(), "BinTextObject::GetText: Absatz existiert nicht!" );
+ if ( nPara < aContents.Count() )
+ {
+ ContentInfo* pC = aContents[ nPara ];
+ aContents.Remove( nPara );
+ delete pC;
+ ClearPortionInfo();
+ }
+}
+
+BOOL BinTextObject::HasPortionInfo() const
+{
+ return pPortionInfo ? TRUE : FALSE;
+}
+
+void BinTextObject::ClearPortionInfo()
+{
+ if ( pPortionInfo )
+ {
+ for ( USHORT n = pPortionInfo->Count(); n; )
+ delete pPortionInfo->GetObject( --n );
+ delete pPortionInfo;
+ pPortionInfo = NULL;
+ }
+}
+
+BOOL BinTextObject::HasOnlineSpellErrors() const
+{
+#ifndef SVX_LIGHT
+ for ( USHORT n = 0; n < aContents.Count(); n++ )
+ {
+ ContentInfo* p = aContents.GetObject( n );
+ if ( p->GetWrongList() && p->GetWrongList()->Count() )
+ return TRUE;
+ }
+#endif // !SVX_LIGHT
+ return FALSE;
+
+}
+
+BOOL BinTextObject::HasCharAttribs( USHORT _nWhich ) const
+{
+ for ( USHORT nPara = GetContents().Count(); nPara; )
+ {
+ ContentInfo* pC = GetContents().GetObject( --nPara );
+
+ USHORT nAttribs = pC->GetAttribs().Count();
+ if ( nAttribs && !_nWhich )
+ return TRUE;
+
+ for ( USHORT nAttr = nAttribs; nAttr; )
+ {
+ XEditAttribute* pX = pC->GetAttribs().GetObject( --nAttr );
+ if ( pX->GetItem()->Which() == _nWhich )
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void BinTextObject::GetCharAttribs( USHORT nPara, EECharAttribArray& rLst ) const
+{
+ rLst.Remove( 0, rLst.Count() );
+ ContentInfo* pC = GetContents().GetObject( nPara );
+ if ( pC )
+ {
+ for ( USHORT nAttr = 0; nAttr < pC->GetAttribs().Count(); nAttr++ )
+ {
+ XEditAttribute* pAttr = pC->GetAttribs().GetObject( nAttr );
+ EECharAttrib aEEAttr;
+ aEEAttr.pAttr = pAttr->GetItem();
+ aEEAttr.nPara = nPara;
+ aEEAttr.nStart = pAttr->GetStart();
+ aEEAttr.nEnd = pAttr->GetEnd();
+ rLst.Insert( aEEAttr, rLst.Count() );
+ }
+ }
+}
+
+void BinTextObject::MergeParaAttribs( const SfxItemSet& rAttribs, USHORT nStart, USHORT nEnd )
+{
+ BOOL bChanged = FALSE;
+
+ for ( USHORT nPara = GetContents().Count(); nPara; )
+ {
+ ContentInfo* pC = GetContents().GetObject( --nPara );
+
+ for ( USHORT nW = nStart; nW <= nEnd; nW++ )
+ {
+ if ( ( pC->GetParaAttribs().GetItemState( nW, FALSE ) != SFX_ITEM_ON )
+ && ( rAttribs.GetItemState( nW, FALSE ) == SFX_ITEM_ON ) )
+ {
+ pC->GetParaAttribs().Put( rAttribs.Get( nW ) );
+ bChanged = TRUE;
+ }
+ }
+ }
+
+ if ( bChanged )
+ ClearPortionInfo();
+}
+
+BOOL BinTextObject::IsFieldObject() const
+{
+ return BinTextObject::GetField() ? TRUE : FALSE;
+}
+
+const SvxFieldItem* BinTextObject::GetField() const
+{
+ if ( GetContents().Count() == 1 )
+ {
+ ContentInfo* pC = GetContents()[0];
+ if ( pC->GetText().Len() == 1 )
+ {
+ USHORT nAttribs = pC->GetAttribs().Count();
+ for ( USHORT nAttr = nAttribs; nAttr; )
+ {
+ XEditAttribute* pX = pC->GetAttribs().GetObject( --nAttr );
+ if ( pX->GetItem()->Which() == EE_FEATURE_FIELD )
+ return (const SvxFieldItem*)pX->GetItem();
+ }
+ }
+ }
+ return 0;
+}
+
+BOOL BinTextObject::HasField( TypeId aType ) const
+{
+ USHORT nParagraphs = GetContents().Count();
+ for ( USHORT nPara = 0; nPara < nParagraphs; nPara++ )
+ {
+ ContentInfo* pC = GetContents().GetObject( nPara );
+ USHORT nAttrs = pC->GetAttribs().Count();
+ for ( USHORT nAttr = 0; nAttr < nAttrs; nAttr++ )
+ {
+ XEditAttribute* pAttr = pC->GetAttribs()[nAttr];
+ if ( pAttr->GetItem()->Which() == EE_FEATURE_FIELD )
+ {
+ if ( !aType )
+ return TRUE;
+
+ const SvxFieldData* pFldData = ((const SvxFieldItem*)pAttr->GetItem())->GetField();
+ if ( pFldData && pFldData->IsA( aType ) )
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+SfxItemSet BinTextObject::GetParaAttribs( USHORT nPara ) const
+{
+ ContentInfo* pC = GetContents().GetObject( nPara );
+ return pC->GetParaAttribs();
+}
+
+void BinTextObject::SetParaAttribs( USHORT nPara, const SfxItemSet& rAttribs )
+{
+ ContentInfo* pC = GetContents().GetObject( nPara );
+ pC->GetParaAttribs().Set( rAttribs );
+ ClearPortionInfo();
+}
+
+BOOL BinTextObject::RemoveCharAttribs( USHORT _nWhich )
+{
+ BOOL bChanged = FALSE;
+
+ for ( USHORT nPara = GetContents().Count(); nPara; )
+ {
+ ContentInfo* pC = GetContents().GetObject( --nPara );
+
+ for ( USHORT nAttr = pC->GetAttribs().Count(); nAttr; )
+ {
+ XEditAttribute* pAttr = pC->GetAttribs().GetObject( --nAttr );
+ if ( !_nWhich || ( pAttr->GetItem()->Which() == _nWhich ) )
+ {
+ pC->GetAttribs().Remove( nAttr );
+ DestroyAttrib( pAttr );
+ bChanged = TRUE;
+ }
+ }
+ }
+
+ if ( bChanged )
+ ClearPortionInfo();
+
+ return bChanged;
+}
+
+BOOL BinTextObject::RemoveParaAttribs( USHORT _nWhich )
+{
+ BOOL bChanged = FALSE;
+
+ for ( USHORT nPara = GetContents().Count(); nPara; )
+ {
+ ContentInfo* pC = GetContents().GetObject( --nPara );
+
+ if ( !_nWhich )
+ {
+ if( pC->GetParaAttribs().Count() )
+ bChanged = TRUE;
+ pC->GetParaAttribs().ClearItem();
+ }
+ else
+ {
+ if ( pC->GetParaAttribs().GetItemState( _nWhich ) == SFX_ITEM_ON )
+ {
+ pC->GetParaAttribs().ClearItem( _nWhich );
+ bChanged = TRUE;
+ }
+ }
+ }
+
+ if ( bChanged )
+ ClearPortionInfo();
+
+ return bChanged;
+}
+
+BOOL BinTextObject::HasStyleSheet( const XubString& rName, SfxStyleFamily eFamily ) const
+{
+ USHORT nParagraphs = GetContents().Count();
+ for ( USHORT nPara = 0; nPara < nParagraphs; nPara++ )
+ {
+ ContentInfo* pC = GetContents().GetObject( nPara );
+ if ( ( pC->GetFamily() == eFamily ) && ( pC->GetStyle() == rName ) )
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void BinTextObject::GetStyleSheet( USHORT nPara, XubString& rName, SfxStyleFamily& rFamily ) const
+{
+ if ( nPara < aContents.Count() )
+ {
+ ContentInfo* pC = aContents[ nPara ];
+ rName = pC->GetStyle();
+ rFamily = pC->GetFamily();
+ }
+}
+
+void BinTextObject::SetStyleSheet( USHORT nPara, const XubString& rName, const SfxStyleFamily& rFamily )
+{
+ if ( nPara < aContents.Count() )
+ {
+ ContentInfo* pC = aContents[ nPara ];
+ pC->GetStyle() = rName;
+ pC->GetFamily() = rFamily;
+ }
+}
+
+BOOL BinTextObject::ImpChangeStyleSheets(
+ const XubString& rOldName, SfxStyleFamily eOldFamily,
+ const XubString& rNewName, SfxStyleFamily eNewFamily )
+{
+ const USHORT nParagraphs = GetContents().Count();
+ BOOL bChanges = FALSE;
+
+ for ( USHORT nPara = 0; nPara < nParagraphs; nPara++ )
+ {
+ ContentInfo* pC = GetContents().GetObject( nPara );
+ if ( pC->GetFamily() == eOldFamily )
+ {
+ if ( pC->GetStyle() == rOldName )
+ {
+ pC->GetStyle() = rNewName;
+ pC->GetFamily() = eNewFamily;
+ bChanges = TRUE;
+ }
+ }
+ }
+ return bChanges;
+}
+
+BOOL __EXPORT BinTextObject::ChangeStyleSheets(
+ const XubString& rOldName, SfxStyleFamily eOldFamily,
+ const XubString& rNewName, SfxStyleFamily eNewFamily )
+{
+ BOOL bChanges = ImpChangeStyleSheets( rOldName, eOldFamily, rNewName, eNewFamily );
+ if ( bChanges )
+ ClearPortionInfo();
+
+ return bChanges;
+}
+
+void __EXPORT BinTextObject::ChangeStyleSheetName( SfxStyleFamily eFamily,
+ const XubString& rOldName, const XubString& rNewName )
+{
+ ImpChangeStyleSheets( rOldName, eFamily, rNewName, eFamily );
+}
+
+void __EXPORT BinTextObject::StoreData( SvStream& rOStream ) const
+{
+ USHORT nVer = 602;
+ rOStream << nVer;
+
+ rOStream << bOwnerOfPool;
+
+ // Erst den Pool speichern, spaeter nur noch Surregate
+ if ( bOwnerOfPool )
+ {
+ GetPool()->SetFileFormatVersion( SOFFICE_FILEFORMAT_50 );
+ GetPool()->Store( rOStream );
+ }
+
+ // Aktuelle Zeichensatz speichern...
+ // #90477# GetSOStoreTextEncoding: Bug in 5.2, when default char set is multi byte text encoding
+ rtl_TextEncoding eEncoding = GetSOStoreTextEncoding( gsl_getSystemTextEncoding(), (USHORT) rOStream.GetVersion() );
+ rOStream << (USHORT) eEncoding;
+
+ // Die Anzahl der Absaetze...
+ USHORT nParagraphs = GetContents().Count();
+ rOStream << nParagraphs;
+
+ char cFeatureConverted = ByteString( CH_FEATURE, eEncoding ).GetChar(0);
+
+ // Die einzelnen Absaetze...
+ for ( USHORT nPara = 0; nPara < nParagraphs; nPara++ )
+ {
+ ContentInfo* pC = GetContents().GetObject( nPara );
+
+ // Text...
+ ByteString aText( pC->GetText(), eEncoding );
+
+ // Symbols?
+ BOOL bSymbolPara = FALSE;
+ if ( pC->GetParaAttribs().GetItemState( EE_CHAR_FONTINFO ) == SFX_ITEM_ON )
+ {
+ const SvxFontItem& rFontItem = (const SvxFontItem&)pC->GetParaAttribs().Get( EE_CHAR_FONTINFO );
+ if ( rFontItem.GetCharSet() == RTL_TEXTENCODING_SYMBOL )
+ {
+ aText = ByteString( pC->GetText(), RTL_TEXTENCODING_SYMBOL );
+ bSymbolPara = TRUE;
+ }
+ }
+ for ( USHORT nA = 0; nA < pC->GetAttribs().Count(); nA++ )
+ {
+ XEditAttribute* pAttr = pC->GetAttribs().GetObject( nA );
+
+ if ( pAttr->GetItem()->Which() == EE_CHAR_FONTINFO )
+ {
+ const SvxFontItem& rFontItem = (const SvxFontItem&)*pAttr->GetItem();
+ if ( ( !bSymbolPara && ( rFontItem.GetCharSet() == RTL_TEXTENCODING_SYMBOL ) )
+ || ( bSymbolPara && ( rFontItem.GetCharSet() != RTL_TEXTENCODING_SYMBOL ) ) )
+ {
+ // Not correctly converted
+ String aPart( pC->GetText(), pAttr->GetStart(), pAttr->GetEnd() - pAttr->GetStart() );
+ ByteString aNew( aPart, rFontItem.GetCharSet() );
+ aText.Erase( pAttr->GetStart(), pAttr->GetEnd() - pAttr->GetStart() );
+ aText.Insert( aNew, pAttr->GetStart() );
+ }
+
+ // #88414# Convert StarSymbol back to StarBats
+ FontToSubsFontConverter hConv = CreateFontToSubsFontConverter( rFontItem.GetFamilyName(), FONTTOSUBSFONT_EXPORT | FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS );
+ if ( hConv )
+ {
+ // Don't create a new Attrib with StarBats font, MBR changed the
+ // SvxFontItem::Store() to store StarBats instead of StarSymbol!
+ for ( USHORT nChar = pAttr->GetStart(); nChar < pAttr->GetEnd(); nChar++ )
+ {
+ sal_Unicode cOld = pC->GetText().GetChar( nChar );
+ char cConv = ByteString::ConvertFromUnicode( ConvertFontToSubsFontChar( hConv, cOld ), RTL_TEXTENCODING_SYMBOL );
+ if ( cConv )
+ aText.SetChar( nChar, cConv );
+ }
+
+ DestroyFontToSubsFontConverter( hConv );
+ }
+ }
+ }
+
+ // #88414# Convert StarSymbol back to StarBats
+ // StarSymbol as paragraph attribute or in StyleSheet?
+
+ FontToSubsFontConverter hConv = NULL;
+ if ( pC->GetParaAttribs().GetItemState( EE_CHAR_FONTINFO ) == SFX_ITEM_ON )
+ {
+ hConv = CreateFontToSubsFontConverter( ((const SvxFontItem&)pC->GetParaAttribs().Get( EE_CHAR_FONTINFO )).GetFamilyName(), FONTTOSUBSFONT_EXPORT | FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS );
+ }
+/* cl removed because not needed anymore since binfilter
+
+ else if ( pC->GetStyle().Len() && pC->GetLoadStoreTempInfos() )
+ {
+ hConv = pC->GetLoadStoreTempInfos()->hOldSymbolConv_Store;
+ }
+*/
+ if ( hConv )
+ {
+ for ( USHORT nChar = 0; nChar < pC->GetText().Len(); nChar++ )
+ {
+ if ( !pC->GetAttribs().FindAttrib( EE_CHAR_FONTINFO, nChar ) )
+ {
+ sal_Unicode cOld = pC->GetText().GetChar( nChar );
+ char cConv = ByteString::ConvertFromUnicode( ConvertFontToSubsFontChar( hConv, cOld ), RTL_TEXTENCODING_SYMBOL );
+ if ( cConv )
+ aText.SetChar( nChar, cConv );
+ }
+ }
+
+ DestroyFontToSubsFontConverter( hConv );
+
+ }
+
+
+ // Convert CH_FEATURE to CH_FEATURE_OLD
+ aText.SearchAndReplaceAll( cFeatureConverted, CH_FEATURE_OLD );
+ rOStream.WriteByteString( aText );
+
+ // StyleName und Family...
+ rOStream.WriteByteString( ByteString( pC->GetStyle(), eEncoding ) );
+ rOStream << (USHORT)pC->GetFamily();
+
+ // Absatzattribute...
+ pC->GetParaAttribs().Store( rOStream );
+
+ // Die Anzahl der Attribute...
+ USHORT nAttribs = pC->GetAttribs().Count();
+ rOStream << nAttribs;
+
+ // Und die einzelnen Attribute
+ // Items als Surregate => immer 8 Byte pro Attrib
+ // Which = 2; Surregat = 2; Start = 2; End = 2;
+ for ( USHORT nAttr = 0; nAttr < nAttribs; nAttr++ )
+ {
+ XEditAttribute* pX = pC->GetAttribs().GetObject( nAttr );
+
+ rOStream << pX->GetItem()->Which();
+ GetPool()->StoreSurrogate( rOStream, pX->GetItem() );
+ rOStream << pX->GetStart();
+ rOStream << pX->GetEnd();
+ }
+ }
+
+ // Ab 400:
+ rOStream << nMetric;
+
+ // Ab 600
+ rOStream << nUserType;
+ rOStream << nObjSettings;
+
+ // Ab 601
+ rOStream << bVertical;
+
+ // Ab 602
+ rOStream << nScriptType;
+
+ rOStream << bStoreUnicodeStrings;
+ if ( bStoreUnicodeStrings )
+ {
+ for ( USHORT nPara = 0; nPara < nParagraphs; nPara++ )
+ {
+ ContentInfo* pC = GetContents().GetObject( nPara );
+ USHORT nL = pC->GetText().Len();
+ rOStream << nL;
+ rOStream.Write( pC->GetText().GetBuffer(), nL*sizeof(sal_Unicode) );
+
+ // #91575# StyleSheetName must be Unicode too!
+ // Copy/Paste from EA3 to BETA or from BETA to EA3 not possible, not needed...
+ // If needed, change nL back to ULONG and increase version...
+ nL = pC->GetStyle().Len();
+ rOStream << nL;
+ rOStream.Write( pC->GetStyle().GetBuffer(), nL*sizeof(sal_Unicode) );
+ }
+ }
+}
+
+void __EXPORT BinTextObject::CreateData( SvStream& rIStream )
+{
+ rIStream >> nVersion;
+
+ // Das Textobject wurde erstmal mit der aktuellen Einstellung
+ // von pTextObjectPool erzeugt.
+ BOOL bOwnerOfCurrent = bOwnerOfPool;
+ rIStream >> bOwnerOfPool;
+
+ if ( bOwnerOfCurrent && !bOwnerOfPool )
+ {
+ // Es wurde ein globaler Pool verwendet, mir jetzt nicht uebergeben,
+ // aber ich brauche ihn!
+ DBG_ERROR( "Man gebe mir den globalen TextObjectPool!" );
+ return;
+ }
+ else if ( !bOwnerOfCurrent && bOwnerOfPool )
+ {
+ // Es soll ein globaler Pool verwendet werden, aber dieses
+ // Textobject hat einen eigenen.
+ pPool = EditEngine::CreatePool();
+ }
+
+ if ( bOwnerOfPool )
+ GetPool()->Load( rIStream );
+
+ // CharSet, in dem gespeichert wurde:
+ USHORT nCharSet;
+ rIStream >> nCharSet;
+
+ rtl_TextEncoding eSrcEncoding = GetSOLoadTextEncoding( (rtl_TextEncoding)nCharSet, (USHORT)rIStream.GetVersion() );
+
+ // Die Anzahl der Absaetze...
+ USHORT nParagraphs;
+ rIStream >> nParagraphs;
+
+ // Die einzelnen Absaetze...
+ for ( ULONG nPara = 0; nPara < nParagraphs; nPara++ )
+ {
+ ContentInfo* pC = CreateAndInsertContent();
+
+ // Der Text...
+ ByteString aByteString;
+ rIStream.ReadByteString( aByteString );
+ pC->GetText() = String( aByteString, eSrcEncoding );
+
+ // StyleName und Family...
+ rIStream.ReadByteString( pC->GetStyle(), eSrcEncoding );
+ USHORT nStyleFamily;
+ rIStream >> nStyleFamily;
+ pC->GetFamily() = (SfxStyleFamily)nStyleFamily;
+
+ // Absatzattribute...
+ pC->GetParaAttribs().Load( rIStream );
+
+ // Die Anzahl der Attribute...
+ USHORT nAttribs;
+ rIStream >> nAttribs;
+
+ // Und die einzelnen Attribute
+ // Items als Surregate => immer 8 Byte pro Attrib
+ // Which = 2; Surregat = 2; Start = 2; End = 2;
+ USHORT nAttr;
+ for ( nAttr = 0; nAttr < nAttribs; nAttr++ )
+ {
+ USHORT _nWhich, nStart, nEnd;
+ const SfxPoolItem* pItem;
+
+ rIStream >> _nWhich;
+ _nWhich = pPool->GetNewWhich( _nWhich );
+ pItem = pPool->LoadSurrogate( rIStream, _nWhich, 0 );
+ rIStream >> nStart;
+ rIStream >> nEnd;
+ if ( pItem )
+ {
+ if ( pItem->Which() == EE_FEATURE_NOTCONV )
+ {
+ pC->GetText().SetChar( nStart, ByteString::ConvertToUnicode( aByteString.GetChar( nStart ), ((SvxCharSetColorItem*)pItem)->GetCharSet() ) );
+ }
+ else
+ {
+ XEditAttribute* pAttr = new XEditAttribute( *pItem, nStart, nEnd );
+ pC->GetAttribs().Insert( pAttr, pC->GetAttribs().Count() );
+
+ if ( ( _nWhich >= EE_FEATURE_START ) && ( _nWhich <= EE_FEATURE_END ) )
+ {
+ // Convert CH_FEATURE to CH_FEATURE_OLD
+ DBG_ASSERT( (BYTE) aByteString.GetChar( nStart ) == CH_FEATURE_OLD, "CreateData: CH_FEATURE expected!" );
+ if ( (BYTE) aByteString.GetChar( nStart ) == CH_FEATURE_OLD )
+ pC->GetText().SetChar( nStart, CH_FEATURE );
+ }
+ }
+ }
+ }
+
+ // But check for paragraph and character symbol attribs here,
+ // FinishLoad will not be called in OpenOffice Calc, no StyleSheets...
+
+ BOOL bSymbolPara = FALSE;
+ if ( pC->GetParaAttribs().GetItemState( EE_CHAR_FONTINFO ) == SFX_ITEM_ON )
+ {
+ const SvxFontItem& rFontItem = (const SvxFontItem&)pC->GetParaAttribs().Get( EE_CHAR_FONTINFO );
+ if ( rFontItem.GetCharSet() == RTL_TEXTENCODING_SYMBOL )
+ {
+ pC->GetText() = String( aByteString, RTL_TEXTENCODING_SYMBOL );
+ bSymbolPara = TRUE;
+ }
+ }
+
+ for ( nAttr = pC->GetAttribs().Count(); nAttr; )
+ {
+ XEditAttribute* pAttr = pC->GetAttribs().GetObject( --nAttr );
+ if ( pAttr->GetItem()->Which() == EE_CHAR_FONTINFO )
+ {
+ const SvxFontItem& rFontItem = (const SvxFontItem&)*pAttr->GetItem();
+ if ( ( !bSymbolPara && ( rFontItem.GetCharSet() == RTL_TEXTENCODING_SYMBOL ) )
+ || ( bSymbolPara && ( rFontItem.GetCharSet() != RTL_TEXTENCODING_SYMBOL ) ) )
+ {
+ // Not correctly converted
+ ByteString aPart( aByteString, pAttr->GetStart(), pAttr->GetEnd()-pAttr->GetStart() );
+ String aNew( aPart, rFontItem.GetCharSet() );
+ pC->GetText().Erase( pAttr->GetStart(), pAttr->GetEnd()-pAttr->GetStart() );
+ pC->GetText().Insert( aNew, pAttr->GetStart() );
+ }
+
+ // #88414# Convert StarMath and StarBats to StarSymbol
+ FontToSubsFontConverter hConv = CreateFontToSubsFontConverter( rFontItem.GetFamilyName(), FONTTOSUBSFONT_IMPORT | FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS );
+ if ( hConv )
+ {
+ SvxFontItem aNewFontItem( rFontItem );
+ aNewFontItem.GetFamilyName() = GetFontToSubsFontName( hConv );
+
+ pC->GetAttribs().Remove( nAttr );
+ XEditAttribute* pNewAttr = CreateAttrib( aNewFontItem, pAttr->GetStart(), pAttr->GetEnd() );
+ pC->GetAttribs().Insert( pNewAttr, nAttr );
+ DestroyAttrib( pAttr );
+
+ for ( USHORT nChar = pNewAttr->GetStart(); nChar < pNewAttr->GetEnd(); nChar++ )
+ {
+ sal_Unicode cOld = pC->GetText().GetChar( nChar );
+ DBG_ASSERT( cOld >= 0xF000, "cOld not converted?!" );
+ sal_Unicode cConv = ConvertFontToSubsFontChar( hConv, cOld );
+ if ( cConv )
+ pC->GetText().SetChar( nChar, cConv );
+ }
+
+ DestroyFontToSubsFontConverter( hConv );
+ }
+ }
+ }
+
+
+ // #88414# Convert StarMath and StarBats to StarSymbol
+ // Maybe old symbol font as paragraph attribute?
+ if ( pC->GetParaAttribs().GetItemState( EE_CHAR_FONTINFO ) == SFX_ITEM_ON )
+ {
+ const SvxFontItem& rFontItem = (const SvxFontItem&)pC->GetParaAttribs().Get( EE_CHAR_FONTINFO );
+ FontToSubsFontConverter hConv = CreateFontToSubsFontConverter( rFontItem.GetFamilyName(), FONTTOSUBSFONT_IMPORT | FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS );
+ if ( hConv )
+ {
+ SvxFontItem aNewFontItem( rFontItem );
+ aNewFontItem.GetFamilyName() = GetFontToSubsFontName( hConv );
+ pC->GetParaAttribs().Put( aNewFontItem );
+
+ for ( USHORT nChar = 0; nChar < pC->GetText().Len(); nChar++ )
+ {
+ if ( !pC->GetAttribs().FindAttrib( EE_CHAR_FONTINFO, nChar ) )
+ {
+ sal_Unicode cOld = pC->GetText().GetChar( nChar );
+ DBG_ASSERT( cOld >= 0xF000, "cOld not converted?!" );
+ sal_Unicode cConv = ConvertFontToSubsFontChar( hConv, cOld );
+ if ( cConv )
+ pC->GetText().SetChar( nChar, cConv );
+ }
+ }
+
+ DestroyFontToSubsFontConverter( hConv );
+ }
+ }
+ }
+
+ // Ab 400 auch die DefMetric:
+ if ( nVersion >= 400 )
+ {
+ USHORT nTmpMetric;
+ rIStream >> nTmpMetric;
+ if ( nVersion >= 401 )
+ {
+ // In der 400 gab es noch einen Bug bei Textobjekten mit eigenem
+ // Pool, deshalb erst ab 401 auswerten.
+ nMetric = nTmpMetric;
+ if ( bOwnerOfPool && pPool && ( nMetric != 0xFFFF ) )
+ pPool->SetDefaultMetric( (SfxMapUnit)nMetric );
+ }
+ }
+
+ if ( nVersion >= 600 )
+ {
+ rIStream >> nUserType;
+ rIStream >> nObjSettings;
+ }
+
+ if ( nVersion >= 601 )
+ {
+ rIStream >> bVertical;
+ }
+
+ if ( nVersion >= 602 )
+ {
+ rIStream >> nScriptType;
+
+ BOOL bUnicodeStrings;
+ rIStream >> bUnicodeStrings;
+ if ( bUnicodeStrings )
+ {
+ for ( USHORT nPara = 0; nPara < nParagraphs; nPara++ )
+ {
+ ContentInfo* pC = GetContents().GetObject( nPara );
+ USHORT nL;
+
+ // Text
+ rIStream >> nL;
+ if ( nL )
+ {
+ pC->GetText().AllocBuffer( nL );
+ rIStream.Read( pC->GetText().GetBufferAccess(), nL*sizeof(sal_Unicode) );
+ pC->GetText().ReleaseBufferAccess( (USHORT)nL );
+ }
+
+ // StyleSheetName
+ rIStream >> nL;
+ if ( nL )
+ {
+ pC->GetStyle().AllocBuffer( nL );
+ rIStream.Read( pC->GetStyle().GetBufferAccess(), nL*sizeof(sal_Unicode) );
+ pC->GetStyle().ReleaseBufferAccess( (USHORT)nL );
+ }
+ }
+ }
+ }
+
+
+ // Ab 500 werden die Tabs anders interpretiert: TabPos + LI, vorher nur TabPos.
+ // Wirkt nur wenn auch Tab-Positionen eingestellt wurden, nicht beim DefTab.
+ if ( nVersion < 500 )
+ {
+ for ( USHORT n = 0; n < aContents.Count(); n++ )
+ {
+ ContentInfo* pC = aContents.GetObject( n );
+ const SvxLRSpaceItem& rLRSpace = (const SvxLRSpaceItem&) pC->GetParaAttribs().Get( EE_PARA_LRSPACE );
+ if ( rLRSpace.GetTxtLeft() && ( pC->GetParaAttribs().GetItemState( EE_PARA_TABS ) == SFX_ITEM_ON ) )
+ {
+ const SvxTabStopItem& rTabs = (const SvxTabStopItem&) pC->GetParaAttribs().Get( EE_PARA_TABS );
+ SvxTabStopItem aNewTabs( 0, 0, SVX_TAB_ADJUST_LEFT, EE_PARA_TABS );
+ for ( USHORT t = 0; t < rTabs.Count(); t++ )
+ {
+ const SvxTabStop& rT = rTabs[ t ];
+ aNewTabs.Insert( SvxTabStop( rT.GetTabPos() - rLRSpace.GetTxtLeft(),
+ rT.GetAdjustment(), rT.GetDecimal(), rT.GetFill() ) );
+ }
+ pC->GetParaAttribs().Put( aNewTabs );
+ }
+ }
+ }
+}
+
+USHORT BinTextObject::GetVersion() const
+{
+ return nVersion;
+}
+
+bool BinTextObject::operator==( const BinTextObject& rCompare ) const
+{
+ if( this == &rCompare )
+ return true;
+
+ if( ( aContents.Count() != rCompare.aContents.Count() ) ||
+ ( pPool != rCompare.pPool ) ||
+ ( nMetric != rCompare.nMetric ) ||
+ ( nUserType!= rCompare.nUserType ) ||
+ ( nScriptType != rCompare.nScriptType ) ||
+ ( bVertical != rCompare.bVertical ) )
+ return false;
+
+ USHORT n;
+ for( n = 0; n < aContents.Count(); n++ )
+ {
+ if( !( *aContents.GetObject( n ) == *rCompare.aContents.GetObject( n ) ) )
+ return false;
+ }
+
+ return true;
+}
+
+// #i102062#
+bool BinTextObject::isWrongListEqual(const BinTextObject& rCompare) const
+{
+ if(GetContents().Count() != rCompare.GetContents().Count())
+ {
+ return false;
+ }
+
+ for(USHORT a(0); a < GetContents().Count(); a++)
+ {
+ const ContentInfo& rCandA(*GetContents().GetObject(a));
+ const ContentInfo& rCandB(*rCompare.GetContents().GetObject(a));
+
+ if(!rCandA.isWrongListEqual(rCandB))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+#define CHARSETMARKER 0x9999
+
+void __EXPORT BinTextObject::CreateData300( SvStream& rIStream )
+{
+ // Fuer Aufwaertskompatibilitaet.
+
+ // Erst den Pool laden...
+ // Ist in der 300 immer gespeichert worden!
+ GetPool()->Load( rIStream );
+
+ // Die Anzahl der Absaetze...
+ sal_uInt32 nParagraphs;
+ rIStream >> nParagraphs;
+
+ // Die einzelnen Absaetze...
+ for ( ULONG nPara = 0; nPara < nParagraphs; nPara++ )
+ {
+ ContentInfo* pC = CreateAndInsertContent();
+
+ // Der Text...
+ rIStream.ReadByteString( pC->GetText() );
+
+ // StyleName und Family...
+ rIStream.ReadByteString( pC->GetStyle() );
+ USHORT nStyleFamily;
+ rIStream >> nStyleFamily;
+ pC->GetFamily() = (SfxStyleFamily)nStyleFamily;
+
+ // Absatzattribute...
+ pC->GetParaAttribs().Load( rIStream );
+
+ // Die Anzahl der Attribute...
+ sal_uInt32 nAttribs;
+ rIStream >> nAttribs;
+
+ // Und die einzelnen Attribute
+ // Items als Surregate => immer 8 Byte pro Attrib
+ // Which = 2; Surregat = 2; Start = 2; End = 2;
+ for ( ULONG nAttr = 0; nAttr < nAttribs; nAttr++ )
+ {
+ USHORT _nWhich, nStart, nEnd;
+ const SfxPoolItem* pItem;
+
+ rIStream >> _nWhich;
+ _nWhich = pPool->GetNewWhich( _nWhich );
+ pItem = pPool->LoadSurrogate( rIStream, _nWhich, 0 );
+ rIStream >> nStart;
+ rIStream >> nEnd;
+ if ( pItem )
+ {
+ XEditAttribute* pAttr = new XEditAttribute( *pItem, nStart, nEnd );
+ pC->GetAttribs().Insert( pAttr, pC->GetAttribs().Count() );
+ }
+ }
+ }
+
+ // Prueffen, ob ein Zeichensatz gespeichert wurde
+ USHORT nCharSetMarker;
+ rIStream >> nCharSetMarker;
+ if ( nCharSetMarker == CHARSETMARKER )
+ {
+ USHORT nCharSet;
+ rIStream >> nCharSet;
+ }
+}
diff --git a/editeng/source/editeng/editobj2.hxx b/editeng/source/editeng/editobj2.hxx
new file mode 100644
index 000000000000..6ef3ce359d49
--- /dev/null
+++ b/editeng/source/editeng/editobj2.hxx
@@ -0,0 +1,309 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef _EDITOBJ2_HXX
+#define _EDITOBJ2_HXX
+
+#include <editeng/editobj.hxx>
+#include <editdoc.hxx>
+
+#include <unotools/fontcvt.hxx>
+
+
+class SfxStyleSheetPool;
+
+class XEditAttribute
+{
+ friend class ContentInfo; // fuer DTOR
+ friend class BinTextObject; // fuer DTOR
+
+private:
+ const SfxPoolItem* pItem;
+ USHORT nStart;
+ USHORT nEnd;
+
+ XEditAttribute();
+ XEditAttribute( const XEditAttribute& rCopyFrom );
+
+ ~XEditAttribute();
+
+public:
+ XEditAttribute( const SfxPoolItem& rAttr );
+ XEditAttribute( const SfxPoolItem& rAttr, USHORT nStart, USHORT nEnd );
+
+ const SfxPoolItem* GetItem() const { return pItem; }
+
+ USHORT& GetStart() { return nStart; }
+ USHORT& GetEnd() { return nEnd; }
+
+ USHORT GetStart() const { return nStart; }
+ USHORT GetEnd() const { return nEnd; }
+
+ USHORT GetLen() const { return nEnd-nStart; }
+
+ inline BOOL IsFeature();
+
+ inline bool operator==( const XEditAttribute& rCompare );
+};
+
+inline bool XEditAttribute::operator==( const XEditAttribute& rCompare )
+{
+ return (nStart == rCompare.nStart) &&
+ (nEnd == rCompare.nEnd) &&
+ ( (pItem == rCompare.pItem) ||
+ ( pItem->Which() != rCompare.pItem->Which()) ||
+ (*pItem == *rCompare.pItem));
+}
+
+inline BOOL XEditAttribute::IsFeature()
+{
+ USHORT nWhich = pItem->Which();
+ return ( ( nWhich >= EE_FEATURE_START ) &&
+ ( nWhich <= EE_FEATURE_END ) );
+}
+
+typedef XEditAttribute* XEditAttributePtr;
+SV_DECL_PTRARR( XEditAttributeListImpl, XEditAttributePtr, 0, 4 )
+
+class XEditAttributeList : public XEditAttributeListImpl
+{
+public:
+ XEditAttribute* FindAttrib( USHORT nWhich, USHORT nChar ) const;
+};
+
+struct XParaPortion
+{
+ long nHeight;
+ USHORT nFirstLineOffset;
+
+ EditLineList aLines;
+ TextPortionList aTextPortions;
+};
+
+typedef XParaPortion* XParaPortionPtr;
+SV_DECL_PTRARR( XBaseParaPortionList, XParaPortionPtr, 0, 4 )
+
+class XParaPortionList : public XBaseParaPortionList
+{
+ ULONG nRefDevPtr;
+ OutDevType eRefDevType;
+ MapMode aRefMapMode;
+ ULONG nPaperWidth;
+
+
+public:
+ XParaPortionList( OutputDevice* pRefDev, ULONG nPW ) :
+ aRefMapMode( pRefDev->GetMapMode() )
+ {
+ nRefDevPtr = (ULONG)pRefDev; nPaperWidth = nPW;
+ eRefDevType = pRefDev->GetOutDevType();
+ }
+
+ ULONG GetRefDevPtr() const { return nRefDevPtr; }
+ ULONG GetPaperWidth() const { return nPaperWidth; }
+ OutDevType GetRefDevType() const { return eRefDevType; }
+ const MapMode& GetRefMapMode() const { return aRefMapMode; }
+};
+
+/* cl removed because not needed anymore since binfilter
+struct LoadStoreTempInfos
+{
+ ByteString aOrgString_Load;
+
+ FontToSubsFontConverter hOldSymbolConv_Store;
+ BOOL bSymbolParagraph_Store;
+
+
+ LoadStoreTempInfos() { bSymbolParagraph_Store = FALSE; hOldSymbolConv_Store = NULL; }
+};
+*/
+
+class ContentInfo
+{
+ friend class BinTextObject;
+
+private:
+ String aText;
+ String aStyle;
+ XEditAttributeList aAttribs;
+ SfxStyleFamily eFamily;
+ SfxItemSet aParaAttribs;
+ WrongList* pWrongs;
+
+/* cl removed because not needed anymore since binfilter
+ LoadStoreTempInfos* pTempLoadStoreInfos;
+*/
+
+ ContentInfo( SfxItemPool& rPool );
+ ContentInfo( const ContentInfo& rCopyFrom, SfxItemPool& rPoolToUse );
+
+public:
+ ~ContentInfo();
+
+ const String& GetText() const { return aText; }
+ const String& GetStyle() const { return aStyle; }
+ const XEditAttributeList& GetAttribs() const { return aAttribs; }
+ const SfxItemSet& GetParaAttribs() const { return aParaAttribs; }
+ SfxStyleFamily GetFamily() const { return eFamily; }
+
+ String& GetText() { return aText; }
+ String& GetStyle() { return aStyle; }
+ XEditAttributeList& GetAttribs() { return aAttribs; }
+ SfxItemSet& GetParaAttribs() { return aParaAttribs; }
+ SfxStyleFamily& GetFamily() { return eFamily; }
+
+ WrongList* GetWrongList() const { return pWrongs; }
+ void SetWrongList( WrongList* p ) { pWrongs = p; }
+ bool operator==( const ContentInfo& rCompare ) const;
+
+ // #i102062#
+ bool isWrongListEqual(const ContentInfo& rCompare) const;
+};
+
+typedef ContentInfo* ContentInfoPtr;
+SV_DECL_PTRARR( ContentInfoList, ContentInfoPtr, 1, 4 )
+
+// MT 05/00: Sollte mal direkt EditTextObjekt werden => keine virtuellen Methoden mehr.
+
+class BinTextObject : public EditTextObject, public SfxItemPoolUser
+{
+ using EditTextObject::operator==;
+ using EditTextObject::isWrongListEqual;
+
+private:
+ ContentInfoList aContents;
+ SfxItemPool* pPool;
+ BOOL bOwnerOfPool;
+ XParaPortionList* pPortionInfo;
+
+ sal_uInt32 nObjSettings;
+ USHORT nMetric;
+ USHORT nVersion;
+ USHORT nUserType;
+ USHORT nScriptType;
+
+ BOOL bVertical;
+ BOOL bStoreUnicodeStrings;
+
+protected:
+ void DeleteContents();
+ virtual void StoreData( SvStream& rOStream ) const;
+ virtual void CreateData( SvStream& rIStream );
+ BOOL ImpChangeStyleSheets( const String& rOldName, SfxStyleFamily eOldFamily,
+ const String& rNewName, SfxStyleFamily eNewFamily );
+
+public:
+ BinTextObject( SfxItemPool* pPool );
+ BinTextObject( const BinTextObject& );
+ virtual ~BinTextObject();
+
+ virtual EditTextObject* Clone() const;
+
+ USHORT GetUserType() const;
+ void SetUserType( USHORT n );
+
+ ULONG GetObjectSettings() const;
+ void SetObjectSettings( ULONG n );
+
+ BOOL IsVertical() const;
+ void SetVertical( BOOL b );
+
+ USHORT GetScriptType() const;
+ void SetScriptType( USHORT nType );
+
+ USHORT GetVersion() const; // Solange der Outliner keine Recordlaenge speichert
+
+ ContentInfo* CreateAndInsertContent();
+ XEditAttribute* CreateAttrib( const SfxPoolItem& rItem, USHORT nStart, USHORT nEnd );
+ void DestroyAttrib( XEditAttribute* pAttr );
+
+ ContentInfoList& GetContents() { return aContents; }
+ const ContentInfoList& GetContents() const { return aContents; }
+ SfxItemPool* GetPool() const { return pPool; }
+ XParaPortionList* GetPortionInfo() const { return pPortionInfo; }
+ void SetPortionInfo( XParaPortionList* pP )
+ { pPortionInfo = pP; }
+
+ virtual USHORT GetParagraphCount() const;
+ virtual String GetText( USHORT nParagraph ) const;
+ virtual void Insert( const EditTextObject& rObj, USHORT nPara );
+ virtual EditTextObject* CreateTextObject( USHORT nPara, USHORT nParas = 1 ) const;
+ virtual void RemoveParagraph( USHORT nPara );
+
+ virtual BOOL HasPortionInfo() const;
+ virtual void ClearPortionInfo();
+
+ virtual BOOL HasOnlineSpellErrors() const;
+
+ virtual BOOL HasCharAttribs( USHORT nWhich = 0 ) const;
+ virtual void GetCharAttribs( USHORT nPara, EECharAttribArray& rLst ) const;
+
+ virtual BOOL RemoveCharAttribs( USHORT nWhich = 0 );
+ virtual BOOL RemoveParaAttribs( USHORT nWhich = 0 );
+
+ virtual void MergeParaAttribs( const SfxItemSet& rAttribs, USHORT nStart, USHORT nEnd );
+
+ virtual BOOL IsFieldObject() const;
+ virtual const SvxFieldItem* GetField() const;
+ virtual BOOL HasField( TypeId Type = NULL ) const;
+
+ SfxItemSet GetParaAttribs( USHORT nPara ) const;
+ void SetParaAttribs( USHORT nPara, const SfxItemSet& rAttribs );
+
+ virtual BOOL HasStyleSheet( const XubString& rName, SfxStyleFamily eFamily ) const;
+ virtual void GetStyleSheet( USHORT nPara, XubString& rName, SfxStyleFamily& eFamily ) const;
+ virtual void SetStyleSheet( USHORT nPara, const XubString& rName, const SfxStyleFamily& eFamily );
+ virtual BOOL ChangeStyleSheets( const XubString& rOldName, SfxStyleFamily eOldFamily,
+ const String& rNewName, SfxStyleFamily eNewFamily );
+ virtual void ChangeStyleSheetName( SfxStyleFamily eFamily, const XubString& rOldName, const XubString& rNewName );
+
+ void CreateData300( SvStream& rIStream );
+
+ BOOL HasMetric() const { return nMetric != 0xFFFF; }
+ USHORT GetMetric() const { return nMetric; }
+ void SetMetric( USHORT n ) { nMetric = n; }
+
+ BOOL IsOwnerOfPool() const { return bOwnerOfPool; }
+ void StoreUnicodeStrings( BOOL b ) { bStoreUnicodeStrings = b; }
+
+/* cl removed because not needed anymore since binfilter
+ void PrepareStore( SfxStyleSheetPool* pStyleSheetPool );
+ void FinishStore();
+ void FinishLoad( SfxStyleSheetPool* pStyleSheetPool );
+*/
+
+ bool operator==( const BinTextObject& rCompare ) const;
+
+ // #i102062#
+ bool isWrongListEqual(const BinTextObject& rCompare) const;
+
+ // from SfxItemPoolUser
+ virtual void ObjectInDestruction(const SfxItemPool& rSfxItemPool);
+};
+
+#endif // _EDITOBJ2_HXX
+
diff --git a/editeng/source/editeng/editsel.cxx b/editeng/source/editeng/editsel.cxx
new file mode 100644
index 000000000000..3ea9e9b3e290
--- /dev/null
+++ b/editeng/source/editeng/editsel.cxx
@@ -0,0 +1,121 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 <eeng_pch.hxx>
+
+#include <editsel.hxx>
+#include <impedit.hxx>
+#include <editeng/editview.hxx>
+
+// ----------------------------------------------------------------------
+// class EditSelFunctionSet
+// ----------------------------------------------------------------------
+EditSelFunctionSet::EditSelFunctionSet()
+{
+ pCurView = NULL;
+}
+
+void __EXPORT EditSelFunctionSet::CreateAnchor()
+{
+ if ( pCurView )
+ pCurView->pImpEditView->CreateAnchor();
+}
+
+void __EXPORT EditSelFunctionSet::DestroyAnchor()
+{
+ // Nur bei Mehrfachselektion
+}
+
+BOOL __EXPORT EditSelFunctionSet::SetCursorAtPoint( const Point& rPointPixel, BOOL )
+{
+ if ( pCurView )
+ return pCurView->pImpEditView->SetCursorAtPoint( rPointPixel );
+
+ return FALSE;
+}
+
+BOOL __EXPORT EditSelFunctionSet::IsSelectionAtPoint( const Point& rPointPixel )
+{
+ if ( pCurView )
+ return pCurView->pImpEditView->IsSelectionAtPoint( rPointPixel );
+
+ return FALSE;
+}
+
+void __EXPORT EditSelFunctionSet::DeselectAtPoint( const Point& )
+{
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// ! Implementieren, wenn Mehrfachselektion moeglich !
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+}
+
+void __EXPORT EditSelFunctionSet::BeginDrag()
+{
+ // Nur bei Mehrfachselektion
+}
+
+
+void __EXPORT EditSelFunctionSet::DeselectAll()
+{
+ if ( pCurView )
+ pCurView->pImpEditView->DeselectAll();
+}
+
+// ----------------------------------------------------------------------
+// class EditSelectionEngine
+// ----------------------------------------------------------------------
+EditSelectionEngine::EditSelectionEngine() : SelectionEngine( (Window*)0 )
+{
+ // Wegen Bug OV: (1994)
+ // 1995: RangeSelection lassen, SingleSelection nur fuer ListBoxen geeignet!
+ SetSelectionMode( RANGE_SELECTION );
+ EnableDrag( TRUE );
+}
+
+void EditSelectionEngine::SetCurView( EditView* pNewView )
+{
+ if ( GetFunctionSet() )
+ ((EditSelFunctionSet*)GetFunctionSet())->SetCurView( pNewView );
+
+ if ( pNewView )
+ SetWindow( pNewView->GetWindow() );
+ else
+ SetWindow( (Window*)0 );
+}
+
+EditView* EditSelectionEngine::GetCurView()
+{
+ EditView* pView = 0;
+ if ( GetFunctionSet() )
+ pView = ((EditSelFunctionSet*)GetFunctionSet())->GetCurView();
+
+ return pView;
+}
+
diff --git a/editeng/source/editeng/editsel.hxx b/editeng/source/editeng/editsel.hxx
new file mode 100644
index 000000000000..e4d5b9d71b05
--- /dev/null
+++ b/editeng/source/editeng/editsel.hxx
@@ -0,0 +1,75 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef _EDITSEL_HXX
+#define _EDITSEL_HXX
+
+#include <vcl/seleng.hxx>
+
+class EditView;
+
+// ----------------------------------------------------------------------
+// class EditSelFunctionSet
+// ----------------------------------------------------------------------
+class EditSelFunctionSet: public FunctionSet
+{
+private:
+ EditView* pCurView;
+
+public:
+ EditSelFunctionSet();
+
+ virtual void BeginDrag();
+
+ virtual void CreateAnchor();
+ virtual void DestroyAnchor();
+
+ virtual BOOL SetCursorAtPoint( const Point& rPointPixel, BOOL bDontSelectAtCursor = FALSE );
+
+ virtual BOOL IsSelectionAtPoint( const Point& rPointPixel );
+ virtual void DeselectAtPoint( const Point& rPointPixel );
+ virtual void DeselectAll();
+
+ void SetCurView( EditView* pView ) { pCurView = pView; }
+ EditView* GetCurView() { return pCurView; }
+};
+
+ // ----------------------------------------------------------------------
+// class EditSelectionEngine
+// ----------------------------------------------------------------------
+class EditSelectionEngine : public SelectionEngine
+{
+private:
+
+public:
+ EditSelectionEngine();
+
+ void SetCurView( EditView* pNewView );
+ EditView* GetCurView();
+};
+
+#endif // _EDITSEL_HXX
diff --git a/editeng/source/editeng/editstt2.hxx b/editeng/source/editeng/editstt2.hxx
new file mode 100644
index 000000000000..40c53634b5ce
--- /dev/null
+++ b/editeng/source/editeng/editstt2.hxx
@@ -0,0 +1,130 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef _EDITSTT2_HXX
+#define _EDITSTT2_HXX
+
+#include <editeng/editstat.hxx>
+
+class InternalEditStatus : public EditStatus
+{
+
+public:
+ InternalEditStatus() { ; }
+
+ void TurnOnFlags( ULONG nFlags )
+ { nControlBits |= nFlags; }
+
+ void TurnOffFlags( ULONG nFlags )
+ { nControlBits &= ~nFlags; }
+
+ void TurnOnStatusBits( ULONG nBits )
+ { nStatusBits |= nBits; }
+
+ void TurnOffStatusBits( ULONG nBits )
+ { nStatusBits &= ~nBits; }
+
+
+ BOOL UseCharAttribs() const
+ { return ( ( nControlBits & EE_CNTRL_USECHARATTRIBS ) != 0 ); }
+
+ BOOL NotifyCursorMovements() const
+ { return ( ( nControlBits & EE_CNTRL_CRSRLEFTPARA ) != 0 ); }
+
+ BOOL UseIdleFormatter() const
+ { return ( ( nControlBits & EE_CNTRL_DOIDLEFORMAT) != 0 ); }
+
+ BOOL AllowPasteSpecial() const
+ { return ( ( nControlBits & EE_CNTRL_PASTESPECIAL ) != 0 ); }
+
+ BOOL DoAutoIndenting() const
+ { return ( ( nControlBits & EE_CNTRL_AUTOINDENTING ) != 0 ); }
+
+ BOOL DoUndoAttribs() const
+ { return ( ( nControlBits & EE_CNTRL_UNDOATTRIBS ) != 0 ); }
+
+ BOOL OneCharPerLine() const
+ { return ( ( nControlBits & EE_CNTRL_ONECHARPERLINE ) != 0 ); }
+
+ BOOL IsOutliner() const
+ { return ( ( nControlBits & EE_CNTRL_OUTLINER ) != 0 ); }
+
+ BOOL IsOutliner2() const
+ { return ( ( nControlBits & EE_CNTRL_OUTLINER2 ) != 0 ); }
+
+ BOOL IsAnyOutliner() const
+ { return IsOutliner() || IsOutliner2(); }
+
+ BOOL DoNotUseColors() const
+ { return ( ( nControlBits & EE_CNTRL_NOCOLORS ) != 0 ); }
+
+ BOOL AllowBigObjects() const
+ { return ( ( nControlBits & EE_CNTRL_ALLOWBIGOBJS ) != 0 ); }
+
+ BOOL DoOnlineSpelling() const
+ { return ( ( nControlBits & EE_CNTRL_ONLINESPELLING ) != 0 ); }
+
+ BOOL DoStretch() const
+ { return ( ( nControlBits & EE_CNTRL_STRETCHING ) != 0 ); }
+
+ BOOL AutoPageSize() const
+ { return ( ( nControlBits & EE_CNTRL_AUTOPAGESIZE ) != 0 ); }
+ BOOL AutoPageWidth() const
+ { return ( ( nControlBits & EE_CNTRL_AUTOPAGESIZEX ) != 0 ); }
+ BOOL AutoPageHeight() const
+ { return ( ( nControlBits & EE_CNTRL_AUTOPAGESIZEY ) != 0 ); }
+
+ BOOL MarkFields() const
+ { return ( ( nControlBits & EE_CNTRL_MARKFIELDS ) != 0 ); }
+
+ BOOL DoRestoreFont() const
+ { return ( ( nControlBits & EE_CNTRL_RESTOREFONT ) != 0 ); }
+
+ BOOL DoImportRTFStyleSheets() const
+ { return ( ( nControlBits & EE_CNTRL_RTFSTYLESHEETS ) != 0 ); }
+
+ BOOL DoAutoCorrect() const
+ { return ( ( nControlBits & EE_CNTRL_AUTOCORRECT ) != 0 ); }
+
+ BOOL DoAutoComplete() const
+ { return ( ( nControlBits & EE_CNTRL_AUTOCOMPLETE ) != 0 ); }
+
+ BOOL DoTabIndenting() const
+ { return ( ( nControlBits & EE_CNTRL_TABINDENTING ) != 0 ); }
+
+ BOOL DoFormat100() const
+ { return ( ( nControlBits & EE_CNTRL_FORMAT100 ) != 0 ); }
+
+ BOOL ULSpaceSummation() const
+ { return ( ( nControlBits & EE_CNTRL_ULSPACESUMMATION ) != 0 ); }
+
+ BOOL ULSpaceFirstParagraph() const
+ { return ( ( nControlBits & EE_CNTRL_ULSPACEFIRSTPARA ) != 0 ); }
+};
+
+#endif // _EDITSTT2_HXX
+
diff --git a/editeng/source/editeng/editundo.cxx b/editeng/source/editeng/editundo.cxx
new file mode 100644
index 000000000000..054971c240fd
--- /dev/null
+++ b/editeng/source/editeng/editundo.cxx
@@ -0,0 +1,750 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 <eeng_pch.hxx>
+
+#include <impedit.hxx>
+#include <editundo.hxx>
+#include <editeng/editview.hxx>
+#include <editeng/editeng.hxx>
+
+DBG_NAME( EditUndo )
+
+#define MAX_UNDOS 100 // ab dieser Menge darf geloescht werden....
+#define MIN_UNDOS 50 // soviel muss stehen bleiben...
+
+#define NO_UNDO 0xFFFF
+#define GROUP_NOTFOUND 0xFFFF
+
+TYPEINIT1( EditUndo, SfxUndoAction );
+TYPEINIT1( EditUndoDelContent, EditUndo );
+TYPEINIT1( EditUndoConnectParas, EditUndo );
+TYPEINIT1( EditUndoSplitPara, EditUndo );
+TYPEINIT1( EditUndoInsertChars, EditUndo );
+TYPEINIT1( EditUndoRemoveChars, EditUndo );
+TYPEINIT1( EditUndoInsertFeature, EditUndo );
+TYPEINIT1( EditUndoMoveParagraphs, EditUndo );
+TYPEINIT1( EditUndoSetStyleSheet, EditUndo );
+TYPEINIT1( EditUndoSetParaAttribs, EditUndo );
+TYPEINIT1( EditUndoSetAttribs, EditUndo );
+TYPEINIT1( EditUndoTransliteration, EditUndo );
+TYPEINIT1( EditUndoMarkSelection, EditUndo );
+
+void lcl_DoSetSelection( EditView* pView, USHORT nPara )
+{
+ EPaM aEPaM( nPara, 0 );
+ EditPaM aPaM( pView->GetImpEditEngine()->CreateEditPaM( aEPaM ) );
+ aPaM.SetIndex( aPaM.GetNode()->Len() );
+ EditSelection aSel( aPaM, aPaM );
+ pView->GetImpEditView()->SetEditSelection( aSel );
+}
+
+ // -----------------------------------------------------------------------
+// EditUndoManager
+// ------------------------------------------------------------------------
+EditUndoManager::EditUndoManager( ImpEditEngine* p )
+{
+ pImpEE = p;
+}
+
+BOOL __EXPORT EditUndoManager::Undo( USHORT nCount )
+{
+ if ( GetUndoActionCount() == 0 )
+ return FALSE;
+
+ DBG_ASSERT( pImpEE->GetActiveView(), "Active View?" );
+
+ if ( !pImpEE->GetActiveView() )
+ {
+ if ( pImpEE->GetEditViews().Count() )
+ pImpEE->SetActiveView( pImpEE->GetEditViews().GetObject(0) );
+ else
+ {
+ DBG_ERROR( "Undo in Engine ohne View nicht moeglich!" );
+ return FALSE;
+ }
+ }
+
+ pImpEE->GetActiveView()->GetImpEditView()->DrawSelection(); // alte Selektion entfernen
+
+ pImpEE->SetUndoMode( TRUE );
+ BOOL bDone = SfxUndoManager::Undo( nCount );
+ pImpEE->SetUndoMode( FALSE );
+
+ EditSelection aNewSel( pImpEE->GetActiveView()->GetImpEditView()->GetEditSelection() );
+ DBG_ASSERT( !aNewSel.IsInvalid(), "Ungueltige Selektion nach Undo()" );
+ DBG_ASSERT( !aNewSel.DbgIsBuggy( pImpEE->GetEditDoc() ), "Kaputte Selektion nach Undo()" );
+
+ aNewSel.Min() = aNewSel.Max();
+ pImpEE->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel );
+ pImpEE->FormatAndUpdate( pImpEE->GetActiveView() );
+
+ return bDone;
+}
+
+BOOL __EXPORT EditUndoManager::Redo( USHORT nCount )
+{
+ if ( GetRedoActionCount() == 0 )
+ return FALSE;
+
+ DBG_ASSERT( pImpEE->GetActiveView(), "Active View?" );
+
+ if ( !pImpEE->GetActiveView() )
+ {
+ if ( pImpEE->GetEditViews().Count() )
+ pImpEE->SetActiveView( pImpEE->GetEditViews().GetObject(0) );
+ else
+ {
+ DBG_ERROR( "Redo in Engine ohne View nicht moeglich!" );
+ return FALSE;
+ }
+ }
+
+ pImpEE->GetActiveView()->GetImpEditView()->DrawSelection(); // alte Selektion entfernen
+
+ pImpEE->SetUndoMode( TRUE );
+ BOOL bDone = SfxUndoManager::Redo( nCount );
+ pImpEE->SetUndoMode( FALSE );
+
+ EditSelection aNewSel( pImpEE->GetActiveView()->GetImpEditView()->GetEditSelection() );
+ DBG_ASSERT( !aNewSel.IsInvalid(), "Ungueltige Selektion nach Undo()" );
+ DBG_ASSERT( !aNewSel.DbgIsBuggy( pImpEE->GetEditDoc() ), "Kaputte Selektion nach Redo()" );
+
+ aNewSel.Min() = aNewSel.Max();
+ pImpEE->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel );
+ pImpEE->FormatAndUpdate( pImpEE->GetActiveView() );
+
+ return bDone;
+}
+
+ // -----------------------------------------------------------------------
+// EditUndo
+// ------------------------------------------------------------------------
+EditUndo::EditUndo( USHORT nI, ImpEditEngine* p )
+{
+ DBG_CTOR( EditUndo, 0 );
+ nId = nI;
+ pImpEE = p;
+}
+
+EditUndo::~EditUndo()
+{
+ DBG_DTOR( EditUndo, 0 );
+}
+
+USHORT __EXPORT EditUndo::GetId() const
+{
+ DBG_CHKTHIS( EditUndo, 0 );
+ return nId;
+}
+
+BOOL __EXPORT EditUndo::CanRepeat(SfxRepeatTarget&) const
+{
+ return FALSE;
+}
+
+XubString __EXPORT EditUndo::GetComment() const
+{
+ XubString aComment;
+ if ( pImpEE )
+ {
+ EditEngine* pEditEng = pImpEE->GetEditEnginePtr();
+ aComment = pEditEng->GetUndoComment( GetId() );
+ }
+ return aComment;
+}
+
+ // -----------------------------------------------------------------------
+// EditUndoDelContent
+// ------------------------------------------------------------------------
+EditUndoDelContent::EditUndoDelContent( ImpEditEngine* _pImpEE, ContentNode* pNode, USHORT n )
+ : EditUndo( EDITUNDO_DELCONTENT, _pImpEE )
+{
+ pContentNode = pNode;
+ nNode = n;
+ bDelObject = TRUE;
+}
+
+EditUndoDelContent::~EditUndoDelContent()
+{
+ if ( bDelObject )
+ delete pContentNode;
+}
+
+void __EXPORT EditUndoDelContent::Undo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+ GetImpEditEngine()->InsertContent( pContentNode, nNode );
+ bDelObject = FALSE; // gehoert wieder der Engine
+ EditSelection aSel( EditPaM( pContentNode, 0 ), EditPaM( pContentNode, pContentNode->Len() ) );
+ GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aSel );
+}
+
+void __EXPORT EditUndoDelContent::Redo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+
+ ImpEditEngine* _pImpEE = GetImpEditEngine();
+
+ // pNode stimmt nicht mehr, falls zwischendurch Undos, in denen
+ // Absaetze verschmolzen sind.
+ pContentNode = _pImpEE->GetEditDoc().SaveGetObject( nNode );
+ DBG_ASSERT( pContentNode, "EditUndoDelContent::Redo(): Node?!" );
+
+ delete _pImpEE->GetParaPortions()[nNode];
+ _pImpEE->GetParaPortions().Remove( nNode );
+
+ // Node nicht loeschen, haengt im Undo!
+ _pImpEE->GetEditDoc().Remove( nNode );
+ if( _pImpEE->IsCallParaInsertedOrDeleted() )
+ _pImpEE->GetEditEnginePtr()->ParagraphDeleted( nNode );
+
+ DeletedNodeInfo* pInf = new DeletedNodeInfo( (ULONG)pContentNode, nNode );
+ _pImpEE->aDeletedNodes.Insert( pInf, _pImpEE->aDeletedNodes.Count() );
+ _pImpEE->UpdateSelections();
+
+ ContentNode* pN = ( nNode < _pImpEE->GetEditDoc().Count() )
+ ? _pImpEE->GetEditDoc().SaveGetObject( nNode )
+ : _pImpEE->GetEditDoc().SaveGetObject( nNode-1 );
+ DBG_ASSERT( pN && ( pN != pContentNode ), "?! RemoveContent !? " );
+ EditPaM aPaM( pN, pN->Len() );
+
+ bDelObject = TRUE; // gehoert wieder dem Undo
+
+ _pImpEE->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aPaM ) );
+}
+
+ // -----------------------------------------------------------------------
+// EditUndoConnectParas
+// ------------------------------------------------------------------------
+EditUndoConnectParas::EditUndoConnectParas( ImpEditEngine* _pImpEE, USHORT nN, USHORT nSP,
+ const SfxItemSet& rLeftParaAttribs, const SfxItemSet& rRightParaAttribs,
+ const SfxStyleSheet* pLeftStyle, const SfxStyleSheet* pRightStyle, BOOL bBkwrd )
+ : EditUndo( EDITUNDO_CONNECTPARAS, _pImpEE ),
+ aLeftParaAttribs( rLeftParaAttribs ),
+ aRightParaAttribs( rRightParaAttribs )
+{
+ nNode = nN;
+ nSepPos = nSP;
+
+ if ( pLeftStyle )
+ {
+ aLeftStyleName = pLeftStyle->GetName();
+ eLeftStyleFamily = pLeftStyle->GetFamily();
+ }
+ if ( pRightStyle )
+ {
+ aRightStyleName = pRightStyle->GetName();
+ eRightStyleFamily = pRightStyle->GetFamily();
+ }
+
+ bBackward = bBkwrd;
+}
+
+EditUndoConnectParas::~EditUndoConnectParas()
+{
+}
+
+void __EXPORT EditUndoConnectParas::Undo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+
+ // Bei SplitContent darf noch kein ParagraphInserted gerufen werden,
+ // weil der Outliner sich auf die Attribute verlaesst um die Tiefe
+ // des Absatzes zu initialisieren
+
+ BOOL bCall = GetImpEditEngine()->IsCallParaInsertedOrDeleted();
+ GetImpEditEngine()->SetCallParaInsertedOrDeleted( FALSE );
+
+ EditPaM aPaM = GetImpEditEngine()->SplitContent( nNode, nSepPos );
+ GetImpEditEngine()->SetParaAttribs( nNode, aLeftParaAttribs );
+ GetImpEditEngine()->SetParaAttribs( nNode+1, aRightParaAttribs );
+
+ GetImpEditEngine()->SetCallParaInsertedOrDeleted( bCall );
+ if ( GetImpEditEngine()->IsCallParaInsertedOrDeleted() )
+ GetImpEditEngine()->GetEditEnginePtr()->ParagraphInserted( nNode+1 );
+
+ if ( GetImpEditEngine()->GetStyleSheetPool() )
+ {
+ if ( aLeftStyleName.Len() )
+ GetImpEditEngine()->SetStyleSheet( (USHORT)nNode, (SfxStyleSheet*)GetImpEditEngine()->GetStyleSheetPool()->Find( aLeftStyleName, eLeftStyleFamily ) );
+ if ( aRightStyleName.Len() )
+ GetImpEditEngine()->SetStyleSheet( nNode+1, (SfxStyleSheet*)GetImpEditEngine()->GetStyleSheetPool()->Find( aRightStyleName, eRightStyleFamily ) );
+ }
+
+ GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aPaM ) );
+}
+
+void __EXPORT EditUndoConnectParas::Redo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+ EditPaM aPaM = GetImpEditEngine()->ConnectContents( nNode, bBackward );
+
+ GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aPaM ) );
+}
+
+ // -----------------------------------------------------------------------
+// EditUndoSplitPara
+// ------------------------------------------------------------------------
+EditUndoSplitPara::EditUndoSplitPara( ImpEditEngine* _pImpEE, USHORT nN, USHORT nSP )
+ : EditUndo( EDITUNDO_SPLITPARA, _pImpEE )
+{
+ nNode = nN;
+ nSepPos = nSP;
+}
+
+EditUndoSplitPara::~EditUndoSplitPara()
+{
+}
+
+void __EXPORT EditUndoSplitPara::Undo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+ EditPaM aPaM = GetImpEditEngine()->ConnectContents( nNode, FALSE );
+ GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aPaM ) );
+}
+
+void __EXPORT EditUndoSplitPara::Redo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+ EditPaM aPaM = GetImpEditEngine()->SplitContent( nNode, nSepPos );
+ GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aPaM ) );
+}
+
+ // -----------------------------------------------------------------------
+// EditUndoInsertChars
+// ------------------------------------------------------------------------
+EditUndoInsertChars::EditUndoInsertChars( ImpEditEngine* _pImpEE, const EPaM& rEPaM, const XubString& rStr )
+ : EditUndo( EDITUNDO_INSERTCHARS, _pImpEE ),
+ aEPaM( rEPaM ), aText( rStr )
+{
+}
+
+void __EXPORT EditUndoInsertChars::Undo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+ EditPaM aPaM( GetImpEditEngine()->CreateEditPaM( aEPaM ) );
+ EditSelection aSel( aPaM, aPaM );
+ aSel.Max().GetIndex() = aSel.Max().GetIndex() + aText.Len();
+ EditPaM aNewPaM( GetImpEditEngine()->ImpDeleteSelection( aSel ) );
+ GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aNewPaM, aNewPaM ) );
+}
+
+void __EXPORT EditUndoInsertChars::Redo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+ EditPaM aPaM( GetImpEditEngine()->CreateEditPaM( aEPaM ) );
+ GetImpEditEngine()->ImpInsertText( EditSelection( aPaM, aPaM ), aText );
+ EditPaM aNewPaM( aPaM );
+ aNewPaM.GetIndex() = aNewPaM.GetIndex() + aText.Len();
+ GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aNewPaM ) );
+}
+
+BOOL __EXPORT EditUndoInsertChars::Merge( SfxUndoAction* pNextAction )
+{
+ if ( !pNextAction->ISA( EditUndoInsertChars ) )
+ return FALSE;
+
+ EditUndoInsertChars* pNext = (EditUndoInsertChars*)pNextAction;
+
+ if ( aEPaM.nPara != pNext->aEPaM.nPara )
+ return FALSE;
+
+ if ( ( aEPaM.nIndex + aText.Len() ) == pNext->aEPaM.nIndex )
+ {
+ aText += pNext->aText;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+ // -----------------------------------------------------------------------
+// EditUndoRemoveChars
+// ------------------------------------------------------------------------
+EditUndoRemoveChars::EditUndoRemoveChars( ImpEditEngine* _pImpEE, const EPaM& rEPaM, const XubString& rStr )
+ : EditUndo( EDITUNDO_REMOVECHARS, _pImpEE ),
+ aEPaM( rEPaM ), aText( rStr )
+{
+}
+
+void __EXPORT EditUndoRemoveChars::Undo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+ EditPaM aPaM( GetImpEditEngine()->CreateEditPaM( aEPaM ) );
+ EditSelection aSel( aPaM, aPaM );
+ GetImpEditEngine()->ImpInsertText( aSel, aText );
+ aSel.Max().GetIndex() = aSel.Max().GetIndex() + aText.Len();
+ GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aSel );
+}
+
+void __EXPORT EditUndoRemoveChars::Redo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+ EditPaM aPaM( GetImpEditEngine()->CreateEditPaM( aEPaM ) );
+ EditSelection aSel( aPaM, aPaM );
+ aSel.Max().GetIndex() = aSel.Max().GetIndex() + aText.Len();
+ EditPaM aNewPaM = GetImpEditEngine()->ImpDeleteSelection( aSel );
+ GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aNewPaM );
+}
+
+ // -----------------------------------------------------------------------
+// EditUndoInsertFeature
+// ------------------------------------------------------------------------
+EditUndoInsertFeature::EditUndoInsertFeature( ImpEditEngine* _pImpEE, const EPaM& rEPaM, const SfxPoolItem& rFeature)
+ : EditUndo( EDITUNDO_INSERTFEATURE, _pImpEE ), aEPaM( rEPaM )
+{
+ pFeature = rFeature.Clone();
+ DBG_ASSERT( pFeature, "Feature konnte nicht dupliziert werden: EditUndoInsertFeature" );
+}
+
+EditUndoInsertFeature::~EditUndoInsertFeature()
+{
+ delete pFeature;
+}
+
+void __EXPORT EditUndoInsertFeature::Undo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+ EditPaM aPaM( GetImpEditEngine()->CreateEditPaM( aEPaM ) );
+ EditSelection aSel( aPaM, aPaM );
+ // Attribute werden dort implizit vom Dokument korrigiert...
+ aSel.Max().GetIndex()++;
+ EditPaM aNewPaM = GetImpEditEngine()->ImpDeleteSelection( aSel );
+ aSel.Max().GetIndex()--; // Fuer Selektion
+ GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aSel );
+}
+
+void __EXPORT EditUndoInsertFeature::Redo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+ EditPaM aPaM( GetImpEditEngine()->CreateEditPaM( aEPaM ) );
+ EditSelection aSel( aPaM, aPaM );
+ GetImpEditEngine()->ImpInsertFeature( aSel, *pFeature );
+ if ( pFeature->Which() == EE_FEATURE_FIELD )
+ GetImpEditEngine()->UpdateFields();
+ aSel.Max().GetIndex()++;
+ GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aSel );
+}
+
+ // -----------------------------------------------------------------------
+// EditUndoMoveParagraphs
+// ------------------------------------------------------------------------
+EditUndoMoveParagraphs::EditUndoMoveParagraphs
+ ( ImpEditEngine* _pImpEE, const Range& rParas, USHORT n )
+ : EditUndo( EDITUNDO_MOVEPARAGRAPHS, _pImpEE ),
+ nParagraphs( rParas )
+{
+ nDest = n;
+}
+
+EditUndoMoveParagraphs::~EditUndoMoveParagraphs()
+{
+}
+
+void __EXPORT EditUndoMoveParagraphs::Undo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+ Range aTmpRange( nParagraphs );
+ long nTmpDest = aTmpRange.Min();
+
+ long nDiff = ( nDest - aTmpRange.Min() );
+ aTmpRange.Min() += nDiff;
+ aTmpRange.Max() += nDiff;
+
+ if ( nParagraphs.Min() < (long)nDest )
+ {
+ long nLen = aTmpRange.Len();
+ aTmpRange.Min() -= nLen;
+ aTmpRange.Max() -= nLen;
+ }
+ else
+ nTmpDest += aTmpRange.Len();
+
+ EditSelection aNewSel( GetImpEditEngine()->MoveParagraphs( aTmpRange, (USHORT)nTmpDest, 0 ) );
+ GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel );
+}
+
+void __EXPORT EditUndoMoveParagraphs::Redo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+ EditSelection aNewSel( GetImpEditEngine()->MoveParagraphs( nParagraphs, nDest, 0 ) );
+ GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel );
+}
+
+ // -----------------------------------------------------------------------
+// EditUndoSetStyleSheet
+// ------------------------------------------------------------------------
+EditUndoSetStyleSheet::EditUndoSetStyleSheet( ImpEditEngine* _pImpEE, USHORT nP,
+ const XubString& rPrevName, SfxStyleFamily ePrevFam,
+ const XubString& rNewName, SfxStyleFamily eNewFam,
+ const SfxItemSet& rPrevParaAttribs )
+ : EditUndo( EDITUNDO_STYLESHEET, _pImpEE ), aPrevName( rPrevName ), aNewName( rNewName ),
+ aPrevParaAttribs( rPrevParaAttribs )
+{
+ ePrevFamily = ePrevFam;
+ eNewFamily = eNewFam;
+ nPara = nP;
+}
+
+EditUndoSetStyleSheet::~EditUndoSetStyleSheet()
+{
+}
+
+void __EXPORT EditUndoSetStyleSheet::Undo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+ GetImpEditEngine()->SetStyleSheet( nPara, (SfxStyleSheet*)GetImpEditEngine()->GetStyleSheetPool()->Find( aPrevName, ePrevFamily ) );
+ GetImpEditEngine()->SetParaAttribs( nPara, aPrevParaAttribs );
+ lcl_DoSetSelection( GetImpEditEngine()->GetActiveView(), nPara );
+}
+
+void __EXPORT EditUndoSetStyleSheet::Redo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+ GetImpEditEngine()->SetStyleSheet( nPara, (SfxStyleSheet*)GetImpEditEngine()->GetStyleSheetPool()->Find( aNewName, eNewFamily ) );
+ lcl_DoSetSelection( GetImpEditEngine()->GetActiveView(), nPara );
+}
+
+ // -----------------------------------------------------------------------
+// EditUndoSetParaAttribs
+// ------------------------------------------------------------------------
+EditUndoSetParaAttribs::EditUndoSetParaAttribs( ImpEditEngine* _pImpEE, USHORT nP, const SfxItemSet& rPrevItems, const SfxItemSet& rNewItems )
+ : EditUndo( EDITUNDO_PARAATTRIBS, _pImpEE ),
+ aPrevItems( rPrevItems ),
+ aNewItems(rNewItems )
+{
+ nPara = nP;
+}
+
+EditUndoSetParaAttribs::~EditUndoSetParaAttribs()
+{
+}
+
+void __EXPORT EditUndoSetParaAttribs::Undo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+ GetImpEditEngine()->SetParaAttribs( nPara, aPrevItems );
+ lcl_DoSetSelection( GetImpEditEngine()->GetActiveView(), nPara );
+}
+
+void __EXPORT EditUndoSetParaAttribs::Redo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+ GetImpEditEngine()->SetParaAttribs( nPara, aNewItems );
+ lcl_DoSetSelection( GetImpEditEngine()->GetActiveView(), nPara );
+}
+
+ // -----------------------------------------------------------------------
+// EditUndoSetAttribs
+// ------------------------------------------------------------------------
+EditUndoSetAttribs::EditUndoSetAttribs( ImpEditEngine* _pImpEE, const ESelection& rESel, const SfxItemSet& rNewItems )
+ : EditUndo( EDITUNDO_ATTRIBS, _pImpEE ),
+ aESel( rESel ),
+ aNewAttribs( rNewItems )
+{
+ // Wenn das EditUndoSetAttribs eigentlich ein RemoveAttribs ist, koennte
+ // man das eigentlich an einem leeren ItemSet erkennen, aber dann muesste
+ // an einigen Stellen abgefangen werden, das ggf. ein SetAttribs mit einem
+ // leeren ItemSet gemacht wird.
+ // => Ich habe lieber diesen Member spendiert...
+ bSetIsRemove = FALSE;
+ bRemoveParaAttribs = FALSE;
+ nRemoveWhich = 0;
+ nSpecial = 0;
+}
+
+EditUndoSetAttribs::~EditUndoSetAttribs()
+{
+ // Items aus Pool holen...
+ SfxItemPool* pPool = aNewAttribs.GetPool();
+ USHORT nContents = aPrevAttribs.Count();
+ for ( USHORT n = 0; n < nContents; n++ )
+ {
+ ContentAttribsInfo* pInf = aPrevAttribs[n];
+ DBG_ASSERT( pInf, "Undo_DTOR (SetAttribs): pInf = NULL!" );
+ for ( USHORT nAttr = 0; nAttr < pInf->GetPrevCharAttribs().Count(); nAttr++ )
+ {
+ EditCharAttrib* pX = pInf->GetPrevCharAttribs()[nAttr];
+ DBG_ASSERT( pX, "Undo_DTOR (SetAttribs): pX = NULL!" );
+ pPool->Remove( *pX->GetItem() );
+ delete pX;
+ }
+ delete pInf;
+ }
+}
+
+void __EXPORT EditUndoSetAttribs::Undo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+ ImpEditEngine* _pImpEE = GetImpEditEngine();
+ BOOL bFields = FALSE;
+ for ( USHORT nPara = aESel.nStartPara; nPara <= aESel.nEndPara; nPara++ )
+ {
+ ContentAttribsInfo* pInf = aPrevAttribs[ (USHORT)(nPara-aESel.nStartPara) ];
+ DBG_ASSERT( pInf, "Undo (SetAttribs): pInf = NULL!" );
+
+ // erstmal die Absatzattribute...
+ _pImpEE->SetParaAttribs( nPara, pInf->GetPrevParaAttribs() );
+
+ // Dann die Zeichenattribute...
+ // Alle Attribute inkl. Features entfernen, werden wieder neu eingestellt.
+ _pImpEE->RemoveCharAttribs( nPara, 0, TRUE );
+ DBG_ASSERT( _pImpEE->GetEditDoc().SaveGetObject( nPara ), "Undo (SetAttribs): pNode = NULL!" );
+ ContentNode* pNode = _pImpEE->GetEditDoc().GetObject( nPara );
+ for ( USHORT nAttr = 0; nAttr < pInf->GetPrevCharAttribs().Count(); nAttr++ )
+ {
+ EditCharAttrib* pX = pInf->GetPrevCharAttribs()[nAttr];
+ DBG_ASSERT( pX, "Redo (SetAttribs): pX = NULL!" );
+ // wird autom. 'eingepoolt'.
+ _pImpEE->GetEditDoc().InsertAttrib( pNode, pX->GetStart(), pX->GetEnd(), *pX->GetItem() );
+ if ( pX->Which() == EE_FEATURE_FIELD )
+ bFields = TRUE;
+ }
+ }
+ if ( bFields )
+ _pImpEE->UpdateFields();
+ ImpSetSelection( GetImpEditEngine()->GetActiveView() );
+}
+
+void __EXPORT EditUndoSetAttribs::Redo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+ ImpEditEngine* _pImpEE = GetImpEditEngine();
+
+ EditSelection aSel( _pImpEE->CreateSel( aESel ) );
+ if ( !bSetIsRemove )
+ _pImpEE->SetAttribs( aSel, aNewAttribs, nSpecial );
+ else
+ _pImpEE->RemoveCharAttribs( aSel, bRemoveParaAttribs, nRemoveWhich );
+
+ ImpSetSelection( GetImpEditEngine()->GetActiveView() );
+}
+
+void EditUndoSetAttribs::ImpSetSelection( EditView* /*pView*/ )
+{
+ ImpEditEngine* _pImpEE = GetImpEditEngine();
+ EditSelection aSel( _pImpEE->CreateSel( aESel ) );
+ GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aSel );
+}
+
+ // -----------------------------------------------------------------------
+// EditUndoTransliteration
+// ------------------------------------------------------------------------
+EditUndoTransliteration::EditUndoTransliteration( ImpEditEngine* _pImpEE, const ESelection& rESel, sal_Int32 nM )
+ : EditUndo( EDITUNDO_TRANSLITERATE, _pImpEE ), aOldESel( rESel )
+{
+ nMode = nM;
+ pTxtObj = NULL;
+}
+
+EditUndoTransliteration::~EditUndoTransliteration()
+{
+ delete pTxtObj;
+}
+
+void __EXPORT EditUndoTransliteration::Undo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+
+ ImpEditEngine* _pImpEE = GetImpEditEngine();
+
+ EditSelection aSel( _pImpEE->CreateSel( aNewESel ) );
+
+ // Insert text, but don't expand Atribs at the current position:
+ aSel = _pImpEE->DeleteSelected( aSel );
+ EditSelection aDelSel( aSel );
+ aSel = _pImpEE->InsertParaBreak( aSel );
+ aDelSel.Max() = aSel.Min();
+ aDelSel.Max().GetNode()->GetCharAttribs().DeleteEmptyAttribs( _pImpEE->GetEditDoc().GetItemPool() );
+ EditSelection aNewSel;
+ if ( pTxtObj )
+ {
+ aNewSel = _pImpEE->InsertText( *pTxtObj, aSel );
+ }
+ else
+ {
+ aNewSel = _pImpEE->InsertText( aSel, aText );
+ }
+ if ( aNewSel.Min().GetNode() == aDelSel.Max().GetNode() )
+ {
+ aNewSel.Min().SetNode( aDelSel.Min().GetNode() );
+ aNewSel.Min().GetIndex() =
+ aNewSel.Min().GetIndex() + aDelSel.Min().GetIndex();
+ }
+ if ( aNewSel.Max().GetNode() == aDelSel.Max().GetNode() )
+ {
+ aNewSel.Max().SetNode( aDelSel.Min().GetNode() );
+ aNewSel.Max().GetIndex() =
+ aNewSel.Max().GetIndex() + aDelSel.Min().GetIndex();
+ }
+ _pImpEE->DeleteSelected( aDelSel );
+
+ GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel );
+}
+
+void __EXPORT EditUndoTransliteration::Redo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+ ImpEditEngine* _pImpEE = GetImpEditEngine();
+
+ EditSelection aSel( _pImpEE->CreateSel( aOldESel ) );
+ EditSelection aNewSel = _pImpEE->TransliterateText( aSel, nMode );
+ GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel );
+}
+
+ // -----------------------------------------------------------------------
+// EditUndoMarkSelection
+// ------------------------------------------------------------------------
+EditUndoMarkSelection::EditUndoMarkSelection( ImpEditEngine* _pImpEE, const ESelection& rSel )
+ : EditUndo( EDITUNDO_MARKSELECTION, _pImpEE ), aSelection( rSel )
+{
+}
+
+EditUndoMarkSelection::~EditUndoMarkSelection()
+{
+}
+
+void __EXPORT EditUndoMarkSelection::Undo()
+{
+ DBG_ASSERT( GetImpEditEngine()->GetActiveView(), "Undo/Redo: Keine Active View!" );
+ if ( GetImpEditEngine()->GetActiveView() )
+ {
+ if ( GetImpEditEngine()->IsFormatted() )
+ GetImpEditEngine()->GetActiveView()->SetSelection( aSelection );
+ else
+ GetImpEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( GetImpEditEngine()->CreateSel( aSelection ) );
+ }
+}
+
+void __EXPORT EditUndoMarkSelection::Redo()
+{
+ // Fuer Redo unwichtig, weil am Anfang der Undo-Klammerung
+}
+
diff --git a/editeng/source/editeng/editundo.hxx b/editeng/source/editeng/editundo.hxx
new file mode 100644
index 000000000000..4c54c553c353
--- /dev/null
+++ b/editeng/source/editeng/editundo.hxx
@@ -0,0 +1,315 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef _EDITUNDO_HXX
+#define _EDITUNDO_HXX
+
+#include <editdoc.hxx>
+#include <editeng/editund2.hxx>
+#include <editeng/editdata.hxx>
+
+#define UNDO_NOACTION 0
+#define UNDO_NEWUNDO 1
+#define UNDO_UNDOSDELETED 2
+#define UNDO_EMPTYGROUPDELETED 3
+#define UNDO_INVALIDEND 4
+
+class ImpEditEngine;
+class EditView;
+
+// -----------------------------------------------------------------------
+// EditUndoDelContent
+// ------------------------------------------------------------------------
+class EditUndoDelContent : public EditUndo
+{
+private:
+ BOOL bDelObject;
+ USHORT nNode;
+ ContentNode* pContentNode; // Zeigt auf das gueltige,
+ // nicht zerstoerte Objekt!
+
+public:
+ TYPEINFO();
+ EditUndoDelContent( ImpEditEngine* pImpEE, ContentNode* pNode, USHORT nPortio );
+ ~EditUndoDelContent();
+
+ virtual void Undo();
+ virtual void Redo();
+};
+
+// -----------------------------------------------------------------------
+// EditUndoConnectParas
+// ------------------------------------------------------------------------
+class EditUndoConnectParas : public EditUndo
+{
+private:
+ USHORT nNode;
+ USHORT nSepPos;
+ SfxItemSet aLeftParaAttribs;
+ SfxItemSet aRightParaAttribs;
+
+ // 2 Pointer waeren schoener, aber dann muesste es ein SfxListener sein.
+ String aLeftStyleName;
+ String aRightStyleName;
+ SfxStyleFamily eLeftStyleFamily;
+ SfxStyleFamily eRightStyleFamily;
+
+ BOOL bBackward;
+
+public:
+ TYPEINFO();
+ EditUndoConnectParas( ImpEditEngine* pImpEE, USHORT nNode, USHORT nSepPos,
+ const SfxItemSet& rLeftParaAttribs, const SfxItemSet& rRightParaAttribs,
+ const SfxStyleSheet* pLeftStyle, const SfxStyleSheet* pRightStyle, BOOL bBackward );
+ ~EditUndoConnectParas();
+
+ virtual void Undo();
+ virtual void Redo();
+};
+
+// -----------------------------------------------------------------------
+// EditUndoSplitPara
+// ------------------------------------------------------------------------
+class EditUndoSplitPara : public EditUndo
+{
+private:
+ USHORT nNode;
+ USHORT nSepPos;
+
+public:
+ TYPEINFO();
+ EditUndoSplitPara( ImpEditEngine* pImpEE, USHORT nNode, USHORT nSepPos );
+ ~EditUndoSplitPara();
+
+ virtual void Undo();
+ virtual void Redo();
+};
+
+// -----------------------------------------------------------------------
+// EditUndoInsertChars
+// ------------------------------------------------------------------------
+class EditUndoInsertChars : public EditUndo
+{
+private:
+ EPaM aEPaM;
+ String aText;
+
+public:
+ TYPEINFO();
+ EditUndoInsertChars( ImpEditEngine* pImpEE, const EPaM& rEPaM, const String& rStr );
+
+ const EPaM& GetEPaM() { return aEPaM; }
+ String& GetStr() { return aText; }
+
+ virtual void Undo();
+ virtual void Redo();
+
+ virtual BOOL Merge( SfxUndoAction *pNextAction );
+};
+
+// -----------------------------------------------------------------------
+// EditUndoRemoveChars
+// ------------------------------------------------------------------------
+class EditUndoRemoveChars : public EditUndo
+{
+private:
+ EPaM aEPaM;
+ String aText;
+
+public:
+ TYPEINFO();
+ EditUndoRemoveChars( ImpEditEngine* pImpEE, const EPaM& rEPaM, const String& rStr );
+
+ const EPaM& GetEPaM() { return aEPaM; }
+ String& GetStr() { return aText; }
+
+ virtual void Undo();
+ virtual void Redo();
+};
+
+// -----------------------------------------------------------------------
+// EditUndoInsertFeature
+// ------------------------------------------------------------------------
+class EditUndoInsertFeature : public EditUndo
+{
+private:
+ EPaM aEPaM;
+ SfxPoolItem* pFeature;
+
+public:
+ TYPEINFO();
+ EditUndoInsertFeature( ImpEditEngine* pImpEE, const EPaM& rEPaM,
+ const SfxPoolItem& rFeature);
+ ~EditUndoInsertFeature();
+
+ virtual void Undo();
+ virtual void Redo();
+};
+
+// -----------------------------------------------------------------------
+// EditUndoMoveParagraphs
+// ------------------------------------------------------------------------
+class EditUndoMoveParagraphs: public EditUndo
+{
+private:
+ Range nParagraphs;
+ USHORT nDest;
+
+public:
+ TYPEINFO();
+ EditUndoMoveParagraphs( ImpEditEngine* pImpEE, const Range& rParas, USHORT nDest );
+ ~EditUndoMoveParagraphs();
+
+ virtual void Undo();
+ virtual void Redo();
+};
+
+// -----------------------------------------------------------------------
+// EditUndoSetStyleSheet
+// ------------------------------------------------------------------------
+class EditUndoSetStyleSheet: public EditUndo
+{
+private:
+ USHORT nPara;
+ XubString aPrevName;
+ XubString aNewName;
+ SfxStyleFamily ePrevFamily;
+ SfxStyleFamily eNewFamily;
+ SfxItemSet aPrevParaAttribs;
+
+public:
+ TYPEINFO();
+
+ EditUndoSetStyleSheet( ImpEditEngine* pImpEE, USHORT nPara,
+ const XubString& rPrevName, SfxStyleFamily ePrevFamily,
+ const XubString& rNewName, SfxStyleFamily eNewFamily,
+ const SfxItemSet& rPrevParaAttribs );
+ ~EditUndoSetStyleSheet();
+
+ virtual void Undo();
+ virtual void Redo();
+};
+
+// -----------------------------------------------------------------------
+// EditUndoSetParaAttribs
+// ------------------------------------------------------------------------
+class EditUndoSetParaAttribs: public EditUndo
+{
+private:
+ USHORT nPara;
+ SfxItemSet aPrevItems;
+ SfxItemSet aNewItems;
+
+public:
+ TYPEINFO();
+ EditUndoSetParaAttribs( ImpEditEngine* pImpEE, USHORT nPara, const SfxItemSet& rPrevItems, const SfxItemSet& rNewItems );
+ ~EditUndoSetParaAttribs();
+
+ virtual void Undo();
+ virtual void Redo();
+};
+
+// -----------------------------------------------------------------------
+// EditUndoSetAttribs
+// ------------------------------------------------------------------------
+class EditUndoSetAttribs: public EditUndo
+{
+private:
+ ESelection aESel;
+ SfxItemSet aNewAttribs;
+ ContentInfoArray aPrevAttribs;
+
+ BYTE nSpecial;
+ BOOL bSetIsRemove;
+ BOOL bRemoveParaAttribs;
+ USHORT nRemoveWhich;
+
+ void ImpSetSelection( EditView* pView );
+
+
+public:
+ TYPEINFO();
+ EditUndoSetAttribs( ImpEditEngine* pImpEE, const ESelection& rESel, const SfxItemSet& rNewItems );
+ ~EditUndoSetAttribs();
+
+ ContentInfoArray& GetContentInfos() { return aPrevAttribs; }
+ SfxItemSet& GetNewAttribs() { return aNewAttribs; }
+
+ void SetSpecial( BYTE n ) { nSpecial = n; }
+ void SetRemoveAttribs( BOOL b ) { bSetIsRemove = b; }
+ void SetRemoveParaAttribs( BOOL b ) { bRemoveParaAttribs = b; }
+ void SetRemoveWhich( USHORT n ) { nRemoveWhich = n; }
+
+ virtual void Undo();
+ virtual void Redo();
+};
+
+// -----------------------------------------------------------------------
+// EditUndoTransliteration
+// ------------------------------------------------------------------------
+class EditUndoTransliteration: public EditUndo
+{
+private:
+ ESelection aOldESel;
+ ESelection aNewESel;
+
+ sal_Int32 nMode;
+ EditTextObject* pTxtObj;
+ String aText;
+
+public:
+ TYPEINFO();
+ EditUndoTransliteration( ImpEditEngine* pImpEE, const ESelection& rESel, sal_Int32 nMode );
+ ~EditUndoTransliteration();
+
+ void SetText( const String& rText ) { aText = rText; }
+ void SetText( EditTextObject* pObj ) { pTxtObj = pObj; }
+ void SetNewSelection( const ESelection& rSel ) { aNewESel = rSel; }
+
+ virtual void Undo();
+ virtual void Redo();
+};
+
+// -----------------------------------------------------------------------
+// EditUndoMarkSelection
+// ------------------------------------------------------------------------
+class EditUndoMarkSelection: public EditUndo
+{
+private:
+ ESelection aSelection;
+
+public:
+ TYPEINFO();
+ EditUndoMarkSelection( ImpEditEngine* pImpEE, const ESelection& rSel );
+ ~EditUndoMarkSelection();
+
+ virtual void Undo();
+ virtual void Redo();
+};
+
+
+#endif // _EDITUNDO_HXX
diff --git a/editeng/source/editeng/editview.cxx b/editeng/source/editeng/editview.cxx
new file mode 100644
index 000000000000..766023a0038c
--- /dev/null
+++ b/editeng/source/editeng/editview.cxx
@@ -0,0 +1,1595 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 <com/sun/star/i18n/WordType.hpp>
+#include <vcl/metric.hxx>
+
+#include <i18npool/mslangid.hxx>
+#include <svl/languageoptions.hxx>
+#include <svtools/ctrltool.hxx>
+#include <svtools/langtab.hxx>
+
+#include <svl/srchitem.hxx>
+
+#define _SVSTDARR_USHORTS
+#include <svl/svstdarr.hxx>
+
+#include <impedit.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/editview.hxx>
+#include <editeng/flditem.hxx>
+#include <editeng/svxacorr.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/eerdll.hxx>
+#include <eerdll2.hxx>
+#include <editeng.hrc>
+#include <helpid.hrc>
+#include <i18npool/lang.h>
+#include <vcl/menu.hxx>
+#include <editeng/acorrcfg.hxx>
+#include <editeng/unolingu.hxx>
+#include <editeng/fontitem.hxx>
+
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/beans/PropertyValues.hdl>
+#include <com/sun/star/lang/Locale.hpp>
+#include <linguistic/lngprops.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <unotools/lingucfg.hxx>
+
+using ::rtl::OUString;
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::linguistic2;
+
+
+DBG_NAME( EditView )
+
+
+// From SW => Create common method
+LanguageType lcl_CheckLanguage(
+ const OUString &rText,
+ Reference< XSpellChecker1 > xSpell,
+ Reference< linguistic2::XLanguageGuessing > xLangGuess,
+ sal_Bool bIsParaText )
+{
+ LanguageType nLang = LANGUAGE_NONE;
+ if (bIsParaText) // check longer texts with language-guessing...
+ {
+ if (!xLangGuess.is())
+ return nLang;
+
+ lang::Locale aLocale( xLangGuess->guessPrimaryLanguage( rText, 0, rText.getLength()) );
+
+ // get language as from "Tools/Options - Language Settings - Languages: Locale setting"
+ LanguageType nTmpLang = Application::GetSettings().GetLanguage();
+
+ // if the result from language guessing does not provide a 'Country' part
+ // try to get it by looking up the locale setting of the office.
+ if (aLocale.Country.getLength() == 0)
+ {
+ lang::Locale aTmpLocale = SvxCreateLocale( nTmpLang );
+ if (aTmpLocale.Language == aLocale.Language)
+ nLang = nTmpLang;
+ }
+ if (nLang == LANGUAGE_NONE) // language not found by looking up the sytem language...
+ nLang = MsLangId::convertLocaleToLanguageWithFallback( aLocale );
+ if (nLang == LANGUAGE_SYSTEM)
+ nLang = nTmpLang;
+ if (nLang == LANGUAGE_DONTKNOW)
+ nLang = LANGUAGE_NONE;
+ }
+ else // check single word
+ {
+ if (!xSpell.is())
+ return nLang;
+
+ //
+ // build list of languages to check
+ //
+ LanguageType aLangList[4];
+ const AllSettings& rSettings = Application::GetSettings();
+ SvtLinguOptions aLinguOpt;
+ SvtLinguConfig().GetOptions( aLinguOpt );
+ // The default document language from "Tools/Options - Language Settings - Languages: Western"
+ aLangList[0] = aLinguOpt.nDefaultLanguage;
+ // The one from "Tools/Options - Language Settings - Languages: User interface"
+ aLangList[1] = rSettings.GetUILanguage();
+ // The one from "Tools/Options - Language Settings - Languages: Locale setting"
+ aLangList[2] = rSettings.GetLanguage();
+ // en-US
+ aLangList[3] = LANGUAGE_ENGLISH_US;
+#ifdef DEBUG
+ lang::Locale a0( SvxCreateLocale( aLangList[0] ) );
+ lang::Locale a1( SvxCreateLocale( aLangList[1] ) );
+ lang::Locale a2( SvxCreateLocale( aLangList[2] ) );
+ lang::Locale a3( SvxCreateLocale( aLangList[3] ) );
+#endif
+
+ INT32 nCount = sizeof(aLangList) / sizeof(aLangList[0]);
+ for (INT32 i = 0; i < nCount; i++)
+ {
+ INT16 nTmpLang = aLangList[i];
+ if (nTmpLang != LANGUAGE_NONE && nTmpLang != LANGUAGE_DONTKNOW)
+ {
+ if (xSpell->hasLanguage( nTmpLang ) &&
+ xSpell->isValid( rText, nTmpLang, Sequence< PropertyValue >() ))
+ {
+ nLang = nTmpLang;
+ break;
+ }
+ }
+ }
+ }
+
+ return nLang;
+}
+
+
+ // ----------------------------------------------------------------------
+// class EditView
+// ----------------------------------------------------------------------
+EditView::EditView( EditEngine* pEng, Window* pWindow )
+{
+ DBG_CTOR( EditView, 0 );
+ pImpEditView = new ImpEditView( this, pEng, pWindow );
+}
+
+EditView::~EditView()
+{
+ DBG_DTOR( EditView, 0 );
+ delete pImpEditView;
+}
+
+ImpEditEngine* EditView::GetImpEditEngine() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ return pImpEditView->pEditEngine->pImpEditEngine;
+}
+
+EditEngine* EditView::GetEditEngine() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ return pImpEditView->pEditEngine;
+}
+
+void EditView::Invalidate()
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ if ( !pImpEditView->DoInvalidateMore() )
+ pImpEditView->GetWindow()->Invalidate( pImpEditView->aOutArea );
+ else
+ {
+ Rectangle aRect( pImpEditView->aOutArea );
+ long nMore = pImpEditView->GetWindow()->PixelToLogic( Size( pImpEditView->GetInvalidateMore(), 0 ) ).Width();
+ aRect.Left() -= nMore;
+ aRect.Right() += nMore;
+ aRect.Top() -= nMore;
+ aRect.Bottom() += nMore;
+ pImpEditView->GetWindow()->Invalidate( aRect );
+ }
+}
+
+void EditView::SetReadOnly( sal_Bool bReadOnly )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ pImpEditView->bReadOnly = bReadOnly;
+}
+
+sal_Bool EditView::IsReadOnly() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ return pImpEditView->bReadOnly;
+}
+
+void EditView::SetSelection( const ESelection& rESel )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+
+ // Falls jemand gerade ein leeres Attribut hinterlassen hat,
+ // und dann der Outliner die Selektion manipulitert:
+ if ( !pImpEditView->GetEditSelection().HasRange() )
+ {
+ ContentNode* pNode = pImpEditView->GetEditSelection().Max().GetNode();
+ PIMPEE->CursorMoved( pNode );
+ }
+ EditSelection aNewSelection( PIMPEE->ConvertSelection( rESel.nStartPara, rESel.nStartPos, rESel.nEndPara, rESel.nEndPos ) );
+
+ // Wenn nach einem KeyInput die Selection manipuliert wird:
+ PIMPEE->CheckIdleFormatter();
+
+ // Selektion darf nicht bei einem unsichtbaren Absatz Starten/Enden:
+ ParaPortion* pPortion = PIMPEE->FindParaPortion( aNewSelection.Min().GetNode() );
+ if ( !pPortion->IsVisible() )
+ {
+ pPortion = PIMPEE->GetPrevVisPortion( pPortion );
+ ContentNode* pNode = pPortion ? pPortion->GetNode() : PIMPEE->GetEditDoc().GetObject( 0 );
+ aNewSelection.Min() = EditPaM( pNode, pNode->Len() );
+ }
+ pPortion = PIMPEE->FindParaPortion( aNewSelection.Max().GetNode() );
+ if ( !pPortion->IsVisible() )
+ {
+ pPortion = PIMPEE->GetPrevVisPortion( pPortion );
+ ContentNode* pNode = pPortion ? pPortion->GetNode() : PIMPEE->GetEditDoc().GetObject( 0 );
+ aNewSelection.Max() = EditPaM( pNode, pNode->Len() );
+ }
+
+ pImpEditView->DrawSelection(); // alte Selektion 'weg-zeichnen'
+ pImpEditView->SetEditSelection( aNewSelection );
+ pImpEditView->DrawSelection();
+ sal_Bool bGotoCursor = pImpEditView->DoAutoScroll();
+ ShowCursor( bGotoCursor );
+}
+
+ESelection EditView::GetSelection() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+
+ ESelection aSelection;
+
+ aSelection.nStartPara = PIMPEE->GetEditDoc().GetPos( pImpEditView->GetEditSelection().Min().GetNode() );
+ aSelection.nEndPara = PIMPEE->GetEditDoc().GetPos( pImpEditView->GetEditSelection().Max().GetNode() );
+
+ aSelection.nStartPos = pImpEditView->GetEditSelection().Min().GetIndex();
+ aSelection.nEndPos = pImpEditView->GetEditSelection().Max().GetIndex();
+
+ return aSelection;
+}
+
+sal_Bool EditView::HasSelection() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ return pImpEditView->HasSelection();
+}
+
+void EditView::DeleteSelected()
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ pImpEditView->DeleteSelected();
+}
+
+USHORT EditView::GetSelectedScriptType() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ return PIMPEE->GetScriptType( pImpEditView->GetEditSelection() );
+}
+
+void EditView::Paint( const Rectangle& rRect )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ PIMPEE->Paint( pImpEditView, rRect );
+}
+
+void EditView::SetEditEngine( EditEngine* pEditEng )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ pImpEditView->pEditEngine = pEditEng;
+ EditSelection aStartSel;
+ aStartSel = PIMPEE->GetEditDoc().GetStartPaM();
+ pImpEditView->SetEditSelection( aStartSel );
+}
+
+void EditView::SetWindow( Window* pWin )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ pImpEditView->pOutWin = pWin;
+ PIMPEE->GetSelEngine().Reset();
+}
+
+Window* EditView::GetWindow() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ return pImpEditView->pOutWin;
+}
+
+void EditView::SetVisArea( const Rectangle& rRec )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ pImpEditView->SetVisDocStartPos( rRec.TopLeft() );
+}
+
+const Rectangle& EditView::GetVisArea() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ // Change return value to Rectangle in next incompatible build !!!
+ static Rectangle aRect;
+ aRect = pImpEditView->GetVisDocArea();
+ return aRect;
+}
+
+void EditView::SetOutputArea( const Rectangle& rRec )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ pImpEditView->SetOutputArea( rRec );
+
+ // Rest nur hier, wenn API-Aufruf:
+ pImpEditView->CalcAnchorPoint();
+ if ( PIMPEE->GetStatus().AutoPageSize() )
+ pImpEditView->RecalcOutputArea();
+ pImpEditView->ShowCursor( sal_False, sal_False );
+}
+
+const Rectangle& EditView::GetOutputArea() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ return pImpEditView->GetOutputArea();
+}
+
+void EditView::SetPointer( const Pointer& rPointer )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ pImpEditView->SetPointer( rPointer );
+}
+
+const Pointer& EditView::GetPointer() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ return pImpEditView->GetPointer();
+}
+
+void EditView::SetCursor( const Cursor& rCursor )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ delete pImpEditView->pCursor;
+ pImpEditView->pCursor = new Cursor( rCursor );
+}
+
+Cursor* EditView::GetCursor() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ return pImpEditView->pCursor;
+}
+
+void EditView::InsertText( const XubString& rStr, sal_Bool bSelect )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+
+ ImpEditEngine* pImpEE = PIMPEE;
+ pImpEditView->DrawSelection();
+
+ EditPaM aPaM1;
+ if ( bSelect )
+ {
+ EditSelection aTmpSel( pImpEditView->GetEditSelection() );
+ aTmpSel.Adjust( pImpEE->GetEditDoc() );
+ aPaM1 = aTmpSel.Min();
+ }
+
+ pImpEE->UndoActionStart( EDITUNDO_INSERT );
+ EditPaM aPaM2( pImpEE->InsertText( pImpEditView->GetEditSelection(), rStr ) );
+ pImpEE->UndoActionEnd( EDITUNDO_INSERT );
+
+ if ( bSelect )
+ {
+ DBG_ASSERT( !aPaM1.DbgIsBuggy( pImpEE->GetEditDoc() ), "Insert: PaM kaputt" );
+ pImpEditView->SetEditSelection( EditSelection( aPaM1, aPaM2 ) );
+ }
+ else
+ pImpEditView->SetEditSelection( EditSelection( aPaM2, aPaM2 ) );
+
+ pImpEE->FormatAndUpdate( this );
+}
+
+sal_Bool EditView::PostKeyEvent( const KeyEvent& rKeyEvent )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ return pImpEditView->PostKeyEvent( rKeyEvent );
+}
+
+sal_Bool EditView::MouseButtonUp( const MouseEvent& rMouseEvent )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ return pImpEditView->MouseButtonUp( rMouseEvent );
+}
+
+sal_Bool EditView::MouseButtonDown( const MouseEvent& rMouseEvent )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ return pImpEditView->MouseButtonDown( rMouseEvent );
+}
+
+sal_Bool EditView::MouseMove( const MouseEvent& rMouseEvent )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ return pImpEditView->MouseMove( rMouseEvent );
+}
+
+void EditView::Command( const CommandEvent& rCEvt )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ pImpEditView->Command( rCEvt );
+}
+
+void EditView::ShowCursor( sal_Bool bGotoCursor, sal_Bool bForceVisCursor )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+
+// Draw vertraegt die Assertion nicht, spaeter mal aktivieren
+// DBG_ASSERT( pImpEditView->pEditEngine->HasView( this ), "ShowCursor - View nicht angemeldet!" );
+// DBG_ASSERT( !GetWindow()->IsInPaint(), "ShowCursor - Why in Paint ?!" );
+
+ if ( pImpEditView->pEditEngine->HasView( this ) )
+ {
+ // Das ControlWord hat mehr Gewicht:
+ if ( !pImpEditView->DoAutoScroll() )
+ bGotoCursor = sal_False;
+ pImpEditView->ShowCursor( bGotoCursor, bForceVisCursor );
+ }
+}
+
+void EditView::HideCursor()
+{
+ DBG_CHKTHIS( EditView, 0 );
+ pImpEditView->GetCursor()->Hide();
+}
+
+Pair EditView::Scroll( long ndX, long ndY, BYTE nRangeCheck )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ return pImpEditView->Scroll( ndX, ndY, nRangeCheck );
+}
+
+const SfxItemSet& EditView::GetEmptyItemSet()
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ return PIMPEE->GetEmptyItemSet();
+}
+
+void EditView::SetAttribs( const SfxItemSet& rSet )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ DBG_ASSERT( !pImpEditView->aEditSelection.IsInvalid(), "Blinde Selection in ...." );
+
+ // Kein Undo-Kappseln noetig...
+ pImpEditView->DrawSelection();
+ PIMPEE->SetAttribs( pImpEditView->GetEditSelection(), rSet, ATTRSPECIAL_WHOLEWORD );
+ PIMPEE->FormatAndUpdate( this );
+}
+
+void EditView::SetParaAttribs( const SfxItemSet& rSet, sal_uInt16 nPara )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ // Kein Undo-Kappseln noetig...
+ PIMPEE->SetParaAttribs( nPara, rSet );
+ // Beim Aendern von Absatzattributen muss immer formatiert werden...
+ PIMPEE->FormatAndUpdate( this );
+}
+
+void EditView::RemoveAttribsKeepLanguages( sal_Bool bRemoveParaAttribs )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+
+ pImpEditView->DrawSelection();
+ PIMPEE->UndoActionStart( EDITUNDO_RESETATTRIBS );
+ EditSelection aSelection( pImpEditView->GetEditSelection() );
+
+ for (sal_uInt16 nWID = EE_ITEMS_START; nWID <= EE_ITEMS_END; ++nWID)
+ {
+ bool bIsLang = EE_CHAR_LANGUAGE == nWID ||
+ EE_CHAR_LANGUAGE_CJK == nWID ||
+ EE_CHAR_LANGUAGE_CTL == nWID;
+ if (!bIsLang)
+ PIMPEE->RemoveCharAttribs( aSelection, bRemoveParaAttribs, nWID );
+ }
+
+ PIMPEE->UndoActionEnd( EDITUNDO_RESETATTRIBS );
+ PIMPEE->FormatAndUpdate( this );
+}
+
+void EditView::RemoveAttribs( sal_Bool bRemoveParaAttribs, sal_uInt16 nWhich )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+
+ pImpEditView->DrawSelection();
+ PIMPEE->UndoActionStart( EDITUNDO_RESETATTRIBS );
+ PIMPEE->RemoveCharAttribs( pImpEditView->GetEditSelection(), bRemoveParaAttribs, nWhich );
+ PIMPEE->UndoActionEnd( EDITUNDO_RESETATTRIBS );
+ PIMPEE->FormatAndUpdate( this );
+}
+
+void EditView::RemoveCharAttribs( sal_uInt16 nPara, sal_uInt16 nWhich )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ PIMPEE->UndoActionStart( EDITUNDO_RESETATTRIBS );
+ PIMPEE->RemoveCharAttribs( nPara, nWhich );
+ PIMPEE->UndoActionEnd( EDITUNDO_RESETATTRIBS );
+ PIMPEE->FormatAndUpdate( this );
+}
+
+SfxItemSet EditView::GetAttribs()
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ DBG_ASSERT( !pImpEditView->aEditSelection.IsInvalid(), "Blinde Selection in ...." );
+ return PIMPEE->GetAttribs( pImpEditView->GetEditSelection() );
+}
+
+void EditView::Undo()
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ PIMPEE->Undo( this );
+}
+
+void EditView::Redo()
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ PIMPEE->Redo( this );
+}
+
+ULONG EditView::Read( SvStream& rInput, const String& rBaseURL, EETextFormat eFormat, sal_Bool bSelect, SvKeyValueIterator* pHTTPHeaderAttrs )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ EditSelection aOldSel( pImpEditView->GetEditSelection() );
+ pImpEditView->DrawSelection();
+ PIMPEE->UndoActionStart( EDITUNDO_READ );
+ EditPaM aEndPaM = PIMPEE->Read( rInput, rBaseURL, eFormat, aOldSel, pHTTPHeaderAttrs );
+ PIMPEE->UndoActionEnd( EDITUNDO_READ );
+ EditSelection aNewSel( aEndPaM, aEndPaM );
+ if ( bSelect )
+ {
+ aOldSel.Adjust( PIMPEE->GetEditDoc() );
+ aNewSel.Min() = aOldSel.Min();
+ }
+
+ pImpEditView->SetEditSelection( aNewSel );
+ sal_Bool bGotoCursor = pImpEditView->DoAutoScroll();
+ ShowCursor( bGotoCursor );
+
+ return rInput.GetError();
+}
+
+#ifndef SVX_LIGHT
+ULONG EditView::Write( SvStream& rOutput, EETextFormat eFormat )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ PIMPEE->Write( rOutput, eFormat, pImpEditView->GetEditSelection() );
+ ShowCursor();
+ return rOutput.GetError();
+}
+#endif
+
+void EditView::Cut()
+{
+ DBG_CHKTHIS( EditView, 0 );
+ Reference<com::sun::star::datatransfer::clipboard::XClipboard> aClipBoard(GetWindow()->GetClipboard());
+ pImpEditView->CutCopy( aClipBoard, sal_True );
+}
+
+::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable > EditView::GetTransferable()
+{
+ uno::Reference< datatransfer::XTransferable > xData = GetEditEngine()->pImpEditEngine->CreateTransferable( pImpEditView->GetEditSelection() );
+ return xData;
+}
+
+void EditView::Copy()
+{
+ DBG_CHKTHIS( EditView, 0 );
+ Reference<com::sun::star::datatransfer::clipboard::XClipboard> aClipBoard(GetWindow()->GetClipboard());
+ pImpEditView->CutCopy( aClipBoard, sal_False );
+}
+
+void EditView::Paste()
+{
+ DBG_CHKTHIS( EditView, 0 );
+ Reference<com::sun::star::datatransfer::clipboard::XClipboard> aClipBoard(GetWindow()->GetClipboard());
+ pImpEditView->Paste( aClipBoard, sal_False );
+}
+
+void EditView::PasteSpecial()
+{
+ DBG_CHKTHIS( EditView, 0 );
+ Reference<com::sun::star::datatransfer::clipboard::XClipboard> aClipBoard(GetWindow()->GetClipboard());
+ pImpEditView->Paste(aClipBoard, sal_True );
+}
+
+void EditView::EnablePaste( sal_Bool bEnable )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ pImpEditView->EnablePaste( bEnable );
+}
+
+sal_Bool EditView::IsPasteEnabled() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ return pImpEditView->IsPasteEnabled();
+}
+
+Point EditView::GetWindowPosTopLeft( sal_uInt16 nParagraph )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ Point aDocPos( pImpEditView->pEditEngine->GetDocPosTopLeft( nParagraph ) );
+ return pImpEditView->GetWindowPos( aDocPos );
+}
+
+sal_uInt16 EditView::GetParagraph( const Point& rMousePosPixel )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ Point aMousePos( rMousePosPixel );
+ aMousePos = GetWindow()->PixelToLogic( aMousePos );
+ Point aDocPos( pImpEditView->GetDocPos( aMousePos ) );
+ sal_uInt16 nParagraph = PIMPEE->GetParaPortions().FindParagraph( aDocPos.Y() );
+ return nParagraph;
+}
+
+void EditView::IndentBlock()
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+
+ PIMPEE->IndentBlock( this, sal_True );
+}
+
+void EditView::UnindentBlock()
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+
+ PIMPEE->IndentBlock( this, sal_False );
+}
+
+EESelectionMode EditView::GetSelectionMode() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ return pImpEditView->GetSelectionMode();
+}
+
+void EditView::SetSelectionMode( EESelectionMode eMode )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ pImpEditView->SetSelectionMode( eMode );
+}
+
+XubString EditView::GetSelected()
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ return PIMPEE->GetSelected( pImpEditView->GetEditSelection() );
+}
+
+void EditView::MoveParagraphs( Range aParagraphs, sal_uInt16 nNewPos )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ PIMPEE->UndoActionStart( EDITUNDO_MOVEPARAS );
+ PIMPEE->MoveParagraphs( aParagraphs, nNewPos, this );
+ PIMPEE->UndoActionEnd( EDITUNDO_MOVEPARAS );
+}
+
+void EditView::MoveParagraphs( long nDiff )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ ESelection aSel = GetSelection();
+ Range aRange( aSel.nStartPara, aSel.nEndPara );
+ aRange.Justify();
+ long nDest = ( nDiff > 0 ? aRange.Max() : aRange.Min() ) + nDiff;
+ if ( nDiff > 0 )
+ nDest++;
+ DBG_ASSERT( ( nDest >= 0 ) && ( nDest <= pImpEditView->pEditEngine->GetParagraphCount() ), "MoveParagraphs - wrong Parameters!" );
+ MoveParagraphs( aRange,
+ sal::static_int_cast< USHORT >( nDest ) );
+}
+
+void EditView::SetBackgroundColor( const Color& rColor )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ pImpEditView->SetBackgroundColor( rColor );
+}
+
+Color EditView::GetBackgroundColor() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ return pImpEditView->GetBackgroundColor();
+}
+
+void EditView::SetControlWord( sal_uInt32 nWord )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ pImpEditView->nControl = nWord;
+}
+
+sal_uInt32 EditView::GetControlWord() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ return pImpEditView->nControl;
+}
+
+EditTextObject* EditView::CreateTextObject()
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ return PIMPEE->CreateTextObject( pImpEditView->GetEditSelection() );
+}
+
+void EditView::InsertText( const EditTextObject& rTextObject )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ pImpEditView->DrawSelection();
+
+ PIMPEE->UndoActionStart( EDITUNDO_INSERT );
+ EditSelection aTextSel( PIMPEE->InsertText( rTextObject, pImpEditView->GetEditSelection() ) );
+ PIMPEE->UndoActionEnd( EDITUNDO_INSERT );
+
+ aTextSel.Min() = aTextSel.Max(); // Selektion nicht behalten.
+ pImpEditView->SetEditSelection( aTextSel );
+ PIMPEE->FormatAndUpdate( this );
+}
+
+void EditView::InsertText( ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable > xDataObj, const String& rBaseURL, BOOL bUseSpecial )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+
+ PIMPEE->UndoActionStart( EDITUNDO_INSERT );
+ pImpEditView->DeleteSelected();
+ EditSelection aTextSel( PIMPEE->InsertText( xDataObj, rBaseURL, pImpEditView->GetEditSelection().Max(), bUseSpecial ) );
+ PIMPEE->UndoActionEnd( EDITUNDO_INSERT );
+
+ aTextSel.Min() = aTextSel.Max(); // Selektion nicht behalten.
+ pImpEditView->SetEditSelection( aTextSel );
+ PIMPEE->FormatAndUpdate( this );
+}
+
+sal_Bool EditView::Drop( const DropEvent& )
+{
+ return FALSE;
+}
+
+ESelection EditView::GetDropPos()
+{
+ DBG_ERROR( "GetDropPos - Why?!" );
+ return ESelection();
+}
+
+sal_Bool EditView::QueryDrop( DropEvent& )
+{
+ return FALSE;
+}
+
+void EditView::SetEditEngineUpdateMode( sal_Bool bUpdate )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ PIMPEE->SetUpdateMode( bUpdate, this );
+}
+
+void EditView::ForceUpdate()
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ PIMPEE->SetUpdateMode( sal_True, this, sal_True );
+}
+
+void EditView::SetStyleSheet( SfxStyleSheet* pStyle )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+
+ EditSelection aSel( pImpEditView->GetEditSelection() );
+ PIMPEE->UndoActionStart( EDITUNDO_STYLESHEET );
+ PIMPEE->SetStyleSheet( aSel, pStyle );
+ PIMPEE->UndoActionEnd( EDITUNDO_STYLESHEET );
+}
+
+SfxStyleSheet* EditView::GetStyleSheet() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+
+
+ EditSelection aSel( pImpEditView->GetEditSelection() );
+ aSel.Adjust( PIMPEE->GetEditDoc() );
+ sal_uInt16 nStartPara = PIMPEE->GetEditDoc().GetPos( aSel.Min().GetNode() );
+ sal_uInt16 nEndPara = PIMPEE->GetEditDoc().GetPos( aSel.Max().GetNode() );
+
+ SfxStyleSheet* pStyle = NULL;
+ for ( sal_uInt16 n = nStartPara; n <= nEndPara; n++ )
+ {
+ SfxStyleSheet* pTmpStyle = PIMPEE->GetStyleSheet( n );
+ if ( ( n != nStartPara ) && ( pStyle != pTmpStyle ) )
+ return NULL; // Nicht eindeutig.
+ pStyle = pTmpStyle;
+ }
+ return pStyle;
+}
+
+sal_Bool EditView::IsInsertMode() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ return pImpEditView->IsInsertMode();
+}
+
+void EditView::SetInsertMode( sal_Bool bInsert )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ pImpEditView->SetInsertMode( bInsert );
+}
+
+void EditView::SetAnchorMode( EVAnchorMode eMode )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ pImpEditView->SetAnchorMode( eMode );
+}
+
+EVAnchorMode EditView::GetAnchorMode() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ return pImpEditView->GetAnchorMode();
+}
+
+void EditView::TransliterateText( sal_Int32 nTransliterationMode )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ EditSelection aOldSel( pImpEditView->GetEditSelection() );
+ EditSelection aNewSel = PIMPEE->TransliterateText( pImpEditView->GetEditSelection(), nTransliterationMode );
+ if ( aNewSel != aOldSel )
+ {
+ pImpEditView->DrawSelection(); // alte Selektion 'weg-zeichnen'
+ pImpEditView->SetEditSelection( aNewSel );
+ pImpEditView->DrawSelection();
+ }
+}
+
+
+sal_Bool EditView::MatchGroup()
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ EditSelection aNewSel( PIMPEE->MatchGroup( pImpEditView->GetEditSelection() ) );
+ if ( aNewSel.HasRange() )
+ {
+ pImpEditView->DrawSelection();
+ pImpEditView->SetEditSelection( aNewSel );
+ pImpEditView->DrawSelection();
+ ShowCursor();
+ return sal_True;
+ }
+ return sal_False;
+}
+
+void EditView::CompleteAutoCorrect()
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ if ( !pImpEditView->HasSelection() && PIMPEE->GetStatus().DoAutoCorrect() )
+ {
+ pImpEditView->DrawSelection();
+ EditSelection aSel = pImpEditView->GetEditSelection();
+ aSel = PIMPEE->EndOfWord( aSel.Max() );
+ // MT 06/00: Why pass EditSelection to AutoCorrect, not EditPaM?!
+ aSel = PIMPEE->AutoCorrect( aSel, 0, !IsInsertMode() );
+ pImpEditView->SetEditSelection( aSel );
+ if ( PIMPEE->IsModified() )
+ PIMPEE->FormatAndUpdate( this );
+ }
+}
+
+EESpellState EditView::StartSpeller( sal_Bool bMultipleDoc )
+{
+#ifdef SVX_LIGHT
+ return EE_SPELL_NOSPELLER;
+#else
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ if ( !PIMPEE->GetSpeller().is() )
+ return EE_SPELL_NOSPELLER;
+
+ return PIMPEE->Spell( this, bMultipleDoc );
+#endif
+}
+
+EESpellState EditView::StartThesaurus()
+{
+#ifdef SVX_LIGHT
+ return EE_SPELL_NOSPELLER;
+#else
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ if ( !PIMPEE->GetSpeller().is() )
+ return EE_SPELL_NOSPELLER;
+
+ return PIMPEE->StartThesaurus( this );
+#endif
+}
+
+
+void EditView::StartTextConversion(
+ LanguageType nSrcLang, LanguageType nDestLang, const Font *pDestFont,
+ INT32 nOptions, BOOL bIsInteractive, BOOL bMultipleDoc )
+{
+#ifdef SVX_LIGHT
+#else
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ PIMPEE->Convert( this, nSrcLang, nDestLang, pDestFont, nOptions, bIsInteractive, bMultipleDoc );
+#endif
+}
+
+
+sal_uInt16 EditView::StartSearchAndReplace( const SvxSearchItem& rSearchItem )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ return PIMPEE->StartSearchAndReplace( this, rSearchItem );
+}
+
+sal_Bool EditView::IsCursorAtWrongSpelledWord( sal_Bool bMarkIfWrong )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ sal_Bool bIsWrong = sal_False;
+ if ( !HasSelection() )
+ {
+ EditPaM aPaM = pImpEditView->GetEditSelection().Max();
+ bIsWrong = pImpEditView->IsWrongSpelledWord( aPaM, bMarkIfWrong );
+ }
+ return bIsWrong;
+}
+
+sal_Bool EditView::IsWrongSpelledWordAtPos( const Point& rPosPixel, sal_Bool bMarkIfWrong )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ Point aPos ( pImpEditView->GetWindow()->PixelToLogic( rPosPixel ) );
+ aPos = pImpEditView->GetDocPos( aPos );
+ EditPaM aPaM = pImpEditView->pEditEngine->pImpEditEngine->GetPaM( aPos, sal_False );
+ return pImpEditView->IsWrongSpelledWord( aPaM , bMarkIfWrong );
+}
+
+void EditView::ExecuteSpellPopup( const Point& rPosPixel, Link* pCallBack )
+{
+#ifndef SVX_LIGHT
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+
+ Point aPos ( pImpEditView->GetWindow()->PixelToLogic( rPosPixel ) );
+ aPos = pImpEditView->GetDocPos( aPos );
+ EditPaM aPaM = pImpEditView->pEditEngine->pImpEditEngine->GetPaM( aPos, sal_False );
+ Reference< XSpellChecker1 > xSpeller( PIMPEE->GetSpeller() );
+ ESelection aOldSel = GetSelection();
+ if ( xSpeller.is() && pImpEditView->IsWrongSpelledWord( aPaM, sal_True ) )
+ {
+ PopupMenu aPopupMenu( EditResId( RID_MENU_SPELL ) );
+ PopupMenu *pAutoMenu = aPopupMenu.GetPopupMenu( MN_AUTOCORR );
+ PopupMenu *pInsertMenu = aPopupMenu.GetPopupMenu( MN_INSERT );
+
+ EditPaM aPaM2( aPaM );
+ aPaM2.GetIndex()++;
+
+ // Gibt es Replace-Vorschlaege?
+ String aSelected( GetSelected() );
+ //
+ // restrict the maximal number of suggestions displayed
+ // in the context menu.
+ // Note: That could of course be done by clipping the
+ // resulting sequence but the current third party
+ // implementations result differs greatly if the number of
+ // suggestions to be retuned gets changed. Statistically
+ // it gets much better if told to return e.g. only 7 strings
+ // than returning e.g. 16 suggestions and using only the
+ // first 7. Thus we hand down the value to use to that
+ // implementation here by providing an additional parameter.
+ Sequence< PropertyValue > aPropVals(1);
+ PropertyValue &rVal = aPropVals.getArray()[0];
+ rVal.Name = OUString::createFromAscii( UPN_MAX_NUMBER_OF_SUGGESTIONS );
+ rVal.Value <<= (INT16) 7;
+ //
+ // Gibt es Replace-Vorschlaege?
+ Reference< XSpellAlternatives > xSpellAlt =
+ xSpeller->spell( aSelected, PIMPEE->GetLanguage( aPaM2 ), aPropVals );
+
+ Reference< XLanguageGuessing > xLangGuesser( EE_DLL()->GetGlobalData()->GetLanguageGuesser() );
+
+ // check if text might belong to a different language...
+ LanguageType nGuessLangWord = LANGUAGE_NONE;
+ LanguageType nGuessLangPara = LANGUAGE_NONE;
+ if (xSpellAlt.is() && xLangGuesser.is())
+ {
+ String aParaText;
+ ContentNode *pNode = aPaM.GetNode();
+ if (pNode)
+ {
+ aParaText = *pNode;
+ }
+ else
+ {
+ DBG_ERROR( "content node is NULL" );
+ }
+
+ nGuessLangWord = lcl_CheckLanguage( xSpellAlt->getWord(), xSpeller, xLangGuesser, sal_False );
+ nGuessLangPara = lcl_CheckLanguage( aParaText, xSpeller, xLangGuesser, sal_True );
+ }
+ if (nGuessLangWord != LANGUAGE_NONE || nGuessLangPara != LANGUAGE_NONE)
+ {
+ // make sure LANGUAGE_NONE gets not used as menu entry
+ if (nGuessLangWord == LANGUAGE_NONE)
+ nGuessLangWord = nGuessLangPara;
+ if (nGuessLangPara == LANGUAGE_NONE)
+ nGuessLangPara = nGuessLangWord;
+
+ aPopupMenu.InsertSeparator();
+ String aTmpWord( SvtLanguageTable::GetLanguageString( nGuessLangWord ) );
+ String aTmpPara( SvtLanguageTable::GetLanguageString( nGuessLangPara ) );
+ String aWordStr( EditResId( RID_STR_WORD ) );
+ aWordStr.SearchAndReplace( String( RTL_CONSTASCII_USTRINGPARAM( "%x" ) ), aTmpWord );
+ String aParaStr( EditResId( RID_STR_PARAGRAPH ) );
+ aParaStr.SearchAndReplace( String( RTL_CONSTASCII_USTRINGPARAM( "%x" ) ), aTmpPara );
+ aPopupMenu.InsertItem( MN_WORDLANGUAGE, aWordStr );
+ aPopupMenu.SetHelpId( MN_WORDLANGUAGE, HID_EDITENG_SPELLER_WORDLANGUAGE );
+ aPopupMenu.InsertItem( MN_PARALANGUAGE, aParaStr );
+ aPopupMenu.SetHelpId( MN_PARALANGUAGE, HID_EDITENG_SPELLER_PARALANGUAGE );
+ }
+
+ // ## Create mnemonics here
+ if ( Application::IsAutoMnemonicEnabled() )
+ {
+ aPopupMenu.CreateAutoMnemonics();
+ aPopupMenu.SetMenuFlags( aPopupMenu.GetMenuFlags() | MENU_FLAG_NOAUTOMNEMONICS );
+ }
+
+ // Replace suggestions...
+ Sequence< OUString > aAlt;
+ if (xSpellAlt.is())
+ aAlt = xSpellAlt->getAlternatives();
+ const OUString *pAlt = aAlt.getConstArray();
+ sal_uInt16 nWords = (USHORT) aAlt.getLength();
+ if ( nWords )
+ {
+ for ( sal_uInt16 nW = 0; nW < nWords; nW++ )
+ {
+ String aAlternate( pAlt[nW] );
+ aPopupMenu.InsertItem( MN_ALTSTART+nW, aAlternate, 0, nW );
+ pAutoMenu->InsertItem( MN_AUTOSTART+nW, aAlternate, 0, nW );
+ }
+ aPopupMenu.InsertSeparator( nWords );
+ }
+ else
+ aPopupMenu.RemoveItem( MN_AUTOCORR ); // Loeschen?
+
+ Reference< XDictionaryList > xDicList( SvxGetDictionaryList() );
+
+ Sequence< Reference< XDictionary > > aDics;
+ if (xDicList.is())
+ aDics = xDicList->getDictionaries();
+ const Reference< XDictionary > *pDic = aDics.getConstArray();
+ sal_uInt16 nLanguage = PIMPEE->GetLanguage( aPaM2 );
+ sal_uInt16 nDicCount = (USHORT)aDics.getLength();
+ for ( sal_uInt16 i = 0; i < nDicCount; i++ )
+ {
+ Reference< XDictionary > xDic( pDic[i], UNO_QUERY );
+ if (xDic.is())
+ {
+ sal_uInt16 nActLanguage = SvxLocaleToLanguage( xDic->getLocale() );
+ if( xDic->isActive() &&
+ xDic->getDictionaryType() == DictionaryType_POSITIVE &&
+ (nLanguage == nActLanguage || LANGUAGE_NONE == nActLanguage ) )
+ {
+ pInsertMenu->InsertItem( MN_DICTSTART + i, xDic->getName() );
+ }
+ }
+ }
+
+ if ( !pInsertMenu->GetItemCount() )
+ aPopupMenu.EnableItem( MN_INSERT, sal_False );
+
+ aPopupMenu.RemoveDisabledEntries( sal_True, sal_True );
+
+ Rectangle aTempRect = PIMPEE->PaMtoEditCursor( aPaM, GETCRSR_TXTONLY );
+ Point aScreenPos = pImpEditView->GetWindowPos( aTempRect.TopLeft() );
+ aScreenPos = pImpEditView->GetWindow()->OutputToScreenPixel( aScreenPos );
+ aTempRect = pImpEditView->GetWindow()->LogicToPixel( Rectangle(aScreenPos, aTempRect.GetSize() ));
+
+ sal_uInt16 nId = aPopupMenu.Execute( pImpEditView->GetWindow(), aTempRect, POPUPMENU_NOMOUSEUPCLOSE );
+ if ( nId == MN_IGNORE )
+ {
+ String aWord = pImpEditView->SpellIgnoreOrAddWord( sal_False );
+ if ( pCallBack )
+ {
+ SpellCallbackInfo aInf( SPELLCMD_IGNOREWORD, aWord );
+ pCallBack->Call( &aInf );
+ }
+ SetSelection( aOldSel );
+ }
+ else if ( ( nId == MN_WORDLANGUAGE ) || ( nId == MN_PARALANGUAGE ) )
+ {
+ LanguageType nLangToUse = (nId == MN_WORDLANGUAGE) ? nGuessLangWord : nGuessLangPara;
+ sal_uInt16 nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( nLangToUse );
+
+ SfxItemSet aAttrs = GetEditEngine()->GetEmptyItemSet();
+ if (nScriptType == SCRIPTTYPE_LATIN)
+ aAttrs.Put( SvxLanguageItem( nLangToUse, EE_CHAR_LANGUAGE ) );
+ if (nScriptType == SCRIPTTYPE_COMPLEX)
+ aAttrs.Put( SvxLanguageItem( nLangToUse, EE_CHAR_LANGUAGE_CTL ) );
+ if (nScriptType == SCRIPTTYPE_ASIAN)
+ aAttrs.Put( SvxLanguageItem( nLangToUse, EE_CHAR_LANGUAGE_CJK ) );
+ if ( nId == MN_PARALANGUAGE )
+ {
+ ESelection aSel = GetSelection();
+ aSel.nStartPos = 0;
+ aSel.nEndPos = 0xFFFF;
+ SetSelection( aSel );
+ }
+ SetAttribs( aAttrs );
+ PIMPEE->StartOnlineSpellTimer();
+
+ if ( pCallBack )
+ {
+ SpellCallbackInfo aInf( ( nId == MN_WORDLANGUAGE ) ? SPELLCMD_WORDLANGUAGE : SPELLCMD_PARALANGUAGE, nLangToUse );
+ pCallBack->Call( &aInf );
+ }
+ SetSelection( aOldSel );
+ }
+ else if ( nId == MN_SPELLING )
+ {
+ if ( !pCallBack )
+ {
+ // Cursor vor das Wort setzen...
+ EditPaM aCursor = pImpEditView->GetEditSelection().Min();
+ pImpEditView->DrawSelection(); // alte Selektion 'weg-zeichnen'
+ pImpEditView->SetEditSelection( EditSelection( aCursor, aCursor ) );
+ pImpEditView->DrawSelection();
+ // Stuerzt ab, wenn keine SfxApp
+ PIMPEE->Spell( this, sal_False );
+ }
+ else
+ {
+ SpellCallbackInfo aInf( SPELLCMD_STARTSPELLDLG, String() );
+ pCallBack->Call( &aInf );
+ }
+ }
+ else if ( nId >= MN_DICTSTART )
+ {
+ Reference< XDictionary > xDic( pDic[nId - MN_DICTSTART], UNO_QUERY );
+ if (xDic.is())
+ xDic->add( aSelected, sal_False, String() );
+ // save modified user-dictionary if it is persistent
+ Reference< frame::XStorable > xSavDic( xDic, UNO_QUERY );
+ if (xSavDic.is())
+ xSavDic->store();
+
+ aPaM.GetNode()->GetWrongList()->GetInvalidStart() = 0;
+ aPaM.GetNode()->GetWrongList()->GetInvalidEnd() = aPaM.GetNode()->Len();
+ PIMPEE->StartOnlineSpellTimer();
+
+ if ( pCallBack )
+ {
+ SpellCallbackInfo aInf( SPELLCMD_ADDTODICTIONARY, aSelected );
+ pCallBack->Call( &aInf );
+ }
+ SetSelection( aOldSel );
+ }
+ else if ( nId >= MN_AUTOSTART )
+ {
+ DBG_ASSERT(nId - MN_AUTOSTART < aAlt.getLength(), "index out of range");
+ String aWord = pAlt[nId - MN_AUTOSTART];
+ SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get()->GetAutoCorrect();
+ if ( pAutoCorrect )
+ pAutoCorrect->PutText( aSelected, aWord, PIMPEE->GetLanguage( aPaM2 ) );
+ InsertText( aWord );
+ }
+ else if ( nId >= MN_ALTSTART ) // Replace
+ {
+ DBG_ASSERT(nId - MN_ALTSTART < aAlt.getLength(), "index out of range");
+ String aWord = pAlt[nId - MN_ALTSTART];
+ InsertText( aWord );
+ }
+ else
+ {
+ SetSelection( aOldSel );
+ }
+ }
+#endif
+}
+
+void EditView::SpellIgnoreWord()
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ pImpEditView->SpellIgnoreOrAddWord( sal_False );
+}
+
+sal_Bool EditView::SelectCurrentWord()
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ EditSelection aCurSel( pImpEditView->GetEditSelection() );
+ pImpEditView->DrawSelection();
+ aCurSel = PIMPEE->SelectWord( aCurSel.Max() );
+ pImpEditView->SetEditSelection( aCurSel );
+ pImpEditView->DrawSelection();
+ ShowCursor( sal_True, sal_False );
+ return aCurSel.HasRange() ? sal_True : sal_False;
+}
+
+void EditView::InsertField( const SvxFieldItem& rFld )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+
+ ImpEditEngine* pImpEE = PIMPEE;
+ pImpEditView->DrawSelection();
+ pImpEE->UndoActionStart( EDITUNDO_INSERT );
+ EditPaM aPaM( pImpEE->InsertField( pImpEditView->GetEditSelection(), rFld ) );
+ pImpEE->UndoActionEnd( EDITUNDO_INSERT );
+ pImpEditView->SetEditSelection( EditSelection( aPaM, aPaM ) );
+ pImpEE->UpdateFields();
+ pImpEE->FormatAndUpdate( this );
+}
+
+const SvxFieldItem* EditView::GetFieldUnderMousePointer() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ sal_uInt16 nPara, nPos;
+ return GetFieldUnderMousePointer( nPara, nPos );
+}
+
+const SvxFieldItem* EditView::GetField( const Point& rPos, sal_uInt16* pPara, sal_uInt16* pPos ) const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ return pImpEditView->GetField( rPos, pPara, pPos );
+}
+
+const SvxFieldItem* EditView::GetFieldUnderMousePointer( sal_uInt16& nPara, sal_uInt16& nPos ) const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+ Point aPos = pImpEditView->GetWindow()->GetPointerPosPixel();
+ aPos = pImpEditView->GetWindow()->PixelToLogic( aPos );
+ return GetField( aPos, &nPara, &nPos );
+}
+
+const SvxFieldItem* EditView::GetFieldAtSelection() const
+{
+ EditSelection aSel( pImpEditView->GetEditSelection() );
+ aSel.Adjust( pImpEditView->pEditEngine->pImpEditEngine->GetEditDoc() );
+ // Nur wenn Cursor vor Feld, keine Selektion, oder nur Feld selektiert
+ if ( ( aSel.Min().GetNode() == aSel.Max().GetNode() ) &&
+ ( ( aSel.Max().GetIndex() == aSel.Min().GetIndex() ) ||
+ ( aSel.Max().GetIndex() == aSel.Min().GetIndex()+1 ) ) )
+ {
+ EditPaM aPaM = aSel.Min();
+ const CharAttribArray& rAttrs = aPaM.GetNode()->GetCharAttribs().GetAttribs();
+ sal_uInt16 nXPos = aPaM.GetIndex();
+ for ( sal_uInt16 nAttr = rAttrs.Count(); nAttr; )
+ {
+ EditCharAttrib* pAttr = rAttrs[--nAttr];
+ if ( pAttr->GetStart() == nXPos )
+ if ( pAttr->Which() == EE_FEATURE_FIELD )
+ {
+ DBG_ASSERT( pAttr->GetItem()->ISA( SvxFieldItem ), "Kein FeldItem..." );
+ return (const SvxFieldItem*)pAttr->GetItem();
+ }
+ }
+ }
+ return 0;
+}
+
+XubString EditView::GetWordUnderMousePointer() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+
+ Rectangle aRect;
+ return GetWordUnderMousePointer( aRect );
+}
+
+XubString EditView::GetWordUnderMousePointer( Rectangle& rWordRect ) const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+
+ Point aPos = pImpEditView->GetWindow()->GetPointerPosPixel();
+ aPos = pImpEditView->GetWindow()->PixelToLogic( aPos );
+
+ XubString aWord;
+
+ if( GetOutputArea().IsInside( aPos ) )
+ {
+ ImpEditEngine* pImpEE = pImpEditView->pEditEngine->pImpEditEngine;
+ Point aDocPos( pImpEditView->GetDocPos( aPos ) );
+ EditPaM aPaM = pImpEE->GetPaM( aDocPos, sal_False );
+ EditSelection aWordSel = pImpEE->SelectWord( aPaM );
+
+ Rectangle aTopLeftRec( pImpEE->PaMtoEditCursor( aWordSel.Min() ) );
+ Rectangle aBottomRightRec( pImpEE->PaMtoEditCursor( aWordSel.Max() ) );
+
+#if OSL_DEBUG_LEVEL > 1
+ DBG_ASSERT( aTopLeftRec.Top() == aBottomRightRec.Top(), "Top() in einer Zeile unterschiedlich?" );
+#endif
+
+ Point aPnt1( pImpEditView->GetWindowPos( aTopLeftRec.TopLeft() ) );
+ Point aPnt2( pImpEditView->GetWindowPos( aBottomRightRec.BottomRight()) );
+ rWordRect = Rectangle( aPnt1, aPnt2 );
+ aWord = pImpEE->GetSelected( aWordSel );
+ }
+
+ return aWord;
+}
+
+void EditView::SetInvalidateMore( sal_uInt16 nPixel )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ pImpEditView->SetInvalidateMore( nPixel );
+}
+
+sal_uInt16 EditView::GetInvalidateMore() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ return (sal_uInt16)pImpEditView->GetInvalidateMore();
+}
+
+static void ChangeFontSizeImpl( EditView* pEditView, bool bGrow, const ESelection& rSel, const FontList* pFontList )
+{
+ pEditView->SetSelection( rSel );
+
+ SfxItemSet aSet( pEditView->GetAttribs() );
+ if( EditView::ChangeFontSize( bGrow, aSet, pFontList ) )
+ {
+ SfxItemSet aNewSet( pEditView->GetEmptyItemSet() );
+ aNewSet.Put( aSet.Get( EE_CHAR_FONTHEIGHT ), EE_CHAR_FONTHEIGHT );
+ aNewSet.Put( aSet.Get( EE_CHAR_FONTHEIGHT_CJK ), EE_CHAR_FONTHEIGHT_CJK );
+ aNewSet.Put( aSet.Get( EE_CHAR_FONTHEIGHT_CTL ), EE_CHAR_FONTHEIGHT_CTL );
+ pEditView->SetAttribs( aNewSet );
+ }
+}
+
+void EditView::ChangeFontSize( bool bGrow, const FontList* pFontList )
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+
+ EditEngine& rEditEngine = *pImpEditView->pEditEngine;
+
+ ESelection aSel( GetSelection() );
+ ESelection aOldSelection( aSel );
+ aSel.Adjust();
+
+ if( !aSel.HasRange() )
+ {
+ aSel = rEditEngine.GetWord( aSel, com::sun::star::i18n::WordType::DICTIONARY_WORD );
+ }
+
+ if( aSel.HasRange() )
+ {
+ for( USHORT nPara = aSel.nStartPara; nPara <= aSel.nEndPara; nPara++ )
+ {
+ SvUShorts aPortions;
+ rEditEngine.GetPortions( nPara, aPortions );
+
+ if( aPortions.Count() == 0 )
+ aPortions.Insert( rEditEngine.GetTextLen(nPara), 0 );
+
+ const USHORT nBeginPos = (nPara == aSel.nStartPara) ? aSel.nStartPos : 0;
+ const USHORT nEndPos = (nPara == aSel.nEndPara) ? aSel.nEndPos : 0xffff;
+
+ for ( USHORT nPos = 0; nPos < aPortions.Count(); ++nPos )
+ {
+ USHORT nPortionEnd = aPortions.GetObject( nPos );
+ USHORT nPortionStart = nPos > 0 ? aPortions.GetObject( nPos - 1 ) : 0;
+
+ if( (nPortionEnd < nBeginPos) || (nPortionStart > nEndPos) )
+ continue;
+
+ if( nPortionStart < nBeginPos )
+ nPortionStart = nBeginPos;
+ if( nPortionEnd > nEndPos )
+ nPortionEnd = nEndPos;
+
+ if( nPortionStart == nPortionEnd )
+ continue;
+
+ ESelection aPortionSel( nPara, nPortionStart, nPara, nPortionEnd );
+ ChangeFontSizeImpl( this, bGrow, aPortionSel, pFontList );
+ }
+ }
+ }
+ else
+ {
+ ChangeFontSizeImpl( this, bGrow, aSel, pFontList );
+ }
+
+ SetSelection( aOldSelection );
+}
+
+bool EditView::ChangeFontSize( bool bGrow, SfxItemSet& rSet, const FontList* pFontList )
+{
+ static const sal_uInt16 gFontSizeWichMap[] = { EE_CHAR_FONTHEIGHT, EE_CHAR_FONTHEIGHT_CJK, EE_CHAR_FONTHEIGHT_CTL, 0 };
+
+ const SvxFontItem* pFontItem = static_cast<const SvxFontItem*>(&rSet.Get( EE_CHAR_FONTINFO ));
+ if( !pFontItem || !pFontList )
+ return false;
+
+ bool bRet = false;
+
+ const sal_uInt16* pWhich = gFontSizeWichMap;
+ while( *pWhich )
+ {
+ SvxFontHeightItem aFontHeightItem( static_cast<const SvxFontHeightItem&>(rSet.Get( *pWhich )) );
+ long nHeight = aFontHeightItem.GetHeight();
+ const SfxMapUnit eUnit = rSet.GetPool()->GetMetric( *pWhich );
+ nHeight = OutputDevice::LogicToLogic( nHeight * 10, (MapUnit)eUnit, MAP_POINT );
+
+ FontInfo aFontInfo = pFontList->Get( pFontItem->GetFamilyName(), pFontItem->GetStyleName() );
+ const long* pAry = pFontList->GetSizeAry( aFontInfo );
+
+ if( bGrow )
+ {
+ while( *pAry )
+ {
+ if( *pAry > nHeight )
+ {
+ nHeight = *pAry;
+ break;
+ }
+ pAry++;
+ }
+
+ if( *pAry == 0 )
+ {
+ nHeight += (nHeight + 5) / 10;
+ if( nHeight > 9999 )
+ nHeight = 9999;
+ }
+
+ }
+ else if( *pAry )
+ {
+ bool bFound = false;
+ if( *pAry < nHeight )
+ {
+ pAry++;
+ while( *pAry )
+ {
+ if( *pAry >= nHeight )
+ {
+ nHeight = pAry[-1];
+ bFound = true;
+ break;
+ }
+ pAry++;
+ }
+ }
+
+ if( !bFound )
+ {
+ nHeight -= (nHeight + 5) / 10;
+ if( nHeight < 2 )
+ nHeight = 2;
+ }
+ }
+
+ if( (nHeight >= 2) && (nHeight <= 9999 ) )
+ {
+ nHeight = OutputDevice::LogicToLogic( nHeight, MAP_POINT, (MapUnit)eUnit ) / 10;
+
+ if( nHeight != (long)aFontHeightItem.GetHeight() )
+ {
+ aFontHeightItem.SetHeight( nHeight );
+ rSet.Put( aFontHeightItem, *pWhich );
+ bRet = true;
+ }
+ }
+ pWhich++;
+ }
+ return bRet;
+}
+
+String EditView::GetSurroundingText() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+ DBG_CHKOBJ( pImpEditView->pEditEngine, EditEngine, 0 );
+
+ EditSelection aSel( pImpEditView->GetEditSelection() );
+ aSel.Adjust( PIMPEE->GetEditDoc() );
+
+ if( HasSelection() )
+ {
+ XubString aStr = PIMPEE->GetSelected( aSel );
+
+ // Stop reconversion if the selected text includes a line break.
+ if ( aStr.Search( 0x0A ) == STRING_NOTFOUND )
+ return aStr;
+ else
+ return String();
+ }
+ else
+ {
+ aSel.Min().SetIndex( 0 );
+ aSel.Max().SetIndex( aSel.Max().GetNode()->Len() );
+ return PIMPEE->GetSelected( aSel );
+ }
+}
+
+Selection EditView::GetSurroundingTextSelection() const
+{
+ DBG_CHKTHIS( EditView, 0 );
+
+ ESelection aSelection( GetSelection() );
+ aSelection.Adjust();
+
+ if( HasSelection() )
+ {
+ EditSelection aSel( pImpEditView->GetEditSelection() );
+ aSel.Adjust( PIMPEE->GetEditDoc() );
+ XubString aStr = PIMPEE->GetSelected( aSel );
+
+ // Stop reconversion if the selected text includes a line break.
+ if ( aStr.Search( 0x0A ) == STRING_NOTFOUND )
+ return Selection( 0, aSelection.nEndPos - aSelection.nStartPos );
+ else
+ return Selection( 0, 0 );
+ }
+ else
+ {
+ return Selection( aSelection.nStartPos, aSelection.nEndPos );
+ }
+}
diff --git a/editeng/source/editeng/edtspell.cxx b/editeng/source/editeng/edtspell.cxx
new file mode 100644
index 000000000000..fed1394e5fd0
--- /dev/null
+++ b/editeng/source/editeng/edtspell.cxx
@@ -0,0 +1,746 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 <impedit.hxx>
+#include <editeng/editview.hxx>
+#include <editeng/editeng.hxx>
+#include <edtspell.hxx>
+#include <editeng/flditem.hxx>
+#include <editeng/fontitem.hxx>
+#include <svl/intitem.hxx>
+#include <svl/eitem.hxx>
+#include <editeng/unolingu.hxx>
+#include <linguistic/lngprops.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+using ::rtl::OUString;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::linguistic2;
+
+
+EditSpellWrapper::EditSpellWrapper( Window* _pWin,
+ Reference< XSpellChecker1 > &xChecker,
+ sal_Bool bIsStart, sal_Bool bIsAllRight, EditView* pView ) :
+ SvxSpellWrapper( _pWin, xChecker, bIsStart, bIsAllRight )
+{
+ DBG_ASSERT( pView, "Es muss eine View uebergeben werden!" );
+ // IgnoreList behalten, ReplaceList loeschen...
+ if (SvxGetChangeAllList().is())
+ SvxGetChangeAllList()->clear();
+ pEditView = pView;
+}
+
+void __EXPORT EditSpellWrapper::SpellStart( SvxSpellArea eArea )
+{
+ ImpEditEngine* pImpEE = pEditView->GetImpEditEngine();
+ SpellInfo* pSpellInfo = pImpEE->GetSpellInfo();
+
+ if ( eArea == SVX_SPELL_BODY_START )
+ {
+ // Wird gerufen, wenn
+ // a) Spell-Forwad ist am Ende angekomment und soll von vorne beginnen
+ // IsEndDone() liefert auch sal_True, wenn Rueckwaerts-Spelling am Ende gestartet wird!
+ if ( IsEndDone() )
+ {
+ pSpellInfo->bSpellToEnd = sal_False;
+ pSpellInfo->aSpellTo = pSpellInfo->aSpellStart;
+ pEditView->GetImpEditView()->SetEditSelection(
+ pImpEE->GetEditDoc().GetStartPaM() );
+ }
+ else
+ {
+ pSpellInfo->bSpellToEnd = sal_True;
+ pSpellInfo->aSpellTo = pImpEE->CreateEPaM(
+ pImpEE->GetEditDoc().GetStartPaM() );
+ }
+ }
+ else if ( eArea == SVX_SPELL_BODY_END )
+ {
+ // Wird gerufen, wenn
+ // a) Spell-Forwad wird gestartet
+ // IsStartDone() liefert auch sal_True, wenn Vorwaerts-Spelling am Anfang gestartet wird!
+ if ( !IsStartDone() )
+ {
+ pSpellInfo->bSpellToEnd = sal_True;
+ pSpellInfo->aSpellTo = pImpEE->CreateEPaM(
+ pImpEE->GetEditDoc().GetEndPaM() );
+ }
+ else
+ {
+ pSpellInfo->bSpellToEnd = sal_False;
+ pSpellInfo->aSpellTo = pSpellInfo->aSpellStart;
+ pEditView->GetImpEditView()->SetEditSelection(
+ pImpEE->GetEditDoc().GetEndPaM() );
+ }
+ }
+ else if ( eArea == SVX_SPELL_BODY )
+ {
+ ; // Wird ueber SpellNextDocument von App gehandelt
+
+ // pSpellInfo->bSpellToEnd = sal_True;
+ // pSpellInfo->aSpellTo = pImpEE->CreateEPaM( pImpEE->GetEditDoc().GetEndPaM() );
+ }
+ else
+ {
+ DBG_ERROR( "SpellStart: Unknown Area!" );
+ }
+}
+
+sal_Bool EditSpellWrapper::SpellContinue()
+{
+ SetLast( pEditView->GetImpEditEngine()->ImpSpell( pEditView ) );
+ return GetLast().is();
+}
+
+void __EXPORT EditSpellWrapper::SpellEnd()
+{
+ // Base class will show language errors...
+ SvxSpellWrapper::SpellEnd();
+}
+
+sal_Bool __EXPORT EditSpellWrapper::HasOtherCnt()
+{
+ return sal_False;
+}
+
+sal_Bool __EXPORT EditSpellWrapper::SpellMore()
+{
+ ImpEditEngine* pImpEE = pEditView->GetImpEditEngine();
+ SpellInfo* pSpellInfo = pImpEE->GetSpellInfo();
+ sal_Bool bMore = sal_False;
+ if ( pSpellInfo->bMultipleDoc )
+ {
+ bMore = pImpEE->GetEditEnginePtr()->SpellNextDocument();
+ if ( bMore )
+ {
+ // Der Text wurde in diese Engine getreten, bei Rueckwaerts
+ // muss die Selektion hinten sein.
+ Reference< XPropertySet > xProp( SvxGetLinguPropertySet() );
+ pEditView->GetImpEditView()->SetEditSelection(
+ pImpEE->GetEditDoc().GetStartPaM() );
+ }
+ }
+ return bMore;
+}
+
+void __EXPORT EditSpellWrapper::ScrollArea()
+{
+ // Keine weitere Aktion noetig...
+ // Es sei denn, der Bereich soll in die Mitte gescrollt werden,
+ // und nicht irgendwo stehen.
+}
+
+void __EXPORT EditSpellWrapper::ReplaceAll( const String &rNewText,
+ sal_Int16 )
+{
+ // Wird gerufen, wenn Wort in ReplaceList des SpellCheckers
+ pEditView->InsertText( rNewText );
+ CheckSpellTo();
+}
+
+void __EXPORT EditSpellWrapper::ChangeWord( const String& rNewWord,
+ const sal_uInt16 )
+{
+ // Wird gerufen, wenn Wort Button Change
+ // bzw. intern von mir bei ChangeAll
+
+ // Wenn Punkt hinterm Wort, wird dieser nicht mitgegeben.
+ // Falls '"' => PreStripped.
+ String aNewWord( rNewWord );
+ pEditView->InsertText( aNewWord );
+ CheckSpellTo();
+}
+
+void __EXPORT EditSpellWrapper::ChangeThesWord( const String& rNewWord )
+{
+ pEditView->InsertText( rNewWord );
+ CheckSpellTo();
+}
+
+void __EXPORT EditSpellWrapper::AutoCorrect( const String&, const String& )
+{
+}
+
+void EditSpellWrapper::CheckSpellTo()
+{
+ ImpEditEngine* pImpEE = pEditView->GetImpEditEngine();
+ SpellInfo* pSpellInfo = pImpEE->GetSpellInfo();
+ EditPaM aPaM( pEditView->GetImpEditView()->GetEditSelection().Max() );
+ EPaM aEPaM = pImpEE->CreateEPaM( aPaM );
+ if ( aEPaM.nPara == pSpellInfo->aSpellTo.nPara )
+ {
+ // prueffen, ob SpellToEnd noch gueltiger Index, falls in dem Absatz
+ // ersetzt wurde.
+ if ( pSpellInfo->aSpellTo.nIndex > aPaM.GetNode()->Len() )
+ pSpellInfo->aSpellTo.nIndex = aPaM.GetNode()->Len();
+ }
+}
+SV_IMPL_VARARR( WrongRanges, WrongRange );
+
+WrongList::WrongList()
+{
+ nInvalidStart = 0;
+ nInvalidEnd = 0xFFFF;
+}
+
+WrongList::~WrongList()
+{
+}
+
+void WrongList::TextInserted( sal_uInt16 nPos, sal_uInt16 nNew, sal_Bool bPosIsSep )
+{
+ if ( !IsInvalid() )
+ {
+ nInvalidStart = nPos;
+ nInvalidEnd = nPos+nNew;
+ }
+ else
+ {
+ if ( nInvalidStart > nPos )
+ nInvalidStart = nPos;
+ if ( nInvalidEnd >= nPos )
+ nInvalidEnd = nInvalidEnd + nNew;
+ else
+ nInvalidEnd = nPos+nNew;
+ }
+
+ for ( sal_uInt16 n = 0; n < Count(); n++ )
+ {
+ WrongRange& rWrong = GetObject( n );
+ sal_Bool bRefIsValid = sal_True;
+ if ( rWrong.nEnd >= nPos )
+ {
+ // Alle Wrongs hinter der Einfuegeposition verschieben...
+ if ( rWrong.nStart > nPos )
+ {
+ rWrong.nStart = rWrong.nStart + nNew;
+ rWrong.nEnd = rWrong.nEnd + nNew;
+ }
+ // 1: Startet davor, geht bis nPos...
+ else if ( rWrong.nEnd == nPos )
+ {
+ // Sollte bei einem Blank unterbunden werden!
+ if ( !bPosIsSep )
+ rWrong.nEnd = rWrong.nEnd + nNew;
+ }
+ // 2: Startet davor, geht hinter Pos...
+ else if ( ( rWrong.nStart < nPos ) && ( rWrong.nEnd > nPos ) )
+ {
+ rWrong.nEnd = rWrong.nEnd + nNew;
+ // Bei einem Trenner das Wrong entfernen und neu pruefen
+ if ( bPosIsSep )
+ {
+ // Wrong aufteilen...
+ WrongRange aNewWrong( rWrong.nStart, nPos );
+ rWrong.nStart = nPos+1;
+ Insert( aNewWrong, n );
+ bRefIsValid = sal_False; // Referenz nach Insert nicht mehr gueltig, der andere wurde davor an dessen Position eingefuegt
+ n++; // Diesen nicht nochmal...
+ }
+ }
+ // 3: Attribut startet auf Pos...
+ else if ( rWrong.nStart == nPos )
+ {
+ rWrong.nEnd = rWrong.nEnd + nNew;
+ if ( bPosIsSep )
+ rWrong.nStart++;
+ }
+ }
+ DBG_ASSERT( !bRefIsValid || ( rWrong.nStart < rWrong.nEnd ),
+ "TextInserted, WrongRange: Start >= End?!" );
+ }
+
+ DBG_ASSERT( !DbgIsBuggy(), "InsertWrong: WrongList kaputt!" );
+}
+
+void WrongList::TextDeleted( sal_uInt16 nPos, sal_uInt16 nDeleted )
+{
+ sal_uInt16 nEndChanges = nPos+nDeleted;
+ if ( !IsInvalid() )
+ {
+ sal_uInt16 nNewInvalidStart = nPos ? nPos - 1 : 0;
+ nInvalidStart = nNewInvalidStart;
+ nInvalidEnd = nNewInvalidStart + 1;
+ }
+ else
+ {
+ if ( nInvalidStart > nPos )
+ nInvalidStart = nPos;
+ if ( nInvalidEnd > nPos )
+ {
+ if ( nInvalidEnd > nEndChanges )
+ nInvalidEnd = nInvalidEnd - nDeleted;
+ else
+ nInvalidEnd = nPos+1;
+ }
+ }
+
+ for ( sal_uInt16 n = 0; n < Count(); n++ )
+ {
+ WrongRange& rWrong = GetObject( n );
+ sal_Bool bDelWrong = sal_False;
+ if ( rWrong.nEnd >= nPos )
+ {
+ // Alles Wrongs hinter der Einfuegeposition verschieben...
+ if ( rWrong.nStart >= nEndChanges )
+ {
+ rWrong.nStart = rWrong.nStart - nDeleted;
+ rWrong.nEnd = rWrong.nEnd - nDeleted;
+ }
+ // 1. Innenliegende Wrongs loeschen...
+ else if ( ( rWrong.nStart >= nPos ) && ( rWrong.nEnd <= nEndChanges ) )
+ {
+ bDelWrong = sal_True;
+ }
+ // 2. Wrong beginnt davor, endet drinnen oder dahinter...
+ else if ( ( rWrong.nStart <= nPos ) && ( rWrong.nEnd > nPos ) )
+ {
+ if ( rWrong.nEnd <= nEndChanges ) // endet drinnen
+ rWrong.nEnd = nPos;
+ else
+ rWrong.nEnd = rWrong.nEnd - nDeleted; // endet dahinter
+ }
+ // 3. Wrong beginnt drinnen, endet dahinter...
+ else if ( ( rWrong.nStart >= nPos ) && ( rWrong.nEnd > nEndChanges ) )
+ {
+ rWrong.nStart = nEndChanges;
+ rWrong.nStart = rWrong.nStart - nDeleted;
+ rWrong.nEnd = rWrong.nEnd - nDeleted;
+ }
+ }
+ DBG_ASSERT( rWrong.nStart < rWrong.nEnd,
+ "TextInserted, WrongRange: Start >= End?!" );
+ if ( bDelWrong )
+ {
+ Remove( n, 1 );
+ n--;
+ }
+ }
+
+ DBG_ASSERT( !DbgIsBuggy(), "InsertWrong: WrongList kaputt!" );
+}
+
+sal_Bool WrongList::NextWrong( sal_uInt16& rnStart, sal_uInt16& rnEnd ) const
+{
+ /*
+ rnStart enthaelt die Startposition, wird ggf. auf Wrong-Start korrigiert
+ rnEnd braucht nicht inizialisiert sein.
+ */
+ for ( sal_uInt16 n = 0; n < Count(); n++ )
+ {
+ WrongRange& rWrong = GetObject( n );
+ if ( rWrong.nEnd > rnStart )
+ {
+ rnStart = rWrong.nStart;
+ rnEnd = rWrong.nEnd;
+ return sal_True;
+ }
+ }
+ return sal_False;
+}
+
+sal_Bool WrongList::HasWrong( sal_uInt16 nStart, sal_uInt16 nEnd ) const
+{
+ for ( sal_uInt16 n = 0; n < Count(); n++ )
+ {
+ WrongRange& rWrong = GetObject( n );
+ if ( ( rWrong.nStart == nStart ) && ( rWrong.nEnd == nEnd ) )
+ return sal_True;
+ else if ( rWrong.nStart >= nStart )
+ break;
+ }
+ return sal_False;
+}
+
+sal_Bool WrongList::HasAnyWrong( sal_uInt16 nStart, sal_uInt16 nEnd ) const
+{
+ for ( sal_uInt16 n = 0; n < Count(); n++ )
+ {
+ WrongRange& rWrong = GetObject( n );
+ if ( ( rWrong.nEnd >= nStart ) && ( rWrong.nStart < nEnd ) )
+ return sal_True;
+ else if ( rWrong.nStart >= nEnd )
+ break;
+ }
+ return sal_False;
+}
+
+void WrongList::ClearWrongs( sal_uInt16 nStart, sal_uInt16 nEnd,
+ const ContentNode* pNode )
+{
+ for ( sal_uInt16 n = 0; n < Count(); n++ )
+ {
+ WrongRange& rWrong = GetObject( n );
+ if ( ( rWrong.nEnd > nStart ) && ( rWrong.nStart < nEnd ) )
+ {
+ if ( rWrong.nEnd > nEnd ) // // Laeuft raus
+ {
+ rWrong.nStart = nEnd;
+ // Blanks?
+ while ( ( rWrong.nStart < pNode->Len() ) &&
+ ( ( pNode->GetChar( rWrong.nStart ) == ' ' ) ||
+ ( pNode->IsFeature( rWrong.nStart ) ) ) )
+ {
+ rWrong.nStart++;
+ }
+ }
+ else
+ {
+ Remove( n, 1 );
+ n--;
+ }
+ }
+ }
+
+ DBG_ASSERT( !DbgIsBuggy(), "InsertWrong: WrongList kaputt!" );
+}
+
+void WrongList::InsertWrong( sal_uInt16 nStart, sal_uInt16 nEnd,
+ sal_Bool bClearRange )
+{
+ sal_uInt16 nPos = Count();
+ for ( sal_uInt16 n = 0; n < Count(); n++ )
+ {
+ WrongRange& rWrong = GetObject( n );
+ if ( rWrong.nStart >= nStart )
+ {
+ nPos = n;
+ if ( bClearRange )
+ {
+ // Es kann eigentlich nur Passieren, dass der Wrong genau
+ // hier beginnt und weiter rauslauft, aber nicht, dass hier
+ // mehrere im Bereich liegen...
+ // Genau im Bereich darf keiner liegen, sonst darf diese Methode
+ // garnicht erst gerufen werden!
+ DBG_ASSERT( ( ( rWrong.nStart == nStart ) && ( rWrong.nEnd > nEnd ) )
+ || ( rWrong.nStart > nEnd ), "InsertWrong: RangeMismatch!" );
+ if ( ( rWrong.nStart == nStart ) && ( rWrong.nEnd > nEnd ) )
+ rWrong.nStart = nEnd+1;
+ }
+ break;
+ }
+ }
+ Insert( WrongRange( nStart, nEnd ), nPos );
+
+ DBG_ASSERT( !DbgIsBuggy(), "InsertWrong: WrongList kaputt!" );
+}
+
+void WrongList::MarkWrongsInvalid()
+{
+ if ( Count() )
+ MarkInvalid( GetObject( 0 ).nStart, GetObject( Count()-1 ).nEnd );
+}
+
+WrongList* WrongList::Clone() const
+{
+ WrongList* pNew = new WrongList;
+ for ( sal_uInt16 n = 0; n < Count(); n++ )
+ {
+ WrongRange& rWrong = GetObject( n );
+ pNew->Insert( rWrong, pNew->Count() );
+ }
+
+ return pNew;
+}
+
+// #i102062#
+bool WrongList::operator==(const WrongList& rCompare) const
+{
+ // cleck direct members
+ if(GetInvalidStart() != rCompare.GetInvalidStart()
+ || GetInvalidEnd() != rCompare.GetInvalidEnd()
+ || Count() != rCompare.Count())
+ {
+ return false;
+ }
+
+ for(USHORT a(0); a < Count(); a++)
+ {
+ const WrongRange& rCandA(GetObject(a));
+ const WrongRange& rCandB(rCompare.GetObject(a));
+
+ if(rCandA.nStart != rCandB.nStart
+ || rCandA.nEnd != rCandB.nEnd)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+#ifdef DBG_UTIL
+sal_Bool WrongList::DbgIsBuggy() const
+{
+ // Pruefen, ob sich Bereiche ueberlappen
+ sal_Bool bError = sal_False;
+ for ( sal_uInt16 _nA = 0; !bError && ( _nA < Count() ); _nA++ )
+ {
+ WrongRange& rWrong = GetObject( _nA );
+ for ( sal_uInt16 nB = _nA+1; !bError && ( nB < Count() ); nB++ )
+ {
+ WrongRange& rNextWrong = GetObject( nB );
+ // 1) Start davor, End hinterm anderen Start
+ if ( ( rWrong.nStart <= rNextWrong.nStart )
+ && ( rWrong.nEnd >= rNextWrong.nStart ) )
+ bError = sal_True;
+ // 2) Start hinter anderen Start, aber noch vorm anderen End
+ else if ( ( rWrong.nStart >= rNextWrong.nStart)
+ && ( rWrong.nStart <= rNextWrong.nEnd ) )
+ bError = sal_True;
+ }
+ }
+ return bError;
+}
+#endif
+
+
+EdtAutoCorrDoc::EdtAutoCorrDoc( ImpEditEngine* pE, ContentNode* pN,
+ sal_uInt16 nCrsr, xub_Unicode cIns )
+{
+ pImpEE = pE;
+ pCurNode = pN;
+ nCursor = nCrsr;
+
+ bUndoAction = sal_False;
+ bAllowUndoAction = cIns ? sal_True : sal_False;
+}
+
+EdtAutoCorrDoc::~EdtAutoCorrDoc()
+{
+ if ( bUndoAction )
+ pImpEE->UndoActionEnd( EDITUNDO_INSERT );
+}
+
+sal_Bool EdtAutoCorrDoc::Delete( sal_uInt16 nStt, sal_uInt16 nEnd )
+{
+ EditSelection aSel( EditPaM( pCurNode, nStt ), EditPaM( pCurNode, nEnd ) );
+ pImpEE->ImpDeleteSelection( aSel );
+ DBG_ASSERT( nCursor >= nEnd, "Cursor mitten im Geschehen ?!" );
+ nCursor -= ( nEnd-nStt );
+ bAllowUndoAction = sal_False;
+ return sal_True;
+}
+
+sal_Bool EdtAutoCorrDoc::Insert( sal_uInt16 nPos, const String& rTxt )
+{
+ EditSelection aSel = EditPaM( pCurNode, nPos );
+ pImpEE->ImpInsertText( aSel, rTxt );
+ DBG_ASSERT( nCursor >= nPos, "Cursor mitten im Geschehen ?!" );
+ nCursor = nCursor + rTxt.Len();
+
+ if ( bAllowUndoAction && ( rTxt.Len() == 1 ) )
+ ImplStartUndoAction();
+ bAllowUndoAction = sal_False;
+
+ return sal_True;
+}
+
+sal_Bool EdtAutoCorrDoc::Replace( sal_uInt16 nPos, const String& rTxt )
+{
+ // Eigentlich ein Replace einfuehren => Entspr. UNDO
+ sal_uInt16 nEnd = nPos+rTxt.Len();
+ if ( nEnd > pCurNode->Len() )
+ nEnd = pCurNode->Len();
+
+ // #i5925# First insert new text behind to be deleted text, for keeping attributes.
+ pImpEE->ImpInsertText( EditSelection( EditPaM( pCurNode, nEnd ) ), rTxt );
+ pImpEE->ImpDeleteSelection( EditSelection( EditPaM( pCurNode, nPos ), EditPaM( pCurNode, nEnd ) ) );
+
+ if ( nPos == nCursor )
+ nCursor = nCursor + rTxt.Len();
+
+ if ( bAllowUndoAction && ( rTxt.Len() == 1 ) )
+ ImplStartUndoAction();
+
+ bAllowUndoAction = sal_False;
+
+ return sal_True;
+}
+
+sal_Bool EdtAutoCorrDoc::SetAttr( sal_uInt16 nStt, sal_uInt16 nEnd,
+ sal_uInt16 nSlotId, SfxPoolItem& rItem )
+{
+ SfxItemPool* pPool = &pImpEE->GetEditDoc().GetItemPool();
+ while ( pPool->GetSecondaryPool() &&
+ !pPool->GetName().EqualsAscii( "EditEngineItemPool" ) )
+ {
+ pPool = pPool->GetSecondaryPool();
+
+ }
+ sal_uInt16 nWhich = pPool->GetWhich( nSlotId );
+ if ( nWhich )
+ {
+ rItem.SetWhich( nWhich );
+
+ SfxItemSet aSet( pImpEE->GetEmptyItemSet() );
+ aSet.Put( rItem );
+
+ EditSelection aSel( EditPaM( pCurNode, nStt ), EditPaM( pCurNode, nEnd ) );
+ aSel.Max().SetIndex( nEnd ); // ???
+ pImpEE->SetAttribs( aSel, aSet, ATTRSPECIAL_EDGE );
+ bAllowUndoAction = sal_False;
+ }
+ return sal_True;
+}
+
+sal_Bool EdtAutoCorrDoc::SetINetAttr( sal_uInt16 nStt, sal_uInt16 nEnd,
+ const String& rURL )
+{
+ // Aus dem Text ein Feldbefehl machen...
+ EditSelection aSel( EditPaM( pCurNode, nStt ), EditPaM( pCurNode, nEnd ) );
+ String aText = pImpEE->GetSelected( aSel );
+ aSel = pImpEE->ImpDeleteSelection( aSel );
+ DBG_ASSERT( nCursor >= nEnd, "Cursor mitten im Geschehen ?!" );
+ nCursor -= ( nEnd-nStt );
+ SvxFieldItem aField( SvxURLField( rURL, aText, SVXURLFORMAT_REPR ),
+ EE_FEATURE_FIELD );
+ pImpEE->InsertField( aSel, aField );
+ nCursor++;
+ pImpEE->UpdateFields();
+ bAllowUndoAction = sal_False;
+ return sal_True;
+}
+
+sal_Bool EdtAutoCorrDoc::HasSymbolChars( sal_uInt16 nStt, sal_uInt16 nEnd )
+{
+ USHORT nScriptType = pImpEE->GetScriptType( EditPaM( pCurNode, nStt ) );
+ USHORT nScriptFontInfoItemId = GetScriptItemId( EE_CHAR_FONTINFO, nScriptType );
+
+ CharAttribArray& rAttribs = pCurNode->GetCharAttribs().GetAttribs();
+ sal_uInt16 nAttrs = rAttribs.Count();
+ for ( sal_uInt16 n = 0; n < nAttrs; n++ )
+ {
+ EditCharAttrib* pAttr = rAttribs.GetObject( n );
+ if ( pAttr->GetStart() >= nEnd )
+ return sal_False;
+
+ if ( ( pAttr->Which() == nScriptFontInfoItemId ) &&
+ ( ((SvxFontItem*)pAttr->GetItem())->GetCharSet() == RTL_TEXTENCODING_SYMBOL ) )
+ {
+ // Pruefen, ob das Attribt im Bereich liegt...
+ if ( pAttr->GetEnd() >= nStt )
+ return sal_True;
+ }
+ }
+ return sal_False;
+}
+
+const String* EdtAutoCorrDoc::GetPrevPara( sal_Bool )
+{
+ // Vorherigen Absatz zurueck geben, damit ermittel werden kann,
+ // ob es sich beim aktuellen Wort um einen Satzanfang handelt.
+
+ bAllowUndoAction = sal_False; // Jetzt nicht mehr...
+
+ ContentList& rNodes = pImpEE->GetEditDoc();
+ sal_uInt16 nPos = rNodes.GetPos( pCurNode );
+
+ // Sonderbehandlung: Bullet => Absatzanfang => einfach NULL returnen...
+ const SfxBoolItem& rBulletState = (const SfxBoolItem&)
+ pImpEE->GetParaAttrib( nPos, EE_PARA_BULLETSTATE );
+ sal_Bool bBullet = rBulletState.GetValue() ? sal_True : sal_False;
+ if ( !bBullet && ( pImpEE->aStatus.GetControlWord() & EE_CNTRL_OUTLINER ) )
+ {
+ // Der Outliner hat im Gliederungsmodus auf Ebene 0 immer ein Bullet.
+ const SfxInt16Item& rLevel = (const SfxInt16Item&)
+ pImpEE->GetParaAttrib( nPos, EE_PARA_OUTLLEVEL );
+ if ( rLevel.GetValue() == 0 )
+ bBullet = sal_True;
+ }
+ if ( bBullet )
+ return NULL;
+
+ for ( sal_uInt16 n = nPos; n; )
+ {
+ n--;
+ ContentNode* pNode = rNodes[n];
+ if ( pNode->Len() )
+ return pNode;
+ }
+ return NULL;
+
+}
+
+sal_Bool EdtAutoCorrDoc::ChgAutoCorrWord( sal_uInt16& rSttPos,
+ sal_uInt16 nEndPos, SvxAutoCorrect& rACorrect,
+ const String** ppPara )
+{
+ // Absatz-Anfang oder ein Blank gefunden, suche nach dem Wort
+ // Kuerzel im Auto
+
+ bAllowUndoAction = sal_False; // Jetzt nicht mehr...
+
+ String aShort( pCurNode->Copy( rSttPos, nEndPos - rSttPos ) );
+ sal_Bool bRet = sal_False;
+
+ if( !aShort.Len() )
+ return bRet;
+
+ LanguageType eLang = pImpEE->GetLanguage( EditPaM( pCurNode, rSttPos+1 ) );
+ const SvxAutocorrWord* pFnd = rACorrect.SearchWordsInList( *pCurNode, rSttPos, nEndPos, *this, eLang );
+ if( pFnd && pFnd->IsTextOnly() )
+ {
+ // dann mal ersetzen
+ EditSelection aSel( EditPaM( pCurNode, rSttPos ),
+ EditPaM( pCurNode, nEndPos ) );
+ aSel = pImpEE->ImpDeleteSelection( aSel );
+ DBG_ASSERT( nCursor >= nEndPos, "Cursor mitten im Geschehen ?!" );
+ nCursor -= ( nEndPos-rSttPos );
+ pImpEE->ImpInsertText( aSel, pFnd->GetLong() );
+ nCursor = nCursor + pFnd->GetLong().Len();
+ if( ppPara )
+ *ppPara = pCurNode;
+ bRet = sal_True;
+ }
+
+ return bRet;
+}
+
+LanguageType EdtAutoCorrDoc::GetLanguage( sal_uInt16 nPos, sal_Bool ) const
+{
+ return pImpEE->GetLanguage( EditPaM( pCurNode, nPos+1 ) );
+}
+
+void EdtAutoCorrDoc::ImplStartUndoAction()
+{
+ sal_uInt16 nPara = pImpEE->GetEditDoc().GetPos( pCurNode );
+ ESelection aSel( nPara, nCursor, nPara, nCursor );
+ pImpEE->UndoActionStart( EDITUNDO_INSERT, aSel );
+ bUndoAction = sal_True;
+ bAllowUndoAction = sal_False;
+}
+
diff --git a/editeng/source/editeng/edtspell.hxx b/editeng/source/editeng/edtspell.hxx
new file mode 100644
index 000000000000..cfe0aaf57e87
--- /dev/null
+++ b/editeng/source/editeng/edtspell.hxx
@@ -0,0 +1,185 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef _EDTSPELL_HXX
+#define _EDTSPELL_HXX
+
+#include <svtools/svxbox.hxx>
+#include <editeng/svxenum.hxx>
+#include <editeng/splwrap.hxx>
+#include <editeng/svxacorr.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <editeng/editengdllapi.h>
+
+namespace com { namespace sun { namespace star { namespace linguistic2 {
+ class XSpellChecker1;
+}}}}
+
+
+class EditView;
+class ImpEditEngine;
+class ContentNode;
+
+class EditSpellWrapper : public SvxSpellWrapper
+{
+private:
+ EditView* pEditView;
+ void CheckSpellTo();
+
+protected:
+ virtual void SpellStart( SvxSpellArea eArea );
+ virtual BOOL SpellContinue(); // Bereich pruefen
+ virtual void ReplaceAll( const String &rNewText, INT16 nLanguage );
+ virtual void SpellEnd();
+ virtual BOOL SpellMore();
+ virtual BOOL HasOtherCnt();
+ virtual void ScrollArea();
+ virtual void ChangeWord( const String& rNewWord, const USHORT nLang );
+ virtual void ChangeThesWord( const String& rNewWord );
+ virtual void AutoCorrect( const String& rOldWord, const String& rNewWord );
+
+public:
+ EditSpellWrapper( Window* pWin,
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::linguistic2::XSpellChecker1 > &xChecker,
+ BOOL bIsStart,
+ BOOL bIsAllRight, EditView* pView );
+
+};
+
+
+struct WrongRange
+{
+ USHORT nStart;
+ USHORT nEnd;
+
+ WrongRange( USHORT nS, USHORT nE ) { nStart = nS; nEnd = nE; }
+};
+
+SV_DECL_VARARR( WrongRanges, WrongRange, 4, 4 )
+#define NOT_INVALID 0xFFFF
+
+class WrongList : private WrongRanges
+{
+private:
+ USHORT nInvalidStart;
+ USHORT nInvalidEnd;
+
+ BOOL DbgIsBuggy() const;
+
+public:
+ WrongList();
+ ~WrongList();
+
+ BOOL IsInvalid() const { return nInvalidStart != NOT_INVALID; }
+ void SetValid() { nInvalidStart = NOT_INVALID; nInvalidEnd = 0; }
+ void MarkInvalid( USHORT nS, USHORT nE )
+ {
+ if ( ( nInvalidStart == NOT_INVALID ) || ( nInvalidStart > nS ) )
+ nInvalidStart = nS;
+ if ( nInvalidEnd < nE )
+ nInvalidEnd = nE;
+ }
+
+ USHORT Count() const { return WrongRanges::Count(); }
+
+ // Wenn man weiss was man tut:
+ WrongRange& GetObject( USHORT n ) const { return WrongRanges::GetObject( n ); }
+ void InsertWrong( const WrongRange& rWrong, USHORT nPos );
+
+ USHORT GetInvalidStart() const { return nInvalidStart; }
+ USHORT& GetInvalidStart() { return nInvalidStart; }
+
+ USHORT GetInvalidEnd() const { return nInvalidEnd; }
+ USHORT& GetInvalidEnd() { return nInvalidEnd; }
+
+ void TextInserted( USHORT nPos, USHORT nChars, BOOL bPosIsSep );
+ void TextDeleted( USHORT nPos, USHORT nChars );
+
+ void ResetRanges() { Remove( 0, Count() ); }
+ BOOL HasWrongs() const { return Count() != 0; }
+ void InsertWrong( USHORT nStart, USHORT nEnd, BOOL bClearRange );
+ BOOL NextWrong( USHORT& rnStart, USHORT& rnEnd ) const;
+ BOOL HasWrong( USHORT nStart, USHORT nEnd ) const;
+ BOOL HasAnyWrong( USHORT nStart, USHORT nEnd ) const;
+ void ClearWrongs( USHORT nStart, USHORT nEnd, const ContentNode* pNode );
+ void MarkWrongsInvalid();
+
+ WrongList* Clone() const;
+
+ // #i102062#
+ bool operator==(const WrongList& rCompare) const;
+};
+
+inline void WrongList::InsertWrong( const WrongRange& rWrong, USHORT nPos )
+{
+ WrongRanges::Insert( rWrong, nPos );
+#ifdef DBG_UTIL
+ DBG_ASSERT( !DbgIsBuggy(), "Insert: WrongList kaputt!" );
+#endif
+}
+
+
+
+class EdtAutoCorrDoc : public SvxAutoCorrDoc
+{
+ ImpEditEngine* pImpEE;
+ ContentNode* pCurNode;
+ USHORT nCursor;
+
+ BOOL bAllowUndoAction;
+ BOOL bUndoAction;
+
+protected:
+ void ImplStartUndoAction();
+
+public:
+ EdtAutoCorrDoc( ImpEditEngine* pImpEE, ContentNode* pCurNode, USHORT nCrsr, xub_Unicode cIns );
+ ~EdtAutoCorrDoc();
+
+ virtual BOOL Delete( USHORT nStt, USHORT nEnd );
+ virtual BOOL Insert( USHORT nPos, const String& rTxt );
+ virtual BOOL Replace( USHORT nPos, const String& rTxt );
+
+ virtual BOOL SetAttr( USHORT nStt, USHORT nEnd, USHORT nSlotId, SfxPoolItem& );
+ virtual BOOL SetINetAttr( USHORT nStt, USHORT nEnd, const String& rURL );
+
+ virtual BOOL HasSymbolChars( USHORT nStt, USHORT nEnd );
+
+ virtual const String* GetPrevPara( BOOL bAtNormalPos );
+
+ virtual BOOL ChgAutoCorrWord( USHORT& rSttPos, USHORT nEndPos,
+ SvxAutoCorrect& rACorrect, const String** ppPara );
+
+ virtual LanguageType GetLanguage( USHORT nPos, BOOL bPrevPara = FALSE ) const;
+
+ USHORT GetCursor() const { return nCursor; }
+
+};
+
+#endif // EDTSPELL
+
diff --git a/editeng/source/editeng/eehtml.cxx b/editeng/source/editeng/eehtml.cxx
new file mode 100644
index 000000000000..ddb82a06661d
--- /dev/null
+++ b/editeng/source/editeng/eehtml.cxx
@@ -0,0 +1,850 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 <eehtml.hxx>
+#include <impedit.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/flditem.hxx>
+#include <tools/urlobj.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <svtools/htmltokn.h>
+#include <svtools/htmlkywd.hxx>
+
+
+#define ACTION_INSERTTEXT 1
+#define ACTION_INSERTPARABRK 2
+
+#define STYLE_PRE 101
+
+EditHTMLParser::EditHTMLParser( SvStream& rIn, const String& rBaseURL, SvKeyValueIterator* pHTTPHeaderAttrs )
+ : HTMLParser( rIn, true )
+ , aBaseURL( rBaseURL )
+{
+ pImpEditEngine = 0;
+ pCurAnchor = 0;
+ bInPara = FALSE;
+ bWasInPara = FALSE;
+ nInTable = 0;
+ nInCell = 0;
+ nDefListLevel = 0;
+ nBulletLevel = 0;
+ nNumberingLevel = 0;
+ bFieldsInserted = FALSE;
+
+ if ( pHTTPHeaderAttrs )
+ SetEncodingByHTTPHeader( pHTTPHeaderAttrs );
+}
+
+EditHTMLParser::~EditHTMLParser()
+{
+ delete pCurAnchor;
+}
+
+SvParserState EditHTMLParser::CallParser( ImpEditEngine* pImpEE, const EditPaM& rPaM )
+{
+ DBG_ASSERT( pImpEE, "CallParser: ImpEditEngine ?!" );
+ pImpEditEngine = pImpEE;
+ SvParserState _eState = SVPAR_NOTSTARTED;
+ if ( pImpEditEngine )
+ {
+ // Umbrechmimik vom RTF-Import einbauen?
+ aCurSel = EditSelection( rPaM, rPaM );
+
+ if ( pImpEditEngine->aImportHdl.IsSet() )
+ {
+ ImportInfo aImportInfo( HTMLIMP_START, this, pImpEditEngine->CreateESel( aCurSel ) );
+ pImpEditEngine->aImportHdl.Call( &aImportInfo );
+ }
+
+ ImpSetStyleSheet( 0 );
+ _eState = HTMLParser::CallParser();
+
+ if ( pImpEditEngine->aImportHdl.IsSet() )
+ {
+ ImportInfo aImportInfo( HTMLIMP_END, this, pImpEditEngine->CreateESel( aCurSel ) );
+ pImpEditEngine->aImportHdl.Call( &aImportInfo );
+ }
+
+ if ( bFieldsInserted )
+ pImpEditEngine->UpdateFields();
+ }
+ return _eState;
+}
+
+void EditHTMLParser::NextToken( int nToken )
+{
+ #ifdef DBG_UTIL
+ HTML_TOKEN_IDS xID = (HTML_TOKEN_IDS)nToken;
+ (void)xID;
+ #endif
+
+ switch( nToken )
+ {
+ case HTML_META:
+ {
+ const HTMLOptions *_pOptions = GetOptions();
+ USHORT nArrLen = _pOptions->Count();
+ BOOL bEquiv = FALSE;
+ for ( USHORT i = 0; i < nArrLen; i++ )
+ {
+ const HTMLOption *pOption = (*_pOptions)[i];
+ switch( pOption->GetToken() )
+ {
+ case HTML_O_HTTPEQUIV:
+ {
+ bEquiv = TRUE;
+ }
+ break;
+ case HTML_O_CONTENT:
+ {
+ if ( bEquiv )
+ {
+ rtl_TextEncoding eEnc = GetEncodingByMIME( pOption->GetString() );
+ if ( eEnc != RTL_TEXTENCODING_DONTKNOW )
+ SetSrcEncoding( eEnc );
+ }
+ }
+ break;
+ }
+ }
+
+ }
+ break;
+ case HTML_PLAINTEXT_ON:
+ case HTML_PLAINTEXT2_ON:
+ bInPara = TRUE;
+ break;
+ case HTML_PLAINTEXT_OFF:
+ case HTML_PLAINTEXT2_OFF:
+ bInPara = FALSE;
+ break;
+
+ case HTML_LINEBREAK:
+ case HTML_NEWPARA:
+ {
+ if ( ( bInPara || nInTable ) &&
+ ( ( nToken == HTML_LINEBREAK ) || HasTextInCurrentPara() ) )
+ {
+ ImpInsertParaBreak();
+ }
+ }
+ break;
+ case HTML_HORZRULE:
+ {
+ if ( HasTextInCurrentPara() )
+ ImpInsertParaBreak();
+ ImpInsertParaBreak();
+ }
+ case HTML_NONBREAKSPACE:
+ {
+ if ( bInPara )
+ {
+ ImpInsertText( String( RTL_CONSTASCII_USTRINGPARAM( " " ) ) );
+ }
+ }
+ break;
+ case HTML_TEXTTOKEN:
+ {
+ if ( !bInPara )
+ StartPara( FALSE );
+
+// if ( bInPara || pCurAnchor )
+ {
+ String aText = aToken;
+ if ( aText.Len() && ( aText.GetChar( 0 ) == ' ' )
+ && ThrowAwayBlank() && !IsReadPRE() )
+ aText.Erase( 0, 1 );
+
+ if ( pCurAnchor )
+ {
+ pCurAnchor->aText += aText;
+ }
+ else
+ {
+ // Nur bis HTML mit 319 geschrieben ?!
+ if ( IsReadPRE() )
+ {
+ USHORT nTabPos = aText.Search( '\t', 0 );
+ while ( nTabPos != STRING_NOTFOUND )
+ {
+ aText.Erase( nTabPos, 1 );
+ aText.Insert( String( RTL_CONSTASCII_USTRINGPARAM( " " ) ), nTabPos );
+ nTabPos = aText.Search( '\t', nTabPos+8 );
+ }
+ }
+ ImpInsertText( aText );
+ }
+ }
+ }
+ break;
+
+ case HTML_CENTER_ON:
+ case HTML_CENTER_OFF: // if ( bInPara )
+ {
+ USHORT nNode = pImpEditEngine->GetEditDoc().GetPos( aCurSel.Max().GetNode() );
+ SfxItemSet aItems( aCurSel.Max().GetNode()->GetContentAttribs().GetItems() );
+ aItems.ClearItem( EE_PARA_JUST );
+ if ( nToken == HTML_CENTER_ON )
+ aItems.Put( SvxAdjustItem( SVX_ADJUST_CENTER, EE_PARA_JUST ) );
+ pImpEditEngine->SetParaAttribs( nNode, aItems );
+ }
+ break;
+
+ case HTML_ANCHOR_ON: AnchorStart();
+ break;
+ case HTML_ANCHOR_OFF: AnchorEnd();
+ break;
+
+ case HTML_PARABREAK_ON:
+ if( bInPara && HasTextInCurrentPara() )
+ EndPara( TRUE );
+ StartPara( TRUE );
+ break;
+
+ case HTML_PARABREAK_OFF:
+ if( bInPara )
+ EndPara( TRUE );
+ break;
+
+ case HTML_HEAD1_ON:
+ case HTML_HEAD2_ON:
+ case HTML_HEAD3_ON:
+ case HTML_HEAD4_ON:
+ case HTML_HEAD5_ON:
+ case HTML_HEAD6_ON:
+ {
+ HeadingStart( nToken );
+ }
+ break;
+
+ case HTML_HEAD1_OFF:
+ case HTML_HEAD2_OFF:
+ case HTML_HEAD3_OFF:
+ case HTML_HEAD4_OFF:
+ case HTML_HEAD5_OFF:
+ case HTML_HEAD6_OFF:
+ {
+ HeadingEnd( nToken );
+ }
+ break;
+
+ case HTML_PREFORMTXT_ON:
+ case HTML_XMP_ON:
+ case HTML_LISTING_ON:
+ {
+ StartPara( TRUE );
+ ImpSetStyleSheet( STYLE_PRE );
+ }
+ break;
+
+ case HTML_DEFLIST_ON:
+ {
+ nDefListLevel++;
+ }
+ break;
+
+ case HTML_DEFLIST_OFF:
+ {
+ if( nDefListLevel )
+ nDefListLevel--;
+ }
+ break;
+
+ case HTML_TABLE_ON: nInTable++;
+ break;
+ case HTML_TABLE_OFF: DBG_ASSERT( nInTable, "Nicht in Table, aber TABLE_OFF?" );
+ nInTable--;
+ break;
+
+ case HTML_TABLEHEADER_ON:
+ case HTML_TABLEDATA_ON:
+ nInCell++;
+ // fallthru
+ case HTML_BLOCKQUOTE_ON:
+ case HTML_BLOCKQUOTE_OFF:
+ case HTML_BLOCKQUOTE30_ON:
+ case HTML_BLOCKQUOTE30_OFF:
+ case HTML_LISTHEADER_ON:
+ case HTML_LI_ON:
+ case HTML_DD_ON:
+ case HTML_DT_ON:
+ case HTML_ORDERLIST_ON:
+ case HTML_UNORDERLIST_ON:
+ {
+ BOOL bHasText = HasTextInCurrentPara();
+ if ( bHasText )
+ ImpInsertParaBreak();
+ StartPara( FALSE );
+ }
+ break;
+
+ case HTML_TABLEHEADER_OFF:
+ case HTML_TABLEDATA_OFF:
+ {
+ if ( nInCell )
+ nInCell--;
+ }
+ // fallthru
+ case HTML_LISTHEADER_OFF:
+ case HTML_LI_OFF:
+ case HTML_DD_OFF:
+ case HTML_DT_OFF:
+ case HTML_ORDERLIST_OFF:
+ case HTML_UNORDERLIST_OFF: EndPara( FALSE );
+ break;
+
+ case HTML_TABLEROW_ON:
+ case HTML_TABLEROW_OFF: // Nur nach einem CELL ein RETURN, fuer Calc
+
+ case HTML_COL_ON:
+ case HTML_COLGROUP_ON:
+ case HTML_COLGROUP_OFF: break;
+
+ case HTML_FONT_ON: // ...
+ break;
+ case HTML_FONT_OFF: // ...
+ break;
+
+
+ // #58335# kein SkipGroup on/off auf inline markup etc.
+
+ // globals
+ case HTML_HTML_ON:
+ case HTML_HTML_OFF:
+ case HTML_BODY_ON:
+ case HTML_BODY_OFF:
+ case HTML_HEAD_ON:
+ case HTML_HEAD_OFF:
+ case HTML_FORM_ON:
+ case HTML_FORM_OFF:
+ case HTML_THEAD_ON:
+ case HTML_THEAD_OFF:
+ case HTML_TBODY_ON:
+ case HTML_TBODY_OFF:
+ case HTML_TITLE_ON:
+ case HTML_TITLE_OFF:
+ // inline elements, structural markup
+ // HTML 3.0
+ case HTML_BANNER_ON:
+ case HTML_BANNER_OFF:
+ case HTML_DIVISION_ON:
+ case HTML_DIVISION_OFF:
+// case HTML_LISTHEADER_ON: //! special handling
+// case HTML_LISTHEADER_OFF:
+ case HTML_NOTE_ON:
+ case HTML_NOTE_OFF:
+ // inline elements, logical markup
+ // HTML 2.0
+ case HTML_ADDRESS_ON:
+ case HTML_ADDRESS_OFF:
+// case HTML_BLOCKQUOTE_ON: //! extra Behandlung
+// case HTML_BLOCKQUOTE_OFF:
+ case HTML_CITIATION_ON:
+ case HTML_CITIATION_OFF:
+ case HTML_CODE_ON:
+ case HTML_CODE_OFF:
+ case HTML_DEFINSTANCE_ON:
+ case HTML_DEFINSTANCE_OFF:
+ case HTML_EMPHASIS_ON:
+ case HTML_EMPHASIS_OFF:
+ case HTML_KEYBOARD_ON:
+ case HTML_KEYBOARD_OFF:
+ case HTML_SAMPLE_ON:
+ case HTML_SAMPLE_OFF:
+ case HTML_STRIKE_ON:
+ case HTML_STRIKE_OFF:
+ case HTML_STRONG_ON:
+ case HTML_STRONG_OFF:
+ case HTML_VARIABLE_ON:
+ case HTML_VARIABLE_OFF:
+ // HTML 3.0
+ case HTML_ABBREVIATION_ON:
+ case HTML_ABBREVIATION_OFF:
+ case HTML_ACRONYM_ON:
+ case HTML_ACRONYM_OFF:
+ case HTML_AUTHOR_ON:
+ case HTML_AUTHOR_OFF:
+// case HTML_BLOCKQUOTE30_ON: //! extra Behandlung
+// case HTML_BLOCKQUOTE30_OFF:
+ case HTML_DELETEDTEXT_ON:
+ case HTML_DELETEDTEXT_OFF:
+ case HTML_INSERTEDTEXT_ON:
+ case HTML_INSERTEDTEXT_OFF:
+ case HTML_LANGUAGE_ON:
+ case HTML_LANGUAGE_OFF:
+ case HTML_PERSON_ON:
+ case HTML_PERSON_OFF:
+ case HTML_SHORTQUOTE_ON:
+ case HTML_SHORTQUOTE_OFF:
+ case HTML_SUBSCRIPT_ON:
+ case HTML_SUBSCRIPT_OFF:
+ case HTML_SUPERSCRIPT_ON:
+ case HTML_SUPERSCRIPT_OFF:
+ // inline elements, visual markup
+ // HTML 2.0
+ case HTML_BOLD_ON:
+ case HTML_BOLD_OFF:
+ case HTML_ITALIC_ON:
+ case HTML_ITALIC_OFF:
+ case HTML_TELETYPE_ON:
+ case HTML_TELETYPE_OFF:
+ case HTML_UNDERLINE_ON:
+ case HTML_UNDERLINE_OFF:
+ // HTML 3.0
+ case HTML_BIGPRINT_ON:
+ case HTML_BIGPRINT_OFF:
+ case HTML_STRIKETHROUGH_ON:
+ case HTML_STRIKETHROUGH_OFF:
+ case HTML_SMALLPRINT_ON:
+ case HTML_SMALLPRINT_OFF:
+ // figures
+ case HTML_FIGURE_ON:
+ case HTML_FIGURE_OFF:
+ case HTML_CAPTION_ON:
+ case HTML_CAPTION_OFF:
+ case HTML_CREDIT_ON:
+ case HTML_CREDIT_OFF:
+ // misc
+ case HTML_DIRLIST_ON:
+ case HTML_DIRLIST_OFF:
+ case HTML_FOOTNOTE_ON: //! landen so im Text
+ case HTML_FOOTNOTE_OFF:
+ case HTML_MENULIST_ON:
+ case HTML_MENULIST_OFF:
+// case HTML_PLAINTEXT_ON: //! extra Behandlung
+// case HTML_PLAINTEXT_OFF:
+// case HTML_PREFORMTXT_ON: //! extra Behandlung
+// case HTML_PREFORMTXT_OFF:
+ case HTML_SPAN_ON:
+ case HTML_SPAN_OFF:
+ // obsolete
+// case HTML_XMP_ON: //! extra Behandlung
+// case HTML_XMP_OFF:
+// case HTML_LISTING_ON: //! extra Behandlung
+// case HTML_LISTING_OFF:
+ // Netscape
+ case HTML_BLINK_ON:
+ case HTML_BLINK_OFF:
+ case HTML_NOBR_ON:
+ case HTML_NOBR_OFF:
+ case HTML_NOEMBED_ON:
+ case HTML_NOEMBED_OFF:
+ case HTML_NOFRAMES_ON:
+ case HTML_NOFRAMES_OFF:
+ // Internet Explorer
+ case HTML_MARQUEE_ON:
+ case HTML_MARQUEE_OFF:
+// case HTML_PLAINTEXT2_ON: //! extra Behandlung
+// case HTML_PLAINTEXT2_OFF:
+ break;
+
+ default:
+ {
+ if ( nToken & HTML_TOKEN_ONOFF )
+ {
+ if ( ( nToken == HTML_UNKNOWNCONTROL_ON ) || ( nToken == HTML_UNKNOWNCONTROL_OFF ) )
+ {
+ ;
+ }
+ else if ( !(nToken & 1) )
+ {
+ DBG_ASSERT( !( nToken & 1 ), "Kein Start-Token ?!" );
+ SkipGroup( nToken + 1 );
+ }
+ }
+ }
+ } // SWITCH
+
+ if ( pImpEditEngine->aImportHdl.IsSet() )
+ {
+ ImportInfo aImportInfo( HTMLIMP_NEXTTOKEN, this, pImpEditEngine->CreateESel( aCurSel ) );
+ aImportInfo.nToken = nToken;
+ aImportInfo.nTokenValue = (short)nTokenValue;
+ if ( nToken == HTML_TEXTTOKEN )
+ aImportInfo.aText = aToken;
+ pImpEditEngine->aImportHdl.Call( &aImportInfo );
+ }
+
+}
+
+void EditHTMLParser::ImpInsertParaBreak()
+{
+ if ( pImpEditEngine->aImportHdl.IsSet() )
+ {
+ ImportInfo aImportInfo( HTMLIMP_INSERTPARA, this, pImpEditEngine->CreateESel( aCurSel ) );
+ pImpEditEngine->aImportHdl.Call( &aImportInfo );
+ }
+ aCurSel = pImpEditEngine->ImpInsertParaBreak( aCurSel );
+ nLastAction = ACTION_INSERTPARABRK;
+}
+
+void EditHTMLParser::ImpSetAttribs( const SfxItemSet& rItems, EditSelection* pSel )
+{
+ // pSel, wenn Zeichenattribute, sonst Absatzattribute fuer den
+ // aktuellen Absatz.
+ DBG_ASSERT( pSel || ( aCurSel.Min().GetNode() == aCurSel.Max().GetNode() ), "ImpInsertAttribs: Selektion?" );
+
+ EditPaM aStartPaM( pSel ? pSel->Min() : aCurSel.Min() );
+ EditPaM aEndPaM( pSel ? pSel->Max() : aCurSel.Max() );
+
+ if ( !pSel )
+ {
+ aStartPaM.SetIndex( 0 );
+ aEndPaM.SetIndex( aEndPaM.GetNode()->Len() );
+ }
+
+ if ( pImpEditEngine->aImportHdl.IsSet() )
+ {
+ EditSelection aSel( aStartPaM, aEndPaM );
+ ImportInfo aImportInfo( HTMLIMP_SETATTR, this, pImpEditEngine->CreateESel( aSel ) );
+ aImportInfo.pAttrs = (void*)&rItems;
+ pImpEditEngine->aImportHdl.Call( &aImportInfo );
+ }
+
+ ContentNode* pSN = aStartPaM.GetNode();
+ USHORT nStartNode = pImpEditEngine->GetEditDoc().GetPos( pSN );
+
+ // Wenn ein Attribut von 0 bis aktuelle Absatzlaenge geht,
+ // soll es ein Absatz-Attribut sein!
+
+ // Achtung: Selektion kann ueber mehrere Absaetze gehen.
+ // Alle vollstaendigen Absaetze sind Absatzattribute...
+
+ // HTML eigentlich nicht:
+#ifdef DBG_UTIL
+ ContentNode* pEN = aEndPaM.GetNode();
+ USHORT nEndNode = pImpEditEngine->GetEditDoc().GetPos( pEN );
+ DBG_ASSERT( nStartNode == nEndNode, "ImpSetAttribs: Mehrere Absaetze?" );
+#endif
+
+/*
+ for ( USHORT z = nStartNode+1; z < nEndNode; z++ )
+ {
+ DBG_ASSERT( pImpEditEngine->GetEditDoc().SaveGetObject( z ), "Node existiert noch nicht(RTF)" );
+ pImpEditEngine->SetParaAttribs( z, rSet.GetAttrSet() );
+ }
+
+ if ( aStartPaM.GetNode() != aEndPaM.GetNode() )
+ {
+ // Den Rest des StartNodes...
+ if ( aStartPaM.GetIndex() == 0 )
+ pImpEditEngine->SetParaAttribs( nStartNode, rSet.GetAttrSet() );
+ else
+ pImpEditEngine->SetAttribs( EditSelection( aStartPaM, EditPaM( aStartPaM.GetNode(), aStartPaM.GetNode()->Len() ) ), rSet.GetAttrSet() );
+
+ // Den Anfang des EndNodes....
+ if ( aEndPaM.GetIndex() == aEndPaM.GetNode()->Len() )
+ pImpEditEngine->SetParaAttribs( nEndNode, rSet.GetAttrSet() );
+ else
+ pImpEditEngine->SetAttribs( EditSelection( EditPaM( aEndPaM.GetNode(), 0 ), aEndPaM ), rSet.GetAttrSet() );
+ }
+ else
+*/
+ {
+ if ( ( aStartPaM.GetIndex() == 0 ) && ( aEndPaM.GetIndex() == aEndPaM.GetNode()->Len() ) )
+ {
+ // Muesse gemergt werden:
+ SfxItemSet aItems( pImpEditEngine->GetParaAttribs( nStartNode ) );
+ aItems.Put( rItems );
+ pImpEditEngine->SetParaAttribs( nStartNode, aItems );
+ }
+ else
+ pImpEditEngine->SetAttribs( EditSelection( aStartPaM, aEndPaM ), rItems );
+ }
+}
+
+void EditHTMLParser::ImpSetStyleSheet( USHORT nHLevel )
+{
+ /*
+ nHLevel: 0: Ausschalten
+ 1-6: Heading
+ STYLE_PRE: Preformatted
+ */
+
+// if ( pImpEditEngine->GetStatus().DoImportRTFStyleSheets() )
+// {
+// SvxRTFStyleType* pS = GetStyleTbl().Get( rSet.StyleNo() );
+// DBG_ASSERT( pS, "Vorlage in RTF nicht definiert!" );
+// if ( pS )
+// pImpEditEngine->SetStyleSheet( EditSelection( aStartPaM, aEndPaM ), pS->sName, SFX_STYLE_FAMILY_ALL );
+// }
+// else
+ {
+ // Harte Attribute erzeugen...
+ // Reicht fuer Calc, bei StyleSheets muesste noch geklaert werden,
+ // dass diese auch in der App liegen sollten, damit sie beim
+ // fuettern in eine andere Engine auch noch da sind...
+
+ USHORT nNode = pImpEditEngine->GetEditDoc().GetPos( aCurSel.Max().GetNode() );
+// SfxItemSet aItems( pImpEditEngine->GetEmptyItemSet() );
+ SfxItemSet aItems( aCurSel.Max().GetNode()->GetContentAttribs().GetItems() );
+
+ aItems.ClearItem( EE_PARA_ULSPACE );
+ aItems.ClearItem( EE_CHAR_FONTHEIGHT );
+ aItems.ClearItem( EE_CHAR_FONTINFO );
+ aItems.ClearItem( EE_CHAR_WEIGHT );
+
+ // Fett in den ersten 3 Headings
+ if ( ( nHLevel >= 1 ) && ( nHLevel <= 3 ) )
+ {
+ SvxWeightItem aWeightItem( WEIGHT_BOLD, EE_CHAR_WEIGHT );
+ aItems.Put( aWeightItem );
+ }
+
+ // Fonthoehe und Abstaende, wenn LogicToLogic moeglich:
+ MapUnit eUnit = pImpEditEngine->GetRefMapMode().GetMapUnit();
+ if ( ( eUnit != MAP_PIXEL ) && ( eUnit != MAP_SYSFONT ) &&
+ ( eUnit != MAP_APPFONT ) && ( eUnit != MAP_RELATIVE ) )
+ {
+ long nPoints = 10;
+ if ( nHLevel == 1 )
+ nPoints = 22;
+ else if ( nHLevel == 2 )
+ nPoints = 16;
+ else if ( nHLevel == 3 )
+ nPoints = 12;
+ else if ( nHLevel == 4 )
+ nPoints = 11;
+
+ nPoints = OutputDevice::LogicToLogic( nPoints, MAP_POINT, eUnit );
+ SvxFontHeightItem aHeightItem( nPoints, 100, EE_CHAR_FONTHEIGHT );
+ aItems.Put( aHeightItem );
+
+ // Absatzabstaende, wenn Heading:
+ if ( !nHLevel || ((nHLevel >= 1) && (nHLevel <= 6)) )
+ {
+ SvxULSpaceItem aULSpaceItem( EE_PARA_ULSPACE );
+ aULSpaceItem.SetUpper( (USHORT)OutputDevice::LogicToLogic( 42, MAP_10TH_MM, eUnit ) );
+ aULSpaceItem.SetLower( (USHORT)OutputDevice::LogicToLogic( 35, MAP_10TH_MM, eUnit ) );
+ aItems.Put( aULSpaceItem );
+ }
+ }
+
+ // Bei Pre einen proportionalen Font waehlen
+ if ( nHLevel == STYLE_PRE )
+ {
+ Font aFont = OutputDevice::GetDefaultFont( DEFAULTFONT_FIXED, LANGUAGE_SYSTEM, 0 );
+ SvxFontItem aFontItem( aFont.GetFamily(), aFont.GetName(), XubString(), aFont.GetPitch(), aFont.GetCharSet(), EE_CHAR_FONTINFO );
+ aItems.Put( aFontItem );
+ }
+
+ pImpEditEngine->SetParaAttribs( nNode, aItems );
+ }
+}
+
+void EditHTMLParser::ImpInsertText( const String& rText )
+{
+ String aText( rText );
+ if ( pImpEditEngine->aImportHdl.IsSet() )
+ {
+ ImportInfo aImportInfo( HTMLIMP_INSERTTEXT, this, pImpEditEngine->CreateESel( aCurSel ) );
+ aImportInfo.aText = aText;
+ pImpEditEngine->aImportHdl.Call( &aImportInfo );
+ }
+
+ aCurSel = pImpEditEngine->ImpInsertText( aCurSel, aText );
+ nLastAction = ACTION_INSERTTEXT;
+}
+
+void EditHTMLParser::SkipGroup( int nEndToken )
+{
+ // #69109# groups in cells are closed upon leaving the cell, because those
+ // ******* web authors don't know their job
+ // for example: <td><form></td> lacks a closing </form>
+ BYTE nCellLevel = nInCell;
+ int nToken;
+ while( nCellLevel <= nInCell && ( (nToken = GetNextToken() ) != nEndToken ) && nToken )
+ {
+ switch ( nToken )
+ {
+ case HTML_TABLEHEADER_ON:
+ case HTML_TABLEDATA_ON:
+ nInCell++;
+ break;
+ case HTML_TABLEHEADER_OFF:
+ case HTML_TABLEDATA_OFF:
+ if ( nInCell )
+ nInCell--;
+ break;
+ }
+ }
+}
+
+void EditHTMLParser::StartPara( BOOL bReal )
+{
+ if ( bReal )
+ {
+ const HTMLOptions *_pOptions = GetOptions();
+ USHORT nArrLen = _pOptions->Count();
+ SvxAdjust eAdjust = SVX_ADJUST_LEFT;
+ for ( USHORT i = 0; i < nArrLen; i++ )
+ {
+ const HTMLOption *pOption = (*_pOptions)[i];
+ switch( pOption->GetToken() )
+ {
+ case HTML_O_ALIGN:
+ {
+ if ( pOption->GetString().CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_AL_right ) == COMPARE_EQUAL )
+ eAdjust = SVX_ADJUST_RIGHT;
+ else if ( pOption->GetString().CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_AL_middle ) == COMPARE_EQUAL )
+ eAdjust = SVX_ADJUST_CENTER;
+ else if ( pOption->GetString().CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_AL_center ) == COMPARE_EQUAL )
+ eAdjust = SVX_ADJUST_CENTER;
+ else
+ eAdjust = SVX_ADJUST_LEFT;
+ }
+ break;
+ }
+ }
+ SfxItemSet aItemSet( pImpEditEngine->GetEmptyItemSet() );
+ aItemSet.Put( SvxAdjustItem( eAdjust, EE_PARA_JUST ) );
+ ImpSetAttribs( aItemSet );
+ }
+ bInPara = TRUE;
+}
+
+void EditHTMLParser::EndPara( BOOL )
+{
+ if ( bInPara )
+ {
+ BOOL bHasText = HasTextInCurrentPara();
+ if ( bHasText )
+ ImpInsertParaBreak();
+ // Nur, wenn ohne Absatzabstaende gearbeitet wird...
+// if ( !nInTable && bReal && (nNumberingLevel<=1) && (nBulletLevel<=1) )
+// ImpInsertParaBreak();
+ }
+ bInPara = FALSE;
+}
+
+BOOL EditHTMLParser::ThrowAwayBlank()
+{
+ // Ein Blank muss weggeschmissen werden, wenn der neue Text mit einem
+ // Blank beginnt und der aktuelle Absatz leer ist oder mit einem
+ // Blank endet...
+ ContentNode* pNode = aCurSel.Max().GetNode();
+ if ( pNode->Len() && ( pNode->GetChar( pNode->Len()-1 ) != ' ' ) )
+ return FALSE;
+ return TRUE;
+}
+
+BOOL EditHTMLParser::HasTextInCurrentPara()
+{
+ return aCurSel.Max().GetNode()->Len() ? TRUE : FALSE;
+}
+
+void EditHTMLParser::AnchorStart()
+{
+ // Anker im Anker ignoriern
+ if ( !pCurAnchor )
+ {
+ const HTMLOptions* _pOptions = GetOptions();
+ USHORT nArrLen = _pOptions->Count();
+
+ String aRef;
+
+ for ( USHORT i = 0; i < nArrLen; i++ )
+ {
+ const HTMLOption* pOption = (*_pOptions)[i];
+ switch( pOption->GetToken() )
+ {
+ case HTML_O_HREF:
+ aRef = pOption->GetString();
+ break;
+ }
+ }
+
+ if ( aRef.Len() )
+ {
+ String aURL = aRef;
+ if ( aURL.Len() && ( aURL.GetChar( 0 ) != '#' ) )
+ {
+ INetURLObject aTargetURL;
+ INetURLObject aRootURL( aBaseURL );
+ aRootURL.GetNewAbsURL( aRef, &aTargetURL );
+ aURL = aTargetURL.GetMainURL( INetURLObject::DECODE_TO_IURI );
+ }
+ pCurAnchor = new AnchorInfo;
+ pCurAnchor->aHRef = aURL;
+ }
+ }
+}
+
+void EditHTMLParser::AnchorEnd()
+{
+ if ( pCurAnchor )
+ {
+ // Als URL-Feld einfuegen...
+ SvxFieldItem aFld( SvxURLField( pCurAnchor->aHRef, pCurAnchor->aText, SVXURLFORMAT_REPR ), EE_FEATURE_FIELD );
+ aCurSel = pImpEditEngine->InsertField( aCurSel, aFld );
+ bFieldsInserted = TRUE;
+ delete pCurAnchor;
+ pCurAnchor = 0;
+
+ if ( pImpEditEngine->aImportHdl.IsSet() )
+ {
+ ImportInfo aImportInfo( HTMLIMP_INSERTFIELD, this, pImpEditEngine->CreateESel( aCurSel ) );
+ pImpEditEngine->aImportHdl.Call( &aImportInfo );
+ }
+ }
+}
+
+void EditHTMLParser::HeadingStart( int nToken )
+{
+ bWasInPara = bInPara;
+ StartPara( FALSE );
+
+ if ( bWasInPara && HasTextInCurrentPara() )
+ ImpInsertParaBreak();
+
+ USHORT nId = sal::static_int_cast< USHORT >(
+ 1 + ( ( nToken - HTML_HEAD1_ON ) / 2 ) );
+ DBG_ASSERT( (nId >= 1) && (nId <= 9), "HeadingStart: ID kann nicht stimmen!" );
+ ImpSetStyleSheet( nId );
+}
+
+void EditHTMLParser::HeadingEnd( int )
+{
+ EndPara( FALSE );
+ ImpSetStyleSheet( 0 );
+
+ if ( bWasInPara )
+ {
+ bInPara = TRUE;
+ bWasInPara = FALSE;
+ }
+}
diff --git a/editeng/source/editeng/eehtml.hxx b/editeng/source/editeng/eehtml.hxx
new file mode 100644
index 000000000000..a9b20bcd652f
--- /dev/null
+++ b/editeng/source/editeng/eehtml.hxx
@@ -0,0 +1,98 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef _EEHTML_HXX
+#define _EEHTML_HXX
+
+#include <svl/svarray.hxx>
+
+#include <editdoc.hxx>
+#include <svtools/parhtml.hxx>
+
+class ImpEditEngine;
+
+#define MAX_NUMBERLEVEL 10
+
+struct AnchorInfo
+{
+ String aHRef;
+ String aText;
+};
+
+class EditHTMLParser : public HTMLParser
+{
+ using HTMLParser::CallParser;
+private:
+ EditSelection aCurSel;
+ String aBaseURL;
+ ImpEditEngine* pImpEditEngine;
+ AnchorInfo* pCurAnchor;
+
+ BOOL bInPara;
+ BOOL bWasInPara; // bInPara vor HeadingStart merken, weil sonst hinterher weg
+ BOOL bFieldsInserted;
+ BYTE nInTable;
+ BYTE nInCell;
+
+ BYTE nDefListLevel;
+ BYTE nBulletLevel;
+ BYTE nNumberingLevel;
+
+ BYTE nLastAction;
+
+ void StartPara( BOOL bReal );
+ void EndPara( BOOL bReal );
+ void AnchorStart();
+ void AnchorEnd();
+ void HeadingStart( int nToken );
+ void HeadingEnd( int nToken );
+ void SkipGroup( int nEndToken );
+ BOOL ThrowAwayBlank();
+ BOOL HasTextInCurrentPara();
+ void ProcessUnknownControl( BOOL bOn );
+
+ void ImpInsertParaBreak();
+ void ImpInsertText( const String& rText );
+ void ImpSetAttribs( const SfxItemSet& rItems, EditSelection* pSel = 0 );
+ void ImpSetStyleSheet( USHORT nHeadingLevel );
+
+protected:
+ virtual void NextToken( int nToken );
+
+public:
+ EditHTMLParser( SvStream& rIn, const String& rBaseURL, SvKeyValueIterator* pHTTPHeaderAttrs );
+ ~EditHTMLParser();
+
+ virtual SvParserState CallParser( ImpEditEngine* pImpEE, const EditPaM& rPaM );
+
+ const EditSelection& GetCurSelection() const { return aCurSel; }
+};
+
+SV_DECL_REF( EditHTMLParser )
+SV_IMPL_REF( EditHTMLParser );
+
+#endif // _EEHTML_HXX
diff --git a/editeng/source/editeng/eeng_pch.cxx b/editeng/source/editeng/eeng_pch.cxx
new file mode 100644
index 000000000000..249f4cb0ab12
--- /dev/null
+++ b/editeng/source/editeng/eeng_pch.cxx
@@ -0,0 +1,30 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 <eeng_pch.hxx>
diff --git a/editeng/source/editeng/eeng_pch.hxx b/editeng/source/editeng/eeng_pch.hxx
new file mode 100644
index 000000000000..14c8b9f5dc4b
--- /dev/null
+++ b/editeng/source/editeng/eeng_pch.hxx
@@ -0,0 +1,34 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+#define _STD_VAR_ARRAYS
+
+#include <vcl/wrkwin.hxx>
+#include <vcl/dialog.hxx>
+#include <vcl/msgbox.hxx>
+#include <vcl/svapp.hxx>
+
+
diff --git a/editeng/source/editeng/eeobj.cxx b/editeng/source/editeng/eeobj.cxx
new file mode 100644
index 000000000000..a275f8b5d372
--- /dev/null
+++ b/editeng/source/editeng/eeobj.cxx
@@ -0,0 +1,112 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 <eeng_pch.hxx>
+
+#include <eeobj.hxx>
+#include <sot/exchange.hxx>
+#include <sot/formats.hxx>
+#include <editeng/editeng.hxx>
+#include <svl/itempool.hxx>
+#include <vos/mutex.hxx>
+#include <vcl/svapp.hxx>
+using namespace ::com::sun::star;
+
+
+EditDataObject::EditDataObject()
+{
+}
+
+EditDataObject::~EditDataObject()
+{
+}
+
+// uno::XInterface
+uno::Any EditDataObject::queryInterface( const uno::Type & rType ) throw(uno::RuntimeException)
+{
+ uno::Any aRet = ::cppu::queryInterface( rType, SAL_STATIC_CAST( datatransfer::XTransferable*, this ) );
+ return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ));
+}
+
+// datatransfer::XTransferable
+uno::Any EditDataObject::getTransferData( const datatransfer::DataFlavor& rFlavor ) throw(datatransfer::UnsupportedFlavorException, io::IOException, uno::RuntimeException)
+{
+ uno::Any aAny;
+
+ ULONG nT = SotExchange::GetFormat( rFlavor );
+ if ( nT == SOT_FORMAT_STRING )
+ {
+ aAny <<= (::rtl::OUString)GetString();
+ }
+ else if ( ( nT == SOT_FORMATSTR_ID_EDITENGINE ) || ( nT == SOT_FORMAT_RTF ) )
+ {
+ // MT 01/2002: No RTF on demand any more:
+ // 1) Was not working, because I had to flush() the clipboard immediately anyway
+ // 2) Don't have the old pool defaults and the StyleSheetPool here.
+
+ SvMemoryStream* pStream = ( nT == SOT_FORMATSTR_ID_EDITENGINE ) ? &GetStream() : &GetRTFStream();
+ pStream->Seek( STREAM_SEEK_TO_END );
+ ULONG nLen = pStream->Tell();
+ pStream->Seek(0);
+
+ uno::Sequence< sal_Int8 > aSeq( nLen );
+ memcpy( aSeq.getArray(), pStream->GetData(), nLen );
+ aAny <<= aSeq;
+ }
+ else
+ {
+ datatransfer::UnsupportedFlavorException aException;
+ throw( aException );
+ }
+
+ return aAny;
+}
+
+uno::Sequence< datatransfer::DataFlavor > EditDataObject::getTransferDataFlavors( ) throw(uno::RuntimeException)
+{
+ uno::Sequence< datatransfer::DataFlavor > aDataFlavors(3);
+ SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_EDITENGINE, aDataFlavors.getArray()[0] );
+ SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aDataFlavors.getArray()[1] );
+ SotExchange::GetFormatDataFlavor( SOT_FORMAT_RTF, aDataFlavors.getArray()[2] );
+
+ return aDataFlavors;
+}
+
+sal_Bool EditDataObject::isDataFlavorSupported( const datatransfer::DataFlavor& rFlavor ) throw(uno::RuntimeException)
+{
+ sal_Bool bSupported = sal_False;
+
+ ULONG nT = SotExchange::GetFormat( rFlavor );
+ if ( ( nT == SOT_FORMAT_STRING ) || ( nT == SOT_FORMAT_RTF ) /* || ( nT == SOT_FORMAT_XML ) */ || ( nT == SOT_FORMATSTR_ID_EDITENGINE ) )
+ bSupported = sal_True;
+
+ return bSupported;
+}
diff --git a/editeng/source/editeng/eeobj.hxx b/editeng/source/editeng/eeobj.hxx
new file mode 100644
index 000000000000..6a4956b2481a
--- /dev/null
+++ b/editeng/source/editeng/eeobj.hxx
@@ -0,0 +1,72 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef _DATAOBJ_HXX
+#define _DATAOBJ_HXX
+
+#include <cppuhelper/weak.hxx>
+#include <com/sun/star/datatransfer/XTransferable.hpp>
+
+#include <tools/stream.hxx>
+
+class EditDataObject : public ::com::sun::star::datatransfer::XTransferable,
+ public ::cppu::OWeakObject
+
+{
+private:
+ SvMemoryStream maBinData;
+ SvMemoryStream maRTFData;
+ String maText;
+
+ String maOfficeBookmark;
+
+// String maNetscapeBookmark;
+// SvMemoryStream maRTFData;
+
+public:
+ EditDataObject();
+ ~EditDataObject();
+
+ SvMemoryStream& GetStream() { return maBinData; }
+ SvMemoryStream& GetRTFStream() { return maRTFData; }
+ String& GetString() { return maText; }
+ String& GetURL() { return maOfficeBookmark; }
+
+
+ // ::com::sun::star::uno::XInterface
+ ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException);
+ void SAL_CALL acquire() throw() { OWeakObject::acquire(); }
+ void SAL_CALL release() throw() { OWeakObject::release(); }
+
+ // ::com::sun::star::datatransfer::XTransferable
+ ::com::sun::star::uno::Any SAL_CALL getTransferData( const ::com::sun::star::datatransfer::DataFlavor& aFlavor ) throw(::com::sun::star::datatransfer::UnsupportedFlavorException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ ::com::sun::star::uno::Sequence< ::com::sun::star::datatransfer::DataFlavor > SAL_CALL getTransferDataFlavors( ) throw(::com::sun::star::uno::RuntimeException);
+ sal_Bool SAL_CALL isDataFlavorSupported( const ::com::sun::star::datatransfer::DataFlavor& aFlavor ) throw(::com::sun::star::uno::RuntimeException);
+};
+
+#endif // _DATAOBJ_HXX
+
diff --git a/editeng/source/editeng/eerdll.cxx b/editeng/source/editeng/eerdll.cxx
new file mode 100644
index 000000000000..7d6df3f0fab4
--- /dev/null
+++ b/editeng/source/editeng/eerdll.cxx
@@ -0,0 +1,237 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 <com/sun/star/linguistic2/XLanguageGuessing.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <comphelper/processfactory.hxx>
+
+#include <svl/solar.hrc>
+#include <editeng/eerdll.hxx>
+#include <eerdll2.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/bulitem.hxx>
+#include <editeng/flditem.hxx>
+#include <editeng/emphitem.hxx>
+#include <editeng/scriptspaceitem.hxx>
+#include <svl/itempool.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/svapp.hxx>
+
+#include <editeng/akrnitem.hxx>
+#include <editeng/cntritem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/crsditem.hxx>
+#include <editeng/cscoitem.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/wrlmitem.hxx>
+#include <editeng/numitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/charreliefitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/xmlcnitm.hxx>
+#include <editeng/forbiddencharacterstable.hxx>
+#include <comphelper/processfactory.hxx>
+
+static EditDLL* pDLL=0;
+
+using namespace ::com::sun::star;
+
+EditDLL* EditDLL::Get()
+{
+ if ( !pDLL )
+ pDLL = new EditDLL;
+ return pDLL;
+}
+
+GlobalEditData::GlobalEditData()
+{
+ ppDefItems = NULL;
+ pStdRefDevice = NULL;
+}
+
+GlobalEditData::~GlobalEditData()
+{
+ // DefItems zerstoeren...
+ // Oder einfach stehen lassen, da sowieso App-Ende?!
+ if ( ppDefItems )
+ SfxItemPool::ReleaseDefaults( ppDefItems, EDITITEMCOUNT, TRUE );
+ delete pStdRefDevice;
+}
+
+SfxPoolItem** GlobalEditData::GetDefItems()
+{
+ if ( !ppDefItems )
+ {
+ ppDefItems = new SfxPoolItem*[EDITITEMCOUNT];
+
+ // Absatzattribute:
+ SvxNumRule aTmpNumRule( 0, 0, FALSE );
+
+ ppDefItems[0] = new SvxFrameDirectionItem( FRMDIR_HORI_LEFT_TOP, EE_PARA_WRITINGDIR );
+ ppDefItems[1] = new SvXMLAttrContainerItem( EE_PARA_XMLATTRIBS );
+ ppDefItems[2] = new SfxBoolItem( EE_PARA_HANGINGPUNCTUATION, FALSE );
+ ppDefItems[3] = new SfxBoolItem( EE_PARA_FORBIDDENRULES, TRUE );
+ ppDefItems[4] = new SvxScriptSpaceItem( TRUE, EE_PARA_ASIANCJKSPACING );
+ ppDefItems[5] = new SvxNumBulletItem( aTmpNumRule, EE_PARA_NUMBULLET );
+ ppDefItems[6] = new SfxBoolItem( EE_PARA_HYPHENATE, FALSE );
+ ppDefItems[7] = new SfxBoolItem( EE_PARA_BULLETSTATE, TRUE );
+ ppDefItems[8] = new SvxLRSpaceItem( EE_PARA_OUTLLRSPACE );
+ ppDefItems[9] = new SfxInt16Item( EE_PARA_OUTLLEVEL, -1 );
+ ppDefItems[10] = new SvxBulletItem( EE_PARA_BULLET );
+ ppDefItems[11] = new SvxLRSpaceItem( EE_PARA_LRSPACE );
+ ppDefItems[12] = new SvxULSpaceItem( EE_PARA_ULSPACE );
+ ppDefItems[13] = new SvxLineSpacingItem( 0, EE_PARA_SBL );
+ ppDefItems[14] = new SvxAdjustItem( SVX_ADJUST_LEFT, EE_PARA_JUST );
+ ppDefItems[15] = new SvxTabStopItem( 0, 0, SVX_TAB_ADJUST_LEFT, EE_PARA_TABS );
+
+ // Zeichenattribute:
+ ppDefItems[16] = new SvxColorItem( Color( COL_AUTO ), EE_CHAR_COLOR );
+ ppDefItems[17] = new SvxFontItem( EE_CHAR_FONTINFO );
+ ppDefItems[18] = new SvxFontHeightItem( 240, 100, EE_CHAR_FONTHEIGHT );
+ ppDefItems[19] = new SvxCharScaleWidthItem( 100, EE_CHAR_FONTWIDTH );
+ ppDefItems[20] = new SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT );
+ ppDefItems[21] = new SvxUnderlineItem( UNDERLINE_NONE, EE_CHAR_UNDERLINE );
+ ppDefItems[22] = new SvxCrossedOutItem( STRIKEOUT_NONE, EE_CHAR_STRIKEOUT );
+ ppDefItems[23] = new SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC );
+ ppDefItems[24] = new SvxContourItem( FALSE, EE_CHAR_OUTLINE );
+ ppDefItems[25] = new SvxShadowedItem( FALSE, EE_CHAR_SHADOW );
+ ppDefItems[26] = new SvxEscapementItem( 0, 100, EE_CHAR_ESCAPEMENT );
+ ppDefItems[27] = new SvxAutoKernItem( FALSE, EE_CHAR_PAIRKERNING );
+ ppDefItems[28] = new SvxKerningItem( 0, EE_CHAR_KERNING );
+ ppDefItems[29] = new SvxWordLineModeItem( FALSE, EE_CHAR_WLM );
+ ppDefItems[30] = new SvxLanguageItem( LANGUAGE_DONTKNOW, EE_CHAR_LANGUAGE );
+ ppDefItems[31] = new SvxLanguageItem( LANGUAGE_DONTKNOW, EE_CHAR_LANGUAGE_CJK );
+ ppDefItems[32] = new SvxLanguageItem( LANGUAGE_DONTKNOW, EE_CHAR_LANGUAGE_CTL );
+ ppDefItems[33] = new SvxFontItem( EE_CHAR_FONTINFO_CJK );
+ ppDefItems[34] = new SvxFontItem( EE_CHAR_FONTINFO_CTL );
+ ppDefItems[35] = new SvxFontHeightItem( 240, 100, EE_CHAR_FONTHEIGHT_CJK );
+ ppDefItems[36] = new SvxFontHeightItem( 240, 100, EE_CHAR_FONTHEIGHT_CTL );
+ ppDefItems[37] = new SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT_CJK );
+ ppDefItems[38] = new SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT_CTL );
+ ppDefItems[39] = new SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC_CJK );
+ ppDefItems[40] = new SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC_CTL );
+ ppDefItems[41] = new SvxEmphasisMarkItem( EMPHASISMARK_NONE, EE_CHAR_EMPHASISMARK );
+ ppDefItems[42] = new SvxCharReliefItem( RELIEF_NONE, EE_CHAR_RELIEF );
+ ppDefItems[43] = new SfxVoidItem( EE_CHAR_RUBI_DUMMY );
+#ifndef SVX_LIGHT
+ ppDefItems[44] = new SvXMLAttrContainerItem( EE_CHAR_XMLATTRIBS );
+#else
+ // no need to have alien attributes persistent
+ ppDefItems[44] = new SfxVoidItem( EE_CHAR_XMLATTRIBS );
+#endif // #ifndef SVX_LIGHT
+ ppDefItems[45] = new SvxOverlineItem( UNDERLINE_NONE, EE_CHAR_OVERLINE );
+
+ // Features
+ ppDefItems[46] = new SfxVoidItem( EE_FEATURE_TAB );
+ ppDefItems[47] = new SfxVoidItem( EE_FEATURE_LINEBR );
+ ppDefItems[48] = new SvxCharSetColorItem( Color( COL_RED ), RTL_TEXTENCODING_DONTKNOW, EE_FEATURE_NOTCONV );
+ ppDefItems[49] = new SvxFieldItem( SvxFieldData(), EE_FEATURE_FIELD );
+
+ DBG_ASSERT( EDITITEMCOUNT == 50, "ITEMCOUNT geaendert, DefItems nicht angepasst!" );
+
+ // Init DefFonts:
+ GetDefaultFonts( *(SvxFontItem*)ppDefItems[EE_CHAR_FONTINFO - EE_ITEMS_START],
+ *(SvxFontItem*)ppDefItems[EE_CHAR_FONTINFO_CJK - EE_ITEMS_START],
+ *(SvxFontItem*)ppDefItems[EE_CHAR_FONTINFO_CTL - EE_ITEMS_START] );
+ }
+
+ return ppDefItems;
+}
+
+vos::ORef<SvxForbiddenCharactersTable> GlobalEditData::GetForbiddenCharsTable()
+{
+ if ( !xForbiddenCharsTable.isValid() )
+ {
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory();
+ xForbiddenCharsTable = new SvxForbiddenCharactersTable( xMSF );
+ }
+ return xForbiddenCharsTable;
+}
+
+uno::Reference< linguistic2::XLanguageGuessing > GlobalEditData::GetLanguageGuesser()
+{
+ if (!xLanguageGuesser.is())
+ {
+ uno::Reference< lang::XMultiServiceFactory > xMgr ( comphelper::getProcessServiceFactory() );
+ if (xMgr.is())
+ {
+ xLanguageGuesser = uno::Reference< linguistic2::XLanguageGuessing >(
+ xMgr->createInstance(
+ rtl::OUString::createFromAscii( "com.sun.star.linguistic2.LanguageGuessing" ) ),
+ uno::UNO_QUERY );
+ }
+ }
+ return xLanguageGuesser;
+}
+
+OutputDevice* GlobalEditData::GetStdRefDevice()
+{
+ if ( !pStdRefDevice )
+ {
+ pStdRefDevice = new VirtualDevice;
+ pStdRefDevice->SetMapMode( MAP_TWIP );
+ }
+ return pStdRefDevice;
+}
+
+EditResId::EditResId( USHORT nId ):
+ ResId( nId, *EE_DLL()->GetResMgr() )
+{
+}
+
+EditDLL::EditDLL()
+{
+ pGlobalData = new GlobalEditData;
+ ByteString aResMgrName( "editeng" );
+ pResMgr = ResMgr::CreateResMgr(
+ aResMgrName.GetBuffer(), Application::GetSettings().GetUILocale() );
+}
+
+EditDLL::~EditDLL()
+{
+ delete pResMgr;
+ delete pGlobalData;
+}
diff --git a/editeng/source/editeng/eerdll2.hxx b/editeng/source/editeng/eerdll2.hxx
new file mode 100644
index 000000000000..49bfa058038e
--- /dev/null
+++ b/editeng/source/editeng/eerdll2.hxx
@@ -0,0 +1,61 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#ifndef _EERDLL2_HXX
+#define _EERDLL2_HXX
+
+#include <com/sun/star/linguistic2/XLanguageGuessing.hpp>
+#include <editeng/forbiddencharacterstable.hxx>
+#include <vos/ref.hxx>
+
+class SfxPoolItem;
+
+class GlobalEditData
+{
+private:
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::linguistic2::XLanguageGuessing > xLanguageGuesser;
+ SfxPoolItem** ppDefItems;
+ OutputDevice* pStdRefDevice;
+
+ vos::ORef<SvxForbiddenCharactersTable> xForbiddenCharsTable;
+
+public:
+ GlobalEditData();
+ ~GlobalEditData();
+
+ SfxPoolItem** GetDefItems();
+ OutputDevice* GetStdRefDevice();
+
+ vos::ORef<SvxForbiddenCharactersTable> GetForbiddenCharsTable();
+ void SetForbiddenCharsTable( vos::ORef<SvxForbiddenCharactersTable> xForbiddenChars ) { xForbiddenCharsTable = xForbiddenChars; }
+ ::com::sun::star::uno::Reference< ::com::sun::star::linguistic2::XLanguageGuessing > GetLanguageGuesser();
+};
+
+
+#endif //_EERDLL2_HXX
+
diff --git a/editeng/source/editeng/eertfpar.cxx b/editeng/source/editeng/eertfpar.cxx
new file mode 100644
index 000000000000..9f919afb39d6
--- /dev/null
+++ b/editeng/source/editeng/eertfpar.cxx
@@ -0,0 +1,632 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 <eertfpar.hxx>
+#include <impedit.hxx>
+#include <svl/intitem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/flditem.hxx>
+
+#include <svtools/rtftoken.h>
+
+// alle Werte auf default; wird nach einlesen der Bitmap aufgerufen !
+void SvxRTFPictureType::ResetValues()
+{ // setze alle Werte RTF-Defaults
+ eStyle = RTF_BITMAP;
+ nMode = HEX_MODE;
+ nType = nGoalWidth = nGoalHeight = 0;
+ nWidth = nHeight = nWidthBytes = 0;
+ uPicLen = 0;
+ nBitsPerPixel = nPlanes = 1;
+ nScalX = nScalY = 100; // Skalierung in Prozent
+ nCropT = nCropB = nCropL = nCropR = 0;
+}
+
+ImportInfo::ImportInfo( ImportState eSt, SvParser* pPrsrs, const ESelection& rSel )
+ : aSelection( rSel )
+{
+ pParser = pPrsrs,
+ eState = eSt;
+
+ nToken = 0;
+ nTokenValue = 0;
+ pAttrs = NULL;
+}
+
+ImportInfo::~ImportInfo()
+{
+}
+
+EditRTFParser::EditRTFParser( SvStream& rIn, EditSelection aSel, SfxItemPool& rAttrPool, ImpEditEngine* pImpEE )
+ : SvxRTFParser( rAttrPool, rIn, 0 ), aRTFMapMode( MAP_TWIP )
+{
+
+ pImpEditEngine = pImpEE;
+ aCurSel = aSel;
+ eDestCharSet = RTL_TEXTENCODING_DONTKNOW;
+ nDefFont = 0;
+ nDefTab = 0;
+ nLastAction = 0;
+ nDefFontHeight = 0;
+
+ SetInsPos( EditPosition( pImpEditEngine, &aCurSel ) );
+
+ // Umwandeln der Twips-Werte...
+ SetCalcValue( TRUE );
+ SetChkStyleAttr( pImpEE->GetStatus().DoImportRTFStyleSheets() );
+ SetNewDoc( FALSE ); // damit die Pool-Defaults nicht
+ // ueberschrieben werden...
+ aEditMapMode = MapMode( pImpEE->GetRefDevice()->GetMapMode().GetMapUnit() );
+}
+
+EditRTFParser::~EditRTFParser()
+{
+}
+
+SvParserState __EXPORT EditRTFParser::CallParser()
+{
+ DBG_ASSERT( !aCurSel.HasRange(), "Selection bei CallParser!" );
+ // Den Teil, in den importiert wird, vom Rest abtrennen.
+ // Diese Mimik sollte fuer alle Imports verwendet werden.
+ // aStart1PaM: Letzte Position vor dem importierten Inhalt
+ // aEnd1PaM: Erste Position nach dem importierten Inhalt
+ // aStart2PaM: Erste Position des importierten Inhaltes
+ // aEnd2PaM: Letzte Position des importierten Inhaltes
+ EditPaM aStart1PaM( aCurSel.Min().GetNode(), aCurSel.Min().GetIndex() );
+ aCurSel = pImpEditEngine->ImpInsertParaBreak( aCurSel );
+ EditPaM aStart2PaM = aCurSel.Min();
+ // Sinnvoll oder nicht?:
+ aStart2PaM.GetNode()->GetContentAttribs().GetItems().ClearItem();
+ AddRTFDefaultValues( aStart2PaM, aStart2PaM );
+ EditPaM aEnd1PaM( pImpEditEngine->ImpInsertParaBreak( aCurSel.Max() ) );
+ // aCurCel zeigt jetzt auf den Zwischenraum
+
+ if ( pImpEditEngine->aImportHdl.IsSet() )
+ {
+ ImportInfo aImportInfo( RTFIMP_START, this, pImpEditEngine->CreateESel( aCurSel ) );
+ pImpEditEngine->aImportHdl.Call( &aImportInfo );
+ }
+
+ SvParserState _eState = SvxRTFParser::CallParser();
+
+ if ( pImpEditEngine->aImportHdl.IsSet() )
+ {
+ ImportInfo aImportInfo( RTFIMP_END, this, pImpEditEngine->CreateESel( aCurSel ) );
+ pImpEditEngine->aImportHdl.Call( &aImportInfo );
+ }
+
+ if ( nLastAction == ACTION_INSERTPARABRK )
+ {
+ ContentNode* pCurNode = aCurSel.Max().GetNode();
+ USHORT nPara = pImpEditEngine->GetEditDoc().GetPos( pCurNode );
+ ContentNode* pPrevNode = pImpEditEngine->GetEditDoc().SaveGetObject( nPara-1 );
+ DBG_ASSERT( pPrevNode, "Ungueltiges RTF-Dokument ?!" );
+ EditSelection aSel;
+ aSel.Min() = EditPaM( pPrevNode, pPrevNode->Len() );
+ aSel.Max() = EditPaM( pCurNode, 0 );
+ aCurSel.Max() = pImpEditEngine->ImpDeleteSelection( aSel );
+ }
+ EditPaM aEnd2PaM( aCurSel.Max() );
+ //AddRTFDefaultValues( aStart2PaM, aEnd2PaM );
+ BOOL bOnlyOnePara = ( aEnd2PaM.GetNode() == aStart2PaM.GetNode() );
+ // Den Brocken wieder einfuegen...
+ // Problem: Absatzattribute duerfen ggf. nicht uebernommen werden
+ // => Zeichenattribute machen.
+
+ BOOL bSpecialBackward = aStart1PaM.GetNode()->Len() ? FALSE : TRUE;
+ if ( bOnlyOnePara || aStart1PaM.GetNode()->Len() )
+ pImpEditEngine->ParaAttribsToCharAttribs( aStart2PaM.GetNode() );
+ aCurSel.Min() = pImpEditEngine->ImpConnectParagraphs(
+ aStart1PaM.GetNode(), aStart2PaM.GetNode(), bSpecialBackward );
+ bSpecialBackward = aEnd1PaM.GetNode()->Len() ? TRUE : FALSE;
+ // wenn bOnlyOnePara, dann ist der Node beim Connect verschwunden.
+ if ( !bOnlyOnePara && aEnd1PaM.GetNode()->Len() )
+ pImpEditEngine->ParaAttribsToCharAttribs( aEnd2PaM.GetNode() );
+ aCurSel.Max() = pImpEditEngine->ImpConnectParagraphs(
+ ( bOnlyOnePara ? aStart1PaM.GetNode() : aEnd2PaM.GetNode() ),
+ aEnd1PaM.GetNode(), bSpecialBackward );
+
+ return _eState;
+}
+
+void EditRTFParser::AddRTFDefaultValues( const EditPaM& rStart, const EditPaM& rEnd )
+{
+ // Problem: DefFont und DefFontHeight
+ Size aSz( 12, 0 );
+ MapMode aPntMode( MAP_POINT );
+ MapMode _aEditMapMode( pImpEditEngine->GetRefDevice()->GetMapMode().GetMapUnit() );
+ aSz = pImpEditEngine->GetRefDevice()->LogicToLogic( aSz, &aPntMode, &_aEditMapMode );
+ SvxFontHeightItem aFontHeightItem( aSz.Width(), 100, EE_CHAR_FONTHEIGHT );
+ Font aDefFont( GetDefFont() );
+ SvxFontItem aFontItem( aDefFont.GetFamily(), aDefFont.GetName(),
+ aDefFont.GetStyleName(), aDefFont.GetPitch(), aDefFont.GetCharSet(), EE_CHAR_FONTINFO );
+
+ USHORT nStartPara = pImpEditEngine->GetEditDoc().GetPos( rStart.GetNode() );
+ USHORT nEndPara = pImpEditEngine->GetEditDoc().GetPos( rEnd.GetNode() );
+ for ( USHORT nPara = nStartPara; nPara <= nEndPara; nPara++ )
+ {
+ ContentNode* pNode = pImpEditEngine->GetEditDoc().SaveGetObject( nPara );
+ DBG_ASSERT( pNode, "AddRTFDefaultValues - Kein Absatz ?!" );
+ if ( !pNode->GetContentAttribs().HasItem( EE_CHAR_FONTINFO ) )
+ pNode->GetContentAttribs().GetItems().Put( aFontItem );
+ if ( !pNode->GetContentAttribs().HasItem( EE_CHAR_FONTHEIGHT ) )
+ pNode->GetContentAttribs().GetItems().Put( aFontHeightItem );
+ }
+}
+
+void __EXPORT EditRTFParser::NextToken( int nToken )
+{
+ switch( nToken )
+ {
+ case RTF_DEFF:
+ {
+ nDefFont = USHORT(nTokenValue);
+ }
+ break;
+ case RTF_DEFTAB:
+ {
+ nDefTab = USHORT(nTokenValue);
+ }
+ break;
+ case RTF_CELL:
+ {
+ aCurSel = pImpEditEngine->ImpInsertParaBreak( aCurSel );
+ }
+ break;
+ case RTF_LINE:
+ {
+ aCurSel = pImpEditEngine->InsertLineBreak( aCurSel );
+ }
+ break;
+ case RTF_FIELD:
+ {
+ ReadField();
+ }
+ break;
+ case RTF_PGDSCTBL: // #i29453# ignore \*\pgdsctbl destination
+ case RTF_LISTTEXT:
+ {
+ SkipGroup();
+ }
+ break;
+ default:
+ {
+ SvxRTFParser::NextToken( nToken );
+ if ( nToken == RTF_STYLESHEET )
+ CreateStyleSheets();
+ }
+ break;
+ }
+ if ( pImpEditEngine->aImportHdl.IsSet() )
+ {
+ ImportInfo aImportInfo( RTFIMP_NEXTTOKEN, this, pImpEditEngine->CreateESel( aCurSel ) );
+ aImportInfo.nToken = nToken;
+ aImportInfo.nTokenValue = short(nTokenValue);
+ pImpEditEngine->aImportHdl.Call( &aImportInfo );
+ }
+}
+
+void __EXPORT EditRTFParser::UnknownAttrToken( int nToken, SfxItemSet* )
+{
+ // fuer Tokens, die im ReadAttr nicht ausgewertet werden
+ // Eigentlich nur fuer Calc (RTFTokenHdl), damit RTF_INTBL
+ if ( pImpEditEngine->aImportHdl.IsSet() )
+ {
+ ImportInfo aImportInfo( RTFIMP_UNKNOWNATTR, this, pImpEditEngine->CreateESel( aCurSel ) );
+ aImportInfo.nToken = nToken;
+ aImportInfo.nTokenValue = short(nTokenValue);
+ pImpEditEngine->aImportHdl.Call( &aImportInfo );
+ }
+}
+
+void __EXPORT EditRTFParser::InsertText()
+{
+ String aText( aToken );
+ if ( pImpEditEngine->aImportHdl.IsSet() )
+ {
+ ImportInfo aImportInfo( RTFIMP_INSERTTEXT, this, pImpEditEngine->CreateESel( aCurSel ) );
+ aImportInfo.aText = aText;
+ pImpEditEngine->aImportHdl.Call( &aImportInfo );
+ }
+ aCurSel = pImpEditEngine->ImpInsertText( aCurSel, aText );
+ nLastAction = ACTION_INSERTTEXT;
+}
+
+void __EXPORT EditRTFParser::InsertPara()
+{
+ if ( pImpEditEngine->aImportHdl.IsSet() )
+ {
+ ImportInfo aImportInfo( RTFIMP_INSERTPARA, this, pImpEditEngine->CreateESel( aCurSel ) );
+ pImpEditEngine->aImportHdl.Call( &aImportInfo );
+ }
+ aCurSel = pImpEditEngine->ImpInsertParaBreak( aCurSel );
+ nLastAction = ACTION_INSERTPARABRK;
+}
+
+void __EXPORT EditRTFParser::MovePos( int bForward )
+{
+ if( bForward )
+ aCurSel = pImpEditEngine->CursorRight( aCurSel.Max(), ::com::sun::star::i18n::CharacterIteratorMode::SKIPCHARACTER );
+ else
+ aCurSel = pImpEditEngine->CursorLeft( aCurSel.Max(), ::com::sun::star::i18n::CharacterIteratorMode::SKIPCHARACTER );
+}
+
+void __EXPORT EditRTFParser::SetEndPrevPara( SvxNodeIdx*& rpNodePos,
+ USHORT& rCntPos )
+{
+ // Gewollt ist: von der aktuellen Einfuegeposition den vorherigen
+ // Absatz bestimmen und von dem das Ende setzen.
+ // Dadurch wird "\pard" immer auf den richtigen Absatz
+ // angewendet.
+
+ ContentNode* pN = aCurSel.Max().GetNode();
+ USHORT nCurPara = pImpEditEngine->GetEditDoc().GetPos( pN );
+ DBG_ASSERT( nCurPara != 0, "Absatz gleich 0: SetEnfPrevPara" );
+ if ( nCurPara )
+ nCurPara--;
+ ContentNode* pPrevNode = pImpEditEngine->GetEditDoc().SaveGetObject( nCurPara );
+ DBG_ASSERT( pPrevNode, "pPrevNode = 0!" );
+ rpNodePos = new EditNodeIdx( pImpEditEngine, pPrevNode );
+ rCntPos = pPrevNode->Len();
+}
+
+int __EXPORT EditRTFParser::IsEndPara( SvxNodeIdx* pNd, USHORT nCnt ) const
+{
+ return ( nCnt == ( ((EditNodeIdx*)pNd)->GetNode()->Len()) );
+}
+
+void __EXPORT EditRTFParser::SetAttrInDoc( SvxRTFItemStackType &rSet )
+{
+ ContentNode* pSttNode = ((EditNodeIdx&)rSet.GetSttNode()).GetNode();
+ ContentNode* pEndNode = ((EditNodeIdx&)rSet.GetEndNode()).GetNode();
+
+ EditPaM aStartPaM( pSttNode, rSet.GetSttCnt() );
+ EditPaM aEndPaM( pEndNode, rSet.GetEndCnt() );
+
+ // ggf. noch das Escapemant-Item umbiegen:
+ const SfxPoolItem* pItem;
+
+ // #i66167# adapt font heights to destination MapUnit if necessary
+ const MapUnit eDestUnit = ( MapUnit )( pImpEditEngine->GetEditDoc().GetItemPool().GetMetric(0) );
+ const MapUnit eSrcUnit = aRTFMapMode.GetMapUnit();
+ if (eDestUnit != eSrcUnit)
+ {
+ USHORT aFntHeightIems[3] = { EE_CHAR_FONTHEIGHT, EE_CHAR_FONTHEIGHT_CJK, EE_CHAR_FONTHEIGHT_CTL };
+ for (int i = 0; i < 2; ++i)
+ {
+ if (SFX_ITEM_SET == rSet.GetAttrSet().GetItemState( aFntHeightIems[i], FALSE, &pItem ))
+ {
+ UINT32 nHeight = ((SvxFontHeightItem*)pItem)->GetHeight();
+ long nNewHeight;
+ nNewHeight = pImpEditEngine->GetRefDevice()->LogicToLogic( (long)nHeight, eSrcUnit, eDestUnit );
+
+ SvxFontHeightItem aFntHeightItem( nNewHeight, ((SvxFontHeightItem*)pItem)->GetProp(), aFntHeightIems[i] );
+ rSet.GetAttrSet().Put( aFntHeightItem );
+ }
+ }
+ }
+
+ if( SFX_ITEM_SET == rSet.GetAttrSet().GetItemState( EE_CHAR_ESCAPEMENT, FALSE, &pItem ))
+ {
+ // die richtige
+ long nEsc = ((SvxEscapementItem*)pItem)->GetEsc();
+
+ if( ( DFLT_ESC_AUTO_SUPER != nEsc ) && ( DFLT_ESC_AUTO_SUB != nEsc ) )
+ {
+ nEsc *= 10; //HalPoints => Twips wurde in RTFITEM.CXX unterschlagen!
+ SvxFont aFont;
+ pImpEditEngine->SeekCursor( aStartPaM.GetNode(), aStartPaM.GetIndex()+1, aFont );
+ nEsc = nEsc * 100 / aFont.GetSize().Height();
+
+ SvxEscapementItem aEscItem( (short) nEsc, ((SvxEscapementItem*)pItem)->GetProp(), EE_CHAR_ESCAPEMENT );
+ rSet.GetAttrSet().Put( aEscItem );
+ }
+ }
+
+ if ( pImpEditEngine->aImportHdl.IsSet() )
+ {
+ EditSelection aSel( aStartPaM, aEndPaM );
+ ImportInfo aImportInfo( RTFIMP_SETATTR, this, pImpEditEngine->CreateESel( aSel ) );
+ aImportInfo.pAttrs = &rSet;
+ pImpEditEngine->aImportHdl.Call( &aImportInfo );
+ }
+
+ ContentNode* pSN = aStartPaM.GetNode();
+ ContentNode* pEN = aEndPaM.GetNode();
+ USHORT nStartNode = pImpEditEngine->GetEditDoc().GetPos( pSN );
+ USHORT nEndNode = pImpEditEngine->GetEditDoc().GetPos( pEN );
+ sal_Int16 nOutlLevel = 0xff;
+
+ if ( rSet.StyleNo() && pImpEditEngine->GetStyleSheetPool() && pImpEditEngine->GetStatus().DoImportRTFStyleSheets() )
+ {
+ SvxRTFStyleType* pS = GetStyleTbl().Get( rSet.StyleNo() );
+ DBG_ASSERT( pS, "Vorlage in RTF nicht definiert!" );
+ if ( pS )
+ {
+ pImpEditEngine->SetStyleSheet( EditSelection( aStartPaM, aEndPaM ), (SfxStyleSheet*)pImpEditEngine->GetStyleSheetPool()->Find( pS->sName, SFX_STYLE_FAMILY_ALL ) );
+ nOutlLevel = pS->nOutlineNo;
+ }
+ }
+
+ // Wenn ein Attribut von 0 bis aktuelle Absatzlaenge geht,
+ // soll es ein Absatz-Attribut sein!
+
+ // Achtung: Selektion kann ueber mehrere Absaetze gehen.
+ // Alle vollstaendigen Absaetze sind Absatzattribute...
+ for ( USHORT z = nStartNode+1; z < nEndNode; z++ )
+ {
+ DBG_ASSERT( pImpEditEngine->GetEditDoc().SaveGetObject( z ), "Node existiert noch nicht(RTF)" );
+ pImpEditEngine->SetParaAttribs( z, rSet.GetAttrSet() );
+ }
+
+ if ( aStartPaM.GetNode() != aEndPaM.GetNode() )
+ {
+ // Den Rest des StartNodes...
+ if ( aStartPaM.GetIndex() == 0 )
+ pImpEditEngine->SetParaAttribs( nStartNode, rSet.GetAttrSet() );
+ else
+ pImpEditEngine->SetAttribs( EditSelection( aStartPaM, EditPaM( aStartPaM.GetNode(), aStartPaM.GetNode()->Len() ) ), rSet.GetAttrSet() );
+
+ // Den Anfang des EndNodes....
+ if ( aEndPaM.GetIndex() == aEndPaM.GetNode()->Len() )
+ pImpEditEngine->SetParaAttribs( nEndNode, rSet.GetAttrSet() );
+ else
+ pImpEditEngine->SetAttribs( EditSelection( EditPaM( aEndPaM.GetNode(), 0 ), aEndPaM ), rSet.GetAttrSet() );
+ }
+ else
+ {
+ if ( ( aStartPaM.GetIndex() == 0 ) && ( aEndPaM.GetIndex() == aEndPaM.GetNode()->Len() ) )
+ {
+ // #96298# When settings char attribs as para attribs, we must merge with existing attribs, not overwrite the ItemSet!
+ SfxItemSet aAttrs = pImpEditEngine->GetParaAttribs( nStartNode );
+ aAttrs.Put( rSet.GetAttrSet() );
+ pImpEditEngine->SetParaAttribs( nStartNode, aAttrs );
+ }
+ else
+ {
+ pImpEditEngine->SetAttribs( EditSelection( aStartPaM, aEndPaM ), rSet.GetAttrSet() );
+ }
+ }
+
+ // OutlLevel...
+ if ( nOutlLevel != 0xff )
+ {
+ for ( USHORT n = nStartNode; n <= nEndNode; n++ )
+ {
+ ContentNode* pNode = pImpEditEngine->GetEditDoc().SaveGetObject( n );
+ pNode->GetContentAttribs().GetItems().Put( SfxInt16Item( EE_PARA_OUTLLEVEL, nOutlLevel ) );
+ }
+ }
+}
+
+SvxRTFStyleType* EditRTFParser::FindStyleSheet( const XubString& rName )
+{
+ SvxRTFStyleType* pS = GetStyleTbl().First();
+ while ( pS && ( pS->sName != rName ) )
+ pS = GetStyleTbl().Next();
+
+ return pS;
+}
+
+SfxStyleSheet* EditRTFParser::CreateStyleSheet( SvxRTFStyleType* pRTFStyle )
+{
+ // Prueffen, ob so eine Vorlage existiert....
+ // dann wird sie auch nicht geaendert!
+ SfxStyleSheet* pStyle = (SfxStyleSheet*)pImpEditEngine->GetStyleSheetPool()->Find( pRTFStyle->sName, SFX_STYLE_FAMILY_ALL );
+ if ( pStyle )
+ return pStyle;
+
+ String aName( pRTFStyle->sName );
+ String aParent;
+ if ( pRTFStyle->nBasedOn )
+ {
+ SvxRTFStyleType* pS = GetStyleTbl().Get( pRTFStyle->nBasedOn );
+ if ( pS && ( pS !=pRTFStyle ) )
+ aParent = pS->sName;
+ }
+
+ pStyle = (SfxStyleSheet*) &pImpEditEngine->GetStyleSheetPool()->Make( aName, SFX_STYLE_FAMILY_PARA );
+
+ // 1) Items konvertieren und uebernehmen...
+ ConvertAndPutItems( pStyle->GetItemSet(), pRTFStyle->aAttrSet );
+
+ // 2) Solange Parent nicht im Pool, auch diesen kreieren...
+ if ( aParent.Len() && ( aParent != aName ) )
+ {
+ SfxStyleSheet* pS = (SfxStyleSheet*)pImpEditEngine->GetStyleSheetPool()->Find( aParent, SFX_STYLE_FAMILY_ALL );
+ if ( !pS )
+ {
+ // Wenn nirgendwo gefunden, aus RTF erzeugen...
+ SvxRTFStyleType* _pRTFStyle = FindStyleSheet( aParent );
+ if ( _pRTFStyle )
+ pS = CreateStyleSheet( _pRTFStyle );
+ }
+ // 2b) ItemSet mit Parent verknuepfen...
+ if ( pS )
+ pStyle->GetItemSet().SetParent( &pS->GetItemSet() );
+ }
+ return pStyle;
+}
+
+void EditRTFParser::CreateStyleSheets()
+{
+ // der SvxRTFParser hat jetzt die Vorlagen erzeugt...
+ if ( pImpEditEngine->GetStyleSheetPool() && pImpEditEngine->GetStatus().DoImportRTFStyleSheets() )
+ {
+ SvxRTFStyleType* pRTFStyle = GetStyleTbl().First();
+ while ( pRTFStyle )
+ {
+ CreateStyleSheet( pRTFStyle );
+
+ pRTFStyle = GetStyleTbl().Next();
+ }
+ }
+}
+
+void __EXPORT EditRTFParser::CalcValue()
+{
+ const MapUnit eDestUnit = static_cast< MapUnit >( aEditMapMode.GetMapUnit() );
+ const MapUnit eSrcUnit = aRTFMapMode.GetMapUnit();
+ if (eDestUnit != eSrcUnit)
+ nTokenValue = OutputDevice::LogicToLogic( (long)nTokenValue, eSrcUnit, eDestUnit );
+}
+
+void EditRTFParser::ReadField()
+{
+ // Aus SwRTFParser::ReadField()
+ int _nOpenBrakets = 1; // die erste wurde schon vorher erkannt
+ BOOL bFldInst = FALSE;
+ BOOL bFldRslt = FALSE;
+ String aFldInst;
+ String aFldRslt;
+
+ while( _nOpenBrakets && IsParserWorking() )
+ {
+ switch( GetNextToken() )
+ {
+ case '}':
+ {
+ _nOpenBrakets--;
+ if ( _nOpenBrakets == 1 )
+ {
+ bFldInst = FALSE;
+ bFldRslt = FALSE;
+ }
+ }
+ break;
+
+ case '{': _nOpenBrakets++;
+ break;
+
+ case RTF_FIELD: SkipGroup();
+ break;
+
+ case RTF_FLDINST: bFldInst = TRUE;
+ break;
+
+ case RTF_FLDRSLT: bFldRslt = TRUE;
+ break;
+
+ case RTF_TEXTTOKEN:
+ {
+ if ( bFldInst )
+ aFldInst += aToken;
+ else if ( bFldRslt )
+ aFldRslt += aToken;
+ }
+ break;
+ }
+ }
+ if ( aFldInst.Len() )
+ {
+ String aHyperLinkMarker( RTL_CONSTASCII_USTRINGPARAM( "HYPERLINK " ) );
+ if ( aFldInst.CompareIgnoreCaseToAscii( aHyperLinkMarker, aHyperLinkMarker.Len() ) == COMPARE_EQUAL )
+ {
+ aFldInst.Erase( 0, aHyperLinkMarker.Len() );
+ aFldInst.EraseLeadingChars();
+ aFldInst.EraseTrailingChars();
+ aFldInst.Erase( 0, 1 ); // "
+ aFldInst.Erase( aFldInst.Len()-1, 1 ); // "
+
+ if ( !aFldRslt.Len() )
+ aFldRslt = aFldInst;
+
+ SvxFieldItem aField( SvxURLField( aFldInst, aFldRslt, SVXURLFORMAT_REPR ), EE_FEATURE_FIELD );
+ aCurSel = pImpEditEngine->InsertField( aCurSel, aField );
+ pImpEditEngine->UpdateFields();
+ nLastAction = ACTION_INSERTTEXT;
+ }
+ }
+
+ SkipToken( -1 ); // die schliesende Klammer wird "oben" ausgewertet
+}
+
+void EditRTFParser::SkipGroup()
+{
+ int _nOpenBrakets = 1; // die erste wurde schon vorher erkannt
+
+ while( _nOpenBrakets && IsParserWorking() )
+ {
+ switch( GetNextToken() )
+ {
+ case '}':
+ {
+ _nOpenBrakets--;
+ }
+ break;
+
+ case '{':
+ {
+ _nOpenBrakets++;
+ }
+ break;
+ }
+ }
+
+ SkipToken( -1 ); // die schliesende Klammer wird "oben" ausgewertet
+}
+
+ULONG __EXPORT EditNodeIdx::GetIdx() const
+{
+ return pImpEditEngine->GetEditDoc().GetPos( pNode );
+}
+
+SvxNodeIdx* __EXPORT EditNodeIdx::Clone() const
+{
+ return new EditNodeIdx( pImpEditEngine, pNode );
+}
+
+SvxPosition* __EXPORT EditPosition::Clone() const
+{
+ return new EditPosition( pImpEditEngine, pCurSel );
+}
+
+SvxNodeIdx* __EXPORT EditPosition::MakeNodeIdx() const
+{
+ return new EditNodeIdx( pImpEditEngine, pCurSel->Max().GetNode() );
+}
+
+ULONG __EXPORT EditPosition::GetNodeIdx() const
+{
+ ContentNode* pN = pCurSel->Max().GetNode();
+ return pImpEditEngine->GetEditDoc().GetPos( pN );
+}
+
+USHORT __EXPORT EditPosition::GetCntIdx() const
+{
+ return pCurSel->Max().GetIndex();
+}
diff --git a/editeng/source/editeng/eertfpar.hxx b/editeng/source/editeng/eertfpar.hxx
new file mode 100644
index 000000000000..42c75b811f33
--- /dev/null
+++ b/editeng/source/editeng/eertfpar.hxx
@@ -0,0 +1,128 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+#ifndef _EERTFPAR_HXX
+#define _EERTFPAR_HXX
+
+#include <editeng/svxrtf.hxx>
+
+#include <editdoc.hxx>
+#include <impedit.hxx>
+
+#ifndef SVX_LIGHT
+
+class EditNodeIdx : public SvxNodeIdx
+{
+private:
+ ContentNode* pNode;
+ ImpEditEngine* pImpEditEngine;
+
+public:
+ EditNodeIdx( ImpEditEngine* pIEE, ContentNode* pNd = 0)
+ { pImpEditEngine = pIEE; pNode = pNd; }
+ virtual ULONG GetIdx() const;
+ virtual SvxNodeIdx* Clone() const;
+ ContentNode* GetNode() { return pNode; }
+};
+
+class EditPosition : public SvxPosition
+{
+private:
+ EditSelection* pCurSel;
+ ImpEditEngine* pImpEditEngine;
+
+public:
+ EditPosition( ImpEditEngine* pIEE, EditSelection* pSel )
+ { pImpEditEngine = pIEE; pCurSel = pSel; }
+
+ virtual ULONG GetNodeIdx() const;
+ virtual USHORT GetCntIdx() const;
+
+ // erzeuge von sich selbst eine Kopie
+ virtual SvxPosition* Clone() const;
+
+ // erzeuge vom NodeIndex eine Kopie
+ virtual SvxNodeIdx* MakeNodeIdx() const;
+};
+
+#define ACTION_INSERTTEXT 1
+#define ACTION_INSERTPARABRK 2
+
+class EditRTFParser : public SvxRTFParser
+{
+private:
+ EditSelection aCurSel;
+ ImpEditEngine* pImpEditEngine;
+ CharSet eDestCharSet;
+ MapMode aRTFMapMode;
+ MapMode aEditMapMode;
+
+ USHORT nDefFont;
+ USHORT nDefTab;
+ USHORT nDefFontHeight;
+ BYTE nLastAction;
+
+protected:
+ virtual void InsertPara();
+ virtual void InsertText();
+ virtual void MovePos( int bForward = TRUE );
+ virtual void SetEndPrevPara( SvxNodeIdx*& rpNodePos,
+ USHORT& rCntPos );
+
+ virtual void UnknownAttrToken( int nToken, SfxItemSet* pSet );
+ virtual void NextToken( int nToken );
+ virtual void SetAttrInDoc( SvxRTFItemStackType &rSet );
+ virtual int IsEndPara( SvxNodeIdx* pNd, USHORT nCnt ) const;
+ virtual void CalcValue();
+ void CreateStyleSheets();
+ SfxStyleSheet* CreateStyleSheet( SvxRTFStyleType* pRTFStyle );
+ SvxRTFStyleType* FindStyleSheet( const String& rName );
+ void AddRTFDefaultValues( const EditPaM& rStart, const EditPaM& rEnd );
+ void ReadField();
+ void SkipGroup();
+
+public:
+ EditRTFParser( SvStream& rIn, EditSelection aCurSel, SfxItemPool& rAttrPool, ImpEditEngine* pImpEditEngine );
+ ~EditRTFParser();
+
+ virtual SvParserState CallParser();
+
+
+ void SetDestCharSet( CharSet eCharSet ) { eDestCharSet = eCharSet; }
+ CharSet GetDestCharSet() const { return eDestCharSet; }
+
+ USHORT GetDefTab() const { return nDefTab; }
+ Font GetDefFont() { return GetFont( nDefFont ); }
+
+ EditPaM GetCurPaM() const { return aCurSel.Max(); }
+};
+
+SV_DECL_REF( EditRTFParser )
+SV_IMPL_REF( EditRTFParser );
+
+
+#endif // !SVX_LIGH
+#endif //_EERTFPAR_HXX
diff --git a/editeng/source/editeng/impedit.cxx b/editeng/source/editeng/impedit.cxx
new file mode 100644
index 000000000000..b327d2a685bd
--- /dev/null
+++ b/editeng/source/editeng/impedit.cxx
@@ -0,0 +1,2002 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 <eeng_pch.hxx>
+
+#include <impedit.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/editview.hxx>
+#include <tools/poly.hxx>
+#include <editeng/unolingu.hxx>
+#include <com/sun/star/linguistic2/XDictionaryEntry.hpp>
+#include <com/sun/star/linguistic2/DictionaryType.hpp>
+#include <com/sun/star/linguistic2/DictionaryEvent.hpp>
+#include <com/sun/star/linguistic2/XDictionaryEventListener.hpp>
+#include <com/sun/star/linguistic2/DictionaryEventFlags.hpp>
+#include <com/sun/star/linguistic2/XDictionary.hpp>
+#include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
+#include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp>
+#include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
+#include <vos/mutex.hxx>
+#include <editeng/flditem.hxx>
+#include <svl/intitem.hxx>
+#include <svtools/transfer.hxx>
+#include <sot/exchange.hxx>
+#include <sot/formats.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::linguistic2;
+
+#define SCRLRANGE 20 // 1/20 der Breite/Hoehe scrollen, wenn im QueryDrop
+
+inline void lcl_AllignToPixel( Point& rPoint, OutputDevice* pOutDev, short nDiffX, short nDiffY )
+{
+ rPoint = pOutDev->LogicToPixel( rPoint );
+
+ if ( nDiffX )
+ rPoint.X() += nDiffX;
+ if ( nDiffY )
+ rPoint.Y() += nDiffY;
+
+ rPoint = pOutDev->PixelToLogic( rPoint );
+}
+
+ // ----------------------------------------------------------------------
+// class ImpEditView
+// ----------------------------------------------------------------------
+ImpEditView::ImpEditView( EditView* pView, EditEngine* pEng, Window* pWindow ) :
+ aOutArea( Point(), pEng->GetPaperSize() )
+{
+ pEditView = pView;
+ pEditEngine = pEng;
+ pOutWin = pWindow;
+ pPointer = NULL;
+ pBackgroundColor = NULL;
+ nScrollDiffX = 0;
+ nExtraCursorFlags = 0;
+ nCursorBidiLevel = CURSOR_BIDILEVEL_DONTKNOW;
+ pCursor = NULL;
+ pDragAndDropInfo = NULL;
+ bReadOnly = sal_False;
+ bClickedInSelection = sal_False;
+ eSelectionMode = EE_SELMODE_TXTONLY;
+ eAnchorMode = ANCHOR_TOP_LEFT;
+ nInvMore = 1;
+ nTravelXPos = TRAVEL_X_DONTKNOW;
+ nControl = EV_CNTRL_AUTOSCROLL | EV_CNTRL_ENABLEPASTE;
+ bActiveDragAndDropListener = FALSE;
+
+ aEditSelection.Min() = pEng->pImpEditEngine->GetEditDoc().GetStartPaM();
+ aEditSelection.Max() = pEng->pImpEditEngine->GetEditDoc().GetEndPaM();
+}
+
+ImpEditView::~ImpEditView()
+{
+ RemoveDragAndDropListeners();
+
+ if ( pOutWin && ( pOutWin->GetCursor() == pCursor ) )
+ pOutWin->SetCursor( NULL );
+
+ delete pCursor;
+ delete pBackgroundColor;
+ delete pPointer;
+ delete pDragAndDropInfo;
+}
+
+void ImpEditView::SetBackgroundColor( const Color& rColor )
+{
+ delete pBackgroundColor;
+ pBackgroundColor = new Color( rColor );
+}
+
+void ImpEditView::SetEditSelection( const EditSelection& rEditSelection )
+{
+ // #100856# set state before notification
+ aEditSelection = rEditSelection;
+
+ if ( pEditEngine->pImpEditEngine->GetNotifyHdl().IsSet() )
+ {
+ EENotify aNotify( EE_NOTIFY_TEXTVIEWSELECTIONCHANGED );
+ aNotify.pEditEngine = pEditEngine;
+ aNotify.pEditView = GetEditViewPtr();
+ pEditEngine->pImpEditEngine->CallNotify( aNotify );
+ }
+}
+
+
+void ImpEditView::DrawSelection( EditSelection aTmpSel, Region* pRegion )
+{
+ if ( GetSelectionMode() == EE_SELMODE_HIDDEN )
+ return;
+
+ // Vor dem Zeichnen der Selektion muss sichergestellt werden,
+ // das der Fensterinhalt komplett gueltig ist!
+ // Muss hier stehen, damit auf jeden Fall weg wenn lerr, nicht spaeter
+ // zwei Paint-Events!
+ // 19.10: Muss sogar vor Abfrage von bUpdate, falls nach Invalidate
+ // noch Paints in der Queue, aber jemand schaltet den UpdateMode um!
+
+ // pRegion: Wenn nicht NULL, dann nur Region berechnen.
+ PolyPolygon* pPolyPoly = NULL;
+ if ( pRegion )
+ pPolyPoly = new PolyPolygon;
+
+ sal_Bool bClipRegion = pOutWin->IsClipRegion();
+ Region aOldRegion = pOutWin->GetClipRegion();
+
+ if ( !pRegion )
+ {
+ if ( pEditEngine->pImpEditEngine->GetUpdateMode() == sal_False )
+ return;
+ if ( pEditEngine->pImpEditEngine->IsInUndo() )
+ return;
+
+ if ( !aTmpSel.HasRange() )
+ return;
+
+ // aTmpOutArea: Falls OutputArea > Papierbreite und
+ // Text > Papierbreite ( uebergrosse Felder )
+ Rectangle aTmpOutArea( aOutArea );
+ if ( aTmpOutArea.GetWidth() > pEditEngine->pImpEditEngine->GetPaperSize().Width() )
+ aTmpOutArea.Right() = aTmpOutArea.Left() + pEditEngine->pImpEditEngine->GetPaperSize().Width();
+ pOutWin->IntersectClipRegion( aTmpOutArea );
+
+ if ( pOutWin->GetCursor() )
+ pOutWin->GetCursor()->Hide();
+ }
+
+ DBG_ASSERT( !pEditEngine->pImpEditEngine->aIdleFormatter.IsActive(), "DrawSelection: Not formatted!" );
+ aTmpSel.Adjust( pEditEngine->pImpEditEngine->GetEditDoc() );
+
+ ContentNode* pStartNode = aTmpSel.Min().GetNode();
+ ContentNode* pEndNode = aTmpSel.Max().GetNode();
+ sal_uInt16 nStartPara = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( pStartNode );
+ sal_uInt16 nEndPara = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( pEndNode );
+ // ueber die Absaetze iterieren....
+ for ( sal_uInt16 nPara = nStartPara; nPara <= nEndPara; nPara++ )
+ {
+ ParaPortion* pTmpPortion = pEditEngine->pImpEditEngine->GetParaPortions().SaveGetObject( nPara );
+ DBG_ASSERT( pTmpPortion, "Portion in Selektion nicht gefunden!" );
+ DBG_ASSERT( !pTmpPortion->IsInvalid(), "Portion in Selektion nicht formatiert!" );
+
+ if ( !pTmpPortion->IsVisible() || pTmpPortion->IsInvalid() )
+ continue;
+
+ long nParaStart = pEditEngine->pImpEditEngine->GetParaPortions().GetYOffset( pTmpPortion );
+ if ( ( nParaStart + pTmpPortion->GetHeight() ) < GetVisDocTop() )
+ continue;
+ if ( nParaStart > GetVisDocBottom() )
+ break;
+
+ sal_uInt16 nStartLine = 0;
+ sal_uInt16 nEndLine = pTmpPortion->GetLines().Count() -1;
+ if ( nPara == nStartPara )
+ nStartLine = pTmpPortion->GetLines().FindLine( aTmpSel.Min().GetIndex(), sal_False );
+ if ( nPara == nEndPara )
+ nEndLine = pTmpPortion->GetLines().FindLine( aTmpSel.Max().GetIndex(), sal_True );
+
+ // ueber die Zeilen iterieren....
+ for ( sal_uInt16 nLine = nStartLine; nLine <= nEndLine; nLine++ )
+ {
+ EditLine* pLine = pTmpPortion->GetLines().GetObject( nLine );
+ DBG_ASSERT( pLine, "Zeile nicht gefunden: DrawSelection()" );
+
+ BOOL bPartOfLine = FALSE;
+ sal_uInt16 nStartIndex = pLine->GetStart();
+ sal_uInt16 nEndIndex = pLine->GetEnd();
+ if ( ( nPara == nStartPara ) && ( nLine == nStartLine ) && ( nStartIndex != aTmpSel.Min().GetIndex() ) )
+ {
+ nStartIndex = aTmpSel.Min().GetIndex();
+ bPartOfLine = TRUE;
+ }
+ if ( ( nPara == nEndPara ) && ( nLine == nEndLine ) && ( nEndIndex != aTmpSel.Max().GetIndex() ) )
+ {
+ nEndIndex = aTmpSel.Max().GetIndex();
+ bPartOfLine = TRUE;
+ }
+
+ // Kann passieren, wenn am Anfang einer umgebrochenen Zeile.
+ if ( nEndIndex < nStartIndex )
+ nEndIndex = nStartIndex;
+
+ Rectangle aTmpRec( pEditEngine->pImpEditEngine->GetEditCursor( pTmpPortion, nStartIndex ) );
+ Point aTopLeft( aTmpRec.TopLeft() );
+ Point aBottomRight( aTmpRec.BottomRight() );
+
+ aTopLeft.Y() += nParaStart;
+ aBottomRight.Y() += nParaStart;
+
+ // Nur Painten, wenn im sichtbaren Bereich...
+ if ( aTopLeft.Y() > GetVisDocBottom() )
+ break;
+
+ if ( aBottomRight.Y() < GetVisDocTop() )
+ continue;
+
+ // Now that we have Bidi, the first/last index doesn't have to be the 'most outside' postion
+ if ( !bPartOfLine )
+ {
+ Range aLineXPosStartEnd = pEditEngine->pImpEditEngine->GetLineXPosStartEnd( pTmpPortion, pLine );
+ aTopLeft.X() = aLineXPosStartEnd.Min();
+ aBottomRight.X() = aLineXPosStartEnd.Max();
+ ImplDrawHighlightRect( pOutWin, aTopLeft, aBottomRight, pPolyPoly );
+ }
+ else
+ {
+ USHORT nTmpStartIndex = nStartIndex;
+ USHORT nWritingDirStart, nTmpEndIndex;
+
+ while ( nTmpStartIndex < nEndIndex )
+ {
+ pEditEngine->pImpEditEngine->GetRightToLeft( nPara, nTmpStartIndex+1, &nWritingDirStart, &nTmpEndIndex );
+ if ( nTmpEndIndex > nEndIndex )
+ nTmpEndIndex = nEndIndex;
+
+ DBG_ASSERT( nTmpEndIndex > nTmpStartIndex, "DrawSelection, Start >= End?" );
+
+ long nX1 = pEditEngine->pImpEditEngine->GetXPos( pTmpPortion, pLine, nTmpStartIndex, TRUE );
+ long nX2 = pEditEngine->pImpEditEngine->GetXPos( pTmpPortion, pLine, nTmpEndIndex );
+
+ Point aPt1( Min( nX1, nX2 ), aTopLeft.Y() );
+ Point aPt2( Max( nX1, nX2 ), aBottomRight.Y() );
+
+ ImplDrawHighlightRect( pOutWin, aPt1, aPt2, pPolyPoly );
+
+ nTmpStartIndex = nTmpEndIndex;
+ }
+ }
+
+ }
+ }
+
+ if ( pRegion )
+ {
+ *pRegion = Region( *pPolyPoly );
+ delete pPolyPoly;
+ }
+ else
+ {
+ if ( pOutWin->GetCursor() )
+ pOutWin->GetCursor()->Show();
+
+ if ( bClipRegion )
+ pOutWin->SetClipRegion( aOldRegion );
+ else
+ pOutWin->SetClipRegion();
+ }
+}
+
+void ImpEditView::ImplDrawHighlightRect( Window* _pOutWin, const Point& rDocPosTopLeft, const Point& rDocPosBottomRight, PolyPolygon* pPolyPoly )
+{
+ if ( rDocPosTopLeft.X() != rDocPosBottomRight.X() )
+ {
+ sal_Bool bPixelMode = _pOutWin->GetMapMode() == MAP_PIXEL;
+
+ Point aPnt1( GetWindowPos( rDocPosTopLeft ) );
+ Point aPnt2( GetWindowPos( rDocPosBottomRight ) );
+
+ if ( !IsVertical() )
+ {
+ lcl_AllignToPixel( aPnt1, _pOutWin, +1, 0 );
+ lcl_AllignToPixel( aPnt2, _pOutWin, 0, ( bPixelMode ? 0 : -1 ) );
+ }
+ else
+ {
+ lcl_AllignToPixel( aPnt1, _pOutWin, 0, +1 );
+ lcl_AllignToPixel( aPnt2, _pOutWin, ( bPixelMode ? 0 : +1 ), 0 );
+ }
+
+ Rectangle aRect( aPnt1, aPnt2 );
+ if ( pPolyPoly )
+ {
+ Polygon aTmpPoly( 4 );
+ aTmpPoly[0] = aRect.TopLeft();
+ aTmpPoly[1] = aRect.TopRight();
+ aTmpPoly[2] = aRect.BottomRight();
+ aTmpPoly[3] = aRect.BottomLeft();
+ pPolyPoly->Insert( aTmpPoly );
+ }
+ else
+ {
+ _pOutWin->Invert( aRect );
+ }
+ }
+}
+
+
+BOOL ImpEditView::IsVertical() const
+{
+ return pEditEngine->pImpEditEngine->IsVertical();
+}
+
+Rectangle ImpEditView::GetVisDocArea() const
+{
+ return Rectangle( GetVisDocLeft(), GetVisDocTop(), GetVisDocRight(), GetVisDocBottom() );
+}
+
+Point ImpEditView::GetDocPos( const Point& rWindowPos ) const
+{
+ // Fensterposition => Dokumentposition
+ Point aPoint;
+
+ if ( !pEditEngine->pImpEditEngine->IsVertical() )
+ {
+ aPoint.X() = rWindowPos.X() - aOutArea.Left() + GetVisDocLeft();
+ aPoint.Y() = rWindowPos.Y() - aOutArea.Top() + GetVisDocTop();
+ }
+ else
+ {
+ aPoint.X() = rWindowPos.Y() - aOutArea.Top() + GetVisDocLeft();
+ aPoint.Y() = aOutArea.Right() - rWindowPos.X() + GetVisDocTop();
+ }
+
+ return aPoint;
+}
+
+Point ImpEditView::GetWindowPos( const Point& rDocPos ) const
+{
+ // Dokumentposition => Fensterposition
+ Point aPoint;
+
+ if ( !pEditEngine->pImpEditEngine->IsVertical() )
+ {
+ aPoint.X() = rDocPos.X() + aOutArea.Left() - GetVisDocLeft();
+ aPoint.Y() = rDocPos.Y() + aOutArea.Top() - GetVisDocTop();
+ }
+ else
+ {
+ aPoint.X() = aOutArea.Right() - rDocPos.Y() + GetVisDocTop();
+ aPoint.Y() = rDocPos.X() + aOutArea.Top() - GetVisDocLeft();
+ }
+
+ return aPoint;
+}
+
+Rectangle ImpEditView::GetWindowPos( const Rectangle& rDocRect ) const
+{
+ // Dokumentposition => Fensterposition
+ Point aPos( GetWindowPos( rDocRect.TopLeft() ) );
+ Size aSz = rDocRect.GetSize();
+ Rectangle aRect;
+ if ( !pEditEngine->pImpEditEngine->IsVertical() )
+ {
+ aRect = Rectangle( aPos, aSz );
+ }
+ else
+ {
+ Point aNewPos( aPos.X()-aSz.Height(), aPos.Y() );
+ aRect = Rectangle( aNewPos, Size( aSz.Height(), aSz.Width() ) );
+ }
+ return aRect;
+}
+
+
+Region* ImpEditView::CalcSelectedRegion()
+{
+ Region* pRegion = new Region;
+ DrawSelection( GetEditSelection(), pRegion );
+ return pRegion;
+}
+
+void ImpEditView::SetSelectionMode( EESelectionMode eNewMode )
+{
+ if ( eSelectionMode != eNewMode )
+ {
+ DrawSelection(); // 'Wegmalen' ...
+ eSelectionMode = eNewMode;
+ DrawSelection(); // und neu zeichnen.
+ }
+}
+
+void ImpEditView::SetOutputArea( const Rectangle& rRec )
+{
+ // sollte besser auf Pixel allignt sein!
+ Rectangle aNewRec( pOutWin->LogicToPixel( rRec ) );
+ aNewRec = pOutWin->PixelToLogic( aNewRec );
+ aOutArea = aNewRec;
+ if ( aOutArea.Right() < aOutArea.Left() )
+ aOutArea.Right() = aOutArea.Left();
+ if ( aOutArea.Bottom() < aOutArea.Top() )
+ aOutArea.Bottom() = aOutArea.Top();
+
+ if ( DoBigScroll() )
+ SetScrollDiffX( (sal_uInt16)aOutArea.GetWidth() * 3 / 10 );
+ else
+ SetScrollDiffX( (sal_uInt16)aOutArea.GetWidth() * 2 / 10 );
+}
+
+void ImpEditView::ResetOutputArea( const Rectangle& rRec )
+{
+ Rectangle aCurArea( aOutArea );
+ SetOutputArea( rRec );
+ // Umliegende Bereiche invalidieren, wenn UpdateMode der Engine auf sal_True
+ if ( !aCurArea.IsEmpty() && pEditEngine->pImpEditEngine->GetUpdateMode() )
+ {
+ long nMore = 0;
+ if ( DoInvalidateMore() )
+ nMore = GetWindow()->PixelToLogic( Size( nInvMore, 0 ) ).Width();
+ if ( aCurArea.Left() < aOutArea.Left() )
+ {
+ Rectangle aRect( aCurArea.TopLeft(),
+ Size( aOutArea.Left()-aCurArea.Left(), aCurArea.GetHeight() ) );
+ if ( nMore )
+ {
+ aRect.Left() -= nMore;
+ aRect.Top() -= nMore;
+ aRect.Bottom() += nMore;
+ }
+ GetWindow()->Invalidate( aRect );
+ }
+ if ( aCurArea.Right() > aOutArea.Right() )
+ {
+ long nW = aCurArea.Right() - aOutArea.Right();
+ Point aPos( aCurArea.TopRight() );
+ aPos.X() -= nW;
+ Rectangle aRect( aPos, Size( nW, aCurArea.GetHeight() ) );
+ if ( nMore )
+ {
+ aRect.Right() += nMore;
+ aRect.Top() -= nMore;
+ aRect.Bottom() += nMore;
+ }
+ GetWindow()->Invalidate( aRect );
+ }
+ if ( aCurArea.Top() < aOutArea.Top() )
+ {
+ Rectangle aRect( aCurArea.TopLeft(), Size( aCurArea.GetWidth(), aOutArea.Top() - aCurArea.Top() ) );
+ if ( nMore )
+ {
+ aRect.Top() -= nMore;
+ aRect.Left() -= nMore;
+ aRect.Right() += nMore;
+ }
+ GetWindow()->Invalidate( aRect );
+ }
+ if ( aCurArea.Bottom() > aOutArea.Bottom() )
+ {
+ long nH = aCurArea.Bottom() - aOutArea.Bottom();
+ Point aPos( aCurArea.BottomLeft() );
+ aPos.Y() -= nH;
+ Rectangle aRect( aPos, Size( aCurArea.GetWidth(), nH ) );
+ if ( nMore )
+ {
+ aRect.Bottom() += nMore;
+ aRect.Left() -= nMore;
+ aRect.Right() += nMore;
+ }
+
+ GetWindow()->Invalidate( aRect );
+ }
+ }
+}
+
+void ImpEditView::RecalcOutputArea()
+{
+ Rectangle aOldArea( aOutArea );
+ Point aNewTopLeft( aOutArea.TopLeft() );
+ Size aNewSz( aOutArea.GetSize() );
+
+ // X:
+ if ( DoAutoWidth() )
+ {
+ if ( pEditEngine->pImpEditEngine->GetStatus().AutoPageWidth() )
+ aNewSz.Width() = pEditEngine->pImpEditEngine->GetPaperSize().Width();
+ switch ( eAnchorMode )
+ {
+ case ANCHOR_TOP_LEFT:
+ case ANCHOR_VCENTER_LEFT:
+ case ANCHOR_BOTTOM_LEFT:
+ {
+ aNewTopLeft.X() = aAnchorPoint.X();
+ }
+ break;
+ case ANCHOR_TOP_HCENTER:
+ case ANCHOR_VCENTER_HCENTER:
+ case ANCHOR_BOTTOM_HCENTER:
+ {
+ aNewTopLeft.X() = aAnchorPoint.X() - aNewSz.Width() / 2;
+ }
+ break;
+ case ANCHOR_TOP_RIGHT:
+ case ANCHOR_VCENTER_RIGHT:
+ case ANCHOR_BOTTOM_RIGHT:
+ {
+ aNewTopLeft.X() = aAnchorPoint.X() - aNewSz.Width() - 1;
+ }
+ break;
+ }
+ }
+
+ // Y:
+ if ( DoAutoHeight() )
+ {
+ if ( pEditEngine->pImpEditEngine->GetStatus().AutoPageHeight() )
+ aNewSz.Height() = pEditEngine->pImpEditEngine->GetPaperSize().Height();
+ switch ( eAnchorMode )
+ {
+ case ANCHOR_TOP_LEFT:
+ case ANCHOR_TOP_HCENTER:
+ case ANCHOR_TOP_RIGHT:
+ {
+ aNewTopLeft.Y() = aAnchorPoint.Y();
+ }
+ break;
+ case ANCHOR_VCENTER_LEFT:
+ case ANCHOR_VCENTER_HCENTER:
+ case ANCHOR_VCENTER_RIGHT:
+ {
+ aNewTopLeft.Y() = aAnchorPoint.Y() - aNewSz.Height() / 2;
+ }
+ break;
+ case ANCHOR_BOTTOM_LEFT:
+ case ANCHOR_BOTTOM_HCENTER:
+ case ANCHOR_BOTTOM_RIGHT:
+ {
+ aNewTopLeft.Y() = aAnchorPoint.Y() - aNewSz.Height() - 1;
+ }
+ break;
+ }
+ }
+ ResetOutputArea( Rectangle( aNewTopLeft, aNewSz ) );
+}
+
+void ImpEditView::SetAnchorMode( EVAnchorMode eMode )
+{
+ eAnchorMode = eMode;
+ CalcAnchorPoint();
+}
+
+void ImpEditView::CalcAnchorPoint()
+{
+ // GetHeight() und GetWidth() -1, da Rectangle-Berechnung nicht erwuenscht.
+
+ // X:
+ switch ( eAnchorMode )
+ {
+ case ANCHOR_TOP_LEFT:
+ case ANCHOR_VCENTER_LEFT:
+ case ANCHOR_BOTTOM_LEFT:
+ {
+ aAnchorPoint.X() = aOutArea.Left();
+ }
+ break;
+ case ANCHOR_TOP_HCENTER:
+ case ANCHOR_VCENTER_HCENTER:
+ case ANCHOR_BOTTOM_HCENTER:
+ {
+ aAnchorPoint.X() = aOutArea.Left() + (aOutArea.GetWidth()-1) / 2;
+ }
+ break;
+ case ANCHOR_TOP_RIGHT:
+ case ANCHOR_VCENTER_RIGHT:
+ case ANCHOR_BOTTOM_RIGHT:
+ {
+ aAnchorPoint.X() = aOutArea.Right();
+ }
+ break;
+ }
+
+ // Y:
+ switch ( eAnchorMode )
+ {
+ case ANCHOR_TOP_LEFT:
+ case ANCHOR_TOP_HCENTER:
+ case ANCHOR_TOP_RIGHT:
+ {
+ aAnchorPoint.Y() = aOutArea.Top();
+ }
+ break;
+ case ANCHOR_VCENTER_LEFT:
+ case ANCHOR_VCENTER_HCENTER:
+ case ANCHOR_VCENTER_RIGHT:
+ {
+ aAnchorPoint.Y() = aOutArea.Top() + (aOutArea.GetHeight()-1) / 2;
+ }
+ break;
+ case ANCHOR_BOTTOM_LEFT:
+ case ANCHOR_BOTTOM_HCENTER:
+ case ANCHOR_BOTTOM_RIGHT:
+ {
+ aAnchorPoint.Y() = aOutArea.Bottom() - 1;
+ }
+ break;
+ }
+}
+
+void ImpEditView::ShowCursor( sal_Bool bGotoCursor, sal_Bool bForceVisCursor, USHORT nShowCursorFlags )
+{
+ // Kein ShowCursor bei einer leeren View...
+ if ( ( aOutArea.Left() >= aOutArea.Right() ) && ( aOutArea.Top() >= aOutArea.Bottom() ) )
+ return;
+
+ pEditEngine->pImpEditEngine->CheckIdleFormatter();
+ if ( !pEditEngine->pImpEditEngine->IsFormatted() )
+ pEditEngine->pImpEditEngine->FormatDoc();
+
+ // Aus irgendwelchen Gruenden lande ich waehrend der Formatierung hier,
+ // wenn sich der Outiner im Paint initialisiert, weil kein SetPool();
+ if ( pEditEngine->pImpEditEngine->IsFormatting() )
+ return;
+ if ( pEditEngine->pImpEditEngine->GetUpdateMode() == sal_False )
+ return;
+ if ( pEditEngine->pImpEditEngine->IsInUndo() )
+ return;
+
+ if ( pOutWin->GetCursor() != GetCursor() )
+ pOutWin->SetCursor( GetCursor() );
+
+ EditPaM aPaM( aEditSelection.Max() );
+
+ USHORT nTextPortionStart = 0;
+ USHORT nPara = pEditEngine->pImpEditEngine->aEditDoc.GetPos( aPaM.GetNode() );
+ if (nPara == USHRT_MAX) // #i94322
+ return;
+ ParaPortion* pParaPortion = pEditEngine->pImpEditEngine->GetParaPortions().GetObject( nPara );
+
+ nShowCursorFlags |= nExtraCursorFlags;
+
+ nShowCursorFlags |= GETCRSR_TXTONLY;
+
+ // Use CursorBidiLevel 0/1 in meaning of
+ // 0: prefer portion end, normal mode
+ // 1: prefer portion start
+
+ if ( ( GetCursorBidiLevel() != CURSOR_BIDILEVEL_DONTKNOW ) && GetCursorBidiLevel() )
+ {
+ nShowCursorFlags |= GETCRSR_PREFERPORTIONSTART;
+ }
+
+ Rectangle aEditCursor = pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM, nShowCursorFlags );
+ if ( !IsInsertMode() && !aEditSelection.HasRange() )
+ {
+ if ( aPaM.GetNode()->Len() && ( aPaM.GetIndex() < aPaM.GetNode()->Len() ) )
+ {
+ // If we are behind a portion, and the next portion has other direction, we must change position...
+ aEditCursor.Left() = aEditCursor.Right() = pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM, GETCRSR_TXTONLY|GETCRSR_PREFERPORTIONSTART ).Left();
+
+ USHORT nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, TRUE );
+ TextPortion* pTextPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );
+ if ( pTextPortion->GetKind() == PORTIONKIND_TAB )
+ {
+ aEditCursor.Right() += pTextPortion->GetSize().Width();
+ }
+ else
+ {
+ EditPaM aNext = pEditEngine->pImpEditEngine->CursorRight( aPaM, (USHORT)i18n::CharacterIteratorMode::SKIPCELL );
+ Rectangle aTmpRect = pEditEngine->pImpEditEngine->PaMtoEditCursor( aNext, GETCRSR_TXTONLY );
+ if ( aTmpRect.Top() != aEditCursor.Top() )
+ aTmpRect = pEditEngine->pImpEditEngine->PaMtoEditCursor( aNext, GETCRSR_TXTONLY|GETCRSR_ENDOFLINE );
+ aEditCursor.Right() = aTmpRect.Left();
+ }
+ }
+ }
+ long nMaxHeight = !IsVertical() ? aOutArea.GetHeight() : aOutArea.GetWidth();
+ if ( aEditCursor.GetHeight() > nMaxHeight )
+ {
+ aEditCursor.Bottom() = aEditCursor.Top() + nMaxHeight - 1;
+ }
+ if ( bGotoCursor ) // && (!pEditEngine->pImpEditEngine->GetStatus().AutoPageSize() ) )
+ {
+ // pruefen, ob scrollen notwendig...
+ // wenn scrollen, dann Update() und Scroll() !
+ long nDocDiffX = 0;
+ long nDocDiffY = 0;
+
+ Rectangle aTmpVisArea( GetVisDocArea() );
+ // aTmpOutArea: Falls OutputArea > Papierbreite und
+ // Text > Papierbreite ( uebergrosse Felder )
+ long nMaxTextWidth = !IsVertical() ? pEditEngine->pImpEditEngine->GetPaperSize().Width() : pEditEngine->pImpEditEngine->GetPaperSize().Height();
+ if ( aTmpVisArea.GetWidth() > nMaxTextWidth )
+ aTmpVisArea.Right() = aTmpVisArea.Left() + nMaxTextWidth;
+
+ if ( aEditCursor.Bottom() > aTmpVisArea.Bottom() )
+ { // hochscrollen, hier positiv
+ nDocDiffY = aEditCursor.Bottom() - aTmpVisArea.Bottom();
+ }
+ else if ( aEditCursor.Top() < aTmpVisArea.Top() )
+ { // runterscrollen, negativ
+ nDocDiffY = aEditCursor.Top() - aTmpVisArea.Top();
+ }
+
+ if ( aEditCursor.Right() > aTmpVisArea.Right() )
+ {
+ // linksscrollen, positiv
+ nDocDiffX = aEditCursor.Right() - aTmpVisArea.Right();
+ // Darfs ein bischen mehr sein?
+ if ( aEditCursor.Right() < ( nMaxTextWidth - GetScrollDiffX() ) )
+ nDocDiffX += GetScrollDiffX();
+ else
+ {
+ long n = nMaxTextWidth - aEditCursor.Right();
+ // Bei einem MapMode != RefMapMode kann der EditCursor auch mal ueber
+ // die Papierbreite Wandern!
+ nDocDiffX += ( n > 0 ? n : -n );
+ }
+ }
+ else if ( aEditCursor.Left() < aTmpVisArea.Left() )
+ { // rechtsscrollen
+ // negativ:
+ nDocDiffX = aEditCursor.Left() - aTmpVisArea.Left();
+ // Darfs ein bischen mehr sein?
+ if ( aEditCursor.Left() > ( - (long)GetScrollDiffX() ) )
+ nDocDiffX -= GetScrollDiffX();
+ else
+ nDocDiffX -= aEditCursor.Left();
+ }
+ if ( aPaM.GetIndex() == 0 ) // braucht Olli fuer den Outliner
+ {
+ // Aber sicherstellen, dass dadurch der Cursor nicht den
+ // sichtbaren bereich verlaesst!
+ if ( aEditCursor.Left() < aTmpVisArea.GetWidth() )
+ {
+ nDocDiffX = -aTmpVisArea.Left();
+ }
+ }
+
+ if ( nDocDiffX | nDocDiffY )
+ {
+ long nDiffX = !IsVertical() ? nDocDiffX : -nDocDiffY;
+ long nDiffY = !IsVertical() ? nDocDiffY : nDocDiffX;
+
+ // Negativ: Zum Anfang bzw. linken Rand
+ if ( ( Abs( nDiffY ) > pEditEngine->pImpEditEngine->nOnePixelInRef ) && DoBigScroll() )
+ {
+ long nH = aOutArea.GetHeight() / 4;
+ if ( ( nH > aEditCursor.GetHeight() ) && ( Abs( nDiffY ) < nH ) )
+ {
+ if ( nDiffY < 0 )
+ nDiffY -= nH;
+ else
+ nDiffY += nH;
+ }
+ }
+
+ if ( ( Abs( nDiffX ) > pEditEngine->pImpEditEngine->nOnePixelInRef ) && DoBigScroll() )
+ {
+ long nW = aOutArea.GetWidth() / 4;
+ if ( Abs( nDiffX ) < nW )
+ {
+ if ( nDiffY < 0 )
+ nDiffY -= nW;
+ else
+ nDiffY += nW;
+ }
+ }
+
+ if ( nDiffX )
+ pEditEngine->pImpEditEngine->aStatus.GetStatusWord() = pEditEngine->pImpEditEngine->aStatus.GetStatusWord() | EE_STAT_HSCROLL;
+ if ( nDiffY )
+ pEditEngine->pImpEditEngine->aStatus.GetStatusWord() = pEditEngine->pImpEditEngine->aStatus.GetStatusWord() | EE_STAT_VSCROLL;
+ Scroll( -nDiffX, -nDiffY );
+ pEditEngine->pImpEditEngine->DelayedCallStatusHdl();
+ }
+ }
+
+ // Cursor evtl. etwas stutzen...
+ if ( ( aEditCursor.Bottom() > GetVisDocTop() ) &&
+ ( aEditCursor.Top() < GetVisDocBottom() ) )
+ {
+ if ( aEditCursor.Bottom() > GetVisDocBottom() )
+ aEditCursor.Bottom() = GetVisDocBottom();
+ if ( aEditCursor.Top() < GetVisDocTop() )
+ aEditCursor.Top() = GetVisDocTop();
+ }
+
+ long nOnePixel = pOutWin->PixelToLogic( Size( 1, 0 ) ).Width();
+
+ if ( /* pEditEngine->pImpEditEngine->GetStatus().AutoPageSize() || */
+ ( ( aEditCursor.Top() + nOnePixel >= GetVisDocTop() ) &&
+ ( aEditCursor.Bottom() - nOnePixel <= GetVisDocBottom() ) &&
+ ( aEditCursor.Left() + nOnePixel >= GetVisDocLeft() ) &&
+ ( aEditCursor.Right() - nOnePixel <= GetVisDocRight() ) ) )
+ {
+ Rectangle aCursorRect = GetWindowPos( aEditCursor );
+ GetCursor()->SetPos( aCursorRect.TopLeft() );
+ Size aCursorSz( aCursorRect.GetSize() );
+ // Rectangle is inclusive
+ aCursorSz.Width()--;
+ aCursorSz.Height()--;
+ if ( !aCursorSz.Width() || !aCursorSz.Height() )
+ {
+ long nCursorSz = pOutWin->GetSettings().GetStyleSettings().GetCursorSize();
+ nCursorSz = pOutWin->PixelToLogic( Size( nCursorSz, 0 ) ).Width();
+ if ( !aCursorSz.Width() )
+ aCursorSz.Width() = nCursorSz;
+ if ( !aCursorSz.Height() )
+ aCursorSz.Height() = nCursorSz;
+ }
+ // #111036# Let VCL do orientation for cursor, otherwise problem when cursor has direction flag
+ if ( IsVertical() )
+ {
+ Size aOldSz( aCursorSz );
+ aCursorSz.Width() = aOldSz.Height();
+ aCursorSz.Height() = aOldSz.Width();
+ GetCursor()->SetPos( aCursorRect.TopRight() );
+ GetCursor()->SetOrientation( 2700 );
+ }
+ else
+ // --> FME 2004-10-18 #i32593#
+ // Reset correct orientation in horizontal layout
+ GetCursor()->SetOrientation( 0 );
+ // <--
+
+ GetCursor()->SetSize( aCursorSz );
+
+ unsigned char nCursorDir = CURSOR_DIRECTION_NONE;
+ if ( IsInsertMode() && !aEditSelection.HasRange() && ( pEditEngine->pImpEditEngine->HasDifferentRTLLevels( aPaM.GetNode() ) ) )
+ {
+ USHORT nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, nShowCursorFlags & GETCRSR_PREFERPORTIONSTART ? TRUE : FALSE );
+ TextPortion* pTextPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );
+ USHORT nRTLLevel = pTextPortion->GetRightToLeft();
+ if ( nRTLLevel%2 )
+ nCursorDir = CURSOR_DIRECTION_RTL;
+ else
+ nCursorDir = CURSOR_DIRECTION_LTR;
+
+ }
+ GetCursor()->SetDirection( nCursorDir );
+
+ if ( bForceVisCursor )
+ GetCursor()->Show();
+
+ // #102936# Call SetInputContext every time, otherwise we may have the wrong font
+ // if ( !pEditEngine->pImpEditEngine->mpIMEInfos )
+ {
+ SvxFont aFont;
+ pEditEngine->pImpEditEngine->SeekCursor( aPaM.GetNode(), aPaM.GetIndex()+1, aFont );
+ ULONG nContextFlags = INPUTCONTEXT_TEXT|INPUTCONTEXT_EXTTEXTINPUT;
+ GetWindow()->SetInputContext( InputContext( aFont, nContextFlags ) );
+ }
+ }
+ else
+ {
+ pEditEngine->pImpEditEngine->GetStatus().GetStatusWord() = pEditEngine->pImpEditEngine->GetStatus().GetStatusWord() | EE_STAT_CURSOROUT;
+ GetCursor()->Hide();
+ GetCursor()->SetPos( Point( -1, -1 ) );
+ GetCursor()->SetSize( Size( 0, 0 ) );
+ }
+}
+
+Pair ImpEditView::Scroll( long ndX, long ndY, BYTE nRangeCheck )
+{
+ DBG_ASSERT( pEditEngine->pImpEditEngine->IsFormatted(), "Scroll: Nicht formatiert!" );
+ if ( !ndX && !ndY )
+ return Range( 0, 0 );
+
+#ifdef DBG_UTIL
+ Rectangle aR( aOutArea );
+ aR = pOutWin->LogicToPixel( aR );
+ aR = pOutWin->PixelToLogic( aR );
+ DBG_ASSERTWARNING( aR == aOutArea, "OutArea vor Scroll nicht aligned" );
+#endif
+
+ Rectangle aNewVisArea( GetVisDocArea() );
+ Size aPaperSz( pEditEngine->pImpEditEngine->GetPaperSize() );
+
+ // Vertical:
+ if ( !IsVertical() )
+ {
+ aNewVisArea.Top() -= ndY;
+ aNewVisArea.Bottom() -= ndY;
+ }
+ else
+ {
+ aNewVisArea.Top() += ndX;
+ aNewVisArea.Bottom() += ndX;
+ }
+ if ( ( nRangeCheck == RGCHK_PAPERSZ1 ) && ( aNewVisArea.Bottom() > (long)pEditEngine->pImpEditEngine->GetTextHeight() ) )
+ {
+ // GetTextHeight noch optimieren!
+ long nDiff = pEditEngine->pImpEditEngine->GetTextHeight() - aNewVisArea.Bottom(); // negativ
+ aNewVisArea.Move( 0, nDiff ); // koennte im neg. Bereich landen...
+ }
+ if ( ( aNewVisArea.Top() < 0 ) && ( nRangeCheck != RGCHK_NONE ) )
+ aNewVisArea.Move( 0, -aNewVisArea.Top() );
+
+ // Horizontal:
+ if ( !IsVertical() )
+ {
+ aNewVisArea.Left() -= ndX;
+ aNewVisArea.Right() -= ndX;
+ }
+ else
+ {
+ aNewVisArea.Left() -= ndY;
+ aNewVisArea.Right() -= ndY;
+ }
+ if ( ( nRangeCheck == RGCHK_PAPERSZ1 ) && ( aNewVisArea.Right() > (long)pEditEngine->pImpEditEngine->CalcTextWidth( FALSE ) ) )
+ {
+ long nDiff = pEditEngine->pImpEditEngine->CalcTextWidth( FALSE ) - aNewVisArea.Right(); // negativ
+ aNewVisArea.Move( nDiff, 0 ); // koennte im neg. Bereich landen...
+ }
+ if ( ( aNewVisArea.Left() < 0 ) && ( nRangeCheck != RGCHK_NONE ) )
+ aNewVisArea.Move( -aNewVisArea.Left(), 0 );
+
+ // Die Differenz muss auf Pixel alignt sein (wegen Scroll!)
+ long nDiffX = !IsVertical() ? ( GetVisDocLeft() - aNewVisArea.Left() ) : -( GetVisDocTop() - aNewVisArea.Top() );
+ long nDiffY = !IsVertical() ? ( GetVisDocTop() - aNewVisArea.Top() ) : ( GetVisDocLeft() - aNewVisArea.Left() );
+
+ Size aDiffs( nDiffX, nDiffY );
+ aDiffs = pOutWin->LogicToPixel( aDiffs );
+ aDiffs = pOutWin->PixelToLogic( aDiffs );
+
+ long nRealDiffX = aDiffs.Width();
+ long nRealDiffY = aDiffs.Height();
+
+
+ if ( nRealDiffX || nRealDiffY )
+ {
+ Cursor* pCrsr = GetCursor();
+ sal_Bool bVisCursor = pCrsr->IsVisible();
+ pCrsr->Hide();
+ pOutWin->Update();
+ if ( !IsVertical() )
+ aVisDocStartPos.Move( -nRealDiffX, -nRealDiffY );
+ else
+ aVisDocStartPos.Move( -nRealDiffY, nRealDiffX );
+ // Das Move um den allignten Wert ergibt nicht unbedingt ein
+ // alligntes Rechteck...
+ // MT 11/00: Align VisArea???
+ aVisDocStartPos = pOutWin->LogicToPixel( aVisDocStartPos );
+ aVisDocStartPos = pOutWin->PixelToLogic( aVisDocStartPos );
+ Rectangle aRec( aOutArea );
+ pOutWin->Scroll( nRealDiffX, nRealDiffY, aRec, sal_True );
+ pOutWin->Update();
+ pCrsr->SetPos( pCrsr->GetPos() + Point( nRealDiffX, nRealDiffY ) );
+ if ( bVisCursor )
+ {
+ Rectangle aCursorRec( pCrsr->GetPos(), pCrsr->GetSize() );
+ if ( aOutArea.IsInside( aCursorRec ) )
+ pCrsr->Show();
+ }
+
+ if ( pEditEngine->pImpEditEngine->GetNotifyHdl().IsSet() )
+ {
+ EENotify aNotify( EE_NOTIFY_TEXTVIEWSCROLLED );
+ aNotify.pEditEngine = pEditEngine;
+ aNotify.pEditView = GetEditViewPtr();
+ pEditEngine->pImpEditEngine->CallNotify( aNotify );
+ }
+ }
+
+ return Pair( nRealDiffX, nRealDiffY );
+}
+
+sal_Bool ImpEditView::PostKeyEvent( const KeyEvent& rKeyEvent )
+{
+ BOOL bDone = FALSE;
+
+ KeyFuncType eFunc = rKeyEvent.GetKeyCode().GetFunction();
+ if ( eFunc != KEYFUNC_DONTKNOW )
+ {
+ switch ( eFunc )
+ {
+ case KEYFUNC_CUT:
+ {
+ if ( !bReadOnly )
+ {
+ Reference<com::sun::star::datatransfer::clipboard::XClipboard> aClipBoard(GetWindow()->GetClipboard());
+ CutCopy( aClipBoard, sal_True );
+ bDone = sal_True;
+ }
+ }
+ break;
+ case KEYFUNC_COPY:
+ {
+ Reference<com::sun::star::datatransfer::clipboard::XClipboard> aClipBoard(GetWindow()->GetClipboard());
+ CutCopy( aClipBoard, sal_False );
+ bDone = TRUE;
+ }
+ break;
+ case KEYFUNC_PASTE:
+ {
+ if ( !bReadOnly && IsPasteEnabled() )
+ {
+ pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_PASTE );
+ Reference<com::sun::star::datatransfer::clipboard::XClipboard> aClipBoard(GetWindow()->GetClipboard());
+ Paste( aClipBoard, pEditEngine->pImpEditEngine->GetStatus().AllowPasteSpecial() );
+ pEditEngine->pImpEditEngine->UndoActionEnd( EDITUNDO_PASTE );
+ bDone = sal_True;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if( !bDone )
+ bDone = pEditEngine->PostKeyEvent( rKeyEvent, GetEditViewPtr() );
+
+ return bDone;
+}
+
+sal_Bool ImpEditView::MouseButtonUp( const MouseEvent& rMouseEvent )
+{
+ if ( pEditEngine->pImpEditEngine->aStatus.NotifyCursorMovements() )
+ {
+ if ( pEditEngine->pImpEditEngine->aStatus.GetPrevParagraph() != pEditEngine->pImpEditEngine->GetEditDoc().GetPos( GetEditSelection().Max().GetNode() ) )
+ {
+ pEditEngine->pImpEditEngine->aStatus.GetStatusWord() = pEditEngine->pImpEditEngine->aStatus.GetStatusWord() | EE_STAT_CRSRLEFTPARA;
+ pEditEngine->pImpEditEngine->CallStatusHdl();
+ }
+ }
+ nTravelXPos = TRAVEL_X_DONTKNOW;
+ nCursorBidiLevel = CURSOR_BIDILEVEL_DONTKNOW;
+ nExtraCursorFlags = 0;
+ bClickedInSelection = sal_False;
+
+ if ( rMouseEvent.IsMiddle() && !bReadOnly &&
+ ( GetWindow()->GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION ) )
+ {
+ Reference<com::sun::star::datatransfer::clipboard::XClipboard> aClipBoard(GetWindow()->GetPrimarySelection());
+ Paste( aClipBoard );
+ }
+ else if ( rMouseEvent.IsLeft() && GetEditSelection().HasRange() )
+ {
+ Reference<com::sun::star::datatransfer::clipboard::XClipboard> aClipBoard(GetWindow()->GetPrimarySelection());
+ CutCopy( aClipBoard, FALSE );
+ }
+
+ return pEditEngine->pImpEditEngine->MouseButtonUp( rMouseEvent, GetEditViewPtr() );
+}
+
+sal_Bool ImpEditView::MouseButtonDown( const MouseEvent& rMouseEvent )
+{
+ pEditEngine->pImpEditEngine->CheckIdleFormatter(); // Falls schnelles Tippen und MouseButtonDown
+ if ( pEditEngine->pImpEditEngine->aStatus.NotifyCursorMovements() )
+ pEditEngine->pImpEditEngine->aStatus.GetPrevParagraph() = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( GetEditSelection().Max().GetNode() );
+ nTravelXPos = TRAVEL_X_DONTKNOW;
+ nExtraCursorFlags = 0;
+ nCursorBidiLevel = CURSOR_BIDILEVEL_DONTKNOW;
+ bClickedInSelection = IsSelectionAtPoint( rMouseEvent.GetPosPixel() );
+ return pEditEngine->pImpEditEngine->MouseButtonDown( rMouseEvent, GetEditViewPtr() );
+}
+
+sal_Bool ImpEditView::MouseMove( const MouseEvent& rMouseEvent )
+{
+ return pEditEngine->pImpEditEngine->MouseMove( rMouseEvent, GetEditViewPtr() );
+}
+
+void ImpEditView::Command( const CommandEvent& rCEvt )
+{
+ pEditEngine->pImpEditEngine->CheckIdleFormatter(); // Falls schnelles Tippen und MouseButtonDown
+ pEditEngine->pImpEditEngine->Command( rCEvt, GetEditViewPtr() );
+}
+
+
+void ImpEditView::SetInsertMode( sal_Bool bInsert )
+{
+ if ( bInsert != IsInsertMode() )
+ {
+ SetFlags( nControl, EV_CNTRL_OVERWRITE, !bInsert );
+ ShowCursor( DoAutoScroll(), sal_False );
+ }
+}
+
+sal_Bool ImpEditView::IsWrongSpelledWord( const EditPaM& rPaM, sal_Bool bMarkIfWrong )
+{
+ sal_Bool bIsWrong = sal_False;
+#ifndef SVX_LIGHT
+ if ( rPaM.GetNode()->GetWrongList() )
+ {
+ EditSelection aSel = pEditEngine->pImpEditEngine->SelectWord( rPaM, ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
+ bIsWrong = rPaM.GetNode()->GetWrongList()->HasWrong( aSel.Min().GetIndex(), aSel.Max().GetIndex() );
+ if ( bIsWrong && bMarkIfWrong )
+ {
+ DrawSelection(); // alte Selektion 'weg-zeichnen'
+ SetEditSelection( aSel );
+ DrawSelection();
+ }
+ }
+#endif // !SVX_LIGHT
+ return bIsWrong;
+}
+
+String ImpEditView::SpellIgnoreOrAddWord( sal_Bool bAdd )
+{
+ String aWord;
+#ifndef SVX_LIGHT
+ if ( pEditEngine->pImpEditEngine->GetSpeller().is() )
+ {
+ EditPaM aPaM = GetEditSelection().Max();
+ if ( !HasSelection() )
+ {
+ EditSelection aSel = pEditEngine->pImpEditEngine->SelectWord( aPaM );
+ aWord = pEditEngine->pImpEditEngine->GetSelected( aSel );
+ }
+ else
+ {
+ aWord = pEditEngine->pImpEditEngine->GetSelected( GetEditSelection() );
+ // Und deselektieren
+ DrawSelection(); // alte Selektion 'weg-zeichnen'
+ SetEditSelection( EditSelection( aPaM, aPaM ) );
+ DrawSelection();
+ }
+
+ if ( aWord.Len() )
+ {
+ if ( bAdd )
+ {
+ DBG_ERROR( "Sorry, AddWord not implemented" );
+ }
+ else // Ignore
+ {
+ Reference< XDictionary > xDic( SvxGetIgnoreAllList(), UNO_QUERY );
+ if (xDic.is())
+ xDic->add( aWord, sal_False, String() );
+ }
+ const EditDoc& rDoc = pEditEngine->pImpEditEngine->GetEditDoc();
+ sal_uInt16 nNodes = rDoc.Count();
+ for ( sal_uInt16 n = 0; n < nNodes; n++ )
+ {
+ ContentNode* pNode = rDoc.GetObject( n );
+ pNode->GetWrongList()->MarkWrongsInvalid();
+ }
+ pEditEngine->pImpEditEngine->DoOnlineSpelling( aPaM.GetNode() );
+ pEditEngine->pImpEditEngine->StartOnlineSpellTimer();
+ }
+ }
+#endif // !SVX_LIGHT
+ return aWord;
+}
+
+void ImpEditView::DeleteSelected()
+{
+ DrawSelection();
+
+ pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_DELETE );
+
+ EditPaM aPaM = pEditEngine->pImpEditEngine->DeleteSelected( GetEditSelection() );
+
+ pEditEngine->pImpEditEngine->UndoActionEnd( EDITUNDO_DELETE );
+
+ SetEditSelection( EditSelection( aPaM, aPaM ) );
+ pEditEngine->pImpEditEngine->FormatAndUpdate( GetEditViewPtr() );
+ ShowCursor( DoAutoScroll(), TRUE );
+}
+
+const SvxFieldItem* ImpEditView::GetField( const Point& rPos, sal_uInt16* pPara, sal_uInt16* pPos ) const
+{
+ if( !GetOutputArea().IsInside( rPos ) )
+ return 0;
+
+ Point aDocPos( GetDocPos( rPos ) );
+ EditPaM aPaM = pEditEngine->pImpEditEngine->GetPaM( aDocPos, sal_False );
+
+ if ( aPaM.GetIndex() == aPaM.GetNode()->Len() )
+ {
+ // Sonst immer, wenn Feld ganz am Schluss und Mouse unter Text
+ return 0;
+ }
+
+ const CharAttribArray& rAttrs = aPaM.GetNode()->GetCharAttribs().GetAttribs();
+ sal_uInt16 nXPos = aPaM.GetIndex();
+ for ( sal_uInt16 nAttr = rAttrs.Count(); nAttr; )
+ {
+ EditCharAttrib* pAttr = rAttrs[--nAttr];
+ if ( pAttr->GetStart() == nXPos )
+ if ( pAttr->Which() == EE_FEATURE_FIELD )
+ {
+ DBG_ASSERT( pAttr->GetItem()->ISA( SvxFieldItem ), "Kein FeldItem..." );
+ if ( pPara )
+ *pPara = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( aPaM.GetNode() );
+ if ( pPos )
+ *pPos = pAttr->GetStart();
+ return (const SvxFieldItem*)pAttr->GetItem();
+ }
+ }
+ return NULL;
+}
+
+BOOL ImpEditView::IsBulletArea( const Point& rPos, sal_uInt16* pPara )
+{
+ if ( pPara )
+ *pPara = 0xFFFF;
+
+ if( !GetOutputArea().IsInside( rPos ) )
+ return FALSE;
+
+ Point aDocPos( GetDocPos( rPos ) );
+ EditPaM aPaM = pEditEngine->pImpEditEngine->GetPaM( aDocPos, sal_False );
+
+ if ( aPaM.GetIndex() == 0 )
+ {
+ USHORT nPara = pEditEngine->pImpEditEngine->aEditDoc.GetPos( aPaM.GetNode() );
+ Rectangle aBulletArea = pEditEngine->GetBulletArea( nPara );
+ long nY = pEditEngine->GetDocPosTopLeft( nPara ).Y();
+ ParaPortion* pParaPortion = pEditEngine->pImpEditEngine->GetParaPortions().GetObject( nPara );
+ nY += pParaPortion->GetFirstLineOffset();
+ if ( ( aDocPos.Y() > ( nY + aBulletArea.Top() ) ) &&
+ ( aDocPos.Y() < ( nY + aBulletArea.Bottom() ) ) &&
+ ( aDocPos.X() > ( aBulletArea.Left() ) ) &&
+ ( aDocPos.X() < ( aBulletArea.Right() ) ) )
+ {
+ if ( pPara )
+ *pPara = nPara;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+void ImpEditView::CutCopy( ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboard >& rxClipboard, BOOL bCut )
+{
+ if ( rxClipboard.is() && GetEditSelection().HasRange() )
+ {
+ uno::Reference< datatransfer::XTransferable > xData = pEditEngine->pImpEditEngine->CreateTransferable( GetEditSelection() );
+
+ const sal_uInt32 nRef = Application::ReleaseSolarMutex();
+
+ try
+ {
+ rxClipboard->setContents( xData, NULL );
+
+ // #87756# FlushClipboard, but it would be better to become a TerminateListener to the Desktop and flush on demand...
+ uno::Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( rxClipboard, uno::UNO_QUERY );
+ if( xFlushableClipboard.is() )
+ xFlushableClipboard->flushClipboard();
+ }
+ catch( const ::com::sun::star::uno::Exception& )
+ {
+ }
+
+ Application::AcquireSolarMutex( nRef );
+
+ if ( bCut )
+ {
+ pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_CUT );
+ DeleteSelected();
+ pEditEngine->pImpEditEngine->UndoActionEnd( EDITUNDO_CUT );
+
+ }
+ }
+}
+
+void ImpEditView::Paste( ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboard >& rxClipboard, BOOL bUseSpecial )
+{
+ if ( rxClipboard.is() )
+ {
+ uno::Reference< datatransfer::XTransferable > xDataObj;
+
+ const sal_uInt32 nRef = Application::ReleaseSolarMutex();
+
+ try
+ {
+ xDataObj = rxClipboard->getContents();
+ }
+ catch( const ::com::sun::star::uno::Exception& )
+ {
+ }
+
+ Application::AcquireSolarMutex( nRef );
+
+ if ( xDataObj.is() && EditEngine::HasValidData( xDataObj ) )
+ {
+ pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_PASTE );
+
+ EditSelection aSel( GetEditSelection() );
+ if ( aSel.HasRange() )
+ {
+ DrawSelection();
+ aSel = pEditEngine->pImpEditEngine->ImpDeleteSelection( aSel );
+ }
+
+ PasteOrDropInfos aPasteOrDropInfos;
+ aPasteOrDropInfos.nAction = EE_ACTION_PASTE;
+ aPasteOrDropInfos.nStartPara = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( aSel.Min().GetNode() );
+ pEditEngine->pImpEditEngine->aBeginPasteOrDropHdl.Call( &aPasteOrDropInfos );
+
+ if ( DoSingleLinePaste() )
+ {
+ datatransfer::DataFlavor aFlavor;
+ SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor );
+ if ( xDataObj->isDataFlavorSupported( aFlavor ) )
+ {
+ try
+ {
+ uno::Any aData = xDataObj->getTransferData( aFlavor );
+ ::rtl::OUString aTmpText;
+ aData >>= aTmpText;
+ String aText( aTmpText );
+ aText.ConvertLineEnd( LINEEND_LF );
+ aText.SearchAndReplaceAll( LINE_SEP, ' ' );
+ aSel = pEditEngine->pImpEditEngine->ImpInsertText( aSel, aText );
+ }
+ catch( ... )
+ {
+ ; // #i9286# can happen, even if isDataFlavorSupported returns true...
+ }
+ }
+ }
+ else
+ {
+ aSel = pEditEngine->pImpEditEngine->InsertText( xDataObj, String(), aSel.Min(), bUseSpecial && pEditEngine->pImpEditEngine->GetStatus().AllowPasteSpecial() );
+ }
+
+ aPasteOrDropInfos.nEndPara = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( aSel.Max().GetNode() );
+ pEditEngine->pImpEditEngine->aEndPasteOrDropHdl.Call( &aPasteOrDropInfos );
+
+ pEditEngine->pImpEditEngine->UndoActionEnd( EDITUNDO_PASTE );
+ SetEditSelection( aSel );
+ pEditEngine->pImpEditEngine->UpdateSelections();
+ pEditEngine->pImpEditEngine->FormatAndUpdate( GetEditViewPtr() );
+ ShowCursor( DoAutoScroll(), TRUE );
+ }
+ }
+}
+
+
+BOOL ImpEditView::IsInSelection( const EditPaM& rPaM )
+{
+ EditSelection aSel = GetEditSelection();
+ if ( !aSel.HasRange() )
+ return FALSE;
+
+ aSel.Adjust( pEditEngine->pImpEditEngine->GetEditDoc() );
+
+ USHORT nStartNode = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( aSel.Min().GetNode() );
+ USHORT nEndNode = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( aSel.Max().GetNode() );
+ USHORT nCurNode = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( rPaM.GetNode() );
+
+ if ( ( nCurNode > nStartNode ) && ( nCurNode < nEndNode ) )
+ return TRUE;
+
+ if ( nStartNode == nEndNode )
+ {
+ if ( nCurNode == nStartNode )
+ if ( ( rPaM.GetIndex() >= aSel.Min().GetIndex() ) && ( rPaM.GetIndex() < aSel.Max().GetIndex() ) )
+ return TRUE;
+ }
+ else if ( ( nCurNode == nStartNode ) && ( rPaM.GetIndex() >= aSel.Min().GetIndex() ) )
+ return TRUE;
+ else if ( ( nCurNode == nEndNode ) && ( rPaM.GetIndex() < aSel.Max().GetIndex() ) )
+ return TRUE;
+
+ return FALSE;
+}
+
+void ImpEditView::CreateAnchor()
+{
+ pEditEngine->pImpEditEngine->bInSelection = TRUE;
+ GetEditSelection().Min() = GetEditSelection().Max();
+}
+
+void ImpEditView::DeselectAll()
+{
+ pEditEngine->pImpEditEngine->bInSelection = FALSE;
+ DrawSelection();
+ GetEditSelection().Min() = GetEditSelection().Max();
+}
+
+BOOL ImpEditView::IsSelectionAtPoint( const Point& rPosPixel )
+{
+ if ( pDragAndDropInfo && pDragAndDropInfo->pField )
+ return TRUE;
+
+ Point aMousePos( rPosPixel );
+
+ // Logische Einheiten...
+ aMousePos = GetWindow()->PixelToLogic( aMousePos );
+
+ if ( ( !GetOutputArea().IsInside( aMousePos ) ) && !pEditEngine->pImpEditEngine->IsInSelectionMode() )
+ {
+ return FALSE;
+ }
+
+ Point aDocPos( GetDocPos( aMousePos ) );
+ EditPaM aPaM = pEditEngine->pImpEditEngine->GetPaM( aDocPos, FALSE );
+ return IsInSelection( aPaM );
+}
+
+BOOL ImpEditView::SetCursorAtPoint( const Point& rPointPixel )
+{
+ pEditEngine->pImpEditEngine->CheckIdleFormatter();
+
+ Point aMousePos( rPointPixel );
+
+ // Logische Einheiten...
+ aMousePos = GetWindow()->PixelToLogic( aMousePos );
+
+ if ( ( !GetOutputArea().IsInside( aMousePos ) ) && !pEditEngine->pImpEditEngine->IsInSelectionMode() )
+ {
+ return FALSE;
+ }
+
+ Point aDocPos( GetDocPos( aMousePos ) );
+
+ // Kann optimiert werden: Erst innerhalb eines Absatzes die Zeilen
+ // fuer den PaM durchwuehlen, dann nochmal mit dem PaM fuer das Rect,
+ // obwohl die Zeile schon bekannt ist....
+ // Das muss doch nicht sein !
+
+ EditPaM aPaM = pEditEngine->pImpEditEngine->GetPaM( aDocPos );
+ BOOL bGotoCursor = DoAutoScroll();
+
+ // aTmpNewSel: Diff zwischen alt und neu, nicht die neue Selektion
+ EditSelection aTmpNewSel( GetEditSelection().Max(), aPaM );
+
+ // --> OD 2005-12-16 #i27299#
+ // work on copy of current selection and set new selection, if it has changed.
+ EditSelection aNewEditSelection( GetEditSelection() );
+
+ aNewEditSelection.Max() = aPaM;
+ if ( !pEditEngine->pImpEditEngine->aSelEngine.HasAnchor() )
+ {
+ if ( aNewEditSelection.Min() != aPaM )
+ pEditEngine->pImpEditEngine->CursorMoved( aNewEditSelection.Min().GetNode() );
+ aNewEditSelection.Min() = aPaM;
+ }
+ else
+ {
+ DrawSelection( aTmpNewSel );
+ }
+
+ // set changed text selection
+ if ( GetEditSelection() != aNewEditSelection )
+ {
+ SetEditSelection( aNewEditSelection );
+ }
+ // <--
+
+ BOOL bForceCursor = ( pDragAndDropInfo ? FALSE : TRUE ) && !pEditEngine->pImpEditEngine->IsInSelectionMode();
+ ShowCursor( bGotoCursor, bForceCursor );
+ return TRUE;
+}
+
+
+void ImpEditView::HideDDCursor()
+{
+ if ( pDragAndDropInfo && pDragAndDropInfo->bVisCursor )
+ {
+ GetWindow()->DrawOutDev( pDragAndDropInfo->aCurSavedCursor.TopLeft(), pDragAndDropInfo->aCurSavedCursor.GetSize(),
+ Point(0,0), pDragAndDropInfo->aCurSavedCursor.GetSize(),*pDragAndDropInfo->pBackground );
+ pDragAndDropInfo->bVisCursor = sal_False;
+ }
+}
+
+void ImpEditView::ShowDDCursor( const Rectangle& rRect )
+{
+ if ( !pDragAndDropInfo->bVisCursor )
+ {
+ if ( pOutWin->GetCursor() )
+ pOutWin->GetCursor()->Hide();
+
+ Color aOldFillColor = GetWindow()->GetFillColor();
+ GetWindow()->SetFillColor( Color(4210752) ); // GRAY BRUSH_50, OLDSV, change to DDCursor!
+
+ // Hintergrund sichern...
+ Rectangle aSaveRec( GetWindow()->LogicToPixel( rRect ) );
+ // lieber etwas mehr sichern...
+ aSaveRec.Right() += 1;
+ aSaveRec.Bottom() += 1;
+
+ Size aNewSzPx( aSaveRec.GetSize() );
+ if ( !pDragAndDropInfo->pBackground )
+ {
+ pDragAndDropInfo->pBackground = new VirtualDevice( *GetWindow() );
+ MapMode aMapMode( GetWindow()->GetMapMode() );
+ aMapMode.SetOrigin( Point( 0, 0 ) );
+ pDragAndDropInfo->pBackground->SetMapMode( aMapMode );
+
+ }
+
+#ifdef DBG_UTIL
+ Size aCurSzPx( pDragAndDropInfo->pBackground->GetOutputSizePixel() );
+ if ( ( aCurSzPx.Width() < aNewSzPx.Width() ) ||( aCurSzPx.Height() < aNewSzPx.Height() ) )
+ {
+ sal_Bool bDone = pDragAndDropInfo->pBackground->SetOutputSizePixel( aNewSzPx );
+ DBG_ASSERT( bDone, "Virtuelles Device kaputt?" );
+ }
+#endif
+
+ aSaveRec = GetWindow()->PixelToLogic( aSaveRec );
+
+ pDragAndDropInfo->pBackground->DrawOutDev( Point(0,0), aSaveRec.GetSize(),
+ aSaveRec.TopLeft(), aSaveRec.GetSize(), *GetWindow() );
+ pDragAndDropInfo->aCurSavedCursor = aSaveRec;
+
+ // Cursor malen...
+ GetWindow()->DrawRect( rRect );
+
+ pDragAndDropInfo->bVisCursor = sal_True;
+ pDragAndDropInfo->aCurCursor = rRect;
+
+ GetWindow()->SetFillColor( aOldFillColor );
+ }
+}
+
+void ImpEditView::dragGestureRecognized( const ::com::sun::star::datatransfer::dnd::DragGestureEvent& rDGE ) throw (::com::sun::star::uno::RuntimeException)
+{
+ DBG_ASSERT( !pDragAndDropInfo, "dragGestureRecognized - DragAndDropInfo exist!" );
+
+ vos::OGuard aVclGuard( Application::GetSolarMutex() );
+
+ Point aMousePosPixel( rDGE.DragOriginX, rDGE.DragOriginY );
+
+ EditSelection aCopySel( GetEditSelection() );
+ aCopySel.Adjust( pEditEngine->pImpEditEngine->GetEditDoc() );
+
+ if ( GetEditSelection().HasRange() && bClickedInSelection )
+ {
+ pDragAndDropInfo = new DragAndDropInfo();
+ }
+ else
+ {
+ // Field?!
+ USHORT nPara, nPos;
+ Point aMousePos = GetWindow()->PixelToLogic( aMousePosPixel );
+ const SvxFieldItem* pField = GetField( aMousePos, &nPara, &nPos );
+ if ( pField )
+ {
+ pDragAndDropInfo = new DragAndDropInfo();
+ pDragAndDropInfo->pField = pField;
+ ContentNode* pNode = pEditEngine->pImpEditEngine->GetEditDoc().GetObject( nPara );
+ aCopySel = EditSelection( EditPaM( pNode, nPos ), EditPaM( pNode, nPos+1 ) );
+ GetEditSelection() = aCopySel;
+ DrawSelection();
+ BOOL bGotoCursor = DoAutoScroll();
+ BOOL bForceCursor = ( pDragAndDropInfo ? FALSE : TRUE ) && !pEditEngine->pImpEditEngine->IsInSelectionMode();
+ ShowCursor( bGotoCursor, bForceCursor );
+ }
+ else if ( IsBulletArea( aMousePos, &nPara ) )
+ {
+ pDragAndDropInfo = new DragAndDropInfo();
+ pDragAndDropInfo->bOutlinerMode = TRUE;
+ EditPaM aStartPaM( pEditEngine->pImpEditEngine->GetEditDoc().GetObject( nPara ), 0 );
+ EditPaM aEndPaM( aStartPaM );
+ const SfxInt16Item& rLevel = (const SfxInt16Item&) pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL );
+ for ( USHORT n = nPara +1; n < pEditEngine->pImpEditEngine->GetEditDoc().Count(); n++ )
+ {
+ const SfxInt16Item& rL = (const SfxInt16Item&) pEditEngine->GetParaAttrib( n, EE_PARA_OUTLLEVEL );
+ if ( rL.GetValue() > rLevel.GetValue() )
+ {
+ aEndPaM.SetNode( pEditEngine->pImpEditEngine->GetEditDoc().GetObject( n ) );
+ }
+ else
+ {
+ break;
+ }
+ }
+ aEndPaM.GetIndex() = aEndPaM.GetNode()->Len();
+ SetEditSelection( EditSelection( aStartPaM, aEndPaM ) );
+ }
+ }
+
+ if ( pDragAndDropInfo )
+ {
+
+ pDragAndDropInfo->bStarterOfDD = sal_True;
+
+ // Sensibler Bereich, wo gescrollt werden soll.
+ Size aSz( 5, 0 );
+ aSz = GetWindow()->PixelToLogic( aSz );
+ pDragAndDropInfo->nSensibleRange = (sal_uInt16) aSz.Width();
+ pDragAndDropInfo->nCursorWidth = (sal_uInt16) aSz.Width() / 2;
+ pDragAndDropInfo->aBeginDragSel = pEditEngine->pImpEditEngine->CreateESel( aCopySel );
+
+ uno::Reference< datatransfer::XTransferable > xData = pEditEngine->pImpEditEngine->CreateTransferable( aCopySel );
+
+ sal_Int8 nActions = bReadOnly ? datatransfer::dnd::DNDConstants::ACTION_COPY : datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE;
+
+ rDGE.DragSource->startDrag( rDGE, nActions, 0 /*cursor*/, 0 /*image*/, xData, mxDnDListener );
+ // Falls Drag&Move in einer Engine, muessen Copy&Del geklammert sein!
+ GetCursor()->Hide();
+
+ }
+}
+
+void ImpEditView::dragDropEnd( const ::com::sun::star::datatransfer::dnd::DragSourceDropEvent& rDSDE ) throw (::com::sun::star::uno::RuntimeException)
+{
+ vos::OGuard aVclGuard( Application::GetSolarMutex() );
+
+ DBG_ASSERT( pDragAndDropInfo, "ImpEditView::dragDropEnd: pDragAndDropInfo is NULL!" );
+
+ // #123688# Shouldn't happen, but seems to happen...
+ if ( pDragAndDropInfo )
+ {
+ if ( !bReadOnly && rDSDE.DropSuccess && !pDragAndDropInfo->bOutlinerMode && ( rDSDE.DropAction & datatransfer::dnd::DNDConstants::ACTION_MOVE ) )
+ {
+ if ( pDragAndDropInfo->bStarterOfDD && pDragAndDropInfo->bDroppedInMe )
+ {
+ // DropPos: Wohin wurde gedroppt, unabhaengig von laenge.
+ ESelection aDropPos( pDragAndDropInfo->aDropSel.nStartPara, pDragAndDropInfo->aDropSel.nStartPos, pDragAndDropInfo->aDropSel.nStartPara, pDragAndDropInfo->aDropSel.nStartPos );
+ ESelection aToBeDelSel = pDragAndDropInfo->aBeginDragSel;
+ ESelection aNewSel( pDragAndDropInfo->aDropSel.nEndPara, pDragAndDropInfo->aDropSel.nEndPos,
+ pDragAndDropInfo->aDropSel.nEndPara, pDragAndDropInfo->aDropSel.nEndPos );
+ sal_Bool bBeforeSelection = aDropPos.IsLess( pDragAndDropInfo->aBeginDragSel );
+ sal_uInt16 nParaDiff = pDragAndDropInfo->aBeginDragSel.nEndPara - pDragAndDropInfo->aBeginDragSel.nStartPara;
+ if ( bBeforeSelection )
+ {
+ // aToBeDelSel anpassen.
+ DBG_ASSERT( pDragAndDropInfo->aBeginDragSel.nStartPara >= pDragAndDropInfo->aDropSel.nStartPara, "Doch nicht davor?" );
+ aToBeDelSel.nStartPara = aToBeDelSel.nStartPara + nParaDiff;
+ aToBeDelSel.nEndPara = aToBeDelSel.nEndPara + nParaDiff;
+ // Zeichen korrigieren?
+ if ( aToBeDelSel.nStartPara == pDragAndDropInfo->aDropSel.nEndPara )
+ {
+ sal_uInt16 nMoreChars;
+ if ( pDragAndDropInfo->aDropSel.nStartPara == pDragAndDropInfo->aDropSel.nEndPara )
+ nMoreChars = pDragAndDropInfo->aDropSel.nEndPos - pDragAndDropInfo->aDropSel.nStartPos;
+ else
+ nMoreChars = pDragAndDropInfo->aDropSel.nEndPos;
+ aToBeDelSel.nStartPos =
+ aToBeDelSel.nStartPos + nMoreChars;
+ if ( aToBeDelSel.nStartPara == aToBeDelSel.nEndPara )
+ aToBeDelSel.nEndPos =
+ aToBeDelSel.nEndPos + nMoreChars;
+ }
+ }
+ else
+ {
+ // aToBeDelSel ist ok, aber Selektion der View
+ // muss angepasst werden, wenn davor geloescht wird!
+ DBG_ASSERT( pDragAndDropInfo->aBeginDragSel.nStartPara <= pDragAndDropInfo->aDropSel.nStartPara, "Doch nicht davor?" );
+ aNewSel.nStartPara = aNewSel.nStartPara - nParaDiff;
+ aNewSel.nEndPara = aNewSel.nEndPara - nParaDiff;
+ // Zeichen korrigieren?
+ if ( pDragAndDropInfo->aBeginDragSel.nEndPara == pDragAndDropInfo->aDropSel.nStartPara )
+ {
+ sal_uInt16 nLessChars;
+ if ( pDragAndDropInfo->aBeginDragSel.nStartPara == pDragAndDropInfo->aBeginDragSel.nEndPara )
+ nLessChars = pDragAndDropInfo->aBeginDragSel.nEndPos - pDragAndDropInfo->aBeginDragSel.nStartPos;
+ else
+ nLessChars = pDragAndDropInfo->aBeginDragSel.nEndPos;
+ aNewSel.nStartPos = aNewSel.nStartPos - nLessChars;
+ if ( aNewSel.nStartPara == aNewSel.nEndPara )
+ aNewSel.nEndPos = aNewSel.nEndPos - nLessChars;
+ }
+ }
+
+ DrawSelection();
+ EditSelection aDelSel( pEditEngine->pImpEditEngine->CreateSel( aToBeDelSel ) );
+ DBG_ASSERT( !aDelSel.DbgIsBuggy( pEditEngine->pImpEditEngine->aEditDoc ), "ToBeDel ist buggy!" );
+ pEditEngine->pImpEditEngine->ImpDeleteSelection( aDelSel );
+ if ( !bBeforeSelection )
+ {
+ DBG_ASSERT( !pEditEngine->pImpEditEngine->CreateSel( aNewSel ).DbgIsBuggy(pEditEngine->pImpEditEngine->aEditDoc), "Bad" );
+ SetEditSelection( pEditEngine->pImpEditEngine->CreateSel( aNewSel ) );
+ }
+ pEditEngine->pImpEditEngine->FormatAndUpdate( pEditEngine->pImpEditEngine->GetActiveView() );
+ DrawSelection();
+ }
+ else
+ {
+ // andere EditEngine...
+ if ( pEditEngine->pImpEditEngine->ImplHasText() ) // #88630# SC ist removing the content when switching the task
+ DeleteSelected();
+ }
+ }
+
+ if ( pDragAndDropInfo->bUndoAction )
+ pEditEngine->pImpEditEngine->UndoActionEnd( EDITUNDO_DRAGANDDROP );
+
+ HideDDCursor();
+ ShowCursor( DoAutoScroll(), TRUE );
+ delete pDragAndDropInfo;
+ pDragAndDropInfo = NULL;
+ pEditEngine->GetEndDropHdl().Call(GetEditViewPtr());
+ }
+}
+
+void ImpEditView::drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException)
+{
+ vos::OGuard aVclGuard( Application::GetSolarMutex() );
+
+ DBG_ASSERT( pDragAndDropInfo, "Drop - No Drag&Drop info?!" );
+
+ if ( pDragAndDropInfo->bDragAccepted )
+ {
+ pEditEngine->GetBeginDropHdl().Call(GetEditViewPtr());
+ BOOL bChanges = FALSE;
+
+ HideDDCursor();
+
+ if ( pDragAndDropInfo->bStarterOfDD )
+ {
+ pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_DRAGANDDROP );
+ pDragAndDropInfo->bUndoAction = TRUE;
+ }
+
+ if ( pDragAndDropInfo->bOutlinerMode )
+ {
+ bChanges = TRUE;
+ GetEditViewPtr()->MoveParagraphs( Range( pDragAndDropInfo->aBeginDragSel.nStartPara, pDragAndDropInfo->aBeginDragSel.nEndPara ), pDragAndDropInfo->nOutlinerDropDest );
+ }
+ else
+ {
+ uno::Reference< datatransfer::XTransferable > xDataObj = rDTDE.Transferable;
+ if ( xDataObj.is() )
+ {
+ bChanges = TRUE;
+ // Selektion wegmalen...
+ DrawSelection();
+ EditPaM aPaM( pDragAndDropInfo->aDropDest );
+
+ PasteOrDropInfos aPasteOrDropInfos;
+ aPasteOrDropInfos.nAction = EE_ACTION_DROP;
+ aPasteOrDropInfos.nStartPara = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( aPaM.GetNode() );
+ pEditEngine->pImpEditEngine->aBeginPasteOrDropHdl.Call( &aPasteOrDropInfos );
+
+ EditSelection aNewSel = pEditEngine->pImpEditEngine->InsertText( xDataObj, String(), aPaM, pEditEngine->pImpEditEngine->GetStatus().AllowPasteSpecial() );
+
+ aPasteOrDropInfos.nEndPara = pEditEngine->pImpEditEngine->GetEditDoc().GetPos( aNewSel.Max().GetNode() );
+ pEditEngine->pImpEditEngine->aEndPasteOrDropHdl.Call( &aPasteOrDropInfos );
+
+ SetEditSelection( aNewSel );
+ pEditEngine->pImpEditEngine->FormatAndUpdate( pEditEngine->pImpEditEngine->GetActiveView() );
+ if ( pDragAndDropInfo->bStarterOfDD )
+ {
+ // Nur dann setzen, wenn in gleicher Engine!
+ pDragAndDropInfo->aDropSel.nStartPara = pEditEngine->pImpEditEngine->aEditDoc.GetPos( aPaM.GetNode() );
+ pDragAndDropInfo->aDropSel.nStartPos = aPaM.GetIndex();
+ pDragAndDropInfo->aDropSel.nEndPara = pEditEngine->pImpEditEngine->aEditDoc.GetPos( aNewSel.Max().GetNode() );
+ pDragAndDropInfo->aDropSel.nEndPos = aNewSel.Max().GetIndex();
+ pDragAndDropInfo->bDroppedInMe = sal_True;
+ }
+ }
+ }
+
+ if ( bChanges )
+ {
+ rDTDE.Context->acceptDrop( rDTDE.DropAction );
+ }
+
+ if ( !pDragAndDropInfo->bStarterOfDD )
+ {
+ delete pDragAndDropInfo;
+ pDragAndDropInfo = NULL;
+ }
+
+ rDTDE.Context->dropComplete( bChanges );
+ }
+}
+
+void ImpEditView::dragEnter( const ::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent& rDTDEE ) throw (::com::sun::star::uno::RuntimeException)
+{
+ vos::OGuard aVclGuard( Application::GetSolarMutex() );
+
+ if ( !pDragAndDropInfo )
+ pDragAndDropInfo = new DragAndDropInfo( );
+
+ pDragAndDropInfo->bHasValidData = sal_False;
+
+ // Check for supported format...
+ // Only check for text, will also be there if bin or rtf
+ datatransfer::DataFlavor aTextFlavor;
+ SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aTextFlavor );
+ const ::com::sun::star::datatransfer::DataFlavor* pFlavors = rDTDEE.SupportedDataFlavors.getConstArray();
+ int nFlavors = rDTDEE.SupportedDataFlavors.getLength();
+ for ( int n = 0; n < nFlavors; n++ )
+ {
+ if( TransferableDataHelper::IsEqual( pFlavors[n], aTextFlavor ) )
+ {
+ pDragAndDropInfo->bHasValidData = sal_True;
+ break;
+ }
+ }
+
+ dragOver( rDTDEE );
+}
+
+void ImpEditView::dragExit( const ::com::sun::star::datatransfer::dnd::DropTargetEvent& ) throw (::com::sun::star::uno::RuntimeException)
+{
+ vos::OGuard aVclGuard( Application::GetSolarMutex() );
+
+ HideDDCursor();
+
+ if ( !pDragAndDropInfo->bStarterOfDD )
+ {
+ delete pDragAndDropInfo;
+ pDragAndDropInfo = NULL;
+ }
+}
+
+void ImpEditView::dragOver( const ::com::sun::star::datatransfer::dnd::DropTargetDragEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException)
+{
+ vos::OGuard aVclGuard( Application::GetSolarMutex() );
+
+ Point aMousePos( rDTDE.LocationX, rDTDE.LocationY );
+ aMousePos = GetWindow()->PixelToLogic( aMousePos );
+
+ sal_Bool bAccept = sal_False;
+
+ if ( GetOutputArea().IsInside( aMousePos ) && !bReadOnly )
+ {
+// sal_Int8 nSupportedActions = bReadOnly ? datatransfer::dnd::DNDConstants::ACTION_COPY : datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE;
+
+ if ( pDragAndDropInfo->bHasValidData /* && ( nSupportedActions & rDTDE.DropAction ) MT: Default = 0x80 ?! */ )
+ {
+ bAccept = sal_True;
+
+ sal_Bool bAllowScroll = DoAutoScroll();
+ if ( bAllowScroll )
+ {
+ long nScrollX = 0;
+ long nScrollY = 0;
+ // pruefen, ob im sensitiven Bereich
+ if ( ( (aMousePos.X()-pDragAndDropInfo->nSensibleRange) < GetOutputArea().Left() ) && ( ( aMousePos.X() + pDragAndDropInfo->nSensibleRange ) > GetOutputArea().Left() ) )
+ nScrollX = GetOutputArea().GetWidth() / SCRLRANGE;
+ else if ( ( (aMousePos.X()+pDragAndDropInfo->nSensibleRange) > GetOutputArea().Right() ) && ( ( aMousePos.X() - pDragAndDropInfo->nSensibleRange ) < GetOutputArea().Right() ) )
+ nScrollX = -( GetOutputArea().GetWidth() / SCRLRANGE );
+
+ if ( ( (aMousePos.Y()-pDragAndDropInfo->nSensibleRange) < GetOutputArea().Top() ) && ( ( aMousePos.Y() + pDragAndDropInfo->nSensibleRange ) > GetOutputArea().Top() ) )
+ nScrollY = GetOutputArea().GetHeight() / SCRLRANGE;
+ else if ( ( (aMousePos.Y()+pDragAndDropInfo->nSensibleRange) > GetOutputArea().Bottom() ) && ( ( aMousePos.Y() - pDragAndDropInfo->nSensibleRange ) < GetOutputArea().Bottom() ) )
+ nScrollY = -( GetOutputArea().GetHeight() / SCRLRANGE );
+
+ if ( nScrollX || nScrollY )
+ {
+ HideDDCursor();
+ Scroll( nScrollX, nScrollY, RGCHK_PAPERSZ1 );
+ }
+ }
+
+ Point aDocPos( GetDocPos( aMousePos ) );
+ EditPaM aPaM = pEditEngine->pImpEditEngine->GetPaM( aDocPos );
+ pDragAndDropInfo->aDropDest = aPaM;
+ if ( pDragAndDropInfo->bOutlinerMode )
+ {
+ USHORT nPara = pEditEngine->pImpEditEngine->aEditDoc.GetPos( aPaM.GetNode() );
+ ParaPortion* pPPortion = pEditEngine->pImpEditEngine->GetParaPortions().SaveGetObject( nPara );
+ long nDestParaStartY = pEditEngine->pImpEditEngine->GetParaPortions().GetYOffset( pPPortion );
+ long nRel = aDocPos.Y() - nDestParaStartY;
+ if ( nRel < ( pPPortion->GetHeight() / 2 ) )
+ {
+ pDragAndDropInfo->nOutlinerDropDest = nPara;
+ }
+ else
+ {
+ pDragAndDropInfo->nOutlinerDropDest = nPara+1;
+ }
+
+ if( ( pDragAndDropInfo->nOutlinerDropDest >= pDragAndDropInfo->aBeginDragSel.nStartPara ) &&
+ ( pDragAndDropInfo->nOutlinerDropDest <= (pDragAndDropInfo->aBeginDragSel.nEndPara+1) ) )
+ {
+ bAccept = FALSE;
+ }
+ }
+ else if ( HasSelection() )
+ {
+ // es darf nicht in eine Selektion gedroppt werden
+ EPaM aP = pEditEngine->pImpEditEngine->CreateEPaM( aPaM );
+ ESelection aDestSel( aP.nPara, aP.nIndex, aP.nPara, aP.nIndex);
+ ESelection aCurSel = pEditEngine->pImpEditEngine->CreateESel( GetEditSelection() );
+ aCurSel.Adjust();
+ if ( !aDestSel.IsLess( aCurSel ) && !aDestSel.IsGreater( aCurSel ) )
+ {
+ bAccept = FALSE;
+ }
+ }
+ if ( bAccept )
+ {
+ Rectangle aEditCursor;
+ if ( pDragAndDropInfo->bOutlinerMode )
+ {
+ long nDDYPos;
+ if ( pDragAndDropInfo->nOutlinerDropDest < pEditEngine->pImpEditEngine->GetEditDoc().Count() )
+ {
+ ParaPortion* pPPortion = pEditEngine->pImpEditEngine->GetParaPortions().SaveGetObject( pDragAndDropInfo->nOutlinerDropDest );
+ nDDYPos = pEditEngine->pImpEditEngine->GetParaPortions().GetYOffset( pPPortion );
+ }
+ else
+ {
+ nDDYPos = pEditEngine->pImpEditEngine->GetTextHeight();
+ }
+ Point aStartPos( 0, nDDYPos );
+ aStartPos = GetWindowPos( aStartPos );
+ Point aEndPos( GetOutputArea().GetWidth(), nDDYPos );
+ aEndPos = GetWindowPos( aEndPos );
+ aEditCursor = GetWindow()->LogicToPixel( Rectangle( aStartPos, aEndPos ) );
+ if ( !pEditEngine->IsVertical() )
+ {
+ aEditCursor.Top()--;
+ aEditCursor.Bottom()++;
+ }
+ else
+ {
+ aEditCursor.Left()--;
+ aEditCursor.Right()++;
+ }
+ aEditCursor = GetWindow()->PixelToLogic( aEditCursor );
+ }
+ else
+ {
+ aEditCursor = pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM );
+ Point aTopLeft( GetWindowPos( aEditCursor.TopLeft() ) );
+ aEditCursor.SetPos( aTopLeft );
+ aEditCursor.Right() = aEditCursor.Left() + pDragAndDropInfo->nCursorWidth;
+ aEditCursor = GetWindow()->LogicToPixel( aEditCursor );
+ aEditCursor = GetWindow()->PixelToLogic( aEditCursor );
+ }
+
+ sal_Bool bCursorChanged = !pDragAndDropInfo->bVisCursor || ( pDragAndDropInfo->aCurCursor != aEditCursor );
+ if ( bCursorChanged )
+ {
+ HideDDCursor();
+ ShowDDCursor(aEditCursor );
+ }
+ pDragAndDropInfo->bDragAccepted = TRUE;
+ rDTDE.Context->acceptDrag( rDTDE.DropAction );
+ }
+ }
+ }
+
+ if ( !bAccept )
+ {
+ HideDDCursor();
+ pDragAndDropInfo->bDragAccepted = FALSE;
+ rDTDE.Context->rejectDrag();
+ }
+}
+
+void ImpEditView::AddDragAndDropListeners()
+{
+ Window* pWindow = GetWindow();
+ if ( !bActiveDragAndDropListener && pWindow && pWindow->GetDragGestureRecognizer().is() )
+ {
+ vcl::unohelper::DragAndDropWrapper* pDnDWrapper = new vcl::unohelper::DragAndDropWrapper( this );
+ mxDnDListener = pDnDWrapper;
+
+ uno::Reference< datatransfer::dnd::XDragGestureListener> xDGL( mxDnDListener, uno::UNO_QUERY );
+ pWindow->GetDragGestureRecognizer()->addDragGestureListener( xDGL );
+ uno::Reference< datatransfer::dnd::XDropTargetListener> xDTL( xDGL, uno::UNO_QUERY );
+ pWindow->GetDropTarget()->addDropTargetListener( xDTL );
+ pWindow->GetDropTarget()->setActive( sal_True );
+ pWindow->GetDropTarget()->setDefaultActions( datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE );
+
+ bActiveDragAndDropListener = TRUE;
+ }
+}
+
+void ImpEditView::RemoveDragAndDropListeners()
+{
+ if ( bActiveDragAndDropListener && GetWindow() && GetWindow()->GetDragGestureRecognizer().is() )
+ {
+ uno::Reference< datatransfer::dnd::XDragGestureListener> xDGL( mxDnDListener, uno::UNO_QUERY );
+ GetWindow()->GetDragGestureRecognizer()->removeDragGestureListener( xDGL );
+ uno::Reference< datatransfer::dnd::XDropTargetListener> xDTL( xDGL, uno::UNO_QUERY );
+ GetWindow()->GetDropTarget()->removeDropTargetListener( xDTL );
+
+ if ( mxDnDListener.is() )
+ {
+ uno::Reference< lang::XEventListener> xEL( mxDnDListener, uno::UNO_QUERY );
+ xEL->disposing( lang::EventObject() ); // #95154# Empty Source means it's the Client
+ mxDnDListener.clear();
+ }
+
+ bActiveDragAndDropListener = FALSE;
+ }
+}
diff --git a/editeng/source/editeng/impedit.hxx b/editeng/source/editeng/impedit.hxx
new file mode 100644
index 000000000000..3bacfc949e3b
--- /dev/null
+++ b/editeng/source/editeng/impedit.hxx
@@ -0,0 +1,1208 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+#ifndef _IMPEDIT_HXX
+#define _IMPEDIT_HXX
+
+#include <editdoc.hxx>
+#include <editsel.hxx>
+#include <editundo.hxx>
+#include <editobj2.hxx>
+#include <editstt2.hxx>
+#include <editeng/editdata.hxx>
+#include <editeng/svxacorr.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/cursor.hxx>
+
+#include <vcl/dndhelp.hxx>
+#include <svl/ondemand.hxx>
+#include <com/sun/star/linguistic2/XSpellAlternatives.hpp>
+#include <com/sun/star/linguistic2/SpellFailure.hpp>
+#include <com/sun/star/linguistic2/XSpellChecker.hpp>
+#include <com/sun/star/linguistic2/XSpellChecker1.hpp>
+#include <com/sun/star/linguistic2/XHyphenator.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/i18n/XBreakIterator.hpp>
+#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
+#include <com/sun/star/i18n/WordType.hpp>
+#include <com/sun/star/i18n/XExtendedInputSequenceChecker.hpp>
+
+#include <i18npool/lang.h>
+#include <vos/ref.hxx>
+
+DBG_NAMEEX( EditView )
+DBG_NAMEEX( EditEngine )
+
+#define PIMPEE pImpEditView->pEditEngine->pImpEditEngine
+
+#define DEL_LEFT 1
+#define DEL_RIGHT 2
+#define TRAVEL_X_DONTKNOW 0xFFFFFFFF
+#define CURSOR_BIDILEVEL_DONTKNOW 0xFFFF
+#define MAXCHARSINPARA 0x3FFF-CHARPOSGROW // Max 16K, because WYSIWYG array
+
+#define ATTRSPECIAL_WHOLEWORD 1
+#define ATTRSPECIAL_EDGE 2
+
+#define GETCRSR_TXTONLY 0x0001
+#define GETCRSR_STARTOFLINE 0x0002
+#define GETCRSR_ENDOFLINE 0x0004
+#define GETCRSR_PREFERPORTIONSTART 0x0008
+
+#define LINE_SEP 0x0A
+
+typedef EENotify* EENotifyPtr;
+SV_DECL_PTRARR_DEL( NotifyList, EENotifyPtr, 1, 1 ) // IMPL is in outliner.cxx, move to EE later and share declaration, or use BlockNotifications from EE directly
+
+
+class EditView;
+class EditEngine;
+class SvxFontTable;
+class SvxColorList;
+
+class SvxSearchItem;
+class SvxLRSpaceItem;
+class TextRanger;
+class SvKeyValueIterator;
+class SvxForbiddenCharactersTable;
+class SvtCTLOptions;
+#include <editeng/SpellPortions.hxx>
+
+#include <editeng/eedata.hxx>
+
+class SvUShorts;
+class SvxNumberFormat;
+
+
+namespace com {
+namespace sun {
+namespace star {
+namespace datatransfer {
+namespace clipboard {
+ class XClipboard;
+}}}}}
+
+namespace svtools {
+ class ColorConfig;
+}
+
+struct DragAndDropInfo
+{
+ Rectangle aCurCursor;
+ Rectangle aCurSavedCursor;
+ sal_uInt16 nSensibleRange;
+ sal_uInt16 nCursorWidth;
+ ESelection aBeginDragSel;
+ EditPaM aDropDest;
+ USHORT nOutlinerDropDest;
+ ESelection aDropSel;
+ VirtualDevice* pBackground;
+ const SvxFieldItem* pField;
+ sal_Bool bVisCursor : 1;
+ sal_Bool bDroppedInMe : 1;
+ sal_Bool bStarterOfDD : 1;
+ sal_Bool bHasValidData : 1;
+ sal_Bool bUndoAction : 1;
+ sal_Bool bOutlinerMode : 1;
+ sal_Bool bDragAccepted : 1;
+
+ DragAndDropInfo()
+ {
+ pBackground = NULL; bVisCursor = sal_False; bDroppedInMe = sal_False; bStarterOfDD = sal_False;
+ bHasValidData = sal_False; bUndoAction = sal_False; bOutlinerMode = sal_False;
+ nSensibleRange = 0; nCursorWidth = 0; pField = 0; nOutlinerDropDest = 0; bDragAccepted = sal_False;
+ }
+};
+
+struct ImplIMEInfos
+{
+ String aOldTextAfterStartPos;
+ sal_uInt16* pAttribs;
+ EditPaM aPos;
+ sal_uInt16 nLen;
+ sal_Bool bCursor;
+ sal_Bool bWasCursorOverwrite;
+
+ ImplIMEInfos( const EditPaM& rPos, const String& rOldTextAfterStartPos );
+ ~ImplIMEInfos();
+
+ void CopyAttribs( const sal_uInt16* pA, sal_uInt16 nL );
+ void DestroyAttribs();
+};
+
+// #i18881# to be able to identify the postions of changed words
+// the positions of each portion need to be saved
+typedef std::vector<EditSelection> SpellContentSelections;
+
+struct SpellInfo
+{
+ EESpellState eState;
+ EPaM aSpellStart;
+ EPaM aSpellTo;
+ sal_Bool bSpellToEnd;
+ sal_Bool bMultipleDoc;
+ ::svx::SpellPortions aLastSpellPortions;
+ SpellContentSelections aLastSpellContentSelections;
+ SpellInfo()
+ { bSpellToEnd = sal_True; eState = EE_SPELL_OK; bMultipleDoc = sal_False; }
+};
+
+// used for text conversion
+struct ConvInfo
+{
+ EPaM aConvStart;
+ EPaM aConvTo;
+ EPaM aConvContinue; // position to start search for next text portion (word) with
+ sal_Bool bConvToEnd;
+ sal_Bool bMultipleDoc;
+
+ ConvInfo() { bConvToEnd = sal_True; bMultipleDoc = sal_False; }
+};
+
+struct FormatterFontMetric
+{
+ sal_uInt16 nMaxAscent;
+ sal_uInt16 nMaxDescent;
+
+ FormatterFontMetric() { nMaxAscent = 0; nMaxDescent = 0; /* nMinLeading = 0xFFFF; */ }
+ sal_uInt16 GetHeight() const { return nMaxAscent+nMaxDescent; }
+};
+
+class IdleFormattter : public Timer
+{
+private:
+ EditView* pView;
+ int nRestarts;
+
+public:
+ IdleFormattter();
+ ~IdleFormattter();
+
+ void DoIdleFormat( EditView* pV );
+ void ForceTimeout();
+ void ResetRestarts() { nRestarts = 0; }
+ EditView* GetView() { return pView; }
+};
+
+ // ----------------------------------------------------------------------
+// class ImpEditView
+// ----------------------------------------------------------------------
+class ImpEditView : public vcl::unohelper::DragAndDropClient
+{
+ friend class EditView;
+ friend class EditEngine;
+ friend class ImpEditEngine;
+ using vcl::unohelper::DragAndDropClient::dragEnter;
+ using vcl::unohelper::DragAndDropClient::dragExit;
+ using vcl::unohelper::DragAndDropClient::dragOver;
+
+private:
+ EditView* pEditView;
+ Cursor* pCursor;
+ Color* pBackgroundColor;
+ EditEngine* pEditEngine;
+ Window* pOutWin;
+ Pointer* pPointer;
+ DragAndDropInfo* pDragAndDropInfo;
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::dnd::XDragSourceListener > mxDnDListener;
+
+
+ long nInvMore;
+ ULONG nControl;
+ sal_uInt32 nTravelXPos;
+ sal_uInt16 nExtraCursorFlags;
+ sal_uInt16 nCursorBidiLevel;
+ sal_uInt16 nScrollDiffX;
+ sal_Bool bReadOnly;
+ sal_Bool bClickedInSelection;
+ sal_Bool bActiveDragAndDropListener;
+
+ Point aAnchorPoint;
+ Rectangle aOutArea;
+ Point aVisDocStartPos;
+ EESelectionMode eSelectionMode;
+ EditSelection aEditSelection;
+ EVAnchorMode eAnchorMode;
+
+protected:
+
+ // DragAndDropClient
+ void dragGestureRecognized( const ::com::sun::star::datatransfer::dnd::DragGestureEvent& dge ) throw (::com::sun::star::uno::RuntimeException);
+ void dragDropEnd( const ::com::sun::star::datatransfer::dnd::DragSourceDropEvent& dsde ) throw (::com::sun::star::uno::RuntimeException);
+ void drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEvent& dtde ) throw (::com::sun::star::uno::RuntimeException);
+ void dragEnter( const ::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent& dtdee ) throw (::com::sun::star::uno::RuntimeException);
+ void dragExit( const ::com::sun::star::datatransfer::dnd::DropTargetEvent& dte ) throw (::com::sun::star::uno::RuntimeException);
+ void dragOver( const ::com::sun::star::datatransfer::dnd::DropTargetDragEvent& dtde ) throw (::com::sun::star::uno::RuntimeException);
+
+ void ShowDDCursor( const Rectangle& rRect );
+ void HideDDCursor();
+
+ void ImplDrawHighlightRect( Window* pOutWin, const Point& rDocPosTopLeft, const Point& rDocPosBottomRight, PolyPolygon* pPolyPoly );
+
+public:
+ ImpEditView( EditView* pView, EditEngine* pEng, Window* pWindow );
+ ~ImpEditView();
+
+ EditView* GetEditViewPtr() { return pEditView; }
+
+ sal_uInt16 GetScrollDiffX() const { return nScrollDiffX; }
+ void SetScrollDiffX( sal_uInt16 n ) { nScrollDiffX = n; }
+
+ sal_uInt16 GetCursorBidiLevel() const { return nCursorBidiLevel; }
+ void SetCursorBidiLevel( sal_uInt16 n ) { nCursorBidiLevel = n; }
+
+ Point GetDocPos( const Point& rWindowPos ) const;
+ Point GetWindowPos( const Point& rDocPos ) const;
+ Rectangle GetWindowPos( const Rectangle& rDocPos ) const;
+
+ void SetOutputArea( const Rectangle& rRec );
+ void ResetOutputArea( const Rectangle& rRec );
+ const Rectangle& GetOutputArea() const { return aOutArea; }
+
+ BOOL IsVertical() const;
+
+ BOOL PostKeyEvent( const KeyEvent& rKeyEvent );
+
+ BOOL MouseButtonUp( const MouseEvent& rMouseEvent );
+ BOOL MouseButtonDown( const MouseEvent& rMouseEvent );
+ BOOL MouseMove( const MouseEvent& rMouseEvent );
+ void Command( const CommandEvent& rCEvt );
+
+ void CutCopy( ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboard >& rxClipboard, sal_Bool bCut );
+ void Paste( ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboard >& rxClipboard, sal_Bool bUseSpecial = sal_False );
+
+ void SetVisDocStartPos( const Point& rPos ) { aVisDocStartPos = rPos; }
+ const Point& GetVisDocStartPos() const { return aVisDocStartPos; }
+
+ long GetVisDocLeft() const { return aVisDocStartPos.X(); }
+ long GetVisDocTop() const { return aVisDocStartPos.Y(); }
+ long GetVisDocRight() const { return aVisDocStartPos.X() + ( !IsVertical() ? aOutArea.GetWidth() : aOutArea.GetHeight() ); }
+ long GetVisDocBottom() const { return aVisDocStartPos.Y() + ( !IsVertical() ? aOutArea.GetHeight() : aOutArea.GetWidth() ); }
+ Rectangle GetVisDocArea() const;
+
+ EditSelection& GetEditSelection() { return aEditSelection; }
+ void SetEditSelection( const EditSelection& rEditSelection );
+ sal_Bool HasSelection() const { return aEditSelection.HasRange(); }
+
+ void DrawSelection() { DrawSelection( aEditSelection ); }
+ void DrawSelection( EditSelection, Region* pRegion = NULL );
+ Region* CalcSelectedRegion();
+
+ Window* GetWindow() const { return pOutWin; }
+
+ EESelectionMode GetSelectionMode() const { return eSelectionMode; }
+ void SetSelectionMode( EESelectionMode eMode );
+
+ inline void SetPointer( const Pointer& rPointer );
+ inline const Pointer& GetPointer();
+
+ inline void SetCursor( const Cursor& rCursor );
+ inline Cursor* GetCursor();
+
+ void AddDragAndDropListeners();
+ void RemoveDragAndDropListeners();
+
+ BOOL IsBulletArea( const Point& rPos, sal_uInt16* pPara );
+
+// Fuer die SelectionEngine...
+ void CreateAnchor();
+ void DeselectAll();
+ sal_Bool SetCursorAtPoint( const Point& rPointPixel );
+ sal_Bool IsSelectionAtPoint( const Point& rPosPixel );
+ sal_Bool IsInSelection( const EditPaM& rPaM );
+
+
+ void SetAnchorMode( EVAnchorMode eMode );
+ EVAnchorMode GetAnchorMode() const { return eAnchorMode; }
+ void CalcAnchorPoint();
+ void RecalcOutputArea();
+
+ void ShowCursor( sal_Bool bGotoCursor, sal_Bool bForceVisCursor, BOOL test );
+ void ShowCursor( sal_Bool bGotoCursor, sal_Bool bForceVisCursor, USHORT nShowCursorFlags = 0 );
+ Pair Scroll( long ndX, long ndY, BYTE nRangeCheck = RGCHK_NEG );
+
+ void SetInsertMode( sal_Bool bInsert );
+ sal_Bool IsInsertMode() const { return ( ( nControl & EV_CNTRL_OVERWRITE ) == 0 ); }
+
+ void EnablePaste( sal_Bool bEnable ) { SetFlags( nControl, EV_CNTRL_ENABLEPASTE, bEnable ); }
+ sal_Bool IsPasteEnabled() const { return ( ( nControl & EV_CNTRL_ENABLEPASTE ) != 0 ); }
+
+ sal_Bool DoSingleLinePaste() const { return ( ( nControl & EV_CNTRL_SINGLELINEPASTE ) != 0 ); }
+ sal_Bool DoAutoScroll() const { return ( ( nControl & EV_CNTRL_AUTOSCROLL ) != 0 ); }
+ sal_Bool DoBigScroll() const { return ( ( nControl & EV_CNTRL_BIGSCROLL ) != 0 ); }
+ sal_Bool DoAutoSize() const { return ( ( nControl & EV_CNTRL_AUTOSIZE ) != 0 ); }
+ sal_Bool DoAutoWidth() const { return ( ( nControl & EV_CNTRL_AUTOSIZEX) != 0 ); }
+ sal_Bool DoAutoHeight() const { return ( ( nControl & EV_CNTRL_AUTOSIZEY) != 0 ); }
+ sal_Bool DoInvalidateMore() const { return ( ( nControl & EV_CNTRL_INVONEMORE ) != 0 ); }
+
+ void SetBackgroundColor( const Color& rColor );
+ const Color& GetBackgroundColor() const {
+ return ( pBackgroundColor ? *pBackgroundColor : pOutWin->GetBackground().GetColor() ); }
+
+ sal_Bool IsWrongSpelledWord( const EditPaM& rPaM, sal_Bool bMarkIfWrong );
+ String SpellIgnoreOrAddWord( sal_Bool bAdd );
+
+ const SvxFieldItem* GetField( const Point& rPos, sal_uInt16* pPara, sal_uInt16* pPos ) const;
+ void DeleteSelected();
+
+ // Ggf. mehr als OutputArea invalidieren, fuer den DrawingEngine-Textrahmen...
+ void SetInvalidateMore( sal_uInt16 nPixel ) { nInvMore = nPixel; }
+ sal_uInt16 GetInvalidateMore() const { return (sal_uInt16)nInvMore; }
+};
+
+// ----------------------------------------------------------------------
+// ImpEditEngine
+// ----------------------------------------------------------------------
+
+typedef EditView* EditViewPtr;
+SV_DECL_PTRARR( EditViews, EditViewPtr, 0, 1 )
+
+class ImpEditEngine : public SfxListener
+{
+ // Die Undos muessen direkt manipulieren ( private-Methoden ),
+ // damit keine neues Undos eingefuegt werden!
+ friend class EditUndoInsertChars;
+ friend class EditUndoRemoveChars;
+ friend class EditUndoDelContent;
+ friend class EditUndoConnectParas;
+ friend class EditUndoSplitPara;
+ friend class EditUndoInsertFeature;
+ friend class EditUndoMoveParagraphs;
+
+ friend class EditView;
+ friend class ImpEditView;
+ friend class EditEngine; // Fuer Zugriff auf Imp-Methoden
+ friend class EditRTFParser; // Fuer Zugriff auf Imp-Methoden
+ friend class EditHTMLParser; // Fuer Zugriff auf Imp-Methoden
+ friend class EdtAutoCorrDoc; // Fuer Zugriff auf Imp-Methoden
+ friend class EditDbg; // DebugRoutinen
+
+private:
+
+ // ================================================================
+ // Daten...
+ // ================================================================
+
+ // Dokument-Spezifische Daten...
+ ParaPortionList aParaPortionList; // Formatierung
+ Size aPaperSize; // Layout
+ Size aMinAutoPaperSize; // Layout ?
+ Size aMaxAutoPaperSize; // Layout ?
+ EditDoc aEditDoc; // Dokumenteninhalt
+
+ // Engine-Spezifische Daten....
+ EditEngine* pEditEngine;
+ EditViews aEditViews;
+ EditView* pActiveView;
+ TextRanger* pTextRanger;
+
+ SfxStyleSheetPool* pStylePool;
+ SfxItemPool* pTextObjectPool;
+
+ VirtualDevice* pVirtDev;
+ OutputDevice* pRefDev;
+
+ svtools::ColorConfig* pColorConfig;
+ mutable SvtCTLOptions* pCTLOptions;
+
+ SfxItemSet* pEmptyItemSet;
+ EditUndoManager* pUndoManager;
+ ESelection* pUndoMarkSelection;
+
+ ImplIMEInfos* mpIMEInfos;
+
+ NotifyList aNotifyCache;
+
+ XubString aWordDelimiters;
+ XubString aGroupChars;
+
+ EditSelFunctionSet aSelFuncSet;
+ EditSelectionEngine aSelEngine;
+
+ Color maBackgroundColor;
+
+ sal_uInt32 nBlockNotifications;
+ sal_uInt16 nStretchX;
+ sal_uInt16 nStretchY;
+
+ USHORT nAsianCompressionMode;
+ BOOL bKernAsianPunctuation;
+ BOOL bAddExtLeading;
+
+ EEHorizontalTextDirection eDefaultHorizontalTextDirection;
+
+ sal_uInt16 nBigTextObjectStart;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::linguistic2::XSpellChecker1 > xSpeller;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::linguistic2::XHyphenator > xHyphenator;
+ SpellInfo* pSpellInfo;
+ mutable ::com::sun::star::uno::Reference < ::com::sun::star::i18n::XBreakIterator > xBI;
+ mutable ::com::sun::star::uno::Reference < ::com::sun::star::i18n::XExtendedInputSequenceChecker > xISC;
+
+ ConvInfo * pConvInfo;
+
+ XubString aAutoCompleteText;
+
+ InternalEditStatus aStatus;
+
+ LanguageType eDefLanguage;
+
+ OnDemandLocaleDataWrapper xLocaleDataWrapper;
+ OnDemandTransliterationWrapper xTransliterationWrapper;
+
+ sal_Bool bIsFormatting;
+ sal_Bool bFormatted;
+ sal_Bool bInSelection;
+ sal_Bool bIsInUndo;
+ sal_Bool bUpdate;
+ sal_Bool bUndoEnabled;
+ sal_Bool bOwnerOfRefDev;
+ sal_Bool bDowning;
+ sal_Bool bUseAutoColor;
+ sal_Bool bForceAutoColor;
+ sal_Bool bCallParaInsertedOrDeleted;
+ sal_Bool bImpConvertFirstCall; // specifies if ImpConvert is called the very first time after Convert was called
+ sal_Bool bFirstWordCapitalization; // specifies if auto-correction should capitalize the first word or not
+
+ // Fuer Formatierung / Update....
+ DeletedNodesList aDeletedNodes;
+ Rectangle aInvalidRec;
+ sal_uInt32 nCurTextHeight;
+ sal_uInt16 nOnePixelInRef;
+
+ IdleFormattter aIdleFormatter;
+
+ Timer aOnlineSpellTimer;
+
+ // Wenn an einer Stelle erkannt wird, dass der StatusHdl gerufen werden
+ // muss, dies aber nicht sofort geschehen darf (kritischer Abschnitt):
+ Timer aStatusTimer;
+ Link aStatusHdlLink;
+ Link aNotifyHdl;
+ Link aImportHdl;
+ Link aBeginMovingParagraphsHdl;
+ Link aEndMovingParagraphsHdl;
+ Link aBeginPasteOrDropHdl;
+ Link aEndPasteOrDropHdl;
+ Link aModifyHdl;
+ Link maBeginDropHdl;
+ Link maEndDropHdl;
+
+ vos::ORef<SvxForbiddenCharactersTable> xForbiddenCharsTable;
+
+
+ // ================================================================
+ // Methoden...
+ // ================================================================
+
+ void CursorMoved( ContentNode* pPrevNode );
+ void ParaAttribsChanged( ContentNode* pNode );
+ void TextModified();
+ void CalcHeight( ParaPortion* pPortion );
+
+ // ggf. lieber inline, aber so einiges...
+ void InsertUndo( EditUndo* pUndo, sal_Bool bTryMerge = sal_False );
+ void ResetUndoManager();
+ sal_Bool HasUndoManager() const { return pUndoManager ? sal_True : sal_False; }
+
+ EditUndoSetAttribs* CreateAttribUndo( EditSelection aSel, const SfxItemSet& rSet );
+
+ EditPaM GetPaM( Point aDocPos, sal_Bool bSmart = sal_True );
+ EditPaM GetPaM( ParaPortion* pPortion, Point aPos, sal_Bool bSmart = sal_True );
+ long GetXPos( ParaPortion* pParaPortion, EditLine* pLine, USHORT nIndex, BOOL bPreferPortionStart = FALSE );
+ long GetPortionXOffset( ParaPortion* pParaPortion, EditLine* pLine, USHORT nTextPortion );
+ USHORT GetChar( ParaPortion* pParaPortion, EditLine* pLine, long nX, BOOL bSmart = TRUE );
+ Range GetInvalidYOffsets( ParaPortion* pPortion );
+ Range GetLineXPosStartEnd( ParaPortion* pParaPortion, EditLine* pLine );
+
+ void SetParaAttrib( BYTE nFunc, EditSelection aSel, sal_uInt16 nValue );
+ sal_uInt16 GetParaAttrib( BYTE nFunc, EditSelection aSel );
+ void SetCharAttrib( EditSelection aSel, const SfxPoolItem& rItem );
+ void ParaAttribsToCharAttribs( ContentNode* pNode );
+ void GetCharAttribs( sal_uInt16 nPara, EECharAttribArray& rLst ) const;
+
+ EditTextObject* CreateBinTextObject( EditSelection aSelection, SfxItemPool*, sal_Bool bAllowBigObjects = sal_False, sal_uInt16 nBigObjStart = 0 ) const;
+ void StoreBinTextObject( SvStream& rOStream, BinTextObject& rTextObject );
+ EditSelection InsertBinTextObject( BinTextObject&, EditPaM aPaM );
+ EditSelection InsertText( ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable >& rxDataObj, const String& rBaseURL, const EditPaM& rPaM, BOOL bUseSpecial );
+
+ EditPaM Clear();
+ EditPaM RemoveText();
+ EditPaM RemoveText( EditSelection aEditSelection );
+ sal_Bool CreateLines( USHORT nPara, sal_uInt32 nStartPosY );
+ void CreateAndInsertEmptyLine( ParaPortion* pParaPortion, sal_uInt32 nStartPosY );
+ sal_Bool FinishCreateLines( ParaPortion* pParaPortion );
+ void CalcCharPositions( ParaPortion* pParaPortion );
+ void CreateTextPortions( ParaPortion* pParaPortion, sal_uInt16& rStartPos /*, sal_Bool bCreateBlockPortions */ );
+ void RecalcTextPortion( ParaPortion* pParaPortion, sal_uInt16 nStartPos, short nNewChars );
+ sal_uInt16 SplitTextPortion( ParaPortion* pParaPortion, sal_uInt16 nPos, EditLine* pCurLine = 0 );
+ void SeekCursor( ContentNode* pNode, sal_uInt16 nPos, SvxFont& rFont, OutputDevice* pOut = NULL, sal_uInt16 nIgnoreWhich = 0 );
+ void RecalcFormatterFontMetrics( FormatterFontMetric& rCurMetrics, SvxFont& rFont );
+ void CheckAutoPageSize();
+
+ void ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, TextPortion* pPortion, sal_uInt16 nPortionStart, long nRemainingWidth, sal_Bool bCanHyphenate );
+ void ImpAdjustBlocks( ParaPortion* pParaPortion, EditLine* pLine, long nRemainingSpace );
+ EditPaM ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pRight, sal_Bool bBackward = sal_False );
+ EditPaM ImpDeleteSelection( EditSelection aEditSelection);
+ EditPaM ImpInsertParaBreak( const EditPaM& rPaM, sal_Bool bKeepEndingAttribs = sal_True );
+ EditPaM ImpInsertParaBreak( const EditSelection& rEditSelection, sal_Bool bKeepEndingAttribs = sal_True );
+ EditPaM ImpInsertText( EditSelection aCurEditSelection, const String& rStr );
+ EditPaM ImpInsertFeature( EditSelection aEditSelection, const SfxPoolItem& rItem );
+ void ImpRemoveChars( const EditPaM& rPaM, sal_uInt16 nChars, EditUndoRemoveChars* pCurUndo = 0 );
+ void ImpRemoveParagraph( sal_uInt16 nPara );
+ EditSelection ImpMoveParagraphs( Range aParagraphs, sal_uInt16 nNewPos );
+
+ EditPaM ImpFastInsertText( EditPaM aPaM, const String& rStr );
+ EditPaM ImpFastInsertParagraph( sal_uInt16 nPara );
+
+ sal_Bool ImpCheckRefMapMode();
+
+ BOOL ImplHasText() const;
+
+ void ImpFindKashidas( ContentNode* pNode, USHORT nStart, USHORT nEnd, SvUShorts& rArray );
+
+ void InsertContent( ContentNode* pNode, sal_uInt16 nPos );
+ EditPaM SplitContent( sal_uInt16 nNode, sal_uInt16 nSepPos );
+ EditPaM ConnectContents( sal_uInt16 nLeftNode, sal_Bool bBackward );
+
+ void ShowParagraph( sal_uInt16 nParagraph, sal_Bool bShow );
+ sal_Bool IsParagraphVisible( sal_uInt16 nParagraph );
+
+ EditPaM PageUp( const EditPaM& rPaM, EditView* pView);
+ EditPaM PageDown( const EditPaM& rPaM, EditView* pView);
+ EditPaM CursorUp( const EditPaM& rPaM, EditView* pEditView );
+ EditPaM CursorDown( const EditPaM& rPaM, EditView* pEditView );
+ EditPaM CursorLeft( const EditPaM& rPaM, USHORT nCharacterIteratorMode = ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL );
+ EditPaM CursorRight( const EditPaM& rPaM, USHORT nCharacterIteratorMode = ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL );
+ EditPaM CursorStartOfLine( const EditPaM& rPaM );
+ EditPaM CursorEndOfLine( const EditPaM& rPaM );
+ EditPaM CursorStartOfParagraph( const EditPaM& rPaM );
+ EditPaM CursorEndOfParagraph( const EditPaM& rPaM );
+ EditPaM CursorStartOfDoc();
+ EditPaM CursorEndOfDoc();
+ EditPaM WordLeft( const EditPaM& rPaM, sal_Int16 nWordType = ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES );
+ EditPaM WordRight( const EditPaM& rPaM, sal_Int16 nWordType = ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES );
+ EditPaM StartOfWord( const EditPaM& rPaM, sal_Int16 nWordType = ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES );
+ EditPaM EndOfWord( const EditPaM& rPaM, sal_Int16 nWordType = ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES );
+ EditSelection SelectWord( const EditSelection& rCurSelection, sal_Int16 nWordType = ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, BOOL bAcceptStartOfWord = TRUE );
+ EditSelection SelectSentence( const EditSelection& rCurSel );
+ EditPaM CursorVisualLeftRight( EditView* pEditView, const EditPaM& rPaM, USHORT nCharacterIteratorMode, BOOL bToLeft );
+ EditPaM CursorVisualStartEnd( EditView* pEditView, const EditPaM& rPaM, BOOL bStart );
+
+
+ void InitScriptTypes( USHORT nPara );
+ USHORT GetScriptType( const EditPaM& rPaM, USHORT* pEndPos = NULL ) const;
+ USHORT GetScriptType( const EditSelection& rSel ) const;
+ BOOL IsScriptChange( const EditPaM& rPaM ) const;
+ BOOL HasScriptType( USHORT nPara, USHORT nType ) const;
+
+ BOOL ImplCalcAsianCompression( ContentNode* pNode, TextPortion* pTextPortion, USHORT nStartPos, sal_Int32* pDXArray, USHORT n100thPercentFromMax, BOOL bManipulateDXArray );
+ void ImplExpandCompressedPortions( EditLine* pLine, ParaPortion* pParaPortion, long nRemainingWidth );
+
+ void ImplInitLayoutMode( OutputDevice* pOutDev, USHORT nPara, USHORT nIndex );
+ void ImplInitDigitMode( OutputDevice* pOutDev, String* pString, xub_StrLen nStt, xub_StrLen nLen, LanguageType eLang );
+
+ EditPaM ReadText( SvStream& rInput, EditSelection aSel );
+ EditPaM ReadRTF( SvStream& rInput, EditSelection aSel );
+ EditPaM ReadXML( SvStream& rInput, EditSelection aSel );
+ EditPaM ReadHTML( SvStream& rInput, const String& rBaseURL, EditSelection aSel, SvKeyValueIterator* pHTTPHeaderAttrs );
+ EditPaM ReadBin( SvStream& rInput, EditSelection aSel );
+ sal_uInt32 WriteText( SvStream& rOutput, EditSelection aSel );
+ sal_uInt32 WriteRTF( SvStream& rOutput, EditSelection aSel );
+ sal_uInt32 WriteXML( SvStream& rOutput, EditSelection aSel );
+ sal_uInt32 WriteHTML( SvStream& rOutput, EditSelection aSel );
+ sal_uInt32 WriteBin( SvStream& rOutput, EditSelection aSel, BOOL bStoreUnicode = FALSE ) const;
+
+ void WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, sal_uInt16 nPara, sal_uInt16 nPos,
+ SvxFontTable& rFontTable, SvxColorList& rColorList );
+ sal_Bool WriteItemListAsRTF( ItemList& rLst, SvStream& rOutput, sal_uInt16 nPara, sal_uInt16 nPos,
+ SvxFontTable& rFontTable, SvxColorList& rColorList );
+ long LogicToTwips( long n );
+
+ inline short GetXValue( short nXValue ) const;
+ inline sal_uInt16 GetXValue( sal_uInt16 nXValue ) const;
+ inline long GetXValue( long nXValue ) const;
+
+ inline short GetYValue( short nYValue ) const;
+ inline sal_uInt16 GetYValue( sal_uInt16 nYValue ) const;
+
+ ContentNode* GetPrevVisNode( ContentNode* pCurNode );
+ ContentNode* GetNextVisNode( ContentNode* pCurNode );
+
+ ParaPortion* GetPrevVisPortion( ParaPortion* pCurPortion );
+ ParaPortion* GetNextVisPortion( ParaPortion* pCurPortion );
+
+ void SetBackgroundColor( const Color& rColor ) { maBackgroundColor = rColor; }
+ Color GetBackgroundColor() const { return maBackgroundColor; }
+
+ Color GetAutoColor() const;
+ void EnableAutoColor( BOOL b ) { bUseAutoColor = b; }
+ BOOL IsAutoColorEnabled() const { return bUseAutoColor; }
+ void ForceAutoColor( BOOL b ) { bForceAutoColor = b; }
+ BOOL IsForceAutoColor() const { return bForceAutoColor; }
+
+ inline VirtualDevice* GetVirtualDevice( const MapMode& rMapMode, ULONG nDrawMode );
+ inline void EraseVirtualDevice();
+
+ DECL_LINK( StatusTimerHdl, Timer * );
+ DECL_LINK( IdleFormatHdl, Timer * );
+ DECL_LINK( OnlineSpellHdl, Timer * );
+ DECL_LINK( DocModified, void* );
+
+ void CheckIdleFormatter();
+
+ inline ParaPortion* FindParaPortion( ContentNode* pNode ) const;
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable > CreateTransferable( const EditSelection& rSelection ) const;
+
+ void SetValidPaperSize( const Size& rSz );
+
+ ::com::sun::star::uno::Reference < ::com::sun::star::i18n::XBreakIterator > ImplGetBreakIterator() const;
+ ::com::sun::star::uno::Reference < ::com::sun::star::i18n::XExtendedInputSequenceChecker > ImplGetInputSequenceChecker() const;
+
+ /** Decorate metafile output with verbose text comments
+
+ This method is used to wrap SvxFont::QuickDrawText, to
+ determine character-by-character wise, which logical text
+ units like characters, words and sentences are contained in
+ the output string at hand. This is necessary for slideshow
+ text effects.
+ */
+ void ImplFillTextMarkingVector(const ::com::sun::star::lang::Locale& rLocale, EEngineData::TextMarkingVector& rTextMarkingVector, const String& rTxt, const USHORT nIdx, const USHORT nLen) const;
+
+protected:
+ virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
+
+public:
+ ImpEditEngine( EditEngine* pEditEngine, SfxItemPool* pPool );
+ ~ImpEditEngine();
+
+ void InitDoc( BOOL bKeepParaAttribs );
+ EditDoc& GetEditDoc() { return aEditDoc; }
+ const EditDoc& GetEditDoc() const { return aEditDoc; }
+
+ inline EditUndoManager& GetUndoManager();
+
+ void SetUpdateMode( sal_Bool bUp, EditView* pCurView = 0, sal_Bool bForceUpdate = sal_False );
+ sal_Bool GetUpdateMode() const { return bUpdate; }
+
+ const ParaPortionList& GetParaPortions() const { return aParaPortionList; }
+ ParaPortionList& GetParaPortions() { return aParaPortionList; }
+ EditViews& GetEditViews() { return aEditViews; }
+
+ const Size& GetPaperSize() const { return aPaperSize; }
+ void SetPaperSize( const Size& rSz ) { aPaperSize = rSz; }
+
+ void SetVertical( BOOL bVertical );
+ BOOL IsVertical() const { return GetEditDoc().IsVertical(); }
+
+ void SetFixedCellHeight( BOOL bUseFixedCellHeight );
+ BOOL IsFixedCellHeight() const { return GetEditDoc().IsFixedCellHeight(); }
+
+ void SetDefaultHorizontalTextDirection( EEHorizontalTextDirection eHTextDir ) { eDefaultHorizontalTextDirection = eHTextDir; }
+ EEHorizontalTextDirection GetDefaultHorizontalTextDirection() const { return eDefaultHorizontalTextDirection; }
+
+
+ void InitWritingDirections( USHORT nPara );
+ BOOL IsRightToLeft( USHORT nPara ) const;
+ BYTE GetRightToLeft( USHORT nPara, USHORT nChar, USHORT* pStart = NULL, USHORT* pEnd = NULL );
+ BOOL HasDifferentRTLLevels( const ContentNode* pNode );
+
+ void SetTextRanger( TextRanger* pRanger );
+ TextRanger* GetTextRanger() const { return pTextRanger; }
+
+ const Size& GetMinAutoPaperSize() const { return aMinAutoPaperSize; }
+ void SetMinAutoPaperSize( const Size& rSz ) { aMinAutoPaperSize = rSz; }
+
+ const Size& GetMaxAutoPaperSize() const { return aMaxAutoPaperSize; }
+ void SetMaxAutoPaperSize( const Size& rSz ) { aMaxAutoPaperSize = rSz; }
+
+ void FormatDoc();
+ void FormatFullDoc();
+ void UpdateViews( EditView* pCurView = 0 );
+ void Paint( ImpEditView* pView, const Rectangle& rRect, sal_Bool bUseVirtDev = sal_False );
+ void Paint( OutputDevice* pOutDev, Rectangle aClipRec, Point aStartPos, sal_Bool bStripOnly = sal_False, short nOrientation = 0 );
+
+ sal_Bool MouseButtonUp( const MouseEvent& rMouseEvent, EditView* pView );
+ sal_Bool MouseButtonDown( const MouseEvent& rMouseEvent, EditView* pView );
+ sal_Bool MouseMove( const MouseEvent& rMouseEvent, EditView* pView );
+ void Command( const CommandEvent& rCEvt, EditView* pView );
+
+ EditSelectionEngine& GetSelEngine() { return aSelEngine; }
+ XubString GetSelected( const EditSelection& rSel, const LineEnd eParaSep = LINEEND_LF ) const;
+
+ const SfxItemSet& GetEmptyItemSet();
+
+ void UpdateSelections();
+
+ void EnableUndo( sal_Bool bEnable );
+ sal_Bool IsUndoEnabled() { return bUndoEnabled; }
+ void SetUndoMode( sal_Bool b ) { bIsInUndo = b; }
+ sal_Bool IsInUndo() { return bIsInUndo; }
+
+ void SetCallParaInsertedOrDeleted( sal_Bool b ) { bCallParaInsertedOrDeleted = b; }
+ sal_Bool IsCallParaInsertedOrDeleted() const { return bCallParaInsertedOrDeleted; }
+
+ sal_Bool IsFormatted() const { return bFormatted; }
+ sal_Bool IsFormatting() const { return bIsFormatting; }
+
+ void SetText( const String& rText );
+ EditPaM DeleteSelected( EditSelection aEditSelection);
+ EditPaM InsertText( const EditSelection& rCurEditSelection, sal_Unicode c, sal_Bool bOverwrite, sal_Bool bIsUserInput = sal_False );
+ EditPaM InsertText( EditSelection aCurEditSelection, const String& rStr );
+ EditPaM AutoCorrect( const EditSelection& rCurEditSelection, sal_Unicode c, sal_Bool bOverwrite );
+ EditPaM DeleteLeftOrRight( const EditSelection& rEditSelection, BYTE nMode, BYTE nDelMode = DELMODE_SIMPLE );
+ EditPaM InsertParaBreak( EditSelection aEditSelection );
+ EditPaM InsertLineBreak( EditSelection aEditSelection );
+ EditPaM InsertTab( EditSelection aEditSelection );
+ EditPaM InsertField( EditSelection aEditSelection, const SvxFieldItem& rFld );
+ sal_Bool UpdateFields();
+
+ EditPaM Read( SvStream& rInput, const String& rBaseURL, EETextFormat eFormat, EditSelection aSel, SvKeyValueIterator* pHTTPHeaderAttrs = NULL );
+ void Write( SvStream& rOutput, EETextFormat eFormat, EditSelection aSel );
+
+ EditTextObject* CreateTextObject();
+ EditTextObject* CreateTextObject( EditSelection aSel );
+ void SetText( const EditTextObject& rTextObject );
+ EditSelection InsertText( const EditTextObject& rTextObject, EditSelection aSel );
+
+ EditSelection MoveCursor( const KeyEvent& rKeyEvent, EditView* pEditView );
+
+ EditSelection MoveParagraphs( Range aParagraphs, sal_uInt16 nNewPos, EditView* pCurView );
+
+ sal_uInt32 CalcTextHeight();
+ sal_uInt32 GetTextHeight() const;
+ sal_uInt32 CalcTextWidth( BOOL bIgnoreExtraSpace );
+ sal_uInt32 CalcLineWidth( ParaPortion* pPortion, EditLine* pLine, BOOL bIgnoreExtraSpace );
+ sal_uInt16 GetLineCount( sal_uInt16 nParagraph ) const;
+ sal_uInt16 GetLineLen( sal_uInt16 nParagraph, sal_uInt16 nLine ) const;
+ void GetLineBoundaries( /*out*/USHORT &rStart, /*out*/USHORT &rEnd, USHORT nParagraph, USHORT nLine ) const;
+ USHORT GetLineNumberAtIndex( USHORT nPara, USHORT nIndex ) const;
+ sal_uInt16 GetLineHeight( sal_uInt16 nParagraph, sal_uInt16 nLine );
+ sal_uInt32 GetParaHeight( sal_uInt16 nParagraph );
+
+ SfxItemSet GetAttribs( USHORT nPara, USHORT nStart, USHORT nEnd, sal_uInt8 nFlags = 0xFF ) const;
+ SfxItemSet GetAttribs( EditSelection aSel, BOOL bOnlyHardAttrib = FALSE );
+ void SetAttribs( EditSelection aSel, const SfxItemSet& rSet, BYTE nSpecial = 0 );
+ void RemoveCharAttribs( EditSelection aSel, sal_Bool bRemoveParaAttribs, sal_uInt16 nWhich = 0 );
+ void RemoveCharAttribs( sal_uInt16 nPara, sal_uInt16 nWhich = 0, sal_Bool bRemoveFeatures = sal_False );
+ void SetFlatMode( sal_Bool bFlat );
+
+ void SetParaAttribs( sal_uInt16 nPara, const SfxItemSet& rSet );
+ const SfxItemSet& GetParaAttribs( sal_uInt16 nPara ) const;
+
+ sal_Bool HasParaAttrib( sal_uInt16 nPara, sal_uInt16 nWhich ) const;
+ const SfxPoolItem& GetParaAttrib( sal_uInt16 nPara, sal_uInt16 nWhich ) const;
+
+ Rectangle PaMtoEditCursor( EditPaM aPaM, sal_uInt16 nFlags = 0 );
+ Rectangle GetEditCursor( ParaPortion* pPortion, sal_uInt16 nIndex, sal_uInt16 nFlags = 0 );
+
+ sal_Bool IsModified() const { return aEditDoc.IsModified(); }
+ void SetModifyFlag( sal_Bool b ) { aEditDoc.SetModified( b ); }
+ void SetModifyHdl( const Link& rLink ) { aModifyHdl = rLink; }
+ Link GetModifyHdl() const { return aModifyHdl; }
+
+
+ sal_Bool IsInSelectionMode() { return bInSelection; }
+ void StopSelectionMode();
+
+ void IndentBlock( EditView* pView, sal_Bool bRight );
+
+// Fuer Undo/Redo
+ sal_Bool Undo( EditView* pView );
+ sal_Bool Redo( EditView* pView );
+ sal_Bool Repeat( EditView* pView );
+
+// OV-Special
+ void InvalidateFromParagraph( sal_uInt16 nFirstInvPara );
+ EditPaM InsertParagraph( sal_uInt16 nPara );
+ EditSelection* SelectParagraph( sal_uInt16 nPara );
+
+ void SetStatusEventHdl( const Link& rLink ) { aStatusHdlLink = rLink; }
+ Link GetStatusEventHdl() const { return aStatusHdlLink; }
+
+ void SetNotifyHdl( const Link& rLink ) { aNotifyHdl = rLink; }
+ Link GetNotifyHdl() const { return aNotifyHdl; }
+
+ void FormatAndUpdate( EditView* pCurView = 0 );
+ inline void IdleFormatAndUpdate( EditView* pCurView = 0 );
+
+ svtools::ColorConfig& GetColorConfig();
+ BOOL IsVisualCursorTravelingEnabled();
+ BOOL DoVisualCursorTraveling( const ContentNode* pNode );
+
+ EditSelection ConvertSelection( sal_uInt16 nStartPara, sal_uInt16 nStartPos, sal_uInt16 nEndPara, sal_uInt16 nEndPos ) const;
+ inline EPaM CreateEPaM( const EditPaM& rPaM );
+ inline EditPaM CreateEditPaM( const EPaM& rEPaM );
+ inline ESelection CreateESel( const EditSelection& rSel );
+ inline EditSelection CreateSel( const ESelection& rSel );
+
+
+ void SetStyleSheetPool( SfxStyleSheetPool* pSPool );
+ SfxStyleSheetPool* GetStyleSheetPool() const { return pStylePool; }
+
+ void SetStyleSheet( EditSelection aSel, SfxStyleSheet* pStyle );
+ void SetStyleSheet( sal_uInt16 nPara, SfxStyleSheet* pStyle );
+ SfxStyleSheet* GetStyleSheet( sal_uInt16 nPara ) const;
+
+ void UpdateParagraphsWithStyleSheet( SfxStyleSheet* pStyle );
+ void RemoveStyleFromParagraphs( SfxStyleSheet* pStyle );
+
+ OutputDevice* GetRefDevice() const { return pRefDev; }
+ void SetRefDevice( OutputDevice* pRefDef );
+
+ const MapMode& GetRefMapMode() { return pRefDev->GetMapMode(); }
+ void SetRefMapMode( const MapMode& rMapMode );
+
+ InternalEditStatus& GetStatus() { return aStatus; }
+ void CallStatusHdl();
+ void DelayedCallStatusHdl() { aStatusTimer.Start(); }
+
+ void CallNotify( EENotify& rNotify );
+ void EnterBlockNotifications();
+ void LeaveBlockNotifications();
+
+
+ EditSelection MatchGroup( const EditSelection& rSel );
+
+ void UndoActionStart( sal_uInt16 nId );
+ void UndoActionStart( sal_uInt16 nId, const ESelection& rSel );
+ void UndoActionEnd( sal_uInt16 nId );
+
+ EditView* GetActiveView() const { return pActiveView; }
+ void SetActiveView( EditView* pView );
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::linguistic2::XSpellChecker1 >
+ GetSpeller();
+ void SetSpeller( ::com::sun::star::uno::Reference<
+ ::com::sun::star::linguistic2::XSpellChecker1 > &xSpl )
+ { xSpeller = xSpl; }
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::linguistic2::XHyphenator >
+ GetHyphenator() const { return xHyphenator; }
+ void SetHyphenator( ::com::sun::star::uno::Reference<
+ ::com::sun::star::linguistic2::XHyphenator > &xHyph )
+ { xHyphenator = xHyph; }
+ SpellInfo* GetSpellInfo() const { return pSpellInfo; }
+
+ void SetDefaultLanguage( LanguageType eLang ) { eDefLanguage = eLang; }
+ LanguageType GetDefaultLanguage() const { return eDefLanguage; }
+
+
+ LanguageType GetLanguage( const EditSelection rSelection ) const;
+ LanguageType GetLanguage( const EditPaM& rPaM, USHORT* pEndPos = NULL ) const;
+ ::com::sun::star::lang::Locale GetLocale( const EditPaM& rPaM ) const;
+
+ void DoOnlineSpelling( ContentNode* pThisNodeOnly = 0, sal_Bool bSpellAtCursorPos = sal_False, sal_Bool bInteruptable = sal_True );
+ EESpellState Spell( EditView* pEditView, sal_Bool bMultipleDoc );
+ EESpellState HasSpellErrors();
+ EESpellState StartThesaurus( EditView* pEditView );
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::linguistic2::XSpellAlternatives >
+ ImpSpell( EditView* pEditView );
+
+ // text conversion functions
+ void Convert( EditView* pEditView, LanguageType nSrcLang, LanguageType nDestLang, const Font *pDestFont, INT32 nOptions, sal_Bool bIsInteractive, sal_Bool bMultipleDoc );
+ void ImpConvert( rtl::OUString &rConvTxt, LanguageType &rConvTxtLang, EditView* pEditView, LanguageType nSrcLang, const ESelection &rConvRange,
+ sal_Bool bAllowImplicitChangesForNotConvertibleText, LanguageType nTargetLang, const Font *pTargetFont );
+ ConvInfo * GetConvInfo() const { return pConvInfo; }
+ sal_Bool HasConvertibleTextPortion( LanguageType nLang );
+ void SetLanguageAndFont( const ESelection &rESel,
+ LanguageType nLang, USHORT nLangWhichId,
+ const Font *pFont, USHORT nFontWhichId );
+
+ // returns true if input sequence checking should be applied
+ sal_Bool IsInputSequenceCheckingRequired( sal_Unicode nChar, const EditSelection& rCurSel ) const;
+
+ //find the next error within the given selection - forward only!
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::linguistic2::XSpellAlternatives >
+ ImpFindNextError(EditSelection& rSelection);
+ //initialize sentence spelling
+ void StartSpelling(EditView& rEditView, sal_Bool bMultipleDoc);
+ //spell and return a sentence
+ bool SpellSentence(EditView& rView, ::svx::SpellPortions& rToFill, bool bIsGrammarChecking );
+ //put spelling back to start of current sentence - needed after switch of grammar support
+ void PutSpellingToSentenceStart( EditView& rEditView );
+ //applies a changed sentence
+ void ApplyChangedSentence(EditView& rEditView, const ::svx::SpellPortions& rNewPortions, bool bIsGrammarChecking );
+ //deinitialize sentence spelling
+ void EndSpelling();
+ //adds one or more portions of text to the SpellPortions depending on language changes
+ void AddPortionIterated(
+ EditView& rEditView,
+ const EditSelection rSel,
+ ::com::sun::star::uno::Reference< ::com::sun::star::linguistic2::XSpellAlternatives > xAlt,
+ ::svx::SpellPortions& rToFill);
+ //adds one portion to the SpellPortions
+ void AddPortion(
+ const EditSelection rSel,
+ ::com::sun::star::uno::Reference< ::com::sun::star::linguistic2::XSpellAlternatives > xAlt,
+ ::svx::SpellPortions& rToFill,
+ bool bIsField );
+
+ sal_Bool Search( const SvxSearchItem& rSearchItem, EditView* pView );
+ sal_Bool ImpSearch( const SvxSearchItem& rSearchItem, const EditSelection& rSearchSelection, const EditPaM& rStartPos, EditSelection& rFoundSel );
+ sal_uInt16 StartSearchAndReplace( EditView* pEditView, const SvxSearchItem& rSearchItem );
+ sal_Bool HasText( const SvxSearchItem& rSearchItem );
+
+ void SetEditTextObjectPool( SfxItemPool* pP ) { pTextObjectPool = pP; }
+ SfxItemPool* GetEditTextObjectPool() const { return pTextObjectPool; }
+
+ const SvxNumberFormat * GetNumberFormat( const ContentNode* pNode ) const;
+ sal_Int32 GetSpaceBeforeAndMinLabelWidth( const ContentNode *pNode, sal_Int32 *pnSpaceBefore = 0, sal_Int32 *pnMinLabelWidth = 0 ) const;
+
+ const SvxLRSpaceItem& GetLRSpaceItem( ContentNode* pNode );
+ SvxAdjust GetJustification( USHORT nPara ) const;
+
+ void SetCharStretching( sal_uInt16 nX, sal_uInt16 nY );
+ inline void GetCharStretching( sal_uInt16& rX, sal_uInt16& rY );
+ void DoStretchChars( sal_uInt16 nX, sal_uInt16 nY );
+
+ void SetBigTextObjectStart( sal_uInt16 nStartAtPortionCount ) { nBigTextObjectStart = nStartAtPortionCount; }
+ sal_uInt16 GetBigTextObjectStart() const { return nBigTextObjectStart; }
+
+ inline EditEngine* GetEditEnginePtr() const { return pEditEngine; }
+
+ void StartOnlineSpellTimer() { aOnlineSpellTimer.Start(); }
+ void StopOnlineSpellTimer() { aOnlineSpellTimer.Stop(); }
+
+ const XubString& GetAutoCompleteText() const { return aAutoCompleteText; }
+ void SetAutoCompleteText( const String& rStr, sal_Bool bUpdateTipWindow );
+
+ EditSelection TransliterateText( const EditSelection& rSelection, sal_Int32 nTransliterationMode );
+
+ void SetAsianCompressionMode( USHORT n );
+ USHORT GetAsianCompressionMode() const { return nAsianCompressionMode; }
+
+ void SetKernAsianPunctuation( BOOL b );
+ BOOL IsKernAsianPunctuation() const { return bKernAsianPunctuation; }
+
+ void SetAddExtLeading( BOOL b );
+ BOOL IsAddExtLeading() const { return bAddExtLeading; }
+
+ vos::ORef<SvxForbiddenCharactersTable> GetForbiddenCharsTable( BOOL bGetInternal = TRUE ) const;
+ void SetForbiddenCharsTable( vos::ORef<SvxForbiddenCharactersTable> xForbiddenChars );
+
+ BOOL mbLastTryMerge;
+
+ /** sets a link that is called at the beginning of a drag operation at an edit view */
+ void SetBeginDropHdl( const Link& rLink ) { maBeginDropHdl = rLink; }
+ Link GetBeginDropHdl() const { return maBeginDropHdl; }
+
+ /** sets a link that is called at the end of a drag operation at an edit view */
+ void SetEndDropHdl( const Link& rLink ) { maEndDropHdl = rLink; }
+ Link GetEndDropHdl() const { return maEndDropHdl; }
+
+ /// specifies if auto-correction should capitalize the first word or not (default is on)
+ void SetFirstWordCapitalization( BOOL bCapitalize ) { bFirstWordCapitalization = bCapitalize; }
+ BOOL IsFirstWordCapitalization() const { return bFirstWordCapitalization; }
+};
+
+inline EPaM ImpEditEngine::CreateEPaM( const EditPaM& rPaM )
+{
+ ContentNode* pNode = rPaM.GetNode();
+ return EPaM( aEditDoc.GetPos( pNode ), rPaM.GetIndex() );
+}
+
+inline EditPaM ImpEditEngine::CreateEditPaM( const EPaM& rEPaM )
+{
+ DBG_ASSERT( rEPaM.nPara < aEditDoc.Count(), "CreateEditPaM: Ungueltiger Absatz" );
+ DBG_ASSERT( aEditDoc[ rEPaM.nPara ]->Len() >= rEPaM.nIndex, "CreateEditPaM: Ungueltiger Index" );
+ return EditPaM( aEditDoc[ rEPaM.nPara], rEPaM.nIndex );
+}
+
+inline ESelection ImpEditEngine::CreateESel( const EditSelection& rSel )
+{
+ ContentNode* pStartNode = rSel.Min().GetNode();
+ ContentNode* pEndNode = rSel.Max().GetNode();
+ ESelection aESel;
+ aESel.nStartPara = aEditDoc.GetPos( pStartNode );
+ aESel.nStartPos = rSel.Min().GetIndex();
+ aESel.nEndPara = aEditDoc.GetPos( pEndNode );
+ aESel.nEndPos = rSel.Max().GetIndex();
+ return aESel;
+}
+
+inline EditSelection ImpEditEngine::CreateSel( const ESelection& rSel )
+{
+ DBG_ASSERT( rSel.nStartPara < aEditDoc.Count(), "CreateSel: Ungueltiger Start-Absatz" );
+ DBG_ASSERT( rSel.nEndPara < aEditDoc.Count(), "CreateSel: Ungueltiger End-Absatz" );
+ EditSelection aSel;
+ aSel.Min().SetNode( aEditDoc[ rSel.nStartPara ] );
+ aSel.Min().SetIndex( rSel.nStartPos );
+ aSel.Max().SetNode( aEditDoc[ rSel.nEndPara ] );
+ aSel.Max().SetIndex( rSel.nEndPos );
+ DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "CreateSel: Fehlerhafte Selektion!" );
+ return aSel;
+}
+
+inline VirtualDevice* ImpEditEngine::GetVirtualDevice( const MapMode& rMapMode, ULONG nDrawMode )
+{
+ if ( !pVirtDev )
+ pVirtDev = new VirtualDevice;
+
+ if ( ( pVirtDev->GetMapMode().GetMapUnit() != rMapMode.GetMapUnit() ) ||
+ ( pVirtDev->GetMapMode().GetScaleX() != rMapMode.GetScaleX() ) ||
+ ( pVirtDev->GetMapMode().GetScaleY() != rMapMode.GetScaleY() ) )
+ {
+ MapMode aMapMode( rMapMode );
+ aMapMode.SetOrigin( Point( 0, 0 ) );
+ pVirtDev->SetMapMode( aMapMode );
+ }
+
+ pVirtDev->SetDrawMode( nDrawMode );
+
+ return pVirtDev;
+}
+
+inline void ImpEditEngine::EraseVirtualDevice()
+{
+ delete pVirtDev;
+ pVirtDev = 0;
+}
+
+inline void ImpEditEngine::IdleFormatAndUpdate( EditView* pCurView )
+{
+ aIdleFormatter.DoIdleFormat( pCurView );
+}
+
+#ifndef SVX_LIGHT
+inline EditUndoManager& ImpEditEngine::GetUndoManager()
+{
+ if ( !pUndoManager )
+ pUndoManager = new EditUndoManager( this );
+ return *pUndoManager;
+}
+#endif
+
+inline ParaPortion* ImpEditEngine::FindParaPortion( ContentNode* pNode ) const
+{
+ sal_uInt16 nPos = aEditDoc.GetPos( pNode );
+ DBG_ASSERT( nPos < GetParaPortions().Count(), "Portionloser Node?" );
+ return GetParaPortions()[ nPos ];
+}
+
+inline void ImpEditEngine::GetCharStretching( sal_uInt16& rX, sal_uInt16& rY )
+{
+ rX = nStretchX;
+ rY = nStretchY;
+}
+
+inline short ImpEditEngine::GetXValue( short nXValue ) const
+{
+ if ( !aStatus.DoStretch() || ( nStretchX == 100 ) )
+ return nXValue;
+
+ return (short) ((long)nXValue*nStretchX/100);
+}
+
+inline sal_uInt16 ImpEditEngine::GetXValue( sal_uInt16 nXValue ) const
+{
+ if ( !aStatus.DoStretch() || ( nStretchX == 100 ) )
+ return nXValue;
+
+ return (sal_uInt16) ((long)nXValue*nStretchX/100);
+}
+
+inline long ImpEditEngine::GetXValue( long nXValue ) const
+{
+ if ( !aStatus.DoStretch() || ( nStretchX == 100 ) )
+ return nXValue;
+
+ return nXValue*nStretchX/100;
+}
+
+inline short ImpEditEngine::GetYValue( short nYValue ) const
+{
+ if ( !aStatus.DoStretch() || ( nStretchY == 100 ) )
+ return nYValue;
+
+ return (short) ((long)nYValue*nStretchY/100);
+}
+
+inline sal_uInt16 ImpEditEngine::GetYValue( sal_uInt16 nYValue ) const
+{
+ if ( !aStatus.DoStretch() || ( nStretchY == 100 ) )
+ return nYValue;
+
+ return (sal_uInt16) ((long)nYValue*nStretchY/100);
+}
+
+inline void ImpEditView::SetPointer( const Pointer& rPointer )
+{
+ delete pPointer;
+ pPointer = new Pointer( rPointer );
+}
+
+inline const Pointer& ImpEditView::GetPointer()
+{
+ if ( !pPointer )
+ {
+ pPointer = new Pointer( IsVertical() ? POINTER_TEXT_VERTICAL : POINTER_TEXT );
+ return *pPointer;
+ }
+
+ if(POINTER_TEXT == pPointer->GetStyle() && IsVertical())
+ {
+ delete pPointer;
+ pPointer = new Pointer(POINTER_TEXT_VERTICAL);
+ }
+ else if(POINTER_TEXT_VERTICAL == pPointer->GetStyle() && !IsVertical())
+ {
+ delete pPointer;
+ pPointer = new Pointer(POINTER_TEXT);
+ }
+
+ return *pPointer;
+}
+
+inline void ImpEditView::SetCursor( const Cursor& rCursor )
+{
+ delete pCursor;
+ pCursor = new Cursor( rCursor );
+}
+
+inline Cursor* ImpEditView::GetCursor()
+{
+ if ( !pCursor )
+ pCursor = new Cursor;
+ return pCursor;
+}
+
+void ConvertItem( SfxPoolItem& rPoolItem, MapUnit eSourceUnit, MapUnit eDestUnit );
+void ConvertAndPutItems( SfxItemSet& rDest, const SfxItemSet& rSource, const MapUnit* pSourceUnit = NULL, const MapUnit* pDestUnit = NULL );
+BYTE GetCharTypeForCompression( xub_Unicode cChar );
+Point Rotate( const Point& rPoint, short nOrientation, const Point& rOrigin );
+
+#endif // _IMPEDIT_HXX
+
+
diff --git a/editeng/source/editeng/impedit2.cxx b/editeng/source/editeng/impedit2.cxx
new file mode 100644
index 000000000000..bbdfa47e6a57
--- /dev/null
+++ b/editeng/source/editeng/impedit2.cxx
@@ -0,0 +1,4632 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 <editeng/lspcitem.hxx>
+#include <editeng/flditem.hxx>
+#include <impedit.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/editview.hxx>
+#include <editdbg.hxx>
+#include <eerdll2.hxx>
+#include <editeng/eerdll.hxx>
+#include <edtspell.hxx>
+#include <eeobj.hxx>
+#include <editeng/txtrange.hxx>
+#include <svl/urlbmk.hxx>
+#include <svtools/colorcfg.hxx>
+#include <svl/ctloptions.hxx>
+#include <editeng/acorrcfg.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/scripttypeitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/fontitem.hxx>
+#include <vcl/cmdevt.h>
+
+#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
+#include <com/sun/star/i18n/WordType.hpp>
+#include <com/sun/star/i18n/ScriptType.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/text/CharacterCompressionType.hpp>
+#include <com/sun/star/i18n/InputSequenceCheckMode.hpp>
+
+#include <comphelper/processfactory.hxx>
+
+#include <sot/formats.hxx>
+
+#include <unicode/ubidi.h>
+
+using namespace ::com::sun::star;
+
+USHORT lcl_CalcExtraSpace( ParaPortion*, const SvxLineSpacingItem& rLSItem )
+{
+ USHORT nExtra = 0;
+ /* if ( ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP )
+ && ( rLSItem.GetPropLineSpace() != 100 ) )
+ {
+ // ULONG nH = pPortion->GetNode()->GetCharAttribs().GetDefFont().GetSize().Height();
+ ULONG nH = pPortion->GetLines().GetObject( 0 )->GetHeight();
+ long n = nH * rLSItem.GetPropLineSpace();
+ n /= 100;
+ n -= nH; // nur den Abstand
+ if ( n > 0 )
+ nExtra = (USHORT)n;
+ }
+ else */
+ if ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_FIX )
+ {
+ nExtra = rLSItem.GetInterLineSpace();
+ }
+
+ return nExtra;
+}
+
+ // ----------------------------------------------------------------------
+// class ImpEditEngine
+// ----------------------------------------------------------------------
+
+ImpEditEngine::ImpEditEngine( EditEngine* pEE, SfxItemPool* pItemPool ) :
+ aPaperSize( 0x7FFFFFFF, 0x7FFFFFFF ),
+ aMinAutoPaperSize( 0x0, 0x0 ),
+ aMaxAutoPaperSize( 0x7FFFFFFF, 0x7FFFFFFF ),
+ aEditDoc( pItemPool ),
+ aWordDelimiters( RTL_CONSTASCII_USTRINGPARAM( " .,;:-'`'?!_=\"{}()[]\0xFF" ) ),
+ aGroupChars( RTL_CONSTASCII_USTRINGPARAM( "{}()[]" ) )
+{
+ pEditEngine = pEE;
+ pRefDev = NULL;
+ pVirtDev = NULL;
+ pEmptyItemSet = NULL;
+ pActiveView = NULL;
+ pSpellInfo = NULL;
+ pConvInfo = NULL;
+ pTextObjectPool = NULL;
+ mpIMEInfos = NULL;
+ pStylePool = NULL;
+ pUndoManager = NULL;
+ pUndoMarkSelection = NULL;
+ pTextRanger = NULL;
+ pColorConfig = NULL;
+ pCTLOptions = NULL;
+
+ nCurTextHeight = 0;
+ nBlockNotifications = 0;
+ nBigTextObjectStart = 20;
+
+ nStretchX = 100;
+ nStretchY = 100;
+
+ bInSelection = FALSE;
+ bOwnerOfRefDev = FALSE;
+ bDowning = FALSE;
+ bIsInUndo = FALSE;
+ bIsFormatting = FALSE;
+ bFormatted = FALSE;
+ bUpdate = TRUE;
+ bUseAutoColor = TRUE;
+ bForceAutoColor = FALSE;
+ bAddExtLeading = FALSE;
+ bUndoEnabled = TRUE;
+ bCallParaInsertedOrDeleted = FALSE;
+ bImpConvertFirstCall= FALSE;
+ bFirstWordCapitalization = TRUE;
+
+ eDefLanguage = LANGUAGE_DONTKNOW;
+ maBackgroundColor = COL_AUTO;
+
+ nAsianCompressionMode = text::CharacterCompressionType::NONE;
+ bKernAsianPunctuation = FALSE;
+
+ eDefaultHorizontalTextDirection = EE_HTEXTDIR_DEFAULT;
+
+
+ aStatus.GetControlWord() = EE_CNTRL_USECHARATTRIBS | EE_CNTRL_DOIDLEFORMAT |
+ EE_CNTRL_PASTESPECIAL | EE_CNTRL_UNDOATTRIBS |
+ EE_CNTRL_ALLOWBIGOBJS | EE_CNTRL_RTFSTYLESHEETS |
+ EE_CNTRL_FORMAT100;
+
+ aSelEngine.SetFunctionSet( &aSelFuncSet );
+
+ aStatusTimer.SetTimeout( 200 );
+ aStatusTimer.SetTimeoutHdl( LINK( this, ImpEditEngine, StatusTimerHdl ) );
+
+ aIdleFormatter.SetTimeout( 5 );
+ aIdleFormatter.SetTimeoutHdl( LINK( this, ImpEditEngine, IdleFormatHdl ) );
+
+ aOnlineSpellTimer.SetTimeout( 100 );
+ aOnlineSpellTimer.SetTimeoutHdl( LINK( this, ImpEditEngine, OnlineSpellHdl ) );
+
+ pRefDev = EE_DLL()->GetGlobalData()->GetStdRefDevice();
+
+ // Ab hier wird schon auf Daten zugegriffen!
+ SetRefDevice( pRefDev );
+ InitDoc( FALSE );
+
+ bCallParaInsertedOrDeleted = TRUE;
+
+ aEditDoc.SetModifyHdl( LINK( this, ImpEditEngine, DocModified ) );
+
+ mbLastTryMerge = FALSE;
+}
+
+ImpEditEngine::~ImpEditEngine()
+{
+ aStatusTimer.Stop();
+ aOnlineSpellTimer.Stop();
+ aIdleFormatter.Stop();
+
+ // das Zerstoeren von Vorlagen kann sonst unnoetiges Formatieren ausloesen,
+ // wenn eine Parent-Vorlage zerstoert wird.
+ // Und das nach dem Zerstoeren der Daten!
+ bDowning = TRUE;
+ SetUpdateMode( FALSE );
+
+ delete pVirtDev;
+ delete pEmptyItemSet;
+ delete pUndoManager;
+ delete pTextRanger;
+ delete mpIMEInfos;
+ delete pColorConfig;
+ delete pCTLOptions;
+ if ( bOwnerOfRefDev )
+ delete pRefDev;
+ delete pSpellInfo;
+}
+
+void ImpEditEngine::SetRefDevice( OutputDevice* pRef )
+{
+ if ( bOwnerOfRefDev )
+ delete pRefDev;
+
+ pRefDev = pRef;
+ bOwnerOfRefDev = FALSE;
+
+ if ( !pRef )
+ pRefDev = EE_DLL()->GetGlobalData()->GetStdRefDevice();
+
+ nOnePixelInRef = (USHORT)pRefDev->PixelToLogic( Size( 1, 0 ) ).Width();
+
+ if ( IsFormatted() )
+ {
+ FormatFullDoc();
+ UpdateViews( (EditView*) 0);
+ }
+}
+
+void ImpEditEngine::SetRefMapMode( const MapMode& rMapMode )
+{
+ if ( GetRefDevice()->GetMapMode() == rMapMode )
+ return;
+
+ // Wenn RefDev == GlobalRefDev => eigenes anlegen!
+ if ( !bOwnerOfRefDev && ( pRefDev == EE_DLL()->GetGlobalData()->GetStdRefDevice() ) )
+ {
+ pRefDev = new VirtualDevice;
+ pRefDev->SetMapMode( MAP_TWIP );
+ SetRefDevice( pRefDev );
+ bOwnerOfRefDev = TRUE;
+ }
+ pRefDev->SetMapMode( rMapMode );
+ nOnePixelInRef = (USHORT)pRefDev->PixelToLogic( Size( 1, 0 ) ).Width();
+ if ( IsFormatted() )
+ {
+ FormatFullDoc();
+ UpdateViews( (EditView*) 0);
+ }
+}
+
+void ImpEditEngine::InitDoc( BOOL bKeepParaAttribs )
+{
+ USHORT nParas = aEditDoc.Count();
+ for ( USHORT n = bKeepParaAttribs ? 1 : 0; n < nParas; n++ )
+ {
+ if ( aEditDoc[n]->GetStyleSheet() )
+ EndListening( *aEditDoc[n]->GetStyleSheet(), FALSE );
+ }
+
+ if ( bKeepParaAttribs )
+ aEditDoc.RemoveText();
+ else
+ aEditDoc.Clear();
+
+ GetParaPortions().Reset();
+
+ ParaPortion* pIniPortion = new ParaPortion( aEditDoc[0] );
+ GetParaPortions().Insert( pIniPortion, 0 );
+
+ bFormatted = FALSE;
+
+ if ( IsCallParaInsertedOrDeleted() )
+ {
+ GetEditEnginePtr()->ParagraphDeleted( EE_PARA_ALL );
+ GetEditEnginePtr()->ParagraphInserted( 0 );
+ }
+
+#ifndef SVX_LIGHT
+ if ( GetStatus().DoOnlineSpelling() )
+ aEditDoc.GetObject( 0 )->CreateWrongList();
+#endif // !SVX_LIGHT
+}
+
+EditPaM ImpEditEngine::DeleteSelected( EditSelection aSel )
+{
+ EditPaM aPaM ( ImpDeleteSelection( aSel ) );
+ return aPaM;
+}
+
+XubString ImpEditEngine::GetSelected( const EditSelection& rSel, const LineEnd eEnd ) const
+{
+ XubString aText;
+ if ( !rSel.HasRange() )
+ return aText;
+
+ String aSep = EditDoc::GetSepStr( eEnd );
+
+ EditSelection aSel( rSel );
+ aSel.Adjust( aEditDoc );
+
+ ContentNode* pStartNode = aSel.Min().GetNode();
+ ContentNode* pEndNode = aSel.Max().GetNode();
+ USHORT nStartNode = aEditDoc.GetPos( pStartNode );
+ USHORT nEndNode = aEditDoc.GetPos( pEndNode );
+
+ DBG_ASSERT( nStartNode <= nEndNode, "Selektion nicht sortiert ?" );
+
+ // ueber die Absaetze iterieren...
+ for ( USHORT nNode = nStartNode; nNode <= nEndNode; nNode++ )
+ {
+ DBG_ASSERT( aEditDoc.SaveGetObject( nNode ), "Node nicht gefunden: GetSelected" );
+ 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();
+
+ aText += aEditDoc.GetParaAsString( pNode, nStartPos, nEndPos );
+ if ( nNode < nEndNode )
+ aText += aSep;
+ }
+ return aText;
+}
+
+BOOL ImpEditEngine::MouseButtonDown( const MouseEvent& rMEvt, EditView* pView )
+{
+ GetSelEngine().SetCurView( pView );
+ SetActiveView( pView );
+
+ if ( GetAutoCompleteText().Len() )
+ SetAutoCompleteText( String(), TRUE );
+
+ GetSelEngine().SelMouseButtonDown( rMEvt );
+ // Sonderbehandlungen
+ EditSelection aCurSel( pView->pImpEditView->GetEditSelection() );
+ if ( !rMEvt.IsShift() )
+ {
+ if ( rMEvt.GetClicks() == 2 )
+ {
+ // damit die SelectionEngine weiss, dass Anker.
+ aSelEngine.CursorPosChanging( TRUE, FALSE );
+
+ EditSelection aNewSelection( SelectWord( aCurSel ) );
+ pView->pImpEditView->DrawSelection();
+ pView->pImpEditView->SetEditSelection( aNewSelection );
+ pView->pImpEditView->DrawSelection();
+ pView->ShowCursor( TRUE, TRUE );
+ }
+ else if ( rMEvt.GetClicks() == 3 )
+ {
+ // damit die SelectionEngine weiss, dass Anker.
+ aSelEngine.CursorPosChanging( TRUE, FALSE );
+
+ EditSelection aNewSelection( aCurSel );
+ aNewSelection.Min().SetIndex( 0 );
+ aNewSelection.Max().SetIndex( aCurSel.Min().GetNode()->Len() );
+ pView->pImpEditView->DrawSelection();
+ pView->pImpEditView->SetEditSelection( aNewSelection );
+ pView->pImpEditView->DrawSelection();
+ pView->ShowCursor( TRUE, TRUE );
+ }
+ }
+ return TRUE;
+}
+
+void ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView )
+{
+ GetSelEngine().SetCurView( pView );
+ SetActiveView( pView );
+ if ( rCEvt.GetCommand() == COMMAND_VOICE )
+ {
+ const CommandVoiceData* pData = rCEvt.GetVoiceData();
+ if ( pData->GetType() == VOICECOMMANDTYPE_DICTATION )
+ {
+ // Funktionen auf KeyEvents umbiegen, wenn keine entsprechende
+ // Methode an EditView/EditEngine, damit Undo konsistent bleibt.
+
+ SfxPoolItem* pNewAttr = NULL;
+
+ switch ( pData->GetCommand() )
+ {
+ case DICTATIONCOMMAND_UNKNOWN:
+ {
+ pView->InsertText( pData->GetText() );
+ }
+ break;
+ case DICTATIONCOMMAND_NEWPARAGRAPH:
+ {
+ pView->PostKeyEvent( KeyEvent( 0, KeyCode( KEY_RETURN, 0 ) ) );
+ }
+ break;
+ case DICTATIONCOMMAND_NEWLINE:
+ {
+ pView->PostKeyEvent( KeyEvent( 0, KeyCode( KEY_RETURN, KEY_SHIFT ) ) );
+ }
+ break;
+ case DICTATIONCOMMAND_TAB:
+ {
+ pView->PostKeyEvent( KeyEvent( 0, KeyCode( KEY_TAB, 0 ) ) );
+ }
+ break;
+ case DICTATIONCOMMAND_LEFT:
+ {
+ pView->PostKeyEvent( KeyEvent( 0, KeyCode( KEY_LEFT, KEY_MOD1 ) ) );
+ }
+ break;
+ case DICTATIONCOMMAND_RIGHT:
+ {
+ pView->PostKeyEvent( KeyEvent( 0, KeyCode( KEY_RIGHT, KEY_MOD1 ) ) );
+ }
+ break;
+ case DICTATIONCOMMAND_UP:
+ {
+ pView->PostKeyEvent( KeyEvent( 0, KeyCode( KEY_UP, 0 ) ) );
+ }
+ break;
+ case DICTATIONCOMMAND_DOWN:
+ {
+ pView->PostKeyEvent( KeyEvent( 0, KeyCode( KEY_UP, 0 ) ) );
+ }
+ break;
+ case DICTATIONCOMMAND_UNDO:
+ {
+ pView->Undo();
+ }
+ break;
+ case DICTATIONCOMMAND_DEL:
+ {
+ pView->PostKeyEvent( KeyEvent( 0, KeyCode( KEY_LEFT, KEY_MOD1|KEY_SHIFT ) ) );
+ pView->DeleteSelected();
+ }
+ break;
+ case DICTATIONCOMMAND_BOLD_ON:
+ {
+ pNewAttr = new SvxWeightItem( WEIGHT_BOLD, EE_CHAR_WEIGHT );
+ }
+ break;
+ case DICTATIONCOMMAND_BOLD_OFF:
+ {
+ pNewAttr = new SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT );
+ }
+ break;
+ case DICTATIONCOMMAND_ITALIC_ON:
+ {
+ pNewAttr = new SvxPostureItem( ITALIC_NORMAL, EE_CHAR_ITALIC );
+ }
+ break;
+ case DICTATIONCOMMAND_ITALIC_OFF:
+ {
+ pNewAttr = new SvxPostureItem( ITALIC_NORMAL, EE_CHAR_ITALIC );
+ }
+ break;
+ case DICTATIONCOMMAND_UNDERLINE_ON:
+ {
+ pNewAttr = new SvxUnderlineItem( UNDERLINE_SINGLE, EE_CHAR_UNDERLINE );
+ }
+ break;
+ case DICTATIONCOMMAND_UNDERLINE_OFF:
+ {
+ pNewAttr = new SvxUnderlineItem( UNDERLINE_NONE, EE_CHAR_UNDERLINE );
+ }
+ break;
+ }
+
+ if ( pNewAttr )
+ {
+ SfxItemSet aSet( GetEmptyItemSet() );
+ aSet.Put( *pNewAttr );
+ pView->SetAttribs( aSet );
+ delete pNewAttr;
+ }
+ }
+ }
+ else if ( rCEvt.GetCommand() == COMMAND_STARTEXTTEXTINPUT )
+ {
+ pView->DeleteSelected();
+ delete mpIMEInfos;
+ EditPaM aPaM = pView->GetImpEditView()->GetEditSelection().Max();
+ String aOldTextAfterStartPos = aPaM.GetNode()->Copy( aPaM.GetIndex() );
+ USHORT nMax = aOldTextAfterStartPos.Search( CH_FEATURE );
+ if ( nMax != STRING_NOTFOUND ) // don't overwrite features!
+ aOldTextAfterStartPos.Erase( nMax );
+ mpIMEInfos = new ImplIMEInfos( aPaM, aOldTextAfterStartPos );
+ mpIMEInfos->bWasCursorOverwrite = !pView->IsInsertMode();
+ UndoActionStart( EDITUNDO_INSERT );
+ }
+ else if ( rCEvt.GetCommand() == COMMAND_ENDEXTTEXTINPUT )
+ {
+ DBG_ASSERT( mpIMEInfos, "COMMAND_ENDEXTTEXTINPUT => Kein Start ?" );
+ if( mpIMEInfos )
+ {
+ // #102812# convert quotes in IME text
+ // works on the last input character, this is escpecially in Korean text often done
+ // quotes that are inside of the string are not replaced!
+ // Borrowed from sw: edtwin.cxx
+ if ( mpIMEInfos->nLen )
+ {
+ EditSelection aSel( mpIMEInfos->aPos );
+ aSel.Min().GetIndex() += mpIMEInfos->nLen-1;
+ aSel.Max().GetIndex() =
+ aSel.Max().GetIndex() + mpIMEInfos->nLen;
+ // #102812# convert quotes in IME text
+ // works on the last input character, this is escpecially in Korean text often done
+ // quotes that are inside of the string are not replaced!
+ const sal_Unicode nCharCode = aSel.Min().GetNode()->GetChar( aSel.Min().GetIndex() );
+ if ( ( GetStatus().DoAutoCorrect() ) && ( ( nCharCode == '\"' ) || ( nCharCode == '\'' ) ) )
+ {
+ aSel = DeleteSelected( aSel );
+ aSel = AutoCorrect( aSel, nCharCode, mpIMEInfos->bWasCursorOverwrite );
+ pView->pImpEditView->SetEditSelection( aSel );
+ }
+ }
+
+ ParaPortion* pPortion = FindParaPortion( mpIMEInfos->aPos.GetNode() );
+ pPortion->MarkSelectionInvalid( mpIMEInfos->aPos.GetIndex(), 0 );
+
+ BOOL bWasCursorOverwrite = mpIMEInfos->bWasCursorOverwrite;
+
+ delete mpIMEInfos;
+ mpIMEInfos = NULL;
+
+ FormatAndUpdate( pView );
+
+ pView->SetInsertMode( !bWasCursorOverwrite );
+ }
+ UndoActionEnd( EDITUNDO_INSERT );
+ }
+ else if ( rCEvt.GetCommand() == COMMAND_EXTTEXTINPUT )
+ {
+ DBG_ASSERT( mpIMEInfos, "COMMAND_EXTTEXTINPUT => Kein Start ?" );
+ if( mpIMEInfos )
+ {
+ const CommandExtTextInputData* pData = rCEvt.GetExtTextInputData();
+
+ if ( !pData->IsOnlyCursorChanged() )
+ {
+ EditSelection aSel( mpIMEInfos->aPos );
+ aSel.Max().GetIndex() =
+ aSel.Max().GetIndex() + mpIMEInfos->nLen;
+ aSel = DeleteSelected( aSel );
+ aSel = ImpInsertText( aSel, pData->GetText() );
+
+ if ( mpIMEInfos->bWasCursorOverwrite )
+ {
+ USHORT nOldIMETextLen = mpIMEInfos->nLen;
+ USHORT nNewIMETextLen = pData->GetText().Len();
+
+ if ( ( nOldIMETextLen > nNewIMETextLen ) &&
+ ( nNewIMETextLen < mpIMEInfos->aOldTextAfterStartPos.Len() ) )
+ {
+ // restore old characters
+ USHORT nRestore = nOldIMETextLen - nNewIMETextLen;
+ EditPaM aPaM( mpIMEInfos->aPos );
+ aPaM.GetIndex() = aPaM.GetIndex() + nNewIMETextLen;
+ ImpInsertText( aPaM, mpIMEInfos->aOldTextAfterStartPos.Copy( nNewIMETextLen, nRestore ) );
+ }
+ else if ( ( nOldIMETextLen < nNewIMETextLen ) &&
+ ( nOldIMETextLen < mpIMEInfos->aOldTextAfterStartPos.Len() ) )
+ {
+ // overwrite
+ USHORT nOverwrite = nNewIMETextLen - nOldIMETextLen;
+ if ( ( nOldIMETextLen + nOverwrite ) > mpIMEInfos->aOldTextAfterStartPos.Len() )
+ nOverwrite = mpIMEInfos->aOldTextAfterStartPos.Len() - nOldIMETextLen;
+ DBG_ASSERT( nOverwrite && (nOverwrite < 0xFF00), "IME Overwrite?!" );
+ EditPaM aPaM( mpIMEInfos->aPos );
+ aPaM.GetIndex() = aPaM.GetIndex() + nNewIMETextLen;
+ EditSelection _aSel( aPaM );
+ _aSel.Max().GetIndex() =
+ _aSel.Max().GetIndex() + nOverwrite;
+ DeleteSelected( _aSel );
+ }
+ }
+ if ( pData->GetTextAttr() )
+ {
+ mpIMEInfos->CopyAttribs( pData->GetTextAttr(), pData->GetText().Len() );
+ mpIMEInfos->bCursor = pData->IsCursorVisible();
+ }
+ else
+ {
+ mpIMEInfos->DestroyAttribs();
+ mpIMEInfos->nLen = pData->GetText().Len();
+ }
+
+ ParaPortion* pPortion = FindParaPortion( mpIMEInfos->aPos.GetNode() );
+ pPortion->MarkSelectionInvalid( mpIMEInfos->aPos.GetIndex(), 0 );
+ FormatAndUpdate( pView );
+ }
+
+ EditSelection aNewSel = EditPaM( mpIMEInfos->aPos.GetNode(), mpIMEInfos->aPos.GetIndex()+pData->GetCursorPos() );
+ pView->SetSelection( CreateESel( aNewSel ) );
+ pView->SetInsertMode( !pData->IsCursorOverwrite() );
+
+ if ( pData->IsCursorVisible() )
+ pView->ShowCursor();
+ else
+ pView->HideCursor();
+ }
+ }
+ else if ( rCEvt.GetCommand() == COMMAND_INPUTCONTEXTCHANGE )
+ {
+ }
+ else if ( rCEvt.GetCommand() == COMMAND_CURSORPOS )
+ {
+ if ( mpIMEInfos && mpIMEInfos->nLen )
+ {
+ EditPaM aPaM( pView->pImpEditView->GetEditSelection().Max() );
+ Rectangle aR1 = PaMtoEditCursor( aPaM, 0 );
+
+ USHORT nInputEnd = mpIMEInfos->aPos.GetIndex() + mpIMEInfos->nLen;
+
+ if ( !IsFormatted() )
+ FormatDoc();
+
+ ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( GetEditDoc().GetPos( aPaM.GetNode() ) );
+ USHORT nLine = pParaPortion->GetLines().FindLine( aPaM.GetIndex(), sal_True );
+ EditLine* pLine = pParaPortion->GetLines().GetObject( nLine );
+ if ( pLine && ( nInputEnd > pLine->GetEnd() ) )
+ nInputEnd = pLine->GetEnd();
+ Rectangle aR2 = PaMtoEditCursor( EditPaM( aPaM.GetNode(), nInputEnd ), GETCRSR_ENDOFLINE );
+ Rectangle aRect = pView->GetImpEditView()->GetWindowPos( aR1 );
+ pView->GetWindow()->SetCursorRect( &aRect, aR2.Left()-aR1.Right() );
+ }
+ else
+ {
+ pView->GetWindow()->SetCursorRect();
+ }
+ }
+ else if ( rCEvt.GetCommand() == COMMAND_SELECTIONCHANGE )
+ {
+ const CommandSelectionChangeData *pData = rCEvt.GetSelectionChangeData();
+
+ ESelection aSelection = pView->GetSelection();
+ aSelection.Adjust();
+
+ if( pView->HasSelection() )
+ {
+ aSelection.nEndPos = aSelection.nStartPos;
+ aSelection.nStartPos += pData->GetStart();
+ aSelection.nEndPos += pData->GetEnd();
+ }
+ else
+ {
+ aSelection.nStartPos = pData->GetStart();
+ aSelection.nEndPos = pData->GetEnd();
+ }
+ pView->SetSelection( aSelection );
+ }
+ else if ( rCEvt.GetCommand() == COMMAND_PREPARERECONVERSION )
+ {
+ if ( pView->HasSelection() )
+ {
+ ESelection aSelection = pView->GetSelection();
+ aSelection.Adjust();
+
+ if ( aSelection.nStartPara != aSelection.nEndPara )
+ {
+ xub_StrLen aParaLen = pEditEngine->GetTextLen( aSelection.nStartPara );
+ aSelection.nEndPara = aSelection.nStartPara;
+ aSelection.nEndPos = aParaLen;
+ pView->SetSelection( aSelection );
+ }
+ }
+ }
+
+ GetSelEngine().Command( rCEvt );
+}
+
+BOOL ImpEditEngine::MouseButtonUp( const MouseEvent& rMEvt, EditView* pView )
+{
+ GetSelEngine().SetCurView( pView );
+ GetSelEngine().SelMouseButtonUp( rMEvt );
+ bInSelection = FALSE;
+ // Sonderbehandlungen
+ EditSelection aCurSel( pView->pImpEditView->GetEditSelection() );
+ if ( !aCurSel.HasRange() )
+ {
+ if ( ( rMEvt.GetClicks() == 1 ) && rMEvt.IsLeft() && !rMEvt.IsMod2() )
+ {
+ const SvxFieldItem* pFld = pView->GetFieldUnderMousePointer();
+ if ( pFld )
+ {
+ EditPaM aPaM( aCurSel.Max() );
+ USHORT nPara = GetEditDoc().GetPos( aPaM.GetNode() );
+ GetEditEnginePtr()->FieldClicked( *pFld, nPara, aPaM.GetIndex() );
+ }
+ }
+ }
+ return TRUE;
+}
+
+BOOL ImpEditEngine::MouseMove( const MouseEvent& rMEvt, EditView* pView )
+{
+ // MouseMove wird sofort nach ShowQuickHelp() gerufen!
+// if ( GetAutoCompleteText().Len() )
+// SetAutoCompleteText( String(), TRUE );
+ GetSelEngine().SetCurView( pView );
+ GetSelEngine().SelMouseMove( rMEvt );
+ return TRUE;
+}
+
+EditPaM ImpEditEngine::InsertText( EditSelection aSel, const XubString& rStr )
+{
+ EditPaM aPaM = ImpInsertText( aSel, rStr );
+ return aPaM;
+}
+
+EditPaM ImpEditEngine::Clear()
+{
+ InitDoc( FALSE );
+
+ EditPaM aPaM = aEditDoc.GetStartPaM();
+ EditSelection aSel( aPaM );
+
+ nCurTextHeight = 0;
+
+ ResetUndoManager();
+
+ for ( USHORT nView = aEditViews.Count(); nView; )
+ {
+ EditView* pView = aEditViews[--nView];
+ DBG_CHKOBJ( pView, EditView, 0 );
+ pView->pImpEditView->SetEditSelection( aSel );
+ }
+
+ return aPaM;
+}
+
+EditPaM ImpEditEngine::RemoveText()
+{
+ InitDoc( TRUE );
+
+ EditPaM aStartPaM = aEditDoc.GetStartPaM();
+ EditSelection aEmptySel( aStartPaM, aStartPaM );
+ for ( USHORT nView = 0; nView < aEditViews.Count(); nView++ )
+ {
+ EditView* pView = aEditViews.GetObject(nView);
+ DBG_CHKOBJ( pView, EditView, 0 );
+ pView->pImpEditView->SetEditSelection( aEmptySel );
+ }
+ ResetUndoManager();
+ return aEditDoc.GetStartPaM();
+}
+
+
+void ImpEditEngine::SetText( const XubString& rText )
+{
+ // RemoveText loescht die Undo-Liste!
+ EditPaM aStartPaM = RemoveText();
+ BOOL bUndoCurrentlyEnabled = IsUndoEnabled();
+ // Der von Hand reingesteckte Text kann nicht vom Anwender rueckgaengig gemacht werden.
+ EnableUndo( FALSE );
+
+ EditSelection aEmptySel( aStartPaM, aStartPaM );
+ EditPaM aPaM = aStartPaM;
+ if ( rText.Len() )
+ aPaM = ImpInsertText( aEmptySel, rText );
+
+ for ( USHORT nView = 0; nView < aEditViews.Count(); nView++ )
+ {
+ EditView* pView = aEditViews[nView];
+ DBG_CHKOBJ( pView, EditView, 0 );
+ pView->pImpEditView->SetEditSelection( EditSelection( aPaM, aPaM ) );
+ // Wenn kein Text, dann auch Kein Format&Update
+ // => Der Text bleibt stehen.
+ if ( !rText.Len() && GetUpdateMode() )
+ {
+ Rectangle aTmpRec( pView->GetOutputArea().TopLeft(),
+ Size( aPaperSize.Width(), nCurTextHeight ) );
+ aTmpRec.Intersection( pView->GetOutputArea() );
+ pView->GetWindow()->Invalidate( aTmpRec );
+ }
+ }
+ if( !rText.Len() ) // sonst muss spaeter noch invalidiert werden, !bFormatted reicht.
+ nCurTextHeight = 0;
+ EnableUndo( bUndoCurrentlyEnabled );
+#ifndef SVX_LIGHT
+ DBG_ASSERT( !HasUndoManager() || !GetUndoManager().GetUndoActionCount(), "Undo nach SetText?" );
+#endif
+}
+
+
+const SfxItemSet& ImpEditEngine::GetEmptyItemSet()
+{
+ if ( !pEmptyItemSet )
+ {
+ pEmptyItemSet = new SfxItemSet( aEditDoc.GetItemPool(), EE_ITEMS_START, EE_ITEMS_END );
+ for ( USHORT nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
+ {
+ pEmptyItemSet->ClearItem( nWhich );
+ }
+ }
+ return *pEmptyItemSet;
+}
+
+// ----------------------------------------------------------------------
+// MISC
+// ----------------------------------------------------------------------
+void ImpEditEngine::CursorMoved( ContentNode* pPrevNode )
+{
+ // Leere Attribute loeschen, aber nur, wenn Absatz nicht leer!
+ if ( pPrevNode->GetCharAttribs().HasEmptyAttribs() && pPrevNode->Len() )
+ pPrevNode->GetCharAttribs().DeleteEmptyAttribs( aEditDoc.GetItemPool() );
+}
+
+void ImpEditEngine::TextModified()
+{
+ bFormatted = FALSE;
+
+ if ( GetNotifyHdl().IsSet() )
+ {
+ EENotify aNotify( EE_NOTIFY_TEXTMODIFIED );
+ aNotify.pEditEngine = GetEditEnginePtr();
+ CallNotify( aNotify );
+ }
+}
+
+
+void ImpEditEngine::ParaAttribsChanged( ContentNode* pNode )
+{
+ DBG_ASSERT( pNode, "ParaAttribsChanged: Welcher?" );
+
+ aEditDoc.SetModified( TRUE );
+ bFormatted = FALSE;
+
+ ParaPortion* pPortion = FindParaPortion( pNode );
+ DBG_ASSERT( pPortion, "ParaAttribsChanged: Portion?" );
+ pPortion->MarkSelectionInvalid( 0, pNode->Len() );
+
+ USHORT nPara = aEditDoc.GetPos( pNode );
+ pEditEngine->ParaAttribsChanged( nPara );
+
+ ParaPortion* pNextPortion = GetParaPortions().SaveGetObject( nPara+1 );
+ // => wird sowieso noch formatiert, wenn Invalid.
+ if ( pNextPortion && !pNextPortion->IsInvalid() )
+ CalcHeight( pNextPortion );
+}
+
+// ----------------------------------------------------------------------
+// Cursorbewegungen
+// ----------------------------------------------------------------------
+
+EditSelection ImpEditEngine::MoveCursor( const KeyEvent& rKeyEvent, EditView* pEditView )
+{
+ // Eigentlich nur bei Up/Down noetig, aber was solls.
+ CheckIdleFormatter();
+
+ EditPaM aPaM( pEditView->pImpEditView->GetEditSelection().Max() );
+
+ EditPaM aOldPaM( aPaM );
+
+ TextDirectionality eTextDirection = TextDirectionality_LeftToRight_TopToBottom;
+ if ( IsVertical() )
+ eTextDirection = TextDirectionality_TopToBottom_RightToLeft;
+ else if ( IsRightToLeft( GetEditDoc().GetPos( aPaM.GetNode() ) ) )
+ eTextDirection = TextDirectionality_RightToLeft_TopToBottom;
+
+ KeyEvent aTranslatedKeyEvent = rKeyEvent.LogicalTextDirectionality( eTextDirection );
+
+ BOOL bCtrl = aTranslatedKeyEvent.GetKeyCode().IsMod1() ? TRUE : FALSE;
+ USHORT nCode = aTranslatedKeyEvent.GetKeyCode().GetCode();
+
+ if ( DoVisualCursorTraveling( aPaM.GetNode() ) )
+ {
+ // Only for simple cursor movement...
+ if ( !bCtrl && ( ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) ) )
+ {
+ aPaM = CursorVisualLeftRight( pEditView, aPaM, rKeyEvent.GetKeyCode().IsMod2() ? i18n::CharacterIteratorMode::SKIPCHARACTER : i18n::CharacterIteratorMode::SKIPCELL, rKeyEvent.GetKeyCode().GetCode() == KEY_LEFT );
+ nCode = 0; // skip switch statement
+ }
+ /*
+ else if ( !bCtrl && ( ( nCode == KEY_HOME ) || ( nCode == KEY_END ) ) )
+ {
+ aPaM = CursorVisualStartEnd( pEditView, aPaM, nCode == KEY_HOME );
+ nCode = 0; // skip switch statement
+ }
+ */
+ }
+
+ bool bKeyModifySelection = aTranslatedKeyEvent.GetKeyCode().IsShift();
+ switch ( nCode )
+ {
+ case KEY_UP: aPaM = CursorUp( aPaM, pEditView );
+ break;
+ case KEY_DOWN: aPaM = CursorDown( aPaM, pEditView );
+ break;
+ case KEY_LEFT: aPaM = bCtrl ? WordLeft( aPaM ) : CursorLeft( aPaM, aTranslatedKeyEvent.GetKeyCode().IsMod2() ? i18n::CharacterIteratorMode::SKIPCHARACTER : i18n::CharacterIteratorMode::SKIPCELL );
+ break;
+ case KEY_RIGHT: aPaM = bCtrl ? WordRight( aPaM ) : CursorRight( aPaM, aTranslatedKeyEvent.GetKeyCode().IsMod2() ? i18n::CharacterIteratorMode::SKIPCHARACTER : i18n::CharacterIteratorMode::SKIPCELL );
+ break;
+ case KEY_HOME: aPaM = bCtrl ? CursorStartOfDoc() : CursorStartOfLine( aPaM );
+ break;
+ case KEY_END: aPaM = bCtrl ? CursorEndOfDoc() : CursorEndOfLine( aPaM );
+ break;
+ case KEY_PAGEUP: aPaM = bCtrl ? CursorStartOfDoc() : PageUp( aPaM, pEditView );
+ break;
+ case KEY_PAGEDOWN: aPaM = bCtrl ? CursorEndOfDoc() : PageDown( aPaM, pEditView );
+ break;
+ case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE:
+ aPaM = CursorStartOfLine( aPaM );
+ bKeyModifySelection = false;
+ break;
+ case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE:
+ aPaM = CursorEndOfLine( aPaM );
+ bKeyModifySelection = false;
+ break;
+ case com::sun::star::awt::Key::MOVE_WORD_BACKWARD:
+ aPaM = WordLeft( aPaM );
+ bKeyModifySelection = false;
+ break;
+ case com::sun::star::awt::Key::MOVE_WORD_FORWARD:
+ aPaM = WordRight( aPaM );
+ bKeyModifySelection = false;
+ break;
+ case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
+ aPaM = CursorStartOfParagraph( aPaM );
+ if( aPaM == aOldPaM )
+ {
+ aPaM = CursorLeft( aPaM, i18n::CharacterIteratorMode::SKIPCELL );
+ aPaM = CursorStartOfParagraph( aPaM );
+ }
+ bKeyModifySelection = false;
+ break;
+ case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
+ aPaM = CursorEndOfParagraph( aPaM );
+ if( aPaM == aOldPaM )
+ {
+ aPaM = CursorRight( aPaM, i18n::CharacterIteratorMode::SKIPCELL );
+ aPaM = CursorEndOfParagraph( aPaM );
+ }
+ bKeyModifySelection = false;
+ break;
+ case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
+ aPaM = CursorStartOfDoc();
+ bKeyModifySelection = false;
+ break;
+ case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT:
+ aPaM = CursorEndOfDoc();
+ bKeyModifySelection = false;
+ break;
+ case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE:
+ aPaM = CursorStartOfLine( aPaM );
+ bKeyModifySelection = true;
+ break;
+ case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE:
+ aPaM = CursorEndOfLine( aPaM );
+ bKeyModifySelection = true;
+ break;
+ case com::sun::star::awt::Key::SELECT_BACKWARD:
+ aPaM = CursorLeft( aPaM, i18n::CharacterIteratorMode::SKIPCELL );
+ bKeyModifySelection = true;
+ break;
+ case com::sun::star::awt::Key::SELECT_FORWARD:
+ aPaM = CursorRight( aPaM, i18n::CharacterIteratorMode::SKIPCELL );
+ bKeyModifySelection = true;
+ break;
+ case com::sun::star::awt::Key::SELECT_WORD_BACKWARD:
+ aPaM = WordLeft( aPaM );
+ bKeyModifySelection = true;
+ break;
+ case com::sun::star::awt::Key::SELECT_WORD_FORWARD:
+ aPaM = WordRight( aPaM );
+ bKeyModifySelection = true;
+ break;
+ case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
+ aPaM = CursorStartOfParagraph( aPaM );
+ if( aPaM == aOldPaM )
+ {
+ aPaM = CursorLeft( aPaM, i18n::CharacterIteratorMode::SKIPCELL );
+ aPaM = CursorStartOfParagraph( aPaM );
+ }
+ bKeyModifySelection = true;
+ break;
+ case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
+ aPaM = CursorEndOfParagraph( aPaM );
+ if( aPaM == aOldPaM )
+ {
+ aPaM = CursorRight( aPaM, i18n::CharacterIteratorMode::SKIPCELL );
+ aPaM = CursorEndOfParagraph( aPaM );
+ }
+ bKeyModifySelection = true;
+ break;
+ case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
+ aPaM = CursorStartOfDoc();
+ bKeyModifySelection = true;
+ break;
+ case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT:
+ aPaM = CursorEndOfDoc();
+ bKeyModifySelection = true;
+ break;
+ }
+
+ if ( aOldPaM != aPaM )
+ {
+ CursorMoved( aOldPaM.GetNode() );
+ if ( aStatus.NotifyCursorMovements() && ( aOldPaM.GetNode() != aPaM.GetNode() ) )
+ {
+ aStatus.GetStatusWord() = aStatus.GetStatusWord() | EE_STAT_CRSRLEFTPARA;
+ aStatus.GetPrevParagraph() = aEditDoc.GetPos( aOldPaM.GetNode() );
+ }
+ }
+ else
+ aStatus.GetStatusWord() = aStatus.GetStatusWord() | EE_STAT_CRSRMOVEFAIL;
+
+ // Bewirkt evtl. ein CreateAnchor oder Deselection all
+ aSelEngine.SetCurView( pEditView );
+ aSelEngine.CursorPosChanging( bKeyModifySelection, aTranslatedKeyEvent.GetKeyCode().IsMod1() );
+ EditPaM aOldEnd( pEditView->pImpEditView->GetEditSelection().Max() );
+ pEditView->pImpEditView->GetEditSelection().Max() = aPaM;
+ if ( bKeyModifySelection )
+ {
+ // Dann wird die Selektion erweitert...
+ EditSelection aTmpNewSel( aOldEnd, aPaM );
+ pEditView->pImpEditView->DrawSelection( aTmpNewSel );
+ }
+ else
+ pEditView->pImpEditView->GetEditSelection().Min() = aPaM;
+
+ return pEditView->pImpEditView->GetEditSelection();
+}
+
+EditPaM ImpEditEngine::CursorVisualStartEnd( EditView* pEditView, const EditPaM& rPaM, BOOL bStart )
+{
+ EditPaM aPaM( rPaM );
+
+ USHORT nPara = GetEditDoc().GetPos( aPaM.GetNode() );
+ ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
+
+ USHORT nLine = pParaPortion->GetLines().FindLine( aPaM.GetIndex(), sal_False );
+ EditLine* pLine = pParaPortion->GetLines().GetObject( nLine );
+ BOOL bEmptyLine = pLine->GetStart() == pLine->GetEnd();
+
+ pEditView->pImpEditView->nExtraCursorFlags = 0;
+
+ if ( !bEmptyLine )
+ {
+ String aLine( *aPaM.GetNode(), pLine->GetStart(), pLine->GetEnd() - pLine->GetStart() );
+// USHORT nPosInLine = aPaM.GetIndex() - pLine->GetStart();
+
+ const sal_Unicode* pLineString = aLine.GetBuffer();
+
+ UErrorCode nError = U_ZERO_ERROR;
+ UBiDi* pBidi = ubidi_openSized( aLine.Len(), 0, &nError );
+
+ const UBiDiLevel nBidiLevel = IsRightToLeft( nPara ) ? 1 /*RTL*/ : 0 /*LTR*/;
+ ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(pLineString), aLine.Len(), nBidiLevel, NULL, &nError ); // UChar != sal_Unicode in MinGW
+
+ USHORT nVisPos = bStart ? 0 : aLine.Len()-1;
+ USHORT nLogPos = (USHORT)ubidi_getLogicalIndex( pBidi, nVisPos, &nError );
+
+ ubidi_close( pBidi );
+
+ aPaM.GetIndex() = nLogPos + pLine->GetStart();
+
+ USHORT nTmp;
+ USHORT nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nTmp, TRUE );
+ TextPortion* pTextPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );
+ USHORT nRTLLevel = pTextPortion->GetRightToLeft();
+// BOOL bParaRTL = IsRightToLeft( nPara );
+ BOOL bPortionRTL = nRTLLevel%2 ? TRUE : FALSE;
+
+ if ( bStart )
+ {
+ pEditView->pImpEditView->SetCursorBidiLevel( bPortionRTL ? 0 : 1 );
+ // Maybe we must be *behind* the character
+ if ( bPortionRTL && pEditView->IsInsertMode() )
+ aPaM.GetIndex()++;
+ }
+ else
+ {
+ pEditView->pImpEditView->SetCursorBidiLevel( bPortionRTL ? 1 : 0 );
+ if ( !bPortionRTL && pEditView->IsInsertMode() )
+ aPaM.GetIndex()++;
+ }
+ }
+
+ return aPaM;
+}
+
+EditPaM ImpEditEngine::CursorVisualLeftRight( EditView* pEditView, const EditPaM& rPaM, USHORT nCharacterIteratorMode, BOOL bVisualToLeft )
+{
+ EditPaM aPaM( rPaM );
+
+ USHORT nPara = GetEditDoc().GetPos( aPaM.GetNode() );
+ ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
+
+ USHORT nLine = pParaPortion->GetLines().FindLine( aPaM.GetIndex(), sal_False );
+ EditLine* pLine = pParaPortion->GetLines().GetObject( nLine );
+ BOOL bEmptyLine = pLine->GetStart() == pLine->GetEnd();
+
+// USHORT nCurrentCursorFlags = pEditView->pImpEditView->nExtraCursorFlags;
+ pEditView->pImpEditView->nExtraCursorFlags = 0;
+
+ BOOL bParaRTL = IsRightToLeft( nPara );
+
+ BOOL bDone = FALSE;
+
+ if ( bEmptyLine )
+ {
+ if ( bVisualToLeft )
+ {
+ aPaM = CursorUp( aPaM, pEditView );
+ if ( aPaM != rPaM )
+ aPaM = CursorVisualStartEnd( pEditView, aPaM, FALSE );
+ }
+ else
+ {
+ aPaM = CursorDown( aPaM, pEditView );
+ if ( aPaM != rPaM )
+ aPaM = CursorVisualStartEnd( pEditView, aPaM, TRUE );
+ }
+
+ bDone = TRUE;
+ }
+
+ BOOL bLogicalBackward = bParaRTL ? !bVisualToLeft : bVisualToLeft;
+
+ if ( !bDone && pEditView->IsInsertMode() )
+ {
+ // Check if we are within a portion and don't have overwrite mode, then it's easy...
+ USHORT nPortionStart;
+ USHORT nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nPortionStart, FALSE );
+ TextPortion* pTextPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );
+
+ BOOL bPortionBoundary = ( aPaM.GetIndex() == nPortionStart ) || ( aPaM.GetIndex() == (nPortionStart+pTextPortion->GetLen()) );
+ USHORT nRTLLevel = pTextPortion->GetRightToLeft();
+
+ // Portion boundary doesn't matter if both have same RTL level
+ USHORT nRTLLevelNextPortion = 0xFFFF;
+ if ( bPortionBoundary && aPaM.GetIndex() && ( aPaM.GetIndex() < aPaM.GetNode()->Len() ) )
+ {
+ USHORT nTmp;
+ USHORT nNextTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex()+1, nTmp, bLogicalBackward ? FALSE : TRUE );
+ TextPortion* pNextTextPortion = pParaPortion->GetTextPortions().GetObject( nNextTextPortion );
+ nRTLLevelNextPortion = pNextTextPortion->GetRightToLeft();
+ }
+
+ if ( !bPortionBoundary || ( nRTLLevel == nRTLLevelNextPortion ) )
+ {
+ if ( ( bVisualToLeft && !(nRTLLevel%2) ) || ( !bVisualToLeft && (nRTLLevel%2) ) )
+ {
+ aPaM = CursorLeft( aPaM, nCharacterIteratorMode );
+ pEditView->pImpEditView->SetCursorBidiLevel( 1 );
+ }
+ else
+ {
+ aPaM = CursorRight( aPaM, nCharacterIteratorMode );
+ pEditView->pImpEditView->SetCursorBidiLevel( 0 );
+ }
+ bDone = TRUE;
+ }
+ }
+
+ if ( !bDone )
+ {
+ BOOL bGotoStartOfNextLine = FALSE;
+ BOOL bGotoEndOfPrevLine = FALSE;
+
+ String aLine( *aPaM.GetNode(), pLine->GetStart(), pLine->GetEnd() - pLine->GetStart() );
+ USHORT nPosInLine = aPaM.GetIndex() - pLine->GetStart();
+
+ const sal_Unicode* pLineString = aLine.GetBuffer();
+
+ UErrorCode nError = U_ZERO_ERROR;
+ UBiDi* pBidi = ubidi_openSized( aLine.Len(), 0, &nError );
+
+ const UBiDiLevel nBidiLevel = IsRightToLeft( nPara ) ? 1 /*RTL*/ : 0 /*LTR*/;
+ ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(pLineString), aLine.Len(), nBidiLevel, NULL, &nError ); // UChar != sal_Unicode in MinGW
+
+ if ( !pEditView->IsInsertMode() )
+ {
+ BOOL bEndOfLine = nPosInLine == aLine.Len();
+ USHORT nVisPos = (USHORT)ubidi_getVisualIndex( pBidi, !bEndOfLine ? nPosInLine : nPosInLine-1, &nError );
+ if ( bVisualToLeft )
+ {
+ bGotoEndOfPrevLine = nVisPos == 0;
+ if ( !bEndOfLine )
+ nVisPos--;
+ }
+ else
+ {
+ bGotoStartOfNextLine = nVisPos == (aLine.Len() - 1);
+ if ( !bEndOfLine )
+ nVisPos++;
+ }
+
+ if ( !bGotoEndOfPrevLine && !bGotoStartOfNextLine )
+ {
+ USHORT nLogPos = (USHORT)ubidi_getLogicalIndex( pBidi, nVisPos, &nError );
+ aPaM.GetIndex() = pLine->GetStart() + nLogPos;
+ pEditView->pImpEditView->SetCursorBidiLevel( 0 );
+ }
+ }
+ else
+ {
+ BOOL bWasBehind = FALSE;
+ BOOL bBeforePortion = !nPosInLine || pEditView->pImpEditView->GetCursorBidiLevel() == 1;
+ if ( nPosInLine && ( !bBeforePortion ) ) // before the next portion
+ bWasBehind = TRUE; // step one back, otherwise visual will be unusable when rtl portion follows.
+
+ USHORT nPortionStart;
+ USHORT nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nPortionStart, bBeforePortion );
+ TextPortion* pTextPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );
+ BOOL bRTLPortion = (pTextPortion->GetRightToLeft() % 2) != 0;
+
+ // -1: We are 'behind' the character
+ long nVisPos = (long)ubidi_getVisualIndex( pBidi, bWasBehind ? nPosInLine-1 : nPosInLine, &nError );
+ if ( bVisualToLeft )
+ {
+ if ( !bWasBehind || bRTLPortion )
+ nVisPos--;
+ }
+ else
+ {
+ if ( bWasBehind || bRTLPortion || bBeforePortion )
+ nVisPos++;
+// if ( bWasBehind && bRTLPortion )
+// nVisPos++;
+ }
+
+ bGotoEndOfPrevLine = nVisPos < 0;
+ bGotoStartOfNextLine = nVisPos >= aLine.Len();
+
+ if ( !bGotoEndOfPrevLine && !bGotoStartOfNextLine )
+ {
+ USHORT nLogPos = (USHORT)ubidi_getLogicalIndex( pBidi, nVisPos, &nError );
+
+/*
+ if ( nLogPos == aPaM.GetIndex() )
+ {
+ if ( bVisualToLeft )
+ bGotoEndOfPrevLine = TRUE;
+ else
+ bGotoStartOfNextLine = TRUE;
+ }
+ else
+*/
+ {
+ aPaM.GetIndex() = pLine->GetStart() + nLogPos;
+
+ // RTL portion, stay visually on the left side.
+ USHORT _nPortionStart;
+ // USHORT nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nPortionStart, !bRTLPortion );
+ USHORT _nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), _nPortionStart, TRUE );
+ TextPortion* _pTextPortion = pParaPortion->GetTextPortions().GetObject( _nTextPortion );
+ if ( bVisualToLeft && !bRTLPortion && ( _pTextPortion->GetRightToLeft() % 2 ) )
+ aPaM.GetIndex()++;
+ else if ( !bVisualToLeft && bRTLPortion && ( bWasBehind || !(_pTextPortion->GetRightToLeft() % 2 )) )
+ aPaM.GetIndex()++;
+
+ pEditView->pImpEditView->SetCursorBidiLevel( _nPortionStart );
+ }
+ }
+ }
+
+ ubidi_close( pBidi );
+
+ if ( bGotoEndOfPrevLine )
+ {
+ aPaM = CursorUp( aPaM, pEditView );
+ if ( aPaM != rPaM )
+ aPaM = CursorVisualStartEnd( pEditView, aPaM, FALSE );
+ }
+ else if ( bGotoStartOfNextLine )
+ {
+ aPaM = CursorDown( aPaM, pEditView );
+ if ( aPaM != rPaM )
+ aPaM = CursorVisualStartEnd( pEditView, aPaM, TRUE );
+ }
+ }
+ return aPaM;
+}
+
+
+EditPaM ImpEditEngine::CursorLeft( const EditPaM& rPaM, USHORT nCharacterIteratorMode )
+{
+ EditPaM aCurPaM( rPaM );
+ EditPaM aNewPaM( aCurPaM );
+
+ if ( aCurPaM.GetIndex() )
+ {
+ sal_Int32 nCount = 1;
+ uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
+ aNewPaM.SetIndex( (USHORT)_xBI->previousCharacters( *aNewPaM.GetNode(), aNewPaM.GetIndex(), GetLocale( aNewPaM ), nCharacterIteratorMode, nCount, nCount ) );
+ }
+ else
+ {
+ ContentNode* pNode = aCurPaM.GetNode();
+ pNode = GetPrevVisNode( pNode );
+ if ( pNode )
+ {
+ aNewPaM.SetNode( pNode );
+ aNewPaM.SetIndex( pNode->Len() );
+ }
+ }
+
+ return aNewPaM;
+}
+
+EditPaM ImpEditEngine::CursorRight( const EditPaM& rPaM, USHORT nCharacterIteratorMode )
+{
+ EditPaM aCurPaM( rPaM );
+ EditPaM aNewPaM( aCurPaM );
+
+ if ( aCurPaM.GetIndex() < aCurPaM.GetNode()->Len() )
+ {
+ uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
+ sal_Int32 nCount = 1;
+ aNewPaM.SetIndex( (USHORT)_xBI->nextCharacters( *aNewPaM.GetNode(), aNewPaM.GetIndex(), GetLocale( aNewPaM ), nCharacterIteratorMode, nCount, nCount ) );
+ }
+ else
+ {
+ ContentNode* pNode = aCurPaM.GetNode();
+ pNode = GetNextVisNode( pNode );
+ if ( pNode )
+ {
+ aNewPaM.SetNode( pNode );
+ aNewPaM.SetIndex( 0 );
+ }
+ }
+
+ return aNewPaM;
+}
+
+EditPaM ImpEditEngine::CursorUp( const EditPaM& rPaM, EditView* pView )
+{
+ DBG_ASSERT( pView, "Keine View - Keine Cursorbewegung!" );
+
+ ParaPortion* pPPortion = FindParaPortion( rPaM.GetNode() );
+ DBG_ASSERT( pPPortion, "Keine passende Portion gefunden: CursorUp" );
+ USHORT nLine = pPPortion->GetLineNumber( rPaM.GetIndex() );
+ EditLine* pLine = pPPortion->GetLines().GetObject( nLine );
+
+ long nX;
+ if ( pView->pImpEditView->nTravelXPos == TRAVEL_X_DONTKNOW )
+ {
+ nX = GetXPos( pPPortion, pLine, rPaM.GetIndex() );
+ pView->pImpEditView->nTravelXPos = nX+nOnePixelInRef;
+ }
+ else
+ nX = pView->pImpEditView->nTravelXPos;
+
+ EditPaM aNewPaM( rPaM );
+ if ( nLine ) // gleicher Absatz
+ {
+ EditLine* pPrevLine = pPPortion->GetLines().GetObject(nLine-1);
+ aNewPaM.SetIndex( GetChar( pPPortion, pPrevLine, nX ) );
+ // Wenn davor eine autom.Umgebrochene Zeile, und ich muss genau an das
+ // Ende dieser Zeile, landet der Cursor in der aktuellen Zeile am Anfang
+ // Siehe Problem: Letztes Zeichen einer autom.umgebr. Zeile = Cursor
+ if ( aNewPaM.GetIndex() && ( aNewPaM.GetIndex() == pLine->GetStart() ) )
+ aNewPaM = CursorLeft( aNewPaM );
+ }
+ else // vorheriger Absatz
+ {
+ ParaPortion* pPrevPortion = GetPrevVisPortion( pPPortion );
+ if ( pPrevPortion )
+ {
+ pLine = pPrevPortion->GetLines().GetObject( pPrevPortion->GetLines().Count()-1 );
+ DBG_ASSERT( pLine, "Zeile davor nicht gefunden: CursorUp" );
+ aNewPaM.SetNode( pPrevPortion->GetNode() );
+ aNewPaM.SetIndex( GetChar( pPrevPortion, pLine, nX+nOnePixelInRef ) );
+ }
+ }
+
+ return aNewPaM;
+}
+
+EditPaM ImpEditEngine::CursorDown( const EditPaM& rPaM, EditView* pView )
+{
+ DBG_ASSERT( pView, "Keine View - Keine Cursorbewegung!" );
+
+ ParaPortion* pPPortion = FindParaPortion( rPaM.GetNode() );
+ DBG_ASSERT( pPPortion, "Keine passende Portion gefunden: CursorDown" );
+ USHORT nLine = pPPortion->GetLineNumber( rPaM.GetIndex() );
+
+ long nX;
+ if ( pView->pImpEditView->nTravelXPos == TRAVEL_X_DONTKNOW )
+ {
+ EditLine* pLine = pPPortion->GetLines().GetObject(nLine);
+ nX = GetXPos( pPPortion, pLine, rPaM.GetIndex() );
+ pView->pImpEditView->nTravelXPos = nX+nOnePixelInRef;
+ }
+ else
+ nX = pView->pImpEditView->nTravelXPos;
+
+ EditPaM aNewPaM( rPaM );
+ if ( nLine < pPPortion->GetLines().Count()-1 )
+ {
+ EditLine* pNextLine = pPPortion->GetLines().GetObject(nLine+1);
+ aNewPaM.SetIndex( GetChar( pPPortion, pNextLine, nX ) );
+ // Sonderbehandlung siehe CursorUp...
+ if ( ( aNewPaM.GetIndex() == pNextLine->GetEnd() ) && ( aNewPaM.GetIndex() > pNextLine->GetStart() ) && ( aNewPaM.GetIndex() < pPPortion->GetNode()->Len() ) )
+ aNewPaM = CursorLeft( aNewPaM );
+ }
+ else // naechster Absatz
+ {
+ ParaPortion* pNextPortion = GetNextVisPortion( pPPortion );
+ if ( pNextPortion )
+ {
+ EditLine* pLine = pNextPortion->GetLines().GetObject(0);
+ DBG_ASSERT( pLine, "Zeile davor nicht gefunden: CursorUp" );
+ aNewPaM.SetNode( pNextPortion->GetNode() );
+ // Nie ganz ans Ende wenn mehrere Zeilen, da dann eine
+ // Zeile darunter der Cursor angezeigt wird.
+ aNewPaM.SetIndex( GetChar( pNextPortion, pLine, nX+nOnePixelInRef ) );
+ if ( ( aNewPaM.GetIndex() == pLine->GetEnd() ) && ( aNewPaM.GetIndex() > pLine->GetStart() ) && ( pNextPortion->GetLines().Count() > 1 ) )
+ aNewPaM = CursorLeft( aNewPaM );
+ }
+ }
+
+ return aNewPaM;
+}
+
+EditPaM ImpEditEngine::CursorStartOfLine( const EditPaM& rPaM )
+{
+ ParaPortion* pCurPortion = FindParaPortion( rPaM.GetNode() );
+ DBG_ASSERT( pCurPortion, "Keine Portion fuer den PaM ?" );
+ USHORT nLine = pCurPortion->GetLineNumber( rPaM.GetIndex() );
+ EditLine* pLine = pCurPortion->GetLines().GetObject(nLine);
+ DBG_ASSERT( pLine, "Aktuelle Zeile nicht gefunden ?!" );
+
+ EditPaM aNewPaM( rPaM );
+ aNewPaM.SetIndex( pLine->GetStart() );
+ return aNewPaM;
+}
+
+EditPaM ImpEditEngine::CursorEndOfLine( const EditPaM& rPaM )
+{
+ ParaPortion* pCurPortion = FindParaPortion( rPaM.GetNode() );
+ DBG_ASSERT( pCurPortion, "Keine Portion fuer den PaM ?" );
+ USHORT nLine = pCurPortion->GetLineNumber( rPaM.GetIndex() );
+ EditLine* pLine = pCurPortion->GetLines().GetObject(nLine);
+ DBG_ASSERT( pLine, "Aktuelle Zeile nicht gefunden ?!" );
+
+ EditPaM aNewPaM( rPaM );
+ aNewPaM.SetIndex( pLine->GetEnd() );
+ if ( pLine->GetEnd() > pLine->GetStart() )
+ {
+// xub_Unicode cLastChar = aNewPaM.GetNode()->GetChar( aNewPaM.GetIndex()-1 );
+ if ( aNewPaM.GetNode()->IsFeature( aNewPaM.GetIndex() - 1 ) )
+ {
+ // Bei einem weichen Umbruch muss ich davor stehen!
+ EditCharAttrib* pNextFeature = aNewPaM.GetNode()->GetCharAttribs().FindFeature( aNewPaM.GetIndex()-1 );
+ if ( pNextFeature && ( pNextFeature->GetItem()->Which() == EE_FEATURE_LINEBR ) )
+ aNewPaM = CursorLeft( aNewPaM );
+ }
+ else if ( ( aNewPaM.GetNode()->GetChar( aNewPaM.GetIndex() - 1 ) == ' ' ) && ( aNewPaM.GetIndex() != aNewPaM.GetNode()->Len() ) )
+ {
+ // Bei einem Blank in einer autom. umgebrochenen Zeile macht es Sinn,
+ // davor zu stehen, da der Anwender hinter das Wort will.
+ // Wenn diese geaendert wird, Sonderbehandlung fuer Pos1 nach End!
+ aNewPaM = CursorLeft( aNewPaM );
+ }
+ }
+ return aNewPaM;
+}
+
+EditPaM ImpEditEngine::CursorStartOfParagraph( const EditPaM& rPaM )
+{
+ EditPaM aPaM( rPaM.GetNode(), 0 );
+ return aPaM;
+}
+
+EditPaM ImpEditEngine::CursorEndOfParagraph( const EditPaM& rPaM )
+{
+ EditPaM aPaM( rPaM.GetNode(), rPaM.GetNode()->Len() );
+ return aPaM;
+}
+
+EditPaM ImpEditEngine::CursorStartOfDoc()
+{
+ EditPaM aPaM( aEditDoc.SaveGetObject( 0 ), 0 );
+ return aPaM;
+}
+
+EditPaM ImpEditEngine::CursorEndOfDoc()
+{
+ ContentNode* pLastNode = aEditDoc.SaveGetObject( aEditDoc.Count()-1 );
+ ParaPortion* pLastPortion = GetParaPortions().SaveGetObject( aEditDoc.Count()-1 );
+ DBG_ASSERT( pLastNode && pLastPortion, "CursorEndOfDoc: Node oder Portion nicht gefunden" );
+
+ if ( !pLastPortion->IsVisible() )
+ {
+ pLastNode = GetPrevVisNode( pLastPortion->GetNode() );
+ DBG_ASSERT( pLastNode, "Kein sichtbarer Absatz?" );
+ if ( !pLastNode )
+ pLastNode = aEditDoc.SaveGetObject( aEditDoc.Count()-1 );
+ }
+
+ EditPaM aPaM( pLastNode, pLastNode->Len() );
+ return aPaM;
+}
+
+EditPaM ImpEditEngine::PageUp( const EditPaM& rPaM, EditView* pView )
+{
+ Rectangle aRec = PaMtoEditCursor( rPaM );
+ Point aTopLeft = aRec.TopLeft();
+ aTopLeft.Y() -= pView->GetVisArea().GetHeight() *9/10;
+ aTopLeft.X() += nOnePixelInRef;
+ if ( aTopLeft.Y() < 0 )
+ {
+ aTopLeft.Y() = 0;
+ }
+ return GetPaM( aTopLeft );
+}
+
+EditPaM ImpEditEngine::PageDown( const EditPaM& rPaM, EditView* pView )
+{
+ Rectangle aRec = PaMtoEditCursor( rPaM );
+ Point aBottomRight = aRec.BottomRight();
+ aBottomRight.Y() += pView->GetVisArea().GetHeight() *9/10;
+ aBottomRight.X() += nOnePixelInRef;
+ long nHeight = GetTextHeight();
+ if ( aBottomRight.Y() > nHeight )
+ {
+ aBottomRight.Y() = nHeight-2;
+ }
+ return GetPaM( aBottomRight );
+}
+
+EditPaM ImpEditEngine::WordLeft( const EditPaM& rPaM, sal_Int16 nWordType )
+{
+ USHORT nCurrentPos = rPaM.GetIndex();
+ EditPaM aNewPaM( rPaM );
+ if ( nCurrentPos == 0 )
+ {
+ // Vorheriger Absatz...
+ USHORT nCurPara = aEditDoc.GetPos( aNewPaM.GetNode() );
+ ContentNode* pPrevNode = aEditDoc.SaveGetObject( --nCurPara );
+ if ( pPrevNode )
+ {
+ aNewPaM.SetNode( pPrevNode );
+ aNewPaM.SetIndex( pPrevNode->Len() );
+ }
+ }
+ else
+ {
+ // we need to increase the position by 1 when retrieving the locale
+ // since the attribute for the char left to the cursor position is returned
+ EditPaM aTmpPaM( aNewPaM );
+ xub_StrLen nMax = rPaM.GetNode()->Len();
+ if ( aTmpPaM.GetIndex() < nMax )
+ aTmpPaM.SetIndex( aTmpPaM.GetIndex() + 1 );
+ lang::Locale aLocale( GetLocale( aTmpPaM ) );
+
+ uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
+ i18n::Boundary aBoundary = _xBI->getWordBoundary( *aNewPaM.GetNode(), nCurrentPos, aLocale, nWordType, sal_True );
+ if ( aBoundary.startPos >= nCurrentPos )
+ aBoundary = _xBI->previousWord( *aNewPaM.GetNode(), nCurrentPos, aLocale, nWordType );
+ aNewPaM.SetIndex( ( aBoundary.startPos != (-1) ) ? (USHORT)aBoundary.startPos : 0 );
+ }
+
+ return aNewPaM;
+}
+
+EditPaM ImpEditEngine::WordRight( const EditPaM& rPaM, sal_Int16 nWordType )
+{
+ xub_StrLen nMax = rPaM.GetNode()->Len();
+ EditPaM aNewPaM( rPaM );
+ if ( aNewPaM.GetIndex() < nMax )
+ {
+ // we need to increase the position by 1 when retrieving the locale
+ // since the attribute for the char left to the cursor position is returned
+ EditPaM aTmpPaM( aNewPaM );
+ aTmpPaM.SetIndex( aTmpPaM.GetIndex() + 1 );
+ lang::Locale aLocale( GetLocale( aTmpPaM ) );
+
+ uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
+ i18n::Boundary aBoundary = _xBI->nextWord( *aNewPaM.GetNode(), aNewPaM.GetIndex(), aLocale, nWordType );
+ aNewPaM.SetIndex( (USHORT)aBoundary.startPos );
+ }
+ // not 'else', maybe the index reached nMax now...
+ if ( aNewPaM.GetIndex() >= nMax )
+ {
+ // Naechster Absatz...
+ USHORT nCurPara = aEditDoc.GetPos( aNewPaM.GetNode() );
+ ContentNode* pNextNode = aEditDoc.SaveGetObject( ++nCurPara );
+ if ( pNextNode )
+ {
+ aNewPaM.SetNode( pNextNode );
+ aNewPaM.SetIndex( 0 );
+ }
+ }
+ return aNewPaM;
+}
+
+EditPaM ImpEditEngine::StartOfWord( const EditPaM& rPaM, sal_Int16 nWordType )
+{
+ EditPaM aNewPaM( rPaM );
+
+ // we need to increase the position by 1 when retrieving the locale
+ // since the attribute for the char left to the cursor position is returned
+ EditPaM aTmpPaM( aNewPaM );
+ xub_StrLen nMax = rPaM.GetNode()->Len();
+ if ( aTmpPaM.GetIndex() < nMax )
+ aTmpPaM.SetIndex( aTmpPaM.GetIndex() + 1 );
+ lang::Locale aLocale( GetLocale( aTmpPaM ) );
+
+ uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
+ i18n::Boundary aBoundary = _xBI->getWordBoundary( *rPaM.GetNode(), rPaM.GetIndex(), aLocale, nWordType, sal_True );
+ aNewPaM.SetIndex( (USHORT)aBoundary.startPos );
+ return aNewPaM;
+}
+
+EditPaM ImpEditEngine::EndOfWord( const EditPaM& rPaM, sal_Int16 nWordType )
+{
+ EditPaM aNewPaM( rPaM );
+
+ // we need to increase the position by 1 when retrieving the locale
+ // since the attribute for the char left to the cursor position is returned
+ EditPaM aTmpPaM( aNewPaM );
+ xub_StrLen nMax = rPaM.GetNode()->Len();
+ if ( aTmpPaM.GetIndex() < nMax )
+ aTmpPaM.SetIndex( aTmpPaM.GetIndex() + 1 );
+ lang::Locale aLocale( GetLocale( aTmpPaM ) );
+
+ uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
+ i18n::Boundary aBoundary = _xBI->getWordBoundary( *rPaM.GetNode(), rPaM.GetIndex(), aLocale, nWordType, sal_True );
+ aNewPaM.SetIndex( (USHORT)aBoundary.endPos );
+ return aNewPaM;
+}
+
+EditSelection ImpEditEngine::SelectWord( const EditSelection& rCurSel, sal_Int16 nWordType, BOOL bAcceptStartOfWord )
+{
+ EditSelection aNewSel( rCurSel );
+ EditPaM aPaM( rCurSel.Max() );
+
+ // we need to increase the position by 1 when retrieving the locale
+ // since the attribute for the char left to the cursor position is returned
+ EditPaM aTmpPaM( aPaM );
+ xub_StrLen nMax = aPaM.GetNode()->Len();
+ if ( aTmpPaM.GetIndex() < nMax )
+ aTmpPaM.SetIndex( aTmpPaM.GetIndex() + 1 );
+ lang::Locale aLocale( GetLocale( aTmpPaM ) );
+
+ uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
+ sal_Int16 nType = _xBI->getWordType( *aPaM.GetNode(), aPaM.GetIndex(), aLocale );
+ if ( nType == i18n::WordType::ANY_WORD )
+ {
+ i18n::Boundary aBoundary = _xBI->getWordBoundary( *aPaM.GetNode(), aPaM.GetIndex(), aLocale, nWordType, sal_True );
+ // don't select when curser at end of word
+ if ( ( aBoundary.endPos > aPaM.GetIndex() ) &&
+ ( ( aBoundary.startPos < aPaM.GetIndex() ) || ( bAcceptStartOfWord && ( aBoundary.startPos == aPaM.GetIndex() ) ) ) )
+ {
+ aNewSel.Min().SetIndex( (USHORT)aBoundary.startPos );
+ aNewSel.Max().SetIndex( (USHORT)aBoundary.endPos );
+ }
+ }
+
+ return aNewSel;
+}
+
+EditSelection ImpEditEngine::SelectSentence( const EditSelection& rCurSel )
+{
+ uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
+ const EditPaM& rPaM = rCurSel.Min();
+ const ContentNode* pNode = rPaM.GetNode();
+ // #i50710# line breaks are marked with 0x01 - the break iterator prefers 0x0a for that
+ String sParagraph(*pNode);
+ sParagraph.SearchAndReplaceAll(0x01,0x0a);
+ //return Null if search starts at the beginning of the string
+ long nStart = rPaM.GetIndex() ? _xBI->beginOfSentence( sParagraph, rPaM.GetIndex(), GetLocale( rPaM ) ) : 0;
+
+ long nEnd = _xBI->endOfSentence( *pNode, rPaM.GetIndex(), GetLocale( rPaM ) );
+ EditSelection aNewSel( rCurSel );
+ DBG_ASSERT(nStart < pNode->Len() && nEnd <= pNode->Len(), "sentence indices out of range");
+ aNewSel.Min().SetIndex( (USHORT)nStart );
+ aNewSel.Max().SetIndex( (USHORT)nEnd );
+ return aNewSel;
+}
+
+sal_Bool ImpEditEngine::IsInputSequenceCheckingRequired( sal_Unicode nChar, const EditSelection& rCurSel ) const
+{
+ uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
+ if (!pCTLOptions)
+ pCTLOptions = new SvtCTLOptions;
+
+ // get the index that really is first
+ USHORT nFirstPos = rCurSel.Min().GetIndex();
+ USHORT nMaxPos = rCurSel.Max().GetIndex();
+ if (nMaxPos < nFirstPos)
+ nFirstPos = nMaxPos;
+
+ sal_Bool bIsSequenceChecking =
+ pCTLOptions->IsCTLFontEnabled() &&
+ pCTLOptions->IsCTLSequenceChecking() &&
+ nFirstPos != 0 && /* first char needs not to be checked */
+ _xBI.is() && i18n::ScriptType::COMPLEX == _xBI->getScriptType( rtl::OUString( nChar ), 0 );
+
+ return bIsSequenceChecking;
+}
+
+/*************************************************************************
+ * lcl_HasStrongLTR
+ *************************************************************************/
+ bool lcl_HasStrongLTR ( const String& rTxt, xub_StrLen nStart, xub_StrLen nEnd )
+ {
+ for ( xub_StrLen nCharIdx = nStart; nCharIdx < nEnd; ++nCharIdx )
+ {
+ const UCharDirection nCharDir = u_charDirection ( rTxt.GetChar ( nCharIdx ));
+ if ( nCharDir == U_LEFT_TO_RIGHT ||
+ nCharDir == U_LEFT_TO_RIGHT_EMBEDDING ||
+ nCharDir == U_LEFT_TO_RIGHT_OVERRIDE )
+ return true;
+ }
+ return false;
+ }
+
+
+
+void ImpEditEngine::InitScriptTypes( USHORT nPara )
+{
+ ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
+ ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
+ rTypes.Remove( 0, rTypes.Count() );
+
+// pParaPortion->aExtraCharInfos.Remove( 0, pParaPortion->aExtraCharInfos.Count() );
+
+ ContentNode* pNode = pParaPortion->GetNode();
+ if ( pNode->Len() )
+ {
+ uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
+
+ String aText( *pNode );
+
+ // To handle fields put the character from the field in the string,
+ // because endOfScript( ... ) will skip the CH_FEATURE, because this is WEAK
+ EditCharAttrib* pField = pNode->GetCharAttribs().FindNextAttrib( EE_FEATURE_FIELD, 0 );
+ while ( pField )
+ {
+ ::rtl::OUString aFldText( ((EditCharAttribField*)pField)->GetFieldValue() );
+ if ( aFldText.getLength() )
+ {
+ aText.SetChar( pField->GetStart(), aFldText.getStr()[0] );
+ short nFldScriptType = _xBI->getScriptType( aFldText, 0 );
+
+ for ( USHORT nCharInField = 1; nCharInField < aFldText.getLength(); nCharInField++ )
+ {
+ short nTmpType = _xBI->getScriptType( aFldText, nCharInField );
+
+ // First char from field wins...
+ if ( nFldScriptType == i18n::ScriptType::WEAK )
+ {
+ nFldScriptType = nTmpType;
+ aText.SetChar( pField->GetStart(), aFldText.getStr()[nCharInField] );
+ }
+
+ // ... but if the first one is LATIN, and there are CJK or CTL chars too,
+ // we prefer that ScripType because we need an other font.
+ if ( ( nTmpType == i18n::ScriptType::ASIAN ) || ( nTmpType == i18n::ScriptType::COMPLEX ) )
+ {
+ aText.SetChar( pField->GetStart(), aFldText.getStr()[nCharInField] );
+ break;
+ }
+ }
+ }
+ // #112831# Last Field might go from 0xffff to 0x0000
+ pField = pField->GetEnd() ? pNode->GetCharAttribs().FindNextAttrib( EE_FEATURE_FIELD, pField->GetEnd() ) : NULL;
+ }
+
+ ::rtl::OUString aOUText( aText );
+ USHORT nTextLen = (USHORT)aOUText.getLength();
+
+ sal_Int32 nPos = 0;
+ short nScriptType = _xBI->getScriptType( aOUText, nPos );
+ rTypes.Insert( ScriptTypePosInfo( nScriptType, (USHORT)nPos, nTextLen ), rTypes.Count() );
+ nPos = _xBI->endOfScript( aOUText, nPos, nScriptType );
+ while ( ( nPos != (-1) ) && ( nPos < nTextLen ) )
+ {
+ rTypes[rTypes.Count()-1].nEndPos = (USHORT)nPos;
+
+ nScriptType = _xBI->getScriptType( aOUText, nPos );
+ long nEndPos = _xBI->endOfScript( aOUText, nPos, nScriptType );
+
+ if ( ( nScriptType == i18n::ScriptType::WEAK ) || ( nScriptType == rTypes[rTypes.Count()-1].nScriptType ) )
+ {
+ // Expand last ScriptTypePosInfo, don't create weak or unecessary portions
+ rTypes[rTypes.Count()-1].nEndPos = (USHORT)nEndPos;
+ }
+ else
+ {
+ if ( _xBI->getScriptType( aOUText, nPos - 1 ) == i18n::ScriptType::WEAK )
+ {
+ switch ( u_charType(aOUText.iterateCodePoints(&nPos, 0) ) ) {
+ case U_NON_SPACING_MARK:
+ case U_ENCLOSING_MARK:
+ case U_COMBINING_SPACING_MARK:
+ --nPos;
+ rTypes[rTypes.Count()-1].nEndPos--;
+ break;
+ }
+ }
+ rTypes.Insert( ScriptTypePosInfo( nScriptType, (USHORT)nPos, nTextLen ), rTypes.Count() );
+ }
+
+ nPos = nEndPos;
+ }
+
+ if ( rTypes[0].nScriptType == i18n::ScriptType::WEAK )
+ rTypes[0].nScriptType = ( rTypes.Count() > 1 ) ? rTypes[1].nScriptType : GetI18NScriptTypeOfLanguage( GetDefaultLanguage() );
+
+ // create writing direction information:
+ if ( !pParaPortion->aWritingDirectionInfos.Count() )
+ InitWritingDirections( nPara );
+
+ // i89825: Use CTL font for numbers embedded into an RTL run:
+ WritingDirectionInfos& rDirInfos = pParaPortion->aWritingDirectionInfos;
+ for ( USHORT n = 0; n < rDirInfos.Count(); ++n )
+ {
+ const xub_StrLen nStart = rDirInfos[n].nStartPos;
+ const xub_StrLen nEnd = rDirInfos[n].nEndPos;
+ const BYTE nCurrDirType = rDirInfos[n].nType;
+
+ if ( nCurrDirType % 2 == UBIDI_RTL || // text in RTL run
+ ( nCurrDirType > UBIDI_LTR && !lcl_HasStrongLTR( aText, nStart, nEnd ) ) ) // non-strong text in embedded LTR run
+ {
+ USHORT nIdx = 0;
+
+ // Skip entries in ScriptArray which are not inside the RTL run:
+ while ( nIdx < rTypes.Count() && rTypes[nIdx].nStartPos < nStart )
+ ++nIdx;
+
+ // Remove any entries *inside* the current run:
+ while ( nIdx < rTypes.Count() && rTypes[nIdx].nEndPos <= nEnd )
+ rTypes.Remove( nIdx );
+
+ // special case:
+ if(nIdx < rTypes.Count() && rTypes[nIdx].nStartPos < nStart && rTypes[nIdx].nEndPos > nEnd)
+ {
+ rTypes.Insert( ScriptTypePosInfo( rTypes[nIdx].nScriptType, (USHORT)nEnd, rTypes[nIdx].nEndPos ), nIdx );
+ rTypes[nIdx].nEndPos = nStart;
+ }
+
+ if( nIdx )
+ rTypes[nIdx - 1].nEndPos = nStart;
+
+ rTypes.Insert( ScriptTypePosInfo( i18n::ScriptType::COMPLEX, (USHORT)nStart, (USHORT)nEnd), nIdx );
+ ++nIdx;
+
+ if( nIdx < rTypes.Count() )
+ rTypes[nIdx].nStartPos = nEnd;
+ }
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ USHORT nDebugStt = 0;
+ USHORT nDebugEnd = 0;
+ short nDebugType = 0;
+ for ( USHORT n = 0; n < rTypes.Count(); ++n )
+ {
+ nDebugStt = rTypes[n].nStartPos;
+ nDebugEnd = rTypes[n].nEndPos;
+ nDebugType = rTypes[n].nScriptType;
+ }
+#endif
+ }
+}
+
+USHORT ImpEditEngine::GetScriptType( const EditPaM& rPaM, USHORT* pEndPos ) const
+{
+ USHORT nScriptType = 0;
+
+ if ( pEndPos )
+ *pEndPos = rPaM.GetNode()->Len();
+
+ if ( rPaM.GetNode()->Len() )
+ {
+ USHORT nPara = GetEditDoc().GetPos( rPaM.GetNode() );
+ ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
+ if ( !pParaPortion->aScriptInfos.Count() )
+ ((ImpEditEngine*)this)->InitScriptTypes( nPara );
+
+ ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
+ USHORT nPos = rPaM.GetIndex();
+ for ( USHORT n = 0; n < rTypes.Count(); n++ )
+ {
+ if ( ( rTypes[n].nStartPos <= nPos ) && ( rTypes[n].nEndPos >= nPos ) )
+ {
+ nScriptType = rTypes[n].nScriptType;
+ if( pEndPos )
+ *pEndPos = rTypes[n].nEndPos;
+ break;
+ }
+ }
+ }
+ return nScriptType ? nScriptType : GetI18NScriptTypeOfLanguage( GetDefaultLanguage() );
+}
+
+USHORT ImpEditEngine::GetScriptType( const EditSelection& rSel ) const
+{
+ EditSelection aSel( rSel );
+ aSel.Adjust( aEditDoc );
+
+ short nScriptType = 0;
+
+ USHORT nStartPara = GetEditDoc().GetPos( aSel.Min().GetNode() );
+ USHORT nEndPara = GetEditDoc().GetPos( aSel.Max().GetNode() );
+
+ for ( USHORT nPara = nStartPara; nPara <= nEndPara; nPara++ )
+ {
+ ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
+ if ( !pParaPortion->aScriptInfos.Count() )
+ ((ImpEditEngine*)this)->InitScriptTypes( nPara );
+
+ ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
+
+ // find the first(!) script type position that holds the
+ // complete selection. Thus it will work for selections as
+ // well as with just moving the cursor from char to char.
+ USHORT nS = ( nPara == nStartPara ) ? aSel.Min().GetIndex() : 0;
+ USHORT nE = ( nPara == nEndPara ) ? aSel.Max().GetIndex() : pParaPortion->GetNode()->Len();
+ for ( USHORT n = 0; n < rTypes.Count(); n++ )
+ {
+ if (rTypes[n].nStartPos <= nS && nE <= rTypes[n].nEndPos)
+ {
+ if ( rTypes[n].nScriptType != i18n::ScriptType::WEAK )
+ {
+ nScriptType |= GetItemScriptType ( rTypes[n].nScriptType );
+ }
+ else
+ {
+ if ( !nScriptType && n )
+ {
+ // #93548# When starting with WEAK, use prev ScriptType...
+ nScriptType = rTypes[n-1].nScriptType;
+ }
+ }
+ break;
+ }
+ }
+ }
+ return nScriptType ? nScriptType : GetI18NScriptTypeOfLanguage( GetDefaultLanguage() );
+}
+
+BOOL ImpEditEngine::IsScriptChange( const EditPaM& rPaM ) const
+{
+ BOOL bScriptChange = FALSE;
+
+ if ( rPaM.GetNode()->Len() )
+ {
+ USHORT nPara = GetEditDoc().GetPos( rPaM.GetNode() );
+ ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
+ if ( !pParaPortion->aScriptInfos.Count() )
+ ((ImpEditEngine*)this)->InitScriptTypes( nPara );
+
+ ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
+ USHORT nPos = rPaM.GetIndex();
+ for ( USHORT n = 0; n < rTypes.Count(); n++ )
+ {
+ if ( rTypes[n].nStartPos == nPos )
+ {
+ bScriptChange = TRUE;
+ break;
+ }
+ }
+ }
+ return bScriptChange;
+}
+
+BOOL ImpEditEngine::HasScriptType( USHORT nPara, USHORT nType ) const
+{
+ BOOL bTypeFound = FALSE;
+
+ ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
+ if ( !pParaPortion->aScriptInfos.Count() )
+ ((ImpEditEngine*)this)->InitScriptTypes( nPara );
+
+ ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
+ for ( USHORT n = rTypes.Count(); n && !bTypeFound; )
+ {
+ if ( rTypes[--n].nScriptType == nType )
+ bTypeFound = TRUE;
+ }
+ return bTypeFound;
+}
+
+void ImpEditEngine::InitWritingDirections( USHORT nPara )
+{
+ ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
+ WritingDirectionInfos& rInfos = pParaPortion->aWritingDirectionInfos;
+ rInfos.Remove( 0, rInfos.Count() );
+
+ BOOL bCTL = FALSE;
+ ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
+ for ( USHORT n = 0; n < rTypes.Count(); n++ )
+ {
+ if ( rTypes[n].nScriptType == i18n::ScriptType::COMPLEX )
+ {
+ bCTL = TRUE;
+ break;
+ }
+ }
+
+ const UBiDiLevel nBidiLevel = IsRightToLeft( nPara ) ? 1 /*RTL*/ : 0 /*LTR*/;
+ if ( ( bCTL || ( nBidiLevel == 1 /*RTL*/ ) ) && pParaPortion->GetNode()->Len() )
+ {
+
+ String aText( *pParaPortion->GetNode() );
+
+ //
+ // Bidi functions from icu 2.0
+ //
+ UErrorCode nError = U_ZERO_ERROR;
+ UBiDi* pBidi = ubidi_openSized( aText.Len(), 0, &nError );
+ nError = U_ZERO_ERROR;
+
+ ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(aText.GetBuffer()), aText.Len(), nBidiLevel, NULL, &nError ); // UChar != sal_Unicode in MinGW
+ nError = U_ZERO_ERROR;
+
+ long nCount = ubidi_countRuns( pBidi, &nError );
+
+ int32_t nStart = 0;
+ int32_t nEnd;
+ UBiDiLevel nCurrDir;
+
+ for ( USHORT nIdx = 0; nIdx < nCount; ++nIdx )
+ {
+ ubidi_getLogicalRun( pBidi, nStart, &nEnd, &nCurrDir );
+ rInfos.Insert( WritingDirectionInfo( nCurrDir, (USHORT)nStart, (USHORT)nEnd ), rInfos.Count() );
+ nStart = nEnd;
+ }
+
+ ubidi_close( pBidi );
+ }
+
+ // No infos mean no CTL and default dir is L2R...
+ if ( !rInfos.Count() )
+ rInfos.Insert( WritingDirectionInfo( 0, 0, (USHORT)pParaPortion->GetNode()->Len() ), rInfos.Count() );
+
+}
+
+BOOL ImpEditEngine::IsRightToLeft( USHORT nPara ) const
+{
+ BOOL bR2L = FALSE;
+ const SvxFrameDirectionItem* pFrameDirItem = NULL;
+
+ if ( !IsVertical() )
+ {
+ bR2L = GetDefaultHorizontalTextDirection() == EE_HTEXTDIR_R2L;
+ pFrameDirItem = &(const SvxFrameDirectionItem&)GetParaAttrib( nPara, EE_PARA_WRITINGDIR );
+ if ( pFrameDirItem->GetValue() == FRMDIR_ENVIRONMENT )
+ {
+ // #103045# if DefaultHorizontalTextDirection is set, use that value, otherwise pool default.
+ if ( GetDefaultHorizontalTextDirection() != EE_HTEXTDIR_DEFAULT )
+ {
+ pFrameDirItem = NULL; // bR2L allready set to default horizontal text direction
+ }
+ else
+ {
+ // Use pool default
+ pFrameDirItem = &(const SvxFrameDirectionItem&)((ImpEditEngine*)this)->GetEmptyItemSet().Get( EE_PARA_WRITINGDIR );
+ }
+ }
+ }
+
+ if ( pFrameDirItem )
+ bR2L = pFrameDirItem->GetValue() == FRMDIR_HORI_RIGHT_TOP;
+
+ return bR2L;
+}
+
+BOOL ImpEditEngine::HasDifferentRTLLevels( const ContentNode* pNode )
+{
+ USHORT nPara = GetEditDoc().GetPos( (ContentNode*)pNode );
+ ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
+
+ BOOL bHasDifferentRTLLevels = FALSE;
+
+ USHORT nRTLLevel = IsRightToLeft( nPara ) ? 1 : 0;
+ for ( USHORT n = 0; n < pParaPortion->GetTextPortions().Count(); n++ )
+ {
+ TextPortion* pTextPortion = pParaPortion->GetTextPortions().GetObject( n );
+ if ( pTextPortion->GetRightToLeft() != nRTLLevel )
+ {
+ bHasDifferentRTLLevels = TRUE;
+ break;
+ }
+ }
+ return bHasDifferentRTLLevels;
+}
+
+
+BYTE ImpEditEngine::GetRightToLeft( USHORT nPara, USHORT nPos, USHORT* pStart, USHORT* pEnd )
+{
+// BYTE nRightToLeft = IsRightToLeft( nPara ) ? 1 : 0;
+ BYTE nRightToLeft = 0;
+
+ ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
+ if ( pNode && pNode->Len() )
+ {
+ ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
+ if ( !pParaPortion->aWritingDirectionInfos.Count() )
+ InitWritingDirections( nPara );
+
+// BYTE nType = 0;
+ WritingDirectionInfos& rDirInfos = pParaPortion->aWritingDirectionInfos;
+ for ( USHORT n = 0; n < rDirInfos.Count(); n++ )
+ {
+ if ( ( rDirInfos[n].nStartPos <= nPos ) && ( rDirInfos[n].nEndPos >= nPos ) )
+ {
+ nRightToLeft = rDirInfos[n].nType;
+ if ( pStart )
+ *pStart = rDirInfos[n].nStartPos;
+ if ( pEnd )
+ *pEnd = rDirInfos[n].nEndPos;
+ break;
+ }
+ }
+ }
+ return nRightToLeft;
+}
+
+SvxAdjust ImpEditEngine::GetJustification( USHORT nPara ) const
+{
+ SvxAdjust eJustification = SVX_ADJUST_LEFT;
+
+ if ( !aStatus.IsOutliner() )
+ {
+ eJustification = ((const SvxAdjustItem&) GetParaAttrib( nPara, EE_PARA_JUST )).GetAdjust();
+
+ if ( IsRightToLeft( nPara ) )
+ {
+ if ( eJustification == SVX_ADJUST_LEFT )
+ eJustification = SVX_ADJUST_RIGHT;
+ else if ( eJustification == SVX_ADJUST_RIGHT )
+ eJustification = SVX_ADJUST_LEFT;
+ }
+ }
+ return eJustification;
+}
+
+
+// ----------------------------------------------------------------------
+// Textaenderung
+// ----------------------------------------------------------------------
+
+void ImpEditEngine::ImpRemoveChars( const EditPaM& rPaM, USHORT nChars, EditUndoRemoveChars* pCurUndo )
+{
+ if ( IsUndoEnabled() && !IsInUndo() )
+ {
+ XubString aStr( rPaM.GetNode()->Copy( rPaM.GetIndex(), nChars ) );
+
+ // Pruefen, ob Attribute geloescht oder geaendert werden:
+ USHORT nStart = rPaM.GetIndex();
+ USHORT nEnd = nStart + nChars;
+ CharAttribArray& rAttribs = rPaM.GetNode()->GetCharAttribs().GetAttribs();
+// USHORT nAttrs = rAttribs.Count();
+ for ( USHORT nAttr = 0; nAttr < rAttribs.Count(); nAttr++ )
+ {
+ EditCharAttrib* pAttr = rAttribs[nAttr];
+ if ( ( pAttr->GetEnd() >= nStart ) && ( pAttr->GetStart() < nEnd ) )
+ {
+#ifndef SVX_LIGHT
+ EditSelection aSel( rPaM );
+ aSel.Max().GetIndex() = aSel.Max().GetIndex() + nChars;
+ EditUndoSetAttribs* pAttrUndo = CreateAttribUndo( aSel, GetEmptyItemSet() );
+ InsertUndo( pAttrUndo );
+#endif
+ break; // for
+ }
+ }
+ if ( pCurUndo && ( CreateEditPaM( pCurUndo->GetEPaM() ) == rPaM ) )
+ pCurUndo->GetStr() += aStr;
+#ifndef SVX_LIGHT
+ else
+ InsertUndo( new EditUndoRemoveChars( this, CreateEPaM( rPaM ), aStr ) );
+#endif
+ }
+
+ aEditDoc.RemoveChars( rPaM, nChars );
+ TextModified();
+}
+
+EditSelection ImpEditEngine::ImpMoveParagraphs( Range aOldPositions, USHORT nNewPos )
+{
+ aOldPositions.Justify();
+ BOOL bValidAction = ( (long)nNewPos < aOldPositions.Min() ) || ( (long)nNewPos > aOldPositions.Max() );
+ DBG_ASSERT( bValidAction, "Move in sich selbst ?" );
+ DBG_ASSERT( aOldPositions.Max() <= (long)GetParaPortions().Count(), "Voll drueber weg: MoveParagraphs" );
+
+ EditSelection aSelection;
+
+ if ( !bValidAction )
+ {
+ aSelection = aEditDoc.GetStartPaM();
+ return aSelection;
+ }
+
+ ULONG nParaCount = GetParaPortions().Count();
+
+ if ( nNewPos >= nParaCount )
+ nNewPos = GetParaPortions().Count();
+
+ // Height may change when moving first or last Paragraph
+ ParaPortion* pRecalc1 = NULL;
+ ParaPortion* pRecalc2 = NULL;
+ ParaPortion* pRecalc3 = NULL;
+ ParaPortion* pRecalc4 = NULL;
+
+ if ( nNewPos == 0 ) // Move to Start
+ {
+ pRecalc1 = GetParaPortions().GetObject( 0 );
+ pRecalc2 = GetParaPortions().GetObject( (USHORT)aOldPositions.Min() );
+
+ }
+ else if ( nNewPos == nParaCount )
+ {
+ pRecalc1 = GetParaPortions().GetObject( (USHORT)(nParaCount-1) );
+ pRecalc2 = GetParaPortions().GetObject( (USHORT)aOldPositions.Max() );
+ }
+
+ if ( aOldPositions.Min() == 0 ) // Move from Start
+ {
+ pRecalc3 = GetParaPortions().GetObject( 0 );
+ pRecalc4 = GetParaPortions().GetObject(
+ sal::static_int_cast< USHORT >( aOldPositions.Max()+1 ) );
+ }
+ else if ( (USHORT)aOldPositions.Max() == (nParaCount-1) )
+ {
+ pRecalc3 = GetParaPortions().GetObject( (USHORT)aOldPositions.Max() );
+ pRecalc4 = GetParaPortions().GetObject( (USHORT)(aOldPositions.Min()-1) );
+ }
+
+ MoveParagraphsInfo aMoveParagraphsInfo( sal::static_int_cast< USHORT >(aOldPositions.Min()), sal::static_int_cast< USHORT >(aOldPositions.Max()), nNewPos );
+ aBeginMovingParagraphsHdl.Call( &aMoveParagraphsInfo );
+
+ if ( IsUndoEnabled() && !IsInUndo())
+ InsertUndo( new EditUndoMoveParagraphs( this, aOldPositions, nNewPos ) );
+
+ // Position nicht aus dem Auge verlieren!
+ ParaPortion* pDestPortion = GetParaPortions().SaveGetObject( nNewPos );
+
+ ParaPortionList aTmpPortionList;
+ USHORT i;
+ for ( i = (USHORT)aOldPositions.Min(); i <= (USHORT)aOldPositions.Max(); i++ )
+ {
+ // Immer aOldPositions.Min(), da Remove().
+ ParaPortion* pTmpPortion = GetParaPortions().GetObject( (USHORT)aOldPositions.Min() );
+ GetParaPortions().Remove( (USHORT)aOldPositions.Min() );
+ aEditDoc.Remove( (USHORT)aOldPositions.Min() );
+ aTmpPortionList.Insert( pTmpPortion, aTmpPortionList.Count() );
+ }
+
+ USHORT nRealNewPos = pDestPortion ? GetParaPortions().GetPos( pDestPortion ) : GetParaPortions().Count();
+ DBG_ASSERT( nRealNewPos != USHRT_MAX, "ImpMoveParagraphs: Ungueltige Position!" );
+
+ for ( i = 0; i < (USHORT)aTmpPortionList.Count(); i++ )
+ {
+ ParaPortion* pTmpPortion = aTmpPortionList.GetObject( i );
+ if ( i == 0 )
+ aSelection.Min().SetNode( pTmpPortion->GetNode() );
+
+ aSelection.Max().SetNode( pTmpPortion->GetNode() );
+ aSelection.Max().SetIndex( pTmpPortion->GetNode()->Len() );
+
+ ContentNode* pN = pTmpPortion->GetNode();
+ aEditDoc.Insert( pN, nRealNewPos+i );
+
+ GetParaPortions().Insert( pTmpPortion, nRealNewPos+i );
+ }
+
+ aEndMovingParagraphsHdl.Call( &aMoveParagraphsInfo );
+
+ if ( GetNotifyHdl().IsSet() )
+ {
+ EENotify aNotify( EE_NOTIFY_PARAGRAPHSMOVED );
+ aNotify.pEditEngine = GetEditEnginePtr();
+ aNotify.nParagraph = nNewPos;
+ aNotify.nParam1 = sal::static_int_cast< USHORT >(aOldPositions.Min());
+ aNotify.nParam2 = sal::static_int_cast< USHORT >(aOldPositions.Max());
+ CallNotify( aNotify );
+ }
+
+ aEditDoc.SetModified( TRUE );
+
+ if ( pRecalc1 )
+ CalcHeight( pRecalc1 );
+ if ( pRecalc2 )
+ CalcHeight( pRecalc2 );
+ if ( pRecalc3 )
+ CalcHeight( pRecalc3 );
+ if ( pRecalc4 )
+ CalcHeight( pRecalc4 );
+
+ aTmpPortionList.Remove( 0, aTmpPortionList.Count() ); // wichtig !
+
+#ifdef EDITDEBUG
+ GetParaPortions().DbgCheck(aEditDoc);
+#endif
+ return aSelection;
+}
+
+
+EditPaM ImpEditEngine::ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pRight, BOOL bBackward )
+{
+ DBG_ASSERT( pLeft != pRight, "Den gleichen Absatz zusammenfuegen ?" );
+ DBG_ASSERT( aEditDoc.GetPos( pLeft ) != USHRT_MAX, "Einzufuegenden Node nicht gefunden(1)" );
+ DBG_ASSERT( aEditDoc.GetPos( pRight ) != USHRT_MAX, "Einzufuegenden Node nicht gefunden(2)" );
+
+ USHORT nParagraphTobeDeleted = aEditDoc.GetPos( pRight );
+ DeletedNodeInfo* pInf = new DeletedNodeInfo( (ULONG)pRight, nParagraphTobeDeleted );
+ aDeletedNodes.Insert( pInf, aDeletedNodes.Count() );
+
+ GetEditEnginePtr()->ParagraphConnected( aEditDoc.GetPos( pLeft ), aEditDoc.GetPos( pRight ) );
+
+#ifndef SVX_LIGHT
+ if ( IsUndoEnabled() && !IsInUndo() )
+ {
+ InsertUndo( new EditUndoConnectParas( this,
+ aEditDoc.GetPos( pLeft ), pLeft->Len(),
+ pLeft->GetContentAttribs().GetItems(), pRight->GetContentAttribs().GetItems(),
+ pLeft->GetStyleSheet(), pRight->GetStyleSheet(), bBackward ) );
+ }
+#endif
+
+ if ( bBackward )
+ {
+ pLeft->SetStyleSheet( pRight->GetStyleSheet(), TRUE );
+ pLeft->GetContentAttribs().GetItems().Set( pRight->GetContentAttribs().GetItems() );
+ pLeft->GetCharAttribs().GetDefFont() = pRight->GetCharAttribs().GetDefFont();
+ }
+
+ ParaAttribsChanged( pLeft );
+
+ // Erstmal Portions suchen, da pRight nach ConnectParagraphs weg.
+ ParaPortion* pLeftPortion = FindParaPortion( pLeft );
+ ParaPortion* pRightPortion = FindParaPortion( pRight );
+ DBG_ASSERT( pLeftPortion, "Blinde Portion in ImpConnectParagraphs(1)" );
+ DBG_ASSERT( pRightPortion, "Blinde Portion in ImpConnectParagraphs(2)" );
+ DBG_ASSERT( nParagraphTobeDeleted == GetParaPortions().GetPos( pRightPortion ), "NodePos != PortionPos?" );
+
+#ifndef SVX_LIGHT
+ if ( GetStatus().DoOnlineSpelling() )
+ {
+ xub_StrLen nEnd = pLeft->Len();
+ xub_StrLen nInv = nEnd ? nEnd-1 : nEnd;
+ pLeft->GetWrongList()->ClearWrongs( nInv, 0xFFFF, pLeft ); // Evtl. einen wegnehmen
+ pLeft->GetWrongList()->MarkInvalid( nInv, nEnd+1 );
+ // Falschgeschriebene Woerter ruebernehmen:
+ USHORT nRWrongs = pRight->GetWrongList()->Count();
+ for ( USHORT nW = 0; nW < nRWrongs; nW++ )
+ {
+ WrongRange aWrong = pRight->GetWrongList()->GetObject( nW );
+ if ( aWrong.nStart != 0 ) // Nicht ein anschliessender
+ {
+ aWrong.nStart = aWrong.nStart + nEnd;
+ aWrong.nEnd = aWrong.nEnd + nEnd;
+ pLeft->GetWrongList()->InsertWrong( aWrong, pLeft->GetWrongList()->Count() );
+ }
+ }
+ }
+#endif
+
+ if ( IsCallParaInsertedOrDeleted() )
+ GetEditEnginePtr()->ParagraphDeleted( nParagraphTobeDeleted );
+
+ EditPaM aPaM = aEditDoc.ConnectParagraphs( pLeft, pRight );
+ GetParaPortions().Remove( nParagraphTobeDeleted );
+ delete pRightPortion;
+
+ pLeftPortion->MarkSelectionInvalid( aPaM.GetIndex(), pLeft->Len() );
+
+ // der rechte Node wird von EditDoc::ConnectParagraphs() geloescht.
+
+ if ( GetTextRanger() )
+ {
+ // Durch das zusammenfuegen wird der linke zwar neu formatiert, aber
+ // wenn sich dessen Hoehe nicht aendert bekommt die Formatierung die
+ // Aenderung der Gesaamthoehe des Textes zu spaet mit...
+ for ( USHORT n = nParagraphTobeDeleted; n < GetParaPortions().Count(); n++ )
+ {
+ ParaPortion* pPP = GetParaPortions().GetObject( n );
+ pPP->MarkSelectionInvalid( 0, pPP->GetNode()->Len() );
+ pPP->GetLines().Reset();
+ }
+ }
+
+ TextModified();
+
+ return aPaM;
+}
+
+EditPaM ImpEditEngine::DeleteLeftOrRight( const EditSelection& rSel, BYTE nMode, BYTE nDelMode )
+{
+ DBG_ASSERT( !EditSelection( rSel ).DbgIsBuggy( aEditDoc ), "Index im Wald in DeleteLeftOrRight" );
+
+ if ( rSel.HasRange() ) // dann nur Sel. loeschen
+ return ImpDeleteSelection( rSel );
+
+ const EditPaM aCurPos( rSel.Max() );
+ EditPaM aDelStart( aCurPos );
+ EditPaM aDelEnd( aCurPos );
+ if ( nMode == DEL_LEFT )
+ {
+ if ( nDelMode == DELMODE_SIMPLE )
+ {
+ aDelStart = CursorLeft( aCurPos, i18n::CharacterIteratorMode::SKIPCHARACTER );
+ }
+ else if ( nDelMode == DELMODE_RESTOFWORD )
+ {
+ aDelStart = StartOfWord( aCurPos );
+ if ( aDelStart.GetIndex() == aCurPos.GetIndex() )
+ aDelStart = WordLeft( aCurPos );
+ }
+ else // DELMODE_RESTOFCONTENT
+ {
+ aDelStart.SetIndex( 0 );
+ if ( aDelStart == aCurPos )
+ {
+ // kompletter Absatz davor
+ ContentNode* pPrev = GetPrevVisNode( aCurPos.GetNode() );
+ if ( pPrev )
+ aDelStart = EditPaM( pPrev, 0 );
+ }
+ }
+ }
+ else
+ {
+ if ( nDelMode == DELMODE_SIMPLE )
+ {
+ aDelEnd = CursorRight( aCurPos );
+ }
+ else if ( nDelMode == DELMODE_RESTOFWORD )
+ {
+ aDelEnd = EndOfWord( aCurPos );
+ if (aDelEnd.GetIndex() == aCurPos.GetIndex())
+ {
+ xub_StrLen nLen = aCurPos.GetNode()->Len();
+ // end of para?
+ if (aDelEnd.GetIndex() == nLen)
+ aDelEnd = WordLeft( aCurPos );
+ else // there's still sth to delete on the right
+ {
+ aDelEnd = EndOfWord( WordRight( aCurPos ) );
+ // if there'n no next word...
+ if (aDelEnd.GetIndex() == nLen )
+ aDelEnd.SetIndex( nLen );
+ }
+ }
+ }
+ else // DELMODE_RESTOFCONTENT
+ {
+ aDelEnd.SetIndex( aCurPos.GetNode()->Len() );
+ if ( aDelEnd == aCurPos )
+ {
+ // kompletter Absatz dahinter
+ ContentNode* pNext = GetNextVisNode( aCurPos.GetNode() );
+ if ( pNext )
+ aDelEnd = EditPaM( pNext, pNext->Len() );
+ }
+ }
+ }
+
+ // Bei DELMODE_RESTOFCONTENT reicht bei verschiedenen Nodes
+ // kein ConnectParagraphs.
+ if ( ( nDelMode == DELMODE_RESTOFCONTENT ) || ( aDelStart.GetNode() == aDelEnd.GetNode() ) )
+ return ImpDeleteSelection( EditSelection( aDelStart, aDelEnd ) );
+
+ // Jetzt entscheiden, ob noch Selektion loeschen (RESTOFCONTENTS)
+ BOOL bSpecialBackward = ( ( nMode == DEL_LEFT ) && ( nDelMode == DELMODE_SIMPLE ) )
+ ? TRUE : FALSE;
+ if ( aStatus.IsAnyOutliner() )
+ bSpecialBackward = FALSE;
+
+ return ImpConnectParagraphs( aDelStart.GetNode(), aDelEnd.GetNode(), bSpecialBackward );
+}
+
+EditPaM ImpEditEngine::ImpDeleteSelection( EditSelection aSel )
+{
+ if ( !aSel.HasRange() )
+ return aSel.Min();
+
+ aSel.Adjust( aEditDoc );
+ EditPaM aStartPaM( aSel.Min() );
+ EditPaM aEndPaM( aSel.Max() );
+
+ CursorMoved( aStartPaM.GetNode() ); // nur damit neu eingestellte Attribute verschwinden...
+ CursorMoved( aEndPaM.GetNode() ); // nur damit neu eingestellte Attribute verschwinden...
+
+ DBG_ASSERT( aStartPaM.GetIndex() <= aStartPaM.GetNode()->Len(), "Index im Wald in ImpDeleteSelection" );
+ DBG_ASSERT( aEndPaM.GetIndex() <= aEndPaM.GetNode()->Len(), "Index im Wald in ImpDeleteSelection" );
+
+ USHORT nStartNode = aEditDoc.GetPos( aStartPaM.GetNode() );
+ USHORT nEndNode = aEditDoc.GetPos( aEndPaM.GetNode() );
+
+ DBG_ASSERT( nEndNode != USHRT_MAX, "Start > End ?!" );
+ DBG_ASSERT( nStartNode <= nEndNode, "Start > End ?!" );
+
+ // Alle Nodes dazwischen entfernen....
+ for ( ULONG z = nStartNode+1; z < nEndNode; z++ )
+ {
+ // Immer nStartNode+1, wegen Remove()!
+ ImpRemoveParagraph( nStartNode+1 );
+ }
+
+ if ( aStartPaM.GetNode() != aEndPaM.GetNode() )
+ {
+ // Den Rest des StartNodes...
+ USHORT nChars;
+ nChars = aStartPaM.GetNode()->Len() - aStartPaM.GetIndex();
+ ImpRemoveChars( aStartPaM, nChars );
+ ParaPortion* pPortion = FindParaPortion( aStartPaM.GetNode() );
+ DBG_ASSERT( pPortion, "Blinde Portion in ImpDeleteSelection(3)" );
+ pPortion->MarkSelectionInvalid( aStartPaM.GetIndex(), aStartPaM.GetNode()->Len() );
+
+ // Den Anfang des EndNodes....
+ nChars = aEndPaM.GetIndex();
+ aEndPaM.SetIndex( 0 );
+ ImpRemoveChars( aEndPaM, nChars );
+ pPortion = FindParaPortion( aEndPaM.GetNode() );
+ DBG_ASSERT( pPortion, "Blinde Portion in ImpDeleteSelection(4)" );
+ pPortion->MarkSelectionInvalid( 0, aEndPaM.GetNode()->Len() );
+ // Zusammenfuegen....
+ aStartPaM = ImpConnectParagraphs( aStartPaM.GetNode(), aEndPaM.GetNode() );
+ }
+ else
+ {
+ USHORT nChars;
+ nChars = aEndPaM.GetIndex() - aStartPaM.GetIndex();
+ ImpRemoveChars( aStartPaM, nChars );
+ ParaPortion* pPortion = FindParaPortion( aStartPaM.GetNode() );
+ DBG_ASSERT( pPortion, "Blinde Portion in ImpDeleteSelection(5)" );
+ pPortion->MarkInvalid( aEndPaM.GetIndex(), aStartPaM.GetIndex() - aEndPaM.GetIndex() );
+ }
+
+ UpdateSelections();
+ TextModified();
+ return aStartPaM;
+}
+
+void ImpEditEngine::ImpRemoveParagraph( USHORT nPara )
+{
+ ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
+ ContentNode* pNextNode = aEditDoc.SaveGetObject( nPara+1 );
+ ParaPortion* pPortion = GetParaPortions().SaveGetObject( nPara );
+
+ DBG_ASSERT( pNode, "Blinder Node in ImpRemoveParagraph" );
+ DBG_ASSERT( pPortion, "Blinde Portion in ImpRemoveParagraph(2)" );
+
+ DeletedNodeInfo* pInf = new DeletedNodeInfo( (ULONG)pNode, nPara );
+ aDeletedNodes.Insert( pInf, aDeletedNodes.Count() );
+
+ // Der Node wird vom Undo verwaltet und ggf. zerstoert!
+ /* delete */ aEditDoc.Remove( nPara );
+ GetParaPortions().Remove( nPara );
+ delete pPortion;
+
+ if ( IsCallParaInsertedOrDeleted() )
+ {
+ GetEditEnginePtr()->ParagraphDeleted( nPara );
+ }
+
+ // Im folgenden muss ggf. Extra-Space neu ermittelt werden.
+ // Bei ParaAttribsChanged wird leider der Absatz neu formatiert,
+ // aber diese Methode sollte nicht Zeitkritsch sein!
+ if ( pNextNode )
+ ParaAttribsChanged( pNextNode );
+
+#ifndef SVX_LIGHT
+ if ( IsUndoEnabled() && !IsInUndo() )
+ InsertUndo( new EditUndoDelContent( this, pNode, nPara ) );
+ else
+#endif
+ {
+ aEditDoc.RemoveItemsFromPool( pNode );
+ if ( pNode->GetStyleSheet() )
+ EndListening( *pNode->GetStyleSheet(), FALSE );
+ delete pNode;
+ }
+}
+
+EditPaM ImpEditEngine::AutoCorrect( const EditSelection& rCurSel, xub_Unicode c, BOOL bOverwrite )
+{
+ EditSelection aSel( rCurSel );
+#ifndef SVX_LIGHT
+ SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get()->GetAutoCorrect();
+ if ( pAutoCorrect )
+ {
+ if ( aSel.HasRange() )
+ aSel = ImpDeleteSelection( rCurSel );
+
+ // #i78661 allow application to turn off capitalization of
+ // start sentence explicitly.
+ // (This is done by setting IsFirstWordCapitalization to FALSE.)
+ BOOL bOldCptlSttSntnc = pAutoCorrect->IsAutoCorrFlag( CptlSttSntnc );
+ if (!IsFirstWordCapitalization())
+ {
+ ESelection aESel( CreateESel(aSel) );
+ EditSelection aFirstWordSel;
+ EditSelection aSecondWordSel;
+ if (aESel.nEndPara == 0) // is this the first para?
+ {
+ // select first word...
+ // start by checking if para starts with word.
+ aFirstWordSel = SelectWord( CreateSel(ESelection()) );
+ if (aFirstWordSel.Min().GetIndex() == 0 && aFirstWordSel.Max().GetIndex() == 0)
+ {
+ // para does not start with word -> select next/first word
+ EditPaM aRightWord( WordRight( aFirstWordSel.Max(), 1 ) );
+ aFirstWordSel = SelectWord( EditSelection( aRightWord ) );
+ }
+
+ // select second word
+ // (sometimes aSel mightnot point to the end of the first word
+ // but to some following char like '.'. ':', ...
+ // In those cases we need aSecondWordSel to see if aSel
+ // will actually effect the first word.)
+ EditPaM aRight2Word( WordRight( aFirstWordSel.Max(), 1 ) );
+ aSecondWordSel = SelectWord( EditSelection( aRight2Word ) );
+ }
+ BOOL bIsFirstWordInFirstPara = aESel.nEndPara == 0 &&
+ aFirstWordSel.Max().GetIndex() <= aSel.Max().GetIndex() &&
+ aSel.Max().GetIndex() <= aSecondWordSel.Min().GetIndex();
+
+ if (bIsFirstWordInFirstPara)
+ pAutoCorrect->SetAutoCorrFlag( CptlSttSntnc, IsFirstWordCapitalization() );
+ }
+
+ ContentNode* pNode = aSel.Max().GetNode();
+ USHORT nIndex = aSel.Max().GetIndex();
+ EdtAutoCorrDoc aAuto( this, pNode, nIndex, c );
+ pAutoCorrect->AutoCorrect( aAuto, *pNode, nIndex, c, !bOverwrite );
+ aSel.Max().SetIndex( aAuto.GetCursor() );
+
+ // #i78661 since the SvxAutoCorrect object used here is
+ // shared we need to reset the value to it's original state.
+ pAutoCorrect->SetAutoCorrFlag( CptlSttSntnc, bOldCptlSttSntnc );
+ }
+#endif // !SVX_LIGHT
+ return aSel.Max();
+}
+
+
+EditPaM ImpEditEngine::InsertText( const EditSelection& rCurSel,
+ xub_Unicode c, BOOL bOverwrite, sal_Bool bIsUserInput )
+{
+ DBG_ASSERT( c != '\t', "Tab bei InsertText ?" );
+ DBG_ASSERT( c != '\n', "Zeilenumbruch bei InsertText ?" );
+
+ EditPaM aPaM( rCurSel.Min() );
+
+ BOOL bDoOverwrite = ( bOverwrite &&
+ ( aPaM.GetIndex() < aPaM.GetNode()->Len() ) ) ? TRUE : FALSE;
+
+ BOOL bUndoAction = ( rCurSel.HasRange() || bDoOverwrite );
+
+ if ( bUndoAction )
+ UndoActionStart( EDITUNDO_INSERT );
+
+ if ( rCurSel.HasRange() )
+ {
+ aPaM = ImpDeleteSelection( rCurSel );
+ }
+ else if ( bDoOverwrite )
+ {
+ // Wenn Selektion, dann nicht auch noch ein Zeichen ueberschreiben!
+ EditSelection aTmpSel( aPaM );
+ aTmpSel.Max().GetIndex()++;
+ DBG_ASSERT( !aTmpSel.DbgIsBuggy( aEditDoc ), "Overwrite: Fehlerhafte Selektion!" );
+ ImpDeleteSelection( aTmpSel );
+ }
+
+ if ( aPaM.GetNode()->Len() < MAXCHARSINPARA )
+ {
+ if (bIsUserInput && IsInputSequenceCheckingRequired( c, rCurSel ))
+ {
+ uno::Reference < i18n::XExtendedInputSequenceChecker > _xISC( ImplGetInputSequenceChecker() );
+ if (!pCTLOptions)
+ pCTLOptions = new SvtCTLOptions;
+
+ if (_xISC.is() || pCTLOptions)
+ {
+ xub_StrLen nTmpPos = aPaM.GetIndex();
+ sal_Int16 nCheckMode = pCTLOptions->IsCTLSequenceCheckingRestricted() ?
+ i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC;
+
+ // the text that needs to be checked is only the one
+ // before the current cursor position
+ rtl::OUString aOldText( aPaM.GetNode()->Copy(0, nTmpPos) );
+ rtl::OUString aNewText( aOldText );
+ if (pCTLOptions->IsCTLSequenceCheckingTypeAndReplace())
+ {
+ /*const xub_StrLen nPrevPos = static_cast< xub_StrLen >*/( _xISC->correctInputSequence( aNewText, nTmpPos - 1, c, nCheckMode ) );
+
+ // find position of first character that has changed
+ sal_Int32 nOldLen = aOldText.getLength();
+ sal_Int32 nNewLen = aNewText.getLength();
+ const sal_Unicode *pOldTxt = aOldText.getStr();
+ const sal_Unicode *pNewTxt = aNewText.getStr();
+ sal_Int32 nChgPos = 0;
+ while ( nChgPos < nOldLen && nChgPos < nNewLen &&
+ pOldTxt[nChgPos] == pNewTxt[nChgPos] )
+ ++nChgPos;
+
+ xub_StrLen nChgLen = static_cast< xub_StrLen >( nNewLen - nChgPos );
+ String aChgText( aNewText.copy( nChgPos ), nChgLen );
+
+ // select text from first pos to be changed to current pos
+ EditSelection aSel( EditPaM( aPaM.GetNode(), (USHORT) nChgPos ), aPaM );
+
+ if (aChgText.Len())
+ return InsertText( aSel, aChgText ); // implicitly handles undo
+ else
+ return aPaM;
+ }
+ else
+ {
+ // should the character be ignored (i.e. not get inserted) ?
+ if (!_xISC->checkInputSequence( aOldText, nTmpPos - 1, c, nCheckMode ))
+ return aPaM; // nothing to be done -> no need for undo
+ }
+ }
+
+ // at this point now we will insert the character 'normally' some lines below...
+ }
+
+ if ( IsUndoEnabled() && !IsInUndo() )
+ {
+ EditUndoInsertChars* pNewUndo = new EditUndoInsertChars( this, CreateEPaM( aPaM ), c );
+ BOOL bTryMerge = ( !bDoOverwrite && ( c != ' ' ) ) ? TRUE : FALSE;
+ InsertUndo( pNewUndo, bTryMerge );
+ }
+
+ aEditDoc.InsertText( (const EditPaM&)aPaM, c );
+ ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() );
+ DBG_ASSERT( pPortion, "Blinde Portion in InsertText" );
+ pPortion->MarkInvalid( aPaM.GetIndex(), 1 );
+ aPaM.GetIndex()++; // macht EditDoc-Methode nicht mehr
+ }
+
+ TextModified();
+
+ if ( bUndoAction )
+ UndoActionEnd( EDITUNDO_INSERT );
+
+ return aPaM;
+}
+
+EditPaM ImpEditEngine::ImpInsertText( EditSelection aCurSel, const XubString& rStr )
+{
+ UndoActionStart( EDITUNDO_INSERT );
+
+ EditPaM aPaM;
+ if ( aCurSel.HasRange() )
+ aPaM = ImpDeleteSelection( aCurSel );
+ else
+ aPaM = aCurSel.Max();
+
+ EditPaM aCurPaM( aPaM ); // fuers Invalidieren
+
+ XubString aText( rStr );
+ aText.ConvertLineEnd( LINEEND_LF );
+ SfxVoidItem aTabItem( EE_FEATURE_TAB );
+
+ // Konvertiert nach LineSep = \n
+ // Token mit LINE_SEP abfragen,
+ // da der MAC-Compiler aus \n etwas anderes macht!
+
+ USHORT nStart = 0;
+ while ( nStart < aText.Len() )
+ {
+ USHORT nEnd = aText.Search( LINE_SEP, nStart );
+ if ( nEnd == STRING_NOTFOUND )
+ nEnd = aText.Len(); // nicht dereferenzieren!
+
+ // Start == End => Leerzeile
+ if ( nEnd > nStart )
+ {
+ XubString aLine( aText, nStart, nEnd-nStart );
+ xub_StrLen nChars = aPaM.GetNode()->Len() + aLine.Len();
+ if ( nChars > MAXCHARSINPARA )
+ {
+ USHORT nMaxNewChars = MAXCHARSINPARA-aPaM.GetNode()->Len();
+ nEnd -= ( aLine.Len() - nMaxNewChars ); // Dann landen die Zeichen im naechsten Absatz.
+ aLine.Erase( nMaxNewChars ); // Del Rest...
+ }
+#ifndef SVX_LIGHT
+ if ( IsUndoEnabled() && !IsInUndo() )
+ InsertUndo( new EditUndoInsertChars( this, CreateEPaM( aPaM ), aLine ) );
+#endif
+ // Tabs ?
+ if ( aLine.Search( '\t' ) == STRING_NOTFOUND )
+ aPaM = aEditDoc.InsertText( aPaM, aLine );
+ else
+ {
+ USHORT nStart2 = 0;
+ while ( nStart2 < aLine.Len() )
+ {
+ USHORT nEnd2 = aLine.Search( '\t', nStart2 );
+ if ( nEnd2 == STRING_NOTFOUND )
+ nEnd2 = aLine.Len(); // nicht dereferenzieren!
+
+ if ( nEnd2 > nStart2 )
+ aPaM = aEditDoc.InsertText( aPaM, XubString( aLine, nStart2, nEnd2-nStart2 ) );
+ if ( nEnd2 < aLine.Len() )
+ {
+ // aPaM = ImpInsertFeature( EditSelection( aPaM, aPaM ), );
+ aPaM = aEditDoc.InsertFeature( aPaM, aTabItem );
+ }
+ nStart2 = nEnd2+1;
+ }
+ }
+ ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() );
+ DBG_ASSERT( pPortion, "Blinde Portion in InsertText" );
+ pPortion->MarkInvalid( aCurPaM.GetIndex(), aLine.Len() );
+ }
+ if ( nEnd < aText.Len() )
+ aPaM = ImpInsertParaBreak( aPaM );
+
+ nStart = nEnd+1;
+ }
+
+ UndoActionEnd( EDITUNDO_INSERT );
+
+ TextModified();
+ return aPaM;
+}
+
+EditPaM ImpEditEngine::ImpFastInsertText( EditPaM aPaM, const XubString& rStr )
+{
+ DBG_ASSERT( rStr.Search( 0x0A ) == STRING_NOTFOUND, "FastInsertText: Zeilentrenner nicht erlaubt!" );
+ DBG_ASSERT( rStr.Search( 0x0D ) == STRING_NOTFOUND, "FastInsertText: Zeilentrenner nicht erlaubt!" );
+ DBG_ASSERT( rStr.Search( '\t' ) == STRING_NOTFOUND, "FastInsertText: Features nicht erlaubt!" );
+
+ if ( ( aPaM.GetNode()->Len() + rStr.Len() ) < MAXCHARSINPARA )
+ {
+#ifndef SVX_LIGHT
+ if ( IsUndoEnabled() && !IsInUndo() )
+ InsertUndo( new EditUndoInsertChars( this, CreateEPaM( aPaM ), rStr ) );
+#endif
+
+ aPaM = aEditDoc.InsertText( aPaM, rStr );
+ TextModified();
+ }
+ else
+ {
+ aPaM = ImpInsertText( aPaM, rStr );
+ }
+
+ return aPaM;
+}
+
+EditPaM ImpEditEngine::ImpInsertFeature( EditSelection aCurSel, const SfxPoolItem& rItem )
+{
+ EditPaM aPaM;
+ if ( aCurSel.HasRange() )
+ aPaM = ImpDeleteSelection( aCurSel );
+ else
+ aPaM = aCurSel.Max();
+
+ if ( aPaM.GetIndex() >= 0xfffe )
+ return aPaM;
+
+#ifndef SVX_LIGHT
+ if ( IsUndoEnabled() && !IsInUndo() )
+ InsertUndo( new EditUndoInsertFeature( this, CreateEPaM( aPaM ), rItem ) );
+#endif
+ aPaM = aEditDoc.InsertFeature( aPaM, rItem );
+
+ ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() );
+ DBG_ASSERT( pPortion, "Blinde Portion in InsertFeature" );
+ pPortion->MarkInvalid( aPaM.GetIndex()-1, 1 );
+
+ TextModified();
+
+ return aPaM;
+}
+
+EditPaM ImpEditEngine::ImpInsertParaBreak( const EditSelection& rCurSel, BOOL bKeepEndingAttribs )
+{
+ EditPaM aPaM;
+ if ( rCurSel.HasRange() )
+ aPaM = ImpDeleteSelection( rCurSel );
+ else
+ aPaM = rCurSel.Max();
+
+ return ImpInsertParaBreak( aPaM, bKeepEndingAttribs );
+}
+
+EditPaM ImpEditEngine::ImpInsertParaBreak( const EditPaM& rPaM, BOOL bKeepEndingAttribs )
+{
+ if ( aEditDoc.Count() >= 0xFFFE )
+ {
+ DBG_ERROR( "Can't process more than 64K paragraphs!" );
+ return rPaM;
+ }
+
+#ifndef SVX_LIGHT
+ if ( IsUndoEnabled() && !IsInUndo() )
+ InsertUndo( new EditUndoSplitPara( this, aEditDoc.GetPos( rPaM.GetNode() ), rPaM.GetIndex() ) );
+#endif
+
+ EditPaM aPaM( aEditDoc.InsertParaBreak( rPaM, bKeepEndingAttribs ) );
+
+#ifndef SVX_LIGHT
+ if ( GetStatus().DoOnlineSpelling() )
+ {
+ xub_StrLen nEnd = rPaM.GetNode()->Len();
+ aPaM.GetNode()->CreateWrongList();
+ WrongList* pLWrongs = rPaM.GetNode()->GetWrongList();
+ WrongList* pRWrongs = aPaM.GetNode()->GetWrongList();
+ // Falschgeschriebene Woerter ruebernehmen:
+ USHORT nLWrongs = pLWrongs->Count();
+ for ( USHORT nW = 0; nW < nLWrongs; nW++ )
+ {
+ WrongRange& rWrong = pLWrongs->GetObject( nW );
+ // Nur wenn wirklich dahinter, ein ueberlappendes wird beim Spell korrigiert
+ if ( rWrong.nStart > nEnd )
+ {
+ pRWrongs->InsertWrong( rWrong, pRWrongs->Count() );
+ WrongRange& rRWrong = pRWrongs->GetObject( pRWrongs->Count() - 1 );
+ rRWrong.nStart = rRWrong.nStart - nEnd;
+ rRWrong.nEnd = rRWrong.nEnd - nEnd;
+ }
+ else if ( ( rWrong.nStart < nEnd ) && ( rWrong.nEnd > nEnd ) )
+ rWrong.nEnd = nEnd;
+ }
+ USHORT nInv = nEnd ? nEnd-1 : nEnd;
+ if ( nEnd )
+ pLWrongs->MarkInvalid( nInv, nEnd );
+ else
+ pLWrongs->SetValid();
+ pRWrongs->SetValid(); // sonst 0 - 0xFFFF
+ pRWrongs->MarkInvalid( 0, 1 ); // Nur das erste Wort testen
+ }
+#endif // !SVX_LIGHT
+
+
+ ParaPortion* pPortion = FindParaPortion( rPaM.GetNode() );
+ DBG_ASSERT( pPortion, "Blinde Portion in ImpInsertParaBreak" );
+ pPortion->MarkInvalid( rPaM.GetIndex(), 0 );
+
+ // Optimieren: Nicht unnoetig viele GetPos auf die Listen ansetzen!
+ // Hier z.B. bei Undo, aber auch in allen anderen Methoden.
+ USHORT nPos = GetParaPortions().GetPos( pPortion );
+ ParaPortion* pNewPortion = new ParaPortion( aPaM.GetNode() );
+ GetParaPortions().Insert( pNewPortion, nPos + 1 );
+ ParaAttribsChanged( pNewPortion->GetNode() );
+ if ( IsCallParaInsertedOrDeleted() )
+ GetEditEnginePtr()->ParagraphInserted( nPos+1 );
+
+ CursorMoved( rPaM.GetNode() ); // falls leeres Attribut entstanden.
+ TextModified();
+ return aPaM;
+}
+
+EditPaM ImpEditEngine::ImpFastInsertParagraph( USHORT nPara )
+{
+#ifndef SVX_LIGHT
+ if ( IsUndoEnabled() && !IsInUndo() )
+ {
+ if ( nPara )
+ {
+ DBG_ASSERT( aEditDoc.SaveGetObject( nPara-1 ), "FastInsertParagraph: Prev existiert nicht" );
+ InsertUndo( new EditUndoSplitPara( this, nPara-1, aEditDoc.GetObject( nPara-1 )->Len() ) );
+ }
+ else
+ InsertUndo( new EditUndoSplitPara( this, 0, 0 ) );
+ }
+#endif
+
+ ContentNode* pNode = new ContentNode( aEditDoc.GetItemPool() );
+ // Falls FlatMode, wird spaeter kein Font eingestellt:
+ pNode->GetCharAttribs().GetDefFont() = aEditDoc.GetDefFont();
+
+#ifndef SVX_LIGHT
+ if ( GetStatus().DoOnlineSpelling() )
+ pNode->CreateWrongList();
+#endif // !SVX_LIGHT
+
+ aEditDoc.Insert( pNode, nPara );
+
+ ParaPortion* pNewPortion = new ParaPortion( pNode );
+ GetParaPortions().Insert( pNewPortion, nPara );
+ if ( IsCallParaInsertedOrDeleted() )
+ GetEditEnginePtr()->ParagraphInserted( nPara );
+
+ return EditPaM( pNode, 0 );
+}
+
+EditPaM ImpEditEngine::InsertParaBreak( EditSelection aCurSel )
+{
+ EditPaM aPaM( ImpInsertParaBreak( aCurSel ) );
+ if ( aStatus.DoAutoIndenting() )
+ {
+ USHORT nPara = aEditDoc.GetPos( aPaM.GetNode() );
+ DBG_ASSERT( nPara > 0, "AutoIndenting: Fehler!" );
+ XubString aPrevParaText( GetEditDoc().GetParaAsString( nPara-1 ) );
+ USHORT n = 0;
+ while ( ( n < aPrevParaText.Len() ) &&
+ ( ( aPrevParaText.GetChar(n) == ' ' ) || ( aPrevParaText.GetChar(n) == '\t' ) ) )
+ {
+ if ( aPrevParaText.GetChar(n) == '\t' )
+ aPaM = ImpInsertFeature( aPaM, SfxVoidItem( EE_FEATURE_TAB ) );
+ else
+ aPaM = ImpInsertText( aPaM, aPrevParaText.GetChar(n) );
+ n++;
+ }
+
+ }
+ return aPaM;
+}
+
+EditPaM ImpEditEngine::InsertTab( EditSelection aCurSel )
+{
+ EditPaM aPaM( ImpInsertFeature( aCurSel, SfxVoidItem( EE_FEATURE_TAB ) ) );
+ return aPaM;
+}
+
+EditPaM ImpEditEngine::InsertField( EditSelection aCurSel, const SvxFieldItem& rFld )
+{
+ EditPaM aPaM( ImpInsertFeature( aCurSel, rFld ) );
+ return aPaM;
+}
+
+BOOL ImpEditEngine::UpdateFields()
+{
+ BOOL bChanges = FALSE;
+ USHORT nParas = GetEditDoc().Count();
+ for ( USHORT nPara = 0; nPara < nParas; nPara++ )
+ {
+ BOOL bChangesInPara = FALSE;
+ ContentNode* pNode = GetEditDoc().GetObject( nPara );
+ DBG_ASSERT( pNode, "NULL-Pointer im Doc" );
+ CharAttribArray& rAttribs = pNode->GetCharAttribs().GetAttribs();
+// USHORT nAttrs = rAttribs.Count();
+ for ( USHORT nAttr = 0; nAttr < rAttribs.Count(); nAttr++ )
+ {
+ EditCharAttrib* pAttr = rAttribs[nAttr];
+ if ( pAttr->Which() == EE_FEATURE_FIELD )
+ {
+ EditCharAttribField* pField = (EditCharAttribField*)pAttr;
+ EditCharAttribField* pCurrent = new EditCharAttribField( *pField );
+ pField->Reset();
+
+ if ( aStatus.MarkFields() )
+ pField->GetFldColor() = new Color( GetColorConfig().GetColorValue( svtools::WRITERFIELDSHADINGS ).nColor );
+
+ XubString aFldValue = GetEditEnginePtr()->CalcFieldValue(
+ (const SvxFieldItem&)*pField->GetItem(),
+ nPara, pField->GetStart(),
+ pField->GetTxtColor(), pField->GetFldColor() );
+ pField->GetFieldValue() = aFldValue;
+ if ( *pField != *pCurrent )
+ {
+ bChanges = TRUE;
+ bChangesInPara = TRUE;
+ }
+ delete pCurrent;
+ }
+ }
+ if ( bChangesInPara )
+ {
+ // ggf. etwas genauer invalidieren.
+ ParaPortion* pPortion = GetParaPortions().GetObject( nPara );
+ DBG_ASSERT( pPortion, "NULL-Pointer im Doc" );
+ pPortion->MarkSelectionInvalid( 0, pNode->Len() );
+ }
+ }
+ return bChanges;
+}
+
+EditPaM ImpEditEngine::InsertLineBreak( EditSelection aCurSel )
+{
+ EditPaM aPaM( ImpInsertFeature( aCurSel, SfxVoidItem( EE_FEATURE_LINEBR ) ) );
+ return aPaM;
+}
+
+// ----------------------------------------------------------------------
+// Hilfsfunktionen
+// ----------------------------------------------------------------------
+Rectangle ImpEditEngine::PaMtoEditCursor( EditPaM aPaM, USHORT nFlags )
+{
+ DBG_ASSERT( GetUpdateMode(), "Darf bei Update=FALSE nicht erreicht werden: PaMtoEditCursor" );
+
+ Rectangle aEditCursor;
+ long nY = 0;
+ for ( USHORT nPortion = 0; nPortion < GetParaPortions().Count(); nPortion++ )
+ {
+ ParaPortion* pPortion = GetParaPortions().GetObject(nPortion);
+ ContentNode* pNode = pPortion->GetNode();
+ DBG_ASSERT( pNode, "Ungueltiger Node in Portion!" );
+ if ( pNode != aPaM.GetNode() )
+ {
+ nY += pPortion->GetHeight();
+ }
+ else
+ {
+ aEditCursor = GetEditCursor( pPortion, aPaM.GetIndex(), nFlags );
+ aEditCursor.Top() += nY;
+ aEditCursor.Bottom() += nY;
+ return aEditCursor;
+ }
+ }
+ DBG_ERROR( "Portion nicht gefunden!" );
+ return aEditCursor;
+}
+
+EditPaM ImpEditEngine::GetPaM( Point aDocPos, BOOL bSmart )
+{
+ DBG_ASSERT( GetUpdateMode(), "Darf bei Update=FALSE nicht erreicht werden: GetPaM" );
+
+ long nY = 0;
+ long nTmpHeight;
+ EditPaM aPaM;
+ USHORT nPortion;
+ for ( nPortion = 0; nPortion < GetParaPortions().Count(); nPortion++ )
+ {
+ ParaPortion* pPortion = GetParaPortions().GetObject(nPortion);
+ nTmpHeight = pPortion->GetHeight(); // sollte auch bei !bVisible richtig sein!
+ nY += nTmpHeight;
+ if ( nY > aDocPos.Y() )
+ {
+ nY -= nTmpHeight;
+ aDocPos.Y() -= nY;
+ // unsichtbare Portions ueberspringen:
+ while ( pPortion && !pPortion->IsVisible() )
+ {
+ nPortion++;
+ pPortion = GetParaPortions().SaveGetObject( nPortion );
+ }
+ DBG_ASSERT( pPortion, "Keinen sichtbaren Absatz gefunden: GetPaM" );
+ aPaM = GetPaM( pPortion, aDocPos, bSmart );
+ return aPaM;
+
+ }
+ }
+ // Dann den letzten sichtbaren Suchen:
+ nPortion = GetParaPortions().Count()-1;
+ while ( nPortion && !GetParaPortions()[nPortion]->IsVisible() )
+ nPortion--;
+
+ DBG_ASSERT( GetParaPortions()[nPortion]->IsVisible(), "Keinen sichtbaren Absatz gefunden: GetPaM" );
+ aPaM.SetNode( GetParaPortions()[nPortion]->GetNode() );
+ aPaM.SetIndex( GetParaPortions()[nPortion]->GetNode()->Len() );
+ return aPaM;
+}
+
+sal_uInt32 ImpEditEngine::GetTextHeight() const
+{
+ DBG_ASSERT( GetUpdateMode(), "Sollte bei Update=FALSE nicht verwendet werden: GetTextHeight" );
+ DBG_ASSERT( IsFormatted() || IsFormatting(), "GetTextHeight: Nicht formatiert" );
+ return nCurTextHeight;
+}
+
+sal_uInt32 ImpEditEngine::CalcTextWidth( BOOL bIgnoreExtraSpace )
+{
+ // Wenn noch nicht formatiert und nicht gerade dabei.
+ // Wird in der Formatierung bei AutoPageSize gerufen.
+ if ( !IsFormatted() && !IsFormatting() )
+ FormatDoc();
+
+ EditLine* pLine;
+
+ long nMaxWidth = 0;
+ long nCurWidth = 0;
+
+ // --------------------------------------------------
+ // Ueber alle Absaetze...
+ // --------------------------------------------------
+ USHORT nParas = GetParaPortions().Count();
+// USHORT nBiggestPara = 0;
+// USHORT nBiggestLine = 0;
+ for ( USHORT nPara = 0; nPara < nParas; nPara++ )
+ {
+ ParaPortion* pPortion = GetParaPortions().GetObject( nPara );
+ if ( pPortion->IsVisible() )
+ {
+ const SvxLRSpaceItem& rLRItem = GetLRSpaceItem( pPortion->GetNode() );
+ sal_Int32 nSpaceBeforeAndMinLabelWidth = GetSpaceBeforeAndMinLabelWidth( pPortion->GetNode() );
+
+ // --------------------------------------------------
+ // Ueber die Zeilen des Absatzes...
+ // --------------------------------------------------
+ ULONG nLines = pPortion->GetLines().Count();
+ for ( USHORT nLine = 0; nLine < nLines; nLine++ )
+ {
+ pLine = pPortion->GetLines().GetObject( nLine );
+ DBG_ASSERT( pLine, "NULL-Pointer im Zeileniterator in CalcWidth" );
+ // nCurWidth = pLine->GetStartPosX();
+ // Bei Center oder Right haengt die breite von der
+ // Papierbreite ab, hier nicht erwuenscht.
+ // Am besten generell nicht auf StartPosX verlassen,
+ // es muss auch die rechte Einrueckung beruecksichtigt werden!
+ nCurWidth = GetXValue( rLRItem.GetTxtLeft() + nSpaceBeforeAndMinLabelWidth );
+ if ( nLine == 0 )
+ {
+ long nFI = GetXValue( rLRItem.GetTxtFirstLineOfst() );
+ nCurWidth -= nFI;
+ if ( pPortion->GetBulletX() > nCurWidth )
+ {
+ nCurWidth += nFI; // LI?
+ if ( pPortion->GetBulletX() > nCurWidth )
+ nCurWidth = pPortion->GetBulletX();
+ }
+ }
+ nCurWidth += GetXValue( rLRItem.GetRight() );
+ nCurWidth += CalcLineWidth( pPortion, pLine, bIgnoreExtraSpace );
+ if ( nCurWidth > nMaxWidth )
+ {
+ nMaxWidth = nCurWidth;
+ }
+ }
+ }
+ }
+ if ( nMaxWidth < 0 )
+ nMaxWidth = 0;
+
+ nMaxWidth++; // Ein breiter, da in CreateLines bei >= umgebrochen wird.
+ return (sal_uInt32)nMaxWidth;
+}
+
+sal_uInt32 ImpEditEngine::CalcLineWidth( ParaPortion* pPortion, EditLine* pLine, BOOL bIgnoreExtraSpace )
+{
+ USHORT nPara = GetEditDoc().GetPos( pPortion->GetNode() );
+
+ // #114278# Saving both layout mode and language (since I'm
+ // potentially changing both)
+ GetRefDevice()->Push( PUSH_TEXTLAYOUTMODE|PUSH_TEXTLANGUAGE );
+
+ ImplInitLayoutMode( GetRefDevice(), nPara, 0xFFFF );
+
+ SvxAdjust eJustification = GetJustification( nPara );
+
+ // Berechnung der Breite ohne die Indents...
+ sal_uInt32 nWidth = 0;
+ USHORT nPos = pLine->GetStart();
+ for ( USHORT nTP = pLine->GetStartPortion(); nTP <= pLine->GetEndPortion(); nTP++ )
+ {
+ TextPortion* pTextPortion = pPortion->GetTextPortions().GetObject( nTP );
+ switch ( pTextPortion->GetKind() )
+ {
+ case PORTIONKIND_FIELD:
+ case PORTIONKIND_HYPHENATOR:
+ case PORTIONKIND_TAB:
+ {
+ nWidth += pTextPortion->GetSize().Width();
+ }
+ break;
+ case PORTIONKIND_TEXT:
+ {
+ if ( ( eJustification != SVX_ADJUST_BLOCK ) || ( !bIgnoreExtraSpace ) )
+ {
+ nWidth += pTextPortion->GetSize().Width();
+ }
+ else
+ {
+ SvxFont aTmpFont( pPortion->GetNode()->GetCharAttribs().GetDefFont() );
+ SeekCursor( pPortion->GetNode(), nPos+1, aTmpFont );
+ aTmpFont.SetPhysFont( GetRefDevice() );
+ ImplInitDigitMode( GetRefDevice(), 0, 0, 0, aTmpFont.GetLanguage() );
+ nWidth += aTmpFont.QuickGetTextSize( GetRefDevice(), *pPortion->GetNode(), nPos, pTextPortion->GetLen(), NULL ).Width();
+ }
+ }
+ break;
+ }
+ nPos = nPos + pTextPortion->GetLen();
+ }
+
+ GetRefDevice()->Pop();
+
+ return nWidth;
+}
+
+sal_uInt32 ImpEditEngine::CalcTextHeight()
+{
+ DBG_ASSERT( GetUpdateMode(), "Sollte bei Update=FALSE nicht verwendet werden: CalcTextHeight" );
+ sal_uInt32 nY = 0;
+ for ( USHORT nPortion = 0; nPortion < GetParaPortions().Count(); nPortion++ )
+ nY += GetParaPortions()[nPortion]->GetHeight();
+ return nY;
+}
+
+USHORT ImpEditEngine::GetLineCount( USHORT nParagraph ) const
+{
+ DBG_ASSERT( nParagraph < GetParaPortions().Count(), "GetLineCount: Out of range" );
+ ParaPortion* pPPortion = GetParaPortions().SaveGetObject( nParagraph );
+ DBG_ASSERT( pPPortion, "Absatz nicht gefunden: GetLineCount" );
+ if ( pPPortion )
+ return pPPortion->GetLines().Count();
+
+ return 0xFFFF;
+}
+
+xub_StrLen ImpEditEngine::GetLineLen( USHORT nParagraph, USHORT nLine ) const
+{
+ DBG_ASSERT( nParagraph < GetParaPortions().Count(), "GetLineLen: Out of range" );
+ ParaPortion* pPPortion = GetParaPortions().SaveGetObject( nParagraph );
+ DBG_ASSERT( pPPortion, "Absatz nicht gefunden: GetLineLen" );
+ if ( pPPortion && ( nLine < pPPortion->GetLines().Count() ) )
+ {
+ EditLine* pLine = pPPortion->GetLines().GetObject( nLine );
+ DBG_ASSERT( pLine, "Zeile nicht gefunden: GetLineHeight" );
+ return pLine->GetLen();
+ }
+
+ return 0xFFFF;
+}
+
+void ImpEditEngine::GetLineBoundaries( /*out*/USHORT &rStart, /*out*/USHORT &rEnd, USHORT nParagraph, USHORT nLine ) const
+{
+ DBG_ASSERT( nParagraph < GetParaPortions().Count(), "GetLineCount: Out of range" );
+ ParaPortion* pPPortion = GetParaPortions().SaveGetObject( nParagraph );
+ DBG_ASSERT( pPPortion, "Absatz nicht gefunden: GetLineBoundaries" );
+ rStart = rEnd = 0xFFFF; // default values in case of error
+ if ( pPPortion && ( nLine < pPPortion->GetLines().Count() ) )
+ {
+ EditLine* pLine = pPPortion->GetLines().GetObject( nLine );
+ DBG_ASSERT( pLine, "Zeile nicht gefunden: GetLineBoundaries" );
+ rStart = pLine->GetStart();
+ rEnd = pLine->GetEnd();
+ }
+}
+
+USHORT ImpEditEngine::GetLineNumberAtIndex( USHORT nPara, USHORT nIndex ) const
+{
+ USHORT nLineNo = 0xFFFF;
+ ContentNode* pNode = GetEditDoc().SaveGetObject( nPara );
+ DBG_ASSERT( pNode, "GetLineNumberAtIndex: invalid paragraph index" );
+ if (pNode)
+ {
+ // we explicitly allow for the index to point at the character right behind the text
+ const bool bValidIndex = /*0 <= nIndex &&*/ nIndex <= pNode->Len();
+ DBG_ASSERT( bValidIndex, "GetLineNumberAtIndex: invalid index" );
+ const USHORT nLineCount = GetLineCount( nPara );
+ if (nIndex == pNode->Len())
+ nLineNo = nLineCount > 0 ? nLineCount - 1 : 0;
+ else if (bValidIndex) // nIndex < pNode->Len()
+ {
+ USHORT nStart = USHRT_MAX, nEnd = USHRT_MAX;
+ for (USHORT i = 0; i < nLineCount && nLineNo == 0xFFFF; ++i)
+ {
+ GetLineBoundaries( nStart, nEnd, nPara, i );
+ if (nStart <= nIndex && nIndex < nEnd)
+ nLineNo = i;
+ }
+ }
+ }
+ return nLineNo;
+}
+
+USHORT ImpEditEngine::GetLineHeight( USHORT nParagraph, USHORT nLine )
+{
+ DBG_ASSERT( nParagraph < GetParaPortions().Count(), "GetLineCount: Out of range" );
+ ParaPortion* pPPortion = GetParaPortions().SaveGetObject( nParagraph );
+ DBG_ASSERT( pPPortion, "Absatz nicht gefunden: GetLineHeight" );
+ if ( pPPortion && ( nLine < pPPortion->GetLines().Count() ) )
+ {
+ EditLine* pLine = pPPortion->GetLines().GetObject( nLine );
+ DBG_ASSERT( pLine, "Zeile nicht gefunden: GetLineHeight" );
+ return pLine->GetHeight();
+ }
+
+ return 0xFFFF;
+}
+
+sal_uInt32 ImpEditEngine::GetParaHeight( USHORT nParagraph )
+{
+ sal_uInt32 nHeight = 0;
+
+ ParaPortion* pPPortion = GetParaPortions().SaveGetObject( nParagraph );
+ DBG_ASSERT( pPPortion, "Absatz nicht gefunden: GetParaHeight" );
+
+ if ( pPPortion )
+ nHeight = pPPortion->GetHeight();
+
+ return nHeight;
+}
+
+void ImpEditEngine::UpdateSelections()
+{
+ USHORT nInvNodes = aDeletedNodes.Count();
+
+ // Pruefen, ob eine der Selektionen auf einem geloeschten Node steht...
+ // Wenn der Node gueltig ist, muss noch der Index geprueft werden!
+ for ( USHORT nView = 0; nView < aEditViews.Count(); nView++ )
+ {
+ EditView* pView = aEditViews.GetObject(nView);
+ DBG_CHKOBJ( pView, EditView, 0 );
+ EditSelection aCurSel( pView->pImpEditView->GetEditSelection() );
+ BOOL bChanged = FALSE;
+ for ( USHORT n = 0; n < nInvNodes; n++ )
+ {
+ DeletedNodeInfo* pInf = aDeletedNodes.GetObject( n );
+ if ( ( ( ULONG )(aCurSel.Min().GetNode()) == pInf->GetInvalidAdress() ) ||
+ ( ( ULONG )(aCurSel.Max().GetNode()) == pInf->GetInvalidAdress() ) )
+ {
+ // ParaPortions verwenden, da jetzt auch versteckte
+ // Absaetze beruecksichtigt werden muessen!
+ USHORT nPara = pInf->GetPosition();
+ ParaPortion* pPPortion = GetParaPortions().SaveGetObject( nPara );
+ if ( !pPPortion ) // letzter Absatz
+ {
+ nPara = GetParaPortions().Count()-1;
+ pPPortion = GetParaPortions().GetObject( nPara );
+ }
+ DBG_ASSERT( pPPortion, "Leeres Document in UpdateSelections ?" );
+ // Nicht aus einem verstecktem Absatz landen:
+ USHORT nCurPara = nPara;
+ USHORT nLastPara = GetParaPortions().Count()-1;
+ while ( nPara <= nLastPara && !GetParaPortions()[nPara]->IsVisible() )
+ nPara++;
+ if ( nPara > nLastPara ) // dann eben rueckwaerts...
+ {
+ nPara = nCurPara;
+ while ( nPara && !GetParaPortions()[nPara]->IsVisible() )
+ nPara--;
+ }
+ DBG_ASSERT( GetParaPortions()[nPara]->IsVisible(), "Keinen sichtbaren Absatz gefunden: UpdateSelections" );
+
+ ParaPortion* pParaPortion = GetParaPortions()[nPara];
+ EditSelection aTmpSelection( EditPaM( pParaPortion->GetNode(), 0 ) );
+ pView->pImpEditView->SetEditSelection( aTmpSelection );
+ bChanged=TRUE;
+ break; // for-Schleife
+ }
+ }
+ if ( !bChanged )
+ {
+ // Index prueffen, falls Node geschrumpft.
+ if ( aCurSel.Min().GetIndex() > aCurSel.Min().GetNode()->Len() )
+ {
+ aCurSel.Min().GetIndex() = aCurSel.Min().GetNode()->Len();
+ pView->pImpEditView->SetEditSelection( aCurSel );
+ }
+ if ( aCurSel.Max().GetIndex() > aCurSel.Max().GetNode()->Len() )
+ {
+ aCurSel.Max().GetIndex() = aCurSel.Max().GetNode()->Len();
+ pView->pImpEditView->SetEditSelection( aCurSel );
+ }
+ }
+ }
+
+ // Loeschen...
+ for ( USHORT n = 0; n < nInvNodes; n++ )
+ {
+ DeletedNodeInfo* pInf = aDeletedNodes.GetObject( n );
+ delete pInf;
+ }
+ aDeletedNodes.Remove( 0, aDeletedNodes.Count() );
+}
+
+EditSelection ImpEditEngine::ConvertSelection( USHORT nStartPara, USHORT nStartPos,
+ USHORT nEndPara, USHORT nEndPos ) const
+{
+ EditSelection aNewSelection;
+
+ // Start...
+ ContentNode* pNode = aEditDoc.SaveGetObject( nStartPara );
+ USHORT nIndex = nStartPos;
+ if ( !pNode )
+ {
+ pNode = aEditDoc[ aEditDoc.Count()-1 ];
+ nIndex = pNode->Len();
+ }
+ else if ( nIndex > pNode->Len() )
+ nIndex = pNode->Len();
+
+ aNewSelection.Min().SetNode( pNode );
+ aNewSelection.Min().SetIndex( nIndex );
+
+ // End...
+ pNode = aEditDoc.SaveGetObject( nEndPara );
+ nIndex = nEndPos;
+ if ( !pNode )
+ {
+ pNode = aEditDoc[ aEditDoc.Count()-1 ];
+ nIndex = pNode->Len();
+ }
+ else if ( nIndex > pNode->Len() )
+ nIndex = pNode->Len();
+
+ aNewSelection.Max().SetNode( pNode );
+ aNewSelection.Max().SetIndex( nIndex );
+
+ return aNewSelection;
+}
+
+EditSelection ImpEditEngine::MatchGroup( const EditSelection& rSel )
+{
+ EditSelection aMatchSel;
+ EditSelection aTmpSel( rSel );
+ aTmpSel.Adjust( GetEditDoc() );
+ if ( ( aTmpSel.Min().GetNode() != aTmpSel.Max().GetNode() ) ||
+ ( ( aTmpSel.Max().GetIndex() - aTmpSel.Min().GetIndex() ) > 1 ) )
+ {
+ return aMatchSel;
+ }
+
+ USHORT nPos = aTmpSel.Min().GetIndex();
+ ContentNode* pNode = aTmpSel.Min().GetNode();
+ if ( nPos >= pNode->Len() )
+ return aMatchSel;
+
+ USHORT nMatchChar = aGroupChars.Search( pNode->GetChar( nPos ) );
+ if ( nMatchChar != STRING_NOTFOUND )
+ {
+ USHORT nNode = aEditDoc.GetPos( pNode );
+ if ( ( nMatchChar % 2 ) == 0 )
+ {
+ // Vorwaerts suchen...
+ xub_Unicode nSC = aGroupChars.GetChar( nMatchChar );
+ DBG_ASSERT( aGroupChars.Len() > (nMatchChar+1), "Ungueltige Gruppe von MatchChars!" );
+ xub_Unicode nEC = aGroupChars.GetChar( nMatchChar+1 );
+
+ USHORT nCur = aTmpSel.Min().GetIndex()+1;
+ USHORT nLevel = 1;
+ while ( pNode && nLevel )
+ {
+ XubString& rStr = *pNode;
+ while ( nCur < rStr.Len() )
+ {
+ if ( rStr.GetChar( nCur ) == nSC )
+ nLevel++;
+ else if ( rStr.GetChar( nCur ) == nEC )
+ {
+ nLevel--;
+ if ( !nLevel )
+ break; // while nCur...
+ }
+ nCur++;
+ }
+
+ if ( nLevel )
+ {
+ nNode++;
+ pNode = nNode < aEditDoc.Count() ? aEditDoc.GetObject( nNode ) : 0;
+ nCur = 0;
+ }
+ }
+ if ( nLevel == 0 ) // gefunden
+ {
+ aMatchSel.Min() = aTmpSel.Min();
+ aMatchSel.Max() = EditPaM( pNode, nCur+1 );
+ }
+ }
+ else
+ {
+ // Rueckwaerts suchen...
+ xub_Unicode nEC = aGroupChars.GetChar( nMatchChar );
+ xub_Unicode nSC = aGroupChars.GetChar( nMatchChar-1 );
+
+ USHORT nCur = aTmpSel.Min().GetIndex()-1;
+ USHORT nLevel = 1;
+ while ( pNode && nLevel )
+ {
+ if ( pNode->Len() )
+ {
+ XubString& rStr = *pNode;
+ while ( nCur )
+ {
+ if ( rStr.GetChar( nCur ) == nSC )
+ {
+ nLevel--;
+ if ( !nLevel )
+ break; // while nCur...
+ }
+ else if ( rStr.GetChar( nCur ) == nEC )
+ nLevel++;
+
+ nCur--;
+ }
+ }
+
+ if ( nLevel )
+ {
+ pNode = nNode ? aEditDoc.GetObject( --nNode ) : 0;
+ if ( pNode )
+ nCur = pNode->Len()-1; // egal ob negativ, weil if Len()
+ }
+ }
+
+ if ( nLevel == 0 ) // gefunden
+ {
+ aMatchSel.Min() = aTmpSel.Min();
+ aMatchSel.Min().GetIndex()++; // hinter das Zeichen
+ aMatchSel.Max() = EditPaM( pNode, nCur );
+ }
+ }
+ }
+ return aMatchSel;
+}
+
+void ImpEditEngine::StopSelectionMode()
+{
+ if ( ( IsInSelectionMode() || aSelEngine.IsInSelection() ) && pActiveView )
+ {
+ pActiveView->pImpEditView->DrawSelection(); // Wegzeichnen...
+ EditSelection aSel( pActiveView->pImpEditView->GetEditSelection() );
+ aSel.Min() = aSel.Max();
+ pActiveView->pImpEditView->SetEditSelection( aSel );
+ pActiveView->ShowCursor();
+ aSelEngine.Reset();
+ bInSelection = FALSE;
+ }
+}
+
+void ImpEditEngine::SetActiveView( EditView* pView )
+{
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ // Eigentlich waere jetzt ein bHasVisSel und HideSelection notwendig !!!
+
+ if ( pView == pActiveView )
+ return;
+
+ if ( pActiveView && pActiveView->HasSelection() )
+ pActiveView->pImpEditView->DrawSelection(); // Wegzeichnen...
+
+ pActiveView = pView;
+
+ if ( pActiveView && pActiveView->HasSelection() )
+ pActiveView->pImpEditView->DrawSelection(); // Wegzeichnen...
+
+ // NN: Quick fix for #78668#:
+ // When editing of a cell in Calc is ended, the edit engine is not deleted,
+ // only the edit views are removed. If mpIMEInfos is still set in that case,
+ // mpIMEInfos->aPos points to an invalid selection.
+ // -> reset mpIMEInfos now
+ // (probably something like this is necessary whenever the content is modified
+ // from the outside)
+
+ if ( !pView && mpIMEInfos )
+ {
+ delete mpIMEInfos;
+ mpIMEInfos = NULL;
+ }
+}
+
+uno::Reference< datatransfer::XTransferable > ImpEditEngine::CreateTransferable( const EditSelection& rSelection ) const
+{
+#ifndef SVX_LIGHT
+ EditSelection aSelection( rSelection );
+ aSelection.Adjust( GetEditDoc() );
+
+ EditDataObject* pDataObj = new EditDataObject;
+ uno::Reference< datatransfer::XTransferable > xDataObj;
+ xDataObj = pDataObj;
+
+ XubString aText( GetSelected( aSelection ) );
+ aText.ConvertLineEnd(); // Systemspezifisch
+ pDataObj->GetString() = aText;
+
+ SvxFontItem::EnableStoreUnicodeNames( TRUE );
+ WriteBin( pDataObj->GetStream(), aSelection, TRUE );
+ pDataObj->GetStream().Seek( 0 );
+ SvxFontItem::EnableStoreUnicodeNames( FALSE );
+
+ ((ImpEditEngine*)this)->WriteRTF( pDataObj->GetRTFStream(), aSelection );
+ pDataObj->GetRTFStream().Seek( 0 );
+
+ if ( ( aSelection.Min().GetNode() == aSelection.Max().GetNode() )
+ && ( aSelection.Max().GetIndex() == (aSelection.Min().GetIndex()+1) ) )
+ {
+ const EditCharAttrib* pAttr = aSelection.Min().GetNode()->GetCharAttribs().
+ FindFeature( aSelection.Min().GetIndex() );
+ if ( pAttr &&
+ ( pAttr->GetStart() == aSelection.Min().GetIndex() ) &&
+ ( pAttr->Which() == EE_FEATURE_FIELD ) )
+ {
+ const SvxFieldItem* pField = (const SvxFieldItem*)pAttr->GetItem();
+ const SvxFieldData* pFld = pField->GetField();
+ if ( pFld && pFld->ISA( SvxURLField ) )
+ {
+ // Office-Bookmark
+ String aURL( ((const SvxURLField*)pFld)->GetURL() );
+ String aTxt( ((const SvxURLField*)pFld)->GetRepresentation() );
+ pDataObj->GetURL() = aURL;
+ }
+ }
+ }
+
+ return xDataObj;
+#else
+ return uno::Reference< datatransfer::XTransferable >();
+#endif
+}
+
+EditSelection ImpEditEngine::InsertText( uno::Reference< datatransfer::XTransferable >& rxDataObj, const String& rBaseURL, const EditPaM& rPaM, BOOL bUseSpecial )
+{
+ EditSelection aNewSelection( rPaM );
+
+ if ( rxDataObj.is() )
+ {
+ datatransfer::DataFlavor aFlavor;
+ BOOL bDone = FALSE;
+
+ if ( bUseSpecial )
+ {
+ // BIN
+ SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_EDITENGINE, aFlavor );
+ if ( rxDataObj->isDataFlavorSupported( aFlavor ) )
+ {
+ try
+ {
+ uno::Any aData = rxDataObj->getTransferData( aFlavor );
+ uno::Sequence< sal_Int8 > aSeq;
+ aData >>= aSeq;
+ {
+ SvMemoryStream aBinStream( aSeq.getArray(), aSeq.getLength(), STREAM_READ );
+ aNewSelection = Read( aBinStream, rBaseURL, EE_FORMAT_BIN, rPaM );
+ }
+ bDone = TRUE;
+ }
+ catch( const ::com::sun::star::uno::Exception& )
+ {
+ }
+ }
+
+ if ( !bDone )
+ {
+ // Bookmark
+ /*
+ String aURL = ...;
+ String aTxt = ...;
+ // Feld nur einfuegen, wenn Factory vorhanden.
+ if ( ITEMDATA() && ITEMDATA()->GetClassManager().Get( SVX_URLFIELD ) )
+ {
+ SvxFieldItem aField( SvxURLField( aURL, aTxt, SVXURLFORMAT_URL ), EE_FEATURE_FIELD );
+ aNewSelection = InsertField( aPaM, aField );
+ UpdateFields();
+ }
+ else
+ aNewSelection = ImpInsertText( aPaM, aURL );
+ }
+ */
+ }
+ if ( !bDone )
+ {
+ // RTF
+ SotExchange::GetFormatDataFlavor( SOT_FORMAT_RTF, aFlavor );
+ if ( rxDataObj->isDataFlavorSupported( aFlavor ) )
+ {
+ try
+ {
+ uno::Any aData = rxDataObj->getTransferData( aFlavor );
+ uno::Sequence< sal_Int8 > aSeq;
+ aData >>= aSeq;
+ {
+ SvMemoryStream aRTFStream( aSeq.getArray(), aSeq.getLength(), STREAM_READ );
+ aNewSelection = Read( aRTFStream, rBaseURL, EE_FORMAT_RTF, rPaM );
+ }
+ bDone = TRUE;
+ }
+ catch( const ::com::sun::star::uno::Exception& )
+ {
+ }
+ }
+ }
+ if ( !bDone )
+ {
+ // XML ?
+ // Currently, there is nothing like "The" XML format, StarOffice doesn't offer plain XML in Clipboard...
+ }
+ }
+ if ( !bDone )
+ {
+ SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor );
+ if ( rxDataObj->isDataFlavorSupported( aFlavor ) )
+ {
+ try
+ {
+ uno::Any aData = rxDataObj->getTransferData( aFlavor );
+ ::rtl::OUString aText;
+ aData >>= aText;
+ aNewSelection = ImpInsertText( rPaM, aText );
+ bDone = TRUE;
+ }
+ catch( ... )
+ {
+ ; // #i9286# can happen, even if isDataFlavorSupported returns true...
+ }
+ }
+ }
+ }
+
+ return aNewSelection;
+}
+
+Range ImpEditEngine::GetInvalidYOffsets( ParaPortion* pPortion )
+{
+ Range aRange( 0, 0 );
+
+ if ( pPortion->IsVisible() )
+ {
+ const SvxULSpaceItem& rULSpace = (const SvxULSpaceItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE );
+ const SvxLineSpacingItem& rLSItem = (const SvxLineSpacingItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
+ USHORT nSBL = ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_FIX )
+ ? GetYValue( rLSItem.GetInterLineSpace() ) : 0;
+
+ // erst von vorne...
+ USHORT nFirstInvalid = 0xFFFF;
+ USHORT nLine;
+ for ( nLine = 0; nLine < pPortion->GetLines().Count(); nLine++ )
+ {
+ EditLine* pL = pPortion->GetLines().GetObject( nLine );
+ if ( pL->IsInvalid() )
+ {
+ nFirstInvalid = nLine;
+ break;
+ }
+ if ( nLine && !aStatus.IsOutliner() ) // nicht die erste Zeile
+ aRange.Min() += nSBL;
+ aRange.Min() += pL->GetHeight();
+ }
+ DBG_ASSERT( nFirstInvalid != 0xFFFF, "Keine ungueltige Zeile gefunden in GetInvalidYOffset(1)" );
+
+
+ // Abgleichen und weiter...
+ aRange.Max() = aRange.Min();
+ aRange.Max() += pPortion->GetFirstLineOffset();
+ if ( nFirstInvalid != 0 ) // Nur wenn nicht die erste Zeile ungueltig
+ aRange.Min() = aRange.Max();
+
+ USHORT nLastInvalid = pPortion->GetLines().Count()-1;
+ for ( nLine = nFirstInvalid; nLine < pPortion->GetLines().Count(); nLine++ )
+ {
+ EditLine* pL = pPortion->GetLines().GetObject( nLine );
+ if ( pL->IsValid() )
+ {
+ nLastInvalid = nLine;
+ break;
+ }
+
+ if ( nLine && !aStatus.IsOutliner() )
+ aRange.Max() += nSBL;
+ aRange.Max() += pL->GetHeight();
+ }
+
+ // MT 07/00 SBL kann jetzt kleiner 100% sein => ggf. die Zeile davor neu ausgeben.
+ if( ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP ) && rLSItem.GetPropLineSpace() &&
+ ( rLSItem.GetPropLineSpace() < 100 ) )
+ {
+ EditLine* pL = pPortion->GetLines().GetObject( nFirstInvalid );
+ long n = pL->GetTxtHeight() * ( 100 - rLSItem.GetPropLineSpace() );
+ n /= 100;
+ aRange.Min() -= n;
+ aRange.Max() += n;
+ }
+
+ if ( ( nLastInvalid == pPortion->GetLines().Count()-1 ) && ( !aStatus.IsOutliner() ) )
+ aRange.Max() += GetYValue( rULSpace.GetLower() );
+ }
+ return aRange;
+}
+
+EditPaM ImpEditEngine::GetPaM( ParaPortion* pPortion, Point aDocPos, BOOL bSmart )
+{
+ DBG_ASSERT( pPortion->IsVisible(), "Wozu GetPaM() bei einem unsichtbaren Absatz?" );
+ DBG_ASSERT( IsFormatted(), "GetPaM: Nicht formatiert" );
+
+ USHORT nCurIndex = 0;
+ EditPaM aPaM;
+ aPaM.SetNode( pPortion->GetNode() );
+
+ const SvxLineSpacingItem& rLSItem = (const SvxLineSpacingItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
+ USHORT nSBL = ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_FIX )
+ ? GetYValue( rLSItem.GetInterLineSpace() ) : 0;
+
+ long nY = pPortion->GetFirstLineOffset();
+
+ DBG_ASSERT( pPortion->GetLines().Count(), "Leere ParaPortion in GetPaM!" );
+
+ EditLine* pLine = 0;
+ for ( USHORT nLine = 0; nLine < pPortion->GetLines().Count(); nLine++ )
+ {
+ EditLine* pTmpLine = pPortion->GetLines().GetObject( nLine );
+ nY += pTmpLine->GetHeight();
+ if ( !aStatus.IsOutliner() )
+ nY += nSBL;
+ if ( nY > aDocPos.Y() ) // das war 'se
+ {
+ pLine = pTmpLine;
+ break; // richtige Y-Position intressiert nicht
+ }
+
+ nCurIndex = nCurIndex + pTmpLine->GetLen();
+ }
+
+ if ( !pLine ) // darf nur im Bereich von SA passieren!
+ {
+ #ifdef DBG_UTIL
+ const SvxULSpaceItem& rULSpace =(const SvxULSpaceItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE );
+ DBG_ASSERT( nY+GetYValue( rULSpace.GetLower() ) >= aDocPos.Y() , "Index in keiner Zeile, GetPaM ?" );
+ #endif
+ aPaM.SetIndex( pPortion->GetNode()->Len() );
+ return aPaM;
+ }
+
+ // Wenn Zeile gefunden, nur noch X-Position => Index
+ nCurIndex = GetChar( pPortion, pLine, aDocPos.X(), bSmart );
+ aPaM.SetIndex( nCurIndex );
+
+ if ( nCurIndex && ( nCurIndex == pLine->GetEnd() ) &&
+ ( pLine != pPortion->GetLines().GetObject( pPortion->GetLines().Count()-1) ) )
+ {
+ aPaM = CursorLeft( aPaM, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL );
+ }
+
+ return aPaM;
+}
+
+USHORT ImpEditEngine::GetChar( ParaPortion* pParaPortion, EditLine* pLine, long nXPos, BOOL bSmart )
+{
+ DBG_ASSERT( pLine, "Keine Zeile erhalten: GetChar" );
+
+ USHORT nChar = 0xFFFF;
+ USHORT nCurIndex = pLine->GetStart();
+
+
+ // Search best matching portion with GetPortionXOffset()
+ for ( USHORT i = pLine->GetStartPortion(); i <= pLine->GetEndPortion(); i++ )
+ {
+ TextPortion* pPortion = pParaPortion->GetTextPortions().GetObject( i );
+ long nXLeft = GetPortionXOffset( pParaPortion, pLine, i );
+ long nXRight = nXLeft + pPortion->GetSize().Width();
+ if ( ( nXLeft <= nXPos ) && ( nXRight >= nXPos ) )
+ {
+ nChar = nCurIndex;
+
+ // Search within Portion...
+
+ // Don't search within special portions...
+ if ( pPortion->GetKind() != PORTIONKIND_TEXT )
+ {
+ // ...but check on which side
+ if ( bSmart )
+ {
+ long nLeftDiff = nXPos-nXLeft;
+ long nRightDiff = nXRight-nXPos;
+ if ( nRightDiff < nLeftDiff )
+ nChar++;
+ }
+ }
+ else
+ {
+ USHORT nMax = pPortion->GetLen();
+ USHORT nOffset = 0xFFFF;
+ USHORT nTmpCurIndex = nChar - pLine->GetStart();
+
+ long nXInPortion = nXPos - nXLeft;
+ if ( pPortion->IsRightToLeft() )
+ nXInPortion = nXRight - nXPos;
+
+ // Search in Array...
+ for ( USHORT x = 0; x < nMax; x++ )
+ {
+ long nTmpPosMax = pLine->GetCharPosArray().GetObject( nTmpCurIndex+x );
+ if ( nTmpPosMax > nXInPortion )
+ {
+ // pruefen, ob dieser oder der davor...
+ long nTmpPosMin = x ? pLine->GetCharPosArray().GetObject( nTmpCurIndex+x-1 ) : 0;
+ long nDiffLeft = nXInPortion - nTmpPosMin;
+ long nDiffRight = nTmpPosMax - nXInPortion;
+ DBG_ASSERT( nDiffLeft >= 0, "DiffLeft negativ" );
+ DBG_ASSERT( nDiffRight >= 0, "DiffRight negativ" );
+ nOffset = ( bSmart && ( nDiffRight < nDiffLeft ) ) ? x+1 : x;
+ // I18N: If there are character position with the length of 0,
+ // they belong to the same character, we can not use this position as an index.
+ // Skip all 0-positions, cheaper than using XBreakIterator:
+ if ( nOffset < nMax )
+ {
+ const long nX = pLine->GetCharPosArray().GetObject(nOffset);
+ while ( ( (nOffset+1) < nMax ) && ( pLine->GetCharPosArray().GetObject(nOffset+1) == nX ) )
+ nOffset++;
+ }
+ break;
+ }
+ }
+
+ // Bei Verwendung des CharPosArray duerfte es keine Ungenauigkeiten geben!
+ // Vielleicht bei Kerning ?
+ // 0xFFF passiert z.B. bei Outline-Font, wenn ganz hinten.
+ if ( nOffset == 0xFFFF )
+ nOffset = nMax;
+
+ DBG_ASSERT( nOffset <= nMax, "nOffset > nMax" );
+
+ nChar = nChar + nOffset;
+
+ // Check if index is within a cell:
+ if ( nChar && ( nChar < pParaPortion->GetNode()->Len() ) )
+ {
+ EditPaM aPaM( pParaPortion->GetNode(), nChar+1 );
+ USHORT nScriptType = GetScriptType( aPaM );
+ if ( nScriptType == i18n::ScriptType::COMPLEX )
+ {
+ uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
+ sal_Int32 nCount = 1;
+ lang::Locale aLocale = GetLocale( aPaM );
+ USHORT nRight = (USHORT)_xBI->nextCharacters( *pParaPortion->GetNode(), nChar, aLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount );
+ USHORT nLeft = (USHORT)_xBI->previousCharacters( *pParaPortion->GetNode(), nRight, aLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount );
+ if ( ( nLeft != nChar ) && ( nRight != nChar ) )
+ {
+ nChar = ( Abs( nRight - nChar ) < Abs( nLeft - nChar ) ) ? nRight : nLeft;
+ }
+ }
+ }
+ }
+ }
+
+ nCurIndex = nCurIndex + pPortion->GetLen();
+ }
+
+ if ( nChar == 0xFFFF )
+ {
+ nChar = ( nXPos <= pLine->GetStartPosX() ) ? pLine->GetStart() : pLine->GetEnd();
+ }
+
+ return nChar;
+}
+
+Range ImpEditEngine::GetLineXPosStartEnd( ParaPortion* pParaPortion, EditLine* pLine )
+{
+ Range aLineXPosStartEnd;
+
+ USHORT nPara = GetEditDoc().GetPos( pParaPortion->GetNode() );
+ if ( !IsRightToLeft( nPara ) )
+ {
+ aLineXPosStartEnd.Min() = pLine->GetStartPosX();
+ aLineXPosStartEnd.Max() = pLine->GetStartPosX() + pLine->GetTextWidth();
+ }
+ else
+ {
+ aLineXPosStartEnd.Min() = GetPaperSize().Width() - ( pLine->GetStartPosX() + pLine->GetTextWidth() );
+ aLineXPosStartEnd.Max() = GetPaperSize().Width() - pLine->GetStartPosX();
+ }
+
+
+ return aLineXPosStartEnd;
+}
+
+long ImpEditEngine::GetPortionXOffset( ParaPortion* pParaPortion, EditLine* pLine, USHORT nTextPortion )
+{
+ long nX = pLine->GetStartPosX();
+
+ for ( USHORT i = pLine->GetStartPortion(); i < nTextPortion; i++ )
+ {
+ TextPortion* pPortion = pParaPortion->GetTextPortions().GetObject( i );
+ switch ( pPortion->GetKind() )
+ {
+ case PORTIONKIND_FIELD:
+ case PORTIONKIND_TEXT:
+ case PORTIONKIND_HYPHENATOR:
+ case PORTIONKIND_TAB:
+// case PORTIONKIND_EXTRASPACE:
+ {
+ nX += pPortion->GetSize().Width();
+ }
+ break;
+ }
+ }
+
+ USHORT nPara = GetEditDoc().GetPos( pParaPortion->GetNode() );
+ BOOL bR2LPara = IsRightToLeft( nPara );
+
+ TextPortion* pDestPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );
+ if ( pDestPortion->GetKind() != PORTIONKIND_TAB )
+ {
+ if ( !bR2LPara && pDestPortion->GetRightToLeft() )
+ {
+ // Portions behind must be added, visual before this portion
+ sal_uInt16 nTmpPortion = nTextPortion+1;
+ while ( nTmpPortion <= pLine->GetEndPortion() )
+ {
+ TextPortion* pNextTextPortion = pParaPortion->GetTextPortions().GetObject( nTmpPortion );
+ if ( pNextTextPortion->GetRightToLeft() && ( pNextTextPortion->GetKind() != PORTIONKIND_TAB ) )
+ nX += pNextTextPortion->GetSize().Width();
+ else
+ break;
+ nTmpPortion++;
+ }
+ // Portions before must be removed, visual behind this portion
+ nTmpPortion = nTextPortion;
+ while ( nTmpPortion > pLine->GetStartPortion() )
+ {
+ --nTmpPortion;
+ TextPortion* pPrevTextPortion = pParaPortion->GetTextPortions().GetObject( nTmpPortion );
+ if ( pPrevTextPortion->GetRightToLeft() && ( pPrevTextPortion->GetKind() != PORTIONKIND_TAB ) )
+ nX -= pPrevTextPortion->GetSize().Width();
+ else
+ break;
+ }
+ }
+ else if ( bR2LPara && !pDestPortion->IsRightToLeft() )
+ {
+ // Portions behind must be ermoved, visual behind this portion
+ sal_uInt16 nTmpPortion = nTextPortion+1;
+ while ( nTmpPortion <= pLine->GetEndPortion() )
+ {
+ TextPortion* pNextTextPortion = pParaPortion->GetTextPortions().GetObject( nTmpPortion );
+ if ( !pNextTextPortion->IsRightToLeft() && ( pNextTextPortion->GetKind() != PORTIONKIND_TAB ) )
+ nX += pNextTextPortion->GetSize().Width();
+ else
+ break;
+ nTmpPortion++;
+ }
+ // Portions before must be added, visual before this portion
+ nTmpPortion = nTextPortion;
+ while ( nTmpPortion > pLine->GetStartPortion() )
+ {
+ --nTmpPortion;
+ TextPortion* pPrevTextPortion = pParaPortion->GetTextPortions().GetObject( nTmpPortion );
+ if ( !pPrevTextPortion->IsRightToLeft() && ( pPrevTextPortion->GetKind() != PORTIONKIND_TAB ) )
+ nX -= pPrevTextPortion->GetSize().Width();
+ else
+ break;
+ }
+ }
+ }
+ if ( bR2LPara )
+ {
+ // Switch X postions...
+ DBG_ASSERT( GetTextRanger() || GetPaperSize().Width(), "GetPortionXOffset - paper size?!" );
+ DBG_ASSERT( GetTextRanger() || (nX <= GetPaperSize().Width()), "GetPortionXOffset - position out of paper size!" );
+ nX = GetPaperSize().Width() - nX;
+ nX -= pDestPortion->GetSize().Width();
+ }
+
+ return nX;
+}
+
+long ImpEditEngine::GetXPos( ParaPortion* pParaPortion, EditLine* pLine, USHORT nIndex, BOOL bPreferPortionStart )
+{
+ DBG_ASSERT( pLine, "Keine Zeile erhalten: GetXPos" );
+ DBG_ASSERT( ( nIndex >= pLine->GetStart() ) && ( nIndex <= pLine->GetEnd() ) , "GetXPos muss richtig gerufen werden!" );
+
+ BOOL bDoPreferPortionStart = bPreferPortionStart;
+ // Assure that the portion belongs to this line:
+ if ( nIndex == pLine->GetStart() )
+ bDoPreferPortionStart = TRUE;
+ else if ( nIndex == pLine->GetEnd() )
+ bDoPreferPortionStart = FALSE;
+
+ USHORT nTextPortionStart = 0;
+ USHORT nTextPortion = pParaPortion->GetTextPortions().FindPortion( nIndex, nTextPortionStart, bDoPreferPortionStart );
+
+ DBG_ASSERT( ( nTextPortion >= pLine->GetStartPortion() ) && ( nTextPortion <= pLine->GetEndPortion() ), "GetXPos: Portion not in current line! " );
+
+ TextPortion* pPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );
+
+ long nX = GetPortionXOffset( pParaPortion, pLine, nTextPortion );
+
+ // calc text width, portion size may include CJK/CTL spacing...
+ // But the array migh not be init yet, if using text ranger this method is called within CreateLines()...
+ long nPortionTextWidth = pPortion->GetSize().Width();
+ if ( ( pPortion->GetKind() == PORTIONKIND_TEXT ) && pPortion->GetLen() && !GetTextRanger() )
+ nPortionTextWidth = pLine->GetCharPosArray().GetObject( nTextPortionStart + pPortion->GetLen() - 1 - pLine->GetStart() );
+
+ if ( nTextPortionStart != nIndex )
+ {
+ // Search within portion...
+ if ( nIndex == ( nTextPortionStart + pPortion->GetLen() ) )
+ {
+ // End of Portion
+ if ( pPortion->GetKind() == PORTIONKIND_TAB )
+ {
+ if ( (nTextPortion+1) < pParaPortion->GetTextPortions().Count() )
+ {
+ TextPortion* pNextPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion+1 );
+ if ( pNextPortion->GetKind() != PORTIONKIND_TAB )
+ {
+ // DBG_ASSERT( !bPreferPortionStart, "GetXPos - How can we this tab portion here???" );
+ // #109879# We loop if nIndex == pLine->GetEnd, because bPreferPortionStart will be reset
+ if ( !bPreferPortionStart )
+ nX = GetXPos( pParaPortion, pLine, nIndex, TRUE );
+ else if ( !IsRightToLeft( GetEditDoc().GetPos( pParaPortion->GetNode() ) ) )
+ nX += nPortionTextWidth;
+ }
+ }
+ else if ( !IsRightToLeft( GetEditDoc().GetPos( pParaPortion->GetNode() ) ) )
+ {
+ nX += nPortionTextWidth;
+ }
+ }
+ else if ( !pPortion->IsRightToLeft() )
+ {
+ nX += nPortionTextWidth;
+ }
+ }
+ else if ( pPortion->GetKind() == PORTIONKIND_TEXT )
+ {
+ DBG_ASSERT( nIndex != pLine->GetStart(), "Strange behavior in new GetXPos()" );
+ DBG_ASSERT( pLine && pLine->GetCharPosArray().Count(), "svx::ImpEditEngine::GetXPos(), portion in an empty line?" );
+
+ if( pLine->GetCharPosArray().Count() )
+ {
+ USHORT nPos = nIndex - 1 - pLine->GetStart();
+ if( nPos >= pLine->GetCharPosArray().Count() )
+ {
+ nPos = pLine->GetCharPosArray().Count()-1;
+ DBG_ERROR("svx::ImpEditEngine::GetXPos(), index out of range!");
+ }
+
+ long nPosInPortion = pLine->GetCharPosArray().GetObject( nPos );
+
+ if ( !pPortion->IsRightToLeft() )
+ {
+ nX += nPosInPortion;
+ }
+ else
+ {
+ nX += nPortionTextWidth - nPosInPortion;
+ }
+
+ if ( pPortion->GetExtraInfos() && pPortion->GetExtraInfos()->bCompressed )
+ {
+ nX += pPortion->GetExtraInfos()->nPortionOffsetX;
+ if ( pPortion->GetExtraInfos()->nAsianCompressionTypes & CHAR_PUNCTUATIONRIGHT )
+ {
+ BYTE nType = GetCharTypeForCompression( pParaPortion->GetNode()->GetChar( nIndex ) );
+ if ( nType == CHAR_PUNCTUATIONRIGHT )
+ {
+ USHORT n = nIndex - nTextPortionStart;
+ const sal_Int32* pDXArray = pLine->GetCharPosArray().GetData()+( nTextPortionStart-pLine->GetStart() );
+ sal_Int32 nCharWidth = ( ( (n+1) < pPortion->GetLen() ) ? pDXArray[n] : pPortion->GetSize().Width() )
+ - ( n ? pDXArray[n-1] : 0 );
+ if ( (n+1) < pPortion->GetLen() )
+ {
+ // smaller, when char behind is CHAR_PUNCTUATIONRIGHT also
+ nType = GetCharTypeForCompression( pParaPortion->GetNode()->GetChar( nIndex+1 ) );
+ if ( nType == CHAR_PUNCTUATIONRIGHT )
+ {
+ sal_Int32 nNextCharWidth = ( ( (n+2) < pPortion->GetLen() ) ? pDXArray[n+1] : pPortion->GetSize().Width() )
+ - pDXArray[n];
+ sal_Int32 nCompressed = nNextCharWidth/2;
+ nCompressed *= pPortion->GetExtraInfos()->nMaxCompression100thPercent;
+ nCompressed /= 10000;
+ nCharWidth += nCompressed;
+ }
+ }
+ else
+ {
+ nCharWidth *= 2; // last char pos to portion end is only compressed size
+ }
+ nX += nCharWidth/2; // 50% compression
+ }
+ }
+ }
+ }
+ }
+ }
+ else // if ( nIndex == pLine->GetStart() )
+ {
+ if ( pPortion->IsRightToLeft() )
+ {
+ nX += nPortionTextWidth;
+ }
+ }
+
+ return nX;
+}
+
+void ImpEditEngine::CalcHeight( ParaPortion* pPortion )
+{
+ pPortion->nHeight = 0;
+ pPortion->nFirstLineOffset = 0;
+
+ if ( pPortion->IsVisible() )
+ {
+ DBG_ASSERT( pPortion->GetLines().Count(), "Absatz ohne Zeilen in ParaPortion::CalcHeight" );
+ for ( USHORT nLine = 0; nLine < pPortion->GetLines().Count(); nLine++ )
+ pPortion->nHeight += pPortion->GetLines().GetObject( nLine )->GetHeight();
+
+ if ( !aStatus.IsOutliner() )
+ {
+ const SvxULSpaceItem& rULItem = (const SvxULSpaceItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE );
+ const SvxLineSpacingItem& rLSItem = (const SvxLineSpacingItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
+ USHORT nSBL = ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_FIX ) ? GetYValue( rLSItem.GetInterLineSpace() ) : 0;
+
+ if ( nSBL )
+ {
+ if ( pPortion->GetLines().Count() > 1 )
+ pPortion->nHeight += ( pPortion->GetLines().Count() - 1 ) * nSBL;
+ if ( aStatus.ULSpaceSummation() )
+ pPortion->nHeight += nSBL;
+ }
+
+ USHORT nPortion = GetParaPortions().GetPos( pPortion );
+ if ( nPortion || aStatus.ULSpaceFirstParagraph() )
+ {
+ USHORT nUpper = GetYValue( rULItem.GetUpper() );
+ pPortion->nHeight += nUpper;
+ pPortion->nFirstLineOffset = nUpper;
+ }
+
+ if ( ( nPortion != (GetParaPortions().Count()-1) ) )
+ {
+ pPortion->nHeight += GetYValue( rULItem.GetLower() ); // nicht in letzter
+ }
+
+
+ if ( nPortion && !aStatus.ULSpaceSummation() )
+ {
+ ParaPortion* pPrev = GetParaPortions().SaveGetObject( nPortion-1 );
+ const SvxULSpaceItem& rPrevULItem = (const SvxULSpaceItem&)pPrev->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE );
+ const SvxLineSpacingItem& rPrevLSItem = (const SvxLineSpacingItem&)pPrev->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
+
+ // Verhalten WinWord6/Writer3:
+ // Bei einem proportionalen Zeilenabstand wird auch der Absatzabstand
+ // manipuliert.
+ // Nur Writer3: Nicht aufaddieren, sondern Mindestabstand.
+
+ // Pruefen, ob Abstand durch LineSpacing > Upper:
+ USHORT nExtraSpace = GetYValue( lcl_CalcExtraSpace( pPortion, rLSItem ) );
+ if ( nExtraSpace > pPortion->nFirstLineOffset )
+ {
+ // Absatz wird 'groesser':
+ pPortion->nHeight += ( nExtraSpace - pPortion->nFirstLineOffset );
+ pPortion->nFirstLineOffset = nExtraSpace;
+ }
+
+ // nFirstLineOffset jetzt f(pNode) => jetzt f(pNode, pPrev) ermitteln:
+ USHORT nPrevLower = GetYValue( rPrevULItem.GetLower() );
+
+ // Dieser PrevLower steckt noch in der Hoehe der PrevPortion...
+ if ( nPrevLower > pPortion->nFirstLineOffset )
+ {
+ // Absatz wird 'kleiner':
+ pPortion->nHeight -= pPortion->nFirstLineOffset;
+ pPortion->nFirstLineOffset = 0;
+ }
+ else if ( nPrevLower )
+ {
+ // Absatz wird 'etwas kleiner':
+ pPortion->nHeight -= nPrevLower;
+ pPortion->nFirstLineOffset =
+ pPortion->nFirstLineOffset - nPrevLower;
+ }
+
+ // Finde ich zwar nicht so gut, aber Writer3-Feature:
+ // Pruefen, ob Abstand durch LineSpacing > Lower:
+ // Dieser Wert steckt nicht in der Hoehe der PrevPortion.
+ if ( !pPrev->IsInvalid() )
+ {
+ nExtraSpace = GetYValue( lcl_CalcExtraSpace( pPrev, rPrevLSItem ) );
+ if ( nExtraSpace > nPrevLower )
+ {
+ USHORT nMoreLower = nExtraSpace - nPrevLower;
+ // Absatz wird 'groesser', 'waechst' nach unten:
+ if ( nMoreLower > pPortion->nFirstLineOffset )
+ {
+ pPortion->nHeight += ( nMoreLower - pPortion->nFirstLineOffset );
+ pPortion->nFirstLineOffset = nMoreLower;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+Rectangle ImpEditEngine::GetEditCursor( ParaPortion* pPortion, USHORT nIndex, USHORT nFlags )
+{
+ DBG_ASSERT( pPortion->IsVisible(), "Wozu GetEditCursor() bei einem unsichtbaren Absatz?" );
+ DBG_ASSERT( IsFormatted() || GetTextRanger(), "GetEditCursor: Nicht formatiert" );
+
+ /*
+ GETCRSR_ENDOFLINE: Wenn hinter dem letzten Zeichen einer umgebrochenen Zeile,
+ am Ende der Zeile bleiben, nicht am Anfang der naechsten.
+ Zweck: - END => wirklich hinter das letzte Zeichen
+ - Selektion....
+ */
+
+ long nY = pPortion->GetFirstLineOffset();
+
+ const SvxLineSpacingItem& rLSItem = (const SvxLineSpacingItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
+ USHORT nSBL = ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_FIX )
+ ? GetYValue( rLSItem.GetInterLineSpace() ) : 0;
+
+ USHORT nCurIndex = 0;
+ DBG_ASSERT( pPortion->GetLines().Count(), "Leere ParaPortion in GetEditCursor!" );
+ EditLine* pLine = 0;
+ BOOL bEOL = ( nFlags & GETCRSR_ENDOFLINE ) ? TRUE : FALSE;
+ for ( USHORT nLine = 0; nLine < pPortion->GetLines().Count(); nLine++ )
+ {
+ EditLine* pTmpLine = pPortion->GetLines().GetObject( nLine );
+ if ( ( pTmpLine->GetStart() == nIndex ) || ( pTmpLine->IsIn( nIndex, bEOL ) ) )
+ {
+ pLine = pTmpLine;
+ break;
+ }
+
+ nCurIndex = nCurIndex + pTmpLine->GetLen();
+ nY += pTmpLine->GetHeight();
+ if ( !aStatus.IsOutliner() )
+ nY += nSBL;
+ }
+ if ( !pLine )
+ {
+ // Cursor am Ende des Absatzes.
+ DBG_ASSERT( nIndex == nCurIndex, "Index voll daneben in GetEditCursor!" );
+
+ pLine = pPortion->GetLines().GetObject( pPortion->GetLines().Count()-1 );
+ nY -= pLine->GetHeight();
+ if ( !aStatus.IsOutliner() )
+ nY -= nSBL;
+ nCurIndex = nCurIndex - pLine->GetLen();
+ }
+
+ Rectangle aEditCursor;
+
+ aEditCursor.Top() = nY;
+ nY += pLine->GetHeight();
+ aEditCursor.Bottom() = nY-1;
+
+ // innerhalb der Zeile suchen...
+ long nX;
+
+ if ( ( nIndex == pLine->GetStart() ) && ( nFlags & GETCRSR_STARTOFLINE ) )
+ {
+ Range aXRange = GetLineXPosStartEnd( pPortion, pLine );
+ nX = !IsRightToLeft( GetEditDoc().GetPos( pPortion->GetNode() ) ) ? aXRange.Min() : aXRange.Max();
+ }
+ else if ( ( nIndex == pLine->GetEnd() ) && ( nFlags & GETCRSR_ENDOFLINE ) )
+ {
+ Range aXRange = GetLineXPosStartEnd( pPortion, pLine );
+ nX = !IsRightToLeft( GetEditDoc().GetPos( pPortion->GetNode() ) ) ? aXRange.Max() : aXRange.Min();
+ }
+ else
+ {
+ nX = GetXPos( pPortion, pLine, nIndex, ( nFlags & GETCRSR_PREFERPORTIONSTART ) ? TRUE : FALSE );
+ }
+
+ aEditCursor.Left() = aEditCursor.Right() = nX;
+
+ if ( nFlags & GETCRSR_TXTONLY )
+ aEditCursor.Top() = aEditCursor.Bottom() - pLine->GetTxtHeight() + 1;
+ else
+ aEditCursor.Top() = aEditCursor.Bottom() - Min( pLine->GetTxtHeight(), pLine->GetHeight() ) + 1;
+
+ return aEditCursor;
+}
+
+void ImpEditEngine::SetValidPaperSize( const Size& rNewSz )
+{
+ aPaperSize = rNewSz;
+
+ long nMinWidth = aStatus.AutoPageWidth() ? aMinAutoPaperSize.Width() : 0;
+ long nMaxWidth = aStatus.AutoPageWidth() ? aMaxAutoPaperSize.Width() : 0x7FFFFFFF;
+ long nMinHeight = aStatus.AutoPageHeight() ? aMinAutoPaperSize.Height() : 0;
+ long nMaxHeight = aStatus.AutoPageHeight() ? aMaxAutoPaperSize.Height() : 0x7FFFFFFF;
+
+ // Minimale/Maximale Breite:
+ if ( aPaperSize.Width() < nMinWidth )
+ aPaperSize.Width() = nMinWidth;
+ else if ( aPaperSize.Width() > nMaxWidth )
+ aPaperSize.Width() = nMaxWidth;
+
+ // Minimale/Maximale Hoehe:
+ if ( aPaperSize.Height() < nMinHeight )
+ aPaperSize.Height() = nMinHeight;
+ else if ( aPaperSize.Height() > nMaxHeight )
+ aPaperSize.Height() = nMaxHeight;
+}
+
+void ImpEditEngine::IndentBlock( EditView* pEditView, BOOL bRight )
+{
+ ESelection aESel( CreateESel( pEditView->pImpEditView->GetEditSelection() ) );
+ aESel.Adjust();
+
+ // Nur wenn mehrere selektierte Absaetze...
+ if ( aESel.nEndPara > aESel.nStartPara )
+ {
+ ESelection aNewSel = aESel;
+ aNewSel.nStartPos = 0;
+ aNewSel.nEndPos = 0xFFFF;
+
+ if ( aESel.nEndPos == 0 )
+ {
+ aESel.nEndPara--; // dann diesen Absatz nicht...
+ aNewSel.nEndPos = 0;
+ }
+
+ pEditView->pImpEditView->DrawSelection();
+ pEditView->pImpEditView->SetEditSelection(
+ pEditView->pImpEditView->GetEditSelection().Max() );
+ UndoActionStart( bRight ? EDITUNDO_INDENTBLOCK : EDITUNDO_UNINDENTBLOCK );
+
+ for ( USHORT nPara = aESel.nStartPara; nPara <= aESel.nEndPara; nPara++ )
+ {
+ ContentNode* pNode = GetEditDoc().GetObject( nPara );
+ if ( bRight )
+ {
+ // Tabs hinzufuegen
+ EditPaM aPaM( pNode, 0 );
+ InsertTab( aPaM );
+ }
+ else
+ {
+ // Tabs entfernen
+ EditCharAttrib* pFeature = pNode->GetCharAttribs().FindFeature( 0 );
+ if ( pFeature && ( pFeature->GetStart() == 0 ) &&
+ ( pFeature->GetItem()->Which() == EE_FEATURE_TAB ) )
+ {
+ EditPaM aStartPaM( pNode, 0 );
+ EditPaM aEndPaM( pNode, 1 );
+ ImpDeleteSelection( EditSelection( aStartPaM, aEndPaM ) );
+ }
+ }
+ }
+
+ UndoActionEnd( bRight ? EDITUNDO_INDENTBLOCK : EDITUNDO_UNINDENTBLOCK );
+ UpdateSelections();
+ FormatAndUpdate( pEditView );
+
+ ContentNode* pLastNode = GetEditDoc().GetObject( aNewSel.nEndPara );
+ if ( pLastNode->Len() < aNewSel.nEndPos )
+ aNewSel.nEndPos = pLastNode->Len();
+ pEditView->pImpEditView->SetEditSelection( CreateSel( aNewSel ) );
+ pEditView->pImpEditView->DrawSelection();
+ pEditView->pImpEditView->ShowCursor( FALSE, TRUE );
+ }
+}
+
+vos::ORef<SvxForbiddenCharactersTable> ImpEditEngine::GetForbiddenCharsTable( BOOL bGetInternal ) const
+{
+ vos::ORef<SvxForbiddenCharactersTable> xF = xForbiddenCharsTable;
+ if ( !xF.isValid() && bGetInternal )
+ xF = EE_DLL()->GetGlobalData()->GetForbiddenCharsTable();
+ return xF;
+}
+
+void ImpEditEngine::SetForbiddenCharsTable( vos::ORef<SvxForbiddenCharactersTable> xForbiddenChars )
+{
+ EE_DLL()->GetGlobalData()->SetForbiddenCharsTable( xForbiddenChars );
+}
+
+svtools::ColorConfig& ImpEditEngine::GetColorConfig()
+{
+ if ( !pColorConfig )
+ pColorConfig = new svtools::ColorConfig;
+
+ return *pColorConfig;
+}
+
+BOOL ImpEditEngine::IsVisualCursorTravelingEnabled()
+{
+ BOOL bVisualCursorTravaling = FALSE;
+
+ if( !pCTLOptions )
+ pCTLOptions = new SvtCTLOptions;
+
+ if ( pCTLOptions->IsCTLFontEnabled() && ( pCTLOptions->GetCTLCursorMovement() == SvtCTLOptions::MOVEMENT_VISUAL ) )
+ {
+ bVisualCursorTravaling = TRUE;
+ }
+
+ return bVisualCursorTravaling;
+
+}
+
+BOOL ImpEditEngine::DoVisualCursorTraveling( const ContentNode* )
+{
+ // Don't check if it's necessary, because we also need it when leaving the paragraph
+ return IsVisualCursorTravelingEnabled();
+/*
+ BOOL bDoVisualCursorTraveling = FALSE;
+
+ if ( IsVisualCursorTravelingEnabled() && pNode->Len() )
+ {
+ // Only necessary when RTL text in LTR para or LTR text in RTL para
+ bDoVisualCursorTraveling = HasDifferentRTLLevels( pNode );
+ }
+
+ return bDoVisualCursorTraveling;
+*/
+}
+
+
+void ImpEditEngine::CallNotify( EENotify& rNotify )
+{
+ if ( !nBlockNotifications )
+ {
+ GetNotifyHdl().Call( &rNotify );
+ }
+ else
+ {
+ EENotify* pNewNotify = new EENotify( rNotify );
+ aNotifyCache.Insert( pNewNotify, aNotifyCache.Count() );
+ }
+}
+
+void ImpEditEngine::EnterBlockNotifications()
+{
+ if( !nBlockNotifications )
+ {
+ // #109864# Send out START notification immediately, to allow
+ // external, non-queued events to be captured as well from
+ // client side
+ EENotify aNotify( EE_NOTIFY_BLOCKNOTIFICATION_START );
+ aNotify.pEditEngine = GetEditEnginePtr();
+ GetNotifyHdl().Call( &aNotify );
+ }
+
+ nBlockNotifications++;
+}
+
+void ImpEditEngine::LeaveBlockNotifications()
+{
+ DBG_ASSERT( nBlockNotifications, "LeaveBlockNotifications - Why?" );
+
+ nBlockNotifications--;
+ if ( !nBlockNotifications )
+ {
+ // Call blocked notify events...
+ while ( aNotifyCache.Count() )
+ {
+ EENotify* pNotify = aNotifyCache[0];
+ // Remove from list before calling, maybe we enter LeaveBlockNotifications while calling the handler...
+ aNotifyCache.Remove( 0 );
+ GetNotifyHdl().Call( pNotify );
+ delete pNotify;
+ }
+
+ EENotify aNotify( EE_NOTIFY_BLOCKNOTIFICATION_END );
+ aNotify.pEditEngine = GetEditEnginePtr();
+ GetNotifyHdl().Call( &aNotify );
+ }
+}
+
+IMPL_LINK( ImpEditEngine, DocModified, void*, EMPTYARG )
+{
+ aModifyHdl.Call( NULL /*GetEditEnginePtr()*/ ); // NULL, because also used for Outliner
+ return 0;
+}
diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx
new file mode 100644
index 000000000000..dbc6767d1f91
--- /dev/null
+++ b/editeng/source/editeng/impedit3.cxx
@@ -0,0 +1,4677 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 <vcl/metaact.hxx>
+#include <vcl/gdimtf.hxx>
+
+#define _SVSTDARR_USHORTS
+#include <svl/svstdarr.hxx>
+
+#include <vcl/wrkwin.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/flditem.hxx>
+#include <impedit.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/editview.hxx>
+#include <editeng/txtrange.hxx>
+#include <editeng/cscoitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/scriptspaceitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/numitem.hxx>
+
+#include <svtools/colorcfg.hxx>
+#include <svl/ctloptions.hxx>
+
+#include <editeng/forbiddencharacterstable.hxx>
+
+#include <unotools/localedatawrapper.hxx>
+
+#include <editeng/unolingu.hxx>
+
+#include <math.h>
+#include <vcl/svapp.hxx>
+#include <vcl/metric.hxx>
+#include <com/sun/star/i18n/ScriptType.hpp>
+#include <com/sun/star/text/CharacterCompressionType.hpp>
+#include <vcl/pdfextoutdevdata.hxx>
+#include <i18npool/mslangid.hxx>
+
+#include <comphelper/processfactory.hxx>
+
+using ::rtl::OUString;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::linguistic2;
+
+SV_DECL_VARARR_SORT( SortedPositions, sal_uInt32, 16, 8 )
+SV_IMPL_VARARR_SORT( SortedPositions, sal_uInt32 );
+
+#define CH_HYPH '-'
+
+#define RESDIFF 10
+
+#define WRONG_SHOW_MIN 5
+#define WRONG_SHOW_SMALL 11
+#define WRONG_SHOW_MEDIUM 15
+
+struct TabInfo
+{
+ BOOL bValid;
+
+ SvxTabStop aTabStop;
+ xub_StrLen nCharPos;
+ USHORT nTabPortion;
+ long nStartPosX;
+ long nTabPos;
+
+ TabInfo() { bValid = FALSE; }
+};
+
+Point Rotate( const Point& rPoint, short nOrientation, const Point& rOrigin )
+{
+ double nRealOrientation = nOrientation*F_PI1800;
+ double nCos = cos( nRealOrientation );
+ double nSin = sin( nRealOrientation );
+
+ Point aRotatedPos;
+ Point aTranslatedPos( rPoint );
+
+ // Translation
+ aTranslatedPos -= rOrigin;
+
+ // Rotation...
+ aRotatedPos.X() = (long) ( nCos*aTranslatedPos.X() + nSin*aTranslatedPos.Y() );
+ aRotatedPos.Y() = (long) - ( nSin*aTranslatedPos.X() - nCos*aTranslatedPos.Y() );
+ aTranslatedPos = aRotatedPos;
+
+ // Translation...
+ aTranslatedPos += rOrigin;
+ return aTranslatedPos;
+}
+
+BYTE GetCharTypeForCompression( xub_Unicode cChar )
+{
+ switch ( cChar )
+ {
+ case 0x3008: case 0x300A: case 0x300C: case 0x300E:
+ case 0x3010: case 0x3014: case 0x3016: case 0x3018:
+ case 0x301A: case 0x301D:
+ {
+ return CHAR_PUNCTUATIONRIGHT;
+ }
+ case 0x3001: case 0x3002: case 0x3009: case 0x300B:
+ case 0x300D: case 0x300F: case 0x3011: case 0x3015:
+ case 0x3017: case 0x3019: case 0x301B: case 0x301E:
+ case 0x301F:
+ {
+ return CHAR_PUNCTUATIONLEFT;
+ }
+ default:
+ {
+ return ( ( 0x3040 <= cChar ) && ( 0x3100 > cChar ) ) ? CHAR_KANA : CHAR_NORMAL;
+ }
+ }
+}
+
+void lcl_DrawRedLines(
+ OutputDevice* pOutDev,
+ long nFontHeight,
+ const Point& rPnt,
+ sal_uInt16 nIndex,
+ sal_uInt16 nMaxEnd,
+ const sal_Int32* pDXArray,
+ WrongList* pWrongs,
+ short nOrientation,
+ const Point& rOrigin,
+ BOOL bVertical,
+ BOOL bIsRightToLeft )
+{
+#ifndef SVX_LIGHT
+ // Aber nur, wenn Font nicht zu klein...
+ long nHght = pOutDev->LogicToPixel( Size( 0, nFontHeight ) ).Height();
+ if( WRONG_SHOW_MIN < nHght )
+ {
+ sal_uInt16 nStyle;
+ if( WRONG_SHOW_MEDIUM < nHght )
+ nStyle = WAVE_NORMAL;
+ else if( WRONG_SHOW_SMALL < nHght )
+ nStyle = WAVE_SMALL;
+ else
+ nStyle = WAVE_FLAT;
+
+ sal_uInt16 nEnd, nStart = nIndex;
+ sal_Bool bWrong = pWrongs->NextWrong( nStart, nEnd );
+ while ( bWrong )
+ {
+ if ( nStart >= nMaxEnd )
+ break;
+
+ if ( nStart < nIndex ) // Wurde korrigiert
+ nStart = nIndex;
+ if ( nEnd > nMaxEnd )
+ nEnd = nMaxEnd;
+ Point aPnt1( rPnt );
+ if ( bVertical && ( nStyle != WAVE_FLAT ) )
+ {
+ // VCL doesn't know that the text is vertical, and is manipulating
+ // the positions a little bit in y direction...
+ long nOnePixel = pOutDev->PixelToLogic( Size( 0, 1 ) ).Height();
+ long nCorrect = ( nStyle == WAVE_NORMAL ) ? 2*nOnePixel : nOnePixel;
+ aPnt1.Y() -= nCorrect;
+ aPnt1.X() -= nCorrect;
+ }
+ if ( nStart > nIndex )
+ {
+ if ( !bVertical )
+ {
+ // since for RTL portions rPnt is on the visual right end of the portion
+ // (i.e. at the start of the first RTL char) we need to subtract the offset
+ // for RTL portions...
+ aPnt1.X() += (bIsRightToLeft ? -1 : 1) * pDXArray[ nStart - nIndex - 1 ];
+ }
+ else
+ aPnt1.Y() += pDXArray[ nStart - nIndex - 1 ];
+ }
+ Point aPnt2( rPnt );
+ DBG_ASSERT( nEnd > nIndex, "RedLine: aPnt2?" );
+ if ( !bVertical )
+ {
+ // since for RTL portions rPnt is on the visual right end of the portion
+ // (i.e. at the start of the first RTL char) we need to subtract the offset
+ // for RTL portions...
+ aPnt2.X() += (bIsRightToLeft ? -1 : 1) * pDXArray[ nEnd - nIndex - 1 ];
+ }
+ else
+ aPnt2.Y() += pDXArray[ nEnd - nIndex - 1 ];
+ if ( nOrientation )
+ {
+ aPnt1 = Rotate( aPnt1, nOrientation, rOrigin );
+ aPnt2 = Rotate( aPnt2, nOrientation, rOrigin );
+ }
+
+ pOutDev->DrawWaveLine( aPnt1, aPnt2, nStyle );
+
+ nStart = nEnd+1;
+ if ( nEnd < nMaxEnd )
+ bWrong = pWrongs->NextWrong( nStart, nEnd );
+ else
+ bWrong = sal_False;
+ }
+ }
+#endif // !SVX_LIGHT
+}
+
+Point lcl_ImplCalcRotatedPos( Point rPos, Point rOrigin, double nSin, double nCos )
+{
+ Point aRotatedPos;
+ // Translation...
+ Point aTranslatedPos( rPos);
+ aTranslatedPos -= rOrigin;
+
+ aRotatedPos.X() = (long) ( nCos*aTranslatedPos.X() + nSin*aTranslatedPos.Y() );
+ aRotatedPos.Y() = (long) - ( nSin*aTranslatedPos.X() - nCos*aTranslatedPos.Y() );
+ aTranslatedPos = aRotatedPos;
+ // Translation...
+ aTranslatedPos += rOrigin;
+
+ return aTranslatedPos;
+}
+
+sal_Bool lcl_IsLigature( xub_Unicode cCh, xub_Unicode cNextCh ) // For Kashidas from sw/source/core/text/porlay.txt
+{
+ // Lam + Alef
+ return ( 0x644 == cCh && 0x627 == cNextCh ) ||
+ // Beh + Reh
+ ( 0x628 == cCh && 0x631 == cNextCh );
+}
+
+sal_Bool lcl_ConnectToPrev( xub_Unicode cCh, xub_Unicode cPrevCh ) // For Kashidas from sw/source/core/text/porlay.txt
+{
+ // Alef, Dal, Thal, Reh, Zain, and Waw do not connect to the left
+ sal_Bool bRet = 0x627 != cPrevCh && 0x62F != cPrevCh && 0x630 != cPrevCh &&
+ 0x631 != cPrevCh && 0x632 != cPrevCh && 0x648 != cPrevCh;
+
+ // check for ligatures cPrevChar + cChar
+ if ( bRet )
+ bRet = ! lcl_IsLigature( cPrevCh, cCh );
+
+ return bRet;
+}
+
+
+// ----------------------------------------------------------------------
+// class ImpEditEngine
+// ----------------------------------------------------------------------
+void ImpEditEngine::UpdateViews( EditView* pCurView )
+{
+ if ( !GetUpdateMode() || IsFormatting() || aInvalidRec.IsEmpty() )
+ return;
+
+ DBG_ASSERT( IsFormatted(), "UpdateViews: Doc nicht formatiert!" );
+
+ for ( sal_uInt16 nView = 0; nView < aEditViews.Count(); nView++ )
+ {
+ EditView* pView = aEditViews[nView];
+ DBG_CHKOBJ( pView, EditView, 0 );
+ pView->HideCursor();
+
+ Rectangle aClipRec( aInvalidRec );
+ Rectangle aVisArea( pView->GetVisArea() );
+ aClipRec.Intersection( aVisArea );
+
+ if ( !aClipRec.IsEmpty() )
+ {
+ // in Fensterkoordinaten umwandeln....
+ aClipRec = pView->pImpEditView->GetWindowPos( aClipRec );
+
+ if ( ( pView == pCurView ) )
+ Paint( pView->pImpEditView, aClipRec, sal_True );
+ else
+ pView->GetWindow()->Invalidate( aClipRec );
+ }
+ }
+
+ if ( pCurView )
+ {
+ sal_Bool bGotoCursor = pCurView->pImpEditView->DoAutoScroll();
+ pCurView->ShowCursor( bGotoCursor );
+ }
+
+ aInvalidRec = Rectangle();
+ CallStatusHdl();
+}
+
+IMPL_LINK( ImpEditEngine, OnlineSpellHdl, Timer *, EMPTYARG )
+{
+ if ( !Application::AnyInput( INPUT_KEYBOARD ) && GetUpdateMode() && IsFormatted() )
+ DoOnlineSpelling();
+ else
+ aOnlineSpellTimer.Start();
+
+ return 0;
+}
+
+IMPL_LINK_INLINE_START( ImpEditEngine, IdleFormatHdl, Timer *, EMPTYARG )
+{
+ aIdleFormatter.ResetRestarts();
+
+ // #i97146# check if that view is still available
+ // else probably the idle format timer fired while we're already
+ // downing
+ EditView* pView = aIdleFormatter.GetView();
+ for( sal_uInt16 nView = 0; nView < aEditViews.Count(); nView++ )
+ {
+ if( aEditViews[nView] == pView )
+ {
+ FormatAndUpdate( pView );
+ break;
+ }
+ }
+ return 0;
+}
+IMPL_LINK_INLINE_END( ImpEditEngine, IdleFormatHdl, Timer *, EMPTYARG )
+
+void ImpEditEngine::CheckIdleFormatter()
+{
+ aIdleFormatter.ForceTimeout();
+ // Falls kein Idle, aber trotzdem nicht formatiert:
+ if ( !IsFormatted() )
+ FormatDoc();
+}
+
+void ImpEditEngine::FormatFullDoc()
+{
+ for ( sal_uInt16 nPortion = 0; nPortion < GetParaPortions().Count(); nPortion++ )
+ GetParaPortions()[nPortion]->MarkSelectionInvalid( 0, GetParaPortions()[nPortion]->GetNode()->Len() );
+ FormatDoc();
+}
+
+void ImpEditEngine::FormatDoc()
+{
+ if ( !GetUpdateMode() || IsFormatting() )
+ return;
+
+ EnterBlockNotifications();
+
+ bIsFormatting = sal_True;
+
+ // Dann kann ich auch den Spell-Timer starten...
+ if ( GetStatus().DoOnlineSpelling() )
+ StartOnlineSpellTimer();
+
+ long nY = 0;
+ sal_Bool bGrow = sal_False;
+
+ Font aOldFont( GetRefDevice()->GetFont() );
+
+ // Hier schon, damit nicht jedesmal in CreateLines...
+ sal_Bool bMapChanged = ImpCheckRefMapMode();
+
+ aInvalidRec = Rectangle(); // leermachen
+ for ( sal_uInt16 nPara = 0; nPara < GetParaPortions().Count(); nPara++ )
+ {
+ ParaPortion* pParaPortion = GetParaPortions().GetObject( nPara );
+ if ( pParaPortion->MustRepaint() || ( pParaPortion->IsInvalid() && pParaPortion->IsVisible() ) )
+ {
+ if ( pParaPortion->IsInvalid() )
+ {
+ sal_Bool bChangedByDerivedClass = GetEditEnginePtr()->FormattingParagraph( nPara );
+ if ( bChangedByDerivedClass )
+ {
+ pParaPortion->GetTextPortions().Reset();
+ pParaPortion->MarkSelectionInvalid( 0, pParaPortion->GetNode()->Len() );
+ }
+ }
+ // bei MustRepaint() sollte keine Formatierung noetig sein!
+ // 23.1.95: Evtl. ist sie durch eine andere Aktion aber doch
+ // ungueltig geworden!
+// if ( pParaPortion->MustRepaint() || CreateLines( nPara ) )
+ if ( ( pParaPortion->MustRepaint() && !pParaPortion->IsInvalid() )
+ || CreateLines( nPara, nY ) )
+ {
+ if ( !bGrow && GetTextRanger() )
+ {
+ // Bei einer Aenderung der Hoehe muss alles weiter unten
+ // neu formatiert werden...
+ for ( sal_uInt16 n = nPara+1; n < GetParaPortions().Count(); n++ )
+ {
+ ParaPortion* pPP = GetParaPortions().GetObject( n );
+ pPP->MarkSelectionInvalid( 0, pPP->GetNode()->Len() );
+ pPP->GetLines().Reset();
+ }
+ }
+ bGrow = sal_True;
+ if ( IsCallParaInsertedOrDeleted() )
+ GetEditEnginePtr()->ParagraphHeightChanged( nPara );
+ pParaPortion->SetMustRepaint( sal_False );
+ }
+
+ // InvalidRec nur einmal setzen...
+ if ( aInvalidRec.IsEmpty() )
+ {
+ // Bei Paperwidth 0 (AutoPageSize) bleibt es sonst Empty()...
+ long nWidth = Max( (long)1, ( !IsVertical() ? aPaperSize.Width() : aPaperSize.Height() ) );
+ Range aInvRange( GetInvalidYOffsets( pParaPortion ) );
+ aInvalidRec = Rectangle( Point( 0, nY+aInvRange.Min() ),
+ Size( nWidth, aInvRange.Len() ) );
+ }
+ else
+ {
+ aInvalidRec.Bottom() = nY + pParaPortion->GetHeight();
+ }
+ }
+ else if ( bGrow )
+ {
+ aInvalidRec.Bottom() = nY + pParaPortion->GetHeight();
+ }
+ nY += pParaPortion->GetHeight();
+ }
+
+ // Man kann auch durch UpdateMode An=>AUS=>AN in die Formatierung gelangen...
+ // Optimierung erst nach Vobis-Auslieferung aktivieren...
+// if ( !aInvalidRec.IsEmpty() )
+ {
+ sal_uInt32 nNewHeight = CalcTextHeight();
+ long nDiff = nNewHeight - nCurTextHeight;
+ if ( nDiff )
+ aStatus.GetStatusWord() |= !IsVertical() ? EE_STAT_TEXTHEIGHTCHANGED : EE_STAT_TEXTWIDTHCHANGED;
+ if ( nNewHeight < nCurTextHeight )
+ {
+ aInvalidRec.Bottom() = (long)Max( nNewHeight, nCurTextHeight );
+ if ( aInvalidRec.IsEmpty() )
+ {
+ aInvalidRec.Top() = 0;
+ // Left und Right werden nicht ausgewertet, aber wegen IsEmpty gesetzt.
+ aInvalidRec.Left() = 0;
+ aInvalidRec.Right() = !IsVertical() ? aPaperSize.Width() : aPaperSize.Height();
+ }
+ }
+
+ nCurTextHeight = nNewHeight;
+
+ if ( aStatus.AutoPageSize() )
+ CheckAutoPageSize();
+ else if ( nDiff )
+ {
+ for ( sal_uInt16 nView = 0; nView < aEditViews.Count(); nView++ )
+ {
+ EditView* pView = aEditViews[nView];
+ ImpEditView* pImpView = pView->pImpEditView;
+ if ( pImpView->DoAutoHeight() )
+ {
+ Size aSz( pImpView->GetOutputArea().GetWidth(), nCurTextHeight );
+ if ( aSz.Height() > aMaxAutoPaperSize.Height() )
+ aSz.Height() = aMaxAutoPaperSize.Height();
+ else if ( aSz.Height() < aMinAutoPaperSize.Height() )
+ aSz.Height() = aMinAutoPaperSize.Height();
+ pImpView->ResetOutputArea( Rectangle(
+ pImpView->GetOutputArea().TopLeft(), aSz ) );
+ }
+ }
+ }
+ }
+
+ if ( aStatus.DoRestoreFont() )
+ GetRefDevice()->SetFont( aOldFont );
+ bIsFormatting = sal_False;
+ bFormatted = sal_True;
+
+ if ( bMapChanged )
+ GetRefDevice()->Pop();
+
+ CallStatusHdl(); // Falls Modified...
+
+ LeaveBlockNotifications();
+}
+
+sal_Bool ImpEditEngine::ImpCheckRefMapMode()
+{
+ sal_Bool bChange = sal_False;
+
+ if ( aStatus.DoFormat100() )
+ {
+ MapMode aMapMode( GetRefDevice()->GetMapMode() );
+ if ( aMapMode.GetScaleX().GetNumerator() != aMapMode.GetScaleX().GetDenominator() )
+ bChange = sal_True;
+ else if ( aMapMode.GetScaleY().GetNumerator() != aMapMode.GetScaleY().GetDenominator() )
+ bChange = sal_True;
+
+ if ( bChange )
+ {
+ Fraction Scale1( 1, 1 );
+ aMapMode.SetScaleX( Scale1 );
+ aMapMode.SetScaleY( Scale1 );
+ GetRefDevice()->Push();
+ GetRefDevice()->SetMapMode( aMapMode );
+ }
+ }
+
+ return bChange;
+}
+
+void ImpEditEngine::CheckAutoPageSize()
+{
+ Size aPrevPaperSize( GetPaperSize() );
+ if ( GetStatus().AutoPageWidth() )
+ aPaperSize.Width() = (long) !IsVertical() ? CalcTextWidth( TRUE ) : GetTextHeight();
+ if ( GetStatus().AutoPageHeight() )
+ aPaperSize.Height() = (long) !IsVertical() ? GetTextHeight() : CalcTextWidth( TRUE );
+
+ SetValidPaperSize( aPaperSize ); //Min, Max beruecksichtigen
+
+ if ( aPaperSize != aPrevPaperSize )
+ {
+ if ( ( !IsVertical() && ( aPaperSize.Width() != aPrevPaperSize.Width() ) )
+ || ( IsVertical() && ( aPaperSize.Height() != aPrevPaperSize.Height() ) ) )
+ {
+ // Falls davor zentriert/rechts oder Tabs...
+ aStatus.GetStatusWord() |= !IsVertical() ? EE_STAT_TEXTWIDTHCHANGED : EE_STAT_TEXTHEIGHTCHANGED;
+ for ( sal_uInt16 nPara = 0; nPara < GetParaPortions().Count(); nPara++ )
+ {
+ // Es brauchen nur Absaetze neu formatiert werden,
+ // die nicht linksbuendig sind.
+ // Die Hoehe kann sich hier nicht mehr aendern.
+ ParaPortion* pParaPortion = GetParaPortions().GetObject( nPara );
+ ContentNode* pNode = pParaPortion->GetNode();
+ SvxAdjust eJustification = GetJustification( nPara );
+ if ( eJustification != SVX_ADJUST_LEFT )
+ {
+ pParaPortion->MarkSelectionInvalid( 0, pNode->Len() );
+ CreateLines( nPara, 0 ); // 0: Bei AutoPageSize kein TextRange!
+ }
+ }
+ }
+
+ Size aInvSize = aPaperSize;
+ if ( aPaperSize.Width() < aPrevPaperSize.Width() )
+ aInvSize.Width() = aPrevPaperSize.Width();
+ if ( aPaperSize.Height() < aPrevPaperSize.Height() )
+ aInvSize.Height() = aPrevPaperSize.Height();
+
+ Size aSz( aInvSize );
+ if ( IsVertical() )
+ {
+ aSz.Width() = aInvSize.Height();
+ aSz.Height() = aInvSize.Width();
+ }
+ aInvalidRec = Rectangle( Point(), aSz );
+
+
+ for ( sal_uInt16 nView = 0; nView < aEditViews.Count(); nView++ )
+ {
+ EditView* pView = aEditViews[nView];
+ pView->pImpEditView->RecalcOutputArea();
+ }
+ }
+}
+
+static sal_Int32 ImplCalculateFontIndependentLineSpacing( const sal_Int32 nFontHeight )
+{
+ return ( nFontHeight * 12 ) / 10; // + 20%
+}
+
+sal_Bool ImpEditEngine::CreateLines( USHORT nPara, sal_uInt32 nStartPosY )
+{
+ ParaPortion* pParaPortion = GetParaPortions().GetObject( nPara );
+
+ // sal_Bool: Aenderung der Hoehe des Absatzes Ja/Nein - sal_True/sal_False
+ DBG_ASSERT( pParaPortion->GetNode(), "Portion ohne Node in CreateLines" );
+ DBG_ASSERT( pParaPortion->IsVisible(), "Unsichtbare Absaetze nicht formatieren!" );
+ DBG_ASSERT( pParaPortion->IsInvalid(), "CreateLines: Portion nicht invalid!" );
+
+ BOOL bProcessingEmptyLine = ( pParaPortion->GetNode()->Len() == 0 );
+ BOOL bEmptyNodeWithPolygon = ( pParaPortion->GetNode()->Len() == 0 ) && GetTextRanger();
+
+ // ---------------------------------------------------------------
+ // Schnelle Sonderbehandlung fuer leere Absaetze...
+ // ---------------------------------------------------------------
+ if ( ( pParaPortion->GetNode()->Len() == 0 ) && !GetTextRanger() )
+ {
+ // schnelle Sonderbehandlung...
+ if ( pParaPortion->GetTextPortions().Count() )
+ pParaPortion->GetTextPortions().Reset();
+ if ( pParaPortion->GetLines().Count() )
+ pParaPortion->GetLines().Reset();
+ CreateAndInsertEmptyLine( pParaPortion, nStartPosY );
+ return FinishCreateLines( pParaPortion );
+ }
+
+ // ---------------------------------------------------------------
+ // Initialisierung......
+ // ---------------------------------------------------------------
+
+ // Immer fuer 100% formatieren:
+ sal_Bool bMapChanged = ImpCheckRefMapMode();
+
+ if ( pParaPortion->GetLines().Count() == 0 )
+ {
+ EditLine* pL = new EditLine;
+ pParaPortion->GetLines().Insert( pL, 0 );
+ }
+
+ // ---------------------------------------------------------------
+ // Absatzattribute holen......
+ // ---------------------------------------------------------------
+ ContentNode* const pNode = pParaPortion->GetNode();
+
+ BOOL bRightToLeftPara = IsRightToLeft( nPara );
+
+ SvxAdjust eJustification = GetJustification( nPara );
+ sal_Bool bHyphenatePara = ((const SfxBoolItem&)pNode->GetContentAttribs().GetItem( EE_PARA_HYPHENATE )).GetValue();
+ sal_Int32 nSpaceBefore = 0;
+ sal_Int32 nMinLabelWidth = 0;
+ sal_Int32 nSpaceBeforeAndMinLabelWidth = GetSpaceBeforeAndMinLabelWidth( pNode, &nSpaceBefore, &nMinLabelWidth );
+ const SvxLRSpaceItem& rLRItem = GetLRSpaceItem( pNode );
+ const SvxLineSpacingItem& rLSItem = (const SvxLineSpacingItem&) pNode->GetContentAttribs().GetItem( EE_PARA_SBL );
+ const BOOL bScriptSpace = ((const SvxScriptSpaceItem&) pNode->GetContentAttribs().GetItem( EE_PARA_ASIANCJKSPACING )).GetValue();
+
+// const sal_uInt16 nInvalidEnd = ( pParaPortion->GetInvalidDiff() > 0 )
+// ? pParaPortion->GetInvalidPosStart() + pParaPortion->GetInvalidDiff()
+// : pNode->Len();
+ const short nInvalidDiff = pParaPortion->GetInvalidDiff();
+ const sal_uInt16 nInvalidStart = pParaPortion->GetInvalidPosStart();
+ const sal_uInt16 nInvalidEnd = nInvalidStart + Abs( nInvalidDiff );
+
+ sal_Bool bQuickFormat = sal_False;
+ if ( !bEmptyNodeWithPolygon && !HasScriptType( nPara, i18n::ScriptType::COMPLEX ) )
+ {
+ if ( ( pParaPortion->IsSimpleInvalid() ) && ( nInvalidDiff > 0 ) &&
+ ( pNode->Search( CH_FEATURE, nInvalidStart ) > nInvalidEnd ) )
+ {
+ bQuickFormat = sal_True;
+ }
+ else if ( ( pParaPortion->IsSimpleInvalid() ) && ( nInvalidDiff < 0 ) )
+ {
+ // pruefen, ob loeschen ueber Portiongrenzen erfolgte...
+ sal_uInt16 nStart = nInvalidStart; // DOPPELT !!!!!!!!!!!!!!!
+ sal_uInt16 nEnd = nStart - nInvalidDiff; // neg.
+ bQuickFormat = sal_True;
+ sal_uInt16 nPos = 0;
+ sal_uInt16 nPortions = pParaPortion->GetTextPortions().Count();
+ for ( sal_uInt16 nTP = 0; nTP < nPortions; nTP++ )
+ {
+ // Es darf kein Start/Ende im geloeschten Bereich liegen.
+ TextPortion* const pTP = pParaPortion->GetTextPortions()[ nTP ];
+ nPos = nPos + pTP->GetLen();
+ if ( ( nPos > nStart ) && ( nPos < nEnd ) )
+ {
+ bQuickFormat = sal_False;
+ break;
+ }
+ }
+ }
+ }
+
+ // SW disables TEXT_LAYOUT_COMPLEX_DISABLED, so maybe I have to enable it...
+
+ // #114278# Saving both layout mode and language (since I'm
+ // potentially changing both)
+
+ GetRefDevice()->Push( PUSH_TEXTLAYOUTMODE|PUSH_TEXTLANGUAGE );
+
+ ImplInitLayoutMode( GetRefDevice(), nPara, 0xFFFF );
+
+ sal_uInt16 nRealInvalidStart = nInvalidStart;
+
+ if ( bEmptyNodeWithPolygon )
+ {
+ TextPortion* pDummyPortion = new TextPortion( 0 );
+ pParaPortion->GetTextPortions().Reset();
+ pParaPortion->GetTextPortions().Insert( pDummyPortion, 0 );
+ }
+ else if ( bQuickFormat )
+ {
+ // schnellere Methode:
+ RecalcTextPortion( pParaPortion, nInvalidStart, nInvalidDiff );
+ }
+ else // nRealInvalidStart kann vor InvalidStart liegen, weil Portions geloescht....
+ {
+ CreateTextPortions( pParaPortion, nRealInvalidStart );
+ }
+
+
+ // ---------------------------------------------------------------
+ // Zeile mit InvalidPos suchen, eine Zeile davor beginnen...
+ // Zeilen flaggen => nicht removen !
+ // ---------------------------------------------------------------
+
+ sal_uInt16 nLine = pParaPortion->GetLines().Count()-1;
+ for ( sal_uInt16 nL = 0; nL <= nLine; nL++ )
+ {
+ EditLine* pLine = pParaPortion->GetLines().GetObject( nL );
+ if ( pLine->GetEnd() > nRealInvalidStart ) // nicht nInvalidStart!
+ {
+ nLine = nL;
+ break;
+ }
+ pLine->SetValid();
+ }
+ // Eine Zeile davor beginnen...
+ // Wenn ganz hinten getippt wird, kann sich die Zeile davor nicht aendern.
+ if ( nLine && ( !pParaPortion->IsSimpleInvalid() || ( nInvalidEnd < pNode->Len() ) || ( nInvalidDiff <= 0 ) ) )
+ nLine--;
+
+ EditLine* pLine = pParaPortion->GetLines().GetObject( nLine );
+
+ static Rectangle aZeroArea = Rectangle( Point(), Point() );
+ Rectangle aBulletArea( aZeroArea );
+ if ( !nLine )
+ {
+ aBulletArea = GetEditEnginePtr()->GetBulletArea( GetParaPortions().GetPos( pParaPortion ) );
+ if ( aBulletArea.Right() > 0 )
+ pParaPortion->SetBulletX( (sal_uInt16) GetXValue( aBulletArea.Right() ) );
+ else
+ pParaPortion->SetBulletX( 0 ); // Falls Bullet falsch eingestellt.
+ }
+
+ // ---------------------------------------------------------------
+ // Ab hier alle Zeilen durchformatieren...
+ // ---------------------------------------------------------------
+ sal_uInt16 nDelFromLine = 0xFFFF;
+ sal_Bool bLineBreak = sal_False;
+
+ sal_uInt16 nIndex = pLine->GetStart();
+ EditLine aSaveLine( *pLine );
+ SvxFont aTmpFont( pNode->GetCharAttribs().GetDefFont() );
+
+ sal_Bool bCalcCharPositions = sal_True;
+ sal_Int32* pBuf = new sal_Int32[ pNode->Len() ];
+
+ sal_Bool bSameLineAgain = sal_False; // Fuer TextRanger, wenn sich die Hoehe aendert.
+ TabInfo aCurrentTab;
+
+ BOOL bForceOneRun = bEmptyNodeWithPolygon;
+ BOOL bCompressedChars = FALSE;
+
+ while ( ( nIndex < pNode->Len() ) || bForceOneRun )
+ {
+ bForceOneRun = FALSE;
+
+ sal_Bool bEOL = sal_False;
+ sal_Bool bEOC = sal_False;
+ sal_uInt16 nPortionStart = 0;
+ sal_uInt16 nPortionEnd = 0;
+
+ long nStartX = GetXValue( rLRItem.GetTxtLeft() + nSpaceBeforeAndMinLabelWidth );
+ if ( nIndex == 0 )
+ {
+ long nFI = GetXValue( rLRItem.GetTxtFirstLineOfst() );
+ nStartX += nFI;
+
+ if ( !nLine && ( pParaPortion->GetBulletX() > nStartX ) )
+ {
+// TL_NFLR nStartX += nFI; // Vielleicht reicht der LI?
+// TL_NFLR if ( pParaPortion->GetBulletX() > nStartX )
+ nStartX = pParaPortion->GetBulletX();
+ }
+ }
+
+ long nMaxLineWidth;
+ if ( !IsVertical() )
+ nMaxLineWidth = aStatus.AutoPageWidth() ? aMaxAutoPaperSize.Width() : aPaperSize.Width();
+ else
+ nMaxLineWidth = aStatus.AutoPageHeight() ? aMaxAutoPaperSize.Height() : aPaperSize.Height();
+
+ nMaxLineWidth -= GetXValue( rLRItem.GetRight() );
+ nMaxLineWidth -= nStartX;
+
+ // Wenn PaperSize == long_max, kann ich keinen neg. Erstzeileneinzug
+ // abziehen (Overflow)
+ if ( ( nMaxLineWidth < 0 ) && ( nStartX < 0 ) )
+ nMaxLineWidth = ( !IsVertical() ? aPaperSize.Width() : aPaperSize.Height() ) - GetXValue( rLRItem.GetRight() );
+
+ // Wenn jetzt noch kleiner 0, kann es nur der rechte Rand sein.
+ if ( nMaxLineWidth <= 0 )
+ nMaxLineWidth = 1;
+
+ // Problem: Da eine Zeile _vor_ der ungueltigen Position mit der
+ // Formatierung begonnen wird, werden hier leider auch die Positionen
+ // neu bestimmt...
+ // Loesungsansatz:
+ // Die Zeile davor kann nur groesser werden, nicht kleiner
+ // => ...
+ if ( bCalcCharPositions )
+ pLine->GetCharPosArray().Remove( 0, pLine->GetCharPosArray().Count() );
+
+ sal_uInt16 nTmpPos = nIndex;
+ sal_uInt16 nTmpPortion = pLine->GetStartPortion();
+ long nTmpWidth = 0;
+ long nXWidth = nMaxLineWidth;
+ if ( nXWidth <= nTmpWidth ) // while muss 1x durchlaufen werden
+ nXWidth = nTmpWidth+1;
+
+ SvLongsPtr pTextRanges = 0;
+ long nTextExtraYOffset = 0;
+ long nTextXOffset = 0;
+ long nTextLineHeight = 0;
+ if ( GetTextRanger() )
+ {
+ GetTextRanger()->SetVertical( IsVertical() );
+
+ long nTextY = nStartPosY + GetEditCursor( pParaPortion, pLine->GetStart() ).Top();
+ if ( !bSameLineAgain )
+ {
+ SeekCursor( pNode, nTmpPos+1, aTmpFont );
+ aTmpFont.SetPhysFont( GetRefDevice() );
+ ImplInitDigitMode( GetRefDevice(), 0, 0, 0, aTmpFont.GetLanguage() );
+
+ if ( IsFixedCellHeight() )
+ nTextLineHeight = ImplCalculateFontIndependentLineSpacing( aTmpFont.GetHeight() );
+ else
+ nTextLineHeight = aTmpFont.GetPhysTxtSize( GetRefDevice(), String() ).Height();
+ // Metriken koennen groesser sein
+ FormatterFontMetric aTempFormatterMetrics;
+ RecalcFormatterFontMetrics( aTempFormatterMetrics, aTmpFont );
+ sal_uInt16 nLineHeight = aTempFormatterMetrics.GetHeight();
+ if ( nLineHeight > nTextLineHeight )
+ nTextLineHeight = nLineHeight;
+ }
+ else
+ nTextLineHeight = pLine->GetHeight();
+
+ nXWidth = 0;
+ while ( !nXWidth )
+ {
+ long nYOff = nTextY + nTextExtraYOffset;
+ long nYDiff = nTextLineHeight;
+ if ( IsVertical() )
+ {
+ long nMaxPolygonX = GetTextRanger()->GetBoundRect().Right();
+ nYOff = nMaxPolygonX-nYOff;
+ nYDiff = -nTextLineHeight;
+ }
+ pTextRanges = GetTextRanger()->GetTextRanges( Range( nYOff, nYOff + nYDiff ) );
+ DBG_ASSERT( pTextRanges, "GetTextRanges?!" );
+ long nMaxRangeWidth = 0;
+ // Den breitesten Bereich verwenden...
+ // Der breiteste Bereich koennte etwas verwirren, also
+ // generell den ersten. Am besten mal richtig mit Luecken.
+// for ( sal_uInt16 n = 0; n < pTextRanges->Count(); )
+ if ( pTextRanges->Count() )
+ {
+ sal_uInt16 n = 0;
+ long nA = pTextRanges->GetObject( n++ );
+ long nB = pTextRanges->GetObject( n++ );
+ DBG_ASSERT( nA <= nB, "TextRange verdreht?" );
+ long nW = nB - nA;
+ if ( nW > nMaxRangeWidth )
+ {
+ nMaxRangeWidth = nW;
+ nTextXOffset = nA;
+ }
+ }
+ nXWidth = nMaxRangeWidth;
+ if ( nXWidth )
+ nMaxLineWidth = nXWidth - nStartX - GetXValue( rLRItem.GetRight() );
+ else
+ {
+ // Weiter unten im Polygon versuchen.
+ // Unterhalb des Polygons die Paperbreite verwenden.
+ nTextExtraYOffset += Max( (long)(nTextLineHeight / 10), (long)1 );
+ if ( ( nTextY + nTextExtraYOffset ) > GetTextRanger()->GetBoundRect().Bottom() )
+ {
+ nXWidth = !IsVertical() ? GetPaperSize().Width() : GetPaperSize().Height();
+ if ( !nXWidth ) // AutoPaperSize
+ nXWidth = 0x7FFFFFFF;
+ }
+ }
+ }
+ }
+
+ // Portion suchen, die nicht mehr in Zeile passt....
+ TextPortion* pPortion = 0;
+ sal_Bool bBrokenLine = sal_False;
+ bLineBreak = sal_False;
+ EditCharAttrib* pNextFeature = pNode->GetCharAttribs().FindFeature( pLine->GetStart() );
+ while ( ( nTmpWidth < nXWidth ) && !bEOL && ( nTmpPortion < pParaPortion->GetTextPortions().Count() ) )
+ {
+ nPortionStart = nTmpPos;
+ pPortion = pParaPortion->GetTextPortions().GetObject( nTmpPortion );
+ if ( pPortion->GetKind() == PORTIONKIND_HYPHENATOR )
+ {
+ // Portion wegschmeissen, ggf. die davor korrigieren, wenn
+ // die Hyph-Portion ein Zeichen geschluckt hat...
+ pParaPortion->GetTextPortions().Remove( nTmpPortion );
+ if ( nTmpPortion && pPortion->GetLen() )
+ {
+ nTmpPortion--;
+ TextPortion* pPrev = pParaPortion->GetTextPortions().GetObject( nTmpPortion );
+ DBG_ASSERT( pPrev->GetKind() == PORTIONKIND_TEXT, "Portion?!" );
+ nTmpWidth -= pPrev->GetSize().Width();
+ nTmpPos = nTmpPos - pPrev->GetLen();
+ pPrev->SetLen( pPrev->GetLen() + pPortion->GetLen() );
+ pPrev->GetSize().Width() = (-1);
+ }
+ delete pPortion;
+ DBG_ASSERT( nTmpPortion < pParaPortion->GetTextPortions().Count(), "Keine Portion mehr da!" );
+ pPortion = pParaPortion->GetTextPortions().GetObject( nTmpPortion );
+ }
+ DBG_ASSERT( pPortion->GetKind() != PORTIONKIND_HYPHENATOR, "CreateLines: Hyphenator-Portion!" );
+ DBG_ASSERT( pPortion->GetLen() || bProcessingEmptyLine, "Leere Portion in CreateLines ?!" );
+ if ( pNextFeature && ( pNextFeature->GetStart() == nTmpPos ) )
+ {
+ sal_uInt16 nWhich = pNextFeature->GetItem()->Which();
+ switch ( nWhich )
+ {
+ case EE_FEATURE_TAB:
+ {
+ long nOldTmpWidth = nTmpWidth;
+
+ // Tab-Pos suchen...
+ long nCurPos = nTmpWidth+nStartX;
+// nCurPos -= rLRItem.GetTxtLeft(); // Tabs relativ zu LI
+ // Skalierung rausrechnen
+ if ( aStatus.DoStretch() && ( nStretchX != 100 ) )
+ nCurPos = nCurPos*100/nStretchX;
+
+ short nAllSpaceBeforeText = static_cast< short >(rLRItem.GetTxtLeft()/* + rLRItem.GetTxtLeft()*/ + nSpaceBeforeAndMinLabelWidth);
+ aCurrentTab.aTabStop = pNode->GetContentAttribs().FindTabStop( nCurPos - nAllSpaceBeforeText /*rLRItem.GetTxtLeft()*/, aEditDoc.GetDefTab() );
+ aCurrentTab.nTabPos = GetXValue( (long) ( aCurrentTab.aTabStop.GetTabPos() + nAllSpaceBeforeText /*rLRItem.GetTxtLeft()*/ ) );
+ aCurrentTab.bValid = FALSE;
+
+ // Switch direction in R2L para...
+ if ( bRightToLeftPara )
+ {
+ if ( aCurrentTab.aTabStop.GetAdjustment() == SVX_TAB_ADJUST_RIGHT )
+ aCurrentTab.aTabStop.GetAdjustment() = SVX_TAB_ADJUST_LEFT;
+ else if ( aCurrentTab.aTabStop.GetAdjustment() == SVX_TAB_ADJUST_LEFT )
+ aCurrentTab.aTabStop.GetAdjustment() = SVX_TAB_ADJUST_RIGHT;
+ }
+
+ if ( ( aCurrentTab.aTabStop.GetAdjustment() == SVX_TAB_ADJUST_RIGHT ) ||
+ ( aCurrentTab.aTabStop.GetAdjustment() == SVX_TAB_ADJUST_CENTER ) ||
+ ( aCurrentTab.aTabStop.GetAdjustment() == SVX_TAB_ADJUST_DECIMAL ) )
+ {
+ // Bei LEFT/DEFAULT wird dieses Tab nicht mehr betrachtet.
+ aCurrentTab.bValid = TRUE;
+ aCurrentTab.nStartPosX = nTmpWidth;
+ aCurrentTab.nCharPos = nTmpPos;
+ aCurrentTab.nTabPortion = nTmpPortion;
+ }
+
+ pPortion->GetKind() = PORTIONKIND_TAB;
+ pPortion->SetExtraValue( aCurrentTab.aTabStop.GetFill() );
+ pPortion->GetSize().Width() = aCurrentTab.nTabPos - (nTmpWidth+nStartX);
+
+ // #90520# Height needed...
+ SeekCursor( pNode, nTmpPos+1, aTmpFont );
+ pPortion->GetSize().Height() = aTmpFont.QuickGetTextSize( GetRefDevice(), String(), 0, 0, NULL ).Height();
+
+ DBG_ASSERT( pPortion->GetSize().Width() >= 0, "Tab falsch berechnet!" );
+
+ nTmpWidth = aCurrentTab.nTabPos-nStartX;
+
+ // Wenn dies das erste Token in der Zeile ist,
+ // und nTmpWidth > aPaperSize.Width, habe ich eine
+ // Endlos-Schleife!
+ if ( ( nTmpWidth >= nXWidth ) && ( nTmpPortion == pLine->GetStartPortion() ) )
+ {
+ // Aber was jetzt ?
+ // Tab passend machen
+ pPortion->GetSize().Width() = nXWidth-nOldTmpWidth;
+ nTmpWidth = nXWidth-1;
+ bEOL = sal_True;
+ bBrokenLine = sal_True;
+ }
+ pLine->GetCharPosArray().Insert( pPortion->GetSize().Width(), nTmpPos-pLine->GetStart() );
+ bCompressedChars = FALSE;
+ }
+ break;
+ case EE_FEATURE_LINEBR:
+ {
+ DBG_ASSERT( pPortion, "?!" );
+ pPortion->GetSize().Width() = 0;
+ bEOL = sal_True;
+ bLineBreak = sal_True;
+ pPortion->GetKind() = PORTIONKIND_LINEBREAK;
+ bCompressedChars = FALSE;
+ pLine->GetCharPosArray().Insert( pPortion->GetSize().Width(), nTmpPos-pLine->GetStart() );
+ }
+ break;
+ case EE_FEATURE_FIELD:
+ {
+// long nCurWidth = nTmpWidth;
+ SeekCursor( pNode, nTmpPos+1, aTmpFont );
+ sal_Unicode cChar = 0; // later: NBS?
+ aTmpFont.SetPhysFont( GetRefDevice() );
+ ImplInitDigitMode( GetRefDevice(), 0, 0, 0, aTmpFont.GetLanguage() );
+
+ String aFieldValue = cChar ? String(cChar) : ((EditCharAttribField*)pNextFeature)->GetFieldValue();
+ if ( bCalcCharPositions || !pPortion->HasValidSize() )
+ {
+ pPortion->GetSize() = aTmpFont.QuickGetTextSize( GetRefDevice(), aFieldValue, 0, aFieldValue.Len(), 0 );
+ // Damit kein Scrollen bei ueberlangen Feldern
+ if ( pPortion->GetSize().Width() > nXWidth )
+ pPortion->GetSize().Width() = nXWidth;
+ }
+ nTmpWidth += pPortion->GetSize().Width();
+ pLine->GetCharPosArray().Insert( pPortion->GetSize().Width(), nTmpPos-pLine->GetStart() );
+ pPortion->GetKind() = cChar ? PORTIONKIND_TEXT : PORTIONKIND_FIELD;
+ // Wenn dies das erste Token in der Zeile ist,
+ // und nTmpWidth > aPaperSize.Width, habe ich eine
+ // Endlos-Schleife!
+ if ( ( nTmpWidth >= nXWidth ) && ( nTmpPortion == pLine->GetStartPortion() ) )
+ {
+ nTmpWidth = nXWidth-1;
+ bEOL = sal_True;
+ bBrokenLine = sal_True;
+ }
+ // Compression in Fields????
+ // I think this could be a little bit difficult and is not very usefull
+ bCompressedChars = FALSE;
+ }
+ break;
+ default: DBG_ERROR( "Was fuer ein Feature ?" );
+ }
+ pNextFeature = pNode->GetCharAttribs().FindFeature( pNextFeature->GetStart() + 1 );
+ }
+ else
+ {
+ DBG_ASSERT( pPortion->GetLen() || bProcessingEmptyLine, "Empty Portion - Extra Space?!" );
+ SeekCursor( pNode, nTmpPos+1, aTmpFont );
+ aTmpFont.SetPhysFont( GetRefDevice() );
+ ImplInitDigitMode( GetRefDevice(), 0, 0, 0, aTmpFont.GetLanguage() );
+
+ if ( bCalcCharPositions || !pPortion->HasValidSize() )
+ {
+ pPortion->GetSize() = aTmpFont.QuickGetTextSize( GetRefDevice(), *pParaPortion->GetNode(), nTmpPos, pPortion->GetLen(), pBuf );
+
+ // #i9050# Do Kerning also behind portions...
+ if ( ( aTmpFont.GetFixKerning() > 0 ) && ( ( nTmpPos + pPortion->GetLen() ) < pNode->Len() ) )
+ pPortion->GetSize().Width() += aTmpFont.GetFixKerning();
+ if ( IsFixedCellHeight() )
+ pPortion->GetSize().Height() = ImplCalculateFontIndependentLineSpacing( aTmpFont.GetHeight() );
+ }
+ if ( bCalcCharPositions )
+ {
+ sal_uInt16 nLen = pPortion->GetLen();
+ // Es wird am Anfang generell das Array geplaettet
+ // => Immer einfach schnelles insert.
+ sal_uInt16 nPos = nTmpPos - pLine->GetStart();
+ pLine->GetCharPosArray().Insert( pBuf, nLen, nPos );
+ }
+
+ // And now check for Compression:
+ if ( pPortion->GetLen() && GetAsianCompressionMode() )
+ bCompressedChars |= ImplCalcAsianCompression( pNode, pPortion, nTmpPos, (sal_Int32*)pLine->GetCharPosArray().GetData() + (nTmpPos-pLine->GetStart()), 10000, FALSE );
+
+ nTmpWidth += pPortion->GetSize().Width();
+
+ pPortion->SetRightToLeft( GetRightToLeft( nPara, nTmpPos+1 ) );
+
+ USHORT _nPortionEnd = nTmpPos + pPortion->GetLen();
+ if( bScriptSpace && ( _nPortionEnd < pNode->Len() ) && ( nTmpWidth < nXWidth ) && IsScriptChange( EditPaM( pNode, _nPortionEnd ) ) )
+ {
+ BOOL bAllow = FALSE;
+ USHORT nScriptTypeLeft = GetScriptType( EditPaM( pNode, _nPortionEnd ) );
+ USHORT nScriptTypeRight = GetScriptType( EditPaM( pNode, _nPortionEnd+1 ) );
+ if ( ( nScriptTypeLeft == i18n::ScriptType::ASIAN ) || ( nScriptTypeRight == i18n::ScriptType::ASIAN ) )
+ bAllow = TRUE;
+
+ // No spacing within L2R/R2L nesting
+ if ( bAllow )
+ {
+ long nExtraSpace = pPortion->GetSize().Height()/5;
+ nExtraSpace = GetXValue( nExtraSpace );
+ pPortion->GetSize().Width() += nExtraSpace;
+ nTmpWidth += nExtraSpace;
+ }
+ }
+ }
+
+ if ( aCurrentTab.bValid && ( nTmpPortion != aCurrentTab.nTabPortion ) )
+ {
+ long nWidthAfterTab = 0;
+ for ( USHORT n = aCurrentTab.nTabPortion+1; n <= nTmpPortion; n++ )
+ {
+ TextPortion* pTP = pParaPortion->GetTextPortions().GetObject( n );
+ nWidthAfterTab += pTP->GetSize().Width();
+ }
+ long nW = nWidthAfterTab; // Length before tab position
+ if ( aCurrentTab.aTabStop.GetAdjustment() == SVX_TAB_ADJUST_RIGHT )
+ {
+// nW = nWidthAfterTab;
+ }
+ else if ( aCurrentTab.aTabStop.GetAdjustment() == SVX_TAB_ADJUST_CENTER )
+ {
+ nW = nWidthAfterTab/2;
+ }
+ else if ( aCurrentTab.aTabStop.GetAdjustment() == SVX_TAB_ADJUST_DECIMAL )
+ {
+// nW = nWidthAfterTab;
+ String aText = GetSelected( EditSelection( EditPaM( pParaPortion->GetNode(), nTmpPos ),
+ EditPaM( pParaPortion->GetNode(), nTmpPos + pPortion->GetLen() ) ) );
+ USHORT nDecPos = aText.Search( aCurrentTab.aTabStop.GetDecimal() );
+ if ( nDecPos != STRING_NOTFOUND )
+ {
+ nW -= pParaPortion->GetTextPortions().GetObject( nTmpPortion )->GetSize().Width();
+ nW += aTmpFont.QuickGetTextSize( GetRefDevice(), *pParaPortion->GetNode(), nTmpPos, nDecPos, NULL ).Width();
+ aCurrentTab.bValid = FALSE;
+ }
+ }
+ else
+ {
+ DBG_ERROR( "CreateLines: Tab not handled!" );
+ }
+ long nMaxW = aCurrentTab.nTabPos - aCurrentTab.nStartPosX - nStartX;
+ if ( nW >= nMaxW )
+ {
+ nW = nMaxW;
+ aCurrentTab.bValid = FALSE;
+ }
+ TextPortion* pTabPortion = pParaPortion->GetTextPortions().GetObject( aCurrentTab.nTabPortion );
+ pTabPortion->GetSize().Width() = aCurrentTab.nTabPos - aCurrentTab.nStartPosX - nW - nStartX;
+ nTmpWidth = aCurrentTab.nStartPosX + pTabPortion->GetSize().Width() + nWidthAfterTab;
+ }
+
+ nTmpPos = nTmpPos + pPortion->GetLen();
+ nPortionEnd = nTmpPos;
+ nTmpPortion++;
+ if ( aStatus.OneCharPerLine() )
+ bEOL = sal_True;
+ }
+
+ DBG_ASSERT( pPortion, "no portion!?" );
+
+ aCurrentTab.bValid = FALSE;
+
+ // das war evtl. eine Portion zu weit:
+ sal_Bool bFixedEnd = sal_False;
+ if ( aStatus.OneCharPerLine() )
+ {
+ // Zustand vor Portion: ( bis auf nTmpWidth )
+ nPortionEnd = nTmpPos;
+ nTmpPos -= pPortion ? pPortion->GetLen() : 0;
+ nPortionStart = nTmpPos;
+ nTmpPortion--;
+
+ bEOL = sal_True;
+ bEOC = sal_False;
+
+ // Und jetzt genau ein Zeichen:
+ nTmpPos++;
+ nTmpPortion++;
+ nPortionEnd = nTmpPortion;
+ // Eine Nicht-Feature-Portion muss gebrochen werden
+ if ( pPortion->GetLen() > 1 )
+ {
+ DBG_ASSERT( pPortion && (pPortion->GetKind() == PORTIONKIND_TEXT), "Len>1, aber keine TextPortion?" );
+ nTmpWidth -= pPortion ? pPortion->GetSize().Width() : 0;
+ sal_uInt16 nP = SplitTextPortion( pParaPortion, nTmpPos, pLine );
+ TextPortion* p = pParaPortion->GetTextPortions().GetObject( nP );
+ DBG_ASSERT( p, "Portion ?!" );
+ nTmpWidth += p->GetSize().Width();
+ }
+ }
+ else if ( nTmpWidth >= nXWidth )
+ {
+ nPortionEnd = nTmpPos;
+ nTmpPos -= pPortion ? pPortion->GetLen() : 0;
+ nPortionStart = nTmpPos;
+ nTmpPortion--;
+ bEOL = sal_False;
+ bEOC = sal_False;
+ if( pPortion ) switch ( pPortion->GetKind() )
+ {
+ case PORTIONKIND_TEXT:
+ {
+ nTmpWidth -= pPortion->GetSize().Width();
+ }
+ break;
+ case PORTIONKIND_FIELD:
+ case PORTIONKIND_TAB:
+ {
+ nTmpWidth -= pPortion->GetSize().Width();
+ bEOL = sal_True;
+ bFixedEnd = sal_True;
+ }
+ break;
+ default:
+ {
+ // Ein Feature wird nicht umgebrochen:
+ DBG_ASSERT( ( pPortion->GetKind() == PORTIONKIND_LINEBREAK ), "Was fuer ein Feature ?" );
+ bEOL = sal_True;
+ bFixedEnd = sal_True;
+ }
+ }
+ }
+ else
+ {
+ bEOL = sal_True;
+ bEOC = sal_True;
+ pLine->SetEnd( nPortionEnd );
+ DBG_ASSERT( pParaPortion->GetTextPortions().Count(), "Keine TextPortions?" );
+ pLine->SetEndPortion( (sal_uInt16)pParaPortion->GetTextPortions().Count() - 1 );
+ }
+
+ if ( aStatus.OneCharPerLine() )
+ {
+ pLine->SetEnd( nPortionEnd );
+ pLine->SetEndPortion( nTmpPortion-1 );
+ }
+ else if ( bFixedEnd )
+ {
+ pLine->SetEnd( nPortionStart );
+ pLine->SetEndPortion( nTmpPortion-1 );
+ }
+ else if ( bLineBreak || bBrokenLine )
+ {
+ pLine->SetEnd( nPortionStart+1 );
+ pLine->SetEndPortion( nTmpPortion-1 );
+ bEOC = sal_False; // wurde oben gesetzt, vielleich mal die if's umstellen?
+ }
+ else if ( !bEOL )
+ {
+ DBG_ASSERT( pPortion && ((nPortionEnd-nPortionStart) == pPortion->GetLen()), "Doch eine andere Portion?!" );
+ long nRemainingWidth = nMaxLineWidth - nTmpWidth;
+ sal_Bool bCanHyphenate = ( aTmpFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL );
+ if ( bCompressedChars && pPortion && ( pPortion->GetLen() > 1 ) && pPortion->GetExtraInfos() && pPortion->GetExtraInfos()->bCompressed )
+ {
+ // I need the manipulated DXArray for determining the break postion...
+ ImplCalcAsianCompression( pNode, pPortion, nPortionStart, const_cast<sal_Int32*>(( pLine->GetCharPosArray().GetData() + (nPortionStart-pLine->GetStart()) )), 10000, TRUE );
+ }
+ if( pPortion )
+ ImpBreakLine( pParaPortion, pLine, pPortion, nPortionStart,
+ nRemainingWidth, bCanHyphenate && bHyphenatePara );
+ }
+
+ // ------------------------------------------------------------------
+ // Zeile fertig => justieren
+ // ------------------------------------------------------------------
+
+ // CalcTextSize sollte besser durch ein kontinuierliches
+ // Registrieren ersetzt werden !
+ Size aTextSize = pLine->CalcTextSize( *pParaPortion );
+
+ if ( aTextSize.Height() == 0 )
+ {
+ SeekCursor( pNode, pLine->GetStart()+1, aTmpFont );
+ aTmpFont.SetPhysFont( pRefDev );
+ ImplInitDigitMode( pRefDev, 0, 0, 0, aTmpFont.GetLanguage() );
+
+ if ( IsFixedCellHeight() )
+ aTextSize.Height() = ImplCalculateFontIndependentLineSpacing( aTmpFont.GetHeight() );
+ else
+ aTextSize.Height() = aTmpFont.GetPhysTxtSize( pRefDev, String() ).Height();
+ pLine->SetHeight( (sal_uInt16)aTextSize.Height() );
+ }
+
+ // Die Fontmetriken koennen nicht kontinuierlich berechnet werden,
+ // wenn der Font sowieso eingestellt ist, weil ggf. ein grosser Font
+ // erst nach dem Umbrechen ploetzlich in der naechsten Zeile landet
+ // => Font-Metriken zu gross.
+ FormatterFontMetric aFormatterMetrics;
+ sal_uInt16 nTPos = pLine->GetStart();
+ for ( sal_uInt16 nP = pLine->GetStartPortion(); nP <= pLine->GetEndPortion(); nP++ )
+ {
+ TextPortion* pTP = pParaPortion->GetTextPortions().GetObject( nP );
+ // #95819# problem with hard font height attribute, when everthing but the line break has this attribute
+ if ( pTP->GetKind() != PORTIONKIND_LINEBREAK )
+ {
+ SeekCursor( pNode, nTPos+1, aTmpFont );
+ aTmpFont.SetPhysFont( GetRefDevice() );
+ ImplInitDigitMode( GetRefDevice(), 0, 0, 0, aTmpFont.GetLanguage() );
+ RecalcFormatterFontMetrics( aFormatterMetrics, aTmpFont );
+ }
+ nTPos = nTPos + pTP->GetLen();
+ }
+ sal_uInt16 nLineHeight = aFormatterMetrics.GetHeight();
+ if ( nLineHeight > pLine->GetHeight() )
+ pLine->SetHeight( nLineHeight );
+ pLine->SetMaxAscent( aFormatterMetrics.nMaxAscent );
+
+ bSameLineAgain = sal_False;
+ if ( GetTextRanger() && ( pLine->GetHeight() > nTextLineHeight ) )
+ {
+ // Nochmal mit der anderen Groesse aufsetzen!
+ bSameLineAgain = sal_True;
+ }
+
+
+ if ( !bSameLineAgain && !aStatus.IsOutliner() )
+ {
+ if ( rLSItem.GetLineSpaceRule() == SVX_LINE_SPACE_MIN )
+ {
+ sal_uInt16 nMinHeight = GetYValue( rLSItem.GetLineHeight() );
+ sal_uInt16 nTxtHeight = pLine->GetHeight();
+ if ( nTxtHeight < nMinHeight )
+ {
+ // Der Ascent muss um die Differenz angepasst werden:
+ long nDiff = nMinHeight - nTxtHeight;
+ pLine->SetMaxAscent( (sal_uInt16)(pLine->GetMaxAscent() + nDiff) );
+ pLine->SetHeight( nMinHeight, nTxtHeight );
+ }
+ }
+ else if ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP )
+ {
+ if ( nPara || IsFixedCellHeight() || pLine->GetStartPortion() ) // Nicht die aller erste Zeile
+ {
+ // #100508# There are documents with PropLineSpace 0, why?
+ // (cmc: re above question :-) such documents can be seen by importing a .ppt
+ if ( rLSItem.GetPropLineSpace() && ( rLSItem.GetPropLineSpace() != 100 ) )
+ {
+ sal_uInt16 nTxtHeight = pLine->GetHeight();
+ sal_Int32 nH = nTxtHeight;
+ nH *= rLSItem.GetPropLineSpace();
+ nH /= 100;
+ // Der Ascent muss um die Differenz angepasst werden:
+ long nDiff = pLine->GetHeight() - nH;
+ if ( nDiff > pLine->GetMaxAscent() )
+ nDiff = pLine->GetMaxAscent();
+ pLine->SetMaxAscent( (sal_uInt16)(pLine->GetMaxAscent() - nDiff) );
+ pLine->SetHeight( (sal_uInt16)nH, nTxtHeight );
+ }
+ }
+ }
+ }
+
+
+ // #80582# - Bullet should not influence line height
+// if ( !nLine )
+// {
+// long nBulletHeight = aBulletArea.GetHeight();
+// if ( nBulletHeight > (long)pLine->GetHeight() )
+// {
+// long nDiff = nBulletHeight - (long)pLine->GetHeight();
+// // nDiff auf oben und unten verteilen.
+// pLine->SetMaxAscent( (sal_uInt16)(pLine->GetMaxAscent() + nDiff/2) );
+// pLine->SetHeight( (sal_uInt16)nBulletHeight );
+// }
+// }
+
+ if ( ( !IsVertical() && aStatus.AutoPageWidth() ) ||
+ ( IsVertical() && aStatus.AutoPageHeight() ) )
+ {
+ // Wenn die Zeile in die aktuelle Papierbreite passt, muss
+ // diese Breite fuer die Ausrichting verwendet werden.
+ // Wenn sie nicht passt oder sie die Papierbreite aendert,
+ // wird bei Justification != LEFT sowieso noch mal formatiert.
+ long nMaxLineWidthFix = ( !IsVertical() ? aPaperSize.Width() : aPaperSize.Height() )
+ - GetXValue( rLRItem.GetRight() ) - nStartX;
+ if ( aTextSize.Width() < nMaxLineWidthFix )
+ nMaxLineWidth = nMaxLineWidthFix;
+ }
+
+ if ( bCompressedChars )
+ {
+ long nRemainingWidth = nMaxLineWidth - aTextSize.Width();
+ if ( nRemainingWidth > 0 )
+ {
+ ImplExpandCompressedPortions( pLine, pParaPortion, nRemainingWidth );
+ aTextSize = pLine->CalcTextSize( *pParaPortion );
+ }
+ }
+
+ if ( pLine->IsHangingPunctuation() )
+ {
+ // Width from HangingPunctuation was set to 0 in ImpBreakLine,
+ // check for rel width now, maybe create compression...
+ long n = nMaxLineWidth - aTextSize.Width();
+ TextPortion* pTP = pParaPortion->GetTextPortions().GetObject( pLine->GetEndPortion() );
+ sal_uInt16 nPosInArray = pLine->GetEnd()-1-pLine->GetStart();
+ long nNewValue = ( nPosInArray ? pLine->GetCharPosArray()[ nPosInArray-1 ] : 0 ) + n;
+ pLine->GetCharPosArray()[ nPosInArray ] = nNewValue;
+ pTP->GetSize().Width() += n;
+ }
+
+ pLine->SetTextWidth( aTextSize.Width() );
+ switch ( eJustification )
+ {
+ case SVX_ADJUST_CENTER:
+ {
+ long n = ( nMaxLineWidth - aTextSize.Width() ) / 2;
+ n += nStartX; // Einrueckung bleibt erhalten.
+ if ( n > 0 )
+ pLine->SetStartPosX( (sal_uInt16)n );
+ else
+ pLine->SetStartPosX( 0 );
+
+ }
+ break;
+ case SVX_ADJUST_RIGHT:
+ {
+ // Bei automatisch umgebrochenen Zeilen, die ein Blank
+ // am Ende enthalten, darf das Blank nicht ausgegeben werden!
+
+ long n = nMaxLineWidth - aTextSize.Width();
+ n += nStartX; // Einrueckung bleibt erhalten.
+ if ( n > 0 )
+ pLine->SetStartPosX( (sal_uInt16)n );
+ else
+ pLine->SetStartPosX( 0 );
+ }
+ break;
+ case SVX_ADJUST_BLOCK:
+ {
+ long nRemainingSpace = nMaxLineWidth - aTextSize.Width();
+ pLine->SetStartPosX( (sal_uInt16)nStartX );
+ if ( !bEOC && ( nRemainingSpace > 0 ) ) // nicht die letzte Zeile...
+ ImpAdjustBlocks( pParaPortion, pLine, nRemainingSpace );
+ }
+ break;
+ default:
+ {
+ pLine->SetStartPosX( (sal_uInt16)nStartX ); // FI, LI
+ }
+ break;
+ }
+
+ // -----------------------------------------------------------------
+ // pruefen, ob die Zeile neu ausgegeben werden muss...
+ // -----------------------------------------------------------------
+ pLine->SetInvalid();
+
+ // Wenn eine Portion umgebrochen wurde sind ggf. viel zu viele Positionen
+ // im CharPosArray:
+ if ( bCalcCharPositions )
+ {
+ sal_uInt16 nLen = pLine->GetLen();
+ sal_uInt16 nCount = pLine->GetCharPosArray().Count();
+ if ( nCount > nLen )
+ pLine->GetCharPosArray().Remove( nLen, nCount-nLen );
+ }
+
+ if ( GetTextRanger() )
+ {
+ if ( nTextXOffset )
+ pLine->SetStartPosX( (sal_uInt16) ( pLine->GetStartPosX() + nTextXOffset ) );
+ if ( nTextExtraYOffset )
+ {
+ pLine->SetHeight( (sal_uInt16) ( pLine->GetHeight() + nTextExtraYOffset ), 0, pLine->GetHeight() );
+ pLine->SetMaxAscent( (sal_uInt16) ( pLine->GetMaxAscent() + nTextExtraYOffset ) );
+ }
+ }
+
+ // Fuer kleiner 0 noch ueberlegen!
+ if ( pParaPortion->IsSimpleInvalid() /* && ( nInvalidDiff > 0 ) */ )
+ {
+ // Aenderung durch einfache Textaenderung...
+ // Formatierung nicht abbrechen, da Portions evtl. wieder
+ // gesplittet werden muessen!
+ // Wenn irgendwann mal abbrechbar, dann fogende Zeilen Validieren!
+ // Aber ggf. als Valid markieren, damit weniger Ausgabe...
+ if ( pLine->GetEnd() < nInvalidStart )
+ {
+ if ( *pLine == aSaveLine )
+ {
+ pLine->SetValid();
+ }
+ }
+ else
+ {
+ sal_uInt16 nStart = pLine->GetStart();
+ sal_uInt16 nEnd = pLine->GetEnd();
+
+ if ( nStart > nInvalidEnd )
+ {
+ if ( ( ( nStart-nInvalidDiff ) == aSaveLine.GetStart() ) &&
+ ( ( nEnd-nInvalidDiff ) == aSaveLine.GetEnd() ) )
+ {
+ pLine->SetValid();
+ if ( bCalcCharPositions && bQuickFormat )
+ {
+ bCalcCharPositions = sal_False;
+ bLineBreak = sal_False;
+ pParaPortion->CorrectValuesBehindLastFormattedLine( nLine );
+ break;
+ }
+ }
+ }
+ else if ( bCalcCharPositions && bQuickFormat && ( nEnd > nInvalidEnd) )
+ {
+ // Wenn die ungueltige Zeile so endet, dass die naechste an
+ // der 'gleichen' Textstelle wie vorher beginnt, also nicht
+ // anders umgebrochen wird, brauche ich dort auch nicht die
+ // textbreiten neu bestimmen:
+ if ( nEnd == ( aSaveLine.GetEnd() + nInvalidDiff ) )
+ {
+ bCalcCharPositions = sal_False;
+ bLineBreak = sal_False;
+ pParaPortion->CorrectValuesBehindLastFormattedLine( nLine );
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !bSameLineAgain )
+ {
+ nIndex = pLine->GetEnd(); // naechste Zeile Start = letzte Zeile Ende
+ // weil nEnd hinter das letzte Zeichen zeigt!
+
+ sal_uInt16 nEndPortion = pLine->GetEndPortion();
+
+ // Naechste Zeile oder ggf. neue Zeile....
+ pLine = 0;
+ if ( nLine < pParaPortion->GetLines().Count()-1 )
+ pLine = pParaPortion->GetLines().GetObject( ++nLine );
+ if ( pLine && ( nIndex >= pNode->Len() ) )
+ {
+ nDelFromLine = nLine;
+ break;
+ }
+ if ( !pLine )
+ {
+ if ( nIndex < pNode->Len() )
+ {
+ pLine = new EditLine;
+ pParaPortion->GetLines().Insert( pLine, ++nLine );
+ }
+ else if ( nIndex && bLineBreak && GetTextRanger() )
+ {
+ // normaly CreateAndInsertEmptyLine would be called, but I want to use
+ // CreateLines, so I need Polygon code only here...
+ TextPortion* pDummyPortion = new TextPortion( 0 );
+ pParaPortion->GetTextPortions().Insert( pDummyPortion, pParaPortion->GetTextPortions().Count() );
+ pLine = new EditLine;
+ pParaPortion->GetLines().Insert( pLine, ++nLine );
+ bForceOneRun = TRUE;
+ bProcessingEmptyLine = TRUE;
+ }
+ }
+ if ( pLine )
+ {
+ aSaveLine = *pLine;
+ pLine->SetStart( nIndex );
+ pLine->SetEnd( nIndex );
+ pLine->SetStartPortion( nEndPortion+1 );
+ pLine->SetEndPortion( nEndPortion+1 );
+ }
+ }
+ } // while ( Index < Len )
+
+ if ( nDelFromLine != 0xFFFF )
+ pParaPortion->GetLines().DeleteFromLine( nDelFromLine );
+
+ DBG_ASSERT( pParaPortion->GetLines().Count(), "Keine Zeile nach CreateLines!" );
+
+ if ( bLineBreak == sal_True )
+ CreateAndInsertEmptyLine( pParaPortion, nStartPosY );
+
+ delete[] pBuf;
+
+ sal_Bool bHeightChanged = FinishCreateLines( pParaPortion );
+
+ if ( bMapChanged )
+ GetRefDevice()->Pop();
+
+ GetRefDevice()->Pop();
+
+ return bHeightChanged;
+}
+
+void ImpEditEngine::CreateAndInsertEmptyLine( ParaPortion* pParaPortion, sal_uInt32 )
+{
+ DBG_ASSERT( !GetTextRanger(), "Don't use CreateAndInsertEmptyLine with a polygon!" );
+
+ EditLine* pTmpLine = new EditLine;
+ pTmpLine->SetStart( pParaPortion->GetNode()->Len() );
+ pTmpLine->SetEnd( pParaPortion->GetNode()->Len() );
+ pParaPortion->GetLines().Insert( pTmpLine, pParaPortion->GetLines().Count() );
+
+ sal_Bool bLineBreak = pParaPortion->GetNode()->Len() ? sal_True : sal_False;
+ sal_Int32 nSpaceBefore = 0;
+ sal_Int32 nSpaceBeforeAndMinLabelWidth = GetSpaceBeforeAndMinLabelWidth( pParaPortion->GetNode(), &nSpaceBefore );
+ const SvxLRSpaceItem& rLRItem = GetLRSpaceItem( pParaPortion->GetNode() );
+ const SvxLineSpacingItem& rLSItem = (const SvxLineSpacingItem&)pParaPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
+ short nStartX = GetXValue( (short)(rLRItem.GetTxtLeft() + rLRItem.GetTxtFirstLineOfst() + nSpaceBefore));
+
+ Rectangle aBulletArea = Rectangle( Point(), Point() );
+ if ( bLineBreak == sal_True )
+ {
+ nStartX = (short)GetXValue( rLRItem.GetTxtLeft() + rLRItem.GetTxtFirstLineOfst() + nSpaceBeforeAndMinLabelWidth );
+ }
+ else
+ {
+ aBulletArea = GetEditEnginePtr()->GetBulletArea( GetParaPortions().GetPos( pParaPortion ) );
+ if ( aBulletArea.Right() > 0 )
+ pParaPortion->SetBulletX( (sal_uInt16) GetXValue( aBulletArea.Right() ) );
+ else
+ pParaPortion->SetBulletX( 0 ); // Falls Bullet falsch eingestellt.
+ if ( pParaPortion->GetBulletX() > nStartX )
+ {
+ nStartX = (short)GetXValue( rLRItem.GetTxtLeft() + rLRItem.GetTxtFirstLineOfst() + nSpaceBeforeAndMinLabelWidth );
+ if ( pParaPortion->GetBulletX() > nStartX )
+ nStartX = pParaPortion->GetBulletX();
+ }
+ }
+
+ SvxFont aTmpFont;
+ SeekCursor( pParaPortion->GetNode(), bLineBreak ? pParaPortion->GetNode()->Len() : 0, aTmpFont );
+ aTmpFont.SetPhysFont( pRefDev );
+
+ TextPortion* pDummyPortion = new TextPortion( 0 );
+ pDummyPortion->GetSize() = aTmpFont.GetPhysTxtSize( pRefDev, String() );
+ if ( IsFixedCellHeight() )
+ pDummyPortion->GetSize().Height() = ImplCalculateFontIndependentLineSpacing( aTmpFont.GetHeight() );
+ pParaPortion->GetTextPortions().Insert( pDummyPortion, pParaPortion->GetTextPortions().Count() );
+ FormatterFontMetric aFormatterMetrics;
+ RecalcFormatterFontMetrics( aFormatterMetrics, aTmpFont );
+ pTmpLine->SetMaxAscent( aFormatterMetrics.nMaxAscent );
+ pTmpLine->SetHeight( (sal_uInt16) pDummyPortion->GetSize().Height() );
+ sal_uInt16 nLineHeight = aFormatterMetrics.GetHeight();
+ if ( nLineHeight > pTmpLine->GetHeight() )
+ pTmpLine->SetHeight( nLineHeight );
+
+ if ( !aStatus.IsOutliner() )
+ {
+ USHORT nPara = GetParaPortions().GetPos( pParaPortion );
+ SvxAdjust eJustification = GetJustification( nPara );
+ long nMaxLineWidth = !IsVertical() ? aPaperSize.Width() : aPaperSize.Height();
+ nMaxLineWidth -= GetXValue( rLRItem.GetRight() );
+ long nTextXOffset = 0;
+ if ( nMaxLineWidth < 0 )
+ nMaxLineWidth = 1;
+ if ( eJustification == SVX_ADJUST_CENTER )
+ nStartX = sal::static_int_cast< short >(nMaxLineWidth / 2);
+ else if ( eJustification == SVX_ADJUST_RIGHT )
+ nStartX = sal::static_int_cast< short >(nMaxLineWidth);
+
+ nStartX = sal::static_int_cast< short >(nStartX + nTextXOffset);
+ }
+
+ pTmpLine->SetStartPosX( nStartX );
+
+ if ( !aStatus.IsOutliner() )
+ {
+ if ( rLSItem.GetLineSpaceRule() == SVX_LINE_SPACE_MIN )
+ {
+ sal_uInt16 nMinHeight = rLSItem.GetLineHeight();
+ sal_uInt16 nTxtHeight = pTmpLine->GetHeight();
+ if ( nTxtHeight < nMinHeight )
+ {
+ // Der Ascent muss um die Differenz angepasst werden:
+ long nDiff = nMinHeight - nTxtHeight;
+ pTmpLine->SetMaxAscent( (sal_uInt16)(pTmpLine->GetMaxAscent() + nDiff) );
+ pTmpLine->SetHeight( nMinHeight, nTxtHeight );
+ }
+ }
+ else if ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP )
+ {
+ USHORT nPara = GetParaPortions().GetPos( pParaPortion );
+ if ( nPara || IsFixedCellHeight() || pTmpLine->GetStartPortion() ) // Nicht die aller erste Zeile
+ {
+ // #100508# There are documents with PropLineSpace 0, why?
+ // (cmc: re above question :-) such documents can be seen by importing a .ppt
+ if ( rLSItem.GetPropLineSpace() && ( rLSItem.GetPropLineSpace() != 100 ) )
+ {
+ sal_uInt16 nTxtHeight = pTmpLine->GetHeight();
+ sal_Int32 nH = nTxtHeight;
+ nH *= rLSItem.GetPropLineSpace();
+ nH /= 100;
+ // Der Ascent muss um die Differenz angepasst werden:
+ long nDiff = pTmpLine->GetHeight() - nH;
+ if ( nDiff > pTmpLine->GetMaxAscent() )
+ nDiff = pTmpLine->GetMaxAscent();
+ pTmpLine->SetMaxAscent( (sal_uInt16)(pTmpLine->GetMaxAscent() - nDiff) );
+ pTmpLine->SetHeight( (sal_uInt16)nH, nTxtHeight );
+ }
+ }
+ }
+ }
+
+ if ( !bLineBreak )
+ {
+ long nMinHeight = aBulletArea.GetHeight();
+ if ( nMinHeight > (long)pTmpLine->GetHeight() )
+ {
+ long nDiff = nMinHeight - (long)pTmpLine->GetHeight();
+ // nDiff auf oben und unten verteilen.
+ pTmpLine->SetMaxAscent( (sal_uInt16)(pTmpLine->GetMaxAscent() + nDiff/2) );
+ pTmpLine->SetHeight( (sal_uInt16)nMinHeight );
+ }
+ }
+ else
+ {
+ // -2: Die neue ist bereits eingefuegt.
+#ifdef DBG_UTIL
+ EditLine* pLastLine = pParaPortion->GetLines().GetObject( pParaPortion->GetLines().Count()-2 );
+ DBG_ASSERT( pLastLine, "Weicher Umbruch, keine Zeile ?!" );
+ DBG_ASSERT( pLastLine->GetEnd() == pParaPortion->GetNode()->Len(), "Doch anders?" );
+#endif
+// pTmpLine->SetStart( pLastLine->GetEnd() );
+// pTmpLine->SetEnd( pLastLine->GetEnd() );
+ sal_uInt16 nPos = (sal_uInt16) pParaPortion->GetTextPortions().Count() - 1 ;
+ pTmpLine->SetStartPortion( nPos );
+ pTmpLine->SetEndPortion( nPos );
+ }
+}
+
+sal_Bool ImpEditEngine::FinishCreateLines( ParaPortion* pParaPortion )
+{
+// CalcCharPositions( pParaPortion );
+ pParaPortion->SetValid();
+ long nOldHeight = pParaPortion->GetHeight();
+// sal_uInt16 nPos = GetParaPortions().GetPos( pParaPortion );
+// DBG_ASSERT( nPos != USHRT_MAX, "FinishCreateLines: Portion nicht in Liste!" );
+// ParaPortion* pPrev = nPos ? GetParaPortions().GetObject( nPos-1 ) : 0;
+ CalcHeight( pParaPortion );
+
+ DBG_ASSERT( pParaPortion->GetTextPortions().Count(), "FinishCreateLines: Keine Text-Portion?" );
+ sal_Bool bRet = ( pParaPortion->GetHeight() != nOldHeight );
+ return bRet;
+}
+
+void ImpEditEngine::ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, TextPortion* pPortion, sal_uInt16 nPortionStart, long nRemainingWidth, sal_Bool bCanHyphenate )
+{
+ ContentNode* const pNode = pParaPortion->GetNode();
+
+ sal_uInt16 nBreakInLine = nPortionStart - pLine->GetStart();
+ sal_uInt16 nMax = nBreakInLine + pPortion->GetLen();
+ while ( ( nBreakInLine < nMax ) && ( pLine->GetCharPosArray()[nBreakInLine] < nRemainingWidth ) )
+ nBreakInLine++;
+
+ sal_uInt16 nMaxBreakPos = nBreakInLine + pLine->GetStart();
+ sal_uInt16 nBreakPos = 0xFFFF;
+
+ sal_Bool bCompressBlank = sal_False;
+ sal_Bool bHyphenated = sal_False;
+ sal_Bool bHangingPunctuation = sal_False;
+ sal_Unicode cAlternateReplChar = 0;
+ sal_Unicode cAlternateExtraChar = 0;
+
+ if ( ( nMaxBreakPos < ( nMax + pLine->GetStart() ) ) && ( pNode->GetChar( nMaxBreakPos ) == ' ' ) )
+ {
+ // Break behind the blank, blank will be compressed...
+ nBreakPos = nMaxBreakPos + 1;
+ bCompressBlank = sal_True;
+ }
+ else
+ {
+ sal_uInt16 nMinBreakPos = pLine->GetStart();
+ USHORT nAttrs = pNode->GetCharAttribs().GetAttribs().Count();
+ for ( USHORT nAttr = nAttrs; nAttr; )
+ {
+ EditCharAttrib* pAttr = pNode->GetCharAttribs().GetAttribs()[--nAttr];
+ if ( pAttr->IsFeature() && ( pAttr->GetEnd() > nMinBreakPos ) && ( pAttr->GetEnd() <= nMaxBreakPos ) )
+ {
+ nMinBreakPos = pAttr->GetEnd();
+ break;
+ }
+ }
+
+ lang::Locale aLocale = GetLocale( EditPaM( pNode, nMaxBreakPos ) );
+
+ Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
+ OUString aText( *pNode );
+ Reference< XHyphenator > xHyph;
+ if ( bCanHyphenate )
+ xHyph = GetHyphenator();
+ i18n::LineBreakHyphenationOptions aHyphOptions( xHyph, Sequence< PropertyValue >(), 1 );
+ i18n::LineBreakUserOptions aUserOptions;
+
+ const i18n::ForbiddenCharacters* pForbidden = GetForbiddenCharsTable()->GetForbiddenCharacters( SvxLocaleToLanguage( aLocale ), TRUE );
+ aUserOptions.forbiddenBeginCharacters = pForbidden->beginLine;
+ aUserOptions.forbiddenEndCharacters = pForbidden->endLine;
+ aUserOptions.applyForbiddenRules = ((const SfxBoolItem&)pNode->GetContentAttribs().GetItem( EE_PARA_FORBIDDENRULES )).GetValue();
+ aUserOptions.allowPunctuationOutsideMargin = ((const SfxBoolItem&)pNode->GetContentAttribs().GetItem( EE_PARA_HANGINGPUNCTUATION )).GetValue();
+ aUserOptions.allowHyphenateEnglish = FALSE;
+
+ i18n::LineBreakResults aLBR = _xBI->getLineBreak( *pNode, nMaxBreakPos, aLocale, nMinBreakPos, aHyphOptions, aUserOptions );
+ nBreakPos = (USHORT)aLBR.breakIndex;
+
+ // BUG in I18N - under special condition (break behind field, #87327#) breakIndex is < nMinBreakPos
+ if ( nBreakPos < nMinBreakPos )
+ {
+ nBreakPos = nMinBreakPos;
+ }
+ else if ( ( nBreakPos > nMaxBreakPos ) && !aUserOptions.allowPunctuationOutsideMargin )
+ {
+ DBG_ERROR( "I18N: XBreakIterator::getLineBreak returns position > Max" );
+ nBreakPos = nMaxBreakPos;
+ }
+
+ // #101795# nBreakPos can never be outside the portion, even not with hangig punctuation
+ if ( nBreakPos > nMaxBreakPos )
+ nBreakPos = nMaxBreakPos;
+
+ // BUG in I18N - the japanese dot is in the next line!
+ // !!! Testen!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ if ( (nBreakPos + ( aUserOptions.allowPunctuationOutsideMargin ? 0 : 1 ) ) <= nMaxBreakPos )
+ {
+ sal_Unicode cFirstInNextLine = ( (nBreakPos+1) < pNode->Len() ) ? pNode->GetChar( nBreakPos ) : 0;
+ if ( cFirstInNextLine == 12290 )
+ nBreakPos++;
+ }
+
+ bHangingPunctuation = ( nBreakPos > nMaxBreakPos ) ? sal_True : sal_False;
+ pLine->SetHangingPunctuation( bHangingPunctuation );
+
+ #ifndef SVX_LIGHT
+ // Egal ob Trenner oder nicht: Das Wort nach dem Trenner durch
+ // die Silbentrennung jagen...
+ // nMaxBreakPos ist das letzte Zeichen was in die Zeile passt,
+ // nBreakPos ist der Wort-Anfang
+ // Ein Problem gibt es, wenn das Dok so schmal ist, dass ein Wort
+ // auf mehr als Zwei Zeilen gebrochen wird...
+ if ( !bHangingPunctuation && bCanHyphenate && GetHyphenator().is() )
+ {
+ i18n::Boundary aBoundary = _xBI->getWordBoundary( *pNode, nBreakPos, GetLocale( EditPaM( pNode, nBreakPos ) ), ::com::sun::star::i18n::WordType::DICTIONARY_WORD, sal_True );
+// sal_uInt16 nWordStart = nBreakPos;
+// sal_uInt16 nBreakPos_OLD = nBreakPos;
+ sal_uInt16 nWordStart = nBreakPos;
+ sal_uInt16 nWordEnd = (USHORT) aBoundary.endPos;
+ DBG_ASSERT( nWordEnd > nWordStart, "ImpBreakLine: Start >= End?" );
+
+ USHORT nWordLen = nWordEnd - nWordStart;
+ if ( ( nWordEnd >= nMaxBreakPos ) && ( nWordLen > 3 ) )
+ {
+ // #104415# May happen, because getLineBreak may differ from getWordBoudary with DICTIONARY_WORD
+ // DBG_ASSERT( nWordEnd >= nMaxBreakPos, "Hyph: Break?" );
+ String aWord( *pNode, nWordStart, nWordLen );
+ sal_uInt16 nMinTrail = nWordEnd-nMaxBreakPos+1; //+1: Vor dem angeknacksten Buchstaben
+ Reference< XHyphenatedWord > xHyphWord;
+ if (xHyphenator.is())
+ xHyphWord = xHyphenator->hyphenate( aWord, aLocale, aWord.Len() - nMinTrail, Sequence< PropertyValue >() );
+ if (xHyphWord.is())
+ {
+ sal_Bool bAlternate = xHyphWord->isAlternativeSpelling();
+ sal_uInt16 _nWordLen = 1 + xHyphWord->getHyphenPos();
+
+ if ( ( _nWordLen >= 2 ) && ( (nWordStart+_nWordLen) >= (pLine->GetStart() + 2 ) ) )
+ {
+ if ( !bAlternate )
+ {
+ bHyphenated = sal_True;
+ nBreakPos = nWordStart + _nWordLen;
+ }
+ else
+ {
+ String aAlt( xHyphWord->getHyphenatedWord() );
+
+ // Wir gehen von zwei Faellen aus, die nun
+ // vorliegen koennen:
+ // 1) packen wird zu pak-ken
+ // 2) Schiffahrt wird zu Schiff-fahrt
+ // In Fall 1 muss ein Zeichen ersetzt werden,
+ // in Fall 2 wird ein Zeichen hinzugefuegt.
+ // Die Identifikation wird erschwert durch Worte wie
+ // "Schiffahrtsbrennesseln", da der Hyphenator alle
+ // Position des Wortes auftrennt und "Schifffahrtsbrennnesseln"
+ // ermittelt. Wir koennen also eigentlich nicht unmittelbar vom
+ // Index des AlternativWord auf aWord schliessen.
+
+ // Das ganze geraffel wird durch eine Funktion am
+ // Hyphenator vereinfacht werden, sobald AMA sie einbaut...
+ sal_uInt16 nAltStart = _nWordLen - 1;
+ sal_uInt16 nTxtStart = nAltStart - (aAlt.Len() - aWord.Len());
+ sal_uInt16 nTxtEnd = nTxtStart;
+ sal_uInt16 nAltEnd = nAltStart;
+
+ // Die Bereiche zwischen den nStart und nEnd ist
+ // die Differenz zwischen Alternativ- und OriginalString.
+ while( nTxtEnd < aWord.Len() && nAltEnd < aAlt.Len() &&
+ aWord.GetChar(nTxtEnd) != aAlt.GetChar(nAltEnd) )
+ {
+ ++nTxtEnd;
+ ++nAltEnd;
+ }
+
+ // Wenn ein Zeichen hinzugekommen ist, dann bemerken wir es jetzt:
+ if( nAltEnd > nTxtEnd && nAltStart == nAltEnd &&
+ aWord.GetChar( nTxtEnd ) == aAlt.GetChar(nAltEnd) )
+ {
+ ++nAltEnd;
+ ++nTxtStart;
+ ++nTxtEnd;
+ }
+
+ DBG_ASSERT( ( nAltEnd - nAltStart ) == 1, "Alternate: Falsche Annahme!" );
+
+ if ( nTxtEnd > nTxtStart )
+ cAlternateReplChar = aAlt.GetChar( nAltStart );
+ else
+ cAlternateExtraChar = aAlt.GetChar( nAltStart );
+
+ bHyphenated = sal_True;
+ nBreakPos = nWordStart + nTxtStart;
+ if ( cAlternateReplChar )
+ nBreakPos++;
+ }
+ }
+ }
+ }
+ }
+
+ #endif // !SVX_LIGHT
+
+ if ( nBreakPos <= pLine->GetStart() )
+ {
+ // keine Trenner in Zeile => abhacken !
+ nBreakPos = nMaxBreakPos;
+ // MT: I18N nextCharacters !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ if ( nBreakPos <= pLine->GetStart() )
+ nBreakPos = pLine->GetStart() + 1; // Sonst Endlosschleife!
+ }
+ }
+
+ // die angeknackste Portion ist die End-Portion
+ pLine->SetEnd( nBreakPos );
+
+ sal_uInt16 nEndPortion = SplitTextPortion( pParaPortion, nBreakPos, pLine );
+
+ if ( !bCompressBlank && !bHangingPunctuation )
+ {
+ // #96187# When justification is not SVX_ADJUST_LEFT, it's important to compress
+ // the trailing space even if there is enough room for the space...
+ // Don't check for SVX_ADJUST_LEFT, doesn't matter to compress in this case too...
+ DBG_ASSERT( nBreakPos > pLine->GetStart(), "ImpBreakLines - BreakPos not expected!" );
+ if ( pNode->GetChar( nBreakPos-1 ) == ' ' )
+ bCompressBlank = sal_True;
+ }
+
+ if ( bCompressBlank || bHangingPunctuation )
+ {
+ TextPortion* pTP = pParaPortion->GetTextPortions().GetObject( nEndPortion );
+ DBG_ASSERT( pTP->GetKind() == PORTIONKIND_TEXT, "BlankRubber: Keine TextPortion!" );
+ DBG_ASSERT( nBreakPos > pLine->GetStart(), "SplitTextPortion am Anfang der Zeile?" );
+ sal_uInt16 nPosInArray = nBreakPos - 1 - pLine->GetStart();
+ pTP->GetSize().Width() = ( nPosInArray && ( pTP->GetLen() > 1 ) ) ? pLine->GetCharPosArray()[ nPosInArray-1 ] : 0;
+ pLine->GetCharPosArray()[ nPosInArray ] = pTP->GetSize().Width();
+ }
+ else if ( bHyphenated )
+ {
+ // Eine Portion fuer den Trenner einbauen...
+ TextPortion* pHyphPortion = new TextPortion( 0 );
+ pHyphPortion->GetKind() = PORTIONKIND_HYPHENATOR;
+ String aHyphText( CH_HYPH );
+ if ( cAlternateReplChar )
+ {
+ TextPortion* pPrev = pParaPortion->GetTextPortions().GetObject( nEndPortion );
+ DBG_ASSERT( pPrev && pPrev->GetLen(), "Hyphenate: Prev portion?!" );
+ pPrev->SetLen( pPrev->GetLen() - 1 );
+ pHyphPortion->SetLen( 1 );
+ pHyphPortion->SetExtraValue( cAlternateReplChar );
+ // Breite der Portion davor korrigieren:
+ pPrev->GetSize().Width() =
+ pLine->GetCharPosArray()[ nBreakPos-1 - pLine->GetStart() - 1 ];
+ }
+ else if ( cAlternateExtraChar )
+ {
+ pHyphPortion->SetExtraValue( cAlternateExtraChar );
+ aHyphText.Insert( cAlternateExtraChar, 0 );
+ }
+
+ // Breite der Hyph-Portion ermitteln:
+ SvxFont aFont;
+ SeekCursor( pParaPortion->GetNode(), nBreakPos, aFont );
+ aFont.SetPhysFont( GetRefDevice() );
+ pHyphPortion->GetSize().Height() = GetRefDevice()->GetTextHeight();
+ pHyphPortion->GetSize().Width() = GetRefDevice()->GetTextWidth( aHyphText );
+
+ pParaPortion->GetTextPortions().Insert( pHyphPortion, ++nEndPortion );
+ }
+ pLine->SetEndPortion( nEndPortion );
+}
+
+void ImpEditEngine::ImpAdjustBlocks( ParaPortion* pParaPortion, EditLine* pLine, long nRemainingSpace )
+{
+ DBG_ASSERT( nRemainingSpace > 0, "AdjustBlocks: Etwas zuwenig..." );
+ DBG_ASSERT( pLine, "AdjustBlocks: Zeile ?!" );
+ if ( ( nRemainingSpace < 0 ) || pLine->IsEmpty() )
+ return ;
+
+ const USHORT nFirstChar = pLine->GetStart();
+ const USHORT nLastChar = pLine->GetEnd() -1; // Last zeigt dahinter
+ ContentNode* pNode = pParaPortion->GetNode();
+
+ DBG_ASSERT( nLastChar < pNode->Len(), "AdjustBlocks: Out of range!" );
+
+ // Search blanks or Kashidas...
+ SvUShorts aPositions;
+ USHORT nChar;
+ for ( nChar = nFirstChar; nChar <= nLastChar; nChar++ )
+ {
+ if ( pNode->GetChar(nChar) == ' ' )
+ {
+ // Don't use blank if language is arabic
+ LanguageType eLang = GetLanguage( EditPaM( pNode, nChar ) );
+ if ( MsLangId::getPrimaryLanguage( eLang) != LANGUAGE_ARABIC_PRIMARY_ONLY )
+ aPositions.Insert( nChar, aPositions.Count() );
+ }
+ }
+
+ // Kashidas ?
+ ImpFindKashidas( pNode, nFirstChar, nLastChar, aPositions );
+
+
+ if ( !aPositions.Count() )
+ return;
+
+ // Wenn das letzte Zeichen ein Blank ist, will ich es nicht haben!
+ // Die Breite muss auf die Blocker davor verteilt werden...
+ // Aber nicht, wenn es das einzige ist
+ if ( ( pNode->GetChar( nLastChar ) == ' ' ) && ( aPositions.Count() > 1 ) && ( MsLangId::getPrimaryLanguage( GetLanguage( EditPaM( pNode, nLastChar ) ) ) != LANGUAGE_ARABIC_PRIMARY_ONLY ) )
+ {
+ aPositions.Remove( aPositions.Count()-1, 1 );
+ USHORT nPortionStart, nPortion;
+ nPortion = pParaPortion->GetTextPortions().FindPortion( nLastChar+1, nPortionStart );
+ TextPortion* pLastPortion = pParaPortion->GetTextPortions()[ nPortion ];
+ long nRealWidth = pLine->GetCharPosArray()[nLastChar-nFirstChar];
+ long nBlankWidth = nRealWidth;
+ if ( nLastChar > nPortionStart )
+ nBlankWidth -= pLine->GetCharPosArray()[nLastChar-nFirstChar-1];
+ // Evtl. ist das Blank schon in ImpBreakLine abgezogen worden:
+ if ( nRealWidth == pLastPortion->GetSize().Width() )
+ {
+ // Beim letzten Zeichen muss die Portion hinter dem Blank aufhoeren
+ // => Korrektur vereinfachen:
+ DBG_ASSERT( ( nPortionStart + pLastPortion->GetLen() ) == ( nLastChar+1 ), "Blank doch nicht am Portion-Ende?!" );
+ pLastPortion->GetSize().Width() -= nBlankWidth;
+ nRemainingSpace += nBlankWidth;
+ }
+ pLine->GetCharPosArray()[nLastChar-nFirstChar] -= nBlankWidth;
+ }
+
+ USHORT nGaps = aPositions.Count();
+ const long nMore4Everyone = nRemainingSpace / nGaps;
+ long nSomeExtraSpace = nRemainingSpace - nMore4Everyone*nGaps;
+
+ DBG_ASSERT( nSomeExtraSpace < (long)nGaps, "AdjustBlocks: ExtraSpace zu gross" );
+ DBG_ASSERT( nSomeExtraSpace >= 0, "AdjustBlocks: ExtraSpace < 0 " );
+
+ // Die Positionen im Array und die Portion-Breiten korrigieren:
+ // Letztes Zeichen wird schon nicht mehr beachtet...
+ for ( USHORT n = 0; n < aPositions.Count(); n++ )
+ {
+ nChar = aPositions[n];
+ if ( nChar < nLastChar )
+ {
+ USHORT nPortionStart, nPortion;
+ nPortion = pParaPortion->GetTextPortions().FindPortion( nChar, nPortionStart );
+ TextPortion* pLastPortion = pParaPortion->GetTextPortions()[ nPortion ];
+
+ // Die Breite der Portion:
+ pLastPortion->GetSize().Width() += nMore4Everyone;
+ if ( nSomeExtraSpace )
+ pLastPortion->GetSize().Width()++;
+
+ // Correct positions in array
+ // Even for kashidas just change positions, VCL will then draw the kashida automaticly
+ USHORT nPortionEnd = nPortionStart + pLastPortion->GetLen();
+ for ( USHORT _n = nChar; _n < nPortionEnd; _n++ )
+ {
+ pLine->GetCharPosArray()[_n-nFirstChar] += nMore4Everyone;
+ if ( nSomeExtraSpace )
+ pLine->GetCharPosArray()[_n-nFirstChar]++;
+ }
+
+ if ( nSomeExtraSpace )
+ nSomeExtraSpace--;
+ }
+ }
+
+ // Now the text width contains the extra width...
+ pLine->SetTextWidth( pLine->GetTextWidth() + nRemainingSpace );
+}
+
+void ImpEditEngine::ImpFindKashidas( ContentNode* pNode, USHORT nStart, USHORT nEnd, SvUShorts& rArray )
+{
+ // the search has to be performed on a per word base
+
+ EditSelection aWordSel( EditPaM( pNode, nStart ) );
+ aWordSel = SelectWord( aWordSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
+ if ( aWordSel.Min().GetIndex() < nStart )
+ aWordSel.Min().GetIndex() = nStart;
+
+ while ( ( aWordSel.Min().GetNode() == pNode ) && ( aWordSel.Min().GetIndex() < nEnd ) )
+ {
+ USHORT nSavPos = aWordSel.Max().GetIndex();
+ if ( aWordSel.Max().GetIndex() > nEnd )
+ aWordSel.Max().GetIndex() = nEnd;
+
+ String aWord = GetSelected( aWordSel );
+
+ // restore selection for proper iteration at the end of the function
+ aWordSel.Max().GetIndex() = nSavPos;
+
+ xub_StrLen nIdx = 0;
+ xub_StrLen nKashidaPos = STRING_LEN;
+ xub_Unicode cCh;
+ xub_Unicode cPrevCh = 0;
+
+ while ( nIdx < aWord.Len() )
+ {
+ cCh = aWord.GetChar( nIdx );
+
+ // 1. Priority:
+ // after user inserted kashida
+ if ( 0x640 == cCh )
+ {
+ nKashidaPos = aWordSel.Min().GetIndex() + nIdx;
+ break;
+ }
+
+ // 2. Priority:
+ // after a Seen or Sad
+ if ( nIdx + 1 < aWord.Len() &&
+ ( 0x633 == cCh || 0x635 == cCh ) )
+ {
+ nKashidaPos = aWordSel.Min().GetIndex() + nIdx;
+ break;
+ }
+
+ // 3. Priority:
+ // before final form of Teh Marbuta, Hah, Dal
+ // 4. Priority:
+ // before final form of Alef, Lam or Kaf
+ if ( nIdx && nIdx + 1 == aWord.Len() &&
+ ( 0x629 == cCh || 0x62D == cCh || 0x62F == cCh ||
+ 0x627 == cCh || 0x644 == cCh || 0x643 == cCh ) )
+ {
+ DBG_ASSERT( 0 != cPrevCh, "No previous character" );
+
+ // check if character is connectable to previous character,
+ if ( lcl_ConnectToPrev( cCh, cPrevCh ) )
+ {
+ nKashidaPos = aWordSel.Min().GetIndex() + nIdx - 1;
+ break;
+ }
+ }
+
+ // 5. Priority:
+ // before media Bah
+ if ( nIdx && nIdx + 1 < aWord.Len() && 0x628 == cCh )
+ {
+ DBG_ASSERT( 0 != cPrevCh, "No previous character" );
+
+ // check if next character is Reh, Yeh or Alef Maksura
+ xub_Unicode cNextCh = aWord.GetChar( nIdx + 1 );
+
+ if ( 0x631 == cNextCh || 0x64A == cNextCh ||
+ 0x649 == cNextCh )
+ {
+ // check if character is connectable to previous character,
+ if ( lcl_ConnectToPrev( cCh, cPrevCh ) )
+ nKashidaPos = aWordSel.Min().GetIndex() + nIdx - 1;
+ }
+ }
+
+ // 6. Priority:
+ // other connecting possibilities
+ if ( nIdx && nIdx + 1 == aWord.Len() &&
+ 0x60C <= cCh && 0x6FE >= cCh )
+ {
+ DBG_ASSERT( 0 != cPrevCh, "No previous character" );
+
+ // check if character is connectable to previous character,
+ if ( lcl_ConnectToPrev( cCh, cPrevCh ) )
+ {
+ // only choose this position if we did not find
+ // a better one:
+ if ( STRING_LEN == nKashidaPos )
+ nKashidaPos = aWordSel.Min().GetIndex() + nIdx - 1;
+ break;
+ }
+ }
+
+ // Do not consider Fathatan, Dammatan, Kasratan, Fatha,
+ // Damma, Kasra, Shadda and Sukun when checking if
+ // a character can be connected to previous character.
+ if ( cCh < 0x64B || cCh > 0x652 )
+ cPrevCh = cCh;
+
+ ++nIdx;
+ } // end of current word
+
+ if ( STRING_LEN != nKashidaPos )
+ rArray.Insert( nKashidaPos, rArray.Count() );
+
+ aWordSel = WordRight( aWordSel.Max(), ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
+ aWordSel = SelectWord( aWordSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
+ }
+}
+
+sal_uInt16 ImpEditEngine::SplitTextPortion( ParaPortion* pPortion, sal_uInt16 nPos, EditLine* pCurLine )
+{
+ DBG_ASSERT( pPortion, "SplitTextPortion: Welche ?" );
+
+ // Die Portion bei nPos wird geplittet, wenn bei nPos nicht
+ // sowieso ein Wechsel ist
+ if ( nPos == 0 )
+ return 0;
+
+ sal_uInt16 nSplitPortion;
+ sal_uInt16 nTmpPos = 0;
+ TextPortion* pTextPortion = 0;
+ sal_uInt16 nPortions = pPortion->GetTextPortions().Count();
+ for ( nSplitPortion = 0; nSplitPortion < nPortions; nSplitPortion++ )
+ {
+ TextPortion* pTP = pPortion->GetTextPortions().GetObject(nSplitPortion);
+ nTmpPos = nTmpPos + pTP->GetLen();
+ if ( nTmpPos >= nPos )
+ {
+ if ( nTmpPos == nPos ) // dann braucht nichts geteilt werden
+ {
+ // Skip Portions with ExtraSpace
+// while ( ( (nSplitPortion+1) < nPortions ) && (pPortion->GetTextPortions().GetObject(nSplitPortion+1)->GetKind() == PORTIONKIND_EXTRASPACE ) )
+// nSplitPortion++;
+
+ return nSplitPortion;
+ }
+ pTextPortion = pTP;
+ break;
+ }
+ }
+
+ DBG_ASSERT( pTextPortion, "Position ausserhalb des Bereichs!" );
+ DBG_ASSERT( pTextPortion->GetKind() == PORTIONKIND_TEXT, "SplitTextPortion: Keine TextPortion!" );
+
+ sal_uInt16 nOverlapp = nTmpPos - nPos;
+ pTextPortion->GetLen() = pTextPortion->GetLen() - nOverlapp;
+ TextPortion* pNewPortion = new TextPortion( nOverlapp );
+ pPortion->GetTextPortions().Insert( pNewPortion, nSplitPortion+1 );
+ // Groessen setzen:
+ if ( pCurLine )
+ {
+ // Kein neues GetTextSize, sondern Werte aus Array verwenden:
+ DBG_ASSERT( nPos > pCurLine->GetStart(), "SplitTextPortion am Anfang der Zeile?" );
+ pTextPortion->GetSize().Width() = pCurLine->GetCharPosArray()[ nPos-pCurLine->GetStart()-1 ];
+
+ if ( pTextPortion->GetExtraInfos() && pTextPortion->GetExtraInfos()->bCompressed )
+ {
+ // We need the original size from the portion
+ USHORT nTxtPortionStart = pPortion->GetTextPortions().GetStartPos( nSplitPortion );
+ SvxFont aTmpFont( pPortion->GetNode()->GetCharAttribs().GetDefFont() );
+ SeekCursor( pPortion->GetNode(), nTxtPortionStart+1, aTmpFont );
+ aTmpFont.SetPhysFont( GetRefDevice() );
+ GetRefDevice()->Push( PUSH_TEXTLANGUAGE );
+ ImplInitDigitMode( GetRefDevice(), 0, 0, 0, aTmpFont.GetLanguage() );
+ Size aSz = aTmpFont.QuickGetTextSize( GetRefDevice(), *pPortion->GetNode(), nTxtPortionStart, pTextPortion->GetLen(), NULL );
+ GetRefDevice()->Pop();
+ pTextPortion->GetExtraInfos()->nOrgWidth = aSz.Width();
+ }
+ }
+ else
+ pTextPortion->GetSize().Width() = (-1);
+
+ return nSplitPortion;
+}
+
+void ImpEditEngine::CreateTextPortions( ParaPortion* pParaPortion, sal_uInt16& rStart /* , sal_Bool bCreateBlockPortions */ )
+{
+ sal_uInt16 nStartPos = rStart;
+ ContentNode* pNode = pParaPortion->GetNode();
+ DBG_ASSERT( pNode->Len(), "CreateTextPortions sollte nicht fuer leere Absaetze verwendet werden!" );
+
+ SortedPositions aPositions;
+ aPositions.Insert( (sal_uInt32) 0 );
+
+ sal_uInt16 nAttr = 0;
+ EditCharAttrib* pAttrib = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
+ while ( pAttrib )
+ {
+ // Start und Ende in das Array eintragen...
+ // Die InsertMethode laesst keine doppelten Werte zu....
+ aPositions.Insert( pAttrib->GetStart() );
+ aPositions.Insert( pAttrib->GetEnd() );
+ nAttr++;
+ pAttrib = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
+ }
+ aPositions.Insert( pNode->Len() );
+
+ if ( !pParaPortion->aScriptInfos.Count() )
+ ((ImpEditEngine*)this)->InitScriptTypes( GetParaPortions().GetPos( pParaPortion ) );
+
+ const ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
+ for ( USHORT nT = 0; nT < rTypes.Count(); nT++ )
+ aPositions.Insert( rTypes[nT].nStartPos );
+
+ const WritingDirectionInfos& rWritingDirections = pParaPortion->aWritingDirectionInfos;
+ for ( USHORT nD = 0; nD < rWritingDirections.Count(); nD++ )
+ aPositions.Insert( rWritingDirections[nD].nStartPos );
+
+ if ( mpIMEInfos && mpIMEInfos->nLen && mpIMEInfos->pAttribs && ( mpIMEInfos->aPos.GetNode() == pNode ) )
+ {
+ sal_uInt16 nLastAttr = 0xFFFF;
+ for( sal_uInt16 n = 0; n < mpIMEInfos->nLen; n++ )
+ {
+ if ( mpIMEInfos->pAttribs[n] != nLastAttr )
+ {
+ aPositions.Insert( mpIMEInfos->aPos.GetIndex() + n );
+ nLastAttr = mpIMEInfos->pAttribs[n];
+ }
+ }
+ aPositions.Insert( mpIMEInfos->aPos.GetIndex() + mpIMEInfos->nLen );
+ }
+
+ // Ab ... loeschen:
+ // Leider muss die Anzahl der TextPortions mit aPositions.Count()
+ // nicht uebereinstimmen, da evtl. Zeilenumbrueche...
+ sal_uInt16 nPortionStart = 0;
+ sal_uInt16 nInvPortion = 0;
+ sal_uInt16 nP;
+ for ( nP = 0; nP < pParaPortion->GetTextPortions().Count(); nP++ )
+ {
+ TextPortion* pTmpPortion = pParaPortion->GetTextPortions().GetObject(nP);
+ nPortionStart = nPortionStart + pTmpPortion->GetLen();
+ if ( nPortionStart >= nStartPos )
+ {
+ nPortionStart = nPortionStart - pTmpPortion->GetLen();
+ rStart = nPortionStart;
+ nInvPortion = nP;
+ break;
+ }
+ }
+ DBG_ASSERT( nP < pParaPortion->GetTextPortions().Count() || !pParaPortion->GetTextPortions().Count(), "Nichts zum loeschen: CreateTextPortions" );
+ if ( nInvPortion && ( nPortionStart+pParaPortion->GetTextPortions().GetObject(nInvPortion)->GetLen() > nStartPos ) )
+ {
+ // lieber eine davor...
+ // Aber nur wenn es mitten in der Portion war, sonst ist es evtl.
+ // die einzige in der Zeile davor !
+ nInvPortion--;
+ nPortionStart = nPortionStart - pParaPortion->GetTextPortions().GetObject(nInvPortion)->GetLen();
+ }
+ pParaPortion->GetTextPortions().DeleteFromPortion( nInvPortion );
+
+ // Eine Portion kann auch durch einen Zeilenumbruch entstanden sein:
+ aPositions.Insert( nPortionStart );
+
+ sal_uInt16 nInvPos;
+#ifdef DBG_UTIL
+ sal_Bool bFound =
+#endif
+ aPositions.Seek_Entry( nPortionStart, &nInvPos );
+
+ DBG_ASSERT( bFound && ( nInvPos < (aPositions.Count()-1) ), "InvPos ?!" );
+ for ( sal_uInt16 i = nInvPos+1; i < aPositions.Count(); i++ )
+ {
+ TextPortion* pNew = new TextPortion( (sal_uInt16)aPositions[i] - (sal_uInt16)aPositions[i-1] );
+ pParaPortion->GetTextPortions().Insert( pNew, pParaPortion->GetTextPortions().Count());
+ }
+
+ DBG_ASSERT( pParaPortion->GetTextPortions().Count(), "Keine Portions?!" );
+#ifdef EDITDEBUG
+ DBG_ASSERT( pParaPortion->DbgCheckTextPortions(), "Portions kaputt?" );
+#endif
+}
+
+void ImpEditEngine::RecalcTextPortion( ParaPortion* pParaPortion, sal_uInt16 nStartPos, short nNewChars )
+{
+ DBG_ASSERT( pParaPortion->GetTextPortions().Count(), "Keine Portions!" );
+ DBG_ASSERT( nNewChars, "RecalcTextPortion mit Diff == 0" );
+
+ ContentNode* const pNode = pParaPortion->GetNode();
+ if ( nNewChars > 0 )
+ {
+ // Wenn an nStartPos ein Attribut beginnt/endet, faengt eine neue Portion
+ // an, ansonsten wird die Portion an nStartPos erweitert.
+
+ if ( pNode->GetCharAttribs().HasBoundingAttrib( nStartPos ) || IsScriptChange( EditPaM( pNode, nStartPos ) ) )
+ {
+ sal_uInt16 nNewPortionPos = 0;
+ if ( nStartPos )
+ nNewPortionPos = SplitTextPortion( pParaPortion, nStartPos ) + 1;
+
+ // Eine leere Portion kann hier stehen, wenn der Absatz leer war,
+ // oder eine Zeile durch einen harten Zeilenumbruch entstanden ist.
+ if ( ( nNewPortionPos < pParaPortion->GetTextPortions().Count() ) &&
+ !pParaPortion->GetTextPortions()[nNewPortionPos]->GetLen() )
+ {
+ DBG_ASSERT( pParaPortion->GetTextPortions()[nNewPortionPos]->GetKind() == PORTIONKIND_TEXT, "Leere Portion war keine TextPortion!" );
+ USHORT & r =
+ pParaPortion->GetTextPortions()[nNewPortionPos]->GetLen();
+ r = r + nNewChars;
+ }
+ else
+ {
+ TextPortion* pNewPortion = new TextPortion( nNewChars );
+ pParaPortion->GetTextPortions().Insert( pNewPortion, nNewPortionPos );
+ }
+ }
+ else
+ {
+ sal_uInt16 nPortionStart;
+ const sal_uInt16 nTP = pParaPortion->GetTextPortions().
+ FindPortion( nStartPos, nPortionStart );
+ TextPortion* const pTP = pParaPortion->GetTextPortions()[ nTP ];
+ DBG_ASSERT( pTP, "RecalcTextPortion: Portion nicht gefunden" );
+ pTP->GetLen() = pTP->GetLen() + nNewChars;
+ pTP->GetSize().Width() = (-1);
+ }
+ }
+ else
+ {
+ // Portion schrumpfen oder ggf. entfernen.
+ // Vor Aufruf dieser Methode muss sichergestellt sein, dass
+ // keine Portions in dem geloeschten Bereich lagen!
+
+ // Es darf keine reinragende oder im Bereich startende Portion geben,
+ // also muss nStartPos <= nPos <= nStartPos - nNewChars(neg.) sein
+ sal_uInt16 nPortion = 0;
+ sal_uInt16 nPos = 0;
+ sal_uInt16 nEnd = nStartPos-nNewChars;
+ sal_uInt16 nPortions = pParaPortion->GetTextPortions().Count();
+ TextPortion* pTP = 0;
+ for ( nPortion = 0; nPortion < nPortions; nPortion++ )
+ {
+ pTP = pParaPortion->GetTextPortions()[ nPortion ];
+ if ( ( nPos+pTP->GetLen() ) > nStartPos )
+ {
+ DBG_ASSERT( nPos <= nStartPos, "Start falsch!" );
+ DBG_ASSERT( nPos+pTP->GetLen() >= nEnd, "End falsch!" );
+ break;
+ }
+ nPos = nPos + pTP->GetLen();
+ }
+ DBG_ASSERT( pTP, "RecalcTextPortion: Portion nicht gefunden" );
+ if ( ( nPos == nStartPos ) && ( (nPos+pTP->GetLen()) == nEnd ) )
+ {
+ // Portion entfernen;
+ BYTE nType = pTP->GetKind();
+ pParaPortion->GetTextPortions().Remove( nPortion );
+ delete pTP;
+ if ( nType == PORTIONKIND_LINEBREAK )
+ {
+ TextPortion* pNext = pParaPortion->GetTextPortions()[ nPortion ];
+ if ( pNext && !pNext->GetLen() )
+ {
+ // Dummy-Portion entfernen
+ pParaPortion->GetTextPortions().Remove( nPortion );
+ delete pNext;
+ }
+ }
+ }
+ else
+ {
+ DBG_ASSERT( pTP->GetLen() > (-nNewChars), "Portion zu klein zum schrumpfen!" );
+ pTP->GetLen() = pTP->GetLen() + nNewChars;
+ }
+
+ // ganz am Schluss darf keine HYPHENATOR-Portion stehen bleiben...
+ DBG_ASSERT( pParaPortion->GetTextPortions().Count(), "RecalcTextPortions: Keine mehr da!" );
+ sal_uInt16 nLastPortion = pParaPortion->GetTextPortions().Count() - 1;
+ pTP = pParaPortion->GetTextPortions().GetObject( nLastPortion );
+ if ( pTP->GetKind() == PORTIONKIND_HYPHENATOR )
+ {
+ // Portion wegschmeissen, ggf. die davor korrigieren, wenn
+ // die Hyph-Portion ein Zeichen geschluckt hat...
+ pParaPortion->GetTextPortions().Remove( nLastPortion );
+ if ( nLastPortion && pTP->GetLen() )
+ {
+ TextPortion* pPrev = pParaPortion->GetTextPortions().GetObject( nLastPortion - 1 );
+ DBG_ASSERT( pPrev->GetKind() == PORTIONKIND_TEXT, "Portion?!" );
+ pPrev->SetLen( pPrev->GetLen() + pTP->GetLen() );
+ pPrev->GetSize().Width() = (-1);
+ }
+ delete pTP;
+ }
+ }
+#ifdef EDITDEBUG
+ DBG_ASSERT( pParaPortion->DbgCheckTextPortions(), "Portions kaputt?" );
+#endif
+}
+
+void ImpEditEngine::SetTextRanger( TextRanger* pRanger )
+{
+ if ( pTextRanger != pRanger )
+ {
+ delete pTextRanger;
+ pTextRanger = pRanger;
+
+ for ( sal_uInt16 nPara = 0; nPara < GetParaPortions().Count(); nPara++ )
+ {
+ ParaPortion* pParaPortion = GetParaPortions().GetObject( nPara );
+ pParaPortion->MarkSelectionInvalid( 0, pParaPortion->GetNode()->Len() );
+ pParaPortion->GetLines().Reset();
+ }
+
+ FormatFullDoc();
+ UpdateViews( GetActiveView() );
+ if ( GetUpdateMode() && GetActiveView() )
+ pActiveView->ShowCursor( sal_False, sal_False );
+ }
+}
+
+void ImpEditEngine::SetVertical( BOOL bVertical )
+{
+ if ( IsVertical() != bVertical )
+ {
+ GetEditDoc().SetVertical( bVertical );
+ sal_Bool bUseCharAttribs = ( aStatus.GetControlWord() & EE_CNTRL_USECHARATTRIBS ) ? sal_True : sal_False;
+ GetEditDoc().CreateDefFont( bUseCharAttribs );
+ if ( IsFormatted() )
+ {
+ FormatFullDoc();
+ UpdateViews( GetActiveView() );
+ }
+ }
+}
+
+void ImpEditEngine::SetFixedCellHeight( BOOL bUseFixedCellHeight )
+{
+ if ( IsFixedCellHeight() != bUseFixedCellHeight )
+ {
+ GetEditDoc().SetFixedCellHeight( bUseFixedCellHeight );
+ if ( IsFormatted() )
+ {
+ FormatFullDoc();
+ UpdateViews( GetActiveView() );
+ }
+ }
+}
+
+void ImpEditEngine::SeekCursor( ContentNode* pNode, sal_uInt16 nPos, SvxFont& rFont, OutputDevice* pOut, sal_uInt16 nIgnoreWhich )
+{
+ // Es war mal geplant, SeekCursor( nStartPos, nEndPos, ... ), damit nur
+ // ab der StartPosition neu gesucht wird.
+ // Problem: Es mussten zwei Listen beruecksichtigt/gefuehrt werden:
+ // OrderedByStart,OrderedByEnd.
+
+ if ( nPos > pNode->Len() )
+ nPos = pNode->Len();
+
+ rFont = pNode->GetCharAttribs().GetDefFont();
+
+ short nScriptType = GetScriptType( EditPaM( pNode, nPos ) );
+ if ( ( nScriptType == i18n::ScriptType::ASIAN ) || ( nScriptType == i18n::ScriptType::COMPLEX ) )
+ {
+ const SvxFontItem& rFontItem = (const SvxFontItem&)pNode->GetContentAttribs().GetItem( GetScriptItemId( EE_CHAR_FONTINFO, nScriptType ) );
+ rFont.SetName( rFontItem.GetFamilyName() );
+ rFont.SetFamily( rFontItem.GetFamily() );
+ rFont.SetPitch( rFontItem.GetPitch() );
+ rFont.SetCharSet( rFontItem.GetCharSet() );
+ Size aSz( rFont.GetSize() );
+ aSz.Height() = ((const SvxFontHeightItem&)pNode->GetContentAttribs().GetItem( GetScriptItemId( EE_CHAR_FONTHEIGHT, nScriptType ) ) ).GetHeight();
+ rFont.SetSize( aSz );
+ rFont.SetWeight( ((const SvxWeightItem&)pNode->GetContentAttribs().GetItem( GetScriptItemId( EE_CHAR_WEIGHT, nScriptType ))).GetWeight() );
+ rFont.SetItalic( ((const SvxPostureItem&)pNode->GetContentAttribs().GetItem( GetScriptItemId( EE_CHAR_ITALIC, nScriptType ))).GetPosture() );
+ rFont.SetLanguage( ((const SvxLanguageItem&)pNode->GetContentAttribs().GetItem( GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType ))).GetLanguage() );
+ }
+
+ sal_uInt16 nRelWidth = ((const SvxCharScaleWidthItem&)pNode->GetContentAttribs().GetItem( EE_CHAR_FONTWIDTH)).GetValue();
+
+ if ( pOut )
+ {
+ const SvxUnderlineItem& rTextLineColor = (const SvxUnderlineItem&)pNode->GetContentAttribs().GetItem( EE_CHAR_UNDERLINE );
+ if ( rTextLineColor.GetColor() != COL_TRANSPARENT )
+ pOut->SetTextLineColor( rTextLineColor.GetColor() );
+ else
+ pOut->SetTextLineColor();
+ }
+
+ if ( pOut )
+ {
+ const SvxOverlineItem& rOverlineColor = (const SvxOverlineItem&)pNode->GetContentAttribs().GetItem( EE_CHAR_OVERLINE );
+ if ( rOverlineColor.GetColor() != COL_TRANSPARENT )
+ pOut->SetOverlineColor( rOverlineColor.GetColor() );
+ else
+ pOut->SetOverlineColor();
+ }
+
+ const SvxLanguageItem* pCJKLanguageItem = NULL;
+
+ if ( aStatus.UseCharAttribs() )
+ {
+ const CharAttribArray& rAttribs = pNode->GetCharAttribs().GetAttribs();
+ sal_uInt16 nAttr = 0;
+ EditCharAttrib* pAttrib = GetAttrib( rAttribs, nAttr );
+ while ( pAttrib && ( pAttrib->GetStart() <= nPos ) )
+ {
+ // Beim Seeken nicht die Attr beruecksichtigen, die dort beginnen!
+ // Leere Attribute werden beruecksichtigt( verwendet), da diese
+ // gerade eingestellt wurden.
+ // 12.4.95: Doch keine Leeren Attribute verwenden:
+ // - Wenn gerade eingestellt und leer => keine Auswirkung auf Font
+ // In einem leeren Absatz eingestellte Zeichen werden sofort wirksam.
+ if ( ( pAttrib->Which() != nIgnoreWhich ) &&
+ ( ( ( pAttrib->GetStart() < nPos ) && ( pAttrib->GetEnd() >= nPos ) )
+ || ( !pNode->Len() ) ) )
+ {
+ DBG_ASSERT( ( pAttrib->Which() >= EE_CHAR_START ) && ( pAttrib->Which() <= EE_FEATURE_END ), "Unglueltiges Attribut in Seek() " );
+ if ( IsScriptItemValid( pAttrib->Which(), nScriptType ) )
+ {
+ pAttrib->SetFont( rFont, pOut );
+ // #i1550# hard color attrib should win over text color from field
+ if ( pAttrib->Which() == EE_FEATURE_FIELD )
+ {
+ EditCharAttrib* pColorAttr = pNode->GetCharAttribs().FindAttrib( EE_CHAR_COLOR, nPos );
+ if ( pColorAttr )
+ pColorAttr->SetFont( rFont, pOut );
+ }
+ }
+ if ( pAttrib->Which() == EE_CHAR_FONTWIDTH )
+ nRelWidth = ((const SvxCharScaleWidthItem*)pAttrib->GetItem())->GetValue();
+ if ( pAttrib->Which() == EE_CHAR_LANGUAGE_CJK )
+ pCJKLanguageItem = (const SvxLanguageItem*) pAttrib->GetItem();
+ }
+ pAttrib = GetAttrib( rAttribs, ++nAttr );
+ }
+ }
+
+ if ( !pCJKLanguageItem )
+ pCJKLanguageItem = (const SvxLanguageItem*) &pNode->GetContentAttribs().GetItem( EE_CHAR_LANGUAGE_CJK );
+
+ rFont.SetCJKContextLanguage( pCJKLanguageItem->GetLanguage() );
+
+ if ( rFont.GetKerning() && IsKernAsianPunctuation() && ( nScriptType == i18n::ScriptType::ASIAN ) )
+ rFont.SetKerning( rFont.GetKerning() | KERNING_ASIAN );
+
+ if ( aStatus.DoNotUseColors() )
+ {
+ // Hack fuer DL,weil JOE staendig die Pooldefaults verbiegt!
+ // const SvxColorItem& rColorItem = (const SvxColorItem&)aEditDoc.GetItemPool().GetDefaultItem( EE_CHAR_COLOR );
+ rFont.SetColor( /* rColorItem.GetValue() */ COL_BLACK );
+ }
+
+ if ( aStatus.DoStretch() || ( nRelWidth != 100 ) )
+ {
+ // Fuer das aktuelle Ausgabegeraet, weil es sonst bei einem
+ // Drucker als RefDev auf dem Bildschirm #?!@' aussieht!
+ OutputDevice* pDev = pOut ? pOut : GetRefDevice();
+ rFont.SetPhysFont( pDev );
+ FontMetric aMetric( pDev->GetFontMetric() );
+ // Fuer die Hoehe nicht die Metriken nehmen, da das bei
+ // Hoch-/Tiefgestellt schief geht.
+ Size aRealSz( aMetric.GetSize().Width(), rFont.GetSize().Height() );
+ if ( aStatus.DoStretch() )
+ {
+ if ( nStretchY != 100 )
+ {
+ aRealSz.Height() *= nStretchY;
+ aRealSz.Height() /= 100;
+ }
+ if ( nStretchX != 100 )
+ {
+ aRealSz.Width() *= nStretchX;
+ aRealSz.Width() /= 100;
+
+ // Auch das Kerning: (long wegen Zwischenergebnis)
+ long nKerning = rFont.GetFixKerning();
+/*
+ Die Ueberlegung war: Wenn neg. Kerning, aber StretchX = 200
+ => Nicht das Kerning verdoppelt, also die Buchstaben weiter
+ zusammenziehen
+ ---------------------------
+ Kern StretchX =>Kern
+ ---------------------------
+ >0 <100 < (Proportional)
+ <0 <100 < (Proportional)
+ >0 >100 > (Proportional)
+ <0 >100 < (Der Betrag, also Antiprop)
+*/
+ if ( ( nKerning < 0 ) && ( nStretchX > 100 ) )
+ {
+ // Antiproportional
+ nKerning *= 100;
+ nKerning /= nStretchX;
+ }
+ else if ( nKerning )
+ {
+ // Proportional
+ nKerning *= nStretchX;
+ nKerning /= 100;
+ }
+ rFont.SetFixKerning( (short)nKerning );
+ }
+ }
+ if ( nRelWidth != 100 )
+ {
+ aRealSz.Width() *= nRelWidth;
+ aRealSz.Width() /= 100;
+ }
+ rFont.SetSize( aRealSz );
+ // Font wird nicht restauriert...
+ }
+
+ if ( ( ( rFont.GetColor() == COL_AUTO ) || ( IsForceAutoColor() ) ) && pOut )
+ {
+ // #i75566# Do not use AutoColor when printing OR Pdf export
+ const bool bPrinting(OUTDEV_PRINTER == pOut->GetOutDevType());
+ const bool bPDFExporting(0 != pOut->GetPDFWriter());
+
+ if ( IsAutoColorEnabled() && !bPrinting && !bPDFExporting)
+ {
+ // Never use WindowTextColor on the printer
+ rFont.SetColor( GetAutoColor() );
+ }
+ else
+ {
+ if ( ( GetBackgroundColor() != COL_AUTO ) && GetBackgroundColor().IsDark() )
+ rFont.SetColor( COL_WHITE );
+ else
+ rFont.SetColor( COL_BLACK );
+ }
+ }
+
+ if ( mpIMEInfos && mpIMEInfos->pAttribs && ( mpIMEInfos->aPos.GetNode() == pNode ) &&
+ ( nPos > mpIMEInfos->aPos.GetIndex() ) && ( nPos <= ( mpIMEInfos->aPos.GetIndex() + mpIMEInfos->nLen ) ) )
+ {
+ sal_uInt16 nAttr = mpIMEInfos->pAttribs[ nPos - mpIMEInfos->aPos.GetIndex() - 1 ];
+ if ( nAttr & EXTTEXTINPUT_ATTR_UNDERLINE )
+ rFont.SetUnderline( UNDERLINE_SINGLE );
+ else if ( nAttr & EXTTEXTINPUT_ATTR_BOLDUNDERLINE )
+ rFont.SetUnderline( UNDERLINE_BOLD );
+ else if ( nAttr & EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE )
+ rFont.SetUnderline( UNDERLINE_DOTTED );
+ else if ( nAttr & EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE )
+ rFont.SetUnderline( UNDERLINE_DOTTED );
+ else if ( nAttr & EXTTEXTINPUT_ATTR_REDTEXT )
+ rFont.SetColor( Color( COL_RED ) );
+ else if ( nAttr & EXTTEXTINPUT_ATTR_HALFTONETEXT )
+ rFont.SetColor( Color( COL_LIGHTGRAY ) );
+ if ( nAttr & EXTTEXTINPUT_ATTR_HIGHLIGHT )
+ {
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ rFont.SetColor( rStyleSettings.GetHighlightTextColor() );
+ rFont.SetFillColor( rStyleSettings.GetHighlightColor() );
+ rFont.SetTransparent( FALSE );
+ }
+ else if ( nAttr & EXTTEXTINPUT_ATTR_GRAYWAVELINE )
+ {
+ rFont.SetUnderline( UNDERLINE_WAVE );
+ if( pOut )
+ pOut->SetTextLineColor( Color( COL_LIGHTGRAY ) );
+ }
+ }
+}
+
+void ImpEditEngine::RecalcFormatterFontMetrics( FormatterFontMetric& rCurMetrics, SvxFont& rFont )
+{
+ // Fuer Zeilenhoehe bei Hoch/Tief erstmal ohne Propr!
+ sal_uInt16 nPropr = rFont.GetPropr();
+ DBG_ASSERT( ( nPropr == 100 ) || rFont.GetEscapement(), "Propr ohne Escape?!" );
+ if ( nPropr != 100 )
+ {
+ rFont.SetPropr( 100 );
+ rFont.SetPhysFont( pRefDev );
+ }
+ sal_uInt16 nAscent, nDescent;
+
+ FontMetric aMetric( pRefDev->GetFontMetric() );
+ nAscent = (sal_uInt16)aMetric.GetAscent();
+ if ( IsAddExtLeading() )
+ nAscent = sal::static_int_cast< sal_uInt16 >(
+ nAscent + aMetric.GetExtLeading() );
+ nDescent = (sal_uInt16)aMetric.GetDescent();
+
+ if ( IsFixedCellHeight() )
+ {
+/* creating correct proportional ascent and descent values lead to problems if different fonts are used
+ in the same portion, it results in a bigger linespacing.
+ sal_Int32 f = nAscent + nDescent;
+ if ( f )
+ {
+ sal_Int32 nHeight = ImplCalculateFontIndependentLineSpacing( rFont.GetHeight() );
+ nAscent = (sal_Int16)(( nHeight * nAscent ) / f );
+ nDescent = (sal_Int16)(nHeight - nAscent);
+ }
+*/
+ nAscent = sal::static_int_cast< sal_uInt16 >( rFont.GetHeight() );
+ nDescent= sal::static_int_cast< sal_uInt16 >( ImplCalculateFontIndependentLineSpacing( rFont.GetHeight() ) - nAscent );
+ }
+ else
+ {
+ sal_uInt16 nIntLeading = ( aMetric.GetIntLeading() > 0 ) ? (sal_uInt16)aMetric.GetIntLeading() : 0;
+ // Fonts ohne Leading bereiten Probleme
+ if ( ( nIntLeading == 0 ) && ( pRefDev->GetOutDevType() == OUTDEV_PRINTER ) )
+ {
+ // Da schaun wir mal, was fuer eine Leading ich auf dem
+ // Bildschirm erhalte
+ VirtualDevice* pVDev = GetVirtualDevice( pRefDev->GetMapMode(), pRefDev->GetDrawMode() );
+ rFont.SetPhysFont( pVDev );
+ aMetric = pVDev->GetFontMetric();
+
+ // Damit sich die Leading nicht wieder rausrechnet,
+ // wenn die ganze Zeile den Font hat, nTmpLeading.
+
+ // 4/96: Kommt bei HP Laserjet 4V auch nicht hin
+ // => Werte komplett vom Bildschirm holen.
+ // sal_uInt16 nTmpLeading = (sal_uInt16)aMetric.GetLeading();
+ // nAscent += nTmpLeading;
+ nAscent = (sal_uInt16)aMetric.GetAscent();
+ nDescent = (sal_uInt16)aMetric.GetDescent();
+ // nLeading = (sal_uInt16)aMetric.GetLeading();
+ }
+ }
+ if ( nAscent > rCurMetrics.nMaxAscent )
+ rCurMetrics.nMaxAscent = nAscent;
+ if ( nDescent > rCurMetrics.nMaxDescent )
+ rCurMetrics.nMaxDescent= nDescent;
+ // Sonderbehandlung Hoch/Tief:
+ if ( rFont.GetEscapement() )
+ {
+ // Jetzt unter Beruecksichtigung von Escape/Propr
+ // Ascent oder Descent ggf vergroessern
+ short nDiff = (short)(rFont.GetSize().Height()*rFont.GetEscapement()/100L);
+ if ( rFont.GetEscapement() > 0 )
+ {
+ nAscent = (sal_uInt16) (((long)nAscent)*nPropr/100 + nDiff);
+ if ( nAscent > rCurMetrics.nMaxAscent )
+ rCurMetrics.nMaxAscent = nAscent;
+ }
+ else // muss < 0 sein
+ {
+ nDescent = (sal_uInt16) (((long)nDescent)*nPropr/100 - nDiff);
+ if ( nDescent > rCurMetrics.nMaxDescent )
+ rCurMetrics.nMaxDescent= nDescent;
+ }
+ }
+}
+
+void ImpEditEngine::Paint( OutputDevice* pOutDev, Rectangle aClipRec, Point aStartPos, sal_Bool bStripOnly, short nOrientation )
+{
+ if ( !GetUpdateMode() && !bStripOnly )
+ return;
+
+ if ( !IsFormatted() )
+ FormatDoc();
+
+ long nFirstVisXPos = - pOutDev->GetMapMode().GetOrigin().X();
+ long nFirstVisYPos = - pOutDev->GetMapMode().GetOrigin().Y();
+
+ EditLine* pLine;
+ Point aTmpPos;
+ Point aRedLineTmpPos;
+ DBG_ASSERT( GetParaPortions().Count(), "Keine ParaPortion?!" );
+ SvxFont aTmpFont( GetParaPortions()[0]->GetNode()->GetCharAttribs().GetDefFont() );
+ Font aOldFont( pOutDev->GetFont() );
+ vcl::PDFExtOutDevData* pPDFExtOutDevData = PTR_CAST( vcl::PDFExtOutDevData, pOutDev->GetExtOutDevData() );
+
+ // Bei gedrehtem Text wird aStartPos als TopLeft angesehen, da andere
+ // Informationen fehlen, und sowieso das ganze Object ungescrollt
+ // dargestellt wird.
+ // Das Rechteck ist unendlich gross.
+ Point aOrigin( aStartPos );
+ double nCos = 0.0, nSin = 0.0;
+ if ( nOrientation )
+ {
+ double nRealOrientation = nOrientation*F_PI1800;
+ nCos = cos( nRealOrientation );
+ nSin = sin( nRealOrientation );
+ }
+
+ // #110496# Added some more optional metafile comments. This
+ // change: factored out some duplicated code.
+ GDIMetaFile* pMtf = pOutDev->GetConnectMetaFile();
+ const bool bMetafileValid( pMtf != NULL );
+
+ // Fuer OnlineSpelling:
+// EditPaM aCursorPos;
+// if( GetStatus().DoOnlineSpelling() && pActiveView )
+// aCurPos = pActiveView->pImpEditView->GetEditSelections().Max();
+
+ // --------------------------------------------------
+ // Ueber alle Absaetze...
+ // --------------------------------------------------
+ for ( sal_uInt16 n = 0; n < GetParaPortions().Count(); n++ )
+ {
+ ParaPortion* pPortion = GetParaPortions().GetObject( n );
+ DBG_ASSERT( pPortion, "NULL-Pointer in TokenList in Paint" );
+ // falls beim Tippen Idle-Formatierung, asynchrones Paint.
+ // Unsichtbare Portions koennen ungueltig sein.
+ if ( pPortion->IsVisible() && pPortion->IsInvalid() )
+ return;
+
+ if ( pPDFExtOutDevData )
+ pPDFExtOutDevData->BeginStructureElement( vcl::PDFWriter::Paragraph );
+
+ long nParaHeight = pPortion->GetHeight();
+ sal_uInt16 nIndex = 0;
+ if ( pPortion->IsVisible() && (
+ ( !IsVertical() && ( ( aStartPos.Y() + nParaHeight ) > aClipRec.Top() ) ) ||
+ ( IsVertical() && ( ( aStartPos.X() - nParaHeight ) < aClipRec.Right() ) ) ) )
+
+ {
+ // --------------------------------------------------
+ // Ueber die Zeilen des Absatzes...
+ // --------------------------------------------------
+ sal_uInt16 nLines = pPortion->GetLines().Count();
+ sal_uInt16 nLastLine = nLines-1;
+
+ if ( !IsVertical() )
+ aStartPos.Y() += pPortion->GetFirstLineOffset();
+ else
+ aStartPos.X() -= pPortion->GetFirstLineOffset();
+
+ Point aParaStart( aStartPos );
+
+ const SvxLineSpacingItem& rLSItem = ((const SvxLineSpacingItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL ));
+ sal_uInt16 nSBL = ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_FIX )
+ ? GetYValue( rLSItem.GetInterLineSpace() ) : 0;
+ for ( sal_uInt16 nLine = 0; nLine < nLines; nLine++ )
+ {
+ pLine = pPortion->GetLines().GetObject(nLine);
+ DBG_ASSERT( pLine, "NULL-Pointer im Zeileniterator in UpdateViews" );
+ aTmpPos = aStartPos;
+ if ( !IsVertical() )
+ {
+ aTmpPos.X() += pLine->GetStartPosX();
+ aTmpPos.Y() += pLine->GetMaxAscent();
+ aStartPos.Y() += pLine->GetHeight();
+ }
+ else
+ {
+ aTmpPos.Y() += pLine->GetStartPosX();
+ aTmpPos.X() -= pLine->GetMaxAscent();
+ aStartPos.X() -= pLine->GetHeight();
+ }
+
+ if ( ( !IsVertical() && ( aStartPos.Y() > aClipRec.Top() ) )
+ || ( IsVertical() && aStartPos.X() < aClipRec.Right() ) )
+ {
+ // Why not just also call when stripping portions? This will give the correct values
+ // and needs no position corrections in OutlinerEditEng::DrawingText which tries to call
+ // PaintBullet correctly; exactly what GetEditEnginePtr()->PaintingFirstLine
+ // does, too. No change for not-layouting (painting).
+ if(0 == nLine) // && !bStripOnly)
+ {
+ // VERT???
+ GetEditEnginePtr()->PaintingFirstLine( n, aParaStart, aTmpPos.Y(), aOrigin, nOrientation, pOutDev );
+ }
+
+ // --------------------------------------------------
+ // Ueber die Portions der Zeile...
+ // --------------------------------------------------
+ nIndex = pLine->GetStart();
+ for ( sal_uInt16 y = pLine->GetStartPortion(); y <= pLine->GetEndPortion(); y++ )
+ {
+ DBG_ASSERT( pPortion->GetTextPortions().Count(), "Zeile ohne Textportion im Paint!" );
+ TextPortion* pTextPortion = pPortion->GetTextPortions().GetObject( y );
+ DBG_ASSERT( pTextPortion, "NULL-Pointer im Portioniterator in UpdateViews" );
+
+ long nPortionXOffset = GetPortionXOffset( pPortion, pLine, y );
+ if ( !IsVertical() )
+ {
+ aTmpPos.X() = aStartPos.X() + nPortionXOffset;
+ if ( aTmpPos.X() > aClipRec.Right() )
+ break; // Keine weitere Ausgabe in Zeile noetig
+ }
+ else
+ {
+ aTmpPos.Y() = aStartPos.Y() + nPortionXOffset;
+ if ( aTmpPos.Y() > aClipRec.Bottom() )
+ break; // Keine weitere Ausgabe in Zeile noetig
+ }
+
+ // R2L replaces with obove...
+ // New position after processing R2L text...
+// R2L if ( nR2LWidth && !pTextPortion->GetRightToLeft() )
+// R2L {
+// R2L if ( !IsVertical() )
+// R2L aTmpPos.X() += nR2LWidth;
+// R2L else
+// R2L aTmpPos.Y() += nR2LWidth;
+// R2L
+// R2L nR2LWidth = 0;
+// R2L }
+
+ switch ( pTextPortion->GetKind() )
+ {
+ case PORTIONKIND_TEXT:
+ case PORTIONKIND_FIELD:
+ case PORTIONKIND_HYPHENATOR:
+ {
+ SeekCursor( pPortion->GetNode(), nIndex+1, aTmpFont, pOutDev );
+
+ BOOL bDrawFrame = FALSE;
+
+ if ( ( pTextPortion->GetKind() == PORTIONKIND_FIELD ) && !aTmpFont.IsTransparent() &&
+ ( GetBackgroundColor() != COL_AUTO ) && GetBackgroundColor().IsDark() &&
+ ( IsAutoColorEnabled() && ( pOutDev->GetOutDevType() != OUTDEV_PRINTER ) ) )
+ {
+ aTmpFont.SetTransparent( TRUE );
+ pOutDev->SetFillColor();
+ pOutDev->SetLineColor( GetAutoColor() );
+ bDrawFrame = TRUE;
+ }
+
+#ifdef EDITDEBUG
+ if ( pTextPortion->GetKind() == PORTIONKIND_HYPHENATOR )
+ {
+ aTmpFont.SetFillColor( COL_LIGHTGRAY );
+ aTmpFont.SetTransparent( sal_False );
+ }
+ if ( pTextPortion->GetRightToLeft() )
+ {
+ aTmpFont.SetFillColor( COL_LIGHTGRAY );
+ aTmpFont.SetTransparent( sal_False );
+ }
+ else if ( GetScriptType( EditPaM( pPortion->GetNode(), nIndex+1 ) ) == i18n::ScriptType::COMPLEX )
+ {
+ aTmpFont.SetFillColor( COL_LIGHTCYAN );
+ aTmpFont.SetTransparent( sal_False );
+ }
+#endif
+ aTmpFont.SetPhysFont( pOutDev );
+
+ // #114278# Saving both layout mode and language (since I'm
+ // potentially changing both)
+ pOutDev->Push( PUSH_TEXTLAYOUTMODE|PUSH_TEXTLANGUAGE );
+ ImplInitLayoutMode( pOutDev, n, nIndex );
+ ImplInitDigitMode( pOutDev, 0, 0, 0, aTmpFont.GetLanguage() );
+
+ XubString aText;
+ USHORT nTextStart = 0;
+ USHORT nTextLen = 0;
+ const sal_Int32* pDXArray = 0;
+ sal_Int32* pTmpDXArray = 0;
+
+ if ( pTextPortion->GetKind() == PORTIONKIND_TEXT )
+ {
+ aText = *pPortion->GetNode();
+ nTextStart = nIndex;
+ nTextLen = pTextPortion->GetLen();
+ pDXArray = pLine->GetCharPosArray().GetData()+( nIndex-pLine->GetStart() );
+
+ // --> FME 2005-10-18 #i55716# Paint control characters
+ if ( aStatus.MarkFields() )
+ {
+ xub_StrLen nTmpIdx;
+ const xub_StrLen nTmpEnd = nTextStart + pTextPortion->GetLen();
+
+ for ( nTmpIdx = nTextStart; nTmpIdx <= nTmpEnd ; ++nTmpIdx )
+ {
+ const sal_Unicode cChar = ( nTmpIdx != aText.Len() && ( nTmpIdx != nTextStart || 0 == nTextStart ) ) ?
+ aText.GetChar( nTmpIdx ) :
+ 0;
+
+ if ( 0x200B == cChar || 0x2060 == cChar )
+ {
+ const String aBlank( ' ' );
+ long nHalfBlankWidth = aTmpFont.QuickGetTextSize( pOutDev, aBlank, 0, 1, 0 ).Width() / 2;
+
+ const long nAdvanceX = ( nTmpIdx == nTmpEnd ?
+ pTextPortion->GetSize().Width() :
+ pDXArray[ nTmpIdx - nTextStart ] ) - nHalfBlankWidth;
+ const long nAdvanceY = -pLine->GetMaxAscent();
+
+ Point aTopLeftRectPos( aTmpPos );
+ if ( !IsVertical() )
+ {
+ aTopLeftRectPos.X() += nAdvanceX;
+ aTopLeftRectPos.Y() += nAdvanceY;
+ }
+ else
+ {
+ aTopLeftRectPos.Y() += nAdvanceX;
+ aTopLeftRectPos.X() -= nAdvanceY;
+ }
+
+ Point aBottomRightRectPos( aTopLeftRectPos );
+ if ( !IsVertical() )
+ {
+ aBottomRightRectPos.X() += 2 * nHalfBlankWidth;
+ aBottomRightRectPos.Y() += pLine->GetHeight();
+ }
+ else
+ {
+ aBottomRightRectPos.X() -= pLine->GetHeight();
+ aBottomRightRectPos.Y() += 2 * nHalfBlankWidth;
+ }
+
+ pOutDev->Push( PUSH_FILLCOLOR );
+ pOutDev->Push( PUSH_LINECOLOR );
+ pOutDev->SetFillColor( COL_LIGHTGRAY );
+ pOutDev->SetLineColor( COL_LIGHTGRAY );
+
+ const Rectangle aBackRect( aTopLeftRectPos, aBottomRightRectPos );
+ pOutDev->DrawRect( aBackRect );
+
+ pOutDev->Pop();
+ pOutDev->Pop();
+
+ if ( 0x200B == cChar )
+ {
+ const String aSlash( '/' );
+ const short nOldEscapement = aTmpFont.GetEscapement();
+ const BYTE nOldPropr = aTmpFont.GetPropr();
+
+ aTmpFont.SetEscapement( -20 );
+ aTmpFont.SetPropr( 25 );
+ aTmpFont.SetPhysFont( pOutDev );
+
+ const Size aSlashSize = aTmpFont.QuickGetTextSize( pOutDev, aSlash, 0, 1, 0 );
+ Point aSlashPos( aTmpPos );
+ const long nAddX = nHalfBlankWidth - aSlashSize.Width() / 2;
+ if ( !IsVertical() )
+ {
+ aSlashPos.X() = aTopLeftRectPos.X() + nAddX;
+ }
+ else
+ {
+ aSlashPos.Y() = aTopLeftRectPos.Y() + nAddX;
+ }
+
+ aTmpFont.QuickDrawText( pOutDev, aSlashPos, aSlash, 0, 1, 0 );
+
+ aTmpFont.SetEscapement( nOldEscapement );
+ aTmpFont.SetPropr( nOldPropr );
+ aTmpFont.SetPhysFont( pOutDev );
+ }
+ }
+ }
+ }
+ // <--
+ }
+ else if ( pTextPortion->GetKind() == PORTIONKIND_FIELD )
+ {
+ EditCharAttrib* pAttr = pPortion->GetNode()->GetCharAttribs().FindFeature( nIndex );
+ DBG_ASSERT( pAttr, "Feld nicht gefunden" );
+ DBG_ASSERT( pAttr && pAttr->GetItem()->ISA( SvxFieldItem ), "Feld vom falschen Typ!" );
+ aText = ((EditCharAttribField*)pAttr)->GetFieldValue();
+ nTextStart = 0;
+ nTextLen = aText.Len();
+
+ pTmpDXArray = new sal_Int32[ aText.Len() ];
+ pDXArray = pTmpDXArray;
+ Font _aOldFont( GetRefDevice()->GetFont() );
+ aTmpFont.SetPhysFont( GetRefDevice() );
+ aTmpFont.QuickGetTextSize( GetRefDevice(), aText, 0, aText.Len(), pTmpDXArray );
+ if ( aStatus.DoRestoreFont() )
+ GetRefDevice()->SetFont( _aOldFont );
+
+ // add a meta file comment if we record to a metafile
+ if( bMetafileValid )
+ {
+ SvxFieldItem* pFieldItem = PTR_CAST( SvxFieldItem, pAttr->GetItem() );
+ if( pFieldItem )
+ {
+ const SvxFieldData* pFieldData = pFieldItem->GetField();
+ if( pFieldData )
+ pMtf->AddAction( pFieldData->createBeginComment() );
+ }
+ }
+
+ }
+ else if ( pTextPortion->GetKind() == PORTIONKIND_HYPHENATOR )
+ {
+ if ( pTextPortion->GetExtraValue() )
+ aText = pTextPortion->GetExtraValue();
+ aText += CH_HYPH;
+ nTextStart = 0;
+ nTextLen = aText.Len();
+
+ // #b6668980# crash when accessing 0 pointer in pDXArray
+ pTmpDXArray = new sal_Int32[ aText.Len() ];
+ pDXArray = pTmpDXArray;
+ Font _aOldFont( GetRefDevice()->GetFont() );
+ aTmpFont.SetPhysFont( GetRefDevice() );
+ aTmpFont.QuickGetTextSize( GetRefDevice(), aText, 0, aText.Len(), pTmpDXArray );
+ if ( aStatus.DoRestoreFont() )
+ GetRefDevice()->SetFont( _aOldFont );
+ }
+
+ long nTxtWidth = pTextPortion->GetSize().Width();
+
+ Point aOutPos( aTmpPos );
+ aRedLineTmpPos = aTmpPos;
+ // In RTL portions spell markup pos should be at the start of the
+ // first chara as well. That is on the right end of the portion
+ if (pTextPortion->IsRightToLeft())
+ aRedLineTmpPos.X() += pTextPortion->GetSize().Width();
+
+//L2R if ( pTextPortion->GetRightToLeft() )
+//L2R {
+//L2R sal_uInt16 nNextPortion = y+1;
+//L2R while ( nNextPortion <= pLine->GetEndPortion() )
+//L2R {
+//L2R TextPortion* pNextTextPortion = pPortion->GetTextPortions().GetObject( nNextPortion );
+//L2R if ( pNextTextPortion->GetRightToLeft() )
+//L2R {
+//L2R if ( !IsVertical() )
+//L2R aOutPos.X() += pNextTextPortion->GetSize().Width();
+//L2R else
+//L2R aOutPos.Y() += pNextTextPortion->GetSize().Width();
+//L2R }
+//L2R else
+//L2R break;
+//L2R nNextPortion++;
+//L2R }
+//L2R }
+ if ( bStripOnly )
+ {
+ EEngineData::WrongSpellVector aWrongSpellVector;
+
+ if(GetStatus().DoOnlineSpelling() && pTextPortion->GetLen())
+ {
+ WrongList* pWrongs = pPortion->GetNode()->GetWrongList();
+
+ if(pWrongs && pWrongs->HasWrongs())
+ {
+ sal_uInt16 nStart(nIndex);
+ sal_uInt16 nEnd(0);
+ sal_Bool bWrong(pWrongs->NextWrong(nStart, nEnd));
+ const sal_uInt16 nMaxEnd(nIndex + pTextPortion->GetLen());
+
+ while(bWrong)
+ {
+ if(nStart >= nMaxEnd)
+ {
+ break;
+ }
+
+ if(nStart < nIndex)
+ {
+ nStart = nIndex;
+ }
+
+ if(nEnd > nMaxEnd)
+ {
+ nEnd = nMaxEnd;
+ }
+
+ // add to vector
+ aWrongSpellVector.push_back(EEngineData::WrongSpellClass(nStart, nEnd));
+
+ // goto next index
+ nStart = nEnd + 1;
+
+ if(nEnd < nMaxEnd)
+ {
+ bWrong = pWrongs->NextWrong(nStart, nEnd);
+ }
+ else
+ {
+ bWrong = sal_False;
+ }
+ }
+ }
+ }
+
+ const SvxFieldData* pFieldData = 0;
+
+ if(PORTIONKIND_FIELD == pTextPortion->GetKind())
+ {
+ EditCharAttrib* pAttr = pPortion->GetNode()->GetCharAttribs().FindFeature(nIndex);
+ SvxFieldItem* pFieldItem = PTR_CAST(SvxFieldItem, pAttr->GetItem());
+
+ if(pFieldItem)
+ {
+ pFieldData = pFieldItem->GetField();
+ }
+ }
+
+ // support for EOC, EOW, EOS TEXT comments. To support that,
+ // the locale is needed. With the locale and a XBreakIterator it is
+ // possible to re-create the text marking info on primitive level
+ const lang::Locale aLocale(GetLocale(EditPaM(pPortion->GetNode(), nIndex + 1)));
+
+ // create EOL and EOP bools
+ const bool bEndOfLine(y == pLine->GetEndPortion());
+ const bool bEndOfParagraph(bEndOfLine && nLine + 1 == nLines);
+
+ // get Overline color (from ((const SvxOverlineItem*)GetItem())->GetColor() in
+ // consequence, but also already set at pOutDev)
+ const Color aOverlineColor(pOutDev->GetOverlineColor());
+
+ // get TextLine color (from ((const SvxUnderlineItem*)GetItem())->GetColor() in
+ // consequence, but also already set at pOutDev)
+ const Color aTextLineColor(pOutDev->GetTextLineColor());
+
+ // Unicode code points conversion according to ctl text numeral setting
+ ImplInitDigitMode( 0, &aText, nTextStart, nTextLen, aTmpFont.GetLanguage() );
+
+ // StripPortions() data callback
+ GetEditEnginePtr()->DrawingText( aOutPos, aText, nTextStart, nTextLen, pDXArray,
+ aTmpFont, n, nIndex, pTextPortion->GetRightToLeft(),
+ aWrongSpellVector.size() ? &aWrongSpellVector : 0,
+ pFieldData,
+ bEndOfLine, bEndOfParagraph, false, // support for EOL/EOP TEXT comments
+ &aLocale,
+ aOverlineColor,
+ aTextLineColor);
+ }
+ else
+ {
+ short nEsc = aTmpFont.GetEscapement();
+ if ( nOrientation )
+ {
+ // Bei Hoch/Tief selbst Hand anlegen:
+ if ( aTmpFont.GetEscapement() )
+ {
+ long nDiff = aTmpFont.GetSize().Height() * aTmpFont.GetEscapement() / 100L;
+ if ( !IsVertical() )
+ aOutPos.Y() -= nDiff;
+ else
+ aOutPos.X() += nDiff;
+ aRedLineTmpPos = aOutPos;
+ aTmpFont.SetEscapement( 0 );
+ }
+
+ aOutPos = lcl_ImplCalcRotatedPos( aOutPos, aOrigin, nSin, nCos );
+ aTmpFont.SetOrientation( aTmpFont.GetOrientation()+nOrientation );
+ aTmpFont.SetPhysFont( pOutDev );
+
+ }
+ // nur ausgeben, was im sichtbaren Bereich beginnt:
+ // Wichtig, weil Bug bei einigen Grafikkarten bei transparentem Font, Ausgabe bei neg.
+ if ( nOrientation || ( !IsVertical() && ( ( aTmpPos.X() + nTxtWidth ) >= nFirstVisXPos ) )
+ || ( IsVertical() && ( ( aTmpPos.Y() + nTxtWidth ) >= nFirstVisYPos ) ) )
+ {
+ if ( nEsc && ( ( aTmpFont.GetUnderline() != UNDERLINE_NONE ) ) )
+ {
+ // Das Hoch/Tief ohne Underline malen, das Underline
+ // auf der BaseLine der Original-Fonthoehe ausgeben...
+
+ // Aber nur, wenn davor auch Unterstrichen!
+ sal_Bool bSpecialUnderline = sal_False;
+ EditCharAttrib* pPrev = pPortion->GetNode()->GetCharAttribs().FindAttrib( EE_CHAR_ESCAPEMENT, nIndex );
+ if ( pPrev )
+ {
+ SvxFont aDummy;
+ // Unterstreichung davor?
+ if ( pPrev->GetStart() )
+ {
+ SeekCursor( pPortion->GetNode(), pPrev->GetStart(), aDummy );
+ if ( aDummy.GetUnderline() != UNDERLINE_NONE )
+ bSpecialUnderline = sal_True;
+ }
+ if ( !bSpecialUnderline && ( pPrev->GetEnd() < pPortion->GetNode()->Len() ) )
+ {
+ SeekCursor( pPortion->GetNode(), pPrev->GetEnd()+1, aDummy );
+ if ( aDummy.GetUnderline() != UNDERLINE_NONE )
+ bSpecialUnderline = sal_True;
+ }
+ }
+ if ( bSpecialUnderline )
+ {
+ Size aSz = aTmpFont.GetPhysTxtSize( pOutDev, aText, nTextStart, nTextLen );
+ BYTE nProp = aTmpFont.GetPropr();
+ aTmpFont.SetEscapement( 0 );
+ aTmpFont.SetPropr( 100 );
+ aTmpFont.SetPhysFont( pOutDev );
+ String aBlanks;
+ aBlanks.Fill( nTextLen, ' ' );
+ Point aUnderlinePos( aOutPos );
+ if ( nOrientation )
+ aUnderlinePos = lcl_ImplCalcRotatedPos( aTmpPos, aOrigin, nSin, nCos );
+ pOutDev->DrawStretchText( aUnderlinePos, aSz.Width(), aBlanks, 0, nTextLen );
+
+ aTmpFont.SetUnderline( UNDERLINE_NONE );
+ if ( !nOrientation )
+ aTmpFont.SetEscapement( nEsc );
+ aTmpFont.SetPropr( nProp );
+ aTmpFont.SetPhysFont( pOutDev );
+ }
+ }
+ Point aRealOutPos( aOutPos );
+ if ( ( pTextPortion->GetKind() == PORTIONKIND_TEXT )
+ && pTextPortion->GetExtraInfos() && pTextPortion->GetExtraInfos()->bCompressed
+ && pTextPortion->GetExtraInfos()->bFirstCharIsRightPunktuation )
+ {
+ aRealOutPos.X() += pTextPortion->GetExtraInfos()->nPortionOffsetX;
+ }
+
+ // --> FME 2005-06-17 #i37132# RTL portions with
+ // compressed blank should not paint this blank:
+ if ( pTextPortion->IsRightToLeft() && nTextLen >= 2 &&
+ pDXArray[ nTextLen - 1 ] ==
+ pDXArray[ nTextLen - 2 ] &&
+ ' ' == aText.GetChar( nTextStart + nTextLen - 1 ) )
+ --nTextLen;
+ // <--
+
+ // output directly
+ aTmpFont.QuickDrawText( pOutDev, aRealOutPos, aText, nTextStart, nTextLen, pDXArray );
+
+ if ( bDrawFrame )
+ {
+ Point aTopLeft( aTmpPos );
+ aTopLeft.Y() -= pLine->GetMaxAscent();
+ if ( nOrientation )
+ aTopLeft = lcl_ImplCalcRotatedPos( aTopLeft, aOrigin, nSin, nCos );
+ Rectangle aRect( aTopLeft, pTextPortion->GetSize() );
+ pOutDev->DrawRect( aRect );
+ }
+
+
+ // PDF export:
+ if ( pPDFExtOutDevData )
+ {
+ if ( pTextPortion->GetKind() == PORTIONKIND_FIELD )
+ {
+ EditCharAttrib* pAttr = pPortion->GetNode()->GetCharAttribs().FindFeature( nIndex );
+ SvxFieldItem* pFieldItem = PTR_CAST( SvxFieldItem, pAttr->GetItem() );
+ if( pFieldItem )
+ {
+ const SvxFieldData* pFieldData = pFieldItem->GetField();
+ if ( pFieldData->ISA( SvxURLField ) )
+ {
+ Point aTopLeft( aTmpPos );
+ aTopLeft.Y() -= pLine->GetMaxAscent();
+// if ( nOrientation )
+// aTopLeft = lcl_ImplCalcRotatedPos( aTopLeft, aOrigin, nSin, nCos );
+
+ Rectangle aRect( aTopLeft, pTextPortion->GetSize() );
+ vcl::PDFExtOutDevBookmarkEntry aBookmark;
+ aBookmark.nLinkId = pPDFExtOutDevData->CreateLink( aRect );
+ aBookmark.aBookmark = ((SvxURLField*)pFieldData)->GetURL();
+ std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFExtOutDevData->GetBookmarks();
+ rBookmarks.push_back( aBookmark );
+ }
+ }
+ }
+ }
+
+ // comment
+
+
+
+
+ }
+
+#ifndef SVX_LIGHT
+ if ( GetStatus().DoOnlineSpelling() && pPortion->GetNode()->GetWrongList()->HasWrongs() && pTextPortion->GetLen() )
+ {
+ {//#105750# adjust LinePos for superscript or subscript text
+ short _nEsc = aTmpFont.GetEscapement();
+ if( _nEsc )
+ {
+ long nShift = ((_nEsc*long(aTmpFont.GetSize().Height()))/ 100L);
+ if( !IsVertical() )
+ aRedLineTmpPos.Y() -= nShift;
+ else
+ aRedLineTmpPos.X() += nShift;
+ }
+ }
+ Color aOldColor( pOutDev->GetLineColor() );
+ pOutDev->SetLineColor( Color( GetColorConfig().GetColorValue( svtools::SPELL ).nColor ) );
+ lcl_DrawRedLines( pOutDev, aTmpFont.GetSize().Height(), aRedLineTmpPos, nIndex, nIndex + pTextPortion->GetLen(), pDXArray, pPortion->GetNode()->GetWrongList(), nOrientation, aOrigin, IsVertical(), pTextPortion->IsRightToLeft() );
+ pOutDev->SetLineColor( aOldColor );
+ }
+#endif // !SVX_LIGHT
+ }
+
+ pOutDev->Pop();
+
+ if ( pTmpDXArray )
+ delete[] pTmpDXArray;
+
+// R2L if ( !pTextPortion->GetRightToLeft() )
+// R2L {
+// R2L if ( !IsVertical() )
+// R2L aTmpPos.X() += nTxtWidth;
+// R2L else
+// R2L aTmpPos.Y() += nTxtWidth;
+// R2L }
+// R2L else
+// R2L {
+// R2L nR2LWidth += nTxtWidth;
+// R2L }
+
+ if ( pTextPortion->GetKind() == PORTIONKIND_FIELD )
+ {
+ EditCharAttrib* pAttr = pPortion->GetNode()->GetCharAttribs().FindFeature( nIndex );
+ DBG_ASSERT( pAttr, "Feld nicht gefunden" );
+ DBG_ASSERT( pAttr && pAttr->GetItem()->ISA( SvxFieldItem ), "Feld vom falschen Typ!" );
+
+ // add a meta file comment if we record to a metafile
+ if( bMetafileValid )
+ {
+ SvxFieldItem* pFieldItem = PTR_CAST( SvxFieldItem, pAttr->GetItem() );
+
+ if( pFieldItem )
+ {
+ const SvxFieldData* pFieldData = pFieldItem->GetField();
+ if( pFieldData )
+ pMtf->AddAction( pFieldData->createEndComment() );
+ }
+ }
+
+ }
+
+ }
+ break;
+// case PORTIONKIND_EXTRASPACE:
+ case PORTIONKIND_TAB:
+ {
+ if ( pTextPortion->GetExtraValue() && ( pTextPortion->GetExtraValue() != ' ' ) )
+ {
+ SeekCursor( pPortion->GetNode(), nIndex+1, aTmpFont, pOutDev );
+ aTmpFont.SetTransparent( sal_False );
+ aTmpFont.SetEscapement( 0 );
+ aTmpFont.SetPhysFont( pOutDev );
+ long nCharWidth = aTmpFont.QuickGetTextSize( pOutDev, pTextPortion->GetExtraValue(), 0, 1, NULL ).Width();
+ long nChars = 2;
+ if( nCharWidth )
+ nChars = pTextPortion->GetSize().Width() / nCharWidth;
+ if ( nChars < 2 )
+ nChars = 2; // wird durch DrawStretchText gestaucht.
+ else if ( nChars == 2 )
+ nChars = 3; // sieht besser aus
+
+ String aText;
+ aText.Fill( (USHORT)nChars, pTextPortion->GetExtraValue() );
+ pOutDev->DrawStretchText( aTmpPos, pTextPortion->GetSize().Width(), aText );
+ }
+ }
+ break;
+ }
+ nIndex = nIndex + pTextPortion->GetLen();
+ }
+ }
+
+ if ( ( nLine != nLastLine ) && !aStatus.IsOutliner() )
+ {
+ if ( !IsVertical() )
+ aStartPos.Y() += nSBL;
+ else
+ aStartPos.X() -= nSBL;
+ }
+
+ // keine sichtbaren Aktionen mehr?
+ if ( !IsVertical() && ( aStartPos.Y() >= aClipRec.Bottom() ) )
+ break;
+ else if ( IsVertical() && ( aStartPos.X() <= aClipRec.Left() ) )
+ break;
+ }
+
+ if ( !aStatus.IsOutliner() )
+ {
+ const SvxULSpaceItem& rULItem = (const SvxULSpaceItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE );
+ long nUL = GetYValue( rULItem.GetLower() );
+ if ( !IsVertical() )
+ aStartPos.Y() += nUL;
+ else
+ aStartPos.X() -= nUL;
+ }
+ }
+ else
+ {
+ if ( !IsVertical() )
+ aStartPos.Y() += nParaHeight;
+ else
+ aStartPos.X() -= nParaHeight;
+ }
+
+ if ( pPDFExtOutDevData )
+ pPDFExtOutDevData->EndStructureElement();
+
+ // keine sichtbaren Aktionen mehr?
+ if ( !IsVertical() && ( aStartPos.Y() > aClipRec.Bottom() ) )
+ break;
+ if ( IsVertical() && ( aStartPos.X() < aClipRec.Left() ) )
+ break;
+ }
+ if ( aStatus.DoRestoreFont() )
+ pOutDev->SetFont( aOldFont );
+}
+
+void ImpEditEngine::Paint( ImpEditView* pView, const Rectangle& rRec, sal_Bool bUseVirtDev )
+{
+ DBG_ASSERT( pView, "Keine View - Kein Paint!" );
+ DBG_CHKOBJ( GetEditEnginePtr(), EditEngine, 0 );
+
+ if ( !GetUpdateMode() || IsInUndo() )
+ return;
+
+ // Schnittmenge aus Paintbereich und OutputArea.
+ Rectangle aClipRec( pView->GetOutputArea() );
+ aClipRec.Intersection( rRec );
+
+ Window* pOutWin = pView->GetWindow();
+
+ if ( bUseVirtDev )
+ {
+ Rectangle aClipRecPixel( pOutWin->LogicToPixel( aClipRec ) );
+ if ( !IsVertical() )
+ {
+ // etwas mehr, falls abgerundet!
+ aClipRecPixel.Right() += 1;
+ aClipRecPixel.Bottom() += 1;
+ }
+ else
+ {
+ aClipRecPixel.Left() -= 1;
+ aClipRecPixel.Bottom() += 1;
+ }
+
+ // Wenn aClipRecPixel > XXXX, dann invalidieren ?!
+
+ VirtualDevice* pVDev = GetVirtualDevice( pOutWin->GetMapMode(), pOutWin->GetDrawMode() );
+ pVDev->SetDigitLanguage( GetRefDevice()->GetDigitLanguage() );
+
+ {
+ Color aBackgroundColor( pView->GetBackgroundColor() );
+ // #i47161# Check if text is visible on background
+ SvxFont aTmpFont;
+ ContentNode* pNode = GetEditDoc().SaveGetObject( 0 );
+ SeekCursor( pNode, 1, aTmpFont );
+ Color aFontColor( aTmpFont.GetColor() );
+ if( aFontColor == COL_AUTO )
+ aFontColor = GetAutoColor();
+
+ // #i69346# check for reverse color of input method attribute
+ if( mpIMEInfos && (mpIMEInfos->aPos.GetNode() == pNode &&
+ mpIMEInfos->pAttribs))
+ {
+ sal_uInt16 nAttr = mpIMEInfos->pAttribs[ 0 ];
+ if ( nAttr & EXTTEXTINPUT_ATTR_HIGHLIGHT )
+ {
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ aFontColor = rStyleSettings.GetHighlightColor() ;
+ }
+ }
+
+ UINT8 nColorDiff = aFontColor.GetColorError( aBackgroundColor );
+ if( nColorDiff < 8 )
+ aBackgroundColor = aFontColor.IsDark() ? COL_WHITE : COL_BLACK;
+ pVDev->SetBackground( aBackgroundColor );
+ }
+
+ sal_Bool bVDevValid = sal_True;
+ Size aOutSz( pVDev->GetOutputSizePixel() );
+ if ( ( aOutSz.Width() < aClipRecPixel.GetWidth() ) ||
+ ( aOutSz.Height() < aClipRecPixel.GetHeight() ) )
+ {
+ bVDevValid = pVDev->SetOutputSizePixel( aClipRecPixel.GetSize() );
+ }
+ else
+ {
+ // Das VirtDev kann bei einem Resize sehr gross werden =>
+ // irgendwann mal kleiner machen!
+ if ( ( aOutSz.Height() > ( aClipRecPixel.GetHeight() + RESDIFF ) ) ||
+ ( aOutSz.Width() > ( aClipRecPixel.GetWidth() + RESDIFF ) ) )
+ {
+ bVDevValid = pVDev->SetOutputSizePixel( aClipRecPixel.GetSize() );
+ }
+ else
+ {
+ pVDev->Erase();
+ }
+ }
+ DBG_ASSERT( bVDevValid, "VDef konnte nicht vergroessert werden!" );
+ if ( !bVDevValid )
+ {
+ Paint( pView, rRec, sal_False /* ohne VDev */ );
+ return;
+ }
+
+ // PaintRect fuer VDev nicht mit alignter Groesse,
+ // da sonst die Zeile darunter auch ausgegeben werden muss:
+ Rectangle aTmpRec( Point( 0, 0 ), aClipRec.GetSize() );
+
+ aClipRec = pOutWin->PixelToLogic( aClipRecPixel );
+ Point aStartPos;
+ if ( !IsVertical() )
+ {
+ aStartPos = aClipRec.TopLeft();
+ aStartPos = pView->GetDocPos( aStartPos );
+ aStartPos.X() *= (-1);
+ aStartPos.Y() *= (-1);
+ }
+ else
+ {
+ aStartPos = aClipRec.TopRight();
+ Point aDocPos( pView->GetDocPos( aStartPos ) );
+ aStartPos.X() = aClipRec.GetSize().Width() + aDocPos.Y();
+ aStartPos.Y() = -aDocPos.X();
+ }
+
+ Paint( pVDev, aTmpRec, aStartPos );
+
+ sal_Bool bClipRegion = sal_False;
+ Region aOldRegion;
+ MapMode aOldMapMode;
+ if ( GetTextRanger() )
+ {
+ // Some problems here with push/pop, why?!
+// pOutWin->Push( PUSH_CLIPREGION|PUSH_MAPMODE );
+ bClipRegion = pOutWin->IsClipRegion();
+ aOldRegion = pOutWin->GetClipRegion();
+ // Wie bekomme ich das Polygon an die richtige Stelle????
+ // Das Polygon bezieht sich auf die View, nicht auf das Window
+ // => Origin umsetzen...
+ aOldMapMode = pOutWin->GetMapMode();
+ Point aOrigin = aOldMapMode.GetOrigin();
+ Point aViewPos = pView->GetOutputArea().TopLeft();
+ aOrigin.Move( aViewPos.X(), aViewPos.Y() );
+ aClipRec.Move( -aViewPos.X(), -aViewPos.Y() );
+ MapMode aNewMapMode( aOldMapMode );
+ aNewMapMode.SetOrigin( aOrigin );
+ pOutWin->SetMapMode( aNewMapMode );
+ pOutWin->SetClipRegion( Region( GetTextRanger()->GetPolyPolygon() ) );
+ }
+
+ pOutWin->DrawOutDev( aClipRec.TopLeft(), aClipRec.GetSize(),
+ Point(0,0), aClipRec.GetSize(), *pVDev );
+
+ if ( GetTextRanger() )
+ {
+// pOutWin->Pop();
+ if ( bClipRegion )
+ pOutWin->SetClipRegion( aOldRegion );
+ else
+ pOutWin->SetClipRegion();
+ pOutWin->SetMapMode( aOldMapMode );
+ }
+
+
+ pView->DrawSelection();
+ }
+ else
+ {
+ Point aStartPos;
+ if ( !IsVertical() )
+ {
+ aStartPos = pView->GetOutputArea().TopLeft();
+ aStartPos.X() -= pView->GetVisDocLeft();
+ aStartPos.Y() -= pView->GetVisDocTop();
+ }
+ else
+ {
+ aStartPos = pView->GetOutputArea().TopRight();
+ aStartPos.X() += pView->GetVisDocTop();
+ aStartPos.Y() -= pView->GetVisDocLeft();
+ }
+
+ // Wenn Doc-Breite < OutputArea,Width, nicht umgebrochene Felder,
+ // stehen die Felder sonst �ber, wenn > Zeile.
+ // ( Oben nicht, da dort bereits Doc-Breite von Formatierung mit drin )
+ if ( !IsVertical() && ( pView->GetOutputArea().GetWidth() > GetPaperSize().Width() ) )
+ {
+ long nMaxX = pView->GetOutputArea().Left() + GetPaperSize().Width();
+ if ( aClipRec.Left() > nMaxX )
+ return;
+ if ( aClipRec.Right() > nMaxX )
+ aClipRec.Right() = nMaxX;
+ }
+
+ sal_Bool bClipRegion = pOutWin->IsClipRegion();
+ Region aOldRegion = pOutWin->GetClipRegion();
+ pOutWin->IntersectClipRegion( aClipRec );
+
+ Paint( pOutWin, aClipRec, aStartPos );
+
+ if ( bClipRegion )
+ pOutWin->SetClipRegion( aOldRegion );
+ else
+ pOutWin->SetClipRegion();
+
+ pView->DrawSelection();
+ }
+
+}
+
+void ImpEditEngine::InsertContent( ContentNode* pNode, sal_uInt16 nPos )
+{
+ DBG_ASSERT( pNode, "NULL-Poointer in InsertContent! " );
+ DBG_ASSERT( IsInUndo(), "InsertContent nur fuer Undo()!" );
+ ParaPortion* pNew = new ParaPortion( pNode );
+ GetParaPortions().Insert( pNew, nPos );
+ aEditDoc.Insert( pNode, nPos );
+ if ( IsCallParaInsertedOrDeleted() )
+ GetEditEnginePtr()->ParagraphInserted( nPos );
+}
+
+EditPaM ImpEditEngine::SplitContent( sal_uInt16 nNode, sal_uInt16 nSepPos )
+{
+ ContentNode* pNode = aEditDoc.SaveGetObject( nNode );
+ DBG_ASSERT( pNode, "Ungueltiger Node in SplitContent" );
+ DBG_ASSERT( IsInUndo(), "SplitContent nur fuer Undo()!" );
+ DBG_ASSERT( nSepPos <= pNode->Len(), "Index im Wald: SplitContent" );
+ EditPaM aPaM( pNode, nSepPos );
+ return ImpInsertParaBreak( aPaM );
+}
+
+EditPaM ImpEditEngine::ConnectContents( sal_uInt16 nLeftNode, sal_Bool bBackward )
+{
+ ContentNode* pLeftNode = aEditDoc.SaveGetObject( nLeftNode );
+ ContentNode* pRightNode = aEditDoc.SaveGetObject( nLeftNode+1 );
+ DBG_ASSERT( pLeftNode, "Ungueltiger linker Node in ConnectContents" );
+ DBG_ASSERT( pRightNode, "Ungueltiger rechter Node in ConnectContents" );
+ DBG_ASSERT( IsInUndo(), "ConnectContent nur fuer Undo()!" );
+ return ImpConnectParagraphs( pLeftNode, pRightNode, bBackward );
+}
+
+void ImpEditEngine::SetUpdateMode( sal_Bool bUp, EditView* pCurView, sal_Bool bForceUpdate )
+{
+ sal_Bool bChanged = ( GetUpdateMode() != bUp );
+
+ // Beim Umschalten von sal_True auf sal_False waren alle Selektionen sichtbar,
+ // => Wegmalen
+ // Umgekehrt waren alle unsichtbar => malen
+
+// DrawAllSelections(); sieht im Outliner schlecht aus !
+// EditView* pView = aEditViewList.First();
+// while ( pView )
+// {
+// DBG_CHKOBJ( pView, EditView, 0 );
+// pView->pImpEditView->DrawSelection();
+// pView = aEditViewList.Next();
+// }
+
+ // Wenn !bFormatted, also z.B. nach SetText, braucht bei UpdateMode sal_True
+ // nicht sofort formatiert werden, weil warscheinlich noch Text kommt.
+ // Spaetestens bei einem Paint / CalcTextWidth wird formatiert.
+
+ bUpdate = bUp;
+ if ( bUpdate && ( bChanged || bForceUpdate ) )
+ FormatAndUpdate( pCurView );
+}
+
+void ImpEditEngine::ShowParagraph( sal_uInt16 nParagraph, sal_Bool bShow )
+{
+ ParaPortion* pPPortion = GetParaPortions().SaveGetObject( nParagraph );
+ DBG_ASSERT( pPPortion, "ShowParagraph: Absatz existiert nicht!" );
+ if ( pPPortion && ( pPPortion->IsVisible() != bShow ) )
+ {
+ pPPortion->SetVisible( bShow );
+
+ if ( !bShow )
+ {
+ // Als deleted kenzeichnen, damit keine Selektion auf diesem
+ // Absatz beginnt oder endet...
+ DeletedNodeInfo* pDelInfo = new DeletedNodeInfo( (sal_uIntPtr)pPPortion->GetNode(), nParagraph );
+ aDeletedNodes.Insert( pDelInfo, aDeletedNodes.Count() );
+ UpdateSelections();
+ // Dann kriege ich den unteren Bereich nicht invalidiert,
+ // wenn UpdateMode = sal_False!
+ // Wenn doch, dann vor SetVisible auf sal_False merken!
+// nCurTextHeight -= pPPortion->GetHeight();
+ }
+
+ if ( bShow && ( pPPortion->IsInvalid() || !pPPortion->nHeight ) )
+ {
+ if ( !GetTextRanger() )
+ {
+ if ( pPPortion->IsInvalid() )
+ {
+ Font aOldFont( GetRefDevice()->GetFont() );
+ CreateLines( nParagraph, 0 ); // 0: Kein TextRanger
+ if ( aStatus.DoRestoreFont() )
+ GetRefDevice()->SetFont( aOldFont );
+ }
+ else
+ {
+ CalcHeight( pPPortion );
+ }
+ nCurTextHeight += pPPortion->GetHeight();
+ }
+ else
+ {
+ nCurTextHeight = 0x7fffffff;
+ }
+ }
+
+ pPPortion->SetMustRepaint( sal_True );
+ if ( GetUpdateMode() && !IsInUndo() && !GetTextRanger() )
+ {
+ aInvalidRec = Rectangle( Point( 0, GetParaPortions().GetYOffset( pPPortion ) ),
+ Point( GetPaperSize().Width(), nCurTextHeight ) );
+ UpdateViews( GetActiveView() );
+ }
+ }
+}
+
+sal_Bool ImpEditEngine::IsParagraphVisible( sal_uInt16 nParagraph )
+{
+ ParaPortion* pPPortion = GetParaPortions().SaveGetObject( nParagraph );
+ DBG_ASSERT( pPPortion, "IsParagraphVisible: Absatz existiert nicht!" );
+ if ( pPPortion )
+ return pPPortion->IsVisible();
+ return sal_False;
+}
+
+EditSelection ImpEditEngine::MoveParagraphs( Range aOldPositions, sal_uInt16 nNewPos, EditView* pCurView )
+{
+ DBG_ASSERT( GetParaPortions().Count() != 0, "Keine Absaetze gefunden: MoveParagraphs" );
+ if ( GetParaPortions().Count() == 0 )
+ return EditSelection();
+ aOldPositions.Justify();
+
+ EditSelection aSel( ImpMoveParagraphs( aOldPositions, nNewPos ) );
+
+ if ( nNewPos >= GetParaPortions().Count() )
+ nNewPos = GetParaPortions().Count() - 1;
+
+ // Dort, wo der Absatz eingefuegt wurde, muss richtig gepainted werden:
+ // Dort, wo der Absatz entfernt wurde, muss richtig gepainted werden:
+ // ( Und dazwischen entsprechend auch...)
+ if ( pCurView && ( GetUpdateMode() == sal_True ) )
+ {
+ // in diesem Fall kann ich direkt neu malen, ohne die
+ // Portions zu Invalidieren.
+ sal_uInt16 nFirstPortion = Min( (sal_uInt16)aOldPositions.Min(), nNewPos );
+ sal_uInt16 nLastPortion = Max( (sal_uInt16)aOldPositions.Max(), nNewPos );
+
+ ParaPortion* pUpperPortion = GetParaPortions().SaveGetObject( nFirstPortion );
+ ParaPortion* pLowerPortion = GetParaPortions().SaveGetObject( nLastPortion );
+
+ aInvalidRec = Rectangle(); // leermachen
+ aInvalidRec.Left() = 0;
+ aInvalidRec.Right() = aPaperSize.Width();
+ aInvalidRec.Top() = GetParaPortions().GetYOffset( pUpperPortion );
+ aInvalidRec.Bottom() = GetParaPortions().GetYOffset( pLowerPortion ) + pLowerPortion->GetHeight();
+
+ UpdateViews( pCurView );
+ }
+ else
+ {
+ // aber der oberen ungueltigen Position neu painten...
+ sal_uInt16 nFirstInvPara = Min( (sal_uInt16)aOldPositions.Min(), nNewPos );
+ InvalidateFromParagraph( nFirstInvPara );
+ }
+ return aSel;
+}
+
+void ImpEditEngine::InvalidateFromParagraph( sal_uInt16 nFirstInvPara )
+{
+ // Es werden nicht die folgenden Absaetze invalidiert,
+ // da ResetHeight() => Groessenanderung => alles folgende wird
+ // sowieso neu ausgegeben.
+ ParaPortion* pTmpPortion;
+ if ( nFirstInvPara != 0 )
+ {
+ pTmpPortion = GetParaPortions().GetObject( nFirstInvPara-1 );
+ pTmpPortion->MarkInvalid( pTmpPortion->GetNode()->Len(), 0 );
+ }
+ else
+ {
+ pTmpPortion = GetParaPortions().GetObject( 0 );
+ pTmpPortion->MarkSelectionInvalid( 0, pTmpPortion->GetNode()->Len() );
+ }
+ pTmpPortion->ResetHeight();
+}
+
+IMPL_LINK_INLINE_START( ImpEditEngine, StatusTimerHdl, Timer *, EMPTYARG )
+{
+ CallStatusHdl();
+ return 0;
+}
+IMPL_LINK_INLINE_END( ImpEditEngine, StatusTimerHdl, Timer *, EMPTYARG )
+
+void ImpEditEngine::CallStatusHdl()
+{
+ if ( aStatusHdlLink.IsSet() && aStatus.GetStatusWord() )
+ {
+ // Der Status muss vor Call zurueckgesetzt werden,
+ // da im Hdl evtl. weitere Fags gesetzt werden...
+ EditStatus aTmpStatus( aStatus );
+ aStatus.Clear();
+ aStatusHdlLink.Call( &aTmpStatus );
+ aStatusTimer.Stop(); // Falls von Hand gerufen...
+ }
+}
+
+ContentNode* ImpEditEngine::GetPrevVisNode( ContentNode* pCurNode )
+{
+ ParaPortion* pPortion = FindParaPortion( pCurNode );
+ DBG_ASSERT( pPortion, "GetPrevVisibleNode: Keine passende Portion!" );
+ pPortion = GetPrevVisPortion( pPortion );
+ if ( pPortion )
+ return pPortion->GetNode();
+ return 0;
+}
+
+ContentNode* ImpEditEngine::GetNextVisNode( ContentNode* pCurNode )
+{
+ ParaPortion* pPortion = FindParaPortion( pCurNode );
+ DBG_ASSERT( pPortion, "GetNextVisibleNode: Keine passende Portion!" );
+ pPortion = GetNextVisPortion( pPortion );
+ if ( pPortion )
+ return pPortion->GetNode();
+ return 0;
+}
+
+ParaPortion* ImpEditEngine::GetPrevVisPortion( ParaPortion* pCurPortion )
+{
+ sal_uInt16 nPara = GetParaPortions().GetPos( pCurPortion );
+ DBG_ASSERT( nPara < GetParaPortions().Count() , "Portion nicht gefunden: GetPrevVisPortion" );
+ ParaPortion* pPortion = nPara ? GetParaPortions()[--nPara] : 0;
+ while ( pPortion && !pPortion->IsVisible() )
+ pPortion = nPara ? GetParaPortions()[--nPara] : 0;
+
+ return pPortion;
+}
+
+ParaPortion* ImpEditEngine::GetNextVisPortion( ParaPortion* pCurPortion )
+{
+ sal_uInt16 nPara = GetParaPortions().GetPos( pCurPortion );
+ DBG_ASSERT( nPara < GetParaPortions().Count() , "Portion nicht gefunden: GetPrevVisNode" );
+ ParaPortion* pPortion = GetParaPortions().SaveGetObject( ++nPara );
+ while ( pPortion && !pPortion->IsVisible() )
+ pPortion = GetParaPortions().SaveGetObject( ++nPara );
+
+ return pPortion;
+}
+
+EditPaM ImpEditEngine::InsertParagraph( sal_uInt16 nPara )
+{
+ EditPaM aPaM;
+ if ( nPara != 0 )
+ {
+ ContentNode* pNode = GetEditDoc().SaveGetObject( nPara-1 );
+ if ( !pNode )
+ pNode = GetEditDoc().SaveGetObject( GetEditDoc().Count() - 1 );
+ DBG_ASSERT( pNode, "Kein einziger Absatz in InsertParagraph ?" );
+ aPaM = EditPaM( pNode, pNode->Len() );
+ }
+ else
+ {
+ ContentNode* pNode = GetEditDoc().SaveGetObject( 0 );
+ aPaM = EditPaM( pNode, 0 );
+ }
+
+ return ImpInsertParaBreak( aPaM );
+}
+
+EditSelection* ImpEditEngine::SelectParagraph( sal_uInt16 nPara )
+{
+ EditSelection* pSel = 0;
+ ContentNode* pNode = GetEditDoc().SaveGetObject( nPara );
+ DBG_ASSERTWARNING( pNode, "Absatz existiert nicht: SelectParagraph" );
+ if ( pNode )
+ pSel = new EditSelection( EditPaM( pNode, 0 ), EditPaM( pNode, pNode->Len() ) );
+
+ return pSel;
+}
+
+void ImpEditEngine::FormatAndUpdate( EditView* pCurView )
+{
+ if ( bDowning )
+ return ;
+
+ if ( IsInUndo() )
+ IdleFormatAndUpdate( pCurView );
+ else
+ {
+ FormatDoc();
+ UpdateViews( pCurView );
+ }
+}
+
+void ImpEditEngine::SetFlatMode( sal_Bool bFlat )
+{
+ if ( bFlat != aStatus.UseCharAttribs() )
+ return;
+
+ if ( !bFlat )
+ aStatus.TurnOnFlags( EE_CNTRL_USECHARATTRIBS );
+ else
+ aStatus.TurnOffFlags( EE_CNTRL_USECHARATTRIBS );
+
+ aEditDoc.CreateDefFont( !bFlat );
+
+ FormatFullDoc();
+ UpdateViews( (EditView*) 0);
+ if ( pActiveView )
+ pActiveView->ShowCursor();
+}
+
+void ImpEditEngine::SetCharStretching( sal_uInt16 nX, sal_uInt16 nY )
+{
+ if ( !IsVertical() )
+ {
+ nStretchX = nX;
+ nStretchY = nY;
+ }
+ else
+ {
+ nStretchX = nY;
+ nStretchY = nX;
+ }
+
+ if ( aStatus.DoStretch() )
+ {
+ FormatFullDoc();
+ UpdateViews( GetActiveView() );
+ }
+}
+
+void ImpEditEngine::DoStretchChars( sal_uInt16 nX, sal_uInt16 nY )
+{
+ UndoActionStart( EDITUNDO_STRETCH );
+ sal_uInt16 nParas = GetEditDoc().Count();
+ for ( sal_uInt16 nPara = 0; nPara < nParas; nPara++ )
+ {
+ ContentNode* pNode = GetEditDoc()[nPara];
+ SfxItemSet aTmpSet( pNode->GetContentAttribs().GetItems() );
+
+ if ( nX != 100 )
+ {
+ // Fontbreite
+ SvxCharScaleWidthItem* pNewWidth = (SvxCharScaleWidthItem*) pNode->GetContentAttribs().GetItem( EE_CHAR_FONTWIDTH ).Clone();
+ sal_uInt32 nProp = pNewWidth->GetValue(); // sal_uInt32, kann temporaer gross werden
+ nProp *= nX;
+ nProp /= 100;
+ pNewWidth->SetValue( (sal_uInt16)nProp );
+ aTmpSet.Put( *pNewWidth );
+ delete pNewWidth;
+
+ // Kerning:
+ const SvxKerningItem& rKerningItem =
+ (const SvxKerningItem&)pNode->GetContentAttribs().GetItem( EE_CHAR_KERNING );
+ SvxKerningItem* pNewKerning = (SvxKerningItem*)rKerningItem.Clone();
+ long nKerning = pNewKerning->GetValue();
+ if ( nKerning > 0 )
+ {
+ nKerning *= nX;
+ nKerning /= 100;
+ }
+ else if ( nKerning < 0 )
+ {
+ // Bei Negativen Werten:
+ // Bei Stretching > 100 muessen die Werte kleiner werden und umgekehrt.
+ nKerning *= 100;
+ nKerning /= nX;
+ }
+ pNewKerning->SetValue( (short)nKerning );
+ aTmpSet.Put( *pNewKerning);
+ delete pNewKerning;
+ }
+ else
+ aTmpSet.ClearItem( EE_CHAR_FONTWIDTH );
+
+ if ( nY != 100 )
+ {
+ // Fonthoehe
+ for ( int nItem = 0; nItem < 3; nItem++ )
+ {
+ USHORT nItemId = EE_CHAR_FONTHEIGHT;
+ if ( nItem == 1 )
+ nItemId = EE_CHAR_FONTHEIGHT_CJK;
+ else if ( nItem == 2 )
+ nItemId = EE_CHAR_FONTHEIGHT_CTL;
+
+ const SvxFontHeightItem& rHeightItem =
+ (const SvxFontHeightItem&)pNode->GetContentAttribs().GetItem( nItemId );
+ SvxFontHeightItem* pNewHeight = (SvxFontHeightItem*)rHeightItem.Clone();
+ sal_uInt32 nHeight = pNewHeight->GetHeight();
+ nHeight *= nY;
+ nHeight /= 100;
+ pNewHeight->SetHeightValue( nHeight );
+ aTmpSet.Put( *pNewHeight );
+ delete pNewHeight;
+ }
+
+ // Absatzabstaende
+ const SvxULSpaceItem& rULSpaceItem =
+ (const SvxULSpaceItem&)pNode->GetContentAttribs().GetItem( EE_PARA_ULSPACE );
+ SvxULSpaceItem* pNewUL = (SvxULSpaceItem*)rULSpaceItem.Clone();
+ sal_uInt32 nUpper = pNewUL->GetUpper();
+ nUpper *= nY;
+ nUpper /= 100;
+ pNewUL->SetUpper( (sal_uInt16)nUpper );
+ sal_uInt32 nLower = pNewUL->GetLower();
+ nLower *= nY;
+ nLower /= 100;
+ pNewUL->SetLower( (sal_uInt16)nLower );
+ aTmpSet.Put( *pNewUL );
+ delete pNewUL;
+ }
+ else
+ aTmpSet.ClearItem( EE_CHAR_FONTHEIGHT );
+
+ SetParaAttribs( nPara, aTmpSet );
+
+ // harte Attribute:
+ sal_uInt16 nLastEnd = 0; // damit nach entfernen und neu nicht nochmal
+ CharAttribArray& rAttribs = pNode->GetCharAttribs().GetAttribs();
+ sal_uInt16 nAttribs = rAttribs.Count();
+ for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ )
+ {
+ EditCharAttrib* pAttr = rAttribs[nAttr];
+ if ( pAttr->GetStart() >= nLastEnd )
+ {
+ sal_uInt16 nWhich = pAttr->Which();
+ SfxPoolItem* pNew = 0;
+ if ( nWhich == EE_CHAR_FONTHEIGHT )
+ {
+ SvxFontHeightItem* pNewHeight = (SvxFontHeightItem*)pAttr->GetItem()->Clone();
+ sal_uInt32 nHeight = pNewHeight->GetHeight();
+ nHeight *= nY;
+ nHeight /= 100;
+ pNewHeight->SetHeightValue( nHeight );
+ pNew = pNewHeight;
+ }
+ else if ( nWhich == EE_CHAR_FONTWIDTH )
+ {
+ SvxCharScaleWidthItem* pNewWidth = (SvxCharScaleWidthItem*)pAttr->GetItem()->Clone();
+ sal_uInt32 nProp = pNewWidth->GetValue();
+ nProp *= nX;
+ nProp /= 100;
+ pNewWidth->SetValue( (sal_uInt16)nProp );
+ pNew = pNewWidth;
+ }
+ else if ( nWhich == EE_CHAR_KERNING )
+ {
+ SvxKerningItem* pNewKerning = (SvxKerningItem*)pAttr->GetItem()->Clone();
+ long nKerning = pNewKerning->GetValue();
+ if ( nKerning > 0 )
+ {
+ nKerning *= nX;
+ nKerning /= 100;
+ }
+ else if ( nKerning < 0 )
+ {
+ // Bei Negativen Werten:
+ // Bei Stretching > 100 muessen die Werte kleiner werden und umgekehrt.
+ nKerning *= 100;
+ nKerning /= nX;
+ }
+ pNewKerning->SetValue( (short)nKerning );
+ pNew = pNewKerning;
+ }
+ if ( pNew )
+ {
+ SfxItemSet _aTmpSet( GetEmptyItemSet() );
+ _aTmpSet.Put( *pNew );
+ SetAttribs( EditSelection( EditPaM( pNode, pAttr->GetStart() ),
+ EditPaM( pNode, pAttr->GetEnd() ) ), _aTmpSet );
+
+ nLastEnd = pAttr->GetEnd();
+ delete pNew;
+ }
+ }
+ }
+ }
+ UndoActionEnd( EDITUNDO_STRETCH );
+}
+
+const SvxNumberFormat* ImpEditEngine::GetNumberFormat( const ContentNode *pNode ) const
+{
+ const SvxNumberFormat *pRes = 0;
+
+ if (pNode)
+ {
+ // get index of paragraph
+ USHORT nPara = GetEditDoc().GetPos( const_cast< ContentNode * >(pNode) );
+ DBG_ASSERT( nPara < USHRT_MAX, "node not found in array" );
+ if (nPara < USHRT_MAX)
+ {
+ // the called function may be overloaded by an OutlinerEditEng object to provide
+ // access to the SvxNumberFormat of the Outliner.
+ // The EditEngine implementation will just return 0.
+ pRes = pEditEngine->GetNumberFormat( nPara );
+ }
+ }
+
+ return pRes;
+}
+
+sal_Int32 ImpEditEngine::GetSpaceBeforeAndMinLabelWidth(
+ const ContentNode *pNode,
+ sal_Int32 *pnSpaceBefore, sal_Int32 *pnMinLabelWidth ) const
+{
+ // nSpaceBefore matches the ODF attribut text:space-before
+ // nMinLabelWidth matches the ODF attribut text:min-label-width
+
+ const SvxNumberFormat *pNumFmt = GetNumberFormat( pNode );
+
+ // if no number format was found we have no Outliner or the numbering level
+ // within the Outliner is -1 which means no number format should be applied.
+ // Thus the default values to be returned are 0.
+ sal_Int32 nSpaceBefore = 0;
+ sal_Int32 nMinLabelWidth = 0;
+
+ if (pNumFmt)
+ {
+ nMinLabelWidth = -pNumFmt->GetFirstLineOffset();
+ nSpaceBefore = pNumFmt->GetAbsLSpace() - nMinLabelWidth;
+ DBG_ASSERT( nMinLabelWidth >= 0, "ImpEditEngine::GetSpaceBeforeAndMinLabelWidth: min-label-width < 0 encountered" );
+ }
+ if (pnSpaceBefore)
+ *pnSpaceBefore = nSpaceBefore;
+ if (pnMinLabelWidth)
+ *pnMinLabelWidth = nMinLabelWidth;
+
+ return nSpaceBefore + nMinLabelWidth;
+}
+
+const SvxLRSpaceItem& ImpEditEngine::GetLRSpaceItem( ContentNode* pNode )
+{
+ return (const SvxLRSpaceItem&)pNode->GetContentAttribs().GetItem( aStatus.IsOutliner() ? EE_PARA_OUTLLRSPACE : EE_PARA_LRSPACE );
+}
+
+// Either sets the digit mode at the output device or
+// modifies the passed string according to the text numeral setting:
+void ImpEditEngine::ImplInitDigitMode( OutputDevice* pOutDev, String* pString, xub_StrLen nStt, xub_StrLen nLen, LanguageType eCurLang )
+{
+ // #114278# Also setting up digit language from Svt options
+ // (cannot reliably inherit the outdev's setting)
+ if( !pCTLOptions )
+ pCTLOptions = new SvtCTLOptions;
+
+ LanguageType eLang = eCurLang;
+ const SvtCTLOptions::TextNumerals nCTLTextNumerals = pCTLOptions->GetCTLTextNumerals();
+
+ if ( SvtCTLOptions::NUMERALS_HINDI == nCTLTextNumerals )
+ eLang = LANGUAGE_ARABIC_SAUDI_ARABIA;
+ else if ( SvtCTLOptions::NUMERALS_ARABIC == nCTLTextNumerals )
+ eLang = LANGUAGE_ENGLISH;
+ else if ( SvtCTLOptions::NUMERALS_SYSTEM == nCTLTextNumerals )
+ eLang = (LanguageType) Application::GetSettings().GetLanguage();
+
+ if(pOutDev)
+ {
+ pOutDev->SetDigitLanguage( eLang );
+ }
+ else if (pString)
+ {
+ // see sallayout.cxx in vcl
+ int nOffset;
+ switch( eLang & LANGUAGE_MASK_PRIMARY )
+ {
+ default:
+ nOffset = 0;
+ break;
+ case LANGUAGE_ARABIC_SAUDI_ARABIA & LANGUAGE_MASK_PRIMARY:
+ nOffset = 0x0660 - '0'; // arabic-indic digits
+ break;
+ case LANGUAGE_URDU & LANGUAGE_MASK_PRIMARY:
+ case LANGUAGE_PUNJABI & LANGUAGE_MASK_PRIMARY: //???
+ case LANGUAGE_SINDHI & LANGUAGE_MASK_PRIMARY:
+ nOffset = 0x06F0 - '0'; // eastern arabic-indic digits
+ break;
+ }
+ if (nOffset)
+ {
+ const xub_StrLen nEnd = nStt + nLen;
+ for( xub_StrLen nIdx = nStt; nIdx < nEnd; ++nIdx )
+ {
+ sal_Unicode nChar = pString->GetChar( nIdx );
+ if( (nChar < '0') || ('9' < nChar) )
+ continue;
+ nChar = (sal_Unicode)(nChar + nOffset);
+ pString->SetChar( nIdx, nChar );
+ }
+ }
+ }
+}
+
+void ImpEditEngine::ImplInitLayoutMode( OutputDevice* pOutDev, USHORT nPara, USHORT nIndex )
+{
+ BOOL bCTL = FALSE;
+ BYTE bR2L = FALSE;
+ if ( nIndex == 0xFFFF )
+ {
+ bCTL = HasScriptType( nPara, i18n::ScriptType::COMPLEX );
+ bR2L = IsRightToLeft( nPara );
+ }
+ else
+ {
+ ContentNode* pNode = GetEditDoc().SaveGetObject( nPara );
+ short nScriptType = GetScriptType( EditPaM( pNode, nIndex+1 ) );
+ bCTL = nScriptType == i18n::ScriptType::COMPLEX;
+ bR2L = GetRightToLeft( nPara, nIndex + 1); // this change was discussed in issue 37190
+ // it also works for issue 55927
+ }
+
+ ULONG nLayoutMode = pOutDev->GetLayoutMode();
+
+ // We always use the left postion for DrawText()
+ nLayoutMode &= ~(TEXT_LAYOUT_BIDI_RTL);
+
+ if ( !bCTL && !bR2L)
+ {
+ // No CTL/Bidi checking neccessary
+ nLayoutMode |= ( TEXT_LAYOUT_COMPLEX_DISABLED | TEXT_LAYOUT_BIDI_STRONG );
+ }
+ else
+ {
+ // CTL/Bidi checking neccessary
+ // Don't use BIDI_STRONG, VCL must do some checks.
+ nLayoutMode &= ~( TEXT_LAYOUT_COMPLEX_DISABLED | TEXT_LAYOUT_BIDI_STRONG );
+
+ if ( bR2L )
+ nLayoutMode |= TEXT_LAYOUT_BIDI_RTL|TEXT_LAYOUT_TEXTORIGIN_LEFT;
+ }
+
+ pOutDev->SetLayoutMode( nLayoutMode );
+
+ // #114278# Also setting up digit language from Svt options
+ // (cannot reliably inherit the outdev's setting)
+ LanguageType eLang;
+
+ if( !pCTLOptions )
+ pCTLOptions = new SvtCTLOptions;
+
+ if ( SvtCTLOptions::NUMERALS_HINDI == pCTLOptions->GetCTLTextNumerals() )
+ eLang = LANGUAGE_ARABIC_SAUDI_ARABIA;
+ else if ( SvtCTLOptions::NUMERALS_ARABIC == pCTLOptions->GetCTLTextNumerals() )
+ eLang = LANGUAGE_ENGLISH;
+ else
+ eLang = (LanguageType) Application::GetSettings().GetLanguage();
+
+ pOutDev->SetDigitLanguage( eLang );
+}
+
+Reference < i18n::XBreakIterator > ImpEditEngine::ImplGetBreakIterator() const
+{
+ if ( !xBI.is() )
+ {
+ Reference< lang::XMultiServiceFactory > xMSF( ::comphelper::getProcessServiceFactory() );
+ xBI.set( xMSF->createInstance( OUString::createFromAscii( "com.sun.star.i18n.BreakIterator" ) ), UNO_QUERY );
+ }
+ return xBI;
+}
+
+Reference < i18n::XExtendedInputSequenceChecker > ImpEditEngine::ImplGetInputSequenceChecker() const
+{
+ if ( !xISC.is() )
+ {
+ Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory();
+ Reference < XInterface > xI = xMSF->createInstance( OUString::createFromAscii( "com.sun.star.i18n.InputSequenceChecker" ) );
+ if ( xI.is() )
+ {
+ Any x = xI->queryInterface( ::getCppuType((const Reference< i18n::XExtendedInputSequenceChecker >*)0) );
+ x >>= xISC;
+ }
+ }
+ return xISC;
+}
+
+Color ImpEditEngine::GetAutoColor() const
+{
+ Color aColor = const_cast<ImpEditEngine*>(this)->GetColorConfig().GetColorValue( svtools::FONTCOLOR ).nColor;
+
+ if ( GetBackgroundColor() != COL_AUTO )
+ {
+ if ( GetBackgroundColor().IsDark() && aColor.IsDark() )
+ aColor = COL_WHITE;
+ else if ( GetBackgroundColor().IsBright() && aColor.IsBright() )
+ aColor = COL_BLACK;
+ }
+
+ return aColor;
+}
+
+
+BOOL ImpEditEngine::ImplCalcAsianCompression( ContentNode* pNode, TextPortion* pTextPortion, USHORT nStartPos, sal_Int32* pDXArray, USHORT n100thPercentFromMax, BOOL bManipulateDXArray )
+{
+ DBG_ASSERT( GetAsianCompressionMode(), "ImplCalcAsianCompression - Why?" );
+ DBG_ASSERT( pTextPortion->GetLen(), "ImplCalcAsianCompression - Empty Portion?" );
+
+ // Percent is 1/100 Percent...
+
+ if ( n100thPercentFromMax == 10000 )
+ pTextPortion->SetExtraInfos( NULL );
+
+ BOOL bCompressed = FALSE;
+
+ if ( GetScriptType( EditPaM( pNode, nStartPos+1 ) ) == i18n::ScriptType::ASIAN )
+ {
+ long nNewPortionWidth = pTextPortion->GetSize().Width();
+ USHORT nPortionLen = pTextPortion->GetLen();
+ for ( USHORT n = 0; n < nPortionLen; n++ )
+ {
+ BYTE nType = GetCharTypeForCompression( pNode->GetChar( n+nStartPos ) );
+
+ BOOL bCompressPunctuation = ( nType == CHAR_PUNCTUATIONLEFT ) || ( nType == CHAR_PUNCTUATIONRIGHT );
+ BOOL bCompressKana = ( nType == CHAR_KANA ) && ( GetAsianCompressionMode() == text::CharacterCompressionType::PUNCTUATION_AND_KANA );
+
+ // create Extra infos only if needed...
+ if ( bCompressPunctuation || bCompressKana )
+ {
+ if ( !pTextPortion->GetExtraInfos() )
+ {
+ ExtraPortionInfo* pExtraInfos = new ExtraPortionInfo;
+ pTextPortion->SetExtraInfos( pExtraInfos );
+ pExtraInfos->nOrgWidth = pTextPortion->GetSize().Width();
+ pExtraInfos->nAsianCompressionTypes = CHAR_NORMAL;
+ }
+ pTextPortion->GetExtraInfos()->nMaxCompression100thPercent = n100thPercentFromMax;
+ pTextPortion->GetExtraInfos()->nAsianCompressionTypes |= nType;
+// pTextPortion->GetExtraInfos()->nCompressedChars++;
+
+ long nOldCharWidth;
+ if ( (n+1) < nPortionLen )
+ {
+ nOldCharWidth = pDXArray[n];
+ }
+ else
+ {
+ if ( bManipulateDXArray )
+ nOldCharWidth = nNewPortionWidth - pTextPortion->GetExtraInfos()->nPortionOffsetX;
+ else
+ nOldCharWidth = pTextPortion->GetExtraInfos()->nOrgWidth;
+ }
+ nOldCharWidth -= ( n ? pDXArray[n-1] : 0 );
+
+ long nCompress = 0;
+
+ if ( bCompressPunctuation )
+ {
+ // pTextPortion->GetExtraInfos()->nComressionWeight += 5;
+ nCompress = nOldCharWidth / 2;
+ }
+ else // Kana
+ {
+ // pTextPortion->GetExtraInfos()->nComressionWeight += 1;
+ nCompress = nOldCharWidth / 10;
+ }
+
+ if ( n100thPercentFromMax != 10000 )
+ {
+ nCompress *= n100thPercentFromMax;
+ nCompress /= 10000;
+ }
+
+ if ( nCompress )
+ {
+ bCompressed = TRUE;
+ nNewPortionWidth -= nCompress;
+ pTextPortion->GetExtraInfos()->bCompressed = TRUE;
+
+
+ // Special handling for rightpunctuation: For the 'compression' we must
+ // start th eoutput before the normal char position....
+ if ( bManipulateDXArray && ( pTextPortion->GetLen() > 1 ) )
+ {
+ if ( !pTextPortion->GetExtraInfos()->pOrgDXArray )
+ pTextPortion->GetExtraInfos()->SaveOrgDXArray( pDXArray, pTextPortion->GetLen()-1 );
+
+ if ( nType == CHAR_PUNCTUATIONRIGHT )
+ {
+ // If it's the first char, I must handle it in Paint()...
+ if ( n )
+ {
+ // -1: No entry for the last character
+ for ( USHORT i = n-1; i < (nPortionLen-1); i++ )
+ pDXArray[i] -= nCompress;
+ }
+ else
+ {
+ pTextPortion->GetExtraInfos()->bFirstCharIsRightPunktuation = TRUE;
+ pTextPortion->GetExtraInfos()->nPortionOffsetX = -nCompress;
+ }
+ }
+ else
+ {
+ // -1: No entry for the last character
+ for ( USHORT i = n; i < (nPortionLen-1); i++ )
+ pDXArray[i] -= nCompress;
+ }
+ }
+ }
+ }
+ }
+
+ if ( bCompressed && ( n100thPercentFromMax == 10000 ) )
+ pTextPortion->GetExtraInfos()->nWidthFullCompression = nNewPortionWidth;
+
+ pTextPortion->GetSize().Width() = nNewPortionWidth;
+
+ if ( pTextPortion->GetExtraInfos() && ( n100thPercentFromMax != 10000 ) )
+ {
+ // Maybe rounding errors in nNewPortionWidth, assure that width not bigger than expected
+ long nShrink = pTextPortion->GetExtraInfos()->nOrgWidth - pTextPortion->GetExtraInfos()->nWidthFullCompression;
+ nShrink *= n100thPercentFromMax;
+ nShrink /= 10000;
+ long nNewWidth = pTextPortion->GetExtraInfos()->nOrgWidth - nShrink;
+ if ( nNewWidth < pTextPortion->GetSize().Width() )
+ pTextPortion->GetSize().Width() = nNewWidth;
+ }
+ }
+ return bCompressed;
+}
+
+
+void ImpEditEngine::ImplExpandCompressedPortions( EditLine* pLine, ParaPortion* pParaPortion, long nRemainingWidth )
+{
+ BOOL bFoundCompressedPortion = FALSE;
+ long nCompressed = 0;
+// long nCompressWeight = 0;
+ TextPortionList aCompressedPortions;
+
+ USHORT nPortion = pLine->GetEndPortion();
+ TextPortion* pTP = pParaPortion->GetTextPortions()[ nPortion ];
+ while ( pTP && ( pTP->GetKind() == PORTIONKIND_TEXT ) )
+ {
+ if ( pTP->GetExtraInfos() && pTP->GetExtraInfos()->bCompressed )
+ {
+ bFoundCompressedPortion = TRUE;
+ nCompressed += pTP->GetExtraInfos()->nOrgWidth - pTP->GetSize().Width();
+ aCompressedPortions.Insert( pTP, aCompressedPortions.Count() );
+ }
+ pTP = ( nPortion > pLine->GetStartPortion() ) ? pParaPortion->GetTextPortions()[ --nPortion ] : NULL;
+ }
+
+ if ( bFoundCompressedPortion )
+ {
+ long nCompressPercent = 0;
+ if ( nCompressed > nRemainingWidth )
+ {
+ nCompressPercent = nCompressed - nRemainingWidth;
+ DBG_ASSERT( nCompressPercent < 200000, "ImplExpandCompressedPortions - Overflow!" );
+ nCompressPercent *= 10000;
+ nCompressPercent /= nCompressed;
+ }
+
+ for ( USHORT n = 0; n < aCompressedPortions.Count(); n++ )
+ {
+ pTP = aCompressedPortions[n];
+ pTP->GetExtraInfos()->bCompressed = FALSE;
+ pTP->GetSize().Width() = pTP->GetExtraInfos()->nOrgWidth;
+ if ( nCompressPercent )
+ {
+ USHORT nTxtPortion = pParaPortion->GetTextPortions().GetPos( pTP );
+ USHORT nTxtPortionStart = pParaPortion->GetTextPortions().GetStartPos( nTxtPortion );
+ DBG_ASSERT( nTxtPortionStart >= pLine->GetStart(), "Portion doesn't belong to the line!!!" );
+ sal_Int32* pDXArray = const_cast< sal_Int32* >( pLine->GetCharPosArray().GetData()+( nTxtPortionStart-pLine->GetStart() ) );
+ if ( pTP->GetExtraInfos()->pOrgDXArray )
+ memcpy( pDXArray, pTP->GetExtraInfos()->pOrgDXArray, (pTP->GetLen()-1)*sizeof(sal_Int32) );
+ ImplCalcAsianCompression( pParaPortion->GetNode(), pTP, nTxtPortionStart, pDXArray, (USHORT)nCompressPercent, TRUE );
+ }
+ }
+ }
+
+ aCompressedPortions.Remove( 0, aCompressedPortions.Count() );
+}
+
+// redesigned to work with TextMarkingVector
+void ImpEditEngine::ImplFillTextMarkingVector(const lang::Locale& rLocale, EEngineData::TextMarkingVector& rTextMarkingVector, const String& rTxt, const USHORT nIdx, const USHORT nLen) const
+{
+ // determine relevant logical text elements for the just-rendered
+ // string of characters.
+ Reference< i18n::XBreakIterator > _xBI(ImplGetBreakIterator());
+
+ if(_xBI.is())
+ {
+ sal_Int32 nDone;
+ sal_Int32 nNextCellBreak(_xBI->nextCharacters(rTxt, nIdx, rLocale, i18n::CharacterIteratorMode::SKIPCELL, 0, nDone));
+ i18n::Boundary nNextWordBoundary(_xBI->getWordBoundary(rTxt, nIdx, rLocale, i18n::WordType::ANY_WORD, sal_True));
+ sal_Int32 nNextSentenceBreak(_xBI->endOfSentence(rTxt, nIdx, rLocale));
+
+ const sal_Int32 nEndPos(nIdx + nLen);
+ sal_Int32 i;
+
+ for(i = nIdx; i < nEndPos; i++)
+ {
+ // create the entries for the respective break positions
+ if(i == nNextCellBreak)
+ {
+ rTextMarkingVector.push_back(EEngineData::TextMarkingClass(EEngineData::EndOfCaracter, i - nIdx));
+ nNextCellBreak = _xBI->nextCharacters(rTxt, i, rLocale, i18n::CharacterIteratorMode::SKIPCELL, 1, nDone);
+ }
+ if(i == nNextWordBoundary.endPos)
+ {
+ rTextMarkingVector.push_back(EEngineData::TextMarkingClass(EEngineData::EndOfWord, i - nIdx));
+ nNextWordBoundary = _xBI->getWordBoundary(rTxt, i + 1, rLocale, i18n::WordType::ANY_WORD, sal_True);
+ }
+ if(i == nNextSentenceBreak)
+ {
+ rTextMarkingVector.push_back(EEngineData::TextMarkingClass(EEngineData::EndOfSentence, i - nIdx));
+ nNextSentenceBreak = _xBI->endOfSentence(rTxt, i + 1, rLocale);
+ }
+ }
+ }
+}
+
+// eof
diff --git a/editeng/source/editeng/impedit4.cxx b/editeng/source/editeng/impedit4.cxx
new file mode 100644
index 000000000000..c45c6faf2b6a
--- /dev/null
+++ b/editeng/source/editeng/impedit4.cxx
@@ -0,0 +1,2955 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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();
+}
+
+
diff --git a/editeng/source/editeng/impedit5.cxx b/editeng/source/editeng/impedit5.cxx
new file mode 100644
index 000000000000..2efbb60b6c0f
--- /dev/null
+++ b/editeng/source/editeng/impedit5.cxx
@@ -0,0 +1,911 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 <eeng_pch.hxx>
+
+#include <impedit.hxx>
+#include <editeng/editeng.hxx>
+#include <editdbg.hxx>
+
+#include <svl/smplhint.hxx>
+
+
+#include <editeng/lrspitem.hxx>
+
+void ImpEditEngine::SetStyleSheetPool( SfxStyleSheetPool* pSPool )
+{
+ if ( pStylePool != pSPool )
+ {
+// if ( pStylePool )
+// EndListening( *pStylePool, TRUE );
+
+ pStylePool = pSPool;
+
+// if ( pStylePool )
+// StartListening( *pStylePool, TRUE );
+ }
+}
+
+SfxStyleSheet* ImpEditEngine::GetStyleSheet( USHORT nPara ) const
+{
+ ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
+ return pNode ? pNode->GetContentAttribs().GetStyleSheet() : NULL;
+}
+
+void ImpEditEngine::SetStyleSheet( EditSelection aSel, SfxStyleSheet* pStyle )
+{
+ aSel.Adjust( aEditDoc );
+
+ USHORT nStartPara = aEditDoc.GetPos( aSel.Min().GetNode() );
+ USHORT nEndPara = aEditDoc.GetPos( aSel.Max().GetNode() );
+
+ BOOL _bUpdate = GetUpdateMode();
+ SetUpdateMode( FALSE );
+
+ for ( USHORT n = nStartPara; n <= nEndPara; n++ )
+ SetStyleSheet( n, pStyle );
+
+ SetUpdateMode( _bUpdate, 0 );
+}
+
+void ImpEditEngine::SetStyleSheet( USHORT nPara, SfxStyleSheet* pStyle )
+{
+ DBG_ASSERT( GetStyleSheetPool() || !pStyle, "SetStyleSheet: No StyleSheetPool registered!" );
+ ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
+ SfxStyleSheet* pCurStyle = pNode->GetStyleSheet();
+ if ( pStyle != pCurStyle )
+ {
+ if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
+ {
+ XubString aPrevStyleName;
+ if ( pCurStyle )
+ aPrevStyleName = pCurStyle->GetName();
+
+ XubString aNewStyleName;
+ if ( pStyle )
+ aNewStyleName = pStyle->GetName();
+
+ InsertUndo(
+ new EditUndoSetStyleSheet( this, aEditDoc.GetPos( pNode ),
+ aPrevStyleName, pCurStyle ? pCurStyle->GetFamily() : SFX_STYLE_FAMILY_PARA,
+ aNewStyleName, pStyle ? pStyle->GetFamily() : SFX_STYLE_FAMILY_PARA,
+ pNode->GetContentAttribs().GetItems() ) );
+ }
+ if ( pCurStyle )
+ EndListening( *pCurStyle, FALSE );
+ pNode->SetStyleSheet( pStyle, aStatus.UseCharAttribs() );
+ if ( pStyle )
+ StartListening( *pStyle, FALSE );
+ ParaAttribsChanged( pNode );
+ }
+ FormatAndUpdate();
+}
+
+void ImpEditEngine::UpdateParagraphsWithStyleSheet( SfxStyleSheet* pStyle )
+{
+ SvxFont aFontFromStyle;
+ CreateFont( aFontFromStyle, pStyle->GetItemSet() );
+
+ BOOL bUsed = FALSE;
+ for ( USHORT nNode = 0; nNode < aEditDoc.Count(); nNode++ )
+ {
+ ContentNode* pNode = aEditDoc.GetObject( nNode );
+ if ( pNode->GetStyleSheet() == pStyle )
+ {
+ bUsed = TRUE;
+ if ( aStatus.UseCharAttribs() )
+ pNode->SetStyleSheet( pStyle, aFontFromStyle );
+ else
+ pNode->SetStyleSheet( pStyle, FALSE );
+
+ ParaAttribsChanged( pNode );
+ }
+ }
+ if ( bUsed )
+ {
+ GetEditEnginePtr()->StyleSheetChanged( pStyle );
+ FormatAndUpdate();
+ }
+}
+
+void ImpEditEngine::RemoveStyleFromParagraphs( SfxStyleSheet* pStyle )
+{
+ for ( USHORT nNode = 0; nNode < aEditDoc.Count(); nNode++ )
+ {
+ ContentNode* pNode = aEditDoc.GetObject(nNode);
+ if ( pNode->GetStyleSheet() == pStyle )
+ {
+ pNode->SetStyleSheet( NULL );
+ ParaAttribsChanged( pNode );
+ }
+ }
+ FormatAndUpdate();
+}
+
+void ImpEditEngine::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ // Damit nicht beim Destruieren unnoetig formatiert wird:
+ if ( !bDowning )
+ {
+ DBG_CHKOBJ( GetEditEnginePtr(), EditEngine, 0 );
+
+ SfxStyleSheet* pStyle = NULL;
+ ULONG nId = 0;
+
+ if ( rHint.ISA( SfxStyleSheetHint ) )
+ {
+ const SfxStyleSheetHint& rH = (const SfxStyleSheetHint&) rHint;
+ DBG_ASSERT( rH.GetStyleSheet()->ISA( SfxStyleSheet ), "Kein SfxStyleSheet!" );
+ pStyle = (SfxStyleSheet*) rH.GetStyleSheet();
+ nId = rH.GetHint();
+ }
+ else if ( ( rHint.Type() == TYPE(SfxSimpleHint ) ) && ( rBC.ISA( SfxStyleSheet ) ) )
+ {
+ pStyle = (SfxStyleSheet*)&rBC;
+ nId = ((SfxSimpleHint&)rHint).GetId();
+ }
+
+ if ( pStyle )
+ {
+ if ( ( nId == SFX_HINT_DYING ) ||
+ ( nId == SFX_STYLESHEET_INDESTRUCTION ) ||
+ ( nId == SFX_STYLESHEET_ERASED ) )
+ {
+ RemoveStyleFromParagraphs( pStyle );
+ }
+ else if ( ( nId == SFX_HINT_DATACHANGED ) ||
+ ( nId == SFX_STYLESHEET_MODIFIED ) )
+ {
+ UpdateParagraphsWithStyleSheet( pStyle );
+
+ // Alle Absaetze mit EditStyles, die das geaenderte Style
+ // irgendwie als Parent haben, muessen formatiert werden.
+ // ULONG nStyles = pMyStylePool->GetStyles().Count();
+ // for ( ULONG nStyle = 0; nStyle < nStyles; nStyle++ )
+ // {
+ // EditStyleSheet* pES = (EditStyleSheet*)pMyStylePool->GetStyles().GetObject( nStyle );
+ // DBG_ASSERT( pES, "NULL-Pointer im StyleSheetPool!" );
+ // if ( pES->IsUsed() && pES->HasStyleAsAnyParent( *pStyle ) )
+ // UpdateParagraphsWithStyleSheet( pES );
+ // }
+ }
+ }
+ }
+}
+
+EditUndoSetAttribs* ImpEditEngine::CreateAttribUndo( EditSelection aSel, const SfxItemSet& rSet )
+{
+ DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "CreateAttribUndo: Fehlerhafte Selektion" );
+ aSel.Adjust( aEditDoc );
+
+ ESelection aESel( CreateESel( aSel ) );
+
+ USHORT nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
+ USHORT nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
+
+ DBG_ASSERT( nStartNode <= nEndNode, "CreateAttribUndo: Start > End ?!" );
+
+ EditUndoSetAttribs* pUndo = NULL;
+ if ( rSet.GetPool() != &aEditDoc.GetItemPool() )
+ {
+ SfxItemSet aTmpSet( GetEmptyItemSet() );
+ aTmpSet.Put( rSet );
+ pUndo = new EditUndoSetAttribs( this, aESel, aTmpSet );
+ }
+ else
+ {
+ pUndo = new EditUndoSetAttribs( this, aESel, rSet );
+ }
+
+ SfxItemPool* pPool = pUndo->GetNewAttribs().GetPool();
+
+ for ( USHORT nPara = nStartNode; nPara <= nEndNode; nPara++ )
+ {
+ ContentNode* pNode = aEditDoc.GetObject( nPara );
+ DBG_ASSERT( aEditDoc.SaveGetObject( nPara ), "Node nicht gefunden: CreateAttribUndo" );
+ ContentAttribsInfo* pInf = new ContentAttribsInfo( pNode->GetContentAttribs().GetItems() );
+ pUndo->GetContentInfos().Insert( pInf, pUndo->GetContentInfos().Count() );
+
+ for ( USHORT nAttr = 0; nAttr < pNode->GetCharAttribs().Count(); nAttr++ )
+ {
+ EditCharAttribPtr pAttr = pNode->GetCharAttribs().GetAttribs()[ nAttr ];
+ if ( pAttr->GetLen() )
+ {
+ EditCharAttribPtr pNew = MakeCharAttrib( *pPool, *pAttr->GetItem(), pAttr->GetStart(), pAttr->GetEnd() );
+ pInf->GetPrevCharAttribs().Insert( pNew, pInf->GetPrevCharAttribs().Count() );
+ }
+ }
+ }
+ return pUndo;
+}
+
+void ImpEditEngine::UndoActionStart( USHORT nId, const ESelection& aSel )
+{
+ if ( IsUndoEnabled() && !IsInUndo() )
+ {
+ GetUndoManager().EnterListAction( GetEditEnginePtr()->GetUndoComment( nId ), XubString(), nId );
+ DBG_ASSERT( !pUndoMarkSelection, "UndoAction SelectionMarker?" );
+ pUndoMarkSelection = new ESelection( aSel );
+ }
+}
+
+void ImpEditEngine::UndoActionStart( USHORT nId )
+{
+ if ( IsUndoEnabled() && !IsInUndo() )
+ {
+ GetUndoManager().EnterListAction( GetEditEnginePtr()->GetUndoComment( nId ), XubString(), nId );
+ DBG_ASSERT( !pUndoMarkSelection, "UndoAction SelectionMarker?" );
+ }
+}
+
+void ImpEditEngine::UndoActionEnd( USHORT )
+{
+ if ( IsUndoEnabled() && !IsInUndo() )
+ {
+ GetUndoManager().LeaveListAction();
+ delete pUndoMarkSelection;
+ pUndoMarkSelection = NULL;
+ }
+}
+
+void ImpEditEngine::InsertUndo( EditUndo* pUndo, BOOL bTryMerge )
+{
+ DBG_ASSERT( !IsInUndo(), "InsertUndo im Undomodus!" );
+ if ( pUndoMarkSelection )
+ {
+ EditUndoMarkSelection* pU = new EditUndoMarkSelection( this, *pUndoMarkSelection );
+ GetUndoManager().AddUndoAction( pU, FALSE );
+ delete pUndoMarkSelection;
+ pUndoMarkSelection = NULL;
+ }
+ GetUndoManager().AddUndoAction( pUndo, bTryMerge );
+
+ mbLastTryMerge = bTryMerge;
+}
+
+void ImpEditEngine::ResetUndoManager()
+{
+ if ( HasUndoManager() )
+ GetUndoManager().Clear();
+}
+
+void ImpEditEngine::EnableUndo( BOOL bEnable )
+{
+ // Beim Umschalten des Modus Liste loeschen:
+ if ( bEnable != IsUndoEnabled() )
+ ResetUndoManager();
+
+ bUndoEnabled = bEnable;
+}
+
+BOOL ImpEditEngine::Undo( EditView* pView )
+{
+ if ( HasUndoManager() && GetUndoManager().GetUndoActionCount() )
+ {
+ SetActiveView( pView );
+ GetUndoManager().Undo( 1 );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL ImpEditEngine::Redo( EditView* pView )
+{
+ if ( HasUndoManager() && GetUndoManager().GetRedoActionCount() )
+ {
+ SetActiveView( pView );
+ GetUndoManager().Redo( 0 );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL ImpEditEngine::Repeat( EditView* /* pView */ )
+{
+ if ( HasUndoManager() && GetUndoManager().GetRepeatActionCount() )
+ {
+ DBG_WARNING( "Repeat nicht implementiert!" );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+SfxItemSet ImpEditEngine::GetAttribs( EditSelection aSel, BOOL bOnlyHardAttrib )
+{
+ DBG_CHKOBJ( GetEditEnginePtr(), EditEngine, 0 );
+
+ aSel.Adjust( aEditDoc );
+
+#if OSL_DEBUG_LEVEL > 1
+// if ( ( aSel.Min().GetNode() == aSel.Max().GetNode() ) && ( bOnlyHardAttrib == EditEngineAttribs_All ) )
+// return GetAttribs( aEditDoc.GetPos( aSel.Min().GetNode() ), aSel.Min().GetIndex(), aSel.Max().GetIndex(), GETATTRIBS_ALL );
+#endif
+
+
+ SfxItemSet aCurSet( GetEmptyItemSet() );
+
+ USHORT nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
+ USHORT nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
+
+ // ueber die Absaetze iterieren...
+ for ( USHORT nNode = nStartNode; nNode <= nEndNode; nNode++ )
+ {
+ ContentNode* pNode = aEditDoc.GetObject( nNode );
+ DBG_ASSERT( aEditDoc.SaveGetObject( nNode ), "Node nicht gefunden: GetAttrib" );
+
+ 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();
+
+ // Problem: Vorlagen....
+ // => Andersrum:
+ // 1) Harte Zeichenattribute, wie gehabt...
+ // 2) Nur wenn OFF, Style and Absatzattr. pruefen...
+
+ // Erst die ganz harte Formatierung...
+ aEditDoc.FindAttribs( pNode, nStartPos, nEndPos, aCurSet );
+
+ if( bOnlyHardAttrib != EditEngineAttribs_OnlyHard )
+ {
+ // Und dann Absatzformatierung und Vorlage...
+ // SfxStyleSheet* pStyle = pNode->GetStyleSheet();
+ for ( USHORT nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
+ {
+ if ( aCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF )
+ {
+ if ( bOnlyHardAttrib == EditEngineAttribs_All )
+ {
+ const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItem( nWhich );
+ aCurSet.Put( rItem );
+ }
+ else if ( pNode->GetContentAttribs().GetItems().GetItemState( nWhich ) == SFX_ITEM_ON )
+ {
+ const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItems().Get( nWhich );
+ aCurSet.Put( rItem );
+ }
+ }
+ else if ( aCurSet.GetItemState( nWhich ) == SFX_ITEM_ON )
+ {
+ const SfxPoolItem* pItem = NULL;
+ if ( bOnlyHardAttrib == EditEngineAttribs_All )
+ {
+ pItem = &pNode->GetContentAttribs().GetItem( nWhich );
+ }
+ else if ( pNode->GetContentAttribs().GetItems().GetItemState( nWhich ) == SFX_ITEM_ON )
+ {
+ pItem = &pNode->GetContentAttribs().GetItems().Get( nWhich );
+ }
+ // pItem can only be NULL when bOnlyHardAttrib...
+ if ( !pItem || ( *pItem != aCurSet.Get( nWhich ) ) )
+ {
+ // Problem: Wenn Absatzvorlage mit z.B. Font,
+ // aber Font hart und anders und komplett in Selektion
+ // Falsch, wenn invalidiert....
+ // => Lieber nicht invalidieren, UMSTELLEN!
+ // Besser waere, Absatzweise ein ItemSet zu fuellen
+ // und dieses mit dem gesmten vergleichen.
+ // aCurSet.InvalidateItem( nWhich );
+ if ( nWhich <= EE_PARA_END )
+ aCurSet.InvalidateItem( nWhich );
+ }
+ }
+ }
+ }
+ }
+
+ // Leere Slots mit Defaults fuellen...
+ if ( bOnlyHardAttrib == EditEngineAttribs_All )
+ {
+ for ( USHORT nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++ )
+ {
+ if ( aCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF )
+ {
+ aCurSet.Put( aEditDoc.GetItemPool().GetDefaultItem( nWhich ) );
+ }
+ }
+ }
+ return aCurSet;
+}
+
+
+SfxItemSet ImpEditEngine::GetAttribs( USHORT nPara, USHORT nStart, USHORT nEnd, sal_uInt8 nFlags ) const
+{
+ // MT: #94002# Optimized function with less Puts(), which cause unnecessary cloning from default items.
+ // If this works, change GetAttribs( EditSelection ) to use this for each paragraph and merge the results!
+
+ DBG_CHKOBJ( GetEditEnginePtr(), EditEngine, 0 );
+
+ ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
+ DBG_ASSERT( pNode, "GetAttribs - unknown paragraph!" );
+ DBG_ASSERT( nStart <= nEnd, "getAttribs: Start > End not supported!" );
+
+ SfxItemSet aAttribs( ((ImpEditEngine*)this)->GetEmptyItemSet() );
+
+ if ( pNode )
+ {
+ if ( nEnd > pNode->Len() )
+ nEnd = pNode->Len();
+
+ if ( nStart > nEnd )
+ nStart = nEnd;
+
+ // StyleSheet / Parattribs...
+
+ if ( pNode->GetStyleSheet() && ( nFlags & GETATTRIBS_STYLESHEET ) )
+ aAttribs.Set( pNode->GetStyleSheet()->GetItemSet(), TRUE );
+
+ if ( nFlags & GETATTRIBS_PARAATTRIBS )
+ aAttribs.Put( pNode->GetContentAttribs().GetItems() );
+
+ // CharAttribs...
+
+ if ( nFlags & GETATTRIBS_CHARATTRIBS )
+ {
+ // Make testing easier...
+ pNode->GetCharAttribs().OptimizeRanges( ((ImpEditEngine*)this)->GetEditDoc().GetItemPool() );
+
+ const CharAttribArray& rAttrs = pNode->GetCharAttribs().GetAttribs();
+ for ( USHORT nAttr = 0; nAttr < rAttrs.Count(); nAttr++ )
+ {
+ EditCharAttrib* pAttr = rAttrs.GetObject( nAttr );
+
+ if ( nStart == nEnd )
+ {
+ USHORT nCursorPos = nStart;
+ if ( ( pAttr->GetStart() <= nCursorPos ) && ( pAttr->GetEnd() >= nCursorPos ) )
+ {
+ // To be used the attribute has to start BEFORE the position, or it must be a
+ // new empty attr AT the position, or we are on position 0.
+ if ( ( pAttr->GetStart() < nCursorPos ) || pAttr->IsEmpty() || !nCursorPos )
+ {
+ // maybe this attrib ends here and a new attrib with 0 Len may follow and be valid here,
+ // but that s no problem, the empty item will come later and win.
+ aAttribs.Put( *pAttr->GetItem() );
+ }
+ }
+ }
+ else
+ {
+ // Check every attribute covering the area, partial or full.
+ if ( ( pAttr->GetStart() < nEnd ) && ( pAttr->GetEnd() > nStart ) )
+ {
+ if ( ( pAttr->GetStart() <= nStart ) && ( pAttr->GetEnd() >= nEnd ) )
+ {
+ // full coverage
+ aAttribs.Put( *pAttr->GetItem() );
+ }
+ else
+ {
+ // OptimizeRagnge() assures that not the same attr can follow for full coverage
+ // only partial, check with current, when using para/styhe, otherwise invalid.
+ if ( !( nFlags & (GETATTRIBS_PARAATTRIBS|GETATTRIBS_STYLESHEET) ) ||
+ ( *pAttr->GetItem() != aAttribs.Get( pAttr->Which() ) ) )
+ {
+ aAttribs.InvalidateItem( pAttr->Which() );
+ }
+ }
+ }
+ }
+
+ if ( pAttr->GetStart() > nEnd )
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ return aAttribs;
+}
+
+
+void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, BYTE nSpecial )
+{
+ aSel.Adjust( aEditDoc );
+
+ // Wenn keine Selektion => die Attribute aufs Wort anwenden.
+ // ( Der RTF-Perser sollte die Methode eigentlich nie ohne Range rufen )
+ if ( ( nSpecial == ATTRSPECIAL_WHOLEWORD ) && !aSel.HasRange() )
+ aSel = SelectWord( aSel, ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, FALSE );
+
+ USHORT nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
+ USHORT nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
+
+ if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
+ {
+ EditUndoSetAttribs* pUndo = CreateAttribUndo( aSel, rSet );
+ pUndo->SetSpecial( nSpecial );
+ InsertUndo( pUndo );
+ }
+
+ BOOL bCheckLanguage = FALSE;
+ if ( GetStatus().DoOnlineSpelling() )
+ {
+ bCheckLanguage = ( rSet.GetItemState( EE_CHAR_LANGUAGE ) == SFX_ITEM_ON ) ||
+ ( rSet.GetItemState( EE_CHAR_LANGUAGE_CJK ) == SFX_ITEM_ON ) ||
+ ( rSet.GetItemState( EE_CHAR_LANGUAGE_CTL ) == SFX_ITEM_ON );
+ }
+
+ // ueber die Absaetze iterieren...
+ for ( USHORT nNode = nStartNode; nNode <= nEndNode; nNode++ )
+ {
+ BOOL bParaAttribFound = FALSE;
+ BOOL bCharAttribFound = FALSE;
+
+ ContentNode* pNode = aEditDoc.GetObject( nNode );
+ ParaPortion* pPortion = GetParaPortions().GetObject( nNode );
+
+ DBG_ASSERT( aEditDoc.SaveGetObject( nNode ), "Node nicht gefunden: SetAttribs" );
+ DBG_ASSERT( GetParaPortions().GetObject( nNode ), "Portion nicht gefunden: SetAttribs" );
+
+ 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();
+
+ // ueber die Items iterieren...
+#ifdef EDITDEBUG
+// FILE* fp = fopen( "d:\\debug.log", "a" );
+// if ( fp )
+// {
+// fprintf( fp, "\n \n=> Zeichen-Attribute: Absatz %i, %i-%i\n", nNode, nStartPos, nEndPos );
+// DbgOutItemSet( fp, rSet, TRUE, FALSE );
+// fclose( fp );
+// }
+#endif
+
+ for ( USHORT nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
+ {
+ if ( rSet.GetItemState( nWhich ) == SFX_ITEM_ON )
+ {
+ const SfxPoolItem& rItem = rSet.Get( nWhich );
+ if ( nWhich <= EE_PARA_END )
+ {
+ pNode->GetContentAttribs().GetItems().Put( rItem );
+ bParaAttribFound = TRUE;
+ }
+ else
+ {
+ aEditDoc.InsertAttrib( pNode, nStartPos, nEndPos, rItem );
+ bCharAttribFound = TRUE;
+ if ( nSpecial == ATTRSPECIAL_EDGE )
+ {
+ CharAttribArray& rAttribs = pNode->GetCharAttribs().GetAttribs();
+ USHORT nAttrs = rAttribs.Count();
+ for ( USHORT n = 0; n < nAttrs; n++ )
+ {
+ EditCharAttrib* pAttr = rAttribs.GetObject( n );
+ if ( pAttr->GetStart() > nEndPos )
+ break;
+
+ if ( ( pAttr->GetEnd() == nEndPos ) && ( pAttr->Which() == nWhich ) )
+ {
+ pAttr->SetEdge( TRUE );
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ( bParaAttribFound )
+ {
+ ParaAttribsChanged( pPortion->GetNode() );
+ }
+ else if ( bCharAttribFound )
+ {
+ bFormatted = FALSE;
+ if ( !pNode->Len() || ( nStartPos != nEndPos ) )
+ {
+ pPortion->MarkSelectionInvalid( nStartPos, nEndPos-nStartPos );
+ if ( bCheckLanguage )
+ pNode->GetWrongList()->MarkInvalid( nStartPos, nEndPos );
+ }
+ }
+ }
+}
+
+void ImpEditEngine::RemoveCharAttribs( EditSelection aSel, BOOL bRemoveParaAttribs, USHORT nWhich )
+{
+ aSel.Adjust( aEditDoc );
+
+ USHORT nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
+ USHORT nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
+
+ const SfxItemSet* _pEmptyItemSet = bRemoveParaAttribs ? &GetEmptyItemSet() : 0;
+
+ if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
+ {
+ // Eventuel spezielles Undo, oder ItemSet*
+ EditUndoSetAttribs* pUndo = CreateAttribUndo( aSel, GetEmptyItemSet() );
+ pUndo->SetRemoveAttribs( TRUE );
+ pUndo->SetRemoveParaAttribs( bRemoveParaAttribs );
+ pUndo->SetRemoveWhich( nWhich );
+ InsertUndo( pUndo );
+ }
+
+ // ueber die Absaetze iterieren...
+ for ( USHORT nNode = nStartNode; nNode <= nEndNode; nNode++ )
+ {
+ ContentNode* pNode = aEditDoc.GetObject( nNode );
+ ParaPortion* pPortion = GetParaPortions().GetObject( nNode );
+
+ DBG_ASSERT( aEditDoc.SaveGetObject( nNode ), "Node nicht gefunden: SetAttribs" );
+ DBG_ASSERT( GetParaPortions().SaveGetObject( nNode ), "Portion nicht gefunden: SetAttribs" );
+
+ 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();
+
+ // Optimieren: Wenn ganzer Absatz, dann RemoveCharAttribs( nPara )?!
+ BOOL bChanged = aEditDoc.RemoveAttribs( pNode, nStartPos, nEndPos, nWhich );
+ if ( bRemoveParaAttribs )
+ {
+ SetParaAttribs( nNode, *_pEmptyItemSet ); // Invalidiert
+ }
+ else
+ {
+ // Bei 'Format-Standard' sollen auch die Zeichenattribute verschwinden,
+ // die von der DrawingEngine als Absatzattribute eingestellt wurden.
+ // Diese koennen sowieso nicht vom Anwender eingestellt worden sein.
+
+ // #106871# Not when nWhich
+ // Would have been better to offer a separate method for format/standard...
+ if ( !nWhich )
+ {
+ SfxItemSet aAttribs( GetParaAttribs( nNode ) );
+ for ( USHORT nW = EE_CHAR_START; nW <= EE_CHAR_END; nW++ )
+ aAttribs.ClearItem( nW );
+ SetParaAttribs( nNode, aAttribs );
+ }
+ }
+
+ if ( bChanged && !bRemoveParaAttribs )
+ {
+ bFormatted = FALSE;
+ pPortion->MarkSelectionInvalid( nStartPos, nEndPos-nStartPos );
+ }
+ }
+}
+
+typedef EditCharAttrib* EditCharAttribPtr;
+
+void ImpEditEngine::RemoveCharAttribs( USHORT nPara, USHORT nWhich, BOOL bRemoveFeatures )
+{
+ ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
+ ParaPortion* pPortion = GetParaPortions().SaveGetObject( nPara );
+
+ DBG_ASSERT( pNode, "Node nicht gefunden: RemoveCharAttribs" );
+ DBG_ASSERT( pPortion, "Portion nicht gefunden: RemoveCharAttribs" );
+
+ if ( !pNode )
+ return;
+
+ USHORT nAttr = 0;
+ EditCharAttribPtr pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
+ while ( pAttr )
+ {
+ if ( ( !pAttr->IsFeature() || bRemoveFeatures ) &&
+ ( !nWhich || ( pAttr->GetItem()->Which() == nWhich ) ) )
+ {
+ pNode->GetCharAttribs().GetAttribs().Remove( nAttr );
+ delete pAttr;
+ nAttr--;
+ }
+ nAttr++;
+ pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
+ }
+
+ pPortion->MarkSelectionInvalid( 0, pNode->Len() );
+}
+
+void ImpEditEngine::SetParaAttribs( USHORT nPara, const SfxItemSet& rSet )
+{
+ ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
+
+ if ( !pNode )
+ return;
+
+#ifdef EDITDEBUG
+// FILE* fp = fopen( "d:\\debug.log", "a" );
+// if ( fp )
+// {
+// fprintf( fp, "\n \n=> Absatz-Attribute: Absatz %i\n", nPara );
+// DbgOutItemSet( fp, rSet, TRUE, FALSE );
+// fclose( fp );
+// }
+#endif
+
+ if ( !( pNode->GetContentAttribs().GetItems() == rSet ) )
+ {
+ if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
+ {
+ if ( rSet.GetPool() != &aEditDoc.GetItemPool() )
+ {
+ SfxItemSet aTmpSet( GetEmptyItemSet() );
+ aTmpSet.Put( rSet );
+ InsertUndo( new EditUndoSetParaAttribs( this, nPara, pNode->GetContentAttribs().GetItems(), aTmpSet ) );
+ }
+ else
+ {
+ InsertUndo( new EditUndoSetParaAttribs( this, nPara, pNode->GetContentAttribs().GetItems(), rSet ) );
+ }
+ }
+ pNode->GetContentAttribs().GetItems().Set( rSet );
+ if ( aStatus.UseCharAttribs() )
+ pNode->CreateDefFont();
+
+ ParaAttribsChanged( pNode );
+ }
+}
+
+const SfxItemSet& ImpEditEngine::GetParaAttribs( USHORT nPara ) const
+{
+ ContentNode* pNode = aEditDoc.GetObject( nPara );
+ DBG_ASSERT( pNode, "Node nicht gefunden: GetParaAttribs" );
+ return pNode->GetContentAttribs().GetItems();
+}
+
+BOOL ImpEditEngine::HasParaAttrib( USHORT nPara, USHORT nWhich ) const
+{
+ ContentNode* pNode = aEditDoc.GetObject( nPara );
+ DBG_ASSERT( pNode, "Node nicht gefunden: HasParaAttrib" );
+
+ return pNode->GetContentAttribs().HasItem( nWhich );
+}
+
+const SfxPoolItem& ImpEditEngine::GetParaAttrib( USHORT nPara, USHORT nWhich ) const
+{
+ ContentNode* pNode = aEditDoc.GetObject( nPara );
+ DBG_ASSERT( pNode, "Node nicht gefunden: GetParaAttrib" );
+
+ return pNode->GetContentAttribs().GetItem( nWhich );
+}
+
+void ImpEditEngine::GetCharAttribs( USHORT nPara, EECharAttribArray& rLst ) const
+{
+ rLst.Remove( 0, rLst.Count() );
+ ContentNode* pNode = aEditDoc.GetObject( nPara );
+ if ( pNode )
+ {
+ for ( USHORT nAttr = 0; nAttr < pNode->GetCharAttribs().Count(); nAttr++ )
+ {
+ EditCharAttribPtr pAttr = pNode->GetCharAttribs().GetAttribs()[ nAttr ];
+ EECharAttrib aEEAttr;
+ aEEAttr.pAttr = pAttr->GetItem();
+ aEEAttr.nPara = nPara;
+ aEEAttr.nStart = pAttr->GetStart();
+ aEEAttr.nEnd = pAttr->GetEnd();
+ rLst.Insert( aEEAttr, rLst.Count() );
+ }
+ }
+}
+
+void ImpEditEngine::ParaAttribsToCharAttribs( ContentNode* pNode )
+{
+ pNode->GetCharAttribs().DeleteEmptyAttribs( GetEditDoc().GetItemPool() );
+ xub_StrLen nEndPos = pNode->Len();
+ for ( USHORT nWhich = EE_CHAR_START; nWhich <= EE_CHAR_END; nWhich++ )
+ {
+ if ( pNode->GetContentAttribs().HasItem( nWhich ) )
+ {
+ const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItem( nWhich );
+ // Die Luecken auffuellen:
+ USHORT nLastEnd = 0;
+ EditCharAttrib* pAttr = pNode->GetCharAttribs().FindNextAttrib( nWhich, nLastEnd );
+ while ( pAttr )
+ {
+ nLastEnd = pAttr->GetEnd();
+ if ( pAttr->GetStart() > nLastEnd )
+ aEditDoc.InsertAttrib( pNode, nLastEnd, pAttr->GetStart(), rItem );
+ // #112831# Last Attr might go from 0xffff to 0x0000
+ pAttr = nLastEnd ? pNode->GetCharAttribs().FindNextAttrib( nWhich, nLastEnd ) : NULL;
+ }
+
+ // Und den Rest:
+ if ( nLastEnd < nEndPos )
+ aEditDoc.InsertAttrib( pNode, nLastEnd, nEndPos, rItem );
+ }
+ }
+ bFormatted = FALSE;
+ // Portion braucht hier nicht invalidiert werden, geschieht woanders.
+}
+
+IdleFormattter::IdleFormattter()
+{
+ pView = 0;
+ nRestarts = 0;
+}
+
+IdleFormattter::~IdleFormattter()
+{
+ pView = 0;
+}
+
+void IdleFormattter::DoIdleFormat( EditView* pV )
+{
+ pView = pV;
+
+ if ( IsActive() )
+ nRestarts++;
+
+ if ( nRestarts > 4 )
+ ForceTimeout();
+ else
+ Start();
+}
+
+void IdleFormattter::ForceTimeout()
+{
+ if ( IsActive() )
+ {
+ Stop();
+ ((Link&)GetTimeoutHdl()).Call( this );
+ }
+}
+
+ImplIMEInfos::ImplIMEInfos( const EditPaM& rPos, const String& rOldTextAfterStartPos )
+ : aOldTextAfterStartPos( rOldTextAfterStartPos )
+{
+ aPos = rPos;
+ nLen = 0;
+ bCursor = TRUE;
+ pAttribs = NULL;
+ bWasCursorOverwrite = FALSE;
+}
+
+ImplIMEInfos::~ImplIMEInfos()
+{
+ delete[] pAttribs;
+}
+
+void ImplIMEInfos::CopyAttribs( const USHORT* pA, USHORT nL )
+{
+ nLen = nL;
+ delete pAttribs;
+ pAttribs = new USHORT[ nL ];
+ memcpy( pAttribs, pA, nL*sizeof(USHORT) );
+}
+
+void ImplIMEInfos::DestroyAttribs()
+{
+ delete[] pAttribs;
+ pAttribs = NULL;
+ nLen = 0;
+}
diff --git a/editeng/source/editeng/makefile.mk b/editeng/source/editeng/makefile.mk
new file mode 100644
index 000000000000..4a8f8f254070
--- /dev/null
+++ b/editeng/source/editeng/makefile.mk
@@ -0,0 +1,80 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# 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.
+#
+#*************************************************************************
+PRJ=..$/..
+
+PRJNAME=editeng
+TARGET=editeng
+AUTOSEG=true
+
+#PROJECTPCH4DLL=TRUE
+#PROJECTPCH=eeng_pch
+#PROJECTPCHSOURCE=eeng_pch
+
+ENABLE_EXCEPTIONS=TRUE
+
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Allgemein ----------------------------------------------------------
+
+.IF "$(editdebug)" != "" || "$(EDITDEBUG)" != ""
+CDEFS+=-DEDITDEBUG
+.ENDIF
+
+SLOFILES = \
+ $(SLO)$/textconv.obj \
+ $(SLO)$/editattr.obj \
+ $(SLO)$/editdbg.obj \
+ $(SLO)$/editdoc.obj \
+ $(SLO)$/editdoc2.obj \
+ $(SLO)$/editeng.obj \
+ $(SLO)$/editobj.obj \
+ $(SLO)$/editsel.obj \
+ $(SLO)$/editundo.obj \
+ $(SLO)$/editview.obj \
+ $(SLO)$/edtspell.obj \
+ $(SLO)$/eehtml.obj \
+ $(SLO)$/eerdll.obj \
+ $(SLO)$/eeobj.obj \
+ $(SLO)$/eertfpar.obj \
+ $(SLO)$/impedit.obj \
+ $(SLO)$/impedit2.obj \
+ $(SLO)$/impedit3.obj \
+ $(SLO)$/impedit4.obj \
+ $(SLO)$/impedit5.obj
+
+SRS1NAME=$(TARGET)
+SRC1FILES= editeng.src
+
+EXCEPTIONSFILES= \
+ $(SLO)$/unolingu.obj
+
+.INCLUDE : target.mk
+
diff --git a/editeng/source/editeng/textconv.cxx b/editeng/source/editeng/textconv.cxx
new file mode 100644
index 000000000000..e46a40f09e02
--- /dev/null
+++ b/editeng/source/editeng/textconv.cxx
@@ -0,0 +1,629 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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 <impedit.hxx>
+#include <editeng/editview.hxx>
+#include <editeng/editeng.hxx>
+#include <editeng/unolingu.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+#include <editeng/langitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <textconv.hxx>
+
+
+using ::rtl::OUString;
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::linguistic2;
+
+#define C2U(cChar) OUString::createFromAscii(cChar)
+
+//////////////////////////////////////////////////////////////////////
+
+TextConvWrapper::TextConvWrapper( Window* pWindow,
+ const Reference< XMultiServiceFactory >& rxMSF,
+ const Locale& rSourceLocale,
+ const Locale& rTargetLocale,
+ const Font* pTargetFont,
+ sal_Int32 nOptions,
+ sal_Bool bIsInteractive,
+ BOOL bIsStart,
+ EditView* pView ) :
+ HangulHanjaConversion( pWindow, rxMSF, rSourceLocale, rTargetLocale, pTargetFont, nOptions, bIsInteractive )
+{
+ DBG_ASSERT( pWindow, "TextConvWrapper: window missing" );
+
+ nConvTextLang = LANGUAGE_NONE;
+ nUnitOffset = 0;
+
+ bStartChk = sal_False;
+ bStartDone = bIsStart;
+ bEndDone = sal_False;
+ pWin = pWindow;
+ pEditView = pView;
+
+ aConvSel = pEditView->GetSelection();
+ aConvSel.Adjust(); // make Start <= End
+
+ bAllowChange = sal_False;
+}
+
+
+TextConvWrapper::~TextConvWrapper()
+{
+}
+
+
+sal_Bool TextConvWrapper::ConvNext_impl()
+{
+ // modified version of SvxSpellWrapper::SpellNext
+
+ if( bStartChk )
+ bStartDone = sal_True;
+ else
+ bEndDone = sal_True;
+
+ if ( bStartDone && bEndDone )
+ {
+ if ( ConvMore_impl() ) // ein weiteres Dokument pruefen?
+ {
+ bStartDone = sal_True;
+ bEndDone = sal_False;
+ ConvStart_impl( SVX_SPELL_BODY );
+ return sal_True;
+ }
+ return sal_False;
+
+ }
+
+ //ResMgr* pMgr = DIALOG_MGR();
+ sal_Bool bGoOn = sal_False;
+
+ if ( bStartDone && bEndDone )
+ {
+ if ( ConvMore_impl() ) // ein weiteres Dokument pruefen?
+ {
+ bStartDone = sal_True;
+ bEndDone = sal_False;
+ ConvStart_impl( SVX_SPELL_BODY );
+ return sal_True;
+ }
+ }
+ else
+ {
+ // Ein BODY_Bereich erledigt, Frage nach dem anderen BODY_Bereich
+/*
+ pWin->LeaveWait();
+
+ sal_uInt16 nResId = bReverse ? RID_SVXQB_BW_CONTINUE : RID_SVXQB_CONTINUE;
+ QueryBox aBox( pWin, ResId( nResId, pMgr ) );
+ if ( aBox.Execute() != RET_YES )
+ {
+ // Verzicht auf den anderen Bereich, ggf. Frage nach Sonderbereich
+ pWin->EnterWait();
+ bStartDone = bEndDone = sal_True;
+ return ConvNext_impl();
+ }
+ else
+ {
+*/
+ if (!aConvSel.HasRange())
+ {
+ bStartChk = !bStartDone;
+ ConvStart_impl( bStartChk ? SVX_SPELL_BODY_START : SVX_SPELL_BODY_END );
+ bGoOn = sal_True;
+ }
+/*
+ }
+ pWin->EnterWait();
+*/
+ }
+ return bGoOn;
+}
+
+
+sal_Bool TextConvWrapper::FindConvText_impl()
+{
+ // modified version of SvxSpellWrapper::FindSpellError
+
+ //ShowLanguageErrors();
+
+ sal_Bool bFound = sal_False;
+
+ pWin->EnterWait();
+ sal_Bool bConvert = sal_True;
+
+ while ( bConvert )
+ {
+ bFound = ConvContinue_impl();
+ if (bFound)
+ {
+ bConvert = sal_False;
+ }
+ else
+ {
+ ConvEnd_impl();
+ bConvert = ConvNext_impl();
+ }
+ }
+ pWin->LeaveWait();
+ return bFound;
+}
+
+
+sal_Bool TextConvWrapper::ConvMore_impl()
+{
+ // modified version of SvxSpellWrapper::SpellMore
+
+ sal_Bool bMore = sal_False;
+ ImpEditEngine* pImpEE = pEditView->GetImpEditEngine();
+ ConvInfo* pConvInfo = pImpEE->GetConvInfo();
+ if ( pConvInfo->bMultipleDoc )
+ {
+ bMore = pImpEE->GetEditEnginePtr()->ConvertNextDocument();
+ if ( bMore )
+ {
+ // Der Text wurde in diese Engine getreten...
+ pEditView->GetImpEditView()->SetEditSelection(
+ pImpEE->GetEditDoc().GetStartPaM() );
+ }
+ }
+ return bMore;
+}
+
+
+void TextConvWrapper::ConvStart_impl( SvxSpellArea eArea )
+{
+ // modified version of EditSpellWrapper::SpellStart
+
+ ImpEditEngine* pImpEE = pEditView->GetImpEditEngine();
+ ConvInfo* pConvInfo = pImpEE->GetConvInfo();
+
+ if ( eArea == SVX_SPELL_BODY_START )
+ {
+ // Wird gerufen, wenn Spell-Forwad am Ende angekomment ist
+ // und soll von vorne beginnen
+ if ( bEndDone )
+ {
+ pConvInfo->bConvToEnd = sal_False;
+ pConvInfo->aConvTo = pConvInfo->aConvStart;
+ pConvInfo->aConvContinue = EPaM( 0, 0 );
+ pEditView->GetImpEditView()->SetEditSelection(
+ pImpEE->GetEditDoc().GetStartPaM() );
+ }
+ else
+ {
+ pConvInfo->bConvToEnd = sal_True;
+ pConvInfo->aConvTo = pImpEE->CreateEPaM(
+ pImpEE->GetEditDoc().GetStartPaM() );
+ }
+ }
+ else if ( eArea == SVX_SPELL_BODY_END )
+ {
+ // Wird gerufen, wenn Spell-Forwad gestartet wird
+ pConvInfo->bConvToEnd = sal_True;
+ if (aConvSel.HasRange())
+ {
+ // user selection: convert to end of selection
+ pConvInfo->aConvTo.nPara = aConvSel.nEndPara;
+ pConvInfo->aConvTo.nIndex = aConvSel.nEndPos;
+ pConvInfo->bConvToEnd = sal_False;
+ }
+ else
+ {
+ // nothing selected: convert to end of document
+ pConvInfo->aConvTo = pImpEE->CreateEPaM(
+ pImpEE->GetEditDoc().GetEndPaM() );
+ }
+ }
+ else if ( eArea == SVX_SPELL_BODY )
+ {
+ // called by ConvNext_impl...
+ pConvInfo->aConvContinue = pConvInfo->aConvStart;
+ pConvInfo->aConvTo = pImpEE->CreateEPaM(
+ pImpEE->GetEditDoc().GetEndPaM() );
+ // pSpellInfo->bSpellToEnd = sal_True;
+ }
+ else
+ {
+ DBG_ERROR( "ConvStart_impl: Unknown Area!" );
+ }
+}
+
+
+void TextConvWrapper::ConvEnd_impl()
+{
+}
+
+
+sal_Bool TextConvWrapper::ConvContinue_impl()
+{
+ // modified version of EditSpellWrapper::SpellContinue
+
+ // get next convertible text portion and its language
+ aConvText = rtl::OUString();
+ nConvTextLang = LANGUAGE_NONE;
+ pEditView->GetImpEditEngine()->ImpConvert( aConvText, nConvTextLang,
+ pEditView, GetSourceLanguage(), aConvSel,
+ bAllowChange, GetTargetLanguage(), GetTargetFont() );
+ return aConvText.getLength() != 0;
+}
+
+
+void TextConvWrapper::SetLanguageAndFont( const ESelection &rESel,
+ LanguageType nLang, USHORT nLangWhichId,
+ const Font *pFont, USHORT nFontWhichId )
+{
+ ESelection aOldSel = pEditView->GetSelection();
+ pEditView->SetSelection( rESel );
+
+ // set new language attribute
+ SfxItemSet aNewSet( pEditView->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
+ pEditView->SetAttribs( aNewSet );
+
+ pEditView->SetSelection( aOldSel );
+}
+
+
+void TextConvWrapper::SelectNewUnit_impl(
+ const sal_Int32 nUnitStart,
+ const sal_Int32 nUnitEnd )
+{
+ BOOL bOK = 0 <= nUnitStart && 0 <= nUnitEnd && nUnitStart <= nUnitEnd;
+ DBG_ASSERT( bOK, "invalid arguments" );
+ if (!bOK)
+ return;
+
+ ESelection aSelection = pEditView->GetSelection();
+ DBG_ASSERT( aSelection.nStartPara == aSelection.nEndPara,
+ "paragraph mismatch in selection" );
+ aSelection.nStartPos = (USHORT) (nLastPos + nUnitOffset + nUnitStart);
+ aSelection.nEndPos = (USHORT) (nLastPos + nUnitOffset + nUnitEnd);
+ pEditView->SetSelection( aSelection );
+}
+
+
+void TextConvWrapper::GetNextPortion(
+ ::rtl::OUString& /* [out] */ rNextPortion,
+ LanguageType& /* [out] */ rLangOfPortion,
+ sal_Bool /* [in] */ _bAllowImplicitChangesForNotConvertibleText )
+{
+ bAllowChange = _bAllowImplicitChangesForNotConvertibleText;
+
+ FindConvText_impl();
+ rNextPortion = aConvText;
+ rLangOfPortion = nConvTextLang;
+ nUnitOffset = 0;
+
+ ESelection aSelection = pEditView->GetSelection();
+ DBG_ASSERT( aSelection.nStartPara == aSelection.nEndPara,
+ "paragraph mismatch in selection" );
+ DBG_ASSERT( aSelection.nStartPos <= aSelection.nEndPos,
+ "start pos > end pos" );
+ nLastPos = aSelection.nStartPos;
+}
+
+
+void TextConvWrapper::HandleNewUnit(
+ const sal_Int32 nUnitStart,
+ const sal_Int32 nUnitEnd )
+{
+ SelectNewUnit_impl( nUnitStart, nUnitEnd );
+}
+
+
+void TextConvWrapper::ReplaceUnit(
+ const sal_Int32 nUnitStart, const sal_Int32 nUnitEnd,
+ const ::rtl::OUString& rOrigText,
+ const ::rtl::OUString& rReplaceWith,
+ const ::com::sun::star::uno::Sequence< sal_Int32 > &rOffsets,
+ ReplacementAction eAction,
+ LanguageType *pNewUnitLanguage )
+{
+ BOOL bOK = 0 <= nUnitStart && 0 <= nUnitEnd && nUnitStart <= nUnitEnd;
+ DBG_ASSERT( bOK, "invalid arguments" );
+ if (!bOK)
+ return;
+
+ static OUString aBracketedStart( C2U( "(" ) );
+ static OUString aBracketedEnd( C2U( ")" ) );
+
+ // select current unit
+ SelectNewUnit_impl( nUnitStart, nUnitEnd );
+
+ OUString aOrigTxt( pEditView->GetSelected() );
+ OUString aNewTxt( rReplaceWith );
+ String aNewOrigText;
+ switch (eAction)
+ {
+ case eExchange :
+ break;
+ case eReplacementBracketed :
+ (((aNewTxt = aOrigTxt) += aBracketedStart) += rReplaceWith) += aBracketedEnd;
+ break;
+ case eOriginalBracketed :
+ (((aNewTxt = rReplaceWith) += aBracketedStart) += aOrigTxt) += aBracketedEnd;
+ break;
+ case eReplacementAbove :
+ case eOriginalAbove :
+ case eReplacementBelow :
+ case eOriginalBelow :
+ DBG_ERROR( "Rubies not supported" );
+ break;
+ default:
+ DBG_ERROR( "unexpected case" );
+ }
+ nUnitOffset = sal::static_int_cast< USHORT >(
+ nUnitOffset + nUnitStart + aNewTxt.getLength());
+
+ // remember current original language for kater use
+ ImpEditEngine *pImpEditEng = pEditView->GetImpEditEngine();
+ ESelection _aOldSel = pEditView->GetSelection();
+ //EditSelection aOldEditSel = pEditView->GetImpEditView()->GetEditSelection();
+
+#ifdef DBG_UTIL
+ LanguageType nOldLang = pImpEditEng->GetLanguage( pImpEditEng->CreateSel( _aOldSel ).Min() );
+#endif
+
+ pImpEditEng->UndoActionStart( EDITUNDO_INSERT );
+
+ // according to FT we should currently not bother about keeping
+ // attributes in Hangul/Hanja conversion and leave that untouched.
+ // Thus we do this only for Chinese translation...
+ sal_Bool bIsChineseConversion = IsChinese( GetSourceLanguage() );
+ if (bIsChineseConversion)
+ ChangeText( aNewTxt, rOrigText, &rOffsets, &_aOldSel );
+ else
+ ChangeText( aNewTxt, rOrigText, NULL, NULL );
+
+ // change language and font if necessary
+ if (bIsChineseConversion)
+ {
+ DBG_ASSERT( GetTargetLanguage() == LANGUAGE_CHINESE_SIMPLIFIED || GetTargetLanguage() == LANGUAGE_CHINESE_TRADITIONAL,
+ "TextConvWrapper::ReplaceUnit : unexpected target language" );
+
+ ESelection aOldSel = pEditView->GetSelection();
+ ESelection aNewSel( aOldSel );
+ aNewSel.nStartPos = sal::static_int_cast< xub_StrLen >(
+ aNewSel.nStartPos - aNewTxt.getLength());
+// DBG_ASSERT( aOldSel.nEndPos >= 0, "error while building selection" );
+
+ if (pNewUnitLanguage)
+ {
+ DBG_ASSERT(!IsSimilarChinese( *pNewUnitLanguage, nOldLang ),
+ "similar language should not be changed!");
+ SetLanguageAndFont( aNewSel, *pNewUnitLanguage, EE_CHAR_LANGUAGE_CJK,
+ GetTargetFont(), EE_CHAR_FONTINFO_CJK );
+ }
+ }
+
+ pImpEditEng->UndoActionEnd( EDITUNDO_INSERT );
+
+ // adjust ConvContinue / ConvTo if necessary
+ ImpEditEngine* pImpEE = pEditView->GetImpEditEngine();
+ ConvInfo* pConvInfo = pImpEE->GetConvInfo();
+ sal_Int32 nDelta = aNewTxt.getLength() - aOrigTxt.getLength();
+ if (nDelta != 0)
+ {
+ // Note: replacement is always done in the current paragraph
+ // which is the one ConvContinue points to
+ pConvInfo->aConvContinue.nIndex = sal::static_int_cast< USHORT >(
+ pConvInfo->aConvContinue.nIndex + nDelta);
+
+ // if that is the same as the one where the conversions ends
+ // the end needs to be updated also
+ if (pConvInfo->aConvTo.nPara == pConvInfo->aConvContinue.nPara)
+ pConvInfo->aConvTo.nIndex = sal::static_int_cast< USHORT >(
+ pConvInfo->aConvTo.nIndex + nDelta);
+ }
+}
+
+
+void TextConvWrapper::ChangeText( const String &rNewText,
+ const OUString& rOrigText,
+ const uno::Sequence< sal_Int32 > *pOffsets,
+ ESelection *pESelection )
+{
+ //!! code is a modifed copy of SwHHCWrapper::ChangeText from sw !!
+
+ DBG_ASSERT( rNewText.Len() != 0, "unexpected empty string" );
+ if (rNewText.Len() == 0)
+ return;
+
+ if (pOffsets && pESelection) // try to keep as much attributation as possible ?
+ {
+ pESelection->Adjust();
+
+ // remember cursor start position for later setting of the cursor
+ const xub_StrLen nStartIndex = pESelection->nStartPos;
+
+ const sal_Int32 nIndices = pOffsets->getLength();
+ const sal_Int32 *pIndices = pOffsets->getConstArray();
+ xub_StrLen nConvTextLen = rNewText.Len();
+ xub_StrLen nPos = 0;
+ xub_StrLen nChgPos = STRING_NOTFOUND;
+ xub_StrLen nChgLen = 0;
+ xub_StrLen nConvChgPos = STRING_NOTFOUND;
+ xub_StrLen nConvChgLen = 0;
+
+ // offset to calculate the position in the text taking into
+ // account that text may have been replaced with new text of
+ // different length. Negative values allowed!
+ long nCorrectionOffset = 0;
+
+ DBG_ASSERT(nIndices == 0 || nIndices == nConvTextLen,
+ "mismatch between string length and sequence length!" );
+
+ // find all substrings that need to be replaced (and only those)
+ while (sal_True)
+ {
+ // get index in original text that matches nPos in new text
+ xub_StrLen nIndex;
+ if (nPos < nConvTextLen)
+ nIndex = (sal_Int32) nPos < nIndices ? (xub_StrLen) pIndices[nPos] : nPos;
+ else
+ {
+ nPos = nConvTextLen;
+ nIndex = static_cast< xub_StrLen >( rOrigText.getLength() );
+ }
+
+ if (rOrigText.getStr()[nIndex] == rNewText.GetChar(nPos) ||
+ nPos == nConvTextLen /* end of string also terminates non-matching char sequence */)
+ {
+ // substring that needs to be replaced found?
+ if (nChgPos != STRING_NOTFOUND && nConvChgPos != STRING_NOTFOUND)
+ {
+ nChgLen = nIndex - nChgPos;
+ nConvChgLen = nPos - nConvChgPos;
+#ifdef DEBUG
+ String aInOrig( rOrigText.copy( nChgPos, nChgLen ) );
+#endif
+ String aInNew( rNewText.Copy( nConvChgPos, nConvChgLen ) );
+
+ // set selection to sub string to be replaced in original text
+ ESelection aSel( *pESelection );
+ xub_StrLen nChgInNodeStartIndex = static_cast< xub_StrLen >( nStartIndex + nCorrectionOffset + nChgPos );
+ aSel.nStartPos = nChgInNodeStartIndex;
+ aSel.nEndPos = nChgInNodeStartIndex + nChgLen;
+ pEditView->SetSelection( aSel );
+#ifdef DEBUG
+ String aSelTxt1( pEditView->GetSelected() );
+#endif
+
+ // replace selected sub string with the corresponding
+ // sub string from the new text while keeping as
+ // much from the attributes as possible
+ ChangeText_impl( aInNew, sal_True );
+
+ nCorrectionOffset += nConvChgLen - nChgLen;
+
+ nChgPos = STRING_NOTFOUND;
+ nConvChgPos = STRING_NOTFOUND;
+ }
+ }
+ else
+ {
+ // begin of non-matching char sequence found ?
+ if (nChgPos == STRING_NOTFOUND && nConvChgPos == STRING_NOTFOUND)
+ {
+ nChgPos = nIndex;
+ nConvChgPos = nPos;
+ }
+ }
+ if (nPos >= nConvTextLen)
+ break;
+ ++nPos;
+ }
+
+ // set cursor to the end of the inserted text
+ // (as it would happen after ChangeText_impl (Delete and Insert)
+ // of the whole text in the 'else' branch below)
+ pESelection->nStartPos = pESelection->nEndPos = nStartIndex + nConvTextLen;
+ }
+ else
+ {
+ ChangeText_impl( rNewText, sal_False );
+ }
+}
+
+
+void TextConvWrapper::ChangeText_impl( const String &rNewText, sal_Bool bKeepAttributes )
+{
+ if (bKeepAttributes)
+ {
+ // save attributes to be restored
+ SfxItemSet aSet( pEditView->GetAttribs() );
+
+#ifdef DEBUG
+ String aSelTxt1( pEditView->GetSelected() );
+#endif
+ // replace old text and select new text
+ pEditView->InsertText( rNewText, sal_True );
+#ifdef DEBUG
+ String aSelTxt2( pEditView->GetSelected() );
+#endif
+
+ // since 'SetAttribs' below function like merging with the attributes
+ // from the itemset with any existing ones we have to get rid of all
+ // all attributes now. (Those attributes that may take effect left
+ // to the position where the new text gets inserted after the old text
+ // was deleted)
+ pEditView->RemoveAttribs();
+ // apply saved attributes to new inserted text
+ pEditView->SetAttribs( aSet );
+ }
+ else
+ {
+ pEditView->InsertText( rNewText );
+ }
+}
+
+
+void TextConvWrapper::Convert()
+{
+ bStartChk = sal_False;
+ ConvStart_impl( SVX_SPELL_BODY_END );
+ ConvertDocument();
+ ConvEnd_impl();
+}
+
+
+sal_Bool TextConvWrapper::HasRubySupport() const
+{
+ return sal_False;
+}
+
+//////////////////////////////////////////////////////////////////////
+
diff --git a/editeng/source/editeng/textconv.hxx b/editeng/source/editeng/textconv.hxx
new file mode 100644
index 000000000000..8ffc00291fe9
--- /dev/null
+++ b/editeng/source/editeng/textconv.hxx
@@ -0,0 +1,122 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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.
+ *
+ ************************************************************************/
+#ifndef _TEXTCONV_HXX
+#define _TEXTCONV_HXX
+
+#include <editeng/splwrap.hxx>
+#include <editeng/svxacorr.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <editeng/hangulhanja.hxx>
+
+class EditView;
+class ImpEditEngine;
+class ContentNode;
+
+class TextConvWrapper : public editeng::HangulHanjaConversion
+{
+ rtl::OUString aConvText; // convertible text part found last time
+ LanguageType nConvTextLang; // language of aConvText
+ USHORT nLastPos; // starting position of the last found text portion (word)
+ USHORT nUnitOffset; // offset of current unit in the current text portion (word)
+
+ ESelection aConvSel; // selection to be converted if
+ // 'HasRange' is true, other conversion
+ // starts from the cursor position
+
+ EditView * pEditView;
+ Window * pWin;
+
+ sal_Bool bStartChk;
+ sal_Bool bStartDone;
+ sal_Bool bEndDone;
+ sal_Bool bAllowChange; // storage for _bAllowImplicitChangesForNotConvertibleText
+ // paramters value of function GetNextPortion.
+ // used to transport the value to where it is needed.
+
+
+ // from SvxSpellWrapper copied and modified
+ sal_Bool ConvNext_impl(); // former SpellNext
+ sal_Bool FindConvText_impl(); // former FindSpellError
+ sal_Bool ConvMore_impl(); // former SpellMore
+
+ // from EditSpellWrapper copied and modified
+ void ConvStart_impl( SvxSpellArea eSpell ); // former SpellStart
+ void ConvEnd_impl(); // former SpellEnd
+ sal_Bool ConvContinue_impl(); // former SpellContinue
+
+ void SelectNewUnit_impl( const sal_Int32 nUnitStart,
+ const sal_Int32 nUnitEnd );
+
+ void ChangeText( const String &rNewText,
+ const ::rtl::OUString& rOrigText,
+ const ::com::sun::star::uno::Sequence< sal_Int32 > *pOffsets,
+ ESelection *pESelection );
+ void ChangeText_impl( const String &rNewText, sal_Bool bKeepAttributes );
+
+ // Forbidden and not implemented.
+ TextConvWrapper (const TextConvWrapper &);
+ TextConvWrapper & operator= (const TextConvWrapper &);
+
+protected:
+ virtual void GetNextPortion( ::rtl::OUString& /* [out] */ rNextPortion,
+ LanguageType& /* [out] */ rLangOfPortion,
+ sal_Bool /* [in] */ _bAllowImplicitChangesForNotConvertibleText );
+ virtual void HandleNewUnit( const sal_Int32 nUnitStart,
+ const sal_Int32 nUnitEnd );
+ virtual void ReplaceUnit(
+ const sal_Int32 nUnitStart, const sal_Int32 nUnitEnd,
+ const ::rtl::OUString& rOrigText,
+ const ::rtl::OUString& rReplaceWith,
+ const ::com::sun::star::uno::Sequence< sal_Int32 > &rOffsets,
+ ReplacementAction eAction,
+ LanguageType *pNewUnitLanguage );
+
+ virtual sal_Bool HasRubySupport() const;
+
+ void SetLanguageAndFont( const ESelection &rESel,
+ LanguageType nLang, USHORT nLangWhichId,
+ const Font *pFont, USHORT nFontWhichId );
+
+
+public:
+ TextConvWrapper( Window* pWindow,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxMSF,
+ const ::com::sun::star::lang::Locale& rSourceLocale,
+ const ::com::sun::star::lang::Locale& rTargetLocale,
+ const Font* pTargetFont,
+ INT32 nOptions,
+ sal_Bool bIsInteractive,
+ BOOL bIsStart, EditView* pView );
+
+ virtual ~TextConvWrapper();
+
+ void Convert();
+};
+
+#endif
+