Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / nsgmls / GenericEventHandler.C
1 /* $XConsortium: GenericEventHandler.C /main/1 1996/07/29 16:52:15 cde-hp $ */
2 // Copyright (c) 1996 James Clark
3 // See the file COPYING for copying permission.
4
5 #ifdef __GNUG__
6 #pragma implementation
7 #endif
8
9 #include "splib.h"
10 #include "GenericEventHandler.h"
11 #include "macros.h"
12 #include "ExtendEntityManager.h"
13
14 #ifdef SP_NAMESPACE
15 namespace SP_NAMESPACE {
16 #endif
17
18 class SpOpenEntity : public SGMLApplication::OpenEntity {
19 public:
20   SpOpenEntity(const ConstPtr<Origin> &origin);
21   SGMLApplication::Location location(SGMLApplication::Position) const;
22 private:
23   ConstPtr<Origin> origin_;
24 };
25
26 inline
27 void *operator new(size_t n, GenericEventHandler *handler)
28 {
29   return handler->allocate(n);
30 }
31
32 inline
33 void GenericEventHandler::freeAll()
34 {
35   if (allocBlocks_)
36     freeAll1();
37 }
38
39 inline
40 void GenericEventHandler::clearNotation(SGMLApplication::Notation &to)
41 {
42   clearString(to.name);
43 }
44
45 inline
46 void GenericEventHandler::setLocation(SGMLApplication::Position &pos,
47                                   const Location &loc)
48 {
49   if (lastOrigin_ != loc.origin())
50     setLocation1(pos, loc);
51   else
52     pos = loc.index();
53 }
54
55 GenericEventHandler::GenericEventHandler(SGMLApplication &app,
56                                          bool generalEntities)
57 : app_(&app), generalEntities_(generalEntities),
58   freeBlocks_(0), allocBlocks_(0), firstBlockSpare_(0), firstBlockUsed_(0)
59 {
60 }
61
62 GenericEventHandler::~GenericEventHandler()
63 {
64   freeAll();
65   while (freeBlocks_) {
66     Block *tem = freeBlocks_;
67     freeBlocks_ = freeBlocks_->next;
68     delete [] tem->mem;
69     delete tem;
70   }
71 }
72
73 void GenericEventHandler::freeAll1()
74 {
75   Block **p;
76   for (p = &allocBlocks_; *p; p = &(*p)->next)
77     ;
78   *p = freeBlocks_;
79   freeBlocks_ = allocBlocks_;
80   allocBlocks_ = 0;
81   if (freeBlocks_)
82     firstBlockSpare_ = freeBlocks_->size;
83   else
84     firstBlockSpare_ = 0;
85   firstBlockUsed_ = 0;
86 }
87
88 void *GenericEventHandler::allocate(size_t n)
89 {
90   if (n == 0)
91     return 0;
92   // round up to avoid alignment problems
93   n = (n + sizeof(char *) - 1) & ~(sizeof(char *) - 1);
94   enum { BIG = 1024 };
95   if (n > firstBlockSpare_) {
96     if (freeBlocks_ && firstBlockUsed_) {
97       Block *tem = freeBlocks_;
98       freeBlocks_ = freeBlocks_->next;
99       tem->next = allocBlocks_;
100       allocBlocks_ = tem;
101     }
102     if (!freeBlocks_ || freeBlocks_->size < n) {
103       Block *tem = new Block;
104       tem->size = n < BIG ? int(BIG) : n;
105       tem->mem = new char[tem->size];
106       tem->next = freeBlocks_;
107       freeBlocks_ = tem;
108     }
109     firstBlockUsed_ = 0;
110     firstBlockSpare_ = freeBlocks_->size;
111   }
112   char *tem = freeBlocks_->mem + firstBlockUsed_;
113   firstBlockUsed_ += n;
114   firstBlockSpare_ -= n;
115   return tem;
116 }
117
118 void GenericEventHandler::startElement(StartElementEvent *event)
119 {
120   SGMLApplication::StartElementEvent appEvent;
121   setString(appEvent.gi, event->name());
122   const ElementDefinition *def = event->elementType()->definition();
123   switch (def->declaredContent()) {
124   case ElementDefinition::modelGroup:
125     appEvent.contentType
126       = (def->compiledModelGroup()->containsPcdata()
127          ? SGMLApplication::StartElementEvent::mixed
128          : SGMLApplication::StartElementEvent::element);
129     break;
130   case ElementDefinition::any:
131     appEvent.contentType = SGMLApplication::StartElementEvent::mixed;
132     break;
133   case ElementDefinition::cdata:
134     appEvent.contentType = SGMLApplication::StartElementEvent::cdata;
135     break;
136   case ElementDefinition::rcdata:
137     appEvent.contentType = SGMLApplication::StartElementEvent::rcdata;
138     break;
139   case ElementDefinition::empty:
140     appEvent.contentType = SGMLApplication::StartElementEvent::empty;
141     break;
142   }
143   appEvent.included = event->included();
144   appEvent.nAttributes = event->attributes().size();
145   if (appEvent.nAttributes != 0) {
146     if (event->attributes().conref())
147       appEvent.contentType = SGMLApplication::StartElementEvent::empty;
148     setAttributes(appEvent.attributes, event->attributes());
149   }
150   setLocation(appEvent.pos, event->location());
151   app_->startElement(appEvent);
152   freeAll();
153   delete event;
154 }
155
156 void GenericEventHandler::endElement(EndElementEvent *event)
157 {
158   SGMLApplication::EndElementEvent appEvent;
159   setString(appEvent.gi, event->name());
160   setLocation(appEvent.pos, event->location());
161   app_->endElement(appEvent);
162   delete event;
163 }
164
165 void GenericEventHandler::data(DataEvent *event)
166 {
167   SGMLApplication::DataEvent appEvent;
168   appEvent.data.ptr = event->data();
169   appEvent.data.len = event->dataLength();
170   setLocation(appEvent.pos, event->location());
171   app_->data(appEvent);
172   delete event;
173 }
174
175 void GenericEventHandler::pi(PiEvent *event)
176 {
177   SGMLApplication::PiEvent appEvent;
178   appEvent.data.ptr = event->data();
179   appEvent.data.len = event->dataLength();
180   const Entity *entity = event->entity();
181   if (entity)
182     setString(appEvent.entityName, entity->name());
183   else
184     appEvent.entityName.len = 0;
185   setLocation(appEvent.pos, event->location());
186   app_->pi(appEvent);
187   delete event;
188 }
189
190 void GenericEventHandler::sdataEntity(SdataEntityEvent *event)
191 {
192   SGMLApplication::SdataEvent appEvent;
193   appEvent.text.ptr = event->data();
194   appEvent.text.len = event->dataLength();
195   setString(appEvent.entityName, event->entity()->name());
196   // Don't want location of chars in entity.
197   setLocation(appEvent.pos, event->location().origin()->parent());
198   app_->sdata(appEvent);
199   delete event;
200 }
201
202 void GenericEventHandler::externalDataEntity(ExternalDataEntityEvent *event)
203 {
204   SGMLApplication::ExternalDataEntityRefEvent appEvent;
205   setEntity(appEvent.entity, *event->entity());
206   setLocation(appEvent.pos, event->location());
207   app_->externalDataEntityRef(appEvent);
208   freeAll();
209   delete event;
210 }
211
212 void GenericEventHandler::subdocEntity(SubdocEntityEvent *event)
213 {
214   SGMLApplication::SubdocEntityRefEvent appEvent;
215   setEntity(appEvent.entity, *event->entity());
216   setLocation(appEvent.pos, event->location());
217   app_->subdocEntityRef(appEvent);
218   freeAll();
219   delete event;
220 }
221
222 void GenericEventHandler::startDtd(StartDtdEvent *event)
223 {
224   SGMLApplication::StartDtdEvent appEvent;
225   setString(appEvent.name, event->name());
226   const Entity *entity = event->entity().pointer();
227   if (entity) {
228     appEvent.haveExternalId = 1;
229     setExternalId(appEvent.externalId,
230                   entity->asExternalEntity()->externalId());
231   }
232   else
233     appEvent.haveExternalId = 0;
234   setLocation(appEvent.pos, event->location());
235   app_->startDtd(appEvent);
236   freeAll();
237   delete event;
238 }
239
240 void GenericEventHandler::endDtd(EndDtdEvent *event)
241 {
242   SGMLApplication::EndDtdEvent appEvent;
243   setString(appEvent.name, event->dtd().name());
244   setLocation(appEvent.pos, event->location());
245   app_->endDtd(appEvent);
246   delete event;
247 }
248
249 void GenericEventHandler::endProlog(EndPrologEvent *event)
250 {
251   if (generalEntities_) {
252     SGMLApplication::GeneralEntityEvent entityEvent;
253     const Dtd &dtd = event->dtd();
254     Dtd::ConstEntityIter iter(dtd.generalEntityIter());
255     for (;;) {
256       const Entity *entity = iter.nextTemp();
257       if (!entity)
258         break;
259       setEntity(entityEvent.entity, *entity);
260       app_->generalEntity(entityEvent);
261     }
262     freeAll();
263   }
264   SGMLApplication::EndPrologEvent appEvent;
265   setLocation(appEvent.pos, event->location());
266   app_->endProlog(appEvent);
267   delete event;
268 }
269
270 void GenericEventHandler::entityDefaulted(EntityDefaultedEvent *event)
271 {
272   if (generalEntities_) {
273     SGMLApplication::GeneralEntityEvent appEvent;
274     setEntity(appEvent.entity, event->entity());
275     app_->generalEntity(appEvent);
276   }
277   delete event;
278 }
279
280 void GenericEventHandler::appinfo(AppinfoEvent *event)
281 {
282   SGMLApplication::AppinfoEvent appEvent;
283   const StringC *str;
284   if (event->literal(str)) {
285     setString(appEvent.string, *str);
286     appEvent.none = 0;
287   }
288   else
289     appEvent.none = 1;
290   setLocation(appEvent.pos, event->location());
291   app_->appinfo(appEvent);
292   delete event;
293 }
294
295 void GenericEventHandler::commentDecl(CommentDeclEvent *event)
296 {
297   SGMLApplication::CommentDeclEvent appEvent;
298   appEvent.nComments = 0;
299   {
300     for (MarkupIter iter(event->markup()); iter.valid(); iter.advance())
301       if (iter.type() == Markup::comment)
302         appEvent.nComments++;
303   }
304   SGMLApplication::CharString *comments
305     = (SGMLApplication::CharString *)allocate(appEvent.nComments * 2
306                                               * sizeof(SGMLApplication::CharString));
307   appEvent.comments = comments;
308   appEvent.seps = appEvent.comments + appEvent.nComments;
309   size_t i = 0;
310   for (MarkupIter iter(event->markup()); iter.valid(); iter.advance())
311     switch (iter.type()) {
312     case Markup::comment:
313       comments[i].ptr = iter.charsPointer();
314       comments[i].len = iter.charsLength();
315       clearString(comments[appEvent.nComments + i]);
316       i++;
317       break;
318     case Markup::s:
319       comments[appEvent.nComments + i - 1].ptr = iter.charsPointer();
320       comments[appEvent.nComments + i - 1].len = iter.charsLength();
321       break;
322     default:
323       break;
324     }
325   setLocation(appEvent.pos, event->location());
326   app_->commentDecl(appEvent);
327   freeAll();
328   delete event;
329 }
330
331 void GenericEventHandler::markedSectionStart(MarkedSectionStartEvent *event)
332 {
333   SGMLApplication::MarkedSectionStartEvent appEvent;
334   unsigned depth = 0;
335   appEvent.nParams = 0;
336   {
337     for (MarkupIter iter(event->markup()); iter.valid(); iter.advance())
338       switch (iter.type()) {
339       case Markup::reservedName:
340         if (!depth)
341           appEvent.nParams++;
342         break;
343       case Markup::entityStart:
344         if (!depth)
345           appEvent.nParams++;
346         depth++;
347         break;
348       case Markup::entityEnd:
349         depth--;
350         break;
351       default:
352         break;
353       }
354   }
355   SGMLApplication::MarkedSectionStartEvent::Param *params
356     = (SGMLApplication::MarkedSectionStartEvent::Param *)
357       allocate(appEvent.nParams * sizeof(appEvent.params[0]));
358   appEvent.params = params;
359   size_t i = 0;
360   for (MarkupIter iter(event->markup()); iter.valid(); iter.advance())
361     switch (iter.type()) {
362     case Markup::reservedName:
363       if (!depth) {
364         switch (iter.reservedName()) {
365         case Syntax::rTEMP:
366           params[i].type
367             = SGMLApplication::MarkedSectionStartEvent::Param::temp;
368           break;
369         case Syntax::rINCLUDE:
370           params[i].type
371             = SGMLApplication::MarkedSectionStartEvent::Param::include;
372           break;
373         case Syntax::rRCDATA:
374           params[i].type
375             = SGMLApplication::MarkedSectionStartEvent::Param::rcdata;
376           break;
377         case Syntax::rCDATA:
378           params[i].type
379             = SGMLApplication::MarkedSectionStartEvent::Param::cdata;
380           break;
381         case Syntax::rIGNORE:
382           params[i].type
383             = SGMLApplication::MarkedSectionStartEvent::Param::ignore;
384           break;
385         default:
386           CANNOT_HAPPEN();
387         }
388         clearString(params[i].entityName);
389         i++;
390       }
391       break;
392     case Markup::entityStart:
393       if (!depth) {
394         params[i].type
395           = SGMLApplication::MarkedSectionStartEvent::Param::entityRef;
396         setString(params[i].entityName,
397                   iter.entityOrigin()->entity()->name());
398         i++;
399       }
400       depth++;
401       break;
402     case Markup::entityEnd:
403       depth--;
404       break;
405     default:
406       break;
407     }
408   switch (event->status()) {
409   case MarkedSectionEvent::include:
410     appEvent.status = SGMLApplication::MarkedSectionStartEvent::include;
411     break;
412   case MarkedSectionEvent::rcdata:
413     appEvent.status = SGMLApplication::MarkedSectionStartEvent::rcdata;
414     break;
415   case MarkedSectionEvent::cdata:
416     appEvent.status = SGMLApplication::MarkedSectionStartEvent::cdata;
417     break;
418   case MarkedSectionEvent::ignore:
419     appEvent.status = SGMLApplication::MarkedSectionStartEvent::ignore;
420     break;
421   }
422   setLocation(appEvent.pos, event->location());
423   app_->markedSectionStart(appEvent);
424   freeAll();
425   delete event;
426 }
427
428 void GenericEventHandler::ignoredChars(IgnoredCharsEvent *event)
429 {
430   SGMLApplication::IgnoredCharsEvent appEvent;
431   appEvent.data.ptr = event->data();
432   appEvent.data.len = event->dataLength();
433   setLocation(appEvent.pos, event->location());
434   app_->ignoredChars(appEvent);
435   delete event;
436 }
437
438 void GenericEventHandler::markedSectionEnd(MarkedSectionEndEvent *event)
439 {
440   SGMLApplication::MarkedSectionEndEvent appEvent;
441   switch (event->status()) {
442   case MarkedSectionEvent::include:
443     appEvent.status = SGMLApplication::MarkedSectionEndEvent::include;
444     break;
445   case MarkedSectionEvent::rcdata:
446     appEvent.status = SGMLApplication::MarkedSectionEndEvent::rcdata;
447     break;
448   case MarkedSectionEvent::cdata:
449     appEvent.status = SGMLApplication::MarkedSectionEndEvent::cdata;
450     break;
451   case MarkedSectionEvent::ignore:
452     appEvent.status = SGMLApplication::MarkedSectionEndEvent::ignore;
453     break;
454   }
455   setLocation(appEvent.pos, event->location());
456   app_->markedSectionEnd(appEvent);
457   delete event;
458 }
459
460 void GenericEventHandler::message(MessageEvent *event)
461 {
462   SGMLApplication::ErrorEvent appEvent;
463   switch (event->message().type->severity()) {
464   case MessageType::quantityError:
465     appEvent.type = SGMLApplication::ErrorEvent::quantity;
466     break;
467   case MessageType::idrefError:
468     appEvent.type = SGMLApplication::ErrorEvent::idref;
469     break;
470   case MessageType::error:
471     appEvent.type = SGMLApplication::ErrorEvent::otherError;
472     break;
473   case MessageType::info:
474     appEvent.type = SGMLApplication::ErrorEvent::info;
475     break;
476   case MessageType::warning:
477     appEvent.type = SGMLApplication::ErrorEvent::warning;
478     break;
479   }
480   setLocation(appEvent.pos, event->message().loc);
481   StringC str;
482   reportMessage(event->message(), str);
483   setString(appEvent.message, str);
484   app_->error(appEvent);
485   ErrorCountEventHandler::message(event);
486 }
487
488 void GenericEventHandler::setLocation1(SGMLApplication::Position &pos,
489                                    const Location &loc)
490 {
491   const Location *locp = &loc;
492   for (;;) {
493     if (locp->origin().isNull()) {
494       lastOrigin_.clear();
495       openEntityPtr_ = (SpOpenEntity *)0;
496       return;
497     }
498     const InputSourceOrigin *origin = locp->origin()->asInputSourceOrigin();
499     if (origin && origin->externalInfo())
500       break;
501     locp = &locp->origin()->parent();
502   }
503   lastOrigin_ = locp->origin();
504   pos = locp->index();
505   openEntityPtr_ = new SpOpenEntity(locp->origin());
506   app_->openEntityChange(openEntityPtr_);
507 }
508
509 void 
510 GenericEventHandler::setAttributes(const SGMLApplication::Attribute *&attributes,
511                                const AttributeList &attributeList)
512 {
513   size_t nAttributes = attributeList.size();
514   SGMLApplication::Attribute *to
515     = (SGMLApplication::Attribute *)allocate(nAttributes * sizeof(*to));
516   attributes = to;
517   for (size_t i = 0; i < nAttributes; i++) {
518     SGMLApplication::Attribute *p = to + i;
519     setString(p->name, attributeList.name(i));
520     const AttributeValue *value = attributeList.value(i);
521     if (!value)
522       p->type = SGMLApplication::Attribute::invalid;
523     else {
524       const Text *text;
525       const StringC *string;
526       switch (value->info(text, string)) {
527       case AttributeValue::implied:
528         p->type = SGMLApplication::Attribute::implied;
529         break;
530       case AttributeValue::tokenized:
531         {
532           if (attributeList.specified(i))
533             p->defaulted = SGMLApplication::Attribute::specified;
534           else if (attributeList.current(i))
535             p->defaulted = SGMLApplication::Attribute::current;
536           else
537             p->defaulted = SGMLApplication::Attribute::definition;
538           p->type = SGMLApplication::Attribute::tokenized;
539           p->nEntities = 0;
540           p->notation.name.len = 0;
541           p->isId = attributeList.id(i);
542           p->isGroup = (attributeList.getAllowedTokens(i) != 0);
543           setString(p->tokens, *string);
544           const AttributeSemantics *semantics = attributeList.semantics(i);
545           if (semantics) {
546             ConstPtr<Notation> notation = semantics->notation();
547             if (!notation.isNull())
548               setNotation(p->notation, *notation);
549             else {
550               size_t nEntities = semantics->nEntities();
551               if (nEntities) {
552                 SGMLApplication::Entity *v
553                   = (SGMLApplication::Entity *)allocate(nEntities * sizeof(*v));
554                 p->entities = v;
555                 p->nEntities = nEntities;
556                 for (size_t i = 0; i < nEntities; i++)
557                   setEntity(v[i], *semantics->entity(i));
558               }
559             }
560           }
561         }
562         break;
563       case AttributeValue::cdata:
564         {
565           p->type = SGMLApplication::Attribute::cdata;
566           if (attributeList.specified(i))
567             p->defaulted = SGMLApplication::Attribute::specified;
568           else if (attributeList.current(i))
569             p->defaulted = SGMLApplication::Attribute::current;
570           else
571             p->defaulted = SGMLApplication::Attribute::definition;
572           TextItem::Type type;
573           const Char *s;
574           size_t length;
575           const Location *loc;
576           size_t nChunks = 0;
577           {
578             TextIter iter(*text);
579             while (iter.next(type, s, length, loc))
580               switch (type) {
581               case TextItem::data:
582               case TextItem::sdata:
583               case TextItem::cdata:
584                 nChunks++;
585                 break;
586               default:
587                 break;
588               }
589           }
590           p->cdataChunks
591             = (SGMLApplication::Attribute::CdataChunk *)allocate(nChunks * sizeof(SGMLApplication::Attribute::CdataChunk));
592           p->nCdataChunks = nChunks;
593
594           {
595             size_t i = 0;
596             for (TextIter iter(*text);
597                  iter.next(type, s, length, loc);
598                  i++) {
599               switch (type) {
600               case TextItem::data:
601               case TextItem::sdata:
602               case TextItem::cdata:
603                 {
604                   SGMLApplication::Attribute::CdataChunk *chunk
605                     = (SGMLApplication::Attribute::CdataChunk *)(p->cdataChunks + i);
606                   if (type != TextItem::sdata)
607                     chunk->isSdata = 0;
608                   else {
609                     chunk->isSdata = 1;
610                     setString(chunk->entityName,
611                               *loc->origin()->asInputSourceOrigin()->entityName());
612                   }
613                   chunk->data.ptr = s;
614                   chunk->data.len = length;
615                 }
616                 break;
617               default:
618                 break;
619               }
620             }
621           }
622         }
623         break;
624       }
625     }
626   }
627 }
628
629
630 void GenericEventHandler::setEntity(SGMLApplication::Entity &to,
631                                 const Entity &from)
632 {
633   setString(to.name, from.name());
634   switch (from.declType()) {
635   case Entity::generalEntity:
636     to.declType = SGMLApplication::Entity::general;
637     break;
638   case Entity::parameterEntity:
639     to.declType = SGMLApplication::Entity::parameter;
640     break;
641   case Entity::doctype:
642     to.declType = SGMLApplication::Entity::doctype;
643     break;
644   case Entity::linktype:
645     to.declType = SGMLApplication::Entity::linktype;
646     break;
647   default:
648     CANNOT_HAPPEN();
649   }
650   switch (from.dataType()) {
651   case Entity::sgmlText:
652     to.dataType = SGMLApplication::Entity::sgml;
653     break;
654   case Entity::cdata:
655     to.dataType = SGMLApplication::Entity::cdata;
656     break;
657   case Entity::sdata:
658     to.dataType = SGMLApplication::Entity::sdata;
659     break;
660   case Entity::ndata:
661     to.dataType = SGMLApplication::Entity::ndata;
662     break;
663   case Entity::subdoc:
664     to.dataType = SGMLApplication::Entity::subdoc;
665     break;
666   case Entity::pi:
667     to.dataType = SGMLApplication::Entity::pi;
668     break;
669   }
670   const InternalEntity *internal = from.asInternalEntity();
671   if (internal) {
672     to.isInternal = 1;
673     setString(to.text, internal->string());
674   }
675   else {
676     const ExternalEntity *external = from.asExternalEntity();
677     to.isInternal = 0;
678     setExternalId(to.externalId, external->externalId());
679     const ExternalDataEntity *externalData = from.asExternalDataEntity();
680     if (externalData) {
681       setNotation(to.notation, *externalData->notation());
682       to.nAttributes = externalData->attributes().size();
683       if (to.nAttributes)
684         setAttributes(to.attributes, externalData->attributes());
685     }
686     else {
687       to.notation.name.len = 0;
688       to.nAttributes = 0;
689     }
690   }
691 }
692
693
694 void GenericEventHandler::setNotation(SGMLApplication::Notation &to,
695                                       const Notation &from)
696 {
697   setString(to.name, from.name());
698   setExternalId(to.externalId, from.externalId());
699 }
700
701 void GenericEventHandler::setExternalId(SGMLApplication::ExternalId &to,
702                                         const ExternalId &from)
703 {
704   const StringC *str;
705   str = from.systemIdString();
706   if (str) {
707     to.haveSystemId = 1;
708     setString(to.systemId, *str);
709   }
710   else
711     to.haveSystemId = 0;
712   str = from.publicIdString();
713   if (str) {
714     to.havePublicId = 1;
715     setString(to.publicId, *str);
716   }
717   else
718     to.havePublicId = 0;
719   str = &from.effectiveSystemId();
720   if (str->size()) {
721     to.haveGeneratedSystemId = 1;
722     setString(to.generatedSystemId, *str);
723   }
724   else
725     to.haveGeneratedSystemId = 0;
726 }
727
728 MsgGenericEventHandler::MsgGenericEventHandler(SGMLApplication &app, 
729                                                bool generalEntities,
730                                                MessageReporter &reporter,
731                                                const bool *messagesInhibitedPtr)
732 : GenericEventHandler(app, generalEntities),
733   reporter_(&reporter),
734   messagesInhibitedPtr_(messagesInhibitedPtr)
735 {
736 }
737
738 void MsgGenericEventHandler::reportMessage(const Message &msg, StringC &str)
739 {
740   WrapReporter wrap(reporter_);
741   reporter_->dispatchMessage(msg);
742   wrap.strStream.extractString(str);
743   if (!*messagesInhibitedPtr_)
744     *wrap.origStream << str;
745 }
746
747 SpOpenEntity::SpOpenEntity(const ConstPtr<Origin> &origin)
748 : origin_(origin)
749 {
750 }
751
752 SGMLApplication::Location
753 SpOpenEntity::location(SGMLApplication::Position pos) const
754 {
755   SGMLApplication::Location loc;
756   const Origin *origin = origin_.pointer();
757   const InputSourceOrigin *inputSourceOrigin;
758   const ExternalInfo *externalInfo;
759   Index index = Index(pos);
760   for (;;) {
761     if (!origin)
762       return loc;
763     inputSourceOrigin = origin->asInputSourceOrigin();
764     if (inputSourceOrigin) {
765       externalInfo = inputSourceOrigin->externalInfo();
766       if (externalInfo)
767         break;
768     }
769     const Location &loc = origin->parent();
770     index = loc.index();
771     origin = loc.origin().pointer();
772   }
773   const StringC *entityName = inputSourceOrigin->entityName();
774   if (entityName)
775     GenericEventHandler::setString(loc.entityName, *entityName);
776   Offset off = inputSourceOrigin->startOffset(index);
777   loc.entityOffset = off;
778   StorageObjectLocation soLoc;
779   if (!ExtendEntityManager::externalize(externalInfo, off, soLoc))
780     return loc;
781   loc.lineNumber = soLoc.lineNumber;
782   GenericEventHandler::setString(loc.filename, soLoc.storageObjectSpec->id);
783   loc.columnNumber = soLoc.columnNumber;
784   loc.byteOffset = soLoc.byteIndex;
785   loc.other = soLoc.storageObjectSpec;
786   return loc;
787 }
788
789 #ifdef SP_NAMESPACE
790 }
791 #endif