1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /*
3 * This file is part of the libetonyek 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 "PAG1TextStorageElement.h"
11
12 #include <cassert>
13 #include <string>
14
15 #include <boost/optional.hpp>
16
17 #include <librevenge/librevenge.h>
18
19 #include "IWORKGroupElement.h"
20 #include "IWORKLayoutElement.h"
21 #include "IWORKLinkElement.h"
22 #include "IWORKMediaElement.h"
23 #include "IWORKPElement.h"
24 #include "IWORKPositionElement.h"
25 #include "IWORKRefContext.h"
26 #include "IWORKSizeElement.h"
27 #include "IWORKShapeContext.h"
28 #include "IWORKSpanElement.h"
29 #include "IWORKTabularInfoElement.h"
30 #include "IWORKText.h"
31 #include "IWORKTextBodyElement.h"
32 #include "IWORKToken.h"
33 #include "PAG1AnnotationElement.h"
34 #include "PAG1Dictionary.h"
35 #include "PAG1FootnotesElement.h"
36 #include "PAG1ParserState.h"
37 #include "PAGCollector.h"
38 #include "libetonyek_xml.h"
39
40 namespace libetonyek
41 {
42
43 using boost::optional;
44
45 using std::string;
46
47 namespace
48 {
49
50 struct ContainerFrame
51 {
52 ContainerFrame();
53
54 optional<double> m_w;
55 optional<double> m_h;
56 optional<double> m_x;
57 optional<double> m_y;
58 };
59
ContainerFrame()60 ContainerFrame::ContainerFrame()
61 : m_w()
62 , m_h()
63 , m_x()
64 , m_y()
65 {
66 }
67
68 }
69
70 namespace
71 {
72
73 class AttachmentElement : public PAG1XMLElementContextBase
74 {
75 public:
76 explicit AttachmentElement(PAG1ParserState &state);
77
78 private:
79 void attribute(int name, const char *value) override;
80 void startOfElement() override;
81 IWORKXMLContextPtr_t element(int name) override;
82 void endOfElement() override;
83
84 private:
85 bool m_known;
86 bool m_block;
87 optional<IWORKPosition> m_position;
88 optional<IWORKSize> m_originalSize;
89 std::shared_ptr<IWORKText> m_savedText;
90 };
91
AttachmentElement(PAG1ParserState & state)92 AttachmentElement::AttachmentElement(PAG1ParserState &state)
93 : PAG1XMLElementContextBase(state)
94 , m_known(false)
95 , m_block(false)
96 , m_position()
97 , m_originalSize()
98 , m_savedText()
99 {
100 }
101
attribute(const int name,const char * const value)102 void AttachmentElement::attribute(const int name, const char *const value)
103 {
104 switch (name)
105 {
106 case IWORKToken::NS_URI_SFA | IWORKToken::sfclass :
107 case IWORKToken::NS_URI_SF | IWORKToken::kind :
108 break;
109 case IWORKToken::NS_URI_SFA | IWORKToken::ID :
110 return PAG1XMLElementContextBase::attribute(name, value);
111 default:
112 ETONYEK_DEBUG_MSG(("AttachmentElement::attribute[PAG1TextStorageElement]: find some unknown attribute\n"));
113 break;
114 }
115 }
116
startOfElement()117 void AttachmentElement::startOfElement()
118 {
119 // saved the current zone of text
120 m_savedText=getState().m_currentText;
121 getState().m_currentText.reset();
122
123 if (isCollector())
124 getCollector().startAttachment();
125 }
126
element(const int name)127 IWORKXMLContextPtr_t AttachmentElement::element(const int name)
128 {
129 IWORKXMLContextPtr_t context;
130
131 switch (name)
132 {
133 case IWORKToken::NS_URI_SF | IWORKToken::drawable_shape :
134 {
135 m_block = false;
136 context = std::make_shared<IWORKShapeContext>(getState());
137 break;
138 }
139 case IWORKToken::NS_URI_SF | IWORKToken::group :
140 {
141 static bool first=true;
142 if (first)
143 {
144 ETONYEK_DEBUG_MSG(("AttachmentElement::attribute[PAG1TextStorageElement]: find some groups attached in textbox, not implemented\n"));
145 first=false;
146 }
147 //m_block = true;
148 //context = std::make_shared<IWORKGroupElement>(getState());
149 break;
150 }
151 case IWORKToken::NS_URI_SF | IWORKToken::media :
152 m_block = false;
153 context = std::make_shared<IWORKMediaElement>(getState());
154 break;
155 case IWORKToken::NS_URI_SF | IWORKToken::original_size :
156 return std::make_shared<IWORKSizeElement>(getState(), m_originalSize);
157 case IWORKToken::NS_URI_SF | IWORKToken::position :
158 return std::make_shared<IWORKPositionElement>(getState(), m_position);
159 case IWORKToken::NS_URI_SF | IWORKToken::tabular_info :
160 m_block = true;
161 context = std::make_shared<IWORKTabularInfoElement>(getState());
162 break;
163 default:
164 ETONYEK_DEBUG_MSG(("AttachmentElement::element[PAG1TextStorageElement]: find some unknown element\n"));
165 }
166
167 if (bool(context))
168 {
169 m_known = true;
170 if (isCollector())
171 getCollector().getOutputManager().push();
172 }
173
174 return context;
175 }
176
endOfElement()177 void AttachmentElement::endOfElement()
178 {
179 if (isCollector())
180 {
181 if (m_known)
182 {
183 if (m_position)
184 getCollector().collectAttachmentPosition(get(m_position));
185 if (getId())
186 getState().getDictionary().m_attachments[get(getId())] = PAGAttachment(getCollector().getOutputManager().save(), m_block);
187 getCollector().getOutputManager().pop();
188 }
189 getCollector().endAttachment();
190 }
191 // reset the current zone of text
192 getState().m_currentText=m_savedText;
193 }
194
195 }
196
197 namespace
198 {
199
200 class AttachmentsElement : public PAG1XMLElementContextBase
201 {
202 public:
203 explicit AttachmentsElement(PAG1ParserState &state);
204
205 private:
206 void startOfElement() override;
207 IWORKXMLContextPtr_t element(int name) override;
208 void endOfElement() override;
209 };
210
AttachmentsElement(PAG1ParserState & state)211 AttachmentsElement::AttachmentsElement(PAG1ParserState &state)
212 : PAG1XMLElementContextBase(state)
213 {
214 }
215
startOfElement()216 void AttachmentsElement::startOfElement()
217 {
218 if (isCollector())
219 getCollector().startAttachments();
220 }
221
element(const int name)222 IWORKXMLContextPtr_t AttachmentsElement::element(const int name)
223 {
224 if (name == (IWORKToken::NS_URI_SF | IWORKToken::attachment))
225 return std::make_shared<AttachmentElement>(getState());
226 return IWORKXMLContextPtr_t();
227 }
228
endOfElement()229 void AttachmentsElement::endOfElement()
230 {
231 if (isCollector())
232 getCollector().endAttachments();
233 }
234
235 }
236
237 namespace
238 {
239 class AttachmentRef : public PAG1XMLElementContextBase
240 {
241 public:
242 explicit AttachmentRef(PAG1ParserState &state);
243
244 private:
245 void attribute(const int name, const char *const value) override;
246 IWORKXMLContextPtr_t element(int name) override;
247 void endOfElement() override;
248
249 boost::optional<ID_t> m_ref;
250 boost::optional<std::string> m_kind;
251 };
252
AttachmentRef(PAG1ParserState & state)253 AttachmentRef::AttachmentRef(PAG1ParserState &state)
254 : PAG1XMLElementContextBase(state)
255 , m_ref()
256 , m_kind()
257 {
258 }
259
attribute(const int name,const char * const value)260 void AttachmentRef::attribute(const int name, const char *const value)
261 {
262 switch (name)
263 {
264 case IWORKToken::NS_URI_SFA | IWORKToken::IDREF :
265 m_ref = value;
266 break;
267 case IWORKToken::NS_URI_SF | IWORKToken::kind :
268 m_kind = value;
269 break;
270 default:
271 ETONYEK_DEBUG_MSG(("AttachmentRef::attribute[PAG1TextStorageElement]: find unexpected attribute\n"));
272 }
273 }
274
element(int)275 IWORKXMLContextPtr_t AttachmentRef::element(int /*name*/)
276 {
277 ETONYEK_DEBUG_MSG(("AttachmentRef::element[PAG1TextStorageElement]: find unexpected element\n"));
278 return IWORKXMLContextPtr_t();
279 }
280
endOfElement()281 void AttachmentRef::endOfElement()
282 {
283 if (!isCollector())
284 return;
285 if (!m_ref)
286 {
287 ETONYEK_DEBUG_MSG(("AttachmentRef::endOfElement[PAG1TextStorageElement]: called without ref\n"));
288 return;
289 }
290 if (!getState().m_currentText)
291 {
292 ETONYEK_DEBUG_MSG(("AttachmentRef::endOfElement[PAG1TextStorageElement]: can not find attachment current text\n"));
293 return;
294 }
295
296 const PAGAttachmentMap_t::const_iterator it = getState().getDictionary().m_attachments.find(get(m_ref));
297 if (it != getState().getDictionary().m_attachments.end())
298 {
299 const IWORKOutputElements &content = getCollector().getOutputManager().get(it->second.m_id);
300 if (it->second.m_block)
301 getState().m_currentText->insertBlockContent(content);
302 else
303 getState().m_currentText->insertInlineContent(content);
304 }
305 else
306 {
307 ETONYEK_DEBUG_MSG(("AttachmentRef::endOfElement[PAG1TextStorageElement]: can not find attachment %s\n", get(m_ref).c_str()));
308 }
309 }
310
311 }
312
313 namespace
314 {
315
316 class FootnoteElement : public PAG1XMLEmptyContextBase
317 {
318 public:
319 explicit FootnoteElement(PAG1ParserState &state);
320
321 private:
322 void endOfElement() override;
323 };
324
FootnoteElement(PAG1ParserState & state)325 FootnoteElement::FootnoteElement(PAG1ParserState &state)
326 : PAG1XMLEmptyContextBase(state)
327 {
328 }
329
endOfElement()330 void FootnoteElement::endOfElement()
331 {
332 if (getState().m_footnoteState.m_nextFootnote != getState().m_footnoteState.m_footnotes.end())
333 {
334 if (bool(getState().m_currentText))
335 getState().m_currentText->insertInlineContent(*getState().m_footnoteState.m_nextFootnote);
336 ++getState().m_footnoteState.m_nextFootnote;
337 }
338 }
339
340 }
341
342 namespace
343 {
344
345 class FootnotebrElement : public PAG1XMLEmptyContextBase
346 {
347 public:
348 explicit FootnotebrElement(PAG1ParserState &state);
349
350 private:
351 void endOfElement() override;
352 };
353
FootnotebrElement(PAG1ParserState & state)354 FootnotebrElement::FootnotebrElement(PAG1ParserState &state)
355 : PAG1XMLEmptyContextBase(state)
356 {
357 }
358
endOfElement()359 void FootnotebrElement::endOfElement()
360 {
361 getState().m_footnoteState.m_pending = true;
362 }
363
364 }
365
366 namespace
367 {
368
369 class FootnoteMarkElement : public PAG1XMLEmptyContextBase
370 {
371 public:
372 explicit FootnoteMarkElement(PAG1ParserState &state);
373
374 private:
375 void attribute(int name, const char *value) override;
376 void endOfElement() override;
377 };
378
FootnoteMarkElement(PAG1ParserState & state)379 FootnoteMarkElement::FootnoteMarkElement(PAG1ParserState &state)
380 : PAG1XMLEmptyContextBase(state)
381 {
382 }
383
attribute(const int name,const char * const value)384 void FootnoteMarkElement::attribute(const int name, const char *const value)
385 {
386 if (name == (IWORKToken::NS_URI_SF | IWORKToken::mark))
387 m_state.m_footnoteState.m_mark = value;
388 else
389 {
390 ETONYEK_DEBUG_MSG(("FootnoteMarkElement::attribute[PAG1TextStorageElement]: find some unknown attribute\n"));
391 }
392 }
393
endOfElement()394 void FootnoteMarkElement::endOfElement()
395 {
396 m_state.m_footnoteState.m_firstTextAfterMark = true;
397 }
398
399 }
400
401 namespace
402 {
403
404 class FootnoteHelper
405 {
406 public:
407 explicit FootnoteHelper(PAG1ParserState &state);
408
409 IWORKXMLContextPtr_t element(int name);
410 const char *text(const char *value);
411
412 private:
413 PAG1ParserState &m_state;
414 };
415
FootnoteHelper(PAG1ParserState & state)416 FootnoteHelper::FootnoteHelper(PAG1ParserState &state)
417 : m_state(state)
418 {
419 }
420
element(const int name)421 IWORKXMLContextPtr_t FootnoteHelper::element(const int name)
422 {
423 switch (name)
424 {
425 case IWORKToken::NS_URI_SF | IWORKToken::footnote :
426 return std::make_shared<FootnoteElement>(m_state);
427 case IWORKToken::NS_URI_SF | IWORKToken::footnotebr :
428 return std::make_shared<FootnotebrElement>(m_state);
429 case IWORKToken::NS_URI_SF | IWORKToken::footnote_mark :
430 return std::make_shared<FootnoteMarkElement>(m_state);
431 default:
432 break;
433 }
434
435 return IWORKXMLContextPtr_t();
436 }
437
text(const char * const value)438 const char *FootnoteHelper::text(const char *const value)
439 {
440 if (m_state.m_footnoteState.m_firstTextAfterMark && value && (value[0] == ' '))
441 {
442 m_state.m_footnoteState.m_firstTextAfterMark = false;
443 return value + 1;
444 }
445 return value;
446 }
447
448 }
449
450 namespace
451 {
452
453 class SpanElement : public PAG1XMLContextBase<IWORKSpanElement>
454 {
455 public:
456 explicit SpanElement(PAG1ParserState &state);
457
458 private:
459 IWORKXMLContextPtr_t element(int name) override;
460 void text(const char *value) override;
461
462 private:
463 FootnoteHelper m_footnoteHelper;
464 };
465
SpanElement(PAG1ParserState & state)466 SpanElement::SpanElement(PAG1ParserState &state)
467 : PAG1XMLContextBase<IWORKSpanElement>(state)
468 , m_footnoteHelper(state)
469 {
470 }
471
element(const int name)472 IWORKXMLContextPtr_t SpanElement::element(const int name)
473 {
474 const IWORKXMLContextPtr_t context = m_footnoteHelper.element(name);
475 if (bool(context))
476 return context;
477 if (name==(IWORKToken::NS_URI_SF | IWORKToken::attachment_ref))
478 return std::make_shared<AttachmentRef>(getState());
479 return IWORKSpanElement::element(name);
480 }
481
text(const char * value)482 void SpanElement::text(const char *value)
483 {
484 PAG1XMLContextBase<IWORKSpanElement>::text(m_footnoteHelper.text(value));
485 }
486
487 }
488
489 namespace
490 {
491
492 class LinkElement : public PAG1XMLContextBase<IWORKLinkElement>
493 {
494 public:
495 explicit LinkElement(PAG1ParserState &state);
496
497 private:
498 IWORKXMLContextPtr_t element(int name) override;
499 void text(const char *value) override;
500
501 private:
502 FootnoteHelper m_footnoteHelper;
503 };
504
LinkElement(PAG1ParserState & state)505 LinkElement::LinkElement(PAG1ParserState &state)
506 : PAG1XMLContextBase<IWORKLinkElement>(state)
507 , m_footnoteHelper(state)
508 {
509 }
510
element(const int name)511 IWORKXMLContextPtr_t LinkElement::element(const int name)
512 {
513 if (name == (IWORKToken::NS_URI_SF | IWORKToken::span))
514 return std::make_shared<SpanElement>(m_state);
515 const IWORKXMLContextPtr_t context = m_footnoteHelper.element(name);
516 if (bool(context))
517 return context;
518 return IWORKLinkElement::element(name);
519 }
520
text(const char * value)521 void LinkElement::text(const char *value)
522 {
523 PAG1XMLContextBase<IWORKLinkElement>::text(m_footnoteHelper.text(value));
524 }
525
526 }
527
528 namespace
529 {
530
531 class PElement : public PAG1XMLContextBase<IWORKPElement>
532 {
533 public:
534 explicit PElement(PAG1ParserState &state);
535
536 private:
537 IWORKXMLContextPtr_t element(int name) override;
538 void text(const char *value) override;
539 void endOfElement() override;
540
541 private:
542 FootnoteHelper m_footnoteHelper;
543 };
544
PElement(PAG1ParserState & state)545 PElement::PElement(PAG1ParserState &state)
546 : PAG1XMLContextBase<IWORKPElement>(state)
547 , m_footnoteHelper(state)
548 {
549 }
550
element(const int name)551 IWORKXMLContextPtr_t PElement::element(const int name)
552 {
553 ensureOpened();
554
555 switch (name)
556 {
557 case IWORKToken::NS_URI_SF | IWORKToken::attachment_ref :
558 return std::make_shared<AttachmentRef>(getState());
559 case IWORKToken::NS_URI_SF | IWORKToken::link :
560 return std::make_shared<LinkElement>(getState());
561 case IWORKToken::NS_URI_SF | IWORKToken::span :
562 return std::make_shared<SpanElement>(getState());
563 case IWORKToken::NS_URI_SF | IWORKToken::annotation_field :
564 return std::make_shared<PAG1AnnotationElement>(getState(),*this);
565 case IWORKToken::NS_URI_SF | IWORKToken::annotation_field_ref :
566 return std::make_shared<PAG1AnnotationElement>(getState(),*this,true);
567 default:
568 break;
569 }
570
571 const IWORKXMLContextPtr_t context = m_footnoteHelper.element(name);
572 if (bool(context))
573 return context;
574
575 return IWORKPElement::element(name);
576 }
577
text(const char * value)578 void PElement::text(const char *value)
579 {
580 PAG1XMLContextBase<IWORKPElement>::text(m_footnoteHelper.text(value));
581 }
582
endOfElement()583 void PElement::endOfElement()
584 {
585 IWORKPElement::endOfElement();
586
587 if (getState().m_footnoteState.m_pending)
588 {
589 PAGFootnoteState &fs = getState().m_footnoteState;
590 const bool firstFootnote = fs.m_footnotes.empty();
591 fs.m_footnotes.push_back(IWORKOutputElements());
592 if (firstFootnote) // We can init. insertion iterator now
593 fs.m_nextFootnote = fs.m_footnotes.begin();
594 librevenge::RVNGPropertyList props;
595 if (!fs.m_mark.empty())
596 props.insert("text:label", fs.m_mark.c_str());
597 if (getCollector().getFootnoteKind() == PAG_FOOTNOTE_KIND_FOOTNOTE)
598 fs.m_footnotes.back().addOpenFootnote(props);
599 else
600 fs.m_footnotes.back().addOpenEndnote(props);
601 getState().m_currentText->draw(fs.m_footnotes.back());
602 // prepare for possible next footnote
603 // TODO: introduce IN_FOOTNOTES state and move this to startOfElement
604 getState().m_currentText = getCollector().createText(getState().m_langManager, false, false);
605
606 if (getCollector().getFootnoteKind() == PAG_FOOTNOTE_KIND_FOOTNOTE)
607 fs.m_footnotes.back().addCloseFootnote();
608 else
609 fs.m_footnotes.back().addCloseEndnote();
610
611 fs.m_pending = false;
612 fs.m_firstTextAfterMark = false;
613 fs.m_mark.clear();
614 }
615 }
616
617 }
618
619 namespace
620 {
621
622 class LayoutElement : public PAG1XMLContextBase<IWORKLayoutElement>
623 {
624 public:
625 explicit LayoutElement(PAG1ParserState &state);
626
627 private:
628 IWORKXMLContextPtr_t element(int name) override;
629 };
630
LayoutElement(PAG1ParserState & state)631 LayoutElement::LayoutElement(PAG1ParserState &state)
632 : PAG1XMLContextBase<IWORKLayoutElement>(state)
633 {
634 }
635
element(const int name)636 IWORKXMLContextPtr_t LayoutElement::element(const int name)
637 {
638 if (!m_opened)
639 open();
640
641 if (name == (IWORKToken::NS_URI_SF | IWORKToken::p))
642 return std::make_shared<PElement>(getState());
643
644 return IWORKLayoutElement::element(name);
645 }
646
647 }
648
649 namespace
650 {
651
652 class SectionElement : public PAG1XMLElementContextBase
653 {
654 public:
655 explicit SectionElement(PAG1ParserState &state);
656
657 private:
658 void open();
659
660 void startOfElement() override;
661 void attribute(int name, const char *value) override;
662 IWORKXMLContextPtr_t element(int name) override;
663 void endOfElement() override;
664
665 private:
666 bool m_opened;
667 optional<string> m_style;
668 };
669
SectionElement(PAG1ParserState & state)670 SectionElement::SectionElement(PAG1ParserState &state)
671 : PAG1XMLElementContextBase(state)
672 , m_opened(false)
673 , m_style()
674 {
675 }
676
open()677 void SectionElement::open()
678 {
679 assert(!m_opened);
680
681 if (isCollector())
682 getCollector().openSection(get_optional_value_or(m_style, ""));
683
684 m_opened = true;
685 }
686
startOfElement()687 void SectionElement::startOfElement()
688 {
689 if (isCollector())
690 {
691 // This should not happen in normal files, but better be safe than sorry
692 if (bool(getState().m_currentText) && !getState().m_currentText->empty())
693 {
694 getCollector().collectText(getState().m_currentText);
695 getState().m_currentText = getCollector().createText(getState().m_langManager);
696 getCollector().collectTextBody();
697 }
698 }
699 }
700
attribute(const int name,const char * const value)701 void SectionElement::attribute(const int name, const char *const value)
702 {
703 if (name == (IWORKToken::NS_URI_SF | IWORKToken::style))
704 m_style = value;
705 else
706 PAG1XMLElementContextBase::attribute(name, value);
707 }
708
element(const int name)709 IWORKXMLContextPtr_t SectionElement::element(const int name)
710 {
711 if (!m_opened)
712 open();
713
714 if ((IWORKToken::NS_URI_SF | IWORKToken::layout) == name)
715 return std::make_shared<LayoutElement>(getState());
716
717 return IWORKXMLContextPtr_t();
718 }
719
endOfElement()720 void SectionElement::endOfElement()
721 {
722 if (isCollector())
723 {
724 if (!m_opened)
725 open();
726 getCollector().collectText(getState().m_currentText);
727 // In case there's non-section text following. Again, this should not happen in normal files.
728 getState().m_currentText = getCollector().createText(getState().m_langManager);
729 getCollector().closeSection();
730 }
731 }
732
733 }
734
735 namespace
736 {
737
738 class ContainerHintElement : public PAG1XMLEmptyContextBase
739 {
740 public:
741 ContainerHintElement(PAG1ParserState &state, ContainerFrame &containerFrame);
742
743 private:
744 void attribute(int name, const char *value) override;
745
746 private:
747 ContainerFrame &m_containerFrame;
748 };
749
ContainerHintElement(PAG1ParserState & state,ContainerFrame & containerFrame)750 ContainerHintElement::ContainerHintElement(PAG1ParserState &state, ContainerFrame &containerFrame)
751 : PAG1XMLEmptyContextBase(state)
752 , m_containerFrame(containerFrame)
753 {
754 }
755
attribute(const int name,const char * const value)756 void ContainerHintElement::attribute(const int name, const char *const value)
757 {
758 switch (name)
759 {
760 case IWORKToken::NS_URI_SF | IWORKToken::frame_h :
761 m_containerFrame.m_h = double_cast(value);
762 break;
763 case IWORKToken::NS_URI_SF | IWORKToken::frame_w :
764 m_containerFrame.m_w = double_cast(value);
765 break;
766 case IWORKToken::NS_URI_SF | IWORKToken::frame_x :
767 m_containerFrame.m_x = double_cast(value);
768 break;
769 case IWORKToken::NS_URI_SF | IWORKToken::frame_y :
770 m_containerFrame.m_y = double_cast(value);
771 break;
772 // also page-index, cindex, sindex, lindex, anchor-loc, nlabel=true/false
773 default:
774 break;
775 }
776 }
777
778 }
779
780 namespace
781 {
782
783 class TextBodyElement : public PAG1XMLContextBase<IWORKTextBodyElement>
784 {
785 public:
786 explicit TextBodyElement(PAG1ParserState &state);
787
788 private:
789 IWORKXMLContextPtr_t element(int name) override;
790
791 private:
792 ContainerFrame m_containerFrame;
793 };
794
TextBodyElement(PAG1ParserState & state)795 TextBodyElement::TextBodyElement(PAG1ParserState &state)
796 : PAG1XMLContextBase<IWORKTextBodyElement>(state)
797 , m_containerFrame()
798 {
799 }
800
element(const int name)801 IWORKXMLContextPtr_t TextBodyElement::element(const int name)
802 {
803 switch (name)
804 {
805 case IWORKToken::NS_URI_SF | IWORKToken::container_hint :
806 return std::make_shared<ContainerHintElement>(getState(), m_containerFrame);
807 case IWORKToken::NS_URI_SF | IWORKToken::p : // for footnotes
808 return std::make_shared<PElement>(getState());
809 case IWORKToken::NS_URI_SF | IWORKToken::section :
810 return std::make_shared<SectionElement>(getState());
811 default:
812 break;
813 }
814
815 return IWORKTextBodyElement::element(name);
816 }
817
818 }
819
PAG1TextStorageElement(PAG1ParserState & state,PAGTextStorageKind kind)820 PAG1TextStorageElement::PAG1TextStorageElement(PAG1ParserState &state, PAGTextStorageKind kind)
821 : PAG1XMLContextBase<IWORKTextStorageElement>(state)
822 , m_kind(kind)
823 , m_textOpened(false)
824 {
825 if (m_kind==PAG_TEXTSTORAGE_KIND_TEXTBOX)
826 {
827 m_textOpened=true;
828 if (!bool(getState().m_currentText))
829 {
830 ETONYEK_DEBUG_MSG(("PAG1TextStorageElement::PAG1TextStorageElement: called in textbox without current tetx\n"));
831 }
832 }
833 }
834
PAG1TextStorageElement(PAG1ParserState & state,IWORKStylesheetPtr_t & sheetmap,PAGTextStorageKind kind)835 PAG1TextStorageElement::PAG1TextStorageElement(PAG1ParserState &state, IWORKStylesheetPtr_t &sheetmap, PAGTextStorageKind kind)
836 : PAG1XMLContextBase<IWORKTextStorageElement>(state)
837 , m_kind(kind)
838 , m_textOpened(false)
839 {
840 PAG1XMLContextBase<IWORKTextStorageElement>::m_stylesheet=&sheetmap;
841 if (m_kind==PAG_TEXTSTORAGE_KIND_TEXTBOX)
842 {
843 m_textOpened=true;
844 if (!bool(getState().m_currentText))
845 {
846 ETONYEK_DEBUG_MSG(("PAG1TextStorageElement::PAG1TextStorageElement: called in textbox without current tetx\n"));
847 }
848 }
849 }
850
element(const int name)851 IWORKXMLContextPtr_t PAG1TextStorageElement::element(const int name)
852 {
853 sendStylesheet();
854
855 switch (name)
856 {
857 case IWORKToken::NS_URI_SF | IWORKToken::attachments :
858 return std::make_shared<AttachmentsElement>(getState());
859 case IWORKToken::NS_URI_SF | IWORKToken::footnotes :
860 return std::make_shared<PAG1FootnotesElement>(getState());
861 case IWORKToken::NS_URI_SF | IWORKToken::text_body :
862 if (!m_textOpened)
863 {
864 assert(!getState().m_currentText);
865 getState().m_currentText = getCollector().createText(getState().m_langManager, m_kind==PAG_TEXTSTORAGE_KIND_TEXTBOX);
866 m_textOpened = true;
867 }
868 return std::make_shared<TextBodyElement>(getState());
869 default:
870 break;
871 }
872
873 return PAG1XMLContextBase<IWORKTextStorageElement>::element(name);
874 }
875
endOfElement()876 void PAG1TextStorageElement::endOfElement()
877 {
878 if (isCollector() && m_textOpened && m_kind==PAG_TEXTSTORAGE_KIND_BASIC)
879 {
880 assert(getState().m_currentText);
881 if (bool(getState().m_currentText) && !getState().m_currentText->empty())
882 getCollector().collectText(getState().m_currentText);
883 getCollector().collectTextBody();
884 }
885 if (m_kind!=PAG_TEXTSTORAGE_KIND_TEXTBOX)
886 getState().m_currentText.reset();
887
888 PAG1XMLContextBase<IWORKTextStorageElement>::endOfElement();
889 }
890
891 }
892
893 /* vim:set shiftwidth=2 softtabstop=2 expandtab: */
894