//
// Print the group information into the cfg file.
//
bool PanelGroupManager::cfgPrintComment(FILE *f)
{
    int	  i, inst;
    List  plist;
    ListIterator li;
    char  *name;

    for(i=1; (name = (char*)this->getPanelGroup(i, &plist)); i++)
    {
        if (fprintf(f, "// panel group: \"%s\"", name) < 0)
            return false;

        li.setList(plist);

        while( (inst = (int)(long)li.getNext()) )
            if (fprintf(f, " %d", inst-1) < 0)
                return false;

        if (fputc('\n', f) < 0)
            return false;

        plist.clear();
    }

    return true;
}
boolean
MacroParameterNode::canCoerceValue (const char* option, List* types)
{
	ListIterator iter;
	boolean coerced = FALSE;
	DXType* dxtype;
	for (iter.setList(*types) ; (dxtype = (DXType*)iter.getNext()) ; ) {
		char* s = DXValue::CoerceValue (option, dxtype->getType());
		if (s) {
			coerced = TRUE;
			delete s;
			break;
		}
	}
	return coerced;
}
boolean MacroParameterNode::removeIOArk(List *io, int index, Ark *a)
{
    int destIndex;
    int srcIndex;
    Node* destinationNode = a->getDestinationNode(destIndex);
    Node* sourceNode = a->getSourceNode(srcIndex);
    NodeDefinition* destinationDefinition = destinationNode->getDefinition();
    if (!this->UniqueNameNode::removeIOArk(io, index, a))
	return FALSE;

    ParameterDefinition *macroPd = this->getParameterDefinition();

    //
    // During deletion of a MacroDefinition, there is no MacroDefinition
    // for this node and therefore no ParameterDefinition.  So just return.
    //
    if (!macroPd)
	return TRUE;

    Parameter *pout;
    if (this->isInput())
	pout = this->getOutputParameter(1);
    else
	pout = this->getInputParameter(1);

    ParameterDefinition *nodePd = pout->getDefinition();

    List *outTypes = macroPd->getTypes();
    DXType *t;
    while( (t = (DXType*)(outTypes->getElement(1))) )
    {
	macroPd->removeType(t);
    }

    outTypes = nodePd->getTypes();
    while( (t = (DXType*)(outTypes->getElement(1))) )
    {
	nodePd->removeType(t);
    }

    // for each arc connected to this, intersect this type
    // list with "typesList" and set this to be the current types list.
    const List *arcs;
    if (this->isInput())
	arcs = this->getOutputArks(srcIndex);
    else
	arcs = this->getInputArks(destIndex);
    

    ListIterator li;
    li.setList(*(List *)arcs);

    List *typesList = new List;
    typesList->appendElement(new DXType(DXType::ObjectType));

    while( (a = (Ark*)li.getNext()) )
    {
	ParameterDefinition *pind;
	if (this->isInput())
	{
	    int dummy;
	    Node *dest = a->getDestinationNode(dummy);
	    pind = ((MacroParameterNode*)dest)->getInputParameter(dummy)->
				    getDefinition();
	}
	else
	{
	    int dummy;
	    Node *dest = a->getSourceNode(dummy);
	    pind = ((MacroParameterNode*)dest)->getOutputParameter(dummy)->
				    getDefinition();
	}
	List *newTypesList = DXType::IntersectTypeLists(
	    *typesList,
	    *pind->getTypes());
	// FIXME:  don't you have to delete the items in the list first?
	delete typesList;
	typesList = newTypesList;
    }


    li.setList(*typesList);
    while( (t = (DXType*)li.getNext()) )
    {
	DXType *newt = t->duplicate(); 
	nodePd->addType(newt);
	macroPd->addType(t);
    }
    delete typesList;

    if (this->isInput()) {
	const char *const *dest_option_vals;
	const char *const *src_option_vals;
	// If our current option values are equal to the options
	// values at the other end of the ark that we're disconnecting,
	// then assume that our option values came over this ark, and
	// toss ours out.  This prevents us from discarding a user's input.
	boolean we_disconnected_the_one = FALSE;

	ParameterDefinition *dpd = destinationDefinition->getInputDefinition(destIndex);
	dest_option_vals = dpd->getValueOptions();
	ParameterDefinition *macroPd = this->getParameterDefinition();
	src_option_vals = macroPd->getValueOptions();

	if (src_option_vals && src_option_vals[0] && 
	    dest_option_vals && dest_option_vals[0]) {
	    int i=0;
	    while (dest_option_vals[i] && src_option_vals[i]) {
		if (!EqualString (dest_option_vals[i], src_option_vals[i])) break;
		i++;
	    }
	    if ((dest_option_vals[i] == NULL) && (src_option_vals[i] == NULL))
		we_disconnected_the_one = TRUE;
	}

	if (we_disconnected_the_one) {
	    macroPd->removeValueOptions();
	    this->setTypeSafeOptions();
	}
    }
    if (this->isInput())
    {
	if (this->getConfigurationDialog())
	    this->getConfigurationDialog()->changeInput(1);
    }
    else
    {
	if (this->getConfigurationDialog())
	    this->getConfigurationDialog()->changeOutput(1);
    }
    return TRUE;
}
Example #4
0
//
// When a Receiver gets a new label, it has to disconnect from its existing
// transmitter, and connect to the new one.  This will work even if it's
// the transmitter that's changing our label.
boolean ReceiverNode::setLabelString(const char *label)
{
    if (EqualString(label, this->getLabelString()))
        return TRUE;

    if (initializing && this->getNetwork()->isReadingNetwork())
        return this->UniqueNameNode::setLabelString(label);

    if (!this->verifyRestrictedLabel(label))
        return FALSE;

    //
    // Skip the conflict check when reading in a newer style net since
    // there can't be any conflict in these nets.
    //
    const char* conflict = NUL(char*);
    if (this->getNetwork()->isReadingNetwork()) {
        int net_major = this->getNetwork()->getNetMajorVersion();
        int net_minor = this->getNetwork()->getNetMinorVersion();
        int net_micro = this->getNetwork()->getNetMicroVersion();
        int net_version =   VERSION_NUMBER( net_major, net_minor, net_micro);
        if (net_version < VERSION_NUMBER(3,1,1))
            conflict = this->getNetwork()->nameConflictExists(this, label);
    }

    //
    // If there is a name conflict while reading a network, it's important to try
    // to continue in spite of the conflict and fix things up later.  Reason: older
    // versions of dx allowed the name conflict and we would like to try and fix
    // things and report what happened rather than read the net incorrectly.
    //
    if ((conflict) && (this->getNetwork()->isReadingNetwork() == FALSE)) {
        ErrorMessage("A %s with name \"%s\" already exists.", conflict, label);
        return FALSE;
    }

    boolean found = FALSE;
    List *ia = (List*)this->getInputArks(1);
    if ((ia) && (ia->getSize() > 0)) {
        Ark *a = (Ark*)ia->getElement(1);
        int dummy;
        if (EqualString(a->getSourceNode(dummy)->getLabelString(), label))
            found = TRUE;
        else
            delete a;
    }
    ia = NUL(List*);


    if (!found) {
        List* l = this->getNetwork()->makeClassifiedNodeList(ClassTransmitterNode, FALSE);
        ListIterator iterator;
        Node *n;

        if ((l) && (this->getNetwork()->isReadingNetwork() == FALSE)) {
            //
            // Before creating any Arks, check for cycles.
            //
            iterator.setList(*l);
            while ( (n = (Node*)iterator.getNext()) ) {
                if (EqualString(label, n->getLabelString())) {
                    Network* net = this->getNetwork();
                    if (net->checkForCycle(n, this)) {
                        ErrorMessage (
                            "Unable to rename Receiver \"%s\" to \"%s\"\n"
                            "because that would cause a cyclic connection.",
                            this->getLabelString(), label
                        );
                        delete l;
                        return FALSE;
                    }
                }
            }
        }

        if (l) {
            iterator.setList(*l);
            while ( (n = (Node*)iterator.getNext()) ) {
                if (EqualString(label, n->getLabelString()))
                {
                    found = TRUE;
                    // link me to transmitter
                    new Ark(n, 1, this, 1);
                }
            }
            delete l;
        }
    }

    //
    // There was a name conflict because earlier versions of dx were less restrictive.
    // Record the transmitter for later fixup.  When the transmitter is fixed up,
    // then we'll automatically get fixed up also.  Caveat:  if there is no transmitter
    // connected, then it's cool to refuse the name because then we're not breaking
    // anything.
    //
    if (conflict) {
        ASSERT (this->getNetwork()->isReadingNetwork());
        if (this->isTransmitterConnected() == FALSE) {
            ErrorMessage("A %s with name \"%s\" already exists.", conflict, label);
            return FALSE;
        }
        List *l = (List*)this->getInputArks(1);
        ASSERT (l->getSize() > 0);
        Ark *a = (Ark*)l->getElement(1);
        int dummy;
        TransmitterNode* tn = (TransmitterNode*)a->getSourceNode(dummy);
        this->getNetwork()->fixupTransmitter(tn);
    }

    return this->UniqueNameNode::setLabelString(label);

}