xref: /trunk/main/starmath/source/mathmlimport.cxx (revision 7db8e690)
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                 // Get text from imported formula
581                 pTree->CreateTextFromNode(aText);
582                 aText.EraseTrailingChars();
583                 if ((aText.GetChar(0) == '{') &&
584                     (aText.GetChar(aText.Len()-1) == '}'))
585                 {
586                     aText.Erase(0,1);
587                     aText.Erase(aText.Len()-1,1);
588                 }
589             }
590 
591             // Convert symbol names
592             SmParser &rParser = pDocShell->GetParser();
593             sal_Bool bVal = rParser.IsImportSymbolNames();
594             rParser.SetImportSymbolNames( sal_True );
595             SmNode *pTmpTree = rParser.Parse( aText );
596             aText = rParser.GetText();
597             delete pTmpTree;
598             rParser.SetImportSymbolNames( bVal );
599 
600             pDocShell->SetText( aText );
601         }
602         DBG_ASSERT(pModel,"So there *was* a uno problem after all");
603 
604         bSuccess = sal_True;
605     }
606 
607     SvXMLImport::endDocument();
608 }
609 
610 ////////////////////////////////////////////////////////////
611 
612 class SmXMLImportContext: public SvXMLImportContext
613 {
614 public:
615     SmXMLImportContext( SmXMLImport &rImport, sal_uInt16 nPrfx,
616         const OUString& rLName)
617         : SvXMLImportContext(rImport, nPrfx, rLName) {}
618 
619     const SmXMLImport& GetSmImport() const
620     {
621         return (const SmXMLImport&)GetImport();
622     }
623 
624     SmXMLImport& GetSmImport()
625     {
626         return (SmXMLImport&)GetImport();
627     }
628 
629     virtual void TCharacters(const OUString & /*rChars*/);
630     virtual void Characters(const OUString &rChars);
631     virtual SvXMLImportContext *CreateChildContext(sal_uInt16 /*nPrefix*/, const OUString& /*rLocalName*/, const uno::Reference< xml::sax::XAttributeList > & /*xAttrList*/);
632 };
633 
634 void SmXMLImportContext::TCharacters(const OUString & /*rChars*/)
635 {
636 }
637 
638 void SmXMLImportContext::Characters(const OUString &rChars)
639 {
640     /*
641     Whitespace occurring within the content of token elements is "trimmed"
642     from the ends (i.e. all whitespace at the beginning and end of the
643     content is removed), and "collapsed" internally (i.e. each sequence of
644     1 or more whitespace characters is replaced with one blank character).
645     */
646     //collapsing not done yet!
647     const OUString &rChars2 = rChars.trim();
648     if (rChars2.getLength())
649         TCharacters(rChars2/*.collapse()*/);
650 }
651 
652 SvXMLImportContext * SmXMLImportContext::CreateChildContext(sal_uInt16 /*nPrefix*/,
653     const OUString& /*rLocalName*/,
654     const uno::Reference< xml::sax::XAttributeList > & /*xAttrList*/)
655 {
656     return 0;
657 }
658 
659 ////////////////////////////////////////////////////////////
660 
661 struct SmXMLContext_Helper
662 {
663     sal_Int8 nIsBold;
664     sal_Int8 nIsItalic;
665     double nFontSize;
666     sal_Bool bFontNodeNeeded;
667     OUString sFontFamily;
668     OUString sColor;
669 
670     SmXMLImportContext rContext;
671 
672     SmXMLContext_Helper(SmXMLImportContext &rImport) :
673         nIsBold(-1), nIsItalic(-1), nFontSize(0.0), rContext(rImport)  {}
674 
675     void RetrieveAttrs(const uno::Reference< xml::sax::XAttributeList > &xAttrList );
676     void ApplyAttrs();
677 };
678 
679 void SmXMLContext_Helper::RetrieveAttrs(const uno::Reference<
680     xml::sax::XAttributeList > & xAttrList )
681 {
682     sal_Int8 nOldIsBold=nIsBold;
683     sal_Int8 nOldIsItalic=nIsItalic;
684     double nOldFontSize=nFontSize;
685     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
686     OUString sOldFontFamily = sFontFamily;
687     for (sal_Int16 i=0;i<nAttrCount;i++)
688     {
689         OUString sAttrName = xAttrList->getNameByIndex(i);
690         OUString aLocalName;
691         sal_uInt16 nPrefix = rContext.GetSmImport().GetNamespaceMap().
692             GetKeyByAttrName(sAttrName,&aLocalName);
693         OUString sValue = xAttrList->getValueByIndex(i);
694         const SvXMLTokenMap &rAttrTokenMap =
695             rContext.GetSmImport().GetPresLayoutAttrTokenMap();
696         switch(rAttrTokenMap.Get(nPrefix,aLocalName))
697         {
698             case XML_TOK_FONTWEIGHT:
699                 nIsBold = sValue.equals(GetXMLToken(XML_BOLD));
700                 break;
701             case XML_TOK_FONTSTYLE:
702                 nIsItalic = sValue.equals(GetXMLToken(XML_ITALIC));
703                 break;
704             case XML_TOK_FONTSIZE:
705                 SvXMLUnitConverter::convertDouble(nFontSize,sValue);
706                 rContext.GetSmImport().GetMM100UnitConverter().
707                     setXMLMeasureUnit(MAP_POINT);
708                 if (-1 == sValue.indexOf(GetXMLToken(XML_UNIT_PT)))
709                 {
710                     if (-1 == sValue.indexOf('%'))
711                         nFontSize=0.0;
712                     else
713                     {
714                         rContext.GetSmImport().GetMM100UnitConverter().
715                             setXMLMeasureUnit(MAP_RELATIVE);
716                     }
717                 }
718                 break;
719             case XML_TOK_FONTFAMILY:
720                 sFontFamily = sValue;
721                 break;
722             case XML_TOK_COLOR:
723                 sColor = sValue;
724                 break;
725             case XML_TOK_MATHCOLOR:
726                 sColor = sValue;
727                 break;
728             default:
729                 break;
730         }
731     }
732 
733     if ((nOldIsBold!=nIsBold) || (nOldIsItalic!=nIsItalic) ||
734         (nOldFontSize!=nFontSize) || (sOldFontFamily!=sFontFamily)
735         || sColor.getLength())
736         bFontNodeNeeded=sal_True;
737     else
738         bFontNodeNeeded=sal_False;
739 }
740 
741 void SmXMLContext_Helper::ApplyAttrs()
742 {
743     SmNodeStack &rNodeStack = rContext.GetSmImport().GetNodeStack();
744 
745     if (bFontNodeNeeded)
746     {
747         SmToken aToken;
748         aToken.cMathChar = '\0';
749         aToken.nGroup = 0;
750         aToken.nLevel = 5;
751 
752         if (nIsBold != -1)
753         {
754             if (nIsBold)
755                 aToken.eType = TBOLD;
756             else
757                 aToken.eType = TNBOLD;
758             SmStructureNode *pFontNode = static_cast<SmStructureNode *>
759                 (new SmFontNode(aToken));
760             pFontNode->SetSubNodes(0,rNodeStack.Pop());
761             rNodeStack.Push(pFontNode);
762         }
763         if (nIsItalic != -1)
764         {
765             if (nIsItalic)
766                 aToken.eType = TITALIC;
767             else
768                 aToken.eType = TNITALIC;
769             SmStructureNode *pFontNode = static_cast<SmStructureNode *>
770                 (new SmFontNode(aToken));
771             pFontNode->SetSubNodes(0,rNodeStack.Pop());
772             rNodeStack.Push(pFontNode);
773         }
774         if (nFontSize != 0.0)
775         {
776             aToken.eType = TSIZE;
777             SmFontNode *pFontNode = new SmFontNode(aToken);
778 
779             if (MAP_RELATIVE == rContext.GetSmImport().GetMM100UnitConverter().
780                 getXMLMeasureUnit())
781             {
782                 if (nFontSize < 100.00)
783                     pFontNode->SetSizeParameter(Fraction(100.00/nFontSize),
784                         FNTSIZ_DIVIDE);
785                 else
786                     pFontNode->SetSizeParameter(Fraction(nFontSize/100.00),
787                         FNTSIZ_MULTIPLY);
788             }
789             else
790                 pFontNode->SetSizeParameter(Fraction(nFontSize),FNTSIZ_ABSOLUT);
791 
792             pFontNode->SetSubNodes(0,rNodeStack.Pop());
793             rNodeStack.Push(pFontNode);
794         }
795         if (sFontFamily.getLength())
796         {
797             if (sFontFamily.equalsIgnoreAsciiCase(GetXMLToken(XML_FIXED)))
798                 aToken.eType = TFIXED;
799             else if (sFontFamily.equalsIgnoreAsciiCase(OUString(
800                 RTL_CONSTASCII_USTRINGPARAM("sans"))))
801                 aToken.eType = TSANS;
802             else if (sFontFamily.equalsIgnoreAsciiCase(OUString(
803                 RTL_CONSTASCII_USTRINGPARAM("serif"))))
804                 aToken.eType = TSERIF;
805             else //Just give up, we need to extend our font mechanism to be
806                 //more general
807                 return;
808 
809             aToken.aText = sFontFamily;
810             SmFontNode *pFontNode = new SmFontNode(aToken);
811             pFontNode->SetSubNodes(0,rNodeStack.Pop());
812             rNodeStack.Push(pFontNode);
813         }
814         if (sColor.getLength())
815         {
816             //Again we can only handle a small set of colours in
817             //StarMath for now.
818             const SvXMLTokenMap& rTokenMap =
819                 rContext.GetSmImport().GetColorTokenMap();
820             aToken.eType = static_cast<SmTokenType>(rTokenMap.Get(
821                 XML_NAMESPACE_MATH, sColor));
822             if (aToken.eType != -1)
823             {
824                 SmFontNode *pFontNode = new SmFontNode(aToken);
825                 pFontNode->SetSubNodes(0,rNodeStack.Pop());
826                 rNodeStack.Push(pFontNode);
827             }
828         }
829 
830     }
831 }
832 
833 ////////////////////////////////////////////////////////////
834 
835 class SmXMLDocContext_Impl : public SmXMLImportContext
836 {
837 public:
838     SmXMLDocContext_Impl( SmXMLImport &rImport, sal_uInt16 nPrfx,
839         const OUString& rLName)
840         : SmXMLImportContext(rImport,nPrfx,rLName) {}
841 
842     virtual SvXMLImportContext *CreateChildContext(sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > &xAttrList);
843 
844     void EndElement();
845 };
846 
847 ////////////////////////////////////////////////////////////
848 
849 /*avert thy gaze from the proginator*/
850 class SmXMLRowContext_Impl : public SmXMLDocContext_Impl
851 {
852 protected:
853     sal_uLong nElementCount;
854 
855 public:
856     SmXMLRowContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
857         const OUString& rLName)
858         : SmXMLDocContext_Impl(rImport,nPrefix,rLName)
859         { nElementCount = GetSmImport().GetNodeStack().Count(); }
860 
861     virtual SvXMLImportContext *CreateChildContext(sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > &xAttrList);
862 
863     SvXMLImportContext *StrictCreateChildContext(sal_uInt16 nPrefix,
864         const OUString& rLocalName,
865         const uno::Reference< xml::sax::XAttributeList > &xAttrList);
866 
867     void EndElement();
868 };
869 
870 ////////////////////////////////////////////////////////////
871 
872 class SmXMLFracContext_Impl : public SmXMLRowContext_Impl
873 {
874 public:
875     SmXMLFracContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
876         const OUString& rLName)
877         : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
878 
879     void EndElement();
880 };
881 
882 ////////////////////////////////////////////////////////////
883 
884 class SmXMLSqrtContext_Impl : public SmXMLRowContext_Impl
885 {
886 public:
887     SmXMLSqrtContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
888         const OUString& rLName)
889         : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
890 
891     void EndElement();
892 };
893 
894 ////////////////////////////////////////////////////////////
895 
896 class SmXMLRootContext_Impl : public SmXMLRowContext_Impl
897 {
898 public:
899     SmXMLRootContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
900         const OUString& rLName)
901         : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
902 
903     void EndElement();
904 };
905 
906 ////////////////////////////////////////////////////////////
907 
908 class SmXMLStyleContext_Impl : public SmXMLRowContext_Impl
909 {
910 protected:
911     SmXMLContext_Helper aStyleHelper;
912 
913 public:
914     /*Right now the style tag is completely ignored*/
915     SmXMLStyleContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
916         const OUString& rLName) : SmXMLRowContext_Impl(rImport,nPrefix,rLName),
917         aStyleHelper(*this) {}
918 
919     void EndElement();
920     void StartElement(const uno::Reference< xml::sax::XAttributeList > &xAttrList );
921 };
922 
923 void SmXMLStyleContext_Impl::StartElement(const uno::Reference<
924     xml::sax::XAttributeList > & xAttrList )
925 {
926 #if 1
927     aStyleHelper.RetrieveAttrs(xAttrList);
928 #else
929     sal_Int8 nOldIsBold=nIsBold;
930     sal_Int8 nOldIsItalic=nIsItalic;
931     double nOldFontSize=nFontSize;
932     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
933     OUString sOldFontFamily = sFontFamily;
934     for (sal_Int16 i=0;i<nAttrCount;i++)
935     {
936         OUString sAttrName = xAttrList->getNameByIndex(i);
937         OUString aLocalName;
938         sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
939             GetKeyByAttrName(sAttrName,&aLocalName);
940         OUString sValue = xAttrList->getValueByIndex(i);
941         const SvXMLTokenMap &rAttrTokenMap =
942             GetSmImport().GetPresLayoutAttrTokenMap();
943         switch(rAttrTokenMap.Get(nPrefix,aLocalName))
944         {
945             case XML_TOK_FONTWEIGHT:
946                 nIsBold = sValue.equals(GetXMLToken(XML_BOLD));
947                 break;
948             case XML_TOK_FONTSTYLE:
949                 nIsItalic = sValue.equals(GetXMLToken(XML_ITALIC));
950                 break;
951             case XML_TOK_FONTSIZE:
952                 SvXMLUnitConverter::convertDouble(nFontSize,sValue);
953                 GetSmImport().GetMM100UnitConverter().
954                     setXMLMeasureUnit(MAP_POINT);
955                 if (-1 == sValue.indexOf(GetXMLToken(XML_UNIT_PT)))
956                     if (-1 == sValue.indexOf('%'))
957                         nFontSize=0.0;
958                     else
959                     {
960                         GetSmImport().GetMM100UnitConverter().
961                             setXMLMeasureUnit(MAP_RELATIVE);
962                     }
963                 break;
964             case XML_TOK_FONTFAMILY:
965                 sFontFamily = sValue;
966                 break;
967             case XML_TOK_COLOR:
968                 sColor = sValue;
969                 break;
970             case XML_TOK_MATHCOLOR:
971                 sColor = sValue;
972                 break;
973             default:
974                 break;
975         }
976     }
977 
978     if ((nOldIsBold!=nIsBold) || (nOldIsItalic!=nIsItalic) ||
979         (nOldFontSize!=nFontSize) || (sOldFontFamily!=sFontFamily)
980         || sColor.getLength())
981         bFontNodeNeeded=sal_True;
982     else
983         bFontNodeNeeded=sal_False;
984 #endif
985 }
986 
987 
988 void SmXMLStyleContext_Impl::EndElement()
989 {
990     /*
991     <mstyle> accepts any number of arguments; if this number is not 1, its
992     contents are treated as a single "inferred <mrow>" containing its
993     arguments
994     */
995     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
996     if (rNodeStack.Count() - nElementCount > 1)
997         SmXMLRowContext_Impl::EndElement();
998 #if 1
999     aStyleHelper.ApplyAttrs();
1000 #else
1001     if (bFontNodeNeeded)
1002     {
1003         SmToken aToken;
1004         aToken.cMathChar = '\0';
1005         aToken.nGroup = 0;
1006         aToken.nLevel = 5;
1007 
1008         if (nIsBold != -1)
1009         {
1010             if (nIsBold)
1011                 aToken.eType = TBOLD;
1012             else
1013                 aToken.eType = TNBOLD;
1014             SmStructureNode *pFontNode = static_cast<SmStructureNode *>
1015                 (new SmFontNode(aToken));
1016             pFontNode->SetSubNodes(0,rNodeStack.Pop());
1017             rNodeStack.Push(pFontNode);
1018         }
1019         if (nIsItalic != -1)
1020         {
1021             if (nIsItalic)
1022                 aToken.eType = TITALIC;
1023             else
1024                 aToken.eType = TNITALIC;
1025             SmStructureNode *pFontNode = static_cast<SmStructureNode *>
1026                 (new SmFontNode(aToken));
1027             pFontNode->SetSubNodes(0,rNodeStack.Pop());
1028             rNodeStack.Push(pFontNode);
1029         }
1030         if (nFontSize != 0.0)
1031         {
1032             aToken.eType = TSIZE;
1033             SmFontNode *pFontNode = new SmFontNode(aToken);
1034 
1035             if (MAP_RELATIVE == GetSmImport().GetMM100UnitConverter().
1036                 getXMLMeasureUnit())
1037             {
1038                 if (nFontSize < 100.00)
1039                     pFontNode->SetSizeParameter(Fraction(100.00/nFontSize),
1040                         FNTSIZ_DIVIDE);
1041                 else
1042                     pFontNode->SetSizeParameter(Fraction(nFontSize/100.00),
1043                         FNTSIZ_MULTIPLY);
1044             }
1045             else
1046                 pFontNode->SetSizeParameter(Fraction(nFontSize),FNTSIZ_ABSOLUT);
1047 
1048             pFontNode->SetSubNodes(0,rNodeStack.Pop());
1049             rNodeStack.Push(pFontNode);
1050         }
1051         if (sFontFamily.getLength())
1052         {
1053             if (sFontFamily.equalsIgnoreCase(GetXMLToken(XML_FIXED)))
1054                 aToken.eType = TFIXED;
1055             else if (sFontFamily.equalsIgnoreCase(OUString(
1056                 RTL_CONSTASCII_USTRINGPARAM("sans"))))
1057                 aToken.eType = TSANS;
1058             else if (sFontFamily.equalsIgnoreCase(OUString(
1059                 RTL_CONSTASCII_USTRINGPARAM("serif"))))
1060                 aToken.eType = TSERIF;
1061             else //Just give up, we need to extend our font mechanism to be
1062                 //more general
1063                 return;
1064 
1065             aToken.aText = sFontFamily;
1066             SmFontNode *pFontNode = new SmFontNode(aToken);
1067             pFontNode->SetSubNodes(0,rNodeStack.Pop());
1068             rNodeStack.Push(pFontNode);
1069         }
1070         if (sColor.getLength())
1071         {
1072             //Again we can only handle a small set of colours in
1073             //StarMath for now.
1074             const SvXMLTokenMap& rTokenMap =
1075                 GetSmImport().GetColorTokenMap();
1076             aToken.eType = static_cast<SmTokenType>(rTokenMap.Get(
1077                 XML_NAMESPACE_MATH, sColor));
1078             if (aToken.eType != -1)
1079             {
1080                 SmFontNode *pFontNode = new SmFontNode(aToken);
1081                 pFontNode->SetSubNodes(0,rNodeStack.Pop());
1082                 rNodeStack.Push(pFontNode);
1083             }
1084         }
1085 
1086     }
1087 #endif
1088 }
1089 
1090 ////////////////////////////////////////////////////////////
1091 
1092 class SmXMLPaddedContext_Impl : public SmXMLRowContext_Impl
1093 {
1094 public:
1095     /*Right now the style tag is completely ignored*/
1096     SmXMLPaddedContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1097         const OUString& rLName)
1098         : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
1099 
1100     void EndElement();
1101 };
1102 
1103 void SmXMLPaddedContext_Impl::EndElement()
1104 {
1105     /*
1106     <mpadded> accepts any number of arguments; if this number is not 1, its
1107     contents are treated as a single "inferred <mrow>" containing its
1108     arguments
1109     */
1110     if (GetSmImport().GetNodeStack().Count() - nElementCount > 1)
1111         SmXMLRowContext_Impl::EndElement();
1112 }
1113 
1114 ////////////////////////////////////////////////////////////
1115 
1116 class SmXMLPhantomContext_Impl : public SmXMLRowContext_Impl
1117 {
1118 public:
1119     /*Right now the style tag is completely ignored*/
1120     SmXMLPhantomContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1121         const OUString& rLName)
1122         : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
1123 
1124     void EndElement();
1125 };
1126 
1127 void SmXMLPhantomContext_Impl::EndElement()
1128 {
1129     /*
1130     <mphantom> accepts any number of arguments; if this number is not 1, its
1131     contents are treated as a single "inferred <mrow>" containing its
1132     arguments
1133     */
1134     if (GetSmImport().GetNodeStack().Count() - nElementCount > 1)
1135         SmXMLRowContext_Impl::EndElement();
1136 
1137     SmToken aToken;
1138     aToken.cMathChar = '\0';
1139     aToken.nGroup = 0;
1140     aToken.nLevel = 5;
1141     aToken.eType = TPHANTOM;
1142 
1143     SmStructureNode *pPhantom = static_cast<SmStructureNode *>
1144         (new SmFontNode(aToken));
1145     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1146     pPhantom->SetSubNodes(0,rNodeStack.Pop());
1147     rNodeStack.Push(pPhantom);
1148 }
1149 
1150 ////////////////////////////////////////////////////////////
1151 
1152 class SmXMLFencedContext_Impl : public SmXMLRowContext_Impl
1153 {
1154 protected:
1155     sal_Unicode cBegin;
1156     sal_Unicode cEnd;
1157 
1158 public:
1159     SmXMLFencedContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1160         const OUString& rLName)
1161         : SmXMLRowContext_Impl(rImport,nPrefix,rLName),
1162         cBegin('('), cEnd(')') {}
1163 
1164     void StartElement(const uno::Reference< xml::sax::XAttributeList > & xAttrList );
1165     void EndElement();
1166 };
1167 
1168 
1169 void SmXMLFencedContext_Impl::StartElement(const uno::Reference<
1170     xml::sax::XAttributeList > & xAttrList )
1171 {
1172     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
1173     for (sal_Int16 i=0;i<nAttrCount;i++)
1174     {
1175         OUString sAttrName = xAttrList->getNameByIndex(i);
1176         OUString aLocalName;
1177         sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
1178             GetKeyByAttrName(sAttrName,&aLocalName);
1179         OUString sValue = xAttrList->getValueByIndex(i);
1180         const SvXMLTokenMap &rAttrTokenMap =
1181             GetSmImport().GetFencedAttrTokenMap();
1182         switch(rAttrTokenMap.Get(nPrefix,aLocalName))
1183         {
1184             //temp, starmath cannot handle multichar brackets (I think)
1185             case XML_TOK_OPEN:
1186                 cBegin = sValue[0];
1187                 break;
1188             case XML_TOK_CLOSE:
1189                 cEnd = sValue[0];
1190                 break;
1191             default:
1192                 /*Go to superclass*/
1193                 break;
1194         }
1195     }
1196 }
1197 
1198 
1199 void SmXMLFencedContext_Impl::EndElement()
1200 {
1201     SmToken aToken;
1202     aToken.cMathChar = '\0';
1203     aToken.nGroup = 0;
1204     aToken.aText = ',';
1205     aToken.eType = TLEFT;
1206     aToken.nLevel = 5;
1207 
1208     aToken.eType = TLPARENT;
1209     aToken.cMathChar = cBegin;
1210     SmStructureNode *pSNode = new SmBraceNode(aToken);
1211     SmNode *pLeft = new SmMathSymbolNode(aToken);
1212 
1213     aToken.cMathChar = cEnd;
1214     aToken.eType = TRPARENT;
1215     SmNode *pRight = new SmMathSymbolNode(aToken);
1216 
1217     SmNodeArray aRelationArray;
1218     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1219 
1220     aToken.cMathChar = '\0';
1221     aToken.aText = ',';
1222     aToken.eType = TIDENT;
1223 
1224     sal_uLong i = rNodeStack.Count() - nElementCount;
1225     if (rNodeStack.Count() - nElementCount > 1)
1226         i += rNodeStack.Count() - 1 - nElementCount;
1227     aRelationArray.resize(i);
1228     while (rNodeStack.Count() > nElementCount)
1229     {
1230         aRelationArray[--i] = rNodeStack.Pop();
1231         if (i > 1 && rNodeStack.Count() > 1)
1232             aRelationArray[--i] = new SmGlyphSpecialNode(aToken);
1233     }
1234 
1235     SmToken aDummy;
1236     SmStructureNode *pBody = new SmExpressionNode(aDummy);
1237     pBody->SetSubNodes(aRelationArray);
1238 
1239 
1240     pSNode->SetSubNodes(pLeft,pBody,pRight);
1241     pSNode->SetScaleMode(SCALE_HEIGHT);
1242     GetSmImport().GetNodeStack().Push(pSNode);
1243 }
1244 
1245 
1246 ////////////////////////////////////////////////////////////
1247 
1248 class SmXMLErrorContext_Impl : public SmXMLRowContext_Impl
1249 {
1250 public:
1251     SmXMLErrorContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1252         const OUString& rLName)
1253         : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
1254 
1255     void EndElement();
1256 };
1257 
1258 void SmXMLErrorContext_Impl::EndElement()
1259 {
1260     /*Right now the error tag is completely ignored, what
1261      can I do with it in starmath, ?, maybe we need a
1262      report window ourselves, do a test for validity of
1263      the xml input, use merrors, and then generate
1264      the markup inside the merror with a big red colour
1265      of something. For now just throw them all away.
1266      */
1267     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1268     while (rNodeStack.Count() > nElementCount)
1269     {
1270         SmNode *pNode = rNodeStack.Pop();
1271         delete pNode;
1272     }
1273 }
1274 
1275 ////////////////////////////////////////////////////////////
1276 
1277 class SmXMLNumberContext_Impl : public SmXMLImportContext
1278 {
1279 protected:
1280     SmToken aToken;
1281 
1282 public:
1283     SmXMLNumberContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1284         const OUString& rLName)
1285         : SmXMLImportContext(rImport,nPrefix,rLName)
1286     {
1287         aToken.cMathChar = '\0';
1288         aToken.nGroup = 0;
1289         aToken.nLevel = 5;
1290         aToken.eType = TNUMBER;
1291     }
1292 
1293     virtual void TCharacters(const OUString &rChars);
1294 
1295     void EndElement();
1296 };
1297 
1298 void SmXMLNumberContext_Impl::TCharacters(const OUString &rChars)
1299 {
1300     aToken.aText = rChars;
1301 }
1302 
1303 void SmXMLNumberContext_Impl::EndElement()
1304 {
1305     GetSmImport().GetNodeStack().Push(new SmTextNode(aToken,FNT_NUMBER));
1306 }
1307 
1308 ////////////////////////////////////////////////////////////
1309 
1310 class SmXMLAnnotationContext_Impl : public SmXMLImportContext
1311 {
1312     sal_Bool bIsStarMath;
1313 
1314 public:
1315     SmXMLAnnotationContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1316         const OUString& rLName)
1317         : SmXMLImportContext(rImport,nPrefix,rLName), bIsStarMath(sal_False) {}
1318 
1319     virtual void Characters(const OUString &rChars);
1320 
1321     void StartElement(const uno::Reference<xml::sax::XAttributeList > & xAttrList );
1322 };
1323 
1324 void SmXMLAnnotationContext_Impl::StartElement(const uno::Reference<
1325     xml::sax::XAttributeList > & xAttrList )
1326 {
1327     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
1328     for (sal_Int16 i=0;i<nAttrCount;i++)
1329     {
1330         OUString sAttrName = xAttrList->getNameByIndex(i);
1331         OUString aLocalName;
1332         sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
1333             GetKeyByAttrName(sAttrName,&aLocalName);
1334 
1335         OUString sValue = xAttrList->getValueByIndex(i);
1336         const SvXMLTokenMap &rAttrTokenMap =
1337             GetSmImport().GetAnnotationAttrTokenMap();
1338         switch(rAttrTokenMap.Get(nPrefix,aLocalName))
1339         {
1340             case XML_TOK_ENCODING:
1341                 bIsStarMath= sValue.equals(
1342                     OUString(RTL_CONSTASCII_USTRINGPARAM("StarMath 5.0")));
1343                 break;
1344             default:
1345                 break;
1346         }
1347     }
1348 }
1349 
1350 void SmXMLAnnotationContext_Impl::Characters(const OUString &rChars)
1351 {
1352     if (bIsStarMath)
1353         GetSmImport().GetText().Append(String(rChars));
1354 }
1355 
1356 ////////////////////////////////////////////////////////////
1357 
1358 class SmXMLTextContext_Impl : public SmXMLImportContext
1359 {
1360 protected:
1361     SmToken aToken;
1362 
1363 public:
1364     SmXMLTextContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1365         const OUString& rLName)
1366         : SmXMLImportContext(rImport,nPrefix,rLName)
1367     {
1368         aToken.cMathChar = '\0';
1369         aToken.nGroup = 0;
1370         aToken.nLevel = 5;
1371         aToken.eType = TTEXT;
1372     }
1373 
1374     virtual void TCharacters(const OUString &rChars);
1375 
1376     void EndElement();
1377 };
1378 
1379 void SmXMLTextContext_Impl::TCharacters(const OUString &rChars)
1380 {
1381     aToken.aText = rChars;
1382 }
1383 
1384 void SmXMLTextContext_Impl::EndElement()
1385 {
1386     GetSmImport().GetNodeStack().Push(new SmTextNode(aToken,FNT_TEXT));
1387 }
1388 
1389 ////////////////////////////////////////////////////////////
1390 
1391 class SmXMLStringContext_Impl : public SmXMLImportContext
1392 {
1393 protected:
1394     SmToken aToken;
1395 
1396 public:
1397     SmXMLStringContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1398         const OUString& rLName)
1399         : SmXMLImportContext(rImport,nPrefix,rLName)
1400     {
1401         aToken.cMathChar = '\0';
1402         aToken.nGroup = 0;
1403         aToken.nLevel = 5;
1404         aToken.eType = TTEXT;
1405     }
1406 
1407     virtual void TCharacters(const OUString &rChars);
1408 
1409     void EndElement();
1410 };
1411 
1412 void SmXMLStringContext_Impl::TCharacters(const OUString &rChars)
1413 {
1414     /*
1415     The content of <ms> elements should be rendered with visible "escaping" of
1416     certain characters in the content, including at least "double quote"
1417     itself, and preferably whitespace other than individual blanks. The intent
1418     is for the viewer to see that the expression is a string literal, and to
1419     see exactly which characters form its content. For example, <ms>double
1420     quote is "</ms> might be rendered as "double quote is \"".
1421 
1422     Obviously this isn't fully done here.
1423     */
1424     aToken.aText.Erase();
1425     aToken.aText += '\"';
1426     aToken.aText += String(rChars);
1427     aToken.aText += '\"';
1428 }
1429 
1430 void SmXMLStringContext_Impl::EndElement()
1431 {
1432     GetSmImport().GetNodeStack().Push(new SmTextNode(aToken,FNT_FIXED));
1433 }
1434 
1435 ////////////////////////////////////////////////////////////
1436 
1437 class SmXMLIdentifierContext_Impl : public SmXMLImportContext
1438 {
1439 protected:
1440     SmXMLContext_Helper aStyleHelper;
1441     SmToken aToken;
1442 
1443 public:
1444     SmXMLIdentifierContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1445         const OUString& rLName)
1446         : SmXMLImportContext(rImport,nPrefix,rLName),aStyleHelper(*this)
1447     {
1448         aToken.cMathChar = '\0';
1449         aToken.nGroup = 0;
1450         aToken.nLevel = 5;
1451         aToken.eType = TIDENT;
1452     }
1453 
1454     void TCharacters(const OUString &rChars);
1455     void StartElement(const uno::Reference< xml::sax::XAttributeList > & xAttrList )
1456     {
1457         aStyleHelper.RetrieveAttrs(xAttrList);
1458     };
1459     void EndElement();
1460 };
1461 
1462 void SmXMLIdentifierContext_Impl::EndElement()
1463 {
1464     SmTextNode *pNode = 0;
1465     //we will handle identifier italic/normal here instead of with a standalone
1466     //font node
1467     if (((aStyleHelper.nIsItalic == -1) && (aToken.aText.Len() > 1))
1468         || ((aStyleHelper.nIsItalic == 0) && (aToken.aText.Len() == 1)))
1469     {
1470         pNode = new SmTextNode(aToken,FNT_FUNCTION);
1471         pNode->GetFont().SetItalic(ITALIC_NONE);
1472         aStyleHelper.nIsItalic = -1;
1473     }
1474     else
1475         pNode = new SmTextNode(aToken,FNT_VARIABLE);
1476     if (aStyleHelper.bFontNodeNeeded && aStyleHelper.nIsItalic != -1)
1477     {
1478         if (aStyleHelper.nIsItalic)
1479             pNode->GetFont().SetItalic(ITALIC_NORMAL);
1480         else
1481             pNode->GetFont().SetItalic(ITALIC_NONE);
1482     }
1483 
1484     if ((-1!=aStyleHelper.nIsBold) || (0.0!=aStyleHelper.nFontSize) ||
1485         (aStyleHelper.sFontFamily.getLength()) ||
1486         aStyleHelper.sColor.getLength())
1487         aStyleHelper.bFontNodeNeeded=sal_True;
1488     else
1489         aStyleHelper.bFontNodeNeeded=sal_False;
1490     if (aStyleHelper.bFontNodeNeeded)
1491         aStyleHelper.ApplyAttrs();
1492     GetSmImport().GetNodeStack().Push(pNode);
1493 }
1494 
1495 void SmXMLIdentifierContext_Impl::TCharacters(const OUString &rChars)
1496 {
1497     aToken.aText = rChars;
1498 }
1499 
1500 ////////////////////////////////////////////////////////////
1501 
1502 class SmXMLOperatorContext_Impl : public SmXMLImportContext
1503 {
1504     sal_Bool bIsStretchy;
1505 
1506 protected:
1507     SmToken aToken;
1508 
1509 public:
1510     SmXMLOperatorContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1511         const OUString& rLName)
1512         : SmXMLImportContext(rImport,nPrefix,rLName), bIsStretchy(sal_False)
1513     {
1514         aToken.nGroup = 0;
1515         aToken.eType = TSPECIAL;
1516         aToken.nLevel = 5;
1517     }
1518 
1519     void TCharacters(const OUString &rChars);
1520     void StartElement(const uno::Reference< xml::sax::XAttributeList > &xAttrList );
1521     void EndElement();
1522 };
1523 
1524 void SmXMLOperatorContext_Impl::TCharacters(const OUString &rChars)
1525 {
1526     aToken.cMathChar = rChars[0];
1527 }
1528 
1529 void SmXMLOperatorContext_Impl::EndElement()
1530 {
1531     SmMathSymbolNode *pNode = new SmMathSymbolNode(aToken);
1532     //For stretchy scaling the scaling must be retrieved from this node
1533     //and applied to the expression itself so as to get the expression
1534     //to scale the operator to the height of the expression itself
1535     if (bIsStretchy)
1536         pNode->SetScaleMode(SCALE_HEIGHT);
1537     GetSmImport().GetNodeStack().Push(pNode);
1538 }
1539 
1540 
1541 
1542 void SmXMLOperatorContext_Impl::StartElement(const uno::Reference<
1543     xml::sax::XAttributeList > & xAttrList )
1544 {
1545     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
1546     for (sal_Int16 i=0;i<nAttrCount;i++)
1547     {
1548         OUString sAttrName = xAttrList->getNameByIndex(i);
1549         OUString aLocalName;
1550         sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
1551             GetKeyByAttrName(sAttrName,&aLocalName);
1552 
1553         OUString sValue = xAttrList->getValueByIndex(i);
1554         const SvXMLTokenMap &rAttrTokenMap =
1555             GetSmImport().GetOperatorAttrTokenMap();
1556         switch(rAttrTokenMap.Get(nPrefix,aLocalName))
1557         {
1558             case XML_TOK_STRETCHY:
1559                 bIsStretchy = sValue.equals(
1560                     GetXMLToken(XML_TRUE));
1561                 break;
1562             default:
1563                 break;
1564         }
1565     }
1566 }
1567 
1568 
1569 ////////////////////////////////////////////////////////////
1570 
1571 class SmXMLSpaceContext_Impl : public SmXMLImportContext
1572 {
1573 public:
1574     SmXMLSpaceContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1575         const OUString& rLName)
1576         : SmXMLImportContext(rImport,nPrefix,rLName) {}
1577 
1578     void StartElement(const uno::Reference< xml::sax::XAttributeList >& xAttrList );
1579 };
1580 
1581 void SmXMLSpaceContext_Impl::StartElement(
1582     const uno::Reference<xml::sax::XAttributeList > & /*xAttrList*/ )
1583 {
1584     SmToken aToken;
1585     aToken.cMathChar = '\0';
1586     aToken.nGroup = 0;
1587     aToken.eType = TBLANK;
1588     aToken.nLevel = 5;
1589     SmBlankNode *pBlank = new SmBlankNode(aToken);
1590     pBlank->IncreaseBy(aToken);
1591     GetSmImport().GetNodeStack().Push(pBlank);
1592 }
1593 
1594 ////////////////////////////////////////////////////////////
1595 
1596 class SmXMLSubContext_Impl : public SmXMLRowContext_Impl
1597 {
1598 protected:
1599     void GenericEndElement(SmTokenType eType,SmSubSup aSubSup);
1600 
1601 public:
1602     SmXMLSubContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1603         const OUString& rLName)
1604         : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
1605 
1606     void EndElement()
1607     {
1608         GenericEndElement(TRSUB,RSUB);
1609     }
1610 };
1611 
1612 
1613 void SmXMLSubContext_Impl::GenericEndElement(SmTokenType eType, SmSubSup eSubSup)
1614 {
1615     /*The <msub> element requires exactly 2 arguments.*/
1616     const bool bNodeCheck = GetSmImport().GetNodeStack().Count() - nElementCount == 2;
1617     DBG_ASSERT( bNodeCheck, "Sub has not two arguments" );
1618     if (!bNodeCheck)
1619         return;
1620 
1621     SmToken aToken;
1622     aToken.cMathChar = '\0';
1623     aToken.nGroup = 0;
1624     aToken.nLevel = 0;
1625     aToken.eType = eType;
1626     SmSubSupNode *pNode = new SmSubSupNode(aToken);
1627     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1628 
1629     // initialize subnodes array
1630     SmNodeArray  aSubNodes;
1631     aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES);
1632     for (sal_uLong i = 1;  i < aSubNodes.size();  i++)
1633         aSubNodes[i] = NULL;
1634 
1635     aSubNodes[eSubSup+1] = rNodeStack.Pop();
1636     aSubNodes[0] = rNodeStack.Pop();
1637     pNode->SetSubNodes(aSubNodes);
1638     rNodeStack.Push(pNode);
1639 }
1640 
1641 ////////////////////////////////////////////////////////////
1642 
1643 class SmXMLSupContext_Impl : public SmXMLSubContext_Impl
1644 {
1645 public:
1646     SmXMLSupContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1647         const OUString& rLName)
1648         : SmXMLSubContext_Impl(rImport,nPrefix,rLName) {}
1649 
1650     void EndElement()
1651     {
1652         GenericEndElement(TRSUP,RSUP);
1653     }
1654 };
1655 
1656 ////////////////////////////////////////////////////////////
1657 
1658 class SmXMLSubSupContext_Impl : public SmXMLRowContext_Impl
1659 {
1660 protected:
1661     void GenericEndElement(SmTokenType eType, SmSubSup aSub,SmSubSup aSup);
1662 
1663 public:
1664     SmXMLSubSupContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1665         const OUString& rLName)
1666         : SmXMLRowContext_Impl(rImport,nPrefix,rLName) {}
1667 
1668     void EndElement()
1669     {
1670         GenericEndElement(TRSUB,RSUB,RSUP);
1671     }
1672 };
1673 
1674 void SmXMLSubSupContext_Impl::GenericEndElement(SmTokenType eType,
1675         SmSubSup aSub,SmSubSup aSup)
1676 {
1677     /*The <msub> element requires exactly 3 arguments.*/
1678     const bool bNodeCheck = GetSmImport().GetNodeStack().Count() - nElementCount == 3;
1679     DBG_ASSERT( bNodeCheck, "SubSup has not three arguments" );
1680     if (!bNodeCheck)
1681         return;
1682 
1683     SmToken aToken;
1684     aToken.cMathChar = '\0';
1685     aToken.nGroup = 0;
1686     aToken.nLevel = 0;
1687     aToken.eType = eType;
1688     SmSubSupNode *pNode = new SmSubSupNode(aToken);
1689     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1690 
1691     // initialize subnodes array
1692     SmNodeArray  aSubNodes;
1693     aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES);
1694     for (sal_uLong i = 1;  i < aSubNodes.size();  i++)
1695         aSubNodes[i] = NULL;
1696 
1697     aSubNodes[aSup+1] = rNodeStack.Pop();
1698     aSubNodes[aSub+1] = rNodeStack.Pop();
1699     aSubNodes[0] =  rNodeStack.Pop();
1700     pNode->SetSubNodes(aSubNodes);
1701     rNodeStack.Push(pNode);
1702 }
1703 
1704 ////////////////////////////////////////////////////////////
1705 
1706 class SmXMLUnderContext_Impl : public SmXMLSubContext_Impl
1707 {
1708 protected:
1709     sal_Int16 nAttrCount;
1710 
1711 public:
1712     SmXMLUnderContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1713         const OUString& rLName)
1714         : SmXMLSubContext_Impl(rImport,nPrefix,rLName) {}
1715 
1716     void StartElement(const uno::Reference< xml::sax::XAttributeList > &xAttrList );
1717     void EndElement();
1718     void HandleAccent();
1719 };
1720 
1721 void SmXMLUnderContext_Impl::StartElement(const uno::Reference<
1722     xml::sax::XAttributeList > & xAttrList )
1723 {
1724     nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
1725 }
1726 
1727 void SmXMLUnderContext_Impl::HandleAccent()
1728 {
1729     const bool bNodeCheck = GetSmImport().GetNodeStack().Count() - nElementCount == 2;
1730     DBG_ASSERT( bNodeCheck, "Sub has not two arguments" );
1731     if (!bNodeCheck)
1732         return;
1733 
1734     /*Just one special case for the underline thing*/
1735     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1736     SmNode *pTest = rNodeStack.Pop();
1737     SmToken aToken;
1738     aToken.cMathChar = '\0';
1739     aToken.nGroup = 0;
1740     aToken.nLevel = 0;
1741     aToken.eType = TUNDERLINE;
1742 
1743 
1744     SmNodeArray aSubNodes;
1745     aSubNodes.resize(2);
1746 
1747     SmStructureNode *pNode = new SmAttributNode(aToken);
1748     if ((pTest->GetToken().cMathChar & 0x0FFF) == 0x0332)
1749     {
1750         aSubNodes[0] = new SmRectangleNode(aToken);
1751         delete pTest;
1752     }
1753     else
1754         aSubNodes[0] = pTest;
1755 
1756     aSubNodes[1] = rNodeStack.Pop();
1757     pNode->SetSubNodes(aSubNodes);
1758     pNode->SetScaleMode(SCALE_WIDTH);
1759     rNodeStack.Push(pNode);
1760 }
1761 
1762 
1763 void SmXMLUnderContext_Impl::EndElement()
1764 {
1765     if (!nAttrCount)
1766         GenericEndElement(TCSUB,CSUB);
1767     else
1768         HandleAccent();
1769 #if 0
1770     //UnderBrace trick
1771     SmStructureNode *pNode = rNodeStack.Pop();
1772     if (pNode->GetSubNode(1)->GetToken().cMathChar == (0x0332|0xf000))
1773     if (pNode->GetSubNode(0)->GetToken().cMathChar == (0x0332|0xf000))
1774 #endif
1775 }
1776 
1777 ////////////////////////////////////////////////////////////
1778 
1779 class SmXMLOverContext_Impl : public SmXMLSubContext_Impl
1780 {
1781 protected:
1782     sal_Int16 nAttrCount;
1783 
1784 public:
1785     SmXMLOverContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1786         const OUString& rLName)
1787         : SmXMLSubContext_Impl(rImport,nPrefix,rLName), nAttrCount(0) {}
1788 
1789     void EndElement();
1790     void StartElement(const uno::Reference< xml::sax::XAttributeList > &xAttrList );
1791     void HandleAccent();
1792 };
1793 
1794 
1795 void SmXMLOverContext_Impl::StartElement(const uno::Reference<
1796     xml::sax::XAttributeList > & xAttrList )
1797 {
1798     nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
1799 }
1800 
1801 
1802 void SmXMLOverContext_Impl::EndElement()
1803 {
1804     if (!nAttrCount)
1805         GenericEndElement(TCSUP,CSUP);
1806     else
1807         HandleAccent();
1808 }
1809 
1810 
1811 void SmXMLOverContext_Impl::HandleAccent()
1812 {
1813     const bool bNodeCheck = GetSmImport().GetNodeStack().Count() - nElementCount == 2;
1814     DBG_ASSERT( bNodeCheck, "Sub has not two arguments" );
1815     if (!bNodeCheck)
1816         return;
1817 
1818     SmToken aToken;
1819     aToken.cMathChar = '\0';
1820     aToken.nGroup = 0;
1821     aToken.nLevel = 0;
1822     aToken.eType = TACUTE;
1823 
1824     SmAttributNode *pNode = new SmAttributNode(aToken);
1825     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
1826 
1827     SmNodeArray aSubNodes;
1828     aSubNodes.resize(2);
1829     aSubNodes[0] = rNodeStack.Pop();
1830     aSubNodes[1] = rNodeStack.Pop();
1831     pNode->SetSubNodes(aSubNodes);
1832     pNode->SetScaleMode(SCALE_WIDTH);
1833     rNodeStack.Push(pNode);
1834 
1835 }
1836 
1837 ////////////////////////////////////////////////////////////
1838 
1839 class SmXMLUnderOverContext_Impl : public SmXMLSubSupContext_Impl
1840 {
1841 public:
1842     SmXMLUnderOverContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1843         const OUString& rLName)
1844         : SmXMLSubSupContext_Impl(rImport,nPrefix,rLName) {}
1845 
1846     void EndElement()
1847     {
1848         GenericEndElement(TCSUB,CSUB,CSUP);
1849     }
1850 };
1851 
1852 ////////////////////////////////////////////////////////////
1853 
1854 class SmXMLMultiScriptsContext_Impl : public SmXMLSubSupContext_Impl
1855 {
1856     sal_Bool bHasPrescripts;
1857 
1858 public:
1859     SmXMLMultiScriptsContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1860         const OUString& rLName) :
1861         SmXMLSubSupContext_Impl(rImport,nPrefix,rLName),
1862         bHasPrescripts(sal_False) {}
1863 
1864     void EndElement();
1865     void MiddleElement();
1866     SvXMLImportContext *CreateChildContext(sal_uInt16 nPrefix,
1867         const OUString& rLocalName,
1868         const uno::Reference< xml::sax::XAttributeList > &xAttrList);
1869 };
1870 
1871 ////////////////////////////////////////////////////////////
1872 
1873 class SmXMLNoneContext_Impl : public SmXMLImportContext
1874 {
1875 public:
1876     SmXMLNoneContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1877         const OUString& rLName)
1878         : SmXMLImportContext(rImport,nPrefix,rLName) {}
1879 
1880     void EndElement();
1881 };
1882 
1883 
1884 void SmXMLNoneContext_Impl::EndElement(void)
1885 {
1886     SmToken aToken;
1887     aToken.cMathChar = '\0';
1888     aToken.nGroup = 0;
1889     aToken.aText.Erase();
1890     aToken.nLevel = 5;
1891     aToken.eType = TIDENT;
1892     GetSmImport().GetNodeStack().Push(
1893         new SmTextNode(aToken,FNT_VARIABLE));
1894 }
1895 
1896 ////////////////////////////////////////////////////////////
1897 
1898 class SmXMLPrescriptsContext_Impl : public SmXMLImportContext
1899 {
1900 public:
1901     SmXMLPrescriptsContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1902         const OUString& rLName)
1903         : SmXMLImportContext(rImport,nPrefix,rLName) {}
1904 };
1905 
1906 ////////////////////////////////////////////////////////////
1907 
1908 class SmXMLTableRowContext_Impl : public SmXMLRowContext_Impl
1909 {
1910 public:
1911     SmXMLTableRowContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1912         const OUString& rLName) :
1913         SmXMLRowContext_Impl(rImport,nPrefix,rLName)
1914         {}
1915 
1916     SvXMLImportContext *CreateChildContext(sal_uInt16 nPrefix,
1917         const OUString& rLocalName,
1918         const uno::Reference< xml::sax::XAttributeList > &xAttrList);
1919 };
1920 
1921 
1922 ////////////////////////////////////////////////////////////
1923 
1924 class SmXMLTableContext_Impl : public SmXMLTableRowContext_Impl
1925 {
1926 public:
1927     SmXMLTableContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1928         const OUString& rLName) :
1929         SmXMLTableRowContext_Impl(rImport,nPrefix,rLName)
1930         {}
1931 
1932     void EndElement();
1933     SvXMLImportContext *CreateChildContext(sal_uInt16 nPrefix,
1934         const OUString& rLocalName,
1935         const uno::Reference< xml::sax::XAttributeList > &xAttrList);
1936 };
1937 
1938 
1939 ////////////////////////////////////////////////////////////
1940 
1941 class SmXMLTableCellContext_Impl : public SmXMLRowContext_Impl
1942 {
1943 public:
1944     SmXMLTableCellContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1945         const OUString& rLName) :
1946         SmXMLRowContext_Impl(rImport,nPrefix,rLName)
1947         {}
1948 };
1949 
1950 ////////////////////////////////////////////////////////////
1951 
1952 class SmXMLAlignGroupContext_Impl : public SmXMLRowContext_Impl
1953 {
1954 public:
1955     SmXMLAlignGroupContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1956         const OUString& rLName) :
1957         SmXMLRowContext_Impl(rImport,nPrefix,rLName)
1958         {}
1959 
1960     /*Don't do anything with alignment for now*/
1961     void EndElement()
1962     {
1963     }
1964 };
1965 
1966 ////////////////////////////////////////////////////////////
1967 
1968 class SmXMLActionContext_Impl : public SmXMLRowContext_Impl
1969 {
1970 public:
1971     SmXMLActionContext_Impl(SmXMLImport &rImport,sal_uInt16 nPrefix,
1972         const OUString& rLName) :
1973         SmXMLRowContext_Impl(rImport,nPrefix,rLName)
1974         {}
1975 
1976     void EndElement();
1977 };
1978 
1979 ////////////////////////////////////////////////////////////
1980 
1981 // NB: virtually inherit so we can multiply inherit properly
1982 //     in SmXMLFlatDocContext_Impl
1983 class SmXMLOfficeContext_Impl : public virtual SvXMLImportContext
1984 {
1985 public:
1986     SmXMLOfficeContext_Impl( SmXMLImport &rImport, sal_uInt16 nPrfx,
1987         const OUString& rLName)
1988         : SvXMLImportContext(rImport,nPrfx,rLName) {}
1989 
1990     virtual SvXMLImportContext *CreateChildContext(sal_uInt16 nPrefix, const OUString& rLocalName, const uno::Reference< xml::sax::XAttributeList > &xAttrList);
1991 };
1992 
1993 SvXMLImportContext *SmXMLOfficeContext_Impl::CreateChildContext(sal_uInt16 nPrefix,
1994         const OUString& rLocalName,
1995         const uno::Reference< xml::sax::XAttributeList > &xAttrList)
1996 {
1997     SvXMLImportContext *pContext = 0;
1998     if ( XML_NAMESPACE_OFFICE == nPrefix &&
1999         rLocalName == GetXMLToken(XML_META) )
2000     {
2001         DBG_WARNING("XML_TOK_DOC_META: should not have come here, maybe document is invalid?");
2002     }
2003     else if ( XML_NAMESPACE_OFFICE == nPrefix &&
2004         rLocalName == GetXMLToken(XML_SETTINGS) )
2005     {
2006         pContext = new XMLDocumentSettingsContext( GetImport(),
2007                                     XML_NAMESPACE_OFFICE, rLocalName,
2008                                     xAttrList );
2009     }
2010     else
2011         pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
2012 
2013     return pContext;
2014 }
2015 
2016 ////////////////////////////////////////////////////////////
2017 
2018 // context for flat file xml format
2019 class SmXMLFlatDocContext_Impl
2020     : public SmXMLOfficeContext_Impl, public SvXMLMetaDocumentContext
2021 {
2022 public:
2023     SmXMLFlatDocContext_Impl( SmXMLImport& i_rImport,
2024         sal_uInt16 i_nPrefix, const OUString & i_rLName,
2025         const uno::Reference<document::XDocumentProperties>& i_xDocProps,
2026         const uno::Reference<xml::sax::XDocumentHandler>& i_xDocBuilder);
2027 
2028     virtual ~SmXMLFlatDocContext_Impl();
2029 
2030     virtual SvXMLImportContext *CreateChildContext(sal_uInt16 i_nPrefix, const OUString& i_rLocalName, const uno::Reference<xml::sax::XAttributeList>& i_xAttrList);
2031 };
2032 
2033 SmXMLFlatDocContext_Impl::SmXMLFlatDocContext_Impl( SmXMLImport& i_rImport,
2034         sal_uInt16 i_nPrefix, const OUString & i_rLName,
2035         const uno::Reference<document::XDocumentProperties>& i_xDocProps,
2036         const uno::Reference<xml::sax::XDocumentHandler>& i_xDocBuilder) :
2037     SvXMLImportContext(i_rImport, i_nPrefix, i_rLName),
2038     SmXMLOfficeContext_Impl(i_rImport, i_nPrefix, i_rLName),
2039     SvXMLMetaDocumentContext(i_rImport, i_nPrefix, i_rLName,
2040         i_xDocProps, i_xDocBuilder)
2041 {
2042 }
2043 
2044 SmXMLFlatDocContext_Impl::~SmXMLFlatDocContext_Impl()
2045 {
2046 }
2047 
2048 SvXMLImportContext *SmXMLFlatDocContext_Impl::CreateChildContext(
2049     sal_uInt16 i_nPrefix, const OUString& i_rLocalName,
2050     const uno::Reference<xml::sax::XAttributeList>& i_xAttrList)
2051 {
2052     // behave like meta base class iff we encounter office:meta
2053     if ( XML_NAMESPACE_OFFICE == i_nPrefix &&
2054             i_rLocalName == GetXMLToken(XML_META) )
2055     {
2056         return SvXMLMetaDocumentContext::CreateChildContext(
2057                     i_nPrefix, i_rLocalName, i_xAttrList );
2058     }
2059     else
2060     {
2061         return SmXMLOfficeContext_Impl::CreateChildContext(
2062                     i_nPrefix, i_rLocalName, i_xAttrList );
2063     }
2064 }
2065 
2066 ////////////////////////////////////////////////////////////
2067 
2068 static __FAR_DATA SvXMLTokenMapEntry aPresLayoutElemTokenMap[] =
2069 {
2070     { XML_NAMESPACE_MATH,   XML_SEMANTICS, XML_TOK_SEMANTICS },
2071     { XML_NAMESPACE_MATH,   XML_MATH,      XML_TOK_MATH   },
2072     { XML_NAMESPACE_MATH,   XML_MSTYLE,    XML_TOK_MSTYLE  },
2073     { XML_NAMESPACE_MATH,   XML_MERROR,    XML_TOK_MERROR },
2074     { XML_NAMESPACE_MATH,   XML_MPHANTOM,  XML_TOK_MPHANTOM },
2075     { XML_NAMESPACE_MATH,   XML_MROW,      XML_TOK_MROW },
2076     { XML_NAMESPACE_MATH,   XML_MFRAC,     XML_TOK_MFRAC },
2077     { XML_NAMESPACE_MATH,   XML_MSQRT,     XML_TOK_MSQRT },
2078     { XML_NAMESPACE_MATH,   XML_MROOT,     XML_TOK_MROOT },
2079     { XML_NAMESPACE_MATH,   XML_MSUB,      XML_TOK_MSUB },
2080     { XML_NAMESPACE_MATH,   XML_MSUP,      XML_TOK_MSUP },
2081     { XML_NAMESPACE_MATH,   XML_MSUBSUP,   XML_TOK_MSUBSUP },
2082     { XML_NAMESPACE_MATH,   XML_MUNDER,    XML_TOK_MUNDER },
2083     { XML_NAMESPACE_MATH,   XML_MOVER,     XML_TOK_MOVER },
2084     { XML_NAMESPACE_MATH,   XML_MUNDEROVER,    XML_TOK_MUNDEROVER },
2085     { XML_NAMESPACE_MATH,   XML_MMULTISCRIPTS, XML_TOK_MMULTISCRIPTS },
2086     { XML_NAMESPACE_MATH,   XML_MTABLE,    XML_TOK_MTABLE },
2087     { XML_NAMESPACE_MATH,   XML_MACTION,   XML_TOK_MACTION },
2088     { XML_NAMESPACE_MATH,   XML_MFENCED,   XML_TOK_MFENCED },
2089     { XML_NAMESPACE_MATH,   XML_MPADDED,   XML_TOK_MPADDED },
2090     XML_TOKEN_MAP_END
2091 };
2092 
2093 static __FAR_DATA SvXMLTokenMapEntry aPresLayoutAttrTokenMap[] =
2094 {
2095     { XML_NAMESPACE_MATH,   XML_FONTWEIGHT,      XML_TOK_FONTWEIGHT    },
2096     { XML_NAMESPACE_MATH,   XML_FONTSTYLE,       XML_TOK_FONTSTYLE     },
2097     { XML_NAMESPACE_MATH,   XML_FONTSIZE,        XML_TOK_FONTSIZE      },
2098     { XML_NAMESPACE_MATH,   XML_FONTFAMILY,      XML_TOK_FONTFAMILY    },
2099     { XML_NAMESPACE_MATH,   XML_COLOR,           XML_TOK_COLOR },
2100     { XML_NAMESPACE_MATH,   XML_MATHCOLOR,       XML_TOK_MATHCOLOR },
2101     XML_TOKEN_MAP_END
2102 };
2103 
2104 static __FAR_DATA SvXMLTokenMapEntry aFencedAttrTokenMap[] =
2105 {
2106     { XML_NAMESPACE_MATH,   XML_OPEN,       XML_TOK_OPEN },
2107     { XML_NAMESPACE_MATH,   XML_CLOSE,      XML_TOK_CLOSE },
2108     XML_TOKEN_MAP_END
2109 };
2110 
2111 static __FAR_DATA SvXMLTokenMapEntry aOperatorAttrTokenMap[] =
2112 {
2113     { XML_NAMESPACE_MATH,   XML_STRETCHY,      XML_TOK_STRETCHY },
2114     XML_TOKEN_MAP_END
2115 };
2116 
2117 static __FAR_DATA SvXMLTokenMapEntry aAnnotationAttrTokenMap[] =
2118 {
2119     { XML_NAMESPACE_MATH,   XML_ENCODING,      XML_TOK_ENCODING },
2120     XML_TOKEN_MAP_END
2121 };
2122 
2123 
2124 static __FAR_DATA SvXMLTokenMapEntry aPresElemTokenMap[] =
2125 {
2126     { XML_NAMESPACE_MATH,   XML_ANNOTATION,    XML_TOK_ANNOTATION },
2127     { XML_NAMESPACE_MATH,   XML_MI,    XML_TOK_MI },
2128     { XML_NAMESPACE_MATH,   XML_MN,    XML_TOK_MN },
2129     { XML_NAMESPACE_MATH,   XML_MO,    XML_TOK_MO },
2130     { XML_NAMESPACE_MATH,   XML_MTEXT, XML_TOK_MTEXT },
2131     { XML_NAMESPACE_MATH,   XML_MSPACE,XML_TOK_MSPACE },
2132     { XML_NAMESPACE_MATH,   XML_MS,    XML_TOK_MS },
2133     { XML_NAMESPACE_MATH,   XML_MALIGNGROUP,   XML_TOK_MALIGNGROUP },
2134     XML_TOKEN_MAP_END
2135 };
2136 
2137 static __FAR_DATA SvXMLTokenMapEntry aPresScriptEmptyElemTokenMap[] =
2138 {
2139     { XML_NAMESPACE_MATH,   XML_MPRESCRIPTS,   XML_TOK_MPRESCRIPTS },
2140     { XML_NAMESPACE_MATH,   XML_NONE,  XML_TOK_NONE },
2141     XML_TOKEN_MAP_END
2142 };
2143 
2144 static __FAR_DATA SvXMLTokenMapEntry aPresTableElemTokenMap[] =
2145 {
2146     { XML_NAMESPACE_MATH,   XML_MTR,       XML_TOK_MTR },
2147     { XML_NAMESPACE_MATH,   XML_MTD,       XML_TOK_MTD },
2148     XML_TOKEN_MAP_END
2149 };
2150 
2151 static __FAR_DATA SvXMLTokenMapEntry aColorTokenMap[] =
2152 {
2153     { XML_NAMESPACE_MATH,   XML_BLACK,        TBLACK},
2154     { XML_NAMESPACE_MATH,   XML_WHITE,        TWHITE},
2155     { XML_NAMESPACE_MATH,   XML_RED,          TRED},
2156     { XML_NAMESPACE_MATH,   XML_GREEN,        TGREEN},
2157     { XML_NAMESPACE_MATH,   XML_BLUE,         TBLUE},
2158     { XML_NAMESPACE_MATH,   XML_AQUA,         TAQUA},
2159     { XML_NAMESPACE_MATH,   XML_FUCHSIA,      TFUCHSIA},
2160     { XML_NAMESPACE_MATH,   XML_YELLOW,       TYELLOW},
2161     { XML_NAMESPACE_MATH,   XML_NAVY,         TNAVY},
2162     { XML_NAMESPACE_MATH,   XML_TEAL,         TTEAL},
2163     { XML_NAMESPACE_MATH,   XML_MAROON,       TMAROON},
2164     { XML_NAMESPACE_MATH,   XML_PURPLE,       TPURPLE},
2165     { XML_NAMESPACE_MATH,   XML_OLIVE,        TOLIVE},
2166     { XML_NAMESPACE_MATH,   XML_GRAY,         TGRAY},
2167     { XML_NAMESPACE_MATH,   XML_SILVER,       TSILVER},
2168     { XML_NAMESPACE_MATH,   XML_LIME,         TLIME},
2169     XML_TOKEN_MAP_END
2170 };
2171 
2172 ////////////////////////////////////////////////////////////
2173 
2174 const SvXMLTokenMap& SmXMLImport::GetPresLayoutElemTokenMap()
2175 {
2176     if (!pPresLayoutElemTokenMap)
2177         pPresLayoutElemTokenMap = new SvXMLTokenMap(aPresLayoutElemTokenMap);
2178     return *pPresLayoutElemTokenMap;
2179 }
2180 
2181 const SvXMLTokenMap& SmXMLImport::GetPresLayoutAttrTokenMap()
2182 {
2183     if (!pPresLayoutAttrTokenMap)
2184         pPresLayoutAttrTokenMap = new SvXMLTokenMap(aPresLayoutAttrTokenMap);
2185     return *pPresLayoutAttrTokenMap;
2186 }
2187 
2188 
2189 const SvXMLTokenMap& SmXMLImport::GetFencedAttrTokenMap()
2190 {
2191     if (!pFencedAttrTokenMap)
2192         pFencedAttrTokenMap = new SvXMLTokenMap(aFencedAttrTokenMap);
2193     return *pFencedAttrTokenMap;
2194 }
2195 
2196 const SvXMLTokenMap& SmXMLImport::GetOperatorAttrTokenMap()
2197 {
2198     if (!pOperatorAttrTokenMap)
2199         pOperatorAttrTokenMap = new SvXMLTokenMap(aOperatorAttrTokenMap);
2200     return *pOperatorAttrTokenMap;
2201 }
2202 
2203 const SvXMLTokenMap& SmXMLImport::GetAnnotationAttrTokenMap()
2204 {
2205     if (!pAnnotationAttrTokenMap)
2206         pAnnotationAttrTokenMap = new SvXMLTokenMap(aAnnotationAttrTokenMap);
2207     return *pAnnotationAttrTokenMap;
2208 }
2209 
2210 const SvXMLTokenMap& SmXMLImport::GetPresElemTokenMap()
2211 {
2212     if (!pPresElemTokenMap)
2213         pPresElemTokenMap = new SvXMLTokenMap(aPresElemTokenMap);
2214     return *pPresElemTokenMap;
2215 }
2216 
2217 const SvXMLTokenMap& SmXMLImport::GetPresScriptEmptyElemTokenMap()
2218 {
2219     if (!pPresScriptEmptyElemTokenMap)
2220         pPresScriptEmptyElemTokenMap = new
2221             SvXMLTokenMap(aPresScriptEmptyElemTokenMap);
2222     return *pPresScriptEmptyElemTokenMap;
2223 }
2224 
2225 const SvXMLTokenMap& SmXMLImport::GetPresTableElemTokenMap()
2226 {
2227     if (!pPresTableElemTokenMap)
2228         pPresTableElemTokenMap = new SvXMLTokenMap(aPresTableElemTokenMap);
2229     return *pPresTableElemTokenMap;
2230 }
2231 
2232 const SvXMLTokenMap& SmXMLImport::GetColorTokenMap()
2233 {
2234     if (!pColorTokenMap)
2235         pColorTokenMap = new SvXMLTokenMap(aColorTokenMap);
2236     return *pColorTokenMap;
2237 }
2238 
2239 ////////////////////////////////////////////////////////////
2240 
2241 SvXMLImportContext *SmXMLDocContext_Impl::CreateChildContext(
2242     sal_uInt16 nPrefix,
2243     const OUString& rLocalName,
2244     const uno::Reference<xml::sax::XAttributeList>& xAttrList)
2245 {
2246     SvXMLImportContext* pContext = 0L;
2247 
2248     const SvXMLTokenMap& rTokenMap = GetSmImport().GetPresLayoutElemTokenMap();
2249 
2250     //sal_uInt32 nTest = rTokenMap.Get(nPrefix, rLocalName);
2251 
2252     switch(rTokenMap.Get(nPrefix, rLocalName))
2253     {
2254         //Consider semantics a dummy except for any starmath annotations
2255         case XML_TOK_SEMANTICS:
2256             pContext = GetSmImport().CreateRowContext(nPrefix,rLocalName,
2257                 xAttrList);
2258             break;
2259         /*General Layout Schemata*/
2260         case XML_TOK_MROW:
2261             pContext = GetSmImport().CreateRowContext(nPrefix,rLocalName,
2262                 xAttrList);
2263             break;
2264         case XML_TOK_MFRAC:
2265             pContext = GetSmImport().CreateFracContext(nPrefix,rLocalName,
2266                 xAttrList);
2267             break;
2268         case XML_TOK_MSQRT:
2269             pContext = GetSmImport().CreateSqrtContext(nPrefix,rLocalName,
2270                 xAttrList);
2271             break;
2272         case XML_TOK_MROOT:
2273             pContext = GetSmImport().CreateRootContext(nPrefix,rLocalName,
2274                 xAttrList);
2275             break;
2276         case XML_TOK_MSTYLE:
2277             pContext = GetSmImport().CreateStyleContext(nPrefix,rLocalName,
2278                 xAttrList);
2279             break;
2280         case XML_TOK_MERROR:
2281             pContext = GetSmImport().CreateErrorContext(nPrefix,rLocalName,
2282                 xAttrList);
2283             break;
2284         case XML_TOK_MPADDED:
2285             pContext = GetSmImport().CreatePaddedContext(nPrefix,rLocalName,
2286                 xAttrList);
2287             break;
2288         case XML_TOK_MPHANTOM:
2289             pContext = GetSmImport().CreatePhantomContext(nPrefix,rLocalName,
2290                 xAttrList);
2291             break;
2292         case XML_TOK_MFENCED:
2293             pContext = GetSmImport().CreateFencedContext(nPrefix,rLocalName,
2294                 xAttrList);
2295             break;
2296         /*Script and Limit Schemata*/
2297         case XML_TOK_MSUB:
2298             pContext = GetSmImport().CreateSubContext(nPrefix,rLocalName,
2299                 xAttrList);
2300             break;
2301         case XML_TOK_MSUP:
2302             pContext = GetSmImport().CreateSupContext(nPrefix,rLocalName,
2303                 xAttrList);
2304             break;
2305         case XML_TOK_MSUBSUP:
2306             pContext = GetSmImport().CreateSubSupContext(nPrefix,rLocalName,
2307                 xAttrList);
2308             break;
2309         case XML_TOK_MUNDER:
2310             pContext = GetSmImport().CreateUnderContext(nPrefix,rLocalName,
2311                 xAttrList);
2312             break;
2313         case XML_TOK_MOVER:
2314             pContext = GetSmImport().CreateOverContext(nPrefix,rLocalName,
2315                 xAttrList);
2316             break;
2317         case XML_TOK_MUNDEROVER:
2318             pContext = GetSmImport().CreateUnderOverContext(nPrefix,rLocalName,
2319                 xAttrList);
2320             break;
2321         case XML_TOK_MMULTISCRIPTS:
2322             pContext = GetSmImport().CreateMultiScriptsContext(nPrefix,
2323                 rLocalName, xAttrList);
2324             break;
2325         case XML_TOK_MTABLE:
2326             pContext = GetSmImport().CreateTableContext(nPrefix,
2327                 rLocalName, xAttrList);
2328             break;
2329         case XML_TOK_MACTION:
2330             pContext = GetSmImport().CreateActionContext(nPrefix,
2331                 rLocalName, xAttrList);
2332             break;
2333         default:
2334             /*Basically theres an implicit mrow around certain bare
2335              *elements, use a RowContext to see if this is one of
2336              *those ones*/
2337             SmXMLRowContext_Impl aTempContext(GetSmImport(),nPrefix,
2338                 GetXMLToken(XML_MROW));
2339 
2340             pContext = aTempContext.StrictCreateChildContext(nPrefix,
2341                 rLocalName, xAttrList);
2342             break;
2343     }
2344     return pContext;
2345 }
2346 
2347 void SmXMLDocContext_Impl::EndElement()
2348 {
2349     SmNodeArray ContextArray;
2350     ContextArray.resize(1);
2351     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2352 
2353     for (sal_uLong i=0;i< 1;i++)
2354         ContextArray[i] = rNodeStack.Pop();
2355 
2356     SmToken aDummy;
2357     SmStructureNode *pSNode = new SmLineNode(aDummy);
2358     pSNode->SetSubNodes(ContextArray);
2359     rNodeStack.Push(pSNode);
2360 
2361     SmNodeArray  LineArray;
2362     sal_uLong n = rNodeStack.Count();
2363     LineArray.resize(n);
2364     for (sal_uLong j = 0; j < n; j++)
2365         LineArray[n - (j + 1)] = rNodeStack.Pop();
2366     SmStructureNode *pSNode2 = new SmTableNode(aDummy);
2367     pSNode2->SetSubNodes(LineArray);
2368     rNodeStack.Push(pSNode2);
2369 }
2370 
2371 void SmXMLFracContext_Impl::EndElement()
2372 {
2373     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2374     const bool bNodeCheck = rNodeStack.Count() - nElementCount == 2;
2375     DBG_ASSERT( bNodeCheck, "Fraction (mfrac) tag is missing component" );
2376     if (!bNodeCheck)
2377         return;
2378 
2379     SmToken aToken;
2380     aToken.cMathChar = '\0';
2381     aToken.nGroup = 0;
2382     aToken.nLevel = 0;
2383     aToken.eType = TOVER;
2384     SmStructureNode *pSNode = new SmBinVerNode(aToken);
2385     SmNode *pOper = new SmRectangleNode(aToken);
2386     SmNode *pSecond = rNodeStack.Pop();
2387     SmNode *pFirst = rNodeStack.Pop();
2388     pSNode->SetSubNodes(pFirst,pOper,pSecond);
2389     rNodeStack.Push(pSNode);
2390 }
2391 
2392 void SmXMLRootContext_Impl::EndElement()
2393 {
2394     /*The <mroot> element requires exactly 2 arguments.*/
2395     const bool bNodeCheck = GetSmImport().GetNodeStack().Count() - nElementCount == 2;
2396     DBG_ASSERT( bNodeCheck, "Root tag is missing component" );
2397     if (!bNodeCheck)
2398         return;
2399 
2400     SmToken aToken;
2401     aToken.cMathChar = MS_SQRT;  //Temporary: alert, based on StarSymbol font
2402     aToken.nGroup = 0;
2403     aToken.nLevel = 0;
2404     aToken.eType = TNROOT;
2405     SmStructureNode *pSNode = new SmRootNode(aToken);
2406     SmNode *pOper = new SmRootSymbolNode(aToken);
2407     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2408     SmNode *pIndex = rNodeStack.Pop();
2409     SmNode *pBase = rNodeStack.Pop();
2410     pSNode->SetSubNodes(pIndex,pOper,pBase);
2411     rNodeStack.Push(pSNode);
2412 }
2413 
2414 void SmXMLSqrtContext_Impl::EndElement()
2415 {
2416     /*
2417     <msqrt> accepts any number of arguments; if this number is not 1, its
2418     contents are treated as a single "inferred <mrow>" containing its
2419     arguments
2420     */
2421     if (GetSmImport().GetNodeStack().Count() - nElementCount > 1)
2422         SmXMLRowContext_Impl::EndElement();
2423 
2424     SmToken aToken;
2425     aToken.cMathChar = MS_SQRT;  //Temporary: alert, based on StarSymbol font
2426     aToken.nGroup = 0;
2427     aToken.nLevel = 0;
2428     aToken.eType = TSQRT;
2429     SmStructureNode *pSNode = new SmRootNode(aToken);
2430     SmNode *pOper = new SmRootSymbolNode(aToken);
2431     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2432     pSNode->SetSubNodes(0,pOper,rNodeStack.Pop());
2433     rNodeStack.Push(pSNode);
2434 }
2435 
2436 void SmXMLRowContext_Impl::EndElement()
2437 {
2438     SmNodeArray aRelationArray;
2439     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2440     sal_uLong nSize = rNodeStack.Count()-nElementCount;
2441 
2442     if (nSize > 0)
2443     {
2444         aRelationArray.resize(nSize);
2445         for (sal_uLong j=rNodeStack.Count()-nElementCount;j > 0;j--)
2446             aRelationArray[j-1] = rNodeStack.Pop();
2447 
2448 
2449         //If the first or last element is an operator with stretchyness
2450         //set then we must create a brace node here from those elements,
2451         //removing the stretchness from the operators and applying it to
2452         //ourselves, and creating the appropriate dummy StarMath none bracket
2453         //to balance the arrangement
2454         if (((aRelationArray[0]->GetScaleMode() == SCALE_HEIGHT)
2455             && (aRelationArray[0]->GetType() == NMATH))
2456         || ((aRelationArray[nSize-1]->GetScaleMode() == SCALE_HEIGHT)
2457             && (aRelationArray[nSize-1]->GetType() == NMATH)))
2458         {
2459             SmToken aToken;
2460             aToken.cMathChar = '\0';
2461             aToken.nGroup = 0;
2462             aToken.nLevel = 5;
2463 
2464             int nLeft=0,nRight=0;
2465             if ((aRelationArray[0]->GetScaleMode() == SCALE_HEIGHT)
2466                 && (aRelationArray[0]->GetType() == NMATH))
2467             {
2468                 aToken = aRelationArray[0]->GetToken();
2469                 nLeft=1;
2470             }
2471             else
2472                 aToken.cMathChar = '\0';
2473 
2474             aToken.eType = TLPARENT;
2475             SmNode *pLeft = new SmMathSymbolNode(aToken);
2476 
2477             if ((aRelationArray[nSize-1]->GetScaleMode() == SCALE_HEIGHT)
2478                 && (aRelationArray[nSize-1]->GetType() == NMATH))
2479             {
2480                 aToken = aRelationArray[nSize-1]->GetToken();
2481                 nRight=1;
2482             }
2483             else
2484                 aToken.cMathChar = '\0';
2485 
2486             aToken.eType = TRPARENT;
2487             SmNode *pRight = new SmMathSymbolNode(aToken);
2488 
2489             SmNodeArray aRelationArray2;
2490 
2491             //!! nSize-nLeft-nRight may be < 0 !!
2492             int nRelArrSize = nSize-nLeft-nRight;
2493             if (nRelArrSize > 0)
2494             {
2495                 aRelationArray2.resize(nRelArrSize);
2496                 for (int i=0;i < nRelArrSize;i++)
2497                     aRelationArray2[i] = aRelationArray[i+nLeft];
2498             }
2499 
2500             SmToken aDummy;
2501             SmStructureNode *pSNode = new SmBraceNode(aToken);
2502             SmStructureNode *pBody = new SmExpressionNode(aDummy);
2503             pBody->SetSubNodes(aRelationArray2);
2504 
2505             pSNode->SetSubNodes(pLeft,pBody,pRight);
2506             pSNode->SetScaleMode(SCALE_HEIGHT);
2507             rNodeStack.Push(pSNode);
2508             return;
2509         }
2510     }
2511     else //Multiple newlines result in empty row elements
2512     {
2513         aRelationArray.resize(1);
2514         SmToken aToken;
2515         aToken.cMathChar = '\0';
2516         aToken.nGroup = 0;
2517         aToken.nLevel = 5;
2518         aToken.eType = TNEWLINE;
2519         aRelationArray[0] = new SmLineNode(aToken);
2520     }
2521 
2522     SmToken aDummy;
2523     SmStructureNode *pSNode = new SmExpressionNode(aDummy);
2524     pSNode->SetSubNodes(aRelationArray);
2525     rNodeStack.Push(pSNode);
2526 }
2527 
2528 
2529 SvXMLImportContext *SmXMLRowContext_Impl::StrictCreateChildContext(
2530     sal_uInt16 nPrefix,
2531     const OUString& rLocalName,
2532     const uno::Reference<xml::sax::XAttributeList>& xAttrList)
2533 {
2534     SvXMLImportContext* pContext = 0L;
2535 
2536     const SvXMLTokenMap& rTokenMap = GetSmImport().GetPresElemTokenMap();
2537     switch(rTokenMap.Get(nPrefix, rLocalName))
2538     {
2539         /*Note that these should accept malignmark subelements, but do not*/
2540         case XML_TOK_MN:
2541             pContext = GetSmImport().CreateNumberContext(nPrefix,rLocalName,
2542                 xAttrList);
2543             break;
2544         case XML_TOK_MI:
2545             pContext = GetSmImport().CreateIdentifierContext(nPrefix,rLocalName,
2546                 xAttrList);
2547             break;
2548         case XML_TOK_MO:
2549             pContext = GetSmImport().CreateOperatorContext(nPrefix,rLocalName,
2550                 xAttrList);
2551             break;
2552         case XML_TOK_MTEXT:
2553             pContext = GetSmImport().CreateTextContext(nPrefix,rLocalName,
2554                 xAttrList);
2555             break;
2556         case XML_TOK_MSPACE:
2557             pContext = GetSmImport().CreateSpaceContext(nPrefix,rLocalName,
2558                 xAttrList);
2559             break;
2560         case XML_TOK_MS:
2561             pContext = GetSmImport().CreateStringContext(nPrefix,rLocalName,
2562                 xAttrList);
2563             break;
2564 
2565         /*Note: The maligngroup should only be seen when the row
2566          * (or descendants) are in a table*/
2567         case XML_TOK_MALIGNGROUP:
2568             pContext = GetSmImport().CreateAlignGroupContext(nPrefix,rLocalName,
2569                 xAttrList);
2570             break;
2571 
2572         case XML_TOK_ANNOTATION:
2573             pContext = GetSmImport().CreateAnnotationContext(nPrefix,rLocalName,
2574                 xAttrList);
2575             break;
2576 
2577         default:
2578             break;
2579     }
2580     return pContext;
2581 }
2582 
2583 
2584 SvXMLImportContext *SmXMLRowContext_Impl::CreateChildContext(
2585     sal_uInt16 nPrefix,
2586     const OUString& rLocalName,
2587     const uno::Reference<xml::sax::XAttributeList>& xAttrList)
2588 {
2589     SvXMLImportContext* pContext = StrictCreateChildContext(nPrefix,
2590     rLocalName, xAttrList);
2591 
2592     if (!pContext)
2593     {
2594         //Hmm, unrecognized for this level, check to see if its
2595         //an element that can have an implicit schema around it
2596         pContext = SmXMLDocContext_Impl::CreateChildContext(nPrefix,
2597             rLocalName,xAttrList);
2598     }
2599     return pContext;
2600 }
2601 
2602 
2603 SvXMLImportContext *SmXMLMultiScriptsContext_Impl::CreateChildContext(
2604     sal_uInt16 nPrefix,
2605     const OUString& rLocalName,
2606     const uno::Reference<xml::sax::XAttributeList>& xAttrList)
2607 {
2608     SvXMLImportContext* pContext = 0L;
2609 
2610     const SvXMLTokenMap& rTokenMap = GetSmImport().
2611         GetPresScriptEmptyElemTokenMap();
2612     switch(rTokenMap.Get(nPrefix, rLocalName))
2613     {
2614         case XML_TOK_MPRESCRIPTS:
2615             MiddleElement();
2616             pContext = GetSmImport().CreatePrescriptsContext(nPrefix,
2617                 rLocalName, xAttrList);
2618             break;
2619         case XML_TOK_NONE:
2620             pContext = GetSmImport().CreateNoneContext(nPrefix,rLocalName,
2621                 xAttrList);
2622             break;
2623         default:
2624             pContext = SmXMLRowContext_Impl::CreateChildContext(nPrefix,
2625                 rLocalName,xAttrList);
2626             break;
2627     }
2628     return pContext;
2629 }
2630 
2631 void SmXMLMultiScriptsContext_Impl::MiddleElement()
2632 {
2633     bHasPrescripts=sal_True;
2634 
2635     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2636     DBG_ASSERT( rNodeStack.Count() - nElementCount > 0, "Sub has no arguments" );
2637     if (rNodeStack.Count()-nElementCount > 1)
2638     {
2639         SmToken aToken;
2640         aToken.cMathChar = '\0';
2641         aToken.nGroup = 0;
2642         aToken.nLevel = 0;
2643         aToken.eType = TRSUB;
2644         sal_uLong nFinalCount = rNodeStack.Count()-nElementCount-1;
2645 
2646         SmNodeStack aReverseStack;
2647         while (rNodeStack.Count()-nElementCount)
2648         {
2649             SmNode *pThing = rNodeStack.Pop();
2650             aReverseStack.Push(pThing);
2651         }
2652 
2653         for (sal_uLong nCount=0;nCount < nFinalCount;nCount+=2)
2654         {
2655             SmSubSupNode *pNode = new SmSubSupNode(aToken);
2656 
2657             // initialize subnodes array
2658             SmNodeArray  aSubNodes;
2659             aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES);
2660             for (sal_uLong i = 1;  i < aSubNodes.size();  i++)
2661                 aSubNodes[i] = NULL;
2662 
2663             /*On each loop the base and its sub sup pair becomes the
2664              base for the next loop to which the next sub sup pair is
2665              attached, i.e. wheels within wheels*/
2666             //if (nCount == 0)
2667             aSubNodes[0] = aReverseStack.Pop();
2668 
2669             SmNode *pScriptNode = aReverseStack.Pop();
2670 
2671             if (pScriptNode && ((pScriptNode->GetToken().eType != TIDENT) ||
2672                 (pScriptNode->GetToken().aText.Len())))
2673                 aSubNodes[RSUB+1] = pScriptNode;
2674             pScriptNode = aReverseStack.Pop();
2675             if (pScriptNode && ((pScriptNode->GetToken().eType != TIDENT) ||
2676                 (pScriptNode->GetToken().aText.Len())))
2677                 aSubNodes[RSUP+1] = pScriptNode;
2678 
2679             pNode->SetSubNodes(aSubNodes);
2680             aReverseStack.Push(pNode);
2681         }
2682         rNodeStack.Push(aReverseStack.Pop());
2683     }
2684 }
2685 
2686 
2687 void SmXMLTableContext_Impl::EndElement()
2688 {
2689     SmNodeArray aExpressionArray;
2690     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2691     SmNodeStack aReverseStack;
2692     aExpressionArray.resize(rNodeStack.Count()-nElementCount);
2693 
2694     sal_uLong nRows = rNodeStack.Count()-nElementCount;
2695     sal_uInt16 nCols = 0;
2696 
2697     SmStructureNode *pArray;
2698     for (sal_uLong i=rNodeStack.Count()-nElementCount;i > 0;i--)
2699     {
2700         pArray = (SmStructureNode *)rNodeStack.Pop();
2701         if (pArray->GetNumSubNodes() == 0)
2702         {
2703             //This is a little tricky, it is possible that there was
2704             //be elements that were not inside a <mtd> pair, in which
2705             //case they will not be in a row, i.e. they will not have
2706             //SubNodes, so we have to wait until here before we can
2707             //resolve the situation. Implicitsurrounding tags are
2708             //surprisingly difficult to get right within this
2709             //architecture
2710 
2711             SmNodeArray aRelationArray;
2712             aRelationArray.resize(1);
2713             aRelationArray[0] = pArray;
2714             SmToken aDummy;
2715             pArray = new SmExpressionNode(aDummy);
2716             pArray->SetSubNodes(aRelationArray);
2717         }
2718 
2719         if (pArray->GetNumSubNodes() > nCols)
2720             nCols = pArray->GetNumSubNodes();
2721         aReverseStack.Push(pArray);
2722     }
2723     aExpressionArray.resize(nCols*nRows);
2724     sal_uLong j=0;
2725     while (aReverseStack.Count())
2726     {
2727         pArray = (SmStructureNode *)aReverseStack.Pop();
2728         for (sal_uInt16 i=0;i<pArray->GetNumSubNodes();i++)
2729             aExpressionArray[j++] = pArray->GetSubNode(i);
2730     }
2731 
2732     SmToken aToken;
2733     aToken.cMathChar = '\0';
2734     aToken.nGroup = TRGROUP;
2735     aToken.nLevel = 0;
2736     aToken.eType = TMATRIX;
2737     SmMatrixNode *pSNode = new SmMatrixNode(aToken);
2738     pSNode->SetSubNodes(aExpressionArray);
2739     pSNode->SetRowCol(static_cast<sal_uInt16>(nRows),nCols);
2740     rNodeStack.Push(pSNode);
2741 }
2742 
2743 SvXMLImportContext *SmXMLTableRowContext_Impl::CreateChildContext(
2744     sal_uInt16 nPrefix,
2745     const OUString& rLocalName,
2746     const uno::Reference<xml::sax::XAttributeList>& xAttrList)
2747 {
2748     SvXMLImportContext* pContext = 0L;
2749 
2750     const SvXMLTokenMap& rTokenMap = GetSmImport().
2751         GetPresTableElemTokenMap();
2752     switch(rTokenMap.Get(nPrefix, rLocalName))
2753     {
2754         case XML_TOK_MTD:
2755             pContext = GetSmImport().CreateTableCellContext(nPrefix,
2756                 rLocalName, xAttrList);
2757             break;
2758         default:
2759             pContext = SmXMLRowContext_Impl::CreateChildContext(nPrefix,
2760                 rLocalName,xAttrList);
2761             break;
2762     }
2763     return pContext;
2764 }
2765 
2766 SvXMLImportContext *SmXMLTableContext_Impl::CreateChildContext(
2767     sal_uInt16 nPrefix,
2768     const OUString& rLocalName,
2769     const uno::Reference<xml::sax::XAttributeList>& xAttrList)
2770 {
2771     SvXMLImportContext* pContext = 0L;
2772 
2773     const SvXMLTokenMap& rTokenMap = GetSmImport().
2774         GetPresTableElemTokenMap();
2775     switch(rTokenMap.Get(nPrefix, rLocalName))
2776     {
2777         case XML_TOK_MTR:
2778             pContext = GetSmImport().CreateTableRowContext(nPrefix,rLocalName,
2779                 xAttrList);
2780             break;
2781         default:
2782             pContext = SmXMLTableRowContext_Impl::CreateChildContext(nPrefix,
2783                 rLocalName,xAttrList);
2784             break;
2785     }
2786     return pContext;
2787 }
2788 
2789 void SmXMLMultiScriptsContext_Impl::EndElement()
2790 {
2791     if (!bHasPrescripts)
2792         MiddleElement();
2793 
2794     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2795     if (rNodeStack.Count()-nElementCount > 1)
2796     {
2797         SmToken aToken;
2798         aToken.cMathChar = '\0';
2799         aToken.nGroup = 0;
2800         aToken.nLevel = 0;
2801         aToken.eType = TLSUB;
2802         sal_uLong nFinalCount = rNodeStack.Count()-nElementCount-1;
2803 
2804         SmNodeStack aReverseStack;
2805         while (rNodeStack.Count()-nElementCount)
2806             aReverseStack.Push(rNodeStack.Pop());
2807         for (sal_uLong nCount=0;nCount < nFinalCount;nCount+=2)
2808         {
2809             SmSubSupNode *pNode = new SmSubSupNode(aToken);
2810 
2811             // initialize subnodes array
2812             SmNodeArray  aSubNodes;
2813             aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES);
2814             for (sal_uLong i = 1;  i < aSubNodes.size();  i++)
2815                 aSubNodes[i] = NULL;
2816 
2817             /*On each loop the base and its sub sup pair becomes the
2818              base for the next loop to which the next sub sup pair is
2819              attached, i.e. wheels within wheels*/
2820             //if (nCount == 0)
2821             aSubNodes[0] = aReverseStack.Pop();
2822 
2823             SmNode *pScriptNode = aReverseStack.Pop();
2824             if (pScriptNode->GetToken().aText.Len())
2825                 aSubNodes[LSUB+1] = pScriptNode;
2826             pScriptNode = aReverseStack.Pop();
2827             if (pScriptNode->GetToken().aText.Len())
2828                 aSubNodes[LSUP+1] = pScriptNode;
2829 
2830             pNode->SetSubNodes(aSubNodes);
2831             aReverseStack.Push(pNode);
2832         }
2833         rNodeStack.Push(aReverseStack.Pop());
2834     }
2835 
2836 }
2837 void SmXMLActionContext_Impl::EndElement()
2838 {
2839     /*For now we will just assume that the
2840      selected attribute is one, and then just display
2841      that expression alone, i.e. remove all expect the
2842      first pushed one*/
2843 
2844     SmNodeStack &rNodeStack = GetSmImport().GetNodeStack();
2845     for (sal_uLong i=rNodeStack.Count()-nElementCount;i > 1;i--)
2846     {
2847         delete rNodeStack.Pop();
2848     }
2849 }
2850 
2851 SvXMLImportContext *SmXMLImport::CreateContext(sal_uInt16 nPrefix,
2852     const OUString &rLocalName,
2853     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2854 {
2855     if ( XML_NAMESPACE_OFFICE == nPrefix )
2856     {
2857         if ( (IsXMLToken(rLocalName, XML_DOCUMENT) ||
2858               IsXMLToken(rLocalName, XML_DOCUMENT_META)))
2859         {
2860             uno::Reference<xml::sax::XDocumentHandler> xDocBuilder(
2861                 mxServiceFactory->createInstance(
2862                     ::rtl::OUString::createFromAscii(
2863                         "com.sun.star.xml.dom.SAXDocumentBuilder")),
2864                     uno::UNO_QUERY_THROW);
2865             uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
2866                 GetModel(), uno::UNO_QUERY_THROW);
2867             return IsXMLToken(rLocalName, XML_DOCUMENT_META)
2868                 ? new SvXMLMetaDocumentContext(*this,
2869                         XML_NAMESPACE_OFFICE, rLocalName,
2870                         xDPS->getDocumentProperties(), xDocBuilder)
2871                 // flat OpenDocument file format -- this has not been tested...
2872                 : new SmXMLFlatDocContext_Impl( *this, nPrefix, rLocalName,
2873                             xDPS->getDocumentProperties(), xDocBuilder);
2874         }
2875         else
2876         {
2877             return new SmXMLOfficeContext_Impl( *this,nPrefix,rLocalName);
2878         }
2879     }
2880     else
2881         return new SmXMLDocContext_Impl(*this,nPrefix,rLocalName);
2882 }
2883 
2884 SvXMLImportContext *SmXMLImport::CreateRowContext(sal_uInt16 nPrefix,
2885     const OUString &rLocalName,
2886     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2887 {
2888         return new SmXMLRowContext_Impl(*this,nPrefix,rLocalName);
2889 }
2890 
2891 SvXMLImportContext *SmXMLImport::CreateTextContext(sal_uInt16 nPrefix,
2892     const OUString &rLocalName,
2893     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2894 {
2895     return new SmXMLTextContext_Impl(*this,nPrefix,rLocalName);
2896 }
2897 
2898 SvXMLImportContext *SmXMLImport::CreateAnnotationContext(sal_uInt16 nPrefix,
2899     const OUString &rLocalName,
2900     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2901 {
2902     return new SmXMLAnnotationContext_Impl(*this,nPrefix,rLocalName);
2903 }
2904 
2905 SvXMLImportContext *SmXMLImport::CreateStringContext(sal_uInt16 nPrefix,
2906     const OUString &rLocalName,
2907     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2908 {
2909     return new SmXMLStringContext_Impl(*this,nPrefix,rLocalName);
2910 }
2911 
2912 SvXMLImportContext *SmXMLImport::CreateNumberContext(sal_uInt16 nPrefix,
2913     const OUString &rLocalName,
2914     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2915 {
2916     return new SmXMLNumberContext_Impl(*this,nPrefix,rLocalName);
2917 }
2918 
2919 SvXMLImportContext *SmXMLImport::CreateIdentifierContext(sal_uInt16 nPrefix,
2920     const OUString &rLocalName,
2921     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2922 {
2923     return new SmXMLIdentifierContext_Impl(*this,nPrefix,rLocalName);
2924 }
2925 
2926 SvXMLImportContext *SmXMLImport::CreateOperatorContext(sal_uInt16 nPrefix,
2927     const OUString &rLocalName,
2928     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2929 {
2930     return new SmXMLOperatorContext_Impl(*this,nPrefix,rLocalName);
2931 }
2932 
2933 SvXMLImportContext *SmXMLImport::CreateSpaceContext(sal_uInt16 nPrefix,
2934     const OUString &rLocalName,
2935     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2936 {
2937     return new SmXMLSpaceContext_Impl(*this,nPrefix,rLocalName);
2938 }
2939 
2940 
2941 SvXMLImportContext *SmXMLImport::CreateFracContext(sal_uInt16 nPrefix,
2942     const OUString &rLocalName,
2943     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2944 {
2945     return new SmXMLFracContext_Impl(*this,nPrefix,rLocalName);
2946 }
2947 
2948 SvXMLImportContext *SmXMLImport::CreateSqrtContext(sal_uInt16 nPrefix,
2949     const OUString &rLocalName,
2950     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2951 {
2952     return new SmXMLSqrtContext_Impl(*this,nPrefix,rLocalName);
2953 }
2954 
2955 SvXMLImportContext *SmXMLImport::CreateRootContext(sal_uInt16 nPrefix,
2956     const OUString &rLocalName,
2957     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2958 {
2959     return new SmXMLRootContext_Impl(*this,nPrefix,rLocalName);
2960 }
2961 
2962 SvXMLImportContext *SmXMLImport::CreateStyleContext(sal_uInt16 nPrefix,
2963     const OUString &rLocalName,
2964     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2965 {
2966     return new SmXMLStyleContext_Impl(*this,nPrefix,rLocalName);
2967 }
2968 
2969 SvXMLImportContext *SmXMLImport::CreatePaddedContext(sal_uInt16 nPrefix,
2970     const OUString &rLocalName,
2971     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2972 {
2973     return new SmXMLPaddedContext_Impl(*this,nPrefix,rLocalName);
2974 }
2975 
2976 SvXMLImportContext *SmXMLImport::CreatePhantomContext(sal_uInt16 nPrefix,
2977     const OUString &rLocalName,
2978     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2979 {
2980     return new SmXMLPhantomContext_Impl(*this,nPrefix,rLocalName);
2981 }
2982 
2983 SvXMLImportContext *SmXMLImport::CreateFencedContext(sal_uInt16 nPrefix,
2984     const OUString &rLocalName,
2985     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2986 {
2987     return new SmXMLFencedContext_Impl(*this,nPrefix,rLocalName);
2988 }
2989 
2990 SvXMLImportContext *SmXMLImport::CreateErrorContext(sal_uInt16 nPrefix,
2991     const OUString &rLocalName,
2992     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
2993 {
2994     return new SmXMLErrorContext_Impl(*this,nPrefix,rLocalName);
2995 }
2996 
2997 SvXMLImportContext *SmXMLImport::CreateSubContext(sal_uInt16 nPrefix,
2998     const OUString &rLocalName,
2999     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3000 {
3001     return new SmXMLSubContext_Impl(*this,nPrefix,rLocalName);
3002 }
3003 
3004 SvXMLImportContext *SmXMLImport::CreateSubSupContext(sal_uInt16 nPrefix,
3005     const OUString &rLocalName,
3006     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3007 {
3008     return new SmXMLSubSupContext_Impl(*this,nPrefix,rLocalName);
3009 }
3010 
3011 SvXMLImportContext *SmXMLImport::CreateSupContext(sal_uInt16 nPrefix,
3012     const OUString &rLocalName,
3013     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3014 {
3015     return new SmXMLSupContext_Impl(*this,nPrefix,rLocalName);
3016 }
3017 
3018 SvXMLImportContext *SmXMLImport::CreateUnderContext(sal_uInt16 nPrefix,
3019     const OUString &rLocalName,
3020     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3021 {
3022         return new SmXMLUnderContext_Impl(*this,nPrefix,rLocalName);
3023 }
3024 
3025 SvXMLImportContext *SmXMLImport::CreateOverContext(sal_uInt16 nPrefix,
3026     const OUString &rLocalName,
3027     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3028 {
3029     return new SmXMLOverContext_Impl(*this,nPrefix,rLocalName);
3030 }
3031 
3032 SvXMLImportContext *SmXMLImport::CreateUnderOverContext(sal_uInt16 nPrefix,
3033     const OUString &rLocalName,
3034     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3035 {
3036     return new SmXMLUnderOverContext_Impl(*this,nPrefix,rLocalName);
3037 }
3038 
3039 SvXMLImportContext *SmXMLImport::CreateMultiScriptsContext(sal_uInt16 nPrefix,
3040     const OUString &rLocalName,
3041     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3042 {
3043     return new SmXMLMultiScriptsContext_Impl(*this,nPrefix,rLocalName);
3044 }
3045 
3046 SvXMLImportContext *SmXMLImport::CreateTableContext(sal_uInt16 nPrefix,
3047     const OUString &rLocalName,
3048     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3049 {
3050     return new SmXMLTableContext_Impl(*this,nPrefix,rLocalName);
3051 }
3052 SvXMLImportContext *SmXMLImport::CreateTableRowContext(sal_uInt16 nPrefix,
3053     const OUString &rLocalName,
3054     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3055 {
3056     return new SmXMLTableRowContext_Impl(*this,nPrefix,rLocalName);
3057 }
3058 SvXMLImportContext *SmXMLImport::CreateTableCellContext(sal_uInt16 nPrefix,
3059     const OUString &rLocalName,
3060     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3061 {
3062     return new SmXMLTableCellContext_Impl(*this,nPrefix,rLocalName);
3063 }
3064 
3065 SvXMLImportContext *SmXMLImport::CreateNoneContext(sal_uInt16 nPrefix,
3066     const OUString &rLocalName,
3067     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3068 {
3069     return new SmXMLNoneContext_Impl(*this,nPrefix,rLocalName);
3070 }
3071 
3072 SvXMLImportContext *SmXMLImport::CreatePrescriptsContext(sal_uInt16 nPrefix,
3073     const OUString &rLocalName,
3074     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3075 {
3076     return new SmXMLPrescriptsContext_Impl(*this,nPrefix,rLocalName);
3077 }
3078 
3079 SvXMLImportContext *SmXMLImport::CreateAlignGroupContext(sal_uInt16 nPrefix,
3080     const OUString &rLocalName,
3081     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3082 {
3083     return new SmXMLAlignGroupContext_Impl(*this,nPrefix,rLocalName);
3084 }
3085 
3086 SvXMLImportContext *SmXMLImport::CreateActionContext(sal_uInt16 nPrefix,
3087     const OUString &rLocalName,
3088     const uno::Reference <xml::sax::XAttributeList> & /*xAttrList*/)
3089 {
3090     return new SmXMLActionContext_Impl(*this,nPrefix,rLocalName);
3091 }
3092 
3093 SmXMLImport::~SmXMLImport() throw ()
3094 {
3095     delete pPresLayoutElemTokenMap;
3096     delete pPresElemTokenMap;
3097     delete pPresScriptEmptyElemTokenMap;
3098     delete pPresTableElemTokenMap;
3099     delete pPresLayoutAttrTokenMap;
3100     delete pFencedAttrTokenMap;
3101     delete pColorTokenMap;
3102     delete pOperatorAttrTokenMap;
3103     delete pAnnotationAttrTokenMap;
3104 }
3105 
3106 void SmXMLImport::SetViewSettings(const Sequence<PropertyValue>& aViewProps)
3107 {
3108     uno::Reference <frame::XModel> xModel = GetModel();
3109     if ( !xModel.is() )
3110         return;
3111 
3112     uno::Reference <lang::XUnoTunnel> xTunnel;
3113     xTunnel = uno::Reference <lang::XUnoTunnel> (xModel,uno::UNO_QUERY);
3114     SmModel *pModel = reinterpret_cast<SmModel *>
3115         (xTunnel->getSomething(SmModel::getUnoTunnelId()));
3116 
3117     if ( !pModel )
3118         return;
3119 
3120     SmDocShell *pDocShell =
3121         static_cast<SmDocShell*>(pModel->GetObjectShell());
3122     if ( !pDocShell )
3123         return;
3124 
3125     Rectangle aRect( pDocShell->GetVisArea() );
3126 
3127     sal_Int32 nCount = aViewProps.getLength();
3128     const PropertyValue *pValue = aViewProps.getConstArray();
3129 
3130     long nTmp = 0;
3131     //sal_Bool bShowDeletes = sal_False, bShowInserts = sal_False, bShowFooter = sal_False, bShowHeader = sal_False;
3132 
3133     for (sal_Int32 i = 0; i < nCount ; i++)
3134     {
3135         if (pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "ViewAreaTop" ) ) )
3136         {
3137             pValue->Value >>= nTmp;
3138             aRect.setY( nTmp );
3139         }
3140         else if (pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "ViewAreaLeft" ) ) )
3141         {
3142             pValue->Value >>= nTmp;
3143             aRect.setX( nTmp );
3144         }
3145         else if (pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "ViewAreaWidth" ) ) )
3146         {
3147             pValue->Value >>= nTmp;
3148             Size aSize( aRect.GetSize() );
3149             aSize.Width() = nTmp;
3150             aRect.SetSize( aSize );
3151         }
3152         else if (pValue->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "ViewAreaHeight" ) ) )
3153         {
3154             pValue->Value >>= nTmp;
3155             Size aSize( aRect.GetSize() );
3156             aSize.Height() = nTmp;
3157             aRect.SetSize( aSize );
3158         }
3159         pValue++;
3160     }
3161 
3162     pDocShell->SetVisArea ( aRect );
3163 }
3164 
3165 void SmXMLImport::SetConfigurationSettings(const Sequence<PropertyValue>& aConfProps)
3166 {
3167     uno::Reference < XPropertySet > xProps ( GetModel(), UNO_QUERY );
3168     if ( xProps.is() )
3169     {
3170         Reference < XPropertySetInfo > xInfo ( xProps->getPropertySetInfo() );
3171         if (xInfo.is() )
3172         {
3173             sal_Int32 nCount = aConfProps.getLength();
3174             const PropertyValue* pValues = aConfProps.getConstArray();
3175 
3176             const OUString sFormula ( RTL_CONSTASCII_USTRINGPARAM ( "Formula" ) );
3177             const OUString sBasicLibraries ( RTL_CONSTASCII_USTRINGPARAM ( "BasicLibraries" ) );
3178             const OUString sDialogLibraries ( RTL_CONSTASCII_USTRINGPARAM ( "DialogLibraries" ) );
3179             while ( nCount-- )
3180             {
3181                 if (pValues->Name != sFormula &&
3182                     pValues->Name != sBasicLibraries &&
3183                     pValues->Name != sDialogLibraries)
3184                 {
3185                     try
3186                     {
3187                         if ( xInfo->hasPropertyByName( pValues->Name ) )
3188                             xProps->setPropertyValue( pValues->Name, pValues->Value );
3189                     }
3190                     catch (beans::PropertyVetoException &e)
3191                     {
3192                         (void) e;
3193                         // dealing with read-only properties here. Nothing to do...
3194                     }
3195                     catch( Exception& e)
3196                     {
3197                         (void) e;
3198                         DBG_ERROR( "SmXMLImport::SetConfigurationSettings: Exception!" );
3199                     }
3200                 }
3201 
3202                 pValues++;
3203             }
3204         }
3205     }
3206 }
3207 
3208 
3209 ////////////////////////////////////////////////////////////
3210 
3211 
3212