1 // Copyright (c) 1996 James Clark
2 // See the file copying.txt for copying permission.
3
4 #include "stylelib.h"
5 #include "ProcessContext.h"
6 #include "Interpreter.h"
7 #include "InterpreterMessages.h"
8 #include "SosofoObj.h"
9 #include "macros.h"
10
11 #ifdef DSSSL_NAMESPACE
12 namespace DSSSL_NAMESPACE {
13 #endif
14
FlowObj()15 FlowObj::FlowObj()
16 : style_(0)
17 {
18 hasSubObjects_ = 1;
19 }
20
process(ProcessContext & context)21 void FlowObj::process(ProcessContext &context)
22 {
23 context.startFlowObj();
24 unsigned flags = 0;
25 pushStyle(context, flags);
26 processInner(context);
27 popStyle(context, flags);
28 context.endFlowObj();
29 }
30
pushStyle(ProcessContext & context,unsigned &)31 void FlowObj::pushStyle(ProcessContext &context, unsigned &)
32 {
33 if (style_)
34 context.currentStyleStack().push(style_, context.vm(), context.currentFOTBuilder());
35 else
36 context.currentStyleStack().pushEmpty();
37 }
38
popStyle(ProcessContext & context,unsigned)39 void FlowObj::popStyle(ProcessContext &context, unsigned)
40 {
41 if (style_)
42 context.currentStyleStack().pop();
43 else
44 context.currentStyleStack().popEmpty();
45 }
46
traceSubObjects(Collector & c) const47 void FlowObj::traceSubObjects(Collector &c) const
48 {
49 c.trace(style_);
50 }
51
asCompoundFlowObj()52 CompoundFlowObj *FlowObj::asCompoundFlowObj()
53 {
54 return 0;
55 }
56
hasNonInheritedC(const Identifier *) const57 bool FlowObj::hasNonInheritedC(const Identifier *) const
58 {
59 return 0;
60 }
61
hasPseudoNonInheritedC(const Identifier *) const62 bool FlowObj::hasPseudoNonInheritedC(const Identifier *) const
63 {
64 return 0;
65 }
66
setNonInheritedC(const Identifier *,ELObj *,const Location &,Interpreter &)67 void FlowObj::setNonInheritedC(const Identifier *, ELObj *, const Location &, Interpreter &)
68 {
69 CANNOT_HAPPEN();
70 }
71
isDisplayNIC(const Identifier * ident)72 bool FlowObj::isDisplayNIC(const Identifier *ident)
73 {
74 Identifier::SyntacticKey key;
75 if (ident->syntacticKey(key)) {
76 switch (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:
87 return 1;
88 default:
89 break;
90 }
91 }
92 return 0;
93 }
94
setDisplayNIC(FOTBuilder::DisplayNIC & nic,const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)95 bool FlowObj::setDisplayNIC(FOTBuilder::DisplayNIC &nic,
96 const Identifier *ident, ELObj *obj,
97 const Location &loc, Interpreter &interp)
98 {
99 static FOTBuilder::Symbol breakVals[] = {
100 FOTBuilder::symbolFalse,
101 FOTBuilder::symbolPage,
102 FOTBuilder::symbolColumnSet,
103 FOTBuilder::symbolColumn
104 };
105 Identifier::SyntacticKey key;
106 if (ident->syntacticKey(key)) {
107 switch (key) {
108 case Identifier::keyPositionPreference:
109 {
110 static FOTBuilder::Symbol vals[] = {
111 FOTBuilder::symbolFalse,
112 FOTBuilder::symbolTop,
113 FOTBuilder::symbolBottom,
114 };
115 interp.convertEnumC(vals, SIZEOF(vals), obj, ident, loc, nic.positionPreference);
116 }
117 return 1;
118 case Identifier::keyIsKeepWithPrevious:
119 interp.convertBooleanC(obj, ident, loc, nic.keepWithPrevious);
120 return 1;
121 case Identifier::keyIsKeepWithNext:
122 interp.convertBooleanC(obj, ident, loc, nic.keepWithNext);
123 return 1;
124 case Identifier::keyKeep:
125 {
126 static FOTBuilder::Symbol vals[] = {
127 FOTBuilder::symbolFalse,
128 FOTBuilder::symbolTrue,
129 FOTBuilder::symbolPage,
130 FOTBuilder::symbolColumnSet,
131 FOTBuilder::symbolColumn
132 };
133 interp.convertEnumC(vals, SIZEOF(vals), obj, ident, loc, nic.keep);
134 }
135 return 1;
136 case Identifier::keyBreakBefore:
137 interp.convertEnumC(breakVals, SIZEOF(breakVals), obj, ident, loc, nic.breakBefore);
138 return 1;
139 case Identifier::keyBreakAfter:
140 interp.convertEnumC(breakVals, SIZEOF(breakVals), obj, ident, loc, nic.breakAfter);
141 return 1;
142 case Identifier::keyIsMayViolateKeepBefore:
143 interp.convertBooleanC(obj, ident, loc, nic.mayViolateKeepBefore);
144 return 1;
145 case Identifier::keyIsMayViolateKeepAfter:
146 interp.convertBooleanC(obj, ident, loc, nic.mayViolateKeepAfter);
147 return 1;
148 case Identifier::keySpaceBefore:
149 case Identifier::keySpaceAfter:
150 {
151 FOTBuilder::DisplaySpace &ds = (key == Identifier::keySpaceBefore
152 ? nic.spaceBefore
153 : nic.spaceAfter);
154 DisplaySpaceObj *dso = obj->asDisplaySpace();
155 if (dso)
156 ds = dso->displaySpace();
157 else if (interp.convertLengthSpecC(obj, ident, loc, ds.nominal)) {
158 ds.max = ds.nominal;
159 ds.min = ds.nominal;
160 }
161 }
162 return 1;
163 default:
164 break;
165 }
166 }
167 return 0;
168 }
169
170
processInner(ProcessContext & context)171 void CompoundFlowObj::processInner(ProcessContext &context)
172 {
173 if (content_)
174 content_->process(context);
175 else
176 context.processChildren(context.vm().interp->initialProcessingMode());
177 }
178
traceSubObjects(Collector & c) const179 void CompoundFlowObj::traceSubObjects(Collector &c) const
180 {
181 c.trace(content_);
182 FlowObj::traceSubObjects(c);
183 }
184
asCompoundFlowObj()185 CompoundFlowObj *CompoundFlowObj::asCompoundFlowObj()
186 {
187 return this;
188 }
189
190 class DisplayGroupFlowObj : public CompoundFlowObj {
191 public:
operator new(size_t,Collector & c)192 void *operator new(size_t, Collector &c) {
193 return c.allocateObject(1);
194 }
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;
202 protected:
203 Owner<FOTBuilder::DisplayGroupNIC> nic_;
204 };
205
DisplayGroupFlowObj()206 DisplayGroupFlowObj::DisplayGroupFlowObj()
207 : nic_(new FOTBuilder::DisplayGroupNIC)
208 {
209 }
210
DisplayGroupFlowObj(const DisplayGroupFlowObj & fo)211 DisplayGroupFlowObj::DisplayGroupFlowObj(const DisplayGroupFlowObj &fo)
212 : CompoundFlowObj(fo), nic_(new FOTBuilder::DisplayGroupNIC(*fo.nic_))
213 {
214 }
215
processInner(ProcessContext & context)216 void DisplayGroupFlowObj::processInner(ProcessContext &context)
217 {
218 FOTBuilder &fotb = context.currentFOTBuilder();
219 fotb.startDisplayGroup(*nic_);
220 CompoundFlowObj::processInner(context);
221 fotb.endDisplayGroup();
222 }
223
hasNonInheritedC(const Identifier * ident) const224 bool DisplayGroupFlowObj::hasNonInheritedC(const Identifier *ident) const
225 {
226 Identifier::SyntacticKey key;
227 if (ident->syntacticKey(key) && key == Identifier::keyCoalesceId)
228 return 1;
229 return isDisplayNIC(ident);
230 }
231
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)232 void DisplayGroupFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
233 const Location &loc, Interpreter &interp)
234 {
235 if (!setDisplayNIC(*nic_, ident, obj, loc, interp)) {
236 const Char *s;
237 size_t n;
238 if (!obj->stringData(s, n)) {
239 interp.setNextLocation(loc);
240 interp.message(InterpreterMessages::invalidCharacteristicValue,
241 StringMessageArg(ident->name()));
242 }
243 nic_->hasCoalesceId = 1;
244 nic_->coalesceId.assign(s, n);
245 }
246 }
247
copy(Collector & c) const248 FlowObj *DisplayGroupFlowObj::copy(Collector &c) const
249 {
250 return new (c) DisplayGroupFlowObj(*this);
251 }
252
253 class ParagraphFlowObj : public CompoundFlowObj {
254 public:
operator new(size_t,Collector & c)255 void *operator new(size_t, Collector &c) {
256 return c.allocateObject(1);
257 }
258 ParagraphFlowObj();
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;
265 private:
266 Owner<FOTBuilder::ParagraphNIC> nic_;
267 };
268
269
ParagraphFlowObj()270 ParagraphFlowObj::ParagraphFlowObj()
271 : nic_(new FOTBuilder::ParagraphNIC)
272 {
273 }
274
ParagraphFlowObj(const ParagraphFlowObj & fo)275 ParagraphFlowObj::ParagraphFlowObj(const ParagraphFlowObj &fo)
276 : CompoundFlowObj(fo), nic_(new FOTBuilder::ParagraphNIC(*fo.nic_))
277 {
278 }
279
processInner(ProcessContext & context)280 void ParagraphFlowObj::processInner(ProcessContext &context)
281 {
282 FOTBuilder &fotb = context.currentFOTBuilder();
283 fotb.startParagraph(*nic_);
284 CompoundFlowObj::processInner(context);
285 fotb.endParagraph();
286 }
287
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)288 void ParagraphFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
289 const Location &loc, Interpreter &interp)
290 {
291 setDisplayNIC(*nic_, ident, obj, loc, interp);
292 }
293
hasNonInheritedC(const Identifier * ident) const294 bool ParagraphFlowObj::hasNonInheritedC(const Identifier *ident) const
295 {
296 return isDisplayNIC(ident);
297 }
298
copy(Collector & c) const299 FlowObj *ParagraphFlowObj::copy(Collector &c) const
300 {
301 return new (c) ParagraphFlowObj(*this);
302 }
303
304 class ParagraphBreakFlowObj : public FlowObj {
305 public:
operator new(size_t,Collector & c)306 void *operator new(size_t, Collector &c) {
307 return c.allocateObject(1);
308 }
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;
316 private:
317 Owner<FOTBuilder::ParagraphNIC> nic_;
318 };
319
320
ParagraphBreakFlowObj()321 ParagraphBreakFlowObj::ParagraphBreakFlowObj()
322 : nic_(new FOTBuilder::ParagraphNIC)
323 {
324 }
325
ParagraphBreakFlowObj(const ParagraphBreakFlowObj & fo)326 ParagraphBreakFlowObj::ParagraphBreakFlowObj(const ParagraphBreakFlowObj &fo)
327 : FlowObj(fo), nic_(new FOTBuilder::ParagraphNIC(*fo.nic_))
328 {
329 }
330
copy(Collector & c) const331 FlowObj *ParagraphBreakFlowObj::copy(Collector &c) const
332 {
333 return new (c) ParagraphBreakFlowObj(*this);
334 }
335
processInner(ProcessContext & context)336 void ParagraphBreakFlowObj::processInner(ProcessContext &context)
337 {
338 context.currentFOTBuilder().paragraphBreak(*nic_);
339 }
340
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)341 void ParagraphBreakFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
342 const Location &loc, Interpreter &interp)
343 {
344 setDisplayNIC(*nic_, ident, obj, loc, interp);
345 }
346
hasNonInheritedC(const Identifier * ident) const347 bool ParagraphBreakFlowObj::hasNonInheritedC(const Identifier *ident) const
348 {
349 return isDisplayNIC(ident);
350 }
351
352 class ExternalGraphicFlowObj : public FlowObj {
353 public:
operator new(size_t,Collector & c)354 void *operator new(size_t, Collector &c) {
355 return c.allocateObject(1);
356 }
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;
364 private:
365 Owner<FOTBuilder::ExternalGraphicNIC> nic_;
366 };
367
368
ExternalGraphicFlowObj()369 ExternalGraphicFlowObj::ExternalGraphicFlowObj()
370 : nic_(new FOTBuilder::ExternalGraphicNIC)
371 {
372 }
373
ExternalGraphicFlowObj(const ExternalGraphicFlowObj & fo)374 ExternalGraphicFlowObj::ExternalGraphicFlowObj(const ExternalGraphicFlowObj &fo)
375 : FlowObj(fo), nic_(new FOTBuilder::ExternalGraphicNIC(*fo.nic_))
376 {
377 }
378
processInner(ProcessContext & context)379 void ExternalGraphicFlowObj::processInner(ProcessContext &context)
380 {
381 context.currentFOTBuilder().externalGraphic(*nic_);
382 }
383
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)384 void ExternalGraphicFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
385 const Location &loc, Interpreter &interp)
386 {
387 if (!setDisplayNIC(*nic_, ident, obj, loc, interp)) {
388 Identifier::SyntacticKey key;
389 if (ident->syntacticKey(key)) {
390 switch (key) {
391 case Identifier::keyIsDisplay:
392 interp.convertBooleanC(obj, ident, loc, nic_->isDisplay);
393 return;
394 case Identifier::keyScale:
395 {
396 double d;
397 if (obj->realValue(d)) {
398 nic_->scaleType = FOTBuilder::symbolFalse;
399 nic_->scale[0] = nic_->scale[1] = d;
400 }
401 else if (obj->asSymbol()) {
402 static FOTBuilder::Symbol vals[] = {
403 FOTBuilder::symbolMax,
404 FOTBuilder::symbolMaxUniform
405 };
406 interp.convertEnumC(vals, 2, obj, ident, loc, nic_->scaleType);
407 }
408 else {
409 PairObj *pair = obj->asPair();
410 if (pair
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;
416 }
417 else
418 interp.invalidCharacteristicValue(ident, loc);
419 }
420 }
421 return;
422 case Identifier::keyMaxWidth:
423 if (interp.convertLengthSpecC(obj, ident, loc, nic_->maxWidth))
424 nic_->hasMaxWidth = 1;
425 return;
426 case Identifier::keyMaxHeight:
427 if (interp.convertLengthSpecC(obj, ident, loc, nic_->maxHeight))
428 nic_->hasMaxHeight = 1;
429 return;
430 case Identifier::keyEntitySystemId:
431 interp.convertStringC(obj, ident, loc, nic_->entitySystemId);
432 return;
433 case Identifier::keyNotationSystemId:
434 interp.convertStringC(obj, ident, loc, nic_->notationSystemId);
435 return;
436 case Identifier::keyPositionPointX:
437 interp.convertLengthSpecC(obj, ident, loc, nic_->positionPointX);
438 return;
439 case Identifier::keyPositionPointY:
440 interp.convertLengthSpecC(obj, ident, loc, nic_->positionPointY);
441 return;
442 case Identifier::keyEscapementDirection:
443 {
444 static FOTBuilder::Symbol vals[] = {
445 FOTBuilder::symbolTopToBottom,
446 FOTBuilder::symbolLeftToRight,
447 FOTBuilder::symbolBottomToTop,
448 FOTBuilder::symbolRightToLeft
449 };
450 interp.convertEnumC(vals, SIZEOF(vals), obj, ident, loc, nic_->escapementDirection);
451 }
452 return;
453 case Identifier::keyBreakBeforePriority:
454 interp.convertIntegerC(obj, ident, loc, nic_->breakBeforePriority);
455 return;
456 case Identifier::keyBreakAfterPriority:
457 interp.convertIntegerC(obj, ident, loc, nic_->breakAfterPriority);
458 return;
459 default:
460 break;
461 }
462 }
463 CANNOT_HAPPEN();
464 }
465 }
466
hasNonInheritedC(const Identifier * ident) const467 bool ExternalGraphicFlowObj::hasNonInheritedC(const Identifier *ident) const
468 {
469 Identifier::SyntacticKey key;
470 if (ident->syntacticKey(key)) {
471 switch (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:
483 return 1;
484 default:
485 break;
486 }
487 }
488 return isDisplayNIC(ident);
489 }
490
copy(Collector & c) const491 FlowObj *ExternalGraphicFlowObj::copy(Collector &c) const
492 {
493 return new (c) ExternalGraphicFlowObj(*this);
494 }
495
496 class RuleFlowObj : public FlowObj {
497 public:
operator new(size_t,Collector & c)498 void *operator new(size_t, Collector &c) {
499 return c.allocateObject(1);
500 }
501 RuleFlowObj();
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;
ruleStyle(ProcessContext &,StyleObj * & style)508 bool ruleStyle(ProcessContext &, StyleObj *&style) {
509 style = style_;
510 return 1;
511 }
isRule()512 bool isRule() { return 1; }
513 private:
514 Owner<FOTBuilder::RuleNIC> nic_;
515 };
516
RuleFlowObj()517 RuleFlowObj::RuleFlowObj()
518 : nic_(new FOTBuilder::RuleNIC)
519 {
520 }
521
RuleFlowObj(const RuleFlowObj & fo)522 RuleFlowObj::RuleFlowObj(const RuleFlowObj &fo)
523 : FlowObj(fo), nic_(new FOTBuilder::RuleNIC(*fo.nic_))
524 {
525 }
526
processInner(ProcessContext & context)527 void RuleFlowObj::processInner(ProcessContext &context)
528 {
529 context.currentFOTBuilder().rule(*nic_);
530 }
531
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)532 void RuleFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
533 const Location &loc, Interpreter &interp)
534 {
535 if (setDisplayNIC(*nic_, ident, obj, loc, interp))
536 return;
537 Identifier::SyntacticKey key;
538 if (ident->syntacticKey(key)) {
539 switch (key) {
540 case Identifier::keyOrientation:
541 {
542 static FOTBuilder::Symbol vals[] = {
543 FOTBuilder::symbolHorizontal,
544 FOTBuilder::symbolVertical,
545 FOTBuilder::symbolEscapement,
546 FOTBuilder::symbolLineProgression
547 };
548 interp.convertEnumC(vals, SIZEOF(vals), obj, ident, loc, nic_->orientation);
549 }
550 return;
551 case Identifier::keyLength:
552 if (interp.convertLengthSpecC(obj, ident, loc, nic_->length))
553 nic_->hasLength = 1;
554 return;
555 case Identifier::keyBreakBeforePriority:
556 interp.convertIntegerC(obj, ident, loc, nic_->breakBeforePriority);
557 return;
558 case Identifier::keyBreakAfterPriority:
559 interp.convertIntegerC(obj, ident, loc, nic_->breakAfterPriority);
560 return;
561 default:
562 break;
563 }
564 }
565 CANNOT_HAPPEN();
566 }
567
hasNonInheritedC(const Identifier * ident) const568 bool RuleFlowObj::hasNonInheritedC(const Identifier *ident) const
569 {
570 Identifier::SyntacticKey key;
571 if (ident->syntacticKey(key)) {
572 switch (key) {
573 case Identifier::keyOrientation:
574 case Identifier::keyLength:
575 case Identifier::keyBreakBeforePriority:
576 case Identifier::keyBreakAfterPriority:
577 return 1;
578 default:
579 break;
580 }
581 }
582 return isDisplayNIC(ident);
583 }
584
copy(Collector & c) const585 FlowObj *RuleFlowObj::copy(Collector &c) const
586 {
587 return new (c) RuleFlowObj(*this);
588 }
589
590 class AlignmentPointFlowObj : public FlowObj {
591 public:
AlignmentPointFlowObj()592 AlignmentPointFlowObj() { }
593 FlowObj *copy(Collector &) const;
594 void processInner(ProcessContext &);
595 };
596
copy(Collector & c) const597 FlowObj *AlignmentPointFlowObj::copy(Collector &c) const
598 {
599 return new (c) AlignmentPointFlowObj(*this);
600 }
601
processInner(ProcessContext & context)602 void AlignmentPointFlowObj::processInner(ProcessContext &context)
603 {
604 context.currentFOTBuilder().alignmentPoint();
605 }
606
607 class SidelineFlowObj : public CompoundFlowObj {
608 public:
SidelineFlowObj()609 SidelineFlowObj() { }
610 FlowObj *copy(Collector &) const;
611 void processInner(ProcessContext &);
612 };
613
copy(Collector & c) const614 FlowObj *SidelineFlowObj::copy(Collector &c) const
615 {
616 return new (c) SidelineFlowObj(*this);
617 }
618
processInner(ProcessContext & context)619 void SidelineFlowObj::processInner(ProcessContext &context)
620 {
621 FOTBuilder &fotb = context.currentFOTBuilder();
622 fotb.startSideline();
623 CompoundFlowObj::processInner(context);
624 fotb.endSideline();
625 }
processInner(ProcessContext & context)626 void SequenceFlowObj::processInner(ProcessContext &context)
627 {
628 FOTBuilder &fotb = context.currentFOTBuilder();
629 fotb.startSequence();
630 CompoundFlowObj::processInner(context);
631 fotb.endSequence();
632 }
633
copy(Collector & c) const634 FlowObj *SequenceFlowObj::copy(Collector &c) const
635 {
636 return new (c) SequenceFlowObj(*this);
637 }
638
639 class LineFieldFlowObj : public CompoundFlowObj {
640 public:
operator new(size_t,Collector & c)641 void *operator new(size_t, Collector &c) {
642 return c.allocateObject(1);
643 }
LineFieldFlowObj()644 LineFieldFlowObj() : nic_(new FOTBuilder::LineFieldNIC) { }
LineFieldFlowObj(const LineFieldFlowObj & fo)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);
652 private:
653 Owner<FOTBuilder::LineFieldNIC> nic_;
654 };
655
copy(Collector & c) const656 FlowObj *LineFieldFlowObj::copy(Collector &c) const
657 {
658 return new (c) LineFieldFlowObj(*this);
659 }
660
processInner(ProcessContext & context)661 void LineFieldFlowObj::processInner(ProcessContext &context)
662 {
663 FOTBuilder &fotb = context.currentFOTBuilder();
664 fotb.startLineField(*nic_);
665 CompoundFlowObj::processInner(context);
666 fotb.endLineField();
667 }
668
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)669 void LineFieldFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
670 const Location &loc, Interpreter &interp)
671 {
672 Identifier::SyntacticKey key;
673 if (ident->syntacticKey(key)) {
674 switch (key) {
675 case Identifier::keyBreakBeforePriority:
676 interp.convertIntegerC(obj, ident, loc, nic_->breakBeforePriority);
677 return;
678 case Identifier::keyBreakAfterPriority:
679 interp.convertIntegerC(obj, ident, loc, nic_->breakAfterPriority);
680 return;
681 default:
682 break;
683 }
684 }
685 CANNOT_HAPPEN();
686 }
687
hasNonInheritedC(const Identifier * ident) const688 bool LineFieldFlowObj::hasNonInheritedC(const Identifier *ident) const
689 {
690 Identifier::SyntacticKey key;
691 if (ident->syntacticKey(key)) {
692 switch (key) {
693 case Identifier::keyBreakBeforePriority:
694 case Identifier::keyBreakAfterPriority:
695 return 1;
696 default:
697 break;
698 }
699 }
700 return 0;
701 }
702
703 class SimplePageSequenceFlowObj : public CompoundFlowObj {
704 public:
operator new(size_t,Collector & c)705 void *operator new(size_t, Collector &c) {
706 return c.allocateObject(1);
707 }
708 struct HeaderFooter {
709 enum { nParts = 6 };
710 HeaderFooter();
711 SosofoObj *part[nParts];
712 };
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;
721 private:
722 enum { nPageTypeBits = 2 };
723 Owner<HeaderFooter> hf_;
724 };
725
726
SimplePageSequenceFlowObj()727 SimplePageSequenceFlowObj::SimplePageSequenceFlowObj()
728 : hf_(new HeaderFooter)
729 {
730 hasSubObjects_ = 1;
731 }
732
SimplePageSequenceFlowObj(const SimplePageSequenceFlowObj & fo)733 SimplePageSequenceFlowObj::SimplePageSequenceFlowObj(const SimplePageSequenceFlowObj &fo)
734 : CompoundFlowObj(fo), hf_(new HeaderFooter(*fo.hf_))
735 {
736 }
737
traceSubObjects(Collector & c) const738 void SimplePageSequenceFlowObj::traceSubObjects(Collector &c) const
739 {
740 for (int i = 0; i < HeaderFooter::nParts; i++)
741 c.trace(hf_->part[i]);
742 CompoundFlowObj::traceSubObjects(c);
743 }
744
processInner(ProcessContext & context)745 void SimplePageSequenceFlowObj::processInner(ProcessContext &context)
746 {
747 FOTBuilder &fotb = context.currentFOTBuilder();
748 fotb.startSimplePageSequence();
749 for (int i = 0; i < (1 << nPageTypeBits); i++) {
750 context.setPageType(i);
751 for (int j = 0; j < HeaderFooter::nParts; j++) {
752 fotb.startSimplePageSequenceHeaderFooter(i | (j << nPageTypeBits));
753 if (hf_->part[j])
754 hf_->part[j]->process(context);
755 fotb.endSimplePageSequenceHeaderFooter(i | (j << nPageTypeBits));
756 }
757 }
758 fotb.endAllSimplePageSequenceHeaderFooter();
759 context.clearPageType();
760 CompoundFlowObj::processInner(context);
761 fotb.endSimplePageSequence();
762 }
763
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)764 void SimplePageSequenceFlowObj::setNonInheritedC(const Identifier *ident,
765 ELObj *obj,
766 const Location &loc,
767 Interpreter &interp)
768 {
769 SosofoObj *sosofo = obj->asSosofo();
770 if (!sosofo) {
771 interp.setNextLocation(loc);
772 interp.message(InterpreterMessages::invalidCharacteristicValue,
773 StringMessageArg(ident->name()));
774 return;
775 }
776 Identifier::SyntacticKey key;
777 if (ident->syntacticKey(key)) {
778 switch (key) {
779 case Identifier::keyLeftHeader:
780 hf_->part[(FOTBuilder::leftHF | FOTBuilder::headerHF) >> nPageTypeBits] = sosofo;
781 return;
782 case Identifier::keyCenterHeader:
783 hf_->part[(FOTBuilder::centerHF | FOTBuilder::headerHF) >> nPageTypeBits] = sosofo;
784 return;
785 case Identifier::keyRightHeader:
786 hf_->part[(FOTBuilder::rightHF | FOTBuilder::headerHF) >> nPageTypeBits] = sosofo;
787 return;
788 case Identifier::keyLeftFooter:
789 hf_->part[(FOTBuilder::leftHF | FOTBuilder::footerHF) >> nPageTypeBits] = sosofo;
790 return;
791 case Identifier::keyCenterFooter:
792 hf_->part[(FOTBuilder::centerHF | FOTBuilder::footerHF) >> nPageTypeBits] = sosofo;
793 return;
794 case Identifier::keyRightFooter:
795 hf_->part[(FOTBuilder::rightHF | FOTBuilder::footerHF) >> nPageTypeBits] = sosofo;
796 return;
797 default:
798 break;
799 }
800 }
801 CANNOT_HAPPEN();
802 }
803
hasNonInheritedC(const Identifier * ident) const804 bool SimplePageSequenceFlowObj::hasNonInheritedC(const Identifier *ident) const
805 {
806 Identifier::SyntacticKey key;
807 if (ident->syntacticKey(key)) {
808 switch (key) {
809 case Identifier::keyLeftHeader:
810 case Identifier::keyCenterHeader:
811 case Identifier::keyRightHeader:
812 case Identifier::keyLeftFooter:
813 case Identifier::keyCenterFooter:
814 case Identifier::keyRightFooter:
815 return 1;
816 default:
817 break;
818 }
819 }
820 return 0;
821 }
822
copy(Collector & c) const823 FlowObj *SimplePageSequenceFlowObj::copy(Collector &c) const
824 {
825 return new (c) SimplePageSequenceFlowObj(*this);
826 }
827
HeaderFooter()828 SimplePageSequenceFlowObj::HeaderFooter::HeaderFooter()
829 {
830 for (int i = 0; i < nParts; i++)
831 part[i] = 0;
832 }
833
834 class LinkFlowObj : public CompoundFlowObj {
835 public:
836 LinkFlowObj();
837 FlowObj *copy(Collector &) const;
838 void processInner(ProcessContext &);
839 void traceSubObjects(Collector &) const;
840 bool hasNonInheritedC(const Identifier *) const;
841 void setNonInheritedC(const Identifier *, ELObj *,
842 const Location &, Interpreter &);
843 private:
844 AddressObj *addressObj_;
845 };
846
LinkFlowObj()847 LinkFlowObj::LinkFlowObj()
848 : addressObj_(0)
849 {
850 }
851
processInner(ProcessContext & context)852 void LinkFlowObj::processInner(ProcessContext &context)
853 {
854 FOTBuilder &fotb = context.currentFOTBuilder();
855 if (!addressObj_) {
856 FOTBuilder::Address addr;
857 addr.type = FOTBuilder::Address::none;
858 fotb.startLink(addr);
859 }
860 else
861 fotb.startLink(addressObj_->address());
862 CompoundFlowObj::processInner(context);
863 fotb.endLink();
864 }
865
copy(Collector & c) const866 FlowObj *LinkFlowObj::copy(Collector &c) const
867 {
868 return new (c) LinkFlowObj(*this);
869 }
870
traceSubObjects(Collector & c) const871 void LinkFlowObj::traceSubObjects(Collector &c) const
872 {
873 CompoundFlowObj::traceSubObjects(c);
874 c.trace(addressObj_);
875 }
876
hasNonInheritedC(const Identifier * ident) const877 bool LinkFlowObj::hasNonInheritedC(const Identifier *ident) const
878 {
879 Identifier::SyntacticKey key;
880 return ident->syntacticKey(key) && key == Identifier::keyDestination;
881 }
882
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)883 void LinkFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
884 const Location &loc, Interpreter &interp)
885 {
886 AddressObj *address = obj->asAddress();
887 if (!address) {
888 if (obj != interp.makeFalse()) {
889 interp.setNextLocation(loc);
890 interp.message(InterpreterMessages::invalidCharacteristicValue,
891 StringMessageArg(ident->name()));
892 }
893 else
894 address = interp.makeAddressNone();
895 }
896 addressObj_ = address;
897 }
898
899 class ScrollFlowObj : public CompoundFlowObj {
900 public:
ScrollFlowObj()901 ScrollFlowObj() { }
902 void processInner(ProcessContext &);
903 FlowObj *copy(Collector &) const;
904 };
905
processInner(ProcessContext & context)906 void ScrollFlowObj::processInner(ProcessContext &context)
907 {
908 FOTBuilder &fotb = context.currentFOTBuilder();
909 fotb.startScroll();
910 CompoundFlowObj::processInner(context);
911 fotb.endScroll();
912 }
913
copy(Collector & c) const914 FlowObj *ScrollFlowObj::copy(Collector &c) const
915 {
916 return new (c) ScrollFlowObj(*this);
917 }
918
919 class MarginaliaFlowObj : public CompoundFlowObj {
920 public:
MarginaliaFlowObj()921 MarginaliaFlowObj() { }
922 void processInner(ProcessContext &);
923 FlowObj *copy(Collector &) const;
924 };
925
processInner(ProcessContext & context)926 void MarginaliaFlowObj::processInner(ProcessContext &context)
927 {
928 FOTBuilder &fotb = context.currentFOTBuilder();
929 fotb.startMarginalia();
930 CompoundFlowObj::processInner(context);
931 fotb.endMarginalia();
932 }
933
copy(Collector & c) const934 FlowObj *MarginaliaFlowObj::copy(Collector &c) const
935 {
936 return new (c) MarginaliaFlowObj(*this);
937 }
938
939 class MultiModeFlowObj : public CompoundFlowObj {
940 public:
operator new(size_t,Collector & c)941 void *operator new(size_t, Collector &c) {
942 return c.allocateObject(1);
943 }
944 MultiModeFlowObj();
945 MultiModeFlowObj(const MultiModeFlowObj &);
946 void processInner(ProcessContext &);
947 FlowObj *copy(Collector &) const;
948 bool hasNonInheritedC(const Identifier *) const;
949 void setNonInheritedC(const Identifier *, ELObj *,
950 const Location &, Interpreter &);
951 struct NIC {
NICDSSSL_NAMESPACE::MultiModeFlowObj::NIC952 NIC() : hasPrincipalMode(0) { }
953 bool hasPrincipalMode;
954 FOTBuilder::MultiMode principalMode;
955 Vector<FOTBuilder::MultiMode> namedModes;
956 };
957 private:
958 bool handleMultiModesMember(const Identifier *, ELObj *obj,
959 const Location &, Interpreter &);
960 Owner<NIC> nic_;
961 };
962
MultiModeFlowObj()963 MultiModeFlowObj::MultiModeFlowObj()
964 : nic_(new NIC)
965 {
966 }
967
MultiModeFlowObj(const MultiModeFlowObj & fo)968 MultiModeFlowObj::MultiModeFlowObj(const MultiModeFlowObj &fo)
969 : CompoundFlowObj(fo), nic_(new NIC(*fo.nic_))
970 {
971 }
972
processInner(ProcessContext & context)973 void MultiModeFlowObj::processInner(ProcessContext &context)
974 {
975 FOTBuilder &fotb = context.currentFOTBuilder();
976 Vector<FOTBuilder *> fotbs(nic_->namedModes.size());
977 fotb.startMultiMode(nic_->hasPrincipalMode ? &nic_->principalMode : 0,
978 nic_->namedModes,
979 fotbs);
980 Vector<SymbolObj *> portSyms(nic_->namedModes.size());
981 for (size_t i = 0; i < portSyms.size(); i++)
982 portSyms[i] = context.vm().interp->makeSymbol(nic_->namedModes[i].name);
983 context.pushPorts(nic_->hasPrincipalMode, portSyms, fotbs);
984 CompoundFlowObj::processInner(context);
985 context.popPorts();
986 fotb.endMultiMode();
987 }
988
copy(Collector & c) const989 FlowObj *MultiModeFlowObj::copy(Collector &c) const
990 {
991 return new (c) MultiModeFlowObj(*this);
992 }
993
hasNonInheritedC(const Identifier * ident) const994 bool MultiModeFlowObj::hasNonInheritedC(const Identifier *ident) const
995 {
996 Identifier::SyntacticKey key;
997 return ident->syntacticKey(key) && key == Identifier::keyMultiModes;
998 }
999
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)1000 void MultiModeFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
1001 const Location &loc, Interpreter &interp)
1002 {
1003 while (!obj->isNil()) {
1004 PairObj *pair = obj->asPair();
1005 if (!pair || !handleMultiModesMember(ident, pair->car(), loc, interp)) {
1006 interp.setNextLocation(loc);
1007 interp.message(InterpreterMessages::invalidCharacteristicValue,
1008 StringMessageArg(ident->name()));
1009 return;
1010 }
1011 obj = pair->cdr();
1012 }
1013 }
1014
handleMultiModesMember(const Identifier *,ELObj * obj,const Location & loc,Interpreter & interp)1015 bool MultiModeFlowObj::handleMultiModesMember(const Identifier *, ELObj *obj,
1016 const Location &loc, Interpreter &interp)
1017 {
1018 if (obj == interp.makeFalse()) {
1019 nic_->hasPrincipalMode = 1;
1020 return 1;
1021 }
1022 SymbolObj *sym = obj->asSymbol();
1023 if (sym) {
1024 nic_->namedModes.resize(nic_->namedModes.size() + 1);
1025 nic_->namedModes.back().name = *sym->name();
1026 return 1;
1027 }
1028 PairObj *pair = obj->asPair();
1029 if (!pair)
1030 return 0;
1031 ELObj *spec = pair->car();
1032 pair = pair->cdr()->asPair();
1033 if (!pair || !pair->cdr()->isNil())
1034 return 0;
1035 const Char *s;
1036 size_t n;
1037 if (!pair->car()->stringData(s, n))
1038 return 0;
1039 if (spec == interp.makeFalse()) {
1040 nic_->hasPrincipalMode = 1;
1041 nic_->principalMode.hasDesc = 1;
1042 nic_->principalMode.desc.assign(s, n);
1043 return 1;
1044 }
1045 sym = spec->asSymbol();
1046 if (!sym)
1047 return 0;
1048 nic_->namedModes.resize(nic_->namedModes.size() + 1);
1049 nic_->namedModes.back().name = *sym->name();
1050 nic_->namedModes.back().desc.assign(s, n);
1051 nic_->namedModes.back().hasDesc = 1;
1052 return 1;
1053 }
1054
1055
1056 class ScoreFlowObj : public CompoundFlowObj {
1057 public:
operator new(size_t,Collector & c)1058 void *operator new(size_t, Collector &c) {
1059 return c.allocateObject(1);
1060 }
1061 ScoreFlowObj();
1062 FlowObj *copy(Collector &) const;
1063 void processInner(ProcessContext &);
1064 bool hasNonInheritedC(const Identifier *) const;
1065 void setNonInheritedC(const Identifier *, ELObj *,
1066 const Location &, Interpreter &);
1067 class Type {
1068 public:
1069 virtual ~Type();
1070 virtual void start(FOTBuilder &) = 0;
1071 virtual Type *copy() const = 0;
1072 };
1073 private:
1074 class SymbolType : public Type {
1075 public:
SymbolType(FOTBuilder::Symbol type)1076 SymbolType(FOTBuilder::Symbol type) : type_(type) { }
1077 void start(FOTBuilder &);
1078 Type *copy() const;
1079 private:
1080 FOTBuilder::Symbol type_;
1081 };
1082 class LengthSpecType : public Type {
1083 public:
LengthSpecType(long n)1084 LengthSpecType(long n) : len_(n) { }
1085 void start(FOTBuilder &);
1086 Type *copy() const;
1087 private:
1088 FOTBuilder::LengthSpec len_;
1089 };
1090 class CharType : public Type {
1091 public:
CharType(Char c)1092 CharType(Char c) : c_(c) { }
1093 void start(FOTBuilder &);
1094 Type *copy() const;
1095 private:
1096 Char c_;
1097 };
1098 CopyOwner<Type> type_;
1099 };
1100
ScoreFlowObj()1101 ScoreFlowObj::ScoreFlowObj()
1102 {
1103 }
1104
copy(Collector & c) const1105 FlowObj *ScoreFlowObj::copy(Collector &c) const
1106 {
1107 return new (c) ScoreFlowObj(*this);
1108 }
1109
processInner(ProcessContext & context)1110 void ScoreFlowObj::processInner(ProcessContext &context)
1111 {
1112 FOTBuilder &fotb = context.currentFOTBuilder();
1113 if (type_)
1114 type_->start(fotb);
1115 else
1116 fotb.startSequence();
1117 CompoundFlowObj::processInner(context);
1118 if (type_)
1119 fotb.endScore();
1120 else
1121 fotb.endSequence();
1122 }
1123
hasNonInheritedC(const Identifier * ident) const1124 bool ScoreFlowObj::hasNonInheritedC(const Identifier *ident) const
1125 {
1126 Identifier::SyntacticKey key;
1127 return ident->syntacticKey(key) && key == Identifier::keyType;
1128 }
1129
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)1130 void ScoreFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
1131 const Location &loc, Interpreter &interp)
1132 {
1133 Char c;
1134 if (obj->charValue(c)) {
1135 type_ = new CharType(c);
1136 return;
1137 }
1138 double d;
1139 long n;
1140 int dim;
1141 switch (obj->quantityValue(n, d, dim)) {
1142 case longQuantity:
1143 if (dim == 1) {
1144 type_ = new LengthSpecType(n);
1145 return;
1146 }
1147 break;
1148 case doubleQuantity:
1149 if (dim == 1) {
1150 type_ = new LengthSpecType(long(d));
1151 return;
1152 }
1153 break;
1154 default:
1155 break;
1156 }
1157 static FOTBuilder::Symbol vals[] = {
1158 FOTBuilder::symbolBefore,
1159 FOTBuilder::symbolThrough,
1160 FOTBuilder::symbolAfter
1161 };
1162 FOTBuilder::Symbol sym;
1163 if (interp.convertEnumC(vals, SIZEOF(vals), obj, ident, loc, sym))
1164 type_ = new SymbolType(sym);
1165 }
1166
~Type()1167 ScoreFlowObj::Type::~Type()
1168 {
1169 }
1170
start(FOTBuilder & fotb)1171 void ScoreFlowObj::SymbolType::start(FOTBuilder &fotb)
1172 {
1173 fotb.startScore(type_);
1174 }
1175
start(FOTBuilder & fotb)1176 void ScoreFlowObj::CharType::start(FOTBuilder &fotb)
1177 {
1178 fotb.startScore(c_);
1179 }
1180
start(FOTBuilder & fotb)1181 void ScoreFlowObj::LengthSpecType::start(FOTBuilder &fotb)
1182 {
1183 fotb.startScore(len_);
1184 }
1185
copy() const1186 ScoreFlowObj::Type *ScoreFlowObj::SymbolType::copy() const
1187 {
1188 return new SymbolType(*this);
1189 }
1190
copy() const1191 ScoreFlowObj::Type *ScoreFlowObj::LengthSpecType::copy() const
1192 {
1193 return new LengthSpecType(*this);
1194 }
1195
copy() const1196 ScoreFlowObj::Type *ScoreFlowObj::CharType::copy() const
1197 {
1198 return new CharType(*this);
1199 }
1200
1201 class BoxFlowObj : public CompoundFlowObj {
1202 public:
operator new(size_t,Collector & c)1203 void *operator new(size_t, Collector &c) {
1204 return c.allocateObject(1);
1205 }
1206 BoxFlowObj();
1207 BoxFlowObj(const BoxFlowObj &);
1208 FlowObj *copy(Collector &) const;
1209 void processInner(ProcessContext &);
1210 bool hasNonInheritedC(const Identifier *) const;
1211 void setNonInheritedC(const Identifier *, ELObj *,
1212 const Location &, Interpreter &);
1213 private:
1214 Owner<FOTBuilder::BoxNIC> nic_;
1215 };
1216
BoxFlowObj()1217 BoxFlowObj::BoxFlowObj()
1218 : nic_(new FOTBuilder::BoxNIC)
1219 {
1220 }
1221
BoxFlowObj(const BoxFlowObj & fo)1222 BoxFlowObj::BoxFlowObj(const BoxFlowObj &fo)
1223 : CompoundFlowObj(fo), nic_(new FOTBuilder::BoxNIC(*fo.nic_))
1224 {
1225 }
1226
processInner(ProcessContext & context)1227 void BoxFlowObj::processInner(ProcessContext &context)
1228 {
1229 FOTBuilder &fotb = context.currentFOTBuilder();
1230 fotb.startBox(*nic_);
1231 CompoundFlowObj::processInner(context);
1232 fotb.endBox();
1233 }
1234
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)1235 void BoxFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
1236 const Location &loc, Interpreter &interp)
1237 {
1238 if (setDisplayNIC(*nic_, ident, obj, loc, interp))
1239 return;
1240 Identifier::SyntacticKey key;
1241 if (ident->syntacticKey(key)) {
1242 switch (key) {
1243 case Identifier::keyIsDisplay:
1244 interp.convertBooleanC(obj, ident, loc, nic_->isDisplay);
1245 return;
1246 case Identifier::keyBreakBeforePriority:
1247 interp.convertIntegerC(obj, ident, loc, nic_->breakBeforePriority);
1248 return;
1249 case Identifier::keyBreakAfterPriority:
1250 interp.convertIntegerC(obj, ident, loc, nic_->breakAfterPriority);
1251 return;
1252 default:
1253 break;
1254 }
1255 }
1256 CANNOT_HAPPEN();
1257 }
1258
hasNonInheritedC(const Identifier * ident) const1259 bool BoxFlowObj::hasNonInheritedC(const Identifier *ident) const
1260 {
1261 Identifier::SyntacticKey key;
1262 if (ident->syntacticKey(key)) {
1263 switch (key) {
1264 case Identifier::keyIsDisplay:
1265 case Identifier::keyBreakBeforePriority:
1266 case Identifier::keyBreakAfterPriority:
1267 return 1;
1268 default:
1269 break;
1270 }
1271 }
1272 return isDisplayNIC(ident);
1273 }
1274
copy(Collector & c) const1275 FlowObj *BoxFlowObj::copy(Collector &c) const
1276 {
1277 return new (c) BoxFlowObj(*this);
1278 }
1279
1280 class LeaderFlowObj : public CompoundFlowObj {
1281 public:
operator new(size_t,Collector & c)1282 void *operator new(size_t, Collector &c) {
1283 return c.allocateObject(1);
1284 }
1285 LeaderFlowObj();
1286 LeaderFlowObj(const LeaderFlowObj &);
1287 void processInner(ProcessContext &);
1288 FlowObj *copy(Collector &) const;
1289 void setNonInheritedC(const Identifier *, ELObj *,
1290 const Location &, Interpreter &);
1291 bool hasNonInheritedC(const Identifier *) const;
1292 private:
1293 Owner<FOTBuilder::LeaderNIC> nic_;
1294 };
1295
LeaderFlowObj()1296 LeaderFlowObj::LeaderFlowObj()
1297 : nic_(new FOTBuilder::LeaderNIC)
1298 {
1299 }
1300
LeaderFlowObj(const LeaderFlowObj & fo)1301 LeaderFlowObj::LeaderFlowObj(const LeaderFlowObj &fo)
1302 : CompoundFlowObj(fo), nic_(new FOTBuilder::LeaderNIC(*fo.nic_))
1303 {
1304 }
1305
processInner(ProcessContext & context)1306 void LeaderFlowObj::processInner(ProcessContext &context)
1307 {
1308 FOTBuilder &fotb = context.currentFOTBuilder();
1309 fotb.startLeader(*nic_);
1310 CompoundFlowObj::processInner(context);
1311 fotb.endLeader();
1312 }
1313
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)1314 void LeaderFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
1315 const Location &loc, Interpreter &interp)
1316 {
1317 Identifier::SyntacticKey key;
1318 if (ident->syntacticKey(key)) {
1319 switch (key) {
1320 case Identifier::keyLength:
1321 if (interp.convertLengthSpecC(obj, ident, loc, nic_->length))
1322 nic_->hasLength = 1;
1323 return;
1324 case Identifier::keyBreakBeforePriority:
1325 interp.convertIntegerC(obj, ident, loc, nic_->breakBeforePriority);
1326 return;
1327 case Identifier::keyBreakAfterPriority:
1328 interp.convertIntegerC(obj, ident, loc, nic_->breakAfterPriority);
1329 return;
1330 default:
1331 break;
1332 }
1333 }
1334 CANNOT_HAPPEN();
1335 }
1336
hasNonInheritedC(const Identifier * ident) const1337 bool LeaderFlowObj::hasNonInheritedC(const Identifier *ident) const
1338 {
1339 Identifier::SyntacticKey key;
1340 if (ident->syntacticKey(key)) {
1341 switch (key) {
1342 case Identifier::keyLength:
1343 case Identifier::keyBreakBeforePriority:
1344 case Identifier::keyBreakAfterPriority:
1345 return 1;
1346 default:
1347 break;
1348 }
1349 }
1350 return 0;
1351 }
1352
copy(Collector & c) const1353 FlowObj *LeaderFlowObj::copy(Collector &c) const
1354 {
1355 return new (c) LeaderFlowObj(*this);
1356 }
1357
1358 class CharacterFlowObj : public FlowObj {
1359 public:
operator new(size_t,Collector & c)1360 void *operator new(size_t, Collector &c) {
1361 return c.allocateObject(1);
1362 }
1363 CharacterFlowObj();
1364 CharacterFlowObj(const CharacterFlowObj &);
1365 void processInner(ProcessContext &);
1366 FlowObj *copy(Collector &) const;
1367 void setNonInheritedC(const Identifier *, ELObj *,
1368 const Location &, Interpreter &);
1369 bool hasNonInheritedC(const Identifier *) const;
characterStyle(ProcessContext &,StyleObj * & style,FOTBuilder::CharacterNIC & nic)1370 bool characterStyle(ProcessContext &, StyleObj *&style, FOTBuilder::CharacterNIC &nic) {
1371 style = style_;
1372 nic = *nic_;
1373 return 1;
1374 }
isCharacter()1375 bool isCharacter() { return 1; }
1376 private:
1377 Owner<FOTBuilder::CharacterNIC> nic_;
1378 };
1379
CharacterFlowObj()1380 CharacterFlowObj::CharacterFlowObj()
1381 : nic_(new FOTBuilder::CharacterNIC)
1382 {
1383 }
1384
CharacterFlowObj(const CharacterFlowObj & fo)1385 CharacterFlowObj::CharacterFlowObj(const CharacterFlowObj &fo)
1386 : FlowObj(fo), nic_(new FOTBuilder::CharacterNIC(*fo.nic_))
1387 {
1388 }
1389
processInner(ProcessContext & context)1390 void CharacterFlowObj::processInner(ProcessContext &context)
1391 {
1392 context.currentFOTBuilder().character(*nic_);
1393 }
1394
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)1395 void CharacterFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
1396 const Location &loc, Interpreter &interp)
1397 {
1398 Identifier::SyntacticKey key;
1399 if (ident->syntacticKey(key)) {
1400 switch (key) {
1401 case Identifier::keyIsSpace:
1402 if (interp.convertBooleanC(obj, ident, loc, nic_->isSpace))
1403 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cIsSpace);
1404 return;
1405 case Identifier::keyIsRecordEnd:
1406 if (interp.convertBooleanC(obj, ident, loc, nic_->isRecordEnd))
1407 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cIsRecordEnd);
1408 return;
1409 case Identifier::keyIsInputTab:
1410 if (interp.convertBooleanC(obj, ident, loc, nic_->isInputTab))
1411 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cIsInputTab);
1412 return;
1413 case Identifier::keyIsInputWhitespace:
1414 if (interp.convertBooleanC(obj, ident, loc, nic_->isInputWhitespace))
1415 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cIsInputWhitespace);
1416 return;
1417 case Identifier::keyIsPunct:
1418 if (interp.convertBooleanC(obj, ident, loc, nic_->isPunct))
1419 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cIsPunct);
1420 return;
1421 case Identifier::keyIsDropAfterLineBreak:
1422 if (interp.convertBooleanC(obj, ident, loc, nic_->isDropAfterLineBreak))
1423 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cIsDropAfterLineBreak);
1424 return;
1425 case Identifier::keyIsDropUnlessBeforeLineBreak:
1426 if (interp.convertBooleanC(obj, ident, loc, nic_->isDropUnlessBeforeLineBreak))
1427 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cIsDropUnlessBeforeLineBreak);
1428 return;
1429 case Identifier::keyBreakBeforePriority:
1430 if (interp.convertIntegerC(obj, ident, loc, nic_->breakBeforePriority))
1431 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cBreakBeforePriority);
1432 return;
1433 case Identifier::keyBreakAfterPriority:
1434 if (interp.convertIntegerC(obj, ident, loc, nic_->breakAfterPriority))
1435 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cBreakAfterPriority);
1436 return;
1437 case Identifier::keyScript:
1438 {
1439 if (obj == interp.makeFalse())
1440 nic_->script = 0;
1441 else {
1442 StringC tem;
1443 if (!interp.convertStringC(obj, ident, loc, tem))
1444 return;
1445 nic_->script = interp.storePublicId(tem.data(), tem.size(), loc);
1446 }
1447 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cScript);
1448 }
1449 return;
1450 case Identifier::keyChar:
1451 if (interp.convertCharC(obj, ident, loc, nic_->ch))
1452 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cChar);
1453 return;
1454 case Identifier::keyGlyphId:
1455 {
1456 if (obj == interp.makeFalse()) {
1457 nic_->glyphId = FOTBuilder::GlyphId();
1458 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cGlyphId);
1459 return;
1460 }
1461 const FOTBuilder::GlyphId *p = obj->glyphId();
1462 if (!p) {
1463 interp.setNextLocation(loc);
1464 interp.message(InterpreterMessages::invalidCharacteristicValue,
1465 StringMessageArg(ident->name()));
1466 return;
1467 }
1468 nic_->glyphId = *p;
1469 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cGlyphId);
1470 }
1471 return;
1472 case Identifier::keyMathFontPosture:
1473 {
1474 static FOTBuilder::Symbol vals[] = {
1475 FOTBuilder::symbolFalse,
1476 FOTBuilder::symbolNotApplicable,
1477 FOTBuilder::symbolUpright,
1478 FOTBuilder::symbolOblique,
1479 FOTBuilder::symbolBackSlantedOblique,
1480 FOTBuilder::symbolItalic,
1481 FOTBuilder::symbolBackSlantedItalic,
1482 };
1483 if (interp.convertEnumC(vals, SIZEOF(vals), obj, ident, loc, nic_->mathFontPosture))
1484 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cMathFontPosture);
1485 }
1486 return;
1487 case Identifier::keyMathClass:
1488 {
1489 static FOTBuilder::Symbol vals[] = {
1490 FOTBuilder::symbolOrdinary,
1491 FOTBuilder::symbolOperator,
1492 FOTBuilder::symbolBinary,
1493 FOTBuilder::symbolRelation,
1494 FOTBuilder::symbolOpening,
1495 FOTBuilder::symbolClosing,
1496 FOTBuilder::symbolPunctuation,
1497 FOTBuilder::symbolInner,
1498 FOTBuilder::symbolSpace,
1499 };
1500 if (interp.convertEnumC(vals, SIZEOF(vals), obj, ident, loc, nic_->mathClass))
1501 nic_->specifiedC |= (1 << FOTBuilder::CharacterNIC::cMathClass);
1502 }
1503 return;
1504 case Identifier::keyStretchFactor:
1505 interp.convertRealC(obj, ident, loc, nic_->stretchFactor);
1506 return;
1507 default:
1508 break;
1509 }
1510 }
1511 CANNOT_HAPPEN();
1512 }
1513
hasNonInheritedC(const Identifier * ident) const1514 bool CharacterFlowObj::hasNonInheritedC(const Identifier *ident) const
1515 {
1516 Identifier::SyntacticKey key;
1517 if (ident->syntacticKey(key)) {
1518 switch (key) {
1519 case Identifier::keyChar:
1520 case Identifier::keyGlyphId:
1521 case Identifier::keyIsSpace:
1522 case Identifier::keyIsRecordEnd:
1523 case Identifier::keyIsInputTab:
1524 case Identifier::keyIsInputWhitespace:
1525 case Identifier::keyIsPunct:
1526 case Identifier::keyIsDropAfterLineBreak:
1527 case Identifier::keyIsDropUnlessBeforeLineBreak:
1528 case Identifier::keyScript:
1529 case Identifier::keyMathClass:
1530 case Identifier::keyMathFontPosture:
1531 case Identifier::keyStretchFactor:
1532 case Identifier::keyBreakBeforePriority:
1533 case Identifier::keyBreakAfterPriority:
1534 return 1;
1535 default:
1536 break;
1537 }
1538 }
1539 return 0;
1540 }
1541
copy(Collector & c) const1542 FlowObj *CharacterFlowObj::copy(Collector &c) const
1543 {
1544 return new (c) CharacterFlowObj(*this);
1545 }
1546
1547 class MathSequenceFlowObj : public CompoundFlowObj {
1548 public:
MathSequenceFlowObj()1549 MathSequenceFlowObj() { }
processInner(ProcessContext & context)1550 void processInner(ProcessContext &context) {
1551 FOTBuilder &fotb = context.currentFOTBuilder();
1552 fotb.startMathSequence();
1553 CompoundFlowObj::processInner(context);
1554 fotb.endMathSequence();
1555 }
copy(Collector & c) const1556 FlowObj *copy(Collector &c) const {
1557 return new (c) MathSequenceFlowObj(*this);
1558 }
1559 };
1560
1561 class FractionFlowObj : public CompoundFlowObj {
1562 public:
FractionFlowObj()1563 FractionFlowObj() { }
1564 void processInner(ProcessContext &);
1565 FlowObj *copy(Collector &) const;
1566 };
1567
processInner(ProcessContext & context)1568 void FractionFlowObj::processInner(ProcessContext &context)
1569 {
1570 FOTBuilder &fotb = context.currentFOTBuilder();
1571 Vector<FOTBuilder *> fotbs(2);
1572 fotb.startFraction(fotbs[0], fotbs[1]);
1573 Vector<size_t> dep;
1574 StyleObj *fractionBarStyle = 0;
1575 SosofoObj *sosofo
1576 = context.currentStyleStack().actual(context.vm().interp->fractionBarC(),
1577 *context.vm().interp, dep)->asSosofo();
1578 if (sosofo)
1579 sosofo->ruleStyle(context, fractionBarStyle);
1580 if (fractionBarStyle)
1581 context.currentStyleStack().push(fractionBarStyle, context.vm(), fotb);
1582 fotb.fractionBar();
1583 if (fractionBarStyle)
1584 context.currentStyleStack().pop();
1585 Vector<SymbolObj *> labels(2);
1586 labels[0] = context.vm().interp->portName(Interpreter::portNumerator);
1587 labels[1] = context.vm().interp->portName(Interpreter::portDenominator);
1588 context.pushPorts(0, labels, fotbs);
1589 // Fraction flow object doesn't have principal port,
1590 // so clear the current connection.
1591 CompoundFlowObj::processInner(context);
1592 context.popPorts();
1593 fotb.endFraction();
1594 }
1595
copy(Collector & c) const1596 FlowObj *FractionFlowObj::copy(Collector &c) const
1597 {
1598 return new (c) FractionFlowObj(*this);
1599 }
1600
1601 class UnmathFlowObj : public CompoundFlowObj {
1602 public:
UnmathFlowObj()1603 UnmathFlowObj() { }
processInner(ProcessContext & context)1604 void processInner(ProcessContext &context) {
1605 FOTBuilder &fotb = context.currentFOTBuilder();
1606 fotb.startUnmath();
1607 CompoundFlowObj::processInner(context);
1608 fotb.endUnmath();
1609 }
copy(Collector & c) const1610 FlowObj *copy(Collector &c) const {
1611 return new (c) UnmathFlowObj(*this);
1612 }
1613 };
1614
1615 class SuperscriptFlowObj : public CompoundFlowObj {
1616 public:
SuperscriptFlowObj()1617 SuperscriptFlowObj() { }
processInner(ProcessContext & context)1618 void processInner(ProcessContext &context) {
1619 FOTBuilder &fotb = context.currentFOTBuilder();
1620 fotb.startSuperscript();
1621 CompoundFlowObj::processInner(context);
1622 fotb.endSuperscript();
1623 }
copy(Collector & c) const1624 FlowObj *copy(Collector &c) const {
1625 return new (c) SuperscriptFlowObj(*this);
1626 }
1627 };
1628
1629 class SubscriptFlowObj : public CompoundFlowObj {
1630 public:
SubscriptFlowObj()1631 SubscriptFlowObj() { }
processInner(ProcessContext & context)1632 void processInner(ProcessContext &context) {
1633 FOTBuilder &fotb = context.currentFOTBuilder();
1634 fotb.startSubscript();
1635 CompoundFlowObj::processInner(context);
1636 fotb.endSubscript();
1637 }
copy(Collector & c) const1638 FlowObj *copy(Collector &c) const {
1639 return new (c) SubscriptFlowObj(*this);
1640 }
1641 };
1642
1643 class ScriptFlowObj : public CompoundFlowObj {
1644 public:
ScriptFlowObj()1645 ScriptFlowObj() { }
1646 void processInner(ProcessContext &);
copy(Collector & c) const1647 FlowObj *copy(Collector &c) const {
1648 return new (c) ScriptFlowObj(*this);
1649 }
1650
1651 };
1652
processInner(ProcessContext & context)1653 void ScriptFlowObj::processInner(ProcessContext &context)
1654 {
1655 FOTBuilder &fotb = context.currentFOTBuilder();
1656 Vector<FOTBuilder *> fotbs(6);
1657 fotb.startScript(fotbs[0], fotbs[1], fotbs[2], fotbs[3],
1658 fotbs[4], fotbs[5]);
1659 Vector<SymbolObj *> labels(6);
1660 labels[0] = context.vm().interp->portName(Interpreter::portPreSup);
1661 labels[1] = context.vm().interp->portName(Interpreter::portPreSub);
1662 labels[2] = context.vm().interp->portName(Interpreter::portPostSup);
1663 labels[3] = context.vm().interp->portName(Interpreter::portPostSub);
1664 labels[4] = context.vm().interp->portName(Interpreter::portMidSup);
1665 labels[5] = context.vm().interp->portName(Interpreter::portMidSub);
1666 context.pushPorts(1, labels, fotbs);
1667 CompoundFlowObj::processInner(context);
1668 context.popPorts();
1669 fotb.endScript();
1670 }
1671
1672 class MarkFlowObj : public CompoundFlowObj {
1673 public:
MarkFlowObj()1674 MarkFlowObj() { }
1675 void processInner(ProcessContext &);
copy(Collector & c) const1676 FlowObj *copy(Collector &c) const {
1677 return new (c) MarkFlowObj(*this);
1678 }
1679 };
1680
processInner(ProcessContext & context)1681 void MarkFlowObj::processInner(ProcessContext &context)
1682 {
1683 FOTBuilder &fotb = context.currentFOTBuilder();
1684 Vector<FOTBuilder *> fotbs(2);
1685 fotb.startMark(fotbs[0], fotbs[1]);
1686 Vector<SymbolObj *> labels(2);
1687 labels[0] = context.vm().interp->portName(Interpreter::portOverMark);
1688 labels[1] = context.vm().interp->portName(Interpreter::portUnderMark);
1689 context.pushPorts(1, labels, fotbs);
1690 CompoundFlowObj::processInner(context);
1691 context.popPorts();
1692 fotb.endMark();
1693 }
1694
1695 class FenceFlowObj : public CompoundFlowObj {
1696 public:
FenceFlowObj()1697 FenceFlowObj() { }
1698 void processInner(ProcessContext &);
copy(Collector & c) const1699 FlowObj *copy(Collector &c) const {
1700 return new (c) FenceFlowObj(*this);
1701 }
1702 };
1703
processInner(ProcessContext & context)1704 void FenceFlowObj::processInner(ProcessContext &context)
1705 {
1706 FOTBuilder &fotb = context.currentFOTBuilder();
1707 Vector<FOTBuilder *> fotbs(2);
1708 fotb.startFence(fotbs[0], fotbs[1]);
1709 Vector<SymbolObj *> labels(2);
1710 labels[0] = context.vm().interp->portName(Interpreter::portOpen);
1711 labels[1] = context.vm().interp->portName(Interpreter::portClose);
1712 context.pushPorts(1, labels, fotbs);
1713 CompoundFlowObj::processInner(context);
1714 context.popPorts();
1715 fotb.endFence();
1716 }
1717
1718 class RadicalFlowObj : public CompoundFlowObj {
1719 public:
RadicalFlowObj()1720 RadicalFlowObj() : radical_(0) { }
1721 void processInner(ProcessContext &);
copy(Collector & c) const1722 FlowObj *copy(Collector &c) const {
1723 return new (c) RadicalFlowObj(*this);
1724 }
1725 void setNonInheritedC(const Identifier *, ELObj *,
1726 const Location &, Interpreter &);
1727 bool hasNonInheritedC(const Identifier *) const;
traceSubObjects(Collector & c) const1728 void traceSubObjects(Collector &c) const {
1729 c.trace(radical_);
1730 CompoundFlowObj::traceSubObjects(c);
1731 }
1732 private:
1733 SosofoObj *radical_;
1734 };
1735
processInner(ProcessContext & context)1736 void RadicalFlowObj::processInner(ProcessContext &context)
1737 {
1738 FOTBuilder &fotb = context.currentFOTBuilder();
1739 Vector<FOTBuilder *> fotbs(1);
1740 fotb.startRadical(fotbs[0]);
1741 StyleObj *style;
1742 FOTBuilder::CharacterNIC nic;
1743 if (radical_ && radical_->characterStyle(context, style, nic)) {
1744 if (style)
1745 context.currentStyleStack().push(style, context.vm(), fotb);
1746 fotb.radicalRadical(nic);
1747 if (style)
1748 context.currentStyleStack().pop();
1749 }
1750 else
1751 fotb.radicalRadicalDefaulted();
1752 Vector<SymbolObj *> labels(1);
1753 labels[0] = context.vm().interp->portName(Interpreter::portDegree);
1754 context.pushPorts(1, labels, fotbs);
1755 CompoundFlowObj::processInner(context);
1756 context.popPorts();
1757 fotb.endRadical();
1758 }
1759
hasNonInheritedC(const Identifier * ident) const1760 bool RadicalFlowObj::hasNonInheritedC(const Identifier *ident) const
1761 {
1762 Identifier::SyntacticKey key;
1763 return ident->syntacticKey(key) && key == Identifier::keyRadical;
1764 }
1765
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)1766 void RadicalFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
1767 const Location &loc, Interpreter &interp)
1768 {
1769 radical_ = obj->asSosofo();
1770 if (!radical_ || !radical_->isCharacter()) {
1771 interp.setNextLocation(loc);
1772 interp.message(InterpreterMessages::invalidCharacteristicValue,
1773 StringMessageArg(ident->name()));
1774 }
1775 }
1776
1777 class MathOperatorFlowObj : public CompoundFlowObj {
1778 public:
MathOperatorFlowObj()1779 MathOperatorFlowObj() { }
1780 void processInner(ProcessContext &);
copy(Collector & c) const1781 FlowObj *copy(Collector &c) const {
1782 return new (c) MathOperatorFlowObj(*this);
1783 }
1784 };
1785
processInner(ProcessContext & context)1786 void MathOperatorFlowObj::processInner(ProcessContext &context)
1787 {
1788 FOTBuilder &fotb = context.currentFOTBuilder();
1789 Vector<FOTBuilder *> fotbs(3);
1790 fotb.startMathOperator(fotbs[0], fotbs[1], fotbs[2]);
1791 Vector<SymbolObj *> labels(3);
1792 labels[0] = context.vm().interp->portName(Interpreter::portOperator);
1793 labels[1] = context.vm().interp->portName(Interpreter::portLowerLimit);
1794 labels[2] = context.vm().interp->portName(Interpreter::portUpperLimit);
1795 context.pushPorts(1, labels, fotbs);
1796 CompoundFlowObj::processInner(context);
1797 context.popPorts();
1798 fotb.endMathOperator();
1799 }
1800
1801 class GridFlowObj : public CompoundFlowObj {
1802 public:
operator new(size_t,Collector & c)1803 void *operator new(size_t, Collector &c) {
1804 return c.allocateObject(1);
1805 }
1806 GridFlowObj();
1807 GridFlowObj(const GridFlowObj &);
1808 void processInner(ProcessContext &);
copy(Collector & c) const1809 FlowObj *copy(Collector &c) const {
1810 return new (c) GridFlowObj(*this);
1811 }
1812 void setNonInheritedC(const Identifier *, ELObj *,
1813 const Location &, Interpreter &);
1814 bool hasNonInheritedC(const Identifier *) const;
1815 private:
1816 Owner<FOTBuilder::GridNIC> nic_;
1817 };
1818
GridFlowObj()1819 GridFlowObj::GridFlowObj()
1820 : nic_(new FOTBuilder::GridNIC)
1821 {
1822 }
1823
GridFlowObj(const GridFlowObj & fo)1824 GridFlowObj::GridFlowObj(const GridFlowObj &fo)
1825 : CompoundFlowObj(fo), nic_(new FOTBuilder::GridNIC(*fo.nic_))
1826 {
1827 }
1828
processInner(ProcessContext & context)1829 void GridFlowObj::processInner(ProcessContext &context)
1830 {
1831 FOTBuilder &fotb = context.currentFOTBuilder();
1832 fotb.startGrid(*nic_);
1833 CompoundFlowObj::processInner(context);
1834 fotb.endGrid();
1835 }
1836
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)1837 void GridFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
1838 const Location &loc, Interpreter &interp)
1839 {
1840 long tem;
1841 if (!interp.convertIntegerC(obj, ident, loc, tem))
1842 return;
1843 if (tem <= 0) {
1844 interp.setNextLocation(loc);
1845 interp.message(InterpreterMessages::invalidCharacteristicValue,
1846 StringMessageArg(ident->name()));
1847 return;
1848 }
1849 Identifier::SyntacticKey key;
1850 if (ident->syntacticKey(key)) {
1851 switch (key) {
1852 case Identifier::keyGridNColumns:
1853 nic_->nColumns = tem;
1854 return;
1855 case Identifier::keyGridNRows:
1856 nic_->nRows = tem;
1857 return;
1858 default:
1859 break;
1860 }
1861 }
1862 CANNOT_HAPPEN();
1863 }
1864
hasNonInheritedC(const Identifier * ident) const1865 bool GridFlowObj::hasNonInheritedC(const Identifier *ident) const
1866 {
1867 Identifier::SyntacticKey key;
1868 if (ident->syntacticKey(key)) {
1869 switch (key) {
1870 case Identifier::keyGridNColumns:
1871 case Identifier::keyGridNRows:
1872 return 1;
1873 default:
1874 break;
1875 }
1876 }
1877 return 0;
1878 }
1879
1880 class GridCellFlowObj : public CompoundFlowObj {
1881 public:
operator new(size_t,Collector & c)1882 void *operator new(size_t, Collector &c) {
1883 return c.allocateObject(1);
1884 }
1885 GridCellFlowObj();
1886 GridCellFlowObj(const GridCellFlowObj &);
1887 void processInner(ProcessContext &);
copy(Collector & c) const1888 FlowObj *copy(Collector &c) const {
1889 return new (c) GridCellFlowObj(*this);
1890 }
1891 void setNonInheritedC(const Identifier *, ELObj *,
1892 const Location &, Interpreter &);
1893 bool hasNonInheritedC(const Identifier *) const;
1894 private:
1895 Owner<FOTBuilder::GridCellNIC> nic_;
1896 };
1897
GridCellFlowObj()1898 GridCellFlowObj::GridCellFlowObj()
1899 : nic_(new FOTBuilder::GridCellNIC)
1900 {
1901 }
1902
GridCellFlowObj(const GridCellFlowObj & fo)1903 GridCellFlowObj::GridCellFlowObj(const GridCellFlowObj &fo)
1904 : CompoundFlowObj(fo), nic_(new FOTBuilder::GridCellNIC(*fo.nic_))
1905 {
1906 }
1907
processInner(ProcessContext & context)1908 void GridCellFlowObj::processInner(ProcessContext &context)
1909 {
1910 FOTBuilder &fotb = context.currentFOTBuilder();
1911 fotb.startGridCell(*nic_);
1912 CompoundFlowObj::processInner(context);
1913 fotb.endGridCell();
1914 }
1915
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)1916 void GridCellFlowObj::setNonInheritedC(const Identifier *ident, ELObj *obj,
1917 const Location &loc, Interpreter &interp)
1918 {
1919 long tem;
1920 if (!interp.convertIntegerC(obj, ident, loc, tem))
1921 return;
1922 if (tem <= 0) {
1923 interp.setNextLocation(loc);
1924 interp.message(InterpreterMessages::invalidCharacteristicValue,
1925 StringMessageArg(ident->name()));
1926 return;
1927 }
1928 Identifier::SyntacticKey key;
1929 if (ident->syntacticKey(key)) {
1930 switch (key) {
1931 case Identifier::keyColumnNumber:
1932 nic_->columnNumber = tem;
1933 return;
1934 case Identifier::keyRowNumber:
1935 nic_->rowNumber = tem;
1936 return;
1937 default:
1938 break;
1939 }
1940 }
1941 CANNOT_HAPPEN();
1942 }
1943
hasNonInheritedC(const Identifier * ident) const1944 bool GridCellFlowObj::hasNonInheritedC(const Identifier *ident) const
1945 {
1946 Identifier::SyntacticKey key;
1947 if (ident->syntacticKey(key)) {
1948 switch (key) {
1949 case Identifier::keyColumnNumber:
1950 case Identifier::keyRowNumber:
1951 return 1;
1952 default:
1953 break;
1954 }
1955 }
1956 return 0;
1957 }
1958
1959 class TableFlowObj : public CompoundFlowObj {
1960 public:
operator new(size_t,Collector & c)1961 void *operator new(size_t, Collector &c) {
1962 return c.allocateObject(1);
1963 }
1964 struct NIC : public FOTBuilder::TableNIC {
NICDSSSL_NAMESPACE::TableFlowObj::NIC1965 NIC() : beforeRowBorder(0), afterRowBorder(0),
1966 beforeColumnBorder(0), afterColumnBorder(0) { }
1967 StyleObj *beforeRowBorder;
1968 StyleObj *afterRowBorder;
1969 StyleObj *beforeColumnBorder;
1970 StyleObj *afterColumnBorder;
1971 };
TableFlowObj()1972 TableFlowObj() : nic_(new NIC) { }
TableFlowObj(const TableFlowObj & fo)1973 TableFlowObj(const TableFlowObj &fo) : CompoundFlowObj(fo), nic_(new NIC(*fo.nic_)) { }
processInner(ProcessContext & context)1974 void processInner(ProcessContext &context) {
1975 context.startTable();
1976 FOTBuilder &fotb = context.currentFOTBuilder();
1977 fotb.startTable(*nic_);
1978 Interpreter &interp = *context.vm().interp;
1979 Vector<size_t> dep;
1980 ELObj *obj = context.currentStyleStack().actual(interp.tableBorderC(), interp, dep);
1981 StyleObj *borderStyle;
1982 if (obj == interp.makeFalse())
1983 borderStyle = interp.borderFalseStyle();
1984 else if (obj == interp.makeTrue())
1985 borderStyle = interp.borderTrueStyle();
1986 else {
1987 SosofoObj *sosofo = obj->asSosofo();
1988 if (!sosofo || !sosofo->tableBorderStyle(borderStyle))
1989 borderStyle = 0;
1990 }
1991 border(nic_->beforeRowBorder, borderStyle, &FOTBuilder::tableBeforeRowBorder, context);
1992 border(nic_->afterRowBorder, borderStyle, &FOTBuilder::tableAfterRowBorder, context);
1993 border(nic_->beforeColumnBorder, borderStyle, &FOTBuilder::tableBeforeColumnBorder, context);
1994 border(nic_->afterColumnBorder, borderStyle, &FOTBuilder::tableAfterColumnBorder, context);
1995 CompoundFlowObj::processInner(context);
1996 if (context.inTableRow())
1997 context.endTableRow();
1998 context.endTable();
1999 fotb.endTable();
2000 }
copy(Collector & c) const2001 FlowObj *copy(Collector &c) const {
2002 return new (c) TableFlowObj(*this);
2003 }
hasNonInheritedC(const Identifier * ident) const2004 bool hasNonInheritedC(const Identifier *ident) const {
2005 Identifier::SyntacticKey key;
2006 if (ident->syntacticKey(key)) {
2007 switch (key) {
2008 case Identifier::keyBeforeRowBorder:
2009 case Identifier::keyAfterRowBorder:
2010 case Identifier::keyBeforeColumnBorder:
2011 case Identifier::keyAfterColumnBorder:
2012 case Identifier::keyTableWidth:
2013 return 1;
2014 default:
2015 break;
2016 }
2017 }
2018 return isDisplayNIC(ident);
2019 }
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)2020 void setNonInheritedC(const Identifier *ident, ELObj *obj,
2021 const Location &loc, Interpreter &interp) {
2022 if (setDisplayNIC(*nic_, ident, obj, loc, interp))
2023 return;
2024 Identifier::SyntacticKey key;
2025 if (!ident->syntacticKey(key))
2026 CANNOT_HAPPEN();
2027 if (key == Identifier::keyTableWidth) {
2028 if (obj == interp.makeFalse())
2029 nic_->widthType = FOTBuilder::TableNIC::widthMinimum;
2030 else if (interp.convertLengthSpecC(obj, ident, loc, nic_->width))
2031 nic_->widthType = FOTBuilder::TableNIC::widthExplicit;
2032 return;
2033 }
2034 StyleObj *style;
2035 SosofoObj *sosofo = obj->asSosofo();
2036 if (!sosofo || !sosofo->tableBorderStyle(style)) {
2037 Boolean b;
2038 if (!interp.convertBooleanC(obj, ident, loc, b))
2039 return;
2040 style = b ? interp.borderTrueStyle() : interp.borderFalseStyle();
2041 }
2042 switch (key) {
2043 case Identifier::keyBeforeRowBorder:
2044 nic_->beforeRowBorder = style;
2045 break;
2046 case Identifier::keyAfterRowBorder:
2047 nic_->afterRowBorder = style;
2048 break;
2049 case Identifier::keyBeforeColumnBorder:
2050 nic_->beforeColumnBorder = style;
2051 break;
2052 case Identifier::keyAfterColumnBorder:
2053 nic_->afterColumnBorder = style;
2054 break;
2055 default:
2056 CANNOT_HAPPEN();
2057 }
2058 }
2059 private:
border(StyleObj * style,StyleObj * style2,void (FOTBuilder::* setter)(),ProcessContext & context)2060 void border(StyleObj *style, StyleObj *style2,
2061 void (FOTBuilder::*setter)(), ProcessContext &context) {
2062 FOTBuilder &fotb = context.currentFOTBuilder();
2063 if (!style)
2064 style = style2;
2065 if (style)
2066 context.currentStyleStack().push(style, context.vm(), fotb);
2067 (fotb.*setter)();
2068 if (style)
2069 context.currentStyleStack().pop();
2070 }
2071 Owner<NIC> nic_;
2072 };
2073
2074 class TablePartFlowObj : public CompoundFlowObj {
2075 public:
operator new(size_t,Collector & c)2076 void *operator new(size_t, Collector &c) {
2077 return c.allocateObject(1);
2078 }
TablePartFlowObj()2079 TablePartFlowObj() : nic_(new FOTBuilder::TablePartNIC) { }
TablePartFlowObj(const TablePartFlowObj & fo)2080 TablePartFlowObj(const TablePartFlowObj &fo)
2081 : CompoundFlowObj(fo), nic_(new FOTBuilder::TablePartNIC(*fo.nic_)) { }
processInner(ProcessContext & context)2082 void processInner(ProcessContext &context) {
2083 context.startTablePart();
2084 FOTBuilder &fotb = context.currentFOTBuilder();
2085 Vector<FOTBuilder *> fotbs(2);
2086 fotb.startTablePart(*nic_, fotbs[0], fotbs[1]);
2087 Vector<SymbolObj *> labels(2);
2088 labels[0] = context.vm().interp->portName(Interpreter::portHeader);
2089 labels[1] = context.vm().interp->portName(Interpreter::portFooter);
2090 context.pushPorts(1, labels, fotbs);
2091 CompoundFlowObj::processInner(context);
2092 context.popPorts();
2093 if (context.inTableRow())
2094 context.endTableRow();
2095 context.endTablePart();
2096 fotb.endTablePart();
2097 }
copy(Collector & c) const2098 FlowObj *copy(Collector &c) const {
2099 return new (c) TablePartFlowObj(*this);
2100 }
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)2101 void setNonInheritedC(const Identifier *ident, ELObj *obj,
2102 const Location &loc, Interpreter &interp) {
2103 setDisplayNIC(*nic_, ident, obj, loc, interp);
2104 }
hasNonInheritedC(const Identifier * ident) const2105 bool hasNonInheritedC(const Identifier *ident) const {
2106 if (!isDisplayNIC(ident))
2107 return 0;
2108 Identifier::SyntacticKey key;
2109 ident->syntacticKey(key);
2110 if (key == Identifier::keyPositionPreference)
2111 return 0;
2112 return 1;
2113 }
2114 private:
2115 Owner<FOTBuilder::TablePartNIC> nic_;
2116 };
2117
2118 class TableColumnFlowObj : public FlowObj {
2119 public:
operator new(size_t,Collector & c)2120 void *operator new(size_t, Collector &c) {
2121 return c.allocateObject(1);
2122 }
2123 struct NIC : public FOTBuilder::TableColumnNIC {
NICDSSSL_NAMESPACE::TableColumnFlowObj::NIC2124 NIC() : hasColumnNumber(0) { }
2125 bool hasColumnNumber;
2126 };
TableColumnFlowObj()2127 TableColumnFlowObj() : nic_(new NIC) { }
TableColumnFlowObj(const TableColumnFlowObj & fo)2128 TableColumnFlowObj(const TableColumnFlowObj &fo) : FlowObj(fo), nic_(new NIC(*fo.nic_)) { }
processInner(ProcessContext & context)2129 void processInner(ProcessContext &context) {
2130 if (nic_->hasColumnNumber) {
2131 context.currentFOTBuilder().tableColumn(*nic_);
2132 context.addTableColumn(nic_->columnIndex, nic_->nColumnsSpanned, style_);
2133 }
2134 else {
2135 FOTBuilder::TableColumnNIC nic(*nic_);
2136 nic.columnIndex = context.currentTableColumn();
2137 context.currentFOTBuilder().tableColumn(nic);
2138 context.addTableColumn(nic.columnIndex, nic_->nColumnsSpanned, style_);
2139 }
2140 }
copy(Collector & c) const2141 FlowObj *copy(Collector &c) const {
2142 return new (c) TableColumnFlowObj(*this);
2143 }
hasNonInheritedC(const Identifier * ident) const2144 bool hasNonInheritedC(const Identifier *ident) const {
2145 Identifier::SyntacticKey key;
2146 if (ident->syntacticKey(key)) {
2147 switch (key) {
2148 case Identifier::keyColumnNumber:
2149 case Identifier::keyNColumnsSpanned:
2150 case Identifier::keyWidth:
2151 return 1;
2152 default:
2153 break;
2154 }
2155 }
2156 return 0;
2157 }
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)2158 void setNonInheritedC(const Identifier *ident, ELObj *obj,
2159 const Location &loc, Interpreter &interp) {
2160 Identifier::SyntacticKey key;
2161 if (ident->syntacticKey(key)) {
2162 switch (key) {
2163 case Identifier::keyColumnNumber:
2164 case Identifier::keyNColumnsSpanned:
2165 {
2166 long n;
2167 if (!interp.convertIntegerC(obj, ident, loc, n))
2168 return;
2169 if (n <= 0) {
2170 interp.setNextLocation(loc);
2171 interp.message(InterpreterMessages::invalidCharacteristicValue,
2172 StringMessageArg(ident->name()));
2173 return;
2174 }
2175 if (key == Identifier::keyColumnNumber) {
2176 nic_->columnIndex = n - 1;
2177 nic_->hasColumnNumber = 1;
2178 }
2179 else
2180 nic_->nColumnsSpanned = n;
2181 }
2182 return;
2183 case Identifier::keyWidth:
2184 {
2185 const LengthSpec *ls = obj->lengthSpec();
2186 if (ls) {
2187 // width is a TableLengthSpec not just a LengthSpec
2188 if (ls->convert(nic_->width))
2189 nic_->hasWidth = 1;
2190 else
2191 interp.invalidCharacteristicValue(ident, loc);
2192 }
2193 else if (interp.convertLengthSpecC(obj, ident, loc, nic_->width))
2194 nic_->hasWidth = 1;
2195 }
2196 return;
2197 default:
2198 break;
2199 }
2200 }
2201 CANNOT_HAPPEN();
2202 }
2203 private:
2204 Owner<NIC> nic_;
2205 };
2206
2207 class TableRowFlowObj : public CompoundFlowObj {
2208 public:
TableRowFlowObj()2209 TableRowFlowObj() { }
pushStyle(ProcessContext &,unsigned &)2210 void pushStyle(ProcessContext &, unsigned &) { }
popStyle(ProcessContext &,unsigned)2211 void popStyle(ProcessContext &, unsigned) { }
processInner(ProcessContext & context)2212 void processInner(ProcessContext &context) {
2213 if (!context.inTable()) {
2214 // FIXME location
2215 context.vm().interp->message(InterpreterMessages::tableRowOutsideTable);
2216 CompoundFlowObj::processInner(context);
2217 return;
2218 }
2219 if (context.inTableRow())
2220 context.endTableRow();
2221 context.startTableRow(style_);
2222 CompoundFlowObj::processInner(context);
2223 if (context.inTableRow())
2224 context.endTableRow();
2225 // else FIXME give an error
2226 // must have used ends-row? in a table-row
2227 }
copy(Collector & c) const2228 FlowObj *copy(Collector &c) const {
2229 return new (c) TableRowFlowObj(*this);
2230 }
2231 };
2232
2233 class TableCellFlowObj : public CompoundFlowObj {
2234 public:
operator new(size_t,Collector & c)2235 void *operator new(size_t, Collector &c) {
2236 return c.allocateObject(1);
2237 }
2238 struct NIC : FOTBuilder::TableCellNIC {
NICDSSSL_NAMESPACE::TableCellFlowObj::NIC2239 NIC() : startsRow(0), endsRow(0), hasColumnNumber(0) { }
2240 bool hasColumnNumber;
2241 bool startsRow;
2242 bool endsRow;
2243 };
TableCellFlowObj(bool missing=0)2244 TableCellFlowObj(bool missing = 0) : nic_(new NIC) {
2245 if (missing)
2246 nic_->missing = 1;
2247 }
TableCellFlowObj(const TableCellFlowObj & fo)2248 TableCellFlowObj(const TableCellFlowObj &fo) : CompoundFlowObj(fo), nic_(new NIC(*fo.nic_)) { }
pushStyle(ProcessContext & context,unsigned & nPush)2249 void pushStyle(ProcessContext &context, unsigned &nPush) {
2250 if (context.inTableRow()) {
2251 if (nic_->startsRow) {
2252 context.endTableRow();
2253 context.startTableRow(0);
2254 }
2255 }
2256 else
2257 context.startTableRow(0);
2258 unsigned columnNumber
2259 = nic_->hasColumnNumber ? nic_->columnIndex : context.currentTableColumn();
2260 StyleObj *columnStyle = context.tableColumnStyle(columnNumber, nic_->nColumnsSpanned);
2261 if (columnStyle) {
2262 context.currentStyleStack().push(columnStyle, context.vm(), context.currentFOTBuilder());
2263 context.currentFOTBuilder().startSequence();
2264 nPush++;
2265 }
2266 StyleObj *rowStyle = context.tableRowStyle();
2267 if (rowStyle) {
2268 context.currentStyleStack().push(rowStyle, context.vm(), context.currentFOTBuilder());
2269 context.currentFOTBuilder().startSequence();
2270 nPush++;
2271 }
2272 CompoundFlowObj::pushStyle(context, nPush);
2273 }
popStyle(ProcessContext & context,unsigned nPush)2274 void popStyle(ProcessContext &context, unsigned nPush) {
2275 CompoundFlowObj::popStyle(context, nPush);
2276 for (unsigned i = 0; i < nPush; i++) {
2277 context.currentFOTBuilder().endSequence();
2278 context.currentStyleStack().pop();
2279 }
2280 if (nic_->endsRow)
2281 context.endTableRow();
2282 }
processInner(ProcessContext & context)2283 void processInner(ProcessContext &context) {
2284 if (!context.inTable()) {
2285 // FIXME location
2286 context.vm().interp->message(InterpreterMessages::tableCellOutsideTable);
2287 CompoundFlowObj::processInner(context);
2288 return;
2289 }
2290 FOTBuilder &fotb = context.currentFOTBuilder();
2291 if (!nic_->hasColumnNumber) {
2292 FOTBuilder::TableCellNIC nic(*nic_);
2293 nic.columnIndex = context.currentTableColumn();
2294 fotb.startTableCell(nic);
2295 if (!nic_->missing)
2296 context.noteTableCell(nic.columnIndex, nic.nColumnsSpanned, nic.nRowsSpanned);
2297 }
2298 else {
2299 fotb.startTableCell(*nic_);
2300 if (!nic_->missing)
2301 context.noteTableCell(nic_->columnIndex, nic_->nColumnsSpanned, nic_->nRowsSpanned);
2302 }
2303 Interpreter &interp = *context.vm().interp;
2304 border(interp.cellBeforeRowBorderC(), &FOTBuilder::tableCellBeforeRowBorder, context);
2305 border(interp.cellAfterRowBorderC(), &FOTBuilder::tableCellAfterRowBorder, context);
2306 border(interp.cellBeforeColumnBorderC(), &FOTBuilder::tableCellBeforeColumnBorder, context);
2307 border(interp.cellAfterColumnBorderC(), &FOTBuilder::tableCellAfterColumnBorder, context);
2308 CompoundFlowObj::processInner(context);
2309 fotb.endTableCell();
2310 }
copy(Collector & c) const2311 FlowObj *copy(Collector &c) const {
2312 return new (c) TableCellFlowObj(*this);
2313 }
hasNonInheritedC(const Identifier * ident) const2314 bool hasNonInheritedC(const Identifier *ident) const {
2315 Identifier::SyntacticKey key;
2316 if (ident->syntacticKey(key)) {
2317 switch (key) {
2318 case Identifier::keyNRowsSpanned:
2319 return 1;
2320 default:
2321 break;
2322 }
2323 }
2324 return 0;
2325 }
hasPseudoNonInheritedC(const Identifier * ident) const2326 bool hasPseudoNonInheritedC(const Identifier *ident) const {
2327 Identifier::SyntacticKey key;
2328 if (ident->syntacticKey(key)) {
2329 switch (key) {
2330 case Identifier::keyColumnNumber:
2331 case Identifier::keyNColumnsSpanned:
2332 case Identifier::keyIsStartsRow:
2333 case Identifier::keyIsEndsRow:
2334 return 1;
2335 default:
2336 break;
2337 }
2338 }
2339 return 0;
2340 }
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)2341 void setNonInheritedC(const Identifier *ident, ELObj *obj,
2342 const Location &loc, Interpreter &interp) {
2343 Identifier::SyntacticKey key;
2344 if (ident->syntacticKey(key)) {
2345 switch (key) {
2346 case Identifier::keyIsStartsRow:
2347 interp.convertBooleanC(obj, ident, loc, nic_->startsRow);
2348 return;
2349 case Identifier::keyIsEndsRow:
2350 interp.convertBooleanC(obj, ident, loc, nic_->endsRow);
2351 return;
2352 case Identifier::keyColumnNumber:
2353 case Identifier::keyNColumnsSpanned:
2354 case Identifier::keyNRowsSpanned:
2355 {
2356 long n;
2357 if (!interp.convertIntegerC(obj, ident, loc, n))
2358 return;
2359 if (n <= 0) {
2360 interp.setNextLocation(loc);
2361 interp.message(InterpreterMessages::invalidCharacteristicValue,
2362 StringMessageArg(ident->name()));
2363 return;
2364 }
2365 if (key == Identifier::keyColumnNumber) {
2366 nic_->columnIndex = n - 1;
2367 nic_->hasColumnNumber = 1;
2368 }
2369 else if (key == Identifier::keyNColumnsSpanned)
2370 nic_->nColumnsSpanned = n;
2371 else
2372 nic_->nRowsSpanned = n;
2373 }
2374 return;
2375 default:
2376 break;
2377 }
2378 }
2379 CANNOT_HAPPEN();
2380 }
2381 private:
border(const ConstPtr<InheritedC> & ic,void (FOTBuilder::* setter)(),ProcessContext & context)2382 void border(const ConstPtr<InheritedC> &ic, void (FOTBuilder::*setter)(),
2383 ProcessContext &context) {
2384 Interpreter &interp = *context.vm().interp;
2385 Vector<size_t> dep;
2386 ELObj *obj = context.currentStyleStack().actual(ic, interp, dep);
2387 StyleObj *style;
2388 if (obj == interp.makeFalse())
2389 style = interp.borderFalseStyle();
2390 else if (obj == interp.makeTrue())
2391 style = interp.borderTrueStyle();
2392 else {
2393 SosofoObj *sosofo = obj->asSosofo();
2394 if (!sosofo || !sosofo->tableBorderStyle(style))
2395 style = 0;
2396 }
2397 FOTBuilder &fotb = context.currentFOTBuilder();
2398 if (style)
2399 context.currentStyleStack().push(style, context.vm(), fotb);
2400 (fotb.*setter)();
2401 if (style)
2402 context.currentStyleStack().pop();
2403 }
2404 Owner<NIC> nic_;
2405 };
2406
2407 class TableBorderFlowObj : public FlowObj {
2408 public:
TableBorderFlowObj()2409 TableBorderFlowObj() { }
process(ProcessContext &)2410 void process(ProcessContext &) { }
processInner(ProcessContext &)2411 void processInner(ProcessContext &) { }
tableBorderStyle(StyleObj * & style)2412 bool tableBorderStyle(StyleObj *&style) {
2413 style = style_;
2414 return 1;
2415 }
copy(Collector & c) const2416 FlowObj *copy(Collector &c) const {
2417 return new (c) TableBorderFlowObj(*this);
2418 }
2419 };
2420
2421
startTable()2422 void ProcessContext::startTable()
2423 {
2424 tableStack_.insert(new Table);
2425 }
2426
endTable()2427 void ProcessContext::endTable()
2428 {
2429 coverSpannedRows();
2430 delete tableStack_.get();
2431 }
2432
coverSpannedRows()2433 void ProcessContext::coverSpannedRows()
2434 {
2435 // Generate empty cells to cover any remaining vertical spans
2436 Table *table = tableStack_.head();
2437 if (!table)
2438 return;
2439 unsigned n = 0;
2440 for (size_t i = 0; i < table->covered.size(); i++)
2441 if (table->covered[i] > n)
2442 n = table->covered[i];
2443 for (; n > 0; n--) {
2444 SosofoObj *content = new (*vm().interp) EmptySosofoObj;
2445 ELObjDynamicRoot protect(*vm().interp, content);
2446 TableRowFlowObj *row = new (*vm().interp) TableRowFlowObj;
2447 row->setContent(content);
2448 protect = row;
2449 row->process(*this);
2450 }
2451 }
2452
startTablePart()2453 void ProcessContext::startTablePart()
2454 {
2455 Table *table = tableStack_.head();
2456 if (table) {
2457 table->currentColumn = 0;
2458 table->rowStyle = 0;
2459 table->columnStyles.clear();
2460 table->covered.clear();
2461 table->nColumns = 0;
2462 }
2463 }
2464
endTablePart()2465 void ProcessContext::endTablePart()
2466 {
2467 coverSpannedRows();
2468 }
2469
addTableColumn(unsigned columnIndex,unsigned span,StyleObj * style)2470 void ProcessContext::addTableColumn(unsigned columnIndex, unsigned span, StyleObj *style)
2471 {
2472 Table *table = tableStack_.head();
2473 if (table) {
2474 table->currentColumn = columnIndex + span;
2475 if (columnIndex >= table->columnStyles.size())
2476 table->columnStyles.resize(columnIndex + 1);
2477 Vector<StyleObj *> &tem = table->columnStyles[columnIndex];
2478 if (span > 0) {
2479 while (tem.size() < span)
2480 tem.push_back((StyleObj *)0);
2481 tem[span - 1] = style;
2482 }
2483 }
2484 }
2485
currentTableColumn()2486 unsigned ProcessContext::currentTableColumn()
2487 {
2488 Table *table = tableStack_.head();
2489 if (table)
2490 return table->currentColumn;
2491 return 0;
2492 }
2493
noteTableCell(unsigned colIndex,unsigned colSpan,unsigned rowSpan)2494 void ProcessContext::noteTableCell(unsigned colIndex, unsigned colSpan, unsigned rowSpan)
2495 {
2496 Table *table = tableStack_.head();
2497 if (!table)
2498 return;
2499 table->currentColumn = colIndex + colSpan;
2500 Vector<unsigned> &covered = table->covered;
2501 for (size_t i = covered.size(); i < colIndex + colSpan; i++)
2502 covered.push_back(0);
2503 for (size_t i = 0; i < colSpan; i++)
2504 covered[colIndex + i] = rowSpan;
2505 if (colIndex + colSpan > table->nColumns)
2506 table->nColumns = colIndex + colSpan;
2507 }
2508
tableColumnStyle(unsigned columnIndex,unsigned span)2509 StyleObj *ProcessContext::tableColumnStyle(unsigned columnIndex, unsigned span)
2510 {
2511 Table *table = tableStack_.head();
2512 if (table) {
2513 if (columnIndex < table->columnStyles.size()) {
2514 Vector<StyleObj *> &tem = table->columnStyles[columnIndex];
2515 if (span > 0 && span <= tem.size())
2516 return tem[span - 1];
2517 }
2518 }
2519 return 0;
2520 }
2521
tableRowStyle()2522 StyleObj *ProcessContext::tableRowStyle()
2523 {
2524 Table *table = tableStack_.head();
2525 if (table)
2526 return table->rowStyle;
2527 return 0;
2528 }
2529
startTableRow(StyleObj * style)2530 void ProcessContext::startTableRow(StyleObj *style)
2531 {
2532 Table *table = tableStack_.head();
2533 if (table) {
2534 table->rowStyle = style;
2535 table->currentColumn = 0;
2536 table->inTableRow = 1;
2537 table->rowConnectableLevel = connectionStack_.head()->connectableLevel;
2538 }
2539 currentFOTBuilder().startTableRow();
2540 }
2541
endTableRow()2542 void ProcessContext::endTableRow()
2543 {
2544 Table *table = tableStack_.head();
2545 if (table) {
2546 // Fill in blank cells
2547 Vector<unsigned> &covered = table->covered;
2548 for (size_t i = 0; i < table->nColumns + 1; i++) {
2549 if (i >= covered.size() || !covered[i]) {
2550 table->currentColumn = i;
2551 SosofoObj *content = new (*vm().interp) EmptySosofoObj;
2552 ELObjDynamicRoot protect(*vm().interp, content);
2553 // The last cell is a dummy one
2554 TableCellFlowObj *cell = new (*vm().interp) TableCellFlowObj(i >= table->nColumns);
2555 cell->setContent(content);
2556 protect = cell;
2557 cell->process(*this);
2558 }
2559 // cell->process() will cover it
2560 if (i < table->nColumns)
2561 covered[i] -= 1;
2562 }
2563 table->inTableRow = 0;
2564 }
2565 currentFOTBuilder().endTableRow();
2566 }
2567
inTableRow()2568 bool ProcessContext::inTableRow()
2569 {
2570 Table *table = tableStack_.head();
2571 if (table)
2572 return table->inTableRow;
2573 return 0;
2574 }
2575
Table()2576 ProcessContext::Table::Table()
2577 : rowStyle(0), currentColumn(0), inTableRow(0), nColumns(0)
2578 {
2579 }
2580
2581
2582 // Flow object classes declared with declare-flow-object-class
2583 // that we don't know about are assumed to have one principal port
2584 // and accept any non-inherited characteristic.
2585
2586 class UnknownFlowObj : public CompoundFlowObj {
2587 public:
UnknownFlowObj()2588 UnknownFlowObj() { }
copy(Collector & c) const2589 FlowObj *copy(Collector &c) const {
2590 return new (c) UnknownFlowObj(*this);
2591 }
setNonInheritedC(const Identifier *,ELObj *,const Location &,Interpreter &)2592 void setNonInheritedC(const Identifier *, ELObj *,
2593 const Location &, Interpreter &) { }
hasNonInheritedC(const Identifier * ident) const2594 bool hasNonInheritedC(const Identifier *ident) const {
2595 Identifier::SyntacticKey syn;
2596 if (ident->syntacticKey(syn)
2597 && (syn == Identifier::keyLabel || syn == Identifier::keyContentMap))
2598 return 0;
2599 if (!ident->inheritedC().isNull())
2600 return 0;
2601 return 1;
2602 }
2603 };
2604
2605 class FormattingInstructionFlowObj : public FlowObj {
2606 public:
operator new(size_t,Collector & c)2607 void *operator new(size_t, Collector &c) {
2608 return c.allocateObject(1);
2609 }
FormattingInstructionFlowObj()2610 FormattingInstructionFlowObj() { }
processInner(ProcessContext & context)2611 void processInner(ProcessContext &context) {
2612 context.currentFOTBuilder().formattingInstruction(data_);
2613 }
copy(Collector & c) const2614 FlowObj *copy(Collector &c) const {
2615 return new (c) FormattingInstructionFlowObj(*this);
2616 }
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)2617 void setNonInheritedC(const Identifier *ident, ELObj *obj,
2618 const Location &loc, Interpreter &interp) {
2619 interp.convertStringC(obj, ident, loc, data_);
2620 }
hasNonInheritedC(const Identifier * ident) const2621 bool hasNonInheritedC(const Identifier *ident) const {
2622 Identifier::SyntacticKey key;
2623 return ident->syntacticKey(key) && key == Identifier::keyData;
2624 }
2625 private:
2626 StringC data_;
2627 };
2628
2629 class ELObjExtensionFlowObjValue : public FOTBuilder::ExtensionFlowObj::Value {
2630 public:
ELObjExtensionFlowObjValue(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)2631 ELObjExtensionFlowObjValue(const Identifier *ident, ELObj *obj,
2632 const Location &loc, Interpreter &interp)
2633 : ident_(ident), obj_(obj), loc_(&loc), interp_(&interp) { }
convertString(StringC & result) const2634 bool convertString(StringC &result) const {
2635 return interp_->convertStringC(obj_, ident_, *loc_, result);
2636 }
convertStringPairList(Vector<StringC> & v) const2637 bool convertStringPairList(Vector<StringC> &v) const {
2638 ELObj *obj = obj_;
2639 for (;;) {
2640 if (obj->isNil())
2641 return 1;
2642 PairObj *pair = obj->asPair();
2643 if (!pair)
2644 break;
2645 obj = pair->cdr();
2646 PairObj *att = pair->car()->asPair();
2647 if (!att)
2648 break;
2649 const Char *s;
2650 size_t n;
2651 if (!att->car()->stringData(s, n))
2652 break;
2653 v.resize(v.size() + 1);
2654 v.back().assign(s, n);
2655 att = att->cdr()->asPair();
2656 if (!att || !att->car()->stringData(s, n) || !att->cdr()->isNil()) {
2657 v.resize(v.size() - 1);
2658 break;
2659 }
2660 v.resize(v.size() + 1);
2661 v.back().assign(s, n);
2662 }
2663 interp_->setNextLocation(*loc_);
2664 interp_->message(InterpreterMessages::invalidCharacteristicValue,
2665 StringMessageArg(ident_->name()));
2666 return 0;
2667 }
convertStringList(Vector<StringC> & v) const2668 bool convertStringList(Vector<StringC> &v) const {
2669 ELObj *obj = obj_;
2670 for (;;) {
2671 if (obj->isNil())
2672 return 1;
2673 PairObj *pair = obj->asPair();
2674 if (!pair)
2675 break;
2676 const Char *s;
2677 size_t n;
2678 if (!pair->car()->stringData(s, n))
2679 break;
2680 v.resize(v.size() + 1);
2681 v.back().assign(s, n);
2682 obj = pair->cdr();
2683 }
2684 interp_->setNextLocation(*loc_);
2685 interp_->message(InterpreterMessages::invalidCharacteristicValue,
2686 StringMessageArg(ident_->name()));
2687 return 0;
2688 }
convertBoolean(bool & result) const2689 bool convertBoolean(bool &result) const {
2690 return interp_->convertBooleanC(obj_, ident_, *loc_, result);
2691 }
2692 private:
2693 ELObj *obj_;
2694 const Identifier *ident_;
2695 const Location *loc_;
2696 Interpreter *interp_;
2697 };
2698
2699 class ExtensionFlowObj : public FlowObj {
2700 public:
operator new(size_t,Collector & c)2701 void *operator new(size_t, Collector &c) {
2702 return c.allocateObject(1);
2703 }
2704 ExtensionFlowObj(const FOTBuilder::ExtensionFlowObj &);
2705 ExtensionFlowObj(const ExtensionFlowObj &);
2706 void processInner(ProcessContext &);
2707 FlowObj *copy(Collector &) const;
2708 bool hasNonInheritedC(const Identifier *) const;
2709 void setNonInheritedC(const Identifier *, ELObj *,
2710 const Location &, Interpreter &);
2711 private:
2712 Owner<FOTBuilder::ExtensionFlowObj> fo_;
2713 };
2714
ExtensionFlowObj(const FOTBuilder::ExtensionFlowObj & fo)2715 ExtensionFlowObj::ExtensionFlowObj(const FOTBuilder::ExtensionFlowObj &fo)
2716 : fo_(fo.copy())
2717 {
2718 }
2719
ExtensionFlowObj(const ExtensionFlowObj & fo)2720 ExtensionFlowObj::ExtensionFlowObj(const ExtensionFlowObj &fo)
2721 : FlowObj(fo), fo_(fo.fo_->copy())
2722 {
2723 }
2724
processInner(ProcessContext & context)2725 void ExtensionFlowObj::processInner(ProcessContext &context)
2726 {
2727 context.currentFOTBuilder().extension(*fo_, context.vm().currentNode);
2728 }
2729
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)2730 void ExtensionFlowObj::setNonInheritedC(const Identifier *ident,
2731 ELObj *obj,
2732 const Location &loc,
2733 Interpreter &interp)
2734 {
2735 fo_->setNIC(ident->name(), ELObjExtensionFlowObjValue(ident, obj, loc, interp));
2736 }
2737
hasNonInheritedC(const Identifier * ident) const2738 bool ExtensionFlowObj::hasNonInheritedC(const Identifier *ident) const
2739 {
2740 return fo_->hasNIC(ident->name());
2741 }
2742
copy(Collector & c) const2743 FlowObj *ExtensionFlowObj::copy(Collector &c) const
2744 {
2745 return new (c) ExtensionFlowObj(*this);
2746 }
2747
2748 class CompoundExtensionFlowObj : public CompoundFlowObj {
2749 public:
operator new(size_t,Collector & c)2750 void *operator new(size_t, Collector &c) {
2751 return c.allocateObject(1);
2752 }
2753 CompoundExtensionFlowObj(const FOTBuilder::CompoundExtensionFlowObj &);
2754 CompoundExtensionFlowObj(const CompoundExtensionFlowObj &);
2755 void processInner(ProcessContext &);
2756 FlowObj *copy(Collector &) const;
2757 bool hasNonInheritedC(const Identifier *) const;
2758 void setNonInheritedC(const Identifier *, ELObj *,
2759 const Location &, Interpreter &);
2760 private:
2761 Owner<FOTBuilder::CompoundExtensionFlowObj> fo_;
2762 };
2763
CompoundExtensionFlowObj(const FOTBuilder::CompoundExtensionFlowObj & fo)2764 CompoundExtensionFlowObj::CompoundExtensionFlowObj(const FOTBuilder::CompoundExtensionFlowObj &fo)
2765 : fo_(fo.copy()->asCompoundExtensionFlowObj())
2766 {
2767 }
2768
CompoundExtensionFlowObj(const CompoundExtensionFlowObj & fo)2769 CompoundExtensionFlowObj::CompoundExtensionFlowObj(const CompoundExtensionFlowObj &fo)
2770 : CompoundFlowObj(fo), fo_(fo.fo_->copy()->asCompoundExtensionFlowObj())
2771 {
2772 }
2773
processInner(ProcessContext & context)2774 void CompoundExtensionFlowObj::processInner(ProcessContext &context)
2775 {
2776 FOTBuilder &fotb = context.currentFOTBuilder();
2777 Vector<StringC> portNames;
2778 fo_->portNames(portNames);
2779 Vector<FOTBuilder *> fotbs(portNames.size());
2780 fotb.startExtension(*fo_, context.vm().currentNode, fotbs);
2781 if (portNames.size()) {
2782 Vector<SymbolObj *> portSyms(portNames.size());
2783 for (size_t i = 0; i < portSyms.size(); i++)
2784 portSyms[i] = context.vm().interp->makeSymbol(portNames[i]);
2785 context.pushPorts(fo_->hasPrincipalPort(), portSyms, fotbs);
2786 CompoundFlowObj::processInner(context);
2787 context.popPorts();
2788 }
2789 else
2790 CompoundFlowObj::processInner(context);
2791 fotb.endExtension(*fo_);
2792 }
2793
setNonInheritedC(const Identifier * ident,ELObj * obj,const Location & loc,Interpreter & interp)2794 void CompoundExtensionFlowObj::setNonInheritedC(const Identifier *ident,
2795 ELObj *obj,
2796 const Location &loc,
2797 Interpreter &interp)
2798 {
2799 fo_->setNIC(ident->name(), ELObjExtensionFlowObjValue(ident, obj, loc, interp));
2800 }
2801
hasNonInheritedC(const Identifier * ident) const2802 bool CompoundExtensionFlowObj::hasNonInheritedC(const Identifier *ident) const
2803 {
2804 return fo_->hasNIC(ident->name());
2805 }
2806
copy(Collector & c) const2807 FlowObj *CompoundExtensionFlowObj::copy(Collector &c) const
2808 {
2809 return new (c) CompoundExtensionFlowObj(*this);
2810 }
2811
2812 #define FLOW_OBJ(name, string) \
2813 { FlowObj *tem = new (*this) name; \
2814 lookup(makeStringC(string))->setFlowObj(tem); \
2815 makePermanent(tem); }
2816
installFlowObjs()2817 void Interpreter::installFlowObjs()
2818 {
2819 FLOW_OBJ(SequenceFlowObj, "sequence");
2820 FLOW_OBJ(DisplayGroupFlowObj, "display-group");
2821 FLOW_OBJ(ParagraphFlowObj, "paragraph");
2822 FLOW_OBJ(ParagraphBreakFlowObj, "paragraph-break");
2823 FLOW_OBJ(LineFieldFlowObj, "line-field");
2824 FLOW_OBJ(ScoreFlowObj, "score");
2825 FLOW_OBJ(ExternalGraphicFlowObj, "external-graphic");
2826 FLOW_OBJ(RuleFlowObj, "rule");
2827 FLOW_OBJ(LeaderFlowObj, "leader");
2828 FLOW_OBJ(CharacterFlowObj, "character");
2829 FLOW_OBJ(BoxFlowObj, "box");
2830 FLOW_OBJ(AlignmentPointFlowObj, "alignment-point");
2831 FLOW_OBJ(SidelineFlowObj, "sideline");
2832 // simple-page
2833 FLOW_OBJ(SimplePageSequenceFlowObj, "simple-page-sequence");
2834 // tables
2835 FLOW_OBJ(TableFlowObj, "table");
2836 FLOW_OBJ(TablePartFlowObj, "table-part");
2837 FLOW_OBJ(TableColumnFlowObj, "table-column");
2838 FLOW_OBJ(TableRowFlowObj, "table-row");
2839 FLOW_OBJ(TableCellFlowObj, "table-cell");
2840 FLOW_OBJ(TableBorderFlowObj, "table-border");
2841 // online
2842 FLOW_OBJ(LinkFlowObj, "link");
2843 FLOW_OBJ(ScrollFlowObj, "scroll");
2844 FLOW_OBJ(MarginaliaFlowObj, "marginalia");
2845 FLOW_OBJ(MultiModeFlowObj, "multi-mode");
2846 // math
2847 FLOW_OBJ(MathSequenceFlowObj, "math-sequence");
2848 FLOW_OBJ(FractionFlowObj, "fraction");
2849 FLOW_OBJ(UnmathFlowObj, "unmath");
2850 FLOW_OBJ(SuperscriptFlowObj, "superscript");
2851 FLOW_OBJ(SubscriptFlowObj, "subscript");
2852 FLOW_OBJ(ScriptFlowObj, "script");
2853 FLOW_OBJ(MarkFlowObj, "mark");
2854 FLOW_OBJ(FenceFlowObj, "fence");
2855 FLOW_OBJ(RadicalFlowObj, "radical");
2856 FLOW_OBJ(MathOperatorFlowObj, "math-operator");
2857 FLOW_OBJ(GridFlowObj, "grid");
2858 FLOW_OBJ(GridCellFlowObj, "grid-cell");
2859 }
2860
installExtensionFlowObjectClass(Identifier * ident,const StringC & pubid,const Location & loc)2861 void Interpreter::installExtensionFlowObjectClass(Identifier *ident,
2862 const StringC &pubid,
2863 const Location &loc)
2864 {
2865 FlowObj *tem = 0;
2866 if (extensionTable_) {
2867 for (const FOTBuilder::Extension *ep = extensionTable_; ep->pubid; ep++) {
2868 if (pubid == ep->pubid) {
2869 if (ep->flowObj) {
2870 const FOTBuilder::CompoundExtensionFlowObj *cFlowObj
2871 = ep->flowObj->asCompoundExtensionFlowObj();
2872 if (cFlowObj)
2873 tem = new (*this) CompoundExtensionFlowObj(*cFlowObj);
2874 else
2875 tem = new (*this) ExtensionFlowObj(*ep->flowObj);
2876 }
2877 break;
2878 }
2879 }
2880 }
2881 if (!tem) {
2882 if (pubid
2883 == "UNREGISTERED::James Clark//Flow Object Class::"
2884 "formatting-instruction")
2885 tem = new (*this) FormattingInstructionFlowObj;
2886 else
2887 tem = new (*this) UnknownFlowObj;
2888 }
2889 makePermanent(tem);
2890 ident->setFlowObj(tem, currentPartIndex(), loc);
2891 }
2892
2893 #ifdef DSSSL_NAMESPACE
2894 }
2895 #endif
2896
2897 #include "FlowObj_inst.cxx"
2898