From b01573861cdcb32619c7745055e14823b865a12d Mon Sep 17 00:00:00 2001 From: Kurt Zenker Date: Fri, 11 Sep 2009 14:29:45 +0000 Subject: CWS-TOOLING: integrate CWS odfmetadata3 2009-09-11 Michael Stahl merge DEV300_m58 2009-09-07 Michael Stahl SwFmtFld::Modify(): do nothing on RES_OBJECTDYING 2009-08-27 Michael Stahl #i91565#, #i91566#: TextPortionEnumerationTest.java: add test document 2009-08-27 Michael Stahl #i91565#, #i91566#: add complex test: TextPortionEnumerationTest.java 2009-08-27 Michael Stahl CLiteral::initialize(): zero-length literals probably not an error 2009-08-27 Michael Stahl #i91565#, #i91566#: offapi: new InContentMetadata and MetadataField services adapt TextPortion for InContentMetadata 2009-08-27 Michael Stahl #i91564#: xmloff: load/store xml:id and RDFa for text:bookmark(-start). 2009-08-27 Michael Stahl #i91564#: sw core: add support for xml:id at bookmarks: sw::mark::Bookmark: derive from Metadatable. SwHistoryBookmark, SaveBookmark: store a MetadatableUndo. ndcopy.cxx: lcl_CopyBookmarks(): copy the xml:id. SwXBookmark: derive from MetadatableMixin. 2009-08-27 Michael Stahl #i91565#, #i91566#: xmloff: refactor ruby import so nested meta(-field) works: remove XMLRubyHint_Impl. XMLImpRubyContext_Impl::~XMLImpRubyContext_Impl(): insert ruby directly. 2009-08-27 Michael Stahl #i91565#, #i91566#: xmloff: fix text:meta(-field) import/export: new XMLTextParagraphExport::exportTextField() overload for XTextField. CreateAndInsertMark(): set xml:id after insertion. fix meta(-field) service names, bugs etc. 2009-08-27 Michael Stahl #i91565#, #i91566#: sw text formatting: paint background of meta(-field) body: SwFont: add member m_nMetaCount. txttypes.hxx: add POR_META. atrstck.cxx: handle RES_TXTATR_META(FIELD). itrform2.cxx: SwTxtFormatter::WhichTxtPor(): create new class SwMetaPortion. 2009-08-27 Michael Stahl #i91566#: sw text formatting: display meta-field prefix and suffix: SwAttrIter::GetAttr(): replace with call to GetTxtAttrForCharAt(). SwTxtFormatter::NewExtraPortion(): handle meta-field prefix. SwTxtFormatter: new member m_nHintEndIndex. SwTxtFormatter::WhichFirstPortion(): call TryNewNoLengthPortion(). SwTxtFormatter::TryNewNoLengthPortion(): new; handle suffix of meta-field. SwTxtFormatter::UnderFlow(): UGLY HACK: decrement m_nHintEndIndex. SwFldPortion: add flag m_bNoLength: portion has zero length (for suffix). 2009-08-27 Michael Stahl #i91565#, #i91566#: extend text:meta(-field) uno wrapper with XText interface: unoobj.hxx: new CursorType CURSOR_META. unoobj2.cxx: refactor SwXText implementation to ensure that when the SwXText belongs to a SwXMeta, content is always inserted inside the meta(-field). unoobj.cxx: new SwXTextCursor::ForceIntoMeta(): cursor stays in meta(-field). unometa.hxx: SwXMeta implements XText, forwarding to a member SwXMetaText. DocInsertStringSplitCR(), SwX*::attachToRange(), SwX*::DeleteAndInsert(): use FORCEHINTEXPAND hack to ensure insert into the meta(-field) at the end. 2009-08-27 Michael Stahl #i91565#, #i91566#: add text:meta(-field) uno wrapper to sw: fmtmeta.hxx, fmtatr2.cxx: new class sw::MetaField, new sw::MetaFieldManager. doc.hxx, docnew.cxx: new SwDoc::GetMetaFieldManager(). unocoll.hxx,.cxx: new SW_SERVICE_FIELDTYPE_METAFIELD, SW_SERVICE_TYPE_META. unomap.hxx,.cxx: new PROPERTY_MAP_METAFIELD. unoprnms.hxx: new UNO_NAME_META. unoport.hxx: new PORTION_META; add "InContentMetadata" prop to SwXTextPortion. new unometa.hxx: new class SwXMeta and SwXMetaField. unofield.cxx: SwXFieldEnumeration: include meta-fields. unoportenum.cxx: handle RES_TXTATR_META(FIELD) by using a portion list stack. unotext.cxx: SwXText::insertTextContent(): handle meta(-field) as attribute. 2009-08-27 Michael Stahl #i91565#, #i91566#: ndhints.cxx: remove sort number from SwTxtAttrNesting 2009-08-27 Michael Stahl #i91565#, #i91566#: add support for hints with end and CH_TXTATR to sw core: doc.hxx, docedt.cxx: replace SwDoc::Delete(), DeleteAndJoin(), ReplaceRange() with wrappers that split at left-overlapped end+CH_TXTATR hints. txatbase.hxx: new member SwTxtAttr::m_bHasDummyChar. ndtxt.hxx: rename SwTxtNode::GetTxtAttr() to GetTxtAttrForCharAt(). ndtxt.cxx: SwTxtNode::CopyText(): copy end+CH_TXTATR hints iff copy CH_TXTATR. txtatr2.cxx, thints.cxx: SwTxtMeta gets a CH_TXTATR. 2009-08-27 Michael Stahl #i91565#, #i91566#: add text:meta(-field) to sw core: txatbase.hxx: new member SwTxtAttr::m_bNesting. hintids.hxx: new ids RES_TXTATR_META, RES_TXTATR_METAFIELD. txtatr.hxx: new base class SwTxtAttrNesting. new hint SwTxtMeta. SwTxtRuby derives from SwTxtAttrNesting. txtinet.hxx: SwTxtINetFmt derives from SwTxtAttrNesting. new header fmtmeta.hxx: new pool item SwFmtMeta. new class sw::Meta. ndhints.hxx, thints.cxx: new method SwpHints::TryInsertNesting(). thints.cxx: refactoring: BuildPortions() no longer handles Ruby/Hyperlink, but TryInsertNesting(), which also handles meta(-field). SwTxtNode::InsertItem(): check if the hint is actually inserted. ndhints.cxx: sort nesting hints based on sort number. ndtxt.cxx: lcl_CopyHint(): handle copy of meta/meta-field. 2009-08-27 Michael Stahl enable expanding hints with m_bLockExpandFlag set: add new InsertFlag: INS_FORCEHINTEXPAND. add new SetAttrMode: SETATTR_FORCEHINTEXPAND. rename SwEditShell::Insert() to Insert2() because changed signature fails to compile when SwWrtShell tries to overwrite these non-virtual members... SwWrtShell::Insert() sets FOCEHINTEXPAND if range was selected/deleted. adapt SwUndoInsert to store flags. 2009-08-27 Michael Stahl change formal parameters of item insertion methods to type SetAttrMode 2009-08-27 Michael Stahl fix incorrect resetting of text attributes in SwUndoInsSection, SwUndoInserts 2009-08-27 Michael Stahl clean up SwTxtNode::CutImpl() and lcl_CopyHint() 2009-08-27 Michael Stahl rename SwDoc::Copy() to CopyRange(), and _Copy() to CopyImpl() 2009-08-27 Michael Stahl rename SwNodes::Move() to MoveRange(), and remove unused parameter 2009-08-27 Michael Stahl rename SwDoc::Move() to MoveRange()/MoveNodeRange() 2009-08-27 Michael Stahl rename SwDoc::Insert() to InsertString(), and remove sal_Unicode variant 2009-08-27 Michael Stahl rename SwDoc::Insert() to InsertPoolItem()/InsertItemSet()/InsertSwSection() 2009-08-27 Michael Stahl rename SwDoc::Replace() to ReplaceRange() 2009-08-27 Michael Stahl remove SwDoc::Overwrite() sal_Unicode variant 2009-08-27 Michael Stahl split up SwDoc::DeleteAndJoin(): factor out DeleteAndJoinWithRedline() 2009-08-27 Michael Stahl rename overloaded SwDoc::Delete() to DeleteRange()/DeleteTOXMark() 2009-08-27 Michael Stahl rename SwTxtNode::Copy() to CopyText() 2009-08-27 Michael Stahl rename SwTxtNode::Cut() to CutText(), and _Cut() to CutImpl() 2009-08-27 Michael Stahl rename SwTxtNode::Delete() to DeleteAttribute()/DeleteAttributes() 2009-08-27 Michael Stahl rename SwTxtNode::Replace() to ReplaceText(), and remove the xub_Unicode variant 2009-08-27 Michael Stahl rename SwTxtNode::Erase() to EraseText() 2009-08-27 Michael Stahl rename SwTxtNode::Insert() to InsertText(), and remove the xub_Unicode variant 2009-08-27 Michael Stahl clean up SwTxtNode::Update() 2009-08-27 Michael Stahl remove SwTxtAttr::RemoveFromPool() and make destructor non-public, to be invoked by new method SwTxtAttr::Destroy() 2009-08-27 Michael Stahl ensure that SwDoc::Insert() for item (set) returns success indicator: replace SwRegHistory constructor with method InsertItems(), returning bool. refactor InsAttr() so that it checks if InsertItems() succeeds. 2009-08-27 Michael Stahl move SwXTextPortionEnumeration from unoobj.hxx to unoport.hxx 2009-08-27 Michael Stahl add missing SolarMutex in SwXTextPortion methods 2009-08-27 Michael Stahl SwXTextPortion: new member m_xTextField (so the TextField property need not be returned indirectly via SwUnoCursorHelper). factor out function CreateSwXTextField(). 2009-08-27 Michael Stahl SwXTextPortion: remove PORTION_CONTROL_CHAR and implementation of XTextField 2009-08-27 Michael Stahl remove obsolete hint SwTxtHardBlank and formats SwFmtHardBlank/SwFmtSoftHyph 2009-08-27 Michael Stahl clean up SwTxtAttr and friends: remove many accessor methods for obsolete (due to autofmt) char format items. remove unused flag SwTxtAttr::m_bDontMergeAttr. MakeRedlineTxtAttr() now dedicated function, no longer calls MakeTxtAttr(). 2009-08-27 Michael Stahl remove obsolete attribute SwTxt2Lines 2009-08-27 Michael Stahl SwXTextPortionEnumeration: finish refactoring CreatePortions change ExportHints so it always returns a text portion for hint w/ CH_TXTATR. remove special case for handling end of paragraph. unfortunately had to refactor the fieldmarks export as well (got in the way). 2009-08-27 Michael Stahl SwXTextPortionEnumeration: refactor CreatePortions: frames export extract function ExportFrames() from CreatePortions(). remove (un)dead code that calls evil MovePara(fnParaCurr, fnParaEnd) 2009-08-27 Michael Stahl clean up SwXParaFrameEnumeration 2009-08-27 Michael Stahl CollectFrameAtNode: replace SwDependArr with STL based FrameDependList_t 2009-08-27 Michael Stahl SwXTextPortionEnumeration: tweak refmark/toxmark export so ExportHints returns the portion for point marks 2009-08-27 Michael Stahl clean up SwXTextPortionEnumeration: prefix members, remove casts, replace SvWeirdArray with STL, etc. make CreatePortions() method a function, and remove lots of members. extract fieldmarks function from CreatePortions. 2009-08-27 Michael Stahl remove FOREACHUNOPAM_START/END macros 2009-08-27 Michael Stahl clean up SwXTextPortion: prefix members, remove casts, etc. remove SwXRubyPortion: replace it with another SwXTextPortion constructor 2009-08-27 Michael Stahl #i102541# SwXReferenceMark::InsertRefMark(): use flag SETATTR_DONTEXPAND 2009-08-27 Michael Stahl rename SwTxtNode::Insert to SwTxtNode::InsertHint, and fix constness in SwTxtNode::InsertItem 2009-08-27 Michael Stahl turn SwTxtNode::MakeTxtAttr() methods into global functions in ndhints.hxx 2009-08-27 Michael Stahl remove obsolete sw/inc/bookmrk.hxx 2009-08-27 Michael Stahl pam.cxx: fix ComparePosition functions (returned wrong result in one case) 2009-08-27 Michael Stahl #i103613# only import RDF metadata on normal open of a document 2009-09-11 kz CWS-TOOLING: integrate CWS impress176 2009-09-08 20:18:24 +0200 sj r275957 : fixed warning (shadowed variable) 2009-09-08 18:02:05 +0200 cl r275948 : #i104315# added missing tab pages 2009-09-08 17:35:18 +0200 cl r275947 : #i104866# fixed angle import 2009-09-08 17:32:53 +0200 cl r275946 : #i104841# fixed angle import 2009-09-08 17:01:25 +0200 cl r275943 : #i103935# fixed the SID_EVENTCONFIG mess 2009-09-08 14:32:57 +0200 sj r275928 : #i104685# only comments 2009-09-07 12:37:36 +0200 sj r275886 : #i104683# fixed import of bold/italic attributes for normal text shapes 2009-09-04 15:07:46 +0200 sj r275808 : #104689# fixed bullet color problem 2009-09-03 15:25:07 +0200 sj r275753 : #160200# added vertical alignment of table cells 2009-09-11 kz CWS-TOOLING: integrate CWS dv14 2009-09-10 15:16:32 +0200 sg r276035 : #160513# updated wfs scheme to accept ports 2009-09-10 07:41:47 +0200 dv r276019 : #i104942# Better renaming algorithmen 2009-08-31 13:41:11 +0200 dv r275604 : #160505# Setting APP1PRODUCTNAME must not overwrite APP1PRODUCTDEF 2009-09-11 kz CWS-TOOLING: integrate CWS jl131 2009-09-02 16:42:40 +0200 jl r275720 : #i97896# 2009-08-31 13:01:53 +0200 jl r275599 : CWS-TOOLING: rebase CWS jl131 to trunk@275331 (milestone: DEV300:m56) 2009-07-31 14:35:30 +0200 jl r274531 : CWS-TOOLING: rebase CWS jl131 to trunk@274203 (milestone: DEV300:m53) 2009-07-23 14:20:32 +0200 jl r274272 : #i79839# better error text when trying to modify shared layer without having write permission, eg. unopkg add --shared, unopkg remove --shared, unopkg reinstall --shared 2009-07-22 16:38:02 +0200 jl r274252 : #i97896# localize error message for lock file 2009-07-22 16:37:22 +0200 jl r274251 : #i80462# unprecise wording in updatedialog 2009-07-22 16:36:06 +0200 jl r274250 : #i97896# localize error message for lock file 2009-07-22 16:35:20 +0200 jl r274249 : #i97896# localize error message for lock file 2009-07-22 15:07:30 +0200 jl r274242 : #i98873# minimum java version is 1.5 since OOo 3.0 2009-09-11 kz CWS-TOOLING: integrate CWS changehc 2009-08-31 19:38:50 +0200 pl r275633 : remove dbug printf 2009-08-31 17:41:50 +0200 pl r275623 : CWS-TOOLING: rebase CWS changehc to trunk@275331 (milestone: DEV300:m56) 2009-07-15 19:45:46 +0200 pl r274028 : #i35482# use HC flag to decide high contrast mode 2009-07-15 17:40:52 +0200 pl r274020 : #i35482# use HC flag to decide high contrast mode 2009-07-15 17:39:50 +0200 pl r274019 : #i35482# update autohc correctly in MergeSystemSettings 2009-07-15 17:38:57 +0200 pl r274018 : #i35482# update autohc correctly in MergeSystemSettings 2009-09-11 kz CWS-TOOLING: integrate CWS notes10 2009-08-24 07:25:57 +0200 mod r275287 : 2009-07-26 02:38:32 +0200 mod r274343 : #i#i103645# 2009-07-26 02:01:53 +0200 mod r274342 : #i103645# 2009-07-26 01:52:42 +0200 mod r274341 : #i103490# 2009-07-22 08:31:48 +0200 mod r274215 : #i103373# 2009-07-15 00:55:11 +0200 mod r273987 : #i101419# 2009-07-14 07:07:55 +0200 mod r273956 : #i101419# 2009-07-14 07:07:43 +0200 mod r273955 : #i101419# 2009-07-14 07:02:10 +0200 mod r273954 : changes from notes9 2009-07-14 06:14:25 +0200 mod r273953 : #i103476# 2009-09-11 kz CWS-TOOLING: integrate CWS ab70 2009-09-10 15:12:54 +0200 jsk r276034 : #i85434# - mandatory automatic update test 2009-09-10 15:11:06 +0200 jsk r276033 : #i85434# - mandatory automatic update test 2009-09-02 09:49:24 +0200 ab r275698 : #i85434# Dialog Import 2009-09-11 kz CWS-TOOLING: integrate CWS hb32bugs02 2009-09-02 Henning Brinkmann #i102420# revert changes 2009-08-26 Henning Brinkmann merged DEV300_m56 2009-08-19 Henning Brinkmann merged DEV300_m55 2009-08-14 Henning Brinkmann merged changes from wntmsci12 2009-08-12 Henning Brinkmann Implemented NoSpaceEdit constructor and destructor in .cxx to allow compile with debug on wntmsci12. 2009-08-12 Henning Brinkmann Added some SW_DLLPUBLIC to make compilable on wntmsci12. 2009-08-11 Henning Brinkmann #i102420# dbg_out: surround output for SwNodes with . 2009-08-10 Henning Brinkmann #i102420# rewritten debug output for SwNodes. 2009-08-07 Henning Brinkmann #i102420# debug _MoveNodes: output the destination, too. Break after two iterations. 2009-08-07 Henning Brinkmann #i102420# _MoveNodes: Additionally check if destination index is inside source => false Check if current range was already handled => loop Debug output current range 2009-08-06 Henning Brinkmann merged DEV300_m54 2009-08-06 Henning Brinkmann added master fix 2009-08-06 Henning Brinkmann debug output for SwNodeRange 2009-08-04 Henning Brinkmann #i102844# robustness: check for NULL pointer to prevent crash 2009-08-03 Henning Brinkmann #i103475# applied patch and verified 2009-08-03 Henning Brinkmann Removed code preventing build of sw with DEBUG. 2009-09-11 convert-repo update tags 2009-09-10 kz CWS-TOOLING: integrate CWS os2port06dev300 2009-09-05 22:49:00 +0200 ydario r275858 : #i99588# applied os2port06 diff to DEV300 tree. 2009-09-10 kz CWS-TOOLING: integrate CWS mingwport23 2009-08-29 07:07:53 +0200 tono r275555 : i#104522: mingw port graphite 2009-08-29 07:07:26 +0200 tono r275554 : i#104522: mingw port printf format fix 2009-09-10 kz CWS-TOOLING: integrate CWS mh232 2009-08-26 03:52:57 +0200 mh r275385 : #i102182# FreeBSD patch 2009-08-26 03:43:20 +0200 mh r275384 : #i101333# patch for FreeBSD 2009-08-26 03:11:20 +0200 mh r275383 : #i39230 2009-08-26 03:07:51 +0200 mh r275382 : #i39230# more space for initials field 2009-08-26 02:41:19 +0200 mh r275380 : #i39230# use vos::osecurity for reading the user name 2009-08-18 22:06:00 +0200 mh r275130 : #i104243#, line ending problem with newer perl 2009-08-18 21:53:21 +0200 mh r275129 : #i39230# read initials via getpwnam 2009-08-18 21:34:05 +0200 mh r275128 : enable CAIROCANVAS for Linux and Mac, #i88613# 2009-08-17 18:02:59 +0200 mh r275067 : #i95498# make compile with gcc3 2009-09-10 kz CWS-TOOLING: integrate CWS tkr24 2009-09-07 14:31:06 +0200 is r275898 : #160081# adding NO_LICENSE_INTO_COPYRIGHT 2009-09-10 releng #i10000# change KeyMapping to SingletonRef 2009-09-11 convert-repo update tags 2009-09-10 kz CWS-TOOLING: integrate CWS os2port06dev300 2009-09-05 22:49:00 +0200 ydario r275858 : #i99588# applied os2port06 diff to DEV300 tree. 2009-09-10 kz CWS-TOOLING: integrate CWS mingwport23 2009-08-29 07:07:53 +0200 tono r275555 : i#104522: mingw port graphite 2009-08-29 07:07:26 +0200 tono r275554 : i#104522: mingw port printf format fix 2009-09-10 kz CWS-TOOLING: integrate CWS mh232 2009-08-26 03:52:57 +0200 mh r275385 : #i102182# FreeBSD patch 2009-08-26 03:43:20 +0200 mh r275384 : #i101333# patch for FreeBSD 2009-08-26 03:11:20 +0200 mh r275383 : #i39230 2009-08-26 03:07:51 +0200 mh r275382 : #i39230# more space for initials field 2009-08-26 02:41:19 +0200 mh r275380 : #i39230# use vos::osecurity for reading the user name 2009-08-18 22:06:00 +0200 mh r275130 : #i104243#, line ending problem with newer perl 2009-08-18 21:53:21 +0200 mh r275129 : #i39230# read initials via getpwnam 2009-08-18 21:34:05 +0200 mh r275128 : enable CAIROCANVAS for Linux and Mac, #i88613# 2009-08-17 18:02:59 +0200 mh r275067 : #i95498# make compile with gcc3 2009-09-10 kz CWS-TOOLING: integrate CWS tkr24 2009-09-07 14:31:06 +0200 is r275898 : #160081# adding NO_LICENSE_INTO_COPYRIGHT 2009-09-10 releng #i10000# change KeyMapping to SingletonRef --- sw/qa/complex/writer/makefile.mk | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'sw/qa') diff --git a/sw/qa/complex/writer/makefile.mk b/sw/qa/complex/writer/makefile.mk index 7bcc7fe934c9..de5200d47142 100755 --- a/sw/qa/complex/writer/makefile.mk +++ b/sw/qa/complex/writer/makefile.mk @@ -41,7 +41,7 @@ PACKAGE = complex$/writer #----- compile .java files ----------------------------------------- JARFILES = mysql.jar sandbox.jar ridl.jar unoil.jar jurt.jar juh.jar java_uno.jar OOoRunner.jar -JAVAFILES = CheckIndexedPropertyValues.java CheckNamedPropertyValues.java CheckCrossReferences.java CheckBookmarks.java CheckFlies.java +JAVAFILES = CheckIndexedPropertyValues.java CheckNamedPropertyValues.java CheckCrossReferences.java CheckBookmarks.java CheckFlies.java TextPortionEnumerationTest.java JAVACLASSFILES = $(foreach,i,$(JAVAFILES) $(CLASSDIR)$/$(PACKAGE)$/$(i:b).class) #----- make a jar from compiled files ------------------------------ @@ -85,7 +85,9 @@ run: \ CheckCrossReferences \ CheckIndexedPropertyValues \ CheckNamedPropertyValues \ - CheckFlies + CheckFlies \ + TextPortionEnumerationTest \ + RUN: run @@ -105,3 +107,6 @@ CheckBookmarks: CheckFlies: +java -cp $(CLASSPATH) $(CT_APP) $(CT_APPEXECCOMMAND) $(CT_TESTBASE) -tdoc $(PWD)$/testdocuments $(CT_PACKAGE).CheckFlies +TextPortionEnumerationTest: + +java -cp $(CLASSPATH) $(CT_APP) $(CT_APPEXECCOMMAND) $(CT_TESTBASE) -tdoc $(PWD)$/testdocuments $(CT_PACKAGE).TextPortionEnumerationTest + -- cgit v1.2.3 From aaf0f982b10b35a587bcfff623cf4912ae93d253 Mon Sep 17 00:00:00 2001 From: Kurt Zenker Date: Mon, 14 Sep 2009 09:36:01 +0000 Subject: #i10000# cws odfmetadata3 corrected --- sw/inc/bookmrk.hxx | 218 -- sw/inc/fmthbsh.hxx | 74 - sw/inc/fmtmeta.hxx | 218 ++ .../complex/writer/TextPortionEnumerationTest.java | 3858 ++++++++++++++++++++ sw/qa/complex/writer/testdocuments/TESTMETA.odt | Bin 0 -> 8678 bytes sw/source/core/inc/unometa.hxx | 345 ++ sw/source/core/txtnode/fmtatr1.cxx | 97 - 7 files changed, 4421 insertions(+), 389 deletions(-) delete mode 100644 sw/inc/bookmrk.hxx delete mode 100644 sw/inc/fmthbsh.hxx create mode 100755 sw/inc/fmtmeta.hxx create mode 100755 sw/qa/complex/writer/TextPortionEnumerationTest.java create mode 100755 sw/qa/complex/writer/testdocuments/TESTMETA.odt create mode 100755 sw/source/core/inc/unometa.hxx delete mode 100644 sw/source/core/txtnode/fmtatr1.cxx (limited to 'sw/qa') diff --git a/sw/inc/bookmrk.hxx b/sw/inc/bookmrk.hxx deleted file mode 100644 index 3b459f61c081..000000000000 --- a/sw/inc/bookmrk.hxx +++ /dev/null @@ -1,218 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: bookmrk.hxx,v $ - * $Revision: 1.11 $ - * - * 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 - * - * for a copy of the LGPLv3 License. - * - ************************************************************************/ -#ifndef _BOOKMRK_HXX -#define _BOOKMRK_HXX - -#include "hintids.hxx" //die Ids der Attribute, vor macitem damit die - //die Attribut richtig angezogen werden. -#include - -#ifndef _KEYCOD_HXX //autogen -#include -#endif -#ifndef _TOOLS_REF_HXX -#include -#endif -#include -#include -#include - -#ifndef SW_DECL_SWSERVEROBJECT_DEFINED -#define SW_DECL_SWSERVEROBJECT_DEFINED -SV_DECL_REF( SwServerObject ) -#endif - - -struct SwPosition; // fwd Decl. wg. UI - -class SwBookmark : public SwModify -{ - SwPosition *pPos1, *pPos2; // wird im CTOR gesetzt, im DTOR geloescht - // pPos1 is always != 0, pPos2 may be 0 - SwServerObjectRef refObj; // falls DataServer -> Pointer gesetzt - -protected: - String aName; - String aShortName; - KeyCode aCode; - IDocumentBookmarkAccess::BookmarkType eMarkType; - - SwBookmark( const SwPosition& aPos, - const KeyCode& rCode, - const String& rName, const String& rShortName); - -public: - TYPEINFO(); - - SwBookmark( const SwPosition& aPos ); - // --> OD 2007-09-26 #i81002# - SwBookmark( const SwPaM& aPaM, - const KeyCode& rCode, - const String& rName, const String& rShortName); - // <-- - - // Beim Loeschen von Text werden Bookmarks mitgeloescht! - virtual ~SwBookmark(); - - // --> OD 2007-10-10 #i81002# - // made virtual and thus no longer inline - virtual const SwPosition& GetBookmarkPos() const; - virtual const SwPosition* GetOtherBookmarkPos() const; - // <-- - - // nicht undofaehig - const String& GetName() const { return aName; } - // nicht undofaehig - const String& GetShortName() const { return aShortName; } - // nicht undofaehig - const KeyCode& GetKeyCode() const { return aCode; } - - // Vergleiche auf Basis der Dokumentposition - BOOL operator < (const SwBookmark &) const; - BOOL operator ==(const SwBookmark &) const; - // falls man wirklich auf gleiche Position abfragen will. - BOOL IsEqualPos( const SwBookmark &rBM ) const; - - BOOL IsFormFieldMark() const { return IDocumentBookmarkAccess::FORM_FIELDMARK_TEXT == eMarkType || IDocumentBookmarkAccess::FORM_FIELDMARK_NO_TEXT == eMarkType; } - BOOL IsBookMark() const { return IDocumentBookmarkAccess::BOOKMARK == eMarkType || IDocumentBookmarkAccess::FORM_FIELDMARK_TEXT == eMarkType || IDocumentBookmarkAccess::FORM_FIELDMARK_NO_TEXT == eMarkType; } -// // --> OD 2007-10-17 #TESTING# -// BOOL IsBookMark() const -// { -// return IDocumentBookmarkAccess::BOOKMARK == eMarkType || -// IsCrossRefMark(); -// } -// // <-- - BOOL IsMark() const { return IDocumentBookmarkAccess::MARK == eMarkType; } - BOOL IsUNOMark() const { return IDocumentBookmarkAccess::UNO_BOOKMARK == eMarkType; } - // --> OD 2007-10-11 #i81002# - bookmark type for cross-references - BOOL IsCrossRefMark() const { return IDocumentBookmarkAccess::CROSSREF_BOOKMARK == eMarkType; } - // <-- - void SetType( IDocumentBookmarkAccess::BookmarkType eNewType ) { eMarkType = eNewType; } - IDocumentBookmarkAccess::BookmarkType GetType() const { return eMarkType; } - - // Daten Server-Methoden - void SetRefObject( SwServerObject* pObj ); - const SwServerObject* GetObject() const { return &refObj; } - SwServerObject* GetObject() { return &refObj; } - BOOL IsServer() const { return refObj.Is(); } - - // --> OD 2007-10-10 #i81002# - // made virtual and thus no longer inline - // to access start and end of a bookmark. - // start and end may be the same - virtual const SwPosition* BookmarkStart() const; - virtual const SwPosition* BookmarkEnd() const; - // <-- - - // --> OD 2007-09-26 #i81002# - virtual void SetBookmarkPos( const SwPosition* pNewPos1 ); - virtual void SetOtherBookmarkPos( const SwPosition* pNewPos2 ); - // <-- - -private: - // fuer METWARE: - // es wird (vorerst) nicht kopiert und nicht zugewiesen - SwBookmark(const SwBookmark &); - SwBookmark &operator=(const SwBookmark &); -}; - -class SwMark: public SwBookmark -{ -public: - SwMark( const SwPosition& aPos, - const KeyCode& rCode, - const String& rName, const String& rShortName); -}; - -class SW_DLLPUBLIC SwFieldBookmark : public SwBookmark -{ -private: - int fftype; // Type: 0 = Text, 1 = Check Box, 2 = List - int ffres; - bool ffprot; - bool ffsize; // 0 = Auto, 1=Exact (see ffhps) - int fftypetxt; // Type of text field: 0 = Regular text, 1 = Number, 2 = Date, 3 = Current date, 4 = Current time, 5 = Calculation - bool ffrecalc; - int ffmaxlen; // Number of characters for text field. Zero means unlimited. - int ffhps; // Check box size (half-point sizes). - - String ffname; - String ffhelptext; - -public: - SwFieldBookmark(const SwPosition& aPos, - const KeyCode& rCode, - const String& rName, const String& rShortName, - IDocumentBookmarkAccess::BookmarkType eMark); - - void SetFieldType(int fftype); - int GetFieldType(); - - void SetChecked(bool checked); - bool IsChecked(); - - void SetFFName(String aNewName) { - this->ffname=aNewName; - } - - String GetFFName() - { - return ffname; - } - - int GetFFRes() { - return ffres; - } - - void SetFFRes(int nNew) { - this->ffres=nNew; - } - - void SetFFHelpText(String newffhelptext) { - this->ffhelptext=newffhelptext; - } - - String GetFFHelpText() { - return ffhelptext; - } -}; - -class SwUNOMark: public SwBookmark -{ -public: - // --> OD 2007-09-26 #i81002# - SwUNOMark( const SwPaM& aPaM, - const KeyCode& rCode, - const String& rName, const String& rShortName); - // <-- -}; - - -#endif diff --git a/sw/inc/fmthbsh.hxx b/sw/inc/fmthbsh.hxx deleted file mode 100644 index 32c4df8c4007..000000000000 --- a/sw/inc/fmthbsh.hxx +++ /dev/null @@ -1,74 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: fmthbsh.hxx,v $ - * $Revision: 1.5 $ - * - * 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 - * - * for a copy of the LGPLv3 License. - * - ************************************************************************/ -#ifndef _FMTHBSH_HXX -#define _FMTHBSH_HXX - - -#include - -// ATT_SOFTHYPH ****************************** -// Attribut fuer benutzerdefinierte Trennstellen. - -class SwFmtSoftHyph : public SfxPoolItem -{ -public: - SwFmtSoftHyph(); - - // "pure virtual Methoden" vom SfxPoolItem - virtual int operator==( const SfxPoolItem& ) const; - virtual SfxPoolItem* Clone( SfxItemPool* pPool = 0 ) const; - - inline SwFmtSoftHyph& operator=(const SwFmtSoftHyph&) { - return *this; - } -}; - -// ATT_HARDBLANK ****************************** -// Attribut fuer geschuetzte Leerzeichen. - -class SW_DLLPUBLIC SwFmtHardBlank : public SfxPoolItem -{ - sal_Unicode cChar; -public: - SwFmtHardBlank( sal_Unicode cCh, BOOL bCheck = TRUE ); - - // "pure virtual Methoden" vom SfxPoolItem - virtual int operator==( const SfxPoolItem& ) const; - virtual SfxPoolItem* Clone( SfxItemPool* pPool = 0 ) const; - - - inline sal_Unicode GetChar() const { return cChar; } - inline SwFmtHardBlank& operator=(const SwFmtHardBlank& rHB) - { cChar = rHB.GetChar(); return *this; } -}; - - -#endif - diff --git a/sw/inc/fmtmeta.hxx b/sw/inc/fmtmeta.hxx new file mode 100755 index 000000000000..952181d0498c --- /dev/null +++ b/sw/inc/fmtmeta.hxx @@ -0,0 +1,218 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: fmtmeta.hxx,v $ + * $Revision: 1.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SW_FMTMETA_HXX +#define SW_FMTMETA_HXX + +#include +#include + +#include +#include + +#include + + +namespace com { namespace sun { namespace star { + namespace text { + class XTextField; + } +}}} + + +/** + * The classes that make up a meta entity are: + *
+ *
SwTxtMeta
the text hint
+ *
SwFmtMeta
the pool item
+ *
sw::Meta
the metadatable entity itself
+ *
SwXMeta
the UNO wrapper object
+ *
+ * + * The text hint contains the pool item (as usual) and has a pointer to the + * text node at which it is attached. + * The pool item has a shared pointer to the metadatable entity, and a reverse + * pointer to the text attribute at which it is attached. + * The pool item is non-poolable; it may only be attached to one text + * attribute. + * Of all the pool items that refer to a metadatable entity, only one may be + * in the document content at any time. Others may be in the undo array, or in + * undo objects. + * The metadatable entity has a reverse pointer to the pool item that is + * currently in the document. It also registers as a client at the text node + * at which it is attached via this pool item and its text attribute. + * The UNO wrapper object registers as a client at the metadatable entity. + * + * Copying the metadatable entity proceeds in the following way: + *
    + *
  1. The pool item is cloned (because it is non-poolable); the clone + * points to the same metadatable entity, but the metadatable entity's + * reverse pointer is unchanged.
  2. + *
  3. A new text hint is created, taking over the new pool item. + * Unfortunately, this also makes the metadatable entity point at the + * cloned pool item.
  4. + *
  5. The text hint is inserted into the hints array of some text node.
  6. + *
  7. The DoCopy() method must be called at the new pool item: + * it will clone the metadatable entity (using RegisterAsCopyOf), + * and fix the reverse pointer of the original to point at the + * original pool item. + * This is necessary, because first, a metadatable entity may + * only be inserted once into a document, and second, the copy may be + * inserted into a different document than the source document!
  8. + *
