tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / oox / source / mathml / importutils.cxx
blob4f6c243b9970267a2748a98701e6636f4cfa6cd6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <oox/mathml/importutils.hxx>
12 #include <assert.h>
14 #include <com/sun/star/xml/FastAttribute.hpp>
15 #include <com/sun/star/xml/sax/XFastAttributeList.hpp>
16 #include <oox/token/tokenmap.hxx>
17 #include <oox/token/tokens.hxx>
18 #include <oox/token/namespaces.hxx>
19 #include <rtl/ustring.hxx>
20 #include <sal/log.hxx>
21 #include <utility>
23 #define OPENING( token ) XML_STREAM_OPENING( token )
24 #define CLOSING( token ) XML_STREAM_CLOSING( token )
26 using namespace com::sun::star;
28 namespace oox::formulaimport
31 namespace
33 // a class that inherits from AttributeList, builds the internal data and then will be sliced off
34 // during conversion to the base class
35 class AttributeListBuilder
36 : public XmlStream::AttributeList
38 public:
39 explicit AttributeListBuilder( const uno::Reference< xml::sax::XFastAttributeList >& a );
42 AttributeListBuilder::AttributeListBuilder( const uno::Reference< xml::sax::XFastAttributeList >& a )
44 if( !a )
45 return;
46 const uno::Sequence< xml::FastAttribute > aFastAttrSeq = a->getFastAttributes();
47 for( const xml::FastAttribute& rFastAttr : aFastAttrSeq )
49 attrs[ rFastAttr.Token ] = rFastAttr.Value;
53 OString tokenToString( int token )
55 uno::Sequence<sal_Int8> const& aTokenNameSeq = TokenMap::getUtf8TokenName(token & TOKEN_MASK);
56 OString tokenname( reinterpret_cast< const char* >( aTokenNameSeq.getConstArray() ), aTokenNameSeq.getLength() );
57 if( tokenname.isEmpty())
58 tokenname = "???"_ostr;
59 int nmsp = ( token & NMSP_MASK & ~( TAG_OPENING | TAG_CLOSING ));
60 #if 0 // this is awfully long
61 OString namespacename = StaticNamespaceMap::get().count( nmsp ) != 0
62 ? StaticNamespaceMap::get()[ nmsp ] : OString( "???" );
63 #else
64 OString namespacename;
65 // only few are needed actually
66 switch( nmsp )
68 case NMSP_officeMath:
69 namespacename = "m"_ostr;
70 break;
71 case NMSP_doc:
72 namespacename = "w"_ostr;
73 break;
74 default:
75 namespacename = "?"_ostr;
76 break;
78 #endif
79 if( token == OPENING( token ))
80 return "<" + namespacename + ":" + tokenname + ">";
81 if( token == CLOSING( token ))
82 return "</" + namespacename + ":" + tokenname + ">";
83 // just the name itself, not specified whether opening or closing
84 return namespacename + ":" + tokenname;
87 } // namespace
89 OUString& XmlStream::AttributeList::operator[] (int token)
91 return attrs[token];
94 OUString XmlStream::AttributeList::attribute( int token, const OUString& def ) const
96 std::map< int, OUString >::const_iterator find = attrs.find( token );
97 if( find != attrs.end())
98 return find->second;
99 return def;
102 bool XmlStream::AttributeList::attribute( int token, bool def ) const
104 std::map< int, OUString >::const_iterator find = attrs.find( token );
105 if( find != attrs.end())
107 const OUString sValue = find->second;
108 if( sValue.equalsIgnoreAsciiCase("true") ||
109 sValue.equalsIgnoreAsciiCase("on") ||
110 sValue.equalsIgnoreAsciiCase("t") ||
111 sValue.equalsIgnoreAsciiCase("1") )
112 return true;
113 if( sValue.equalsIgnoreAsciiCase("false") ||
114 sValue.equalsIgnoreAsciiCase("off") ||
115 sValue.equalsIgnoreAsciiCase("f") ||
116 sValue.equalsIgnoreAsciiCase("0") )
117 return false;
118 SAL_WARN( "oox.xmlstream", "Cannot convert \'" << sValue << "\' to bool." );
120 return def;
123 sal_Unicode XmlStream::AttributeList::attribute( int token, sal_Unicode def ) const
125 std::map< int, OUString >::const_iterator find = attrs.find( token );
126 if( find != attrs.end())
128 if( !find->second.isEmpty() )
130 if( find->second.getLength() != 1 )
131 SAL_WARN( "oox.xmlstream", "Cannot convert \'" << find->second << "\' to sal_Unicode, stripping." );
132 return find->second[ 0 ];
135 return def;
138 XmlStream::Tag::Tag( int t, const uno::Reference< xml::sax::XFastAttributeList >& a )
139 : token( t )
140 , attributes( AttributeListBuilder( a ))
144 XmlStream::Tag::Tag( int t, AttributeList a )
145 : token( t )
146 , attributes(std::move( a ))
150 XmlStream::Tag::operator bool() const
152 return token != XML_TOKEN_INVALID;
155 XmlStream::XmlStream()
156 : pos( 0 )
158 // make sure our extra bit does not conflict with values used by oox
159 assert( TAG_OPENING > ( 1024 << NMSP_SHIFT ));
162 bool XmlStream::atEnd() const
164 return pos >= tags.size();
167 XmlStream::Tag XmlStream::currentTag() const
169 if( pos >= tags.size())
170 return Tag();
171 return tags[ pos ];
174 int XmlStream::currentToken() const
176 if( pos >= tags.size())
177 return XML_TOKEN_INVALID;
178 return tags[ pos ].token;
181 void XmlStream::moveToNextTag()
183 if( pos < tags.size())
184 ++pos;
187 XmlStream::Tag XmlStream::ensureOpeningTag( int token )
189 return checkTag( OPENING( token ), false );
192 XmlStream::Tag XmlStream::checkOpeningTag( int token )
194 return checkTag( OPENING( token ), true );
197 void XmlStream::ensureClosingTag( int token )
199 checkTag( CLOSING( token ), false );
202 XmlStream::Tag XmlStream::checkTag( int token, bool optional )
204 // either it's the following tag, or find it
205 int savedPos = pos;
206 if( optional )
207 { // avoid printing debug messages about skipping tags if the optional one
208 // will not be found and the position will be reset back
209 if( currentToken() != token && !findTagInternal( token, true ))
211 pos = savedPos;
212 return Tag();
215 if( currentToken() == token || findTag( token ))
217 Tag ret = currentTag();
218 moveToNextTag();
219 return ret; // ok
221 if( optional )
222 { // not a problem, just rewind
223 pos = savedPos;
224 return Tag();
226 SAL_WARN( "oox.xmlstream", "Expected tag " << tokenToString( token ) << " not found." );
227 return Tag();
230 bool XmlStream::findTag( int token )
232 return findTagInternal( token, false );
235 bool XmlStream::findTagInternal( int token, bool silent )
237 int depth = 0;
238 for(;
239 !atEnd();
240 moveToNextTag())
242 if( depth > 0 ) // we're inside a nested element, skip those
244 if( currentToken() == OPENING( currentToken()))
246 if( !silent )
247 SAL_INFO( "oox.xmlstream", "Skipping tag " << tokenToString( currentToken()));
248 ++depth;
250 else if( currentToken() == CLOSING( currentToken()))
252 if( !silent )
253 SAL_INFO( "oox.xmlstream", "Skipping tag " << tokenToString( currentToken()));
254 --depth;
256 else
258 if( !silent )
259 SAL_WARN( "oox.xmlstream", "Malformed token " << currentToken() << " ("
260 << tokenToString( currentToken()) << ")" );
261 abort();
263 continue;
265 if( currentToken() == token )
266 return true; // ok, found
267 if( currentToken() == CLOSING( currentToken()))
268 return false; // that would be leaving current element, so not found
269 if( currentToken() == OPENING( currentToken()))
271 if( !silent )
272 SAL_INFO( "oox.xmlstream", "Skipping tag " << tokenToString( currentToken()));
273 ++depth;
275 else
276 abort();
278 if( !silent )
279 SAL_WARN( "oox.xmlstream", "Unexpected end of stream reached." );
280 return false;
283 void XmlStream::skipElementInternal( int token, bool silent )
285 int closing = ( token & ~TAG_OPENING ) | TAG_CLOSING; // make it a closing tag
286 assert( currentToken() == OPENING( token ));
287 if( !silent )
288 SAL_INFO( "oox.xmlstream", "Skipping unexpected element " << tokenToString( currentToken()));
289 moveToNextTag();
290 // and just find the matching closing tag
291 if( findTag( closing ))
293 if( !silent )
294 SAL_INFO( "oox.xmlstream", "Skipped unexpected element " << tokenToString( token ));
295 moveToNextTag(); // and skip it too
296 return;
298 // this one is an unexpected problem, do not silent it
299 SAL_WARN( "oox.xmlstream", "Expected end of element " << tokenToString( token ) << " not found." );
302 void XmlStream::handleUnexpectedTag()
304 if( atEnd())
305 return;
306 if( currentToken() == CLOSING( currentToken()))
308 SAL_INFO( "oox.xmlstream", "Skipping unexpected tag " << tokenToString( currentToken()));
309 moveToNextTag(); // just skip it
310 return;
312 skipElementInternal( currentToken(), false ); // otherwise skip the entire element
315 void XmlStreamBuilder::appendOpeningTag( int token, const uno::Reference< xml::sax::XFastAttributeList >& attrs )
317 tags.emplace_back( OPENING( token ), attrs );
320 void XmlStreamBuilder::appendOpeningTag( int token, const AttributeList& attrs )
322 tags.emplace_back( OPENING( token ), attrs );
325 void XmlStreamBuilder::appendClosingTag( int token )
327 tags.emplace_back( CLOSING( token ));
330 void XmlStreamBuilder::appendCharacters( std::u16string_view chars )
332 assert( !tags.empty());
333 tags.back().text += chars;
336 } // namespace
338 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */