Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtinfo / DtMmdb / HardCopy / autoNumberFP.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 /* $TOG: autoNumberFP.C /main/7 1998/04/17 11:47:29 mgreess $ */
24
25 #include "autoNumberFP.h"
26 #include "StyleSheet/Const.h"
27 #include "StyleSheet/Expression.h"
28
29 autoNumberFP gAutoNumberFP;
30
31 #ifndef CDE_NEXT
32 typedef CC_TPtrSlistIterator<autoNumber> autoNumberListIteratorT;
33 unsigned ANP_StringHash(const CC_String& str)
34 {
35    return str.hash();
36 }
37 #else
38 typedef CC_TPtrSlistIterator<autoNumber> autoNumberListIteratorT;
39 unsigned ANP_StringHash(const CC_String& str)
40 {
41    return str.hash();
42 }
43 #endif
44
45
46 ///////////////////////////////////////////////
47 // static member initialization
48 ///////////////////////////////////////////////
49
50 /*
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);
54 */
55
56 ///////////////////////////////////////////////
57 //
58 ///////////////////////////////////////////////
59
60
61 autoNumberFP::autoNumberFP() :
62 f_autoNumberSet(ANP_StringHash),
63 f_resetControlList(ANP_StringHash),
64 f_registerList(ANP_StringHash)
65 {
66 }
67
68 autoNumberFP::~autoNumberFP() 
69 {
70    f_autoNumberSet.clearAndDestroy();
71    f_resetControlList.clearAndDestroy();
72    f_registerList.clearAndDestroy();
73 }
74
75 const char* autoNumberFP::stringToCharPtr(const FeatureValue* f)
76 {
77    if ( f ) {
78       if ( f -> type() == FeatureValue::string ) {
79          const char* x = *f;
80          return x;
81       } else
82          throw(CASTHCREXCEPT hardCopyRendererException());
83    }
84    return 0;
85 }
86
87 #if 0
88 // reset autonumbers
89 void autoNumberFP::resetAutoNumbers(const char* name)
90 {
91    CC_String key(name);
92
93    autoNumberListT* anList = f_resetControlList.findValue(&key);
94
95    if ( anList == 0 ) 
96       return;
97
98    autoNumberListIteratorT l_iter(*anList);  
99
100    while ( ++l_iter ) {
101       l_iter.key() -> reset();
102    }
103 }
104 #endif
105
106 void
107 autoNumberFP::pushAutoNumbers(const char* giname)
108 {
109   if (giname && *giname)
110   {
111     CC_String key(giname);
112
113     autoNumberListT* anList = f_resetControlList.findValue(&key);
114
115     if (anList)
116     {
117       autoNumberListIteratorT l_iter(*anList);
118       while ( ++l_iter )
119         l_iter.key()->push();
120     }
121   }
122 }
123
124 void
125 autoNumberFP::popAutoNumbers(const char* giname)
126 {
127   if (giname && *giname)
128   {
129     CC_String key(giname);
130
131     autoNumberListT* anList = f_resetControlList.findValue(&key);
132
133     if (anList)
134     {
135       autoNumberListIteratorT l_iter(*anList);
136       while ( ++l_iter )
137         l_iter.key()->pop();
138     }
139   }
140 }
141
142 // update autonumbers
143 void autoNumberFP::updateAutoNumbers(const char* name)
144 {
145    CC_String key(name);
146    autoNumberListT* anList = f_registerList.findValue(&key);
147
148    if ( anList == 0 )
149       return;
150
151    autoNumberListIteratorT l_iter(*anList);
152
153    while ( ++l_iter ) {
154       l_iter.key() -> setNextValue();
155    }
156 }
157
158
159 //////////////////////////////////////////////////////////////////////////
160 //
161 // Array fields:
162 // Type, InitValue, Delta, RegisterList, ControlList, [Prefix], [PostFix]
163 //
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 //////////////////////////////////////////////////////////////////////////
169 void 
170 autoNumberFP::defineAutoNumber(const char* nm, const FeatureValue* f)
171 {
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());
176    }
177
178    FeatureValueArray* fa = (FeatureValueArray*)f;
179
180    if ( fa -> length() != 5 ) {
181       cerr << "Autonumber: invalid number of arguments.\n";
182       throw(CASTHCREXCEPT hardCopyRendererException());
183    }
184
185 // name
186    const char* name = nm;
187
188 // type
189    if ( (*fa)[0] -> type() != FeatureValue::string ) {
190       cerr << "Autonumber: type should be a string.\n";
191       throw(CASTHCREXCEPT hardCopyRendererException());
192    } 
193
194    const char* type = stringToCharPtr((*fa)[0]);
195
196 // init value
197    if ( (*fa)[1] -> type() != FeatureValue::string ) {
198       cerr << "Autonumber: initial value should be a string.\n";
199       throw(CASTHCREXCEPT hardCopyRendererException());
200    } 
201    const char* initvalue = stringToCharPtr((*fa)[1]);
202
203 // delta
204    if ( (*fa)[2] -> type() != FeatureValue::string ) {
205       cerr << "Autonumber: delta value should be a string.\n";
206       throw(CASTHCREXCEPT hardCopyRendererException());
207    } 
208    int delta = atoi(stringToCharPtr((*fa)[2]));
209
210
211 // register list
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());
216    } else {
217       registerList = (FeatureValueArray*)(*fa)[3]; 
218    }
219
220 // control list
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());
225    } else {
226       controlList = (FeatureValueArray*)(*fa)[4]; 
227    }
228
229 // prefix
230    const char* prefix = "";
231
232 // postfix
233    const char* postfix = "";
234
235 //////////////////////////////////
236 // create the autonumber object
237 //////////////////////////////////
238    autoNumber* an = 0;
239    if ( strcasecmp(type, AUTO_NUMBER_NUMERIC) == 0 )
240       an = new autoNumberNumeric(
241                 name, delta, atoi(initvalue), prefix, postfix
242                                 );
243    else
244    if ( strcasecmp(type, AUTO_NUMBER_ALPHABETIC_UPPERCASE) == 0 ) {
245       an = new autoNumberAlphabetic(
246            name, delta, autoNumberCased::UPPER, initvalue, prefix, postfix
247                                    );
248    } else
249    if ( strcasecmp(type, AUTO_NUMBER_ALPHABETIC_LOWERCASE) == 0 ) {
250       an = new autoNumberAlphabetic(
251            name, delta, autoNumberCased::LOWER, initvalue, prefix, postfix
252                                    );
253    } else
254    if ( strcasecmp(type, AUTO_NUMBER_ROMAN_UPPERCASE) == 0 )
255       an = new autoNumberRoman(
256            name, delta, autoNumberCased::UPPER, initvalue, prefix, postfix
257                               );
258    else 
259    if ( strcasecmp(type, AUTO_NUMBER_ROMAN_LOWERCASE) == 0 )
260       an = new autoNumberRoman(
261            name, delta, autoNumberCased::LOWER, initvalue, prefix, postfix
262                               );
263    else {
264       MESSAGE(cerr, form("unknown type: %s", type));
265       cerr << form("Autonumber: unknown type %s.", type) << "\n";
266       throw(CASTHCREXCEPT hardCopyRendererException());
267    }
268
269 //////////////////////////
270 // log the new autonumber
271 //////////////////////////
272    CC_String *key = new CC_String(name);
273
274    if ( f_autoNumberSet.findValue(key) ) {
275       delete key;
276       delete an;
277       return;
278    } else
279       f_autoNumberSet.insertKeyAndValue(key, an);
280    
281 ///////////////////////////////
282 // log into reset control list
283 ///////////////////////////////
284
285    const char* gi = 0;
286    autoNumberListT* anList = 0;
287    for (int i=0; i<controlList -> length(); i++ ) {
288
289       gi = stringToCharPtr((*controlList)[i]);
290       key = new CC_String(gi);
291
292       anList = f_resetControlList.findValue(key);
293
294       if ( anList == 0 ) {
295         anList = new autoNumberListT();
296         f_resetControlList.insertKeyAndValue(key, anList);
297       } else
298         delete key;
299
300       anList -> append(an);
301    }
302
303 ////////////////////////////////
304 // log into register list
305 ////////////////////////////////
306    for (i=0; i<registerList -> length(); i++ ) {
307
308       gi = stringToCharPtr((*registerList)[i]);
309       key = new CC_String(gi);
310
311       anList = f_registerList.findValue(key);
312
313       if ( anList == 0 ) {
314         anList = new autoNumberListT();
315         f_registerList.insertKeyAndValue(key, anList);
316       } else
317          delete key;
318
319       anList -> append(an);
320    }
321 }
322
323 void autoNumberFP::setSeenTagStatus(const char* tagName)
324 {
325    CC_String key(tagName);
326    autoNumberListT* anList = f_registerList.findValue(&key);
327
328    if ( anList == 0 ) 
329      return;
330
331    autoNumberListIteratorT next(*anList);
332    while ( ++next ) {
333       next.key() -> setNumTagsSeen();
334    }
335 }
336
337
338 FeatureValue* 
339 autoNumberFP::evaluate(const char* varName) 
340 {
341    CC_String key(varName);
342    autoNumber* an = f_autoNumberSet.findValue(&key);
343
344    if ( an == 0 ) {
345       MESSAGE(cerr, form("Warning: unknown autonumber name %s.", varName));
346       return 0;
347    } else
348       return new FeatureValueString(an -> getValue());
349 }
350
351 unsigned int 
352 autoNumberFP::accept(const char* name, const Expression* expr) 
353 {
354    FeatureValue* fv = 0;
355
356    try
357     {
358       fv = expr -> evaluate();
359     }
360    catch_any()
361     {
362       return false;
363     }
364    end_try;
365
366 /*
367 debug(cerr, name);
368 fv -> print(cerr);
369 */
370
371    if ( fv -> type() != FeatureValue::array ) {
372      delete fv;
373      return false;
374    }
375
376    FeatureValueArray* fvArray = (FeatureValueArray*) fv;
377
378 /*
379 debug(cerr, fvArray -> length());
380 debug(cerr, fvArray -> name());
381 */
382
383    if ( fvArray -> length() >= 1 &&
384         strcasecmp(fvArray -> name(), AUTO_NUMBER) == 0 
385       ) 
386    {
387       defineAutoNumber(name, fv);
388       delete fv;
389       return true;
390    } else {
391       delete fv;
392       return false;
393    }
394 }
395
396 void
397 autoNumberFP::beginElement(const Element& element)
398 {
399   const char* giname = element.gi().name();
400
401   if (giname && *giname)
402   {
403     pushAutoNumbers(giname);
404
405     setSeenTagStatus(giname);
406     updateAutoNumbers(giname);
407   }
408 #ifdef DEBUG
409   else
410     abort();
411 #endif
412 }
413
414 void
415 autoNumberFP::endElement(const Symbol& sym)
416 {
417   const char* giname = sym.name();
418
419   if (giname && *giname)
420   {
421     popAutoNumbers(giname);
422   }
423 #ifdef DEBUG
424   else
425     abort();
426 #endif
427 }
428
429 #if 0
430 void autoNumberFP::preEvaluate(const Element& element)
431 {
432    setSeenTagStatus(element.gi().name());
433    updateAutoNumbers(element.gi().name());
434 }
435
436 void autoNumberFP::postEvaluate(const Element& element)
437 {
438    resetAutoNumbers(element.gi().name());
439 }
440 #endif
441
442 void autoNumberFP::clear()
443 {
444    f_autoNumberSet.clearAndDestroy();
445    f_resetControlList.clearAndDestroy();
446    f_registerList.clearAndDestroy();
447 }
448
449 // reset All autonumbers
450 void autoNumberFP::resetAllAutoNumbers()
451 {
452    hashTableIterator<CC_String, autoNumberListT> l_rc_iterator(f_resetControlList);
453
454    while ( ++l_rc_iterator ) {
455      
456       autoNumberListT* anList = l_rc_iterator.value();
457
458       autoNumberListIteratorT l_iter(*anList);
459
460       while ( ++l_iter ) {
461          l_iter.key() -> reset();
462       }
463    }
464 }
465