update dev300-m58
[ooovba.git] / starmath / source / mathmlexport.cxx
blob9ddabab9c32597ab2d319841a47066c1ba290749
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: x $
10 * $Revision: 1.00 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_starmath.hxx"
35 Warning: The SvXMLElementExport helper class creates the beginning and
36 closing tags of xml elements in its constructor and destructor, so theres
37 hidden stuff going on, on occasion the ordering of these classes declarations
38 may be significant
42 #include <com/sun/star/xml/sax/XErrorHandler.hpp>
43 #include <com/sun/star/xml/sax/XEntityResolver.hpp>
44 #include <com/sun/star/xml/sax/InputSource.hpp>
45 #include <com/sun/star/xml/sax/XDTDHandler.hpp>
46 #include <com/sun/star/xml/sax/XParser.hpp>
47 #include <com/sun/star/io/XActiveDataSource.hpp>
48 #include <com/sun/star/io/XActiveDataControl.hpp>
49 #include <com/sun/star/document/XDocumentProperties.hpp>
50 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
51 #include <com/sun/star/packages/zip/ZipIOException.hpp>
52 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
53 #include <com/sun/star/beans/PropertyAttribute.hpp>
54 #include <com/sun/star/container/XNameAccess.hpp>
55 #include <com/sun/star/embed/ElementModes.hpp>
56 #include <com/sun/star/uno/Any.h>
58 #include <rtl/math.hxx>
59 #include <sfx2/frame.hxx>
60 #include <sfx2/docfile.hxx>
61 #include <tools/debug.hxx>
62 #include <tools/urlobj.hxx>
63 #include <svtools/sfxecode.hxx>
64 #include <svtools/saveopt.hxx>
65 #include <svtools/stritem.hxx>
66 #include <svtools/itemprop.hxx>
67 #include <unotools/processfactory.hxx>
68 #include <unotools/streamwrap.hxx>
69 #include <xmloff/xmlnmspe.hxx>
70 #include <xmloff/xmltoken.hxx>
71 #include <xmloff/nmspmap.hxx>
72 #include <xmloff/attrlist.hxx>
73 #include <xmloff/xmluconv.hxx>
74 #include <xmloff/xmlmetai.hxx>
75 #include <osl/mutex.hxx>
76 #include <comphelper/genericpropertyset.hxx>
78 #include <memory>
80 #include "mathmlexport.hxx"
81 #include "mathtype.hxx"
82 #include <starmath.hrc>
83 #include <unomodel.hxx>
84 #include <document.hxx>
85 #include <utility.hxx>
87 using namespace ::com::sun::star::beans;
88 using namespace ::com::sun::star::container;
89 using namespace ::com::sun::star::document;
90 using namespace ::com::sun::star::lang;
91 using namespace ::com::sun::star::uno;
92 using namespace ::com::sun::star;
93 using namespace ::xmloff::token;
95 using ::rtl::OUString;
96 using ::rtl::OUStringBuffer;
98 #define EXPORT_SVC_NAME RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.XMLExportFilter")
100 #undef WANTEXCEPT
103 ////////////////////////////////////////////////////////////
105 sal_Bool SmXMLExportWrapper::Export(SfxMedium &rMedium)
107 sal_Bool bRet=sal_True;
108 uno::Reference<lang::XMultiServiceFactory>
109 xServiceFactory(utl::getProcessServiceFactory());
110 DBG_ASSERT(xServiceFactory.is(),"got no service manager");
112 //Get model
113 uno::Reference< lang::XComponent > xModelComp(xModel, uno::UNO_QUERY );
115 sal_Bool bEmbedded = sal_False;
116 uno::Reference <lang::XUnoTunnel> xTunnel;
117 xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY);
118 SmModel *pModel = reinterpret_cast<SmModel *>
119 (xTunnel->getSomething(SmModel::getUnoTunnelId()));
121 SmDocShell *pDocShell = pModel ?
122 static_cast<SmDocShell*>(pModel->GetObjectShell()) : 0;
123 if ( pDocShell &&
124 SFX_CREATE_MODE_EMBEDDED == pDocShell->GetCreateMode() )
125 bEmbedded = sal_True;
127 uno::Reference<task::XStatusIndicator> xStatusIndicator;
128 if (!bEmbedded)
130 if (pDocShell /*&& pDocShell->GetMedium()*/)
132 DBG_ASSERT( pDocShell->GetMedium() == &rMedium,
133 "different SfxMedium found" );
135 SfxItemSet* pSet = rMedium.GetItemSet();
136 if (pSet)
138 const SfxUnoAnyItem* pItem = static_cast<const SfxUnoAnyItem*>(
139 pSet->GetItem(SID_PROGRESS_STATUSBAR_CONTROL) );
140 if (pItem)
141 pItem->GetValue() >>= xStatusIndicator;
145 // set progress range and start status indicator
146 if (xStatusIndicator.is())
148 sal_Int32 nProgressRange = bFlat ? 1 : 3;
149 xStatusIndicator->start(String(SmResId(STR_STATSTR_WRITING)),
150 nProgressRange);
155 // create XPropertySet with three properties for status indicator
156 comphelper::PropertyMapEntry aInfoMap[] =
158 { "UsePrettyPrinting", sizeof("UsePrettyPrinting")-1, 0,
159 &::getBooleanCppuType(),
160 beans::PropertyAttribute::MAYBEVOID, 0},
161 { "BaseURI", sizeof("BaseURI")-1, 0,
162 &::getCppuType( (OUString *)0 ),
163 beans::PropertyAttribute::MAYBEVOID, 0 },
164 { "StreamRelPath", sizeof("StreamRelPath")-1, 0,
165 &::getCppuType( (OUString *)0 ),
166 beans::PropertyAttribute::MAYBEVOID, 0 },
167 { "StreamName", sizeof("StreamName")-1, 0,
168 &::getCppuType( (OUString *)0 ),
169 beans::PropertyAttribute::MAYBEVOID, 0 },
170 { NULL, 0, 0, NULL, 0, 0 }
172 uno::Reference< beans::XPropertySet > xInfoSet(
173 comphelper::GenericPropertySet_CreateInstance(
174 new comphelper::PropertySetInfo( aInfoMap ) ) );
176 SvtSaveOptions aSaveOpt;
177 OUString sUsePrettyPrinting(RTL_CONSTASCII_USTRINGPARAM("UsePrettyPrinting"));
178 sal_Bool bUsePrettyPrinting( bFlat || aSaveOpt.IsPrettyPrinting() );
179 Any aAny;
180 aAny.setValue( &bUsePrettyPrinting, ::getBooleanCppuType() );
181 xInfoSet->setPropertyValue( sUsePrettyPrinting, aAny );
183 // Set base URI
184 OUString sPropName( RTL_CONSTASCII_USTRINGPARAM("BaseURI") );
185 xInfoSet->setPropertyValue( sPropName, makeAny( rMedium.GetBaseURL( true ) ) );
187 sal_Int32 nSteps=0;
188 if (xStatusIndicator.is())
189 xStatusIndicator->setValue(nSteps++);
190 if (!bFlat) //Storage (Package) of Stream
192 uno::Reference < embed::XStorage > xStg = rMedium.GetOutputStorage();
193 sal_Bool bOASIS = ( SotStorage::GetVersion( xStg ) > SOFFICE_FILEFORMAT_60 );
195 // TODO/LATER: handle the case of embedded links gracefully
196 if ( bEmbedded ) //&& !pStg->IsRoot() )
198 OUString aName;
199 if ( rMedium.GetItemSet() )
201 const SfxStringItem* pDocHierarchItem = static_cast<const SfxStringItem*>(
202 rMedium.GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME) );
203 if ( pDocHierarchItem )
204 aName = pDocHierarchItem->GetValue();
207 if ( aName.getLength() )
209 sPropName = OUString(RTL_CONSTASCII_USTRINGPARAM("StreamRelPath"));
210 xInfoSet->setPropertyValue( sPropName, makeAny( aName ) );
214 if ( !bEmbedded )
216 if (xStatusIndicator.is())
217 xStatusIndicator->setValue(nSteps++);
219 bRet = WriteThroughComponent(
220 xStg, xModelComp, "meta.xml", xServiceFactory, xInfoSet,
221 (bOASIS ? "com.sun.star.comp.Math.XMLOasisMetaExporter"
222 : "com.sun.star.comp.Math.XMLMetaExporter"),
223 sal_False);
225 if ( bRet )
227 if (xStatusIndicator.is())
228 xStatusIndicator->setValue(nSteps++);
230 bRet = WriteThroughComponent(
231 xStg, xModelComp, "content.xml", xServiceFactory, xInfoSet,
232 "com.sun.star.comp.Math.XMLContentExporter");
235 if ( bRet )
237 if (xStatusIndicator.is())
238 xStatusIndicator->setValue(nSteps++);
240 bRet = WriteThroughComponent(
241 xStg, xModelComp, "settings.xml", xServiceFactory, xInfoSet,
242 (bOASIS ? "com.sun.star.comp.Math.XMLOasisSettingsExporter"
243 : "com.sun.star.comp.Math.XMLSettingsExporter") );
246 else
248 SvStream *pStream = rMedium.GetOutStream();
249 uno::Reference<io::XOutputStream> xOut(
250 new utl::OOutputStreamWrapper(*pStream) );
252 if (xStatusIndicator.is())
253 xStatusIndicator->setValue(nSteps++);
255 bRet = WriteThroughComponent(
256 xOut, xModelComp, xServiceFactory, xInfoSet,
257 "com.sun.star.comp.Math.XMLContentExporter");
260 if (xStatusIndicator.is())
261 xStatusIndicator->end();
263 return bRet;
267 /// export through an XML exporter component (output stream version)
268 sal_Bool SmXMLExportWrapper::WriteThroughComponent(
269 Reference<io::XOutputStream> xOutputStream,
270 Reference<XComponent> xComponent,
271 Reference<lang::XMultiServiceFactory> & rFactory,
272 Reference<beans::XPropertySet> & rPropSet,
273 const sal_Char* pComponentName )
275 DBG_ASSERT(xOutputStream.is(), "I really need an output stream!");
276 DBG_ASSERT(xComponent.is(), "Need component!");
277 DBG_ASSERT(NULL != pComponentName, "Need component name!");
279 // get component
280 Reference< io::XActiveDataSource > xSaxWriter(
281 rFactory->createInstance(
282 OUString::createFromAscii("com.sun.star.xml.sax.Writer") ),
283 UNO_QUERY );
284 DBG_ASSERT( xSaxWriter.is(), "can't instantiate XML writer" );
285 if (!xSaxWriter.is())
286 return sal_False;
288 // connect XML writer to output stream
289 xSaxWriter->setOutputStream( xOutputStream );
291 // prepare arguments (prepend doc handler to given arguments)
292 Reference<xml::sax::XDocumentHandler> xDocHandler( xSaxWriter,UNO_QUERY);
294 Sequence<Any> aArgs( 2 );
295 aArgs[0] <<= xDocHandler;
296 aArgs[1] <<= rPropSet;
298 // get filter component
299 Reference< document::XExporter > xExporter(
300 rFactory->createInstanceWithArguments(
301 OUString::createFromAscii(pComponentName), aArgs), UNO_QUERY);
302 DBG_ASSERT( xExporter.is(),
303 "can't instantiate export filter component" );
304 if ( !xExporter.is() )
305 return sal_False;
308 // connect model and filter
309 xExporter->setSourceDocument( xComponent );
311 // filter!
312 Reference < XFilter > xFilter( xExporter, UNO_QUERY );
313 uno::Sequence< PropertyValue > aProps(0);
314 xFilter->filter( aProps );
316 uno::Reference<lang::XUnoTunnel> xFilterTunnel;
317 xFilterTunnel = uno::Reference<lang::XUnoTunnel>
318 ( xFilter, uno::UNO_QUERY );
319 SmXMLExport *pFilter = reinterpret_cast< SmXMLExport * >(
320 sal::static_int_cast< sal_uIntPtr >(
321 xFilterTunnel->getSomething( SmXMLExport::getUnoTunnelId() )));
322 return pFilter ? pFilter->GetSuccess() : sal_True;
326 /// export through an XML exporter component (storage version)
327 sal_Bool SmXMLExportWrapper::WriteThroughComponent(
328 const Reference < embed::XStorage >& xStorage,
329 Reference<XComponent> xComponent,
330 const sal_Char* pStreamName,
331 Reference<lang::XMultiServiceFactory> & rFactory,
332 Reference<beans::XPropertySet> & rPropSet,
333 const sal_Char* pComponentName,
334 sal_Bool bCompress
337 DBG_ASSERT(xStorage.is(), "Need storage!");
338 DBG_ASSERT(NULL != pStreamName, "Need stream name!");
340 // open stream
341 Reference < io::XStream > xStream;
342 OUString sStreamName = OUString::createFromAscii(pStreamName);
345 xStream = xStorage->openStreamElement( sStreamName,
346 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
348 catch ( uno::Exception& )
350 DBG_ERROR( "Can't create output stream in package!" );
351 return sal_False;
354 String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) );
355 OUString aMime( RTL_CONSTASCII_USTRINGPARAM("text/xml") );
356 uno::Any aAny;
357 aAny <<= aMime;
359 uno::Reference < beans::XPropertySet > xSet( xStream, uno::UNO_QUERY );
360 xSet->setPropertyValue( aPropName, aAny );
362 if ( !bCompress )
364 aPropName = String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("Compressed") );
365 sal_Bool bFalse = sal_False;
366 aAny.setValue( &bFalse, ::getBooleanCppuType() );
367 xSet->setPropertyValue( aPropName, aAny );
370 // even plain stream must be encrypted in encrypted document
371 OUString aTmpPropName( RTL_CONSTASCII_USTRINGPARAM("UseCommonStoragePasswordEncryption") );
372 sal_Bool bTrue = sal_True;
373 aAny.setValue( &bTrue, ::getBooleanCppuType() );
374 xSet->setPropertyValue( aTmpPropName, aAny );
376 // set Base URL
377 if ( rPropSet.is() )
379 OUString sPropName( RTL_CONSTASCII_USTRINGPARAM("StreamName") );
380 rPropSet->setPropertyValue( sPropName, makeAny( sStreamName ) );
383 // write the stuff
384 sal_Bool bRet = WriteThroughComponent( xStream->getOutputStream(), xComponent, rFactory,
385 rPropSet, pComponentName );
387 // stream is closed by SAX parser
388 //if ( bRet )
389 // xStream->getOutputStream()->closeOutput();
391 return bRet;
394 ////////////////////////////////////////////////////////////
396 // #110680#
397 SmXMLExport::SmXMLExport(
398 const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory,
399 sal_uInt16 nExportFlags)
400 : SvXMLExport( xServiceFactory, MAP_INCH, XML_MATH, nExportFlags ) ,
401 pTree(0) ,
402 bSuccess(sal_False)
406 sal_Int64 SAL_CALL SmXMLExport::getSomething(
407 const uno::Sequence< sal_Int8 >& rId )
408 throw(uno::RuntimeException)
410 if ( rId.getLength() == 16 &&
411 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
412 rId.getConstArray(), 16 ) )
413 return sal::static_int_cast< sal_Int64 >(reinterpret_cast< sal_uIntPtr >(this));
415 return SvXMLExport::getSomething( rId );
418 const uno::Sequence< sal_Int8 > & SmXMLExport::getUnoTunnelId() throw()
420 static uno::Sequence< sal_Int8 > * pSeq = 0;
421 if ( !pSeq )
423 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
424 if ( !pSeq )
426 static uno::Sequence< sal_Int8 > aSeq( 16 );
427 rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
428 pSeq = &aSeq;
431 return *pSeq;
434 OUString SAL_CALL SmXMLExport_getImplementationName() throw()
436 return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLExporter" ) );
439 uno::Sequence< OUString > SAL_CALL SmXMLExport_getSupportedServiceNames()
440 throw()
442 const OUString aServiceName( EXPORT_SVC_NAME );
443 const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
444 return aSeq;
447 uno::Reference< uno::XInterface > SAL_CALL SmXMLExport_createInstance(
448 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
449 throw( uno::Exception )
451 // #110680#
452 // return (cppu::OWeakObject*)new SmXMLExport( EXPORT_ALL );
453 // EXPORT_OASIS is required here allthough there is no differrence between
454 // OOo and OASIS, because without the flag, a transformation to OOo would
455 // be chained in.
456 return (cppu::OWeakObject*)new SmXMLExport( rSMgr, EXPORT_OASIS|EXPORT_ALL );
459 ////////////////////////////////////////////////////////////
461 OUString SAL_CALL SmXMLExportMetaOOO_getImplementationName() throw()
463 return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLMetaExporter" ) );
466 uno::Sequence< OUString > SAL_CALL SmXMLExportMetaOOO_getSupportedServiceNames()
467 throw()
469 const OUString aServiceName( EXPORT_SVC_NAME );
470 const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
471 return aSeq;
474 uno::Reference< uno::XInterface > SAL_CALL SmXMLExportMetaOOO_createInstance(
475 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
476 throw( uno::Exception )
478 // #110680#
479 // return (cppu::OWeakObject*)new SmXMLExport( EXPORT_META );
480 return (cppu::OWeakObject*)new SmXMLExport( rSMgr, EXPORT_META );
483 ////////////////////////////////////////////////////////////
485 OUString SAL_CALL SmXMLExportMeta_getImplementationName() throw()
487 return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLOasisMetaExporter" ) );
490 uno::Sequence< OUString > SAL_CALL SmXMLExportMeta_getSupportedServiceNames()
491 throw()
493 const OUString aServiceName( EXPORT_SVC_NAME );
494 const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
495 return aSeq;
498 uno::Reference< uno::XInterface > SAL_CALL SmXMLExportMeta_createInstance(
499 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
500 throw( uno::Exception )
502 // #110680#
503 // return (cppu::OWeakObject*)new SmXMLExport( EXPORT_META );
504 return (cppu::OWeakObject*)new SmXMLExport( rSMgr, EXPORT_OASIS|EXPORT_META );
507 ////////////////////////////////////////////////////////////
509 OUString SAL_CALL SmXMLExportSettingsOOO_getImplementationName() throw()
511 return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLSettingsExporter" ) );
514 uno::Sequence< OUString > SAL_CALL SmXMLExportSettingsOOO_getSupportedServiceNames()
515 throw()
517 const OUString aServiceName( EXPORT_SVC_NAME );
518 const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
519 return aSeq;
522 uno::Reference< uno::XInterface > SAL_CALL SmXMLExportSettingsOOO_createInstance(
523 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
524 throw( uno::Exception )
526 // #110680#
527 // return (cppu::OWeakObject*)new SmXMLExport( EXPORT_SETTINGS );
528 return (cppu::OWeakObject*)new SmXMLExport( rSMgr, EXPORT_SETTINGS );
531 ////////////////////////////////////////////////////////////
533 OUString SAL_CALL SmXMLExportSettings_getImplementationName() throw()
535 return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLOasisSettingsExporter" ) );
538 uno::Sequence< OUString > SAL_CALL SmXMLExportSettings_getSupportedServiceNames()
539 throw()
541 const OUString aServiceName( EXPORT_SVC_NAME );
542 const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
543 return aSeq;
546 uno::Reference< uno::XInterface > SAL_CALL SmXMLExportSettings_createInstance(
547 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
548 throw( uno::Exception )
550 // #110680#
551 // return (cppu::OWeakObject*)new SmXMLExport( EXPORT_SETTINGS );
552 return (cppu::OWeakObject*)new SmXMLExport( rSMgr, EXPORT_OASIS|EXPORT_SETTINGS );
555 ////////////////////////////////////////////////////////////
557 OUString SAL_CALL SmXMLExportContent_getImplementationName() throw()
559 return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLContentExporter" ) );
562 uno::Sequence< OUString > SAL_CALL SmXMLExportContent_getSupportedServiceNames()
563 throw()
565 const OUString aServiceName( EXPORT_SVC_NAME );
566 const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
567 return aSeq;
570 uno::Reference< uno::XInterface > SAL_CALL SmXMLExportContent_createInstance(
571 const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
572 throw( uno::Exception )
574 // #110680#
575 // return (cppu::OWeakObject*)new SmXMLExport( EXPORT_CONTENT );
576 // The EXPORT_OASIS flag is only required to avoid that a transformer is
577 // chanied in
578 return (cppu::OWeakObject*)new SmXMLExport( rSMgr, EXPORT_OASIS|EXPORT_CONTENT );
581 ////////////////////////////////////////////////////////////
583 // XServiceInfo
584 // override empty method from parent class
585 rtl::OUString SAL_CALL SmXMLExport::getImplementationName()
586 throw(uno::RuntimeException)
588 OUString aTxt;
589 switch( getExportFlags() )
591 case EXPORT_META:
592 aTxt = SmXMLExportMeta_getImplementationName();
593 break;
594 case EXPORT_SETTINGS:
595 aTxt = SmXMLExportSettings_getImplementationName();
596 break;
597 case EXPORT_CONTENT:
598 aTxt = SmXMLExportContent_getImplementationName();
599 break;
600 case EXPORT_ALL:
601 default:
602 aTxt = SmXMLExport_getImplementationName();
603 break;
605 return aTxt;
608 sal_uInt32 SmXMLExport::exportDoc(enum XMLTokenEnum eClass)
610 if ( (getExportFlags() & EXPORT_CONTENT) == 0 )
612 SvXMLExport::exportDoc( eClass );
614 else
616 uno::Reference <frame::XModel> xModel = GetModel();
617 uno::Reference <lang::XUnoTunnel> xTunnel;
618 xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY);
619 SmModel *pModel = reinterpret_cast<SmModel *>
620 (xTunnel->getSomething(SmModel::getUnoTunnelId()));
622 if (pModel)
624 SmDocShell *pDocShell =
625 static_cast<SmDocShell*>(pModel->GetObjectShell());
626 pTree = pDocShell->GetFormulaTree();
627 aText = pDocShell->GetText();
630 GetDocHandler()->startDocument();
632 /*Add xmlns line*/
633 SvXMLAttributeList &rList = GetAttrList();
635 // make use of a default namespace
636 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)
637 _GetNamespaceMap().Add( OUString::createFromAscii(""), GetXMLToken(XML_N_MATH), XML_NAMESPACE_MATH );
639 rList.AddAttribute(GetNamespaceMap().GetAttrNameByKey(XML_NAMESPACE_MATH_IDX),
640 GetNamespaceMap().GetNameByKey( XML_NAMESPACE_MATH_IDX));
642 //I think we need something like ImplExportEntities();
643 _ExportContent();
644 GetDocHandler()->endDocument();
647 bSuccess=sal_True;
648 return 0;
651 void SmXMLExport::_ExportContent()
653 SvXMLElementExport aEquation(*this, XML_NAMESPACE_MATH, XML_MATH, sal_True, sal_True);
654 SvXMLElementExport *pSemantics=0;
656 if (aText.Len())
658 pSemantics = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
659 XML_SEMANTICS, sal_True, sal_True);
662 ExportNodes(pTree, 0);
664 if (aText.Len())
666 // Convert symbol names
667 uno::Reference <frame::XModel> xModel = GetModel();
668 uno::Reference <lang::XUnoTunnel> xTunnel;
669 xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY);
670 SmModel *pModel = reinterpret_cast<SmModel *>
671 (xTunnel->getSomething(SmModel::getUnoTunnelId()));
672 SmDocShell *pDocShell = pModel ?
673 static_cast<SmDocShell*>(pModel->GetObjectShell()) : 0;
674 DBG_ASSERT( pDocShell, "doc shell missing" );
675 if (pDocShell)
677 SmParser &rParser = pDocShell->GetParser();
678 BOOL bVal = rParser.IsExportSymbolNames();
679 rParser.SetExportSymbolNames( TRUE );
680 SmNode *pTmpTree = rParser.Parse( aText );
681 aText = rParser.GetText();
682 delete pTmpTree;
683 rParser.SetExportSymbolNames( bVal );
686 AddAttribute(XML_NAMESPACE_MATH, XML_ENCODING,
687 OUString(RTL_CONSTASCII_USTRINGPARAM("StarMath 5.0")));
688 SvXMLElementExport aAnnotation(*this, XML_NAMESPACE_MATH,
689 XML_ANNOTATION, sal_True, sal_False);
690 GetDocHandler()->characters(OUString( aText ));
692 delete pSemantics;
695 void SmXMLExport::GetViewSettings( Sequence < PropertyValue >& aProps)
697 uno::Reference <frame::XModel> xModel = GetModel();
698 if ( !xModel.is() )
699 return;
701 uno::Reference <lang::XUnoTunnel> xTunnel;
702 xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY);
703 SmModel *pModel = reinterpret_cast<SmModel *>
704 (xTunnel->getSomething(SmModel::getUnoTunnelId()));
706 if ( !pModel )
707 return;
709 SmDocShell *pDocShell =
710 static_cast<SmDocShell*>(pModel->GetObjectShell());
711 if ( !pDocShell )
712 return;
714 aProps.realloc( 4 );
715 PropertyValue *pValue = aProps.getArray();
716 sal_Int32 nIndex = 0;
718 Rectangle aRect( pDocShell->GetVisArea() );
720 pValue[nIndex].Name = OUString( RTL_CONSTASCII_USTRINGPARAM ( "ViewAreaTop") );
721 pValue[nIndex++].Value <<= aRect.Top();
723 pValue[nIndex].Name = OUString( RTL_CONSTASCII_USTRINGPARAM ( "ViewAreaLeft") );
724 pValue[nIndex++].Value <<= aRect.Left();
726 pValue[nIndex].Name = OUString( RTL_CONSTASCII_USTRINGPARAM ( "ViewAreaWidth") );
727 pValue[nIndex++].Value <<= aRect.GetWidth();
729 pValue[nIndex].Name = OUString( RTL_CONSTASCII_USTRINGPARAM ( "ViewAreaHeight") );
730 pValue[nIndex++].Value <<= aRect.GetHeight();
733 void SmXMLExport::GetConfigurationSettings( Sequence < PropertyValue > & rProps)
735 Reference < XPropertySet > xProps ( GetModel(), UNO_QUERY );
736 if ( xProps.is() )
738 Reference< XPropertySetInfo > xPropertySetInfo = xProps->getPropertySetInfo();
739 if (xPropertySetInfo.is())
741 Sequence< Property > aProps = xPropertySetInfo->getProperties();
742 sal_Int32 nCount(aProps.getLength());
743 if (nCount > 0)
745 rProps.realloc(nCount);
746 PropertyValue* pProps = rProps.getArray();
747 if (pProps)
749 const OUString sFormula ( RTL_CONSTASCII_USTRINGPARAM ( "Formula" ) );
750 const OUString sBasicLibraries ( RTL_CONSTASCII_USTRINGPARAM ( "BasicLibraries" ) );
751 const OUString sDialogLibraries ( RTL_CONSTASCII_USTRINGPARAM ( "DialogLibraries" ) );
752 const OUString sRuntimeUID ( RTL_CONSTASCII_USTRINGPARAM ( "RuntimeUID" ) );
753 for (sal_Int32 i = 0; i < nCount; i++, pProps++)
755 const OUString &rPropName = aProps[i].Name;
756 if (rPropName != sFormula &&
757 rPropName != sBasicLibraries &&
758 rPropName != sDialogLibraries &&
759 rPropName != sRuntimeUID)
761 pProps->Name = rPropName;
762 pProps->Value = xProps->getPropertyValue(rPropName);
771 void SmXMLExport::ExportLine(const SmNode *pNode, int nLevel)
773 ExportExpression(pNode, nLevel);
776 void SmXMLExport::ExportBinaryHorizontal(const SmNode *pNode, int nLevel)
778 ExportExpression(pNode, nLevel);
781 void SmXMLExport::ExportUnaryHorizontal(const SmNode *pNode, int nLevel)
783 ExportExpression(pNode, nLevel);
786 void SmXMLExport::ExportExpression(const SmNode *pNode, int nLevel)
788 SvXMLElementExport *pRow=0;
789 ULONG nSize = pNode->GetNumSubNodes();
791 if (nSize > 1)
792 pRow = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MROW, sal_True, sal_True);
794 //if (nSize)
796 for (USHORT i = 0; i < nSize; i++)
797 if (const SmNode *pTemp = pNode->GetSubNode(i))
798 ExportNodes(pTemp, nLevel+1);
800 #if 0
801 else
803 //This saves us from situations like "a newline" where the
804 //lack of a term following the newline would otherwise create
805 //a incorrect token like <mtr/>
806 SvXMLElementExport aDummy(*this, XML_NAMESPACE_MATH, XML_MI, sal_True, sal_False);
807 sal_Unicode nArse[2] = {'\n','\0'};
808 GetDocHandler()->characters(nArse);
810 #endif
812 delete pRow;
815 void SmXMLExport::ExportBinaryVertical(const SmNode *pNode, int nLevel)
817 DBG_ASSERT(pNode->GetNumSubNodes()==3,"Bad Fraction");
818 SvXMLElementExport aFraction(*this, XML_NAMESPACE_MATH, XML_MFRAC, sal_True, sal_True);
819 ExportNodes(pNode->GetSubNode(0), nLevel);
820 ExportNodes(pNode->GetSubNode(2), nLevel);
823 void SmXMLExport::ExportTable(const SmNode *pNode, int nLevel)
825 SvXMLElementExport *pTable=0;
827 USHORT nSize = pNode->GetNumSubNodes();
829 //If the list ends in newline then the last entry has
830 //no subnodes, the newline is superfulous so we just drop
831 //the last node, inclusion would create a bad MathML
832 //table
833 if (nSize >= 1 && pNode->GetSubNode(nSize-1)->GetNumSubNodes() == 0)
834 --nSize;
836 // try to avoid creating a mtable element when the formula consists only
837 // of a single output line
838 if (nLevel || (nSize >1))
839 pTable = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTABLE, sal_True, sal_True);
841 for (USHORT i = 0; i < nSize; i++)
842 if (const SmNode *pTemp = pNode->GetSubNode(i))
844 SvXMLElementExport *pRow=0;
845 SvXMLElementExport *pCell=0;
846 if (pTable)
848 pRow = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTR, sal_True, sal_True);
849 pCell = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTD, sal_True, sal_True);
851 ExportNodes(pTemp, nLevel+1);
852 delete pCell;
853 delete pRow;
856 delete pTable;
859 void SmXMLExport::ExportMath(const SmNode *pNode, int /*nLevel*/)
861 const SmMathSymbolNode *pTemp = static_cast<const SmMathSymbolNode *>(pNode);
862 SvXMLElementExport aMath(*this, XML_NAMESPACE_MATH, XML_MO, sal_True, sal_False);
863 sal_Unicode nArse[2];
864 nArse[0] = pTemp->GetText().GetChar(0);
865 sal_Unicode cTmp = ConvertMathToMathML( nArse[0] );
866 if (cTmp != 0)
867 nArse[0] = cTmp;
868 DBG_ASSERT(nArse[0] != 0xffff,"Non existant symbol");
869 nArse[1] = 0;
870 GetDocHandler()->characters(nArse);
873 void SmXMLExport::ExportText(const SmNode *pNode, int /*nLevel*/)
875 SvXMLElementExport *pText;
876 const SmTextNode *pTemp = static_cast<const SmTextNode *>(pNode);
877 switch (pNode->GetToken().eType)
879 default:
880 case TIDENT:
882 //Note that we change the fontstyle to italic for strings that
883 //are italic and longer than a single character.
884 sal_Bool bIsItalic = IsItalic( pTemp->GetFont() );
885 if ((pTemp->GetText().Len() > 1) && bIsItalic)
886 AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, XML_ITALIC);
887 else if ((pTemp->GetText().Len() == 1) && !bIsItalic)
888 AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, XML_NORMAL);
889 pText = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MI,sal_True,sal_False);
890 break;
892 case TNUMBER:
893 pText = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MN,sal_True,sal_False);
894 break;
895 case TTEXT:
896 pText = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MTEXT,sal_True,sal_False);
897 break;
899 GetDocHandler()->characters(OUString(pTemp->GetText().GetBuffer()));
900 delete pText;
903 void SmXMLExport::ExportBlank(const SmNode * /*pNode*/, int /*nLevel*/)
905 //!! exports an empty <mi> tag since for example "~_~" is allowed in
906 //!! Math (so it has no sense at all) but must not result in an empty
907 //!! <msub> tag in MathML !!
909 SvXMLElementExport *pText;
910 //const SmBlankNode *pTemp = static_cast<const SmBlankNode *>(pNode);
912 pText = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MI, sal_True, sal_False);
914 GetDocHandler()->characters( OUString() );
915 delete pText;
918 void SmXMLExport::ExportSubSupScript(const SmNode *pNode, int nLevel)
920 const SmNode *pSub = 0;
921 const SmNode *pSup = 0;
922 const SmNode *pCSub = 0;
923 const SmNode *pCSup = 0;
924 const SmNode *pLSub = 0;
925 const SmNode *pLSup = 0;
926 SvXMLElementExport *pThing = 0, *pThing2 = 0;
928 //if we have prescripts at all then we must use the tensor notation
930 //This is one of those excellent locations where scope is vital to
931 //arrange the construction and destruction of the element helper
932 //classes correctly
933 pLSub = pNode->GetSubNode(LSUB+1);
934 pLSup = pNode->GetSubNode(LSUP+1);
935 if (pLSub || pLSup)
937 SvXMLElementExport aMultiScripts(*this, XML_NAMESPACE_MATH,
938 XML_MMULTISCRIPTS, sal_True, sal_True);
941 if (NULL != (pCSub = pNode->GetSubNode(CSUB+1))
942 && NULL != (pCSup = pNode->GetSubNode(CSUP+1)))
944 pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
945 XML_MUNDEROVER, sal_True,sal_True);
947 else if (NULL != (pCSub = pNode->GetSubNode(CSUB+1)))
949 pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
950 XML_MUNDER, sal_True,sal_True);
952 else if (NULL != (pCSup = pNode->GetSubNode(CSUP+1)))
954 pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
955 XML_MOVER, sal_True,sal_True);
958 ExportNodes(pNode->GetSubNode(0), nLevel+1); //Main Term
960 if (pCSub)
961 ExportNodes(pCSub, nLevel+1);
962 if (pCSup)
963 ExportNodes(pCSup, nLevel+1);
964 delete pThing2;
966 pSub = pNode->GetSubNode(RSUB+1);
967 pSup = pNode->GetSubNode(RSUP+1);
968 if (pSub || pSup)
970 if (pSub)
971 ExportNodes(pSub, nLevel+1);
972 else
974 SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE,sal_True,sal_True);
976 if (pSup)
977 ExportNodes(pSup, nLevel+1);
978 else
980 SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE,sal_True,sal_True);
984 //Seperator element between suffix and prefix sub/sup pairs
986 SvXMLElementExport aPrescripts(*this, XML_NAMESPACE_MATH,
987 XML_MPRESCRIPTS, sal_True,sal_True);
990 if (pLSub)
991 ExportNodes(pLSub, nLevel+1);
992 else
994 SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE,
995 sal_True,sal_True);
998 if (pLSup)
999 ExportNodes(pLSup, nLevel+1);
1000 else
1002 SvXMLElementExport aNone(*this, XML_NAMESPACE_MATH, XML_NONE,
1003 sal_True,sal_True);
1007 else
1009 if (NULL != (pSub = pNode->GetSubNode(RSUB+1)) &&
1010 NULL != (pSup = pNode->GetSubNode(RSUP+1)))
1012 pThing = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
1013 XML_MSUBSUP, sal_True,sal_True);
1015 else if (NULL != (pSub = pNode->GetSubNode(RSUB+1)))
1017 pThing = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MSUB,
1018 sal_True,sal_True);
1020 else if (NULL != (pSup = pNode->GetSubNode(RSUP+1)))
1022 pThing = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MSUP,
1023 sal_True,sal_True);
1026 if (NULL != (pCSub = pNode->GetSubNode(CSUB+1))
1027 && NULL != (pCSup=pNode->GetSubNode(CSUP+1)))
1029 pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
1030 XML_MUNDEROVER, sal_True,sal_True);
1032 else if (NULL != (pCSub = pNode->GetSubNode(CSUB+1)))
1034 pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
1035 XML_MUNDER, sal_True,sal_True);
1037 else if (NULL != (pCSup = pNode->GetSubNode(CSUP+1)))
1039 pThing2 = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
1040 XML_MOVER, sal_True,sal_True);
1042 ExportNodes(pNode->GetSubNode(0), nLevel+1); //Main Term
1044 if (pCSub)
1045 ExportNodes(pCSub, nLevel+1);
1046 if (pCSup)
1047 ExportNodes(pCSup, nLevel+1);
1048 delete pThing2;
1050 if (pSub)
1051 ExportNodes(pSub, nLevel+1);
1052 if (pSup)
1053 ExportNodes(pSup, nLevel+1);
1054 delete pThing;
1058 void SmXMLExport::ExportBrace(const SmNode *pNode, int nLevel)
1060 const SmNode *pTemp;
1061 const SmNode *pLeft=pNode->GetSubNode(0);
1062 const SmNode *pRight=pNode->GetSubNode(2);
1063 SvXMLElementExport *pFences=0,*pRow=0;
1064 if ( ((pLeft) && (pLeft->GetToken().eType != TNONE)) &&
1065 ((pRight) && (pRight->GetToken().eType != TNONE)) &&
1066 (pNode->GetScaleMode() == SCALE_HEIGHT))
1068 sal_Unicode nArse[2];
1069 nArse[1] = 0;
1070 nArse[0] = static_cast<
1071 const SmMathSymbolNode* >(pLeft)->GetText().GetChar(0);
1072 DBG_ASSERT(nArse[0] != 0xffff,"Non existant symbol");
1073 AddAttribute(XML_NAMESPACE_MATH, XML_OPEN,nArse);
1074 nArse[0] = static_cast<
1075 const SmMathSymbolNode* >(pRight)->GetText().GetChar(0);
1076 DBG_ASSERT(nArse[0] != 0xffff,"Non existant symbol");
1077 AddAttribute(XML_NAMESPACE_MATH, XML_CLOSE,nArse);
1078 pFences = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MFENCED,
1079 sal_True,sal_True);
1081 else if (pLeft && (pLeft->GetToken().eType != TNONE))
1083 pRow = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MROW,
1084 sal_True, sal_True);
1085 if (pNode->GetScaleMode() == SCALE_HEIGHT)
1086 AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_TRUE);
1087 else
1088 AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_FALSE);
1089 ExportNodes(pLeft, nLevel+1);
1091 else
1092 pRow = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MROW,
1093 sal_True, sal_True);
1095 if (NULL != (pTemp = pNode->GetSubNode(1)))
1096 ExportNodes(pTemp, nLevel+1);
1097 if (pFences)
1098 delete pFences;
1099 else if (pRight && (pRight->GetToken().eType != TNONE))
1101 if (pNode->GetScaleMode() == SCALE_HEIGHT)
1102 AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_TRUE);
1103 else
1104 AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_FALSE);
1105 ExportNodes(pRight, nLevel+1);
1107 delete pRow;
1110 void SmXMLExport::ExportRoot(const SmNode *pNode, int nLevel)
1112 if (pNode->GetSubNode(0))
1114 SvXMLElementExport aRoot(*this, XML_NAMESPACE_MATH, XML_MROOT,sal_True,
1115 sal_True);
1116 ExportNodes(pNode->GetSubNode(2), nLevel+1);
1117 ExportNodes(pNode->GetSubNode(0), nLevel+1);
1119 else
1121 SvXMLElementExport aSqrt(*this, XML_NAMESPACE_MATH, XML_MSQRT,sal_True,
1122 sal_True);
1123 ExportNodes(pNode->GetSubNode(2), nLevel+1);
1127 void SmXMLExport::ExportOperator(const SmNode *pNode, int nLevel)
1129 /*we need to either use content or font and size attributes
1130 *here*/
1131 #if 0
1133 SvXMLElementExport aMath(*this, XML_NAMESPACE_MATH, XML_MO,
1134 sal_True,sal_False);
1135 SmTextNode *pTemp = (SmTextNode *)pNode->GetSubNode(0);
1136 GetDocHandler()->characters(pTemp->GetText());
1138 #endif
1139 SvXMLElementExport aRow(*this, XML_NAMESPACE_MATH, XML_MROW,
1140 sal_True, sal_True);
1141 ExportNodes(pNode->GetSubNode(0), nLevel+1);
1142 ExportNodes(pNode->GetSubNode(1), nLevel+1);
1145 void SmXMLExport::ExportAttributes(const SmNode *pNode, int nLevel)
1147 SvXMLElementExport *pElement=0;
1149 if (pNode->GetToken().eType == TUNDERLINE)
1151 AddAttribute(XML_NAMESPACE_MATH, XML_ACCENTUNDER,
1152 XML_TRUE);
1153 pElement = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MUNDER,
1154 sal_True,sal_True);
1156 else if (pNode->GetToken().eType != TOVERSTRIKE)
1158 AddAttribute(XML_NAMESPACE_MATH, XML_ACCENT,
1159 XML_TRUE);
1160 pElement = new SvXMLElementExport(*this, XML_NAMESPACE_MATH, XML_MOVER,
1161 sal_True,sal_True);
1164 ExportNodes(pNode->GetSubNode(1), nLevel+1);
1165 switch (pNode->GetToken().eType)
1167 case TOVERLINE:
1169 //proper entity support required
1170 SvXMLElementExport aMath(*this, XML_NAMESPACE_MATH, XML_MO,
1171 sal_True,sal_True);
1172 #if 0
1173 GetDocHandler()->characters(
1174 OUString(RTL_CONSTASCII_USTRINGPARAM("&overbar;")));
1175 #else
1176 sal_Unicode nArse[2] = {0xAF,0x00};
1177 #endif
1178 GetDocHandler()->characters(nArse);
1180 break;
1181 case TUNDERLINE:
1183 //proper entity support required
1184 SvXMLElementExport aMath(*this, XML_NAMESPACE_MATH, XML_MO,
1185 sal_True,sal_True);
1186 #if 0
1187 GetDocHandler()->characters(
1188 OUString(RTL_CONSTASCII_USTRINGPARAM("&underbar;")));
1189 #else
1190 sal_Unicode nArse[2] = {0x0332,0x00};
1191 #endif
1192 GetDocHandler()->characters(nArse);
1194 break;
1195 case TOVERSTRIKE:
1196 break;
1197 default:
1198 ExportNodes(pNode->GetSubNode(0), nLevel+1);
1199 break;
1201 delete pElement;
1204 static bool lcl_HasEffectOnMathvariant( const SmTokenType eType )
1206 return eType == TBOLD || eType == TNBOLD ||
1207 eType == TITALIC || eType == TNBOLD ||
1208 eType == TSANS || eType == TSERIF || eType == TFIXED;
1211 void SmXMLExport::ExportFont(const SmNode *pNode, int nLevel)
1213 SvXMLElementExport *pElement = 0;
1216 // gather the mathvariant attribut relevant data from all
1217 // successively following SmFontNodes...
1219 int nBold = -1; // for the following variables: -1 = yet undefined; 0 = false; 1 = true;
1220 int nItalic = -1; // for the following variables: -1 = yet undefined; 0 = false; 1 = true;
1221 int nSansSerifFixed = -1;
1222 SmTokenType eNodeType = TUNKNOWN;
1223 while (lcl_HasEffectOnMathvariant( (eNodeType = pNode->GetToken().eType) ))
1225 switch (eNodeType)
1227 case TBOLD : nBold = 1; break;
1228 case TNBOLD : nBold = 0; break;
1229 case TITALIC : nItalic = 1; break;
1230 case TNITALIC : nItalic = 0; break;
1231 case TSANS : nSansSerifFixed = 0; break;
1232 case TSERIF : nSansSerifFixed = 1; break;
1233 case TFIXED : nSansSerifFixed = 2; break;
1234 default:
1235 DBG_ASSERT( 0, "unexpected case" );
1237 // According to the parser every node that is to be evaluated heres
1238 // has a single non-zero subnode at index 1!! Thus we only need to check
1239 // that single node for follow-up nodes that have an effect on the attribute.
1240 if (pNode->GetNumSubNodes() > 1 && pNode->GetSubNode(1) &&
1241 lcl_HasEffectOnMathvariant( pNode->GetSubNode(1)->GetToken().eType))
1243 pNode = pNode->GetSubNode(1);
1245 else
1246 break;
1249 switch (pNode->GetToken().eType)
1251 //wrap a phantom element around everything*/
1252 case TPHANTOM:
1253 pElement = new SvXMLElementExport(*this, XML_NAMESPACE_MATH,
1254 XML_MPHANTOM, sal_True,sal_True);
1255 break;
1256 case TBLACK:
1257 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_BLACK);
1258 break;
1259 case TWHITE:
1260 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_WHITE);
1261 break;
1262 case TRED:
1263 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_RED);
1264 break;
1265 case TGREEN:
1266 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_GREEN);
1267 break;
1268 case TBLUE:
1269 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_BLUE);
1270 break;
1271 case TCYAN:
1272 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_AQUA);
1273 break;
1274 case TMAGENTA:
1275 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_FUCHSIA);
1276 break;
1277 case TYELLOW:
1278 AddAttribute(XML_NAMESPACE_MATH, XML_COLOR, XML_YELLOW);
1279 break;
1280 case TSIZE:
1282 const SmFontNode *pFontNode = static_cast<const SmFontNode *>(pNode);
1283 const Fraction &aFrac = pFontNode->GetSizeParameter();
1285 OUStringBuffer sStrBuf;
1286 switch(pFontNode->GetSizeType())
1288 case FNTSIZ_MULTIPLY:
1289 SvXMLUnitConverter::convertDouble(sStrBuf,
1290 static_cast<double>(aFrac*Fraction(100.00)));
1291 sStrBuf.append(static_cast<sal_Unicode>('%'));
1292 break;
1293 case FNTSIZ_DIVIDE:
1294 SvXMLUnitConverter::convertDouble(sStrBuf,
1295 static_cast<double>(Fraction(100.00)/aFrac));
1296 sStrBuf.append(static_cast<sal_Unicode>('%'));
1297 break;
1298 case FNTSIZ_ABSOLUT:
1299 SvXMLUnitConverter::convertDouble(sStrBuf,
1300 static_cast<double>(aFrac));
1301 sStrBuf.append(
1302 GetXMLToken(XML_UNIT_PT));
1303 break;
1304 default:
1306 //The problem here is that the wheels fall off because
1307 //font size is stored in 100th's of a mm not pts, and
1308 //rounding errors take their toll on the original
1309 //value specified in points.
1311 //Must fix StarMath to retain the original pt values
1312 Fraction aTemp = Sm100th_mmToPts(pFontNode->GetFont().
1313 GetSize().Height());
1315 if (pFontNode->GetSizeType() == FNTSIZ_MINUS)
1316 aTemp-=aFrac;
1317 else
1318 aTemp+=aFrac;
1320 double mytest = static_cast<double>(aTemp);
1322 mytest = ::rtl::math::round(mytest,1);
1323 SvXMLUnitConverter::convertDouble(sStrBuf,mytest);
1324 sStrBuf.append(GetXMLToken(XML_UNIT_PT));
1326 break;
1329 OUString sStr(sStrBuf.makeStringAndClear());
1330 AddAttribute(XML_NAMESPACE_MATH, XML_MATHSIZE, sStr);
1332 break;
1333 case TBOLD:
1334 case TITALIC:
1335 case TNBOLD:
1336 case TNITALIC:
1337 case TFIXED:
1338 case TSANS:
1339 case TSERIF:
1341 // nBold: -1 = yet undefined; 0 = false; 1 = true;
1342 // nItalic: -1 = yet undefined; 0 = false; 1 = true;
1343 // nSansSerifFixed: -1 = undefined; 0 = sans; 1 = serif; 2 = fixed;
1344 const sal_Char *pText = "normal";
1345 if (nSansSerifFixed == -1 || nSansSerifFixed == 1)
1347 pText = "normal";
1348 if (nBold == 1 && nItalic != 1)
1349 pText = "bold";
1350 else if (nBold != 1 && nItalic == 1)
1351 pText = "italic";
1352 else if (nBold == 1 && nItalic == 1)
1353 pText = "bold-italic";
1355 else if (nSansSerifFixed == 0)
1357 pText = "sans-serif";
1358 if (nBold == 1 && nItalic != 1)
1359 pText = "bold-sans-serif";
1360 else if (nBold != 1 && nItalic == 1)
1361 pText = "sans-serif-italic";
1362 else if (nBold == 1 && nItalic == 1)
1363 pText = "sans-serif-bold-italic";
1365 else if (nSansSerifFixed == 2)
1366 pText = "monospace"; // no modifiers allowed for monospace ...
1367 else
1369 DBG_ASSERT( 0, "unexpected case" );
1371 AddAttribute(XML_NAMESPACE_MATH, XML_MATHVARIANT, A2OU(pText));
1373 break;
1374 default:
1375 break;
1378 #if 0
1379 if (pNode->GetNumSubNodes() > 1) //or in the future is a node that
1380 //cannot take the currently supported
1381 //properties
1382 #endif
1383 //for now we will just always export with a style and not worry about
1384 //anyone else for the moment.
1386 //wrap a style around it
1387 SvXMLElementExport aStyle(*this, XML_NAMESPACE_MATH, XML_MSTYLE, sal_True,sal_True);
1388 ExportExpression(pNode, nLevel);
1390 #if 0
1391 else
1392 ExportNodes(pNode->GetSubNode(0), nLevel+1);
1393 #endif
1395 delete pElement;
1399 void SmXMLExport::ExportVerticalBrace(const SmNode *pNode, int nLevel)
1401 //Place the overbrace value OVER a vertical brace and then place that
1402 //expression OVER the overbrace value, If someone can find a
1403 //dedicated term in MathML to handle this overbrace/underbrace concept
1404 //let me know. C.
1405 XMLTokenEnum which;
1407 switch (pNode->GetToken().eType)
1409 case TOVERBRACE:
1410 default:
1411 which = XML_MOVER;
1412 break;
1413 case TUNDERBRACE:
1414 which = XML_MUNDER;
1415 break;
1418 DBG_ASSERT(pNode->GetNumSubNodes()==3,"Bad Vertical Brace");
1419 SvXMLElementExport aOver1(*this, XML_NAMESPACE_MATH,which, sal_True, sal_True);
1420 {//Scoping
1421 // using accents will draw the over-/underbraces too close to the base
1422 // see http://www.w3.org/TR/MathML2/chapter3.html#id.3.4.5.2
1423 // also XML_ACCENT is illegal with XML_MUNDER. Thus no XML_ACCENT attribut here!
1424 // AddAttribute(XML_NAMESPACE_MATH, XML_ACCENT, XML_TRUE);
1425 SvXMLElementExport aOver2(*this, XML_NAMESPACE_MATH,which, sal_True, sal_True);
1426 ExportNodes(pNode->GetSubNode(0), nLevel);
1427 ExportNodes(pNode->GetSubNode(1), nLevel);
1429 ExportNodes(pNode->GetSubNode(2), nLevel);
1432 void SmXMLExport::ExportMatrix(const SmNode *pNode, int nLevel)
1434 SvXMLElementExport aTable(*this, XML_NAMESPACE_MATH, XML_MTABLE, sal_True, sal_True);
1435 const SmMatrixNode *pMatrix = static_cast<const SmMatrixNode *>(pNode);
1436 USHORT i=0;
1437 for (ULONG y = 0; y < pMatrix->GetNumRows(); y++)
1439 SvXMLElementExport aRow(*this, XML_NAMESPACE_MATH, XML_MTR, sal_True, sal_True);
1440 for (ULONG x = 0; x < pMatrix->GetNumCols(); x++)
1441 if (const SmNode *pTemp = pNode->GetSubNode(i++))
1443 SvXMLElementExport aCell(*this, XML_NAMESPACE_MATH, XML_MTD, sal_True, sal_True);
1444 ExportNodes(pTemp, nLevel+1);
1449 void SmXMLExport::ExportNodes(const SmNode *pNode, int nLevel)
1451 if (!pNode)
1452 return;
1453 switch(pNode->GetType())
1455 case NTABLE:
1456 ExportTable(pNode, nLevel);
1457 break;
1458 case NALIGN:
1459 case NBRACEBODY:
1460 case NEXPRESSION:
1461 ExportExpression(pNode, nLevel);
1462 break;
1463 case NLINE:
1464 ExportLine(pNode, nLevel);
1465 break;
1466 case NTEXT:
1467 ExportText(pNode, nLevel);
1468 break;
1469 case NSPECIAL: //NSPECIAL requires some sort of Entity preservation in the XML engine.
1470 case NGLYPH_SPECIAL:
1471 case NMATH:
1473 sal_Unicode cTmp = 0;
1474 const SmTextNode *pTemp = static_cast< const SmTextNode * >(pNode);
1475 if (pTemp->GetText().Len() > 0)
1476 cTmp = ConvertMathToMathML( pTemp->GetText().GetChar(0) );
1477 if (cTmp == 0)
1479 // no conversion to MathML implemented -> export it as text
1480 // thus at least it will not vanish into nothing
1481 ExportText(pNode, nLevel);
1483 else
1485 //To fully handle generic MathML we need to implement the full
1486 //operator dictionary, we will generate MathML with explicit
1487 //stretchiness for now.
1488 sal_Int16 nLength = GetAttrList().getLength();
1489 sal_Bool bAddStretch=sal_True;
1490 for ( sal_Int16 i = 0; i < nLength; i++ )
1492 OUString sLocalName;
1493 sal_uInt16 nPrefix = GetNamespaceMap().GetKeyByAttrName(
1494 GetAttrList().getNameByIndex(i), &sLocalName );
1496 if ( ( XML_NAMESPACE_MATH == nPrefix ) &&
1497 IsXMLToken(sLocalName, XML_STRETCHY) )
1499 bAddStretch = sal_False;
1500 break;
1503 if (bAddStretch)
1505 AddAttribute(XML_NAMESPACE_MATH, XML_STRETCHY, XML_FALSE);
1507 ExportMath(pNode, nLevel);
1510 break;
1511 case NPLACE:
1512 ExportMath(pNode, nLevel);
1513 break;
1514 case NBINHOR:
1515 ExportBinaryHorizontal(pNode, nLevel);
1516 break;
1517 case NUNHOR:
1518 ExportUnaryHorizontal(pNode, nLevel);
1519 break;
1520 case NBRACE:
1521 ExportBrace(pNode, nLevel);
1522 break;
1523 case NBINVER:
1524 ExportBinaryVertical(pNode, nLevel);
1525 break;
1526 case NSUBSUP:
1527 ExportSubSupScript(pNode, nLevel);
1528 break;
1529 case NROOT:
1530 ExportRoot(pNode, nLevel);
1531 break;
1532 case NOPER:
1533 ExportOperator(pNode, nLevel);
1534 break;
1535 case NATTRIBUT:
1536 ExportAttributes(pNode, nLevel);
1537 break;
1538 case NFONT:
1539 ExportFont(pNode, nLevel);
1540 break;
1541 case NVERTICAL_BRACE:
1542 ExportVerticalBrace(pNode, nLevel);
1543 break;
1544 case NMATRIX:
1545 ExportMatrix(pNode, nLevel);
1546 break;
1547 case NBLANK:
1548 ExportBlank(pNode, nLevel);
1549 break;
1550 default:
1551 DBG_ASSERT( 0, "Warning: failed to export a node?" );
1552 break;
1554 #if 0
1555 default:
1557 ULONG nSize = pNode->GetNumSubNodes();
1558 for (ULONG i = 0; i < nSize; i++)
1559 if (SmNode *pTemp = pNode->GetSubNode(i))
1560 ExportNodes(pTemp, nLevel+1);
1562 break;
1563 #endif
1567 ////////////////////////////////////////////////////////////