Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / nsgmls / ContentState.C
1 /* $XConsortium: ContentState.C /main/1 1996/07/29 16:48:21 cde-hp $ */
2 // Copyright (c) 1994, 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 "ContentState.h"
11 #include "IListIter.h"
12 #include "NCVector.h"
13 #include "macros.h"
14
15 #ifdef SP_NAMESPACE
16 namespace SP_NAMESPACE {
17 #endif
18
19 const ShortReferenceMap ContentState::theEmptyMap;
20
21 #ifdef __GNUG__
22 typedef IListIter<OpenElement> Dummy_IListIter_OpenElement;
23 #endif
24
25 ContentState::ContentState()
26 : documentElementContainer_(StringC(), size_t(-1))
27 {
28 }
29
30 void ContentState::startContent(const Dtd &dtd)
31 {
32   NCVector<Owner<ContentToken> > tokens(1);
33   tokens[0] = new ElementToken(dtd.documentElementType(),
34                                ContentToken::none);
35   Owner<ModelGroup> model(new SeqModelGroup(tokens, ContentToken::none));
36   Owner<CompiledModelGroup> compiledModel(new CompiledModelGroup(model));
37   Vector<ContentModelAmbiguity> ambiguities;
38   Boolean pcdataUnreachable;
39   compiledModel->compile(dtd.nElementTypeIndex(), ambiguities,
40                          pcdataUnreachable);
41   ASSERT(ambiguities.size() == 0);
42   ConstPtr<ElementDefinition> def
43     = new ElementDefinition(Location(),
44                             0,
45                             0,
46                             ElementDefinition::modelGroup,
47                             compiledModel);
48   documentElementContainer_.setElementDefinition(def, 0);
49   tagLevel_ = 0;
50   while (!openElements_.empty())
51     delete openElements_.get();
52   openElements_.insert(new OpenElement(&documentElementContainer_,
53                                        0,
54                                        0,
55                                        &theEmptyMap,
56                                        Location()));
57   includeCount_.assign(dtd.nElementTypeIndex(), 0);
58   excludeCount_.assign(dtd.nElementTypeIndex(), 0);
59   openElementCount_.assign(dtd.nElementTypeIndex(), 0);
60   netEnablingCount_ = 0;
61   totalExcludeCount_ = 0;
62   lastEndedElementType_ = 0;
63   undefinedElementTypeTable_.clear();
64 }
65
66 void ContentState::pushElement(OpenElement *e)
67 {
68   tagLevel_++;
69   openElementCount_[e->type()->index()]++;
70   const ElementDefinition *def = e->type()->definition();
71   if (def) {
72     size_t i;
73     for (i = 0; i < def->nInclusions(); i++)
74       includeCount_[def->inclusion(i)->index()]++;
75     for (i = 0; i < def->nExclusions(); i++) {
76       excludeCount_[def->exclusion(i)->index()]++;
77       totalExcludeCount_++;
78     }
79   }
80   if (e->netEnabling())
81     netEnablingCount_++;
82   openElements_.insert(e);
83 }
84
85 OpenElement *ContentState::popSaveElement()
86 {
87   ASSERT(tagLevel_ > 0);
88   OpenElement *e = openElements_.get();
89   tagLevel_--;
90   openElementCount_[e->type()->index()]--;
91   const ElementDefinition *def = e->type()->definition();
92   if (def) {
93     size_t i;
94     for (i = 0; i < def->nInclusions(); i++)
95       includeCount_[def->inclusion(i)->index()]--;
96     for (i = 0; i < def->nExclusions(); i++) {
97       excludeCount_[def->exclusion(i)->index()]--;
98       totalExcludeCount_--;
99     }
100   }
101   if (e->netEnabling())
102     netEnablingCount_--;
103   lastEndedElementType_ = e->type();
104   return e;
105 }
106
107 void ContentState::popElement()
108 {
109   delete popSaveElement();
110 }
111                               
112 Boolean ContentState::checkImplyLoop(unsigned count)
113 {
114   for (IListIter<OpenElement> iter(openElements_);
115        count > 0;
116        iter.next(), count--)
117     if (iter.cur()->type() == openElements_.head()->type()
118         // I'm not sure whether this is necessary.
119         && iter.cur()->matchState() == openElements_.head()->matchState())
120       return 0;
121   return 1;
122 }
123
124 void ContentState::getOpenElementInfo(Vector<OpenElementInfo> &v,
125                                       const StringC &rniPcdata) const
126 {
127   v.clear();
128   v.resize(tagLevel_);
129   unsigned i = tagLevel_;
130   for (IListIter<OpenElement> iter(openElements_);
131        !iter.done() && i > 0;
132        iter.next()) {
133     OpenElementInfo &e = v[--i];
134     e.gi = iter.cur()->type()->name();
135     const LeafContentToken *token = iter.cur()->currentPosition();
136     if (token && !token->isInitial()) {
137       e.matchIndex = token->typeIndex() + 1;
138       const ElementType *type = token->elementType();
139       e.matchType = type ? type->name() : rniPcdata;
140     }
141     e.included = iter.cur()->included();
142   }
143 }
144
145 const ElementType *
146 ContentState::lookupCreateUndefinedElement(const StringC &name,
147                                            const Location &loc)
148 {
149   const ElementType *e = undefinedElementTypeTable_.lookup(name);
150   if (e)
151     return e;
152   ElementType *p = new ElementType(name,
153                                    openElementCount_.size());
154   p->setElementDefinition(new ElementDefinition(loc,
155                                                 ElementDefinition::undefinedIndex,
156                                                 (ElementDefinition::omitStart
157                                                  |ElementDefinition::omitEnd),
158                                                 ElementDefinition::any),
159                           0);
160   undefinedElementTypeTable_.insert(p);
161   includeCount_.push_back(0);
162   excludeCount_.push_back(0);
163   openElementCount_.push_back(0);
164   return p;
165 }
166
167
168 #ifdef SP_NAMESPACE
169 }
170 #endif