1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_starmath.hxx"
26 
27 /*todo: Change characters and tcharacters to accumulate the characters together
28 into one string, xml parser hands them to us line by line rather than all in
29 one go*/
30 
31 #include <com/sun/star/xml/sax/XErrorHandler.hpp>
32 #include <com/sun/star/xml/sax/XEntityResolver.hpp>
33 #include <com/sun/star/xml/sax/InputSource.hpp>
34 #include <com/sun/star/xml/sax/XDTDHandler.hpp>
35 #include <com/sun/star/xml/sax/XParser.hpp>
36 #include <com/sun/star/io/XActiveDataSource.hpp>
37 #include <com/sun/star/io/XActiveDataControl.hpp>
38 #include <com/sun/star/document/XDocumentProperties.hpp>
39 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
40 #include <com/sun/star/packages/zip/ZipIOException.hpp>
41 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
42 #include <com/sun/star/beans/PropertyAttribute.hpp>
43 #include <com/sun/star/container/XNameAccess.hpp>
44 #include <com/sun/star/embed/ElementModes.hpp>
45 #include <com/sun/star/uno/Any.h>
46 
47 #include <rtl/math.hxx>
48 #include <sfx2/frame.hxx>
49 #include <sfx2/docfile.hxx>
50 #include <tools/debug.hxx>
51 #include <tools/urlobj.hxx>
52 #include <svtools/sfxecode.hxx>
53 #include <unotools/saveopt.hxx>
54 #include <svl/stritem.hxx>
55 #include <svl/itemprop.hxx>
56 #include <unotools/processfactory.hxx>
57 #include <unotools/streamwrap.hxx>
58 #include <xmloff/xmlnmspe.hxx>
59 #include <xmloff/xmltoken.hxx>
60 #include <xmloff/nmspmap.hxx>
61 #include <xmloff/attrlist.hxx>
62 #include <xmloff/xmluconv.hxx>
63 #include <xmloff/xmlmetai.hxx>
64 #include <osl/mutex.hxx>
65 #include <comphelper/genericpropertyset.hxx>
66 
67 #include <memory>
68 
69 #include "mathmlimport.hxx"
70 #include <starmath.hrc>
71 #include <unomodel.hxx>
72 #include <document.hxx>
73 #include <utility.hxx>
74 
75 using namespace ::com::sun::star::beans;
76 using namespace ::com::sun::star::container;
77 using namespace ::com::sun::star::document;
78 using namespace ::com::sun::star::lang;
79 using namespace ::com::sun::star::uno;
80 using namespace ::com::sun::star;
81 using namespace ::xmloff::token;
82 
83 using ::rtl::OUString;
84 using ::rtl::OUStringBuffer;
85 
86 #define IMPORT_SVC_NAME RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.XMLImportFilter")
87 
88 #undef WANTEXCEPT
89 
90 ////////////////////////////////////////////////////////////
91 
92 sal_uLong SmXMLImportWrapper::Import(SfxMedium &rMedium)
93 {
94     sal_uLong nError = ERRCODE_SFX_DOLOADFAILED;
95 
96     uno::Reference<lang::XMultiServiceFactory> xServiceFactory(
97         utl::getProcessServiceFactory());
98     DBG_ASSERT(xServiceFactory.is(), "XMLReader::Read: got no service manager");
99     if ( !xServiceFactory.is() )
100         return nError;
101 
102     //Make a model component from our SmModel
103     uno::Reference< lang::XComponent > xModelComp( xModel, uno::UNO_QUERY );
104     DBG_ASSERT( xModelComp.is(), "XMLReader::Read: got no model" );
105 
106     // try to get an XStatusIndicator from the Medium
107     uno::Reference<task::XStatusIndicator> xStatusIndicator;
108 
109     sal_Bool bEmbedded = sal_False;
110     uno::Reference <lang::XUnoTunnel> xTunnel;
111     xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY);
112     SmModel *pModel = reinterpret_cast<SmModel *>
113         (xTunnel->getSomething(SmModel::getUnoTunnelId()));
114 
115     SmDocShell *pDocShell = pModel ?
116             static_cast<SmDocShell*>(pModel->GetObjectShell()) : 0;
117     if (pDocShell)
118     {
119 //        if (pDocShell->GetMedium())
120         {
121             DBG_ASSERT( pDocShell->GetMedium() == &rMedium,
122                     "different SfxMedium found" );
123 
124             SfxItemSet* pSet = rMedium.GetItemSet();
125             if (pSet)
126             {
127                 const SfxUnoAnyItem* pItem = static_cast<const SfxUnoAnyItem*>(
128                     pSet->GetItem(SID_PROGRESS_STATUSBAR_CONTROL) );
129                 if (pItem)
130                     pItem->GetValue() >>= xStatusIndicator;
131             }
132         }
133 
134         if ( SFX_CREATE_MODE_EMBEDDED == pDocShell->GetCreateMode() )
135             bEmbedded = sal_True;
136     }
137 
138     comphelper::PropertyMapEntry aInfoMap[] =
139     {
140         { "PrivateData", sizeof("PrivateData")-1, 0,
141               &::getCppuType( (Reference<XInterface> *)0 ),
142               beans::PropertyAttribute::MAYBEVOID, 0 },
143         { "BaseURI", sizeof("BaseURI")-1, 0,
144               &::getCppuType( (OUString *)0 ),
145               beans::PropertyAttribute::MAYBEVOID, 0 },
146         { "StreamRelPath", sizeof("StreamRelPath")-1, 0,
147               &::getCppuType( (OUString *)0 ),
148               beans::PropertyAttribute::MAYBEVOID, 0 },
149         { "StreamName", sizeof("StreamName")-1, 0,
150               &::getCppuType( (OUString *)0 ),
151               beans::PropertyAttribute::MAYBEVOID, 0 },
152         { NULL, 0, 0, NULL, 0, 0 }
153     };
154     uno::Reference< beans::XPropertySet > xInfoSet(
155                 comphelper::GenericPropertySet_CreateInstance(
156                             new comphelper::PropertySetInfo( aInfoMap ) ) );
157 
158     // Set base URI
159     OUString sPropName( RTL_CONSTASCII_USTRINGPARAM("BaseURI") );
160     xInfoSet->setPropertyValue( sPropName, makeAny( rMedium.GetBaseURL() ) );
161 
162     sal_Int32 nSteps=3;
163     if ( !(rMedium.IsStorage()))
164         nSteps = 1;
165 
166     sal_Int32 nProgressRange(nSteps);
167     if (xStatusIndicator.is())
168     {
169         xStatusIndicator->start(String(SmResId(STR_STATSTR_READING)),
170             nProgressRange);
171     }
172 
173     nSteps=0;
174     if (xStatusIndicator.is())
175         xStatusIndicator->setValue(nSteps++);
176 
177     if ( rMedium.IsStorage())
178     {
179         // TODO/LATER: handle the case of embedded links gracefully
180         if ( bEmbedded ) // && !rMedium.GetStorage()->IsRoot() )
181         {
182             OUString aName( RTL_CONSTASCII_USTRINGPARAM( "dummyObjName" ) );
183             if ( rMedium.GetItemSet() )
184             {
185                 const SfxStringItem* pDocHierarchItem = static_cast<const SfxStringItem*>(
186                     rMedium.GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME) );
187                 if ( pDocHierarchItem )
188                     aName = pDocHierarchItem->GetValue();
189             }
190 
191             if ( aName.getLength() )
192             {
193                 sPropName = OUString(RTL_CONSTASCII_USTRINGPARAM("StreamRelPath"));
194                 xInfoSet->setPropertyValue( sPropName, makeAny( aName ) );
195             }
196         }
197 
198         sal_Bool bOASIS = ( SotStorage::GetVersion( rMedium.GetStorage() ) > SOFFICE_FILEFORMAT_60 );
199         if (xStatusIndicator.is())
200             xStatusIndicator->setValue(nSteps++);
201 
202         sal_uLong nWarn = ReadThroughComponent(
203             rMedium.GetStorage(), xModelComp, "meta.xml", "Meta.xml",
204             xServiceFactory, xInfoSet,
205                 (bOASIS ? "com.sun.star.comp.Math.XMLOasisMetaImporter"
206                         : "com.sun.star.comp.Math.XMLMetaImporter") );
207 
208         if ( nWarn != ERRCODE_IO_BROKENPACKAGE )
209         {
210             if (xStatusIndicator.is())
211                 xStatusIndicator->setValue(nSteps++);
212 
213             nWarn = ReadThroughComponent(
214                 rMedium.GetStorage(), xModelComp, "settings.xml", 0,
215                 xServiceFactory, xInfoSet,
216                 (bOASIS ? "com.sun.star.comp.Math.XMLOasisSettingsImporter"
217                         : "com.sun.star.comp.Math.XMLSettingsImporter" ) );
218 
219             if ( nWarn != ERRCODE_IO_BROKENPACKAGE )
220             {
221                 if (xStatusIndicator.is())
222                     xStatusIndicator->setValue(nSteps++);
223 
224                 nError = ReadThroughComponent(
225                     rMedium.GetStorage(), xModelComp, "content.xml", "Content.xml",
226                     xServiceFactory, xInfoSet, "com.sun.star.comp.Math.XMLImporter" );
227             }
228             else
229                 nError = ERRCODE_IO_BROKENPACKAGE;
230         }
231         else
232             nError = ERRCODE_IO_BROKENPACKAGE;
233     }
234     else
235     {
236         Reference<io::XInputStream> xInputStream =
237             new utl::OInputStreamWrapper(rMedium.GetInStream());
238 
239         if (xStatusIndicator.is())
240             xStatusIndicator->setValue(nSteps++);
241 
242         nError = ReadThroughComponent( xInputStream, xModelComp,
243             xServiceFactory, xInfoSet, "com.sun.star.comp.Math.XMLImporter", sal_False );
244     }
245 
246     if (xStatusIndicator.is())
247         xStatusIndicator->end();
248     return nError;
249 }
250 
251 
252 /// read a component (file + filter version)
253 sal_uLong SmXMLImportWrapper::ReadThroughComponent(
254     Reference<io::XInputStream> xInputStream,
255     Reference<XComponent> xModelComponent,
256     Reference<lang::XMultiServiceFactory> & rFactory,
257     Reference<beans::XPropertySet> & rPropSet,
258     const sal_Char* pFilterName,
259     sal_Bool bEncrypted )
260 {
261     sal_uLong nError = ERRCODE_SFX_DOLOADFAILED;
262     DBG_ASSERT(xInputStream.is(), "input stream missing");
263     DBG_ASSERT(xModelComponent.is(), "document missing");
264     DBG_ASSERT(rFactory.is(), "factory missing");
265     DBG_ASSERT(NULL != pFilterName,"I need a service name for the component!");
266 
267     // prepare ParserInputSrouce
268     xml::sax::InputSource aParserInput;
269     aParserInput.aInputStream = xInputStream;
270 
271     // get parser
272     Reference< xml::sax::XParser > xParser(
273         rFactory->createInstance(
274             OUString::createFromAscii("com.sun.star.xml.sax.Parser") ),
275         UNO_QUERY );
276     DBG_ASSERT( xParser.is(), "Can't create parser" );
277     if ( !xParser.is() )
278         return nError;
279 
280     Sequence<Any> aArgs( 1 );
281     aArgs[0] <<= rPropSet;
282 
283     // get filter
284     Reference< xml::sax::XDocumentHandler > xFilter(
285         rFactory->createInstanceWithArguments(
286             OUString::createFromAscii(pFilterName), aArgs ),
287         UNO_QUERY );
288     DBG_ASSERT( xFilter.is(), "Can't instantiate filter component." );
289     if ( !xFilter.is() )
290         return nError;
291 
292     // connect parser and filter
293     xParser->setDocumentHandler( xFilter );
294 
295     // connect model and filter
296     Reference < XImporter > xImporter( xFilter, UNO_QUERY );
297     xImporter->setTargetDocument( xModelComponent );
298 
299     // finally, parser the stream
300     try
301     {
302         xParser->parseStream( aParserInput );
303 
304         uno::Reference<lang::XUnoTunnel> xFilterTunnel;
305         xFilterTunnel = uno::Reference<lang::XUnoTunnel>
306             ( xFilter, uno::UNO_QUERY );
307         SmXMLImport *pFilter = reinterpret_cast< SmXMLImport * >(
308                 sal::static_int_cast< sal_uIntPtr >(
309                 xFilterTunnel->getSomething( SmXMLImport::getUnoTunnelId() )));
310         if ( pFilter && pFilter->GetSuccess() )
311             nError = 0;
312     }
313     catch( xml::sax::SAXParseException& r )
314     {
315         // sax parser sends wrapped exceptions,
316         // try to find the original one
317         xml::sax::SAXException aSaxEx = *(xml::sax::SAXException*)(&r);
318         sal_Bool bTryChild = sal_True;
319 
320         while( bTryChild )
321         {
322             xml::sax::SAXException aTmp;
323             if ( aSaxEx.WrappedException >>= aTmp )
324                 aSaxEx = aTmp;
325             else
326                 bTryChild = sal_False;
327         }
328 
329         packages::zip::ZipIOException aBrokenPackage;
330         if ( aSaxEx.WrappedException >>= aBrokenPackage )
331             return ERRCODE_IO_BROKENPACKAGE;
332 
333         if ( bEncrypted )
334             nError = ERRCODE_SFX_WRONGPASSWORD;
335     }
336     catch( xml::sax::SAXException& r )
337     {
338         packages::zip::ZipIOException aBrokenPackage;
339         if ( r.WrappedException >>= aBrokenPackage )
340             return ERRCODE_IO_BROKENPACKAGE;
341 
342         if ( bEncrypted )
343             nError = ERRCODE_SFX_WRONGPASSWORD;
344     }
345     catch( packages::zip::ZipIOException& )
346     {
347         nError = ERRCODE_IO_BROKENPACKAGE;
348     }
349     catch( io::IOException& )
350     {
351     }
352 
353     return nError;
354 }
355 
356 
357 sal_uLong SmXMLImportWrapper::ReadThroughComponent(
358     const uno::Reference< embed::XStorage >& xStorage,
359     Reference<XComponent> xModelComponent,
360     const sal_Char* pStreamName,
361     const sal_Char* pCompatibilityStreamName,
362     Reference<lang::XMultiServiceFactory> & rFactory,
363     Reference<beans::XPropertySet> & rPropSet,
364     const sal_Char* pFilterName )
365 {
366     DBG_ASSERT(xStorage.is(), "Need storage!");
367     DBG_ASSERT(NULL != pStreamName, "Please, please, give me a name!");
368 
369     // open stream (and set parser input)
370     OUString sStreamName = OUString::createFromAscii(pStreamName);
371     uno::Reference < container::XNameAccess > xAccess( xStorage, uno::UNO_QUERY );
372     if ( !xAccess->hasByName(sStreamName) || !xStorage->isStreamElement(sStreamName) )
373     {
374         // stream name not found! Then try the compatibility name.
375         // do we even have an alternative name?
376         if ( pCompatibilityStreamName )
377             sStreamName = OUString::createFromAscii(pCompatibilityStreamName);
378     }
379 
380     // get input stream
381     try
382     {
383         uno::Reference < io::XStream > xEventsStream = xStorage->openStreamElement( sStreamName, embed::ElementModes::READ );
384 
385         // determine if stream is encrypted or not
386         uno::Reference < beans::XPropertySet > xProps( xEventsStream, uno::UNO_QUERY );
387         Any aAny = xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Encrypted") ) );
388         sal_Bool bEncrypted = sal_False;
389         if ( aAny.getValueType() == ::getBooleanCppuType() )
390             aAny >>= bEncrypted;
391 
392         // set Base URL
393         if ( rPropSet.is() )
394         {
395             OUString sPropName( RTL_CONSTASCII_USTRINGPARAM("StreamName") );
396             rPropSet->setPropertyValue( sPropName, makeAny( sStreamName ) );
397         }
398 
399 
400         Reference < io::XInputStream > xStream = xEventsStream->getInputStream();
401         return ReadThroughComponent( xStream, xModelComponent, rFactory, rPropSet, pFilterName, bEncrypted );
402     }
403     catch ( packages::WrongPasswordException& )
404     {
405         return ERRCODE_SFX_WRONGPASSWORD;
406     }
407     catch( packages::zip::ZipIOException& )
408     {
409         return ERRCODE_IO_BROKENPACKAGE;
410     }
411     catch ( uno::Exception& )
412     {
413     }
414 
415     return ERRCODE_SFX_DOLOADFAILED;
416 }
417 
418 ////////////////////////////////////////////////////////////
419 
420 SmXMLImport::SmXMLImport(
421     const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory,
422     sal_uInt16 nImportFlags)
423 :   SvXMLImport( xServiceFactory, nImportFlags ),
424     pPresLayoutElemTokenMap(0),
425     pPresLayoutAttrTokenMap(0),
426     pFencedAttrTokenMap(0),
427     pOperatorAttrTokenMap(0),
428     pAnnotationAttrTokenMap(0),
429     pPresElemTokenMap(0),
430     pPresScriptEmptyElemTokenMap(0),
431     pPresTableElemTokenMap(0),
432     pColorTokenMap(0),
433     bSuccess(sal_False)
434 {
435 }
436 
437 const uno::Sequence< sal_Int8 > & SmXMLImport::getUnoTunnelId() throw()
438 {
439     static uno::Sequence< sal_Int8 > * pSeq = 0;
440     if ( !pSeq )
441     {
442         osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
443         if ( !pSeq )
444         {
445             static uno::Sequence< sal_Int8 > aSeq( 16 );
446             rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
447             pSeq = &aSeq;
448         }
449     }
450     return *pSeq;
451 }
452 
453 OUString SAL_CALL SmXMLImport_getImplementationName() throw()
454 {
455     return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLImporter" ) );
456 }
457 
458 uno::Sequence< OUString > SAL_CALL SmXMLImport_getSupportedServiceNames()
459         throw()
460 {
461     const OUString aServiceName( IMPORT_SVC_NAME );
462     const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
463         return aSeq;
464 }
465 
466 uno::Reference< uno::XInterface > SAL_CALL SmXMLImport_createInstance(
467     const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
468     throw( uno::Exception )
469 {
470     // #110680#
471     // return (cppu::OWeakObject*)new SmXMLImport(IMPORT_ALL);
472     return (cppu::OWeakObject*)new SmXMLImport(rSMgr, IMPORT_ALL);
473 }
474 
475 ////////////////////////////////////////////////////////////
476 
477 OUString SAL_CALL SmXMLImportMeta_getImplementationName() throw()
478 {
479     return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLOasisMetaImporter" ) );
480 }
481 
482 uno::Sequence< OUString > SAL_CALL SmXMLImportMeta_getSupportedServiceNames()
483 throw()
484 {
485     const OUString aServiceName( IMPORT_SVC_NAME );
486     const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
487     return aSeq;
488 }
489 
490 uno::Reference< uno::XInterface > SAL_CALL SmXMLImportMeta_createInstance(
491     const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
492 throw( uno::Exception )
493 {
494     // #110680#
495     // return (cppu::OWeakObject*)new SmXMLImport( IMPORT_META );
496     return (cppu::OWeakObject*)new SmXMLImport( rSMgr, IMPORT_META );
497 }
498 
499 ////////////////////////////////////////////////////////////
500 
501 OUString SAL_CALL SmXMLImportSettings_getImplementationName() throw()
502 {
503     return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Math.XMLOasisSettingsImporter" ) );
504 }
505 
506 uno::Sequence< OUString > SAL_CALL SmXMLImportSettings_getSupportedServiceNames()
507         throw()
508 {
509     const OUString aServiceName( IMPORT_SVC_NAME );
510     const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
511         return aSeq;
512 }
513 
514 uno::Reference< uno::XInterface > SAL_CALL SmXMLImportSettings_createInstance(
515     const uno::Reference< lang::XMultiServiceFactory > & rSMgr)
516     throw( uno::Exception )
517 {
518     // #110680#
519     // return (cppu::OWeakObject*)new SmXMLImport( IMPORT_SETTINGS );
520     return (cppu::OWeakObject*)new SmXMLImport( rSMgr, IMPORT_SETTINGS );
521 }
522 
523 ////////////////////////////////////////////////////////////
524 
525 // XServiceInfo
526 // override empty method from parent class
527 rtl::OUString SAL_CALL SmXMLImport::getImplementationName()
528     throw(uno::RuntimeException)
529 {
530     OUString aTxt;
531     switch( getImportFlags() )
532     {
533         case IMPORT_META:
534             aTxt = SmXMLImportMeta_getImplementationName();
535             break;
536         case IMPORT_SETTINGS:
537             aTxt = SmXMLImportSettings_getImplementationName();
538             break;
539         case IMPORT_ALL:
540         default:
541             aTxt = SmXMLImport_getImplementationName();
542             break;
543     }
544     return aTxt;
545 }
546 
547 
548 sal_Int64 SAL_CALL SmXMLImport::getSomething(
549     const uno::Sequence< sal_Int8 >&rId )
550 throw(uno::RuntimeException)
551 {
552     if ( rId.getLength() == 16 &&
553         0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
554         rId.getConstArray(), 16 ) )
555     return sal::static_int_cast< sal_Int64 >(reinterpret_cast< sal_uIntPtr >(this));
556 
557     return SvXMLImport::getSomething( rId );
558 }
559 
560 void SmXMLImport::endDocument(void)
561     throw(xml::sax::SAXException, uno::RuntimeException)
562 {
563     //Set the resulted tree into the SmDocShell where it belongs
564     SmNode *pTree;
565     if (NULL != (pTree = GetTree()))
566     {
567         uno::Reference <frame::XModel> xModel = GetModel();
568         uno::Reference <lang::XUnoTunnel> xTunnel;
569         xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY);
570         SmModel *pModel = reinterpret_cast<SmModel *>
571             (xTunnel->getSomething(SmModel::getUnoTunnelId()));
572 
573         if (pModel)
574         {
575             SmDocShell *pDocShell =
576                 static_cast<SmDocShell*>(pModel->GetObjectShell());
577             pDocShell->SetFormulaTree(pTree);
578             if (0 == aText.Len())  //If we picked up no annotation text
579             {
580                 //Make up some editable text
581                 aText = pDocShell->GetText();
582                 pTree->CreateTextFromNode(aText);
583                 aText.EraseTrailingChars();
584                 if ((aText.GetChar(0) == '{') &&
585                     (aText.GetChar(aText.Len()-1) == '}'))
586                 {
587                     aText.Erase(0,1);
588                     aText.Erase(aText.Len()-1,1);
589                 }
590             }
591             pDocShell->SetText( String() );
592 
593             // Convert symbol names
594             SmParser &rParser = pDocShell->GetParser();
595             sal_Bool bVal = rParser.IsImportSymbolNames();
596             rParser.SetImportSymbolNames( sal_True );
597             SmNode *pTmpTree = rParser.Parse( aText );
598             aText = rParser.GetText();
599             delete pTmpTree;
600             rParser.SetImportSymbolNames( bVal );
601 
602             pDocShell->SetText( aText );
603         }
604         DBG_ASSERT(pModel,"So there *was* a uno problem after all");
605 
606         bSuccess = sal_True;
607     }
608 
609     SvXMLImport::endDocument();
610 }
611 
612 ////////////////////////////////////////////////////////////
613 
614 class SmXMLImportContext: public SvXMLImportContext
615 {
616 public:
617     SmXMLImportContext( SmXMLImport &rImport, sal_uInt16 nPrfx,
618         const OUString& rLName)
619         : SvXMLImportContext(rImport, nPrfx, rLName) {}
620 
621     const SmXMLImport& GetSmImport() const
622     {
623         return (const SmXMLImport&)GetImport();
624     }
625 
626     SmXMLImport& GetSmImport()
627     {
628         return (SmXMLImport&)GetImport();
629     }
630 
631     virtual void TCharacters(const OUString & /*rChars*/);
632     virtual void Characters(const OUString &rChars);
633     virtual SvXMLImportContext *CreateChildContext(sal_uInt16 /*nPrefix*/, const OUString& /*rLocalName*/, const uno::Reference< xml::sax::XAttributeList > & /*xAttrList*/);
634 };
635 
636 void SmXMLImportContext::TCharacters(const OUString & /*rChars*/)
637 {
638 }
639 
640 void SmXMLImportContext::Characters(const OUString &rChars)
641 {
642     /*
643     Whitespace occurring within the content of token elements is "trimmed"
644     from the ends (i.e. all whitespace at the beginning and end of the
645     content is removed), and "collapsed" internally (i.e. each sequence of
646     1 or more whitespace characters is replaced with one blank character).
647     */
648     //collapsing not done yet!
649     const OUString &rChars2 = rChars.trim();
650     if (rChars2.getLength())
651         TCharacters(rChars2/*.collapse()*/);
652 }
653 
654 SvXMLImportContext * SmXMLImportContext::CreateChildContext(sal_uInt16 /*nPrefix*/,
655     const OUString& /*rLocalName*/,
656     const uno::Reference< xml::sax::XAttributeList > & /*xAttrList*/)
657 {
658     return 0;
659 }
660 
661 ////////////////////////////////////////////////////////////
662 
663 struct SmXMLContext_Helper
664 {
665     sal_Int8 nIsBold;
666     sal_Int8 nIsItalic;
667     double nFontSize;
668     sal_Bool bFontNodeNeeded;
669     OUString sFontFamily;
670     OUString sColor;
671 
672     SmXMLImportContext rContext;
673 
674     SmXMLContext_Helper(SmXMLImportContext &rImport) :
675         nIsBold(-1), nIsItalic(-1), nFontSize(0.0), rContext(rImport)  {}
676 
677     void RetrieveAttrs(const uno::Reference< xml::sax::XAttributeList > &xAttrList );
678     void ApplyAttrs();
679 };
680 
681 void SmXMLContext_Helper::RetrieveAttrs(const uno::Reference<
682     xml::sax::XAttributeList > & xAttrList )
683 {
684     sal_Int8 nOldIsBold=nIsBold;
685     sal_Int8 nOldIsItalic=nIsItalic;
686     double nOldFontSize=nFontSize;
687     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
688     OUString sOldFontFamily = sFontFamily;
689     for (sal_Int16 i=0;i<nAttrCount;i++)
690     {
691         OUString sAttrName = xAttrList->getNameByIndex(i);
692         OUString aLocalName;
693         sal_uInt16 nPrefix = rContext.GetSmImport().GetNamespaceMap().
694             GetKeyByAttrName(sAttrName,&aLocalName);
695         OUString sValue = xAttrList->getValueByIndex(i);
696         const SvXMLTokenMap &rAttrTokenMap =
697             rContext.GetSmImport().GetPresLayoutAttrTokenMap();
698         switch(rAttrTokenMap.Get(nPrefix,aLocalName))
699         {
700             case XML_TOK_FONTWEIGHT:
701                 nIsBold = sValue.equals(GetXMLToken(XML_BOLD));
702                 break;
703             case XML_TOK_FONTSTYLE:
704                 nIsItalic = sValue.equals(GetXMLToken(XML_ITALIC));
705                 break;
706             case XML_TOK_FONTSIZE:
707                 SvXMLUnitConverter::convertDouble(nFontSize,sValue);
708                 rContext.GetSmImport().GetMM100UnitConverter().
709                     setXMLMeasureUnit(MAP_POINT);
710                 if (-1 == sValue.indexOf(GetXMLToken(XML_UNIT_PT)))
711                 {
712                     if (-1 == sValue.indexOf('%'))
713                         nFontSize=0.0;
714                     else
715                     {
716                         rContext.GetSmImport().GetMM100UnitConverter().
717                             setXMLMeasureUnit(MAP_RELATIVE);
718                     }
719                 }
720                 break;
721             case XML_TOK_FONTFAMILY:
722                 sFontFamily = sValue;
723                 break;
724             case XML_TOK_COLOR:
725                 sColor = sValue;
726                 break;
727             case XML_TOK_MATHCOLOR:
728                 sColor = sValue;
729                 break;
730             default:
731                 break;
732         }
733     }
734 
735     if ((nOldIsBold!=nIsBold) || (nOldIsItalic!=nIsItalic) ||
736         (nOldFontSize!=nFontSize) || (sOldFontFamily!=sFontFamily)
737         || sColor.getLength())
738         bFontNodeNeeded=sal_True;
739     else
740         bFontNodeNeeded=sal_False;
741 }
742 
743 void SmXMLContext_Helper::ApplyAttrs()
744 {
745     SmNodeStack &rNodeStack = rContext.GetSmImport().GetNodeStack();
746 
747     if (bFontNodeNeeded)
748     {
749         SmToken aToken;
750         aToken.cMathChar = '\0';
751         aToken.nGroup = 0;
752         aToken.nLevel = 5;
753 
754         if (nIsBold != -1)
755         {
756             if (nIsBold)
757                 aToken.eType = TBOLD;
758             else
759                 aToken.eType = TNBOLD;
760             SmStructureNode *pFontNode = static_cast<SmStructureNode *>
761                 (new SmFontNode(aToken));
762             pFontNode->SetSubNodes(0,rNodeStack.Pop());
763             rNodeStack.Push(pFontNode);
764         }
765         if (nIsItalic != -1)
766         {
767             if (nIsItalic)
768                 aToken.eType = TITALIC;
769             else
770                 aToken.eType = TNITALIC;
771             SmStructureNode *pFontNode = static_cast<SmStructureNode *>
772                 (new SmFontNode(aToken));
773             pFontNode->SetSubNodes(0,rNodeStack.Pop());
774             rNodeStack.Push(pFontNode);
775         }
776         if (nFontSize != 0.0)
777         {
778             aToken.eType = TSIZE;
779             SmFontNode *pFontNode = new SmFontNode(aToken);
780 
781             if (MAP_RELATIVE == rContext.GetSmImport().GetMM100UnitConverter().
782                 getXMLMeasureUnit())
783             {
784                 if (nFontSize < 100.00)
785                     pFontNode->SetSizeParameter(Fraction(100.00/nFontSize),
786                         FNTSIZ_DIVIDE);
787                 else
788                     pFontNode->SetSizeParameter(Fraction(nFontSize/100.00),
789                         FNTSIZ_MULTIPLY);
790             }
791             else
792                 pFontNode->SetSizeParameter(Fraction(nFontSize),FNTSIZ_ABSOLUT);
793 
794             pFontNode->SetSubNodes(0,rNodeStack.Pop());
795             rNodeStack.Push(pFontNode);
796         }
797         if (sFontFamily.getLength())
798         {
799             if (sFontFamily.equalsIgnoreAsciiCase(GetXMLToken(XML_FIXED)))
800                 aToken.eType = TFIXED;
801             else if (sFontFamily.equalsIgnoreAsciiCase(OUString(
802                 RTL_CONSTASCII_USTRINGPARAM("sans"))))
803                 aToken.eType = TSANS;
804             else if (sFontFamily.equalsIgnoreAsciiCase(OUString(
805                 RTL_CONSTASCII_USTRINGPARAM("serif"))))
806                 aToken.eType = TSERIF;
807             else //Just give up, we need to extend our font mechanism to be
808                 //more general
809                 return;
810 
811             aToken.aText = sFontFamily;
812             SmFontNode *pFontNode = new SmFontNode(aToken);
813             pFontNode->SetSubNodes(0,rNodeStack.Pop());
814             rNodeStack.Push(pFontNode);
815         }
816         if (sColor.getLength())
817         {
818             //Again we can only handle a small set of colours in
819             //StarMath for now.
820             const SvXMLTokenMap& rTokenMap =
821                 rContext.GetSmImport().GetColorTokenMap();
822             aToken.eType = static_cast<SmTokenType>(rTokenMap.Get(
823                 XML_NAMESPACE_MATH, sColor));
824             if (aToken.eType != -1)
825             {
826                 SmFontNode *pFontNode = new SmFontNode(aToken);
827                 pFontNode->SetSubNodes(0,rNodeStack.Pop());
828                 rNodeStack.Push(pFontNode);
829             }
830         }
831 
832     }
833 }
834 
835 ////////////////////////////////////////////////////////////
836 
837 class SmXMLDocContext_Impl : public SmXMLImportContext
838 {
839 public:
840     SmXMLDocContext_Impl( SmXMLImport &rImport, sal_uInt16 nPrfx,
841         const OUString& rLName)
842         : SmXMLImportContext(rImport,nPrfx,rLName) {}
843 
844     virtual SvXMLImportContext *CreateChildContext(sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > &xAttrList);
845 
846     void EndElement();
847 };
848 
849 ////////////////////////////////////////////////////////////
850 
851 /*avert thy gaze from the proginator*/
852 class SmXMLRowContext_Impl : public SmXMLDocContext_Impl
853 {
854 protected:
855     sal_uLong nElementCount;
856 
857 public:
858     SmXMLRowContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
859         const OUString& rLName)
860         : SmXMLDocContext_Impl(rImport,nPrefix,rLName)
861         { nElementCount = GetSmImport().GetNodeStack().Count(); }
862 
863     virtual SvXMLImportContext *CreateChildContext(sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > &xAttrList);
864 
865     SvXMLImportContext *StrictCreateChildContext(sal_uInt16 nPrefix,
866         const OUString& rLocalName,
867         const uno::Reference< xml::sax::XAttributeList > &xAttrList);
868 
869     void EndElement();
870 };
871 
872 ////////////////////////////////////////////////////////////
873 
874 class SmXMLFracContext_Impl : public SmXMLRowContext_Impl
875 {
876 public:
877     SmXMLFracContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
878         const OUString& rLName)
879         : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
880 
881     void EndElement();
882 };
883 
884 ////////////////////////////////////////////////////////////
885 
886 class SmXMLSqrtContext_Impl : public SmXMLRowContext_Impl
887 {
888 public:
889     SmXMLSqrtContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
890         const OUString& rLName)
891         : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
892 
893     void EndElement();
894 };
895 
896 ////////////////////////////////////////////////////////////
897 
898 class SmXMLRootContext_Impl : public SmXMLRowContext_Impl
899 {
900 public:
901     SmXMLRootContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
902         const OUString& rLName)
903         : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
904 
905     void EndElement();
906 };
907 
908 ////////////////////////////////////////////////////////////
909 
910 class SmXMLStyleContext_Impl : public SmXMLRowContext_Impl
911 {
912 protected:
913     SmXMLContext_Helper aStyleHelper;
914 
915 public:
916     /*Right now the style tag is completely ignored*/
917     SmXMLStyleContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
918         const OUString& rLName) : SmXMLRowContext_Impl(rImport,nPrefix,rLName),
919         aStyleHelper(*this) {}
920 
921     void EndElement();
922     void StartElement(const uno::Reference< xml::sax::XAttributeList > &xAttrList );
923 };
924 
925 void SmXMLStyleContext_Impl::StartElement(const uno::Reference<
926     xml::sax::XAttributeList > & xAttrList )
927 {
928 #if 1
929     aStyleHelper.RetrieveAttrs(xAttrList);
930 #else
931     sal_Int8 nOldIsBold=nIsBold;
932     sal_Int8 nOldIsItalic=nIsItalic;
933     double nOldFontSize=nFontSize;
934     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
935     OUString sOldFontFamily = sFontFamily;
936     for (sal_Int16 i=0;i<nAttrCount;i++)
937     {
938         OUString sAttrName = xAttrList->getNameByIndex(i);
939         OUString aLocalName;
940         sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
941             GetKeyByAttrName(sAttrName,&aLocalName);
942         OUString sValue = xAttrList->getValueByIndex(i);
943         const SvXMLTokenMap &rAttrTokenMap =
944             GetSmImport().GetPresLayoutAttrTokenMap();
945         switch(rAttrTokenMap.Get(nPrefix,aLocalName))
946         {
947             case XML_TOK_FONTWEIGHT:
948                 nIsBold = sValue.equals(GetXMLToken(XML_BOLD));
949                 break;
950             case XML_TOK_FONTSTYLE:
951                 nIsItalic = sValue.equals(GetXMLToken(XML_ITALIC));
952                 break;
953             case XML_TOK_FONTSIZE:
954                 SvXMLUnitConverter::convertDouble(nFontSize,sValue);
955                 GetSmImport().GetMM100UnitConverter().
956                     setXMLMeasureUnit(MAP_POINT);
957                 if (-1 == sValue.indexOf(GetXMLToken(XML_UNIT_PT)))
958                     if (-1 == sValue.indexOf('%'))
959                         nFontSize=0.0;
960                     else
961                     {
962                         GetSmImport().GetMM100UnitConverter().
963                             setXMLMeasureUnit(MAP_RELATIVE);
964                     }
965                 break;
966             case XML_TOK_FONTFAMILY:
967                 sFontFamily = sValue;
968                 break;
969             case XML_TOK_COLOR:
970                 sColor = sValue;
971                 break;
972             case XML_TOK_MATHCOLOR:
973                 sColor = sValue;
974                 break;
975             default:
976                 break;
977         }
978     }
979 
980     if ((nOldIsBold!=nIsBold) || (nOldIsItalic!=nIsItalic) ||
981         (nOldFontSize!=nFontSize) || (sOldFontFamily!=sFontFamily)
982         || sColor.getLength())
983         bFontNodeNeeded=sal_True;
984     else
985         bFontNodeNeeded=sal_False;
986 #endif
987 }
988 
989 
990 void SmXMLStyleContext_Impl::EndElement()
991 {
992     /*
993     <mstyle> accepts any number of arguments; if this number is not 1, its
994     contents are treated as a single "inferred <mrow>" containing its
995     arguments
996     */
997     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
998     if (rNodeStack.Count() - nElementCount > 1)
999         SmXMLRowContext_Impl::EndElement();
1000 #if 1
1001     aStyleHelper.ApplyAttrs();
1002 #else
1003     if (bFontNodeNeeded)
1004     {
1005         SmToken aToken;
1006         aToken.cMathChar = '\0';
1007         aToken.nGroup = 0;
1008         aToken.nLevel = 5;
1009 
1010         if (nIsBold != -1)
1011         {
1012             if (nIsBold)
1013                 aToken.eType = TBOLD;
1014             else
1015                 aToken.eType = TNBOLD;
1016             SmStructureNode *pFontNode = static_cast<SmStructureNode *>
1017                 (new SmFontNode(aToken));
1018             pFontNode->SetSubNodes(0,rNodeStack.Pop());
1019             rNodeStack.Push(pFontNode);
1020         }
1021         if (nIsItalic != -1)
1022         {
1023             if (nIsItalic)
1024                 aToken.eType = TITALIC;
1025             else
1026                 aToken.eType = TNITALIC;
1027             SmStructureNode *pFontNode = static_cast<SmStructureNode *>
1028                 (new SmFontNode(aToken));
1029             pFontNode->SetSubNodes(0,rNodeStack.Pop());
1030             rNodeStack.Push(pFontNode);
1031         }
1032         if (nFontSize != 0.0)
1033         {
1034             aToken.eType = TSIZE;
1035             SmFontNode *pFontNode = new SmFontNode(aToken);
1036 
1037             if (MAP_RELATIVE == GetSmImport().GetMM100UnitConverter().
1038                 getXMLMeasureUnit())
1039             {
1040                 if (nFontSize < 100.00)
1041                     pFontNode->SetSizeParameter(Fraction(100.00/nFontSize),
1042                         FNTSIZ_DIVIDE);
1043                 else
1044                     pFontNode->SetSizeParameter(Fraction(nFontSize/100.00),
1045                         FNTSIZ_MULTIPLY);
1046             }
1047             else
1048                 pFontNode->SetSizeParameter(Fraction(nFontSize),FNTSIZ_ABSOLUT);
1049 
1050             pFontNode->SetSubNodes(0,rNodeStack.Pop());
1051             rNodeStack.Push(pFontNode);
1052         }
1053         if (sFontFamily.getLength())
1054         {
1055             if (sFontFamily.equalsIgnoreCase(GetXMLToken(XML_FIXED)))
1056                 aToken.eType = TFIXED;
1057             else if (sFontFamily.equalsIgnoreCase(OUString(
1058                 RTL_CONSTASCII_USTRINGPARAM("sans"))))
1059                 aToken.eType = TSANS;
1060             else if (sFontFamily.equalsIgnoreCase(OUString(
1061                 RTL_CONSTASCII_USTRINGPARAM("serif"))))
1062                 aToken.eType = TSERIF;
1063             else //Just give up, we need to extend our font mechanism to be
1064                 //more general
1065                 return;
1066 
1067             aToken.aText = sFontFamily;
1068             SmFontNode *pFontNode = new SmFontNode(aToken);
1069             pFontNode->SetSubNodes(0,rNodeStack.Pop());
1070             rNodeStack.Push(pFontNode);
1071         }
1072         if (sColor.getLength())
1073         {
1074             //Again we can only handle a small set of colours in
1075             //StarMath for now.
1076             const SvXMLTokenMap& rTokenMap =
1077                 GetSmImport().GetColorTokenMap();
1078             aToken.eType = static_cast<SmTokenType>(rTokenMap.Get(
1079                 XML_NAMESPACE_MATH, sColor));
1080             if (aToken.eType != -1)
1081             {
1082                 SmFontNode *pFontNode = new SmFontNode(aToken);
1083                 pFontNode->SetSubNodes(0,rNodeStack.Pop());
1084                 rNodeStack.Push(pFontNode);
1085             }
1086         }
1087 
1088     }
1089 #endif
1090 }
1091 
1092 ////////////////////////////////////////////////////////////
1093 
1094 class SmXMLPaddedContext_Impl : public SmXMLRowContext_Impl
1095 {
1096 public:
1097     /*Right now the style tag is completely ignored*/
1098     SmXMLPaddedContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1099         const OUString& rLName)
1100         : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
1101 
1102     void EndElement();
1103 };
1104 
1105 void SmXMLPaddedContext_Impl::EndElement()
1106 {
1107     /*
1108     <mpadded> accepts any number of arguments; if this number is not 1, its
1109     contents are treated as a single "inferred <mrow>" containing its
1110     arguments
1111     */
1112     if (GetSmImport().GetNodeStack().Count() - nElementCount > 1)
1113         SmXMLRowContext_Impl::EndElement();
1114 }
1115 
1116 ////////////////////////////////////////////////////////////
1117 
1118 class SmXMLPhantomContext_Impl : public SmXMLRowContext_Impl
1119 {
1120 public:
1121     /*Right now the style tag is completely ignored*/
1122     SmXMLPhantomContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1123         const OUString& rLName)
1124         : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
1125 
1126     void EndElement();
1127 };
1128 
1129 void SmXMLPhantomContext_Impl::EndElement()
1130 {
1131     /*
1132     <mphantom> accepts any number of arguments; if this number is not 1, its
1133     contents are treated as a single "inferred <mrow>" containing its
1134     arguments
1135     */
1136     if (GetSmImport().GetNodeStack().Count() - nElementCount > 1)
1137         SmXMLRowContext_Impl::EndElement();
1138 
1139     SmToken aToken;
1140     aToken.cMathChar = '\0';
1141     aToken.nGroup = 0;
1142     aToken.nLevel = 5;
1143     aToken.eType = TPHANTOM;
1144 
1145     SmStructureNode *pPhantom = static_cast<SmStructureNode *>
1146         (new SmFontNode(aToken));
1147     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1148     pPhantom->SetSubNodes(0,rNodeStack.Pop());
1149     rNodeStack.Push(pPhantom);
1150 }
1151 
1152 ////////////////////////////////////////////////////////////
1153 
1154 class SmXMLFencedContext_Impl : public SmXMLRowContext_Impl
1155 {
1156 protected:
1157     sal_Unicode cBegin;
1158     sal_Unicode cEnd;
1159 
1160 public:
1161     SmXMLFencedContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1162         const OUString& rLName)
1163         : SmXMLRowContext_Impl(rImport,nPrefix,rLName),
1164         cBegin('('), cEnd(')') {}
1165 
1166     void StartElement(const uno::Reference< xml::sax::XAttributeList > & xAttrList );
1167     void EndElement();
1168 };
1169 
1170 
1171 void SmXMLFencedContext_Impl::StartElement(const uno::Reference<
1172     xml::sax::XAttributeList > & xAttrList )
1173 {
1174     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
1175     for (sal_Int16 i=0;i<nAttrCount;i++)
1176     {
1177         OUString sAttrName = xAttrList->getNameByIndex(i);
1178         OUString aLocalName;
1179         sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
1180             GetKeyByAttrName(sAttrName,&aLocalName);
1181         OUString sValue = xAttrList->getValueByIndex(i);
1182         const SvXMLTokenMap &rAttrTokenMap =
1183             GetSmImport().GetFencedAttrTokenMap();
1184         switch(rAttrTokenMap.Get(nPrefix,aLocalName))
1185         {
1186             //temp, starmath cannot handle multichar brackets (I think)
1187             case XML_TOK_OPEN:
1188                 cBegin = sValue[0];
1189                 break;
1190             case XML_TOK_CLOSE:
1191                 cEnd = sValue[0];
1192                 break;
1193             default:
1194                 /*Go to superclass*/
1195                 break;
1196         }
1197     }
1198 }
1199 
1200 
1201 void SmXMLFencedContext_Impl::EndElement()
1202 {
1203     SmToken aToken;
1204     aToken.cMathChar = '\0';
1205     aToken.nGroup = 0;
1206     aToken.aText = ',';
1207     aToken.eType = TLEFT;
1208     aToken.nLevel = 5;
1209 
1210     aToken.eType = TLPARENT;
1211     aToken.cMathChar = cBegin;
1212     SmStructureNode *pSNode = new SmBraceNode(aToken);
1213     SmNode *pLeft = new SmMathSymbolNode(aToken);
1214 
1215     aToken.cMathChar = cEnd;
1216     aToken.eType = TRPARENT;
1217     SmNode *pRight = new SmMathSymbolNode(aToken);
1218 
1219     SmNodeArray aRelationArray;
1220     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1221 
1222     aToken.cMathChar = '\0';
1223     aToken.aText = ',';
1224     aToken.eType = TIDENT;
1225 
1226     sal_uLong i = rNodeStack.Count() - nElementCount;
1227     if (rNodeStack.Count() - nElementCount > 1)
1228         i += rNodeStack.Count() - 1 - nElementCount;
1229     aRelationArray.resize(i);
1230     while (rNodeStack.Count() > nElementCount)
1231     {
1232         aRelationArray[--i] = rNodeStack.Pop();
1233         if (i > 1 && rNodeStack.Count() > 1)
1234             aRelationArray[--i] = new SmGlyphSpecialNode(aToken);
1235     }
1236 
1237     SmToken aDummy;
1238     SmStructureNode *pBody = new SmExpressionNode(aDummy);
1239     pBody->SetSubNodes(aRelationArray);
1240 
1241 
1242     pSNode->SetSubNodes(pLeft,pBody,pRight);
1243     pSNode->SetScaleMode(SCALE_HEIGHT);
1244     GetSmImport().GetNodeStack().Push(pSNode);
1245 }
1246 
1247 
1248 ////////////////////////////////////////////////////////////
1249 
1250 class SmXMLErrorContext_Impl : public SmXMLRowContext_Impl
1251 {
1252 public:
1253     SmXMLErrorContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1254         const OUString& rLName)
1255         : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
1256 
1257     void EndElement();
1258 };
1259 
1260 void SmXMLErrorContext_Impl::EndElement()
1261 {
1262     /*Right now the error tag is completely ignored, what
1263      can I do with it in starmath, ?, maybe we need a
1264      report window ourselves, do a test for validity of
1265      the xml input, use merrors, and then generate
1266      the markup inside the merror with a big red colour
1267      of something. For now just throw them all away.
1268      */
1269     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1270     while (rNodeStack.Count() > nElementCount)
1271     {
1272         SmNode *pNode = rNodeStack.Pop();
1273         delete pNode;
1274     }
1275 }
1276 
1277 ////////////////////////////////////////////////////////////
1278 
1279 class SmXMLNumberContext_Impl : public SmXMLImportContext
1280 {
1281 protected:
1282     SmToken aToken;
1283 
1284 public:
1285     SmXMLNumberContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1286         const OUString& rLName)
1287         : SmXMLImportContext(rImport,nPrefix,rLName)
1288     {
1289         aToken.cMathChar = '\0';
1290         aToken.nGroup = 0;
1291         aToken.nLevel = 5;
1292         aToken.eType = TNUMBER;
1293     }
1294 
1295     virtual void TCharacters(const OUString &rChars);
1296 
1297     void EndElement();
1298 };
1299 
1300 void SmXMLNumberContext_Impl::TCharacters(const OUString &rChars)
1301 {
1302     aToken.aText = rChars;
1303 }
1304 
1305 void SmXMLNumberContext_Impl::EndElement()
1306 {
1307     GetSmImport().GetNodeStack().Push(new SmTextNode(aToken,FNT_NUMBER));
1308 }
1309 
1310 ////////////////////////////////////////////////////////////
1311 
1312 class SmXMLAnnotationContext_Impl : public SmXMLImportContext
1313 {
1314     sal_Bool bIsStarMath;
1315 
1316 public:
1317     SmXMLAnnotationContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1318         const OUString& rLName)
1319         : SmXMLImportContext(rImport,nPrefix,rLName), bIsStarMath(sal_False) {}
1320 
1321     virtual void Characters(const OUString &rChars);
1322 
1323     void StartElement(const uno::Reference<xml::sax::XAttributeList > & xAttrList );
1324 };
1325 
1326 void SmXMLAnnotationContext_Impl::StartElement(const uno::Reference<
1327     xml::sax::XAttributeList > & xAttrList )
1328 {
1329     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
1330     for (sal_Int16 i=0;i<nAttrCount;i++)
1331     {
1332         OUString sAttrName = xAttrList->getNameByIndex(i);
1333         OUString aLocalName;
1334         sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
1335             GetKeyByAttrName(sAttrName,&aLocalName);
1336 
1337         OUString sValue = xAttrList->getValueByIndex(i);
1338         const SvXMLTokenMap &rAttrTokenMap =
1339             GetSmImport().GetAnnotationAttrTokenMap();
1340         switch(rAttrTokenMap.Get(nPrefix,aLocalName))
1341         {
1342             case XML_TOK_ENCODING:
1343                 bIsStarMath= sValue.equals(
1344                     OUString(RTL_CONSTASCII_USTRINGPARAM("StarMath 5.0")));
1345                 break;
1346             default:
1347                 break;
1348         }
1349     }
1350 }
1351 
1352 void SmXMLAnnotationContext_Impl::Characters(const OUString &rChars)
1353 {
1354     if (bIsStarMath)
1355         GetSmImport().GetText().Append(String(rChars));
1356 }
1357 
1358 ////////////////////////////////////////////////////////////
1359 
1360 class SmXMLTextContext_Impl : public SmXMLImportContext
1361 {
1362 protected:
1363     SmToken aToken;
1364 
1365 public:
1366     SmXMLTextContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1367         const OUString& rLName)
1368         : SmXMLImportContext(rImport,nPrefix,rLName)
1369     {
1370         aToken.cMathChar = '\0';
1371         aToken.nGroup = 0;
1372         aToken.nLevel = 5;
1373         aToken.eType = TTEXT;
1374     }
1375 
1376     virtual void TCharacters(const OUString &rChars);
1377 
1378     void EndElement();
1379 };
1380 
1381 void SmXMLTextContext_Impl::TCharacters(const OUString &rChars)
1382 {
1383     aToken.aText = rChars;
1384 }
1385 
1386 void SmXMLTextContext_Impl::EndElement()
1387 {
1388     GetSmImport().GetNodeStack().Push(new SmTextNode(aToken,FNT_TEXT));
1389 }
1390 
1391 ////////////////////////////////////////////////////////////
1392 
1393 class SmXMLStringContext_Impl : public SmXMLImportContext
1394 {
1395 protected:
1396     SmToken aToken;
1397 
1398 public:
1399     SmXMLStringContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1400         const OUString& rLName)
1401         : SmXMLImportContext(rImport,nPrefix,rLName)
1402     {
1403         aToken.cMathChar = '\0';
1404         aToken.nGroup = 0;
1405         aToken.nLevel = 5;
1406         aToken.eType = TTEXT;
1407     }
1408 
1409     virtual void TCharacters(const OUString &rChars);
1410 
1411     void EndElement();
1412 };
1413 
1414 void SmXMLStringContext_Impl::TCharacters(const OUString &rChars)
1415 {
1416     /*
1417     The content of <ms> elements should be rendered with visible "escaping" of
1418     certain characters in the content, including at least "double quote"
1419     itself, and preferably whitespace other than individual blanks. The intent
1420     is for the viewer to see that the expression is a string literal, and to
1421     see exactly which characters form its content. For example, <ms>double
1422     quote is "</ms> might be rendered as "double quote is \"".
1423 
1424     Obviously this isn't fully done here.
1425     */
1426     aToken.aText.Erase();
1427     aToken.aText += '\"';
1428     aToken.aText += String(rChars);
1429     aToken.aText += '\"';
1430 }
1431 
1432 void SmXMLStringContext_Impl::EndElement()
1433 {
1434     GetSmImport().GetNodeStack().Push(new SmTextNode(aToken,FNT_FIXED));
1435 }
1436 
1437 ////////////////////////////////////////////////////////////
1438 
1439 class SmXMLIdentifierContext_Impl : public SmXMLImportContext
1440 {
1441 protected:
1442     SmXMLContext_Helper aStyleHelper;
1443     SmToken aToken;
1444 
1445 public:
1446     SmXMLIdentifierContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1447         const OUString& rLName)
1448         : SmXMLImportContext(rImport,nPrefix,rLName),aStyleHelper(*this)
1449     {
1450         aToken.cMathChar = '\0';
1451         aToken.nGroup = 0;
1452         aToken.nLevel = 5;
1453         aToken.eType = TIDENT;
1454     }
1455 
1456     void TCharacters(const OUString &rChars);
1457     void StartElement(const uno::Reference< xml::sax::XAttributeList > & xAttrList )
1458     {
1459         aStyleHelper.RetrieveAttrs(xAttrList);
1460     };
1461     void EndElement();
1462 };
1463 
1464 void SmXMLIdentifierContext_Impl::EndElement()
1465 {
1466     SmTextNode *pNode = 0;
1467     //we will handle identifier italic/normal here instead of with a standalone
1468     //font node
1469     if (((aStyleHelper.nIsItalic == -1) && (aToken.aText.Len() > 1))
1470         || ((aStyleHelper.nIsItalic == 0) && (aToken.aText.Len() == 1)))
1471     {
1472         pNode = new SmTextNode(aToken,FNT_FUNCTION);
1473         pNode->GetFont().SetItalic(ITALIC_NONE);
1474         aStyleHelper.nIsItalic = -1;
1475     }
1476     else
1477         pNode = new SmTextNode(aToken,FNT_VARIABLE);
1478     if (aStyleHelper.bFontNodeNeeded && aStyleHelper.nIsItalic != -1)
1479     {
1480         if (aStyleHelper.nIsItalic)
1481             pNode->GetFont().SetItalic(ITALIC_NORMAL);
1482         else
1483             pNode->GetFont().SetItalic(ITALIC_NONE);
1484     }
1485 
1486     if ((-1!=aStyleHelper.nIsBold) || (0.0!=aStyleHelper.nFontSize) ||
1487         (aStyleHelper.sFontFamily.getLength()) ||
1488         aStyleHelper.sColor.getLength())
1489         aStyleHelper.bFontNodeNeeded=sal_True;
1490     else
1491         aStyleHelper.bFontNodeNeeded=sal_False;
1492     if (aStyleHelper.bFontNodeNeeded)
1493         aStyleHelper.ApplyAttrs();
1494     GetSmImport().GetNodeStack().Push(pNode);
1495 }
1496 
1497 void SmXMLIdentifierContext_Impl::TCharacters(const OUString &rChars)
1498 {
1499     aToken.aText = rChars;
1500 }
1501 
1502 ////////////////////////////////////////////////////////////
1503 
1504 class SmXMLOperatorContext_Impl : public SmXMLImportContext
1505 {
1506     sal_Bool bIsStretchy;
1507 
1508 protected:
1509     SmToken aToken;
1510 
1511 public:
1512     SmXMLOperatorContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1513         const OUString& rLName)
1514         : SmXMLImportContext(rImport,nPrefix,rLName), bIsStretchy(sal_False)
1515     {
1516         aToken.nGroup = 0;
1517         aToken.eType = TSPECIAL;
1518         aToken.nLevel = 5;
1519     }
1520 
1521     void TCharacters(const OUString &rChars);
1522     void StartElement(const uno::Reference< xml::sax::XAttributeList > &xAttrList );
1523     void EndElement();
1524 };
1525 
1526 void SmXMLOperatorContext_Impl::TCharacters(const OUString &rChars)
1527 {
1528     aToken.cMathChar = rChars[0];
1529 }
1530 
1531 void SmXMLOperatorContext_Impl::EndElement()
1532 {
1533     SmMathSymbolNode *pNode = new SmMathSymbolNode(aToken);
1534     //For stretchy scaling the scaling must be retrieved from this node
1535     //and applied to the expression itself so as to get the expression
1536     //to scale the operator to the height of the expression itself
1537     if (bIsStretchy)
1538         pNode->SetScaleMode(SCALE_HEIGHT);
1539     GetSmImport().GetNodeStack().Push(pNode);
1540 }
1541 
1542 
1543 
1544 void SmXMLOperatorContext_Impl::StartElement(const uno::Reference<
1545     xml::sax::XAttributeList > & xAttrList )
1546 {
1547     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
1548     for (sal_Int16 i=0;i<nAttrCount;i++)
1549     {
1550         OUString sAttrName = xAttrList->getNameByIndex(i);
1551         OUString aLocalName;
1552         sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
1553             GetKeyByAttrName(sAttrName,&aLocalName);
1554 
1555         OUString sValue = xAttrList->getValueByIndex(i);
1556         const SvXMLTokenMap &rAttrTokenMap =
1557             GetSmImport().GetOperatorAttrTokenMap();
1558         switch(rAttrTokenMap.Get(nPrefix,aLocalName))
1559         {
1560             case XML_TOK_STRETCHY:
1561                 bIsStretchy = sValue.equals(
1562                     GetXMLToken(XML_TRUE));
1563                 break;
1564             default:
1565                 break;
1566         }
1567     }
1568 }
1569 
1570 
1571 ////////////////////////////////////////////////////////////
1572 
1573 class SmXMLSpaceContext_Impl : public SmXMLImportContext
1574 {
1575 public:
1576     SmXMLSpaceContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1577         const OUString& rLName)
1578         : SmXMLImportContext(rImport,nPrefix,rLName) {}
1579 
1580     void StartElement(const uno::Reference< xml::sax::XAttributeList >& xAttrList );
1581 };
1582 
1583 void SmXMLSpaceContext_Impl::StartElement(
1584     const uno::Reference<xml::sax::XAttributeList > & /*xAttrList*/ )
1585 {
1586     SmToken aToken;
1587     aToken.cMathChar = '\0';
1588     aToken.nGroup = 0;
1589     aToken.eType = TBLANK;
1590     aToken.nLevel = 5;
1591     SmBlankNode *pBlank = new SmBlankNode(aToken);
1592     pBlank->IncreaseBy(aToken);
1593     GetSmImport().GetNodeStack().Push(pBlank);
1594 }
1595 
1596 ////////////////////////////////////////////////////////////
1597 
1598 class SmXMLSubContext_Impl : public SmXMLRowContext_Impl
1599 {
1600 protected:
1601     void GenericEndElement(SmTokenType eType,SmSubSup aSubSup);
1602 
1603 public:
1604     SmXMLSubContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1605         const OUString& rLName)
1606         : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
1607 
1608     void EndElement()
1609     {
1610         GenericEndElement(TRSUB,RSUB);
1611     }
1612 };
1613 
1614 
1615 void SmXMLSubContext_Impl::GenericEndElement(SmTokenType eType, SmSubSup eSubSup)
1616 {
1617     /*The <msub> element requires exactly 2 arguments.*/
1618     const bool bNodeCheck = GetSmImport().GetNodeStack().Count() - nElementCount == 2;
1619     DBG_ASSERT( bNodeCheck, "Sub has not two arguments" );
1620     if (!bNodeCheck)
1621         return;
1622 
1623     SmToken aToken;
1624     aToken.cMathChar = '\0';
1625     aToken.nGroup = 0;
1626     aToken.nLevel = 0;
1627     aToken.eType = eType;
1628     SmSubSupNode *pNode = new SmSubSupNode(aToken);
1629     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1630 
1631     // initialize subnodes array
1632     SmNodeArray  aSubNodes;
1633     aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES);
1634     for (sal_uLong i = 1;  i < aSubNodes.size();  i++)
1635         aSubNodes[i] = NULL;
1636 
1637     aSubNodes[eSubSup+1] = rNodeStack.Pop();
1638     aSubNodes[0] = rNodeStack.Pop();
1639     pNode->SetSubNodes(aSubNodes);
1640     rNodeStack.Push(pNode);
1641 }
1642 
1643 ////////////////////////////////////////////////////////////
1644 
1645 class SmXMLSupContext_Impl : public SmXMLSubContext_Impl
1646 {
1647 public:
1648     SmXMLSupContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1649         const OUString& rLName)
1650         : SmXMLSubContext_Impl(rImport,nPrefix,rLName) {}
1651 
1652     void EndElement()
1653     {
1654         GenericEndElement(TRSUP,RSUP);
1655     }
1656 };
1657 
1658 ////////////////////////////////////////////////////////////
1659 
1660 class SmXMLSubSupContext_Impl : public SmXMLRowContext_Impl
1661 {
1662 protected:
1663     void GenericEndElement(SmTokenType eType, SmSubSup aSub,SmSubSup aSup);
1664 
1665 public:
1666     SmXMLSubSupContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1667         const OUString& rLName)
1668         : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
1669 
1670     void EndElement()
1671     {
1672         GenericEndElement(TRSUB,RSUB,RSUP);
1673     }
1674 };
1675 
1676 void SmXMLSubSupContext_Impl::GenericEndElement(SmTokenType eType,
1677         SmSubSup aSub,SmSubSup aSup)
1678 {
1679     /*The <msub> element requires exactly 3 arguments.*/
1680     const bool bNodeCheck = GetSmImport().GetNodeStack().Count() - nElementCount == 3;
1681     DBG_ASSERT( bNodeCheck, "SubSup has not three arguments" );
1682     if (!bNodeCheck)
1683         return;
1684 
1685     SmToken aToken;
1686     aToken.cMathChar = '\0';
1687     aToken.nGroup = 0;
1688     aToken.nLevel = 0;
1689     aToken.eType = eType;
1690     SmSubSupNode *pNode = new SmSubSupNode(aToken);
1691     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1692 
1693     // initialize subnodes array
1694     SmNodeArray  aSubNodes;
1695     aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES);
1696     for (sal_uLong i = 1;  i < aSubNodes.size();  i++)
1697         aSubNodes[i] = NULL;
1698 
1699     aSubNodes[aSup+1] = rNodeStack.Pop();
1700     aSubNodes[aSub+1] = rNodeStack.Pop();
1701     aSubNodes[0] =  rNodeStack.Pop();
1702     pNode->SetSubNodes(aSubNodes);
1703     rNodeStack.Push(pNode);
1704 }
1705 
1706 ////////////////////////////////////////////////////////////
1707 
1708 class SmXMLUnderContext_Impl : public SmXMLSubContext_Impl
1709 {
1710 protected:
1711     sal_Int16 nAttrCount;
1712 
1713 public:
1714     SmXMLUnderContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1715         const OUString& rLName)
1716         : SmXMLSubContext_Impl(rImport,nPrefix,rLName) {}
1717 
1718     void StartElement(const uno::Reference< xml::sax::XAttributeList > &xAttrList );
1719     void EndElement();
1720     void HandleAccent();
1721 };
1722 
1723 void SmXMLUnderContext_Impl::StartElement(const uno::Reference<
1724     xml::sax::XAttributeList > & xAttrList )
1725 {
1726     nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
1727 }
1728 
1729 void SmXMLUnderContext_Impl::HandleAccent()
1730 {
1731     const bool bNodeCheck = GetSmImport().GetNodeStack().Count() - nElementCount == 2;
1732     DBG_ASSERT( bNodeCheck, "Sub has not two arguments" );
1733     if (!bNodeCheck)
1734         return;
1735 
1736     /*Just one special case for the underline thing*/
1737     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1738     SmNode *pTest = rNodeStack.Pop();
1739     SmToken aToken;
1740     aToken.cMathChar = '\0';
1741     aToken.nGroup = 0;
1742     aToken.nLevel = 0;
1743     aToken.eType = TUNDERLINE;
1744 
1745 
1746     SmNodeArray aSubNodes;
1747     aSubNodes.resize(2);
1748 
1749     SmStructureNode *pNode = new SmAttributNode(aToken);
1750     if ((pTest->GetToken().cMathChar & 0x0FFF) == 0x0332)
1751     {
1752         aSubNodes[0] = new SmRectangleNode(aToken);
1753         delete pTest;
1754     }
1755     else
1756         aSubNodes[0] = pTest;
1757 
1758     aSubNodes[1] = rNodeStack.Pop();
1759     pNode->SetSubNodes(aSubNodes);
1760     pNode->SetScaleMode(SCALE_WIDTH);
1761     rNodeStack.Push(pNode);
1762 }
1763 
1764 
1765 void SmXMLUnderContext_Impl::EndElement()
1766 {
1767     if (!nAttrCount)
1768         GenericEndElement(TCSUB,CSUB);
1769     else
1770         HandleAccent();
1771 #if 0
1772     //UnderBrace trick
1773     SmStructureNode *pNode = rNodeStack.Pop();
1774     if (pNode->GetSubNode(1)->GetToken().cMathChar == (0x0332|0xf000))
1775     if (pNode->GetSubNode(0)->GetToken().cMathChar == (0x0332|0xf000))
1776 #endif
1777 }
1778 
1779 ////////////////////////////////////////////////////////////
1780 
1781 class SmXMLOverContext_Impl : public SmXMLSubContext_Impl
1782 {
1783 protected:
1784     sal_Int16 nAttrCount;
1785 
1786 public:
1787     SmXMLOverContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1788         const OUString& rLName)
1789         : SmXMLSubContext_Impl(rImport,nPrefix,rLName), nAttrCount(0) {}
1790 
1791     void EndElement();
1792     void StartElement(const uno::Reference< xml::sax::XAttributeList > &xAttrList );
1793     void HandleAccent();
1794 };
1795 
1796 
1797 void SmXMLOverContext_Impl::StartElement(const uno::Reference<
1798     xml::sax::XAttributeList > & xAttrList )
1799 {
1800     nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
1801 }
1802 
1803 
1804 void SmXMLOverContext_Impl::EndElement()
1805 {
1806     if (!nAttrCount)
1807         GenericEndElement(TCSUP,CSUP);
1808     else
1809         HandleAccent();
1810 }
1811 
1812 
1813 void SmXMLOverContext_Impl::HandleAccent()
1814 {
1815     const bool bNodeCheck = GetSmImport().GetNodeStack().Count() - nElementCount == 2;
1816     DBG_ASSERT( bNodeCheck, "Sub has not two arguments" );
1817     if (!bNodeCheck)
1818         return;
1819 
1820     SmToken aToken;
1821     aToken.cMathChar = '\0';
1822     aToken.nGroup = 0;
1823     aToken.nLevel = 0;
1824     aToken.eType = TACUTE;
1825 
1826     SmAttributNode *pNode = new SmAttributNode(aToken);
1827     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1828 
1829     SmNodeArray aSubNodes;
1830     aSubNodes.resize(2);
1831     aSubNodes[0] = rNodeStack.Pop();
1832     aSubNodes[1] = rNodeStack.Pop();
1833     pNode->SetSubNodes(aSubNodes);
1834     pNode->SetScaleMode(SCALE_WIDTH);
1835     rNodeStack.Push(pNode);
1836 
1837 }
1838 
1839 ////////////////////////////////////////////////////////////
1840 
1841 class SmXMLUnderOverContext_Impl : public SmXMLSubSupContext_Impl
1842 {
1843 public:
1844     SmXMLUnderOverContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1845         const OUString& rLName)
1846         : SmXMLSubSupContext_Impl(rImport,nPrefix,rLName) {}
1847 
1848     void EndElement()
1849     {
1850         GenericEndElement(TCSUB,CSUB,CSUP);
1851     }
1852 };
1853 
1854 ////////////////////////////////////////////////////////////
1855 
1856 class SmXMLMultiScriptsContext_Impl : public SmXMLSubSupContext_Impl
1857 {
1858     sal_Bool bHasPrescripts;
1859 
1860 public:
1861     SmXMLMultiScriptsContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1862         const OUString& rLName) :
1863         SmXMLSubSupContext_Impl(rImport,nPrefix,rLName),
1864         bHasPrescripts(sal_False) {}
1865 
1866     void EndElement();
1867     void MiddleElement();
1868     SvXMLImportContext *CreateChildContext(sal_uInt16 nPrefix,
1869         const OUString& rLocalName,
1870         const uno::Reference< xml::sax::XAttributeList > &xAttrList);
1871 };
1872 
1873 ////////////////////////////////////////////////////////////
1874 
1875 class SmXMLNoneContext_Impl : public SmXMLImportContext
1876 {
1877 public:
1878     SmXMLNoneContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1879         const OUString& rLName)
1880         : SmXMLImportContext(rImport,nPrefix,rLName) {}
1881 
1882     void EndElement();
1883 };
1884 
1885 
1886 void SmXMLNoneContext_Impl::EndElement(void)
1887 {
1888     SmToken aToken;
1889     aToken.cMathChar = '\0';
1890     aToken.nGroup = 0;
1891     aToken.aText.Erase();
1892     aToken.nLevel = 5;
1893     aToken.eType = TIDENT;
1894     GetSmImport().GetNodeStack().Push(
1895         new SmTextNode(aToken,FNT_VARIABLE));
1896 }
1897 
1898 ////////////////////////////////////////////////////////////
1899 
1900 class SmXMLPrescriptsContext_Impl : public SmXMLImportContext
1901 {
1902 public:
1903     SmXMLPrescriptsContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1904         const OUString& rLName)
1905         : SmXMLImportContext(rImport,nPrefix,rLName) {}
1906 };
1907 
1908 ////////////////////////////////////////////////////////////
1909 
1910 class SmXMLTableRowContext_Impl : public SmXMLRowContext_Impl
1911 {
1912 public:
1913     SmXMLTableRowContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1914         const OUString& rLName) :
1915         SmXMLRowContext_Impl(rImport,nPrefix,rLName)
1916         {}
1917 
1918     SvXMLImportContext *CreateChildContext(sal_uInt16 nPrefix,
1919         const OUString& rLocalName,
1920         const uno::Reference< xml::sax::XAttributeList > &xAttrList);
1921 };
1922 
1923 
1924 ////////////////////////////////////////////////////////////
1925 
1926 class SmXMLTableContext_Impl : public SmXMLTableRowContext_Impl
1927 {
1928 public:
1929     SmXMLTableContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1930         const OUString& rLName) :
1931         SmXMLTableRowContext_Impl(rImport,nPrefix,rLName)
1932         {}
1933 
1934     void EndElement();
1935     SvXMLImportContext *CreateChildContext(sal_uInt16 nPrefix,
1936         const OUString& rLocalName,
1937         const uno::Reference< xml::sax::XAttributeList > &xAttrList);
1938 };
1939 
1940 
1941 ////////////////////////////////////////////////////////////
1942 
1943 class SmXMLTableCellContext_Impl : public SmXMLRowContext_Impl
1944 {
1945 public:
1946     SmXMLTableCellContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1947         const OUString& rLName) :
1948         SmXMLRowContext_Impl(rImport,nPrefix,rLName)
1949         {}
1950 };
1951 
1952 ////////////////////////////////////////////////////////////
1953 
1954 class SmXMLAlignGroupContext_Impl : public SmXMLRowContext_Impl
1955 {
1956 public:
1957     SmXMLAlignGroupContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1958         const OUString& rLName) :
1959         SmXMLRowContext_Impl(rImport,nPrefix,rLName)
1960         {}
1961 
1962     /*Don't do anything with alignment for now*/
1963     void EndElement()
1964     {
1965     }
1966 };
1967 
1968 ////////////////////////////////////////////////////////////
1969 
1970 class SmXMLActionContext_Impl : public SmXMLRowContext_Impl
1971 {
1972 public:
1973     SmXMLActionContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1974         const OUString& rLName) :
1975         SmXMLRowContext_Impl(rImport,nPrefix,rLName)
1976         {}
1977 
1978     void EndElement();
1979 };
1980 
1981 ////////////////////////////////////////////////////////////
1982 
1983 // NB: virtually inherit so we can multiply inherit properly
1984 //     in SmXMLFlatDocContext_Impl
1985 class SmXMLOfficeContext_Impl : public virtual SvXMLImportContext
1986 {
1987 public:
1988     SmXMLOfficeContext_Impl( SmXMLImport &rImport, sal_uInt16 nPrfx,
1989         const OUString& rLName)
1990         : SvXMLImportContext(rImport,nPrfx,rLName) {}
1991 
1992     virtual SvXMLImportContext *CreateChildContext(sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > &xAttrList);
1993 };
1994 
1995 SvXMLImportContext *SmXMLOfficeContext_Impl::CreateChildContext(sal_uInt16 nPrefix,
1996         const OUString& rLocalName,
1997         const uno::Reference< xml::sax::XAttributeList > &xAttrList)
1998 {
1999     SvXMLImportContext *pContext = 0;
2000     if ( XML_NAMESPACE_OFFICE == nPrefix &&
2001         rLocalName == GetXMLToken(XML_META) )
2002     {
2003         DBG_WARNING("XML_TOK_DOC_META: should not have come here, maybe document is invalid?");
2004     }
2005     else if ( XML_NAMESPACE_OFFICE == nPrefix &&
2006         rLocalName == GetXMLToken(XML_SETTINGS) )
2007     {
2008         pContext = new XMLDocumentSettingsContext( GetImport(),
2009                                     XML_NAMESPACE_OFFICE, rLocalName,
2010                                     xAttrList );
2011     }
2012     else
2013         pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
2014 
2015     return pContext;
2016 }
2017 
2018 ////////////////////////////////////////////////////////////
2019 
2020 // context for flat file xml format
2021 class SmXMLFlatDocContext_Impl
2022     : public SmXMLOfficeContext_Impl, public SvXMLMetaDocumentContext
2023 {
2024 public:
2025     SmXMLFlatDocContext_Impl( SmXMLImport& i_rImport,
2026         sal_uInt16 i_nPrefix, const OUString & i_rLName,
2027         const uno::Reference<document::XDocumentProperties>& i_xDocProps,
2028         const uno::Reference<xml::sax::XDocumentHandler>& i_xDocBuilder);
2029 
2030     virtual ~SmXMLFlatDocContext_Impl();
2031 
2032     virtual SvXMLImportContext *CreateChildContext(sal_uInt16 i_nPrefix, const OUString& i_rLocalName, const uno::Reference<xml::sax::XAttributeList>& i_xAttrList);
2033 };
2034 
2035 SmXMLFlatDocContext_Impl::SmXMLFlatDocContext_Impl( SmXMLImport& i_rImport,
2036         sal_uInt16 i_nPrefix, const OUString & i_rLName,
2037         const uno::Reference<document::XDocumentProperties>& i_xDocProps,
2038         const uno::Reference<xml::sax::XDocumentHandler>& i_xDocBuilder) :
2039     SvXMLImportContext(i_rImport, i_nPrefix, i_rLName),
2040     SmXMLOfficeContext_Impl(i_rImport, i_nPrefix, i_rLName),
2041     SvXMLMetaDocumentContext(i_rImport, i_nPrefix, i_rLName,
2042         i_xDocProps, i_xDocBuilder)
2043 {
2044 }
2045 
2046 SmXMLFlatDocContext_Impl::~SmXMLFlatDocContext_Impl()
2047 {
2048 }
2049 
2050 SvXMLImportContext *SmXMLFlatDocContext_Impl::CreateChildContext(
2051     sal_uInt16 i_nPrefix, const OUString& i_rLocalName,
2052     const uno::Reference<xml::sax::XAttributeList>& i_xAttrList)
2053 {
2054     // behave like meta base class iff we encounter office:meta
2055     if ( XML_NAMESPACE_OFFICE == i_nPrefix &&
2056             i_rLocalName == GetXMLToken(XML_META) )
2057     {
2058         return SvXMLMetaDocumentContext::CreateChildContext(
2059                     i_nPrefix, i_rLocalName, i_xAttrList );
2060     }
2061     else
2062     {
2063         return SmXMLOfficeContext_Impl::CreateChildContext(
2064                     i_nPrefix, i_rLocalName, i_xAttrList );
2065     }
2066 }
2067 
2068 ////////////////////////////////////////////////////////////
2069 
2070 static __FAR_DATA SvXMLTokenMapEntry aPresLayoutElemTokenMap[] =
2071 {
2072     { XML_NAMESPACE_MATH,   XML_SEMANTICS, XML_TOK_SEMANTICS },
2073     { XML_NAMESPACE_MATH,   XML_MATH,      XML_TOK_MATH   },
2074     { XML_NAMESPACE_MATH,   XML_MSTYLE,    XML_TOK_MSTYLE  },
2075     { XML_NAMESPACE_MATH,   XML_MERROR,    XML_TOK_MERROR },
2076     { XML_NAMESPACE_MATH,   XML_MPHANTOM,  XML_TOK_MPHANTOM },
2077     { XML_NAMESPACE_MATH,   XML_MROW,      XML_TOK_MROW },
2078     { XML_NAMESPACE_MATH,   XML_MFRAC,     XML_TOK_MFRAC },
2079     { XML_NAMESPACE_MATH,   XML_MSQRT,     XML_TOK_MSQRT },
2080     { XML_NAMESPACE_MATH,   XML_MROOT,     XML_TOK_MROOT },
2081     { XML_NAMESPACE_MATH,   XML_MSUB,      XML_TOK_MSUB },
2082     { XML_NAMESPACE_MATH,   XML_MSUP,      XML_TOK_MSUP },
2083     { XML_NAMESPACE_MATH,   XML_MSUBSUP,   XML_TOK_MSUBSUP },
2084     { XML_NAMESPACE_MATH,   XML_MUNDER,    XML_TOK_MUNDER },
2085     { XML_NAMESPACE_MATH,   XML_MOVER,     XML_TOK_MOVER },
2086     { XML_NAMESPACE_MATH,   XML_MUNDEROVER,    XML_TOK_MUNDEROVER },
2087     { XML_NAMESPACE_MATH,   XML_MMULTISCRIPTS, XML_TOK_MMULTISCRIPTS },
2088     { XML_NAMESPACE_MATH,   XML_MTABLE,    XML_TOK_MTABLE },
2089     { XML_NAMESPACE_MATH,   XML_MACTION,   XML_TOK_MACTION },
2090     { XML_NAMESPACE_MATH,   XML_MFENCED,   XML_TOK_MFENCED },
2091     { XML_NAMESPACE_MATH,   XML_MPADDED,   XML_TOK_MPADDED },
2092     XML_TOKEN_MAP_END
2093 };
2094 
2095 static __FAR_DATA SvXMLTokenMapEntry aPresLayoutAttrTokenMap[] =
2096 {
2097     { XML_NAMESPACE_MATH,   XML_FONTWEIGHT,      XML_TOK_FONTWEIGHT    },
2098     { XML_NAMESPACE_MATH,   XML_FONTSTYLE,       XML_TOK_FONTSTYLE     },
2099     { XML_NAMESPACE_MATH,   XML_FONTSIZE,        XML_TOK_FONTSIZE      },
2100     { XML_NAMESPACE_MATH,   XML_FONTFAMILY,      XML_TOK_FONTFAMILY    },
2101     { XML_NAMESPACE_MATH,   XML_COLOR,           XML_TOK_COLOR },
2102     { XML_NAMESPACE_MATH,   XML_MATHCOLOR,       XML_TOK_MATHCOLOR },
2103     XML_TOKEN_MAP_END
2104 };
2105 
2106 static __FAR_DATA SvXMLTokenMapEntry aFencedAttrTokenMap[] =
2107 {
2108     { XML_NAMESPACE_MATH,   XML_OPEN,       XML_TOK_OPEN },
2109     { XML_NAMESPACE_MATH,   XML_CLOSE,      XML_TOK_CLOSE },
2110     XML_TOKEN_MAP_END
2111 };
2112 
2113 static __FAR_DATA SvXMLTokenMapEntry aOperatorAttrTokenMap[] =
2114 {
2115     { XML_NAMESPACE_MATH,   XML_STRETCHY,      XML_TOK_STRETCHY },
2116     XML_TOKEN_MAP_END
2117 };
2118 
2119 static __FAR_DATA SvXMLTokenMapEntry aAnnotationAttrTokenMap[] =
2120 {
2121     { XML_NAMESPACE_MATH,   XML_ENCODING,      XML_TOK_ENCODING },
2122     XML_TOKEN_MAP_END
2123 };
2124 
2125 
2126 static __FAR_DATA SvXMLTokenMapEntry aPresElemTokenMap[] =
2127 {
2128     { XML_NAMESPACE_MATH,   XML_ANNOTATION,    XML_TOK_ANNOTATION },
2129     { XML_NAMESPACE_MATH,   XML_MI,    XML_TOK_MI },
2130     { XML_NAMESPACE_MATH,   XML_MN,    XML_TOK_MN },
2131     { XML_NAMESPACE_MATH,   XML_MO,    XML_TOK_MO },
2132     { XML_NAMESPACE_MATH,   XML_MTEXT, XML_TOK_MTEXT },
2133     { XML_NAMESPACE_MATH,   XML_MSPACE,XML_TOK_MSPACE },
2134     { XML_NAMESPACE_MATH,   XML_MS,    XML_TOK_MS },
2135     { XML_NAMESPACE_MATH,   XML_MALIGNGROUP,   XML_TOK_MALIGNGROUP },
2136     XML_TOKEN_MAP_END
2137 };
2138 
2139 static __FAR_DATA SvXMLTokenMapEntry aPresScriptEmptyElemTokenMap[] =
2140 {
2141     { XML_NAMESPACE_MATH,   XML_MPRESCRIPTS,   XML_TOK_MPRESCRIPTS },
2142     { XML_NAMESPACE_MATH,   XML_NONE,  XML_TOK_NONE },
2143     XML_TOKEN_MAP_END
2144 };
2145 
2146 static __FAR_DATA SvXMLTokenMapEntry aPresTableElemTokenMap[] =
2147 {
2148     { XML_NAMESPACE_MATH,   XML_MTR,       XML_TOK_MTR },
2149     { XML_NAMESPACE_MATH,   XML_MTD,       XML_TOK_MTD },
2150     XML_TOKEN_MAP_END
2151 };
2152 
2153 static __FAR_DATA SvXMLTokenMapEntry aColorTokenMap[] =
2154 {
2155     { XML_NAMESPACE_MATH,   XML_BLACK,        TBLACK},
2156     { XML_NAMESPACE_MATH,   XML_WHITE,        TWHITE},
2157     { XML_NAMESPACE_MATH,   XML_RED,          TRED},
2158     { XML_NAMESPACE_MATH,   XML_GREEN,        TGREEN},
2159     { XML_NAMESPACE_MATH,   XML_BLUE,         TBLUE},
2160     { XML_NAMESPACE_MATH,   XML_AQUA,         TAQUA},
2161     { XML_NAMESPACE_MATH,   XML_FUCHSIA,      TFUCHSIA},
2162     { XML_NAMESPACE_MATH,   XML_YELLOW,       TYELLOW},
2163     { XML_NAMESPACE_MATH,   XML_NAVY,         TNAVY},
2164     { XML_NAMESPACE_MATH,   XML_TEAL,         TTEAL},
2165     { XML_NAMESPACE_MATH,   XML_MAROON,       TMAROON},
2166     { XML_NAMESPACE_MATH,   XML_PURPLE,       TPURPLE},
2167     { XML_NAMESPACE_MATH,   XML_OLIVE,        TOLIVE},
2168     { XML_NAMESPACE_MATH,   XML_GRAY,         TGRAY},
2169     { XML_NAMESPACE_MATH,   XML_SILVER,       TSILVER},
2170     { XML_NAMESPACE_MATH,   XML_LIME,         TLIME},
2171     XML_TOKEN_MAP_END
2172 };
2173 
2174 ////////////////////////////////////////////////////////////
2175 
2176 const SvXMLTokenMap& SmXMLImport::GetPresLayoutElemTokenMap()
2177 {
2178     if (!pPresLayoutElemTokenMap)
2179         pPresLayoutElemTokenMap = new SvXMLTokenMap(aPresLayoutElemTokenMap);
2180     return *pPresLayoutElemTokenMap;
2181 }
2182 
2183 const SvXMLTokenMap& SmXMLImport::GetPresLayoutAttrTokenMap()
2184 {
2185     if (!pPresLayoutAttrTokenMap)
2186         pPresLayoutAttrTokenMap = new SvXMLTokenMap(aPresLayoutAttrTokenMap);
2187     return *pPresLayoutAttrTokenMap;
2188 }
2189 
2190 
2191 const SvXMLTokenMap& SmXMLImport::GetFencedAttrTokenMap()
2192 {
2193     if (!pFencedAttrTokenMap)
2194         pFencedAttrTokenMap = new SvXMLTokenMap(aFencedAttrTokenMap);
2195     return *pFencedAttrTokenMap;
2196 }
2197 
2198 const SvXMLTokenMap& SmXMLImport::GetOperatorAttrTokenMap()
2199 {
2200     if (!pOperatorAttrTokenMap)
2201         pOperatorAttrTokenMap = new SvXMLTokenMap(aOperatorAttrTokenMap);
2202     return *pOperatorAttrTokenMap;
2203 }
2204 
2205 const SvXMLTokenMap& SmXMLImport::GetAnnotationAttrTokenMap()
2206 {
2207     if (!pAnnotationAttrTokenMap)
2208         pAnnotationAttrTokenMap = new SvXMLTokenMap(aAnnotationAttrTokenMap);
2209     return *pAnnotationAttrTokenMap;
2210 }
2211 
2212 const SvXMLTokenMap& SmXMLImport::GetPresElemTokenMap()
2213 {
2214     if (!pPresElemTokenMap)
2215         pPresElemTokenMap = new SvXMLTokenMap(aPresElemTokenMap);
2216     return *pPresElemTokenMap;
2217 }
2218 
2219 const SvXMLTokenMap& SmXMLImport::GetPresScriptEmptyElemTokenMap()
2220 {
2221     if (!pPresScriptEmptyElemTokenMap)
2222         pPresScriptEmptyElemTokenMap = new
2223             SvXMLTokenMap(aPresScriptEmptyElemTokenMap);
2224     return *pPresScriptEmptyElemTokenMap;
2225 }
2226 
2227 const SvXMLTokenMap& SmXMLImport::GetPresTableElemTokenMap()
2228 {
2229     if (!pPresTableElemTokenMap)
2230         pPresTableElemTokenMap = new SvXMLTokenMap(aPresTableElemTokenMap);
2231     return *pPresTableElemTokenMap;
2232 }
2233 
2234 const SvXMLTokenMap& SmXMLImport::GetColorTokenMap()
2235 {
2236     if (!pColorTokenMap)
2237         pColorTokenMap = new SvXMLTokenMap(aColorTokenMap);
2238     return *pColorTokenMap;
2239 }
2240 
2241 ////////////////////////////////////////////////////////////
2242 
2243 SvXMLImportContext *SmXMLDocContext_Impl::CreateChildContext(
2244     sal_uInt16 nPrefix,
2245     const OUString& rLocalName,
2246     const uno::Reference<xml::sax::XAttributeList>& xAttrList)
2247 {
2248     SvXMLImportContext* pContext = 0L;
2249 
2250     const SvXMLTokenMap& rTokenMap = GetSmImport().GetPresLayoutElemTokenMap();
2251 
2252     //sal_uInt32 nTest = rTokenMap.Get(nPrefix, rLocalName);
2253 
2254     switch(rTokenMap.Get(nPrefix, rLocalName))
2255     {
2256         //Consider semantics a dummy except for any starmath annotations
2257         case XML_TOK_SEMANTICS:
2258             pContext = GetSmImport().CreateRowContext(nPrefix,rLocalName,
2259                 xAttrList);
2260             break;
2261         /*General Layout Schemata*/
2262         case XML_TOK_MROW:
2263             pContext = GetSmImport().CreateRowContext(nPrefix,rLocalName,
2264                 xAttrList);
2265             break;
2266         case XML_TOK_MFRAC:
2267             pContext = GetSmImport().CreateFracContext(nPrefix,rLocalName,
2268                 xAttrList);
2269             break;
2270         case XML_TOK_MSQRT:
2271             pContext = GetSmImport().CreateSqrtContext(nPrefix,rLocalName,
2272                 xAttrList);
2273             break;
2274         case XML_TOK_MROOT:
2275             pContext = GetSmImport().CreateRootContext(nPrefix,rLocalName,
2276                 xAttrList);
2277             break;
2278         case XML_TOK_MSTYLE:
2279             pContext = GetSmImport().CreateStyleContext(nPrefix,rLocalName,
2280                 xAttrList);
2281             break;
2282         case XML_TOK_MERROR:
2283             pContext = GetSmImport().CreateErrorContext(nPrefix,rLocalName,
2284                 xAttrList);
2285             break;
2286         case XML_TOK_MPADDED:
2287             pContext = GetSmImport().CreatePaddedContext(nPrefix,rLocalName,
2288                 xAttrList);
2289             break;
2290         case XML_TOK_MPHANTOM:
2291             pContext = GetSmImport().CreatePhantomContext(nPrefix,rLocalName,
2292                 xAttrList);
2293             break;
2294         case XML_TOK_MFENCED:
2295             pContext = GetSmImport().CreateFencedContext(nPrefix,rLocalName,
2296                 xAttrList);
2297             break;
2298         /*Script and Limit Schemata*/
2299         case XML_TOK_MSUB:
2300             pContext = GetSmImport().CreateSubContext(nPrefix,rLocalName,
2301                 xAttrList);
2302             break;
2303         case XML_TOK_MSUP:
2304             pContext = GetSmImport().CreateSupContext(nPrefix,rLocalName,
2305                 xAttrList);
2306             break;
2307         case XML_TOK_MSUBSUP:
2308             pContext = GetSmImport().CreateSubSupContext(nPrefix,rLocalName,
2309                 xAttrList);
2310             break;
2311         case XML_TOK_MUNDER:
2312             pContext = GetSmImport().CreateUnderContext(nPrefix,rLocalName,
2313                 xAttrList);
2314             break;
2315         case XML_TOK_MOVER:
2316             pContext = GetSmImport().CreateOverContext(nPrefix,rLocalName,
2317                 xAttrList);
2318             break;
2319         case XML_TOK_MUNDEROVER:
2320             pContext = GetSmImport().CreateUnderOverContext(nPrefix,rLocalName,
2321                 xAttrList);
2322             break;
2323         case XML_TOK_MMULTISCRIPTS:
2324             pContext = GetSmImport().CreateMultiScriptsContext(nPrefix,
2325                 rLocalName, xAttrList);
2326             break;
2327         case XML_TOK_MTABLE:
2328             pContext = GetSmImport().CreateTableContext(nPrefix,
2329                 rLocalName, xAttrList);
2330             break;
2331         case XML_TOK_MACTION:
2332             pContext = GetSmImport().CreateActionContext(nPrefix,
2333                 rLocalName, xAttrList);
2334             break;
2335         default:
2336             /*Basically theres an implicit mrow around certain bare
2337              *elements, use a RowContext to see if this is one of
2338              *those ones*/
2339             SmXMLRowContext_Impl aTempContext(GetSmImport(),nPrefix,
2340                 GetXMLToken(XML_MROW));
2341 
2342             pContext = aTempContext.StrictCreateChildContext(nPrefix,
2343                 rLocalName, xAttrList);
2344             break;
2345     }
2346     return pContext;
2347 }
2348 
2349 void SmXMLDocContext_Impl::EndElement()
2350 {
2351     SmNodeArray ContextArray;
2352     ContextArray.resize(1);
2353     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2354 
2355     for (sal_uLong i=0;i< 1;i++)
2356         ContextArray[i] = rNodeStack.Pop();
2357 
2358     SmToken aDummy;
2359     SmStructureNode *pSNode = new SmLineNode(aDummy);
2360     pSNode->SetSubNodes(ContextArray);
2361     rNodeStack.Push(pSNode);
2362 
2363     SmNodeArray  LineArray;
2364     sal_uLong n = rNodeStack.Count();
2365     LineArray.resize(n);
2366     for (sal_uLong j = 0; j < n; j++)
2367         LineArray[n - (j + 1)] = rNodeStack.Pop();
2368     SmStructureNode *pSNode2 = new SmTableNode(aDummy);
2369     pSNode2->SetSubNodes(LineArray);
2370     rNodeStack.Push(pSNode2);
2371 }
2372 
2373 void SmXMLFracContext_Impl::EndElement()
2374 {
2375     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2376     const bool bNodeCheck = rNodeStack.Count() - nElementCount == 2;
2377     DBG_ASSERT( bNodeCheck, "Fraction (mfrac) tag is missing component" );
2378     if (!bNodeCheck)
2379         return;
2380 
2381     SmToken aToken;
2382     aToken.cMathChar = '\0';
2383     aToken.nGroup = 0;
2384     aToken.nLevel = 0;
2385     aToken.eType = TOVER;
2386     SmStructureNode *pSNode = new SmBinVerNode(aToken);
2387     SmNode *pOper = new SmRectangleNode(aToken);
2388     SmNode *pSecond = rNodeStack.Pop();
2389     SmNode *pFirst = rNodeStack.Pop();
2390     pSNode->SetSubNodes(pFirst,pOper,pSecond);
2391     rNodeStack.Push(pSNode);
2392 }
2393 
2394 void SmXMLRootContext_Impl::EndElement()
2395 {
2396     /*The <mroot> element requires exactly 2 arguments.*/
2397     const bool bNodeCheck = GetSmImport().GetNodeStack().Count() - nElementCount == 2;
2398     DBG_ASSERT( bNodeCheck, "Root tag is missing component" );
2399     if (!bNodeCheck)
2400         return;
2401 
2402     SmToken aToken;
2403     aToken.cMathChar = MS_SQRT;  //Temporary: alert, based on StarSymbol font
2404     aToken.nGroup = 0;
2405     aToken.nLevel = 0;
2406     aToken.eType = TNROOT;
2407     SmStructureNode *pSNode = new SmRootNode(aToken);
2408     SmNode *pOper = new SmRootSymbolNode(aToken);
2409     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2410     SmNode *pIndex = rNodeStack.Pop();
2411     SmNode *pBase = rNodeStack.Pop();
2412     pSNode->SetSubNodes(pIndex,pOper,pBase);
2413     rNodeStack.Push(pSNode);
2414 }
2415 
2416 void SmXMLSqrtContext_Impl::EndElement()
2417 {
2418     /*
2419     <msqrt> accepts any number of arguments; if this number is not 1, its
2420     contents are treated as a single "inferred <mrow>" containing its
2421     arguments
2422     */
2423     if (GetSmImport().GetNodeStack().Count() - nElementCount > 1)
2424         SmXMLRowContext_Impl::EndElement();
2425 
2426     SmToken aToken;
2427     aToken.cMathChar = MS_SQRT;  //Temporary: alert, based on StarSymbol font
2428     aToken.nGroup = 0;
2429     aToken.nLevel = 0;
2430     aToken.eType = TSQRT;
2431     SmStructureNode *pSNode = new SmRootNode(aToken);
2432     SmNode *pOper = new SmRootSymbolNode(aToken);
2433     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2434     pSNode->SetSubNodes(0,pOper,rNodeStack.Pop());
2435     rNodeStack.Push(pSNode);
2436 }
2437 
2438 void SmXMLRowContext_Impl::EndElement()
2439 {
2440     SmNodeArray aRelationArray;
2441     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2442     sal_uLong nSize = rNodeStack.Count()-nElementCount;
2443 
2444     if (nSize > 0)
2445     {
2446         aRelationArray.resize(nSize);
2447         for (sal_uLong j=rNodeStack.Count()-nElementCount;j > 0;j--)
2448             aRelationArray[j-1] = rNodeStack.Pop();
2449 
2450 
2451         //If the first or last element is an operator with stretchyness
2452         //set then we must create a brace node here from those elements,
2453         //removing the stretchness from the operators and applying it to
2454         //ourselves, and creating the appropriate dummy StarMath none bracket
2455         //to balance the arrangement
2456         if (((aRelationArray[0]->GetScaleMode() == SCALE_HEIGHT)
2457             && (aRelationArray[0]->GetType() == NMATH))
2458         || ((aRelationArray[nSize-1]->GetScaleMode() == SCALE_HEIGHT)
2459             && (aRelationArray[nSize-1]->GetType() == NMATH)))
2460         {
2461             SmToken aToken;
2462             aToken.cMathChar = '\0';
2463             aToken.nGroup = 0;
2464             aToken.nLevel = 5;
2465 
2466             int nLeft=0,nRight=0;
2467             if ((aRelationArray[0]->GetScaleMode() == SCALE_HEIGHT)
2468                 && (aRelationArray[0]->GetType() == NMATH))
2469             {
2470                 aToken = aRelationArray[0]->GetToken();
2471                 nLeft=1;
2472             }
2473             else
2474                 aToken.cMathChar = '\0';
2475 
2476             aToken.eType = TLPARENT;
2477             SmNode *pLeft = new SmMathSymbolNode(aToken);
2478 
2479             if ((aRelationArray[nSize-1]->GetScaleMode() == SCALE_HEIGHT)
2480                 && (aRelationArray[nSize-1]->GetType() == NMATH))
2481             {
2482                 aToken = aRelationArray[nSize-1]->GetToken();
2483                 nRight=1;
2484             }
2485             else
2486                 aToken.cMathChar = '\0';
2487 
2488             aToken.eType = TRPARENT;
2489             SmNode *pRight = new SmMathSymbolNode(aToken);
2490 
2491             SmNodeArray aRelationArray2;
2492 
2493             //!! nSize-nLeft-nRight may be < 0 !!
2494             int nRelArrSize = nSize-nLeft-nRight;
2495             if (nRelArrSize > 0)
2496             {
2497                 aRelationArray2.resize(nRelArrSize);
2498                 for (int i=0;i < nRelArrSize;i++)
2499                     aRelationArray2[i] = aRelationArray[i+nLeft];
2500             }
2501 
2502             SmToken aDummy;
2503             SmStructureNode *pSNode = new SmBraceNode(aToken);
2504             SmStructureNode *pBody = new SmExpressionNode(aDummy);
2505             pBody->SetSubNodes(aRelationArray2);
2506 
2507             pSNode->SetSubNodes(pLeft,pBody,pRight);
2508             pSNode->SetScaleMode(SCALE_HEIGHT);
2509             rNodeStack.Push(pSNode);
2510             return;
2511         }
2512     }
2513     else //Multiple newlines result in empty row elements
2514     {
2515         aRelationArray.resize(1);
2516         SmToken aToken;
2517         aToken.cMathChar = '\0';
2518         aToken.nGroup = 0;
2519         aToken.nLevel = 5;
2520         aToken.eType = TNEWLINE;
2521         aRelationArray[0] = new SmLineNode(aToken);
2522     }
2523 
2524     SmToken aDummy;
2525     SmStructureNode *pSNode = new SmExpressionNode(aDummy);
2526     pSNode->SetSubNodes(aRelationArray);
2527     rNodeStack.Push(pSNode);
2528 }
2529 
2530 
2531 SvXMLImportContext *SmXMLRowContext_Impl::StrictCreateChildContext(
2532     sal_uInt16 nPrefix,
2533     const OUString& rLocalName,
2534     const uno::Reference<xml::sax::XAttributeList>& xAttrList)
2535 {
2536     SvXMLImportContext* pContext = 0L;
2537 
2538     const SvXMLTokenMap& rTokenMap = GetSmImport().GetPresElemTokenMap();
2539     switch(rTokenMap.Get(nPrefix, rLocalName))
2540     {
2541         /*Note that these should accept malignmark subelements, but do not*/
2542         case XML_TOK_MN:
2543             pContext = GetSmImport().CreateNumberContext(nPrefix,rLocalName,
2544                 xAttrList);
2545             break;
2546         case XML_TOK_MI:
2547             pContext = GetSmImport().CreateIdentifierContext(nPrefix,rLocalName,
2548                 xAttrList);
2549             break;
2550         case XML_TOK_MO:
2551             pContext = GetSmImport().CreateOperatorContext(nPrefix,rLocalName,
2552                 xAttrList);
2553             break;
2554         case XML_TOK_MTEXT:
2555             pContext = GetSmImport().CreateTextContext(nPrefix,rLocalName,
2556                 xAttrList);
2557             break;
2558         case XML_TOK_MSPACE:
2559             pContext = GetSmImport().CreateSpaceContext(nPrefix,rLocalName,
2560                 xAttrList);
2561             break;
2562         case XML_TOK_MS:
2563             pContext = GetSmImport().CreateStringContext(nPrefix,rLocalName,
2564                 xAttrList);
2565             break;
2566 
2567         /*Note: The maligngroup should only be seen when the row
2568          * (or descendants) are in a table*/
2569         case XML_TOK_MALIGNGROUP:
2570             pContext = GetSmImport().CreateAlignGroupContext(nPrefix,rLocalName,
2571                 xAttrList);
2572             break;
2573 
2574         case XML_TOK_ANNOTATION:
2575             pContext = GetSmImport().CreateAnnotationContext(nPrefix,rLocalName,
2576                 xAttrList);
2577             break;
2578 
2579         default:
2580             break;
2581     }
2582     return pContext;
2583 }
2584 
2585 
2586 SvXMLImportContext *SmXMLRowContext_Impl::CreateChildContext(
2587     sal_uInt16 nPrefix,
2588     const OUString& rLocalName,
2589     const uno::Reference<xml::sax::XAttributeList>& xAttrList)
2590 {
2591     SvXMLImportContext* pContext = StrictCreateChildContext(nPrefix,
2592     rLocalName, xAttrList);
2593 
2594     if (!pContext)
2595     {
2596         //Hmm, unrecognized for this level, check to see if its
2597         //an element that can have an implicit schema around it
2598         pContext = SmXMLDocContext_Impl::CreateChildContext(nPrefix,
2599             rLocalName,xAttrList);
2600     }
2601     return pContext;
2602 }
2603 
2604 
2605 SvXMLImportContext *SmXMLMultiScriptsContext_Impl::CreateChildContext(
2606     sal_uInt16 nPrefix,
2607     const OUString& rLocalName,
2608     const uno::Reference<xml::sax::XAttributeList>& xAttrList)
2609 {
2610     SvXMLImportContext* pContext = 0L;
2611 
2612     const SvXMLTokenMap& rTokenMap = GetSmImport().
2613         GetPresScriptEmptyElemTokenMap();
2614     switch(rTokenMap.Get(nPrefix, rLocalName))
2615     {
2616         case XML_TOK_MPRESCRIPTS:
2617             MiddleElement();
2618             pContext = GetSmImport().CreatePrescriptsContext(nPrefix,
2619                 rLocalName, xAttrList);
2620             break;
2621         case XML_TOK_NONE:
2622             pContext = GetSmImport().CreateNoneContext(nPrefix,rLocalName,
2623                 xAttrList);
2624             break;
2625         default:
2626             pContext = SmXMLRowContext_Impl::CreateChildContext(nPrefix,
2627                 rLocalName,xAttrList);
2628             break;
2629     }
2630     return pContext;
2631 }
2632 
2633 void SmXMLMultiScriptsContext_Impl::MiddleElement()
2634 {
2635     bHasPrescripts=sal_True;
2636 
2637     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2638     DBG_ASSERT( rNodeStack.Count() - nElementCount > 0, "Sub has no arguments" );
2639     if (rNodeStack.Count()-nElementCount > 1)
2640     {
2641         SmToken aToken;
2642         aToken.cMathChar = '\0';
2643         aToken.nGroup = 0;
2644         aToken.nLevel = 0;
2645         aToken.eType = TRSUB;
2646         sal_uLong nFinalCount = rNodeStack.Count()-nElementCount-1;
2647 
2648         SmNodeStack aReverseStack;
2649         while (rNodeStack.Count()-nElementCount)
2650         {
2651             SmNode *pThing = rNodeStack.Pop();
2652             aReverseStack.Push(pThing);
2653         }
2654 
2655         for (sal_uLong nCount=0;nCount < nFinalCount;nCount+=2)
2656         {
2657             SmSubSupNode *pNode = new SmSubSupNode(aToken);
2658 
2659             // initialize subnodes array
2660             SmNodeArray  aSubNodes;
2661             aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES);
2662             for (sal_uLong i = 1;  i < aSubNodes.size();  i++)
2663                 aSubNodes[i] = NULL;
2664 
2665             /*On each loop the base and its sub sup pair becomes the
2666              base for the next loop to which the next sub sup pair is
2667              attached, i.e. wheels within wheels*/
2668             //if (nCount == 0)
2669             aSubNodes[0] = aReverseStack.Pop();
2670 
2671             SmNode *pScriptNode = aReverseStack.Pop();
2672 
2673             if (pScriptNode && ((pScriptNode->GetToken().eType != TIDENT) ||
2674                 (pScriptNode->GetToken().aText.Len())))
2675                 aSubNodes[RSUB+1] = pScriptNode;
2676             pScriptNode = aReverseStack.Pop();
2677             if (pScriptNode && ((pScriptNode->GetToken().eType != TIDENT) ||
2678                 (pScriptNode->GetToken().aText.Len())))
2679                 aSubNodes[RSUP+1] = pScriptNode;
2680 
2681             pNode->SetSubNodes(aSubNodes);
2682             aReverseStack.Push(pNode);
2683         }
2684         rNodeStack.Push(aReverseStack.Pop());
2685     }
2686 }
2687 
2688 
2689 void SmXMLTableContext_Impl::EndElement()
2690 {
2691     SmNodeArray aExpressionArray;
2692     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2693     SmNodeStack aReverseStack;
2694     aExpressionArray.resize(rNodeStack.Count()-nElementCount);
2695 
2696     sal_uLong nRows = rNodeStack.Count()-nElementCount;
2697     sal_uInt16 nCols = 0;
2698 
2699     SmStructureNode *pArray;
2700     for (sal_uLong i=rNodeStack.Count()-nElementCount;i > 0;i--)
2701     {
2702         pArray = (SmStructureNode *)rNodeStack.Pop();
2703         if (pArray->GetNumSubNodes() == 0)
2704         {
2705             //This is a little tricky, it is possible that there was
2706             //be elements that were not inside a <mtd> pair, in which
2707             //case they will not be in a row, i.e. they will not have
2708             //SubNodes, so we have to wait until here before we can
2709             //resolve the situation. Implicitsurrounding tags are
2710             //surprisingly difficult to get right within this
2711             //architecture
2712 
2713             SmNodeArray aRelationArray;
2714             aRelationArray.resize(1);
2715             aRelationArray[0] = pArray;
2716             SmToken aDummy;
2717             pArray = new SmExpressionNode(aDummy);
2718             pArray->SetSubNodes(aRelationArray);
2719         }
2720 
2721         if (pArray->GetNumSubNodes() > nCols)
2722             nCols = pArray->GetNumSubNodes();
2723         aReverseStack.Push(pArray);
2724     }
2725     aExpressionArray.resize(nCols*nRows);
2726     sal_uLong j=0;
2727     while (aReverseStack.Count())
2728     {
2729         pArray = (SmStructureNode *)aReverseStack.Pop();
2730         for (sal_uInt16 i=0;i<pArray->GetNumSubNodes();i++)
2731             aExpressionArray[j++] = pArray->GetSubNode(i);
2732     }
2733 
2734     SmToken aToken;
2735     aToken.cMathChar = '\0';
2736     aToken.nGroup = TRGROUP;
2737     aToken.nLevel = 0;
2738     aToken.eType = TMATRIX;
2739     SmMatrixNode *pSNode = new SmMatrixNode(aToken);
2740     pSNode->SetSubNodes(aExpressionArray);
2741     pSNode->SetRowCol(static_cast<sal_uInt16>(nRows),nCols);
2742     rNodeStack.Push(pSNode);
2743 }
2744 
2745 SvXMLImportContext *SmXMLTableRowContext_Impl::CreateChildContext(
2746     sal_uInt16 nPrefix,
2747     const OUString& rLocalName,
2748     const uno::Reference<xml::sax::XAttributeList>& xAttrList)
2749 {
2750     SvXMLImportContext* pContext = 0L;
2751 
2752     const SvXMLTokenMap& rTokenMap = GetSmImport().
2753         GetPresTableElemTokenMap();
2754     switch(rTokenMap.Get(nPrefix, rLocalName))
2755     {
2756         case XML_TOK_MTD:
2757             pContext = GetSmImport().CreateTableCellContext(nPrefix,
2758                 rLocalName, xAttrList);
2759             break;
2760         default:
2761             pContext = SmXMLRowContext_Impl::CreateChildContext(nPrefix,
2762                 rLocalName,xAttrList);
2763             break;
2764     }
2765     return pContext;
2766 }
2767 
2768 SvXMLImportContext *SmXMLTableContext_Impl::CreateChildContext(
2769     sal_uInt16 nPrefix,
2770     const OUString& rLocalName,
2771     const uno::Reference<xml::sax::XAttributeList>& xAttrList)
2772 {
2773     SvXMLImportContext* pContext = 0L;
2774 
2775     const SvXMLTokenMap& rTokenMap = GetSmImport().
2776         GetPresTableElemTokenMap();
2777     switch(rTokenMap.Get(nPrefix, rLocalName))
2778     {
2779         case XML_TOK_MTR:
2780             pContext = GetSmImport().CreateTableRowContext(nPrefix,rLocalName,
2781                 xAttrList);
2782             break;
2783         default:
2784             pContext = SmXMLTableRowContext_Impl::CreateChildContext(nPrefix,
2785                 rLocalName,xAttrList);
2786             break;
2787     }
2788     return pContext;
2789 }
2790 
2791 void SmXMLMultiScriptsContext_Impl::EndElement()
2792 {
2793     if (!bHasPrescripts)
2794         MiddleElement();
2795 
2796     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2797     if (rNodeStack.Count()-nElementCount > 1)
2798     {
2799         SmToken aToken;
2800         aToken.cMathChar = '\0';
2801         aToken.nGroup = 0;
2802         aToken.nLevel = 0;
2803         aToken.eType = TLSUB;
2804         sal_uLong nFinalCount = rNodeStack.Count()-nElementCount-1;
2805 
2806         SmNodeStack aReverseStack;
2807         while (rNodeStack.Count()-nElementCount)
2808             aReverseStack.Push(rNodeStack.Pop());
2809         for (sal_uLong nCount=0;nCount < nFinalCount;nCount+=2)
2810         {
2811             SmSubSupNode *pNode = new SmSubSupNode(aToken);
2812 
2813             // initialize subnodes array
2814             SmNodeArray  aSubNodes;
2815             aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES);
2816             for (sal_uLong i = 1;  i < aSubNodes.size();  i++)
2817                 aSubNodes[i] = NULL;
2818 
2819             /*On each loop the base and its sub sup pair becomes the
2820              base for the next loop to which the next sub sup pair is
2821              attached, i.e. wheels within wheels*/
2822             //if (nCount == 0)
2823             aSubNodes[0] = aReverseStack.Pop();
2824 
2825             SmNode *pScriptNode = aReverseStack.Pop();
2826             if (pScriptNode->GetToken().aText.Len())
2827                 aSubNodes[LSUB+1] = pScriptNode;
2828             pScriptNode = aReverseStack.Pop();
2829             if (pScriptNode->GetToken().aText.Len())
2830                 aSubNodes[LSUP+1] = pScriptNode;
2831 
2832             pNode->SetSubNodes(aSubNodes);
2833             aReverseStack.Push(pNode);
2834         }
2835         rNodeStack.Push(aReverseStack.Pop());
2836     }
2837 
2838 }
2839 void SmXMLActionContext_Impl::EndElement()
2840 {
2841     /*For now we will just assume that the
2842      selected attribute is one, and then just display
2843      that expression alone, i.e. remove all expect the
2844      first pushed one*/
2845 
2846     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2847     for (sal_uLong i=rNodeStack.Count()-nElementCount;i > 1;i--)
2848     {
2849         delete rNodeStack.Pop();
2850     }
2851 }
2852 
2853 SvXMLImportContext *SmXMLImport::CreateContext(sal_uInt16 nPrefix,
2854     const OUString &rLocalName,
2855     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2856 {
2857     if ( XML_NAMESPACE_OFFICE == nPrefix )
2858     {
2859         if ( (IsXMLToken(rLocalName, XML_DOCUMENT) ||
2860               IsXMLToken(rLocalName, XML_DOCUMENT_META)))
2861         {
2862             uno::Reference<xml::sax::XDocumentHandler> xDocBuilder(
2863                 mxServiceFactory->createInstance(
2864                     ::rtl::OUString::createFromAscii(
2865                         "com.sun.star.xml.dom.SAXDocumentBuilder")),
2866                     uno::UNO_QUERY_THROW);
2867             uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
2868                 GetModel(), uno::UNO_QUERY_THROW);
2869             return IsXMLToken(rLocalName, XML_DOCUMENT_META)
2870                 ? new SvXMLMetaDocumentContext(*this,
2871                         XML_NAMESPACE_OFFICE, rLocalName,
2872                         xDPS->getDocumentProperties(), xDocBuilder)
2873                 // flat OpenDocument file format -- this has not been tested...
2874                 : new SmXMLFlatDocContext_Impl( *this, nPrefix, rLocalName,
2875                             xDPS->getDocumentProperties(), xDocBuilder);
2876         }
2877         else
2878         {
2879             return new SmXMLOfficeContext_Impl( *this,nPrefix,rLocalName);
2880         }
2881     }
2882     else
2883         return new SmXMLDocContext_Impl(*this,nPrefix,rLocalName);
2884 }
2885 
2886 SvXMLImportContext *SmXMLImport::CreateRowContext(sal_uInt16 nPrefix,
2887     const OUString &rLocalName,
2888     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2889 {
2890         return new SmXMLRowContext_Impl(*this,nPrefix,rLocalName);
2891 }
2892 
2893 SvXMLImportContext *SmXMLImport::CreateTextContext(sal_uInt16 nPrefix,
2894     const OUString &rLocalName,
2895     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2896 {
2897     return new SmXMLTextContext_Impl(*this,nPrefix,rLocalName);
2898 }
2899 
2900 SvXMLImportContext *SmXMLImport::CreateAnnotationContext(sal_uInt16 nPrefix,
2901     const OUString &rLocalName,
2902     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2903 {
2904     return new SmXMLAnnotationContext_Impl(*this,nPrefix,rLocalName);
2905 }
2906 
2907 SvXMLImportContext *SmXMLImport::CreateStringContext(sal_uInt16 nPrefix,
2908     const OUString &rLocalName,
2909     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2910 {
2911     return new SmXMLStringContext_Impl(*this,nPrefix,rLocalName);
2912 }
2913 
2914 SvXMLImportContext *SmXMLImport::CreateNumberContext(sal_uInt16 nPrefix,
2915     const OUString &rLocalName,
2916     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2917 {
2918     return new SmXMLNumberContext_Impl(*this,nPrefix,rLocalName);
2919 }
2920 
2921 SvXMLImportContext *SmXMLImport::CreateIdentifierContext(sal_uInt16 nPrefix,
2922     const OUString &rLocalName,
2923     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2924 {
2925     return new SmXMLIdentifierContext_Impl(*this,nPrefix,rLocalName);
2926 }
2927 
2928 SvXMLImportContext *SmXMLImport::CreateOperatorContext(sal_uInt16 nPrefix,
2929     const OUString &rLocalName,
2930     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2931 {
2932     return new SmXMLOperatorContext_Impl(*this,nPrefix,rLocalName);
2933 }
2934 
2935 SvXMLImportContext *SmXMLImport::CreateSpaceContext(sal_uInt16 nPrefix,
2936     const OUString &rLocalName,
2937     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2938 {
2939     return new SmXMLSpaceContext_Impl(*this,nPrefix,rLocalName);
2940 }
2941 
2942 
2943 SvXMLImportContext *SmXMLImport::CreateFracContext(sal_uInt16 nPrefix,
2944     const OUString &rLocalName,
2945     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2946 {
2947     return new SmXMLFracContext_Impl(*this,nPrefix,rLocalName);
2948 }
2949 
2950 SvXMLImportContext *SmXMLImport::CreateSqrtContext(sal_uInt16 nPrefix,
2951     const OUString &rLocalName,
2952     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2953 {
2954     return new SmXMLSqrtContext_Impl(*this,nPrefix,rLocalName);
2955 }
2956 
2957 SvXMLImportContext *SmXMLImport::CreateRootContext(sal_uInt16 nPrefix,
2958     const OUString &rLocalName,
2959     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2960 {
2961     return new SmXMLRootContext_Impl(*this,nPrefix,rLocalName);
2962 }
2963 
2964 SvXMLImportContext *SmXMLImport::CreateStyleContext(sal_uInt16 nPrefix,
2965     const OUString &rLocalName,
2966     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2967 {
2968     return new SmXMLStyleContext_Impl(*this,nPrefix,rLocalName);
2969 }
2970 
2971 SvXMLImportContext *SmXMLImport::CreatePaddedContext(sal_uInt16 nPrefix,
2972     const OUString &rLocalName,
2973     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2974 {
2975     return new SmXMLPaddedContext_Impl(*this,nPrefix,rLocalName);
2976 }
2977 
2978 SvXMLImportContext *SmXMLImport::CreatePhantomContext(sal_uInt16 nPrefix,
2979     const OUString &rLocalName,
2980     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2981 {
2982     return new SmXMLPhantomContext_Impl(*this,nPrefix,rLocalName);
2983 }
2984 
2985 SvXMLImportContext *SmXMLImport::CreateFencedContext(sal_uInt16 nPrefix,
2986     const OUString &rLocalName,
2987     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2988 {
2989     return new SmXMLFencedContext_Impl(*this,nPrefix,rLocalName);
2990 }
2991 
2992 SvXMLImportContext *SmXMLImport::CreateErrorContext(sal_uInt16 nPrefix,
2993     const OUString &rLocalName,
2994     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2995 {
2996     return new SmXMLErrorContext_Impl(*this,nPrefix,rLocalName);
2997 }
2998 
2999 SvXMLImportContext *SmXMLImport::CreateSubContext(sal_uInt16 nPrefix,
3000     const OUString &rLocalName,
3001     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3002 {
3003     return new SmXMLSubContext_Impl(*this,nPrefix,rLocalName);
3004 }
3005 
3006 SvXMLImportContext *SmXMLImport::CreateSubSupContext(sal_uInt16 nPrefix,
3007     const OUString &rLocalName,
3008     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3009 {
3010     return new SmXMLSubSupContext_Impl(*this,nPrefix,rLocalName);
3011 }
3012 
3013 SvXMLImportContext *SmXMLImport::CreateSupContext(sal_uInt16 nPrefix,
3014     const OUString &rLocalName,
3015     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3016 {
3017     return new SmXMLSupContext_Impl(*this,nPrefix,rLocalName);
3018 }
3019 
3020 SvXMLImportContext *SmXMLImport::CreateUnderContext(sal_uInt16 nPrefix,
3021     const OUString &rLocalName,
3022     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3023 {
3024         return new SmXMLUnderContext_Impl(*this,nPrefix,rLocalName);
3025 }
3026 
3027 SvXMLImportContext *SmXMLImport::CreateOverContext(sal_uInt16 nPrefix,
3028     const OUString &rLocalName,
3029     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3030 {
3031     return new SmXMLOverContext_Impl(*this,nPrefix,rLocalName);
3032 }
3033 
3034 SvXMLImportContext *SmXMLImport::CreateUnderOverContext(sal_uInt16 nPrefix,
3035     const OUString &rLocalName,
3036     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3037 {
3038     return new SmXMLUnderOverContext_Impl(*this,nPrefix,rLocalName);
3039 }
3040 
3041 SvXMLImportContext *SmXMLImport::CreateMultiScriptsContext(sal_uInt16 nPrefix,
3042     const OUString &rLocalName,
3043     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3044 {
3045     return new SmXMLMultiScriptsContext_Impl(*this,nPrefix,rLocalName);
3046 }
3047 
3048 SvXMLImportContext *SmXMLImport::CreateTableContext(sal_uInt16 nPrefix,
3049     const OUString &rLocalName,
3050     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3051 {
3052     return new SmXMLTableContext_Impl(*this,nPrefix,rLocalName);
3053 }
3054 SvXMLImportContext *SmXMLImport::CreateTableRowContext(sal_uInt16 nPrefix,
3055     const OUString &rLocalName,
3056     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3057 {
3058     return new SmXMLTableRowContext_Impl(*this,nPrefix,rLocalName);
3059 }
3060 SvXMLImportContext *SmXMLImport::CreateTableCellContext(sal_uInt16 nPrefix,
3061     const OUString &rLocalName,
3062     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3063 {
3064     return new SmXMLTableCellContext_Impl(*this,nPrefix,rLocalName);
3065 }
3066 
3067 SvXMLImportContext *SmXMLImport::CreateNoneContext(sal_uInt16 nPrefix,
3068     const OUString &rLocalName,
3069     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3070 {
3071     return new SmXMLNoneContext_Impl(*this,nPrefix,rLocalName);
3072 }
3073 
3074 SvXMLImportContext *SmXMLImport::CreatePrescriptsContext(sal_uInt16 nPrefix,
3075     const OUString &rLocalName,
3076     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3077 {
3078     return new SmXMLPrescriptsContext_Impl(*this,nPrefix,rLocalName);
3079 }
3080 
3081 SvXMLImportContext *SmXMLImport::CreateAlignGroupContext(sal_uInt16 nPrefix,
3082     const OUString &rLocalName,
3083     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3084 {
3085     return new SmXMLAlignGroupContext_Impl(*this,nPrefix,rLocalName);
3086 }
3087 
3088 SvXMLImportContext *SmXMLImport::CreateActionContext(sal_uInt16 nPrefix,
3089     const OUString &rLocalName,
3090     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3091 {
3092     return new SmXMLActionContext_Impl(*this,nPrefix,rLocalName);
3093 }
3094 
3095 SmXMLImport::~SmXMLImport() throw ()
3096 {
3097     delete pPresLayoutElemTokenMap;
3098     delete pPresElemTokenMap;
3099     delete pPresScriptEmptyElemTokenMap;
3100     delete pPresTableElemTokenMap;
3101     delete pPresLayoutAttrTokenMap;
3102     delete pFencedAttrTokenMap;
3103     delete pColorTokenMap;
3104     delete pOperatorAttrTokenMap;
3105     delete pAnnotationAttrTokenMap;
3106 }
3107 
3108 void SmXMLImport::SetViewSettings(const Sequence<PropertyValue>& aViewProps)
3109 {
3110     uno::Reference <frame::XModel> xModel = GetModel();
3111     if ( !xModel.is() )
3112         return;
3113 
3114     uno::Reference <lang::XUnoTunnel> xTunnel;
3115     xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY);
3116     SmModel *pModel = reinterpret_cast<SmModel *>
3117         (xTunnel->getSomething(SmModel::getUnoTunnelId()));
3118 
3119     if ( !pModel )
3120         return;
3121 
3122     SmDocShell *pDocShell =
3123         static_cast<SmDocShell*>(pModel->GetObjectShell());
3124     if ( !pDocShell )
3125         return;
3126 
3127     Rectangle aRect( pDocShell->GetVisArea() );
3128 
3129     sal_Int32 nCount = aViewProps.getLength();
3130     const PropertyValue *pValue = aViewProps.getConstArray();
3131 
3132     long nTmp = 0;
3133     //sal_Bool bShowDeletes = sal_False, bShowInserts = sal_False, bShowFooter = sal_False, bShowHeader = sal_False;
3134 
3135     for (sal_Int32 i = 0; i < nCount ; i++)
3136     {
3137         if (pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "ViewAreaTop" ) ) )
3138         {
3139             pValue->Value >>= nTmp;
3140             aRect.setY( nTmp );
3141         }
3142         else if (pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "ViewAreaLeft" ) ) )
3143         {
3144             pValue->Value >>= nTmp;
3145             aRect.setX( nTmp );
3146         }
3147         else if (pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "ViewAreaWidth" ) ) )
3148         {
3149             pValue->Value >>= nTmp;
3150             Size aSize( aRect.GetSize() );
3151             aSize.Width() = nTmp;
3152             aRect.SetSize( aSize );
3153         }
3154         else if (pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "ViewAreaHeight" ) ) )
3155         {
3156             pValue->Value >>= nTmp;
3157             Size aSize( aRect.GetSize() );
3158             aSize.Height() = nTmp;
3159             aRect.SetSize( aSize );
3160         }
3161         pValue++;
3162     }
3163 
3164     pDocShell->SetVisArea ( aRect );
3165 }
3166 
3167 void SmXMLImport::SetConfigurationSettings(const Sequence<PropertyValue>& aConfProps)
3168 {
3169     uno::Reference < XPropertySet > xProps ( GetModel(), UNO_QUERY );
3170     if ( xProps.is() )
3171     {
3172         Reference < XPropertySetInfo > xInfo ( xProps->getPropertySetInfo() );
3173         if (xInfo.is() )
3174         {
3175             sal_Int32 nCount = aConfProps.getLength();
3176             const PropertyValue* pValues = aConfProps.getConstArray();
3177 
3178             const OUString sFormula ( RTL_CONSTASCII_USTRINGPARAM ( "Formula" ) );
3179             const OUString sBasicLibraries ( RTL_CONSTASCII_USTRINGPARAM ( "BasicLibraries" ) );
3180             const OUString sDialogLibraries ( RTL_CONSTASCII_USTRINGPARAM ( "DialogLibraries" ) );
3181             while ( nCount-- )
3182             {
3183                 if (pValues->Name != sFormula &&
3184                     pValues->Name != sBasicLibraries &&
3185                     pValues->Name != sDialogLibraries)
3186                 {
3187                     try
3188                     {
3189                         if ( xInfo->hasPropertyByName( pValues->Name ) )
3190                             xProps->setPropertyValue( pValues->Name, pValues->Value );
3191                     }
3192                     catch (beans::PropertyVetoException &e)
3193                     {
3194                         (void) e;
3195                         // dealing with read-only properties here. Nothing to do...
3196                     }
3197                     catch( Exception& e)
3198                     {
3199                         (void) e;
3200                         DBG_ERROR( "SmXMLImport::SetConfigurationSettings: Exception!" );
3201                     }
3202                 }
3203 
3204                 pValues++;
3205             }
3206         }
3207     }
3208 }
3209 
3210 
3211 ////////////////////////////////////////////////////////////
3212 
3213 
3214