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