1 // Copyright (c) 1994 James Clark
2 // See the file COPYING for copying permission.
3 #pragma ident "%Z%%M% %I% %E% SMI"
4
5 #ifdef __GNUG__
6 #pragma implementation
7 #endif
8 #include "splib.h"
9 #include "OutputState.h"
10 #include "Event.h"
11 #include "Allocator.h"
12
13 #ifdef SP_NAMESPACE
14 namespace SP_NAMESPACE {
15 #endif
16
OutputState()17 OutputState::OutputState()
18 {
19 init();
20 }
21
init()22 void OutputState::init()
23 {
24 nextSerial_ = 0;
25 stack_.clear();
26 stack_.insert(new OutputStateLevel);
27 }
28
OutputStateLevel()29 OutputStateLevel::OutputStateLevel()
30 : state(OutputState::afterStartTag)
31 {
32 }
33
handleRe(EventHandler & handler,Allocator & alloc,const EventsWanted & eventsWanted,Char re,const Location & location)34 void OutputState::handleRe(EventHandler &handler, Allocator &alloc,
35 const EventsWanted &eventsWanted, Char re,
36 const Location &location)
37 {
38 re_ = re;
39 if (eventsWanted.wantInstanceMarkup())
40 handler.reOrigin(new (alloc) ReOriginEvent(re_, location, nextSerial_));
41 switch (top().state) {
42 case afterStartTag:
43 // it's the first RE in the element
44 if (eventsWanted.wantInstanceMarkup())
45 handler.ignoredRe(new (alloc) IgnoredReEvent(re_, location, nextSerial_++));
46 top().state = afterRsOrRe;
47 break;
48 case afterRsOrRe:
49 case afterData:
50 top().state = pendingAfterRsOrRe;
51 top().reLocation = location;
52 top().reSerial = nextSerial_++;
53 break;
54 case pendingAfterRsOrRe:
55 // We now know that the pending RE won't be ignored as the last RE.
56 handler.data(new (alloc) ReEvent(&re_, top().reLocation, top().reSerial));
57 top().state = pendingAfterRsOrRe;
58 top().reLocation = location;
59 top().reSerial = nextSerial_++;
60 break;
61 case pendingAfterMarkup:
62 // We've had only markup since the last RS or RE, so this
63 // RE is ignored. Note that it's this RE that's ignored, not
64 // the pending one.
65 if (eventsWanted.wantInstanceMarkup())
66 handler.ignoredRe(new (alloc) IgnoredReEvent(re_, location, nextSerial_++));
67 top().state = pendingAfterRsOrRe;
68 break;
69 }
70 }
71
noteRs(EventHandler &,Allocator &,const EventsWanted &)72 void OutputState::noteRs(EventHandler &, Allocator &, const EventsWanted &)
73 {
74 if (top().hasPendingRe())
75 top().state = pendingAfterRsOrRe;
76 else
77 top().state = afterRsOrRe;
78 }
79
noteMarkup(EventHandler &,Allocator &,const EventsWanted &)80 void OutputState::noteMarkup(EventHandler &, Allocator &, const EventsWanted &)
81 {
82 switch (top().state) {
83 case afterRsOrRe:
84 top().state = afterStartTag;
85 break;
86 case pendingAfterRsOrRe:
87 top().state = pendingAfterMarkup;
88 break;
89 default:
90 break; // avoid warning
91 }
92 }
93
noteData(EventHandler & handler,Allocator & alloc,const EventsWanted &)94 void OutputState::noteData(EventHandler &handler, Allocator &alloc,
95 const EventsWanted &)
96 {
97 if (top().hasPendingRe())
98 handler.data(new (alloc) ReEvent(&re_, top().reLocation, top().reSerial));
99 top().state = afterData;
100 }
101
noteStartElement(Boolean included,EventHandler & handler,Allocator & alloc,const EventsWanted &)102 void OutputState::noteStartElement(Boolean included,
103 EventHandler &handler, Allocator &alloc,
104 const EventsWanted &)
105 {
106 if (included)
107 stack_.insert(new OutputStateLevel);
108 else {
109 if (top().hasPendingRe())
110 handler.data(new (alloc) ReEvent(&re_, top().reLocation, top().reSerial));
111 top().state = afterStartTag;
112 }
113 }
114
noteEndElement(Boolean included,EventHandler & handler,Allocator & alloc,const EventsWanted & eventsWanted)115 void OutputState::noteEndElement(Boolean included, EventHandler &handler,
116 Allocator &alloc,
117 const EventsWanted &eventsWanted)
118 {
119 if (eventsWanted.wantInstanceMarkup() && top().hasPendingRe())
120 handler.ignoredRe(new (alloc) IgnoredReEvent(re_, top().reLocation,
121 top().reSerial));
122 if (included) {
123 delete stack_.get();
124 noteMarkup(handler, alloc, eventsWanted);
125 }
126 else
127 top().state = afterData;
128 }
129
130 #ifdef SP_NAMESPACE
131 }
132 #endif
133