Link with C++ linker
[oweals/cde.git] / cde / programs / nsgmls / ContentState.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: ContentState.C /main/1 1996/07/29 16:48:21 cde-hp $ */
24 // Copyright (c) 1994, 1996 James Clark
25 // See the file COPYING for copying permission.
26
27 #ifdef __GNUG__
28 #pragma implementation
29 #endif
30
31 #include "splib.h"
32 #include "ContentState.h"
33 #include "IListIter.h"
34 #include "NCVector.h"
35 #include "macros.h"
36
37 #ifdef SP_NAMESPACE
38 namespace SP_NAMESPACE {
39 #endif
40
41 const ShortReferenceMap ContentState::theEmptyMap;
42
43 #ifdef __GNUG__
44 typedef IListIter<OpenElement> Dummy_IListIter_OpenElement;
45 #endif
46
47 ContentState::ContentState()
48 : documentElementContainer_(StringC(), size_t(-1))
49 {
50 }
51
52 void ContentState::startContent(const Dtd &dtd)
53 {
54   NCVector<Owner<ContentToken> > tokens(1);
55   tokens[0] = new ElementToken(dtd.documentElementType(),
56                                ContentToken::none);
57   Owner<ModelGroup> model(new SeqModelGroup(tokens, ContentToken::none));
58   Owner<CompiledModelGroup> compiledModel(new CompiledModelGroup(model));
59   Vector<ContentModelAmbiguity> ambiguities;
60   Boolean pcdataUnreachable;
61   compiledModel->compile(dtd.nElementTypeIndex(), ambiguities,
62                          pcdataUnreachable);
63   ASSERT(ambiguities.size() == 0);
64   ConstPtr<ElementDefinition> def
65     = new ElementDefinition(Location(),
66                             0,
67                             0,
68                             ElementDefinition::modelGroup,
69                             compiledModel);
70   documentElementContainer_.setElementDefinition(def, 0);
71   tagLevel_ = 0;
72   while (!openElements_.empty())
73     delete openElements_.get();
74   openElements_.insert(new OpenElement(&documentElementContainer_,
75                                        0,
76                                        0,
77                                        &theEmptyMap,
78                                        Location()));
79   includeCount_.assign(dtd.nElementTypeIndex(), 0);
80   excludeCount_.assign(dtd.nElementTypeIndex(), 0);
81   openElementCount_.assign(dtd.nElementTypeIndex(), 0);
82   netEnablingCount_ = 0;
83   totalExcludeCount_ = 0;
84   lastEndedElementType_ = 0;
85   undefinedElementTypeTable_.clear();
86 }
87
88 void ContentState::pushElement(OpenElement *e)
89 {
90   tagLevel_++;
91   openElementCount_[e->type()->index()]++;
92   const ElementDefinition *def = e->type()->definition();
93   if (def) {
94     size_t i;
95     for (i = 0; i < def->nInclusions(); i++)
96       includeCount_[def->inclusion(i)->index()]++;
97     for (i = 0; i < def->nExclusions(); i++) {
98       excludeCount_[def->exclusion(i)->index()]++;
99       totalExcludeCount_++;
100     }
101   }
102   if (e->netEnabling())
103     netEnablingCount_++;
104   openElements_.insert(e);
105 }
106
107 OpenElement *ContentState::popSaveElement()
108 {
109   ASSERT(tagLevel_ > 0);
110   OpenElement *e = openElements_.get();
111   tagLevel_--;
112   openElementCount_[e->type()->index()]--;
113   const ElementDefinition *def = e->type()->definition();
114   if (def) {
115     size_t i;
116     for (i = 0; i < def->nInclusions(); i++)
117       includeCount_[def->inclusion(i)->index()]--;
118     for (i = 0; i < def->nExclusions(); i++) {
119       excludeCount_[def->exclusion(i)->index()]--;
120       totalExcludeCount_--;
121     }
122   }
123   if (e->netEnabling())
124     netEnablingCount_--;
125   lastEndedElementType_ = e->type();
126   return e;
127 }
128
129 void ContentState::popElement()
130 {
131   delete popSaveElement();
132 }
133                               
134 Boolean ContentState::checkImplyLoop(unsigned count)
135 {
136   for (IListIter<OpenElement> iter(openElements_);
137        count > 0;
138        iter.next(), count--)
139     if (iter.cur()->type() == openElements_.head()->type()
140         // I'm not sure whether this is necessary.
141         && iter.cur()->matchState() == openElements_.head()->matchState())
142       return 0;
143   return 1;
144 }
145
146 void ContentState::getOpenElementInfo(Vector<OpenElementInfo> &v,
147                                       const StringC &rniPcdata) const
148 {
149   v.clear();
150   v.resize(tagLevel_);
151   unsigned i = tagLevel_;
152   for (IListIter<OpenElement> iter(openElements_);
153        !iter.done() && i > 0;
154        iter.next()) {
155     OpenElementInfo &e = v[--i];
156     e.gi = iter.cur()->type()->name();
157     const LeafContentToken *token = iter.cur()->currentPosition();
158     if (token && !token->isInitial()) {
159       e.matchIndex = token->typeIndex() + 1;
160       const ElementType *type = token->elementType();
161       e.matchType = type ? type->name() : rniPcdata;
162     }
163     e.included = iter.cur()->included();
164   }
165 }
166
167 const ElementType *
168 ContentState::lookupCreateUndefinedElement(const StringC &name,
169                                            const Location &loc)
170 {
171   const ElementType *e = undefinedElementTypeTable_.lookup(name);
172   if (e)
173     return e;
174   ElementType *p = new ElementType(name,
175                                    openElementCount_.size());
176   p->setElementDefinition(new ElementDefinition(loc,
177                                                 ElementDefinition::undefinedIndex,
178                                                 (ElementDefinition::omitStart
179                                                  |ElementDefinition::omitEnd),
180                                                 ElementDefinition::any),
181                           0);
182   undefinedElementTypeTable_.insert(p);
183   includeCount_.push_back(0);
184   excludeCount_.push_back(0);
185   openElementCount_.push_back(0);
186   return p;
187 }
188
189
190 #ifdef SP_NAMESPACE
191 }
192 #endif