📄 rasteventhandler.cxx
字号:
// Copyright (c) 1994,1995 James Clark// See the file COPYING for copying permission.#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_NAMESPACEnamespace SP_NAMESPACE {#endifconst 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 0const #endifRastPrintable 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;}// inlinevoid 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;}inlineBoolean 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?inlineBoolean 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -