1 // Copyright (c) 1995 James Clark
2 // See the file COPYING for copying permission.
3
4 #ifdef __GNUG__
5 #pragma implementation
6 #endif
7
8 #include "config.h"
9 #include "CopyEventHandler.h"
10 #include "macros.h"
11
12 #ifdef SP_NAMESPACE
13 namespace SP_NAMESPACE {
14 #endif
15
16 inline
operator <<(OutputCharStream & os,const MarkupIter & iter)17 OutputCharStream &operator<<(OutputCharStream &os, const MarkupIter &iter)
18 {
19 return os.write(iter.charsPointer(), iter.charsLength());
20 }
21
22 #ifdef __GNUG__
23 inline
24 #endif
noOutput()25 Boolean CopyEventHandler::noOutput()
26 {
27 if (inInstance_) {
28 if (normalizeFlags_ & normalizeExpand) {
29 if (entityLevel_ >= outputEntityLevel_)
30 return 0;
31 }
32 else {
33 if (entityLevel_ == outputEntityLevel_)
34 return 0;
35 }
36 }
37 else if (normalizeFlags_ & normalizeIncludeProlog) {
38 if (normalizeFlags_ & normalizeExpandProlog) {
39 if (entityLevel_ >= outputEntityLevel_)
40 return 0;
41 }
42 else {
43 if (entityLevel_ == outputEntityLevel_)
44 return 0;
45 }
46 }
47 return 1;
48 }
49
50 inline
doNothing(Event * event)51 Boolean CopyEventHandler::doNothing(Event *event)
52 {
53 if (noOutput()) {
54 delete event;
55 return 1;
56 }
57 else
58 return 0;
59 }
60
61
62 inline
withNamedCharRef(const StringC & str,const Location & loc)63 void CopyEventHandler::withNamedCharRef(const StringC &str,
64 const Location &loc)
65 {
66 withNamedCharRef(str.data(), str.size(), loc);
67 }
68
69 static
escape(OutputCharStream & s,Char c)70 void escape(OutputCharStream &s, Char c)
71 {
72 s << "&#" << (unsigned long)c << ";";
73 }
74
CopyEventHandler(OutputCharStream * os,unsigned normalizeFlags,const StringC & outputEntity)75 CopyEventHandler::CopyEventHandler(OutputCharStream *os,
76 unsigned normalizeFlags,
77 const StringC &outputEntity)
78 : os_(os), topOs_(os), inInstance_(0), entityLevel_(0),
79 normalizeFlags_(normalizeFlags), outputEntity_(outputEntity),
80 omittagHoist_(0), inSpecialMarkedSection_(0),
81 currentAttributes_(0), emptyElementNormal_(0)
82 {
83 outputEntityLevel_ = outputEntity_.size() == 0 ? 0 : unsigned(-1);
84 os_->setEscaper(escape);
85 }
86
~CopyEventHandler()87 CopyEventHandler::~CopyEventHandler()
88 {
89 delete os_;
90 }
91
markup(const Location & loc,const Markup & markup)92 void CopyEventHandler::markup(const Location &loc,
93 const Markup &markup)
94 {
95 if (!noOutput())
96 outputMarkup(loc, markup);
97 }
98
sgmlDecl(SgmlDeclEvent * event)99 void CopyEventHandler::sgmlDecl(SgmlDeclEvent *event)
100 {
101 if (event->implySystemId().size() == 0
102 && !event->location().origin().isNull()
103 && (normalizeFlags_ & normalizeIncludeProlog)) {
104 syntax_ = event->refSyntaxPointer();
105 sd_ = event->refSdPointer();
106 outputMarkup(event->location(), event->markup());
107 }
108 syntax_ = event->prologSyntaxPointer();
109 instanceSyntax_ = event->instanceSyntaxPointer();
110 if (instanceSyntax_->namecaseGeneral())
111 instanceSyntax_->generalSubstTable()->inverseTable(lowerSubst_);
112 else if (instanceSyntax_->namecaseEntity())
113 instanceSyntax_->entitySubstTable()->inverseTable(lowerSubst_);
114 sd_ = event->sdPointer();
115 emptyElementNormal_ = sd_->emptyElementNormal();
116 delete event;
117 }
118
endProlog(EndPrologEvent * event)119 void CopyEventHandler::endProlog(EndPrologEvent *event)
120 {
121 inInstance_ = 1;
122 syntax_ = instanceSyntax_;
123 delete event;
124 }
125
data(DataEvent * event)126 void CopyEventHandler::data(DataEvent *event)
127 {
128 omittagHoist_ = 0;
129 if (doNothing(event))
130 return;
131 if (event->entity())
132 entityRef(event->location().origin()->asEntityOrigin());
133 else {
134 size_t n = event->dataLength();
135 unsigned long dummy;
136 if (n > 1 || !event->isRe(dummy))
137 writeData(event->data(), n, event->location());
138 }
139 delete event;
140 }
141
nonSgmlChar(NonSgmlCharEvent * event)142 void CopyEventHandler::nonSgmlChar(NonSgmlCharEvent *event)
143 {
144 omittagHoist_ = 0;
145 if (doNothing(event))
146 return;
147 Char c = event->character();
148 writeData(&c, 1, event->location());
149 delete event;
150 }
151
writeData(const Char * p,size_t n,const Location & loc)152 void CopyEventHandler::writeData(const Char *p, size_t n,
153 const Location &loc)
154 {
155 const Markup *markupPtr;
156 if (n == 1 && loc.origin()->isNumericCharRef(markupPtr)) {
157 if (markupPtr)
158 outputMarkup(loc.origin()->parent(), *markupPtr);
159 }
160 else
161 withNamedCharRef(p, n, loc);
162 }
163
withNamedCharRef(const Char * p,size_t n,const Location & loc)164 void CopyEventHandler::withNamedCharRef(const Char *p, size_t n,
165 const Location &loc)
166 {
167 if (n > 0) {
168 const Origin *origin = loc.origin().pointer();
169 if (origin) {
170 NamedCharRef ref;
171 if (origin->isNamedCharRef(loc.index(), ref)) {
172 Markup markup;
173 markup.addDelim(Syntax::dCRO);
174 markup.addName(ref.origName().data(), ref.origName().size());
175 switch (ref.refEndType()) {
176 case NamedCharRef::endOmitted:
177 break;
178 case NamedCharRef::endRE:
179 markup.addRefEndRe();
180 break;
181 case NamedCharRef::endRefc:
182 markup.addDelim(Syntax::dREFC);
183 break;
184 }
185 outputMarkup(Location(loc.origin(), ref.refStartIndex()), markup);
186 p++;
187 n--;
188 }
189 }
190 }
191 os().write(p, n);
192 }
193
reOrigin(ReOriginEvent * event)194 void CopyEventHandler::reOrigin(ReOriginEvent *event)
195 {
196 omittagHoist_ = 0;
197 if (doNothing(event))
198 return;
199 Char c = event->re();
200 withNamedCharRef(&c, 1, event->location());
201 delete event;
202 }
203
sSep(SSepEvent * event)204 void CopyEventHandler::sSep(SSepEvent *event)
205 {
206 if (doNothing(event))
207 return;
208 withNamedCharRef(event->data(), event->dataLength(), event->location());
209 delete event;
210 }
211
ignoredRs(IgnoredRsEvent * event)212 void CopyEventHandler::ignoredRs(IgnoredRsEvent *event)
213 {
214 if (doNothing(event))
215 return;
216 Char c = event->rs();
217 withNamedCharRef(&c, 1, event->location());
218 delete event;
219 }
220
startElement(StartElementEvent * event)221 void CopyEventHandler::startElement(StartElementEvent *event)
222 {
223 mustOmitEnd_ = event->mustOmitEnd();
224 const Markup *markup = event->markupPtr();
225 if (!markup) {
226 if (normalizeFlags_ & normalizeExpand) {
227 if (outputEntityLevel_ > entityLevel_ - omittagHoist_) {
228 delete event;
229 return;
230 }
231 if (omittagHoist_ >= entityStack_.size())
232 os_ = topOs_;
233 }
234 else if (entityLevel_ - omittagHoist_ != outputEntityLevel_) {
235 delete event;
236 return;
237 }
238 }
239 else {
240 omittagHoist_ = 0;
241 if (doNothing(event))
242 return;
243 }
244 if (normalizeFlags_ & normalizeExpandAll)
245 handleChange();
246 if (markup) {
247 Boolean hadName = 0;
248 Boolean closed = 1;
249 MarkupIter iter(*markup);
250 while (iter.valid()) {
251 switch (iter.type()) {
252 case Markup::delimiter:
253 switch (iter.delimGeneral()) {
254 case Syntax::dTAGC:
255 closed = 1;
256 if (!hadName) {
257 StringC nameBuf;
258 StringC tag(elementTypeOrigName(event->elementType(), nameBuf));
259 if (normalizeFlags_ & normalizeEmptytag) {
260 handleChange();
261 os() << tag;
262 tag.resize(0);
263 }
264 unspecifiedAttributeValues(event->attributes(), tag);
265 }
266 os() << syntax_->delimGeneral(iter.delimGeneral());
267 break;
268 case Syntax::dNESTC:
269 closed = 1;
270 if (normalizeFlags_ & normalizeNet) {
271 handleChange();
272 os() << syntax_->delimGeneral(Syntax::dTAGC);
273 break;
274 }
275 // fall through
276 default:
277 os() << syntax_->delimGeneral(iter.delimGeneral());
278 break;
279 }
280 iter.advance();
281 break;
282 case Markup::name:
283 {
284 ASSERT(!hadName);
285 const ElementType *elementType = event->elementType();
286 if (elementType->index() >= elementTypeOrigNames_.size())
287 elementTypeOrigNames_.resize(elementType->index() + 1);
288 StringC &elementTypeOrigName
289 = elementTypeOrigNames_[elementType->index()];
290 if (elementTypeOrigName.size() == 0) {
291 elementTypeOrigName.assign(iter.charsPointer(),
292 iter.charsLength());
293 // add rank if missing
294 elementTypeOrigName.append(event->name().data() +
295 elementTypeOrigName.size(),
296 event->name().size()
297 - elementTypeOrigName.size());
298 }
299 os() << iter;
300 if (normalizeFlags_ & normalizeRank) {
301 for (size_t i = iter.charsLength();
302 i < event->name().size();
303 i++) {
304 handleChange();
305 os().put(event->name()[i]);
306 }
307 }
308 attributeSpecList(iter, event->attributes());
309 hadName = 1;
310 }
311 break;
312 case Markup::s:
313 os() << iter;
314 iter.advance();
315 break;
316 default:
317 CANNOT_HAPPEN();
318 }
319 }
320 if (!closed && (normalizeFlags_ && normalizeUnclosed)) {
321 handleChange();
322 os() << syntax_->delimGeneral(Syntax::dTAGC);
323 }
324 }
325 else if (normalizeFlags_ & normalizeOmittag) {
326 if (inSpecialMarkedSection_) {
327 reportTagInSpecialMarkedSection(event->location());
328 return;
329 }
330 handleChange();
331 StringC nameBuf;
332 os() << syntax_->delimGeneral(Syntax::dSTAGO)
333 << elementTypeOrigName(event->elementType(), nameBuf);
334 unspecifiedAttributeValues(event->attributes(), StringC());
335 os() << syntax_->delimGeneral(Syntax::dTAGC);
336 }
337 delete event;
338 if (entityStack_.size() > 0 && os_ == topOs_)
339 os_ = &entityStack_.back().str;
340 }
341
attributeSpecList(MarkupIter & iter,const AttributeList & atts)342 void CopyEventHandler::attributeSpecList(MarkupIter &iter,
343 const AttributeList &atts)
344 {
345 size_t nAtt = atts.size();
346 unsigned i;
347 unsigned *attIndex;
348 if (atts.nSpec()) {
349 attIndex = new unsigned[atts.nSpec()];
350 for (i = 0; i < atts.nSpec(); i++)
351 attIndex[i] = unsigned(-1);
352 for (i = 0; i < nAtt; i++)
353 if (atts.specified(i))
354 attIndex[atts.specIndex(i)] = i;
355 }
356 else
357 attIndex = 0;
358 Boolean hadAttname = 0;
359 i = 0;
360 StringC nameBuf;
361 for (iter.advance(); iter.valid(); iter.advance())
362 switch (iter.type()) {
363 case Markup::name:
364 os() << iter;
365 hadAttname = 1;
366 break;
367 case Markup::s:
368 os() << iter;
369 break;
370 case Markup::attributeValue:
371 if (!hadAttname
372 && attIndex
373 && attIndex[i] != unsigned(-1)
374 && (normalizeFlags_ & (normalizeAttname | normalizeAttvalue))) {
375 handleChange();
376 os() << generalName(atts.name(attIndex[i]), nameBuf)
377 << syntax_->delimGeneral(Syntax::dVI);
378 }
379 if (normalizeFlags_ & normalizeAttvalue) {
380 handleChange();
381 os() << syntax_->delimGeneral(Syntax::dLIT)
382 << iter
383 << syntax_->delimGeneral(Syntax::dLIT);
384 }
385 else
386 os() << iter;
387 hadAttname = 0;
388 i++;
389 break;
390 case Markup::literal:
391 literal(iter.text());
392 i++;
393 hadAttname = 0;
394 break;
395 case Markup::delimiter:
396 if (iter.delimGeneral() == Syntax::dVI)
397 os() << syntax_->delimGeneral(iter.delimGeneral());
398 else {
399 unspecifiedAttributeValues(atts, StringC());
400 delete [] attIndex;
401 return;
402 }
403 break;
404 default:
405 CANNOT_HAPPEN();
406 }
407 }
408
unspecifiedAttributeValues(const AttributeList & atts,const StringC & beforeFirst)409 void CopyEventHandler::unspecifiedAttributeValues(const AttributeList &atts,
410 const StringC &beforeFirst)
411 {
412 if (normalizeFlags_ & (normalizeCurrent|normalizeAttspec)) {
413 Boolean first = 1;
414 size_t nAtt = atts.size();
415 StringC nameBuf;
416 for (unsigned i = 0; i < nAtt; i++) {
417 const Text *text;
418 if (!atts.specified(i)
419 && ((normalizeFlags_ & normalizeAttspec)
420 || atts.current(i))
421 && atts.value(i)
422 && (text = atts.value(i)->text()) != 0) {
423 if (first) {
424 handleChange();
425 os() << beforeFirst;
426 first = 0;
427 }
428 os().put(syntax_->standardFunction(Syntax::fSPACE));
429 os() << generalName(atts.name(i), nameBuf)
430 << syntax_->delimGeneral(Syntax::dVI);
431 Boolean lita;
432 if (text->delimType(lita))
433 literal(*text);
434 else {
435 if (normalizeFlags_ & normalizeAttvalue) {
436 os() << syntax_->delimGeneral(Syntax::dLIT)
437 << text->string()
438 << syntax_->delimGeneral(Syntax::dLIT);
439 }
440 else
441 os() << text->string();
442 }
443 }
444 }
445 }
446 }
447
literal(const Text & text)448 void CopyEventHandler::literal(const Text &text)
449 {
450 TextIter iter(text);
451 TextItem::Type type;
452 const Char *p;
453 size_t n;
454 const Location *loc;
455 StringC delim;
456 Boolean lita;
457 if (!text.delimType(lita))
458 CANNOT_HAPPEN();
459 delim = syntax_->delimGeneral(lita ? Syntax::dLITA : Syntax::dLIT);
460 os() << delim;
461 int level = 0;
462 while (iter.next(type, p, n, loc)) {
463 switch (type) {
464 case TextItem::ignore:
465 case TextItem::data:
466 case TextItem::nonSgml:
467 if (!level) {
468 const Char *orig;
469 if (loc->origin()->origChars(orig))
470 writeData(orig, n, loc->origin()->parent());
471 else
472 writeData(p, n, *loc);
473 }
474 break;
475 case TextItem::cdata:
476 case TextItem::sdata:
477 if (!level)
478 entityRef(loc->origin()->asEntityOrigin());
479 break;
480 case TextItem::entityStart:
481 if (!level++)
482 entityRef(loc->origin()->asEntityOrigin());
483 break;
484 case TextItem::entityEnd:
485 level--;
486 break;
487 case TextItem::startDelim:
488 case TextItem::endDelim:
489 case TextItem::endDelimA:
490 break;
491 }
492 }
493 Location delimLoc;
494 if (!text.endDelimLocation(delimLoc))
495 CANNOT_HAPPEN();
496 withNamedCharRef(delim, delimLoc);
497 }
498
endElement(EndElementEvent * event)499 void CopyEventHandler::endElement(EndElementEvent *event)
500 {
501 if (!emptyElementNormal_ && mustOmitEnd_) {
502 delete event;
503 mustOmitEnd_ = 0;
504 return;
505 }
506 const Markup *markup = event->markupPtr();
507 if (!markup) {
508 if (normalizeFlags_ & normalizeExpand) {
509 if (outputEntityLevel_ > entityLevel_ - omittagHoist_) {
510 delete event;
511 return;
512 }
513 if (omittagHoist_ >= entityStack_.size())
514 os_ = topOs_;
515 }
516 else if (entityLevel_ - omittagHoist_ != outputEntityLevel_) {
517 delete event;
518 return;
519 }
520 }
521 else {
522 omittagHoist_ = 0;
523 if (doNothing(event))
524 return;
525 }
526 if (normalizeFlags_ & normalizeExpandAll)
527 handleChange();
528 if (markup) {
529 Boolean closed = 0;
530 Boolean hadAttname = 0;
531 for (MarkupIter iter(*markup); iter.valid(); iter.advance())
532 switch (iter.type()) {
533 case Markup::s:
534 os() << iter;
535 break;
536 case Markup::name:
537 {
538 os() << iter;
539 for (size_t i = iter.charsLength();
540 i < event->name().size();
541 i++) {
542 handleChange();
543 os().put(event->name()[i]);
544 }
545 hadAttname = 1;
546 }
547 break;
548 case Markup::delimiter:
549 if (iter.delimGeneral() == Syntax::dTAGC) {
550 closed = 1;
551 if (!hadAttname
552 && (normalizeFlags_ & normalizeEmptytag)) {
553 handleChange();
554 StringC nameBuf;
555 os() << elementTypeOrigName(event->elementType(), nameBuf);
556 }
557 }
558 else if (iter.delimGeneral() == Syntax::dNET) {
559 closed = 1;
560 if (normalizeFlags_ & normalizeNet) {
561 handleChange();
562 StringC nameBuf;
563 os() << syntax_->delimGeneral(Syntax::dETAGO)
564 << elementTypeOrigName(event->elementType(), nameBuf)
565 << syntax_->delimGeneral(Syntax::dTAGC);
566 break;
567 }
568 }
569 os() << syntax_->delimGeneral(iter.delimGeneral());
570 break;
571 default:
572 CANNOT_HAPPEN();
573 }
574 if (!closed && (normalizeFlags_ & normalizeUnclosed)) {
575 handleChange();
576 os() << syntax_->delimGeneral(Syntax::dTAGC);
577 }
578 }
579 else if (normalizeFlags_ & normalizeOmittag) {
580 if (inSpecialMarkedSection_) {
581 reportTagInSpecialMarkedSection(event->location());
582 return;
583 }
584 handleChange();
585 StringC nameBuf;
586 os() << syntax_->delimGeneral(Syntax::dETAGO)
587 << elementTypeOrigName(event->elementType(), nameBuf)
588 << syntax_->delimGeneral(Syntax::dTAGC);
589 }
590 delete event;
591 if (entityStack_.size() > 0 && os_ == topOs_)
592 os_ = &entityStack_.back().str;
593 }
594
pi(PiEvent * event)595 void CopyEventHandler::pi(PiEvent *event)
596 {
597 omittagHoist_ = 0;
598 if (doNothing(event))
599 return;
600 if (event->entity())
601 entityRef(event->location().origin()->asEntityOrigin());
602 else {
603 os() << syntax_->delimGeneral(Syntax::dPIO);
604 os().write(event->data(), event->dataLength());
605 os() << syntax_->delimGeneral(Syntax::dPIC);
606 }
607 delete event;
608 }
609
sdataEntity(SdataEntityEvent * event)610 void CopyEventHandler::sdataEntity(SdataEntityEvent *event)
611 {
612 omittagHoist_ = 0;
613 if (doNothing(event))
614 return;
615 entityRef(event->location().origin()->asEntityOrigin());
616 delete event;
617 }
618
externalDataEntity(ExternalDataEntityEvent * event)619 void CopyEventHandler::externalDataEntity(ExternalDataEntityEvent *event)
620 {
621 omittagHoist_ = 0;
622 if (doNothing(event))
623 return;
624 entityRef(event->entityOrigin().pointer());
625 delete event;
626 }
627
subdocEntity(SubdocEntityEvent * event)628 void CopyEventHandler::subdocEntity(SubdocEntityEvent *event)
629 {
630 omittagHoist_ = 0;
631 if (doNothing(event))
632 return;
633 entityRef(event->entityOrigin().pointer());
634 delete event;
635 }
636
markedSectionStart(MarkedSectionStartEvent * event)637 void CopyEventHandler::markedSectionStart(MarkedSectionStartEvent *event)
638 {
639 omittagHoist_ = 0;
640 switch (event->status()) {
641 case MarkedSectionEvent::rcdata:
642 case MarkedSectionEvent::cdata:
643 inSpecialMarkedSection_ = 1;
644 break;
645 default:
646 break;
647 }
648 if (doNothing(event))
649 return;
650 if (!(normalizeFlags_ & normalizeMarkedSection)
651 || (inInstance_ && inSpecialMarkedSection_))
652 outputMarkup(event->location(), event->markup());
653 else if (inInstance_ && event->status() != MarkedSectionEvent::ignore) {
654 // Put an empty comment so that REs aren't changed.
655 // With an ignored marked section, sufficent to have comment at the end.
656 handleChange();
657 os() << syntax_->delimGeneral(Syntax::dMDO)
658 << syntax_->delimGeneral(Syntax::dMDC);
659 }
660 delete event;
661 }
662
markedSectionEnd(MarkedSectionEndEvent * event)663 void CopyEventHandler::markedSectionEnd(MarkedSectionEndEvent *event)
664 {
665 omittagHoist_ = 0;
666 if (doNothing(event)) {
667 inSpecialMarkedSection_ = 0;
668 return;
669 }
670 if (!(normalizeFlags_ & normalizeMarkedSection)
671 || (inInstance_ && inSpecialMarkedSection_))
672 outputMarkup(event->location(), event->markup());
673 else if (inInstance_) {
674 // Put an empty comment so that REs aren't changed.
675 handleChange();
676 os() << syntax_->delimGeneral(Syntax::dMDO)
677 << syntax_->delimGeneral(Syntax::dMDC);
678 }
679 inSpecialMarkedSection_ = 0;
680 delete event;
681 }
682
ignoredChars(IgnoredCharsEvent * event)683 void CopyEventHandler::ignoredChars(IgnoredCharsEvent *event)
684 {
685 omittagHoist_ = 0;
686 if (doNothing(event))
687 return;
688 if (!(normalizeFlags_ & normalizeMarkedSection))
689 os().write(event->data(), event->dataLength());
690 delete event;
691 }
692
usemap(UsemapEvent * event)693 void CopyEventHandler::usemap(UsemapEvent *event)
694 {
695 omittagHoist_ = 0;
696 if (doNothing(event))
697 return;
698 if (!(normalizeFlags_ & normalizeShortref))
699 outputMarkup(event->location(), event->markup());
700 else if (inInstance_) {
701 // Put an empty comment so that REs aren't changed.
702 handleChange();
703 os() << syntax_->delimGeneral(Syntax::dMDO)
704 << syntax_->delimGeneral(Syntax::dMDC);
705 }
706 delete event;
707 }
708
uselink(UselinkEvent * event)709 void CopyEventHandler::uselink(UselinkEvent *event)
710 {
711 omittagHoist_ = 0;
712 markup(event->location(), event->markup());
713 delete event;
714 }
715
startDtd(StartDtdEvent * event)716 void CopyEventHandler::startDtd(StartDtdEvent *event)
717 {
718 startSubset(event);
719 }
720
startLpd(StartLpdEvent * event)721 void CopyEventHandler::startLpd(StartLpdEvent *event)
722 {
723 startSubset(event);
724 }
725
startSubset(StartSubsetEvent * event)726 void CopyEventHandler::startSubset(StartSubsetEvent *event)
727 {
728 if (doNothing(event))
729 return;
730 if (!event->entity().isNull()
731 && (normalizeFlags_ & normalizeExpandProlog)) {
732 const Markup &m = event->markup();
733 for (MarkupIter iter(m); iter.valid(); iter.advance())
734 if (iter.type() == Markup::reservedName
735 && (iter.reservedName() == Syntax::rSYSTEM
736 || iter.reservedName() == Syntax::rPUBLIC)) {
737 Markup copy(m);
738 copy.resize(iter.index());
739 outputMarkup(event->location(), copy);
740 break;
741 }
742 }
743 else
744 outputMarkup(event->location(), event->markup());
745 if (event->hasInternalSubset()
746 || (normalizeFlags_ & normalizeExpandProlog)) {
747 os() << syntax_->delimGeneral(Syntax::dDSO);
748 hasInternalSubset_ = 1;
749 }
750 else
751 hasInternalSubset_ = 0;
752 delete event;
753 }
754
endDtd(EndDtdEvent * event)755 void CopyEventHandler::endDtd(EndDtdEvent *event)
756 {
757 endSubset(event);
758 }
759
endLpd(EndLpdEvent * event)760 void CopyEventHandler::endLpd(EndLpdEvent *event)
761 {
762 endSubset(event);
763 }
764
endSubset(MarkupEvent * event)765 void CopyEventHandler::endSubset(MarkupEvent *event)
766 {
767 if (doNothing(event))
768 return;
769 if (hasInternalSubset_)
770 os() << syntax_->delimGeneral(Syntax::dDSC);
771 outputMarkup(event->location(), event->markup());
772 delete event;
773 }
774
entityDecl(EntityDeclEvent * event)775 void CopyEventHandler::entityDecl(EntityDeclEvent *event)
776 {
777 currentAttributes_ = 0;
778 const ExternalDataEntity *extData = event->entity().asExternalDataEntity();
779 if (extData)
780 currentAttributes_ = &extData->attributes();
781 markup(event->location(), event->markup());
782 currentAttributes_ = 0;
783 delete event;
784 }
785
shortrefDecl(ShortrefDeclEvent * event)786 void CopyEventHandler::shortrefDecl(ShortrefDeclEvent *event)
787 {
788 if (doNothing(event))
789 return;
790 if (!(normalizeFlags_ & normalizeShortref))
791 outputMarkup(event->location(), event->markup());
792 delete event;
793 }
794
entityStart(EntityStartEvent * event)795 void CopyEventHandler::entityStart(EntityStartEvent *event)
796 {
797 if (event->entity()->name() == outputEntity_
798 && event->entity()->declType() == Entity::generalEntity)
799 outputEntityLevel_ = entityLevel_ + 1;
800 if (inInstance_ && (normalizeFlags_ & normalizeOmittagHoist)) {
801 if (event->entity()->asInternalEntity())
802 omittagHoist_++;
803 else
804 omittagHoist_ = 0;
805 }
806 if (doNothing(event)) {
807 entityLevel_++;
808 return;
809 }
810 entityLevel_++;
811 if ((normalizeFlags_ & normalizeExpand)
812 && inInstance_
813 && entityLevel_ > outputEntityLevel_) {
814 entityStack_.resize(entityStack_.size() + 1);
815 entityStack_.back().ref = event->entityOrigin();
816 os_ = &entityStack_.back().str;
817 }
818 entityOrigin_ = event->entityOrigin();
819 delete event;
820 }
821
entityEnd(EntityEndEvent * event)822 void CopyEventHandler::entityEnd(EntityEndEvent *event)
823 {
824 if (omittagHoist_ > 0)
825 omittagHoist_--;
826 if (entityLevel_-- == outputEntityLevel_) {
827 outputEntityLevel_ = unsigned(-1);
828 outputEntity_.resize(0);
829 }
830 else if (!(normalizeFlags_
831 & (inInstance_ ? normalizeExpand : normalizeExpandProlog))
832 && entityLevel_ == outputEntityLevel_) {
833 if (!entityOrigin_.isNull()) {
834 switch (entityOrigin_->entity()->declType()) {
835 case Entity::doctype:
836 case Entity::linktype:
837 break;
838 default:
839 entityRef(entityOrigin_.pointer());
840 break;
841 }
842 }
843 entityOrigin_.clear();
844 }
845 else if ((normalizeFlags_ & normalizeExpand)
846 && inInstance_
847 && entityLevel_ >= outputEntityLevel_) {
848 if (entityStack_.size() > 0) {
849 ConstPtr<EntityOrigin> origin
850 = entityStack_.back().ref;
851 entityStack_.resize(entityStack_.size() - 1);
852 if (entityStack_.size() > 0)
853 os_ = &entityStack_.back().str;
854 else
855 os_ = topOs_;
856 entityRef(origin.pointer());
857 }
858 }
859 delete event;
860 }
861
outputMarkup(const Location & loc,const Markup & markup)862 void CopyEventHandler::outputMarkup(const Location &loc,
863 const Markup &markup)
864 {
865 int level = 0;
866 Boolean first = 1;
867 MarkupIter iter(markup);
868 while (iter.valid()) {
869 switch (iter.type()) {
870 case Markup::delimiter:
871 if (first)
872 withNamedCharRef(syntax_->delimGeneral(iter.delimGeneral()), loc);
873 else if (!level) {
874 os() << syntax_->delimGeneral(iter.delimGeneral());
875 // hack, hack!
876 if (iter.delimGeneral() == Syntax::dDSO && currentAttributes_ != 0) {
877 attributeSpecList(iter, *currentAttributes_);
878 first = 0;
879 continue; // skip the advance
880 }
881 }
882 break;
883 case Markup::refEndRe:
884 if (!level)
885 os().put(syntax_->standardFunction(Syntax::fRE));
886 break;
887 case Markup::sdReservedName:
888 if (!level) {
889 if (normalizeFlags_ & normalizeReserved)
890 os() << sd_->reservedName(iter.sdReservedName());
891 else
892 os() << iter;
893 }
894 break;
895 case Markup::reservedName:
896 if (!level && (normalizeFlags_ & normalizeReserved)) {
897 os() << syntax_->reservedName(iter.reservedName());
898 break;
899 }
900 case Markup::shortref:
901 if (first) {
902 withNamedCharRef(iter.charsPointer(), iter.charsLength(), loc);
903 break;
904 }
905 // fall through
906 case Markup::name:
907 case Markup::nameToken:
908 case Markup::attributeValue:
909 case Markup::number:
910 case Markup::s:
911 if (!level)
912 os() << iter;
913 break;
914 case Markup::comment:
915 if (!level)
916 os() << syntax_->delimGeneral(Syntax::dCOM)
917 << iter
918 << syntax_->delimGeneral(Syntax::dCOM);
919 break;
920 case Markup::entityStart:
921 if (!level++) {
922 const EntityOrigin *origin = iter.entityOrigin();
923 // entityStarts in the SGML declaration don't have explicit references
924 if (origin->entity())
925 entityRef(origin);
926 }
927 break;
928 case Markup::entityEnd:
929 level--;
930 break;
931 case Markup::literal:
932 if (!level)
933 literal(iter.text());
934 break;
935 case Markup::sdLiteral:
936 if (!level)
937 sdParamLiteral(iter.sdText());
938 break;
939 default:
940 CANNOT_HAPPEN();
941 }
942 iter.advance();
943 first = 0;
944 }
945 }
946
sdParamLiteral(const SdText & text)947 void CopyEventHandler::sdParamLiteral(const SdText &text)
948 {
949 const StringC &delim = syntax_->delimGeneral(text.lita()
950 ? Syntax::dLITA
951 : Syntax::dLIT);
952 os() << delim;
953 SdTextIter iter(text);
954 const SyntaxChar *p;
955 size_t n;
956 Location loc;
957 while (iter.next(p, n, loc)) {
958 const Markup *markupPtr;
959 if (n == 1 && loc.origin()->isNumericCharRef(markupPtr)) {
960 if (markupPtr)
961 outputMarkup(loc.origin()->parent(), *markupPtr);
962 }
963 else if (n > 0) {
964 Char c = Char(*p);
965 withNamedCharRef(&c, 1, loc);
966 for (++p, --n; n > 0; ++p, --n)
967 os().put(Char(*p));
968 }
969 }
970 os() << delim;
971 }
972
entityRef(const EntityOrigin * origin)973 void CopyEventHandler::entityRef(const EntityOrigin *origin)
974 {
975 const Markup *m = origin->markup();
976 if (!m)
977 return;
978 MarkupIter iter(*m);
979 if (iter.valid()) {
980 iter.advance();
981 if (iter.valid()
982 && iter.type() == Markup::shortref
983 && (normalizeFlags_ & normalizeShortref)) {
984 handleChange();
985 Boolean containsRE = 0;
986 Boolean containsRS = 0;
987 for (size_t i = 0; i < iter.charsLength(); i++) {
988 Char c = iter.charsPointer()[i];
989 if (c == syntax_->standardFunction(Syntax::fRE))
990 containsRE = 1;
991 else if (c == syntax_->standardFunction(Syntax::fRS))
992 containsRS = 1;
993 }
994 if (containsRS)
995 os().put(syntax_->standardFunction(Syntax::fRS));
996 os() << syntax_->delimGeneral(Syntax::dERO)
997 << origin->entity()->name();
998 if (containsRE)
999 os().put(syntax_->standardFunction(Syntax::fRE));
1000 else
1001 os() << syntax_->delimGeneral(Syntax::dREFC);
1002 return;
1003 }
1004 }
1005 outputMarkup(origin->parent(), *m);
1006 }
1007
elementTypeOrigName(const ElementType * type,StringC & buf)1008 const StringC &CopyEventHandler::elementTypeOrigName(const ElementType *type,
1009 StringC &buf)
1010 {
1011 if (type->index() < elementTypeOrigNames_.size()
1012 && elementTypeOrigNames_[type->index()].size() > 0)
1013 return elementTypeOrigNames_[type->index()];
1014 else
1015 return generalName(type->name(), buf);
1016 }
1017
generalName(const StringC & name,StringC & buf)1018 const StringC &CopyEventHandler::generalName(const StringC &name,
1019 StringC &buf)
1020 {
1021 if ((normalizeFlags_ & normalizeLower)
1022 && syntax_->namecaseGeneral())
1023 return lowerCaseName(name, buf);
1024 else
1025 return name;
1026 }
1027
entityName(const StringC & name,StringC & buf)1028 const StringC &CopyEventHandler::entityName(const StringC &name,
1029 StringC &buf)
1030 {
1031 if ((normalizeFlags_ & normalizeLower)
1032 && syntax_->namecaseEntity())
1033 return lowerCaseName(name, buf);
1034 else
1035 return name;
1036 }
1037
lowerCaseName(const StringC & name,StringC & buf)1038 const StringC &CopyEventHandler::lowerCaseName(const StringC &name,
1039 StringC &buf)
1040 {
1041 size_t i;
1042 for (i = 0; i < name.size(); i++) {
1043 Char c = lowerSubst_[name[i]];
1044 if (c != name[i]) {
1045 buf = name;
1046 buf[i] = c;
1047 for (i++; i < name.size(); i++)
1048 lowerSubst_.subst(buf[i]);
1049 return buf;
1050 }
1051 }
1052 return name;
1053 }
1054
handleChange()1055 void CopyEventHandler::handleChange()
1056 {
1057 if (os_ != topOs_) {
1058 os_ = topOs_;
1059 for (size_t i = 0; i < entityStack_.size(); i++) {
1060 StringC tem;
1061 entityStack_[i].str.flush();
1062 entityStack_[i].str.extractString(tem);
1063 os() << tem;
1064 }
1065 entityStack_.resize(0);
1066 }
1067 }
1068
1069 #ifdef SP_NAMESPACE
1070 }
1071 #endif
1072