"Fossies" - the Fresh Open Source Software Archive

Member "OpenSP-1.5.2/spam/CopyEventHandler.cxx" (14 May 2005, 26473 Bytes) of package /linux/misc/old/OpenSP-1.5.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "CopyEventHandler.cxx" see the Fossies "Dox" file reference documentation.

    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
   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
   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
   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
   63 void CopyEventHandler::withNamedCharRef(const StringC &str,
   64                     const Location &loc)
   65 {
   66   withNamedCharRef(str.data(), str.size(), loc);
   67 }
   68 
   69 static
   70 void escape(OutputCharStream &s, Char c)
   71 {
   72   s << "&#" << (unsigned long)c << ";";
   73 }
   74 
   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 
   87 CopyEventHandler::~CopyEventHandler()
   88 {
   89   delete os_;
   90 }
   91 
   92 void CopyEventHandler::markup(const Location &loc,
   93                   const Markup &markup)
   94 {
   95   if (!noOutput())
   96     outputMarkup(loc, markup);
   97 }
   98 
   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 
  119 void CopyEventHandler::endProlog(EndPrologEvent *event)
  120 {
  121   inInstance_ = 1;
  122   syntax_ = instanceSyntax_;
  123   delete event;
  124 }
  125 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  709 void CopyEventHandler::uselink(UselinkEvent *event)
  710 {
  711   omittagHoist_ = 0;
  712   markup(event->location(), event->markup());
  713   delete event;
  714 }
  715 
  716 void CopyEventHandler::startDtd(StartDtdEvent *event)
  717 {
  718   startSubset(event);
  719 }
  720 
  721 void CopyEventHandler::startLpd(StartLpdEvent *event)
  722 {
  723   startSubset(event);
  724 }
  725 
  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 
  755 void CopyEventHandler::endDtd(EndDtdEvent *event)
  756 {
  757   endSubset(event);
  758 }
  759 
  760 void CopyEventHandler::endLpd(EndLpdEvent *event)
  761 {
  762   endSubset(event);
  763 }
  764 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
  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 
 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 
 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 
 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 
 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 
 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