Logo Search packages:      
Sourcecode: jade version File versions  Download package

CopyEventHandler.cxx

// Copyright (c) 1995 James Clark
// See the file COPYING for copying permission.

#ifdef __GNUG__
#pragma implementation
#endif

#include "config.h"
#include "CopyEventHandler.h"
#include "macros.h"

#ifdef SP_NAMESPACE
namespace SP_NAMESPACE {
#endif

inline
OutputCharStream &operator<<(OutputCharStream &os, const MarkupIter &iter)
{
  return os.write(iter.charsPointer(), iter.charsLength());
}

#ifdef __GNUG__
inline
#endif
Boolean CopyEventHandler::noOutput()
{
  if (inInstance_) {
    if (normalizeFlags_ & normalizeExpand) {
      if (entityLevel_ >= outputEntityLevel_)
      return 0;
    }
    else {
      if (entityLevel_ == outputEntityLevel_)
      return 0;
    }
  }
  else if (normalizeFlags_ & normalizeIncludeProlog) {
    if (normalizeFlags_ & normalizeExpandProlog) {
      if (entityLevel_ >= outputEntityLevel_)
      return 0;
    }
    else {
      if (entityLevel_ == outputEntityLevel_)
      return 0;
    }
  }
  return 1;
}

inline
Boolean CopyEventHandler::doNothing(Event *event)
{
  if (noOutput()) {
    delete event;
    return 1;
  }
  else
    return 0;
}


inline
void CopyEventHandler::withNamedCharRef(const StringC &str,
                              const Location &loc)
{
  withNamedCharRef(str.data(), str.size(), loc);
}

static
void escape(OutputCharStream &s, Char c)
{
  s << "&#" << (unsigned long)c << ";";
}

CopyEventHandler::CopyEventHandler(OutputCharStream *os,
                           unsigned normalizeFlags,
                           const StringC &outputEntity)
: os_(os), topOs_(os), inInstance_(0), entityLevel_(0),
  normalizeFlags_(normalizeFlags), outputEntity_(outputEntity),
  omittagHoist_(0), inSpecialMarkedSection_(0),
  currentAttributes_(0), emptyElementNormal_(0)
{
  outputEntityLevel_ = outputEntity_.size() == 0 ? 0 : unsigned(-1);
  os_->setEscaper(escape);
}

CopyEventHandler::~CopyEventHandler()
{
  delete os_;
}

void CopyEventHandler::markup(const Location &loc,
                        const Markup &markup)
{
  if (!noOutput())
    outputMarkup(loc, markup);
}

void CopyEventHandler::sgmlDecl(SgmlDeclEvent *event)
{
  if (event->implySystemId().size() == 0
      && !event->location().origin().isNull()
      && (normalizeFlags_ & normalizeIncludeProlog)) {
    syntax_ = event->refSyntaxPointer();
    sd_ = event->refSdPointer();
    outputMarkup(event->location(), event->markup());
  }
  syntax_ = event->prologSyntaxPointer();
  instanceSyntax_ = event->instanceSyntaxPointer();
  if (instanceSyntax_->namecaseGeneral())
    instanceSyntax_->generalSubstTable()->inverseTable(lowerSubst_);
  else if (instanceSyntax_->namecaseEntity())
    instanceSyntax_->entitySubstTable()->inverseTable(lowerSubst_);
  sd_ = event->sdPointer();
  emptyElementNormal_ = sd_->emptyElementNormal();
  delete event;
}

void CopyEventHandler::endProlog(EndPrologEvent *event)
{
  inInstance_ = 1;
  syntax_ = instanceSyntax_;
  delete event;
}

void CopyEventHandler::data(DataEvent *event)
{
  omittagHoist_ = 0;
  if (doNothing(event))
    return;
  if (event->entity())
    entityRef(event->location().origin()->asEntityOrigin());
  else {
    size_t n = event->dataLength();
    unsigned long dummy;
    if (n > 1 || !event->isRe(dummy))
      writeData(event->data(), n, event->location());
  }
  delete event;
}

void CopyEventHandler::nonSgmlChar(NonSgmlCharEvent *event)
{
  omittagHoist_ = 0;
  if (doNothing(event))
    return;
  Char c = event->character();
  writeData(&c, 1, event->location());
  delete event;
}

void CopyEventHandler::writeData(const Char *p, size_t n,
                         const Location &loc)
{
  const Markup *markupPtr;
  if (n == 1 && loc.origin()->isNumericCharRef(markupPtr)) {
    if (markupPtr)
      outputMarkup(loc.origin()->parent(), *markupPtr);
  }
  else
    withNamedCharRef(p, n, loc);
}

void CopyEventHandler::withNamedCharRef(const Char *p, size_t n,
                              const Location &loc)
{
  if (n > 0) {
    const Origin *origin = loc.origin().pointer();
    if (origin) {
      NamedCharRef ref;
      if (origin->isNamedCharRef(loc.index(), ref)) {
      Markup markup;
      markup.addDelim(Syntax::dCRO);
      markup.addName(ref.origName().data(), ref.origName().size());
      switch (ref.refEndType()) {
      case NamedCharRef::endOmitted:
        break;
      case NamedCharRef::endRE:
        markup.addRefEndRe();
        break;
      case NamedCharRef::endRefc:
        markup.addDelim(Syntax::dREFC);
        break;
      }
      outputMarkup(Location(loc.origin(), ref.refStartIndex()), markup);
      p++;
      n--;
      }
    }
  }
  os().write(p, n);
}

void CopyEventHandler::reOrigin(ReOriginEvent *event)
{
  omittagHoist_ = 0;
  if (doNothing(event))
    return;
  Char c = event->re();
  withNamedCharRef(&c, 1, event->location());
  delete event;
}

void CopyEventHandler::sSep(SSepEvent *event)
{
  if (doNothing(event))
    return;
  withNamedCharRef(event->data(), event->dataLength(), event->location());
  delete event;
}

void CopyEventHandler::ignoredRs(IgnoredRsEvent *event)
{
  if (doNothing(event))
    return;
  Char c = event->rs();
  withNamedCharRef(&c, 1, event->location());
  delete event;
}

void CopyEventHandler::startElement(StartElementEvent *event)
{
  mustOmitEnd_ = event->mustOmitEnd();
  const Markup *markup = event->markupPtr();
  if (!markup) {
    if (normalizeFlags_ & normalizeExpand) {
      if (outputEntityLevel_ > entityLevel_ - omittagHoist_) {
      delete event;
      return;
      }
      if (omittagHoist_ >= entityStack_.size())
      os_ = topOs_;
    }
    else if (entityLevel_ - omittagHoist_ != outputEntityLevel_) {
      delete event;
      return;
    }
  }
  else {
    omittagHoist_ = 0;
    if (doNothing(event))
      return;
  }
  if (normalizeFlags_ & normalizeExpandAll)
    handleChange();
  if (markup) {
    Boolean hadName = 0;
    Boolean closed = 1;
    MarkupIter iter(*markup);
    while (iter.valid()) {
      switch (iter.type()) {
      case Markup::delimiter:
      switch (iter.delimGeneral()) {
      case Syntax::dTAGC:
        closed = 1;
        if (!hadName) {
          StringC nameBuf;
          StringC tag(elementTypeOrigName(event->elementType(), nameBuf));
          if (normalizeFlags_ & normalizeEmptytag) {
            handleChange();
            os() << tag;
            tag.resize(0);
          }
          unspecifiedAttributeValues(event->attributes(), tag);
        }
        os() << syntax_->delimGeneral(iter.delimGeneral());
        break;
      case Syntax::dNESTC:
        closed = 1;
        if (normalizeFlags_ & normalizeNet) {
          handleChange();
          os() << syntax_->delimGeneral(Syntax::dTAGC);
          break;
        }
        // fall through
      default:
        os() << syntax_->delimGeneral(iter.delimGeneral());
        break;
      }
      iter.advance();
      break;
      case Markup::name:
      {
        ASSERT(!hadName);
        const ElementType *elementType = event->elementType();
        if (elementType->index() >= elementTypeOrigNames_.size())
          elementTypeOrigNames_.resize(elementType->index() + 1);
        StringC &elementTypeOrigName
          = elementTypeOrigNames_[elementType->index()];
        if (elementTypeOrigName.size() == 0) {
          elementTypeOrigName.assign(iter.charsPointer(),
                               iter.charsLength());
          // add rank if missing
          elementTypeOrigName.append(event->name().data() +
                               elementTypeOrigName.size(),
                               event->name().size()
                               - elementTypeOrigName.size());
        }
        os() << iter;
        if (normalizeFlags_ & normalizeRank) {
          for (size_t i = iter.charsLength();
             i < event->name().size();
             i++) {
            handleChange();
            os().put(event->name()[i]);
          }
        }
        attributeSpecList(iter, event->attributes());
        hadName = 1;
      }
      break;
      case Markup::s:
      os() << iter;
      iter.advance();
      break;
      default:
      CANNOT_HAPPEN();
      }
    }
    if (!closed && (normalizeFlags_ && normalizeUnclosed)) {
      handleChange();
      os() << syntax_->delimGeneral(Syntax::dTAGC);
    }
  }
  else if (normalizeFlags_ & normalizeOmittag) {
    if (inSpecialMarkedSection_) {
      reportTagInSpecialMarkedSection(event->location());
      return;
    }
    handleChange();
    StringC nameBuf;
    os() << syntax_->delimGeneral(Syntax::dSTAGO)
      << elementTypeOrigName(event->elementType(), nameBuf);
    unspecifiedAttributeValues(event->attributes(), StringC());
    os() << syntax_->delimGeneral(Syntax::dTAGC);
  }
  delete event;
  if (entityStack_.size() > 0 && os_ == topOs_)
    os_ = &entityStack_.back().str;
}

void CopyEventHandler::attributeSpecList(MarkupIter &iter,
                               const AttributeList &atts)
{
  size_t nAtt = atts.size();
  unsigned i;
  unsigned *attIndex;
  if (atts.nSpec()) {
    attIndex = new unsigned[atts.nSpec()];
    for (i = 0; i < atts.nSpec(); i++)
      attIndex[i] = unsigned(-1);
    for (i = 0; i < nAtt; i++)
      if (atts.specified(i))
      attIndex[atts.specIndex(i)] = i;
  }
  else
    attIndex = 0;
  Boolean hadAttname = 0;
  i = 0;
  StringC nameBuf;
  for (iter.advance(); iter.valid(); iter.advance())
    switch (iter.type()) {
    case Markup::name:
      os() << iter;
      hadAttname = 1;
      break;
    case Markup::s:
      os() << iter;
      break;
    case Markup::attributeValue:
      if (!hadAttname
        && attIndex
        && attIndex[i] != unsigned(-1)
        && (normalizeFlags_ & (normalizeAttname | normalizeAttvalue))) {
      handleChange();
      os() << generalName(atts.name(attIndex[i]), nameBuf)
        << syntax_->delimGeneral(Syntax::dVI);
      }
      if (normalizeFlags_ & normalizeAttvalue) {
      handleChange();
      os() << syntax_->delimGeneral(Syntax::dLIT)
        << iter
          << syntax_->delimGeneral(Syntax::dLIT);
      }
      else
      os() << iter;
      hadAttname = 0;
      i++;
      break;
    case Markup::literal:
      literal(iter.text());
      i++;
      hadAttname = 0;
      break;
    case Markup::delimiter:
      if (iter.delimGeneral() == Syntax::dVI)
      os() << syntax_->delimGeneral(iter.delimGeneral());
      else {
      unspecifiedAttributeValues(atts, StringC());
      delete [] attIndex;
      return;
      }
      break;
    default:
      CANNOT_HAPPEN();
    }
}

void CopyEventHandler::unspecifiedAttributeValues(const AttributeList &atts,
                                      const StringC &beforeFirst)
{
  if (normalizeFlags_ & (normalizeCurrent|normalizeAttspec)) {
    Boolean first = 1;
    size_t nAtt = atts.size();
    StringC nameBuf;
    for (unsigned i = 0; i < nAtt; i++) {
      const Text *text;
      if (!atts.specified(i)
        && ((normalizeFlags_ & normalizeAttspec)
            || atts.current(i))
        && atts.value(i)
        && (text = atts.value(i)->text()) != 0) {
      if (first) {
        handleChange();
        os() << beforeFirst;
        first = 0;
      }
      os().put(syntax_->standardFunction(Syntax::fSPACE));
      os() << generalName(atts.name(i), nameBuf)
        << syntax_->delimGeneral(Syntax::dVI);
      Boolean lita;
      if (text->delimType(lita))
        literal(*text);
      else {
        if (normalizeFlags_ & normalizeAttvalue) {
          os() << syntax_->delimGeneral(Syntax::dLIT)
            << text->string()
            <<  syntax_->delimGeneral(Syntax::dLIT);
        }
        else
          os() << text->string();
      }
      }
    }
  }
}

void CopyEventHandler::literal(const Text &text)
{
  TextIter iter(text);
  TextItem::Type type;
  const Char *p;
  size_t n;
  const Location *loc;
  StringC delim;
  Boolean lita;
  if (!text.delimType(lita))
    CANNOT_HAPPEN();
  delim = syntax_->delimGeneral(lita ? Syntax::dLITA : Syntax::dLIT);
  os() << delim;
  int level = 0;
  while (iter.next(type, p, n, loc)) {
    switch (type) {
    case TextItem::ignore:
    case TextItem::data:
    case TextItem::nonSgml:
      if (!level) {
      const Char *orig;
      if (loc->origin()->origChars(orig))
        writeData(orig, n, loc->origin()->parent());
      else
        writeData(p, n, *loc);
      }
      break;
    case TextItem::cdata:
    case TextItem::sdata:
      if (!level)
      entityRef(loc->origin()->asEntityOrigin());
      break;
    case TextItem::entityStart:
      if (!level++)
      entityRef(loc->origin()->asEntityOrigin());
      break;
    case TextItem::entityEnd:
      level--;
      break;
    case TextItem::startDelim:
    case TextItem::endDelim:
    case TextItem::endDelimA:
      break;
    }
  }
  Location delimLoc;
  if (!text.endDelimLocation(delimLoc))
    CANNOT_HAPPEN();
  withNamedCharRef(delim, delimLoc);
}

void CopyEventHandler::endElement(EndElementEvent *event)
{
  if (!emptyElementNormal_ && mustOmitEnd_) {
    delete event;
    mustOmitEnd_ = 0;
    return;
  }
  const Markup *markup = event->markupPtr();
  if (!markup) {
    if (normalizeFlags_ & normalizeExpand) {
      if (outputEntityLevel_ > entityLevel_ - omittagHoist_) {
      delete event;
      return;
      }
      if (omittagHoist_ >= entityStack_.size())
      os_ = topOs_;
    }
    else if (entityLevel_ - omittagHoist_ != outputEntityLevel_) {
      delete event;
      return;
    }
  }
  else {
    omittagHoist_ = 0;
    if (doNothing(event))
      return;
  }
  if (normalizeFlags_ & normalizeExpandAll)
    handleChange();
  if (markup) {
    Boolean closed = 0;
    Boolean hadAttname = 0;
    for (MarkupIter iter(*markup); iter.valid(); iter.advance())
      switch (iter.type()) {
      case Markup::s:
      os() << iter;
      break;
      case Markup::name:
      {
        os() << iter;
        for (size_t i = iter.charsLength();
             i < event->name().size();
             i++) {
          handleChange();
          os().put(event->name()[i]);
        }
        hadAttname = 1;
      }
      break;
      case Markup::delimiter:
      if (iter.delimGeneral() == Syntax::dTAGC) {
        closed = 1;
        if (!hadAttname
            && (normalizeFlags_ & normalizeEmptytag)) {
          handleChange();
          StringC nameBuf;
          os() << elementTypeOrigName(event->elementType(), nameBuf);
        }
      }
      else if (iter.delimGeneral() == Syntax::dNET) {
        closed = 1;
        if (normalizeFlags_ & normalizeNet) {
          handleChange();
          StringC nameBuf;
          os() << syntax_->delimGeneral(Syntax::dETAGO)
               << elementTypeOrigName(event->elementType(), nameBuf)
               << syntax_->delimGeneral(Syntax::dTAGC);
          break;
        }
      }
      os() << syntax_->delimGeneral(iter.delimGeneral());
      break;
      default:
      CANNOT_HAPPEN();
      }
    if (!closed && (normalizeFlags_ & normalizeUnclosed)) {
      handleChange();
      os() << syntax_->delimGeneral(Syntax::dTAGC);
    }
  }
  else if (normalizeFlags_ & normalizeOmittag) {
    if (inSpecialMarkedSection_) {
      reportTagInSpecialMarkedSection(event->location());
      return;
    }
    handleChange();
    StringC nameBuf;
    os() << syntax_->delimGeneral(Syntax::dETAGO)
      << elementTypeOrigName(event->elementType(), nameBuf)
      << syntax_->delimGeneral(Syntax::dTAGC);
  }
  delete event;
  if (entityStack_.size() > 0 && os_ == topOs_)
    os_ = &entityStack_.back().str;
}

void CopyEventHandler::pi(PiEvent *event)
{
  omittagHoist_ = 0;
  if (doNothing(event))
    return;
  if (event->entity())
    entityRef(event->location().origin()->asEntityOrigin());
  else {
    os() << syntax_->delimGeneral(Syntax::dPIO);
    os().write(event->data(), event->dataLength());
    os() << syntax_->delimGeneral(Syntax::dPIC);
  }
  delete event;
}

void CopyEventHandler::sdataEntity(SdataEntityEvent *event)
{
  omittagHoist_ = 0;
  if (doNothing(event))
    return;
  entityRef(event->location().origin()->asEntityOrigin());
  delete event;
}

void CopyEventHandler::externalDataEntity(ExternalDataEntityEvent *event)
{
  omittagHoist_ = 0;
  if (doNothing(event))
    return;
  entityRef(event->entityOrigin().pointer());
  delete event;
}

void CopyEventHandler::subdocEntity(SubdocEntityEvent *event)
{
  omittagHoist_ = 0;
  if (doNothing(event))
    return;
  entityRef(event->entityOrigin().pointer());
  delete event;
}

void CopyEventHandler::markedSectionStart(MarkedSectionStartEvent *event)
{
  omittagHoist_ = 0;
  switch (event->status()) {
  case MarkedSectionEvent::rcdata:
  case MarkedSectionEvent::cdata:
    inSpecialMarkedSection_ = 1;
    break;
  default:
    break;
  }
  if (doNothing(event))
    return;
  if (!(normalizeFlags_ & normalizeMarkedSection)
      || (inInstance_ && inSpecialMarkedSection_))
    outputMarkup(event->location(), event->markup());
  else if (inInstance_ && event->status() != MarkedSectionEvent::ignore) {
    // Put an empty comment so that REs aren't changed.
    // With an ignored marked section, sufficent to have comment at the end.
    handleChange();
    os() << syntax_->delimGeneral(Syntax::dMDO)
         << syntax_->delimGeneral(Syntax::dMDC);
  }
  delete event;
}

void CopyEventHandler::markedSectionEnd(MarkedSectionEndEvent *event)
{
  omittagHoist_ = 0;
  if (doNothing(event)) {
    inSpecialMarkedSection_ = 0;
    return;
  }
  if (!(normalizeFlags_ & normalizeMarkedSection)
      || (inInstance_ && inSpecialMarkedSection_))
    outputMarkup(event->location(), event->markup());
  else if (inInstance_) {
    // Put an empty comment so that REs aren't changed.
    handleChange();
    os() << syntax_->delimGeneral(Syntax::dMDO)
         << syntax_->delimGeneral(Syntax::dMDC);
  }
  inSpecialMarkedSection_ = 0;
  delete event;
}

void CopyEventHandler::ignoredChars(IgnoredCharsEvent *event)
{
  omittagHoist_ = 0;
  if (doNothing(event))
    return;
  if (!(normalizeFlags_ & normalizeMarkedSection))
    os().write(event->data(), event->dataLength());
  delete event;
}

void CopyEventHandler::usemap(UsemapEvent *event)
{
  omittagHoist_ = 0;
  if (doNothing(event))
    return;
  if (!(normalizeFlags_ & normalizeShortref))
    outputMarkup(event->location(), event->markup());
  else if (inInstance_) {
    // Put an empty comment so that REs aren't changed.
    handleChange();
    os() << syntax_->delimGeneral(Syntax::dMDO)
         << syntax_->delimGeneral(Syntax::dMDC);
  }
  delete event;
}

void CopyEventHandler::uselink(UselinkEvent *event)
{
  omittagHoist_ = 0;
  markup(event->location(), event->markup());
  delete event;
}

void CopyEventHandler::startDtd(StartDtdEvent *event)
{
  startSubset(event);
}

void CopyEventHandler::startLpd(StartLpdEvent *event)
{
  startSubset(event);
}

void CopyEventHandler::startSubset(StartSubsetEvent *event)
{
  if (doNothing(event))
    return;
  if (!event->entity().isNull()
      && (normalizeFlags_ & normalizeExpandProlog)) {
    const Markup &m = event->markup();
    for (MarkupIter iter(m); iter.valid(); iter.advance())
      if (iter.type() == Markup::reservedName
        && (iter.reservedName() == Syntax::rSYSTEM
            || iter.reservedName() == Syntax::rPUBLIC)) {
      Markup copy(m);
      copy.resize(iter.index());
      outputMarkup(event->location(), copy);
      break;
      }
  }
  else
    outputMarkup(event->location(), event->markup());
  if (event->hasInternalSubset()
      || (normalizeFlags_ & normalizeExpandProlog)) {
    os() << syntax_->delimGeneral(Syntax::dDSO);
    hasInternalSubset_ = 1;
  }
  else
    hasInternalSubset_ = 0;
  delete event;
}

void CopyEventHandler::endDtd(EndDtdEvent *event)
{
  endSubset(event);
}

void CopyEventHandler::endLpd(EndLpdEvent *event)
{
  endSubset(event);
}

void CopyEventHandler::endSubset(MarkupEvent *event)
{
  if (doNothing(event))
    return;
  if (hasInternalSubset_)
    os() << syntax_->delimGeneral(Syntax::dDSC);
  outputMarkup(event->location(), event->markup());
  delete event;
}

void CopyEventHandler::entityDecl(EntityDeclEvent *event)
{
  currentAttributes_ = 0;
  const ExternalDataEntity *extData = event->entity().asExternalDataEntity();
  if (extData)
    currentAttributes_ = &extData->attributes();
  markup(event->location(), event->markup());
  currentAttributes_ = 0;
  delete event;
}

void CopyEventHandler::shortrefDecl(ShortrefDeclEvent *event)
{
  if (doNothing(event))
    return;
  if (!(normalizeFlags_ & normalizeShortref))
    outputMarkup(event->location(), event->markup());
  delete event;
}

void CopyEventHandler::entityStart(EntityStartEvent *event)
{
  if (event->entity()->name() == outputEntity_
      && event->entity()->declType() == Entity::generalEntity)
    outputEntityLevel_ = entityLevel_ + 1;
  if (inInstance_ && (normalizeFlags_ & normalizeOmittagHoist)) {
    if (event->entity()->asInternalEntity())
      omittagHoist_++;
    else
      omittagHoist_ = 0;
  }
  if (doNothing(event)) {
    entityLevel_++;
    return;
  }
  entityLevel_++;
  if ((normalizeFlags_ & normalizeExpand)
      && inInstance_
      && entityLevel_ > outputEntityLevel_) {
    entityStack_.resize(entityStack_.size() + 1);
    entityStack_.back().ref = event->entityOrigin();
    os_ = &entityStack_.back().str;
  }
  entityOrigin_ = event->entityOrigin();
  delete event;
}

void CopyEventHandler::entityEnd(EntityEndEvent *event)
{
  if (omittagHoist_ > 0)
    omittagHoist_--;
  if (entityLevel_-- == outputEntityLevel_) {
    outputEntityLevel_ = unsigned(-1);
    outputEntity_.resize(0);
  }
  else if (!(normalizeFlags_
           & (inInstance_ ? normalizeExpand : normalizeExpandProlog))
         && entityLevel_ == outputEntityLevel_) {
    if (!entityOrigin_.isNull()) {
      switch (entityOrigin_->entity()->declType()) {
      case Entity::doctype:
      case Entity::linktype:
      break;
      default:
      entityRef(entityOrigin_.pointer());
      break;
      }
    }
    entityOrigin_.clear();
  }
  else if ((normalizeFlags_ & normalizeExpand)
         && inInstance_
         && entityLevel_ >= outputEntityLevel_) {
    if (entityStack_.size() > 0) {
      ConstPtr<EntityOrigin> origin
      = entityStack_.back().ref;
      entityStack_.resize(entityStack_.size() - 1);
      if (entityStack_.size() > 0)
      os_ = &entityStack_.back().str;
      else
      os_ = topOs_;
      entityRef(origin.pointer());
    }
  }
  delete event;
}

void CopyEventHandler::outputMarkup(const Location &loc,
                            const Markup &markup)
{
  int level = 0;
  Boolean first = 1;
  MarkupIter iter(markup);
  while (iter.valid()) {
    switch (iter.type()) {
    case Markup::delimiter:
      if (first)
      withNamedCharRef(syntax_->delimGeneral(iter.delimGeneral()), loc);
      else if (!level) {
      os() << syntax_->delimGeneral(iter.delimGeneral());
      // hack, hack!
      if (iter.delimGeneral() == Syntax::dDSO && currentAttributes_ != 0) {
        attributeSpecList(iter, *currentAttributes_);
        first = 0;
        continue;       // skip the advance
      }
      }
      break;
    case Markup::refEndRe:
      if (!level)
      os().put(syntax_->standardFunction(Syntax::fRE));
      break;
    case Markup::sdReservedName:
      if (!level) {
      if (normalizeFlags_ & normalizeReserved)
        os() << sd_->reservedName(iter.sdReservedName());
      else
        os() << iter;
      }
      break;
    case Markup::reservedName:
      if (!level && (normalizeFlags_ & normalizeReserved)) {
      os() << syntax_->reservedName(iter.reservedName());
      break;
      }
    case Markup::shortref:
      if (first) {
      withNamedCharRef(iter.charsPointer(), iter.charsLength(), loc);
      break;
      }
      // fall through
    case Markup::name:
    case Markup::nameToken:
    case Markup::attributeValue:
    case Markup::number:
    case Markup::s:
      if (!level)
      os() << iter;
      break;
    case Markup::comment:
      if (!level)
      os() << syntax_->delimGeneral(Syntax::dCOM)
           << iter
           << syntax_->delimGeneral(Syntax::dCOM);
      break;
    case Markup::entityStart:
      if (!level++) {
      const EntityOrigin *origin = iter.entityOrigin();
      // entityStarts in the SGML declaration don't have explicit references
      if (origin->entity())
        entityRef(origin);
      }
      break;
    case Markup::entityEnd:
      level--;
      break;
    case Markup::literal:
      if (!level)
      literal(iter.text());
      break;
    case Markup::sdLiteral:
      if (!level)
      sdParamLiteral(iter.sdText());
      break;
    default:
      CANNOT_HAPPEN();
    }
    iter.advance();
    first = 0;
  }
}

void CopyEventHandler::sdParamLiteral(const SdText &text)
{
  const StringC &delim = syntax_->delimGeneral(text.lita()
                                     ? Syntax::dLITA
                                     : Syntax::dLIT);
  os() << delim;
  SdTextIter iter(text);
  const SyntaxChar *p;
  size_t n;
  Location loc;
  while (iter.next(p, n, loc)) {
    const Markup *markupPtr;
    if (n == 1 && loc.origin()->isNumericCharRef(markupPtr)) {
      if (markupPtr)
      outputMarkup(loc.origin()->parent(), *markupPtr);
    }
    else if (n > 0) {
      Char c = Char(*p);
      withNamedCharRef(&c, 1, loc);
      for (++p, --n; n > 0; ++p, --n)
      os().put(Char(*p));
    }
  }
  os() << delim;
}

void CopyEventHandler::entityRef(const EntityOrigin *origin)
{
  const Markup *m = origin->markup();
  if (!m)
    return;
  MarkupIter iter(*m);
  if (iter.valid()) {
    iter.advance();
    if (iter.valid()
      && iter.type() == Markup::shortref
      && (normalizeFlags_ & normalizeShortref)) {
       handleChange();
       Boolean containsRE = 0;
       Boolean containsRS = 0;
       for (size_t i = 0; i < iter.charsLength(); i++) {
       Char c = iter.charsPointer()[i];
       if (c == syntax_->standardFunction(Syntax::fRE))
         containsRE = 1;
       else if (c == syntax_->standardFunction(Syntax::fRS))
         containsRS = 1;
       }
       if (containsRS)
       os().put(syntax_->standardFunction(Syntax::fRS));
       os() << syntax_->delimGeneral(Syntax::dERO)
       << origin->entity()->name();
       if (containsRE)
       os().put(syntax_->standardFunction(Syntax::fRE));
       else
       os() << syntax_->delimGeneral(Syntax::dREFC);
       return;
     }
  }
  outputMarkup(origin->parent(), *m);
}

const StringC &CopyEventHandler::elementTypeOrigName(const ElementType *type,
                                         StringC &buf)
{
  if (type->index() < elementTypeOrigNames_.size()
      && elementTypeOrigNames_[type->index()].size() > 0)
    return elementTypeOrigNames_[type->index()];
  else
    return generalName(type->name(), buf);
}

const StringC &CopyEventHandler::generalName(const StringC &name,
                                   StringC &buf)
{
  if ((normalizeFlags_ & normalizeLower)
      && syntax_->namecaseGeneral())
    return lowerCaseName(name, buf);
  else
    return name;
}

const StringC &CopyEventHandler::entityName(const StringC &name,
                                  StringC &buf)
{
  if ((normalizeFlags_ & normalizeLower)
      && syntax_->namecaseEntity())
    return lowerCaseName(name, buf);
  else
    return name;
}

const StringC &CopyEventHandler::lowerCaseName(const StringC &name,
                                     StringC &buf)
{
  size_t i;
  for (i = 0; i < name.size(); i++) {
    Char c = lowerSubst_[name[i]];
    if (c != name[i]) {
      buf = name;
      buf[i] = c;
      for (i++; i < name.size(); i++)
      lowerSubst_.subst(buf[i]);
      return buf;
    }
  }
  return name;
}

void CopyEventHandler::handleChange()
{
  if (os_ != topOs_) {
    os_ = topOs_;
    for (size_t i = 0; i < entityStack_.size(); i++) {
      StringC tem;
      entityStack_[i].str.flush();
      entityStack_[i].str.extractString(tem);
      os() << tem;
    }
    entityStack_.resize(0);
  }
}

#ifdef SP_NAMESPACE
}
#endif

Generated by  Doxygen 1.6.0   Back to index