mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
196 lines
5.6 KiB
C
196 lines
5.6 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/* $XConsortium: ContentState.C /main/1 1996/07/29 16:48:21 cde-hp $ */
|
|
// Copyright (c) 1994, 1996 James Clark
|
|
// See the file COPYING for copying permission.
|
|
|
|
#ifdef __GNUG__
|
|
#pragma implementation
|
|
#endif
|
|
|
|
#include "splib.h"
|
|
#include "ContentState.h"
|
|
#include "IListIter.h"
|
|
#include "NCVector.h"
|
|
#include "macros.h"
|
|
|
|
#ifdef SP_NAMESPACE
|
|
namespace SP_NAMESPACE {
|
|
#endif
|
|
|
|
const ShortReferenceMap ContentState::theEmptyMap;
|
|
|
|
#ifdef __GNUG__
|
|
typedef IListIter<OpenElement> Dummy_IListIter_OpenElement;
|
|
#endif
|
|
|
|
ContentState::ContentState()
|
|
: documentElementContainer_(StringC(), size_t(-1)),
|
|
totalExcludeCount_(0),
|
|
tagLevel_(0),
|
|
netEnablingCount_(0),
|
|
lastEndedElementType_(NULL)
|
|
{
|
|
}
|
|
|
|
void ContentState::startContent(const Dtd &dtd)
|
|
{
|
|
NCVector<Owner<ContentToken> > tokens(1);
|
|
tokens[0] = new ElementToken(dtd.documentElementType(),
|
|
ContentToken::none);
|
|
Owner<ModelGroup> model(new SeqModelGroup(tokens, ContentToken::none));
|
|
Owner<CompiledModelGroup> compiledModel(new CompiledModelGroup(model));
|
|
Vector<ContentModelAmbiguity> ambiguities;
|
|
Boolean pcdataUnreachable;
|
|
compiledModel->compile(dtd.nElementTypeIndex(), ambiguities,
|
|
pcdataUnreachable);
|
|
ASSERT(ambiguities.size() == 0);
|
|
ConstPtr<ElementDefinition> def
|
|
= new ElementDefinition(Location(),
|
|
0,
|
|
0,
|
|
ElementDefinition::modelGroup,
|
|
compiledModel);
|
|
documentElementContainer_.setElementDefinition(def, 0);
|
|
tagLevel_ = 0;
|
|
while (!openElements_.empty())
|
|
delete openElements_.get();
|
|
openElements_.insert(new OpenElement(&documentElementContainer_,
|
|
0,
|
|
0,
|
|
&theEmptyMap,
|
|
Location()));
|
|
includeCount_.assign(dtd.nElementTypeIndex(), 0);
|
|
excludeCount_.assign(dtd.nElementTypeIndex(), 0);
|
|
openElementCount_.assign(dtd.nElementTypeIndex(), 0);
|
|
netEnablingCount_ = 0;
|
|
totalExcludeCount_ = 0;
|
|
lastEndedElementType_ = 0;
|
|
undefinedElementTypeTable_.clear();
|
|
}
|
|
|
|
void ContentState::pushElement(OpenElement *e)
|
|
{
|
|
tagLevel_++;
|
|
openElementCount_[e->type()->index()]++;
|
|
const ElementDefinition *def = e->type()->definition();
|
|
if (def) {
|
|
size_t i;
|
|
for (i = 0; i < def->nInclusions(); i++)
|
|
includeCount_[def->inclusion(i)->index()]++;
|
|
for (i = 0; i < def->nExclusions(); i++) {
|
|
excludeCount_[def->exclusion(i)->index()]++;
|
|
totalExcludeCount_++;
|
|
}
|
|
}
|
|
if (e->netEnabling())
|
|
netEnablingCount_++;
|
|
openElements_.insert(e);
|
|
}
|
|
|
|
OpenElement *ContentState::popSaveElement()
|
|
{
|
|
ASSERT(tagLevel_ > 0);
|
|
OpenElement *e = openElements_.get();
|
|
tagLevel_--;
|
|
openElementCount_[e->type()->index()]--;
|
|
const ElementDefinition *def = e->type()->definition();
|
|
if (def) {
|
|
size_t i;
|
|
for (i = 0; i < def->nInclusions(); i++)
|
|
includeCount_[def->inclusion(i)->index()]--;
|
|
for (i = 0; i < def->nExclusions(); i++) {
|
|
excludeCount_[def->exclusion(i)->index()]--;
|
|
totalExcludeCount_--;
|
|
}
|
|
}
|
|
if (e->netEnabling())
|
|
netEnablingCount_--;
|
|
lastEndedElementType_ = e->type();
|
|
return e;
|
|
}
|
|
|
|
void ContentState::popElement()
|
|
{
|
|
delete popSaveElement();
|
|
}
|
|
|
|
Boolean ContentState::checkImplyLoop(unsigned count)
|
|
{
|
|
for (IListIter<OpenElement> iter(openElements_);
|
|
count > 0;
|
|
iter.next(), count--)
|
|
if (iter.cur()->type() == openElements_.head()->type()
|
|
// I'm not sure whether this is necessary.
|
|
&& iter.cur()->matchState() == openElements_.head()->matchState())
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
void ContentState::getOpenElementInfo(Vector<OpenElementInfo> &v,
|
|
const StringC &rniPcdata) const
|
|
{
|
|
v.clear();
|
|
v.resize(tagLevel_);
|
|
unsigned i = tagLevel_;
|
|
for (IListIter<OpenElement> iter(openElements_);
|
|
!iter.done() && i > 0;
|
|
iter.next()) {
|
|
OpenElementInfo &e = v[--i];
|
|
e.gi = iter.cur()->type()->name();
|
|
const LeafContentToken *token = iter.cur()->currentPosition();
|
|
if (token && !token->isInitial()) {
|
|
e.matchIndex = token->typeIndex() + 1;
|
|
const ElementType *type = token->elementType();
|
|
e.matchType = type ? type->name() : rniPcdata;
|
|
}
|
|
e.included = iter.cur()->included();
|
|
}
|
|
}
|
|
|
|
const ElementType *
|
|
ContentState::lookupCreateUndefinedElement(const StringC &name,
|
|
const Location &loc)
|
|
{
|
|
const ElementType *e = undefinedElementTypeTable_.lookup(name);
|
|
if (e)
|
|
return e;
|
|
ElementType *p = new ElementType(name,
|
|
openElementCount_.size());
|
|
p->setElementDefinition(new ElementDefinition(loc,
|
|
ElementDefinition::undefinedIndex,
|
|
(ElementDefinition::omitStart
|
|
|ElementDefinition::omitEnd),
|
|
ElementDefinition::any),
|
|
0);
|
|
undefinedElementTypeTable_.insert(p);
|
|
includeCount_.push_back(0);
|
|
excludeCount_.push_back(0);
|
|
openElementCount_.push_back(0);
|
|
return p;
|
|
}
|
|
|
|
|
|
#ifdef SP_NAMESPACE
|
|
}
|
|
#endif
|