2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /* $TOG: autoNumberFP.C /main/7 1998/04/17 11:47:29 mgreess $ */
25 #include "autoNumberFP.h"
26 #include "StyleSheet/Const.h"
27 #include "StyleSheet/Expression.h"
29 autoNumberFP gAutoNumberFP;
32 typedef CC_TPtrSlistIterator<autoNumber> autoNumberListIteratorT;
33 unsigned ANP_StringHash(const CC_String& str)
38 typedef CC_TPtrSlistIterator<autoNumber> autoNumberListIteratorT;
39 unsigned ANP_StringHash(const CC_String& str)
46 ///////////////////////////////////////////////
47 // static member initialization
48 ///////////////////////////////////////////////
51 f_autoNumberSet_t autoNumberFP::f_autoNumberSet(ANP_StringHash);
52 f_resetControlList_t autoNumberFP::f_resetControlList(ANP_StringHash);
53 f_registerList_t autoNumberFP::f_registerList(ANP_StringHash);
56 ///////////////////////////////////////////////
58 ///////////////////////////////////////////////
61 autoNumberFP::autoNumberFP() :
62 f_autoNumberSet(ANP_StringHash),
63 f_resetControlList(ANP_StringHash),
64 f_registerList(ANP_StringHash)
68 autoNumberFP::~autoNumberFP()
70 f_autoNumberSet.clearAndDestroy();
71 f_resetControlList.clearAndDestroy();
72 f_registerList.clearAndDestroy();
75 const char* autoNumberFP::stringToCharPtr(const FeatureValue* f)
78 if ( f -> type() == FeatureValue::string ) {
82 throw(CASTHCREXCEPT hardCopyRendererException());
89 void autoNumberFP::resetAutoNumbers(const char* name)
93 autoNumberListT* anList = f_resetControlList.findValue(&key);
98 autoNumberListIteratorT l_iter(*anList);
101 l_iter.key() -> reset();
107 autoNumberFP::pushAutoNumbers(const char* giname)
109 if (giname && *giname)
111 CC_String key(giname);
113 autoNumberListT* anList = f_resetControlList.findValue(&key);
117 autoNumberListIteratorT l_iter(*anList);
119 l_iter.key()->push();
125 autoNumberFP::popAutoNumbers(const char* giname)
127 if (giname && *giname)
129 CC_String key(giname);
131 autoNumberListT* anList = f_resetControlList.findValue(&key);
135 autoNumberListIteratorT l_iter(*anList);
142 // update autonumbers
143 void autoNumberFP::updateAutoNumbers(const char* name)
146 autoNumberListT* anList = f_registerList.findValue(&key);
151 autoNumberListIteratorT l_iter(*anList);
154 l_iter.key() -> setNextValue();
159 //////////////////////////////////////////////////////////////////////////
162 // Type, InitValue, Delta, RegisterList, ControlList, [Prefix], [PostFix]
164 // Type, Pretfix and Postfix are strings.
165 // RegisterList and ControlList are array.
166 // InitValue and Delta are integers.
167 // Prefix and Postfix are optional
168 //////////////////////////////////////////////////////////////////////////
170 autoNumberFP::defineAutoNumber(const char* nm, const FeatureValue* f)
172 if ( f -> type() != FeatureValue::array ) {
173 debug(cerr, f -> type());
174 cerr << "Autonumber: should use an array to define.\n";
175 throw(CASTHCREXCEPT hardCopyRendererException());
178 FeatureValueArray* fa = (FeatureValueArray*)f;
180 if ( fa -> length() != 5 ) {
181 cerr << "Autonumber: invalid number of arguments.\n";
182 throw(CASTHCREXCEPT hardCopyRendererException());
186 const char* name = nm;
189 if ( (*fa)[0] -> type() != FeatureValue::string ) {
190 cerr << "Autonumber: type should be a string.\n";
191 throw(CASTHCREXCEPT hardCopyRendererException());
194 const char* type = stringToCharPtr((*fa)[0]);
197 if ( (*fa)[1] -> type() != FeatureValue::string ) {
198 cerr << "Autonumber: initial value should be a string.\n";
199 throw(CASTHCREXCEPT hardCopyRendererException());
201 const char* initvalue = stringToCharPtr((*fa)[1]);
204 if ( (*fa)[2] -> type() != FeatureValue::string ) {
205 cerr << "Autonumber: delta value should be a string.\n";
206 throw(CASTHCREXCEPT hardCopyRendererException());
208 int delta = atoi(stringToCharPtr((*fa)[2]));
212 FeatureValueArray* registerList = 0;
213 if ( (*fa)[3] -> type() != FeatureValue::array ) {
214 cerr << "Autonumber: counter list should be an array\n.";
215 throw(CASTHCREXCEPT hardCopyRendererException());
217 registerList = (FeatureValueArray*)(*fa)[3];
221 FeatureValueArray* controlList = 0;
222 if ( (*fa)[4] -> type() != FeatureValue::array ) {
223 cerr << "Autonumber: reset list should be an array\n.";
224 throw(CASTHCREXCEPT hardCopyRendererException());
226 controlList = (FeatureValueArray*)(*fa)[4];
230 const char* prefix = "";
233 const char* postfix = "";
235 //////////////////////////////////
236 // create the autonumber object
237 //////////////////////////////////
239 if ( strcasecmp(type, AUTO_NUMBER_NUMERIC) == 0 )
240 an = new autoNumberNumeric(
241 name, delta, atoi(initvalue), prefix, postfix
244 if ( strcasecmp(type, AUTO_NUMBER_ALPHABETIC_UPPERCASE) == 0 ) {
245 an = new autoNumberAlphabetic(
246 name, delta, autoNumberCased::UPPER, initvalue, prefix, postfix
249 if ( strcasecmp(type, AUTO_NUMBER_ALPHABETIC_LOWERCASE) == 0 ) {
250 an = new autoNumberAlphabetic(
251 name, delta, autoNumberCased::LOWER, initvalue, prefix, postfix
254 if ( strcasecmp(type, AUTO_NUMBER_ROMAN_UPPERCASE) == 0 )
255 an = new autoNumberRoman(
256 name, delta, autoNumberCased::UPPER, initvalue, prefix, postfix
259 if ( strcasecmp(type, AUTO_NUMBER_ROMAN_LOWERCASE) == 0 )
260 an = new autoNumberRoman(
261 name, delta, autoNumberCased::LOWER, initvalue, prefix, postfix
264 MESSAGE(cerr, form("unknown type: %s", type));
265 cerr << form("Autonumber: unknown type %s.", type) << "\n";
266 throw(CASTHCREXCEPT hardCopyRendererException());
269 //////////////////////////
270 // log the new autonumber
271 //////////////////////////
272 CC_String *key = new CC_String(name);
274 if ( f_autoNumberSet.findValue(key) ) {
279 f_autoNumberSet.insertKeyAndValue(key, an);
281 ///////////////////////////////
282 // log into reset control list
283 ///////////////////////////////
286 autoNumberListT* anList = 0;
287 for (int i=0; i<controlList -> length(); i++ ) {
289 gi = stringToCharPtr((*controlList)[i]);
290 key = new CC_String(gi);
292 anList = f_resetControlList.findValue(key);
295 anList = new autoNumberListT();
296 f_resetControlList.insertKeyAndValue(key, anList);
300 anList -> append(an);
303 ////////////////////////////////
304 // log into register list
305 ////////////////////////////////
306 for (i=0; i<registerList -> length(); i++ ) {
308 gi = stringToCharPtr((*registerList)[i]);
309 key = new CC_String(gi);
311 anList = f_registerList.findValue(key);
314 anList = new autoNumberListT();
315 f_registerList.insertKeyAndValue(key, anList);
319 anList -> append(an);
323 void autoNumberFP::setSeenTagStatus(const char* tagName)
325 CC_String key(tagName);
326 autoNumberListT* anList = f_registerList.findValue(&key);
331 autoNumberListIteratorT next(*anList);
333 next.key() -> setNumTagsSeen();
339 autoNumberFP::evaluate(const char* varName)
341 CC_String key(varName);
342 autoNumber* an = f_autoNumberSet.findValue(&key);
345 MESSAGE(cerr, form("Warning: unknown autonumber name %s.", varName));
348 return new FeatureValueString(an -> getValue());
352 autoNumberFP::accept(const char* name, const Expression* expr)
354 FeatureValue* fv = 0;
358 fv = expr -> evaluate();
371 if ( fv -> type() != FeatureValue::array ) {
376 FeatureValueArray* fvArray = (FeatureValueArray*) fv;
379 debug(cerr, fvArray -> length());
380 debug(cerr, fvArray -> name());
383 if ( fvArray -> length() >= 1 &&
384 strcasecmp(fvArray -> name(), AUTO_NUMBER) == 0
387 defineAutoNumber(name, fv);
397 autoNumberFP::beginElement(const Element& element)
399 const char* giname = element.gi().name();
401 if (giname && *giname)
403 pushAutoNumbers(giname);
405 setSeenTagStatus(giname);
406 updateAutoNumbers(giname);
415 autoNumberFP::endElement(const Symbol& sym)
417 const char* giname = sym.name();
419 if (giname && *giname)
421 popAutoNumbers(giname);
430 void autoNumberFP::preEvaluate(const Element& element)
432 setSeenTagStatus(element.gi().name());
433 updateAutoNumbers(element.gi().name());
436 void autoNumberFP::postEvaluate(const Element& element)
438 resetAutoNumbers(element.gi().name());
442 void autoNumberFP::clear()
444 f_autoNumberSet.clearAndDestroy();
445 f_resetControlList.clearAndDestroy();
446 f_registerList.clearAndDestroy();
449 // reset All autonumbers
450 void autoNumberFP::resetAllAutoNumbers()
452 hashTableIterator<CC_String, autoNumberListT> l_rc_iterator(f_resetControlList);
454 while ( ++l_rc_iterator ) {
456 autoNumberListT* anList = l_rc_iterator.value();
458 autoNumberListIteratorT l_iter(*anList);
461 l_iter.key() -> reset();