1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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  */
9 
10 #include "celltextparacontext.hxx"
11 #include "xmlimprt.hxx"
12 #include "xmlcelli.hxx"
13 
14 #include <comphelper/string.hxx>
15 #include <xmloff/xmlnamespace.hxx>
16 #include <xmloff/xmltoken.hxx>
17 
18 using namespace com::sun::star;
19 using namespace xmloff::token;
20 
ScXMLCellTextParaContext(ScXMLImport & rImport,ScXMLTableRowCellContext & rParent)21 ScXMLCellTextParaContext::ScXMLCellTextParaContext(
22     ScXMLImport& rImport, ScXMLTableRowCellContext& rParent) :
23     ScXMLImportContext(rImport),
24     mrParentCxt(rParent)
25 {
26 }
27 
endFastElement(sal_Int32)28 void SAL_CALL ScXMLCellTextParaContext::endFastElement( sal_Int32 /*nElement*/ )
29 {
30     if (!maContent.isEmpty())
31         mrParentCxt.PushParagraphSpan(maContent, OUString());
32 
33     mrParentCxt.PushParagraphEnd();
34 }
35 
characters(const OUString & rChars)36 void SAL_CALL ScXMLCellTextParaContext::characters( const OUString& rChars )
37 {
38     maContent += rChars;
39 }
40 
createFastChildContext(sal_Int32 nElement,const uno::Reference<xml::sax::XFastAttributeList> &)41 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLCellTextParaContext::createFastChildContext(
42     sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ )
43 {
44     if (!maContent.isEmpty())
45     {
46         mrParentCxt.PushParagraphSpan(maContent, OUString());
47         maContent.clear();
48     }
49 
50     switch (nElement)
51     {
52         case XML_ELEMENT( TEXT, XML_S ):
53             return new ScXMLCellFieldSContext(GetScImport(), *this);
54         case XML_ELEMENT( TEXT, XML_SPAN ):
55             return new ScXMLCellTextSpanContext(GetScImport(), *this);
56         case XML_ELEMENT( TEXT, XML_SHEET_NAME ):
57             return new ScXMLCellFieldSheetNameContext(GetScImport(), *this);
58         case XML_ELEMENT( TEXT, XML_DATE ):
59             return new ScXMLCellFieldDateContext(GetScImport(), *this);
60         case XML_ELEMENT( TEXT, XML_TITLE ):
61             return new ScXMLCellFieldTitleContext(GetScImport(), *this);
62         case XML_ELEMENT( TEXT, XML_A ):
63             return new ScXMLCellFieldURLContext(GetScImport(), *this);
64         case XML_ELEMENT( TEXT, XML_RUBY ):
65             return new ScXMLCellTextRubyContext(GetScImport(), *this);
66         case XML_ELEMENT(TEXT, XML_TAB):
67             maContent += "\t";
68             break;
69         case XML_ELEMENT(TEXT, XML_LINE_BREAK):
70             maContent += "\x0a";
71             break;
72         case XML_ELEMENT(TEXT, XML_BOOKMARK):
73         case XML_ELEMENT(TEXT, XML_BOOKMARK_START):
74         case XML_ELEMENT(TEXT, XML_BOOKMARK_END):
75             // TODO: ooo95423-1 [file.ods] and tdf#116079-3 have these bookmarks.
76             // Is this valid, and how can we prevent losing these?
77             break;
78         default:
79             SAL_WARN("sc","unknown text element["<<nElement<<"]["<<SvXMLImport::getNameFromToken(nElement )<<"] lost");
80     }
81 
82     return nullptr;
83 }
84 
PushSpan(std::u16string_view aSpan,const OUString & rStyleName)85 void ScXMLCellTextParaContext::PushSpan(std::u16string_view aSpan, const OUString& rStyleName)
86 {
87     mrParentCxt.PushParagraphSpan(aSpan, rStyleName);
88 }
89 
PushFieldSheetName(const OUString & rStyleName)90 void ScXMLCellTextParaContext::PushFieldSheetName(const OUString& rStyleName)
91 {
92     mrParentCxt.PushParagraphFieldSheetName(rStyleName);
93 }
94 
PushFieldDate(const OUString & rStyleName)95 void ScXMLCellTextParaContext::PushFieldDate(const OUString& rStyleName)
96 {
97     mrParentCxt.PushParagraphFieldDate(rStyleName);
98 }
99 
PushFieldTitle(const OUString & rStyleName)100 void ScXMLCellTextParaContext::PushFieldTitle(const OUString& rStyleName)
101 {
102     mrParentCxt.PushParagraphFieldDocTitle(rStyleName);
103 }
104 
PushFieldURL(const OUString & rURL,const OUString & rRep,const OUString & rStyleName,const OUString & rTargetFrame)105 void ScXMLCellTextParaContext::PushFieldURL(
106     const OUString& rURL, const OUString& rRep, const OUString& rStyleName, const OUString& rTargetFrame)
107 {
108     mrParentCxt.PushParagraphFieldURL(rURL, rRep, rStyleName, rTargetFrame);
109 }
110 
ScXMLCellTextSpanContext(ScXMLImport & rImport,ScXMLCellTextParaContext & rParent)111 ScXMLCellTextSpanContext::ScXMLCellTextSpanContext(
112     ScXMLImport& rImport, ScXMLCellTextParaContext& rParent) :
113     ScXMLImportContext(rImport),
114     mrParentCxt(rParent)
115 {
116 }
117 
startFastElement(sal_Int32,const uno::Reference<xml::sax::XFastAttributeList> & xAttrList)118 void SAL_CALL ScXMLCellTextSpanContext::startFastElement( sal_Int32 /*nElement*/,
119     const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
120 {
121     for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
122     {
123         switch (aIter.getToken())
124         {
125             case XML_ELEMENT( TEXT, XML_STYLE_NAME ):
126                 maStyleName = aIter.toString();
127             break;
128             default:
129                 ;
130         }
131     }
132 }
133 
endFastElement(sal_Int32)134 void SAL_CALL ScXMLCellTextSpanContext::endFastElement( sal_Int32 /*nElement*/ )
135 {
136     submitContentAndClear();
137 }
138 
characters(const OUString & rChars)139 void SAL_CALL ScXMLCellTextSpanContext::characters( const OUString& rChars )
140 {
141     maContent += rChars;
142 }
143 
createFastChildContext(sal_Int32 nElement,const uno::Reference<xml::sax::XFastAttributeList> &)144 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLCellTextSpanContext::createFastChildContext(
145     sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ )
146 {
147     submitContentAndClear();
148 
149     switch (nElement)
150     {
151         case XML_ELEMENT( TEXT, XML_SHEET_NAME ):
152         {
153             ScXMLCellFieldSheetNameContext* p = new ScXMLCellFieldSheetNameContext(GetScImport(), mrParentCxt);
154             p->SetStyleName(maStyleName);
155             return p;
156         }
157         case XML_ELEMENT( TEXT, XML_DATE ):
158         {
159             ScXMLCellFieldDateContext* p = new ScXMLCellFieldDateContext(GetScImport(), mrParentCxt);
160             p->SetStyleName(maStyleName);
161             return p;
162         }
163         case XML_ELEMENT( TEXT, XML_TITLE ):
164         {
165             ScXMLCellFieldTitleContext* p = new ScXMLCellFieldTitleContext(GetScImport(), mrParentCxt);
166             p->SetStyleName(maStyleName);
167             return p;
168         }
169         case XML_ELEMENT( TEXT, XML_A ):
170         {
171             ScXMLCellFieldURLContext* p = new ScXMLCellFieldURLContext(GetScImport(), mrParentCxt);
172             p->SetStyleName(maStyleName);
173             return p;
174         }
175         case XML_ELEMENT( TEXT, XML_S ):
176         {
177             ScXMLCellFieldSContext* p = new ScXMLCellFieldSContext(GetScImport(), mrParentCxt);
178             p->SetStyleName(maStyleName);
179             return p;
180         }
181         default:
182             ;
183     }
184 
185     return nullptr;
186 }
187 
submitContentAndClear()188 void ScXMLCellTextSpanContext::submitContentAndClear()
189 {
190     if (!maContent.isEmpty())
191     {
192         mrParentCxt.PushSpan(maContent, maStyleName);
193         maContent.clear();
194     }
195 }
196 
ScXMLCellFieldSheetNameContext(ScXMLImport & rImport,ScXMLCellTextParaContext & rParent)197 ScXMLCellFieldSheetNameContext::ScXMLCellFieldSheetNameContext(
198     ScXMLImport& rImport, ScXMLCellTextParaContext& rParent) :
199     ScXMLImportContext(rImport),
200     mrParentCxt(rParent)
201 {
202 }
203 
SetStyleName(const OUString & rStyleName)204 void ScXMLCellFieldSheetNameContext::SetStyleName(const OUString& rStyleName)
205 {
206     maStyleName = rStyleName;
207 }
208 
endFastElement(sal_Int32)209 void SAL_CALL ScXMLCellFieldSheetNameContext::endFastElement( sal_Int32 /*nElement*/ )
210 {
211     mrParentCxt.PushFieldSheetName(maStyleName);
212 }
213 
ScXMLCellFieldDateContext(ScXMLImport & rImport,ScXMLCellTextParaContext & rParent)214 ScXMLCellFieldDateContext::ScXMLCellFieldDateContext(
215     ScXMLImport& rImport, ScXMLCellTextParaContext& rParent) :
216     ScXMLImportContext(rImport),
217     mrParentCxt(rParent)
218 {
219 }
220 
SetStyleName(const OUString & rStyleName)221 void ScXMLCellFieldDateContext::SetStyleName(const OUString& rStyleName)
222 {
223     maStyleName = rStyleName;
224 }
225 
endFastElement(sal_Int32)226 void SAL_CALL ScXMLCellFieldDateContext::endFastElement( sal_Int32 /*nElement*/ )
227 {
228     mrParentCxt.PushFieldDate(maStyleName);
229 }
230 
ScXMLCellFieldTitleContext(ScXMLImport & rImport,ScXMLCellTextParaContext & rParent)231 ScXMLCellFieldTitleContext::ScXMLCellFieldTitleContext(
232     ScXMLImport& rImport, ScXMLCellTextParaContext& rParent) :
233     ScXMLImportContext(rImport),
234     mrParentCxt(rParent)
235 {
236 }
237 
SetStyleName(const OUString & rStyleName)238 void ScXMLCellFieldTitleContext::SetStyleName(const OUString& rStyleName)
239 {
240     maStyleName = rStyleName;
241 }
242 
endFastElement(sal_Int32)243 void SAL_CALL ScXMLCellFieldTitleContext::endFastElement( sal_Int32 /*nElement*/ )
244 {
245     mrParentCxt.PushFieldTitle(maStyleName);
246 }
247 
ScXMLCellFieldURLContext(ScXMLImport & rImport,ScXMLCellTextParaContext & rParent)248 ScXMLCellFieldURLContext::ScXMLCellFieldURLContext(
249     ScXMLImport& rImport, ScXMLCellTextParaContext& rParent) :
250     ScXMLImportContext(rImport),
251     mrParentCxt(rParent)
252 {
253 }
254 
SetStyleName(const OUString & rStyleName)255 void ScXMLCellFieldURLContext::SetStyleName(const OUString& rStyleName)
256 {
257     maStyleName = rStyleName;
258 }
259 
startFastElement(sal_Int32,const uno::Reference<xml::sax::XFastAttributeList> & xAttrList)260 void SAL_CALL ScXMLCellFieldURLContext::startFastElement( sal_Int32 /*nElement*/,
261     const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
262 {
263     for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
264     {
265         switch (aIter.getToken())
266         {
267             case XML_ELEMENT( XLINK, XML_HREF ):
268                 maURL = aIter.toString();
269             break;
270             case XML_ELEMENT( XLINK, XML_TYPE ):
271                 // Ignored for now.
272             break;
273             case XML_ELEMENT( OFFICE, XML_TARGET_FRAME_NAME ):
274                 maTargetFrame = aIter.toString();
275             break;
276             default:
277                 ;
278         }
279     }
280 }
281 
endFastElement(sal_Int32)282 void SAL_CALL ScXMLCellFieldURLContext::endFastElement( sal_Int32 /*nElement*/ )
283 {
284     mrParentCxt.PushFieldURL(maURL, maRep, maStyleName, maTargetFrame);
285 }
286 
characters(const OUString & rChars)287 void SAL_CALL ScXMLCellFieldURLContext::characters( const OUString& rChars )
288 {
289     maRep += rChars;
290 }
291 
ScXMLCellFieldSContext(ScXMLImport & rImport,ScXMLCellTextParaContext & rParent)292 ScXMLCellFieldSContext::ScXMLCellFieldSContext(
293     ScXMLImport& rImport, ScXMLCellTextParaContext& rParent) :
294     ScXMLImportContext(rImport),
295     mrParentCxt(rParent),
296     mnCount(1)
297 {
298 }
299 
SetStyleName(const OUString & rStyleName)300 void ScXMLCellFieldSContext::SetStyleName(const OUString& rStyleName)
301 {
302     maStyleName = rStyleName;
303 }
304 
startFastElement(sal_Int32,const uno::Reference<xml::sax::XFastAttributeList> & xAttrList)305 void SAL_CALL ScXMLCellFieldSContext::startFastElement( sal_Int32 /*nElement*/,
306     const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
307 {
308     for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
309     {
310         switch (aIter.getToken())
311         {
312             case XML_ELEMENT( TEXT, XML_C ):
313                 mnCount = aIter.toInt32();
314                 if (mnCount <= 0)
315                     mnCount = 1;     // worth a warning?
316             break;
317             default:
318                 ;
319         }
320     }
321 }
322 
endFastElement(sal_Int32)323 void SAL_CALL ScXMLCellFieldSContext::endFastElement( sal_Int32 /*nElement*/ )
324 {
325     if (mnCount)
326         PushSpaces();
327 }
328 
createFastChildContext(sal_Int32,const uno::Reference<xml::sax::XFastAttributeList> &)329 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLCellFieldSContext::createFastChildContext(
330     sal_Int32 /*nElement*/, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ )
331 {
332     // <text:s> does not have child elements, but ...
333     if (mnCount)
334     {
335         PushSpaces();
336         mnCount = 0;
337     }
338 
339     return nullptr;
340 }
341 
PushSpaces()342 void ScXMLCellFieldSContext::PushSpaces()
343 {
344     if (mnCount > 0)
345     {
346         if (mnCount == 1)
347             mrParentCxt.PushSpan(u" ", maStyleName);
348         else
349         {
350             OUStringBuffer aBuf( mnCount);
351             comphelper::string::padToLength( aBuf, mnCount, ' ');
352             mrParentCxt.PushSpan( aBuf.makeStringAndClear(), maStyleName);
353         }
354     }
355 }
356 
ScXMLCellTextRubyContext(ScXMLImport & rImport,ScXMLCellTextParaContext & rParent)357 ScXMLCellTextRubyContext::ScXMLCellTextRubyContext(
358     ScXMLImport& rImport, ScXMLCellTextParaContext& rParent) :
359     ScXMLImportContext(rImport),
360     mrParentCxt(rParent)
361 {
362 }
363 
startFastElement(sal_Int32,const uno::Reference<xml::sax::XFastAttributeList> & xAttrList)364 void SAL_CALL ScXMLCellTextRubyContext::startFastElement( sal_Int32 /*nElement*/,
365     const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
366 {
367     for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
368     {
369         switch (aIter.getToken())
370         {
371             case XML_ELEMENT( TEXT, XML_STYLE_NAME ):
372                 // This is ruby style instead of text style.
373             break;
374             default:
375                 ;
376         }
377     }
378 }
379 
createFastChildContext(sal_Int32 nElement,const uno::Reference<xml::sax::XFastAttributeList> &)380 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLCellTextRubyContext::createFastChildContext(
381     sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ )
382 {
383 
384     switch (nElement)
385     {
386         case XML_ELEMENT( TEXT, XML_RUBY_BASE ):
387         {
388             ScXMLCellRubyBaseContext* p = new ScXMLCellRubyBaseContext(GetScImport(), mrParentCxt);
389             return p;
390         }
391         case XML_ELEMENT( TEXT, XML_RUBY_TEXT ):
392         {
393             ScXMLCellRubyTextContext* p = new ScXMLCellRubyTextContext(GetScImport(), maRubyText, maRubyTextStyle);
394             return p;
395         }
396         default:
397             ;
398     }
399 
400     return nullptr;
401 }
402 
ScXMLCellRubyBaseContext(ScXMLImport & rImport,ScXMLCellTextParaContext & rParent)403 ScXMLCellRubyBaseContext::ScXMLCellRubyBaseContext(
404     ScXMLImport& rImport, ScXMLCellTextParaContext& rParent) :
405     ScXMLCellTextSpanContext( rImport, rParent),
406     mrParentCxt(rParent)
407 {
408 }
409 
createFastChildContext(sal_Int32 nElement,const uno::Reference<xml::sax::XFastAttributeList> &)410 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLCellRubyBaseContext::createFastChildContext(
411     sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ )
412 {
413     submitContentAndClear();
414 
415     switch (nElement)
416     {
417         case XML_ELEMENT( TEXT, XML_SPAN ):
418             return new ScXMLCellTextSpanContext(GetScImport(), mrParentCxt);
419         default:
420             ;
421     }
422     return nullptr;
423 }
424 
ScXMLCellRubyTextContext(ScXMLImport & rImport,OUString & rRubyText,OUString & rRubyTextStyle)425 ScXMLCellRubyTextContext::ScXMLCellRubyTextContext(
426     ScXMLImport& rImport, OUString& rRubyText, OUString& rRubyTextStyle) :
427     ScXMLImportContext(rImport),
428     mrRubyText(rRubyText),
429     mrRubyTextStyle(rRubyTextStyle)
430 {
431 }
432 
startFastElement(sal_Int32,const uno::Reference<xml::sax::XFastAttributeList> & xAttrList)433 void SAL_CALL ScXMLCellRubyTextContext::startFastElement( sal_Int32 /*nElement*/,
434     const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
435 {
436     for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
437     {
438         switch (aIter.getToken())
439         {
440             case XML_ELEMENT( TEXT, XML_STYLE_NAME ):
441                 mrRubyTextStyle = aIter.toString();
442             break;
443             default:
444                 ;
445         }
446     }
447 }
448 
characters(const OUString & rChars)449 void SAL_CALL ScXMLCellRubyTextContext::characters( const OUString& rChars )
450 {
451     mrRubyText+= rChars;
452 }
453 
454 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
455