CWS-TOOLING: integrate CWS tl88
[LibreOffice.git] / starmath / source / mathmlexport.cxx
blobbec69eb01b9531fa7abf0402d2bc494ae9277c3c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_starmath.hxx"
32 Warning: The SvXMLElementExport helper class creates the beginning and
33 closing tags of xml elements in its constructor and destructor, so theres
34 hidden stuff going on, on occasion the ordering of these classes declarations
35 may be significant
39 #include <com/sun/star/xml/sax/XErrorHandler.hpp>
40 #include <com/sun/star/xml/sax/XEntityResolver.hpp>
41 #include <com/sun/star/xml/sax/InputSource.hpp>
42 #include <com/sun/star/xml/sax/XDTDHandler.hpp>
43 #include <com/sun/star/xml/sax/XParser.hpp>
44 #include <com/sun/star/io/XActiveDataSource.hpp>
45 #include <com/sun/star/io/XActiveDataControl.hpp>
46 #include <com/sun/star/document/XDocumentProperties.hpp>
47 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
48 #include <com/sun/star/packages/zip/ZipIOException.hpp>
49 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
50 #include <com/sun/star/beans/PropertyAttribute.hpp>
51 #include <com/sun/star/container/XNameAccess.hpp>
52 #include <com/sun/star/embed/ElementModes.hpp>
53 #include <com/sun/star/uno/Any.h>
55 #include <rtl/math.hxx>
56 #include <sfx2/frame.hxx>
57 #include <sfx2/docfile.hxx>
58 #include <tools/debug.hxx>
59 #include <tools/urlobj.hxx>
60 #include <svtools/sfxecode.hxx>
61 #include <unotools/saveopt.hxx>
62 #include <svl/stritem.hxx>
63 #include <svl/itemprop.hxx>
64 #include <unotools/processfactory.hxx>
65 #include <unotools/streamwrap.hxx>
66 #include <xmloff/xmlnmspe.hxx>
67 #include <xmloff/xmltoken.hxx>
68 #include <xmloff/nmspmap.hxx>
69 #include <xmloff/attrlist.hxx>
70 #include <xmloff/xmluconv.hxx>
71 #include <xmloff/xmlmetai.hxx>
72 #include <osl/mutex.hxx>
73 #include <comphelper/genericpropertyset.hxx>
75 #include <memory>
77 #include "mathmlexport.hxx"
78 #include <starmath.hrc>
79 #include <unomodel.hxx>
80 #include <document.hxx>
81 #include <utility.hxx>
83 using namespace ::com::sun::star::beans;
84 using namespace ::com::sun::star::container;
85 using namespace ::com::sun::star::document;
86 using namespace ::com::sun::star::lang;
87 using namespace ::com::sun::star::uno;
88 using namespace ::com::sun::star;
89 using namespace ::xmloff::token;
91 using ::rtl::OUString;
92 using ::rtl::OUStringBuffer;
94 #define EXPORT_SVC_NAME RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.XMLExportFilter")
96 #undef WANTEXCEPT
99 ////////////////////////////////////////////////////////////
101 sal_Bool SmXMLExportWrapper::Export(SfxMedium &rMedium)
103 sal_Bool bRet=sal_True;
104 uno::Reference<lang::XMultiServiceFactory>
105 xServiceFactory(utl::getProcessServiceFactory());
106 DBG_ASSERT(xServiceFactory.is(),"got no service manager");
108 //Get model
109 uno::Reference< lang::XComponent > xModelComp(xModel, uno::UNO_QUERY );
111 sal_Bool bEmbedded = sal_False;
112 uno::Reference <lang::XUnoTunnel> xTunnel;
113 xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY);
114 SmModel *pModel = reinterpret_cast<SmModel *>
115 (xTunnel->getSomething(SmModel::getUnoTunnelId()));
117 SmDocShell *pDocShell = pModel ?
118 static_cast<SmDocShell*>(pModel->GetObjectShell()) : 0;
119 if ( pDocShell &&
120 SFX_CREATE_MODE_EMBEDDED == pDocShell->GetCreateMode() )
121 bEmbedded = sal_True;
123 uno::Reference<task::XStatusIndicator> xStatusIndicator;
124 if (!bEmbedded)
126 if (pDocShell /*&& pDocShell->GetMedium()*/)
128 DBG_ASSERT( pDocShell->GetMedium() == &rMedium,
129 "different SfxMedium found" );
131 SfxItemSet* pSet = rMedium.GetItemSet();
132 if (pSet)
134 const SfxUnoAnyItem* pItem = static_cast<const SfxUnoAnyItem*>(
135 pSet->GetItem(SID_PROGRESS_STATUSBAR_CONTROL) );
136 if (pItem)
137 pItem->GetValue() >>= xStatusIndicator;
141 // set progress range and start status indicator
142 if (xStatusIndicator.is())
144 sal_Int32 nProgressRange = bFlat ? 1 : 3;
145 xStatusIndicator->start(String(SmResId(STR_STATSTR_WRITING)),
146 nProgressRange);
151 // create XPropertySet with three properties for status indicator
152 comphelper::PropertyMapEntry aInfoMap[] =
154 { "UsePrettyPrinting", sizeof("UsePrettyPrinting")-1, 0,
155 &::getBooleanCppuType(),
156 beans::PropertyAttribute::MAYBEVOID, 0},
157 { "BaseURI", sizeof("BaseURI")-1, 0,
158 &::getCppuType( (OUString *)0 ),
159 beans::PropertyAttribute::MAYBEVOID, 0 },
160 { "StreamRelPath", sizeof("StreamRelPath")-1, 0,
161 &::getCppuType( (OUString *)0 ),
162 beans::PropertyAttribute::MAYBEVOID, 0 },
163 { "StreamName", sizeof("StreamName")-1, 0,
164 &::getCppuType( (OUString *)0 ),
165 beans::PropertyAttribute::MAYBEVOID, 0 },
166 { NULL, 0, 0, NULL, 0, 0 }
168 uno::Reference< beans::XPropertySet > xInfoSet(
169 comphelper::GenericPropertySet_CreateInstance(
170 new comphelper::PropertySetInfo( aInfoMap ) ) );
172 SvtSaveOptions aSaveOpt;
173 OUString sUsePrettyPrinting(RTL_CONSTASCII_USTRINGPARAM("UsePrettyPrinting"));
174 sal_Bool bUsePrettyPrinting( bFlat || aSaveOpt.IsPrettyPrinting() );
175 Any aAny;
176 aAny.setValue( &bUsePrettyPrinting, ::getBooleanCppuType() );
177 xInfoSet->setPropertyValue( sUsePrettyPrinting, aAny );
179 // Set base URI
180 OUString sPropName( RTL_CONSTASCII_USTRINGPARAM("BaseURI") );
181 xInfoSet->setPropertyValue( sPropName, makeAny( rMedium.GetBaseURL( true ) ) );
183 sal_Int32 nSteps=0;
184 if (xStatusIndicator.is())
185 xStatusIndicator->setValue(nSteps++);
186 if (!bFlat) //Storage (Package) of Stream
188 uno::Reference < embed::XStorage > xStg = rMedium.GetOutputStorage();
189 sal_Bool bOASIS = ( SotStorage::GetVersion( xStg ) > SOFFICE_FILEFORMAT_60 );
191 // TODO/LATER: handle the case of embedded links gracefully
192 if ( bEmbedded ) //&& !pStg->IsRoot() )
194 OUString aName;
195 if ( rMedium.GetItemSet() )
197 const SfxStringItem* pDocHierarchItem = static_cast<const SfxStringItem*>(
198 rMedium.GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME) );
199 if ( pDocHierarchItem )
200 aName = pDocHierarchItem->GetValue();
203 if ( aName.getLength() )
205 sPropName = OUString(RTL_CONSTASCII_USTRINGPARAM("StreamRelPath"));
206 xInfoSet->setPropertyValue( sPropName, makeAny( aName ) );
210 if ( !bEmbedded )
212 if (xStatusIndicator.is())
213 xStatusIndicator->setValue(nSteps++);
215 bRet = WriteThroughComponent(
216 xStg, xModelComp, "meta.xml", xServiceFactory, xInfoSet,
217 (bOASIS ? "com.sun.star.comp.Math.XMLOasisMetaExporter"
218 : "com.sun.star.comp.Math.XMLMetaExporter"),
219 sal_False);
221 if ( bRet )
223 if (xStatusIndicator.is())
224 xStatusIndicator->setValue(nSteps++);
226 bRet = WriteThroughComponent(
227 xStg, xModelComp, "content.xml", xServiceFactory, xInfoSet,
228 "com.sun.star.comp.Math.XMLContentExporter");
231 if ( bRet )
233 if (xStatusIndicator.is())
234 xStatusIndicator->setValue(nSteps++);
236 bRet = WriteThroughComponent(
237 xStg, xModelComp, "settings.xml", xServiceFactory, xInfoSet,
238 (bOASIS ? "com.sun.star.comp.Math.XMLOasisSettingsExporter"
239 : "com.sun.star.comp.Math.XMLSettingsExporter") );
242 else
244 SvStream *pStream = rMedium.GetOutStream();
245 uno::Reference<io::XOutputStream> xOut(
246 new utl::OOutputStreamWrapper(*pStream) );
248 if (xStatusIndicator.is())
249 xStatusIndicator->setValue(nSteps++);
251 bRet = WriteThroughComponent(
252 xOut, xModelComp, xServiceFactory, xInfoSet,
253 "com.sun.star.comp.Math.XMLContentExporter");
256 if (xStatusIndicator.is())
257 xStatusIndicator->end();
259 return bRet;
263 /// export through an XML exporter component (output stream version)
264 sal_Bool SmXMLExportWrapper::WriteThroughComponent(
265 Reference<io::XOutputStream> xOutputStream,
266 Reference<XComponent> xComponent,
267 Reference<lang::XMultiServiceFactory> & rFactory,
268 Reference<beans::XPropertySet> & rPropSet,
269 const sal_Char* pComponentName )
271 DBG_ASSERT(xOutputStream.is(), "I really need an output stream!");
272 DBG_ASSERT(xComponent.is(), "Need component!");
273 DBG_ASSERT(NULL != pComponentName, "Need component name!");
275 // get component
276 Reference< io::XActiveDataSource > xSaxWriter(
277 rFactory->createInstance(
278 OUString::createFromAscii("com.sun.star.xml.sax.Writer") ),
279 UNO_QUERY );
280 DBG_ASSERT( xSaxWriter.is(), "can't instantiate XML writer" );
281 if (!xSaxWriter.is())
282 return sal_False;
284 // connect XML writer to output stream
285 xSaxWriter->setOutputStream( xOutputStream );
287 // prepare arguments (prepend doc handler to given arguments)
288 Reference<xml::sax::XDocumentHandler> xDocHandler( xSaxWriter,UNO_QUERY);
290 Sequence<Any> aArgs( 2 );
291 aArgs[0] <<= xDocHandler;
292 aArgs[1] <<= rPropSet;
294 // get filter component
295 Reference< document::XExporter > xExporter(
296 rFactory->createInstanceWithArguments(
297 OUString::createFromAscii(pComponentName), aArgs), UNO_QUERY);
298 DBG_ASSERT( xExporter.is(),
299 "can't instantiate export filter component" );
300 if ( !xExporter.is() )
301 return sal_False;
304 // connect model and filter
305 xExporter->setSourceDocument( xComponent );
307 // filter!
308 Reference < XFilter > xFilter( xExporter, UNO_QUERY );
309 uno::Sequence< PropertyValue > aProps(0);
310 xFilter->filter( aProps );
312 uno::Reference<lang::XUnoTunnel> xFilterTunnel;
313 xFilterTunnel = uno::Reference<lang::XUnoTunnel>
314 ( xFilter, uno::UNO_QUERY );
315 SmXMLExport *pFilter = reinterpret_cast< SmXMLExport * >(
316 sal::static_int_cast< sal_uIntPtr >(
317 xFilterTunnel->getSomething( SmXMLExport::getUnoTunnelId() )));
318 return pFilter ? pFilter->GetSuccess() : sal_True;
322 /// export through an XML exporter component (storage version)
323 sal_Bool SmXMLExportWrapper::WriteThroughComponent(
324 const Reference < embed::XStorage >& xStorage,
325 Reference<XComponent> xComponent,
326 const sal_Char* pStreamName,
327 Reference<lang::XMultiServiceFactory> & rFactory,
328 Reference<beans::XPropertySet> & rPropSet,
329 const sal_Char* pComponentName,
330 sal_Bool bCompress
333 DBG_ASSERT(xStorage.is(), "Need storage!");
334 DBG_ASSERT(NULL != pStreamName, "Need stream name!");
336 // open stream
337 Reference < io::XStream > xStream;
338 OUString sStreamName = OUString::createFromAscii(pStreamName);
341 xStream = xStorage->openStreamElement( sStreamName,
342 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
344 catch ( uno::Exception& )
346 DBG_ERROR( "Can't create output stream in package!" );
347 return sal_False;
350 String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) );
351 OUString aMime( RTL_CONSTASCII_USTRINGPARAM("text/xml") );
352 uno::Any aAny;
353 aAny <<= aMime;
355 uno::Reference < beans::XPropertySet > xSet( xStream, uno::UNO_QUERY );
356 xSet->setPropertyValue( aPropName, aAny );
358 if ( !bCompress )
360 aPropName = String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("Compressed") );
361 sal_Bool bFalse = sal_False;
362 aAny.setValue( &bFalse, ::getBooleanCppuType() );
363 xSet->setPropertyValue( aPropName, aAny );
366 // even plain stream must be encrypted in encrypted document
367 OUString aTmpPropName( RTL_CONSTASCII_USTRINGPARAM("UseCommonStoragePasswordEncryption") );
368 sal_Bool bTrue = sal_True;
369 aAny.setValue( &bTrue, ::getBooleanCppuType() );
370 xSet->setPropertyValue( aTmpPropName, aAny );
372 // set Base URL
373 if ( rPropSet.is() )
375 OUString sPropName( RTL_CONSTASCII_USTRINGPARAM("StreamName") );
376 rPropSet->setPropertyValue( sPropName, makeAny( sStreamName ) );
379 // write the stuff
380 sal_Bool bRet = WriteThroughComponent( xStream->getOutputStream(), xComponent, rFactory,
381 rPropSet, pComponentName );
383 // stream is closed by SAX parser
384 //if ( bRet )
385 // xStream->getOutputStream()->closeOutput();
387 return bRet;
390 ////////////////////////////////////////////////////////////
392 // #110680#
393 SmXMLExport::SmXMLExport(
394 const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory,
395 sal_uInt16 nExportFlags)
396 : SvXMLExport( xServiceFactory, MAP_INCH, XML_MATH, nExportFlags ) ,
397 pTree(0) ,
398 bSuccess(sal_False)
402 sal_Int64 SAL_CALL SmXMLExport::getSomething(
403 const uno::Sequence< sal_Int8 >& rId )
404 throw(uno::RuntimeException)
406 if ( rId.getLength() == 16 &&
407 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
408 rId.getConstArray(), 16 ) )
409 return sal::static_int_cast< sal_Int64 >(reinterpret_cast< sal_uIntPtr >(this));
411 return SvXMLExport::getSomething( rId );
414 const uno::Sequence< sal_Int8 > & SmXMLExport::getUnoTunnelId() throw()
416 static uno::Sequence< sal_Int8 > * pSeq = 0;
417 if ( !pSeq )
419 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
420 if ( !pSeq )
422 static uno::Sequence< sal_Int8 > aSeq( 16 );
423 rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
424 pSeq = &aSeq;
427 return *pSeq;
430 OUString SAL_CALL SmXMLExport_getImplementationName() throw()
432 return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLExporter" ) );
435 uno::Sequence< OUString > SAL_CALL SmXMLExport_getSupportedServiceNames()
436 throw()
438 const OUString aServiceName( EXPORT_SVC_NAME );
439 const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
440 return aSeq;
443 uno::Reference< uno::XInterface > SAL_CALL SmXMLExport_createInstance(
444 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
445 throw( uno::Exception )
447 // #110680#
448 // return (cppu::OWeakObject*)new SmXMLExport( EXPORT_ALL );
449 // EXPORT_OASIS is required here allthough there is no differrence between
450 // OOo and OASIS, because without the flag, a transformation to OOo would
451 // be chained in.
452 return (cppu::OWeakObject*)new SmXMLExport( rSMgr, EXPORT_OASIS|EXPORT_ALL );
455 ////////////////////////////////////////////////////////////
457 OUString SAL_CALL SmXMLExportMetaOOO_getImplementationName() throw()
459 return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLMetaExporter" ) );
462 uno::Sequence< OUString > SAL_CALL SmXMLExportMetaOOO_getSupportedServiceNames()
463 throw()
465 const OUString aServiceName( EXPORT_SVC_NAME );
466 const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
467 return aSeq;
470 uno::Reference< uno::XInterface > SAL_CALL SmXMLExportMetaOOO_createInstance(
471 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
472 throw( uno::Exception )
474 // #110680#
475 // return (cppu::OWeakObject*)new SmXMLExport( EXPORT_META );
476 return (cppu::OWeakObject*)new SmXMLExport( rSMgr, EXPORT_META );
479 ////////////////////////////////////////////////////////////
481 OUString SAL_CALL SmXMLExportMeta_getImplementationName() throw()
483 return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLOasisMetaExporter" ) );
486 uno::Sequence< OUString > SAL_CALL SmXMLExportMeta_getSupportedServiceNames()
487 throw()
489 const OUString aServiceName( EXPORT_SVC_NAME );
490 const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
491 return aSeq;
494 uno::Reference< uno::XInterface > SAL_CALL SmXMLExportMeta_createInstance(
495 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
496 throw( uno::Exception )
498 // #110680#
499 // return (cppu::OWeakObject*)new SmXMLExport( EXPORT_META );
500 return (cppu::OWeakObject*)new SmXMLExport( rSMgr, EXPORT_OASIS|EXPORT_META );
503 ////////////////////////////////////////////////////////////
505 OUString SAL_CALL SmXMLExportSettingsOOO_getImplementationName() throw()
507 return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLSettingsExporter" ) );
510 uno::Sequence< OUString > SAL_CALL SmXMLExportSettingsOOO_getSupportedServiceNames()
511 throw()
513 const OUString aServiceName( EXPORT_SVC_NAME );
514 const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
515 return aSeq;
518 uno::Reference< uno::XInterface > SAL_CALL SmXMLExportSettingsOOO_createInstance(
519 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
520 throw( uno::Exception )
522 // #110680#
523 // return (cppu::OWeakObject*)new SmXMLExport( EXPORT_SETTINGS );
524 return (cppu::OWeakObject*)new SmXMLExport( rSMgr, EXPORT_SETTINGS );
527 ////////////////////////////////////////////////////////////
529 OUString SAL_CALL SmXMLExportSettings_getImplementationName() throw()
531 return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLOasisSettingsExporter" ) );
534 uno::Sequence< OUString > SAL_CALL SmXMLExportSettings_getSupportedServiceNames()
535 throw()
537 const OUString aServiceName( EXPORT_SVC_NAME );
538 const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
539 return aSeq;
542 uno::Reference< uno::XInterface > SAL_CALL SmXMLExportSettings_createInstance(
543 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
544 throw( uno::Exception )
546 // #110680#
547 // return (cppu::OWeakObject*)new SmXMLExport( EXPORT_SETTINGS );
548 return (cppu::OWeakObject*)new SmXMLExport( rSMgr, EXPORT_OASIS|EXPORT_SETTINGS );
551 ////////////////////////////////////////////////////////////
553 OUString SAL_CALL SmXMLExportContent_getImplementationName() throw()
555 return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLContentExporter" ) );
558 uno::Sequence< OUString > SAL_CALL SmXMLExportContent_getSupportedServiceNames()
559 throw()
561 const OUString aServiceName( EXPORT_SVC_NAME );
562 const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
563 return aSeq;
566 uno::Reference< uno::XInterface > SAL_CALL SmXMLExportContent_createInstance(
567 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
568 throw( uno::Exception )
570 // #110680#
571 // return (cppu::OWeakObject*)new SmXMLExport( EXPORT_CONTENT );
572 // The EXPORT_OASIS flag is only required to avoid that a transformer is
573 // chanied in
574 return (cppu::OWeakObject*)new SmXMLExport( rSMgr, EXPORT_OASIS|EXPORT_CONTENT );
577 ////////////////////////////////////////////////////////////
579 // XServiceInfo
580 // override empty method from parent class
581 rtl::OUString SAL_CALL SmXMLExport::getImplementationName()
582 throw(uno::RuntimeException)
584 OUString aTxt;
585 switch( getExportFlags() )
587 case EXPORT_META:
588 aTxt = SmXMLExportMeta_getImplementationName();
589 break;
590 case EXPORT_SETTINGS:
591 aTxt = SmXMLExportSettings_getImplementationName();
592 break;
593 case EXPORT_CONTENT:
594 aTxt = SmXMLExportContent_getImplementationName();
595 break;
596 case EXPORT_ALL:
597 default:
598 aTxt = SmXMLExport_getImplementationName();
599 break;
601 return aTxt;
604 sal_uInt32 SmXMLExport::exportDoc(enum XMLTokenEnum eClass)
606 if ( (getExportFlags() & EXPORT_CONTENT) == 0 )
608 SvXMLExport::exportDoc( eClass );
610 else
612 uno::Reference <frame::XModel> xModel = GetModel();
613 uno::Reference <lang::XUnoTunnel> xTunnel;
614 xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY);
615 SmModel *pModel = reinterpret_cast<SmModel *>
616 (xTunnel->getSomething(SmModel::getUnoTunnelId()));
618 if (pModel)
620 SmDocShell *pDocShell =
621 static_cast<SmDocShell*>(pModel->GetObjectShell());
622 pTree = pDocShell->GetFormulaTree();
623 aText = pDocShell->GetText();
626 GetDocHandler()->startDocument();
628 /*Add xmlns line*/
629 SvXMLAttributeList &rList = GetAttrList();
631 // make use of a default namespace
632 ResetNamespaceMap(); // Math doesn't need namespaces from xmloff, since it now uses default namespaces (because that is common with current MathML usage in the web)
633 _GetNamespaceMap().Add( OUString::createFromAscii(""), GetXMLToken(XML_N_MATH), XML_NAMESPACE_MATH );
635 rList.AddAttribute(GetNamespaceMap().GetAttrNameByKey(XML_NAMESPACE_MATH_IDX),
636 GetNamespaceMap().GetNameByKey( XML_NAMESPACE_MATH_IDX));
638 //I think we need something like ImplExportEntities();
639 _ExportContent();
640 GetDocHandler()->endDocument();
643 bSuccess=sal_True;
644 return 0;
647 void SmXMLExport::_ExportContent()
649 SvXMLElementExport aEquation(*this, XML_NAMESPACE_MATH, XML_MATH, sal_True, sal_True);
650 SvXMLElementExport *pSemantics=0;
652 if (aText.Len())
654 pSemantics = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
655 XML_SEMANTICS, sal_True, sal_True);
658 ExportNodes(pTree, 0);
660 if (aText.Len())
662 // Convert symbol names
663 uno::Reference <frame::XModel> xModel = GetModel();
664 uno::Reference <lang::XUnoTunnel> xTunnel;
665 xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY);
666 SmModel *pModel = reinterpret_cast<SmModel *>
667 (xTunnel->getSomething(SmModel::getUnoTunnelId()));
668 SmDocShell *pDocShell = pModel ?
669 static_cast<SmDocShell*>(pModel->GetObjectShell()) : 0;
670 DBG_ASSERT( pDocShell, "doc shell missing" );
671 if (pDocShell)
673 SmParser &rParser = pDocShell->GetParser();
674 BOOL bVal = rParser.IsExportSymbolNames();
675 rParser.SetExportSymbolNames( TRUE );
676 SmNode *pTmpTree = rParser.Parse( aText );
677 aText = rParser.GetText();
678 delete pTmpTree;
679 rParser.SetExportSymbolNames( bVal );
682 AddAttribute(XML_NAMESPACE_MATH, XML_ENCODING,
683 OUString(RTL_CONSTASCII_USTRINGPARAM("StarMath 5.0")));
684 SvXMLElementExport aAnnotation(*this, XML_NAMESPACE_MATH,
685 XML_ANNOTATION, sal_True, sal_False);
686 GetDocHandler()->characters(OUString( aText ));
688 delete pSemantics;
691 void SmXMLExport::GetViewSettings( Sequence < PropertyValue >& aProps)
693 uno::Reference <frame::XModel> xModel = GetModel();
694 if ( !xModel.is() )
695 return;
697 uno::Reference <lang::XUnoTunnel> xTunnel;
698 xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY);
699 SmModel *pModel = reinterpret_cast<SmModel *>
700 (xTunnel->getSomething(SmModel::getUnoTunnelId()));
702 if ( !pModel )
703 return;
705 SmDocShell *pDocShell =
706 static_cast<SmDocShell*>(pModel->GetObjectShell());
707 if ( !pDocShell )
708 return;
710 aProps.realloc( 4 );
711 PropertyValue *pValue = aProps.getArray();
712 sal_Int32 nIndex = 0;
714 Rectangle aRect( pDocShell->GetVisArea() );
716 pValue[nIndex].Name = OUString( RTL_CONSTASCII_USTRINGPARAM ( "ViewAreaTop") );
717 pValue[nIndex++].Value <<= aRect.Top();
719 pValue[nIndex].Name = OUString( RTL_CONSTASCII_USTRINGPARAM ( "ViewAreaLeft") );
720 pValue[nIndex++].Value <<= aRect.Left();
722 pValue[nIndex].Name = OUString( RTL_CONSTASCII_USTRINGPARAM ( "ViewAreaWidth") );
723 pValue[nIndex++].Value <<= aRect.GetWidth();
725 pValue[nIndex].Name = OUString( RTL_CONSTASCII_USTRINGPARAM ( "ViewAreaHeight") );
726 pValue[nIndex++].Value <<= aRect.GetHeight();
729 void SmXMLExport::GetConfigurationSettings( Sequence < PropertyValue > & rProps)
731 Reference < XPropertySet > xProps ( GetModel(), UNO_QUERY );
732 if ( xProps.is() )
734 Reference< XPropertySetInfo > xPropertySetInfo = xProps->getPropertySetInfo();
735 if (xPropertySetInfo.is())
737 Sequence< Property > aProps = xPropertySetInfo->getProperties();
738 sal_Int32 nCount(aProps.getLength());
739 if (nCount > 0)
741 rProps.realloc(nCount);
742 PropertyValue* pProps = rProps.getArray();
743 if (pProps)
745 const OUString sFormula ( RTL_CONSTASCII_USTRINGPARAM ( "Formula" ) );
746 const OUString sBasicLibraries ( RTL_CONSTASCII_USTRINGPARAM ( "BasicLibraries" ) );
747 const OUString sDialogLibraries ( RTL_CONSTASCII_USTRINGPARAM ( "DialogLibraries" ) );
748 const OUString sRuntimeUID ( RTL_CONSTASCII_USTRINGPARAM ( "RuntimeUID" ) );
749 for (sal_Int32 i = 0; i < nCount; i++, pProps++)
751 const OUString &rPropName = aProps[i].Name;
752 if (rPropName != sFormula &&
753 rPropName != sBasicLibraries &&
754 rPropName != sDialogLibraries &&
755 rPropName != sRuntimeUID)
757 pProps->Name = rPropName;
758 pProps->Value = xProps->getPropertyValue(rPropName);
767 void SmXMLExport::ExportLine(const SmNode *pNode, int nLevel)
769 ExportExpression(pNode, nLevel);
772 void SmXMLExport::ExportBinaryHorizontal(const SmNode *pNode, int nLevel)
774 ExportExpression(pNode, nLevel);
777 void SmXMLExport::ExportUnaryHorizontal(const SmNode *pNode, int nLevel)
779 ExportExpression(pNode, nLevel);
782 void SmXMLExport::ExportExpression(const SmNode *pNode, int nLevel)
784 SvXMLElementExport *pRow=0;
785 ULONG nSize = pNode->GetNumSubNodes();
787 if (nSize > 1)
788 pRow = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MROW, sal_True, sal_True);
790 //if (nSize)
792 for (USHORT i = 0; i < nSize; i++)
793 if (const SmNode *pTemp = pNode->GetSubNode(i))
794 ExportNodes(pTemp, nLevel+1);
796 #if 0
797 else
799 //This saves us from situations like "a newline" where the
800 //lack of a term following the newline would otherwise create
801 //a incorrect token like <mtr/>
802 SvXMLElementExport aDummy(*this, XML_NAMESPACE_MATH, XML_MI, sal_True, sal_False);
803 sal_Unicode nArse[2] = {'\n','\0'};
804 GetDocHandler()->characters(nArse);
806 #endif
808 delete pRow;
811 void SmXMLExport::ExportBinaryVertical(const SmNode *pNode, int nLevel)
813 DBG_ASSERT(pNode->GetNumSubNodes()==3,"Bad Fraction");
814 SvXMLElementExport aFraction(*this, XML_NAMESPACE_MATH, XML_MFRAC, sal_True, sal_True);
815 ExportNodes(pNode->GetSubNode(0), nLevel);
816 ExportNodes(pNode->GetSubNode(2), nLevel);
819 void SmXMLExport::ExportTable(const SmNode *pNode, int nLevel)
821 SvXMLElementExport *pTable=0;
823 USHORT nSize = pNode->GetNumSubNodes();
825 //If the list ends in newline then the last entry has
826 //no subnodes, the newline is superfulous so we just drop
827 //the last node, inclusion would create a bad MathML
828 //table
829 if (nSize >= 1 && pNode->GetSubNode(nSize-1)->GetNumSubNodes() == 0)
830 --nSize;
832 // try to avoid creating a mtable element when the formula consists only
833 // of a single output line
834 if (nLevel || (nSize >1))
835 pTable = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTABLE, sal_True, sal_True);
837 for (USHORT i = 0; i < nSize; i++)
838 if (const SmNode *pTemp = pNode->GetSubNode(i))
840 SvXMLElementExport *pRow=0;
841 SvXMLElementExport *pCell=0;
842 if (pTable)
844 pRow = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTR, sal_True, sal_True);
845 pCell = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTD, sal_True, sal_True);
847 ExportNodes(pTemp, nLevel+1);
848 delete pCell;
849 delete pRow;
852 delete pTable;
855 void SmXMLExport::ExportMath(const SmNode *pNode, int /*nLevel*/)
857 const SmMathSymbolNode *pTemp = static_cast<const SmMathSymbolNode *>(pNode);
858 SvXMLElementExport aMath(*this, XML_NAMESPACE_MATH, XML_MO, sal_True, sal_False);
859 sal_Unicode nArse[2];
860 nArse[0] = pTemp->GetText().GetChar(0);
861 sal_Unicode cTmp = ConvertMathToMathML( nArse[0] );
862 if (cTmp != 0)
863 nArse[0] = cTmp;
864 DBG_ASSERT(nArse[0] != 0xffff,"Non existant symbol");
865 nArse[1] = 0;
866 GetDocHandler()->characters(nArse);
869 void SmXMLExport::ExportText(const SmNode *pNode, int /*nLevel*/)
871 SvXMLElementExport *pText;
872 const SmTextNode *pTemp = static_cast<const SmTextNode *>(pNode);
873 switch (pNode->GetToken().eType)
875 default:
876 case TIDENT:
878 //Note that we change the fontstyle to italic for strings that
879 //are italic and longer than a single character.
880 sal_Bool bIsItalic = IsItalic( pTemp->GetFont() );
881 if ((pTemp->GetText().Len() > 1) && bIsItalic)
882 AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, XML_ITALIC);
883 else if ((pTemp->GetText().Len() == 1) && !bIsItalic)
884 AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, XML_NORMAL);
885 pText = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MI,sal_True,sal_False);
886 break;
888 case TNUMBER:
889 pText = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MN,sal_True,sal_False);
890 break;
891 case TTEXT:
892 pText = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTEXT,sal_True,sal_False);
893 break;
895 GetDocHandler()->characters(OUString(pTemp->GetText().GetBuffer()));
896 delete pText;
899 void SmXMLExport::ExportBlank(const SmNode * /*pNode*/, int /*nLevel*/)
901 //!! exports an empty <mi> tag since for example "~_~" is allowed in
902 //!! Math (so it has no sense at all) but must not result in an empty
903 //!! <msub> tag in MathML !!
905 SvXMLElementExport *pText;
906 //const SmBlankNode *pTemp = static_cast<const SmBlankNode *>(pNode);
908 pText = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MI, sal_True, sal_False);
910 GetDocHandler()->characters( OUString() );
911 delete pText;
914 void SmXMLExport::ExportSubSupScript(const SmNode *pNode, int nLevel)
916 const SmNode *pSub = 0;
917 const SmNode *pSup = 0;
918 const SmNode *pCSub = 0;
919 const SmNode *pCSup = 0;
920 const SmNode *pLSub = 0;
921 const SmNode *pLSup = 0;
922 SvXMLElementExport *pThing = 0, *pThing2 = 0;
924 //if we have prescripts at all then we must use the tensor notation
926 //This is one of those excellent locations where scope is vital to
927 //arrange the construction and destruction of the element helper
928 //classes correctly
929 pLSub = pNode->GetSubNode(LSUB+1);
930 pLSup = pNode->GetSubNode(LSUP+1);
931 if (pLSub || pLSup)
933 SvXMLElementExport aMultiScripts(*this, XML_NAMESPACE_MATH,
934 XML_MMULTISCRIPTS, sal_True, sal_True);
937 if (NULL != (pCSub = pNode->GetSubNode(CSUB+1))
938 && NULL != (pCSup = pNode->GetSubNode(CSUP+1)))
940 pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
941 XML_MUNDEROVER, sal_True,sal_True);
943 else if (NULL != (pCSub = pNode->GetSubNode(CSUB+1)))
945 pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
946 XML_MUNDER, sal_True,sal_True);
948 else if (NULL != (pCSup = pNode->GetSubNode(CSUP+1)))
950 pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
951 XML_MOVER, sal_True,sal_True);
954 ExportNodes(pNode->GetSubNode(0), nLevel+1); //Main Term
956 if (pCSub)
957 ExportNodes(pCSub, nLevel+1);
958 if (pCSup)
959 ExportNodes(pCSup, nLevel+1);
960 delete pThing2;
962 pSub = pNode->GetSubNode(RSUB+1);
963 pSup = pNode->GetSubNode(RSUP+1);
964 if (pSub || pSup)
966 if (pSub)
967 ExportNodes(pSub, nLevel+1);
968 else
970 SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE,sal_True,sal_True);
972 if (pSup)
973 ExportNodes(pSup, nLevel+1);
974 else
976 SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE,sal_True,sal_True);
980 //Seperator element between suffix and prefix sub/sup pairs
982 SvXMLElementExport aPrescripts(*this, XML_NAMESPACE_MATH,
983 XML_MPRESCRIPTS, sal_True,sal_True);
986 if (pLSub)
987 ExportNodes(pLSub, nLevel+1);
988 else
990 SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE,
991 sal_True,sal_True);
994 if (pLSup)
995 ExportNodes(pLSup, nLevel+1);
996 else
998 SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE,
999 sal_True,sal_True);
1003 else
1005 if (NULL != (pSub = pNode->GetSubNode(RSUB+1)) &&
1006 NULL != (pSup = pNode->GetSubNode(RSUP+1)))
1008 pThing = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
1009 XML_MSUBSUP, sal_True,sal_True);
1011 else if (NULL != (pSub = pNode->GetSubNode(RSUB+1)))
1013 pThing = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MSUB,
1014 sal_True,sal_True);
1016 else if (NULL != (pSup = pNode->GetSubNode(RSUP+1)))
1018 pThing = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MSUP,
1019 sal_True,sal_True);
1022 if (NULL != (pCSub = pNode->GetSubNode(CSUB+1))
1023 && NULL != (pCSup=pNode->GetSubNode(CSUP+1)))
1025 pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
1026 XML_MUNDEROVER, sal_True,sal_True);
1028 else if (NULL != (pCSub = pNode->GetSubNode(CSUB+1)))
1030 pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
1031 XML_MUNDER, sal_True,sal_True);
1033 else if (NULL != (pCSup = pNode->GetSubNode(CSUP+1)))
1035 pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
1036 XML_MOVER, sal_True,sal_True);
1038 ExportNodes(pNode->GetSubNode(0), nLevel+1); //Main Term
1040 if (pCSub)
1041 ExportNodes(pCSub, nLevel+1);
1042 if (pCSup)
1043 ExportNodes(pCSup, nLevel+1);
1044 delete pThing2;
1046 if (pSub)
1047 ExportNodes(pSub, nLevel+1);
1048 if (pSup)
1049 ExportNodes(pSup, nLevel+1);
1050 delete pThing;
1054 void SmXMLExport::ExportBrace(const SmNode *pNode, int nLevel)
1056 const SmNode *pTemp;
1057 const SmNode *pLeft=pNode->GetSubNode(0);
1058 const SmNode *pRight=pNode->GetSubNode(2);
1059 SvXMLElementExport *pFences=0,*pRow=0;
1060 if ( ((pLeft) && (pLeft->GetToken().eType != TNONE)) &&
1061 ((pRight) && (pRight->GetToken().eType != TNONE)) &&
1062 (pNode->GetScaleMode() == SCALE_HEIGHT))
1064 sal_Unicode nArse[2];
1065 nArse[1] = 0;
1066 nArse[0] = static_cast<
1067 const SmMathSymbolNode* >(pLeft)->GetText().GetChar(0);
1068 DBG_ASSERT(nArse[0] != 0xffff,"Non existant symbol");
1069 AddAttribute(XML_NAMESPACE_MATH, XML_OPEN,nArse);
1070 nArse[0] = static_cast<
1071 const SmMathSymbolNode* >(pRight)->GetText().GetChar(0);
1072 DBG_ASSERT(nArse[0] != 0xffff,"Non existant symbol");
1073 AddAttribute(XML_NAMESPACE_MATH, XML_CLOSE,nArse);
1074 pFences = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MFENCED,
1075 sal_True,sal_True);
1077 else if (pLeft && (pLeft->GetToken().eType != TNONE))
1079 pRow = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MROW,
1080 sal_True, sal_True);
1081 if (pNode->GetScaleMode() == SCALE_HEIGHT)
1082 AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_TRUE);
1083 else
1084 AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_FALSE);
1085 ExportNodes(pLeft, nLevel+1);
1087 else
1088 pRow = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MROW,
1089 sal_True, sal_True);
1091 if (NULL != (pTemp = pNode->GetSubNode(1)))
1092 ExportNodes(pTemp, nLevel+1);
1093 if (pFences)
1094 delete pFences;
1095 else if (pRight && (pRight->GetToken().eType != TNONE))
1097 if (pNode->GetScaleMode() == SCALE_HEIGHT)
1098 AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_TRUE);
1099 else
1100 AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_FALSE);
1101 ExportNodes(pRight, nLevel+1);
1103 delete pRow;
1106 void SmXMLExport::ExportRoot(const SmNode *pNode, int nLevel)
1108 if (pNode->GetSubNode(0))
1110 SvXMLElementExport aRoot(*this, XML_NAMESPACE_MATH, XML_MROOT,sal_True,
1111 sal_True);
1112 ExportNodes(pNode->GetSubNode(2), nLevel+1);
1113 ExportNodes(pNode->GetSubNode(0), nLevel+1);
1115 else
1117 SvXMLElementExport aSqrt(*this, XML_NAMESPACE_MATH, XML_MSQRT,sal_True,
1118 sal_True);
1119 ExportNodes(pNode->GetSubNode(2), nLevel+1);
1123 void SmXMLExport::ExportOperator(const SmNode *pNode, int nLevel)
1125 /*we need to either use content or font and size attributes
1126 *here*/
1127 #if 0
1129 SvXMLElementExport aMath(*this, XML_NAMESPACE_MATH, XML_MO,
1130 sal_True,sal_False);
1131 SmTextNode *pTemp = (SmTextNode *)pNode->GetSubNode(0);
1132 GetDocHandler()->characters(pTemp->GetText());
1134 #endif
1135 SvXMLElementExport aRow(*this, XML_NAMESPACE_MATH, XML_MROW,
1136 sal_True, sal_True);
1137 ExportNodes(pNode->GetSubNode(0), nLevel+1);
1138 ExportNodes(pNode->GetSubNode(1), nLevel+1);
1141 void SmXMLExport::ExportAttributes(const SmNode *pNode, int nLevel)
1143 SvXMLElementExport *pElement=0;
1145 if (pNode->GetToken().eType == TUNDERLINE)
1147 AddAttribute(XML_NAMESPACE_MATH, XML_ACCENTUNDER,
1148 XML_TRUE);
1149 pElement = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MUNDER,
1150 sal_True,sal_True);
1152 else if (pNode->GetToken().eType != TOVERSTRIKE)
1154 AddAttribute(XML_NAMESPACE_MATH, XML_ACCENT,
1155 XML_TRUE);
1156 pElement = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MOVER,
1157 sal_True,sal_True);
1160 ExportNodes(pNode->GetSubNode(1), nLevel+1);
1161 switch (pNode->GetToken().eType)
1163 case TOVERLINE:
1165 //proper entity support required
1166 SvXMLElementExport aMath(*this, XML_NAMESPACE_MATH, XML_MO,
1167 sal_True,sal_True);
1168 #if 0
1169 GetDocHandler()->characters(
1170 OUString(RTL_CONSTASCII_USTRINGPARAM("&overbar;")));
1171 #else
1172 sal_Unicode nArse[2] = {0xAF,0x00};
1173 #endif
1174 GetDocHandler()->characters(nArse);
1176 break;
1177 case TUNDERLINE:
1179 //proper entity support required
1180 SvXMLElementExport aMath(*this, XML_NAMESPACE_MATH, XML_MO,
1181 sal_True,sal_True);
1182 #if 0
1183 GetDocHandler()->characters(
1184 OUString(RTL_CONSTASCII_USTRINGPARAM("&underbar;")));
1185 #else
1186 sal_Unicode nArse[2] = {0x0332,0x00};
1187 #endif
1188 GetDocHandler()->characters(nArse);
1190 break;
1191 case TOVERSTRIKE:
1192 break;
1193 default:
1194 ExportNodes(pNode->GetSubNode(0), nLevel+1);
1195 break;
1197 delete pElement;
1200 static bool lcl_HasEffectOnMathvariant( const SmTokenType eType )
1202 return eType == TBOLD || eType == TNBOLD ||
1203 eType == TITALIC || eType == TNBOLD ||
1204 eType == TSANS || eType == TSERIF || eType == TFIXED;
1207 void SmXMLExport::ExportFont(const SmNode *pNode, int nLevel)
1209 SvXMLElementExport *pElement = 0;
1212 // gather the mathvariant attribut relevant data from all
1213 // successively following SmFontNodes...
1215 int nBold = -1; // for the following variables: -1 = yet undefined; 0 = false; 1 = true;
1216 int nItalic = -1; // for the following variables: -1 = yet undefined; 0 = false; 1 = true;
1217 int nSansSerifFixed = -1;
1218 SmTokenType eNodeType = TUNKNOWN;
1219 while (lcl_HasEffectOnMathvariant( (eNodeType = pNode->GetToken().eType) ))
1221 switch (eNodeType)
1223 case TBOLD : nBold = 1; break;
1224 case TNBOLD : nBold = 0; break;
1225 case TITALIC : nItalic = 1; break;
1226 case TNITALIC : nItalic = 0; break;
1227 case TSANS : nSansSerifFixed = 0; break;
1228 case TSERIF : nSansSerifFixed = 1; break;
1229 case TFIXED : nSansSerifFixed = 2; break;
1230 default:
1231 DBG_ASSERT( 0, "unexpected case" );
1233 // According to the parser every node that is to be evaluated heres
1234 // has a single non-zero subnode at index 1!! Thus we only need to check
1235 // that single node for follow-up nodes that have an effect on the attribute.
1236 if (pNode->GetNumSubNodes() > 1 && pNode->GetSubNode(1) &&
1237 lcl_HasEffectOnMathvariant( pNode->GetSubNode(1)->GetToken().eType))
1239 pNode = pNode->GetSubNode(1);
1241 else
1242 break;
1245 switch (pNode->GetToken().eType)
1247 //wrap a phantom element around everything*/
1248 case TPHANTOM:
1249 pElement = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
1250 XML_MPHANTOM, sal_True,sal_True);
1251 break;
1252 case TBLACK:
1253 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_BLACK);
1254 break;
1255 case TWHITE:
1256 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_WHITE);
1257 break;
1258 case TRED:
1259 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_RED);
1260 break;
1261 case TGREEN:
1262 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_GREEN);
1263 break;
1264 case TBLUE:
1265 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_BLUE);
1266 break;
1267 case TCYAN:
1268 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_AQUA);
1269 break;
1270 case TMAGENTA:
1271 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_FUCHSIA);
1272 break;
1273 case TYELLOW:
1274 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_YELLOW);
1275 break;
1276 case TSIZE:
1278 const SmFontNode *pFontNode = static_cast<const SmFontNode *>(pNode);
1279 const Fraction &aFrac = pFontNode->GetSizeParameter();
1281 OUStringBuffer sStrBuf;
1282 switch(pFontNode->GetSizeType())
1284 case FNTSIZ_MULTIPLY:
1285 SvXMLUnitConverter::convertDouble(sStrBuf,
1286 static_cast<double>(aFrac*Fraction(100.00)));
1287 sStrBuf.append(static_cast<sal_Unicode>('%'));
1288 break;
1289 case FNTSIZ_DIVIDE:
1290 SvXMLUnitConverter::convertDouble(sStrBuf,
1291 static_cast<double>(Fraction(100.00)/aFrac));
1292 sStrBuf.append(static_cast<sal_Unicode>('%'));
1293 break;
1294 case FNTSIZ_ABSOLUT:
1295 SvXMLUnitConverter::convertDouble(sStrBuf,
1296 static_cast<double>(aFrac));
1297 sStrBuf.append(
1298 GetXMLToken(XML_UNIT_PT));
1299 break;
1300 default:
1302 //The problem here is that the wheels fall off because
1303 //font size is stored in 100th's of a mm not pts, and
1304 //rounding errors take their toll on the original
1305 //value specified in points.
1307 //Must fix StarMath to retain the original pt values
1308 Fraction aTemp = Sm100th_mmToPts(pFontNode->GetFont().
1309 GetSize().Height());
1311 if (pFontNode->GetSizeType() == FNTSIZ_MINUS)
1312 aTemp-=aFrac;
1313 else
1314 aTemp+=aFrac;
1316 double mytest = static_cast<double>(aTemp);
1318 mytest = ::rtl::math::round(mytest,1);
1319 SvXMLUnitConverter::convertDouble(sStrBuf,mytest);
1320 sStrBuf.append(GetXMLToken(XML_UNIT_PT));
1322 break;
1325 OUString sStr(sStrBuf.makeStringAndClear());
1326 AddAttribute(XML_NAMESPACE_MATH, XML_MATHSIZE, sStr);
1328 break;
1329 case TBOLD:
1330 case TITALIC:
1331 case TNBOLD:
1332 case TNITALIC:
1333 case TFIXED:
1334 case TSANS:
1335 case TSERIF:
1337 // nBold: -1 = yet undefined; 0 = false; 1 = true;
1338 // nItalic: -1 = yet undefined; 0 = false; 1 = true;
1339 // nSansSerifFixed: -1 = undefined; 0 = sans; 1 = serif; 2 = fixed;
1340 const sal_Char *pText = "normal";
1341 if (nSansSerifFixed == -1 || nSansSerifFixed == 1)
1343 pText = "normal";
1344 if (nBold == 1 && nItalic != 1)
1345 pText = "bold";
1346 else if (nBold != 1 && nItalic == 1)
1347 pText = "italic";
1348 else if (nBold == 1 && nItalic == 1)
1349 pText = "bold-italic";
1351 else if (nSansSerifFixed == 0)
1353 pText = "sans-serif";
1354 if (nBold == 1 && nItalic != 1)
1355 pText = "bold-sans-serif";
1356 else if (nBold != 1 && nItalic == 1)
1357 pText = "sans-serif-italic";
1358 else if (nBold == 1 && nItalic == 1)
1359 pText = "sans-serif-bold-italic";
1361 else if (nSansSerifFixed == 2)
1362 pText = "monospace"; // no modifiers allowed for monospace ...
1363 else
1365 DBG_ASSERT( 0, "unexpected case" );
1367 AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, A2OU(pText));
1369 break;
1370 default:
1371 break;
1374 #if 0
1375 if (pNode->GetNumSubNodes() > 1) //or in the future is a node that
1376 //cannot take the currently supported
1377 //properties
1378 #endif
1379 //for now we will just always export with a style and not worry about
1380 //anyone else for the moment.
1382 //wrap a style around it
1383 SvXMLElementExport aStyle(*this, XML_NAMESPACE_MATH, XML_MSTYLE, sal_True,sal_True);
1384 ExportExpression(pNode, nLevel);
1386 #if 0
1387 else
1388 ExportNodes(pNode->GetSubNode(0), nLevel+1);
1389 #endif
1391 delete pElement;
1395 void SmXMLExport::ExportVerticalBrace(const SmNode *pNode, int nLevel)
1397 //Place the overbrace value OVER a vertical brace and then place that
1398 //expression OVER the overbrace value, If someone can find a
1399 //dedicated term in MathML to handle this overbrace/underbrace concept
1400 //let me know. C.
1401 XMLTokenEnum which;
1403 switch (pNode->GetToken().eType)
1405 case TOVERBRACE:
1406 default:
1407 which = XML_MOVER;
1408 break;
1409 case TUNDERBRACE:
1410 which = XML_MUNDER;
1411 break;
1414 DBG_ASSERT(pNode->GetNumSubNodes()==3,"Bad Vertical Brace");
1415 SvXMLElementExport aOver1(*this, XML_NAMESPACE_MATH,which, sal_True, sal_True);
1416 {//Scoping
1417 // using accents will draw the over-/underbraces too close to the base
1418 // see http://www.w3.org/TR/MathML2/chapter3.html#id.3.4.5.2
1419 // also XML_ACCENT is illegal with XML_MUNDER. Thus no XML_ACCENT attribut here!
1420 // AddAttribute(XML_NAMESPACE_MATH, XML_ACCENT, XML_TRUE);
1421 SvXMLElementExport aOver2(*this, XML_NAMESPACE_MATH,which, sal_True, sal_True);
1422 ExportNodes(pNode->GetSubNode(0), nLevel);
1423 ExportNodes(pNode->GetSubNode(1), nLevel);
1425 ExportNodes(pNode->GetSubNode(2), nLevel);
1428 void SmXMLExport::ExportMatrix(const SmNode *pNode, int nLevel)
1430 SvXMLElementExport aTable(*this, XML_NAMESPACE_MATH, XML_MTABLE, sal_True, sal_True);
1431 const SmMatrixNode *pMatrix = static_cast<const SmMatrixNode *>(pNode);
1432 USHORT i=0;
1433 for (ULONG y = 0; y < pMatrix->GetNumRows(); y++)
1435 SvXMLElementExport aRow(*this, XML_NAMESPACE_MATH, XML_MTR, sal_True, sal_True);
1436 for (ULONG x = 0; x < pMatrix->GetNumCols(); x++)
1437 if (const SmNode *pTemp = pNode->GetSubNode(i++))
1439 SvXMLElementExport aCell(*this, XML_NAMESPACE_MATH, XML_MTD, sal_True, sal_True);
1440 ExportNodes(pTemp, nLevel+1);
1445 void SmXMLExport::ExportNodes(const SmNode *pNode, int nLevel)
1447 if (!pNode)
1448 return;
1449 switch(pNode->GetType())
1451 case NTABLE:
1452 ExportTable(pNode, nLevel);
1453 break;
1454 case NALIGN:
1455 case NBRACEBODY:
1456 case NEXPRESSION:
1457 ExportExpression(pNode, nLevel);
1458 break;
1459 case NLINE:
1460 ExportLine(pNode, nLevel);
1461 break;
1462 case NTEXT:
1463 ExportText(pNode, nLevel);
1464 break;
1465 case NSPECIAL: //NSPECIAL requires some sort of Entity preservation in the XML engine.
1466 case NGLYPH_SPECIAL:
1467 case NMATH:
1469 sal_Unicode cTmp = 0;
1470 const SmTextNode *pTemp = static_cast< const SmTextNode * >(pNode);
1471 if (pTemp->GetText().Len() > 0)
1472 cTmp = ConvertMathToMathML( pTemp->GetText().GetChar(0) );
1473 if (cTmp == 0)
1475 // no conversion to MathML implemented -> export it as text
1476 // thus at least it will not vanish into nothing
1477 ExportText(pNode, nLevel);
1479 else
1481 //To fully handle generic MathML we need to implement the full
1482 //operator dictionary, we will generate MathML with explicit
1483 //stretchiness for now.
1484 sal_Int16 nLength = GetAttrList().getLength();
1485 sal_Bool bAddStretch=sal_True;
1486 for ( sal_Int16 i = 0; i < nLength; i++ )
1488 OUString sLocalName;
1489 sal_uInt16 nPrefix = GetNamespaceMap().GetKeyByAttrName(
1490 GetAttrList().getNameByIndex(i), &sLocalName );
1492 if ( ( XML_NAMESPACE_MATH == nPrefix ) &&
1493 IsXMLToken(sLocalName, XML_STRETCHY) )
1495 bAddStretch = sal_False;
1496 break;
1499 if (bAddStretch)
1501 AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_FALSE);
1503 ExportMath(pNode, nLevel);
1506 break;
1507 case NPLACE:
1508 ExportMath(pNode, nLevel);
1509 break;
1510 case NBINHOR:
1511 ExportBinaryHorizontal(pNode, nLevel);
1512 break;
1513 case NUNHOR:
1514 ExportUnaryHorizontal(pNode, nLevel);
1515 break;
1516 case NBRACE:
1517 ExportBrace(pNode, nLevel);
1518 break;
1519 case NBINVER:
1520 ExportBinaryVertical(pNode, nLevel);
1521 break;
1522 case NSUBSUP:
1523 ExportSubSupScript(pNode, nLevel);
1524 break;
1525 case NROOT:
1526 ExportRoot(pNode, nLevel);
1527 break;
1528 case NOPER:
1529 ExportOperator(pNode, nLevel);
1530 break;
1531 case NATTRIBUT:
1532 ExportAttributes(pNode, nLevel);
1533 break;
1534 case NFONT:
1535 ExportFont(pNode, nLevel);
1536 break;
1537 case NVERTICAL_BRACE:
1538 ExportVerticalBrace(pNode, nLevel);
1539 break;
1540 case NMATRIX:
1541 ExportMatrix(pNode, nLevel);
1542 break;
1543 case NBLANK:
1544 ExportBlank(pNode, nLevel);
1545 break;
1546 default:
1547 DBG_ASSERT( 0, "Warning: failed to export a node?" );
1548 break;
1550 #if 0
1551 default:
1553 ULONG nSize = pNode->GetNumSubNodes();
1554 for (ULONG i = 0; i < nSize; i++)
1555 if (SmNode *pTemp = pNode->GetSubNode(i))
1556 ExportNodes(pTemp, nLevel+1);
1558 break;
1559 #endif
1563 ////////////////////////////////////////////////////////////