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 #define AUTOTEXT_GALLERY "autoTxt"
44 
45 using namespace css;
46 
47 extern "C" SAL_DLLPUBLIC_EXPORT Reader* ImportDOCX()
48 {
49  return new SwDOCXReader;
50 }
51 
52 ErrCode SwDOCXReader::Read(SwDoc& rDoc, const OUString& /* rBaseURL */, SwPaM& rPam, const OUString& /* FileName */ )
53 {
54  if (!m_pMedium->GetInStream())
55  return ERR_SWG_READ_ERROR;
56 
57  // We want to work in an empty paragraph.
58  std::shared_ptr<SwNodeIndex> pSttNdIdx(new SwNodeIndex(rDoc.GetNodes()));
59  const SwPosition* pPos = rPam.GetPoint();
60  rDoc.getIDocumentContentOperations().SplitNode(*pPos, false);
62 
63  uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(comphelper::getProcessServiceFactory());
64  uno::Reference<uno::XInterface> xInterface(xMultiServiceFactory->createInstance("com.sun.star.comp.Writer.WriterFilter"), uno::UNO_SET_THROW);
65 
66  SwDocShell* pDocShell(rDoc.GetDocShell());
67  uno::Reference<lang::XComponent> xDstDoc(pDocShell->GetModel(), uno::UNO_QUERY_THROW);
68  uno::Reference<document::XImporter> xImporter(xInterface, uno::UNO_QUERY_THROW);
69  xImporter->setTargetDocument(xDstDoc);
70 
71  const uno::Reference<text::XTextRange> xInsertTextRange = SwXTextRange::CreateXTextRange(rDoc, *rPam.GetPoint(), nullptr);
72  uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(*m_pMedium->GetInStream()));
73 
74  //SetLoading hack because the document properties will be re-initted
75  //by the xml filter and during the init, while its considered uninitialized,
76  //setting a property will inform the document its modified, which attempts
77  //to update the properties, which throws cause the properties are uninitialized
78  pDocShell->SetLoading(SfxLoadedFlags::NONE);
79 
80  uno::Sequence<beans::PropertyValue> aDescriptor(comphelper::InitPropertySequence(
81  {
82  { "InputStream", uno::Any(xStream) },
83  { "InsertMode", uno::Any(true) },
84  { "TextInsertModeRange", uno::Any(xInsertTextRange) }
85  }));
86 
87  ErrCode ret = ERRCODE_NONE;
88  uno::Reference<document::XFilter> xFilter(xInterface, uno::UNO_QUERY_THROW);
89  try
90  {
91  xFilter->filter(aDescriptor);
92  }
93  catch (uno::Exception const& e)
94  {
95  SAL_WARN("sw.docx", "SwDOCXReader::Read(): " << e);
96  ret = ERR_SWG_READ_ERROR;
97  }
98  pDocShell->SetLoading(SfxLoadedFlags::ALL);
99 
100  return ret;
101 }
102 
104 {
106 }
107 
109 {
110  // TODO
111  return true;
112 }
113 
114 bool SwDOCXReader::ReadGlossaries( SwTextBlocks& rBlocks, bool /* bSaveRelFiles */ ) const
115 {
116  uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(
118 
119  uno::Reference<uno::XInterface> xInterface(
120  xMultiServiceFactory->createInstance( "com.sun.star.comp.Writer.WriterFilter" ),
121  uno::UNO_SET_THROW );
122 
123  uno::Reference<document::XFilter> xFilter( xInterface, uno::UNO_QUERY_THROW );
124  uno::Reference<document::XImporter> xImporter( xFilter, uno::UNO_QUERY_THROW );
125 
126  SfxObjectShellLock xDocSh( new SwDocShell( SfxObjectCreateMode::INTERNAL ) );
127  if( xDocSh->DoInitNew() )
128  {
129  uno::Reference<lang::XComponent> xDstDoc( xDocSh->GetModel(), uno::UNO_QUERY_THROW );
130  xImporter->setTargetDocument( xDstDoc );
131 
132  uno::Reference<io::XStream> xStream( new utl::OStreamWrapper( *m_pMedium->GetInStream() ) );
133 
134  uno::Sequence<beans::PropertyValue> aDescriptor( comphelper::InitPropertySequence({
135  { "InputStream", uno::Any(xStream) },
136  { "ReadGlossaries", uno::Any(true) }
137  }));
138 
139  if( xFilter->filter( aDescriptor ) )
140  {
141  if (rBlocks.StartPutMuchBlockEntries())
142  {
143  bool bRet = MakeEntries(static_cast<SwDocShell*>(&xDocSh)->GetDoc(), rBlocks);
144  rBlocks.EndPutMuchBlockEntries();
145  return bRet;
146  }
147  }
148  }
149 
150  return false;
151 }
152 
154 {
155  const OUString aOldURL( rBlocks.GetBaseURL() );
156  rBlocks.SetBaseURL( OUString() );
157 
158  bool bRet = false;
159 
160  SwNodeIndex aDocEnd( pD->GetNodes().GetEndOfContent() );
161  SwNodeIndex aStart( *aDocEnd.GetNode().StartOfSectionNode(), 1 );
162  bool bIsAutoText = false;
163 
164  if( aStart < aDocEnd && ( aDocEnd.GetIndex() - aStart.GetIndex() > 2 ) )
165  {
167  (RES_POOLCOLL_STANDARD, false);
168  SwContentNode* pCNd = nullptr;
169  bRet = true;
170  do {
171  // Get name - first paragraph
172  OUString aLNm;
173  {
174  SwPaM aPam( aStart );
175  SwNodeIndex& rIdx = aPam.GetPoint()->nNode;
176  ++rIdx;
177  aLNm = aPam.GetNode().GetTextNode()->GetText();
178 
179  // is AutoText?
180  bIsAutoText = aLNm.startsWith(AUTOTEXT_GALLERY);
181  aLNm = aLNm.copy(strlen(AUTOTEXT_GALLERY) + 1);
182  }
183 
184  // Do not copy name
185  aStart++;
186 
187  // Get content
188  SwPaM aPam( aStart );
189  {
190  SwNodeIndex& rIdx = aPam.GetPoint()->nNode;
191  ++rIdx;
192  if( nullptr == ( pCNd = rIdx.GetNode().GetTextNode() ) )
193  {
194  pCNd = pD->GetNodes().MakeTextNode( rIdx, pColl );
195  rIdx = *pCNd;
196  }
197  }
198 
199  aPam.GetPoint()->nContent.Assign( pCNd, 0 );
200  aPam.SetMark();
201  {
202  SwNodeIndex& rIdx = aPam.GetPoint()->nNode;
203  rIdx = aStart.GetNode().EndOfSectionIndex() - 1;
204  // don't add extra empty text node if exist (.dotx but not .dotm)
205  if( rIdx.GetNode().GetTextNode() &&
206  rIdx.GetNode().GetTextNode()->GetText().isEmpty() )
207  rIdx = aStart.GetNode().EndOfSectionIndex() - 2;
208  if( nullptr == ( pCNd = rIdx.GetNode().GetContentNode() ) )
209  {
210  ++rIdx;
211  pCNd = pD->GetNodes().MakeTextNode( rIdx, pColl );
212  rIdx = *pCNd;
213  }
214  }
215  aPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
216 
217  if( bIsAutoText )
218  {
219  // Now we have the right selection for one entry
220  rBlocks.ClearDoc();
221 
222  OUString sShortcut = aLNm;
223 
224  // Need to check make sure the shortcut is not already being used
225  sal_Int32 nStart = 0;
226  sal_uInt16 nCurPos = rBlocks.GetIndex( sShortcut );
227 
228  while( sal_uInt16(-1) != nCurPos )
229  {
230  // add an Number to it
231  sShortcut = aLNm + OUString::number( ++nStart );
232  nCurPos = rBlocks.GetIndex( sShortcut );
233  }
234 
235  if( rBlocks.BeginPutDoc( sShortcut, sShortcut ) )
236  {
237  SwDoc* pGlDoc = rBlocks.GetDoc();
238  SwNodeIndex aIdx( pGlDoc->GetNodes().GetEndOfContent(), -1 );
239  pCNd = aIdx.GetNode().GetContentNode();
240  SwPosition aPos( aIdx, SwIndex( pCNd, pCNd ? pCNd->Len() : 0 ) );
241  pD->getIDocumentContentOperations().CopyRange( aPam, aPos, /*bCopyAll=*/false, /*bCheckPos=*/true );
242  rBlocks.PutDoc();
243  }
244  else
245  {
246  bRet = false;
247  }
248  }
249 
250  aStart = aStart.GetNode().EndOfSectionIndex() + 1;
251  } while( aStart < aDocEnd && aStart.GetNode().IsStartNode() );
252  }
253 
254  rBlocks.SetBaseURL( aOldURL );
255 
256  return bRet;
257 }
258 
259 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual sal_Int32 Len() const
Definition: node.cxx:1183
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:436
const OUString & GetText() const
Definition: ndtxt.hxx:211
SwDocShell * GetDocShell()
Definition: doc.hxx:1340
SwNodeIndex nNode
Definition: pam.hxx:37
virtual bool HasGlossaries() const override
Definition: doc.hxx:185
SwNode & GetNode() const
Definition: ndindex.hxx:118
css::uno::Reference< css::frame::XModel > GetModel() const
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:347
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:1096
IDocumentStylePoolAccess const & getIDocumentStylePoolAccess() const
Definition: doc.cxx:458
#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
void SetBaseURL(const OUString &rURL)
Definition: swblocks.cxx:603
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:590
Marks a node in the document model.
Definition: ndindex.hxx:31
SwReaderType
Definition: shellio.hxx:182
SwDoc * GetDoc()
Definition: swblocks.cxx:508
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:412
sal_uLong EndOfSectionIndex() const
Definition: node.hxx:677
OUString GetBaseURL() const
Definition: swblocks.cxx:596
Reference< XMultiServiceFactory > getProcessServiceFactory()
#define ERRCODE_NONE
sal_uInt16 GetIndex(const OUString &) const
Definition: swblocks.cxx:279
virtual SwReaderType GetReaderType() override
bool DoInitNew(SfxMedium *pMedium=nullptr)
SwNodes & GetNodes()
Definition: doc.hxx:403
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:515
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
#define SAL_WARN(area, stream)
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:457
static css::uno::Reference< css::text::XTextRange > CreateXTextRange(SwDoc &rDoc, const SwPosition &rPos, const SwPosition *const pMark)
Definition: unoobj2.cxx:1135
SAL_DLLPUBLIC_EXPORT Reader * ImportDOCX()
bool StartPutMuchBlockEntries()
Definition: swblocks.cxx:582
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.