1 /***********************************************************************/
2 /* Open Visualization Data Explorer                                    */
3 /* (C) Copyright IBM Corp. 1989,1999                                   */
4 /* ALL RIGHTS RESERVED                                                 */
5 /* This code licensed under the                                        */
6 /*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
7 /***********************************************************************/
8 
9 #include <dxconfig.h>
10 #include "../base/defines.h"
11 
12 
13 
14 
15 
16 #include <stdio.h>
17 #ifdef ABS_IN_MATH_H
18 # define abs __Dont_define_abs
19 #endif
20 #include <math.h>
21 #ifdef ABS_IN_MATH_H
22 # undef abs
23 #endif
24 
25 #include "lex.h"
26 #include "ScalarNode.h"
27 #include "ScalarInstance.h"
28 #include "ErrorDialogManager.h"
29 #include "Parameter.h"
30 #include "AttributeParameter.h"
31 #include "Network.h"
32 #include "ListIterator.h"
33 #include "WarningDialogManager.h"
34 
35 
36 //
37 // The following define the mapping of parameter indices to parameter
38 // functionality in the module that is used to 'data-drive' the
39 // ScalarNode class and Nodes derived from it.
40 // These MUST match the entries in the ui.mdf file for the interactors
41 // that expect to be implemented by the ScalarInteractor class.
42 //
43 #define ID_PARAM_NUM            1       // Id used for UI messages
44 #define DATA_PARAM_NUM          2       // The input object
45 #define CVAL_PARAM_NUM          3       // Current Value
46 #define REFRESH_PARAM_NUM       4       // Does the module refresh
47 #define MIN_PARAM_NUM           5       // The current minimum
48 #define MAX_PARAM_NUM           6       // The current maximum
49 #define INCR_PARAM_NUM          7       // The current increment
50 #define INCRMETHOD_PARAM_NUM	8	// Method used to interpret incr.
51 #define DECIMALS_PARAM_NUM      9       // The number of decimals to display
52 #define DFLTVAL_PARAM_NUM       10      // The default output indicator
53 #define LABEL_PARAM_NUM         11      // The label
54 
55 // The total number of inputs as defined in the mdf file.
56 #define EXPECTED_SCALAR_INPUTS		LABEL_PARAM_NUM
57 
58 
59 #define DEFAULT_VALUE	0.0
60 #define DEFAULT_INCR	1.0
61 #define DEFAULT_MAX	1.0e6
62 #define DEFAULT_MIN	-1.0e6
63 #define DEFAULT_SCALAR_DECIMALS 5
64 
65 #define DEFAULT_VALUE_STR	      " 0 "
66 #define DEFAULT_INCR_STR	      " 1 "
67 #define DEFAULT_MAX_STR		"  100000 "
68 #define DEFAULT_MIN_STR	 	" -100000 "
69 #define DEFAULT_SCALAR_DECIMALS_STR   " 5 "
70 
71 //
72 // Create the component
73 //
ScalarNode(NodeDefinition * nd,Network * net,int instance,boolean isVector,int dimensions)74 ScalarNode::ScalarNode(NodeDefinition *nd,
75 			Network *net, int instance,
76 			boolean isVector,
77 			int dimensions) :
78                         InteractorNode(nd, net, instance)
79 {
80     ASSERT(dimensions > 0);
81     this->isContinuousUpdate = FALSE;
82     this->vectorType = isVector;
83     this->numComponents = dimensions;
84     this->rangeCheckDeferrals = 0;
85     this->needsRangeCheck = FALSE;
86 
87     if (!this->verifyInputCount())
88 	return;
89 
90     //
91     // The attribute is an absolute increment and the parameter value
92     // is a relative increment (between 0..1).  They have the same types
93     // so turn off value synchronization in the increment parameter (which
94     // is where the increment value is stored).
95     //
96     AttributeParameter *ap = (AttributeParameter*)
97 			this->getInputParameter(INCR_PARAM_NUM);
98     ASSERT(ap);
99     ap->setSyncOnTypeMatch(FALSE);
100 }
101 
hasDynamicDimensionality(boolean ignoreDataDriven)102 boolean ScalarNode::hasDynamicDimensionality(boolean ignoreDataDriven)
103 {
104     return this->isVectorType() &&
105 	   (ignoreDataDriven || !this->isDataDriven());
106 }
107 //
108 // Change the dimensionality of a Vector interactor.
109 //
doDimensionalityChange(int new_dim)110 boolean ScalarNode::doDimensionalityChange(int new_dim)
111 {
112     ScalarInstance *si;
113     int old_dim = this->getComponentCount();
114 
115     ASSERT(this->isVectorType());
116 
117     if (new_dim == old_dim)
118 	return TRUE;
119 
120     this->numComponents = new_dim;
121     //
122     // Delete the interactors, so that they don't get updated when setting
123     // the output value.  If we don't do this, we can get references to
124     // non-existent vector components.
125     //
126     ListIterator iterator(this->instanceList);
127     while ( (si = (ScalarInstance*)iterator.getNext()) )
128 	si->uncreateInteractor();
129 
130 
131     //
132     // Adjust the and output values first.
133     //
134     this->adjustOutputDimensions(old_dim, new_dim);
135 
136     //
137     // Adjust all the attribute values.
138     //
139     this->adjustAttributeDimensions(old_dim,new_dim);
140 
141     //
142     // Now have all the instances adjust themselves
143     //
144     iterator.setList(this->instanceList);
145     while ( (si = (ScalarInstance*)iterator.getNext()) )  {
146 	if (!si->handleNewDimensionality())
147 	    return FALSE;
148     }
149     return TRUE;
150 
151 }
adjustOutputDimensions(int old_dim,int new_dim)152 boolean ScalarNode::adjustOutputDimensions(int old_dim, int new_dim)
153 {
154     const char *oldval = this->getOutputValueString(1);
155     char *newval = DXValue::AdjustVectorDimensions(oldval,
156 			new_dim, DEFAULT_VALUE, this->isIntegerTypeComponent());
157     if (!newval)
158 	return FALSE;
159 
160     this->setOutputValue(1,newval,DXType::VectorType,TRUE);
161     delete newval;
162     return TRUE;
163 }
164 
adjustAttributeDimensions(int old_dim,int new_dim)165 boolean ScalarNode::adjustAttributeDimensions(int old_dim, int new_dim)
166 {
167 
168     boolean is_int = this->isIntegerTypeComponent();
169     const char *v;
170     char *newval;
171 
172     //
173     // Adjust the min attribute
174     //
175     v = this->getInputAttributeParameterValue(MIN_PARAM_NUM);
176     newval = DXValue::AdjustVectorDimensions(v, new_dim, DEFAULT_MIN,is_int);
177     this->setMinimumAttribute(newval);
178     delete newval;
179 
180     //
181     // Adjust the max attribute
182     //
183     v = this->getInputAttributeParameterValue(MAX_PARAM_NUM);
184     newval = DXValue::AdjustVectorDimensions(v, new_dim, DEFAULT_MAX, is_int);
185     this->setMaximumAttribute(newval);
186     delete newval;
187 
188     //
189     // Adjust the delta attribute
190     //
191     v = this->getInputAttributeParameterValue(INCR_PARAM_NUM);
192     newval = DXValue::AdjustVectorDimensions(v, new_dim, DEFAULT_INCR, is_int);
193     this->setDeltaAttribute(newval);
194     delete newval;
195 
196     //
197     // Adjust the decimals attribute
198     //
199     double decimals;
200     if (is_int)
201 	decimals = 0;
202     else
203 	decimals = DEFAULT_SCALAR_DECIMALS;
204     v = this->getInputAttributeParameterValue(DECIMALS_PARAM_NUM);
205     newval = DXValue::AdjustVectorDimensions(v, new_dim, decimals, TRUE);
206     this->setDecimalsAttribute(newval);
207     delete newval;
208 
209     return TRUE;
210 }
211 //
212 // Set the interactor's default attributes.
213 //
setDefaultAttributes()214 boolean ScalarNode::setDefaultAttributes()
215 {
216     const char *id;
217     const char *min=NULL, *max=NULL, *incr=NULL, *decimals=NULL;
218     boolean r;
219 
220 // FIXME: these strings should be build from DEFAULT_*_STR
221     switch (this->numComponents) {
222 	case 1:
223 	    if (this->isVectorType()) {
224 		min     = "[ -1000000 ]";
225 		max     = "[ 1000000 ]";
226 		incr    = "[ 1 ]";
227 		decimals = (this->isIntegerTypeComponent() ? "[0]" : "[5]");
228 	    } else {
229 		min     = "-1000000";
230 		max     = "1000000";
231 		incr    = "1";
232 		decimals = (this->isIntegerTypeComponent() ? "0" : "5");
233 	    }
234 	    break;
235 	case 2:
236 	    min     = "[-1000000 -1000000]";
237 	    max     = "[ 1000000  1000000]";
238 	    incr    = "[ 1        1]";
239 	    decimals= "[ 5        5]";
240 	    break;
241 	case 3:
242 	    min     = "[-1000000 -1000000 -1000000]";
243 	    max     = "[ 1000000  1000000  1000000]";
244 	    incr    = "[       1        1        1]";
245 	    decimals= "[       5        5        5]";
246 	    break;
247 	default:
248 	    ASSERT(0);
249     }
250 
251     id = this->getModuleMessageIdString();
252 
253     if ((this->setInputValue(ID_PARAM_NUM,id, DXType::UndefinedType,FALSE)
254 				== DXType::UndefinedType)
255 	||
256 	!this->initMinimumAttribute(min)
257 	||
258     	!this->initMaximumAttribute(max)
259 	||
260     	!this->initDeltaAttribute(incr)
261 	||
262     	!this->initDecimalsAttribute(decimals)
263 	) {
264          r = FALSE;
265     } else
266 	r = TRUE;
267 
268     return r;
269 }
270 
271 //
272 // Make sure the number of inputs is the number expected.
273 //
verifyInputCount()274 boolean ScalarNode::verifyInputCount()
275 {
276     if (this->getInputCount() != EXPECTED_SCALAR_INPUTS) {
277         ErrorMessage(
278 	   "Expected %d inputs for %s interactor, please check the mdf file.\n",
279 			EXPECTED_SCALAR_INPUTS,
280 			this->getNameString());
281 	return FALSE;
282     }
283     return TRUE;
284 }
285 //
286 // Called after allocation is complete.
287 // The work done here is to assigned default values to the InteractorNode inputs
288 // so that we can use them later when setting the attributes for the
289 // Interactor.
290 //
initialize()291 boolean ScalarNode::initialize()
292 {
293 
294     if (!this->verifyInputCount())
295 	return FALSE;
296 
297 // FIXME: these strings should be build from DEFAULT_*_STR
298     const char *value;
299     switch (this->numComponents) {
300     	case 1: if (this->isVectorType())
301 		    value = "[ 0 ]";
302 		else
303 		    value = "0";
304 		break;
305 	case 2: value = "[ 0 0 ]"; break;
306 	case 3: value = "[ 0 0 0 ]"; break;
307 	default: return FALSE;
308     }
309 
310     if (!this->setDefaultAttributes()
311 	||
312 	(this->setOutputValue(1,value, DXType::UndefinedType,FALSE) ==
313 				DXType::UndefinedType)
314  	){
315         ErrorMessage(
316       "Error setting default attributes for %s interactor, check ui.mdf\n",
317 		this->getNameString());
318         return FALSE;
319     }
320     //
321     // Make the shadows defaulting (even though we have a current output)
322     // so that the executive module can tell when it is executing a just
323     // placed module and one that is read in from a .net or .cfg file.
324     // When read in, the output will be set again which should make the
325     // corresponding shadowing input be non-defaulting.
326     //
327     this->setShadowingInputsDefaulting();
328 
329     return TRUE;
330 }
331 
332 
333 // The messages we parse can contain one or more of the following...
334 //
335 // 'min=%g' 'max=%g' 'delta=%g' 'value=%g' 'decimals=%d'
336 //
337 //  or one or more of the following...
338 //
339 // 'min=[%g %g %g]' 'max=[%g %g %g]' 'delta=[%g %g %g]' 'value=[%g %g %g]'
340 // 'decimals=[%g %g %g]'
341 //
342 // If any input or output values are to be changed, don't send them
343 // because the module backing up the interactor will have just executed
344 // and if the UI is in 'execute on change' mode then there will be an
345 // extra execution.
346 //
347 // Returns the number of attributes parsed.
348 //
handleInteractorMsgInfo(const char * line)349 int ScalarNode::handleInteractorMsgInfo(const char *line)
350 {
351     int values;
352     if (this->isVectorType())
353 	values = this->handleVectorMsgInfo(line);
354     else
355 	values = this->handleScalarMsgInfo(line);
356 
357     //
358     // Handle the 'method="%s"' part of the message.
359     // We only need to look for the message if we don't already have it.
360     //
361 	if (this->isInputConnected(INCRMETHOD_PARAM_NUM)) {
362 		char *p, buf[128];
363 		if ((p = strstr((char*)line,"method="))	&&
364 			FindDelimitedString(p,'"','"', buf)) {
365 				values++;
366 				this->setInputAttributeFromServer(INCRMETHOD_PARAM_NUM,buf,
367 					DXType::StringType);
368 		}
369 	}
370 
371 
372     //
373     // Make sure that the min or max sent back from the executive is
374     // consistent.  If the user has not connected the data tab and has
375     // only one of min and max set then it is possible that the value sent
376     // back by the module conflicts with the other value stored in the ui.
377     //
378 	if (!this->isInputDefaulting(DATA_PARAM_NUM))  {
379 		boolean min_dflting = this->isInputDefaulting(MIN_PARAM_NUM);
380 		boolean max_dflting = this->isInputDefaulting(MAX_PARAM_NUM);
381 		if ((min_dflting && !max_dflting) || (!min_dflting &&  max_dflting)) {
382 			int i, comps = this->getComponentCount();
383 			boolean issue_warning = FALSE;
384 			for (i=1 ; i<=comps  ; i++) {
385 				double minval = this->getComponentMinimum(i);
386 				double maxval = this->getComponentMaximum(i);
387 				if (minval > maxval) {
388 					issue_warning = TRUE;
389 					if (min_dflting)
390 						this->setComponentMinimum(i,maxval);
391 					else
392 						this->setComponentMaximum(i,minval);
393 				}
394 			}
395 			if (issue_warning) {
396 				char *setattr, *set;
397 				if (min_dflting) {
398 					set     = "maximum";
399 					setattr = "minimum";
400 				} else  {
401 					set     = "minimum";
402 					setattr = "maximum";
403 				}
404 				WarningMessage("%s value provided to %s conflicts "
405 					"with %s value set with 'Set Attributes' dialog"
406 					"...adjusting %s.",
407 					set, this->getNameString(),
408 					setattr,setattr);
409 			}
410 		}
411 	}
412 
413 
414     return values;
415 
416 }
417 // The messages we parse can contain one or more of the following...
418 //
419 // 'min=%g' 'max=%g' 'delta=%g' 'value=%g' 'decimals=%d'
420 //
421 // If any input or output values are to be changed, don't send them
422 // because the module backing up the interactor will have just executed
423 // and if the UI is in 'execute on change' mode then there will be an
424 // extra execution.
425 //
426 // Returns the number of attributes parsed.
427 //
handleScalarMsgInfo(const char * line)428 int ScalarNode::handleScalarMsgInfo(const char *line)
429 {
430 	int index, values = 0;
431 	char *p, *buf = NULL;
432 
433 	//
434 	// Handle the 'min=%g' part of the message.
435 	//
436 	if ( (p = strstr((char*)line,"min=")) ) {
437 		values++;
438 		while (*p != '=') p++;
439 		p++;
440 		buf = DuplicateString(p);
441 		index = 0;
442 		if (IsScalar(buf, index)) {
443 			buf[index] = '\0';
444 			this->setInputAttributeFromServer(MIN_PARAM_NUM,buf,
445 				DXType::UndefinedType);
446 		}
447 		delete buf;
448 	}
449 	//
450 	// Handle the 'max=%g' part of the message.
451 	//
452 	if ( (p = strstr((char*)line,"max=")) ) {
453 		values++;
454 		while (*p != '=') p++;
455 		p++;
456 		buf = DuplicateString(p);
457 		index = 0;
458 		if (IsScalar(buf, index)) {
459 			buf[index] = '\0';
460 			this->setInputAttributeFromServer(MAX_PARAM_NUM,buf,
461 				DXType::UndefinedType);
462 		}
463 		delete buf;
464 	}
465 	//
466 	// Handle the 'delta=%g' part of the message.
467 	// Since the attribute and parameter value have the same type, but
468 	// different meanings we only set the attribute value as received from
469 	// the exec.
470 	//
471 	if ( (p = strstr((char*)line,"delta=")) ) {
472 		values++;
473 		while (*p != '=') p++;
474 		p++;
475 		buf = DuplicateString(p);
476 		index = 0;
477 		if (IsScalar(buf, index)) {
478 			buf[index] = '\0';
479 			this->setInputAttributeFromServer(INCR_PARAM_NUM,buf,
480 				DXType::UndefinedType);
481 		}
482 		delete buf;
483 	}
484 	//
485 	// Handle the 'decimals=%d' part of the message.
486 	//
487 	if ( (p = strstr((char*)line,"decimals=")) ) {
488 		values++;
489 		while (*p != '=') p++;
490 		p++;
491 		buf = DuplicateString(p);
492 		index = 0;
493 		if (IsScalar(buf, index)) {
494 			buf[index] = '\0';
495 			this->setInputAttributeFromServer(DECIMALS_PARAM_NUM,buf,
496 				DXType::UndefinedType);
497 		}
498 		delete buf;
499 	}
500 	//
501 	// Handle the 'value=%g' part of the message.
502 	//
503 	if ( (p = strstr((char*)line,"value=")) ) {
504 		values++;
505 		while (*p != '=') p++;
506 		p++;
507 		buf = DuplicateString(p);
508 		index = 0;
509 		if (IsScalar(buf, index)) {
510 			buf[index] = '\0';
511 			this->setShadowedOutputSentFromServer(1,buf,
512 				DXType::UndefinedType);
513 		}
514 		delete buf;
515 	}
516 	return values;
517 
518 }
519 
520 //
521 // Called when a message is received from the executive to parse class
522 // specific message information.
523 //
524 // The messages we handle can contain one or more of the following...
525 //
526 // 'dim=%d'
527 // 'min=[%g %g %g]' 'max=[%g %g %g]' 'delta=[%g %g %g]' 'value=[%g %g %g]'
528 // 'decimals=[%g %g %g]'
529 //
530 // If any input or output values are to be changed, don't send them
531 // because the module backing up the interactor will have just executed
532 // and if the UI is in 'execute on change' mode then there will be an
533 // extra execution.
534 //
535 // Returns the number of attributes parsed.
536 //
handleVectorMsgInfo(const char * line)537 int ScalarNode::handleVectorMsgInfo(const char *line)
538 {
539     char *p;
540     int  values = 0;
541     char buf[256];
542 
543     //
544     // Handle the 'dim=%d' part of the message.
545     // This message must be handled first, because changing the dimensionality
546     // resets all the interactor values which can be reset by subsequent
547     // assignments in the current message.
548     // We don't need to do a 'values++' since the info is handled locally
549     // with this->changeDimensionality().
550     //
551     if ( (p = strstr((char*)line,"dim=")) ) {
552 	while (*p != '=') p++;
553 	p++;
554 	int dim = atoi(p);
555 	if (this->isVectorType() && (this->getComponentCount() != dim))
556 	    this->changeDimensionality(dim);
557     }
558     //
559     // Handle the 'min=[%g...]' part of the message.
560     //
561     if ( (p = strstr((char*)line,"min=")) ) {
562 	values++;
563 	while (*p != '=') p++;
564 	p++;
565 	if (FindDelimitedString(p,'[',']', buf)) {
566 	    this->setInputAttributeFromServer(MIN_PARAM_NUM,buf,
567 						DXType::UndefinedType);
568 	}
569 
570     }
571     //
572     // Handle the 'max=[%g...]' part of the message.
573     //
574     if ( (p = strstr((char*)line,"max=")) ) {
575 	values++;
576 	while (*p != '=') p++;
577 	p++;
578 	if (FindDelimitedString(p,'[',']', buf)) {
579 	    this->setInputAttributeFromServer(MAX_PARAM_NUM,buf,
580 						DXType::UndefinedType);
581 	}
582     }
583     //
584     // Handle the 'delta=[%g...]' part of the message.
585     // Since the attribute and parameter value have the same type, but
586     // different meanings we only set the attribute value as received from
587     // the exec.
588     //
589     if ( (p = strstr((char*)line,"delta=")) ) {
590 	values++;
591 	while (*p != '=') p++;
592 	p++;
593 	if (FindDelimitedString(p,'[',']', buf)) {
594 	    this->setInputAttributeFromServer(INCR_PARAM_NUM,buf,
595 						DXType::UndefinedType);
596 	}
597     }
598     //
599     // Handle the 'decimals=[%g...]' part of the message.
600     //
601     if ( (p = strstr((char*)line,"decimals=")) ) {
602 	values++;
603 	while (*p != '=') p++;
604 	p++;
605 	if (FindDelimitedString(p,'[',']', buf)) {
606 	    this->setInputAttributeFromServer(DECIMALS_PARAM_NUM,buf,
607 						DXType::UndefinedType);
608 	}
609     }
610     //
611     // Handle the 'value=[%g...]' part of the message.
612     //
613     if ( (p = strstr((char*)line,"value=")) ) {
614 	values++;
615 	while (*p != '=') p++;
616 	p++;
617 	if (FindDelimitedString(p,'[',']', buf)) {
618 	    this->setShadowedOutputSentFromServer(1,buf,
619 						DXType::UndefinedType);
620 	}
621     }
622     return values;
623 }
624 
cfgParseComment(const char * comment,const char * filename,int lineno)625 boolean ScalarNode::cfgParseComment(const char *comment,
626                                 const char *filename, int lineno)
627 {
628     //
629     // Don't do range checking until after the value AND the component's
630     // min/max have been set (see cfgParseComponentComment()).
631     //
632     if (strncmp(" interactor",comment,11))
633 	this->deferRangeChecking();
634 
635     return this->cfgParseComponentComment(comment, filename,lineno)     ||
636            this->cfgParseInstanceComment(comment, filename, lineno) ||
637            this->cfgParseLocalIncrementComment(comment, filename, lineno) ||
638            this->cfgParseLocalContinuousComment(comment, filename, lineno) ||
639            this->InteractorNode::cfgParseComment(comment, filename, lineno);
640 }
641 
642 //
643 // Print the '// interactor...' comment  to the file.
644 // We override the parent's method so that we can print num_components
645 // correctly.
646 //
cfgPrintInteractorComment(FILE * f)647 boolean ScalarNode::cfgPrintInteractorComment(FILE *f)
648 {
649     return fprintf(f,
650                 "// interactor %s[%d]: num_components = %d, value = %s\n",
651                 this->getNameString(),
652                 this->getInstanceNumber(),
653                 this->getComponentCount(),
654                 this->getOutputValueString(1)) >= 0;
655 }
656 
657 //
658 // Print auxiliary info for this interactor, which includes all global
659 // information about each component.
660 //
cfgPrintInteractorAuxInfo(FILE * f)661 boolean ScalarNode::cfgPrintInteractorAuxInfo(FILE *f)
662 {
663     int i, ncomp = this->getComponentCount();
664 
665     for (i=1 ; i<=ncomp ; i++ ) {
666     	if (fprintf(f,
667             "// component[%d]: minimum = %g, maximum = %g, "
668 	    "global increment = %g, decimal = %d, global continuous = %d\n",
669 		i-1,	// File uses 0 based indexing
670 		this->getComponentMinimum(i),
671 		this->getComponentMaximum(i),
672 		this->getComponentDelta(i),
673 		this->getComponentDecimals(i),
674                 this->isContinuous()) < 0)
675 		return FALSE;
676     }
677     return TRUE;
678 }
679 
680 //
681 // Print auxiliary info for the interactor instance,  which include all local
682 // information about each component.
683 //
cfgPrintInstanceAuxInfo(FILE * f,InteractorInstance * ii)684 boolean ScalarNode::cfgPrintInstanceAuxInfo(FILE *f,
685 					InteractorInstance *ii)
686 {
687     int i, ncomp = this->getComponentCount();
688     ScalarInstance *si = (ScalarInstance *)ii;
689 
690     if (fprintf(f,
691             "// local continuous: value = %d, mode = %s\n",
692 		(si->getLocalContinuous() ? 1 : 0),
693 		(si->usingGlobalContinuous() ? "global" : "local") ) < 0)
694 	return FALSE;
695 
696     for (i=1 ; i<=ncomp ; i++ ) {
697         if (fprintf(f,
698             "// local increment[%d]: value = %g, mode = %s\n",
699 		i-1,	// File uses 0 based indexing
700 		si->getLocalDelta(i),
701 		(si->isLocalDelta(i) ? "local" : "global") ) < 0)
702 	    return FALSE;
703     }
704     return TRUE;
705 
706 }
707 //
708 // This is the same as for the super class except that when we get a new
709 // instance we build the list of local attributes (one LocalAttributes
710 // for each component).
711 //
cfgParseInstanceComment(const char * comment,const char * filename,int lineno)712 boolean ScalarNode::cfgParseInstanceComment(const char *comment,
713                                 const char *filename, int lineno)
714 {
715     if (!this->InteractorNode::cfgParseInstanceComment(comment,filename,lineno))
716 	return FALSE;
717 
718 #if 0
719     int i, instance, components;
720     //
721     // Get the instance added above.
722     //
723     instance = this->getInstanceCount();	// The just added instance #
724     ScalarInstance *si = (ScalarInstance*)this->getInstance(instance);
725 
726     //
727     // Copy the global attributes to the local.
728     //
729     for (i=1 ; i<=this->getComponentCount() ; i++) {
730 	double   dval;
731 	int	 ival = this->getComponentDecimals(i);
732 	dval = this->getComponentMinimum(i);
733 	si->setLocalMinimum(i, dval);
734 	dval = this->getComponentMaximum(i);
735 	si->setLocalMaximum(i, dval);
736 	dval = this->getComponentDelta(i);
737 	si->setLocalDelta(i, dval);
738 	ival = this->getComponentDecimals(i);
739 	si->setLocalDecimals(i, ival);
740     }
741 #endif
742 
743     return TRUE;
744 
745 }
cfgParseComponentComment(const char * comment,const char * filename,int lineno)746 boolean ScalarNode::cfgParseComponentComment(const char *comment,
747                                 const char *filename, int lineno)
748 {
749     int      items_parsed;
750     double   minimum;
751     double   maximum;
752     double   delta;
753     int      decimal;
754     int      component_num;
755     int      continuous;
756 
757     if (strncmp(comment," component",10))
758         return FALSE;
759 
760     items_parsed = sscanf
761                 (comment,
762                  " component[%d]: minimum = %lf, maximum = %lf, global increment = %lf, decimal = %d, global continuous = %d",
763                  &component_num,
764                  &minimum,
765                  &maximum,
766                  &delta,
767                  &decimal,
768                  &continuous);
769 
770     if (items_parsed != 5 && items_parsed != 6)
771     {
772         ErrorMessage("Bad 'component' comment (file %s, line %d)",
773                                         filename,lineno);
774         return FALSE;
775     }
776 
777     component_num++;	// 1 based indexing.
778 
779 #if 0
780     Parameter *p = this->getOutputParameter(1);
781     Type t = p->getValueType();
782 
783     //
784     // The following is done most for lists, which when the list is empty
785     // have "NULL" value.  In this case we want to set the type to the
786     // default type.
787     //
788     if ((t == DXType::ObjectType) || EqualString("NULL",p->getValueString())) {
789 	t = p->getDefaultType();
790 	this->clearOutputValue(1);
791 	p->setValue(NULL,t);
792     }
793 #endif
794 
795     this->setComponentMinimum(component_num,minimum);
796     this->setComponentMaximum(component_num,maximum);
797     this->setComponentDelta(component_num,delta);
798     this->setComponentDecimals(component_num,decimal);
799 
800     if ((items_parsed == 6) && continuous)
801         this->setContinuous();
802     else
803         this->clrContinuous();
804 
805     //
806     // Enable range checking of the output value after the last component
807     // min/max has been set (see cfgParseComments() for matching
808     // deferComponentCount()).
809     //
810     if (component_num == this->getComponentCount())
811 	this->undeferRangeChecking();
812 
813     return TRUE;
814 }
815 
816 //
817 // Get a an ScalarInstance instead of an InteractorInstance.
818 //
newInteractorInstance()819 InteractorInstance *ScalarNode::newInteractorInstance()
820 {
821     ScalarInstance *si = new ScalarInstance(this);
822 
823     return (InteractorInstance*)si;
824 }
825 //
826 // G/Set the 'minimum' attribute for the given component
827 //
setAllComponentRanges(double * min,double * max)828 boolean ScalarNode::setAllComponentRanges(double *min, double *max)
829 {
830     this->deferRangeChecking();
831 
832     int i, ncomps = this->getComponentCount();
833     for (i=1 ; i<=ncomps ; i++) {
834 	if (min)
835 	    this->setComponentMinimum(i,min[i-1]);
836 	if (max)
837 	    this->setComponentMaximum(i,max[i-1]);
838     }
839 
840     this->undeferRangeChecking();
841     return TRUE;
842 }
initMinimumAttribute(const char * val)843 boolean ScalarNode::initMinimumAttribute(const char *val)
844 {
845     AttributeParameter *p = (AttributeParameter*) this->getInputParameter(
846 						MIN_PARAM_NUM);
847     return p->initAttributeValue(val);
848 }
setMinimumAttribute(const char * val)849 boolean ScalarNode::setMinimumAttribute(const char *val)
850 {
851     AttributeParameter *p = (AttributeParameter*) this->getInputParameter(
852 						MIN_PARAM_NUM);
853     return p->setAttributeValue(val);
854 }
setComponentMinimum(int component,double min)855 boolean ScalarNode::setComponentMinimum(int component, double min)
856 {
857     AttributeParameter *p = (AttributeParameter*) this->getInputParameter(
858 						MIN_PARAM_NUM);
859 
860     double oldmin = p->getAttributeComponentValue(component);
861 
862     if (!p->setAttributeComponentValue(component, min))
863 	return FALSE;
864 
865     if (min > oldmin)
866 	this->rangeCheckComponentValue(component,
867 			    min, this->getComponentMaximum(component));
868     return TRUE;
869 
870 }
getComponentMinimum(int component)871 double ScalarNode::getComponentMinimum(int component)
872 {
873     AttributeParameter *p = (AttributeParameter*) this->getInputParameter(
874 						MIN_PARAM_NUM);
875 
876     if (p->getAttributeComponentCount() < component)
877 	return DEFAULT_MIN;
878     else
879         return p->getAttributeComponentValue(component);
880 }
881 //
882 // G/Set the 'maximum' attribute for the given component
883 //
initMaximumAttribute(const char * val)884 boolean ScalarNode::initMaximumAttribute(const char *val)
885 {
886     AttributeParameter *p = (AttributeParameter*) this->getInputParameter(
887 						MAX_PARAM_NUM);
888     return p->initAttributeValue(val);
889 }
setMaximumAttribute(const char * val)890 boolean ScalarNode::setMaximumAttribute(const char *val)
891 {
892     AttributeParameter *p = (AttributeParameter*) this->getInputParameter(
893 						MAX_PARAM_NUM);
894     return p->setAttributeValue(val);
895 }
setComponentMaximum(int component,double max)896 boolean ScalarNode::setComponentMaximum(int component, double max)
897 {
898     AttributeParameter *p = (AttributeParameter*) this->getInputParameter(
899 							MAX_PARAM_NUM);
900 
901     double oldmax = p->getAttributeComponentValue(component);
902 
903     if (!p->setAttributeComponentValue(component, max))
904 	return FALSE;
905 
906     if (max < oldmax)
907 	this->rangeCheckComponentValue(component,
908 			this->getComponentMinimum(component), max);
909     return TRUE;
910 }
getComponentMaximum(int component)911 double ScalarNode::getComponentMaximum(int component)
912 {
913     AttributeParameter *p = (AttributeParameter*) this->getInputParameter(
914 						MAX_PARAM_NUM);
915     if (p->getAttributeComponentCount() < component)
916 	return DEFAULT_MAX;
917     else
918         return p->getAttributeComponentValue(component);
919 }
920 
921 //
922 // G/Set the 'delta' attribute for the given component
923 //
initDeltaAttribute(const char * val)924 boolean ScalarNode::initDeltaAttribute(const char *val)
925 {
926     AttributeParameter *p = (AttributeParameter*) this->getInputParameter(
927 						INCR_PARAM_NUM);
928     return p->initAttributeValue(val);
929 }
setDeltaAttribute(const char * val)930 boolean ScalarNode::setDeltaAttribute(const char *val)
931 {
932     AttributeParameter *p = (AttributeParameter*) this->getInputParameter(
933 						INCR_PARAM_NUM);
934     return p->setAttributeValue(val);
935 }
setComponentDelta(int component,double delta)936 boolean ScalarNode::setComponentDelta(int component, double delta)
937 {
938     AttributeParameter *p = (AttributeParameter*) this->getInputParameter(
939 						INCR_PARAM_NUM);
940     return p->setAttributeComponentValue(component, delta);
941 }
getComponentDelta(int component)942 double ScalarNode::getComponentDelta(int component)
943 {
944     AttributeParameter *p = (AttributeParameter*) this->getInputParameter(
945 						INCR_PARAM_NUM);
946     if (p->getAttributeComponentCount() < component)
947 	return DEFAULT_INCR;
948     else
949         return p->getAttributeComponentValue(component);
950 }
951 //
952 // G/Set the 'decimal places' attribute for the given component
953 //
initDecimalsAttribute(const char * val)954 boolean ScalarNode::initDecimalsAttribute(const char *val)
955 {
956     AttributeParameter *p = (AttributeParameter*) this->getInputParameter(
957 						DECIMALS_PARAM_NUM);
958     return p->initAttributeValue(val);
959 }
setDecimalsAttribute(const char * val)960 boolean ScalarNode::setDecimalsAttribute(const char *val)
961 {
962     AttributeParameter *p = (AttributeParameter*) this->getInputParameter(
963 						DECIMALS_PARAM_NUM);
964     return p->setAttributeValue(val);
965 }
setComponentDecimals(int component,int decimals)966 boolean ScalarNode::setComponentDecimals(int component, int decimals)
967 {
968     AttributeParameter *p = (AttributeParameter*) this->getInputParameter(
969 						DECIMALS_PARAM_NUM);
970     return p->setAttributeComponentValue(component, decimals);
971 }
getComponentDecimals(int component)972 int ScalarNode::getComponentDecimals(int component)
973 {
974     AttributeParameter *p = (AttributeParameter*) this->getInputParameter(
975 						DECIMALS_PARAM_NUM);
976     if (p->getAttributeComponentCount() < component) {
977 	if (this->isIntegerTypeComponent())
978 	    return 0;
979 	else
980 	    return DEFAULT_SCALAR_DECIMALS;
981     } else
982         return (int) p->getAttributeComponentValue(component);
983 }
setComponentValue(int component,double value)984 boolean ScalarNode::setComponentValue(int component, double value)
985 {
986     Parameter *out = this->getOutputParameter(1);
987     if (!out->setComponentValue(component, value))
988 	return FALSE;
989     const char *v = this->getOutputValueString(1);
990     // This forces update of the shadowing input.
991     return this->setOutputValue(1,v,DXType::UndefinedType,FALSE);
992 }
getComponentValue(int component)993 double ScalarNode::getComponentValue(int component)
994 {
995     Parameter *p = this->getOutputParameter(1);
996     ASSERT(p->getComponentCount() >= component);
997     return p->getComponentValue(component);
998 }
999 
1000 //
1001 // Call doRangeCheckComponentValue() if range checking is not
1002 // deferred.
1003 //
rangeCheckComponentValue(int component,double min,double max)1004 void ScalarNode::rangeCheckComponentValue(int component, double min, double max)
1005 {
1006     if (!this->isRangeCheckingDeferred()) {
1007         this->needsRangeCheck = FALSE;
1008         this->doRangeCheckComponentValue(component, min,max);
1009     } else {
1010         this->needsRangeCheck = TRUE;
1011     }
1012 }
1013 
1014 //
1015 // Do what ever is necessary when the given component of the output
1016 // value is out of range as indicated by the limits.  Typically, this just
1017 // means resetting the current output value that is associated with the
1018 // node.  ScalarListNodes however, have the current (non-output) value
1019 // associated with the interactor instance. Therefore, ScalarListNodes,
1020 // re-implement this to reset the component values of all their instances.
1021 // If 'component' is less than 0, then min/max are ignored and all
1022 // components are checked with the current min/max values.
1023 //
doRangeCheckComponentValue(int component,double min,double max)1024 void ScalarNode::doRangeCheckComponentValue(int component,
1025 				double min, double max)
1026 {
1027     double val;
1028 
1029     if (component < 0) {
1030 	//
1031 	// Check all components of current output value against current
1032 	// component min/max values (ignore input min/max).
1033 	//
1034 	int i, ncomp = this->getComponentCount();
1035 	double *mins = new double[ncomp];
1036 	double *maxs = new double[ncomp];
1037 	Type output_type = this->getOutputSetValueType(1);
1038 	char *newval;
1039 
1040 	for (i=1 ; i<=ncomp ; i++) {
1041 	    mins[i-1] = this->getComponentMinimum(i);
1042 	    maxs[i-1] = this->getComponentMaximum(i);
1043 	}
1044 	if (DXValue::ClampVSIValue(this->getOutputValueString(1),
1045 			  output_type,
1046 		 	  mins,maxs,&newval)) {
1047 	    ASSERT(newval);
1048 	    this->setOutputValue(1,newval,output_type,TRUE);
1049 	    delete newval;
1050    	}
1051 	delete[] mins;
1052 	delete[] maxs;
1053     } else {
1054 	//
1055 	// Just do a single component.
1056 	// Instead of doing this we could just always do the above, but
1057 	// this is much faster.
1058 	// Eventually, this causes a setOutputValue() just as above.
1059 	//
1060         val = this->getComponentValue(component);
1061 	if (val < min) {
1062 	    this->setComponentValue(component,min);
1063 	} else if (val > max) {
1064 	    this->setComponentValue(component,max);
1065 	}
1066     }
1067 
1068 }
1069 //
1070 // Determine if the given component is an integer type.
1071 // We ignore component and assume all components have the same type.
1072 //
isIntegerTypeComponent()1073 boolean ScalarNode::isIntegerTypeComponent()
1074 {
1075     // FIXME: is there a better way to do this.
1076     if (!strncmp("Integer",this->getNameString(),7))
1077 	return TRUE;
1078     else
1079 	return FALSE;
1080 }
1081 
cfgParseLocalIncrementComment(const char * comment,const char * filename,int lineno)1082 boolean ScalarNode::cfgParseLocalIncrementComment(
1083 		const char *comment, const char *filename, int lineno)
1084 
1085 {
1086     int            items_parsed;
1087     int            component_num;
1088     double         double_step;
1089     char           mode[32];
1090 
1091     ASSERT(comment);
1092 
1093     if (strncmp(comment," local increment",16))
1094         return FALSE;
1095 
1096 #if 0
1097     is_int = uiuEqualString(_interactor_name, "Integer");
1098 #endif
1099 
1100     items_parsed =
1101 	    sscanf(comment,
1102 		   " local increment[%d]: value = %lf, mode = %s",
1103 		   &component_num, // Ignoring component number (always 0?)
1104 		   &double_step,
1105 		   mode);
1106 
1107     component_num++;	// 1 based indexing
1108     if (component_num < 1 || component_num > this->getComponentCount()) {
1109 	ErrorMessage(
1110   "'local increment' comment references undefined component (file %s, line %d)",
1111 				filename, lineno);
1112 	return FALSE;
1113     }
1114 
1115 
1116     if (items_parsed != 3)
1117     {
1118 #if 1
1119 	ErrorMessage("Bad 'local increment' comment (file %s, line %d)",
1120 				filename, lineno);
1121 	return FALSE;
1122     }
1123 #else
1124 	uiuModelessErrorMessageDialog
1125 	    (_parse_widget,
1126 	     "#10001",
1127 	     "local increment",
1128 	     _parse_file,
1129 	     yylineno);
1130 	_error_occurred = TRUE;
1131 	return;
1132     }
1133 
1134     if (_interactor_index < 0)
1135     {
1136 	uiuModelessErrorMessageDialog
1137 	    (_parse_widget,
1138 	     "#10011", "local increment", "interactor", _parse_file, yylineno);
1139 	_error_occurred = TRUE;
1140 	return;
1141     }
1142 
1143     interactor = _network->interactor + _interactor_index;
1144 
1145     if (NOT interactor->in_use)
1146     {
1147 	uiuModelessErrorMessageDialog
1148 	    (_parse_widget,
1149 	     "#10011",
1150 	     "local increment",
1151 	     "interactor",
1152 	     _parse_file,
1153 	     yylineno);
1154 	_error_occurred = TRUE;
1155 	return;
1156     }
1157 #endif
1158 
1159 #if 1
1160     int instance = this->getInstanceCount();
1161     ScalarInstance *si = (ScalarInstance*)this->getInstance(instance);
1162     if (!si) {
1163  	ErrorMessage("'local increment' comment out of order (file %s, line%d)",
1164 			filename, lineno);
1165 	return FALSE;
1166     }
1167     si->useLocalDelta(component_num, double_step);
1168     if (!EqualString(mode,"local"))
1169        si->clrLocalDelta(component_num);
1170 
1171 #else
1172     if (is_int)
1173     {
1174 	interactor->increment[component_num].integer =
1175 	    interactor->restore_increment[component_num].integer =
1176 		int_step;
1177     }
1178     else
1179     {
1180 	interactor->increment[component_num].real =
1181 	    interactor->restore_increment[component_num].real =
1182 		double_step;
1183     }
1184 
1185     interactor->local_increment[component_num] =
1186 	interactor->restore_local_increment[component_num] =
1187 	    uiuEqualString(mode, "local");
1188 #endif
1189    return TRUE;
1190 
1191 }
1192 
cfgParseLocalContinuousComment(const char * comment,const char * filename,int lineno)1193 boolean ScalarNode::cfgParseLocalContinuousComment(
1194 		const char *comment, const char *filename, int lineno)
1195 {
1196     int            items_parsed;
1197     int	           continuous;
1198     char           mode[32];
1199 
1200     ASSERT(comment);
1201 
1202     if (strncmp(comment," local continuous",17))
1203         return FALSE;
1204 
1205     items_parsed =
1206 	sscanf(comment,
1207 	       " local continuous: value = %d, mode = %s",
1208 	       &continuous,
1209 	       mode);
1210 
1211     /*
1212      * Backwards compatibility...
1213      */
1214     if (items_parsed != 2)
1215     {
1216 	items_parsed =
1217 	    sscanf(comment,
1218 		   " local continuous[0]: value = %d, mode = %s",
1219 		   &continuous,
1220 		   mode);
1221     }
1222 
1223     if (items_parsed != 2)
1224     {
1225 #if 1
1226 	ErrorMessage("Bad 'local continuous' comment (file %s, line %d)",
1227 			filename, lineno);
1228 	return FALSE;
1229 #else
1230 	uiuModelessErrorMessageDialog
1231 	    (_parse_widget,
1232 	     "#10001",
1233 	     "local continuous",
1234 	     _parse_file,
1235 	     yylineno);
1236 	_error_occurred = TRUE;
1237 	return;
1238 #endif
1239     }
1240 
1241 #if 0
1242     if (_interactor_index < 0)
1243     {
1244 	uiuModelessErrorMessageDialog
1245 	    (_parse_widget,
1246 	     "#10011",
1247 	     "local continuous",
1248 	     "interactor",
1249 	     _parse_file,
1250 	     yylineno);
1251 	_error_occurred = TRUE;
1252 	return;
1253     }
1254 
1255     interactor = _network->interactor + _interactor_index;
1256 
1257     if (NOT interactor->in_use)
1258     {
1259 	uiuModelessErrorMessageDialog
1260 	    (_parse_widget,
1261 	     "#10011",
1262 	     "local continuous",
1263 	     "interactor",
1264 	     _parse_file,
1265 	     yylineno);
1266 	_error_occurred = TRUE;
1267 	return;
1268     }
1269 #endif
1270 
1271 #if 1
1272     int instance = this->getInstanceCount();
1273     ScalarInstance *si = (ScalarInstance*)this->getInstance(instance);
1274     if (!si) {
1275  	ErrorMessage("'local continuous' comment out of order (file %s, line%d)",
1276 			filename, lineno);
1277 	return FALSE;
1278     }
1279     si->useLocalContinuous((continuous == 0 ? FALSE : TRUE));
1280     if (!EqualString(mode,"local"))
1281        si->useGlobalContinuous();
1282 
1283 #else
1284     interactor->continuous =
1285 	interactor->restore_continuous =
1286 	    continuous;
1287 
1288     interactor->restore_local_continuous =
1289 	interactor->local_continuous =
1290 	    uiuEqualString(mode, "local");
1291 #endif
1292 
1293     return TRUE;
1294 
1295 }
1296 
1297 //
1298 // Determine if this node is of the given class.
1299 //
isA(Symbol classname)1300 boolean ScalarNode::isA(Symbol classname)
1301 {
1302     Symbol s = theSymbolManager->registerSymbol(ClassScalarNode);
1303     if (s == classname)
1304 	return TRUE;
1305     else
1306 	return this->InteractorNode::isA(classname);
1307 }
1308 
isMinimumVisuallyWriteable()1309 boolean ScalarNode::isMinimumVisuallyWriteable()
1310 {
1311     return
1312 	this->isInputDefaulting(DATA_PARAM_NUM) 	&&
1313 	this->isAttributeVisuallyWriteable(MIN_PARAM_NUM);
1314 }
isMaximumVisuallyWriteable()1315 boolean ScalarNode::isMaximumVisuallyWriteable()
1316 {
1317     return
1318 	this->isInputDefaulting(DATA_PARAM_NUM) 	&&
1319 	this->isAttributeVisuallyWriteable(MAX_PARAM_NUM);
1320 }
isDecimalsVisuallyWriteable()1321 boolean ScalarNode::isDecimalsVisuallyWriteable()
1322 {
1323     return
1324 	this->isInputDefaulting(DATA_PARAM_NUM) 	&&
1325 	(this->isInputDefaulting(MIN_PARAM_NUM) ||
1326  	 this->isInputDefaulting(MAX_PARAM_NUM))  	&&
1327         this->isAttributeVisuallyWriteable(DECIMALS_PARAM_NUM);
1328 }
isDeltaVisuallyWriteable()1329 boolean ScalarNode::isDeltaVisuallyWriteable()
1330 {
1331     const char *delta_method = this->getInputValueString(INCRMETHOD_PARAM_NUM);
1332 
1333     //
1334     // Check to see of the tab-down value of the method input is set to
1335     // 'absolute'.  We can only write this value when using absolute
1336     // increments.  Actually, this test should be moved to the set attributes
1337     // code since it is the one that decides what kind of increments it
1338     // can support.
1339     //
1340     if (!this->isInputDefaulting(INCRMETHOD_PARAM_NUM) &&
1341 	!this->isInputConnected(INCRMETHOD_PARAM_NUM)  &&
1342 	!EqualString(delta_method,"absolute"))
1343 	return FALSE;
1344 
1345     return
1346 	this->isInputDefaulting(DATA_PARAM_NUM) 	&&
1347 	(this->isInputDefaulting(MIN_PARAM_NUM) ||
1348  	 this->isInputDefaulting(MAX_PARAM_NUM))  	&&
1349 	this->isAttributeVisuallyWriteable(INCR_PARAM_NUM);
1350 }
1351 //
1352 // Catch the output comment to determine the number of components.
1353 // We need to do this when we have a 2d vector and no .cfg file to
1354 // tell us so.  We then get numComponent==3, but all the parameter
1355 // values are 2d, which results in an ASSERTion failure.
1356 //
netParseComment(const char * comment,const char * file,int lineno)1357 boolean     ScalarNode::netParseComment(const char* comment,
1358                                         const char *file, int lineno)
1359 {
1360     boolean r = this->InteractorNode::netParseComment(comment,file,lineno);
1361     if (r && EqualSubstring(comment," output[",8)) {
1362   	Parameter *p = this->getOutputParameter(1);
1363 	this->numComponents = p->getComponentCount();
1364     }
1365     return r;
1366 }
1367 
1368 
1369 
1370 //
1371 // If we're parsing input #4 (which is now REFRESH and was at one point REMAP)
1372 // and the net version is older than 3.1.0 (which is compiled in by DXVersion.h),
1373 // then set the defaulting status = TRUE.  Reason:  the older ui was setting
1374 // the defaulting status of this unused param to FALSE.  Now that we want to use
1375 // the param again, old nets believe the param is set.
1376 //
1377 // So, this chunk of code should go away if REFRESH goes away.  It should also
1378 // go away sometime in the future (after no more old nets exist).
1379 //
1380 // In case it's not obvious, I'll tell you: this code was copy/pasted from
1381 // Node.C.  Maybe it should be kept up to date with Node.C, but really its only
1382 // purpose is to deal with old nets, so if comments change this code won't really
1383 // affected.
1384 //
parseIOComment(boolean input,const char * comment,const char * filename,int lineno,boolean valueOnly)1385 boolean ScalarNode::parseIOComment(boolean input, const char* comment,
1386 								   const char* filename, int lineno, boolean valueOnly)
1387 {
1388 	int      defaulting = 0, items_parsed, ionum, tmp_type;
1389 	int	     visible = TRUE;
1390 	boolean  parse_error = FALSE;
1391 
1392 	if(this->Node::parseIOComment(input, comment, filename, lineno, valueOnly) == FALSE)
1393 		return FALSE;
1394 
1395 	//
1396 	//
1397 	// If the net version is less than 3.1.0 then set param 4 defaulting status
1398 	// to true.  The ui had mistakenly been setting it to false although the param
1399 	// was not in use by the module.  Now we want to use that param but existing
1400 	// nets don't work unless param 4 (REFRESH) starts out defaulting.
1401 	//
1402 	// This code turns into NoOp starting with net version == 3.1.0
1403 	//
1404 	Network *net = this->getNetwork();
1405 	if (net->getNetMajorVersion() >  3) return TRUE;
1406 	if (net->getNetMinorVersion() >= 1) return TRUE;
1407 
1408 	ASSERT(comment);
1409 
1410 	if ((input) && (!parse_error)) {
1411 
1412 		if (valueOnly) {
1413 			if (sscanf(comment, " input[%d]: defaulting = %d",
1414 				&ionum, &defaulting) != 2)
1415 				parse_error = TRUE;
1416 			/*type = DXType::UndefinedType;*/
1417 		} else {
1418 			items_parsed = sscanf(comment,
1419 				" input[%d]: defaulting = %d, visible = %d, type = %d",
1420 				&ionum, &defaulting, &visible, &tmp_type);
1421 			/*type = (Type) tmp_type;*/
1422 			if (items_parsed != 4) {
1423 				// Invisibility added 3/30/93
1424 				items_parsed = sscanf(comment, " input[%d]: visible = %d",
1425 					&ionum, &visible);
1426 				if (items_parsed != 2) {
1427 					// Backwards compatibility added 3/25/93
1428 					items_parsed = sscanf(comment, " input[%d]: type = %d",
1429 						&ionum, &tmp_type);
1430 					/*type = (Type) tmp_type;*/
1431 					if (items_parsed != 2) {
1432 						items_parsed = sscanf(comment,
1433 							" input[%d]: defaulting = %d, type = %d",
1434 							&ionum, &defaulting, &tmp_type);
1435 						/*type = (Type) tmp_type;*/
1436 						if (items_parsed != 3)
1437 							parse_error = TRUE;
1438 					}
1439 				}
1440 				else
1441 				{
1442 					defaulting = 1;
1443 				}
1444 			}
1445 		}
1446 	}
1447 
1448 	if ((!parse_error) && (input) &&
1449 		(ionum == REFRESH_PARAM_NUM) && (defaulting == FALSE)) {
1450 			Parameter *par = this->getInputParameter(REFRESH_PARAM_NUM);
1451 			par->setUnconnectedDefaultingStatus(TRUE);
1452 	}
1453 
1454 
1455 	return TRUE;
1456 }
1457 
1458 
printJavaValue(FILE * jf)1459 boolean ScalarNode::printJavaValue (FILE* jf)
1460 {
1461     const char* indent = "        ";
1462     int comp_count = this->getComponentCount();
1463     const char* var_name = this->getJavaVariable();
1464     int i;
1465     for (i=1; i<=comp_count; i++) {
1466 	if (this->isIntegerTypeComponent()) {
1467 	    int min = (int)this->getComponentMinimum(i);
1468 	    int max = (int)this->getComponentMaximum(i);
1469 	    int step = (int)this->getComponentDelta(i);
1470 	    int value = (int)this->getComponentValue(i);
1471 	    fprintf (jf, "%s%s.setValues(%d,%d,%d,%d,%d);\n",
1472 		indent, var_name, i,min,max,step,value);
1473 	} else {
1474 	    double min = this->getComponentMinimum(i);
1475 	    double max = this->getComponentMaximum(i);
1476 	    double step = this->getComponentDelta(i);
1477 	    double value = this->getComponentValue(i);
1478 	    int decimals = this->getComponentDecimals(i);
1479 	    fprintf (jf, "%s%s.setValues(%d,%g,%g,%g,%d,%g);\n",
1480 		indent, var_name, i,min,max,step,decimals,value);
1481 	}
1482     }
1483     return TRUE;
1484 }
1485 
1486 
1487