LibreOffice Module sw (master)  1
swdocxreader.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include "swdocxreader.hxx"
21 
22 #include <com/sun/star/document/XFilter.hpp>
23 #include <com/sun/star/document/XImporter.hpp>
24 #include <com/sun/star/xml/dom/XDocument.hpp>
25 #include <com/sun/star/xml/dom/XElement.hpp>
26 #include <com/sun/star/xml/dom/XNode.hpp>
27 #include <com/sun/star/xml/dom/XNodeList.hpp>
30 #include <doc.hxx>
31 #include <docsh.hxx>
33 #include <ndtxt.hxx>
34 #include <poolfmt.hxx>
35 #include <svl/urihelper.hxx>
36 #include <swerror.h>
37 #include <tools/ref.hxx>
38 #include <unotxdoc.hxx>
39 #include <unotools/streamwrap.hxx>
40 #include <unotextrange.hxx>
41 #include <sfx2/docfile.hxx>
42 #include <sal/log.hxx>
43 #include <tools/diagnose_ex.h>
44 
45 #define AUTOTEXT_GALLERY "autoTxt"
46 
47 using namespace css;
48 
49 extern "C" SAL_DLLPUBLIC_EXPORT Reader* ImportDOCX()
50 {
51  return new SwDOCXReader;
52 }
53 
54 ErrCode SwDOCXReader::Read(SwDoc& rDoc, const OUString& /* rBaseURL */, SwPaM& rPam, const OUString& /* FileName */ )
55 {
56  if (!m_pMedium->GetInStream())
57  return ERR_SWG_READ_ERROR;
58 
59  // We want to work in an empty paragraph.
60  std::shared_ptr<SwNodeIndex> pSttNdIdx(new SwNodeIndex(rDoc.GetNodes()));
61  const SwPosition* pPos = rPam.GetPoint();
62  rDoc.getIDocumentContentOperations().SplitNode(*pPos, false);
64 
65  uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(comphelper::getProcessServiceFactory());
66  uno::Reference<uno::XInterface> xInterface(xMultiServiceFactory->createInstance("com.sun.star.comp.Writer.WriterFilter"), uno::UNO_SET_THROW);
67 
68  SwDocShell* pDocShell(rDoc.GetDocShell());
69  uno::Reference<lang::XComponent> xDstDoc(pDocShell->GetModel(), uno::UNO_QUERY_THROW);
70  uno::Reference<document::XImporter> xImporter(xInterface, uno::UNO_QUERY_THROW);
71  xImporter->setTargetDocument(xDstDoc);
72 
73  const uno::Reference<text::XTextRange> xInsertTextRange = SwXTextRange::CreateXTextRange(rDoc, *rPam.GetPoint(), nullptr);
74  uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(*m_pMedium->GetInStream()));
75 
76  //SetLoading hack because the document properties will be re-initted
77  //by the xml filter and during the init, while it's considered uninitialized,
78  //setting a property will inform the document it's modified, which attempts
79  //to update the properties, which throws cause the properties are uninitialized
80  pDocShell->SetLoading(SfxLoadedFlags::NONE);
81 
82  uno::Sequence<beans::PropertyValue> aDescriptor(comphelper::InitPropertySequence(
83  {
84  { "InputStream", uno::Any(xStream) },
85  { "InsertMode", uno::Any(true) },
86  { "TextInsertModeRange", uno::Any(xInsertTextRange) }
87  }));
88 
89  ErrCode ret = ERRCODE_NONE;
90  uno::Reference<document::XFilter> xFilter(xInterface, uno::UNO_QUERY_THROW);
91  try
92  {
93  xFilter->filter(aDescriptor);
94  }
95  catch (uno::Exception const&)
96  {
97  TOOLS_WARN_EXCEPTION("sw.docx", "SwDOCXReader::Read()");
98  ret = ERR_SWG_READ_ERROR;
99  }
100  pDocShell->SetLoading(SfxLoadedFlags::ALL);
101 
102  return ret;
103 }
104 
106 {
108 }
109 
111 {
112  // TODO
113  return true;
114 }
115 
116 bool SwDOCXReader::ReadGlossaries( SwTextBlocks& rBlocks, bool /* bSaveRelFiles */ ) const
117 {
118  uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(
120 
121  uno::Reference<uno::XInterface> xInterface(
122  xMultiServiceFactory->createInstance( "com.sun.star.comp.Writer.WriterFilter" ),
123  uno::UNO_SET_THROW );
124 
125  uno::Reference<document::XFilter> xFilter( xInterface, uno::UNO_QUERY_THROW );
126  uno::Reference<document::XImporter> xImporter( xFilter, uno::UNO_QUERY_THROW );
127 
128  SfxObjectShellLock xDocSh( new SwDocShell( SfxObjectCreateMode::INTERNAL ) );
129  if( xDocSh->DoInitNew() )
130  {
131  uno::Reference<lang::XComponent> xDstDoc( xDocSh->GetModel(), uno::UNO_QUERY_THROW );
132  xImporter->setTargetDocument( xDstDoc );
133 
134  uno::Reference<io::XStream> xStream( new utl::OStreamWrapper( *m_pMedium->GetInStream() ) );
135 
136  uno::Sequence<beans::PropertyValue> aDescriptor( comphelper::InitPropertySequence({
137  { "InputStream", uno::Any(xStream) },
138  { "ReadGlossaries", uno::Any(true) }
139  }));
140 
141  if( xFilter->filter( aDescriptor ) )
142  {
143  if (rBlocks.StartPutMuchBlockEntries())
144  {
145  bool bRet = MakeEntries(static_cast<SwDocShell*>(&xDocSh)->GetDoc(), rBlocks);
146  rBlocks.EndPutMuchBlockEntries();
147  return bRet;
148  }
149  }
150  }
151 
152  return false;
153 }
154 
156 {
157  const OUString aOldURL( rBlocks.GetBaseURL() );
158  rBlocks.SetBaseURL( OUString() );
159 
160  bool bRet = false;
161 
162  SwNodeIndex aDocEnd( pD->GetNodes().GetEndOfContent() );
163  SwNodeIndex aStart( *aDocEnd.GetNode().StartOfSectionNode(), 1 );
164  bool bIsAutoText = false;
165 
166  if( aStart < aDocEnd && ( aDocEnd.GetIndex() - aStart.GetIndex() > 2 ) )
167  {
169  (RES_POOLCOLL_STANDARD, false);
170  SwContentNode* pCNd = nullptr;
171  bRet = true;
172  do {
173  // Get name - first paragraph
174  OUString aLNm;
175  {
176  SwPaM aPam( aStart );
177  SwNodeIndex& rIdx = aPam.GetPoint()->nNode;
178  ++rIdx;
179  aLNm = aPam.GetNode().GetTextNode()->GetText();
180 
181  // is AutoText?
182  bIsAutoText = aLNm.startsWith(AUTOTEXT_GALLERY);
183  aLNm = aLNm.copy(strlen(AUTOTEXT_GALLERY) + 1);
184  }
185 
186  // Do not copy name
187  aStart++;
188 
189  // Get content
190  SwPaM aPam( aStart );
191  {
192  SwNodeIndex& rIdx = aPam.GetPoint()->nNode;
193  ++rIdx;
194  if( nullptr == ( pCNd = rIdx.GetNode().GetTextNode() ) )
195  {
196  pCNd = pD->GetNodes().MakeTextNode( rIdx, pColl );
197  rIdx = *pCNd;
198  }
199  }
200 
201  aPam.GetPoint()->nContent.Assign( pCNd, 0 );
202  aPam.SetMark();
203  {
204  SwNodeIndex& rIdx = aPam.GetPoint()->nNode;
205  rIdx = aStart.GetNode().EndOfSectionIndex() - 1;
206  // don't add extra empty text node if exist (.dotx but not .dotm)
207  if( rIdx.GetNode().GetTextNode() &&
208  rIdx.GetNode().GetTextNode()->GetText().isEmpty() )
209  rIdx = aStart.GetNode().EndOfSectionIndex() - 2;
210  if( nullptr == ( pCNd = rIdx.GetNode().GetContentNode() ) )
211  {
212  ++rIdx;
213  pCNd = pD->GetNodes().MakeTextNode( rIdx, pColl );
214  rIdx = *pCNd;
215  }
216  }
217  aPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
218 
219  if( bIsAutoText )
220  {
221  // Now we have the right selection for one entry
222  rBlocks.ClearDoc();
223 
224  OUString sShortcut = aLNm;
225 
226  // Need to check make sure the shortcut is not already being used
227  sal_Int32 nStart = 0;
228  sal_uInt16 nCurPos = rBlocks.GetIndex( sShortcut );
229 
230  while( sal_uInt16(-1) != nCurPos )
231  {
232  // add a Number to it
233  sShortcut = aLNm + OUString::number( ++nStart );
234  nCurPos = rBlocks.GetIndex( sShortcut );
235  }
236 
237  if( rBlocks.BeginPutDoc( sShortcut, sShortcut ) )
238  {
239  SwDoc* pGlDoc = rBlocks.GetDoc();
240  SwNodeIndex aIdx( pGlDoc->GetNodes().GetEndOfContent(), -1 );
241  pCNd = aIdx.GetNode().GetContentNode();
242  SwPosition aPos( aIdx, SwIndex( pCNd, pCNd ? pCNd->Len() : 0 ) );
243  pD->getIDocumentContentOperations().CopyRange( aPam, aPos, /*bCopyAll=*/false, /*bCheckPos=*/true );
244  rBlocks.PutDoc();
245  }
246  else
247  {
248  bRet = false;
249  }
250  }
251 
252  aStart = aStart.GetNode().EndOfSectionIndex() + 1;
253  } while( aStart < aDocEnd && aStart.GetNode().IsStartNode() );
254  }
255 
256  rBlocks.SetBaseURL( aOldURL );
257 
258  return bRet;
259 }
260 
261 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual sal_Int32 Len() const
Definition: node.cxx:1180
virtual ErrCode Read(SwDoc &, const OUString &, SwPaM &, const OUString &) override
SwNode & GetNode(bool bPoint=true) const
Definition: pam.hxx:223
Represents the style of a paragraph.
Definition: fmtcol.hxx:55
Marks a position in the document model.
Definition: pam.hxx:35
sal_uInt16 PutDoc()
Definition: swblocks.cxx:404
const OUString & GetText() const
Definition: ndtxt.hxx:210
SwDocShell * GetDocShell()
Definition: doc.hxx:1342
SwNodeIndex nNode
Definition: pam.hxx:37
virtual bool HasGlossaries() const override
Definition: doc.hxx:185
SwNode & GetNode() const
Definition: ndindex.hxx:119
css::uno::Reference< css::frame::XModel > GetModel() const
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:314
Reference< XInputStream > xStream
SwIndex nContent
Definition: pam.hxx:38
bool SetTextFormatColl(const SwPaM &rRg, SwTextFormatColl *pFormat, const bool bReset=true, const bool bResetListAttrs=false, SwRootFrame const *pLayout=nullptr)
Add 4th optional parameter .
Definition: docfmt.cxx:1064
IDocumentStylePoolAccess const & getIDocumentStylePoolAccess() const
Definition: doc.cxx:425
#define AUTOTEXT_GALLERY
css::uno::Sequence< css::beans::PropertyValue > InitPropertySequence(::std::initializer_list< ::std::pair< OUString, css::uno::Any > > vInit)
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:164
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
#define TOOLS_WARN_EXCEPTION(area, stream)
void SetBaseURL(const OUString &rURL)
Definition: swblocks.cxx:571
const SwPosition * GetPoint() const
Definition: pam.hxx:207
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:198
SwContentNode * GetContentNode()
Definition: node.hxx:615
Marks a character position inside a document model node.
Definition: index.hxx:37
void EndPutMuchBlockEntries()
Definition: swblocks.cxx:558
Marks a node in the document model.
Definition: ndindex.hxx:31
SwReaderType
Definition: shellio.hxx:183
SwDoc * GetDoc()
Definition: swblocks.cxx:476
virtual bool ReadGlossaries(SwTextBlocks &rBlocks, bool bSaveRelFiles) const override
static bool MakeEntries(SwDoc *pD, SwTextBlocks &rBlocks)
bool BeginPutDoc(const OUString &, const OUString &)
Definition: swblocks.cxx:380
sal_uLong EndOfSectionIndex() const
Definition: node.hxx:677
OUString GetBaseURL() const
Definition: swblocks.cxx:564
Reference< XMultiServiceFactory > getProcessServiceFactory()
#define ERRCODE_NONE
sal_uInt16 GetIndex(const OUString &) const
Definition: swblocks.cxx:266
virtual SwReaderType GetReaderType() override
bool DoInitNew(SfxMedium *pMedium=nullptr)
SwNodes & GetNodes()
Definition: doc.hxx:402
virtual SwTextFormatColl * GetTextCollFromPool(sal_uInt16 nId, bool bRegardLanguage=true)=0
Return "Auto-Collection with ID.
Wrapper for the UNO DOCX import filter (in writerfilter) for autotext purposes.
void ClearDoc()
Definition: swblocks.cxx:483
virtual bool SplitNode(const SwPosition &rPos, bool bChkTableStart)=0
Split a node at rPos (implemented only for TextNode).
#define ERR_SWG_READ_ERROR
Definition: swerror.h:25
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:459
static css::uno::Reference< css::text::XTextRange > CreateXTextRange(SwDoc &rDoc, const SwPosition &rPos, const SwPosition *const pMark)
Definition: unoobj2.cxx:1091
SAL_DLLPUBLIC_EXPORT Reader * ImportDOCX()
bool StartPutMuchBlockEntries()
Definition: swblocks.cxx:550
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:842
SwTextNode * MakeTextNode(const SwNodeIndex &rWhere, SwTextFormatColl *pColl, bool bNewFrames=true)
Implementations of "Make...Node" are in the given .cxx-files.
Definition: ndtxt.cxx:114
virtual bool CopyRange(SwPaM &rPam, SwPosition &rPos, const bool bCopyAll, bool bCheckPos) const =0
Copy a selected content range to a position.