+ */ + +class SwTxtMeta; +class SwXMeta; +class SwXMetaField; +namespace sw { + class Meta; +} + +class SwFmtMeta + : public SfxPoolItem +{ +private: + friend class SwTxtMeta; // needs SetTxtAttr + friend class ::sw::Meta; // needs m_pTxtAttr + + ::boost::shared_ptr< ::sw::Meta > m_pMeta; + SwTxtMeta * m_pTxtAttr; + + SwTxtMeta * GetTxtAttr() { return m_pTxtAttr; } + void SetTxtAttr(SwTxtMeta * const i_pTxtAttr); + + explicit SwFmtMeta( const USHORT i_nWhich ); + +public: + // takes ownership + explicit SwFmtMeta( ::boost::shared_ptr< ::sw::Meta > const & i_pMeta, + const USHORT i_nWhich ); + virtual ~SwFmtMeta(); + + // SfxPoolItem + virtual int operator==( const SfxPoolItem & ) const; + virtual SfxPoolItem * Clone( SfxItemPool *pPool = 0 ) const; +// TYPEINFO(); + + // notify clients registered at m_pMeta that this meta is being removed + void NotifyRemoval(); + static SwFmtMeta * CreatePoolDefault( const USHORT i_nWhich ); + ::sw::Meta * GetMeta() { return m_pMeta.get(); } + /// this method must be called when the hint is actually copied + void DoCopy( SwFmtMeta & rOriginalMeta ); +}; + + +namespace sw { + +class MetaFieldManager; + +class Meta + : public ::sfx2::Metadatable + , public SwModify +{ +protected: + friend class ::SwFmtMeta; // SetFmtMeta + friend class ::SwXMeta; // GetTxtNode, GetTxtAttr + + SwFmtMeta * m_pFmt; + + SwTxtMeta * GetTxtAttr() const; + SwTxtNode * GetTxtNode() const; // returns 0 if not in document (undo) + + SwFmtMeta * GetFmtMeta() const { return m_pFmt; } + void SetFmtMeta( SwFmtMeta * const i_pFmt ) { m_pFmt = i_pFmt; }; + +public: + explicit Meta(SwFmtMeta * const i_pFmt = 0); + virtual ~Meta(); + + // SwClient + virtual void Modify( SfxPoolItem *pOld, SfxPoolItem *pNew ); + + // sfx2::Metadatable + virtual ::sfx2::IXmlIdRegistry& GetRegistry(); + virtual bool IsInClipboard() const; + virtual bool IsInUndo() const; + virtual bool IsInContent() const; + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::rdf::XMetadatable > MakeUnoObject(); +}; + +class MetaField + : public Meta +{ +private: + friend class ::SwFmtMeta; + friend class ::SwXMetaField; + friend class ::sw::MetaFieldManager; + + sal_uInt32 m_nNumberFormat; + bool m_bIsFixedLanguage; + + sal_uInt32 GetNumberFormat(::rtl::OUString const & rContent) const; + void SetNumberFormat(sal_uInt32 nNumberFormat); + bool IsFixedLanguage() const { return m_bIsFixedLanguage; } + void SetIsFixedLanguage(bool b) { m_bIsFixedLanguage = b; } + + explicit MetaField(SwFmtMeta * const i_pFmt = 0, + const sal_uInt32 nNumberFormat = SAL_MAX_UINT32, + const bool bIsFixedLanguage = false ); + +public: + /// get prefix/suffix from the RDF repository. @throws RuntimeException + void GetPrefixAndSuffix( + ::rtl::OUString *const o_pPrefix, ::rtl::OUString *const o_pSuffix); +}; + +/** knows all meta-fields in the document. */ +class MetaFieldManager + : private ::boost::noncopyable +{ +private: + typedef ::std::vector< ::boost::weak_ptr > MetaFieldList_t; + MetaFieldList_t m_MetaFields; + +public: + MetaFieldManager(); + ::boost::shared_ptr makeMetaField( + SwFmtMeta * const i_pFmt = 0, + const sal_uInt32 nNumberFormat = SAL_MAX_UINT32, + const bool bIsFixedLanguage = false ); + /// get all meta fields + ::std::vector< ::com::sun::star::uno::Reference< + ::com::sun::star::text::XTextField> > getMetaFields(); +}; + +} // namespace sw + +#endif // SW_FMTMETA_HXX + diff --git a/sw/qa/complex/writer/TextPortionEnumerationTest.java b/sw/qa/complex/writer/TextPortionEnumerationTest.java new file mode 100755 index 000000000000..aec77b891a0b --- /dev/null +++ b/sw/qa/complex/writer/TextPortionEnumerationTest.java @@ -0,0 +1,3858 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: $ + * $Revision: $ + * + * 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 + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package complex.writer; + +import complexlib.ComplexTestCase; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.XComponentContext; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.beans.XPropertySet; +import com.sun.star.beans.XPropertySetInfo; +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.Pair; +import com.sun.star.beans.StringPair; +import com.sun.star.container.XNamed; +import com.sun.star.container.XContentEnumerationAccess; +import com.sun.star.container.XEnumerationAccess; +import com.sun.star.container.XEnumeration; +import com.sun.star.container.NoSuchElementException; +import com.sun.star.frame.XStorable; +import com.sun.star.util.XCloseable; +import com.sun.star.text.XText; +import com.sun.star.text.XTextContent; +import com.sun.star.text.XTextDocument; +import com.sun.star.text.XTextRange; +import com.sun.star.text.XTextCursor; +import com.sun.star.text.XWordCursor; +import com.sun.star.text.XSentenceCursor; +import com.sun.star.text.XParagraphCursor; +import com.sun.star.text.XFootnote; +import com.sun.star.text.XTextField; +import com.sun.star.text.TextContentAnchorType; +import static com.sun.star.text.TextContentAnchorType.*; +import static com.sun.star.text.ControlCharacter.*; +import com.sun.star.rdf.XMetadatable; + +import java.util.Map; +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; +import java.util.Stack; + + +class TreeNodeEnum +{ + private Object[] m_Elements; + private int m_Pos; + TreeNodeEnum(Object[] Elements) { m_Elements = Elements; m_Pos = 0; } + boolean hasNext() { return m_Pos < m_Elements.length; } + TreeNode next() { return (TreeNode) m_Elements[m_Pos++]; } +} + +/** base class for tree nodes. only instance: root of tree. */ +class TreeNode +{ + private List m_Children; + String getType() { return "__ROOT__"; } + boolean hasContent() { return false; } + boolean isNesting() { return false; } + TreeNode dup() { throw new RuntimeException("TreeNode.dup"); } + TreeNodeEnum createEnumeration() { + return new TreeNodeEnum(m_Children.toArray()); + } + TreeNode() { m_Children = new ArrayList(); } + TreeNode appendChild(TreeNode child) + { m_Children.add(child); return this; } + public String toString() { + return "<" + getType() + ">"; + } +} + +abstract class MarkNode extends TreeNode +{ + boolean m_isPoint; + boolean m_isStart = false; + String m_Name; + boolean isPoint() { return m_isPoint; } + boolean isStart() { return m_isStart; } + String getName() { return m_Name; } + MarkNode(String name) { m_Name = name; m_isPoint = true; } + boolean equals(MarkNode other) { + return (other.m_Name.equals(m_Name)) && (other.m_isPoint == m_isPoint) + && (other.m_isStart == m_isStart); + } + public String toString() { + return super.toString() + "\tname: " + m_Name + + "\tisPoint: " + m_isPoint + "\tisStart: " + m_isStart; + } +} + +class BookmarkNode extends MarkNode +{ + private StringPair m_XmlId; + StringPair getXmlId() { return m_XmlId; } + BookmarkNode dup() { return new BookmarkNode(getName(), getXmlId()); } + BookmarkNode(String name) { this(name, new StringPair()); } + BookmarkNode(String name, StringPair xmlid) { + super(name); m_XmlId = xmlid; + } + String getType() { return "Bookmark"; } + public boolean equals(Object other) { + return (other instanceof BookmarkNode) + && super.equals((MarkNode) other) + && MetaNode.eq(((BookmarkNode) other).m_XmlId, m_XmlId); + } + public String toString() { + return super.toString() + + "\txmlid: " + m_XmlId.First + "#" + m_XmlId.Second; + } +} + +class BookmarkStartNode extends BookmarkNode +{ + BookmarkStartNode dup() { return new BookmarkStartNode(getName()); } + BookmarkStartNode(String name) { this(name, new StringPair()); } + BookmarkStartNode(String name, StringPair xmlid) { + super(name, xmlid); m_isPoint = false; m_isStart = true; + } +} + +class BookmarkEndNode extends BookmarkNode +{ + BookmarkEndNode dup() { return new BookmarkEndNode(getName()); } + BookmarkEndNode(String name) { this(name, new StringPair()); } + BookmarkEndNode(String name, StringPair xmlid) { + super(name, xmlid); m_isPoint = false; m_isStart = false; + } +} + +class ReferenceMarkNode extends MarkNode +{ + ReferenceMarkNode dup() { return new ReferenceMarkNode(getName()); } + ReferenceMarkNode(String name) { super(name); } + String getType() { return "ReferenceMark"; } + public boolean equals(Object other) { + return (other instanceof ReferenceMarkNode) + && super.equals((MarkNode) other); + } +} + +class ReferenceMarkStartNode extends ReferenceMarkNode +{ + ReferenceMarkStartNode dup() + { return new ReferenceMarkStartNode(getName()); } + ReferenceMarkStartNode(String name) { + super(name); m_isPoint = false; m_isStart = true; + } +} + +class ReferenceMarkEndNode extends ReferenceMarkNode +{ + ReferenceMarkEndNode dup() + { return new ReferenceMarkEndNode(getName()); } + ReferenceMarkEndNode(String name) { + super(name); m_isPoint = false; m_isStart = false; + } +} + +class DocumentIndexMarkNode extends MarkNode +{ + DocumentIndexMarkNode dup() + { return new DocumentIndexMarkNode(getName()); } + DocumentIndexMarkNode(String name) { super(name); } + String getType() { return "DocumentIndexMark"; } + public boolean equals(Object other) { + return (other instanceof DocumentIndexMarkNode) + && super.equals((MarkNode) other); + } +} + +class DocumentIndexMarkStartNode extends DocumentIndexMarkNode +{ + DocumentIndexMarkStartNode dup() + { return new DocumentIndexMarkStartNode(getName()); } + DocumentIndexMarkStartNode(String name) { + super(name); m_isPoint = false; m_isStart = true; + } +} + +class DocumentIndexMarkEndNode extends DocumentIndexMarkNode +{ + DocumentIndexMarkEndNode dup() + { return new DocumentIndexMarkEndNode(getName()); } + DocumentIndexMarkEndNode(String name) { + super(name); m_isPoint = false; m_isStart = false; + } +} + +abstract class ContentNode extends TreeNode +{ + private String m_Content; + String getContent() { return m_Content; } + boolean hasContent() { return true; } + ContentNode(String content) { + m_Content = content; + } + TreeNode appendChild(TreeNode t) { + throw new RuntimeException("ContentNode.appendChild"); + } + public String toString() { + return super.toString() + "\tcontent: " + m_Content; + } + boolean equals(ContentNode other) { + return (other.m_Content.equals(m_Content)); + } +} + +class TextNode extends ContentNode +{ + TextNode dup() { return new TextNode(getContent()); } + TextNode(String content) { super(content); } + String getType() { return "Text"; } + public boolean equals(Object other) { + return (other instanceof TextNode) && super.equals((ContentNode) other); + } +} + +class TextFieldNode extends ContentNode +{ + TextFieldNode dup() { return new TextFieldNode(getContent()); } + TextFieldNode(String content) { super(content); } + String getType() { return "TextField"; } + public boolean equals(Object other) { + return (other instanceof TextFieldNode) + && super.equals((ContentNode) other); + } +} + +class FrameNode extends TreeNode +{ + private String m_Name; + private TextContentAnchorType m_Anchor; + String getName() { return m_Name; } + TextContentAnchorType getAnchor() { return m_Anchor; } + FrameNode dup() { return new FrameNode(getName(), getAnchor()); } + FrameNode(String name, TextContentAnchorType anchor) { + m_Name = name; m_Anchor = anchor; + } + String getType() { return "Frame"; } + public boolean equals(Object other) { + return (other instanceof FrameNode) + && (((FrameNode) other).m_Name.equals(m_Name)) + && (((FrameNode) other).m_Anchor == m_Anchor); + } + public String toString() { + return super.toString() + + "\tname: " + m_Name + "\tanchor: " + toString(m_Anchor); + } + static String toString(TextContentAnchorType anchor) { + switch (anchor.getValue()) { + case AS_CHARACTER_value: return "AS_CHARACTER"; + case AT_CHARACTER_value: return "AT_CHARACTER"; + case AT_PARAGRAPH_value: return "AT_PARAGRAPH"; + case AT_PAGE_value: return "AT_PAGE"; + case AT_FRAME_value: return "AT_FRAME"; + default: throw new RuntimeException("unknown anchor"); + } + } +} + +class FootnoteNode extends TreeNode +{ + private String m_Label; + String getLabel() { return m_Label; } + FootnoteNode dup() { return new FootnoteNode(getLabel()); } + FootnoteNode(String label) { m_Label = label; } + String getType() { return "Footnote"; } + public boolean equals(Object other) { + return (other instanceof FootnoteNode) + && (((FootnoteNode) other).m_Label.equals(m_Label)); + } + public String toString() { + return super.toString() + "\tlabel: " + m_Label; + } +} + +class ControlCharacterNode extends TreeNode +{ + private short m_Char; + short getChar() { return m_Char; } + ControlCharacterNode dup() { return new ControlCharacterNode(getChar()); } + ControlCharacterNode(short c) { m_Char = c; } + String getType() { return "ControlCharacter"; } + public boolean equals(Object other) { + return (other instanceof ControlCharacterNode) + && (((ControlCharacterNode) other).m_Char == m_Char); + } + public String toString() { + return super.toString() + "\tchar: " + m_Char; + } +} + +class SoftPageBreakNode extends TreeNode +{ + String getType() { return "SoftPageBreak"; } + public boolean equals(Object other) { + return (other instanceof SoftPageBreakNode); + } +} + +class HyperlinkNode extends TreeNode +{ + private String m_URL; + String getURL() { return m_URL; } + HyperlinkNode dup() { return new HyperlinkNode(getURL()); } + HyperlinkNode(String url) { + if (url.length() == 0) throw new RuntimeException("HyperlinkNode"); + m_URL = url; + } + String getType() { return "Hyperlink"; } + boolean isNesting() { return true; } + public boolean equals(Object other) { + return (other instanceof HyperlinkNode) + && (((HyperlinkNode) other).m_URL.equals(m_URL)); + } + public String toString() { + return super.toString() + "\turl: " + m_URL; + } +} + +class RubyNode extends TreeNode +{ + private String m_Ruby; + String getRubyText() { return m_Ruby; } + RubyNode dup() { return new RubyNode(getRubyText()); } + RubyNode(String ruby) { + if (ruby.length() == 0) throw new RuntimeException("RubyNode"); + m_Ruby = ruby; + } + String getType() { return "Ruby"; } + boolean isNesting() { return true; } + public boolean equals(Object other) { + return (other instanceof RubyNode) + && (((RubyNode) other).m_Ruby.equals(m_Ruby)); + } + public String toString() { + return super.toString() + "\trubytext: " + m_Ruby; + } +} + +class MetaNode extends TreeNode +{ + private StringPair m_XmlId; + StringPair getXmlId() { return m_XmlId; } + MetaNode dup() { return new MetaNode(getXmlId()); } + MetaNode (StringPair xmlid) { m_XmlId = xmlid; } + String getType() { return "InContentMetadata"; } + boolean isNesting() { return true; } + public boolean equals(Object other) { + return (other instanceof MetaNode) + && eq(((MetaNode) other).m_XmlId, m_XmlId); + } + static boolean eq(StringPair left, StringPair right) + { + return left.First.equals(right.First) + && left.Second.equals(right.Second); + } + public String toString() { + return super.toString() + + "\txmlid: " + m_XmlId.First + "#" + m_XmlId.Second; + } +} + +class MetaFieldNode extends MetaNode +{ + MetaFieldNode dup() { return new MetaFieldNode(getXmlId()); } + MetaFieldNode (StringPair xmlid) { super(xmlid); } + String getType() { return "MetadataField"; } +} + +class Range +{ + private short m_Start; + private short m_End; + private TreeNode m_Node; + short getStart() { return m_Start; } + short getEnd() { return m_End ; } + short getExtent() { return (short) (m_End - m_Start); } + TreeNode getNode() { return m_Node; } + Range(int start, int end, TreeNode node) + { m_Start = (short) start; m_End = (short) end; m_Node = node; } +} + +//---------------------------------------------------------------------- + +/* this is where we nail the pudding to the wall */ +class FuzzyTester +{ + private long m_DiffContent = 0; + private long m_DiffMissing = 0; + private long m_DiffNesting = 0; + private long m_DiffSpuriousEmptyText = 0; + private long m_DiffSequence = 0; // ignored? + private Stack> m_StackExpected; + private Stack> m_StackActual; + private List m_BufferExpected; + private List m_BufferActual; + private share.LogWriter m_Log; + + FuzzyTester(share.LogWriter log) { + m_Log = log; + m_BufferExpected = new ArrayList(); + m_BufferActual = new ArrayList(); + m_StackExpected = new Stack>(); + m_StackActual = new Stack>(); + } + + /** idea: traverse both trees, enumerate nodes, stopping at content nodes. + then compare buffers. */ + boolean doTest(TreeNode expected, TreeNode actual) + { + if (!expected.getType().equals("__ROOT__")) + throw new RuntimeException("doTest: expected: root"); + if (!actual.getType().equals("__ROOT__")) + throw new RuntimeException("doTest: actual: root"); + m_StackExpected.push(new Pair(expected, expected.createEnumeration())); + m_StackActual.push(new Pair(actual, actual.createEnumeration())); + do { + traverse(m_StackExpected, m_BufferExpected); + traverse(m_StackActual, m_BufferActual); + //??? root? + testBuffer(); + } while (!m_StackExpected.empty() || !m_StackActual.empty()); + if (m_DiffSequence != 0) { + m_Log.println("warning: " + m_DiffSequence + + " differences in sequence"); + } + if (m_DiffSpuriousEmptyText != 0) { + m_Log.println("warning: " + m_DiffSpuriousEmptyText + + " spurious empty text nodes"); + } + if (m_DiffNesting != 0) { + m_Log.println("WARNING: " + m_DiffNesting + + " differences in nesting"); + } + return (m_DiffContent == 0) && (m_DiffMissing == 0); + } + + private void traverse(Stack> stack, + List buffer) + { + while (!stack.empty()) { + TreeNodeEnum topEnum = stack.peek().Second; + if (topEnum.hasNext()) { + TreeNode node = topEnum.next(); + buffer.add(node); + TreeNodeEnum nodeEnum = node.createEnumeration(); + if (nodeEnum.hasNext()) { + stack.push(new Pair(node, nodeEnum)); + } + if (node.hasContent()) { + if (!((node instanceof TextNode) // spurious empty text? + && ((TextNode) node).getContent().length() == 0)) { + return; // break here + } + } + } else { + buffer.add(stack.peek().First); + stack.pop(); + } + } + } + + private void testTerminatingNode() + { + int lenExpected = m_BufferExpected.size(); + int lenActual = m_BufferActual.size(); + if (lenExpected == 0 || lenActual == 0) + return; + TreeNode expected = m_BufferExpected.get(lenExpected - 1); + TreeNode actual = m_BufferActual.get(lenActual - 1); + + boolean eRoot = expected.getType().equals("__ROOT__"); + boolean aRoot = actual.getType().equals("__ROOT__"); + if (eRoot || aRoot) { + if (!(eRoot && aRoot)) { + if (aRoot) printMissing(expected); + else printUnexpected(actual); + m_DiffMissing++; + } + return; + } + + testContentNode((ContentNode) expected, (ContentNode) actual); + + m_BufferExpected.set(lenExpected - 1, null); + m_BufferActual.set(lenActual - 1, null); + } + + private void testContentNode(ContentNode expected, ContentNode actual) + { + String contentExpected = expected.getContent(); + String contentActual = actual.getContent(); + if (!expected.equals(actual)) { + printDiff("text content differs", contentExpected, contentActual); + m_DiffContent++; + } + } + + private void testBuffer() + { + int lenExpected = m_BufferExpected.size(); + int lenActual = m_BufferActual.size(); + for (int i = 0; i < lenExpected - 1; i++ ) + { + TreeNode node = m_BufferExpected.get(i); + int j = m_BufferActual.indexOf(node); + if (j >= 0) { + TreeNode other = m_BufferActual.get(j); + if (j != i) + { + //FIXME how bad is this? + printDiff("position differs", + String.valueOf(i), String.valueOf(j)); + // a hacky hack + int min = Math.min(i,j); + int max = Math.max(Math.min(lenActual - 1, i),j); + for (int k = min; k != max; k ++) { + TreeNode tmp = m_BufferActual.get(k); + if (tmp != null && tmp.isNesting()) { + printNesting(node, tmp); + m_DiffNesting++; + } + } + m_DiffSequence++; + } + m_BufferActual.set(j, null); + } else { +//m_Log.println("testBuffer:"); + printMissing(node); + m_DiffMissing++; + } + } + for (int j = 0; j < lenActual - 1; j++) + { + TreeNode node = m_BufferActual.get(j); + if (node != null) + { +//m_Log.println("testBuffer:"); + printUnexpected(node); + if ((node instanceof TextNode) && + ((TextNode) node).getContent().length() == 0) { + m_DiffSpuriousEmptyText++; + } else { + m_DiffMissing++; + } + } + } + testTerminatingNode(); + m_BufferExpected.clear(); + m_BufferActual.clear(); + } + + void printDiff(String prefix, String expected, String actual) + { + m_Log.println(prefix + + ":\texpected: " + expected + "\tactual: " + actual); + } + + void printNesting(TreeNode node, TreeNode nesting) + { + m_Log.println("node: " + node.toString() + + " possibly moved across nesting " + nesting.toString()); + } + + void printMissing(TreeNode node) + { + m_Log.println(" missing node: " + node.toString()); + + } + + void printUnexpected(TreeNode node) + { + m_Log.println("unexpected node: " + node.toString()); + + } +} + + +//---------------------------------------------------------------------- + +class EnumConverter +{ + private Stack m_Stack; + TextPortionEnumerationTest m_T; + + EnumConverter(TextPortionEnumerationTest err) { + m_Stack = new Stack(); m_T = err; + } + + TreeNode convert(XEnumeration xEnum) throws Exception + { + TreeNode root = new TreeNode(); + m_Stack.push(root); + TreeNode ret = convertChildren(xEnum); + m_T.assure("EnumConverter.convert: stack", m_Stack.empty()); + return ret; + } + + TreeNode convertChildren(XEnumeration xEnum) throws Exception + { + while (xEnum.hasMoreElements()) { + TreeNode node; + Object xElement = xEnum.nextElement(); + XTextRange xPortion = (XTextRange) + UnoRuntime.queryInterface(XTextRange.class, xElement); + XPropertySet xPropSet = (XPropertySet) + UnoRuntime.queryInterface(XPropertySet.class, xPortion); + String type = (String) xPropSet.getPropertyValue("TextPortionType"); + if (type.equals("Text")) { + String text = xPortion.getString(); + node = new TextNode(text); + String url = (String) xPropSet.getPropertyValue("HyperLinkURL"); + if (url.length() > 0) { + TreeNode temp = node; + node = new HyperlinkNode(url); + node.appendChild(temp); + } + } else if (type.equals("TextField")) { + Object xField = xPropSet.getPropertyValue("TextField"); + XServiceInfo xService = (XServiceInfo) + UnoRuntime.queryInterface(XServiceInfo.class, xField); + if (xService.supportsService( + "com.sun.star.text.textfield.MetadataField")) + { + XMetadatable xMeta = (XMetadatable) + UnoRuntime.queryInterface(XMetadatable.class, xField); + StringPair xmlid = xMeta.getMetadataReference(); + node = new MetaFieldNode(xmlid); + m_Stack.push(node); + XEnumerationAccess xEA = (XEnumerationAccess) + UnoRuntime.queryInterface(XEnumerationAccess.class, + xMeta); + XEnumeration xEnumChildren = xEA.createEnumeration(); + TreeNode node2 = convertChildren(xEnumChildren); + m_T.assure("stack error: meta-field", node == node2); + } else { + XPropertySet xFieldPropSet = (XPropertySet) + UnoRuntime.queryInterface(XPropertySet.class, xField); + String content = (String) + xFieldPropSet.getPropertyValue("Content"); + boolean isFixed = (Boolean) + xFieldPropSet.getPropertyValue("IsFixed"); + m_T.assure("field not fixed?", isFixed); + node = new TextFieldNode(content); + } + } else if (type.equals("Footnote")) { + Object xNote = xPropSet.getPropertyValue("Footnote"); + XFootnote xFootnote = (XFootnote) + UnoRuntime.queryInterface(XFootnote.class, xNote); + String label = xFootnote.getLabel(); + node = new FootnoteNode(label); + } else if (type.equals("Frame")) { + XContentEnumerationAccess xCEA = (XContentEnumerationAccess) + UnoRuntime.queryInterface(XContentEnumerationAccess.class, + xPortion); + XEnumeration xContentEnum = xCEA.createContentEnumeration(""); + while (xContentEnum.hasMoreElements()) { + Object xFrame = xContentEnum.nextElement(); + XPropertySet xFramePropSet = (XPropertySet) + UnoRuntime.queryInterface(XPropertySet.class, xFrame); + TextContentAnchorType anchor = (TextContentAnchorType) + xFramePropSet.getPropertyValue("AnchorType"); + XNamed xNamed = (XNamed) + UnoRuntime.queryInterface(XNamed.class, xFrame); + String name = xNamed.getName(); + node = new FrameNode(name, anchor); + m_Stack.peek().appendChild(node); + } + continue; + } else if (type.equals("ControlCharacter")) { + short c = (Short) + xPropSet.getPropertyValue("ControlCharacter"); + node = new ControlCharacterNode(c); + } else if (type.equals("Bookmark")) { + Object xMark = xPropSet.getPropertyValue("Bookmark"); + XNamed xNamed = (XNamed) + UnoRuntime.queryInterface(XNamed.class, xMark); + String name = xNamed.getName(); + XMetadatable xMetadatable = (XMetadatable) + UnoRuntime.queryInterface(XMetadatable.class, xMark); + StringPair xmlid = xMetadatable.getMetadataReference(); + boolean isCollapsed = (Boolean) + xPropSet.getPropertyValue("IsCollapsed"); + if (isCollapsed) { + node = new BookmarkNode(name, xmlid); + } else { + boolean isStart = (Boolean) + xPropSet.getPropertyValue("IsStart"); + if (isStart) { + node = new BookmarkStartNode(name, xmlid); + } else { + node = new BookmarkEndNode(name, xmlid); + } + } + } else if (type.equals("ReferenceMark")) { + Object xMark = xPropSet.getPropertyValue("ReferenceMark"); + XNamed xNamed = (XNamed) + UnoRuntime.queryInterface(XNamed.class, xMark); + String name = xNamed.getName(); + boolean isCollapsed = (Boolean) + xPropSet.getPropertyValue("IsCollapsed"); + if (isCollapsed) { + node = new ReferenceMarkNode(name); + } else { + boolean isStart = (Boolean) + xPropSet.getPropertyValue("IsStart"); + if (isStart) { + node = new ReferenceMarkStartNode(name); + } else { + node = new ReferenceMarkEndNode(name); + } + } + } else if (type.equals("DocumentIndexMark")) { + Object xMark = xPropSet.getPropertyValue("DocumentIndexMark"); + XPropertySet xMarkSet = (XPropertySet) + UnoRuntime.queryInterface(XPropertySet.class, xMark); + String name = (String) xMarkSet.getPropertyValue("PrimaryKey"); + boolean isCollapsed = (Boolean) + xPropSet.getPropertyValue("IsCollapsed"); + if (isCollapsed) { + node = new DocumentIndexMarkNode(name); + } else { + boolean isStart = (Boolean) + xPropSet.getPropertyValue("IsStart"); + if (isStart) { + node = new DocumentIndexMarkStartNode(name); + } else { + node = new DocumentIndexMarkEndNode(name); + } + } + } else if (type.equals("SoftPageBreak")) { + node = new SoftPageBreakNode(); + } else if (type.equals("Ruby")) { + boolean isStart = (Boolean) + xPropSet.getPropertyValue("IsStart"); + if (isStart) { + // ARRGH!!! stupid api... + // the text is ONLY at the start! + String ruby = (String) + xPropSet.getPropertyValue("RubyText"); + node = new RubyNode(ruby); + m_Stack.push(node); + continue; + } else { + node = m_Stack.pop(); + m_T.assure("stack error: Ruby expected; is: " + + node.toString(), node instanceof RubyNode); +// m_T.assure("stack error: ruby", +// ruby.equals(((RubyNode)node).getRubyText())); + } + } else if (type.equals("InContentMetadata")) { + Object xMeta = xPropSet.getPropertyValue("InContentMetadata"); + XMetadatable xMetadatable = (XMetadatable) + UnoRuntime.queryInterface(XMetadatable.class, xMeta); + StringPair xmlid = xMetadatable.getMetadataReference(); + node = new MetaNode(xmlid); + m_Stack.push(node); + XEnumerationAccess xEA = (XEnumerationAccess) + UnoRuntime.queryInterface(XEnumerationAccess.class, xMeta); + XEnumeration xEnumChildren = xEA.createEnumeration(); + TreeNode node2 = convertChildren(xEnumChildren); + m_T.assure("stack error: meta", node == node2); +// } else if (type.equals("MetadataField")) { +// Object xMeta = xPropSet.getPropertyValue("MetadataField"); + } else { + throw new RuntimeException("unexpected type: " + type); + } + m_Stack.peek().appendChild(node); + } + TreeNode ret = m_Stack.pop(); + return ret; + } +} + + +//---------------------------------------------------------------------- + +abstract class Inserter +{ + private XMultiServiceFactory m_xDocFactory; + XText m_xText; + XParagraphCursor m_xCursor; + + Inserter(XTextDocument xDoc) + { + m_xDocFactory = (XMultiServiceFactory) + UnoRuntime.queryInterface(XMultiServiceFactory.class, xDoc); + m_xText = xDoc.getText(); + XTextCursor xCursor = m_xText.createTextCursor(); + m_xCursor = (XParagraphCursor) + UnoRuntime.queryInterface(XParagraphCursor.class, xCursor); + } + + void initParagraph() throws Exception + { + m_xCursor.gotoStartOfParagraph(false); + m_xText.insertControlCharacter(m_xCursor, PARAGRAPH_BREAK, false); + // we split the first (empty) paragraph, and then insert into the + // second (empty) paragraph; this ensures first is always empty! + } + + void insertControlCharacter(XTextCursor xCursor, short cchar) + throws Exception + { + m_xText.insertControlCharacter(xCursor, cchar, false); + } + + void insertText(XTextCursor xCursor, String text) + { + xCursor.setString(text); + } + + void insertTextField(XTextCursor xCursor, String content) throws Exception + { + XTextContent xContent = makeTextField(content); + xContent.attach(xCursor); + } + + XTextContent makeTextField(String content) + throws Exception + { + Object xField = + m_xDocFactory.createInstance("com.sun.star.text.textfield.Author"); + XTextContent xContent = (XTextContent) + UnoRuntime.queryInterface(XTextContent.class, xField); + XPropertySet xPropSet = (XPropertySet) + UnoRuntime.queryInterface(XPropertySet.class, xField); + xPropSet.setPropertyValue("IsFixed", true); + xPropSet.setPropertyValue("FullName", false); + xPropSet.setPropertyValue("Content", content); + return xContent; + } + + void insertFrame(XTextRange xCursor, String name, + TextContentAnchorType anchor) throws Exception + { + XTextContent xContent = makeFrame(name, anchor); + xContent.attach(xCursor); + } + + XTextContent makeFrame(String name, TextContentAnchorType anchor) + throws Exception + { + Object xFrame = + m_xDocFactory.createInstance("com.sun.star.text.TextFrame"); + XTextContent xContent = (XTextContent) + UnoRuntime.queryInterface(XTextContent.class, xFrame); + XPropertySet xPropSet = (XPropertySet) + UnoRuntime.queryInterface(XPropertySet.class, xFrame); + xPropSet.setPropertyValue("AnchorType", anchor); + XNamed xNamed = (XNamed) + UnoRuntime.queryInterface(XNamed.class, xContent); + xNamed.setName(name); + return xContent; + } + + void insertFootnote(XTextCursor xCursor, String label) throws Exception + { + XTextContent xContent = makeFootnote(label); + xContent.attach(xCursor); + } + + XTextContent makeFootnote(String label) throws Exception + { + Object xNote = + m_xDocFactory.createInstance("com.sun.star.text.Footnote"); + XTextContent xContent = (XTextContent) + UnoRuntime.queryInterface(XTextContent.class, xNote); + XFootnote xFootnote = (XFootnote) + UnoRuntime.queryInterface(XFootnote.class, xNote); + xFootnote.setLabel(label); + return xContent; + } + + void insertBookmark(XTextCursor xCursor, String name, StringPair xmlid) + throws Exception + { + XTextContent xContent = makeBookmark(name); + xContent.attach(xCursor); + if (!xmlid.First.equals("")) + { + XMetadatable xMetadatable = (XMetadatable) + UnoRuntime.queryInterface(XMetadatable.class, xContent); + xMetadatable.setMetadataReference(xmlid); + } + } + + XTextContent makeBookmark(String name) throws Exception + { + Object xBookmark = + m_xDocFactory.createInstance("com.sun.star.text.Bookmark"); + XTextContent xContent = (XTextContent) + UnoRuntime.queryInterface(XTextContent.class, xBookmark); + XNamed xNamed = (XNamed) + UnoRuntime.queryInterface(XNamed.class, xContent); + xNamed.setName(name); + return xContent; + } + + void insertReferenceMark(XTextCursor xCursor, String name) throws Exception + { + XTextContent xContent = makeReferenceMark(name); + xContent.attach(xCursor); + } + + XTextContent makeReferenceMark(String name) throws Exception + { + Object xMark = + m_xDocFactory.createInstance("com.sun.star.text.ReferenceMark"); + XTextContent xContent = (XTextContent) + UnoRuntime.queryInterface(XTextContent.class, xMark); + XNamed xNamed = (XNamed) + UnoRuntime.queryInterface(XNamed.class, xContent); + xNamed.setName(name); + return xContent; + } + + void insertDocumentIndexMark(XTextCursor xCursor, String key) + throws Exception + { + XTextContent xContent = makeDocumentIndexMark(key); + xContent.attach(xCursor); + } + + XTextContent makeDocumentIndexMark(String key) throws Exception + { + Object xMark = + m_xDocFactory.createInstance("com.sun.star.text.DocumentIndexMark"); + XTextContent xContent = (XTextContent) + UnoRuntime.queryInterface(XTextContent.class, xMark); + XPropertySet xPropSet = (XPropertySet) + UnoRuntime.queryInterface(XPropertySet.class, xMark); + xPropSet.setPropertyValue("PrimaryKey", key); + return xContent; + } + + void insertHyperlink(XTextCursor xCursor, String url) throws Exception + { + XPropertySet xPropSet = (XPropertySet) + UnoRuntime.queryInterface(XPropertySet.class, xCursor); + xPropSet.setPropertyValue("HyperLinkURL", url); + } + + void insertRuby(XTextCursor xCursor, String rubytext) throws Exception + { + XPropertySet xPropSet = (XPropertySet) + UnoRuntime.queryInterface(XPropertySet.class, xCursor); + xPropSet.setPropertyValue("RubyText", rubytext); + } + + void insertMeta(XTextCursor xCursor, StringPair xmlid) + throws Exception + { + XTextContent xContent = makeMeta(); + xContent.attach(xCursor); + XMetadatable xMetadatable = (XMetadatable) + UnoRuntime.queryInterface(XMetadatable.class, xContent); + xMetadatable.setMetadataReference(xmlid); + } + + XTextContent makeMeta() throws Exception + { + Object xMeta = m_xDocFactory.createInstance( + "com.sun.star.text.InContentMetadata"); + XTextContent xContent = (XTextContent) + UnoRuntime.queryInterface(XTextContent.class, xMeta); + return xContent; + } + + void insertMetaField(XTextCursor xCursor, StringPair xmlid) + throws Exception + { + XTextContent xContent = makeMetaField(); + xContent.attach(xCursor); + XMetadatable xMetadatable = (XMetadatable) + UnoRuntime.queryInterface(XMetadatable.class, xContent); + xMetadatable.setMetadataReference(xmlid); + } + + XTextField makeMetaField() throws Exception + { + Object xMeta = m_xDocFactory.createInstance( + "com.sun.star.text.textfield.MetadataField"); + XTextField xContent = (XTextField) + UnoRuntime.queryInterface(XTextField.class, xMeta); + return xContent; + } + +} + +class TreeInserter extends Inserter +{ + private Map m_BookmarkStarts; + private Map m_ReferenceMarkStarts; + private Map m_DocumentIndexMarkStarts; + private List> m_FrameHints; + + TreeInserter(XTextDocument xDoc) + { + super(xDoc); + m_BookmarkStarts = new HashMap(); + m_ReferenceMarkStarts = new HashMap(); + m_DocumentIndexMarkStarts = new HashMap(); + m_FrameHints = new ArrayList>(); + } + + void insertTree(TreeNode tree) throws Exception + { + if (!tree.getType().equals("__ROOT__")) + throw new RuntimeException("insertTree: test error: no root"); + initParagraph(); + insertChildren(tree.createEnumeration()); + for (int i = 0; i < m_FrameHints.size(); ++i) { + Pair p = m_FrameHints.get(i); + insertFrame(p.First, p.Second.getName(), p.Second.getAnchor()); + } + } + + void insertChildren(TreeNodeEnum children) throws Exception + { + while (children.hasNext()) { + m_xCursor.gotoEndOfParagraph(false); + TreeNode node = children.next(); + String type = node.getType(); + if (type.equals("Bookmark")) { + BookmarkNode bkmk = (BookmarkNode) node; + String name = bkmk.getName(); + StringPair id = bkmk.getXmlId(); + if (bkmk.isPoint()) { + insertBookmark(m_xCursor, name, id); + } else if (bkmk.isStart()) { + m_BookmarkStarts.put(name, m_xCursor.getStart()); + } else { + XTextRange xRange = m_BookmarkStarts.get(name); + XParagraphCursor xCursor = mkCursor(xRange); + insertBookmark(xCursor, name, id); + } + } else if (type.equals("ReferenceMark")) { + ReferenceMarkNode mark = (ReferenceMarkNode) node; + String name = mark.getName(); + if (mark.isPoint()) { + insertReferenceMark(m_xCursor, name); + } else if (mark.isStart()) { + m_ReferenceMarkStarts.put(name, m_xCursor.getStart()); + } else { + XTextRange xRange = m_ReferenceMarkStarts.get(name); + XParagraphCursor xCursor = mkCursor(xRange); + insertReferenceMark(xCursor, name); + } + } else if (type.equals("DocumentIndexMark")) { + DocumentIndexMarkNode mark = (DocumentIndexMarkNode) node; + String name = mark.getName(); + if (mark.isPoint()) { + insertDocumentIndexMark(m_xCursor, name); + } else if (mark.isStart()) { + m_DocumentIndexMarkStarts.put(name, m_xCursor.getStart()); + } else { + XTextRange xRange = m_DocumentIndexMarkStarts.get(name); + XParagraphCursor xCursor = mkCursor(xRange); + insertDocumentIndexMark(xCursor, name); + } + } else if (type.equals("Hyperlink")) { + HyperlinkNode href = (HyperlinkNode) node; + XTextRange xRange = m_xCursor.getStart(); + insertChildren(href.createEnumeration()); + XParagraphCursor xCursor = mkCursor(xRange); + insertHyperlink(xCursor, href.getURL()); + } else if (type.equals("Ruby")) { + RubyNode ruby = (RubyNode) node; + XTextRange xRange = m_xCursor.getStart(); + insertChildren(ruby.createEnumeration()); + XParagraphCursor xCursor = mkCursor(xRange); + insertRuby(xCursor, ruby.getRubyText()); + } else if (type.equals("InContentMetadata")) { + MetaNode meta = (MetaNode) node; + XTextRange xRange = m_xCursor.getStart(); + insertChildren(meta.createEnumeration()); + XParagraphCursor xCursor = mkCursor(xRange); + insertMeta(xCursor, meta.getXmlId()); + } else if (type.equals("MetadataField")) { + MetaFieldNode meta = (MetaFieldNode) node; + XTextRange xRange = m_xCursor.getStart(); + insertChildren(meta.createEnumeration()); + XParagraphCursor xCursor = mkCursor(xRange); + insertMetaField(xCursor, meta.getXmlId()); + } else if (type.equals("Text")) { + TextNode text = (TextNode) node; + insertText(m_xCursor, text.getContent()); + } else if (type.equals("TextField")) { + TextFieldNode field = (TextFieldNode) node; + insertTextField(m_xCursor, field.getContent()); + } else if (type.equals("Footnote")) { + FootnoteNode note = (FootnoteNode) node; + insertFootnote(m_xCursor, note.getLabel()); + } else if (type.equals("Frame")) { + FrameNode frame = (FrameNode) node; + if (frame.getAnchor() == AT_CHARACTER) { + m_FrameHints.add( new Pair(m_xCursor.getStart(), frame) ); + } else { + insertFrame(m_xCursor, frame.getName(), frame.getAnchor()); + } + } else if (type.equals("ControlCharacter")) { + ControlCharacterNode cchar = (ControlCharacterNode) node; + insertControlCharacter(m_xCursor, cchar.getChar()); + } else if (type.equals("SoftPageBreak")) { + SoftPageBreakNode spbk = (SoftPageBreakNode) node; + throw new RuntimeException("sorry, cannot test SoftPageBreak"); + } else { + throw new RuntimeException("unexpected type: " + type); + } + } + } + + XParagraphCursor mkCursor(XTextRange xRange) + { + XTextCursor xCursor = m_xText.createTextCursorByRange(xRange); + XParagraphCursor xParaCursor = (XParagraphCursor) + UnoRuntime.queryInterface(XParagraphCursor.class, xCursor); + xParaCursor.gotoEndOfParagraph(true); + return xParaCursor; + } +} + + +// FIXME: this does not account for inserted dummy characters! +class RangeInserter extends Inserter +{ + RangeInserter(XTextDocument xDoc) throws Exception + { super(xDoc); initParagraph(); } + + /* + void insertText(int pos, String text) + { + m_xCursor.gotoStartOfParagraph(false); + m_xCursor.goRight((short) pos, false); + insertText(m_xCursor, text); + } + */ + + void insertRange(Range range) throws Exception + { + m_xCursor.gotoStartOfParagraph(false); + m_xCursor.goRight(range.getStart(), false); + m_xCursor.goRight(range.getExtent(), true); + insertNode(m_xCursor, range.getNode()); + } + + void insertNode(XParagraphCursor xCursor, TreeNode node) throws Exception + { + String type = node.getType(); + if (type.equals("Bookmark")) { + BookmarkNode bkmk = (BookmarkNode) node; + if (bkmk.isPoint()) throw new RuntimeException("range only"); + insertBookmark(xCursor, bkmk.getName(), bkmk.getXmlId()); + } else if (type.equals("ReferenceMark")) { + ReferenceMarkNode mark = (ReferenceMarkNode) node; + if (mark.isPoint()) throw new RuntimeException("range only"); + insertReferenceMark(xCursor, mark.getName()); + } else if (type.equals("DocumentIndexMark")) { + DocumentIndexMarkNode mark = (DocumentIndexMarkNode) node; + if (mark.isPoint()) throw new RuntimeException("range only"); + insertDocumentIndexMark(xCursor, mark.getName()); + } else if (type.equals("Hyperlink")) { + HyperlinkNode href = (HyperlinkNode) node; + insertHyperlink(xCursor, href.getURL()); + } else if (type.equals("Ruby")) { + RubyNode ruby = (RubyNode) node; + insertRuby(xCursor, ruby.getRubyText()); + } else if (type.equals("InContentMetadata")) { + MetaNode meta = (MetaNode) node; + insertMeta(xCursor, meta.getXmlId()); + } else if (type.equals("MetadataField")) { + MetaFieldNode meta = (MetaFieldNode) node; + insertMetaField(xCursor, meta.getXmlId()); + } else if (type.equals("Text")) { + TextNode text = (TextNode) node; + insertText(xCursor, text.getContent()); + } else if (type.equals("TextField")) { + TextFieldNode field = (TextFieldNode) node; + insertTextField(m_xCursor, field.getContent()); + } else if (type.equals("Footnote")) { + FootnoteNode note = (FootnoteNode) node; + insertFootnote(m_xCursor, note.getLabel()); + } else if (type.equals("Frame")) { + FrameNode frame = (FrameNode) node; + insertFrame(xCursor, frame.getName(), frame.getAnchor()); + } else if (type.equals("ControlCharacter")) { + ControlCharacterNode cchar = (ControlCharacterNode) node; + insertControlCharacter(m_xCursor, cchar.getChar()); + } else if (type.equals("SoftPageBreak")) { + throw new RuntimeException("sorry, cannot test SoftPageBreak"); + } else { + throw new RuntimeException("unexpected type: " + type); + } + } +} + + +//---------------------------------------------------------------------- + +public class TextPortionEnumerationTest extends ComplexTestCase +{ + private XMultiServiceFactory m_xMSF = null; + private XComponentContext m_xContext = null; + private XTextDocument m_xDoc = null; + private String m_TmpDir = null; + + private int m_Count = 1; + +// public String[] getTestMethodNames() { return new String[] { "testLoadStore" }; } + public String[] getTestMethodNames() { + return new String[] { + "testText", + "testTextField", +// "testControlChar", +// "testSoftPageBreak", + "testFootnote", + "testFrameAs", + "testFrameAt", + "testBookmarkPoint", + "testBookmark", + "testBookmarkPointXmlId", + "testBookmarkXmlId", + "testRefmarkPoint", + "testRefmark", + "testToxmarkPoint", + "testToxmark", + "testHyperlink", + "testHyperlinkEmpty", + "testRuby", + "testRubyEmpty", + "testMeta", + "testMetaEmpty", + "testMetaField", + "testMetaFieldEmpty", + "testBookmark1", + "testBookmark2", + "testRefMark2", + "testRefMark3", + "testToxMark2", + "testToxMark3", + "testMarks1", + "testMarks2", + "testMarks3", + "testFrameMark1", + "testFrameMark2", + "testFrameMark3", + "testFrameMark4", + "testFrames1", + "testFrames2", + "testFrames3", + "testFrames4", + "testFrames5", + "testRubyHyperlink1", + "testRubyHyperlink2", + "testEnd1", + "testEnd2", + "testEnd3", + "testEnd4", + "testEnd5", + "testEmpty1", + "testEmpty2", + "testEmpty3", + "test1", + "testRange1", + "testRangeHyperlinkHyperlink", + "testRangeHyperlinkRuby", + "testRangeRubyHyperlink", + "testRangeRubyRuby", + "testRangeHyperlinkMeta", + "testRangeRubyMeta", + "testRangeMetaHyperlink", + "testRangeMetaRuby", + "testRangeMetaMeta", + "testRange2", + "testRange3", + "testRange4", + "testRange5", + "testRange6", + "testRange7", + "testMetaXText", + "testMetaXTextCursor", + "testMetaXTextAttachToxMark", + "testMetaXTextAttachRefMark", + "testMetaXTextAttachTextField", + "testMetaXTextAttachFootnote", + "testMetaXTextAttachMeta", + "testMetaFieldXTextField", + "testMetaFieldXPropertySet", + "testLoadStore", + }; + } + + public void before() throws Exception + { + m_xMSF = (XMultiServiceFactory) param.getMSF(); + XPropertySet xPropertySet = (XPropertySet) + UnoRuntime.queryInterface(XPropertySet.class, m_xMSF); + Object defaultCtx = xPropertySet.getPropertyValue("DefaultContext"); + m_xContext = (XComponentContext) + UnoRuntime.queryInterface(XComponentContext.class, defaultCtx); + assure("could not get component context.", m_xContext != null); + m_xDoc = util.WriterTools.createTextDoc(m_xMSF); + m_TmpDir = util.utils.getOfficeTemp/*Dir*/(m_xMSF); + log.println("tempdir: " + m_TmpDir); + } + + public void after() + { + if (m_xDoc != null) { + util.DesktopTools.closeDoc(m_xDoc); + m_xDoc = null; + } + } + + public void testText() throws Exception + { + TreeNode root = new TreeNode(); + TreeNode text = new TextNode("abc"); + root.appendChild(text); + doTest(root); + } + + public void testTextField() throws Exception + { + String name = mkName("ruby"); + TreeNode root = new TreeNode(); + TreeNode txtf = new TextFieldNode("abc"); + root.appendChild(txtf); + doTest(root); + } + + public void testControlChar() throws Exception + { +//FIXME this is converted to a text portion: ControlCharacter is obsolete + TreeNode root = new TreeNode(); + TreeNode cchr = new ControlCharacterNode(HARD_HYPHEN); + root.appendChild(cchr); + doTest(root); + } + + public void testSoftPageBreak() throws Exception + { +//FIXME: insert a soft page break: not done + TreeNode root = new TreeNode(); + TreeNode spbk = new SoftPageBreakNode(); + TreeNode text = new TextNode("abc"); + root.appendChild(spbk); + root.appendChild(text); + doTest(root); + } + + public void testFootnote() throws Exception + { + String name = mkName("ftn"); + TreeNode root = new TreeNode(); + TreeNode ftnd = new FootnoteNode(name); + root.appendChild(ftnd); + doTest(root); + } + + public void testFrameAs() throws Exception + { + String name = mkName("frame"); + TreeNode root = new TreeNode(); + TreeNode fram = new FrameNode(name, AS_CHARACTER); + root.appendChild(fram); + doTest(root); + } + + public void testFrameAt() throws Exception + { + String name = mkName("frame"); + TreeNode root = new TreeNode(); +// TreeNode text = new TextNode(""); // necessary? + TreeNode fram = new FrameNode(name, AT_CHARACTER); +// root.appendChild(text); + root.appendChild(fram); + doTest(root); + } + + public void testBookmarkPoint() throws Exception + { + String name = mkName("mark"); + TreeNode root = new TreeNode(); + TreeNode bkmk = new BookmarkNode(name); + TreeNode text = new TextNode("abc"); + root.appendChild(bkmk); + root.appendChild(text); + doTest(root); + } + + public void testBookmark() throws Exception + { + String name = mkName("mark"); + TreeNode root = new TreeNode(); + TreeNode bkm1 = new BookmarkStartNode(name); + TreeNode text = new TextNode("abc"); + TreeNode bkm2 = new BookmarkEndNode(name); + root.appendChild(bkm1); + root.appendChild(text); + root.appendChild(bkm2); + doTest(root); + } + + public void testBookmarkPointXmlId() throws Exception + { + String name = mkName("mark"); + StringPair id = mkId("id"); + TreeNode root = new TreeNode(); + TreeNode bkmk = new BookmarkNode(name, id); + TreeNode text = new TextNode("abc"); + root.appendChild(bkmk); + root.appendChild(text); + doTest(root); + } + + public void testBookmarkXmlId() throws Exception + { + String name = mkName("mark"); + StringPair id = mkId("id"); + TreeNode root = new TreeNode(); + TreeNode bkm1 = new BookmarkStartNode(name, id); + TreeNode text = new TextNode("abc"); + TreeNode bkm2 = new BookmarkEndNode(name, id); + root.appendChild(bkm1); + root.appendChild(text); + root.appendChild(bkm2); + doTest(root); + } + + public void testRefmarkPoint() throws Exception + { + String name = mkName("refmark"); + TreeNode root = new TreeNode(); + TreeNode rfmk = new ReferenceMarkNode(name); + TreeNode text = new TextNode("abc"); + root.appendChild(rfmk); + root.appendChild(text); + doTest(root); + } + + public void testRefmark() throws Exception + { + String name = mkName("refmark"); + TreeNode root = new TreeNode(); + TreeNode rfm1 = new ReferenceMarkStartNode(name); + TreeNode text = new TextNode("abc"); + TreeNode rfm2 = new ReferenceMarkEndNode(name); + root.appendChild(rfm1); + root.appendChild(text); + root.appendChild(rfm2); + doTest(root); + } + + public void testToxmarkPoint() throws Exception + { + String name = mkName("toxmark"); + TreeNode root = new TreeNode(); + TreeNode txmk = new DocumentIndexMarkNode(name); + TreeNode text = new TextNode("abc"); + root.appendChild(txmk); + root.appendChild(text); + doTest(root); + } + + public void testToxmark() throws Exception + { + String name = mkName("toxmark"); + TreeNode root = new TreeNode(); + TreeNode txm1 = new DocumentIndexMarkStartNode(name); + TreeNode text = new TextNode("abc"); + TreeNode txm2 = new DocumentIndexMarkEndNode(name); + root.appendChild(txm1); + root.appendChild(text); + root.appendChild(txm2); + doTest(root); + } + + public void testHyperlink() throws Exception + { + String name = mkName("url"); + TreeNode root = new TreeNode(); + TreeNode href = new HyperlinkNode(name); + TreeNode text = new TextNode("abc"); + href.appendChild(text); + root.appendChild(href); + doTest(root); + } + + public void testHyperlinkEmpty() throws Exception + { + String name = mkName("url"); + TreeNode root = new TreeNode(); + TreeNode href = new HyperlinkNode(name); + TreeNode text = new TextNode(""); + href.appendChild(text); + root.appendChild(href); + doTest(root); + } + + public void testRuby() throws Exception + { + String name = mkName("ruby"); + TreeNode root = new TreeNode(); + TreeNode ruby = new RubyNode(name); + TreeNode text = new TextNode("abc"); + ruby.appendChild(text); + root.appendChild(ruby); + doTest(root); + } + + public void testRubyEmpty() throws Exception + { + // BUG: #i91534# + String name = mkName("ruby"); + TreeNode root = new TreeNode(); + TreeNode ruby = new RubyNode(name); + root.appendChild(ruby); + doTest(root); + } + + public void testMeta() throws Exception + { + StringPair id = new StringPair("content.xml", mkName("id")); + TreeNode root = new TreeNode(); + TreeNode meta = new MetaNode(id); + TreeNode text = new TextNode("abc"); + root.appendChild(new TextNode("123")); + meta.appendChild(text); + root.appendChild(meta); + doTest(root); + } + + public void testMetaEmpty() throws Exception + { + StringPair id = new StringPair("content.xml", mkName("id")); + TreeNode root = new TreeNode(); + TreeNode meta = new MetaNode(id); +// TreeNode text = new TextNode(""); +// meta.appendChild(text); + root.appendChild(meta); + doTest(root); + } + + public void testMetaField() throws Exception + { + StringPair id = new StringPair("content.xml", mkName("id")); + TreeNode root = new TreeNode(); + TreeNode meta = new MetaFieldNode(id); + TreeNode text = new TextNode("abc"); + root.appendChild(new TextNode("123")); + meta.appendChild(text); + root.appendChild(meta); + doTest(root); + } + + public void testMetaFieldEmpty() throws Exception + { + StringPair id = new StringPair("content.xml", mkName("id")); + TreeNode root = new TreeNode(); + TreeNode meta = new MetaFieldNode(id); +// TreeNode text = new TextNode(""); +// meta.appendChild(text); + root.appendChild(meta); + doTest(root); + } + + public void testBookmark1() throws Exception + { + String name1 = mkName("mark"); + String name2 = mkName("mark"); + String name3 = mkName("mark"); + TreeNode root = new TreeNode(); + root.appendChild( new BookmarkStartNode(name1) ); + root.appendChild( new BookmarkNode(name2) ); + root.appendChild( new BookmarkStartNode(name3) ); + root.appendChild( new TextNode("abc") ); + root.appendChild( new BookmarkEndNode(name1) ); + root.appendChild( new TextNode("de") ); + root.appendChild( new BookmarkEndNode(name3) ); + doTest(root); + } + + public void testBookmark2() throws Exception + { + String name1 = mkName("mark"); + String name2 = mkName("mark"); + String name3 = mkName("mark"); + TreeNode root = new TreeNode(); + root.appendChild( new BookmarkStartNode(name1) ); + root.appendChild( new TextNode("abc") ); + root.appendChild( new BookmarkNode(name2) ); + root.appendChild( new BookmarkStartNode(name3) ); + root.appendChild( new BookmarkEndNode(name1) ); + root.appendChild( new TextNode("de") ); + root.appendChild( new BookmarkEndNode(name3) ); + doTest(root); + } + + public void testRefMark2() throws Exception + { + String name1 = mkName("refmark"); + TreeNode root = new TreeNode(); + root.appendChild( new ReferenceMarkStartNode(name1) ); + root.appendChild( new TextNode("abc") ); + // BUG: #i102541# (this is actually not unoportenum's fault) + root.appendChild( new ReferenceMarkEndNode(name1) ); + root.appendChild( new TextNode("de") ); + doTest(root); + } + + public void testRefMark3() throws Exception + { + String name1 = mkName("refmark"); + String name2 = mkName("refmark"); + TreeNode root = new TreeNode(); + root.appendChild( new ReferenceMarkStartNode(name1) ); + root.appendChild( new ReferenceMarkStartNode(name2) ); + root.appendChild( new TextNode("abc") ); + root.appendChild( new ReferenceMarkEndNode(name2) ); + root.appendChild( new ReferenceMarkEndNode(name1) ); + root.appendChild( new TextNode("de") ); + doTest(root); + } + + public void testToxMark2() throws Exception + { + String name1 = mkName("toxmark"); + TreeNode root = new TreeNode(); + root.appendChild( new DocumentIndexMarkStartNode(name1) ); + root.appendChild( new TextNode("abc") ); + root.appendChild( new DocumentIndexMarkEndNode(name1) ); + root.appendChild( new TextNode("de") ); + doTest(root); + } + + public void testToxMark3() throws Exception + { + String name1 = mkName("toxmark"); + String name2 = mkName("toxmark"); + TreeNode root = new TreeNode(); + root.appendChild( new DocumentIndexMarkStartNode(name1) ); + root.appendChild( new DocumentIndexMarkStartNode(name2) ); + root.appendChild( new TextNode("abc") ); + root.appendChild( new DocumentIndexMarkEndNode(name2) ); + root.appendChild( new DocumentIndexMarkEndNode(name1) ); + root.appendChild( new TextNode("de") ); + doTest(root); + } + + public void testMarks1() throws Exception + { + String name1 = mkName("bookmark"); + String name2 = mkName("toxmark"); + String name3 = mkName("refmark"); + String name4 = mkName("toxmark"); + TreeNode root = new TreeNode(); + root.appendChild( new BookmarkStartNode(name1) ); + root.appendChild( new DocumentIndexMarkNode(name2) ); + root.appendChild( new ReferenceMarkStartNode(name3) ); + root.appendChild( new TextNode("abc") ); + root.appendChild( new BookmarkEndNode(name1) ); + root.appendChild( new DocumentIndexMarkStartNode(name4) ); + root.appendChild( new TextNode("de") ); + root.appendChild( new DocumentIndexMarkEndNode(name4) ); + root.appendChild( new ReferenceMarkEndNode(name3) ); + doTest(root); + } + + public void testMarks2() throws Exception + { + String name1 = mkName("bookmark"); + String name2 = mkName("refmark"); + String name3 = mkName("refmark"); + String name4 = mkName("toxmark"); + String name5 = mkName("refmark"); + TreeNode root = new TreeNode(); + root.appendChild( new BookmarkStartNode(name1) ); + root.appendChild( new ReferenceMarkNode(name2) ); + root.appendChild( new ReferenceMarkStartNode(name3) ); + root.appendChild( new TextNode("abc") ); + root.appendChild( new DocumentIndexMarkStartNode(name4) ); + root.appendChild( new ReferenceMarkStartNode(name5) ); + // BUG: #i102541# (this is actually not unoportenum's fault) + root.appendChild( new ReferenceMarkEndNode(name3) ); + root.appendChild( new TextNode("de") ); + root.appendChild( new DocumentIndexMarkEndNode(name4) ); + root.appendChild( new BookmarkEndNode(name1) ); + root.appendChild( new ReferenceMarkEndNode(name5) ); + doTest(root); + } + + public void testMarks3() throws Exception + { + String name1 = mkName("bookmark"); + String name2 = mkName("refmark"); + String name3 = mkName("refmark"); + String name4 = mkName("toxmark"); + String name5 = mkName("refmark"); + TreeNode root = new TreeNode(); + root.appendChild( new BookmarkStartNode(name1) ); + root.appendChild( new DocumentIndexMarkNode(name2) ); + root.appendChild( new DocumentIndexMarkStartNode(name3) ); + root.appendChild( new TextNode("abc") ); + root.appendChild( new ReferenceMarkStartNode(name4) ); + root.appendChild( new DocumentIndexMarkStartNode(name5) ); + root.appendChild( new DocumentIndexMarkEndNode(name3) ); + root.appendChild( new TextNode("de") ); + root.appendChild( new ReferenceMarkEndNode(name4) ); + root.appendChild( new BookmarkEndNode(name1) ); + root.appendChild( new DocumentIndexMarkEndNode(name5) ); + doTest(root); + } + + public void testFrameMark1() throws Exception + { + String name1 = mkName("bookmark"); + String name2 = mkName("frame"); + TreeNode root = new TreeNode(); + root.appendChild( new TextNode("abc") ); + root.appendChild( new BookmarkNode(name1) ); + root.appendChild( new TextNode("de") ); + root.appendChild( new FrameNode(name2, AS_CHARACTER) ); + doTest(root); + } + + public void testFrameMark2() throws Exception + { + // BUG: #i98530# + String name1 = mkName("bookmark"); + String name2 = mkName("frame"); + TreeNode root = new TreeNode(); + root.appendChild( new TextNode("abc") ); + root.appendChild( new BookmarkNode(name1) ); + root.appendChild( new TextNode("de") ); + root.appendChild( new FrameNode(name2, AT_CHARACTER) ); + doTest(root); + } + + public void testFrameMark3() throws Exception + { + String name1 = mkName("frame"); + String name2 = mkName("bookmark"); + TreeNode root = new TreeNode(); + root.appendChild( new TextNode("abc") ); + root.appendChild( new FrameNode(name1, AS_CHARACTER) ); + root.appendChild( new TextNode("de") ); + root.appendChild( new BookmarkNode(name2) ); + doTest(root); + } + + public void testFrameMark4() throws Exception + { + String name1 = mkName("frame"); + String name2 = mkName("bookmark"); + TreeNode root = new TreeNode(); + root.appendChild( new TextNode("abc") ); + root.appendChild( new FrameNode(name1, AT_CHARACTER) ); + root.appendChild( new TextNode("de") ); + root.appendChild( new BookmarkNode(name2) ); + doTest(root); + } + + public void testFrames1() throws Exception + { + String name1 = mkName("frame"); + String name2 = mkName("frame"); + String name3 = mkName("frame"); + TreeNode root = new TreeNode(); + root.appendChild( new FrameNode(name1, AT_CHARACTER) ); + root.appendChild( new FrameNode(name2, AT_CHARACTER) ); + root.appendChild( new FrameNode(name3, AT_CHARACTER) ); + doTest(root); + } + + public void testFrames2() throws Exception + { + String name1 = mkName("frame"); + String name2 = mkName("frame"); + String name3 = mkName("frame"); + TreeNode root = new TreeNode(); + root.appendChild( new FrameNode(name1, AS_CHARACTER) ); + root.appendChild( new FrameNode(name2, AS_CHARACTER) ); + root.appendChild( new FrameNode(name3, AS_CHARACTER) ); + doTest(root); + } + + public void testFrames3() throws Exception + { + String name1 = mkName("frame"); + String name2 = mkName("frame"); + String name3 = mkName("frame"); + TreeNode root = new TreeNode(); + root.appendChild( new FrameNode(name1, AT_CHARACTER) ); + root.appendChild( new FrameNode(name2, AS_CHARACTER) ); + root.appendChild( new FrameNode(name3, AT_CHARACTER) ); + doTest(root); + } + + public void testFrames4() throws Exception + { + String name1 = mkName("frame"); + String name2 = mkName("frame"); + String name3 = mkName("frame"); + TreeNode root = new TreeNode(); + root.appendChild( new FrameNode(name1, AT_CHARACTER) ); + root.appendChild( new FrameNode(name2, AT_CHARACTER) ); + root.appendChild( new FrameNode(name3, AS_CHARACTER) ); + doTest(root); + } + + public void testFrames5() throws Exception + { + String name1 = mkName("frame"); + String name2 = mkName("frame"); + String name3 = mkName("frame"); + TreeNode root = new TreeNode(); + root.appendChild( new FrameNode(name1, AS_CHARACTER) ); + root.appendChild( new FrameNode(name2, AT_CHARACTER) ); + root.appendChild( new FrameNode(name3, AT_CHARACTER) ); + doTest(root); + } + + public void testRubyHyperlink1() throws Exception + { + String name1 = mkName("ruby"); + String name2 = mkName("url"); + TreeNode root = new TreeNode(); + TreeNode ruby = new RubyNode(name1); + TreeNode href = new HyperlinkNode(name2); + href.appendChild( new TextNode("abc") ); + ruby.appendChild(href); + root.appendChild(ruby); + doTest(root); + } + + public void testRubyHyperlink2() throws Exception + { + String name1 = mkName("url"); + String name2 = mkName("ruby"); + TreeNode root = new TreeNode(); + TreeNode href = new HyperlinkNode(name1); + TreeNode ruby = new RubyNode(name2); + ruby.appendChild( new TextNode("abc") ); + href.appendChild(ruby); + root.appendChild(href); + doTest(root); + } + + public void testEnd1() throws Exception + { + String name1 = mkName("bookmark"); + String name2 = mkName("toxmark"); + String name3 = mkName("refmark"); + TreeNode root = new TreeNode(); + root.appendChild( new TextNode("abc") ); + root.appendChild( new BookmarkNode(name1) ); + root.appendChild( new DocumentIndexMarkNode(name2) ); + root.appendChild( new ReferenceMarkNode(name3) ); + doTest(root); + } + + public void testEnd2() throws Exception + { + String name1 = mkName("bookmark"); + String name2 = mkName("frame"); + String name3 = mkName("refmark"); + String name4 = mkName("frame"); + String name5 = mkName("frame"); + TreeNode root = new TreeNode(); + root.appendChild( new TextNode("abc") ); + root.appendChild( new BookmarkNode(name1) ); + root.appendChild( new FrameNode(name2, AT_CHARACTER) ); + root.appendChild( new ReferenceMarkNode(name3) ); + root.appendChild( new FrameNode(name4, AT_CHARACTER) ); + root.appendChild( new FrameNode(name5, AT_CHARACTER) ); + doTest(root); + } + + public void testEnd3() throws Exception + { + String name1 = mkName("ftn"); + String name2 = mkName("toxmark"); + TreeNode root = new TreeNode(); + root.appendChild( new TextNode("abc") ); + root.appendChild( new FootnoteNode(name1) ); + root.appendChild( new DocumentIndexMarkNode(name2) ); + doTest(root); + } + + public void testEnd4() throws Exception + { + String name1 = mkName("bookmark"); + String name2 = mkName("frame"); + TreeNode root = new TreeNode(); + root.appendChild( new BookmarkStartNode(name1) ); + root.appendChild( new TextNode("abc") ); + root.appendChild( new FrameNode(name2, AS_CHARACTER) ); + root.appendChild( new BookmarkEndNode(name1) ); + doTest(root); + } + + public void testEnd5() throws Exception + { + String name1 = mkName("refmark"); + String name2 = mkName("ruby"); + TreeNode root = new TreeNode(); + root.appendChild( new ReferenceMarkStartNode(name1) ); + root.appendChild( new TextNode("abc") ); + TreeNode ruby = new RubyNode(name2); + ruby.appendChild( new TextFieldNode("de") ); + root.appendChild(ruby); + root.appendChild( new ReferenceMarkEndNode(name1) ); + doTest(root); + } + + public void testEmpty1() throws Exception + { + String name1 = mkName("refmark"); + String name2 = mkName("toxmark"); + String name3 = mkName("bookmark"); + String name4 = mkName("frame"); + String name7 = mkName("refmark"); + String name8 = mkName("toxmark"); + String name9 = mkName("bookmark"); + String nameA = mkName("frame"); + TreeNode root = new TreeNode(); + root.appendChild( new ReferenceMarkNode(name1) ); + root.appendChild( new DocumentIndexMarkNode(name2) ); + root.appendChild( new BookmarkNode(name3) ); + root.appendChild( new FrameNode(name4, AT_CHARACTER) ); + root.appendChild( new ReferenceMarkNode(name7) ); + root.appendChild( new DocumentIndexMarkNode(name8) ); + root.appendChild( new BookmarkNode(name9) ); + root.appendChild( new FrameNode(nameA, AT_CHARACTER) ); + doTest(root); + } + + public void testEmpty2() throws Exception + { + String name3 = mkName("bookmark"); + String name4 = mkName("frame"); + String name9 = mkName("bookmark"); + String nameA = mkName("frame"); + TreeNode root = new TreeNode(); + root.appendChild( new BookmarkNode(name3) ); + root.appendChild( new FrameNode(name4, AT_CHARACTER) ); + root.appendChild( new BookmarkNode(name9) ); + root.appendChild( new FrameNode(nameA, AT_CHARACTER) ); + doTest(root); + } + + public void testEmpty3() throws Exception + { + String name1 = mkName("refmark"); + String name2 = mkName("toxmark"); + String name3 = mkName("bookmark"); + String name4 = mkName("frame"); + String name5 = mkName("url"); + String name6 = mkName("ruby"); + String name7 = mkName("refmark"); + String name8 = mkName("toxmark"); + String name9 = mkName("bookmark"); + String nameA = mkName("frame"); + TreeNode root = new TreeNode(); + root.appendChild( new ReferenceMarkNode(name1) ); + root.appendChild( new DocumentIndexMarkNode(name2) ); + root.appendChild( new BookmarkNode(name3) ); + root.appendChild( new FrameNode(name4, AT_CHARACTER) ); + /* currently empty hyperlinks may get eaten... + TreeNode href = new HyperlinkNode(name5); + href.appendChild( new TextNode("") ); + root.appendChild(href); + */ + TreeNode ruby = new RubyNode(name6); + root.appendChild(ruby); + root.appendChild( new ReferenceMarkNode(name7) ); + root.appendChild( new DocumentIndexMarkNode(name8) ); + root.appendChild( new BookmarkNode(name9) ); + root.appendChild( new FrameNode(nameA, AT_CHARACTER) ); + doTest(root); + } + + public void test1() throws Exception + { + String name1 = mkName("frame"); + String name2 = mkName("bookmark"); + String name3 = mkName("ruby"); + String name4 = mkName("ftn"); + String name5 = mkName("frame"); + TreeNode root = new TreeNode(); + root.appendChild( new FrameNode(name1, AT_CHARACTER) ); + root.appendChild( new BookmarkStartNode(name2) ); + root.appendChild( new TextNode("abc") ); + TreeNode ruby = new RubyNode(name3); + ruby.appendChild( new TextNode("de") ); + ruby.appendChild( new FootnoteNode(name4) ); + ruby.appendChild( new BookmarkEndNode(name2) ); + root.appendChild(ruby); + root.appendChild( new TextNode("fg") ); + root.appendChild( new FrameNode(name5, AT_CHARACTER) ); + root.appendChild( new TextFieldNode("h") ); + doTest(root); + } + + /* some range tests for the insertion: these are for the current + API which treats hyperlinks and rubys not as entities, but as formatting + attributes; if these ever become entities, they should not be split! + */ + + public void testRange1() throws Exception + { + String name1 = mkName("url"); + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("12345"); + inserter.insertRange(new Range(0, 0, text)); + TreeNode url1 = new HyperlinkNode(name1); + Range range1 = new Range(0, 5, url1); + inserter.insertRange(range1); + TreeNode root = new TreeNode(); + root.appendChild( url1 ); + url1.appendChild( text ); + doTest(root, false); + } + + public void testRangeHyperlinkHyperlink() throws Exception + { + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("123456789"); + inserter.insertRange( new Range(0, 0, text) ); + TreeNode url1 = new HyperlinkNode( mkName("url") ); + inserter.insertRange( new Range(1, 4, url1) ); + // overlap left + TreeNode url2 = new HyperlinkNode( mkName("url") ); + inserter.insertRange( new Range(0, 2, url2) ); + TreeNode root = new TreeNode() + .appendChild( url2.dup().appendChild( new TextNode("12") ) ) + .appendChild( url1.dup().appendChild( new TextNode("34") ) ) + .appendChild( new TextNode("56789") ); + doTest(root, false); + // overlap right + TreeNode url3 = new HyperlinkNode( mkName("url") ); + inserter.insertRange( new Range(3, 7, url3) ); + root = new TreeNode() + .appendChild( url2.dup().appendChild( new TextNode("12") ) ) + .appendChild( url1.dup().appendChild( new TextNode("3") ) ) + .appendChild( url3.dup().appendChild( new TextNode("4567") ) ) + .appendChild( new TextNode("89") ); + doTest(root, false); + // around + TreeNode url4 = new HyperlinkNode( mkName("url") ); + inserter.insertRange( new Range(3, 7, url4) ); + root = new TreeNode() + .appendChild( url2.dup().appendChild( new TextNode("12") ) ) + .appendChild( url1.dup().appendChild( new TextNode("3") ) ) + .appendChild( url4.dup().appendChild( new TextNode("4567") ) ) + .appendChild( new TextNode("89") ); + doTest(root, false); + // inside + TreeNode url5 = new HyperlinkNode( mkName("url") ); + inserter.insertRange( new Range(4, 6, url5) ); + root = new TreeNode() + .appendChild( url2.dup().appendChild( new TextNode("12") ) ) + .appendChild( url1.dup().appendChild( new TextNode("3") ) ) + .appendChild( url4.dup().appendChild( new TextNode("4") ) ) + .appendChild( url5.dup().appendChild( new TextNode("56") ) ) + .appendChild( url4.dup().appendChild( new TextNode("7") ) ) + .appendChild( new TextNode("89") ); + doTest(root, false); + } + + public void testRangeHyperlinkRuby() throws Exception + { + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("123456789"); + inserter.insertRange( new Range(0, 0, text) ); + TreeNode url1 = new HyperlinkNode( mkName("url") ); + inserter.insertRange( new Range(1, 4, url1) ); + // overlap left + TreeNode rby2 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(0, 2, rby2) ); + TreeNode root = new TreeNode() + .appendChild( rby2.dup() + .appendChild( new TextNode("1") ) + .appendChild( url1.dup().appendChild( new TextNode("2") ) ) ) + .appendChild( url1.dup().appendChild( new TextNode("34") ) ) + .appendChild( new TextNode("56789") ); + doTest(root, false); + // overlap right + TreeNode rby3 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(3, 5, rby3) ); + root = new TreeNode() + .appendChild( rby2.dup() + .appendChild( new TextNode("1") ) + .appendChild( url1.dup().appendChild( new TextNode("2") ) ) ) + .appendChild( url1.dup().appendChild( new TextNode("3") ) ) + .appendChild( rby3.dup() + .appendChild( url1.dup().appendChild( new TextNode("4") ) ) + .appendChild( new TextNode("5") ) ) + .appendChild( new TextNode("6789") ); + doTest(root, false); + // around + TreeNode rby4 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(2, 3, rby4) ); + root = new TreeNode() + .appendChild( rby2.dup() + .appendChild( new TextNode("1") ) + .appendChild( url1.dup().appendChild( new TextNode("2") ) ) ) + .appendChild( rby4.dup() + .appendChild( url1.dup().appendChild( new TextNode("3") ) ) ) + .appendChild( rby3.dup() + .appendChild( url1.dup().appendChild( new TextNode("4") ) ) + .appendChild( new TextNode("5") ) ) + .appendChild( new TextNode("6789") ); + doTest(root, false); + // inside + TreeNode url5 = new HyperlinkNode( mkName("url") ); + inserter.insertRange( new Range(6, 9, url5) ); + TreeNode rby6 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(7, 8, rby6) ); + root = new TreeNode() + .appendChild( rby2.dup() + .appendChild( new TextNode("1") ) + .appendChild( url1.dup().appendChild( new TextNode("2") ) ) ) + .appendChild( rby4.dup() + .appendChild( url1.dup().appendChild( new TextNode("3") ) ) ) + .appendChild( rby3.dup() + .appendChild( url1.dup().appendChild( new TextNode("4") ) ) + .appendChild( new TextNode("5") ) ) + .appendChild( new TextNode("6") ) + .appendChild( url5.dup().appendChild( new TextNode("7") ) ) + .appendChild( rby6.dup() + .appendChild( url5.dup().appendChild( new TextNode("8") ) ) ) + .appendChild( url5.dup().appendChild( new TextNode("9") ) ); + doTest(root, false); + } + + public void testRangeRubyHyperlink() throws Exception + { + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("123456789"); + inserter.insertRange( new Range(0, 0, text) ); + TreeNode rby1 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(1, 6, rby1) ); + // overlap left + TreeNode url2 = new HyperlinkNode( mkName("url") ); + inserter.insertRange( new Range(0, 3, url2) ); + TreeNode root = new TreeNode() + .appendChild( url2.dup().appendChild( new TextNode("1") ) ) + .appendChild( rby1.dup() + .appendChild( url2.dup().appendChild( new TextNode("23") ) ) + .appendChild( new TextNode("456") ) ) + .appendChild( new TextNode("789") ); + doTest(root, false); + // overlap right + TreeNode url3 = new HyperlinkNode( mkName("url") ); + inserter.insertRange( new Range(5, 7, url3) ); + root = new TreeNode() + .appendChild( url2.dup().appendChild( new TextNode("1") ) ) + .appendChild( rby1.dup() + .appendChild( url2.dup().appendChild( new TextNode("23") ) ) + .appendChild( new TextNode("45") ) + .appendChild( url3.dup().appendChild( new TextNode("6") ) ) ) + .appendChild( url3.dup().appendChild( new TextNode("7") ) ) + .appendChild( new TextNode("89") ); + doTest(root, false); + // around (not quite, due to API) + TreeNode url4 = new HyperlinkNode( mkName("url") ); + inserter.insertRange( new Range(1, 8, url4) ); + root = new TreeNode() + .appendChild( url2.dup().appendChild( new TextNode("1") ) ) + .appendChild( rby1.dup() + .appendChild( url4.dup() + .appendChild( new TextNode("23456") ) ) ) + .appendChild( url4.dup().appendChild( new TextNode("78") ) ) + .appendChild( new TextNode("9") ); + doTest(root, false); + // inside + TreeNode url5 = new HyperlinkNode( mkName("url") ); + inserter.insertRange( new Range(3, 5, url5) ); + root = new TreeNode() + .appendChild( url2.dup().appendChild( new TextNode("1") ) ) + .appendChild( rby1.dup() + .appendChild( url4.dup() + .appendChild( new TextNode("23") ) ) + .appendChild( url5.dup() + .appendChild( new TextNode("45") ) ) + .appendChild( url4.dup() + .appendChild( new TextNode("6") ) ) ) + .appendChild( url4.dup().appendChild( new TextNode("78") ) ) + .appendChild( new TextNode("9") ); + doTest(root, false); + } + + public void testRangeRubyRuby() throws Exception + { + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("123456789"); + inserter.insertRange( new Range(0, 0, text) ); + TreeNode rby1 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(1, 4, rby1) ); + // overlap left + TreeNode rby2 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(0, 2, rby2) ); + TreeNode root = new TreeNode() + .appendChild( rby2.dup().appendChild( new TextNode("12") ) ) + .appendChild( rby1.dup().appendChild( new TextNode("34") ) ) + .appendChild( new TextNode("56789") ); + doTest(root, false); + // overlap right + TreeNode rby3 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(3, 7, rby3) ); + root = new TreeNode() + .appendChild( rby2.dup().appendChild( new TextNode("12") ) ) + .appendChild( rby1.dup().appendChild( new TextNode("3") ) ) + .appendChild( rby3.dup().appendChild( new TextNode("4567") ) ) + .appendChild( new TextNode("89") ); + doTest(root, false); + // around + TreeNode rby4 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(3, 7, rby4) ); + root = new TreeNode() + .appendChild( rby2.dup().appendChild( new TextNode("12") ) ) + .appendChild( rby1.dup().appendChild( new TextNode("3") ) ) + .appendChild( rby4.dup().appendChild( new TextNode("4567") ) ) + .appendChild( new TextNode("89") ); + doTest(root, false); + // inside + TreeNode rby5 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(4, 6, rby5) ); + root = new TreeNode() + .appendChild( rby2.dup().appendChild( new TextNode("12") ) ) + .appendChild( rby1.dup().appendChild( new TextNode("3") ) ) + .appendChild( rby4.dup().appendChild( new TextNode("4") ) ) + .appendChild( rby5.dup().appendChild( new TextNode("56") ) ) + .appendChild( rby4.dup().appendChild( new TextNode("7") ) ) + .appendChild( new TextNode("89") ); + doTest(root, false); + } + + public void testRangeHyperlinkMeta() throws Exception + { + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("123456789"); + inserter.insertRange( new Range(0, 0, text) ); + TreeNode url1 = new HyperlinkNode( mkName("url") ); + inserter.insertRange( new Range(1, 4, url1) ); + // overlap left + TreeNode met2 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(0, 2, met2) ); + TreeNode root = new TreeNode() + .appendChild( met2.dup() + .appendChild( new TextNode("1") ) + .appendChild( url1.dup().appendChild( new TextNode("2") ) ) ) + .appendChild( url1.dup().appendChild( new TextNode("34") ) ) + .appendChild( new TextNode("56789") ); + doTest(root, false); + // overlap right + TreeNode met3 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(4/*-1*/, 6/*-1*/, met3) ); + root = new TreeNode() + .appendChild( met2.dup() + .appendChild( new TextNode("1") ) + .appendChild( url1.dup().appendChild( new TextNode("2") ) ) ) + .appendChild( url1.dup().appendChild( new TextNode("3") ) ) + .appendChild( met3.dup() + .appendChild( url1.dup().appendChild( new TextNode("4") ) ) + .appendChild( new TextNode("5") ) ) + .appendChild( new TextNode("6789") ); + doTest(root, false); + // around + TreeNode met4 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(3/*-1*/, 4/*-1*/, met4) ); + root = new TreeNode() + .appendChild( met2.dup() + .appendChild( new TextNode("1") ) + .appendChild( url1.dup().appendChild( new TextNode("2") ) ) ) + .appendChild( met4.dup() + .appendChild( url1.dup().appendChild( new TextNode("3") ) ) ) + .appendChild( met3.dup() + .appendChild( url1.dup().appendChild( new TextNode("4") ) ) + .appendChild( new TextNode("5") ) ) + .appendChild( new TextNode("6789") ); + doTest(root, false); + // inside + TreeNode url5 = new HyperlinkNode( mkName("url") ); + inserter.insertRange( new Range(9/*-3*/, 12/*-3*/, url5) ); + TreeNode met6 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(10/*-3*/, 11/*-3*/, met6) ); + root = new TreeNode() + .appendChild( met2.dup() + .appendChild( new TextNode("1") ) + .appendChild( url1.dup().appendChild( new TextNode("2") ) ) ) + .appendChild( met4.dup() + .appendChild( url1.dup().appendChild( new TextNode("3") ) ) ) + .appendChild( met3.dup() + .appendChild( url1.dup().appendChild( new TextNode("4") ) ) + .appendChild( new TextNode("5") ) ) + .appendChild( new TextNode("6") ) + .appendChild( url5.dup().appendChild( new TextNode("7") ) ) + .appendChild( met6.dup() + .appendChild( url5.dup().appendChild( new TextNode("8") ) ) ) + .appendChild( url5.dup().appendChild( new TextNode("9") ) ); + doTest(root, false); + } + + public void testRangeRubyMeta() throws Exception + { + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("123456789"); + inserter.insertRange( new Range(0, 0, text) ); + TreeNode rby1 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(1, 4, rby1) ); + // overlap left + TreeNode met2 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(0, 2, met2) ); + TreeNode root = new TreeNode() + .appendChild( met2.dup() + .appendChild( new TextNode("1") ) + .appendChild( rby1.dup().appendChild( new TextNode("2") ) ) ) + .appendChild( rby1.dup().appendChild( new TextNode("34") ) ) + .appendChild( new TextNode("56789") ); + doTest(root, false); + // overlap right + TreeNode met3 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(4/*-1*/, 6/*-1*/, met3) ); + root = new TreeNode() + .appendChild( met2.dup() + .appendChild( new TextNode("1") ) + .appendChild( rby1.dup().appendChild( new TextNode("2") ) ) ) + .appendChild( rby1.dup().appendChild( new TextNode("3") ) ) + .appendChild( met3.dup() + .appendChild( rby1.dup().appendChild( new TextNode("4") ) ) + .appendChild( new TextNode("5") ) ) + .appendChild( new TextNode("6789") ); + doTest(root, false); + // around + TreeNode met4 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(3/*-1*/, 4/*-1*/, met4) ); + root = new TreeNode() + .appendChild( met2.dup() + .appendChild( new TextNode("1") ) + .appendChild( rby1.dup().appendChild( new TextNode("2") ) ) ) + .appendChild( met4.dup() + .appendChild( rby1.dup().appendChild( new TextNode("3") ) ) ) + .appendChild( met3.dup() + .appendChild( rby1.dup().appendChild( new TextNode("4") ) ) + .appendChild( new TextNode("5") ) ) + .appendChild( new TextNode("6789") ); + doTest(root, false); + // inside + TreeNode rby5 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(9/*-3*/, 12/*-3*/, rby5) ); + TreeNode met6 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(10/*-3*/, 11/*-3*/, met6) ); + root = new TreeNode() + .appendChild( met2.dup() + .appendChild( new TextNode("1") ) + .appendChild( rby1.dup().appendChild( new TextNode("2") ) ) ) + .appendChild( met4.dup() + .appendChild( rby1.dup().appendChild( new TextNode("3") ) ) ) + .appendChild( met3.dup() + .appendChild( rby1.dup().appendChild( new TextNode("4") ) ) + .appendChild( new TextNode("5") ) ) + .appendChild( new TextNode("6") ) + .appendChild( rby5.dup() + .appendChild( new TextNode("7") ) + .appendChild( met6.dup() + .appendChild( new TextNode("8") ) ) + .appendChild( new TextNode("9") ) ); + doTest(root, false); + } + + public void testRangeMetaHyperlink() throws Exception + { + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("123456789"); + inserter.insertRange( new Range(0, 0, text) ); + TreeNode met1 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(1, 6, met1) ); + // overlap left + TreeNode url2 = new HyperlinkNode( mkName("url") ); + inserter.insertRange( new Range(0, 4/*-1*/, url2) ); + TreeNode root = new TreeNode() + .appendChild( url2.dup().appendChild( new TextNode("1") ) ) + .appendChild( met1.dup() + .appendChild( url2.dup().appendChild( new TextNode("23") ) ) + .appendChild( new TextNode("456") ) ) + .appendChild( new TextNode("789") ); + doTest(root, false); + // overlap right + TreeNode url3 = new HyperlinkNode( mkName("url") ); + inserter.insertRange( new Range(6/*-1*/, 8/*-1*/, url3) ); + root = new TreeNode() + .appendChild( url2.dup().appendChild( new TextNode("1") ) ) + .appendChild( met1.dup() + .appendChild( url2.dup().appendChild( new TextNode("23") ) ) + .appendChild( new TextNode("45") ) + .appendChild( url3.dup().appendChild( new TextNode("6") ) ) ) + .appendChild( url3.dup().appendChild( new TextNode("7") ) ) + .appendChild( new TextNode("89") ); + doTest(root, false); + // around (not quite, due to API) + TreeNode url4 = new HyperlinkNode( mkName("url") ); + inserter.insertRange( new Range(1, 9/*-1*/, url4) ); + root = new TreeNode() + .appendChild( url2.dup().appendChild( new TextNode("1") ) ) + .appendChild( met1.dup() + .appendChild( url4.dup() + .appendChild( new TextNode("23456") ) ) ) + .appendChild( url4.dup().appendChild( new TextNode("78") ) ) + .appendChild( new TextNode("9") ); + doTest(root, false); + // inside + TreeNode url5 = new HyperlinkNode( mkName("url") ); + inserter.insertRange( new Range(4/*-1*/, 6/*-1*/, url5) ); + root = new TreeNode() + .appendChild( url2.dup().appendChild( new TextNode("1") ) ) + .appendChild( met1.dup() + .appendChild( url4.dup() + .appendChild( new TextNode("23") ) ) + .appendChild( url5.dup() + .appendChild( new TextNode("45") ) ) + .appendChild( url4.dup() + .appendChild( new TextNode("6") ) ) ) + .appendChild( url4.dup().appendChild( new TextNode("78") ) ) + .appendChild( new TextNode("9") ); + doTest(root, false); + } + + public void testRangeMetaRuby() throws Exception + { + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("123456789"); + inserter.insertRange( new Range(0, 0, text) ); + TreeNode met1 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(1, 5, met1) ); + // overlap left + TreeNode rby2 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(0, 3/*-1*/, rby2) ); + TreeNode root = new TreeNode() + .appendChild( rby2.dup().appendChild( new TextNode("1") ) ) + .appendChild( met1.dup() + .appendChild( rby2.dup().appendChild( new TextNode("2") ) ) + .appendChild( new TextNode("345") ) ) + .appendChild( new TextNode("6789") ); + doTest(root, false); + // overlap right + TreeNode rby3 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(5/*-1*/, 7/*-1*/, rby3) ); + root = new TreeNode() + .appendChild( rby2.dup().appendChild( new TextNode("1") ) ) + .appendChild( met1.dup() + .appendChild( rby2.dup().appendChild( new TextNode("2") ) ) + .appendChild( new TextNode("34") ) + .appendChild( rby3.dup().appendChild( new TextNode("5") ) ) ) + .appendChild( rby3.dup().appendChild( new TextNode("6") ) ) + .appendChild( new TextNode("789") ); + doTest(root, false); + // around + TreeNode rby4 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(1, 7/*-1*/, rby4) ); + root = new TreeNode() + .appendChild( rby2.dup().appendChild( new TextNode("1") ) ) + .appendChild( rby4.dup() + .appendChild( met1.dup() + .appendChild( new TextNode("2345") ) ) + .appendChild( new TextNode("6") ) ) + .appendChild( new TextNode("789") ); + doTest(root, false); + // inside + TreeNode met5 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(7/*-1*/, 9/*-1*/, met5) ); + TreeNode rby6 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(9/*-2*/, 10/*-2*/, rby6) ); + root = new TreeNode() + .appendChild( rby2.dup().appendChild( new TextNode("1") ) ) + .appendChild( rby4.dup() + .appendChild( met1.dup() + .appendChild( new TextNode("2345") ) ) + .appendChild( new TextNode("6") ) ) + .appendChild( met5.dup() + .appendChild( new TextNode("7") ) + .appendChild( rby6.dup() + .appendChild( new TextNode("8") ) ) ) + .appendChild( new TextNode("9") ); + doTest(root, false); + // inside, with invalid range that includes the dummy char + TreeNode rby7 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(7/*-1*/, 9/*-2*/, rby7) ); + root = new TreeNode() + .appendChild( rby2.dup().appendChild( new TextNode("1") ) ) + .appendChild( rby4.dup() + .appendChild( met1.dup() + .appendChild( new TextNode("2345") ) ) + .appendChild( new TextNode("6") ) ) + .appendChild( met5.dup() + .appendChild( rby7.dup() + .appendChild( new TextNode("7") ) ) + .appendChild( rby6.dup() + .appendChild( new TextNode("8") ) ) ) + .appendChild( new TextNode("9") ); + doTest(root, false); + // around, at same position as meta + TreeNode rby8 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(7/*-1*/, 10/*-2*/, rby8) ); + root = new TreeNode() + .appendChild( rby2.dup().appendChild( new TextNode("1") ) ) + .appendChild( rby4.dup() + .appendChild( met1.dup() + .appendChild( new TextNode("2345") ) ) + .appendChild( new TextNode("6") ) ) + .appendChild( rby8.dup() + .appendChild( met5.dup() + .appendChild( new TextNode("78") ) ) ) + .appendChild( new TextNode("9") ); + doTest(root, false); + } + + public void testRangeMetaMeta() throws Exception + { + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("123456789"); + inserter.insertRange( new Range(0, 0, text) ); + TreeNode met1 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(3, 6, met1) ); + // overlap left + TreeNode met2 = new MetaNode( mkId("id") ); + try { + inserter.insertRange( new Range(0, 4, met2) ); + assure("testRangeMetaMeta: overlap left allowed", false); + } catch (com.sun.star.lang.IllegalArgumentException e) { /* ignore */ } + TreeNode root = new TreeNode() + .appendChild( new TextNode("123") ) + .appendChild( met1.dup().appendChild( new TextNode("456") ) ) + .appendChild( new TextNode("789") ); + doTest(root, false); + // overlap right + TreeNode met3 = new MetaNode( mkId("id") ); + try { + inserter.insertRange( new Range(5/*-1*/, 8/*-1*/, met3) ); + assure("testRangeMetaMeta: overlap right allowed", false); + } catch (com.sun.star.lang.IllegalArgumentException e) { /* ignore */ } + root = new TreeNode() + .appendChild( new TextNode("123") ) + .appendChild( met1.dup().appendChild( new TextNode("456") ) ) + .appendChild( new TextNode("789") ); + doTest(root, false); + // around + TreeNode met4 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(3, 7/*-1*/, met4) ); + root = new TreeNode() + .appendChild( new TextNode("123") ) + .appendChild( met4.dup() + .appendChild( met1.dup().appendChild( new TextNode("456") ) ) ) + .appendChild( new TextNode("789") ); + doTest(root, false); + // inside + TreeNode met5 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(6/*-2*/, 8/*-2*/, met5) ); + root = new TreeNode() + .appendChild( new TextNode("123") ) + .appendChild( met4.dup() + .appendChild( met1.dup() + .appendChild( new TextNode("4") ) + .appendChild( met5.dup() + .appendChild( new TextNode("56") ) ) ) ) + .appendChild( new TextNode("789") ); + doTest(root, false); + } + + public void testRange2() throws Exception + { + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("123456789"); + inserter.insertRange( new Range(0, 0, text) ); + TreeNode met1 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(1, 8, met1) ); + TreeNode met2 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(3/*-1*/, 8/*-1*/, met2) ); + TreeNode met3 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(5/*-2*/, 8/*-2*/, met3) ); + TreeNode root = new TreeNode() + .appendChild( new TextNode("1") ) + .appendChild( met1.dup() + .appendChild( new TextNode("2") ) + .appendChild( met2.dup() + .appendChild( new TextNode("3") ) + .appendChild( met3.dup() + .appendChild( new TextNode("456") ) ) + .appendChild( new TextNode("7") ) ) + .appendChild( new TextNode("8") ) ) + .appendChild( new TextNode("9") ); + doTest(root, false); + // split ruby at every meta start! + TreeNode rby4 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(0, 7/*-3*/, rby4) ); + root = new TreeNode() + .appendChild( rby4.dup() + .appendChild( new TextNode("1") ) ) + .appendChild( met1.dup() + .appendChild( rby4.dup() + .appendChild( new TextNode("2") ) ) + .appendChild( met2.dup() + .appendChild( rby4.dup() + .appendChild( new TextNode("3") ) ) + .appendChild( met3.dup() + .appendChild( rby4.dup() + .appendChild( new TextNode("4") ) ) + .appendChild( new TextNode("56") ) ) + .appendChild( new TextNode("7") ) ) + .appendChild( new TextNode("8") ) ) + .appendChild( new TextNode("9") ); + doTest(root, false); + // split ruby at every meta end! + TreeNode rby5 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(8/*-3*/, 12/*-3*/, rby5) ); + root = new TreeNode() + .appendChild( rby4.dup() + .appendChild( new TextNode("1") ) ) + .appendChild( met1.dup() + .appendChild( rby4.dup() + .appendChild( new TextNode("2") ) ) + .appendChild( met2.dup() + .appendChild( rby4.dup() + .appendChild( new TextNode("3") ) ) + .appendChild( met3.dup() + .appendChild( rby4.dup() + .appendChild( new TextNode("4") ) ) + .appendChild( new TextNode("5") ) + .appendChild( rby5.dup() + .appendChild( new TextNode("6") ) ) ) + .appendChild( rby5.dup() + .appendChild( new TextNode("7") ) ) ) + .appendChild( rby5.dup() + .appendChild( new TextNode("8") ) ) ) + .appendChild( rby5.dup() + .appendChild( new TextNode("9") ) ); + doTest(root, false); + } + + public void testRange3() throws Exception + { + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("123456789"); + inserter.insertRange( new Range(0, 0, text) ); + TreeNode rby1 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(0, 9, rby1) ); + TreeNode met2 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(2, 7, met2) ); + TreeNode root = new TreeNode() + .appendChild( rby1.dup() + .appendChild( new TextNode("12") ) + .appendChild( met2.dup() + .appendChild( new TextNode("34567") ) ) + .appendChild( new TextNode("89") ) ); + doTest(root, false); + // overwrite outer ruby, split remains at inner meta! + TreeNode rby3 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(5/*-1*/, 6/*-1*/, rby3) ); + root = new TreeNode() + .appendChild( rby1.dup() + .appendChild( new TextNode("12") ) ) + .appendChild( met2.dup() + .appendChild( rby1.dup() + .appendChild( new TextNode("34") ) ) + .appendChild( rby3.dup() + .appendChild( new TextNode("5") ) ) + .appendChild( rby1.dup() + .appendChild( new TextNode("67") ) ) ) + .appendChild( rby1.dup() + .appendChild( new TextNode("89") ) ); + doTest(root, false); + } + + public void testRange4() throws Exception + { + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("123456789"); + inserter.insertRange( new Range(0, 0, text) ); + TreeNode rby1 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(0, 9, rby1) ); + TreeNode met2 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(1, 8, met2) ); + TreeNode met3 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(3/*-1*/, 8/*-1*/, met3) ); + TreeNode met4 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(5/*-2*/, 8/*-2*/, met4) ); + TreeNode root = new TreeNode() + .appendChild( rby1.dup() + .appendChild( new TextNode("1") ) + .appendChild( met2.dup() + .appendChild( new TextNode("2") ) + .appendChild( met3.dup() + .appendChild( new TextNode("3") ) + .appendChild( met4.dup() + .appendChild( new TextNode("456") ) ) + .appendChild( new TextNode("7") ) ) + .appendChild( new TextNode("8") ) ) + .appendChild( new TextNode("9") ) ); + doTest(root, false); + // overwrite outer ruby, split remains at every inner meta! + TreeNode rby5 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(7/*-3*/, 8/*-3*/, rby5) ); + root = new TreeNode() + .appendChild( rby1.dup() + .appendChild( new TextNode("1") ) ) + .appendChild( met2.dup() + .appendChild( rby1.dup() + .appendChild( new TextNode("2") ) ) + .appendChild( met3.dup() + .appendChild( rby1.dup() + .appendChild( new TextNode("3") ) ) + .appendChild( met4.dup() + .appendChild( rby1.dup() + .appendChild( new TextNode("4") ) ) + .appendChild( rby5.dup() + .appendChild( new TextNode("5") ) ) + .appendChild( rby1.dup() + .appendChild( new TextNode("6") ) ) ) + .appendChild( rby1.dup() + .appendChild( new TextNode("7") ) ) ) + .appendChild( rby1.dup() + .appendChild( new TextNode("8") ) ) ) + .appendChild( rby1.dup() + .appendChild( new TextNode("9") ) ); + doTest(root, false); + } + + public void testRange5() throws Exception + { + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("123456789"); + inserter.insertRange( new Range(0, 0, text) ); + TreeNode rby1 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(0, 9, rby1) ); + TreeNode met2 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(1, 3, met2) ); + TreeNode met3 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(5/*-1*/, 6/*-1*/, met3) ); + TreeNode met4 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(8/*-2*/, 10/*-2*/, met4) ); + TreeNode root = new TreeNode() + .appendChild( rby1.dup() + .appendChild( new TextNode("1") ) + .appendChild( met2.dup().appendChild( new TextNode("23") ) ) + .appendChild( new TextNode("4") ) + .appendChild( met3.dup().appendChild( new TextNode("5") ) ) + .appendChild( new TextNode("6") ) + .appendChild( met4.dup().appendChild( new TextNode("78") ) ) + .appendChild( new TextNode("9") ) ); + doTest(root, false); + // overwrite outer ruby, but split at inner metas! + TreeNode rby5 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(3/*-1*/, 10/*-3*/, rby5) ); + root = new TreeNode() + .appendChild( rby1.dup() + .appendChild( new TextNode("1") ) ) + .appendChild( met2.dup() + .appendChild( rby1.dup() + .appendChild( new TextNode("2") ) ) + .appendChild( rby5.dup() + .appendChild( new TextNode("3") ) ) ) + .appendChild( rby5.dup() + .appendChild( new TextNode("4") ) + .appendChild( met3.dup() + .appendChild( new TextNode("5") ) ) + .appendChild( new TextNode("6") ) ) + .appendChild( met4.dup() + .appendChild( rby5.dup() + .appendChild( new TextNode("7") ) ) + .appendChild( rby1.dup() + .appendChild( new TextNode("8") ) ) ) + .appendChild( rby1.dup() + .appendChild( new TextNode("9") ) ); + doTest(root, false); + } + + public void testRange6() throws Exception + { + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("123456789"); + inserter.insertRange( new Range(0, 0, text) ); + TreeNode met1 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(1, 5, met1) ); + TreeNode met2 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(3/*-1*/, 6/*-1*/, met2) ); + TreeNode met3 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(5/*-2*/, 7/*-2*/, met3) ); + TreeNode root = new TreeNode() + .appendChild( new TextNode("1") ) + .appendChild( met1.dup() + .appendChild( new TextNode("2") ) + .appendChild( met2.dup() + .appendChild( new TextNode("3") ) + .appendChild( met3.dup() + .appendChild( new TextNode("45") ) ) ) ) + .appendChild( new TextNode("6789") ); + doTest(root, false); + // split at 3 metas, all at same position + TreeNode rby4 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(7/*-3*/, 10/*-3*/, rby4) ); + root = new TreeNode() + .appendChild( new TextNode("1") ) + .appendChild( met1.dup() + .appendChild( new TextNode("2") ) + .appendChild( met2.dup() + .appendChild( new TextNode("3") ) + .appendChild( met3.dup() + .appendChild( new TextNode("4") ) + .appendChild( rby4.dup() + .appendChild( new TextNode("5") ) ) ) ) ) + .appendChild( rby4.dup() + .appendChild( new TextNode("67") ) ) + .appendChild( new TextNode("89") ); + doTest(root, false); + } + + public void testRange7() throws Exception + { + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("123456789"); + inserter.insertRange( new Range(0, 0, text) ); + TreeNode url1 = new HyperlinkNode( mkName("url") ); + inserter.insertRange( new Range(1, 5, url1) ); + TreeNode met2 = new MetaNode( mkId("id") ); + inserter.insertRange( new Range(3, 5, met2) ); + TreeNode root = new TreeNode() + .appendChild( new TextNode("1") ) + .appendChild( url1.dup() + .appendChild( new TextNode("23") ) ) + .appendChild( met2.dup() + .appendChild( url1.dup() + .appendChild( new TextNode("45") ) ) ) + .appendChild( new TextNode("6789") ); + doTest(root, false); + // this should result in not splitting the hyperlink, but due to API + // we can't tell :( + TreeNode rby3 = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(5/*-1*/, 8/*-1*/, rby3) ); + root = new TreeNode() + .appendChild( new TextNode("1") ) + .appendChild( url1.dup() + .appendChild( new TextNode("23") ) ) + .appendChild( met2.dup() + .appendChild( url1.dup() + .appendChild( new TextNode("4") ) ) + .appendChild( rby3.dup() + .appendChild( url1.dup() + .appendChild( new TextNode("5") ) ) ) ) + .appendChild( rby3.dup() + .appendChild( new TextNode("67") ) ) + .appendChild( new TextNode("89") ); + doTest(root, false); + } + + /* TODO: test partial selection, test UNDO/REDO */ + + /** test SwXMeta XText interface */ + public void testMetaXText() throws Exception + { + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("12AB6789"); + inserter.insertRange( new Range(0, 0, text) ); + MetaNode meta = new MetaNode( mkId("id") ); +// inserter.insertRange( new Range(3, 5, met2) ); + XTextContent xMeta = inserter.makeMeta(); + + XText xDocText = m_xDoc.getText(); + XTextCursor xDocTextCursor = xDocText.createTextCursor(); + xDocTextCursor.goRight((short)3, false); + xDocTextCursor.goRight((short)2, true); + xDocText.insertTextContent(xDocTextCursor, xMeta, true); +// xMeta.attach(xDocTextCursor); + + XMetadatable xMetadatable = (XMetadatable) + UnoRuntime.queryInterface(XMetadatable.class, xMeta); + xMetadatable.setMetadataReference(meta.getXmlId()); + XText xText = (XText) UnoRuntime.queryInterface(XText.class, xMeta); + + XText xParentText = xText.getText(); + assure("getText(): no parent", xParentText != null); + + XTextRange xStart = xText.getStart(); + assure("getStart(): no start", xStart != null); + + XTextRange xEnd = xText.getEnd(); + assure("getEnd(): no end", xEnd != null); + + /* + String string = xText.getString(); + assure("getString(): invalid string returned", + string != null && "AB".equals(string) ); + */ + + xText.setString("45"); + + { + String string = xText.getString(); + assure("getString(): invalid string returned: " + string, + string != null && "45".equals(string) ); + } + + XTextCursor xTextCursor = xText.createTextCursor(); + assure("createTextCursor(): failed", xTextCursor != null); + + try { + xText.createTextCursorByRange(null); + assure("createTextCursorByRange(): null allowed?", false); + } catch (RuntimeException e) { /* expected */ } + + XTextCursor xTextCursorStart = xText.createTextCursorByRange(xStart); + assure("createTextCursorByRange(): failed for start", + xTextCursorStart != null); + + XTextCursor xTextCursorEnd = xText.createTextCursorByRange(xEnd); + assure("createTextCursorByRange(): failed for end", + xTextCursorEnd != null); + + // move outside meta + xDocTextCursor.gotoStart(false); + + try { + xText.insertString(null, "foo", false); + assure("insertString(): null allowed?", false); + } catch (RuntimeException e) { /* expected */ } + + try { + xText.insertString(xDocTextCursor, "foo", false); + assure("insertString(): cursor outside allowed?", false); + } catch (RuntimeException e) { /* expected */ } + + xStart = xText.getStart(); + xText.insertString(xStart, "A", false); + { + String string = xText.getString(); + assure("getString(): invalid string returned: " + string, + string != null && "A45".equals(string) ); + } + + xText.insertString(xEnd, "B", false); + { + String string = xText.getString(); + assure("getString(): invalid string returned: " + string, + string != null && "A45B".equals(string) ); + } + + try { + xText.insertControlCharacter(null, HARD_HYPHEN, false); + assure("insertControlCharacter(): null allowed?", false); + } catch (com.sun.star.lang.IllegalArgumentException e) { /* ignore */ } + + xStart = xText.getStart(); + try { + xText.insertControlCharacter(xDocTextCursor, HARD_HYPHEN, false); + assure("insertControlCharacter(): cursor outside allowed?", false); + } catch (com.sun.star.lang.IllegalArgumentException e) { /* ignore */ } + + xText.insertControlCharacter(xStart, HARD_HYPHEN, false); + { + String string = xText.getString(); + assure("getString(): invalid string returned: " + string, + string != null && ('\u2011' + "A45B").equals(string) ); + } + + xText.insertControlCharacter(xEnd, HARD_HYPHEN, false); + { + String string = xText.getString(); + assure("getString(): invalid string returned: " + string, + string != null && + ('\u2011' + "A45B" + '\u2011').equals(string) ); + } + + xText.setString("45"); + + try { + xText.insertTextContent(null, xMeta, false); + assure("insertTextContent(): null range allowed?", false); + } catch (com.sun.star.lang.IllegalArgumentException e) { /* ignore */ } + + try { + xText.insertTextContent(xStart, null, false); + assure("insertTextContent(): null content allowed?", false); + } catch (com.sun.star.lang.IllegalArgumentException e) { /* ignore */ } + + try { + xText.insertTextContent(xDocTextCursor, xMeta, false); + assure("insertTextContent(): cursor outside allowed?", false); + } catch (com.sun.star.lang.IllegalArgumentException e) { /* ignore */ } + + TextFieldNode field1 = new TextFieldNode( "f1" ); + TextFieldNode field2 = new TextFieldNode( "f2" ); + XTextContent xField1 = inserter.makeTextField(field1.getContent()); + XTextContent xField2 = inserter.makeTextField(field2.getContent()); + + xStart = xText.getStart(); + xText.insertTextContent(xStart, xField1, false); + + TreeNode root = new TreeNode() + .appendChild( new TextNode("12") ) + .appendChild( meta.dup() + .appendChild( field1.dup() ) + .appendChild( new TextNode("45") ) ) + .appendChild( new TextNode("6789") ); + doTest(root, false); + + xText.insertTextContent(xEnd, xField2, false); + + root = new TreeNode() + .appendChild( new TextNode("12") ) + .appendChild( meta.dup() + .appendChild( field1.dup() ) + .appendChild( new TextNode("45") ) + .appendChild( field2.dup() ) ) + .appendChild( new TextNode("6789") ); + doTest(root, false); + + try { + xText.removeTextContent(null); + assure("removeTextContent(): null content allowed?", false); + } catch (RuntimeException e) { /* expected */ } + + xText.removeTextContent(xField1); + + XTextRange xAnchor = xMeta.getAnchor(); + assure("getAnchor(): null", xAnchor != null); + + // evil test case: insert ruby around meta + RubyNode ruby = new RubyNode( mkName("ruby") ); + inserter.insertRange( new Range(2, 6, ruby) ); + + /* prevent caching... + root = new TreeNode() + .appendChild( new TextNode("12") ) + .appendChild( ruby.dup() + .appendChild( meta.dup() + .appendChild( new TextNode("45") ) + .appendChild( field2.dup() ) ) ) + .appendChild( new TextNode("6789") ); + doTest(root, false); + */ + + XEnumerationAccess xEA = (XEnumerationAccess) + UnoRuntime.queryInterface(XEnumerationAccess.class, xMeta); + XEnumeration xEnum = xEA.createEnumeration(); + assure("createEnumeration(): returns null", xEnum != null); + { + assure("hasNext(): first missing", xEnum.hasMoreElements()); + Object xElement = xEnum.nextElement(); + XTextRange xPortion = (XTextRange) + UnoRuntime.queryInterface(XTextRange.class, xElement); + XPropertySet xPropSet = (XPropertySet) + UnoRuntime.queryInterface(XPropertySet.class, xPortion); + String type = (String) xPropSet.getPropertyValue("TextPortionType"); + assure("first: not text", type.equals("Text")); + String txt = xPortion.getString(); + assure("first: text differs: " + txt, "45".equals(txt)); + } + { + assure("hasNext(): second missing", xEnum.hasMoreElements()); + Object xElement = xEnum.nextElement(); + XTextRange xPortion = (XTextRange) + UnoRuntime.queryInterface(XTextRange.class, xElement); + XPropertySet xPropSet = (XPropertySet) + UnoRuntime.queryInterface(XPropertySet.class, xPortion); + String type = (String) xPropSet.getPropertyValue("TextPortionType"); + assure("second: not text", type.equals("TextField")); + } + // no ruby end here!!! + assure("hasNext(): more elements?", !xEnum.hasMoreElements()); + + XComponent xComponent = (XComponent) + UnoRuntime.queryInterface(XComponent.class, xMeta); + xComponent.dispose(); + + try { + XTextCursor xCursor = xText.createTextCursor(); + assure("createTextCursor(): succeeds on disposed object?", + xCursor == null); + } catch (RuntimeException e) { /* expected */ } + } + + /** check that cursor move methods move to positions in the meta, + but do not move to positions outside the meta. */ + public void testMetaXTextCursor() throws Exception + { + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("Text. 12 More text here."); + inserter.insertRange( new Range(0, 0, text) ); + MetaNode met1 = new MetaNode( mkId("id") ); + XTextContent xMeta = inserter.makeMeta(); + + XText xDocText = m_xDoc.getText(); + XTextCursor xDocTextCursor = xDocText.createTextCursor(); + xDocTextCursor.goRight((short)7, false); + xDocTextCursor.goRight((short)2, true); + xDocText.insertTextContent(xDocTextCursor, xMeta, true); + xDocTextCursor.gotoStart(true); + + XMetadatable xMetadatable = (XMetadatable) + UnoRuntime.queryInterface(XMetadatable.class, xMeta); + xMetadatable.setMetadataReference(met1.getXmlId()); + XText xText = (XText) UnoRuntime.queryInterface(XText.class, xMeta); + + XTextRange xStart = xText.getStart(); + assure("getStart(): no start", xStart != null); + XTextRange xEnd = xText.getEnd(); + assure("getEnd(): no end", xEnd != null); + + XTextCursor xTextCursor = xText.createTextCursor(); + assure("createTextCursor(): no cursor", xTextCursor != null); + + // XTextCursor + boolean bSuccess = false; + xTextCursor.gotoStart(false); + xTextCursor.gotoEnd(false); + bSuccess = xTextCursor.goLeft((short)1, false); + assure("goLeft(): failed", bSuccess); + bSuccess = xTextCursor.goLeft((short)1000, false); + assure("goLeft(): succeeded", !bSuccess); + bSuccess = xTextCursor.goRight((short)1, false); + assure("goRight(): failed", bSuccess); + bSuccess = xTextCursor.goRight((short)1000, false); + assure("goRight(): succeeded", !bSuccess); + xTextCursor.gotoRange(xStart, false); + xTextCursor.gotoRange(xEnd, false); + try { + xTextCursor.gotoRange(xDocTextCursor, false); + assure("gotoRange(): succeeded", false); + } catch (RuntimeException e) { /* expected */ } + + // XWordCursor + xText.setString("Two words"); + xTextCursor.gotoStart(false); + XWordCursor xWordCursor = (XWordCursor) + UnoRuntime.queryInterface(XWordCursor.class, xTextCursor); + + bSuccess = xWordCursor.gotoNextWord(true); + assure("gotoNextWord(): failed", bSuccess); + { + String string = xTextCursor.getString(); + assure("gotoNextWord(): wrong string: " + string, + "Two ".equals(string)); + } + bSuccess = xWordCursor.gotoNextWord(false); + assure("gotoNextWord(): succeeded", !bSuccess); + xTextCursor.collapseToEnd(); + bSuccess = xWordCursor.gotoPreviousWord(true); + assure("gotoPreviousWord(): failed", bSuccess); + { + String string = xTextCursor.getString(); + assure("gotoPreviousWord(): wrong string: " + string, + "words".equals(string)); + } + bSuccess = xWordCursor.gotoPreviousWord(false); + assure("gotoPreviousWord(): succeeded", !bSuccess); + bSuccess = xWordCursor.gotoEndOfWord(true); + assure("gotoEndOfWord(): failed", bSuccess); + { + String string = xTextCursor.getString(); + assure("gotoEndOfWord(): wrong string: " + string, + "Two".equals(string)); + } + xTextCursor.gotoEnd(false); + bSuccess = xWordCursor.gotoStartOfWord(true); + assure("gotoStartOfWord(): failed", bSuccess); + { + String string = xTextCursor.getString(); + assure("gotoStartOfWord(): wrong string: " + string, + "words".equals(string)); + } + xText.setString(""); + bSuccess = xWordCursor.gotoEndOfWord(false); + assure("gotoEndOfWord(): succeeded", !bSuccess); + bSuccess = xWordCursor.gotoStartOfWord(false); + assure("gotoStartOfWord(): succeeded", !bSuccess); + + // XSentenceCursor + xText.setString("This is a sentence. Another sentence."); + xTextCursor.gotoStart(false); + XSentenceCursor xSentenceCursor = (XSentenceCursor) + UnoRuntime.queryInterface(XSentenceCursor.class, xTextCursor); + + bSuccess = xSentenceCursor.gotoNextSentence(true); + assure("gotoNextSentence(): failed", bSuccess); + { + String string = xTextCursor.getString(); + assure("gotoNextSentence(): wrong string: " + string, + "This is a sentence. ".equals(string)); + } + bSuccess = xSentenceCursor.gotoNextSentence(false); + assure("gotoNextSentence(): succeeded", !bSuccess); + // FIXME: + // the sentence cursor seems to work differently than the word cursor + xText.setString("This is a sentence. Another sentence. Sentence 3."); + xTextCursor.gotoEnd(false); + bSuccess = xSentenceCursor.gotoPreviousSentence(true); + assure("gotoPreviousSentence(): failed", bSuccess); + { + String string = xTextCursor.getString(); + assure("gotoPreviousSentence(): wrong string: " + string, + "Another sentence. Sentence 3.".equals(string)); + } + bSuccess = xSentenceCursor.gotoPreviousSentence(false); + assure("gotoPreviousSentence(): succeeded", !bSuccess); + bSuccess = xSentenceCursor.gotoEndOfSentence(true); + assure("gotoEndOfSentence(): failed", bSuccess); + { + String string = xTextCursor.getString(); + assure("gotoEndOfSentence(): wrong string: " + string, + "This is a sentence.".equals(string)); + } + xTextCursor.gotoEnd(false); + bSuccess = xSentenceCursor.gotoStartOfSentence(true); + assure("gotoStartOfSentence(): failed", bSuccess); + { + String string = xTextCursor.getString(); + assure("gotoStartOfSentence(): wrong string: " + string, + "Sentence 3.".equals(string)); + } + xText.setString(""); + bSuccess = xSentenceCursor.gotoEndOfSentence(false); + assure("gotoEndOfSentence(): succeeded", !bSuccess); + bSuccess = xSentenceCursor.gotoStartOfSentence(false); + assure("gotoStartOfSentence(): succeeded", !bSuccess); + + XParagraphCursor xParagraphCursor = (XParagraphCursor) + UnoRuntime.queryInterface(XParagraphCursor.class, xTextCursor); + + // XParagraphCursor (does not make sense) + bSuccess = xParagraphCursor.gotoNextParagraph(false); + assure("gotoNextParagraph(): succeeded", !bSuccess); + bSuccess = xParagraphCursor.gotoPreviousParagraph(false); + assure("gotoPreviousParagraph(): succeeded", !bSuccess); + bSuccess = xParagraphCursor.gotoStartOfParagraph(false); + assure("gotoStartOfParagraph(): succeeded", !bSuccess); + bSuccess = xParagraphCursor.gotoEndOfParagraph(false); + assure("gotoEndOfParagraph(): succeeded", !bSuccess); + } + + + abstract class AttachHelper + { + abstract boolean isAttribute(); + abstract TreeNode mkTreeNode(); + abstract XTextContent mkTextContent(Inserter inserter, TreeNode node) + throws Exception; + void postInserted(TreeNode node, XTextContent xContent) + throws Exception { } + } + + public void testMetaXTextAttachToxMark() throws Exception + { + doMetaXTextAttach( new AttachHelper() + { + boolean isAttribute() { return true; } + TreeNode mkTreeNode() { + return new DocumentIndexMarkNode( mkName("toxmark") ); + } + XTextContent mkTextContent(Inserter inserter, TreeNode node) + throws Exception { + return inserter.makeDocumentIndexMark( + ((DocumentIndexMarkNode)node).getName()); + } + }); + } + + public void testMetaXTextAttachRefMark() throws Exception + { + doMetaXTextAttach( new AttachHelper() + { + boolean isAttribute() { return true; } + TreeNode mkTreeNode() { + return new ReferenceMarkNode( mkName("refmark") ); + } + XTextContent mkTextContent(Inserter inserter, TreeNode node) + throws Exception { + return inserter.makeReferenceMark( + ((ReferenceMarkNode)node).getName()); + } + }); + } + + public void testMetaXTextAttachTextField() throws Exception + { + doMetaXTextAttach( new AttachHelper() + { + boolean isAttribute() { return false; } + TreeNode mkTreeNode() { + return new TextFieldNode( mkName("field") ); + } + XTextContent mkTextContent(Inserter inserter, TreeNode node) + throws Exception { + return inserter.makeTextField( + ((TextFieldNode)node).getContent()); + } + }); + } + + public void testMetaXTextAttachFootnote() throws Exception + { + doMetaXTextAttach( new AttachHelper() + { + boolean isAttribute() { return false; } + TreeNode mkTreeNode() { + return new FootnoteNode( mkName("ftn") ); + } + XTextContent mkTextContent(Inserter inserter, TreeNode node) + throws Exception { + return inserter.makeFootnote( + ((FootnoteNode)node).getLabel()); + } + }); + } + + public void testMetaXTextAttachMeta() throws Exception + { + doMetaXTextAttach( new AttachHelper() + { + boolean isAttribute() { return true; } + TreeNode mkTreeNode() { + return new MetaNode( mkId("id") ); + } + XTextContent mkTextContent(Inserter inserter, TreeNode node) + throws Exception { + return inserter.makeMeta(); + } + void postInserted(TreeNode node, XTextContent xContent) + throws Exception { + XMetadatable xMetadatable = (XMetadatable) + UnoRuntime.queryInterface(XMetadatable.class, xContent); + xMetadatable.setMetadataReference( + ((MetaNode)node).getXmlId()); + } + }); + } + + void doMetaXTextAttach(AttachHelper helper) throws Exception + { + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("12AB6789"); + inserter.insertRange( new Range(0, 0, text) ); + MetaNode met1 = new MetaNode( mkId("id") ); + XTextContent xMeta = inserter.makeMeta(); + + XText xDocText = m_xDoc.getText(); + XTextCursor xDocTextCursor = xDocText.createTextCursor(); + xDocTextCursor.goRight((short)3, false); + xDocTextCursor.goRight((short)2, true); + xDocText.insertTextContent(xDocTextCursor, xMeta, true); + + XMetadatable xMetadatable = (XMetadatable) + UnoRuntime.queryInterface(XMetadatable.class, xMeta); + xMetadatable.setMetadataReference(met1.getXmlId()); + XText xText = (XText) UnoRuntime.queryInterface(XText.class, xMeta); + XTextRange xStart = null; + XTextRange xEnd = null; + + { + xStart = xText.getStart(); + xEnd = xText.getEnd(); + + TreeNode nod1 = helper.mkTreeNode(); + TreeNode nod2 = helper.mkTreeNode(); + XTextContent xContent1 = helper.mkTextContent(inserter, nod1); + XTextContent xContent2 = helper.mkTextContent(inserter, nod2); + + // insertTextContent with meta getStart()/getEnd() + xText.insertTextContent(xStart, xContent1, false); + xText.insertTextContent(xEnd , xContent2, false); + + helper.postInserted(nod1, xContent1); + helper.postInserted(nod2, xContent2); + + TreeNode root = new TreeNode() + .appendChild( new TextNode("12") ) + .appendChild( met1.dup() + .appendChild( nod1.dup() ) + .appendChild( new TextNode("AB") ) + .appendChild( nod2.dup() ) ) + .appendChild( new TextNode("6789") ); + doTest(root, false); + } + { + xText.setString("AB"); + xStart = xText.getStart(); + xEnd = xText.getEnd(); + + TreeNode nod1 = helper.mkTreeNode(); + TreeNode nod2 = helper.mkTreeNode(); + XTextContent xContent1 = helper.mkTextContent(inserter, nod1); + XTextContent xContent2 = helper.mkTextContent(inserter, nod2); + + XTextCursor xTextCursor = xText.createTextCursor(); + xTextCursor.gotoStart(false); + + // insertTextContent with meta cursor + xText.insertTextContent(xTextCursor, xContent1, false); + xTextCursor.gotoEnd(false); + xText.insertTextContent(xTextCursor, xContent2, false); + + helper.postInserted(nod1, xContent1); + helper.postInserted(nod2, xContent2); + + TreeNode root = new TreeNode() + .appendChild( new TextNode("12") ) + .appendChild( met1.dup() + .appendChild( nod1.dup() ) + .appendChild( new TextNode("AB") ) + .appendChild( nod2.dup() ) ) + .appendChild( new TextNode("6789") ); + doTest(root, false); + } + if (!helper.isAttribute()) + { +// xText.setString("AB"); + xStart = xText.getStart(); + xEnd = xText.getEnd(); + + TreeNode nod1 = helper.mkTreeNode(); + TreeNode nod2 = helper.mkTreeNode(); + XTextContent xContent1 = helper.mkTextContent(inserter, nod1); + XTextContent xContent2 = helper.mkTextContent(inserter, nod2); + + XTextCursor xTextCursor = xText.createTextCursor(); + xTextCursor.gotoStart(false); + xTextCursor.goRight((short)1, true); + + // insertTextContent with meta cursor and absorb + xText.insertTextContent(xTextCursor, xContent1, true); + xTextCursor.gotoEnd(false); + xTextCursor.goLeft((short)1, true); + xText.insertTextContent(xTextCursor, xContent2, true); + + helper.postInserted(nod1, xContent1); + helper.postInserted(nod2, xContent2); + + TreeNode root = new TreeNode() + .appendChild( new TextNode("12") ) + .appendChild( met1.dup() + .appendChild( nod1.dup() ) + .appendChild( new TextNode("AB") ) + .appendChild( nod2.dup() ) ) + .appendChild( new TextNode("6789") ); + doTest(root, false); + } + { + xText.setString("AB"); + xStart = xText.getStart(); + xEnd = xText.getEnd(); + + TreeNode nod1 = helper.mkTreeNode(); + TreeNode nod2 = helper.mkTreeNode(); + XTextContent xContent1 = helper.mkTextContent(inserter, nod1); + XTextContent xContent2 = helper.mkTextContent(inserter, nod2); + + xDocTextCursor.gotoRange(xStart, false); + + // insertTextContent with document cursor + xText.insertTextContent(xDocTextCursor, xContent1, false); + xDocTextCursor.gotoRange(xEnd, false); + xText.insertTextContent(xDocTextCursor, xContent2, false); + + helper.postInserted(nod1, xContent1); + helper.postInserted(nod2, xContent2); + + TreeNode root = new TreeNode() + .appendChild( new TextNode("12") ) + .appendChild( met1.dup() + .appendChild( nod1.dup() ) + .appendChild( new TextNode("AB") ) + .appendChild( nod2.dup() ) ) + .appendChild( new TextNode("6789") ); + doTest(root, false); + } + if (!helper.isAttribute()) + { +// xText.setString("AB"); + xStart = xText.getStart(); + xEnd = xText.getEnd(); + + TreeNode nod1 = helper.mkTreeNode(); + TreeNode nod2 = helper.mkTreeNode(); + XTextContent xContent1 = helper.mkTextContent(inserter, nod1); + XTextContent xContent2 = helper.mkTextContent(inserter, nod2); + + xDocTextCursor.gotoRange(xStart, false); + xDocTextCursor.goRight((short)1, true); + + // insertTextContent with document cursor and absorb + xText.insertTextContent(xDocTextCursor, xContent1, true); + xDocTextCursor.gotoRange(xEnd, false); + xDocTextCursor.goLeft((short)1, true); + xText.insertTextContent(xDocTextCursor, xContent2, true); + + helper.postInserted(nod1, xContent1); + helper.postInserted(nod2, xContent2); + + TreeNode root = new TreeNode() + .appendChild( new TextNode("12") ) + .appendChild( met1.dup() + .appendChild( nod1.dup() ) + .appendChild( new TextNode("AB") ) + .appendChild( nod2.dup() ) ) + .appendChild( new TextNode("6789") ); + doTest(root, false); + } + { + xText.setString("AB"); + xStart = xText.getStart(); + xEnd = xText.getEnd(); + + TreeNode nod1 = helper.mkTreeNode(); + TreeNode nod2 = helper.mkTreeNode(); + XTextContent xContent1 = helper.mkTextContent(inserter, nod1); + XTextContent xContent2 = helper.mkTextContent(inserter, nod2); + + // attach to range from meta getStart()/getEnd() + xContent1.attach(xStart); + xContent2.attach(xEnd); + + helper.postInserted(nod1, xContent1); + helper.postInserted(nod2, xContent2); + + TreeNode root = new TreeNode() + .appendChild( new TextNode("12") ) + .appendChild( met1.dup() + .appendChild( nod1.dup() ) + .appendChild( new TextNode("AB") ) + .appendChild( nod2.dup() ) ) + .appendChild( new TextNode("6789") ); + doTest(root, false); + } + { + xText.setString("AB"); + xStart = xText.getStart(); + xEnd = xText.getEnd(); + + TreeNode nod1 = helper.mkTreeNode(); + TreeNode nod2 = helper.mkTreeNode(); + XTextContent xContent1 = helper.mkTextContent(inserter, nod1); + XTextContent xContent2 = helper.mkTextContent(inserter, nod2); + + XTextCursor xTextCursor = xText.createTextCursor(); + xTextCursor.gotoStart(false); + + // attach to cursor from meta XText + xContent1.attach(xTextCursor); + xTextCursor.gotoEnd(false); + xContent2.attach(xTextCursor); + + helper.postInserted(nod1, xContent1); + helper.postInserted(nod2, xContent2); + + TreeNode root = new TreeNode() + .appendChild( new TextNode("12") ) + .appendChild( met1.dup() + .appendChild( nod1.dup() ) + .appendChild( new TextNode("AB") ) + .appendChild( nod2.dup() ) ) + .appendChild( new TextNode("6789") ); + doTest(root, false); + } + } + + public void testMetaFieldXTextField() throws Exception + { + com.sun.star.rdf.XRepositorySupplier xModel = + (com.sun.star.rdf.XRepositorySupplier) UnoRuntime.queryInterface( + com.sun.star.rdf.XRepositorySupplier.class, m_xDoc); + com.sun.star.rdf.XRepository xRepo = xModel.getRDFRepository(); + // for testing just add it to the first graph + com.sun.star.rdf.XURI[] Graphs = xRepo.getGraphNames(); + com.sun.star.rdf.XNamedGraph xGraph = xRepo.getGraph(Graphs[0]); + com.sun.star.rdf.XURI xOdfPrefix = + com.sun.star.rdf.URI.createKnown(m_xContext, + com.sun.star.rdf.URIs.ODF_PREFIX); + com.sun.star.rdf.XURI xOdfSuffix = + com.sun.star.rdf.URI.createKnown(m_xContext, + com.sun.star.rdf.URIs.ODF_SUFFIX); + com.sun.star.rdf.XNode xPrefix = + com.sun.star.rdf.Literal.create(m_xContext, "foo"); + com.sun.star.rdf.XNode xSuffix = + com.sun.star.rdf.Literal.create(m_xContext, "bar"); + + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("abc"); + inserter.insertRange( new Range(0, 0, text) ); + XText xDocText = m_xDoc.getText(); + XTextCursor xDocTextCursor = xDocText.createTextCursor(); + xDocTextCursor.goRight((short)1, false); + xDocTextCursor.goRight((short)3, true); + + XTextField xMetaField = inserter.makeMetaField(); + + xDocText.insertTextContent(xDocTextCursor, xMetaField, true); + + XMetadatable xMetadatable = (XMetadatable) + UnoRuntime.queryInterface(XMetadatable.class, xMetaField); + xMetadatable.ensureMetadataReference(); + + xGraph.addStatement(xMetadatable, xOdfPrefix, xPrefix); + xGraph.addStatement(xMetadatable, xOdfSuffix, xSuffix); + assure("getPresentation(): wrong", + "fooabcbar".equals(xMetaField.getPresentation(false))); + inserter.insertRange( new Range(0, 0, text) ); + } + + public void testMetaFieldXPropertySet() throws Exception + { + RangeInserter inserter = new RangeInserter(m_xDoc); + TreeNode text = new TextNode("123"); + inserter.insertRange( new Range(0, 0, text) ); + XText xDocText = m_xDoc.getText(); + XTextCursor xDocTextCursor = xDocText.createTextCursor(); + xDocTextCursor.goRight((short)1, false); + xDocTextCursor.goRight((short)3, true); + + XTextField xMetaField = inserter.makeMetaField(); + + xDocText.insertTextContent(xDocTextCursor, xMetaField, true); + + XPropertySet xPropertySet = (XPropertySet) + UnoRuntime.queryInterface(XPropertySet.class, xMetaField); + assure("PropertySet: not supported?", xPropertySet != null); + XPropertySetInfo xPropertySetInfo = xPropertySet.getPropertySetInfo(); + assure("hasPropertyByName(\"NumberFormat\"):", + xPropertySetInfo.hasPropertyByName("NumberFormat")); + assure("hasPropertyByName(\"IsFixedLanguage\"):", + xPropertySetInfo.hasPropertyByName("IsFixedLanguage")); + + int def = (Integer) xPropertySet.getPropertyValue("NumberFormat"); + log.println("NumberFormat: default is " + def); + short INT = com.sun.star.i18n.NumberFormatIndex.NUMBER_INT; + xPropertySet.setPropertyValue("NumberFormat", INT); + xPropertySet.setPropertyValue("IsFixedLanguage", true); + int format = (Integer) xPropertySet.getPropertyValue("NumberFormat"); + assure("NumberFormat: failed", format == INT); + boolean isFixed = (Boolean) + xPropertySet.getPropertyValue("IsFixedLanguage"); + assure("IsFixedLanguage: failed", isFixed); + } + + public void testLoadStore() throws Exception + { + XComponent xComp = null; + String filename = "TESTMETA.odt"; + String file; + try { + file = util.utils.getFullTestURL(filename); + xComp = doLoad(file); + if (xComp != null) + { + file = m_TmpDir + filename; + doStore(xComp, file); + close(xComp); + xComp = doLoad(file); + } + } finally { + close(xComp); + } + } + + private void doStore(XComponent xComp, String file) throws Exception + { + log.println("Storing test document..."); + + XStorable xStor = (XStorable) UnoRuntime.queryInterface( + XStorable.class, xComp); + + xStor.storeToURL(file, new PropertyValue[0]); + + log.println("...done"); + } + + public XComponent doLoad(String file) throws Exception + { + XComponent xComp = null; + + log.println("Loading test document..."); + + PropertyValue[] loadProps = new PropertyValue[1]; + loadProps[0] = new PropertyValue(); + loadProps[0].Name = "Hidden"; + loadProps[0].Value = new Boolean(true); + + xComp = util.DesktopTools.loadDoc(m_xMSF, file, loadProps); +// xComp = util.DesktopTools.getCLoader(m_xMSF).loadComponentFromURL(file, "_blank", 0, loadProps); + + + XTextDocument xTextDoc = (XTextDocument) + UnoRuntime.queryInterface(XTextDocument.class, xComp); + + XText xText = xTextDoc.getText(); + + log.println("...done"); + + log.println("Checking meta(-field)s in loaded test document..."); + + TreeNode root = new TreeNode() + .appendChild( new RubyNode("ruby1") + .appendChild( new TextNode("1") ) ) + .appendChild( new MetaNode(mkId_("id1")) + .appendChild( new TextNode("2") ) ) + .appendChild( new MetaFieldNode(mkId_("id2")) + .appendChild( new TextNode("3") ) ) + .appendChild( new RubyNode("ruby2") + .appendChild( new MetaNode(mkId_("id3")) + .appendChild( new TextNode("4") ) ) ) + .appendChild( new RubyNode("ruby3") + .appendChild( new MetaFieldNode(mkId_("id4")) + .appendChild( new TextNode("5") ) ) ) + .appendChild( new MetaNode(mkId_("id5")) + .appendChild( new RubyNode("ruby4") + .appendChild( new TextNode("6") ) ) ) + .appendChild( new MetaFieldNode(mkId_("id6")) + .appendChild( new RubyNode("ruby5") + .appendChild( new TextNode("7") ) ) ) + .appendChild( new MetaNode(mkId_("id7")) + .appendChild( new MetaNode(mkId_("id8")) + .appendChild( new TextNode("8") ) ) ) + .appendChild( new MetaNode(mkId_("id9")) + .appendChild( new MetaFieldNode(mkId_("id10")) + .appendChild( new TextNode("9") ) ) ) + .appendChild( new MetaFieldNode(mkId_("id11")) + .appendChild( new MetaNode(mkId_("id12")) + .appendChild( new TextNode("10") ) ) ) + .appendChild( new MetaFieldNode(mkId_("id13")) + .appendChild( new MetaFieldNode(mkId_("id14")) + .appendChild( new TextNode("11") ) ) ) + .appendChild( new MetaNode(mkId_("id15")) + .appendChild( new RubyNode("ruby6") + .appendChild( new MetaFieldNode(mkId_("id16")) + .appendChild( new TextNode("12") ) ) ) ) + .appendChild( new MetaNode(mkId_("")) { + public boolean equals(Object other) { + return (other instanceof MetaNode); + } } + .appendChild( new TextNode("13") ) ) + .appendChild( new TextNode(" X X ") ); + doTest(xTextDoc, root, false); + + log.println("...done"); + + return xComp; + } + + static void close(XComponent i_comp) + { + try { + XCloseable xClos = (XCloseable) UnoRuntime.queryInterface( + XCloseable.class, i_comp); + if (xClos != null) xClos.close(true); + } catch (Exception e) { + } + } + + private void doTest(TreeNode intree) throws Exception + { + doTest(m_xDoc, intree, true); + } + + private void doTest(TreeNode intree, boolean insert) throws Exception + { + doTest(m_xDoc, intree, insert); + } + + private void doTest(XTextDocument xDoc, TreeNode intree, + boolean insert) throws Exception + { + dumpTree(intree, "I: "); + + if (insert) { + new TreeInserter(xDoc).insertTree(intree); + } + +//Thread.sleep(10000); + + XText xText = xDoc.getText(); + XEnumerationAccess xTextEA = (XEnumerationAccess) + UnoRuntime.queryInterface(XEnumerationAccess.class, xText); + XEnumeration xTextEnum = xTextEA.createEnumeration(); + // skip to right paragraph + xTextEnum.nextElement(); // skip first -- always empty! + Object xElement = xTextEnum.nextElement(); // second contains test case + XEnumerationAccess xEA = (XEnumerationAccess) + UnoRuntime.queryInterface(XEnumerationAccess.class, xElement); + XEnumeration xEnum = xEA.createEnumeration(); + TreeNode outtree = new EnumConverter(this).convert(xEnum); + + dumpTree(outtree, "O: "); + + boolean success = new FuzzyTester(log).doTest(intree, outtree); + assure("test failed", success); + } + + private void dumpTree(TreeNode tree) { dumpTree(tree, "> "); } + + private void dumpTree(TreeNode tree, String prefix) + { + log.println(prefix + tree.toString()); + TreeNodeEnum children = tree.createEnumeration(); + while (children.hasNext()) { + TreeNode node = children.next(); + dumpTree(node, prefix + " "); + } + } + + private String mkName(String prefix) + { + return prefix + String.valueOf(m_Count++); + } + + private StringPair mkId(String prefix) + { + return new StringPair("content.xml", mkName(prefix)); + } + + private StringPair mkId_(String id) + { + return new StringPair("content.xml", id); + } + + public void assure(String str, boolean cond) { super.assure(str, cond); } +} + diff --git a/sw/qa/complex/writer/testdocuments/TESTMETA.odt b/sw/qa/complex/writer/testdocuments/TESTMETA.odt new file mode 100755 index 000000000000..004af82e5ddf Binary files /dev/null and b/sw/qa/complex/writer/testdocuments/TESTMETA.odt differ diff --git a/sw/source/core/inc/unometa.hxx b/sw/source/core/inc/unometa.hxx new file mode 100755 index 000000000000..1dc1985f7dfe --- /dev/null +++ b/sw/source/core/inc/unometa.hxx @@ -0,0 +1,345 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: unometa.hxx,v $ + * $Revision: 1.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SW_UNOMETA_HXX +#define SW_UNOMETA_HXX + +#include "calbck.hxx" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + + +typedef ::std::deque< + ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextRange > > + TextRangeList_t; + +class SwXTextRange; +class SwPaM; +class SwTxtMeta; +namespace sw { + class Meta; + class MetaField; +} + +typedef +::cppu::ImplInheritanceHelper5 +< ::sfx2::MetadatableMixin +, ::com::sun::star::lang::XUnoTunnel +, ::com::sun::star::lang::XServiceInfo +, ::com::sun::star::text::XTextContent +, ::com::sun::star::text::XText +, ::com::sun::star::container::XEnumerationAccess +> SwXMetaBaseClass; + +class SwXMeta + : public SwXMetaBaseClass + , public SwClient + , private ::boost::noncopyable +{ +private: + struct Impl; + ::std::auto_ptr m_pImpl; + +protected: + virtual ~SwXMeta(); + +public: + SwXMeta(SwDoc *const pDoc, + ::com::sun::star::uno::Reference< ::com::sun::star::text::XText> const& + xParentText, + TextRangeList_t * const pPortions, SwTxtMeta * const pHint); + SwXMeta(SwDoc *const pDoc); + + TYPEINFO(); + + static const ::com::sun::star::uno::Sequence< sal_Int8 > & getUnoTunnelId(); + + // XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( + const ::com::sun::star::uno::Sequence< sal_Int8 >& Identifier ) + throw (::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( + const ::rtl::OUString& rServiceName) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames() + throw (::com::sun::star::uno::RuntimeException); + + // XComponent + virtual void SAL_CALL dispose() + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addEventListener( + const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XEventListener > & xListener) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeEventListener( + const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XEventListener > & xListener) + throw (::com::sun::star::uno::RuntimeException); + + // XTextContent + virtual void SAL_CALL attach( + const ::com::sun::star::uno::Reference< + ::com::sun::star::text::XTextRange > & xTextRange) + throw (::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::text::XTextRange > SAL_CALL getAnchor() + throw (::com::sun::star::uno::RuntimeException); + + // XTextRange + virtual ::com::sun::star::uno::Reference< ::com::sun::star::text::XText > + SAL_CALL getText() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::text::XTextRange > SAL_CALL getStart() + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::text::XTextRange > SAL_CALL getEnd() + throw (::com::sun::star::uno::RuntimeException); + virtual rtl::OUString SAL_CALL getString() + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setString(const rtl::OUString& rString) + throw (::com::sun::star::uno::RuntimeException); + + // XSimpleText + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::text::XTextCursor > SAL_CALL + createTextCursor() + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::text::XTextCursor > SAL_CALL + createTextCursorByRange( + const ::com::sun::star::uno::Reference< + ::com::sun::star::text::XTextRange > & xTextPosition) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL insertString( + const ::com::sun::star::uno::Reference< + ::com::sun::star::text::XTextRange > & xRange, + const rtl::OUString& aString, sal_Bool bAbsorb) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL insertControlCharacter( + const ::com::sun::star::uno::Reference< + ::com::sun::star::text::XTextRange > & xRange, + sal_Int16 nControlCharacter, sal_Bool bAbsorb) + throw (::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::uno::RuntimeException); + + // XText + virtual void SAL_CALL insertTextContent( + const ::com::sun::star::uno::Reference< + ::com::sun::star::text::XTextRange > & xRange, + const ::com::sun::star::uno::Reference< + ::com::sun::star::text::XTextContent > & xContent, + sal_Bool bAbsorb) + throw (::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeTextContent( + const ::com::sun::star::uno::Reference< + ::com::sun::star::text::XTextContent > & xContent) + throw (::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException); + + // XElementAccess + virtual ::com::sun::star::uno::Type SAL_CALL getElementType() + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasElements() + throw (::com::sun::star::uno::RuntimeException); + + // XEnumerationAccess + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::container::XEnumeration > SAL_CALL + createEnumeration() + throw (::com::sun::star::uno::RuntimeException); + + // MetadatableMixin + virtual ::sfx2::Metadatable * GetCoreObject(); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > + GetModel(); + + // SwClient + virtual void Modify( SfxPoolItem *pOld, SfxPoolItem *pNew ); + + /// init params with position of the attribute content (w/out CH_TXTATR) + bool SetContentRange( + SwTxtNode *& rpNode, xub_StrLen & rStart, xub_StrLen & rEnd) const; + ::com::sun::star::uno::Reference< ::com::sun::star::text::XText > + GetParentText() const; + + bool CheckForOwnMemberMeta(const SwXTextRange* const pRange, + const SwPaM* const pPam, bool bAbsorb) + throw (::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::uno::RuntimeException); + +protected: + virtual void SAL_CALL AttachImpl( + const ::com::sun::star::uno::Reference< + ::com::sun::star::text::XTextRange > & xTextRange, + const USHORT nWhich) + throw ( ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::uno::RuntimeException ); + +private: + inline const ::sw::Meta * GetMeta() const; + +}; + + +typedef +::cppu::ImplInheritanceHelper2 +< SwXMeta +, ::com::sun::star::beans::XPropertySet +, ::com::sun::star::text::XTextField +> SwXMetaFieldBaseClass; + +class SwXMetaField + : public SwXMetaFieldBaseClass +{ +private: + virtual ~SwXMetaField(); + +private: + inline const ::sw::MetaField * GetMetaField() const; + +public: + SwXMetaField(SwDoc *const pDoc, + ::com::sun::star::uno::Reference< ::com::sun::star::text::XText> const& + xParentText, + TextRangeList_t * const pPortions, SwTxtMeta * const pHint); + SwXMetaField(SwDoc *const pDoc); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( + const ::rtl::OUString& ServiceName) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames( ) + throw (::com::sun::star::uno::RuntimeException); + + // XComponent + virtual void SAL_CALL dispose() + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addEventListener( + const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XEventListener > & xListener) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeEventListener( + const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XEventListener > & xListener) + throw (::com::sun::star::uno::RuntimeException); + + // XTextContent + virtual void SAL_CALL attach( + const ::com::sun::star::uno::Reference< + ::com::sun::star::text::XTextRange > & xTextRange) + throw ( ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::text::XTextRange > SAL_CALL getAnchor() + throw (::com::sun::star::uno::RuntimeException); + + // XPropertySet + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setPropertyValue( + const ::rtl::OUString& rPropertyName, + const ::com::sun::star::uno::Any& rValue) + throw (::com::sun::star::beans::UnknownPropertyException, + ::com::sun::star::beans::PropertyVetoException, + ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL + getPropertyValue(const ::rtl::OUString& rPropertyName) + throw (::com::sun::star::beans::UnknownPropertyException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addPropertyChangeListener( + const ::rtl::OUString& rPropertyName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertyChangeListener >& xListener) + throw (::com::sun::star::beans::UnknownPropertyException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removePropertyChangeListener( + const ::rtl::OUString& rPropertyName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XPropertyChangeListener >& xListener) + throw (::com::sun::star::beans::UnknownPropertyException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addVetoableChangeListener( + const ::rtl::OUString& rPropertyName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XVetoableChangeListener >& xListener) + throw (::com::sun::star::beans::UnknownPropertyException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeVetoableChangeListener( + const ::rtl::OUString& rPropertyName, + const ::com::sun::star::uno::Reference< + ::com::sun::star::beans::XVetoableChangeListener >& xListener) + throw (::com::sun::star::beans::UnknownPropertyException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + + // XTextField + virtual rtl::OUString SAL_CALL getPresentation(sal_Bool bShowCommand) + throw (::com::sun::star::uno::RuntimeException); + +}; + +/// get prefix/suffix from the RDF repository. @throws RuntimeException +void getPrefixAndSuffix( + const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel>& xModel, + const ::com::sun::star::uno::Reference< + ::com::sun::star::rdf::XMetadatable>& xMetaField, + ::rtl::OUString *const o_pPrefix, ::rtl::OUString *const o_pSuffix); + +#endif // SW_UNOMETA_HXX + diff --git a/sw/source/core/txtnode/fmtatr1.cxx b/sw/source/core/txtnode/fmtatr1.cxx deleted file mode 100644 index bcbe7a2df680..000000000000 --- a/sw/source/core/txtnode/fmtatr1.cxx +++ /dev/null @@ -1,97 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: fmtatr1.cxx,v $ - * $Revision: 1.6 $ - * - * 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 - * - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_sw.hxx" - - - -#include -#include -#include - - -/************************************************************************* -|* -|* class SwFmtHardBlank -|* -|* Beschreibung Dokument 1.20 -|* Ersterstellung JP 23.11.90 -|* Letzte Aenderung JP 20.02.91 -|* -*************************************************************************/ - -SwFmtHardBlank::SwFmtHardBlank( sal_Unicode cCh, BOOL ) - : SfxPoolItem( RES_TXTATR_HARDBLANK ), - cChar( cCh ) -{ -// ASSERT( !bCheck || (' ' != cCh && '-' != cCh), -// "Invalid character for the HardBlank attribute - " -// "must be a normal unicode character" ); -} - -int SwFmtHardBlank::operator==( const SfxPoolItem& rAttr ) const -{ - ASSERT( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" ); - return cChar == ((SwFmtHardBlank&)rAttr).GetChar(); -} - -SfxPoolItem* SwFmtHardBlank::Clone( SfxItemPool* ) const -{ - return new SwFmtHardBlank( *this ); -} - -/************************************************************************* -|* -|* class SwFmtSoftHyph -|* -|* Beschreibung Dokument 1.20 -|* Ersterstellung JP 23.11.90 -|* Letzte Aenderung JP 20.02.91 -|* -*************************************************************************/ - -SwFmtSoftHyph::SwFmtSoftHyph() - : SfxPoolItem( RES_TXTATR_SOFTHYPH ) -{ -} - -int SwFmtSoftHyph::operator==( const SfxPoolItem& ) const -{ -// ASSERT( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" ); - return TRUE; -} - -SfxPoolItem* SwFmtSoftHyph::Clone( SfxItemPool* ) const -{ - return new SwFmtSoftHyph( *this ); -} - - -- cgit v1.2.3