Bugzilla – Attachment 65167 Details for
Bug 46193
Let the user copy error message from error dialog
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
MessBox was made copyable
0001-fdo-46193-MessBox-was-made-copyable.patch (text/plain), 795.72 KB, created by
Tamás Zolnai
on 2012-08-06 10:56:27 UTC
(
hide
)
Description:
MessBox was made copyable
Filename:
MIME Type:
Creator:
Tamás Zolnai
Created:
2012-08-06 10:56:27 UTC
Size:
795.72 KB
patch
obsolete
>From a3cc1cef516dd4e6b2992fe17968cdb68abeb849 Mon Sep 17 00:00:00 2001 >From: =?UTF-8?q?Zolnai=20Tam=C3=A1s?= <zolniatamas@caesar.elte.hu> >Date: Sat, 4 Aug 2012 19:58:24 +0200 >Subject: [PATCH] fdo#46193 MessBox was made copyable > >Part of MultiLineEdit was moved down from stvools to vcl >with name VCLMultiLineEdit. MessBox uses it to display the >message in read-only mode. Some of svtools' classes - which >are necessary to implement VCLMultiLineEdit - were moved to >vcl as a whole. >Note: ExtTextView and ExtTextEngine classes would be leaved in svtools >if VCLMultiLineEdit is a template class, but two macros: IMPL_LINK >end IMPL_LINK_NOARG make it impossible to use template syntax. > >Change-Id: I6322983fc767bd90b0175c5e84004ee5b451b00b >--- > .../extended/textwindowaccessibility.hxx | 8 +- > basctl/source/basicide/baside2.cxx | 2 +- > basctl/source/basicide/baside2b.cxx | 4 +- > basctl/source/basicide/basides1.cxx | 2 +- > basctl/source/basicide/basides2.cxx | 6 +- > basctl/source/basicide/linenumberwindow.cxx | 4 +- > cui/source/dialogs/SpellAttrib.hxx | 2 +- > cui/source/dialogs/SpellDialog.cxx | 2 +- > cui/source/inc/SpellDialog.hxx | 2 +- > desktop/source/deployment/gui/descedit.cxx | 4 +- > .../deployment/gui/dp_gui_autoscrolledit.cxx | 2 +- > desktop/source/deployment/gui/license_dialog.cxx | 2 +- > editeng/inc/editeng/unoedhlp.hxx | 2 +- > filter/source/xsltdialog/xmlfileview.cxx | 4 +- > filter/source/xsltdialog/xmlfileview.hxx | 2 +- > framework/source/services/license.cxx | 2 +- > svtools/Library_svt.mk | 7 - > svtools/Package_inc.mk | 5 - > svtools/inc/svtools/svmedit.hxx | 110 +- > svtools/inc/svtools/textdata.hxx | 172 -- > svtools/inc/svtools/texteng.hxx | 332 -- > svtools/inc/svtools/textview.hxx | 217 -- > svtools/inc/svtools/txtattr.hxx | 236 -- > svtools/inc/svtools/xtextedt.hxx | 69 - > svtools/source/brwbox/ebbcontrols.cxx | 2 +- > svtools/source/contnr/DocumentInfoPreview.cxx | 2 +- > svtools/source/contnr/templwin.cxx | 4 +- > svtools/source/edit/editsyntaxhighlighter.cxx | 4 +- > svtools/source/edit/svmedit.cxx | 1573 +---------- > svtools/source/edit/svmedit2.cxx | 2 +- > svtools/source/edit/textdat2.hxx | 312 -- > svtools/source/edit/textdata.cxx | 345 --- > svtools/source/edit/textdoc.cxx | 636 ---- > svtools/source/edit/textdoc.hxx | 145 - > svtools/source/edit/texteng.cxx | 3205 -------------------- > svtools/source/edit/textund2.hxx | 122 - > svtools/source/edit/textundo.cxx | 295 -- > svtools/source/edit/textundo.hxx | 85 - > svtools/source/edit/textview.cxx | 2378 --------------- > svtools/source/edit/textwindowpeer.cxx | 2 +- > svtools/source/edit/txtattr.cxx | 164 - > svtools/source/edit/xtextedt.cxx | 421 --- > svx/source/dialog/docrecovery.cxx | 2 +- > sw/source/ui/dbui/mmaddressblockpage.cxx | 4 +- > sw/source/ui/docvw/srcedtw.cxx | 4 +- > sw/source/ui/inc/srcedtw.hxx | 2 +- > vcl/Library_vcl.mk | 9 + > vcl/Package_inc.mk | 7 + > vcl/inc/vcl/msgbox.hxx | 4 +- > vcl/inc/vcl/textdata.hxx | 172 ++ > vcl/inc/vcl/texteng.hxx | 332 ++ > vcl/inc/vcl/textview.hxx | 217 ++ > vcl/inc/vcl/txtattr.hxx | 236 ++ > vcl/inc/vcl/vclmedit.hxx | 149 + > vcl/inc/vcl/xtextedt.hxx | 69 + > vcl/source/edit/textdat2.hxx | 312 ++ > vcl/source/edit/textdata.cxx | 345 +++ > vcl/source/edit/textdoc.cxx | 636 ++++ > vcl/source/edit/textdoc.hxx | 145 + > vcl/source/edit/texteng.cxx | 3205 ++++++++++++++++++++ > vcl/source/edit/textund2.hxx | 122 + > vcl/source/edit/textundo.cxx | 295 ++ > vcl/source/edit/textundo.hxx | 85 + > vcl/source/edit/textview.cxx | 2378 +++++++++++++++ > vcl/source/edit/txtattr.cxx | 164 + > vcl/source/edit/vclmedit.cxx | 1572 ++++++++++ > vcl/source/edit/xtextedt.cxx | 421 +++ > vcl/source/window/msgbox.cxx | 41 +- > 68 files changed, 10947 insertions(+), 10876 deletions(-) > delete mode 100644 svtools/inc/svtools/textdata.hxx > delete mode 100644 svtools/inc/svtools/texteng.hxx > delete mode 100644 svtools/inc/svtools/textview.hxx > delete mode 100644 svtools/inc/svtools/txtattr.hxx > delete mode 100644 svtools/inc/svtools/xtextedt.hxx > delete mode 100644 svtools/source/edit/textdat2.hxx > delete mode 100644 svtools/source/edit/textdata.cxx > delete mode 100644 svtools/source/edit/textdoc.cxx > delete mode 100644 svtools/source/edit/textdoc.hxx > delete mode 100644 svtools/source/edit/texteng.cxx > delete mode 100644 svtools/source/edit/textund2.hxx > delete mode 100644 svtools/source/edit/textundo.cxx > delete mode 100644 svtools/source/edit/textundo.hxx > delete mode 100644 svtools/source/edit/textview.cxx > delete mode 100644 svtools/source/edit/txtattr.cxx > delete mode 100644 svtools/source/edit/xtextedt.cxx > create mode 100644 vcl/inc/vcl/textdata.hxx > create mode 100644 vcl/inc/vcl/texteng.hxx > create mode 100644 vcl/inc/vcl/textview.hxx > create mode 100644 vcl/inc/vcl/txtattr.hxx > create mode 100644 vcl/inc/vcl/vclmedit.hxx > create mode 100644 vcl/inc/vcl/xtextedt.hxx > create mode 100644 vcl/source/edit/textdat2.hxx > create mode 100644 vcl/source/edit/textdata.cxx > create mode 100644 vcl/source/edit/textdoc.cxx > create mode 100644 vcl/source/edit/textdoc.hxx > create mode 100644 vcl/source/edit/texteng.cxx > create mode 100644 vcl/source/edit/textund2.hxx > create mode 100644 vcl/source/edit/textundo.cxx > create mode 100644 vcl/source/edit/textundo.hxx > create mode 100644 vcl/source/edit/textview.cxx > create mode 100644 vcl/source/edit/txtattr.cxx > create mode 100644 vcl/source/edit/vclmedit.cxx > create mode 100644 vcl/source/edit/xtextedt.cxx > >diff --git a/accessibility/inc/accessibility/extended/textwindowaccessibility.hxx b/accessibility/inc/accessibility/extended/textwindowaccessibility.hxx >index f1557e1..1ee7a3b 100644 >--- a/accessibility/inc/accessibility/extended/textwindowaccessibility.hxx >+++ b/accessibility/inc/accessibility/extended/textwindowaccessibility.hxx >@@ -31,10 +31,10 @@ > > #include <toolkit/awt/vclxaccessiblecomponent.hxx> > #include <svl/lstner.hxx> >-#include <svtools/textdata.hxx> >-#include <svtools/texteng.hxx> >-#include <svtools/textview.hxx> >-#include <svtools/txtattr.hxx> >+#include <vcl/textdata.hxx> >+#include <vcl/texteng.hxx> >+#include <vcl/textview.hxx> >+#include <vcl/txtattr.hxx> > #include <com/sun/star/awt/FontWeight.hpp> > #include <com/sun/star/lang/EventObject.hpp> > #include <com/sun/star/uno/Reference.hxx> >diff --git a/basctl/source/basicide/baside2.cxx b/basctl/source/basicide/baside2.cxx >index 1eab598..2a91daa 100644 >--- a/basctl/source/basicide/baside2.cxx >+++ b/basctl/source/basicide/baside2.cxx >@@ -42,7 +42,7 @@ > #include <svl/aeitem.hxx> > #include <svl/srchitem.hxx> > #include <svl/whiter.hxx> >-#include <svtools/xtextedt.hxx> >+#include <vcl/xtextedt.hxx> > #include <toolkit/helper/vclunohelper.hxx> > #include <vcl/msgbox.hxx> > >diff --git a/basctl/source/basicide/baside2b.cxx b/basctl/source/basicide/baside2b.cxx >index a5702c1..95c887d 100644 >--- a/basctl/source/basicide/baside2b.cxx >+++ b/basctl/source/basicide/baside2b.cxx >@@ -38,8 +38,8 @@ > #include <sfx2/viewfrm.hxx> > #include <vcl/msgbox.hxx> > #include <svl/urihelper.hxx> >-#include <svtools/xtextedt.hxx> >-#include <svtools/txtattr.hxx> >+#include <vcl/xtextedt.hxx> >+#include <vcl/txtattr.hxx> > #include <svtools/textwindowpeer.hxx> > #include <vcl/taskpanelist.hxx> > #include <vcl/help.hxx> >diff --git a/basctl/source/basicide/basides1.cxx b/basctl/source/basicide/basides1.cxx >index f4eb16d..435f28d 100644 >--- a/basctl/source/basicide/basides1.cxx >+++ b/basctl/source/basicide/basides1.cxx >@@ -51,7 +51,7 @@ > #include <svl/srchitem.hxx> > #include <svl/visitem.hxx> > #include <svl/whiter.hxx> >-#include <svtools/xtextedt.hxx> >+#include <vcl/xtextedt.hxx> > #include <vcl/msgbox.hxx> > > using namespace ::com::sun::star; >diff --git a/basctl/source/basicide/basides2.cxx b/basctl/source/basicide/basides2.cxx >index 4de4d77..cff69a3 100644 >--- a/basctl/source/basicide/basides2.cxx >+++ b/basctl/source/basicide/basides2.cxx >@@ -29,9 +29,9 @@ > #include <baside2.hxx> > #include <basdoc.hxx> > #include <basobj.hxx> >-#include <svtools/texteng.hxx> >-#include <svtools/textview.hxx> >-#include <svtools/xtextedt.hxx> >+#include <vcl/texteng.hxx> >+#include <vcl/textview.hxx> >+#include <vcl/xtextedt.hxx> > #include <tools/diagnose_ex.h> > #include <sfx2/childwin.hxx> > #include <sfx2/dispatch.hxx> >diff --git a/basctl/source/basicide/linenumberwindow.cxx b/basctl/source/basicide/linenumberwindow.cxx >index 97674a6..b6d5223 100644 >--- a/basctl/source/basicide/linenumberwindow.cxx >+++ b/basctl/source/basicide/linenumberwindow.cxx >@@ -29,8 +29,8 @@ > #include "baside2.hxx" > #include "linenumberwindow.hxx" > >-#include <svtools/xtextedt.hxx> >-#include <svtools/textview.hxx> >+#include <vcl/xtextedt.hxx> >+#include <vcl/textview.hxx> > > LineNumberWindow::LineNumberWindow( Window* pParent, ModulWindow* pModulWin ) : > Window( pParent, WB_BORDER ), >diff --git a/cui/source/dialogs/SpellAttrib.hxx b/cui/source/dialogs/SpellAttrib.hxx >index 4a260f5..1cc0304 100644 >--- a/cui/source/dialogs/SpellAttrib.hxx >+++ b/cui/source/dialogs/SpellAttrib.hxx >@@ -28,7 +28,7 @@ > #ifndef _SVX_SPELL_ATTRIB > #define _SVX_SPELL_ATTRIB > >-#include <svtools/txtattr.hxx> >+#include <vcl/txtattr.hxx> > #include <i18npool/lang.h> > #include <com/sun/star/uno/Reference.h> > #include <com/sun/star/uno/Sequence.h> >diff --git a/cui/source/dialogs/SpellDialog.cxx b/cui/source/dialogs/SpellDialog.cxx >index c832bbc..9dcd2ac 100644 >--- a/cui/source/dialogs/SpellDialog.cxx >+++ b/cui/source/dialogs/SpellDialog.cxx >@@ -36,7 +36,7 @@ > #include <sfx2/bindings.hxx> > #include <svl/undo.hxx> > #include <unotools/lingucfg.hxx> >-#include <svtools/textdata.hxx> >+#include <vcl/textdata.hxx> > #include <svtools/filter.hxx> > #include <editeng/unolingu.hxx> > #include <editeng/splwrap.hxx> >diff --git a/cui/source/inc/SpellDialog.hxx b/cui/source/inc/SpellDialog.hxx >index c9cac11..c58ff7b 100644 >--- a/cui/source/inc/SpellDialog.hxx >+++ b/cui/source/inc/SpellDialog.hxx >@@ -48,7 +48,7 @@ > #include <svtools/svmedit.hxx> > #include <svl/lstner.hxx> > #include <svtools/fixedhyper.hxx> >-#include <svtools/xtextedt.hxx> >+#include <vcl/xtextedt.hxx> > #include <editeng/SpellPortions.hxx> > > #include <set> >diff --git a/desktop/source/deployment/gui/descedit.cxx b/desktop/source/deployment/gui/descedit.cxx >index b90061e..49ab5b6 100644 >--- a/desktop/source/deployment/gui/descedit.cxx >+++ b/desktop/source/deployment/gui/descedit.cxx >@@ -19,8 +19,8 @@ > > > #include <vcl/scrbar.hxx> >-#include <svtools/txtattr.hxx> >-#include <svtools/xtextedt.hxx> >+#include <vcl/txtattr.hxx> >+#include <vcl/xtextedt.hxx> > > #include "descedit.hxx" > >diff --git a/desktop/source/deployment/gui/dp_gui_autoscrolledit.cxx b/desktop/source/deployment/gui/dp_gui_autoscrolledit.cxx >index cf3c740..d3a76d9 100644 >--- a/desktop/source/deployment/gui/dp_gui_autoscrolledit.cxx >+++ b/desktop/source/deployment/gui/dp_gui_autoscrolledit.cxx >@@ -19,7 +19,7 @@ > > #include "svtools/svmedit2.hxx" > #include "svl/lstner.hxx" >-#include "svtools/xtextedt.hxx" >+#include "vcl/xtextedt.hxx" > #include "vcl/scrbar.hxx" > > #include "dp_gui_autoscrolledit.hxx" >diff --git a/desktop/source/deployment/gui/license_dialog.cxx b/desktop/source/deployment/gui/license_dialog.cxx >index 2a76bba..3e1e23e 100644 >--- a/desktop/source/deployment/gui/license_dialog.cxx >+++ b/desktop/source/deployment/gui/license_dialog.cxx >@@ -40,7 +40,7 @@ > #include "com/sun/star/task/XJobExecutor.hpp" > #include "svtools/svmedit.hxx" > #include "svl/lstner.hxx" >-#include "svtools/xtextedt.hxx" >+#include "vcl/xtextedt.hxx" > #include <vcl/scrbar.hxx> > #include "vcl/threadex.hxx" > >diff --git a/editeng/inc/editeng/unoedhlp.hxx b/editeng/inc/editeng/unoedhlp.hxx >index df625f5..5848338 100644 >--- a/editeng/inc/editeng/unoedhlp.hxx >+++ b/editeng/inc/editeng/unoedhlp.hxx >@@ -31,7 +31,7 @@ > > #include <memory> > #include <tools/solar.h> >-#include <svtools/textdata.hxx> >+#include <vcl/textdata.hxx> > #include <svl/hint.hxx> > #include <tools/gen.hxx> > #include "editeng/editengdllapi.h" >diff --git a/filter/source/xsltdialog/xmlfileview.cxx b/filter/source/xsltdialog/xmlfileview.cxx >index ca1fa3f..a200a92 100644 >--- a/filter/source/xsltdialog/xmlfileview.cxx >+++ b/filter/source/xsltdialog/xmlfileview.cxx >@@ -36,7 +36,7 @@ > #include <rtl/tencinfo.h> > #include <vcl/svapp.hxx> > #include <osl/mutex.hxx> >-#include <svtools/textview.hxx> >+#include <vcl/textview.hxx> > #include <vcl/scrbar.hxx> > #include <tools/stream.hxx> > #include <tools/time.hxx> >@@ -44,7 +44,7 @@ > #include <vcl/msgbox.hxx> > #include <svtools/colorcfg.hxx> > #include <svtools/htmltokn.h> >-#include <svtools/txtattr.hxx> >+#include <vcl/txtattr.hxx> > > #include "xmlfilterdialogstrings.hrc" > #include "xmlfiltersettingsdialog.hxx" >diff --git a/filter/source/xsltdialog/xmlfileview.hxx b/filter/source/xsltdialog/xmlfileview.hxx >index abbe487..51684f1 100644 >--- a/filter/source/xsltdialog/xmlfileview.hxx >+++ b/filter/source/xsltdialog/xmlfileview.hxx >@@ -32,7 +32,7 @@ > #include <svl/lstner.hxx> > #include <vcl/timer.hxx> > >-#include <svtools/xtextedt.hxx> >+#include <vcl/xtextedt.hxx> > #include <vcl/wrkwin.hxx> > #include <vcl/ctrl.hxx> > #include <vcl/button.hxx> >diff --git a/framework/source/services/license.cxx b/framework/source/services/license.cxx >index c91321b..99753a7b 100644 >--- a/framework/source/services/license.cxx >+++ b/framework/source/services/license.cxx >@@ -62,7 +62,7 @@ > #include <rtl/string.hxx> > #include <unotools/bootstrap.hxx> > #include <osl/file.hxx> >-#include <svtools/xtextedt.hxx> >+#include <vcl/xtextedt.hxx> > #include <vcl/svapp.hxx> > #include <comphelper/processfactory.hxx> > #include <tools/date.hxx> >diff --git a/svtools/Library_svt.mk b/svtools/Library_svt.mk >index c5f3e83..433ac78 100644 >--- a/svtools/Library_svt.mk >+++ b/svtools/Library_svt.mk >@@ -146,14 +146,7 @@ $(eval $(call gb_Library_add_exception_objects,svt,\ > svtools/source/edit/svmedit \ > svtools/source/edit/svmedit2 \ > svtools/source/edit/syntaxhighlight \ >- svtools/source/edit/textdata \ >- svtools/source/edit/textdoc \ >- svtools/source/edit/texteng \ >- svtools/source/edit/textundo \ >- svtools/source/edit/textview \ > svtools/source/edit/textwindowpeer \ >- svtools/source/edit/txtattr \ >- svtools/source/edit/xtextedt \ > svtools/source/filter/FilterConfigCache \ > svtools/source/filter/FilterConfigItem \ > svtools/source/filter/SvFilterOptionsDialog \ >diff --git a/svtools/Package_inc.mk b/svtools/Package_inc.mk >index a7ce3a1..21953b1 100644 >--- a/svtools/Package_inc.mk >+++ b/svtools/Package_inc.mk >@@ -155,9 +155,6 @@ $(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/table/tabletypes.hxx,s > $(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/table/tablesort.hxx,svtools/table/tablesort.hxx)) > $(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/templatefoldercache.hxx,svtools/templatefoldercache.hxx)) > $(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/templdlg.hxx,svtools/templdlg.hxx)) >-$(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/textdata.hxx,svtools/textdata.hxx)) >-$(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/texteng.hxx,svtools/texteng.hxx)) >-$(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/textview.hxx,svtools/textview.hxx)) > $(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/textwindowpeer.hxx,svtools/textwindowpeer.hxx)) > $(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/toolbarmenu.hxx,svtools/toolbarmenu.hxx)) > $(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/toolboxcontroller.hxx,svtools/toolboxcontroller.hxx)) >@@ -172,7 +169,6 @@ $(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/toolpanel/toolpanel.hx > $(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/toolpanel/toolpaneldeck.hxx,svtools/toolpanel/toolpaneldeck.hxx)) > $(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/transfer.hxx,svtools/transfer.hxx)) > $(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/treelist.hxx,svtools/treelist.hxx)) >-$(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/txtattr.hxx,svtools/txtattr.hxx)) > $(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/txtcmp.hxx,svtools/txtcmp.hxx)) > $(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/unitconv.hxx,svtools/unitconv.hxx)) > $(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/unoevent.hxx,svtools/unoevent.hxx)) >@@ -183,7 +179,6 @@ $(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/wallitem.hxx,svtools/w > $(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/wizardmachine.hxx,svtools/wizardmachine.hxx)) > $(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/wizdlg.hxx,svtools/wizdlg.hxx)) > $(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/wmf.hxx,svtools/wmf.hxx)) >-$(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/xtextedt.hxx,svtools/xtextedt.hxx)) > $(eval $(call gb_Package_add_file,svtools_inc,inc/svtools/xwindowitem.hxx,svtools/xwindowitem.hxx)) > > # vim: set noet sw=4 ts=4: >diff --git a/svtools/inc/svtools/svmedit.hxx b/svtools/inc/svtools/svmedit.hxx >index f0d30d1..9085349 100644 >--- a/svtools/inc/svtools/svmedit.hxx >+++ b/svtools/inc/svtools/svmedit.hxx >@@ -29,127 +29,27 @@ > #ifndef _SVEDIT_HXX > #define _SVEDIT_HXX > >-#include <tools/wintypes.hxx> >-#include <vcl/edit.hxx> >+#include <vcl/vclmedit.hxx> > > #include <svtools/syntaxhighlight.hxx> > #include <svtools/svtdllapi.h> > #include <svtools/colorcfg.hxx> > >-class ImpSvMEdit; >-class Timer; >-class ExtTextEngine; >-class ExtTextView; > >-class SVT_DLLPUBLIC MultiLineEdit : public Edit >-{ >-private: >- ImpSvMEdit* pImpSvMEdit; >- >- XubString aSaveValue; >- Link aModifyHdlLink; >- >- Timer* pUpdateDataTimer; >- Link aUpdateDataHdlLink; >- >-protected: >- >- DECL_LINK( ImpUpdateDataHdl, void* ); >- void StateChanged( StateChangedType nType ); >- void DataChanged( const DataChangedEvent& rDCEvt ); >- virtual long PreNotify( NotifyEvent& rNEvt ); >- long Notify( NotifyEvent& rNEvt ); >- using Control::ImplInitSettings; >- void ImplInitSettings( sal_Bool bFont, sal_Bool bForeground, sal_Bool bBackground ); >- WinBits ImplInitStyle( WinBits nStyle ); >- >- ExtTextEngine* GetTextEngine() const; >- ExtTextView* GetTextView() const; >- ScrollBar* GetVScrollBar() const; > >+class SVT_DLLPUBLIC MultiLineEdit : public VCLMultiLineEdit >+{ > public: > MultiLineEdit( Window* pParent, WinBits nWinStyle = WB_LEFT | WB_BORDER ); > MultiLineEdit( Window* pParent, const ResId& rResId ); >- ~MultiLineEdit(); >- >- >- virtual void Modify(); >- virtual void UpdateData(); >- >- virtual void SetModifyFlag(); >- virtual void ClearModifyFlag(); >- virtual sal_Bool IsModified() const; >- >- virtual void EnableUpdateData( sal_uLong nTimeout = EDIT_UPDATEDATA_TIMEOUT ); >- virtual void DisableUpdateData() { delete pUpdateDataTimer; pUpdateDataTimer = NULL; } >- virtual sal_uLong IsUpdateDataEnabled() const; >- >- virtual void SetReadOnly( sal_Bool bReadOnly = sal_True ); >- virtual sal_Bool IsReadOnly() const; >- >- void EnableFocusSelectionHide( sal_Bool bHide ); >- >- virtual void SetMaxTextLen( xub_StrLen nMaxLen = 0 ); >- virtual xub_StrLen GetMaxTextLen() const; >- >- virtual void SetSelection( const Selection& rSelection ); >- virtual const Selection& GetSelection() const; >- >- virtual void ReplaceSelected( const XubString& rStr ); >- virtual void DeleteSelected(); >- virtual XubString GetSelected() const; >- virtual XubString GetSelected( LineEnd aSeparator ) const; >- >- virtual void Cut(); >- virtual void Copy(); >- virtual void Paste(); >- >- virtual void SetText( const XubString& rStr ); >- virtual void SetText( const XubString& rStr, const Selection& rNewSelection ) >- { SetText( rStr ); SetSelection( rNewSelection ); } >- String GetText() const; >- String GetText( LineEnd aSeparator ) const; >- String GetTextLines( LineEnd aSeparator ) const; >- >- void SetRightToLeft( sal_Bool bRightToLeft ); >- sal_Bool IsRightToLeft() const; >- >- void SaveValue() { aSaveValue = GetText(); } >- const XubString& GetSavedValue() const { return aSaveValue; } >- >- void SetModifyHdl( const Link& rLink ) { aModifyHdlLink = rLink; } >- const Link& GetModifyHdl() const { return aModifyHdlLink; } >- >- void SetUpdateDataHdl( const Link& rLink ) { aUpdateDataHdlLink = rLink; } >- const Link& GetUpdateDataHdl() const { return aUpdateDataHdlLink; } >- >- virtual void Resize(); >- virtual void GetFocus(); >- >- Size CalcMinimumSize() const; >- Size CalcAdjustedSize( const Size& rPrefSize ) const; >- using Edit::CalcSize; >- Size CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const; >- void GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const; >- >- void Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags ); >- >- void SetLeftMargin( sal_uInt16 n ); >+ ~MultiLineEdit(){}; > > virtual > ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > > GetComponentInterface(sal_Bool bCreate = sal_True); >- >- void DisableSelectionOnFocus(); >- >- void SetTextSelectable( sal_Bool bTextSelectable ); > }; > >-inline sal_uLong MultiLineEdit::IsUpdateDataEnabled() const >-{ >- return pUpdateDataTimer ? pUpdateDataTimer->GetTimeout() : 0; >-} > >-#endif >+#endif //_SVEDIT_HXX > > /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/svtools/inc/svtools/textdata.hxx b/svtools/inc/svtools/textdata.hxx >deleted file mode 100644 >index 29d97e6..0000000 >--- a/svtools/inc/svtools/textdata.hxx >+++ /dev/null >@@ -1,172 +0,0 @@ >-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >-/* >- * This file is part of the LibreOffice project. >- * >- * This Source Code Form is subject to the terms of the Mozilla Public >- * License, v. 2.0. If a copy of the MPL was not distributed with this >- * file, You can obtain one at http://mozilla.org/MPL/2.0/. >- * >- * This file incorporates work covered by the following license notice: >- * >- * Licensed to the Apache Software Foundation (ASF) under one or more >- * contributor license agreements. See the NOTICE file distributed >- * with this work for additional information regarding copyright >- * ownership. The ASF licenses this file to you under the Apache >- * License, Version 2.0 (the "License"); you may not use this file >- * except in compliance with the License. You may obtain a copy of >- * the License at http://www.apache.org/licenses/LICENSE-2.0 . >- */ >- >-#ifndef _TEXTDATA_HXX >-#define _TEXTDATA_HXX >- >-#include "svtools/svtdllapi.h" >-#include <svl/brdcst.hxx> >-#include <svl/smplhint.hxx> >-#include <tools/string.hxx> >- >-// Fuer Notify, wenn alle Absaetze geloescht wurden... >-#define TEXT_PARA_ALL 0xFFFFFFFF >- >-class TextPaM >-{ >-private: >- sal_uLong mnPara; >- sal_uInt16 mnIndex; >- >-public: >- TextPaM() { mnPara = 0, mnIndex = 0; } >- TextPaM( sal_uLong nPara, sal_uInt16 nIndex ) { mnPara = nPara, mnIndex = nIndex; } >- >- sal_uLong GetPara() const { return mnPara; } >- sal_uLong& GetPara() { return mnPara; } >- >- sal_uInt16 GetIndex() const { return mnIndex; } >- sal_uInt16& GetIndex() { return mnIndex; } >- >- inline sal_Bool operator == ( const TextPaM& rPaM ) const; >- inline sal_Bool operator != ( const TextPaM& rPaM ) const; >- inline sal_Bool operator < ( const TextPaM& rPaM ) const; >- inline sal_Bool operator > ( const TextPaM& rPaM ) const; >-}; >- >-inline sal_Bool TextPaM::operator == ( const TextPaM& rPaM ) const >-{ >- return ( ( mnPara == rPaM.mnPara ) && ( mnIndex == rPaM.mnIndex ) ) ? sal_True : sal_False; >-} >- >-inline sal_Bool TextPaM::operator != ( const TextPaM& rPaM ) const >-{ >- return !( *this == rPaM ); >-} >- >-inline sal_Bool TextPaM::operator < ( const TextPaM& rPaM ) const >-{ >- return ( ( mnPara < rPaM.mnPara ) || >- ( ( mnPara == rPaM.mnPara ) && mnIndex < rPaM.mnIndex ) ) ? sal_True : sal_False; >-} >- >-inline sal_Bool TextPaM::operator > ( const TextPaM& rPaM ) const >-{ >- return ( ( mnPara > rPaM.mnPara ) || >- ( ( mnPara == rPaM.mnPara ) && mnIndex > rPaM.mnIndex ) ) ? sal_True : sal_False; >-} >- >-class SVT_DLLPUBLIC TextSelection >-{ >-private: >- TextPaM maStartPaM; >- TextPaM maEndPaM; >- >-public: >- TextSelection(); >- TextSelection( const TextPaM& rPaM ); >- TextSelection( const TextPaM& rStart, const TextPaM& rEnd ); >- >- const TextPaM& GetStart() const { return maStartPaM; } >- TextPaM& GetStart() { return maStartPaM; } >- >- const TextPaM& GetEnd() const { return maEndPaM; } >- TextPaM& GetEnd() { return maEndPaM; } >- >- void Justify(); >- >- sal_Bool HasRange() const { return maStartPaM != maEndPaM; } >- >- inline sal_Bool operator == ( const TextSelection& rSel ) const; >- inline sal_Bool operator != ( const TextSelection& rSel ) const; >-}; >- >-inline sal_Bool TextSelection::operator == ( const TextSelection& rSel ) const >-{ >- return ( ( maStartPaM == rSel.maStartPaM ) && ( maEndPaM == rSel.maEndPaM ) ); >-} >- >-inline sal_Bool TextSelection::operator != ( const TextSelection& rSel ) const >-{ >- return !( *this == rSel ); >-} >- >-#define TEXT_HINT_PARAINSERTED 1 >-#define TEXT_HINT_PARAREMOVED 2 >-#define TEXT_HINT_PARACONTENTCHANGED 3 >-#define TEXT_HINT_TEXTHEIGHTCHANGED 4 >-#define TEXT_HINT_FORMATPARA 5 >-#define TEXT_HINT_TEXTFORMATTED 6 >-#define TEXT_HINT_MODIFIED 7 >-#define TEXT_HINT_BLOCKNOTIFICATION_START 8 >-#define TEXT_HINT_BLOCKNOTIFICATION_END 9 >-#define TEXT_HINT_INPUT_START 10 >-#define TEXT_HINT_INPUT_END 11 >- >-#define TEXT_HINT_VIEWSCROLLED 100 >-#define TEXT_HINT_VIEWSELECTIONCHANGED 101 >- >-class SVT_DLLPUBLIC TextHint : public SfxSimpleHint >-{ >-private: >- sal_uLong mnValue; >- >-public: >- TYPEINFO(); >- TextHint( sal_uLong nId ); >- TextHint( sal_uLong nId, sal_uLong nValue ); >- >- sal_uLong GetValue() const { return mnValue; } >- void SetValue( sal_uLong n ) { mnValue = n; } >-}; >- >-struct TEIMEInfos >-{ >- String aOldTextAfterStartPos; >- sal_uInt16* pAttribs; >- TextPaM aPos; >- sal_uInt16 nLen; >- sal_Bool bCursor; >- sal_Bool bWasCursorOverwrite; >- >- TEIMEInfos( const TextPaM& rPos, const String& rOldTextAfterStartPos ); >- ~TEIMEInfos(); >- >- void CopyAttribs( const sal_uInt16* pA, sal_uInt16 nL ); >- void DestroyAttribs(); >-}; >- >-// ----------------- Wrapper for old Tools List ------------------- >- >-#include <vector> >-#include <algorithm> >- >-template <class T> class ToolsList : public ::std::vector< T > >-{ >-public: >- sal_uLong Count() const { return static_cast<sal_uLong>(::std::vector< T >::size()); } >- sal_uLong GetPos( T pObject ) const { return ( ::std::find( this->begin(), this->end(), pObject ) ) - this->begin(); } >- T GetObject( sal_uLong nIndex ) const { return (*this)[nIndex]; } >- void Insert( T pObject, sal_uLong nPos ) { ::std::vector< T >::insert( this->begin()+nPos, pObject ); } >- void Remove( sal_uLong nPos ) { ::std::vector< T >::erase( this->begin()+nPos ); } >-}; >- >-#endif // _TEXTDATA_HXX >- >-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/svtools/inc/svtools/texteng.hxx b/svtools/inc/svtools/texteng.hxx >deleted file mode 100644 >index b20a01b..0000000 >--- a/svtools/inc/svtools/texteng.hxx >+++ /dev/null >@@ -1,332 +0,0 @@ >-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >-/************************************************************************* >- * >- * 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 _TEXTENG_HXX >-#define _TEXTENG_HXX >- >-#include "svtools/svtdllapi.h" >- >-class TextDoc; >-class TextView; >-class TextPaM; >-class TextSelection; >-class TEParaPortions; >-class TextAttrib; >-class TextCharAttrib; >-class TextUndo; >-class TextUndoManager; >-class EditSelFunctionSet; >-class EditSelEngine; >-class IdleFormatter; >-class TextNode; >-class OutputDevice; >-class SfxUndoAction; >-class KeyEvent; >-class Timer; >- >-namespace svl >-{ >- class IUndoManager; >-} >- >-class TextLine; >-class TETextPortion; >-#include <svl/brdcst.hxx> >-#include <tools/link.hxx> >-#include <vcl/font.hxx> >-#include <tools/string.hxx> >-#include <tools/gen.hxx> >- >-#include <com/sun/star/lang/Locale.hpp> >-#include <com/sun/star/uno/Reference.hxx> >- >-struct TEIMEInfos; >-class SvtCTLOptions; >- >-namespace com { >-namespace sun { >-namespace star { >-namespace i18n { >- class XBreakIterator; >- class XExtendedInputSequenceChecker; >-}}}} >- >-class LocaleDataWrapper; >- >-enum TxtAlign { TXTALIGN_LEFT, TXTALIGN_CENTER, TXTALIGN_RIGHT }; >- >-typedef std::vector<TextView*> TextViews; >- >-class SVT_DLLPUBLIC TextEngine : public SfxBroadcaster >-{ >- friend class TextView; >- friend class TextSelFunctionSet; >- friend class ExtTextEngine; >- friend class ExtTextView; >- >- friend class TextUndo; >- friend class TextUndoManager; >- friend class TextUndoDelPara; >- friend class TextUndoConnectParas; >- friend class TextUndoSplitPara; >- friend class TextUndoInsertChars; >- friend class TextUndoRemoveChars; >- friend class TextUndoSetAttribs; >- >-private: >- TextDoc* mpDoc; >- TEParaPortions* mpTEParaPortions; >- OutputDevice* mpRefDev; >- >- TextViews* mpViews; >- TextView* mpActiveView; >- >- TextUndoManager* mpUndoManager; >- >- IdleFormatter* mpIdleFormatter; >- >- TEIMEInfos* mpIMEInfos; >- >- ::com::sun::star::lang::Locale maLocale; >- ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XBreakIterator > mxBreakIterator; >- >- Rectangle maInvalidRec; >- Range maInvalidRange; >- >- LocaleDataWrapper* mpLocaleDataWrapper; >- >- Font maFont; >- Color maTextColor; >- sal_uInt16 mnCharHeight; >- sal_uInt16 mnFixCharWidth100; >- >- sal_uLong mnMaxTextLen; >- sal_uLong mnMaxTextWidth; >- sal_uLong mnCurTextWidth; >- sal_uLong mnCurTextHeight; >- sal_uLong mnDefTab; >- >- TxtAlign meAlign; >- >- sal_Bool mbIsFormatting : 1; // Semaphore wegen der Hook's >- sal_Bool mbFormatted : 1; >- sal_Bool mbUpdate : 1; >- sal_Bool mbModified : 1; >- sal_Bool mbUndoEnabled : 1; >- sal_Bool mbIsInUndo : 1; >- sal_Bool mbDowning : 1; >- sal_Bool mbRightToLeft : 1; >- sal_Bool mbHasMultiLineParas : 1; >- >- TextEngine( const TextEngine& ) : SfxBroadcaster() {} >- TextEngine& operator=( const TextEngine& ) { return *this; } >- >-protected: >- >- void CursorMoved( sal_uLong nNode ); >- void TextModified(); >- >- void ImpInitDoc(); >- void ImpRemoveText(); >- TextPaM ImpDeleteText( const TextSelection& rSel ); >- TextPaM ImpInsertText( const TextSelection& rSel, sal_Unicode c, sal_Bool bOverwrite = sal_False ); >- TextPaM ImpInsertText( const TextSelection& rSel, const String& rText ); >- TextPaM ImpInsertParaBreak( const TextSelection& rTextSelection, sal_Bool bKeepEndingAttribs = sal_True ); >- TextPaM ImpInsertParaBreak( const TextPaM& rPaM, sal_Bool bKeepEndingAttribs = sal_True ); >- void ImpRemoveChars( const TextPaM& rPaM, sal_uInt16 nChars, SfxUndoAction* pCurUndo = 0 ); >- TextPaM ImpConnectParagraphs( sal_uLong nLeft, sal_uLong nRight ); >- void ImpRemoveParagraph( sal_uLong nPara ); >- void ImpInitWritingDirections( sal_uLong nPara ); >- LocaleDataWrapper* ImpGetLocaleDataWrapper(); >- >- // to remain compatible in the minor release we copy the above ImpInsertText >- // function and add the extra parameter we need but make sure this function >- // gets not exported. First and seconf parameter swapped to have a different signatur. >- SAL_DLLPRIVATE TextPaM ImpInsertText( sal_Unicode c, const TextSelection& rSel, sal_Bool bOverwrite = sal_False, sal_Bool bIsUserInput = sal_False ); >- // some other new functions needed that must not be exported to remain compatible >- SAL_DLLPRIVATE ::com::sun::star::uno::Reference < ::com::sun::star::i18n::XExtendedInputSequenceChecker > GetInputSequenceChecker() const; >- SAL_DLLPRIVATE sal_Bool IsInputSequenceCheckingRequired( sal_Unicode c, const TextSelection& rCurSel ) const; >- >- // Broadcasten bzw. Selektionen anpassen: >- void ImpParagraphInserted( sal_uLong nPara ); >- void ImpParagraphRemoved( sal_uLong nPara ); >- void ImpCharsRemoved( sal_uLong nPara, sal_uInt16 nPos, sal_uInt16 nChars ); >- void ImpCharsInserted( sal_uLong nPara, sal_uInt16 nPos, sal_uInt16 nChars ); >- void ImpFormattingParagraph( sal_uLong nPara ); >- void ImpTextHeightChanged(); >- void ImpTextFormatted(); >- >- DECL_LINK( IdleFormatHdl, void * ); >- void CheckIdleFormatter(); >- void IdleFormatAndUpdate( TextView* pCurView = 0, sal_uInt16 nMaxTimerRestarts = 5 ); >- >- sal_Bool CreateLines( sal_uLong nPara ); >- void CreateAndInsertEmptyLine( sal_uLong nPara ); >- void ImpBreakLine( sal_uLong nPara, TextLine* pLine, TETextPortion* pPortion, sal_uInt16 nPortionStart, long nRemainingWidth ); >- sal_uInt16 SplitTextPortion( sal_uLong nPara, sal_uInt16 nPos ); >- void CreateTextPortions( sal_uLong nPara, sal_uInt16 nStartPos ); >- void RecalcTextPortion( sal_uLong nPara, sal_uInt16 nStartPos, short nNewChars ); >- void SeekCursor( sal_uLong nNode, sal_uInt16 nPos, Font& rFont, OutputDevice* pOutDev ); >- >- void FormatDoc(); >- void FormatFullDoc(); >- void FormatAndUpdate( TextView* pCurView = 0 ); >- sal_Bool IsFormatting() const { return mbIsFormatting; } >- void UpdateViews( TextView* pCurView = 0 ); >- >- void ImpPaint( OutputDevice* pOut, const Point& rStartPos, Rectangle const* pPaintArea, TextSelection const* pPaintRange = 0, TextSelection const* pSelection = 0 ); >- >- void UpdateSelections(); >- >- sal_Bool IsFormatted() const { return mbFormatted; } >- >- sal_uInt16 GetCharPos( sal_uLong nPara, sal_uInt16 nLine, long nDocPosX, sal_Bool bSmart = sal_False ); >- Rectangle GetEditCursor( const TextPaM& rPaM, sal_Bool bSpecial, sal_Bool bPreferPortionStart = sal_False ); >- sal_uInt16 ImpFindIndex( sal_uLong nPortion, const Point& rPosInPara, sal_Bool bSmart ); >- long ImpGetPortionXOffset( sal_uLong nPara, TextLine* pLine, sal_uInt16 nTextPortion ); >- long ImpGetXPos( sal_uLong nPara, TextLine* pLine, sal_uInt16 nIndex, sal_Bool bPreferPortionStart = sal_False ); >- long ImpGetOutputOffset( sal_uLong nPara, TextLine* pLine, sal_uInt16 nIndex, sal_uInt16 nIndex2 ); >- sal_uInt8 ImpGetRightToLeft( sal_uLong nPara, sal_uInt16 nPos, sal_uInt16* pStart = NULL, sal_uInt16* pEnd = NULL ); >- void ImpInitLayoutMode( OutputDevice* pOutDev, sal_Bool bDrawingR2LPortion = sal_False ); >- TxtAlign ImpGetAlign() const; >- >- sal_uLong CalcTextHeight(); >- sal_uLong CalcParaHeight( sal_uLong nParagraph ) const; >- sal_uLong CalcTextWidth( sal_uLong nPara ); >- sal_uLong CalcTextWidth( sal_uLong nPara, sal_uInt16 nPortionStart, sal_uInt16 nPortionLen, const Font* pFont = 0 ); >- Range GetInvalidYOffsets( sal_uLong nPortion ); >- >- // Fuer Undo/Redo >- void InsertContent( TextNode* pNode, sal_uLong nPara ); >- TextPaM SplitContent( sal_uLong nNode, sal_uInt16 nSepPos ); >- TextPaM ConnectContents( sal_uLong nLeftNode ); >- >- // Ans API uebergebene PaM's und Selektionen auf einen gueltigen Bereich einstellen >- void ValidateSelection( TextSelection& rSel ) const; >- void ValidatePaM( TextPaM& rPaM ) const; >- >-public: >- TextEngine(); >- ~TextEngine(); >- >- void SetText( const String& rStr ); >- String GetText( LineEnd aSeparator = LINEEND_LF ) const; >- String GetText( const TextSelection& rSel, LineEnd aSeparator = LINEEND_LF ) const; >- String GetTextLines( LineEnd aSeparator = LINEEND_LF ) const; >- void ReplaceText(const TextSelection& rSel, const String& rText); >- >- sal_uLong GetTextLen( LineEnd aSeparator = LINEEND_LF ) const; >- sal_uLong GetTextLen( const TextSelection& rSel, LineEnd aSeparator = LINEEND_LF ) const; >- >- void SetFont( const Font& rFont ); >- const Font& GetFont() const { return maFont; } >- >- sal_uInt16 GetDefTab() const; >- >- void SetLeftMargin( sal_uInt16 n ); >- sal_uInt16 GetLeftMargin() const; >- >- void SetUpdateMode( sal_Bool bUpdate ); >- sal_Bool GetUpdateMode() const { return mbUpdate; } >- >- sal_uInt16 GetViewCount() const; >- TextView* GetView( sal_uInt16 nView ) const; >- void InsertView( TextView* pTextView ); >- void RemoveView( TextView* pTextView ); >- TextView* GetActiveView() const; >- void SetActiveView( TextView* pView ); >- >- void SetMaxTextLen( sal_uLong nLen ); >- sal_uLong GetMaxTextLen() const { return mnMaxTextLen; } >- >- void SetMaxTextWidth( sal_uLong nWidth ); >- sal_uLong GetMaxTextWidth() const { return mnMaxTextWidth; } >- >- sal_uLong GetTextHeight() const; >- sal_uLong CalcTextWidth(); >- sal_uInt16 GetCharHeight() const { return mnCharHeight; } >- >- sal_uLong GetParagraphCount() const; >- String GetText( sal_uLong nParagraph ) const; >- sal_uInt16 GetTextLen( sal_uLong nParagraph ) const; >- sal_uLong GetTextHeight( sal_uLong nParagraph ) const; >- >- sal_uInt16 GetLineCount( sal_uLong nParagraph ) const; >- sal_uInt16 GetLineLen( sal_uLong nParagraph, sal_uInt16 nLine ) const; >- >- void SetRightToLeft( sal_Bool bR2L ); >- sal_Bool IsRightToLeft() const { return mbRightToLeft; } >- >- sal_Bool HasUndoManager() const { return mpUndoManager ? sal_True : sal_False; } >- ::svl::IUndoManager& >- GetUndoManager(); >- void UndoActionStart( sal_uInt16 nId = 0 ); >- void UndoActionEnd(); >- void InsertUndo( TextUndo* pUndo, sal_Bool bTryMerge = sal_False ); >- sal_Bool IsInUndo() { return mbIsInUndo; } >- void SetIsInUndo( sal_Bool bInUndo ) { mbIsInUndo = bInUndo; } >- void ResetUndo(); >- >- void EnableUndo( sal_Bool bEnable ); >- sal_Bool IsUndoEnabled() { return mbUndoEnabled; } >- >- void SetModified( sal_Bool bModified ) { mbModified = bModified; } >- sal_Bool IsModified() const { return mbModified; } >- >- sal_Bool Read( SvStream& rInput, const TextSelection* pSel = NULL ); >- >- sal_Bool Write( SvStream& rOutput, const TextSelection* pSel = NULL, sal_Bool bHTML = sal_False ); >- >- TextPaM GetPaM( const Point& rDocPos, sal_Bool bSmart = sal_True ); >- Rectangle PaMtoEditCursor( const TextPaM& rPaM, sal_Bool bSpecial = sal_False ); >- String GetWord( const TextPaM& rCursorPos, TextPaM* pStartOfWord = 0 ); >- >- sal_Bool HasAttrib( sal_uInt16 nWhich ) const; >- const TextAttrib* FindAttrib( const TextPaM& rPaM, sal_uInt16 nWhich ) const; >- const TextCharAttrib* FindCharAttrib( const TextPaM& rPaM, sal_uInt16 nWhich ) const; >- >- void RemoveAttribs( sal_uLong nPara, sal_uInt16 nWhich, sal_Bool bIdleFormatAndUpdate ); >- void RemoveAttrib( sal_uLong nPara, const TextCharAttrib& rAttrib ); >- void RemoveAttribs( sal_uLong nPara, sal_Bool bIdleFormatAndUpdate = sal_True ); >- void SetAttrib( const TextAttrib& rAttr, sal_uLong nPara, sal_uInt16 nStart, sal_uInt16 nEnd, sal_Bool bIdleFormatAndUpdate = sal_True ); >- >- TxtAlign GetTextAlign() const { return meAlign; } >- void SetTextAlign( TxtAlign eAlign ); >- >- void Draw( OutputDevice* pDev, const Point& rPos ); >- >- void SetLocale( const ::com::sun::star::lang::Locale& rLocale ); >- ::com::sun::star::lang::Locale GetLocale(); >- ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XBreakIterator > GetBreakIterator(); >- >- static sal_Bool DoesKeyChangeText( const KeyEvent& rKeyEvent ); >- static sal_Bool IsSimpleCharInput( const KeyEvent& rKeyEvent ); >-}; >- >-#endif // _TEXTENG_HXX >- >-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/svtools/inc/svtools/textview.hxx b/svtools/inc/svtools/textview.hxx >deleted file mode 100644 >index ebf7a4f..0000000 >--- a/svtools/inc/svtools/textview.hxx >+++ /dev/null >@@ -1,217 +0,0 @@ >-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >-/************************************************************************* >- * >- * 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 _TEXTVIEW_HXX >-#define _TEXTVIEW_HXX >- >-#include "svtools/svtdllapi.h" >-#include <svtools/textdata.hxx> >-#include <tools/gen.hxx> >-#include <vcl/dndhelp.hxx> >- >-class TextEngine; >-class OutputDevice; >-class Window; >-class Cursor; >-class KeyEvent; >-class MouseEvent; >-class CommandEvent; >-class TextSelFunctionSet; >-class SelectionEngine; >-class VirtualDevice; >-struct TextDDInfo; >- >-namespace com { >-namespace sun { >-namespace star { >-namespace datatransfer { >-namespace clipboard { >- class XClipboard; >-}}}}} >- >-struct ImpTextView; >- >-class SVT_DLLPUBLIC TextView : public vcl::unohelper::DragAndDropClient >-{ >- friend class TextEngine; >- friend class TextUndo; >- friend class TextUndoManager; >- friend class TextSelFunctionSet; >- friend class ExtTextView; >- >-private: >- ImpTextView* mpImpl; >- >- TextView( const TextView& ) : vcl::unohelper::DragAndDropClient() {} >- TextView& operator=( const TextView& ) { return *this; } >- >-protected: >- void ShowSelection(); >- void HideSelection(); >- void ShowSelection( const TextSelection& rSel ); >- void ImpShowHideSelection( sal_Bool bShow, const TextSelection* pRange = NULL ); >- >- TextSelection ImpMoveCursor( const KeyEvent& rKeyEvent ); >- TextPaM ImpDelete( sal_uInt8 nMode, sal_uInt8 nDelMode ); >- void ImpSetSelection( const TextSelection& rNewSel, sal_Bool bUI ); >- sal_Bool IsInSelection( const TextPaM& rPaM ); >- >- void ImpPaint( OutputDevice* pOut, const Point& rStartPos, Rectangle const* pPaintArea, TextSelection const* pPaintRange = 0, TextSelection const* pSelection = 0 ); >- void ImpPaint( const Rectangle& rRect, sal_Bool bUseVirtDev ); >- void ImpShowCursor( sal_Bool bGotoCursor, sal_Bool bForceVisCursor, sal_Bool bEndKey ); >- void ImpHighlight( const TextSelection& rSel ); >- void ImpSetSelection( const TextSelection& rSelection ); >- Point ImpGetOutputStartPos( const Point& rStartDocPos ) const; >- >- void ImpHideDDCursor(); >- void ImpShowDDCursor(); >- >- bool ImplTruncateNewText( rtl::OUString& rNewText ) const; >- sal_Bool ImplCheckTextLen( const String& rNewText ); >- >- VirtualDevice* GetVirtualDevice(); >- >- // DragAndDropClient >- virtual void dragGestureRecognized( const ::com::sun::star::datatransfer::dnd::DragGestureEvent& dge ) throw (::com::sun::star::uno::RuntimeException); >- virtual void dragDropEnd( const ::com::sun::star::datatransfer::dnd::DragSourceDropEvent& dsde ) throw (::com::sun::star::uno::RuntimeException); >- virtual void drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEvent& dtde ) throw (::com::sun::star::uno::RuntimeException); >- virtual void dragEnter( const ::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent& dtdee ) throw (::com::sun::star::uno::RuntimeException); >- virtual void dragExit( const ::com::sun::star::datatransfer::dnd::DropTargetEvent& dte ) throw (::com::sun::star::uno::RuntimeException); >- virtual void dragOver( const ::com::sun::star::datatransfer::dnd::DropTargetDragEvent& dtde ) throw (::com::sun::star::uno::RuntimeException); >- >- using DragAndDropClient::dragEnter; >- using DragAndDropClient::dragExit; >- using DragAndDropClient::dragOver; >- >-public: >- TextView( TextEngine* pEng, Window* pWindow ); >- virtual ~TextView(); >- >- TextEngine* GetTextEngine() const; >- Window* GetWindow() const; >- >- void Invalidate(); >- void Scroll( long nHorzScroll, long nVertScroll ); >- >- void ShowCursor( sal_Bool bGotoCursor = sal_True, sal_Bool bForceVisCursor = sal_True ); >- void HideCursor(); >- >- void EnableCursor( sal_Bool bEnable ); >- sal_Bool IsCursorEnabled() const; >- >- const TextSelection& GetSelection() const; >- TextSelection& GetSelection(); >- void SetSelection( const TextSelection& rNewSel ); >- void SetSelection( const TextSelection& rNewSel, sal_Bool bGotoCursor ); >- sal_Bool HasSelection() const; >- >- String GetSelected(); >- String GetSelected( LineEnd aSeparator ); >- void DeleteSelected(); >- >- void InsertNewText( const rtl::OUString& rNew, sal_Bool bSelect = sal_False ); >- // deprecated: use InsertNewText instead >- void InsertText( const String& rNew, sal_Bool bSelect = sal_False ); >- >- sal_Bool KeyInput( const KeyEvent& rKeyEvent ); >- void Paint( const Rectangle& rRect ); >- void MouseButtonUp( const MouseEvent& rMouseEvent ); >- void MouseButtonDown( const MouseEvent& rMouseEvent ); >- void MouseMove( const MouseEvent& rMouseEvent ); >- void Command( const CommandEvent& rCEvt ); >- >- void Cut(); >- void Copy(); >- void Paste(); >- >- void Copy( ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboard >& rxClipboard ); >- void Paste( ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboard >& rxClipboard ); >- >- void Undo(); >- void Redo(); >- >- sal_Bool Read( SvStream& rInput ); >- >- void SetStartDocPos( const Point& rPos ); >- const Point& GetStartDocPos() const; >- >- Point GetDocPos( const Point& rWindowPos ) const; >- Point GetWindowPos( const Point& rDocPos ) const; >- >- void SetInsertMode( sal_Bool bInsert ); >- sal_Bool IsInsertMode() const; >- >- void SetAutoIndentMode( sal_Bool bAutoIndent ); >- >- void SetReadOnly( sal_Bool bReadOnly ); >- sal_Bool IsReadOnly() const; >- >- void SetAutoScroll( sal_Bool bAutoScroll ); >- sal_Bool IsAutoScroll() const; >- >- sal_Bool SetCursorAtPoint( const Point& rPointPixel ); >- sal_Bool IsSelectionAtPoint( const Point& rPointPixel ); >- >- void SetPaintSelection( sal_Bool bPaint); >- >- void EraseVirtualDevice(); >- >- // aus dem protected Teil hierher verschoben >- // F�r 'SvtXECTextCursor' (TL). Mu� ggf nochmal anders gel�st werden. >- TextPaM PageUp( const TextPaM& rPaM ); >- TextPaM PageDown( const TextPaM& rPaM ); >- TextPaM CursorUp( const TextPaM& rPaM ); >- TextPaM CursorDown( const TextPaM& rPaM ); >- TextPaM CursorLeft( const TextPaM& rPaM, sal_uInt16 nCharacterIteratorMode ); >- TextPaM CursorRight( const TextPaM& rPaM, sal_uInt16 nCharacterIteratorMode ); >- TextPaM CursorWordLeft( const TextPaM& rPaM ); >- TextPaM CursorWordRight( const TextPaM& rPaM ); >- TextPaM CursorStartOfLine( const TextPaM& rPaM ); >- TextPaM CursorEndOfLine( const TextPaM& rPaM ); >- TextPaM CursorStartOfParagraph( const TextPaM& rPaM ); >- TextPaM CursorEndOfParagraph( const TextPaM& rPaM ); >- TextPaM CursorStartOfDoc(); >- TextPaM CursorEndOfDoc(); >- >- /** >- Drag and Drop, deleting and selection regards all text that has an attribute >- TEXTATTR_PROTECTED set as one entitity. Drag and dropped text is automatically >- attibuted as protected. >- */ >- void SupportProtectAttribute(sal_Bool bSupport); >- >- /** >- Returns the number in paragraph of the line in which the cursor is blinking >- if enabled, -1 otherwise. >- */ >- sal_Int32 GetLineNumberOfCursorInSelection() const; >-}; >- >-#endif // _TEXTVIEW_HXX >- >-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/svtools/inc/svtools/txtattr.hxx b/svtools/inc/svtools/txtattr.hxx >deleted file mode 100644 >index bf4c8e3..0000000 >--- a/svtools/inc/svtools/txtattr.hxx >+++ /dev/null >@@ -1,236 +0,0 @@ >-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >-/************************************************************************* >- * >- * 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 _TXTATTR_HXX >-#define _TXTATTR_HXX >- >-#include "svtools/svtdllapi.h" >-#include <tools/color.hxx> >-#include <vcl/vclenum.hxx> >-#include <tools/string.hxx> >-#include <tools/debug.hxx> >- >-class Font; >- >-#define TEXTATTR_INVALID 0 >-#define TEXTATTR_FONTCOLOR 1 >-#define TEXTATTR_HYPERLINK 2 >-#define TEXTATTR_FONTWEIGHT 3 >- >-#define TEXTATTR_USER_START 1000 //start id for user defined text attributes >-#define TEXTATTR_PROTECTED 4 >- >- >-class SVT_DLLPUBLIC TextAttrib >-{ >-private: >- sal_uInt16 mnWhich; >- >-protected: >- TextAttrib( sal_uInt16 nWhich ) { mnWhich = nWhich; } >- TextAttrib( const TextAttrib& rAttr ) { mnWhich = rAttr.mnWhich; } >- >-public: >- >- virtual ~TextAttrib(); >- >- sal_uInt16 Which() const { return mnWhich; } >- virtual void SetFont( Font& rFont ) const = 0; >- virtual TextAttrib* Clone() const = 0; >- >- virtual int operator==( const TextAttrib& rAttr ) const = 0; >- int operator!=( const TextAttrib& rAttr ) const >- { return !(*this == rAttr ); } >-}; >- >- >- >-class SVT_DLLPUBLIC TextAttribFontColor : public TextAttrib >-{ >-private: >- Color maColor; >- >-public: >- TextAttribFontColor( const Color& rColor ); >- TextAttribFontColor( const TextAttribFontColor& rAttr ); >- ~TextAttribFontColor(); >- >- const Color& GetColor() const { return maColor; } >- >- virtual void SetFont( Font& rFont ) const; >- virtual TextAttrib* Clone() const; >- virtual int operator==( const TextAttrib& rAttr ) const; >- >-}; >- >-class SVT_DLLPUBLIC TextAttribFontWeight : public TextAttrib >-{ >-private: >- FontWeight meWeight; >- >-public: >- TextAttribFontWeight( FontWeight eWeight ); >- TextAttribFontWeight( const TextAttribFontWeight& rAttr ); >- ~TextAttribFontWeight(); >- >- virtual void SetFont( Font& rFont ) const; >- virtual TextAttrib* Clone() const; >- virtual int operator==( const TextAttrib& rAttr ) const; >- >- inline FontWeight getFontWeight() const { return meWeight; } >-}; >- >- >-class TextAttribHyperLink : public TextAttrib >-{ >-private: >- XubString maURL; >- XubString maDescription; >- Color maColor; >- >-public: >- TextAttribHyperLink( const TextAttribHyperLink& rAttr ); >- ~TextAttribHyperLink(); >- >- void SetURL( const XubString& rURL ) { maURL = rURL; } >- const XubString& GetURL() const { return maURL; } >- >- void SetDescription( const XubString& rDescr ) { maDescription = rDescr; } >- const XubString& GetDescription() const { return maDescription; } >- >- void SetColor( const Color& rColor ) { maColor = rColor; } >- const Color& GetColor() const { return maColor; } >- >- virtual void SetFont( Font& rFont ) const; >- virtual TextAttrib* Clone() const; >- virtual int operator==( const TextAttrib& rAttr ) const; >-}; >- >-class SVT_DLLPUBLIC TextAttribProtect : public TextAttrib >-{ >-public: >- TextAttribProtect(); >- TextAttribProtect( const TextAttribProtect& rAttr ); >- ~TextAttribProtect(); >- >- virtual void SetFont( Font& rFont ) const; >- virtual TextAttrib* Clone() const; >- virtual int operator==( const TextAttrib& rAttr ) const; >- >-}; >- >- >-class TextCharAttrib >-{ >-private: >- TextAttrib* mpAttr; >- sal_uInt16 mnStart; >- sal_uInt16 mnEnd; >- >-protected: >- >-public: >- >- TextCharAttrib( const TextAttrib& rAttr, sal_uInt16 nStart, sal_uInt16 nEnd ); >- TextCharAttrib( const TextCharAttrib& rTextCharAttrib ); >- ~TextCharAttrib(); >- >- const TextAttrib& GetAttr() const { return *mpAttr; } >- >- sal_uInt16 Which() const { return mpAttr->Which(); } >- >- sal_uInt16 GetStart() const { return mnStart; } >- sal_uInt16& GetStart() { return mnStart; } >- >- sal_uInt16 GetEnd() const { return mnEnd; } >- sal_uInt16& GetEnd() { return mnEnd; } >- >- inline sal_uInt16 GetLen() const; >- >- inline void MoveForward( sal_uInt16 nDiff ); >- inline void MoveBackward( sal_uInt16 nDiff ); >- >- inline void Expand( sal_uInt16 nDiff ); >- inline void Collaps( sal_uInt16 nDiff ); >- >- inline sal_Bool IsIn( sal_uInt16 nIndex ); >- inline sal_Bool IsInside( sal_uInt16 nIndex ); >- inline sal_Bool IsEmpty(); >- >-}; >- >-inline sal_uInt16 TextCharAttrib::GetLen() const >-{ >- DBG_ASSERT( mnEnd >= mnStart, "TextCharAttrib: nEnd < nStart!" ); >- return mnEnd-mnStart; >-} >- >-inline void TextCharAttrib::MoveForward( sal_uInt16 nDiff ) >-{ >- DBG_ASSERT( ((long)mnEnd + nDiff) <= 0xFFFF, "TextCharAttrib: MoveForward?!" ); >- mnStart = mnStart + nDiff; >- mnEnd = mnEnd + nDiff; >-} >- >-inline void TextCharAttrib::MoveBackward( sal_uInt16 nDiff ) >-{ >- DBG_ASSERT( ((long)mnStart - nDiff) >= 0, "TextCharAttrib: MoveBackward?!" ); >- mnStart = mnStart - nDiff; >- mnEnd = mnEnd - nDiff; >-} >- >-inline void TextCharAttrib::Expand( sal_uInt16 nDiff ) >-{ >- DBG_ASSERT( ( ((long)mnEnd + nDiff) <= (long)0xFFFF ), "TextCharAttrib: Expand?!" ); >- mnEnd = mnEnd + nDiff; >-} >- >-inline void TextCharAttrib::Collaps( sal_uInt16 nDiff ) >-{ >- DBG_ASSERT( (long)mnEnd - nDiff >= (long)mnStart, "TextCharAttrib: Collaps?!" ); >- mnEnd = mnEnd - nDiff; >-} >- >-inline sal_Bool TextCharAttrib::IsIn( sal_uInt16 nIndex ) >-{ >- return ( ( mnStart <= nIndex ) && ( mnEnd >= nIndex ) ); >-} >- >-inline sal_Bool TextCharAttrib::IsInside( sal_uInt16 nIndex ) >-{ >- return ( ( mnStart < nIndex ) && ( mnEnd > nIndex ) ); >-} >- >-inline sal_Bool TextCharAttrib::IsEmpty() >-{ >- return mnStart == mnEnd; >-} >- >-#endif // _TXTATTR_HXX >- >-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/svtools/inc/svtools/xtextedt.hxx b/svtools/inc/svtools/xtextedt.hxx >deleted file mode 100644 >index b0b09b0..0000000 >--- a/svtools/inc/svtools/xtextedt.hxx >+++ /dev/null >@@ -1,69 +0,0 @@ >-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >-/* >- * This file is part of the LibreOffice project. >- * >- * This Source Code Form is subject to the terms of the Mozilla Public >- * License, v. 2.0. If a copy of the MPL was not distributed with this >- * file, You can obtain one at http://mozilla.org/MPL/2.0/. >- * >- * This file incorporates work covered by the following license notice: >- * >- * Licensed to the Apache Software Foundation (ASF) under one or more >- * contributor license agreements. See the NOTICE file distributed >- * with this work for additional information regarding copyright >- * ownership. The ASF licenses this file to you under the Apache >- * License, Version 2.0 (the "License"); you may not use this file >- * except in compliance with the License. You may obtain a copy of >- * the License at http://www.apache.org/licenses/LICENSE-2.0 . >- */ >-#ifndef _XTEXTEDT_HXX >-#define _XTEXTEDT_HXX >- >-#include "svtools/svtdllapi.h" >-#include <svtools/texteng.hxx> >-#include <svtools/textview.hxx> >- >-namespace com { >-namespace sun { >-namespace star { >-namespace util { >- struct SearchOptions; >-}}}} >- >-class SVT_DLLPUBLIC ExtTextEngine : public TextEngine >-{ >-private: >- String maGroupChars; >- >-public: >- ExtTextEngine(); >- ~ExtTextEngine(); >- >- const String& GetGroupChars() const { return maGroupChars; } >- void SetGroupChars( const String& r ) { maGroupChars = r; } >- TextSelection MatchGroup( const TextPaM& rCursor ) const; >- >- sal_Bool Search( TextSelection& rSel, const ::com::sun::star::util::SearchOptions& rSearchOptions, sal_Bool bForward = sal_True ); >-}; >- >-class SVT_DLLPUBLIC ExtTextView : public TextView >-{ >-protected: >- sal_Bool ImpIndentBlock( sal_Bool bRight ); >- >-public: >- ExtTextView( ExtTextEngine* pEng, Window* pWindow ); >- ~ExtTextView(); >- >- sal_Bool MatchGroup(); >- >- sal_Bool Search( const ::com::sun::star::util::SearchOptions& rSearchOptions, sal_Bool bForward ); >- sal_uInt16 Replace( const ::com::sun::star::util::SearchOptions& rSearchOptions, sal_Bool bAll, sal_Bool bForward ); >- >- sal_Bool IndentBlock(); >- sal_Bool UnindentBlock(); >-}; >- >-#endif // _XTEXTEDT_HXX >- >-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/svtools/source/brwbox/ebbcontrols.cxx b/svtools/source/brwbox/ebbcontrols.cxx >index b0ab801..bf818c2 100644 >--- a/svtools/source/brwbox/ebbcontrols.cxx >+++ b/svtools/source/brwbox/ebbcontrols.cxx >@@ -29,7 +29,7 @@ > #include <svtools/editbrowsebox.hxx> > #include <vcl/decoview.hxx> > #include <svtools/fmtfield.hxx> >-#include <svtools/xtextedt.hxx> >+#include <vcl/xtextedt.hxx> > > #include <algorithm> > >diff --git a/svtools/source/contnr/DocumentInfoPreview.cxx b/svtools/source/contnr/DocumentInfoPreview.cxx >index b27df17..3f3f15a 100644 >--- a/svtools/source/contnr/DocumentInfoPreview.cxx >+++ b/svtools/source/contnr/DocumentInfoPreview.cxx >@@ -38,7 +38,7 @@ > #include "svl/inettype.hxx" > #include "svtools/DocumentInfoPreview.hxx" > #include "svtools/imagemgr.hxx" >-#include "svtools/txtattr.hxx" >+#include "vcl/txtattr.hxx" > #include "tools/datetime.hxx" > #include "tools/urlobj.hxx" > #include "unotools/pathoptions.hxx" >diff --git a/svtools/source/contnr/templwin.cxx b/svtools/source/contnr/templwin.cxx >index 937236f..301967a 100644 >--- a/svtools/source/contnr/templwin.cxx >+++ b/svtools/source/contnr/templwin.cxx >@@ -33,13 +33,13 @@ > #include <unotools/pathoptions.hxx> > #include <unotools/dynamicmenuoptions.hxx> > #include <unotools/extendedsecurityoptions.hxx> >-#include <svtools/xtextedt.hxx> >+#include <vcl/xtextedt.hxx> > #include <svl/inettype.hxx> > #include <svtools/imagemgr.hxx> > #include <svtools/miscopt.hxx> > #include <svtools/templatefoldercache.hxx> > #include <svtools/imgdef.hxx> >-#include <svtools/txtattr.hxx> >+#include <vcl/txtattr.hxx> > #include <svtools/svtools.hrc> > #include "templwin.hrc" > #include <svtools/helpid.hrc> >diff --git a/svtools/source/edit/editsyntaxhighlighter.cxx b/svtools/source/edit/editsyntaxhighlighter.cxx >index 20749db..18361d3 100644 >--- a/svtools/source/edit/editsyntaxhighlighter.cxx >+++ b/svtools/source/edit/editsyntaxhighlighter.cxx >@@ -28,9 +28,9 @@ > > > #include <svtools/svmedit.hxx> >-#include <svtools/xtextedt.hxx> >+#include <vcl/xtextedt.hxx> > #include <svtools/editsyntaxhighlighter.hxx> >-#include <svtools/txtattr.hxx> >+#include <vcl/txtattr.hxx> > > > MultiLineEditSyntaxHighlight::MultiLineEditSyntaxHighlight( Window* pParent, WinBits nWinStyle, >diff --git a/svtools/source/edit/svmedit.cxx b/svtools/source/edit/svmedit.cxx >index 4fff9e0..24e97ec 100644 >--- a/svtools/source/edit/svmedit.cxx >+++ b/svtools/source/edit/svmedit.cxx >@@ -26,1593 +26,38 @@ > * > ************************************************************************/ > >-#include <memory> > >-#include "unoiface.hxx" >- >-#include <tools/rc.h> >- >-#include <vcl/decoview.hxx> >-#include <vcl/svapp.hxx> >- >-#include <svtools/svmedit.hxx> >-#include <svtools/xtextedt.hxx> >-#include <svl/brdcst.hxx> >-#include <svl/undo.hxx> >-#include <svtools/textwindowpeer.hxx> >-#include <svl/lstner.hxx> >-#include <svl/smplhint.hxx> >- >- >-// IDs erstmal aus VCL geklaut, muss mal richtig delivert werden... >-#define SV_MENU_EDIT_UNDO 1 >-#define SV_MENU_EDIT_CUT 2 >-#define SV_MENU_EDIT_COPY 3 >-#define SV_MENU_EDIT_PASTE 4 >-#define SV_MENU_EDIT_DELETE 5 >-#define SV_MENU_EDIT_SELECTALL 6 >-#define SV_MENU_EDIT_INSERTSYMBOL 7 >-#include <vcl/scrbar.hxx> >- >-namespace css = ::com::sun::star; >- >-class TextWindow : public Window >-{ >-private: >- ExtTextEngine* mpExtTextEngine; >- ExtTextView* mpExtTextView; >- >- sal_Bool mbInMBDown; >- sal_Bool mbFocusSelectionHide; >- sal_Bool mbIgnoreTab; >- sal_Bool mbActivePopup; >- sal_Bool mbSelectOnTab; >- sal_Bool mbTextSelectable; >- >-public: >- TextWindow( Window* pParent ); >- ~TextWindow(); >- >- ExtTextEngine* GetTextEngine() const { return mpExtTextEngine; } >- ExtTextView* GetTextView() const { return mpExtTextView; } >- >- virtual void MouseMove( const MouseEvent& rMEvt ); >- virtual void MouseButtonDown( const MouseEvent& rMEvt ); >- virtual void MouseButtonUp( const MouseEvent& rMEvt ); >- virtual void KeyInput( const KeyEvent& rKEvent ); >- >- virtual void Command( const CommandEvent& rCEvt ); >- >- virtual void Paint( const Rectangle& rRect ); >- virtual void Resize(); >- >- virtual void GetFocus(); >- virtual void LoseFocus(); >- >- sal_Bool IsAutoFocusHide() const { return mbFocusSelectionHide; } >- void SetAutoFocusHide( sal_Bool bAutoHide ) { mbFocusSelectionHide = bAutoHide; } >- >- sal_Bool IsIgnoreTab() const { return mbIgnoreTab; } >- void SetIgnoreTab( sal_Bool bIgnore ) { mbIgnoreTab = bIgnore; } >- >- void DisableSelectionOnFocus() { mbSelectOnTab = sal_False; } >- >- void SetTextSelectable( sal_Bool bTextSelectable ) { mbTextSelectable = bTextSelectable; } >- >- virtual >- ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > >- GetComponentInterface(sal_Bool bCreate = sal_True); >-}; >- >- >-class ImpSvMEdit : public SfxListener >-{ >-private: >- MultiLineEdit* pSvMultiLineEdit; >- >- TextWindow* mpTextWindow; >- ScrollBar* mpHScrollBar; >- ScrollBar* mpVScrollBar; >- ScrollBarBox* mpScrollBox; >- >- Point maTextWindowOffset; >- xub_StrLen mnTextWidth; >- mutable Selection maSelection; >- >-protected: >- virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); >- void ImpUpdateSrollBarVis( WinBits nWinStyle ); >- void ImpInitScrollBars(); >- void ImpSetScrollBarRanges(); >- void ImpSetHScrollBarThumbPos(); >- DECL_LINK( ScrollHdl, ScrollBar* ); >- >-public: >- ImpSvMEdit( MultiLineEdit* pSvMultiLineEdit, WinBits nWinStyle ); >- ~ImpSvMEdit(); >- >- void SetModified( sal_Bool bMod ); >- sal_Bool IsModified() const; >- >- void SetReadOnly( sal_Bool bRdOnly ); >- sal_Bool IsReadOnly() const; >- >- void SetMaxTextLen( xub_StrLen nLen ); >- xub_StrLen GetMaxTextLen() const; >- >- sal_Bool IsInsertMode() const; >- >- void InsertText( const String& rStr ); >- String GetSelected() const; >- String GetSelected( LineEnd aSeparator ) const; >- >- void SetSelection( const Selection& rSelection ); >- const Selection& GetSelection() const; >- >- void Cut(); >- void Copy(); >- void Paste(); >- >- void SetText( const String& rStr ); >- String GetText() const; >- String GetText( LineEnd aSeparator ) const; >- String GetTextLines( LineEnd aSeparator ) const; >- >- void Resize(); >- void GetFocus(); >- >- sal_Bool HandleCommand( const CommandEvent& rCEvt ); >- >- void Enable( sal_Bool bEnable ); >- >- Size CalcMinimumSize() const; >- Size CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const; >- void GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const; >- >- void SetAlign( WinBits nWinStyle ); >- >- void InitFromStyle( WinBits nWinStyle ); >- >- TextWindow* GetTextWindow() { return mpTextWindow; } >- ScrollBar* GetHScrollBar() { return mpHScrollBar; } >- ScrollBar* GetVScrollBar() { return mpVScrollBar; } >-}; >- >-ImpSvMEdit::ImpSvMEdit( MultiLineEdit* pEdt, WinBits nWinStyle ) >- :mpHScrollBar(NULL) >- ,mpVScrollBar(NULL) >- ,mpScrollBox(NULL) >-{ >- pSvMultiLineEdit = pEdt; >- mnTextWidth = 0; >- mpTextWindow = new TextWindow( pEdt ); >- mpTextWindow->Show(); >- InitFromStyle( nWinStyle ); >- StartListening( *mpTextWindow->GetTextEngine() ); >-} >- >-void ImpSvMEdit::ImpUpdateSrollBarVis( WinBits nWinStyle ) >-{ >- const sal_Bool bHaveVScroll = (NULL != mpVScrollBar); >- const sal_Bool bHaveHScroll = (NULL != mpHScrollBar); >- const sal_Bool bHaveScrollBox = (NULL != mpScrollBox); >- >- sal_Bool bNeedVScroll = ( nWinStyle & WB_VSCROLL ) == WB_VSCROLL; >- const sal_Bool bNeedHScroll = ( nWinStyle & WB_HSCROLL ) == WB_HSCROLL; >- >- const sal_Bool bAutoVScroll = ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL; >- if ( !bNeedVScroll && bAutoVScroll ) >- { >- TextEngine& rEngine( *mpTextWindow->GetTextEngine() ); >- sal_uLong nOverallTextHeight(0); >- for ( sal_uLong i=0; i<rEngine.GetParagraphCount(); ++i ) >- nOverallTextHeight += rEngine.GetTextHeight( i ); >- if ( nOverallTextHeight > (sal_uLong)mpTextWindow->GetOutputSizePixel().Height() ) >- bNeedVScroll = true; >- } >- >- const sal_Bool bNeedScrollBox = bNeedVScroll && bNeedHScroll; >- >- sal_Bool bScrollbarsChanged = false; >- if ( bHaveVScroll != bNeedVScroll ) >- { >- delete mpVScrollBar; >- mpVScrollBar = bNeedVScroll ? new ScrollBar( pSvMultiLineEdit, WB_VSCROLL|WB_DRAG ) : NULL; >- >- if ( bNeedVScroll ) >- { >- mpVScrollBar->Show(); >- mpVScrollBar->SetScrollHdl( LINK( this, ImpSvMEdit, ScrollHdl ) ); >- } >- >- bScrollbarsChanged = sal_True; >- } >- >- if ( bHaveHScroll != bNeedHScroll ) >- { >- delete mpHScrollBar; >- mpHScrollBar = bNeedHScroll ? new ScrollBar( pSvMultiLineEdit, WB_HSCROLL|WB_DRAG ) : NULL; >- >- if ( bNeedHScroll ) >- { >- mpHScrollBar->Show(); >- mpHScrollBar->SetScrollHdl( LINK( this, ImpSvMEdit, ScrollHdl ) ); >- } >- >- bScrollbarsChanged = sal_True; >- } >- >- if ( bHaveScrollBox != bNeedScrollBox ) >- { >- delete mpScrollBox; >- mpScrollBox = bNeedScrollBox ? new ScrollBarBox( pSvMultiLineEdit, WB_SIZEABLE ) : NULL; >- >- if ( bNeedScrollBox ) >- mpScrollBox->Show(); >- } >- >- if ( bScrollbarsChanged ) >- { >- ImpInitScrollBars(); >- Resize(); >- } >-} >- >-void ImpSvMEdit::InitFromStyle( WinBits nWinStyle ) >-{ >- ImpUpdateSrollBarVis( nWinStyle ); >- SetAlign( nWinStyle ); >- >- if ( nWinStyle & WB_NOHIDESELECTION ) >- mpTextWindow->SetAutoFocusHide( sal_False ); >- else >- mpTextWindow->SetAutoFocusHide( sal_True ); >- >- if ( nWinStyle & WB_READONLY ) >- mpTextWindow->GetTextView()->SetReadOnly( sal_True ); >- else >- mpTextWindow->GetTextView()->SetReadOnly( sal_False ); >- >- if ( nWinStyle & WB_IGNORETAB ) >- { >- mpTextWindow->SetIgnoreTab( sal_True ); >- } >- else >- { >- mpTextWindow->SetIgnoreTab( sal_False ); >- // #103667# MultiLineEdit has the flag, but focusable window also needs this flag >- WinBits nStyle = mpTextWindow->GetStyle(); >- nStyle |= WINDOW_DLGCTRL_MOD1TAB; >- mpTextWindow->SetStyle( nStyle ); >- } >-} >- >-ImpSvMEdit::~ImpSvMEdit() >-{ >- EndListening( *mpTextWindow->GetTextEngine() ); >- delete mpTextWindow; >- delete mpHScrollBar; >- delete mpVScrollBar; >- delete mpScrollBox; >-} >- >-void ImpSvMEdit::ImpSetScrollBarRanges() >-{ >- if ( mpVScrollBar ) >- { >- sal_uLong nTextHeight = mpTextWindow->GetTextEngine()->GetTextHeight(); >- mpVScrollBar->SetRange( Range( 0, (long)nTextHeight-1 ) ); >- } >- if ( mpHScrollBar ) >- { >-// sal_uLong nTextWidth = mpTextWindow->GetTextEngine()->CalcTextWidth(); >- // Es gibt kein Notify bei Breiten-Aenderung... >-// sal_uLong nW = Max( (sal_uLong)mpTextWindow->GetOutputSizePixel().Width()*5, (sal_uLong)nTextWidth ); >-// mpHScrollBar->SetRange( Range( 0, (long)nW ) ); >- mpHScrollBar->SetRange( Range( 0, (long)mnTextWidth-1 ) ); >- } >-} >- >-void ImpSvMEdit::ImpInitScrollBars() >-{ >- static const sal_Unicode sampleChar = { 'x' }; >- if ( mpHScrollBar || mpVScrollBar ) >- { >- ImpSetScrollBarRanges(); >- Size aCharBox; >- aCharBox.Width() = mpTextWindow->GetTextWidth( rtl::OUString(sampleChar) ); >- aCharBox.Height() = mpTextWindow->GetTextHeight(); >- Size aOutSz = mpTextWindow->GetOutputSizePixel(); >- if ( mpHScrollBar ) >- { >- mpHScrollBar->SetVisibleSize( aOutSz.Width() ); >- mpHScrollBar->SetPageSize( aOutSz.Width() * 8 / 10 ); >- mpHScrollBar->SetLineSize( aCharBox.Width()*10 ); >- ImpSetHScrollBarThumbPos(); >- } >- if ( mpVScrollBar ) >- { >- mpVScrollBar->SetVisibleSize( aOutSz.Height() ); >- mpVScrollBar->SetPageSize( aOutSz.Height() * 8 / 10 ); >- mpVScrollBar->SetLineSize( aCharBox.Height() ); >- mpVScrollBar->SetThumbPos( mpTextWindow->GetTextView()->GetStartDocPos().Y() ); >- } >- } >-} >- >-void ImpSvMEdit::ImpSetHScrollBarThumbPos() >-{ >- long nX = mpTextWindow->GetTextView()->GetStartDocPos().X(); >- if ( !mpTextWindow->GetTextEngine()->IsRightToLeft() ) >- mpHScrollBar->SetThumbPos( nX ); >- else >- mpHScrollBar->SetThumbPos( mnTextWidth - mpHScrollBar->GetVisibleSize() - nX ); >- >-} >- >-IMPL_LINK( ImpSvMEdit, ScrollHdl, ScrollBar*, pCurScrollBar ) >-{ >- long nDiffX = 0, nDiffY = 0; >- >- if ( pCurScrollBar == mpVScrollBar ) >- nDiffY = mpTextWindow->GetTextView()->GetStartDocPos().Y() - pCurScrollBar->GetThumbPos(); >- else if ( pCurScrollBar == mpHScrollBar ) >- nDiffX = mpTextWindow->GetTextView()->GetStartDocPos().X() - pCurScrollBar->GetThumbPos(); >- >- mpTextWindow->GetTextView()->Scroll( nDiffX, nDiffY ); >- // mpTextWindow->GetTextView()->ShowCursor( sal_False, sal_True ); >- >- return 0; >-} >- >- >-// void ImpSvMEdit::ImpModified() >-// { >-// // Wann wird das gerufen ????????????????????? >-// pSvMultiLineEdit->Modify(); >-// } >- >-void ImpSvMEdit::SetAlign( WinBits nWinStyle ) >-{ >- sal_Bool bRTL = Application::GetSettings().GetLayoutRTL(); >- mpTextWindow->GetTextEngine()->SetRightToLeft( bRTL ); >- >- if ( nWinStyle & WB_CENTER ) >- mpTextWindow->GetTextEngine()->SetTextAlign( TXTALIGN_CENTER ); >- else if ( nWinStyle & WB_RIGHT ) >- mpTextWindow->GetTextEngine()->SetTextAlign( !bRTL ? TXTALIGN_RIGHT : TXTALIGN_LEFT ); >- else if ( nWinStyle & WB_LEFT ) >- mpTextWindow->GetTextEngine()->SetTextAlign( !bRTL ? TXTALIGN_LEFT : TXTALIGN_RIGHT ); >-} >- >-void ImpSvMEdit::SetModified( sal_Bool bMod ) >-{ >- mpTextWindow->GetTextEngine()->SetModified( bMod ); >-} >- >-sal_Bool ImpSvMEdit::IsModified() const >-{ >- return mpTextWindow->GetTextEngine()->IsModified(); >-} >- >-void ImpSvMEdit::SetReadOnly( sal_Bool bRdOnly ) >-{ >- mpTextWindow->GetTextView()->SetReadOnly( bRdOnly ); >- // Farbe anpassen ??????????????????????????? >-} >- >-sal_Bool ImpSvMEdit::IsReadOnly() const >-{ >- return mpTextWindow->GetTextView()->IsReadOnly(); >-} >- >-void ImpSvMEdit::SetMaxTextLen( xub_StrLen nLen ) >-{ >- mpTextWindow->GetTextEngine()->SetMaxTextLen( nLen ); >-} >- >-xub_StrLen ImpSvMEdit::GetMaxTextLen() const >-{ >- return sal::static_int_cast< xub_StrLen >( >- mpTextWindow->GetTextEngine()->GetMaxTextLen()); >-} >- >-void ImpSvMEdit::InsertText( const String& rStr ) >-{ >- mpTextWindow->GetTextView()->InsertText( rStr ); >-} >- >-String ImpSvMEdit::GetSelected() const >-{ >- return mpTextWindow->GetTextView()->GetSelected(); >-} >- >-String ImpSvMEdit::GetSelected( LineEnd aSeparator ) const >-{ >- return mpTextWindow->GetTextView()->GetSelected( aSeparator ); >-} >- >-void ImpSvMEdit::Resize() >-{ >- size_t nIteration = 1; >- do >- { >- WinBits nWinStyle( pSvMultiLineEdit->GetStyle() ); >- if ( ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL ) >- ImpUpdateSrollBarVis( nWinStyle ); >- >- Size aSz = pSvMultiLineEdit->GetOutputSizePixel(); >- Size aEditSize = aSz; >- long nSBWidth = pSvMultiLineEdit->GetSettings().GetStyleSettings().GetScrollBarSize(); >- nSBWidth = pSvMultiLineEdit->CalcZoom( nSBWidth ); >- >- if ( mpHScrollBar ) >- aSz.Height() -= nSBWidth+1; >- if ( mpVScrollBar ) >- aSz.Width() -= nSBWidth+1; >- >- if ( !mpHScrollBar ) >- mpTextWindow->GetTextEngine()->SetMaxTextWidth( aSz.Width() ); >- else >- mpHScrollBar->SetPosSizePixel( 0, aEditSize.Height()-nSBWidth, aSz.Width(), nSBWidth ); >- >- Point aTextWindowPos( maTextWindowOffset ); >- if ( mpVScrollBar ) >- { >- if( Application::GetSettings().GetLayoutRTL() ) >- { >- mpVScrollBar->SetPosSizePixel( 0, 0, nSBWidth, aSz.Height() ); >- aTextWindowPos.X() += nSBWidth; >- } >- else >- mpVScrollBar->SetPosSizePixel( aEditSize.Width()-nSBWidth, 0, nSBWidth, aSz.Height() ); >- } >- >- if ( mpScrollBox ) >- mpScrollBox->SetPosSizePixel( aSz.Width(), aSz.Height(), nSBWidth, nSBWidth ); >- >- Size aTextWindowSize( aSz ); >- aTextWindowSize.Width() -= maTextWindowOffset.X(); >- aTextWindowSize.Height() -= maTextWindowOffset.Y(); >- if ( aTextWindowSize.Width() < 0 ) >- aTextWindowSize.Width() = 0; >- if ( aTextWindowSize.Height() < 0 ) >- aTextWindowSize.Height() = 0; >- >- Size aOldTextWindowSize( mpTextWindow->GetSizePixel() ); >- mpTextWindow->SetPosSizePixel( aTextWindowPos, aTextWindowSize ); >- if ( aOldTextWindowSize == aTextWindowSize ) >- break; >- >- // Changing the text window size might effectively have changed the need for >- // scrollbars, so do another iteration. >- ++nIteration; >- OSL_ENSURE( nIteration < 3, "ImpSvMEdit::Resize: isn't this expected to terminate with the second iteration?" ); >- >- } while ( nIteration <= 3 ); // artificial break after four iterations >- >- ImpInitScrollBars(); >-} >- >-void ImpSvMEdit::GetFocus() >-{ >- mpTextWindow->GrabFocus(); >-} >- >-void ImpSvMEdit::Cut() >-{ >- if ( !mpTextWindow->GetTextView()->IsReadOnly() ) >- mpTextWindow->GetTextView()->Cut(); >-} >- >-void ImpSvMEdit::Copy() >-{ >- mpTextWindow->GetTextView()->Copy(); >-} >- >-void ImpSvMEdit::Paste() >-{ >- if ( !mpTextWindow->GetTextView()->IsReadOnly() ) >- mpTextWindow->GetTextView()->Paste(); >-} >- >-void ImpSvMEdit::SetText( const String& rStr ) >-{ >- sal_Bool bWasModified = mpTextWindow->GetTextEngine()->IsModified(); >- mpTextWindow->GetTextEngine()->SetText( rStr ); >- if ( !bWasModified ) >- mpTextWindow->GetTextEngine()->SetModified( sal_False ); >- >- mpTextWindow->GetTextView()->SetSelection( TextSelection() ); >- >- WinBits nWinStyle( pSvMultiLineEdit->GetStyle() ); >- if ( ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL ) >- ImpUpdateSrollBarVis( nWinStyle ); >-} >- >-String ImpSvMEdit::GetText() const >-{ >- return mpTextWindow->GetTextEngine()->GetText(); >-} >- >-String ImpSvMEdit::GetText( LineEnd aSeparator ) const >-{ >- return mpTextWindow->GetTextEngine()->GetText( aSeparator ); >-} >- >-String ImpSvMEdit::GetTextLines( LineEnd aSeparator ) const >-{ >- return mpTextWindow->GetTextEngine()->GetTextLines( aSeparator ); >-} >- >-void ImpSvMEdit::Notify( SfxBroadcaster&, const SfxHint& rHint ) >-{ >- if ( rHint.ISA( TextHint ) ) >- { >- const TextHint& rTextHint = (const TextHint&)rHint; >- if( rTextHint.GetId() == TEXT_HINT_VIEWSCROLLED ) >- { >- if ( mpHScrollBar ) >- ImpSetHScrollBarThumbPos(); >- if ( mpVScrollBar ) >- mpVScrollBar->SetThumbPos( mpTextWindow->GetTextView()->GetStartDocPos().Y() ); >- } >- else if( rTextHint.GetId() == TEXT_HINT_TEXTHEIGHTCHANGED ) >- { >- if ( mpTextWindow->GetTextView()->GetStartDocPos().Y() ) >- { >- long nOutHeight = mpTextWindow->GetOutputSizePixel().Height(); >- long nTextHeight = mpTextWindow->GetTextEngine()->GetTextHeight(); >- if ( nTextHeight < nOutHeight ) >- mpTextWindow->GetTextView()->Scroll( 0, mpTextWindow->GetTextView()->GetStartDocPos().Y() ); >- } >- >- ImpSetScrollBarRanges(); >- } >- else if( rTextHint.GetId() == TEXT_HINT_TEXTFORMATTED ) >- { >- if ( mpHScrollBar ) >- { >- sal_uLong nWidth = mpTextWindow->GetTextEngine()->CalcTextWidth(); >- if ( nWidth != mnTextWidth ) >- { >- mnTextWidth = sal::static_int_cast< xub_StrLen >(nWidth); >- mpHScrollBar->SetRange( Range( 0, (long)mnTextWidth-1 ) ); >- ImpSetHScrollBarThumbPos(); >- } >- } >- } >- else if( rTextHint.GetId() == TEXT_HINT_MODIFIED ) >- { >- pSvMultiLineEdit->Modify(); >- } >- } >-} >- >-void ImpSvMEdit::SetSelection( const Selection& rSelection ) >-{ >- String aText = mpTextWindow->GetTextEngine()->GetText(); >- >- Selection aNewSelection( rSelection ); >- if ( aNewSelection.Min() < 0 ) >- aNewSelection.Min() = 0; >- else if ( aNewSelection.Min() > aText.Len() ) >- aNewSelection.Min() = aText.Len(); >- if ( aNewSelection.Max() < 0 ) >- aNewSelection.Max() = 0; >- else if ( aNewSelection.Max() > aText.Len() ) >- aNewSelection.Max() = aText.Len(); >- >- long nEnd = Max( aNewSelection.Min(), aNewSelection.Max() ); >- TextSelection aTextSel; >- sal_uLong nPara = 0; >- sal_uInt16 nChar = 0; >- sal_uInt16 x = 0; >- while ( x <= nEnd ) >- { >- if ( x == aNewSelection.Min() ) >- aTextSel.GetStart() = TextPaM( nPara, nChar ); >- if ( x == aNewSelection.Max() ) >- aTextSel.GetEnd() = TextPaM( nPara, nChar ); >- >- if ( ( x < aText.Len() ) && ( aText.GetChar( x ) == '\n' ) ) >- { >- nPara++; >- nChar = 0; >- } >- else >- nChar++; >- x++; >- } >- mpTextWindow->GetTextView()->SetSelection( aTextSel ); >-} >- >-const Selection& ImpSvMEdit::GetSelection() const >-{ >- maSelection = Selection(); >- TextSelection aTextSel( mpTextWindow->GetTextView()->GetSelection() ); >- aTextSel.Justify(); >- // Selektion flachklopfen => jeder Umbruch ein Zeichen... >- >- ExtTextEngine* pExtTextEngine = mpTextWindow->GetTextEngine(); >- // Absaetze davor: >- sal_uLong n; >- for ( n = 0; n < aTextSel.GetStart().GetPara(); n++ ) >- { >- maSelection.Min() += pExtTextEngine->GetTextLen( n ); >- maSelection.Min()++; >- } >- >- // Erster Absatz mit Selektion: >- maSelection.Max() = maSelection.Min(); >- maSelection.Min() += aTextSel.GetStart().GetIndex(); >- >- for ( n = aTextSel.GetStart().GetPara(); n < aTextSel.GetEnd().GetPara(); n++ ) >- { >- maSelection.Max() += pExtTextEngine->GetTextLen( n ); >- maSelection.Max()++; >- } >- >- maSelection.Max() += aTextSel.GetEnd().GetIndex(); >- >- return maSelection; >-} >- >-Size ImpSvMEdit::CalcMinimumSize() const >-{ >- Size aSz( mpTextWindow->GetTextEngine()->CalcTextWidth(), >- mpTextWindow->GetTextEngine()->GetTextHeight() ); >- >- if ( mpHScrollBar ) >- aSz.Height() += mpHScrollBar->GetSizePixel().Height(); >- if ( mpVScrollBar ) >- aSz.Width() += mpVScrollBar->GetSizePixel().Width(); >- >- return aSz; >-} >- >-Size ImpSvMEdit::CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const >-{ >- static const sal_Unicode sampleChar = 'X'; >- >- Size aSz; >- Size aCharSz; >- aCharSz.Width() = mpTextWindow->GetTextWidth( rtl::OUString(sampleChar) ); >- aCharSz.Height() = mpTextWindow->GetTextHeight(); >- >- if ( nLines ) >- aSz.Height() = nLines*aCharSz.Height(); >- else >- aSz.Height() = mpTextWindow->GetTextEngine()->GetTextHeight(); >- >- if ( nColumns ) >- aSz.Width() = nColumns*aCharSz.Width(); >- else >- aSz.Width() = mpTextWindow->GetTextEngine()->CalcTextWidth(); >- >- if ( mpHScrollBar ) >- aSz.Height() += mpHScrollBar->GetSizePixel().Height(); >- if ( mpVScrollBar ) >- aSz.Width() += mpVScrollBar->GetSizePixel().Width(); >- >- return aSz; >-} >- >-void ImpSvMEdit::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const >-{ >- static const sal_Unicode sampleChar = { 'x' }; >- Size aOutSz = mpTextWindow->GetOutputSizePixel(); >- Size aCharSz( mpTextWindow->GetTextWidth( rtl::OUString(sampleChar) ), mpTextWindow->GetTextHeight() ); >- rnCols = (sal_uInt16) (aOutSz.Width()/aCharSz.Width()); >- rnLines = (sal_uInt16) (aOutSz.Height()/aCharSz.Height()); >-} >- >-void ImpSvMEdit::Enable( sal_Bool bEnable ) >-{ >- mpTextWindow->Enable( bEnable ); >- if ( mpHScrollBar ) >- mpHScrollBar->Enable( bEnable ); >- if ( mpVScrollBar ) >- mpVScrollBar->Enable( bEnable ); >-} >- >-sal_Bool ImpSvMEdit::HandleCommand( const CommandEvent& rCEvt ) >-{ >- sal_Bool bDone = sal_False; >- if ( ( rCEvt.GetCommand() == COMMAND_WHEEL ) || >- ( rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL ) || >- ( rCEvt.GetCommand() == COMMAND_AUTOSCROLL ) ) >- { >- mpTextWindow->HandleScrollCommand( rCEvt, mpHScrollBar, mpVScrollBar ); >- bDone = sal_True; >- } >- return bDone; >-} >- >- >-TextWindow::TextWindow( Window* pParent ) : Window( pParent ) >-{ >- mbInMBDown = sal_False; >- mbSelectOnTab = sal_True; >- mbFocusSelectionHide = sal_False; >- mbIgnoreTab = sal_False; >- mbActivePopup = sal_False; >- mbSelectOnTab = sal_True; >- mbTextSelectable = sal_True; >- >- SetPointer( Pointer( POINTER_TEXT ) ); >- >- mpExtTextEngine = new ExtTextEngine; >- mpExtTextEngine->SetMaxTextLen( STRING_MAXLEN ); >- if( pParent->GetStyle() & WB_BORDER ) >- mpExtTextEngine->SetLeftMargin( 2 ); >- mpExtTextEngine->SetLocale( GetSettings().GetLocale() ); >- mpExtTextView = new ExtTextView( mpExtTextEngine, this ); >- mpExtTextEngine->InsertView( mpExtTextView ); >- mpExtTextEngine->EnableUndo( sal_True ); >- mpExtTextView->ShowCursor(); >- >- Color aBackgroundColor = GetSettings().GetStyleSettings().GetWorkspaceColor(); >- SetBackground( aBackgroundColor ); >- pParent->SetBackground( aBackgroundColor ); >-} >- >-TextWindow::~TextWindow() >-{ >- delete mpExtTextView; >- delete mpExtTextEngine; >-} >- >-void TextWindow::MouseMove( const MouseEvent& rMEvt ) >-{ >- mpExtTextView->MouseMove( rMEvt ); >- Window::MouseMove( rMEvt ); >-} >- >-void TextWindow::MouseButtonDown( const MouseEvent& rMEvt ) >-{ >- if ( !mbTextSelectable ) >- return; >- >- mbInMBDown = sal_True; // Dann im GetFocus nicht alles selektieren wird >- mpExtTextView->MouseButtonDown( rMEvt ); >- Window::MouseButtonDown( rMEvt ); >- GrabFocus(); >- mbInMBDown = sal_False; >-} >- >-void TextWindow::MouseButtonUp( const MouseEvent& rMEvt ) >-{ >- mpExtTextView->MouseButtonUp( rMEvt ); >- Window::MouseButtonUp( rMEvt ); >-} >- >-void TextWindow::KeyInput( const KeyEvent& rKEvent ) >-{ >- sal_Bool bDone = sal_False; >- sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode(); >- if ( nCode == com::sun::star::awt::Key::SELECT_ALL || >- ( (nCode == KEY_A) && rKEvent.GetKeyCode().IsMod1() && !rKEvent.GetKeyCode().IsMod2() ) >- ) >- { >- mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( 0xFFFF, 0xFFFF ) ) ); >- bDone = sal_True; >- } >- else if ( (nCode == KEY_S) && rKEvent.GetKeyCode().IsShift() && rKEvent.GetKeyCode().IsMod1() ) >- { >- if ( Edit::GetGetSpecialCharsFunction() ) >- { >- // Damit die Selektion erhalten bleibt >- mbActivePopup = sal_True; >- rtl::OUString aChars = Edit::GetGetSpecialCharsFunction()( this, GetFont() ); >- if (!aChars.isEmpty()) >- { >- mpExtTextView->InsertText( aChars ); >- mpExtTextView->GetTextEngine()->SetModified( sal_True ); >- } >- mbActivePopup = sal_False; >- bDone = sal_True; >- } >- } >- else if ( nCode == KEY_TAB ) >- { >- if ( !mbIgnoreTab || rKEvent.GetKeyCode().IsMod1() ) >- bDone = mpExtTextView->KeyInput( rKEvent ); >- } >- else >- { >- bDone = mpExtTextView->KeyInput( rKEvent ); >- } > >- if ( !bDone ) >- Window::KeyInput( rKEvent ); >-} >- >-void TextWindow::Paint( const Rectangle& rRect ) >-{ >- mpExtTextView->Paint( rRect ); >-} >- >-void TextWindow::Resize() >-{ >-} >- >-void TextWindow::Command( const CommandEvent& rCEvt ) >-{ >- if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU ) >- { >- PopupMenu* pPopup = Edit::CreatePopupMenu(); >- if ( !mpExtTextView->HasSelection() ) >- { >- pPopup->EnableItem( SV_MENU_EDIT_CUT, sal_False ); >- pPopup->EnableItem( SV_MENU_EDIT_COPY, sal_False ); >- pPopup->EnableItem( SV_MENU_EDIT_DELETE, sal_False ); >- } >- if ( mpExtTextView->IsReadOnly() ) >- { >- pPopup->EnableItem( SV_MENU_EDIT_CUT, sal_False ); >- pPopup->EnableItem( SV_MENU_EDIT_PASTE, sal_False ); >- pPopup->EnableItem( SV_MENU_EDIT_DELETE, sal_False ); >- pPopup->EnableItem( SV_MENU_EDIT_INSERTSYMBOL, sal_False ); >- } >- if ( !mpExtTextView->GetTextEngine()->HasUndoManager() || !mpExtTextView->GetTextEngine()->GetUndoManager().GetUndoActionCount() ) >- { >- pPopup->EnableItem( SV_MENU_EDIT_UNDO, sal_False ); >- } >-// if ( ( maSelection.Min() == 0 ) && ( maSelection.Max() == maText.Len() ) ) >-// { >-// pPopup->EnableItem( SV_MENU_EDIT_SELECTALL, sal_False ); >-// } >- if ( !Edit::GetGetSpecialCharsFunction() ) >- { >- sal_uInt16 nPos = pPopup->GetItemPos( SV_MENU_EDIT_INSERTSYMBOL ); >- pPopup->RemoveItem( nPos ); >- pPopup->RemoveItem( nPos-1 ); >- } >- >- mbActivePopup = sal_True; >- Point aPos = rCEvt.GetMousePosPixel(); >- if ( !rCEvt.IsMouseEvent() ) >- { >- // !!! Irgendwann einmal Menu zentriert in der Selektion anzeigen !!! >- Size aSize = GetOutputSizePixel(); >- aPos = Point( aSize.Width()/2, aSize.Height()/2 ); >- } >-// pPopup->RemoveDisabledEntries(); >- sal_uInt16 n = pPopup->Execute( this, aPos ); >- Edit::DeletePopupMenu( pPopup ); >- switch ( n ) >- { >- case SV_MENU_EDIT_UNDO: mpExtTextView->Undo(); >- mpExtTextEngine->SetModified( sal_True ); >- mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) ); >- break; >- case SV_MENU_EDIT_CUT: mpExtTextView->Cut(); >- mpExtTextEngine->SetModified( sal_True ); >- mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) ); >- break; >- case SV_MENU_EDIT_COPY: mpExtTextView->Copy(); >- break; >- case SV_MENU_EDIT_PASTE: mpExtTextView->Paste(); >- mpExtTextEngine->SetModified( sal_True ); >- mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) ); >- break; >- case SV_MENU_EDIT_DELETE: mpExtTextView->DeleteSelected(); >- mpExtTextEngine->SetModified( sal_True ); >- mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) ); >- break; >- case SV_MENU_EDIT_SELECTALL: mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( 0xFFFFFFFF, 0xFFFF ) ) ); >- break; >- case SV_MENU_EDIT_INSERTSYMBOL: >- { >- rtl::OUString aChars = Edit::GetGetSpecialCharsFunction()( this, GetFont() ); >- if (!aChars.isEmpty()) >- { >- mpExtTextView->InsertText( aChars ); >- mpExtTextEngine->SetModified( sal_True ); >- mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) ); >- } >- } >- break; >- } >- mbActivePopup = sal_False; >- } >- else >- { >- mpExtTextView->Command( rCEvt ); >- } >- Window::Command( rCEvt ); >-} >- >-void TextWindow::GetFocus() >-{ >- Window::GetFocus(); >- if ( !mbActivePopup ) >- { >- sal_Bool bGotoCursor = !mpExtTextView->IsReadOnly(); >- if ( mbFocusSelectionHide && IsReallyVisible() && !mpExtTextView->IsReadOnly() >- && ( mbSelectOnTab && >- (!mbInMBDown || ( GetSettings().GetStyleSettings().GetSelectionOptions() & SELECTION_OPTION_FOCUS ) )) ) >- { >- // Alles selektieren, aber nicht scrollen >- sal_Bool bAutoScroll = mpExtTextView->IsAutoScroll(); >- mpExtTextView->SetAutoScroll( sal_False ); >- mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( 0xFFFF, 0xFFFF ) ) ); >- mpExtTextView->SetAutoScroll( bAutoScroll ); >- bGotoCursor = sal_False; >- } >- mpExtTextView->SetPaintSelection( sal_True ); >- mpExtTextView->ShowCursor( bGotoCursor ); >- } >-} >- >-void TextWindow::LoseFocus() >-{ >- Window::LoseFocus(); >+#include "unoiface.hxx" >+#include <svtools/textwindowpeer.hxx> > >- if ( mbFocusSelectionHide && !mbActivePopup ) >- mpExtTextView->SetPaintSelection( sal_False ); >-} > >-// virtual >-::css::uno::Reference< ::css::awt::XWindowPeer > >-TextWindow::GetComponentInterface(sal_Bool bCreate) >-{ >- ::css::uno::Reference< ::css::awt::XWindowPeer > xPeer( >- Window::GetComponentInterface(false)); >- if (!xPeer.is() && bCreate) >- { >- xPeer = new ::svt::TextWindowPeer(*GetTextView(), true); >- SetComponentInterface(xPeer); >- } >- return xPeer; >-} > > MultiLineEdit::MultiLineEdit( Window* pParent, WinBits nWinStyle ) >- : Edit( pParent, nWinStyle ) >+ : VCLMultiLineEdit( pParent,nWinStyle ) > { >- SetType( WINDOW_MULTILINEEDIT ); >- pImpSvMEdit = new ImpSvMEdit( this, nWinStyle ); >- ImplInitSettings( sal_True, sal_True, sal_True ); >- pUpdateDataTimer = 0; >- >- SetCompoundControl( sal_True ); >- SetStyle( ImplInitStyle( nWinStyle ) ); > } >- > MultiLineEdit::MultiLineEdit( Window* pParent, const ResId& rResId ) >- : Edit( pParent, rResId.SetRT( RSC_MULTILINEEDIT ) ) >-{ >- SetType( WINDOW_MULTILINEEDIT ); >- WinBits nWinStyle = rResId.GetWinBits(); >- pImpSvMEdit = new ImpSvMEdit( this, nWinStyle ); >- ImplInitSettings( sal_True, sal_True, sal_True ); >- pUpdateDataTimer = 0; >- >- sal_uInt16 nMaxLen = Edit::GetMaxTextLen(); >- if ( nMaxLen ) >- SetMaxTextLen( nMaxLen ); >- >- SetText( Edit::GetText() ); >- >- if ( IsVisible() ) >- pImpSvMEdit->Resize(); >- >- SetCompoundControl( sal_True ); >- SetStyle( ImplInitStyle( nWinStyle ) ); >- >- // Base Edit ctor could call Show already, but that would cause problems >- // with accessibility, as Show might (indirectly) trigger a call to virtual >- // GetComponentInterface, which is the Edit's base version instead of the >- // MultiLineEdit's version while in the base Edit ctor: >- if ((GetStyle() & WB_HIDE) == 0) >- Show(); >- >-} >- >-MultiLineEdit::~MultiLineEdit() >-{ >- { >- ::std::auto_ptr< ImpSvMEdit > pDelete( pImpSvMEdit ); >- pImpSvMEdit = NULL; >- } >- delete pUpdateDataTimer; >-} >- >-WinBits MultiLineEdit::ImplInitStyle( WinBits nStyle ) >-{ >- if ( !(nStyle & WB_NOTABSTOP) ) >- nStyle |= WB_TABSTOP; >- >- if ( !(nStyle & WB_NOGROUP) ) >- nStyle |= WB_GROUP; >- >- if ( !(nStyle & WB_IGNORETAB )) >- nStyle |= WINDOW_DLGCTRL_MOD1TAB; >- >- return nStyle; >-} >- >- >-void MultiLineEdit::ImplInitSettings( sal_Bool /*bFont*/, sal_Bool /*bForeground*/, sal_Bool bBackground ) >-{ >- const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); >- >- // Der Font muss immer mit manipuliert werden, weil die TextEngine >- // sich nicht um TextColor/Background kuemmert >- >- Color aTextColor = rStyleSettings.GetFieldTextColor(); >- if ( IsControlForeground() ) >- aTextColor = GetControlForeground(); >- if ( !IsEnabled() ) >- aTextColor = rStyleSettings.GetDisableColor(); >- >- Font aFont = rStyleSettings.GetFieldFont(); >- if ( IsControlFont() ) >- aFont.Merge( GetControlFont() ); >- aFont.SetTransparent( IsPaintTransparent() ); >- SetZoomedPointFont( aFont ); >- Font TheFont = GetFont(); >- TheFont.SetColor( aTextColor ); >- if( IsPaintTransparent() ) >- TheFont.SetFillColor( Color( COL_TRANSPARENT ) ); >- else >- TheFont.SetFillColor( IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor() ); >- pImpSvMEdit->GetTextWindow()->SetFont( TheFont ); >- pImpSvMEdit->GetTextWindow()->GetTextEngine()->SetFont( TheFont ); >- pImpSvMEdit->GetTextWindow()->SetTextColor( aTextColor ); >- >- if ( bBackground ) >- { >- if( IsPaintTransparent() ) >- { >- pImpSvMEdit->GetTextWindow()->SetPaintTransparent( sal_True ); >- pImpSvMEdit->GetTextWindow()->SetBackground(); >- pImpSvMEdit->GetTextWindow()->SetControlBackground(); >- SetBackground(); >- SetControlBackground(); >- } >- else >- { >- if( IsControlBackground() ) >- pImpSvMEdit->GetTextWindow()->SetBackground( GetControlBackground() ); >- else >- pImpSvMEdit->GetTextWindow()->SetBackground( rStyleSettings.GetFieldColor() ); >- // Auch am MultiLineEdit einstellen, weil die TextComponent >- // ggf. die Scrollbars hidet. >- SetBackground( pImpSvMEdit->GetTextWindow()->GetBackground() ); >- } >- } >-} >- >-void MultiLineEdit::Modify() >-{ >- aModifyHdlLink.Call( this ); >- >- CallEventListeners( VCLEVENT_EDIT_MODIFY ); >- >- if ( pUpdateDataTimer ) >- pUpdateDataTimer->Start(); >-} >- >-IMPL_LINK_NOARG(MultiLineEdit, ImpUpdateDataHdl) >-{ >- UpdateData(); >- return 0; >-} >- >-void MultiLineEdit::UpdateData() >-{ >- aUpdateDataHdlLink.Call( this ); >-} >- >-void MultiLineEdit::SetModifyFlag() >-{ >- pImpSvMEdit->SetModified( sal_True ); >-} >- >-void MultiLineEdit::ClearModifyFlag() >-{ >- pImpSvMEdit->SetModified( sal_False ); >-} >- >-sal_Bool MultiLineEdit::IsModified() const >-{ >- return pImpSvMEdit->IsModified(); >-} >- >-void MultiLineEdit::EnableUpdateData( sal_uLong nTimeout ) >-{ >- if ( !nTimeout ) >- DisableUpdateData(); >- else >- { >- if ( !pUpdateDataTimer ) >- { >- pUpdateDataTimer = new Timer; >- pUpdateDataTimer->SetTimeoutHdl( LINK( this, MultiLineEdit, ImpUpdateDataHdl ) ); >- } >- pUpdateDataTimer->SetTimeout( nTimeout ); >- } >-} >- >-void MultiLineEdit::SetReadOnly( sal_Bool bReadOnly ) >-{ >- pImpSvMEdit->SetReadOnly( bReadOnly ); >- Edit::SetReadOnly( bReadOnly ); >- >- // #94921# ReadOnly can be overwritten in InitFromStyle() when WB not set. >- WinBits nStyle = GetStyle(); >- if ( bReadOnly ) >- nStyle |= WB_READONLY; >- else >- nStyle &= ~WB_READONLY; >- SetStyle( nStyle ); >-} >- >-sal_Bool MultiLineEdit::IsReadOnly() const >-{ >- return pImpSvMEdit->IsReadOnly(); >-} >- >-void MultiLineEdit::SetMaxTextLen( xub_StrLen nMaxLen ) >-{ >- pImpSvMEdit->SetMaxTextLen( nMaxLen ); >-} >- >-xub_StrLen MultiLineEdit::GetMaxTextLen() const >-{ >- return pImpSvMEdit->GetMaxTextLen(); >-} >- >-void MultiLineEdit::ReplaceSelected( const String& rStr ) >-{ >- pImpSvMEdit->InsertText( rStr ); >-} >- >-void MultiLineEdit::DeleteSelected() >-{ >- pImpSvMEdit->InsertText( String() ); >-} >- >-String MultiLineEdit::GetSelected() const >-{ >- return pImpSvMEdit->GetSelected(); >-} >- >-String MultiLineEdit::GetSelected( LineEnd aSeparator ) const >-{ >- return pImpSvMEdit->GetSelected( aSeparator ); >-} >- >-void MultiLineEdit::Cut() >-{ >- pImpSvMEdit->Cut(); >-} >- >-void MultiLineEdit::Copy() >-{ >- pImpSvMEdit->Copy(); >-} >- >-void MultiLineEdit::Paste() >-{ >- pImpSvMEdit->Paste(); >-} >- >-void MultiLineEdit::SetText( const String& rStr ) >-{ >- pImpSvMEdit->SetText( rStr ); >-} >- >-String MultiLineEdit::GetText() const >-{ >- return pImpSvMEdit->GetText(); >-} >- >-String MultiLineEdit::GetText( LineEnd aSeparator ) const >-{ >- return pImpSvMEdit->GetText( aSeparator ); >-} >- >-String MultiLineEdit::GetTextLines( LineEnd aSeparator ) const >-{ >- return pImpSvMEdit->GetTextLines( aSeparator ); >-} >- >-void MultiLineEdit::Resize() >-{ >- pImpSvMEdit->Resize(); >-} >- >-void MultiLineEdit::GetFocus() >-{ >- if ( !pImpSvMEdit ) // might be called from within the dtor, when pImpSvMEdit == NULL is a valid state >- return; >- >- Edit::GetFocus(); >- pImpSvMEdit->GetFocus(); >-} >- >-void MultiLineEdit::SetSelection( const Selection& rSelection ) >-{ >- pImpSvMEdit->SetSelection( rSelection ); >-} >- >-const Selection& MultiLineEdit::GetSelection() const >-{ >- return pImpSvMEdit->GetSelection(); >-} >- >-Size MultiLineEdit::CalcMinimumSize() const >-{ >- Size aSz = pImpSvMEdit->CalcMinimumSize(); >- >- sal_Int32 nLeft, nTop, nRight, nBottom; >- ((Window*)this)->GetBorder( nLeft, nTop, nRight, nBottom ); >- aSz.Width() += nLeft+nRight; >- aSz.Height() += nTop+nBottom; >- >- return aSz; >-} >- >-Size MultiLineEdit::CalcAdjustedSize( const Size& rPrefSize ) const >-{ >- Size aSz = rPrefSize; >- sal_Int32 nLeft, nTop, nRight, nBottom; >- ((Window*)this)->GetBorder( nLeft, nTop, nRight, nBottom ); >- >- // In der Hoehe auf ganze Zeilen justieren >- >- long nHeight = aSz.Height() - nTop - nBottom; >- long nLineHeight = pImpSvMEdit->CalcSize( 1, 1 ).Height(); >- long nLines = nHeight / nLineHeight; >- if ( nLines < 1 ) >- nLines = 1; >- >- aSz.Height() = nLines * nLineHeight; >- aSz.Height() += nTop+nBottom; >- >- return aSz; >-} >- >-Size MultiLineEdit::CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const >-{ >- Size aSz = pImpSvMEdit->CalcSize( nColumns, nLines ); >- >- sal_Int32 nLeft, nTop, nRight, nBottom; >- ((Window*)this)->GetBorder( nLeft, nTop, nRight, nBottom ); >- aSz.Width() += nLeft+nRight; >- aSz.Height() += nTop+nBottom; >- return aSz; >-} >- >-void MultiLineEdit::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const >-{ >- pImpSvMEdit->GetMaxVisColumnsAndLines( rnCols, rnLines ); >-} >- >-void MultiLineEdit::StateChanged( StateChangedType nType ) >-{ >- if( nType == STATE_CHANGE_ENABLE ) >- { >- pImpSvMEdit->Enable( IsEnabled() ); >- ImplInitSettings( sal_True, sal_False, sal_False ); >- } >- else if( nType == STATE_CHANGE_READONLY ) >- { >- pImpSvMEdit->SetReadOnly( IsReadOnly() ); >- } >- else if ( nType == STATE_CHANGE_ZOOM ) >- { >- pImpSvMEdit->GetTextWindow()->SetZoom( GetZoom() ); >- ImplInitSettings( sal_True, sal_False, sal_False ); >- Resize(); >- } >- else if ( nType == STATE_CHANGE_CONTROLFONT ) >- { >- ImplInitSettings( sal_True, sal_False, sal_False ); >- Resize(); >- Invalidate(); >- } >- else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) >- { >- ImplInitSettings( sal_False, sal_True, sal_False ); >- Invalidate(); >- } >- else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) >- { >- ImplInitSettings( sal_False, sal_False, sal_True ); >- Invalidate(); >- } >- else if ( nType == STATE_CHANGE_STYLE ) >- { >- pImpSvMEdit->InitFromStyle( GetStyle() ); >- SetStyle( ImplInitStyle( GetStyle() ) ); >- } >- else if ( nType == STATE_CHANGE_INITSHOW ) >- { >- if( IsPaintTransparent() ) >- { >- pImpSvMEdit->GetTextWindow()->SetPaintTransparent( sal_True ); >- pImpSvMEdit->GetTextWindow()->SetBackground(); >- pImpSvMEdit->GetTextWindow()->SetControlBackground(); >- SetBackground(); >- SetControlBackground(); >- } >- } >- >- Control::StateChanged( nType ); >-} >- >-void MultiLineEdit::DataChanged( const DataChangedEvent& rDCEvt ) >-{ >- if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && >- (rDCEvt.GetFlags() & SETTINGS_STYLE) ) >- { >- ImplInitSettings( sal_True, sal_True, sal_True ); >- Resize(); >- Invalidate(); >- } >- else >- Control::DataChanged( rDCEvt ); >-} >- >-void MultiLineEdit::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags ) >-{ >- ImplInitSettings( sal_True, sal_True, sal_True ); >- >- Point aPos = pDev->LogicToPixel( rPos ); >- Size aSize = pDev->LogicToPixel( rSize ); >- Font aFont = pImpSvMEdit->GetTextWindow()->GetDrawPixelFont( pDev ); >- aFont.SetTransparent( sal_True ); >- OutDevType eOutDevType = pDev->GetOutDevType(); >- >- pDev->Push(); >- pDev->SetMapMode(); >- pDev->SetFont( aFont ); >- pDev->SetTextFillColor(); >- >- // Border/Background >- pDev->SetLineColor(); >- pDev->SetFillColor(); >- sal_Bool bBorder = !(nFlags & WINDOW_DRAW_NOBORDER ) && (GetStyle() & WB_BORDER); >- sal_Bool bBackground = !(nFlags & WINDOW_DRAW_NOBACKGROUND) && IsControlBackground(); >- if ( bBorder || bBackground ) >- { >- Rectangle aRect( aPos, aSize ); >- if ( bBorder ) >- { >- DecorationView aDecoView( pDev ); >- aRect = aDecoView.DrawFrame( aRect, FRAME_DRAW_DOUBLEIN ); >- } >- if ( bBackground ) >- { >- pDev->SetFillColor( GetControlBackground() ); >- pDev->DrawRect( aRect ); >- } >- } >- >- // Inhalt >- if ( ( nFlags & WINDOW_DRAW_MONO ) || ( eOutDevType == OUTDEV_PRINTER ) ) >- pDev->SetTextColor( Color( COL_BLACK ) ); >- else >- { >- if ( !(nFlags & WINDOW_DRAW_NODISABLE ) && !IsEnabled() ) >- { >- const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); >- pDev->SetTextColor( rStyleSettings.GetDisableColor() ); >- } >- else >- { >- pDev->SetTextColor( GetTextColor() ); >- } >- } >- >- rtl::OUString aText = GetText(); >- Size aTextSz( pDev->GetTextWidth( aText ), pDev->GetTextHeight() ); >- sal_uLong nLines = (sal_uLong) (aSize.Height() / aTextSz.Height()); >- if ( !nLines ) >- nLines = 1; >- aTextSz.Height() = nLines*aTextSz.Height(); >- long nOnePixel = GetDrawPixel( pDev, 1 ); >- long nOffX = 3*nOnePixel; >- long nOffY = 2*nOnePixel; >- >- // Clipping? >- if ( ( nOffY < 0 ) || ( (nOffY+aTextSz.Height()) > aSize.Height() ) || ( (nOffX+aTextSz.Width()) > aSize.Width() ) ) >- { >- Rectangle aClip( aPos, aSize ); >- if ( aTextSz.Height() > aSize.Height() ) >- aClip.Bottom() += aTextSz.Height() - aSize.Height() + 1; // Damit HP-Drucker nicht 'weg-optimieren' >- pDev->IntersectClipRegion( aClip ); >- } >- >- TextEngine aTE; >- aTE.SetText( GetText() ); >- aTE.SetMaxTextWidth( aSize.Width() ); >- aTE.SetFont( aFont ); >- aTE.SetTextAlign( pImpSvMEdit->GetTextWindow()->GetTextEngine()->GetTextAlign() ); >- aTE.Draw( pDev, Point( aPos.X() + nOffX, aPos.Y() + nOffY ) ); >- >- pDev->Pop(); >-} >- >-long MultiLineEdit::Notify( NotifyEvent& rNEvt ) >-{ >- long nDone = 0; >- if( rNEvt.GetType() == EVENT_COMMAND ) >- { >- nDone = pImpSvMEdit->HandleCommand( *rNEvt.GetCommandEvent() ); >- } >- return nDone ? nDone : Edit::Notify( rNEvt ); >-} >- >-long MultiLineEdit::PreNotify( NotifyEvent& rNEvt ) >-{ >- long nDone = 0; >- >-#if (OSL_DEBUG_LEVEL > 1) && defined(DBG_UTIL) >- if( rNEvt.GetType() == EVENT_KEYINPUT ) >- { >- const KeyEvent& rKEvent = *rNEvt.GetKeyEvent(); >- if ( ( rKEvent.GetKeyCode().GetCode() == KEY_W ) && rKEvent.GetKeyCode().IsMod1() && rKEvent.GetKeyCode().IsMod2() ) >- { >- SetRightToLeft( !IsRightToLeft() ); >- } >- } >-#endif >- >- if( ( rNEvt.GetType() == EVENT_KEYINPUT ) && ( !GetTextView()->IsCursorEnabled() ) ) >- { >- const KeyEvent& rKEvent = *rNEvt.GetKeyEvent(); >- if ( !rKEvent.GetKeyCode().IsShift() && ( rKEvent.GetKeyCode().GetGroup() == KEYGROUP_CURSOR ) ) >- { >- nDone = 1; >- TextSelection aSel = pImpSvMEdit->GetTextWindow()->GetTextView()->GetSelection(); >- if ( aSel.HasRange() ) >- { >- aSel.GetStart() = aSel.GetEnd(); >- pImpSvMEdit->GetTextWindow()->GetTextView()->SetSelection( aSel ); >- } >- else >- { >- switch ( rKEvent.GetKeyCode().GetCode() ) >- { >- case KEY_UP: >- { >- if ( pImpSvMEdit->GetVScrollBar() ) >- pImpSvMEdit->GetVScrollBar()->DoScrollAction( SCROLL_LINEUP ); >- } >- break; >- case KEY_DOWN: >- { >- if ( pImpSvMEdit->GetVScrollBar() ) >- pImpSvMEdit->GetVScrollBar()->DoScrollAction( SCROLL_LINEDOWN ); >- } >- break; >- case KEY_PAGEUP : >- { >- if ( pImpSvMEdit->GetVScrollBar() ) >- pImpSvMEdit->GetVScrollBar()->DoScrollAction( SCROLL_PAGEUP ); >- } >- break; >- case KEY_PAGEDOWN: >- { >- if ( pImpSvMEdit->GetVScrollBar() ) >- pImpSvMEdit->GetVScrollBar()->DoScrollAction( SCROLL_PAGEDOWN ); >- } >- break; >- case KEY_LEFT: >- { >- if ( pImpSvMEdit->GetHScrollBar() ) >- pImpSvMEdit->GetHScrollBar()->DoScrollAction( SCROLL_LINEUP ); >- } >- break; >- case KEY_RIGHT: >- { >- if ( pImpSvMEdit->GetHScrollBar() ) >- pImpSvMEdit->GetHScrollBar()->DoScrollAction( SCROLL_LINEDOWN ); >- } >- break; >- case KEY_HOME: >- { >- if ( rKEvent.GetKeyCode().IsMod1() ) >- pImpSvMEdit->GetTextWindow()->GetTextView()-> >- SetSelection( TextSelection( TextPaM( 0, 0 ) ) ); >- } >- break; >- case KEY_END: >- { >- if ( rKEvent.GetKeyCode().IsMod1() ) >- pImpSvMEdit->GetTextWindow()->GetTextView()-> >- SetSelection( TextSelection( TextPaM( 0xFFFF, 0xFFFF ) ) ); >- } >- break; >- default: >- { >- nDone = 0; >- } >- } >- } >- } >- } >- >- return nDone ? nDone : Edit::PreNotify( rNEvt ); >-} >- >-// >-// Internas fuer abgeleitete Klassen, z.B. TextComponent >- >-ExtTextEngine* MultiLineEdit::GetTextEngine() const >-{ >- return pImpSvMEdit->GetTextWindow()->GetTextEngine(); >-} >- >-ExtTextView* MultiLineEdit::GetTextView() const >-{ >- return pImpSvMEdit->GetTextWindow()->GetTextView(); >-} >- >-ScrollBar* MultiLineEdit::GetVScrollBar() const >-{ >- return pImpSvMEdit->GetVScrollBar(); >-} >- >-void MultiLineEdit::EnableFocusSelectionHide( sal_Bool bHide ) >-{ >- pImpSvMEdit->GetTextWindow()->SetAutoFocusHide( bHide ); >-} >- >-void MultiLineEdit::SetLeftMargin( sal_uInt16 n ) >+ : VCLMultiLineEdit( pParent,rResId ) > { >- if ( GetTextEngine() ) >- GetTextEngine()->SetLeftMargin( n ); > } > >-void MultiLineEdit::SetRightToLeft( sal_Bool bRightToLeft ) >-{ >- if ( GetTextEngine() ) >- { >- GetTextEngine()->SetRightToLeft( bRightToLeft ); >- GetTextView()->ShowCursor(); >- } >-} >- >-sal_Bool MultiLineEdit::IsRightToLeft() const >-{ >- sal_Bool bRightToLeft = sal_False; >- >- if ( GetTextEngine() ) >- bRightToLeft = GetTextEngine()->IsRightToLeft(); >- >- return bRightToLeft; >-} >+namespace css = ::com::sun::star; > > // virtual > ::css::uno::Reference< ::css::awt::XWindowPeer > > MultiLineEdit::GetComponentInterface(sal_Bool bCreate) > { > ::css::uno::Reference< ::css::awt::XWindowPeer > xPeer( >- Edit::GetComponentInterface(false)); >+ VCLMultiLineEdit::GetComponentInterface(false)); > if (!xPeer.is() && bCreate) > { >- ::std::auto_ptr< VCLXMultiLineEdit > xEdit(new VCLXMultiLineEdit()); >- xEdit->SetWindow(this); >- xPeer = xEdit.release(); >+ ::std::auto_ptr< VCLXMultiLineEdit > xVCLMEdit(new VCLXMultiLineEdit()); >+ xVCLMEdit->SetWindow(this); >+ xPeer = xVCLMEdit.release(); > SetComponentInterface(xPeer); > } > return xPeer; > } > >-void MultiLineEdit::DisableSelectionOnFocus() >-{ >- pImpSvMEdit->GetTextWindow()->DisableSelectionOnFocus(); >-} >- >-void MultiLineEdit::SetTextSelectable( sal_Bool bTextSelectable ) >-{ >- pImpSvMEdit->GetTextWindow()->SetTextSelectable( bTextSelectable ); >-} >- > /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/svtools/source/edit/svmedit2.cxx b/svtools/source/edit/svmedit2.cxx >index abd2fcf..8d530b2 100644 >--- a/svtools/source/edit/svmedit2.cxx >+++ b/svtools/source/edit/svmedit2.cxx >@@ -19,7 +19,7 @@ > > > #include <svtools/svmedit2.hxx> >-#include <svtools/xtextedt.hxx> >+#include <vcl/xtextedt.hxx> > > ExtMultiLineEdit::ExtMultiLineEdit( Window* pParent, WinBits nWinStyle ) : > >diff --git a/svtools/source/edit/textdat2.hxx b/svtools/source/edit/textdat2.hxx >deleted file mode 100644 >index c52d33e..0000000 >--- a/svtools/source/edit/textdat2.hxx >+++ /dev/null >@@ -1,312 +0,0 @@ >-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >-/************************************************************************* >- * >- * 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 _TEXTDAT2_HXX >-#define _TEXTDAT2_HXX >- >-#include <vcl/seleng.hxx> >-#include <vcl/virdev.hxx> >-#include <vcl/cursor.hxx> >- >-#include <vector> >- >-class TextNode; >-class TextView; >- >-#define PORTIONKIND_TEXT 0 >-#define PORTIONKIND_TAB 1 >- >-#define DELMODE_SIMPLE 0 >-#define DELMODE_RESTOFWORD 1 >-#define DELMODE_RESTOFCONTENT 2 >- >-#define DEL_LEFT 1 >-#define DEL_RIGHT 2 >-#define TRAVEL_X_DONTKNOW 0xFFFF >-#define MAXCHARSINPARA 0x3FFF-CHARPOSGROW >- >-#define LINE_SEP 0x0A >- >- >-class TETextPortion >-{ >-private: >- sal_uInt16 nLen; >- long nWidth; >- sal_uInt8 nKind; >- sal_uInt8 nRightToLeft; >- >- TETextPortion() { nLen = 0; nKind = PORTIONKIND_TEXT; nWidth = -1; nRightToLeft = 0;} >- >-public: >- TETextPortion( sal_uInt16 nL ) { >- nLen = nL; >- nKind = PORTIONKIND_TEXT; >- nWidth= -1; >- nRightToLeft = 0; >- } >- >- sal_uInt16 GetLen() const { return nLen; } >- sal_uInt16& GetLen() { return nLen; } >- >- long GetWidth()const { return nWidth; } >- long& GetWidth() { return nWidth; } >- >- sal_uInt8 GetKind() const { return nKind; } >- sal_uInt8& GetKind() { return nKind; } >- >- sal_uInt8 GetRightToLeft() const { return nRightToLeft; } >- sal_uInt8& GetRightToLeft() { return nRightToLeft; } >- sal_Bool IsRightToLeft() const { return (nRightToLeft&1); } >- >- sal_Bool HasValidSize() const { return nWidth != (-1); } >-}; >- >- >- >-typedef std::vector<TETextPortion*> TextPortionArray; >- >-class TETextPortionList : public TextPortionArray >-{ >-public: >- TETextPortionList(); >- ~TETextPortionList(); >- >- void Reset(); >- sal_uInt16 FindPortion( sal_uInt16 nCharPos, sal_uInt16& rPortionStart, sal_Bool bPreferStartingPortion = sal_False ); >- sal_uInt16 GetPortionStartIndex( sal_uInt16 nPortion ); >- void DeleteFromPortion( sal_uInt16 nDelFrom ); >-}; >- >-struct TEWritingDirectionInfo >-{ >- sal_uInt8 nType; >- sal_uInt16 nStartPos; >- sal_uInt16 nEndPos; >- TEWritingDirectionInfo( sal_uInt8 _Type, sal_uInt16 _Start, sal_uInt16 _End ) >- { >- nType = _Type; >- nStartPos = _Start; >- nEndPos = _End; >- } >-}; >- >-class TextLine >-{ >-private: >- sal_uInt16 mnStart; >- sal_uInt16 mnEnd; >- sal_uInt16 mnStartPortion; >- sal_uInt16 mnEndPortion; >- >- short mnStartX; >- >- sal_Bool mbInvalid; // fuer geschickte Formatierung/Ausgabe >- >-public: >- TextLine() { >- mnStart = mnEnd = 0; >- mnStartPortion = mnEndPortion = 0; >- mnStartX = 0; >- mbInvalid = sal_True; >- } >- >- sal_Bool IsIn( sal_uInt16 nIndex ) const >- { return ( (nIndex >= mnStart ) && ( nIndex < mnEnd ) ); } >- >- sal_Bool IsIn( sal_uInt16 nIndex, sal_Bool bInclEnd ) const >- { return ( ( nIndex >= mnStart ) && ( bInclEnd ? ( nIndex <= mnEnd ) : ( nIndex < mnEnd ) ) ); } >- >- void SetStart( sal_uInt16 n ) { mnStart = n; } >- sal_uInt16 GetStart() const { return mnStart; } >- sal_uInt16& GetStart() { return mnStart; } >- >- void SetEnd( sal_uInt16 n ) { mnEnd = n; } >- sal_uInt16 GetEnd() const { return mnEnd; } >- sal_uInt16& GetEnd() { return mnEnd; } >- >- void SetStartPortion( sal_uInt16 n ) { mnStartPortion = n; } >- sal_uInt16 GetStartPortion() const { return mnStartPortion; } >- sal_uInt16& GetStartPortion() { return mnStartPortion; } >- >- void SetEndPortion( sal_uInt16 n ) { mnEndPortion = n; } >- sal_uInt16 GetEndPortion() const { return mnEndPortion; } >- sal_uInt16& GetEndPortion() { return mnEndPortion; } >- >- sal_uInt16 GetLen() const { return mnEnd - mnStart; } >- >- sal_Bool IsInvalid() const { return mbInvalid; } >- sal_Bool IsValid() const { return !mbInvalid; } >- void SetInvalid() { mbInvalid = sal_True; } >- void SetValid() { mbInvalid = sal_False; } >- >- sal_Bool IsEmpty() const { return (mnEnd > mnStart) ? sal_False : sal_True; } >- >- short GetStartX() const { return mnStartX; } >- void SetStartX( short n ) { mnStartX = n; } >- >- inline sal_Bool operator == ( const TextLine& rLine ) const; >- inline sal_Bool operator != ( const TextLine& rLine ) const; >-}; >- >-class TextLines : public std::vector<TextLine*> { >-public: >- ~TextLines() >- { >- for( iterator it = begin(); it != end(); ++it ) >- delete *it; >- } >-}; >- >-inline sal_Bool TextLine::operator == ( const TextLine& rLine ) const >-{ >- return ( ( mnStart == rLine.mnStart ) && >- ( mnEnd == rLine.mnEnd ) && >- ( mnStartPortion == rLine.mnStartPortion ) && >- ( mnEndPortion == rLine.mnEndPortion ) ); >-} >- >-inline sal_Bool TextLine::operator != ( const TextLine& rLine ) const >-{ >- return !( *this == rLine ); >-} >- >- >- >-class TEParaPortion >-{ >-private: >- TextNode* mpNode; >- >- TextLines maLines; >- TETextPortionList maTextPortions; >- std::vector<TEWritingDirectionInfo> maWritingDirectionInfos; >- >- >- sal_uInt16 mnInvalidPosStart; >- short mnInvalidDiff; >- >- sal_Bool mbInvalid; >- sal_Bool mbSimple; // nur lineares Tippen >- >- >- TEParaPortion( const TEParaPortion& ) {;} >- >-public: >- TEParaPortion( TextNode* pNode ); >- ~TEParaPortion(); >- >- >- sal_Bool IsInvalid() const { return mbInvalid; } >- sal_Bool IsSimpleInvalid() const { return mbSimple; } >- void SetNotSimpleInvalid() { mbSimple = sal_False; } >- void SetValid() { mbInvalid = sal_False; mbSimple = sal_True;} >- >- void MarkInvalid( sal_uInt16 nStart, short nDiff); >- void MarkSelectionInvalid( sal_uInt16 nStart, sal_uInt16 nEnd ); >- >- sal_uInt16 GetInvalidPosStart() const { return mnInvalidPosStart; } >- short GetInvalidDiff() const { return mnInvalidDiff; } >- >- TextNode* GetNode() const { return mpNode; } >- TextLines& GetLines() { return maLines; } >- TETextPortionList& GetTextPortions() { return maTextPortions; } >- std::vector<TEWritingDirectionInfo>& GetWritingDirectionInfos() { return maWritingDirectionInfos; } >- >- >- sal_uInt16 GetLineNumber( sal_uInt16 nIndex, sal_Bool bInclEnd ); >- void CorrectValuesBehindLastFormattedLine( sal_uInt16 nLastFormattedLine ); >-}; >- >- >-class TEParaPortions : public ToolsList<TEParaPortion*> >-{ >-public: >- TEParaPortions(); >- ~TEParaPortions(); >- void Reset(); >-}; >- >- >-class TextSelFunctionSet: public FunctionSet >-{ >-private: >- TextView* mpView; >- >-public: >- TextSelFunctionSet( TextView* pView ); >- >- virtual void BeginDrag(); >- >- virtual void CreateAnchor(); >- >- virtual sal_Bool SetCursorAtPoint( const Point& rPointPixel, sal_Bool bDontSelectAtCursor = sal_False ); >- >- virtual sal_Bool IsSelectionAtPoint( const Point& rPointPixel ); >- virtual void DeselectAll(); >- >- virtual void DeselectAtPoint( const Point& ); >- virtual void DestroyAnchor(); >-}; >- >- >-class IdleFormatter : public Timer >-{ >-private: >- TextView* mpView; >- sal_uInt16 mnRestarts; >- >-public: >- IdleFormatter(); >- ~IdleFormatter(); >- >- void DoIdleFormat( TextView* pV, sal_uInt16 nMaxRestarts ); >- void ForceTimeout(); >- TextView* GetView() { return mpView; } >-}; >- >-struct TextDDInfo >-{ >- Cursor maCursor; >- TextPaM maDropPos; >- >- sal_Bool mbStarterOfDD; >- sal_Bool mbVisCursor; >- >- TextDDInfo() >- { >- maCursor.SetStyle( CURSOR_SHADOW ); >- mbStarterOfDD = sal_False; >- mbVisCursor = sal_False; >- } >-}; >- >-#endif // _TEXTDAT2_HXX >- >-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/svtools/source/edit/textdata.cxx b/svtools/source/edit/textdata.cxx >deleted file mode 100644 >index 7d55ee1..0000000 >--- a/svtools/source/edit/textdata.cxx >+++ /dev/null >@@ -1,345 +0,0 @@ >-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >-/************************************************************************* >- * >- * 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 <svtools/textdata.hxx> >-#include <textdat2.hxx> >- >-#include <tools/debug.hxx> >- >- >-// ------------------------------------------------------------------------- >-// (+) class TextSelection >-// ------------------------------------------------------------------------- >- >-TextSelection::TextSelection() >-{ >-} >- >-TextSelection::TextSelection( const TextPaM& rPaM ) : >- maStartPaM( rPaM ), maEndPaM( rPaM ) >-{ >-} >- >-TextSelection::TextSelection( const TextPaM& rStart, const TextPaM& rEnd ) : >- maStartPaM( rStart ), maEndPaM( rEnd ) >-{ >-} >- >-void TextSelection::Justify() >-{ >- if ( maEndPaM < maStartPaM ) >- { >- TextPaM aTemp( maStartPaM ); >- maStartPaM = maEndPaM; >- maEndPaM = aTemp; >- } >-} >- >- >-// ------------------------------------------------------------------------- >-// (+) class TETextPortionList >-// ------------------------------------------------------------------------- >-TETextPortionList::TETextPortionList() >-{ >-} >- >-TETextPortionList::~TETextPortionList() >-{ >- Reset(); >-} >- >-void TETextPortionList::Reset() >-{ >- for ( iterator it = begin(); it != end(); ++it ) >- delete *it; >- clear(); >-} >- >-void TETextPortionList::DeleteFromPortion( sal_uInt16 nDelFrom ) >-{ >- DBG_ASSERT( ( nDelFrom < size() ) || ( (nDelFrom == 0) && (size() == 0) ), "DeleteFromPortion: Out of range" ); >- for ( iterator it = begin() + nDelFrom; it != end(); ++it ) >- delete *it; >- erase( begin() + nDelFrom, end() ); >-} >- >-sal_uInt16 TETextPortionList::FindPortion( sal_uInt16 nCharPos, sal_uInt16& nPortionStart, sal_Bool bPreferStartingPortion ) >-{ >- // Bei nCharPos an Portion-Grenze wird die linke Portion gefunden >- sal_uInt16 nTmpPos = 0; >- for ( sal_uInt16 nPortion = 0; nPortion < size(); nPortion++ ) >- { >- TETextPortion* pPortion = operator[]( 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 == size() - 1 ) ) >- { >- nPortionStart = nTmpPos - pPortion->GetLen(); >- return nPortion; >- } >- } >- } >- OSL_FAIL( "FindPortion: Nicht gefunden!" ); >- return ( size() - 1 ); >-} >- >- >-// ------------------------------------------------------------------------- >-// (+) class TEParaPortion >-// ------------------------------------------------------------------------- >-TEParaPortion::TEParaPortion( TextNode* pN ) >-{ >- mpNode = pN; >- mnInvalidPosStart = mnInvalidDiff = 0; >- mbInvalid = sal_True; >- mbSimple = sal_False; >-} >- >-TEParaPortion::~TEParaPortion() >-{ >-} >- >-void TEParaPortion::MarkInvalid( sal_uInt16 nStart, short nDiff ) >-{ >- if ( mbInvalid == sal_False ) >- { >- mnInvalidPosStart = ( nDiff >= 0 ) ? nStart : ( nStart + nDiff ); >- mnInvalidDiff = nDiff; >- } >- else >- { >- // Einfaches hintereinander tippen >- if ( ( nDiff > 0 ) && ( mnInvalidDiff > 0 ) && >- ( ( mnInvalidPosStart+mnInvalidDiff ) == nStart ) ) >- { >- mnInvalidDiff = mnInvalidDiff + nDiff; >- } >- // Einfaches hintereinander loeschen >- else if ( ( nDiff < 0 ) && ( mnInvalidDiff < 0 ) && ( mnInvalidPosStart == nStart ) ) >- { >- mnInvalidPosStart = mnInvalidPosStart + nDiff; >- mnInvalidDiff = mnInvalidDiff + nDiff; >- } >- else >- { >- DBG_ASSERT( ( nDiff >= 0 ) || ( (nStart+nDiff) >= 0 ), "MarkInvalid: Diff out of Range" ); >- mnInvalidPosStart = Min( mnInvalidPosStart, (sal_uInt16) ( (nDiff < 0) ? nStart+nDiff : nDiff ) ); >- mnInvalidDiff = 0; >- mbSimple = sal_False; >- } >- } >- >- maWritingDirectionInfos.clear(); >- >- mbInvalid = sal_True; >-} >- >-void TEParaPortion::MarkSelectionInvalid( sal_uInt16 nStart, sal_uInt16 /*nEnd*/ ) >-{ >- if ( mbInvalid == sal_False ) >- { >- mnInvalidPosStart = nStart; >-// nInvalidPosEnd = nEnd; >- } >- else >- { >- mnInvalidPosStart = Min( mnInvalidPosStart, nStart ); >-// nInvalidPosEnd = pNode->Len(); >- } >- >- maWritingDirectionInfos.clear(); >- >- mnInvalidDiff = 0; >- mbInvalid = sal_True; >- mbSimple = sal_False; >-} >- >-sal_uInt16 TEParaPortion::GetLineNumber( sal_uInt16 nChar, sal_Bool bInclEnd ) >-{ >- for ( sal_uInt16 nLine = 0; nLine < maLines.size(); nLine++ ) >- { >- TextLine* pLine = maLines[ nLine ]; >- if ( ( bInclEnd && ( pLine->GetEnd() >= nChar ) ) || >- ( pLine->GetEnd() > nChar ) ) >- { >- return nLine; >- } >- } >- >- // Then it should be at the end of the last line >- OSL_ENSURE(nChar == maLines[maLines.size() - 1]->GetEnd(), "wrong Index"); >- OSL_ENSURE(!bInclEnd, "Line not found: FindLine"); >- return ( maLines.size() - 1 ); >-} >- >- >-void TEParaPortion::CorrectValuesBehindLastFormattedLine( sal_uInt16 nLastFormattedLine ) >-{ >- sal_uInt16 nLines = maLines.size(); >- DBG_ASSERT( nLines, "CorrectPortionNumbersFromLine: Leere Portion?" ); >- if ( nLastFormattedLine < ( nLines - 1 ) ) >- { >- const TextLine* pLastFormatted = maLines[ nLastFormattedLine ]; >- const TextLine* pUnformatted = maLines[ 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! >- short nPDiff = sal::static_int_cast< short >(-( nPortionDiff-1 )); >- short nTDiff = sal::static_int_cast< short >(-( nTextDiff-1 )); >- if ( nPDiff || nTDiff ) >- { >- for ( sal_uInt16 nL = nLastFormattedLine+1; nL < nLines; nL++ ) >- { >- TextLine* pLine = maLines[ nL ]; >- >- pLine->GetStartPortion() = pLine->GetStartPortion() + nPDiff; >- pLine->GetEndPortion() = pLine->GetEndPortion() + nPDiff; >- >- pLine->GetStart() = pLine->GetStart() + nTDiff; >- pLine->GetEnd() = pLine->GetEnd() + nTDiff; >- >- pLine->SetValid(); >- } >- } >- } >-} >- >-// ------------------------------------------------------------------------- >-// (+) class TEParaPortions >-// ------------------------------------------------------------------------- >-TEParaPortions::TEParaPortions() >-{ >-} >- >-TEParaPortions::~TEParaPortions() >-{ >- Reset(); >-} >- >-void TEParaPortions::Reset() >-{ >- TEParaPortions::iterator aIter( begin() ); >- while ( aIter != end() ) >- delete *aIter++; >- clear(); >-} >- >-// ------------------------------------------------------------------------- >-// (+) class IdleFormatter >-// ------------------------------------------------------------------------- >-IdleFormatter::IdleFormatter() >-{ >- mpView = 0; >- mnRestarts = 0; >-} >- >-IdleFormatter::~IdleFormatter() >-{ >- mpView = 0; >-} >- >-void IdleFormatter::DoIdleFormat( TextView* pV, sal_uInt16 nMaxRestarts ) >-{ >- mpView = pV; >- >- if ( IsActive() ) >- mnRestarts++; >- >- if ( mnRestarts > nMaxRestarts ) >- { >- mnRestarts = 0; >- ((Link&)GetTimeoutHdl()).Call( this ); >- } >- else >- { >- Start(); >- } >-} >- >-void IdleFormatter::ForceTimeout() >-{ >- if ( IsActive() ) >- { >- Stop(); >- mnRestarts = 0; >- ((Link&)GetTimeoutHdl()).Call( this ); >- } >-} >- >-TYPEINIT1( TextHint, SfxSimpleHint ); >- >-TextHint::TextHint( sal_uLong Id ) : SfxSimpleHint( Id ) >-{ >- mnValue = 0; >-} >- >-TextHint::TextHint( sal_uLong Id, sal_uLong nValue ) : SfxSimpleHint( Id ) >-{ >- mnValue = nValue; >-} >- >-TEIMEInfos::TEIMEInfos( const TextPaM& rPos, const String& rOldTextAfterStartPos ) >-: aOldTextAfterStartPos( rOldTextAfterStartPos ) >-{ >- aPos = rPos; >- nLen = 0; >- bCursor = sal_True; >- pAttribs = NULL; >- bWasCursorOverwrite = sal_False; >-} >- >-TEIMEInfos::~TEIMEInfos() >-{ >- delete[] pAttribs; >-} >- >-void TEIMEInfos::CopyAttribs( const sal_uInt16* pA, sal_uInt16 nL ) >-{ >- nLen = nL; >- delete pAttribs; >- pAttribs = new sal_uInt16[ nL ]; >- memcpy( pAttribs, pA, nL*sizeof(sal_uInt16) ); >-} >- >-void TEIMEInfos::DestroyAttribs() >-{ >- delete pAttribs; >- pAttribs = NULL; >- nLen = 0; >-} >- >- >-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/svtools/source/edit/textdoc.cxx b/svtools/source/edit/textdoc.cxx >deleted file mode 100644 >index a8062ec..0000000 >--- a/svtools/source/edit/textdoc.cxx >+++ /dev/null >@@ -1,636 +0,0 @@ >-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >-/************************************************************************* >- * >- * 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 <textdoc.hxx> >- >-#include <stdlib.h> >- >- >- >-// Vergleichmethode wird von QuickSort gerufen... >- >-static bool CompareStart( const TextCharAttrib* pFirst, const TextCharAttrib* pSecond ) >-{ >- return pFirst->GetStart() < pSecond->GetStart(); >-} >- >-// ------------------------------------------------------------------------- >-// (+) class TextCharAttrib >-// ------------------------------------------------------------------------- >-TextCharAttrib::TextCharAttrib( const TextAttrib& rAttr, sal_uInt16 nStart, sal_uInt16 nEnd ) >-{ >- mpAttr = rAttr.Clone(); >- mnStart = nStart, >- mnEnd = nEnd; >-} >- >-TextCharAttrib::TextCharAttrib( const TextCharAttrib& rTextCharAttrib ) >-{ >- mpAttr = rTextCharAttrib.GetAttr().Clone(); >- mnStart = rTextCharAttrib.mnStart; >- mnEnd = rTextCharAttrib.mnEnd; >-} >- >-TextCharAttrib::~TextCharAttrib() >-{ >- delete mpAttr; >-} >- >-// ------------------------------------------------------------------------- >-// (+) class TextCharAttribList >-// ------------------------------------------------------------------------- >- >-TextCharAttribList::TextCharAttribList() >-{ >- mbHasEmptyAttribs = sal_False; >-} >- >-TextCharAttribList::~TextCharAttribList() >-{ >- // PTRARR_DEL >-} >- >-void TextCharAttribList::Clear( sal_Bool bDestroyAttribs ) >-{ >- if ( bDestroyAttribs ) >- for(iterator it = begin(); it != end(); ++it) >- delete *it; >- TextCharAttribs::clear(); >-} >- >- >-void TextCharAttribList::InsertAttrib( TextCharAttrib* pAttrib ) >-{ >- if ( pAttrib->IsEmpty() ) >- mbHasEmptyAttribs = sal_True; >- >- const sal_uInt16 nCount = size(); >- const sal_uInt16 nStart = pAttrib->GetStart(); // vielleicht besser fuer Comp.Opt. >- sal_Bool bInserted = sal_False; >- for ( sal_uInt16 x = 0; x < nCount; x++ ) >- { >- TextCharAttrib* pCurAttrib = GetAttrib( x ); >- if ( pCurAttrib->GetStart() > nStart ) >- { >- insert( begin() + x, pAttrib ); >- bInserted = sal_True; >- break; >- } >- } >- if ( !bInserted ) >- push_back( pAttrib ); >-} >- >-void TextCharAttribList::ResortAttribs() >-{ >- if ( !empty() ) >- std::sort( begin(), end(), CompareStart ); >-} >- >-TextCharAttrib* TextCharAttribList::FindAttrib( sal_uInt16 nWhich, sal_uInt16 nPos ) >-{ >- // Rueckwaerts, falls eins dort endet, das naechste startet. >- // => Das startende gilt... >- >- for ( sal_uInt16 nAttr = size(); nAttr; ) >- { >- TextCharAttrib* pAttr = GetAttrib( --nAttr ); >- >- if ( pAttr->GetEnd() < nPos ) >- return 0; >- >- if ( ( pAttr->Which() == nWhich ) && pAttr->IsIn(nPos) ) >- return pAttr; >- } >- return NULL; >-} >- >-TextCharAttrib* TextCharAttribList::FindNextAttrib( sal_uInt16 nWhich, sal_uInt16 nFromPos, sal_uInt16 nMaxPos ) const >-{ >- DBG_ASSERT( nWhich, "FindNextAttrib: Which?" ); >- const sal_uInt16 nAttribs = size(); >- for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ ) >- { >- TextCharAttrib* pAttr = GetAttrib( nAttr ); >- if ( ( pAttr->GetStart() >= nFromPos ) && >- ( pAttr->GetEnd() <= nMaxPos ) && >- ( pAttr->Which() == nWhich ) ) >- return pAttr; >- } >- return NULL; >-} >- >-sal_Bool TextCharAttribList::HasAttrib( sal_uInt16 nWhich ) const >-{ >- for ( sal_uInt16 nAttr = size(); nAttr; ) >- { >- const TextCharAttrib* pAttr = GetAttrib( --nAttr ); >- if ( pAttr->Which() == nWhich ) >- return sal_True; >- } >- return sal_False; >-} >- >-sal_Bool TextCharAttribList::HasBoundingAttrib( sal_uInt16 nBound ) >-{ >- // Rueckwaerts, falls eins dort endet, das naechste startet. >- // => Das startende gilt... >- for ( sal_uInt16 nAttr = size(); nAttr; ) >- { >- TextCharAttrib* pAttr = GetAttrib( --nAttr ); >- >- if ( pAttr->GetEnd() < nBound ) >- return sal_False; >- >- if ( ( pAttr->GetStart() == nBound ) || ( pAttr->GetEnd() == nBound ) ) >- return sal_True; >- } >- return sal_False; >-} >- >-TextCharAttrib* TextCharAttribList::FindEmptyAttrib( sal_uInt16 nWhich, sal_uInt16 nPos ) >-{ >- if ( !mbHasEmptyAttribs ) >- return 0; >- >- const sal_uInt16 nAttribs = size(); >- for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ ) >- { >- TextCharAttrib* pAttr = GetAttrib( nAttr ); >- if ( pAttr->GetStart() > nPos ) >- return 0; >- >- if ( ( pAttr->GetStart() == nPos ) && ( pAttr->GetEnd() == nPos ) && ( pAttr->Which() == nWhich ) ) >- return pAttr; >- } >- return 0; >-} >- >-void TextCharAttribList::DeleteEmptyAttribs() >-{ >- for ( sal_uInt16 nAttr = 0; nAttr < size(); nAttr++ ) >- { >- TextCharAttrib* pAttr = GetAttrib( nAttr ); >- if ( pAttr->IsEmpty() ) >- { >- erase( begin() + nAttr ); >- delete pAttr; >- nAttr--; >- } >- } >- mbHasEmptyAttribs = sal_False; >-} >- >-// ------------------------------------------------------------------------- >-// (+) class TextNode >-// ------------------------------------------------------------------------- >- >-TextNode::TextNode( const String& rText ) : >- maText( rText ) >-{ >-} >- >-void TextNode::ExpandAttribs( sal_uInt16 nIndex, sal_uInt16 nNew ) >-{ >- if ( !nNew ) >- return; >- >- sal_Bool bResort = sal_False; >- sal_uInt16 nAttribs = maCharAttribs.Count(); >- for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ ) >- { >- TextCharAttrib* pAttrib = maCharAttribs.GetAttrib( nAttr ); >- 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 ); >- } >- // 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 ( !maCharAttribs.FindEmptyAttrib( pAttrib->Which(), nIndex ) ) >- { >- pAttrib->Expand( nNew ); >- } >- else >- bResort = sal_True; >- } >- // 2: Attribut startet davor, geht hinter Index... >- else if ( ( pAttrib->GetStart() < nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) >- { >- pAttrib->Expand( nNew ); >- } >- // 3: Attribut startet auf Index... >- else if ( pAttrib->GetStart() == nIndex ) >- { >- if ( nIndex == 0 ) >- { >- pAttrib->Expand( nNew ); >-// bResort = sal_True; // es gibt ja keine Features mehr... >- } >- else >- pAttrib->MoveForward( nNew ); >- } >- } >- >- DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Expand: Attribut verdreht!" ); >- DBG_ASSERT( ( pAttrib->GetEnd() <= maText.Len() ), "Expand: Attrib groesser als Absatz!" ); >- DBG_ASSERT( !pAttrib->IsEmpty(), "Leeres Attribut nach ExpandAttribs?" ); >- } >- >- if ( bResort ) >- maCharAttribs.ResortAttribs(); >-} >- >-void TextNode::CollapsAttribs( sal_uInt16 nIndex, sal_uInt16 nDeleted ) >-{ >- if ( !nDeleted ) >- return; >- >- sal_Bool bResort = sal_False; >- sal_uInt16 nEndChanges = nIndex+nDeleted; >- >- for ( sal_uInt16 nAttr = 0; nAttr < maCharAttribs.Count(); nAttr++ ) >- { >- TextCharAttrib* pAttrib = maCharAttribs.GetAttrib( nAttr ); >- sal_Bool bDelAttr = sal_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->GetStart() == nIndex ) && ( pAttrib->GetEnd() == nEndChanges ) ) >- pAttrib->GetEnd() = nIndex; // leer >- else >- bDelAttr = sal_True; >- } >- // 2. Attribut beginnt davor, endet drinnen oder dahinter... >- else if ( ( pAttrib->GetStart() <= nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) >- { >- 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! >- pAttrib->GetStart() = nEndChanges; >- pAttrib->MoveBackward( nDeleted ); >- } >- } >- >- DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Collaps: Attribut verdreht!" ); >- DBG_ASSERT( ( pAttrib->GetEnd() <= maText.Len()) || bDelAttr, "Collaps: Attrib groesser als Absatz!" ); >- if ( bDelAttr /* || pAttrib->IsEmpty() */ ) >- { >- bResort = sal_True; >- maCharAttribs.RemoveAttrib( nAttr ); >- delete pAttrib; >- nAttr--; >- } >- else if ( pAttrib->IsEmpty() ) >- maCharAttribs.HasEmptyAttribs() = sal_True; >- } >- >- if ( bResort ) >- maCharAttribs.ResortAttribs(); >-} >- >-void TextNode::InsertText( sal_uInt16 nPos, const String& rText ) >-{ >- maText.Insert( rText, nPos ); >- ExpandAttribs( nPos, rText.Len() ); >-} >- >-void TextNode::InsertText( sal_uInt16 nPos, sal_Unicode c ) >-{ >- maText.Insert( c, nPos ); >- ExpandAttribs( nPos, 1 ); >-} >- >-void TextNode::RemoveText( sal_uInt16 nPos, sal_uInt16 nChars ) >-{ >- maText.Erase( nPos, nChars ); >- CollapsAttribs( nPos, nChars ); >-} >- >-TextNode* TextNode::Split( sal_uInt16 nPos, sal_Bool bKeepEndingAttribs ) >-{ >- String aNewText; >- if ( nPos < maText.Len() ) >- { >- aNewText = maText.Copy( nPos ); >- maText.Erase( nPos ); >- } >- TextNode* pNew = new TextNode( aNewText ); >- >- for ( sal_uInt16 nAttr = 0; nAttr < maCharAttribs.Count(); nAttr++ ) >- { >- TextCharAttrib* pAttrib = maCharAttribs.GetAttrib( nAttr ); >- if ( pAttrib->GetEnd() < nPos ) >- { >- // bleiben unveraendert.... >- ; >- } >- else if ( pAttrib->GetEnd() == nPos ) >- { >- // muessen als leeres Attribut kopiert werden. >- // !FindAttrib nur sinnvoll, wenn Rueckwaerts durch Liste! >- if ( bKeepEndingAttribs && !pNew->maCharAttribs.FindAttrib( pAttrib->Which(), 0 ) ) >- { >- TextCharAttrib* pNewAttrib = new TextCharAttrib( *pAttrib ); >- pNewAttrib->GetStart() = 0; >- pNewAttrib->GetEnd() = 0; >- pNew->maCharAttribs.InsertAttrib( pNewAttrib ); >- } >- } >- else if ( pAttrib->IsInside( nPos ) || ( !nPos && !pAttrib->GetStart() ) ) >- { >- // Wenn ganz vorne gecuttet wird, muss das Attribut erhalten bleiben! >- // muessen kopiert und geaendert werden >- TextCharAttrib* pNewAttrib = new TextCharAttrib( *pAttrib ); >- pNewAttrib->GetStart() = 0; >- pNewAttrib->GetEnd() = pAttrib->GetEnd()-nPos; >- pNew->maCharAttribs.InsertAttrib( pNewAttrib ); >- // stutzen: >- pAttrib->GetEnd() = nPos; >- } >- else >- { >- DBG_ASSERT( pAttrib->GetStart() >= nPos, "Start < nPos!" ); >- DBG_ASSERT( pAttrib->GetEnd() >= nPos, "End < nPos!" ); >- // alle dahinter verschieben in den neuen Node (this) >- maCharAttribs.RemoveAttrib( nAttr ); >- pNew->maCharAttribs.InsertAttrib( pAttrib ); >- pAttrib->GetStart() = pAttrib->GetStart() - nPos; >- pAttrib->GetEnd() = pAttrib->GetEnd() - nPos; >- nAttr--; >- } >- } >- return pNew; >-} >- >-void TextNode::Append( const TextNode& rNode ) >-{ >- sal_uInt16 nOldLen = maText.Len(); >- >- maText += rNode.GetText(); >- >- const sal_uInt16 nAttribs = rNode.GetCharAttribs().Count(); >- for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ ) >- { >- TextCharAttrib* pAttrib = rNode.GetCharAttribs().GetAttrib( nAttr ); >- sal_Bool bMelted = sal_False; >- if ( pAttrib->GetStart() == 0 ) >- { >- // Evtl koennen Attribute zusammengefasst werden: >- sal_uInt16 nTmpAttribs = maCharAttribs.Count(); >- for ( sal_uInt16 nTmpAttr = 0; nTmpAttr < nTmpAttribs; nTmpAttr++ ) >- { >- TextCharAttrib* pTmpAttrib = maCharAttribs.GetAttrib( nTmpAttr ); >- >- if ( pTmpAttrib->GetEnd() == nOldLen ) >- { >- if ( ( pTmpAttrib->Which() == pAttrib->Which() ) && >- ( pTmpAttrib->GetAttr() == pAttrib->GetAttr() ) ) >- { >- pTmpAttrib->GetEnd() = >- pTmpAttrib->GetEnd() + pAttrib->GetLen(); >- bMelted = sal_True; >- break; // es kann nur eins von der Sorte an der Stelle geben >- } >- } >- } >- } >- >- if ( !bMelted ) >- { >- TextCharAttrib* pNewAttrib = new TextCharAttrib( *pAttrib ); >- pNewAttrib->GetStart() = pNewAttrib->GetStart() + nOldLen; >- pNewAttrib->GetEnd() = pNewAttrib->GetEnd() + nOldLen; >- maCharAttribs.InsertAttrib( pNewAttrib ); >- } >- } >-} >- >-// ------------------------------------------------------------------------- >-// (+) class TextDoc >-// ------------------------------------------------------------------------- >- >-TextDoc::TextDoc() >-{ >- mnLeftMargin = 0; >-}; >- >-TextDoc::~TextDoc() >-{ >- DestroyTextNodes(); >-} >- >-void TextDoc::Clear() >-{ >- DestroyTextNodes(); >-} >- >-void TextDoc::DestroyTextNodes() >-{ >- for ( sal_uLong nNode = 0; nNode < maTextNodes.Count(); nNode++ ) >- delete maTextNodes.GetObject( nNode ); >- maTextNodes.clear(); >-} >- >-String TextDoc::GetText( const sal_Unicode* pSep ) const >-{ >- sal_uLong nLen = GetTextLen( pSep ); >- sal_uLong nNodes = maTextNodes.Count(); >- >- if ( nLen > STRING_MAXLEN ) >- { >- OSL_FAIL( "Text zu gross fuer String" ); >- return String(); >- } >- >- String aASCIIText; >- sal_uLong nLastNode = nNodes-1; >- for ( sal_uLong nNode = 0; nNode < nNodes; nNode++ ) >- { >- TextNode* pNode = maTextNodes.GetObject( nNode ); >- String aTmp( pNode->GetText() ); >- aASCIIText += aTmp; >- if ( pSep && ( nNode != nLastNode ) ) >- aASCIIText += pSep; >- } >- >- return aASCIIText; >-} >- >-XubString TextDoc::GetText( sal_uLong nPara ) const >-{ >- XubString aText; >- TextNode* pNode = ( nPara < maTextNodes.Count() ) ? maTextNodes.GetObject( nPara ) : 0; >- if ( pNode ) >- aText = pNode->GetText(); >- >- return aText; >-} >- >- >-sal_uLong TextDoc::GetTextLen( const xub_Unicode* pSep, const TextSelection* pSel ) const >-{ >- sal_uLong nLen = 0; >- sal_uLong nNodes = maTextNodes.Count(); >- if ( nNodes ) >- { >- sal_uLong nStartNode = 0; >- sal_uLong nEndNode = nNodes-1; >- if ( pSel ) >- { >- nStartNode = pSel->GetStart().GetPara(); >- nEndNode = pSel->GetEnd().GetPara(); >- } >- >- for ( sal_uLong nNode = nStartNode; nNode <= nEndNode; nNode++ ) >- { >- TextNode* pNode = maTextNodes.GetObject( nNode ); >- >- sal_uInt16 nS = 0; >- sal_uLong nE = pNode->GetText().Len(); >- if ( pSel && ( nNode == pSel->GetStart().GetPara() ) ) >- nS = pSel->GetStart().GetIndex(); >- if ( pSel && ( nNode == pSel->GetEnd().GetPara() ) ) >- nE = pSel->GetEnd().GetIndex(); >- >- nLen += ( nE - nS ); >- } >- >- if ( pSep ) >- nLen += (nEndNode-nStartNode) * rtl_ustr_getLength(pSep); >- } >- >- return nLen; >-} >- >-TextPaM TextDoc::InsertText( const TextPaM& rPaM, xub_Unicode c ) >-{ >- DBG_ASSERT( c != 0x0A, "TextDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); >- DBG_ASSERT( c != 0x0D, "TextDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); >- >- TextNode* pNode = maTextNodes.GetObject( rPaM.GetPara() ); >- pNode->InsertText( rPaM.GetIndex(), c ); >- >- TextPaM aPaM( rPaM.GetPara(), rPaM.GetIndex()+1 ); >- return aPaM; >-} >- >-TextPaM TextDoc::InsertText( const TextPaM& rPaM, const XubString& rStr ) >-{ >- DBG_ASSERT( rStr.Search( 0x0A ) == STRING_NOTFOUND, "TextDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); >- DBG_ASSERT( rStr.Search( 0x0D ) == STRING_NOTFOUND, "TextDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); >- >- TextNode* pNode = maTextNodes.GetObject( rPaM.GetPara() ); >- pNode->InsertText( rPaM.GetIndex(), rStr ); >- >- TextPaM aPaM( rPaM.GetPara(), rPaM.GetIndex()+rStr.Len() ); >- return aPaM; >-} >- >-TextPaM TextDoc::InsertParaBreak( const TextPaM& rPaM, sal_Bool bKeepEndingAttribs ) >-{ >- TextNode* pNode = maTextNodes.GetObject( rPaM.GetPara() ); >- TextNode* pNew = pNode->Split( rPaM.GetIndex(), bKeepEndingAttribs ); >- >- maTextNodes.Insert( pNew, rPaM.GetPara()+1 ); >- >- TextPaM aPaM( rPaM.GetPara()+1, 0 ); >- return aPaM; >-} >- >-TextPaM TextDoc::ConnectParagraphs( TextNode* pLeft, TextNode* pRight ) >-{ >- sal_uInt16 nPrevLen = pLeft->GetText().Len(); >- pLeft->Append( *pRight ); >- >- // der rechte verschwindet. >- sal_uLong nRight = maTextNodes.GetPos( pRight ); >- maTextNodes.Remove( nRight ); >- delete pRight; >- >- sal_uLong nLeft = maTextNodes.GetPos( pLeft ); >- TextPaM aPaM( nLeft, nPrevLen ); >- return aPaM; >-} >- >-TextPaM TextDoc::RemoveChars( const TextPaM& rPaM, sal_uInt16 nChars ) >-{ >- TextNode* pNode = maTextNodes.GetObject( rPaM.GetPara() ); >- pNode->RemoveText( rPaM.GetIndex(), nChars ); >- >- return rPaM; >-} >- >-sal_Bool TextDoc::IsValidPaM( const TextPaM& rPaM ) >-{ >- if ( rPaM.GetPara() >= maTextNodes.Count() ) >- { >- OSL_FAIL( "PaM: Para out of range" ); >- return sal_False; >- } >- TextNode * pNode = maTextNodes.GetObject( rPaM.GetPara() ); >- if ( rPaM.GetIndex() > pNode->GetText().Len() ) >- { >- OSL_FAIL( "PaM: Index out of range" ); >- return sal_False; >- } >- return sal_True; >-} >- >-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/svtools/source/edit/textdoc.hxx b/svtools/source/edit/textdoc.hxx >deleted file mode 100644 >index 1551123..0000000 >--- a/svtools/source/edit/textdoc.hxx >+++ /dev/null >@@ -1,145 +0,0 @@ >-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >-/************************************************************************* >- * >- * 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 _TEXTDOC_HXX >-#define _TEXTDOC_HXX >- >-#include <svtools/textdata.hxx> >-#include <svtools/txtattr.hxx> >- >-#include <tools/string.hxx> >-#include <vector> >- >-class TextCharAttribs : public std::vector<TextCharAttrib*> { >-public: >- ~TextCharAttribs() >- { >- for( iterator it = begin(); it != end(); ++it ) >- delete *it; >- } >-}; >- >-class TextCharAttribList : private TextCharAttribs >-{ >-private: >- sal_Bool mbHasEmptyAttribs; >- >- TextCharAttribList( const TextCharAttribList& ) : TextCharAttribs() {} >- >-public: >- TextCharAttribList(); >- ~TextCharAttribList(); >- >- void Clear( sal_Bool bDestroyAttribs ); >- sal_uInt16 Count() const { return TextCharAttribs::size(); } >- >- TextCharAttrib* GetAttrib( sal_uInt16 n ) const { return TextCharAttribs::operator[]( n ); } >- void RemoveAttrib( sal_uInt16 n ) { TextCharAttribs::erase( begin() + n ); } >- >- void InsertAttrib( TextCharAttrib* pAttrib ); >- >- void DeleteEmptyAttribs(); >- void ResortAttribs(); >- >- sal_Bool HasEmptyAttribs() const { return mbHasEmptyAttribs; } >- sal_Bool& HasEmptyAttribs() { return mbHasEmptyAttribs; } >- >- TextCharAttrib* FindAttrib( sal_uInt16 nWhich, sal_uInt16 nPos ); >- TextCharAttrib* FindNextAttrib( sal_uInt16 nWhich, sal_uInt16 nFromPos, sal_uInt16 nMaxPos = 0xFFFF ) const; >- TextCharAttrib* FindEmptyAttrib( sal_uInt16 nWhich, sal_uInt16 nPos ); >- sal_Bool HasAttrib( sal_uInt16 nWhich ) const; >- sal_Bool HasBoundingAttrib( sal_uInt16 nBound ); >-}; >- >- >-class TextNode >-{ >-private: >- String maText; >- TextCharAttribList maCharAttribs; >- >- TextNode( const TextNode& ) {;} >-protected: >- void ExpandAttribs( sal_uInt16 nIndex, sal_uInt16 nNewChars ); >- void CollapsAttribs( sal_uInt16 nIndex, sal_uInt16 nDelChars ); >- >-public: >- TextNode( const String& rText ); >- >- >- const String& GetText() const { return maText; } >- >- const TextCharAttribList& GetCharAttribs() const { return maCharAttribs; } >- TextCharAttribList& GetCharAttribs() { return maCharAttribs; } >- >- void InsertText( sal_uInt16 nPos, const String& rText ); >- void InsertText( sal_uInt16 nPos, sal_Unicode c ); >- void RemoveText( sal_uInt16 nPos, sal_uInt16 nChars ); >- >- TextNode* Split( sal_uInt16 nPos, sal_Bool bKeepEndigAttribs ); >- void Append( const TextNode& rNode ); >-}; >- >-class TextDoc >-{ >-private: >- ToolsList<TextNode*> maTextNodes; >- sal_uInt16 mnLeftMargin; >- >-protected: >- void DestroyTextNodes(); >- >-public: >- TextDoc(); >- ~TextDoc(); >- >- void Clear(); >- >- ToolsList<TextNode*>& GetNodes() { return maTextNodes; } >- const ToolsList<TextNode*>& GetNodes() const { return maTextNodes; } >- >- TextPaM RemoveChars( const TextPaM& rPaM, sal_uInt16 nChars ); >- TextPaM InsertText( const TextPaM& rPaM, sal_Unicode c ); >- TextPaM InsertText( const TextPaM& rPaM, const String& rStr ); >- >- TextPaM InsertParaBreak( const TextPaM& rPaM, sal_Bool bKeepEndingAttribs ); >- TextPaM ConnectParagraphs( TextNode* pLeft, TextNode* pRight ); >- >- sal_uLong GetTextLen( const sal_Unicode* pSep, const TextSelection* pSel = NULL ) const; >- String GetText( const sal_Unicode* pSep ) const; >- String GetText( sal_uLong nPara ) const; >- >- void SetLeftMargin( sal_uInt16 n ) { mnLeftMargin = n; } >- sal_uInt16 GetLeftMargin() const { return mnLeftMargin; } >- >- sal_Bool IsValidPaM( const TextPaM& rPaM ); >-}; >- >-#endif // _TEXTDOC_HXX >- >-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/svtools/source/edit/texteng.cxx b/svtools/source/edit/texteng.cxx >deleted file mode 100644 >index efce793..0000000 >--- a/svtools/source/edit/texteng.cxx >+++ /dev/null >@@ -1,3205 +0,0 @@ >-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >-/************************************************************************* >- * >- * 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 <tools/stream.hxx> >- >-#include <svtools/texteng.hxx> >-#include <svtools/textview.hxx> >-#include <textdoc.hxx> >-#include <textdat2.hxx> >-#include <textundo.hxx> >-#include <textund2.hxx> >-#include <svl/ctloptions.hxx> >-#include <vcl/window.hxx> >- >-#include <vcl/edit.hxx> >-#include <com/sun/star/lang/XMultiServiceFactory.hpp> >-#include <com/sun/star/beans/PropertyValues.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 <com/sun/star/i18n/InputSequenceCheckMode.hpp> >-#include <com/sun/star/i18n/ScriptType.hpp> >- >-#include <comphelper/processfactory.hxx> >- >-#include <unotools/localedatawrapper.hxx> >-#include <vcl/unohelp.hxx> >- >-#include <vcl/svapp.hxx> >-#include <vcl/metric.hxx> >- >-#include <unicode/ubidi.h> >- >-#include <set> >-#include <vector> >-#include <boost/foreach.hpp> >- >-using namespace ::com::sun::star; >-using namespace ::com::sun::star::uno; >-using namespace ::rtl; >- >- >-// ------------------------------------------------------------------------- >-// (-) class TextEngine >-// ------------------------------------------------------------------------- >-TextEngine::TextEngine() >-{ >- mpDoc = 0; >- mpTEParaPortions = 0; >- >- mpViews = new TextViews; >- mpActiveView = NULL; >- >- mbIsFormatting = sal_False; >- mbFormatted = sal_False; >- mbUpdate = sal_True; >- mbModified = sal_False; >- mbUndoEnabled = sal_False; >- mbIsInUndo = sal_False; >- mbDowning = sal_False; >- mbRightToLeft = sal_False; >- mbHasMultiLineParas = sal_False; >- >- meAlign = TXTALIGN_LEFT; >- >- mnMaxTextWidth = 0; >- mnMaxTextLen = 0; >- mnCurTextWidth = 0xFFFFFFFF; >- mnCurTextHeight = 0; >- >- mpUndoManager = NULL; >- mpIMEInfos = NULL; >- mpLocaleDataWrapper = NULL; >- >- mpIdleFormatter = new IdleFormatter; >- mpIdleFormatter->SetTimeoutHdl( LINK( this, TextEngine, IdleFormatHdl ) ); >- >- mpRefDev = new VirtualDevice; >- >- ImpInitLayoutMode( mpRefDev ); >- >- ImpInitDoc(); >- >- maTextColor = COL_BLACK; >- Font aFont; >- aFont.SetTransparent( sal_False ); >- Color aFillColor( aFont.GetFillColor() ); >- aFillColor.SetTransparency( 0 ); >- aFont.SetFillColor( aFillColor ); >- SetFont( aFont ); >-} >- >-TextEngine::~TextEngine() >-{ >- mbDowning = sal_True; >- >- delete mpIdleFormatter; >- delete mpDoc; >- delete mpTEParaPortions; >- delete mpViews; // nur die Liste, nicht die Vies >- delete mpRefDev; >- delete mpUndoManager; >- delete mpIMEInfos; >- delete mpLocaleDataWrapper; >-} >- >-void TextEngine::InsertView( TextView* pTextView ) >-{ >- mpViews->push_back( pTextView ); >- pTextView->SetSelection( TextSelection() ); >- >- if ( !GetActiveView() ) >- SetActiveView( pTextView ); >-} >- >-void TextEngine::RemoveView( TextView* pTextView ) >-{ >- TextViews::iterator it = std::find( mpViews->begin(), mpViews->end(), pTextView ); >- if( it != mpViews->end() ) >- { >- pTextView->HideCursor(); >- mpViews->erase( it ); >- if ( pTextView == GetActiveView() ) >- SetActiveView( 0 ); >- } >-} >- >-sal_uInt16 TextEngine::GetViewCount() const >-{ >- return mpViews->size(); >-} >- >-TextView* TextEngine::GetView( sal_uInt16 nView ) const >-{ >- return (*mpViews)[ nView ]; >-} >- >-TextView* TextEngine::GetActiveView() const >-{ >- return mpActiveView; >-} >- >-void TextEngine::SetActiveView( TextView* pTextView ) >-{ >- if ( pTextView != mpActiveView ) >- { >- if ( mpActiveView ) >- mpActiveView->HideSelection(); >- >- mpActiveView = pTextView; >- >- if ( mpActiveView ) >- mpActiveView->ShowSelection(); >- } >-} >- >-void TextEngine::SetFont( const Font& rFont ) >-{ >- if ( rFont != maFont ) >- { >- maFont = rFont; >- // #i40221# As the font's color now defaults to transparent (since i35764) >- // we have to choose a useful textcolor in this case. >- // Otherwise maTextColor and maFont.GetColor() are both transparent.... >- if( rFont.GetColor() == COL_TRANSPARENT ) >- maTextColor = COL_BLACK; >- else >- maTextColor = rFont.GetColor(); >- >- // Wegen Selektion keinen Transparenten Font zulassen... >- // (Sonst spaeter in ImplPaint den Hintergrund anders loeschen...) >- maFont.SetTransparent( sal_False ); >- // Tell VCL not to use the font color, use text color from OutputDevice >- maFont.SetColor( COL_TRANSPARENT ); >- Color aFillColor( maFont.GetFillColor() ); >- aFillColor.SetTransparency( 0 ); >- maFont.SetFillColor( aFillColor ); >- >- maFont.SetAlign( ALIGN_TOP ); >- mpRefDev->SetFont( maFont); >- Size aTextSize; >- aTextSize.Width() = mpRefDev->GetTextWidth(rtl::OUString(" ")); >- aTextSize.Height() = mpRefDev->GetTextHeight(); >- if ( !aTextSize.Width() ) >- aTextSize.Width() = mpRefDev->GetTextWidth(rtl::OUString("XXXX")); >- >- mnDefTab = (sal_uInt16)aTextSize.Width(); >- if ( !mnDefTab ) >- mnDefTab = 1; >- mnCharHeight = (sal_uInt16)aTextSize.Height(); >- mnFixCharWidth100 = 0; >- >- FormatFullDoc(); >- UpdateViews(); >- >- for ( sal_uInt16 nView = mpViews->size(); nView; ) >- { >- TextView* pView = (*mpViews)[ --nView ]; >- pView->GetWindow()->SetInputContext( InputContext( GetFont(), !pView->IsReadOnly() ? INPUTCONTEXT_TEXT|INPUTCONTEXT_EXTTEXTINPUT : 0 ) ); >- } >- } >-} >- >-void TextEngine::SetMaxTextLen( sal_uLong nLen ) >-{ >- mnMaxTextLen = nLen; >-} >- >-void TextEngine::SetMaxTextWidth( sal_uLong nMaxWidth ) >-{ >- if ( nMaxWidth != mnMaxTextWidth ) >- { >- mnMaxTextWidth = Min( nMaxWidth, (sal_uLong)0x7FFFFFFF ); >- FormatFullDoc(); >- UpdateViews(); >- } >-} >- >-static sal_Unicode static_aLFText[] = { '\n', 0 }; >-static sal_Unicode static_aCRText[] = { '\r', 0 }; >-static sal_Unicode static_aCRLFText[] = { '\r', '\n', 0 }; >- >-static inline const sal_Unicode* static_getLineEndText( LineEnd aLineEnd ) >-{ >- const sal_Unicode* pRet = NULL; >- >- switch( aLineEnd ) >- { >- case LINEEND_LF: pRet = static_aLFText;break; >- case LINEEND_CR: pRet = static_aCRText;break; >- case LINEEND_CRLF: pRet = static_aCRLFText;break; >- } >- return pRet; >-} >- >-void TextEngine::ReplaceText(const TextSelection& rSel, const String& rText) >-{ >- ImpInsertText( rSel, rText ); >-} >- >-String TextEngine::GetText( LineEnd aSeparator ) const >-{ >- return mpDoc->GetText( static_getLineEndText( aSeparator ) ); >-} >- >-String TextEngine::GetTextLines( LineEnd aSeparator ) const >-{ >- String aText; >- sal_uLong nParas = mpTEParaPortions->Count(); >- const sal_Unicode* pSep = static_getLineEndText( aSeparator ); >- for ( sal_uLong nP = 0; nP < nParas; nP++ ) >- { >- TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nP ); >- >- sal_uInt16 nLines = pTEParaPortion->GetLines().size(); >- for ( sal_uInt16 nL = 0; nL < nLines; nL++ ) >- { >- TextLine* pLine = pTEParaPortion->GetLines()[nL]; >- aText += pTEParaPortion->GetNode()->GetText().Copy( pLine->GetStart(), pLine->GetEnd() - pLine->GetStart() ); >- if ( pSep && ( ( (nP+1) < nParas ) || ( (nL+1) < nLines ) ) ) >- aText += pSep; >- } >- } >- return aText; >-} >- >-String TextEngine::GetText( sal_uLong nPara ) const >-{ >- return mpDoc->GetText( nPara ); >-} >- >-sal_uLong TextEngine::GetTextLen( LineEnd aSeparator ) const >-{ >- return mpDoc->GetTextLen( static_getLineEndText( aSeparator ) ); >-} >- >-sal_uLong TextEngine::GetTextLen( const TextSelection& rSel, LineEnd aSeparator ) const >-{ >- TextSelection aSel( rSel ); >- aSel.Justify(); >- ValidateSelection( aSel ); >- return mpDoc->GetTextLen( static_getLineEndText( aSeparator ), &aSel ); >-} >- >-sal_uInt16 TextEngine::GetTextLen( sal_uLong nPara ) const >-{ >- return mpDoc->GetNodes().GetObject( nPara )->GetText().Len(); >-} >- >-void TextEngine::SetUpdateMode( sal_Bool bUpdate ) >-{ >- if ( bUpdate != mbUpdate ) >- { >- mbUpdate = bUpdate; >- if ( mbUpdate ) >- { >- FormatAndUpdate( GetActiveView() ); >- if ( GetActiveView() ) >- GetActiveView()->ShowCursor(); >- } >- } >-} >- >-sal_Bool TextEngine::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: >- { >- if ( !rKeyEvent.GetKeyCode().IsMod2() ) >- bDoesChange = sal_True; >- } >- break; >- case KEY_RETURN: >- case KEY_TAB: >- { >- if ( !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() ) >- bDoesChange = sal_True; >- } >- break; >- default: >- { >- bDoesChange = TextEngine::IsSimpleCharInput( rKeyEvent ); >- } >- } >- } >- return bDoesChange; >-} >- >-sal_Bool TextEngine::IsSimpleCharInput( const KeyEvent& rKeyEvent ) >-{ >- if( rKeyEvent.GetCharCode() >= 32 && rKeyEvent.GetCharCode() != 127 && >- KEY_MOD1 != (rKeyEvent.GetKeyCode().GetModifier() & ~KEY_SHIFT) && // (ssa) #i45714#: >- KEY_MOD2 != (rKeyEvent.GetKeyCode().GetModifier() & ~KEY_SHIFT) ) // check for Ctrl and Alt separately >- { >- return sal_True; >- } >- return sal_False; >-} >- >-void TextEngine::ImpInitDoc() >-{ >- if ( mpDoc ) >- mpDoc->Clear(); >- else >- mpDoc = new TextDoc; >- >- delete mpTEParaPortions; >- mpTEParaPortions = new TEParaPortions; >- >- TextNode* pNode = new TextNode( String() ); >- mpDoc->GetNodes().Insert( pNode, 0 ); >- >- TEParaPortion* pIniPortion = new TEParaPortion( pNode ); >- mpTEParaPortions->Insert( pIniPortion, (sal_uLong)0 ); >- >- mbFormatted = sal_False; >- >- ImpParagraphRemoved( TEXT_PARA_ALL ); >- ImpParagraphInserted( 0 ); >-} >- >-String TextEngine::GetText( const TextSelection& rSel, LineEnd aSeparator ) const >-{ >- String aText; >- >- if ( !rSel.HasRange() ) >- return aText; >- >- TextSelection aSel( rSel ); >- aSel.Justify(); >- >- sal_uLong nStartPara = aSel.GetStart().GetPara(); >- sal_uLong nEndPara = aSel.GetEnd().GetPara(); >- const sal_Unicode* pSep = static_getLineEndText( aSeparator ); >- for ( sal_uLong nNode = aSel.GetStart().GetPara(); nNode <= nEndPara; nNode++ ) >- { >- TextNode* pNode = mpDoc->GetNodes().GetObject( nNode ); >- >- sal_uInt16 nStartPos = 0; >- sal_uInt16 nEndPos = pNode->GetText().Len(); >- if ( nNode == nStartPara ) >- nStartPos = aSel.GetStart().GetIndex(); >- if ( nNode == nEndPara ) // kann auch == nStart sein! >- nEndPos = aSel.GetEnd().GetIndex(); >- >- aText += pNode->GetText().Copy( nStartPos, nEndPos-nStartPos ); >- if ( nNode < nEndPara ) >- aText += pSep; >- } >- return aText; >-} >- >-void TextEngine::ImpRemoveText() >-{ >- ImpInitDoc(); >- >- TextPaM aStartPaM( 0, 0 ); >- TextSelection aEmptySel( aStartPaM, aStartPaM ); >- for ( sal_uInt16 nView = 0; nView < mpViews->size(); nView++ ) >- { >- TextView* pView = (*mpViews)[ nView ]; >- pView->ImpSetSelection( aEmptySel ); >- } >- ResetUndo(); >-} >- >-void TextEngine::SetText( const XubString& rText ) >-{ >- ImpRemoveText(); >- >- sal_Bool bUndoCurrentlyEnabled = IsUndoEnabled(); >- // Der von Hand reingesteckte Text kann nicht vom Anwender rueckgaengig gemacht werden. >- EnableUndo( sal_False ); >- >- TextPaM aStartPaM( 0, 0 ); >- TextSelection aEmptySel( aStartPaM, aStartPaM ); >- >- TextPaM aPaM = aStartPaM; >- if ( rText.Len() ) >- aPaM = ImpInsertText( aEmptySel, rText ); >- >- for ( sal_uInt16 nView = 0; nView < mpViews->size(); nView++ ) >- { >- TextView* pView = (*mpViews)[ nView ]; >- pView->ImpSetSelection( aEmptySel ); >- >- // Wenn kein Text, dann auch Kein Format&Update >- // => Der Text bleibt stehen. >- if ( !rText.Len() && GetUpdateMode() ) >- pView->Invalidate(); >- } >- >- if( !rText.Len() ) // sonst muss spaeter noch invalidiert werden, !bFormatted reicht. >- mnCurTextHeight = 0; >- >- FormatAndUpdate(); >- >- EnableUndo( bUndoCurrentlyEnabled ); >- DBG_ASSERT( !HasUndoManager() || !GetUndoManager().GetUndoActionCount(), "Undo nach SetText?" ); >-} >- >- >-void TextEngine::CursorMoved( sal_uLong nNode ) >-{ >- // Leere Attribute loeschen, aber nur, wenn Absatz nicht leer! >- TextNode* pNode = mpDoc->GetNodes().GetObject( nNode ); >- if ( pNode && pNode->GetCharAttribs().HasEmptyAttribs() && pNode->GetText().Len() ) >- pNode->GetCharAttribs().DeleteEmptyAttribs(); >-} >- >-void TextEngine::ImpRemoveChars( const TextPaM& rPaM, sal_uInt16 nChars, SfxUndoAction* ) >-{ >- DBG_ASSERT( nChars, "ImpRemoveChars - 0 Chars?!" ); >- if ( IsUndoEnabled() && !IsInUndo() ) >- { >- // Attribute muessen hier vorm RemoveChars fuer UNDO gesichert werden! >- TextNode* pNode = mpDoc->GetNodes().GetObject( rPaM.GetPara() ); >- XubString aStr( pNode->GetText().Copy( rPaM.GetIndex(), nChars ) ); >- >- // Pruefen, ob Attribute geloescht oder geaendert werden: >- sal_uInt16 nStart = rPaM.GetIndex(); >- sal_uInt16 nEnd = nStart + nChars; >- for ( sal_uInt16 nAttr = pNode->GetCharAttribs().Count(); nAttr; ) >- { >- TextCharAttrib* pAttr = pNode->GetCharAttribs().GetAttrib( --nAttr ); >- if ( ( pAttr->GetEnd() >= nStart ) && ( pAttr->GetStart() < nEnd ) ) >- { >- break; // for >- } >- } >- InsertUndo( new TextUndoRemoveChars( this, rPaM, aStr ) ); >- } >- >- mpDoc->RemoveChars( rPaM, nChars ); >- ImpCharsRemoved( rPaM.GetPara(), rPaM.GetIndex(), nChars ); >-} >- >-TextPaM TextEngine::ImpConnectParagraphs( sal_uLong nLeft, sal_uLong nRight ) >-{ >- DBG_ASSERT( nLeft != nRight, "Den gleichen Absatz zusammenfuegen ?" ); >- >- TextNode* pLeft = mpDoc->GetNodes().GetObject( nLeft ); >- TextNode* pRight = mpDoc->GetNodes().GetObject( nRight ); >- >- if ( IsUndoEnabled() && !IsInUndo() ) >- InsertUndo( new TextUndoConnectParas( this, nLeft, pLeft->GetText().Len() ) ); >- >- // Erstmal Portions suchen, da pRight nach ConnectParagraphs weg. >- TEParaPortion* pLeftPortion = mpTEParaPortions->GetObject( nLeft ); >- TEParaPortion* pRightPortion = mpTEParaPortions->GetObject( nRight ); >- DBG_ASSERT( pLeft && pLeftPortion, "Blinde Portion in ImpConnectParagraphs(1)" ); >- DBG_ASSERT( pRight && pRightPortion, "Blinde Portion in ImpConnectParagraphs(2)" ); >- >- TextPaM aPaM = mpDoc->ConnectParagraphs( pLeft, pRight ); >- ImpParagraphRemoved( nRight ); >- >- pLeftPortion->MarkSelectionInvalid( aPaM.GetIndex(), pLeft->GetText().Len() ); >- >- mpTEParaPortions->Remove( nRight ); >- delete pRightPortion; >- // der rechte Node wird von EditDoc::ConnectParagraphs() geloescht. >- >- return aPaM; >-} >- >-TextPaM TextEngine::ImpDeleteText( const TextSelection& rSel ) >-{ >- if ( !rSel.HasRange() ) >- return rSel.GetStart(); >- >- TextSelection aSel( rSel ); >- aSel.Justify(); >- TextPaM aStartPaM( aSel.GetStart() ); >- TextPaM aEndPaM( aSel.GetEnd() ); >- >- CursorMoved( aStartPaM.GetPara() ); // nur damit neu eingestellte Attribute verschwinden... >- CursorMoved( aEndPaM.GetPara() ); // nur damit neu eingestellte Attribute verschwinden... >- >- DBG_ASSERT( mpDoc->IsValidPaM( aStartPaM ), "Index im Wald in ImpDeleteText" ); >- DBG_ASSERT( mpDoc->IsValidPaM( aEndPaM ), "Index im Wald in ImpDeleteText" ); >- >- sal_uLong nStartNode = aStartPaM.GetPara(); >- sal_uLong nEndNode = aEndPaM.GetPara(); >- >- // Alle Nodes dazwischen entfernen.... >- for ( sal_uLong z = nStartNode+1; z < nEndNode; z++ ) >- { >- // Immer nStartNode+1, wegen Remove()! >- ImpRemoveParagraph( nStartNode+1 ); >- } >- >- if ( nStartNode != nEndNode ) >- { >- // Den Rest des StartNodes... >- TextNode* pLeft = mpDoc->GetNodes().GetObject( nStartNode ); >- sal_uInt16 nChars = pLeft->GetText().Len() - aStartPaM.GetIndex(); >- if ( nChars ) >- { >- ImpRemoveChars( aStartPaM, nChars ); >- TEParaPortion* pPortion = mpTEParaPortions->GetObject( nStartNode ); >- DBG_ASSERT( pPortion, "Blinde Portion in ImpDeleteText(3)" ); >- pPortion->MarkSelectionInvalid( aStartPaM.GetIndex(), pLeft->GetText().Len() ); >- } >- >- // Den Anfang des EndNodes.... >- nEndNode = nStartNode+1; // Die anderen Absaetze wurden geloescht >- nChars = aEndPaM.GetIndex(); >- if ( nChars ) >- { >- aEndPaM.GetPara() = nEndNode; >- aEndPaM.GetIndex() = 0; >- ImpRemoveChars( aEndPaM, nChars ); >- TEParaPortion* pPortion = mpTEParaPortions->GetObject( nEndNode ); >- DBG_ASSERT( pPortion, "Blinde Portion in ImpDeleteText(4)" ); >- pPortion->MarkSelectionInvalid( 0, pPortion->GetNode()->GetText().Len() ); >- } >- >- // Zusammenfuegen.... >- aStartPaM = ImpConnectParagraphs( nStartNode, nEndNode ); >- } >- else >- { >- sal_uInt16 nChars; >- nChars = aEndPaM.GetIndex() - aStartPaM.GetIndex(); >- ImpRemoveChars( aStartPaM, nChars ); >- TEParaPortion* pPortion = mpTEParaPortions->GetObject( nStartNode ); >- DBG_ASSERT( pPortion, "Blinde Portion in ImpDeleteText(5)" ); >- pPortion->MarkInvalid( aEndPaM.GetIndex(), aStartPaM.GetIndex() - aEndPaM.GetIndex() ); >- } >- >-// UpdateSelections(); >- TextModified(); >- return aStartPaM; >-} >- >-void TextEngine::ImpRemoveParagraph( sal_uLong nPara ) >-{ >- TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >- TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPara ); >- >- // Der Node wird vom Undo verwaltet und ggf. zerstoert! >- /* delete */ mpDoc->GetNodes().Remove( nPara ); >- if ( IsUndoEnabled() && !IsInUndo() ) >- InsertUndo( new TextUndoDelPara( this, pNode, nPara ) ); >- else >- delete pNode; >- >- mpTEParaPortions->Remove( nPara ); >- delete pPortion; >- >- ImpParagraphRemoved( nPara ); >-} >- >-uno::Reference < i18n::XExtendedInputSequenceChecker > TextEngine::GetInputSequenceChecker() const >-{ >- uno::Reference < i18n::XExtendedInputSequenceChecker > xISC; >-// if ( !xISC.is() ) >- { >- uno::Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory(); >- uno::Reference< uno::XInterface > xI = xMSF->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.InputSequenceChecker" )) ); >- if ( xI.is() ) >- { >- Any x = xI->queryInterface( ::getCppuType((const uno::Reference< i18n::XExtendedInputSequenceChecker >*)0) ); >- x >>= xISC; >- } >- } >- return xISC; >-} >- >-sal_Bool TextEngine::IsInputSequenceCheckingRequired( sal_Unicode c, const TextSelection& rCurSel ) const >-{ >- uno::Reference< i18n::XBreakIterator > xBI = ((TextEngine *) this)->GetBreakIterator(); >- SvtCTLOptions aCTLOptions; >- >- // get the index that really is first >- sal_uInt16 nFirstPos = rCurSel.GetStart().GetIndex(); >- sal_uInt16 nMaxPos = rCurSel.GetEnd().GetIndex(); >- if (nMaxPos < nFirstPos) >- nFirstPos = nMaxPos; >- >- sal_Bool bIsSequenceChecking = >- aCTLOptions.IsCTLFontEnabled() && >- aCTLOptions.IsCTLSequenceChecking() && >- nFirstPos != 0 && /* first char needs not to be checked */ >- xBI.is() && i18n::ScriptType::COMPLEX == xBI->getScriptType( rtl::OUString( c ), 0 ); >- >- return bIsSequenceChecking; >-} >- >-TextPaM TextEngine::ImpInsertText( const TextSelection& rCurSel, sal_Unicode c, sal_Bool bOverwrite ) >-{ >- return ImpInsertText( c, rCurSel, bOverwrite, sal_False ); >-} >- >-TextPaM TextEngine::ImpInsertText( sal_Unicode c, const TextSelection& rCurSel, sal_Bool bOverwrite, sal_Bool bIsUserInput ) >-{ >- DBG_ASSERT( c != '\n', "Zeilenumbruch bei InsertText ?" ); >- DBG_ASSERT( c != '\r', "Zeilenumbruch bei InsertText ?" ); >- >- TextPaM aPaM( rCurSel.GetStart() ); >- TextNode* pNode = mpDoc->GetNodes().GetObject( aPaM.GetPara() ); >- >- if ( pNode->GetText().Len() < STRING_MAXLEN ) >- { >- sal_Bool bDoOverwrite = ( bOverwrite && >- ( aPaM.GetIndex() < pNode->GetText().Len() ) ) ? sal_True : sal_False; >- >- sal_Bool bUndoAction = ( rCurSel.HasRange() || bDoOverwrite ); >- >- if ( bUndoAction ) >- UndoActionStart(); >- >- if ( rCurSel.HasRange() ) >- { >- aPaM = ImpDeleteText( rCurSel ); >- } >- else if ( bDoOverwrite ) >- { >- // Wenn Selektion, dann kein Zeichen ueberschreiben >- TextSelection aTmpSel( aPaM ); >- aTmpSel.GetEnd().GetIndex()++; >- ImpDeleteText( aTmpSel ); >- } >- >- if (bIsUserInput && IsInputSequenceCheckingRequired( c, rCurSel )) >- { >- uno::Reference < i18n::XExtendedInputSequenceChecker > xISC = GetInputSequenceChecker(); >- SvtCTLOptions aCTLOptions; >- >- if (xISC.is()) >- { >- xub_StrLen nTmpPos = aPaM.GetIndex(); >- sal_Int16 nCheckMode = aCTLOptions.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( mpDoc->GetText( aPaM.GetPara() ).Copy(0, nTmpPos) ); >- rtl::OUString aNewText( aOldText ); >- if (aCTLOptions.IsCTLSequenceCheckingTypeAndReplace()) >- { >- 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; >- >- String aChgText( aNewText.copy( nChgPos ) ); >- >- // select text from first pos to be changed to current pos >- TextSelection aSel( TextPaM( aPaM.GetPara(), (sal_uInt16) nChgPos ), aPaM ); >- >- if (aChgText.Len()) >- // ImpInsertText implicitly handles undo... >- return ImpInsertText( aSel, aChgText ); >- 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() ) >- { >- TextUndoInsertChars* pNewUndo = new TextUndoInsertChars( this, aPaM, rtl::OUString(c) ); >- sal_Bool bTryMerge = ( !bDoOverwrite && ( c != ' ' ) ) ? sal_True : sal_False; >- InsertUndo( pNewUndo, bTryMerge ); >- } >- >- TEParaPortion* pPortion = mpTEParaPortions->GetObject( aPaM.GetPara() ); >- pPortion->MarkInvalid( aPaM.GetIndex(), 1 ); >- if ( c == '\t' ) >- pPortion->SetNotSimpleInvalid(); >- aPaM = mpDoc->InsertText( aPaM, c ); >- ImpCharsInserted( aPaM.GetPara(), aPaM.GetIndex()-1, 1 ); >- >- TextModified(); >- >- if ( bUndoAction ) >- UndoActionEnd(); >- } >- >- return aPaM; >-} >- >- >-TextPaM TextEngine::ImpInsertText( const TextSelection& rCurSel, const XubString& rStr ) >-{ >- UndoActionStart(); >- >- TextPaM aPaM; >- >- if ( rCurSel.HasRange() ) >- aPaM = ImpDeleteText( rCurSel ); >- else >- aPaM = rCurSel.GetEnd(); >- >- XubString aText(convertLineEnd(rStr, LINEEND_LF)); >- >- sal_uInt16 nStart = 0; >- while ( nStart < aText.Len() ) >- { >- sal_uInt16 nEnd = aText.Search( LINE_SEP, nStart ); >- if ( nEnd == STRING_NOTFOUND ) >- nEnd = aText.Len(); // nicht dereferenzieren! >- >- // Start == End => Leerzeile >- if ( nEnd > nStart ) >- { >- sal_uLong nL = aPaM.GetIndex(); >- nL += ( nEnd-nStart ); >- if ( nL > STRING_MAXLEN ) >- { >- sal_uInt16 nDiff = (sal_uInt16) (nL-STRING_MAXLEN); >- nEnd = nEnd - nDiff; >- } >- >- XubString aLine( aText, nStart, nEnd-nStart ); >- if ( IsUndoEnabled() && !IsInUndo() ) >- InsertUndo( new TextUndoInsertChars( this, aPaM, aLine ) ); >- >- TEParaPortion* pPortion = mpTEParaPortions->GetObject( aPaM.GetPara() ); >- pPortion->MarkInvalid( aPaM.GetIndex(), aLine.Len() ); >- if ( aLine.Search( '\t' ) != STRING_NOTFOUND ) >- pPortion->SetNotSimpleInvalid(); >- >- aPaM = mpDoc->InsertText( aPaM, aLine ); >- ImpCharsInserted( aPaM.GetPara(), aPaM.GetIndex()-aLine.Len(), aLine.Len() ); >- >- } >- if ( nEnd < aText.Len() ) >- aPaM = ImpInsertParaBreak( aPaM ); >- >- nStart = nEnd+1; >- >- if ( nStart < nEnd ) // #108611# overflow >- break; >- } >- >- UndoActionEnd(); >- >- TextModified(); >- return aPaM; >-} >- >-TextPaM TextEngine::ImpInsertParaBreak( const TextSelection& rCurSel, sal_Bool bKeepEndingAttribs ) >-{ >- TextPaM aPaM; >- if ( rCurSel.HasRange() ) >- aPaM = ImpDeleteText( rCurSel ); >- else >- aPaM = rCurSel.GetEnd(); >- >- return ImpInsertParaBreak( aPaM, bKeepEndingAttribs ); >-} >- >-TextPaM TextEngine::ImpInsertParaBreak( const TextPaM& rPaM, sal_Bool bKeepEndingAttribs ) >-{ >- if ( IsUndoEnabled() && !IsInUndo() ) >- InsertUndo( new TextUndoSplitPara( this, rPaM.GetPara(), rPaM.GetIndex() ) ); >- >- TextNode* pNode = mpDoc->GetNodes().GetObject( rPaM.GetPara() ); >- sal_Bool bFirstParaContentChanged = rPaM.GetIndex() < pNode->GetText().Len(); >- >- TextPaM aPaM( mpDoc->InsertParaBreak( rPaM, bKeepEndingAttribs ) ); >- >- TEParaPortion* pPortion = mpTEParaPortions->GetObject( rPaM.GetPara() ); >- DBG_ASSERT( pPortion, "Blinde Portion in ImpInsertParaBreak" ); >- pPortion->MarkInvalid( rPaM.GetIndex(), 0 ); >- >- TextNode* pNewNode = mpDoc->GetNodes().GetObject( aPaM.GetPara() ); >- TEParaPortion* pNewPortion = new TEParaPortion( pNewNode ); >- mpTEParaPortions->Insert( pNewPortion, aPaM.GetPara() ); >- ImpParagraphInserted( aPaM.GetPara() ); >- >- CursorMoved( rPaM.GetPara() ); // falls leeres Attribut entstanden. >- TextModified(); >- >- if ( bFirstParaContentChanged ) >- Broadcast( TextHint( TEXT_HINT_PARACONTENTCHANGED, rPaM.GetPara() ) ); >- >- return aPaM; >-} >- >-Rectangle TextEngine::PaMtoEditCursor( const TextPaM& rPaM, sal_Bool bSpecial ) >-{ >- DBG_ASSERT( GetUpdateMode(), "Darf bei Update=sal_False nicht erreicht werden: PaMtoEditCursor" ); >- >- Rectangle aEditCursor; >- long nY = 0; >- >- if ( !mbHasMultiLineParas ) >- { >- nY = rPaM.GetPara() * mnCharHeight; >- } >- else >- { >- for ( sal_uLong nPortion = 0; nPortion < rPaM.GetPara(); nPortion++ ) >- { >- TEParaPortion* pPortion = mpTEParaPortions->GetObject(nPortion); >- nY += pPortion->GetLines().size() * mnCharHeight; >- } >- } >- >- aEditCursor = GetEditCursor( rPaM, bSpecial ); >- aEditCursor.Top() += nY; >- aEditCursor.Bottom() += nY; >- return aEditCursor; >-} >- >-Rectangle TextEngine::GetEditCursor( const TextPaM& rPaM, sal_Bool bSpecial, sal_Bool bPreferPortionStart ) >-{ >- if ( !IsFormatted() && !IsFormatting() ) >- FormatAndUpdate(); >- >- TEParaPortion* pPortion = mpTEParaPortions->GetObject( rPaM.GetPara() ); >- //TextNode* pNode = mpDoc->GetNodes().GetObject( rPaM.GetPara() ); >- >- /* >- bSpecial: 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.... >- bSpecial: If behind the last character of a made up line, stay at the >- end of the line, not at the start of the next line. >- Purpose: - really END = > behind the last character >- - to selection... >- >- */ >- >- long nY = 0; >- sal_uInt16 nCurIndex = 0; >- TextLine* pLine = 0; >- for ( sal_uInt16 nLine = 0; nLine < pPortion->GetLines().size(); nLine++ ) >- { >- TextLine* pTmpLine = pPortion->GetLines()[ nLine ]; >- if ( ( pTmpLine->GetStart() == rPaM.GetIndex() ) || ( pTmpLine->IsIn( rPaM.GetIndex(), bSpecial ) ) ) >- { >- pLine = pTmpLine; >- break; >- } >- >- nCurIndex = nCurIndex + pTmpLine->GetLen(); >- nY += mnCharHeight; >- } >- if ( !pLine ) >- { >- // Cursor am Ende des Absatzes. >- DBG_ASSERT( rPaM.GetIndex() == nCurIndex, "Index voll daneben in GetEditCursor!" ); >- >- pLine = pPortion->GetLines().back(); >- nY -= mnCharHeight; >- nCurIndex = nCurIndex - pLine->GetLen(); >- } >- >- Rectangle aEditCursor; >- >- aEditCursor.Top() = nY; >- nY += mnCharHeight; >- aEditCursor.Bottom() = nY-1; >- >- // innerhalb der Zeile suchen.... >- long nX = ImpGetXPos( rPaM.GetPara(), pLine, rPaM.GetIndex(), bPreferPortionStart ); >- aEditCursor.Left() = aEditCursor.Right() = nX; >- return aEditCursor; >-} >- >-long TextEngine::ImpGetXPos( sal_uLong nPara, TextLine* pLine, sal_uInt16 nIndex, sal_Bool bPreferPortionStart ) >-{ >- DBG_ASSERT( ( nIndex >= pLine->GetStart() ) && ( nIndex <= pLine->GetEnd() ) , "ImpGetXPos muss richtig gerufen werden!" ); >- >- sal_Bool bDoPreferPortionStart = bPreferPortionStart; >- // Assure that the portion belongs to this line: >- if ( nIndex == pLine->GetStart() ) >- bDoPreferPortionStart = sal_True; >- else if ( nIndex == pLine->GetEnd() ) >- bDoPreferPortionStart = sal_False; >- >- TEParaPortion* pParaPortion = mpTEParaPortions->GetObject( nPara ); >- >- sal_uInt16 nTextPortionStart = 0; >- size_t nTextPortion = pParaPortion->GetTextPortions().FindPortion( nIndex, nTextPortionStart, bDoPreferPortionStart ); >- >- DBG_ASSERT( ( nTextPortion >= pLine->GetStartPortion() ) && ( nTextPortion <= pLine->GetEndPortion() ), "GetXPos: Portion not in current line! " ); >- >- TETextPortion* pPortion = pParaPortion->GetTextPortions()[ nTextPortion ]; >- >- long nX = ImpGetPortionXOffset( nPara, pLine, nTextPortion ); >- >- long nPortionTextWidth = pPortion->GetWidth(); >- >- if ( nTextPortionStart != nIndex ) >- { >- // Search within portion... >- if ( nIndex == ( nTextPortionStart + pPortion->GetLen() ) ) >- { >- // End of Portion >- if ( ( pPortion->GetKind() == PORTIONKIND_TAB ) || >- ( !IsRightToLeft() && !pPortion->IsRightToLeft() ) || >- ( IsRightToLeft() && pPortion->IsRightToLeft() ) ) >- { >- nX += nPortionTextWidth; >- if ( ( pPortion->GetKind() == PORTIONKIND_TAB ) && ( (nTextPortion+1) < pParaPortion->GetTextPortions().size() ) ) >- { >- TETextPortion* pNextPortion = pParaPortion->GetTextPortions()[ nTextPortion+1 ]; >- if ( ( pNextPortion->GetKind() != PORTIONKIND_TAB ) && ( >- ( !IsRightToLeft() && pNextPortion->IsRightToLeft() ) || >- ( IsRightToLeft() && !pNextPortion->IsRightToLeft() ) ) ) >- { >-// nX += pNextPortion->GetWidth(); >- // End of the tab portion, use start of next for cursor pos >- DBG_ASSERT( !bPreferPortionStart, "ImpGetXPos - How can we this tab portion here???" ); >- nX = ImpGetXPos( nPara, pLine, nIndex, sal_True ); >- } >- >- } >- } >- } >- else if ( pPortion->GetKind() == PORTIONKIND_TEXT ) >- { >- DBG_ASSERT( nIndex != pLine->GetStart(), "Strange behavior in new ImpGetXPos()" ); >- >- long nPosInPortion = (long)CalcTextWidth( nPara, nTextPortionStart, nIndex-nTextPortionStart ); >- >- if ( ( !IsRightToLeft() && !pPortion->IsRightToLeft() ) || >- ( IsRightToLeft() && pPortion->IsRightToLeft() ) ) >- { >- nX += nPosInPortion; >- } >- else >- { >- nX += nPortionTextWidth - nPosInPortion; >- } >- } >- } >- else // if ( nIndex == pLine->GetStart() ) >- { >- if ( ( pPortion->GetKind() != PORTIONKIND_TAB ) && >- ( ( !IsRightToLeft() && pPortion->IsRightToLeft() ) || >- ( IsRightToLeft() && !pPortion->IsRightToLeft() ) ) ) >- { >- nX += nPortionTextWidth; >- } >- } >- >- return nX; >-} >- >-const TextAttrib* TextEngine::FindAttrib( const TextPaM& rPaM, sal_uInt16 nWhich ) const >-{ >- const TextAttrib* pAttr = NULL; >- const TextCharAttrib* pCharAttr = FindCharAttrib( rPaM, nWhich ); >- if ( pCharAttr ) >- pAttr = &pCharAttr->GetAttr(); >- return pAttr; >-} >- >-const TextCharAttrib* TextEngine::FindCharAttrib( const TextPaM& rPaM, sal_uInt16 nWhich ) const >-{ >- const TextCharAttrib* pAttr = NULL; >- TextNode* pNode = mpDoc->GetNodes().GetObject( rPaM.GetPara() ); >- if ( pNode && ( rPaM.GetIndex() < pNode->GetText().Len() ) ) >- pAttr = pNode->GetCharAttribs().FindAttrib( nWhich, rPaM.GetIndex() ); >- return pAttr; >-} >- >-sal_Bool TextEngine::HasAttrib( sal_uInt16 nWhich ) const >-{ >- sal_Bool bAttr = sal_False; >- for ( sal_uLong n = mpDoc->GetNodes().Count(); --n && !bAttr; ) >- { >- TextNode* pNode = mpDoc->GetNodes().GetObject( n ); >- bAttr = pNode->GetCharAttribs().HasAttrib( nWhich ); >- } >- return bAttr; >-} >- >-TextPaM TextEngine::GetPaM( const Point& rDocPos, sal_Bool bSmart ) >-{ >- DBG_ASSERT( GetUpdateMode(), "Darf bei Update=sal_False nicht erreicht werden: GetPaM" ); >- >- long nY = 0; >- for ( sal_uLong nPortion = 0; nPortion < mpTEParaPortions->Count(); nPortion++ ) >- { >- TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPortion ); >- long nTmpHeight = pPortion->GetLines().size() * mnCharHeight; >- nY += nTmpHeight; >- if ( nY > rDocPos.Y() ) >- { >- nY -= nTmpHeight; >- Point aPosInPara( rDocPos ); >- aPosInPara.Y() -= nY; >- >- TextPaM aPaM( nPortion, 0 ); >- aPaM.GetIndex() = ImpFindIndex( nPortion, aPosInPara, bSmart ); >- return aPaM; >- } >- } >- >- // Nicht gefunden - Dann den letzten sichtbare... >- sal_uLong nLastNode = mpDoc->GetNodes().Count() - 1; >- TextNode* pLast = mpDoc->GetNodes().GetObject( nLastNode ); >- return TextPaM( nLastNode, pLast->GetText().Len() ); >-} >- >-sal_uInt16 TextEngine::ImpFindIndex( sal_uLong nPortion, const Point& rPosInPara, sal_Bool bSmart ) >-{ >- DBG_ASSERT( IsFormatted(), "GetPaM: Nicht formatiert" ); >- TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPortion ); >- >- sal_uInt16 nCurIndex = 0; >- >- long nY = 0; >- TextLine* pLine = 0; >- sal_uInt16 nLine; >- for ( nLine = 0; nLine < pPortion->GetLines().size(); nLine++ ) >- { >- TextLine* pTmpLine = pPortion->GetLines()[ nLine ]; >- nY += mnCharHeight; >- if ( nY > rPosInPara.Y() ) // das war 'se >- { >- pLine = pTmpLine; >- break; // richtige Y-Position intressiert nicht >- } >- } >- DBG_ASSERT( pLine, "ImpFindIndex: pLine ?" ); >- >- nCurIndex = GetCharPos( nPortion, nLine, rPosInPara.X(), bSmart ); >- >- if ( nCurIndex && ( nCurIndex == pLine->GetEnd() ) && >- ( pLine != pPortion->GetLines().back() ) ) >- { >- uno::Reference < i18n::XBreakIterator > xBI = GetBreakIterator(); >- sal_Int32 nCount = 1; >- nCurIndex = (sal_uInt16)xBI->previousCharacters( pPortion->GetNode()->GetText(), nCurIndex, GetLocale(), i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount ); >- } >- return nCurIndex; >-} >- >-sal_uInt16 TextEngine::GetCharPos( sal_uLong nPortion, sal_uInt16 nLine, long nXPos, sal_Bool ) >-{ >- >- TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPortion ); >- TextLine* pLine = pPortion->GetLines()[ nLine ]; >- >- sal_uInt16 nCurIndex = pLine->GetStart(); >- >- long nTmpX = pLine->GetStartX(); >- if ( nXPos <= nTmpX ) >- return nCurIndex; >- >- for ( sal_uInt16 i = pLine->GetStartPortion(); i <= pLine->GetEndPortion(); i++ ) >- { >- TETextPortion* pTextPortion = pPortion->GetTextPortions()[ i ]; >- nTmpX += pTextPortion->GetWidth(); >- >- if ( nTmpX > nXPos ) >- { >- if( pTextPortion->GetLen() > 1 ) >- { >- nTmpX -= pTextPortion->GetWidth(); // vor die Portion stellen >- // Optimieren: Kein GetTextBreak, wenn feste Fontbreite... >- Font aFont; >- SeekCursor( nPortion, nCurIndex+1, aFont, NULL ); >- mpRefDev->SetFont( aFont); >- long nPosInPortion = nXPos-nTmpX; >- if ( IsRightToLeft() != pTextPortion->IsRightToLeft() ) >- nPosInPortion = pTextPortion->GetWidth() - nPosInPortion; >- nCurIndex = mpRefDev->GetTextBreak( pPortion->GetNode()->GetText(), nPosInPortion, nCurIndex ); >- // MT: GetTextBreak should assure that we are not withing a CTL cell... >- } >- return nCurIndex; >- } >- nCurIndex = nCurIndex + pTextPortion->GetLen(); >- } >- return nCurIndex; >-} >- >- >-sal_uLong TextEngine::GetTextHeight() const >-{ >- DBG_ASSERT( GetUpdateMode(), "Sollte bei Update=sal_False nicht verwendet werden: GetTextHeight" ); >- >- if ( !IsFormatted() && !IsFormatting() ) >- ((TextEngine*)this)->FormatAndUpdate(); >- >- return mnCurTextHeight; >-} >- >-sal_uLong TextEngine::GetTextHeight( sal_uLong nParagraph ) const >-{ >- DBG_ASSERT( GetUpdateMode(), "Sollte bei Update=sal_False nicht verwendet werden: GetTextHeight" ); >- >- if ( !IsFormatted() && !IsFormatting() ) >- ((TextEngine*)this)->FormatAndUpdate(); >- >- return CalcParaHeight( nParagraph ); >-} >- >-sal_uLong TextEngine::CalcTextWidth( sal_uLong nPara ) >-{ >- sal_uLong nParaWidth = 0; >- TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPara ); >- for ( sal_uInt16 nLine = pPortion->GetLines().size(); nLine; ) >- { >- sal_uLong nLineWidth = 0; >- TextLine* pLine = pPortion->GetLines()[ --nLine ]; >- for ( sal_uInt16 nTP = pLine->GetStartPortion(); nTP <= pLine->GetEndPortion(); nTP++ ) >- { >- TETextPortion* pTextPortion = pPortion->GetTextPortions()[ nTP ]; >- nLineWidth += pTextPortion->GetWidth(); >- } >- if ( nLineWidth > nParaWidth ) >- nParaWidth = nLineWidth; >- } >- return nParaWidth; >-} >- >-sal_uLong TextEngine::CalcTextWidth() >-{ >- if ( !IsFormatted() && !IsFormatting() ) >- FormatAndUpdate(); >- >- if ( mnCurTextWidth == 0xFFFFFFFF ) >- { >- mnCurTextWidth = 0; >- for ( sal_uLong nPara = mpTEParaPortions->Count(); nPara; ) >- { >- sal_uLong nParaWidth = CalcTextWidth( --nPara ); >- if ( nParaWidth > mnCurTextWidth ) >- mnCurTextWidth = nParaWidth; >- } >- } >- return mnCurTextWidth+1;// Ein breiter, da in CreateLines bei >= umgebrochen wird. >-} >- >-sal_uLong TextEngine::CalcTextHeight() >-{ >- DBG_ASSERT( GetUpdateMode(), "Sollte bei Update=sal_False nicht verwendet werden: CalcTextHeight" ); >- >- sal_uLong nY = 0; >- for ( sal_uLong nPortion = mpTEParaPortions->Count(); nPortion; ) >- nY += CalcParaHeight( --nPortion ); >- return nY; >-} >- >-sal_uLong TextEngine::CalcTextWidth( sal_uLong nPara, sal_uInt16 nPortionStart, sal_uInt16 nLen, const Font* pFont ) >-{ >- // Innerhalb des Textes darf es keinen Portionwechsel (Attribut/Tab) geben! >- DBG_ASSERT( mpDoc->GetNodes().GetObject( nPara )->GetText().Search( '\t', nPortionStart ) >= (nPortionStart+nLen), "CalcTextWidth: Tab!" ); >- >- sal_uLong nWidth; >- if ( mnFixCharWidth100 ) >- { >- nWidth = (sal_uLong)nLen*mnFixCharWidth100/100; >- } >- else >- { >- if ( pFont ) >- { >- if ( !mpRefDev->GetFont().IsSameInstance( *pFont ) ) >- mpRefDev->SetFont( *pFont ); >- } >- else >- { >- Font aFont; >- SeekCursor( nPara, nPortionStart+1, aFont, NULL ); >- mpRefDev->SetFont( aFont ); >- } >- TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >- nWidth = (sal_uLong)mpRefDev->GetTextWidth( pNode->GetText(), nPortionStart, nLen ); >- >- } >- return nWidth; >-} >- >- >-sal_uInt16 TextEngine::GetLineCount( sal_uLong nParagraph ) const >-{ >- DBG_ASSERT( nParagraph < mpTEParaPortions->Count(), "GetLineCount: Out of range" ); >- >- TEParaPortion* pPPortion = mpTEParaPortions->GetObject( nParagraph ); >- if ( pPPortion ) >- return pPPortion->GetLines().size(); >- >- return 0xFFFF; >-} >- >-sal_uInt16 TextEngine::GetLineLen( sal_uLong nParagraph, sal_uInt16 nLine ) const >-{ >- DBG_ASSERT( nParagraph < mpTEParaPortions->Count(), "GetLineCount: Out of range" ); >- >- TEParaPortion* pPPortion = mpTEParaPortions->GetObject( nParagraph ); >- if ( pPPortion && ( nLine < pPPortion->GetLines().size() ) ) >- { >- TextLine* pLine = pPPortion->GetLines()[ nLine ]; >- return pLine->GetLen(); >- } >- >- return 0xFFFF; >-} >- >-sal_uLong TextEngine::CalcParaHeight( sal_uLong nParagraph ) const >-{ >- sal_uLong nHeight = 0; >- >- TEParaPortion* pPPortion = mpTEParaPortions->GetObject( nParagraph ); >- DBG_ASSERT( pPPortion, "Absatz nicht gefunden: GetParaHeight" ); >- if ( pPPortion ) >- nHeight = pPPortion->GetLines().size() * mnCharHeight; >- >- return nHeight; >-} >- >-void TextEngine::UpdateSelections() >-{ >-} >- >-Range TextEngine::GetInvalidYOffsets( sal_uLong nPortion ) >-{ >- TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPortion ); >- sal_uInt16 nLines = pTEParaPortion->GetLines().size(); >- sal_uInt16 nLastInvalid, nFirstInvalid = 0; >- sal_uInt16 nLine; >- for ( nLine = 0; nLine < nLines; nLine++ ) >- { >- TextLine* pL = pTEParaPortion->GetLines()[ nLine ]; >- if ( pL->IsInvalid() ) >- { >- nFirstInvalid = nLine; >- break; >- } >- } >- >- for ( nLastInvalid = nFirstInvalid; nLastInvalid < nLines; nLastInvalid++ ) >- { >- TextLine* pL = pTEParaPortion->GetLines()[ nLine ]; >- if ( pL->IsValid() ) >- break; >- } >- >- if ( nLastInvalid >= nLines ) >- nLastInvalid = nLines-1; >- >- return Range( nFirstInvalid*mnCharHeight, ((nLastInvalid+1)*mnCharHeight)-1 ); >-} >- >-sal_uLong TextEngine::GetParagraphCount() const >-{ >- return mpDoc->GetNodes().Count(); >-} >- >-void TextEngine::EnableUndo( sal_Bool bEnable ) >-{ >- // Beim Umschalten des Modus Liste loeschen: >- if ( bEnable != IsUndoEnabled() ) >- ResetUndo(); >- >- mbUndoEnabled = bEnable; >-} >- >-::svl::IUndoManager& TextEngine::GetUndoManager() >-{ >- if ( !mpUndoManager ) >- mpUndoManager = new TextUndoManager( this ); >- return *mpUndoManager; >-} >- >-void TextEngine::UndoActionStart( sal_uInt16 nId ) >-{ >- if ( IsUndoEnabled() && !IsInUndo() ) >- { >- String aComment; >- // ... >- GetUndoManager().EnterListAction( aComment, XubString(), nId ); >- } >-} >- >-void TextEngine::UndoActionEnd() >-{ >- if ( IsUndoEnabled() && !IsInUndo() ) >- GetUndoManager().LeaveListAction(); >-} >- >-void TextEngine::InsertUndo( TextUndo* pUndo, sal_Bool bTryMerge ) >-{ >- DBG_ASSERT( !IsInUndo(), "InsertUndo im Undomodus!" ); >- GetUndoManager().AddUndoAction( pUndo, bTryMerge ); >-} >- >-void TextEngine::ResetUndo() >-{ >- if ( mpUndoManager ) >- mpUndoManager->Clear(); >-} >- >-void TextEngine::InsertContent( TextNode* pNode, sal_uLong nPara ) >-{ >- DBG_ASSERT( pNode, "NULL-Pointer in InsertContent! " ); >- DBG_ASSERT( IsInUndo(), "InsertContent nur fuer Undo()!" ); >- TEParaPortion* pNew = new TEParaPortion( pNode ); >- mpTEParaPortions->Insert( pNew, nPara ); >- mpDoc->GetNodes().Insert( pNode, nPara ); >- ImpParagraphInserted( nPara ); >-} >- >-TextPaM TextEngine::SplitContent( sal_uLong nNode, sal_uInt16 nSepPos ) >-{ >- #ifdef DBG_UTIL >- TextNode* pNode = mpDoc->GetNodes().GetObject( nNode ); >- DBG_ASSERT( pNode, "Ungueltiger Node in SplitContent" ); >- DBG_ASSERT( IsInUndo(), "SplitContent nur fuer Undo()!" ); >- DBG_ASSERT( nSepPos <= pNode->GetText().Len(), "Index im Wald: SplitContent" ); >- #endif >- TextPaM aPaM( nNode, nSepPos ); >- return ImpInsertParaBreak( aPaM ); >-} >- >-TextPaM TextEngine::ConnectContents( sal_uLong nLeftNode ) >-{ >- DBG_ASSERT( IsInUndo(), "ConnectContent nur fuer Undo()!" ); >- return ImpConnectParagraphs( nLeftNode, nLeftNode+1 ); >-} >- >-void TextEngine::SeekCursor( sal_uLong nPara, sal_uInt16 nPos, Font& rFont, OutputDevice* pOutDev ) >-{ >- rFont = maFont; >- if ( pOutDev ) >- pOutDev->SetTextColor( maTextColor ); >- >- TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >- sal_uInt16 nAttribs = pNode->GetCharAttribs().Count(); >- for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ ) >- { >- TextCharAttrib* pAttrib = pNode->GetCharAttribs().GetAttrib( nAttr ); >- if ( pAttrib->GetStart() > nPos ) >- break; >- >- // 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->GetStart() < nPos ) && ( pAttrib->GetEnd() >= nPos ) ) >- || !pNode->GetText().Len() ) >- { >- if ( pAttrib->Which() != TEXTATTR_FONTCOLOR ) >- { >- pAttrib->GetAttr().SetFont(rFont); >- } >- else >- { >- if ( pOutDev ) >- pOutDev->SetTextColor( ((TextAttribFontColor&)pAttrib->GetAttr()).GetColor() ); >- } >- } >- } >- >- if ( mpIMEInfos && mpIMEInfos->pAttribs && ( mpIMEInfos->aPos.GetPara() == nPara ) && >- ( 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 ); >- 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( sal_False ); >- } >- else if ( nAttr & EXTTEXTINPUT_ATTR_GRAYWAVELINE ) >- { >- rFont.SetUnderline( UNDERLINE_WAVE ); >-// if( pOut ) >-// pOut->SetTextLineColor( Color( COL_LIGHTGRAY ) ); >- } >- } >-} >- >-void TextEngine::FormatAndUpdate( TextView* pCurView ) >-{ >- if ( mbDowning ) >- return ; >- >- if ( IsInUndo() ) >- IdleFormatAndUpdate( pCurView ); >- else >- { >- FormatDoc(); >- UpdateViews( pCurView ); >- } >-} >- >- >-void TextEngine::IdleFormatAndUpdate( TextView* pCurView, sal_uInt16 nMaxTimerRestarts ) >-{ >- mpIdleFormatter->DoIdleFormat( pCurView, nMaxTimerRestarts ); >-} >- >-void TextEngine::TextModified() >-{ >- mbFormatted = sal_False; >- mbModified = sal_True; >-} >- >-void TextEngine::UpdateViews( TextView* pCurView ) >-{ >- if ( !GetUpdateMode() || IsFormatting() || maInvalidRec.IsEmpty() ) >- return; >- >- DBG_ASSERT( IsFormatted(), "UpdateViews: Doc nicht formatiert!" ); >- >- for ( sal_uInt16 nView = 0; nView < mpViews->size(); nView++ ) >- { >- TextView* pView = (*mpViews)[ nView ]; >- pView->HideCursor(); >- >- Rectangle aClipRec( maInvalidRec ); >- Size aOutSz = pView->GetWindow()->GetOutputSizePixel(); >- Rectangle aVisArea( pView->GetStartDocPos(), aOutSz ); >- aClipRec.Intersection( aVisArea ); >- if ( !aClipRec.IsEmpty() ) >- { >- // in Fensterkoordinaten umwandeln.... >- Point aNewPos = pView->GetWindowPos( aClipRec.TopLeft() ); >- if ( IsRightToLeft() ) >- aNewPos.X() -= aOutSz.Width() - 1; >- aClipRec.SetPos( aNewPos ); >- >- if ( pView == pCurView ) >- pView->ImpPaint( aClipRec, !pView->GetWindow()->IsPaintTransparent() ); >- else >- pView->GetWindow()->Invalidate( aClipRec ); >- } >- } >- >- if ( pCurView ) >- { >- pCurView->ShowCursor( pCurView->IsAutoScroll() ); >- } >- >- maInvalidRec = Rectangle(); >-} >- >-IMPL_LINK_NOARG(TextEngine, IdleFormatHdl) >-{ >- FormatAndUpdate( mpIdleFormatter->GetView() ); >- return 0; >-} >- >-void TextEngine::CheckIdleFormatter() >-{ >- mpIdleFormatter->ForceTimeout(); >-} >- >-void TextEngine::FormatFullDoc() >-{ >- for ( sal_uLong nPortion = 0; nPortion < mpTEParaPortions->Count(); nPortion++ ) >- { >- TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPortion ); sal_uInt16 nLen = pTEParaPortion->GetNode()->GetText().Len(); >- pTEParaPortion->MarkSelectionInvalid( 0, nLen ); >- } >- mbFormatted = sal_False; >- FormatDoc(); >-} >- >-void TextEngine::FormatDoc() >-{ >- if ( IsFormatted() || !GetUpdateMode() || IsFormatting() ) >- return; >- >- mbIsFormatting = sal_True; >- mbHasMultiLineParas = sal_False; >- >- long nY = 0; >- sal_Bool bGrow = sal_False; >- >- maInvalidRec = Rectangle(); // leermachen >- for ( sal_uLong nPara = 0; nPara < mpTEParaPortions->Count(); nPara++ ) >- { >- TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >- if ( pTEParaPortion->IsInvalid() ) >- { >- sal_uLong nOldParaWidth = 0xFFFFFFFF; >- if ( mnCurTextWidth != 0xFFFFFFFF ) >- nOldParaWidth = CalcTextWidth( nPara ); >- >- ImpFormattingParagraph( nPara ); >- >- if ( CreateLines( nPara ) ) >- bGrow = sal_True; >- >- // InvalidRec nur einmal setzen... >- if ( maInvalidRec.IsEmpty() ) >- { >- // Bei Paperwidth 0 (AutoPageSize) bleibt es sonst Empty()... >- long nWidth = (long)mnMaxTextWidth; >- if ( !nWidth ) >- nWidth = 0x7FFFFFFF; >- Range aInvRange( GetInvalidYOffsets( nPara ) ); >- maInvalidRec = Rectangle( Point( 0, nY+aInvRange.Min() ), >- Size( nWidth, aInvRange.Len() ) ); >- } >- else >- { >- maInvalidRec.Bottom() = nY + CalcParaHeight( nPara ); >- } >- >- if ( mnCurTextWidth != 0xFFFFFFFF ) >- { >- sal_uLong nNewParaWidth = CalcTextWidth( nPara ); >- if ( nNewParaWidth >= mnCurTextWidth ) >- mnCurTextWidth = nNewParaWidth; >- else if ( ( nOldParaWidth != 0xFFFFFFFF ) && ( nOldParaWidth >= mnCurTextWidth ) ) >- mnCurTextWidth = 0xFFFFFFFF; >- } >- } >- else if ( bGrow ) >- { >- maInvalidRec.Bottom() = nY + CalcParaHeight( nPara ); >- } >- nY += CalcParaHeight( nPara ); >- if ( !mbHasMultiLineParas && pTEParaPortion->GetLines().size() > 1 ) >- mbHasMultiLineParas = sal_True; >- } >- >- if ( !maInvalidRec.IsEmpty() ) >- { >- sal_uLong nNewHeight = CalcTextHeight(); >- long nDiff = nNewHeight - mnCurTextHeight; >- if ( nNewHeight < mnCurTextHeight ) >- { >- maInvalidRec.Bottom() = (long)Max( nNewHeight, mnCurTextHeight ); >- if ( maInvalidRec.IsEmpty() ) >- { >- maInvalidRec.Top() = 0; >- // Left und Right werden nicht ausgewertet, aber wegen IsEmpty gesetzt. >- maInvalidRec.Left() = 0; >- maInvalidRec.Right() = mnMaxTextWidth; >- } >- } >- >- mnCurTextHeight = nNewHeight; >- if ( nDiff ) >- { >- mbFormatted = sal_True; >- ImpTextHeightChanged(); >- } >- } >- >- mbIsFormatting = sal_False; >- mbFormatted = sal_True; >- >- ImpTextFormatted(); >-} >- >-void TextEngine::CreateAndInsertEmptyLine( sal_uLong nPara ) >-{ >- TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >- TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >- >- TextLine* pTmpLine = new TextLine; >- pTmpLine->SetStart( pNode->GetText().Len() ); >- pTmpLine->SetEnd( pTmpLine->GetStart() ); >- pTEParaPortion->GetLines().push_back( pTmpLine ); >- >- if ( ImpGetAlign() == TXTALIGN_CENTER ) >- pTmpLine->SetStartX( (short)(mnMaxTextWidth / 2) ); >- else if ( ImpGetAlign() == TXTALIGN_RIGHT ) >- pTmpLine->SetStartX( (short)mnMaxTextWidth ); >- else >- pTmpLine->SetStartX( mpDoc->GetLeftMargin() ); >- >- sal_Bool bLineBreak = pNode->GetText().Len() ? sal_True : sal_False; >- >- TETextPortion* pDummyPortion = new TETextPortion( 0 ); >- pDummyPortion->GetWidth() = 0; >- pTEParaPortion->GetTextPortions().push_back( pDummyPortion ); >- >- if ( bLineBreak == sal_True ) >- { >- // -2: The new one is already inserted. >- OSL_ENSURE( >- pTEParaPortion->GetLines()[pTEParaPortion->GetLines().size()-2], >- "Soft Break, no Line?!"); >- sal_uInt16 nPos = (sal_uInt16) pTEParaPortion->GetTextPortions().size() - 1 ; >- pTmpLine->SetStartPortion( nPos ); >- pTmpLine->SetEndPortion( nPos ); >- } >-} >- >-void TextEngine::ImpBreakLine( sal_uLong nPara, TextLine* pLine, TETextPortion*, sal_uInt16 nPortionStart, long nRemainingWidth ) >-{ >- TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >- >- // Font sollte noch eingestellt sein. >- sal_uInt16 nMaxBreakPos = mpRefDev->GetTextBreak( pNode->GetText(), nRemainingWidth, nPortionStart ); >- >- DBG_ASSERT( nMaxBreakPos < pNode->GetText().Len(), "Break?!" ); >- >- if ( nMaxBreakPos == STRING_LEN ) // GetTextBreak() ist anderer Auffassung als GetTextSize() >- nMaxBreakPos = pNode->GetText().Len() - 1; >- >- uno::Reference < i18n::XBreakIterator > xBI = GetBreakIterator(); >- i18n::LineBreakHyphenationOptions aHyphOptions( NULL, uno::Sequence< beans::PropertyValue >(), 1 ); >- >- i18n::LineBreakUserOptions aUserOptions; >- aUserOptions.forbiddenBeginCharacters = ImpGetLocaleDataWrapper()->getForbiddenCharacters().beginLine; >- aUserOptions.forbiddenEndCharacters = ImpGetLocaleDataWrapper()->getForbiddenCharacters().endLine; >- aUserOptions.applyForbiddenRules = sal_True; >- aUserOptions.allowPunctuationOutsideMargin = sal_False; >- aUserOptions.allowHyphenateEnglish = sal_False; >- >- static const com::sun::star::lang::Locale aDefLocale; >- i18n::LineBreakResults aLBR = xBI->getLineBreak( pNode->GetText(), nMaxBreakPos, aDefLocale, pLine->GetStart(), aHyphOptions, aUserOptions ); >- sal_uInt16 nBreakPos = (sal_uInt16)aLBR.breakIndex; >- if ( nBreakPos <= pLine->GetStart() ) >- { >- nBreakPos = nMaxBreakPos; >- if ( nBreakPos <= pLine->GetStart() ) >- nBreakPos = pLine->GetStart() + 1; // Sonst Endlosschleife! >- } >- >- >- // die angeknackste Portion ist die End-Portion >- pLine->SetEnd( nBreakPos ); >- sal_uInt16 nEndPortion = SplitTextPortion( nPara, nBreakPos ); >- >- sal_Bool bBlankSeparator = ( ( nBreakPos >= pLine->GetStart() ) && >- ( pNode->GetText().GetChar( nBreakPos ) == ' ' ) ) ? sal_True : sal_False; >- if ( bBlankSeparator ) >- { >- // Blanks am Zeilenende generell unterdruecken... >- TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >- TETextPortion* pTP = pTEParaPortion->GetTextPortions()[ nEndPortion ]; >- DBG_ASSERT( nBreakPos > pLine->GetStart(), "SplitTextPortion am Anfang der Zeile?" ); >- pTP->GetWidth() = (long)CalcTextWidth( nPara, nBreakPos-pTP->GetLen(), pTP->GetLen()-1 ); >- } >- pLine->SetEndPortion( nEndPortion ); >-} >- >-sal_uInt16 TextEngine::SplitTextPortion( sal_uLong nPara, sal_uInt16 nPos ) >-{ >- >- // 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; >- TETextPortion* pTextPortion = 0; >- TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >- sal_uInt16 nPortions = pTEParaPortion->GetTextPortions().size(); >- for ( nSplitPortion = 0; nSplitPortion < nPortions; nSplitPortion++ ) >- { >- TETextPortion* pTP = pTEParaPortion->GetTextPortions()[nSplitPortion]; >- nTmpPos = nTmpPos + pTP->GetLen(); >- if ( nTmpPos >= nPos ) >- { >- if ( nTmpPos == nPos ) // dann braucht nichts geteilt werden >- return nSplitPortion; >- pTextPortion = pTP; >- break; >- } >- } >- >- DBG_ASSERT( pTextPortion, "Position ausserhalb des Bereichs!" ); >- >- sal_uInt16 nOverlapp = nTmpPos - nPos; >- pTextPortion->GetLen() = pTextPortion->GetLen() - nOverlapp; >- TETextPortion* pNewPortion = new TETextPortion( nOverlapp ); >- pTEParaPortion->GetTextPortions().insert( pTEParaPortion->GetTextPortions().begin() + nSplitPortion + 1, pNewPortion ); >- pTextPortion->GetWidth() = (long)CalcTextWidth( nPara, nPos-pTextPortion->GetLen(), pTextPortion->GetLen() ); >- >- return nSplitPortion; >-} >- >-void TextEngine::CreateTextPortions( sal_uLong nPara, sal_uInt16 nStartPos ) >-{ >- TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >- TextNode* pNode = pTEParaPortion->GetNode(); >- DBG_ASSERT( pNode->GetText().Len(), "CreateTextPortions sollte nicht fuer leere Absaetze verwendet werden!" ); >- >- std::set<sal_uInt16> aPositions; >- std::set<sal_uInt16>::iterator aPositionsIt; >- aPositions.insert(0); >- >- sal_uInt16 nAttribs = pNode->GetCharAttribs().Count(); >- for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ ) >- { >- TextCharAttrib* pAttrib = pNode->GetCharAttribs().GetAttrib( nAttr ); >- >- aPositions.insert( pAttrib->GetStart() ); >- aPositions.insert( pAttrib->GetEnd() ); >- } >- aPositions.insert( pNode->GetText().Len() ); >- >- const std::vector<TEWritingDirectionInfo>& rWritingDirections = pTEParaPortion->GetWritingDirectionInfos(); >- for ( std::vector<TEWritingDirectionInfo>::const_iterator it = rWritingDirections.begin(); it != rWritingDirections.end(); ++it ) >- aPositions.insert( (*it).nStartPos ); >- >- if ( mpIMEInfos && mpIMEInfos->pAttribs && ( mpIMEInfos->aPos.GetPara() == nPara ) ) >- { >- 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]; >- } >- } >- } >- >- sal_uInt16 nTabPos = pNode->GetText().Search( '\t', 0 ); >- while ( nTabPos != STRING_NOTFOUND ) >- { >- aPositions.insert( nTabPos ); >- aPositions.insert( nTabPos + 1 ); >- nTabPos = pNode->GetText().Search( '\t', nTabPos+1 ); >- } >- >- // 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 < pTEParaPortion->GetTextPortions().size(); nP++ ) >- { >- TETextPortion* pTmpPortion = pTEParaPortion->GetTextPortions()[nP]; >- nPortionStart = nPortionStart + pTmpPortion->GetLen(); >- if ( nPortionStart >= nStartPos ) >- { >- nPortionStart = nPortionStart - pTmpPortion->GetLen(); >- nInvPortion = nP; >- break; >- } >- } >- OSL_ENSURE(nP < pTEParaPortion->GetTextPortions().size() >- || pTEParaPortion->GetTextPortions().empty(), >- "Nothing to delete: CreateTextPortions"); >- if ( nInvPortion && ( nPortionStart+pTEParaPortion->GetTextPortions()[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 - pTEParaPortion->GetTextPortions()[nInvPortion]->GetLen(); >- } >- pTEParaPortion->GetTextPortions().DeleteFromPortion( nInvPortion ); >- >- // Eine Portion kann auch durch einen Zeilenumbruch entstanden sein: >- aPositions.insert( nPortionStart ); >- >- aPositionsIt = aPositions.find( nPortionStart ); >- DBG_ASSERT( aPositionsIt != aPositions.end(), "nPortionStart not found" ); >- >- if ( aPositionsIt != aPositions.end() ) >- { >- std::set<sal_uInt16>::iterator nextIt = aPositionsIt; >- for ( ++nextIt; nextIt != aPositions.end(); ++aPositionsIt, ++nextIt ) >- { >- TETextPortion* pNew = new TETextPortion( *nextIt - *aPositionsIt ); >- pTEParaPortion->GetTextPortions().push_back( pNew ); >- } >- } >- OSL_ENSURE(pTEParaPortion->GetTextPortions().size(), "No Portions?!"); >-} >- >-void TextEngine::RecalcTextPortion( sal_uLong nPara, sal_uInt16 nStartPos, short nNewChars ) >-{ >- TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >- OSL_ENSURE(pTEParaPortion->GetTextPortions().size(), "no Portions!"); >- OSL_ENSURE(nNewChars, "RecalcTextPortion with Diff == 0"); >- >- TextNode* const pNode = pTEParaPortion->GetNode(); >- if ( nNewChars > 0 ) >- { >- // Wenn an nStartPos ein Attribut beginnt/endet, oder vor nStartPos >- // ein Tab steht, faengt eine neue Portion an, >- // ansonsten wird die Portion an nStartPos erweitert. >- // Oder wenn ganz vorne ( StartPos 0 ) und dann ein Tab >- >- if ( ( pNode->GetCharAttribs().HasBoundingAttrib( nStartPos ) ) || >- ( nStartPos && ( pNode->GetText().GetChar( nStartPos - 1 ) == '\t' ) ) || >- ( ( !nStartPos && ( nNewChars < pNode->GetText().Len() ) && pNode->GetText().GetChar( nNewChars ) == '\t' ) ) ) >- { >- sal_uInt16 nNewPortionPos = 0; >- if ( nStartPos ) >- nNewPortionPos = SplitTextPortion( nPara, nStartPos ) + 1; >- >- // Eine leere Portion kann hier stehen, wenn der Absatz leer war, >- // oder eine Zeile durch einen harten Zeilenumbruch entstanden ist. >- if ( ( nNewPortionPos < pTEParaPortion->GetTextPortions().size() ) && >- !pTEParaPortion->GetTextPortions()[nNewPortionPos]->GetLen() ) >- { >- // Dann die leere Portion verwenden. >- sal_uInt16 & r = >- pTEParaPortion->GetTextPortions()[nNewPortionPos]->GetLen(); >- r = r + nNewChars; >- } >- else >- { >- TETextPortion* pNewPortion = new TETextPortion( nNewChars ); >- pTEParaPortion->GetTextPortions().insert( pTEParaPortion->GetTextPortions().begin() + nNewPortionPos, pNewPortion ); >- } >- } >- else >- { >- sal_uInt16 nPortionStart; >- const sal_uInt16 nTP = pTEParaPortion->GetTextPortions(). >- FindPortion( nStartPos, nPortionStart ); >- TETextPortion* const pTP = pTEParaPortion->GetTextPortions()[ nTP ]; >- DBG_ASSERT( pTP, "RecalcTextPortion: Portion nicht gefunden" ); >- pTP->GetLen() = pTP->GetLen() + nNewChars; >- pTP->GetWidth() = (-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 = pTEParaPortion->GetTextPortions().size(); >- TETextPortion* pTP = 0; >- for ( nPortion = 0; nPortion < nPortions; nPortion++ ) >- { >- pTP = pTEParaPortion->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; >- pTEParaPortion->GetTextPortions().erase( pTEParaPortion->GetTextPortions().begin() + nPortion ); >- delete pTP; >- } >- else >- { >- DBG_ASSERT( pTP->GetLen() > (-nNewChars), "Portion zu klein zum schrumpfen!" ); >- pTP->GetLen() = pTP->GetLen() + nNewChars; >- } >- OSL_ENSURE( pTEParaPortion->GetTextPortions().size(), >- "RecalcTextPortions: none are left!" ); >- } >-} >- >-void TextEngine::ImpPaint( OutputDevice* pOutDev, const Point& rStartPos, Rectangle const* pPaintArea, TextSelection const* pPaintRange, TextSelection const* pSelection ) >-{ >- if ( !GetUpdateMode() ) >- return; >- >- if ( !IsFormatted() ) >- FormatDoc(); >- >- bool bTransparent = false; >- Window* pOutWin = dynamic_cast<Window*>(pOutDev); >- bTransparent = (pOutWin && pOutWin->IsPaintTransparent()); >- >- long nY = rStartPos.Y(); >- >- TextPaM const* pSelStart = 0; >- TextPaM const* pSelEnd = 0; >- if ( pSelection && pSelection->HasRange() ) >- { >- sal_Bool bInvers = pSelection->GetEnd() < pSelection->GetStart(); >- pSelStart = !bInvers ? &pSelection->GetStart() : &pSelection->GetEnd(); >- pSelEnd = bInvers ? &pSelection->GetStart() : &pSelection->GetEnd(); >- } >- DBG_ASSERT( !pPaintRange || ( pPaintRange->GetStart() < pPaintRange->GetEnd() ), "ImpPaint: Paint-Range?!" ); >- >- const StyleSettings& rStyleSettings = pOutDev->GetSettings().GetStyleSettings(); >- >- // -------------------------------------------------- >- // Ueber alle Absaetze... >- // -------------------------------------------------- >- for ( sal_uLong nPara = 0; nPara < mpTEParaPortions->Count(); nPara++ ) >- { >- TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPara ); >- // falls beim Tippen Idle-Formatierung, asynchrones Paint. >- if ( pPortion->IsInvalid() ) >- return; >- >- sal_uLong nParaHeight = CalcParaHeight( nPara ); >- if ( ( !pPaintArea || ( ( nY + (long)nParaHeight ) > pPaintArea->Top() ) ) >- && ( !pPaintRange || ( ( nPara >= pPaintRange->GetStart().GetPara() ) && ( nPara <= pPaintRange->GetEnd().GetPara() ) ) ) ) >- { >- // -------------------------------------------------- >- // Ueber die Zeilen des Absatzes... >- // -------------------------------------------------- >- sal_uInt16 nLines = pPortion->GetLines().size(); >- sal_uInt16 nIndex = 0; >- for ( sal_uInt16 nLine = 0; nLine < nLines; nLine++ ) >- { >- TextLine* pLine = pPortion->GetLines()[nLine]; >- Point aTmpPos( rStartPos.X() + pLine->GetStartX(), nY ); >- >- if ( ( !pPaintArea || ( ( nY + mnCharHeight ) > pPaintArea->Top() ) ) >- && ( !pPaintRange || ( >- ( TextPaM( nPara, pLine->GetStart() ) < pPaintRange->GetEnd() ) && >- ( TextPaM( nPara, pLine->GetEnd() ) > pPaintRange->GetStart() ) ) ) ) >- { >- // -------------------------------------------------- >- // Ueber die Portions der Zeile... >- // -------------------------------------------------- >- nIndex = pLine->GetStart(); >- for ( sal_uInt16 y = pLine->GetStartPortion(); y <= pLine->GetEndPortion(); y++ ) >- { >- OSL_ENSURE(pPortion->GetTextPortions().size(), >- "Line without Textportion in Paint!"); >- TETextPortion* pTextPortion = pPortion->GetTextPortions()[ y ]; >- DBG_ASSERT( pTextPortion, "NULL-Pointer im Portioniterator in UpdateViews" ); >- >- ImpInitLayoutMode( pOutDev /*, pTextPortion->IsRightToLeft() */); >- >- long nTxtWidth = pTextPortion->GetWidth(); >- aTmpPos.X() = rStartPos.X() + ImpGetOutputOffset( nPara, pLine, nIndex, nIndex ); >- >- // nur ausgeben, was im sichtbaren Bereich beginnt: >- if ( ( ( aTmpPos.X() + nTxtWidth ) >= 0 ) >- && ( !pPaintRange || ( >- ( TextPaM( nPara, nIndex ) < pPaintRange->GetEnd() ) && >- ( TextPaM( nPara, nIndex + pTextPortion->GetLen() ) > pPaintRange->GetStart() ) ) ) ) >- { >- switch ( pTextPortion->GetKind() ) >- { >- case PORTIONKIND_TEXT: >- { >- { >- Font aFont; >- SeekCursor( nPara, nIndex+1, aFont, pOutDev ); >- if( bTransparent ) >- aFont.SetTransparent( sal_True ); >- else if ( pSelection ) >- aFont.SetTransparent( sal_False ); >- pOutDev->SetFont( aFont ); >- >- sal_uInt16 nTmpIndex = nIndex; >- sal_uInt16 nEnd = nTmpIndex + pTextPortion->GetLen(); >- Point aPos = aTmpPos; >- if ( pPaintRange ) >- { >- // evtl soll nicht alles ausgegeben werden... >- if ( ( pPaintRange->GetStart().GetPara() == nPara ) >- && ( nTmpIndex < pPaintRange->GetStart().GetIndex() ) ) >- { >- nTmpIndex = pPaintRange->GetStart().GetIndex(); >- } >- if ( ( pPaintRange->GetEnd().GetPara() == nPara ) >- && ( nEnd > pPaintRange->GetEnd().GetIndex() ) ) >- { >- nEnd = pPaintRange->GetEnd().GetIndex(); >- } >- } >- >- sal_Bool bDone = sal_False; >- if ( pSelStart ) >- { >- // liegt ein Teil in der Selektion??? >- TextPaM aTextStart( nPara, nTmpIndex ); >- TextPaM aTextEnd( nPara, nEnd ); >- if ( ( aTextStart < *pSelEnd ) && ( aTextEnd > *pSelStart ) ) >- { >- sal_uInt16 nL; >- >- // 1) Bereich vor Selektion >- if ( aTextStart < *pSelStart ) >- { >- nL = pSelStart->GetIndex() - nTmpIndex; >- pOutDev->SetFont( aFont); >- aPos.X() = rStartPos.X() + ImpGetOutputOffset( nPara, pLine, nTmpIndex, nTmpIndex+nL ); >- pOutDev->DrawText( aPos, pPortion->GetNode()->GetText(), nTmpIndex, nL ); >- nTmpIndex = nTmpIndex + nL; >- >- } >- // 2) Bereich mit Selektion >- nL = nEnd-nTmpIndex; >- if ( aTextEnd > *pSelEnd ) >- nL = pSelEnd->GetIndex() - nTmpIndex; >- if ( nL ) >- { >- Color aOldTextColor = pOutDev->GetTextColor(); >- pOutDev->SetTextColor( rStyleSettings.GetHighlightTextColor() ); >- pOutDev->SetTextFillColor( rStyleSettings.GetHighlightColor() ); >- aPos.X() = rStartPos.X() + ImpGetOutputOffset( nPara, pLine, nTmpIndex, nTmpIndex+nL ); >- pOutDev->DrawText( aPos, pPortion->GetNode()->GetText(), nTmpIndex, nL ); >- pOutDev->SetTextColor( aOldTextColor ); >- pOutDev->SetTextFillColor(); >- nTmpIndex = nTmpIndex + nL; >- } >- >- // 3) Bereich nach Selektion >- if ( nTmpIndex < nEnd ) >- { >- nL = nEnd-nTmpIndex; >- aPos.X() = rStartPos.X() + ImpGetOutputOffset( nPara, pLine, nTmpIndex, nTmpIndex+nL ); >- pOutDev->DrawText( aPos, pPortion->GetNode()->GetText(), nTmpIndex, nEnd-nTmpIndex ); >- } >- bDone = sal_True; >- } >- } >- if ( !bDone ) >- { >- aPos.X() = rStartPos.X() + ImpGetOutputOffset( nPara, pLine, nTmpIndex, nEnd ); >- pOutDev->DrawText( aPos, pPortion->GetNode()->GetText(), nTmpIndex, nEnd-nTmpIndex ); >- } >- } >- >- } >- break; >- case PORTIONKIND_TAB: >- { >- // Bei HideSelection() nur Range, pSelection = 0. >- if ( pSelStart || pPaintRange ) >- { >- Rectangle aTabArea( aTmpPos, Point( aTmpPos.X()+nTxtWidth, aTmpPos.Y()+mnCharHeight-1 ) ); >- sal_Bool bDone = sal_False; >- if ( pSelStart ) >- { >- // liegt der Tab in der Selektion??? >- TextPaM aTextStart( nPara, nIndex ); >- TextPaM aTextEnd( nPara, nIndex+1 ); >- if ( ( aTextStart < *pSelEnd ) && ( aTextEnd > *pSelStart ) ) >- { >- Color aOldColor = pOutDev->GetFillColor(); >- pOutDev->SetFillColor( rStyleSettings.GetHighlightColor() ); >- pOutDev->DrawRect( aTabArea ); >- pOutDev->SetFillColor( aOldColor ); >- bDone = sal_True; >- } >- } >- if ( !bDone ) >- { >- pOutDev->Erase( aTabArea ); >- } >- } >- } >- break; >- default: OSL_FAIL( "ImpPaint: Unknown Portion-Type !" ); >- } >- } >- >- nIndex = nIndex + pTextPortion->GetLen(); >- } >- } >- >- nY += mnCharHeight; >- >- if ( pPaintArea && ( nY >= pPaintArea->Bottom() ) ) >- break; // keine sichtbaren Aktionen mehr... >- } >- } >- else >- { >- nY += nParaHeight; >- } >- >- if ( pPaintArea && ( nY > pPaintArea->Bottom() ) ) >- break; // keine sichtbaren Aktionen mehr... >- } >-} >- >-sal_Bool TextEngine::CreateLines( sal_uLong nPara ) >-{ >- // sal_Bool: Aenderung der Hoehe des Absatzes Ja/Nein - sal_True/sal_False >- >- TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >- TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >- DBG_ASSERT( pTEParaPortion->IsInvalid(), "CreateLines: Portion nicht invalid!" ); >- >- sal_uInt16 nOldLineCount = pTEParaPortion->GetLines().size(); >- >- // --------------------------------------------------------------- >- // Schnelle Sonderbehandlung fuer leere Absaetze... >- // --------------------------------------------------------------- >- if ( pTEParaPortion->GetNode()->GetText().Len() == 0 ) >- { >- // schnelle Sonderbehandlung... >- if ( !pTEParaPortion->GetTextPortions().empty() ) >- pTEParaPortion->GetTextPortions().Reset(); >- if ( !pTEParaPortion->GetLines().empty() ) >- { >- BOOST_FOREACH(TextLine* pLine, pTEParaPortion->GetLines()) >- delete pLine; >- pTEParaPortion->GetLines().clear(); >- } >- CreateAndInsertEmptyLine( nPara ); >- pTEParaPortion->SetValid(); >- return nOldLineCount != pTEParaPortion->GetLines().size(); >- } >- >- // --------------------------------------------------------------- >- // Initialisierung...... >- // --------------------------------------------------------------- >- >- if ( pTEParaPortion->GetLines().empty() ) >- { >- TextLine* pL = new TextLine; >- pTEParaPortion->GetLines().push_back( pL ); >- } >- >- const short nInvalidDiff = pTEParaPortion->GetInvalidDiff(); >- const sal_uInt16 nInvalidStart = pTEParaPortion->GetInvalidPosStart(); >- const sal_uInt16 nInvalidEnd = nInvalidStart + Abs( nInvalidDiff ); >- sal_Bool bQuickFormat = sal_False; >- >- if ( pTEParaPortion->GetWritingDirectionInfos().empty() ) >- ImpInitWritingDirections( nPara ); >- >- if ( pTEParaPortion->GetWritingDirectionInfos().size() == 1 ) >- { >- if ( pTEParaPortion->IsSimpleInvalid() && ( nInvalidDiff > 0 ) ) >- { >- bQuickFormat = sal_True; >- } >- else if ( ( pTEParaPortion->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 = pTEParaPortion->GetTextPortions().size(); >- for ( sal_uInt16 nTP = 0; nTP < nPortions; nTP++ ) >- { >- // Es darf kein Start/Ende im geloeschten Bereich liegen. >- TETextPortion* const pTP = pTEParaPortion->GetTextPortions()[ nTP ]; >- nPos = nPos + pTP->GetLen(); >- if ( ( nPos > nStart ) && ( nPos < nEnd ) ) >- { >- bQuickFormat = sal_False; >- break; >- } >- } >- } >- } >- >- if ( bQuickFormat ) >- RecalcTextPortion( nPara, nInvalidStart, nInvalidDiff ); >- else >- CreateTextPortions( nPara, nInvalidStart ); >- >- // --------------------------------------------------------------- >- // Zeile mit InvalidPos suchen, eine Zeile davor beginnen... >- // Zeilen flaggen => nicht removen ! >- // --------------------------------------------------------------- >- >- sal_uInt16 nLine = pTEParaPortion->GetLines().size()-1; >- for ( sal_uInt16 nL = 0; nL <= nLine; nL++ ) >- { >- TextLine* pLine = pTEParaPortion->GetLines()[ nL ]; >- if ( pLine->GetEnd() > nInvalidStart ) >- { >- nLine = nL; >- break; >- } >- pLine->SetValid(); >- } >- // Eine Zeile davor beginnen... >- // Wenn ganz hinten getippt wird, kann sich die Zeile davor nicht aendern. >- if ( nLine && ( !pTEParaPortion->IsSimpleInvalid() || ( nInvalidEnd < pNode->GetText().Len() ) || ( nInvalidDiff <= 0 ) ) ) >- nLine--; >- >- TextLine* pLine = pTEParaPortion->GetLines()[ nLine ]; >- >- // --------------------------------------------------------------- >- // Ab hier alle Zeilen durchformatieren... >- // --------------------------------------------------------------- >- size_t nDelFromLine = std::numeric_limits<size_t>::max(); >- sal_Bool bLineBreak = sal_False; >- >- sal_uInt16 nIndex = pLine->GetStart(); >- TextLine aSaveLine( *pLine ); >- >- Font aFont; >- >- sal_Bool bCalcPortion = sal_True; >- >- while ( nIndex < pNode->GetText().Len() ) >- { >- sal_Bool bEOL = sal_False; >- sal_uInt16 nPortionStart = 0; >- sal_uInt16 nPortionEnd = 0; >- >- sal_uInt16 nTmpPos = nIndex; >- sal_uInt16 nTmpPortion = pLine->GetStartPortion(); >- long nTmpWidth = mpDoc->GetLeftMargin(); >-// long nXWidth = mnMaxTextWidth ? ( mnMaxTextWidth - mpDoc->GetLeftMargin() ) : 0x7FFFFFFF; >- // Margin nicht abziehen, ist schon in TmpWidth enthalten. >- long nXWidth = mnMaxTextWidth ? mnMaxTextWidth : 0x7FFFFFFF; >- if ( nXWidth < nTmpWidth ) >- nXWidth = nTmpWidth; >- >- // Portion suchen, die nicht mehr in Zeile passt.... >- TETextPortion* pPortion = 0; >- sal_Bool bBrokenLine = sal_False; >- bLineBreak = sal_False; >- >- while ( ( nTmpWidth <= nXWidth ) && !bEOL && ( nTmpPortion < pTEParaPortion->GetTextPortions().size() ) ) >- { >- nPortionStart = nTmpPos; >- pPortion = pTEParaPortion->GetTextPortions()[ nTmpPortion ]; >- DBG_ASSERT( pPortion->GetLen(), "Leere Portion in CreateLines ?!" ); >- if ( pNode->GetText().GetChar( nTmpPos ) == '\t' ) >- { >- long nCurPos = nTmpWidth-mpDoc->GetLeftMargin(); >- nTmpWidth = ((nCurPos/mnDefTab)+1)*mnDefTab+mpDoc->GetLeftMargin(); >- pPortion->GetWidth() = nTmpWidth - nCurPos - mpDoc->GetLeftMargin(); >- // 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->GetWidth() = nXWidth-1; >- nTmpWidth = pPortion->GetWidth(); >- bEOL = sal_True; >- bBrokenLine = sal_True; >- } >- pPortion->GetKind() = PORTIONKIND_TAB; >- } >- else >- { >- >- if ( bCalcPortion || !pPortion->HasValidSize() ) >- pPortion->GetWidth() = (long)CalcTextWidth( nPara, nTmpPos, pPortion->GetLen() ); >- nTmpWidth += pPortion->GetWidth(); >- >- pPortion->GetRightToLeft() = ImpGetRightToLeft( nPara, nTmpPos+1 ); >- pPortion->GetKind() = PORTIONKIND_TEXT; >- } >- >- nTmpPos = nTmpPos + pPortion->GetLen(); >- nPortionEnd = nTmpPos; >- nTmpPortion++; >- } >- >- // das war evtl. eine Portion zu weit: >- sal_Bool bFixedEnd = sal_False; >- if ( nTmpWidth > nXWidth ) >- { >- nPortionEnd = nTmpPos; >- nTmpPos = nTmpPos - pPortion->GetLen(); >- nPortionStart = nTmpPos; >- nTmpPortion--; >- bEOL = sal_False; >- >- nTmpWidth -= pPortion->GetWidth(); >- if ( pPortion->GetKind() == PORTIONKIND_TAB ) >- { >- bEOL = sal_True; >- bFixedEnd = sal_True; >- } >- } >- else >- { >- bEOL = sal_True; >- pLine->SetEnd( nPortionEnd ); >- OSL_ENSURE(pTEParaPortion->GetTextPortions().size(), >- "No TextPortions?"); >- pLine->SetEndPortion( (sal_uInt16)pTEParaPortion->GetTextPortions().size() - 1 ); >- } >- >- if ( bFixedEnd ) >- { >- pLine->SetEnd( nPortionStart ); >- pLine->SetEndPortion( nTmpPortion-1 ); >- } >- else if ( bLineBreak || bBrokenLine ) >- { >- pLine->SetEnd( nPortionStart+1 ); >- pLine->SetEndPortion( nTmpPortion-1 ); >- } >- else if ( !bEOL ) >- { >- DBG_ASSERT( (nPortionEnd-nPortionStart) == pPortion->GetLen(), "Doch eine andere Portion?!" ); >- long nRemainingWidth = mnMaxTextWidth - nTmpWidth; >- ImpBreakLine( nPara, pLine, pPortion, nPortionStart, nRemainingWidth ); >- } >- >- if ( ( ImpGetAlign() == TXTALIGN_CENTER ) || ( ImpGetAlign() == TXTALIGN_RIGHT ) ) >- { >- // Ausrichten... >- long nTextWidth = 0; >- for ( sal_uInt16 nTP = pLine->GetStartPortion(); nTP <= pLine->GetEndPortion(); nTP++ ) >- { >- TETextPortion* pTextPortion = pTEParaPortion->GetTextPortions()[ nTP ]; >- nTextWidth += pTextPortion->GetWidth(); >- } >- long nSpace = mnMaxTextWidth - nTextWidth; >- if ( nSpace > 0 ) >- { >- if ( ImpGetAlign() == TXTALIGN_CENTER ) >- pLine->SetStartX( (sal_uInt16)(nSpace / 2) ); >- else // TXTALIGN_RIGHT >- pLine->SetStartX( (sal_uInt16)nSpace ); >- } >- } >- else >- { >- pLine->SetStartX( mpDoc->GetLeftMargin() ); >- } >- >- // ----------------------------------------------------------------- >- // pruefen, ob die Zeile neu ausgegeben werden muss... >- // ----------------------------------------------------------------- >- pLine->SetInvalid(); >- >- if ( pTEParaPortion->IsSimpleInvalid() ) >- { >- // 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 ( bCalcPortion && bQuickFormat ) >- { >- bCalcPortion = sal_False; >- pTEParaPortion->CorrectValuesBehindLastFormattedLine( nLine ); >- break; >- } >- } >- } >- else if ( 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 ) ) >- { >- bCalcPortion = sal_False; >- pTEParaPortion->CorrectValuesBehindLastFormattedLine( nLine ); >- break; >- } >- } >- } >- } >- >- 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 < pTEParaPortion->GetLines().size()-1 ) >- pLine = pTEParaPortion->GetLines()[ ++nLine ]; >- if ( pLine && ( nIndex >= pNode->GetText().Len() ) ) >- { >- nDelFromLine = nLine; >- break; >- } >- if ( !pLine && ( nIndex < pNode->GetText().Len() ) ) >- { >- pLine = new TextLine; >- pTEParaPortion->GetLines().insert( pTEParaPortion->GetLines().begin() + ++nLine, pLine ); >- } >- if ( pLine ) >- { >- aSaveLine = *pLine; >- pLine->SetStart( nIndex ); >- pLine->SetEnd( nIndex ); >- pLine->SetStartPortion( nEndPortion+1 ); >- pLine->SetEndPortion( nEndPortion+1 ); >- } >- } // while ( Index < Len ) >- >- if (nDelFromLine != std::numeric_limits<size_t>::max()) >- { >- for( TextLines::iterator it = pTEParaPortion->GetLines().begin() + nDelFromLine; >- it != pTEParaPortion->GetLines().end(); ++it ) >- { >- delete *it; >- } >- pTEParaPortion->GetLines().erase( pTEParaPortion->GetLines().begin() + nDelFromLine, >- pTEParaPortion->GetLines().end() ); >- } >- >- DBG_ASSERT( pTEParaPortion->GetLines().size(), "Keine Zeile nach CreateLines!" ); >- >- if ( bLineBreak == sal_True ) >- CreateAndInsertEmptyLine( nPara ); >- >- pTEParaPortion->SetValid(); >- >- return nOldLineCount != pTEParaPortion->GetLines().size(); >-} >- >-String TextEngine::GetWord( const TextPaM& rCursorPos, TextPaM* pStartOfWord ) >-{ >- String aWord; >- if ( rCursorPos.GetPara() < mpDoc->GetNodes().Count() ) >- { >- TextSelection aSel( rCursorPos ); >- TextNode* pNode = mpDoc->GetNodes().GetObject( rCursorPos.GetPara() ); >- uno::Reference < i18n::XBreakIterator > xBI = GetBreakIterator(); >- i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), rCursorPos.GetIndex(), GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True ); >- aSel.GetStart().GetIndex() = (sal_uInt16)aBoundary.startPos; >- aSel.GetEnd().GetIndex() = (sal_uInt16)aBoundary.endPos; >- aWord = pNode->GetText().Copy( aSel.GetStart().GetIndex(), aSel.GetEnd().GetIndex() - aSel.GetStart().GetIndex() ); >- if ( pStartOfWord ) >- *pStartOfWord = aSel.GetStart(); >- } >- return aWord; >-} >- >-sal_Bool TextEngine::Read( SvStream& rInput, const TextSelection* pSel ) >-{ >- sal_Bool bUpdate = GetUpdateMode(); >- SetUpdateMode( sal_False ); >- >- UndoActionStart(); >- TextSelection aSel; >- if ( pSel ) >- aSel = *pSel; >- else >- { >- sal_uLong nParas = mpDoc->GetNodes().Count(); >- TextNode* pNode = mpDoc->GetNodes().GetObject( nParas - 1 ); >- aSel = TextPaM( nParas-1 , pNode->GetText().Len() ); >- } >- >- if ( aSel.HasRange() ) >- aSel = ImpDeleteText( aSel ); >- >- rtl::OString aLine; >- sal_Bool bDone = rInput.ReadLine( aLine ); >- rtl::OUString aTmpStr(rtl::OStringToOUString(aLine, rInput.GetStreamCharSet())), aStr; >- while ( bDone ) >- { >- aSel = ImpInsertText( aSel, aTmpStr ); >- bDone = rInput.ReadLine( aLine ); >- aTmpStr = rtl::OStringToOUString(aLine, rInput.GetStreamCharSet()); >- if ( bDone ) >- aSel = ImpInsertParaBreak( aSel.GetEnd() ); >- } >- >- UndoActionEnd(); >- >- TextSelection aNewSel( aSel.GetEnd(), aSel.GetEnd() ); >- >- // Damit bei FormatAndUpdate nicht auf die ungueltige Selektion zugegriffen wird. >- if ( GetActiveView() ) >- GetActiveView()->ImpSetSelection( aNewSel ); >- >- SetUpdateMode( bUpdate ); >- FormatAndUpdate( GetActiveView() ); >- >- return rInput.GetError() ? sal_False : sal_True; >-} >- >-sal_Bool TextEngine::Write( SvStream& rOutput, const TextSelection* pSel, sal_Bool bHTML ) >-{ >- TextSelection aSel; >- if ( pSel ) >- aSel = *pSel; >- else >- { >- sal_uLong nParas = mpDoc->GetNodes().Count(); >- TextNode* pNode = mpDoc->GetNodes().GetObject( nParas - 1 ); >- aSel.GetStart() = TextPaM( 0, 0 ); >- aSel.GetEnd() = TextPaM( nParas-1, pNode->GetText().Len() ); >- } >- >- if ( bHTML ) >- { >- rOutput.WriteLine( "<HTML>" ); >- rOutput.WriteLine( "<BODY>" ); >- } >- >- for ( sal_uLong nPara = aSel.GetStart().GetPara(); nPara <= aSel.GetEnd().GetPara(); nPara++ ) >- { >- TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >- >- sal_uInt16 nStartPos = 0; >- sal_uInt16 nEndPos = pNode->GetText().Len(); >- if ( nPara == aSel.GetStart().GetPara() ) >- nStartPos = aSel.GetStart().GetIndex(); >- if ( nPara == aSel.GetEnd().GetPara() ) >- nEndPos = aSel.GetEnd().GetIndex(); >- >- String aText; >- if ( !bHTML ) >- { >- aText = pNode->GetText().Copy( nStartPos, nEndPos-nStartPos ); >- } >- else >- { >- aText.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "<P STYLE=\"margin-bottom: 0cm\">" ) ); >- >- if ( nStartPos == nEndPos ) >- { >- // Leerzeilen werden von Writer wegoptimiert >- aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "<BR>" ) ); >- } >- else >- { >- sal_uInt16 nTmpStart = nStartPos; >- sal_uInt16 nTmpEnd = nEndPos; >- do >- { >- TextCharAttrib* pAttr = pNode->GetCharAttribs().FindNextAttrib( TEXTATTR_HYPERLINK, nTmpStart, nEndPos ); >- nTmpEnd = pAttr ? pAttr->GetStart() : nEndPos; >- >- // Text vor dem Attribut >- aText += pNode->GetText().Copy( nTmpStart, nTmpEnd-nTmpStart ); >- >- if ( pAttr ) >- { >- nTmpEnd = Min( pAttr->GetEnd(), nEndPos ); >- >- // z.B. <A HREF="http://www.mopo.de/">Morgenpost</A> >- aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "<A HREF=\"" ) ); >- aText += ((const TextAttribHyperLink&) pAttr->GetAttr() ).GetURL(); >- aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "\">" ) ); >- nTmpStart = pAttr->GetStart(); >- aText += pNode->GetText().Copy( nTmpStart, nTmpEnd-nTmpStart ); >- aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "</A>" ) ); >- >- nTmpStart = pAttr->GetEnd(); >- } >- } while ( nTmpEnd < nEndPos ); >- } >- >- aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "</P>" ) ); >- } >- rOutput.WriteLine(rtl::OUStringToOString(aText, >- rOutput.GetStreamCharSet())); >- } >- >- if ( bHTML ) >- { >- rOutput.WriteLine( "</BODY>" ); >- rOutput.WriteLine( "</HTML>" ); >- } >- >- return rOutput.GetError() ? sal_False : sal_True; >-} >- >-void TextEngine::RemoveAttribs( sal_uLong nPara, sal_Bool bIdleFormatAndUpdate ) >-{ >- if ( nPara < mpDoc->GetNodes().Count() ) >- { >- TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >- if ( pNode->GetCharAttribs().Count() ) >- { >- pNode->GetCharAttribs().Clear( sal_True ); >- >- TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >- pTEParaPortion->MarkSelectionInvalid( 0, pNode->GetText().Len() ); >- >- mbFormatted = sal_False; >- >- if ( bIdleFormatAndUpdate ) >- IdleFormatAndUpdate( NULL, 0xFFFF ); >- else >- FormatAndUpdate( NULL ); >- } >- } >-} >-void TextEngine::RemoveAttribs( sal_uLong nPara, sal_uInt16 nWhich, sal_Bool bIdleFormatAndUpdate ) >-{ >- if ( nPara < mpDoc->GetNodes().Count() ) >- { >- TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >- if ( pNode->GetCharAttribs().Count() ) >- { >- TextCharAttribList& rAttribs = pNode->GetCharAttribs(); >- sal_uInt16 nAttrCount = rAttribs.Count(); >- for(sal_uInt16 nAttr = nAttrCount; nAttr; --nAttr) >- { >- if(rAttribs.GetAttrib( nAttr - 1 )->Which() == nWhich) >- rAttribs.RemoveAttrib( nAttr -1 ); >- } >- TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >- pTEParaPortion->MarkSelectionInvalid( 0, pNode->GetText().Len() ); >- mbFormatted = sal_False; >- if(bIdleFormatAndUpdate) >- IdleFormatAndUpdate( NULL, 0xFFFF ); >- else >- FormatAndUpdate( NULL ); >- } >- } >-} >-void TextEngine::RemoveAttrib( sal_uLong nPara, const TextCharAttrib& rAttrib ) >-{ >- if ( nPara < mpDoc->GetNodes().Count() ) >- { >- TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >- if ( pNode->GetCharAttribs().Count() ) >- { >- TextCharAttribList& rAttribs = pNode->GetCharAttribs(); >- sal_uInt16 nAttrCount = rAttribs.Count(); >- for(sal_uInt16 nAttr = nAttrCount; nAttr; --nAttr) >- { >- if(rAttribs.GetAttrib( nAttr - 1 ) == &rAttrib) >- { >- rAttribs.RemoveAttrib( nAttr -1 ); >- break; >- } >- } >- TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >- pTEParaPortion->MarkSelectionInvalid( 0, pNode->GetText().Len() ); >- mbFormatted = sal_False; >- FormatAndUpdate( NULL ); >- } >- } >-} >- >-void TextEngine::SetAttrib( const TextAttrib& rAttr, sal_uLong nPara, sal_uInt16 nStart, sal_uInt16 nEnd, sal_Bool bIdleFormatAndUpdate ) >-{ >- // Es wird hier erstmal nicht geprueft, ob sich Attribute ueberlappen! >- // Diese Methode ist erstmal nur fuer einen Editor, der fuer eine Zeile >- // _schnell_ das Syntax-Highlight einstellen will. >- >- // Da die TextEngine z.Zt fuer Editoren gedacht ist gibt es auch kein >- // Undo fuer Attribute! >- >- if ( nPara < mpDoc->GetNodes().Count() ) >- { >- TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >- TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >- >- sal_uInt16 nMax = pNode->GetText().Len(); >- if ( nStart > nMax ) >- nStart = nMax; >- if ( nEnd > nMax ) >- nEnd = nMax; >- >- pNode->GetCharAttribs().InsertAttrib( new TextCharAttrib( rAttr, nStart, nEnd ) ); >- pTEParaPortion->MarkSelectionInvalid( nStart, nEnd ); >- >- mbFormatted = sal_False; >- if ( bIdleFormatAndUpdate ) >- IdleFormatAndUpdate( NULL, 0xFFFF ); >- else >- FormatAndUpdate( NULL ); >- } >-} >- >-void TextEngine::SetTextAlign( TxtAlign eAlign ) >-{ >- if ( eAlign != meAlign ) >- { >- meAlign = eAlign; >- FormatFullDoc(); >- UpdateViews(); >- } >-} >- >- >-void TextEngine::ValidateSelection( TextSelection& rSel ) const >-{ >- ValidatePaM( rSel.GetStart() ); >- ValidatePaM( rSel.GetEnd() ); >-} >- >-void TextEngine::ValidatePaM( TextPaM& rPaM ) const >-{ >- sal_uLong nMaxPara = mpDoc->GetNodes().Count() - 1; >- if ( rPaM.GetPara() > nMaxPara ) >- { >- rPaM.GetPara() = nMaxPara; >- rPaM.GetIndex() = 0xFFFF; >- } >- >- sal_uInt16 nMaxIndex = GetTextLen( rPaM.GetPara() ); >- if ( rPaM.GetIndex() > nMaxIndex ) >- rPaM.GetIndex() = nMaxIndex; >-} >- >- >-// Status & Selektionsanpassung >- >-void TextEngine::ImpParagraphInserted( sal_uLong nPara ) >-{ >- // Die aktive View braucht nicht angepasst werden, aber bei allen >- // passiven muss die Selektion angepasst werden: >- if ( mpViews->size() > 1 ) >- { >- for ( sal_uInt16 nView = mpViews->size(); nView; ) >- { >- TextView* pView = (*mpViews)[ --nView ]; >- if ( pView != GetActiveView() ) >- { >- for ( int n = 0; n <= 1; n++ ) >- { >- TextPaM& rPaM = n ? pView->GetSelection().GetStart(): pView->GetSelection().GetEnd(); >- if ( rPaM.GetPara() >= nPara ) >- rPaM.GetPara()++; >- } >- } >- } >- } >- Broadcast( TextHint( TEXT_HINT_PARAINSERTED, nPara ) ); >-} >- >-void TextEngine::ImpParagraphRemoved( sal_uLong nPara ) >-{ >- if ( mpViews->size() > 1 ) >- { >- for ( sal_uInt16 nView = mpViews->size(); nView; ) >- { >- TextView* pView = (*mpViews)[ --nView ]; >- if ( pView != GetActiveView() ) >- { >- sal_uLong nParas = mpDoc->GetNodes().Count(); >- for ( int n = 0; n <= 1; n++ ) >- { >- TextPaM& rPaM = n ? pView->GetSelection().GetStart(): pView->GetSelection().GetEnd(); >- if ( rPaM.GetPara() > nPara ) >- rPaM.GetPara()--; >- else if ( rPaM.GetPara() == nPara ) >- { >- rPaM.GetIndex() = 0; >- if ( rPaM.GetPara() >= nParas ) >- rPaM.GetPara()--; >- } >- } >- } >- } >- } >- Broadcast( TextHint( TEXT_HINT_PARAREMOVED, nPara ) ); >-} >- >-void TextEngine::ImpCharsRemoved( sal_uLong nPara, sal_uInt16 nPos, sal_uInt16 nChars ) >-{ >- if ( mpViews->size() > 1 ) >- { >- for ( sal_uInt16 nView = mpViews->size(); nView; ) >- { >- TextView* pView = (*mpViews)[ --nView ]; >- if ( pView != GetActiveView() ) >- { >- sal_uInt16 nEnd = nPos+nChars; >- for ( int n = 0; n <= 1; n++ ) >- { >- TextPaM& rPaM = n ? pView->GetSelection().GetStart(): pView->GetSelection().GetEnd(); >- if ( rPaM.GetPara() == nPara ) >- { >- if ( rPaM.GetIndex() > nEnd ) >- rPaM.GetIndex() = rPaM.GetIndex() - nChars; >- else if ( rPaM.GetIndex() > nPos ) >- rPaM.GetIndex() = nPos; >- } >- } >- } >- } >- } >- Broadcast( TextHint( TEXT_HINT_PARACONTENTCHANGED, nPara ) ); >-} >- >-void TextEngine::ImpCharsInserted( sal_uLong nPara, sal_uInt16 nPos, sal_uInt16 nChars ) >-{ >- if ( mpViews->size() > 1 ) >- { >- for ( sal_uInt16 nView = mpViews->size(); nView; ) >- { >- TextView* pView = (*mpViews)[ --nView ]; >- if ( pView != GetActiveView() ) >- { >- for ( int n = 0; n <= 1; n++ ) >- { >- TextPaM& rPaM = n ? pView->GetSelection().GetStart(): pView->GetSelection().GetEnd(); >- if ( rPaM.GetPara() == nPara ) >- { >- if ( rPaM.GetIndex() >= nPos ) >- rPaM.GetIndex() = rPaM.GetIndex() + nChars; >- } >- } >- } >- } >- } >- Broadcast( TextHint( TEXT_HINT_PARACONTENTCHANGED, nPara ) ); >-} >- >-void TextEngine::ImpFormattingParagraph( sal_uLong nPara ) >-{ >- Broadcast( TextHint( TEXT_HINT_FORMATPARA, nPara ) ); >-} >- >-void TextEngine::ImpTextHeightChanged() >-{ >- Broadcast( TextHint( TEXT_HINT_TEXTHEIGHTCHANGED ) ); >-} >- >-void TextEngine::ImpTextFormatted() >-{ >- Broadcast( TextHint( TEXT_HINT_TEXTFORMATTED ) ); >-} >- >-void TextEngine::Draw( OutputDevice* pDev, const Point& rPos ) >-{ >- ImpPaint( pDev, rPos, NULL ); >-} >- >-void TextEngine::SetLeftMargin( sal_uInt16 n ) >-{ >- mpDoc->SetLeftMargin( n ); >-} >- >-sal_uInt16 TextEngine::GetLeftMargin() const >-{ >- return mpDoc->GetLeftMargin(); >-} >- >-uno::Reference< i18n::XBreakIterator > TextEngine::GetBreakIterator() >-{ >- if ( !mxBreakIterator.is() ) >- mxBreakIterator = vcl::unohelper::CreateBreakIterator(); >- DBG_ASSERT( mxBreakIterator.is(), "Could not create BreakIterator" ); >- return mxBreakIterator; >-} >- >-void TextEngine::SetLocale( const ::com::sun::star::lang::Locale& rLocale ) >-{ >- maLocale = rLocale; >- delete mpLocaleDataWrapper; >- mpLocaleDataWrapper = NULL; >-} >- >-::com::sun::star::lang::Locale TextEngine::GetLocale() >-{ >- if ( maLocale.Language.isEmpty() ) >- { >- maLocale = Application::GetSettings().GetUILocale(); >- } >- return maLocale; >-} >- >-LocaleDataWrapper* TextEngine::ImpGetLocaleDataWrapper() >-{ >- if ( !mpLocaleDataWrapper ) >- mpLocaleDataWrapper = new LocaleDataWrapper( vcl::unohelper::GetMultiServiceFactory(), GetLocale() ); >- >- return mpLocaleDataWrapper; >-} >- >-void TextEngine::SetRightToLeft( sal_Bool bR2L ) >-{ >- if ( mbRightToLeft != bR2L ) >- { >- mbRightToLeft = bR2L; >- meAlign = bR2L ? TXTALIGN_RIGHT : TXTALIGN_LEFT; >- FormatFullDoc(); >- UpdateViews(); >- } >-} >- >-void TextEngine::ImpInitWritingDirections( sal_uLong nPara ) >-{ >- TEParaPortion* pParaPortion = mpTEParaPortions->GetObject( nPara ); >- std::vector<TEWritingDirectionInfo>& rInfos = pParaPortion->GetWritingDirectionInfos(); >- rInfos.clear(); >- >- if ( pParaPortion->GetNode()->GetText().Len() ) >- { >- const UBiDiLevel nBidiLevel = IsRightToLeft() ? 1 /*RTL*/ : 0 /*LTR*/; >- String aText( pParaPortion->GetNode()->GetText() ); >- >- // >- // 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 ( sal_uInt16 nIdx = 0; nIdx < nCount; ++nIdx ) >- { >- ubidi_getLogicalRun( pBidi, nStart, &nEnd, &nCurrDir ); >- rInfos.push_back( TEWritingDirectionInfo( nCurrDir, (sal_uInt16)nStart, (sal_uInt16)nEnd ) ); >- nStart = nEnd; >- } >- >- ubidi_close( pBidi ); >- } >- >- // No infos mean no CTL and default dir is L2R... >- if ( rInfos.empty() ) >- rInfos.push_back( TEWritingDirectionInfo( 0, 0, (sal_uInt16)pParaPortion->GetNode()->GetText().Len() ) ); >- >-} >- >-sal_uInt8 TextEngine::ImpGetRightToLeft( sal_uLong nPara, sal_uInt16 nPos, sal_uInt16* pStart, sal_uInt16* pEnd ) >-{ >- sal_uInt8 nRightToLeft = 0; >- >- TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >- if ( pNode && pNode->GetText().Len() ) >- { >- TEParaPortion* pParaPortion = mpTEParaPortions->GetObject( nPara ); >- if ( pParaPortion->GetWritingDirectionInfos().empty() ) >- ImpInitWritingDirections( nPara ); >- >- std::vector<TEWritingDirectionInfo>& rDirInfos = pParaPortion->GetWritingDirectionInfos(); >- for ( std::vector<TEWritingDirectionInfo>::const_iterator rDirInfosIt = rDirInfos.begin(); rDirInfosIt != rDirInfos.end(); ++rDirInfosIt ) >- { >- if ( ( (*rDirInfosIt).nStartPos <= nPos ) && ( (*rDirInfosIt).nEndPos >= nPos ) ) >- { >- nRightToLeft = (*rDirInfosIt).nType; >- if ( pStart ) >- *pStart = (*rDirInfosIt).nStartPos; >- if ( pEnd ) >- *pEnd = (*rDirInfosIt).nEndPos; >- break; >- } >- } >- } >- return nRightToLeft; >-} >- >-long TextEngine::ImpGetPortionXOffset( sal_uLong nPara, TextLine* pLine, sal_uInt16 nTextPortion ) >-{ >- long nX = pLine->GetStartX(); >- >- TEParaPortion* pParaPortion = mpTEParaPortions->GetObject( nPara ); >- >- for ( sal_uInt16 i = pLine->GetStartPortion(); i < nTextPortion; i++ ) >- { >- TETextPortion* pPortion = pParaPortion->GetTextPortions()[ i ]; >- nX += pPortion->GetWidth(); >- } >- >- TETextPortion* pDestPortion = pParaPortion->GetTextPortions()[ nTextPortion ]; >- if ( pDestPortion->GetKind() != PORTIONKIND_TAB ) >- { >- if ( !IsRightToLeft() && pDestPortion->GetRightToLeft() ) >- { >- // Portions behind must be added, visual before this portion >- sal_uInt16 nTmpPortion = nTextPortion+1; >- while ( nTmpPortion <= pLine->GetEndPortion() ) >- { >- TETextPortion* pNextTextPortion = pParaPortion->GetTextPortions()[ nTmpPortion ]; >- if ( pNextTextPortion->GetRightToLeft() && ( pNextTextPortion->GetKind() != PORTIONKIND_TAB ) ) >- nX += pNextTextPortion->GetWidth(); >- else >- break; >- nTmpPortion++; >- } >- // Portions before must be removed, visual behind this portion >- nTmpPortion = nTextPortion; >- while ( nTmpPortion > pLine->GetStartPortion() ) >- { >- --nTmpPortion; >- TETextPortion* pPrevTextPortion = pParaPortion->GetTextPortions()[ nTmpPortion ]; >- if ( pPrevTextPortion->GetRightToLeft() && ( pPrevTextPortion->GetKind() != PORTIONKIND_TAB ) ) >- nX -= pPrevTextPortion->GetWidth(); >- else >- break; >- } >- } >- else if ( IsRightToLeft() && !pDestPortion->IsRightToLeft() ) >- { >- // Portions behind must be removed, visual behind this portion >- sal_uInt16 nTmpPortion = nTextPortion+1; >- while ( nTmpPortion <= pLine->GetEndPortion() ) >- { >- TETextPortion* pNextTextPortion = pParaPortion->GetTextPortions()[ nTmpPortion ]; >- if ( !pNextTextPortion->IsRightToLeft() && ( pNextTextPortion->GetKind() != PORTIONKIND_TAB ) ) >- nX += pNextTextPortion->GetWidth(); >- else >- break; >- nTmpPortion++; >- } >- // Portions before must be added, visual before this portion >- nTmpPortion = nTextPortion; >- while ( nTmpPortion > pLine->GetStartPortion() ) >- { >- --nTmpPortion; >- TETextPortion* pPrevTextPortion = pParaPortion->GetTextPortions()[ nTmpPortion ]; >- if ( !pPrevTextPortion->IsRightToLeft() && ( pPrevTextPortion->GetKind() != PORTIONKIND_TAB ) ) >- nX -= pPrevTextPortion->GetWidth(); >- else >- break; >- } >- } >- } >- >- return nX; >-} >- >-void TextEngine::ImpInitLayoutMode( OutputDevice* pOutDev, sal_Bool bDrawingR2LPortion ) >-{ >- sal_uLong nLayoutMode = pOutDev->GetLayoutMode(); >- >- nLayoutMode &= ~(TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_COMPLEX_DISABLED | TEXT_LAYOUT_BIDI_STRONG ); >- if ( bDrawingR2LPortion ) >- nLayoutMode |= TEXT_LAYOUT_BIDI_RTL; >- >- pOutDev->SetLayoutMode( nLayoutMode ); >-} >- >-TxtAlign TextEngine::ImpGetAlign() const >-{ >- TxtAlign eAlign = meAlign; >- if ( IsRightToLeft() ) >- { >- if ( eAlign == TXTALIGN_LEFT ) >- eAlign = TXTALIGN_RIGHT; >- else if ( eAlign == TXTALIGN_RIGHT ) >- eAlign = TXTALIGN_LEFT; >- } >- return eAlign; >-} >- >-long TextEngine::ImpGetOutputOffset( sal_uLong nPara, TextLine* pLine, sal_uInt16 nIndex, sal_uInt16 nIndex2 ) >-{ >- TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPara ); >- >- sal_uInt16 nPortionStart; >- sal_uInt16 nPortion = pPortion->GetTextPortions().FindPortion( nIndex, nPortionStart, sal_True ); >- >- TETextPortion* pTextPortion = pPortion->GetTextPortions()[ nPortion ]; >- >- long nX; >- >- if ( ( nIndex == nPortionStart ) && ( nIndex == nIndex2 ) ) >- { >- // Output of full portion, so we need portion x offset. >- // Use ImpGetPortionXOffset, because GetXPos may deliver left or right position from portioon, depending on R2L, L2R >- nX = ImpGetPortionXOffset( nPara, pLine, nPortion ); >- if ( IsRightToLeft() ) >- { >- nX = -nX -pTextPortion->GetWidth(); >- } >- } >- else >- { >- nX = ImpGetXPos( nPara, pLine, nIndex, nIndex == nPortionStart ); >- if ( nIndex2 != nIndex ) >- { >- long nX2 = ImpGetXPos( nPara, pLine, nIndex2, sal_False ); >- if ( ( !IsRightToLeft() && ( nX2 < nX ) ) || >- ( IsRightToLeft() && ( nX2 > nX ) ) ) >- { >- nX = nX2; >- } >- } >- if ( IsRightToLeft() ) >- { >- nX = -nX; >- } >- } >- >- return nX; >-} >- >-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/svtools/source/edit/textund2.hxx b/svtools/source/edit/textund2.hxx >deleted file mode 100644 >index c5ce90c..0000000 >--- a/svtools/source/edit/textund2.hxx >+++ /dev/null >@@ -1,122 +0,0 @@ >-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >-/* >- * This file is part of the LibreOffice project. >- * >- * This Source Code Form is subject to the terms of the Mozilla Public >- * License, v. 2.0. If a copy of the MPL was not distributed with this >- * file, You can obtain one at http://mozilla.org/MPL/2.0/. >- * >- * This file incorporates work covered by the following license notice: >- * >- * Licensed to the Apache Software Foundation (ASF) under one or more >- * contributor license agreements. See the NOTICE file distributed >- * with this work for additional information regarding copyright >- * ownership. The ASF licenses this file to you under the Apache >- * License, Version 2.0 (the "License"); you may not use this file >- * except in compliance with the License. You may obtain a copy of >- * the License at http://www.apache.org/licenses/LICENSE-2.0 . >- */ >-#ifndef _TEXTUND2_HXX >-#define _TEXTUND2_HXX >- >-#include <textundo.hxx> >- >- >-class TextUndoDelPara : public TextUndo >-{ >-private: >- sal_Bool mbDelObject; >- sal_uLong mnPara; >- TextNode* mpNode; // Zeigt auf das gueltige, nicht zerstoerte Objekt! >- >-public: >- TYPEINFO(); >- TextUndoDelPara( TextEngine* pTextEngine, TextNode* pNode, sal_uLong nPara ); >- ~TextUndoDelPara(); >- >- virtual void Undo(); >- virtual void Redo(); >-}; >- >- >-class TextUndoConnectParas : public TextUndo >-{ >-private: >- sal_uLong mnPara; >- sal_uInt16 mnSepPos; >- >-public: >- TYPEINFO(); >- TextUndoConnectParas( TextEngine* pTextEngine, sal_uLong nPara, sal_uInt16 nSepPos ); >- ~TextUndoConnectParas(); >- >- virtual void Undo(); >- virtual void Redo(); >-}; >- >- >-class TextUndoSplitPara : public TextUndo >-{ >-private: >- sal_uLong mnPara; >- sal_uInt16 mnSepPos; >- >-public: >- TYPEINFO(); >- TextUndoSplitPara( TextEngine* pTextEngine, sal_uLong nPara, sal_uInt16 nSepPos ); >- ~TextUndoSplitPara(); >- >- virtual void Undo(); >- virtual void Redo(); >-}; >- >- >-class TextUndoInsertChars : public TextUndo >-{ >-private: >- TextPaM maTextPaM; >- String maText; >- >-public: >- TYPEINFO(); >- TextUndoInsertChars( TextEngine* pTextEngine, const TextPaM& rTextPaM, const String& rStr ); >- >- virtual void Undo(); >- virtual void Redo(); >- >- virtual sal_Bool Merge( SfxUndoAction *pNextAction ); >-}; >- >- >-class TextUndoRemoveChars : public TextUndo >-{ >-private: >- TextPaM maTextPaM; >- String maText; >- >-public: >- TYPEINFO(); >- TextUndoRemoveChars( TextEngine* pTextEngine, const TextPaM& rTextPaM, const String& rStr ); >- >- virtual void Undo(); >- virtual void Redo(); >-}; >- >- >-class TextUndoSetAttribs: public TextUndo >-{ >-private: >- TextSelection maSelection; >- >-public: >- TYPEINFO(); >- TextUndoSetAttribs( TextEngine* pTextEngine, const TextSelection& rESel ); >- ~TextUndoSetAttribs(); >- >- virtual void Undo(); >- virtual void Redo(); >-}; >- >-#endif // _TEXTUND2_HXX >- >-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/svtools/source/edit/textundo.cxx b/svtools/source/edit/textundo.cxx >deleted file mode 100644 >index 1b82d0f..0000000 >--- a/svtools/source/edit/textundo.cxx >+++ /dev/null >@@ -1,295 +0,0 @@ >-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >-/************************************************************************* >- * >- * 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 <svtools/texteng.hxx> >-#include <svtools/textview.hxx> >-#include <textundo.hxx> >-#include <textund2.hxx> >-#include <svtools/textdata.hxx> >-#include <textdoc.hxx> >-#include <textdat2.hxx> >- >-TYPEINIT1( TextUndo, SfxUndoAction ); >-TYPEINIT1( TextUndoDelPara, TextUndo ); >-TYPEINIT1( TextUndoConnectParas, TextUndo ); >-TYPEINIT1( TextUndoSplitPara, TextUndo ); >-TYPEINIT1( TextUndoInsertChars, TextUndo ); >-TYPEINIT1( TextUndoRemoveChars, TextUndo ); >- >- >-TextUndoManager::TextUndoManager( TextEngine* p ) >-{ >- mpTextEngine = p; >-} >- >-TextUndoManager::~TextUndoManager() >-{ >-} >- >-sal_Bool TextUndoManager::Undo() >-{ >- if ( GetUndoActionCount() == 0 ) >- return sal_False; >- >- UndoRedoStart(); >- >- mpTextEngine->SetIsInUndo( sal_True ); >- sal_Bool bDone = SfxUndoManager::Undo(); >- mpTextEngine->SetIsInUndo( sal_False ); >- >- UndoRedoEnd(); >- >- return bDone; >-} >- >-sal_Bool TextUndoManager::Redo() >-{ >- if ( GetRedoActionCount() == 0 ) >- return sal_False; >- >- >- UndoRedoStart(); >- >- mpTextEngine->SetIsInUndo( sal_True ); >- sal_Bool bDone = SfxUndoManager::Redo(); >- mpTextEngine->SetIsInUndo( sal_False ); >- >- UndoRedoEnd(); >- >- return bDone; >-} >- >-void TextUndoManager::UndoRedoStart() >-{ >- DBG_ASSERT( GetView(), "Undo/Redo: Active View?" ); >- >-// if ( GetView() ) >-// GetView()->HideSelection(); >-} >- >-void TextUndoManager::UndoRedoEnd() >-{ >- if ( GetView() ) >- { >- TextSelection aNewSel( GetView()->GetSelection() ); >- aNewSel.GetStart() = aNewSel.GetEnd(); >- GetView()->ImpSetSelection( aNewSel ); >- } >- >- mpTextEngine->UpdateSelections(); >- >- mpTextEngine->FormatAndUpdate( GetView() ); >-} >- >- >-TextUndo::TextUndo( TextEngine* p ) >-{ >- mpTextEngine = p; >-} >- >-TextUndo::~TextUndo() >-{ >-} >- >-rtl::OUString TextUndo::GetComment() const >-{ >- return rtl::OUString(); >-} >- >-void TextUndo::SetSelection( const TextSelection& rSel ) >-{ >- if ( GetView() ) >- GetView()->ImpSetSelection( rSel ); >-} >- >- >-TextUndoDelPara::TextUndoDelPara( TextEngine* pTextEngine, TextNode* pNode, sal_uLong nPara ) >- : TextUndo( pTextEngine ) >-{ >- mpNode = pNode; >- mnPara = nPara; >- mbDelObject = sal_True; >-} >- >-TextUndoDelPara::~TextUndoDelPara() >-{ >- if ( mbDelObject ) >- delete mpNode; >-} >- >-void TextUndoDelPara::Undo() >-{ >- GetTextEngine()->InsertContent( mpNode, mnPara ); >- mbDelObject = sal_False; // gehoert wieder der Engine >- >- if ( GetView() ) >- { >- TextSelection aSel( TextPaM( mnPara, 0 ), TextPaM( mnPara, mpNode->GetText().Len() ) ); >- SetSelection( aSel ); >- } >-} >- >-void TextUndoDelPara::Redo() >-{ >- // pNode stimmt nicht mehr, falls zwischendurch Undos, in denen >- // Absaetze verschmolzen sind. >- mpNode = GetDoc()->GetNodes().GetObject( mnPara ); >- >- delete GetTEParaPortions()->GetObject( mnPara ); >- GetTEParaPortions()->Remove( mnPara ); >- >- // Node nicht loeschen, haengt im Undo! >- GetDoc()->GetNodes().Remove( mnPara ); >- GetTextEngine()->ImpParagraphRemoved( mnPara ); >- >- mbDelObject = sal_True; // gehoert wieder dem Undo >- >- sal_uLong nParas = GetDoc()->GetNodes().Count(); >- sal_uLong n = mnPara < nParas ? mnPara : (nParas-1); >- TextNode* pN = GetDoc()->GetNodes().GetObject( n ); >- TextPaM aPaM( n, pN->GetText().Len() ); >- SetSelection( aPaM ); >-} >- >-// ----------------------------------------------------------------------- >-// TextUndoConnectParas >-// ------------------------------------------------------------------------ >-TextUndoConnectParas::TextUndoConnectParas( TextEngine* pTextEngine, sal_uLong nPara, sal_uInt16 nPos ) >- : TextUndo( pTextEngine ) >-{ >- mnPara = nPara; >- mnSepPos = nPos; >-} >- >-TextUndoConnectParas::~TextUndoConnectParas() >-{ >-} >- >-void TextUndoConnectParas::Undo() >-{ >- TextPaM aPaM = GetTextEngine()->SplitContent( mnPara, mnSepPos ); >- SetSelection( aPaM ); >-} >- >-void TextUndoConnectParas::Redo() >-{ >- TextPaM aPaM = GetTextEngine()->ConnectContents( mnPara ); >- SetSelection( aPaM ); >-} >- >- >-TextUndoSplitPara::TextUndoSplitPara( TextEngine* pTextEngine, sal_uLong nPara, sal_uInt16 nPos ) >- : TextUndo( pTextEngine ) >-{ >- mnPara = nPara; >- mnSepPos = nPos; >-} >- >-TextUndoSplitPara::~TextUndoSplitPara() >-{ >-} >- >-void TextUndoSplitPara::Undo() >-{ >- TextPaM aPaM = GetTextEngine()->ConnectContents( mnPara ); >- SetSelection( aPaM ); >-} >- >-void TextUndoSplitPara::Redo() >-{ >- TextPaM aPaM = GetTextEngine()->SplitContent( mnPara, mnSepPos ); >- SetSelection( aPaM ); >-} >- >- >-TextUndoInsertChars::TextUndoInsertChars( TextEngine* pTextEngine, const TextPaM& rTextPaM, const XubString& rStr ) >- : TextUndo( pTextEngine ), >- maTextPaM( rTextPaM ), maText( rStr ) >-{ >-} >- >-void TextUndoInsertChars::Undo() >-{ >- TextSelection aSel( maTextPaM, maTextPaM ); >- aSel.GetEnd().GetIndex() = aSel.GetEnd().GetIndex() + maText.Len(); >- TextPaM aPaM = GetTextEngine()->ImpDeleteText( aSel ); >- SetSelection( aPaM ); >-} >- >-void TextUndoInsertChars::Redo() >-{ >- TextSelection aSel( maTextPaM, maTextPaM ); >- GetTextEngine()->ImpInsertText( aSel, maText ); >- TextPaM aNewPaM( maTextPaM ); >- aNewPaM.GetIndex() = aNewPaM.GetIndex() + maText.Len(); >- SetSelection( TextSelection( aSel.GetStart(), aNewPaM ) ); >-} >- >-sal_Bool TextUndoInsertChars::Merge( SfxUndoAction* pNextAction ) >-{ >- if ( !pNextAction->ISA( TextUndoInsertChars ) ) >- return sal_False; >- >- TextUndoInsertChars* pNext = (TextUndoInsertChars*)pNextAction; >- >- if ( maTextPaM.GetPara() != pNext->maTextPaM.GetPara() ) >- return sal_False; >- >- if ( ( maTextPaM.GetIndex() + maText.Len() ) == pNext->maTextPaM.GetIndex() ) >- { >- maText += pNext->maText; >- return sal_True; >- } >- return sal_False; >-} >- >- >-TextUndoRemoveChars::TextUndoRemoveChars( TextEngine* pTextEngine, const TextPaM& rTextPaM, const XubString& rStr ) >- : TextUndo( pTextEngine ), >- maTextPaM( rTextPaM ), maText( rStr ) >-{ >-} >- >-void TextUndoRemoveChars::Undo() >-{ >- TextSelection aSel( maTextPaM, maTextPaM ); >- GetTextEngine()->ImpInsertText( aSel, maText ); >- aSel.GetEnd().GetIndex() = aSel.GetEnd().GetIndex() + maText.Len(); >- SetSelection( aSel ); >-} >- >-void TextUndoRemoveChars::Redo() >-{ >- TextSelection aSel( maTextPaM, maTextPaM ); >- aSel.GetEnd().GetIndex() = aSel.GetEnd().GetIndex() + maText.Len(); >- TextPaM aPaM = GetTextEngine()->ImpDeleteText( aSel ); >- SetSelection( aPaM ); >-} >- >-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/svtools/source/edit/textundo.hxx b/svtools/source/edit/textundo.hxx >deleted file mode 100644 >index f86f877..0000000 >--- a/svtools/source/edit/textundo.hxx >+++ /dev/null >@@ -1,85 +0,0 @@ >-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >-/************************************************************************* >- * >- * 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 _TEXTUNDO_HXX >-#define _TEXTUNDO_HXX >- >-#include <svl/undo.hxx> >- >-class TextEngine; >- >-class TextUndoManager : public SfxUndoManager >-{ >- TextEngine* mpTextEngine; >- >-protected: >- >- void UndoRedoStart(); >- void UndoRedoEnd(); >- >- TextView* GetView() const { return mpTextEngine->GetActiveView(); } >- >-public: >- TextUndoManager( TextEngine* pTextEngine ); >- ~TextUndoManager(); >- >- using SfxUndoManager::Undo; >- virtual sal_Bool Undo(); >- using SfxUndoManager::Redo; >- virtual sal_Bool Redo(); >- >-}; >- >-class TextUndo : public SfxUndoAction >-{ >-private: >- TextEngine* mpTextEngine; >- >-protected: >- >- TextView* GetView() const { return mpTextEngine->GetActiveView(); } >- void SetSelection( const TextSelection& rSel ); >- >- TextDoc* GetDoc() const { return mpTextEngine->mpDoc; } >- TEParaPortions* GetTEParaPortions() const { return mpTextEngine->mpTEParaPortions; } >- >-public: >- TYPEINFO(); >- TextUndo( TextEngine* pTextEngine ); >- virtual ~TextUndo(); >- >- TextEngine* GetTextEngine() const { return mpTextEngine; } >- >- virtual void Undo() = 0; >- virtual void Redo() = 0; >- >- virtual rtl::OUString GetComment() const; >-}; >- >-#endif // _TEXTUNDO_HXX >- >-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/svtools/source/edit/textview.cxx b/svtools/source/edit/textview.cxx >deleted file mode 100644 >index 40a6774..0000000 >--- a/svtools/source/edit/textview.cxx >+++ /dev/null >@@ -1,2378 +0,0 @@ >-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >-/************************************************************************* >- * >- * 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 <svtools/textview.hxx> >-#include <svtools/texteng.hxx> >-#include <textdoc.hxx> >-#include <svtools/textdata.hxx> >-#include <textdat2.hxx> >- >-#include <svl/undo.hxx> >-#include <vcl/cursor.hxx> >-#include <vcl/window.hxx> >-#include <vcl/svapp.hxx> >-#include <tools/stream.hxx> >- >-#include <sot/formats.hxx> >-#include <svl/urlbmk.hxx> >- >-#include <com/sun/star/i18n/XBreakIterator.hpp> >- >-#include <com/sun/star/i18n/CharacterIteratorMode.hpp> >- >-#include <com/sun/star/i18n/WordType.hpp> >-#include <cppuhelper/weak.hxx> >-#include <vcl/unohelp.hxx> >-#include <com/sun/star/datatransfer/XTransferable.hpp> >-#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp> >-#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp> >-#include <com/sun/star/lang/XMultiServiceFactory.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 <vcl/edit.hxx> >- >- >-#include <sot/exchange.hxx> >- >-#include <osl/mutex.hxx> >- >- >-using namespace ::com::sun::star; >- >-class TETextDataObject : public ::com::sun::star::datatransfer::XTransferable, >- public ::cppu::OWeakObject >- >-{ >-private: >- String maText; >- SvMemoryStream maHTMLStream; >- >-public: >- TETextDataObject( const String& rText ); >- ~TETextDataObject(); >- >- String& GetText() { return maText; } >- SvMemoryStream& GetHTMLStream() { return maHTMLStream; } >- >- // ::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); >-}; >- >-TETextDataObject::TETextDataObject( const String& rText ) : maText( rText ) >-{ >-} >- >-TETextDataObject::~TETextDataObject() >-{ >-} >- >-// uno::XInterface >-uno::Any TETextDataObject::queryInterface( const uno::Type & rType ) throw(uno::RuntimeException) >-{ >- uno::Any aRet = ::cppu::queryInterface( rType, (static_cast< datatransfer::XTransferable* >(this)) ); >- return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType )); >-} >- >-// datatransfer::XTransferable >-uno::Any TETextDataObject::getTransferData( const datatransfer::DataFlavor& rFlavor ) throw(datatransfer::UnsupportedFlavorException, io::IOException, uno::RuntimeException) >-{ >- uno::Any aAny; >- >- sal_uLong nT = SotExchange::GetFormat( rFlavor ); >- if ( nT == SOT_FORMAT_STRING ) >- { >- aAny <<= (::rtl::OUString)GetText(); >- } >- else if ( nT == SOT_FORMATSTR_ID_HTML ) >- { >- GetHTMLStream().Seek( STREAM_SEEK_TO_END ); >- sal_uLong nLen = GetHTMLStream().Tell(); >- GetHTMLStream().Seek(0); >- >- uno::Sequence< sal_Int8 > aSeq( nLen ); >- memcpy( aSeq.getArray(), GetHTMLStream().GetData(), nLen ); >- aAny <<= aSeq; >- } >- else >- { >- throw datatransfer::UnsupportedFlavorException(); >- } >- return aAny; >-} >- >-uno::Sequence< datatransfer::DataFlavor > TETextDataObject::getTransferDataFlavors( ) throw(uno::RuntimeException) >-{ >- GetHTMLStream().Seek( STREAM_SEEK_TO_END ); >- sal_Bool bHTML = GetHTMLStream().Tell() > 0; >- uno::Sequence< datatransfer::DataFlavor > aDataFlavors( bHTML ? 2 : 1 ); >- SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aDataFlavors.getArray()[0] ); >- if ( bHTML ) >- SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_HTML, aDataFlavors.getArray()[1] ); >- return aDataFlavors; >-} >- >-sal_Bool TETextDataObject::isDataFlavorSupported( const datatransfer::DataFlavor& rFlavor ) throw(uno::RuntimeException) >-{ >- sal_uLong nT = SotExchange::GetFormat( rFlavor ); >- return ( nT == SOT_FORMAT_STRING ); >-} >- >-struct ImpTextView >-{ >- TextEngine* mpTextEngine; >- >- Window* mpWindow; >- TextSelection maSelection; >- Point maStartDocPos; >-// TextPaM maMBDownPaM; >- >- Cursor* mpCursor; >- >- TextDDInfo* mpDDInfo; >- >- VirtualDevice* mpVirtDev; >- >- SelectionEngine* mpSelEngine; >- TextSelFunctionSet* mpSelFuncSet; >- >- ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::dnd::XDragSourceListener > mxDnDListener; >- >- sal_uInt16 mnTravelXPos; >- >- sal_Bool mbAutoScroll : 1; >- sal_Bool mbInsertMode : 1; >- sal_Bool mbReadOnly : 1; >- sal_Bool mbPaintSelection : 1; >- sal_Bool mbAutoIndent : 1; >- sal_Bool mbHighlightSelection : 1; >- sal_Bool mbCursorEnabled : 1; >- sal_Bool mbClickedInSelection : 1; >- sal_Bool mbSupportProtectAttribute : 1; >- bool mbCursorAtEndOfLine; >-}; >- >-// ------------------------------------------------------------------------- >-// (+) class TextView >-// ------------------------------------------------------------------------- >-TextView::TextView( TextEngine* pEng, Window* pWindow ) : >- mpImpl(new ImpTextView) >-{ >- pWindow->EnableRTL( sal_False ); >- >- mpImpl->mpWindow = pWindow; >- mpImpl->mpTextEngine = pEng; >- mpImpl->mpVirtDev = NULL; >- >- mpImpl->mbPaintSelection = sal_True; >- mpImpl->mbAutoScroll = sal_True; >- mpImpl->mbInsertMode = sal_True; >- mpImpl->mbReadOnly = sal_False; >- mpImpl->mbHighlightSelection = sal_False; >- mpImpl->mbAutoIndent = sal_False; >- mpImpl->mbCursorEnabled = sal_True; >- mpImpl->mbClickedInSelection = sal_False; >- mpImpl->mbSupportProtectAttribute = sal_False; >- mpImpl->mbCursorAtEndOfLine = false; >-// mbInSelection = sal_False; >- >- mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW; >- >- mpImpl->mpSelFuncSet = new TextSelFunctionSet( this ); >- mpImpl->mpSelEngine = new SelectionEngine( mpImpl->mpWindow, mpImpl->mpSelFuncSet ); >- mpImpl->mpSelEngine->SetSelectionMode( RANGE_SELECTION ); >- mpImpl->mpSelEngine->EnableDrag( sal_True ); >- >- mpImpl->mpCursor = new Cursor; >- mpImpl->mpCursor->Show(); >- pWindow->SetCursor( mpImpl->mpCursor ); >- pWindow->SetInputContext( InputContext( pEng->GetFont(), INPUTCONTEXT_TEXT|INPUTCONTEXT_EXTTEXTINPUT ) ); >- >- if ( pWindow->GetSettings().GetStyleSettings().GetSelectionOptions() & SELECTION_OPTION_INVERT ) >- mpImpl->mbHighlightSelection = sal_True; >- >- pWindow->SetLineColor(); >- >- mpImpl->mpDDInfo = NULL; >- >- if ( pWindow->GetDragGestureRecognizer().is() ) >- { >- vcl::unohelper::DragAndDropWrapper* pDnDWrapper = new vcl::unohelper::DragAndDropWrapper( this ); >- mpImpl->mxDnDListener = pDnDWrapper; >- >- uno::Reference< datatransfer::dnd::XDragGestureListener> xDGL( mpImpl->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 ); >- } >-} >- >-TextView::~TextView() >-{ >- delete mpImpl->mpSelEngine; >- delete mpImpl->mpSelFuncSet; >- delete mpImpl->mpVirtDev; >- >- if ( mpImpl->mpWindow->GetCursor() == mpImpl->mpCursor ) >- mpImpl->mpWindow->SetCursor( 0 ); >- delete mpImpl->mpCursor; >- delete mpImpl->mpDDInfo; >- delete mpImpl; >-} >- >-void TextView::Invalidate() >-{ >- mpImpl->mpWindow->Invalidate(); >-} >- >-void TextView::SetSelection( const TextSelection& rTextSel, sal_Bool bGotoCursor ) >-{ >- // Falls jemand gerade ein leeres Attribut hinterlassen hat, >- // und dann der Outliner die Selektion manipulitert: >- if ( !mpImpl->maSelection.HasRange() ) >- mpImpl->mpTextEngine->CursorMoved( mpImpl->maSelection.GetStart().GetPara() ); >- >- // Wenn nach einem KeyInput die Selection manipuliert wird: >- mpImpl->mpTextEngine->CheckIdleFormatter(); >- >- HideSelection(); >- TextSelection aNewSel( rTextSel ); >- mpImpl->mpTextEngine->ValidateSelection( aNewSel ); >- ImpSetSelection( aNewSel ); >- ShowSelection(); >- ShowCursor( bGotoCursor ); >-} >- >-void TextView::SetSelection( const TextSelection& rTextSel ) >-{ >- SetSelection( rTextSel, mpImpl->mbAutoScroll ); >-} >- >-const TextSelection& TextView::GetSelection() const >-{ >- return mpImpl->maSelection; >-} >-TextSelection& TextView::GetSelection() >-{ >- return mpImpl->maSelection; >-} >- >-void TextView::DeleteSelected() >-{ >-// HideSelection(); >- >- mpImpl->mpTextEngine->UndoActionStart(); >- TextPaM aPaM = mpImpl->mpTextEngine->ImpDeleteText( mpImpl->maSelection ); >- mpImpl->mpTextEngine->UndoActionEnd(); >- >- ImpSetSelection( aPaM ); >- mpImpl->mpTextEngine->FormatAndUpdate( this ); >- ShowCursor(); >-} >- >-void TextView::ImpPaint( OutputDevice* pOut, const Point& rStartPos, Rectangle const* pPaintArea, TextSelection const* pPaintRange, TextSelection const* pSelection ) >-{ >- if ( !mpImpl->mbPaintSelection ) >- pSelection = NULL; >- else >- { >- // Richtige Hintergrundfarbe einstellen. >- // Ich bekomme leider nicht mit, ob sich diese inzwischen geaendert hat. >- Font aFont = mpImpl->mpTextEngine->GetFont(); >- Color aColor = pOut->GetBackground().GetColor(); >- aColor.SetTransparency( 0 ); >- if ( aColor != aFont.GetFillColor() ) >- { >- if( aFont.IsTransparent() ) >- aColor = Color( COL_TRANSPARENT ); >- aFont.SetFillColor( aColor ); >- mpImpl->mpTextEngine->maFont = aFont; >- } >- } >- >- mpImpl->mpTextEngine->ImpPaint( pOut, rStartPos, pPaintArea, pPaintRange, pSelection ); >-} >- >-void TextView::Paint( const Rectangle& rRect ) >-{ >- ImpPaint( rRect, sal_False ); >-} >- >-void TextView::ImpPaint( const Rectangle& rRect, sal_Bool bUseVirtDev ) >-{ >- if ( !mpImpl->mpTextEngine->GetUpdateMode() || mpImpl->mpTextEngine->IsInUndo() ) >- return; >- >- TextSelection *pDrawSelection = NULL; >- if ( !mpImpl->mbHighlightSelection && mpImpl->maSelection.HasRange() ) >- pDrawSelection = &mpImpl->maSelection; >- >- if ( bUseVirtDev ) >- { >- VirtualDevice* pVDev = GetVirtualDevice(); >- >- const Color& rBackgroundColor = mpImpl->mpWindow->GetBackground().GetColor(); >- if ( pVDev->GetFillColor() != rBackgroundColor ) >- pVDev->SetFillColor( rBackgroundColor ); >- if ( pVDev->GetBackground().GetColor() != rBackgroundColor ) >- pVDev->SetBackground( rBackgroundColor ); >- >- sal_Bool bVDevValid = sal_True; >- Size aOutSz( pVDev->GetOutputSizePixel() ); >- if ( ( aOutSz.Width() < rRect.GetWidth() ) || >- ( aOutSz.Height() < rRect.GetHeight() ) ) >- { >- bVDevValid = pVDev->SetOutputSizePixel( rRect.GetSize() ); >- } >- else >- { >- // Das VirtDev kann bei einem Resize sehr gross werden => >- // irgendwann mal kleiner machen! >- if ( ( aOutSz.Height() > ( rRect.GetHeight() + 20 ) ) || >- ( aOutSz.Width() > ( rRect.GetWidth() + 20 ) ) ) >- { >- bVDevValid = pVDev->SetOutputSizePixel( rRect.GetSize() ); >- } >- else >- { >- pVDev->Erase(); >- } >- } >- if ( !bVDevValid ) >- { >- ImpPaint( rRect, sal_False /* ohne VDev */ ); >- return; >- } >- >- Rectangle aTmpRec( Point( 0, 0 ), rRect.GetSize() ); >- >- Point aDocPos( mpImpl->maStartDocPos.X(), mpImpl->maStartDocPos.Y() + rRect.Top() ); >- Point aStartPos = ImpGetOutputStartPos( aDocPos ); >- ImpPaint( pVDev, aStartPos, &aTmpRec, NULL, pDrawSelection ); >- mpImpl->mpWindow->DrawOutDev( rRect.TopLeft(), rRect.GetSize(), >- Point(0,0), rRect.GetSize(), *pVDev ); >-// ShowSelection(); >- if ( mpImpl->mbHighlightSelection ) >- ImpHighlight( mpImpl->maSelection ); >- } >- else >- { >- Point aStartPos = ImpGetOutputStartPos( mpImpl->maStartDocPos ); >- ImpPaint( mpImpl->mpWindow, aStartPos, &rRect, NULL, pDrawSelection ); >- >-// ShowSelection(); >- if ( mpImpl->mbHighlightSelection ) >- ImpHighlight( mpImpl->maSelection ); >- } >-} >- >-void TextView::ImpHighlight( const TextSelection& rSel ) >-{ >- TextSelection aSel( rSel ); >- aSel.Justify(); >- if ( aSel.HasRange() && !mpImpl->mpTextEngine->IsInUndo() && mpImpl->mpTextEngine->GetUpdateMode() ) >- { >- mpImpl->mpCursor->Hide(); >- >- DBG_ASSERT( !mpImpl->mpTextEngine->mpIdleFormatter->IsActive(), "ImpHighlight: Not formatted!" ); >- >- Rectangle aVisArea( mpImpl->maStartDocPos, mpImpl->mpWindow->GetOutputSizePixel() ); >- long nY = 0; >- sal_uLong nStartPara = aSel.GetStart().GetPara(); >- sal_uLong nEndPara = aSel.GetEnd().GetPara(); >- for ( sal_uLong nPara = 0; nPara <= nEndPara; nPara++ ) >- { >- long nParaHeight = (long)mpImpl->mpTextEngine->CalcParaHeight( nPara ); >- if ( ( nPara >= nStartPara ) && ( ( nY + nParaHeight ) > aVisArea.Top() ) ) >- { >- TEParaPortion* pTEParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( nPara ); >- sal_uInt16 nStartLine = 0; >- sal_uInt16 nEndLine = pTEParaPortion->GetLines().size() -1; >- if ( nPara == nStartPara ) >- nStartLine = pTEParaPortion->GetLineNumber( aSel.GetStart().GetIndex(), sal_False ); >- if ( nPara == nEndPara ) >- nEndLine = pTEParaPortion->GetLineNumber( aSel.GetEnd().GetIndex(), sal_True ); >- >- // ueber die Zeilen iterieren.... >- for ( sal_uInt16 nLine = nStartLine; nLine <= nEndLine; nLine++ ) >- { >- TextLine* pLine = pTEParaPortion->GetLines()[ nLine ]; >- sal_uInt16 nStartIndex = pLine->GetStart(); >- sal_uInt16 nEndIndex = pLine->GetEnd(); >- if ( ( nPara == nStartPara ) && ( nLine == nStartLine ) ) >- nStartIndex = aSel.GetStart().GetIndex(); >- if ( ( nPara == nEndPara ) && ( nLine == nEndLine ) ) >- nEndIndex = aSel.GetEnd().GetIndex(); >- >- // Kann passieren, wenn am Anfang einer umgebrochenen Zeile. >- if ( nEndIndex < nStartIndex ) >- nEndIndex = nStartIndex; >- >- Rectangle aTmpRec( mpImpl->mpTextEngine->GetEditCursor( TextPaM( nPara, nStartIndex ), sal_False ) ); >- aTmpRec.Top() += nY; >- aTmpRec.Bottom() += nY; >- Point aTopLeft( aTmpRec.TopLeft() ); >- >- aTmpRec = mpImpl->mpTextEngine->GetEditCursor( TextPaM( nPara, nEndIndex ), sal_True ); >- aTmpRec.Top() += nY; >- aTmpRec.Bottom() += nY; >- Point aBottomRight( aTmpRec.BottomRight() ); >- aBottomRight.X()--; >- >- // Nur Painten, wenn im sichtbaren Bereich... >- if ( ( aTopLeft.X() < aBottomRight.X() ) && ( aBottomRight.Y() >= aVisArea.Top() ) ) >- { >- Point aPnt1( GetWindowPos( aTopLeft ) ); >- Point aPnt2( GetWindowPos( aBottomRight ) ); >- >- Rectangle aRect( aPnt1, aPnt2 ); >- mpImpl->mpWindow->Invert( aRect ); >- } >- } >- } >- nY += nParaHeight; >- >- if ( nY >= aVisArea.Bottom() ) >- break; >- } >- } >-} >- >-void TextView::ImpSetSelection( const TextSelection& rSelection ) >-{ >- if ( rSelection != mpImpl->maSelection ) >- { >- mpImpl->maSelection = rSelection; >- mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_VIEWSELECTIONCHANGED ) ); >- } >-} >- >-void TextView::ShowSelection() >-{ >- ImpShowHideSelection( sal_True ); >-} >- >-void TextView::HideSelection() >-{ >- ImpShowHideSelection( sal_False ); >-} >- >-void TextView::ShowSelection( const TextSelection& rRange ) >-{ >- ImpShowHideSelection( sal_True, &rRange ); >-} >- >-void TextView::ImpShowHideSelection( sal_Bool bShow, const TextSelection* pRange ) >-{ >- const TextSelection* pRangeOrSelection = pRange ? pRange : &mpImpl->maSelection; >- >- if ( pRangeOrSelection->HasRange() ) >- { >- if ( mpImpl->mbHighlightSelection ) >- { >- ImpHighlight( *pRangeOrSelection ); >- } >- else >- { >- if( mpImpl->mpWindow->IsPaintTransparent() ) >- mpImpl->mpWindow->Invalidate(); >- else >- { >- Rectangle aOutArea( Point( 0, 0 ), mpImpl->mpWindow->GetOutputSizePixel() ); >- Point aStartPos( ImpGetOutputStartPos( mpImpl->maStartDocPos ) ); >- TextSelection aRange( *pRangeOrSelection ); >- aRange.Justify(); >- sal_Bool bVisCursor = mpImpl->mpCursor->IsVisible(); >- mpImpl->mpCursor->Hide(); >- ImpPaint( mpImpl->mpWindow, aStartPos, &aOutArea, &aRange, bShow ? &mpImpl->maSelection : NULL ); >- if ( bVisCursor ) >- mpImpl->mpCursor->Show(); >- } >- } >- } >-} >- >-VirtualDevice* TextView::GetVirtualDevice() >-{ >- if ( !mpImpl->mpVirtDev ) >- { >- mpImpl->mpVirtDev = new VirtualDevice; >- mpImpl->mpVirtDev->SetLineColor(); >- } >- return mpImpl->mpVirtDev; >-} >- >-void TextView::EraseVirtualDevice() >-{ >- delete mpImpl->mpVirtDev; >- mpImpl->mpVirtDev = 0; >-} >- >-sal_Bool TextView::KeyInput( const KeyEvent& rKeyEvent ) >-{ >- sal_Bool bDone = sal_True; >- sal_Bool bModified = sal_False; >- sal_Bool bMoved = sal_False; >- sal_Bool bEndKey = sal_False; // spezielle CursorPosition >- sal_Bool bAllowIdle = sal_True; >- >- // Um zu pruefen ob durch irgendeine Aktion mModified, das lokale >- // bModified wird z.B. bei Cut/Paste nicht gesetzt, weil dort an anderen >- // Stellen das updaten erfolgt. >- sal_Bool bWasModified = mpImpl->mpTextEngine->IsModified(); >- mpImpl->mpTextEngine->SetModified( sal_False ); >- >- TextSelection aCurSel( mpImpl->maSelection ); >- TextSelection aOldSel( aCurSel ); >- >- sal_uInt16 nCode = rKeyEvent.GetKeyCode().GetCode(); >- KeyFuncType eFunc = rKeyEvent.GetKeyCode().GetFunction(); >- if ( eFunc != KEYFUNC_DONTKNOW ) >- { >- switch ( eFunc ) >- { >- case KEYFUNC_CUT: >- { >- if ( !mpImpl->mbReadOnly ) >- Cut(); >- } >- break; >- case KEYFUNC_COPY: >- { >- Copy(); >- } >- break; >- case KEYFUNC_PASTE: >- { >- if ( !mpImpl->mbReadOnly ) >- Paste(); >- } >- break; >- case KEYFUNC_UNDO: >- { >- if ( !mpImpl->mbReadOnly ) >- Undo(); >- } >- break; >- case KEYFUNC_REDO: >- { >- if ( !mpImpl->mbReadOnly ) >- Redo(); >- } >- break; >- >- default: // wird dann evtl. unten bearbeitet. >- eFunc = KEYFUNC_DONTKNOW; >- } >- } >- if ( eFunc == KEYFUNC_DONTKNOW ) >- { >- switch ( nCode ) >- { >- 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 ) ) >- && !( rKeyEvent.GetKeyCode().IsMod1() && ( nCode == KEY_PAGEUP || nCode == KEY_PAGEDOWN ) ) ) >- { >- aCurSel = ImpMoveCursor( rKeyEvent ); >- if ( aCurSel.HasRange() ) { >- uno::Reference<datatransfer::clipboard::XClipboard> aSelection(GetWindow()->GetPrimarySelection()); >- Copy( aSelection ); >- } >- bMoved = sal_True; >- if ( nCode == KEY_END ) >- bEndKey = sal_True; >- } >- else >- bDone = sal_False; >- } >- 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_LINE: >- case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE: >- { >- if ( !mpImpl->mbReadOnly && !rKeyEvent.GetKeyCode().IsMod2() ) >- { >- sal_uInt8 nDel = ( nCode == KEY_DELETE ) ? DEL_RIGHT : DEL_LEFT; >- sal_uInt8 nMode = rKeyEvent.GetKeyCode().IsMod1() ? DELMODE_RESTOFWORD : DELMODE_SIMPLE; >- if ( ( nMode == DELMODE_RESTOFWORD ) && rKeyEvent.GetKeyCode().IsShift() ) >- nMode = DELMODE_RESTOFCONTENT; >- >- switch( nCode ) >- { >- case com::sun::star::awt::Key::DELETE_WORD_BACKWARD: >- nDel = DEL_LEFT; >- nMode = DELMODE_RESTOFWORD; >- break; >- case com::sun::star::awt::Key::DELETE_WORD_FORWARD: >- nDel = DEL_RIGHT; >- nMode = DELMODE_RESTOFWORD; >- break; >- case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE: >- nDel = DEL_LEFT; >- nMode = DELMODE_RESTOFCONTENT; >- break; >- case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE: >- nDel = DEL_RIGHT; >- nMode = DELMODE_RESTOFCONTENT; >- break; >- default: break; >- } >- >- mpImpl->mpTextEngine->UndoActionStart(); >- if(mpImpl->mbSupportProtectAttribute) >- { >- //expand selection to include all protected content - if there is any >- const TextCharAttrib* pStartAttr = mpImpl->mpTextEngine->FindCharAttrib( >- TextPaM(mpImpl->maSelection.GetStart().GetPara(), >- mpImpl->maSelection.GetStart().GetIndex()), >- TEXTATTR_PROTECTED ); >- const TextCharAttrib* pEndAttr = mpImpl->mpTextEngine->FindCharAttrib( >- TextPaM(mpImpl->maSelection.GetEnd().GetPara(), >- mpImpl->maSelection.GetEnd().GetIndex()), >- TEXTATTR_PROTECTED ); >- if(pStartAttr && pStartAttr->GetStart() < mpImpl->maSelection.GetStart().GetIndex()) >- { >- mpImpl->maSelection.GetStart().GetIndex() = pStartAttr->GetStart(); >- } >- if(pEndAttr && pEndAttr->GetEnd() > mpImpl->maSelection.GetEnd().GetIndex()) >- { >- mpImpl->maSelection.GetEnd().GetIndex() = pEndAttr->GetEnd(); >- } >- } >- aCurSel = ImpDelete( nDel, nMode ); >- mpImpl->mpTextEngine->UndoActionEnd(); >- bModified = sal_True; >- bAllowIdle = sal_False; >- } >- else >- bDone = sal_False; >- } >- break; >- case KEY_TAB: >- { >- if ( !mpImpl->mbReadOnly && !rKeyEvent.GetKeyCode().IsShift() && >- !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() && >- ImplCheckTextLen( rtl::OUString('x') ) ) >- { >- aCurSel = mpImpl->mpTextEngine->ImpInsertText( aCurSel, '\t', !IsInsertMode() ); >- bModified = sal_True; >- } >- else >- bDone = sal_False; >- } >- break; >- case KEY_RETURN: >- { >- // Shift-RETURN darf nicht geschluckt werden, weil dann keine >- // mehrzeilige Eingabe in Dialogen/Property-Editor moeglich. >- if ( !mpImpl->mbReadOnly && !rKeyEvent.GetKeyCode().IsMod1() && >- !rKeyEvent.GetKeyCode().IsMod2() && ImplCheckTextLen( rtl::OUString('x') ) ) >- { >- mpImpl->mpTextEngine->UndoActionStart(); >- aCurSel = mpImpl->mpTextEngine->ImpInsertParaBreak( aCurSel ); >- if ( mpImpl->mbAutoIndent ) >- { >- TextNode* pPrev = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aCurSel.GetEnd().GetPara() - 1 ); >- sal_uInt16 n = 0; >- while ( ( n < pPrev->GetText().Len() ) && ( >- ( pPrev->GetText().GetChar( n ) == ' ' ) || >- ( pPrev->GetText().GetChar( n ) == '\t' ) ) ) >- { >- n++; >- } >- if ( n ) >- aCurSel = mpImpl->mpTextEngine->ImpInsertText( aCurSel, pPrev->GetText().Copy( 0, n ) ); >- } >- mpImpl->mpTextEngine->UndoActionEnd(); >- bModified = sal_True; >- } >- else >- bDone = sal_False; >- } >- break; >- case KEY_INSERT: >- { >- if ( !mpImpl->mbReadOnly ) >- SetInsertMode( !IsInsertMode() ); >- } >- break; >- default: >- { >- if ( TextEngine::IsSimpleCharInput( rKeyEvent ) ) >- { >- xub_Unicode nCharCode = rKeyEvent.GetCharCode(); >- if ( !mpImpl->mbReadOnly && ImplCheckTextLen( rtl::OUString(nCharCode) ) ) // sonst trotzdem das Zeichen schlucken... >- { >- aCurSel = mpImpl->mpTextEngine->ImpInsertText( nCharCode, aCurSel, !IsInsertMode(), sal_True ); >- bModified = sal_True; >- } >- } >- else >- bDone = sal_False; >- } >- } >- } >- >- if ( aCurSel != aOldSel ) // Check if changed, maybe other method already changed mpImpl->maSelection, don't overwrite that! >- ImpSetSelection( aCurSel ); >- >- mpImpl->mpTextEngine->UpdateSelections(); >- >- if ( ( nCode != KEY_UP ) && ( nCode != KEY_DOWN ) ) >- mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW; >- >- if ( bModified ) >- { >- // Idle-Formatter nur, wenn AnyInput. >- if ( bAllowIdle && Application::AnyInput( VCL_INPUT_KEYBOARD) ) >- mpImpl->mpTextEngine->IdleFormatAndUpdate( this ); >- else >- mpImpl->mpTextEngine->FormatAndUpdate( this); >- } >- else if ( bMoved ) >- { >- // Selection wird jetzt gezielt in ImpMoveCursor gemalt. >- ImpShowCursor( mpImpl->mbAutoScroll, sal_True, bEndKey ); >- } >- >- if ( mpImpl->mpTextEngine->IsModified() ) >- mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) ); >- else if ( bWasModified ) >- mpImpl->mpTextEngine->SetModified( sal_True ); >- >- return bDone; >-} >- >-void TextView::MouseButtonUp( const MouseEvent& rMouseEvent ) >-{ >- mpImpl->mbClickedInSelection = sal_False; >- mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW; >- mpImpl->mpSelEngine->SelMouseButtonUp( rMouseEvent ); >- if ( rMouseEvent.IsMiddle() && !IsReadOnly() && >- ( GetWindow()->GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION ) ) >- { >- uno::Reference<datatransfer::clipboard::XClipboard> aSelection(GetWindow()->GetPrimarySelection()); >- Paste( aSelection ); >- if ( mpImpl->mpTextEngine->IsModified() ) >- mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) ); >- } >- else if ( rMouseEvent.IsLeft() && GetSelection().HasRange() ) >- { >- uno::Reference<datatransfer::clipboard::XClipboard> aSelection(GetWindow()->GetPrimarySelection()); >- Copy( aSelection ); >- } >-} >- >-void TextView::MouseButtonDown( const MouseEvent& rMouseEvent ) >-{ >- mpImpl->mpTextEngine->CheckIdleFormatter(); // Falls schnelles Tippen und MouseButtonDown >- mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW; >- mpImpl->mbClickedInSelection = IsSelectionAtPoint( rMouseEvent.GetPosPixel() ); >- >- mpImpl->mpTextEngine->SetActiveView( this ); >- >- mpImpl->mpSelEngine->SelMouseButtonDown( rMouseEvent ); >- >- // mbu 20.01.2005 - SelMouseButtonDown() possibly triggers a 'selection changed' >- // notification. The appropriate handler could change the current selection, >- // which is the case in the MailMerge address block control. To enable select'n'drag >- // we need to reevaluate the selection after the notification has been fired. >- mpImpl->mbClickedInSelection = IsSelectionAtPoint( rMouseEvent.GetPosPixel() ); >- >- // Sonderbehandlungen >- if ( !rMouseEvent.IsShift() && ( rMouseEvent.GetClicks() >= 2 ) ) >- { >- if ( rMouseEvent.IsMod2() ) >- { >- HideSelection(); >- ImpSetSelection( mpImpl->maSelection.GetEnd() ); >- SetCursorAtPoint( rMouseEvent.GetPosPixel() ); // Wird von SelectionEngine bei MOD2 nicht gesetzt >- } >- >- if ( rMouseEvent.GetClicks() == 2 ) >- { >- // Wort selektieren >- if ( mpImpl->maSelection.GetEnd().GetIndex() < mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection.GetEnd().GetPara() ) ) >- { >- HideSelection(); >- TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( mpImpl->maSelection.GetEnd().GetPara() ); >- uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator(); >- i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True ); >- TextSelection aNewSel( mpImpl->maSelection ); >- aNewSel.GetStart().GetIndex() = (sal_uInt16)aBoundary.startPos; >- aNewSel.GetEnd().GetIndex() = (sal_uInt16)aBoundary.endPos; >- if(mpImpl->mbSupportProtectAttribute) >- { >- //expand selection to include all protected content - if there is any >- const TextCharAttrib* pStartAttr = mpImpl->mpTextEngine->FindCharAttrib( >- TextPaM(aNewSel.GetStart().GetPara(), >- (sal_uInt16)aBoundary.startPos), >- TEXTATTR_PROTECTED ); >- const TextCharAttrib* pEndAttr = mpImpl->mpTextEngine->FindCharAttrib( >- TextPaM(aNewSel.GetEnd().GetPara(), >- (sal_uInt16)aBoundary.endPos), >- TEXTATTR_PROTECTED ); >- if(pStartAttr && pStartAttr->GetStart() < aNewSel.GetStart().GetIndex()) >- { >- aNewSel.GetStart().GetIndex() = pStartAttr->GetStart(); >- } >- if(pEndAttr && pEndAttr->GetEnd() > aNewSel.GetEnd().GetIndex()) >- { >- aNewSel.GetEnd().GetIndex() = pEndAttr->GetEnd(); >- } >- } >- ImpSetSelection( aNewSel ); >- ShowSelection(); >- ShowCursor( sal_True, sal_True ); >- } >- } >- else if ( rMouseEvent.GetClicks() == 3 ) >- { >- // Absatz selektieren >- if ( mpImpl->maSelection.GetStart().GetIndex() || ( mpImpl->maSelection.GetEnd().GetIndex() < mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection.GetEnd().GetPara() ) ) ) >- { >- HideSelection(); >- TextSelection aNewSel( mpImpl->maSelection ); >- aNewSel.GetStart().GetIndex() = 0; >- aNewSel.GetEnd().GetIndex() = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( mpImpl->maSelection.GetEnd().GetPara() )->GetText().Len(); >- ImpSetSelection( aNewSel ); >- ShowSelection(); >- ShowCursor( sal_True, sal_True ); >- } >- } >- } >-} >- >- >-void TextView::MouseMove( const MouseEvent& rMouseEvent ) >-{ >- mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW; >- mpImpl->mpSelEngine->SelMouseMove( rMouseEvent ); >-} >- >-void TextView::Command( const CommandEvent& rCEvt ) >-{ >- mpImpl->mpTextEngine->CheckIdleFormatter(); // Falls schnelles Tippen und MouseButtonDown >- mpImpl->mpTextEngine->SetActiveView( this ); >- >- if ( rCEvt.GetCommand() == COMMAND_STARTEXTTEXTINPUT ) >- { >- DeleteSelected(); >- delete mpImpl->mpTextEngine->mpIMEInfos; >- TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( GetSelection().GetEnd().GetPara() ); >- mpImpl->mpTextEngine->mpIMEInfos = new TEIMEInfos( GetSelection().GetEnd(), pNode->GetText().Copy( GetSelection().GetEnd().GetIndex() ) ); >- mpImpl->mpTextEngine->mpIMEInfos->bWasCursorOverwrite = !IsInsertMode(); >- } >- else if ( rCEvt.GetCommand() == COMMAND_ENDEXTTEXTINPUT ) >- { >- DBG_ASSERT( mpImpl->mpTextEngine->mpIMEInfos, "COMMAND_ENDEXTTEXTINPUT => Kein Start ?" ); >- if( mpImpl->mpTextEngine->mpIMEInfos ) >- { >- TEParaPortion* pPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetPara() ); >- pPortion->MarkSelectionInvalid( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetIndex(), 0 ); >- >- sal_Bool bInsertMode = !mpImpl->mpTextEngine->mpIMEInfos->bWasCursorOverwrite; >- >- delete mpImpl->mpTextEngine->mpIMEInfos; >- mpImpl->mpTextEngine->mpIMEInfos = NULL; >- >- mpImpl->mpTextEngine->FormatAndUpdate( this ); >- >- SetInsertMode( bInsertMode ); >- >- if ( mpImpl->mpTextEngine->IsModified() ) >- mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) ); >- } >- } >- else if ( rCEvt.GetCommand() == COMMAND_EXTTEXTINPUT ) >- { >- DBG_ASSERT( mpImpl->mpTextEngine->mpIMEInfos, "COMMAND_EXTTEXTINPUT => Kein Start ?" ); >- if( mpImpl->mpTextEngine->mpIMEInfos ) >- { >- const CommandExtTextInputData* pData = rCEvt.GetExtTextInputData(); >- >- if ( !pData->IsOnlyCursorChanged() ) >- { >- TextSelection aSelect( mpImpl->mpTextEngine->mpIMEInfos->aPos ); >- aSelect.GetEnd().GetIndex() = aSelect.GetEnd().GetIndex() + mpImpl->mpTextEngine->mpIMEInfos->nLen; >- aSelect = mpImpl->mpTextEngine->ImpDeleteText( aSelect ); >- aSelect = mpImpl->mpTextEngine->ImpInsertText( aSelect, pData->GetText() ); >- >- if ( mpImpl->mpTextEngine->mpIMEInfos->bWasCursorOverwrite ) >- { >- sal_uInt16 nOldIMETextLen = mpImpl->mpTextEngine->mpIMEInfos->nLen; >- sal_uInt16 nNewIMETextLen = pData->GetText().Len(); >- >- if ( ( nOldIMETextLen > nNewIMETextLen ) && >- ( nNewIMETextLen < mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.Len() ) ) >- { >- // restore old characters >- sal_uInt16 nRestore = nOldIMETextLen - nNewIMETextLen; >- TextPaM aPaM( mpImpl->mpTextEngine->mpIMEInfos->aPos ); >- aPaM.GetIndex() = aPaM.GetIndex() + nNewIMETextLen; >- mpImpl->mpTextEngine->ImpInsertText( aPaM, mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.Copy( nNewIMETextLen, nRestore ) ); >- } >- else if ( ( nOldIMETextLen < nNewIMETextLen ) && >- ( nOldIMETextLen < mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.Len() ) ) >- { >- // overwrite >- sal_uInt16 nOverwrite = nNewIMETextLen - nOldIMETextLen; >- if ( ( nOldIMETextLen + nOverwrite ) > mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.Len() ) >- nOverwrite = mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.Len() - nOldIMETextLen; >- DBG_ASSERT( nOverwrite && (nOverwrite < 0xFF00), "IME Overwrite?!" ); >- TextPaM aPaM( mpImpl->mpTextEngine->mpIMEInfos->aPos ); >- aPaM.GetIndex() = aPaM.GetIndex() + nNewIMETextLen; >- TextSelection aSel( aPaM ); >- aSel.GetEnd().GetIndex() = >- aSel.GetEnd().GetIndex() + nOverwrite; >- mpImpl->mpTextEngine->ImpDeleteText( aSel ); >- } >- } >- >- if ( pData->GetTextAttr() ) >- { >- mpImpl->mpTextEngine->mpIMEInfos->CopyAttribs( pData->GetTextAttr(), pData->GetText().Len() ); >- mpImpl->mpTextEngine->mpIMEInfos->bCursor = pData->IsCursorVisible(); >- } >- else >- { >- mpImpl->mpTextEngine->mpIMEInfos->DestroyAttribs(); >- } >- >- TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetPara() ); >- pPPortion->MarkSelectionInvalid( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetIndex(), 0 ); >- mpImpl->mpTextEngine->FormatAndUpdate( this ); >- } >- >- TextSelection aNewSel = TextPaM( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetPara(), mpImpl->mpTextEngine->mpIMEInfos->aPos.GetIndex()+pData->GetCursorPos() ); >- SetSelection( aNewSel ); >- SetInsertMode( !pData->IsCursorOverwrite() ); >- >- if ( pData->IsCursorVisible() ) >- ShowCursor(); >- else >- HideCursor(); >- } >- } >- else if ( rCEvt.GetCommand() == COMMAND_CURSORPOS ) >- { >- if ( mpImpl->mpTextEngine->mpIMEInfos && mpImpl->mpTextEngine->mpIMEInfos->nLen ) >- { >- TextPaM aPaM( GetSelection().GetEnd() ); >- Rectangle aR1 = mpImpl->mpTextEngine->PaMtoEditCursor( aPaM ); >- >- sal_uInt16 nInputEnd = mpImpl->mpTextEngine->mpIMEInfos->aPos.GetIndex() + mpImpl->mpTextEngine->mpIMEInfos->nLen; >- >- if ( !mpImpl->mpTextEngine->IsFormatted() ) >- mpImpl->mpTextEngine->FormatDoc(); >- >- TEParaPortion* pParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() ); >- sal_uInt16 nLine = pParaPortion->GetLineNumber( aPaM.GetIndex(), sal_True ); >- TextLine* pLine = pParaPortion->GetLines()[ nLine ]; >- if ( pLine && ( nInputEnd > pLine->GetEnd() ) ) >- nInputEnd = pLine->GetEnd(); >- Rectangle aR2 = mpImpl->mpTextEngine->PaMtoEditCursor( TextPaM( aPaM.GetPara(), nInputEnd ) ); >- >- long nWidth = aR2.Left()-aR1.Right(); >- aR1.Move( -GetStartDocPos().X(), -GetStartDocPos().Y() ); >- GetWindow()->SetCursorRect( &aR1, nWidth ); >- } >- else >- { >- GetWindow()->SetCursorRect(); >- } >- } >- else >- { >- mpImpl->mpSelEngine->Command( rCEvt ); >- } >-} >- >-void TextView::ShowCursor( sal_Bool bGotoCursor, sal_Bool bForceVisCursor ) >-{ >- // Die Einstellung hat mehr Gewicht: >- if ( !mpImpl->mbAutoScroll ) >- bGotoCursor = sal_False; >- ImpShowCursor( bGotoCursor, bForceVisCursor, sal_False ); >-} >- >-void TextView::HideCursor() >-{ >- mpImpl->mpCursor->Hide(); >-} >- >-void TextView::Scroll( long ndX, long ndY ) >-{ >- DBG_ASSERT( mpImpl->mpTextEngine->IsFormatted(), "Scroll: Nicht formatiert!" ); >- >- if ( !ndX && !ndY ) >- return; >- >- Point aNewStartPos( mpImpl->maStartDocPos ); >- >- // Vertical: >- aNewStartPos.Y() -= ndY; >- if ( aNewStartPos.Y() < 0 ) >- aNewStartPos.Y() = 0; >- >- // Horizontal: >- aNewStartPos.X() -= ndX; >- if ( aNewStartPos.X() < 0 ) >- aNewStartPos.X() = 0; >- >- long nDiffX = mpImpl->maStartDocPos.X() - aNewStartPos.X(); >- long nDiffY = mpImpl->maStartDocPos.Y() - aNewStartPos.Y(); >- >- if ( nDiffX || nDiffY ) >- { >- sal_Bool bVisCursor = mpImpl->mpCursor->IsVisible(); >- mpImpl->mpCursor->Hide(); >- mpImpl->mpWindow->Update(); >- mpImpl->maStartDocPos = aNewStartPos; >- >- if ( mpImpl->mpTextEngine->IsRightToLeft() ) >- nDiffX = -nDiffX; >- mpImpl->mpWindow->Scroll( nDiffX, nDiffY ); >- mpImpl->mpWindow->Update(); >- mpImpl->mpCursor->SetPos( mpImpl->mpCursor->GetPos() + Point( nDiffX, nDiffY ) ); >- if ( bVisCursor && !mpImpl->mbReadOnly ) >- mpImpl->mpCursor->Show(); >- } >- >- mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_VIEWSCROLLED ) ); >-} >- >-void TextView::Undo() >-{ >- mpImpl->mpTextEngine->SetActiveView( this ); >- mpImpl->mpTextEngine->GetUndoManager().Undo(); >-} >- >-void TextView::Redo() >-{ >- mpImpl->mpTextEngine->SetActiveView( this ); >- mpImpl->mpTextEngine->GetUndoManager().Redo(); >-} >- >-void TextView::Cut() >-{ >- mpImpl->mpTextEngine->UndoActionStart(); >- Copy(); >- DeleteSelected(); >- mpImpl->mpTextEngine->UndoActionEnd(); >-} >- >-void TextView::Copy( uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard ) >-{ >- if ( rxClipboard.is() ) >- { >- TETextDataObject* pDataObj = new TETextDataObject( GetSelected() ); >- >- if ( mpImpl->mpTextEngine->HasAttrib( TEXTATTR_HYPERLINK ) ) // Dann auch als HTML >- mpImpl->mpTextEngine->Write( pDataObj->GetHTMLStream(), &mpImpl->maSelection, sal_True ); >- >- const sal_uInt32 nRef = Application::ReleaseSolarMutex(); >- >- try >- { >- rxClipboard->setContents( pDataObj, NULL ); >- >- 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 ); >- } >-} >- >-void TextView::Copy() >-{ >- uno::Reference<datatransfer::clipboard::XClipboard> aClipboard(GetWindow()->GetClipboard()); >- Copy( aClipboard ); >-} >- >-void TextView::Paste( uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard ) >-{ >- 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() ) >- { >- datatransfer::DataFlavor aFlavor; >- SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor ); >- if ( xDataObj->isDataFlavorSupported( aFlavor ) ) >- { >- try >- { >- uno::Any aData = xDataObj->getTransferData( aFlavor ); >- ::rtl::OUString aText; >- aData >>= aText; >- bool bWasTruncated = false; >- if( mpImpl->mpTextEngine->GetMaxTextLen() != 0 ) >- bWasTruncated = ImplTruncateNewText( aText ); >- InsertNewText( aText, sal_False ); >- mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) ); >- >- if( bWasTruncated ) >- Edit::ShowTruncationWarning( mpImpl->mpWindow ); >- } >- catch( const ::com::sun::star::datatransfer::UnsupportedFlavorException& ) >- { >- } >- } >- } >- } >-} >- >-void TextView::Paste() >-{ >- uno::Reference<datatransfer::clipboard::XClipboard> aClipboard(GetWindow()->GetClipboard()); >- Paste( aClipboard ); >-} >- >-String TextView::GetSelected() >-{ >- return GetSelected( GetSystemLineEnd() ); >-} >- >-String TextView::GetSelected( LineEnd aSeparator ) >-{ >- return mpImpl->mpTextEngine->GetText( mpImpl->maSelection, aSeparator ); >-} >- >-void TextView::SetInsertMode( sal_Bool bInsert ) >-{ >- if ( mpImpl->mbInsertMode != bInsert ) >- { >- mpImpl->mbInsertMode = bInsert; >- ShowCursor( mpImpl->mbAutoScroll, sal_False ); >- } >-} >- >-void TextView::SetReadOnly( sal_Bool bReadOnly ) >-{ >- if ( mpImpl->mbReadOnly != bReadOnly ) >- { >- mpImpl->mbReadOnly = bReadOnly; >- if ( !mpImpl->mbReadOnly ) >- ShowCursor( mpImpl->mbAutoScroll, sal_False ); >- else >- HideCursor(); >- >- GetWindow()->SetInputContext( InputContext( mpImpl->mpTextEngine->GetFont(), bReadOnly ? INPUTCONTEXT_TEXT|INPUTCONTEXT_EXTTEXTINPUT : 0 ) ); >- } >-} >- >-TextSelection TextView::ImpMoveCursor( const KeyEvent& rKeyEvent ) >-{ >- // Eigentlich nur bei Up/Down noetig, aber was solls. >- mpImpl->mpTextEngine->CheckIdleFormatter(); >- >- TextPaM aPaM( mpImpl->maSelection.GetEnd() ); >- TextPaM aOldEnd( aPaM ); >- >- TextDirectionality eTextDirection = TextDirectionality_LeftToRight_TopToBottom; >- if ( mpImpl->mpTextEngine->IsRightToLeft() ) >- eTextDirection = TextDirectionality_RightToLeft_TopToBottom; >- >- KeyEvent aTranslatedKeyEvent = rKeyEvent.LogicalTextDirectionality( eTextDirection ); >- >- sal_Bool bCtrl = aTranslatedKeyEvent.GetKeyCode().IsMod1() ? sal_True : sal_False; >- sal_uInt16 nCode = aTranslatedKeyEvent.GetKeyCode().GetCode(); >- >- bool bSelect = aTranslatedKeyEvent.GetKeyCode().IsShift(); >- switch ( nCode ) >- { >- case KEY_UP: aPaM = CursorUp( aPaM ); >- break; >- case KEY_DOWN: aPaM = CursorDown( aPaM ); >- 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 ); >- break; >- case KEY_PAGEDOWN: aPaM = bCtrl ? CursorEndOfDoc() : PageDown( aPaM ); >- break; >- case KEY_LEFT: aPaM = bCtrl ? CursorWordLeft( aPaM ) : CursorLeft( aPaM, aTranslatedKeyEvent.GetKeyCode().IsMod2() ? (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER : (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL ); >- break; >- case KEY_RIGHT: aPaM = bCtrl ? CursorWordRight( aPaM ) : CursorRight( aPaM, aTranslatedKeyEvent.GetKeyCode().IsMod2() ? (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER : (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL ); >- break; >- case com::sun::star::awt::Key::SELECT_WORD_FORWARD: >- bSelect = true; // fallthrough intentional >- case com::sun::star::awt::Key::MOVE_WORD_FORWARD: >- aPaM = CursorWordRight( aPaM ); >- break; >- case com::sun::star::awt::Key::SELECT_WORD_BACKWARD: >- bSelect = true; // fallthrough intentional >- case com::sun::star::awt::Key::MOVE_WORD_BACKWARD: >- aPaM = CursorWordLeft( aPaM ); >- break; >- case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE: >- bSelect = true; // fallthrough intentional >- case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE: >- aPaM = CursorStartOfLine( aPaM ); >- break; >- case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE: >- bSelect = true; // fallthrough intentional >- case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE: >- aPaM = CursorEndOfLine( aPaM ); >- break; >- case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH: >- bSelect = true; // falltthrough intentional >- case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH: >- aPaM = CursorStartOfParagraph( aPaM ); >- break; >- case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH: >- bSelect = true; // falltthrough intentional >- case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH: >- aPaM = CursorEndOfParagraph( aPaM ); >- break; >- case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT: >- bSelect = true; // falltthrough intentional >- case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT: >- aPaM = CursorStartOfDoc(); >- break; >- case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT: >- bSelect = true; // falltthrough intentional >- case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT: >- aPaM = CursorEndOfDoc(); >- break; >- } >- >- // Bewirkt evtl. ein CreateAnchor oder Deselection all >- mpImpl->mpSelEngine->CursorPosChanging( bSelect, aTranslatedKeyEvent.GetKeyCode().IsMod1() ); >- >- if ( aOldEnd != aPaM ) >- { >- mpImpl->mpTextEngine->CursorMoved( aOldEnd.GetPara() ); >- >- TextSelection aNewSelection( mpImpl->maSelection ); >- aNewSelection.GetEnd() = aPaM; >- if ( bSelect ) >- { >- // Dann wird die Selektion erweitert... >- ImpSetSelection( aNewSelection ); >- ShowSelection( TextSelection( aOldEnd, aPaM ) ); >- } >- else >- { >- aNewSelection.GetStart() = aPaM; >- ImpSetSelection( aNewSelection ); >- } >- } >- >- return mpImpl->maSelection; >-} >- >-void TextView::InsertText( const XubString& rStr, sal_Bool bSelect ) >-{ >- InsertNewText( rStr, bSelect ); >-} >- >-void TextView::InsertNewText( const rtl::OUString& rStr, sal_Bool bSelect ) >-{ >-// HideSelection(); >- mpImpl->mpTextEngine->UndoActionStart(); >- >- /* #i87633# >- break inserted text into chunks that fit into the underlying String >- based API (which has a maximum length of 65534 elements >- >- note: this will of course still cause problems for lines longer than those >- 65534 elements, but those cases will hopefully be few. >- In the long run someone should switch the TextEngine to OUString instead of String >- */ >- sal_Int32 nLen = rStr.getLength(); >- sal_Int32 nPos = 0; >- do >- { >- sal_Int32 nChunkLen = nLen > 65534 ? 65534 : nLen; >- String aChunk( rStr.copy( nPos, nChunkLen ) ); >- >- TextSelection aNewSel( mpImpl->maSelection ); >- >- TextPaM aPaM = mpImpl->mpTextEngine->ImpInsertText( mpImpl->maSelection, aChunk ); >- >- if ( bSelect ) >- { >- aNewSel.Justify(); >- aNewSel.GetEnd() = aPaM; >- } >- else >- { >- aNewSel = aPaM; >- } >- >- ImpSetSelection( aNewSel ); >- nLen -= nChunkLen; >- nPos += nChunkLen; >- } >- while( nLen ); >- >- mpImpl->mpTextEngine->UndoActionEnd(); >- >- mpImpl->mpTextEngine->FormatAndUpdate( this ); >-} >- >-TextPaM TextView::CursorLeft( const TextPaM& rPaM, sal_uInt16 nCharacterIteratorMode ) >-{ >- TextPaM aPaM( rPaM ); >- >- if ( aPaM.GetIndex() ) >- { >- TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() ); >- uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator(); >- sal_Int32 nCount = 1; >- aPaM.GetIndex() = (sal_uInt16)xBI->previousCharacters( pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), nCharacterIteratorMode, nCount, nCount ); >- } >- else if ( aPaM.GetPara() ) >- { >- aPaM.GetPara()--; >- TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() ); >- aPaM.GetIndex() = pNode->GetText().Len(); >- } >- return aPaM; >-} >- >-TextPaM TextView::CursorRight( const TextPaM& rPaM, sal_uInt16 nCharacterIteratorMode ) >-{ >- TextPaM aPaM( rPaM ); >- >- TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() ); >- if ( aPaM.GetIndex() < pNode->GetText().Len() ) >- { >- uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator(); >- sal_Int32 nCount = 1; >- aPaM.GetIndex() = (sal_uInt16)xBI->nextCharacters( pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), nCharacterIteratorMode, nCount, nCount ); >- } >- else if ( aPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count()-1) ) >- { >- aPaM.GetPara()++; >- aPaM.GetIndex() = 0; >- } >- >- return aPaM; >-} >- >- >-TextPaM TextView::CursorWordLeft( const TextPaM& rPaM ) >-{ >- TextPaM aPaM( rPaM ); >- >- if ( aPaM.GetIndex() ) >- { >- TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() ); >- uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator(); >- i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), rPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True ); >- if ( aBoundary.startPos >= rPaM.GetIndex() ) >- aBoundary = xBI->previousWord( pNode->GetText(), rPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES ); >- aPaM.GetIndex() = ( aBoundary.startPos != -1 ) ? (sal_uInt16)aBoundary.startPos : 0; >- } >- else if ( aPaM.GetPara() ) >- { >- aPaM.GetPara()--; >- TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() ); >- aPaM.GetIndex() = pNode->GetText().Len(); >- } >- return aPaM; >-} >- >- >-TextPaM TextView::CursorWordRight( const TextPaM& rPaM ) >-{ >- TextPaM aPaM( rPaM ); >- >- TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() ); >- if ( aPaM.GetIndex() < pNode->GetText().Len() ) >- { >- uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator(); >- i18n::Boundary aBoundary = xBI->nextWord( pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES ); >- aPaM.GetIndex() = (sal_uInt16)aBoundary.startPos; >- } >- else if ( aPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count()-1) ) >- { >- aPaM.GetPara()++; >- aPaM.GetIndex() = 0; >- } >- >- return aPaM; >-} >- >-TextPaM TextView::ImpDelete( sal_uInt8 nMode, sal_uInt8 nDelMode ) >-{ >- if ( mpImpl->maSelection.HasRange() ) // dann nur Sel. loeschen >- return mpImpl->mpTextEngine->ImpDeleteText( mpImpl->maSelection ); >- >- TextPaM aStartPaM = mpImpl->maSelection.GetStart(); >- TextPaM aEndPaM = aStartPaM; >- if ( nMode == DEL_LEFT ) >- { >- if ( nDelMode == DELMODE_SIMPLE ) >- { >- aEndPaM = CursorLeft( aEndPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER ); >- } >- else if ( nDelMode == DELMODE_RESTOFWORD ) >- { >- TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() ); >- uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator(); >- i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True ); >- if ( aBoundary.startPos == mpImpl->maSelection.GetEnd().GetIndex() ) >- aBoundary = xBI->previousWord( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES ); >- // #i63506# startPos is -1 when the paragraph starts with a tab >- aEndPaM.GetIndex() = (aBoundary.startPos >= 0) ? (sal_uInt16)aBoundary.startPos : 0; >- } >- else // DELMODE_RESTOFCONTENT >- { >- if ( aEndPaM.GetIndex() != 0 ) >- aEndPaM.GetIndex() = 0; >- else if ( aEndPaM.GetPara() ) >- { >- // Absatz davor >- aEndPaM.GetPara()--; >- aEndPaM.GetIndex() = 0; >- } >- } >- } >- else >- { >- if ( nDelMode == DELMODE_SIMPLE ) >- { >- aEndPaM = CursorRight( aEndPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL ); >- } >- else if ( nDelMode == DELMODE_RESTOFWORD ) >- { >- TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() ); >- uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator(); >- i18n::Boundary aBoundary = xBI->nextWord( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES ); >- aEndPaM.GetIndex() = (sal_uInt16)aBoundary.startPos; >- } >- else // DELMODE_RESTOFCONTENT >- { >- TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() ); >- if ( aEndPaM.GetIndex() < pNode->GetText().Len() ) >- aEndPaM.GetIndex() = pNode->GetText().Len(); >- else if ( aEndPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1 ) ) >- { >- // Absatz danach >- aEndPaM.GetPara()++; >- TextNode* pNextNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() ); >- aEndPaM.GetIndex() = pNextNode->GetText().Len(); >- } >- } >- } >- >- return mpImpl->mpTextEngine->ImpDeleteText( TextSelection( aStartPaM, aEndPaM ) ); >-} >- >- >- >-TextPaM TextView::CursorUp( const TextPaM& rPaM ) >-{ >- TextPaM aPaM( rPaM ); >- >- long nX; >- if ( mpImpl->mnTravelXPos == TRAVEL_X_DONTKNOW ) >- { >- nX = mpImpl->mpTextEngine->GetEditCursor( rPaM, sal_False ).Left(); >- mpImpl->mnTravelXPos = (sal_uInt16)nX+1; >- } >- else >- nX = mpImpl->mnTravelXPos; >- >- TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() ); >- sal_uInt16 nLine = pPPortion->GetLineNumber( rPaM.GetIndex(), sal_False ); >- if ( nLine ) // gleicher Absatz >- { >- sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( rPaM.GetPara(), nLine-1, nX ); >- aPaM.GetIndex() = nCharPos; >- // 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 >- TextLine* pLine = pPPortion->GetLines()[ nLine - 1 ]; >- if ( aPaM.GetIndex() && ( aPaM.GetIndex() == pLine->GetEnd() ) ) >- aPaM.GetIndex()--; >- } >- else if ( rPaM.GetPara() ) // vorheriger Absatz >- { >- aPaM.GetPara()--; >- pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() ); >- sal_uInt16 nL = pPPortion->GetLines().size() - 1; >- sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( aPaM.GetPara(), nL, nX+1 ); >- aPaM.GetIndex() = nCharPos; >- } >- >- return aPaM; >-} >- >-TextPaM TextView::CursorDown( const TextPaM& rPaM ) >-{ >- TextPaM aPaM( rPaM ); >- >- long nX; >- if ( mpImpl->mnTravelXPos == TRAVEL_X_DONTKNOW ) >- { >- nX = mpImpl->mpTextEngine->GetEditCursor( rPaM, sal_False ).Left(); >- mpImpl->mnTravelXPos = (sal_uInt16)nX+1; >- } >- else >- nX = mpImpl->mnTravelXPos; >- >- TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() ); >- sal_uInt16 nLine = pPPortion->GetLineNumber( rPaM.GetIndex(), sal_False ); >- if ( nLine < ( pPPortion->GetLines().size() - 1 ) ) >- { >- sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( rPaM.GetPara(), nLine+1, nX ); >- aPaM.GetIndex() = nCharPos; >- >- // Sonderbehandlung siehe CursorUp... >- TextLine* pLine = pPPortion->GetLines()[ nLine + 1 ]; >- if ( ( aPaM.GetIndex() == pLine->GetEnd() ) && ( aPaM.GetIndex() > pLine->GetStart() ) && aPaM.GetIndex() < pPPortion->GetNode()->GetText().Len() ) >- aPaM.GetIndex()--; >- } >- else if ( rPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1 ) ) // naechster Absatz >- { >- aPaM.GetPara()++; >- pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() ); >- sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( aPaM.GetPara(), 0, nX+1 ); >- aPaM.GetIndex() = nCharPos; >- TextLine* pLine = pPPortion->GetLines().front(); >- if ( ( aPaM.GetIndex() == pLine->GetEnd() ) && ( aPaM.GetIndex() > pLine->GetStart() ) && ( pPPortion->GetLines().size() > 1 ) ) >- aPaM.GetIndex()--; >- } >- >- return aPaM; >-} >- >-TextPaM TextView::CursorStartOfLine( const TextPaM& rPaM ) >-{ >- TextPaM aPaM( rPaM ); >- >- TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() ); >- sal_uInt16 nLine = pPPortion->GetLineNumber( aPaM.GetIndex(), sal_False ); >- TextLine* pLine = pPPortion->GetLines()[ nLine ]; >- aPaM.GetIndex() = pLine->GetStart(); >- >- return aPaM; >-} >- >-TextPaM TextView::CursorEndOfLine( const TextPaM& rPaM ) >-{ >- TextPaM aPaM( rPaM ); >- >- TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() ); >- sal_uInt16 nLine = pPPortion->GetLineNumber( aPaM.GetIndex(), sal_False ); >- TextLine* pLine = pPPortion->GetLines()[ nLine ]; >- aPaM.GetIndex() = pLine->GetEnd(); >- >- if ( pLine->GetEnd() > pLine->GetStart() ) // Leerzeile >- { >- xub_Unicode cLastChar = pPPortion->GetNode()->GetText().GetChar((sal_uInt16)(aPaM.GetIndex()-1) ); >- if ( ( cLastChar == ' ' ) && ( aPaM.GetIndex() != pPPortion->GetNode()->GetText().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! >- aPaM.GetIndex()--; >- } >- } >- return aPaM; >-} >- >-TextPaM TextView::CursorStartOfParagraph( const TextPaM& rPaM ) >-{ >- TextPaM aPaM( rPaM ); >- aPaM.GetIndex() = 0; >- return aPaM; >-} >- >-TextPaM TextView::CursorEndOfParagraph( const TextPaM& rPaM ) >-{ >- TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( rPaM.GetPara() ); >- TextPaM aPaM( rPaM ); >- aPaM.GetIndex() = pNode->GetText().Len(); >- return aPaM; >-} >- >-TextPaM TextView::CursorStartOfDoc() >-{ >- TextPaM aPaM( 0, 0 ); >- return aPaM; >-} >- >-TextPaM TextView::CursorEndOfDoc() >-{ >- sal_uLong nNode = mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1; >- TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( nNode ); >- TextPaM aPaM( nNode, pNode->GetText().Len() ); >- return aPaM; >-} >- >-TextPaM TextView::PageUp( const TextPaM& rPaM ) >-{ >- Rectangle aRec = mpImpl->mpTextEngine->PaMtoEditCursor( rPaM ); >- Point aTopLeft = aRec.TopLeft(); >- aTopLeft.Y() -= mpImpl->mpWindow->GetOutputSizePixel().Height() * 9/10; >- aTopLeft.X() += 1; >- if ( aTopLeft.Y() < 0 ) >- aTopLeft.Y() = 0; >- >- TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aTopLeft ); >- return aPaM; >-} >- >-TextPaM TextView::PageDown( const TextPaM& rPaM ) >-{ >- Rectangle aRec = mpImpl->mpTextEngine->PaMtoEditCursor( rPaM ); >- Point aBottomRight = aRec.BottomRight(); >- aBottomRight.Y() += mpImpl->mpWindow->GetOutputSizePixel().Height() * 9/10; >- aBottomRight.X() += 1; >- long nHeight = mpImpl->mpTextEngine->GetTextHeight(); >- if ( aBottomRight.Y() > nHeight ) >- aBottomRight.Y() = nHeight-1; >- >- TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aBottomRight ); >- return aPaM; >-} >- >-void TextView::ImpShowCursor( sal_Bool bGotoCursor, sal_Bool bForceVisCursor, sal_Bool bSpecial ) >-{ >- if ( mpImpl->mpTextEngine->IsFormatting() ) >- return; >- if ( mpImpl->mpTextEngine->GetUpdateMode() == sal_False ) >- return; >- if ( mpImpl->mpTextEngine->IsInUndo() ) >- return; >- >- mpImpl->mpTextEngine->CheckIdleFormatter(); >- if ( !mpImpl->mpTextEngine->IsFormatted() ) >- mpImpl->mpTextEngine->FormatAndUpdate( this ); >- >- >- TextPaM aPaM( mpImpl->maSelection.GetEnd() ); >- Rectangle aEditCursor = mpImpl->mpTextEngine->PaMtoEditCursor( aPaM, bSpecial ); >- >- // Remember that we placed the cursor behind the last character of a line >- mpImpl->mbCursorAtEndOfLine = false; >- if( bSpecial ) >- { >- TEParaPortion* pParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() ); >- mpImpl->mbCursorAtEndOfLine = >- pParaPortion->GetLineNumber( aPaM.GetIndex(), sal_True ) != pParaPortion->GetLineNumber( aPaM.GetIndex(), sal_False ); >- } >- >- if ( !IsInsertMode() && !mpImpl->maSelection.HasRange() ) >- { >- TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() ); >- if ( pNode->GetText().Len() && ( aPaM.GetIndex() < pNode->GetText().Len() ) ) >- { >- // If we are behind a portion, and the next portion has other direction, we must change position... >- aEditCursor.Left() = aEditCursor.Right() = mpImpl->mpTextEngine->GetEditCursor( aPaM, sal_False, sal_True ).Left(); >- >- TEParaPortion* pParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() ); >- >- sal_uInt16 nTextPortionStart = 0; >- sal_uInt16 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, sal_True ); >- TETextPortion* pTextPortion = pParaPortion->GetTextPortions()[ nTextPortion ]; >- if ( pTextPortion->GetKind() == PORTIONKIND_TAB ) >- { >- if ( mpImpl->mpTextEngine->IsRightToLeft() ) >- { >- >- } >- aEditCursor.Right() += pTextPortion->GetWidth(); >- } >- else >- { >- TextPaM aNext = CursorRight( TextPaM( aPaM.GetPara(), aPaM.GetIndex() ), (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL ); >- aEditCursor.Right() = mpImpl->mpTextEngine->GetEditCursor( aNext, sal_True ).Left(); >- } >- } >- } >- >- Size aOutSz = mpImpl->mpWindow->GetOutputSizePixel(); >- if ( aEditCursor.GetHeight() > aOutSz.Height() ) >- aEditCursor.Bottom() = aEditCursor.Top() + aOutSz.Height() - 1; >- >- aEditCursor.Left() -= 1; >- >- if ( bGotoCursor >- // #i81283# protext maStartDocPos against initialization problems >- && aOutSz.Width() && aOutSz.Height() >- ) >- { >- long nVisStartY = mpImpl->maStartDocPos.Y(); >- long nVisEndY = mpImpl->maStartDocPos.Y() + aOutSz.Height(); >- long nVisStartX = mpImpl->maStartDocPos.X(); >- long nVisEndX = mpImpl->maStartDocPos.X() + aOutSz.Width(); >- long nMoreX = aOutSz.Width() / 4; >- >- Point aNewStartPos( mpImpl->maStartDocPos ); >- >- if ( aEditCursor.Bottom() > nVisEndY ) >- { >- aNewStartPos.Y() += ( aEditCursor.Bottom() - nVisEndY ); >- } >- else if ( aEditCursor.Top() < nVisStartY ) >- { >- aNewStartPos.Y() -= ( nVisStartY - aEditCursor.Top() ); >- } >- >- if ( aEditCursor.Right() >= nVisEndX ) >- { >- aNewStartPos.X() += ( aEditCursor.Right() - nVisEndX ); >- >- // Darfs ein bischen mehr sein? >- aNewStartPos.X() += nMoreX; >- } >- else if ( aEditCursor.Left() <= nVisStartX ) >- { >- aNewStartPos.X() -= ( nVisStartX - aEditCursor.Left() ); >- >- // Darfs ein bischen mehr sein? >- aNewStartPos.X() -= nMoreX; >- } >- >- // X kann durch das 'bischen mehr' falsch sein: >-// sal_uLong nMaxTextWidth = mpImpl->mpTextEngine->GetMaxTextWidth(); >-// if ( !nMaxTextWidth || ( nMaxTextWidth > 0x7FFFFFFF ) ) >-// nMaxTextWidth = 0x7FFFFFFF; >-// long nMaxX = (long)nMaxTextWidth - aOutSz.Width(); >- long nMaxX = mpImpl->mpTextEngine->CalcTextWidth() - aOutSz.Width(); >- if ( nMaxX < 0 ) >- nMaxX = 0; >- >- if ( aNewStartPos.X() < 0 ) >- aNewStartPos.X() = 0; >- else if ( aNewStartPos.X() > nMaxX ) >- aNewStartPos.X() = nMaxX; >- >- // Y sollte nicht weiter unten als noetig liegen: >- long nYMax = mpImpl->mpTextEngine->GetTextHeight() - aOutSz.Height(); >- if ( nYMax < 0 ) >- nYMax = 0; >- if ( aNewStartPos.Y() > nYMax ) >- aNewStartPos.Y() = nYMax; >- >- if ( aNewStartPos != mpImpl->maStartDocPos ) >- Scroll( -(aNewStartPos.X() - mpImpl->maStartDocPos.X()), -(aNewStartPos.Y() - mpImpl->maStartDocPos.Y()) ); >- } >- >- if ( aEditCursor.Right() < aEditCursor.Left() ) >- { >- long n = aEditCursor.Left(); >- aEditCursor.Left() = aEditCursor.Right(); >- aEditCursor.Right() = n; >- } >- >- Point aPoint( GetWindowPos( !mpImpl->mpTextEngine->IsRightToLeft() ? aEditCursor.TopLeft() : aEditCursor.TopRight() ) ); >- mpImpl->mpCursor->SetPos( aPoint ); >- mpImpl->mpCursor->SetSize( aEditCursor.GetSize() ); >- if ( bForceVisCursor && mpImpl->mbCursorEnabled ) >- mpImpl->mpCursor->Show(); >-} >- >-sal_Bool TextView::SetCursorAtPoint( const Point& rPosPixel ) >-{ >- mpImpl->mpTextEngine->CheckIdleFormatter(); >- >- Point aDocPos = GetDocPos( rPosPixel ); >- >- TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aDocPos ); >- >- // aTmpNewSel: Diff zwischen alt und neu, nicht die neue Selektion >- TextSelection aTmpNewSel( mpImpl->maSelection.GetEnd(), aPaM ); >- TextSelection aNewSel( mpImpl->maSelection ); >- aNewSel.GetEnd() = aPaM; >- >- if ( !mpImpl->mpSelEngine->HasAnchor() ) >- { >- if ( mpImpl->maSelection.GetStart() != aPaM ) >- mpImpl->mpTextEngine->CursorMoved( mpImpl->maSelection.GetStart().GetPara() ); >- aNewSel.GetStart() = aPaM; >- ImpSetSelection( aNewSel ); >- } >- else >- { >- ImpSetSelection( aNewSel ); >- ShowSelection( aTmpNewSel ); >- } >- >- sal_Bool bForceCursor = mpImpl->mpDDInfo ? sal_False : sal_True; // && !mbInSelection >- ImpShowCursor( mpImpl->mbAutoScroll, bForceCursor, sal_False ); >- return sal_True; >-} >- >-sal_Bool TextView::IsSelectionAtPoint( const Point& rPosPixel ) >-{ >-// if ( !Rectangle( Point(), mpImpl->mpWindow->GetOutputSizePixel() ).IsInside( rPosPixel ) && !mbInSelection ) >-// return sal_False; >- >- Point aDocPos = GetDocPos( rPosPixel ); >- TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aDocPos, sal_False ); >- // Bei Hyperlinks D&D auch ohne Selektion starten. >- // BeginDrag wird aber nur gerufen, wenn IsSelectionAtPoint() >- // Problem: IsSelectionAtPoint wird bei Command() nicht gerufen, >- // wenn vorher im MBDown schon sal_False returnt wurde. >- return ( IsInSelection( aPaM ) || >- ( /* mpImpl->mpSelEngine->IsInCommand() && */ mpImpl->mpTextEngine->FindAttrib( aPaM, TEXTATTR_HYPERLINK ) ) ); >-} >- >-sal_Bool TextView::IsInSelection( const TextPaM& rPaM ) >-{ >- TextSelection aSel = mpImpl->maSelection; >- aSel.Justify(); >- >- sal_uLong nStartNode = aSel.GetStart().GetPara(); >- sal_uLong nEndNode = aSel.GetEnd().GetPara(); >- sal_uLong nCurNode = rPaM.GetPara(); >- >- if ( ( nCurNode > nStartNode ) && ( nCurNode < nEndNode ) ) >- return sal_True; >- >- if ( nStartNode == nEndNode ) >- { >- if ( nCurNode == nStartNode ) >- if ( ( rPaM.GetIndex() >= aSel.GetStart().GetIndex() ) && ( rPaM.GetIndex() < aSel.GetEnd().GetIndex() ) ) >- return sal_True; >- } >- else if ( ( nCurNode == nStartNode ) && ( rPaM.GetIndex() >= aSel.GetStart().GetIndex() ) ) >- return sal_True; >- else if ( ( nCurNode == nEndNode ) && ( rPaM.GetIndex() < aSel.GetEnd().GetIndex() ) ) >- return sal_True; >- >- return sal_False; >-} >- >-void TextView::ImpHideDDCursor() >-{ >- if ( mpImpl->mpDDInfo && mpImpl->mpDDInfo->mbVisCursor ) >- { >- mpImpl->mpDDInfo->maCursor.Hide(); >- mpImpl->mpDDInfo->mbVisCursor = sal_False; >- } >-} >- >-void TextView::ImpShowDDCursor() >-{ >- if ( !mpImpl->mpDDInfo->mbVisCursor ) >- { >- Rectangle aCursor = mpImpl->mpTextEngine->PaMtoEditCursor( mpImpl->mpDDInfo->maDropPos, sal_True ); >- aCursor.Right()++; >- aCursor.SetPos( GetWindowPos( aCursor.TopLeft() ) ); >- >- mpImpl->mpDDInfo->maCursor.SetWindow( mpImpl->mpWindow ); >- mpImpl->mpDDInfo->maCursor.SetPos( aCursor.TopLeft() ); >- mpImpl->mpDDInfo->maCursor.SetSize( aCursor.GetSize() ); >- mpImpl->mpDDInfo->maCursor.Show(); >- mpImpl->mpDDInfo->mbVisCursor = sal_True; >- } >-} >- >-void TextView::SetPaintSelection( sal_Bool bPaint ) >-{ >- if ( bPaint != mpImpl->mbPaintSelection ) >- { >- mpImpl->mbPaintSelection = bPaint; >- ShowSelection( mpImpl->maSelection ); >- } >-} >- >-sal_Bool TextView::Read( SvStream& rInput ) >-{ >- sal_Bool bDone = mpImpl->mpTextEngine->Read( rInput, &mpImpl->maSelection ); >- ShowCursor(); >- return bDone; >-} >- >-bool TextView::ImplTruncateNewText( rtl::OUString& rNewText ) const >-{ >- bool bTruncated = false; >- >- if( rNewText.getLength() > 65534 ) // limit to String API >- { >- rNewText = rNewText.copy( 0, 65534 ); >- bTruncated = true; >- } >- >- sal_uLong nMaxLen = mpImpl->mpTextEngine->GetMaxTextLen(); >- // 0 means unlimited, there is just the String API limit handled above >- if( nMaxLen != 0 ) >- { >- sal_uLong nCurLen = mpImpl->mpTextEngine->GetTextLen(); >- >- sal_uInt32 nNewLen = rNewText.getLength(); >- if ( nCurLen + nNewLen > nMaxLen ) >- { >- // see how much text will be replaced >- sal_uLong nSelLen = mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection ); >- if ( nCurLen + nNewLen - nSelLen > nMaxLen ) >- { >- sal_uInt32 nTruncatedLen = static_cast<sal_uInt32>(nMaxLen - (nCurLen - nSelLen)); >- rNewText = rNewText.copy( 0, nTruncatedLen ); >- bTruncated = true; >- } >- } >- } >- return bTruncated; >-} >- >-sal_Bool TextView::ImplCheckTextLen( const String& rNewText ) >-{ >- sal_Bool bOK = sal_True; >- if ( mpImpl->mpTextEngine->GetMaxTextLen() ) >- { >- sal_uLong n = mpImpl->mpTextEngine->GetTextLen(); >- n += rNewText.Len(); >- if ( n > mpImpl->mpTextEngine->GetMaxTextLen() ) >- { >- // nur dann noch ermitteln, wie viel Text geloescht wird >- n -= mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection ); >- if ( n > mpImpl->mpTextEngine->GetMaxTextLen() ) >- bOK = sal_False; >- } >- } >- return bOK; >-} >- >-void TextView::dragGestureRecognized( const ::com::sun::star::datatransfer::dnd::DragGestureEvent& rDGE ) throw (::com::sun::star::uno::RuntimeException) >-{ >- if ( mpImpl->mbClickedInSelection ) >- { >- SolarMutexGuard aVclGuard; >- >- DBG_ASSERT( mpImpl->maSelection.HasRange(), "TextView::dragGestureRecognized: mpImpl->mbClickedInSelection, but no selection?" ); >- >- delete mpImpl->mpDDInfo; >- mpImpl->mpDDInfo = new TextDDInfo; >- mpImpl->mpDDInfo->mbStarterOfDD = sal_True; >- >- TETextDataObject* pDataObj = new TETextDataObject( GetSelected() ); >- >- if ( mpImpl->mpTextEngine->HasAttrib( TEXTATTR_HYPERLINK ) ) // Dann auch als HTML >- mpImpl->mpTextEngine->Write( pDataObj->GetHTMLStream(), &mpImpl->maSelection, sal_True ); >- >- >- /* >- // D&D eines Hyperlinks. >- // Besser waere es im MBDown sich den MBDownPaM zu merken, >- // ist dann aber inkompatibel => spaeter mal umstellen. >- TextPaM aPaM( mpImpl->mpTextEngine->GetPaM( GetDocPos( GetWindow()->GetPointerPosPixel() ) ) ); >- const TextCharAttrib* pAttr = mpImpl->mpTextEngine->FindCharAttrib( aPaM, TEXTATTR_HYPERLINK ); >- if ( pAttr ) >- { >- aSel = aPaM; >- aSel.GetStart().GetIndex() = pAttr->GetStart(); >- aSel.GetEnd().GetIndex() = pAttr->GetEnd(); >- >- const TextAttribHyperLink& rLink = (const TextAttribHyperLink&)pAttr->GetAttr(); >- String aText( rLink.GetDescription() ); >- if ( !aText.Len() ) >- aText = mpImpl->mpTextEngine->GetText( aSel ); >- INetBookmark aBookmark( rLink.GetURL(), aText ); >- aBookmark.CopyDragServer(); >- } >- */ >- >- mpImpl->mpCursor->Hide(); >- >- sal_Int8 nActions = datatransfer::dnd::DNDConstants::ACTION_COPY; >- if ( !IsReadOnly() ) >- nActions |= datatransfer::dnd::DNDConstants::ACTION_MOVE; >- rDGE.DragSource->startDrag( rDGE, nActions, 0 /*cursor*/, 0 /*image*/, pDataObj, mpImpl->mxDnDListener ); >- } >-} >- >-void TextView::dragDropEnd( const ::com::sun::star::datatransfer::dnd::DragSourceDropEvent& ) throw (::com::sun::star::uno::RuntimeException) >-{ >- ImpHideDDCursor(); >- delete mpImpl->mpDDInfo; >- mpImpl->mpDDInfo = NULL; >-} >- >-void TextView::drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException) >-{ >- SolarMutexGuard aVclGuard; >- >- sal_Bool bChanges = sal_False; >- if ( !mpImpl->mbReadOnly && mpImpl->mpDDInfo ) >- { >- ImpHideDDCursor(); >- >- // Daten fuer das loeschen nach einem DROP_MOVE: >- TextSelection aPrevSel( mpImpl->maSelection ); >- aPrevSel.Justify(); >- sal_uLong nPrevParaCount = mpImpl->mpTextEngine->GetParagraphCount(); >- sal_uInt16 nPrevStartParaLen = mpImpl->mpTextEngine->GetTextLen( aPrevSel.GetStart().GetPara() ); >- >- sal_Bool bStarterOfDD = sal_False; >- for ( sal_uInt16 nView = mpImpl->mpTextEngine->GetViewCount(); nView && !bStarterOfDD; ) >- bStarterOfDD = mpImpl->mpTextEngine->GetView( --nView )->mpImpl->mpDDInfo ? mpImpl->mpTextEngine->GetView( nView )->mpImpl->mpDDInfo->mbStarterOfDD : sal_False; >- >- HideSelection(); >- ImpSetSelection( mpImpl->mpDDInfo->maDropPos ); >- >- mpImpl->mpTextEngine->UndoActionStart(); >- >- String aText; >- uno::Reference< datatransfer::XTransferable > xDataObj = rDTDE.Transferable; >- if ( xDataObj.is() ) >- { >- datatransfer::DataFlavor aFlavor; >- SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor ); >- if ( xDataObj->isDataFlavorSupported( aFlavor ) ) >- { >- uno::Any aData = xDataObj->getTransferData( aFlavor ); >- ::rtl::OUString aOUString; >- aData >>= aOUString; >- aText = convertLineEnd(aOUString, LINEEND_LF); >- } >- } >- >- if ( aText.Len() && ( aText.GetChar( aText.Len()-1 ) == LINE_SEP ) ) >- aText.Erase( aText.Len()-1 ); >- >- TextPaM aTempStart = mpImpl->maSelection.GetStart(); >- if ( ImplCheckTextLen( aText ) ) >- ImpSetSelection( mpImpl->mpTextEngine->ImpInsertText( mpImpl->mpDDInfo->maDropPos, aText ) ); >- if(mpImpl->mbSupportProtectAttribute) >- { >- mpImpl->mpTextEngine->SetAttrib( TextAttribProtect(), >- aTempStart.GetPara(), >- aTempStart.GetIndex(), >- mpImpl->maSelection.GetEnd().GetIndex(), sal_False ); >- } >- >- if ( aPrevSel.HasRange() && >- !mpImpl->mbSupportProtectAttribute && // don't remove currently selected element >- (( rDTDE.DropAction & datatransfer::dnd::DNDConstants::ACTION_MOVE ) || !bStarterOfDD) ) >- { >- // ggf. Selection anpasssen: >- if ( ( mpImpl->mpDDInfo->maDropPos.GetPara() < aPrevSel.GetStart().GetPara() ) || >- ( ( mpImpl->mpDDInfo->maDropPos.GetPara() == aPrevSel.GetStart().GetPara() ) >- && ( mpImpl->mpDDInfo->maDropPos.GetIndex() < aPrevSel.GetStart().GetIndex() ) ) ) >- { >- sal_uLong nNewParasBeforeSelection = >- mpImpl->mpTextEngine->GetParagraphCount() - nPrevParaCount; >- >- aPrevSel.GetStart().GetPara() += nNewParasBeforeSelection; >- aPrevSel.GetEnd().GetPara() += nNewParasBeforeSelection; >- >- if ( mpImpl->mpDDInfo->maDropPos.GetPara() == aPrevSel.GetStart().GetPara() ) >- { >- sal_uInt16 nNewChars = >- mpImpl->mpTextEngine->GetTextLen( aPrevSel.GetStart().GetPara() ) - nPrevStartParaLen; >- >- aPrevSel.GetStart().GetIndex() = >- aPrevSel.GetStart().GetIndex() + nNewChars; >- if ( aPrevSel.GetStart().GetPara() == aPrevSel.GetEnd().GetPara() ) >- aPrevSel.GetEnd().GetIndex() = >- aPrevSel.GetEnd().GetIndex() + nNewChars; >- } >- } >- else >- { >- // aktuelle Selektion anpassen >- TextPaM aPaM = mpImpl->maSelection.GetStart(); >- aPaM.GetPara() -= ( aPrevSel.GetEnd().GetPara() - aPrevSel.GetStart().GetPara() ); >- if ( aPrevSel.GetEnd().GetPara() == mpImpl->mpDDInfo->maDropPos.GetPara() ) >- { >- aPaM.GetIndex() = >- aPaM.GetIndex() - aPrevSel.GetEnd().GetIndex(); >- if ( aPrevSel.GetStart().GetPara() == mpImpl->mpDDInfo->maDropPos.GetPara() ) >- aPaM.GetIndex() = >- aPaM.GetIndex() + aPrevSel.GetStart().GetIndex(); >- } >- ImpSetSelection( aPaM ); >- >- } >- mpImpl->mpTextEngine->ImpDeleteText( aPrevSel ); >- } >- >- mpImpl->mpTextEngine->UndoActionEnd(); >- >- delete mpImpl->mpDDInfo; >- mpImpl->mpDDInfo = 0; >- >- mpImpl->mpTextEngine->FormatAndUpdate( this ); >- >- mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) ); >- } >- rDTDE.Context->dropComplete( bChanges ); >-} >- >-void TextView::dragEnter( const ::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent& ) throw (::com::sun::star::uno::RuntimeException) >-{ >-} >- >-void TextView::dragExit( const ::com::sun::star::datatransfer::dnd::DropTargetEvent& ) throw (::com::sun::star::uno::RuntimeException) >-{ >- SolarMutexGuard aVclGuard; >- ImpHideDDCursor(); >-} >- >-void TextView::dragOver( const ::com::sun::star::datatransfer::dnd::DropTargetDragEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException) >-{ >- SolarMutexGuard aVclGuard; >- >- if ( !mpImpl->mpDDInfo ) >- mpImpl->mpDDInfo = new TextDDInfo; >- >- TextPaM aPrevDropPos = mpImpl->mpDDInfo->maDropPos; >- Point aMousePos( rDTDE.LocationX, rDTDE.LocationY ); >- Point aDocPos = GetDocPos( aMousePos ); >- mpImpl->mpDDInfo->maDropPos = mpImpl->mpTextEngine->GetPaM( aDocPos ); >- >- sal_Bool bProtected = sal_False; >- if(mpImpl->mbSupportProtectAttribute) >- { >- const TextCharAttrib* pStartAttr = mpImpl->mpTextEngine->FindCharAttrib( >- mpImpl->mpDDInfo->maDropPos, >- TEXTATTR_PROTECTED ); >- bProtected = pStartAttr != 0 && >- pStartAttr->GetStart() != mpImpl->mpDDInfo->maDropPos.GetIndex() && >- pStartAttr->GetEnd() != mpImpl->mpDDInfo->maDropPos.GetIndex(); >- } >- // Don't drop in selection or in read only engine >- if ( IsReadOnly() || IsInSelection( mpImpl->mpDDInfo->maDropPos ) || bProtected) >- { >- ImpHideDDCursor(); >- rDTDE.Context->rejectDrag(); >- } >- else >- { >- // Alten Cursor wegzeichnen... >- if ( !mpImpl->mpDDInfo->mbVisCursor || ( aPrevDropPos != mpImpl->mpDDInfo->maDropPos ) ) >- { >- ImpHideDDCursor(); >- ImpShowDDCursor(); >- } >- rDTDE.Context->acceptDrag( rDTDE.DropAction ); >- } >-} >- >-Point TextView::ImpGetOutputStartPos( const Point& rStartDocPos ) const >-{ >- Point aStartPos( -rStartDocPos.X(), -rStartDocPos.Y() ); >- if ( mpImpl->mpTextEngine->IsRightToLeft() ) >- { >- Size aSz = mpImpl->mpWindow->GetOutputSizePixel(); >- aStartPos.X() = rStartDocPos.X() + aSz.Width() - 1; // -1: Start is 0 >- } >- return aStartPos; >-} >- >-Point TextView::GetDocPos( const Point& rWindowPos ) const >-{ >- // Fensterposition => Dokumentposition >- >- Point aPoint; >- >- aPoint.Y() = rWindowPos.Y() + mpImpl->maStartDocPos.Y(); >- >- if ( !mpImpl->mpTextEngine->IsRightToLeft() ) >- { >- aPoint.X() = rWindowPos.X() + mpImpl->maStartDocPos.X(); >- } >- else >- { >- Size aSz = mpImpl->mpWindow->GetOutputSizePixel(); >- aPoint.X() = ( aSz.Width() - 1 ) - rWindowPos.X() + mpImpl->maStartDocPos.X(); >- } >- >- return aPoint; >-} >- >-Point TextView::GetWindowPos( const Point& rDocPos ) const >-{ >- // Dokumentposition => Fensterposition >- >- Point aPoint; >- >- aPoint.Y() = rDocPos.Y() - mpImpl->maStartDocPos.Y(); >- >- if ( !mpImpl->mpTextEngine->IsRightToLeft() ) >- { >- aPoint.X() = rDocPos.X() - mpImpl->maStartDocPos.X(); >- } >- else >- { >- Size aSz = mpImpl->mpWindow->GetOutputSizePixel(); >- aPoint.X() = ( aSz.Width() - 1 ) - ( rDocPos.X() - mpImpl->maStartDocPos.X() ); >- } >- >- return aPoint; >-} >- >-sal_Int32 TextView::GetLineNumberOfCursorInSelection() const >-{ >- // PROGRESS >- sal_Int32 nLineNo = -1; >- if( mpImpl->mbCursorEnabled ) >- { >- TextPaM aPaM = GetSelection().GetEnd(); >- TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() ); >- nLineNo = pPPortion->GetLineNumber( aPaM.GetIndex(), sal_False ); >- if( mpImpl->mbCursorAtEndOfLine ) >- --nLineNo; >- } >- return nLineNo; >-} >- >- >-// ------------------------------------------------------------------------- >-// (+) class TextSelFunctionSet >-// ------------------------------------------------------------------------- >-TextSelFunctionSet::TextSelFunctionSet( TextView* pView ) >-{ >- mpView = pView; >-} >- >-void TextSelFunctionSet::BeginDrag() >-{ >-} >- >-void TextSelFunctionSet::CreateAnchor() >-{ >-// TextSelection aSel( mpView->GetSelection() ); >-// aSel.GetStart() = aSel.GetEnd(); >-// mpView->SetSelection( aSel ); >- >- // Es darf kein ShowCursor folgen: >- mpView->HideSelection(); >- mpView->ImpSetSelection( mpView->mpImpl->maSelection.GetEnd() ); >-} >- >-sal_Bool TextSelFunctionSet::SetCursorAtPoint( const Point& rPointPixel, sal_Bool ) >-{ >- return mpView->SetCursorAtPoint( rPointPixel ); >-} >- >-sal_Bool TextSelFunctionSet::IsSelectionAtPoint( const Point& rPointPixel ) >-{ >- return mpView->IsSelectionAtPoint( rPointPixel ); >-} >- >-void TextSelFunctionSet::DeselectAll() >-{ >- CreateAnchor(); >-} >- >-void TextSelFunctionSet::DeselectAtPoint( const Point& ) >-{ >- // Nur bei Mehrfachselektion >-} >- >-void TextSelFunctionSet::DestroyAnchor() >-{ >- // Nur bei Mehrfachselektion >-} >-TextEngine* TextView::GetTextEngine() const >-{ return mpImpl->mpTextEngine; } >-Window* TextView::GetWindow() const >-{ return mpImpl->mpWindow; } >-void TextView::EnableCursor( sal_Bool bEnable ) >-{ mpImpl->mbCursorEnabled = bEnable; } >-sal_Bool TextView::IsCursorEnabled() const >-{ return mpImpl->mbCursorEnabled; } >-void TextView::SetStartDocPos( const Point& rPos ) >-{ mpImpl->maStartDocPos = rPos; } >-const Point& TextView::GetStartDocPos() const >-{ return mpImpl->maStartDocPos; } >-void TextView::SetAutoIndentMode( sal_Bool bAutoIndent ) >-{ mpImpl->mbAutoIndent = bAutoIndent; } >-sal_Bool TextView::IsReadOnly() const >-{ return mpImpl->mbReadOnly; } >-void TextView::SetAutoScroll( sal_Bool bAutoScroll ) >-{ mpImpl->mbAutoScroll = bAutoScroll; } >-sal_Bool TextView::IsAutoScroll() const >-{ return mpImpl->mbAutoScroll; } >-sal_Bool TextView::HasSelection() const >-{ return mpImpl->maSelection.HasRange(); } >-sal_Bool TextView::IsInsertMode() const >-{ return mpImpl->mbInsertMode; } >-void TextView::SupportProtectAttribute(sal_Bool bSupport) >-{ mpImpl->mbSupportProtectAttribute = bSupport;} >- >-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/svtools/source/edit/textwindowpeer.cxx b/svtools/source/edit/textwindowpeer.cxx >index 3609063..59eee86 100644 >--- a/svtools/source/edit/textwindowpeer.cxx >+++ b/svtools/source/edit/textwindowpeer.cxx >@@ -19,7 +19,7 @@ > > > #include <svtools/textwindowpeer.hxx> >-#include <svtools/textview.hxx> >+#include <vcl/textview.hxx> > #include "svtaccessiblefactory.hxx" > > namespace css = ::com::sun::star; >diff --git a/svtools/source/edit/txtattr.cxx b/svtools/source/edit/txtattr.cxx >deleted file mode 100644 >index a332482..0000000 >--- a/svtools/source/edit/txtattr.cxx >+++ /dev/null >@@ -1,164 +0,0 @@ >-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >-/************************************************************************* >- * >- * 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 <svtools/txtattr.hxx> >-#include <vcl/font.hxx> >- >- >- >- >-TextAttrib::~TextAttrib() >-{ >-} >- >-int TextAttrib::operator==( const TextAttrib& rAttr ) const >-{ >- return mnWhich == rAttr.mnWhich; >-} >- >- >-TextAttribFontColor::TextAttribFontColor( const Color& rColor ) >- : TextAttrib( TEXTATTR_FONTCOLOR ), maColor( rColor ) >-{ >-} >- >-TextAttribFontColor::TextAttribFontColor( const TextAttribFontColor& rAttr ) >- : TextAttrib( rAttr ), maColor( rAttr.maColor ) >-{ >-} >- >-TextAttribFontColor::~TextAttribFontColor() >-{ >-} >- >-void TextAttribFontColor::SetFont( Font& rFont ) const >-{ >- rFont.SetColor( maColor ); >-} >- >-TextAttrib* TextAttribFontColor::Clone() const >-{ >- return new TextAttribFontColor( *this ); >-} >- >-int TextAttribFontColor::operator==( const TextAttrib& rAttr ) const >-{ >- return ( ( TextAttrib::operator==(rAttr ) ) && >- ( maColor == ((const TextAttribFontColor&)rAttr).maColor ) ); >-} >- >-TextAttribFontWeight::TextAttribFontWeight( FontWeight eWeight ) >- : TextAttrib( TEXTATTR_FONTWEIGHT ), meWeight( eWeight ) >-{ >-} >- >-TextAttribFontWeight::TextAttribFontWeight( const TextAttribFontWeight& rAttr ) >- : TextAttrib( rAttr ), meWeight( rAttr.meWeight ) >-{ >-} >- >-TextAttribFontWeight::~TextAttribFontWeight() >-{ >-} >- >-void TextAttribFontWeight::SetFont( Font& rFont ) const >-{ >- rFont.SetWeight( meWeight ); >-} >- >-TextAttrib* TextAttribFontWeight::Clone() const >-{ >- return new TextAttribFontWeight( *this ); >-} >- >-int TextAttribFontWeight::operator==( const TextAttrib& rAttr ) const >-{ >- return ( ( TextAttrib::operator==(rAttr ) ) && >- ( meWeight == ((const TextAttribFontWeight&)rAttr).meWeight ) ); >-} >- >- >-TextAttribHyperLink::TextAttribHyperLink( const TextAttribHyperLink& rAttr ) >- : TextAttrib( rAttr ), maURL( rAttr.maURL ), maDescription( rAttr.maDescription ) >-{ >- maColor = rAttr.maColor; >-} >- >-TextAttribHyperLink::~TextAttribHyperLink() >-{ >-} >- >-void TextAttribHyperLink::SetFont( Font& rFont ) const >-{ >- rFont.SetColor( maColor ); >- rFont.SetUnderline( UNDERLINE_SINGLE ); >-} >- >-TextAttrib* TextAttribHyperLink::Clone() const >-{ >- return new TextAttribHyperLink( *this ); >-} >- >-int TextAttribHyperLink::operator==( const TextAttrib& rAttr ) const >-{ >- return ( ( TextAttrib::operator==(rAttr ) ) && >- ( maURL == ((const TextAttribHyperLink&)rAttr).maURL ) && >- ( maDescription == ((const TextAttribHyperLink&)rAttr).maDescription ) && >- ( maColor == ((const TextAttribHyperLink&)rAttr).maColor ) ); >-} >- >-TextAttribProtect::TextAttribProtect() : >- TextAttrib( TEXTATTR_PROTECTED ) >-{ >-} >- >-TextAttribProtect::TextAttribProtect( const TextAttribProtect&) : >- TextAttrib( TEXTATTR_PROTECTED ) >-{ >-} >- >-TextAttribProtect::~TextAttribProtect() >-{ >-} >- >-void TextAttribProtect::SetFont( Font& ) const >-{ >-} >- >-TextAttrib* TextAttribProtect::Clone() const >-{ >- return new TextAttribProtect(); >-} >- >-int TextAttribProtect::operator==( const TextAttrib& rAttr ) const >-{ >- return ( TextAttrib::operator==(rAttr ) ); >-} >- >-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/svtools/source/edit/xtextedt.cxx b/svtools/source/edit/xtextedt.cxx >deleted file mode 100644 >index a02f6aa..0000000 >--- a/svtools/source/edit/xtextedt.cxx >+++ /dev/null >@@ -1,421 +0,0 @@ >-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >-/************************************************************************* >- * >- * 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 <svtools/xtextedt.hxx> >-#include <vcl/svapp.hxx> // International >-#include <unotools/textsearch.hxx> >-#include <com/sun/star/util/SearchOptions.hpp> >-#include <com/sun/star/util/SearchFlags.hpp> >- >-using namespace ::com::sun::star; >- >- >- >-// ------------------------------------------------------------------------- >-// class ExtTextEngine >-// ------------------------------------------------------------------------- >-ExtTextEngine::ExtTextEngine() : maGroupChars(rtl::OUString("(){}[]")) >-{ >-} >- >-ExtTextEngine::~ExtTextEngine() >-{ >-} >- >-TextSelection ExtTextEngine::MatchGroup( const TextPaM& rCursor ) const >-{ >- TextSelection aSel( rCursor ); >- sal_uInt16 nPos = rCursor.GetIndex(); >- sal_uLong nPara = rCursor.GetPara(); >- sal_uLong nParas = GetParagraphCount(); >- if ( ( nPara < nParas ) && ( nPos < GetTextLen( nPara ) ) ) >- { >- sal_uInt16 nMatchChar = maGroupChars.Search( GetText( rCursor.GetPara() ).GetChar( nPos ) ); >- if ( nMatchChar != STRING_NOTFOUND ) >- { >- if ( ( nMatchChar % 2 ) == 0 ) >- { >- // Vorwaerts suchen... >- sal_Unicode nSC = maGroupChars.GetChar( nMatchChar ); >- sal_Unicode nEC = maGroupChars.GetChar( nMatchChar+1 ); >- >- sal_uInt16 nCur = nPos+1; >- sal_uInt16 nLevel = 1; >- while ( nLevel && ( nPara < nParas ) ) >- { >- XubString aStr = GetText( nPara ); >- while ( nCur < aStr.Len() ) >- { >- if ( aStr.GetChar( nCur ) == nSC ) >- nLevel++; >- else if ( aStr.GetChar( nCur ) == nEC ) >- { >- nLevel--; >- if ( !nLevel ) >- break; // while nCur... >- } >- nCur++; >- } >- >- if ( nLevel ) >- { >- nPara++; >- nCur = 0; >- } >- } >- if ( nLevel == 0 ) // gefunden >- { >- aSel.GetStart() = rCursor; >- aSel.GetEnd() = TextPaM( nPara, nCur+1 ); >- } >- } >- else >- { >- // Rueckwaerts suchen... >- xub_Unicode nEC = maGroupChars.GetChar( nMatchChar ); >- xub_Unicode nSC = maGroupChars.GetChar( nMatchChar-1 ); >- >- sal_uInt16 nCur = rCursor.GetIndex()-1; >- sal_uInt16 nLevel = 1; >- while ( nLevel ) >- { >- if ( GetTextLen( nPara ) ) >- { >- XubString aStr = GetText( nPara ); >- while ( nCur ) >- { >- if ( aStr.GetChar( nCur ) == nSC ) >- { >- nLevel--; >- if ( !nLevel ) >- break; // while nCur... >- } >- else if ( aStr.GetChar( nCur ) == nEC ) >- nLevel++; >- >- nCur--; >- } >- } >- >- if ( nLevel ) >- { >- if ( nPara ) >- { >- nPara--; >- nCur = GetTextLen( nPara )-1; // egal ob negativ, weil if Len() >- } >- else >- break; >- } >- } >- >- if ( nLevel == 0 ) // gefunden >- { >- aSel.GetStart() = rCursor; >- aSel.GetStart().GetIndex()++; // hinter das Zeichen >- aSel.GetEnd() = TextPaM( nPara, nCur ); >- } >- } >- } >- } >- return aSel; >-} >- >-sal_Bool ExtTextEngine::Search( TextSelection& rSel, const util::SearchOptions& rSearchOptions, sal_Bool bForward ) >-{ >- TextSelection aSel( rSel ); >- aSel.Justify(); >- >- sal_Bool bSearchInSelection = (0 != (rSearchOptions.searchFlag & util::SearchFlags::REG_NOT_BEGINOFLINE) ); >- >- TextPaM aStartPaM( aSel.GetEnd() ); >- if ( aSel.HasRange() && ( ( bSearchInSelection && bForward ) || ( !bSearchInSelection && !bForward ) ) ) >- { >- aStartPaM = aSel.GetStart(); >- } >- >- bool bFound = false; >- sal_uLong nStartNode, nEndNode; >- >- if ( bSearchInSelection ) >- nEndNode = bForward ? aSel.GetEnd().GetPara() : aSel.GetStart().GetPara(); >- else >- nEndNode = bForward ? (GetParagraphCount()-1) : 0; >- >- nStartNode = aStartPaM.GetPara(); >- >- util::SearchOptions aOptions( rSearchOptions ); >- aOptions.Locale = Application::GetSettings().GetLocale(); >- utl::TextSearch aSearcher( rSearchOptions ); >- >- // ueber die Absaetze iterieren... >- for ( sal_uLong nNode = nStartNode; >- bForward ? ( nNode <= nEndNode) : ( nNode >= nEndNode ); >- bForward ? nNode++ : nNode-- ) >- { >- String aText = GetText( nNode ); >- sal_uInt16 nStartPos = 0; >- sal_uInt16 nEndPos = aText.Len(); >- if ( nNode == nStartNode ) >- { >- if ( bForward ) >- nStartPos = aStartPaM.GetIndex(); >- else >- nEndPos = aStartPaM.GetIndex(); >- } >- if ( ( nNode == nEndNode ) && bSearchInSelection ) >- { >- if ( bForward ) >- nEndPos = aSel.GetEnd().GetIndex(); >- else >- nStartPos = aSel.GetStart().GetIndex(); >- } >- >- if ( bForward ) >- bFound = aSearcher.SearchFrwrd( aText, &nStartPos, &nEndPos ); >- else >- bFound = aSearcher.SearchBkwrd( aText, &nEndPos, &nStartPos ); >- >- if ( bFound ) >- { >- rSel.GetStart().GetPara() = nNode; >- rSel.GetStart().GetIndex() = nStartPos; >- rSel.GetEnd().GetPara() = nNode; >- rSel.GetEnd().GetIndex() = nEndPos; >- // Ueber den Absatz selektieren? >- // Select over the paragraph? >- // FIXME This should be max long... >- if( nEndPos == sal::static_int_cast<sal_uInt16>(-1) ) // sal_uInt16 for 0 and -1 ! >- { >- if ( (rSel.GetEnd().GetPara()+1) < GetParagraphCount() ) >- { >- rSel.GetEnd().GetPara()++; >- rSel.GetEnd().GetIndex() = 0; >- } >- else >- { >- rSel.GetEnd().GetIndex() = nStartPos; >- bFound = false; >- } >- } >- >- break; >- } >- >- if ( !bForward && !nNode ) // Bei rueckwaertsuche, wenn nEndNode = 0: >- break; >- } >- >- return bFound; >-} >- >- >-// ------------------------------------------------------------------------- >-// class ExtTextView >-// ------------------------------------------------------------------------- >-ExtTextView::ExtTextView( ExtTextEngine* pEng, Window* pWindow ) >- : TextView( pEng, pWindow ) >-{ >-} >- >-ExtTextView::~ExtTextView() >-{ >-} >- >-sal_Bool ExtTextView::MatchGroup() >-{ >- TextSelection aTmpSel( GetSelection() ); >- aTmpSel.Justify(); >- if ( ( aTmpSel.GetStart().GetPara() != aTmpSel.GetEnd().GetPara() ) || >- ( ( aTmpSel.GetEnd().GetIndex() - aTmpSel.GetStart().GetIndex() ) > 1 ) ) >- { >- return sal_False; >- } >- >- TextSelection aMatchSel = ((ExtTextEngine*)GetTextEngine())->MatchGroup( aTmpSel.GetStart() ); >- if ( aMatchSel.HasRange() ) >- SetSelection( aMatchSel ); >- >- return aMatchSel.HasRange() ? sal_True : sal_False; >-} >- >-sal_Bool ExtTextView::Search( const util::SearchOptions& rSearchOptions, sal_Bool bForward ) >-{ >- sal_Bool bFound = sal_False; >- TextSelection aSel( GetSelection() ); >- if ( ((ExtTextEngine*)GetTextEngine())->Search( aSel, rSearchOptions, bForward ) ) >- { >- bFound = sal_True; >- // Erstmal den Anfang des Wortes als Selektion einstellen, >- // damit das ganze Wort in den sichtbaren Bereich kommt. >- SetSelection( aSel.GetStart() ); >- ShowCursor( sal_True, sal_False ); >- } >- else >- { >- aSel = GetSelection().GetEnd(); >- } >- >- SetSelection( aSel ); >- ShowCursor(); >- >- return bFound; >-} >- >-sal_uInt16 ExtTextView::Replace( const util::SearchOptions& rSearchOptions, sal_Bool bAll, sal_Bool bForward ) >-{ >- sal_uInt16 nFound = 0; >- >- if ( !bAll ) >- { >- if ( GetSelection().HasRange() ) >- { >- InsertText( rSearchOptions.replaceString ); >- nFound = 1; >- Search( rSearchOptions, bForward ); // gleich zum naechsten >- } >- else >- { >- if( Search( rSearchOptions, bForward ) ) >- nFound = 1; >- } >- } >- else >- { >- // Der Writer ersetzt alle, vom Anfang bis Ende... >- >- ExtTextEngine* pTextEngine = (ExtTextEngine*)GetTextEngine(); >- >- // HideSelection(); >- TextSelection aSel; >- >- sal_Bool bSearchInSelection = (0 != (rSearchOptions.searchFlag & util::SearchFlags::REG_NOT_BEGINOFLINE) ); >- if ( bSearchInSelection ) >- { >- aSel = GetSelection(); >- aSel.Justify(); >- } >- >- TextSelection aSearchSel( aSel ); >- >- sal_Bool bFound = pTextEngine->Search( aSel, rSearchOptions, sal_True ); >- if ( bFound ) >- pTextEngine->UndoActionStart(); >- while ( bFound ) >- { >- nFound++; >- >- TextPaM aNewStart = pTextEngine->ImpInsertText( aSel, rSearchOptions.replaceString ); >- aSel = aSearchSel; >- aSel.GetStart() = aNewStart; >- bFound = pTextEngine->Search( aSel, rSearchOptions, sal_True ); >- } >- if ( nFound ) >- { >- SetSelection( aSel.GetStart() ); >- pTextEngine->FormatAndUpdate( this ); >- pTextEngine->UndoActionEnd(); >- } >- } >- return nFound; >-} >- >-sal_Bool ExtTextView::ImpIndentBlock( sal_Bool bRight ) >-{ >- sal_Bool bDone = sal_False; >- >- TextSelection aSel = GetSelection(); >- aSel.Justify(); >- >- HideSelection(); >- GetTextEngine()->UndoActionStart(); >- >- sal_uLong nStartPara = aSel.GetStart().GetPara(); >- sal_uLong nEndPara = aSel.GetEnd().GetPara(); >- if ( aSel.HasRange() && !aSel.GetEnd().GetIndex() ) >- { >- nEndPara--; // den dann nicht einruecken... >- } >- >- for ( sal_uLong nPara = nStartPara; nPara <= nEndPara; nPara++ ) >- { >- if ( bRight ) >- { >- // Tabs hinzufuegen >- GetTextEngine()->ImpInsertText( TextPaM( nPara, 0 ), '\t' ); >- bDone = sal_True; >- } >- else >- { >- // Tabs/Blanks entfernen >- String aText = GetTextEngine()->GetText( nPara ); >- if ( aText.Len() && ( >- ( aText.GetChar( 0 ) == '\t' ) || >- ( aText.GetChar( 0 ) == ' ' ) ) ) >- { >- GetTextEngine()->ImpDeleteText( TextSelection( TextPaM( nPara, 0 ), TextPaM( nPara, 1 ) ) ); >- bDone = sal_True; >- } >- } >- } >- >- GetTextEngine()->UndoActionEnd(); >- >- sal_Bool bRange = aSel.HasRange(); >- if ( bRight ) >- { >- aSel.GetStart().GetIndex()++; >- if ( bRange && ( aSel.GetEnd().GetPara() == nEndPara ) ) >- aSel.GetEnd().GetIndex()++; >- } >- else >- { >- if ( aSel.GetStart().GetIndex() ) >- aSel.GetStart().GetIndex()--; >- if ( bRange && aSel.GetEnd().GetIndex() ) >- aSel.GetEnd().GetIndex()--; >- } >- >- ImpSetSelection( aSel ); >- GetTextEngine()->FormatAndUpdate( this ); >- >- return bDone; >-} >- >-sal_Bool ExtTextView::IndentBlock() >-{ >- return ImpIndentBlock( sal_True ); >-} >- >-sal_Bool ExtTextView::UnindentBlock() >-{ >- return ImpIndentBlock( sal_False ); >-} >- >-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/svx/source/dialog/docrecovery.cxx b/svx/source/dialog/docrecovery.cxx >index 32685fa..f5fdf8d 100644 >--- a/svx/source/dialog/docrecovery.cxx >+++ b/svx/source/dialog/docrecovery.cxx >@@ -40,7 +40,7 @@ > #include <comphelper/sequenceashashmap.hxx> > #include <comphelper/string.hxx> > #include <svtools/imagemgr.hxx> >-#include <svtools/xtextedt.hxx> >+#include <vcl/xtextedt.hxx> > #include <tools/urlobj.hxx> > #include <vcl/msgbox.hxx> > #include <vcl/svapp.hxx> >diff --git a/sw/source/ui/dbui/mmaddressblockpage.cxx b/sw/source/ui/dbui/mmaddressblockpage.cxx >index 5cde4aa..a9c86b2 100644 >--- a/sw/source/ui/dbui/mmaddressblockpage.cxx >+++ b/sw/source/ui/dbui/mmaddressblockpage.cxx >@@ -33,8 +33,8 @@ > #include <mailmergewizard.hxx> > #include <swtypes.hxx> > #include <addresslistdialog.hxx> >-#include <svtools/xtextedt.hxx> >-#include <svtools/txtattr.hxx> >+#include <vcl/xtextedt.hxx> >+#include <vcl/txtattr.hxx> > #include <vcl/msgbox.hxx> > #include <mmconfigitem.hxx> > #include <com/sun/star/container/XNameAccess.hpp> >diff --git a/sw/source/ui/docvw/srcedtw.cxx b/sw/source/ui/docvw/srcedtw.cxx >index c6bb14f..66273f9 100644 >--- a/sw/source/ui/docvw/srcedtw.cxx >+++ b/sw/source/ui/docvw/srcedtw.cxx >@@ -38,13 +38,13 @@ > #include <rtl/oustringostreaminserter.hxx> > #include <rtl/ustring.hxx> > #include <sal/log.hxx> >-#include <svtools/textview.hxx> >+#include <vcl/textview.hxx> > #include <svx/svxids.hrc> > #include <vcl/scrbar.hxx> > #include <sfx2/dispatch.hxx> > #include <sfx2/app.hxx> > #include <svtools/htmltokn.h> >-#include <svtools/txtattr.hxx> >+#include <vcl/txtattr.hxx> > #include <svtools/colorcfg.hxx> > #include <editeng/flstitem.hxx> > #include <vcl/metric.hxx> >diff --git a/sw/source/ui/inc/srcedtw.hxx b/sw/source/ui/inc/srcedtw.hxx >index 8f4a443..74e1f42 100644 >--- a/sw/source/ui/inc/srcedtw.hxx >+++ b/sw/source/ui/inc/srcedtw.hxx >@@ -32,7 +32,7 @@ > #include <svl/lstner.hxx> > #include <vcl/timer.hxx> > >-#include <svtools/xtextedt.hxx> >+#include <vcl/xtextedt.hxx> > #include <set> > > namespace com { namespace sun { namespace star { namespace beans { >diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk >index 77717fd..daa5176 100644 >--- a/vcl/Library_vcl.mk >+++ b/vcl/Library_vcl.mk >@@ -68,6 +68,7 @@ $(eval $(call gb_Library_add_defs,vcl,\ > $(eval $(call gb_Library_use_sdk_api,vcl)) > > $(eval $(call gb_Library_use_libraries,vcl,\ >+ svl \ > tl \ > utl \ > sot \ >@@ -143,6 +144,14 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ > vcl/source/control/spinfld \ > vcl/source/control/tabctrl \ > vcl/source/control/throbber \ >+ vcl/source/edit/vclmedit \ >+ vcl/source/edit/textdata \ >+ vcl/source/edit/textdoc \ >+ vcl/source/edit/texteng \ >+ vcl/source/edit/textundo \ >+ vcl/source/edit/textview \ >+ vcl/source/edit/txtattr \ >+ vcl/source/edit/xtextedt \ > vcl/source/fontsubset/cff \ > vcl/source/fontsubset/fontsubset \ > vcl/source/fontsubset/gsub \ >diff --git a/vcl/Package_inc.mk b/vcl/Package_inc.mk >index 0da4b14..c5e6fbf 100644 >--- a/vcl/Package_inc.mk >+++ b/vcl/Package_inc.mk >@@ -151,19 +151,26 @@ $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/tabctrl.hxx,vcl/tabctrl.hxx)) > $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/tabdlg.hxx,vcl/tabdlg.hxx)) > $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/tabpage.hxx,vcl/tabpage.hxx)) > $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/taskpanelist.hxx,vcl/taskpanelist.hxx)) >+$(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/textdata.hxx,vcl/textdata.hxx)) >+$(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/texteng.hxx,vcl/texteng.hxx)) >+$(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/textview.hxx,vcl/textview.hxx)) > $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/threadex.hxx,vcl/threadex.hxx)) > $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/throbber.hxx,vcl/throbber.hxx)) > $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/timer.hxx,vcl/timer.hxx)) > $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/toolbox.hxx,vcl/toolbox.hxx)) >+$(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/txtattr.hxx,vcl/txtattr.hxx)) > $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/unohelp2.hxx,vcl/unohelp2.hxx)) > $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/unohelp.hxx,vcl/unohelp.hxx)) > $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/unowrap.hxx,vcl/unowrap.hxx)) > $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/vclenum.hxx,vcl/vclenum.hxx)) > $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/vclevent.hxx,vcl/vclevent.hxx)) >+$(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/vclmedit.hxx,vcl/vclmedit.hxx)) > $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/virdev.hxx,vcl/virdev.hxx)) > $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/waitobj.hxx,vcl/waitobj.hxx)) > $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/wall.hxx,vcl/wall.hxx)) > $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/window.hxx,vcl/window.hxx)) > $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/wrkwin.hxx,vcl/wrkwin.hxx)) >+$(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/xtextedt.hxx,vcl/xtextedt.hxx)) >+ > > # vim: set noet sw=4 ts=4: >diff --git a/vcl/inc/vcl/msgbox.hxx b/vcl/inc/vcl/msgbox.hxx >index 1d76e13..2bb73ab 100644 >--- a/vcl/inc/vcl/msgbox.hxx >+++ b/vcl/inc/vcl/msgbox.hxx >@@ -34,7 +34,7 @@ > #include <vcl/btndlg.hxx> > #include <vcl/image.hxx> > #include <vcl/bitmap.hxx> >-class FixedText; >+class VCLMultiLineEdit; > class FixedImage; > class CheckBox; > >@@ -67,7 +67,7 @@ class CheckBox; > class VCL_DLLPUBLIC MessBox : public ButtonDialog > { > protected: >- FixedText* mpFixedText; >+ VCLMultiLineEdit* mpVCLMultiLineEdit; > FixedImage* mpFixedImage; > XubString maMessText; > Image maImage; >diff --git a/vcl/inc/vcl/textdata.hxx b/vcl/inc/vcl/textdata.hxx >new file mode 100644 >index 0000000..4ee0e2f >--- /dev/null >+++ b/vcl/inc/vcl/textdata.hxx >@@ -0,0 +1,172 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >+/* >+ * This file is part of the LibreOffice project. >+ * >+ * This Source Code Form is subject to the terms of the Mozilla Public >+ * License, v. 2.0. If a copy of the MPL was not distributed with this >+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. >+ * >+ * This file incorporates work covered by the following license notice: >+ * >+ * Licensed to the Apache Software Foundation (ASF) under one or more >+ * contributor license agreements. See the NOTICE file distributed >+ * with this work for additional information regarding copyright >+ * ownership. The ASF licenses this file to you under the Apache >+ * License, Version 2.0 (the "License"); you may not use this file >+ * except in compliance with the License. You may obtain a copy of >+ * the License at http://www.apache.org/licenses/LICENSE-2.0 . >+ */ >+ >+#ifndef _TEXTDATA_HXX >+#define _TEXTDATA_HXX >+ >+#include <vcl/dllapi.h> >+#include <svl/brdcst.hxx> >+#include <svl/smplhint.hxx> >+#include <tools/string.hxx> >+ >+// Fuer Notify, wenn alle Absaetze geloescht wurden... >+#define TEXT_PARA_ALL 0xFFFFFFFF >+ >+class TextPaM >+{ >+private: >+ sal_uLong mnPara; >+ sal_uInt16 mnIndex; >+ >+public: >+ TextPaM() { mnPara = 0, mnIndex = 0; } >+ TextPaM( sal_uLong nPara, sal_uInt16 nIndex ) { mnPara = nPara, mnIndex = nIndex; } >+ >+ sal_uLong GetPara() const { return mnPara; } >+ sal_uLong& GetPara() { return mnPara; } >+ >+ sal_uInt16 GetIndex() const { return mnIndex; } >+ sal_uInt16& GetIndex() { return mnIndex; } >+ >+ inline sal_Bool operator == ( const TextPaM& rPaM ) const; >+ inline sal_Bool operator != ( const TextPaM& rPaM ) const; >+ inline sal_Bool operator < ( const TextPaM& rPaM ) const; >+ inline sal_Bool operator > ( const TextPaM& rPaM ) const; >+}; >+ >+inline sal_Bool TextPaM::operator == ( const TextPaM& rPaM ) const >+{ >+ return ( ( mnPara == rPaM.mnPara ) && ( mnIndex == rPaM.mnIndex ) ) ? sal_True : sal_False; >+} >+ >+inline sal_Bool TextPaM::operator != ( const TextPaM& rPaM ) const >+{ >+ return !( *this == rPaM ); >+} >+ >+inline sal_Bool TextPaM::operator < ( const TextPaM& rPaM ) const >+{ >+ return ( ( mnPara < rPaM.mnPara ) || >+ ( ( mnPara == rPaM.mnPara ) && mnIndex < rPaM.mnIndex ) ) ? sal_True : sal_False; >+} >+ >+inline sal_Bool TextPaM::operator > ( const TextPaM& rPaM ) const >+{ >+ return ( ( mnPara > rPaM.mnPara ) || >+ ( ( mnPara == rPaM.mnPara ) && mnIndex > rPaM.mnIndex ) ) ? sal_True : sal_False; >+} >+ >+class VCL_DLLPUBLIC TextSelection >+{ >+private: >+ TextPaM maStartPaM; >+ TextPaM maEndPaM; >+ >+public: >+ TextSelection(); >+ TextSelection( const TextPaM& rPaM ); >+ TextSelection( const TextPaM& rStart, const TextPaM& rEnd ); >+ >+ const TextPaM& GetStart() const { return maStartPaM; } >+ TextPaM& GetStart() { return maStartPaM; } >+ >+ const TextPaM& GetEnd() const { return maEndPaM; } >+ TextPaM& GetEnd() { return maEndPaM; } >+ >+ void Justify(); >+ >+ sal_Bool HasRange() const { return maStartPaM != maEndPaM; } >+ >+ inline sal_Bool operator == ( const TextSelection& rSel ) const; >+ inline sal_Bool operator != ( const TextSelection& rSel ) const; >+}; >+ >+inline sal_Bool TextSelection::operator == ( const TextSelection& rSel ) const >+{ >+ return ( ( maStartPaM == rSel.maStartPaM ) && ( maEndPaM == rSel.maEndPaM ) ); >+} >+ >+inline sal_Bool TextSelection::operator != ( const TextSelection& rSel ) const >+{ >+ return !( *this == rSel ); >+} >+ >+#define TEXT_HINT_PARAINSERTED 1 >+#define TEXT_HINT_PARAREMOVED 2 >+#define TEXT_HINT_PARACONTENTCHANGED 3 >+#define TEXT_HINT_TEXTHEIGHTCHANGED 4 >+#define TEXT_HINT_FORMATPARA 5 >+#define TEXT_HINT_TEXTFORMATTED 6 >+#define TEXT_HINT_MODIFIED 7 >+#define TEXT_HINT_BLOCKNOTIFICATION_START 8 >+#define TEXT_HINT_BLOCKNOTIFICATION_END 9 >+#define TEXT_HINT_INPUT_START 10 >+#define TEXT_HINT_INPUT_END 11 >+ >+#define TEXT_HINT_VIEWSCROLLED 100 >+#define TEXT_HINT_VIEWSELECTIONCHANGED 101 >+ >+class VCL_DLLPUBLIC TextHint : public SfxSimpleHint >+{ >+private: >+ sal_uLong mnValue; >+ >+public: >+ TYPEINFO(); >+ TextHint( sal_uLong nId ); >+ TextHint( sal_uLong nId, sal_uLong nValue ); >+ >+ sal_uLong GetValue() const { return mnValue; } >+ void SetValue( sal_uLong n ) { mnValue = n; } >+}; >+ >+struct TEIMEInfos >+{ >+ String aOldTextAfterStartPos; >+ sal_uInt16* pAttribs; >+ TextPaM aPos; >+ sal_uInt16 nLen; >+ sal_Bool bCursor; >+ sal_Bool bWasCursorOverwrite; >+ >+ TEIMEInfos( const TextPaM& rPos, const String& rOldTextAfterStartPos ); >+ ~TEIMEInfos(); >+ >+ void CopyAttribs( const sal_uInt16* pA, sal_uInt16 nL ); >+ void DestroyAttribs(); >+}; >+ >+// ----------------- Wrapper for old Tools List ------------------- >+ >+#include <vector> >+#include <algorithm> >+ >+template <class T> class ToolsList : public ::std::vector< T > >+{ >+public: >+ sal_uLong Count() const { return static_cast<sal_uLong>(::std::vector< T >::size()); } >+ sal_uLong GetPos( T pObject ) const { return ( ::std::find( this->begin(), this->end(), pObject ) ) - this->begin(); } >+ T GetObject( sal_uLong nIndex ) const { return (*this)[nIndex]; } >+ void Insert( T pObject, sal_uLong nPos ) { ::std::vector< T >::insert( this->begin()+nPos, pObject ); } >+ void Remove( sal_uLong nPos ) { ::std::vector< T >::erase( this->begin()+nPos ); } >+}; >+ >+#endif // _TEXTDATA_HXX >+ >+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/vcl/inc/vcl/texteng.hxx b/vcl/inc/vcl/texteng.hxx >new file mode 100644 >index 0000000..4eeee73 >--- /dev/null >+++ b/vcl/inc/vcl/texteng.hxx >@@ -0,0 +1,332 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >+/************************************************************************* >+ * >+ * 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 _TEXTENG_HXX >+#define _TEXTENG_HXX >+ >+#include <vcl/dllapi.h> >+ >+class TextDoc; >+class TextView; >+class TextPaM; >+class TextSelection; >+class TEParaPortions; >+class TextAttrib; >+class TextCharAttrib; >+class TextUndo; >+class TextUndoManager; >+class EditSelFunctionSet; >+class EditSelEngine; >+class IdleFormatter; >+class TextNode; >+class OutputDevice; >+class SfxUndoAction; >+class KeyEvent; >+class Timer; >+ >+namespace svl >+{ >+ class IUndoManager; >+} >+ >+class TextLine; >+class TETextPortion; >+#include <svl/brdcst.hxx> >+#include <tools/link.hxx> >+#include <vcl/font.hxx> >+#include <tools/string.hxx> >+#include <tools/gen.hxx> >+ >+#include <com/sun/star/lang/Locale.hpp> >+#include <com/sun/star/uno/Reference.hxx> >+ >+struct TEIMEInfos; >+class SvtCTLOptions; >+ >+namespace com { >+namespace sun { >+namespace star { >+namespace i18n { >+ class XBreakIterator; >+ class XExtendedInputSequenceChecker; >+}}}} >+ >+class LocaleDataWrapper; >+ >+enum TxtAlign { TXTALIGN_LEFT, TXTALIGN_CENTER, TXTALIGN_RIGHT }; >+ >+typedef std::vector<TextView*> TextViews; >+ >+class VCL_DLLPUBLIC TextEngine : public SfxBroadcaster >+{ >+ friend class TextView; >+ friend class TextSelFunctionSet; >+ friend class ExtTextEngine; >+ friend class ExtTextView; >+ >+ friend class TextUndo; >+ friend class TextUndoManager; >+ friend class TextUndoDelPara; >+ friend class TextUndoConnectParas; >+ friend class TextUndoSplitPara; >+ friend class TextUndoInsertChars; >+ friend class TextUndoRemoveChars; >+ friend class TextUndoSetAttribs; >+ >+private: >+ TextDoc* mpDoc; >+ TEParaPortions* mpTEParaPortions; >+ OutputDevice* mpRefDev; >+ >+ TextViews* mpViews; >+ TextView* mpActiveView; >+ >+ TextUndoManager* mpUndoManager; >+ >+ IdleFormatter* mpIdleFormatter; >+ >+ TEIMEInfos* mpIMEInfos; >+ >+ ::com::sun::star::lang::Locale maLocale; >+ ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XBreakIterator > mxBreakIterator; >+ >+ Rectangle maInvalidRec; >+ Range maInvalidRange; >+ >+ LocaleDataWrapper* mpLocaleDataWrapper; >+ >+ Font maFont; >+ Color maTextColor; >+ sal_uInt16 mnCharHeight; >+ sal_uInt16 mnFixCharWidth100; >+ >+ sal_uLong mnMaxTextLen; >+ sal_uLong mnMaxTextWidth; >+ sal_uLong mnCurTextWidth; >+ sal_uLong mnCurTextHeight; >+ sal_uLong mnDefTab; >+ >+ TxtAlign meAlign; >+ >+ sal_Bool mbIsFormatting : 1; // Semaphore wegen der Hook's >+ sal_Bool mbFormatted : 1; >+ sal_Bool mbUpdate : 1; >+ sal_Bool mbModified : 1; >+ sal_Bool mbUndoEnabled : 1; >+ sal_Bool mbIsInUndo : 1; >+ sal_Bool mbDowning : 1; >+ sal_Bool mbRightToLeft : 1; >+ sal_Bool mbHasMultiLineParas : 1; >+ >+ TextEngine( const TextEngine& ) : SfxBroadcaster() {} >+ TextEngine& operator=( const TextEngine& ) { return *this; } >+ >+protected: >+ >+ void CursorMoved( sal_uLong nNode ); >+ void TextModified(); >+ >+ void ImpInitDoc(); >+ void ImpRemoveText(); >+ TextPaM ImpDeleteText( const TextSelection& rSel ); >+ TextPaM ImpInsertText( const TextSelection& rSel, sal_Unicode c, sal_Bool bOverwrite = sal_False ); >+ TextPaM ImpInsertText( const TextSelection& rSel, const String& rText ); >+ TextPaM ImpInsertParaBreak( const TextSelection& rTextSelection, sal_Bool bKeepEndingAttribs = sal_True ); >+ TextPaM ImpInsertParaBreak( const TextPaM& rPaM, sal_Bool bKeepEndingAttribs = sal_True ); >+ void ImpRemoveChars( const TextPaM& rPaM, sal_uInt16 nChars, SfxUndoAction* pCurUndo = 0 ); >+ TextPaM ImpConnectParagraphs( sal_uLong nLeft, sal_uLong nRight ); >+ void ImpRemoveParagraph( sal_uLong nPara ); >+ void ImpInitWritingDirections( sal_uLong nPara ); >+ LocaleDataWrapper* ImpGetLocaleDataWrapper(); >+ >+ // to remain compatible in the minor release we copy the above ImpInsertText >+ // function and add the extra parameter we need but make sure this function >+ // gets not exported. First and seconf parameter swapped to have a different signatur. >+ SAL_DLLPRIVATE TextPaM ImpInsertText( sal_Unicode c, const TextSelection& rSel, sal_Bool bOverwrite = sal_False, sal_Bool bIsUserInput = sal_False ); >+ // some other new functions needed that must not be exported to remain compatible >+ SAL_DLLPRIVATE ::com::sun::star::uno::Reference < ::com::sun::star::i18n::XExtendedInputSequenceChecker > GetInputSequenceChecker() const; >+ SAL_DLLPRIVATE sal_Bool IsInputSequenceCheckingRequired( sal_Unicode c, const TextSelection& rCurSel ) const; >+ >+ // Broadcasten bzw. Selektionen anpassen: >+ void ImpParagraphInserted( sal_uLong nPara ); >+ void ImpParagraphRemoved( sal_uLong nPara ); >+ void ImpCharsRemoved( sal_uLong nPara, sal_uInt16 nPos, sal_uInt16 nChars ); >+ void ImpCharsInserted( sal_uLong nPara, sal_uInt16 nPos, sal_uInt16 nChars ); >+ void ImpFormattingParagraph( sal_uLong nPara ); >+ void ImpTextHeightChanged(); >+ void ImpTextFormatted(); >+ >+ DECL_LINK( IdleFormatHdl, void * ); >+ void CheckIdleFormatter(); >+ void IdleFormatAndUpdate( TextView* pCurView = 0, sal_uInt16 nMaxTimerRestarts = 5 ); >+ >+ sal_Bool CreateLines( sal_uLong nPara ); >+ void CreateAndInsertEmptyLine( sal_uLong nPara ); >+ void ImpBreakLine( sal_uLong nPara, TextLine* pLine, TETextPortion* pPortion, sal_uInt16 nPortionStart, long nRemainingWidth ); >+ sal_uInt16 SplitTextPortion( sal_uLong nPara, sal_uInt16 nPos ); >+ void CreateTextPortions( sal_uLong nPara, sal_uInt16 nStartPos ); >+ void RecalcTextPortion( sal_uLong nPara, sal_uInt16 nStartPos, short nNewChars ); >+ void SeekCursor( sal_uLong nNode, sal_uInt16 nPos, Font& rFont, OutputDevice* pOutDev ); >+ >+ void FormatDoc(); >+ void FormatFullDoc(); >+ void FormatAndUpdate( TextView* pCurView = 0 ); >+ sal_Bool IsFormatting() const { return mbIsFormatting; } >+ void UpdateViews( TextView* pCurView = 0 ); >+ >+ void ImpPaint( OutputDevice* pOut, const Point& rStartPos, Rectangle const* pPaintArea, TextSelection const* pPaintRange = 0, TextSelection const* pSelection = 0 ); >+ >+ void UpdateSelections(); >+ >+ sal_Bool IsFormatted() const { return mbFormatted; } >+ >+ sal_uInt16 GetCharPos( sal_uLong nPara, sal_uInt16 nLine, long nDocPosX, sal_Bool bSmart = sal_False ); >+ Rectangle GetEditCursor( const TextPaM& rPaM, sal_Bool bSpecial, sal_Bool bPreferPortionStart = sal_False ); >+ sal_uInt16 ImpFindIndex( sal_uLong nPortion, const Point& rPosInPara, sal_Bool bSmart ); >+ long ImpGetPortionXOffset( sal_uLong nPara, TextLine* pLine, sal_uInt16 nTextPortion ); >+ long ImpGetXPos( sal_uLong nPara, TextLine* pLine, sal_uInt16 nIndex, sal_Bool bPreferPortionStart = sal_False ); >+ long ImpGetOutputOffset( sal_uLong nPara, TextLine* pLine, sal_uInt16 nIndex, sal_uInt16 nIndex2 ); >+ sal_uInt8 ImpGetRightToLeft( sal_uLong nPara, sal_uInt16 nPos, sal_uInt16* pStart = NULL, sal_uInt16* pEnd = NULL ); >+ void ImpInitLayoutMode( OutputDevice* pOutDev, sal_Bool bDrawingR2LPortion = sal_False ); >+ TxtAlign ImpGetAlign() const; >+ >+ sal_uLong CalcTextHeight(); >+ sal_uLong CalcParaHeight( sal_uLong nParagraph ) const; >+ sal_uLong CalcTextWidth( sal_uLong nPara ); >+ sal_uLong CalcTextWidth( sal_uLong nPara, sal_uInt16 nPortionStart, sal_uInt16 nPortionLen, const Font* pFont = 0 ); >+ Range GetInvalidYOffsets( sal_uLong nPortion ); >+ >+ // Fuer Undo/Redo >+ void InsertContent( TextNode* pNode, sal_uLong nPara ); >+ TextPaM SplitContent( sal_uLong nNode, sal_uInt16 nSepPos ); >+ TextPaM ConnectContents( sal_uLong nLeftNode ); >+ >+ // Ans API uebergebene PaM's und Selektionen auf einen gueltigen Bereich einstellen >+ void ValidateSelection( TextSelection& rSel ) const; >+ void ValidatePaM( TextPaM& rPaM ) const; >+ >+public: >+ TextEngine(); >+ ~TextEngine(); >+ >+ void SetText( const String& rStr ); >+ String GetText( LineEnd aSeparator = LINEEND_LF ) const; >+ String GetText( const TextSelection& rSel, LineEnd aSeparator = LINEEND_LF ) const; >+ String GetTextLines( LineEnd aSeparator = LINEEND_LF ) const; >+ void ReplaceText(const TextSelection& rSel, const String& rText); >+ >+ sal_uLong GetTextLen( LineEnd aSeparator = LINEEND_LF ) const; >+ sal_uLong GetTextLen( const TextSelection& rSel, LineEnd aSeparator = LINEEND_LF ) const; >+ >+ void SetFont( const Font& rFont ); >+ const Font& GetFont() const { return maFont; } >+ >+ sal_uInt16 GetDefTab() const; >+ >+ void SetLeftMargin( sal_uInt16 n ); >+ sal_uInt16 GetLeftMargin() const; >+ >+ void SetUpdateMode( sal_Bool bUpdate ); >+ sal_Bool GetUpdateMode() const { return mbUpdate; } >+ >+ sal_uInt16 GetViewCount() const; >+ TextView* GetView( sal_uInt16 nView ) const; >+ void InsertView( TextView* pTextView ); >+ void RemoveView( TextView* pTextView ); >+ TextView* GetActiveView() const; >+ void SetActiveView( TextView* pView ); >+ >+ void SetMaxTextLen( sal_uLong nLen ); >+ sal_uLong GetMaxTextLen() const { return mnMaxTextLen; } >+ >+ void SetMaxTextWidth( sal_uLong nWidth ); >+ sal_uLong GetMaxTextWidth() const { return mnMaxTextWidth; } >+ >+ sal_uLong GetTextHeight() const; >+ sal_uLong CalcTextWidth(); >+ sal_uInt16 GetCharHeight() const { return mnCharHeight; } >+ >+ sal_uLong GetParagraphCount() const; >+ String GetText( sal_uLong nParagraph ) const; >+ sal_uInt16 GetTextLen( sal_uLong nParagraph ) const; >+ sal_uLong GetTextHeight( sal_uLong nParagraph ) const; >+ >+ sal_uInt16 GetLineCount( sal_uLong nParagraph ) const; >+ sal_uInt16 GetLineLen( sal_uLong nParagraph, sal_uInt16 nLine ) const; >+ >+ void SetRightToLeft( sal_Bool bR2L ); >+ sal_Bool IsRightToLeft() const { return mbRightToLeft; } >+ >+ sal_Bool HasUndoManager() const { return mpUndoManager ? sal_True : sal_False; } >+ ::svl::IUndoManager& >+ GetUndoManager(); >+ void UndoActionStart( sal_uInt16 nId = 0 ); >+ void UndoActionEnd(); >+ void InsertUndo( TextUndo* pUndo, sal_Bool bTryMerge = sal_False ); >+ sal_Bool IsInUndo() { return mbIsInUndo; } >+ void SetIsInUndo( sal_Bool bInUndo ) { mbIsInUndo = bInUndo; } >+ void ResetUndo(); >+ >+ void EnableUndo( sal_Bool bEnable ); >+ sal_Bool IsUndoEnabled() { return mbUndoEnabled; } >+ >+ void SetModified( sal_Bool bModified ) { mbModified = bModified; } >+ sal_Bool IsModified() const { return mbModified; } >+ >+ sal_Bool Read( SvStream& rInput, const TextSelection* pSel = NULL ); >+ >+ sal_Bool Write( SvStream& rOutput, const TextSelection* pSel = NULL, sal_Bool bHTML = sal_False ); >+ >+ TextPaM GetPaM( const Point& rDocPos, sal_Bool bSmart = sal_True ); >+ Rectangle PaMtoEditCursor( const TextPaM& rPaM, sal_Bool bSpecial = sal_False ); >+ String GetWord( const TextPaM& rCursorPos, TextPaM* pStartOfWord = 0 ); >+ >+ sal_Bool HasAttrib( sal_uInt16 nWhich ) const; >+ const TextAttrib* FindAttrib( const TextPaM& rPaM, sal_uInt16 nWhich ) const; >+ const TextCharAttrib* FindCharAttrib( const TextPaM& rPaM, sal_uInt16 nWhich ) const; >+ >+ void RemoveAttribs( sal_uLong nPara, sal_uInt16 nWhich, sal_Bool bIdleFormatAndUpdate ); >+ void RemoveAttrib( sal_uLong nPara, const TextCharAttrib& rAttrib ); >+ void RemoveAttribs( sal_uLong nPara, sal_Bool bIdleFormatAndUpdate = sal_True ); >+ void SetAttrib( const TextAttrib& rAttr, sal_uLong nPara, sal_uInt16 nStart, sal_uInt16 nEnd, sal_Bool bIdleFormatAndUpdate = sal_True ); >+ >+ TxtAlign GetTextAlign() const { return meAlign; } >+ void SetTextAlign( TxtAlign eAlign ); >+ >+ void Draw( OutputDevice* pDev, const Point& rPos ); >+ >+ void SetLocale( const ::com::sun::star::lang::Locale& rLocale ); >+ ::com::sun::star::lang::Locale GetLocale(); >+ ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XBreakIterator > GetBreakIterator(); >+ >+ static sal_Bool DoesKeyChangeText( const KeyEvent& rKeyEvent ); >+ static sal_Bool IsSimpleCharInput( const KeyEvent& rKeyEvent ); >+}; >+ >+#endif // _TEXTENG_HXX >+ >+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/vcl/inc/vcl/textview.hxx b/vcl/inc/vcl/textview.hxx >new file mode 100644 >index 0000000..72de5f0 >--- /dev/null >+++ b/vcl/inc/vcl/textview.hxx >@@ -0,0 +1,217 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >+/************************************************************************* >+ * >+ * 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 _TEXTVIEW_HXX >+#define _TEXTVIEW_HXX >+ >+#include <vcl/dllapi.h> >+#include <vcl/textdata.hxx> >+#include <tools/gen.hxx> >+#include <vcl/dndhelp.hxx> >+ >+class TextEngine; >+class OutputDevice; >+class Window; >+class Cursor; >+class KeyEvent; >+class MouseEvent; >+class CommandEvent; >+class TextSelFunctionSet; >+class SelectionEngine; >+class VirtualDevice; >+struct TextDDInfo; >+ >+namespace com { >+namespace sun { >+namespace star { >+namespace datatransfer { >+namespace clipboard { >+ class XClipboard; >+}}}}} >+ >+struct ImpTextView; >+ >+class VCL_DLLPUBLIC TextView : public vcl::unohelper::DragAndDropClient >+{ >+ friend class TextEngine; >+ friend class TextUndo; >+ friend class TextUndoManager; >+ friend class TextSelFunctionSet; >+ friend class ExtTextView; >+ >+private: >+ ImpTextView* mpImpl; >+ >+ TextView( const TextView& ) : vcl::unohelper::DragAndDropClient() {} >+ TextView& operator=( const TextView& ) { return *this; } >+ >+protected: >+ void ShowSelection(); >+ void HideSelection(); >+ void ShowSelection( const TextSelection& rSel ); >+ void ImpShowHideSelection( sal_Bool bShow, const TextSelection* pRange = NULL ); >+ >+ TextSelection ImpMoveCursor( const KeyEvent& rKeyEvent ); >+ TextPaM ImpDelete( sal_uInt8 nMode, sal_uInt8 nDelMode ); >+ void ImpSetSelection( const TextSelection& rNewSel, sal_Bool bUI ); >+ sal_Bool IsInSelection( const TextPaM& rPaM ); >+ >+ void ImpPaint( OutputDevice* pOut, const Point& rStartPos, Rectangle const* pPaintArea, TextSelection const* pPaintRange = 0, TextSelection const* pSelection = 0 ); >+ void ImpPaint( const Rectangle& rRect, sal_Bool bUseVirtDev ); >+ void ImpShowCursor( sal_Bool bGotoCursor, sal_Bool bForceVisCursor, sal_Bool bEndKey ); >+ void ImpHighlight( const TextSelection& rSel ); >+ void ImpSetSelection( const TextSelection& rSelection ); >+ Point ImpGetOutputStartPos( const Point& rStartDocPos ) const; >+ >+ void ImpHideDDCursor(); >+ void ImpShowDDCursor(); >+ >+ bool ImplTruncateNewText( rtl::OUString& rNewText ) const; >+ sal_Bool ImplCheckTextLen( const String& rNewText ); >+ >+ VirtualDevice* GetVirtualDevice(); >+ >+ // DragAndDropClient >+ virtual void dragGestureRecognized( const ::com::sun::star::datatransfer::dnd::DragGestureEvent& dge ) throw (::com::sun::star::uno::RuntimeException); >+ virtual void dragDropEnd( const ::com::sun::star::datatransfer::dnd::DragSourceDropEvent& dsde ) throw (::com::sun::star::uno::RuntimeException); >+ virtual void drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEvent& dtde ) throw (::com::sun::star::uno::RuntimeException); >+ virtual void dragEnter( const ::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent& dtdee ) throw (::com::sun::star::uno::RuntimeException); >+ virtual void dragExit( const ::com::sun::star::datatransfer::dnd::DropTargetEvent& dte ) throw (::com::sun::star::uno::RuntimeException); >+ virtual void dragOver( const ::com::sun::star::datatransfer::dnd::DropTargetDragEvent& dtde ) throw (::com::sun::star::uno::RuntimeException); >+ >+ using DragAndDropClient::dragEnter; >+ using DragAndDropClient::dragExit; >+ using DragAndDropClient::dragOver; >+ >+public: >+ TextView( TextEngine* pEng, Window* pWindow ); >+ virtual ~TextView(); >+ >+ TextEngine* GetTextEngine() const; >+ Window* GetWindow() const; >+ >+ void Invalidate(); >+ void Scroll( long nHorzScroll, long nVertScroll ); >+ >+ void ShowCursor( sal_Bool bGotoCursor = sal_True, sal_Bool bForceVisCursor = sal_True ); >+ void HideCursor(); >+ >+ void EnableCursor( sal_Bool bEnable ); >+ sal_Bool IsCursorEnabled() const; >+ >+ const TextSelection& GetSelection() const; >+ TextSelection& GetSelection(); >+ void SetSelection( const TextSelection& rNewSel ); >+ void SetSelection( const TextSelection& rNewSel, sal_Bool bGotoCursor ); >+ sal_Bool HasSelection() const; >+ >+ String GetSelected(); >+ String GetSelected( LineEnd aSeparator ); >+ void DeleteSelected(); >+ >+ void InsertNewText( const rtl::OUString& rNew, sal_Bool bSelect = sal_False ); >+ // deprecated: use InsertNewText instead >+ void InsertText( const String& rNew, sal_Bool bSelect = sal_False ); >+ >+ sal_Bool KeyInput( const KeyEvent& rKeyEvent ); >+ void Paint( const Rectangle& rRect ); >+ void MouseButtonUp( const MouseEvent& rMouseEvent ); >+ void MouseButtonDown( const MouseEvent& rMouseEvent ); >+ void MouseMove( const MouseEvent& rMouseEvent ); >+ void Command( const CommandEvent& rCEvt ); >+ >+ void Cut(); >+ void Copy(); >+ void Paste(); >+ >+ void Copy( ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboard >& rxClipboard ); >+ void Paste( ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::clipboard::XClipboard >& rxClipboard ); >+ >+ void Undo(); >+ void Redo(); >+ >+ sal_Bool Read( SvStream& rInput ); >+ >+ void SetStartDocPos( const Point& rPos ); >+ const Point& GetStartDocPos() const; >+ >+ Point GetDocPos( const Point& rWindowPos ) const; >+ Point GetWindowPos( const Point& rDocPos ) const; >+ >+ void SetInsertMode( sal_Bool bInsert ); >+ sal_Bool IsInsertMode() const; >+ >+ void SetAutoIndentMode( sal_Bool bAutoIndent ); >+ >+ void SetReadOnly( sal_Bool bReadOnly ); >+ sal_Bool IsReadOnly() const; >+ >+ void SetAutoScroll( sal_Bool bAutoScroll ); >+ sal_Bool IsAutoScroll() const; >+ >+ sal_Bool SetCursorAtPoint( const Point& rPointPixel ); >+ sal_Bool IsSelectionAtPoint( const Point& rPointPixel ); >+ >+ void SetPaintSelection( sal_Bool bPaint); >+ >+ void EraseVirtualDevice(); >+ >+ // aus dem protected Teil hierher verschoben >+ // F�r 'SvtXECTextCursor' (TL). Mu� ggf nochmal anders gel�st werden. >+ TextPaM PageUp( const TextPaM& rPaM ); >+ TextPaM PageDown( const TextPaM& rPaM ); >+ TextPaM CursorUp( const TextPaM& rPaM ); >+ TextPaM CursorDown( const TextPaM& rPaM ); >+ TextPaM CursorLeft( const TextPaM& rPaM, sal_uInt16 nCharacterIteratorMode ); >+ TextPaM CursorRight( const TextPaM& rPaM, sal_uInt16 nCharacterIteratorMode ); >+ TextPaM CursorWordLeft( const TextPaM& rPaM ); >+ TextPaM CursorWordRight( const TextPaM& rPaM ); >+ TextPaM CursorStartOfLine( const TextPaM& rPaM ); >+ TextPaM CursorEndOfLine( const TextPaM& rPaM ); >+ TextPaM CursorStartOfParagraph( const TextPaM& rPaM ); >+ TextPaM CursorEndOfParagraph( const TextPaM& rPaM ); >+ TextPaM CursorStartOfDoc(); >+ TextPaM CursorEndOfDoc(); >+ >+ /** >+ Drag and Drop, deleting and selection regards all text that has an attribute >+ TEXTATTR_PROTECTED set as one entitity. Drag and dropped text is automatically >+ attibuted as protected. >+ */ >+ void SupportProtectAttribute(sal_Bool bSupport); >+ >+ /** >+ Returns the number in paragraph of the line in which the cursor is blinking >+ if enabled, -1 otherwise. >+ */ >+ sal_Int32 GetLineNumberOfCursorInSelection() const; >+}; >+ >+#endif // _TEXTVIEW_HXX >+ >+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/vcl/inc/vcl/txtattr.hxx b/vcl/inc/vcl/txtattr.hxx >new file mode 100644 >index 0000000..695dfc7 >--- /dev/null >+++ b/vcl/inc/vcl/txtattr.hxx >@@ -0,0 +1,236 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >+/************************************************************************* >+ * >+ * 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 _TXTATTR_HXX >+#define _TXTATTR_HXX >+ >+#include <vcl/dllapi.h> >+#include <tools/color.hxx> >+#include <vcl/vclenum.hxx> >+#include <tools/string.hxx> >+#include <tools/debug.hxx> >+ >+class Font; >+ >+#define TEXTATTR_INVALID 0 >+#define TEXTATTR_FONTCOLOR 1 >+#define TEXTATTR_HYPERLINK 2 >+#define TEXTATTR_FONTWEIGHT 3 >+ >+#define TEXTATTR_USER_START 1000 //start id for user defined text attributes >+#define TEXTATTR_PROTECTED 4 >+ >+ >+class VCL_DLLPUBLIC TextAttrib >+{ >+private: >+ sal_uInt16 mnWhich; >+ >+protected: >+ TextAttrib( sal_uInt16 nWhich ) { mnWhich = nWhich; } >+ TextAttrib( const TextAttrib& rAttr ) { mnWhich = rAttr.mnWhich; } >+ >+public: >+ >+ virtual ~TextAttrib(); >+ >+ sal_uInt16 Which() const { return mnWhich; } >+ virtual void SetFont( Font& rFont ) const = 0; >+ virtual TextAttrib* Clone() const = 0; >+ >+ virtual int operator==( const TextAttrib& rAttr ) const = 0; >+ int operator!=( const TextAttrib& rAttr ) const >+ { return !(*this == rAttr ); } >+}; >+ >+ >+ >+class VCL_DLLPUBLIC TextAttribFontColor : public TextAttrib >+{ >+private: >+ Color maColor; >+ >+public: >+ TextAttribFontColor( const Color& rColor ); >+ TextAttribFontColor( const TextAttribFontColor& rAttr ); >+ ~TextAttribFontColor(); >+ >+ const Color& GetColor() const { return maColor; } >+ >+ virtual void SetFont( Font& rFont ) const; >+ virtual TextAttrib* Clone() const; >+ virtual int operator==( const TextAttrib& rAttr ) const; >+ >+}; >+ >+class VCL_DLLPUBLIC TextAttribFontWeight : public TextAttrib >+{ >+private: >+ FontWeight meWeight; >+ >+public: >+ TextAttribFontWeight( FontWeight eWeight ); >+ TextAttribFontWeight( const TextAttribFontWeight& rAttr ); >+ ~TextAttribFontWeight(); >+ >+ virtual void SetFont( Font& rFont ) const; >+ virtual TextAttrib* Clone() const; >+ virtual int operator==( const TextAttrib& rAttr ) const; >+ >+ inline FontWeight getFontWeight() const { return meWeight; } >+}; >+ >+ >+class TextAttribHyperLink : public TextAttrib >+{ >+private: >+ XubString maURL; >+ XubString maDescription; >+ Color maColor; >+ >+public: >+ TextAttribHyperLink( const TextAttribHyperLink& rAttr ); >+ ~TextAttribHyperLink(); >+ >+ void SetURL( const XubString& rURL ) { maURL = rURL; } >+ const XubString& GetURL() const { return maURL; } >+ >+ void SetDescription( const XubString& rDescr ) { maDescription = rDescr; } >+ const XubString& GetDescription() const { return maDescription; } >+ >+ void SetColor( const Color& rColor ) { maColor = rColor; } >+ const Color& GetColor() const { return maColor; } >+ >+ virtual void SetFont( Font& rFont ) const; >+ virtual TextAttrib* Clone() const; >+ virtual int operator==( const TextAttrib& rAttr ) const; >+}; >+ >+class VCL_DLLPUBLIC TextAttribProtect : public TextAttrib >+{ >+public: >+ TextAttribProtect(); >+ TextAttribProtect( const TextAttribProtect& rAttr ); >+ ~TextAttribProtect(); >+ >+ virtual void SetFont( Font& rFont ) const; >+ virtual TextAttrib* Clone() const; >+ virtual int operator==( const TextAttrib& rAttr ) const; >+ >+}; >+ >+ >+class TextCharAttrib >+{ >+private: >+ TextAttrib* mpAttr; >+ sal_uInt16 mnStart; >+ sal_uInt16 mnEnd; >+ >+protected: >+ >+public: >+ >+ TextCharAttrib( const TextAttrib& rAttr, sal_uInt16 nStart, sal_uInt16 nEnd ); >+ TextCharAttrib( const TextCharAttrib& rTextCharAttrib ); >+ ~TextCharAttrib(); >+ >+ const TextAttrib& GetAttr() const { return *mpAttr; } >+ >+ sal_uInt16 Which() const { return mpAttr->Which(); } >+ >+ sal_uInt16 GetStart() const { return mnStart; } >+ sal_uInt16& GetStart() { return mnStart; } >+ >+ sal_uInt16 GetEnd() const { return mnEnd; } >+ sal_uInt16& GetEnd() { return mnEnd; } >+ >+ inline sal_uInt16 GetLen() const; >+ >+ inline void MoveForward( sal_uInt16 nDiff ); >+ inline void MoveBackward( sal_uInt16 nDiff ); >+ >+ inline void Expand( sal_uInt16 nDiff ); >+ inline void Collaps( sal_uInt16 nDiff ); >+ >+ inline sal_Bool IsIn( sal_uInt16 nIndex ); >+ inline sal_Bool IsInside( sal_uInt16 nIndex ); >+ inline sal_Bool IsEmpty(); >+ >+}; >+ >+inline sal_uInt16 TextCharAttrib::GetLen() const >+{ >+ DBG_ASSERT( mnEnd >= mnStart, "TextCharAttrib: nEnd < nStart!" ); >+ return mnEnd-mnStart; >+} >+ >+inline void TextCharAttrib::MoveForward( sal_uInt16 nDiff ) >+{ >+ DBG_ASSERT( ((long)mnEnd + nDiff) <= 0xFFFF, "TextCharAttrib: MoveForward?!" ); >+ mnStart = mnStart + nDiff; >+ mnEnd = mnEnd + nDiff; >+} >+ >+inline void TextCharAttrib::MoveBackward( sal_uInt16 nDiff ) >+{ >+ DBG_ASSERT( ((long)mnStart - nDiff) >= 0, "TextCharAttrib: MoveBackward?!" ); >+ mnStart = mnStart - nDiff; >+ mnEnd = mnEnd - nDiff; >+} >+ >+inline void TextCharAttrib::Expand( sal_uInt16 nDiff ) >+{ >+ DBG_ASSERT( ( ((long)mnEnd + nDiff) <= (long)0xFFFF ), "TextCharAttrib: Expand?!" ); >+ mnEnd = mnEnd + nDiff; >+} >+ >+inline void TextCharAttrib::Collaps( sal_uInt16 nDiff ) >+{ >+ DBG_ASSERT( (long)mnEnd - nDiff >= (long)mnStart, "TextCharAttrib: Collaps?!" ); >+ mnEnd = mnEnd - nDiff; >+} >+ >+inline sal_Bool TextCharAttrib::IsIn( sal_uInt16 nIndex ) >+{ >+ return ( ( mnStart <= nIndex ) && ( mnEnd >= nIndex ) ); >+} >+ >+inline sal_Bool TextCharAttrib::IsInside( sal_uInt16 nIndex ) >+{ >+ return ( ( mnStart < nIndex ) && ( mnEnd > nIndex ) ); >+} >+ >+inline sal_Bool TextCharAttrib::IsEmpty() >+{ >+ return mnStart == mnEnd; >+} >+ >+#endif // _TXTATTR_HXX >+ >+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/vcl/inc/vcl/vclmedit.hxx b/vcl/inc/vcl/vclmedit.hxx >new file mode 100644 >index 0000000..b9711cf >--- /dev/null >+++ b/vcl/inc/vcl/vclmedit.hxx >@@ -0,0 +1,149 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >+/************************************************************************* >+ * >+ * 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 _VCLMEDIT_HXX >+#define _VCLMEDIT_HXX >+ >+#include <tools/wintypes.hxx> >+#include <vcl/edit.hxx> >+#include <vcl/dllapi.h> >+ >+ >+class ImpSvMEdit; >+class Timer; >+class ExtTextEngine; >+class ExtTextView; >+ >+class VCL_DLLPUBLIC VCLMultiLineEdit : public Edit >+{ >+private: >+ ImpSvMEdit* pImpSvMEdit; >+ >+ XubString aSaveValue; >+ Link aModifyHdlLink; >+ >+ Timer* pUpdateDataTimer; >+ Link aUpdateDataHdlLink; >+ >+protected: >+ >+ DECL_LINK( ImpUpdateDataHdl, void* ); >+ void StateChanged( StateChangedType nType ); >+ void DataChanged( const DataChangedEvent& rDCEvt ); >+ virtual long PreNotify( NotifyEvent& rNEvt ); >+ long Notify( NotifyEvent& rNEvt ); >+ using Control::ImplInitSettings; >+ void ImplInitSettings( sal_Bool bFont, sal_Bool bForeground, sal_Bool bBackground ); >+ WinBits ImplInitStyle( WinBits nStyle ); >+ >+ ExtTextEngine* GetTextEngine() const; >+ ExtTextView* GetTextView() const; >+ ScrollBar* GetVScrollBar() const; >+ >+public: >+ VCLMultiLineEdit( Window* pParent, WinBits nWinStyle = WB_LEFT | WB_BORDER ); >+ VCLMultiLineEdit( Window* pParent, const ResId& rResId ); >+ virtual ~VCLMultiLineEdit(); >+ >+ >+ virtual void Modify(); >+ virtual void UpdateData(); >+ >+ virtual void SetModifyFlag(); >+ virtual void ClearModifyFlag(); >+ virtual sal_Bool IsModified() const; >+ >+ virtual void EnableUpdateData( sal_uLong nTimeout = EDIT_UPDATEDATA_TIMEOUT ); >+ virtual void DisableUpdateData() { delete pUpdateDataTimer; pUpdateDataTimer = NULL; } >+ virtual sal_uLong IsUpdateDataEnabled() const; >+ >+ virtual void SetReadOnly( sal_Bool bReadOnly = sal_True ); >+ virtual sal_Bool IsReadOnly() const; >+ >+ void EnableFocusSelectionHide( sal_Bool bHide ); >+ >+ virtual void SetMaxTextLen( xub_StrLen nMaxLen = 0 ); >+ virtual xub_StrLen GetMaxTextLen() const; >+ >+ virtual void SetSelection( const Selection& rSelection ); >+ virtual const Selection& GetSelection() const; >+ >+ virtual void ReplaceSelected( const XubString& rStr ); >+ virtual void DeleteSelected(); >+ virtual XubString GetSelected() const; >+ virtual XubString GetSelected( LineEnd aSeparator ) const; >+ >+ virtual void Cut(); >+ virtual void Copy(); >+ virtual void Paste(); >+ >+ virtual void SetText( const XubString& rStr ); >+ virtual void SetText( const XubString& rStr, const Selection& rNewSelection ) >+ { SetText( rStr ); SetSelection( rNewSelection ); } >+ String GetText() const; >+ String GetText( LineEnd aSeparator ) const; >+ String GetTextLines( LineEnd aSeparator ) const; >+ >+ void SetRightToLeft( sal_Bool bRightToLeft ); >+ sal_Bool IsRightToLeft() const; >+ >+ void SaveValue() { aSaveValue = GetText(); } >+ const XubString& GetSavedValue() const { return aSaveValue; } >+ >+ void SetModifyHdl( const Link& rLink ) { aModifyHdlLink = rLink; } >+ const Link& GetModifyHdl() const { return aModifyHdlLink; } >+ >+ void SetUpdateDataHdl( const Link& rLink ) { aUpdateDataHdlLink = rLink; } >+ const Link& GetUpdateDataHdl() const { return aUpdateDataHdlLink; } >+ >+ virtual void Resize(); >+ virtual void GetFocus(); >+ >+ Size CalcMinimumSize() const; >+ Size CalcAdjustedSize( const Size& rPrefSize ) const; >+ using Edit::CalcSize; >+ Size CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const; >+ void GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const; >+ >+ void Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags ); >+ >+ void SetLeftMargin( sal_uInt16 n ); >+ >+ void DisableSelectionOnFocus(); >+ >+ void SetTextSelectable( sal_Bool bTextSelectable ); >+}; >+ >+inline sal_uLong VCLMultiLineEdit::IsUpdateDataEnabled() const >+{ >+ return pUpdateDataTimer ? pUpdateDataTimer->GetTimeout() : 0; >+} >+ >+#endif //_VCLMEDIT_HXX >+ >+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/vcl/inc/vcl/xtextedt.hxx b/vcl/inc/vcl/xtextedt.hxx >new file mode 100644 >index 0000000..b763e37 >--- /dev/null >+++ b/vcl/inc/vcl/xtextedt.hxx >@@ -0,0 +1,69 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >+/* >+ * This file is part of the LibreOffice project. >+ * >+ * This Source Code Form is subject to the terms of the Mozilla Public >+ * License, v. 2.0. If a copy of the MPL was not distributed with this >+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. >+ * >+ * This file incorporates work covered by the following license notice: >+ * >+ * Licensed to the Apache Software Foundation (ASF) under one or more >+ * contributor license agreements. See the NOTICE file distributed >+ * with this work for additional information regarding copyright >+ * ownership. The ASF licenses this file to you under the Apache >+ * License, Version 2.0 (the "License"); you may not use this file >+ * except in compliance with the License. You may obtain a copy of >+ * the License at http://www.apache.org/licenses/LICENSE-2.0 . >+ */ >+#ifndef _XTEXTEDT_HXX >+#define _XTEXTEDT_HXX >+ >+#include <vcl/dllapi.h> >+#include <vcl/texteng.hxx> >+#include <vcl/textview.hxx> >+ >+namespace com { >+namespace sun { >+namespace star { >+namespace util { >+ struct SearchOptions; >+}}}} >+ >+class VCL_DLLPUBLIC ExtTextEngine : public TextEngine >+{ >+private: >+ String maGroupChars; >+ >+public: >+ ExtTextEngine(); >+ ~ExtTextEngine(); >+ >+ const String& GetGroupChars() const { return maGroupChars; } >+ void SetGroupChars( const String& r ) { maGroupChars = r; } >+ TextSelection MatchGroup( const TextPaM& rCursor ) const; >+ >+ sal_Bool Search( TextSelection& rSel, const ::com::sun::star::util::SearchOptions& rSearchOptions, sal_Bool bForward = sal_True ); >+}; >+ >+class VCL_DLLPUBLIC ExtTextView : public TextView >+{ >+protected: >+ sal_Bool ImpIndentBlock( sal_Bool bRight ); >+ >+public: >+ ExtTextView( ExtTextEngine* pEng, Window* pWindow ); >+ ~ExtTextView(); >+ >+ sal_Bool MatchGroup(); >+ >+ sal_Bool Search( const ::com::sun::star::util::SearchOptions& rSearchOptions, sal_Bool bForward ); >+ sal_uInt16 Replace( const ::com::sun::star::util::SearchOptions& rSearchOptions, sal_Bool bAll, sal_Bool bForward ); >+ >+ sal_Bool IndentBlock(); >+ sal_Bool UnindentBlock(); >+}; >+ >+#endif // _XTEXTEDT_HXX >+ >+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/vcl/source/edit/textdat2.hxx b/vcl/source/edit/textdat2.hxx >new file mode 100644 >index 0000000..c52d33e >--- /dev/null >+++ b/vcl/source/edit/textdat2.hxx >@@ -0,0 +1,312 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >+/************************************************************************* >+ * >+ * 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 _TEXTDAT2_HXX >+#define _TEXTDAT2_HXX >+ >+#include <vcl/seleng.hxx> >+#include <vcl/virdev.hxx> >+#include <vcl/cursor.hxx> >+ >+#include <vector> >+ >+class TextNode; >+class TextView; >+ >+#define PORTIONKIND_TEXT 0 >+#define PORTIONKIND_TAB 1 >+ >+#define DELMODE_SIMPLE 0 >+#define DELMODE_RESTOFWORD 1 >+#define DELMODE_RESTOFCONTENT 2 >+ >+#define DEL_LEFT 1 >+#define DEL_RIGHT 2 >+#define TRAVEL_X_DONTKNOW 0xFFFF >+#define MAXCHARSINPARA 0x3FFF-CHARPOSGROW >+ >+#define LINE_SEP 0x0A >+ >+ >+class TETextPortion >+{ >+private: >+ sal_uInt16 nLen; >+ long nWidth; >+ sal_uInt8 nKind; >+ sal_uInt8 nRightToLeft; >+ >+ TETextPortion() { nLen = 0; nKind = PORTIONKIND_TEXT; nWidth = -1; nRightToLeft = 0;} >+ >+public: >+ TETextPortion( sal_uInt16 nL ) { >+ nLen = nL; >+ nKind = PORTIONKIND_TEXT; >+ nWidth= -1; >+ nRightToLeft = 0; >+ } >+ >+ sal_uInt16 GetLen() const { return nLen; } >+ sal_uInt16& GetLen() { return nLen; } >+ >+ long GetWidth()const { return nWidth; } >+ long& GetWidth() { return nWidth; } >+ >+ sal_uInt8 GetKind() const { return nKind; } >+ sal_uInt8& GetKind() { return nKind; } >+ >+ sal_uInt8 GetRightToLeft() const { return nRightToLeft; } >+ sal_uInt8& GetRightToLeft() { return nRightToLeft; } >+ sal_Bool IsRightToLeft() const { return (nRightToLeft&1); } >+ >+ sal_Bool HasValidSize() const { return nWidth != (-1); } >+}; >+ >+ >+ >+typedef std::vector<TETextPortion*> TextPortionArray; >+ >+class TETextPortionList : public TextPortionArray >+{ >+public: >+ TETextPortionList(); >+ ~TETextPortionList(); >+ >+ void Reset(); >+ sal_uInt16 FindPortion( sal_uInt16 nCharPos, sal_uInt16& rPortionStart, sal_Bool bPreferStartingPortion = sal_False ); >+ sal_uInt16 GetPortionStartIndex( sal_uInt16 nPortion ); >+ void DeleteFromPortion( sal_uInt16 nDelFrom ); >+}; >+ >+struct TEWritingDirectionInfo >+{ >+ sal_uInt8 nType; >+ sal_uInt16 nStartPos; >+ sal_uInt16 nEndPos; >+ TEWritingDirectionInfo( sal_uInt8 _Type, sal_uInt16 _Start, sal_uInt16 _End ) >+ { >+ nType = _Type; >+ nStartPos = _Start; >+ nEndPos = _End; >+ } >+}; >+ >+class TextLine >+{ >+private: >+ sal_uInt16 mnStart; >+ sal_uInt16 mnEnd; >+ sal_uInt16 mnStartPortion; >+ sal_uInt16 mnEndPortion; >+ >+ short mnStartX; >+ >+ sal_Bool mbInvalid; // fuer geschickte Formatierung/Ausgabe >+ >+public: >+ TextLine() { >+ mnStart = mnEnd = 0; >+ mnStartPortion = mnEndPortion = 0; >+ mnStartX = 0; >+ mbInvalid = sal_True; >+ } >+ >+ sal_Bool IsIn( sal_uInt16 nIndex ) const >+ { return ( (nIndex >= mnStart ) && ( nIndex < mnEnd ) ); } >+ >+ sal_Bool IsIn( sal_uInt16 nIndex, sal_Bool bInclEnd ) const >+ { return ( ( nIndex >= mnStart ) && ( bInclEnd ? ( nIndex <= mnEnd ) : ( nIndex < mnEnd ) ) ); } >+ >+ void SetStart( sal_uInt16 n ) { mnStart = n; } >+ sal_uInt16 GetStart() const { return mnStart; } >+ sal_uInt16& GetStart() { return mnStart; } >+ >+ void SetEnd( sal_uInt16 n ) { mnEnd = n; } >+ sal_uInt16 GetEnd() const { return mnEnd; } >+ sal_uInt16& GetEnd() { return mnEnd; } >+ >+ void SetStartPortion( sal_uInt16 n ) { mnStartPortion = n; } >+ sal_uInt16 GetStartPortion() const { return mnStartPortion; } >+ sal_uInt16& GetStartPortion() { return mnStartPortion; } >+ >+ void SetEndPortion( sal_uInt16 n ) { mnEndPortion = n; } >+ sal_uInt16 GetEndPortion() const { return mnEndPortion; } >+ sal_uInt16& GetEndPortion() { return mnEndPortion; } >+ >+ sal_uInt16 GetLen() const { return mnEnd - mnStart; } >+ >+ sal_Bool IsInvalid() const { return mbInvalid; } >+ sal_Bool IsValid() const { return !mbInvalid; } >+ void SetInvalid() { mbInvalid = sal_True; } >+ void SetValid() { mbInvalid = sal_False; } >+ >+ sal_Bool IsEmpty() const { return (mnEnd > mnStart) ? sal_False : sal_True; } >+ >+ short GetStartX() const { return mnStartX; } >+ void SetStartX( short n ) { mnStartX = n; } >+ >+ inline sal_Bool operator == ( const TextLine& rLine ) const; >+ inline sal_Bool operator != ( const TextLine& rLine ) const; >+}; >+ >+class TextLines : public std::vector<TextLine*> { >+public: >+ ~TextLines() >+ { >+ for( iterator it = begin(); it != end(); ++it ) >+ delete *it; >+ } >+}; >+ >+inline sal_Bool TextLine::operator == ( const TextLine& rLine ) const >+{ >+ return ( ( mnStart == rLine.mnStart ) && >+ ( mnEnd == rLine.mnEnd ) && >+ ( mnStartPortion == rLine.mnStartPortion ) && >+ ( mnEndPortion == rLine.mnEndPortion ) ); >+} >+ >+inline sal_Bool TextLine::operator != ( const TextLine& rLine ) const >+{ >+ return !( *this == rLine ); >+} >+ >+ >+ >+class TEParaPortion >+{ >+private: >+ TextNode* mpNode; >+ >+ TextLines maLines; >+ TETextPortionList maTextPortions; >+ std::vector<TEWritingDirectionInfo> maWritingDirectionInfos; >+ >+ >+ sal_uInt16 mnInvalidPosStart; >+ short mnInvalidDiff; >+ >+ sal_Bool mbInvalid; >+ sal_Bool mbSimple; // nur lineares Tippen >+ >+ >+ TEParaPortion( const TEParaPortion& ) {;} >+ >+public: >+ TEParaPortion( TextNode* pNode ); >+ ~TEParaPortion(); >+ >+ >+ sal_Bool IsInvalid() const { return mbInvalid; } >+ sal_Bool IsSimpleInvalid() const { return mbSimple; } >+ void SetNotSimpleInvalid() { mbSimple = sal_False; } >+ void SetValid() { mbInvalid = sal_False; mbSimple = sal_True;} >+ >+ void MarkInvalid( sal_uInt16 nStart, short nDiff); >+ void MarkSelectionInvalid( sal_uInt16 nStart, sal_uInt16 nEnd ); >+ >+ sal_uInt16 GetInvalidPosStart() const { return mnInvalidPosStart; } >+ short GetInvalidDiff() const { return mnInvalidDiff; } >+ >+ TextNode* GetNode() const { return mpNode; } >+ TextLines& GetLines() { return maLines; } >+ TETextPortionList& GetTextPortions() { return maTextPortions; } >+ std::vector<TEWritingDirectionInfo>& GetWritingDirectionInfos() { return maWritingDirectionInfos; } >+ >+ >+ sal_uInt16 GetLineNumber( sal_uInt16 nIndex, sal_Bool bInclEnd ); >+ void CorrectValuesBehindLastFormattedLine( sal_uInt16 nLastFormattedLine ); >+}; >+ >+ >+class TEParaPortions : public ToolsList<TEParaPortion*> >+{ >+public: >+ TEParaPortions(); >+ ~TEParaPortions(); >+ void Reset(); >+}; >+ >+ >+class TextSelFunctionSet: public FunctionSet >+{ >+private: >+ TextView* mpView; >+ >+public: >+ TextSelFunctionSet( TextView* pView ); >+ >+ virtual void BeginDrag(); >+ >+ virtual void CreateAnchor(); >+ >+ virtual sal_Bool SetCursorAtPoint( const Point& rPointPixel, sal_Bool bDontSelectAtCursor = sal_False ); >+ >+ virtual sal_Bool IsSelectionAtPoint( const Point& rPointPixel ); >+ virtual void DeselectAll(); >+ >+ virtual void DeselectAtPoint( const Point& ); >+ virtual void DestroyAnchor(); >+}; >+ >+ >+class IdleFormatter : public Timer >+{ >+private: >+ TextView* mpView; >+ sal_uInt16 mnRestarts; >+ >+public: >+ IdleFormatter(); >+ ~IdleFormatter(); >+ >+ void DoIdleFormat( TextView* pV, sal_uInt16 nMaxRestarts ); >+ void ForceTimeout(); >+ TextView* GetView() { return mpView; } >+}; >+ >+struct TextDDInfo >+{ >+ Cursor maCursor; >+ TextPaM maDropPos; >+ >+ sal_Bool mbStarterOfDD; >+ sal_Bool mbVisCursor; >+ >+ TextDDInfo() >+ { >+ maCursor.SetStyle( CURSOR_SHADOW ); >+ mbStarterOfDD = sal_False; >+ mbVisCursor = sal_False; >+ } >+}; >+ >+#endif // _TEXTDAT2_HXX >+ >+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/vcl/source/edit/textdata.cxx b/vcl/source/edit/textdata.cxx >new file mode 100644 >index 0000000..79f28f3 >--- /dev/null >+++ b/vcl/source/edit/textdata.cxx >@@ -0,0 +1,345 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >+/************************************************************************* >+ * >+ * 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 <vcl/textdata.hxx> >+#include <textdat2.hxx> >+ >+#include <tools/debug.hxx> >+ >+ >+// ------------------------------------------------------------------------- >+// (+) class TextSelection >+// ------------------------------------------------------------------------- >+ >+TextSelection::TextSelection() >+{ >+} >+ >+TextSelection::TextSelection( const TextPaM& rPaM ) : >+ maStartPaM( rPaM ), maEndPaM( rPaM ) >+{ >+} >+ >+TextSelection::TextSelection( const TextPaM& rStart, const TextPaM& rEnd ) : >+ maStartPaM( rStart ), maEndPaM( rEnd ) >+{ >+} >+ >+void TextSelection::Justify() >+{ >+ if ( maEndPaM < maStartPaM ) >+ { >+ TextPaM aTemp( maStartPaM ); >+ maStartPaM = maEndPaM; >+ maEndPaM = aTemp; >+ } >+} >+ >+ >+// ------------------------------------------------------------------------- >+// (+) class TETextPortionList >+// ------------------------------------------------------------------------- >+TETextPortionList::TETextPortionList() >+{ >+} >+ >+TETextPortionList::~TETextPortionList() >+{ >+ Reset(); >+} >+ >+void TETextPortionList::Reset() >+{ >+ for ( iterator it = begin(); it != end(); ++it ) >+ delete *it; >+ clear(); >+} >+ >+void TETextPortionList::DeleteFromPortion( sal_uInt16 nDelFrom ) >+{ >+ DBG_ASSERT( ( nDelFrom < size() ) || ( (nDelFrom == 0) && (size() == 0) ), "DeleteFromPortion: Out of range" ); >+ for ( iterator it = begin() + nDelFrom; it != end(); ++it ) >+ delete *it; >+ erase( begin() + nDelFrom, end() ); >+} >+ >+sal_uInt16 TETextPortionList::FindPortion( sal_uInt16 nCharPos, sal_uInt16& nPortionStart, sal_Bool bPreferStartingPortion ) >+{ >+ // Bei nCharPos an Portion-Grenze wird die linke Portion gefunden >+ sal_uInt16 nTmpPos = 0; >+ for ( sal_uInt16 nPortion = 0; nPortion < size(); nPortion++ ) >+ { >+ TETextPortion* pPortion = operator[]( 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 == size() - 1 ) ) >+ { >+ nPortionStart = nTmpPos - pPortion->GetLen(); >+ return nPortion; >+ } >+ } >+ } >+ OSL_FAIL( "FindPortion: Nicht gefunden!" ); >+ return ( size() - 1 ); >+} >+ >+ >+// ------------------------------------------------------------------------- >+// (+) class TEParaPortion >+// ------------------------------------------------------------------------- >+TEParaPortion::TEParaPortion( TextNode* pN ) >+{ >+ mpNode = pN; >+ mnInvalidPosStart = mnInvalidDiff = 0; >+ mbInvalid = sal_True; >+ mbSimple = sal_False; >+} >+ >+TEParaPortion::~TEParaPortion() >+{ >+} >+ >+void TEParaPortion::MarkInvalid( sal_uInt16 nStart, short nDiff ) >+{ >+ if ( mbInvalid == sal_False ) >+ { >+ mnInvalidPosStart = ( nDiff >= 0 ) ? nStart : ( nStart + nDiff ); >+ mnInvalidDiff = nDiff; >+ } >+ else >+ { >+ // Einfaches hintereinander tippen >+ if ( ( nDiff > 0 ) && ( mnInvalidDiff > 0 ) && >+ ( ( mnInvalidPosStart+mnInvalidDiff ) == nStart ) ) >+ { >+ mnInvalidDiff = mnInvalidDiff + nDiff; >+ } >+ // Einfaches hintereinander loeschen >+ else if ( ( nDiff < 0 ) && ( mnInvalidDiff < 0 ) && ( mnInvalidPosStart == nStart ) ) >+ { >+ mnInvalidPosStart = mnInvalidPosStart + nDiff; >+ mnInvalidDiff = mnInvalidDiff + nDiff; >+ } >+ else >+ { >+ DBG_ASSERT( ( nDiff >= 0 ) || ( (nStart+nDiff) >= 0 ), "MarkInvalid: Diff out of Range" ); >+ mnInvalidPosStart = Min( mnInvalidPosStart, (sal_uInt16) ( (nDiff < 0) ? nStart+nDiff : nDiff ) ); >+ mnInvalidDiff = 0; >+ mbSimple = sal_False; >+ } >+ } >+ >+ maWritingDirectionInfos.clear(); >+ >+ mbInvalid = sal_True; >+} >+ >+void TEParaPortion::MarkSelectionInvalid( sal_uInt16 nStart, sal_uInt16 /*nEnd*/ ) >+{ >+ if ( mbInvalid == sal_False ) >+ { >+ mnInvalidPosStart = nStart; >+// nInvalidPosEnd = nEnd; >+ } >+ else >+ { >+ mnInvalidPosStart = Min( mnInvalidPosStart, nStart ); >+// nInvalidPosEnd = pNode->Len(); >+ } >+ >+ maWritingDirectionInfos.clear(); >+ >+ mnInvalidDiff = 0; >+ mbInvalid = sal_True; >+ mbSimple = sal_False; >+} >+ >+sal_uInt16 TEParaPortion::GetLineNumber( sal_uInt16 nChar, sal_Bool bInclEnd ) >+{ >+ for ( sal_uInt16 nLine = 0; nLine < maLines.size(); nLine++ ) >+ { >+ TextLine* pLine = maLines[ nLine ]; >+ if ( ( bInclEnd && ( pLine->GetEnd() >= nChar ) ) || >+ ( pLine->GetEnd() > nChar ) ) >+ { >+ return nLine; >+ } >+ } >+ >+ // Then it should be at the end of the last line >+ OSL_ENSURE(nChar == maLines[maLines.size() - 1]->GetEnd(), "wrong Index"); >+ OSL_ENSURE(!bInclEnd, "Line not found: FindLine"); >+ return ( maLines.size() - 1 ); >+} >+ >+ >+void TEParaPortion::CorrectValuesBehindLastFormattedLine( sal_uInt16 nLastFormattedLine ) >+{ >+ sal_uInt16 nLines = maLines.size(); >+ DBG_ASSERT( nLines, "CorrectPortionNumbersFromLine: Leere Portion?" ); >+ if ( nLastFormattedLine < ( nLines - 1 ) ) >+ { >+ const TextLine* pLastFormatted = maLines[ nLastFormattedLine ]; >+ const TextLine* pUnformatted = maLines[ 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! >+ short nPDiff = sal::static_int_cast< short >(-( nPortionDiff-1 )); >+ short nTDiff = sal::static_int_cast< short >(-( nTextDiff-1 )); >+ if ( nPDiff || nTDiff ) >+ { >+ for ( sal_uInt16 nL = nLastFormattedLine+1; nL < nLines; nL++ ) >+ { >+ TextLine* pLine = maLines[ nL ]; >+ >+ pLine->GetStartPortion() = pLine->GetStartPortion() + nPDiff; >+ pLine->GetEndPortion() = pLine->GetEndPortion() + nPDiff; >+ >+ pLine->GetStart() = pLine->GetStart() + nTDiff; >+ pLine->GetEnd() = pLine->GetEnd() + nTDiff; >+ >+ pLine->SetValid(); >+ } >+ } >+ } >+} >+ >+// ------------------------------------------------------------------------- >+// (+) class TEParaPortions >+// ------------------------------------------------------------------------- >+TEParaPortions::TEParaPortions() >+{ >+} >+ >+TEParaPortions::~TEParaPortions() >+{ >+ Reset(); >+} >+ >+void TEParaPortions::Reset() >+{ >+ TEParaPortions::iterator aIter( begin() ); >+ while ( aIter != end() ) >+ delete *aIter++; >+ clear(); >+} >+ >+// ------------------------------------------------------------------------- >+// (+) class IdleFormatter >+// ------------------------------------------------------------------------- >+IdleFormatter::IdleFormatter() >+{ >+ mpView = 0; >+ mnRestarts = 0; >+} >+ >+IdleFormatter::~IdleFormatter() >+{ >+ mpView = 0; >+} >+ >+void IdleFormatter::DoIdleFormat( TextView* pV, sal_uInt16 nMaxRestarts ) >+{ >+ mpView = pV; >+ >+ if ( IsActive() ) >+ mnRestarts++; >+ >+ if ( mnRestarts > nMaxRestarts ) >+ { >+ mnRestarts = 0; >+ ((Link&)GetTimeoutHdl()).Call( this ); >+ } >+ else >+ { >+ Start(); >+ } >+} >+ >+void IdleFormatter::ForceTimeout() >+{ >+ if ( IsActive() ) >+ { >+ Stop(); >+ mnRestarts = 0; >+ ((Link&)GetTimeoutHdl()).Call( this ); >+ } >+} >+ >+TYPEINIT1( TextHint, SfxSimpleHint ); >+ >+TextHint::TextHint( sal_uLong Id ) : SfxSimpleHint( Id ) >+{ >+ mnValue = 0; >+} >+ >+TextHint::TextHint( sal_uLong Id, sal_uLong nValue ) : SfxSimpleHint( Id ) >+{ >+ mnValue = nValue; >+} >+ >+TEIMEInfos::TEIMEInfos( const TextPaM& rPos, const String& rOldTextAfterStartPos ) >+: aOldTextAfterStartPos( rOldTextAfterStartPos ) >+{ >+ aPos = rPos; >+ nLen = 0; >+ bCursor = sal_True; >+ pAttribs = NULL; >+ bWasCursorOverwrite = sal_False; >+} >+ >+TEIMEInfos::~TEIMEInfos() >+{ >+ delete[] pAttribs; >+} >+ >+void TEIMEInfos::CopyAttribs( const sal_uInt16* pA, sal_uInt16 nL ) >+{ >+ nLen = nL; >+ delete pAttribs; >+ pAttribs = new sal_uInt16[ nL ]; >+ memcpy( pAttribs, pA, nL*sizeof(sal_uInt16) ); >+} >+ >+void TEIMEInfos::DestroyAttribs() >+{ >+ delete pAttribs; >+ pAttribs = NULL; >+ nLen = 0; >+} >+ >+ >+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/vcl/source/edit/textdoc.cxx b/vcl/source/edit/textdoc.cxx >new file mode 100644 >index 0000000..a8062ec >--- /dev/null >+++ b/vcl/source/edit/textdoc.cxx >@@ -0,0 +1,636 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >+/************************************************************************* >+ * >+ * 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 <textdoc.hxx> >+ >+#include <stdlib.h> >+ >+ >+ >+// Vergleichmethode wird von QuickSort gerufen... >+ >+static bool CompareStart( const TextCharAttrib* pFirst, const TextCharAttrib* pSecond ) >+{ >+ return pFirst->GetStart() < pSecond->GetStart(); >+} >+ >+// ------------------------------------------------------------------------- >+// (+) class TextCharAttrib >+// ------------------------------------------------------------------------- >+TextCharAttrib::TextCharAttrib( const TextAttrib& rAttr, sal_uInt16 nStart, sal_uInt16 nEnd ) >+{ >+ mpAttr = rAttr.Clone(); >+ mnStart = nStart, >+ mnEnd = nEnd; >+} >+ >+TextCharAttrib::TextCharAttrib( const TextCharAttrib& rTextCharAttrib ) >+{ >+ mpAttr = rTextCharAttrib.GetAttr().Clone(); >+ mnStart = rTextCharAttrib.mnStart; >+ mnEnd = rTextCharAttrib.mnEnd; >+} >+ >+TextCharAttrib::~TextCharAttrib() >+{ >+ delete mpAttr; >+} >+ >+// ------------------------------------------------------------------------- >+// (+) class TextCharAttribList >+// ------------------------------------------------------------------------- >+ >+TextCharAttribList::TextCharAttribList() >+{ >+ mbHasEmptyAttribs = sal_False; >+} >+ >+TextCharAttribList::~TextCharAttribList() >+{ >+ // PTRARR_DEL >+} >+ >+void TextCharAttribList::Clear( sal_Bool bDestroyAttribs ) >+{ >+ if ( bDestroyAttribs ) >+ for(iterator it = begin(); it != end(); ++it) >+ delete *it; >+ TextCharAttribs::clear(); >+} >+ >+ >+void TextCharAttribList::InsertAttrib( TextCharAttrib* pAttrib ) >+{ >+ if ( pAttrib->IsEmpty() ) >+ mbHasEmptyAttribs = sal_True; >+ >+ const sal_uInt16 nCount = size(); >+ const sal_uInt16 nStart = pAttrib->GetStart(); // vielleicht besser fuer Comp.Opt. >+ sal_Bool bInserted = sal_False; >+ for ( sal_uInt16 x = 0; x < nCount; x++ ) >+ { >+ TextCharAttrib* pCurAttrib = GetAttrib( x ); >+ if ( pCurAttrib->GetStart() > nStart ) >+ { >+ insert( begin() + x, pAttrib ); >+ bInserted = sal_True; >+ break; >+ } >+ } >+ if ( !bInserted ) >+ push_back( pAttrib ); >+} >+ >+void TextCharAttribList::ResortAttribs() >+{ >+ if ( !empty() ) >+ std::sort( begin(), end(), CompareStart ); >+} >+ >+TextCharAttrib* TextCharAttribList::FindAttrib( sal_uInt16 nWhich, sal_uInt16 nPos ) >+{ >+ // Rueckwaerts, falls eins dort endet, das naechste startet. >+ // => Das startende gilt... >+ >+ for ( sal_uInt16 nAttr = size(); nAttr; ) >+ { >+ TextCharAttrib* pAttr = GetAttrib( --nAttr ); >+ >+ if ( pAttr->GetEnd() < nPos ) >+ return 0; >+ >+ if ( ( pAttr->Which() == nWhich ) && pAttr->IsIn(nPos) ) >+ return pAttr; >+ } >+ return NULL; >+} >+ >+TextCharAttrib* TextCharAttribList::FindNextAttrib( sal_uInt16 nWhich, sal_uInt16 nFromPos, sal_uInt16 nMaxPos ) const >+{ >+ DBG_ASSERT( nWhich, "FindNextAttrib: Which?" ); >+ const sal_uInt16 nAttribs = size(); >+ for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ ) >+ { >+ TextCharAttrib* pAttr = GetAttrib( nAttr ); >+ if ( ( pAttr->GetStart() >= nFromPos ) && >+ ( pAttr->GetEnd() <= nMaxPos ) && >+ ( pAttr->Which() == nWhich ) ) >+ return pAttr; >+ } >+ return NULL; >+} >+ >+sal_Bool TextCharAttribList::HasAttrib( sal_uInt16 nWhich ) const >+{ >+ for ( sal_uInt16 nAttr = size(); nAttr; ) >+ { >+ const TextCharAttrib* pAttr = GetAttrib( --nAttr ); >+ if ( pAttr->Which() == nWhich ) >+ return sal_True; >+ } >+ return sal_False; >+} >+ >+sal_Bool TextCharAttribList::HasBoundingAttrib( sal_uInt16 nBound ) >+{ >+ // Rueckwaerts, falls eins dort endet, das naechste startet. >+ // => Das startende gilt... >+ for ( sal_uInt16 nAttr = size(); nAttr; ) >+ { >+ TextCharAttrib* pAttr = GetAttrib( --nAttr ); >+ >+ if ( pAttr->GetEnd() < nBound ) >+ return sal_False; >+ >+ if ( ( pAttr->GetStart() == nBound ) || ( pAttr->GetEnd() == nBound ) ) >+ return sal_True; >+ } >+ return sal_False; >+} >+ >+TextCharAttrib* TextCharAttribList::FindEmptyAttrib( sal_uInt16 nWhich, sal_uInt16 nPos ) >+{ >+ if ( !mbHasEmptyAttribs ) >+ return 0; >+ >+ const sal_uInt16 nAttribs = size(); >+ for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ ) >+ { >+ TextCharAttrib* pAttr = GetAttrib( nAttr ); >+ if ( pAttr->GetStart() > nPos ) >+ return 0; >+ >+ if ( ( pAttr->GetStart() == nPos ) && ( pAttr->GetEnd() == nPos ) && ( pAttr->Which() == nWhich ) ) >+ return pAttr; >+ } >+ return 0; >+} >+ >+void TextCharAttribList::DeleteEmptyAttribs() >+{ >+ for ( sal_uInt16 nAttr = 0; nAttr < size(); nAttr++ ) >+ { >+ TextCharAttrib* pAttr = GetAttrib( nAttr ); >+ if ( pAttr->IsEmpty() ) >+ { >+ erase( begin() + nAttr ); >+ delete pAttr; >+ nAttr--; >+ } >+ } >+ mbHasEmptyAttribs = sal_False; >+} >+ >+// ------------------------------------------------------------------------- >+// (+) class TextNode >+// ------------------------------------------------------------------------- >+ >+TextNode::TextNode( const String& rText ) : >+ maText( rText ) >+{ >+} >+ >+void TextNode::ExpandAttribs( sal_uInt16 nIndex, sal_uInt16 nNew ) >+{ >+ if ( !nNew ) >+ return; >+ >+ sal_Bool bResort = sal_False; >+ sal_uInt16 nAttribs = maCharAttribs.Count(); >+ for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ ) >+ { >+ TextCharAttrib* pAttrib = maCharAttribs.GetAttrib( nAttr ); >+ 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 ); >+ } >+ // 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 ( !maCharAttribs.FindEmptyAttrib( pAttrib->Which(), nIndex ) ) >+ { >+ pAttrib->Expand( nNew ); >+ } >+ else >+ bResort = sal_True; >+ } >+ // 2: Attribut startet davor, geht hinter Index... >+ else if ( ( pAttrib->GetStart() < nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) >+ { >+ pAttrib->Expand( nNew ); >+ } >+ // 3: Attribut startet auf Index... >+ else if ( pAttrib->GetStart() == nIndex ) >+ { >+ if ( nIndex == 0 ) >+ { >+ pAttrib->Expand( nNew ); >+// bResort = sal_True; // es gibt ja keine Features mehr... >+ } >+ else >+ pAttrib->MoveForward( nNew ); >+ } >+ } >+ >+ DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Expand: Attribut verdreht!" ); >+ DBG_ASSERT( ( pAttrib->GetEnd() <= maText.Len() ), "Expand: Attrib groesser als Absatz!" ); >+ DBG_ASSERT( !pAttrib->IsEmpty(), "Leeres Attribut nach ExpandAttribs?" ); >+ } >+ >+ if ( bResort ) >+ maCharAttribs.ResortAttribs(); >+} >+ >+void TextNode::CollapsAttribs( sal_uInt16 nIndex, sal_uInt16 nDeleted ) >+{ >+ if ( !nDeleted ) >+ return; >+ >+ sal_Bool bResort = sal_False; >+ sal_uInt16 nEndChanges = nIndex+nDeleted; >+ >+ for ( sal_uInt16 nAttr = 0; nAttr < maCharAttribs.Count(); nAttr++ ) >+ { >+ TextCharAttrib* pAttrib = maCharAttribs.GetAttrib( nAttr ); >+ sal_Bool bDelAttr = sal_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->GetStart() == nIndex ) && ( pAttrib->GetEnd() == nEndChanges ) ) >+ pAttrib->GetEnd() = nIndex; // leer >+ else >+ bDelAttr = sal_True; >+ } >+ // 2. Attribut beginnt davor, endet drinnen oder dahinter... >+ else if ( ( pAttrib->GetStart() <= nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) >+ { >+ 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! >+ pAttrib->GetStart() = nEndChanges; >+ pAttrib->MoveBackward( nDeleted ); >+ } >+ } >+ >+ DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Collaps: Attribut verdreht!" ); >+ DBG_ASSERT( ( pAttrib->GetEnd() <= maText.Len()) || bDelAttr, "Collaps: Attrib groesser als Absatz!" ); >+ if ( bDelAttr /* || pAttrib->IsEmpty() */ ) >+ { >+ bResort = sal_True; >+ maCharAttribs.RemoveAttrib( nAttr ); >+ delete pAttrib; >+ nAttr--; >+ } >+ else if ( pAttrib->IsEmpty() ) >+ maCharAttribs.HasEmptyAttribs() = sal_True; >+ } >+ >+ if ( bResort ) >+ maCharAttribs.ResortAttribs(); >+} >+ >+void TextNode::InsertText( sal_uInt16 nPos, const String& rText ) >+{ >+ maText.Insert( rText, nPos ); >+ ExpandAttribs( nPos, rText.Len() ); >+} >+ >+void TextNode::InsertText( sal_uInt16 nPos, sal_Unicode c ) >+{ >+ maText.Insert( c, nPos ); >+ ExpandAttribs( nPos, 1 ); >+} >+ >+void TextNode::RemoveText( sal_uInt16 nPos, sal_uInt16 nChars ) >+{ >+ maText.Erase( nPos, nChars ); >+ CollapsAttribs( nPos, nChars ); >+} >+ >+TextNode* TextNode::Split( sal_uInt16 nPos, sal_Bool bKeepEndingAttribs ) >+{ >+ String aNewText; >+ if ( nPos < maText.Len() ) >+ { >+ aNewText = maText.Copy( nPos ); >+ maText.Erase( nPos ); >+ } >+ TextNode* pNew = new TextNode( aNewText ); >+ >+ for ( sal_uInt16 nAttr = 0; nAttr < maCharAttribs.Count(); nAttr++ ) >+ { >+ TextCharAttrib* pAttrib = maCharAttribs.GetAttrib( nAttr ); >+ if ( pAttrib->GetEnd() < nPos ) >+ { >+ // bleiben unveraendert.... >+ ; >+ } >+ else if ( pAttrib->GetEnd() == nPos ) >+ { >+ // muessen als leeres Attribut kopiert werden. >+ // !FindAttrib nur sinnvoll, wenn Rueckwaerts durch Liste! >+ if ( bKeepEndingAttribs && !pNew->maCharAttribs.FindAttrib( pAttrib->Which(), 0 ) ) >+ { >+ TextCharAttrib* pNewAttrib = new TextCharAttrib( *pAttrib ); >+ pNewAttrib->GetStart() = 0; >+ pNewAttrib->GetEnd() = 0; >+ pNew->maCharAttribs.InsertAttrib( pNewAttrib ); >+ } >+ } >+ else if ( pAttrib->IsInside( nPos ) || ( !nPos && !pAttrib->GetStart() ) ) >+ { >+ // Wenn ganz vorne gecuttet wird, muss das Attribut erhalten bleiben! >+ // muessen kopiert und geaendert werden >+ TextCharAttrib* pNewAttrib = new TextCharAttrib( *pAttrib ); >+ pNewAttrib->GetStart() = 0; >+ pNewAttrib->GetEnd() = pAttrib->GetEnd()-nPos; >+ pNew->maCharAttribs.InsertAttrib( pNewAttrib ); >+ // stutzen: >+ pAttrib->GetEnd() = nPos; >+ } >+ else >+ { >+ DBG_ASSERT( pAttrib->GetStart() >= nPos, "Start < nPos!" ); >+ DBG_ASSERT( pAttrib->GetEnd() >= nPos, "End < nPos!" ); >+ // alle dahinter verschieben in den neuen Node (this) >+ maCharAttribs.RemoveAttrib( nAttr ); >+ pNew->maCharAttribs.InsertAttrib( pAttrib ); >+ pAttrib->GetStart() = pAttrib->GetStart() - nPos; >+ pAttrib->GetEnd() = pAttrib->GetEnd() - nPos; >+ nAttr--; >+ } >+ } >+ return pNew; >+} >+ >+void TextNode::Append( const TextNode& rNode ) >+{ >+ sal_uInt16 nOldLen = maText.Len(); >+ >+ maText += rNode.GetText(); >+ >+ const sal_uInt16 nAttribs = rNode.GetCharAttribs().Count(); >+ for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ ) >+ { >+ TextCharAttrib* pAttrib = rNode.GetCharAttribs().GetAttrib( nAttr ); >+ sal_Bool bMelted = sal_False; >+ if ( pAttrib->GetStart() == 0 ) >+ { >+ // Evtl koennen Attribute zusammengefasst werden: >+ sal_uInt16 nTmpAttribs = maCharAttribs.Count(); >+ for ( sal_uInt16 nTmpAttr = 0; nTmpAttr < nTmpAttribs; nTmpAttr++ ) >+ { >+ TextCharAttrib* pTmpAttrib = maCharAttribs.GetAttrib( nTmpAttr ); >+ >+ if ( pTmpAttrib->GetEnd() == nOldLen ) >+ { >+ if ( ( pTmpAttrib->Which() == pAttrib->Which() ) && >+ ( pTmpAttrib->GetAttr() == pAttrib->GetAttr() ) ) >+ { >+ pTmpAttrib->GetEnd() = >+ pTmpAttrib->GetEnd() + pAttrib->GetLen(); >+ bMelted = sal_True; >+ break; // es kann nur eins von der Sorte an der Stelle geben >+ } >+ } >+ } >+ } >+ >+ if ( !bMelted ) >+ { >+ TextCharAttrib* pNewAttrib = new TextCharAttrib( *pAttrib ); >+ pNewAttrib->GetStart() = pNewAttrib->GetStart() + nOldLen; >+ pNewAttrib->GetEnd() = pNewAttrib->GetEnd() + nOldLen; >+ maCharAttribs.InsertAttrib( pNewAttrib ); >+ } >+ } >+} >+ >+// ------------------------------------------------------------------------- >+// (+) class TextDoc >+// ------------------------------------------------------------------------- >+ >+TextDoc::TextDoc() >+{ >+ mnLeftMargin = 0; >+}; >+ >+TextDoc::~TextDoc() >+{ >+ DestroyTextNodes(); >+} >+ >+void TextDoc::Clear() >+{ >+ DestroyTextNodes(); >+} >+ >+void TextDoc::DestroyTextNodes() >+{ >+ for ( sal_uLong nNode = 0; nNode < maTextNodes.Count(); nNode++ ) >+ delete maTextNodes.GetObject( nNode ); >+ maTextNodes.clear(); >+} >+ >+String TextDoc::GetText( const sal_Unicode* pSep ) const >+{ >+ sal_uLong nLen = GetTextLen( pSep ); >+ sal_uLong nNodes = maTextNodes.Count(); >+ >+ if ( nLen > STRING_MAXLEN ) >+ { >+ OSL_FAIL( "Text zu gross fuer String" ); >+ return String(); >+ } >+ >+ String aASCIIText; >+ sal_uLong nLastNode = nNodes-1; >+ for ( sal_uLong nNode = 0; nNode < nNodes; nNode++ ) >+ { >+ TextNode* pNode = maTextNodes.GetObject( nNode ); >+ String aTmp( pNode->GetText() ); >+ aASCIIText += aTmp; >+ if ( pSep && ( nNode != nLastNode ) ) >+ aASCIIText += pSep; >+ } >+ >+ return aASCIIText; >+} >+ >+XubString TextDoc::GetText( sal_uLong nPara ) const >+{ >+ XubString aText; >+ TextNode* pNode = ( nPara < maTextNodes.Count() ) ? maTextNodes.GetObject( nPara ) : 0; >+ if ( pNode ) >+ aText = pNode->GetText(); >+ >+ return aText; >+} >+ >+ >+sal_uLong TextDoc::GetTextLen( const xub_Unicode* pSep, const TextSelection* pSel ) const >+{ >+ sal_uLong nLen = 0; >+ sal_uLong nNodes = maTextNodes.Count(); >+ if ( nNodes ) >+ { >+ sal_uLong nStartNode = 0; >+ sal_uLong nEndNode = nNodes-1; >+ if ( pSel ) >+ { >+ nStartNode = pSel->GetStart().GetPara(); >+ nEndNode = pSel->GetEnd().GetPara(); >+ } >+ >+ for ( sal_uLong nNode = nStartNode; nNode <= nEndNode; nNode++ ) >+ { >+ TextNode* pNode = maTextNodes.GetObject( nNode ); >+ >+ sal_uInt16 nS = 0; >+ sal_uLong nE = pNode->GetText().Len(); >+ if ( pSel && ( nNode == pSel->GetStart().GetPara() ) ) >+ nS = pSel->GetStart().GetIndex(); >+ if ( pSel && ( nNode == pSel->GetEnd().GetPara() ) ) >+ nE = pSel->GetEnd().GetIndex(); >+ >+ nLen += ( nE - nS ); >+ } >+ >+ if ( pSep ) >+ nLen += (nEndNode-nStartNode) * rtl_ustr_getLength(pSep); >+ } >+ >+ return nLen; >+} >+ >+TextPaM TextDoc::InsertText( const TextPaM& rPaM, xub_Unicode c ) >+{ >+ DBG_ASSERT( c != 0x0A, "TextDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); >+ DBG_ASSERT( c != 0x0D, "TextDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); >+ >+ TextNode* pNode = maTextNodes.GetObject( rPaM.GetPara() ); >+ pNode->InsertText( rPaM.GetIndex(), c ); >+ >+ TextPaM aPaM( rPaM.GetPara(), rPaM.GetIndex()+1 ); >+ return aPaM; >+} >+ >+TextPaM TextDoc::InsertText( const TextPaM& rPaM, const XubString& rStr ) >+{ >+ DBG_ASSERT( rStr.Search( 0x0A ) == STRING_NOTFOUND, "TextDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); >+ DBG_ASSERT( rStr.Search( 0x0D ) == STRING_NOTFOUND, "TextDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); >+ >+ TextNode* pNode = maTextNodes.GetObject( rPaM.GetPara() ); >+ pNode->InsertText( rPaM.GetIndex(), rStr ); >+ >+ TextPaM aPaM( rPaM.GetPara(), rPaM.GetIndex()+rStr.Len() ); >+ return aPaM; >+} >+ >+TextPaM TextDoc::InsertParaBreak( const TextPaM& rPaM, sal_Bool bKeepEndingAttribs ) >+{ >+ TextNode* pNode = maTextNodes.GetObject( rPaM.GetPara() ); >+ TextNode* pNew = pNode->Split( rPaM.GetIndex(), bKeepEndingAttribs ); >+ >+ maTextNodes.Insert( pNew, rPaM.GetPara()+1 ); >+ >+ TextPaM aPaM( rPaM.GetPara()+1, 0 ); >+ return aPaM; >+} >+ >+TextPaM TextDoc::ConnectParagraphs( TextNode* pLeft, TextNode* pRight ) >+{ >+ sal_uInt16 nPrevLen = pLeft->GetText().Len(); >+ pLeft->Append( *pRight ); >+ >+ // der rechte verschwindet. >+ sal_uLong nRight = maTextNodes.GetPos( pRight ); >+ maTextNodes.Remove( nRight ); >+ delete pRight; >+ >+ sal_uLong nLeft = maTextNodes.GetPos( pLeft ); >+ TextPaM aPaM( nLeft, nPrevLen ); >+ return aPaM; >+} >+ >+TextPaM TextDoc::RemoveChars( const TextPaM& rPaM, sal_uInt16 nChars ) >+{ >+ TextNode* pNode = maTextNodes.GetObject( rPaM.GetPara() ); >+ pNode->RemoveText( rPaM.GetIndex(), nChars ); >+ >+ return rPaM; >+} >+ >+sal_Bool TextDoc::IsValidPaM( const TextPaM& rPaM ) >+{ >+ if ( rPaM.GetPara() >= maTextNodes.Count() ) >+ { >+ OSL_FAIL( "PaM: Para out of range" ); >+ return sal_False; >+ } >+ TextNode * pNode = maTextNodes.GetObject( rPaM.GetPara() ); >+ if ( rPaM.GetIndex() > pNode->GetText().Len() ) >+ { >+ OSL_FAIL( "PaM: Index out of range" ); >+ return sal_False; >+ } >+ return sal_True; >+} >+ >+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/vcl/source/edit/textdoc.hxx b/vcl/source/edit/textdoc.hxx >new file mode 100644 >index 0000000..a1529a4 >--- /dev/null >+++ b/vcl/source/edit/textdoc.hxx >@@ -0,0 +1,145 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >+/************************************************************************* >+ * >+ * 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 _TEXTDOC_HXX >+#define _TEXTDOC_HXX >+ >+#include <vcl/textdata.hxx> >+#include <vcl/txtattr.hxx> >+ >+#include <tools/string.hxx> >+#include <vector> >+ >+class TextCharAttribs : public std::vector<TextCharAttrib*> { >+public: >+ ~TextCharAttribs() >+ { >+ for( iterator it = begin(); it != end(); ++it ) >+ delete *it; >+ } >+}; >+ >+class TextCharAttribList : private TextCharAttribs >+{ >+private: >+ sal_Bool mbHasEmptyAttribs; >+ >+ TextCharAttribList( const TextCharAttribList& ) : TextCharAttribs() {} >+ >+public: >+ TextCharAttribList(); >+ ~TextCharAttribList(); >+ >+ void Clear( sal_Bool bDestroyAttribs ); >+ sal_uInt16 Count() const { return TextCharAttribs::size(); } >+ >+ TextCharAttrib* GetAttrib( sal_uInt16 n ) const { return TextCharAttribs::operator[]( n ); } >+ void RemoveAttrib( sal_uInt16 n ) { TextCharAttribs::erase( begin() + n ); } >+ >+ void InsertAttrib( TextCharAttrib* pAttrib ); >+ >+ void DeleteEmptyAttribs(); >+ void ResortAttribs(); >+ >+ sal_Bool HasEmptyAttribs() const { return mbHasEmptyAttribs; } >+ sal_Bool& HasEmptyAttribs() { return mbHasEmptyAttribs; } >+ >+ TextCharAttrib* FindAttrib( sal_uInt16 nWhich, sal_uInt16 nPos ); >+ TextCharAttrib* FindNextAttrib( sal_uInt16 nWhich, sal_uInt16 nFromPos, sal_uInt16 nMaxPos = 0xFFFF ) const; >+ TextCharAttrib* FindEmptyAttrib( sal_uInt16 nWhich, sal_uInt16 nPos ); >+ sal_Bool HasAttrib( sal_uInt16 nWhich ) const; >+ sal_Bool HasBoundingAttrib( sal_uInt16 nBound ); >+}; >+ >+ >+class TextNode >+{ >+private: >+ String maText; >+ TextCharAttribList maCharAttribs; >+ >+ TextNode( const TextNode& ) {;} >+protected: >+ void ExpandAttribs( sal_uInt16 nIndex, sal_uInt16 nNewChars ); >+ void CollapsAttribs( sal_uInt16 nIndex, sal_uInt16 nDelChars ); >+ >+public: >+ TextNode( const String& rText ); >+ >+ >+ const String& GetText() const { return maText; } >+ >+ const TextCharAttribList& GetCharAttribs() const { return maCharAttribs; } >+ TextCharAttribList& GetCharAttribs() { return maCharAttribs; } >+ >+ void InsertText( sal_uInt16 nPos, const String& rText ); >+ void InsertText( sal_uInt16 nPos, sal_Unicode c ); >+ void RemoveText( sal_uInt16 nPos, sal_uInt16 nChars ); >+ >+ TextNode* Split( sal_uInt16 nPos, sal_Bool bKeepEndigAttribs ); >+ void Append( const TextNode& rNode ); >+}; >+ >+class TextDoc >+{ >+private: >+ ToolsList<TextNode*> maTextNodes; >+ sal_uInt16 mnLeftMargin; >+ >+protected: >+ void DestroyTextNodes(); >+ >+public: >+ TextDoc(); >+ ~TextDoc(); >+ >+ void Clear(); >+ >+ ToolsList<TextNode*>& GetNodes() { return maTextNodes; } >+ const ToolsList<TextNode*>& GetNodes() const { return maTextNodes; } >+ >+ TextPaM RemoveChars( const TextPaM& rPaM, sal_uInt16 nChars ); >+ TextPaM InsertText( const TextPaM& rPaM, sal_Unicode c ); >+ TextPaM InsertText( const TextPaM& rPaM, const String& rStr ); >+ >+ TextPaM InsertParaBreak( const TextPaM& rPaM, sal_Bool bKeepEndingAttribs ); >+ TextPaM ConnectParagraphs( TextNode* pLeft, TextNode* pRight ); >+ >+ sal_uLong GetTextLen( const sal_Unicode* pSep, const TextSelection* pSel = NULL ) const; >+ String GetText( const sal_Unicode* pSep ) const; >+ String GetText( sal_uLong nPara ) const; >+ >+ void SetLeftMargin( sal_uInt16 n ) { mnLeftMargin = n; } >+ sal_uInt16 GetLeftMargin() const { return mnLeftMargin; } >+ >+ sal_Bool IsValidPaM( const TextPaM& rPaM ); >+}; >+ >+#endif // _TEXTDOC_HXX >+ >+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/vcl/source/edit/texteng.cxx b/vcl/source/edit/texteng.cxx >new file mode 100644 >index 0000000..bd6d179 >--- /dev/null >+++ b/vcl/source/edit/texteng.cxx >@@ -0,0 +1,3205 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >+/************************************************************************* >+ * >+ * 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 <tools/stream.hxx> >+ >+#include <vcl/texteng.hxx> >+#include <vcl/textview.hxx> >+#include <textdoc.hxx> >+#include <textdat2.hxx> >+#include <textundo.hxx> >+#include <textund2.hxx> >+#include <svl/ctloptions.hxx> >+#include <vcl/window.hxx> >+ >+#include <vcl/edit.hxx> >+#include <com/sun/star/lang/XMultiServiceFactory.hpp> >+#include <com/sun/star/beans/PropertyValues.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 <com/sun/star/i18n/InputSequenceCheckMode.hpp> >+#include <com/sun/star/i18n/ScriptType.hpp> >+ >+#include <comphelper/processfactory.hxx> >+ >+#include <unotools/localedatawrapper.hxx> >+#include <vcl/unohelp.hxx> >+ >+#include <vcl/svapp.hxx> >+#include <vcl/metric.hxx> >+ >+#include <unicode/ubidi.h> >+ >+#include <set> >+#include <vector> >+#include <boost/foreach.hpp> >+ >+using namespace ::com::sun::star; >+using namespace ::com::sun::star::uno; >+using namespace ::rtl; >+ >+ >+// ------------------------------------------------------------------------- >+// (-) class TextEngine >+// ------------------------------------------------------------------------- >+TextEngine::TextEngine() >+{ >+ mpDoc = 0; >+ mpTEParaPortions = 0; >+ >+ mpViews = new TextViews; >+ mpActiveView = NULL; >+ >+ mbIsFormatting = sal_False; >+ mbFormatted = sal_False; >+ mbUpdate = sal_True; >+ mbModified = sal_False; >+ mbUndoEnabled = sal_False; >+ mbIsInUndo = sal_False; >+ mbDowning = sal_False; >+ mbRightToLeft = sal_False; >+ mbHasMultiLineParas = sal_False; >+ >+ meAlign = TXTALIGN_LEFT; >+ >+ mnMaxTextWidth = 0; >+ mnMaxTextLen = 0; >+ mnCurTextWidth = 0xFFFFFFFF; >+ mnCurTextHeight = 0; >+ >+ mpUndoManager = NULL; >+ mpIMEInfos = NULL; >+ mpLocaleDataWrapper = NULL; >+ >+ mpIdleFormatter = new IdleFormatter; >+ mpIdleFormatter->SetTimeoutHdl( LINK( this, TextEngine, IdleFormatHdl ) ); >+ >+ mpRefDev = new VirtualDevice; >+ >+ ImpInitLayoutMode( mpRefDev ); >+ >+ ImpInitDoc(); >+ >+ maTextColor = COL_BLACK; >+ Font aFont; >+ aFont.SetTransparent( sal_False ); >+ Color aFillColor( aFont.GetFillColor() ); >+ aFillColor.SetTransparency( 0 ); >+ aFont.SetFillColor( aFillColor ); >+ SetFont( aFont ); >+} >+ >+TextEngine::~TextEngine() >+{ >+ mbDowning = sal_True; >+ >+ delete mpIdleFormatter; >+ delete mpDoc; >+ delete mpTEParaPortions; >+ delete mpViews; // nur die Liste, nicht die Vies >+ delete mpRefDev; >+ delete mpUndoManager; >+ delete mpIMEInfos; >+ delete mpLocaleDataWrapper; >+} >+ >+void TextEngine::InsertView( TextView* pTextView ) >+{ >+ mpViews->push_back( pTextView ); >+ pTextView->SetSelection( TextSelection() ); >+ >+ if ( !GetActiveView() ) >+ SetActiveView( pTextView ); >+} >+ >+void TextEngine::RemoveView( TextView* pTextView ) >+{ >+ TextViews::iterator it = std::find( mpViews->begin(), mpViews->end(), pTextView ); >+ if( it != mpViews->end() ) >+ { >+ pTextView->HideCursor(); >+ mpViews->erase( it ); >+ if ( pTextView == GetActiveView() ) >+ SetActiveView( 0 ); >+ } >+} >+ >+sal_uInt16 TextEngine::GetViewCount() const >+{ >+ return mpViews->size(); >+} >+ >+TextView* TextEngine::GetView( sal_uInt16 nView ) const >+{ >+ return (*mpViews)[ nView ]; >+} >+ >+TextView* TextEngine::GetActiveView() const >+{ >+ return mpActiveView; >+} >+ >+void TextEngine::SetActiveView( TextView* pTextView ) >+{ >+ if ( pTextView != mpActiveView ) >+ { >+ if ( mpActiveView ) >+ mpActiveView->HideSelection(); >+ >+ mpActiveView = pTextView; >+ >+ if ( mpActiveView ) >+ mpActiveView->ShowSelection(); >+ } >+} >+ >+void TextEngine::SetFont( const Font& rFont ) >+{ >+ if ( rFont != maFont ) >+ { >+ maFont = rFont; >+ // #i40221# As the font's color now defaults to transparent (since i35764) >+ // we have to choose a useful textcolor in this case. >+ // Otherwise maTextColor and maFont.GetColor() are both transparent.... >+ if( rFont.GetColor() == COL_TRANSPARENT ) >+ maTextColor = COL_BLACK; >+ else >+ maTextColor = rFont.GetColor(); >+ >+ // Wegen Selektion keinen Transparenten Font zulassen... >+ // (Sonst spaeter in ImplPaint den Hintergrund anders loeschen...) >+ maFont.SetTransparent( sal_False ); >+ // Tell VCL not to use the font color, use text color from OutputDevice >+ maFont.SetColor( COL_TRANSPARENT ); >+ Color aFillColor( maFont.GetFillColor() ); >+ aFillColor.SetTransparency( 0 ); >+ maFont.SetFillColor( aFillColor ); >+ >+ maFont.SetAlign( ALIGN_TOP ); >+ mpRefDev->SetFont( maFont); >+ Size aTextSize; >+ aTextSize.Width() = mpRefDev->GetTextWidth(rtl::OUString(" ")); >+ aTextSize.Height() = mpRefDev->GetTextHeight(); >+ if ( !aTextSize.Width() ) >+ aTextSize.Width() = mpRefDev->GetTextWidth(rtl::OUString("XXXX")); >+ >+ mnDefTab = (sal_uInt16)aTextSize.Width(); >+ if ( !mnDefTab ) >+ mnDefTab = 1; >+ mnCharHeight = (sal_uInt16)aTextSize.Height(); >+ mnFixCharWidth100 = 0; >+ >+ FormatFullDoc(); >+ UpdateViews(); >+ >+ for ( sal_uInt16 nView = mpViews->size(); nView; ) >+ { >+ TextView* pView = (*mpViews)[ --nView ]; >+ pView->GetWindow()->SetInputContext( InputContext( GetFont(), !pView->IsReadOnly() ? INPUTCONTEXT_TEXT|INPUTCONTEXT_EXTTEXTINPUT : 0 ) ); >+ } >+ } >+} >+ >+void TextEngine::SetMaxTextLen( sal_uLong nLen ) >+{ >+ mnMaxTextLen = nLen; >+} >+ >+void TextEngine::SetMaxTextWidth( sal_uLong nMaxWidth ) >+{ >+ if ( nMaxWidth != mnMaxTextWidth ) >+ { >+ mnMaxTextWidth = Min( nMaxWidth, (sal_uLong)0x7FFFFFFF ); >+ FormatFullDoc(); >+ UpdateViews(); >+ } >+} >+ >+static sal_Unicode static_aLFText[] = { '\n', 0 }; >+static sal_Unicode static_aCRText[] = { '\r', 0 }; >+static sal_Unicode static_aCRLFText[] = { '\r', '\n', 0 }; >+ >+static inline const sal_Unicode* static_getLineEndText( LineEnd aLineEnd ) >+{ >+ const sal_Unicode* pRet = NULL; >+ >+ switch( aLineEnd ) >+ { >+ case LINEEND_LF: pRet = static_aLFText;break; >+ case LINEEND_CR: pRet = static_aCRText;break; >+ case LINEEND_CRLF: pRet = static_aCRLFText;break; >+ } >+ return pRet; >+} >+ >+void TextEngine::ReplaceText(const TextSelection& rSel, const String& rText) >+{ >+ ImpInsertText( rSel, rText ); >+} >+ >+String TextEngine::GetText( LineEnd aSeparator ) const >+{ >+ return mpDoc->GetText( static_getLineEndText( aSeparator ) ); >+} >+ >+String TextEngine::GetTextLines( LineEnd aSeparator ) const >+{ >+ String aText; >+ sal_uLong nParas = mpTEParaPortions->Count(); >+ const sal_Unicode* pSep = static_getLineEndText( aSeparator ); >+ for ( sal_uLong nP = 0; nP < nParas; nP++ ) >+ { >+ TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nP ); >+ >+ sal_uInt16 nLines = pTEParaPortion->GetLines().size(); >+ for ( sal_uInt16 nL = 0; nL < nLines; nL++ ) >+ { >+ TextLine* pLine = pTEParaPortion->GetLines()[nL]; >+ aText += pTEParaPortion->GetNode()->GetText().Copy( pLine->GetStart(), pLine->GetEnd() - pLine->GetStart() ); >+ if ( pSep && ( ( (nP+1) < nParas ) || ( (nL+1) < nLines ) ) ) >+ aText += pSep; >+ } >+ } >+ return aText; >+} >+ >+String TextEngine::GetText( sal_uLong nPara ) const >+{ >+ return mpDoc->GetText( nPara ); >+} >+ >+sal_uLong TextEngine::GetTextLen( LineEnd aSeparator ) const >+{ >+ return mpDoc->GetTextLen( static_getLineEndText( aSeparator ) ); >+} >+ >+sal_uLong TextEngine::GetTextLen( const TextSelection& rSel, LineEnd aSeparator ) const >+{ >+ TextSelection aSel( rSel ); >+ aSel.Justify(); >+ ValidateSelection( aSel ); >+ return mpDoc->GetTextLen( static_getLineEndText( aSeparator ), &aSel ); >+} >+ >+sal_uInt16 TextEngine::GetTextLen( sal_uLong nPara ) const >+{ >+ return mpDoc->GetNodes().GetObject( nPara )->GetText().Len(); >+} >+ >+void TextEngine::SetUpdateMode( sal_Bool bUpdate ) >+{ >+ if ( bUpdate != mbUpdate ) >+ { >+ mbUpdate = bUpdate; >+ if ( mbUpdate ) >+ { >+ FormatAndUpdate( GetActiveView() ); >+ if ( GetActiveView() ) >+ GetActiveView()->ShowCursor(); >+ } >+ } >+} >+ >+sal_Bool TextEngine::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: >+ { >+ if ( !rKeyEvent.GetKeyCode().IsMod2() ) >+ bDoesChange = sal_True; >+ } >+ break; >+ case KEY_RETURN: >+ case KEY_TAB: >+ { >+ if ( !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() ) >+ bDoesChange = sal_True; >+ } >+ break; >+ default: >+ { >+ bDoesChange = TextEngine::IsSimpleCharInput( rKeyEvent ); >+ } >+ } >+ } >+ return bDoesChange; >+} >+ >+sal_Bool TextEngine::IsSimpleCharInput( const KeyEvent& rKeyEvent ) >+{ >+ if( rKeyEvent.GetCharCode() >= 32 && rKeyEvent.GetCharCode() != 127 && >+ KEY_MOD1 != (rKeyEvent.GetKeyCode().GetModifier() & ~KEY_SHIFT) && // (ssa) #i45714#: >+ KEY_MOD2 != (rKeyEvent.GetKeyCode().GetModifier() & ~KEY_SHIFT) ) // check for Ctrl and Alt separately >+ { >+ return sal_True; >+ } >+ return sal_False; >+} >+ >+void TextEngine::ImpInitDoc() >+{ >+ if ( mpDoc ) >+ mpDoc->Clear(); >+ else >+ mpDoc = new TextDoc; >+ >+ delete mpTEParaPortions; >+ mpTEParaPortions = new TEParaPortions; >+ >+ TextNode* pNode = new TextNode( String() ); >+ mpDoc->GetNodes().Insert( pNode, 0 ); >+ >+ TEParaPortion* pIniPortion = new TEParaPortion( pNode ); >+ mpTEParaPortions->Insert( pIniPortion, (sal_uLong)0 ); >+ >+ mbFormatted = sal_False; >+ >+ ImpParagraphRemoved( TEXT_PARA_ALL ); >+ ImpParagraphInserted( 0 ); >+} >+ >+String TextEngine::GetText( const TextSelection& rSel, LineEnd aSeparator ) const >+{ >+ String aText; >+ >+ if ( !rSel.HasRange() ) >+ return aText; >+ >+ TextSelection aSel( rSel ); >+ aSel.Justify(); >+ >+ sal_uLong nStartPara = aSel.GetStart().GetPara(); >+ sal_uLong nEndPara = aSel.GetEnd().GetPara(); >+ const sal_Unicode* pSep = static_getLineEndText( aSeparator ); >+ for ( sal_uLong nNode = aSel.GetStart().GetPara(); nNode <= nEndPara; nNode++ ) >+ { >+ TextNode* pNode = mpDoc->GetNodes().GetObject( nNode ); >+ >+ sal_uInt16 nStartPos = 0; >+ sal_uInt16 nEndPos = pNode->GetText().Len(); >+ if ( nNode == nStartPara ) >+ nStartPos = aSel.GetStart().GetIndex(); >+ if ( nNode == nEndPara ) // kann auch == nStart sein! >+ nEndPos = aSel.GetEnd().GetIndex(); >+ >+ aText += pNode->GetText().Copy( nStartPos, nEndPos-nStartPos ); >+ if ( nNode < nEndPara ) >+ aText += pSep; >+ } >+ return aText; >+} >+ >+void TextEngine::ImpRemoveText() >+{ >+ ImpInitDoc(); >+ >+ TextPaM aStartPaM( 0, 0 ); >+ TextSelection aEmptySel( aStartPaM, aStartPaM ); >+ for ( sal_uInt16 nView = 0; nView < mpViews->size(); nView++ ) >+ { >+ TextView* pView = (*mpViews)[ nView ]; >+ pView->ImpSetSelection( aEmptySel ); >+ } >+ ResetUndo(); >+} >+ >+void TextEngine::SetText( const XubString& rText ) >+{ >+ ImpRemoveText(); >+ >+ sal_Bool bUndoCurrentlyEnabled = IsUndoEnabled(); >+ // Der von Hand reingesteckte Text kann nicht vom Anwender rueckgaengig gemacht werden. >+ EnableUndo( sal_False ); >+ >+ TextPaM aStartPaM( 0, 0 ); >+ TextSelection aEmptySel( aStartPaM, aStartPaM ); >+ >+ TextPaM aPaM = aStartPaM; >+ if ( rText.Len() ) >+ aPaM = ImpInsertText( aEmptySel, rText ); >+ >+ for ( sal_uInt16 nView = 0; nView < mpViews->size(); nView++ ) >+ { >+ TextView* pView = (*mpViews)[ nView ]; >+ pView->ImpSetSelection( aEmptySel ); >+ >+ // Wenn kein Text, dann auch Kein Format&Update >+ // => Der Text bleibt stehen. >+ if ( !rText.Len() && GetUpdateMode() ) >+ pView->Invalidate(); >+ } >+ >+ if( !rText.Len() ) // sonst muss spaeter noch invalidiert werden, !bFormatted reicht. >+ mnCurTextHeight = 0; >+ >+ FormatAndUpdate(); >+ >+ EnableUndo( bUndoCurrentlyEnabled ); >+ DBG_ASSERT( !HasUndoManager() || !GetUndoManager().GetUndoActionCount(), "Undo nach SetText?" ); >+} >+ >+ >+void TextEngine::CursorMoved( sal_uLong nNode ) >+{ >+ // Leere Attribute loeschen, aber nur, wenn Absatz nicht leer! >+ TextNode* pNode = mpDoc->GetNodes().GetObject( nNode ); >+ if ( pNode && pNode->GetCharAttribs().HasEmptyAttribs() && pNode->GetText().Len() ) >+ pNode->GetCharAttribs().DeleteEmptyAttribs(); >+} >+ >+void TextEngine::ImpRemoveChars( const TextPaM& rPaM, sal_uInt16 nChars, SfxUndoAction* ) >+{ >+ DBG_ASSERT( nChars, "ImpRemoveChars - 0 Chars?!" ); >+ if ( IsUndoEnabled() && !IsInUndo() ) >+ { >+ // Attribute muessen hier vorm RemoveChars fuer UNDO gesichert werden! >+ TextNode* pNode = mpDoc->GetNodes().GetObject( rPaM.GetPara() ); >+ XubString aStr( pNode->GetText().Copy( rPaM.GetIndex(), nChars ) ); >+ >+ // Pruefen, ob Attribute geloescht oder geaendert werden: >+ sal_uInt16 nStart = rPaM.GetIndex(); >+ sal_uInt16 nEnd = nStart + nChars; >+ for ( sal_uInt16 nAttr = pNode->GetCharAttribs().Count(); nAttr; ) >+ { >+ TextCharAttrib* pAttr = pNode->GetCharAttribs().GetAttrib( --nAttr ); >+ if ( ( pAttr->GetEnd() >= nStart ) && ( pAttr->GetStart() < nEnd ) ) >+ { >+ break; // for >+ } >+ } >+ InsertUndo( new TextUndoRemoveChars( this, rPaM, aStr ) ); >+ } >+ >+ mpDoc->RemoveChars( rPaM, nChars ); >+ ImpCharsRemoved( rPaM.GetPara(), rPaM.GetIndex(), nChars ); >+} >+ >+TextPaM TextEngine::ImpConnectParagraphs( sal_uLong nLeft, sal_uLong nRight ) >+{ >+ DBG_ASSERT( nLeft != nRight, "Den gleichen Absatz zusammenfuegen ?" ); >+ >+ TextNode* pLeft = mpDoc->GetNodes().GetObject( nLeft ); >+ TextNode* pRight = mpDoc->GetNodes().GetObject( nRight ); >+ >+ if ( IsUndoEnabled() && !IsInUndo() ) >+ InsertUndo( new TextUndoConnectParas( this, nLeft, pLeft->GetText().Len() ) ); >+ >+ // Erstmal Portions suchen, da pRight nach ConnectParagraphs weg. >+ TEParaPortion* pLeftPortion = mpTEParaPortions->GetObject( nLeft ); >+ TEParaPortion* pRightPortion = mpTEParaPortions->GetObject( nRight ); >+ DBG_ASSERT( pLeft && pLeftPortion, "Blinde Portion in ImpConnectParagraphs(1)" ); >+ DBG_ASSERT( pRight && pRightPortion, "Blinde Portion in ImpConnectParagraphs(2)" ); >+ >+ TextPaM aPaM = mpDoc->ConnectParagraphs( pLeft, pRight ); >+ ImpParagraphRemoved( nRight ); >+ >+ pLeftPortion->MarkSelectionInvalid( aPaM.GetIndex(), pLeft->GetText().Len() ); >+ >+ mpTEParaPortions->Remove( nRight ); >+ delete pRightPortion; >+ // der rechte Node wird von EditDoc::ConnectParagraphs() geloescht. >+ >+ return aPaM; >+} >+ >+TextPaM TextEngine::ImpDeleteText( const TextSelection& rSel ) >+{ >+ if ( !rSel.HasRange() ) >+ return rSel.GetStart(); >+ >+ TextSelection aSel( rSel ); >+ aSel.Justify(); >+ TextPaM aStartPaM( aSel.GetStart() ); >+ TextPaM aEndPaM( aSel.GetEnd() ); >+ >+ CursorMoved( aStartPaM.GetPara() ); // nur damit neu eingestellte Attribute verschwinden... >+ CursorMoved( aEndPaM.GetPara() ); // nur damit neu eingestellte Attribute verschwinden... >+ >+ DBG_ASSERT( mpDoc->IsValidPaM( aStartPaM ), "Index im Wald in ImpDeleteText" ); >+ DBG_ASSERT( mpDoc->IsValidPaM( aEndPaM ), "Index im Wald in ImpDeleteText" ); >+ >+ sal_uLong nStartNode = aStartPaM.GetPara(); >+ sal_uLong nEndNode = aEndPaM.GetPara(); >+ >+ // Alle Nodes dazwischen entfernen.... >+ for ( sal_uLong z = nStartNode+1; z < nEndNode; z++ ) >+ { >+ // Immer nStartNode+1, wegen Remove()! >+ ImpRemoveParagraph( nStartNode+1 ); >+ } >+ >+ if ( nStartNode != nEndNode ) >+ { >+ // Den Rest des StartNodes... >+ TextNode* pLeft = mpDoc->GetNodes().GetObject( nStartNode ); >+ sal_uInt16 nChars = pLeft->GetText().Len() - aStartPaM.GetIndex(); >+ if ( nChars ) >+ { >+ ImpRemoveChars( aStartPaM, nChars ); >+ TEParaPortion* pPortion = mpTEParaPortions->GetObject( nStartNode ); >+ DBG_ASSERT( pPortion, "Blinde Portion in ImpDeleteText(3)" ); >+ pPortion->MarkSelectionInvalid( aStartPaM.GetIndex(), pLeft->GetText().Len() ); >+ } >+ >+ // Den Anfang des EndNodes.... >+ nEndNode = nStartNode+1; // Die anderen Absaetze wurden geloescht >+ nChars = aEndPaM.GetIndex(); >+ if ( nChars ) >+ { >+ aEndPaM.GetPara() = nEndNode; >+ aEndPaM.GetIndex() = 0; >+ ImpRemoveChars( aEndPaM, nChars ); >+ TEParaPortion* pPortion = mpTEParaPortions->GetObject( nEndNode ); >+ DBG_ASSERT( pPortion, "Blinde Portion in ImpDeleteText(4)" ); >+ pPortion->MarkSelectionInvalid( 0, pPortion->GetNode()->GetText().Len() ); >+ } >+ >+ // Zusammenfuegen.... >+ aStartPaM = ImpConnectParagraphs( nStartNode, nEndNode ); >+ } >+ else >+ { >+ sal_uInt16 nChars; >+ nChars = aEndPaM.GetIndex() - aStartPaM.GetIndex(); >+ ImpRemoveChars( aStartPaM, nChars ); >+ TEParaPortion* pPortion = mpTEParaPortions->GetObject( nStartNode ); >+ DBG_ASSERT( pPortion, "Blinde Portion in ImpDeleteText(5)" ); >+ pPortion->MarkInvalid( aEndPaM.GetIndex(), aStartPaM.GetIndex() - aEndPaM.GetIndex() ); >+ } >+ >+// UpdateSelections(); >+ TextModified(); >+ return aStartPaM; >+} >+ >+void TextEngine::ImpRemoveParagraph( sal_uLong nPara ) >+{ >+ TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >+ TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPara ); >+ >+ // Der Node wird vom Undo verwaltet und ggf. zerstoert! >+ /* delete */ mpDoc->GetNodes().Remove( nPara ); >+ if ( IsUndoEnabled() && !IsInUndo() ) >+ InsertUndo( new TextUndoDelPara( this, pNode, nPara ) ); >+ else >+ delete pNode; >+ >+ mpTEParaPortions->Remove( nPara ); >+ delete pPortion; >+ >+ ImpParagraphRemoved( nPara ); >+} >+ >+uno::Reference < i18n::XExtendedInputSequenceChecker > TextEngine::GetInputSequenceChecker() const >+{ >+ uno::Reference < i18n::XExtendedInputSequenceChecker > xISC; >+// if ( !xISC.is() ) >+ { >+ uno::Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory(); >+ uno::Reference< uno::XInterface > xI = xMSF->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.InputSequenceChecker" )) ); >+ if ( xI.is() ) >+ { >+ Any x = xI->queryInterface( ::getCppuType((const uno::Reference< i18n::XExtendedInputSequenceChecker >*)0) ); >+ x >>= xISC; >+ } >+ } >+ return xISC; >+} >+ >+sal_Bool TextEngine::IsInputSequenceCheckingRequired( sal_Unicode c, const TextSelection& rCurSel ) const >+{ >+ uno::Reference< i18n::XBreakIterator > xBI = ((TextEngine *) this)->GetBreakIterator(); >+ SvtCTLOptions aCTLOptions; >+ >+ // get the index that really is first >+ sal_uInt16 nFirstPos = rCurSel.GetStart().GetIndex(); >+ sal_uInt16 nMaxPos = rCurSel.GetEnd().GetIndex(); >+ if (nMaxPos < nFirstPos) >+ nFirstPos = nMaxPos; >+ >+ sal_Bool bIsSequenceChecking = >+ aCTLOptions.IsCTLFontEnabled() && >+ aCTLOptions.IsCTLSequenceChecking() && >+ nFirstPos != 0 && /* first char needs not to be checked */ >+ xBI.is() && i18n::ScriptType::COMPLEX == xBI->getScriptType( rtl::OUString( c ), 0 ); >+ >+ return bIsSequenceChecking; >+} >+ >+TextPaM TextEngine::ImpInsertText( const TextSelection& rCurSel, sal_Unicode c, sal_Bool bOverwrite ) >+{ >+ return ImpInsertText( c, rCurSel, bOverwrite, sal_False ); >+} >+ >+TextPaM TextEngine::ImpInsertText( sal_Unicode c, const TextSelection& rCurSel, sal_Bool bOverwrite, sal_Bool bIsUserInput ) >+{ >+ DBG_ASSERT( c != '\n', "Zeilenumbruch bei InsertText ?" ); >+ DBG_ASSERT( c != '\r', "Zeilenumbruch bei InsertText ?" ); >+ >+ TextPaM aPaM( rCurSel.GetStart() ); >+ TextNode* pNode = mpDoc->GetNodes().GetObject( aPaM.GetPara() ); >+ >+ if ( pNode->GetText().Len() < STRING_MAXLEN ) >+ { >+ sal_Bool bDoOverwrite = ( bOverwrite && >+ ( aPaM.GetIndex() < pNode->GetText().Len() ) ) ? sal_True : sal_False; >+ >+ sal_Bool bUndoAction = ( rCurSel.HasRange() || bDoOverwrite ); >+ >+ if ( bUndoAction ) >+ UndoActionStart(); >+ >+ if ( rCurSel.HasRange() ) >+ { >+ aPaM = ImpDeleteText( rCurSel ); >+ } >+ else if ( bDoOverwrite ) >+ { >+ // Wenn Selektion, dann kein Zeichen ueberschreiben >+ TextSelection aTmpSel( aPaM ); >+ aTmpSel.GetEnd().GetIndex()++; >+ ImpDeleteText( aTmpSel ); >+ } >+ >+ if (bIsUserInput && IsInputSequenceCheckingRequired( c, rCurSel )) >+ { >+ uno::Reference < i18n::XExtendedInputSequenceChecker > xISC = GetInputSequenceChecker(); >+ SvtCTLOptions aCTLOptions; >+ >+ if (xISC.is()) >+ { >+ xub_StrLen nTmpPos = aPaM.GetIndex(); >+ sal_Int16 nCheckMode = aCTLOptions.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( mpDoc->GetText( aPaM.GetPara() ).Copy(0, nTmpPos) ); >+ rtl::OUString aNewText( aOldText ); >+ if (aCTLOptions.IsCTLSequenceCheckingTypeAndReplace()) >+ { >+ 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; >+ >+ String aChgText( aNewText.copy( nChgPos ) ); >+ >+ // select text from first pos to be changed to current pos >+ TextSelection aSel( TextPaM( aPaM.GetPara(), (sal_uInt16) nChgPos ), aPaM ); >+ >+ if (aChgText.Len()) >+ // ImpInsertText implicitly handles undo... >+ return ImpInsertText( aSel, aChgText ); >+ 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() ) >+ { >+ TextUndoInsertChars* pNewUndo = new TextUndoInsertChars( this, aPaM, rtl::OUString(c) ); >+ sal_Bool bTryMerge = ( !bDoOverwrite && ( c != ' ' ) ) ? sal_True : sal_False; >+ InsertUndo( pNewUndo, bTryMerge ); >+ } >+ >+ TEParaPortion* pPortion = mpTEParaPortions->GetObject( aPaM.GetPara() ); >+ pPortion->MarkInvalid( aPaM.GetIndex(), 1 ); >+ if ( c == '\t' ) >+ pPortion->SetNotSimpleInvalid(); >+ aPaM = mpDoc->InsertText( aPaM, c ); >+ ImpCharsInserted( aPaM.GetPara(), aPaM.GetIndex()-1, 1 ); >+ >+ TextModified(); >+ >+ if ( bUndoAction ) >+ UndoActionEnd(); >+ } >+ >+ return aPaM; >+} >+ >+ >+TextPaM TextEngine::ImpInsertText( const TextSelection& rCurSel, const XubString& rStr ) >+{ >+ UndoActionStart(); >+ >+ TextPaM aPaM; >+ >+ if ( rCurSel.HasRange() ) >+ aPaM = ImpDeleteText( rCurSel ); >+ else >+ aPaM = rCurSel.GetEnd(); >+ >+ XubString aText(convertLineEnd(rStr, LINEEND_LF)); >+ >+ sal_uInt16 nStart = 0; >+ while ( nStart < aText.Len() ) >+ { >+ sal_uInt16 nEnd = aText.Search( LINE_SEP, nStart ); >+ if ( nEnd == STRING_NOTFOUND ) >+ nEnd = aText.Len(); // nicht dereferenzieren! >+ >+ // Start == End => Leerzeile >+ if ( nEnd > nStart ) >+ { >+ sal_uLong nL = aPaM.GetIndex(); >+ nL += ( nEnd-nStart ); >+ if ( nL > STRING_MAXLEN ) >+ { >+ sal_uInt16 nDiff = (sal_uInt16) (nL-STRING_MAXLEN); >+ nEnd = nEnd - nDiff; >+ } >+ >+ XubString aLine( aText, nStart, nEnd-nStart ); >+ if ( IsUndoEnabled() && !IsInUndo() ) >+ InsertUndo( new TextUndoInsertChars( this, aPaM, aLine ) ); >+ >+ TEParaPortion* pPortion = mpTEParaPortions->GetObject( aPaM.GetPara() ); >+ pPortion->MarkInvalid( aPaM.GetIndex(), aLine.Len() ); >+ if ( aLine.Search( '\t' ) != STRING_NOTFOUND ) >+ pPortion->SetNotSimpleInvalid(); >+ >+ aPaM = mpDoc->InsertText( aPaM, aLine ); >+ ImpCharsInserted( aPaM.GetPara(), aPaM.GetIndex()-aLine.Len(), aLine.Len() ); >+ >+ } >+ if ( nEnd < aText.Len() ) >+ aPaM = ImpInsertParaBreak( aPaM ); >+ >+ nStart = nEnd+1; >+ >+ if ( nStart < nEnd ) // #108611# overflow >+ break; >+ } >+ >+ UndoActionEnd(); >+ >+ TextModified(); >+ return aPaM; >+} >+ >+TextPaM TextEngine::ImpInsertParaBreak( const TextSelection& rCurSel, sal_Bool bKeepEndingAttribs ) >+{ >+ TextPaM aPaM; >+ if ( rCurSel.HasRange() ) >+ aPaM = ImpDeleteText( rCurSel ); >+ else >+ aPaM = rCurSel.GetEnd(); >+ >+ return ImpInsertParaBreak( aPaM, bKeepEndingAttribs ); >+} >+ >+TextPaM TextEngine::ImpInsertParaBreak( const TextPaM& rPaM, sal_Bool bKeepEndingAttribs ) >+{ >+ if ( IsUndoEnabled() && !IsInUndo() ) >+ InsertUndo( new TextUndoSplitPara( this, rPaM.GetPara(), rPaM.GetIndex() ) ); >+ >+ TextNode* pNode = mpDoc->GetNodes().GetObject( rPaM.GetPara() ); >+ sal_Bool bFirstParaContentChanged = rPaM.GetIndex() < pNode->GetText().Len(); >+ >+ TextPaM aPaM( mpDoc->InsertParaBreak( rPaM, bKeepEndingAttribs ) ); >+ >+ TEParaPortion* pPortion = mpTEParaPortions->GetObject( rPaM.GetPara() ); >+ DBG_ASSERT( pPortion, "Blinde Portion in ImpInsertParaBreak" ); >+ pPortion->MarkInvalid( rPaM.GetIndex(), 0 ); >+ >+ TextNode* pNewNode = mpDoc->GetNodes().GetObject( aPaM.GetPara() ); >+ TEParaPortion* pNewPortion = new TEParaPortion( pNewNode ); >+ mpTEParaPortions->Insert( pNewPortion, aPaM.GetPara() ); >+ ImpParagraphInserted( aPaM.GetPara() ); >+ >+ CursorMoved( rPaM.GetPara() ); // falls leeres Attribut entstanden. >+ TextModified(); >+ >+ if ( bFirstParaContentChanged ) >+ Broadcast( TextHint( TEXT_HINT_PARACONTENTCHANGED, rPaM.GetPara() ) ); >+ >+ return aPaM; >+} >+ >+Rectangle TextEngine::PaMtoEditCursor( const TextPaM& rPaM, sal_Bool bSpecial ) >+{ >+ DBG_ASSERT( GetUpdateMode(), "Darf bei Update=sal_False nicht erreicht werden: PaMtoEditCursor" ); >+ >+ Rectangle aEditCursor; >+ long nY = 0; >+ >+ if ( !mbHasMultiLineParas ) >+ { >+ nY = rPaM.GetPara() * mnCharHeight; >+ } >+ else >+ { >+ for ( sal_uLong nPortion = 0; nPortion < rPaM.GetPara(); nPortion++ ) >+ { >+ TEParaPortion* pPortion = mpTEParaPortions->GetObject(nPortion); >+ nY += pPortion->GetLines().size() * mnCharHeight; >+ } >+ } >+ >+ aEditCursor = GetEditCursor( rPaM, bSpecial ); >+ aEditCursor.Top() += nY; >+ aEditCursor.Bottom() += nY; >+ return aEditCursor; >+} >+ >+Rectangle TextEngine::GetEditCursor( const TextPaM& rPaM, sal_Bool bSpecial, sal_Bool bPreferPortionStart ) >+{ >+ if ( !IsFormatted() && !IsFormatting() ) >+ FormatAndUpdate(); >+ >+ TEParaPortion* pPortion = mpTEParaPortions->GetObject( rPaM.GetPara() ); >+ //TextNode* pNode = mpDoc->GetNodes().GetObject( rPaM.GetPara() ); >+ >+ /* >+ bSpecial: 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.... >+ bSpecial: If behind the last character of a made up line, stay at the >+ end of the line, not at the start of the next line. >+ Purpose: - really END = > behind the last character >+ - to selection... >+ >+ */ >+ >+ long nY = 0; >+ sal_uInt16 nCurIndex = 0; >+ TextLine* pLine = 0; >+ for ( sal_uInt16 nLine = 0; nLine < pPortion->GetLines().size(); nLine++ ) >+ { >+ TextLine* pTmpLine = pPortion->GetLines()[ nLine ]; >+ if ( ( pTmpLine->GetStart() == rPaM.GetIndex() ) || ( pTmpLine->IsIn( rPaM.GetIndex(), bSpecial ) ) ) >+ { >+ pLine = pTmpLine; >+ break; >+ } >+ >+ nCurIndex = nCurIndex + pTmpLine->GetLen(); >+ nY += mnCharHeight; >+ } >+ if ( !pLine ) >+ { >+ // Cursor am Ende des Absatzes. >+ DBG_ASSERT( rPaM.GetIndex() == nCurIndex, "Index voll daneben in GetEditCursor!" ); >+ >+ pLine = pPortion->GetLines().back(); >+ nY -= mnCharHeight; >+ nCurIndex = nCurIndex - pLine->GetLen(); >+ } >+ >+ Rectangle aEditCursor; >+ >+ aEditCursor.Top() = nY; >+ nY += mnCharHeight; >+ aEditCursor.Bottom() = nY-1; >+ >+ // innerhalb der Zeile suchen.... >+ long nX = ImpGetXPos( rPaM.GetPara(), pLine, rPaM.GetIndex(), bPreferPortionStart ); >+ aEditCursor.Left() = aEditCursor.Right() = nX; >+ return aEditCursor; >+} >+ >+long TextEngine::ImpGetXPos( sal_uLong nPara, TextLine* pLine, sal_uInt16 nIndex, sal_Bool bPreferPortionStart ) >+{ >+ DBG_ASSERT( ( nIndex >= pLine->GetStart() ) && ( nIndex <= pLine->GetEnd() ) , "ImpGetXPos muss richtig gerufen werden!" ); >+ >+ sal_Bool bDoPreferPortionStart = bPreferPortionStart; >+ // Assure that the portion belongs to this line: >+ if ( nIndex == pLine->GetStart() ) >+ bDoPreferPortionStart = sal_True; >+ else if ( nIndex == pLine->GetEnd() ) >+ bDoPreferPortionStart = sal_False; >+ >+ TEParaPortion* pParaPortion = mpTEParaPortions->GetObject( nPara ); >+ >+ sal_uInt16 nTextPortionStart = 0; >+ size_t nTextPortion = pParaPortion->GetTextPortions().FindPortion( nIndex, nTextPortionStart, bDoPreferPortionStart ); >+ >+ DBG_ASSERT( ( nTextPortion >= pLine->GetStartPortion() ) && ( nTextPortion <= pLine->GetEndPortion() ), "GetXPos: Portion not in current line! " ); >+ >+ TETextPortion* pPortion = pParaPortion->GetTextPortions()[ nTextPortion ]; >+ >+ long nX = ImpGetPortionXOffset( nPara, pLine, nTextPortion ); >+ >+ long nPortionTextWidth = pPortion->GetWidth(); >+ >+ if ( nTextPortionStart != nIndex ) >+ { >+ // Search within portion... >+ if ( nIndex == ( nTextPortionStart + pPortion->GetLen() ) ) >+ { >+ // End of Portion >+ if ( ( pPortion->GetKind() == PORTIONKIND_TAB ) || >+ ( !IsRightToLeft() && !pPortion->IsRightToLeft() ) || >+ ( IsRightToLeft() && pPortion->IsRightToLeft() ) ) >+ { >+ nX += nPortionTextWidth; >+ if ( ( pPortion->GetKind() == PORTIONKIND_TAB ) && ( (nTextPortion+1) < pParaPortion->GetTextPortions().size() ) ) >+ { >+ TETextPortion* pNextPortion = pParaPortion->GetTextPortions()[ nTextPortion+1 ]; >+ if ( ( pNextPortion->GetKind() != PORTIONKIND_TAB ) && ( >+ ( !IsRightToLeft() && pNextPortion->IsRightToLeft() ) || >+ ( IsRightToLeft() && !pNextPortion->IsRightToLeft() ) ) ) >+ { >+// nX += pNextPortion->GetWidth(); >+ // End of the tab portion, use start of next for cursor pos >+ DBG_ASSERT( !bPreferPortionStart, "ImpGetXPos - How can we this tab portion here???" ); >+ nX = ImpGetXPos( nPara, pLine, nIndex, sal_True ); >+ } >+ >+ } >+ } >+ } >+ else if ( pPortion->GetKind() == PORTIONKIND_TEXT ) >+ { >+ DBG_ASSERT( nIndex != pLine->GetStart(), "Strange behavior in new ImpGetXPos()" ); >+ >+ long nPosInPortion = (long)CalcTextWidth( nPara, nTextPortionStart, nIndex-nTextPortionStart ); >+ >+ if ( ( !IsRightToLeft() && !pPortion->IsRightToLeft() ) || >+ ( IsRightToLeft() && pPortion->IsRightToLeft() ) ) >+ { >+ nX += nPosInPortion; >+ } >+ else >+ { >+ nX += nPortionTextWidth - nPosInPortion; >+ } >+ } >+ } >+ else // if ( nIndex == pLine->GetStart() ) >+ { >+ if ( ( pPortion->GetKind() != PORTIONKIND_TAB ) && >+ ( ( !IsRightToLeft() && pPortion->IsRightToLeft() ) || >+ ( IsRightToLeft() && !pPortion->IsRightToLeft() ) ) ) >+ { >+ nX += nPortionTextWidth; >+ } >+ } >+ >+ return nX; >+} >+ >+const TextAttrib* TextEngine::FindAttrib( const TextPaM& rPaM, sal_uInt16 nWhich ) const >+{ >+ const TextAttrib* pAttr = NULL; >+ const TextCharAttrib* pCharAttr = FindCharAttrib( rPaM, nWhich ); >+ if ( pCharAttr ) >+ pAttr = &pCharAttr->GetAttr(); >+ return pAttr; >+} >+ >+const TextCharAttrib* TextEngine::FindCharAttrib( const TextPaM& rPaM, sal_uInt16 nWhich ) const >+{ >+ const TextCharAttrib* pAttr = NULL; >+ TextNode* pNode = mpDoc->GetNodes().GetObject( rPaM.GetPara() ); >+ if ( pNode && ( rPaM.GetIndex() < pNode->GetText().Len() ) ) >+ pAttr = pNode->GetCharAttribs().FindAttrib( nWhich, rPaM.GetIndex() ); >+ return pAttr; >+} >+ >+sal_Bool TextEngine::HasAttrib( sal_uInt16 nWhich ) const >+{ >+ sal_Bool bAttr = sal_False; >+ for ( sal_uLong n = mpDoc->GetNodes().Count(); --n && !bAttr; ) >+ { >+ TextNode* pNode = mpDoc->GetNodes().GetObject( n ); >+ bAttr = pNode->GetCharAttribs().HasAttrib( nWhich ); >+ } >+ return bAttr; >+} >+ >+TextPaM TextEngine::GetPaM( const Point& rDocPos, sal_Bool bSmart ) >+{ >+ DBG_ASSERT( GetUpdateMode(), "Darf bei Update=sal_False nicht erreicht werden: GetPaM" ); >+ >+ long nY = 0; >+ for ( sal_uLong nPortion = 0; nPortion < mpTEParaPortions->Count(); nPortion++ ) >+ { >+ TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPortion ); >+ long nTmpHeight = pPortion->GetLines().size() * mnCharHeight; >+ nY += nTmpHeight; >+ if ( nY > rDocPos.Y() ) >+ { >+ nY -= nTmpHeight; >+ Point aPosInPara( rDocPos ); >+ aPosInPara.Y() -= nY; >+ >+ TextPaM aPaM( nPortion, 0 ); >+ aPaM.GetIndex() = ImpFindIndex( nPortion, aPosInPara, bSmart ); >+ return aPaM; >+ } >+ } >+ >+ // Nicht gefunden - Dann den letzten sichtbare... >+ sal_uLong nLastNode = mpDoc->GetNodes().Count() - 1; >+ TextNode* pLast = mpDoc->GetNodes().GetObject( nLastNode ); >+ return TextPaM( nLastNode, pLast->GetText().Len() ); >+} >+ >+sal_uInt16 TextEngine::ImpFindIndex( sal_uLong nPortion, const Point& rPosInPara, sal_Bool bSmart ) >+{ >+ DBG_ASSERT( IsFormatted(), "GetPaM: Nicht formatiert" ); >+ TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPortion ); >+ >+ sal_uInt16 nCurIndex = 0; >+ >+ long nY = 0; >+ TextLine* pLine = 0; >+ sal_uInt16 nLine; >+ for ( nLine = 0; nLine < pPortion->GetLines().size(); nLine++ ) >+ { >+ TextLine* pTmpLine = pPortion->GetLines()[ nLine ]; >+ nY += mnCharHeight; >+ if ( nY > rPosInPara.Y() ) // das war 'se >+ { >+ pLine = pTmpLine; >+ break; // richtige Y-Position intressiert nicht >+ } >+ } >+ DBG_ASSERT( pLine, "ImpFindIndex: pLine ?" ); >+ >+ nCurIndex = GetCharPos( nPortion, nLine, rPosInPara.X(), bSmart ); >+ >+ if ( nCurIndex && ( nCurIndex == pLine->GetEnd() ) && >+ ( pLine != pPortion->GetLines().back() ) ) >+ { >+ uno::Reference < i18n::XBreakIterator > xBI = GetBreakIterator(); >+ sal_Int32 nCount = 1; >+ nCurIndex = (sal_uInt16)xBI->previousCharacters( pPortion->GetNode()->GetText(), nCurIndex, GetLocale(), i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount ); >+ } >+ return nCurIndex; >+} >+ >+sal_uInt16 TextEngine::GetCharPos( sal_uLong nPortion, sal_uInt16 nLine, long nXPos, sal_Bool ) >+{ >+ >+ TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPortion ); >+ TextLine* pLine = pPortion->GetLines()[ nLine ]; >+ >+ sal_uInt16 nCurIndex = pLine->GetStart(); >+ >+ long nTmpX = pLine->GetStartX(); >+ if ( nXPos <= nTmpX ) >+ return nCurIndex; >+ >+ for ( sal_uInt16 i = pLine->GetStartPortion(); i <= pLine->GetEndPortion(); i++ ) >+ { >+ TETextPortion* pTextPortion = pPortion->GetTextPortions()[ i ]; >+ nTmpX += pTextPortion->GetWidth(); >+ >+ if ( nTmpX > nXPos ) >+ { >+ if( pTextPortion->GetLen() > 1 ) >+ { >+ nTmpX -= pTextPortion->GetWidth(); // vor die Portion stellen >+ // Optimieren: Kein GetTextBreak, wenn feste Fontbreite... >+ Font aFont; >+ SeekCursor( nPortion, nCurIndex+1, aFont, NULL ); >+ mpRefDev->SetFont( aFont); >+ long nPosInPortion = nXPos-nTmpX; >+ if ( IsRightToLeft() != pTextPortion->IsRightToLeft() ) >+ nPosInPortion = pTextPortion->GetWidth() - nPosInPortion; >+ nCurIndex = mpRefDev->GetTextBreak( pPortion->GetNode()->GetText(), nPosInPortion, nCurIndex ); >+ // MT: GetTextBreak should assure that we are not withing a CTL cell... >+ } >+ return nCurIndex; >+ } >+ nCurIndex = nCurIndex + pTextPortion->GetLen(); >+ } >+ return nCurIndex; >+} >+ >+ >+sal_uLong TextEngine::GetTextHeight() const >+{ >+ DBG_ASSERT( GetUpdateMode(), "Sollte bei Update=sal_False nicht verwendet werden: GetTextHeight" ); >+ >+ if ( !IsFormatted() && !IsFormatting() ) >+ ((TextEngine*)this)->FormatAndUpdate(); >+ >+ return mnCurTextHeight; >+} >+ >+sal_uLong TextEngine::GetTextHeight( sal_uLong nParagraph ) const >+{ >+ DBG_ASSERT( GetUpdateMode(), "Sollte bei Update=sal_False nicht verwendet werden: GetTextHeight" ); >+ >+ if ( !IsFormatted() && !IsFormatting() ) >+ ((TextEngine*)this)->FormatAndUpdate(); >+ >+ return CalcParaHeight( nParagraph ); >+} >+ >+sal_uLong TextEngine::CalcTextWidth( sal_uLong nPara ) >+{ >+ sal_uLong nParaWidth = 0; >+ TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPara ); >+ for ( sal_uInt16 nLine = pPortion->GetLines().size(); nLine; ) >+ { >+ sal_uLong nLineWidth = 0; >+ TextLine* pLine = pPortion->GetLines()[ --nLine ]; >+ for ( sal_uInt16 nTP = pLine->GetStartPortion(); nTP <= pLine->GetEndPortion(); nTP++ ) >+ { >+ TETextPortion* pTextPortion = pPortion->GetTextPortions()[ nTP ]; >+ nLineWidth += pTextPortion->GetWidth(); >+ } >+ if ( nLineWidth > nParaWidth ) >+ nParaWidth = nLineWidth; >+ } >+ return nParaWidth; >+} >+ >+sal_uLong TextEngine::CalcTextWidth() >+{ >+ if ( !IsFormatted() && !IsFormatting() ) >+ FormatAndUpdate(); >+ >+ if ( mnCurTextWidth == 0xFFFFFFFF ) >+ { >+ mnCurTextWidth = 0; >+ for ( sal_uLong nPara = mpTEParaPortions->Count(); nPara; ) >+ { >+ sal_uLong nParaWidth = CalcTextWidth( --nPara ); >+ if ( nParaWidth > mnCurTextWidth ) >+ mnCurTextWidth = nParaWidth; >+ } >+ } >+ return mnCurTextWidth+1;// Ein breiter, da in CreateLines bei >= umgebrochen wird. >+} >+ >+sal_uLong TextEngine::CalcTextHeight() >+{ >+ DBG_ASSERT( GetUpdateMode(), "Sollte bei Update=sal_False nicht verwendet werden: CalcTextHeight" ); >+ >+ sal_uLong nY = 0; >+ for ( sal_uLong nPortion = mpTEParaPortions->Count(); nPortion; ) >+ nY += CalcParaHeight( --nPortion ); >+ return nY; >+} >+ >+sal_uLong TextEngine::CalcTextWidth( sal_uLong nPara, sal_uInt16 nPortionStart, sal_uInt16 nLen, const Font* pFont ) >+{ >+ // Innerhalb des Textes darf es keinen Portionwechsel (Attribut/Tab) geben! >+ DBG_ASSERT( mpDoc->GetNodes().GetObject( nPara )->GetText().Search( '\t', nPortionStart ) >= (nPortionStart+nLen), "CalcTextWidth: Tab!" ); >+ >+ sal_uLong nWidth; >+ if ( mnFixCharWidth100 ) >+ { >+ nWidth = (sal_uLong)nLen*mnFixCharWidth100/100; >+ } >+ else >+ { >+ if ( pFont ) >+ { >+ if ( !mpRefDev->GetFont().IsSameInstance( *pFont ) ) >+ mpRefDev->SetFont( *pFont ); >+ } >+ else >+ { >+ Font aFont; >+ SeekCursor( nPara, nPortionStart+1, aFont, NULL ); >+ mpRefDev->SetFont( aFont ); >+ } >+ TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >+ nWidth = (sal_uLong)mpRefDev->GetTextWidth( pNode->GetText(), nPortionStart, nLen ); >+ >+ } >+ return nWidth; >+} >+ >+ >+sal_uInt16 TextEngine::GetLineCount( sal_uLong nParagraph ) const >+{ >+ DBG_ASSERT( nParagraph < mpTEParaPortions->Count(), "GetLineCount: Out of range" ); >+ >+ TEParaPortion* pPPortion = mpTEParaPortions->GetObject( nParagraph ); >+ if ( pPPortion ) >+ return pPPortion->GetLines().size(); >+ >+ return 0xFFFF; >+} >+ >+sal_uInt16 TextEngine::GetLineLen( sal_uLong nParagraph, sal_uInt16 nLine ) const >+{ >+ DBG_ASSERT( nParagraph < mpTEParaPortions->Count(), "GetLineCount: Out of range" ); >+ >+ TEParaPortion* pPPortion = mpTEParaPortions->GetObject( nParagraph ); >+ if ( pPPortion && ( nLine < pPPortion->GetLines().size() ) ) >+ { >+ TextLine* pLine = pPPortion->GetLines()[ nLine ]; >+ return pLine->GetLen(); >+ } >+ >+ return 0xFFFF; >+} >+ >+sal_uLong TextEngine::CalcParaHeight( sal_uLong nParagraph ) const >+{ >+ sal_uLong nHeight = 0; >+ >+ TEParaPortion* pPPortion = mpTEParaPortions->GetObject( nParagraph ); >+ DBG_ASSERT( pPPortion, "Absatz nicht gefunden: GetParaHeight" ); >+ if ( pPPortion ) >+ nHeight = pPPortion->GetLines().size() * mnCharHeight; >+ >+ return nHeight; >+} >+ >+void TextEngine::UpdateSelections() >+{ >+} >+ >+Range TextEngine::GetInvalidYOffsets( sal_uLong nPortion ) >+{ >+ TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPortion ); >+ sal_uInt16 nLines = pTEParaPortion->GetLines().size(); >+ sal_uInt16 nLastInvalid, nFirstInvalid = 0; >+ sal_uInt16 nLine; >+ for ( nLine = 0; nLine < nLines; nLine++ ) >+ { >+ TextLine* pL = pTEParaPortion->GetLines()[ nLine ]; >+ if ( pL->IsInvalid() ) >+ { >+ nFirstInvalid = nLine; >+ break; >+ } >+ } >+ >+ for ( nLastInvalid = nFirstInvalid; nLastInvalid < nLines; nLastInvalid++ ) >+ { >+ TextLine* pL = pTEParaPortion->GetLines()[ nLine ]; >+ if ( pL->IsValid() ) >+ break; >+ } >+ >+ if ( nLastInvalid >= nLines ) >+ nLastInvalid = nLines-1; >+ >+ return Range( nFirstInvalid*mnCharHeight, ((nLastInvalid+1)*mnCharHeight)-1 ); >+} >+ >+sal_uLong TextEngine::GetParagraphCount() const >+{ >+ return mpDoc->GetNodes().Count(); >+} >+ >+void TextEngine::EnableUndo( sal_Bool bEnable ) >+{ >+ // Beim Umschalten des Modus Liste loeschen: >+ if ( bEnable != IsUndoEnabled() ) >+ ResetUndo(); >+ >+ mbUndoEnabled = bEnable; >+} >+ >+::svl::IUndoManager& TextEngine::GetUndoManager() >+{ >+ if ( !mpUndoManager ) >+ mpUndoManager = new TextUndoManager( this ); >+ return *mpUndoManager; >+} >+ >+void TextEngine::UndoActionStart( sal_uInt16 nId ) >+{ >+ if ( IsUndoEnabled() && !IsInUndo() ) >+ { >+ String aComment; >+ // ... >+ GetUndoManager().EnterListAction( aComment, XubString(), nId ); >+ } >+} >+ >+void TextEngine::UndoActionEnd() >+{ >+ if ( IsUndoEnabled() && !IsInUndo() ) >+ GetUndoManager().LeaveListAction(); >+} >+ >+void TextEngine::InsertUndo( TextUndo* pUndo, sal_Bool bTryMerge ) >+{ >+ DBG_ASSERT( !IsInUndo(), "InsertUndo im Undomodus!" ); >+ GetUndoManager().AddUndoAction( pUndo, bTryMerge ); >+} >+ >+void TextEngine::ResetUndo() >+{ >+ if ( mpUndoManager ) >+ mpUndoManager->Clear(); >+} >+ >+void TextEngine::InsertContent( TextNode* pNode, sal_uLong nPara ) >+{ >+ DBG_ASSERT( pNode, "NULL-Pointer in InsertContent! " ); >+ DBG_ASSERT( IsInUndo(), "InsertContent nur fuer Undo()!" ); >+ TEParaPortion* pNew = new TEParaPortion( pNode ); >+ mpTEParaPortions->Insert( pNew, nPara ); >+ mpDoc->GetNodes().Insert( pNode, nPara ); >+ ImpParagraphInserted( nPara ); >+} >+ >+TextPaM TextEngine::SplitContent( sal_uLong nNode, sal_uInt16 nSepPos ) >+{ >+ #ifdef DBG_UTIL >+ TextNode* pNode = mpDoc->GetNodes().GetObject( nNode ); >+ DBG_ASSERT( pNode, "Ungueltiger Node in SplitContent" ); >+ DBG_ASSERT( IsInUndo(), "SplitContent nur fuer Undo()!" ); >+ DBG_ASSERT( nSepPos <= pNode->GetText().Len(), "Index im Wald: SplitContent" ); >+ #endif >+ TextPaM aPaM( nNode, nSepPos ); >+ return ImpInsertParaBreak( aPaM ); >+} >+ >+TextPaM TextEngine::ConnectContents( sal_uLong nLeftNode ) >+{ >+ DBG_ASSERT( IsInUndo(), "ConnectContent nur fuer Undo()!" ); >+ return ImpConnectParagraphs( nLeftNode, nLeftNode+1 ); >+} >+ >+void TextEngine::SeekCursor( sal_uLong nPara, sal_uInt16 nPos, Font& rFont, OutputDevice* pOutDev ) >+{ >+ rFont = maFont; >+ if ( pOutDev ) >+ pOutDev->SetTextColor( maTextColor ); >+ >+ TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >+ sal_uInt16 nAttribs = pNode->GetCharAttribs().Count(); >+ for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ ) >+ { >+ TextCharAttrib* pAttrib = pNode->GetCharAttribs().GetAttrib( nAttr ); >+ if ( pAttrib->GetStart() > nPos ) >+ break; >+ >+ // 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->GetStart() < nPos ) && ( pAttrib->GetEnd() >= nPos ) ) >+ || !pNode->GetText().Len() ) >+ { >+ if ( pAttrib->Which() != TEXTATTR_FONTCOLOR ) >+ { >+ pAttrib->GetAttr().SetFont(rFont); >+ } >+ else >+ { >+ if ( pOutDev ) >+ pOutDev->SetTextColor( ((TextAttribFontColor&)pAttrib->GetAttr()).GetColor() ); >+ } >+ } >+ } >+ >+ if ( mpIMEInfos && mpIMEInfos->pAttribs && ( mpIMEInfos->aPos.GetPara() == nPara ) && >+ ( 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 ); >+ 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( sal_False ); >+ } >+ else if ( nAttr & EXTTEXTINPUT_ATTR_GRAYWAVELINE ) >+ { >+ rFont.SetUnderline( UNDERLINE_WAVE ); >+// if( pOut ) >+// pOut->SetTextLineColor( Color( COL_LIGHTGRAY ) ); >+ } >+ } >+} >+ >+void TextEngine::FormatAndUpdate( TextView* pCurView ) >+{ >+ if ( mbDowning ) >+ return ; >+ >+ if ( IsInUndo() ) >+ IdleFormatAndUpdate( pCurView ); >+ else >+ { >+ FormatDoc(); >+ UpdateViews( pCurView ); >+ } >+} >+ >+ >+void TextEngine::IdleFormatAndUpdate( TextView* pCurView, sal_uInt16 nMaxTimerRestarts ) >+{ >+ mpIdleFormatter->DoIdleFormat( pCurView, nMaxTimerRestarts ); >+} >+ >+void TextEngine::TextModified() >+{ >+ mbFormatted = sal_False; >+ mbModified = sal_True; >+} >+ >+void TextEngine::UpdateViews( TextView* pCurView ) >+{ >+ if ( !GetUpdateMode() || IsFormatting() || maInvalidRec.IsEmpty() ) >+ return; >+ >+ DBG_ASSERT( IsFormatted(), "UpdateViews: Doc nicht formatiert!" ); >+ >+ for ( sal_uInt16 nView = 0; nView < mpViews->size(); nView++ ) >+ { >+ TextView* pView = (*mpViews)[ nView ]; >+ pView->HideCursor(); >+ >+ Rectangle aClipRec( maInvalidRec ); >+ Size aOutSz = pView->GetWindow()->GetOutputSizePixel(); >+ Rectangle aVisArea( pView->GetStartDocPos(), aOutSz ); >+ aClipRec.Intersection( aVisArea ); >+ if ( !aClipRec.IsEmpty() ) >+ { >+ // in Fensterkoordinaten umwandeln.... >+ Point aNewPos = pView->GetWindowPos( aClipRec.TopLeft() ); >+ if ( IsRightToLeft() ) >+ aNewPos.X() -= aOutSz.Width() - 1; >+ aClipRec.SetPos( aNewPos ); >+ >+ if ( pView == pCurView ) >+ pView->ImpPaint( aClipRec, !pView->GetWindow()->IsPaintTransparent() ); >+ else >+ pView->GetWindow()->Invalidate( aClipRec ); >+ } >+ } >+ >+ if ( pCurView ) >+ { >+ pCurView->ShowCursor( pCurView->IsAutoScroll() ); >+ } >+ >+ maInvalidRec = Rectangle(); >+} >+ >+IMPL_LINK_NOARG(TextEngine, IdleFormatHdl) >+{ >+ FormatAndUpdate( mpIdleFormatter->GetView() ); >+ return 0; >+} >+ >+void TextEngine::CheckIdleFormatter() >+{ >+ mpIdleFormatter->ForceTimeout(); >+} >+ >+void TextEngine::FormatFullDoc() >+{ >+ for ( sal_uLong nPortion = 0; nPortion < mpTEParaPortions->Count(); nPortion++ ) >+ { >+ TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPortion ); sal_uInt16 nLen = pTEParaPortion->GetNode()->GetText().Len(); >+ pTEParaPortion->MarkSelectionInvalid( 0, nLen ); >+ } >+ mbFormatted = sal_False; >+ FormatDoc(); >+} >+ >+void TextEngine::FormatDoc() >+{ >+ if ( IsFormatted() || !GetUpdateMode() || IsFormatting() ) >+ return; >+ >+ mbIsFormatting = sal_True; >+ mbHasMultiLineParas = sal_False; >+ >+ long nY = 0; >+ sal_Bool bGrow = sal_False; >+ >+ maInvalidRec = Rectangle(); // leermachen >+ for ( sal_uLong nPara = 0; nPara < mpTEParaPortions->Count(); nPara++ ) >+ { >+ TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >+ if ( pTEParaPortion->IsInvalid() ) >+ { >+ sal_uLong nOldParaWidth = 0xFFFFFFFF; >+ if ( mnCurTextWidth != 0xFFFFFFFF ) >+ nOldParaWidth = CalcTextWidth( nPara ); >+ >+ ImpFormattingParagraph( nPara ); >+ >+ if ( CreateLines( nPara ) ) >+ bGrow = sal_True; >+ >+ // InvalidRec nur einmal setzen... >+ if ( maInvalidRec.IsEmpty() ) >+ { >+ // Bei Paperwidth 0 (AutoPageSize) bleibt es sonst Empty()... >+ long nWidth = (long)mnMaxTextWidth; >+ if ( !nWidth ) >+ nWidth = 0x7FFFFFFF; >+ Range aInvRange( GetInvalidYOffsets( nPara ) ); >+ maInvalidRec = Rectangle( Point( 0, nY+aInvRange.Min() ), >+ Size( nWidth, aInvRange.Len() ) ); >+ } >+ else >+ { >+ maInvalidRec.Bottom() = nY + CalcParaHeight( nPara ); >+ } >+ >+ if ( mnCurTextWidth != 0xFFFFFFFF ) >+ { >+ sal_uLong nNewParaWidth = CalcTextWidth( nPara ); >+ if ( nNewParaWidth >= mnCurTextWidth ) >+ mnCurTextWidth = nNewParaWidth; >+ else if ( ( nOldParaWidth != 0xFFFFFFFF ) && ( nOldParaWidth >= mnCurTextWidth ) ) >+ mnCurTextWidth = 0xFFFFFFFF; >+ } >+ } >+ else if ( bGrow ) >+ { >+ maInvalidRec.Bottom() = nY + CalcParaHeight( nPara ); >+ } >+ nY += CalcParaHeight( nPara ); >+ if ( !mbHasMultiLineParas && pTEParaPortion->GetLines().size() > 1 ) >+ mbHasMultiLineParas = sal_True; >+ } >+ >+ if ( !maInvalidRec.IsEmpty() ) >+ { >+ sal_uLong nNewHeight = CalcTextHeight(); >+ long nDiff = nNewHeight - mnCurTextHeight; >+ if ( nNewHeight < mnCurTextHeight ) >+ { >+ maInvalidRec.Bottom() = (long)Max( nNewHeight, mnCurTextHeight ); >+ if ( maInvalidRec.IsEmpty() ) >+ { >+ maInvalidRec.Top() = 0; >+ // Left und Right werden nicht ausgewertet, aber wegen IsEmpty gesetzt. >+ maInvalidRec.Left() = 0; >+ maInvalidRec.Right() = mnMaxTextWidth; >+ } >+ } >+ >+ mnCurTextHeight = nNewHeight; >+ if ( nDiff ) >+ { >+ mbFormatted = sal_True; >+ ImpTextHeightChanged(); >+ } >+ } >+ >+ mbIsFormatting = sal_False; >+ mbFormatted = sal_True; >+ >+ ImpTextFormatted(); >+} >+ >+void TextEngine::CreateAndInsertEmptyLine( sal_uLong nPara ) >+{ >+ TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >+ TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >+ >+ TextLine* pTmpLine = new TextLine; >+ pTmpLine->SetStart( pNode->GetText().Len() ); >+ pTmpLine->SetEnd( pTmpLine->GetStart() ); >+ pTEParaPortion->GetLines().push_back( pTmpLine ); >+ >+ if ( ImpGetAlign() == TXTALIGN_CENTER ) >+ pTmpLine->SetStartX( (short)(mnMaxTextWidth / 2) ); >+ else if ( ImpGetAlign() == TXTALIGN_RIGHT ) >+ pTmpLine->SetStartX( (short)mnMaxTextWidth ); >+ else >+ pTmpLine->SetStartX( mpDoc->GetLeftMargin() ); >+ >+ sal_Bool bLineBreak = pNode->GetText().Len() ? sal_True : sal_False; >+ >+ TETextPortion* pDummyPortion = new TETextPortion( 0 ); >+ pDummyPortion->GetWidth() = 0; >+ pTEParaPortion->GetTextPortions().push_back( pDummyPortion ); >+ >+ if ( bLineBreak == sal_True ) >+ { >+ // -2: The new one is already inserted. >+ OSL_ENSURE( >+ pTEParaPortion->GetLines()[pTEParaPortion->GetLines().size()-2], >+ "Soft Break, no Line?!"); >+ sal_uInt16 nPos = (sal_uInt16) pTEParaPortion->GetTextPortions().size() - 1 ; >+ pTmpLine->SetStartPortion( nPos ); >+ pTmpLine->SetEndPortion( nPos ); >+ } >+} >+ >+void TextEngine::ImpBreakLine( sal_uLong nPara, TextLine* pLine, TETextPortion*, sal_uInt16 nPortionStart, long nRemainingWidth ) >+{ >+ TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >+ >+ // Font sollte noch eingestellt sein. >+ sal_uInt16 nMaxBreakPos = mpRefDev->GetTextBreak( pNode->GetText(), nRemainingWidth, nPortionStart ); >+ >+ DBG_ASSERT( nMaxBreakPos < pNode->GetText().Len(), "Break?!" ); >+ >+ if ( nMaxBreakPos == STRING_LEN ) // GetTextBreak() ist anderer Auffassung als GetTextSize() >+ nMaxBreakPos = pNode->GetText().Len() - 1; >+ >+ uno::Reference < i18n::XBreakIterator > xBI = GetBreakIterator(); >+ i18n::LineBreakHyphenationOptions aHyphOptions( NULL, uno::Sequence< beans::PropertyValue >(), 1 ); >+ >+ i18n::LineBreakUserOptions aUserOptions; >+ aUserOptions.forbiddenBeginCharacters = ImpGetLocaleDataWrapper()->getForbiddenCharacters().beginLine; >+ aUserOptions.forbiddenEndCharacters = ImpGetLocaleDataWrapper()->getForbiddenCharacters().endLine; >+ aUserOptions.applyForbiddenRules = sal_True; >+ aUserOptions.allowPunctuationOutsideMargin = sal_False; >+ aUserOptions.allowHyphenateEnglish = sal_False; >+ >+ static const com::sun::star::lang::Locale aDefLocale; >+ i18n::LineBreakResults aLBR = xBI->getLineBreak( pNode->GetText(), nMaxBreakPos, aDefLocale, pLine->GetStart(), aHyphOptions, aUserOptions ); >+ sal_uInt16 nBreakPos = (sal_uInt16)aLBR.breakIndex; >+ if ( nBreakPos <= pLine->GetStart() ) >+ { >+ nBreakPos = nMaxBreakPos; >+ if ( nBreakPos <= pLine->GetStart() ) >+ nBreakPos = pLine->GetStart() + 1; // Sonst Endlosschleife! >+ } >+ >+ >+ // die angeknackste Portion ist die End-Portion >+ pLine->SetEnd( nBreakPos ); >+ sal_uInt16 nEndPortion = SplitTextPortion( nPara, nBreakPos ); >+ >+ sal_Bool bBlankSeparator = ( ( nBreakPos >= pLine->GetStart() ) && >+ ( pNode->GetText().GetChar( nBreakPos ) == ' ' ) ) ? sal_True : sal_False; >+ if ( bBlankSeparator ) >+ { >+ // Blanks am Zeilenende generell unterdruecken... >+ TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >+ TETextPortion* pTP = pTEParaPortion->GetTextPortions()[ nEndPortion ]; >+ DBG_ASSERT( nBreakPos > pLine->GetStart(), "SplitTextPortion am Anfang der Zeile?" ); >+ pTP->GetWidth() = (long)CalcTextWidth( nPara, nBreakPos-pTP->GetLen(), pTP->GetLen()-1 ); >+ } >+ pLine->SetEndPortion( nEndPortion ); >+} >+ >+sal_uInt16 TextEngine::SplitTextPortion( sal_uLong nPara, sal_uInt16 nPos ) >+{ >+ >+ // 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; >+ TETextPortion* pTextPortion = 0; >+ TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >+ sal_uInt16 nPortions = pTEParaPortion->GetTextPortions().size(); >+ for ( nSplitPortion = 0; nSplitPortion < nPortions; nSplitPortion++ ) >+ { >+ TETextPortion* pTP = pTEParaPortion->GetTextPortions()[nSplitPortion]; >+ nTmpPos = nTmpPos + pTP->GetLen(); >+ if ( nTmpPos >= nPos ) >+ { >+ if ( nTmpPos == nPos ) // dann braucht nichts geteilt werden >+ return nSplitPortion; >+ pTextPortion = pTP; >+ break; >+ } >+ } >+ >+ DBG_ASSERT( pTextPortion, "Position ausserhalb des Bereichs!" ); >+ >+ sal_uInt16 nOverlapp = nTmpPos - nPos; >+ pTextPortion->GetLen() = pTextPortion->GetLen() - nOverlapp; >+ TETextPortion* pNewPortion = new TETextPortion( nOverlapp ); >+ pTEParaPortion->GetTextPortions().insert( pTEParaPortion->GetTextPortions().begin() + nSplitPortion + 1, pNewPortion ); >+ pTextPortion->GetWidth() = (long)CalcTextWidth( nPara, nPos-pTextPortion->GetLen(), pTextPortion->GetLen() ); >+ >+ return nSplitPortion; >+} >+ >+void TextEngine::CreateTextPortions( sal_uLong nPara, sal_uInt16 nStartPos ) >+{ >+ TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >+ TextNode* pNode = pTEParaPortion->GetNode(); >+ DBG_ASSERT( pNode->GetText().Len(), "CreateTextPortions sollte nicht fuer leere Absaetze verwendet werden!" ); >+ >+ std::set<sal_uInt16> aPositions; >+ std::set<sal_uInt16>::iterator aPositionsIt; >+ aPositions.insert(0); >+ >+ sal_uInt16 nAttribs = pNode->GetCharAttribs().Count(); >+ for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ ) >+ { >+ TextCharAttrib* pAttrib = pNode->GetCharAttribs().GetAttrib( nAttr ); >+ >+ aPositions.insert( pAttrib->GetStart() ); >+ aPositions.insert( pAttrib->GetEnd() ); >+ } >+ aPositions.insert( pNode->GetText().Len() ); >+ >+ const std::vector<TEWritingDirectionInfo>& rWritingDirections = pTEParaPortion->GetWritingDirectionInfos(); >+ for ( std::vector<TEWritingDirectionInfo>::const_iterator it = rWritingDirections.begin(); it != rWritingDirections.end(); ++it ) >+ aPositions.insert( (*it).nStartPos ); >+ >+ if ( mpIMEInfos && mpIMEInfos->pAttribs && ( mpIMEInfos->aPos.GetPara() == nPara ) ) >+ { >+ 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]; >+ } >+ } >+ } >+ >+ sal_uInt16 nTabPos = pNode->GetText().Search( '\t', 0 ); >+ while ( nTabPos != STRING_NOTFOUND ) >+ { >+ aPositions.insert( nTabPos ); >+ aPositions.insert( nTabPos + 1 ); >+ nTabPos = pNode->GetText().Search( '\t', nTabPos+1 ); >+ } >+ >+ // 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 < pTEParaPortion->GetTextPortions().size(); nP++ ) >+ { >+ TETextPortion* pTmpPortion = pTEParaPortion->GetTextPortions()[nP]; >+ nPortionStart = nPortionStart + pTmpPortion->GetLen(); >+ if ( nPortionStart >= nStartPos ) >+ { >+ nPortionStart = nPortionStart - pTmpPortion->GetLen(); >+ nInvPortion = nP; >+ break; >+ } >+ } >+ OSL_ENSURE(nP < pTEParaPortion->GetTextPortions().size() >+ || pTEParaPortion->GetTextPortions().empty(), >+ "Nothing to delete: CreateTextPortions"); >+ if ( nInvPortion && ( nPortionStart+pTEParaPortion->GetTextPortions()[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 - pTEParaPortion->GetTextPortions()[nInvPortion]->GetLen(); >+ } >+ pTEParaPortion->GetTextPortions().DeleteFromPortion( nInvPortion ); >+ >+ // Eine Portion kann auch durch einen Zeilenumbruch entstanden sein: >+ aPositions.insert( nPortionStart ); >+ >+ aPositionsIt = aPositions.find( nPortionStart ); >+ DBG_ASSERT( aPositionsIt != aPositions.end(), "nPortionStart not found" ); >+ >+ if ( aPositionsIt != aPositions.end() ) >+ { >+ std::set<sal_uInt16>::iterator nextIt = aPositionsIt; >+ for ( ++nextIt; nextIt != aPositions.end(); ++aPositionsIt, ++nextIt ) >+ { >+ TETextPortion* pNew = new TETextPortion( *nextIt - *aPositionsIt ); >+ pTEParaPortion->GetTextPortions().push_back( pNew ); >+ } >+ } >+ OSL_ENSURE(pTEParaPortion->GetTextPortions().size(), "No Portions?!"); >+} >+ >+void TextEngine::RecalcTextPortion( sal_uLong nPara, sal_uInt16 nStartPos, short nNewChars ) >+{ >+ TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >+ OSL_ENSURE(pTEParaPortion->GetTextPortions().size(), "no Portions!"); >+ OSL_ENSURE(nNewChars, "RecalcTextPortion with Diff == 0"); >+ >+ TextNode* const pNode = pTEParaPortion->GetNode(); >+ if ( nNewChars > 0 ) >+ { >+ // Wenn an nStartPos ein Attribut beginnt/endet, oder vor nStartPos >+ // ein Tab steht, faengt eine neue Portion an, >+ // ansonsten wird die Portion an nStartPos erweitert. >+ // Oder wenn ganz vorne ( StartPos 0 ) und dann ein Tab >+ >+ if ( ( pNode->GetCharAttribs().HasBoundingAttrib( nStartPos ) ) || >+ ( nStartPos && ( pNode->GetText().GetChar( nStartPos - 1 ) == '\t' ) ) || >+ ( ( !nStartPos && ( nNewChars < pNode->GetText().Len() ) && pNode->GetText().GetChar( nNewChars ) == '\t' ) ) ) >+ { >+ sal_uInt16 nNewPortionPos = 0; >+ if ( nStartPos ) >+ nNewPortionPos = SplitTextPortion( nPara, nStartPos ) + 1; >+ >+ // Eine leere Portion kann hier stehen, wenn der Absatz leer war, >+ // oder eine Zeile durch einen harten Zeilenumbruch entstanden ist. >+ if ( ( nNewPortionPos < pTEParaPortion->GetTextPortions().size() ) && >+ !pTEParaPortion->GetTextPortions()[nNewPortionPos]->GetLen() ) >+ { >+ // Dann die leere Portion verwenden. >+ sal_uInt16 & r = >+ pTEParaPortion->GetTextPortions()[nNewPortionPos]->GetLen(); >+ r = r + nNewChars; >+ } >+ else >+ { >+ TETextPortion* pNewPortion = new TETextPortion( nNewChars ); >+ pTEParaPortion->GetTextPortions().insert( pTEParaPortion->GetTextPortions().begin() + nNewPortionPos, pNewPortion ); >+ } >+ } >+ else >+ { >+ sal_uInt16 nPortionStart; >+ const sal_uInt16 nTP = pTEParaPortion->GetTextPortions(). >+ FindPortion( nStartPos, nPortionStart ); >+ TETextPortion* const pTP = pTEParaPortion->GetTextPortions()[ nTP ]; >+ DBG_ASSERT( pTP, "RecalcTextPortion: Portion nicht gefunden" ); >+ pTP->GetLen() = pTP->GetLen() + nNewChars; >+ pTP->GetWidth() = (-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 = pTEParaPortion->GetTextPortions().size(); >+ TETextPortion* pTP = 0; >+ for ( nPortion = 0; nPortion < nPortions; nPortion++ ) >+ { >+ pTP = pTEParaPortion->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; >+ pTEParaPortion->GetTextPortions().erase( pTEParaPortion->GetTextPortions().begin() + nPortion ); >+ delete pTP; >+ } >+ else >+ { >+ DBG_ASSERT( pTP->GetLen() > (-nNewChars), "Portion zu klein zum schrumpfen!" ); >+ pTP->GetLen() = pTP->GetLen() + nNewChars; >+ } >+ OSL_ENSURE( pTEParaPortion->GetTextPortions().size(), >+ "RecalcTextPortions: none are left!" ); >+ } >+} >+ >+void TextEngine::ImpPaint( OutputDevice* pOutDev, const Point& rStartPos, Rectangle const* pPaintArea, TextSelection const* pPaintRange, TextSelection const* pSelection ) >+{ >+ if ( !GetUpdateMode() ) >+ return; >+ >+ if ( !IsFormatted() ) >+ FormatDoc(); >+ >+ bool bTransparent = false; >+ Window* pOutWin = dynamic_cast<Window*>(pOutDev); >+ bTransparent = (pOutWin && pOutWin->IsPaintTransparent()); >+ >+ long nY = rStartPos.Y(); >+ >+ TextPaM const* pSelStart = 0; >+ TextPaM const* pSelEnd = 0; >+ if ( pSelection && pSelection->HasRange() ) >+ { >+ sal_Bool bInvers = pSelection->GetEnd() < pSelection->GetStart(); >+ pSelStart = !bInvers ? &pSelection->GetStart() : &pSelection->GetEnd(); >+ pSelEnd = bInvers ? &pSelection->GetStart() : &pSelection->GetEnd(); >+ } >+ DBG_ASSERT( !pPaintRange || ( pPaintRange->GetStart() < pPaintRange->GetEnd() ), "ImpPaint: Paint-Range?!" ); >+ >+ const StyleSettings& rStyleSettings = pOutDev->GetSettings().GetStyleSettings(); >+ >+ // -------------------------------------------------- >+ // Ueber alle Absaetze... >+ // -------------------------------------------------- >+ for ( sal_uLong nPara = 0; nPara < mpTEParaPortions->Count(); nPara++ ) >+ { >+ TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPara ); >+ // falls beim Tippen Idle-Formatierung, asynchrones Paint. >+ if ( pPortion->IsInvalid() ) >+ return; >+ >+ sal_uLong nParaHeight = CalcParaHeight( nPara ); >+ if ( ( !pPaintArea || ( ( nY + (long)nParaHeight ) > pPaintArea->Top() ) ) >+ && ( !pPaintRange || ( ( nPara >= pPaintRange->GetStart().GetPara() ) && ( nPara <= pPaintRange->GetEnd().GetPara() ) ) ) ) >+ { >+ // -------------------------------------------------- >+ // Ueber die Zeilen des Absatzes... >+ // -------------------------------------------------- >+ sal_uInt16 nLines = pPortion->GetLines().size(); >+ sal_uInt16 nIndex = 0; >+ for ( sal_uInt16 nLine = 0; nLine < nLines; nLine++ ) >+ { >+ TextLine* pLine = pPortion->GetLines()[nLine]; >+ Point aTmpPos( rStartPos.X() + pLine->GetStartX(), nY ); >+ >+ if ( ( !pPaintArea || ( ( nY + mnCharHeight ) > pPaintArea->Top() ) ) >+ && ( !pPaintRange || ( >+ ( TextPaM( nPara, pLine->GetStart() ) < pPaintRange->GetEnd() ) && >+ ( TextPaM( nPara, pLine->GetEnd() ) > pPaintRange->GetStart() ) ) ) ) >+ { >+ // -------------------------------------------------- >+ // Ueber die Portions der Zeile... >+ // -------------------------------------------------- >+ nIndex = pLine->GetStart(); >+ for ( sal_uInt16 y = pLine->GetStartPortion(); y <= pLine->GetEndPortion(); y++ ) >+ { >+ OSL_ENSURE(pPortion->GetTextPortions().size(), >+ "Line without Textportion in Paint!"); >+ TETextPortion* pTextPortion = pPortion->GetTextPortions()[ y ]; >+ DBG_ASSERT( pTextPortion, "NULL-Pointer im Portioniterator in UpdateViews" ); >+ >+ ImpInitLayoutMode( pOutDev /*, pTextPortion->IsRightToLeft() */); >+ >+ long nTxtWidth = pTextPortion->GetWidth(); >+ aTmpPos.X() = rStartPos.X() + ImpGetOutputOffset( nPara, pLine, nIndex, nIndex ); >+ >+ // nur ausgeben, was im sichtbaren Bereich beginnt: >+ if ( ( ( aTmpPos.X() + nTxtWidth ) >= 0 ) >+ && ( !pPaintRange || ( >+ ( TextPaM( nPara, nIndex ) < pPaintRange->GetEnd() ) && >+ ( TextPaM( nPara, nIndex + pTextPortion->GetLen() ) > pPaintRange->GetStart() ) ) ) ) >+ { >+ switch ( pTextPortion->GetKind() ) >+ { >+ case PORTIONKIND_TEXT: >+ { >+ { >+ Font aFont; >+ SeekCursor( nPara, nIndex+1, aFont, pOutDev ); >+ if( bTransparent ) >+ aFont.SetTransparent( sal_True ); >+ else if ( pSelection ) >+ aFont.SetTransparent( sal_False ); >+ pOutDev->SetFont( aFont ); >+ >+ sal_uInt16 nTmpIndex = nIndex; >+ sal_uInt16 nEnd = nTmpIndex + pTextPortion->GetLen(); >+ Point aPos = aTmpPos; >+ if ( pPaintRange ) >+ { >+ // evtl soll nicht alles ausgegeben werden... >+ if ( ( pPaintRange->GetStart().GetPara() == nPara ) >+ && ( nTmpIndex < pPaintRange->GetStart().GetIndex() ) ) >+ { >+ nTmpIndex = pPaintRange->GetStart().GetIndex(); >+ } >+ if ( ( pPaintRange->GetEnd().GetPara() == nPara ) >+ && ( nEnd > pPaintRange->GetEnd().GetIndex() ) ) >+ { >+ nEnd = pPaintRange->GetEnd().GetIndex(); >+ } >+ } >+ >+ sal_Bool bDone = sal_False; >+ if ( pSelStart ) >+ { >+ // liegt ein Teil in der Selektion??? >+ TextPaM aTextStart( nPara, nTmpIndex ); >+ TextPaM aTextEnd( nPara, nEnd ); >+ if ( ( aTextStart < *pSelEnd ) && ( aTextEnd > *pSelStart ) ) >+ { >+ sal_uInt16 nL; >+ >+ // 1) Bereich vor Selektion >+ if ( aTextStart < *pSelStart ) >+ { >+ nL = pSelStart->GetIndex() - nTmpIndex; >+ pOutDev->SetFont( aFont); >+ aPos.X() = rStartPos.X() + ImpGetOutputOffset( nPara, pLine, nTmpIndex, nTmpIndex+nL ); >+ pOutDev->DrawText( aPos, pPortion->GetNode()->GetText(), nTmpIndex, nL ); >+ nTmpIndex = nTmpIndex + nL; >+ >+ } >+ // 2) Bereich mit Selektion >+ nL = nEnd-nTmpIndex; >+ if ( aTextEnd > *pSelEnd ) >+ nL = pSelEnd->GetIndex() - nTmpIndex; >+ if ( nL ) >+ { >+ Color aOldTextColor = pOutDev->GetTextColor(); >+ pOutDev->SetTextColor( rStyleSettings.GetHighlightTextColor() ); >+ pOutDev->SetTextFillColor( rStyleSettings.GetHighlightColor() ); >+ aPos.X() = rStartPos.X() + ImpGetOutputOffset( nPara, pLine, nTmpIndex, nTmpIndex+nL ); >+ pOutDev->DrawText( aPos, pPortion->GetNode()->GetText(), nTmpIndex, nL ); >+ pOutDev->SetTextColor( aOldTextColor ); >+ pOutDev->SetTextFillColor(); >+ nTmpIndex = nTmpIndex + nL; >+ } >+ >+ // 3) Bereich nach Selektion >+ if ( nTmpIndex < nEnd ) >+ { >+ nL = nEnd-nTmpIndex; >+ aPos.X() = rStartPos.X() + ImpGetOutputOffset( nPara, pLine, nTmpIndex, nTmpIndex+nL ); >+ pOutDev->DrawText( aPos, pPortion->GetNode()->GetText(), nTmpIndex, nEnd-nTmpIndex ); >+ } >+ bDone = sal_True; >+ } >+ } >+ if ( !bDone ) >+ { >+ aPos.X() = rStartPos.X() + ImpGetOutputOffset( nPara, pLine, nTmpIndex, nEnd ); >+ pOutDev->DrawText( aPos, pPortion->GetNode()->GetText(), nTmpIndex, nEnd-nTmpIndex ); >+ } >+ } >+ >+ } >+ break; >+ case PORTIONKIND_TAB: >+ { >+ // Bei HideSelection() nur Range, pSelection = 0. >+ if ( pSelStart || pPaintRange ) >+ { >+ Rectangle aTabArea( aTmpPos, Point( aTmpPos.X()+nTxtWidth, aTmpPos.Y()+mnCharHeight-1 ) ); >+ sal_Bool bDone = sal_False; >+ if ( pSelStart ) >+ { >+ // liegt der Tab in der Selektion??? >+ TextPaM aTextStart( nPara, nIndex ); >+ TextPaM aTextEnd( nPara, nIndex+1 ); >+ if ( ( aTextStart < *pSelEnd ) && ( aTextEnd > *pSelStart ) ) >+ { >+ Color aOldColor = pOutDev->GetFillColor(); >+ pOutDev->SetFillColor( rStyleSettings.GetHighlightColor() ); >+ pOutDev->DrawRect( aTabArea ); >+ pOutDev->SetFillColor( aOldColor ); >+ bDone = sal_True; >+ } >+ } >+ if ( !bDone ) >+ { >+ pOutDev->Erase( aTabArea ); >+ } >+ } >+ } >+ break; >+ default: OSL_FAIL( "ImpPaint: Unknown Portion-Type !" ); >+ } >+ } >+ >+ nIndex = nIndex + pTextPortion->GetLen(); >+ } >+ } >+ >+ nY += mnCharHeight; >+ >+ if ( pPaintArea && ( nY >= pPaintArea->Bottom() ) ) >+ break; // keine sichtbaren Aktionen mehr... >+ } >+ } >+ else >+ { >+ nY += nParaHeight; >+ } >+ >+ if ( pPaintArea && ( nY > pPaintArea->Bottom() ) ) >+ break; // keine sichtbaren Aktionen mehr... >+ } >+} >+ >+sal_Bool TextEngine::CreateLines( sal_uLong nPara ) >+{ >+ // sal_Bool: Aenderung der Hoehe des Absatzes Ja/Nein - sal_True/sal_False >+ >+ TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >+ TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >+ DBG_ASSERT( pTEParaPortion->IsInvalid(), "CreateLines: Portion nicht invalid!" ); >+ >+ sal_uInt16 nOldLineCount = pTEParaPortion->GetLines().size(); >+ >+ // --------------------------------------------------------------- >+ // Schnelle Sonderbehandlung fuer leere Absaetze... >+ // --------------------------------------------------------------- >+ if ( pTEParaPortion->GetNode()->GetText().Len() == 0 ) >+ { >+ // schnelle Sonderbehandlung... >+ if ( !pTEParaPortion->GetTextPortions().empty() ) >+ pTEParaPortion->GetTextPortions().Reset(); >+ if ( !pTEParaPortion->GetLines().empty() ) >+ { >+ BOOST_FOREACH(TextLine* pLine, pTEParaPortion->GetLines()) >+ delete pLine; >+ pTEParaPortion->GetLines().clear(); >+ } >+ CreateAndInsertEmptyLine( nPara ); >+ pTEParaPortion->SetValid(); >+ return nOldLineCount != pTEParaPortion->GetLines().size(); >+ } >+ >+ // --------------------------------------------------------------- >+ // Initialisierung...... >+ // --------------------------------------------------------------- >+ >+ if ( pTEParaPortion->GetLines().empty() ) >+ { >+ TextLine* pL = new TextLine; >+ pTEParaPortion->GetLines().push_back( pL ); >+ } >+ >+ const short nInvalidDiff = pTEParaPortion->GetInvalidDiff(); >+ const sal_uInt16 nInvalidStart = pTEParaPortion->GetInvalidPosStart(); >+ const sal_uInt16 nInvalidEnd = nInvalidStart + Abs( nInvalidDiff ); >+ sal_Bool bQuickFormat = sal_False; >+ >+ if ( pTEParaPortion->GetWritingDirectionInfos().empty() ) >+ ImpInitWritingDirections( nPara ); >+ >+ if ( pTEParaPortion->GetWritingDirectionInfos().size() == 1 ) >+ { >+ if ( pTEParaPortion->IsSimpleInvalid() && ( nInvalidDiff > 0 ) ) >+ { >+ bQuickFormat = sal_True; >+ } >+ else if ( ( pTEParaPortion->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 = pTEParaPortion->GetTextPortions().size(); >+ for ( sal_uInt16 nTP = 0; nTP < nPortions; nTP++ ) >+ { >+ // Es darf kein Start/Ende im geloeschten Bereich liegen. >+ TETextPortion* const pTP = pTEParaPortion->GetTextPortions()[ nTP ]; >+ nPos = nPos + pTP->GetLen(); >+ if ( ( nPos > nStart ) && ( nPos < nEnd ) ) >+ { >+ bQuickFormat = sal_False; >+ break; >+ } >+ } >+ } >+ } >+ >+ if ( bQuickFormat ) >+ RecalcTextPortion( nPara, nInvalidStart, nInvalidDiff ); >+ else >+ CreateTextPortions( nPara, nInvalidStart ); >+ >+ // --------------------------------------------------------------- >+ // Zeile mit InvalidPos suchen, eine Zeile davor beginnen... >+ // Zeilen flaggen => nicht removen ! >+ // --------------------------------------------------------------- >+ >+ sal_uInt16 nLine = pTEParaPortion->GetLines().size()-1; >+ for ( sal_uInt16 nL = 0; nL <= nLine; nL++ ) >+ { >+ TextLine* pLine = pTEParaPortion->GetLines()[ nL ]; >+ if ( pLine->GetEnd() > nInvalidStart ) >+ { >+ nLine = nL; >+ break; >+ } >+ pLine->SetValid(); >+ } >+ // Eine Zeile davor beginnen... >+ // Wenn ganz hinten getippt wird, kann sich die Zeile davor nicht aendern. >+ if ( nLine && ( !pTEParaPortion->IsSimpleInvalid() || ( nInvalidEnd < pNode->GetText().Len() ) || ( nInvalidDiff <= 0 ) ) ) >+ nLine--; >+ >+ TextLine* pLine = pTEParaPortion->GetLines()[ nLine ]; >+ >+ // --------------------------------------------------------------- >+ // Ab hier alle Zeilen durchformatieren... >+ // --------------------------------------------------------------- >+ size_t nDelFromLine = std::numeric_limits<size_t>::max(); >+ sal_Bool bLineBreak = sal_False; >+ >+ sal_uInt16 nIndex = pLine->GetStart(); >+ TextLine aSaveLine( *pLine ); >+ >+ Font aFont; >+ >+ sal_Bool bCalcPortion = sal_True; >+ >+ while ( nIndex < pNode->GetText().Len() ) >+ { >+ sal_Bool bEOL = sal_False; >+ sal_uInt16 nPortionStart = 0; >+ sal_uInt16 nPortionEnd = 0; >+ >+ sal_uInt16 nTmpPos = nIndex; >+ sal_uInt16 nTmpPortion = pLine->GetStartPortion(); >+ long nTmpWidth = mpDoc->GetLeftMargin(); >+// long nXWidth = mnMaxTextWidth ? ( mnMaxTextWidth - mpDoc->GetLeftMargin() ) : 0x7FFFFFFF; >+ // Margin nicht abziehen, ist schon in TmpWidth enthalten. >+ long nXWidth = mnMaxTextWidth ? mnMaxTextWidth : 0x7FFFFFFF; >+ if ( nXWidth < nTmpWidth ) >+ nXWidth = nTmpWidth; >+ >+ // Portion suchen, die nicht mehr in Zeile passt.... >+ TETextPortion* pPortion = 0; >+ sal_Bool bBrokenLine = sal_False; >+ bLineBreak = sal_False; >+ >+ while ( ( nTmpWidth <= nXWidth ) && !bEOL && ( nTmpPortion < pTEParaPortion->GetTextPortions().size() ) ) >+ { >+ nPortionStart = nTmpPos; >+ pPortion = pTEParaPortion->GetTextPortions()[ nTmpPortion ]; >+ DBG_ASSERT( pPortion->GetLen(), "Leere Portion in CreateLines ?!" ); >+ if ( pNode->GetText().GetChar( nTmpPos ) == '\t' ) >+ { >+ long nCurPos = nTmpWidth-mpDoc->GetLeftMargin(); >+ nTmpWidth = ((nCurPos/mnDefTab)+1)*mnDefTab+mpDoc->GetLeftMargin(); >+ pPortion->GetWidth() = nTmpWidth - nCurPos - mpDoc->GetLeftMargin(); >+ // 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->GetWidth() = nXWidth-1; >+ nTmpWidth = pPortion->GetWidth(); >+ bEOL = sal_True; >+ bBrokenLine = sal_True; >+ } >+ pPortion->GetKind() = PORTIONKIND_TAB; >+ } >+ else >+ { >+ >+ if ( bCalcPortion || !pPortion->HasValidSize() ) >+ pPortion->GetWidth() = (long)CalcTextWidth( nPara, nTmpPos, pPortion->GetLen() ); >+ nTmpWidth += pPortion->GetWidth(); >+ >+ pPortion->GetRightToLeft() = ImpGetRightToLeft( nPara, nTmpPos+1 ); >+ pPortion->GetKind() = PORTIONKIND_TEXT; >+ } >+ >+ nTmpPos = nTmpPos + pPortion->GetLen(); >+ nPortionEnd = nTmpPos; >+ nTmpPortion++; >+ } >+ >+ // das war evtl. eine Portion zu weit: >+ sal_Bool bFixedEnd = sal_False; >+ if ( nTmpWidth > nXWidth ) >+ { >+ nPortionEnd = nTmpPos; >+ nTmpPos = nTmpPos - pPortion->GetLen(); >+ nPortionStart = nTmpPos; >+ nTmpPortion--; >+ bEOL = sal_False; >+ >+ nTmpWidth -= pPortion->GetWidth(); >+ if ( pPortion->GetKind() == PORTIONKIND_TAB ) >+ { >+ bEOL = sal_True; >+ bFixedEnd = sal_True; >+ } >+ } >+ else >+ { >+ bEOL = sal_True; >+ pLine->SetEnd( nPortionEnd ); >+ OSL_ENSURE(pTEParaPortion->GetTextPortions().size(), >+ "No TextPortions?"); >+ pLine->SetEndPortion( (sal_uInt16)pTEParaPortion->GetTextPortions().size() - 1 ); >+ } >+ >+ if ( bFixedEnd ) >+ { >+ pLine->SetEnd( nPortionStart ); >+ pLine->SetEndPortion( nTmpPortion-1 ); >+ } >+ else if ( bLineBreak || bBrokenLine ) >+ { >+ pLine->SetEnd( nPortionStart+1 ); >+ pLine->SetEndPortion( nTmpPortion-1 ); >+ } >+ else if ( !bEOL ) >+ { >+ DBG_ASSERT( (nPortionEnd-nPortionStart) == pPortion->GetLen(), "Doch eine andere Portion?!" ); >+ long nRemainingWidth = mnMaxTextWidth - nTmpWidth; >+ ImpBreakLine( nPara, pLine, pPortion, nPortionStart, nRemainingWidth ); >+ } >+ >+ if ( ( ImpGetAlign() == TXTALIGN_CENTER ) || ( ImpGetAlign() == TXTALIGN_RIGHT ) ) >+ { >+ // Ausrichten... >+ long nTextWidth = 0; >+ for ( sal_uInt16 nTP = pLine->GetStartPortion(); nTP <= pLine->GetEndPortion(); nTP++ ) >+ { >+ TETextPortion* pTextPortion = pTEParaPortion->GetTextPortions()[ nTP ]; >+ nTextWidth += pTextPortion->GetWidth(); >+ } >+ long nSpace = mnMaxTextWidth - nTextWidth; >+ if ( nSpace > 0 ) >+ { >+ if ( ImpGetAlign() == TXTALIGN_CENTER ) >+ pLine->SetStartX( (sal_uInt16)(nSpace / 2) ); >+ else // TXTALIGN_RIGHT >+ pLine->SetStartX( (sal_uInt16)nSpace ); >+ } >+ } >+ else >+ { >+ pLine->SetStartX( mpDoc->GetLeftMargin() ); >+ } >+ >+ // ----------------------------------------------------------------- >+ // pruefen, ob die Zeile neu ausgegeben werden muss... >+ // ----------------------------------------------------------------- >+ pLine->SetInvalid(); >+ >+ if ( pTEParaPortion->IsSimpleInvalid() ) >+ { >+ // 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 ( bCalcPortion && bQuickFormat ) >+ { >+ bCalcPortion = sal_False; >+ pTEParaPortion->CorrectValuesBehindLastFormattedLine( nLine ); >+ break; >+ } >+ } >+ } >+ else if ( 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 ) ) >+ { >+ bCalcPortion = sal_False; >+ pTEParaPortion->CorrectValuesBehindLastFormattedLine( nLine ); >+ break; >+ } >+ } >+ } >+ } >+ >+ 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 < pTEParaPortion->GetLines().size()-1 ) >+ pLine = pTEParaPortion->GetLines()[ ++nLine ]; >+ if ( pLine && ( nIndex >= pNode->GetText().Len() ) ) >+ { >+ nDelFromLine = nLine; >+ break; >+ } >+ if ( !pLine && ( nIndex < pNode->GetText().Len() ) ) >+ { >+ pLine = new TextLine; >+ pTEParaPortion->GetLines().insert( pTEParaPortion->GetLines().begin() + ++nLine, pLine ); >+ } >+ if ( pLine ) >+ { >+ aSaveLine = *pLine; >+ pLine->SetStart( nIndex ); >+ pLine->SetEnd( nIndex ); >+ pLine->SetStartPortion( nEndPortion+1 ); >+ pLine->SetEndPortion( nEndPortion+1 ); >+ } >+ } // while ( Index < Len ) >+ >+ if (nDelFromLine != std::numeric_limits<size_t>::max()) >+ { >+ for( TextLines::iterator it = pTEParaPortion->GetLines().begin() + nDelFromLine; >+ it != pTEParaPortion->GetLines().end(); ++it ) >+ { >+ delete *it; >+ } >+ pTEParaPortion->GetLines().erase( pTEParaPortion->GetLines().begin() + nDelFromLine, >+ pTEParaPortion->GetLines().end() ); >+ } >+ >+ DBG_ASSERT( pTEParaPortion->GetLines().size(), "Keine Zeile nach CreateLines!" ); >+ >+ if ( bLineBreak == sal_True ) >+ CreateAndInsertEmptyLine( nPara ); >+ >+ pTEParaPortion->SetValid(); >+ >+ return nOldLineCount != pTEParaPortion->GetLines().size(); >+} >+ >+String TextEngine::GetWord( const TextPaM& rCursorPos, TextPaM* pStartOfWord ) >+{ >+ String aWord; >+ if ( rCursorPos.GetPara() < mpDoc->GetNodes().Count() ) >+ { >+ TextSelection aSel( rCursorPos ); >+ TextNode* pNode = mpDoc->GetNodes().GetObject( rCursorPos.GetPara() ); >+ uno::Reference < i18n::XBreakIterator > xBI = GetBreakIterator(); >+ i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), rCursorPos.GetIndex(), GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True ); >+ aSel.GetStart().GetIndex() = (sal_uInt16)aBoundary.startPos; >+ aSel.GetEnd().GetIndex() = (sal_uInt16)aBoundary.endPos; >+ aWord = pNode->GetText().Copy( aSel.GetStart().GetIndex(), aSel.GetEnd().GetIndex() - aSel.GetStart().GetIndex() ); >+ if ( pStartOfWord ) >+ *pStartOfWord = aSel.GetStart(); >+ } >+ return aWord; >+} >+ >+sal_Bool TextEngine::Read( SvStream& rInput, const TextSelection* pSel ) >+{ >+ sal_Bool bUpdate = GetUpdateMode(); >+ SetUpdateMode( sal_False ); >+ >+ UndoActionStart(); >+ TextSelection aSel; >+ if ( pSel ) >+ aSel = *pSel; >+ else >+ { >+ sal_uLong nParas = mpDoc->GetNodes().Count(); >+ TextNode* pNode = mpDoc->GetNodes().GetObject( nParas - 1 ); >+ aSel = TextPaM( nParas-1 , pNode->GetText().Len() ); >+ } >+ >+ if ( aSel.HasRange() ) >+ aSel = ImpDeleteText( aSel ); >+ >+ rtl::OString aLine; >+ sal_Bool bDone = rInput.ReadLine( aLine ); >+ rtl::OUString aTmpStr(rtl::OStringToOUString(aLine, rInput.GetStreamCharSet())), aStr; >+ while ( bDone ) >+ { >+ aSel = ImpInsertText( aSel, aTmpStr ); >+ bDone = rInput.ReadLine( aLine ); >+ aTmpStr = rtl::OStringToOUString(aLine, rInput.GetStreamCharSet()); >+ if ( bDone ) >+ aSel = ImpInsertParaBreak( aSel.GetEnd() ); >+ } >+ >+ UndoActionEnd(); >+ >+ TextSelection aNewSel( aSel.GetEnd(), aSel.GetEnd() ); >+ >+ // Damit bei FormatAndUpdate nicht auf die ungueltige Selektion zugegriffen wird. >+ if ( GetActiveView() ) >+ GetActiveView()->ImpSetSelection( aNewSel ); >+ >+ SetUpdateMode( bUpdate ); >+ FormatAndUpdate( GetActiveView() ); >+ >+ return rInput.GetError() ? sal_False : sal_True; >+} >+ >+sal_Bool TextEngine::Write( SvStream& rOutput, const TextSelection* pSel, sal_Bool bHTML ) >+{ >+ TextSelection aSel; >+ if ( pSel ) >+ aSel = *pSel; >+ else >+ { >+ sal_uLong nParas = mpDoc->GetNodes().Count(); >+ TextNode* pNode = mpDoc->GetNodes().GetObject( nParas - 1 ); >+ aSel.GetStart() = TextPaM( 0, 0 ); >+ aSel.GetEnd() = TextPaM( nParas-1, pNode->GetText().Len() ); >+ } >+ >+ if ( bHTML ) >+ { >+ rOutput.WriteLine( "<HTML>" ); >+ rOutput.WriteLine( "<BODY>" ); >+ } >+ >+ for ( sal_uLong nPara = aSel.GetStart().GetPara(); nPara <= aSel.GetEnd().GetPara(); nPara++ ) >+ { >+ TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >+ >+ sal_uInt16 nStartPos = 0; >+ sal_uInt16 nEndPos = pNode->GetText().Len(); >+ if ( nPara == aSel.GetStart().GetPara() ) >+ nStartPos = aSel.GetStart().GetIndex(); >+ if ( nPara == aSel.GetEnd().GetPara() ) >+ nEndPos = aSel.GetEnd().GetIndex(); >+ >+ String aText; >+ if ( !bHTML ) >+ { >+ aText = pNode->GetText().Copy( nStartPos, nEndPos-nStartPos ); >+ } >+ else >+ { >+ aText.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "<P STYLE=\"margin-bottom: 0cm\">" ) ); >+ >+ if ( nStartPos == nEndPos ) >+ { >+ // Leerzeilen werden von Writer wegoptimiert >+ aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "<BR>" ) ); >+ } >+ else >+ { >+ sal_uInt16 nTmpStart = nStartPos; >+ sal_uInt16 nTmpEnd = nEndPos; >+ do >+ { >+ TextCharAttrib* pAttr = pNode->GetCharAttribs().FindNextAttrib( TEXTATTR_HYPERLINK, nTmpStart, nEndPos ); >+ nTmpEnd = pAttr ? pAttr->GetStart() : nEndPos; >+ >+ // Text vor dem Attribut >+ aText += pNode->GetText().Copy( nTmpStart, nTmpEnd-nTmpStart ); >+ >+ if ( pAttr ) >+ { >+ nTmpEnd = Min( pAttr->GetEnd(), nEndPos ); >+ >+ // z.B. <A HREF="http://www.mopo.de/">Morgenpost</A> >+ aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "<A HREF=\"" ) ); >+ aText += ((const TextAttribHyperLink&) pAttr->GetAttr() ).GetURL(); >+ aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "\">" ) ); >+ nTmpStart = pAttr->GetStart(); >+ aText += pNode->GetText().Copy( nTmpStart, nTmpEnd-nTmpStart ); >+ aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "</A>" ) ); >+ >+ nTmpStart = pAttr->GetEnd(); >+ } >+ } while ( nTmpEnd < nEndPos ); >+ } >+ >+ aText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "</P>" ) ); >+ } >+ rOutput.WriteLine(rtl::OUStringToOString(aText, >+ rOutput.GetStreamCharSet())); >+ } >+ >+ if ( bHTML ) >+ { >+ rOutput.WriteLine( "</BODY>" ); >+ rOutput.WriteLine( "</HTML>" ); >+ } >+ >+ return rOutput.GetError() ? sal_False : sal_True; >+} >+ >+void TextEngine::RemoveAttribs( sal_uLong nPara, sal_Bool bIdleFormatAndUpdate ) >+{ >+ if ( nPara < mpDoc->GetNodes().Count() ) >+ { >+ TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >+ if ( pNode->GetCharAttribs().Count() ) >+ { >+ pNode->GetCharAttribs().Clear( sal_True ); >+ >+ TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >+ pTEParaPortion->MarkSelectionInvalid( 0, pNode->GetText().Len() ); >+ >+ mbFormatted = sal_False; >+ >+ if ( bIdleFormatAndUpdate ) >+ IdleFormatAndUpdate( NULL, 0xFFFF ); >+ else >+ FormatAndUpdate( NULL ); >+ } >+ } >+} >+void TextEngine::RemoveAttribs( sal_uLong nPara, sal_uInt16 nWhich, sal_Bool bIdleFormatAndUpdate ) >+{ >+ if ( nPara < mpDoc->GetNodes().Count() ) >+ { >+ TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >+ if ( pNode->GetCharAttribs().Count() ) >+ { >+ TextCharAttribList& rAttribs = pNode->GetCharAttribs(); >+ sal_uInt16 nAttrCount = rAttribs.Count(); >+ for(sal_uInt16 nAttr = nAttrCount; nAttr; --nAttr) >+ { >+ if(rAttribs.GetAttrib( nAttr - 1 )->Which() == nWhich) >+ rAttribs.RemoveAttrib( nAttr -1 ); >+ } >+ TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >+ pTEParaPortion->MarkSelectionInvalid( 0, pNode->GetText().Len() ); >+ mbFormatted = sal_False; >+ if(bIdleFormatAndUpdate) >+ IdleFormatAndUpdate( NULL, 0xFFFF ); >+ else >+ FormatAndUpdate( NULL ); >+ } >+ } >+} >+void TextEngine::RemoveAttrib( sal_uLong nPara, const TextCharAttrib& rAttrib ) >+{ >+ if ( nPara < mpDoc->GetNodes().Count() ) >+ { >+ TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >+ if ( pNode->GetCharAttribs().Count() ) >+ { >+ TextCharAttribList& rAttribs = pNode->GetCharAttribs(); >+ sal_uInt16 nAttrCount = rAttribs.Count(); >+ for(sal_uInt16 nAttr = nAttrCount; nAttr; --nAttr) >+ { >+ if(rAttribs.GetAttrib( nAttr - 1 ) == &rAttrib) >+ { >+ rAttribs.RemoveAttrib( nAttr -1 ); >+ break; >+ } >+ } >+ TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >+ pTEParaPortion->MarkSelectionInvalid( 0, pNode->GetText().Len() ); >+ mbFormatted = sal_False; >+ FormatAndUpdate( NULL ); >+ } >+ } >+} >+ >+void TextEngine::SetAttrib( const TextAttrib& rAttr, sal_uLong nPara, sal_uInt16 nStart, sal_uInt16 nEnd, sal_Bool bIdleFormatAndUpdate ) >+{ >+ // Es wird hier erstmal nicht geprueft, ob sich Attribute ueberlappen! >+ // Diese Methode ist erstmal nur fuer einen Editor, der fuer eine Zeile >+ // _schnell_ das Syntax-Highlight einstellen will. >+ >+ // Da die TextEngine z.Zt fuer Editoren gedacht ist gibt es auch kein >+ // Undo fuer Attribute! >+ >+ if ( nPara < mpDoc->GetNodes().Count() ) >+ { >+ TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >+ TEParaPortion* pTEParaPortion = mpTEParaPortions->GetObject( nPara ); >+ >+ sal_uInt16 nMax = pNode->GetText().Len(); >+ if ( nStart > nMax ) >+ nStart = nMax; >+ if ( nEnd > nMax ) >+ nEnd = nMax; >+ >+ pNode->GetCharAttribs().InsertAttrib( new TextCharAttrib( rAttr, nStart, nEnd ) ); >+ pTEParaPortion->MarkSelectionInvalid( nStart, nEnd ); >+ >+ mbFormatted = sal_False; >+ if ( bIdleFormatAndUpdate ) >+ IdleFormatAndUpdate( NULL, 0xFFFF ); >+ else >+ FormatAndUpdate( NULL ); >+ } >+} >+ >+void TextEngine::SetTextAlign( TxtAlign eAlign ) >+{ >+ if ( eAlign != meAlign ) >+ { >+ meAlign = eAlign; >+ FormatFullDoc(); >+ UpdateViews(); >+ } >+} >+ >+ >+void TextEngine::ValidateSelection( TextSelection& rSel ) const >+{ >+ ValidatePaM( rSel.GetStart() ); >+ ValidatePaM( rSel.GetEnd() ); >+} >+ >+void TextEngine::ValidatePaM( TextPaM& rPaM ) const >+{ >+ sal_uLong nMaxPara = mpDoc->GetNodes().Count() - 1; >+ if ( rPaM.GetPara() > nMaxPara ) >+ { >+ rPaM.GetPara() = nMaxPara; >+ rPaM.GetIndex() = 0xFFFF; >+ } >+ >+ sal_uInt16 nMaxIndex = GetTextLen( rPaM.GetPara() ); >+ if ( rPaM.GetIndex() > nMaxIndex ) >+ rPaM.GetIndex() = nMaxIndex; >+} >+ >+ >+// Status & Selektionsanpassung >+ >+void TextEngine::ImpParagraphInserted( sal_uLong nPara ) >+{ >+ // Die aktive View braucht nicht angepasst werden, aber bei allen >+ // passiven muss die Selektion angepasst werden: >+ if ( mpViews->size() > 1 ) >+ { >+ for ( sal_uInt16 nView = mpViews->size(); nView; ) >+ { >+ TextView* pView = (*mpViews)[ --nView ]; >+ if ( pView != GetActiveView() ) >+ { >+ for ( int n = 0; n <= 1; n++ ) >+ { >+ TextPaM& rPaM = n ? pView->GetSelection().GetStart(): pView->GetSelection().GetEnd(); >+ if ( rPaM.GetPara() >= nPara ) >+ rPaM.GetPara()++; >+ } >+ } >+ } >+ } >+ Broadcast( TextHint( TEXT_HINT_PARAINSERTED, nPara ) ); >+} >+ >+void TextEngine::ImpParagraphRemoved( sal_uLong nPara ) >+{ >+ if ( mpViews->size() > 1 ) >+ { >+ for ( sal_uInt16 nView = mpViews->size(); nView; ) >+ { >+ TextView* pView = (*mpViews)[ --nView ]; >+ if ( pView != GetActiveView() ) >+ { >+ sal_uLong nParas = mpDoc->GetNodes().Count(); >+ for ( int n = 0; n <= 1; n++ ) >+ { >+ TextPaM& rPaM = n ? pView->GetSelection().GetStart(): pView->GetSelection().GetEnd(); >+ if ( rPaM.GetPara() > nPara ) >+ rPaM.GetPara()--; >+ else if ( rPaM.GetPara() == nPara ) >+ { >+ rPaM.GetIndex() = 0; >+ if ( rPaM.GetPara() >= nParas ) >+ rPaM.GetPara()--; >+ } >+ } >+ } >+ } >+ } >+ Broadcast( TextHint( TEXT_HINT_PARAREMOVED, nPara ) ); >+} >+ >+void TextEngine::ImpCharsRemoved( sal_uLong nPara, sal_uInt16 nPos, sal_uInt16 nChars ) >+{ >+ if ( mpViews->size() > 1 ) >+ { >+ for ( sal_uInt16 nView = mpViews->size(); nView; ) >+ { >+ TextView* pView = (*mpViews)[ --nView ]; >+ if ( pView != GetActiveView() ) >+ { >+ sal_uInt16 nEnd = nPos+nChars; >+ for ( int n = 0; n <= 1; n++ ) >+ { >+ TextPaM& rPaM = n ? pView->GetSelection().GetStart(): pView->GetSelection().GetEnd(); >+ if ( rPaM.GetPara() == nPara ) >+ { >+ if ( rPaM.GetIndex() > nEnd ) >+ rPaM.GetIndex() = rPaM.GetIndex() - nChars; >+ else if ( rPaM.GetIndex() > nPos ) >+ rPaM.GetIndex() = nPos; >+ } >+ } >+ } >+ } >+ } >+ Broadcast( TextHint( TEXT_HINT_PARACONTENTCHANGED, nPara ) ); >+} >+ >+void TextEngine::ImpCharsInserted( sal_uLong nPara, sal_uInt16 nPos, sal_uInt16 nChars ) >+{ >+ if ( mpViews->size() > 1 ) >+ { >+ for ( sal_uInt16 nView = mpViews->size(); nView; ) >+ { >+ TextView* pView = (*mpViews)[ --nView ]; >+ if ( pView != GetActiveView() ) >+ { >+ for ( int n = 0; n <= 1; n++ ) >+ { >+ TextPaM& rPaM = n ? pView->GetSelection().GetStart(): pView->GetSelection().GetEnd(); >+ if ( rPaM.GetPara() == nPara ) >+ { >+ if ( rPaM.GetIndex() >= nPos ) >+ rPaM.GetIndex() = rPaM.GetIndex() + nChars; >+ } >+ } >+ } >+ } >+ } >+ Broadcast( TextHint( TEXT_HINT_PARACONTENTCHANGED, nPara ) ); >+} >+ >+void TextEngine::ImpFormattingParagraph( sal_uLong nPara ) >+{ >+ Broadcast( TextHint( TEXT_HINT_FORMATPARA, nPara ) ); >+} >+ >+void TextEngine::ImpTextHeightChanged() >+{ >+ Broadcast( TextHint( TEXT_HINT_TEXTHEIGHTCHANGED ) ); >+} >+ >+void TextEngine::ImpTextFormatted() >+{ >+ Broadcast( TextHint( TEXT_HINT_TEXTFORMATTED ) ); >+} >+ >+void TextEngine::Draw( OutputDevice* pDev, const Point& rPos ) >+{ >+ ImpPaint( pDev, rPos, NULL ); >+} >+ >+void TextEngine::SetLeftMargin( sal_uInt16 n ) >+{ >+ mpDoc->SetLeftMargin( n ); >+} >+ >+sal_uInt16 TextEngine::GetLeftMargin() const >+{ >+ return mpDoc->GetLeftMargin(); >+} >+ >+uno::Reference< i18n::XBreakIterator > TextEngine::GetBreakIterator() >+{ >+ if ( !mxBreakIterator.is() ) >+ mxBreakIterator = vcl::unohelper::CreateBreakIterator(); >+ DBG_ASSERT( mxBreakIterator.is(), "Could not create BreakIterator" ); >+ return mxBreakIterator; >+} >+ >+void TextEngine::SetLocale( const ::com::sun::star::lang::Locale& rLocale ) >+{ >+ maLocale = rLocale; >+ delete mpLocaleDataWrapper; >+ mpLocaleDataWrapper = NULL; >+} >+ >+::com::sun::star::lang::Locale TextEngine::GetLocale() >+{ >+ if ( maLocale.Language.isEmpty() ) >+ { >+ maLocale = Application::GetSettings().GetUILocale(); >+ } >+ return maLocale; >+} >+ >+LocaleDataWrapper* TextEngine::ImpGetLocaleDataWrapper() >+{ >+ if ( !mpLocaleDataWrapper ) >+ mpLocaleDataWrapper = new LocaleDataWrapper( vcl::unohelper::GetMultiServiceFactory(), GetLocale() ); >+ >+ return mpLocaleDataWrapper; >+} >+ >+void TextEngine::SetRightToLeft( sal_Bool bR2L ) >+{ >+ if ( mbRightToLeft != bR2L ) >+ { >+ mbRightToLeft = bR2L; >+ meAlign = bR2L ? TXTALIGN_RIGHT : TXTALIGN_LEFT; >+ FormatFullDoc(); >+ UpdateViews(); >+ } >+} >+ >+void TextEngine::ImpInitWritingDirections( sal_uLong nPara ) >+{ >+ TEParaPortion* pParaPortion = mpTEParaPortions->GetObject( nPara ); >+ std::vector<TEWritingDirectionInfo>& rInfos = pParaPortion->GetWritingDirectionInfos(); >+ rInfos.clear(); >+ >+ if ( pParaPortion->GetNode()->GetText().Len() ) >+ { >+ const UBiDiLevel nBidiLevel = IsRightToLeft() ? 1 /*RTL*/ : 0 /*LTR*/; >+ String aText( pParaPortion->GetNode()->GetText() ); >+ >+ // >+ // 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 ( sal_uInt16 nIdx = 0; nIdx < nCount; ++nIdx ) >+ { >+ ubidi_getLogicalRun( pBidi, nStart, &nEnd, &nCurrDir ); >+ rInfos.push_back( TEWritingDirectionInfo( nCurrDir, (sal_uInt16)nStart, (sal_uInt16)nEnd ) ); >+ nStart = nEnd; >+ } >+ >+ ubidi_close( pBidi ); >+ } >+ >+ // No infos mean no CTL and default dir is L2R... >+ if ( rInfos.empty() ) >+ rInfos.push_back( TEWritingDirectionInfo( 0, 0, (sal_uInt16)pParaPortion->GetNode()->GetText().Len() ) ); >+ >+} >+ >+sal_uInt8 TextEngine::ImpGetRightToLeft( sal_uLong nPara, sal_uInt16 nPos, sal_uInt16* pStart, sal_uInt16* pEnd ) >+{ >+ sal_uInt8 nRightToLeft = 0; >+ >+ TextNode* pNode = mpDoc->GetNodes().GetObject( nPara ); >+ if ( pNode && pNode->GetText().Len() ) >+ { >+ TEParaPortion* pParaPortion = mpTEParaPortions->GetObject( nPara ); >+ if ( pParaPortion->GetWritingDirectionInfos().empty() ) >+ ImpInitWritingDirections( nPara ); >+ >+ std::vector<TEWritingDirectionInfo>& rDirInfos = pParaPortion->GetWritingDirectionInfos(); >+ for ( std::vector<TEWritingDirectionInfo>::const_iterator rDirInfosIt = rDirInfos.begin(); rDirInfosIt != rDirInfos.end(); ++rDirInfosIt ) >+ { >+ if ( ( (*rDirInfosIt).nStartPos <= nPos ) && ( (*rDirInfosIt).nEndPos >= nPos ) ) >+ { >+ nRightToLeft = (*rDirInfosIt).nType; >+ if ( pStart ) >+ *pStart = (*rDirInfosIt).nStartPos; >+ if ( pEnd ) >+ *pEnd = (*rDirInfosIt).nEndPos; >+ break; >+ } >+ } >+ } >+ return nRightToLeft; >+} >+ >+long TextEngine::ImpGetPortionXOffset( sal_uLong nPara, TextLine* pLine, sal_uInt16 nTextPortion ) >+{ >+ long nX = pLine->GetStartX(); >+ >+ TEParaPortion* pParaPortion = mpTEParaPortions->GetObject( nPara ); >+ >+ for ( sal_uInt16 i = pLine->GetStartPortion(); i < nTextPortion; i++ ) >+ { >+ TETextPortion* pPortion = pParaPortion->GetTextPortions()[ i ]; >+ nX += pPortion->GetWidth(); >+ } >+ >+ TETextPortion* pDestPortion = pParaPortion->GetTextPortions()[ nTextPortion ]; >+ if ( pDestPortion->GetKind() != PORTIONKIND_TAB ) >+ { >+ if ( !IsRightToLeft() && pDestPortion->GetRightToLeft() ) >+ { >+ // Portions behind must be added, visual before this portion >+ sal_uInt16 nTmpPortion = nTextPortion+1; >+ while ( nTmpPortion <= pLine->GetEndPortion() ) >+ { >+ TETextPortion* pNextTextPortion = pParaPortion->GetTextPortions()[ nTmpPortion ]; >+ if ( pNextTextPortion->GetRightToLeft() && ( pNextTextPortion->GetKind() != PORTIONKIND_TAB ) ) >+ nX += pNextTextPortion->GetWidth(); >+ else >+ break; >+ nTmpPortion++; >+ } >+ // Portions before must be removed, visual behind this portion >+ nTmpPortion = nTextPortion; >+ while ( nTmpPortion > pLine->GetStartPortion() ) >+ { >+ --nTmpPortion; >+ TETextPortion* pPrevTextPortion = pParaPortion->GetTextPortions()[ nTmpPortion ]; >+ if ( pPrevTextPortion->GetRightToLeft() && ( pPrevTextPortion->GetKind() != PORTIONKIND_TAB ) ) >+ nX -= pPrevTextPortion->GetWidth(); >+ else >+ break; >+ } >+ } >+ else if ( IsRightToLeft() && !pDestPortion->IsRightToLeft() ) >+ { >+ // Portions behind must be removed, visual behind this portion >+ sal_uInt16 nTmpPortion = nTextPortion+1; >+ while ( nTmpPortion <= pLine->GetEndPortion() ) >+ { >+ TETextPortion* pNextTextPortion = pParaPortion->GetTextPortions()[ nTmpPortion ]; >+ if ( !pNextTextPortion->IsRightToLeft() && ( pNextTextPortion->GetKind() != PORTIONKIND_TAB ) ) >+ nX += pNextTextPortion->GetWidth(); >+ else >+ break; >+ nTmpPortion++; >+ } >+ // Portions before must be added, visual before this portion >+ nTmpPortion = nTextPortion; >+ while ( nTmpPortion > pLine->GetStartPortion() ) >+ { >+ --nTmpPortion; >+ TETextPortion* pPrevTextPortion = pParaPortion->GetTextPortions()[ nTmpPortion ]; >+ if ( !pPrevTextPortion->IsRightToLeft() && ( pPrevTextPortion->GetKind() != PORTIONKIND_TAB ) ) >+ nX -= pPrevTextPortion->GetWidth(); >+ else >+ break; >+ } >+ } >+ } >+ >+ return nX; >+} >+ >+void TextEngine::ImpInitLayoutMode( OutputDevice* pOutDev, sal_Bool bDrawingR2LPortion ) >+{ >+ sal_uLong nLayoutMode = pOutDev->GetLayoutMode(); >+ >+ nLayoutMode &= ~(TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_COMPLEX_DISABLED | TEXT_LAYOUT_BIDI_STRONG ); >+ if ( bDrawingR2LPortion ) >+ nLayoutMode |= TEXT_LAYOUT_BIDI_RTL; >+ >+ pOutDev->SetLayoutMode( nLayoutMode ); >+} >+ >+TxtAlign TextEngine::ImpGetAlign() const >+{ >+ TxtAlign eAlign = meAlign; >+ if ( IsRightToLeft() ) >+ { >+ if ( eAlign == TXTALIGN_LEFT ) >+ eAlign = TXTALIGN_RIGHT; >+ else if ( eAlign == TXTALIGN_RIGHT ) >+ eAlign = TXTALIGN_LEFT; >+ } >+ return eAlign; >+} >+ >+long TextEngine::ImpGetOutputOffset( sal_uLong nPara, TextLine* pLine, sal_uInt16 nIndex, sal_uInt16 nIndex2 ) >+{ >+ TEParaPortion* pPortion = mpTEParaPortions->GetObject( nPara ); >+ >+ sal_uInt16 nPortionStart; >+ sal_uInt16 nPortion = pPortion->GetTextPortions().FindPortion( nIndex, nPortionStart, sal_True ); >+ >+ TETextPortion* pTextPortion = pPortion->GetTextPortions()[ nPortion ]; >+ >+ long nX; >+ >+ if ( ( nIndex == nPortionStart ) && ( nIndex == nIndex2 ) ) >+ { >+ // Output of full portion, so we need portion x offset. >+ // Use ImpGetPortionXOffset, because GetXPos may deliver left or right position from portioon, depending on R2L, L2R >+ nX = ImpGetPortionXOffset( nPara, pLine, nPortion ); >+ if ( IsRightToLeft() ) >+ { >+ nX = -nX -pTextPortion->GetWidth(); >+ } >+ } >+ else >+ { >+ nX = ImpGetXPos( nPara, pLine, nIndex, nIndex == nPortionStart ); >+ if ( nIndex2 != nIndex ) >+ { >+ long nX2 = ImpGetXPos( nPara, pLine, nIndex2, sal_False ); >+ if ( ( !IsRightToLeft() && ( nX2 < nX ) ) || >+ ( IsRightToLeft() && ( nX2 > nX ) ) ) >+ { >+ nX = nX2; >+ } >+ } >+ if ( IsRightToLeft() ) >+ { >+ nX = -nX; >+ } >+ } >+ >+ return nX; >+} >+ >+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/vcl/source/edit/textund2.hxx b/vcl/source/edit/textund2.hxx >new file mode 100644 >index 0000000..c5ce90c >--- /dev/null >+++ b/vcl/source/edit/textund2.hxx >@@ -0,0 +1,122 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >+/* >+ * This file is part of the LibreOffice project. >+ * >+ * This Source Code Form is subject to the terms of the Mozilla Public >+ * License, v. 2.0. If a copy of the MPL was not distributed with this >+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. >+ * >+ * This file incorporates work covered by the following license notice: >+ * >+ * Licensed to the Apache Software Foundation (ASF) under one or more >+ * contributor license agreements. See the NOTICE file distributed >+ * with this work for additional information regarding copyright >+ * ownership. The ASF licenses this file to you under the Apache >+ * License, Version 2.0 (the "License"); you may not use this file >+ * except in compliance with the License. You may obtain a copy of >+ * the License at http://www.apache.org/licenses/LICENSE-2.0 . >+ */ >+#ifndef _TEXTUND2_HXX >+#define _TEXTUND2_HXX >+ >+#include <textundo.hxx> >+ >+ >+class TextUndoDelPara : public TextUndo >+{ >+private: >+ sal_Bool mbDelObject; >+ sal_uLong mnPara; >+ TextNode* mpNode; // Zeigt auf das gueltige, nicht zerstoerte Objekt! >+ >+public: >+ TYPEINFO(); >+ TextUndoDelPara( TextEngine* pTextEngine, TextNode* pNode, sal_uLong nPara ); >+ ~TextUndoDelPara(); >+ >+ virtual void Undo(); >+ virtual void Redo(); >+}; >+ >+ >+class TextUndoConnectParas : public TextUndo >+{ >+private: >+ sal_uLong mnPara; >+ sal_uInt16 mnSepPos; >+ >+public: >+ TYPEINFO(); >+ TextUndoConnectParas( TextEngine* pTextEngine, sal_uLong nPara, sal_uInt16 nSepPos ); >+ ~TextUndoConnectParas(); >+ >+ virtual void Undo(); >+ virtual void Redo(); >+}; >+ >+ >+class TextUndoSplitPara : public TextUndo >+{ >+private: >+ sal_uLong mnPara; >+ sal_uInt16 mnSepPos; >+ >+public: >+ TYPEINFO(); >+ TextUndoSplitPara( TextEngine* pTextEngine, sal_uLong nPara, sal_uInt16 nSepPos ); >+ ~TextUndoSplitPara(); >+ >+ virtual void Undo(); >+ virtual void Redo(); >+}; >+ >+ >+class TextUndoInsertChars : public TextUndo >+{ >+private: >+ TextPaM maTextPaM; >+ String maText; >+ >+public: >+ TYPEINFO(); >+ TextUndoInsertChars( TextEngine* pTextEngine, const TextPaM& rTextPaM, const String& rStr ); >+ >+ virtual void Undo(); >+ virtual void Redo(); >+ >+ virtual sal_Bool Merge( SfxUndoAction *pNextAction ); >+}; >+ >+ >+class TextUndoRemoveChars : public TextUndo >+{ >+private: >+ TextPaM maTextPaM; >+ String maText; >+ >+public: >+ TYPEINFO(); >+ TextUndoRemoveChars( TextEngine* pTextEngine, const TextPaM& rTextPaM, const String& rStr ); >+ >+ virtual void Undo(); >+ virtual void Redo(); >+}; >+ >+ >+class TextUndoSetAttribs: public TextUndo >+{ >+private: >+ TextSelection maSelection; >+ >+public: >+ TYPEINFO(); >+ TextUndoSetAttribs( TextEngine* pTextEngine, const TextSelection& rESel ); >+ ~TextUndoSetAttribs(); >+ >+ virtual void Undo(); >+ virtual void Redo(); >+}; >+ >+#endif // _TEXTUND2_HXX >+ >+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/vcl/source/edit/textundo.cxx b/vcl/source/edit/textundo.cxx >new file mode 100644 >index 0000000..807abf2 >--- /dev/null >+++ b/vcl/source/edit/textundo.cxx >@@ -0,0 +1,295 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >+/************************************************************************* >+ * >+ * 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 <vcl/texteng.hxx> >+#include <vcl/textview.hxx> >+#include <textundo.hxx> >+#include <textund2.hxx> >+#include <vcl/textdata.hxx> >+#include <textdoc.hxx> >+#include <textdat2.hxx> >+ >+TYPEINIT1( TextUndo, SfxUndoAction ); >+TYPEINIT1( TextUndoDelPara, TextUndo ); >+TYPEINIT1( TextUndoConnectParas, TextUndo ); >+TYPEINIT1( TextUndoSplitPara, TextUndo ); >+TYPEINIT1( TextUndoInsertChars, TextUndo ); >+TYPEINIT1( TextUndoRemoveChars, TextUndo ); >+ >+ >+TextUndoManager::TextUndoManager( TextEngine* p ) >+{ >+ mpTextEngine = p; >+} >+ >+TextUndoManager::~TextUndoManager() >+{ >+} >+ >+sal_Bool TextUndoManager::Undo() >+{ >+ if ( GetUndoActionCount() == 0 ) >+ return sal_False; >+ >+ UndoRedoStart(); >+ >+ mpTextEngine->SetIsInUndo( sal_True ); >+ sal_Bool bDone = SfxUndoManager::Undo(); >+ mpTextEngine->SetIsInUndo( sal_False ); >+ >+ UndoRedoEnd(); >+ >+ return bDone; >+} >+ >+sal_Bool TextUndoManager::Redo() >+{ >+ if ( GetRedoActionCount() == 0 ) >+ return sal_False; >+ >+ >+ UndoRedoStart(); >+ >+ mpTextEngine->SetIsInUndo( sal_True ); >+ sal_Bool bDone = SfxUndoManager::Redo(); >+ mpTextEngine->SetIsInUndo( sal_False ); >+ >+ UndoRedoEnd(); >+ >+ return bDone; >+} >+ >+void TextUndoManager::UndoRedoStart() >+{ >+ DBG_ASSERT( GetView(), "Undo/Redo: Active View?" ); >+ >+// if ( GetView() ) >+// GetView()->HideSelection(); >+} >+ >+void TextUndoManager::UndoRedoEnd() >+{ >+ if ( GetView() ) >+ { >+ TextSelection aNewSel( GetView()->GetSelection() ); >+ aNewSel.GetStart() = aNewSel.GetEnd(); >+ GetView()->ImpSetSelection( aNewSel ); >+ } >+ >+ mpTextEngine->UpdateSelections(); >+ >+ mpTextEngine->FormatAndUpdate( GetView() ); >+} >+ >+ >+TextUndo::TextUndo( TextEngine* p ) >+{ >+ mpTextEngine = p; >+} >+ >+TextUndo::~TextUndo() >+{ >+} >+ >+rtl::OUString TextUndo::GetComment() const >+{ >+ return rtl::OUString(); >+} >+ >+void TextUndo::SetSelection( const TextSelection& rSel ) >+{ >+ if ( GetView() ) >+ GetView()->ImpSetSelection( rSel ); >+} >+ >+ >+TextUndoDelPara::TextUndoDelPara( TextEngine* pTextEngine, TextNode* pNode, sal_uLong nPara ) >+ : TextUndo( pTextEngine ) >+{ >+ mpNode = pNode; >+ mnPara = nPara; >+ mbDelObject = sal_True; >+} >+ >+TextUndoDelPara::~TextUndoDelPara() >+{ >+ if ( mbDelObject ) >+ delete mpNode; >+} >+ >+void TextUndoDelPara::Undo() >+{ >+ GetTextEngine()->InsertContent( mpNode, mnPara ); >+ mbDelObject = sal_False; // gehoert wieder der Engine >+ >+ if ( GetView() ) >+ { >+ TextSelection aSel( TextPaM( mnPara, 0 ), TextPaM( mnPara, mpNode->GetText().Len() ) ); >+ SetSelection( aSel ); >+ } >+} >+ >+void TextUndoDelPara::Redo() >+{ >+ // pNode stimmt nicht mehr, falls zwischendurch Undos, in denen >+ // Absaetze verschmolzen sind. >+ mpNode = GetDoc()->GetNodes().GetObject( mnPara ); >+ >+ delete GetTEParaPortions()->GetObject( mnPara ); >+ GetTEParaPortions()->Remove( mnPara ); >+ >+ // Node nicht loeschen, haengt im Undo! >+ GetDoc()->GetNodes().Remove( mnPara ); >+ GetTextEngine()->ImpParagraphRemoved( mnPara ); >+ >+ mbDelObject = sal_True; // gehoert wieder dem Undo >+ >+ sal_uLong nParas = GetDoc()->GetNodes().Count(); >+ sal_uLong n = mnPara < nParas ? mnPara : (nParas-1); >+ TextNode* pN = GetDoc()->GetNodes().GetObject( n ); >+ TextPaM aPaM( n, pN->GetText().Len() ); >+ SetSelection( aPaM ); >+} >+ >+// ----------------------------------------------------------------------- >+// TextUndoConnectParas >+// ------------------------------------------------------------------------ >+TextUndoConnectParas::TextUndoConnectParas( TextEngine* pTextEngine, sal_uLong nPara, sal_uInt16 nPos ) >+ : TextUndo( pTextEngine ) >+{ >+ mnPara = nPara; >+ mnSepPos = nPos; >+} >+ >+TextUndoConnectParas::~TextUndoConnectParas() >+{ >+} >+ >+void TextUndoConnectParas::Undo() >+{ >+ TextPaM aPaM = GetTextEngine()->SplitContent( mnPara, mnSepPos ); >+ SetSelection( aPaM ); >+} >+ >+void TextUndoConnectParas::Redo() >+{ >+ TextPaM aPaM = GetTextEngine()->ConnectContents( mnPara ); >+ SetSelection( aPaM ); >+} >+ >+ >+TextUndoSplitPara::TextUndoSplitPara( TextEngine* pTextEngine, sal_uLong nPara, sal_uInt16 nPos ) >+ : TextUndo( pTextEngine ) >+{ >+ mnPara = nPara; >+ mnSepPos = nPos; >+} >+ >+TextUndoSplitPara::~TextUndoSplitPara() >+{ >+} >+ >+void TextUndoSplitPara::Undo() >+{ >+ TextPaM aPaM = GetTextEngine()->ConnectContents( mnPara ); >+ SetSelection( aPaM ); >+} >+ >+void TextUndoSplitPara::Redo() >+{ >+ TextPaM aPaM = GetTextEngine()->SplitContent( mnPara, mnSepPos ); >+ SetSelection( aPaM ); >+} >+ >+ >+TextUndoInsertChars::TextUndoInsertChars( TextEngine* pTextEngine, const TextPaM& rTextPaM, const XubString& rStr ) >+ : TextUndo( pTextEngine ), >+ maTextPaM( rTextPaM ), maText( rStr ) >+{ >+} >+ >+void TextUndoInsertChars::Undo() >+{ >+ TextSelection aSel( maTextPaM, maTextPaM ); >+ aSel.GetEnd().GetIndex() = aSel.GetEnd().GetIndex() + maText.Len(); >+ TextPaM aPaM = GetTextEngine()->ImpDeleteText( aSel ); >+ SetSelection( aPaM ); >+} >+ >+void TextUndoInsertChars::Redo() >+{ >+ TextSelection aSel( maTextPaM, maTextPaM ); >+ GetTextEngine()->ImpInsertText( aSel, maText ); >+ TextPaM aNewPaM( maTextPaM ); >+ aNewPaM.GetIndex() = aNewPaM.GetIndex() + maText.Len(); >+ SetSelection( TextSelection( aSel.GetStart(), aNewPaM ) ); >+} >+ >+sal_Bool TextUndoInsertChars::Merge( SfxUndoAction* pNextAction ) >+{ >+ if ( !pNextAction->ISA( TextUndoInsertChars ) ) >+ return sal_False; >+ >+ TextUndoInsertChars* pNext = (TextUndoInsertChars*)pNextAction; >+ >+ if ( maTextPaM.GetPara() != pNext->maTextPaM.GetPara() ) >+ return sal_False; >+ >+ if ( ( maTextPaM.GetIndex() + maText.Len() ) == pNext->maTextPaM.GetIndex() ) >+ { >+ maText += pNext->maText; >+ return sal_True; >+ } >+ return sal_False; >+} >+ >+ >+TextUndoRemoveChars::TextUndoRemoveChars( TextEngine* pTextEngine, const TextPaM& rTextPaM, const XubString& rStr ) >+ : TextUndo( pTextEngine ), >+ maTextPaM( rTextPaM ), maText( rStr ) >+{ >+} >+ >+void TextUndoRemoveChars::Undo() >+{ >+ TextSelection aSel( maTextPaM, maTextPaM ); >+ GetTextEngine()->ImpInsertText( aSel, maText ); >+ aSel.GetEnd().GetIndex() = aSel.GetEnd().GetIndex() + maText.Len(); >+ SetSelection( aSel ); >+} >+ >+void TextUndoRemoveChars::Redo() >+{ >+ TextSelection aSel( maTextPaM, maTextPaM ); >+ aSel.GetEnd().GetIndex() = aSel.GetEnd().GetIndex() + maText.Len(); >+ TextPaM aPaM = GetTextEngine()->ImpDeleteText( aSel ); >+ SetSelection( aPaM ); >+} >+ >+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/vcl/source/edit/textundo.hxx b/vcl/source/edit/textundo.hxx >new file mode 100644 >index 0000000..f86f877 >--- /dev/null >+++ b/vcl/source/edit/textundo.hxx >@@ -0,0 +1,85 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >+/************************************************************************* >+ * >+ * 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 _TEXTUNDO_HXX >+#define _TEXTUNDO_HXX >+ >+#include <svl/undo.hxx> >+ >+class TextEngine; >+ >+class TextUndoManager : public SfxUndoManager >+{ >+ TextEngine* mpTextEngine; >+ >+protected: >+ >+ void UndoRedoStart(); >+ void UndoRedoEnd(); >+ >+ TextView* GetView() const { return mpTextEngine->GetActiveView(); } >+ >+public: >+ TextUndoManager( TextEngine* pTextEngine ); >+ ~TextUndoManager(); >+ >+ using SfxUndoManager::Undo; >+ virtual sal_Bool Undo(); >+ using SfxUndoManager::Redo; >+ virtual sal_Bool Redo(); >+ >+}; >+ >+class TextUndo : public SfxUndoAction >+{ >+private: >+ TextEngine* mpTextEngine; >+ >+protected: >+ >+ TextView* GetView() const { return mpTextEngine->GetActiveView(); } >+ void SetSelection( const TextSelection& rSel ); >+ >+ TextDoc* GetDoc() const { return mpTextEngine->mpDoc; } >+ TEParaPortions* GetTEParaPortions() const { return mpTextEngine->mpTEParaPortions; } >+ >+public: >+ TYPEINFO(); >+ TextUndo( TextEngine* pTextEngine ); >+ virtual ~TextUndo(); >+ >+ TextEngine* GetTextEngine() const { return mpTextEngine; } >+ >+ virtual void Undo() = 0; >+ virtual void Redo() = 0; >+ >+ virtual rtl::OUString GetComment() const; >+}; >+ >+#endif // _TEXTUNDO_HXX >+ >+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/vcl/source/edit/textview.cxx b/vcl/source/edit/textview.cxx >new file mode 100644 >index 0000000..045fb30 >--- /dev/null >+++ b/vcl/source/edit/textview.cxx >@@ -0,0 +1,2378 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >+/************************************************************************* >+ * >+ * 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 <vcl/textview.hxx> >+#include <vcl/texteng.hxx> >+#include <textdoc.hxx> >+#include <vcl/textdata.hxx> >+#include <textdat2.hxx> >+ >+#include <svl/undo.hxx> >+#include <vcl/cursor.hxx> >+#include <vcl/window.hxx> >+#include <vcl/svapp.hxx> >+#include <tools/stream.hxx> >+ >+#include <sot/formats.hxx> >+#include <svl/urlbmk.hxx> >+ >+#include <com/sun/star/i18n/XBreakIterator.hpp> >+ >+#include <com/sun/star/i18n/CharacterIteratorMode.hpp> >+ >+#include <com/sun/star/i18n/WordType.hpp> >+#include <cppuhelper/weak.hxx> >+#include <vcl/unohelp.hxx> >+#include <com/sun/star/datatransfer/XTransferable.hpp> >+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp> >+#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp> >+#include <com/sun/star/lang/XMultiServiceFactory.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 <vcl/edit.hxx> >+ >+ >+#include <sot/exchange.hxx> >+ >+#include <osl/mutex.hxx> >+ >+ >+using namespace ::com::sun::star; >+ >+class TETextDataObject : public ::com::sun::star::datatransfer::XTransferable, >+ public ::cppu::OWeakObject >+ >+{ >+private: >+ String maText; >+ SvMemoryStream maHTMLStream; >+ >+public: >+ TETextDataObject( const String& rText ); >+ ~TETextDataObject(); >+ >+ String& GetText() { return maText; } >+ SvMemoryStream& GetHTMLStream() { return maHTMLStream; } >+ >+ // ::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); >+}; >+ >+TETextDataObject::TETextDataObject( const String& rText ) : maText( rText ) >+{ >+} >+ >+TETextDataObject::~TETextDataObject() >+{ >+} >+ >+// uno::XInterface >+uno::Any TETextDataObject::queryInterface( const uno::Type & rType ) throw(uno::RuntimeException) >+{ >+ uno::Any aRet = ::cppu::queryInterface( rType, (static_cast< datatransfer::XTransferable* >(this)) ); >+ return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType )); >+} >+ >+// datatransfer::XTransferable >+uno::Any TETextDataObject::getTransferData( const datatransfer::DataFlavor& rFlavor ) throw(datatransfer::UnsupportedFlavorException, io::IOException, uno::RuntimeException) >+{ >+ uno::Any aAny; >+ >+ sal_uLong nT = SotExchange::GetFormat( rFlavor ); >+ if ( nT == SOT_FORMAT_STRING ) >+ { >+ aAny <<= (::rtl::OUString)GetText(); >+ } >+ else if ( nT == SOT_FORMATSTR_ID_HTML ) >+ { >+ GetHTMLStream().Seek( STREAM_SEEK_TO_END ); >+ sal_uLong nLen = GetHTMLStream().Tell(); >+ GetHTMLStream().Seek(0); >+ >+ uno::Sequence< sal_Int8 > aSeq( nLen ); >+ memcpy( aSeq.getArray(), GetHTMLStream().GetData(), nLen ); >+ aAny <<= aSeq; >+ } >+ else >+ { >+ throw datatransfer::UnsupportedFlavorException(); >+ } >+ return aAny; >+} >+ >+uno::Sequence< datatransfer::DataFlavor > TETextDataObject::getTransferDataFlavors( ) throw(uno::RuntimeException) >+{ >+ GetHTMLStream().Seek( STREAM_SEEK_TO_END ); >+ sal_Bool bHTML = GetHTMLStream().Tell() > 0; >+ uno::Sequence< datatransfer::DataFlavor > aDataFlavors( bHTML ? 2 : 1 ); >+ SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aDataFlavors.getArray()[0] ); >+ if ( bHTML ) >+ SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_HTML, aDataFlavors.getArray()[1] ); >+ return aDataFlavors; >+} >+ >+sal_Bool TETextDataObject::isDataFlavorSupported( const datatransfer::DataFlavor& rFlavor ) throw(uno::RuntimeException) >+{ >+ sal_uLong nT = SotExchange::GetFormat( rFlavor ); >+ return ( nT == SOT_FORMAT_STRING ); >+} >+ >+struct ImpTextView >+{ >+ TextEngine* mpTextEngine; >+ >+ Window* mpWindow; >+ TextSelection maSelection; >+ Point maStartDocPos; >+// TextPaM maMBDownPaM; >+ >+ Cursor* mpCursor; >+ >+ TextDDInfo* mpDDInfo; >+ >+ VirtualDevice* mpVirtDev; >+ >+ SelectionEngine* mpSelEngine; >+ TextSelFunctionSet* mpSelFuncSet; >+ >+ ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::dnd::XDragSourceListener > mxDnDListener; >+ >+ sal_uInt16 mnTravelXPos; >+ >+ sal_Bool mbAutoScroll : 1; >+ sal_Bool mbInsertMode : 1; >+ sal_Bool mbReadOnly : 1; >+ sal_Bool mbPaintSelection : 1; >+ sal_Bool mbAutoIndent : 1; >+ sal_Bool mbHighlightSelection : 1; >+ sal_Bool mbCursorEnabled : 1; >+ sal_Bool mbClickedInSelection : 1; >+ sal_Bool mbSupportProtectAttribute : 1; >+ bool mbCursorAtEndOfLine; >+}; >+ >+// ------------------------------------------------------------------------- >+// (+) class TextView >+// ------------------------------------------------------------------------- >+TextView::TextView( TextEngine* pEng, Window* pWindow ) : >+ mpImpl(new ImpTextView) >+{ >+ pWindow->EnableRTL( sal_False ); >+ >+ mpImpl->mpWindow = pWindow; >+ mpImpl->mpTextEngine = pEng; >+ mpImpl->mpVirtDev = NULL; >+ >+ mpImpl->mbPaintSelection = sal_True; >+ mpImpl->mbAutoScroll = sal_True; >+ mpImpl->mbInsertMode = sal_True; >+ mpImpl->mbReadOnly = sal_False; >+ mpImpl->mbHighlightSelection = sal_False; >+ mpImpl->mbAutoIndent = sal_False; >+ mpImpl->mbCursorEnabled = sal_True; >+ mpImpl->mbClickedInSelection = sal_False; >+ mpImpl->mbSupportProtectAttribute = sal_False; >+ mpImpl->mbCursorAtEndOfLine = false; >+// mbInSelection = sal_False; >+ >+ mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW; >+ >+ mpImpl->mpSelFuncSet = new TextSelFunctionSet( this ); >+ mpImpl->mpSelEngine = new SelectionEngine( mpImpl->mpWindow, mpImpl->mpSelFuncSet ); >+ mpImpl->mpSelEngine->SetSelectionMode( RANGE_SELECTION ); >+ mpImpl->mpSelEngine->EnableDrag( sal_True ); >+ >+ mpImpl->mpCursor = new Cursor; >+ mpImpl->mpCursor->Show(); >+ pWindow->SetCursor( mpImpl->mpCursor ); >+ pWindow->SetInputContext( InputContext( pEng->GetFont(), INPUTCONTEXT_TEXT|INPUTCONTEXT_EXTTEXTINPUT ) ); >+ >+ if ( pWindow->GetSettings().GetStyleSettings().GetSelectionOptions() & SELECTION_OPTION_INVERT ) >+ mpImpl->mbHighlightSelection = sal_True; >+ >+ pWindow->SetLineColor(); >+ >+ mpImpl->mpDDInfo = NULL; >+ >+ if ( pWindow->GetDragGestureRecognizer().is() ) >+ { >+ vcl::unohelper::DragAndDropWrapper* pDnDWrapper = new vcl::unohelper::DragAndDropWrapper( this ); >+ mpImpl->mxDnDListener = pDnDWrapper; >+ >+ uno::Reference< datatransfer::dnd::XDragGestureListener> xDGL( mpImpl->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 ); >+ } >+} >+ >+TextView::~TextView() >+{ >+ delete mpImpl->mpSelEngine; >+ delete mpImpl->mpSelFuncSet; >+ delete mpImpl->mpVirtDev; >+ >+ if ( mpImpl->mpWindow->GetCursor() == mpImpl->mpCursor ) >+ mpImpl->mpWindow->SetCursor( 0 ); >+ delete mpImpl->mpCursor; >+ delete mpImpl->mpDDInfo; >+ delete mpImpl; >+} >+ >+void TextView::Invalidate() >+{ >+ mpImpl->mpWindow->Invalidate(); >+} >+ >+void TextView::SetSelection( const TextSelection& rTextSel, sal_Bool bGotoCursor ) >+{ >+ // Falls jemand gerade ein leeres Attribut hinterlassen hat, >+ // und dann der Outliner die Selektion manipulitert: >+ if ( !mpImpl->maSelection.HasRange() ) >+ mpImpl->mpTextEngine->CursorMoved( mpImpl->maSelection.GetStart().GetPara() ); >+ >+ // Wenn nach einem KeyInput die Selection manipuliert wird: >+ mpImpl->mpTextEngine->CheckIdleFormatter(); >+ >+ HideSelection(); >+ TextSelection aNewSel( rTextSel ); >+ mpImpl->mpTextEngine->ValidateSelection( aNewSel ); >+ ImpSetSelection( aNewSel ); >+ ShowSelection(); >+ ShowCursor( bGotoCursor ); >+} >+ >+void TextView::SetSelection( const TextSelection& rTextSel ) >+{ >+ SetSelection( rTextSel, mpImpl->mbAutoScroll ); >+} >+ >+const TextSelection& TextView::GetSelection() const >+{ >+ return mpImpl->maSelection; >+} >+TextSelection& TextView::GetSelection() >+{ >+ return mpImpl->maSelection; >+} >+ >+void TextView::DeleteSelected() >+{ >+// HideSelection(); >+ >+ mpImpl->mpTextEngine->UndoActionStart(); >+ TextPaM aPaM = mpImpl->mpTextEngine->ImpDeleteText( mpImpl->maSelection ); >+ mpImpl->mpTextEngine->UndoActionEnd(); >+ >+ ImpSetSelection( aPaM ); >+ mpImpl->mpTextEngine->FormatAndUpdate( this ); >+ ShowCursor(); >+} >+ >+void TextView::ImpPaint( OutputDevice* pOut, const Point& rStartPos, Rectangle const* pPaintArea, TextSelection const* pPaintRange, TextSelection const* pSelection ) >+{ >+ if ( !mpImpl->mbPaintSelection ) >+ pSelection = NULL; >+ else >+ { >+ // Richtige Hintergrundfarbe einstellen. >+ // Ich bekomme leider nicht mit, ob sich diese inzwischen geaendert hat. >+ Font aFont = mpImpl->mpTextEngine->GetFont(); >+ Color aColor = pOut->GetBackground().GetColor(); >+ aColor.SetTransparency( 0 ); >+ if ( aColor != aFont.GetFillColor() ) >+ { >+ if( aFont.IsTransparent() ) >+ aColor = Color( COL_TRANSPARENT ); >+ aFont.SetFillColor( aColor ); >+ mpImpl->mpTextEngine->maFont = aFont; >+ } >+ } >+ >+ mpImpl->mpTextEngine->ImpPaint( pOut, rStartPos, pPaintArea, pPaintRange, pSelection ); >+} >+ >+void TextView::Paint( const Rectangle& rRect ) >+{ >+ ImpPaint( rRect, sal_False ); >+} >+ >+void TextView::ImpPaint( const Rectangle& rRect, sal_Bool bUseVirtDev ) >+{ >+ if ( !mpImpl->mpTextEngine->GetUpdateMode() || mpImpl->mpTextEngine->IsInUndo() ) >+ return; >+ >+ TextSelection *pDrawSelection = NULL; >+ if ( !mpImpl->mbHighlightSelection && mpImpl->maSelection.HasRange() ) >+ pDrawSelection = &mpImpl->maSelection; >+ >+ if ( bUseVirtDev ) >+ { >+ VirtualDevice* pVDev = GetVirtualDevice(); >+ >+ const Color& rBackgroundColor = mpImpl->mpWindow->GetBackground().GetColor(); >+ if ( pVDev->GetFillColor() != rBackgroundColor ) >+ pVDev->SetFillColor( rBackgroundColor ); >+ if ( pVDev->GetBackground().GetColor() != rBackgroundColor ) >+ pVDev->SetBackground( rBackgroundColor ); >+ >+ sal_Bool bVDevValid = sal_True; >+ Size aOutSz( pVDev->GetOutputSizePixel() ); >+ if ( ( aOutSz.Width() < rRect.GetWidth() ) || >+ ( aOutSz.Height() < rRect.GetHeight() ) ) >+ { >+ bVDevValid = pVDev->SetOutputSizePixel( rRect.GetSize() ); >+ } >+ else >+ { >+ // Das VirtDev kann bei einem Resize sehr gross werden => >+ // irgendwann mal kleiner machen! >+ if ( ( aOutSz.Height() > ( rRect.GetHeight() + 20 ) ) || >+ ( aOutSz.Width() > ( rRect.GetWidth() + 20 ) ) ) >+ { >+ bVDevValid = pVDev->SetOutputSizePixel( rRect.GetSize() ); >+ } >+ else >+ { >+ pVDev->Erase(); >+ } >+ } >+ if ( !bVDevValid ) >+ { >+ ImpPaint( rRect, sal_False /* ohne VDev */ ); >+ return; >+ } >+ >+ Rectangle aTmpRec( Point( 0, 0 ), rRect.GetSize() ); >+ >+ Point aDocPos( mpImpl->maStartDocPos.X(), mpImpl->maStartDocPos.Y() + rRect.Top() ); >+ Point aStartPos = ImpGetOutputStartPos( aDocPos ); >+ ImpPaint( pVDev, aStartPos, &aTmpRec, NULL, pDrawSelection ); >+ mpImpl->mpWindow->DrawOutDev( rRect.TopLeft(), rRect.GetSize(), >+ Point(0,0), rRect.GetSize(), *pVDev ); >+// ShowSelection(); >+ if ( mpImpl->mbHighlightSelection ) >+ ImpHighlight( mpImpl->maSelection ); >+ } >+ else >+ { >+ Point aStartPos = ImpGetOutputStartPos( mpImpl->maStartDocPos ); >+ ImpPaint( mpImpl->mpWindow, aStartPos, &rRect, NULL, pDrawSelection ); >+ >+// ShowSelection(); >+ if ( mpImpl->mbHighlightSelection ) >+ ImpHighlight( mpImpl->maSelection ); >+ } >+} >+ >+void TextView::ImpHighlight( const TextSelection& rSel ) >+{ >+ TextSelection aSel( rSel ); >+ aSel.Justify(); >+ if ( aSel.HasRange() && !mpImpl->mpTextEngine->IsInUndo() && mpImpl->mpTextEngine->GetUpdateMode() ) >+ { >+ mpImpl->mpCursor->Hide(); >+ >+ DBG_ASSERT( !mpImpl->mpTextEngine->mpIdleFormatter->IsActive(), "ImpHighlight: Not formatted!" ); >+ >+ Rectangle aVisArea( mpImpl->maStartDocPos, mpImpl->mpWindow->GetOutputSizePixel() ); >+ long nY = 0; >+ sal_uLong nStartPara = aSel.GetStart().GetPara(); >+ sal_uLong nEndPara = aSel.GetEnd().GetPara(); >+ for ( sal_uLong nPara = 0; nPara <= nEndPara; nPara++ ) >+ { >+ long nParaHeight = (long)mpImpl->mpTextEngine->CalcParaHeight( nPara ); >+ if ( ( nPara >= nStartPara ) && ( ( nY + nParaHeight ) > aVisArea.Top() ) ) >+ { >+ TEParaPortion* pTEParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( nPara ); >+ sal_uInt16 nStartLine = 0; >+ sal_uInt16 nEndLine = pTEParaPortion->GetLines().size() -1; >+ if ( nPara == nStartPara ) >+ nStartLine = pTEParaPortion->GetLineNumber( aSel.GetStart().GetIndex(), sal_False ); >+ if ( nPara == nEndPara ) >+ nEndLine = pTEParaPortion->GetLineNumber( aSel.GetEnd().GetIndex(), sal_True ); >+ >+ // ueber die Zeilen iterieren.... >+ for ( sal_uInt16 nLine = nStartLine; nLine <= nEndLine; nLine++ ) >+ { >+ TextLine* pLine = pTEParaPortion->GetLines()[ nLine ]; >+ sal_uInt16 nStartIndex = pLine->GetStart(); >+ sal_uInt16 nEndIndex = pLine->GetEnd(); >+ if ( ( nPara == nStartPara ) && ( nLine == nStartLine ) ) >+ nStartIndex = aSel.GetStart().GetIndex(); >+ if ( ( nPara == nEndPara ) && ( nLine == nEndLine ) ) >+ nEndIndex = aSel.GetEnd().GetIndex(); >+ >+ // Kann passieren, wenn am Anfang einer umgebrochenen Zeile. >+ if ( nEndIndex < nStartIndex ) >+ nEndIndex = nStartIndex; >+ >+ Rectangle aTmpRec( mpImpl->mpTextEngine->GetEditCursor( TextPaM( nPara, nStartIndex ), sal_False ) ); >+ aTmpRec.Top() += nY; >+ aTmpRec.Bottom() += nY; >+ Point aTopLeft( aTmpRec.TopLeft() ); >+ >+ aTmpRec = mpImpl->mpTextEngine->GetEditCursor( TextPaM( nPara, nEndIndex ), sal_True ); >+ aTmpRec.Top() += nY; >+ aTmpRec.Bottom() += nY; >+ Point aBottomRight( aTmpRec.BottomRight() ); >+ aBottomRight.X()--; >+ >+ // Nur Painten, wenn im sichtbaren Bereich... >+ if ( ( aTopLeft.X() < aBottomRight.X() ) && ( aBottomRight.Y() >= aVisArea.Top() ) ) >+ { >+ Point aPnt1( GetWindowPos( aTopLeft ) ); >+ Point aPnt2( GetWindowPos( aBottomRight ) ); >+ >+ Rectangle aRect( aPnt1, aPnt2 ); >+ mpImpl->mpWindow->Invert( aRect ); >+ } >+ } >+ } >+ nY += nParaHeight; >+ >+ if ( nY >= aVisArea.Bottom() ) >+ break; >+ } >+ } >+} >+ >+void TextView::ImpSetSelection( const TextSelection& rSelection ) >+{ >+ if ( rSelection != mpImpl->maSelection ) >+ { >+ mpImpl->maSelection = rSelection; >+ mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_VIEWSELECTIONCHANGED ) ); >+ } >+} >+ >+void TextView::ShowSelection() >+{ >+ ImpShowHideSelection( sal_True ); >+} >+ >+void TextView::HideSelection() >+{ >+ ImpShowHideSelection( sal_False ); >+} >+ >+void TextView::ShowSelection( const TextSelection& rRange ) >+{ >+ ImpShowHideSelection( sal_True, &rRange ); >+} >+ >+void TextView::ImpShowHideSelection( sal_Bool bShow, const TextSelection* pRange ) >+{ >+ const TextSelection* pRangeOrSelection = pRange ? pRange : &mpImpl->maSelection; >+ >+ if ( pRangeOrSelection->HasRange() ) >+ { >+ if ( mpImpl->mbHighlightSelection ) >+ { >+ ImpHighlight( *pRangeOrSelection ); >+ } >+ else >+ { >+ if( mpImpl->mpWindow->IsPaintTransparent() ) >+ mpImpl->mpWindow->Invalidate(); >+ else >+ { >+ Rectangle aOutArea( Point( 0, 0 ), mpImpl->mpWindow->GetOutputSizePixel() ); >+ Point aStartPos( ImpGetOutputStartPos( mpImpl->maStartDocPos ) ); >+ TextSelection aRange( *pRangeOrSelection ); >+ aRange.Justify(); >+ sal_Bool bVisCursor = mpImpl->mpCursor->IsVisible(); >+ mpImpl->mpCursor->Hide(); >+ ImpPaint( mpImpl->mpWindow, aStartPos, &aOutArea, &aRange, bShow ? &mpImpl->maSelection : NULL ); >+ if ( bVisCursor ) >+ mpImpl->mpCursor->Show(); >+ } >+ } >+ } >+} >+ >+VirtualDevice* TextView::GetVirtualDevice() >+{ >+ if ( !mpImpl->mpVirtDev ) >+ { >+ mpImpl->mpVirtDev = new VirtualDevice; >+ mpImpl->mpVirtDev->SetLineColor(); >+ } >+ return mpImpl->mpVirtDev; >+} >+ >+void TextView::EraseVirtualDevice() >+{ >+ delete mpImpl->mpVirtDev; >+ mpImpl->mpVirtDev = 0; >+} >+ >+sal_Bool TextView::KeyInput( const KeyEvent& rKeyEvent ) >+{ >+ sal_Bool bDone = sal_True; >+ sal_Bool bModified = sal_False; >+ sal_Bool bMoved = sal_False; >+ sal_Bool bEndKey = sal_False; // spezielle CursorPosition >+ sal_Bool bAllowIdle = sal_True; >+ >+ // Um zu pruefen ob durch irgendeine Aktion mModified, das lokale >+ // bModified wird z.B. bei Cut/Paste nicht gesetzt, weil dort an anderen >+ // Stellen das updaten erfolgt. >+ sal_Bool bWasModified = mpImpl->mpTextEngine->IsModified(); >+ mpImpl->mpTextEngine->SetModified( sal_False ); >+ >+ TextSelection aCurSel( mpImpl->maSelection ); >+ TextSelection aOldSel( aCurSel ); >+ >+ sal_uInt16 nCode = rKeyEvent.GetKeyCode().GetCode(); >+ KeyFuncType eFunc = rKeyEvent.GetKeyCode().GetFunction(); >+ if ( eFunc != KEYFUNC_DONTKNOW ) >+ { >+ switch ( eFunc ) >+ { >+ case KEYFUNC_CUT: >+ { >+ if ( !mpImpl->mbReadOnly ) >+ Cut(); >+ } >+ break; >+ case KEYFUNC_COPY: >+ { >+ Copy(); >+ } >+ break; >+ case KEYFUNC_PASTE: >+ { >+ if ( !mpImpl->mbReadOnly ) >+ Paste(); >+ } >+ break; >+ case KEYFUNC_UNDO: >+ { >+ if ( !mpImpl->mbReadOnly ) >+ Undo(); >+ } >+ break; >+ case KEYFUNC_REDO: >+ { >+ if ( !mpImpl->mbReadOnly ) >+ Redo(); >+ } >+ break; >+ >+ default: // wird dann evtl. unten bearbeitet. >+ eFunc = KEYFUNC_DONTKNOW; >+ } >+ } >+ if ( eFunc == KEYFUNC_DONTKNOW ) >+ { >+ switch ( nCode ) >+ { >+ 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 ) ) >+ && !( rKeyEvent.GetKeyCode().IsMod1() && ( nCode == KEY_PAGEUP || nCode == KEY_PAGEDOWN ) ) ) >+ { >+ aCurSel = ImpMoveCursor( rKeyEvent ); >+ if ( aCurSel.HasRange() ) { >+ uno::Reference<datatransfer::clipboard::XClipboard> aSelection(GetWindow()->GetPrimarySelection()); >+ Copy( aSelection ); >+ } >+ bMoved = sal_True; >+ if ( nCode == KEY_END ) >+ bEndKey = sal_True; >+ } >+ else >+ bDone = sal_False; >+ } >+ 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_LINE: >+ case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE: >+ { >+ if ( !mpImpl->mbReadOnly && !rKeyEvent.GetKeyCode().IsMod2() ) >+ { >+ sal_uInt8 nDel = ( nCode == KEY_DELETE ) ? DEL_RIGHT : DEL_LEFT; >+ sal_uInt8 nMode = rKeyEvent.GetKeyCode().IsMod1() ? DELMODE_RESTOFWORD : DELMODE_SIMPLE; >+ if ( ( nMode == DELMODE_RESTOFWORD ) && rKeyEvent.GetKeyCode().IsShift() ) >+ nMode = DELMODE_RESTOFCONTENT; >+ >+ switch( nCode ) >+ { >+ case com::sun::star::awt::Key::DELETE_WORD_BACKWARD: >+ nDel = DEL_LEFT; >+ nMode = DELMODE_RESTOFWORD; >+ break; >+ case com::sun::star::awt::Key::DELETE_WORD_FORWARD: >+ nDel = DEL_RIGHT; >+ nMode = DELMODE_RESTOFWORD; >+ break; >+ case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE: >+ nDel = DEL_LEFT; >+ nMode = DELMODE_RESTOFCONTENT; >+ break; >+ case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE: >+ nDel = DEL_RIGHT; >+ nMode = DELMODE_RESTOFCONTENT; >+ break; >+ default: break; >+ } >+ >+ mpImpl->mpTextEngine->UndoActionStart(); >+ if(mpImpl->mbSupportProtectAttribute) >+ { >+ //expand selection to include all protected content - if there is any >+ const TextCharAttrib* pStartAttr = mpImpl->mpTextEngine->FindCharAttrib( >+ TextPaM(mpImpl->maSelection.GetStart().GetPara(), >+ mpImpl->maSelection.GetStart().GetIndex()), >+ TEXTATTR_PROTECTED ); >+ const TextCharAttrib* pEndAttr = mpImpl->mpTextEngine->FindCharAttrib( >+ TextPaM(mpImpl->maSelection.GetEnd().GetPara(), >+ mpImpl->maSelection.GetEnd().GetIndex()), >+ TEXTATTR_PROTECTED ); >+ if(pStartAttr && pStartAttr->GetStart() < mpImpl->maSelection.GetStart().GetIndex()) >+ { >+ mpImpl->maSelection.GetStart().GetIndex() = pStartAttr->GetStart(); >+ } >+ if(pEndAttr && pEndAttr->GetEnd() > mpImpl->maSelection.GetEnd().GetIndex()) >+ { >+ mpImpl->maSelection.GetEnd().GetIndex() = pEndAttr->GetEnd(); >+ } >+ } >+ aCurSel = ImpDelete( nDel, nMode ); >+ mpImpl->mpTextEngine->UndoActionEnd(); >+ bModified = sal_True; >+ bAllowIdle = sal_False; >+ } >+ else >+ bDone = sal_False; >+ } >+ break; >+ case KEY_TAB: >+ { >+ if ( !mpImpl->mbReadOnly && !rKeyEvent.GetKeyCode().IsShift() && >+ !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() && >+ ImplCheckTextLen( rtl::OUString('x') ) ) >+ { >+ aCurSel = mpImpl->mpTextEngine->ImpInsertText( aCurSel, '\t', !IsInsertMode() ); >+ bModified = sal_True; >+ } >+ else >+ bDone = sal_False; >+ } >+ break; >+ case KEY_RETURN: >+ { >+ // Shift-RETURN darf nicht geschluckt werden, weil dann keine >+ // mehrzeilige Eingabe in Dialogen/Property-Editor moeglich. >+ if ( !mpImpl->mbReadOnly && !rKeyEvent.GetKeyCode().IsMod1() && >+ !rKeyEvent.GetKeyCode().IsMod2() && ImplCheckTextLen( rtl::OUString('x') ) ) >+ { >+ mpImpl->mpTextEngine->UndoActionStart(); >+ aCurSel = mpImpl->mpTextEngine->ImpInsertParaBreak( aCurSel ); >+ if ( mpImpl->mbAutoIndent ) >+ { >+ TextNode* pPrev = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aCurSel.GetEnd().GetPara() - 1 ); >+ sal_uInt16 n = 0; >+ while ( ( n < pPrev->GetText().Len() ) && ( >+ ( pPrev->GetText().GetChar( n ) == ' ' ) || >+ ( pPrev->GetText().GetChar( n ) == '\t' ) ) ) >+ { >+ n++; >+ } >+ if ( n ) >+ aCurSel = mpImpl->mpTextEngine->ImpInsertText( aCurSel, pPrev->GetText().Copy( 0, n ) ); >+ } >+ mpImpl->mpTextEngine->UndoActionEnd(); >+ bModified = sal_True; >+ } >+ else >+ bDone = sal_False; >+ } >+ break; >+ case KEY_INSERT: >+ { >+ if ( !mpImpl->mbReadOnly ) >+ SetInsertMode( !IsInsertMode() ); >+ } >+ break; >+ default: >+ { >+ if ( TextEngine::IsSimpleCharInput( rKeyEvent ) ) >+ { >+ xub_Unicode nCharCode = rKeyEvent.GetCharCode(); >+ if ( !mpImpl->mbReadOnly && ImplCheckTextLen( rtl::OUString(nCharCode) ) ) // sonst trotzdem das Zeichen schlucken... >+ { >+ aCurSel = mpImpl->mpTextEngine->ImpInsertText( nCharCode, aCurSel, !IsInsertMode(), sal_True ); >+ bModified = sal_True; >+ } >+ } >+ else >+ bDone = sal_False; >+ } >+ } >+ } >+ >+ if ( aCurSel != aOldSel ) // Check if changed, maybe other method already changed mpImpl->maSelection, don't overwrite that! >+ ImpSetSelection( aCurSel ); >+ >+ mpImpl->mpTextEngine->UpdateSelections(); >+ >+ if ( ( nCode != KEY_UP ) && ( nCode != KEY_DOWN ) ) >+ mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW; >+ >+ if ( bModified ) >+ { >+ // Idle-Formatter nur, wenn AnyInput. >+ if ( bAllowIdle && Application::AnyInput( VCL_INPUT_KEYBOARD) ) >+ mpImpl->mpTextEngine->IdleFormatAndUpdate( this ); >+ else >+ mpImpl->mpTextEngine->FormatAndUpdate( this); >+ } >+ else if ( bMoved ) >+ { >+ // Selection wird jetzt gezielt in ImpMoveCursor gemalt. >+ ImpShowCursor( mpImpl->mbAutoScroll, sal_True, bEndKey ); >+ } >+ >+ if ( mpImpl->mpTextEngine->IsModified() ) >+ mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) ); >+ else if ( bWasModified ) >+ mpImpl->mpTextEngine->SetModified( sal_True ); >+ >+ return bDone; >+} >+ >+void TextView::MouseButtonUp( const MouseEvent& rMouseEvent ) >+{ >+ mpImpl->mbClickedInSelection = sal_False; >+ mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW; >+ mpImpl->mpSelEngine->SelMouseButtonUp( rMouseEvent ); >+ if ( rMouseEvent.IsMiddle() && !IsReadOnly() && >+ ( GetWindow()->GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION ) ) >+ { >+ uno::Reference<datatransfer::clipboard::XClipboard> aSelection(GetWindow()->GetPrimarySelection()); >+ Paste( aSelection ); >+ if ( mpImpl->mpTextEngine->IsModified() ) >+ mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) ); >+ } >+ else if ( rMouseEvent.IsLeft() && GetSelection().HasRange() ) >+ { >+ uno::Reference<datatransfer::clipboard::XClipboard> aSelection(GetWindow()->GetPrimarySelection()); >+ Copy( aSelection ); >+ } >+} >+ >+void TextView::MouseButtonDown( const MouseEvent& rMouseEvent ) >+{ >+ mpImpl->mpTextEngine->CheckIdleFormatter(); // Falls schnelles Tippen und MouseButtonDown >+ mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW; >+ mpImpl->mbClickedInSelection = IsSelectionAtPoint( rMouseEvent.GetPosPixel() ); >+ >+ mpImpl->mpTextEngine->SetActiveView( this ); >+ >+ mpImpl->mpSelEngine->SelMouseButtonDown( rMouseEvent ); >+ >+ // mbu 20.01.2005 - SelMouseButtonDown() possibly triggers a 'selection changed' >+ // notification. The appropriate handler could change the current selection, >+ // which is the case in the MailMerge address block control. To enable select'n'drag >+ // we need to reevaluate the selection after the notification has been fired. >+ mpImpl->mbClickedInSelection = IsSelectionAtPoint( rMouseEvent.GetPosPixel() ); >+ >+ // Sonderbehandlungen >+ if ( !rMouseEvent.IsShift() && ( rMouseEvent.GetClicks() >= 2 ) ) >+ { >+ if ( rMouseEvent.IsMod2() ) >+ { >+ HideSelection(); >+ ImpSetSelection( mpImpl->maSelection.GetEnd() ); >+ SetCursorAtPoint( rMouseEvent.GetPosPixel() ); // Wird von SelectionEngine bei MOD2 nicht gesetzt >+ } >+ >+ if ( rMouseEvent.GetClicks() == 2 ) >+ { >+ // Wort selektieren >+ if ( mpImpl->maSelection.GetEnd().GetIndex() < mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection.GetEnd().GetPara() ) ) >+ { >+ HideSelection(); >+ TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( mpImpl->maSelection.GetEnd().GetPara() ); >+ uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator(); >+ i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True ); >+ TextSelection aNewSel( mpImpl->maSelection ); >+ aNewSel.GetStart().GetIndex() = (sal_uInt16)aBoundary.startPos; >+ aNewSel.GetEnd().GetIndex() = (sal_uInt16)aBoundary.endPos; >+ if(mpImpl->mbSupportProtectAttribute) >+ { >+ //expand selection to include all protected content - if there is any >+ const TextCharAttrib* pStartAttr = mpImpl->mpTextEngine->FindCharAttrib( >+ TextPaM(aNewSel.GetStart().GetPara(), >+ (sal_uInt16)aBoundary.startPos), >+ TEXTATTR_PROTECTED ); >+ const TextCharAttrib* pEndAttr = mpImpl->mpTextEngine->FindCharAttrib( >+ TextPaM(aNewSel.GetEnd().GetPara(), >+ (sal_uInt16)aBoundary.endPos), >+ TEXTATTR_PROTECTED ); >+ if(pStartAttr && pStartAttr->GetStart() < aNewSel.GetStart().GetIndex()) >+ { >+ aNewSel.GetStart().GetIndex() = pStartAttr->GetStart(); >+ } >+ if(pEndAttr && pEndAttr->GetEnd() > aNewSel.GetEnd().GetIndex()) >+ { >+ aNewSel.GetEnd().GetIndex() = pEndAttr->GetEnd(); >+ } >+ } >+ ImpSetSelection( aNewSel ); >+ ShowSelection(); >+ ShowCursor( sal_True, sal_True ); >+ } >+ } >+ else if ( rMouseEvent.GetClicks() == 3 ) >+ { >+ // Absatz selektieren >+ if ( mpImpl->maSelection.GetStart().GetIndex() || ( mpImpl->maSelection.GetEnd().GetIndex() < mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection.GetEnd().GetPara() ) ) ) >+ { >+ HideSelection(); >+ TextSelection aNewSel( mpImpl->maSelection ); >+ aNewSel.GetStart().GetIndex() = 0; >+ aNewSel.GetEnd().GetIndex() = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( mpImpl->maSelection.GetEnd().GetPara() )->GetText().Len(); >+ ImpSetSelection( aNewSel ); >+ ShowSelection(); >+ ShowCursor( sal_True, sal_True ); >+ } >+ } >+ } >+} >+ >+ >+void TextView::MouseMove( const MouseEvent& rMouseEvent ) >+{ >+ mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW; >+ mpImpl->mpSelEngine->SelMouseMove( rMouseEvent ); >+} >+ >+void TextView::Command( const CommandEvent& rCEvt ) >+{ >+ mpImpl->mpTextEngine->CheckIdleFormatter(); // Falls schnelles Tippen und MouseButtonDown >+ mpImpl->mpTextEngine->SetActiveView( this ); >+ >+ if ( rCEvt.GetCommand() == COMMAND_STARTEXTTEXTINPUT ) >+ { >+ DeleteSelected(); >+ delete mpImpl->mpTextEngine->mpIMEInfos; >+ TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( GetSelection().GetEnd().GetPara() ); >+ mpImpl->mpTextEngine->mpIMEInfos = new TEIMEInfos( GetSelection().GetEnd(), pNode->GetText().Copy( GetSelection().GetEnd().GetIndex() ) ); >+ mpImpl->mpTextEngine->mpIMEInfos->bWasCursorOverwrite = !IsInsertMode(); >+ } >+ else if ( rCEvt.GetCommand() == COMMAND_ENDEXTTEXTINPUT ) >+ { >+ DBG_ASSERT( mpImpl->mpTextEngine->mpIMEInfos, "COMMAND_ENDEXTTEXTINPUT => Kein Start ?" ); >+ if( mpImpl->mpTextEngine->mpIMEInfos ) >+ { >+ TEParaPortion* pPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetPara() ); >+ pPortion->MarkSelectionInvalid( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetIndex(), 0 ); >+ >+ sal_Bool bInsertMode = !mpImpl->mpTextEngine->mpIMEInfos->bWasCursorOverwrite; >+ >+ delete mpImpl->mpTextEngine->mpIMEInfos; >+ mpImpl->mpTextEngine->mpIMEInfos = NULL; >+ >+ mpImpl->mpTextEngine->FormatAndUpdate( this ); >+ >+ SetInsertMode( bInsertMode ); >+ >+ if ( mpImpl->mpTextEngine->IsModified() ) >+ mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) ); >+ } >+ } >+ else if ( rCEvt.GetCommand() == COMMAND_EXTTEXTINPUT ) >+ { >+ DBG_ASSERT( mpImpl->mpTextEngine->mpIMEInfos, "COMMAND_EXTTEXTINPUT => Kein Start ?" ); >+ if( mpImpl->mpTextEngine->mpIMEInfos ) >+ { >+ const CommandExtTextInputData* pData = rCEvt.GetExtTextInputData(); >+ >+ if ( !pData->IsOnlyCursorChanged() ) >+ { >+ TextSelection aSelect( mpImpl->mpTextEngine->mpIMEInfos->aPos ); >+ aSelect.GetEnd().GetIndex() = aSelect.GetEnd().GetIndex() + mpImpl->mpTextEngine->mpIMEInfos->nLen; >+ aSelect = mpImpl->mpTextEngine->ImpDeleteText( aSelect ); >+ aSelect = mpImpl->mpTextEngine->ImpInsertText( aSelect, pData->GetText() ); >+ >+ if ( mpImpl->mpTextEngine->mpIMEInfos->bWasCursorOverwrite ) >+ { >+ sal_uInt16 nOldIMETextLen = mpImpl->mpTextEngine->mpIMEInfos->nLen; >+ sal_uInt16 nNewIMETextLen = pData->GetText().Len(); >+ >+ if ( ( nOldIMETextLen > nNewIMETextLen ) && >+ ( nNewIMETextLen < mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.Len() ) ) >+ { >+ // restore old characters >+ sal_uInt16 nRestore = nOldIMETextLen - nNewIMETextLen; >+ TextPaM aPaM( mpImpl->mpTextEngine->mpIMEInfos->aPos ); >+ aPaM.GetIndex() = aPaM.GetIndex() + nNewIMETextLen; >+ mpImpl->mpTextEngine->ImpInsertText( aPaM, mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.Copy( nNewIMETextLen, nRestore ) ); >+ } >+ else if ( ( nOldIMETextLen < nNewIMETextLen ) && >+ ( nOldIMETextLen < mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.Len() ) ) >+ { >+ // overwrite >+ sal_uInt16 nOverwrite = nNewIMETextLen - nOldIMETextLen; >+ if ( ( nOldIMETextLen + nOverwrite ) > mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.Len() ) >+ nOverwrite = mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.Len() - nOldIMETextLen; >+ DBG_ASSERT( nOverwrite && (nOverwrite < 0xFF00), "IME Overwrite?!" ); >+ TextPaM aPaM( mpImpl->mpTextEngine->mpIMEInfos->aPos ); >+ aPaM.GetIndex() = aPaM.GetIndex() + nNewIMETextLen; >+ TextSelection aSel( aPaM ); >+ aSel.GetEnd().GetIndex() = >+ aSel.GetEnd().GetIndex() + nOverwrite; >+ mpImpl->mpTextEngine->ImpDeleteText( aSel ); >+ } >+ } >+ >+ if ( pData->GetTextAttr() ) >+ { >+ mpImpl->mpTextEngine->mpIMEInfos->CopyAttribs( pData->GetTextAttr(), pData->GetText().Len() ); >+ mpImpl->mpTextEngine->mpIMEInfos->bCursor = pData->IsCursorVisible(); >+ } >+ else >+ { >+ mpImpl->mpTextEngine->mpIMEInfos->DestroyAttribs(); >+ } >+ >+ TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetPara() ); >+ pPPortion->MarkSelectionInvalid( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetIndex(), 0 ); >+ mpImpl->mpTextEngine->FormatAndUpdate( this ); >+ } >+ >+ TextSelection aNewSel = TextPaM( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetPara(), mpImpl->mpTextEngine->mpIMEInfos->aPos.GetIndex()+pData->GetCursorPos() ); >+ SetSelection( aNewSel ); >+ SetInsertMode( !pData->IsCursorOverwrite() ); >+ >+ if ( pData->IsCursorVisible() ) >+ ShowCursor(); >+ else >+ HideCursor(); >+ } >+ } >+ else if ( rCEvt.GetCommand() == COMMAND_CURSORPOS ) >+ { >+ if ( mpImpl->mpTextEngine->mpIMEInfos && mpImpl->mpTextEngine->mpIMEInfos->nLen ) >+ { >+ TextPaM aPaM( GetSelection().GetEnd() ); >+ Rectangle aR1 = mpImpl->mpTextEngine->PaMtoEditCursor( aPaM ); >+ >+ sal_uInt16 nInputEnd = mpImpl->mpTextEngine->mpIMEInfos->aPos.GetIndex() + mpImpl->mpTextEngine->mpIMEInfos->nLen; >+ >+ if ( !mpImpl->mpTextEngine->IsFormatted() ) >+ mpImpl->mpTextEngine->FormatDoc(); >+ >+ TEParaPortion* pParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() ); >+ sal_uInt16 nLine = pParaPortion->GetLineNumber( aPaM.GetIndex(), sal_True ); >+ TextLine* pLine = pParaPortion->GetLines()[ nLine ]; >+ if ( pLine && ( nInputEnd > pLine->GetEnd() ) ) >+ nInputEnd = pLine->GetEnd(); >+ Rectangle aR2 = mpImpl->mpTextEngine->PaMtoEditCursor( TextPaM( aPaM.GetPara(), nInputEnd ) ); >+ >+ long nWidth = aR2.Left()-aR1.Right(); >+ aR1.Move( -GetStartDocPos().X(), -GetStartDocPos().Y() ); >+ GetWindow()->SetCursorRect( &aR1, nWidth ); >+ } >+ else >+ { >+ GetWindow()->SetCursorRect(); >+ } >+ } >+ else >+ { >+ mpImpl->mpSelEngine->Command( rCEvt ); >+ } >+} >+ >+void TextView::ShowCursor( sal_Bool bGotoCursor, sal_Bool bForceVisCursor ) >+{ >+ // Die Einstellung hat mehr Gewicht: >+ if ( !mpImpl->mbAutoScroll ) >+ bGotoCursor = sal_False; >+ ImpShowCursor( bGotoCursor, bForceVisCursor, sal_False ); >+} >+ >+void TextView::HideCursor() >+{ >+ mpImpl->mpCursor->Hide(); >+} >+ >+void TextView::Scroll( long ndX, long ndY ) >+{ >+ DBG_ASSERT( mpImpl->mpTextEngine->IsFormatted(), "Scroll: Nicht formatiert!" ); >+ >+ if ( !ndX && !ndY ) >+ return; >+ >+ Point aNewStartPos( mpImpl->maStartDocPos ); >+ >+ // Vertical: >+ aNewStartPos.Y() -= ndY; >+ if ( aNewStartPos.Y() < 0 ) >+ aNewStartPos.Y() = 0; >+ >+ // Horizontal: >+ aNewStartPos.X() -= ndX; >+ if ( aNewStartPos.X() < 0 ) >+ aNewStartPos.X() = 0; >+ >+ long nDiffX = mpImpl->maStartDocPos.X() - aNewStartPos.X(); >+ long nDiffY = mpImpl->maStartDocPos.Y() - aNewStartPos.Y(); >+ >+ if ( nDiffX || nDiffY ) >+ { >+ sal_Bool bVisCursor = mpImpl->mpCursor->IsVisible(); >+ mpImpl->mpCursor->Hide(); >+ mpImpl->mpWindow->Update(); >+ mpImpl->maStartDocPos = aNewStartPos; >+ >+ if ( mpImpl->mpTextEngine->IsRightToLeft() ) >+ nDiffX = -nDiffX; >+ mpImpl->mpWindow->Scroll( nDiffX, nDiffY ); >+ mpImpl->mpWindow->Update(); >+ mpImpl->mpCursor->SetPos( mpImpl->mpCursor->GetPos() + Point( nDiffX, nDiffY ) ); >+ if ( bVisCursor && !mpImpl->mbReadOnly ) >+ mpImpl->mpCursor->Show(); >+ } >+ >+ mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_VIEWSCROLLED ) ); >+} >+ >+void TextView::Undo() >+{ >+ mpImpl->mpTextEngine->SetActiveView( this ); >+ mpImpl->mpTextEngine->GetUndoManager().Undo(); >+} >+ >+void TextView::Redo() >+{ >+ mpImpl->mpTextEngine->SetActiveView( this ); >+ mpImpl->mpTextEngine->GetUndoManager().Redo(); >+} >+ >+void TextView::Cut() >+{ >+ mpImpl->mpTextEngine->UndoActionStart(); >+ Copy(); >+ DeleteSelected(); >+ mpImpl->mpTextEngine->UndoActionEnd(); >+} >+ >+void TextView::Copy( uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard ) >+{ >+ if ( rxClipboard.is() ) >+ { >+ TETextDataObject* pDataObj = new TETextDataObject( GetSelected() ); >+ >+ if ( mpImpl->mpTextEngine->HasAttrib( TEXTATTR_HYPERLINK ) ) // Dann auch als HTML >+ mpImpl->mpTextEngine->Write( pDataObj->GetHTMLStream(), &mpImpl->maSelection, sal_True ); >+ >+ const sal_uInt32 nRef = Application::ReleaseSolarMutex(); >+ >+ try >+ { >+ rxClipboard->setContents( pDataObj, NULL ); >+ >+ 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 ); >+ } >+} >+ >+void TextView::Copy() >+{ >+ uno::Reference<datatransfer::clipboard::XClipboard> aClipboard(GetWindow()->GetClipboard()); >+ Copy( aClipboard ); >+} >+ >+void TextView::Paste( uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard ) >+{ >+ 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() ) >+ { >+ datatransfer::DataFlavor aFlavor; >+ SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor ); >+ if ( xDataObj->isDataFlavorSupported( aFlavor ) ) >+ { >+ try >+ { >+ uno::Any aData = xDataObj->getTransferData( aFlavor ); >+ ::rtl::OUString aText; >+ aData >>= aText; >+ bool bWasTruncated = false; >+ if( mpImpl->mpTextEngine->GetMaxTextLen() != 0 ) >+ bWasTruncated = ImplTruncateNewText( aText ); >+ InsertNewText( aText, sal_False ); >+ mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) ); >+ >+ if( bWasTruncated ) >+ Edit::ShowTruncationWarning( mpImpl->mpWindow ); >+ } >+ catch( const ::com::sun::star::datatransfer::UnsupportedFlavorException& ) >+ { >+ } >+ } >+ } >+ } >+} >+ >+void TextView::Paste() >+{ >+ uno::Reference<datatransfer::clipboard::XClipboard> aClipboard(GetWindow()->GetClipboard()); >+ Paste( aClipboard ); >+} >+ >+String TextView::GetSelected() >+{ >+ return GetSelected( GetSystemLineEnd() ); >+} >+ >+String TextView::GetSelected( LineEnd aSeparator ) >+{ >+ return mpImpl->mpTextEngine->GetText( mpImpl->maSelection, aSeparator ); >+} >+ >+void TextView::SetInsertMode( sal_Bool bInsert ) >+{ >+ if ( mpImpl->mbInsertMode != bInsert ) >+ { >+ mpImpl->mbInsertMode = bInsert; >+ ShowCursor( mpImpl->mbAutoScroll, sal_False ); >+ } >+} >+ >+void TextView::SetReadOnly( sal_Bool bReadOnly ) >+{ >+ if ( mpImpl->mbReadOnly != bReadOnly ) >+ { >+ mpImpl->mbReadOnly = bReadOnly; >+ if ( !mpImpl->mbReadOnly ) >+ ShowCursor( mpImpl->mbAutoScroll, sal_False ); >+ else >+ HideCursor(); >+ >+ GetWindow()->SetInputContext( InputContext( mpImpl->mpTextEngine->GetFont(), bReadOnly ? INPUTCONTEXT_TEXT|INPUTCONTEXT_EXTTEXTINPUT : 0 ) ); >+ } >+} >+ >+TextSelection TextView::ImpMoveCursor( const KeyEvent& rKeyEvent ) >+{ >+ // Eigentlich nur bei Up/Down noetig, aber was solls. >+ mpImpl->mpTextEngine->CheckIdleFormatter(); >+ >+ TextPaM aPaM( mpImpl->maSelection.GetEnd() ); >+ TextPaM aOldEnd( aPaM ); >+ >+ TextDirectionality eTextDirection = TextDirectionality_LeftToRight_TopToBottom; >+ if ( mpImpl->mpTextEngine->IsRightToLeft() ) >+ eTextDirection = TextDirectionality_RightToLeft_TopToBottom; >+ >+ KeyEvent aTranslatedKeyEvent = rKeyEvent.LogicalTextDirectionality( eTextDirection ); >+ >+ sal_Bool bCtrl = aTranslatedKeyEvent.GetKeyCode().IsMod1() ? sal_True : sal_False; >+ sal_uInt16 nCode = aTranslatedKeyEvent.GetKeyCode().GetCode(); >+ >+ bool bSelect = aTranslatedKeyEvent.GetKeyCode().IsShift(); >+ switch ( nCode ) >+ { >+ case KEY_UP: aPaM = CursorUp( aPaM ); >+ break; >+ case KEY_DOWN: aPaM = CursorDown( aPaM ); >+ 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 ); >+ break; >+ case KEY_PAGEDOWN: aPaM = bCtrl ? CursorEndOfDoc() : PageDown( aPaM ); >+ break; >+ case KEY_LEFT: aPaM = bCtrl ? CursorWordLeft( aPaM ) : CursorLeft( aPaM, aTranslatedKeyEvent.GetKeyCode().IsMod2() ? (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER : (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL ); >+ break; >+ case KEY_RIGHT: aPaM = bCtrl ? CursorWordRight( aPaM ) : CursorRight( aPaM, aTranslatedKeyEvent.GetKeyCode().IsMod2() ? (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER : (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL ); >+ break; >+ case com::sun::star::awt::Key::SELECT_WORD_FORWARD: >+ bSelect = true; // fallthrough intentional >+ case com::sun::star::awt::Key::MOVE_WORD_FORWARD: >+ aPaM = CursorWordRight( aPaM ); >+ break; >+ case com::sun::star::awt::Key::SELECT_WORD_BACKWARD: >+ bSelect = true; // fallthrough intentional >+ case com::sun::star::awt::Key::MOVE_WORD_BACKWARD: >+ aPaM = CursorWordLeft( aPaM ); >+ break; >+ case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE: >+ bSelect = true; // fallthrough intentional >+ case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE: >+ aPaM = CursorStartOfLine( aPaM ); >+ break; >+ case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE: >+ bSelect = true; // fallthrough intentional >+ case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE: >+ aPaM = CursorEndOfLine( aPaM ); >+ break; >+ case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH: >+ bSelect = true; // falltthrough intentional >+ case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH: >+ aPaM = CursorStartOfParagraph( aPaM ); >+ break; >+ case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH: >+ bSelect = true; // falltthrough intentional >+ case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH: >+ aPaM = CursorEndOfParagraph( aPaM ); >+ break; >+ case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT: >+ bSelect = true; // falltthrough intentional >+ case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT: >+ aPaM = CursorStartOfDoc(); >+ break; >+ case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT: >+ bSelect = true; // falltthrough intentional >+ case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT: >+ aPaM = CursorEndOfDoc(); >+ break; >+ } >+ >+ // Bewirkt evtl. ein CreateAnchor oder Deselection all >+ mpImpl->mpSelEngine->CursorPosChanging( bSelect, aTranslatedKeyEvent.GetKeyCode().IsMod1() ); >+ >+ if ( aOldEnd != aPaM ) >+ { >+ mpImpl->mpTextEngine->CursorMoved( aOldEnd.GetPara() ); >+ >+ TextSelection aNewSelection( mpImpl->maSelection ); >+ aNewSelection.GetEnd() = aPaM; >+ if ( bSelect ) >+ { >+ // Dann wird die Selektion erweitert... >+ ImpSetSelection( aNewSelection ); >+ ShowSelection( TextSelection( aOldEnd, aPaM ) ); >+ } >+ else >+ { >+ aNewSelection.GetStart() = aPaM; >+ ImpSetSelection( aNewSelection ); >+ } >+ } >+ >+ return mpImpl->maSelection; >+} >+ >+void TextView::InsertText( const XubString& rStr, sal_Bool bSelect ) >+{ >+ InsertNewText( rStr, bSelect ); >+} >+ >+void TextView::InsertNewText( const rtl::OUString& rStr, sal_Bool bSelect ) >+{ >+// HideSelection(); >+ mpImpl->mpTextEngine->UndoActionStart(); >+ >+ /* #i87633# >+ break inserted text into chunks that fit into the underlying String >+ based API (which has a maximum length of 65534 elements >+ >+ note: this will of course still cause problems for lines longer than those >+ 65534 elements, but those cases will hopefully be few. >+ In the long run someone should switch the TextEngine to OUString instead of String >+ */ >+ sal_Int32 nLen = rStr.getLength(); >+ sal_Int32 nPos = 0; >+ do >+ { >+ sal_Int32 nChunkLen = nLen > 65534 ? 65534 : nLen; >+ String aChunk( rStr.copy( nPos, nChunkLen ) ); >+ >+ TextSelection aNewSel( mpImpl->maSelection ); >+ >+ TextPaM aPaM = mpImpl->mpTextEngine->ImpInsertText( mpImpl->maSelection, aChunk ); >+ >+ if ( bSelect ) >+ { >+ aNewSel.Justify(); >+ aNewSel.GetEnd() = aPaM; >+ } >+ else >+ { >+ aNewSel = aPaM; >+ } >+ >+ ImpSetSelection( aNewSel ); >+ nLen -= nChunkLen; >+ nPos += nChunkLen; >+ } >+ while( nLen ); >+ >+ mpImpl->mpTextEngine->UndoActionEnd(); >+ >+ mpImpl->mpTextEngine->FormatAndUpdate( this ); >+} >+ >+TextPaM TextView::CursorLeft( const TextPaM& rPaM, sal_uInt16 nCharacterIteratorMode ) >+{ >+ TextPaM aPaM( rPaM ); >+ >+ if ( aPaM.GetIndex() ) >+ { >+ TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() ); >+ uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator(); >+ sal_Int32 nCount = 1; >+ aPaM.GetIndex() = (sal_uInt16)xBI->previousCharacters( pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), nCharacterIteratorMode, nCount, nCount ); >+ } >+ else if ( aPaM.GetPara() ) >+ { >+ aPaM.GetPara()--; >+ TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() ); >+ aPaM.GetIndex() = pNode->GetText().Len(); >+ } >+ return aPaM; >+} >+ >+TextPaM TextView::CursorRight( const TextPaM& rPaM, sal_uInt16 nCharacterIteratorMode ) >+{ >+ TextPaM aPaM( rPaM ); >+ >+ TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() ); >+ if ( aPaM.GetIndex() < pNode->GetText().Len() ) >+ { >+ uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator(); >+ sal_Int32 nCount = 1; >+ aPaM.GetIndex() = (sal_uInt16)xBI->nextCharacters( pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), nCharacterIteratorMode, nCount, nCount ); >+ } >+ else if ( aPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count()-1) ) >+ { >+ aPaM.GetPara()++; >+ aPaM.GetIndex() = 0; >+ } >+ >+ return aPaM; >+} >+ >+ >+TextPaM TextView::CursorWordLeft( const TextPaM& rPaM ) >+{ >+ TextPaM aPaM( rPaM ); >+ >+ if ( aPaM.GetIndex() ) >+ { >+ TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() ); >+ uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator(); >+ i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), rPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True ); >+ if ( aBoundary.startPos >= rPaM.GetIndex() ) >+ aBoundary = xBI->previousWord( pNode->GetText(), rPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES ); >+ aPaM.GetIndex() = ( aBoundary.startPos != -1 ) ? (sal_uInt16)aBoundary.startPos : 0; >+ } >+ else if ( aPaM.GetPara() ) >+ { >+ aPaM.GetPara()--; >+ TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() ); >+ aPaM.GetIndex() = pNode->GetText().Len(); >+ } >+ return aPaM; >+} >+ >+ >+TextPaM TextView::CursorWordRight( const TextPaM& rPaM ) >+{ >+ TextPaM aPaM( rPaM ); >+ >+ TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() ); >+ if ( aPaM.GetIndex() < pNode->GetText().Len() ) >+ { >+ uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator(); >+ i18n::Boundary aBoundary = xBI->nextWord( pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES ); >+ aPaM.GetIndex() = (sal_uInt16)aBoundary.startPos; >+ } >+ else if ( aPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count()-1) ) >+ { >+ aPaM.GetPara()++; >+ aPaM.GetIndex() = 0; >+ } >+ >+ return aPaM; >+} >+ >+TextPaM TextView::ImpDelete( sal_uInt8 nMode, sal_uInt8 nDelMode ) >+{ >+ if ( mpImpl->maSelection.HasRange() ) // dann nur Sel. loeschen >+ return mpImpl->mpTextEngine->ImpDeleteText( mpImpl->maSelection ); >+ >+ TextPaM aStartPaM = mpImpl->maSelection.GetStart(); >+ TextPaM aEndPaM = aStartPaM; >+ if ( nMode == DEL_LEFT ) >+ { >+ if ( nDelMode == DELMODE_SIMPLE ) >+ { >+ aEndPaM = CursorLeft( aEndPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER ); >+ } >+ else if ( nDelMode == DELMODE_RESTOFWORD ) >+ { >+ TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() ); >+ uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator(); >+ i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True ); >+ if ( aBoundary.startPos == mpImpl->maSelection.GetEnd().GetIndex() ) >+ aBoundary = xBI->previousWord( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES ); >+ // #i63506# startPos is -1 when the paragraph starts with a tab >+ aEndPaM.GetIndex() = (aBoundary.startPos >= 0) ? (sal_uInt16)aBoundary.startPos : 0; >+ } >+ else // DELMODE_RESTOFCONTENT >+ { >+ if ( aEndPaM.GetIndex() != 0 ) >+ aEndPaM.GetIndex() = 0; >+ else if ( aEndPaM.GetPara() ) >+ { >+ // Absatz davor >+ aEndPaM.GetPara()--; >+ aEndPaM.GetIndex() = 0; >+ } >+ } >+ } >+ else >+ { >+ if ( nDelMode == DELMODE_SIMPLE ) >+ { >+ aEndPaM = CursorRight( aEndPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL ); >+ } >+ else if ( nDelMode == DELMODE_RESTOFWORD ) >+ { >+ TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() ); >+ uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator(); >+ i18n::Boundary aBoundary = xBI->nextWord( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES ); >+ aEndPaM.GetIndex() = (sal_uInt16)aBoundary.startPos; >+ } >+ else // DELMODE_RESTOFCONTENT >+ { >+ TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() ); >+ if ( aEndPaM.GetIndex() < pNode->GetText().Len() ) >+ aEndPaM.GetIndex() = pNode->GetText().Len(); >+ else if ( aEndPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1 ) ) >+ { >+ // Absatz danach >+ aEndPaM.GetPara()++; >+ TextNode* pNextNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() ); >+ aEndPaM.GetIndex() = pNextNode->GetText().Len(); >+ } >+ } >+ } >+ >+ return mpImpl->mpTextEngine->ImpDeleteText( TextSelection( aStartPaM, aEndPaM ) ); >+} >+ >+ >+ >+TextPaM TextView::CursorUp( const TextPaM& rPaM ) >+{ >+ TextPaM aPaM( rPaM ); >+ >+ long nX; >+ if ( mpImpl->mnTravelXPos == TRAVEL_X_DONTKNOW ) >+ { >+ nX = mpImpl->mpTextEngine->GetEditCursor( rPaM, sal_False ).Left(); >+ mpImpl->mnTravelXPos = (sal_uInt16)nX+1; >+ } >+ else >+ nX = mpImpl->mnTravelXPos; >+ >+ TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() ); >+ sal_uInt16 nLine = pPPortion->GetLineNumber( rPaM.GetIndex(), sal_False ); >+ if ( nLine ) // gleicher Absatz >+ { >+ sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( rPaM.GetPara(), nLine-1, nX ); >+ aPaM.GetIndex() = nCharPos; >+ // 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 >+ TextLine* pLine = pPPortion->GetLines()[ nLine - 1 ]; >+ if ( aPaM.GetIndex() && ( aPaM.GetIndex() == pLine->GetEnd() ) ) >+ aPaM.GetIndex()--; >+ } >+ else if ( rPaM.GetPara() ) // vorheriger Absatz >+ { >+ aPaM.GetPara()--; >+ pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() ); >+ sal_uInt16 nL = pPPortion->GetLines().size() - 1; >+ sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( aPaM.GetPara(), nL, nX+1 ); >+ aPaM.GetIndex() = nCharPos; >+ } >+ >+ return aPaM; >+} >+ >+TextPaM TextView::CursorDown( const TextPaM& rPaM ) >+{ >+ TextPaM aPaM( rPaM ); >+ >+ long nX; >+ if ( mpImpl->mnTravelXPos == TRAVEL_X_DONTKNOW ) >+ { >+ nX = mpImpl->mpTextEngine->GetEditCursor( rPaM, sal_False ).Left(); >+ mpImpl->mnTravelXPos = (sal_uInt16)nX+1; >+ } >+ else >+ nX = mpImpl->mnTravelXPos; >+ >+ TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() ); >+ sal_uInt16 nLine = pPPortion->GetLineNumber( rPaM.GetIndex(), sal_False ); >+ if ( nLine < ( pPPortion->GetLines().size() - 1 ) ) >+ { >+ sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( rPaM.GetPara(), nLine+1, nX ); >+ aPaM.GetIndex() = nCharPos; >+ >+ // Sonderbehandlung siehe CursorUp... >+ TextLine* pLine = pPPortion->GetLines()[ nLine + 1 ]; >+ if ( ( aPaM.GetIndex() == pLine->GetEnd() ) && ( aPaM.GetIndex() > pLine->GetStart() ) && aPaM.GetIndex() < pPPortion->GetNode()->GetText().Len() ) >+ aPaM.GetIndex()--; >+ } >+ else if ( rPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1 ) ) // naechster Absatz >+ { >+ aPaM.GetPara()++; >+ pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() ); >+ sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( aPaM.GetPara(), 0, nX+1 ); >+ aPaM.GetIndex() = nCharPos; >+ TextLine* pLine = pPPortion->GetLines().front(); >+ if ( ( aPaM.GetIndex() == pLine->GetEnd() ) && ( aPaM.GetIndex() > pLine->GetStart() ) && ( pPPortion->GetLines().size() > 1 ) ) >+ aPaM.GetIndex()--; >+ } >+ >+ return aPaM; >+} >+ >+TextPaM TextView::CursorStartOfLine( const TextPaM& rPaM ) >+{ >+ TextPaM aPaM( rPaM ); >+ >+ TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() ); >+ sal_uInt16 nLine = pPPortion->GetLineNumber( aPaM.GetIndex(), sal_False ); >+ TextLine* pLine = pPPortion->GetLines()[ nLine ]; >+ aPaM.GetIndex() = pLine->GetStart(); >+ >+ return aPaM; >+} >+ >+TextPaM TextView::CursorEndOfLine( const TextPaM& rPaM ) >+{ >+ TextPaM aPaM( rPaM ); >+ >+ TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() ); >+ sal_uInt16 nLine = pPPortion->GetLineNumber( aPaM.GetIndex(), sal_False ); >+ TextLine* pLine = pPPortion->GetLines()[ nLine ]; >+ aPaM.GetIndex() = pLine->GetEnd(); >+ >+ if ( pLine->GetEnd() > pLine->GetStart() ) // Leerzeile >+ { >+ xub_Unicode cLastChar = pPPortion->GetNode()->GetText().GetChar((sal_uInt16)(aPaM.GetIndex()-1) ); >+ if ( ( cLastChar == ' ' ) && ( aPaM.GetIndex() != pPPortion->GetNode()->GetText().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! >+ aPaM.GetIndex()--; >+ } >+ } >+ return aPaM; >+} >+ >+TextPaM TextView::CursorStartOfParagraph( const TextPaM& rPaM ) >+{ >+ TextPaM aPaM( rPaM ); >+ aPaM.GetIndex() = 0; >+ return aPaM; >+} >+ >+TextPaM TextView::CursorEndOfParagraph( const TextPaM& rPaM ) >+{ >+ TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( rPaM.GetPara() ); >+ TextPaM aPaM( rPaM ); >+ aPaM.GetIndex() = pNode->GetText().Len(); >+ return aPaM; >+} >+ >+TextPaM TextView::CursorStartOfDoc() >+{ >+ TextPaM aPaM( 0, 0 ); >+ return aPaM; >+} >+ >+TextPaM TextView::CursorEndOfDoc() >+{ >+ sal_uLong nNode = mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1; >+ TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( nNode ); >+ TextPaM aPaM( nNode, pNode->GetText().Len() ); >+ return aPaM; >+} >+ >+TextPaM TextView::PageUp( const TextPaM& rPaM ) >+{ >+ Rectangle aRec = mpImpl->mpTextEngine->PaMtoEditCursor( rPaM ); >+ Point aTopLeft = aRec.TopLeft(); >+ aTopLeft.Y() -= mpImpl->mpWindow->GetOutputSizePixel().Height() * 9/10; >+ aTopLeft.X() += 1; >+ if ( aTopLeft.Y() < 0 ) >+ aTopLeft.Y() = 0; >+ >+ TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aTopLeft ); >+ return aPaM; >+} >+ >+TextPaM TextView::PageDown( const TextPaM& rPaM ) >+{ >+ Rectangle aRec = mpImpl->mpTextEngine->PaMtoEditCursor( rPaM ); >+ Point aBottomRight = aRec.BottomRight(); >+ aBottomRight.Y() += mpImpl->mpWindow->GetOutputSizePixel().Height() * 9/10; >+ aBottomRight.X() += 1; >+ long nHeight = mpImpl->mpTextEngine->GetTextHeight(); >+ if ( aBottomRight.Y() > nHeight ) >+ aBottomRight.Y() = nHeight-1; >+ >+ TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aBottomRight ); >+ return aPaM; >+} >+ >+void TextView::ImpShowCursor( sal_Bool bGotoCursor, sal_Bool bForceVisCursor, sal_Bool bSpecial ) >+{ >+ if ( mpImpl->mpTextEngine->IsFormatting() ) >+ return; >+ if ( mpImpl->mpTextEngine->GetUpdateMode() == sal_False ) >+ return; >+ if ( mpImpl->mpTextEngine->IsInUndo() ) >+ return; >+ >+ mpImpl->mpTextEngine->CheckIdleFormatter(); >+ if ( !mpImpl->mpTextEngine->IsFormatted() ) >+ mpImpl->mpTextEngine->FormatAndUpdate( this ); >+ >+ >+ TextPaM aPaM( mpImpl->maSelection.GetEnd() ); >+ Rectangle aEditCursor = mpImpl->mpTextEngine->PaMtoEditCursor( aPaM, bSpecial ); >+ >+ // Remember that we placed the cursor behind the last character of a line >+ mpImpl->mbCursorAtEndOfLine = false; >+ if( bSpecial ) >+ { >+ TEParaPortion* pParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() ); >+ mpImpl->mbCursorAtEndOfLine = >+ pParaPortion->GetLineNumber( aPaM.GetIndex(), sal_True ) != pParaPortion->GetLineNumber( aPaM.GetIndex(), sal_False ); >+ } >+ >+ if ( !IsInsertMode() && !mpImpl->maSelection.HasRange() ) >+ { >+ TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() ); >+ if ( pNode->GetText().Len() && ( aPaM.GetIndex() < pNode->GetText().Len() ) ) >+ { >+ // If we are behind a portion, and the next portion has other direction, we must change position... >+ aEditCursor.Left() = aEditCursor.Right() = mpImpl->mpTextEngine->GetEditCursor( aPaM, sal_False, sal_True ).Left(); >+ >+ TEParaPortion* pParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() ); >+ >+ sal_uInt16 nTextPortionStart = 0; >+ sal_uInt16 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, sal_True ); >+ TETextPortion* pTextPortion = pParaPortion->GetTextPortions()[ nTextPortion ]; >+ if ( pTextPortion->GetKind() == PORTIONKIND_TAB ) >+ { >+ if ( mpImpl->mpTextEngine->IsRightToLeft() ) >+ { >+ >+ } >+ aEditCursor.Right() += pTextPortion->GetWidth(); >+ } >+ else >+ { >+ TextPaM aNext = CursorRight( TextPaM( aPaM.GetPara(), aPaM.GetIndex() ), (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL ); >+ aEditCursor.Right() = mpImpl->mpTextEngine->GetEditCursor( aNext, sal_True ).Left(); >+ } >+ } >+ } >+ >+ Size aOutSz = mpImpl->mpWindow->GetOutputSizePixel(); >+ if ( aEditCursor.GetHeight() > aOutSz.Height() ) >+ aEditCursor.Bottom() = aEditCursor.Top() + aOutSz.Height() - 1; >+ >+ aEditCursor.Left() -= 1; >+ >+ if ( bGotoCursor >+ // #i81283# protext maStartDocPos against initialization problems >+ && aOutSz.Width() && aOutSz.Height() >+ ) >+ { >+ long nVisStartY = mpImpl->maStartDocPos.Y(); >+ long nVisEndY = mpImpl->maStartDocPos.Y() + aOutSz.Height(); >+ long nVisStartX = mpImpl->maStartDocPos.X(); >+ long nVisEndX = mpImpl->maStartDocPos.X() + aOutSz.Width(); >+ long nMoreX = aOutSz.Width() / 4; >+ >+ Point aNewStartPos( mpImpl->maStartDocPos ); >+ >+ if ( aEditCursor.Bottom() > nVisEndY ) >+ { >+ aNewStartPos.Y() += ( aEditCursor.Bottom() - nVisEndY ); >+ } >+ else if ( aEditCursor.Top() < nVisStartY ) >+ { >+ aNewStartPos.Y() -= ( nVisStartY - aEditCursor.Top() ); >+ } >+ >+ if ( aEditCursor.Right() >= nVisEndX ) >+ { >+ aNewStartPos.X() += ( aEditCursor.Right() - nVisEndX ); >+ >+ // Darfs ein bischen mehr sein? >+ aNewStartPos.X() += nMoreX; >+ } >+ else if ( aEditCursor.Left() <= nVisStartX ) >+ { >+ aNewStartPos.X() -= ( nVisStartX - aEditCursor.Left() ); >+ >+ // Darfs ein bischen mehr sein? >+ aNewStartPos.X() -= nMoreX; >+ } >+ >+ // X kann durch das 'bischen mehr' falsch sein: >+// sal_uLong nMaxTextWidth = mpImpl->mpTextEngine->GetMaxTextWidth(); >+// if ( !nMaxTextWidth || ( nMaxTextWidth > 0x7FFFFFFF ) ) >+// nMaxTextWidth = 0x7FFFFFFF; >+// long nMaxX = (long)nMaxTextWidth - aOutSz.Width(); >+ long nMaxX = mpImpl->mpTextEngine->CalcTextWidth() - aOutSz.Width(); >+ if ( nMaxX < 0 ) >+ nMaxX = 0; >+ >+ if ( aNewStartPos.X() < 0 ) >+ aNewStartPos.X() = 0; >+ else if ( aNewStartPos.X() > nMaxX ) >+ aNewStartPos.X() = nMaxX; >+ >+ // Y sollte nicht weiter unten als noetig liegen: >+ long nYMax = mpImpl->mpTextEngine->GetTextHeight() - aOutSz.Height(); >+ if ( nYMax < 0 ) >+ nYMax = 0; >+ if ( aNewStartPos.Y() > nYMax ) >+ aNewStartPos.Y() = nYMax; >+ >+ if ( aNewStartPos != mpImpl->maStartDocPos ) >+ Scroll( -(aNewStartPos.X() - mpImpl->maStartDocPos.X()), -(aNewStartPos.Y() - mpImpl->maStartDocPos.Y()) ); >+ } >+ >+ if ( aEditCursor.Right() < aEditCursor.Left() ) >+ { >+ long n = aEditCursor.Left(); >+ aEditCursor.Left() = aEditCursor.Right(); >+ aEditCursor.Right() = n; >+ } >+ >+ Point aPoint( GetWindowPos( !mpImpl->mpTextEngine->IsRightToLeft() ? aEditCursor.TopLeft() : aEditCursor.TopRight() ) ); >+ mpImpl->mpCursor->SetPos( aPoint ); >+ mpImpl->mpCursor->SetSize( aEditCursor.GetSize() ); >+ if ( bForceVisCursor && mpImpl->mbCursorEnabled ) >+ mpImpl->mpCursor->Show(); >+} >+ >+sal_Bool TextView::SetCursorAtPoint( const Point& rPosPixel ) >+{ >+ mpImpl->mpTextEngine->CheckIdleFormatter(); >+ >+ Point aDocPos = GetDocPos( rPosPixel ); >+ >+ TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aDocPos ); >+ >+ // aTmpNewSel: Diff zwischen alt und neu, nicht die neue Selektion >+ TextSelection aTmpNewSel( mpImpl->maSelection.GetEnd(), aPaM ); >+ TextSelection aNewSel( mpImpl->maSelection ); >+ aNewSel.GetEnd() = aPaM; >+ >+ if ( !mpImpl->mpSelEngine->HasAnchor() ) >+ { >+ if ( mpImpl->maSelection.GetStart() != aPaM ) >+ mpImpl->mpTextEngine->CursorMoved( mpImpl->maSelection.GetStart().GetPara() ); >+ aNewSel.GetStart() = aPaM; >+ ImpSetSelection( aNewSel ); >+ } >+ else >+ { >+ ImpSetSelection( aNewSel ); >+ ShowSelection( aTmpNewSel ); >+ } >+ >+ sal_Bool bForceCursor = mpImpl->mpDDInfo ? sal_False : sal_True; // && !mbInSelection >+ ImpShowCursor( mpImpl->mbAutoScroll, bForceCursor, sal_False ); >+ return sal_True; >+} >+ >+sal_Bool TextView::IsSelectionAtPoint( const Point& rPosPixel ) >+{ >+// if ( !Rectangle( Point(), mpImpl->mpWindow->GetOutputSizePixel() ).IsInside( rPosPixel ) && !mbInSelection ) >+// return sal_False; >+ >+ Point aDocPos = GetDocPos( rPosPixel ); >+ TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aDocPos, sal_False ); >+ // Bei Hyperlinks D&D auch ohne Selektion starten. >+ // BeginDrag wird aber nur gerufen, wenn IsSelectionAtPoint() >+ // Problem: IsSelectionAtPoint wird bei Command() nicht gerufen, >+ // wenn vorher im MBDown schon sal_False returnt wurde. >+ return ( IsInSelection( aPaM ) || >+ ( /* mpImpl->mpSelEngine->IsInCommand() && */ mpImpl->mpTextEngine->FindAttrib( aPaM, TEXTATTR_HYPERLINK ) ) ); >+} >+ >+sal_Bool TextView::IsInSelection( const TextPaM& rPaM ) >+{ >+ TextSelection aSel = mpImpl->maSelection; >+ aSel.Justify(); >+ >+ sal_uLong nStartNode = aSel.GetStart().GetPara(); >+ sal_uLong nEndNode = aSel.GetEnd().GetPara(); >+ sal_uLong nCurNode = rPaM.GetPara(); >+ >+ if ( ( nCurNode > nStartNode ) && ( nCurNode < nEndNode ) ) >+ return sal_True; >+ >+ if ( nStartNode == nEndNode ) >+ { >+ if ( nCurNode == nStartNode ) >+ if ( ( rPaM.GetIndex() >= aSel.GetStart().GetIndex() ) && ( rPaM.GetIndex() < aSel.GetEnd().GetIndex() ) ) >+ return sal_True; >+ } >+ else if ( ( nCurNode == nStartNode ) && ( rPaM.GetIndex() >= aSel.GetStart().GetIndex() ) ) >+ return sal_True; >+ else if ( ( nCurNode == nEndNode ) && ( rPaM.GetIndex() < aSel.GetEnd().GetIndex() ) ) >+ return sal_True; >+ >+ return sal_False; >+} >+ >+void TextView::ImpHideDDCursor() >+{ >+ if ( mpImpl->mpDDInfo && mpImpl->mpDDInfo->mbVisCursor ) >+ { >+ mpImpl->mpDDInfo->maCursor.Hide(); >+ mpImpl->mpDDInfo->mbVisCursor = sal_False; >+ } >+} >+ >+void TextView::ImpShowDDCursor() >+{ >+ if ( !mpImpl->mpDDInfo->mbVisCursor ) >+ { >+ Rectangle aCursor = mpImpl->mpTextEngine->PaMtoEditCursor( mpImpl->mpDDInfo->maDropPos, sal_True ); >+ aCursor.Right()++; >+ aCursor.SetPos( GetWindowPos( aCursor.TopLeft() ) ); >+ >+ mpImpl->mpDDInfo->maCursor.SetWindow( mpImpl->mpWindow ); >+ mpImpl->mpDDInfo->maCursor.SetPos( aCursor.TopLeft() ); >+ mpImpl->mpDDInfo->maCursor.SetSize( aCursor.GetSize() ); >+ mpImpl->mpDDInfo->maCursor.Show(); >+ mpImpl->mpDDInfo->mbVisCursor = sal_True; >+ } >+} >+ >+void TextView::SetPaintSelection( sal_Bool bPaint ) >+{ >+ if ( bPaint != mpImpl->mbPaintSelection ) >+ { >+ mpImpl->mbPaintSelection = bPaint; >+ ShowSelection( mpImpl->maSelection ); >+ } >+} >+ >+sal_Bool TextView::Read( SvStream& rInput ) >+{ >+ sal_Bool bDone = mpImpl->mpTextEngine->Read( rInput, &mpImpl->maSelection ); >+ ShowCursor(); >+ return bDone; >+} >+ >+bool TextView::ImplTruncateNewText( rtl::OUString& rNewText ) const >+{ >+ bool bTruncated = false; >+ >+ if( rNewText.getLength() > 65534 ) // limit to String API >+ { >+ rNewText = rNewText.copy( 0, 65534 ); >+ bTruncated = true; >+ } >+ >+ sal_uLong nMaxLen = mpImpl->mpTextEngine->GetMaxTextLen(); >+ // 0 means unlimited, there is just the String API limit handled above >+ if( nMaxLen != 0 ) >+ { >+ sal_uLong nCurLen = mpImpl->mpTextEngine->GetTextLen(); >+ >+ sal_uInt32 nNewLen = rNewText.getLength(); >+ if ( nCurLen + nNewLen > nMaxLen ) >+ { >+ // see how much text will be replaced >+ sal_uLong nSelLen = mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection ); >+ if ( nCurLen + nNewLen - nSelLen > nMaxLen ) >+ { >+ sal_uInt32 nTruncatedLen = static_cast<sal_uInt32>(nMaxLen - (nCurLen - nSelLen)); >+ rNewText = rNewText.copy( 0, nTruncatedLen ); >+ bTruncated = true; >+ } >+ } >+ } >+ return bTruncated; >+} >+ >+sal_Bool TextView::ImplCheckTextLen( const String& rNewText ) >+{ >+ sal_Bool bOK = sal_True; >+ if ( mpImpl->mpTextEngine->GetMaxTextLen() ) >+ { >+ sal_uLong n = mpImpl->mpTextEngine->GetTextLen(); >+ n += rNewText.Len(); >+ if ( n > mpImpl->mpTextEngine->GetMaxTextLen() ) >+ { >+ // nur dann noch ermitteln, wie viel Text geloescht wird >+ n -= mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection ); >+ if ( n > mpImpl->mpTextEngine->GetMaxTextLen() ) >+ bOK = sal_False; >+ } >+ } >+ return bOK; >+} >+ >+void TextView::dragGestureRecognized( const ::com::sun::star::datatransfer::dnd::DragGestureEvent& rDGE ) throw (::com::sun::star::uno::RuntimeException) >+{ >+ if ( mpImpl->mbClickedInSelection ) >+ { >+ SolarMutexGuard aVclGuard; >+ >+ DBG_ASSERT( mpImpl->maSelection.HasRange(), "TextView::dragGestureRecognized: mpImpl->mbClickedInSelection, but no selection?" ); >+ >+ delete mpImpl->mpDDInfo; >+ mpImpl->mpDDInfo = new TextDDInfo; >+ mpImpl->mpDDInfo->mbStarterOfDD = sal_True; >+ >+ TETextDataObject* pDataObj = new TETextDataObject( GetSelected() ); >+ >+ if ( mpImpl->mpTextEngine->HasAttrib( TEXTATTR_HYPERLINK ) ) // Dann auch als HTML >+ mpImpl->mpTextEngine->Write( pDataObj->GetHTMLStream(), &mpImpl->maSelection, sal_True ); >+ >+ >+ /* >+ // D&D eines Hyperlinks. >+ // Besser waere es im MBDown sich den MBDownPaM zu merken, >+ // ist dann aber inkompatibel => spaeter mal umstellen. >+ TextPaM aPaM( mpImpl->mpTextEngine->GetPaM( GetDocPos( GetWindow()->GetPointerPosPixel() ) ) ); >+ const TextCharAttrib* pAttr = mpImpl->mpTextEngine->FindCharAttrib( aPaM, TEXTATTR_HYPERLINK ); >+ if ( pAttr ) >+ { >+ aSel = aPaM; >+ aSel.GetStart().GetIndex() = pAttr->GetStart(); >+ aSel.GetEnd().GetIndex() = pAttr->GetEnd(); >+ >+ const TextAttribHyperLink& rLink = (const TextAttribHyperLink&)pAttr->GetAttr(); >+ String aText( rLink.GetDescription() ); >+ if ( !aText.Len() ) >+ aText = mpImpl->mpTextEngine->GetText( aSel ); >+ INetBookmark aBookmark( rLink.GetURL(), aText ); >+ aBookmark.CopyDragServer(); >+ } >+ */ >+ >+ mpImpl->mpCursor->Hide(); >+ >+ sal_Int8 nActions = datatransfer::dnd::DNDConstants::ACTION_COPY; >+ if ( !IsReadOnly() ) >+ nActions |= datatransfer::dnd::DNDConstants::ACTION_MOVE; >+ rDGE.DragSource->startDrag( rDGE, nActions, 0 /*cursor*/, 0 /*image*/, pDataObj, mpImpl->mxDnDListener ); >+ } >+} >+ >+void TextView::dragDropEnd( const ::com::sun::star::datatransfer::dnd::DragSourceDropEvent& ) throw (::com::sun::star::uno::RuntimeException) >+{ >+ ImpHideDDCursor(); >+ delete mpImpl->mpDDInfo; >+ mpImpl->mpDDInfo = NULL; >+} >+ >+void TextView::drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException) >+{ >+ SolarMutexGuard aVclGuard; >+ >+ sal_Bool bChanges = sal_False; >+ if ( !mpImpl->mbReadOnly && mpImpl->mpDDInfo ) >+ { >+ ImpHideDDCursor(); >+ >+ // Daten fuer das loeschen nach einem DROP_MOVE: >+ TextSelection aPrevSel( mpImpl->maSelection ); >+ aPrevSel.Justify(); >+ sal_uLong nPrevParaCount = mpImpl->mpTextEngine->GetParagraphCount(); >+ sal_uInt16 nPrevStartParaLen = mpImpl->mpTextEngine->GetTextLen( aPrevSel.GetStart().GetPara() ); >+ >+ sal_Bool bStarterOfDD = sal_False; >+ for ( sal_uInt16 nView = mpImpl->mpTextEngine->GetViewCount(); nView && !bStarterOfDD; ) >+ bStarterOfDD = mpImpl->mpTextEngine->GetView( --nView )->mpImpl->mpDDInfo ? mpImpl->mpTextEngine->GetView( nView )->mpImpl->mpDDInfo->mbStarterOfDD : sal_False; >+ >+ HideSelection(); >+ ImpSetSelection( mpImpl->mpDDInfo->maDropPos ); >+ >+ mpImpl->mpTextEngine->UndoActionStart(); >+ >+ String aText; >+ uno::Reference< datatransfer::XTransferable > xDataObj = rDTDE.Transferable; >+ if ( xDataObj.is() ) >+ { >+ datatransfer::DataFlavor aFlavor; >+ SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor ); >+ if ( xDataObj->isDataFlavorSupported( aFlavor ) ) >+ { >+ uno::Any aData = xDataObj->getTransferData( aFlavor ); >+ ::rtl::OUString aOUString; >+ aData >>= aOUString; >+ aText = convertLineEnd(aOUString, LINEEND_LF); >+ } >+ } >+ >+ if ( aText.Len() && ( aText.GetChar( aText.Len()-1 ) == LINE_SEP ) ) >+ aText.Erase( aText.Len()-1 ); >+ >+ TextPaM aTempStart = mpImpl->maSelection.GetStart(); >+ if ( ImplCheckTextLen( aText ) ) >+ ImpSetSelection( mpImpl->mpTextEngine->ImpInsertText( mpImpl->mpDDInfo->maDropPos, aText ) ); >+ if(mpImpl->mbSupportProtectAttribute) >+ { >+ mpImpl->mpTextEngine->SetAttrib( TextAttribProtect(), >+ aTempStart.GetPara(), >+ aTempStart.GetIndex(), >+ mpImpl->maSelection.GetEnd().GetIndex(), sal_False ); >+ } >+ >+ if ( aPrevSel.HasRange() && >+ !mpImpl->mbSupportProtectAttribute && // don't remove currently selected element >+ (( rDTDE.DropAction & datatransfer::dnd::DNDConstants::ACTION_MOVE ) || !bStarterOfDD) ) >+ { >+ // ggf. Selection anpasssen: >+ if ( ( mpImpl->mpDDInfo->maDropPos.GetPara() < aPrevSel.GetStart().GetPara() ) || >+ ( ( mpImpl->mpDDInfo->maDropPos.GetPara() == aPrevSel.GetStart().GetPara() ) >+ && ( mpImpl->mpDDInfo->maDropPos.GetIndex() < aPrevSel.GetStart().GetIndex() ) ) ) >+ { >+ sal_uLong nNewParasBeforeSelection = >+ mpImpl->mpTextEngine->GetParagraphCount() - nPrevParaCount; >+ >+ aPrevSel.GetStart().GetPara() += nNewParasBeforeSelection; >+ aPrevSel.GetEnd().GetPara() += nNewParasBeforeSelection; >+ >+ if ( mpImpl->mpDDInfo->maDropPos.GetPara() == aPrevSel.GetStart().GetPara() ) >+ { >+ sal_uInt16 nNewChars = >+ mpImpl->mpTextEngine->GetTextLen( aPrevSel.GetStart().GetPara() ) - nPrevStartParaLen; >+ >+ aPrevSel.GetStart().GetIndex() = >+ aPrevSel.GetStart().GetIndex() + nNewChars; >+ if ( aPrevSel.GetStart().GetPara() == aPrevSel.GetEnd().GetPara() ) >+ aPrevSel.GetEnd().GetIndex() = >+ aPrevSel.GetEnd().GetIndex() + nNewChars; >+ } >+ } >+ else >+ { >+ // aktuelle Selektion anpassen >+ TextPaM aPaM = mpImpl->maSelection.GetStart(); >+ aPaM.GetPara() -= ( aPrevSel.GetEnd().GetPara() - aPrevSel.GetStart().GetPara() ); >+ if ( aPrevSel.GetEnd().GetPara() == mpImpl->mpDDInfo->maDropPos.GetPara() ) >+ { >+ aPaM.GetIndex() = >+ aPaM.GetIndex() - aPrevSel.GetEnd().GetIndex(); >+ if ( aPrevSel.GetStart().GetPara() == mpImpl->mpDDInfo->maDropPos.GetPara() ) >+ aPaM.GetIndex() = >+ aPaM.GetIndex() + aPrevSel.GetStart().GetIndex(); >+ } >+ ImpSetSelection( aPaM ); >+ >+ } >+ mpImpl->mpTextEngine->ImpDeleteText( aPrevSel ); >+ } >+ >+ mpImpl->mpTextEngine->UndoActionEnd(); >+ >+ delete mpImpl->mpDDInfo; >+ mpImpl->mpDDInfo = 0; >+ >+ mpImpl->mpTextEngine->FormatAndUpdate( this ); >+ >+ mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) ); >+ } >+ rDTDE.Context->dropComplete( bChanges ); >+} >+ >+void TextView::dragEnter( const ::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent& ) throw (::com::sun::star::uno::RuntimeException) >+{ >+} >+ >+void TextView::dragExit( const ::com::sun::star::datatransfer::dnd::DropTargetEvent& ) throw (::com::sun::star::uno::RuntimeException) >+{ >+ SolarMutexGuard aVclGuard; >+ ImpHideDDCursor(); >+} >+ >+void TextView::dragOver( const ::com::sun::star::datatransfer::dnd::DropTargetDragEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException) >+{ >+ SolarMutexGuard aVclGuard; >+ >+ if ( !mpImpl->mpDDInfo ) >+ mpImpl->mpDDInfo = new TextDDInfo; >+ >+ TextPaM aPrevDropPos = mpImpl->mpDDInfo->maDropPos; >+ Point aMousePos( rDTDE.LocationX, rDTDE.LocationY ); >+ Point aDocPos = GetDocPos( aMousePos ); >+ mpImpl->mpDDInfo->maDropPos = mpImpl->mpTextEngine->GetPaM( aDocPos ); >+ >+ sal_Bool bProtected = sal_False; >+ if(mpImpl->mbSupportProtectAttribute) >+ { >+ const TextCharAttrib* pStartAttr = mpImpl->mpTextEngine->FindCharAttrib( >+ mpImpl->mpDDInfo->maDropPos, >+ TEXTATTR_PROTECTED ); >+ bProtected = pStartAttr != 0 && >+ pStartAttr->GetStart() != mpImpl->mpDDInfo->maDropPos.GetIndex() && >+ pStartAttr->GetEnd() != mpImpl->mpDDInfo->maDropPos.GetIndex(); >+ } >+ // Don't drop in selection or in read only engine >+ if ( IsReadOnly() || IsInSelection( mpImpl->mpDDInfo->maDropPos ) || bProtected) >+ { >+ ImpHideDDCursor(); >+ rDTDE.Context->rejectDrag(); >+ } >+ else >+ { >+ // Alten Cursor wegzeichnen... >+ if ( !mpImpl->mpDDInfo->mbVisCursor || ( aPrevDropPos != mpImpl->mpDDInfo->maDropPos ) ) >+ { >+ ImpHideDDCursor(); >+ ImpShowDDCursor(); >+ } >+ rDTDE.Context->acceptDrag( rDTDE.DropAction ); >+ } >+} >+ >+Point TextView::ImpGetOutputStartPos( const Point& rStartDocPos ) const >+{ >+ Point aStartPos( -rStartDocPos.X(), -rStartDocPos.Y() ); >+ if ( mpImpl->mpTextEngine->IsRightToLeft() ) >+ { >+ Size aSz = mpImpl->mpWindow->GetOutputSizePixel(); >+ aStartPos.X() = rStartDocPos.X() + aSz.Width() - 1; // -1: Start is 0 >+ } >+ return aStartPos; >+} >+ >+Point TextView::GetDocPos( const Point& rWindowPos ) const >+{ >+ // Fensterposition => Dokumentposition >+ >+ Point aPoint; >+ >+ aPoint.Y() = rWindowPos.Y() + mpImpl->maStartDocPos.Y(); >+ >+ if ( !mpImpl->mpTextEngine->IsRightToLeft() ) >+ { >+ aPoint.X() = rWindowPos.X() + mpImpl->maStartDocPos.X(); >+ } >+ else >+ { >+ Size aSz = mpImpl->mpWindow->GetOutputSizePixel(); >+ aPoint.X() = ( aSz.Width() - 1 ) - rWindowPos.X() + mpImpl->maStartDocPos.X(); >+ } >+ >+ return aPoint; >+} >+ >+Point TextView::GetWindowPos( const Point& rDocPos ) const >+{ >+ // Dokumentposition => Fensterposition >+ >+ Point aPoint; >+ >+ aPoint.Y() = rDocPos.Y() - mpImpl->maStartDocPos.Y(); >+ >+ if ( !mpImpl->mpTextEngine->IsRightToLeft() ) >+ { >+ aPoint.X() = rDocPos.X() - mpImpl->maStartDocPos.X(); >+ } >+ else >+ { >+ Size aSz = mpImpl->mpWindow->GetOutputSizePixel(); >+ aPoint.X() = ( aSz.Width() - 1 ) - ( rDocPos.X() - mpImpl->maStartDocPos.X() ); >+ } >+ >+ return aPoint; >+} >+ >+sal_Int32 TextView::GetLineNumberOfCursorInSelection() const >+{ >+ // PROGRESS >+ sal_Int32 nLineNo = -1; >+ if( mpImpl->mbCursorEnabled ) >+ { >+ TextPaM aPaM = GetSelection().GetEnd(); >+ TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() ); >+ nLineNo = pPPortion->GetLineNumber( aPaM.GetIndex(), sal_False ); >+ if( mpImpl->mbCursorAtEndOfLine ) >+ --nLineNo; >+ } >+ return nLineNo; >+} >+ >+ >+// ------------------------------------------------------------------------- >+// (+) class TextSelFunctionSet >+// ------------------------------------------------------------------------- >+TextSelFunctionSet::TextSelFunctionSet( TextView* pView ) >+{ >+ mpView = pView; >+} >+ >+void TextSelFunctionSet::BeginDrag() >+{ >+} >+ >+void TextSelFunctionSet::CreateAnchor() >+{ >+// TextSelection aSel( mpView->GetSelection() ); >+// aSel.GetStart() = aSel.GetEnd(); >+// mpView->SetSelection( aSel ); >+ >+ // Es darf kein ShowCursor folgen: >+ mpView->HideSelection(); >+ mpView->ImpSetSelection( mpView->mpImpl->maSelection.GetEnd() ); >+} >+ >+sal_Bool TextSelFunctionSet::SetCursorAtPoint( const Point& rPointPixel, sal_Bool ) >+{ >+ return mpView->SetCursorAtPoint( rPointPixel ); >+} >+ >+sal_Bool TextSelFunctionSet::IsSelectionAtPoint( const Point& rPointPixel ) >+{ >+ return mpView->IsSelectionAtPoint( rPointPixel ); >+} >+ >+void TextSelFunctionSet::DeselectAll() >+{ >+ CreateAnchor(); >+} >+ >+void TextSelFunctionSet::DeselectAtPoint( const Point& ) >+{ >+ // Nur bei Mehrfachselektion >+} >+ >+void TextSelFunctionSet::DestroyAnchor() >+{ >+ // Nur bei Mehrfachselektion >+} >+TextEngine* TextView::GetTextEngine() const >+{ return mpImpl->mpTextEngine; } >+Window* TextView::GetWindow() const >+{ return mpImpl->mpWindow; } >+void TextView::EnableCursor( sal_Bool bEnable ) >+{ mpImpl->mbCursorEnabled = bEnable; } >+sal_Bool TextView::IsCursorEnabled() const >+{ return mpImpl->mbCursorEnabled; } >+void TextView::SetStartDocPos( const Point& rPos ) >+{ mpImpl->maStartDocPos = rPos; } >+const Point& TextView::GetStartDocPos() const >+{ return mpImpl->maStartDocPos; } >+void TextView::SetAutoIndentMode( sal_Bool bAutoIndent ) >+{ mpImpl->mbAutoIndent = bAutoIndent; } >+sal_Bool TextView::IsReadOnly() const >+{ return mpImpl->mbReadOnly; } >+void TextView::SetAutoScroll( sal_Bool bAutoScroll ) >+{ mpImpl->mbAutoScroll = bAutoScroll; } >+sal_Bool TextView::IsAutoScroll() const >+{ return mpImpl->mbAutoScroll; } >+sal_Bool TextView::HasSelection() const >+{ return mpImpl->maSelection.HasRange(); } >+sal_Bool TextView::IsInsertMode() const >+{ return mpImpl->mbInsertMode; } >+void TextView::SupportProtectAttribute(sal_Bool bSupport) >+{ mpImpl->mbSupportProtectAttribute = bSupport;} >+ >+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/vcl/source/edit/txtattr.cxx b/vcl/source/edit/txtattr.cxx >new file mode 100644 >index 0000000..d0e3a84 >--- /dev/null >+++ b/vcl/source/edit/txtattr.cxx >@@ -0,0 +1,164 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >+/************************************************************************* >+ * >+ * 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 <vcl/txtattr.hxx> >+#include <vcl/font.hxx> >+ >+ >+ >+ >+TextAttrib::~TextAttrib() >+{ >+} >+ >+int TextAttrib::operator==( const TextAttrib& rAttr ) const >+{ >+ return mnWhich == rAttr.mnWhich; >+} >+ >+ >+TextAttribFontColor::TextAttribFontColor( const Color& rColor ) >+ : TextAttrib( TEXTATTR_FONTCOLOR ), maColor( rColor ) >+{ >+} >+ >+TextAttribFontColor::TextAttribFontColor( const TextAttribFontColor& rAttr ) >+ : TextAttrib( rAttr ), maColor( rAttr.maColor ) >+{ >+} >+ >+TextAttribFontColor::~TextAttribFontColor() >+{ >+} >+ >+void TextAttribFontColor::SetFont( Font& rFont ) const >+{ >+ rFont.SetColor( maColor ); >+} >+ >+TextAttrib* TextAttribFontColor::Clone() const >+{ >+ return new TextAttribFontColor( *this ); >+} >+ >+int TextAttribFontColor::operator==( const TextAttrib& rAttr ) const >+{ >+ return ( ( TextAttrib::operator==(rAttr ) ) && >+ ( maColor == ((const TextAttribFontColor&)rAttr).maColor ) ); >+} >+ >+TextAttribFontWeight::TextAttribFontWeight( FontWeight eWeight ) >+ : TextAttrib( TEXTATTR_FONTWEIGHT ), meWeight( eWeight ) >+{ >+} >+ >+TextAttribFontWeight::TextAttribFontWeight( const TextAttribFontWeight& rAttr ) >+ : TextAttrib( rAttr ), meWeight( rAttr.meWeight ) >+{ >+} >+ >+TextAttribFontWeight::~TextAttribFontWeight() >+{ >+} >+ >+void TextAttribFontWeight::SetFont( Font& rFont ) const >+{ >+ rFont.SetWeight( meWeight ); >+} >+ >+TextAttrib* TextAttribFontWeight::Clone() const >+{ >+ return new TextAttribFontWeight( *this ); >+} >+ >+int TextAttribFontWeight::operator==( const TextAttrib& rAttr ) const >+{ >+ return ( ( TextAttrib::operator==(rAttr ) ) && >+ ( meWeight == ((const TextAttribFontWeight&)rAttr).meWeight ) ); >+} >+ >+ >+TextAttribHyperLink::TextAttribHyperLink( const TextAttribHyperLink& rAttr ) >+ : TextAttrib( rAttr ), maURL( rAttr.maURL ), maDescription( rAttr.maDescription ) >+{ >+ maColor = rAttr.maColor; >+} >+ >+TextAttribHyperLink::~TextAttribHyperLink() >+{ >+} >+ >+void TextAttribHyperLink::SetFont( Font& rFont ) const >+{ >+ rFont.SetColor( maColor ); >+ rFont.SetUnderline( UNDERLINE_SINGLE ); >+} >+ >+TextAttrib* TextAttribHyperLink::Clone() const >+{ >+ return new TextAttribHyperLink( *this ); >+} >+ >+int TextAttribHyperLink::operator==( const TextAttrib& rAttr ) const >+{ >+ return ( ( TextAttrib::operator==(rAttr ) ) && >+ ( maURL == ((const TextAttribHyperLink&)rAttr).maURL ) && >+ ( maDescription == ((const TextAttribHyperLink&)rAttr).maDescription ) && >+ ( maColor == ((const TextAttribHyperLink&)rAttr).maColor ) ); >+} >+ >+TextAttribProtect::TextAttribProtect() : >+ TextAttrib( TEXTATTR_PROTECTED ) >+{ >+} >+ >+TextAttribProtect::TextAttribProtect( const TextAttribProtect&) : >+ TextAttrib( TEXTATTR_PROTECTED ) >+{ >+} >+ >+TextAttribProtect::~TextAttribProtect() >+{ >+} >+ >+void TextAttribProtect::SetFont( Font& ) const >+{ >+} >+ >+TextAttrib* TextAttribProtect::Clone() const >+{ >+ return new TextAttribProtect(); >+} >+ >+int TextAttribProtect::operator==( const TextAttrib& rAttr ) const >+{ >+ return ( TextAttrib::operator==(rAttr ) ); >+} >+ >+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/vcl/source/edit/vclmedit.cxx b/vcl/source/edit/vclmedit.cxx >new file mode 100644 >index 0000000..2262c74 >--- /dev/null >+++ b/vcl/source/edit/vclmedit.cxx >@@ -0,0 +1,1572 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >+/************************************************************************* >+ * >+ * 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 <memory> >+ >+#include <tools/rc.h> >+ >+#include <vcl/decoview.hxx> >+#include <vcl/svapp.hxx> >+ >+#include <vcl/vclmedit.hxx> >+#include <vcl/xtextedt.hxx> >+#include <svl/brdcst.hxx> >+#include <svl/undo.hxx> >+#include <svl/lstner.hxx> >+#include <svl/smplhint.hxx> >+ >+#include <svids.hrc> >+#include <vcl/scrbar.hxx> >+ >+ >+class TextWindow : public Window >+{ >+private: >+ ExtTextEngine* mpTextEngine; >+ ExtTextView* mpTextView; >+ >+ sal_Bool mbInMBDown; >+ sal_Bool mbFocusSelectionHide; >+ sal_Bool mbIgnoreTab; >+ sal_Bool mbActivePopup; >+ sal_Bool mbSelectOnTab; >+ sal_Bool mbTextSelectable; >+ >+public: >+ TextWindow( Window* pParent ); >+ ~TextWindow(); >+ >+ ExtTextEngine* GetTextEngine() const { return mpTextEngine; } >+ ExtTextView* GetTextView() const { return mpTextView; } >+ >+ virtual void MouseMove( const MouseEvent& rMEvt ); >+ virtual void MouseButtonDown( const MouseEvent& rMEvt ); >+ virtual void MouseButtonUp( const MouseEvent& rMEvt ); >+ virtual void KeyInput( const KeyEvent& rKEvent ); >+ >+ virtual void Command( const CommandEvent& rCEvt ); >+ >+ virtual void Paint( const Rectangle& rRect ); >+ virtual void Resize(); >+ >+ virtual void GetFocus(); >+ virtual void LoseFocus(); >+ >+ sal_Bool IsAutoFocusHide() const { return mbFocusSelectionHide; } >+ void SetAutoFocusHide( sal_Bool bAutoHide ) { mbFocusSelectionHide = bAutoHide; } >+ >+ sal_Bool IsIgnoreTab() const { return mbIgnoreTab; } >+ void SetIgnoreTab( sal_Bool bIgnore ) { mbIgnoreTab = bIgnore; } >+ >+ void DisableSelectionOnFocus() { mbSelectOnTab = sal_False; } >+ >+ void SetTextSelectable( sal_Bool bTextSelectable ) { mbTextSelectable = bTextSelectable; } >+}; >+ >+ >+class ImpSvMEdit : public SfxListener >+{ >+private: >+ VCLMultiLineEdit* pSvVCLMultiLineEdit; >+ >+ TextWindow* mpTextWindow; >+ ScrollBar* mpHScrollBar; >+ ScrollBar* mpVScrollBar; >+ ScrollBarBox* mpScrollBox; >+ >+ Point maTextWindowOffset; >+ xub_StrLen mnTextWidth; >+ mutable Selection maSelection; >+ >+protected: >+ virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); >+ void ImpUpdateSrollBarVis( WinBits nWinStyle ); >+ void ImpInitScrollBars(); >+ void ImpSetScrollBarRanges(); >+ void ImpSetHScrollBarThumbPos(); >+ DECL_LINK( ScrollHdl, ScrollBar* ); >+ >+public: >+ ImpSvMEdit( VCLMultiLineEdit* pSvVCLMultiLineEdit, WinBits nWinStyle ); >+ ~ImpSvMEdit(); >+ >+ void SetModified( sal_Bool bMod ); >+ sal_Bool IsModified() const; >+ >+ void SetReadOnly( sal_Bool bRdOnly ); >+ sal_Bool IsReadOnly() const; >+ >+ void SetMaxTextLen( xub_StrLen nLen ); >+ xub_StrLen GetMaxTextLen() const; >+ >+ sal_Bool IsInsertMode() const; >+ >+ void InsertText( const String& rStr ); >+ String GetSelected() const; >+ String GetSelected( LineEnd aSeparator ) const; >+ >+ void SetSelection( const Selection& rSelection ); >+ const Selection& GetSelection() const; >+ >+ void Cut(); >+ void Copy(); >+ void Paste(); >+ >+ void SetText( const String& rStr ); >+ String GetText() const; >+ String GetText( LineEnd aSeparator ) const; >+ String GetTextLines( LineEnd aSeparator ) const; >+ >+ void Resize(); >+ void GetFocus(); >+ >+ sal_Bool HandleCommand( const CommandEvent& rCEvt ); >+ >+ void Enable( sal_Bool bEnable ); >+ >+ Size CalcMinimumSize() const; >+ Size CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const; >+ void GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const; >+ >+ void SetAlign( WinBits nWinStyle ); >+ >+ void InitFromStyle( WinBits nWinStyle ); >+ >+ TextWindow* GetTextWindow() { return mpTextWindow; } >+ ScrollBar* GetHScrollBar() { return mpHScrollBar; } >+ ScrollBar* GetVScrollBar() { return mpVScrollBar; } >+}; >+ >+ImpSvMEdit::ImpSvMEdit( VCLMultiLineEdit* pEdt, WinBits nWinStyle ) >+ :mpHScrollBar(NULL) >+ ,mpVScrollBar(NULL) >+ ,mpScrollBox(NULL) >+{ >+ pSvVCLMultiLineEdit = pEdt; >+ mnTextWidth = 0; >+ mpTextWindow = new TextWindow( pEdt ); >+ mpTextWindow->Show(); >+ InitFromStyle( nWinStyle ); >+ StartListening( *mpTextWindow->GetTextEngine() ); >+} >+ >+void ImpSvMEdit::ImpUpdateSrollBarVis( WinBits nWinStyle ) >+{ >+ const sal_Bool bHaveVScroll = (NULL != mpVScrollBar); >+ const sal_Bool bHaveHScroll = (NULL != mpHScrollBar); >+ const sal_Bool bHaveScrollBox = (NULL != mpScrollBox); >+ >+ sal_Bool bNeedVScroll = ( nWinStyle & WB_VSCROLL ) == WB_VSCROLL; >+ const sal_Bool bNeedHScroll = ( nWinStyle & WB_HSCROLL ) == WB_HSCROLL; >+ >+ const sal_Bool bAutoVScroll = ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL; >+ if ( !bNeedVScroll && bAutoVScroll ) >+ { >+ TextEngine& rEngine( *mpTextWindow->GetTextEngine() ); >+ sal_uLong nOverallTextHeight(0); >+ for ( sal_uLong i=0; i<rEngine.GetParagraphCount(); ++i ) >+ nOverallTextHeight += rEngine.GetTextHeight( i ); >+ if ( nOverallTextHeight > (sal_uLong)mpTextWindow->GetOutputSizePixel().Height() ) >+ bNeedVScroll = true; >+ } >+ >+ const sal_Bool bNeedScrollBox = bNeedVScroll && bNeedHScroll; >+ >+ sal_Bool bScrollbarsChanged = false; >+ if ( bHaveVScroll != bNeedVScroll ) >+ { >+ delete mpVScrollBar; >+ mpVScrollBar = bNeedVScroll ? new ScrollBar( pSvVCLMultiLineEdit, WB_VSCROLL|WB_DRAG ) : NULL; >+ >+ if ( bNeedVScroll ) >+ { >+ mpVScrollBar->Show(); >+ mpVScrollBar->SetScrollHdl( LINK( this, ImpSvMEdit, ScrollHdl ) ); >+ } >+ >+ bScrollbarsChanged = sal_True; >+ } >+ >+ if ( bHaveHScroll != bNeedHScroll ) >+ { >+ delete mpHScrollBar; >+ mpHScrollBar = bNeedHScroll ? new ScrollBar( pSvVCLMultiLineEdit, WB_HSCROLL|WB_DRAG ) : NULL; >+ >+ if ( bNeedHScroll ) >+ { >+ mpHScrollBar->Show(); >+ mpHScrollBar->SetScrollHdl( LINK( this, ImpSvMEdit, ScrollHdl ) ); >+ } >+ >+ bScrollbarsChanged = sal_True; >+ } >+ >+ if ( bHaveScrollBox != bNeedScrollBox ) >+ { >+ delete mpScrollBox; >+ mpScrollBox = bNeedScrollBox ? new ScrollBarBox( pSvVCLMultiLineEdit, WB_SIZEABLE ) : NULL; >+ >+ if ( bNeedScrollBox ) >+ mpScrollBox->Show(); >+ } >+ >+ if ( bScrollbarsChanged ) >+ { >+ ImpInitScrollBars(); >+ Resize(); >+ } >+} >+ >+void ImpSvMEdit::InitFromStyle( WinBits nWinStyle ) >+{ >+ ImpUpdateSrollBarVis( nWinStyle ); >+ SetAlign( nWinStyle ); >+ >+ if ( nWinStyle & WB_NOHIDESELECTION ) >+ mpTextWindow->SetAutoFocusHide( sal_False ); >+ else >+ mpTextWindow->SetAutoFocusHide( sal_True ); >+ >+ if ( nWinStyle & WB_READONLY ) >+ mpTextWindow->GetTextView()->SetReadOnly( sal_True ); >+ else >+ mpTextWindow->GetTextView()->SetReadOnly( sal_False ); >+ >+ if ( nWinStyle & WB_IGNORETAB ) >+ { >+ mpTextWindow->SetIgnoreTab( sal_True ); >+ } >+ else >+ { >+ mpTextWindow->SetIgnoreTab( sal_False ); >+ // #103667# VCLMultiLineEdit has the flag, but focusable window also needs this flag >+ WinBits nStyle = mpTextWindow->GetStyle(); >+ nStyle |= WINDOW_DLGCTRL_MOD1TAB; >+ mpTextWindow->SetStyle( nStyle ); >+ } >+} >+ >+ImpSvMEdit::~ImpSvMEdit() >+{ >+ EndListening( *mpTextWindow->GetTextEngine() ); >+ delete mpTextWindow; >+ delete mpHScrollBar; >+ delete mpVScrollBar; >+ delete mpScrollBox; >+} >+ >+void ImpSvMEdit::ImpSetScrollBarRanges() >+{ >+ if ( mpVScrollBar ) >+ { >+ sal_uLong nTextHeight = mpTextWindow->GetTextEngine()->GetTextHeight(); >+ mpVScrollBar->SetRange( Range( 0, (long)nTextHeight-1 ) ); >+ } >+ if ( mpHScrollBar ) >+ { >+// sal_uLong nTextWidth = mpTextWindow->GetTextEngine()->CalcTextWidth(); >+ // Es gibt kein Notify bei Breiten-Aenderung... >+// sal_uLong nW = Max( (sal_uLong)mpTextWindow->GetOutputSizePixel().Width()*5, (sal_uLong)nTextWidth ); >+// mpHScrollBar->SetRange( Range( 0, (long)nW ) ); >+ mpHScrollBar->SetRange( Range( 0, (long)mnTextWidth-1 ) ); >+ } >+} >+ >+void ImpSvMEdit::ImpInitScrollBars() >+{ >+ static const sal_Unicode sampleChar = { 'x' }; >+ if ( mpHScrollBar || mpVScrollBar ) >+ { >+ ImpSetScrollBarRanges(); >+ Size aCharBox; >+ aCharBox.Width() = mpTextWindow->GetTextWidth( rtl::OUString(sampleChar) ); >+ aCharBox.Height() = mpTextWindow->GetTextHeight(); >+ Size aOutSz = mpTextWindow->GetOutputSizePixel(); >+ if ( mpHScrollBar ) >+ { >+ mpHScrollBar->SetVisibleSize( aOutSz.Width() ); >+ mpHScrollBar->SetPageSize( aOutSz.Width() * 8 / 10 ); >+ mpHScrollBar->SetLineSize( aCharBox.Width()*10 ); >+ ImpSetHScrollBarThumbPos(); >+ } >+ if ( mpVScrollBar ) >+ { >+ mpVScrollBar->SetVisibleSize( aOutSz.Height() ); >+ mpVScrollBar->SetPageSize( aOutSz.Height() * 8 / 10 ); >+ mpVScrollBar->SetLineSize( aCharBox.Height() ); >+ mpVScrollBar->SetThumbPos( mpTextWindow->GetTextView()->GetStartDocPos().Y() ); >+ } >+ } >+} >+ >+void ImpSvMEdit::ImpSetHScrollBarThumbPos() >+{ >+ long nX = mpTextWindow->GetTextView()->GetStartDocPos().X(); >+ if ( !mpTextWindow->GetTextEngine()->IsRightToLeft() ) >+ mpHScrollBar->SetThumbPos( nX ); >+ else >+ mpHScrollBar->SetThumbPos( mnTextWidth - mpHScrollBar->GetVisibleSize() - nX ); >+ >+} >+ >+IMPL_LINK( ImpSvMEdit, ScrollHdl, ScrollBar*, pCurScrollBar ) >+{ >+ long nDiffX = 0, nDiffY = 0; >+ >+ if ( pCurScrollBar == mpVScrollBar ) >+ nDiffY = mpTextWindow->GetTextView()->GetStartDocPos().Y() - pCurScrollBar->GetThumbPos(); >+ else if ( pCurScrollBar == mpHScrollBar ) >+ nDiffX = mpTextWindow->GetTextView()->GetStartDocPos().X() - pCurScrollBar->GetThumbPos(); >+ >+ mpTextWindow->GetTextView()->Scroll( nDiffX, nDiffY ); >+ // mpTextWindow->GetTextView()->ShowCursor( sal_False, sal_True ); >+ >+ return 0; >+} >+ >+ >+// void ImpSvMEdit::ImpModified() >+// { >+// // Wann wird das gerufen ????????????????????? >+// pSvVCLMultiLineEdit->Modify(); >+// } >+ >+void ImpSvMEdit::SetAlign( WinBits nWinStyle ) >+{ >+ sal_Bool bRTL = Application::GetSettings().GetLayoutRTL(); >+ mpTextWindow->GetTextEngine()->SetRightToLeft( bRTL ); >+ >+ if ( nWinStyle & WB_CENTER ) >+ mpTextWindow->GetTextEngine()->SetTextAlign( TXTALIGN_CENTER ); >+ else if ( nWinStyle & WB_RIGHT ) >+ mpTextWindow->GetTextEngine()->SetTextAlign( !bRTL ? TXTALIGN_RIGHT : TXTALIGN_LEFT ); >+ else if ( nWinStyle & WB_LEFT ) >+ mpTextWindow->GetTextEngine()->SetTextAlign( !bRTL ? TXTALIGN_LEFT : TXTALIGN_RIGHT ); >+} >+ >+void ImpSvMEdit::SetModified( sal_Bool bMod ) >+{ >+ mpTextWindow->GetTextEngine()->SetModified( bMod ); >+} >+ >+sal_Bool ImpSvMEdit::IsModified() const >+{ >+ return mpTextWindow->GetTextEngine()->IsModified(); >+} >+ >+void ImpSvMEdit::SetReadOnly( sal_Bool bRdOnly ) >+{ >+ mpTextWindow->GetTextView()->SetReadOnly( bRdOnly ); >+ // Farbe anpassen ??????????????????????????? >+} >+ >+sal_Bool ImpSvMEdit::IsReadOnly() const >+{ >+ return mpTextWindow->GetTextView()->IsReadOnly(); >+} >+ >+void ImpSvMEdit::SetMaxTextLen( xub_StrLen nLen ) >+{ >+ mpTextWindow->GetTextEngine()->SetMaxTextLen( nLen ); >+} >+ >+xub_StrLen ImpSvMEdit::GetMaxTextLen() const >+{ >+ return sal::static_int_cast< xub_StrLen >( >+ mpTextWindow->GetTextEngine()->GetMaxTextLen()); >+} >+ >+void ImpSvMEdit::InsertText( const String& rStr ) >+{ >+ mpTextWindow->GetTextView()->InsertText( rStr ); >+} >+ >+String ImpSvMEdit::GetSelected() const >+{ >+ return mpTextWindow->GetTextView()->GetSelected(); >+} >+ >+String ImpSvMEdit::GetSelected( LineEnd aSeparator ) const >+{ >+ return mpTextWindow->GetTextView()->GetSelected( aSeparator ); >+} >+ >+void ImpSvMEdit::Resize() >+{ >+ size_t nIteration = 1; >+ do >+ { >+ WinBits nWinStyle( pSvVCLMultiLineEdit->GetStyle() ); >+ if ( ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL ) >+ ImpUpdateSrollBarVis( nWinStyle ); >+ >+ Size aSz = pSvVCLMultiLineEdit->GetOutputSizePixel(); >+ Size aEditSize = aSz; >+ long nSBWidth = pSvVCLMultiLineEdit->GetSettings().GetStyleSettings().GetScrollBarSize(); >+ nSBWidth = pSvVCLMultiLineEdit->CalcZoom( nSBWidth ); >+ >+ if ( mpHScrollBar ) >+ aSz.Height() -= nSBWidth+1; >+ if ( mpVScrollBar ) >+ aSz.Width() -= nSBWidth+1; >+ >+ if ( !mpHScrollBar ) >+ mpTextWindow->GetTextEngine()->SetMaxTextWidth( aSz.Width() ); >+ else >+ mpHScrollBar->SetPosSizePixel( 0, aEditSize.Height()-nSBWidth, aSz.Width(), nSBWidth ); >+ >+ Point aTextWindowPos( maTextWindowOffset ); >+ if ( mpVScrollBar ) >+ { >+ if( Application::GetSettings().GetLayoutRTL() ) >+ { >+ mpVScrollBar->SetPosSizePixel( 0, 0, nSBWidth, aSz.Height() ); >+ aTextWindowPos.X() += nSBWidth; >+ } >+ else >+ mpVScrollBar->SetPosSizePixel( aEditSize.Width()-nSBWidth, 0, nSBWidth, aSz.Height() ); >+ } >+ >+ if ( mpScrollBox ) >+ mpScrollBox->SetPosSizePixel( aSz.Width(), aSz.Height(), nSBWidth, nSBWidth ); >+ >+ Size aTextWindowSize( aSz ); >+ aTextWindowSize.Width() -= maTextWindowOffset.X(); >+ aTextWindowSize.Height() -= maTextWindowOffset.Y(); >+ if ( aTextWindowSize.Width() < 0 ) >+ aTextWindowSize.Width() = 0; >+ if ( aTextWindowSize.Height() < 0 ) >+ aTextWindowSize.Height() = 0; >+ >+ Size aOldTextWindowSize( mpTextWindow->GetSizePixel() ); >+ mpTextWindow->SetPosSizePixel( aTextWindowPos, aTextWindowSize ); >+ if ( aOldTextWindowSize == aTextWindowSize ) >+ break; >+ >+ // Changing the text window size might effectively have changed the need for >+ // scrollbars, so do another iteration. >+ ++nIteration; >+ OSL_ENSURE( nIteration < 3, "ImpSvMEdit::Resize: isn't this expected to terminate with the second iteration?" ); >+ >+ } while ( nIteration <= 3 ); // artificial break after four iterations >+ >+ ImpInitScrollBars(); >+} >+ >+void ImpSvMEdit::GetFocus() >+{ >+ mpTextWindow->GrabFocus(); >+} >+ >+void ImpSvMEdit::Cut() >+{ >+ if ( !mpTextWindow->GetTextView()->IsReadOnly() ) >+ mpTextWindow->GetTextView()->Cut(); >+} >+ >+void ImpSvMEdit::Copy() >+{ >+ mpTextWindow->GetTextView()->Copy(); >+} >+ >+void ImpSvMEdit::Paste() >+{ >+ if ( !mpTextWindow->GetTextView()->IsReadOnly() ) >+ mpTextWindow->GetTextView()->Paste(); >+} >+ >+void ImpSvMEdit::SetText( const String& rStr ) >+{ >+ sal_Bool bWasModified = mpTextWindow->GetTextEngine()->IsModified(); >+ mpTextWindow->GetTextEngine()->SetText( rStr ); >+ if ( !bWasModified ) >+ mpTextWindow->GetTextEngine()->SetModified( sal_False ); >+ >+ mpTextWindow->GetTextView()->SetSelection( TextSelection() ); >+ >+ WinBits nWinStyle( pSvVCLMultiLineEdit->GetStyle() ); >+ if ( ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL ) >+ ImpUpdateSrollBarVis( nWinStyle ); >+} >+ >+String ImpSvMEdit::GetText() const >+{ >+ return mpTextWindow->GetTextEngine()->GetText(); >+} >+ >+String ImpSvMEdit::GetText( LineEnd aSeparator ) const >+{ >+ return mpTextWindow->GetTextEngine()->GetText( aSeparator ); >+} >+ >+String ImpSvMEdit::GetTextLines( LineEnd aSeparator ) const >+{ >+ return mpTextWindow->GetTextEngine()->GetTextLines( aSeparator ); >+} >+ >+void ImpSvMEdit::Notify( SfxBroadcaster&, const SfxHint& rHint ) >+{ >+ if ( rHint.ISA( TextHint ) ) >+ { >+ const TextHint& rTextHint = (const TextHint&)rHint; >+ if( rTextHint.GetId() == TEXT_HINT_VIEWSCROLLED ) >+ { >+ if ( mpHScrollBar ) >+ ImpSetHScrollBarThumbPos(); >+ if ( mpVScrollBar ) >+ mpVScrollBar->SetThumbPos( mpTextWindow->GetTextView()->GetStartDocPos().Y() ); >+ } >+ else if( rTextHint.GetId() == TEXT_HINT_TEXTHEIGHTCHANGED ) >+ { >+ if ( mpTextWindow->GetTextView()->GetStartDocPos().Y() ) >+ { >+ long nOutHeight = mpTextWindow->GetOutputSizePixel().Height(); >+ long nTextHeight = mpTextWindow->GetTextEngine()->GetTextHeight(); >+ if ( nTextHeight < nOutHeight ) >+ mpTextWindow->GetTextView()->Scroll( 0, mpTextWindow->GetTextView()->GetStartDocPos().Y() ); >+ } >+ >+ ImpSetScrollBarRanges(); >+ } >+ else if( rTextHint.GetId() == TEXT_HINT_TEXTFORMATTED ) >+ { >+ if ( mpHScrollBar ) >+ { >+ sal_uLong nWidth = mpTextWindow->GetTextEngine()->CalcTextWidth(); >+ if ( nWidth != mnTextWidth ) >+ { >+ mnTextWidth = sal::static_int_cast< xub_StrLen >(nWidth); >+ mpHScrollBar->SetRange( Range( 0, (long)mnTextWidth-1 ) ); >+ ImpSetHScrollBarThumbPos(); >+ } >+ } >+ } >+ else if( rTextHint.GetId() == TEXT_HINT_MODIFIED ) >+ { >+ pSvVCLMultiLineEdit->Modify(); >+ } >+ } >+} >+ >+void ImpSvMEdit::SetSelection( const Selection& rSelection ) >+{ >+ String aText = mpTextWindow->GetTextEngine()->GetText(); >+ >+ Selection aNewSelection( rSelection ); >+ if ( aNewSelection.Min() < 0 ) >+ aNewSelection.Min() = 0; >+ else if ( aNewSelection.Min() > aText.Len() ) >+ aNewSelection.Min() = aText.Len(); >+ if ( aNewSelection.Max() < 0 ) >+ aNewSelection.Max() = 0; >+ else if ( aNewSelection.Max() > aText.Len() ) >+ aNewSelection.Max() = aText.Len(); >+ >+ long nEnd = Max( aNewSelection.Min(), aNewSelection.Max() ); >+ TextSelection aTextSel; >+ sal_uLong nPara = 0; >+ sal_uInt16 nChar = 0; >+ sal_uInt16 x = 0; >+ while ( x <= nEnd ) >+ { >+ if ( x == aNewSelection.Min() ) >+ aTextSel.GetStart() = TextPaM( nPara, nChar ); >+ if ( x == aNewSelection.Max() ) >+ aTextSel.GetEnd() = TextPaM( nPara, nChar ); >+ >+ if ( ( x < aText.Len() ) && ( aText.GetChar( x ) == '\n' ) ) >+ { >+ nPara++; >+ nChar = 0; >+ } >+ else >+ nChar++; >+ x++; >+ } >+ mpTextWindow->GetTextView()->SetSelection( aTextSel ); >+} >+ >+const Selection& ImpSvMEdit::GetSelection() const >+{ >+ maSelection = Selection(); >+ TextSelection aTextSel( mpTextWindow->GetTextView()->GetSelection() ); >+ aTextSel.Justify(); >+ // Selektion flachklopfen => jeder Umbruch ein Zeichen... >+ >+ ExtTextEngine* pTextEngine = mpTextWindow->GetTextEngine(); >+ // Absaetze davor: >+ sal_uLong n; >+ for ( n = 0; n < aTextSel.GetStart().GetPara(); n++ ) >+ { >+ maSelection.Min() += pTextEngine->GetTextLen( n ); >+ maSelection.Min()++; >+ } >+ >+ // Erster Absatz mit Selektion: >+ maSelection.Max() = maSelection.Min(); >+ maSelection.Min() += aTextSel.GetStart().GetIndex(); >+ >+ for ( n = aTextSel.GetStart().GetPara(); n < aTextSel.GetEnd().GetPara(); n++ ) >+ { >+ maSelection.Max() += pTextEngine->GetTextLen( n ); >+ maSelection.Max()++; >+ } >+ >+ maSelection.Max() += aTextSel.GetEnd().GetIndex(); >+ >+ return maSelection; >+} >+ >+Size ImpSvMEdit::CalcMinimumSize() const >+{ >+ Size aSz( mpTextWindow->GetTextEngine()->CalcTextWidth(), >+ mpTextWindow->GetTextEngine()->GetTextHeight() ); >+ >+ if ( mpHScrollBar ) >+ aSz.Height() += mpHScrollBar->GetSizePixel().Height(); >+ if ( mpVScrollBar ) >+ aSz.Width() += mpVScrollBar->GetSizePixel().Width(); >+ >+ return aSz; >+} >+ >+Size ImpSvMEdit::CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const >+{ >+ static const sal_Unicode sampleChar = 'X'; >+ >+ Size aSz; >+ Size aCharSz; >+ aCharSz.Width() = mpTextWindow->GetTextWidth( rtl::OUString(sampleChar) ); >+ aCharSz.Height() = mpTextWindow->GetTextHeight(); >+ >+ if ( nLines ) >+ aSz.Height() = nLines*aCharSz.Height(); >+ else >+ aSz.Height() = mpTextWindow->GetTextEngine()->GetTextHeight(); >+ >+ if ( nColumns ) >+ aSz.Width() = nColumns*aCharSz.Width(); >+ else >+ aSz.Width() = mpTextWindow->GetTextEngine()->CalcTextWidth(); >+ >+ if ( mpHScrollBar ) >+ aSz.Height() += mpHScrollBar->GetSizePixel().Height(); >+ if ( mpVScrollBar ) >+ aSz.Width() += mpVScrollBar->GetSizePixel().Width(); >+ >+ return aSz; >+} >+ >+void ImpSvMEdit::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const >+{ >+ static const sal_Unicode sampleChar = { 'x' }; >+ Size aOutSz = mpTextWindow->GetOutputSizePixel(); >+ Size aCharSz( mpTextWindow->GetTextWidth( rtl::OUString(sampleChar) ), mpTextWindow->GetTextHeight() ); >+ rnCols = (sal_uInt16) (aOutSz.Width()/aCharSz.Width()); >+ rnLines = (sal_uInt16) (aOutSz.Height()/aCharSz.Height()); >+} >+ >+void ImpSvMEdit::Enable( sal_Bool bEnable ) >+{ >+ mpTextWindow->Enable( bEnable ); >+ if ( mpHScrollBar ) >+ mpHScrollBar->Enable( bEnable ); >+ if ( mpVScrollBar ) >+ mpVScrollBar->Enable( bEnable ); >+} >+ >+sal_Bool ImpSvMEdit::HandleCommand( const CommandEvent& rCEvt ) >+{ >+ sal_Bool bDone = sal_False; >+ if ( ( rCEvt.GetCommand() == COMMAND_WHEEL ) || >+ ( rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL ) || >+ ( rCEvt.GetCommand() == COMMAND_AUTOSCROLL ) ) >+ { >+ mpTextWindow->HandleScrollCommand( rCEvt, mpHScrollBar, mpVScrollBar ); >+ bDone = sal_True; >+ } >+ return bDone; >+} >+ >+ >+TextWindow::TextWindow( Window* pParent ) : Window( pParent ) >+{ >+ mbInMBDown = sal_False; >+ mbSelectOnTab = sal_True; >+ mbFocusSelectionHide = sal_False; >+ mbIgnoreTab = sal_False; >+ mbActivePopup = sal_False; >+ mbSelectOnTab = sal_True; >+ mbTextSelectable = sal_True; >+ >+ SetPointer( Pointer( POINTER_TEXT ) ); >+ >+ mpTextEngine = new ExtTextEngine; >+ mpTextEngine->SetMaxTextLen( STRING_MAXLEN ); >+ if( pParent->GetStyle() & WB_BORDER ) >+ mpTextEngine->SetLeftMargin( 2 ); >+ mpTextEngine->SetLocale( GetSettings().GetLocale() ); >+ mpTextView = new ExtTextView( mpTextEngine, this ); >+ mpTextEngine->InsertView( mpTextView ); >+ mpTextEngine->EnableUndo( sal_True ); >+ mpTextView->ShowCursor(); >+ >+ Color aBackgroundColor = GetSettings().GetStyleSettings().GetWorkspaceColor(); >+ SetBackground( aBackgroundColor ); >+ pParent->SetBackground( aBackgroundColor ); >+} >+ >+TextWindow::~TextWindow() >+{ >+ delete mpTextView; >+ delete mpTextEngine; >+} >+ >+void TextWindow::MouseMove( const MouseEvent& rMEvt ) >+{ >+ mpTextView->MouseMove( rMEvt ); >+ Window::MouseMove( rMEvt ); >+} >+ >+void TextWindow::MouseButtonDown( const MouseEvent& rMEvt ) >+{ >+ if ( !mbTextSelectable ) >+ return; >+ >+ mbInMBDown = sal_True; // Dann im GetFocus nicht alles selektieren wird >+ mpTextView->MouseButtonDown( rMEvt ); >+ Window::MouseButtonDown( rMEvt ); >+ GrabFocus(); >+ mbInMBDown = sal_False; >+} >+ >+void TextWindow::MouseButtonUp( const MouseEvent& rMEvt ) >+{ >+ mpTextView->MouseButtonUp( rMEvt ); >+ Window::MouseButtonUp( rMEvt ); >+} >+ >+void TextWindow::KeyInput( const KeyEvent& rKEvent ) >+{ >+ sal_Bool bDone = sal_False; >+ sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode(); >+ if ( nCode == com::sun::star::awt::Key::SELECT_ALL || >+ ( (nCode == KEY_A) && rKEvent.GetKeyCode().IsMod1() && !rKEvent.GetKeyCode().IsMod2() ) >+ ) >+ { >+ mpTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( 0xFFFF, 0xFFFF ) ) ); >+ bDone = sal_True; >+ } >+ else if ( (nCode == KEY_S) && rKEvent.GetKeyCode().IsShift() && rKEvent.GetKeyCode().IsMod1() ) >+ { >+ if ( Edit::GetGetSpecialCharsFunction() ) >+ { >+ // Damit die Selektion erhalten bleibt >+ mbActivePopup = sal_True; >+ rtl::OUString aChars = Edit::GetGetSpecialCharsFunction()( this, GetFont() ); >+ if (!aChars.isEmpty()) >+ { >+ mpTextView->InsertText( aChars ); >+ mpTextView->GetTextEngine()->SetModified( sal_True ); >+ } >+ mbActivePopup = sal_False; >+ bDone = sal_True; >+ } >+ } >+ else if ( nCode == KEY_TAB ) >+ { >+ if ( !mbIgnoreTab || rKEvent.GetKeyCode().IsMod1() ) >+ bDone = mpTextView->KeyInput( rKEvent ); >+ } >+ else >+ { >+ bDone = mpTextView->KeyInput( rKEvent ); >+ } >+ >+ if ( !bDone ) >+ Window::KeyInput( rKEvent ); >+} >+ >+void TextWindow::Paint( const Rectangle& rRect ) >+{ >+ mpTextView->Paint( rRect ); >+} >+ >+void TextWindow::Resize() >+{ >+} >+ >+void TextWindow::Command( const CommandEvent& rCEvt ) >+{ >+ if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU ) >+ { >+ PopupMenu* pPopup = Edit::CreatePopupMenu(); >+ if ( !mpTextView->HasSelection() ) >+ { >+ pPopup->EnableItem( SV_MENU_EDIT_CUT, sal_False ); >+ pPopup->EnableItem( SV_MENU_EDIT_COPY, sal_False ); >+ pPopup->EnableItem( SV_MENU_EDIT_DELETE, sal_False ); >+ } >+ if ( mpTextView->IsReadOnly() ) >+ { >+ pPopup->EnableItem( SV_MENU_EDIT_CUT, sal_False ); >+ pPopup->EnableItem( SV_MENU_EDIT_PASTE, sal_False ); >+ pPopup->EnableItem( SV_MENU_EDIT_DELETE, sal_False ); >+ pPopup->EnableItem( SV_MENU_EDIT_INSERTSYMBOL, sal_False ); >+ } >+ if ( !mpTextView->GetTextEngine()->HasUndoManager() || !mpTextView->GetTextEngine()->GetUndoManager().GetUndoActionCount() ) >+ { >+ pPopup->EnableItem( SV_MENU_EDIT_UNDO, sal_False ); >+ } >+// if ( ( maSelection.Min() == 0 ) && ( maSelection.Max() == maText.Len() ) ) >+// { >+// pPopup->EnableItem( SV_MENU_EDIT_SELECTALL, sal_False ); >+// } >+ if ( !Edit::GetGetSpecialCharsFunction() ) >+ { >+ sal_uInt16 nPos = pPopup->GetItemPos( SV_MENU_EDIT_INSERTSYMBOL ); >+ pPopup->RemoveItem( nPos ); >+ pPopup->RemoveItem( nPos-1 ); >+ } >+ >+ mbActivePopup = sal_True; >+ Point aPos = rCEvt.GetMousePosPixel(); >+ if ( !rCEvt.IsMouseEvent() ) >+ { >+ // !!! Irgendwann einmal Menu zentriert in der Selektion anzeigen !!! >+ Size aSize = GetOutputSizePixel(); >+ aPos = Point( aSize.Width()/2, aSize.Height()/2 ); >+ } >+// pPopup->RemoveDisabledEntries(); >+ sal_uInt16 n = pPopup->Execute( this, aPos ); >+ Edit::DeletePopupMenu( pPopup ); >+ switch ( n ) >+ { >+ case SV_MENU_EDIT_UNDO: mpTextView->Undo(); >+ mpTextEngine->SetModified( sal_True ); >+ mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) ); >+ break; >+ case SV_MENU_EDIT_CUT: mpTextView->Cut(); >+ mpTextEngine->SetModified( sal_True ); >+ mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) ); >+ break; >+ case SV_MENU_EDIT_COPY: mpTextView->Copy(); >+ break; >+ case SV_MENU_EDIT_PASTE: mpTextView->Paste(); >+ mpTextEngine->SetModified( sal_True ); >+ mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) ); >+ break; >+ case SV_MENU_EDIT_DELETE: mpTextView->DeleteSelected(); >+ mpTextEngine->SetModified( sal_True ); >+ mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) ); >+ break; >+ case SV_MENU_EDIT_SELECTALL: mpTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( 0xFFFFFFFF, 0xFFFF ) ) ); >+ break; >+ case SV_MENU_EDIT_INSERTSYMBOL: >+ { >+ rtl::OUString aChars = Edit::GetGetSpecialCharsFunction()( this, GetFont() ); >+ if (!aChars.isEmpty()) >+ { >+ mpTextView->InsertText( aChars ); >+ mpTextEngine->SetModified( sal_True ); >+ mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) ); >+ } >+ } >+ break; >+ } >+ mbActivePopup = sal_False; >+ } >+ else >+ { >+ mpTextView->Command( rCEvt ); >+ } >+ Window::Command( rCEvt ); >+} >+ >+void TextWindow::GetFocus() >+{ >+ Window::GetFocus(); >+ if ( !mbActivePopup ) >+ { >+ sal_Bool bGotoCursor = !mpTextView->IsReadOnly(); >+ if ( mbFocusSelectionHide && IsReallyVisible() && !mpTextView->IsReadOnly() >+ && ( mbSelectOnTab && >+ (!mbInMBDown || ( GetSettings().GetStyleSettings().GetSelectionOptions() & SELECTION_OPTION_FOCUS ) )) ) >+ { >+ // Alles selektieren, aber nicht scrollen >+ sal_Bool bAutoScroll = mpTextView->IsAutoScroll(); >+ mpTextView->SetAutoScroll( sal_False ); >+ mpTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( 0xFFFF, 0xFFFF ) ) ); >+ mpTextView->SetAutoScroll( bAutoScroll ); >+ bGotoCursor = sal_False; >+ } >+ mpTextView->SetPaintSelection( sal_True ); >+ mpTextView->ShowCursor( bGotoCursor ); >+ } >+} >+ >+void TextWindow::LoseFocus() >+{ >+ Window::LoseFocus(); >+ >+ if ( mbFocusSelectionHide && !mbActivePopup ) >+ mpTextView->SetPaintSelection( sal_False ); >+} >+ >+VCLMultiLineEdit::VCLMultiLineEdit( Window* pParent, WinBits nWinStyle ) >+ : Edit( pParent, nWinStyle ) >+{ >+ SetType( WINDOW_MULTILINEEDIT ); >+ pImpSvMEdit = new ImpSvMEdit( this, nWinStyle ); >+ ImplInitSettings( sal_True, sal_True, sal_True ); >+ pUpdateDataTimer = 0; >+ >+ SetCompoundControl( sal_True ); >+ SetStyle( ImplInitStyle( nWinStyle ) ); >+} >+ >+VCLMultiLineEdit::VCLMultiLineEdit( Window* pParent, const ResId& rResId ) >+ : Edit( pParent, rResId.SetRT( RSC_MULTILINEEDIT ) ) >+{ >+ SetType( WINDOW_MULTILINEEDIT ); >+ WinBits nWinStyle = rResId.GetWinBits(); >+ pImpSvMEdit = new ImpSvMEdit( this, nWinStyle ); >+ ImplInitSettings( sal_True, sal_True, sal_True ); >+ pUpdateDataTimer = 0; >+ >+ sal_uInt16 nMaxLen = Edit::GetMaxTextLen(); >+ if ( nMaxLen ) >+ SetMaxTextLen( nMaxLen ); >+ >+ SetText( Edit::GetText() ); >+ >+ if ( IsVisible() ) >+ pImpSvMEdit->Resize(); >+ >+ SetCompoundControl( sal_True ); >+ SetStyle( ImplInitStyle( nWinStyle ) ); >+ >+ // Base Edit ctor could call Show already, but that would cause problems >+ // with accessibility, as Show might (indirectly) trigger a call to virtual >+ // GetComponentInterface, which is the Edit's base version instead of the >+ // VCLMultiLineEdit's version while in the base Edit ctor: >+ if ((GetStyle() & WB_HIDE) == 0) >+ Show(); >+ >+} >+ >+VCLMultiLineEdit::~VCLMultiLineEdit() >+{ >+ { >+ ::std::auto_ptr< ImpSvMEdit > pDelete( pImpSvMEdit ); >+ pImpSvMEdit = NULL; >+ } >+ delete pUpdateDataTimer; >+} >+ >+WinBits VCLMultiLineEdit::ImplInitStyle( WinBits nStyle ) >+{ >+ if ( !(nStyle & WB_NOTABSTOP) ) >+ nStyle |= WB_TABSTOP; >+ >+ if ( !(nStyle & WB_NOGROUP) ) >+ nStyle |= WB_GROUP; >+ >+ if ( !(nStyle & WB_IGNORETAB )) >+ nStyle |= WINDOW_DLGCTRL_MOD1TAB; >+ >+ return nStyle; >+} >+ >+ >+void VCLMultiLineEdit::ImplInitSettings( sal_Bool /*bFont*/, sal_Bool /*bForeground*/, sal_Bool bBackground ) >+{ >+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); >+ >+ // Der Font muss immer mit manipuliert werden, weil die TextEngine >+ // sich nicht um TextColor/Background kuemmert >+ >+ Color aTextColor = rStyleSettings.GetFieldTextColor(); >+ if ( IsControlForeground() ) >+ aTextColor = GetControlForeground(); >+ if ( !IsEnabled() ) >+ aTextColor = rStyleSettings.GetDisableColor(); >+ >+ Font aFont = rStyleSettings.GetFieldFont(); >+ if ( IsControlFont() ) >+ aFont.Merge( GetControlFont() ); >+ aFont.SetTransparent( IsPaintTransparent() ); >+ SetZoomedPointFont( aFont ); >+ Font TheFont = GetFont(); >+ TheFont.SetColor( aTextColor ); >+ if( IsPaintTransparent() ) >+ TheFont.SetFillColor( Color( COL_TRANSPARENT ) ); >+ else >+ TheFont.SetFillColor( IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor() ); >+ pImpSvMEdit->GetTextWindow()->SetFont( TheFont ); >+ pImpSvMEdit->GetTextWindow()->GetTextEngine()->SetFont( TheFont ); >+ pImpSvMEdit->GetTextWindow()->SetTextColor( aTextColor ); >+ >+ if ( bBackground ) >+ { >+ if( IsPaintTransparent() ) >+ { >+ pImpSvMEdit->GetTextWindow()->SetPaintTransparent( sal_True ); >+ pImpSvMEdit->GetTextWindow()->SetBackground(); >+ pImpSvMEdit->GetTextWindow()->SetControlBackground(); >+ SetBackground(); >+ SetControlBackground(); >+ } >+ else >+ { >+ if( IsControlBackground() ) >+ pImpSvMEdit->GetTextWindow()->SetBackground( GetControlBackground() ); >+ else >+ pImpSvMEdit->GetTextWindow()->SetBackground( rStyleSettings.GetFieldColor() ); >+ // Auch am VCLMultiLineEdit einstellen, weil die TextComponent >+ // ggf. die Scrollbars hidet. >+ SetBackground( pImpSvMEdit->GetTextWindow()->GetBackground() ); >+ } >+ } >+} >+ >+void VCLMultiLineEdit::Modify() >+{ >+ aModifyHdlLink.Call( this ); >+ >+ CallEventListeners( VCLEVENT_EDIT_MODIFY ); >+ >+ if ( pUpdateDataTimer ) >+ pUpdateDataTimer->Start(); >+} >+ >+IMPL_LINK_NOARG(VCLMultiLineEdit, ImpUpdateDataHdl) >+{ >+ UpdateData(); >+ return 0; >+} >+ >+void VCLMultiLineEdit::UpdateData() >+{ >+ aUpdateDataHdlLink.Call( this ); >+} >+ >+void VCLMultiLineEdit::SetModifyFlag() >+{ >+ pImpSvMEdit->SetModified( sal_True ); >+} >+ >+void VCLMultiLineEdit::ClearModifyFlag() >+{ >+ pImpSvMEdit->SetModified( sal_False ); >+} >+ >+sal_Bool VCLMultiLineEdit::IsModified() const >+{ >+ return pImpSvMEdit->IsModified(); >+} >+ >+void VCLMultiLineEdit::EnableUpdateData( sal_uLong nTimeout ) >+{ >+ if ( !nTimeout ) >+ DisableUpdateData(); >+ else >+ { >+ if ( !pUpdateDataTimer ) >+ { >+ pUpdateDataTimer = new Timer; >+ pUpdateDataTimer->SetTimeoutHdl( LINK( this, VCLMultiLineEdit, ImpUpdateDataHdl ) ); >+ } >+ pUpdateDataTimer->SetTimeout( nTimeout ); >+ } >+} >+ >+void VCLMultiLineEdit::SetReadOnly( sal_Bool bReadOnly ) >+{ >+ pImpSvMEdit->SetReadOnly( bReadOnly ); >+ Edit::SetReadOnly( bReadOnly ); >+ >+ // #94921# ReadOnly can be overwritten in InitFromStyle() when WB not set. >+ WinBits nStyle = GetStyle(); >+ if ( bReadOnly ) >+ nStyle |= WB_READONLY; >+ else >+ nStyle &= ~WB_READONLY; >+ SetStyle( nStyle ); >+} >+ >+sal_Bool VCLMultiLineEdit::IsReadOnly() const >+{ >+ return pImpSvMEdit->IsReadOnly(); >+} >+ >+void VCLMultiLineEdit::SetMaxTextLen( xub_StrLen nMaxLen ) >+{ >+ pImpSvMEdit->SetMaxTextLen( nMaxLen ); >+} >+ >+xub_StrLen VCLMultiLineEdit::GetMaxTextLen() const >+{ >+ return pImpSvMEdit->GetMaxTextLen(); >+} >+ >+void VCLMultiLineEdit::ReplaceSelected( const String& rStr ) >+{ >+ pImpSvMEdit->InsertText( rStr ); >+} >+ >+void VCLMultiLineEdit::DeleteSelected() >+{ >+ pImpSvMEdit->InsertText( String() ); >+} >+ >+String VCLMultiLineEdit::GetSelected() const >+{ >+ return pImpSvMEdit->GetSelected(); >+} >+ >+String VCLMultiLineEdit::GetSelected( LineEnd aSeparator ) const >+{ >+ return pImpSvMEdit->GetSelected( aSeparator ); >+} >+ >+void VCLMultiLineEdit::Cut() >+{ >+ pImpSvMEdit->Cut(); >+} >+ >+void VCLMultiLineEdit::Copy() >+{ >+ pImpSvMEdit->Copy(); >+} >+ >+void VCLMultiLineEdit::Paste() >+{ >+ pImpSvMEdit->Paste(); >+} >+ >+void VCLMultiLineEdit::SetText( const String& rStr ) >+{ >+ pImpSvMEdit->SetText( rStr ); >+} >+ >+String VCLMultiLineEdit::GetText() const >+{ >+ return pImpSvMEdit->GetText(); >+} >+ >+String VCLMultiLineEdit::GetText( LineEnd aSeparator ) const >+{ >+ return pImpSvMEdit->GetText( aSeparator ); >+} >+ >+String VCLMultiLineEdit::GetTextLines( LineEnd aSeparator ) const >+{ >+ return pImpSvMEdit->GetTextLines( aSeparator ); >+} >+ >+void VCLMultiLineEdit::Resize() >+{ >+ pImpSvMEdit->Resize(); >+} >+ >+void VCLMultiLineEdit::GetFocus() >+{ >+ if ( !pImpSvMEdit ) // might be called from within the dtor, when pImpSvMEdit == NULL is a valid state >+ return; >+ >+ Edit::GetFocus(); >+ pImpSvMEdit->GetFocus(); >+} >+ >+void VCLMultiLineEdit::SetSelection( const Selection& rSelection ) >+{ >+ pImpSvMEdit->SetSelection( rSelection ); >+} >+ >+const Selection& VCLMultiLineEdit::GetSelection() const >+{ >+ return pImpSvMEdit->GetSelection(); >+} >+ >+Size VCLMultiLineEdit::CalcMinimumSize() const >+{ >+ Size aSz = pImpSvMEdit->CalcMinimumSize(); >+ >+ sal_Int32 nLeft, nTop, nRight, nBottom; >+ ((Window*)this)->GetBorder( nLeft, nTop, nRight, nBottom ); >+ aSz.Width() += nLeft+nRight; >+ aSz.Height() += nTop+nBottom; >+ >+ return aSz; >+} >+ >+Size VCLMultiLineEdit::CalcAdjustedSize( const Size& rPrefSize ) const >+{ >+ Size aSz = rPrefSize; >+ sal_Int32 nLeft, nTop, nRight, nBottom; >+ ((Window*)this)->GetBorder( nLeft, nTop, nRight, nBottom ); >+ >+ // In der Hoehe auf ganze Zeilen justieren >+ >+ long nHeight = aSz.Height() - nTop - nBottom; >+ long nLineHeight = pImpSvMEdit->CalcSize( 1, 1 ).Height(); >+ long nLines = nHeight / nLineHeight; >+ if ( nLines < 1 ) >+ nLines = 1; >+ >+ aSz.Height() = nLines * nLineHeight; >+ aSz.Height() += nTop+nBottom; >+ >+ return aSz; >+} >+ >+Size VCLMultiLineEdit::CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const >+{ >+ Size aSz = pImpSvMEdit->CalcSize( nColumns, nLines ); >+ >+ sal_Int32 nLeft, nTop, nRight, nBottom; >+ ((Window*)this)->GetBorder( nLeft, nTop, nRight, nBottom ); >+ aSz.Width() += nLeft+nRight; >+ aSz.Height() += nTop+nBottom; >+ return aSz; >+} >+ >+void VCLMultiLineEdit::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const >+{ >+ pImpSvMEdit->GetMaxVisColumnsAndLines( rnCols, rnLines ); >+} >+ >+void VCLMultiLineEdit::StateChanged( StateChangedType nType ) >+{ >+ if( nType == STATE_CHANGE_ENABLE ) >+ { >+ pImpSvMEdit->Enable( IsEnabled() ); >+ ImplInitSettings( sal_True, sal_False, sal_False ); >+ } >+ else if( nType == STATE_CHANGE_READONLY ) >+ { >+ pImpSvMEdit->SetReadOnly( IsReadOnly() ); >+ } >+ else if ( nType == STATE_CHANGE_ZOOM ) >+ { >+ pImpSvMEdit->GetTextWindow()->SetZoom( GetZoom() ); >+ ImplInitSettings( sal_True, sal_False, sal_False ); >+ Resize(); >+ } >+ else if ( nType == STATE_CHANGE_CONTROLFONT ) >+ { >+ ImplInitSettings( sal_True, sal_False, sal_False ); >+ Resize(); >+ Invalidate(); >+ } >+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) >+ { >+ ImplInitSettings( sal_False, sal_True, sal_False ); >+ Invalidate(); >+ } >+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) >+ { >+ ImplInitSettings( sal_False, sal_False, sal_True ); >+ Invalidate(); >+ } >+ else if ( nType == STATE_CHANGE_STYLE ) >+ { >+ pImpSvMEdit->InitFromStyle( GetStyle() ); >+ SetStyle( ImplInitStyle( GetStyle() ) ); >+ } >+ else if ( nType == STATE_CHANGE_INITSHOW ) >+ { >+ if( IsPaintTransparent() ) >+ { >+ pImpSvMEdit->GetTextWindow()->SetPaintTransparent( sal_True ); >+ pImpSvMEdit->GetTextWindow()->SetBackground(); >+ pImpSvMEdit->GetTextWindow()->SetControlBackground(); >+ SetBackground(); >+ SetControlBackground(); >+ } >+ } >+ >+ Control::StateChanged( nType ); >+} >+ >+void VCLMultiLineEdit::DataChanged( const DataChangedEvent& rDCEvt ) >+{ >+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && >+ (rDCEvt.GetFlags() & SETTINGS_STYLE) ) >+ { >+ ImplInitSettings( sal_True, sal_True, sal_True ); >+ Resize(); >+ Invalidate(); >+ } >+ else >+ Control::DataChanged( rDCEvt ); >+} >+ >+void VCLMultiLineEdit::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags ) >+{ >+ ImplInitSettings( sal_True, sal_True, sal_True ); >+ >+ Point aPos = pDev->LogicToPixel( rPos ); >+ Size aSize = pDev->LogicToPixel( rSize ); >+ Font aFont = pImpSvMEdit->GetTextWindow()->GetDrawPixelFont( pDev ); >+ aFont.SetTransparent( sal_True ); >+ OutDevType eOutDevType = pDev->GetOutDevType(); >+ >+ pDev->Push(); >+ pDev->SetMapMode(); >+ pDev->SetFont( aFont ); >+ pDev->SetTextFillColor(); >+ >+ // Border/Background >+ pDev->SetLineColor(); >+ pDev->SetFillColor(); >+ sal_Bool bBorder = !(nFlags & WINDOW_DRAW_NOBORDER ) && (GetStyle() & WB_BORDER); >+ sal_Bool bBackground = !(nFlags & WINDOW_DRAW_NOBACKGROUND) && IsControlBackground(); >+ if ( bBorder || bBackground ) >+ { >+ Rectangle aRect( aPos, aSize ); >+ if ( bBorder ) >+ { >+ DecorationView aDecoView( pDev ); >+ aRect = aDecoView.DrawFrame( aRect, FRAME_DRAW_DOUBLEIN ); >+ } >+ if ( bBackground ) >+ { >+ pDev->SetFillColor( GetControlBackground() ); >+ pDev->DrawRect( aRect ); >+ } >+ } >+ >+ // Inhalt >+ if ( ( nFlags & WINDOW_DRAW_MONO ) || ( eOutDevType == OUTDEV_PRINTER ) ) >+ pDev->SetTextColor( Color( COL_BLACK ) ); >+ else >+ { >+ if ( !(nFlags & WINDOW_DRAW_NODISABLE ) && !IsEnabled() ) >+ { >+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); >+ pDev->SetTextColor( rStyleSettings.GetDisableColor() ); >+ } >+ else >+ { >+ pDev->SetTextColor( GetTextColor() ); >+ } >+ } >+ >+ rtl::OUString aText = GetText(); >+ Size aTextSz( pDev->GetTextWidth( aText ), pDev->GetTextHeight() ); >+ sal_uLong nLines = (sal_uLong) (aSize.Height() / aTextSz.Height()); >+ if ( !nLines ) >+ nLines = 1; >+ aTextSz.Height() = nLines*aTextSz.Height(); >+ long nOnePixel = GetDrawPixel( pDev, 1 ); >+ long nOffX = 3*nOnePixel; >+ long nOffY = 2*nOnePixel; >+ >+ // Clipping? >+ if ( ( nOffY < 0 ) || ( (nOffY+aTextSz.Height()) > aSize.Height() ) || ( (nOffX+aTextSz.Width()) > aSize.Width() ) ) >+ { >+ Rectangle aClip( aPos, aSize ); >+ if ( aTextSz.Height() > aSize.Height() ) >+ aClip.Bottom() += aTextSz.Height() - aSize.Height() + 1; // Damit HP-Drucker nicht 'weg-optimieren' >+ pDev->IntersectClipRegion( aClip ); >+ } >+ >+ ExtTextEngine aTE; >+ aTE.SetText( GetText() ); >+ aTE.SetMaxTextWidth( aSize.Width() ); >+ aTE.SetFont( aFont ); >+ aTE.SetTextAlign( pImpSvMEdit->GetTextWindow()->GetTextEngine()->GetTextAlign() ); >+ aTE.Draw( pDev, Point( aPos.X() + nOffX, aPos.Y() + nOffY ) ); >+ >+ pDev->Pop(); >+} >+ >+long VCLMultiLineEdit::Notify( NotifyEvent& rNEvt ) >+{ >+ long nDone = 0; >+ if( rNEvt.GetType() == EVENT_COMMAND ) >+ { >+ nDone = pImpSvMEdit->HandleCommand( *rNEvt.GetCommandEvent() ); >+ } >+ return nDone ? nDone : Edit::Notify( rNEvt ); >+} >+ >+long VCLMultiLineEdit::PreNotify( NotifyEvent& rNEvt ) >+{ >+ long nDone = 0; >+ >+#if (OSL_DEBUG_LEVEL > 1) && defined(DBG_UTIL) >+ if( rNEvt.GetType() == EVENT_KEYINPUT ) >+ { >+ const KeyEvent& rKEvent = *rNEvt.GetKeyEvent(); >+ if ( ( rKEvent.GetKeyCode().GetCode() == KEY_W ) && rKEvent.GetKeyCode().IsMod1() && rKEvent.GetKeyCode().IsMod2() ) >+ { >+ SetRightToLeft( !IsRightToLeft() ); >+ } >+ } >+#endif >+ >+ if( ( rNEvt.GetType() == EVENT_KEYINPUT ) && ( !GetTextView()->IsCursorEnabled() ) ) >+ { >+ const KeyEvent& rKEvent = *rNEvt.GetKeyEvent(); >+ if ( !rKEvent.GetKeyCode().IsShift() && ( rKEvent.GetKeyCode().GetGroup() == KEYGROUP_CURSOR ) ) >+ { >+ nDone = 1; >+ TextSelection aSel = pImpSvMEdit->GetTextWindow()->GetTextView()->GetSelection(); >+ if ( aSel.HasRange() ) >+ { >+ aSel.GetStart() = aSel.GetEnd(); >+ pImpSvMEdit->GetTextWindow()->GetTextView()->SetSelection( aSel ); >+ } >+ else >+ { >+ switch ( rKEvent.GetKeyCode().GetCode() ) >+ { >+ case KEY_UP: >+ { >+ if ( pImpSvMEdit->GetVScrollBar() ) >+ pImpSvMEdit->GetVScrollBar()->DoScrollAction( SCROLL_LINEUP ); >+ } >+ break; >+ case KEY_DOWN: >+ { >+ if ( pImpSvMEdit->GetVScrollBar() ) >+ pImpSvMEdit->GetVScrollBar()->DoScrollAction( SCROLL_LINEDOWN ); >+ } >+ break; >+ case KEY_PAGEUP : >+ { >+ if ( pImpSvMEdit->GetVScrollBar() ) >+ pImpSvMEdit->GetVScrollBar()->DoScrollAction( SCROLL_PAGEUP ); >+ } >+ break; >+ case KEY_PAGEDOWN: >+ { >+ if ( pImpSvMEdit->GetVScrollBar() ) >+ pImpSvMEdit->GetVScrollBar()->DoScrollAction( SCROLL_PAGEDOWN ); >+ } >+ break; >+ case KEY_LEFT: >+ { >+ if ( pImpSvMEdit->GetHScrollBar() ) >+ pImpSvMEdit->GetHScrollBar()->DoScrollAction( SCROLL_LINEUP ); >+ } >+ break; >+ case KEY_RIGHT: >+ { >+ if ( pImpSvMEdit->GetHScrollBar() ) >+ pImpSvMEdit->GetHScrollBar()->DoScrollAction( SCROLL_LINEDOWN ); >+ } >+ break; >+ case KEY_HOME: >+ { >+ if ( rKEvent.GetKeyCode().IsMod1() ) >+ pImpSvMEdit->GetTextWindow()->GetTextView()-> >+ SetSelection( TextSelection( TextPaM( 0, 0 ) ) ); >+ } >+ break; >+ case KEY_END: >+ { >+ if ( rKEvent.GetKeyCode().IsMod1() ) >+ pImpSvMEdit->GetTextWindow()->GetTextView()-> >+ SetSelection( TextSelection( TextPaM( 0xFFFF, 0xFFFF ) ) ); >+ } >+ break; >+ default: >+ { >+ nDone = 0; >+ } >+ } >+ } >+ } >+ } >+ >+ return nDone ? nDone : Edit::PreNotify( rNEvt ); >+} >+ >+// >+// Internas fuer abgeleitete Klassen, z.B. TextComponent >+ >+ExtTextEngine* VCLMultiLineEdit::GetTextEngine() const >+{ >+ return pImpSvMEdit->GetTextWindow()->GetTextEngine(); >+} >+ >+ExtTextView* VCLMultiLineEdit::GetTextView() const >+{ >+ return pImpSvMEdit->GetTextWindow()->GetTextView(); >+} >+ >+ScrollBar* VCLMultiLineEdit::GetVScrollBar() const >+{ >+ return pImpSvMEdit->GetVScrollBar(); >+} >+ >+void VCLMultiLineEdit::EnableFocusSelectionHide( sal_Bool bHide ) >+{ >+ pImpSvMEdit->GetTextWindow()->SetAutoFocusHide( bHide ); >+} >+ >+void VCLMultiLineEdit::SetLeftMargin( sal_uInt16 n ) >+{ >+ if ( GetTextEngine() ) >+ GetTextEngine()->SetLeftMargin( n ); >+} >+ >+void VCLMultiLineEdit::SetRightToLeft( sal_Bool bRightToLeft ) >+{ >+ if ( GetTextEngine() ) >+ { >+ GetTextEngine()->SetRightToLeft( bRightToLeft ); >+ GetTextView()->ShowCursor(); >+ } >+} >+ >+sal_Bool VCLMultiLineEdit::IsRightToLeft() const >+{ >+ sal_Bool bRightToLeft = sal_False; >+ >+ if ( GetTextEngine() ) >+ bRightToLeft = GetTextEngine()->IsRightToLeft(); >+ >+ return bRightToLeft; >+} >+ >+void VCLMultiLineEdit::DisableSelectionOnFocus() >+{ >+ pImpSvMEdit->GetTextWindow()->DisableSelectionOnFocus(); >+} >+ >+void VCLMultiLineEdit::SetTextSelectable( sal_Bool bTextSelectable ) >+{ >+ pImpSvMEdit->GetTextWindow()->SetTextSelectable( bTextSelectable ); >+} >+ >+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/vcl/source/edit/xtextedt.cxx b/vcl/source/edit/xtextedt.cxx >new file mode 100644 >index 0000000..c434ad0 >--- /dev/null >+++ b/vcl/source/edit/xtextedt.cxx >@@ -0,0 +1,421 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >+/************************************************************************* >+ * >+ * 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 <vcl/xtextedt.hxx> >+#include <vcl/svapp.hxx> // International >+#include <unotools/textsearch.hxx> >+#include <com/sun/star/util/SearchOptions.hpp> >+#include <com/sun/star/util/SearchFlags.hpp> >+ >+using namespace ::com::sun::star; >+ >+ >+ >+// ------------------------------------------------------------------------- >+// class ExtTextEngine >+// ------------------------------------------------------------------------- >+ExtTextEngine::ExtTextEngine() : maGroupChars(rtl::OUString("(){}[]")) >+{ >+} >+ >+ExtTextEngine::~ExtTextEngine() >+{ >+} >+ >+TextSelection ExtTextEngine::MatchGroup( const TextPaM& rCursor ) const >+{ >+ TextSelection aSel( rCursor ); >+ sal_uInt16 nPos = rCursor.GetIndex(); >+ sal_uLong nPara = rCursor.GetPara(); >+ sal_uLong nParas = GetParagraphCount(); >+ if ( ( nPara < nParas ) && ( nPos < GetTextLen( nPara ) ) ) >+ { >+ sal_uInt16 nMatchChar = maGroupChars.Search( GetText( rCursor.GetPara() ).GetChar( nPos ) ); >+ if ( nMatchChar != STRING_NOTFOUND ) >+ { >+ if ( ( nMatchChar % 2 ) == 0 ) >+ { >+ // Vorwaerts suchen... >+ sal_Unicode nSC = maGroupChars.GetChar( nMatchChar ); >+ sal_Unicode nEC = maGroupChars.GetChar( nMatchChar+1 ); >+ >+ sal_uInt16 nCur = nPos+1; >+ sal_uInt16 nLevel = 1; >+ while ( nLevel && ( nPara < nParas ) ) >+ { >+ XubString aStr = GetText( nPara ); >+ while ( nCur < aStr.Len() ) >+ { >+ if ( aStr.GetChar( nCur ) == nSC ) >+ nLevel++; >+ else if ( aStr.GetChar( nCur ) == nEC ) >+ { >+ nLevel--; >+ if ( !nLevel ) >+ break; // while nCur... >+ } >+ nCur++; >+ } >+ >+ if ( nLevel ) >+ { >+ nPara++; >+ nCur = 0; >+ } >+ } >+ if ( nLevel == 0 ) // gefunden >+ { >+ aSel.GetStart() = rCursor; >+ aSel.GetEnd() = TextPaM( nPara, nCur+1 ); >+ } >+ } >+ else >+ { >+ // Rueckwaerts suchen... >+ xub_Unicode nEC = maGroupChars.GetChar( nMatchChar ); >+ xub_Unicode nSC = maGroupChars.GetChar( nMatchChar-1 ); >+ >+ sal_uInt16 nCur = rCursor.GetIndex()-1; >+ sal_uInt16 nLevel = 1; >+ while ( nLevel ) >+ { >+ if ( GetTextLen( nPara ) ) >+ { >+ XubString aStr = GetText( nPara ); >+ while ( nCur ) >+ { >+ if ( aStr.GetChar( nCur ) == nSC ) >+ { >+ nLevel--; >+ if ( !nLevel ) >+ break; // while nCur... >+ } >+ else if ( aStr.GetChar( nCur ) == nEC ) >+ nLevel++; >+ >+ nCur--; >+ } >+ } >+ >+ if ( nLevel ) >+ { >+ if ( nPara ) >+ { >+ nPara--; >+ nCur = GetTextLen( nPara )-1; // egal ob negativ, weil if Len() >+ } >+ else >+ break; >+ } >+ } >+ >+ if ( nLevel == 0 ) // gefunden >+ { >+ aSel.GetStart() = rCursor; >+ aSel.GetStart().GetIndex()++; // hinter das Zeichen >+ aSel.GetEnd() = TextPaM( nPara, nCur ); >+ } >+ } >+ } >+ } >+ return aSel; >+} >+ >+sal_Bool ExtTextEngine::Search( TextSelection& rSel, const util::SearchOptions& rSearchOptions, sal_Bool bForward ) >+{ >+ TextSelection aSel( rSel ); >+ aSel.Justify(); >+ >+ sal_Bool bSearchInSelection = (0 != (rSearchOptions.searchFlag & util::SearchFlags::REG_NOT_BEGINOFLINE) ); >+ >+ TextPaM aStartPaM( aSel.GetEnd() ); >+ if ( aSel.HasRange() && ( ( bSearchInSelection && bForward ) || ( !bSearchInSelection && !bForward ) ) ) >+ { >+ aStartPaM = aSel.GetStart(); >+ } >+ >+ bool bFound = false; >+ sal_uLong nStartNode, nEndNode; >+ >+ if ( bSearchInSelection ) >+ nEndNode = bForward ? aSel.GetEnd().GetPara() : aSel.GetStart().GetPara(); >+ else >+ nEndNode = bForward ? (GetParagraphCount()-1) : 0; >+ >+ nStartNode = aStartPaM.GetPara(); >+ >+ util::SearchOptions aOptions( rSearchOptions ); >+ aOptions.Locale = Application::GetSettings().GetLocale(); >+ utl::TextSearch aSearcher( rSearchOptions ); >+ >+ // ueber die Absaetze iterieren... >+ for ( sal_uLong nNode = nStartNode; >+ bForward ? ( nNode <= nEndNode) : ( nNode >= nEndNode ); >+ bForward ? nNode++ : nNode-- ) >+ { >+ String aText = GetText( nNode ); >+ sal_uInt16 nStartPos = 0; >+ sal_uInt16 nEndPos = aText.Len(); >+ if ( nNode == nStartNode ) >+ { >+ if ( bForward ) >+ nStartPos = aStartPaM.GetIndex(); >+ else >+ nEndPos = aStartPaM.GetIndex(); >+ } >+ if ( ( nNode == nEndNode ) && bSearchInSelection ) >+ { >+ if ( bForward ) >+ nEndPos = aSel.GetEnd().GetIndex(); >+ else >+ nStartPos = aSel.GetStart().GetIndex(); >+ } >+ >+ if ( bForward ) >+ bFound = aSearcher.SearchFrwrd( aText, &nStartPos, &nEndPos ); >+ else >+ bFound = aSearcher.SearchBkwrd( aText, &nEndPos, &nStartPos ); >+ >+ if ( bFound ) >+ { >+ rSel.GetStart().GetPara() = nNode; >+ rSel.GetStart().GetIndex() = nStartPos; >+ rSel.GetEnd().GetPara() = nNode; >+ rSel.GetEnd().GetIndex() = nEndPos; >+ // Ueber den Absatz selektieren? >+ // Select over the paragraph? >+ // FIXME This should be max long... >+ if( nEndPos == sal::static_int_cast<sal_uInt16>(-1) ) // sal_uInt16 for 0 and -1 ! >+ { >+ if ( (rSel.GetEnd().GetPara()+1) < GetParagraphCount() ) >+ { >+ rSel.GetEnd().GetPara()++; >+ rSel.GetEnd().GetIndex() = 0; >+ } >+ else >+ { >+ rSel.GetEnd().GetIndex() = nStartPos; >+ bFound = false; >+ } >+ } >+ >+ break; >+ } >+ >+ if ( !bForward && !nNode ) // Bei rueckwaertsuche, wenn nEndNode = 0: >+ break; >+ } >+ >+ return bFound; >+} >+ >+ >+// ------------------------------------------------------------------------- >+// class ExtTextView >+// ------------------------------------------------------------------------- >+ExtTextView::ExtTextView( ExtTextEngine* pEng, Window* pWindow ) >+ : TextView( pEng, pWindow ) >+{ >+} >+ >+ExtTextView::~ExtTextView() >+{ >+} >+ >+sal_Bool ExtTextView::MatchGroup() >+{ >+ TextSelection aTmpSel( GetSelection() ); >+ aTmpSel.Justify(); >+ if ( ( aTmpSel.GetStart().GetPara() != aTmpSel.GetEnd().GetPara() ) || >+ ( ( aTmpSel.GetEnd().GetIndex() - aTmpSel.GetStart().GetIndex() ) > 1 ) ) >+ { >+ return sal_False; >+ } >+ >+ TextSelection aMatchSel = ((ExtTextEngine*)GetTextEngine())->MatchGroup( aTmpSel.GetStart() ); >+ if ( aMatchSel.HasRange() ) >+ SetSelection( aMatchSel ); >+ >+ return aMatchSel.HasRange() ? sal_True : sal_False; >+} >+ >+sal_Bool ExtTextView::Search( const util::SearchOptions& rSearchOptions, sal_Bool bForward ) >+{ >+ sal_Bool bFound = sal_False; >+ TextSelection aSel( GetSelection() ); >+ if ( ((ExtTextEngine*)GetTextEngine())->Search( aSel, rSearchOptions, bForward ) ) >+ { >+ bFound = sal_True; >+ // Erstmal den Anfang des Wortes als Selektion einstellen, >+ // damit das ganze Wort in den sichtbaren Bereich kommt. >+ SetSelection( aSel.GetStart() ); >+ ShowCursor( sal_True, sal_False ); >+ } >+ else >+ { >+ aSel = GetSelection().GetEnd(); >+ } >+ >+ SetSelection( aSel ); >+ ShowCursor(); >+ >+ return bFound; >+} >+ >+sal_uInt16 ExtTextView::Replace( const util::SearchOptions& rSearchOptions, sal_Bool bAll, sal_Bool bForward ) >+{ >+ sal_uInt16 nFound = 0; >+ >+ if ( !bAll ) >+ { >+ if ( GetSelection().HasRange() ) >+ { >+ InsertText( rSearchOptions.replaceString ); >+ nFound = 1; >+ Search( rSearchOptions, bForward ); // gleich zum naechsten >+ } >+ else >+ { >+ if( Search( rSearchOptions, bForward ) ) >+ nFound = 1; >+ } >+ } >+ else >+ { >+ // Der Writer ersetzt alle, vom Anfang bis Ende... >+ >+ ExtTextEngine* pTextEngine = (ExtTextEngine*)GetTextEngine(); >+ >+ // HideSelection(); >+ TextSelection aSel; >+ >+ sal_Bool bSearchInSelection = (0 != (rSearchOptions.searchFlag & util::SearchFlags::REG_NOT_BEGINOFLINE) ); >+ if ( bSearchInSelection ) >+ { >+ aSel = GetSelection(); >+ aSel.Justify(); >+ } >+ >+ TextSelection aSearchSel( aSel ); >+ >+ sal_Bool bFound = pTextEngine->Search( aSel, rSearchOptions, sal_True ); >+ if ( bFound ) >+ pTextEngine->UndoActionStart(); >+ while ( bFound ) >+ { >+ nFound++; >+ >+ TextPaM aNewStart = pTextEngine->ImpInsertText( aSel, rSearchOptions.replaceString ); >+ aSel = aSearchSel; >+ aSel.GetStart() = aNewStart; >+ bFound = pTextEngine->Search( aSel, rSearchOptions, sal_True ); >+ } >+ if ( nFound ) >+ { >+ SetSelection( aSel.GetStart() ); >+ pTextEngine->FormatAndUpdate( this ); >+ pTextEngine->UndoActionEnd(); >+ } >+ } >+ return nFound; >+} >+ >+sal_Bool ExtTextView::ImpIndentBlock( sal_Bool bRight ) >+{ >+ sal_Bool bDone = sal_False; >+ >+ TextSelection aSel = GetSelection(); >+ aSel.Justify(); >+ >+ HideSelection(); >+ GetTextEngine()->UndoActionStart(); >+ >+ sal_uLong nStartPara = aSel.GetStart().GetPara(); >+ sal_uLong nEndPara = aSel.GetEnd().GetPara(); >+ if ( aSel.HasRange() && !aSel.GetEnd().GetIndex() ) >+ { >+ nEndPara--; // den dann nicht einruecken... >+ } >+ >+ for ( sal_uLong nPara = nStartPara; nPara <= nEndPara; nPara++ ) >+ { >+ if ( bRight ) >+ { >+ // Tabs hinzufuegen >+ GetTextEngine()->ImpInsertText( TextPaM( nPara, 0 ), '\t' ); >+ bDone = sal_True; >+ } >+ else >+ { >+ // Tabs/Blanks entfernen >+ String aText = GetTextEngine()->GetText( nPara ); >+ if ( aText.Len() && ( >+ ( aText.GetChar( 0 ) == '\t' ) || >+ ( aText.GetChar( 0 ) == ' ' ) ) ) >+ { >+ GetTextEngine()->ImpDeleteText( TextSelection( TextPaM( nPara, 0 ), TextPaM( nPara, 1 ) ) ); >+ bDone = sal_True; >+ } >+ } >+ } >+ >+ GetTextEngine()->UndoActionEnd(); >+ >+ sal_Bool bRange = aSel.HasRange(); >+ if ( bRight ) >+ { >+ aSel.GetStart().GetIndex()++; >+ if ( bRange && ( aSel.GetEnd().GetPara() == nEndPara ) ) >+ aSel.GetEnd().GetIndex()++; >+ } >+ else >+ { >+ if ( aSel.GetStart().GetIndex() ) >+ aSel.GetStart().GetIndex()--; >+ if ( bRange && aSel.GetEnd().GetIndex() ) >+ aSel.GetEnd().GetIndex()--; >+ } >+ >+ ImpSetSelection( aSel ); >+ GetTextEngine()->FormatAndUpdate( this ); >+ >+ return bDone; >+} >+ >+sal_Bool ExtTextView::IndentBlock() >+{ >+ return ImpIndentBlock( sal_True ); >+} >+ >+sal_Bool ExtTextView::UnindentBlock() >+{ >+ return ImpIndentBlock( sal_False ); >+} >+ >+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >diff --git a/vcl/source/window/msgbox.cxx b/vcl/source/window/msgbox.cxx >index 7d49f3e..2c20bab 100644 >--- a/vcl/source/window/msgbox.cxx >+++ b/vcl/source/window/msgbox.cxx >@@ -38,6 +38,7 @@ > #include <vcl/svapp.hxx> > #include <vcl/wrkwin.hxx> > #include <vcl/fixed.hxx> >+#include <vcl/vclmedit.hxx> > #include <vcl/msgbox.hxx> > #include <vcl/button.hxx> > #include <vcl/mnemonic.hxx> >@@ -66,7 +67,7 @@ static void ImplInitMsgBoxImageList() > > void MessBox::ImplInitMessBoxData() > { >- mpFixedText = NULL; >+ mpVCLMultiLineEdit = NULL; > mpFixedImage = NULL; > mbHelpBtn = sal_False; > mpCheckBox = NULL; >@@ -203,7 +204,7 @@ void MessBox::ImplLoadRes( const ResId& ) > > MessBox::~MessBox() > { >- delete mpFixedText; >+ delete mpVCLMultiLineEdit; > delete mpFixedImage; > delete mpCheckBox; > } >@@ -236,16 +237,16 @@ void MessBox::ImplPosControls() > Point aTextPos( IMPL_DIALOG_OFFSET, IMPL_DIALOG_OFFSET+IMPL_MSGBOX_OFFSET_EXTRA_Y ); > Size aImageSize; > Size aPageSize; >- Size aFixedSize; >+ Size aMEditSize; > long nTitleWidth; > long nButtonSize = ImplGetButtonSize(); > long nMaxWidth = GetDesktopRectPixel().GetWidth()-8; > long nMaxLineWidth; > long nWidth; >- WinBits nWinStyle = WB_LEFT | WB_WORDBREAK | WB_NOLABEL | WB_INFO; >+ WinBits nWinStyle = WB_LEFT | WB_WORDBREAK | WB_NOLABEL; > sal_uInt16 nTextStyle = TEXT_DRAW_MULTILINE | TEXT_DRAW_TOP | TEXT_DRAW_LEFT; > >- delete mpFixedText; >+ delete mpVCLMultiLineEdit; > if ( mpFixedImage ) > { > delete mpFixedImage; >@@ -325,25 +326,27 @@ void MessBox::ImplPosControls() > aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo ); > } > >- // Style fuer FixedText ermitteln >+ // Style fuer VCLMultiLineEdit ermitteln >+ mpVCLMultiLineEdit = new VCLMultiLineEdit( this, nWinStyle ); >+ mpVCLMultiLineEdit->SetText( aMessText ); >+ aMEditSize = mpVCLMultiLineEdit->CalcMinimumSize(); >+ > aPageSize.Width() = aImageSize.Width(); >- aFixedSize.Width() = aTextInfo.GetMaxLineWidth()+1; >- aFixedSize.Height() = aFormatRect.GetHeight(); >- if ( aFixedSize.Height() < aImageSize.Height() ) >+ if ( aMEditSize.Height() < aImageSize.Height() ) > { > nWinStyle |= WB_VCENTER; > aPageSize.Height() = aImageSize.Height(); >- aFixedSize.Height() = aImageSize.Height(); >+ aMEditSize.Height() = aImageSize.Height(); > } > else > { > nWinStyle |= WB_TOP; >- aPageSize.Height() = aFixedSize.Height(); >+ aPageSize.Height() = aMEditSize.Height(); > } > if ( aImageSize.Width() ) > aPageSize.Width() += IMPL_SEP_MSGBOX_IMAGE; > aPageSize.Width() += (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_X*2); >- aPageSize.Width() += aFixedSize.Width()+1; >+ aPageSize.Width() += aMEditSize.Width()+1; > aPageSize.Height() += (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_Y*2); > > if ( aPageSize.Width() < IMPL_MINSIZE_MSGBOX_WIDTH ) >@@ -353,7 +356,7 @@ void MessBox::ImplPosControls() > > if ( maCheckBoxText.Len() ) > { >- Size aMinCheckboxSize ( aFixedSize ); >+ Size aMinCheckboxSize ( aMEditSize ); > if ( aPageSize.Width() < IMPL_MINSIZE_MSGBOX_WIDTH+80 ) > { > aPageSize.Width() = IMPL_MINSIZE_MSGBOX_WIDTH+80; >@@ -388,7 +391,7 @@ void MessBox::ImplPosControls() > mpCheckBox->SetText( maCheckBoxText ); > > Point aPos( aTextPos ); >- aPos.Y() += aFixedSize.Height() + (IMPL_DIALOG_OFFSET)+(IMPL_MSGBOX_OFFSET_EXTRA_Y*2); >+ aPos.Y() += aMEditSize.Height() + (IMPL_DIALOG_OFFSET)+(IMPL_MSGBOX_OFFSET_EXTRA_Y*2); > > // increase messagebox > aPageSize.Height() += aSize.Height() + (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_Y*2); >@@ -397,12 +400,10 @@ void MessBox::ImplPosControls() > mpCheckBox->Show(); > } > >- mpFixedText = new FixedText( this, nWinStyle ); >- if( mpFixedText->GetStyle() & WB_EXTRAOFFSET ) // TODO: use CalcMinimumSize() instead >- aFixedSize.Width() += 2; >- mpFixedText->SetPosSizePixel( aTextPos, aFixedSize ); >- mpFixedText->SetText( aMessText ); >- mpFixedText->Show(); >+ >+ mpVCLMultiLineEdit->SetPosSizePixel( aTextPos, aMEditSize ); >+ mpVCLMultiLineEdit->Show(); >+ mpVCLMultiLineEdit->SetPaintTransparent(sal_True); > SetPageSizePixel( aPageSize ); > } > >-- >1.7.7 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 46193
:
57175
|
57774
|
57870
|
57871
|
65167
|
65203
|
117433