update credits
[LibreOffice.git] / sw / source / core / swg / SwXMLTextBlocks1.cxx
blobb0822d251452395b3aac7ad5c8a3d92c53e10224
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/embed/ElementModes.hpp>
21 #include <com/sun/star/embed/XTransactedObject.hpp>
22 #include <svl/macitem.hxx>
23 #include <svtools/unoevent.hxx>
24 #include <sfx2/docfile.hxx>
25 #include <unotools/streamwrap.hxx>
26 #include <comphelper/componentcontext.hxx>
27 #include <comphelper/processfactory.hxx>
28 #include <com/sun/star/xml/sax/InputSource.hpp>
29 #include <com/sun/star/io/XActiveDataSource.hpp>
30 #include <com/sun/star/xml/sax/Parser.hpp>
31 #include <com/sun/star/xml/sax/Writer.hpp>
32 #include <com/sun/star/document/XStorageBasedDocument.hpp>
33 #include <doc.hxx>
34 #include <docsh.hxx>
35 #include <shellio.hxx>
36 #include <SwXMLTextBlocks.hxx>
37 #include <SwXMLBlockImport.hxx>
38 #include <SwXMLBlockExport.hxx>
39 #include <swevent.hxx>
40 #include <swerror.h>
42 const char XMLN_BLOCKLIST[] = "BlockList.xml";
44 using namespace ::com::sun::star;
45 using namespace ::com::sun::star::uno;
46 using namespace ::com::sun::star::container;
48 using ::xmloff::token::XML_BLOCK_LIST;
49 using ::xmloff::token::XML_UNFORMATTED_TEXT;
50 using ::xmloff::token::GetXMLToken;
52 sal_uLong SwXMLTextBlocks::GetDoc( sal_uInt16 nIdx )
54 String aFolderName ( GetPackageName ( nIdx ) );
56 if (!IsOnlyTextBlock ( nIdx ) )
58 try
60 xRoot = xBlkRoot->openStorageElement( aFolderName, embed::ElementModes::READ );
61 xMedium = new SfxMedium( xRoot, GetBaseURL(), OUString( "writer8" ) );
62 SwReader aReader( *xMedium, aFolderName, pDoc );
63 ReadXML->SetBlockMode( sal_True );
64 aReader.Read( *ReadXML );
65 ReadXML->SetBlockMode( sal_False );
66 // Ole objects fails to display when inserted into document
67 // because the ObjectReplacement folder ( and contents are missing )
68 OUString sObjReplacements( "ObjectReplacements" );
69 if ( xRoot->hasByName( sObjReplacements ) )
71 uno::Reference< document::XStorageBasedDocument > xDocStor( pDoc->GetDocShell()->GetModel(), uno::UNO_QUERY_THROW );
72 uno::Reference< embed::XStorage > xStr( xDocStor->getDocumentStorage() );
73 if ( xStr.is() )
75 xRoot->copyElementTo( sObjReplacements, xStr, sObjReplacements );
76 uno::Reference< embed::XTransactedObject > xTrans( xStr, uno::UNO_QUERY );
77 if ( xTrans.is() )
78 xTrans->commit();
82 catch( uno::Exception& )
86 xRoot = 0;
88 else
90 String aStreamName = aFolderName + OUString(".xml");
91 try
93 xRoot = xBlkRoot->openStorageElement( aFolderName, embed::ElementModes::READ );
94 uno::Reference < io::XStream > xStream = xRoot->openStreamElement( aStreamName, embed::ElementModes::READ );
96 uno::Reference< uno::XComponentContext > xContext =
97 comphelper::getProcessComponentContext();
99 xml::sax::InputSource aParserInput;
100 aParserInput.sSystemId = aNames[nIdx]->aPackageName;
102 aParserInput.aInputStream = xStream->getInputStream();
104 // get filter
105 // uno::Reference< xml::sax::XDocumentHandler > xFilter = new SwXMLTextBlockImport( *this, aCur, sal_True );
106 uno::Reference< xml::sax::XDocumentHandler > xFilter = new SwXMLTextBlockImport( xContext, *this, aCur, sal_True );
108 // connect parser and filter
109 uno::Reference< xml::sax::XParser > xParser = xml::sax::Parser::create(xContext);
110 xParser->setDocumentHandler( xFilter );
112 // parse
115 xParser->parseStream( aParserInput );
117 catch( xml::sax::SAXParseException& )
119 // re throw ?
121 catch( xml::sax::SAXException& )
123 // re throw ?
125 catch( io::IOException& )
127 // re throw ?
130 bInfoChanged = sal_False;
131 MakeBlockText(aCur);
133 catch( uno::Exception& )
137 xRoot = 0;
139 return 0;
142 // event description for autotext events; this constant should really be
143 // taken from unocore/unoevents.cxx or ui/unotxt.cxx
144 const struct SvEventDescription aAutotextEvents[] =
146 { SW_EVENT_START_INS_GLOSSARY, "OnInsertStart" },
147 { SW_EVENT_END_INS_GLOSSARY, "OnInsertDone" },
148 { 0, NULL }
151 sal_uLong SwXMLTextBlocks::GetMacroTable( sal_uInt16 nIdx,
152 SvxMacroTableDtor& rMacroTbl,
153 sal_Bool bFileAlreadyOpen )
155 // set current auto text
157 aShort = aNames[nIdx]->aShort;
158 aLong = aNames[nIdx]->aLong;
159 aPackageName = aNames[nIdx]->aPackageName;
161 sal_uLong nRet = 0;
163 // open stream in proper sub-storage
164 if( !bFileAlreadyOpen )
166 CloseFile();
167 nRet = OpenFile ( sal_True );
169 if ( 0 == nRet )
173 xRoot = xBlkRoot->openStorageElement( aPackageName, embed::ElementModes::READ );
174 long nTmp = SOT_FORMATSTR_ID_STARWRITER_60;
175 bool bOasis = ( SotStorage::GetVersion( xRoot ) > nTmp );
177 OUString sStreamName("atevent.xml");
178 uno::Reference < io::XStream > xDocStream = xRoot->openStreamElement(
179 sStreamName, embed::ElementModes::READ );
180 OSL_ENSURE(xDocStream.is(), "Can't create stream");
181 if ( xDocStream.is() )
183 uno::Reference<io::XInputStream> xInputStream = xDocStream->getInputStream();
185 // prepare ParserInputSrouce
186 xml::sax::InputSource aParserInput;
187 aParserInput.sSystemId = aName;
188 aParserInput.aInputStream = xInputStream;
190 // get service factory
191 uno::Reference< uno::XComponentContext > xContext =
192 comphelper::getProcessComponentContext();
194 // get parser
195 uno::Reference< xml::sax::XParser > xParser = xml::sax::Parser::create( xContext );
197 // create descriptor and reference to it. Either
198 // both or neither must be kept because of the
199 // reference counting!
200 SvMacroTableEventDescriptor* pDescriptor =
201 new SvMacroTableEventDescriptor(aAutotextEvents);
202 uno::Reference<XNameReplace> xReplace = pDescriptor;
203 Sequence<Any> aFilterArguments( 1 );
204 aFilterArguments[0] <<= xReplace;
206 // get filter
207 OUString sFilterComponent = bOasis
208 ? OUString("com.sun.star.comp.Writer.XMLOasisAutotextEventsImporter")
209 : OUString("com.sun.star.comp.Writer.XMLAutotextEventsImporter");
210 uno::Reference< xml::sax::XDocumentHandler > xFilter(
211 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
212 sFilterComponent, aFilterArguments, xContext),
213 UNO_QUERY );
214 OSL_ENSURE( xFilter.is(),
215 "can't instantiate atevents filter");
216 if ( xFilter.is() )
218 // connect parser and filter
219 xParser->setDocumentHandler( xFilter );
221 // connect model and filter
222 uno::Reference<document::XImporter> xImporter( xFilter,
223 UNO_QUERY );
225 // we don't need a model
226 // xImporter->setTargetDocument( xModelComponent );
228 // parse the stream
231 xParser->parseStream( aParserInput );
233 catch( xml::sax::SAXParseException& )
235 // workaround for #83452#: SetSize doesn't work
236 // nRet = ERR_SWG_READ_ERROR;
238 catch( xml::sax::SAXException& )
240 nRet = ERR_SWG_READ_ERROR;
242 catch( io::IOException& )
244 nRet = ERR_SWG_READ_ERROR;
247 // and finally, copy macro into table
248 if (0 == nRet)
249 pDescriptor->copyMacrosIntoTable(rMacroTbl);
251 else
252 nRet = ERR_SWG_READ_ERROR;
254 else
255 nRet = ERR_SWG_READ_ERROR;
257 catch( uno::Exception& )
259 nRet = ERR_SWG_READ_ERROR;
262 else
263 nRet = ERR_SWG_READ_ERROR;
265 // success!
266 return nRet;
270 sal_uLong SwXMLTextBlocks::GetBlockText( const String& rShort, String& rText )
272 sal_uLong n = 0;
273 sal_Bool bTextOnly = sal_True;
274 String aFolderName = GeneratePackageName ( rShort );
275 String aStreamName = aFolderName + OUString(".xml");
276 rText.Erase();
280 xRoot = xBlkRoot->openStorageElement( aFolderName, embed::ElementModes::READ );
281 uno::Reference < container::XNameAccess > xAccess( xRoot, uno::UNO_QUERY );
282 if ( !xAccess->hasByName( aStreamName ) || !xRoot->isStreamElement( aStreamName ) )
284 bTextOnly = sal_False;
285 aStreamName = OUString("content.xml");
288 uno::Reference < io::XStream > xContents = xRoot->openStreamElement( aStreamName, embed::ElementModes::READ );
289 uno::Reference< uno::XComponentContext > xContext =
290 comphelper::getProcessComponentContext();
292 xml::sax::InputSource aParserInput;
293 aParserInput.sSystemId = aName;
294 aParserInput.aInputStream = xContents->getInputStream();
296 // get filter
297 // #110680#
298 // uno::Reference< xml::sax::XDocumentHandler > xFilter = new SwXMLTextBlockImport( *this, rText, bTextOnly );
299 uno::Reference< xml::sax::XDocumentHandler > xFilter = new SwXMLTextBlockImport( xContext, *this, rText, bTextOnly );
301 // connect parser and filter
302 uno::Reference< xml::sax::XParser > xParser = xml::sax::Parser::create(xContext);
303 xParser->setDocumentHandler( xFilter );
305 // parse
308 xParser->parseStream( aParserInput );
310 catch( xml::sax::SAXParseException& )
312 // re throw ?
314 catch( xml::sax::SAXException& )
316 // re throw ?
318 catch( io::IOException& )
320 // re throw ?
323 xRoot = 0;
325 catch ( uno::Exception& )
327 OSL_FAIL( "Tried to open non-existent folder or stream!");
330 return n;
333 sal_uLong SwXMLTextBlocks::PutBlockText( const String& rShort, const String& ,
334 const String& rText, const String& rPackageName )
336 GetIndex ( rShort );
338 if (xBlkRoot->IsContained ( rPackageName ) )
340 xBlkRoot->Remove ( rPackageName );
341 xBlkRoot->Commit ( );
344 String aFolderName( rPackageName );
345 String aStreamName = aFolderName + OUString(".xml");
347 uno::Reference< uno::XComponentContext > xContext =
348 comphelper::getProcessComponentContext();
350 uno::Reference < xml::sax::XWriter > xWriter = xml::sax::Writer::create(xContext);
351 sal_uLong nRes = 0;
355 xRoot = xBlkRoot->openStorageElement( aFolderName, embed::ElementModes::WRITE );
356 uno::Reference < io::XStream > xDocStream = xRoot->openStreamElement( aStreamName,
357 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
359 uno::Reference < beans::XPropertySet > xSet( xDocStream, uno::UNO_QUERY );
360 OUString aMime ( "text/xml" );
361 Any aAny;
362 aAny <<= aMime;
363 xSet->setPropertyValue( OUString("MediaType"), aAny );
364 uno::Reference < io::XOutputStream > xOut = xDocStream->getOutputStream();
365 uno::Reference<io::XActiveDataSource> xSrc(xWriter, uno::UNO_QUERY);
366 xSrc->setOutputStream(xOut);
368 uno::Reference<xml::sax::XDocumentHandler> xHandler(xWriter,
369 uno::UNO_QUERY);
371 SwXMLTextBlockExport aExp( xContext, *this, GetXMLToken ( XML_UNFORMATTED_TEXT ), xHandler);
373 aExp.exportDoc( rText );
375 uno::Reference < embed::XTransactedObject > xTrans( xRoot, uno::UNO_QUERY );
376 if ( xTrans.is() )
377 xTrans->commit();
379 if (! (nFlags & SWXML_NOROOTCOMMIT) )
381 uno::Reference < embed::XTransactedObject > xTmpTrans( xBlkRoot, uno::UNO_QUERY );
382 if ( xTmpTrans.is() )
383 xTmpTrans->commit();
386 catch ( uno::Exception& )
388 nRes = ERR_SWG_WRITE_ERROR;
391 xRoot = 0;
393 //TODO/LATER: error handling
395 sal_uLong nErr = xBlkRoot->GetError();
396 sal_uLong nRes = 0;
397 if( nErr == SVSTREAM_DISK_FULL )
398 nRes = ERR_W4W_WRITE_FULL;
399 else if( nErr != SVSTREAM_OK )
400 nRes = ERR_SWG_WRITE_ERROR;
402 if( !nRes ) // damit ueber GetText & nCur aufs Doc zugegriffen
403 MakeBlockText( rText );
405 return nRes;
408 void SwXMLTextBlocks::ReadInfo( void )
412 const OUString sDocName( XMLN_BLOCKLIST );
413 uno::Reference < container::XNameAccess > xAccess( xBlkRoot, uno::UNO_QUERY );
414 if ( xAccess.is() && xAccess->hasByName( sDocName ) && xBlkRoot->isStreamElement( sDocName ) )
416 uno::Reference< uno::XComponentContext > xContext =
417 comphelper::getProcessComponentContext();
419 xml::sax::InputSource aParserInput;
420 aParserInput.sSystemId = sDocName;
422 uno::Reference < io::XStream > xDocStream = xBlkRoot->openStreamElement( sDocName, embed::ElementModes::READ );
423 aParserInput.aInputStream = xDocStream->getInputStream();
425 // get filter
426 uno::Reference< xml::sax::XDocumentHandler > xFilter = new SwXMLBlockListImport( xContext, *this );
428 // connect parser and filter
429 uno::Reference< xml::sax::XParser > xParser = xml::sax::Parser::create( xContext );
430 xParser->setDocumentHandler( xFilter );
432 // parse
435 xParser->parseStream( aParserInput );
437 catch( xml::sax::SAXParseException& )
439 // re throw ?
441 catch( xml::sax::SAXException& )
443 // re throw ?
445 catch( io::IOException& )
447 // re throw ?
451 catch ( uno::Exception& )
455 void SwXMLTextBlocks::WriteInfo( void )
457 if ( xBlkRoot.is() || 0 == OpenFile ( sal_False ) )
459 uno::Reference< uno::XComponentContext > xContext =
460 comphelper::getProcessComponentContext();
462 uno::Reference < xml::sax::XWriter > xWriter = xml::sax::Writer::create(xContext);
463 OUString sDocName( XMLN_BLOCKLIST );
466 if ( xBlkRoot->IsContained( sDocName) )
468 xBlkRoot->Remove ( sDocName );
469 xBlkRoot->Commit();
475 uno::Reference < io::XStream > xDocStream = xBlkRoot->openStreamElement( sDocName,
476 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
478 uno::Reference < beans::XPropertySet > xSet( xDocStream, uno::UNO_QUERY );
479 OUString aMime ( "text/xml" );
480 Any aAny;
481 aAny <<= aMime;
482 xSet->setPropertyValue( OUString("MediaType"), aAny );
483 uno::Reference < io::XOutputStream > xOut = xDocStream->getOutputStream();
484 uno::Reference<io::XActiveDataSource> xSrc(xWriter, uno::UNO_QUERY);
485 xSrc->setOutputStream(xOut);
487 uno::Reference<xml::sax::XDocumentHandler> xHandler(xWriter, uno::UNO_QUERY);
489 SwXMLBlockListExport aExp( xContext, *this, OUString(XMLN_BLOCKLIST), xHandler);
491 aExp.exportDoc( XML_BLOCK_LIST );
493 uno::Reference < embed::XTransactedObject > xTrans( xBlkRoot, uno::UNO_QUERY );
494 if ( xTrans.is() )
495 xTrans->commit();
497 catch ( uno::Exception& )
501 bInfoChanged = sal_False;
502 return;
506 sal_uLong SwXMLTextBlocks::SetMacroTable(
507 sal_uInt16 nIdx,
508 const SvxMacroTableDtor& rMacroTbl,
509 sal_Bool bFileAlreadyOpen )
511 // set current autotext
512 aShort = aNames[nIdx]->aShort;
513 aLong = aNames[nIdx]->aLong;
514 aPackageName = aNames[nIdx]->aPackageName;
516 // start XML autotext event export
517 sal_uLong nRes = 0;
519 uno::Reference< uno::XComponentContext > xContext =
520 comphelper::getProcessComponentContext();
522 // Get model
523 uno::Reference< lang::XComponent > xModelComp(
524 pDoc->GetDocShell()->GetModel(), UNO_QUERY );
525 OSL_ENSURE( xModelComp.is(), "XMLWriter::Write: got no model" );
526 if( !xModelComp.is() )
527 return ERR_SWG_WRITE_ERROR;
529 // open stream in proper sub-storage
530 if( !bFileAlreadyOpen )
532 CloseFile(); // close (it may be open in read-only-mode)
533 nRes = OpenFile ( sal_False );
536 if ( 0 == nRes )
540 xRoot = xBlkRoot->openStorageElement( aPackageName, embed::ElementModes::WRITE );
541 OUString sStreamName("atevent.xml" );
542 long nTmp = SOT_FORMATSTR_ID_STARWRITER_60;
543 bool bOasis = ( SotStorage::GetVersion( xRoot ) > nTmp );
545 uno::Reference < io::XStream > xDocStream = xRoot->openStreamElement( sStreamName,
546 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE );
548 uno::Reference < beans::XPropertySet > xSet( xDocStream, uno::UNO_QUERY );
549 OUString aMime( "text/xml" );
550 Any aAny;
551 aAny <<= aMime;
552 xSet->setPropertyValue( OUString("MediaType"), aAny );
553 uno::Reference < io::XOutputStream > xOutputStream = xDocStream->getOutputStream();
555 // get XML writer
556 uno::Reference< xml::sax::XWriter > xSaxWriter =
557 xml::sax::Writer::create( xContext );
559 // connect XML writer to output stream
560 xSaxWriter->setOutputStream( xOutputStream );
561 uno::Reference<xml::sax::XDocumentHandler> xDocHandler(
562 xSaxWriter, UNO_QUERY);
564 // construct events object
565 uno::Reference<XNameAccess> xEvents =
566 new SvMacroTableEventDescriptor(rMacroTbl,aAutotextEvents);
568 // prepare arguments (prepend doc handler to given arguments)
569 Sequence<Any> aParams(2);
570 aParams[0] <<= xDocHandler;
571 aParams[1] <<= xEvents;
574 // get filter component
575 OUString sFilterComponent = bOasis
576 ? OUString("com.sun.star.comp.Writer.XMLOasisAutotextEventsExporter")
577 : OUString("com.sun.star.comp.Writer.XMLAutotextEventsExporter");
578 uno::Reference< document::XExporter > xExporter(
579 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
580 sFilterComponent, aParams, xContext), UNO_QUERY);
581 OSL_ENSURE( xExporter.is(),
582 "can't instantiate export filter component" );
583 if( xExporter.is() )
585 // connect model and filter
586 xExporter->setSourceDocument( xModelComp );
588 // filter!
589 Sequence<beans::PropertyValue> aFilterProps( 0 );
590 uno::Reference < document::XFilter > xFilter( xExporter,
591 UNO_QUERY );
592 xFilter->filter( aFilterProps );
594 else
595 nRes = ERR_SWG_WRITE_ERROR;
597 // finally, commit stream, sub-storage and storage
598 uno::Reference < embed::XTransactedObject > xTmpTrans( xRoot, uno::UNO_QUERY );
599 if ( xTmpTrans.is() )
600 xTmpTrans->commit();
602 if ( !bFileAlreadyOpen )
604 uno::Reference < embed::XTransactedObject > xTrans( xBlkRoot, uno::UNO_QUERY );
605 if ( xTrans.is() )
606 xTrans->commit();
609 xRoot = 0;
611 catch ( uno::Exception& )
613 nRes = ERR_SWG_WRITE_ERROR;
616 if( !bFileAlreadyOpen )
617 CloseFile();
619 else
620 nRes = ERR_SWG_WRITE_ERROR;
622 return nRes;
625 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */