Blame nsgmls/RastEventHandler.cxx

Packit 8a864e
// Copyright (c) 1994,1995 James Clark
Packit 8a864e
// See the file COPYING for copying permission.
Packit 8a864e
Packit 8a864e
#ifdef __GNUG__
Packit 8a864e
#pragma implementation
Packit 8a864e
#endif
Packit 8a864e
Packit 8a864e
#include "config.h"
Packit 8a864e
#include "RastEventHandler.h"
Packit 8a864e
#include "SgmlParser.h"
Packit 8a864e
#include "ParserOptions.h"
Packit 8a864e
#include "Entity.h"
Packit 8a864e
#include "Notation.h"
Packit 8a864e
#include "Attribute.h"
Packit 8a864e
#include "Vector.h"
Packit 8a864e
#include "Vector.h"
Packit 8a864e
#include "MessageArg.h"
Packit 8a864e
Packit 8a864e
#include "RastEventHandlerMessages.h"
Packit 8a864e
Packit 8a864e
#include <stdlib.h>
Packit 8a864e
#include <string.h>
Packit 8a864e
Packit 8a864e
// This is based on ISO/IEC 13673, Intermediate Editor's Draft, 1994/8/29,
Packit 8a864e
// together with editing instructions in ISO/IEC JTC1/SC18/WG8 N1777.
Packit 8a864e
Packit 8a864e
#ifdef SP_NAMESPACE
Packit 8a864e
namespace SP_NAMESPACE {
Packit 8a864e
#endif
Packit 8a864e
Packit 8a864e
const OutputCharStream::Newline nl = OutputCharStream::newline;
Packit 8a864e
Packit 8a864e
class EventHandlerMessenger : public Messenger {
Packit 8a864e
public:
Packit 8a864e
  EventHandlerMessenger(EventHandler *eh) : eh_(eh) { }
Packit 8a864e
  void dispatchMessage(const Message &message) {
Packit 8a864e
    eh_->message(new MessageEvent(message));
Packit 8a864e
  }
Packit 8a864e
  void dispatchMessage(Message &message) {
Packit 8a864e
    eh_->message(new MessageEvent(message));
Packit 8a864e
  }
Packit 8a864e
private:
Packit 8a864e
  EventHandler *eh_;
Packit 8a864e
};
Packit 8a864e
Packit 8a864e
#if 0
Packit 8a864e
const 
Packit 8a864e
#endif
Packit 8a864e
RastPrintable RastEventHandler::printable;
Packit 8a864e
Packit 8a864e
RastPrintable::RastPrintable()
Packit 8a864e
{
Packit 8a864e
  static const char s[] =
Packit 8a864e
    " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
Packit 8a864e
  size_t i;
Packit 8a864e
  for (i = 0; i < sizeof(v_); i++)
Packit 8a864e
    v_[i] = 0;
Packit 8a864e
  for (i = 0; s[i] != '\0'; i++)
Packit 8a864e
    v_[(unsigned char)s[i]] = 32 + i;
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
// inline
Packit 8a864e
void RastEventHandler::flushLine(LineType type)
Packit 8a864e
{
Packit 8a864e
  if (lineLength_ > 0) {
Packit 8a864e
    os() << char(type) << nl;
Packit 8a864e
    lineLength_ = 0;
Packit 8a864e
  }
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
RastSubdocState::RastSubdocState()
Packit 8a864e
{
Packit 8a864e
  init(0, 0);
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
RastSubdocState::RastSubdocState(SgmlParser *parser, RastEventHandler *rast)
Packit 8a864e
{
Packit 8a864e
  init(parser, rast);
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastSubdocState::init(SgmlParser *parser, RastEventHandler *rast)
Packit 8a864e
{
Packit 8a864e
  parser_ = parser;
Packit 8a864e
  hadActiveLpdOrDtd_ = 0;
Packit 8a864e
  activeLinkTypes_.clear();
Packit 8a864e
  hadDocumentElement_ = 0;
Packit 8a864e
  linkProcess_.clear();
Packit 8a864e
  linkProcess_.setHandler(rast);
Packit 8a864e
  haveLinkProcess_ = 0;
Packit 8a864e
  endPrologEvent_.clear();
Packit 8a864e
  parseSubdocQueue_.clear();
Packit 8a864e
  linkRuleQueue_.clear();
Packit 8a864e
  for (int i = 0; i < nAttributeType; i++)
Packit 8a864e
    attributeSortOrder_[i].clear();
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastSubdocState::swap(RastSubdocState &to)
Packit 8a864e
{
Packit 8a864e
  {
Packit 8a864e
    SgmlParser *tem = to.parser_;
Packit 8a864e
    to.parser_ = parser_;
Packit 8a864e
    parser_ = tem;
Packit 8a864e
  }
Packit 8a864e
  {
Packit 8a864e
    Boolean tem = to.hadActiveLpdOrDtd_;
Packit 8a864e
    to.hadActiveLpdOrDtd_ = hadActiveLpdOrDtd_;
Packit 8a864e
    hadActiveLpdOrDtd_ = tem;
Packit 8a864e
  }
Packit 8a864e
  {
Packit 8a864e
    Boolean tem = to.hadDocumentElement_;
Packit 8a864e
    to.hadDocumentElement_ = hadDocumentElement_;
Packit 8a864e
    hadDocumentElement_ = tem;
Packit 8a864e
  }
Packit 8a864e
  activeLpdOrDtdLocation_.swap(to.activeLpdOrDtdLocation_);
Packit 8a864e
  activeLinkTypes_.swap(to.activeLinkTypes_);
Packit 8a864e
  linkProcess_.swap(to.linkProcess_);
Packit 8a864e
  endPrologEvent_.swap(to.endPrologEvent_);
Packit 8a864e
  parseSubdocQueue_.swap(to.parseSubdocQueue_);
Packit 8a864e
  linkRuleQueue_.swap(to.linkRuleQueue_);
Packit 8a864e
  for (int i = 0; i < nAttributeType; i++)
Packit 8a864e
    attributeSortOrder_[i].swap(to.attributeSortOrder_[i]);
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
RastEventHandler::RastEventHandler(SgmlParser *parser, Messenger *mgr)
Packit 8a864e
: lineLength_(0),
Packit 8a864e
  os_(0),
Packit 8a864e
  piErrorCount_(0),
Packit 8a864e
  RastSubdocState(parser, this),
Packit 8a864e
  mgr_(mgr)
Packit 8a864e
{
Packit 8a864e
  RastSubdocState::init(parser, this);
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::end()
Packit 8a864e
{
Packit 8a864e
  if (errorCount() != 0) {
Packit 8a864e
    truncateOutput();
Packit 8a864e
    os() << (piErrorCount_ != 0
Packit 8a864e
	     ? "#RAST-PI-ERROR"
Packit 8a864e
	     : "#ERROR")
Packit 8a864e
         << nl;
Packit 8a864e
  }
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::truncateOutput()
Packit 8a864e
{
Packit 8a864e
  // This must be handled by derived classes to get conforming output.
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::sgmlDecl(SgmlDeclEvent *event)
Packit 8a864e
{
Packit 8a864e
  rastParseSubdocYesString_ = event->sd().execToInternal("rast-parse-subdoc:yes");
Packit 8a864e
  rastParseSubdocNoString_ = event->sd().execToInternal("rast-parse-subdoc:no");
Packit 8a864e
  rastActiveLpdString_ = event->sd().execToInternal("rast-active-lpd:");
Packit 8a864e
  rastLinkRuleString_ = event->sd().execToInternal("rast-link-rule:");
Packit 8a864e
  delete event;
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::startElement(StartElementEvent *event)
Packit 8a864e
{
Packit 8a864e
  flushLine(dataLine);
Packit 8a864e
  if (!hadDocumentElement_) {
Packit 8a864e
    if (activeLinkTypes_.size() > 0) {
Packit 8a864e
      activeLinks();
Packit 8a864e
      simpleLinkInfo();
Packit 8a864e
    }
Packit 8a864e
    hadDocumentElement_ = 1;
Packit 8a864e
  }
Packit 8a864e
  os() << '[' << event->name();
Packit 8a864e
  Boolean hadNewline;
Packit 8a864e
  if (event->attributes().size() > 0) {
Packit 8a864e
    hadNewline = 1;
Packit 8a864e
    os() << nl;
Packit 8a864e
    attributeInfo(event->attributes(), dtdAttribute);
Packit 8a864e
  }
Packit 8a864e
  else
Packit 8a864e
    hadNewline = 0;
Packit 8a864e
  if (haveLinkProcess_) {
Packit 8a864e
    const AttributeList *linkAttributes;
Packit 8a864e
    const ResultElementSpec *resultElementSpec;
Packit 8a864e
    EventHandlerMessenger messenger(this);
Packit 8a864e
    linkProcess_.startElement(event->elementType(),
Packit 8a864e
			      event->attributes(),
Packit 8a864e
			      event->location(),
Packit 8a864e
			      messenger,
Packit 8a864e
			      linkAttributes,
Packit 8a864e
			      resultElementSpec);
Packit 8a864e
    if (linkProcess_.nImpliedLinkRules() > 0) {
Packit 8a864e
      if (!hadNewline) {
Packit 8a864e
	os() << nl;
Packit 8a864e
	hadNewline = 1;
Packit 8a864e
      }
Packit 8a864e
      os() << "#LINK-SET-INFO" << nl;
Packit 8a864e
      impliedSourceLinkRules();
Packit 8a864e
    }
Packit 8a864e
    if (linkAttributes) {
Packit 8a864e
      if (!hadNewline) {
Packit 8a864e
	os() << nl;
Packit 8a864e
	hadNewline = 1;
Packit 8a864e
      }
Packit 8a864e
      os() << "#LINK-RULE" << nl;
Packit 8a864e
      attributeInfo(*linkAttributes, linkAttribute);
Packit 8a864e
      if (linkProcess_.isExplicit()) {
Packit 8a864e
	os() << "#RESULT=";
Packit 8a864e
	if (resultElementSpec && resultElementSpec->elementType) {
Packit 8a864e
	  os() << resultElementSpec->elementType->name() << nl;
Packit 8a864e
	  attributeInfo(resultElementSpec->attributeList, resultAttribute);
Packit 8a864e
	}
Packit 8a864e
	else
Packit 8a864e
	  os() << "#IMPLIED" << nl;
Packit 8a864e
      }
Packit 8a864e
    }
Packit 8a864e
    else
Packit 8a864e
      hadNewline = 0;
Packit 8a864e
  }
Packit 8a864e
  os() << ']' << nl;
Packit 8a864e
  delete event;
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::activeLinks()
Packit 8a864e
{
Packit 8a864e
  for (size_t i = 0; i < activeLinkTypes_.size(); i++) {
Packit 8a864e
    os() << "#ACTIVE-LINK=" << activeLinkTypes_[i] << nl;
Packit 8a864e
    Boolean found = 0;
Packit 8a864e
    if (haveLinkProcess_ && linkProcess_.name() == activeLinkTypes_[i]) {
Packit 8a864e
      found = 1;
Packit 8a864e
      if (linkProcess_.nImpliedLinkRules() > 0) {
Packit 8a864e
	os() << "#INITIAL" << nl;
Packit 8a864e
	impliedSourceLinkRules();
Packit 8a864e
      }
Packit 8a864e
    }
Packit 8a864e
    if (!found) {
Packit 8a864e
      if (endPrologEvent_) {
Packit 8a864e
	for (size_t j = 0; j < endPrologEvent_->simpleLinkNames().size(); j++)
Packit 8a864e
	  if (endPrologEvent_->simpleLinkNames()[j] == activeLinkTypes_[i]) {
Packit 8a864e
	    found = 1;
Packit 8a864e
	    break;
Packit 8a864e
	  }
Packit 8a864e
      }
Packit 8a864e
      if (!found) {
Packit 8a864e
	setNextLocation(activeLpdOrDtdLocation_);
Packit 8a864e
	Messenger::message(RastEventHandlerMessages::invalidActiveLinkType,
Packit 8a864e
			   StringMessageArg(activeLinkTypes_[i]));
Packit 8a864e
      }
Packit 8a864e
    }
Packit 8a864e
    os() << "#END-ACTIVE-LINK" << nl;
Packit 8a864e
  }
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::simpleLinkInfo()
Packit 8a864e
{
Packit 8a864e
  if (!endPrologEvent_)
Packit 8a864e
    return;
Packit 8a864e
  for (size_t i = 0; i < activeLinkTypes_.size(); i++) {
Packit 8a864e
    for (size_t j = 0; j < endPrologEvent_->simpleLinkNames().size(); j++) {
Packit 8a864e
      const StringC &name = endPrologEvent_->simpleLinkNames()[j];
Packit 8a864e
      if (name == activeLinkTypes_[i]) {
Packit 8a864e
	os() << "#SIMPLE-LINK=" << name << nl;
Packit 8a864e
	if (endPrologEvent_->simpleLinkAttributes()[j].size() > 0)
Packit 8a864e
	  attributeInfo(endPrologEvent_->simpleLinkAttributes()[j],
Packit 8a864e
			simpleAttribute);
Packit 8a864e
	os() << "#END-SIMPLE-LINK" << nl;
Packit 8a864e
	break;
Packit 8a864e
      }
Packit 8a864e
    }
Packit 8a864e
  }
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::impliedSourceLinkRules()
Packit 8a864e
{
Packit 8a864e
  size_t n = linkProcess_.nImpliedLinkRules();
Packit 8a864e
  Vector<size_t> sortOrder(n);
Packit 8a864e
  size_t i;
Packit 8a864e
  for (i = 0; i < n; i++)
Packit 8a864e
    sortOrder[i] = i;
Packit 8a864e
  for (i = 1; i < n; i++) {
Packit 8a864e
    size_t tem = sortOrder[i];
Packit 8a864e
    const StringC &name
Packit 8a864e
      = linkProcess_.impliedLinkRule(tem).elementType->name();
Packit 8a864e
    size_t j;
Packit 8a864e
    for (j = i; j > 0; j--) {
Packit 8a864e
      if (lexCmp(linkProcess_.impliedLinkRule(j - 1).elementType->name(),
Packit 8a864e
		 name) <= 0)
Packit 8a864e
	break;
Packit 8a864e
      sortOrder[j] = sortOrder[j - 1];
Packit 8a864e
    }
Packit 8a864e
    sortOrder[j] = tem;
Packit 8a864e
  }
Packit 8a864e
  for (i = 0; i < n; i++) {
Packit 8a864e
    const ResultElementSpec &result
Packit 8a864e
      = linkProcess_.impliedLinkRule(sortOrder[i]);
Packit 8a864e
    os() << '[' << result.elementType->name();
Packit 8a864e
    if (result.attributeList.size() > 0) {
Packit 8a864e
      os() << nl;
Packit 8a864e
      attributeInfo(result.attributeList, resultAttribute);
Packit 8a864e
    }
Packit 8a864e
    os() << ']' << nl;
Packit 8a864e
  }
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::endElement(EndElementEvent *event)
Packit 8a864e
{
Packit 8a864e
  if (haveLinkProcess_)
Packit 8a864e
    linkProcess_.endElement();
Packit 8a864e
  flushLine(dataLine);
Packit 8a864e
  os() << "[/" << event->name() << ']' << nl;
Packit 8a864e
  if (haveLinkProcess_ && linkProcess_.nImpliedLinkRules() > 0) {
Packit 8a864e
    os() << "#LINK-SET-INFO" << nl;
Packit 8a864e
    impliedSourceLinkRules();
Packit 8a864e
    os() << "#END-LINK-SET-INFO" << nl;
Packit 8a864e
  }
Packit 8a864e
  delete event;
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::data(DataEvent *event)
Packit 8a864e
{
Packit 8a864e
  lines(dataLine, event->data(), event->dataLength());
Packit 8a864e
  delete event;
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::pi(PiEvent *event)
Packit 8a864e
{
Packit 8a864e
  flushLine(dataLine);
Packit 8a864e
  os() << "[?";
Packit 8a864e
  size_t dataLength = event->dataLength();
Packit 8a864e
  if (dataLength > 0) {
Packit 8a864e
    const Char *data = event->data();
Packit 8a864e
    if (dataLength >= 4
Packit 8a864e
	&& memcmp(data,
Packit 8a864e
		  rastParseSubdocYesString_.data(),
Packit 8a864e
		  4*sizeof(Char)) == 0
Packit 8a864e
	&& !interpretRastPi(data, dataLength, event->location())) {
Packit 8a864e
      setNextLocation(event->location());
Packit 8a864e
      Messenger::message(RastEventHandlerMessages::invalidRastPiError);
Packit 8a864e
    }
Packit 8a864e
    os() << nl;
Packit 8a864e
    lines(dataLine, event->data(), dataLength);
Packit 8a864e
    flushLine(dataLine);
Packit 8a864e
  }
Packit 8a864e
  os() << ']' << nl;
Packit 8a864e
  delete event;
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
inline
Packit 8a864e
Boolean equal(const Char *s1, size_t n1, const StringC &s2)
Packit 8a864e
{
Packit 8a864e
  return (n1 == s2.size()
Packit 8a864e
	  && (n1 == 0
Packit 8a864e
	      || memcmp(s1, s2.data(), n1*sizeof(Char)) == 0));
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
// Is s2 a prefix of s1 of length n1?
Packit 8a864e
Packit 8a864e
inline
Packit 8a864e
Boolean prefix(const Char *s1, size_t n1, const StringC &s2)
Packit 8a864e
{
Packit 8a864e
  return (n1 >= s2.size()
Packit 8a864e
	  && (n1 == 0
Packit 8a864e
	      || memcmp(s1, s2.data(), s2.size()*sizeof(Char)) == 0));
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
Boolean RastEventHandler::interpretRastPi(const Char *data,
Packit 8a864e
					  size_t dataLength,
Packit 8a864e
					  const Location &loc)
Packit 8a864e
{
Packit 8a864e
  if (equal(data, dataLength, rastParseSubdocNoString_)) {
Packit 8a864e
    queueParseSubdoc(0);
Packit 8a864e
    return 1;
Packit 8a864e
  }
Packit 8a864e
  if (equal(data, dataLength, rastParseSubdocYesString_)) {
Packit 8a864e
    queueParseSubdoc(1);
Packit 8a864e
    return 1;
Packit 8a864e
  }
Packit 8a864e
  if (prefix(data, dataLength, rastActiveLpdString_)) {
Packit 8a864e
    if (hadActiveLpdOrDtd_)
Packit 8a864e
      return 1;
Packit 8a864e
    hadActiveLpdOrDtd_ = 1;
Packit 8a864e
    activeLpdOrDtdLocation_ = loc;
Packit 8a864e
    const Char *p = data + rastActiveLpdString_.size();
Packit 8a864e
    size_t n = dataLength - rastActiveLpdString_.size();
Packit 8a864e
    StringC name;
Packit 8a864e
    for (;;) {
Packit 8a864e
      if (n == 0 || *p == ',') {
Packit 8a864e
	if (name.size() == 0)
Packit 8a864e
	  return 0;
Packit 8a864e
	for (size_t i = 0; i < activeLinkTypes_.size(); i++)
Packit 8a864e
	  if (name == activeLinkTypes_[i]) {
Packit 8a864e
	    setNextLocation(activeLpdOrDtdLocation_);
Packit 8a864e
	    Messenger::message(RastEventHandlerMessages::duplicateActiveLinkType,
Packit 8a864e
			       StringMessageArg(name));
Packit 8a864e
	  }
Packit 8a864e
	activeLinkTypes_.resize(activeLinkTypes_.size() + 1);
Packit 8a864e
	name.swap(activeLinkTypes_.back());
Packit 8a864e
	if (n == 0)
Packit 8a864e
	  break;
Packit 8a864e
      }
Packit 8a864e
      else
Packit 8a864e
	name += *p;
Packit 8a864e
      p++;
Packit 8a864e
      n--;
Packit 8a864e
    }
Packit 8a864e
    for (size_t i = 0; i < activeLinkTypes_.size(); i++)
Packit 8a864e
      parser_->activateLinkType(activeLinkTypes_[i]);
Packit 8a864e
    return 1;
Packit 8a864e
  }
Packit 8a864e
  if (prefix(data, dataLength, rastLinkRuleString_)) {
Packit 8a864e
    LinkRulePi *p = new LinkRulePi;
Packit 8a864e
    p->pi.assign(data + rastLinkRuleString_.size(),
Packit 8a864e
		 dataLength - rastLinkRuleString_.size());
Packit 8a864e
    p->loc = loc;
Packit 8a864e
    linkRuleQueue_.append(p);
Packit 8a864e
    return 1;
Packit 8a864e
  }
Packit 8a864e
  return 0;
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::sdataEntity(SdataEntityEvent *event)
Packit 8a864e
{
Packit 8a864e
  flushLine(dataLine);
Packit 8a864e
  os() << "#SDATA-TEXT" << nl;
Packit 8a864e
  lines(markupLine, event->data(), event->dataLength());
Packit 8a864e
  flushLine(markupLine);
Packit 8a864e
  os() << "#END-SDATA" << nl;
Packit 8a864e
  delete event;
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::externalDataEntity(ExternalDataEntityEvent *event)
Packit 8a864e
{
Packit 8a864e
  const ExternalDataEntity *entity = event->entity();
Packit 8a864e
  if (!entity)
Packit 8a864e
    return;
Packit 8a864e
  flushLine(dataLine);
Packit 8a864e
  os() << "[&" << entity->name() << nl;
Packit 8a864e
  externalEntityInfo(entity, dtdAttribute);
Packit 8a864e
  os() << ']' << nl;
Packit 8a864e
  delete event;
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::externalEntityInfo(const ExternalDataEntity *entity,
Packit 8a864e
					  AttributeType attributeType)
Packit 8a864e
{
Packit 8a864e
  char c;
Packit 8a864e
  switch (entity->dataType()) {
Packit 8a864e
  case Entity::cdata:
Packit 8a864e
    c = 'C';
Packit 8a864e
    break;
Packit 8a864e
  case Entity::sdata:
Packit 8a864e
    c = 'S';
Packit 8a864e
    break;
Packit 8a864e
  case Entity::ndata:
Packit 8a864e
    c = 'N';
Packit 8a864e
    break;
Packit 8a864e
  default:
Packit 8a864e
    return;
Packit 8a864e
  }
Packit 8a864e
  os() << '#' << c << "DATA-EXTERNAL" << nl;
Packit 8a864e
  externalIdInfo(entity->externalId());
Packit 8a864e
  os() << "#NOTATION=" << entity->notation()->name() << nl;
Packit 8a864e
  externalIdInfo(entity->notation()->externalId());
Packit 8a864e
  attributeInfo(entity->attributes(),
Packit 8a864e
		(attributeType == resultAttribute
Packit 8a864e
		 ? resultAttribute
Packit 8a864e
		 : dtdAttribute));
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::subdocEntity(SubdocEntityEvent *event)
Packit 8a864e
{
Packit 8a864e
  const SubdocEntity *entity = event->entity();
Packit 8a864e
  if (!entity)
Packit 8a864e
    return;
Packit 8a864e
  flushLine(dataLine);
Packit 8a864e
  os() << "[&" << entity->name() << nl;
Packit 8a864e
  Ptr<InputSourceOrigin> origin(event->entityOrigin()->copy());
Packit 8a864e
  subdocEntityInfo(entity, origin, 1);
Packit 8a864e
  os() << ']' << nl;
Packit 8a864e
  delete event;
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::subdocEntityInfo(const SubdocEntity *entity,
Packit 8a864e
					const Ptr<InputSourceOrigin> &entityOrigin,
Packit 8a864e
					Boolean referenced)
Packit 8a864e
{
Packit 8a864e
  os() << "#SUBDOC" << nl;
Packit 8a864e
  externalIdInfo(entity->externalId());
Packit 8a864e
  if (parseNextSubdoc()) {
Packit 8a864e
    // FIXME subdocuments in entity attributes shouldn't count against
Packit 8a864e
    // SUBDOC quantity limit.
Packit 8a864e
    os() << "#PARSED-SUBDOCUMENT" << nl;
Packit 8a864e
    SgmlParser::Params params;
Packit 8a864e
    params.entityType = SgmlParser::Params::subdoc;
Packit 8a864e
    params.subdocInheritActiveLinkTypes = 0;
Packit 8a864e
    params.subdocReferenced = referenced;
Packit 8a864e
    params.parent = parser_;
Packit 8a864e
    params.sysid = entity->externalId().effectiveSystemId();
Packit 8a864e
    params.origin = entityOrigin;
Packit 8a864e
    SgmlParser parser(params);
Packit 8a864e
    RastSubdocState oldSubdocState;
Packit 8a864e
    RastSubdocState::swap(oldSubdocState);
Packit 8a864e
    RastSubdocState::init(&parser, this);
Packit 8a864e
    parser.parseAll(*this);
Packit 8a864e
    oldSubdocState.swap(*this);
Packit 8a864e
  }
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::queueParseSubdoc(Boolean parseSubdoc)
Packit 8a864e
{
Packit 8a864e
  parseSubdocQueue_.push_back(PackedBoolean(parseSubdoc));
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
Boolean RastEventHandler::parseNextSubdoc()
Packit 8a864e
{
Packit 8a864e
  if (parseSubdocQueue_.size() == 0)
Packit 8a864e
    return 0;
Packit 8a864e
  Boolean result = parseSubdocQueue_[0];
Packit 8a864e
  if (parseSubdocQueue_.size() > 1) {
Packit 8a864e
    for (size_t i = 1; i < parseSubdocQueue_.size(); i++)
Packit 8a864e
      parseSubdocQueue_[i - 1] = parseSubdocQueue_[i];
Packit 8a864e
  }
Packit 8a864e
  parseSubdocQueue_.resize(parseSubdocQueue_.size() - 1);
Packit 8a864e
  return result;
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
Packit 8a864e
void RastEventHandler::externalIdInfo(const ExternalId &id)
Packit 8a864e
{
Packit 8a864e
  const StringC *systemId = id.systemIdString();
Packit 8a864e
  const StringC *publicId = id.publicIdString();
Packit 8a864e
  if (publicId) {
Packit 8a864e
    os() << "#PUBLIC" << nl;
Packit 8a864e
    if (publicId->size() == 0)
Packit 8a864e
      os() << "#EMPTY" << nl;
Packit 8a864e
    else {
Packit 8a864e
      lines(markupLine, publicId->data(), publicId->size());
Packit 8a864e
      flushLine(markupLine);
Packit 8a864e
    }
Packit 8a864e
  }
Packit 8a864e
  if (systemId || !publicId) {
Packit 8a864e
    os() << "#SYSTEM" << nl;
Packit 8a864e
    if (!systemId)
Packit 8a864e
      os() << "#NONE" << nl;
Packit 8a864e
    else if (systemId->size() == 0)
Packit 8a864e
      os() << "#EMPTY" << nl;
Packit 8a864e
    else {
Packit 8a864e
      lines(markupLine, systemId->data(), systemId->size());
Packit 8a864e
      flushLine(markupLine);
Packit 8a864e
    }
Packit 8a864e
  }
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::nonSgmlChar(NonSgmlCharEvent *event)
Packit 8a864e
{
Packit 8a864e
  flushLine(dataLine);
Packit 8a864e
  os() <<'#' << (unsigned long)event->character() << nl;
Packit 8a864e
  delete event;
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::lines(LineType type, const Char *p, size_t length)
Packit 8a864e
{
Packit 8a864e
  // This needs to be fast.
Packit 8a864e
  while (length != 0) {
Packit 8a864e
    if (printable(*p)) {
Packit 8a864e
      size_t lim;
Packit 8a864e
      switch (lineLength_) {
Packit 8a864e
      case maxLineLength:
Packit 8a864e
	os() << char(type) << nl;
Packit 8a864e
	lineLength_ = 0;
Packit 8a864e
	// fall through
Packit 8a864e
      case 0:
Packit 8a864e
	os() << char(type);
Packit 8a864e
	lim = maxLineLength;
Packit 8a864e
	break;
Packit 8a864e
      default:
Packit 8a864e
	lim = maxLineLength - lineLength_;
Packit 8a864e
	break;
Packit 8a864e
      }
Packit 8a864e
      if (lim > length)
Packit 8a864e
	lim = length;
Packit 8a864e
      size_t n = lim;
Packit 8a864e
      for (;;) {
Packit 8a864e
	os().put(*p);
Packit 8a864e
	p++;
Packit 8a864e
	if (--n == 0)
Packit 8a864e
	  break;
Packit 8a864e
	if (!printable(*p)) {
Packit 8a864e
	  lim -= n;
Packit 8a864e
	  break;
Packit 8a864e
	}
Packit 8a864e
      }
Packit 8a864e
      length -= lim;
Packit 8a864e
      lineLength_ += lim;
Packit 8a864e
    }
Packit 8a864e
    else {
Packit 8a864e
      // *p is an unprintable character print it
Packit 8a864e
      flushLine(type);
Packit 8a864e
      switch (*p) {
Packit 8a864e
      case RS:
Packit 8a864e
	os() << "#RS" << nl;
Packit 8a864e
	break;
Packit 8a864e
      case RE:
Packit 8a864e
	os() << "#RE" << nl;
Packit 8a864e
	break;
Packit 8a864e
      case TAB:
Packit 8a864e
	os() << "#TAB" << nl;
Packit 8a864e
	break;
Packit 8a864e
      default:
Packit 8a864e
	os() << '#' << (unsigned long)*p << nl;
Packit 8a864e
	break;
Packit 8a864e
      }
Packit 8a864e
      p++;
Packit 8a864e
      length--;
Packit 8a864e
    }
Packit 8a864e
  }
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
int RastEventHandler::lexCmp(const StringC &s1, const StringC &s2)
Packit 8a864e
{
Packit 8a864e
  const Char *p1 = s1.data();
Packit 8a864e
  size_t n1 = s1.size();
Packit 8a864e
  const Char *p2 = s2.data();
Packit 8a864e
  size_t n2 = s2.size();
Packit 8a864e
  for (;;) {
Packit 8a864e
    if (n1 == 0)
Packit 8a864e
      return n2 == 0 ? 0 : -1;
Packit 8a864e
    if (n2 == 0)
Packit 8a864e
      return 1;
Packit 8a864e
    if (*p1 != *p2) {
Packit 8a864e
      // printable characters precede non-printable characters;
Packit 8a864e
      // printable characters are in ASCII order
Packit 8a864e
      // non-printable characters are in document character set order
Packit 8a864e
      int a1 = printable(*p1);
Packit 8a864e
      int a2 = printable(*p2);
Packit 8a864e
      if (a1 == 0) {
Packit 8a864e
	if (a2 == 0)
Packit 8a864e
	  return *p1 < *p2 ? -1 : 1;
Packit 8a864e
	else
Packit 8a864e
	  return 1;
Packit 8a864e
      }
Packit 8a864e
      else if (a2 == 0)
Packit 8a864e
	return -1;
Packit 8a864e
      else
Packit 8a864e
	return a1 - a2;
Packit 8a864e
    }
Packit 8a864e
    p1++;
Packit 8a864e
    p2++;
Packit 8a864e
    n1--;
Packit 8a864e
    n2--;
Packit 8a864e
  }
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::attributeInfo(const AttributeList &attributes,
Packit 8a864e
				     AttributeType attributeType)
Packit 8a864e
{
Packit 8a864e
  size_t length = attributes.size();
Packit 8a864e
  if (length == 0)
Packit 8a864e
    return;
Packit 8a864e
  size_t defIndex = attributes.defIndex();
Packit 8a864e
  if (defIndex >= attributeSortOrder_[attributeType].size())
Packit 8a864e
    attributeSortOrder_[attributeType].resize(defIndex + 1);
Packit 8a864e
  Vector<size_t> &sortOrder = attributeSortOrder_[attributeType][defIndex];
Packit 8a864e
  if (sortOrder.size() != length
Packit 8a864e
      || attributeType == simpleAttribute) {
Packit 8a864e
    sortOrder.resize(length);
Packit 8a864e
    size_t i;
Packit 8a864e
    for (i = 0; i < length; i++)
Packit 8a864e
      sortOrder[i] = i;
Packit 8a864e
    // insertion sort
Packit 8a864e
    for (i = 1; i < length; i++) {
Packit 8a864e
      size_t tem = sortOrder[i];
Packit 8a864e
      size_t j;
Packit 8a864e
      for (j = i; j > 0; j--) {
Packit 8a864e
	if (lexCmp(attributes.name(sortOrder[j - 1]),
Packit 8a864e
		   attributes.name(tem)) <= 0)
Packit 8a864e
	  break;
Packit 8a864e
	sortOrder[j] = sortOrder[j - 1];
Packit 8a864e
      }
Packit 8a864e
      sortOrder[j] = tem;
Packit 8a864e
    }
Packit 8a864e
  }
Packit 8a864e
  for (size_t j = 0; j < length; j++) {
Packit 8a864e
    // Don't use sortOrder because attributeSortOrder_ may be grown
Packit 8a864e
    // because of data attributes.
Packit 8a864e
    size_t i = attributeSortOrder_[attributeType][defIndex][j];
Packit 8a864e
    os() << attributes.name(i) << '=' << nl;
Packit 8a864e
    const Text *text;
Packit 8a864e
    const StringC *string;
Packit 8a864e
    const AttributeValue *value = attributes.value(i);
Packit 8a864e
    if (value) {
Packit 8a864e
      switch (value->info(text, string)) {
Packit 8a864e
      case AttributeValue::implied:
Packit 8a864e
	os() << "#IMPLIED" << nl;
Packit 8a864e
	break;
Packit 8a864e
      case AttributeValue::tokenized:
Packit 8a864e
	lines(markupLine, string->data(), string->size());
Packit 8a864e
	flushLine(markupLine);
Packit 8a864e
	break;
Packit 8a864e
      case AttributeValue::cdata:
Packit 8a864e
	{
Packit 8a864e
	  TextIter iter(*text);
Packit 8a864e
	  TextItem::Type type;
Packit 8a864e
	  const Char *p;
Packit 8a864e
	  size_t length;
Packit 8a864e
	  const Location *loc;
Packit 8a864e
	  while (iter.next(type, p, length, loc))
Packit 8a864e
	    switch (type) {
Packit 8a864e
	    case TextItem::data:
Packit 8a864e
	    case TextItem::cdata:
Packit 8a864e
	      lines(markupLine, p, length);
Packit 8a864e
	      break;
Packit 8a864e
	    case TextItem::sdata:
Packit 8a864e
	      flushLine(markupLine);
Packit 8a864e
	      os() << "#SDATA-TEXT" << nl;
Packit 8a864e
	      lines(markupLine, p, length);
Packit 8a864e
	      flushLine(markupLine);
Packit 8a864e
	      os() << "#END-SDATA" << nl;
Packit 8a864e
	      break;
Packit 8a864e
	    case TextItem::nonSgml:
Packit 8a864e
	      flushLine(markupLine);
Packit 8a864e
	      os() << '#' << (unsigned long)*p << nl;
Packit 8a864e
	      break;
Packit 8a864e
	    default:
Packit 8a864e
	      break;
Packit 8a864e
	    }
Packit 8a864e
	  flushLine(markupLine);
Packit 8a864e
	}
Packit 8a864e
	break;
Packit 8a864e
      }
Packit 8a864e
    }
Packit 8a864e
    const AttributeSemantics *semantics = attributes.semantics(i);
Packit 8a864e
    if (semantics) {
Packit 8a864e
      ConstPtr<Notation> notation
Packit 8a864e
	= semantics->notation();
Packit 8a864e
      if (!notation.isNull())
Packit 8a864e
	externalIdInfo(notation->externalId());
Packit 8a864e
      size_t nEntities = semantics->nEntities();
Packit 8a864e
      for (size_t i = 0; i < nEntities; i++) {
Packit 8a864e
	ConstPtr<Entity> entity
Packit 8a864e
	  = semantics->entity(i);
Packit 8a864e
	if (!entity.isNull()) {
Packit 8a864e
	  const ExternalDataEntity *externalDataEntity
Packit 8a864e
	    = entity->asExternalDataEntity();
Packit 8a864e
	  if (externalDataEntity)
Packit 8a864e
	    externalEntityInfo(externalDataEntity,
Packit 8a864e
			       (attributeType == resultAttribute
Packit 8a864e
				? resultAttribute
Packit 8a864e
				: dtdAttribute));
Packit 8a864e
	  else {
Packit 8a864e
	    const SubdocEntity *subdocEntity = entity->asSubdocEntity();
Packit 8a864e
	    if (subdocEntity) {
Packit 8a864e
	      Ptr<InputSourceOrigin> entityOrigin
Packit 8a864e
		= EntityOrigin::make(entity,
Packit 8a864e
				     ((TokenizedAttributeValue *)value)
Packit 8a864e
				     ->tokenLocation(i));
Packit 8a864e
	      subdocEntityInfo(subdocEntity, entityOrigin, 0);
Packit 8a864e
	    }
Packit 8a864e
	    else {
Packit 8a864e
	      const InternalEntity *internalEntity = entity->asInternalEntity();
Packit 8a864e
	      if (internalEntity)
Packit 8a864e
		internalEntityInfo(internalEntity);
Packit 8a864e
	    }
Packit 8a864e
	  }
Packit 8a864e
	}
Packit 8a864e
	os() << "#END-ENTITY" << nl;
Packit 8a864e
      }
Packit 8a864e
    }
Packit 8a864e
  }
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::internalEntityInfo(const InternalEntity *entity)
Packit 8a864e
{
Packit 8a864e
  if (!entity)
Packit 8a864e
    return;
Packit 8a864e
  os() << '#'
Packit 8a864e
       << char(entity->dataType() == Entity::cdata ? 'C' : 'S')
Packit 8a864e
       << "DATA-INTERNAL" << nl;
Packit 8a864e
  const StringC &str = entity->string();
Packit 8a864e
  lines(markupLine, str.data(), str.size());
Packit 8a864e
  flushLine(markupLine);
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::endProlog(EndPrologEvent *event)
Packit 8a864e
{
Packit 8a864e
  if (!event->lpdPointer().isNull()) {
Packit 8a864e
    linkProcess_.init(event->lpdPointer());
Packit 8a864e
    haveLinkProcess_ = 1;
Packit 8a864e
  }
Packit 8a864e
  if (event->simpleLinkNames().size() > 0)
Packit 8a864e
    endPrologEvent_ = event;
Packit 8a864e
  else
Packit 8a864e
    delete event;
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::uselink(UselinkEvent *event)
Packit 8a864e
{
Packit 8a864e
  linkProcess_.uselink(event->linkSet(),
Packit 8a864e
		       event->restore(),
Packit 8a864e
		       event->lpd().pointer());
Packit 8a864e
  if (haveLinkProcess_ && linkProcess_.nImpliedLinkRules() > 0) {
Packit 8a864e
    flushLine(dataLine);
Packit 8a864e
    os() << "#LINK-SET-INFO" << nl;
Packit 8a864e
    impliedSourceLinkRules();
Packit 8a864e
    os() << "#END-LINK-SET-INFO" << nl;
Packit 8a864e
  }
Packit 8a864e
  delete event;
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::initMessage(Message &msg)
Packit 8a864e
{
Packit 8a864e
  mgr_->initMessage(msg);
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastEventHandler::dispatchMessage(const Message &msg)
Packit 8a864e
{
Packit 8a864e
  if (msg.isError())
Packit 8a864e
    piErrorCount_++;
Packit 8a864e
  if (!cancelled()) {
Packit 8a864e
    noteMessage(msg);
Packit 8a864e
    mgr_->dispatchMessage(msg);
Packit 8a864e
  }
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
RastLinkProcess::RastLinkProcess()
Packit 8a864e
: rast_(0)
Packit 8a864e
{
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastLinkProcess::setHandler(RastEventHandler *rast)
Packit 8a864e
{
Packit 8a864e
  rast_ = rast;
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
// Always return 1. 0 means not ready.
Packit 8a864e
Packit 8a864e
Boolean RastLinkProcess::selectLinkRule(const Vector<const AttributeList *> &linkAttributes,
Packit 8a864e
					const Location &location,
Packit 8a864e
					size_t &selected)
Packit 8a864e
{
Packit 8a864e
  if (!rast_->linkRuleQueue_.empty()) {
Packit 8a864e
    LinkRulePi *p = rast_->linkRuleQueue_.get();
Packit 8a864e
    if (!selectLinkRulePi(p->pi, p->loc, linkAttributes, selected))
Packit 8a864e
      selected = 0;
Packit 8a864e
  }
Packit 8a864e
  else {
Packit 8a864e
    if (linkAttributes.size() > 0) {
Packit 8a864e
      rast_->setNextLocation(location);
Packit 8a864e
      rast_->Messenger::message(RastEventHandlerMessages::multipleLinkRules);
Packit 8a864e
    }
Packit 8a864e
    selected = 0;
Packit 8a864e
  }
Packit 8a864e
  return 1;
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
// Return zero for failure (RAST-PI-ERROR).
Packit 8a864e
Packit 8a864e
Boolean RastLinkProcess::selectLinkRulePi(const StringC &value,
Packit 8a864e
					  const Location &loc,
Packit 8a864e
					  const Vector<const AttributeList *> &linkAttributes,
Packit 8a864e
					  size_t &selected)
Packit 8a864e
{
Packit 8a864e
  Boolean haveSelection = 0;
Packit 8a864e
  size_t i;
Packit 8a864e
  for (i = 0; i < linkAttributes.size(); i++) {
Packit 8a864e
    const AttributeList &a = *linkAttributes[i];
Packit 8a864e
    Boolean matchValue = 0;
Packit 8a864e
    for (size_t j = 0; j < a.size(); j++) {
Packit 8a864e
      const Text *textp;
Packit 8a864e
      const StringC *strp;
Packit 8a864e
      switch (a.value(j)->info(textp, strp)) {
Packit 8a864e
      case AttributeValue::cdata:
Packit 8a864e
	// What if it contains SDATA entities?
Packit 8a864e
	if (textp->string() == value)
Packit 8a864e
	  matchValue = 1;
Packit 8a864e
	break;
Packit 8a864e
      case AttributeValue::tokenized:
Packit 8a864e
	if (*strp == value)
Packit 8a864e
	  matchValue = 1;
Packit 8a864e
	break;
Packit 8a864e
      default:
Packit 8a864e
	break;
Packit 8a864e
      }
Packit 8a864e
      if (matchValue)
Packit 8a864e
	break;
Packit 8a864e
    }
Packit 8a864e
    if (matchValue) {
Packit 8a864e
      if (haveSelection) {
Packit 8a864e
	rast_->setNextLocation(loc);
Packit 8a864e
	rast_->Messenger::message(RastEventHandlerMessages::multipleLinkRuleMatch);
Packit 8a864e
	return 0;
Packit 8a864e
      }
Packit 8a864e
      haveSelection = 1;
Packit 8a864e
      selected = i;
Packit 8a864e
    }
Packit 8a864e
  }
Packit 8a864e
  if (!haveSelection) {
Packit 8a864e
    rast_->setNextLocation(loc);
Packit 8a864e
    rast_->Messenger::message(RastEventHandlerMessages::noLinkRuleMatch);
Packit 8a864e
    return 0;
Packit 8a864e
  }
Packit 8a864e
  return 1;
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
void RastLinkProcess::swap(RastLinkProcess &to)
Packit 8a864e
{
Packit 8a864e
  LinkProcess::swap(to);
Packit 8a864e
  RastEventHandler *tem = to.rast_;
Packit 8a864e
  to.rast_ = rast_;
Packit 8a864e
  rast_ = tem;
Packit 8a864e
}
Packit 8a864e
Packit 8a864e
#ifdef SP_NAMESPACE
Packit 8a864e
}
Packit 8a864e
#endif