1 // Copyright (c) 1996 James Clark
2 // See the file copying.txt for copying permission.
5 #include "ProcessContext.h"
6 #include "Interpreter.h"
7 #include "InterpreterMessages.h"
11 #ifdef DSSSL_NAMESPACE
12 namespace DSSSL_NAMESPACE {
21 void FlowObj::process(ProcessContext &context)
23 context.startFlowObj();
25 pushStyle(context, flags);
26 processInner(context);
27 popStyle(context, flags);
31 void FlowObj::pushStyle(ProcessContext &context, unsigned &)
34 context.currentStyleStack().push(style_, context.vm(), context.currentFOTBuilder());
36 context.currentStyleStack().pushEmpty();
39 void FlowObj::popStyle(ProcessContext &context, unsigned)
42 context.currentStyleStack().pop();
44 context.currentStyleStack().popEmpty();
47 void FlowObj::traceSubObjects(Collector &c) const
52 CompoundFlowObj *FlowObj::asCompoundFlowObj()
57 bool FlowObj::hasNonInheritedC(const Identifier *) const
62 bool FlowObj::hasPseudoNonInheritedC(const Identifier *) const
67 void FlowObj::setNonInheritedC(const Identifier *, ELObj *, const Location &, Interpreter &)
72 bool FlowObj::isDisplayNIC(const Identifier *ident)
74 Identifier::SyntacticKey key;
75 if (ident->syntacticKey(key)) {
77 case Identifier::keyPositionPreference:
78 case Identifier::keyIsKeepWithPrevious:
79 case Identifier::keyIsKeepWithNext:
80 case Identifier::keyKeep:
81 case Identifier::keyBreakBefore:
82 case Identifier::keyBreakAfter:
83 case Identifier::keyIsMayViolateKeepBefore:
84 case Identifier::keyIsMayViolateKeepAfter:
85 case Identifier::keySpaceBefore:
86 case Identifier::keySpaceAfter:
95 bool FlowObj::setDisplayNIC(FOTBuilder::DisplayNIC &nic,
96 const Identifier *ident, ELObj *obj,
97 const Location &loc, Interpreter &interp)
99 static FOTBuilder::Symbol breakVals[] = {
100 FOTBuilder::symbolFalse,
101 FOTBuilder::symbolPage,
102 FOTBuilder::symbolColumnSet,
103 FOTBuilder::symbolColumn
105 Identifier::SyntacticKey key;
106 if (ident->syntacticKey(key)) {
108 case Identifier::keyPositionPreference:
110 static FOTBuilder::Symbol vals[] = {
111 FOTBuilder::symbolFalse,
112 FOTBuilder::symbolTop,
113 FOTBuilder::symbolBottom,
115 interp.convertEnumC(vals, SIZEOF(vals), obj, ident, loc, nic.positionPreference);
118 case Identifier::keyIsKeepWithPrevious:
119 interp.convertBooleanC(obj, ident, loc, nic.keepWithPrevious);
121 case Identifier::keyIsKeepWithNext:
122 interp.convertBooleanC(obj, ident, loc, nic.keepWithNext);
124 case Identifier::keyKeep:
126 static FOTBuilder::Symbol vals[] = {
127 FOTBuilder::symbolFalse,
128 FOTBuilder::symbolTrue,
129 FOTBuilder::symbolPage,
130 FOTBuilder::symbolColumnSet,
131 FOTBuilder::symbolColumn
133 interp.convertEnumC(vals, SIZEOF(vals), obj, ident, loc, nic.keep);
136 case Identifier::keyBreakBefore:
137 interp.convertEnumC(breakVals, SIZEOF(breakVals), obj, ident, loc, nic.breakBefore);
139 case Identifier::keyBreakAfter:
140 interp.convertEnumC(breakVals, SIZEOF(breakVals), obj, ident, loc, nic.breakAfter);
142 case Identifier::keyIsMayViolateKeepBefore:
143 interp.convertBooleanC(obj, ident, loc, nic.mayViolateKeepBefore);
145 case Identifier::keyIsMayViolateKeepAfter:
146 interp.convertBooleanC(obj, ident, loc, nic.mayViolateKeepAfter);
148 case Identifier::keySpaceBefore:
149 case Identifier::keySpaceAfter:
151 FOTBuilder::DisplaySpace &ds = (key == Identifier::keySpaceBefore
154 DisplaySpaceObj *dso = obj->asDisplaySpace();
156 ds = dso->displaySpace();
157 else if (interp.convertLengthSpecC(obj, ident, loc, ds.nominal)) {
171 void CompoundFlowObj::processInner(ProcessContext &context)
174 content_->process(context);
176 context.processChildren(context.vm().interp->initialProcessingMode());
179 void CompoundFlowObj::traceSubObjects(Collector &c) const
182 FlowObj::traceSubObjects(c);
185 CompoundFlowObj *CompoundFlowObj::asCompoundFlowObj()
190 class DisplayGroupFlowObj : public CompoundFlowObj {
192 void *operator new(size_t, Collector &c) {
193 return c.allocateObject(1);
195 DisplayGroupFlowObj();
196 DisplayGroupFlowObj(const DisplayGroupFlowObj &);
197 void processInner(ProcessContext &);
198 FlowObj *copy(Collector &) const;
199 void setNonInheritedC(const Identifier *, ELObj *,
200 const Location &, Interpreter &);
201 bool hasNonInheritedC(const Identifier *) const;
203 Owner<FOTBuilder::DisplayGroupNIC> nic_;
206 DisplayGroupFlowObj::DisplayGroupFlowObj()
207 : nic_(new FOTBuilder::DisplayGroupNIC)
211 DisplayGroupFlowObj::DisplayGroupFlowObj(const DisplayGroupFlowObj &fo)
212 : CompoundFlowObj(fo), nic_(new FOTBuilder::DisplayGroupNIC(*fo.nic_))
216 void DisplayGroupFlowObj::processInner(ProcessContext &context)
218 FOTBuilder &fotb = context.currentFOTBuilder();
219 fotb.startDisplayGroup(*nic_);
220 CompoundFlowObj::processInner(context);
221 fotb.endDisplayGroup();
224 bool DisplayGroupFlowObj::hasNonInheritedC(const Identifier *ident) const
226 Identifier::SyntacticKey key;
227 if (ident->syntacticKey(key) && key == Identifier::keyCoalesceId)
229 return isDisplayNIC(ident);
232 void DisplayGroupFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
233 const Location &loc, Interpreter &interp)
235 if (!setDisplayNIC(*nic_, ident, obj, loc, interp)) {
238 if (!obj->stringData(s, n)) {
239 interp.setNextLocation(loc);
240 interp.message(InterpreterMessages::invalidCharacteristicValue,
241 StringMessageArg(ident->name()));
243 nic_->hasCoalesceId = 1;
244 nic_->coalesceId.assign(s, n);
248 FlowObj *DisplayGroupFlowObj::copy(Collector &c) const
250 return new (c) DisplayGroupFlowObj(*this);
253 class ParagraphFlowObj : public CompoundFlowObj {
255 void *operator new(size_t, Collector &c) {
256 return c.allocateObject(1);
259 ParagraphFlowObj(const ParagraphFlowObj &);
260 void processInner(ProcessContext &);
261 FlowObj *copy(Collector &) const;
262 void setNonInheritedC(const Identifier *, ELObj *,
263 const Location &, Interpreter &);
264 bool hasNonInheritedC(const Identifier *) const;
266 Owner<FOTBuilder::ParagraphNIC> nic_;
270 ParagraphFlowObj::ParagraphFlowObj()
271 : nic_(new FOTBuilder::ParagraphNIC)
275 ParagraphFlowObj::ParagraphFlowObj(const ParagraphFlowObj &fo)
276 : CompoundFlowObj(fo), nic_(new FOTBuilder::ParagraphNIC(*fo.nic_))
280 void ParagraphFlowObj::processInner(ProcessContext &context)
282 FOTBuilder &fotb = context.currentFOTBuilder();
283 fotb.startParagraph(*nic_);
284 CompoundFlowObj::processInner(context);
288 void ParagraphFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
289 const Location &loc, Interpreter &interp)
291 setDisplayNIC(*nic_, ident, obj, loc, interp);
294 bool ParagraphFlowObj::hasNonInheritedC(const Identifier *ident) const
296 return isDisplayNIC(ident);
299 FlowObj *ParagraphFlowObj::copy(Collector &c) const
301 return new (c) ParagraphFlowObj(*this);
304 class ParagraphBreakFlowObj : public FlowObj {
306 void *operator new(size_t, Collector &c) {
307 return c.allocateObject(1);
309 ParagraphBreakFlowObj();
310 ParagraphBreakFlowObj(const ParagraphBreakFlowObj &);
311 FlowObj *copy(Collector &) const;
312 void processInner(ProcessContext &);
313 void setNonInheritedC(const Identifier *, ELObj *,
314 const Location &, Interpreter &);
315 bool hasNonInheritedC(const Identifier *) const;
317 Owner<FOTBuilder::ParagraphNIC> nic_;
321 ParagraphBreakFlowObj::ParagraphBreakFlowObj()
322 : nic_(new FOTBuilder::ParagraphNIC)
326 ParagraphBreakFlowObj::ParagraphBreakFlowObj(const ParagraphBreakFlowObj &fo)
327 : FlowObj(fo), nic_(new FOTBuilder::ParagraphNIC(*fo.nic_))
331 FlowObj *ParagraphBreakFlowObj::copy(Collector &c) const
333 return new (c) ParagraphBreakFlowObj(*this);
336 void ParagraphBreakFlowObj::processInner(ProcessContext &context)
338 context.currentFOTBuilder().paragraphBreak(*nic_);
341 void ParagraphBreakFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
342 const Location &loc, Interpreter &interp)
344 setDisplayNIC(*nic_, ident, obj, loc, interp);
347 bool ParagraphBreakFlowObj::hasNonInheritedC(const Identifier *ident) const
349 return isDisplayNIC(ident);
352 class ExternalGraphicFlowObj : public FlowObj {
354 void *operator new(size_t, Collector &c) {
355 return c.allocateObject(1);
357 ExternalGraphicFlowObj();
358 ExternalGraphicFlowObj(const ExternalGraphicFlowObj &);
359 void processInner(ProcessContext &);
360 FlowObj *copy(Collector &) const;
361 void setNonInheritedC(const Identifier *, ELObj *,
362 const Location &, Interpreter &);
363 bool hasNonInheritedC(const Identifier *) const;
365 Owner<FOTBuilder::ExternalGraphicNIC> nic_;
369 ExternalGraphicFlowObj::ExternalGraphicFlowObj()
370 : nic_(new FOTBuilder::ExternalGraphicNIC)
374 ExternalGraphicFlowObj::ExternalGraphicFlowObj(const ExternalGraphicFlowObj &fo)
375 : FlowObj(fo), nic_(new FOTBuilder::ExternalGraphicNIC(*fo.nic_))
379 void ExternalGraphicFlowObj::processInner(ProcessContext &context)
381 context.currentFOTBuilder().externalGraphic(*nic_);
384 void ExternalGraphicFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
385 const Location &loc, Interpreter &interp)
387 if (!setDisplayNIC(*nic_, ident, obj, loc, interp)) {
388 Identifier::SyntacticKey key;
389 if (ident->syntacticKey(key)) {
391 case Identifier::keyIsDisplay:
392 interp.convertBooleanC(obj, ident, loc, nic_->isDisplay);
394 case Identifier::keyScale:
397 if (obj->realValue(d)) {
398 nic_->scaleType = FOTBuilder::symbolFalse;
399 nic_->scale[0] = nic_->scale[1] = d;
401 else if (obj->asSymbol()) {
402 static FOTBuilder::Symbol vals[] = {
403 FOTBuilder::symbolMax,
404 FOTBuilder::symbolMaxUniform
406 interp.convertEnumC(vals, 2, obj, ident, loc, nic_->scaleType);
409 PairObj *pair = obj->asPair();
411 && pair->car()->realValue(nic_->scale[0])
412 && (pair = pair->cdr()->asPair()) != 0
413 && pair->car()->realValue(nic_->scale[1])
414 && pair->cdr()->isNil()) {
415 nic_->scaleType = FOTBuilder::symbolFalse;
418 interp.invalidCharacteristicValue(ident, loc);
422 case Identifier::keyMaxWidth:
423 if (interp.convertLengthSpecC(obj, ident, loc, nic_->maxWidth))
424 nic_->hasMaxWidth = 1;
426 case Identifier::keyMaxHeight:
427 if (interp.convertLengthSpecC(obj, ident, loc, nic_->maxHeight))
428 nic_->hasMaxHeight = 1;
430 case Identifier::keyEntitySystemId:
431 interp.convertStringC(obj, ident, loc, nic_->entitySystemId);
433 case Identifier::keyNotationSystemId:
434 interp.convertStringC(obj, ident, loc, nic_->notationSystemId);
436 case Identifier::keyPositionPointX:
437 interp.convertLengthSpecC(obj, ident, loc, nic_->positionPointX);
439 case Identifier::keyPositionPointY:
440 interp.convertLengthSpecC(obj, ident, loc, nic_->positionPointY);
442 case Identifier::keyEscapementDirection:
444 static FOTBuilder::Symbol vals[] = {
445 FOTBuilder::symbolTopToBottom,
446 FOTBuilder::symbolLeftToRight,
447 FOTBuilder::symbolBottomToTop,
448 FOTBuilder::symbolRightToLeft
450 interp.convertEnumC(vals, SIZEOF(vals), obj, ident, loc, nic_->escapementDirection);
453 case Identifier::keyBreakBeforePriority:
454 interp.convertIntegerC(obj, ident, loc, nic_->breakBeforePriority);
456 case Identifier::keyBreakAfterPriority:
457 interp.convertIntegerC(obj, ident, loc, nic_->breakAfterPriority);
467 bool ExternalGraphicFlowObj::hasNonInheritedC(const Identifier *ident) const
469 Identifier::SyntacticKey key;
470 if (ident->syntacticKey(key)) {
472 case Identifier::keyIsDisplay:
473 case Identifier::keyScale:
474 case Identifier::keyMaxWidth:
475 case Identifier::keyMaxHeight:
476 case Identifier::keyEntitySystemId:
477 case Identifier::keyNotationSystemId:
478 case Identifier::keyPositionPointX:
479 case Identifier::keyPositionPointY:
480 case Identifier::keyEscapementDirection:
481 case Identifier::keyBreakBeforePriority:
482 case Identifier::keyBreakAfterPriority:
488 return isDisplayNIC(ident);
491 FlowObj *ExternalGraphicFlowObj::copy(Collector &c) const
493 return new (c) ExternalGraphicFlowObj(*this);
496 class RuleFlowObj : public FlowObj {
498 void *operator new(size_t, Collector &c) {
499 return c.allocateObject(1);
502 RuleFlowObj(const RuleFlowObj &);
503 void processInner(ProcessContext &);
504 FlowObj *copy(Collector &) const;
505 void setNonInheritedC(const Identifier *, ELObj *,
506 const Location &, Interpreter &);
507 bool hasNonInheritedC(const Identifier *) const;
508 bool ruleStyle(ProcessContext &, StyleObj *&style) {
512 bool isRule() { return 1; }
514 Owner<FOTBuilder::RuleNIC> nic_;
517 RuleFlowObj::RuleFlowObj()
518 : nic_(new FOTBuilder::RuleNIC)
522 RuleFlowObj::RuleFlowObj(const RuleFlowObj &fo)
523 : FlowObj(fo), nic_(new FOTBuilder::RuleNIC(*fo.nic_))
527 void RuleFlowObj::processInner(ProcessContext &context)
529 context.currentFOTBuilder().rule(*nic_);
532 void RuleFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
533 const Location &loc, Interpreter &interp)
535 if (setDisplayNIC(*nic_, ident, obj, loc, interp))
537 Identifier::SyntacticKey key;
538 if (ident->syntacticKey(key)) {
540 case Identifier::keyOrientation:
542 static FOTBuilder::Symbol vals[] = {
543 FOTBuilder::symbolHorizontal,
544 FOTBuilder::symbolVertical,
545 FOTBuilder::symbolEscapement,
546 FOTBuilder::symbolLineProgression
548 interp.convertEnumC(vals, SIZEOF(vals), obj, ident, loc, nic_->orientation);
551 case Identifier::keyLength:
552 if (interp.convertLengthSpecC(obj, ident, loc, nic_->length))
555 case Identifier::keyBreakBeforePriority:
556 interp.convertIntegerC(obj, ident, loc, nic_->breakBeforePriority);
558 case Identifier::keyBreakAfterPriority:
559 interp.convertIntegerC(obj, ident, loc, nic_->breakAfterPriority);
568 bool RuleFlowObj::hasNonInheritedC(const Identifier *ident) const
570 Identifier::SyntacticKey key;
571 if (ident->syntacticKey(key)) {
573 case Identifier::keyOrientation:
574 case Identifier::keyLength:
575 case Identifier::keyBreakBeforePriority:
576 case Identifier::keyBreakAfterPriority:
582 return isDisplayNIC(ident);
585 FlowObj *RuleFlowObj::copy(Collector &c) const
587 return new (c) RuleFlowObj(*this);
590 class AlignmentPointFlowObj : public FlowObj {
592 AlignmentPointFlowObj() { }
593 FlowObj *copy(Collector &) const;
594 void processInner(ProcessContext &);
597 FlowObj *AlignmentPointFlowObj::copy(Collector &c) const
599 return new (c) AlignmentPointFlowObj(*this);
602 void AlignmentPointFlowObj::processInner(ProcessContext &context)
604 context.currentFOTBuilder().alignmentPoint();
607 class SidelineFlowObj : public CompoundFlowObj {
609 SidelineFlowObj() { }
610 FlowObj *copy(Collector &) const;
611 void processInner(ProcessContext &);
614 FlowObj *SidelineFlowObj::copy(Collector &c) const
616 return new (c) SidelineFlowObj(*this);
619 void SidelineFlowObj::processInner(ProcessContext &context)
621 FOTBuilder &fotb = context.currentFOTBuilder();
622 fotb.startSideline();
623 CompoundFlowObj::processInner(context);
626 void SequenceFlowObj::processInner(ProcessContext &context)
628 FOTBuilder &fotb = context.currentFOTBuilder();
629 fotb.startSequence();
630 CompoundFlowObj::processInner(context);
634 FlowObj *SequenceFlowObj::copy(Collector &c) const
636 return new (c) SequenceFlowObj(*this);
639 class LineFieldFlowObj : public CompoundFlowObj {
641 void *operator new(size_t, Collector &c) {
642 return c.allocateObject(1);
644 LineFieldFlowObj() : nic_(new FOTBuilder::LineFieldNIC) { }
645 LineFieldFlowObj(const LineFieldFlowObj &fo)
646 : CompoundFlowObj(fo), nic_(new FOTBuilder::LineFieldNIC(*fo.nic_)) { }
647 void processInner(ProcessContext &);
648 FlowObj *copy(Collector &) const;
649 bool hasNonInheritedC(const Identifier *ident) const;
650 void setNonInheritedC(const Identifier *ident, ELObj *obj,
651 const Location &loc, Interpreter &interp);
653 Owner<FOTBuilder::LineFieldNIC> nic_;
656 FlowObj *LineFieldFlowObj::copy(Collector &c) const
658 return new (c) LineFieldFlowObj(*this);
661 void LineFieldFlowObj::processInner(ProcessContext &context)
663 FOTBuilder &fotb = context.currentFOTBuilder();
664 fotb.startLineField(*nic_);
665 CompoundFlowObj::processInner(context);
669 void LineFieldFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
670 const Location &loc, Interpreter &interp)
672 Identifier::SyntacticKey key;
673 if (ident->syntacticKey(key)) {
675 case Identifier::keyBreakBeforePriority:
676 interp.convertIntegerC(obj, ident, loc, nic_->breakBeforePriority);
678 case Identifier::keyBreakAfterPriority:
679 interp.convertIntegerC(obj, ident, loc, nic_->breakAfterPriority);
688 bool LineFieldFlowObj::hasNonInheritedC(const Identifier *ident) const
690 Identifier::SyntacticKey key;
691 if (ident->syntacticKey(key)) {
693 case Identifier::keyBreakBeforePriority:
694 case Identifier::keyBreakAfterPriority:
703 class SimplePageSequenceFlowObj : public CompoundFlowObj {
705 void *operator new(size_t, Collector &c) {
706 return c.allocateObject(1);
708 struct HeaderFooter {
711 SosofoObj *part[nParts];
713 SimplePageSequenceFlowObj();
714 SimplePageSequenceFlowObj(const SimplePageSequenceFlowObj &);
715 void processInner(ProcessContext &);
716 FlowObj *copy(Collector &) const;
717 bool hasNonInheritedC(const Identifier *) const;
718 void setNonInheritedC(const Identifier *, ELObj *,
719 const Location &, Interpreter &);
720 void traceSubObjects(Collector &) const;
722 enum { nPageTypeBits = 2 };
723 Owner<HeaderFooter> hf_;
727 SimplePageSequenceFlowObj::SimplePageSequenceFlowObj()
728 : hf_(new HeaderFooter)
733 SimplePageSequenceFlowObj::SimplePageSequenceFlowObj(const SimplePageSequenceFlowObj &fo)
734 : CompoundFlowObj(fo), hf_(new HeaderFooter(*fo.hf_))
738 void SimplePageSequenceFlowObj::traceSubObjects(Collector &c) const
740 for (int i = 0; i < HeaderFooter::nParts; i++)
741 c.trace(hf_->part[i]);
742 CompoundFlowObj::traceSubObjects(c);
745 void SimplePageSequenceFlowObj::processInner(ProcessContext &context)
747 FOTBuilder &fotb = context.currentFOTBuilder();
748 FOTBuilder* hf_fotb[FOTBuilder::nHF];
749 fotb.startSimplePageSequence(hf_fotb);
750 for (int i = 0; i < (1 << nPageTypeBits); i++) {
751 context.setPageType(i);
752 for (int j = 0; j < HeaderFooter::nParts; j++) {
754 context.pushPrincipalPort(hf_fotb[i | (j << nPageTypeBits)]);
755 hf_->part[j]->process(context);
756 context.popPrincipalPort();
760 fotb.endSimplePageSequenceHeaderFooter();
761 CompoundFlowObj::processInner(context);
762 fotb.endSimplePageSequence();
765 void SimplePageSequenceFlowObj::setNonInheritedC(const Identifier *ident,
770 SosofoObj *sosofo = obj->asSosofo();
772 interp.setNextLocation(loc);
773 interp.message(InterpreterMessages::invalidCharacteristicValue,
774 StringMessageArg(ident->name()));
777 Identifier::SyntacticKey key;
778 if (ident->syntacticKey(key)) {
780 case Identifier::keyLeftHeader:
781 hf_->part[(FOTBuilder::leftHF | FOTBuilder::headerHF) >> nPageTypeBits] = sosofo;
783 case Identifier::keyCenterHeader:
784 hf_->part[(FOTBuilder::centerHF | FOTBuilder::headerHF) >> nPageTypeBits] = sosofo;
786 case Identifier::keyRightHeader:
787 hf_->part[(FOTBuilder::rightHF | FOTBuilder::headerHF) >> nPageTypeBits] = sosofo;
789 case Identifier::keyLeftFooter:
790 hf_->part[(FOTBuilder::leftHF | FOTBuilder::footerHF) >> nPageTypeBits] = sosofo;
792 case Identifier::keyCenterFooter:
793 hf_->part[(FOTBuilder::centerHF | FOTBuilder::footerHF) >> nPageTypeBits] = sosofo;
795 case Identifier::keyRightFooter:
796 hf_->part[(FOTBuilder::rightHF | FOTBuilder::footerHF) >> nPageTypeBits] = sosofo;
805 bool SimplePageSequenceFlowObj::hasNonInheritedC(const Identifier *ident) const
807 Identifier::SyntacticKey key;
808 if (ident->syntacticKey(key)) {
810 case Identifier::keyLeftHeader:
811 case Identifier::keyCenterHeader:
812 case Identifier::keyRightHeader:
813 case Identifier::keyLeftFooter:
814 case Identifier::keyCenterFooter:
815 case Identifier::keyRightFooter:
824 FlowObj *SimplePageSequenceFlowObj::copy(Collector &c) const
826 return new (c) SimplePageSequenceFlowObj(*this);
829 SimplePageSequenceFlowObj::HeaderFooter::HeaderFooter()
831 for (int i = 0; i < nParts; i++)
835 class LinkFlowObj : public CompoundFlowObj {
838 FlowObj *copy(Collector &) const;
839 void processInner(ProcessContext &);
840 void traceSubObjects(Collector &) const;
841 bool hasNonInheritedC(const Identifier *) const;
842 void setNonInheritedC(const Identifier *, ELObj *,
843 const Location &, Interpreter &);
845 AddressObj *addressObj_;
848 LinkFlowObj::LinkFlowObj()
853 void LinkFlowObj::processInner(ProcessContext &context)
855 FOTBuilder &fotb = context.currentFOTBuilder();
857 FOTBuilder::Address addr;
858 addr.type = FOTBuilder::Address::none;
859 fotb.startLink(addr);
862 fotb.startLink(addressObj_->address());
863 CompoundFlowObj::processInner(context);
867 FlowObj *LinkFlowObj::copy(Collector &c) const
869 return new (c) LinkFlowObj(*this);
872 void LinkFlowObj::traceSubObjects(Collector &c) const
874 CompoundFlowObj::traceSubObjects(c);
875 c.trace(addressObj_);
878 bool LinkFlowObj::hasNonInheritedC(const Identifier *ident) const
880 Identifier::SyntacticKey key;
881 return ident->syntacticKey(key) && key == Identifier::keyDestination;
884 void LinkFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
885 const Location &loc, Interpreter &interp)
887 AddressObj *address = obj->asAddress();
889 if (obj != interp.makeFalse()) {
890 interp.setNextLocation(loc);
891 interp.message(InterpreterMessages::invalidCharacteristicValue,
892 StringMessageArg(ident->name()));
895 address = interp.makeAddressNone();
897 addressObj_ = address;
900 class ScrollFlowObj : public CompoundFlowObj {
903 void processInner(ProcessContext &);
904 FlowObj *copy(Collector &) const;
907 void ScrollFlowObj::processInner(ProcessContext &context)
909 FOTBuilder &fotb = context.currentFOTBuilder();
911 CompoundFlowObj::processInner(context);
915 FlowObj *ScrollFlowObj::copy(Collector &c) const
917 return new (c) ScrollFlowObj(*this);
920 class MarginaliaFlowObj : public CompoundFlowObj {
922 MarginaliaFlowObj() { }
923 void processInner(ProcessContext &);
924 FlowObj *copy(Collector &) const;
927 void MarginaliaFlowObj::processInner(ProcessContext &context)
929 FOTBuilder &fotb = context.currentFOTBuilder();
930 fotb.startMarginalia();
931 CompoundFlowObj::processInner(context);
932 fotb.endMarginalia();
935 FlowObj *MarginaliaFlowObj::copy(Collector &c) const
937 return new (c) MarginaliaFlowObj(*this);
940 class MultiModeFlowObj : public CompoundFlowObj {
942 void *operator new(size_t, Collector &c) {
943 return c.allocateObject(1);
946 MultiModeFlowObj(const MultiModeFlowObj &);
947 void processInner(ProcessContext &);
948 FlowObj *copy(Collector &) const;
949 bool hasNonInheritedC(const Identifier *) const;
950 void setNonInheritedC(const Identifier *, ELObj *,
951 const Location &, Interpreter &);
953 NIC() : hasPrincipalMode(0) { }
954 bool hasPrincipalMode;
955 FOTBuilder::MultiMode principalMode;
956 Vector<FOTBuilder::MultiMode> namedModes;
959 bool handleMultiModesMember(const Identifier *, ELObj *obj,
960 const Location &, Interpreter &);
964 MultiModeFlowObj::MultiModeFlowObj()
969 MultiModeFlowObj::MultiModeFlowObj(const MultiModeFlowObj &fo)
970 : CompoundFlowObj(fo), nic_(new NIC(*fo.nic_))
974 void MultiModeFlowObj::processInner(ProcessContext &context)
976 FOTBuilder &fotb = context.currentFOTBuilder();
977 Vector<FOTBuilder *> fotbs(nic_->namedModes.size());
978 fotb.startMultiMode(nic_->hasPrincipalMode ? &nic_->principalMode : 0,
981 Vector<SymbolObj *> portSyms(nic_->namedModes.size());
982 for (size_t i = 0; i < portSyms.size(); i++)
983 portSyms[i] = context.vm().interp->makeSymbol(nic_->namedModes[i].name);
984 context.pushPorts(nic_->hasPrincipalMode, portSyms, fotbs);
985 CompoundFlowObj::processInner(context);
990 FlowObj *MultiModeFlowObj::copy(Collector &c) const
992 return new (c) MultiModeFlowObj(*this);
995 bool MultiModeFlowObj::hasNonInheritedC(const Identifier *ident) const
997 Identifier::SyntacticKey key;
998 return ident->syntacticKey(key) && key == Identifier::keyMultiModes;
1001 void MultiModeFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
1002 const Location &loc, Interpreter &interp)
1004 while (!obj->isNil()) {
1005 PairObj *pair = obj->asPair();
1006 if (!pair || !handleMultiModesMember(ident, pair->car(), loc, interp)) {
1007 interp.setNextLocation(loc);
1008 interp.message(InterpreterMessages::invalidCharacteristicValue,
1009 StringMessageArg(ident->name()));
1016 bool MultiModeFlowObj::handleMultiModesMember(const Identifier *, ELObj *obj,
1017 const Location &loc, Interpreter &interp)
1019 if (obj == interp.makeFalse()) {
1020 nic_->hasPrincipalMode = 1;
1023 SymbolObj *sym = obj->asSymbol();
1025 nic_->namedModes.resize(nic_->namedModes.size() + 1);
1026 nic_->namedModes.back().name = *sym->name();
1029 PairObj *pair = obj->asPair();
1032 ELObj *spec = pair->car();
1033 pair = pair->cdr()->asPair();
1034 if (!pair || !pair->cdr()->isNil())
1038 if (!pair->car()->stringData(s, n))
1040 if (spec == interp.makeFalse()) {
1041 nic_->hasPrincipalMode = 1;
1042 nic_->principalMode.hasDesc = 1;
1043 nic_->principalMode.desc.assign(s, n);
1046 sym = spec->asSymbol();
1049 nic_->namedModes.resize(nic_->namedModes.size() + 1);
1050 nic_->namedModes.back().name = *sym->name();
1051 nic_->namedModes.back().desc.assign(s, n);
1052 nic_->namedModes.back().hasDesc = 1;
1057 class ScoreFlowObj : public CompoundFlowObj {
1059 void *operator new(size_t, Collector &c) {
1060 return c.allocateObject(1);
1063 FlowObj *copy(Collector &) const;
1064 void processInner(ProcessContext &);
1065 bool hasNonInheritedC(const Identifier *) const;
1066 void setNonInheritedC(const Identifier *, ELObj *,
1067 const Location &, Interpreter &);
1071 virtual void start(FOTBuilder &) = 0;
1072 virtual Type *copy() const = 0;
1075 class SymbolType : public Type {
1077 SymbolType(FOTBuilder::Symbol type) : type_(type) { }
1078 void start(FOTBuilder &);
1081 FOTBuilder::Symbol type_;
1083 class LengthSpecType : public Type {
1085 LengthSpecType(long n) : len_(n) { }
1086 void start(FOTBuilder &);
1089 FOTBuilder::LengthSpec len_;
1091 class CharType : public Type {
1093 CharType(Char c) : c_(c) { }
1094 void start(FOTBuilder &);
1099 CopyOwner<Type> type_;
1102 ScoreFlowObj::ScoreFlowObj()
1106 FlowObj *ScoreFlowObj::copy(Collector &c) const
1108 return new (c) ScoreFlowObj(*this);
1111 void ScoreFlowObj::processInner(ProcessContext &context)
1113 FOTBuilder &fotb = context.currentFOTBuilder();
1117 fotb.startSequence();
1118 CompoundFlowObj::processInner(context);
1125 bool ScoreFlowObj::hasNonInheritedC(const Identifier *ident) const
1127 Identifier::SyntacticKey key;
1128 return ident->syntacticKey(key) && key == Identifier::keyType;
1131 void ScoreFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
1132 const Location &loc, Interpreter &interp)
1135 if (obj->charValue(c)) {
1136 type_ = new CharType(c);
1142 switch (obj->quantityValue(n, d, dim)) {
1145 type_ = new LengthSpecType(n);
1149 case doubleQuantity:
1151 type_ = new LengthSpecType(long(d));
1158 static FOTBuilder::Symbol vals[] = {
1159 FOTBuilder::symbolBefore,
1160 FOTBuilder::symbolThrough,
1161 FOTBuilder::symbolAfter
1163 FOTBuilder::Symbol sym;
1164 if (interp.convertEnumC(vals, SIZEOF(vals), obj, ident, loc, sym))
1165 type_ = new SymbolType(sym);
1168 ScoreFlowObj::Type::~Type()
1172 void ScoreFlowObj::SymbolType::start(FOTBuilder &fotb)
1174 fotb.startScore(type_);
1177 void ScoreFlowObj::CharType::start(FOTBuilder &fotb)
1179 fotb.startScore(c_);
1182 void ScoreFlowObj::LengthSpecType::start(FOTBuilder &fotb)
1184 fotb.startScore(len_);
1187 ScoreFlowObj::Type *ScoreFlowObj::SymbolType::copy() const
1189 return new SymbolType(*this);
1192 ScoreFlowObj::Type *ScoreFlowObj::LengthSpecType::copy() const
1194 return new LengthSpecType(*this);
1197 ScoreFlowObj::Type *ScoreFlowObj::CharType::copy() const
1199 return new CharType(*this);
1202 class BoxFlowObj : public CompoundFlowObj {
1204 void *operator new(size_t, Collector &c) {
1205 return c.allocateObject(1);
1208 BoxFlowObj(const BoxFlowObj &);
1209 FlowObj *copy(Collector &) const;
1210 void processInner(ProcessContext &);
1211 bool hasNonInheritedC(const Identifier *) const;
1212 void setNonInheritedC(const Identifier *, ELObj *,
1213 const Location &, Interpreter &);
1215 Owner<FOTBuilder::BoxNIC> nic_;
1218 BoxFlowObj::BoxFlowObj()
1219 : nic_(new FOTBuilder::BoxNIC)
1223 BoxFlowObj::BoxFlowObj(const BoxFlowObj &fo)
1224 : CompoundFlowObj(fo), nic_(new FOTBuilder::BoxNIC(*fo.nic_))
1228 void BoxFlowObj::processInner(ProcessContext &context)
1230 FOTBuilder &fotb = context.currentFOTBuilder();
1231 fotb.startBox(*nic_);
1232 CompoundFlowObj::processInner(context);
1236 void BoxFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
1237 const Location &loc, Interpreter &interp)
1239 if (setDisplayNIC(*nic_, ident, obj, loc, interp))
1241 Identifier::SyntacticKey key;
1242 if (ident->syntacticKey(key)) {
1244 case Identifier::keyIsDisplay:
1245 interp.convertBooleanC(obj, ident, loc, nic_->isDisplay);
1247 case Identifier::keyBreakBeforePriority:
1248 interp.convertIntegerC(obj, ident, loc, nic_->breakBeforePriority);
1250 case Identifier::keyBreakAfterPriority:
1251 interp.convertIntegerC(obj, ident, loc, nic_->breakAfterPriority);
1260 bool BoxFlowObj::hasNonInheritedC(const Identifier *ident) const
1262 Identifier::SyntacticKey key;
1263 if (ident->syntacticKey(key)) {
1265 case Identifier::keyIsDisplay:
1266 case Identifier::keyBreakBeforePriority:
1267 case Identifier::keyBreakAfterPriority:
1273 return isDisplayNIC(ident);
1276 FlowObj *BoxFlowObj::copy(Collector &c) const
1278 return new (c) BoxFlowObj(*this);
1281 class LeaderFlowObj : public CompoundFlowObj {
1283 void *operator new(size_t, Collector &c) {
1284 return c.allocateObject(1);
1287 LeaderFlowObj(const LeaderFlowObj &);
1288 void processInner(ProcessContext &);
1289 FlowObj *copy(Collector &) const;
1290 void setNonInheritedC(const Identifier *, ELObj *,
1291 const Location &, Interpreter &);
1292 bool hasNonInheritedC(const Identifier *) const;
1294 Owner<FOTBuilder::LeaderNIC> nic_;
1297 LeaderFlowObj::LeaderFlowObj()
1298 : nic_(new FOTBuilder::LeaderNIC)
1302 LeaderFlowObj::LeaderFlowObj(const LeaderFlowObj &fo)
1303 : CompoundFlowObj(fo), nic_(new FOTBuilder::LeaderNIC(*fo.nic_))
1307 void LeaderFlowObj::processInner(ProcessContext &context)
1309 FOTBuilder &fotb = context.currentFOTBuilder();
1310 fotb.startLeader(*nic_);
1311 CompoundFlowObj::processInner(context);
1315 void LeaderFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
1316 const Location &loc, Interpreter &interp)
1318 Identifier::SyntacticKey key;
1319 if (ident->syntacticKey(key)) {
1321 case Identifier::keyLength:
1322 if (interp.convertLengthSpecC(obj, ident, loc, nic_->length))
1323 nic_->hasLength = 1;
1325 case Identifier::keyBreakBeforePriority:
1326 interp.convertIntegerC(obj, ident, loc, nic_->breakBeforePriority);
1328 case Identifier::keyBreakAfterPriority:
1329 interp.convertIntegerC(obj, ident, loc, nic_->breakAfterPriority);
1338 bool LeaderFlowObj::hasNonInheritedC(const Identifier *ident) const
1340 Identifier::SyntacticKey key;
1341 if (ident->syntacticKey(key)) {
1343 case Identifier::keyLength:
1344 case Identifier::keyBreakBeforePriority:
1345 case Identifier::keyBreakAfterPriority:
1354 FlowObj *LeaderFlowObj::copy(Collector &c) const
1356 return new (c) LeaderFlowObj(*this);
1359 class CharacterFlowObj : public FlowObj {
1361 void *operator new(size_t, Collector &c) {
1362 return c.allocateObject(1);
1365 CharacterFlowObj(const CharacterFlowObj &);
1366 void processInner(ProcessContext &);
1367 FlowObj *copy(Collector &) const;
1368 void setNonInheritedC(const Identifier *, ELObj *,
1369 const Location &, Interpreter &);
1370 bool setImplicitChar(ELObj *, const Location &, Interpreter &);
1371 bool hasNonInheritedC(const Identifier *) const;
1372 bool characterStyle(ProcessContext &, StyleObj *&style, FOTBuilder::CharacterNIC &nic) {
1377 bool isCharacter() { return 1; }
1379 Owner<FOTBuilder::CharacterNIC> nic_;
1382 CharacterFlowObj::CharacterFlowObj()
1383 : nic_(new FOTBuilder::CharacterNIC)
1387 CharacterFlowObj::CharacterFlowObj(const CharacterFlowObj &fo)
1388 : FlowObj(fo), nic_(new FOTBuilder::CharacterNIC(*fo.nic_))
1392 void CharacterFlowObj::processInner(ProcessContext &context)
1394 context.currentFOTBuilder().character(*nic_);
1397 bool FlowObj::setImplicitChar(ELObj *obj, const Location &loc,
1398 Interpreter &interp)
1405 bool CharacterFlowObj::setImplicitChar(ELObj *obj, const Location &loc,
1406 Interpreter &interp)
1408 Identifier *ident = interp.lookup(interp.makeStringC("char"));
1409 if (!(nic_->specifiedC & (1 << FOTBuilder::CharacterNIC::cChar))
1410 && interp.convertCharC(obj, ident, loc, nic_->ch)) {
1413 if (!(nic_->specifiedC & (1 << FOTBuilder::CharacterNIC::cIsSpace)))
1414 interp.convertBooleanC(
1415 interp.charProperty(interp.makeStringC("space?"),
1417 ident, loc, nic_->isSpace);
1419 if (!(nic_->specifiedC & (1 << FOTBuilder::CharacterNIC::cIsRecordEnd)))
1420 interp.convertBooleanC(
1421 interp.charProperty(interp.makeStringC("record-end?"),
1423 ident, loc, nic_->isRecordEnd);
1425 if (!(nic_->specifiedC & (1 << FOTBuilder::CharacterNIC::cIsInputTab)))
1426 interp.convertBooleanC(
1427 interp.charProperty(interp.makeStringC("input-tab?"),
1429 ident, loc, nic_->isInputTab);
1431 if (!(nic_->specifiedC & (1 << FOTBuilder::CharacterNIC::cIsInputWhitespace)))
1432 interp.convertBooleanC(
1433 interp.charProperty(interp.makeStringC("input-whitespace?"),
1435 ident, loc, nic_->isInputWhitespace);
1437 if (!(nic_->specifiedC & (1 << FOTBuilder::CharacterNIC::cIsPunct)))
1438 interp.convertBooleanC(
1439 interp.charProperty(interp.makeStringC("punct?"),
1441 ident, loc, nic_->isPunct);
1443 if (!(nic_->specifiedC & (1 << FOTBuilder::CharacterNIC::cIsDropAfterLineBreak)))
1444 interp.convertBooleanC(
1445 interp.charProperty(interp.makeStringC("drop-after-line-break?"),
1447 ident, loc, nic_->isDropAfterLineBreak);
1449 if (!(nic_->specifiedC & (1 << FOTBuilder::CharacterNIC::cIsDropUnlessBeforeLineBreak)))
1450 interp.convertBooleanC(
1451 interp.charProperty(interp.makeStringC("drop-unless-before-line-break?"),
1453 ident, loc, nic_->isDropUnlessBeforeLineBreak);
1455 if (!(nic_->specifiedC & (1 << FOTBuilder::CharacterNIC::cBreakBeforePriority)))
1456 interp.convertIntegerC(
1457 interp.charProperty(interp.makeStringC("break-before-priority"),
1459 ident, loc, nic_->breakBeforePriority);
1461 if (!(nic_->specifiedC & (1 << FOTBuilder::CharacterNIC::cBreakAfterPriority)))
1462 interp.convertIntegerC(
1463 interp.charProperty(interp.makeStringC("break-after-priority"),
1465 ident, loc, nic_->breakAfterPriority);
1467 if (!(nic_->specifiedC & (1 << FOTBuilder::CharacterNIC::cScript))) {
1468 ELObj *prop = interp.charProperty(interp.makeStringC("script"),
1470 if (prop == interp.makeFalse())
1474 if (interp.convertStringC(prop, ident, loc, tem))
1475 nic_->script = interp.storePublicId(tem.data(), tem.size(), loc);
1479 if (!(nic_->specifiedC & (1 << FOTBuilder::CharacterNIC::cGlyphId))) {
1480 ELObj *prop = interp.charProperty(interp.makeStringC("glyph-id"),
1482 if (prop == interp.makeFalse())
1483 nic_->glyphId = FOTBuilder::GlyphId();
1485 const FOTBuilder::GlyphId *p = prop->glyphId();
1491 if (!(nic_->specifiedC & (1 << FOTBuilder::CharacterNIC::cMathFontPosture))) {
1492 ELObj *prop = interp.charProperty(interp.makeStringC("math-font-posture"),
1494 static FOTBuilder::Symbol vals[] = {
1495 FOTBuilder::symbolFalse,
1496 FOTBuilder::symbolNotApplicable,
1497 FOTBuilder::symbolUpright,
1498 FOTBuilder::symbolOblique,
1499 FOTBuilder::symbolBackSlantedOblique,
1500 FOTBuilder::symbolItalic,
1501 FOTBuilder::symbolBackSlantedItalic,
1503 interp.convertEnumC(vals, SIZEOF(vals), prop, ident, loc, nic_->mathFontPosture);
1506 if (!(nic_->specifiedC & (1 << FOTBuilder::CharacterNIC::cMathClass))) {
1507 ELObj *prop = interp.charProperty(interp.makeStringC("math-class"),
1509 static FOTBuilder::Symbol vals[] = {
1510 FOTBuilder::symbolOrdinary,
1511 FOTBuilder::symbolOperator,
1512 FOTBuilder::symbolBinary,
1513 FOTBuilder::symbolRelation,
1514 FOTBuilder::symbolOpening,
1515 FOTBuilder::symbolClosing,
1516 FOTBuilder::symbolPunctuation,
1517 FOTBuilder::symbolInner,
1518 FOTBuilder::symbolSpace,
1520 interp.convertEnumC(vals, SIZEOF(vals), prop, ident, loc, nic_->mathClass);
1529 void CharacterFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
1530 const Location &loc, Interpreter &interp)
1532 Identifier::SyntacticKey key;
1533 if (ident->syntacticKey(key)) {
1535 case Identifier::keyIsSpace:
1536 if (interp.convertBooleanC(obj, ident, loc, nic_->isSpace))
1537 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cIsSpace);
1539 case Identifier::keyIsRecordEnd:
1540 if (interp.convertBooleanC(obj, ident, loc, nic_->isRecordEnd))
1541 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cIsRecordEnd);
1543 case Identifier::keyIsInputTab:
1544 if (interp.convertBooleanC(obj, ident, loc, nic_->isInputTab))
1545 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cIsInputTab);
1547 case Identifier::keyIsInputWhitespace:
1548 if (interp.convertBooleanC(obj, ident, loc, nic_->isInputWhitespace))
1549 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cIsInputWhitespace);
1551 case Identifier::keyIsPunct:
1552 if (interp.convertBooleanC(obj, ident, loc, nic_->isPunct))
1553 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cIsPunct);
1555 case Identifier::keyIsDropAfterLineBreak:
1556 if (interp.convertBooleanC(obj, ident, loc, nic_->isDropAfterLineBreak))
1557 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cIsDropAfterLineBreak);
1559 case Identifier::keyIsDropUnlessBeforeLineBreak:
1560 if (interp.convertBooleanC(obj, ident, loc, nic_->isDropUnlessBeforeLineBreak))
1561 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cIsDropUnlessBeforeLineBreak);
1563 case Identifier::keyBreakBeforePriority:
1564 if (interp.convertIntegerC(obj, ident, loc, nic_->breakBeforePriority))
1565 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cBreakBeforePriority);
1567 case Identifier::keyBreakAfterPriority:
1568 if (interp.convertIntegerC(obj, ident, loc, nic_->breakAfterPriority))
1569 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cBreakAfterPriority);
1571 case Identifier::keyScript:
1573 if (obj == interp.makeFalse())
1577 if (!interp.convertStringC(obj, ident, loc, tem))
1579 nic_->script = interp.storePublicId(tem.data(), tem.size(), loc);
1581 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cScript);
1584 case Identifier::keyChar:
1585 if (setImplicitChar(obj, loc, interp)) {
1586 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cChar);
1587 if (!(nic_->specifiedC & (1 << FOTBuilder::CharacterNIC::cIsInputTab)))
1588 nic_->isInputTab = 0;
1589 if (!(nic_->specifiedC & (1 << FOTBuilder::CharacterNIC::cIsInputWhitespace)))
1590 nic_->isInputWhitespace = 0;
1593 case Identifier::keyGlyphId:
1595 if (obj == interp.makeFalse()) {
1596 nic_->glyphId = FOTBuilder::GlyphId();
1597 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cGlyphId);
1600 const FOTBuilder::GlyphId *p = obj->glyphId();
1602 interp.setNextLocation(loc);
1603 interp.message(InterpreterMessages::invalidCharacteristicValue,
1604 StringMessageArg(ident->name()));
1608 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cGlyphId);
1611 case Identifier::keyMathFontPosture:
1613 static FOTBuilder::Symbol vals[] = {
1614 FOTBuilder::symbolFalse,
1615 FOTBuilder::symbolNotApplicable,
1616 FOTBuilder::symbolUpright,
1617 FOTBuilder::symbolOblique,
1618 FOTBuilder::symbolBackSlantedOblique,
1619 FOTBuilder::symbolItalic,
1620 FOTBuilder::symbolBackSlantedItalic,
1622 if (interp.convertEnumC(vals, SIZEOF(vals), obj, ident, loc, nic_->mathFontPosture))
1623 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cMathFontPosture);
1626 case Identifier::keyMathClass:
1628 static FOTBuilder::Symbol vals[] = {
1629 FOTBuilder::symbolOrdinary,
1630 FOTBuilder::symbolOperator,
1631 FOTBuilder::symbolBinary,
1632 FOTBuilder::symbolRelation,
1633 FOTBuilder::symbolOpening,
1634 FOTBuilder::symbolClosing,
1635 FOTBuilder::symbolPunctuation,
1636 FOTBuilder::symbolInner,
1637 FOTBuilder::symbolSpace,
1639 if (interp.convertEnumC(vals, SIZEOF(vals), obj, ident, loc, nic_->mathClass))
1640 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cMathClass);
1643 case Identifier::keyStretchFactor:
1644 interp.convertRealC(obj, ident, loc, nic_->stretchFactor);
1653 if (ident->charNICDefined(part, loc))
1659 bool CharacterFlowObj::hasNonInheritedC(const Identifier *ident) const
1661 Identifier::SyntacticKey key;
1662 if (ident->syntacticKey(key)) {
1664 case Identifier::keyChar:
1665 case Identifier::keyGlyphId:
1666 case Identifier::keyIsSpace:
1667 case Identifier::keyIsRecordEnd:
1668 case Identifier::keyIsInputTab:
1669 case Identifier::keyIsInputWhitespace:
1670 case Identifier::keyIsPunct:
1671 case Identifier::keyIsDropAfterLineBreak:
1672 case Identifier::keyIsDropUnlessBeforeLineBreak:
1673 case Identifier::keyScript:
1674 case Identifier::keyMathClass:
1675 case Identifier::keyMathFontPosture:
1676 case Identifier::keyStretchFactor:
1677 case Identifier::keyBreakBeforePriority:
1678 case Identifier::keyBreakAfterPriority:
1686 if (ident->charNICDefined(part, loc))
1691 FlowObj *CharacterFlowObj::copy(Collector &c) const
1693 return new (c) CharacterFlowObj(*this);
1696 class MathSequenceFlowObj : public CompoundFlowObj {
1698 MathSequenceFlowObj() { }
1699 void processInner(ProcessContext &context) {
1700 FOTBuilder &fotb = context.currentFOTBuilder();
1701 fotb.startMathSequence();
1702 CompoundFlowObj::processInner(context);
1703 fotb.endMathSequence();
1705 FlowObj *copy(Collector &c) const {
1706 return new (c) MathSequenceFlowObj(*this);
1710 class FractionFlowObj : public CompoundFlowObj {
1712 FractionFlowObj() { }
1713 void processInner(ProcessContext &);
1714 FlowObj *copy(Collector &) const;
1717 void FractionFlowObj::processInner(ProcessContext &context)
1719 FOTBuilder &fotb = context.currentFOTBuilder();
1720 Vector<FOTBuilder *> fotbs(2);
1721 fotb.startFraction(fotbs[0], fotbs[1]);
1723 StyleObj *fractionBarStyle = 0;
1725 = context.currentStyleStack().actual(context.vm().interp->fractionBarC(),
1726 *context.vm().interp, dep)->asSosofo();
1728 sosofo->ruleStyle(context, fractionBarStyle);
1729 if (fractionBarStyle)
1730 context.currentStyleStack().push(fractionBarStyle, context.vm(), fotb);
1732 if (fractionBarStyle)
1733 context.currentStyleStack().pop();
1734 Vector<SymbolObj *> labels(2);
1735 labels[0] = context.vm().interp->portName(Interpreter::portNumerator);
1736 labels[1] = context.vm().interp->portName(Interpreter::portDenominator);
1737 context.pushPorts(0, labels, fotbs);
1738 // Fraction flow object doesn't have principal port,
1739 // so clear the current connection.
1740 CompoundFlowObj::processInner(context);
1745 FlowObj *FractionFlowObj::copy(Collector &c) const
1747 return new (c) FractionFlowObj(*this);
1750 class UnmathFlowObj : public CompoundFlowObj {
1753 void processInner(ProcessContext &context) {
1754 FOTBuilder &fotb = context.currentFOTBuilder();
1756 CompoundFlowObj::processInner(context);
1759 FlowObj *copy(Collector &c) const {
1760 return new (c) UnmathFlowObj(*this);
1764 class SuperscriptFlowObj : public CompoundFlowObj {
1766 SuperscriptFlowObj() { }
1767 void processInner(ProcessContext &context) {
1768 FOTBuilder &fotb = context.currentFOTBuilder();
1769 fotb.startSuperscript();
1770 CompoundFlowObj::processInner(context);
1771 fotb.endSuperscript();
1773 FlowObj *copy(Collector &c) const {
1774 return new (c) SuperscriptFlowObj(*this);
1778 class SubscriptFlowObj : public CompoundFlowObj {
1780 SubscriptFlowObj() { }
1781 void processInner(ProcessContext &context) {
1782 FOTBuilder &fotb = context.currentFOTBuilder();
1783 fotb.startSubscript();
1784 CompoundFlowObj::processInner(context);
1785 fotb.endSubscript();
1787 FlowObj *copy(Collector &c) const {
1788 return new (c) SubscriptFlowObj(*this);
1792 class ScriptFlowObj : public CompoundFlowObj {
1795 void processInner(ProcessContext &);
1796 FlowObj *copy(Collector &c) const {
1797 return new (c) ScriptFlowObj(*this);
1802 void ScriptFlowObj::processInner(ProcessContext &context)
1804 FOTBuilder &fotb = context.currentFOTBuilder();
1805 Vector<FOTBuilder *> fotbs(6);
1806 fotb.startScript(fotbs[0], fotbs[1], fotbs[2], fotbs[3],
1807 fotbs[4], fotbs[5]);
1808 Vector<SymbolObj *> labels(6);
1809 labels[0] = context.vm().interp->portName(Interpreter::portPreSup);
1810 labels[1] = context.vm().interp->portName(Interpreter::portPreSub);
1811 labels[2] = context.vm().interp->portName(Interpreter::portPostSup);
1812 labels[3] = context.vm().interp->portName(Interpreter::portPostSub);
1813 labels[4] = context.vm().interp->portName(Interpreter::portMidSup);
1814 labels[5] = context.vm().interp->portName(Interpreter::portMidSub);
1815 context.pushPorts(1, labels, fotbs);
1816 CompoundFlowObj::processInner(context);
1821 class MarkFlowObj : public CompoundFlowObj {
1824 void processInner(ProcessContext &);
1825 FlowObj *copy(Collector &c) const {
1826 return new (c) MarkFlowObj(*this);
1830 void MarkFlowObj::processInner(ProcessContext &context)
1832 FOTBuilder &fotb = context.currentFOTBuilder();
1833 Vector<FOTBuilder *> fotbs(2);
1834 fotb.startMark(fotbs[0], fotbs[1]);
1835 Vector<SymbolObj *> labels(2);
1836 labels[0] = context.vm().interp->portName(Interpreter::portOverMark);
1837 labels[1] = context.vm().interp->portName(Interpreter::portUnderMark);
1838 context.pushPorts(1, labels, fotbs);
1839 CompoundFlowObj::processInner(context);
1844 class FenceFlowObj : public CompoundFlowObj {
1847 void processInner(ProcessContext &);
1848 FlowObj *copy(Collector &c) const {
1849 return new (c) FenceFlowObj(*this);
1853 void FenceFlowObj::processInner(ProcessContext &context)
1855 FOTBuilder &fotb = context.currentFOTBuilder();
1856 Vector<FOTBuilder *> fotbs(2);
1857 fotb.startFence(fotbs[0], fotbs[1]);
1858 Vector<SymbolObj *> labels(2);
1859 labels[0] = context.vm().interp->portName(Interpreter::portOpen);
1860 labels[1] = context.vm().interp->portName(Interpreter::portClose);
1861 context.pushPorts(1, labels, fotbs);
1862 CompoundFlowObj::processInner(context);
1867 class RadicalFlowObj : public CompoundFlowObj {
1869 RadicalFlowObj() : radical_(0) { }
1870 void processInner(ProcessContext &);
1871 FlowObj *copy(Collector &c) const {
1872 return new (c) RadicalFlowObj(*this);
1874 void setNonInheritedC(const Identifier *, ELObj *,
1875 const Location &, Interpreter &);
1876 bool hasNonInheritedC(const Identifier *) const;
1877 void traceSubObjects(Collector &c) const {
1879 CompoundFlowObj::traceSubObjects(c);
1882 SosofoObj *radical_;
1885 void RadicalFlowObj::processInner(ProcessContext &context)
1887 FOTBuilder &fotb = context.currentFOTBuilder();
1888 Vector<FOTBuilder *> fotbs(1);
1889 fotb.startRadical(fotbs[0]);
1891 FOTBuilder::CharacterNIC nic;
1892 if (radical_ && radical_->characterStyle(context, style, nic)) {
1894 context.currentStyleStack().push(style, context.vm(), fotb);
1895 fotb.radicalRadical(nic);
1897 context.currentStyleStack().pop();
1900 fotb.radicalRadicalDefaulted();
1901 Vector<SymbolObj *> labels(1);
1902 labels[0] = context.vm().interp->portName(Interpreter::portDegree);
1903 context.pushPorts(1, labels, fotbs);
1904 CompoundFlowObj::processInner(context);
1909 bool RadicalFlowObj::hasNonInheritedC(const Identifier *ident) const
1911 Identifier::SyntacticKey key;
1912 return ident->syntacticKey(key) && key == Identifier::keyRadical;
1915 void RadicalFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
1916 const Location &loc, Interpreter &interp)
1918 radical_ = obj->asSosofo();
1919 if (!radical_ || !radical_->isCharacter()) {
1920 interp.setNextLocation(loc);
1921 interp.message(InterpreterMessages::invalidCharacteristicValue,
1922 StringMessageArg(ident->name()));
1926 class MathOperatorFlowObj : public CompoundFlowObj {
1928 MathOperatorFlowObj() { }
1929 void processInner(ProcessContext &);
1930 FlowObj *copy(Collector &c) const {
1931 return new (c) MathOperatorFlowObj(*this);
1935 void MathOperatorFlowObj::processInner(ProcessContext &context)
1937 FOTBuilder &fotb = context.currentFOTBuilder();
1938 Vector<FOTBuilder *> fotbs(3);
1939 fotb.startMathOperator(fotbs[0], fotbs[1], fotbs[2]);
1940 Vector<SymbolObj *> labels(3);
1941 labels[0] = context.vm().interp->portName(Interpreter::portOperator);
1942 labels[1] = context.vm().interp->portName(Interpreter::portLowerLimit);
1943 labels[2] = context.vm().interp->portName(Interpreter::portUpperLimit);
1944 context.pushPorts(1, labels, fotbs);
1945 CompoundFlowObj::processInner(context);
1947 fotb.endMathOperator();
1950 class GridFlowObj : public CompoundFlowObj {
1952 void *operator new(size_t, Collector &c) {
1953 return c.allocateObject(1);
1956 GridFlowObj(const GridFlowObj &);
1957 void processInner(ProcessContext &);
1958 FlowObj *copy(Collector &c) const {
1959 return new (c) GridFlowObj(*this);
1961 void setNonInheritedC(const Identifier *, ELObj *,
1962 const Location &, Interpreter &);
1963 bool hasNonInheritedC(const Identifier *) const;
1965 Owner<FOTBuilder::GridNIC> nic_;
1968 GridFlowObj::GridFlowObj()
1969 : nic_(new FOTBuilder::GridNIC)
1973 GridFlowObj::GridFlowObj(const GridFlowObj &fo)
1974 : CompoundFlowObj(fo), nic_(new FOTBuilder::GridNIC(*fo.nic_))
1978 void GridFlowObj::processInner(ProcessContext &context)
1980 FOTBuilder &fotb = context.currentFOTBuilder();
1981 fotb.startGrid(*nic_);
1982 CompoundFlowObj::processInner(context);
1986 void GridFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
1987 const Location &loc, Interpreter &interp)
1990 if (!interp.convertIntegerC(obj, ident, loc, tem))
1993 interp.setNextLocation(loc);
1994 interp.message(InterpreterMessages::invalidCharacteristicValue,
1995 StringMessageArg(ident->name()));
1998 Identifier::SyntacticKey key;
1999 if (ident->syntacticKey(key)) {
2001 case Identifier::keyGridNColumns:
2002 nic_->nColumns = tem;
2004 case Identifier::keyGridNRows:
2014 bool GridFlowObj::hasNonInheritedC(const Identifier *ident) const
2016 Identifier::SyntacticKey key;
2017 if (ident->syntacticKey(key)) {
2019 case Identifier::keyGridNColumns:
2020 case Identifier::keyGridNRows:
2029 class GridCellFlowObj : public CompoundFlowObj {
2031 void *operator new(size_t, Collector &c) {
2032 return c.allocateObject(1);
2035 GridCellFlowObj(const GridCellFlowObj &);
2036 void processInner(ProcessContext &);
2037 FlowObj *copy(Collector &c) const {
2038 return new (c) GridCellFlowObj(*this);
2040 void setNonInheritedC(const Identifier *, ELObj *,
2041 const Location &, Interpreter &);
2042 bool hasNonInheritedC(const Identifier *) const;
2044 Owner<FOTBuilder::GridCellNIC> nic_;
2047 GridCellFlowObj::GridCellFlowObj()
2048 : nic_(new FOTBuilder::GridCellNIC)
2052 GridCellFlowObj::GridCellFlowObj(const GridCellFlowObj &fo)
2053 : CompoundFlowObj(fo), nic_(new FOTBuilder::GridCellNIC(*fo.nic_))
2057 void GridCellFlowObj::processInner(ProcessContext &context)
2059 FOTBuilder &fotb = context.currentFOTBuilder();
2060 fotb.startGridCell(*nic_);
2061 CompoundFlowObj::processInner(context);
2065 void GridCellFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
2066 const Location &loc, Interpreter &interp)
2069 if (!interp.convertIntegerC(obj, ident, loc, tem))
2072 interp.setNextLocation(loc);
2073 interp.message(InterpreterMessages::invalidCharacteristicValue,
2074 StringMessageArg(ident->name()));
2077 Identifier::SyntacticKey key;
2078 if (ident->syntacticKey(key)) {
2080 case Identifier::keyColumnNumber:
2081 nic_->columnNumber = tem;
2083 case Identifier::keyRowNumber:
2084 nic_->rowNumber = tem;
2093 bool GridCellFlowObj::hasNonInheritedC(const Identifier *ident) const
2095 Identifier::SyntacticKey key;
2096 if (ident->syntacticKey(key)) {
2098 case Identifier::keyColumnNumber:
2099 case Identifier::keyRowNumber:
2108 class TableFlowObj : public CompoundFlowObj {
2110 void *operator new(size_t, Collector &c) {
2111 return c.allocateObject(1);
2113 struct NIC : public FOTBuilder::TableNIC {
2114 NIC() : beforeRowBorder(0), afterRowBorder(0),
2115 beforeColumnBorder(0), afterColumnBorder(0) { }
2116 StyleObj *beforeRowBorder;
2117 StyleObj *afterRowBorder;
2118 StyleObj *beforeColumnBorder;
2119 StyleObj *afterColumnBorder;
2121 TableFlowObj() : nic_(new NIC) { }
2122 TableFlowObj(const TableFlowObj &fo) : CompoundFlowObj(fo), nic_(new NIC(*fo.nic_)) { }
2123 void processInner(ProcessContext &context) {
2124 context.startTable();
2125 FOTBuilder &fotb = context.currentFOTBuilder();
2126 fotb.startTable(*nic_);
2127 Interpreter &interp = *context.vm().interp;
2129 ELObj *obj = context.currentStyleStack().actual(interp.tableBorderC(), interp, dep);
2130 StyleObj *borderStyle;
2131 if (obj == interp.makeFalse())
2132 borderStyle = interp.borderFalseStyle();
2133 else if (obj == interp.makeTrue())
2134 borderStyle = interp.borderTrueStyle();
2136 SosofoObj *sosofo = obj->asSosofo();
2137 if (!sosofo || !sosofo->tableBorderStyle(borderStyle))
2140 border(nic_->beforeRowBorder, borderStyle, &FOTBuilder::tableBeforeRowBorder, context);
2141 border(nic_->afterRowBorder, borderStyle, &FOTBuilder::tableAfterRowBorder, context);
2142 border(nic_->beforeColumnBorder, borderStyle, &FOTBuilder::tableBeforeColumnBorder, context);
2143 border(nic_->afterColumnBorder, borderStyle, &FOTBuilder::tableAfterColumnBorder, context);
2144 CompoundFlowObj::processInner(context);
2145 if (context.inTableRow())
2146 context.endTableRow();
2150 FlowObj *copy(Collector &c) const {
2151 return new (c) TableFlowObj(*this);
2153 bool hasNonInheritedC(const Identifier *ident) const {
2154 Identifier::SyntacticKey key;
2155 if (ident->syntacticKey(key)) {
2157 case Identifier::keyBeforeRowBorder:
2158 case Identifier::keyAfterRowBorder:
2159 case Identifier::keyBeforeColumnBorder:
2160 case Identifier::keyAfterColumnBorder:
2161 case Identifier::keyTableWidth:
2167 return isDisplayNIC(ident);
2169 void setNonInheritedC(const Identifier *ident, ELObj *obj,
2170 const Location &loc, Interpreter &interp) {
2171 if (setDisplayNIC(*nic_, ident, obj, loc, interp))
2173 Identifier::SyntacticKey key;
2174 if (!ident->syntacticKey(key))
2176 if (key == Identifier::keyTableWidth) {
2177 if (obj == interp.makeFalse())
2178 nic_->widthType = FOTBuilder::TableNIC::widthMinimum;
2179 else if (interp.convertLengthSpecC(obj, ident, loc, nic_->width))
2180 nic_->widthType = FOTBuilder::TableNIC::widthExplicit;
2184 SosofoObj *sosofo = obj->asSosofo();
2185 if (!sosofo || !sosofo->tableBorderStyle(style)) {
2187 if (!interp.convertBooleanC(obj, ident, loc, b))
2189 style = b ? interp.borderTrueStyle() : interp.borderFalseStyle();
2192 case Identifier::keyBeforeRowBorder:
2193 nic_->beforeRowBorder = style;
2195 case Identifier::keyAfterRowBorder:
2196 nic_->afterRowBorder = style;
2198 case Identifier::keyBeforeColumnBorder:
2199 nic_->beforeColumnBorder = style;
2201 case Identifier::keyAfterColumnBorder:
2202 nic_->afterColumnBorder = style;
2209 void border(StyleObj *style, StyleObj *style2,
2210 void (FOTBuilder::*setter)(), ProcessContext &context) {
2211 FOTBuilder &fotb = context.currentFOTBuilder();
2215 context.currentStyleStack().push(style, context.vm(), fotb);
2218 context.currentStyleStack().pop();
2223 class TablePartFlowObj : public CompoundFlowObj {
2225 void *operator new(size_t, Collector &c) {
2226 return c.allocateObject(1);
2228 TablePartFlowObj() : nic_(new FOTBuilder::TablePartNIC) { }
2229 TablePartFlowObj(const TablePartFlowObj &fo)
2230 : CompoundFlowObj(fo), nic_(new FOTBuilder::TablePartNIC(*fo.nic_)) { }
2231 void processInner(ProcessContext &context) {
2232 context.startTablePart();
2233 FOTBuilder &fotb = context.currentFOTBuilder();
2234 Vector<FOTBuilder *> fotbs(2);
2235 fotb.startTablePart(*nic_, fotbs[0], fotbs[1]);
2236 Vector<SymbolObj *> labels(2);
2237 labels[0] = context.vm().interp->portName(Interpreter::portHeader);
2238 labels[1] = context.vm().interp->portName(Interpreter::portFooter);
2239 context.pushPorts(1, labels, fotbs);
2240 CompoundFlowObj::processInner(context);
2242 if (context.inTableRow())
2243 context.endTableRow();
2244 context.endTablePart();
2245 fotb.endTablePart();
2247 FlowObj *copy(Collector &c) const {
2248 return new (c) TablePartFlowObj(*this);
2250 void setNonInheritedC(const Identifier *ident, ELObj *obj,
2251 const Location &loc, Interpreter &interp) {
2252 setDisplayNIC(*nic_, ident, obj, loc, interp);
2254 bool hasNonInheritedC(const Identifier *ident) const {
2255 if (!isDisplayNIC(ident))
2257 Identifier::SyntacticKey key;
2258 ident->syntacticKey(key);
2259 if (key == Identifier::keyPositionPreference)
2264 Owner<FOTBuilder::TablePartNIC> nic_;
2267 class TableColumnFlowObj : public FlowObj {
2269 void *operator new(size_t, Collector &c) {
2270 return c.allocateObject(1);
2272 struct NIC : public FOTBuilder::TableColumnNIC {
2273 NIC() : hasColumnNumber(0) { }
2274 bool hasColumnNumber;
2276 TableColumnFlowObj() : nic_(new NIC) { }
2277 TableColumnFlowObj(const TableColumnFlowObj &fo) : FlowObj(fo), nic_(new NIC(*fo.nic_)) { }
2278 void processInner(ProcessContext &context) {
2279 if (nic_->hasColumnNumber) {
2280 context.currentFOTBuilder().tableColumn(*nic_);
2281 context.addTableColumn(nic_->columnIndex, nic_->nColumnsSpanned, style_);
2284 FOTBuilder::TableColumnNIC nic(*nic_);
2285 nic.columnIndex = context.currentTableColumn();
2286 context.currentFOTBuilder().tableColumn(nic);
2287 context.addTableColumn(nic.columnIndex, nic_->nColumnsSpanned, style_);
2290 FlowObj *copy(Collector &c) const {
2291 return new (c) TableColumnFlowObj(*this);
2293 bool hasNonInheritedC(const Identifier *ident) const {
2294 Identifier::SyntacticKey key;
2295 if (ident->syntacticKey(key)) {
2297 case Identifier::keyColumnNumber:
2298 case Identifier::keyNColumnsSpanned:
2299 case Identifier::keyWidth:
2307 void setNonInheritedC(const Identifier *ident, ELObj *obj,
2308 const Location &loc, Interpreter &interp) {
2309 Identifier::SyntacticKey key;
2310 if (ident->syntacticKey(key)) {
2312 case Identifier::keyColumnNumber:
2313 case Identifier::keyNColumnsSpanned:
2316 if (!interp.convertIntegerC(obj, ident, loc, n))
2319 interp.setNextLocation(loc);
2320 interp.message(InterpreterMessages::invalidCharacteristicValue,
2321 StringMessageArg(ident->name()));
2324 if (key == Identifier::keyColumnNumber) {
2325 nic_->columnIndex = n - 1;
2326 nic_->hasColumnNumber = 1;
2329 nic_->nColumnsSpanned = n;
2332 case Identifier::keyWidth:
2334 const LengthSpec *ls = obj->lengthSpec();
2336 // width is a TableLengthSpec not just a LengthSpec
2337 if (ls->convert(nic_->width))
2340 interp.invalidCharacteristicValue(ident, loc);
2342 else if (interp.convertLengthSpecC(obj, ident, loc, nic_->width))
2356 class TableRowFlowObj : public CompoundFlowObj {
2358 TableRowFlowObj() { }
2359 void pushStyle(ProcessContext &, unsigned &) { }
2360 void popStyle(ProcessContext &, unsigned) { }
2361 void processInner(ProcessContext &context) {
2362 if (!context.inTable()) {
2364 context.vm().interp->message(InterpreterMessages::tableRowOutsideTable);
2365 CompoundFlowObj::processInner(context);
2368 if (context.inTableRow())
2369 context.endTableRow();
2370 context.startTableRow(style_);
2371 CompoundFlowObj::processInner(context);
2372 if (context.inTableRow())
2373 context.endTableRow();
2374 // else FIXME give an error
2375 // must have used ends-row? in a table-row
2377 FlowObj *copy(Collector &c) const {
2378 return new (c) TableRowFlowObj(*this);
2382 class TableCellFlowObj : public CompoundFlowObj {
2384 void *operator new(size_t, Collector &c) {
2385 return c.allocateObject(1);
2387 struct NIC : FOTBuilder::TableCellNIC {
2388 NIC() : startsRow(0), endsRow(0), hasColumnNumber(0) { }
2389 bool hasColumnNumber;
2393 TableCellFlowObj(bool missing = 0) : nic_(new NIC) {
2397 TableCellFlowObj(const TableCellFlowObj &fo) : CompoundFlowObj(fo), nic_(new NIC(*fo.nic_)) { }
2398 void pushStyle(ProcessContext &context, unsigned &nPush) {
2399 if (context.inTableRow()) {
2400 if (nic_->startsRow) {
2401 context.endTableRow();
2402 context.startTableRow(0);
2406 context.startTableRow(0);
2407 unsigned columnNumber
2408 = nic_->hasColumnNumber ? nic_->columnIndex : context.currentTableColumn();
2409 StyleObj *columnStyle = context.tableColumnStyle(columnNumber, nic_->nColumnsSpanned);
2411 context.currentStyleStack().push(columnStyle, context.vm(), context.currentFOTBuilder());
2412 context.currentFOTBuilder().startSequence();
2415 StyleObj *rowStyle = context.tableRowStyle();
2417 context.currentStyleStack().push(rowStyle, context.vm(), context.currentFOTBuilder());
2418 context.currentFOTBuilder().startSequence();
2421 CompoundFlowObj::pushStyle(context, nPush);
2423 void popStyle(ProcessContext &context, unsigned nPush) {
2424 CompoundFlowObj::popStyle(context, nPush);
2425 for (unsigned i = 0; i < nPush; i++) {
2426 context.currentFOTBuilder().endSequence();
2427 context.currentStyleStack().pop();
2430 context.endTableRow();
2432 void processInner(ProcessContext &context) {
2433 if (!context.inTable()) {
2435 context.vm().interp->message(InterpreterMessages::tableCellOutsideTable);
2436 CompoundFlowObj::processInner(context);
2439 FOTBuilder &fotb = context.currentFOTBuilder();
2440 if (!nic_->hasColumnNumber) {
2441 FOTBuilder::TableCellNIC nic(*nic_);
2442 nic.columnIndex = context.currentTableColumn();
2443 fotb.startTableCell(nic);
2445 context.noteTableCell(nic.columnIndex, nic.nColumnsSpanned, nic.nRowsSpanned);
2448 fotb.startTableCell(*nic_);
2450 context.noteTableCell(nic_->columnIndex, nic_->nColumnsSpanned, nic_->nRowsSpanned);
2452 Interpreter &interp = *context.vm().interp;
2453 border(interp.cellBeforeRowBorderC(), &FOTBuilder::tableCellBeforeRowBorder, context);
2454 border(interp.cellAfterRowBorderC(), &FOTBuilder::tableCellAfterRowBorder, context);
2455 border(interp.cellBeforeColumnBorderC(), &FOTBuilder::tableCellBeforeColumnBorder, context);
2456 border(interp.cellAfterColumnBorderC(), &FOTBuilder::tableCellAfterColumnBorder, context);
2457 CompoundFlowObj::processInner(context);
2458 fotb.endTableCell();
2460 FlowObj *copy(Collector &c) const {
2461 return new (c) TableCellFlowObj(*this);
2463 bool hasNonInheritedC(const Identifier *ident) const {
2464 Identifier::SyntacticKey key;
2465 if (ident->syntacticKey(key)) {
2467 case Identifier::keyNRowsSpanned:
2475 bool hasPseudoNonInheritedC(const Identifier *ident) const {
2476 Identifier::SyntacticKey key;
2477 if (ident->syntacticKey(key)) {
2479 case Identifier::keyColumnNumber:
2480 case Identifier::keyNColumnsSpanned:
2481 case Identifier::keyIsStartsRow:
2482 case Identifier::keyIsEndsRow:
2490 void setNonInheritedC(const Identifier *ident, ELObj *obj,
2491 const Location &loc, Interpreter &interp) {
2492 Identifier::SyntacticKey key;
2493 if (ident->syntacticKey(key)) {
2495 case Identifier::keyIsStartsRow:
2496 interp.convertBooleanC(obj, ident, loc, nic_->startsRow);
2498 case Identifier::keyIsEndsRow:
2499 interp.convertBooleanC(obj, ident, loc, nic_->endsRow);
2501 case Identifier::keyColumnNumber:
2502 case Identifier::keyNColumnsSpanned:
2503 case Identifier::keyNRowsSpanned:
2506 if (!interp.convertIntegerC(obj, ident, loc, n))
2509 interp.setNextLocation(loc);
2510 interp.message(InterpreterMessages::invalidCharacteristicValue,
2511 StringMessageArg(ident->name()));
2514 if (key == Identifier::keyColumnNumber) {
2515 nic_->columnIndex = n - 1;
2516 nic_->hasColumnNumber = 1;
2518 else if (key == Identifier::keyNColumnsSpanned)
2519 nic_->nColumnsSpanned = n;
2521 nic_->nRowsSpanned = n;
2531 void border(const ConstPtr<InheritedC> &ic, void (FOTBuilder::*setter)(),
2532 ProcessContext &context) {
2533 Interpreter &interp = *context.vm().interp;
2535 ELObj *obj = context.currentStyleStack().actual(ic, interp, dep);
2537 if (obj == interp.makeFalse())
2538 style = interp.borderFalseStyle();
2539 else if (obj == interp.makeTrue())
2540 style = interp.borderTrueStyle();
2542 SosofoObj *sosofo = obj->asSosofo();
2543 if (!sosofo || !sosofo->tableBorderStyle(style))
2546 FOTBuilder &fotb = context.currentFOTBuilder();
2548 context.currentStyleStack().push(style, context.vm(), fotb);
2551 context.currentStyleStack().pop();
2556 class TableBorderFlowObj : public FlowObj {
2558 TableBorderFlowObj() { }
2559 void process(ProcessContext &) { }
2560 void processInner(ProcessContext &) { }
2561 bool tableBorderStyle(StyleObj *&style) {
2565 FlowObj *copy(Collector &c) const {
2566 return new (c) TableBorderFlowObj(*this);
2571 void ProcessContext::startTable()
2573 tableStack_.insert(new Table);
2576 void ProcessContext::endTable()
2579 delete tableStack_.get();
2582 void ProcessContext::coverSpannedRows()
2584 // Generate empty cells to cover any remaining vertical spans
2585 Table *table = tableStack_.head();
2589 for (size_t i = 0; i < table->covered.size(); i++)
2590 if (table->covered[i] > n)
2591 n = table->covered[i];
2592 for (; n > 0; n--) {
2593 SosofoObj *content = new (*vm().interp) EmptySosofoObj;
2594 ELObjDynamicRoot protect(*vm().interp, content);
2595 TableRowFlowObj *row = new (*vm().interp) TableRowFlowObj;
2596 row->setContent(content);
2598 row->process(*this);
2602 void ProcessContext::startTablePart()
2604 Table *table = tableStack_.head();
2606 table->currentColumn = 0;
2607 table->rowStyle = 0;
2608 table->columnStyles.clear();
2609 table->covered.clear();
2610 table->nColumns = 0;
2614 void ProcessContext::endTablePart()
2619 void ProcessContext::addTableColumn(unsigned columnIndex, unsigned span, StyleObj *style)
2621 Table *table = tableStack_.head();
2623 table->currentColumn = columnIndex + span;
2624 if (columnIndex >= table->columnStyles.size())
2625 table->columnStyles.resize(columnIndex + 1);
2626 Vector<StyleObj *> &tem = table->columnStyles[columnIndex];
2628 while (tem.size() < span)
2629 tem.push_back((StyleObj *)0);
2630 tem[span - 1] = style;
2635 unsigned ProcessContext::currentTableColumn()
2637 Table *table = tableStack_.head();
2639 return table->currentColumn;
2643 void ProcessContext::noteTableCell(unsigned colIndex, unsigned colSpan, unsigned rowSpan)
2645 Table *table = tableStack_.head();
2648 table->currentColumn = colIndex + colSpan;
2649 Vector<unsigned> &covered = table->covered;
2650 for (size_t i = covered.size(); i < colIndex + colSpan; i++)
2651 covered.push_back(0);
2652 for (size_t i = 0; i < colSpan; i++)
2653 covered[colIndex + i] = rowSpan;
2654 if (colIndex + colSpan > table->nColumns)
2655 table->nColumns = colIndex + colSpan;
2658 StyleObj *ProcessContext::tableColumnStyle(unsigned columnIndex, unsigned span)
2660 Table *table = tableStack_.head();
2662 if (columnIndex < table->columnStyles.size()) {
2663 Vector<StyleObj *> &tem = table->columnStyles[columnIndex];
2664 if (span > 0 && span <= tem.size())
2665 return tem[span - 1];
2671 StyleObj *ProcessContext::tableRowStyle()
2673 Table *table = tableStack_.head();
2675 return table->rowStyle;
2679 void ProcessContext::startTableRow(StyleObj *style)
2681 Table *table = tableStack_.head();
2683 table->rowStyle = style;
2684 table->currentColumn = 0;
2685 table->inTableRow = 1;
2686 table->rowConnectableLevel = connectionStack_.head()->connectableLevel;
2688 currentFOTBuilder().startTableRow();
2691 void ProcessContext::endTableRow()
2693 Table *table = tableStack_.head();
2695 // Fill in blank cells
2696 Vector<unsigned> &covered = table->covered;
2697 for (size_t i = 0; i < table->nColumns + 1; i++) {
2698 if (i >= covered.size() || !covered[i]) {
2699 table->currentColumn = i;
2700 SosofoObj *content = new (*vm().interp) EmptySosofoObj;
2701 ELObjDynamicRoot protect(*vm().interp, content);
2702 // The last cell is a dummy one
2703 TableCellFlowObj *cell = new (*vm().interp) TableCellFlowObj(i >= table->nColumns);
2704 cell->setContent(content);
2706 cell->process(*this);
2708 // cell->process() will cover it
2709 if (i < table->nColumns)
2712 table->inTableRow = 0;
2714 currentFOTBuilder().endTableRow();
2717 bool ProcessContext::inTableRow()
2719 Table *table = tableStack_.head();
2721 return table->inTableRow;
2725 ProcessContext::Table::Table()
2726 : rowStyle(0), currentColumn(0), inTableRow(0), nColumns(0)
2731 // Flow object classes declared with declare-flow-object-class
2732 // that we don't know about are assumed to have one principal port
2733 // and accept any non-inherited characteristic.
2735 class UnknownFlowObj : public CompoundFlowObj {
2737 UnknownFlowObj() { }
2738 FlowObj *copy(Collector &c) const {
2739 return new (c) UnknownFlowObj(*this);
2741 void setNonInheritedC(const Identifier *, ELObj *,
2742 const Location &, Interpreter &) { }
2743 bool hasNonInheritedC(const Identifier *ident) const {
2744 Identifier::SyntacticKey syn;
2745 if (ident->syntacticKey(syn)
2746 && (syn == Identifier::keyLabel || syn == Identifier::keyContentMap))
2748 if (!ident->inheritedC().isNull())
2754 class FormattingInstructionFlowObj : public FlowObj {
2756 void *operator new(size_t, Collector &c) {
2757 return c.allocateObject(1);
2759 FormattingInstructionFlowObj() { }
2760 void processInner(ProcessContext &context) {
2761 context.currentFOTBuilder().formattingInstruction(data_);
2763 FlowObj *copy(Collector &c) const {
2764 return new (c) FormattingInstructionFlowObj(*this);
2766 void setNonInheritedC(const Identifier *ident, ELObj *obj,
2767 const Location &loc, Interpreter &interp) {
2768 interp.convertStringC(obj, ident, loc, data_);
2770 bool hasNonInheritedC(const Identifier *ident) const {
2771 Identifier::SyntacticKey key;
2772 return ident->syntacticKey(key) && key == Identifier::keyData;
2778 class ELObjExtensionFlowObjValue : public FOTBuilder::ExtensionFlowObj::Value {
2780 ELObjExtensionFlowObjValue(const Identifier *ident, ELObj *obj,
2781 const Location &loc, Interpreter &interp)
2782 : ident_(ident), obj_(obj), loc_(&loc), interp_(&interp) { }
2783 bool convertString(StringC &result) const {
2784 return interp_->convertStringC(obj_, ident_, *loc_, result);
2786 bool convertStringPairList(Vector<StringC> &v) const {
2791 PairObj *pair = obj->asPair();
2795 PairObj *att = pair->car()->asPair();
2800 if (!att->car()->stringData(s, n))
2802 v.resize(v.size() + 1);
2803 v.back().assign(s, n);
2804 att = att->cdr()->asPair();
2805 if (!att || !att->car()->stringData(s, n) || !att->cdr()->isNil()) {
2806 v.resize(v.size() - 1);
2809 v.resize(v.size() + 1);
2810 v.back().assign(s, n);
2812 interp_->setNextLocation(*loc_);
2813 interp_->message(InterpreterMessages::invalidCharacteristicValue,
2814 StringMessageArg(ident_->name()));
2817 bool convertStringList(Vector<StringC> &v) const {
2822 PairObj *pair = obj->asPair();
2827 if (!pair->car()->stringData(s, n))
2829 v.resize(v.size() + 1);
2830 v.back().assign(s, n);
2833 interp_->setNextLocation(*loc_);
2834 interp_->message(InterpreterMessages::invalidCharacteristicValue,
2835 StringMessageArg(ident_->name()));
2838 bool convertBoolean(bool &result) const {
2839 return interp_->convertBooleanC(obj_, ident_, *loc_, result);
2843 const Identifier *ident_;
2844 const Location *loc_;
2845 Interpreter *interp_;
2848 class ExtensionFlowObj : public FlowObj {
2850 void *operator new(size_t, Collector &c) {
2851 return c.allocateObject(1);
2853 ExtensionFlowObj(const FOTBuilder::ExtensionFlowObj &);
2854 ExtensionFlowObj(const ExtensionFlowObj &);
2855 void processInner(ProcessContext &);
2856 FlowObj *copy(Collector &) const;
2857 bool hasNonInheritedC(const Identifier *) const;
2858 void setNonInheritedC(const Identifier *, ELObj *,
2859 const Location &, Interpreter &);
2861 Owner<FOTBuilder::ExtensionFlowObj> fo_;
2864 ExtensionFlowObj::ExtensionFlowObj(const FOTBuilder::ExtensionFlowObj &fo)
2869 ExtensionFlowObj::ExtensionFlowObj(const ExtensionFlowObj &fo)
2870 : FlowObj(fo), fo_(fo.fo_->copy())
2874 void ExtensionFlowObj::processInner(ProcessContext &context)
2876 context.currentFOTBuilder().extension(*fo_, context.vm().currentNode);
2879 void ExtensionFlowObj::setNonInheritedC(const Identifier *ident,
2881 const Location &loc,
2882 Interpreter &interp)
2884 fo_->setNIC(ident->name(), ELObjExtensionFlowObjValue(ident, obj, loc, interp));
2887 bool ExtensionFlowObj::hasNonInheritedC(const Identifier *ident) const
2889 return fo_->hasNIC(ident->name());
2892 FlowObj *ExtensionFlowObj::copy(Collector &c) const
2894 return new (c) ExtensionFlowObj(*this);
2897 class CompoundExtensionFlowObj : public CompoundFlowObj {
2899 void *operator new(size_t, Collector &c) {
2900 return c.allocateObject(1);
2902 CompoundExtensionFlowObj(const FOTBuilder::CompoundExtensionFlowObj &);
2903 CompoundExtensionFlowObj(const CompoundExtensionFlowObj &);
2904 void processInner(ProcessContext &);
2905 FlowObj *copy(Collector &) const;
2906 bool hasNonInheritedC(const Identifier *) const;
2907 void setNonInheritedC(const Identifier *, ELObj *,
2908 const Location &, Interpreter &);
2910 Owner<FOTBuilder::CompoundExtensionFlowObj> fo_;
2913 CompoundExtensionFlowObj::CompoundExtensionFlowObj(const FOTBuilder::CompoundExtensionFlowObj &fo)
2914 : fo_(fo.copy()->asCompoundExtensionFlowObj())
2918 CompoundExtensionFlowObj::CompoundExtensionFlowObj(const CompoundExtensionFlowObj &fo)
2919 : CompoundFlowObj(fo), fo_(fo.fo_->copy()->asCompoundExtensionFlowObj())
2923 void CompoundExtensionFlowObj::processInner(ProcessContext &context)
2925 FOTBuilder &fotb = context.currentFOTBuilder();
2926 Vector<StringC> portNames;
2927 fo_->portNames(portNames);
2928 Vector<FOTBuilder *> fotbs(portNames.size());
2929 fotb.startExtension(*fo_, context.vm().currentNode, fotbs);
2930 if (portNames.size()) {
2931 Vector<SymbolObj *> portSyms(portNames.size());
2932 for (size_t i = 0; i < portSyms.size(); i++)
2933 portSyms[i] = context.vm().interp->makeSymbol(portNames[i]);
2934 context.pushPorts(fo_->hasPrincipalPort(), portSyms, fotbs);
2935 CompoundFlowObj::processInner(context);
2939 CompoundFlowObj::processInner(context);
2940 fotb.endExtension(*fo_);
2943 void CompoundExtensionFlowObj::setNonInheritedC(const Identifier *ident,
2945 const Location &loc,
2946 Interpreter &interp)
2948 fo_->setNIC(ident->name(), ELObjExtensionFlowObjValue(ident, obj, loc, interp));
2951 bool CompoundExtensionFlowObj::hasNonInheritedC(const Identifier *ident) const
2953 return fo_->hasNIC(ident->name());
2956 FlowObj *CompoundExtensionFlowObj::copy(Collector &c) const
2958 return new (c) CompoundExtensionFlowObj(*this);
2961 #define FLOW_OBJ(name, string) \
2962 { FlowObj *tem = new (*this) name; \
2963 lookup(makeStringC(string))->setFlowObj(tem); \
2964 makePermanent(tem); }
2966 void Interpreter::installFlowObjs()
2968 FLOW_OBJ(SequenceFlowObj, "sequence");
2969 FLOW_OBJ(DisplayGroupFlowObj, "display-group");
2970 FLOW_OBJ(ParagraphFlowObj, "paragraph");
2971 FLOW_OBJ(ParagraphBreakFlowObj, "paragraph-break");
2972 FLOW_OBJ(LineFieldFlowObj, "line-field");
2973 FLOW_OBJ(ScoreFlowObj, "score");
2974 FLOW_OBJ(ExternalGraphicFlowObj, "external-graphic");
2975 FLOW_OBJ(RuleFlowObj, "rule");
2976 FLOW_OBJ(LeaderFlowObj, "leader");
2977 FLOW_OBJ(CharacterFlowObj, "character");
2978 FLOW_OBJ(BoxFlowObj, "box");
2979 FLOW_OBJ(AlignmentPointFlowObj, "alignment-point");
2980 FLOW_OBJ(SidelineFlowObj, "sideline");
2982 FLOW_OBJ(SimplePageSequenceFlowObj, "simple-page-sequence");
2984 FLOW_OBJ(TableFlowObj, "table");
2985 FLOW_OBJ(TablePartFlowObj, "table-part");
2986 FLOW_OBJ(TableColumnFlowObj, "table-column");
2987 FLOW_OBJ(TableRowFlowObj, "table-row");
2988 FLOW_OBJ(TableCellFlowObj, "table-cell");
2989 FLOW_OBJ(TableBorderFlowObj, "table-border");
2991 FLOW_OBJ(LinkFlowObj, "link");
2992 FLOW_OBJ(ScrollFlowObj, "scroll");
2993 FLOW_OBJ(MarginaliaFlowObj, "marginalia");
2994 FLOW_OBJ(MultiModeFlowObj, "multi-mode");
2996 FLOW_OBJ(MathSequenceFlowObj, "math-sequence");
2997 FLOW_OBJ(FractionFlowObj, "fraction");
2998 FLOW_OBJ(UnmathFlowObj, "unmath");
2999 FLOW_OBJ(SuperscriptFlowObj, "superscript");
3000 FLOW_OBJ(SubscriptFlowObj, "subscript");
3001 FLOW_OBJ(ScriptFlowObj, "script");
3002 FLOW_OBJ(MarkFlowObj, "mark");
3003 FLOW_OBJ(FenceFlowObj, "fence");
3004 FLOW_OBJ(RadicalFlowObj, "radical");
3005 FLOW_OBJ(MathOperatorFlowObj, "math-operator");
3006 FLOW_OBJ(GridFlowObj, "grid");
3007 FLOW_OBJ(GridCellFlowObj, "grid-cell");
3010 void Interpreter::installExtensionFlowObjectClass(Identifier *ident,
3011 const StringC &pubid,
3012 const Location &loc)
3015 if (extensionTable_) {
3016 for (const FOTBuilder::Extension *ep = extensionTable_; ep->pubid; ep++) {
3017 if (pubid == ep->pubid) {
3019 const FOTBuilder::CompoundExtensionFlowObj *cFlowObj
3020 = ep->flowObj->asCompoundExtensionFlowObj();
3022 tem = new (*this) CompoundExtensionFlowObj(*cFlowObj);
3024 tem = new (*this) ExtensionFlowObj(*ep->flowObj);
3032 == "UNREGISTERED::James Clark//Flow Object Class::"
3033 "formatting-instruction")
3034 tem = new (*this) FormattingInstructionFlowObj;
3036 tem = new (*this) UnknownFlowObj;
3039 ident->setFlowObj(tem, currentPartIndex(), loc);
3042 #ifdef DSSSL_NAMESPACE
3046 #include "FlowObj_inst.cxx"