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