cdesktopenv/cde/lib/DtMmdb/StyleSheet/FeatureSet.C

346 lines
6.9 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: FeatureSet.cc /main/5 1996/08/05 16:18:55 cde-hal $
#include <stdarg.h>
#include <assert.h>
#include "Feature.h"
#include "FeatureValue.h"
#include "StyleSheetExceptions.h"
#include "Debug.h"
unsigned int FeatureSet::f_print_indent_level = 0 ;
ostream &operator << (ostream &o, const FeatureSet &f)
{
return f.print(o);
}
FeatureSet::~FeatureSet()
{
clearAndDestroy(); // clean up memory
}
FeatureSet::FeatureSet()
{
}
FeatureSet::FeatureSet(const FeatureSet &orig_set)
{
// cast to non const
CC_TPtrSlistIterator<Feature> next(*(CC_TPtrSlist<Feature>*) &orig_set) ;
// make a copy of each item and add it to our list
while (++next)
append(new Feature(*next.key()));
}
FeatureSet *
FeatureSet::evaluate() const
{
// I do not yet understand how this evaluate is working well. - TK
#ifdef FS_EVAL_DEBUG
fprintf(stderr, "(DEBUG) FeatureSet::evaluate() called.\n");
#endif
return evaluate(new FeatureSet);
}
FeatureSet *
FeatureSet::evaluate(FeatureSet *result_set) const
{
CC_TPtrSlistIterator<Feature> next(*(FeatureSet*)this);
// cause each feature to evaluate itself
while(++next)
{
FeatureValue *value ;
mtry
{
value = next.key()->evaluate();
result_set->append(new Feature(next.key()->name(),
value));
}
mcatch_noarg(badEvaluationException&)
{
/* do nothing...we just ignore any that will not evaluate */
}
end_try;
}
return result_set ;
}
FeatureSet::FeatureSet(const FeatureSet &base,
const FeatureSet &mixin)
{
Feature dummy = Feature(gSymTab->intern("FAMILY"),0);
int contains_family = mixin.contains(&dummy);
// first duplicate the baseline
CC_TPtrSlistIterator<Feature> base_i(*(CC_TPtrSlist<Feature>*)&base) ;
// make a copy of each item and add it to our list
while (++base_i) {
if (! (contains_family &&
base_i.key()->name() == gSymTab->intern("FAMILY")))
append(new Feature(*base_i.key()));
}
// now merge in mixin
CC_TPtrSlistIterator<Feature> next(*(CC_TPtrSlist<Feature>*)&mixin);
while (++next)
{
if (next.key()->name() == gSymTab->intern("FAMILY"))
append(new Feature(*next.key()));
else {
Feature* mfeature = 0;
mfeature = find(next.key());
#if 0
cout << "Merging: \n" << *next.key() << endl << "into:" << endl;
if (mfeature)
cout << *mfeature << endl;
else
cout << "(nil)" << endl;
#endif
if (mfeature)
mfeature->merge(*next.key()); // merge it if already exists
else
append(new Feature(*next.key())); // else add it if not there
}
}
}
ostream &
FeatureSet::print(ostream &o) const
{
// cast to non-const to get iterator
CC_TPtrSlistIterator<Feature> next(*(CC_TPtrSlist<Feature>*)this);
unsigned int i;
for (i = 0 ; i < f_print_indent_level; i++)
o << " " ;
o << "{" << endl;
f_print_indent_level++;
while (++next)
{
for (unsigned int i = 0 ; i < f_print_indent_level; i++)
o << " " ;
o << *next.key() << endl ;
}
--f_print_indent_level;
for (i = 0 ; i < f_print_indent_level ; i++)
o << " " ;
o << "}" << endl;
return o;
}
void
FeatureSet::add(Feature *f)
{
append(f);
}
unsigned int
FeatureSet::operator==(const FeatureSet &fs) const
{
return &fs == this ;
}
const Feature*
FeatureSet::lookup(const Symbol *symbol) const
{
return lookup(*symbol);
}
const Feature *
FeatureSet::lookup(const Symbol &name) const
{
Feature tmp(name, 0);
return find(&tmp);
}
const Feature *
FeatureSet::lookup(const char *name) const
{
Feature tmp(gSymTab->intern(name),0);
return find(&tmp);
}
const Feature *
FeatureSet::deep_lookup(const char *first_name ...) const
{
const Feature *feature = lookup(first_name);
if (!feature)
return 0;
const FeatureSet *featureset = 0;
va_list ap;
va_start(ap, first_name);
for (;;)
{
const char *p = va_arg(ap, char*);
if (p == 0)
break;
if (feature->value()->type() != FeatureValue::featureset)
{
va_end(ap);
return 0 ;
}
featureset = ((const FeatureValueFeatureSet *)feature->value())->value();
feature = featureset->lookup(p);
if (!feature)
{
va_end(ap);
return 0;
}
}
va_end(ap);
return feature ;
}
const Feature *
FeatureSet::deep_lookup(const Symbol *first_name ...) const
{
const Feature *feature = lookup(*first_name);
if (!feature)
return 0;
const FeatureSet *featureset = 0;
va_list ap;
va_start(ap, first_name);
for (;;)
{
const Symbol *sym = va_arg(ap, const Symbol *);
if (sym == 0)
break;
if (feature->value()->type() != FeatureValue::featureset)
{
va_end(ap);
return 0 ;
}
featureset = ((const FeatureValueFeatureSet *)feature->value())->value();
feature = featureset->lookup(*sym);
if (!feature)
{
va_end(ap);
return 0;
}
}
va_end(ap);
return feature ;
}
const Feature *
FeatureSet::deep_lookup(const dlist_array<Symbol> &vec) const
{
unsigned int index = 0;
const Feature *feature = lookup(*vec[index++]);
if (!feature)
return 0;
const FeatureSet *set = 0;
unsigned int entries = vec.entries();
for (; index < entries ; index++ )
{
if (feature->value()->type() != FeatureValue::featureset)
return 0 ;
set = ((const FeatureValueFeatureSet *)feature->value())->value();
feature = set->lookup(*vec[index++]);
if (!feature)
return 0 ;
}
return feature ;
}
void
FeatureSet::removeFeature(const char *first_name ...)
{
const Feature *feature = lookup(first_name);
if (!feature)
return ;
FeatureSet *featureset = this;
va_list ap;
va_start(ap, first_name);
for (;;)
{
const char *p = va_arg(ap, char*);
if (p == 0)
break;
if (feature->value()->type() != FeatureValue::featureset)
{
va_end(ap);
return ;
}
featureset = (FeatureSet*)
(((const FeatureValueFeatureSet *)feature->value())->value());
feature = featureset->lookup(p);
if (!feature)
{
va_end(ap);
return ;
}
}
va_end(ap);
delete (featureset -> remove((Feature *)feature));
}