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/frame/XModel.hpp>
25 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
28 #include <doc.hxx>
29 #include <docsh.hxx>
31 #include <ndtxt.hxx>
32 #include <poolfmt.hxx>
33 #include <swerror.h>
34 #include <unotools/streamwrap.hxx>
35 #include <unotextrange.hxx>
36 #include <sfx2/docfile.hxx>
37 #include <tools/diagnose_ex.h>
38 
39 #define AUTOTEXT_GALLERY "autoTxt"
40 
41 using namespace css;
42 
43 extern "C" SAL_DLLPUBLIC_EXPORT Reader* ImportDOCX()
44 {
45  return new SwDOCXReader;
46 }
47 
48 ErrCode SwDOCXReader::Read(SwDoc& rDoc, const OUString& /* rBaseURL */, SwPaM& rPam, const OUString& /* FileName */ )
49 {
50  if (!m_pMedium->GetInStream())
51  return ERR_SWG_READ_ERROR;
52 
53  // We want to work in an empty paragraph.
54  const SwPosition* pPos = rPam.GetPoint();
55  rDoc.getIDocumentContentOperations().SplitNode(*pPos, false);
57 
58  uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(comphelper::getProcessServiceFactory());
59  uno::Reference<uno::XInterface> xInterface(xMultiServiceFactory->createInstance("com.sun.star.comp.Writer.WriterFilter"), uno::UNO_SET_THROW);
60 
61  SwDocShell* pDocShell(rDoc.GetDocShell());
62  uno::Reference<lang::XComponent> xDstDoc(pDocShell->GetModel(), uno::UNO_QUERY_THROW);
63  uno::Reference<document::XImporter> xImporter(xInterface, uno::UNO_QUERY_THROW);
64  xImporter->setTargetDocument(xDstDoc);
65 
66  const uno::Reference<text::XTextRange> xInsertTextRange = SwXTextRange::CreateXTextRange(rDoc, *rPam.GetPoint(), nullptr);
67  uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(*m_pMedium->GetInStream()));
68 
69  //SetLoading hack because the document properties will be re-initted
70  //by the xml filter and during the init, while it's considered uninitialized,
71  //setting a property will inform the document it's modified, which attempts
72  //to update the properties, which throws cause the properties are uninitialized
73  pDocShell->SetLoading(SfxLoadedFlags::NONE);
74 
75  uno::Sequence<beans::PropertyValue> aDescriptor(comphelper::InitPropertySequence(
76  {
77  { "InputStream", uno::Any(xStream) },
78  { "InsertMode", uno::Any(true) },
79  { "TextInsertModeRange", uno::Any(xInsertTextRange) }
80  }));
81 
82  ErrCode ret = ERRCODE_NONE;
83  uno::Reference<document::XFilter> xFilter(xInterface, uno::UNO_QUERY_THROW);
84  try
85  {
86  xFilter->filter(aDescriptor);
87  }
88  catch (uno::Exception const&)
89  {
90  TOOLS_WARN_EXCEPTION("sw.docx", "SwDOCXReader::Read()");
91  ret = ERR_SWG_READ_ERROR;
92  }
93  pDocShell->SetLoading(SfxLoadedFlags::ALL);
94 
95  return ret;
96 }
97 
99 {
101 }
102 
104 {
105  // TODO
106  return true;
107 }
108 
109 bool SwDOCXReader::ReadGlossaries( SwTextBlocks& rBlocks, bool /* bSaveRelFiles */ ) const
110 {
111  uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(
113 
114  uno::Reference<uno::XInterface> xInterface(
115  xMultiServiceFactory->createInstance( "com.sun.star.comp.Writer.WriterFilter" ),
116  uno::UNO_SET_THROW );
117 
118  uno::Reference<document::XFilter> xFilter( xInterface, uno::UNO_QUERY_THROW );
119  uno::Reference<document::XImporter> xImporter( xFilter, uno::UNO_QUERY_THROW );
120 
121  SfxObjectShellLock xDocSh( new SwDocShell( SfxObjectCreateMode::INTERNAL ) );
122  if( xDocSh->DoInitNew() )
123  {
124  uno::Reference<lang::XComponent> xDstDoc( xDocSh->GetModel(), uno::UNO_QUERY_THROW );
125  xImporter->setTargetDocument( xDstDoc );
126 
127  uno::Reference<io::XStream> xStream( new utl::OStreamWrapper( *m_pMedium->GetInStream() ) );
128 
129  uno::Sequence<beans::PropertyValue> aDescriptor( comphelper::InitPropertySequence({
130  { "InputStream", uno::Any(xStream) },
131  { "ReadGlossaries", uno::Any(true) }
132  }));
133 
134  if( xFilter->filter( aDescriptor ) )
135  {
136  if (rBlocks.StartPutMuchBlockEntries())
137  {
138  bool bRet = MakeEntries(static_cast<SwDocShell*>(&xDocSh)->GetDoc(), rBlocks);
139  rBlocks.EndPutMuchBlockEntries();
140  return bRet;
141  }
142  }
143  }
144 
145  return false;
146 }
147 
149 {
150  const OUString aOldURL( rBlocks.GetBaseURL() );
151  rBlocks.SetBaseURL( OUString() );
152 
153  bool bRet = false;
154 
155  SwNodeIndex aDocEnd( pD->GetNodes().GetEndOfContent() );
156  SwNodeIndex aStart( *aDocEnd.GetNode().StartOfSectionNode(), 1 );
157  bool bIsAutoText = false;
158 
159  if( aStart < aDocEnd && ( aDocEnd.GetIndex() - aStart.GetIndex() > 2 ) )
160  {
162  (RES_POOLCOLL_STANDARD, false);
163  SwContentNode* pCNd = nullptr;
164  bRet = true;
165  do {
166  // Get name - first paragraph
167  OUString aLNm;
168  {
169  SwPaM aPam( aStart );
170  SwNodeIndex& rIdx = aPam.GetPoint()->nNode;
171  ++rIdx;
172  aLNm = aPam.GetNode().GetTextNode()->GetText();
173 
174  // is AutoText?
175  bIsAutoText = aLNm.startsWith(AUTOTEXT_GALLERY);
176  aLNm = aLNm.copy(strlen(AUTOTEXT_GALLERY) + 1);
177  }
178 
179  // Do not copy name
180  aStart++;
181 
182  // Get content
183  SwPaM aPam( aStart );
184  {
185  SwNodeIndex& rIdx = aPam.GetPoint()->nNode;
186  ++rIdx;
187  if( nullptr == ( pCNd = rIdx.GetNode().GetTextNode() ) )
188  {
189  pCNd = pD->GetNodes().MakeTextNode( rIdx, pColl );
190  rIdx = *pCNd;
191  }
192  }
193 
194  aPam.GetPoint()->nContent.Assign( pCNd, 0 );
195  aPam.SetMark();
196  {
197  SwNodeIndex& rIdx = aPam.GetPoint()->nNode;
198  rIdx = aStart.GetNode().EndOfSectionIndex() - 1;
199  // don't add extra empty text node if exist (.dotx but not .dotm)
200  if( rIdx.GetNode().GetTextNode() &&
201  rIdx.GetNode().GetTextNode()->GetText().isEmpty() )
202  rIdx = aStart.GetNode().EndOfSectionIndex() - 2;
203  if( nullptr == ( pCNd = rIdx.GetNode().GetContentNode() ) )
204  {
205  ++rIdx;
206  pCNd = pD->GetNodes().MakeTextNode( rIdx, pColl );
207  rIdx = *pCNd;
208  }
209  }
210  aPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
211 
212  if( bIsAutoText )
213  {
214  // Now we have the right selection for one entry
215  rBlocks.ClearDoc();
216 
217  OUString sShortcut = aLNm;
218 
219  // Need to check make sure the shortcut is not already being used
220  sal_Int32 nStart = 0;
221  sal_uInt16 nCurPos = rBlocks.GetIndex( sShortcut );
222 
223  while( sal_uInt16(-1) != nCurPos )
224  {
225  // add a Number to it
226  sShortcut = aLNm + OUString::number( ++nStart );
227  nCurPos = rBlocks.GetIndex( sShortcut );
228  }
229 
230  if( rBlocks.BeginPutDoc( sShortcut, sShortcut ) )
231  {
232  SwDoc* pGlDoc = rBlocks.GetDoc();
233  SwNodeIndex aIdx( pGlDoc->GetNodes().GetEndOfContent(), -1 );
234  pCNd = aIdx.GetNode().GetContentNode();
235  SwPosition aPos( aIdx, SwIndex( pCNd, pCNd ? pCNd->Len() : 0 ) );
237  rBlocks.PutDoc();
238  }
239  else
240  {
241  bRet = false;
242  }
243  }
244 
245  aStart = aStart.GetNode().EndOfSectionIndex() + 1;
246  } while( aStart < aDocEnd && aStart.GetNode().IsStartNode() );
247  }
248 
249  rBlocks.SetBaseURL( aOldURL );
250 
251  return bRet;
252 }
253 
254 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual sal_Int32 Len() const
Definition: node.cxx:1181
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:396
const OUString & GetText() const
Definition: ndtxt.hxx:211
SwDocShell * GetDocShell()
Definition: doc.hxx:1350
SwNodeIndex nNode
Definition: pam.hxx:37
virtual bool HasGlossaries() const override
Definition: doc.hxx:186
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:1072
IDocumentStylePoolAccess const & getIDocumentStylePoolAccess() const
Definition: doc.cxx:425
check if target position is in fly anchored at source range
#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:163
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:563
const SwPosition * GetPoint() const
Definition: pam.hxx:207
virtual bool CopyRange(SwPaM &rPam, SwPosition &rPos, SwCopyFlags flags) const =0
Copy a selected content range to a position.
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:206
SwContentNode * GetContentNode()
Definition: node.hxx:615
Marks a character position inside a document model node.
Definition: index.hxx:37
void EndPutMuchBlockEntries()
Definition: swblocks.cxx:550
Marks a node in the document model.
Definition: ndindex.hxx:31
SwReaderType
Definition: shellio.hxx:190
SwDoc * GetDoc()
Definition: swblocks.cxx:468
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:372
sal_uLong EndOfSectionIndex() const
Definition: node.hxx:677
OUString GetBaseURL() const
Definition: swblocks.cxx:556
Reference< XMultiServiceFactory > getProcessServiceFactory()
#define ERRCODE_NONE
sal_uInt16 GetIndex(const OUString &) const
Definition: swblocks.cxx:258
virtual SwReaderType GetReaderType() override
bool DoInitNew(SfxMedium *pMedium=nullptr)
SwNodes & GetNodes()
Definition: doc.hxx:405
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:475
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:475
static css::uno::Reference< css::text::XTextRange > CreateXTextRange(SwDoc &rDoc, const SwPosition &rPos, const SwPosition *const pMark)
Definition: unoobj2.cxx:1054
SAL_DLLPUBLIC_EXPORT Reader * ImportDOCX()
bool StartPutMuchBlockEntries()
Definition: swblocks.cxx:542
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:836
SwTextNode * MakeTextNode(const SwNodeIndex &rWhere, SwTextFormatColl *pColl, bool bNewFrames=true)
Implementations of "Make...Node" are in the given .cxx-files.
Definition: ndtxt.cxx:104