Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtinfo / DtMmdb / StyleSheet / FeatureSet.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: FeatureSet.cc /main/5 1996/08/05 16:18:55 cde-hal $
24 #include <stdarg.h>
25 #include <assert.h>
26 #include "Feature.h"
27 #include "FeatureValue.h"
28 #include "StyleSheetExceptions.h"
29 #include "Debug.h"
30
31 unsigned int FeatureSet::f_print_indent_level = 0 ;
32
33 ostream &operator << (ostream &o, const FeatureSet &f)
34 {
35   return f.print(o);
36 }
37
38 FeatureSet::~FeatureSet()
39 {
40   clearAndDestroy();            // clean up memory 
41 }
42
43 FeatureSet::FeatureSet()
44 {
45 }
46
47 FeatureSet::FeatureSet(const FeatureSet &orig_set)
48 {
49   // cast to non const 
50   CC_TPtrSlistIterator<Feature> next(*(CC_TPtrSlist<Feature>*) &orig_set) ;
51
52   // make a copy of each item and add it to our list 
53   while (++next)
54     append(new Feature(*next.key()));
55
56 }
57
58 FeatureSet *
59 FeatureSet::evaluate() const
60 {
61   // I do not yet understand how this evaluate is working well. - TK
62 #ifdef FS_EVAL_DEBUG
63   fprintf(stderr, "(DEBUG) FeatureSet::evaluate() called.\n");
64 #endif
65   return evaluate(new FeatureSet);
66 }
67
68 FeatureSet *
69 FeatureSet::evaluate(FeatureSet *result_set) const
70 {
71   
72   CC_TPtrSlistIterator<Feature> next(*(FeatureSet*)this);
73   
74   // cause each feature to evaluate itself 
75   while(++next)
76     {
77       FeatureValue *value ;
78       try
79         {
80           value = next.key()->evaluate();
81           result_set->append(new Feature(next.key()->name(),
82                                          value));
83         }
84 #ifdef UXPDS
85       catch_any()
86 #else
87       catch_noarg(badEvaluationException)
88 #endif
89         {
90           /* do nothing...we just ignore any that will not evaluate */
91         }
92       end_try;
93     }
94
95   return result_set ;
96 }
97
98 FeatureSet::FeatureSet(const FeatureSet &base,
99                        const FeatureSet &mixin)
100 {
101   Feature dummy = Feature(gSymTab->intern("FAMILY"),0);
102   int contains_family = mixin.contains(&dummy);
103
104   // first duplicate the baseline
105   CC_TPtrSlistIterator<Feature> base_i(*(CC_TPtrSlist<Feature>*)&base) ;
106
107   // make a copy of each item and add it to our list 
108   while (++base_i) {
109       if (! (contains_family &&
110                 base_i.key()->name() == gSymTab->intern("FAMILY")))
111         append(new Feature(*base_i.key()));
112   }
113
114   // now merge in mixin
115
116   CC_TPtrSlistIterator<Feature> next(*(CC_TPtrSlist<Feature>*)&mixin);
117   
118   while (++next)
119     {
120       if (next.key()->name() == gSymTab->intern("FAMILY"))
121         append(new Feature(*next.key()));
122       else {
123         Feature* mfeature = 0;
124         mfeature = find(next.key());
125 #if 0
126         cout << "Merging: \n" <<  *next.key() << endl << "into:" << endl;
127         if (mfeature)
128           cout << *mfeature << endl;
129         else
130           cout << "(nil)" << endl;
131 #endif
132         if (mfeature)
133           mfeature->merge(*next.key()); // merge it if already exists
134         else
135           append(new Feature(*next.key())); // else add it if not there
136       }
137     }
138 }
139
140 ostream &
141 FeatureSet::print(ostream &o) const
142 {
143   // cast to non-const to get iterator 
144   CC_TPtrSlistIterator<Feature> next(*(CC_TPtrSlist<Feature>*)this);
145   
146   for (int i = 0 ; i < f_print_indent_level; i++)
147     o << "  " ;
148
149   o << "{" << endl;
150   
151   f_print_indent_level++;
152
153   while (++next)
154     {
155       for (int i = 0 ; i < f_print_indent_level; i++)
156         o << "  " ;
157       o << *next.key() << endl ;
158     }
159   
160   --f_print_indent_level;
161   for (i = 0 ; i < f_print_indent_level ; i++)
162     o << "  " ;
163
164   o << "}" << endl;
165
166   return o;
167 }
168
169 void
170 FeatureSet::add(Feature *f)
171 {
172   append(f);
173 }
174
175
176 unsigned int
177 FeatureSet::operator==(const FeatureSet &fs) const
178 {
179   return &fs == this ;
180 }
181
182 const Feature*
183 FeatureSet::lookup(const Symbol *symbol) const
184 {
185   return lookup(*symbol);
186 }
187
188 const Feature *
189 FeatureSet::lookup(const Symbol &name) const
190 {
191   Feature tmp(name, 0);
192   return find(&tmp);
193 }
194
195
196 const Feature *
197 FeatureSet::lookup(const char *name) const
198 {
199   Feature tmp(gSymTab->intern(name),0);
200   return find(&tmp);
201 }
202
203 const Feature *
204 FeatureSet::deep_lookup(const char *first_name ...) const
205 {
206   const Feature *feature = lookup(first_name);
207
208   if (!feature)
209     return 0; 
210
211   const FeatureSet *featureset = 0;
212   
213   va_list ap;
214   va_start(ap, first_name);
215
216
217   for (;;)
218     {
219       const char *p = va_arg(ap, char*);
220       if (p == 0)
221         break;
222
223       if (feature->value()->type() != FeatureValue::featureset)
224         {
225           va_end(ap);
226           return 0 ;
227         }
228
229       featureset = ((const FeatureValueFeatureSet *)feature->value())->value();
230
231       feature = featureset->lookup(p);
232
233       if (!feature)
234         {
235           va_end(ap);
236           return 0;
237         }
238     }
239   va_end(ap);
240   return feature ;
241 }
242
243 const Feature *
244 FeatureSet::deep_lookup(const Symbol *first_name ...) const
245 {
246   const Feature *feature = lookup(*first_name);
247
248   if (!feature)
249     return 0; 
250
251   const FeatureSet *featureset = 0;
252   
253   va_list ap;
254   va_start(ap, first_name);
255
256
257   for (;;)
258     {
259       const Symbol *sym = va_arg(ap, const Symbol *);
260       if (sym == 0)
261         break;
262
263       if (feature->value()->type() != FeatureValue::featureset)
264         {
265           va_end(ap);
266           return 0 ;
267         }
268
269       featureset = ((const FeatureValueFeatureSet *)feature->value())->value();
270
271       feature = featureset->lookup(*sym);
272
273       if (!feature)
274         {
275           va_end(ap);
276           return 0;
277         }
278     }
279   va_end(ap);
280   return feature ;
281 }
282
283 const Feature *
284 FeatureSet::deep_lookup(const dlist_array<Symbol> &vec) const
285 {
286   unsigned int index = 0;
287   const Feature *feature = lookup(*vec[index++]);
288   if (!feature)
289     return 0;
290
291   const FeatureSet *set = 0;
292
293   unsigned int entries = vec.entries();
294   for (; index < entries ; index++ )
295     {
296       if (feature->value()->type() != FeatureValue::featureset)
297         return 0 ;
298       
299       set = ((const FeatureValueFeatureSet *)feature->value())->value();
300       feature = set->lookup(*vec[index++]);
301       if (!feature)
302         return 0 ;
303     }
304   return feature ;
305 }
306
307
308 void
309 FeatureSet::removeFeature(const char *first_name ...) 
310 {
311   const Feature *feature = lookup(first_name);
312
313   if (!feature)
314     return ; 
315
316   FeatureSet *featureset = this;
317   
318   va_list ap;
319   va_start(ap, first_name);
320
321
322   for (;;)
323     {
324       const char *p = va_arg(ap, char*);
325       if (p == 0)
326         break;
327
328       if (feature->value()->type() != FeatureValue::featureset)
329         {
330           va_end(ap);
331           return ;
332         }
333
334       featureset = (FeatureSet*)
335         (((const FeatureValueFeatureSet *)feature->value())->value());
336
337       feature = featureset->lookup(p);
338
339       if (!feature)
340         {
341           va_end(ap);
342           return ;
343         }
344     }
345   va_end(ap);
346
347   delete (featureset -> remove((Feature *)feature));
348 }